forked from 77media/video-flow
修复问题
This commit is contained in:
parent
4291704b0b
commit
f7b1c62df3
@ -617,8 +617,6 @@ export const generateScriptStream = (
|
||||
export const applyScriptToShot = async (request: {
|
||||
/** 项目ID */
|
||||
project_id: string;
|
||||
/** 计划Id*/
|
||||
plan_id: string;
|
||||
})=> {
|
||||
return post<ApiResponse<any>>("/movie/create_movie_project_plan_v1", request);
|
||||
};
|
||||
@ -659,17 +657,14 @@ export const saveScript = async (request: {
|
||||
|
||||
|
||||
/**
|
||||
* 创建电影项目V1版本
|
||||
* @param request 创建电影项目请求参数
|
||||
* 中断视频任务
|
||||
* @returns Promise<ApiResponse<{ projectId: string }>>
|
||||
*/
|
||||
export const abortVideoTask = async (request: {
|
||||
/** 项目ID */
|
||||
project_id: string;
|
||||
/** 计划ID */
|
||||
plan_id: string;
|
||||
}): Promise<ApiResponse<any>> => {
|
||||
return post("/api/v1/video/abort", request);
|
||||
return post("/movie/abort_video_task", request);
|
||||
};
|
||||
|
||||
export const pausePlanFlow = async (request: {
|
||||
|
||||
@ -41,8 +41,6 @@ export interface UseScriptService {
|
||||
characterArc: string;
|
||||
/** 项目ID */
|
||||
projectId: string;
|
||||
/** 计划ID */
|
||||
planId: string;
|
||||
/** AI优化要求 */
|
||||
aiOptimizing: string;
|
||||
/** 渲染数据 */
|
||||
@ -58,18 +56,6 @@ export interface UseScriptService {
|
||||
applyScript: () => Promise<void>;
|
||||
/** 中断视频任务 */
|
||||
abortVideoTask: () => Promise<void>;
|
||||
/** 聚焦处理函数 */
|
||||
focusHandler: (
|
||||
field:
|
||||
| "synopsis"
|
||||
| "categories"
|
||||
| "protagonist"
|
||||
| "incitingIncident"
|
||||
| "problem"
|
||||
| "conflict"
|
||||
| "stakes"
|
||||
| "characterArc"
|
||||
) => Promise<void>;
|
||||
/** 增强剧本 */
|
||||
enhanceScript: () => Promise<void>;
|
||||
/** 设置AI优化要求 */
|
||||
@ -95,8 +81,6 @@ export interface UseScriptService {
|
||||
|
||||
/** 设置项目ID */
|
||||
setProjectId: Dispatch<SetStateAction<string>>;
|
||||
/** 设置计划ID */
|
||||
setPlanId: Dispatch<SetStateAction<string>>;
|
||||
/** 创建项目 */
|
||||
createMovieProjectV1: (
|
||||
idea: string,
|
||||
@ -127,9 +111,8 @@ export const useScriptService = (): UseScriptService => {
|
||||
const [stakes, setStakes] = useState<string>("");
|
||||
const [characterArc, setCharacterArc] = useState<string>("");
|
||||
const [projectId, setProjectId] = useState<string>("");
|
||||
const [planId, setPlanId] = useState<string>("");
|
||||
const [aiOptimizing, setAiOptimizing] = useState<string>("");
|
||||
const [focusedField, setFocusedField] = useState<string>("");
|
||||
const [fieldOld, setFieldOld] = useState<string>("");//旧的剧本内容
|
||||
|
||||
// UseCase实例
|
||||
const [scriptEditUseCase, setScriptEditUseCase] = useState<ScriptEditUseCase>(
|
||||
@ -193,7 +176,6 @@ export const useScriptService = (): UseScriptService => {
|
||||
);
|
||||
|
||||
setProjectId(projectData.project_id);
|
||||
setPlanId(projectData.plan_id);
|
||||
} catch (error) {
|
||||
console.error("创建项目失败:", error);
|
||||
throw error;
|
||||
@ -278,32 +260,31 @@ export const useScriptService = (): UseScriptService => {
|
||||
throw new Error("剧本编辑用例未初始化");
|
||||
}
|
||||
|
||||
if (!projectId || !planId) {
|
||||
if (!projectId) {
|
||||
throw new Error("项目ID或计划ID未设置");
|
||||
}
|
||||
|
||||
await scriptEditUseCase.applyScript(projectId, planId);
|
||||
await scriptEditUseCase.applyScript(projectId);
|
||||
} catch (error) {
|
||||
console.error("应用剧本失败:", error);
|
||||
throw error;
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
}, [scriptEditUseCase, projectId, planId]);
|
||||
}, [scriptEditUseCase, projectId]);
|
||||
|
||||
/**
|
||||
* 中断视频任务
|
||||
*/
|
||||
const abortVideoTaskHandler = useCallback(async (): Promise<void> => {
|
||||
try {
|
||||
if (!projectId || !planId) {
|
||||
if (!projectId) {
|
||||
throw new Error("项目ID或计划ID未设置");
|
||||
}
|
||||
|
||||
// 调用中断视频任务API
|
||||
const response = await abortVideoTask({
|
||||
project_id: projectId,
|
||||
plan_id: planId,
|
||||
});
|
||||
|
||||
if (!response.successful) {
|
||||
@ -315,7 +296,7 @@ export const useScriptService = (): UseScriptService => {
|
||||
console.error("中断视频任务失败:", error);
|
||||
throw error;
|
||||
}
|
||||
}, [projectId, planId]);
|
||||
}, [projectId]);
|
||||
|
||||
// 封装的setter函数,同时更新hook状态和scriptEditUseCase中的值对象
|
||||
const setSynopsisWrapper = useCallback(
|
||||
@ -413,44 +394,42 @@ export const useScriptService = (): UseScriptService => {
|
||||
(type: string, value: SetStateAction<string>, tags?: string[]) => {
|
||||
console.log('setAnyAttributeWrapper', type);
|
||||
if (type === 'synopsis') {
|
||||
setFieldOld(synopsis)
|
||||
scriptEditUseCase.replaceScript(fieldOld,synopsis)
|
||||
setSynopsisWrapper(value);
|
||||
} else if (type === 'categories') {
|
||||
setFieldOld(categories.join(','))
|
||||
scriptEditUseCase.replaceScript(fieldOld,categories.join(','))
|
||||
setCategoriesWrapper(tags || []);
|
||||
} else if (type === 'protagonist') {
|
||||
setFieldOld(protagonist)
|
||||
scriptEditUseCase.replaceScript(fieldOld,protagonist)
|
||||
setProtagonistWrapper(value);
|
||||
} else if (type === 'incitingIncident') {
|
||||
setFieldOld(incitingIncident)
|
||||
scriptEditUseCase.replaceScript(fieldOld,incitingIncident)
|
||||
setIncitingIncidentWrapper(value);
|
||||
} else if (type === 'problem') {
|
||||
setFieldOld(problem)
|
||||
scriptEditUseCase.replaceScript(fieldOld,problem)
|
||||
setProblemWrapper(value);
|
||||
} else if (type === 'conflict') {
|
||||
setFieldOld(conflict)
|
||||
scriptEditUseCase.replaceScript(fieldOld,conflict)
|
||||
setConflictWrapper(value);
|
||||
} else if (type === 'stakes') {
|
||||
setFieldOld(stakes)
|
||||
scriptEditUseCase.replaceScript(fieldOld,stakes)
|
||||
setStakesWrapper(value);
|
||||
} else if (type === 'characterArc') {
|
||||
setFieldOld(characterArc)
|
||||
scriptEditUseCase.replaceScript(fieldOld,characterArc)
|
||||
setCharacterArcWrapper(value);
|
||||
}
|
||||
|
||||
},
|
||||
[scriptEditUseCase]
|
||||
[categories, characterArc, conflict, fieldOld, incitingIncident, problem, protagonist, scriptEditUseCase, setCategoriesWrapper, setCharacterArcWrapper, setConflictWrapper, setIncitingIncidentWrapper, setProblemWrapper, setProtagonistWrapper, setStakesWrapper, setSynopsisWrapper, stakes, synopsis]
|
||||
);
|
||||
|
||||
/**
|
||||
* 聚焦处理函数
|
||||
*/
|
||||
const focusHandler = useCallback(
|
||||
async (field: ScriptEditKey): Promise<void> => {
|
||||
try {
|
||||
// 如果当前已经有聚焦的字段,先处理暂停/继续逻辑
|
||||
|
||||
// 设置新的聚焦字段
|
||||
setFocusedField(field);
|
||||
} catch (error) {
|
||||
console.error("聚焦处理失败:", error);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
[]
|
||||
);
|
||||
|
||||
/**
|
||||
* 增强剧本
|
||||
*/
|
||||
@ -540,7 +519,6 @@ export const useScriptService = (): UseScriptService => {
|
||||
stakes,
|
||||
characterArc,
|
||||
projectId,
|
||||
planId,
|
||||
aiOptimizing,
|
||||
scriptBlocksMemo,
|
||||
// 操作方法
|
||||
@ -549,11 +527,9 @@ export const useScriptService = (): UseScriptService => {
|
||||
updateScript,
|
||||
applyScript,
|
||||
abortVideoTask: abortVideoTaskHandler,
|
||||
focusHandler,
|
||||
enhanceScript,
|
||||
setAiOptimizing,
|
||||
setProjectId,
|
||||
setPlanId,
|
||||
createMovieProjectV1,
|
||||
// 封装的set函数
|
||||
setSynopsis: setSynopsisWrapper,
|
||||
|
||||
@ -243,44 +243,47 @@ export class StoryDetails {
|
||||
|
||||
let content = "";
|
||||
|
||||
// 定义多种匹配模式,按优先级排序
|
||||
const patterns = [
|
||||
// 1. 匹配带编号的主标题:数字. **标题:** 格式
|
||||
new RegExp(
|
||||
`\\d+\\.\\s*\\*\\*${escapedHeaderName}:?\\*\\*\\s*([\\s\\S]*?)(?=\\d+\\.\\s*\\*\\*[^*]+:?\\*\\*|\\*\\*[A-Z]+:\\*\\*|---|\$)`,
|
||||
"i"
|
||||
),
|
||||
// 定义多种匹配模式,按优先级排序
|
||||
const patterns = [
|
||||
// 1. 匹配带编号的主标题:数字. **标题:** 格式
|
||||
new RegExp(
|
||||
`\\d+\\.\\s*\\*\\*${escapedHeaderName}:?\\*\\*\\s*([\\s\\S]*?)(?=\\d+\\.\\s*\\*\\*[^*]+:?\\*\\*|\\*\\*[A-Z]+:\\*\\*|---|\$)`,
|
||||
"i"
|
||||
),
|
||||
|
||||
// 2. 匹配子标题:*标题:* 格式(在主标题下的子项)
|
||||
new RegExp(
|
||||
`\\*\\s*\\*\\*${escapedHeaderName}:?\\*\\*\\s*([\\s\\S]*?)(?=\\*\\s*\\*\\*[^*]+:?\\*\\*|\\d+\\.\\s*\\*\\*[^*]+:?\\*\\*|\\*\\*[A-Z]+:\\*\\*|---|\$)`,
|
||||
"i"
|
||||
),
|
||||
// 2. 匹配子标题:*标题:* 格式(在主标题下的子项)
|
||||
new RegExp(
|
||||
`\\*\\s*\\*\\*${escapedHeaderName}:?\\*\\*\\s*([\\s\\S]*?)(?=\\*\\s*\\*\\*[^*]+:?\\*\\*|\\d+\\.\\s*\\*\\*[^*]+:?\\*\\*|\\*\\*[A-Z]+:\\*\\*|---|\$)`,
|
||||
"i"
|
||||
),
|
||||
|
||||
// 3. 匹配独立的粗体标题:**标题:** 格式
|
||||
new RegExp(
|
||||
`^\\s*\\*\\*${escapedHeaderName}:?\\*\\*\\s*([\\s\\S]*?)(?=^\\s*\\*\\*[^*]+:?\\*\\*|\\d+\\.\\s*\\*\\*[^*]+:?\\*\\*|^\\s*\\*\\*[A-Z]+:\\*\\*|^---|\$)`,
|
||||
"im"
|
||||
),
|
||||
// 3. 匹配独立的粗体标题:**标题:** 格式
|
||||
new RegExp(
|
||||
`^\\s*\\*\\*${escapedHeaderName}:?\\*\\*\\s*([\\s\\S]*?)(?=^\\s*\\*\\*[^*]+:?\\*\\*|\\d+\\.\\s*\\*\\*[^*]+:?\\*\\*|^\\s*\\*\\*[A-Z]+:\\*\\*|^---|\$)`,
|
||||
"im"
|
||||
),
|
||||
|
||||
// 4. 匹配简单的**标题:**格式(可能在段落中)
|
||||
new RegExp(
|
||||
`\\*\\*${escapedHeaderName}:?\\*\\*\\s*([\\s\\S]*?)(?=\\*\\*[^*]+:?\\*\\*|\\d+\\.\\s*\\*\\*[^*]+:?\\*\\*|\\n\\n|---|\$)`,
|
||||
"i"
|
||||
),
|
||||
// 4. 匹配简单的粗体键值对格式:**标题:** 值(适用于简单的键值对,如 **GENRE:** Drama)
|
||||
new RegExp(`\\*\\*${escapedHeaderName}:?\\*\\*\\s*([^\\n]+)`, "i"),
|
||||
|
||||
// 5. 匹配markdown标题:## 标题 格式
|
||||
new RegExp(
|
||||
`^#{1,6}\\s*${escapedHeaderName}:?\\s*\\n([\\s\\S]*?)(?=^#{1,6}\\s|^\\*\\*[^*]+:?\\*\\*|^---|\$)`,
|
||||
"im"
|
||||
),
|
||||
// 5. 匹配简单的**标题:**格式(可能在段落中)
|
||||
new RegExp(
|
||||
`\\*\\*${escapedHeaderName}:?\\*\\*\\s*([\\s\\S]*?)(?=\\*\\*[^*]+:?\\*\\*|\\d+\\.\\s*\\*\\*[^*]+:?\\*\\*|\\n\\n|---|\$)`,
|
||||
"i"
|
||||
),
|
||||
|
||||
// 6. 匹配冒号后的内容:标题: 内容(适用于简单的键值对格式)
|
||||
new RegExp(
|
||||
`^\\s*${escapedHeaderName}:?\\s*([\\s\\S]*?)(?=^\\s*[A-Za-z][^:]*:|^\\*\\*[^*]+:?\\*\\*|^---|\$)`,
|
||||
"im"
|
||||
),
|
||||
];
|
||||
// 6. 匹配markdown标题:## 标题 格式
|
||||
new RegExp(
|
||||
`^#{1,6}\\s*${escapedHeaderName}:?\\s*\\n([\\s\\S]*?)(?=^#{1,6}\\s|^\\*\\*[^*]+:?\\*\\*|^---|\$)`,
|
||||
"im"
|
||||
),
|
||||
|
||||
// 7. 匹配冒号后的内容:标题: 内容(适用于简单的键值对格式)
|
||||
new RegExp(
|
||||
`^\\s*${escapedHeaderName}:?\\s*([\\s\\S]*?)(?=^\\s*[A-Za-z][^:]*:|^\\*\\*[^*]+:?\\*\\*|^---|\$)`,
|
||||
"im"
|
||||
),
|
||||
];
|
||||
|
||||
// 尝试每种模式
|
||||
for (let i = 0; i < patterns.length; i++) {
|
||||
@ -317,7 +320,7 @@ export class StoryDetails {
|
||||
content = cleanMarkdownContent(content);
|
||||
|
||||
// 如果内容太短,可能是匹配错误,返回空
|
||||
if (content.length < 10) {
|
||||
if (content.length < 20&&headerName!=='GENRE') {
|
||||
debug && console.log("匹配到的内容太短,可能匹配错误");
|
||||
return "";
|
||||
}
|
||||
|
||||
@ -28,7 +28,6 @@ describe("ScriptService 业务逻辑测试", () => {
|
||||
"在阳光明媚的码头上,两只柴犬展开了一场薯条吃比赛。一只优雅的母猫担任裁判,端坐高处,威严地监督比赛。两只鸽子站在一旁,歪着头有趣地看着,偶尔咕咕低鸣。柴犬们瞪大眼睛,尾巴摇得飞快,争抢盘子里的金黄薯条。从日出到天黑,它们吃个不停,薯条堆成了小山,母猫无奈摇头,鸽子仍兴致勃勃,场面热闹非凡。";
|
||||
|
||||
let projectId: string;
|
||||
let planId: string;
|
||||
// let name: string;
|
||||
|
||||
it("想法生成剧本", async () => {
|
||||
@ -48,14 +47,13 @@ describe("ScriptService 业务逻辑测试", () => {
|
||||
);
|
||||
expect(createRes.project_id).toBeDefined();
|
||||
projectId = createRes.project_id;
|
||||
planId = createRes.plan_id;
|
||||
});
|
||||
it("保存剧本", async () => {
|
||||
const res = await newScriptEditUseCase.saveScript(projectId);
|
||||
console.log(res);
|
||||
});
|
||||
it("应用剧本", async () => {
|
||||
await newScriptEditUseCase.applyScript(projectId, planId);
|
||||
await newScriptEditUseCase.applyScript(projectId);
|
||||
console.log(projectId);
|
||||
});
|
||||
});
|
||||
@ -101,8 +99,14 @@ describe("解析测试", () => {
|
||||
describe("剧本功能对接测试",()=>{
|
||||
it("初始化 解析剧本" , async()=>{
|
||||
const response = await getProjectScript({ project_id: "21f194df-cb4b-4e3a-8d44-ca14f23fd1c2" });
|
||||
console.log(response.data.generated_script);
|
||||
const newScriptEditUseCase = new ScriptEditUseCase(response.data.generated_script);
|
||||
console.log(newScriptEditUseCase.getStoryDetails());
|
||||
})
|
||||
it("分类解析",()=>{
|
||||
// 测试代码
|
||||
const testText = `**GENRE:** Drama\n\n---\n\n**SCENE 1**`;
|
||||
const s = new StoryDetails("");
|
||||
const result = s.extractContentByHeader(testText, "GENRE", true);
|
||||
console.log("测试结果:", result); // 应该输出 "Drama"
|
||||
|
||||
})
|
||||
} )
|
||||
|
||||
@ -183,14 +183,13 @@ export class ScriptEditUseCase {
|
||||
* @description: 应用剧本方法
|
||||
* @returns Promise<void>
|
||||
*/
|
||||
async applyScript(projectId: string, planId: string): Promise<void> {
|
||||
async applyScript(projectId: string): Promise<void> {
|
||||
try {
|
||||
this.loading = true;
|
||||
|
||||
// 调用应用剧本接口
|
||||
const response = await applyScriptToShot({
|
||||
project_id: projectId,
|
||||
plan_id: planId,
|
||||
project_id: projectId
|
||||
});
|
||||
|
||||
if (!response.successful) {
|
||||
@ -250,4 +249,17 @@ export class ScriptEditUseCase {
|
||||
toString(): string {
|
||||
return this.scriptValueObject.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: 当前剧本进行字符串替换
|
||||
* @returns string
|
||||
*/
|
||||
replaceScript(old: string, newScript: string): void {
|
||||
// 获取当前剧本文本
|
||||
const scriptText = this.scriptValueObject.toString();
|
||||
// 替换剧本文本
|
||||
const newScriptText = scriptText.replace(old, newScript);
|
||||
// 更新剧本
|
||||
this.scriptValueObject = new ScriptValueObject(newScriptText);
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user