feat: 优化
This commit is contained in:
@@ -37,6 +37,9 @@
|
|||||||
<div v-if="column.key === 'name'" class="voice-name">
|
<div v-if="column.key === 'name'" class="voice-name">
|
||||||
{{ record.name || '未命名' }}
|
{{ record.name || '未命名' }}
|
||||||
</div>
|
</div>
|
||||||
|
<a-tooltip v-else-if="column.key === 'note'" :title="record.note" placement="topLeft">
|
||||||
|
<span class="note-text">{{ record.note || '-' }}</span>
|
||||||
|
</a-tooltip>
|
||||||
<span v-else-if="column.key === 'createTime'">
|
<span v-else-if="column.key === 'createTime'">
|
||||||
{{ formatDateTime(record.createTime) }}
|
{{ formatDateTime(record.createTime) }}
|
||||||
</span>
|
</span>
|
||||||
@@ -56,16 +59,18 @@
|
|||||||
<a-modal
|
<a-modal
|
||||||
v-model:open="modalVisible"
|
v-model:open="modalVisible"
|
||||||
:title="isCreateMode ? '新建配音' : '编辑配音'"
|
:title="isCreateMode ? '新建配音' : '编辑配音'"
|
||||||
:width="600"
|
:width="480"
|
||||||
ok-text="确定"
|
ok-text="保存"
|
||||||
cancel-text="取消"
|
cancel-text="取消"
|
||||||
:confirm-loading="submitting"
|
:confirm-loading="submitting"
|
||||||
|
:mask-closable="false"
|
||||||
|
centered
|
||||||
@ok="handleSubmit"
|
@ok="handleSubmit"
|
||||||
@cancel="handleCancel"
|
@cancel="handleCancel"
|
||||||
>
|
>
|
||||||
<a-form ref="formRef" :model="formData" :rules="formRules" layout="vertical">
|
<a-form ref="formRef" :model="formData" :rules="formRules" layout="vertical">
|
||||||
<a-form-item label="配音名称" name="name">
|
<a-form-item label="配音名称" name="name">
|
||||||
<a-input v-model:value="formData.name" placeholder="请输入配音名称" />
|
<a-input v-model:value="formData.name" placeholder="请输入配音名称" allow-clear />
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
|
||||||
<a-form-item
|
<a-form-item
|
||||||
@@ -74,28 +79,50 @@
|
|||||||
name="fileId"
|
name="fileId"
|
||||||
:rules="[{ required: true, message: '请上传音频文件' }]"
|
:rules="[{ required: true, message: '请上传音频文件' }]"
|
||||||
>
|
>
|
||||||
<a-upload
|
<div class="upload-area" :class="{ 'has-file': fileList.length > 0 }">
|
||||||
v-model:file-list="fileList"
|
<a-upload-dragger
|
||||||
:custom-request="handleCustomUpload"
|
v-model:file-list="fileList"
|
||||||
:before-upload="handleBeforeUpload"
|
:custom-request="handleCustomUpload"
|
||||||
:max-count="1"
|
:before-upload="handleBeforeUpload"
|
||||||
accept="audio/*,.mp3,.wav,.aac,.m4a,.flac,.ogg"
|
:max-count="1"
|
||||||
@remove="handleRemoveFile"
|
:show-upload-list="false"
|
||||||
@change="handleFileListChange"
|
accept="audio/*,.mp3,.wav,.aac,.m4a,.flac,.ogg"
|
||||||
>
|
@remove="handleRemoveFile"
|
||||||
<a-button type="primary" :loading="uploadState.uploading">
|
>
|
||||||
<UploadOutlined v-if="!uploadState.uploading" />
|
<template v-if="!uploadState.uploading && fileList.length === 0">
|
||||||
{{ uploadState.uploading ? '上传中...' : (fileList.length > 0 ? '重新上传' : '上传音频文件') }}
|
<div class="upload-icon">
|
||||||
</a-button>
|
<CloudUploadOutlined />
|
||||||
</a-upload>
|
</div>
|
||||||
<div class="upload-hint">
|
<p class="upload-text">点击或拖拽音频文件到此区域</p>
|
||||||
支持格式:MP3、WAV、AAC、M4A、FLAC、OGG,单个文件不超过 5MB<br>
|
<p class="upload-hint-inline">支持 MP3、WAV、AAC 等格式,最大 5MB</p>
|
||||||
<span class="hint-text">🎤 配音建议:使用 5-20 秒的短配音效果更佳</span>
|
</template>
|
||||||
|
<template v-else-if="uploadState.uploading">
|
||||||
|
<a-progress type="circle" :percent="50" :width="60" status="active" />
|
||||||
|
<p class="upload-text" style="margin-top: 12px">正在上传...</p>
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<div class="file-preview">
|
||||||
|
<SoundOutlined class="file-icon" />
|
||||||
|
<div class="file-info">
|
||||||
|
<span class="file-name">{{ fileList[0]?.name || '音频文件' }}</span>
|
||||||
|
<a-button type="link" size="small" danger @click.stop="handleRemoveFile">
|
||||||
|
<DeleteOutlined /> 移除
|
||||||
|
</a-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</a-upload-dragger>
|
||||||
</div>
|
</div>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
|
||||||
<a-form-item label="备注" name="note">
|
<a-form-item label="备注" name="note">
|
||||||
<a-textarea v-model="formData.note" :rows="3" placeholder="请输入备注信息" />
|
<a-textarea
|
||||||
|
v-model:value="formData.note"
|
||||||
|
:rows="2"
|
||||||
|
placeholder="备注信息(选填)"
|
||||||
|
:auto-size="{ minRows: 2, maxRows: 4 }"
|
||||||
|
allow-clear
|
||||||
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-form>
|
</a-form>
|
||||||
</a-modal>
|
</a-modal>
|
||||||
@@ -107,7 +134,7 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { ref, reactive, computed, onMounted } from 'vue'
|
import { ref, reactive, computed, onMounted } from 'vue'
|
||||||
import { message, Modal } from 'ant-design-vue'
|
import { message, Modal } from 'ant-design-vue'
|
||||||
import { PlusOutlined, SearchOutlined, UploadOutlined, PlayCircleOutlined } from '@ant-design/icons-vue'
|
import { PlusOutlined, SearchOutlined, PlayCircleOutlined, CloudUploadOutlined, SoundOutlined, DeleteOutlined } from '@ant-design/icons-vue'
|
||||||
import dayjs from 'dayjs'
|
import dayjs from 'dayjs'
|
||||||
import BasicLayout from '@/layouts/components/BasicLayout.vue'
|
import BasicLayout from '@/layouts/components/BasicLayout.vue'
|
||||||
import { MaterialService } from '@/api/material'
|
import { MaterialService } from '@/api/material'
|
||||||
@@ -170,9 +197,10 @@ const isCreateMode = computed(() => formMode.value === 'create')
|
|||||||
|
|
||||||
// ========== 表格配置 ==========
|
// ========== 表格配置 ==========
|
||||||
const columns = [
|
const columns = [
|
||||||
{ title: '配音名称', key: 'name', dataIndex: 'name', width: 200 },
|
{ title: '配音名称', key: 'name', dataIndex: 'name', width: 160 },
|
||||||
|
{ title: '备注', key: 'note', dataIndex: 'note', ellipsis: true },
|
||||||
{ title: '创建时间', key: 'createTime', dataIndex: 'createTime', width: 180 },
|
{ title: '创建时间', key: 'createTime', dataIndex: 'createTime', width: 180 },
|
||||||
{ title: '操作', key: 'actions', width: 90, fixed: 'right' }
|
{ title: '操作', key: 'actions', width: 100, fixed: 'right' }
|
||||||
]
|
]
|
||||||
|
|
||||||
// ========== 表单验证规则 ==========
|
// ========== 表单验证规则 ==========
|
||||||
@@ -362,15 +390,6 @@ async function fetchAudioTextById(fileId) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleFileListChange(info) {
|
|
||||||
const { fileList: newFileList } = info
|
|
||||||
if (newFileList) {
|
|
||||||
fileList.value = newFileList.filter(function(item) {
|
|
||||||
return item.status !== 'removed'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleRemoveFile() {
|
function handleRemoveFile() {
|
||||||
formData.fileId = null
|
formData.fileId = null
|
||||||
fileList.value = []
|
fileList.value = []
|
||||||
@@ -426,8 +445,8 @@ async function handleSubmit() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function handleCancel() {
|
function handleCancel() {
|
||||||
modalVisible.value = false
|
modalVisible.value = false
|
||||||
resetForm()
|
resetForm()
|
||||||
}
|
}
|
||||||
|
|
||||||
function resetForm() {
|
function resetForm() {
|
||||||
@@ -442,7 +461,7 @@ onMounted(function() {
|
|||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped lang="less">
|
||||||
.search-bar {
|
.search-bar {
|
||||||
background: var(--color-surface);
|
background: var(--color-surface);
|
||||||
border-radius: var(--radius-card);
|
border-radius: var(--radius-card);
|
||||||
@@ -459,10 +478,74 @@ onMounted(function() {
|
|||||||
color: var(--color-text);
|
color: var(--color-text);
|
||||||
}
|
}
|
||||||
|
|
||||||
.upload-hint {
|
.note-text {
|
||||||
font-size: 12px;
|
|
||||||
color: var(--color-text-secondary);
|
color: var(--color-text-secondary);
|
||||||
margin-top: 8px;
|
}
|
||||||
line-height: 1.5;
|
|
||||||
|
// 上传区域样式
|
||||||
|
.upload-area {
|
||||||
|
:deep(.ant-upload-drag) {
|
||||||
|
border: 2px dashed var(--color-border, #d9d9d9);
|
||||||
|
border-radius: 8px;
|
||||||
|
background: var(--color-bg-container, #fafafa);
|
||||||
|
transition: all 0.3s;
|
||||||
|
padding: 24px 16px;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
border-color: var(--color-primary, #1890ff);
|
||||||
|
background: var(--color-primary-bg, #e6f7ff);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.has-file :deep(.ant-upload-drag) {
|
||||||
|
border-style: solid;
|
||||||
|
border-color: var(--color-success-border, #b7eb8f);
|
||||||
|
background: var(--color-success-bg, #f6ffed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.upload-icon {
|
||||||
|
font-size: 40px;
|
||||||
|
color: var(--color-primary, #1890ff);
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.upload-text {
|
||||||
|
font-size: 14px;
|
||||||
|
color: var(--color-text, #333);
|
||||||
|
margin-bottom: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.upload-hint-inline {
|
||||||
|
font-size: 12px;
|
||||||
|
color: var(--color-text-secondary, #999);
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-preview {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 12px;
|
||||||
|
|
||||||
|
.file-icon {
|
||||||
|
font-size: 32px;
|
||||||
|
color: var(--color-primary, #1890ff);
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-info {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
gap: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-name {
|
||||||
|
font-size: 14px;
|
||||||
|
color: var(--color-text, #333);
|
||||||
|
max-width: 200px;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
Reference in New Issue
Block a user