feature:OTA能力完善

This commit is contained in:
Erlei Chen
2025-03-26 17:00:54 +08:00
parent bdd18b384b
commit ee0da9fc3a
31 changed files with 1044 additions and 225 deletions
+4 -2
View File
@@ -2,6 +2,7 @@
import agent from './module/agent.js'
import device from './module/device.js'
import user from './module/user.js'
import ota from './module/ota.js'
/**
* 接口地址
@@ -11,7 +12,7 @@ import user from './module/user.js'
*/
// 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/api/v1'
/**
* 根据开发环境返回接口url
@@ -27,5 +28,6 @@ export default {
getServiceUrl,
user,
agent,
device
device,
ota
}
+17 -17
View File
@@ -5,7 +5,7 @@ import {getServiceUrl} from '../api'
export default {
//智能体列表
getAgentList(callback) {
RequestService.sendRequest().url(`${getServiceUrl()}/api/v1/user/agent`)
RequestService.sendRequest().url(`${getServiceUrl()}/user/agent`)
.method('GET')
.success((res) => {
RequestService.clearRequestTime()
@@ -18,7 +18,7 @@ export default {
//添加智能体
addAgent(agentName, callback) {
RequestService.sendRequest()
.url(`${getServiceUrl()}/api/v1/user/agent`)
.url(`${getServiceUrl()}/user/agent`)
.method('POST')
.data({agentName})
.success((res) => {
@@ -30,9 +30,9 @@ export default {
}).send();
},
//获取智能体配置
getAgentConfig(agent_id, callback) {
getAgentConfig(agentId, callback) {
RequestService.sendRequest()
.url(`${getServiceUrl()}/api/v1/user/agent/${agent_id}`)
.url(`${getServiceUrl()}/user/agent/${agentId}`)
.method('GET')
.success((res) => {
RequestService.clearRequestTime();
@@ -40,15 +40,15 @@ export default {
})
.fail((err) => {
console.error('获取智能体配置失败:', err);
RequestService.reAjaxFun(() => {
this.getAgentConfig(agent_id, callback);
});
// RequestService.reAjaxFun(() => {
// this.getAgentConfig(agent_id, callback);
// });
}).send();
},
//配置智能体
saveAgentConfig(agent_id, configData, callback) {
saveAgentConfig(agentId, configData, callback) {
RequestService.sendRequest()
.url(`${getServiceUrl()}/api/v1/user/agent/${agent_id}`)
.url(`${getServiceUrl()}/user/agent/${agentId}`)
.method('PUT')
.data(configData)
.success((res) => {
@@ -57,15 +57,15 @@ export default {
})
.fail((err) => {
console.error('保存智能体配置失败:', err);
RequestService.reAjaxFun(() => {
this.saveAgentConfig(device_id, configData, callback);
});
// RequestService.reAjaxFun(() => {
// this.saveAgentConfig(device_id, configData, callback);
// });
}).send();
},
//删除智能体
delAgent(agent_id, callback) {
delAgent(agentId, callback) {
RequestService.sendRequest()
.url(`${getServiceUrl()}/api/v1/user/agent/${agent_id}`)
.url(`${getServiceUrl()}/user/agent/${agentId}`)
.method('DELETE')
.success((res) => {
RequestService.clearRequestTime();
@@ -73,9 +73,9 @@ export default {
})
.fail((err) => {
console.error('删除智能体失败:', err);
RequestService.reAjaxFun(() => {
this.deleteAgent(agent_id, callback);
});
// RequestService.reAjaxFun(() => {
// this.deleteAgent(agent_id, callback);
// });
}).send();
},
}
+39 -10
View File
@@ -5,7 +5,7 @@ import {getServiceUrl} from '../api'
export default {
//设备列表
getDeviceList(agent_id, page, callback) {
RequestService.sendRequest().url(`${getServiceUrl()}/api/v1/user/agent/device/bind/${agent_id}`)
RequestService.sendRequest().url(`${getServiceUrl()}/user/agent/device/bind/${agent_id}`)
.method('GET')
.data(page)
.success((res) => {
@@ -19,7 +19,7 @@ export default {
//绑定设备
bindDevice(agentId, deviceCode, callback) {
RequestService.sendRequest()
.url(`${getServiceUrl()}/api/v1/user/agent/device/bind/${agentId}`)
.url(`${getServiceUrl()}/user/agent/device/bind/${agentId}`)
.method('POST')
.data({deviceCode})
.success((res) => {
@@ -28,24 +28,53 @@ export default {
})
.fail((err) => {
console.error('绑定设备失败:', err);
RequestService.reAjaxFun(() => {
this.addDevice(agentId, deviceCode, callback);
});
// RequestService.reAjaxFun(() => {
// this.addDevice(agentId, deviceCode, callback);
// });
}).send();
},
// 解绑设备
unbindDevice(deviceId, callback) {
RequestService.sendRequest()
.url(`${getServiceUrl()}/api/v1/user/agent/device/unbind/${deviceId}`)
.url(`${getServiceUrl()}/user/agent/device/unbind/${deviceId}`)
.method('PUT')
.success((res) => {
RequestService.clearRequestTime();
callback(res);
})
.fail(() => {
RequestService.reAjaxFun(() => {
this.unbindDevice(deviceId, callback);
});
.fail((err) => {
console.error('解绑设备失败:', err);
// RequestService.reAjaxFun(() => {
// this.unbindDevice(deviceId, callback);
// });
}).send()
},
// 切换设备OTA升级状态
toggleAutoUpdate(deviceId, autoUpdate, callback) {
RequestService.sendRequest()
.url(`${getServiceUrl()}/user/agent/device/autoUpdate/${deviceId}`)
.method('POST')
.data({autoUpdate})
.success((res) => {
RequestService.clearRequestTime();
callback(res);
})
.fail((err) => {
console.error('切换设备OTA升级状态失败:', err);
}).send()
},
// 设置设备别名
setAlias(deviceId, alias, callback) {
RequestService.sendRequest()
.url(`${getServiceUrl()}/user/agent/device/alias/${deviceId}`)
.method('POST')
.data({alias})
.success((res) => {
RequestService.clearRequestTime();
callback(res);
})
.fail((err) => {
console.error('设置设备别名失败:', err);
}).send()
},
+67
View File
@@ -0,0 +1,67 @@
import RequestService from '../httpRequest'
import {getServiceUrl} from '../api'
export default {
//设备OTA列表
getOtaList(page, callback) {
RequestService.sendRequest().url(`${getServiceUrl()}/ota/sys/getOtalist`)
.method('GET')
.data(page)
.success((res) => {
RequestService.clearRequestTime()
callback(res)
})
.fail((err) => {
console.error('获取设备OTA列表失败:', err);
}).send()
},
//添加设备OTA
saveOta(ota, callback) {
RequestService.sendRequest()
.url(`${getServiceUrl()}/ota/sys/save`)
.method('POST')
.data(ota)
.success((res) => {
RequestService.clearRequestTime();
callback(res);
})
.fail((err) => {
console.error('添加设备OTA失败:', err);
}).send();
},
//配置设备OTA
updateOta(ota, callback) {
RequestService.sendRequest()
.url(`${getServiceUrl()}/ota/sys/update`)
.method('POST')
.data(ota)
.success((res) => {
RequestService.clearRequestTime();
callback(res);
})
.fail((err) => {
console.error('保存设备OTA配置失败:', err);
// RequestService.reAjaxFun(() => {
// this.saveAgentConfig(device_id, configData, callback);
// });
}).send();
},
//切换设备OTA可用状态失败
toggleEnabled(ota, callback) {
RequestService.sendRequest()
.url(`${getServiceUrl()}/ota/sys/toggleEnabled`)
.method('POST')
.data(ota)
.success((res) => {
RequestService.clearRequestTime();
callback(res);
})
.fail((err) => {
console.error('切换设备OTA可用状态失败:', err);
// RequestService.reAjaxFun(() => {
// this.deleteAgent(agent_id, callback);
// });
}).send();
},
}
+25 -118
View File
@@ -5,53 +5,24 @@ import {getServiceUrl} from '../api'
export default {
// 登录
login(loginForm, callback) {
RequestService.sendRequest().url(`${getServiceUrl()}/api/v1/user/login`)
RequestService.sendRequest().url(`${getServiceUrl()}/user/login`)
.method('POST')
.data(loginForm)
.success((res) => {
RequestService.clearRequestTime()
callback(res)
})
.fail(() => {
RequestService.reAjaxFun(() => {
this.login(loginForm, callback)
})
.fail((err) => {
console.error('登录失败:', err);
// RequestService.reAjaxFun(() => {
// this.login(loginForm, callback)
// })
}).send()
},
// 获取设备信息
getHomeList(callback) {
RequestService.sendRequest().url(`${getServiceUrl()}/api/v1/user/device/bind`)
.method('GET')
.success((res) => {
RequestService.clearRequestTime()
callback(res)
})
.fail(() => {
RequestService.reAjaxFun(() => {
this.getUserInfo()
})
}).send()
},
// 解绑设备
unbindDevice(device_id, callback) {
RequestService.sendRequest()
.url(`${getServiceUrl()}/api/v1/user/device/unbind/${device_id}`)
.method('PUT')
.success((res) => {
RequestService.clearRequestTime();
callback(res);
})
.fail(() => {
RequestService.reAjaxFun(() => {
this.unbindDevice(device_id, callback);
});
}).send()
},
// 获取验证码
}, // 获取验证码
getCaptcha(uuid, callback) {
RequestService.sendRequest()
.url(`${getServiceUrl()}/api/v1/user/captcha?uuid=${uuid}`)
.url(`${getServiceUrl()}/user/captcha?uuid=${uuid}`)
.method('GET')
.type('blob')
.header({
@@ -64,104 +35,57 @@ export default {
callback(res);
})
.fail((err) => { // 添加错误参数
console.error('获取验证码失败:', err);
}).send()
},
// 注册账号
register(registerForm, callback) {
RequestService.sendRequest().url(`${getServiceUrl()}/api/v1/user/register`).method('POST')
RequestService.sendRequest().url(`${getServiceUrl()}/user/register`).method('POST')
.data(registerForm)
.success((res) => {
RequestService.clearRequestTime()
callback(res)
})
.fail(() => {
.fail((err) => {
console.error('注册账号失败:', err);
}).send()
},
// 保存设备配置
saveDeviceConfig(device_id, configData, callback) {
RequestService.sendRequest()
.url(`${getServiceUrl()}/api/v1/user/configDevice/${device_id}`)
.method('PUT')
.data(configData)
.success((res) => {
RequestService.clearRequestTime();
callback(res);
})
.fail((err) => {
console.error('保存配置失败:', err);
RequestService.reAjaxFun(() => {
this.saveDeviceConfig(device_id, configData, callback);
});
}).send();
},
// 获取设备配置
getDeviceConfig(device_id, callback) {
RequestService.sendRequest()
.url(`${getServiceUrl()}/api/v1/user/configDevice/${device_id}`)
.method('GET')
.success((res) => {
RequestService.clearRequestTime();
callback(res);
})
.fail((err) => {
console.error('获取配置失败:', err);
RequestService.reAjaxFun(() => {
this.getDeviceConfig(device_id, callback);
});
}).send();
},
// 获取所有模型名称
getModelNames(callback) {
RequestService.sendRequest()
.url(`${getServiceUrl()}/api/v1/models/names`)
.url(`${getServiceUrl()}/models/names`)
.method('GET')
.success((res) => {
RequestService.clearRequestTime();
callback(res);
})
.fail(() => {
RequestService.reAjaxFun(() => {
this.getModelNames(callback);
});
// RequestService.reAjaxFun(() => {
// this.getModelNames(callback);
// });
}).send();
},
// 获取模型音色
getModelVoices(modelName, callback) {
RequestService.sendRequest()
.url(`${getServiceUrl()}/api/v1/models/${modelName}/voices`)
.url(`${getServiceUrl()}/models/${modelName}/voices`)
.method('GET')
.success((res) => {
RequestService.clearRequestTime();
callback(res);
})
.fail(() => {
RequestService.reAjaxFun(() => {
this.getModelVoices(modelName, callback);
});
// RequestService.reAjaxFun(() => {
// this.getModelVoices(modelName, callback);
// });
}).send();
},
// 获取智能体列表
getAgentList(callback) {
RequestService.sendRequest()
.url(`${getServiceUrl()}/api/v1/user/agent`)
.method('GET')
.success((res) => {
RequestService.clearRequestTime();
callback(res);
})
.fail(() => {
RequestService.reAjaxFun(() => {
this.getAgentList(callback);
});
}).send();
},
// 获取用户信息
getUserInfo(callback) {
RequestService.sendRequest()
.url(`${getServiceUrl()}/api/v1/user/info`)
.url(`${getServiceUrl()}/user/info`)
.method('GET')
.success((res) => {
RequestService.clearRequestTime()
@@ -169,26 +93,9 @@ export default {
})
.fail((err) => {
console.error('接口请求失败:', err)
RequestService.reAjaxFun(() => {
this.getUserInfo(callback)
})
// RequestService.reAjaxFun(() => {
// this.getUserInfo(callback)
// })
}).send()
},
// 添加智能体
addAgent(agentName, callback) {
RequestService.sendRequest()
.url(`${getServiceUrl()}/api/v1/user/agent`)
.method('POST')
.data({ name: agentName })
.success((res) => {
RequestService.clearRequestTime();
callback(res);
})
.fail(() => {
RequestService.reAjaxFun(() => {
this.addAgent(agentName, callback);
});
}).send();
},
}
@@ -1,8 +1,8 @@
<template>
<el-dialog :visible.sync="visible" width="400px" center>
<el-dialog :visible.sync="visible" width="400px" center :close-on-click-modal="false" :close-on-press-escape="false">
<div style="margin: 0 10px 10px;display: flex;align-items: center;gap: 10px;font-weight: 700;font-size: 20px;text-align: left;color: #3d4566;">
<div style="width: 40px;height: 40px;border-radius: 50%;background: #5778ff;display: flex;align-items: center;justify-content: center;">
<img src="@/assets/home/equipment.png" alt="" style="width: 18px;height: 15px;" />
<i class="el-icon-cpu" style="color: #fff;"></i>
</div>
添加智能体
</div>
@@ -1,16 +1,15 @@
<template>
<el-dialog :visible.sync="visible" width="400px" center >
<el-dialog :visible.sync="visible" width="400px" center :close-on-click-modal="false" :close-on-press-escape="false">
<div style="margin: 0 10px 10px;display: flex;align-items: center;gap: 10px;font-weight: 700;font-size: 20px;text-align: left;color: #3d4566;">
<div style="width: 40px;height: 40px;border-radius: 50%;background: #5778ff;display: flex;align-items: center;justify-content: center;">
<img src="@/assets/home/equipment.png" alt="" style="width: 18px;height: 15px;" />
<i class="el-icon-cpu" style="color: #fff;"></i>
</div>
添加设备
</div>
<div style="height: 1px;background: #e8f0ff;" />
<div style="margin: 22px 15px;">
<div style="font-weight: 400;font-size: 14px;text-align: left;color: #3d4566;">
<div style="color: red;display: inline-block;">*</div>
<span style="font-size: 11px"> 验证码</span>
<div style="color: red;display: inline-block;">*</div>验证码
</div>
<div class="input-46" style="margin-top: 12px;">
<el-input placeholder="请输入设备播报的6位数验证码.." v-model="deviceCode" />
@@ -0,0 +1,104 @@
<template>
<el-dialog :visible.sync="visible" width="600px" center :close-on-click-modal="false" :close-on-press-escape="false">
<div style="margin: 0 10px 10px;display: flex;align-items: center;gap: 10px;font-weight: 700;font-size: 20px;text-align: left;color: #3d4566;">
<div style="width: 40px;height: 40px;border-radius: 50%;background: #5778ff;display: flex;align-items: center;justify-content: center;">
<i class="el-icon-lightning" style="color: #fff;"></i>
</div>
{{ data.id?'编辑':'添加' }}设备
</div>
<div style="height: 1px;background: #e8f0ff;" />
<div style="margin: 22px 15px;">
<el-form ref="form" :model="data" label-width="80px">
<el-form-item label="设备型号" prop="board" :rules="[{ required: true, message: '请输入设备型号', trigger: 'blur' }]">
<el-input v-model="data.board" placeholder="请输入设备型号..."></el-input>
</el-form-item>
<el-form-item label="固件版本" prop="appVersion" :rules="[{ required: true, message: '请输入固件版本', trigger: 'blur' }]">
<el-input v-model="data.appVersion" placeholder="请输入固件版本..."></el-input>
</el-form-item>
<el-form-item label="升级地址" prop="url" :rules="[{ required: true, message: '请输入升级地址', trigger: 'blur' },{ type: 'url', message: '请输入正确的升级地址', trigger: 'blur' }]">
<el-input type="textarea" v-model="data.url" placeholder="请输入升级地址..."></el-input>
</el-form-item>
<el-form-item label="是否启用">
<el-switch v-model="data.isEnabled" size="mini" :active-value="1" :inactive-value="0" active-color="#13ce66" inactive-color="#ff4949"></el-switch>
</el-form-item>
<el-form-item label-width="0">
<div style="display: flex;margin: 15px 15px;gap: 7px;">
<div class="dialog-btn" @click="confirm">
确定
</div>
<div class="dialog-btn" style="background: #e6ebff;border: 1px solid #adbdff;color: #5778ff;" @click="cancel">
取消
</div>
</div>
</el-form-item>
</el-form>
</div>
</el-dialog>
</template>
<script>
export default {
name: 'AddDeviceOtaDialog',
props: {
visible: { type: Boolean, required: true },
data: { type: Object,
default: () => ({
id: "",
board: "",
appVersion: "",
url: "",
isEnabled: 1
})
}
},
data() {
return {}
},
methods: {
confirm() {
this.$refs['form'].validate((valid) => {
if (valid) {
this.$emit(this.data.id?'confirmUpdate':'confirmSave',this.data)
this.$emit('update:visible', false)
} else {
return false;
}
});
},
cancel() {
this.$emit('update:visible', false)
}
}
}
</script>
<style scoped>
.dialog-btn {
cursor: pointer;
flex: 1;
border-radius: 23px;
background: #5778ff;
height: 40px;
font-weight: 500;
font-size: 12px;
color: #fff;
line-height: 40px;
text-align: center;
}
::v-deep .el-dialog {
border-radius: 15px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}
::v-deep .el-dialog__headerbtn {
display: none;
}
::v-deep .el-dialog__body {
padding: 4px 6px;
}
::v-deep .el-dialog__header{
padding: 10px;
}
</style>
+31 -10
View File
@@ -4,19 +4,19 @@
<div style="display: flex;align-items: center;gap: 10px;">
<img alt="" src="@/assets/xiaozhi-logo.png" style="width: 42px;height: 42px;"/>
<img alt="" src="@/assets/xiaozhi-ai.png" style="width: 58px;height: 12px;"/>
<div class="ml-20 menu-btn active" @click="goHome">
<div ref="menu-code_agent" class="ml-20 menu-btn" @click="goToPage('/home')">
<!-- <img alt="" src="@/assets/home/equipment.png" style="width: 12px;height: 10px;"/> -->
<i class="el-icon-cpu"></i>
智能体
</div>
<div class="menu-btn">
<div ref="menu-code_console" class="menu-btn">
<i class="el-icon-s-grid" style="font-size: 10px;color: #979db1;"/>
控制台
</div>
<!-- <div class="menu-btn">
设备管理
<img alt="" src="@/assets/home/close.png" style="width: 6px;height: 6px;"/>
</div> -->
<div ref="menu-code_ota" class="menu-btn" @click="goToPage('/ota')">
<i class="el-icon-lightning"></i>
OTA管理
</div>
</div>
<div style="display: flex;align-items: center;gap: 7px; margin-top: 2px;">
<div class="serach-box">
@@ -33,7 +33,7 @@
<el-dropdown-menu slot="dropdown">
<el-dropdown-item icon="el-icon-user" @click.native="">个人中心</el-dropdown-item>
<el-dropdown-item icon="el-icon-key" @click.native="">修改密码</el-dropdown-item>
<el-dropdown-item icon="el-icon-connection" @click.native="">退出登录</el-dropdown-item>
<el-dropdown-item icon="el-icon-connection" @click.native="handleLogout">退出登录</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</div>
@@ -54,16 +54,37 @@ export default {
userInfo: {
username: '',
mobile: ''
}
},
}
},
watch: {
'$route.meta.menuCode': {
handler(to, from) {
const meta = this.$route.meta;
if(meta && meta.menuCode){
this.$nextTick(() => {
const menu = this.$refs[`menu-code_`+ meta.menuCode]
menu && menu.classList.add('active')
})
}
},
immediate: true,
deep: true
}
},
mounted() {
this.fetchUserInfo()
},
methods: {
goHome() {
handleLogout() {
// 退出登录
this.$store.commit('setToken','')
this.$router.push('/login')
},
goToPage(path) {
// 跳转到首页
this.$router.push('/home')
this.$router.replace(path)
},
// 获取用户信息
fetchUserInfo() {
+19
View File
@@ -28,6 +28,9 @@ const routes = [
{
path: '/home',
name: 'home',
meta: {
menuCode: 'agent',
},
component: function () {
return import('../views/home.vue')
}
@@ -35,6 +38,9 @@ const routes = [
{
path: '/role-config',
name: 'RoleConfig',
meta: {
menuCode: 'agent',
},
component: function () {
return import('../views/roleConfig.vue')
}
@@ -42,9 +48,22 @@ const routes = [
{
path: '/device',
name: 'Device',
meta: {
menuCode: 'agent',
},
component: function () {
return import('../views/device.vue')
}
},
{
path: '/ota',
name: 'Ota',
meta: {
menuCode: 'ota',
},
component: function () {
return import('../views/ota.vue')
}
}
]
+2 -2
View File
@@ -9,8 +9,8 @@ export function checkUserLogin(fn) {
let token = localStorage.getItem(Constant.STORAGE_KEY.TOKEN)
let userType = localStorage.getItem(Constant.STORAGE_KEY.USER_TYPE)
if (isNull(token) || isNull(userType)) {
goToPage('console', true)
return
goToPage('/login', true)
return false
}
if (fn) {
fn()
+37 -5
View File
@@ -26,7 +26,7 @@
<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.alias" size="small" @blur="stopEditRemark(scope.$index)"></el-input>
<el-input :ref="'alias_input_'+scope.$index" v-if="scope.row.isEdit" v-model="scope.row.alias" size="small" class="input-pd0" @blur="stopEditRemark(scope.$index, scope.row)"></el-input>
<span v-else>
{{ scope.row.alias }}
</span>
@@ -35,7 +35,7 @@
</el-table-column>
<el-table-column label="OTA升级" width="100" align="center">
<template slot-scope="scope">
<el-switch v-model="scope.row.autoUpdate" 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" @change="handleToggleEnabled(scope.row.id, $event)"></el-switch>
</template>
</el-table-column>
<el-table-column label="操作" width="80" align="center">
@@ -64,7 +64,6 @@ 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',
@@ -74,6 +73,7 @@ export default {
addDeviceDialogVisible: false,
devices: [],
agentId: this.$route.query.agentId,
oldVal: '',
page: {
pageNo: 1,
pageSize: 10,
@@ -101,10 +101,16 @@ export default {
this.addDeviceDialogVisible = true;
},
startEditRemark(index, row) {
this.oldVal = row.alias;
this.devices[index].isEdit = true;
this.$nextTick(()=>{
this.$refs['alias_input_'+index].focus();
})
},
stopEditRemark(index) {
stopEditRemark(index, row) {
this.devices[index].isEdit = false;
if(this.oldVal === row.alias) return;
this.handleSetAlias(row.id, row.alias);
},
handleUnbind(deviceId) {
// 解绑逻辑
@@ -119,7 +125,7 @@ export default {
})
},
handleDeviceBind(deviceCode) {
// 根据需要处理添加设备后逻辑,比如刷新设备列表等
// 绑定逻辑
console.log('设备验证码:', deviceCode)
Api.device.bindDevice(this.agentId, deviceCode, ({data}) => {
if (data.code === 0) {
@@ -130,6 +136,28 @@ export default {
}
})
},
handleSetAlias(id, alias) {
// 设置备注逻辑
Api.device.setAlias(id, alias, ({data}) => {
if (data.code === 0) {
showSuccess('更新成功')
this.fetchDeviceList()
} else {
showDanger(data.msg)
}
})
},
handleToggleEnabled(id, autoUpdate) {
// 更新OTA升级状态
Api.device.toggleAutoUpdate(id, autoUpdate, ({data}) => {
if (data.code === 0) {
showSuccess('更新成功')
this.fetchDeviceList()
} else {
showDanger(data.msg)
}
})
},
formatter(row, column) {
return formatDate(row.createDate)
}
@@ -196,4 +224,8 @@ export default {
vertical-align: middle;
}
.input-pd0 /deep/ .el-input__inner {
padding: 0 2px;
}
</style>
+3 -3
View File
@@ -99,9 +99,9 @@ export default {
handleAgentAdded(agentName) {
// 添加智能体
Api.agent.addAgent(agentName, ({data}) => {
if (data.status === 200) {
if (data.code === 0) {
showSuccess('添加成功')
this.getAgentList()
this.fetchAgentList();
} else {
showDanger(data.msg)
}
@@ -112,7 +112,7 @@ export default {
Api.agent.delAgent(agetnId, (data) => {
if (data.status === 200) {
showSuccess('删除成功')
this.getAgentList()
this.fetchAgentList();
} else {
showDanger(data.msg)
}
+5 -5
View File
@@ -44,7 +44,7 @@
<div style="cursor: pointer;" @click="goToRegister">新用户注册</div>
</div>
</div>
<div class="login-btn" @click="login">登陆</div>
<div class="login-btn" @keyup.enter="login" @click="login">登陆</div>
<div style="font-size: 14px;color: #979db1;">
登录即同意
<div style="display: inline-block;color: #5778FF;cursor: pointer;">用户协议</div>
@@ -88,7 +88,7 @@ export default {
methods: {
fetchCaptcha() {
if (this.$store.getters.getToken) {
goToPage('/home')
this.$router.push('/home')
} else {
this.captchaUuid = getUUID();
@@ -135,17 +135,17 @@ export default {
// 将令牌存储到 Vuex 中
this.$store.commit('setToken', JSON.stringify(data.data))
goToPage('/home')
// this.$router.push('/home')
})
// 重新获取验证码
// 重新获取验证码(token判断逻辑,存在即跳转home页,否则刷新验证码)
setTimeout(() => {
this.fetchCaptcha();
}, 1000);
},
goToRegister() {
goToPage('/register')
this.$router.push('/register')
}
}
}
+190
View File
@@ -0,0 +1,190 @@
<template>
<div class="welcome">
<!-- 公共头部 -->
<HeaderBar />
<!-- 首页内容 -->
<el-main style="padding: 20px; display: flex; flex-direction: column;">
<!-- 面包屑-->
<div class="breadcrumbs">
<el-breadcrumb separator="/">
<el-breadcrumb-item>控制台</el-breadcrumb-item>
<el-breadcrumb-item>OTA管理</el-breadcrumb-item>
</el-breadcrumb>
</div>
<div class="table-container">
<h3 class="device-list-title">OTA设备列表</h3>
<el-button type="primary" class="add-device-btn" @click="handleAddDeviceOta()">
+ 添加设备
</el-button>
<el-table :data="otaList" style="width: 100%; margin-top: 20px" border>
<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="升级地址" prop="url"></el-table-column>
<el-table-column label="是否启用" width="100" align="center">
<template slot-scope="scope">
<el-switch v-model="scope.row.isEnabled" size="mini" :active-value="1" :inactive-value="0" active-color="#13ce66" inactive-color="#ff4949" @change="handleToggleEnabled(scope.row.id, $event)"></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="handleAddDeviceOta(scope.row)" style="color: #ff4949">
编辑
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<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" />
<!-- 添加设备OTA对话框 -->
<AddDeviceOtaDialog :visible.sync="addDeviceOtaDialogVisible" :data="otaData" @confirmSave="handleSaveDeviceOta" @confirmUpdate="handleUpdateDeviceOta" />
</el-main>
</div>
</template>
<script>
import {getUUID, goToPage, showDanger, showSuccess} from '@/utils'
import Api from '@/apis/api';
import AddDeviceOtaDialog from '@/components/AddDeviceOtaDialog.vue'
import HeaderBar from '@/components/HeaderBar.vue'
import Footer from '@/components/Footer.vue'
export default {
name: 'DeviceOtaPage',
components: { AddDeviceOtaDialog, HeaderBar, Footer },
data() {
return {
addDeviceOtaDialogVisible: false,
otaList: [],
otaData: {},
page: {
pageNo: 1,
pageSize: 10,
total: 0
}
}
},
mounted() {
this.fetchDeviceOtaList();
},
methods: {
// 获取设备列表
fetchDeviceOtaList() {
Api.ota.getOtaList(this.page, ({data}) => {
if (data.code === 0) {
this.page = {...this.page,total:parseInt(data.data.total)}
this.otaList = data.data.records
} else {
showDanger(data.msg)
}
})
},
handleAddDeviceOta(ota) {
if (ota) {
this.otaData = ota
}
// 添加设备逻辑
this.addDeviceOtaDialogVisible = true;
},
handleSaveDeviceOta(ota) {
console.log('添加设备', ota);
Api.ota.saveOta(ota, ({data}) => {
if (data.code === 0) {
showSuccess('添加成功')
this.fetchDeviceOtaList()
} else {
showDanger(data.msg)
}
this.otaData = {}
})
},
handleUpdateDeviceOta(ota) {
// 解绑逻辑
console.log('修改设备', ota);
Api.ota.updateOta(ota, ({data}) => {
if (data.code === 0) {
showSuccess('修改成功')
this.fetchDeviceOtaList()
} else {
showDanger(data.msg)
}
this.otaData = {}
})
},
handleToggleEnabled(id, isEnabled) {
// 启用禁用逻辑
Api.ota.toggleEnabled({id, isEnabled}, ({data}) => {
if (data.code === 0) {
showSuccess('更新成功')
this.fetchDeviceOtaList()
} else {
showDanger(data.msg)
}
})
}
}
};
</script>
<style scoped>
.breadcrumbs{
padding: 10px 0 0 5px;
}
.welcome {
min-width: 900px;
min-height: 506px;
height: 100vh;
display: flex;
flex-direction: column;
background-image: url("@/assets/home/background.png");
background-size: cover;
background-position: center;
-webkit-background-size: cover;
-o-background-size: cover;
}
.table-container {
background: #f9fafc;
padding: 20px;
border-radius: 20px;
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
margin-top: 15px;
}
.add-device-btn {
float: right;
background: #409eff;
border: none;
border-radius: 10px;
width: 105px;
height: 32px;
display: flex;
align-items: center;
justify-content: center;
font-size: 14px;
gap: 8px;
margin-bottom: 15px;
&:hover {
background: #3a8ee6;
}
}
.device-list-title {
float: left;
font-size: 18px;
font-weight: 700;
margin: 5px;
color: #2c3e50;
}
.el-icon-edit {
color: #409eff;
cursor: pointer;
font-size: 14px;
vertical-align: middle;
}
</style>