style: format useSmartMatch.ts with prettier (#1899 #1900)
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Has been cancelled
CI/CD Pipeline / Check if frontend-only change (pull_request) Has been cancelled
CI/CD Pipeline / Validate - Style (pull_request) Has been cancelled
CI/CD Pipeline / Validate - Security (pull_request) Has been cancelled
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Has been cancelled
CI/CD Pipeline / Unit Tests (pull_request) Has been cancelled
CI/CD Pipeline / Integration Tests (pull_request) Has been cancelled
CI/CD Pipeline / Frontend Lint (pull_request) Has been cancelled
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been cancelled
CI/CD Pipeline / PR Build API Image (pull_request) Has been cancelled
CI/CD Pipeline / PR Build Web Image (pull_request) Has been cancelled
CI/CD Pipeline / PR Build Worker Image (pull_request) Has been cancelled
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
CI/CD Pipeline / Build Staging API Image (pull_request) Has been cancelled
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been cancelled
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been cancelled
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Has been cancelled
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Has been cancelled
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Has been cancelled
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been cancelled
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been cancelled
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been cancelled
CI/CD Pipeline / Build Production API Image (pull_request) Has been cancelled
CI/CD Pipeline / Build Production Web Image (pull_request) Has been cancelled
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been cancelled
CI/CD Pipeline / Deploy Production (pull_request) Has been cancelled
CI/CD Pipeline / Production Browser E2E (pull_request) Has been cancelled
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been cancelled
AI Code Review / AI Code Review (pull_request) Has been cancelled
CI/CD Pipeline / Canary Release to Production (pull_request) Has been cancelled
CI/CD Pipeline / CI Gate (pull_request) Has been cancelled
PR Automation / Auto Approve on CI Green (pull_request) Has been cancelled
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been cancelled
Preview Deploy / Deploy Preview Environment (pull_request) Has been cancelled

This commit is contained in:
2026-09-14 21:28:59 +08:00
parent 8fcb0c99b0
commit 517d05f9cc
@@ -1,32 +1,32 @@
import { useState, useCallback } from "react"
import { message } from "antd"
import type { AssetItem } from "@/api/assets"
import { smartMatchAssets, isAssetUsable } from "@/api/assets"
import { useState, useCallback } from "react";
import { message } from "antd";
import type { AssetItem } from "@/api/assets";
import { smartMatchAssets, isAssetUsable } from "@/api/assets";
interface UseSmartMatchOptions {
libraryId: string
materials: { items: AssetItem[]; total: number }
onSmartSelectedIdsChange: (ids: string[]) => void
libraryId: string;
materials: { items: AssetItem[]; total: number };
onSmartSelectedIdsChange: (ids: string[]) => void;
/** 片段数量(#1899) */
clipCount: number
clipCount: number;
}
/** 默认 limit(拿不到目标时长时的兜底上限) */
const DEFAULT_LIMIT = 30
const DEFAULT_LIMIT = 30;
/**
* 候选池放大倍数:批量 N 个变体独立选片、跨变体 20% 区间避让需要
* 足够大的素材池才能保证 N 条成片素材排布互不相同。
*/
const ASSET_POOL_MULTIPLIER = 3
const ASSET_POOL_MULTIPLIER = 3;
/**
* 根据片段数量计算智能匹配候选素材数量上限(#1899)。
* 候选池 = clipCount × 倍数;结果钳制到 [1, 200] 区间。
*/
export function computeLimitFromClipCount(clipCount: number): number {
if (clipCount <= 0) return DEFAULT_LIMIT
const limit = clipCount * ASSET_POOL_MULTIPLIER
return Math.max(1, Math.min(limit, 200))
if (clipCount <= 0) return DEFAULT_LIMIT;
const limit = clipCount * ASSET_POOL_MULTIPLIER;
return Math.max(1, Math.min(limit, 200));
}
/**
@@ -38,58 +38,62 @@ export function useSmartMatch({
onSmartSelectedIdsChange,
clipCount,
}: UseSmartMatchOptions) {
const [smartMatching, setSmartMatching] = useState(false)
const [hasMatched, setHasMatched] = useState(false)
const [smartMatching, setSmartMatching] = useState(false);
const [hasMatched, setHasMatched] = useState(false);
const handleSmartMatch = useCallback(async () => {
if (!libraryId) {
message.warning("请先选择视频库")
return
message.warning("请先选择视频库");
return;
}
const usableItems = materials.items.filter(isAssetUsable)
const usableItems = materials.items.filter(isAssetUsable);
if (usableItems.length === 0) {
message.warning(
materials.items.length === 0 ? "当前视频库暂无素材" : "素材可能已用尽,请先上传新素材",
)
return
materials.items.length === 0
? "当前视频库暂无素材"
: "素材可能已用尽,请先上传新素材",
);
return;
}
setSmartMatching(true)
setSmartMatching(true);
try {
const limit = computeLimitFromClipCount(clipCount)
const limit = computeLimitFromClipCount(clipCount);
const result = await smartMatchAssets(libraryId, limit)
const matched = (result.items ?? []).filter((a) => !!a?.id && isAssetUsable(a))
const matchedIds = matched.map((a: AssetItem) => a.id)
const result = await smartMatchAssets(libraryId, limit);
const matched = (result.items ?? []).filter(
(a) => !!a?.id && isAssetUsable(a),
);
const matchedIds = matched.map((a: AssetItem) => a.id);
if (matchedIds.length > 0) {
onSmartSelectedIdsChange(matchedIds)
setHasMatched(true)
message.success(`AI 已为你选择 ${matchedIds.length} 个素材`)
onSmartSelectedIdsChange(matchedIds);
setHasMatched(true);
message.success(`AI 已为你选择 ${matchedIds.length} 个素材`);
} else {
onSmartSelectedIdsChange(usableItems.map((a) => a.id))
setHasMatched(true)
message.info("AI 暂未找到匹配素材,已全选当前库素材")
onSmartSelectedIdsChange(usableItems.map((a) => a.id));
setHasMatched(true);
message.info("AI 暂未找到匹配素材,已全选当前库素材");
}
} catch {
onSmartSelectedIdsChange(usableItems.map((a) => a.id))
setHasMatched(true)
message.info("已为你全选当前库素材(智能匹配功能即将上线)")
onSmartSelectedIdsChange(usableItems.map((a) => a.id));
setHasMatched(true);
message.info("已为你全选当前库素材(智能匹配功能即将上线)");
} finally {
setSmartMatching(false)
setSmartMatching(false);
}
}, [libraryId, materials.items, onSmartSelectedIdsChange, clipCount])
}, [libraryId, materials.items, onSmartSelectedIdsChange, clipCount]);
const handleRefreshMatch = useCallback(async () => {
await handleSmartMatch()
}, [handleSmartMatch])
await handleSmartMatch();
}, [handleSmartMatch]);
return {
smartMatching,
hasMatched,
handleSmartMatch,
handleRefreshMatch,
}
};
}