diff --git a/api/common.ts b/api/common.ts index bb7f349..5139703 100644 --- a/api/common.ts +++ b/api/common.ts @@ -39,7 +39,7 @@ export const getUploadToken = async (timeoutMs: number = 10000): Promise<{ token // 添加超时控制 const controller = new AbortController() const timeoutId = setTimeout(() => { - console.log(`请求超时(${timeoutMs / 1000}秒),正在中断请求...`) + console.log(`Request timeout(${timeoutMs / 1000}s),aborting...`) controller.abort() }, timeoutMs) @@ -59,15 +59,15 @@ export const getUploadToken = async (timeoutMs: number = 10000): Promise<{ token if (!response.ok) { const errorText = await response.text() - console.error("获取token响应错误:", response.status, errorText) - throw new Error(`获取token失败: ${response.status} ${response.statusText}`) + console.error("Get token response error:", response.status, errorText) + throw new Error(`Get token failed: ${response.status} ${response.statusText}`) } const result: TokenWithDomainResponse | TokenResponse = await response.json() - console.log("获取token响应:", result) + console.log("Get token response:", result) if (result.code === 0 && result.successful && result.data.token) { - console.log("成功获取token") + console.log("Successfully get token") // Support both old and new API response formats const domain = 'domain' in result.data ? result.data.domain : 'cdn.qikongjian.com' return { @@ -75,17 +75,17 @@ export const getUploadToken = async (timeoutMs: number = 10000): Promise<{ token domain: domain } } else { - throw new Error(result.message || "获取token失败,服务器未返回有效token") + throw new Error(result.message || "Get token failed, server did not return a valid token") } } catch (error) { clearTimeout(timeoutId) - console.error("获取上传token失败:", error) + console.error("Get upload token failed:", error) if (error instanceof Error) { if (error.name === "AbortError") { - throw new Error("请求超时,请检查网络连接") + throw new Error("Request timeout, please check your network connection") } else if (error.message.includes("Failed to fetch")) { - throw new Error("网络连接失败,可能是CORS策略限制或服务器不可达") + throw new Error("Network connection failed, possibly due to CORS policy or server unreachable") } } @@ -129,25 +129,25 @@ export const uploadToQiniu = async ( try { const response: QiniuUploadResponse = JSON.parse(xhr.responseText) const qiniuUrl = `https://cdn.qikongjian.com/${response.key || uniqueFileName}` - console.log("七牛云上传成功:", response) + console.log("Qiniu cloud upload success:", response) resolve(qiniuUrl) } catch (error) { - console.error("解析响应失败:", error, "原始响应:", xhr.responseText) - reject(new Error(`解析上传响应失败: ${xhr.responseText}`)) + console.error("Parse response failed:", error, "Original response:", xhr.responseText) + reject(new Error(`Parse upload response failed: ${xhr.responseText}`)) } } else { - console.error("七牛云上传失败:", xhr.status, xhr.statusText, xhr.responseText) - reject(new Error(`上传失败: ${xhr.status} ${xhr.statusText}`)) + console.error("Qiniu cloud upload failed:", xhr.status, xhr.statusText, xhr.responseText) + reject(new Error(`Upload failed: ${xhr.status} ${xhr.statusText}`)) } }) xhr.addEventListener("error", (e) => { - console.error("上传网络错误:", e) - reject(new Error("网络错误,上传失败")) + console.error("Upload network error:", e) + reject(new Error("Network error, upload failed")) }) xhr.addEventListener("abort", () => { - reject(new Error("上传被取消")) + reject(new Error("Upload aborted")) }) xhr.open("POST", "https://up-z2.qiniup.com") diff --git a/api/constants.ts b/api/constants.ts index ba0be3f..1d081a8 100644 --- a/api/constants.ts +++ b/api/constants.ts @@ -1,3 +1,3 @@ -export const BASE_URL = process.env.NEXT_PUBLIC_BASE_URL -// export const BASE_URL ='http://192.168.120.36:8000' +// export const BASE_URL = process.env.NEXT_PUBLIC_BASE_URL +export const BASE_URL ='http://192.168.120.5:8000' // diff --git a/api/create_movie.ts b/api/create_movie.ts new file mode 100644 index 0000000..d24446e --- /dev/null +++ b/api/create_movie.ts @@ -0,0 +1,39 @@ +import { + CreateMovieProjectV2Request, + CreateMovieProjectV3Request, +} from "./DTO/movie_start_dto"; +import { post } from "./request"; + +import { withQueuePolling, QueueResponse } from './movie_queue'; + +// 新-创建接口 +export const createMovieProject = async (data: any): Promise => { + const apiCall = (params: any) => post('/movie/create_movie_project', params); + return withQueuePolling(apiCall, data); +}; + +/** + * 创建电影项目V2 + * @param request - 创建项目请求参数 + * @returns Promise + */ +export const createMovieProjectV2 = async ( + request: CreateMovieProjectV2Request +): Promise => { + const apiCall = (params: CreateMovieProjectV2Request) => + post("/movie/create_movie_project_v2", params); + return withQueuePolling(apiCall, request); +}; + +/** + * 创建电影项目V3 + * @param request - 创建项目请求参数 + * @returns Promise + */ +export const createMovieProjectV3 = async ( + request: CreateMovieProjectV3Request +): Promise => { + const apiCall = (params: CreateMovieProjectV3Request) => + post("/movie/create_movie_project_v3", params); + return withQueuePolling(apiCall, request); +}; \ No newline at end of file diff --git a/api/errorHandle.ts b/api/errorHandle.ts index 6fdac06..dda1351 100644 --- a/api/errorHandle.ts +++ b/api/errorHandle.ts @@ -15,6 +15,7 @@ const HTTP_ERROR_MESSAGES: Record = { 502: "Gateway error, please try again later.", 503: "Service temporarily unavailable, please try again later.", 504: "Gateway timeout, please try again later.", + 4001: "Insufficient points, please recharge.", }; /** @@ -32,7 +33,7 @@ const ERROR_HANDLERS: Record void> = { // 跳转到登录页面 window.location.href = '/login'; }, - 403: () => { + 4001: () => { // 显示积分不足通知 import('../utils/notifications').then(({ showInsufficientPointsNotification }) => { showInsufficientPointsNotification(); diff --git a/api/movie_queue.ts b/api/movie_queue.ts new file mode 100644 index 0000000..6e95690 --- /dev/null +++ b/api/movie_queue.ts @@ -0,0 +1,161 @@ +import { ApiResponse } from './common'; +import { showQueueNotification } from '../components/QueueBox/QueueNotification2'; +import { notification } from 'antd'; + +/** 队列状态枚举 */ +export enum QueueStatus { + WAIT = 'wait', // 排队等待中 + READY = 'ready', // 可以开始处理 + PROCESS = 'process' // 处理中 +} + +/** 队列响应数据接口 */ +export interface QueueResponseData { + status: QueueStatus; + position?: number; + queue_length?: number; + waiting?: number; + message?: string; +} + +/** 队列响应接口 */ +export interface QueueResponse extends ApiResponse { + code: number; + message: string; + data: QueueResponseData; +} + +/** + * 处理API轮询的配置选项 + */ +interface PollConfig { + /** 轮询间隔(ms), 默认10000ms */ + interval?: number; + /** 最大轮询次数, 默认120次(20分钟) */ + maxAttempts?: number; + /** 轮询成功后的回调 */ + onSuccess?: (data: any) => void; + /** 轮询失败后的回调 */ + onError?: (error: Error) => void; + /** 每次轮询时的回调 */ + onPolling?: (data: QueueResponseData) => void; + /** 取消轮询时的回调 */ + onCancel?: () => void; +} + +// 用于存储取消函数的映射 +const cancelTokens = new Map void>(); + +/** + * 统一的队列API调用封装 + */ +export async function withQueuePolling( + apiCall: (params: T) => Promise, + params: T, + config: PollConfig = {} +): Promise { + const { + interval = 10000, + maxAttempts = 120, + onSuccess, + onError, + onPolling, + onCancel + } = config; + + let attempts = 0; + let lastNotificationPosition: number | undefined; + let isCancelled = false; + + // 生成唯一的轮询ID + const pollId = Math.random().toString(36).substring(7); + + // 创建取消函数 + const cancel = () => { + isCancelled = true; + notification.destroy(); // 关闭通知 + onCancel?.(); + cancelTokens.delete(pollId); + }; + + // 存储取消函数 + cancelTokens.set(pollId, cancel); + + const poll = async (): Promise => { + try { + if (isCancelled) { + throw new Error('操作已取消'); + } + + const response = await apiCall(params); + + // 处理队列状态 + if (response.code === 202 && + (response.data.status === QueueStatus.WAIT || response.data.status === QueueStatus.PROCESS)) { + attempts++; + + // 获取队列位置和等待时间 + const { position, waiting, status } = response.data; + + // 如果位置发生变化,更新通知 + if ((position !== lastNotificationPosition || status === QueueStatus.PROCESS) && + position !== undefined && waiting !== undefined) { + showQueueNotification(position, waiting, status, cancel); + lastNotificationPosition = position; + } + + // 调用轮询回调 + onPolling?.(response.data); + + // 检查是否达到最大尝试次数 + if (attempts >= maxAttempts) { + notification.destroy(); // 关闭通知 + throw new Error('超过最大轮询次数限制'); + } + + // 继续轮询 + await new Promise(resolve => setTimeout(resolve, interval)); + return poll(); + } + + // 如果状态为ready,结束轮询 + if (response.code !== 202 && response.data) { + notification.destroy(); // 关闭通知 + onSuccess?.(response.data); + return response; + } + + notification.destroy(); // 关闭通知 + return response; + } catch (error) { + notification.destroy(); // 关闭通知 + if (error instanceof Error) { + onError?.(error); + } + throw error; + } finally { + cancelTokens.delete(pollId); + } + }; + + return poll(); +} + +/** + * 取消指定的轮询 + */ +export function cancelPolling(pollId: string) { + const cancel = cancelTokens.get(pollId); + if (cancel) { + cancel(); + } +} + +/** + * 取消所有轮询 + */ +export function cancelAllPolling() { + // 将 Map 转换为数组后再遍历 + Array.from(cancelTokens.values()).forEach(cancel => cancel()); + cancelTokens.clear(); +} \ No newline at end of file diff --git a/api/movie_start.ts b/api/movie_start.ts index 1c53a8a..3cf62d2 100644 --- a/api/movie_start.ts +++ b/api/movie_start.ts @@ -1,11 +1,7 @@ import { ApiResponse } from "./common"; import { - CreateMovieProjectV2Request, - CreateMovieProjectResponse, - MovieStartDTO, StoryAnalysisTask, MovieStoryTaskDetail, - CreateMovieProjectV3Request, GeminiTextToImageRequest, GeminiTextToImageResponse, TextToImageRequest, @@ -44,34 +40,6 @@ export const AIGenerateImageStory = async (request: { ); }; -/** - * 创建电影项目V2 - * @param request - 创建项目请求参数 - * @returns Promise> - */ -export const createMovieProjectV2 = async ( - request: CreateMovieProjectV2Request -) => { - return post>( - "/movie/create_movie_project_v2", - request - ); -}; - -/** - * 创建电影项目V3 - * @param request - 创建项目请求参数 - * @returns Promise> - */ -export const createMovieProjectV3 = async ( - request: CreateMovieProjectV3Request -) => { - return post>( - "/movie/create_movie_project_v3", - request - ); -}; - /** * 获取电影故事任务详情 * @param taskId - 任务ID diff --git a/api/request.ts b/api/request.ts index d04ed06..f997fab 100644 --- a/api/request.ts +++ b/api/request.ts @@ -49,19 +49,19 @@ request.interceptors.request.use( request.interceptors.response.use( (response: AxiosResponse) => { // 检查业务状态码 - if (response.data?.code !== 0) { + if (response.data?.code !== 0 && response.data?.code !== 202) { // 处理业务层面的错误 const businessCode = response.data?.code; const errorMessage = response.data?.message; - // 特殊处理 401 和 403 业务状态码 + // 特殊处理 401 和 4001 业务状态码 if (businessCode === 401) { errorHandle(401, errorMessage); return Promise.reject(new Error(errorMessage)); } - if (businessCode === 403) { - errorHandle(403, errorMessage); + if (businessCode === 4001) { + errorHandle(4001, errorMessage); return Promise.reject(new Error(errorMessage)); } diff --git a/api/script_episode.ts b/api/script_episode.ts index 3bd0767..9b84926 100644 --- a/api/script_episode.ts +++ b/api/script_episode.ts @@ -66,59 +66,6 @@ export const getScriptEpisodeListNew = async (data: any): Promise>('/movie/list_movie_projects', data); }; -// 新-创建接口 -export const createScriptEpisodeNew = async (data: any): Promise> => { - return post>('/movie/create_movie_project', data); -}; - -// 创建剧集 -export const createScriptEpisode = async (data: CreateScriptEpisodeRequest): Promise> => { - // return post>('/script_episode/create', data); - return new Promise((resolve) => { - setTimeout(() => { - resolve({ - code: 0, - message: 'success', - data: { - id: 1, - title: 'test', - script_id: 1, - status: 1, - episode_sort: 1, - creator_name: 'king', - created_at: '2025-07-03 10:00:00', - updated_at: '2025-07-03 10:00:00' - }, - successful: true - }); - }, 1000); - }); -}; - -// 更新剧集 -export const updateScriptEpisode = async (data: UpdateScriptEpisodeRequest): Promise> => { - // return post>('/script_episode/update', data); - return new Promise((resolve) => { - setTimeout(() => { - resolve({ - code: 0, - message: 'success', - data: { - id: 1, - title: 'test', - script_id: 1, - status: 1, - episode_sort: 1, - creator_name: 'king', - created_at: '2025-07-03 10:00:00', - updated_at: '2025-07-03 10:00:00' - }, - successful: true - }); - }, 0); - }); -}; - // 获取剧集详情 export const detailScriptEpisode = async (data: detailScriptEpisodeRequest): Promise> => { return post>('/script_episode/detail', data); diff --git a/app/globals.css b/app/globals.css index a37fc43..2dccfef 100644 --- a/app/globals.css +++ b/app/globals.css @@ -242,4 +242,12 @@ body { .ant-notification-notice-wrapper { background: transparent !important; -} \ No newline at end of file +} + +.ant-switch.ant-switch-checked { + background: rgb(146 78 173 / 0.8); +} + +.ant-switch.ant-switch-checked:hover { + background: rgb(146 78 173) !important; +} \ No newline at end of file diff --git a/app/layout.tsx b/app/layout.tsx index 4cf7678..5464391 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -42,9 +42,14 @@ export default function RootLayout({ return ( - AI Movie Flow - Create Amazing Videos with AI + Movie Flow - Create Amazing Movies with AI + + + + + Promise; + ) => Promise<{ project_id: string } | undefined>; /** 设置角色分析 */ setCharactersAnalysis: Dispatch>; /** 设置原始用户描述 */ @@ -484,8 +484,11 @@ export const useImageStoryServiceHook = (): UseImageStoryService => { }; // 调用create_movie_project_v2接口 - const result = await createMovieProjectV2(params); - return result.data; + const result = await MovieProjectService.createProject( + MovieProjectMode.IMAGE, + params + ); + return { project_id: result.project_id }; } } catch (error) { console.error("创建电影项目失败:", error); diff --git a/app/service/Interaction/MovieProjectService.ts b/app/service/Interaction/MovieProjectService.ts new file mode 100644 index 0000000..54e99f1 --- /dev/null +++ b/app/service/Interaction/MovieProjectService.ts @@ -0,0 +1,90 @@ +import { CreateMovieProjectV2Request, CreateMovieProjectV3Request } from "@/api/DTO/movie_start_dto"; +import { createMovieProject, createMovieProjectV2, createMovieProjectV3 } from "@/api/create_movie"; +import { QueueResponse, QueueStatus, withQueuePolling, QueueResponseData } from "@/api/movie_queue"; +import { message } from "antd"; + +/** + * 电影项目创建模式 + */ +export enum MovieProjectMode { + /** 普通模式 */ + NORMAL = "normal", + /** 照片生成模式 */ + IMAGE = "image", + /** 模板生成模式 */ + TEMPLATE = "template" +} + +/** 创建项目响应数据 */ +export interface CreateProjectResponse { + project_id: string; +} + +/** + * 统一的电影项目创建服务 + */ +export class MovieProjectService { + /** + * 创建电影项目 + */ + static async createProject( + mode: MovieProjectMode, + params: T + ): Promise { + try { + let apiCall: (p: T) => Promise; + + switch (mode) { + case MovieProjectMode.NORMAL: + apiCall = createMovieProject as (p: T) => Promise; + break; + case MovieProjectMode.IMAGE: + apiCall = createMovieProjectV2 as (p: T) => Promise; + break; + case MovieProjectMode.TEMPLATE: + apiCall = createMovieProjectV3 as (p: T) => Promise; + break; + default: + throw new Error(`不支持的创建模式: ${mode}`); + } + + // 使用 withQueuePolling 包装 API 调用 + const result = await withQueuePolling(apiCall, params, { + interval: 5000, // 5秒轮询一次 + maxAttempts: 120, // 最多轮询10分钟 + onPolling: (data: QueueResponseData) => { + console.log("轮询状态:", data); + }, + onError: (error: Error) => { + if (error.message === '操作已取消') { + message.info('已取消排队'); + } else { + message.error(error instanceof Error ? error.message : "创建项目失败"); + } + }, + onCancel: () => { + message.info('已取消排队'); + } + }); + + // 处理其他错误状态 + if (result.code !== 0 && result.code !== 202) { + throw new Error(result.message || "创建项目失败"); + } + + // 从响应中提取 project_id + const projectId = (result.data as any).project_id; + if (!projectId) { + throw new Error("创建项目失败:未返回项目ID"); + } + + return { project_id: projectId }; + } catch (error) { + if (error instanceof Error && error.message === '操作已取消') { + throw error; + } + message.error(error instanceof Error ? error.message : "创建项目失败"); + throw error; + } + } +} \ No newline at end of file diff --git a/app/service/Interaction/templateStoryService.ts b/app/service/Interaction/templateStoryService.ts index 1797609..bf6b85b 100644 --- a/app/service/Interaction/templateStoryService.ts +++ b/app/service/Interaction/templateStoryService.ts @@ -4,7 +4,8 @@ import { useUploadFile } from "../domain/service"; import { debounce } from "lodash"; import { TemplateStoryUseCase } from "../usecase/templateStoryUseCase"; import { useState, useCallback, useMemo } from "react"; -import { createMovieProjectV3, generateTextToImage } from "@/api/movie_start"; +import { generateTextToImage } from "@/api/movie_start"; +import { MovieProjectService, MovieProjectMode } from "./MovieProjectService"; import { CreateMovieProjectV3Request } from "@/api/DTO/movie_start_dto"; /** 模板角色接口 */ @@ -312,12 +313,11 @@ export const useTemplateStoryServiceHook = (): UseTemplateStoryService => { fillable_content: selectedTemplate?.fillable_content || [], }; console.log("params", params); - const result = await createMovieProjectV3(params); - if((result.data as unknown) === 'message'){ - message.error(result.message); - return; - } - return result.data.project_id as string; + const result = await MovieProjectService.createProject( + MovieProjectMode.TEMPLATE, + params + ); + return result.project_id; } catch (error) { console.error("创建电影项目失败:", error); } finally { diff --git a/components/ChatInputBox/ChatInputBox.tsx b/components/ChatInputBox/ChatInputBox.tsx index e7d64d0..f2ea722 100644 --- a/components/ChatInputBox/ChatInputBox.tsx +++ b/components/ChatInputBox/ChatInputBox.tsx @@ -35,7 +35,7 @@ import { AudioRecorder } from "./AudioRecorder"; import { useTemplateStoryServiceHook } from "@/app/service/Interaction/templateStoryService"; import { useRouter } from "next/navigation"; import { createMovieProjectV1 } from "@/api/video_flow"; -import { createScriptEpisodeNew } from "@/api/script_episode"; +import { MovieProjectService, MovieProjectMode } from "@/app/service/Interaction/MovieProjectService"; import { useLoadScriptText, useUploadFile } from "@/app/service/domain/service"; import { ActionButton } from "../common/ActionButton"; import { HighlightEditor } from "../common/HighlightEditor"; @@ -656,17 +656,19 @@ export function ChatInputBox({ noData }: { noData: boolean }) { }; // 调用创建剧集API - const episodeResponse = await createScriptEpisodeNew(episodeData); - console.log("episodeResponse", episodeResponse); - if (episodeResponse.code !== 0) { - console.error(`创建剧集失败: ${episodeResponse.message}`); - alert(`创建剧集失败: ${episodeResponse.message}`); - return; + try { + const result = await MovieProjectService.createProject( + MovieProjectMode.NORMAL, + episodeData + ); + const episodeId = result.project_id; + router.push(`/create/work-flow?episodeId=${episodeId}`); + } catch (error) { + console.error("创建剧集失败:", error); + } finally { + setIsCreating(false); } - let episodeId = episodeResponse.data.project_id; - // let episodeId = '9c34fcc4-c8d8-44fc-879e-9bd56f608c76'; - router.push(`/create/work-flow?episodeId=${episodeId}`); - setIsCreating(false); + }; return ( diff --git a/components/QueueBox/QueueNotification2.tsx b/components/QueueBox/QueueNotification2.tsx index a2b5636..328a0e8 100644 --- a/components/QueueBox/QueueNotification2.tsx +++ b/components/QueueBox/QueueNotification2.tsx @@ -94,7 +94,12 @@ const Workstation = () => ( * @param position - 当前队列位置 * @param estimatedMinutes - 预计等待分钟数 */ -export const showQueueNotification = (position: number, estimatedMinutes: number) => { +export const showQueueNotification = ( + position: number, + estimatedMinutes: number, + status: string, + onCancel: () => void +) => { notification.open({ message: null, description: ( @@ -118,7 +123,7 @@ export const showQueueNotification = (position: number, estimatedMinutes: number borderRadius: '6px', }}> 🎬 - 您的作品正在第 {position} 位等待制作 + {status === 'process' ? `您的作品正在制作,请等待完成后再创建新作品` : `您的作品正在第 ${position} 位等待制作`} {/* 预计等待时间 */} @@ -127,12 +132,15 @@ export const showQueueNotification = (position: number, estimatedMinutes: number color: 'rgba(255, 255, 255, 0.65)', marginBottom: '12px', }}> - 预计等待时间:约 {estimatedMinutes} 分钟 + {status !== 'process' && `预计等待时间:约 ${estimatedMinutes} 分钟`} {/* 取消按钮 */} ), diff --git a/components/SmartChatBox/DateDivider.tsx b/components/SmartChatBox/DateDivider.tsx index d6d7897..7922276 100644 --- a/components/SmartChatBox/DateDivider.tsx +++ b/components/SmartChatBox/DateDivider.tsx @@ -13,14 +13,14 @@ export function DateDivider({ timestamp }: DateDividerProps) { // 判断是否是今天 if (date.toDateString() === today.toDateString()) { - return '今天'; + return 'Today'; } // 判断是否是昨天 if (date.toDateString() === yesterday.toDateString()) { - return '昨天'; + return 'Yesterday'; } // 其他日期显示完整日期 - return date.toLocaleDateString('zh-CN', { + return date.toLocaleDateString('en-US', { year: 'numeric', month: 'long', day: 'numeric' diff --git a/components/SmartChatBox/ProgressBar.tsx b/components/SmartChatBox/ProgressBar.tsx index 78b7e4b..bc68d63 100644 --- a/components/SmartChatBox/ProgressBar.tsx +++ b/components/SmartChatBox/ProgressBar.tsx @@ -12,9 +12,9 @@ export function ProgressBar({ value, total = 100, label }: ProgressBarProps) { return (
{label ?
{label}
: null} -
+
diff --git a/components/layout/top-bar.tsx b/components/layout/top-bar.tsx index 68e6c75..f2a7197 100644 --- a/components/layout/top-bar.tsx +++ b/components/layout/top-bar.tsx @@ -42,9 +42,9 @@ export function TopBar({ const currentUser: User = JSON.parse( localStorage.getItem("currentUser") || "{}" ); + const pathname = usePathname() const [mounted, setMounted] = React.useState(false); const [isLogin, setIsLogin] = useState(false); - const pathname = usePathname(); const [isManagingSubscription, setIsManagingSubscription] = useState(false); const [subscriptionStatus, setSubscriptionStatus] = useState(''); const [credits, setCredits] = useState(100); diff --git a/components/pages/create-to-video2.tsx b/components/pages/create-to-video2.tsx index e8c761d..202301c 100644 --- a/components/pages/create-to-video2.tsx +++ b/components/pages/create-to-video2.tsx @@ -5,7 +5,7 @@ import { ArrowLeft, ListOrdered, Play, Loader2, Pause, MoreHorizontal, Edit2, Ch import { useRouter, useSearchParams } from 'next/navigation'; import './style/create-to-video2.css'; -import { createScriptEpisodeNew, getScriptEpisodeListNew, CreateScriptEpisodeRequest } from "@/api/script_episode"; +import { getScriptEpisodeListNew } from "@/api/script_episode"; import { EmptyStateAnimation } from '@/components/common/EmptyStateAnimation2'; import { ChatInputBox } from '@/components/ChatInputBox/ChatInputBox'; import cover_image1 from '@/public/assets/cover_image1.jpg'; @@ -119,20 +119,7 @@ export default function CreateToVideo2() { transition={{ repeat: Infinity, duration: 1.5 }} /> {/* 状态文字 */} - - PROCESSING - - - )} - {/* 已完成 */} - {status === 'completed' && ( - <> - - - COMPLETED - + )} {/* 失败 */} @@ -183,45 +170,44 @@ export default function CreateToVideo2() { return (
router.push(`/create/work-flow?episodeId=${project.project_id}`)} onMouseEnter={() => handleMouseEnter(project.project_id)} onMouseLeave={() => handleMouseLeave(project.project_id)} data-alt="project-card" > {/* 视频/图片区域 */} - {project.final_video_url ? ( -