test


<template>
<div/>
</template>
<script>
import annyang from 'annyang'
import cnchar from 'cnchar'
import { menuRoutes } from '@/router/index'

export default {
  name: 'SpeechRecognition',
  data () {
    return {
      routerMap: [],
      topMenuMap: []
    }
  },
  created () {
    this.initializeRouterData()
  },
  mounted () {
    this.initializeSpeechRecognition()
  },

  beforeDestroy () {
    if (annyang) {
      annyang.removeCallback('result', this.handleSpeechResult)
      annyang.abort()
    }
  },

  methods: {
    initializeRouterData () {
      this.routerMap = Object.freeze(this.getAllRoutesMeta(menuRoutes))
      this.topMenuMap = Object.freeze(this.findTopLevelPath(menuRoutes))
    },
    initializeSpeechRecognition () {
      if (annyang) {
        annyang.setLanguage('zh-CN')
        annyang.addCallback('result', this.handleSpeechResult)
        annyang.start()
        this.$message.success('语音助手已运行!')
      } else {
        this.$message.error('抱歉,您的浏览器不支持语音识别。')
      }
    },
    handleSpeechResult (phrases) {
      console.log('您说了:', phrases)
      const [word] = phrases
      if (word) {
        this.gotoPage(word)
      }
    },
    gotoPage (word) {
      const hasKeyWord = word.includes('打开')
      const fullStr = cnchar.spell(word, 'first', 'low')
      const noActionWord = word.replace('打开', '')
      const accurateWord = this.routerMap.find((t) => t.title === noActionWord)
      // 精准匹配
      if (accurateWord) {
        this.navigateToRoute(accurateWord)
        return
      }
      // 模糊匹配
      for (const route of this.routerMap) {
        const { title } = route
        const pinyin = cnchar.spell(title, 'first', 'low')
        if (hasKeyWord && (word.includes(title) || fullStr.includes(pinyin))) {
          this.navigateToRoute(route)
          return
        }
      }
      if (hasKeyWord) {
        this.$message.error('抱歉,未能识别清楚,请重新尝试。')
        return
      }
      console.log('未匹配到关键词', word)
    },
    navigateToRoute (route) {
      const { name: routeName, path, child } = route
      const isTop = this.topMenuMap.some((t) => t.path === path)
      const jumpPath = isTop ? { path, child } : this.topMenuMap.find((t) => t.children.includes(path))

      this.$store.dispatch('permission/setActiveMenuPath', jumpPath).then(() => {
        this.$router.push({ name: routeName })
      })
    },
    // 获取所有一级路由和最底层路由的 meta.title 和 name
    getAllRoutesMeta (routes) {
      const result = []
      routes.forEach(route => {
        // 查找当前路由的最顶级路由路径
        // 将当前路由的 meta.title 和 name 添加到结果数组中
        if (route.meta && route.meta.title && route.name) {
          result.push({
            title: route.meta.title,
            name: route.name,
            path: route.path,
            child: route.children || []
          })
        }
        // 如果当前路由有子路由,则递归获取子路由的 meta.title 和 name
        if (route.children && route.children.length > 0) {
          const childMeta = this.getAllRoutesMeta(route.children)
          result.push(...childMeta)
        }
      })
      return result
    },
    // 获取一级菜单
    findTopLevelPath (routes) {
    // 递归地获取所有子路由的路径
      function getChildren (route) {
        if (!route.children || route.children.length === 0) {
          return []
        } else {
          return route.children.flatMap(child => {
            const childPaths = [child.path]
            if (child.children && child.children.length > 0) {
              // 如果子路由还有子路由,则递归获取子路由的路径
              childPaths.push(...getChildren(child))
            }
            return childPaths
          })
        }
      }

      // 遍历所有路由,找到与当前路由匹配的路由
      return routes.map(route => ({
        path: route.path,
        child: route.children,
        children: getChildren(route)
      }))
    }

  }
}
</script>

<style scoped>
/* Add your styles here */
</style>

posted @ 2024-05-15 21:07  古德拉克  阅读(14)  评论(0编辑  收藏  举报