diff --git a/video-gen-app/dist.zip b/video-gen-app/dist.zip new file mode 100644 index 00000000..e41d884d Binary files /dev/null and b/video-gen-app/dist.zip differ diff --git a/video-gen-app/src/api/index.ts b/video-gen-app/src/api/index.ts index d4318155..4c52de8c 100644 --- a/video-gen-app/src/api/index.ts +++ b/video-gen-app/src/api/index.ts @@ -342,3 +342,35 @@ export async function getAuthorizationList(params: OAuthAppParam): Promise(`/admin/user-oauth-apps/list?${query.toString()}`); } + + +// 爆款开头复刻 +export async function generateReplication(params: any): Promise { + return api.post('/hot-opening-replications/tasks', params); +} +// 获取爆款开头复刻任务列表 +export async function getReplicationList(page: number,page_size: number): Promise { + return api.get(`/hot-opening-replications/tasks?page=${page}&page_size=${page_size}`); +} +// 获取爆款开头复刻任务详情 +export async function getReplicationDetail(id: string): Promise { + return api.get(`/hot-opening-replications/tasks/${id}`); +} +// 第一步,生成提示词 +export async function getone(projectId: string, stepId: string): Promise { + return api.post(`/hot-opening-replications/tasks/${projectId}/steps/${stepId}/generate-image-prompt`); +} + +// 第二步,生成图片 +export async function gettwo(projectId: string, stepId: string ,params: any): Promise { + return api.post(`/hot-opening-replications/tasks/${projectId}/steps/${stepId}/generate-image`, params); +} + +// 第三步,生成视频提示词 +export async function getthree(projectId: string, stepId: string ,params: any): Promise { + return api.post(`/hot-opening-replications/tasks/${projectId}/steps/${stepId}/generate-video-prompt`, params); +} +// 第四步,生成视频 +export async function getfour(projectId: string, stepId: string ,params: any): Promise { + return api.post(`/hot-opening-replications/tasks/${projectId}/steps/${stepId}/generate-video`, params); +} diff --git a/video-gen-app/src/pages/GenerateConver.tsx b/video-gen-app/src/pages/GenerateConver.tsx index 45f23b71..5e6d5e4b 100644 --- a/video-gen-app/src/pages/GenerateConver.tsx +++ b/video-gen-app/src/pages/GenerateConver.tsx @@ -121,6 +121,9 @@ const AIChatPage: React.FC = () => { const [previewType, setPreviewType] = useState<'image' | 'video'>('image'); const videoRef = useRef(null); + // 提示词展开状态 + const [expandedPrompts, setExpandedPrompts] = useState>(new Set()); + // 从URL中提取exp时间戳(支持相对路径和完整URL) const extractExpTimestamp = (url: string): number | null => { if (!url) return null; @@ -249,7 +252,6 @@ const AIChatPage: React.FC = () => { } - console.log(config); // 根据配置计算积分 @@ -456,7 +458,7 @@ const AIChatPage: React.FC = () => { setTotalnumber(data.total); }).catch((error) => { }); - }, 5000); + }, 10000); // 清理定时器 return () => { @@ -807,7 +809,7 @@ const AIChatPage: React.FC = () => { const handleClosePreview = () => { setPreviewVisible(false); - setPreviewUrl(''); + setPreviewUrl(''); if (videoRef.current) { videoRef.current.pause(); } @@ -818,7 +820,7 @@ const AIChatPage: React.FC = () => { e.stopPropagation(); if (!previewUrl) return; const link = document.createElement('a'); - link.href = `${import.meta.env.VITE_API_BASE || "http://localhost:8000"}${previewUrl}`; + link.href = `${import.meta.env.VITE_API_BASE || "http://localhost:8000"}${previewUrl}&download=1`; link.download = previewType === 'image' ? 'image.png' : 'video.mp4'; document.body.appendChild(link); link.click(); @@ -1088,7 +1090,7 @@ const AIChatPage: React.FC = () => { }} > {/* 删除按钮 - 右上角 */} -
+
{ @@ -1099,7 +1101,6 @@ const AIChatPage: React.FC = () => { setGen_list(prev => prev.filter(item => item.id !== msg.id)); setTotalnumber(prev => prev - 1); } catch (error: any) { - console.log(error); const errorMsg = error?.response?.data?.message || error?.message || '删除失败'; msgApi.error(errorMsg); @@ -1115,8 +1116,8 @@ const AIChatPage: React.FC = () => { height: 28, borderRadius: 8, border: 'none', - background: 'rgba(0,0,0,0.05)', - color: '#999', + background: 'rgba(146, 144, 144, 1)', + color: '#ffffffff', cursor: 'pointer', display: 'flex', alignItems: 'center', @@ -1140,29 +1141,56 @@ const AIChatPage: React.FC = () => {
{/* 文本内容 */} - -

{ + setExpandedPrompts(prev => { + const newSet = new Set(prev); + newSet.add(msg.id); + return newSet; + }); + }} + onMouseLeave={() => { + setExpandedPrompts(prev => { + const newSet = new Set(prev); + newSet.delete(msg.id); + return newSet; + }); + }} + > + {/* 默认显示:一行省略 */} +

{ e.currentTarget.style.backgroundColor = '#f1f5f9'; }} - onMouseLeave={(e) => { e.currentTarget.style.backgroundColor = 'transparent'; }} - > - {msg.originalPrompt} -

- + display: expandedPrompts.has(msg.id) ? 'none' : 'block', + }}> + {msg.originalPrompt} +
+ + {/* 鼠标移入显示:完整内容 */} +
+ {msg.originalPrompt} +
+
{/* 根据 status 显示不同内容 */} {/* 生成中 - 显示加载动画 */} @@ -2354,7 +2382,7 @@ const AIChatPage: React.FC = () => { - )} - {step.id === 5 && ( + {/* 步骤3: 生成产品融合图 */} + {step.childId === 3 && ( <> -
- 最终视频 -
- +
+ {/* {step.output.result.result_image_url} */} + + + {taskDetail.finalImageUrl ? ( + 融合图 + ) : ( +
暂无融合图
+ )} +
+ {/* 引擎选择器 */} +
+
+ + + {showEngineModal && ( +
e.stopPropagation()} + > + {/* 选择引擎 */} +
+ + 选择引擎 + +
+ {enginesele.video?.map((engine: any) => ( + + ))} +
+
+
+ )} +
+
+ + {/* 视频参数设置 */} +
+
+ + + {showVideoSettingsModal && ( +
e.stopPropagation()} + > + {/* 选择比例 */} +
+ + 选择比例 + +
+ {engineOptions.ratios.map((ratio) => ( + + ))} +
+
+ + {/* 选择时长 */} +
+ + 选择时长 + +
+
+ {/* 背景轨道 */} +
+ {/* 已滑动部分 */} +
+ {/* 滑块 */} + setVideoDuration(Number(e.target.value))} + style={{ + position: 'relative', + width: '100%', + height: 24, + borderRadius: 3, + background: 'transparent', + outline: 'none', + appearance: 'none', + cursor: 'pointer', + zIndex: 1, + }} + /> +
+
+ + {videoDuration} + + +
+
+
+ + {/* 选择分辨率 */} +
+ + 选择分辨率 + +
+ {engineOptions.resolutions.map((resolution) => ( + + ))} +
+
+
+ )}
- - + + + )} + {/* 步骤4: 生成视频提示词 */} + {step.childId === 4 && ( + <> + + {/* {taskDetail?.videoPrompt || '暂无视频提示词'} */} + {step?.output?.payload?.finalPrompt || '暂无提示词'} + + + + + + + + )} + {/* 步骤5: 生成最终视频 */} + {step.childId === 5 && ( + <> +
+ {step.status === 'completed' && taskDetail?.finalVideoUrl ? ( +