Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 31 additions & 4 deletions frontend/src/entities/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
/**
* entities 唯一公开入口。外部不得绕过本文件访问内部文件。
* 本次只提交类型与接口,不提交实现。
* Entity 层的唯一公开入口。
*
* Page 和 Feature 只从 `@/entities` 导入,不直接访问某个 Entity 的内部文件。
* 这不是为了少写一段路径,而是为了稳定模块边界:内部文件可以重构,
* 但公开名称和依赖方向必须经过本文件明确审核。
*
* 这里只暴露 Entity 级别的数据结构、后端端口契约以及必要的本地 Store 工厂。
* 页面状态、路由、弹窗和按钮行为不属于 Entity,不应从此处导出。
*/

/* 项目 —— 全局约束:视角、朝向、精灵尺寸、画风 */
Expand Down Expand Up @@ -55,10 +61,26 @@ export type {
/* 媒体引用 —— 不承诺 URL 或后端 Media ID 的具体表示 */
export type { MediaReference } from './media'

/* 工作流 —— 节点与运行状态都由前端管理 */
export { WORKFLOW_STEP_ORDER } from './workflow-run'
/*
* 工作流 —— 记录“一次用户任务如何运行”。
* 它不是角色/动作资产,也不是负责调后端的 WorkflowController。
*/
export {
ACTION_FIRST_FRAME_CANDIDATE_COUNT,
CHARACTER_CANDIDATE_COUNT,
createWorkflowRunService,
createWorkflowRunStore,
WORKFLOW_STEP_ORDERS,
} from './workflow-run'
export type {
ActionFirstFrameCandidateBatch,
CreateWorkflowRunStoreOptions,
CreateWorkflowRunServiceOptions,
CreateWorkflowRunInput,
CharacterCandidateBatch,
CharacterCandidateConfirmationApis,
ConfirmCharacterSelectionInput,
ConfirmActionFirstFrameInput,
ExportStatus,
GenerationStatus,
WorkflowDriver,
Expand All @@ -68,6 +90,11 @@ export type {
WorkflowRevision,
WorkflowRevisionStatus,
WorkflowRun,
WorkflowRunStore,
WorkflowRunService,
WorkflowRunPurpose,
WorkflowRunStatus,
PublishActionResult,
StartActionRunInput,
StartCharacterRunInput,
} from './workflow-run'
194 changes: 39 additions & 155 deletions frontend/src/entities/workflow-run/index.ts
Original file line number Diff line number Diff line change
@@ -1,157 +1,41 @@
import type { Generation } from '../generation'

/** Quick Start 与手动工作流只改变输入方式,共用同一种运行模型。 */
export type WorkflowDriver = 'ai' | 'manual'

/** 创建 WorkflowRun 时要完成的用户意图。 */
export type WorkflowRunPurpose = 'create_character' | 'add_action'

/**
* 流程步骤类型的唯一标准顺序;它不是后端 Workflow 或 Execution 定义。
* 某个 Revision 已进入执行线的步骤顺序,由 WorkflowRevision.nodes 的数组位置表达。
*/
export const WORKFLOW_STEP_ORDER = [
'character-setup',
'character-template',
'template-candidate',
'action-setup',
'first-frame',
'complete-animation',
'review',
'export',
] as const

/** 前端流程步骤类型,与 WORKFLOW_STEP_ORDER 的成员保持一致。 */
export type WorkflowStepType = (typeof WORKFLOW_STEP_ORDER)[number]

/**
* 步骤的可用性和执行结果;不直接复用后端任务状态。
* locked/available 表示尚未执行,active 表示当前页面阶段,passed/failed 表示结果。
*/
export type WorkflowStepStatus = 'locked' | 'available' | 'active' | 'passed' | 'failed'

/**
* 单个版本的生命周期。
* abandoned 表示停止沿用但仍保留为历史。
*/
export type WorkflowRevisionStatus = 'active' | 'completed' | 'failed' | 'abandoned'

/**
* 整次流程的汇总状态。
* interrupted 只表示用户主动停止自动推进:历史仍保留且可只读查看,它不等于 failed 或 completed。
* 后端生成任务是否真正停止是独立问题;从历史重启成功后可重新进入 active。
*/
export type WorkflowRunStatus = 'active' | 'interrupted' | 'completed' | 'failed'

/**
* 当前版本在生成阶段的汇总状态;素材准备期间为 not_started。
* 它是版本级别的汇总,不是单次生成任务的状态——后者是 TaskStatus。
*/
export type GenerationStatus = 'not_started' | 'in_progress' | 'completed' | 'failed'

/** 当前版本在导出阶段的汇总状态。 */
export type ExportStatus = 'not_exported' | 'exporting' | 'exported' | 'failed'

/**
* 一个 Revision 中已经进入执行线的流程步骤。
* 步骤自身不重复保存顺序;其在 nodes 中的数组位置就是该版本的执行顺序。
*/
export interface WorkflowStep {
/** 只用于编排和页面定位,不作为业务 ID 发送给后端。 */
id: string
type: WorkflowStepType
status: WorkflowStepStatus
/** 进入步骤时保存的输入快照。 */
input: unknown
/** 步骤完成后的结果或引用;尚无结果时为 null。 */
output: unknown
/**
* 本步骤已提交、结果尚未写回 output 的 Generation ID;没有在途任务时为 null。
* 它由前端随 WorkflowRun 一起维护,据此查回在途任务的状态,因而不会在同一次
* 前端运行中重复发起生成。是否写入浏览器存储属于前端实现,不形成后端契约。
* Generation 本身不认识步骤,反向关联不存在。
*
* 字段名沿用后端的 task_id。步骤类型不能从 Generation.type 反推——后端只有
* character_image 和 character_action 两种,本步骤是哪一步以 WorkflowStep.type 为准。
*/
taskId: Generation['id'] | null
/** 该步骤沿用或依赖的步骤 ID,用于版本来源追踪,不代表后端执行依赖。 */
referenceStepIds: string[]
}

/**
* 一次页面执行版本;当前版本会推进,从旧步骤重开则追加新版本。
* WorkflowRun Entity 的对外入口。
*
* MVP 只走单条执行线:revisions 恒为一个成员,basedOnRevisionId 与 restartStepId 恒为 null。
* 「从历史步骤重开并保留旧版本」尚未进入产品定义,结构先留出位置但不实现,
* 避免真要做时改动波及 WorkflowRun 的持久化形状。
*/
export interface WorkflowRevision {
id: string
/** 首次创建的版本没有来源,因此为 null。 */
basedOnRevisionId: string | null
/** 在来源版本中选择的重启步骤 ID;非重启创建的版本为 null。 */
restartStepId: string | null
status: WorkflowRevisionStatus
/**
* 已进入当前执行线的步骤;数组位置是该版本步骤顺序的唯一来源。
* 尚未推进到的后续步骤可以不存在;完整步骤类型顺序以 WORKFLOW_STEP_ORDER 为准。
*/
steps: WorkflowStep[]
generationStatus: GenerationStatus
exportStatus: ExportStatus
createdAt: string
}

/**
* 一次由前端推进的页面流程。
* 步骤推进和运行状态都由前端管理;后端不读取、不推进、也不持久化 WorkflowRun。
* 后端只处理生成任务,并在用户最终确认时持久化角色与动作资产。
*/
export interface WorkflowRun {
id: string
projectId: string
/** 已关联的 Character ID;角色尚未创建或确认时为 null。 */
characterId: string | null
/** 已有角色加动作时的目标造型;新建角色时为 null。 */
outfitId: string | null
purpose: WorkflowRunPurpose
driver: WorkflowDriver
status: WorkflowRunStatus
/** 当前可编辑版本 ID;必须能在 revisions 中找到。 */
currentRevisionId: string
/** 按创建顺序保存的全部版本;历史版本保留用于只读查看和重启。 */
revisions: WorkflowRevision[]
/** Quick Start 的规范化提示词;空白输入或手动模式无提示词时为 null。 */
prompt: string | null
}

/** 两种入口共享的创建字段。 */
interface CreateWorkflowRunInputBase {
projectId: string
driver: WorkflowDriver
/** Quick Start 的自然语言需求;提交时去除首尾空白,空字符串按 null 保存。 */
prompt?: string
}

/**
* 创建 WorkflowRun 的输入。
* add_action 分支把已有角色、造型、母版和基准帧设为必填,避免创建无法恢复的半成品运行。
*/
export type CreateWorkflowRunInput = CreateWorkflowRunInputBase &
(
| {
purpose: 'create_character'
characterId?: never
outfitId?: never
characterTemplateUrl?: never
baseFrameUrls?: never
}
| {
purpose: 'add_action'
characterId: string
outfitId: string
characterTemplateUrl: string
baseFrameUrls: readonly string[]
}
)
* 外部模块只从这里获取 WorkflowRun 能力,不绕过入口直接依赖 model/store
* 内部文件。这样既保留了子目录的职责分工,又不把内部结构变成全仓库 API。
*/

export {
ACTION_FIRST_FRAME_CANDIDATE_COUNT,
CHARACTER_CANDIDATE_COUNT,
WORKFLOW_STEP_ORDERS,
} from './model'
export type {
CreateWorkflowRunInput,
ExportStatus,
GenerationStatus,
WorkflowDriver,
WorkflowRevision,
WorkflowRevisionStatus,
WorkflowRun,
WorkflowRunPurpose,
WorkflowRunStatus,
WorkflowStep,
WorkflowStepStatus,
WorkflowStepType,
} from './model'
export { createWorkflowRunStore } from './store'
export type { CreateWorkflowRunStoreOptions, WorkflowRunStore } from './store'
export { createWorkflowRunService } from './service'
export type {
ActionFirstFrameCandidateBatch,
CharacterCandidateBatch,
CharacterCandidateConfirmationApis,
ConfirmCharacterSelectionInput,
ConfirmActionFirstFrameInput,
CreateWorkflowRunServiceOptions,
PublishActionResult,
StartActionRunInput,
StartCharacterRunInput,
WorkflowRunService,
} from './service'
63 changes: 63 additions & 0 deletions frontend/src/entities/workflow-run/model/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/**
* WorkflowRun 的业务词汇和步骤模板。
*
* 常量数组同时服务于三个地方:TypeScript 联合类型、运行时水合校验、
* 以及页面的进度顺序。只保留一份定义,可以避免“类型说可以,恢复时却拒绝”。
*/

/** 该 Run 是由 AI 自动引导,还是用户在编辑器中手动推进。 */
export const WORKFLOW_DRIVERS = ['ai', 'manual'] as const

/**
* 一个 Run 只有一个目标。新建角色和追加动作可在同一界面连续操作,
* 但是两次独立任务,因此使用两个 WorkflowRun。
*/
export const WORKFLOW_PURPOSES = ['create_character', 'add_action'] as const

/** Run 级状态:描述整个用户任务,不等于某次后端生成任务的状态。 */
export const WORKFLOW_RUN_STATUSES = ['active', 'interrupted', 'completed', 'failed'] as const

/**
* Revision 级状态。用户从旧步骤重做时,旧 Revision 变为 abandoned,
* 并追加新 Revision;不覆盖历史,才能说清“这个结果从哪次重做而来”。
*/
export const WORKFLOW_REVISION_STATUSES = ['active', 'completed', 'failed', 'abandoned'] as const

/** 当前 Revision 中生成阶段的汇总状态,不是单个 GenerationTask.status。 */
export const GENERATION_STATUSES = ['not_started', 'in_progress', 'completed', 'failed'] as const

/** 导出阶段的汇总状态;角色生成 Run 没有导出步骤时保持 not_exported。 */
export const EXPORT_STATUSES = ['not_exported', 'exporting', 'exported', 'failed'] as const

/**
* 单个步骤的状态。locked 表示前置条件未满足,available 表示可开始,
* active 表示当前正在处理,passed/failed 是已结束结果。
*/
export const WORKFLOW_STEP_STATUSES = ['locked', 'available', 'active', 'passed', 'failed'] as const

/** 角色形象每次生成 4 张临时候选;用户只会确认其中 1 张为正式资产。 */
export const CHARACTER_CANDIDATE_COUNT = 4

/** 动作也先生成 4 张独立首帧,避免错误姿势直接扩展成完整动画。 */
export const ACTION_FIRST_FRAME_CANDIDATE_COUNT = 4

/**
* 按任务目的分开定义步骤顺序。
*
* create_character 到“四选一并保存正式角色”就结束;
* add_action 从已有角色/造型开始,不重复跑角色母版生成。
*
* 两个 Run 可以由同一页面连续展示,但数据上必须拆开,否则历史记录、
* 失败重试和后续追加动作都无法准确归属。
*/
export const WORKFLOW_STEP_ORDERS = {
create_character: ['character-setup', 'character-template', 'template-candidate'],
add_action: [
'action-setup',
'first-frame',
'first-frame-candidate',
'complete-animation',
'review',
'export',
],
} as const
27 changes: 27 additions & 0 deletions frontend/src/entities/workflow-run/model/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/**
* WorkflowRun 领域模型的子目录入口。
*
* 本目录只定义“WorkflowRun 是什么”:业务词汇、步骤模板、Run/Revision/Step
* 类型以及创建输入。它不知道 localStorage、订阅者或页面,因此可被
* Store、Controller 和页面共同依赖,而不产生反向依赖。
*/

export {
ACTION_FIRST_FRAME_CANDIDATE_COUNT,
CHARACTER_CANDIDATE_COUNT,
WORKFLOW_STEP_ORDERS,
} from './constants'
export type {
CreateWorkflowRunInput,
ExportStatus,
GenerationStatus,
WorkflowDriver,
WorkflowRevision,
WorkflowRevisionStatus,
WorkflowRun,
WorkflowRunPurpose,
WorkflowRunStatus,
WorkflowStep,
WorkflowStepStatus,
WorkflowStepType,
} from './types'
Loading