# 从新建项目到拆完分镜存储的完整流程
```mermaid
%%{init: {'theme':'base', 'themeVariables': { 'primaryColor':'#e3f2fd','primaryTextColor':'#000','primaryBorderColor':'#1976d2','lineColor':'#424242','secondaryColor':'#fff3e0','tertiaryColor':'#f3e5f5','noteBkgColor':'#fff9c4','noteTextColor':'#000','noteBorderColor':'#fbc02d'}}}%%
sequenceDiagram
autonumber
actor User as 用户
participant ProjectAPI as API Layer
/api/v1/projects
participant ProjectService as ProjectService
participant ProjectRepo as ProjectRepository
participant ProjectDB as PostgreSQL
projects 表
participant StoryboardAPI as API Layer
/api/v1/storyboards
participant StoryboardService as StoryboardService
participant StoryboardRepo as StoryboardRepository
participant StoryboardDB as PostgreSQL
storyboards 表
participant ItemDB as PostgreSQL
storyboard_items 表
%% 阶段 1: 创建项目
rect rgb(227, 242, 253)
Note over User,ProjectDB: 阶段 1: 创建项目
User->>+ProjectAPI: POST /api/v1/projects
{name, type, sharedResources, ...}
ProjectAPI->>+ProjectService: create_project(user_id, project_data)
Note right of ProjectService: 验证逻辑
1. 检查文件夹权限
2. 检查名称唯一性
3. 转换枚举值
ProjectService->>+ProjectRepo: create(project)
ProjectRepo->>+ProjectDB: INSERT INTO projects
(id, name, type, owner_id, ...)
ProjectDB-->>-ProjectRepo: project_id (UUID v7)
ProjectRepo-->>-ProjectService: Project 对象
alt 协作项目 (type = "collab")
ProjectService->>ProjectRepo: add_member(project_id, user_id, OWNER)
ProjectRepo->>ProjectDB: INSERT INTO project_members
end
alt 有共享资源 (shared_resources)
ProjectService->>ProjectService: 调用 ProjectResourceShareService
创建共享资源关联
Note right of ProjectService: ADR 02: 跨项目资源共享
存储到 project_resource_shares 表
loop 处理每个共享配置
alt source_type = "folder"
ProjectService->>ProjectDB: 查询文件夹下的所有父项目
ProjectDB-->>ProjectService: 返回项目列表
loop 为每个项目创建共享记录
ProjectService->>ProjectDB: INSERT INTO project_resource_shares
(source_project_id, target_project_id,
share_type=1, status=1)
end
else source_type = "project"
ProjectService->>ProjectDB: INSERT INTO project_resource_shares
(source_project_id, target_project_id,
share_type=1, status=1)
else source_type = "resource"
ProjectService->>ProjectDB: INSERT INTO project_resource_shares
(source_project_id, target_project_id,
share_type=3, resource_type, resource_id,
status=1)
end
end
end
ProjectService-->>-ProjectAPI: Project 对象
ProjectAPI-->>-User: 200 OK
{id, name, type, status, ...}
Note over User: 项目创建完成
- 项目 ID: UUID v7
- 状态: active
- 类型: mine/collab
end
%% 阶段 2: 创建分镜
rect rgb(255, 243, 224)
Note over User,ItemDB: 阶段 2: 创建分镜
User->>+StoryboardAPI: POST /api/v1/storyboards
{projectId, title, description, ...}
StoryboardAPI->>+StoryboardService: create_storyboard(user_id, project_id, title, ...)
Note right of StoryboardService: 分镜创建逻辑
1. 检查项目权限 (editor)
2. 获取下一个 order_index
3. 计算 end_time
4. 默认时长 5 秒
StoryboardService->>+ProjectRepo: check_user_permission(user_id, project_id, 'editor')
ProjectRepo->>ProjectDB: SELECT FROM projects/project_members
ProjectDB-->>ProjectRepo: 权限验证结果
ProjectRepo-->>-StoryboardService: has_permission = True
StoryboardService->>+StoryboardRepo: get_max_order(project_id)
StoryboardRepo->>StoryboardDB: SELECT MAX(order_index)
FROM storyboards
WHERE project_id = ?
StoryboardDB-->>StoryboardRepo: max_order (例如: 5)
StoryboardRepo-->>-StoryboardService: max_order = 5
Note right of StoryboardService: 计算顺序索引
order_index = max_order + 1
例如: 5 + 1 = 6
StoryboardService->>+StoryboardRepo: create(storyboard)
StoryboardRepo->>+StoryboardDB: INSERT INTO storyboards
(storyboard_id, project_id, title,
order_index, start_time, end_time, ...)
StoryboardDB-->>-StoryboardRepo: storyboard_id (UUID v7)
StoryboardRepo-->>-StoryboardService: Storyboard 对象
StoryboardService-->>-StoryboardAPI: Storyboard 对象
StoryboardAPI-->>-User: 200 OK
{storyboardId, orderIndex, startTime, ...}
Note over User: 分镜创建完成
- 分镜 ID: UUID v7
- 镜号: order_index
- 时间轴: start_time → end_time
end
%% 阶段 3: 添加元素到分镜
rect rgb(243, 229, 245)
Note over User,ItemDB: 阶段 3: 添加元素到分镜 (循环)
loop 为每个分镜添加元素
User->>+StoryboardAPI: POST /api/v1/storyboards/{id}/items
{itemType, elementTagId/resourceId, ...}
StoryboardAPI->>+StoryboardService: add_element_to_storyboard(user_id, storyboard_id, ...)
Note right of StoryboardService: 元素类型验证
item_type = 1: 剧本元素标签
item_type = 2: 项目素材
StoryboardService->>+StoryboardRepo: get_by_id(storyboard_id)
StoryboardRepo->>StoryboardDB: SELECT FROM storyboards
StoryboardDB-->>StoryboardRepo: Storyboard 对象
StoryboardRepo-->>-StoryboardService: Storyboard 对象
StoryboardService->>ProjectRepo: check_user_permission(user_id, project_id, 'editor')
ProjectRepo->>ProjectDB: 权限验证
ProjectDB-->>ProjectRepo: 验证结果
ProjectRepo-->>StoryboardService: has_permission = True
alt item_type = 1 (剧本元素标签)
Note right of StoryboardService: 验证 element_tag_id 存在
获取标签信息
else item_type = 2 (项目素材)
Note right of StoryboardService: 验证 resource_id 存在
获取素材信息
end
StoryboardService->>+StoryboardRepo: get_max_display_order(storyboard_id)
StoryboardRepo->>ItemDB: SELECT MAX(display_order)
FROM storyboard_items
ItemDB-->>StoryboardRepo: max_order (例如: 3)
StoryboardRepo-->>-StoryboardService: max_order = 3
Note right of StoryboardService: 计算显示顺序
display_order = max_order + 1
例如: 3 + 1 = 4
StoryboardService->>+StoryboardRepo: create_item(item)
StoryboardRepo->>+ItemDB: INSERT INTO storyboard_items
(item_id, storyboard_id, item_type,
element_tag_id, resource_id, ...)
ItemDB-->>-StoryboardRepo: item_id (UUID v7)
StoryboardRepo-->>-StoryboardService: StoryboardItem 对象
alt item_type = 2 (项目素材)
StoryboardService->>ProjectDB: UPDATE project_resources
SET usage_count = usage_count + 1
Note right of StoryboardService: 增加素材引用计数
end
StoryboardService-->>-StoryboardAPI: StoryboardItem 对象
StoryboardAPI-->>-User: 200 OK
{itemId, itemType, displayOrder, ...}
end
Note over User: 分镜元素添加完成
- 元素 ID: UUID v7
- 元素类型: 标签/素材
- 显示顺序: display_order
end
```