添加文件预览信息展示,统一按钮操作逻辑
This commit is contained in:
@@ -7,11 +7,13 @@ ENV = 'development'
|
|||||||
# 当前环境: 192.168.3.11(本地开发地址)
|
# 当前环境: 192.168.3.11(本地开发地址)
|
||||||
# 当前环境: 192.168.3.94(本地开发地址)王楠
|
# 当前环境: 192.168.3.94(本地开发地址)王楠
|
||||||
# 备用环境: 192.168.3.200(服务器地址)
|
# 备用环境: 192.168.3.200(服务器地址)
|
||||||
|
# 备用环境: 116.204.74.41(公网开发地址)
|
||||||
# ============================================================
|
# ============================================================
|
||||||
|
|
||||||
# 主服务地址(端口8808)
|
# 主服务地址(端口8808)
|
||||||
# 用途: 系统管理、用户认证、权限控制、模块开通等原有功能
|
# 用途: 系统管理、用户认证、权限控制、模块开通等原有功能
|
||||||
VITE_API_URL = 'http://116.204.74.41:8808/'
|
VITE_API_URL = 'http://192.168.3.94:8808/'
|
||||||
# 新功能服务地址(端口8000)
|
# 新功能服务地址(端口8000)
|
||||||
# 用途: 资产管理、分类、SKU、订单等新业务模块
|
# 用途: 资产管理、分类、SKU、订单等新业务模块
|
||||||
VITE_NEW_API_URL = 'http://116.204.74.41.8000/'
|
VITE_NEW_API_URL = 'http://192.168.3.94.8000/'
|
||||||
|
|
||||||
@@ -1,11 +1,61 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-dialog
|
<el-dialog
|
||||||
v-model="visible"
|
v-model="visible"
|
||||||
title="文本转语音"
|
title="添加音频"
|
||||||
width="700px"
|
width="700px"
|
||||||
:close-on-click-modal="false"
|
:close-on-click-modal="false"
|
||||||
@close="handleClose"
|
@close="handleClose"
|
||||||
>
|
>
|
||||||
|
<el-tabs v-model="activeTab" class="audio-tabs">
|
||||||
|
<el-tab-pane label="上传音频" name="upload">
|
||||||
|
<el-form ref="uploadFormRef" :model="uploadForm" :rules="uploadRules" label-width="100px">
|
||||||
|
<el-form-item label="音频名称" prop="name">
|
||||||
|
<el-input v-model="uploadForm.name" placeholder="请输入音频名称" maxlength="50" show-word-limit />
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item label="音色类型" prop="voiceType">
|
||||||
|
<el-select v-model="uploadForm.voiceType" placeholder="请选择音色类型" style="width: 100%">
|
||||||
|
<el-option label="男声" value="male" />
|
||||||
|
<el-option label="女声" value="female" />
|
||||||
|
<el-option label="童声" value="child" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item label="上传文件" prop="file">
|
||||||
|
<el-upload
|
||||||
|
ref="uploadRef"
|
||||||
|
class="audio-uploader"
|
||||||
|
drag
|
||||||
|
action="#"
|
||||||
|
:auto-upload="false"
|
||||||
|
:limit="1"
|
||||||
|
accept=".mp3,.wav,.pcm,.flac"
|
||||||
|
:on-change="handleFileChange"
|
||||||
|
:on-exceed="handleExceed"
|
||||||
|
>
|
||||||
|
<el-icon class="el-icon--upload"><ele-UploadFilled /></el-icon>
|
||||||
|
<div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
|
||||||
|
<template #tip>
|
||||||
|
<div class="el-upload__tip">支持 mp3、wav、pcm、flac 格式,文件大小不超过 50MB</div>
|
||||||
|
</template>
|
||||||
|
</el-upload>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<!-- 上传预览 -->
|
||||||
|
<div v-if="uploadPreview.show" class="preview-section">
|
||||||
|
<div class="preview-header">
|
||||||
|
<span class="preview-title">文件信息</span>
|
||||||
|
<el-tag type="success" size="small">已选择</el-tag>
|
||||||
|
</div>
|
||||||
|
<div class="preview-info">
|
||||||
|
<span>文件名: {{ uploadPreview.fileName }}</span>
|
||||||
|
<span>文件大小: {{ formatFileSize(uploadPreview.fileSize) }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-form>
|
||||||
|
</el-tab-pane>
|
||||||
|
|
||||||
|
<el-tab-pane label="文本转语音" name="tts">
|
||||||
<el-form ref="formRef" :model="form" :rules="rules" label-width="100px">
|
<el-form ref="formRef" :model="form" :rules="rules" label-width="100px">
|
||||||
<el-form-item label="音频名称" prop="name">
|
<el-form-item label="音频名称" prop="name">
|
||||||
<el-input v-model="form.name" placeholder="请输入音频名称" maxlength="50" show-word-limit />
|
<el-input v-model="form.name" placeholder="请输入音频名称" maxlength="50" show-word-limit />
|
||||||
@@ -81,7 +131,7 @@
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
|
|
||||||
<!-- 预览区域 -->
|
<!-- TTS预览区域 -->
|
||||||
<div v-if="previewGenerated" class="preview-section">
|
<div v-if="previewGenerated" class="preview-section">
|
||||||
<div class="preview-header">
|
<div class="preview-header">
|
||||||
<span class="preview-title">预览</span>
|
<span class="preview-title">预览</span>
|
||||||
@@ -111,10 +161,19 @@
|
|||||||
<span>采样率: {{ form.sampleRate }}Hz</span>
|
<span>采样率: {{ form.sampleRate }}Hz</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</el-tab-pane>
|
||||||
|
</el-tabs>
|
||||||
|
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<div class="dialog-footer">
|
<div class="dialog-footer">
|
||||||
<el-button @click="handleClose">取消</el-button>
|
<el-button @click="handleClose">取消</el-button>
|
||||||
|
<template v-if="activeTab === 'upload'">
|
||||||
|
<el-button type="primary" :loading="uploading" :disabled="!uploadPreview.show" @click="handleUpload">
|
||||||
|
<el-icon><ele-Upload /></el-icon>
|
||||||
|
{{ uploading ? '上传中...' : '上传音频' }}
|
||||||
|
</el-button>
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
<el-button type="warning" :loading="generating" @click="handleGenerate">
|
<el-button type="warning" :loading="generating" @click="handleGenerate">
|
||||||
<el-icon><ele-Headset /></el-icon>
|
<el-icon><ele-Headset /></el-icon>
|
||||||
{{ generating ? '生成中...' : '生成预览' }}
|
{{ generating ? '生成中...' : '生成预览' }}
|
||||||
@@ -123,6 +182,7 @@
|
|||||||
<el-icon><ele-Check /></el-icon>
|
<el-icon><ele-Check /></el-icon>
|
||||||
保存音频
|
保存音频
|
||||||
</el-button>
|
</el-button>
|
||||||
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
@@ -131,14 +191,18 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, reactive, watch } from 'vue';
|
import { ref, reactive, watch } from 'vue';
|
||||||
import { ElMessage } from 'element-plus';
|
import { ElMessage } from 'element-plus';
|
||||||
import type { FormInstance, FormRules } from 'element-plus';
|
import type { FormInstance, FormRules, UploadInstance, UploadFile, UploadRawFile } from 'element-plus';
|
||||||
|
|
||||||
const emit = defineEmits(['success']);
|
const emit = defineEmits(['success']);
|
||||||
|
|
||||||
const visible = ref(false);
|
const visible = ref(false);
|
||||||
|
const activeTab = ref('upload');
|
||||||
const formRef = ref<FormInstance>();
|
const formRef = ref<FormInstance>();
|
||||||
|
const uploadFormRef = ref<FormInstance>();
|
||||||
|
const uploadRef = ref<UploadInstance>();
|
||||||
const generating = ref(false);
|
const generating = ref(false);
|
||||||
const saving = ref(false);
|
const saving = ref(false);
|
||||||
|
const uploading = ref(false);
|
||||||
const previewGenerated = ref(false);
|
const previewGenerated = ref(false);
|
||||||
const isPlaying = ref(false);
|
const isPlaying = ref(false);
|
||||||
const playProgress = ref(0);
|
const playProgress = ref(0);
|
||||||
@@ -146,6 +210,21 @@ const previewDuration = ref(0);
|
|||||||
const previewFileSize = ref(0);
|
const previewFileSize = ref(0);
|
||||||
let progressTimer: ReturnType<typeof setInterval> | null = null;
|
let progressTimer: ReturnType<typeof setInterval> | null = null;
|
||||||
|
|
||||||
|
// 上传表单
|
||||||
|
const uploadForm = reactive({
|
||||||
|
name: '',
|
||||||
|
voiceType: '',
|
||||||
|
file: null as File | null,
|
||||||
|
});
|
||||||
|
|
||||||
|
// 上传预览信息
|
||||||
|
const uploadPreview = reactive({
|
||||||
|
show: false,
|
||||||
|
fileName: '',
|
||||||
|
fileSize: 0,
|
||||||
|
});
|
||||||
|
|
||||||
|
// TTS 表单
|
||||||
const form = reactive({
|
const form = reactive({
|
||||||
name: '',
|
name: '',
|
||||||
text: '',
|
text: '',
|
||||||
@@ -157,6 +236,13 @@ const form = reactive({
|
|||||||
format: 'mp3',
|
format: 'mp3',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 上传表单校验规则
|
||||||
|
const uploadRules = reactive<FormRules>({
|
||||||
|
name: [{ required: true, message: '请输入音频名称', trigger: 'blur' }],
|
||||||
|
voiceType: [{ required: true, message: '请选择音色类型', trigger: 'change' }],
|
||||||
|
});
|
||||||
|
|
||||||
|
// TTS 表单校验规则
|
||||||
const rules = reactive<FormRules>({
|
const rules = reactive<FormRules>({
|
||||||
name: [{ required: true, message: '请输入音频名称', trigger: 'blur' }],
|
name: [{ required: true, message: '请输入音频名称', trigger: 'blur' }],
|
||||||
text: [
|
text: [
|
||||||
@@ -174,6 +260,16 @@ const openDialog = () => {
|
|||||||
|
|
||||||
// 重置表单
|
// 重置表单
|
||||||
const resetForm = () => {
|
const resetForm = () => {
|
||||||
|
activeTab.value = 'upload';
|
||||||
|
// 重置上传表单
|
||||||
|
uploadForm.name = '';
|
||||||
|
uploadForm.voiceType = '';
|
||||||
|
uploadForm.file = null;
|
||||||
|
uploadPreview.show = false;
|
||||||
|
uploadPreview.fileName = '';
|
||||||
|
uploadPreview.fileSize = 0;
|
||||||
|
uploadRef.value?.clearFiles();
|
||||||
|
// 重置 TTS 表单
|
||||||
form.name = '';
|
form.name = '';
|
||||||
form.text = '';
|
form.text = '';
|
||||||
form.voice = 'female_sweet';
|
form.voice = 'female_sweet';
|
||||||
@@ -189,6 +285,62 @@ const resetForm = () => {
|
|||||||
previewFileSize.value = 0;
|
previewFileSize.value = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 文件选择变化
|
||||||
|
const handleFileChange = (file: UploadFile) => {
|
||||||
|
if (file.raw) {
|
||||||
|
const maxSize = 50 * 1024 * 1024; // 50MB
|
||||||
|
if (file.raw.size > maxSize) {
|
||||||
|
ElMessage.error('文件大小不能超过 50MB');
|
||||||
|
uploadRef.value?.clearFiles();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
uploadForm.file = file.raw;
|
||||||
|
uploadPreview.show = true;
|
||||||
|
uploadPreview.fileName = file.name;
|
||||||
|
uploadPreview.fileSize = file.raw.size;
|
||||||
|
// 自动填充音频名称
|
||||||
|
if (!uploadForm.name) {
|
||||||
|
uploadForm.name = file.name.replace(/\.[^/.]+$/, '');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 文件超出限制
|
||||||
|
const handleExceed = () => {
|
||||||
|
ElMessage.warning('只能上传一个文件,请先删除已选文件');
|
||||||
|
};
|
||||||
|
|
||||||
|
// 上传音频
|
||||||
|
const handleUpload = async () => {
|
||||||
|
if (!uploadFormRef.value) return;
|
||||||
|
|
||||||
|
await uploadFormRef.value.validate((valid) => {
|
||||||
|
if (!valid) return;
|
||||||
|
|
||||||
|
if (!uploadForm.file) {
|
||||||
|
ElMessage.warning('请选择要上传的音频文件');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uploading.value = true;
|
||||||
|
|
||||||
|
// 模拟上传过程
|
||||||
|
setTimeout(() => {
|
||||||
|
uploading.value = false;
|
||||||
|
ElMessage.success('音频上传成功');
|
||||||
|
emit('success', {
|
||||||
|
name: uploadForm.name,
|
||||||
|
voiceType: uploadForm.voiceType,
|
||||||
|
duration: Math.floor(Math.random() * 180) + 30,
|
||||||
|
fileSize: uploadPreview.fileSize,
|
||||||
|
sampleRate: 44100,
|
||||||
|
format: uploadPreview.fileName.split('.').pop(),
|
||||||
|
});
|
||||||
|
handleClose();
|
||||||
|
}, 1500);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
// 关闭弹窗
|
// 关闭弹窗
|
||||||
const handleClose = () => {
|
const handleClose = () => {
|
||||||
stopPreview();
|
stopPreview();
|
||||||
@@ -310,6 +462,20 @@ defineExpose({
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
|
.audio-tabs {
|
||||||
|
:deep(.el-tabs__content) {
|
||||||
|
padding: 10px 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.audio-uploader {
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
:deep(.el-upload-dragger) {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.preview-section {
|
.preview-section {
|
||||||
margin-top: 20px;
|
margin-top: 20px;
|
||||||
padding: 16px;
|
padding: 16px;
|
||||||
|
|||||||
@@ -30,11 +30,7 @@
|
|||||||
</el-button>
|
</el-button>
|
||||||
<el-button type="success" @click="handleAdd">
|
<el-button type="success" @click="handleAdd">
|
||||||
<el-icon><ele-Plus /></el-icon>
|
<el-icon><ele-Plus /></el-icon>
|
||||||
上传音频
|
添加音频
|
||||||
</el-button>
|
|
||||||
<el-button type="warning" @click="handleTts">
|
|
||||||
<el-icon><ele-Microphone /></el-icon>
|
|
||||||
文本转语音
|
|
||||||
</el-button>
|
</el-button>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
@@ -315,12 +311,8 @@ const handleReset = () => {
|
|||||||
|
|
||||||
const ttsDialogRef = ref<InstanceType<typeof TtsDialog>>();
|
const ttsDialogRef = ref<InstanceType<typeof TtsDialog>>();
|
||||||
|
|
||||||
|
// 打开添加音频弹窗
|
||||||
const handleAdd = () => {
|
const handleAdd = () => {
|
||||||
ElMessage.info('上传音频功能开发中...');
|
|
||||||
};
|
|
||||||
|
|
||||||
// 打开文本转语音弹窗
|
|
||||||
const handleTts = () => {
|
|
||||||
ttsDialogRef.value?.openDialog();
|
ttsDialogRef.value?.openDialog();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user