From 93a7b2e68a6c83a351c6d91743bbe3204cde0244 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8C=97=E6=9E=B3?= <7854742+wang_rumeng@user.noreply.gitee.com> Date: Mon, 22 Sep 2025 19:36:37 +0800 Subject: [PATCH] =?UTF-8?q?=E5=85=BC=E5=AE=B9=20=E7=AB=96=E5=B1=8F=20?= =?UTF-8?q?=E6=A0=B7=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/DTO/movieEdit.ts | 2 + components/ChatInputBox/ChatInputBox.tsx | 4 +- components/pages/create-to-video2.tsx | 110 +++++++++++------- components/pages/work-flow.tsx | 8 +- components/pages/work-flow/H5MediaViewer.tsx | 12 +- components/pages/work-flow/media-viewer.tsx | 8 +- components/pages/work-flow/thumbnail-grid.tsx | 31 +++-- .../pages/work-flow/use-workflow-data.tsx | 10 +- 8 files changed, 112 insertions(+), 73 deletions(-) diff --git a/api/DTO/movieEdit.ts b/api/DTO/movieEdit.ts index b0f4961..0e89685 100644 --- a/api/DTO/movieEdit.ts +++ b/api/DTO/movieEdit.ts @@ -367,6 +367,8 @@ export interface VideoFlowProjectResponse { final_simple_video: string; /** 最终视频 */ final_video: string; + /** 画面比例 */ + aspect_ratio: string; } /** * 新角色列表项接口 diff --git a/components/ChatInputBox/ChatInputBox.tsx b/components/ChatInputBox/ChatInputBox.tsx index 3a896f1..b072bd2 100644 --- a/components/ChatInputBox/ChatInputBox.tsx +++ b/components/ChatInputBox/ChatInputBox.tsx @@ -50,7 +50,7 @@ import { PcTemplateModal } from "./PcTemplateModal"; import { H5TemplateDrawer } from "./H5TemplateDrawer"; import { PcPhotoStoryModal } from "./PcPhotoStoryModal"; import { H5PhotoStoryDrawer } from "./H5PhotoStoryDrawer"; -import { AspectRatioSelector } from "./AspectRatioSelector"; +import { AspectRatioSelector, AspectRatioValue } from "./AspectRatioSelector"; const LauguageOptions = [ { value: "english", label: "English", isVip: false, code:'EN' }, @@ -131,7 +131,7 @@ export function ChatInputBox({ noData }: { noData: boolean }) { language: string; videoDuration: string; expansion_mode: boolean; - aspect_ratio: "VIDEO_ASPECT_RATIO_LANDSCAPE" | "VIDEO_ASPECT_RATIO_PORTRAIT"; + aspect_ratio: AspectRatioValue; }; const [configOptions, setConfigOptions] = useState({ diff --git a/components/pages/create-to-video2.tsx b/components/pages/create-to-video2.tsx index 3c38f09..3248416 100644 --- a/components/pages/create-to-video2.tsx +++ b/components/pages/create-to-video2.tsx @@ -29,6 +29,8 @@ export default function CreateToVideo2() { const scrollContainerRef = useRef(null); const [userId, setUserId] = useState(0); const [isLoadingDownloadBtn, setIsLoadingDownloadBtn] = useState(false); + /** 保存每个项目的视频朝向 */ + const [orientationMap, setOrientationMap] = useState>({}); // 添加一个 ref 来跟踪当前正在加载的页码 const loadingPageRef = useRef(null); @@ -36,46 +38,14 @@ export default function CreateToVideo2() { // 在客户端挂载后读取localStorage // 监听滚动事件,实现无限加载 // 修改滚动处理函数,添加节流 - const handleScroll = useCallback(() => { - if (!scrollContainerRef.current || !hasMore || isLoadingMore || isLoading) return; - - const { scrollTop, scrollHeight, clientHeight } = scrollContainerRef.current; - if (scrollHeight - scrollTop - clientHeight < 100) { - // 直接使用 currentPage,不再使用 setCurrentPage 的回调 - const nextPage = currentPage + 1; - if (nextPage <= totalPages) { - getEpisodeList(userId, nextPage, true); - } - } - }, [hasMore, isLoadingMore, isLoading, totalPages, userId, currentPage]); - - useEffect(() => { - if (typeof window !== 'undefined') { - const currentUser = JSON.parse(localStorage.getItem('currentUser') || '{}'); - console.log('currentUser', currentUser); - setUserId(currentUser.id); - getEpisodeList(currentUser.id, 1, false); - } - }, []); - - // 添加滚动监听 - useEffect(() => { - const scrollContainer = scrollContainerRef.current; - if (scrollContainer) { - scrollContainer.addEventListener('scroll', handleScroll); - return () => scrollContainer.removeEventListener('scroll', handleScroll); - } - }, [handleScroll]); - - // 修改获取剧集列表函数 - const getEpisodeList = async (userId: number, page: number = 1, loadMore: boolean = false) => { + // 修改获取剧集列表函数(提前定义,供滚动与初始化调用) + const getEpisodeList = useCallback(async (userId: number, page: number = 1, loadMore: boolean = false) => { // 检查是否正在加载该页 if (loadingPageRef.current === page) return; - if (isLoading || (isLoadingMore && !loadMore)) return; - + // 设置当前正在加载的页码 loadingPageRef.current = page; - + if (loadMore) { setIsLoadingMore(true); } else { @@ -93,7 +63,7 @@ export default function CreateToVideo2() { if (episodeListResponse.code === 0) { const { movie_projects, total_pages } = episodeListResponse.data; - + // 确保数据不重复 if (loadMore) { setEpisodeList(prev => { @@ -105,7 +75,7 @@ export default function CreateToVideo2() { } else { setEpisodeList(movie_projects); } - + setTotalPages(total_pages); setHasMore(page < total_pages); setCurrentPage(page); @@ -119,7 +89,39 @@ export default function CreateToVideo2() { // 清除当前加载页码 loadingPageRef.current = null; } - }; + }, [perPage]); + const handleScroll = useCallback(() => { + if (!scrollContainerRef.current || !hasMore || isLoadingMore || isLoading) return; + + const { scrollTop, scrollHeight, clientHeight } = scrollContainerRef.current; + if (scrollHeight - scrollTop - clientHeight < 100) { + // 直接使用 currentPage,不再使用 setCurrentPage 的回调 + const nextPage = currentPage + 1; + if (nextPage <= totalPages) { + getEpisodeList(userId, nextPage, true); + } + } + }, [hasMore, isLoadingMore, isLoading, totalPages, userId, currentPage, getEpisodeList]); + + useEffect(() => { + if (typeof window !== 'undefined') { + const currentUser = JSON.parse(localStorage.getItem('currentUser') || '{}'); + console.log('currentUser', currentUser); + setUserId(currentUser.id); + getEpisodeList(currentUser.id, 1, false); + } + }, [getEpisodeList]); + + // 添加滚动监听 + useEffect(() => { + const scrollContainer = scrollContainerRef.current; + if (scrollContainer) { + scrollContainer.addEventListener('scroll', handleScroll); + return () => scrollContainer.removeEventListener('scroll', handleScroll); + } + }, [handleScroll]); + + // 原函数位置已上移 // 视频上传和创建功能已迁移到ChatInputBox组件中 @@ -188,19 +190,38 @@ export default function CreateToVideo2() { } }; + /** + * 根据元数据记录视频朝向(横/竖) + * @param {string} projectId - 项目唯一标识 + * @param {HTMLVideoElement} videoEl - 视频元素 + */ + const handleVideoMetadata = (projectId: string, videoEl: HTMLVideoElement) => { + const { videoWidth, videoHeight } = videoEl; + if (!videoWidth || !videoHeight) return; + setOrientationMap((prev) => { + if (prev[projectId]) return prev; + const next = videoWidth >= videoHeight ? 'landscape' : 'portrait'; + return { ...prev, [projectId]: next }; + }); + }; + const renderProjectCard = (project: any) => { return (
handleMouseEnter(project.project_id)} onMouseLeave={() => handleMouseLeave(project.project_id)} data-alt="project-card" > {/* 视频/图片区域 */} -
router.push(`/movies/work-flow?episodeId=${project.project_id}`)}> +
router.push(`/movies/work-flow?episodeId=${project.project_id}`)} + data-alt="media-container" + > {(project.final_video_url || project.final_simple_video_url || project.video_urls) ? (
{/* TODO 删除 */} - {/* + {/* */}
@@ -282,7 +304,7 @@ export default function CreateToVideo2() { {episodeList.length > 0 && ( /* 优化的剧集网格 */
-
+
{episodeList.map(renderProjectCard)}
diff --git a/components/pages/work-flow.tsx b/components/pages/work-flow.tsx index 97f2de6..298c99e 100644 --- a/components/pages/work-flow.tsx +++ b/components/pages/work-flow.tsx @@ -222,7 +222,8 @@ const WorkFlow = React.memo(function WorkFlow() { showGotoCutButton, generateEditPlan, handleRetryVideo, - isShowAutoEditing + isShowAutoEditing, + aspectRatio } = useWorkflowData({ onEditPlanGenerated: handleEditPlanGenerated, editingStatus: editingStatus, @@ -537,6 +538,7 @@ Please process this video editing request.`; onRetryVideo={handleRetryVideo} className={isDesktop ? 'auto-cols-[20%]' : (isTablet ? 'auto-cols-[25%]' : 'auto-cols-[40%]')} selectedView={selectedView} + aspectRatio={aspectRatio} />
)} @@ -622,7 +624,7 @@ Please process this video editing request.`;
{/* 智能对话弹窗 */} - - + */} ( -
+
) : ( -
+
{status === 0 && ( Generating... )} @@ -285,7 +285,7 @@ export function H5MediaViewer({ // 渲染图片 slide const renderImageSlides = () => ( -
+
{imageUrls.map((url, idx) => (
- scene + scene
))}
@@ -416,7 +416,7 @@ export function H5MediaViewer({ data-alt="final-thumb-item" aria-label="Select final video" > - final + final
Final
diff --git a/components/pages/work-flow/media-viewer.tsx b/components/pages/work-flow/media-viewer.tsx index f673538..0cafa86 100644 --- a/components/pages/work-flow/media-viewer.tsx +++ b/components/pages/work-flow/media-viewer.tsx @@ -176,7 +176,7 @@ export const MediaViewer = React.memo(function MediaViewer({ return (