Merge pull request #537 from xinnan-tech/web-vue-modelconfig

优化了”模型配置“页面
This commit is contained in:
Sakura-RanChen
2025-03-26 17:15:15 +08:00
committed by GitHub
3 changed files with 353 additions and 293 deletions
+1 -32
View File
@@ -67,37 +67,6 @@ export default {
}); });
}).send(); }).send();
}, },
// 获取所有模型名称
getModelNames(callback) {
RequestService.sendRequest()
.url(`${getServiceUrl()}/api/v1/models/names`)
.method('GET')
.success((res) => {
RequestService.clearRequestTime();
callback(res);
})
.fail(() => {
RequestService.reAjaxFun(() => {
this.getModelNames(callback);
});
}).send();
},
// 获取模型音色
getModelVoices(modelName, callback) {
RequestService.sendRequest()
.url(`${getServiceUrl()}/api/v1/models/${modelName}/voices`)
.method('GET')
.success((res) => {
RequestService.clearRequestTime();
callback(res);
})
.fail(() => {
RequestService.reAjaxFun(() => {
this.getModelVoices(modelName, callback);
});
}).send();
},
// 获取智能体列表 // 获取智能体列表
getAgentList(callback) { getAgentList(callback) {
RequestService.sendRequest() RequestService.sendRequest()
@@ -160,7 +129,7 @@ export default {
}); });
}).send(); }).send();
}, },
// API接口代码修改 // 修改用户密码
changePassword(oldPassword, newPassword, successCallback, errorCallback) { changePassword(oldPassword, newPassword, successCallback, errorCallback) {
RequestService.sendRequest() RequestService.sendRequest()
.url(`${getServiceUrl()}/api/v1/user/change-password`) // 修改URL .url(`${getServiceUrl()}/api/v1/user/change-password`) // 修改URL
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

+235 -144
View File
@@ -1,93 +1,106 @@
<template> <template>
<div class="welcome"> <div class="welcome">
<HeaderBar /> <HeaderBar />
<div class="model-container">
<el-menu :default-active="activeTab" class="el-menu-vertical-demo" @select="handleMenuSelect"> <div class="operation-bar">
<el-menu-item index="vad">语音活动检测</el-menu-item>
<el-menu-item index="asr">语音识别</el-menu-item> <div class="right-operations">
<el-menu-item index="llm">大语言模型</el-menu-item> <el-button v-if="activeTab === 'tts'" type="primary" plain size="small" @click="ttsDialogVisible = true">
<el-menu-item index="intent">意图识别</el-menu-item> 语音设置
<el-menu-item index="tts">语音合成</el-menu-item> </el-button>
<el-menu-item index="memory">记忆</el-menu-item> <el-button type="primary" plain size="small" @click="handleImport">
</el-menu> 导入配置
<div class="content-container"> </el-button>
<div class="import-export-btn"> <el-button type="success" plain size="small" @click="handleExport">
<el-button v-if="activeTab === 'tts'" type="primary" @click="ttsDialogVisible = true" style="margin-right: 10px;"> 导出配置
模型设置
</el-button> </el-button>
<el-button size="small" @click="handleImportExport">导入导出配置</el-button>
</div> </div>
<el-main style="padding: 20px; display: flex; flex-direction: column;">
<el-card class="model-card" shadow="always">
<div class="model-header">
<h2>大语言模型 (LLM)</h2>
<el-button type="primary" @click="addModel" class="add-btn">添加</el-button>
</div> </div>
<div class="model-search-operate" style="margin-bottom: 20px;"> <!-- 主体内容 -->
<el-input <div class="main-wrapper">
placeholder="请输入模型名称查询" <div class="content-panel">
v-model="search" <!-- 左侧导航 -->
style="width: 300px; margin-right: 10px" <el-menu :default-active="activeTab" class="nav-panel" @select="handleMenuSelect"
/> style="background-size: cover; background-position: center;">
<el-button @click="handleSearch">查询</el-button> <el-menu-item index="vad">
<span class="menu-text">语言活动检测</span>
</el-menu-item>
<el-menu-item index="asr">
<span class="menu-text">语音识别</span>
</el-menu-item>
<el-menu-item index="llm">
<span class="menu-text">大语言模型</span>
</el-menu-item>
<el-menu-item index="intent">
<span class="menu-text">意图识别</span>
</el-menu-item>
<el-menu-item index="tts">
<span class="menu-text">语音合成</span>
</el-menu-item>
<el-menu-item index="memory">
<span class="menu-text">记忆</span>
</el-menu-item>
</el-menu>
<!-- 右侧内容 -->
<div class="content-area">
<div class="title-bar">
<div class="title-wrapper">
<h2 class="model-title">大语言模型LLM</h2>
<el-button type="primary" size="small" @click="addModel" class="add-btn">
<i class="el-icon-plus"></i>添加
</el-button>
</div> </div>
<el-table <div class="action-group">
:data="modelList" <div class="search-group">
style="width: 100%;" <el-input placeholder="请输入模型名称查询" v-model="search" size="small" class="search-input" clearable/>
border <el-button type="primary" size="small" class="search-btn" @click="handleSearch">
stripe 查询
header-cell-class-name="header-cell" </el-button>
> </div>
<el-table-column type="selection" width="55"></el-table-column> </div>
<el-table-column label="模型名称" prop="candidateName"></el-table-column> </div>
<el-table-column label="模型编码" prop="code"></el-table-column>
<el-table-column label="提供商" prop="supplier"></el-table-column> <el-table :data="modelList" border class="data-table" header-row-class-name="table-header" >
<el-table-column label="是否启用"> <el-table-column type="selection" width="55" align="center"></el-table-column>
<el-table-column label="模型名称" prop="candidateName" align="center"></el-table-column>
<el-table-column label="模型编码" prop="code" align="center"></el-table-column>
<el-table-column label="提供商" prop="supplier" align="center"></el-table-column>
<el-table-column label="是否启用" align="center" width="120">
<template slot-scope="scope"> <template slot-scope="scope">
<el-switch v-model="scope.row.isApplied" active-color="#409EFF" inactive-color="#C0CCDA"></el-switch> <el-switch v-model="scope.row.isApplied" class="custom-switch" :active-color="null" :inactive-color="null"/>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="操作"> <el-table-column label="操作" align="center" width="180">
<template slot-scope="scope"> <template slot-scope="scope">
<el-button <el-button type="text" size="mini" @click="editModel(scope.row)" class="edit-btn">
size="mini" 修改
@click="editModel(scope.row)" </el-button>
style="margin-right: 5px;" <el-button type="text" size="mini" @click="deleteModel(scope.row)" class="delete-btn">
type="text" 删除
class="action-btn" </el-button>
>修改</el-button>
<el-button
size="mini"
type="danger"
@click="deleteModel(scope.row)"
class="action-btn"
>删除</el-button>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
<div class="table-footer"> <div class="table-footer">
<el-button @click="selectAll" class="footer-btn">全选</el-button> <div class="batch-actions">
<el-button type="danger" @click="batchDelete" class="footer-btn">删除</el-button> <el-button size="mini" @click="selectAll">全选</el-button>
<el-button size="mini" type="danger" icon="el-icon-delete" @click="batchDelete">
删除
</el-button>
</div> </div>
</el-card> <el-pagination small background :current-page="currentPage" :page-size="pageSize" layout="prev, pager, next" :total="total"/>
<div class="pagination-container">
<el-pagination
@current-change="handleCurrentChange"
:current-page="currentPage"
:page-sizes="[5, 10, 15]"
:page-size="pageSize"
layout="prev, pager, next"
:total="total"
/>
</div> </div>
<div class="copyright">
©2025 xiaozhi-esp32-server
</div> </div>
</div>
<ModelEditDialog :visible.sync="editDialogVisible" :modelData="editModelData" @save="handleModelSave"/> <ModelEditDialog :visible.sync="editDialogVisible" :modelData="editModelData" @save="handleModelSave"/>
<TtsModel :visible.sync="ttsDialogVisible" /> <TtsModel :visible.sync="ttsDialogVisible" />
<AddModelDialog :visible.sync="addDialogVisible" :modelType="activeTab" @confirm="handleAddConfirm"/>
</el-main>
</div> </div>
<div class="copyright">
©2025 xiaozhi-esp32-server
</div> </div>
</div> </div>
</template> </template>
@@ -96,10 +109,9 @@
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";
export default { export default {
components: { HeaderBar, ModelEditDialog, TtsModel, AddModelDialog}, components: { HeaderBar, ModelEditDialog, TtsModel },
data() { data() {
return { return {
activeTab: 'llm', activeTab: 'llm',
@@ -107,7 +119,6 @@
editDialogVisible: false, editDialogVisible: false,
editModelData: {}, editModelData: {},
ttsDialogVisible: false, ttsDialogVisible: false,
addDialogVisible: false, // 新增弹窗显示状态
modelList: [ modelList: [
{ code: 'DeepSeek', candidateName: '深度求索', isApplied: true, supplier: '硅基流动' }, { code: 'DeepSeek', candidateName: '深度求索', isApplied: true, supplier: '硅基流动' },
{ code: 'SmartAssist', candidateName: '智能助手', isApplied: false, supplier: '智脑科技' }, { code: 'SmartAssist', candidateName: '智能助手', isApplied: false, supplier: '智脑科技' },
@@ -128,22 +139,8 @@
batchDelete() { batchDelete() {
console.log('批量删除'); console.log('批量删除');
}, },
// 修改addModel方法
addModel() { addModel() {
this.addDialogVisible = true; console.log('增加模型');
},
// 新增处理方法
handleAddConfirm(formData) {
// 这里处理添加模型的逻辑
console.log('新增模型数据:', formData);
// 模拟添加到列表
this.modelList.unshift({
code: formData.modelCode,
candidateName: formData.modelName,
supplier: formData.supplier,
isApplied: formData.isEnabled
});
this.$message.success('模型添加成功');
}, },
editModel(model) { editModel(model) {
this.editModelData = { this.editModelData = {
@@ -160,8 +157,11 @@
this.currentPage = page; this.currentPage = page;
console.log('当前页码:', page); console.log('当前页码:', page);
}, },
handleImportExport() { handleImport() {
console.log('导入导出'); console.log('导入配置');
},
handleExport() {
console.log('导出配置');
}, },
handleModelSave(formData) { handleModelSave(formData) {
console.log('保存的模型数据:', formData); console.log('保存的模型数据:', formData);
@@ -179,107 +179,198 @@
min-height: 506px; min-height: 506px;
height: 100vh; height: 100vh;
display: flex; display: flex;
position: relative;
flex-direction: column; flex-direction: column;
background-image: url("@/assets/home/background.png");
background-size: cover; background-size: cover;
background-position: center; background: linear-gradient(to bottom right, #dce8ff, #e4eeff, #e6cbfd) center;
-webkit-background-size: cover; -webkit-background-size: cover;
-o-background-size: cover; -o-background-size: cover;
} }
.model-container { .main-wrapper {
margin: 5px 50px;
background-image: url("@/assets/home/background.png");
border-radius: 15px;
min-height: 580px;
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
position: relative;
}
.operation-bar {
display: flex; display: flex;
margin-top: 25px; justify-content: flex-end;
align-items: center;
padding: 16px 24px;
border-bottom: 1px solid #ebeef5;
} }
.el-menu-vertical-demo { .content-panel {
width: 250px;
margin-right: 20px;
background-color: #f8f9fa;
}
.content-container {
flex: 1; flex: 1;
display: flex; display: flex;
overflow: hidden;
height: 100%;
border-radius: 15px;
background: transparent;
}
.nav-panel {
width: 18%;
min-width: 200px;
height: 100%;
border-right: 1px solid #ebeef5;
background-size: cover;
background: url("../assets/model/model.png") no-repeat center;
padding: 16px 0;
flex-shrink: 0;
display: flex;
flex-direction: column; flex-direction: column;
} }
.model-header { .nav-panel .el-menu-item {
height: 48px;
line-height: 40px;
border-radius: 4px;
transition: all 0.3s;
display: flex !important;
justify-content: flex-end;
padding-right: 12px !important;
width: fit-content;
margin: 8px 12px 8px auto;
min-width: unset;
}
.nav-panel .el-menu-item.is-active {
background: #ecf5ff;
color: #409EFF;
border-right: 3px solid #409EFF;
}
.menu-text {
font-size: 14px;
color: #606266;
text-align: right;
width: 100%;
padding-right: 8px;
}
.content-area {
flex: 1;
padding: 24px;
height: 100%;
min-width: 600px;
overflow-x: auto;
}
.title-bar {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
margin-bottom: 20px; margin-bottom: 24px;
flex-wrap: nowrap;
} }
.model-search-operate { .model-title {
font-size: 18px;
color: #303133;
margin: 0;
}
.action-group {
display: flex; display: flex;
align-items: center; align-items: center;
gap: 16px;
} }
.model-search-operate > * { .search-group {
margin-right: 10px; display: flex;
gap: 8px;
} }
.el-table__header th { .search-input {
background-color: #f5f7fa; width: 240px;
}
.search-btn {
background: linear-gradient(135deg, #6B8CFF, #A966FF);
border: none;
color: white;
}
.data-table {
border-radius: 6px;
overflow: hidden;
background-color: transparent !important;
}
.data-table /deep/ .el-table__row {
background-color: transparent !important;
}
.table-header th {
background-color: transparent !important;
color: #606266; color: #606266;
font-weight: 500; font-weight: 600;
}
.model-card {
background: #fff;
border-radius: 12px;
padding: 20px;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
}
.import-export-btn {
margin-bottom: 20px;
display: flex;
justify-content: flex-end;
margin-right: 40px;
}
.pagination-container {
margin-top: 20px;
display: flex;
justify-content: flex-end;
} }
.table-footer { .table-footer {
margin-top: 20px; margin-top: 24px;
display: flex; display: flex;
justify-content: space-between;
align-items: center; align-items: center;
padding: 16px 0;
} }
.footer-btn { .batch-actions {
margin-right: 10px; display: flex;
gap: 8px;
} }
.copyright { .copyright {
text-align: center;
color: #979db1;
font-size: 12px; font-size: 12px;
font-weight: 400; font-weight: 400;
color: #979db1;
margin-top: auto; margin-top: auto;
padding-top: 30px; padding: 30px 0 20px;
text-align: center; position: absolute;
bottom: 0;
left: 50%;
transform: translateX(-50%);
width: 100%;
} }
.action-btn { .edit-btn {
padding: 0 8px; color: #409EFF !important;
} }
.header-cell { .delete-btn {
font-weight: 500; color: #F56C6C !important;
} }
.add-btn { .add-btn {
margin-right: 830px; background: #87CEFA;
padding: 8px 16px;
border-radius: 4px;
background-color: #409eff;
color: white;
border: none; border: none;
cursor: pointer; color: white;
padding: 8px 16px;
} }
.title-wrapper {
display: flex;
align-items: center;
gap: 8px;
}
.batch-actions .el-button:first-child {
background: linear-gradient(135deg, #409EFF, #6B8CFF);
border: none;
color: white;
}
.batch-actions .el-button:first-child:hover {
background: linear-gradient(135deg, #3A8EE6, #5A7CFF);
}
</style> </style>