diff --git a/components/ChatInputBox/AspectRatioSelector.tsx b/components/ChatInputBox/AspectRatioSelector.tsx index 97ed5f5..95d4804 100644 --- a/components/ChatInputBox/AspectRatioSelector.tsx +++ b/components/ChatInputBox/AspectRatioSelector.tsx @@ -1,8 +1,6 @@ "use client"; -import { Dropdown } from "antd"; import { RectangleHorizontal, RectangleVertical } from "lucide-react"; -import { AspectRatioOptions } from "./types"; export type AspectRatioValue = | "VIDEO_ASPECT_RATIO_LANDSCAPE" @@ -22,13 +20,13 @@ interface AspectRatioSelectorProps { } /** - * A reusable aspect ratio selector (landscape/portrait) using Antd Dropdown. - * Shows an icon and label, and calls onChange when a new ratio is chosen. + * Aspect ratio selector using Antd Radio.Group with two options: landscape and portrait. + * Uses icons as button content and triggers onChange when selection changes. * @param {AspectRatioValue} value - current selected value * @param {(v: AspectRatioValue) => void} onChange - change handler - * @param {string} [className] - optional className for trigger button - * @param {string} [placement] - Dropdown placement, default is top - * @param {string} [dataAlt] - data-alt attribute for the trigger + * @param {string} [className] - optional className for wrapper + * @param {string} [placement] - kept for backward compatibility (unused) + * @param {string} [dataAlt] - data-alt attribute for the wrapper * @returns {JSX.Element} */ export const AspectRatioSelector = ({ @@ -39,45 +37,47 @@ export const AspectRatioSelector = ({ dataAlt = "config-aspect-ratio", }: AspectRatioSelectorProps) => { return ( - ({ - key: option.value, - label: ( -
- {option.value === "VIDEO_ASPECT_RATIO_LANDSCAPE" ? ( - - ) : ( - - )} - {option.label} -
- ), - })), - onClick: ({ key }) => onChange(key as AspectRatioValue), - }} - trigger={["click"]} - placement={placement} +
- + +
); }; diff --git a/components/ChatInputBox/ChatInputBox.tsx b/components/ChatInputBox/ChatInputBox.tsx index 04e219e..dd530cd 100644 --- a/components/ChatInputBox/ChatInputBox.tsx +++ b/components/ChatInputBox/ChatInputBox.tsx @@ -523,11 +523,12 @@ export function ChatInputBox({ noData }: { noData: boolean }) { placement="top" >
diff --git a/components/pages/work-flow.tsx b/components/pages/work-flow.tsx index cecf083..17056f7 100644 --- a/components/pages/work-flow.tsx +++ b/components/pages/work-flow.tsx @@ -138,9 +138,11 @@ const WorkFlow = React.memo(function WorkFlow() { setTimeout(() => { handleTestExportRef.current?.(); }, 0); + + const title = isMobile ? 'editing...' : 'Performing intelligent editing...'; // 显示进度提示并启动超时定时器 - emitToastShow({ title: 'Performing intelligent editing...', progress: 0 }); + emitToastShow({ title: title, progress: 0 }); // 启动自动推进到 90% 的进度(8分钟) if (editingProgressIntervalRef.current) clearInterval(editingProgressIntervalRef.current); editingProgressStartRef.current = Date.now(); diff --git a/components/pages/work-flow/H5MediaViewer.tsx b/components/pages/work-flow/H5MediaViewer.tsx index 8a4940f..6328577 100644 --- a/components/pages/work-flow/H5MediaViewer.tsx +++ b/components/pages/work-flow/H5MediaViewer.tsx @@ -286,7 +286,7 @@ export function H5MediaViewer({ } }; return ( -
+
{scriptData ? ( <> -
- -
+
⚠️
)} {/* 只在生成过程中或没有分镜图片时使用ProgressiveReveal */} diff --git a/components/pages/work-flow/thumbnail-grid.tsx b/components/pages/work-flow/thumbnail-grid.tsx index cf9ca5b..2a3ae94 100644 --- a/components/pages/work-flow/thumbnail-grid.tsx +++ b/components/pages/work-flow/thumbnail-grid.tsx @@ -298,10 +298,8 @@ export function ThumbnailGrid({
)} {sketch.status === 2 && ( -
-
- -
+
+
⚠️
)} {/* 只在生成过程中或没有分镜图片时使用ProgressiveReveal */} diff --git a/components/pages/work-flow/use-workflow-data.tsx b/components/pages/work-flow/use-workflow-data.tsx index 51bfba6..cdb3d29 100644 --- a/components/pages/work-flow/use-workflow-data.tsx +++ b/components/pages/work-flow/use-workflow-data.tsx @@ -7,6 +7,7 @@ import { useScriptService } from "@/app/service/Interaction/ScriptService"; import { useUpdateEffect } from '@/app/hooks/useUpdateEffect'; import { LOADING_TEXT_MAP, TaskObject, Status, Stage } from '@/api/DTO/movieEdit'; import { AspectRatioValue } from '@/components/ChatInputBox/AspectRatioSelector'; +import { useDeviceType } from '@/hooks/useDeviceType'; interface UseWorkflowDataProps { onEditPlanGenerated?: () => void; @@ -37,6 +38,8 @@ export function useWorkflowData({ onEditPlanGenerated, editingStatus, onExportFa } }; + const { isMobile, isTablet, isDesktop } = useDeviceType(); + const cutUrl = process.env.NEXT_PUBLIC_CUT_URL_TO || 'https://smartcut.api.movieflow.ai'; console.log('cutUrl', cutUrl); @@ -158,7 +161,7 @@ export function useWorkflowData({ onEditPlanGenerated, editingStatus, onExportFa return; } // 显示生成剪辑计划进度提示 - emitToastShow({ title: `Generating intelligent editing plan... ${retryCount ? 'Retry Time: ' + retryCount : ''}`, progress: 0 }); + emitToastShow({ title: isMobile ? 'Preparing for editing...' : `Generating intelligent editing plan... ${retryCount ? 'Retry Time: ' + retryCount : ''}`, progress: 0 }); // 平滑推进到 80%,后续阶段接管 const start = Date.now(); const duration = 3 * 60 * 1000; // 3分钟推进到 80% @@ -198,7 +201,7 @@ export function useWorkflowData({ onEditPlanGenerated, editingStatus, onExportFa setIsGenerateEditPlan(false); // 显示失败提示,并在稍后隐藏 - emitToastShow({ title: 'Editing plan generation failed. Retrying later.', progress: 0 }); + // emitToastShow({ title: isMobile ? 'Editing plan generation failed. Retrying later.' : 'Editing plan generation failed. Retrying later.', progress: 0 }); setTimeout(() => { emitToastHide(); setIsLoadingGenerateEditPlan(false); @@ -419,7 +422,7 @@ export function useWorkflowData({ onEditPlanGenerated, editingStatus, onExportFa if (analyze_video_total_count > 0 && !isAnalyzing && analyze_video_completed_count !== analyze_video_total_count) { setIsAnalyzing(true); // 显示准备剪辑计划的提示 - emitToastShow({ title: 'Preparing intelligent editing plan...', progress: 0 }); + emitToastShow({ title: isMobile ? 'Preparing for editing...' : 'Preparing intelligent editing plan...', progress: 0 }); } if (analyze_video_total_count && analyze_video_completed_count === analyze_video_total_count) { diff --git a/lib/server-config.ts b/lib/server-config.ts index 01767ee..9463fb4 100644 --- a/lib/server-config.ts +++ b/lib/server-config.ts @@ -10,7 +10,14 @@ */ const localPost = async (url: string, data: any): Promise => { try { - const response = await fetch(url, { + // 使用环境变量中的 BASE_URL(生产要求使用 NEXT_PUBLIC_BASE_URL) + const baseUrl = process.env.NEXT_PUBLIC_BASE_URL || ''; + const isAbsolute = /^https?:\/\//i.test(url); + const normalizedBase = baseUrl.replace(/\/$/, ''); + const normalizedPath = url.startsWith('/') ? url : `/${url}`; + const fullUrl = isAbsolute ? url : `${normalizedBase}${normalizedPath}`; + + const response = await fetch(fullUrl, { method: 'POST', headers: { 'Content-Type': 'application/json',