修复问题

This commit is contained in:
海龙 2025-08-07 19:30:29 +08:00
parent 4291704b0b
commit f7b1c62df3
5 changed files with 87 additions and 97 deletions

View File

@ -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: {

View File

@ -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,

View File

@ -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 "";
}

View File

@ -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"
})
} )

View File

@ -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);
}
}