From 35dd478f1db9668628c5371b8ba20dd95c7c713a Mon Sep 17 00:00:00 2001
From: xiaoxia
Date: Mon, 27 Jul 2026 00:53:00 +0800
Subject: [PATCH 1/3] =?UTF-8?q?refactor(voice):=20=E6=8B=86=E5=88=86=20Upl?=
=?UTF-8?q?oadVoiceModal=EF=BC=8C=E6=8A=BD=E7=A6=BB=205=20=E4=B8=AA?=
=?UTF-8?q?=E5=AD=90=E7=BB=84=E4=BB=B6?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- UploadDragger: 拖拽上传区
- SelectedFileInfo: 已选文件信息
- UploadProgress: 上传进度条
- UploadFormFields: 表单区域(名称/性别/描述)
- UploadActions: 底部操作按钮(取消/上传)
- 主文件 329→112 行 (-66%),仅保留 Modal 壳与状态组装
---
.../voices/components/UploadVoiceModal.tsx | 315 +++---------------
.../upload-voice/SelectedFileInfo.tsx | 45 +++
.../components/upload-voice/UploadActions.tsx | 82 +++++
.../components/upload-voice/UploadDragger.tsx | 58 ++++
.../upload-voice/UploadFormFields.tsx | 114 +++++++
.../upload-voice/UploadProgress.tsx | 48 +++
6 files changed, 396 insertions(+), 266 deletions(-)
mode change 100755 => 100644 apps/web/src/pages/voices/components/UploadVoiceModal.tsx
create mode 100644 apps/web/src/pages/voices/components/upload-voice/SelectedFileInfo.tsx
create mode 100644 apps/web/src/pages/voices/components/upload-voice/UploadActions.tsx
create mode 100644 apps/web/src/pages/voices/components/upload-voice/UploadDragger.tsx
create mode 100644 apps/web/src/pages/voices/components/upload-voice/UploadFormFields.tsx
create mode 100644 apps/web/src/pages/voices/components/upload-voice/UploadProgress.tsx
diff --git a/apps/web/src/pages/voices/components/UploadVoiceModal.tsx b/apps/web/src/pages/voices/components/UploadVoiceModal.tsx
old mode 100755
new mode 100644
index 75aaff541..31f6b81fb
--- a/apps/web/src/pages/voices/components/UploadVoiceModal.tsx
+++ b/apps/web/src/pages/voices/components/UploadVoiceModal.tsx
@@ -1,8 +1,21 @@
+/**
+ * 上传音频弹窗
+ *
+ * 子组件目录: upload-voice/
+ * - UploadDragger: 拖拽上传区
+ * - SelectedFileInfo: 已选文件信息
+ * - UploadProgress: 上传进度条
+ * - UploadFormFields: 表单区域(名称/性别/描述)
+ * - UploadActions: 底部操作按钮
+ */
import React from "react"
-import { UploadOutlined, SoundOutlined } from "@ant-design/icons"
-import { Modal, Upload, message } from "antd"
+import { Modal } from "antd"
import { type VoiceGender } from "@/pages/voices/types"
-import { formatFileSize } from "@/pages/voices/utils/format"
+import UploadDragger from "./upload-voice/UploadDragger"
+import SelectedFileInfo from "./upload-voice/SelectedFileInfo"
+import UploadProgress from "./upload-voice/UploadProgress"
+import UploadFormFields from "./upload-voice/UploadFormFields"
+import UploadActions from "./upload-voice/UploadActions"
export interface UploadVoiceModalProps {
open: boolean
@@ -20,7 +33,6 @@ export interface UploadVoiceModalProps {
onUpload: () => void
}
-/** 上传音频弹窗 */
const UploadVoiceModal: React.FC = ({
open,
uploadFile,
@@ -36,17 +48,21 @@ const UploadVoiceModal: React.FC = ({
onDescChange,
onUpload,
}) => {
+ const isUploading = uploadProgress !== null
+
+ const handleClose = () => {
+ if (isUploading) return // 上传中不可关闭
+ onClose()
+ }
+
return (
{
- if (uploadProgress !== null) return // 上传中不可关闭
- onClose()
- }}
+ onCancel={handleClose}
footer={null}
width={520}
- maskClosable={uploadProgress === null}
+ maskClosable={!isUploading}
>
= ({
}}
>
{/* 拖拽上传区 */}
-
{
- onFileSelect(file)
- return false
- }}
- onRemove={() => {
- onFileRemove()
- }}
- showUploadList={false}
- disabled={uploadProgress !== null}
- >
-
-
-
-
- 点击或拖拽音频文件到此处
-
-
- 支持 MP3、WAV、AAC、FLAC 等格式,最大 200MB
-
-
+
{/* 已选文件信息 */}
- {uploadFile && (
-
-
-
-
- {uploadFile.name}
-
-
- {formatFileSize(uploadFile.size)}
-
-
-
- )}
+ {uploadFile &&
}
{/* 上传进度 */}
- {uploadProgress !== null && (
-
-
- {uploadProgress}%
-
-
- {uploadProgress < 100 ? "上传中..." : "处理中..."}
-
-
-
- )}
+ {isUploading &&
}
- {/* 名称 */}
-
-
- 素材名称
-
-
onNameChange(e.target.value)}
- placeholder="输入素材名称"
- maxLength={100}
- disabled={uploadProgress !== null}
- style={{
- width: "100%",
- padding: "8px 12px",
- border: "1px solid var(--border-color)",
- borderRadius: 8,
- fontSize: 13,
- background: "var(--bg-primary)",
- color: "var(--text-primary)",
- outline: "none",
- }}
- />
-
-
- {/* 性别选择 */}
-
-
- 音色性别
-
-
- {(["female", "male", "child"] as VoiceGender[]).map((g) => (
-
- ))}
-
-
-
- {/* 描述 */}
-
+ {/* 表单字段 */}
+
{/* 操作按钮 */}
-
-
-
-
+
)
diff --git a/apps/web/src/pages/voices/components/upload-voice/SelectedFileInfo.tsx b/apps/web/src/pages/voices/components/upload-voice/SelectedFileInfo.tsx
new file mode 100644
index 000000000..e7a71fc7d
--- /dev/null
+++ b/apps/web/src/pages/voices/components/upload-voice/SelectedFileInfo.tsx
@@ -0,0 +1,45 @@
+/**
+ * 上传音频 - 已选文件信息
+ */
+import React from "react"
+import { SoundOutlined } from "@ant-design/icons"
+import { formatFileSize } from "@/pages/voices/utils/format"
+
+export interface SelectedFileInfoProps {
+ file: File
+}
+
+export const SelectedFileInfo: React.FC = ({ file }) => {
+ return (
+
+
+
+
+ {file.name}
+
+
+ {formatFileSize(file.size)}
+
+
+
+ )
+}
+
+export default SelectedFileInfo
diff --git a/apps/web/src/pages/voices/components/upload-voice/UploadActions.tsx b/apps/web/src/pages/voices/components/upload-voice/UploadActions.tsx
new file mode 100644
index 000000000..74ceaa8ca
--- /dev/null
+++ b/apps/web/src/pages/voices/components/upload-voice/UploadActions.tsx
@@ -0,0 +1,82 @@
+/**
+ * 上传音频 - 底部操作按钮
+ */
+import React from "react"
+import { message } from "antd"
+
+export interface UploadActionsProps {
+ hasFile: boolean
+ hasName: boolean
+ uploading: boolean
+ onCancel: () => void
+ onUpload: () => void
+}
+
+export const UploadActions: React.FC = ({
+ hasFile,
+ hasName,
+ uploading,
+ onCancel,
+ onUpload,
+}) => {
+ const canUpload = hasFile && hasName && !uploading
+
+ const handleUploadClick = () => {
+ if (!hasFile) {
+ message.warning("请先选择音频文件")
+ return
+ }
+ if (!hasName) {
+ message.warning("请输入素材名称")
+ return
+ }
+ onUpload()
+ }
+
+ return (
+
+
+
+
+ )
+}
+
+export default UploadActions
diff --git a/apps/web/src/pages/voices/components/upload-voice/UploadDragger.tsx b/apps/web/src/pages/voices/components/upload-voice/UploadDragger.tsx
new file mode 100644
index 000000000..4f5143c60
--- /dev/null
+++ b/apps/web/src/pages/voices/components/upload-voice/UploadDragger.tsx
@@ -0,0 +1,58 @@
+/**
+ * 上传音频 - 拖拽上传区
+ */
+import React from "react"
+import { UploadOutlined } from "@ant-design/icons"
+import { Upload } from "antd"
+
+export interface UploadDraggerProps {
+ disabled: boolean
+ onFileSelect: (file: File) => void
+ onFileRemove: () => void
+}
+
+export const UploadDragger: React.FC = ({
+ disabled,
+ onFileSelect,
+ onFileRemove,
+}) => {
+ return (
+ {
+ onFileSelect(file)
+ return false
+ }}
+ onRemove={() => {
+ onFileRemove()
+ }}
+ showUploadList={false}
+ disabled={disabled}
+ >
+
+
+
+
+ 点击或拖拽音频文件到此处
+
+
+ 支持 MP3、WAV、AAC、FLAC 等格式,最大 200MB
+
+
+ )
+}
+
+export default UploadDragger
diff --git a/apps/web/src/pages/voices/components/upload-voice/UploadFormFields.tsx b/apps/web/src/pages/voices/components/upload-voice/UploadFormFields.tsx
new file mode 100644
index 000000000..8d398d40c
--- /dev/null
+++ b/apps/web/src/pages/voices/components/upload-voice/UploadFormFields.tsx
@@ -0,0 +1,114 @@
+/**
+ * 上传音频 - 表单区域(名称/性别/描述)
+ */
+import React from "react"
+import { type VoiceGender } from "@/pages/voices/types"
+
+export interface UploadFormFieldsProps {
+ name: string
+ gender: VoiceGender
+ description: string
+ disabled: boolean
+ onNameChange: (name: string) => void
+ onGenderChange: (gender: VoiceGender) => void
+ onDescriptionChange: (desc: string) => void
+}
+
+const GENDER_LABELS: Record = {
+ female: "女声",
+ male: "男声",
+ child: "童声",
+}
+
+export const UploadFormFields: React.FC = ({
+ name,
+ gender,
+ description,
+ disabled,
+ onNameChange,
+ onGenderChange,
+ onDescriptionChange,
+}) => {
+ return (
+ <>
+ {/* 名称 */}
+
+
素材名称
+
onNameChange(e.target.value)}
+ placeholder="输入素材名称"
+ maxLength={100}
+ disabled={disabled}
+ style={inputStyle}
+ />
+
+
+ {/* 性别选择 */}
+
+
音色性别
+
+ {(["female", "male", "child"] as VoiceGender[]).map((g) => (
+
+ ))}
+
+
+
+ {/* 描述 */}
+
+ >
+ )
+}
+
+const labelStyle: React.CSSProperties = {
+ fontSize: 13,
+ color: "var(--text-secondary)",
+ marginBottom: 6,
+}
+
+const inputStyle: React.CSSProperties = {
+ width: "100%",
+ padding: "8px 12px",
+ border: "1px solid var(--border-color)",
+ borderRadius: 8,
+ fontSize: 13,
+ background: "var(--bg-primary)",
+ color: "var(--text-primary)",
+ outline: "none",
+}
+
+export default UploadFormFields
diff --git a/apps/web/src/pages/voices/components/upload-voice/UploadProgress.tsx b/apps/web/src/pages/voices/components/upload-voice/UploadProgress.tsx
new file mode 100644
index 000000000..73bf92178
--- /dev/null
+++ b/apps/web/src/pages/voices/components/upload-voice/UploadProgress.tsx
@@ -0,0 +1,48 @@
+/**
+ * 上传音频 - 上传进度条
+ */
+import React from "react"
+
+export interface UploadProgressProps {
+ progress: number
+}
+
+export const UploadProgress: React.FC = ({ progress }) => {
+ return (
+
+
+ {progress}%
+
+
+ {progress < 100 ? "上传中..." : "处理中..."}
+
+
+
+ )
+}
+
+export default UploadProgress
--
2.54.0
From 7603aeca5cbd67e707639b3d23a2fd92290fcd53 Mon Sep 17 00:00:00 2001
From: xiaoxia
Date: Mon, 27 Jul 2026 12:44:47 +0800
Subject: [PATCH 2/3] =?UTF-8?q?fix(upload-voice):=20GENDER=5FLABELS=20?=
=?UTF-8?q?=E8=A1=A5=E5=85=85=20elderly=20=E9=80=89=E9=A1=B9=EF=BC=8C?=
=?UTF-8?q?=E4=BF=AE=E5=A4=8D=20TS2741?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../pages/voices/components/upload-voice/UploadFormFields.tsx | 1 +
1 file changed, 1 insertion(+)
diff --git a/apps/web/src/pages/voices/components/upload-voice/UploadFormFields.tsx b/apps/web/src/pages/voices/components/upload-voice/UploadFormFields.tsx
index 8d398d40c..0deb229ef 100644
--- a/apps/web/src/pages/voices/components/upload-voice/UploadFormFields.tsx
+++ b/apps/web/src/pages/voices/components/upload-voice/UploadFormFields.tsx
@@ -18,6 +18,7 @@ const GENDER_LABELS: Record = {
female: "女声",
male: "男声",
child: "童声",
+ elderly: "老年音",
}
export const UploadFormFields: React.FC = ({
--
2.54.0
From 4f3d7d3c1a392c87ddc64a6a949ff9078139078e Mon Sep 17 00:00:00 2001
From: xiaoxia
Date: Mon, 27 Jul 2026 15:35:22 +0800
Subject: [PATCH 3/3] =?UTF-8?q?fix(upload-voice):=20Prettier=20=E6=A0=BC?=
=?UTF-8?q?=E5=BC=8F=E5=8C=96=20UploadDragger.tsx?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../pages/voices/components/upload-voice/UploadDragger.tsx | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/apps/web/src/pages/voices/components/upload-voice/UploadDragger.tsx b/apps/web/src/pages/voices/components/upload-voice/UploadDragger.tsx
index 4f5143c60..b14bdd7a3 100644
--- a/apps/web/src/pages/voices/components/upload-voice/UploadDragger.tsx
+++ b/apps/web/src/pages/voices/components/upload-voice/UploadDragger.tsx
@@ -39,9 +39,7 @@ export const UploadDragger: React.FC = ({
>
-
- 点击或拖拽音频文件到此处
-
+ 点击或拖拽音频文件到此处