添加查看角色下视频状态

This commit is contained in:
北枳 2025-08-18 20:20:31 +08:00
parent 94cd1c92be
commit 3635e67c0a
4 changed files with 41 additions and 60 deletions

View File

@ -987,7 +987,7 @@ export const batchUpdateVideoSegments = async (request: {
/** 新的视频地址列表 */
video_urls: string[];
/** 新的状态 0:视频加载中 1:任务已完成 2:任务失败 */
status: number;
status: number | null;
/** 优化后的描述文本 */
optimized_description?: string;
/** 关键词列表 */
@ -1033,7 +1033,8 @@ export const getCharacterShots = async (request: {
video_id: string;
video_status: number|null;
}[];
/** 视频状态 */
video_status: number|null;
}>;
/** 总数量 */
total_count: number;

View File

@ -98,7 +98,7 @@ export const useRoleShotServiceHook = (projectId: string,selectRole?:RoleEntity,
name: `视频片段_${scene.video_id}`,
sketchUrl: "",
videoUrl: scene.video_urls,// 保持为string[]类型
status:scene.video_urls.length>0?1:0, // 默认为已完成状态
status: scene.video_status !== null? scene.video_status : scene.video_urls.length>0?1:0, // 默认为已完成状态
lens: [],
selected: false,
applied: true // 由于是通过角色查询到的,所以都是已应用的

View File

@ -88,7 +88,7 @@ export interface VideoSegmentEntity {
video_status: number | null;
}[];
/**视频片段状态 0:视频加载中 1:任务已完成 2:任务失败 */
status: number;
status: number|null;
/**镜头项 */
lens: LensType[];
}

View File

@ -1,6 +1,6 @@
import React, { useState, useRef } from 'react';
import React, { useState, useRef, useEffect } from 'react';
import { motion } from 'framer-motion';
import { Check, X, CircleAlert, ArrowLeft, ArrowRight } from 'lucide-react';
import { Check, X, CircleAlert, ArrowLeft, ArrowRight, Loader2 } from 'lucide-react';
import { cn } from '@/public/lib/utils';
import { throttle } from 'lodash';
@ -30,33 +30,12 @@ export function ReplacePanel({
);
const [addToLibrary, setAddToLibrary] = useState(false);
const [hoveredVideoId, setHoveredVideoId] = useState<string | null>(null);
const [isAtStart, setIsAtStart] = useState(true);
const [isAtEnd, setIsAtEnd] = useState(false);
const videoRefs = useRef<{ [key: string]: HTMLVideoElement }>({});
const shotsRef = useRef<HTMLDivElement>(null);
// 检查滚动位置
const checkScrollPosition = () => {
if (!shotsRef.current) return;
const { scrollLeft, scrollWidth, clientWidth } = shotsRef.current;
setIsAtStart(scrollLeft <= 0);
setIsAtEnd(Math.ceil(scrollLeft + clientWidth) >= scrollWidth);
};
// 添加滚动事件监听
React.useEffect(() => {
const shotsElement = shotsRef.current;
if (!shotsElement) return;
shotsElement.addEventListener('scroll', checkScrollPosition);
// 初始检查
checkScrollPosition();
return () => {
shotsElement.removeEventListener('scroll', checkScrollPosition);
};
}, []);
useEffect(() => {
console.log('replace-panel-shots', shots);
}, [shots]);
const handleShotToggle = (shotId: string) => {
// setSelectedShots(prev =>
@ -66,10 +45,6 @@ export function ReplacePanel({
// );
};
const handleSelectAllShots = (checked: boolean) => {
setSelectedShots(checked ? shots.map(shot => shot.id) : []);
};
const handleMouseEnter = (shotId: string) => {
setHoveredVideoId(shotId);
if (videoRefs.current[shotId]) {
@ -173,29 +148,34 @@ export function ReplacePanel({
whileHover={{ scale: 1.02 }}
whileTap={{ scale: 0.98 }}
>
{shot.videoUrl && shot.videoUrl.length > 0 && (
<video
ref={el => {
if (el) videoRefs.current[shot.id] = el;
}}
src={shot.videoUrl[0]}
className="w-full h-full object-cover"
loop
muted
playsInline
/>
)}
{(!shot.videoUrl || shot.videoUrl.length === 0) && (
<>
<img
src={shot.sketchUrl}
className="w-full h-full object-cover"
/>
<div className="absolute inset-0 bg-black/50 flex items-center justify-center">
<div className="text-white text-sm">Generating...</div>
<>
{(shot.status === 0 || !shot.videoUrl.length) && (
<div className="w-full h-full absolute inset-0 bg-black/50 flex items-center justify-center">
<div className="text-white text-sm">
<Loader2 className="w-4 h-4 animate-spin" />
</div>
</div>
</>
)}
)}
{shot.status === 2 && (
<div className="w-full h-full absolute inset-0 bg-black/50 flex items-center justify-center">
<div className="text-white text-sm">
<CircleAlert className="w-4 h-4" />
</div>
</div>
)}
{shot.status === 1 && shot.videoUrl.length && (
<video
ref={el => {
if (el) videoRefs.current[shot.id] = el;
}}
src={shot.videoUrl[0]}
className="w-full h-full object-cover"
loop
muted
playsInline
/>
)}
</>
</motion.div>
))}
</div>
@ -204,18 +184,18 @@ export function ReplacePanel({
<div
className={cn(
"absolute top-1/2 -translate-y-1/2 left-0 w-10 h-10 rounded-full bg-black/50 flex items-center justify-center transition-opacity duration-200",
isAtStart ? "opacity-30 cursor-not-allowed" : "opacity-100 cursor-pointer hover:bg-black/70"
"opacity-100 cursor-pointer hover:bg-black/70"
)}
onClick={() => !isAtStart && handleLeftArrowClick()}
onClick={() => handleLeftArrowClick()}
>
<ArrowLeft className="w-4 h-4 text-white" />
</div>
<div
className={cn(
"absolute top-1/2 -translate-y-1/2 right-0 w-10 h-10 rounded-full bg-black/50 flex items-center justify-center transition-opacity duration-200",
isAtEnd ? "opacity-30 cursor-not-allowed" : "opacity-100 cursor-pointer hover:bg-black/70"
"opacity-100 cursor-pointer hover:bg-black/70"
)}
onClick={() => !isAtEnd && handleRightArrowClick()}
onClick={() => handleRightArrowClick()}
>
<ArrowRight className="w-4 h-4 text-white" />
</div>