Files
xiaoxia-saas/apps/web/src/pages/assets/hooks/useAssetOperations.ts
T
xiaoxia e48c96633d
PR Automation / Auto Approve on CI Green (pull_request) Successful in 1m5s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 1m7s
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 37s
CI/CD Pipeline / Validate - Type Check (mypy) (pull_request) Successful in 1m52s
CI/CD Pipeline / Validate - Migration (alembic) (pull_request) Successful in 1m52s
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Frontend Lint (pull_request) Successful in 2m52s
CI/CD Pipeline / PR Build Web Image (pull_request) Successful in 2m47s
CI/CD Pipeline / Validate - Code Quality (pull_request) Failing after 3m32s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 1m36s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m0s
CI/CD Pipeline / Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / Build Production API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (pull_request) Failing after 44s
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 5m51s
CI/CD Pipeline / CI Gate (pull_request) Successful in 5s
AI Code Review / AI Code Review (pull_request) Successful in 7m10s
Preview Cleanup / Cleanup Preview Environment (pull_request) Successful in 11s
ACR Cleanup / ACR Image Cleanup (pull_request_target) Successful in 11s
style: prettier格式化5个文件
2026-07-27 21:41:30 +08: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,
}
}