# 项目管理服务 - 流程图与关系图 > **文档版本**:v1.0 > **最后更新**:2026-02-02 > **关联文档**:[项目管理服务](./project-service.md) --- ## 目录 1. [数据库表关系图](#数据库表关系图) 2. [项目创建流程图](#项目创建流程图) 3. [项目克隆流程图](#项目克隆流程图) 4. [权限检查流程图](#权限检查流程图) 5. [项目生命周期状态图](#项目生命周期状态图) 6. [子项目关系图](#子项目关系图) --- ## 数据库表关系图 ```mermaid erDiagram projects ||--o{ project_members : "has members" projects ||--o{ project_shares : "has shares" projects ||--o{ project_versions : "has versions" projects ||--o{ projects : "parent-child" projects }o--|| users : "owned by" projects }o--o| folders : "belongs to" projects }o--o| screenplays : "linked to" projects }o--o| attachments : "cover image" projects { uuid project_id PK "UUID v7" text name "项目名称" smallint type "1=mine, 2=collab" text owner_type "user | organization" uuid owner_id FK "逻辑外键" uuid folder_id FK "逻辑外键" uuid parent_project_id FK "父项目ID" uuid screenplay_id FK "剧本ID(子项目)" uuid cover_image_id FK "封面图片ID" smallint content_type "1=ad, 2=movie..." smallint aspect_ratio "1=16:9, 2=9:16..." integer planned_duration "计划时长(秒)" integer actual_duration "实际时长(秒)" text visual_style "视觉风格" jsonb settings "项目配置" smallint status "0=active, 2=trashed, 3=deleted" timestamptz created_at timestamptz updated_at timestamptz trashed_at timestamptz deleted_at } project_members { uuid member_id PK "UUID v7" uuid project_id FK "逻辑外键" uuid user_id FK "逻辑外键" smallint role "1=owner, 2=editor, 3=viewer" uuid invited_by FK "邀请人ID" timestamptz created_at timestamptz updated_at } project_shares { uuid share_id PK "UUID v7" uuid project_id FK "逻辑外键" text share_token UK "分享令牌" text password_hash "密码哈希" smallint permission "1=viewer, 2=editor" uuid created_by FK "创建者ID" timestamptz created_at timestamptz expires_at timestamptz last_accessed_at integer access_count } project_versions { uuid version_id PK "UUID v7" uuid project_id FK "逻辑外键" integer version_number "版本号" jsonb snapshot_data "项目快照" uuid created_by FK "创建者ID" text note "版本说明" timestamptz created_at } users { uuid user_id PK text nickname } folders { uuid folder_id PK text name } screenplays { uuid screenplay_id PK text title } attachments { uuid attachment_id PK text file_url } ``` **说明**: - 所有外键关系均为**逻辑外键**(无物理约束) - 引用完整性由应用层(Service/Repository)保证 - `projects` 表支持自引用(父子项目关系) - 子项目必须关联剧本(`parent_project_id` 和 `screenplay_id` 同时存在或同时为空) --- ## 项目创建流程图 ```mermaid flowchart TD Start([用户请求创建项目]) --> ValidateAuth{验证用户身份} ValidateAuth -->|未登录| Error1[返回 401 未授权] ValidateAuth -->|已登录| ValidateUser{校验用户存在性} ValidateUser -->|用户不存在| Error2[返回 400 用户不存在] ValidateUser -->|用户存在| CheckFolder{是否指定文件夹?} CheckFolder -->|是| ValidateFolder{校验文件夹存在性} CheckFolder -->|否| CheckCover ValidateFolder -->|文件夹不存在| Error3[返回 400 文件夹不存在] ValidateFolder -->|文件夹存在| CheckFolderPerm{检查文件夹权限} CheckFolderPerm -->|无权限| Error4[返回 403 无权限] CheckFolderPerm -->|有权限| CheckCover CheckCover{是否指定封面图片?} -->|是| ValidateCover{校验附件存在性和所属权} CheckCover -->|否| ValidateType ValidateCover -->|附件不存在或无权限| Error5[返回 400/403] ValidateCover -->|校验通过| ValidateType ValidateType{验证项目类型} -->|无效类型| Error6[返回 400 无效类型] ValidateType -->|有效类型| GenerateUUID[生成 UUID v7] GenerateUUID --> CreateProject[创建项目记录] CreateProject --> CheckCollab{是否为协作项目?} CheckCollab -->|是| AddOwnerMember[添加创建者为成员
role=owner] CheckCollab -->|否| LogCreate AddOwnerMember --> LogCreate[记录日志] LogCreate --> Success([返回项目信息]) style Start fill:#e1f5e1 style Success fill:#e1f5e1 style Error1 fill:#ffe1e1 style Error2 fill:#ffe1e1 style Error3 fill:#ffe1e1 style Error4 fill:#ffe1e1 style Error5 fill:#ffe1e1 style Error6 fill:#ffe1e1 ``` **流程说明**: 1. **身份验证**:检查用户登录状态 2. **用户校验**:确认用户存在(引用完整性) 3. **文件夹校验**:如果指定文件夹,检查存在性和权限 4. **封面图片校验**:如果指定封面,检查附件存在性和所属权 5. **类型验证**:确保项目类型为 `mine` 或 `collab` 6. **UUID 生成**:应用层生成 UUID v7 7. **创建项目**:插入数据库记录 8. **成员管理**:协作项目自动添加创建者为 owner 9. **日志记录**:记录操作日志 --- ## 项目克隆流程图 ```mermaid flowchart TD Start([用户请求克隆项目]) --> CheckPerm{检查源项目权限} CheckPerm -->|无权限| Error1[返回 403 无权限] CheckPerm -->|有 viewer 权限| GetSource[获取源项目信息] GetSource --> GenerateName[生成唯一副本名称
基础名称-副本N] GenerateName --> CreateTask{创建异步任务} CreateTask --> ReturnTaskId[返回 task_id
status=pending] ReturnTaskId --> AsyncStart([异步任务开始]) AsyncStart --> CloneBasic[复制项目基本信息] CloneBasic --> CloneSettings[复制项目配置] CloneSettings --> CloneStoryboards{复制分镜?} CloneStoryboards -->|是| CopyStoryboards[复制所有分镜] CloneStoryboards -->|否| CloneResources CopyStoryboards --> CloneResources{复制资源?} CloneResources -->|是| CopyResources[复制视频/附件] CloneResources -->|否| UpdateProgress CopyResources --> UpdateProgress[更新任务进度] UpdateProgress --> Commit[提交事务] Commit --> Success{克隆成功?} Success -->|是| TaskComplete[任务状态=completed
progress=100] Success -->|否| TaskFailed[任务状态=failed
记录错误信息] TaskComplete --> End([用户查询任务状态]) TaskFailed --> End style Start fill:#e1f5e1 style End fill:#e1f5e1 style Error1 fill:#ffe1e1 style AsyncStart fill:#fff4e1 style TaskComplete fill:#e1f5e1 style TaskFailed fill:#ffe1e1 ``` **流程说明**: 1. **权限检查**:确保用户至少有 viewer 权限 2. **名称生成**:自动生成唯一的副本名称(避免重名) 3. **异步任务**:创建任务并立即返回 task_id 4. **基本信息复制**:复制项目名称、描述、类型等 5. **配置复制**:复制 settings(分辨率、帧率等) 6. **分镜复制**:复制所有分镜及其关联资源 7. **资源复制**:复制视频、附件等文件 8. **进度更新**:实时更新任务进度 9. **状态通知**:任务完成或失败后更新状态 --- ## 权限检查流程图 ```mermaid flowchart TD Start([检查用户权限]) --> GetProject{获取项目信息} GetProject -->|项目不存在| Return1[返回 False] GetProject -->|项目存在| CheckOwner{是否为项目所有者?} CheckOwner -->|是| Return2[返回 True
所有者拥有所有权限] CheckOwner -->|否| CheckType{项目类型?} CheckType -->|个人项目 mine| Return3[返回 False
非所有者无权限] CheckType -->|协作项目 collab| QueryMember[查询成员表
project_members] QueryMember --> IsMember{是否为成员?} IsMember -->|否| Return4[返回 False] IsMember -->|是| GetRole[获取成员角色] GetRole --> CompareRole{角色权限对比} CompareRole --> CalcHierarchy[权限层级:
owner=3
editor=2
viewer=1] CalcHierarchy --> CheckRequired{成员权限 >= 所需权限?} CheckRequired -->|是| Return5[返回 True] CheckRequired -->|否| Return6[返回 False] style Start fill:#e1f5e1 style Return2 fill:#e1f5e1 style Return5 fill:#e1f5e1 style Return1 fill:#ffe1e1 style Return3 fill:#ffe1e1 style Return4 fill:#ffe1e1 style Return6 fill:#ffe1e1 ``` **权限层级说明**: - `owner` (3):所有权限(创建、编辑、删除、管理成员、分享) - `editor` (2):编辑权限(创建、编辑分镜和资源) - `viewer` (1):查看权限(只读访问) **权限检查逻辑**: 1. **项目所有者**:自动拥有所有权限 2. **个人项目**:只有所有者有权限 3. **协作项目**:检查成员表中的角色 4. **权限对比**:成员角色权限 >= 所需权限时通过 **示例**: - 用户角色为 `editor`,所需权限为 `viewer` → 通过(2 >= 1) - 用户角色为 `viewer`,所需权限为 `editor` → 拒绝(1 < 2) --- ## 项目生命周期状态图 ```mermaid stateDiagram-v2 [*] --> Active: 创建项目 Active --> Archived: 用户归档 Archived --> Active: 取消归档 Active --> Trashed: 移至回收站
(DELETE /projects/{id}) Archived --> Trashed: 移至回收站 Trashed --> Active: 从回收站恢复
(POST /projects/{id}/restore) Trashed --> SoftDeleted: 永久删除
(DELETE /projects/{id}/permanent) Trashed --> SoftDeleted: 30天后自动清理 SoftDeleted --> [*]: 物理删除
(仅管理员) note right of Active status = 0 用户可见、可编辑 end note note right of Archived status = 1 用户可见、只读 end note note right of Trashed status = 2 回收站可见 30天内可恢复 trashed_at 记录时间 end note note right of SoftDeleted status = 3 用户不可见 数据保留 deleted_at 记录时间 end note ``` **状态说明**: | 状态 | 数值 | 用户可见 | 可编辑 | 说明 | |------|------|---------|--------|------| | **Active** | 0 | ✅ | ✅ | 活跃项目,正常使用 | | **Archived** | 1 | ✅ | ❌ | 归档项目,只读(预留功能) | | **Trashed** | 2 | ⚠️ | ❌ | 回收站,30天内可恢复 | | **SoftDeleted** | 3 | ❌ | ❌ | 软删除,用户不可见,数据保留 | **状态转换规则**: 1. **创建项目** → Active 2. **用户归档** → Active ↔ Archived(预留功能) 3. **移至回收站** → Active/Archived → Trashed 4. **从回收站恢复** → Trashed → Active 5. **永久删除** → Trashed → SoftDeleted 6. **自动清理** → Trashed(30天后)→ SoftDeleted 7. **物理删除** → SoftDeleted → 数据库删除(仅管理员) **回收站机制**: - 用户删除项目时,状态变为 `Trashed`,设置 `trashed_at` - 30天内可通过 API 恢复 - 30天后自动转为 `SoftDeleted` - 用户可在回收站中立即永久删除(转为 `SoftDeleted`) --- ## 子项目关系图 ```mermaid flowchart TD subgraph "父项目 (Parent Project)" P1[项目: 电视剧制作
parent_project_id = NULL
screenplay_id = NULL] end subgraph "子项目 (Subprojects)" S1[子项目: 第1集
parent_project_id = P1.id
screenplay_id = SC1.id] S2[子项目: 第2集
parent_project_id = P1.id
screenplay_id = SC2.id] S3[子项目: 第3集
parent_project_id = P1.id
screenplay_id = SC3.id] end subgraph "剧本 (Screenplays)" SC1[剧本: 第1集剧本
screenplay_id = SC1] SC2[剧本: 第2集剧本
screenplay_id = SC2] SC3[剧本: 第3集剧本
screenplay_id = SC3] end P1 -->|创建子项目| S1 P1 -->|创建子项目| S2 P1 -->|创建子项目| S3 S1 -.->|关联剧本
一对一| SC1 S2 -.->|关联剧本
一对一| SC2 S3 -.->|关联剧本
一对一| SC3 subgraph "继承关系" I1[权限继承:
子项目继承父项目的成员权限] I2[设置继承:
子项目复制父项目的 settings] I3[文件夹继承:
子项目与父项目在同一文件夹] end P1 -.->|继承| I1 P1 -.->|继承| I2 P1 -.->|继承| I3 style P1 fill:#e1f5e1 style S1 fill:#fff4e1 style S2 fill:#fff4e1 style S3 fill:#fff4e1 style SC1 fill:#e1e5ff style SC2 fill:#e1e5ff style SC3 fill:#e1e5ff ``` **子项目特性**: 1. **一对一关系**:每个子项目关联一个剧本 2. **权限继承**:子项目自动继承父项目的成员权限 3. **设置继承**:子项目复制父项目的配置(分辨率、帧率等) 4. **独立管理**:子项目可独立管理分镜、资源、导出等 5. **自动创建**:上传剧本时自动创建子项目 **数据库约束**: ```sql -- 子项目约束:parent_project_id 和 screenplay_id 必须同时存在或同时为空 CONSTRAINT projects_subproject_screenplay_check CHECK ( (parent_project_id IS NULL AND screenplay_id IS NULL) OR (parent_project_id IS NOT NULL AND screenplay_id IS NOT NULL) ) ``` **使用场景**: - **电视剧制作**:父项目为整部剧,每集为一个子项目 - **系列广告**:父项目为广告系列,每个广告为一个子项目 - **多章节内容**:父项目为整体内容,每章节为一个子项目 **API 接口**: ```bash # 获取子项目列表 GET /api/v1/projects/{parent_project_id}/subprojects # 创建子项目(通常由剧本服务自动调用) POST /api/v1/projects/{parent_project_id}/subprojects ``` --- ## 相关文档 - [项目管理服务](./project-service.md) - 服务实现、API 接口、数据库设计 - [项目资源管理服务](./project-resource-service.md) - 项目资源关联管理 - [文件夹管理服务](../folder/folder-service.md) - 文件夹权限和归属 - [剧本管理服务](../screenplay/screenplay-service.md) - 剧本与子项目关联 --- **文档版本**:v1.0 **最后更新**:2026-02-02