Files
xiaoxia-saas/apps/web/src/pages/assets/hooks/useAssetOperations.ts
T
CI Bot 9eca947f88
CI/CD Pipeline / Check if frontend-only change (push) Has been cancelled
CI/CD Pipeline / Validate - Code Quality (push) Has been cancelled
CI/CD Pipeline / Validate - Type Check (mypy) (push) Has been cancelled
CI/CD Pipeline / Validate - Migration (alembic) (push) Has been cancelled
CI/CD Pipeline / Unit Tests (push) Has been cancelled
CI/CD Pipeline / Integration Tests (push) Has been cancelled
CI/CD Pipeline / Frontend Lint (push) Has been cancelled
CI/CD Pipeline / Frontend Unit Tests (push) Has been cancelled
CI/CD Pipeline / PR Build API Image (push) Has been cancelled
CI/CD Pipeline / PR Build Web Image (push) Has been cancelled
CI/CD Pipeline / PR Build Worker Image (push) Has been cancelled
CI/CD Pipeline / Build Staging API Image (push) Has been cancelled
CI/CD Pipeline / Build Staging Web Image (push) Has been cancelled
CI/CD Pipeline / Build Staging Worker Image (push) Has been cancelled
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Has been cancelled
CI/CD Pipeline / Staging E2E Tests (push) Has been cancelled
CI/CD Pipeline / Staging API Integration Tests (push) Has been cancelled
CI/CD Pipeline / Build Production API Image (push) Has been cancelled
CI/CD Pipeline / Build Production Web Image (push) Has been cancelled
CI/CD Pipeline / Build Production Worker Image (push) Has been cancelled
CI/CD Pipeline / Deploy Production (push) Has been cancelled
CI/CD Pipeline / Production Browser E2E (push) Has been cancelled
CI/CD Pipeline / ACR Image Cleanup (push) Has been cancelled
CI/CD Pipeline / Canary Release to Production (push) Has been cancelled
CI/CD Pipeline / CI Gate (push) Has been cancelled
style: auto-format with black + isort + prettier
2026-07-27 13:33:18 +00:00

133 lines
4.2 KiB
TypeScript

/**
* 素材操作 Hook(入口)
* 组合各子模块,保持导出不变
*
* 子模块位于 ./asset-operations/
*/
import { useState, useCallback } from "react"
import { useQueryClient } from "@tanstack/react-query"
import { useSingleOperations, useBatchHelpers } from "./asset-operations/useSingleOperations"
import {
useBatchDelete,
useBatchTag,
useBatchClassify,
useBatchMark,
} from "./asset-operations/batchOperations"
import type { BatchOperationResult } from "@/api/assets"
import type { SmartViewType } from "../components/BatchMarkModal"
interface UseAssetOperationsProps {
selectedIds: Set<string>
setSelectedIds: (ids: Set<string>) => void
}
export function useAssetOperations({ selectedIds, setSelectedIds }: UseAssetOperationsProps) {
const queryClient = useQueryClient()
/* ── 诊断状态 ── */
const [diagnosingId, setDiagnosingId] = useState<string | null>(null)
/* ── 操作结果 ── */
const [resultDrawerOpen, setResultDrawerOpen] = useState(false)
const [operationResult, setOperationResult] = useState<BatchOperationResult | null>(null)
const [operationTitle, setOperationTitle] = useState("")
/* ── 单个操作 ── */
const { handleDiagnose: handleDiagnoseRaw, handleSingleDelete } = useSingleOperations({
selectedIds,
setSelectedIds,
})
// 包装一下,加上 diagnosingId 状态
const handleDiagnose = useCallback(
async (asset: Parameters<typeof handleDiagnoseRaw>[0]) => {
setDiagnosingId(asset.id)
try {
await handleDiagnoseRaw(asset)
} finally {
setDiagnosingId(null)
}
},
[handleDiagnoseRaw],
)
/* ── 批量操作辅助 ── */
const { invalidateAssets } = useBatchHelpers({ queryClient, setSelectedIds })
// 包装 showResult 适配子模块的接口
const showResult = useCallback(
(result: BatchOperationResult, title: string, clearSelection = true) => {
setOperationResult(result)
setOperationTitle(title)
setResultDrawerOpen(true)
if (clearSelection) setSelectedIds(new Set())
},
[setSelectedIds],
)
/* ── 批量操作 ── */
const { batchLoading: deleteLoading, handleBatchDelete } = useBatchDelete({
selectedIds,
invalidateAssets,
showResult,
})
const tagResult = useBatchTag({ selectedIds, queryClient, showResult })
const classifyResult = useBatchClassify({ selectedIds, queryClient, showResult })
const markResult = useBatchMark({ selectedIds, queryClient, showResult })
// 取任一批量操作的 loading 状态(任意一个在加载都算加载中)
const batchLoading =
deleteLoading ||
tagResult.batchLoading ||
classifyResult.batchLoading ||
markResult.batchLoading
/* ── 关闭结果 Drawer ── */
const handleResultDrawerClose = useCallback(() => {
setResultDrawerOpen(false)
setOperationResult(null)
}, [])
return {
// 诊断
diagnosingId,
handleDiagnose,
// 单个操作
handleSingleDelete,
// 批量操作 loading
batchLoading,
// 批量打标签
tagModalOpen: tagResult.tagModalOpen,
setTagModalOpen: tagResult.setTagModalOpen,
batchTagInput: tagResult.batchTagInput,
setBatchTagInput: tagResult.setBatchTagInput,
batchTags: tagResult.batchTags,
setBatchTags: tagResult.setBatchTags,
tagMode: tagResult.tagMode,
setTagMode: tagResult.setTagMode,
handleBatchTag: tagResult.handleBatchTag,
handleTagInputKeyDown: tagResult.handleTagInputKeyDown,
removeBatchTag: tagResult.removeBatchTag,
// 批量改分类
classifyModalOpen: classifyResult.classifyModalOpen,
setClassifyModalOpen: classifyResult.setClassifyModalOpen,
batchCategory: classifyResult.batchCategory,
setBatchCategory: classifyResult.setBatchCategory,
handleBatchClassify: classifyResult.handleBatchClassify,
// 批量智能标记
markModalOpen: markResult.markModalOpen,
setMarkModalOpen: markResult.setMarkModalOpen,
batchSmartView: markResult.batchSmartView as SmartViewType,
setBatchSmartView: markResult.setBatchSmartView,
handleBatchMark: markResult.handleBatchMark,
// 批量删除
handleBatchDelete,
// 操作结果
resultDrawerOpen,
operationResult,
operationTitle,
handleResultDrawerClose,
}
}