From 1fe702c2f7c4dff0ce778f8d468976d60f33a8dc Mon Sep 17 00:00:00 2001 From: xiaoxia Date: Thu, 10 Sep 2026 12:41:21 +0800 Subject: [PATCH] =?UTF-8?q?chore:=20=E5=88=A0=E9=99=A4=E5=89=8D=E7=AB=AF?= =?UTF-8?q?=E5=86=97=E4=BD=99=E4=BB=A3=E7=A0=81=20(-1215=E8=A1=8C)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Issue #1831 - 前端冗余代码清理 删除 5 处死代码: - editing-planner/components/sticker/ (5文件, 已被 StickerPanel 替代) - editing-planner/components/tts/ (2文件, 已被 TtsPanel 替代) - editing-planner/components/pip-config/ (6文件, 已被 PipConfigPanel 替代) - asset-operations/batch/ (5文件, batch-operations 的完全重复副本) - asset-operations/batchOperations.ts (@deprecated 死代码) 附带修复: - test/pages/assets/smoke.test.tsx: batch/ → batch-operations/ import 路径 - test/pages/editing-planner/smoke.test.tsx: 删除 9 条失效 import 验证: - TypeScript tsc --noEmit 无新增错误 - assets / editing-planner smoke test 全部通过 - 全项目 grep 确认无残留引用 --- .../hooks/asset-operations/batch/index.ts | 4 - .../batch/useBatchClassify.ts | 58 ------ .../asset-operations/batch/useBatchDelete.ts | 40 ---- .../asset-operations/batch/useBatchMark.ts | 53 ------ .../asset-operations/batch/useBatchTag.ts | 86 --------- .../hooks/asset-operations/batchOperations.ts | 8 - .../components/pip-config/LayerConfig.tsx | 5 - .../components/pip-config/LayerList.tsx | 65 ------- .../layer-config/LayerPositionSize.tsx | 172 ------------------ .../layer-config/LayerTimingAnimation.tsx | 87 --------- .../pip-config/layer-config/PipPreview.tsx | 33 ---- .../pip-config/layer-config/index.tsx | 57 ------ .../components/sticker/StickerLibrary.tsx | 142 --------------- .../components/sticker/StickerList.tsx | 54 ------ .../components/sticker/StickerPreview.tsx | 39 ---- .../components/sticker/StickerPropsEditor.tsx | 130 ------------- .../sticker/TextStickerPropsEditor.tsx | 57 ------ .../components/tts/TtsSlider.tsx | 62 ------- .../components/tts/VoiceSelector.tsx | 50 ----- apps/web/src/test/pages/assets/smoke.test.tsx | 8 +- .../test/pages/editing-planner/smoke.test.tsx | 9 - 21 files changed, 4 insertions(+), 1215 deletions(-) delete mode 100644 apps/web/src/pages/assets/hooks/asset-operations/batch/index.ts delete mode 100644 apps/web/src/pages/assets/hooks/asset-operations/batch/useBatchClassify.ts delete mode 100644 apps/web/src/pages/assets/hooks/asset-operations/batch/useBatchDelete.ts delete mode 100644 apps/web/src/pages/assets/hooks/asset-operations/batch/useBatchMark.ts delete mode 100644 apps/web/src/pages/assets/hooks/asset-operations/batch/useBatchTag.ts delete mode 100644 apps/web/src/pages/assets/hooks/asset-operations/batchOperations.ts delete mode 100644 apps/web/src/pages/editing-planner/components/pip-config/LayerConfig.tsx delete mode 100644 apps/web/src/pages/editing-planner/components/pip-config/LayerList.tsx delete mode 100644 apps/web/src/pages/editing-planner/components/pip-config/layer-config/LayerPositionSize.tsx delete mode 100644 apps/web/src/pages/editing-planner/components/pip-config/layer-config/LayerTimingAnimation.tsx delete mode 100644 apps/web/src/pages/editing-planner/components/pip-config/layer-config/PipPreview.tsx delete mode 100644 apps/web/src/pages/editing-planner/components/pip-config/layer-config/index.tsx delete mode 100644 apps/web/src/pages/editing-planner/components/sticker/StickerLibrary.tsx delete mode 100644 apps/web/src/pages/editing-planner/components/sticker/StickerList.tsx delete mode 100755 apps/web/src/pages/editing-planner/components/sticker/StickerPreview.tsx delete mode 100755 apps/web/src/pages/editing-planner/components/sticker/StickerPropsEditor.tsx delete mode 100755 apps/web/src/pages/editing-planner/components/sticker/TextStickerPropsEditor.tsx delete mode 100755 apps/web/src/pages/editing-planner/components/tts/TtsSlider.tsx delete mode 100644 apps/web/src/pages/editing-planner/components/tts/VoiceSelector.tsx diff --git a/apps/web/src/pages/assets/hooks/asset-operations/batch/index.ts b/apps/web/src/pages/assets/hooks/asset-operations/batch/index.ts deleted file mode 100644 index fb51f0659..000000000 --- a/apps/web/src/pages/assets/hooks/asset-operations/batch/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export { useBatchDelete } from "./useBatchDelete" -export { useBatchTag } from "./useBatchTag" -export { useBatchClassify } from "./useBatchClassify" -export { useBatchMark } from "./useBatchMark" diff --git a/apps/web/src/pages/assets/hooks/asset-operations/batch/useBatchClassify.ts b/apps/web/src/pages/assets/hooks/asset-operations/batch/useBatchClassify.ts deleted file mode 100644 index 5ba8d6d37..000000000 --- a/apps/web/src/pages/assets/hooks/asset-operations/batch/useBatchClassify.ts +++ /dev/null @@ -1,58 +0,0 @@ -import { useState, useCallback } from "react" -import { message } from "antd" -import { batchClassifyAssets, type BatchOperationResult } from "@/api/assets" - -interface UseBatchClassifyOptions { - selectedIds: Set - queryClient: ReturnType - showResult: (result: BatchOperationResult, title: string, clear?: boolean) => void -} - -export const useBatchClassify = ({ - selectedIds, - queryClient, - showResult, -}: UseBatchClassifyOptions) => { - const [classifyModalOpen, setClassifyModalOpen] = useState(false) - const [batchCategory, setBatchCategory] = useState("") - const [batchLoading, setBatchLoading] = useState(false) - - const handleBatchClassify = useCallback(async () => { - if (!batchCategory) { - message.warning("请选择分类") - return - } - const ids = Array.from(selectedIds) - setBatchLoading(true) - try { - const result = await batchClassifyAssets({ - asset_ids: ids, - category: batchCategory, - }) - queryClient.invalidateQueries({ queryKey: ["assets"] }) - showResult(result, "批量改分类") - setClassifyModalOpen(false) - setBatchCategory("") - if (result.failure_count === 0) { - message.success(`成功将 ${result.success_count} 个素材改为「${batchCategory}」`) - } else { - message.warning( - `改分类完成:成功 ${result.success_count} 个,失败 ${result.failure_count} 个`, - ) - } - } catch { - message.error("批量改分类失败,请重试") - } finally { - setBatchLoading(false) - } - }, [batchCategory, selectedIds, queryClient, showResult]) - - return { - classifyModalOpen, - setClassifyModalOpen, - batchCategory, - setBatchCategory, - batchLoading, - handleBatchClassify, - } -} diff --git a/apps/web/src/pages/assets/hooks/asset-operations/batch/useBatchDelete.ts b/apps/web/src/pages/assets/hooks/asset-operations/batch/useBatchDelete.ts deleted file mode 100644 index b1243e1df..000000000 --- a/apps/web/src/pages/assets/hooks/asset-operations/batch/useBatchDelete.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { useState, useCallback } from "react" -import { message } from "antd" -import { batchDeleteAssets, type BatchOperationResult } from "@/api/assets" - -interface UseBatchDeleteOptions { - selectedIds: Set - invalidateAssets: () => void - showResult: (result: BatchOperationResult, title: string, clear?: boolean) => void -} - -export const useBatchDelete = ({ - selectedIds, - invalidateAssets, - showResult, -}: UseBatchDeleteOptions) => { - const [batchLoading, setBatchLoading] = useState(false) - - const handleBatchDelete = useCallback(async () => { - const ids = Array.from(selectedIds) - setBatchLoading(true) - try { - const result = await batchDeleteAssets(ids) - invalidateAssets() - showResult(result, "批量删除") - if (result.failure_count === 0) { - message.success(`成功删除 ${result.success_count} 个素材`) - } else { - message.warning( - `删除完成:成功 ${result.success_count} 个,失败 ${result.failure_count} 个`, - ) - } - } catch { - message.error("批量删除失败,请重试") - } finally { - setBatchLoading(false) - } - }, [selectedIds, invalidateAssets, showResult]) - - return { batchLoading, handleBatchDelete } -} diff --git a/apps/web/src/pages/assets/hooks/asset-operations/batch/useBatchMark.ts b/apps/web/src/pages/assets/hooks/asset-operations/batch/useBatchMark.ts deleted file mode 100644 index 296888b1a..000000000 --- a/apps/web/src/pages/assets/hooks/asset-operations/batch/useBatchMark.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { useState, useCallback } from "react" -import { message } from "antd" -import { batchMarkAssets, type BatchOperationResult } from "@/api/assets" -import type { SmartViewType } from "../../../components/BatchMarkModal" -import { SMART_VIEW_LABELS } from "../constants" - -interface UseBatchMarkOptions { - selectedIds: Set - queryClient: ReturnType - showResult: (result: BatchOperationResult, title: string, clear?: boolean) => void -} - -export const useBatchMark = ({ selectedIds, queryClient, showResult }: UseBatchMarkOptions) => { - const [markModalOpen, setMarkModalOpen] = useState(false) - const [batchSmartView, setBatchSmartView] = useState("recommended") - const [batchLoading, setBatchLoading] = useState(false) - - const handleBatchMark = useCallback(async () => { - const ids = Array.from(selectedIds) - setBatchLoading(true) - try { - const result = await batchMarkAssets({ - asset_ids: ids, - smart_view: batchSmartView, - }) - queryClient.invalidateQueries({ queryKey: ["assets"] }) - showResult(result, "批量智能标记") - setMarkModalOpen(false) - if (result.failure_count === 0) { - message.success( - `成功将 ${result.success_count} 个素材标记为「${SMART_VIEW_LABELS[batchSmartView]}」`, - ) - } else { - message.warning( - `智能标记完成:成功 ${result.success_count} 个,失败 ${result.failure_count} 个`, - ) - } - } catch { - message.error("批量智能标记失败,请重试") - } finally { - setBatchLoading(false) - } - }, [batchSmartView, selectedIds, queryClient, showResult]) - - return { - markModalOpen, - setMarkModalOpen, - batchSmartView, - setBatchSmartView, - batchLoading, - handleBatchMark, - } -} diff --git a/apps/web/src/pages/assets/hooks/asset-operations/batch/useBatchTag.ts b/apps/web/src/pages/assets/hooks/asset-operations/batch/useBatchTag.ts deleted file mode 100644 index 6f13ad359..000000000 --- a/apps/web/src/pages/assets/hooks/asset-operations/batch/useBatchTag.ts +++ /dev/null @@ -1,86 +0,0 @@ -import { useState, useCallback } from "react" -import { message } from "antd" -import { batchTagAssets, type BatchOperationResult } from "@/api/assets" - -interface UseBatchTagOptions { - selectedIds: Set - queryClient: ReturnType - showResult: (result: BatchOperationResult, title: string, clear?: boolean) => void -} - -export const useBatchTag = ({ selectedIds, queryClient, showResult }: UseBatchTagOptions) => { - const [tagModalOpen, setTagModalOpen] = useState(false) - const [batchTagInput, setBatchTagInput] = useState("") - const [batchTags, setBatchTags] = useState([]) - const [tagMode, setTagMode] = useState<"add" | "replace">("add") - const [batchLoading, setBatchLoading] = useState(false) - - const handleBatchTag = useCallback(async () => { - if (batchTags.length === 0) { - message.warning("请至少输入一个标签") - return - } - const ids = Array.from(selectedIds) - setBatchLoading(true) - try { - const result = await batchTagAssets({ - asset_ids: ids, - tags: batchTags, - mode: tagMode, - }) - queryClient.invalidateQueries({ queryKey: ["assets"] }) - showResult(result, "批量打标签") - setTagModalOpen(false) - setBatchTags([]) - setBatchTagInput("") - setTagMode("add") - if (result.failure_count === 0) { - message.success(`成功为 ${result.success_count} 个素材打标签`) - } else { - message.warning( - `打标签完成:成功 ${result.success_count} 个,失败 ${result.failure_count} 个`, - ) - } - } catch { - message.error("批量打标签失败,请重试") - } finally { - setBatchLoading(false) - } - }, [batchTags, selectedIds, tagMode, queryClient, showResult]) - - const handleTagInputKeyDown = useCallback( - (e: React.KeyboardEvent) => { - if (e.key === "Enter" && batchTagInput.trim()) { - e.preventDefault() - const tag = batchTagInput.trim() - if (!batchTags.includes(tag)) { - setBatchTags([...batchTags, tag]) - } - setBatchTagInput("") - } - }, - [batchTagInput, batchTags], - ) - - const removeBatchTag = useCallback( - (tag: string) => { - setBatchTags(batchTags.filter((t) => t !== tag)) - }, - [batchTags], - ) - - return { - tagModalOpen, - setTagModalOpen, - batchTagInput, - setBatchTagInput, - batchTags, - setBatchTags, - tagMode, - setTagMode, - batchLoading, - handleBatchTag, - handleTagInputKeyDown, - removeBatchTag, - } -} diff --git a/apps/web/src/pages/assets/hooks/asset-operations/batchOperations.ts b/apps/web/src/pages/assets/hooks/asset-operations/batchOperations.ts deleted file mode 100644 index 19399a7fb..000000000 --- a/apps/web/src/pages/assets/hooks/asset-operations/batchOperations.ts +++ /dev/null @@ -1,8 +0,0 @@ -/** - * @deprecated 请从 ./batch/ 目录导入子模块 - * 保持向后兼容,re-export 所有批量操作 Hook - */ -export { useBatchDelete } from "./batch/useBatchDelete" -export { useBatchTag } from "./batch/useBatchTag" -export { useBatchClassify } from "./batch/useBatchClassify" -export { useBatchMark } from "./batch/useBatchMark" diff --git a/apps/web/src/pages/editing-planner/components/pip-config/LayerConfig.tsx b/apps/web/src/pages/editing-planner/components/pip-config/LayerConfig.tsx deleted file mode 100644 index 7800c4f8c..000000000 --- a/apps/web/src/pages/editing-planner/components/pip-config/LayerConfig.tsx +++ /dev/null @@ -1,5 +0,0 @@ -/** - * LayerConfig 入口(向后兼容) - * 实际实现位于 ./layer-config/ 目录 - */ -export { default } from "./layer-config" diff --git a/apps/web/src/pages/editing-planner/components/pip-config/LayerList.tsx b/apps/web/src/pages/editing-planner/components/pip-config/LayerList.tsx deleted file mode 100644 index 3366c8c26..000000000 --- a/apps/web/src/pages/editing-planner/components/pip-config/LayerList.tsx +++ /dev/null @@ -1,65 +0,0 @@ -/** - * 混剪图层列表 - */ -import React from "react" -import type { PipLayer } from "@/pages/editing-planner/types" -import { LAYER_COLORS } from "@/pages/editing-planner/constants/pipConfig" - -interface LayerListProps { - layers: PipLayer[] - selectedId: string - onSelect: (id: string) => void - onAdd: () => void - onDelete: (id: string) => void -} - -const LayerList: React.FC = ({ layers, selectedId, onSelect, onAdd, onDelete }) => { - return ( -
-
- -
- {layers.length === 0 ? ( -
暂无图层,点击上方添加
- ) : ( - layers.map((layer, idx) => ( -
onSelect(layer.id)} - > - {layer.thumbnail_url || layer.material_url ? ( - {layer.name} - ) : ( -
- )} - {layer.name} - -
- )) - )} -
- ) -} - -export default LayerList diff --git a/apps/web/src/pages/editing-planner/components/pip-config/layer-config/LayerPositionSize.tsx b/apps/web/src/pages/editing-planner/components/pip-config/layer-config/LayerPositionSize.tsx deleted file mode 100644 index 6c6eb10a6..000000000 --- a/apps/web/src/pages/editing-planner/components/pip-config/layer-config/LayerPositionSize.tsx +++ /dev/null @@ -1,172 +0,0 @@ -import React from "react" -import type { PipLayer, PipGridPosition } from "@/pages/editing-planner/types" -import { GRID_POSITIONS } from "@/pages/editing-planner/constants/pipConfig" - -interface LayerPositionSizeProps { - layer: PipLayer - onUpdate: (id: string, partial: Partial) => void - onGridClick: (pos: PipGridPosition) => void - onWidthChange: (val: number) => void - onHeightChange: (val: number) => void -} - -/** - * 图层位置与尺寸配置面板 - */ -export const LayerPositionSize: React.FC = ({ - layer, - onUpdate, - onGridClick, - onWidthChange, - onHeightChange, -}) => ( - <> - {/* 素材类型 */} -
- -
- - -
-
- - {/* 素材 URL */} -
- - onUpdate(layer.id, { material_url: e.target.value })} - /> -
- - {/* 位置:九宫格 + 坐标 */} -
- -
-
- {GRID_POSITIONS.map((pos) => ( - - ))} -
-
-
- - onUpdate(layer.id, { x: Number(e.target.value) })} - /> -
-
- - onUpdate(layer.id, { y: Number(e.target.value) })} - /> -
-
-
-
- - {/* 尺寸 */} -
- -
- - onWidthChange(Number(e.target.value))} - /> - {layer.width}% -
-
- - onHeightChange(Number(e.target.value))} - /> - {layer.height}% -
-
onUpdate(layer.id, { aspect_lock: !layer.aspect_lock })} - > - {layer.aspect_lock ? "🔒" : "🔓"} - {layer.aspect_lock ? "已锁定比例" : "锁定宽高比"} -
-
- - {/* 圆角 */} -
- -
- onUpdate(layer.id, { border_radius: Number(e.target.value) })} - /> - {layer.border_radius}% -
-
- - {/* 透明度 */} -
- -
- onUpdate(layer.id, { opacity: Number(e.target.value) })} - /> - {layer.opacity}% -
-
- -) diff --git a/apps/web/src/pages/editing-planner/components/pip-config/layer-config/LayerTimingAnimation.tsx b/apps/web/src/pages/editing-planner/components/pip-config/layer-config/LayerTimingAnimation.tsx deleted file mode 100644 index a9138f5bc..000000000 --- a/apps/web/src/pages/editing-planner/components/pip-config/layer-config/LayerTimingAnimation.tsx +++ /dev/null @@ -1,87 +0,0 @@ -import React from "react" -import type { PipLayer, PipAnimType, PipSlideDirection } from "@/pages/editing-planner/types" -import { ANIM_OPTIONS, SLIDE_DIR_OPTIONS } from "@/pages/editing-planner/constants/pipConfig" - -interface LayerTimingAnimationProps { - layer: PipLayer - totalDuration: number - onUpdate: (id: string, partial: Partial) => void -} - -/** - * 图层时间与动画配置面板 - */ -export const LayerTimingAnimation: React.FC = ({ - layer, - totalDuration, - onUpdate, -}) => ( - <> - {/* 时间 */} -
- -
-
- - onUpdate(layer.id, { start_time: Number(e.target.value) })} - /> -
-
- - onUpdate(layer.id, { duration: Number(e.target.value) })} - /> -
-
-
- - {/* 入场动画 */} -
- - -
- - {/* 滑入方向(仅 slide_in 时显示) */} - {layer.animation === "slide_in" && ( -
- - -
- )} - -) diff --git a/apps/web/src/pages/editing-planner/components/pip-config/layer-config/PipPreview.tsx b/apps/web/src/pages/editing-planner/components/pip-config/layer-config/PipPreview.tsx deleted file mode 100644 index 6f4356eec..000000000 --- a/apps/web/src/pages/editing-planner/components/pip-config/layer-config/PipPreview.tsx +++ /dev/null @@ -1,33 +0,0 @@ -import React from "react" -import type { PipLayer } from "@/pages/editing-planner/types" -import { LAYER_COLORS } from "@/pages/editing-planner/constants/pipConfig" - -interface PipPreviewProps { - layers: PipLayer[] - selectedId: string -} - -/** - * PIP 图层迷你预览组件 - */ -export const PipPreview: React.FC = ({ layers, selectedId }) => ( -
- {layers.map((l, idx) => ( -
- {l.name} -
- ))} -
-) diff --git a/apps/web/src/pages/editing-planner/components/pip-config/layer-config/index.tsx b/apps/web/src/pages/editing-planner/components/pip-config/layer-config/index.tsx deleted file mode 100644 index 4f522e8cb..000000000 --- a/apps/web/src/pages/editing-planner/components/pip-config/layer-config/index.tsx +++ /dev/null @@ -1,57 +0,0 @@ -/** - * 混剪单图层配置区 - */ -import React from "react" -import type { PipLayer, PipGridPosition } from "@/pages/editing-planner/types" -import { PipPreview } from "./PipPreview" -import { LayerPositionSize } from "./LayerPositionSize" -import { LayerTimingAnimation } from "./LayerTimingAnimation" - -interface LayerConfigProps { - layer: PipLayer | null - layers: PipLayer[] - totalDuration: number - onUpdate: (id: string, partial: Partial) => void - onGridClick: (pos: PipGridPosition) => void - onWidthChange: (val: number) => void - onHeightChange: (val: number) => void -} - -const LayerConfig: React.FC = ({ - layer, - layers, - totalDuration, - onUpdate, - onGridClick, - onWidthChange, - onHeightChange, -}) => { - if (!layer) { - return ( -
-
选择或添加图层以配置
-
- ) - } - - return ( -
- {/* 迷你预览 */} - - - {/* 位置与尺寸 */} - - - {/* 时间与动画 */} - -
- ) -} - -export default LayerConfig diff --git a/apps/web/src/pages/editing-planner/components/sticker/StickerLibrary.tsx b/apps/web/src/pages/editing-planner/components/sticker/StickerLibrary.tsx deleted file mode 100644 index cfcdb9c47..000000000 --- a/apps/web/src/pages/editing-planner/components/sticker/StickerLibrary.tsx +++ /dev/null @@ -1,142 +0,0 @@ -/** - * 贴纸素材库(emoji / 图片 / 文字花字) - */ -import React, { useState } from "react" -import type { StickerType, TextStickerPreset } from "@/pages/editing-planner/types" -import { - EMOJI_LIST, - STICKER_TYPE_TABS, - TEXT_PRESET_STYLES, - TEXT_STICKER_PRESET_LABELS, -} from "@/pages/editing-planner/constants/sticker" - -interface StickerLibraryProps { - activeTab: StickerType - onTabChange: (tab: StickerType) => void - onAddSticker: (type: StickerType, content: string) => void -} - -const StickerLibrary: React.FC = ({ - activeTab, - onTabChange, - onAddSticker, -}) => { - const [textInput, setTextInput] = useState("") - const imageInputRef = React.useRef(null) - - const handleAddImage = () => { - const val = imageInputRef.current?.value.trim() - if (val) { - onAddSticker("image", val) - if (imageInputRef.current) imageInputRef.current.value = "" - } - } - - const handleAddText = () => { - if (textInput.trim()) { - onAddSticker("text", textInput.trim()) - setTextInput("") - } - } - - return ( - <> - {/* 类型 Tab */} -
- {STICKER_TYPE_TABS.map((t) => ( - - ))} -
- - {/* Tab 内容区 */} -
- {/* Emoji 素材库 */} - {activeTab === "emoji" && ( -
- {EMOJI_LIST.map((emoji) => ( - - ))} -
- )} - - {/* 图片贴纸 */} - {activeTab === "image" && ( -
- { - if (e.key === "Enter" && e.currentTarget.value.trim()) { - handleAddImage() - } - }} - /> - -
- )} - - {/* 文字花字 */} - {activeTab === "text" && ( -
-
- setTextInput(e.target.value)} - /> - -
-
-
花字预设预览
-
- {(Object.keys(TEXT_STICKER_PRESET_LABELS) as TextStickerPreset[]).map((p) => ( -
- 示例 -
{TEXT_STICKER_PRESET_LABELS[p]}
-
- ))} -
-
-
- )} -
- - ) -} - -export default StickerLibrary diff --git a/apps/web/src/pages/editing-planner/components/sticker/StickerList.tsx b/apps/web/src/pages/editing-planner/components/sticker/StickerList.tsx deleted file mode 100644 index b7285b534..000000000 --- a/apps/web/src/pages/editing-planner/components/sticker/StickerList.tsx +++ /dev/null @@ -1,54 +0,0 @@ -/** - * 已添加贴纸列表 - */ -import React from "react" -import type { StickerItem } from "@/pages/editing-planner/types" - -interface StickerListProps { - items: StickerItem[] - selectedId: string | null - onSelect: (id: string) => void - onDelete: (id: string) => void -} - -const StickerList: React.FC = ({ items, selectedId, onSelect, onDelete }) => { - if (items.length === 0) return null - - const getDisplayContent = (item: StickerItem) => { - if (item.type === "emoji") return { icon: item.content, name: "表情贴纸" } - if (item.type === "text") return { icon: "T", name: item.content.slice(0, 10) } - return { icon: "🖼", name: "图片贴纸" } - } - - return ( -
-
已添加贴纸 ({items.length})
-
- {items.map((item) => { - const { icon, name } = getDisplayContent(item) - return ( -
onSelect(item.id)} - > - {icon} - {name} - -
- ) - })} -
-
- ) -} - -export default StickerList diff --git a/apps/web/src/pages/editing-planner/components/sticker/StickerPreview.tsx b/apps/web/src/pages/editing-planner/components/sticker/StickerPreview.tsx deleted file mode 100755 index d14132b24..000000000 --- a/apps/web/src/pages/editing-planner/components/sticker/StickerPreview.tsx +++ /dev/null @@ -1,39 +0,0 @@ -import React from "react" -import type { StickerItem } from "@/pages/editing-planner/types" -import { TEXT_PRESET_STYLES } from "@/pages/editing-planner/constants/sticker" - -interface StickerPreviewProps { - sticker: StickerItem -} - -export const StickerPreview: React.FC = ({ sticker }) => ( -
-
- {sticker.type === "emoji" && sticker.content} - {sticker.type === "text" && sticker.content} - {sticker.type === "image" && ( - sticker - )} -
-
-) diff --git a/apps/web/src/pages/editing-planner/components/sticker/StickerPropsEditor.tsx b/apps/web/src/pages/editing-planner/components/sticker/StickerPropsEditor.tsx deleted file mode 100755 index 871b401ff..000000000 --- a/apps/web/src/pages/editing-planner/components/sticker/StickerPropsEditor.tsx +++ /dev/null @@ -1,130 +0,0 @@ -/** - * 选中贴纸的属性编辑器 - */ -import React from "react" -import type { StickerItem } from "@/pages/editing-planner/types" -import { StickerPreview } from "./StickerPreview" -import { TextStickerPropsEditor } from "./TextStickerPropsEditor" - -interface StickerPropsEditorProps { - sticker: StickerItem - totalDuration: number - onUpdate: (id: string, partial: Partial) => void -} - -const StickerPropsEditor: React.FC = ({ - sticker, - totalDuration, - onUpdate, -}) => { - return ( -
-
属性调整
- - {/* 位置 */} -
- 位置 X - onUpdate(sticker.id, { x: Number(e.target.value) })} - /> - {sticker.x}% -
-
- 位置 Y - onUpdate(sticker.id, { y: Number(e.target.value) })} - /> - {sticker.y}% -
- - {/* 尺寸 */} -
- 大小 - - onUpdate(sticker.id, { - width: Number(e.target.value), - height: Number(e.target.value), - }) - } - /> - {sticker.width}% -
- - {/* 旋转 */} -
- 旋转 - onUpdate(sticker.id, { rotation: Number(e.target.value) })} - /> - {sticker.rotation}° -
- - {/* 透明度 */} -
- 透明度 - onUpdate(sticker.id, { opacity: Number(e.target.value) })} - /> - {sticker.opacity}% -
- - {/* 时间 */} -
- 开始 - onUpdate(sticker.id, { start_time: Number(e.target.value) })} - /> - 时长 - onUpdate(sticker.id, { duration: Number(e.target.value) })} - /> -
- - {/* 文字贴纸特有属性 */} - - - {/* 预览 */} - -
- ) -} - -export default StickerPropsEditor diff --git a/apps/web/src/pages/editing-planner/components/sticker/TextStickerPropsEditor.tsx b/apps/web/src/pages/editing-planner/components/sticker/TextStickerPropsEditor.tsx deleted file mode 100755 index 2dd8bdebe..000000000 --- a/apps/web/src/pages/editing-planner/components/sticker/TextStickerPropsEditor.tsx +++ /dev/null @@ -1,57 +0,0 @@ -import React from "react" -import type { StickerItem, TextStickerPreset } from "@/pages/editing-planner/types" -import { TEXT_STICKER_PRESET_LABELS } from "@/pages/editing-planner/constants/sticker" - -interface TextStickerPropsEditorProps { - sticker: StickerItem - onUpdate: (id: string, partial: Partial) => void -} - -export const TextStickerPropsEditor: React.FC = ({ - sticker, - onUpdate, -}) => { - if (sticker.type !== "text") return null - - return ( - <> -
- 花字 - -
-
- 字号 - onUpdate(sticker.id, { font_size: Number(e.target.value) })} - /> - {sticker.font_size}px -
-
- 颜色 - onUpdate(sticker.id, { text_color: e.target.value })} - /> -
- - ) -} diff --git a/apps/web/src/pages/editing-planner/components/tts/TtsSlider.tsx b/apps/web/src/pages/editing-planner/components/tts/TtsSlider.tsx deleted file mode 100755 index 5f9d277c4..000000000 --- a/apps/web/src/pages/editing-planner/components/tts/TtsSlider.tsx +++ /dev/null @@ -1,62 +0,0 @@ -/** - * TTS 滑块组件(语速/语调/音量) - */ -import React from "react" -import { Slider } from "antd" - -interface TtsSliderProps { - label: string - value: number - min: number - max: number - step: number - unit?: string - onChange: (val: number) => void - marks?: string[] - tooltipFormatter?: (v: number) => string -} - -const TtsSlider: React.FC = ({ - label, - value, - min, - max, - step, - unit = "", - onChange, - marks, - tooltipFormatter, -}) => { - const displayValue = - unit === "x" - ? `${value.toFixed(2)}x` - : label === "语调" - ? `${value > 0 ? "+" : ""}${value} 半音` - : `${value}${unit}` - - return ( -
-
- {label} - {displayValue} -
- onChange(v as number)} - tooltip={tooltipFormatter ? { formatter: (v) => tooltipFormatter(v as number) } : undefined} - /> - {marks && ( -
- {marks.map((m, i) => ( - {m} - ))} -
- )} -
- ) -} - -export default TtsSlider diff --git a/apps/web/src/pages/editing-planner/components/tts/VoiceSelector.tsx b/apps/web/src/pages/editing-planner/components/tts/VoiceSelector.tsx deleted file mode 100644 index 6baa2afaf..000000000 --- a/apps/web/src/pages/editing-planner/components/tts/VoiceSelector.tsx +++ /dev/null @@ -1,50 +0,0 @@ -/** - * TTS 音色选择组件 - */ -import React from "react" -import type { TTSVoice } from "@/api/tts" -import { VOICE_CATEGORY_MAP } from "../../constants/tts" - -interface VoiceSelectorProps { - voices: TTSVoice[] - voicesLoading: boolean - selectedVoiceId: string - onVoiceSelect: (voiceId: string) => void -} - -const VoiceSelector: React.FC = ({ - voices, - voicesLoading, - selectedVoiceId, - onVoiceSelect, -}) => { - const voiceCategories = Object.entries(VOICE_CATEGORY_MAP) - - return ( -
-
- 选择音色 - {voicesLoading && 加载中...} -
-
- {voiceCategories.map(([cat, info]) => { - const voice = voices.find((v) => v.category === cat) - const isSelected = voice && selectedVoiceId === voice.id - return ( - - ) - })} -
-
- ) -} - -export default VoiceSelector diff --git a/apps/web/src/test/pages/assets/smoke.test.tsx b/apps/web/src/test/pages/assets/smoke.test.tsx index 1eba95ad5..36c7a1144 100644 --- a/apps/web/src/test/pages/assets/smoke.test.tsx +++ b/apps/web/src/test/pages/assets/smoke.test.tsx @@ -36,10 +36,10 @@ import "@/pages/assets/hooks/useLibraryManagement" import "@/pages/assets/hooks/useAssetUpload" import "@/pages/assets/hooks/useAssetSelection" import "@/pages/assets/hooks/useAssetOperations" -import "@/pages/assets/hooks/asset-operations/batch/useBatchDelete" -import "@/pages/assets/hooks/asset-operations/batch/useBatchTag" -import "@/pages/assets/hooks/asset-operations/batch/useBatchClassify" -import "@/pages/assets/hooks/asset-operations/batch/useBatchMark" +import "@/pages/assets/hooks/asset-operations/batch-operations/useBatchDelete" +import "@/pages/assets/hooks/asset-operations/batch-operations/useBatchTag" +import "@/pages/assets/hooks/asset-operations/batch-operations/useBatchClassify" +import "@/pages/assets/hooks/asset-operations/batch-operations/useBatchMark" describe("AssetLibrary module smoke test", () => { it("should load all asset modules", () => { diff --git a/apps/web/src/test/pages/editing-planner/smoke.test.tsx b/apps/web/src/test/pages/editing-planner/smoke.test.tsx index 35a1dc967..7c6860187 100755 --- a/apps/web/src/test/pages/editing-planner/smoke.test.tsx +++ b/apps/web/src/test/pages/editing-planner/smoke.test.tsx @@ -53,13 +53,6 @@ import "@/pages/editing-planner/components/clip-properties/SubtitleSettingsSecti import "@/pages/editing-planner/components/clip-properties/BgmSettingsSection" import "@/pages/editing-planner/components/clip-properties/ClipDetailSection" import "@/pages/editing-planner/components/clip-properties/StatsSection" -import "@/pages/editing-planner/components/pip-config/LayerList" -import "@/pages/editing-planner/components/pip-config/LayerConfig" -import "@/pages/editing-planner/components/sticker/StickerLibrary" -import "@/pages/editing-planner/components/sticker/StickerList" -import "@/pages/editing-planner/components/sticker/StickerPropsEditor" -import "@/pages/editing-planner/components/sticker/StickerPreview" -import "@/pages/editing-planner/components/sticker/TextStickerPropsEditor" import "@/pages/editing-planner/components/filter/FilterPresetGrid" import "@/pages/editing-planner/components/filter/FilterManualAdjust" import "@/pages/editing-planner/components/intro-outro/IntroOutroBlock" @@ -67,8 +60,6 @@ import "@/pages/editing-planner/components/subtitle-style/SubtitlePreview" import "@/pages/editing-planner/components/subtitle-style/SubtitleModeSwitch" import "@/pages/editing-planner/components/subtitle-style/SubtitlePositionSelector" import "@/pages/editing-planner/components/subtitle-style/SubtitleEffectButtons" -import "@/pages/editing-planner/components/tts/VoiceSelector" -import "@/pages/editing-planner/components/tts/TtsSlider" import "@/pages/editing-planner/components/watermark/WatermarkTypeTabs" import "@/pages/editing-planner/components/watermark/ImageWatermarkSection" import "@/pages/editing-planner/components/watermark/TextWatermarkSection"