# 从新建项目到拆完分镜存储的完整流程 ```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 ```