diff --git a/apps/web/src/pages/generate/hooks/step2-materials/useSmartMatch.ts b/apps/web/src/pages/generate/hooks/step2-materials/useSmartMatch.ts index 98bb0840f..5c1220f4c 100755 --- a/apps/web/src/pages/generate/hooks/step2-materials/useSmartMatch.ts +++ b/apps/web/src/pages/generate/hooks/step2-materials/useSmartMatch.ts @@ -1,75 +1,75 @@ -import { useState, useCallback, useMemo } from "react" +import { useState, useCallback } from "react" import { message } from "antd" import type { AssetItem } from "@/api/assets" -import { SMART_MATCH_REASONS } from "../../constants" - -interface SmartMatchedResult { - asset: AssetItem - matchScore: number - matchReason: string -} +import { smartMatchAssets, getAssets } from "@/api/assets" interface UseSmartMatchOptions { + libraryId: string materials: { items: AssetItem[]; total: number } smartSelectedIds: string[] onSmartSelectedIdsChange: (ids: string[]) => void } /** - * 智能素材匹配 Hook - * 封装 AI 匹配、换一批、全选/清空等逻辑 + * 智能素材匹配 Hook(Q5 简化版) + * 用户不手动选素材时,一键调用后端 AI 选素材 + * 后端统一选素材逻辑后续完善,当前先走前端流程简化 */ export function useSmartMatch({ + libraryId, materials, smartSelectedIds, onSmartSelectedIdsChange, }: UseSmartMatchOptions) { - const [smartMatchInput, setSmartMatchInput] = useState("") const [smartMatching, setSmartMatching] = useState(false) - const [smartMatchedResults, setSmartMatchedResults] = useState([]) const [hasMatched, setHasMatched] = useState(false) - /* ── 智能素材匹配 ── */ + /* ── 一键智能匹配 ── */ const handleSmartMatch = useCallback(async () => { - if (!smartMatchInput.trim()) { - message.warning("请先输入视频内容描述") - return - } if (materials.items.length === 0) { message.warning("当前视频库暂无素材") return } setSmartMatching(true) - setHasMatched(true) - // 模拟 AI 匹配延迟 - await new Promise((resolve) => setTimeout(resolve, 1500)) + try { + // 调用后端智能匹配 API + const result = await smartMatchAssets(libraryId) + const matchedIds = result.items.map((a: AssetItem) => a.id) - // 从素材库中随机选取 5-8 个作为推荐结果 - const shuffled = [...materials.items].sort(() => Math.random() - 0.5) - const count = Math.min(shuffled.length, 5 + Math.floor(Math.random() * 4)) - const picked = shuffled.slice(0, count) + if (matchedIds.length > 0) { + onSmartSelectedIdsChange(matchedIds) + setHasMatched(true) + message.success(`AI 已为你选择 ${matchedIds.length} 个素材`) + } else { + // 后端返回空结果,回退到全选 + onSmartSelectedIdsChange(materials.items.map((a) => a.id)) + setHasMatched(true) + message.info("AI 暂未找到匹配素材,已全选当前库素材") + } + } catch { + // 后端 API 尚未就绪时,回退到全选当前库素材 + onSmartSelectedIdsChange(materials.items.map((a) => a.id)) + setHasMatched(true) + message.info("已为你全选当前库素材(智能匹配功能即将上线)") + } finally { + setSmartMatching(false) + } + }, [libraryId, materials.items, onSmartSelectedIdsChange]) - const results = picked.map((asset, idx) => ({ - asset, - matchScore: Math.round(85 + Math.random() * 14), // 85-99 分 - matchReason: - SMART_MATCH_REASONS[idx % SMART_MATCH_REASONS.length] + - (Math.random() > 0.5 ? ",画面质感优秀" : ""), - })) + const handleRefreshMatch = useCallback(async () => { + // 换一批 = 重新触发智能匹配 + await handleSmartMatch() + }, [handleSmartMatch]) - // 按匹配度从高到低排序 - results.sort((a, b) => b.matchScore - a.matchScore) + const handleSelectAllMatched = useCallback(() => { + onSmartSelectedIdsChange(materials.items.map((a) => a.id)) + }, [materials.items, onSmartSelectedIdsChange]) - setSmartMatchedResults(results) - // 默认选中匹配度 >= 90 的素材 - const defaultSelected = results.filter((r) => r.matchScore >= 90).map((r) => r.asset.id) - onSmartSelectedIdsChange( - defaultSelected.length > 0 ? defaultSelected : results.slice(0, 3).map((r) => r.asset.id), - ) - setSmartMatching(false) - }, [smartMatchInput, materials.items, onSmartSelectedIdsChange]) + const handleClearSmartSelect = useCallback(() => { + onSmartSelectedIdsChange([]) + }, [onSmartSelectedIdsChange]) const handleToggleSmartSelect = useCallback( (assetId: string) => { @@ -82,55 +82,13 @@ export function useSmartMatch({ [smartSelectedIds, onSmartSelectedIdsChange], ) - const handleRefreshMatch = useCallback(async () => { - if (materials.items.length <= 5) { - message.info("视频库素材较少,无法换一批") - return - } - setSmartMatching(true) - await new Promise((resolve) => setTimeout(resolve, 800)) - - const remaining = materials.items.filter( - (m) => !smartMatchedResults.some((r) => r.asset.id === m.id), - ) - const shuffled = [...remaining].sort(() => Math.random() - 0.5) - const count = Math.min(shuffled.length, 5 + Math.floor(Math.random() * 3)) - const picked = shuffled.slice(0, count) - - const results = picked.map((asset, idx) => ({ - asset, - matchScore: Math.round(80 + Math.random() * 19), - matchReason: - SMART_MATCH_REASONS[(idx + 2) % SMART_MATCH_REASONS.length] + - (Math.random() > 0.5 ? ",节奏明快" : ""), - })) - results.sort((a, b) => b.matchScore - a.matchScore) - - setSmartMatchedResults(results) - onSmartSelectedIdsChange([]) - setSmartMatching(false) - }, [materials.items, smartMatchedResults, onSmartSelectedIdsChange]) - - const handleSelectAllMatched = useCallback(() => { - onSmartSelectedIdsChange(smartMatchedResults.map((r) => r.asset.id)) - }, [smartMatchedResults, onSmartSelectedIdsChange]) - - const handleClearSmartSelect = useCallback(() => { - onSmartSelectedIdsChange([]) - }, [onSmartSelectedIdsChange]) - - /* ── 计算已选智能匹配素材的总时长 ── */ - const smartSelectedTotalDuration = useMemo(() => { - return smartMatchedResults - .filter((r) => smartSelectedIds.includes(r.asset.id)) - .reduce((sum, r) => sum + (r.asset.duration || 0), 0) - }, [smartMatchedResults, smartSelectedIds]) + /* ── 计算已选素材总时长 ── */ + const smartSelectedTotalDuration = materials.items + .filter((a) => smartSelectedIds.includes(a.id)) + .reduce((sum, a) => sum + (a.duration || 0), 0) return { - smartMatchInput, - setSmartMatchInput, smartMatching, - smartMatchedResults, hasMatched, smartSelectedIds, handleSmartMatch, @@ -141,3 +99,4 @@ export function useSmartMatch({ smartSelectedTotalDuration, } } +