feat(*): 短剧创作工作台 - 完善章节分镜、资产管理、技能运行与生成任务恢复
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import { apiClient, request } from "@/services/api/request";
|
||||
import type { GenerationTask } from "@/services/api/task-center";
|
||||
|
||||
const api = apiClient;
|
||||
|
||||
@@ -10,6 +11,7 @@ export type Project = {
|
||||
aspectRatio: string;
|
||||
sourceType: string;
|
||||
description: string;
|
||||
coverResourceId?: string;
|
||||
stylePresetId: string;
|
||||
styleProfileJson?: string;
|
||||
status: "active" | "archived" | string;
|
||||
@@ -41,6 +43,7 @@ export type ProjectUnit = {
|
||||
kind: "chapter" | "episode" | string;
|
||||
title: string;
|
||||
sourceText: string;
|
||||
wordCount: number;
|
||||
status: "draft" | "ready" | "completed" | string;
|
||||
position: number;
|
||||
createdAt: string;
|
||||
@@ -243,7 +246,8 @@ export type ProjectDetail = {
|
||||
shotRevisions: ShotRevision[];
|
||||
shotArtifacts: ShotArtifact[];
|
||||
shotReferences: ShotAssetReference[];
|
||||
assetCandidates: ProjectAssetCandidate[];
|
||||
assetCandidates: ProjectAssetCandidate[];
|
||||
tasks: GenerationTask[];
|
||||
};
|
||||
|
||||
export function listProjects(): Promise<{ projects: ProjectSummary[] }>;
|
||||
@@ -288,7 +292,8 @@ function normalizeProjectDetail(detail: ProjectDetail): ProjectDetail {
|
||||
shotRevisions: Array.isArray(detail.shotRevisions) ? detail.shotRevisions : [],
|
||||
shotArtifacts: Array.isArray(detail.shotArtifacts) ? detail.shotArtifacts : [],
|
||||
shotReferences: Array.isArray(detail.shotReferences) ? detail.shotReferences : [],
|
||||
assetCandidates: Array.isArray(detail.assetCandidates) ? detail.assetCandidates : [],
|
||||
assetCandidates: Array.isArray(detail.assetCandidates) ? detail.assetCandidates : [],
|
||||
tasks: Array.isArray(detail.tasks) ? detail.tasks : [],
|
||||
};
|
||||
}
|
||||
|
||||
@@ -296,7 +301,7 @@ export function createProject(input: { name: string; type: string; aspectRatio:
|
||||
return request<{ project: Project }>(api.post("/projects", input));
|
||||
}
|
||||
|
||||
export function updateProject(projectId: string, input: Partial<Pick<Project, "name" | "type" | "aspectRatio" | "sourceType" | "description" | "stylePresetId" | "styleProfileJson" | "status">>) {
|
||||
export function updateProject(projectId: string, input: Partial<Pick<Project, "name" | "type" | "aspectRatio" | "sourceType" | "description" | "coverResourceId" | "stylePresetId" | "styleProfileJson" | "status">>) {
|
||||
return request<{ project: Project }>(api.patch(`/projects/${encodeURIComponent(projectId)}`, input));
|
||||
}
|
||||
|
||||
@@ -396,7 +401,7 @@ export function replaceProjectCharacterRepresentations(projectId: string, assetI
|
||||
return request<ProjectCharacterDetail>(api.put(`/projects/${encodeURIComponent(projectId)}/characters/${encodeURIComponent(assetId)}/representations`, { representations }));
|
||||
}
|
||||
|
||||
export function bindProjectCharacterVoice(projectId: string, assetId: string, input: { voiceProfileId: string; instructions?: string }) {
|
||||
export function bindProjectCharacterVoice(projectId: string, assetId: string, input: { voiceProfileId?: string; sampleResourceId?: string; voiceName?: string; instructions?: string }) {
|
||||
return request<ProjectCharacterDetail>(api.put(`/projects/${encodeURIComponent(projectId)}/characters/${encodeURIComponent(assetId)}/voice`, input));
|
||||
}
|
||||
|
||||
@@ -412,14 +417,22 @@ export function saveProjectShot(projectId: string, input: { id?: string; unitId?
|
||||
return request<{ shot: ProjectShot }>(api.post(`/projects/${encodeURIComponent(projectId)}/shots`, input));
|
||||
}
|
||||
|
||||
export function replaceProjectUnitShots(projectId: string, unitId: string, shots: Array<{ title: string; description: string; durationMs: number }>) {
|
||||
return request<{ shots: ProjectShot[] }>(api.put(`/projects/${encodeURIComponent(projectId)}/units/${encodeURIComponent(unitId)}/shots`, { shots }));
|
||||
export function deleteProjectShot(projectId: string, shotId: string) {
|
||||
return request<{ deleted: boolean }>(api.delete(`/projects/${encodeURIComponent(projectId)}/shots/${encodeURIComponent(shotId)}`));
|
||||
}
|
||||
|
||||
export function replaceProjectUnitShots(projectId: string, unitId: string, shots: Array<{ title: string; description: string; durationMs: number; revision?: Partial<ShotRevisionInput>; assetVersionIds?: string[] }>, expectedShotIds?: string[]) {
|
||||
return request<{ shots: ProjectShot[] }>(api.put(`/projects/${encodeURIComponent(projectId)}/units/${encodeURIComponent(unitId)}/shots`, { shots, ...(expectedShotIds ? { expectedShotIds } : {}) }));
|
||||
}
|
||||
|
||||
export function linkShotAsset(projectId: string, shotId: string, input: { assetVersionId: string; role: ShotAssetReference["role"] }) {
|
||||
return request<{ reference: ShotAssetReference }>(api.post(`/projects/${encodeURIComponent(projectId)}/shots/${encodeURIComponent(shotId)}/assets`, input));
|
||||
}
|
||||
|
||||
export function unlinkShotAsset(projectId: string, shotId: string, referenceId: string) {
|
||||
return request<{ unlinked: boolean }>(api.delete(`/projects/${encodeURIComponent(projectId)}/shots/${encodeURIComponent(shotId)}/assets/${encodeURIComponent(referenceId)}`));
|
||||
}
|
||||
|
||||
export function createShotRevision(projectId: string, shotId: string, input: ShotRevisionInput) {
|
||||
return request<{ shot: ProjectShot; revision: ShotRevision }>(api.post(`/projects/${encodeURIComponent(projectId)}/shots/${encodeURIComponent(shotId)}/revisions`, input));
|
||||
}
|
||||
|
||||
@@ -22,6 +22,21 @@ export type Skill = {
|
||||
skill_name: string;
|
||||
description: string;
|
||||
instruction?: string;
|
||||
version_id: string;
|
||||
version: string;
|
||||
content_hash: string;
|
||||
file_count: number;
|
||||
total_bytes: number;
|
||||
source_type: "builtin" | "markdown" | "zip" | "github" | string;
|
||||
source_url: string;
|
||||
source_ref: string;
|
||||
source_subdir: string;
|
||||
source_commit: string;
|
||||
sync_status: "synced" | "failed" | "syncing" | string;
|
||||
sync_error?: string;
|
||||
auto_update: boolean;
|
||||
last_checked_at: number;
|
||||
last_synced_at: number;
|
||||
status: number;
|
||||
markdown_url: string;
|
||||
create_time: number;
|
||||
@@ -67,7 +82,7 @@ export type ListSkillsInput = {
|
||||
export type SkillMutationInput = {
|
||||
skill_name: string;
|
||||
description: string;
|
||||
instruction: string;
|
||||
instruction?: string;
|
||||
tag: string;
|
||||
is_private: boolean;
|
||||
markdown_url: string;
|
||||
@@ -75,6 +90,50 @@ export type SkillMutationInput = {
|
||||
extra_info: string;
|
||||
};
|
||||
|
||||
export type SkillPackageFile = {
|
||||
path: string;
|
||||
kind: "markdown" | "code" | "text" | "image" | "video" | "audio" | "binary" | string;
|
||||
mime_type: string;
|
||||
size: number;
|
||||
sha256: string;
|
||||
};
|
||||
|
||||
export type SkillPackageFileContent = {
|
||||
file: SkillPackageFile;
|
||||
content: string;
|
||||
binary: boolean;
|
||||
};
|
||||
|
||||
export type SkillPackageBundle = {
|
||||
skill_id: string;
|
||||
name: string;
|
||||
description: string;
|
||||
version_id: string;
|
||||
version: string;
|
||||
content_hash: string;
|
||||
files: Array<{ path: string; mime_type: string; content_base64: string }>;
|
||||
};
|
||||
|
||||
export type SkillFileSearchResult = { path: string; line: number; snippet: string };
|
||||
|
||||
export type InstallSkillUploadInput = {
|
||||
file: File;
|
||||
source_type?: "markdown" | "zip";
|
||||
name?: string;
|
||||
description?: string;
|
||||
tag?: string;
|
||||
is_private?: boolean;
|
||||
};
|
||||
|
||||
export type InstallGitHubSkillInput = {
|
||||
url: string;
|
||||
ref?: string;
|
||||
subdir?: string;
|
||||
tag?: string;
|
||||
is_private?: boolean;
|
||||
auto_update?: boolean;
|
||||
};
|
||||
|
||||
|
||||
export function listSkills(input: ListSkillsInput = {}) {
|
||||
const params = serializeApiParams(compactApiParams(input as ApiParams));
|
||||
@@ -110,6 +169,46 @@ export function createSkill(input: SkillMutationInput) {
|
||||
return request<{ skill: Skill }>(api.post("/skills", input)).finally(invalidateAddedSkillsCache);
|
||||
}
|
||||
|
||||
export function installSkillUpload(input: InstallSkillUploadInput) {
|
||||
const form = new FormData();
|
||||
form.append("file", input.file);
|
||||
if (input.source_type) form.append("source_type", input.source_type);
|
||||
if (input.name) form.append("name", input.name);
|
||||
if (input.description) form.append("description", input.description);
|
||||
if (input.tag) form.append("tag", input.tag);
|
||||
form.append("is_private", String(Boolean(input.is_private)));
|
||||
return request<{ skill: Skill }>(api.post("/skills/install", form)).finally(invalidateAddedSkillsCache);
|
||||
}
|
||||
|
||||
export function installGitHubSkill(input: InstallGitHubSkillInput) {
|
||||
return request<{ skill: Skill }>(api.post("/skills/install/github", input)).finally(invalidateAddedSkillsCache);
|
||||
}
|
||||
|
||||
export function listSkillFiles(id: string) {
|
||||
return request<{ files: SkillPackageFile[] }>(api.get(`/skills/${encodeURIComponent(id)}/files`));
|
||||
}
|
||||
|
||||
export function getSkillFile(id: string, path: string) {
|
||||
return request<{ file: SkillPackageFileContent }>(api.get(`/skills/${encodeURIComponent(id)}/file`, { params: { path } }));
|
||||
}
|
||||
|
||||
export function getSkillBundle(id: string) {
|
||||
return request<{ bundle: SkillPackageBundle }>(api.get(`/skills/${encodeURIComponent(id)}/bundle`));
|
||||
}
|
||||
|
||||
export function searchSkillFiles(id: string, query: string) {
|
||||
return request<{ results: SkillFileSearchResult[] }>(api.get(`/skills/${encodeURIComponent(id)}/search`, { params: { q: query } }));
|
||||
}
|
||||
|
||||
export function syncSkill(id: string) {
|
||||
return request<{ skill: Skill }>(api.post(`/skills/${encodeURIComponent(id)}/sync`)).finally(invalidateAddedSkillsCache);
|
||||
}
|
||||
|
||||
export function skillFileRawURL(id: string, path: string) {
|
||||
const base = String(api.defaults.baseURL || "/api").replace(/\/$/, "");
|
||||
return `${base}/skills/${encodeURIComponent(id)}/file/raw?path=${encodeURIComponent(path)}`;
|
||||
}
|
||||
|
||||
export function updateSkill(id: string, input: SkillMutationInput) {
|
||||
return request<{ skill: Skill }>(api.put(`/skills/${encodeURIComponent(id)}`, input)).finally(invalidateAddedSkillsCache);
|
||||
}
|
||||
|
||||
@@ -74,7 +74,13 @@ export type GenerationTask = {
|
||||
nodeId?: string;
|
||||
batchIndex?: number;
|
||||
batchCount?: number;
|
||||
};
|
||||
domainProjectId?: string;
|
||||
chapterId?: string;
|
||||
chapterOperation?: "characters" | "storyboard";
|
||||
shotId?: string;
|
||||
workflowStepId?: string;
|
||||
artifactType?: string;
|
||||
};
|
||||
created_at?: string;
|
||||
updated_at?: string;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user