Merge pull request #741 from xinnan-tech/web-api-timbre

Web api timbre
This commit is contained in:
hrz
2025-04-11 21:25:34 +08:00
committed by GitHub
6 changed files with 199 additions and 183 deletions
@@ -115,7 +115,6 @@ export default {
},
// 删除
deleteParam(ids, callback) {
console.log(4444,ids )
RequestService.sendRequest()
.url(`${getServiceUrl()}/admin/params/delete`)
.method('POST')
+9 -19
View File
@@ -1,11 +1,8 @@
// timbre.js
import {getServiceUrl} from '../api';
import RequestService from '../httpRequest';
export default {
/**
* 获取音色数据
*/
// 获取音色
getVoiceList(params, callback) {
const queryParams = new URLSearchParams({
ttsModelId: params.ttsModelId,
@@ -28,9 +25,7 @@ export default {
});
}).send();
},
/**
* 音色保存
*/
// 音色保存
saveVoice(params, callback) {
RequestService.sendRequest()
.url(`${getServiceUrl()}/ttsVoice`)
@@ -54,15 +49,12 @@ export default {
});
}).send();
},
/**
* 音色删除
*/
deleteVoice(id, callback) {
console.log('尝试删除音色,ID:', id);
// 音色删除
deleteVoice(ids, callback) {
RequestService.sendRequest()
.url(`${getServiceUrl()}/ttsVoice`)
.method('DELETE')
.data({ ids: [id] })
.url(`${getServiceUrl()}/ttsVoice/delete`)
.method('POST')
.data(ids)
.success((res) => {
RequestService.clearRequestTime()
callback(res);
@@ -70,13 +62,11 @@ export default {
.fail((err) => {
console.error('删除音色失败:', err);
RequestService.reAjaxFun(() => {
this.deleteVoice(id, callback);
this.deleteVoice(ids, callback);
});
}).send();
},
/**
* 音色修改
*/
// 音色修改
updateVoice(params, callback) {
RequestService.sendRequest()
.url(`${getServiceUrl()}/ttsVoice/${params.id}`)
+88 -110
View File
@@ -1,7 +1,7 @@
<template>
<el-dialog
:visible.sync="localVisible"
width="75%"
width="85%"
@close="handleClose"
:show-close="false"
:append-to-body="true"
@@ -13,8 +13,7 @@
<div
class="table-container"
ref="tableContainer"
@scroll="handleScroll"
>
@scroll="handleScroll">
<el-table
v-loading="loading"
:data="filteredTtsModels"
@@ -45,7 +44,7 @@
<span v-else>{{ scope.row.languageType }}</span>
</template>
</el-table-column>
<el-table-column label="试听" align="center" min-width="225" class-name="audio-column">
<el-table-column label="试听" align="center" min-width="100px" class-name="audio-column">
<template slot-scope="scope">
<div class="custom-audio-container">
<el-input
@@ -53,13 +52,13 @@
v-model="scope.row.voiceDemo"
placeholder="请输入MP3地址"
size="mini"
class="audio-input"
></el-input>
class="audio-input">
</el-input>
<AudioPlayer v-else-if="isValidAudioUrl(scope.row.voiceDemo)" :audioUrl="scope.row.voiceDemo"/>
</div>
</template>
</el-table-column>
<el-table-column label="备注" align="center" min-width="120">
<el-table-column label="备注" align="center">
<template slot-scope="scope">
<el-input
v-if="scope.row.editing"
@@ -75,10 +74,10 @@
<el-table-column label="操作" align="center" width="150">
<template slot-scope="scope">
<template v-if="!scope.row.editing">
<el-button type="primary" size="mini" @click="startEdit(scope.row)"
style="background: #5cca8e;border:None">编辑
<el-button type="text" size="mini" @click="startEdit(scope.row)" class="edit-btn">
编辑
</el-button>
<el-button type="primary" size="mini" @click="deleteRow(scope.row)" style="background: red;border:None">
<el-button type="text" size="mini" @click="deleteRow(scope.row)" class="delete-btn">
删除
</el-button>
</template>
@@ -105,10 +104,14 @@
<el-button type="primary" size="mini" @click="toggleSelectAll" style="background: #606ff3;border: None">
{{ selectAll ? '取消全选' : '全选' }}
</el-button>
<el-button type="primary" size="mini" @click="addNew" style="background: #f6cf79;border: None; color: #000012">
<el-button type="primary" size="mini" @click="addNew" style="background: #5bc98c;border: None;">
新增
</el-button>
<el-button type="primary" size="mini" @click="batchDelete" style="background: red;border:None">删除</el-button>
<el-button type="primary"
size="mini"
@click="deleteRow(filteredTtsModels.filter(row => row.selected))"
style="background: red;border:None">删除
</el-button>
</div>
</el-dialog>
</template>
@@ -419,105 +422,57 @@ export default {
},
deleteRow(row) {
this.$confirm("确定要删除该音色吗?", "警告", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
})
.then(() => {
Api.timbre.deleteVoice(row.id, (response) => {
if (response.code === 0) {
this.$message.success({
message: "删除成功",
showClose: true
});
this.loadData(); // 刷新数据
} else {
this.$message.error({
message: response.msg || "删除失败",
showClose: true
});
// 处理单个音色或音色数组
const voices = Array.isArray(row) ? row : [row];
if (Array.isArray(row) && row.length === 0) {
this.$message.warning("请先选择需要删除的音色");
return;
}
const voiceCount = voices.length;
this.$confirm(`确定要删除选中的${voiceCount}个音色吗?`, "警告", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
distinguishCancelAndClose: true
}).then(() => {
const ids = voices.map(voice => voice.id);
if (ids.some(id => !id)) {
this.$message.error("存在无效的音色ID");
return;
}
});
})
.catch(() => {
this.$message.info("已取消删除");
});
},
batchDelete() {
const selectedRows = this.filteredTtsModels.filter(row => row.selected);
if (selectedRows.length === 0) {
this.$message.warning("请先选择需要删除的音色");
return;
}
this.$confirm(`确定要删除选中的${selectedRows.length}个音色吗?`, "警告", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
})
.then(async () => {
const loading = this.$loading({
lock: true,
text: "正在删除中...",
spinner: "el-icon-loading",
background: "rgba(0, 0, 0, 0.7)",
});
try {
const results = await Promise.all(
selectedRows.map((row) => {
return new Promise((resolve) => {
Api.timbre.deleteVoice(row.id, (response) => {
if (response.code === 0) {
resolve({ success: true, id: row.id });
} else {
resolve({
success: false,
id: row.id,
msg: response.msg || '删除失败'
});
}
});
Api.timbre.deleteVoice(ids, ({data}) => {
if (data.code === 0) {
this.$message.success({
message: `成功删除${voiceCount}个参数`,
showClose: true
});
})
);
const successCount = results.filter(r => r.success).length;
const failCount = results.length - successCount;
if (failCount === 0) {
this.$message.success({
message: `成功删除${successCount}个音色`,
showClose: true
});
} else if (successCount === 0) {
this.$message.error({
message: '删除失败,请重试',
showClose: true
});
this.loadData(); // 刷新参数列表
} else {
this.$message.warning({
message: `成功删除${successCount}个音色,${failCount}个删除失败`,
showClose: true
});
this.$message.error({
message: data.msg || '删除失败,请重试',
showClose: true
});
}
this.loadData(); // 刷新数据
} catch (error) {
console.error('批量删除出错:', error);
this.$message.error({
message: '删除过程中发生错误',
showClose: true
});
} finally {
loading.close();
}
})
.catch(() => {
this.$message.info("已取消删除");
});
}).catch(action => {
if (action === 'cancel') {
this.$message({
type: 'info',
message: '已取消删除操作',
duration: 1000
});
} else {
this.$message({
type: 'info',
message: '操作已关闭',
duration: 1000
});
}
});
},
isValidAudioUrl(url) {
@@ -532,7 +487,7 @@ export default {
::v-deep .el-dialog {
border-radius: 8px !important;
overflow: hidden;
top: 8vh !important;
top: 1vh !important;
}
::v-deep .el-dialog__header {
@@ -628,13 +583,13 @@ export default {
.table-container {
flex: 1;
overflow-y: scroll;
scrollbar-width: none; /* Firefox */
padding-right: 15px; /* 为滚动条留出空间 */
width: calc(100% - 16px); /* 减去滚动条宽度 */
scrollbar-width: none;
padding-right: 15px;
width: calc(100% - 16px);
}
.table-container::-webkit-scrollbar {
display: none; /* Chrome/Safari */
display: none;
}
/* 自定义滚动条 */
@@ -684,10 +639,33 @@ export default {
display: none;
}
/* 音频播放器容器样式 */
.custom-audio-container {
width: 280px;
margin: auto;
}
/* 新增按钮组样式 */
.action-buttons {
bottom: 20px;
padding-top: 10px;
}
.edit-btn,
.delete-btn,
.save-btn {
margin: 0 8px;
color: #7079aa !important;
transition: all 0.3s;
}
.edit-btn:hover,
.delete-btn:hover,
.save-btn:hover {
color: #5f70f3 !important;
transform: scale(1.05);
}
.save-btn {
color: #5cca8e !important;
}
</style>
+81 -47
View File
@@ -3,7 +3,7 @@
<HeaderBar />
<div class="operation-bar">
<h2 class="page-title">模型配置</h2>
<h2 class="page-title">{{ modelTypeText }}</h2>
<!-- <div class="right-operations">-->
<!-- <el-button plain size="small" @click="handleImport" style="background: #7b9de5; color: white;">-->
<!-- <img loading="lazy" alt="" src="@/assets/model/inner_conf.png">-->
@@ -14,6 +14,21 @@
<!-- 导出配置-->
<!-- </el-button>-->
<!-- </div>-->
<div class="action-group">
<div class="search-group">
<el-input
placeholder="请输入模型名称查询"
v-model="search"
class="search-input"
clearable
@keyup.enter.native="handleSearch"
style="width: 240px"
/>
<el-button class="btn-search" @click="handleSearch">
搜索
</el-button>
</div>
</div>
</div>
<!-- 主体内容 -->
@@ -44,23 +59,6 @@
<!-- 右侧内容 -->
<div class="content-area">
<div class="title-bar">
<div class="title-wrapper">
<h2 class="model-title">{{ modelTypeText }}</h2>
<el-button type="primary" size="small" @click="addModel" class="add-btn">
添加
</el-button>
</div>
<div class="action-group">
<div class="search-group">
<el-input placeholder="请输入模型名称查询" v-model="search" size="small" class="search-input" clearable @keyup.enter.native="handleSearch" />
<el-button type="primary" size="small" class="search-btn" @click="handleSearch">
查询
</el-button>
</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">
@@ -103,9 +101,13 @@
<div class="table-footer">
<div class="batch-actions">
<el-button size="mini" @click="selectAll" style="width: 75px; background: #606ff3">{{ isAllSelected ?
'取消全选' : '全选'
}}</el-button>
<el-button size="mini" type="primary" @click="selectAll" >
{{ isAllSelected ?
'取消全选' : '全选' }}
</el-button>
<el-button type="success" size="mini" @click="addModel" class="add-btn">
新增
</el-button>
<el-button size="mini" type="danger" icon="el-icon-delete" @click="batchDelete">
删除
</el-button>
@@ -456,7 +458,7 @@ export default {
}
.main-wrapper {
margin: 5px 20px;
margin: 5px 22px;
border-radius: 15px;
min-height: 600px;
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
@@ -517,7 +519,7 @@ export default {
justify-content: flex-end;
padding-right: 12px !important;
width: fit-content;
margin: 8px 0px 8px auto;
margin: 8px 0 8px auto;
min-width: unset;
}
@@ -567,12 +569,6 @@ export default {
flex-wrap: nowrap;
}
.model-title {
font-size: 18px;
color: #303133;
margin: 0;
}
.action-group {
display: flex;
align-items: center;
@@ -581,28 +577,42 @@ export default {
.search-group {
display: flex;
gap: 8px;
gap: 10px;
}
.search-input {
width: 240px;
}
::v-deep .search-input .el-input__inner::placeholder {
color: black;
opacity: 0.6;
.btn-search {
background: linear-gradient(135deg, #6b8cff, #a966ff);
border: none;
color: white;
}
::v-deep .search-input .el-input__inner {
background: transparent;
border-radius: 4px;
border: 1px solid #DCDFE6;
background-color: white;
transition: border-color 0.2s;
}
.search-btn {
background: linear-gradient(135deg, #6B8CFF, #A966FF);
::v-deep .search-input .el-input__inner:focus {
border-color: #6b8cff;
outline: none;
}
.btn-search {
background: linear-gradient(135deg, #6b8cff, #a966ff);
border: none;
color: white;
}
.btn-search:hover {
opacity: 0.9;
transform: translateY(-1px);
}
.data-table {
border-radius: 6px;
overflow: hidden;
@@ -647,20 +657,45 @@ export default {
width: 100%;
}
.add-btn {
background: #cce5f9;
width: 75px;
border: none;
color: black;
padding: 8px 16px;
}
.title-wrapper {
display: flex;
align-items: center;
gap: 8px;
}
.batch-actions .el-button {
min-width: 72px;
height: 32px;
padding: 7px 12px 7px 10px;
font-size: 12px;
border-radius: 4px;
line-height: 1;
font-weight: 500;
border: none;
transition: all 0.3s ease;
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1);
}
.batch-actions .el-button:hover {
transform: translateY(-1px);
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15);
}
.batch-actions .el-button--primary {
background: #5f70f3 !important;
color: white;
}
.batch-actions .el-button--success {
background: #5bc98c;
color: white;
}
.batch-actions .el-button--danger {
background: #fd5b63;
color: white;
}
.batch-actions .el-button:first-child {
background: linear-gradient(135deg, #409EFF, #6B8CFF);
border: none;
@@ -686,7 +721,6 @@ export default {
::v-deep .el-table .custom-selection-header .cell .el-checkbox__inner {
display: none !important;
/* 使表头复选框不可见 */
}
::v-deep .el-table .custom-selection-header .cell::before {
@@ -741,8 +775,8 @@ export default {
}
::v-deep .el-checkbox__input.is-checked .el-checkbox__inner {
background-color: #409EFF !important;
border-color: #409EFF !important;
background-color: #5f70f3;
border-color: #5f70f3;
}
.voice-management-btn {
@@ -31,11 +31,12 @@
<div class="table_bottom">
<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">
{{ isAllSelected ? '取消全选' : '全选' }}
</el-button>
<el-button size="mini" type="success" @click="showAddDialog">新增</el-button>
<el-button size="mini" type="danger" icon="el-icon-delete"
@click="deleteParam($refs.paramsTable.selection)">删除</el-button>
@click="deleteParam($refs.paramsTable.selection)">删除</el-button>
</div>
<div class="custom-pagination">
<button class="pagination-btn" :disabled="currentPage === 1" @click="goFirst">
@@ -82,6 +83,7 @@ export default {
total: 0,
dialogVisible: false,
dialogTitle: "新增参数",
isAllSelected: false,
paramForm: {
id: null,
paramCode: "",
@@ -136,7 +138,12 @@ export default {
this.fetchParams();
},
handleSelectAll() {
this.$refs.paramsTable.toggleAllSelection();
if (this.isAllSelected) {
this.$refs.paramsTable.clearSelection();
} else {
this.$refs.paramsTable.toggleAllSelection();
}
this.isAllSelected = !this.isAllSelected;
},
showAddDialog() {
this.dialogTitle = "新增参数";
+10 -2
View File
@@ -41,7 +41,9 @@
<div class="table_bottom">
<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">
{{ isAllSelected ? '取消全选' : '全选' }}
</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>
@@ -89,6 +91,7 @@ export default {
currentPage: 1,
pageSize: 5,
total: 0,
isAllSelected: false
};
},
created() {
@@ -135,7 +138,12 @@ export default {
this.fetchUsers();
},
handleSelectAll() {
this.$refs.userTable.toggleAllSelection();
if (this.isAllSelected) {
this.$refs.userTable.clearSelection();
} else {
this.$refs.userTable.toggleAllSelection();
}
this.isAllSelected = !this.isAllSelected;
},
batchDelete() {
const selectedUsers = this.$refs.userTable.selection;