forked from 77media/video-flow
Merge branch 'dev' of https://git.qikongjian.com/77media/video-flow into dev
This commit is contained in:
commit
55a61424e8
@ -57,7 +57,7 @@ export const useEditData = (tabType: string) => {
|
||||
toggleShotSelection,
|
||||
applyRoleToSelectedShots,
|
||||
clearShotSelection
|
||||
} = useRoleShotServiceHook(projectId);
|
||||
} = useRoleShotServiceHook(projectId, selectedRole);
|
||||
|
||||
useEffect(() => {
|
||||
if (tabType === 'shot') {
|
||||
@ -69,7 +69,6 @@ export const useEditData = (tabType: string) => {
|
||||
setLoading(false);
|
||||
});
|
||||
} else if (tabType === 'role') {
|
||||
// fetchUserRoleLibrary();
|
||||
fetchRoleList(projectId).then(() => {
|
||||
setLoading(false);
|
||||
}).catch((err) => {
|
||||
@ -105,6 +104,7 @@ export const useEditData = (tabType: string) => {
|
||||
optimizeRoleText,
|
||||
updateRoleText,
|
||||
regenerateRole,
|
||||
fetchUserRoleLibrary,
|
||||
// role shot
|
||||
shotSelectionList,
|
||||
selectedRoleId,
|
||||
|
||||
@ -3,6 +3,7 @@ import { ImageWave } from '@/components/ui/ImageWave';
|
||||
import { RoleEntity } from '@/app/service/domain/Entities';
|
||||
|
||||
interface CharacterLibrarySelectorProps {
|
||||
isLoading: boolean;
|
||||
isReplaceLibraryOpen: boolean;
|
||||
setIsReplaceLibraryOpen: (open: boolean) => void;
|
||||
onSelect: (index: number) => void;
|
||||
@ -11,13 +12,28 @@ interface CharacterLibrarySelectorProps {
|
||||
}
|
||||
|
||||
export function CharacterLibrarySelector({
|
||||
isLoading,
|
||||
isReplaceLibraryOpen,
|
||||
setIsReplaceLibraryOpen,
|
||||
onSelect,
|
||||
userRoleLibrary = []
|
||||
}: CharacterLibrarySelectorProps) {
|
||||
// 将 RoleEntity[] 转换为图片URL数组
|
||||
const imageUrls = userRoleLibrary.map(role => role.imageUrl);
|
||||
|
||||
if (isLoading) {
|
||||
return (
|
||||
<FloatingGlassPanel
|
||||
open={isReplaceLibraryOpen}
|
||||
width='90vw'
|
||||
panel_style={{ background: 'unset', border: 'unset', backdropFilter: 'unset', boxShadow: 'none' }}
|
||||
onClose={() => setIsReplaceLibraryOpen(false)}
|
||||
>
|
||||
<div className="flex flex-col items-center justify-center w-full h-64 text-white/50">
|
||||
<div className="w-12 h-12 mb-4 animate-spin rounded-full border-b-2 border-blue-600" />
|
||||
<p>Loading...</p>
|
||||
</div>
|
||||
</FloatingGlassPanel>
|
||||
);
|
||||
}
|
||||
|
||||
// 如果没有数据,显示空状态
|
||||
if (userRoleLibrary.length === 0) {
|
||||
@ -44,7 +60,7 @@ export function CharacterLibrarySelector({
|
||||
>
|
||||
{/* 内容 */}
|
||||
<ImageWave
|
||||
images={imageUrls}
|
||||
images={userRoleLibrary.map(role => role.imageUrl)}
|
||||
containerWidth="90vw"
|
||||
containerHeight="calc(var(--index) * 15)"
|
||||
itemWidth="calc(var(--index) * 2)"
|
||||
|
||||
@ -10,6 +10,7 @@ import { CharacterLibrarySelector } from './character-library-selector';
|
||||
import HorizontalScroller from './HorizontalScroller';
|
||||
import { useEditData } from '@/components/pages/work-flow/use-edit-data';
|
||||
import { useSearchParams } from 'next/navigation';
|
||||
import { RoleEntity } from '@/app/service/domain/Entities';
|
||||
|
||||
interface Appearance {
|
||||
hairStyle: string;
|
||||
@ -75,6 +76,8 @@ export function CharacterTabContent({
|
||||
const characterEditorRef = useRef<any>(null);
|
||||
const [isInitialized, setIsInitialized] = useState(false);
|
||||
const [isRegenerate, setIsRegenerate] = useState(false);
|
||||
const [isLoadingShots, setIsLoadingShots] = useState(false);
|
||||
const [isLoadingLibrary, setIsLoadingLibrary] = useState(false);
|
||||
|
||||
const {
|
||||
loading,
|
||||
@ -85,16 +88,11 @@ export function CharacterTabContent({
|
||||
optimizeRoleText,
|
||||
updateRoleText,
|
||||
regenerateRole,
|
||||
fetchUserRoleLibrary,
|
||||
// role shot
|
||||
shotSelectionList,
|
||||
selectedRoleId,
|
||||
isAllVideoSegmentSelected,
|
||||
selectedVideoSegmentCount,
|
||||
fetchRoleShots,
|
||||
toggleSelectAllShots,
|
||||
toggleShotSelection,
|
||||
applyRoleToSelectedShots,
|
||||
clearShotSelection
|
||||
applyRoleToSelectedShots
|
||||
} = useEditData('role');
|
||||
const searchParams = useSearchParams();
|
||||
const episodeId = searchParams.get('episodeId');
|
||||
@ -113,16 +111,22 @@ export function CharacterTabContent({
|
||||
console.log('获取选中项数据', selectedRole);
|
||||
}, [selectedRole]);
|
||||
|
||||
useEffect(() => {
|
||||
console.log('获取角色库数据', userRoleLibrary);
|
||||
}, [userRoleLibrary]);
|
||||
|
||||
const handleSmartPolish = (text: string) => {
|
||||
// 然后调用优化角色文本
|
||||
optimizeRoleText(text);
|
||||
};
|
||||
|
||||
const handleStartReplaceCharacter = () => {
|
||||
// 获取当前角色对应的视频片段
|
||||
fetchRoleShots(selectedRole?.id || '');
|
||||
// 打开替换角色面板
|
||||
const handleStartReplaceCharacter = async () => {
|
||||
setIsLoadingShots(true);
|
||||
setIsReplacePanelOpen(true);
|
||||
// 获取当前角色对应的视频片段
|
||||
await fetchRoleShots(selectedRole?.name || '');
|
||||
// 打开替换角色面板
|
||||
setIsLoadingShots(false);
|
||||
};
|
||||
|
||||
const handleConfirmGotoReplace = () => {
|
||||
@ -146,6 +150,7 @@ export function CharacterTabContent({
|
||||
// 处理替换确认逻辑
|
||||
console.log('Selected shots:', selectedShots);
|
||||
console.log('Add to library:', addToLibrary);
|
||||
applyRoleToSelectedShots(selectedRole || {} as RoleEntity);
|
||||
setIsReplacePanelOpen(false);
|
||||
};
|
||||
|
||||
@ -185,9 +190,12 @@ export function CharacterTabContent({
|
||||
}
|
||||
};
|
||||
|
||||
const handleOpenReplaceLibrary = () => {
|
||||
const handleOpenReplaceLibrary = async () => {
|
||||
setIsLoadingLibrary(true);
|
||||
setIsReplaceLibraryOpen(true);
|
||||
setShowAddToLibrary(true);
|
||||
await fetchUserRoleLibrary();
|
||||
setIsLoadingLibrary(false);
|
||||
};
|
||||
|
||||
const handleRegenerate = async () => {
|
||||
@ -200,6 +208,7 @@ export function CharacterTabContent({
|
||||
// 然后调用重新生成角色
|
||||
await regenerateRole();
|
||||
setIsRegenerate(false);
|
||||
handleStartReplaceCharacter();
|
||||
};
|
||||
|
||||
const handleUploadClick = () => {
|
||||
@ -384,8 +393,9 @@ export function CharacterTabContent({
|
||||
onClose={() => handleCloseReplacePanel()}
|
||||
>
|
||||
<ReplaceCharacterPanel
|
||||
isLoading={isLoadingShots}
|
||||
shots={shotSelectionList}
|
||||
character={selectedRole}
|
||||
role={selectedRole}
|
||||
showAddToLibrary={showAddToLibrary}
|
||||
onClose={() => handleCloseReplacePanel()}
|
||||
onConfirm={handleConfirmReplace}
|
||||
@ -394,6 +404,7 @@ export function CharacterTabContent({
|
||||
|
||||
{/* 从角色库中选择角色 */}
|
||||
<CharacterLibrarySelector
|
||||
isLoading={isLoadingLibrary}
|
||||
isReplaceLibraryOpen={isReplaceLibraryOpen}
|
||||
setIsReplaceLibraryOpen={setIsReplaceLibraryOpen}
|
||||
onSelect={handleSelectCharacter}
|
||||
|
||||
@ -1,9 +1,11 @@
|
||||
import { ReplacePanel } from './replace-panel';
|
||||
import { Shot, Character } from '@/app/model/types';
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
interface ReplaceCharacterPanelProps {
|
||||
isLoading: boolean;
|
||||
shots: any[];
|
||||
character: Character;
|
||||
role: any;
|
||||
showAddToLibrary?: boolean;
|
||||
onClose: () => void;
|
||||
onConfirm: (selectedShots: string[], addToLibrary: boolean) => void;
|
||||
@ -40,21 +42,24 @@ export const mockShots: Shot[] = [
|
||||
];
|
||||
|
||||
export function ReplaceCharacterPanel({
|
||||
shots = [],
|
||||
character,
|
||||
isLoading,
|
||||
shots,
|
||||
role,
|
||||
showAddToLibrary = true,
|
||||
onClose,
|
||||
onConfirm,
|
||||
}: ReplaceCharacterPanelProps) {
|
||||
|
||||
return (
|
||||
<ReplacePanel
|
||||
title="替换新形象"
|
||||
shots={shots}
|
||||
item={character}
|
||||
item={role}
|
||||
showAddToLibrary={showAddToLibrary}
|
||||
addToLibraryText="新形象同步添加至角色库"
|
||||
onClose={onClose}
|
||||
onConfirm={onConfirm}
|
||||
isLoading={isLoading}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@ -4,6 +4,7 @@ import { Check, X, CircleAlert, ArrowLeft, ArrowRight } from 'lucide-react';
|
||||
import { cn } from '@/public/lib/utils';
|
||||
|
||||
interface ReplacePanelProps {
|
||||
isLoading: boolean;
|
||||
title: string;
|
||||
shots: any[];
|
||||
item: any;
|
||||
@ -14,6 +15,7 @@ interface ReplacePanelProps {
|
||||
}
|
||||
|
||||
export function ReplacePanel({
|
||||
isLoading,
|
||||
title,
|
||||
shots,
|
||||
item,
|
||||
@ -56,11 +58,11 @@ export function ReplacePanel({
|
||||
}, []);
|
||||
|
||||
const handleShotToggle = (shotId: string) => {
|
||||
setSelectedShots(prev =>
|
||||
prev.includes(shotId)
|
||||
? prev.filter(id => id !== shotId)
|
||||
: [...prev, shotId]
|
||||
);
|
||||
// setSelectedShots(prev =>
|
||||
// prev.includes(shotId)
|
||||
// ? prev.filter(id => id !== shotId)
|
||||
// : [...prev, shotId]
|
||||
// );
|
||||
};
|
||||
|
||||
const handleSelectAllShots = (checked: boolean) => {
|
||||
@ -104,6 +106,15 @@ export function ReplacePanel({
|
||||
});
|
||||
};
|
||||
|
||||
if (isLoading) {
|
||||
return (
|
||||
<div className="flex flex-col items-center justify-center w-full max-w-5xl text-white/50">
|
||||
<div className="w-12 h-12 mb-4 animate-spin rounded-full border-b-2 border-blue-600" />
|
||||
<p>Loading...</p>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="space-y-2 w-full max-w-5xl">
|
||||
{/* 标题 */}
|
||||
@ -115,7 +126,7 @@ export function ReplacePanel({
|
||||
<CircleAlert className="w-4 h-4" />
|
||||
该内容出现在 <span className="text-blue-500">{shots.length}</span> 个分镜中,替换后将影响如下分镜
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
{/* <div className="flex items-center gap-2">
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={selectedShots.length === shots.length}
|
||||
@ -123,12 +134,12 @@ export function ReplacePanel({
|
||||
className="w-4 h-4 rounded border-white/20"
|
||||
/>
|
||||
<label className="text-white/80">全选</label>
|
||||
</div>
|
||||
</div> */}
|
||||
</div>
|
||||
|
||||
{/* 分镜展示区 */}
|
||||
<div className="space-y-2 relative">
|
||||
<div className="text-white/80 text-sm">选择需要替换的分镜:</div>
|
||||
{/* <div className="text-white/80 text-sm">选择需要替换的分镜:</div> */}
|
||||
<div className="relative flex gap-4 overflow-x-auto pb-4 hide-scrollbar h-64" ref={shotsRef}>
|
||||
{shots.map((shot) => (
|
||||
<motion.div
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user