|
|
@@ -0,0 +1,144 @@
|
|
|
+<script setup lang="ts">
|
|
|
+import { ElDialog, ElForm, ElFormItem, ElInput, ElDatePicker, ElButton, ElMessage, ElRadio } from 'element-plus'
|
|
|
+import { Plus } from '@element-plus/icons-vue'
|
|
|
+import type { FormInstance, FormRules } from 'element-plus'
|
|
|
+import { toast } from 'vue-sonner'
|
|
|
+import AudioFileUploader from '@/components/Uploader/AudioFileUploader.vue'
|
|
|
+import { cloneVoice } from '@/api/modules/voice'
|
|
|
+// 定义组件的属性
|
|
|
+interface Props {
|
|
|
+ visible: boolean
|
|
|
+}
|
|
|
+
|
|
|
+// 定义组件的事件
|
|
|
+interface Emits {
|
|
|
+ (e: 'update:visible', value: boolean): void
|
|
|
+ (e: 'cancel'): void
|
|
|
+ (e: 'refresh'): void
|
|
|
+}
|
|
|
+
|
|
|
+// 接收属性和事件
|
|
|
+const props = withDefaults(defineProps<Props>(), {
|
|
|
+ visible: false,
|
|
|
+})
|
|
|
+
|
|
|
+const emit = defineEmits<Emits>()
|
|
|
+
|
|
|
+const dialogVisible = computed({
|
|
|
+ get: () => props.visible,
|
|
|
+ set: (value) => {
|
|
|
+ // 这里可以触发一个事件来通知父组件更新 visible 的值
|
|
|
+ emit('update:visible', value);
|
|
|
+ },
|
|
|
+});
|
|
|
+// 表单引用
|
|
|
+const editFormRef = ref<FormInstance>();
|
|
|
+const cloneLoading = ref(false)
|
|
|
+const formData = ref<{gender: number, voiceName: string, audioUrl: string}>({
|
|
|
+ gender: 1,
|
|
|
+ voiceName: '',
|
|
|
+ audioUrl: '',
|
|
|
+});
|
|
|
+
|
|
|
+// 表单验证规则
|
|
|
+const formRules = ref<FormRules>({
|
|
|
+ voiceName: [
|
|
|
+ { required: true, message: '请输入名称', trigger: 'blur' },
|
|
|
+ ],
|
|
|
+ audioUrl: [
|
|
|
+ { required: true, message: '请输上传声音', trigger: 'blur' },
|
|
|
+ ],
|
|
|
+
|
|
|
+})
|
|
|
+
|
|
|
+function handleCancel() {
|
|
|
+ emit('cancel')
|
|
|
+ emit('update:visible', false)
|
|
|
+}
|
|
|
+
|
|
|
+function handleClose() {
|
|
|
+ emit('update:visible', false)
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+const handleUploadSuccess = (res: { code: number, data: { src: string, srcName: string, duration: number } }, file: any) => {
|
|
|
+ console.log(res, file)
|
|
|
+ if (res.code === 0) {
|
|
|
+ formData.value.voiceName = res.data.srcName
|
|
|
+ formData.value.audioUrl = res.data.src
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+const handleConfirm = async () => {
|
|
|
+ if(!editFormRef.value) return
|
|
|
+ const valid = await editFormRef.value.validate().catch(() => false)
|
|
|
+ if (!valid) {
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ cloneLoading.value = true
|
|
|
+
|
|
|
+ const {code, data} = await cloneVoice({
|
|
|
+ name: formData.value.voiceName,
|
|
|
+ audioUrl: formData.value.audioUrl,
|
|
|
+ gender: formData.value.gender
|
|
|
+ })
|
|
|
+ cloneLoading.value = false
|
|
|
+ console.log(code, data)
|
|
|
+ if(code === 0){
|
|
|
+ toast.success('克隆成功')
|
|
|
+ emit('refresh')
|
|
|
+ }
|
|
|
+
|
|
|
+ // 关闭对话框
|
|
|
+ emit('update:visible', false)
|
|
|
+}
|
|
|
+
|
|
|
+// 监听可见性变化
|
|
|
+watch(() => props.visible, (newVisible) => {
|
|
|
+ resetForm()
|
|
|
+})
|
|
|
+
|
|
|
+
|
|
|
+// 重置表单
|
|
|
+function resetForm() {
|
|
|
+ console.log('reset')
|
|
|
+ if (editFormRef.value) {
|
|
|
+ editFormRef.value.resetFields()
|
|
|
+ }
|
|
|
+ formData.value = {
|
|
|
+ audioUrl: '',
|
|
|
+ voiceName: '',
|
|
|
+ gender: 1,
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+</script>
|
|
|
+<template>
|
|
|
+ <ElDialog title="克隆声音" v-model="dialogVisible" align-center @close="handleClose"
|
|
|
+ width="400" :z-index="2000">
|
|
|
+ <ElForm ref="editFormRef" :model="formData" :rules="formRules" label-width="120px" class="mt-4 space-y-4 w-full" :disabled="cloneLoading">
|
|
|
+ <ElFormItem label="voice" prop="audioUrl" label-width="120">
|
|
|
+ <AudioFileUploader :disabled="cloneLoading" @on-success="handleUploadSuccess"><ElButton type="primary" :icon="Plus">上传声音</ElButton></AudioFileUploader>
|
|
|
+ </ElFormItem>
|
|
|
+
|
|
|
+ <ElFormItem label="voice name" prop="voiceName" label-width="120">
|
|
|
+ <ElInput v-model="formData.voiceName" :disabled="!formData.audioUrl.length" placeholder="Enter name" />
|
|
|
+ </ElFormItem>
|
|
|
+ <ElFormItem label="gender" prop="gender" label-width="120">
|
|
|
+ <ElSelect v-model="formData.gender" placeholder="选择性别" style="width: 120px; margin-bottom: 20px;">
|
|
|
+ <ElOption label="男声" :value="1"></ElOption>
|
|
|
+ <ElOption label="女声" :value="2"></ElOption>
|
|
|
+ </ElSelect>
|
|
|
+ </ElFormItem>
|
|
|
+ </ElForm>
|
|
|
+
|
|
|
+ <template #footer>
|
|
|
+ <div class="flex justify-end space-x-2">
|
|
|
+ <ElButton :loading="cloneLoading" type="primary" @click="handleConfirm" :disabled="cloneLoading">确定</ElButton>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </ElDialog>
|
|
|
+</template>
|