feature:

1.OTA基本能力(固定配置),待优化
2.智能体管理与设备管理对接api,实现流程闭环(已测试)
This commit is contained in:
Erlei Chen
2025-03-24 09:26:45 +08:00
parent 66352de1eb
commit bdd18b384b
55 changed files with 1747 additions and 332 deletions
+2 -2
View File
@@ -9,9 +9,9 @@ import user from './module/user.js'
* 如果你想调用8002端口,就用'/xiaozhi-esp32-api/api/v1',请与vue.config.js的devServer配置相结合,方便跨域请求
*
*/
const DEV_API_SERVICE = 'https://m1.apifoxmock.com/m1/5931378-5618560-default'
// const DEV_API_SERVICE = 'https://m1.apifoxmock.com/m1/5931378-5618560-default'
// 8002开发完成完成后使用这个
// const DEV_API_SERVICE = '/xiaozhi-esp32-api'
const DEV_API_SERVICE = '/xiaozhi-esp32-api'
/**
* 根据开发环境返回接口url
+2 -5
View File
@@ -16,20 +16,17 @@ export default {
}).send()
},
//添加智能体
addAgent(name, callback) {
addAgent(agentName, callback) {
RequestService.sendRequest()
.url(`${getServiceUrl()}/api/v1/user/agent`)
.method('POST')
.data({name})
.data({agentName})
.success((res) => {
RequestService.clearRequestTime();
callback(res);
})
.fail((err) => {
console.error('添加智能体失败:', err);
RequestService.reAjaxFun(() => {
this.addAgent(name, callback);
});
}).send();
},
//获取智能体配置
+9 -8
View File
@@ -4,9 +4,10 @@ import {getServiceUrl} from '../api'
export default {
//设备列表
getDeviceList(agent_id, callback) {
getDeviceList(agent_id, page, callback) {
RequestService.sendRequest().url(`${getServiceUrl()}/api/v1/user/agent/device/bind/${agent_id}`)
.method('GET')
.data(page)
.success((res) => {
RequestService.clearRequestTime()
callback(res)
@@ -16,11 +17,11 @@ export default {
}).send()
},
//绑定设备
bindDevice(agent_id, code, callback) {
bindDevice(agentId, deviceCode, callback) {
RequestService.sendRequest()
.url(`${getServiceUrl()}/api/v1/user/agent/device/bind/${agent_id}`)
.url(`${getServiceUrl()}/api/v1/user/agent/device/bind/${agentId}`)
.method('POST')
.data({code})
.data({deviceCode})
.success((res) => {
RequestService.clearRequestTime();
callback(res);
@@ -28,14 +29,14 @@ export default {
.fail((err) => {
console.error('绑定设备失败:', err);
RequestService.reAjaxFun(() => {
this.addDevice(name, callback);
this.addDevice(agentId, deviceCode, callback);
});
}).send();
},
// 解绑设备
unbindDevice(device_id, callback) {
unbindDevice(deviceId, callback) {
RequestService.sendRequest()
.url(`${getServiceUrl()}/api/v1/user/device/unbind/${device_id}`)
.url(`${getServiceUrl()}/api/v1/user/agent/device/unbind/${deviceId}`)
.method('PUT')
.success((res) => {
RequestService.clearRequestTime();
@@ -43,7 +44,7 @@ export default {
})
.fail(() => {
RequestService.reAjaxFun(() => {
this.unbindDevice(device_id, callback);
this.unbindDevice(deviceId, callback);
});
}).send()
},
@@ -46,12 +46,13 @@ export default {
this.$message.error('请输入智能体名称');
return;
}
userApi.addAgent(this.agentName, (res) => {
this.$message.success('添加成功');
this.$emit('confirm', res);
this.$emit('confirm',this.agentName)
// userApi.addAgent(this.agentName, (res) => {
// this.$message.success('添加成功');
// this.$emit('confirm', res);
this.$emit('update:visible', false);
this.agentName = "";
});
// });
},
cancel() {
this.$emit('update:visible', false)
@@ -40,8 +40,12 @@ export default {
},
methods: {
confirm() {
if (!this.deviceCode.trim()) {
this.$message.error('请输入设备验证码');
return;
}
this.$emit('confirm',this.deviceCode)
this.$emit('update:visible', false)
this.$emit('added', this.deviceCode)
this.deviceCode = ""
},
cancel() {
+6 -1
View File
@@ -39,10 +39,13 @@ function formatDateTool(date, fmt) {
const o = {
'M+': date.getMonth() + 1,
'd+': date.getDate(),
'h+': date.getHours(),
'H+': date.getHours(),
'h+': date.getHours() > 12 ? date.getHours() - 12 : date.getHours(),
'm+': date.getMinutes(),
's+': date.getSeconds()
}
// 12小时制
const is_12Hours = fmt.indexOf('hh') > -1;
for (const k in o) {
if (new RegExp(`(${k})`).test(fmt)) {
const str = o[k] + ''
@@ -52,6 +55,8 @@ function formatDateTool(date, fmt) {
)
}
}
// 12小时制
fmt = is_12Hours ? date.getHours() > 12 ? fmt + " PM" : fmt + " AM" : fmt
return fmt
}
+46 -18
View File
@@ -18,50 +18,53 @@
+ 添加设备
</el-button>
<el-table :data="devices" style="width: 100%; margin-top: 20px" border>
<el-table-column label="设备型号" prop="device_type" flex></el-table-column>
<el-table-column label="固件版本" prop="app_version" width="140"></el-table-column>
<el-table-column label="MAC地址" prop="mac_address" width="220"></el-table-column>
<el-table-column label="绑定时间" prop="bind_time" width="260"></el-table-column>
<el-table-column label="设备型号" prop="board" flex></el-table-column>
<el-table-column label="固件版本" prop="appVersion" width="140"></el-table-column>
<el-table-column label="MAC地址" prop="macAddress" width="220"></el-table-column>
<el-table-column label="绑定时间" width="260" prop="createDate" :formatter="formatter">
</el-table-column>
<el-table-column label="最近对话" prop="recent_chat_time" width="100"></el-table-column>
<el-table-column label="备注" width="220">
<template slot-scope="scope">
<el-input v-if="scope.row.isEdit" v-model="scope.row.remark" size="small" @blur="stopEditRemark(scope.$index)"></el-input>
<el-input v-if="scope.row.isEdit" v-model="scope.row.alias" size="small" @blur="stopEditRemark(scope.$index)"></el-input>
<span v-else>
{{ scope.row.remark }}
{{ scope.row.alias }}
</span>
<i v-if="!scope.row.isEdit" class="el-icon-edit" @click="startEditRemark(scope.$index, scope.row)"></i>
</template>
</el-table-column>
<el-table-column label="OTA升级" width="100" align="center">
<template slot-scope="scope">
<el-switch v-model="scope.row.ota_upgrade" size="mini" :active-value="1" :inactive-value="0" active-color="#13ce66" inactive-color="#ff4949"></el-switch>
<el-switch v-model="scope.row.autoUpdate" size="mini" :active-value="1" :inactive-value="0" active-color="#13ce66" inactive-color="#ff4949"></el-switch>
</template>
</el-table-column>
<el-table-column label="操作" width="80" align="center">
<template slot-scope="scope">
<el-button size="mini" type="text" @click="handleUnbind(scope.row)" style="color: #ff4949">
<el-button size="mini" type="text" @click="handleUnbind(scope.row.id)" style="color: #ff4949">
解绑
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<el-pagination background :page-size="10" :pager-count="5" layout="prev, pager, next" :total="150" style="margin-top: 4px;text-align: right;"></el-pagination>
<el-pagination background :current-page="page.pageNo" :page-size="page.pageSize" :pager-count="5" layout="prev, pager, next" :total="page.total" style="margin-top: 4px;text-align: right;"></el-pagination>
</div>
<!-- 底部 -->
<Footer :visible="true" />
<!-- 添加设备对话框 -->
<AddDeviceDialog :visible.sync="addDeviceDialogVisible" @added="handleDeviceAdded" />
<AddDeviceDialog :visible.sync="addDeviceDialogVisible" @confirm="handleDeviceBind" />
</el-main>
</div>
</template>
<script>
import {getUUID, goToPage, showDanger, showSuccess} from '@/utils'
import { formatDate } from '@/utils/date'
import Api from '@/apis/api';
import AddDeviceDialog from '@/components/AddDeviceDialog.vue'
import HeaderBar from '@/components/HeaderBar.vue'
import Footer from '@/components/Footer.vue'
import api from '@/apis/api';
export default {
name: 'DevicePage',
@@ -70,18 +73,24 @@ export default {
return {
addDeviceDialogVisible: false,
devices: [],
agentId: this.$route.query.agentId
agentId: this.$route.query.agentId,
page: {
pageNo: 1,
pageSize: 10,
total: 0
}
}
},
mounted() {
this.getDeviceList();
this.fetchDeviceList();
},
methods: {
// 获取设备列表
getDeviceList() {
Api.device.getDeviceList(this.agentId, ({data}) => {
fetchDeviceList() {
Api.device.getDeviceList(this.agentId, this.page, ({data}) => {
if (data.code === 0) {
this.devices = data.data[0].list.map((item)=>{item.isEdit=false;return item;})
this.page = {...this.page,total:parseInt(data.data.total)}
this.devices = data.data.records.map((item)=>{item.isEdit=false;return item;})
} else {
showDanger(data.msg)
}
@@ -97,14 +106,33 @@ export default {
stopEditRemark(index) {
this.devices[index].isEdit = false;
},
handleUnbind(device) {
handleUnbind(deviceId) {
// 解绑逻辑
console.log('解绑设备', device);
console.log('解绑设备', deviceId);
Api.device.unbindDevice(deviceId, ({data}) => {
if (data.code === 0) {
showSuccess('解绑成功')
this.fetchDeviceList()
} else {
showDanger(data.msg)
}
})
},
handleDeviceAdded(deviceCode) {
handleDeviceBind(deviceCode) {
// 根据需要处理添加设备后逻辑,比如刷新设备列表等
console.log('设备验证码:', deviceCode)
Api.device.bindDevice(this.agentId, deviceCode, ({data}) => {
if (data.code === 0) {
this.fetchDeviceList();
this.showBindDialog = false;
} else {
showDanger(data.msg);
}
})
},
formatter(row, column) {
return formatDate(row.createDate)
}
}
};
</script>
+3 -3
View File
@@ -1,7 +1,7 @@
<template>
<div class="welcome">
<!-- 公共头部 -->
<HeaderBar :devices="devices" @search-result="handleSearchResult" />
<HeaderBar :devices="agents" @search-result="handleSearchResult" />
<el-main style="padding: 20px;display: flex;flex-direction: column;">
<div>
<!-- 首页内容 -->
@@ -45,7 +45,7 @@
<!-- 底部 -->
<Footer :visible="true" />
<!-- 添加设备对话框 -->
<AddAgentDialog :visible.sync="addAgentDialogVisible" @added="handleAgentAdded" />
<AddAgentDialog :visible.sync="addAgentDialogVisible" @confirm="handleAgentAdded" />
</el-main>
</div>
@@ -120,7 +120,7 @@ export default {
},
// 搜索更新智能体列表
handleSearchResult(filteredList) {
this.devices = filteredList; // 更新设备列表
this.agents = filteredList; // 更新设备列表
}
}
}
+12 -12
View File
@@ -119,19 +119,19 @@ export default {
intent:""
}
},
options: [
{ value: '选项1', label: '黄金糕' },
{ value: '选项2', label: '双皮奶' }
],
options: [
{ value: '选项1', label: '黄金糕' },
{ value: '选项2', label: '双皮奶' }
],
models: [
{ label: '大语言模型(LLM)', key: 'llm' },
{ label: '语音转文本模型(ASR)', key: 'asr' },
{ label: '语音活动检测模型(VAD)', key: 'vad' },
{ label: '语音生成模型(TTS)', key: 'tts' },
{ label: '意图分类模型(Intent)', key: 'intent' },
{ label: '记忆增强模型(Memory)', key: 'memory' }
],
templates: ['台湾女友', '土豆子', '英语老师', '好奇小男孩', '汪汪队队长']
{ label: '大语言模型(LLM)', key: 'llm' },
{ label: '语音转文本模型(ASR)', key: 'asr' },
{ label: '语音活动检测模型(VAD)', key: 'vad' },
{ label: '语音生成模型(TTS)', key: 'tts' },
{ label: '意图分类模型(Intent)', key: 'intent' },
{ label: '记忆增强模型(Memory)', key: 'memory' }
],
templates: ['通用男声','通用女声','阳光男生','奶气萌娃']
}
},