From f843b2d8942c7e96e6c7c341fc0dcbaf5383b8b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E5=BE=B7=E8=BE=89?= Date: Mon, 30 Jun 2025 09:27:45 +0800 Subject: [PATCH] fix --- ...ge_bg_api_v2_local_batch_change_bg_post.ts | 2 +- src/api/models/VideoTaskRequest.ts | 1 + ...ge_bg_api_v2_local_batch_change_bg_post.ts | 2 +- src/api/schemas/$VideoTaskRequest.ts | 4 +++ src/api/services/Service.ts | 11 +++++++ src/lib/indexeddb.ts | 7 +++-- src/pages/TryOnTasksPage/index.tsx | 30 ++++++++++++++----- src/pages/TryOnVideoTaskPage/index.tsx | 25 ++++++++-------- 8 files changed, 59 insertions(+), 23 deletions(-) diff --git a/src/api/models/Body_local_async_change_bg_api_v2_local_batch_change_bg_post.ts b/src/api/models/Body_local_async_change_bg_api_v2_local_batch_change_bg_post.ts index db607e9..c97008d 100644 --- a/src/api/models/Body_local_async_change_bg_api_v2_local_batch_change_bg_post.ts +++ b/src/api/models/Body_local_async_change_bg_api_v2_local_batch_change_bg_post.ts @@ -7,6 +7,6 @@ export type Body_local_async_change_bg_api_v2_local_batch_change_bg_post = { /** * 场景标签集合JSON字符串 */ - scenes_tags: string; + scenes_list: string; }; diff --git a/src/api/models/VideoTaskRequest.ts b/src/api/models/VideoTaskRequest.ts index e69f5ac..da32d35 100644 --- a/src/api/models/VideoTaskRequest.ts +++ b/src/api/models/VideoTaskRequest.ts @@ -5,6 +5,7 @@ export type VideoTaskRequest = { prompt: string; img_url: string; + task_id: string; duration?: string; }; diff --git a/src/api/schemas/$Body_local_async_change_bg_api_v2_local_batch_change_bg_post.ts b/src/api/schemas/$Body_local_async_change_bg_api_v2_local_batch_change_bg_post.ts index 267bbcb..9464e9e 100644 --- a/src/api/schemas/$Body_local_async_change_bg_api_v2_local_batch_change_bg_post.ts +++ b/src/api/schemas/$Body_local_async_change_bg_api_v2_local_batch_change_bg_post.ts @@ -12,7 +12,7 @@ export const $Body_local_async_change_bg_api_v2_local_batch_change_bg_post = { }, isRequired: true, }, - scenes_tags: { + scenes_list: { type: 'string', description: `场景标签集合JSON字符串`, isRequired: true, diff --git a/src/api/schemas/$VideoTaskRequest.ts b/src/api/schemas/$VideoTaskRequest.ts index 5399738..7c17ec5 100644 --- a/src/api/schemas/$VideoTaskRequest.ts +++ b/src/api/schemas/$VideoTaskRequest.ts @@ -12,6 +12,10 @@ export const $VideoTaskRequest = { type: 'string', isRequired: true, }, + task_id: { + type: 'string', + isRequired: true, + }, duration: { type: 'string', }, diff --git a/src/api/services/Service.ts b/src/api/services/Service.ts index 05daf27..21f8dd9 100644 --- a/src/api/services/Service.ts +++ b/src/api/services/Service.ts @@ -333,4 +333,15 @@ export class Service { url: '/api/tag/model/tag_list', }); } + /** + * 获取JM模型的提示词 + * @returns any Successful Response + * @throws ApiError + */ + public static fetchJmPromptApiConfigJmPromptGet(): CancelablePromise { + return __request(OpenAPI, { + method: 'GET', + url: '/api/config/jm/prompt', + }); + } } diff --git a/src/lib/indexeddb.ts b/src/lib/indexeddb.ts index 12955d1..e317c48 100644 --- a/src/lib/indexeddb.ts +++ b/src/lib/indexeddb.ts @@ -17,7 +17,7 @@ function openDB(): Promise { }); } -export async function addVideoTasks(tasks: { id: string; img_url: string; prompt: string; create_time: string; task_id: string }[]) { +export async function addVideoTasks(tasks: { id: string; img_url: string; prompt: string; create_time: string; job_id: string; task_id: string }[]) { const db = await openDB(); return new Promise((resolve, reject) => { const tx = db.transaction(STORE_NAME, 'readwrite'); @@ -39,7 +39,10 @@ export async function getAllVideoTasks(): Promise { }); } -export async function updateVideoTask(id: string, partial: Partial<{ img_url: string; prompt: string; create_time: string; task_id: string; video_url?: string }>) { +export async function updateVideoTask( + id: string, + partial: Partial<{ img_url: string; prompt: string; create_time: string; job_id: string; task_id: string; video_url?: string }> +) { const db = await openDB(); return new Promise((resolve, reject) => { const tx = db.transaction(STORE_NAME, 'readwrite'); diff --git a/src/pages/TryOnTasksPage/index.tsx b/src/pages/TryOnTasksPage/index.tsx index 6c02a23..fe910d6 100644 --- a/src/pages/TryOnTasksPage/index.tsx +++ b/src/pages/TryOnTasksPage/index.tsx @@ -9,17 +9,25 @@ import { Skeleton } from '@/components/ui/skeleton'; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter } from '@/components/ui/dialog'; import { Checkbox } from '@/components/ui/checkbox'; import { ACTION_PROMPTS } from '@/lib/prompt'; -import { Service } from '@/api/services/Service'; import { toast } from 'sonner'; import { addVideoTasks } from '@/lib/indexeddb'; +import type { BatchVideoTaskRequest } from '@/api'; const PAGE_SIZE = 10; +const promptGetter = (list: string[]) => { + let index = 0; + return () => { + index++; + return list[index % list.length]; + }; +}; + const TryOnTasksPage: React.FC = () => { const [page, setPage] = useState(1); const [previewImg, setPreviewImg] = useState(null); const [dialogOpen, setDialogOpen] = useState(false); - const [selectedRows, setSelectedRows] = useState<{ id: number; img_url: string }[]>([]); + const [selectedRows, setSelectedRows] = useState<{ id: number; img_url: string; task_id: string }[]>([]); const [createDialogOpen, setCreateDialogOpen] = useState(false); const [selectedPrompts, setSelectedPrompts] = useState([]); const [creating, setCreating] = useState(false); @@ -47,12 +55,12 @@ const TryOnTasksPage: React.FC = () => { const isAllCurrentPageSelected = currentPageIds.length > 0 && currentPageIds.every(id => isRowSelected(id)); // 单行选择 - const handleRowSelect = (item: { id: number; img_url?: string }) => { + const handleRowSelect = (item: { id: number; img_url?: string; task_id?: string }) => { setSelectedRows(prev => { if (isRowSelected(item.id)) { return prev.filter(row => row.id !== item.id); } else { - return [...prev, { id: item.id, img_url: item.img_url || '' }]; + return [...prev, { id: item.id, img_url: item.img_url || '', task_id: item.task_id || '' }]; } }); }; @@ -61,7 +69,9 @@ const TryOnTasksPage: React.FC = () => { if (isAllCurrentPageSelected) { setSelectedRows(prev => prev.filter(row => !currentPageIds.includes(row.id))); } else { - const toAdd = (data?.data || []).filter(item => !isRowSelected(item.id)).map(item => ({ id: item.id, img_url: item.img_url || '' })); + const toAdd = (data?.data || []) + .filter(item => !isRowSelected(item.id)) + .map(item => ({ id: item.id, img_url: item.img_url || '', task_id: item.task_id || '' })); setSelectedRows(prev => [...prev, ...toAdd]); } }; @@ -70,9 +80,14 @@ const TryOnTasksPage: React.FC = () => { const handleCreateTask = async () => { if (!selectedRows.length || !selectedPrompts.length) return; setCreating(true); + const getPrompt = promptGetter(selectedPrompts); try { - const tasks = selectedRows.flatMap(row => selectedPrompts.map(prompt => ({ prompt, img_url: row.img_url }))); - const res = (await Service.submitVideoTaskApiJmSubmitTaskPost({ requestBody: { tasks } })) as { + const tasks: BatchVideoTaskRequest['tasks'] = selectedRows.map(row => ({ + prompt: getPrompt(), + img_url: row.img_url, + task_id: row.task_id, + })); + const res = (await api.Service.submitVideoTaskApiJmSubmitTaskPost({ requestBody: { tasks } })) as { status: boolean; data: { success: { task_id: string; img_url: string }[]; failed: string[] }; msg: string; @@ -98,6 +113,7 @@ const TryOnTasksPage: React.FC = () => { img_url: item.img_url, prompt, create_time: new Date().toISOString(), + job_id: item.job_id, task_id: item.task_id, }; }); diff --git a/src/pages/TryOnVideoTaskPage/index.tsx b/src/pages/TryOnVideoTaskPage/index.tsx index d9f9500..95a2125 100644 --- a/src/pages/TryOnVideoTaskPage/index.tsx +++ b/src/pages/TryOnVideoTaskPage/index.tsx @@ -12,6 +12,7 @@ interface LocalVideoTask { img_url: string; prompt: string; create_time: string; + job_id: string; task_id: string; video_url?: string; } @@ -51,7 +52,7 @@ const TryOnVideoTaskPage: React.FC = () => { const newMap = { ...prev }; tasks.forEach(t => { if (t.video_url) { - newMap[t.task_id] = { status: 'finished', video_url: t.video_url }; + newMap[t.job_id] = { status: 'finished', video_url: t.video_url }; } }); return newMap; @@ -59,7 +60,7 @@ const TryOnVideoTaskPage: React.FC = () => { // 只查本地没有 video_url 的任务 const job_ids = tasks .filter(t => !t.video_url) - .map(t => t.task_id) + .map(t => t.job_id) .filter(Boolean); if (!job_ids.length) return; setStatusLoading(true); @@ -71,7 +72,7 @@ const TryOnVideoTaskPage: React.FC = () => { (res.data.finished || []).forEach((item: any) => { map[item.job_id] = { status: 'finished', video_url: item.video_url }; if (item.video_url) { - const localTask = tasks.find(t => t.task_id === item.job_id); + const localTask = tasks.find(t => t.job_id === item.job_id); if (localTask && !localTask.video_url) { updateVideoTask(localTask.id, { video_url: item.video_url }); setTasks(prev => prev.map(t => (t.id === localTask.id ? { ...t, video_url: item.video_url } : t))); @@ -91,7 +92,7 @@ const TryOnVideoTaskPage: React.FC = () => { }, [tasks]); const renderStatus = (task: LocalVideoTask) => { - const s = statusMap[task.task_id]; + const s = statusMap[task.job_id]; if (!s || !['finished', 'running', 'failed'].includes(s.status)) { return 未知; } @@ -110,7 +111,7 @@ const TryOnVideoTaskPage: React.FC = () => { }; // 计算可选的任务ID(已完成且有video_url) - const downloadableIds = tasks.filter(t => statusMap[t.task_id]?.status === 'finished' && statusMap[t.task_id]?.video_url).map(t => t.id); + const downloadableIds = tasks.filter(t => statusMap[t.job_id]?.status === 'finished' && statusMap[t.job_id]?.video_url).map(t => t.id); const isAllSelected = downloadableIds.length > 0 && downloadableIds.every(id => selectedIds.includes(id)); @@ -135,7 +136,7 @@ const TryOnVideoTaskPage: React.FC = () => { const selectedTasks = tasks.filter(t => selectedIds.includes(t.id)); let count = 0; for (const task of selectedTasks) { - const s = statusMap[task.task_id]; + const s = statusMap[task.job_id]; if (s?.status === 'finished' && s.video_url) { try { // 直接用 a 标签下载,避免 CORS @@ -156,7 +157,7 @@ const TryOnVideoTaskPage: React.FC = () => { }; return ( -
+

视频任务进度