在业务中,出现个需求
当点击页面上某个麦克风点击,进行识别的时候,会转成文字,然后根据相应的文字跳转相应的路由;
但是现在有个问题,浏览器的麦克风api,只能在https协议下进行请求,以及本机的https方法。这点要注意;
现在做了个另外的。就是调用windows本机的麦克风按钮,然后数据到input框进行展示。当鼠标点击到input 然后进行ctrl+h;唤起麦克风,然后说出话语,跳转路由;
js
// 在https环境下进行请求
<template>
<div class="voice-assistant-input">
<!-- 输入框:用于显示语音识别结果 / 指令 -->
<div class="input-container">
<input
ref="commandInput"
v-model="commandText"
type="text"
placeholder="语音识别结果将显示在这里,或手动输入指令..."
class="command-input"
readonly
/>
</div>
<!-- 操作按钮:麦克风 + 发送 -->
<div class="button-container">
<!-- 麦克风按钮 -->
<button @click="startVoiceRecognition" class="mic-btn" title="点击开始语音指令">
🎤
</button>
<!-- 发送按钮(可用于手动输入指令测试,或提交识别内容) -->
<button @click="handleSendCommand" class="send-btn" title="执行当前指令">
📤
</button>
</div>
<!-- 提示信息 -->
<p v-if="message" :class="['message', messageType]">
{{ message }}
</p>
</div>
</template>
<script>
export default {
name: 'VoiceAssistantInput',
props: {
// 后端返回的菜单数据,每个菜单项需包含 name/title 和 path
menuData: {
type: Array,
required: true,
},
},
data() {
return {
commandText: '', // 输入框中显示的指令(语音识别结果 or 手动输入)
message: '', // 提示信息
messageType: 'info', // info / error
};
},
methods: {
// 开始语音识别
async startVoiceRecognition() {
try {
// 1. 检查 HTTPS 环境
if (location.protocol !== 'https:' && location.hostname !== 'localhost') {
this.showMessage('语音识别需要在 HTTPS 环境下使用,请使用 HTTPS 访问', 'error');
return;
}
// 2. 检查浏览器支持
if (!('SpeechRecognition' in window) && !('webkitSpeechRecognition' in window)) {
this.showMessage('您的浏览器不支持语音识别,请使用 Chrome 浏览器', 'error');
return;
}
// 3. 请求麦克风权限
try {
await navigator.mediaDevices.getUserMedia({ audio: true });
} catch (permissionError) {
console.error('麦克风权限被拒绝:', permissionError);
this.showMessage('请允许访问麦克风权限,然后重试', 'error');
return;
}
// 4. 创建语音识别实例
const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
const recognition = new SpeechRecognition();
// 5. 配置识别参数
recognition.lang = 'zh-CN';
recognition.interimResults = false;
recognition.maxAlternatives = 1;
recognition.continuous = false;
// 6. 事件处理
recognition.onstart = () => {
this.commandText = '';
this.showMessage('正在监听中,请说话...', 'info');
};
recognition.onresult = (event) => {
const text = event.results[0][0].transcript;
this.commandText = text;
console.log('语音识别结果:', text);
this.showMessage('识别完成,正在处理指令...', 'info');
this.handleCommand(text);
};
recognition.onerror = (event) => {
console.error('语音识别错误:', event.error);
let errorMessage = '语音识别出错';
switch (event.error) {
case 'no-speech':
errorMessage = '没有检测到语音,请重试';
break;
case 'audio-capture':
errorMessage = '无法访问麦克风,请检查设备连接';
break;
case 'not-allowed':
errorMessage = '麦克风权限被拒绝,请在浏览器设置中允许访问';
break;
case 'network':
errorMessage = '网络错误,请检查网络连接';
break;
case 'service-not-allowed':
errorMessage = '语音识别服务不可用';
break;
default:
errorMessage = `语音识别出错: ${event.error}`;
}
this.showMessage(errorMessage, 'error');
};
recognition.onend = () => {
console.log('语音识别结束');
};
// 7. 开始识别
recognition.start();
} catch (error) {
console.error('启动语音识别失败:', error);
this.showMessage('启动语音识别失败,请重试', 'error');
}
},
// 处理指令(无论是语音还是手动输入)
handleCommand(command) {
if (!command.trim()) {
this.showMessage('指令为空,请重试', 'error');
return;
}
if (!this.menuData || this.menuData.length === 0) {
this.showMessage('菜单数据未加载,无法识别页面', 'error');
return;
}
console.log('原始指令:', command);
console.log('菜单数据:', this.menuData);
// 提取关键字(改进版本)
const keywords = this.extractKeywords(command);
console.log('提取的关键词:', keywords);
if (keywords.length === 0) {
this.showMessage('未识别到有效的页面关键词,请重试', 'error');
return;
}
// 查找匹配的菜单项
const matchedMenus = this.findMenusByKeywords(this.menuData, keywords);
console.log('匹配结果:', matchedMenus);
if (matchedMenus.length === 0) {
this.showMessage(`未找到与"${keywords.join('、')}"相关的页面,请尝试说:数据监测、实时数据、财务报表等`, 'error');
return;
}
// 选择最佳匹配
const bestMatch = this.selectBestMatch(matchedMenus, keywords);
this.navigateToPage(bestMatch);
},
// 改进的关键词提取方法
extractKeywords(command) {
// 1. 移除常见的语音指令词汇
let cleanCommand = command
.replace(/帮我|请|跳转到|页面|我想|查看|进入|那个|啥|的|打开|去|到|访问|进去/gi, '')
.replace(/\s+/g, '')
.trim();
console.log('清理后的指令:', cleanCommand);
// 2. 如果清理后为空,使用原始指令
if (!cleanCommand) {
cleanCommand = command.trim();
}
// 3. 分词处理(简单版本)
const keywords = [];
// 常见的页面关键词映射
const keywordMap = {
'数据': ['数据监测', '数据', '监测'],
'实时': ['实时数据', '实时', '数据'],
'财务': ['财务报表', '财务', '报表'],
'销售': ['销售报表', '销售', '报表'],
'用户': ['用户管理', '用户', '管理'],
'角色': ['角色管理', '角色', '管理'],
'菜单': ['菜单管理', '菜单', '管理'],
'系统': ['系统管理', '系统', '管理'],
'报表': ['报表', '财务报表', '销售报表'],
'管理': ['管理', '用户管理', '角色管理', '菜单管理', '系统管理']
};
// 4. 检查是否包含关键词
for (const [key, values] of Object.entries(keywordMap)) {
if (cleanCommand.includes(key)) {
keywords.push(...values);
}
}
// 5. 如果没有匹配到预定义关键词,直接使用清理后的指令
if (keywords.length === 0) {
keywords.push(cleanCommand);
}
// 6. 去重
return [...new Set(keywords)];
},
// 改进的菜单搜索方法
findMenusByKeywords(menus, keywords) {
const result = [];
const search = (items) => {
for (const item of items) {
// 计算匹配分数
const score = this.calculateMatchScore(item, keywords);
if (score > 0) {
if (item.path) {
result.push({ ...item, matchScore: score });
}
}
if (item.children && item.children.length > 0) {
search(item.children);
}
}
};
search(menus);
// 按匹配分数排序
return result.sort((a, b) => b.matchScore - a.matchScore);
},
// 计算匹配分数
calculateMatchScore(item, keywords) {
let score = 0;
const itemName = item.name || '';
const itemTitle = item.title || '';
for (const keyword of keywords) {
// 完全匹配得分最高
if (itemName === keyword || itemTitle === keyword) {
score += 10;
}
// 包含匹配
else if (itemName.includes(keyword) || itemTitle.includes(keyword)) {
score += 5;
}
// 部分匹配
else if (keyword.includes(itemName) || keyword.includes(itemTitle)) {
score += 2;
}
}
return score;
},
// 选择最佳匹配
selectBestMatch(matchedMenus, keywords) {
if (matchedMenus.length === 1) {
return matchedMenus[0];
}
// 优先选择完全匹配的项目
for (const keyword of keywords) {
const exactMatch = matchedMenus.find(item =>
item.name === keyword || item.title === keyword
);
if (exactMatch) {
return exactMatch;
}
}
// 返回分数最高的
return matchedMenus[0];
},
// 导航到指定页面
navigateToPage(target) {
if (!target.path) {
this.showMessage(`找到了"${target.name}",但未配置路由`, 'error');
return;
}
try {
// 检查路由是否存在
const route = this.$router.resolve(target.path);
if (route.resolved.matched.length > 0) {
console.log(target.path,'-=-=-');
this.$router.push(target.path);
this.showMessage(`已跳转到:${target.name || target.title}(匹配分数:${target.matchScore})`, 'info');
} else {
this.showMessage(`路由 "${target.path}" 不存在,请检查路由配置`, 'error');
console.error('路由不存在:', target.path);
}
} catch (error) {
console.error('路由跳转失败:', error);
this.showMessage(`跳转失败:${error.message}`, 'error');
}
},
// 简单提取关键字(保留作为备用方法)
extractKeyword(command) {
return command
.replace(/帮我|请|跳转到|页面|我想|查看|进入|那个|啥|的/gi, '')
.replace(/\s+/g, '')
.trim() || command.slice(-6).trim(); // fallback
},
// 从菜单数据中查找包含关键字的菜单项(保留原方法作为备用)
findMenusByKeyword(menus, keyword) {
const result = [];
const search = (items) => {
for (const item of items) {
if (
(item.name && item.name.includes(keyword)) ||
(item.title && item.title.includes(keyword))
) {
if (item.path) {
console.log(item, 'item===');
result.push(item);
}
}
if (item.children && item.children.length > 0) {
search(item.children);
console.log(item, item.children, 'item.children===');
}
}
};
search(menus);
return result;
},
// 处理发送按钮(比如手动输入指令后点击发送)
handleSendCommand() {
if (!this.commandText.trim()) {
this.showMessage('请输入或识别一条指令', 'error');
return;
}
this.handleCommand(this.commandText);
},
// 显示提示信息
showMessage(text, type = 'info') {
this.message = text;
this.messageType = type;
setTimeout(() => {
this.message = '';
}, 3000);
},
},
};
</script>
<style scoped>
.voice-assistant-input {
max-width: 500px;
margin: 20px auto;
padding: 20px;
border: 1px solid #ddd;
border-radius: 8px;
font-family: Arial, sans-serif;
text-align: center;
background:#34537C;
}
.input-container {
margin-bottom: 16px;
}
.command-input {
width: 100%;
padding: 12px;
font-size: 16px;
border: 1px solid #ccc;
border-radius: 6px;
box-sizing: border-box;
text-align: left;
background-color: #f9f9f9;
}
.button-container {
display: flex;
justify-content: center;
gap: 12px;
}
.mic-btn,
.send-btn {
padding: 10px 16px;
font-size: 18px;
border: none;
border-radius: 6px;
cursor: pointer;
transition: background-color 0.2s;
}
.mic-btn {
background-color: #28a745;
color: white;
}
.mic-btn:hover {
background-color: #218838;
}
.send-btn {
background-color: #007bff;
color: white;
}
.send-btn:hover {
background-color: #0056b3;
}
.message {
margin-top: 12px;
font-weight: bold;
}
.message.info {
color: #007bff;
}
.message.error {
color: #dc3545;
}
</style>
js
// 唤起windows本身的麦克风,然后说话展示话术。
<template>
<div class="voice-assistant-input">
<!-- 输入框:用于显示语音识别结果 / 指令 -->
<div class="input-container">
<input
ref="commandInput"
v-model="commandText"
type="text"
placeholder="请使用Windows语音识别或手动输入指令..."
class="command-input"
@keyup.enter="handleSendCommand"
/>
</div>
<!-- 操作按钮:语音输入提示 + 发送 -->
<div class="button-container">
<!-- 语音输入提示按钮 -->
<!-- <button @click="showVoiceInputGuide" class="voice-guide-btn" title="查看语音输入使用指南">
🎤 语音输入
</button> -->
<!-- 清空按钮 -->
<button @click="clearInput" class="clear-btn" title="清空输入框">
🗑️ 清空
</button>
<!-- 发送按钮 -->
<button @click="handleSendCommand" class="send-btn" title="执行当前指令">
📤 执行
</button>
</div>
<!-- 语音输入指南 -->
<div v-if="showGuide" class="voice-guide">
<h4>🎤 Windows语音输入使用指南</h4>
<div class="guide-content">
<p><strong>方法一:Windows语音识别</strong></p>
<ol>
<li>按 <kbd>Win + H</kbd> 开启Windows语音输入</li>
<li>对着麦克风说出指令(如:"数据监测"、"用户管理"、"跳转运行视图")</li>
<li>语音识别结果会自动填入上方输入框并自动执行</li>
<li>如果没有自动跳转,请手动点击"执行"按钮</li>
</ol>
<p><strong>方法二:第三方语音输入软件</strong></p>
<ul>
<li>讯飞输入法:按住语音键说话</li>
<li>搜狗输入法:Shift + 空格 启用语音输入</li>
<li>百度输入法:Ctrl + Shift + S 语音输入</li>
</ul>
<p><strong>支持的指令示例:</strong></p>
<div class="command-examples">
<span class="example-tag">数据监测</span>
<span class="example-tag">实时数据</span>
<span class="example-tag">用户管理</span>
<span class="example-tag">角色管理</span>
<span class="example-tag">菜单管理</span>
<span class="example-tag">系统管理</span>
<span class="example-tag">财务报表</span>
<span class="example-tag">运行视图</span>
</div>
</div>
<button @click="showGuide = false" class="close-guide-btn">关闭指南</button>
</div>
<!-- 提示信息 -->
<p v-if="message" :class="['message', messageType]">
{{ message }}
</p>
</div>
</template>
<script>
export default {
name: 'VoiceAssistantInput',
props: {
// 后端返回的菜单数据,每个菜单项需包含 name/title 和 path
menuData: {
type: Array,
required: true,
},
},
data() {
return {
commandText: '', // 输入框中显示的指令(语音识别结果 or 手动输入)
message: '', // 提示信息
messageType: 'info', // info / error / success
showGuide: false, // 是否显示语音输入指南
lastCommandText: '', // 记录上一次的指令文本
};
},
mounted() {
// 组件加载时显示欢迎信息
this.showMessage('💡 提示:您可以使用Windows语音输入(Win+H)或手动输入指令进行页面导航', 'info');
// 监听输入框变化,实现自动执行
this.setupAutoExecution();
},
methods: {
// 设置自动执行监听
setupAutoExecution() {
// 监听输入框内容变化
this.$watch('commandText', (newVal, oldVal) => {
// 如果输入框内容发生变化且不为空
if (newVal && newVal !== oldVal && newVal !== this.lastCommandText) {
this.lastCommandText = newVal;
// 延迟执行,给用户一点时间看到识别结果
setTimeout(() => {
if (this.commandText === newVal) { // 确保内容没有再次变化
console.log('自动执行语音指令:', newVal);
this.handleCommand(newVal);
}
}, 1000); // 1秒后自动执行
}
});
},
// 显示语音输入使用指南
showVoiceInputGuide() {
this.showGuide = !this.showGuide;
if (this.showGuide) {
this.showMessage('📖 语音输入指南已展开,请查看下方说明', 'info');
}
},
// 清空输入框
clearInput() {
this.commandText = '';
this.lastCommandText = '';
this.showMessage('🗑️ 输入框已清空', 'info');
this.$refs.commandInput.focus();
},
// 处理指令(无论是语音还是手动输入)
handleCommand(command) {
if (!command.trim()) {
this.showMessage('指令为空,请重试', 'error');
return;
}
if (!this.menuData || this.menuData.length === 0) {
this.showMessage('菜单数据未加载,无法识别页面', 'error');
return;
}
console.log('原始指令:', command);
console.log('菜单数据:', this.menuData);
// 提取关键字(改进版本)
const keywords = this.extractKeywords(command);
console.log('提取的关键词:', keywords);
if (keywords.length === 0) {
this.showMessage('未识别到有效的页面关键词,请重试', 'error');
return;
}
// 查找匹配的菜单项
const matchedMenus = this.findMenusByKeywords(this.menuData, keywords);
console.log('匹配结果:', matchedMenus);
if (matchedMenus.length === 0) {
this.showMessage(`未找到与"${keywords.join('、')}"相关的页面,请尝试说:数据监测、实时数据、财务报表、运行视图等`, 'error');
return;
}
// 选择最佳匹配
const bestMatch = this.selectBestMatch(matchedMenus, keywords);
this.navigateToPage(bestMatch);
},
// 改进的关键词提取方法
extractKeywords(command) {
// 1. 移除常见的语音指令词汇
let cleanCommand = command
.replace(/帮我|请|跳转到|页面|我想|查看|进入|那个|啥|的|打开|去|到|访问|进去/gi, '')
.replace(/\s+/g, '')
.trim();
console.log('清理后的指令:', cleanCommand);
// 2. 如果清理后为空,使用原始指令
if (!cleanCommand) {
cleanCommand = command.trim();
}
// 3. 分词处理(简单版本)
const keywords = [];
// 常见的页面关键词映射
const keywordMap = {
'数据': ['数据监测', '数据', '监测'],
'实时': ['实时数据', '实时', '数据'],
'财务': ['财务报表', '财务', '报表'],
'销售': ['销售报表', '销售', '报表'],
'用户': ['用户管理', '用户', '管理'],
'角色': ['角色管理', '角色', '管理'],
'菜单': ['菜单管理', '菜单', '管理'],
'系统': ['系统管理', '系统', '管理'],
'报表': ['报表', '财务报表', '销售报表'],
'管理': ['管理', '用户管理', '角色管理', '菜单管理', '系统管理'],
// 新增运行视图相关关键词
'运行': ['运行视图', '运行', '视图', '运行监控', '运行状态'],
'视图': ['运行视图', '视图', '运行', '监控视图', '状态视图'],
'监控': ['运行监控', '监控', '运行视图', '状态监控'],
'状态': ['运行状态', '状态', '运行视图', '状态监控']
};
// 4. 检查是否包含关键词
for (const [key, values] of Object.entries(keywordMap)) {
if (cleanCommand.includes(key)) {
keywords.push(...values);
}
}
// 5. 如果没有匹配到预定义关键词,直接使用清理后的指令
if (keywords.length === 0) {
keywords.push(cleanCommand);
}
// 6. 去重
return [...new Set(keywords)];
},
// 改进的菜单搜索方法
findMenusByKeywords(menus, keywords) {
const result = [];
const search = (items) => {
for (const item of items) {
// 计算匹配分数
const score = this.calculateMatchScore(item, keywords);
if (score > 0) {
if (item.path) {
result.push({ ...item, matchScore: score });
}
}
if (item.children && item.children.length > 0) {
search(item.children);
}
}
};
search(menus);
// 按匹配分数排序
return result.sort((a, b) => b.matchScore - a.matchScore);
},
// 计算匹配分数
calculateMatchScore(item, keywords) {
let score = 0;
const itemName = item.name || '';
const itemTitle = item.title || '';
for (const keyword of keywords) {
// 完全匹配得分最高
if (itemName === keyword || itemTitle === keyword) {
score += 10;
}
// 包含匹配
else if (itemName.includes(keyword) || itemTitle.includes(keyword)) {
score += 5;
}
// 部分匹配
else if (keyword.includes(itemName) || keyword.includes(itemTitle)) {
score += 2;
}
}
return score;
},
// 选择最佳匹配
selectBestMatch(matchedMenus, keywords) {
if (matchedMenus.length === 1) {
return matchedMenus[0];
}
// 优先选择完全匹配的项目
for (const keyword of keywords) {
const exactMatch = matchedMenus.find(item =>
item.name === keyword || item.title === keyword
);
if (exactMatch) {
return exactMatch;
}
}
// 返回分数最高的
return matchedMenus[0];
},
// 导航到指定页面
navigateToPage(target) {
if (!target.path) {
this.showMessage(`找到了"${target.name}",但未配置路由`, 'error');
return;
}
try {
// 检查路由是否存在
const route = this.$router.resolve(target.path);
if (route.resolved.matched.length > 0) {
console.log(target.path, '-=-=-');
this.$router.push(target.path);
this.showMessage(`✅ 已跳转到:${target.name || target.title}(匹配分数:${target.matchScore})`, 'success');
// 跳转成功后清空输入框
setTimeout(() => {
this.commandText = '';
}, 1000);
} else {
this.showMessage(`路由 "${target.path}" 不存在,请检查路由配置`, 'error');
console.error('路由不存在:', target.path);
}
} catch (error) {
console.error('路由跳转失败:', error);
this.showMessage(`跳转失败:${error.message}`, 'error');
}
},
// 处理发送按钮(手动输入指令后点击发送)
handleSendCommand() {
if (!this.commandText.trim()) {
this.showMessage('请输入指令或使用语音输入', 'error');
this.$refs.commandInput.focus();
return;
}
this.handleCommand(this.commandText);
},
// 显示提示信息
showMessage(text, type = 'info') {
this.message = text;
this.messageType = type;
// 根据消息类型设置不同的显示时间
const timeout = type === 'error' ? 5000 : 3000;
setTimeout(() => {
this.message = '';
}, timeout);
},
},
};
</script>
<style scoped>
.voice-assistant-input {
max-width: 600px;
margin: 20px auto;
padding: 20px;
border: 1px solid #ddd;
border-radius: 8px;
font-family: Arial, sans-serif;
text-align: center;
background: #34537C;
color: white;
}
.input-container {
margin-bottom: 16px;
}
.command-input {
width: 100%;
padding: 12px;
font-size: 16px;
border: 1px solid #ccc;
border-radius: 6px;
box-sizing: border-box;
text-align: left;
background-color: #f9f9f9;
color: #333;
}
.command-input:focus {
outline: none;
border-color: #007bff;
box-shadow: 0 0 5px rgba(0, 123, 255, 0.3);
}
.button-container {
display: flex;
justify-content: center;
gap: 12px;
flex-wrap: wrap;
}
.voice-guide-btn,
.clear-btn,
.send-btn {
padding: 10px 16px;
font-size: 14px;
border: none;
border-radius: 6px;
cursor: pointer;
transition: all 0.2s;
font-weight: bold;
}
.voice-guide-btn {
background-color: #17a2b8;
color: white;
}
.voice-guide-btn:hover {
background-color: #138496;
transform: translateY(-1px);
}
.clear-btn {
background-color: #6c757d;
color: white;
}
.clear-btn:hover {
background-color: #545b62;
transform: translateY(-1px);
}
.send-btn {
background-color: #28a745;
color: white;
}
.send-btn:hover {
background-color: #218838;
transform: translateY(-1px);
}
.voice-guide {
margin-top: 20px;
padding: 20px;
background-color: rgba(255, 255, 255, 0.95);
border-radius: 8px;
text-align: left;
color: #333;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}
.voice-guide h4 {
margin-top: 0;
color: #007bff;
text-align: center;
}
.guide-content {
line-height: 1.6;
}
.guide-content ol,
.guide-content ul {
padding-left: 20px;
}
.guide-content li {
margin-bottom: 8px;
}
.guide-content kbd {
background-color: #f8f9fa;
border: 1px solid #dee2e6;
border-radius: 3px;
padding: 2px 6px;
font-size: 12px;
color: #495057;
}
.command-examples {
display: flex;
flex-wrap: wrap;
gap: 8px;
margin-top: 10px;
}
.example-tag {
background-color: #e9ecef;
color: #495057;
padding: 4px 8px;
border-radius: 4px;
font-size: 12px;
border: 1px solid #ced4da;
}
.close-guide-btn {
display: block;
margin: 15px auto 0;
padding: 8px 16px;
background-color: #dc3545;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 14px;
}
.close-guide-btn:hover {
background-color: #c82333;
}
.message {
margin-top: 12px;
font-weight: bold;
padding: 10px;
border-radius: 4px;
}
.message.info {
color: #0c5460;
background-color: #d1ecf1;
border: 1px solid #bee5eb;
}
.message.error {
color: #721c24;
background-color: #f8d7da;
border: 1px solid #f5c6cb;
}
.message.success {
color: #155724;
background-color: #d4edda;
border: 1px solid #c3e6cb;
}
/* 响应式设计 */
@media (max-width: 768px) {
.voice-assistant-input {
margin: 10px;
padding: 15px;
}
.button-container {
flex-direction: column;
align-items: center;
}
.voice-guide-btn,
.clear-btn,
.send-btn {
width: 100%;
max-width: 200px;
}
}
</style>
js
//父组件进行展示
<div v-if="isDivVisible" class="znkuzsBox">
<VoiceAssistantInput :menuData="menuList" />
</div>
data(){
return{
menuList: [
{
name: '数据监测',
children: [
{ name: '数据监测', path: '/xxxx/xxxx', title: '数据监测' },
],
},
{
name: '运行视图',
children: [
{ name: '运行视图', path: '/xxxx/xxxxx', title: '运行视图' }
],
},
],
}
},