520 lines
21 KiB
TypeScript
520 lines
21 KiB
TypeScript
import http from "@/api/http";
|
|
|
|
export interface CreativeStyle {
|
|
id: string;
|
|
name: string;
|
|
image_url?: string;
|
|
reference_image_asset_id?: string;
|
|
reference_image_url?: string;
|
|
}
|
|
export interface VideoReferenceCapability {
|
|
supported: boolean;
|
|
max_count: number;
|
|
min_total_duration_ms?: number;
|
|
max_total_duration_ms?: number;
|
|
min_short_side_pixels?: number;
|
|
max_short_side_pixels?: number;
|
|
}
|
|
export interface VideoModelCapabilities {
|
|
reference_images: VideoReferenceCapability;
|
|
reference_audios: VideoReferenceCapability;
|
|
reference_videos: VideoReferenceCapability;
|
|
}
|
|
export interface CreativeModel {
|
|
id: string;
|
|
name: string;
|
|
model_type: "text" | "image" | "video";
|
|
channel_name: string;
|
|
multimodal?: boolean;
|
|
text_billing_mode?: "per_request" | "per_token";
|
|
capabilities?: VideoModelCapabilities;
|
|
}
|
|
export interface CreativePrice {
|
|
model_id: string;
|
|
price_key: string;
|
|
unit: string;
|
|
price: number;
|
|
}
|
|
export interface CreativeOptions {
|
|
styles: CreativeStyle[];
|
|
models: CreativeModel[];
|
|
prices?: CreativePrice[];
|
|
}
|
|
export interface PromptPreset {
|
|
id: string;
|
|
name: string;
|
|
type: string;
|
|
content: string;
|
|
scope?: "system" | "user";
|
|
editable?: boolean;
|
|
}
|
|
export interface ModelConfig {
|
|
purpose: string;
|
|
model_id: string;
|
|
model_name: string;
|
|
model_type: "text" | "image" | "video";
|
|
channel_name: string;
|
|
settings?: { aspect_ratio?: string; resolution?: string; prompt?: string };
|
|
capabilities?: VideoModelCapabilities;
|
|
}
|
|
export interface ProjectSummary {
|
|
id: string;
|
|
name: string;
|
|
project_type: string;
|
|
style_name: string;
|
|
era_type: string;
|
|
custom_era?: string;
|
|
aspect_ratio: string;
|
|
localization: string;
|
|
short_drama_type?: string;
|
|
play_count?: string;
|
|
audience_profile?: string;
|
|
producer?: string;
|
|
cast_members: ProjectCastMember[];
|
|
cover_url?: string;
|
|
cover_mime_type?: string;
|
|
cover_video_url?: string;
|
|
episode_count: number;
|
|
processing_count: number;
|
|
updated_at: string;
|
|
}
|
|
|
|
export interface ProjectCastMember {
|
|
name: string;
|
|
follower_count?: string;
|
|
}
|
|
|
|
/** 剧集摘要,包含项目列表和工作台所需的处理状态与产出标记。 */
|
|
export interface Episode {
|
|
id: string;
|
|
episode_no: number;
|
|
name: string;
|
|
audio_source: "video_audio" | "subtitle_file";
|
|
source_language?: string;
|
|
status: string;
|
|
analysis_message?: string;
|
|
source_video_asset_id?: string;
|
|
source_video_url?: string;
|
|
source_video_original_name?: string;
|
|
subtitle_asset_id?: string;
|
|
subtitle_original_name?: string;
|
|
cover_url?: string;
|
|
cover_video_url?: string;
|
|
storyboard_count: number;
|
|
completed_storyboard_count: number;
|
|
has_redraw_script?: boolean;
|
|
has_text_source?: boolean;
|
|
updated_at?: string;
|
|
}
|
|
|
|
export interface ProjectDetail extends ProjectSummary {
|
|
style_id: string;
|
|
style_image_url?: string;
|
|
model_configs: ModelConfig[];
|
|
episodes: Episode[];
|
|
}
|
|
|
|
export interface ProjectAsset {
|
|
id: string;
|
|
project_id: string;
|
|
source_episode_id?: string;
|
|
asset_type: "character" | "scene" | "prop" | "custom";
|
|
name: string;
|
|
description?: string;
|
|
image_prompt?: string;
|
|
appearances?: unknown[];
|
|
image_asset_id?: string;
|
|
audio_asset_id?: string;
|
|
audio_duration_ms?: number;
|
|
image_url?: string;
|
|
audio_url?: string;
|
|
video_url?: string;
|
|
user_edited: boolean;
|
|
}
|
|
|
|
export interface Storyboard {
|
|
id: string;
|
|
episode_id: string;
|
|
sequence_no: number;
|
|
start_ms: number;
|
|
end_ms: number;
|
|
duration_seconds: number;
|
|
title?: string;
|
|
thumbnail_asset_id?: string;
|
|
thumbnail_url?: string;
|
|
script_content?: string;
|
|
source_excerpt?: string;
|
|
prompt_content?: string;
|
|
image_prompt?: string;
|
|
dialogue?: unknown[];
|
|
asset_refs?: Array<{ id: string; name?: string }>;
|
|
locked: boolean;
|
|
active_output_id?: string;
|
|
status: string;
|
|
output_id?: string;
|
|
result_media_id?: string;
|
|
result_url?: string;
|
|
result_mime?: string;
|
|
history_count: number;
|
|
task_status?: string;
|
|
}
|
|
|
|
export interface WorkbenchData {
|
|
project: ProjectDetail;
|
|
episode: Episode;
|
|
assets: ProjectAsset[];
|
|
storyboards: Storyboard[];
|
|
}
|
|
export interface RedrawSource {
|
|
source_video_asset_id?: string;
|
|
source_video_url?: string;
|
|
source_video_original_name?: string;
|
|
subtitle_asset_id?: string;
|
|
subtitle_url?: string;
|
|
subtitle_original_name?: string;
|
|
audio_source: "video_audio" | "subtitle_file";
|
|
source_language?: string;
|
|
status: string;
|
|
analysis_message?: string;
|
|
}
|
|
export interface RedrawWorkbenchData {
|
|
project: ProjectDetail;
|
|
episode: Episode;
|
|
source: RedrawSource;
|
|
assets: ProjectAsset[];
|
|
storyboards: Storyboard[];
|
|
script_content: string;
|
|
}
|
|
export interface DramaChapterPreview {
|
|
title: string;
|
|
char_count: number;
|
|
}
|
|
export interface DramaImportPreview {
|
|
import_token: string;
|
|
has_chapters: boolean;
|
|
total_characters: number;
|
|
chapters: DramaChapterPreview[];
|
|
single_episode_confirmation_required: boolean;
|
|
}
|
|
export interface DramaEpisodeSource {
|
|
id: string;
|
|
episode_id: string;
|
|
title?: string;
|
|
raw_content: string;
|
|
char_count: number;
|
|
source_type: string;
|
|
source_filename?: string;
|
|
content_sha256: string;
|
|
}
|
|
export interface DramaParseTask {
|
|
id: string;
|
|
request_id: string;
|
|
batch_id?: string;
|
|
episode_id: string;
|
|
status: string;
|
|
input_tokens?: number;
|
|
output_tokens?: number;
|
|
total_tokens?: number;
|
|
estimated_points?: string;
|
|
prepaid_points?: string;
|
|
actual_points?: string;
|
|
cost_refunded?: boolean;
|
|
token_count_source?: string;
|
|
error_code?: string;
|
|
error_message?: string;
|
|
created_at: string;
|
|
finished_at?: string;
|
|
}
|
|
export interface GenerationTask {
|
|
id: string;
|
|
request_id: string;
|
|
task_type: string;
|
|
status: string;
|
|
episode_id?: string;
|
|
storyboard_id?: string;
|
|
mode?: string;
|
|
phase_started_at?: string;
|
|
sequence_no?: number;
|
|
asset_id?: string;
|
|
estimated_points?: string;
|
|
actual_points?: string;
|
|
error_code?: string;
|
|
error_message?: string;
|
|
result_url?: string;
|
|
created_at: string;
|
|
submitted_at?: string;
|
|
finished_at?: string;
|
|
last_result_at?: string;
|
|
}
|
|
export interface GenerationOutput {
|
|
id: string;
|
|
task_id: string;
|
|
media_asset_id: string;
|
|
output_type: string;
|
|
public_url: string;
|
|
mime_type: string;
|
|
size_bytes: number;
|
|
estimated_points?: string;
|
|
actual_points?: string;
|
|
active: boolean;
|
|
candidate?: boolean;
|
|
created_at: string;
|
|
}
|
|
export interface ProjectPayload {
|
|
project_type?: "video_redraw" | "premium_drama";
|
|
name: string;
|
|
style_id: string;
|
|
era_type: string;
|
|
custom_era?: string | null;
|
|
aspect_ratio: string;
|
|
localization?: string | null;
|
|
short_drama_type?: string;
|
|
play_count?: string;
|
|
audience_profile?: string;
|
|
producer?: string;
|
|
cast_members?: ProjectCastMember[];
|
|
}
|
|
export interface ScriptAnalysis {
|
|
id: string;
|
|
user_id: string;
|
|
name: string;
|
|
source_content: string;
|
|
result_content: string;
|
|
analysis_result: ScriptAnalysisResult;
|
|
analysis_status: "idle" | "queued" | "running" | "succeeded" | "failed";
|
|
analysis_message?: string;
|
|
characters?: ScriptAnalysisCharacter[];
|
|
created_at: string;
|
|
updated_at: string;
|
|
}
|
|
export interface ScriptAnalysisImportProject {
|
|
id: string;
|
|
name: string;
|
|
episode_count: number;
|
|
char_count: number;
|
|
updated_at: string;
|
|
}
|
|
export interface ScriptAnalysisCharacter {
|
|
id: string;
|
|
script_analysis_id: string;
|
|
name: string;
|
|
faction: "正派" | "反派" | "中立派";
|
|
biography: string;
|
|
motivation: string;
|
|
relationship: string;
|
|
sort_order: number;
|
|
}
|
|
export interface ScriptAnalysisResult {
|
|
tags?: { drama_tags?: string[]; applicable_scene_tags?: string[] };
|
|
selling_point?: { summary?: string; highlights?: Array<{ type: string; content: string }> };
|
|
story_structure?: {
|
|
synopsis?: string;
|
|
story_outline?: string[];
|
|
emotion_outline?: Array<{ stage: string; emotion: string; description: string }>;
|
|
episode_outlines?: Array<{ episode_no: number; title: string; outline: string; emotion: string }>;
|
|
characters?: Array<{
|
|
name: string;
|
|
faction: "正派" | "反派" | "中立派";
|
|
biography: string;
|
|
motivation: string;
|
|
relationship: string;
|
|
}>;
|
|
};
|
|
opening_hook?: {
|
|
first_scene?: string;
|
|
first_line?: string;
|
|
attention_methods?: string[];
|
|
analysis?: string;
|
|
optimization?: string;
|
|
};
|
|
episode_hooks?: Array<{ episode_no: number; hook_type: string; hook: string; basis: string }>;
|
|
episode_10_paywall_hooks?: Array<{ hook_type: string; content: string; appeal: string }>;
|
|
custom_analysis?: Array<{ objective: string; conclusion: string; evidence: string[] }>;
|
|
unmatched_objectives?: Array<{ objective: string; reason: string }>;
|
|
}
|
|
|
|
const data = <T>(response: { data: { data: T } }) => response.data.data;
|
|
|
|
export const creativeApi = {
|
|
options: () => http.get("/creative/options").then(data<CreativeOptions>),
|
|
allProjects: () => http.get("/projects").then(data<ProjectSummary[]>),
|
|
projects: (keyword = "") =>
|
|
http.get("/projects", { params: { project_type: "video_redraw", keyword } }).then(data<ProjectSummary[]>),
|
|
dramaProjects: (keyword = "") =>
|
|
http.get("/projects", { params: { project_type: "premium_drama", keyword } }).then(data<ProjectSummary[]>),
|
|
createProject: (payload: ProjectPayload) => http.post("/projects", payload).then(data<{ id: string }>),
|
|
project: (projectId: string) => http.get(`/projects/${projectId}`).then(data<ProjectDetail>),
|
|
updateProject: (projectId: string, payload: ProjectPayload) => http.put(`/projects/${projectId}`, payload),
|
|
deleteProject: (projectId: string) => http.delete(`/projects/${projectId}`),
|
|
saveModels: (projectId: string, payload: Record<string, unknown>) =>
|
|
http.put(`/projects/${projectId}/model-configs`, payload),
|
|
promptPresets: (type: string) =>
|
|
http.get(`/user/prompts/${encodeURIComponent(type)}`).then(data<{ prompts: PromptPreset[]; selected_id?: string }>),
|
|
selectPrompt: (type: string, promptId?: string) =>
|
|
http.put(`/user/prompts/${encodeURIComponent(type)}/select`, { prompt_id: promptId || null }),
|
|
createCustomPrompt: (payload: { name: string; type: string; content: string }) =>
|
|
http.post("/user/custom-prompts", payload).then(data<PromptPreset>),
|
|
updateCustomPrompt: (id: string, payload: { name: string; type?: string; content: string }) =>
|
|
http.put(`/user/custom-prompts/${id}`, payload).then(data<PromptPreset>),
|
|
deleteCustomPrompt: (id: string) => http.delete(`/user/custom-prompts/${id}`),
|
|
createEpisode: (projectId: string, payload: { episode_no?: number; name?: string } = {}) =>
|
|
http.post(`/projects/${projectId}/episodes`, payload).then(data<Episode>),
|
|
updateEpisodeName: (projectId: string, episodeId: string, name: string) =>
|
|
http.put(`/projects/${projectId}/episodes/${episodeId}`, { name }).then(data<Episode>),
|
|
previewDramaImport: (projectId: string, payload: { file?: File; rawText?: string }) => {
|
|
const form = new FormData();
|
|
if (payload.file) form.append("file", payload.file);
|
|
if (payload.rawText) form.append("raw_text", payload.rawText);
|
|
return http
|
|
.post(`/projects/${projectId}/episodes/import/preview`, form, {
|
|
timeout: 0,
|
|
headers: { "Content-Type": "multipart/form-data" },
|
|
})
|
|
.then(data<DramaImportPreview>);
|
|
},
|
|
confirmDramaImport: (
|
|
projectId: string,
|
|
payload: {
|
|
import_token: string;
|
|
chapters_per_episode: number;
|
|
start_episode_no: number;
|
|
treat_as_single_episode: boolean;
|
|
},
|
|
) => http.post(`/projects/${projectId}/episodes/import/confirm`, payload).then(data<Episode[]>),
|
|
dramaEpisodeSource: (projectId: string, episodeId: string) =>
|
|
http.get(`/projects/${projectId}/episodes/${episodeId}/text-source`).then(data<DramaEpisodeSource>),
|
|
saveDramaEpisodeSource: (projectId: string, episodeId: string, payload: { title?: string; raw_content: string }) =>
|
|
http.put(`/projects/${projectId}/episodes/${episodeId}/text-source`, payload).then(data<DramaEpisodeSource>),
|
|
parseDramaEpisode: (projectId: string, episodeId: string) =>
|
|
http.post(`/projects/${projectId}/episodes/${episodeId}/parse`).then(data<DramaParseTask>),
|
|
reparseDramaEpisode: (projectId: string, episodeId: string) =>
|
|
http.post(`/projects/${projectId}/episodes/${episodeId}/reparse`).then(data<DramaParseTask>),
|
|
createDramaStoryboard: (projectId: string, episodeId: string) =>
|
|
http.post(`/projects/${projectId}/episodes/${episodeId}/storyboards`).then(data<Storyboard>),
|
|
dramaParseTasks: (projectId: string, episodeId?: string) =>
|
|
http.get(`/projects/${projectId}/parse-tasks`, { params: { episode_id: episodeId } }).then(data<DramaParseTask[]>),
|
|
cancelDramaParse: (projectId: string, taskId: string) =>
|
|
http.post(`/projects/${projectId}/parse-tasks/${taskId}/cancel`),
|
|
deleteEpisode: (projectId: string, episodeId: string) => http.delete(`/projects/${projectId}/episodes/${episodeId}`),
|
|
workbench: (projectId: string, episodeId: string) =>
|
|
http.get(`/projects/${projectId}/episodes/${episodeId}/workbench`).then(data<WorkbenchData>),
|
|
// episodeVideosArchive 下载当前剧集按项目类型筛选后的全部视频 ZIP。
|
|
episodeVideosArchive: (projectId: string, episodeId: string) =>
|
|
http
|
|
.get(`/projects/${projectId}/episodes/${episodeId}/videos.zip`, { responseType: "blob", timeout: 0 })
|
|
.then((response) => response.data as Blob),
|
|
redrawWorkbench: (projectId: string, episodeId: string) =>
|
|
http.get(`/projects/${projectId}/episodes/${episodeId}/redraw-workbench`).then(data<RedrawWorkbenchData>),
|
|
uploadSource: (projectId: string, episodeId: string, file: File) =>
|
|
upload(`/projects/${projectId}/episodes/${episodeId}/source`, file),
|
|
uploadSubtitle: (projectId: string, episodeId: string, file: File) =>
|
|
upload(`/projects/${projectId}/episodes/${episodeId}/subtitle`, file),
|
|
uploadRedrawSource: (projectId: string, file: File) => upload(`/projects/${projectId}/redraw-source`, file),
|
|
uploadRedrawSubtitle: (projectId: string, file: File) => upload(`/projects/${projectId}/redraw-subtitle`, file),
|
|
saveAnalysisSettings: (
|
|
projectId: string,
|
|
episodeId: string,
|
|
payload: { audio_source: string; source_language: string },
|
|
) => http.put(`/projects/${projectId}/episodes/${episodeId}/analysis-settings`, payload),
|
|
saveRedrawAnalysisSettings: (projectId: string, payload: { audio_source: string; source_language: string }) =>
|
|
http.put(`/projects/${projectId}/redraw-analysis-settings`, payload),
|
|
analyze: (projectId: string, episodeId: string) =>
|
|
http.post(`/projects/${projectId}/episodes/${episodeId}/analyze`).then(data<GenerationTask>),
|
|
reanalyze: (projectId: string, episodeId: string) =>
|
|
http.post(`/projects/${projectId}/episodes/${episodeId}/reanalyze`).then(data<GenerationTask>),
|
|
analyzeRedraw: (projectId: string) => http.post(`/projects/${projectId}/redraw-analyze`).then(data<GenerationTask>),
|
|
reanalyzeRedraw: (projectId: string) =>
|
|
http.post(`/projects/${projectId}/redraw-reanalyze`).then(data<GenerationTask>),
|
|
reverseRedrawScript: (projectId: string, episodeId: string) =>
|
|
http.post(`/projects/${projectId}/episodes/${episodeId}/redraw-script`).then(data<GenerationTask>),
|
|
saveRedrawScript: (projectId: string, episodeId: string, content: string) =>
|
|
http.put(`/projects/${projectId}/episodes/${episodeId}/redraw-script`, { content }),
|
|
createAsset: (projectId: string, payload: { asset_type: string; name: string }) =>
|
|
http.post(`/projects/${projectId}/assets`, payload).then(data<ProjectAsset>),
|
|
updateAsset: (projectId: string, assetId: string, payload: Partial<ProjectAsset>) =>
|
|
http.put(`/projects/${projectId}/assets/${assetId}`, payload),
|
|
deleteAsset: (projectId: string, assetId: string) => http.delete(`/projects/${projectId}/assets/${assetId}`),
|
|
uploadAssetImage: (projectId: string, assetId: string, file: File) =>
|
|
upload(`/projects/${projectId}/assets/${assetId}/image`, file),
|
|
removeAssetImage: (projectId: string, assetId: string) =>
|
|
http.delete(`/projects/${projectId}/assets/${assetId}/image`),
|
|
uploadAssetAudio: (projectId: string, assetId: string, file: File, durationMs?: number) =>
|
|
upload(
|
|
`/projects/${projectId}/assets/${assetId}/audio`,
|
|
file,
|
|
durationMs === undefined ? undefined : { duration_ms: String(durationMs) },
|
|
),
|
|
updateStoryboard: (projectId: string, storyboardId: string, payload: Partial<Storyboard>) =>
|
|
http.put(`/projects/${projectId}/storyboards/${storyboardId}`, payload),
|
|
insertStoryboard: (projectId: string, storyboardId: string, position: "before" | "after") =>
|
|
http.post(`/projects/${projectId}/storyboards/${storyboardId}/insert`, { position }).then(data<Storyboard>),
|
|
deleteStoryboard: (projectId: string, storyboardId: string) =>
|
|
http.delete(`/projects/${projectId}/storyboards/${storyboardId}`),
|
|
reinferStoryboard: (projectId: string, episodeId: string, storyboardId: string) =>
|
|
http
|
|
.post(`/projects/${projectId}/episodes/${episodeId}/storyboards/${storyboardId}/reinfer`)
|
|
.then(data<GenerationTask>),
|
|
reinferRedrawStoryboard: (projectId: string, storyboardId: string) =>
|
|
http.post(`/projects/${projectId}/storyboards/${storyboardId}/redraw-reinfer`).then(data<GenerationTask>),
|
|
generate: (
|
|
projectId: string,
|
|
episodeId: string,
|
|
storyboardId: string,
|
|
taskType: "image_generation" | "video_generation",
|
|
input: Record<string, unknown>,
|
|
) =>
|
|
http
|
|
.post(`/projects/${projectId}/episodes/${episodeId}/storyboards/${storyboardId}/generate`, {
|
|
task_type: taskType,
|
|
input,
|
|
})
|
|
.then(data<GenerationTask>),
|
|
tasks: (projectId: string, episodeId?: string) =>
|
|
http.get(`/projects/${projectId}/tasks`, { params: { episode_id: episodeId } }).then(data<GenerationTask[]>),
|
|
cancelTask: (projectId: string, taskId: string) => http.post(`/projects/${projectId}/tasks/${taskId}/cancel`),
|
|
outputs: (projectId: string, storyboardId: string) =>
|
|
http.get(`/projects/${projectId}/storyboards/${storyboardId}/outputs`).then(data<GenerationOutput[]>),
|
|
removeStoryboardImage: (projectId: string, storyboardId: string) =>
|
|
http.delete(`/projects/${projectId}/storyboards/${storyboardId}/image`),
|
|
activateOutput: (projectId: string, storyboardId: string, outputId: string) =>
|
|
http.put(`/projects/${projectId}/storyboards/${storyboardId}/outputs/${outputId}/activate`),
|
|
addStoryboardCandidate: (projectId: string, storyboardId: string, outputId: string) =>
|
|
http.put(`/projects/${projectId}/storyboards/${storyboardId}/outputs/${outputId}/candidate`),
|
|
removeStoryboardCandidate: (projectId: string, storyboardId: string, outputId: string) =>
|
|
http.delete(`/projects/${projectId}/storyboards/${storyboardId}/outputs/${outputId}/candidate`),
|
|
deleteOutput: (projectId: string, storyboardId: string, outputId: string) =>
|
|
http.delete(`/projects/${projectId}/storyboards/${storyboardId}/outputs/${outputId}`),
|
|
assetOutputs: (projectId: string, assetId: string) =>
|
|
http.get(`/projects/${projectId}/assets/${assetId}/outputs`).then(data<GenerationOutput[]>),
|
|
activateAssetOutput: (projectId: string, assetId: string, outputId: string) =>
|
|
http.put(`/projects/${projectId}/assets/${assetId}/outputs/${outputId}/activate`),
|
|
deleteAssetOutput: (projectId: string, assetId: string, outputId: string) =>
|
|
http.delete(`/projects/${projectId}/assets/${assetId}/outputs/${outputId}`),
|
|
media: (mediaId: string) =>
|
|
http.get(`/media/${mediaId}`, { responseType: "blob", timeout: 0 }).then((response) => response.data as Blob),
|
|
scriptAnalyses: () => http.get("/script-analyses").then(data<ScriptAnalysis[]>),
|
|
createScriptAnalysis: () => http.post("/script-analyses").then(data<ScriptAnalysis>),
|
|
scriptAnalysisImportProjects: () =>
|
|
http.get("/script-analyses/import-projects").then(data<ScriptAnalysisImportProject[]>),
|
|
scriptAnalysis: (id: string) => http.get(`/script-analyses/${id}`).then(data<ScriptAnalysis>),
|
|
updateScriptAnalysis: (id: string, payload: { name: string; source_content: string; result_content: string }) =>
|
|
http.put(`/script-analyses/${id}`, payload).then(data<ScriptAnalysis>),
|
|
deleteScriptAnalysis: (id: string) => http.delete(`/script-analyses/${id}`),
|
|
importScriptAnalysisProject: (id: string, projectId: string) =>
|
|
http.post(`/script-analyses/${id}/import-project`, { project_id: projectId }).then(data<ScriptAnalysis>),
|
|
importScriptAnalysisFile: (id: string, file: File) =>
|
|
upload<ScriptAnalysis>(`/script-analyses/${id}/import-file`, file),
|
|
analyzeScriptAnalysis: (id: string) => http.post(`/script-analyses/${id}/analyze`).then(data<GenerationTask>),
|
|
cancelScriptAnalysis: (id: string) => http.post(`/script-analyses/${id}/cancel`),
|
|
userModelConfigs: (scope: "script_analysis") => http.get(`/user/model-configs/${scope}`).then(data<ModelConfig[]>),
|
|
saveUserModelConfig: (scope: "script_analysis", modelType: "text", modelId: string) =>
|
|
http.put(`/user/model-configs/${scope}/${modelType}`, { model_id: modelId }),
|
|
};
|
|
|
|
function upload<T = Record<string, unknown>>(path: string, file: File, fields?: Record<string, string>) {
|
|
const form = new FormData();
|
|
form.append("file", file);
|
|
Object.entries(fields || {}).forEach(([key, value]) => form.append(key, value));
|
|
return http.post(path, form, { timeout: 0, headers: { "Content-Type": "multipart/form-data" } }).then(data<T>);
|
|
}
|