From 931daa6e9b792d6382ea772ba38aa757cab05b79 Mon Sep 17 00:00:00 2001 From: xiaoxia Date: Wed, 29 Jul 2026 22:40:48 +0800 Subject: [PATCH] =?UTF-8?q?refactor(assets):=20=E6=8B=86=E5=88=86=20batchO?= =?UTF-8?q?perations=20=E5=AD=90=E6=A8=A1=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../asset-operations/batch/useBatchTag.ts | 86 +++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 apps/web/src/pages/assets/hooks/asset-operations/batch/useBatchTag.ts 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 new file mode 100644 index 000000000..f55a14a5b --- /dev/null +++ b/apps/web/src/pages/assets/hooks/asset-operations/batch/useBatchTag.ts @@ -0,0 +1,86 @@ +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, + } +} \ No newline at end of file