2025-07-04 15:46:31 +08:00

197 lines
6.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// 5组mock数据 - 保留作为fallback数据
export const MOCK_DATA = [
{
id: 1,
detail: {
projectId: '1',
projectName: 'Home and Away',
taskId: '1',
taskName: 'Episode 1: Flood Disaster',
taskDescription: 'A story about a factory accident',
taskStatus: '1',
mode: 'auto',
resolution: 1024,
sketch_count: 18,
role_count: 1,
},
sketch: [{ // sketch_count个分镜草图
url: 'https://cdn.qikongjian.com/1751484624095_ypdp4h.png',
script: 'After the flood disaster in the middle and lower reaches of the Yangtze River in 1981\nFlood Documentary Camera\nAccompanied by the sound of news broadcasts.',
bg_rgb: ['RGB(58, 58, 59)', 'RGB(189, 186, 185)', 'RGB(114, 113, 115)']
}, {
url: 'https://cdn.qikongjian.com/1751484962956_7e2kv2.png',
script: 'A big tree has exposed its roots and is lying horizontally on the ground',
bg_rgb: ['RGB(12, 13, 13)', 'RGB(42, 46, 47)', 'RGB(101, 107, 109)']
}],
roles: [{ // role_count个角色
name: '陈海清',
url: 'https://cdn.qikongjian.com/1751486026891_zieiq5.png',
sound: 'https://cdn.qikongjian.com/audio/1750385931_99a8fb42-af89-4ae9-841a-a49869f026bd_text_to_video_0.mp3',
soundDescription: 'A deep, controlled baritone voice with measured cadence and authoritative undertones.',
roleDescription: 'Brief: A portrait of a male in his late 20s or early 30s from South Korea.',
}],
video: [{ // sketch_count个分镜视频以及对应的音频
url: 'https://cdn.qikongjian.com/1751483686756_01p12v.mp4',
script: 'After the flood disaster in the middle and lower reaches of the Yangtze River in 1981',
audio: 'https://cdn.qikongjian.com/audio/1750385931_99a8fb42-af89-4ae9-841a-a49869f026bd_text_to_video_0.mp3',
}],
music: {
url: 'https://cdn.qikongjian.com/audio/1750385931_99a8fb42-af89-4ae9-841a-a49869f026bd_text_to_video_0.mp3',
script: '激昂的科幻背景音乐',
name: 'Music / sci-fi',
duration: '01m : 35s : 765ms',
totalDuration: '01m : 35s : 765ms',
isLooped: true,
},
final: {
url: 'https://cdn.qikongjian.com/1751593771075_0lxy9f.mp4'
},
}
];
// 从接口获取数据的函数
export const fetchMockDataFromAPI = async () => {
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), 10000); // 10秒超时
try {
console.log('开始请求接口数据...');
const response = await fetch('https://movieflow.api.huiying.video/serversetting/roadshow-configs', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
}),
signal: controller.signal,
});
clearTimeout(timeoutId);
if (!response.ok) {
throw new Error(`接口请求失败: HTTP ${response.status} - ${response.statusText}`);
}
const result = await response.json();
console.log('接口返回数据:', result);
// 验证返回数据格式
if (result.code !== 0) {
throw new Error(`接口错误: ${result.message || '未知错误'} (code: ${result.code})`);
}
if (!result.successful) {
throw new Error(`接口调用不成功: ${result.message || '未知原因'}`);
}
if (!result.data || !Array.isArray(result.data) || result.data.length === 0) {
throw new Error('接口返回数据格式错误或为空');
}
// 验证数据结构
let validData: any[] = [];
result.data.forEach((item: any) => {
if (item) {
validData.push(JSON.parse(item));
}
});
if (validData.length === 0) {
throw new Error('接口返回的数据格式不正确');
}
console.log('成功获取并验证接口数据:', validData);
return validData;
} catch (error: unknown) {
clearTimeout(timeoutId);
if (error instanceof Error && error.name === 'AbortError') {
throw new Error('接口请求超时,请检查网络连接');
}
console.error('接口请求失败:', error);
throw error;
}
};
// 异步获取随机数据 - 从接口或fallback到本地数据
export const getRandomMockData = async () => {
try {
const apiData = await fetchMockDataFromAPI();
const randomIndex = Math.floor(Math.random() * apiData.length);
const selectedData = apiData[randomIndex];
console.log('从接口数据中随机选择:', selectedData);
return selectedData;
} catch (error: unknown) {
const errorMessage = error instanceof Error ? error.message : '未知错误';
console.warn('接口获取数据失败使用本地fallback数据:', errorMessage);
// 确保本地数据结构正确
if (!MOCK_DATA || MOCK_DATA.length === 0) {
throw new Error('本地fallback数据也不可用');
}
const randomIndex = Math.floor(Math.random() * MOCK_DATA.length);
const selectedData = MOCK_DATA[randomIndex];
console.log('使用本地fallback数据:', selectedData);
throw error; // 重新抛出错误让上层知道是fallback数据
}
};
export interface TaskObject {
projectId: string;
projectName: string;
taskId: string;
taskName: string;
taskDescription: string;
taskStatus: string;
taskProgress: number;
mode: string;
resolution: string;
}
export interface SketchItem {
id: string;
url: string;
script: string;
bg_rgb?: string[];
status: string;
}
export interface VideoItem {
id: string;
url: string;
script: string;
status: string;
}
export interface FinalVideo {
url: string;
}
export const STEP_MESSAGES = {
loading: 'Loading task information...',
sketch: (count: number, total: number) => `Generating sketch ${count + 1 > total ? total : count + 1}/${total}...`,
sketchComplete: 'Sketch generation complete',
character: 'Drawing characters...',
newCharacter: (count: number, total: number) => `Drawing character ${count + 1 > total ? total : count + 1}/${total}...`,
video: (count: number, total: number) => `Generating video ${count + 1 > total ? total : count + 1}/${total}...`,
videoComplete: 'Video generation complete',
audio: 'Generating background audio...',
postProduction: (step: string) => `Post-production: ${step}...`,
final: 'Generating final product...',
complete: 'Task completed'
};
export const MOCK_DELAY_TIME = {
sketch: 5000, // 5s 一个草图
character: 2000, // 2s 一个角色
video: 6000, // 6s 一个分镜视频
audio: 2000, // 2s 一个音频
postProduction: 2000, // 2s 一个后期制作
final: 10000, // 10s 一个最终成品
}