diff --git a/api/request.ts b/api/request.ts index c0c4491..e962187 100644 --- a/api/request.ts +++ b/api/request.ts @@ -34,7 +34,7 @@ const request: AxiosInstance = axios.create({ request.interceptors.request.use( (config: InternalAxiosRequestConfig) => { // 从 localStorage 获取 token - const token = localStorage?.getItem('token') || 'mock-token'; + const token = localStorage?.getItem('token'); if (token && config.headers) { (config.headers as AxiosHeaders).set('Authorization', `Bearer ${token}`); } diff --git a/api/video_flow.ts b/api/video_flow.ts index 194d2fe..f37c65c 100644 --- a/api/video_flow.ts +++ b/api/video_flow.ts @@ -269,52 +269,29 @@ export const getRunningStreamData = async (data: { return post>("/movie/get_status", data); }; -// 新增:获取项目任务列表接口(优化版本) +/** + * 获取项目任务列表接口 + * @param data - 请求参数 + * @param data.project_id - 项目ID + * @returns Promise> - 任务列表响应 + */ export const getProjectTaskList = async (data: { project_id: string; }): Promise> => { - const fullUrl = "https://77.smartvideo.py.qikongjian.com/task/get_project_task_list"; - - // 添加请求超时控制 - const controller = new AbortController(); - const timeoutId = setTimeout(() => controller.abort(), 30000); // 30秒超时 + const startTime = Date.now(); + console.log(`[API] 开始请求任务列表,项目ID: ${data.project_id}`); try { - console.log(`[API] 开始请求任务列表,项目ID: ${data.project_id}`); - const startTime = Date.now(); - - const response = await fetch(fullUrl, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'Authorization': `Bearer ${localStorage?.getItem('token') || 'mock-token'}`, - }, - body: JSON.stringify(data), - signal: controller.signal, // 添加超时控制 - }); - - clearTimeout(timeoutId); + const result = await post>('/task/get_project_task_list', data); + const endTime = Date.now(); console.log(`[API] 请求完成,耗时: ${endTime - startTime}ms`); - - if (!response.ok) { - throw new Error(`HTTP error! status: ${response.status}`); - } - - const result = await response.json(); console.log(`[API] 数据解析完成,任务数量: ${Array.isArray(result.data) ? result.data.length : 0}`); return result; } catch (error) { - clearTimeout(timeoutId); - - if (error instanceof Error && error.name === 'AbortError') { - console.error('[API] 请求超时 (30秒)'); - throw new Error('请求超时,请检查网络连接'); - } - console.error('[API] 获取任务列表失败:', error); - throw error instanceof Error ? error : new Error('未知错误'); + throw error; } }; diff --git a/components/pages/login.tsx b/components/pages/login.tsx index 4f9e637..b964236 100644 --- a/components/pages/login.tsx +++ b/components/pages/login.tsx @@ -57,7 +57,7 @@ export default function Login() { // 根据错误类型显示不同的错误消息 setFormError( - "Login failed, please check your credentials and try again." + "Login failed, please try again." ); } finally { setIsSubmitting(false); diff --git a/components/pages/work-flow/use-api-data.ts b/components/pages/work-flow/use-api-data.ts deleted file mode 100644 index 15337c3..0000000 --- a/components/pages/work-flow/use-api-data.ts +++ /dev/null @@ -1,273 +0,0 @@ -import { useState, useEffect, useCallback } from 'react'; -import { detailScriptEpisodeNew, getScriptTitle, getRunningStreamData, StreamData } from '@/api/video_flow'; -import { useSearchParams } from 'next/navigation'; -import { ApiResponse } from '@/api/common'; -import { SketchData, CharacterResponse, VideoData } from '@/api/DTO/movieEdit'; - -// 步骤映射 -const STEP_MAP = { - 'sketch': '1', - 'character': '2', - 'video': '3', - 'music': '4', - 'final_video': '6' -} as const; - -type ApiStep = keyof typeof STEP_MAP; - -interface TaskData { - sketch?: { - url: string; - script: string; - bg_rgb: string[]; - }[]; - roles?: { - name: string; - url: string; - sound: string; - soundDescription: string; - roleDescription: string; - }[]; - videos?: { - url: string; - script: string; - audio: string; - }[]; - music?: { - url: string; - script: string; - name: string; - duration: string; - totalDuration: string; - isLooped: boolean; - }[]; - final?: { - url: string; - }; - [key: string]: any; // 允许其他可能的字段 -} - -export const useApiData = () => { - const searchParams = useSearchParams(); - const episodeId = searchParams.get('episodeId'); - - const [title, setTitle] = useState(''); - const [currentStep, setCurrentStep] = useState('1'); - const [currentLoadingText, setCurrentLoadingText] = useState(''); - const [needStreamData, setNeedStreamData] = useState(false); - const [taskData, setTaskData] = useState({}); - const [streamInterval, setStreamInterval] = useState(null); - - // 处理流式数据 - const handleStreamData = useCallback((streamData: ApiResponse) => { - const { category, message, data, status } = streamData.data; - - // 更新加载文本 - setCurrentLoadingText(message); - - // 根据类别更新任务数据 - setTaskData(prevData => { - const newData = { ...prevData }; - - switch (category) { - case 'sketch': - if (!newData.sketch) newData.sketch = []; - // 更新或追加分镜数据 - const existingSketchIndex = newData.sketch.findIndex(s => s.url === data.url); - if (existingSketchIndex === -1) { - newData.sketch.push(data); - } else { - newData.sketch[existingSketchIndex] = data; - } - break; - - case 'character': - if (!newData.roles) newData.roles = []; - // 更新或追加角色数据 - const existingRoleIndex = newData.roles.findIndex(r => r.name === data.name); - if (existingRoleIndex === -1) { - newData.roles.push(data); - } else { - newData.roles[existingRoleIndex] = data; - } - break; - - case 'video': - if (!newData.videos) newData.videos = []; - // 更新或追加视频数据 - const existingVideoIndex = newData.videos.findIndex(v => v.url === data.url); - if (existingVideoIndex === -1) { - newData.videos.push(data); - } else { - newData.videos[existingVideoIndex] = data; - } - break; - - case 'music': - if (!newData.music) newData.music = []; - newData.music = [data]; - break; - - case 'final_video': - newData.final = data; - break; - } - - return newData; - }); - - // 如果状态为 completed,停止获取流式数据 - if (status === 'completed' || streamData.data.all_completed) { - setNeedStreamData(false); - } - }, []); - - // 获取流式数据 - const fetchStreamData = useCallback(async () => { - if (!episodeId || !needStreamData) return; - - try { - const streamData = await getRunningStreamData({ project_id: episodeId }); - handleStreamData(streamData); - } catch (error) { - console.error('获取流式数据失败:', error); - } - }, [episodeId, needStreamData, handleStreamData]); - - // 启动流式数据轮询 - useEffect(() => { - if (needStreamData && !streamInterval) { - const interval = setInterval(fetchStreamData, 10000); // 修改为10秒 - setStreamInterval(interval); - } else if (!needStreamData && streamInterval) { - clearInterval(streamInterval); - setStreamInterval(null); - } - - return () => { - if (streamInterval) { - clearInterval(streamInterval); - } - }; - }, [needStreamData, fetchStreamData, streamInterval]); - - // 获取标题的轮询函数 - const pollTitle = useCallback(async () => { - if (!episodeId) return; - - try { - const response = await getScriptTitle({ project_id: episodeId }); - if (response.successful && response.data) { - setTitle(response.data.name); - return true; - } - } catch (error) { - console.error('获取标题失败:', error); - } - return false; - }, [episodeId]); - - // 获取剧集详情 - const fetchEpisodeDetail = useCallback(async () => { - if (!episodeId) return; - - try { - const response = await detailScriptEpisodeNew({ project_id: episodeId }); - if (response.successful) { - const { name, status, step, last_message, data } = response.data; - - // 设置标题 - if (name) { - setTitle(name); - } - - // 设置步骤 - if (step && STEP_MAP[step as ApiStep]) { - setCurrentStep(STEP_MAP[step as ApiStep]); - } - - // 设置加载文本 - setCurrentLoadingText(last_message || ''); - - // 设置是否需要流式数据 - setNeedStreamData(status === 'running'); - - // 设置任务数据 - if (data) { - // 将 ProjectContentData 转换为 TaskData - const convertedData: TaskData = { - sketch: data.sketch?.data?.map((item: SketchData) => ({ - url: item.image_path, - script: item.prompt, - bg_rgb: ['255', '255', '255'] // 默认白色背景 - })) || [], - roles: data.character?.data?.map((item: CharacterResponse) => ({ - name: item.character_name, - url: item.image_path, - sound: '', - soundDescription: '', - roleDescription: item.character_description - })) || [], - videos: data.video?.data?.map((item: VideoData) => ({ - url: item.urls?.[0] || '', - script: item.description || '', - audio: '' // 音频URL可能需要从其他地方获取 - })) || [], - music: data.music?.data?.map((item: any) => ({ - url: item.url || '', - script: item.description || '', - name: item.name || '', - duration: item.duration || '', - totalDuration: item.total_duration || '', - isLooped: item.is_looped || false - })) || [], - final: data.final_video ? { - url: data.final_video.video || '' - } : undefined - }; - setTaskData(convertedData); - } - - return true; - } - } catch (error) { - console.error('获取剧集详情失败:', error); - } - return false; - }, [episodeId]); - - // 初始化数据 - useEffect(() => { - let titleInterval: NodeJS.Timeout; - - const initData = async () => { - const detailSuccess = await fetchEpisodeDetail(); - - // 如果详情接口没有返回标题,开始轮询标题 - if (detailSuccess && !title) { - titleInterval = setInterval(async () => { - const success = await pollTitle(); - if (success) { - clearInterval(titleInterval); - } - }, 3000); - } - }; - - initData(); - - return () => { - if (titleInterval) { - clearInterval(titleInterval); - } - }; - }, [episodeId, fetchEpisodeDetail, pollTitle, title]); - - return { - title, - currentStep, - currentLoadingText, - needStreamData, - taskData - }; -}; \ No newline at end of file diff --git a/next.config.js b/next.config.js index dce7dad..3159550 100644 --- a/next.config.js +++ b/next.config.js @@ -36,6 +36,7 @@ const nextConfig = { async rewrites() { // 使用环境变量,如果没有则使用默认值 const BASE_URL = process.env.NEXT_PUBLIC_BASE_URL || 'https://77.smartvideo.py.qikongjian.com' + // const BASE_URL = 'http://192.168.120.5:8000' return [ { source: '/api/proxy/:path*',