mirror of
https://github.com/xinnan-tech/xiaozhi-esp32-server.git
synced 2026-07-29 18:23:59 +08:00
update:格式化代码
This commit is contained in:
@@ -1,13 +1,12 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
presets: [
|
presets: [
|
||||||
['@vue/cli-plugin-babel/preset', {
|
['@vue/cli-plugin-babel/preset', {
|
||||||
useBuiltIns: 'usage',
|
useBuiltIns: 'usage',
|
||||||
corejs: 3
|
corejs: 3
|
||||||
}]
|
}]
|
||||||
],
|
],
|
||||||
plugins: [
|
plugins: [
|
||||||
'@babel/plugin-syntax-dynamic-import', // 确保支持动态导入 (Lazy Loading)
|
'@babel/plugin-syntax-dynamic-import', // 确保支持动态导入 (Lazy Loading)
|
||||||
'@babel/plugin-transform-runtime'
|
'@babel/plugin-transform-runtime'
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
<template>
|
<template>
|
||||||
<div id="app">
|
<div id="app">
|
||||||
<router-view/>
|
<router-view />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
|
|
||||||
#app {
|
#app {
|
||||||
font-family: Avenir, Helvetica, Arial, sans-serif;
|
font-family: Avenir, Helvetica, Arial, sans-serif;
|
||||||
-webkit-font-smoothing: antialiased;
|
-webkit-font-smoothing: antialiased;
|
||||||
@@ -29,7 +28,7 @@ nav {
|
|||||||
|
|
||||||
.copyright {
|
.copyright {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
color:rgb(0, 0, 0);
|
color: rgb(0, 0, 0);
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
margin-top: auto;
|
margin-top: auto;
|
||||||
@@ -40,10 +39,10 @@ nav {
|
|||||||
transform: translateX(-50%);
|
transform: translateX(-50%);
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-message {
|
.el-message {
|
||||||
top: 45px !important;
|
top: 45px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
<script>
|
<script>
|
||||||
</script>
|
</script>
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import {goToPage, showDanger, showWarning, isNotNull} from '../utils/index'
|
|
||||||
import Constant from '../utils/constant'
|
|
||||||
import Fly from 'flyio/dist/npm/fly';
|
import Fly from 'flyio/dist/npm/fly';
|
||||||
import store from '../store/index'
|
import store from '../store/index';
|
||||||
|
import Constant from '../utils/constant';
|
||||||
|
import { goToPage, isNotNull, showDanger, showWarning } from '../utils/index';
|
||||||
|
|
||||||
const fly = new Fly()
|
const fly = new Fly()
|
||||||
// 设置超时
|
// 设置超时
|
||||||
@@ -22,11 +22,11 @@ function sendRequest() {
|
|||||||
_failCallback: null,
|
_failCallback: null,
|
||||||
_method: 'GET',
|
_method: 'GET',
|
||||||
_data: {},
|
_data: {},
|
||||||
_header: {'content-type': 'application/json; charset=utf-8'},
|
_header: { 'content-type': 'application/json; charset=utf-8' },
|
||||||
_url: '',
|
_url: '',
|
||||||
_responseType: undefined, // 新增响应类型字段
|
_responseType: undefined, // 新增响应类型字段
|
||||||
'send'() {
|
'send'() {
|
||||||
if(isNotNull(store.getters.getToken)){
|
if (isNotNull(store.getters.getToken)) {
|
||||||
this._header.Authorization = 'Bearer ' + (JSON.parse(store.getters.getToken)).token
|
this._header.Authorization = 'Bearer ' + (JSON.parse(store.getters.getToken)).token
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -107,7 +107,7 @@ function httpHandlerError(info, callBack) {
|
|||||||
if (info.status === 200) {
|
if (info.status === 200) {
|
||||||
if (info.data.code === 'success' || info.data.code === 0 || info.data.code === undefined) {
|
if (info.data.code === 'success' || info.data.code === 0 || info.data.code === undefined) {
|
||||||
return networkError
|
return networkError
|
||||||
}else if (info.data.code === 401) {
|
} else if (info.data.code === 401) {
|
||||||
console.log('触发 401,清除 Token 并跳转登录页');
|
console.log('触发 401,清除 Token 并跳转登录页');
|
||||||
store.commit('clearAuth');
|
store.commit('clearAuth');
|
||||||
goToPage(Constant.PAGE.LOGIN, true);
|
goToPage(Constant.PAGE.LOGIN, true);
|
||||||
|
|||||||
@@ -1,30 +1,30 @@
|
|||||||
import RequestService from '../httpRequest'
|
import { getServiceUrl } from '../api';
|
||||||
import {getServiceUrl} from '../api'
|
import RequestService from '../httpRequest';
|
||||||
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
// 用户列表
|
// 用户列表
|
||||||
getUserList(params, callback) {
|
getUserList(params, callback) {
|
||||||
const queryParams = new URLSearchParams({
|
const queryParams = new URLSearchParams({
|
||||||
page: params.page,
|
page: params.page,
|
||||||
limit: params.limit,
|
limit: params.limit,
|
||||||
mobile: params.mobile
|
mobile: params.mobile
|
||||||
}).toString();
|
}).toString();
|
||||||
|
|
||||||
RequestService.sendRequest()
|
RequestService.sendRequest()
|
||||||
.url(`${getServiceUrl()}/api/v1/admin/users?${queryParams}`)
|
.url(`${getServiceUrl()}/api/v1/admin/users?${queryParams}`)
|
||||||
.method('GET')
|
.method('GET')
|
||||||
.success((res) => {
|
.success((res) => {
|
||||||
RequestService.clearRequestTime()
|
RequestService.clearRequestTime()
|
||||||
callback(res)
|
callback(res)
|
||||||
|
})
|
||||||
|
.fail((err) => {
|
||||||
|
console.error('请求失败:', err)
|
||||||
|
RequestService.reAjaxFun(() => {
|
||||||
|
this.getUserList(callback)
|
||||||
})
|
})
|
||||||
.fail((err) => {
|
}).send()
|
||||||
console.error('请求失败:', err)
|
},
|
||||||
RequestService.reAjaxFun(() => {
|
|
||||||
this.getUserList(callback)
|
|
||||||
})
|
|
||||||
}).send()
|
|
||||||
},
|
|
||||||
// 删除用户
|
// 删除用户
|
||||||
deleteUser(id, callback) {
|
deleteUser(id, callback) {
|
||||||
RequestService.sendRequest()
|
RequestService.sendRequest()
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import RequestService from '../httpRequest'
|
import { getServiceUrl } from '../api';
|
||||||
import {getServiceUrl} from '../api'
|
import RequestService from '../httpRequest';
|
||||||
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
@@ -23,7 +23,7 @@ export default {
|
|||||||
RequestService.sendRequest()
|
RequestService.sendRequest()
|
||||||
.url(`${getServiceUrl()}/api/v1/agent`)
|
.url(`${getServiceUrl()}/api/v1/agent`)
|
||||||
.method('POST')
|
.method('POST')
|
||||||
.data({agentName: agentName})
|
.data({ agentName: agentName })
|
||||||
.success((res) => {
|
.success((res) => {
|
||||||
RequestService.clearRequestTime();
|
RequestService.clearRequestTime();
|
||||||
callback(res);
|
callback(res);
|
||||||
|
|||||||
@@ -1,38 +1,38 @@
|
|||||||
import RequestService from '../httpRequest'
|
import { getServiceUrl } from '../api';
|
||||||
import {getServiceUrl} from '../api'
|
import RequestService from '../httpRequest';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
// 已绑设备
|
// 已绑设备
|
||||||
getAgentBindDevices(agentId, callback) {
|
getAgentBindDevices(agentId, callback) {
|
||||||
RequestService.sendRequest()
|
RequestService.sendRequest()
|
||||||
.url(`${getServiceUrl()}/api/v1/device/bind/${agentId}`)
|
.url(`${getServiceUrl()}/api/v1/device/bind/${agentId}`)
|
||||||
.method('GET')
|
.method('GET')
|
||||||
.success((res) => {
|
.success((res) => {
|
||||||
RequestService.clearRequestTime();
|
RequestService.clearRequestTime();
|
||||||
callback(res);
|
callback(res);
|
||||||
})
|
})
|
||||||
.fail((err) => {
|
.fail((err) => {
|
||||||
console.error('获取设备列表失败:', err);
|
console.error('获取设备列表失败:', err);
|
||||||
RequestService.reAjaxFun(() => {
|
RequestService.reAjaxFun(() => {
|
||||||
this.getAgentBindDevices(agentId, callback);
|
this.getAgentBindDevices(agentId, callback);
|
||||||
});
|
});
|
||||||
}).send();
|
}).send();
|
||||||
},
|
},
|
||||||
// 解绑设备
|
// 解绑设备
|
||||||
unbindDevice(device_id, callback) {
|
unbindDevice(device_id, callback) {
|
||||||
RequestService.sendRequest()
|
RequestService.sendRequest()
|
||||||
.url(`${getServiceUrl()}/api/v1/device/unbind`)
|
.url(`${getServiceUrl()}/api/v1/device/unbind`)
|
||||||
.method('POST')
|
.method('POST')
|
||||||
.data({ deviceId: device_id })
|
.data({ deviceId: device_id })
|
||||||
.success((res) => {
|
.success((res) => {
|
||||||
RequestService.clearRequestTime();
|
RequestService.clearRequestTime();
|
||||||
callback(res);
|
callback(res);
|
||||||
})
|
})
|
||||||
.fail((err) => {
|
.fail((err) => {
|
||||||
console.error('解绑设备失败:', err);
|
console.error('解绑设备失败:', err);
|
||||||
RequestService.reAjaxFun(() => {
|
RequestService.reAjaxFun(() => {
|
||||||
this.unbindDevice(device_id, callback);
|
this.unbindDevice(device_id, callback);
|
||||||
});
|
});
|
||||||
}).send();
|
}).send();
|
||||||
},
|
},
|
||||||
// 绑定设备
|
// 绑定设备
|
||||||
|
|||||||
@@ -1,96 +1,96 @@
|
|||||||
import RequestService from '../httpRequest'
|
import { getServiceUrl } from '../api';
|
||||||
import {getServiceUrl} from '../api'
|
import RequestService from '../httpRequest';
|
||||||
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
// 获取模型配置列表
|
// 获取模型配置列表
|
||||||
getModelList(params, callback) {
|
getModelList(params, callback) {
|
||||||
const queryParams = new URLSearchParams({
|
const queryParams = new URLSearchParams({
|
||||||
modelType: params.modelType,
|
modelType: params.modelType,
|
||||||
modelName: params.modelName || '',
|
modelName: params.modelName || '',
|
||||||
page: params.page || 0,
|
page: params.page || 0,
|
||||||
limit: params.limit || 10
|
limit: params.limit || 10
|
||||||
}).toString();
|
}).toString();
|
||||||
|
|
||||||
RequestService.sendRequest()
|
RequestService.sendRequest()
|
||||||
.url(`${getServiceUrl()}/api/v1/models/models/list?${queryParams}`)
|
.url(`${getServiceUrl()}/api/v1/models/models/list?${queryParams}`)
|
||||||
.method('GET')
|
.method('GET')
|
||||||
.success((res) => {
|
.success((res) => {
|
||||||
RequestService.clearRequestTime()
|
RequestService.clearRequestTime()
|
||||||
callback(res)
|
callback(res)
|
||||||
|
})
|
||||||
|
.fail((err) => {
|
||||||
|
console.error('获取模型列表失败:', err)
|
||||||
|
RequestService.reAjaxFun(() => {
|
||||||
|
this.getModelList(params, callback)
|
||||||
})
|
})
|
||||||
.fail((err) => {
|
}).send()
|
||||||
console.error('获取模型列表失败:', err)
|
},
|
||||||
RequestService.reAjaxFun(() => {
|
// 获取模型供应器列表
|
||||||
this.getModelList(params, callback)
|
getModelProviders(modelType, callback) {
|
||||||
})
|
RequestService.sendRequest()
|
||||||
}).send()
|
.url(`${getServiceUrl()}/api/v1/models/${modelType}/provideTypes`)
|
||||||
},
|
.method('GET')
|
||||||
// 获取模型供应器列表
|
.success((res) => {
|
||||||
getModelProviders(modelType, callback) {
|
RequestService.clearRequestTime()
|
||||||
RequestService.sendRequest()
|
callback(res.data?.data || [])
|
||||||
.url(`${getServiceUrl()}/api/v1/models/${modelType}/provideTypes`)
|
})
|
||||||
.method('GET')
|
.fail((err) => {
|
||||||
.success((res) => {
|
console.error('获取供应器列表失败:', err)
|
||||||
RequestService.clearRequestTime()
|
this.$message.error('获取供应器列表失败')
|
||||||
callback(res.data?.data || [])
|
RequestService.reAjaxFun(() => {
|
||||||
|
this.getModelProviders(modelType, callback)
|
||||||
})
|
})
|
||||||
.fail((err) => {
|
}).send()
|
||||||
console.error('获取供应器列表失败:', err)
|
},
|
||||||
this.$message.error('获取供应器列表失败')
|
|
||||||
RequestService.reAjaxFun(() => {
|
|
||||||
this.getModelProviders(modelType, callback)
|
|
||||||
})
|
|
||||||
}).send()
|
|
||||||
},
|
|
||||||
|
|
||||||
// 新增模型配置
|
// 新增模型配置
|
||||||
addModel(params, callback) {
|
addModel(params, callback) {
|
||||||
const { modelType, provideCode, formData } = params;
|
const { modelType, provideCode, formData } = params;
|
||||||
const postData = {
|
const postData = {
|
||||||
modelCode: formData.modelCode,
|
modelCode: formData.modelCode,
|
||||||
modelName: formData.modelName,
|
modelName: formData.modelName,
|
||||||
isDefault: formData.isDefault ? 1 : 0,
|
isDefault: formData.isDefault ? 1 : 0,
|
||||||
isEnabled: formData.isEnabled ? 1 : 0,
|
isEnabled: formData.isEnabled ? 1 : 0,
|
||||||
configJson: JSON.stringify(formData.configJson),
|
configJson: JSON.stringify(formData.configJson),
|
||||||
docLink: formData.docLink,
|
docLink: formData.docLink,
|
||||||
remark: formData.remark,
|
remark: formData.remark,
|
||||||
sort: formData.sort || 0
|
sort: formData.sort || 0
|
||||||
};
|
};
|
||||||
|
|
||||||
RequestService.sendRequest()
|
RequestService.sendRequest()
|
||||||
.url(`${getServiceUrl()}/api/v1/models/models/${modelType}/${provideCode}`)
|
.url(`${getServiceUrl()}/api/v1/models/models/${modelType}/${provideCode}`)
|
||||||
.method('POST')
|
.method('POST')
|
||||||
.data(postData)
|
.data(postData)
|
||||||
.success((res) => {
|
.success((res) => {
|
||||||
RequestService.clearRequestTime()
|
RequestService.clearRequestTime()
|
||||||
callback(res)
|
callback(res)
|
||||||
|
})
|
||||||
|
.fail((err) => {
|
||||||
|
console.error('新增模型失败:', err)
|
||||||
|
this.$message.error(err.msg || '新增模型失败')
|
||||||
|
RequestService.reAjaxFun(() => {
|
||||||
|
this.addModel(params, callback)
|
||||||
})
|
})
|
||||||
.fail((err) => {
|
}).send()
|
||||||
console.error('新增模型失败:', err)
|
},
|
||||||
this.$message.error(err.msg || '新增模型失败')
|
// 删除模型配置
|
||||||
RequestService.reAjaxFun(() => {
|
deleteModel(modelType, provideCode, id, callback) {
|
||||||
this.addModel(params, callback)
|
RequestService.sendRequest()
|
||||||
})
|
.url(`${getServiceUrl()}/api/v1/models/models/${modelType}/${provideCode}/${id}`)
|
||||||
}).send()
|
.method('DELETE')
|
||||||
},
|
.success((res) => {
|
||||||
// 删除模型配置
|
RequestService.clearRequestTime()
|
||||||
deleteModel(modelType, provideCode, id, callback) {
|
callback(res)
|
||||||
RequestService.sendRequest()
|
})
|
||||||
.url(`${getServiceUrl()}/api/v1/models/models/${modelType}/${provideCode}/${id}`)
|
.fail((err) => {
|
||||||
.method('DELETE')
|
console.error('删除模型失败:', err)
|
||||||
.success((res) => {
|
this.$message.error(err.msg || '删除模型失败')
|
||||||
RequestService.clearRequestTime()
|
RequestService.reAjaxFun(() => {
|
||||||
callback(res)
|
this.deleteModel(modelType, provideCode, id, callback)
|
||||||
})
|
})
|
||||||
.fail((err) => {
|
}).send()
|
||||||
console.error('删除模型失败:', err)
|
},
|
||||||
this.$message.error(err.msg || '删除模型失败')
|
|
||||||
RequestService.reAjaxFun(() => {
|
|
||||||
this.deleteModel(modelType, provideCode, id, callback)
|
|
||||||
})
|
|
||||||
}).send()
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
|
import { getServiceUrl } from '../api'
|
||||||
import RequestService from '../httpRequest'
|
import RequestService from '../httpRequest'
|
||||||
import {getServiceUrl} from '../api'
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
/**
|
/**
|
||||||
@@ -11,7 +11,7 @@ export default {
|
|||||||
RequestService.sendRequest()
|
RequestService.sendRequest()
|
||||||
.url(`${getServiceUrl()}/api/v1/ota/activation`)
|
.url(`${getServiceUrl()}/api/v1/ota/activation`)
|
||||||
.method('GET')
|
.method('GET')
|
||||||
.query({code})
|
.query({ code })
|
||||||
.success((res) => {
|
.success((res) => {
|
||||||
RequestService.clearRequestTime()
|
RequestService.clearRequestTime()
|
||||||
callback(res)
|
callback(res)
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
|
import { getServiceUrl } from '../api'
|
||||||
import RequestService from '../httpRequest'
|
import RequestService from '../httpRequest'
|
||||||
import {getServiceUrl} from '../api'
|
|
||||||
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import Vue from 'vue'
|
|
||||||
import App from './App.vue'
|
|
||||||
import router from './router'
|
|
||||||
import store from './store'
|
|
||||||
import 'normalize.css/normalize.css' // A modern alternative to CSS resets
|
|
||||||
import ElementUI from 'element-ui';
|
import ElementUI from 'element-ui';
|
||||||
import 'element-ui/lib/theme-chalk/index.css';
|
import 'element-ui/lib/theme-chalk/index.css';
|
||||||
import './styles/global.scss'
|
import 'normalize.css/normalize.css'; // A modern alternative to CSS resets
|
||||||
|
import Vue from 'vue';
|
||||||
|
import App from './App.vue';
|
||||||
|
import router from './router';
|
||||||
|
import store from './store';
|
||||||
|
import './styles/global.scss';
|
||||||
|
|
||||||
Vue.use(ElementUI);
|
Vue.use(ElementUI);
|
||||||
|
|
||||||
|
|||||||
@@ -56,11 +56,11 @@ const routes = [
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/model-config',
|
path: '/model-config',
|
||||||
name: 'ModelConfig',
|
name: 'ModelConfig',
|
||||||
component: function () {
|
component: function () {
|
||||||
return import('../views/ModelConfig.vue')
|
return import('../views/ModelConfig.vue')
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/test',
|
path: '/test',
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import Vue from 'vue'
|
import { goToPage } from "@/utils";
|
||||||
import Vuex from 'vuex'
|
import Vue from 'vue';
|
||||||
import Constant from '../utils/constant'
|
import Vuex from 'vuex';
|
||||||
import {goToPage} from "@/utils";
|
import Constant from '../utils/constant';
|
||||||
|
|
||||||
Vue.use(Vuex)
|
Vue.use(Vuex)
|
||||||
|
|
||||||
@@ -52,7 +52,7 @@ export default new Vuex.Store({
|
|||||||
logout({ commit }) {
|
logout({ commit }) {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
commit('clearAuth')
|
commit('clearAuth')
|
||||||
goToPage(Constant.PAGE.LOGIN,true);
|
goToPage(Constant.PAGE.LOGIN, true);
|
||||||
window.location.reload(); // 彻底重置状态
|
window.location.reload(); // 彻底重置状态
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
|
import { Message } from 'element-ui'
|
||||||
import router from '../router'
|
import router from '../router'
|
||||||
import Constant from '../utils/constant'
|
import Constant from '../utils/constant'
|
||||||
import { Message } from 'element-ui'
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 判断用户是否登录
|
* 判断用户是否登录
|
||||||
|
|||||||
@@ -2,26 +2,26 @@
|
|||||||
<div class="welcome">
|
<div class="welcome">
|
||||||
<HeaderBar />
|
<HeaderBar />
|
||||||
|
|
||||||
<div class="operation-bar">
|
<div class="operation-bar">
|
||||||
<h2 class="page-title">模型配置</h2>
|
<h2 class="page-title">模型配置</h2>
|
||||||
<div class="right-operations">
|
<div class="right-operations">
|
||||||
<el-button plain size="small" @click="handleImport" style="background: #7b9de5; color: white;">
|
<el-button plain size="small" @click="handleImport" style="background: #7b9de5; color: white;">
|
||||||
<img loading="lazy" alt="" src="@/assets/model/inner_conf.png">
|
<img loading="lazy" alt="" src="@/assets/model/inner_conf.png">
|
||||||
导入配置
|
导入配置
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button plain size="small" @click="handleExport" style="background: #71c9d1; color: white;">
|
<el-button plain size="small" @click="handleExport" style="background: #71c9d1; color: white;">
|
||||||
<img loading="lazy" alt="" src="@/assets/model/output_conf.png">
|
<img loading="lazy" alt="" src="@/assets/model/output_conf.png">
|
||||||
导出配置
|
导出配置
|
||||||
</el-button>
|
</el-button>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- 主体内容 -->
|
<!-- 主体内容 -->
|
||||||
<div class="main-wrapper">
|
<div class="main-wrapper">
|
||||||
<div class="content-panel">
|
<div class="content-panel">
|
||||||
<!-- 左侧导航 -->
|
<!-- 左侧导航 -->
|
||||||
<el-menu :default-active="activeTab" class="nav-panel" @select="handleMenuSelect"
|
<el-menu :default-active="activeTab" class="nav-panel" @select="handleMenuSelect"
|
||||||
style="background-size: cover; background-position: center;">
|
style="background-size: cover; background-position: center;">
|
||||||
<el-menu-item index="vad">
|
<el-menu-item index="vad">
|
||||||
<span class="menu-text">语言活动检测</span>
|
<span class="menu-text">语言活动检测</span>
|
||||||
</el-menu-item>
|
</el-menu-item>
|
||||||
@@ -46,14 +46,14 @@
|
|||||||
<div class="content-area">
|
<div class="content-area">
|
||||||
<div class="title-bar">
|
<div class="title-bar">
|
||||||
<div class="title-wrapper">
|
<div class="title-wrapper">
|
||||||
<h2 class="model-title">{{ modelTypeText }}</h2>
|
<h2 class="model-title">{{ modelTypeText }}</h2>
|
||||||
<el-button type="primary" size="small" @click="addModel" class="add-btn">
|
<el-button type="primary" size="small" @click="addModel" class="add-btn">
|
||||||
添加
|
添加
|
||||||
</el-button>
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
<div class="action-group">
|
<div class="action-group">
|
||||||
<div class="search-group">
|
<div class="search-group">
|
||||||
<el-input placeholder="请输入模型名称查询" v-model="search" size="small" class="search-input" clearable/>
|
<el-input placeholder="请输入模型名称查询" v-model="search" size="small" class="search-input" clearable />
|
||||||
<el-button type="primary" size="small" class="search-btn" @click="handleSearch">
|
<el-button type="primary" size="small" class="search-btn" @click="handleSearch">
|
||||||
查询
|
查询
|
||||||
</el-button>
|
</el-button>
|
||||||
@@ -61,7 +61,9 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<el-table ref="modelTable" style="width: 100%" :header-cell-style="{background: 'transparent'}" :data="modelList" class="data-table" header-row-class-name="table-header" :header-cell-class-name="headerCellClassName" @selection-change="handleSelectionChange">
|
<el-table ref="modelTable" style="width: 100%" :header-cell-style="{ background: 'transparent' }"
|
||||||
|
:data="modelList" class="data-table" header-row-class-name="table-header"
|
||||||
|
:header-cell-class-name="headerCellClassName" @selection-change="handleSelectionChange">
|
||||||
<el-table-column type="selection" width="55" align="center"></el-table-column>
|
<el-table-column type="selection" width="55" align="center"></el-table-column>
|
||||||
<el-table-column label="模型名称" prop="modelName" align="center"></el-table-column>
|
<el-table-column label="模型名称" prop="modelName" align="center"></el-table-column>
|
||||||
<el-table-column label="模型编码" prop="modelCode" align="center"></el-table-column>
|
<el-table-column label="模型编码" prop="modelCode" align="center"></el-table-column>
|
||||||
@@ -72,9 +74,8 @@
|
|||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="是否启用" align="center">
|
<el-table-column label="是否启用" align="center">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<el-switch v-model="scope.row.isEnabled" class="custom-switch"
|
<el-switch v-model="scope.row.isEnabled" class="custom-switch" :active-value="1" :inactive-value="0"
|
||||||
:active-value="1" :inactive-value="0"
|
:active-color="null" :inactive-color="null" />
|
||||||
:active-color="null" :inactive-color="null"/>
|
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column v-if="activeTab === 'tts'" label="音色管理" align="center">
|
<el-table-column v-if="activeTab === 'tts'" label="音色管理" align="center">
|
||||||
@@ -98,7 +99,9 @@
|
|||||||
|
|
||||||
<div class="table-footer">
|
<div class="table-footer">
|
||||||
<div class="batch-actions">
|
<div class="batch-actions">
|
||||||
<el-button size="mini" @click="selectAll" style="width: 75px; background: #606ff3">{{ isAllSelected ? '取消全选' : '全选' }}</el-button>
|
<el-button size="mini" @click="selectAll" style="width: 75px; background: #606ff3">{{ isAllSelected ?
|
||||||
|
'取消全选' : '全选'
|
||||||
|
}}</el-button>
|
||||||
<el-button size="mini" type="danger" icon="el-icon-delete" @click="batchDelete">
|
<el-button size="mini" type="danger" icon="el-icon-delete" @click="batchDelete">
|
||||||
删除
|
删除
|
||||||
</el-button>
|
</el-button>
|
||||||
@@ -107,7 +110,8 @@
|
|||||||
<button class="pagination-btn" :disabled="currentPage === 1" @click="goFirst">首页</button>
|
<button class="pagination-btn" :disabled="currentPage === 1" @click="goFirst">首页</button>
|
||||||
<button class="pagination-btn" :disabled="currentPage === 1" @click="goPrev">上一页</button>
|
<button class="pagination-btn" :disabled="currentPage === 1" @click="goPrev">上一页</button>
|
||||||
|
|
||||||
<button v-for="page in visiblePages" :key="page" class="pagination-btn" :class="{ active: page === currentPage }" @click="goToPage(page)">
|
<button v-for="page in visiblePages" :key="page" class="pagination-btn"
|
||||||
|
:class="{ active: page === currentPage }" @click="goToPage(page)">
|
||||||
{{ page }}
|
{{ page }}
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
@@ -118,23 +122,24 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ModelEditDialog :modelType="activeTab" :visible.sync="editDialogVisible" :modelData="editModelData" @save="handleModelSave"/>
|
<ModelEditDialog :modelType="activeTab" :visible.sync="editDialogVisible" :modelData="editModelData"
|
||||||
|
@save="handleModelSave" />
|
||||||
<TtsModel :visible.sync="ttsDialogVisible" />
|
<TtsModel :visible.sync="ttsDialogVisible" />
|
||||||
<AddModelDialog :modelType="activeTab" :visible.sync="addDialogVisible" @confirm="handleAddConfirm"/>
|
<AddModelDialog :modelType="activeTab" :visible.sync="addDialogVisible" @confirm="handleAddConfirm" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="copyright">
|
<div class="copyright">
|
||||||
©2025 xiaozhi-esp32-server
|
©2025 xiaozhi-esp32-server
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import ModelApi from "@/apis/module/model";
|
||||||
|
import AddModelDialog from "@/components/AddModelDialog.vue";
|
||||||
import HeaderBar from "@/components/HeaderBar.vue";
|
import HeaderBar from "@/components/HeaderBar.vue";
|
||||||
import ModelEditDialog from "@/components/ModelEditDialog.vue";
|
import ModelEditDialog from "@/components/ModelEditDialog.vue";
|
||||||
import TtsModel from "@/components/TtsModel.vue";
|
import TtsModel from "@/components/TtsModel.vue";
|
||||||
import AddModelDialog from "@/components/AddModelDialog.vue";
|
|
||||||
import ModelApi from "@/apis/module/model";
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: { HeaderBar, ModelEditDialog, TtsModel, AddModelDialog },
|
components: { HeaderBar, ModelEditDialog, TtsModel, AddModelDialog },
|
||||||
@@ -227,7 +232,7 @@ export default {
|
|||||||
this.activeTab,
|
this.activeTab,
|
||||||
model.configJson?.provider || '',
|
model.configJson?.provider || '',
|
||||||
model.id,
|
model.id,
|
||||||
({data}) => resolve(data.code === 0)
|
({ data }) => resolve(data.code === 0)
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
@@ -262,7 +267,7 @@ export default {
|
|||||||
this.activeTab,
|
this.activeTab,
|
||||||
model.configJson?.provider || '', // 从configJson获取provider
|
model.configJson?.provider || '', // 从configJson获取provider
|
||||||
model.id,
|
model.id,
|
||||||
({data}) => {
|
({ data }) => {
|
||||||
if (data.code === 0) {
|
if (data.code === 0) {
|
||||||
this.$message.success('删除成功')
|
this.$message.success('删除成功')
|
||||||
this.loadData()
|
this.loadData()
|
||||||
@@ -316,7 +321,7 @@ export default {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
ModelApi.addModel(params, ({data}) => {
|
ModelApi.addModel(params, ({ data }) => {
|
||||||
if (data.code === 0) {
|
if (data.code === 0) {
|
||||||
this.$message.success('新增成功');
|
this.$message.success('新增成功');
|
||||||
this.loadData();
|
this.loadData();
|
||||||
@@ -328,8 +333,8 @@ export default {
|
|||||||
|
|
||||||
// 分页器
|
// 分页器
|
||||||
goFirst() {
|
goFirst() {
|
||||||
this.currentPage = 1;
|
this.currentPage = 1;
|
||||||
this.loadData();
|
this.loadData();
|
||||||
},
|
},
|
||||||
goPrev() {
|
goPrev() {
|
||||||
if (this.currentPage > 1) {
|
if (this.currentPage > 1) {
|
||||||
@@ -357,7 +362,7 @@ export default {
|
|||||||
limit: this.pageSize
|
limit: this.pageSize
|
||||||
};
|
};
|
||||||
|
|
||||||
ModelApi.getModelList(params, ({data}) => {
|
ModelApi.getModelList(params, ({ data }) => {
|
||||||
if (data.code === 0) {
|
if (data.code === 0) {
|
||||||
this.modelList = data.data.list;
|
this.modelList = data.data.list;
|
||||||
this.total = data.data.total;
|
this.total = data.data.total;
|
||||||
@@ -371,7 +376,7 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
::v-deep .el-table tr{
|
::v-deep .el-table tr {
|
||||||
background: transparent;
|
background: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -394,7 +399,7 @@ export default {
|
|||||||
min-height: 600px;
|
min-height: 600px;
|
||||||
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
|
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
|
||||||
position: relative;
|
position: relative;
|
||||||
background: rgba(237,242,255,0.5);
|
background: rgba(237, 242, 255, 0.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
.operation-bar {
|
.operation-bar {
|
||||||
@@ -430,12 +435,10 @@ export default {
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
border-right: 1px solid #ebeef5;
|
border-right: 1px solid #ebeef5;
|
||||||
background:
|
background:
|
||||||
linear-gradient(
|
linear-gradient(120deg,
|
||||||
120deg,
|
|
||||||
rgba(107, 140, 255, 0.3) 0%,
|
rgba(107, 140, 255, 0.3) 0%,
|
||||||
rgba(169, 102, 255, 0.3) 25%,
|
rgba(169, 102, 255, 0.3) 25%,
|
||||||
transparent 60%
|
transparent 60%),
|
||||||
),
|
|
||||||
url("../assets/model/model.png") no-repeat center / cover;
|
url("../assets/model/model.png") no-repeat center / cover;
|
||||||
padding: 16px 0;
|
padding: 16px 0;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
@@ -620,7 +623,8 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
::v-deep .el-table .custom-selection-header .cell .el-checkbox__inner {
|
::v-deep .el-table .custom-selection-header .cell .el-checkbox__inner {
|
||||||
display: none !important; /* 使表头复选框不可见 */
|
display: none !important;
|
||||||
|
/* 使表头复选框不可见 */
|
||||||
}
|
}
|
||||||
|
|
||||||
::v-deep .el-table .custom-selection-header .cell::before {
|
::v-deep .el-table .custom-selection-header .cell::before {
|
||||||
@@ -646,6 +650,7 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
::v-deep .data-table {
|
::v-deep .data-table {
|
||||||
|
|
||||||
&.el-table::before,
|
&.el-table::before,
|
||||||
&.el-table::after,
|
&.el-table::after,
|
||||||
&.el-table__inner-wrapper::before {
|
&.el-table__inner-wrapper::before {
|
||||||
@@ -654,14 +659,14 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
::v-deep .data-table .el-table__header-wrapper {
|
::v-deep .data-table .el-table__header-wrapper {
|
||||||
border-bottom: 1px solid rgb(224,227,237);
|
border-bottom: 1px solid rgb(224, 227, 237);
|
||||||
}
|
}
|
||||||
|
|
||||||
::v-deep .data-table .el-table__body td {
|
::v-deep .data-table .el-table__body td {
|
||||||
border-bottom: 1px solid rgb(224,227,237) !important;
|
border-bottom: 1px solid rgb(224, 227, 237) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-button img{
|
.el-button img {
|
||||||
height: 1em;
|
height: 1em;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
padding-right: 2px;
|
padding-right: 2px;
|
||||||
@@ -689,7 +694,8 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.voice-management-btn:hover {
|
.voice-management-btn:hover {
|
||||||
background: #8aa2e0; /* 悬停时颜色加深 */
|
background: #8aa2e0;
|
||||||
|
/* 悬停时颜色加深 */
|
||||||
transform: scale(1.05);
|
transform: scale(1.05);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -701,7 +707,8 @@ export default {
|
|||||||
padding-right: 15px !important;
|
padding-right: 15px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.edit-btn, .delete-btn {
|
.edit-btn,
|
||||||
|
.delete-btn {
|
||||||
margin: 0 8px;
|
margin: 0 8px;
|
||||||
color: #7079aa !important;
|
color: #7079aa !important;
|
||||||
}
|
}
|
||||||
@@ -777,6 +784,4 @@ export default {
|
|||||||
margin-left: 10px;
|
margin-left: 10px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,8 @@
|
|||||||
<div class="operation-bar">
|
<div class="operation-bar">
|
||||||
<h2 class="page-title">用户管理</h2>
|
<h2 class="page-title">用户管理</h2>
|
||||||
<div class="right-operations">
|
<div class="right-operations">
|
||||||
<el-input placeholder="请输入手机号码查询" v-model="searchPhone" class="search-input" @keyup.enter.native="handleSearch"/>
|
<el-input placeholder="请输入手机号码查询" v-model="searchPhone" class="search-input"
|
||||||
|
@keyup.enter.native="handleSearch" />
|
||||||
<el-button class="btn-search" @click="handleSearch">搜索</el-button>
|
<el-button class="btn-search" @click="handleSearch">搜索</el-button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -14,7 +15,8 @@
|
|||||||
<div class="content-panel">
|
<div class="content-panel">
|
||||||
<div class="content-area">
|
<div class="content-area">
|
||||||
<el-card class="user-card" shadow="never">
|
<el-card class="user-card" shadow="never">
|
||||||
<el-table ref="userTable" :data="userList" class="transparent-table" :header-cell-class-name="headerCellClassName">
|
<el-table ref="userTable" :data="userList" class="transparent-table"
|
||||||
|
:header-cell-class-name="headerCellClassName">
|
||||||
<el-table-column label="选择" type="selection" align="center" width="120"></el-table-column>
|
<el-table-column label="选择" type="selection" align="center" width="120"></el-table-column>
|
||||||
<el-table-column label="用户Id" prop="userid" align="center"></el-table-column>
|
<el-table-column label="用户Id" prop="userid" align="center"></el-table-column>
|
||||||
<el-table-column label="手机号码" prop="mobile" align="center"></el-table-column>
|
<el-table-column label="手机号码" prop="mobile" align="center"></el-table-column>
|
||||||
@@ -22,14 +24,14 @@
|
|||||||
<el-table-column label="状态" prop="status" align="center"></el-table-column>
|
<el-table-column label="状态" prop="status" align="center"></el-table-column>
|
||||||
<el-table-column label="操作" align="center">
|
<el-table-column label="操作" align="center">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<el-button size="mini" type="text" @click="resetPassword(scope.row)" style="color: #989fdd">重置密码</el-button>
|
<el-button size="mini" type="text" @click="resetPassword(scope.row)"
|
||||||
<el-button size="mini" type="text"
|
style="color: #989fdd">重置密码</el-button>
|
||||||
v-if="scope.row.status === '正常'"
|
<el-button size="mini" type="text" v-if="scope.row.status === '正常'"
|
||||||
@click="disableUser(scope.row)">禁用账户</el-button>
|
@click="disableUser(scope.row)">禁用账户</el-button>
|
||||||
<el-button size="mini" type="text"
|
<el-button size="mini" type="text" v-if="scope.row.status === '禁用'"
|
||||||
v-if="scope.row.status === '禁用'"
|
|
||||||
@click="restoreUser(scope.row)">恢复账号</el-button>
|
@click="restoreUser(scope.row)">恢复账号</el-button>
|
||||||
<el-button size="mini" type="text" @click="deleteUser(scope.row)" style="color: #989fdd">删除用户</el-button>
|
<el-button size="mini" type="text" @click="deleteUser(scope.row)"
|
||||||
|
style="color: #989fdd">删除用户</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
@@ -38,14 +40,16 @@
|
|||||||
<div class="ctrl_btn">
|
<div class="ctrl_btn">
|
||||||
<el-button size="mini" type="primary" class="select-all-btn" @click="handleSelectAll">全选</el-button>
|
<el-button size="mini" type="primary" class="select-all-btn" @click="handleSelectAll">全选</el-button>
|
||||||
<el-button size="mini" type="success" icon="el-icon-circle-check" @click="batchEnable">启用</el-button>
|
<el-button size="mini" type="success" icon="el-icon-circle-check" @click="batchEnable">启用</el-button>
|
||||||
<el-button size="mini" type="warning" @click="batchDisable"><i class="el-icon-remove-outline rotated-icon"></i>禁用</el-button>
|
<el-button size="mini" type="warning" @click="batchDisable"><i
|
||||||
|
class="el-icon-remove-outline rotated-icon"></i>禁用</el-button>
|
||||||
<el-button size="mini" type="danger" icon="el-icon-delete" @click="batchDelete">删除</el-button>
|
<el-button size="mini" type="danger" icon="el-icon-delete" @click="batchDelete">删除</el-button>
|
||||||
</div>
|
</div>
|
||||||
<div class="custom-pagination">
|
<div class="custom-pagination">
|
||||||
<button class="pagination-btn" :disabled="currentPage === 1" @click="goFirst">首页</button>
|
<button class="pagination-btn" :disabled="currentPage === 1" @click="goFirst">首页</button>
|
||||||
<button class="pagination-btn" :disabled="currentPage === 1" @click="goPrev">上一页</button>
|
<button class="pagination-btn" :disabled="currentPage === 1" @click="goPrev">上一页</button>
|
||||||
|
|
||||||
<button v-for="page in visiblePages" :key="page" class="pagination-btn" :class="{ active: page === currentPage }" @click="goToPage(page)">
|
<button v-for="page in visiblePages" :key="page" class="pagination-btn"
|
||||||
|
:class="{ active: page === currentPage }" @click="goToPage(page)">
|
||||||
{{ page }}
|
{{ page }}
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
@@ -61,14 +65,14 @@
|
|||||||
<div class="copyright">
|
<div class="copyright">
|
||||||
©2025 xiaozhi-esp32-server
|
©2025 xiaozhi-esp32-server
|
||||||
</div>
|
</div>
|
||||||
<view-password-dialog :visible.sync="showViewPassword" :password="currentPassword"/>
|
<view-password-dialog :visible.sync="showViewPassword" :password="currentPassword" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import HeaderBar from "@/components/HeaderBar.vue";
|
|
||||||
import adminApi from '@/apis/module/admin';
|
import adminApi from '@/apis/module/admin';
|
||||||
import ViewPasswordDialog from '@/components/ViewPasswordDialog.vue'
|
import HeaderBar from "@/components/HeaderBar.vue";
|
||||||
|
import ViewPasswordDialog from '@/components/ViewPasswordDialog.vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: { HeaderBar, ViewPasswordDialog },
|
components: { HeaderBar, ViewPasswordDialog },
|
||||||
@@ -108,23 +112,23 @@ export default {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
fetchUsers() {
|
fetchUsers() {
|
||||||
adminApi.getUserList({
|
adminApi.getUserList({
|
||||||
page: this.currentPage,
|
page: this.currentPage,
|
||||||
limit: this.pageSize,
|
limit: this.pageSize,
|
||||||
mobile: this.searchPhone
|
mobile: this.searchPhone
|
||||||
}, ({ data }) => {
|
}, ({ data }) => {
|
||||||
if (data.code === 0) {
|
if (data.code === 0) {
|
||||||
this.userList = data.data.list.map(user => ({
|
this.userList = data.data.list.map(user => ({
|
||||||
...user,
|
...user,
|
||||||
status: user.status === '1' ? '正常' : '禁用'
|
status: user.status === '1' ? '正常' : '禁用'
|
||||||
}));
|
}));
|
||||||
this.total = data.data.total;
|
this.total = data.data.total;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
handleSearch() {
|
handleSearch() {
|
||||||
this.currentPage = 1;
|
this.currentPage = 1;
|
||||||
this.fetchUsers();
|
this.fetchUsers();
|
||||||
},
|
},
|
||||||
handleSelectAll() {
|
handleSelectAll() {
|
||||||
this.$refs.userTable.toggleAllSelection();
|
this.$refs.userTable.toggleAllSelection();
|
||||||
@@ -152,11 +156,11 @@ export default {
|
|||||||
const results = await Promise.all(
|
const results = await Promise.all(
|
||||||
selectedUsers.map(user => {
|
selectedUsers.map(user => {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
adminApi.deleteUser(user.userid, ({data}) => {
|
adminApi.deleteUser(user.userid, ({ data }) => {
|
||||||
if (data.code === 0) {
|
if (data.code === 0) {
|
||||||
resolve({success: true, userid: user.userid});
|
resolve({ success: true, userid: user.userid });
|
||||||
} else {
|
} else {
|
||||||
resolve({success: false, userid: user.userid, msg: data.msg});
|
resolve({ success: false, userid: user.userid, msg: data.msg });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -197,7 +201,7 @@ export default {
|
|||||||
},
|
},
|
||||||
batchDisable() {
|
batchDisable() {
|
||||||
this.userList.forEach(user => {
|
this.userList.forEach(user => {
|
||||||
user.status = '禁用';
|
user.status = '禁用';
|
||||||
});
|
});
|
||||||
this.$message.success('状态已更新为禁用');
|
this.$message.success('状态已更新为禁用');
|
||||||
},
|
},
|
||||||
@@ -224,22 +228,22 @@ export default {
|
|||||||
console.log('恢复用户:', row);
|
console.log('恢复用户:', row);
|
||||||
},
|
},
|
||||||
deleteUser(row) {
|
deleteUser(row) {
|
||||||
this.$confirm('确定要删除该用户吗?', '警告', {
|
this.$confirm('确定要删除该用户吗?', '警告', {
|
||||||
confirmButtonText: '确定',
|
confirmButtonText: '确定',
|
||||||
cancelButtonText: '取消',
|
cancelButtonText: '取消',
|
||||||
type: 'warning'
|
type: 'warning'
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
adminApi.deleteUser(row.userid, ({data}) => {
|
adminApi.deleteUser(row.userid, ({ data }) => {
|
||||||
if (data.code === 0) {
|
if (data.code === 0) {
|
||||||
this.$message.success('删除成功')
|
this.$message.success('删除成功')
|
||||||
this.fetchUsers()
|
this.fetchUsers()
|
||||||
} else {
|
} else {
|
||||||
this.$message.error(data.msg || '删除失败')
|
this.$message.error(data.msg || '删除失败')
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}).catch(() => {})
|
}).catch(() => { })
|
||||||
},
|
},
|
||||||
headerCellClassName({columnIndex}) {
|
headerCellClassName({ columnIndex }) {
|
||||||
if (columnIndex === 0) {
|
if (columnIndex === 0) {
|
||||||
return 'custom-selection-header'
|
return 'custom-selection-header'
|
||||||
}
|
}
|
||||||
@@ -252,13 +256,13 @@ export default {
|
|||||||
goPrev() {
|
goPrev() {
|
||||||
if (this.currentPage > 1) {
|
if (this.currentPage > 1) {
|
||||||
this.currentPage--;
|
this.currentPage--;
|
||||||
this.fetchUsers();
|
this.fetchUsers();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
goNext() {
|
goNext() {
|
||||||
if (this.currentPage < this.pageCount) {
|
if (this.currentPage < this.pageCount) {
|
||||||
this.currentPage++;
|
this.currentPage++;
|
||||||
this.fetchUsers();
|
this.fetchUsers();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
goToPage(page) {
|
goToPage(page) {
|
||||||
@@ -289,7 +293,7 @@ export default {
|
|||||||
min-height: 600px;
|
min-height: 600px;
|
||||||
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
|
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
|
||||||
position: relative;
|
position: relative;
|
||||||
background: rgba(237,242,255,0.5);
|
background: rgba(237, 242, 255, 0.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
.operation-bar {
|
.operation-bar {
|
||||||
@@ -355,6 +359,7 @@ export default {
|
|||||||
display: flex;
|
display: flex;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
padding-left: 26px;
|
padding-left: 26px;
|
||||||
|
|
||||||
.el-button {
|
.el-button {
|
||||||
min-width: 72px;
|
min-width: 72px;
|
||||||
height: 32px;
|
height: 32px;
|
||||||
@@ -481,6 +486,7 @@ export default {
|
|||||||
|
|
||||||
:deep(.transparent-table) {
|
:deep(.transparent-table) {
|
||||||
background: white;
|
background: white;
|
||||||
|
|
||||||
.el-table__header th {
|
.el-table__header th {
|
||||||
background: white !important;
|
background: white !important;
|
||||||
color: black;
|
color: black;
|
||||||
@@ -492,6 +498,7 @@ export default {
|
|||||||
|
|
||||||
.el-table__body tr {
|
.el-table__body tr {
|
||||||
background-color: white;
|
background-color: white;
|
||||||
|
|
||||||
td {
|
td {
|
||||||
border-top: 1px solid rgba(0, 0, 0, 0.04);
|
border-top: 1px solid rgba(0, 0, 0, 0.04);
|
||||||
border-bottom: 1px solid rgba(0, 0, 0, 0.04);
|
border-bottom: 1px solid rgba(0, 0, 0, 0.04);
|
||||||
@@ -534,17 +541,18 @@ export default {
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
margin-top: 40px;
|
margin-top: 40px;
|
||||||
}
|
}
|
||||||
|
|
||||||
:deep(.transparent-table) {
|
:deep(.transparent-table) {
|
||||||
.el-table__body tr {
|
.el-table__body tr {
|
||||||
td {
|
td {
|
||||||
padding-top: 16px;
|
padding-top: 16px;
|
||||||
padding-bottom: 16px;
|
padding-bottom: 16px;
|
||||||
}
|
}
|
||||||
& + tr {
|
|
||||||
|
&+tr {
|
||||||
margin-top: 10px;
|
margin-top: 10px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
@@ -2,20 +2,18 @@
|
|||||||
<div class="welcome">
|
<div class="welcome">
|
||||||
<el-container style="height: 100%;">
|
<el-container style="height: 100%;">
|
||||||
<el-header>
|
<el-header>
|
||||||
<div
|
<div style="display: flex;align-items: center;margin-top: 15px;margin-left: 10px;gap: 10px;">
|
||||||
style="display: flex;align-items: center;margin-top: 15px;margin-left: 10px;gap: 10px;">
|
<img loading="lazy" alt="" src="@/assets/xiaozhi-logo.png" style="width: 45px;height: 45px;" />
|
||||||
<img loading="lazy" alt="" src="@/assets/xiaozhi-logo.png" style="width: 45px;height: 45px;"/>
|
<img loading="lazy" alt="" src="@/assets/xiaozhi-ai.png" style="height: 18px;" />
|
||||||
<img loading="lazy" alt="" src="@/assets/xiaozhi-ai.png" style="height: 18px;"/>
|
|
||||||
</div>
|
</div>
|
||||||
</el-header>
|
</el-header>
|
||||||
<div class="login-person">
|
<div class="login-person">
|
||||||
<img loading="lazy" alt="" src="@/assets/login/login-person.png" style="width: 100%;"/>
|
<img loading="lazy" alt="" src="@/assets/login/login-person.png" style="width: 100%;" />
|
||||||
</div>
|
</div>
|
||||||
<el-main style="position: relative;">
|
<el-main style="position: relative;">
|
||||||
<div class="login-box" @keyup.enter="login">
|
<div class="login-box" @keyup.enter="login">
|
||||||
<div
|
<div style="display: flex;align-items: center;gap: 20px;margin-bottom: 39px;padding: 0 30px;">
|
||||||
style="display: flex;align-items: center;gap: 20px;margin-bottom: 39px;padding: 0 30px;">
|
<img loading="lazy" alt="" src="@/assets/login/hi.png" style="width: 34px;height: 34px;" />
|
||||||
<img loading="lazy" alt="" src="@/assets/login/hi.png" style="width: 34px;height: 34px;"/>
|
|
||||||
<div class="login-text">登录</div>
|
<div class="login-text">登录</div>
|
||||||
<div class="login-welcome">
|
<div class="login-welcome">
|
||||||
WELCOME TO LOGIN
|
WELCOME TO LOGIN
|
||||||
@@ -23,27 +21,23 @@
|
|||||||
</div>
|
</div>
|
||||||
<div style="padding: 0 30px;">
|
<div style="padding: 0 30px;">
|
||||||
<div class="input-box">
|
<div class="input-box">
|
||||||
<img loading="lazy" alt="" class="input-icon" src="@/assets/login/username.png"/>
|
<img loading="lazy" alt="" class="input-icon" src="@/assets/login/username.png" />
|
||||||
<el-input v-model="form.username" placeholder="请输入用户名"/>
|
<el-input v-model="form.username" placeholder="请输入用户名" />
|
||||||
</div>
|
</div>
|
||||||
<div class="input-box">
|
<div class="input-box">
|
||||||
<img loading="lazy" alt="" class="input-icon" src="@/assets/login/password.png"/>
|
<img loading="lazy" alt="" class="input-icon" src="@/assets/login/password.png" />
|
||||||
<el-input v-model="form.password" placeholder="请输入密码" type="password"/>
|
<el-input v-model="form.password" placeholder="请输入密码" type="password" />
|
||||||
</div>
|
</div>
|
||||||
<div style="display: flex; align-items: center; margin-top: 20px; width: 100%; gap: 10px;">
|
<div style="display: flex; align-items: center; margin-top: 20px; width: 100%; gap: 10px;">
|
||||||
<div class="input-box" style="width: calc(100% - 130px); margin-top: 0;">
|
<div class="input-box" style="width: calc(100% - 130px); margin-top: 0;">
|
||||||
<img loading="lazy" alt="" class="input-icon" src="@/assets/login/shield.png"/>
|
<img loading="lazy" alt="" class="input-icon" src="@/assets/login/shield.png" />
|
||||||
<el-input v-model="form.captcha" placeholder="请输入验证码" style="flex: 1;"/>
|
<el-input v-model="form.captcha" placeholder="请输入验证码" style="flex: 1;" />
|
||||||
</div>
|
</div>
|
||||||
<img loading="lazy" v-if="captchaUrl"
|
<img loading="lazy" v-if="captchaUrl" :src="captchaUrl" alt="验证码"
|
||||||
:src="captchaUrl"
|
style="width: 150px; height: 40px; cursor: pointer;" @click="fetchCaptcha" />
|
||||||
alt="验证码"
|
|
||||||
style="width: 150px; height: 40px; cursor: pointer;"
|
|
||||||
@click="fetchCaptcha"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
style="font-weight: 400;font-size: 14px;text-align: left;color: #5778ff;display: flex;justify-content: space-between;margin-top: 20px;">
|
style="font-weight: 400;font-size: 14px;text-align: left;color: #5778ff;display: flex;justify-content: space-between;margin-top: 20px;">
|
||||||
<div style="cursor: pointer;" @click="goToRegister">新用户注册</div>
|
<div style="cursor: pointer;" @click="goToRegister">新用户注册</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -92,7 +86,7 @@ export default {
|
|||||||
fetchCaptcha() {
|
fetchCaptcha() {
|
||||||
console.log(this.$store.getters.getToken)
|
console.log(this.$store.getters.getToken)
|
||||||
if (this.$store.getters.getToken) {
|
if (this.$store.getters.getToken) {
|
||||||
if (this.$route.path !== '/home'){
|
if (this.$route.path !== '/home') {
|
||||||
this.$router.push('/home')
|
this.$router.push('/home')
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -100,7 +94,7 @@ export default {
|
|||||||
|
|
||||||
Api.user.getCaptcha(this.captchaUuid, (res) => {
|
Api.user.getCaptcha(this.captchaUuid, (res) => {
|
||||||
if (res.status === 200) {
|
if (res.status === 200) {
|
||||||
const blob = new Blob([res.data], {type: res.data.type});
|
const blob = new Blob([res.data], { type: res.data.type });
|
||||||
this.captchaUrl = URL.createObjectURL(blob);
|
this.captchaUrl = URL.createObjectURL(blob);
|
||||||
} else {
|
} else {
|
||||||
showDanger('验证码加载失败,点击刷新');
|
showDanger('验证码加载失败,点击刷新');
|
||||||
@@ -133,7 +127,7 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.form.captchaId = this.captchaUuid
|
this.form.captchaId = this.captchaUuid
|
||||||
Api.user.login(this.form, ({data}) => {
|
Api.user.login(this.form, ({ data }) => {
|
||||||
if (data.code === 0) {
|
if (data.code === 0) {
|
||||||
showSuccess('登录成功!');
|
showSuccess('登录成功!');
|
||||||
this.$store.commit('setToken', JSON.stringify(data.data));
|
this.$store.commit('setToken', JSON.stringify(data.data));
|
||||||
@@ -156,5 +150,4 @@ export default {
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
@import './auth.scss'; // 添加这行引用
|
@import './auth.scss'; // 添加这行引用</style>
|
||||||
</style>
|
|
||||||
|
|||||||
@@ -4,8 +4,8 @@
|
|||||||
<!-- 保持相同的头部 -->
|
<!-- 保持相同的头部 -->
|
||||||
<el-header>
|
<el-header>
|
||||||
<div style="display: flex;align-items: center;margin-top: 15px;margin-left: 10px;gap: 10px;">
|
<div style="display: flex;align-items: center;margin-top: 15px;margin-left: 10px;gap: 10px;">
|
||||||
<img loading="lazy" alt="" src="@/assets/xiaozhi-logo.png" style="width: 45px;height: 45px;"/>
|
<img loading="lazy" alt="" src="@/assets/xiaozhi-logo.png" style="width: 45px;height: 45px;" />
|
||||||
<img loading="lazy" alt="" src="@/assets/xiaozhi-ai.png" style="width: 70px;height: 13px;"/>
|
<img loading="lazy" alt="" src="@/assets/xiaozhi-ai.png" style="width: 70px;height: 13px;" />
|
||||||
</div>
|
</div>
|
||||||
</el-header>
|
</el-header>
|
||||||
|
|
||||||
@@ -13,7 +13,7 @@
|
|||||||
<div class="login-box">
|
<div class="login-box">
|
||||||
<!-- 修改标题部分 -->
|
<!-- 修改标题部分 -->
|
||||||
<div style="display: flex;align-items: center;gap: 20px;margin-bottom: 39px;padding: 0 30px;">
|
<div style="display: flex;align-items: center;gap: 20px;margin-bottom: 39px;padding: 0 30px;">
|
||||||
<img loading="lazy" alt="" src="@/assets/login/hi.png" style="width: 34px;height: 34px;"/>
|
<img loading="lazy" alt="" src="@/assets/login/hi.png" style="width: 34px;height: 34px;" />
|
||||||
<div class="login-text">注册</div>
|
<div class="login-text">注册</div>
|
||||||
<div class="login-welcome">
|
<div class="login-welcome">
|
||||||
WELCOME TO REGISTER
|
WELCOME TO REGISTER
|
||||||
@@ -23,34 +23,30 @@
|
|||||||
<div style="padding: 0 30px;">
|
<div style="padding: 0 30px;">
|
||||||
<!-- 用户名输入框 -->
|
<!-- 用户名输入框 -->
|
||||||
<div class="input-box">
|
<div class="input-box">
|
||||||
<img loading="lazy" alt="" class="input-icon" src="@/assets/login/username.png"/>
|
<img loading="lazy" alt="" class="input-icon" src="@/assets/login/username.png" />
|
||||||
<el-input v-model="form.username" placeholder="请输入用户名"/>
|
<el-input v-model="form.username" placeholder="请输入用户名" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 密码输入框 -->
|
<!-- 密码输入框 -->
|
||||||
<div class="input-box">
|
<div class="input-box">
|
||||||
<img loading="lazy" alt="" class="input-icon" src="@/assets/login/password.png"/>
|
<img loading="lazy" alt="" class="input-icon" src="@/assets/login/password.png" />
|
||||||
<el-input v-model="form.password" placeholder="请输入密码" type="password"/>
|
<el-input v-model="form.password" placeholder="请输入密码" type="password" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 新增确认密码 -->
|
<!-- 新增确认密码 -->
|
||||||
<div class="input-box">
|
<div class="input-box">
|
||||||
<img loading="lazy" alt="" class="input-icon" src="@/assets/login/password.png"/>
|
<img loading="lazy" alt="" class="input-icon" src="@/assets/login/password.png" />
|
||||||
<el-input v-model="form.confirmPassword" placeholder="请确认密码" type="password"/>
|
<el-input v-model="form.confirmPassword" placeholder="请确认密码" type="password" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 验证码部分保持相同 -->
|
<!-- 验证码部分保持相同 -->
|
||||||
<div style="display: flex; align-items: center; margin-top: 20px; width: 100%; gap: 10px;">
|
<div style="display: flex; align-items: center; margin-top: 20px; width: 100%; gap: 10px;">
|
||||||
<div class="input-box" style="width: calc(100% - 130px); margin-top: 0;">
|
<div class="input-box" style="width: calc(100% - 130px); margin-top: 0;">
|
||||||
<img loading="lazy" alt="" class="input-icon" src="@/assets/login/shield.png"/>
|
<img loading="lazy" alt="" class="input-icon" src="@/assets/login/shield.png" />
|
||||||
<el-input v-model="form.captcha" placeholder="请输入验证码" style="flex: 1;"/>
|
<el-input v-model="form.captcha" placeholder="请输入验证码" style="flex: 1;" />
|
||||||
</div>
|
</div>
|
||||||
<img loading="lazy" v-if="captchaUrl"
|
<img loading="lazy" v-if="captchaUrl" :src="captchaUrl" alt="验证码"
|
||||||
:src="captchaUrl"
|
style="width: 150px; height: 40px; cursor: pointer;" @click="fetchCaptcha" />
|
||||||
alt="验证码"
|
|
||||||
style="width: 150px; height: 40px; cursor: pointer;"
|
|
||||||
@click="fetchCaptcha"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 修改底部链接 -->
|
<!-- 修改底部链接 -->
|
||||||
@@ -83,8 +79,8 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import {getUUID, goToPage, showDanger, showSuccess} from '@/utils'
|
|
||||||
import Api from '@/apis/api';
|
import Api from '@/apis/api';
|
||||||
|
import { getUUID, goToPage, showDanger, showSuccess } from '@/utils';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'register',
|
name: 'register',
|
||||||
@@ -109,7 +105,7 @@ export default {
|
|||||||
this.form.captchaId = getUUID();
|
this.form.captchaId = getUUID();
|
||||||
Api.user.getCaptcha(this.form.captchaId, (res) => {
|
Api.user.getCaptcha(this.form.captchaId, (res) => {
|
||||||
if (res.status === 200) {
|
if (res.status === 200) {
|
||||||
const blob = new Blob([res.data], {type: res.data.type});
|
const blob = new Blob([res.data], { type: res.data.type });
|
||||||
this.captchaUrl = URL.createObjectURL(blob);
|
this.captchaUrl = URL.createObjectURL(blob);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
@@ -146,7 +142,7 @@ export default {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Api.user.register(this.form, ({data}) => {
|
Api.user.register(this.form, ({ data }) => {
|
||||||
console.log(data)
|
console.log(data)
|
||||||
if (data.code === 0) {
|
if (data.code === 0) {
|
||||||
showSuccess('注册成功!')
|
showSuccess('注册成功!')
|
||||||
@@ -169,5 +165,4 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
@import './auth.scss'; // 修改为导入新建的SCSS文件
|
@import './auth.scss'; // 修改为导入新建的SCSS文件</style>
|
||||||
</style>
|
|
||||||
|
|||||||
@@ -1,27 +1,28 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="welcome">
|
<div class="welcome">
|
||||||
<HeaderBar/>
|
<HeaderBar />
|
||||||
<el-main style="padding: 16px;display: flex;flex-direction: column;">
|
<el-main style="padding: 16px;display: flex;flex-direction: column;">
|
||||||
<div style="border-radius: 16px;background: #fafcfe; border: 1px solid #e8f0ff;">
|
<div style="border-radius: 16px;background: #fafcfe; border: 1px solid #e8f0ff;">
|
||||||
<div
|
<div
|
||||||
style="padding: 15px 24px;font-weight: 700;font-size: 19px;text-align: left;color: #3d4566;display: flex;gap: 13px;align-items: center;">
|
style="padding: 15px 24px;font-weight: 700;font-size: 19px;text-align: left;color: #3d4566;display: flex;gap: 13px;align-items: center;">
|
||||||
<div
|
<div
|
||||||
style="width: 37px;height: 37px;background: #5778ff;border-radius: 50%;display: flex;align-items: center;justify-content: center;">
|
style="width: 37px;height: 37px;background: #5778ff;border-radius: 50%;display: flex;align-items: center;justify-content: center;">
|
||||||
<img loading="lazy" src="@/assets/home/setting-user.png" alt="" style="width: 19px;height: 19px;"/>
|
<img loading="lazy" src="@/assets/home/setting-user.png" alt="" style="width: 19px;height: 19px;" />
|
||||||
</div>
|
</div>
|
||||||
{{ form.agentName }}
|
{{ form.agentName }}
|
||||||
</div>
|
</div>
|
||||||
<div style="height: 1px;background: #e8f0ff;"/>
|
<div style="height: 1px;background: #e8f0ff;" />
|
||||||
<el-form ref="form" :model="form" label-width="72px">
|
<el-form ref="form" :model="form" label-width="72px">
|
||||||
<div style="padding: 16px 24px;max-width: 792px;">
|
<div style="padding: 16px 24px;max-width: 792px;">
|
||||||
<el-form-item label="助手昵称:">
|
<el-form-item label="助手昵称:">
|
||||||
<div class="input-46" style="width: 100%; max-width: 412px;">
|
<div class="input-46" style="width: 100%; max-width: 412px;">
|
||||||
<el-input v-model="form.agentName"/>
|
<el-input v-model="form.agentName" />
|
||||||
</div>
|
</div>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="角色模版:">
|
<el-form-item label="角色模版:">
|
||||||
<div style="display: flex;gap: 8px;">
|
<div style="display: flex;gap: 8px;">
|
||||||
<div v-for="template in templates" :key="template" class="template-item" :class="{ 'template-loading': loadingTemplate }" @click="selectTemplate(template)">
|
<div v-for="template in templates" :key="template" class="template-item"
|
||||||
|
:class="{ 'template-loading': loadingTemplate }" @click="selectTemplate(template)">
|
||||||
{{ template }}
|
{{ template }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -30,32 +31,31 @@
|
|||||||
<div style="display: flex;gap: 8px;align-items: center;">
|
<div style="display: flex;gap: 8px;align-items: center;">
|
||||||
<div class="input-46" style="flex:1.4;">
|
<div class="input-46" style="flex:1.4;">
|
||||||
<el-select v-model="form.ttsVoiceId" placeholder="请选择" style="width: 100%;">
|
<el-select v-model="form.ttsVoiceId" placeholder="请选择" style="width: 100%;">
|
||||||
<el-option v-for="item in options" :key="item.value" :label="item.label"
|
<el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value">
|
||||||
:value="item.value">
|
|
||||||
</el-option>
|
</el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
</div>
|
</div>
|
||||||
<div class="audio-box">
|
<div class="audio-box">
|
||||||
<audio src="http://music.163.com/song/media/outer/url?id=447925558.mp3" controls
|
<audio src="http://music.163.com/song/media/outer/url?id=447925558.mp3" controls
|
||||||
style="height: 100%;width: 100%;"/>
|
style="height: 100%;width: 100%;" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="角色介绍:">
|
<el-form-item label="角色介绍:">
|
||||||
<div class="textarea-box">
|
<div class="textarea-box">
|
||||||
<el-input type="textarea" rows="5" resize="none" placeholder="请输入内容"
|
<el-input type="textarea" rows="5" resize="none" placeholder="请输入内容" v-model="form.systemPrompt"
|
||||||
v-model="form.systemPrompt" maxlength="2000" show-word-limit/>
|
maxlength="2000" show-word-limit />
|
||||||
</div>
|
</div>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="记忆体:">
|
<el-form-item label="记忆体:">
|
||||||
<div class="textarea-box">
|
<div class="textarea-box">
|
||||||
<el-input type="textarea" rows="5" resize="none" placeholder="请输入内容"
|
<el-input type="textarea" rows="5" resize="none" placeholder="请输入内容" v-model="form.langCode"
|
||||||
v-model="form.langCode" maxlength="1000"/>
|
maxlength="1000" />
|
||||||
<div class="prompt-bottom" @click="clearMemory">
|
<div class="prompt-bottom" @click="clearMemory">
|
||||||
<div style="display: flex;gap: 8px;align-items: center;">
|
<div style="display: flex;gap: 8px;align-items: center;">
|
||||||
<div style="color: #979db1;font-size: 11px;">当前记忆(每次对话后重新生成)</div>
|
<div style="color: #979db1;font-size: 11px;">当前记忆(每次对话后重新生成)</div>
|
||||||
<div class="clear-btn">
|
<div class="clear-btn">
|
||||||
<i class="el-icon-delete-solid" style="font-size: 11px;"/>
|
<i class="el-icon-delete-solid" style="font-size: 11px;" />
|
||||||
清除
|
清除
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -65,7 +65,7 @@
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item v-for="model in models" :key="model.label" :label="model.label" class="model-item">
|
<el-form-item v-for="model in models" :key="model.label" :label="model.label" class="model-item">
|
||||||
<el-select v-model="form.model[model.key]" filterable placeholder="请选择" class="select-field">
|
<el-select v-model="form.model[model.key]" filterable placeholder="请选择" class="select-field">
|
||||||
<el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value"/>
|
<el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" />
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="" class="lh-form-item" style="margin-top: -25px;">
|
<el-form-item label="" class="lh-form-item" style="margin-top: -25px;">
|
||||||
@@ -83,7 +83,7 @@
|
|||||||
重制
|
重制
|
||||||
</div>
|
</div>
|
||||||
<div class="clear-text">
|
<div class="clear-text">
|
||||||
<img loading="lazy" src="@/assets/home/red-info.png" alt="" style="width: 19px;height: 19px;"/>
|
<img loading="lazy" src="@/assets/home/red-info.png" alt="" style="width: 19px;height: 19px;" />
|
||||||
保存配置后,需要重启设备,新的配置才会生效。
|
保存配置后,需要重启设备,新的配置才会生效。
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -100,7 +100,7 @@ import HeaderBar from "@/components/HeaderBar.vue";
|
|||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'RoleConfigPage',
|
name: 'RoleConfigPage',
|
||||||
components: {HeaderBar},
|
components: { HeaderBar },
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
form: {
|
form: {
|
||||||
@@ -121,16 +121,16 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
options: [
|
options: [
|
||||||
{value: '选项1', label: '黄金糕'},
|
{ value: '选项1', label: '黄金糕' },
|
||||||
{value: '选项2', label: '双皮奶'}
|
{ value: '选项2', label: '双皮奶' }
|
||||||
],
|
],
|
||||||
models: [
|
models: [
|
||||||
{label: '大语言模型(LLM)', key: 'llmModelId'},
|
{ label: '大语言模型(LLM)', key: 'llmModelId' },
|
||||||
{label: '语音识别(ASR)', key: 'asrModelId'},
|
{ label: '语音识别(ASR)', key: 'asrModelId' },
|
||||||
{label: '语音活动检测(VAD)', key: 'vadModelId'},
|
{ label: '语音活动检测(VAD)', key: 'vadModelId' },
|
||||||
{label: '语音合成(TTS)', key: 'ttsModelId'},
|
{ label: '语音合成(TTS)', key: 'ttsModelId' },
|
||||||
{label: '意图识别(Intent)', key: 'intentModelId'},
|
{ label: '意图识别(Intent)', key: 'intentModelId' },
|
||||||
{label: '记忆(Memory)', key: 'memModelId'}
|
{ label: '记忆(Memory)', key: 'memModelId' }
|
||||||
],
|
],
|
||||||
templates: ['湾湾小何', '星际游子', '英语老师', '好奇男孩', '汪汪队长'],
|
templates: ['湾湾小何', '星际游子', '英语老师', '好奇男孩', '汪汪队长'],
|
||||||
loadingTemplate: false
|
loadingTemplate: false
|
||||||
@@ -153,8 +153,8 @@ export default {
|
|||||||
language: this.form.language,
|
language: this.form.language,
|
||||||
sort: this.form.sort
|
sort: this.form.sort
|
||||||
};
|
};
|
||||||
import('@/apis/module/agent').then(({default: agentApi}) => {
|
import('@/apis/module/agent').then(({ default: agentApi }) => {
|
||||||
agentApi.updateAgentConfig(this.$route.query.agentId, configData, ({data}) => {
|
agentApi.updateAgentConfig(this.$route.query.agentId, configData, ({ data }) => {
|
||||||
if (data.code === 0) {
|
if (data.code === 0) {
|
||||||
this.$message.success('配置保存成功');
|
this.$message.success('配置保存成功');
|
||||||
} else {
|
} else {
|
||||||
@@ -192,31 +192,31 @@ export default {
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
selectTemplate(templateName) {
|
selectTemplate(templateName) {
|
||||||
if (this.loadingTemplate) return;
|
if (this.loadingTemplate) return;
|
||||||
this.loadingTemplate = true;
|
this.loadingTemplate = true;
|
||||||
import('@/apis/module/agent').then(({default: agentApi}) => {
|
import('@/apis/module/agent').then(({ default: agentApi }) => {
|
||||||
agentApi.getAgentTemplate((response) => { // 移除参数传递
|
agentApi.getAgentTemplate((response) => { // 移除参数传递
|
||||||
this.loadingTemplate = false;
|
this.loadingTemplate = false;
|
||||||
if (response.data.code === 0) {
|
if (response.data.code === 0) {
|
||||||
// 在客户端过滤匹配的模板
|
// 在客户端过滤匹配的模板
|
||||||
const matchedTemplate = response.data.data.find(
|
const matchedTemplate = response.data.data.find(
|
||||||
t => t.agentName === templateName
|
t => t.agentName === templateName
|
||||||
);
|
);
|
||||||
if (matchedTemplate) {
|
if (matchedTemplate) {
|
||||||
this.applyTemplateData(matchedTemplate);
|
this.applyTemplateData(matchedTemplate);
|
||||||
this.$message.success(`「${templateName}」模板已应用`);
|
this.$message.success(`「${templateName}」模板已应用`);
|
||||||
} else {
|
} else {
|
||||||
this.$message.warning(`未找到「${templateName}」模板`);
|
this.$message.warning(`未找到「${templateName}」模板`);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this.$message.error(response.data.msg || '获取模板失败');
|
this.$message.error(response.data.msg || '获取模板失败');
|
||||||
}
|
}
|
||||||
});
|
|
||||||
}).catch((error) => {
|
|
||||||
this.loadingTemplate = false;
|
|
||||||
this.$message.error('模板加载失败');
|
|
||||||
console.error('接口异常:', error);
|
|
||||||
});
|
});
|
||||||
|
}).catch((error) => {
|
||||||
|
this.loadingTemplate = false;
|
||||||
|
this.$message.error('模板加载失败');
|
||||||
|
console.error('接口异常:', error);
|
||||||
|
});
|
||||||
},
|
},
|
||||||
applyTemplateData(templateData) {
|
applyTemplateData(templateData) {
|
||||||
this.form = {
|
this.form = {
|
||||||
@@ -235,37 +235,37 @@ export default {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
fetchAgentConfig(agentId) {
|
fetchAgentConfig(agentId) {
|
||||||
import('@/apis/module/agent').then(({default: agentApi}) => {
|
import('@/apis/module/agent').then(({ default: agentApi }) => {
|
||||||
agentApi.getDeviceConfig(agentId, ({data}) => {
|
agentApi.getDeviceConfig(agentId, ({ data }) => {
|
||||||
if (data.code === 0) {
|
if (data.code === 0) {
|
||||||
this.form = {
|
this.form = {
|
||||||
...this.form,
|
...this.form,
|
||||||
...data.data,
|
...data.data,
|
||||||
model: {
|
model: {
|
||||||
ttsModelId: data.data.ttsModelId,
|
ttsModelId: data.data.ttsModelId,
|
||||||
vadModelId: data.data.vadModelId,
|
vadModelId: data.data.vadModelId,
|
||||||
asrModelId: data.data.asrModelId,
|
asrModelId: data.data.asrModelId,
|
||||||
llmModelId: data.data.llmModelId,
|
llmModelId: data.data.llmModelId,
|
||||||
memModelId: data.data.memModelId,
|
memModelId: data.data.memModelId,
|
||||||
intentModelId: data.data.intentModelId
|
intentModelId: data.data.intentModelId
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
this.$message.error(data.msg || '获取配置失败');
|
this.$message.error(data.msg || '获取配置失败');
|
||||||
}
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
},
|
||||||
|
// 清空记忆体内容
|
||||||
|
clearMemory() {
|
||||||
|
this.form.langCode = "";
|
||||||
|
this.$message.success("记忆体已清空");
|
||||||
|
},
|
||||||
},
|
},
|
||||||
// 清空记忆体内容
|
|
||||||
clearMemory() {
|
|
||||||
this.form.langCode = "";
|
|
||||||
this.$message.success("记忆体已清空");
|
|
||||||
},
|
|
||||||
},
|
|
||||||
mounted() {
|
mounted() {
|
||||||
const agentId = this.$route.query.agentId;
|
const agentId = this.$route.query.agentId;
|
||||||
console.log('agentId2222',agentId);
|
console.log('agentId2222', agentId);
|
||||||
if (agentId) {
|
if (agentId) {
|
||||||
this.fetchAgentConfig(agentId);
|
this.fetchAgentConfig(agentId);
|
||||||
}
|
}
|
||||||
@@ -299,7 +299,7 @@ export default {
|
|||||||
padding-bottom: 2px;
|
padding-bottom: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.select-field{
|
.select-field {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
max-width: 720px;
|
max-width: 720px;
|
||||||
border: 1px solid #e4e6ef;
|
border: 1px solid #e4e6ef;
|
||||||
@@ -397,4 +397,3 @@ export default {
|
|||||||
background: #f6f8fb;
|
background: #f6f8fb;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|||||||
@@ -3,13 +3,12 @@
|
|||||||
<h1 class="title">XiaoZhi ESP32 Server 测试助手</h1>
|
<h1 class="title">XiaoZhi ESP32 Server 测试助手</h1>
|
||||||
<div class="chat-container" ref="chatContainer">
|
<div class="chat-container" ref="chatContainer">
|
||||||
<div v-for="(message, index) in messages" :key="index"
|
<div v-for="(message, index) in messages" :key="index"
|
||||||
:class="['message', message.role === 'user' ? 'user' : 'assistant']">
|
:class="['message', message.role === 'user' ? 'user' : 'assistant']">
|
||||||
<span>{{ message.content }}</span>
|
<span>{{ message.content }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
<button @click="toggleRecording" :disabled="wsStatus !== 'connected'"
|
<button @click="toggleRecording" :disabled="wsStatus !== 'connected'" :class="{ recording: isRecording }">
|
||||||
:class="{ recording: isRecording }">
|
|
||||||
{{ isRecording ? '停止录音' : '开始录音' }}
|
{{ isRecording ? '停止录音' : '开始录音' }}
|
||||||
</button>
|
</button>
|
||||||
<p>WebSocket: {{ wsStatus }}</p>
|
<p>WebSocket: {{ wsStatus }}</p>
|
||||||
@@ -18,8 +17,8 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import Recorder from 'opus-recorder';
|
|
||||||
import { OpusDecoder } from 'opus-decoder';
|
import { OpusDecoder } from 'opus-decoder';
|
||||||
|
import Recorder from 'opus-recorder';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'TestPage',
|
name: 'TestPage',
|
||||||
@@ -89,8 +88,8 @@ export default {
|
|||||||
console.log('收到音频帧,大小:', event.data.byteLength, '字节');
|
console.log('收到音频帧,大小:', event.data.byteLength, '字节');
|
||||||
const opusFrame = new Uint8Array(event.data);
|
const opusFrame = new Uint8Array(event.data);
|
||||||
const frameHead = Array.from(opusFrame.slice(0, 8))
|
const frameHead = Array.from(opusFrame.slice(0, 8))
|
||||||
.map(b => b.toString(16).padStart(2, '0'))
|
.map(b => b.toString(16).padStart(2, '0'))
|
||||||
.join(' ');
|
.join(' ');
|
||||||
console.log('音频帧前8字节:', frameHead);
|
console.log('音频帧前8字节:', frameHead);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -258,8 +257,8 @@ export default {
|
|||||||
const frames = this.stripOggContainer(data);
|
const frames = this.stripOggContainer(data);
|
||||||
frames.forEach((frame, index) => {
|
frames.forEach((frame, index) => {
|
||||||
const frameHead = Array.from(new Uint8Array(frame.slice(0, 8)))
|
const frameHead = Array.from(new Uint8Array(frame.slice(0, 8)))
|
||||||
.map(b => b.toString(16).padStart(2, '0'))
|
.map(b => b.toString(16).padStart(2, '0'))
|
||||||
.join(' ');
|
.join(' ');
|
||||||
console.log(`帧 ${index} 大小: ${frame.byteLength} 字节,前8字节: ${frameHead}`);
|
console.log(`帧 ${index} 大小: ${frame.byteLength} 字节,前8字节: ${frameHead}`);
|
||||||
|
|
||||||
if (frame.byteLength < 50 || frame.byteLength > 300) {
|
if (frame.byteLength < 50 || frame.byteLength > 300) {
|
||||||
|
|||||||
Reference in New Issue
Block a user