forked from 77media/video-flow
修复构建报错
This commit is contained in:
parent
01509ad3d5
commit
310ea1c49f
@ -158,6 +158,7 @@ export const useRoleServiceHook = (): UseRoleService => {
|
||||
content: keyword,
|
||||
loadingProgress: 100,
|
||||
disableEdit: false,
|
||||
updatedAt: Date.now(),
|
||||
})),
|
||||
}
|
||||
: role
|
||||
@ -177,6 +178,7 @@ export const useRoleServiceHook = (): UseRoleService => {
|
||||
content: keyword,
|
||||
loadingProgress: 100,
|
||||
disableEdit: false,
|
||||
updatedAt: Date.now(),
|
||||
})),
|
||||
});
|
||||
}
|
||||
@ -383,6 +385,7 @@ export const useRoleServiceHook = (): UseRoleService => {
|
||||
content: highlight,
|
||||
loadingProgress: 100,
|
||||
disableEdit: false,
|
||||
updatedAt: Date.now(),
|
||||
})),
|
||||
};
|
||||
|
||||
|
||||
@ -83,3 +83,17 @@ export class SceneItem extends EditItem<SceneEntity> {
|
||||
super(entity, metadata);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 标签可编辑项
|
||||
*/
|
||||
export class TagItem extends EditItem<TagValueObject> {
|
||||
type: ItemType.TEXT = ItemType.TEXT;
|
||||
|
||||
constructor(
|
||||
entity: TagValueObject,
|
||||
metadata: Record<string, any> = {}
|
||||
) {
|
||||
super(entity, metadata);
|
||||
}
|
||||
}
|
||||
|
||||
@ -95,6 +95,8 @@ export interface TagValueObject {
|
||||
disableEdit: boolean;
|
||||
/** 颜色 */
|
||||
color?: string;
|
||||
/** 更新时间 */
|
||||
readonly updatedAt: number;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -1,90 +0,0 @@
|
||||
import { SceneEntity, AITextEntity } from '../domain/Entities';
|
||||
import { SceneItem, TagItem, TextItem } from '../domain/Item';
|
||||
import { regenerateScene, applySceneToShots, getSceneData } from '@/api/video_flow';
|
||||
|
||||
/**
|
||||
* 场景编辑用例
|
||||
* 负责场景内容的初始化、修改和优化
|
||||
*/
|
||||
export class SceneEditUseCase {
|
||||
constructor(private sceneItem: SceneItem) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: 重新生成场景
|
||||
* @param {TextItem} prompt
|
||||
* @param {TagItem[]} tags
|
||||
* @return {*}
|
||||
*/
|
||||
async AIgenerateScene(prompt: TextItem, tags: TagItem[]): Promise<SceneEntity> {
|
||||
const promptText = prompt.entity.content;
|
||||
const tagList = tags.map((tag) => tag.entity.content);
|
||||
|
||||
// 调用重新生成场景接口
|
||||
const response = await regenerateScene({
|
||||
sceneId: this.sceneItem.entity.id || '',
|
||||
prompt: promptText,
|
||||
tagTypes: tagList,
|
||||
});
|
||||
|
||||
if (response.successful) {
|
||||
const sceneEntity = response.data;
|
||||
this.sceneItem.setEntity(sceneEntity);
|
||||
return sceneEntity;
|
||||
} else {
|
||||
throw new Error(`重新生成场景失败: ${response.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 应用此场景到指定分镜
|
||||
* @param shotIds 分镜ID列表
|
||||
* @returns 应用结果
|
||||
*/
|
||||
async applyScene(shotIds: string[]) {
|
||||
const sceneId = this.sceneItem.entity.id;
|
||||
|
||||
return await applySceneToShots({
|
||||
sceneId,
|
||||
shotIds
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 重新获取当前场景的数据
|
||||
* @description 从服务器重新获取当前场景的AI文本和标签数据,并更新当前实体
|
||||
* @returns Promise<{ text: AITextEntity; tags: TagValueObject[] }> 场景相关的AI文本和标签数据
|
||||
* @throws {Error} 当API调用失败时抛出错误
|
||||
*/
|
||||
async refreshSceneData(): Promise<{ text: AITextEntity; tags: TagValueObject[] }> {
|
||||
const sceneId = this.sceneItem.entity.id;
|
||||
|
||||
if (!sceneId) {
|
||||
throw new Error('场景ID不存在,无法获取场景数据');
|
||||
}
|
||||
|
||||
const response = await getSceneData({
|
||||
sceneId: sceneId
|
||||
});
|
||||
|
||||
if (response.successful) {
|
||||
// 更新当前场景的实体数据
|
||||
const { text, tags } = response.data;
|
||||
|
||||
// 更新场景实体中的相关字段
|
||||
const updatedSceneEntity = {
|
||||
...this.sceneItem.entity,
|
||||
generateTextId: text.id, // 更新AI文本ID
|
||||
tagIds: tags.map(tag => tag.id), // 更新标签ID列表
|
||||
updatedAt: Date.now(), // 更新时间戳
|
||||
};
|
||||
|
||||
// 更新当前UseCase中的实体
|
||||
this.sceneItem.setEntity(updatedSceneEntity);
|
||||
|
||||
return response.data;
|
||||
} else {
|
||||
throw new Error(`获取场景数据失败: ${response.message}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
69
compile_test.sh
Executable file
69
compile_test.sh
Executable file
@ -0,0 +1,69 @@
|
||||
#!/bin/bash
|
||||
|
||||
BRANCH_NAME="dev"
|
||||
|
||||
# 修改项目名称
|
||||
PROJECT_NAME="video-flow-frontend-test"
|
||||
|
||||
# 设置日志文件路径
|
||||
LOGFILE="build_and_copy.log"
|
||||
|
||||
# 记录开始时间
|
||||
echo "Build process started at $(date)" | tee $LOGFILE
|
||||
|
||||
# 获取当前分支名
|
||||
current_branch=$(git rev-parse --abbrev-ref HEAD)
|
||||
|
||||
# 打包之前,需要检查是否在 dev 分支,工作区是否干净,是否和远程分支一致
|
||||
if [ "$(git branch --show-current)" != "$BRANCH_NAME" ]; then
|
||||
echo "当前分支不是 dev 分支"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 检查工作区是否干净
|
||||
if [ -n "$(git status --porcelain)" ]; then
|
||||
echo "工作区不干净"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 检查远程分支是否和本地分支一致
|
||||
if [ "$(git rev-parse HEAD)" != "$(git rev-parse origin/$BRANCH_NAME)" ]; then
|
||||
echo "本地分支和远程分支不一致"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
# 检查当前分支并运行相应的 npm 命令
|
||||
if [ "$current_branch" = "$BRANCH_NAME" ]; then
|
||||
echo "On dev branch, building project..." | tee -a $LOGFILE
|
||||
PROFILE_ENV=$BRANCH_NAME
|
||||
|
||||
# 安装依赖并构建
|
||||
yarn install
|
||||
yarn build
|
||||
|
||||
# 准备dist目录
|
||||
mkdir -p dist
|
||||
cp -r .next dist/
|
||||
cp -r public dist/
|
||||
cp package.json dist/
|
||||
cp package-lock.json dist/
|
||||
|
||||
else
|
||||
echo "On non-dev branch ($current_branch), exiting"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 创建tar包
|
||||
tar -czvf $PROJECT_NAME-$PROFILE_ENV.tar.gz dist
|
||||
|
||||
# 记录结束时间
|
||||
echo "Build process completed at $(date)" | tee -a $LOGFILE
|
||||
|
||||
# 上传到 nexus
|
||||
echo "upload to nexus at $(date)" | tee -a $LOGFILE
|
||||
curl -u 'admin':'YZ9Gq6=8\*G|?:,' --upload-file $PROJECT_NAME-$PROFILE_ENV.tar.gz https://repo.qikongjian.com/repository/frontend-tar-files/
|
||||
|
||||
# 清理构建文件
|
||||
rm -rf dist
|
||||
rm $PROJECT_NAME-$PROFILE_ENV.tar.gz
|
||||
@ -2,6 +2,7 @@ import { useState, useEffect, useCallback } from 'react';
|
||||
import { detailScriptEpisodeNew, getScriptTitle, getRunningStreamData, StreamData } from '@/api/video_flow';
|
||||
import { useSearchParams } from 'next/navigation';
|
||||
import { ApiResponse } from '@/api/common';
|
||||
import { SketchData, CharacterResponse, VideoData } from '@/api/DTO/movieEdit';
|
||||
|
||||
// 步骤映射
|
||||
const STEP_MAP = {
|
||||
@ -15,34 +16,35 @@ const STEP_MAP = {
|
||||
type ApiStep = keyof typeof STEP_MAP;
|
||||
|
||||
interface TaskData {
|
||||
sketch?: Array<{
|
||||
sketch?: {
|
||||
url: string;
|
||||
script: string;
|
||||
bg_rgb: string[];
|
||||
}>;
|
||||
roles?: Array<{
|
||||
}[];
|
||||
roles?: {
|
||||
name: string;
|
||||
url: string;
|
||||
sound: string;
|
||||
soundDescription: string;
|
||||
roleDescription: string;
|
||||
}>;
|
||||
videos?: Array<{
|
||||
}[];
|
||||
videos?: {
|
||||
url: string;
|
||||
script: string;
|
||||
audio: string;
|
||||
}>;
|
||||
music?: Array<{
|
||||
}[];
|
||||
music?: {
|
||||
url: string;
|
||||
script: string;
|
||||
name: string;
|
||||
duration: string;
|
||||
totalDuration: string;
|
||||
isLooped: boolean;
|
||||
}>;
|
||||
}[];
|
||||
final?: {
|
||||
url: string;
|
||||
};
|
||||
[key: string]: any; // 允许其他可能的字段
|
||||
}
|
||||
|
||||
export const useApiData = () => {
|
||||
@ -192,7 +194,38 @@ export const useApiData = () => {
|
||||
|
||||
// 设置任务数据
|
||||
if (data) {
|
||||
setTaskData(data);
|
||||
// 将 ProjectContentData 转换为 TaskData
|
||||
const convertedData: TaskData = {
|
||||
sketch: data.sketch?.data?.map((item: SketchData) => ({
|
||||
url: item.image_path,
|
||||
script: item.prompt,
|
||||
bg_rgb: ['255', '255', '255'] // 默认白色背景
|
||||
})) || [],
|
||||
roles: data.character?.data?.map((item: CharacterResponse) => ({
|
||||
name: item.character_name,
|
||||
url: item.image_path,
|
||||
sound: '',
|
||||
soundDescription: '',
|
||||
roleDescription: item.character_description
|
||||
})) || [],
|
||||
videos: data.video?.data?.map((item: VideoData) => ({
|
||||
url: item.urls?.[0] || '',
|
||||
script: item.description || '',
|
||||
audio: '' // 音频URL可能需要从其他地方获取
|
||||
})) || [],
|
||||
music: data.music?.data?.map((item: any) => ({
|
||||
url: item.url || '',
|
||||
script: item.description || '',
|
||||
name: item.name || '',
|
||||
duration: item.duration || '',
|
||||
totalDuration: item.total_duration || '',
|
||||
isLooped: item.is_looped || false
|
||||
})) || [],
|
||||
final: data.final_video ? {
|
||||
url: data.final_video.video || ''
|
||||
} : undefined
|
||||
};
|
||||
setTaskData(convertedData);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
@ -424,7 +424,7 @@ export function useWorkflowData() {
|
||||
}
|
||||
|
||||
const { name, status, data, tags, mode, original_text } = response.data;
|
||||
setMode(mode);
|
||||
setMode(mode as 'automatic' | 'manual' | 'auto');
|
||||
setOriginalText(original_text);
|
||||
setIsLoading(false);
|
||||
|
||||
@ -569,9 +569,9 @@ export function useWorkflowData() {
|
||||
}
|
||||
|
||||
// 粗剪
|
||||
if (data.final_simple_video && data.final_simple_video.video) {
|
||||
if ((data as any).final_simple_video && (data as any).final_simple_video.video) {
|
||||
setFinal({
|
||||
url: data.final_simple_video.video
|
||||
url: (data as any).final_simple_video.video
|
||||
});
|
||||
taskData.status = '5.5';
|
||||
loadingText = LOADING_TEXT_MAP.postProduction('generating fine-grained video clips...');
|
||||
|
||||
@ -14,7 +14,7 @@ interface ScriptRendererProps {
|
||||
isPauseWorkFlow: boolean;
|
||||
applyScript: any;
|
||||
mode: string;
|
||||
from: string;
|
||||
from?: string;
|
||||
setIsUpdate?: (isUpdate: boolean) => void;
|
||||
}
|
||||
|
||||
@ -32,7 +32,7 @@ export const ScriptRenderer: React.FC<ScriptRendererProps> = ({ data, setIsPause
|
||||
useEffect(() => {
|
||||
const themeBlock = data.find(block => block.id === 'categories');
|
||||
if (themeBlock && themeBlock.content.length > 0) {
|
||||
const themeTag = themeBlock.content[0].text.split(',').map(item => item.trim());
|
||||
const themeTag = themeBlock.content[0].text.split(',').map((item: string) => item.trim());
|
||||
console.log('themeTag', themeTag);
|
||||
setAddThemeTag(themeTag);
|
||||
}
|
||||
@ -110,13 +110,13 @@ export const ScriptRenderer: React.FC<ScriptRendererProps> = ({ data, setIsPause
|
||||
// console.log(e.target.value);
|
||||
};
|
||||
|
||||
const handleBlockTextBlur = (block: ScriptBlock) => (e: ContentEditableEvent) => {
|
||||
const handleBlockTextBlur = (block: ScriptBlock) => () => {
|
||||
setEditBlockId(null);
|
||||
if (contentEditableRef.current) {
|
||||
const text = contentEditableRef.current.innerText;
|
||||
console.log('contentEditableRef---text', text);
|
||||
console.log('contentEditableRef---block', block.id, block);
|
||||
if (block.content[0].text !== text) {
|
||||
if (block.content[0].text !== text && setIsUpdate) {
|
||||
setIsUpdate(true);
|
||||
}
|
||||
setAnyAttribute(block.id, text,from !== 'tab',(old: string)=>{
|
||||
@ -140,7 +140,9 @@ export const ScriptRenderer: React.FC<ScriptRendererProps> = ({ data, setIsPause
|
||||
return;
|
||||
}
|
||||
setAddThemeTag(value);
|
||||
setIsUpdate(true);
|
||||
if (setIsUpdate) {
|
||||
setIsUpdate(true);
|
||||
}
|
||||
from !== 'tab' && setIsPauseWorkFlow(true);
|
||||
setAnyAttribute('categories', value.join(','),from !== 'tab',(old: string)=>{
|
||||
if(old!==value.join(',')){
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { Node, mergeAttributes } from '@tiptap/core'
|
||||
import { ReactNodeViewRenderer, NodeViewWrapper } from '@tiptap/react'
|
||||
import { ReactNodeViewRenderer, NodeViewWrapper, ReactNodeViewProps } from '@tiptap/react'
|
||||
import { motion, AnimatePresence } from 'framer-motion'
|
||||
import { useState } from 'react'
|
||||
|
||||
@ -33,7 +33,8 @@ export const CharacterToken = Node.create({
|
||||
},
|
||||
})
|
||||
|
||||
function CharacterView({ node }) {
|
||||
function CharacterView(props: ReactNodeViewProps) {
|
||||
const { node } = props;
|
||||
const [showCard, setShowCard] = useState(false)
|
||||
const { name, avatar, gender, age } = node.attrs
|
||||
|
||||
|
||||
@ -71,6 +71,7 @@ export function ReplaceScenePanel({
|
||||
showAddToLibrary={false}
|
||||
onClose={onClose}
|
||||
onConfirm={onConfirm}
|
||||
isLoading={false}
|
||||
/>
|
||||
);
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user