# RFC 121: 项目服务实现 > **状态**:已实现 > **创建时间**:2026-01-20 > **实现时间**:2026-01-20 > **作者**:System --- ## 概述 实现项目管理服务的核心功能,包括 CRUD 操作、权限管理、成员管理、搜索筛选、分享功能等。 --- ## 背景 项目(Project)是系统的核心实体,用户通过项目组织和管理分镜、视频等资源。需要实现完整的项目管理功能以支持业务需求。 --- ## 目标 ### 主要目标 1. 实现项目的完整 CRUD 操作 2. 实现三级权限管理(owner/editor/viewer) 3. 支持协作项目的成员管理 4. 实现全文搜索和多条件筛选 5. 实现项目分享功能 6. 为异步任务预留接口 ### 非目标 - 异步任务队列实现(后续 RFC) - 版本控制功能(后续 RFC) - 企业功能(V2) --- ## 技术方案 ### 架构设计 采用三层架构: ``` API Layer (projects.py) ↓ Service Layer (project_service.py) ↓ Repository Layer (project_repository.py) ↓ Model Layer (project.py) ``` ### 数据模型 #### 1. Project(项目表) ```python class Project(SQLModel, table=True): id: UUID # UUID v7 主键 name: str description: Optional[str] type: ProjectType # mine | collab owner_type: str # V1: 固定为 'user' owner_id: UUID folder_id: Optional[UUID] display_order: int content_type: Optional[ProjectContentType] aspect_ratio: Optional[AspectRatioType] planned_duration: Optional[int] actual_duration: Optional[int] style_and_characters: Optional[str] settings: dict # JSONB status: ProjectStatus created_at: datetime updated_at: datetime deleted_at: Optional[datetime] ``` #### 2. ProjectMember(成员表) ```python class ProjectMember(SQLModel, table=True): id: UUID project_id: UUID user_id: UUID role: MemberRole # owner | editor | viewer invited_by: Optional[UUID] joined_at: datetime created_at: datetime ``` #### 3. ProjectShare(分享表) ```python class ProjectShare(SQLModel, table=True): id: UUID project_id: UUID share_token: str # 唯一令牌 password_hash: Optional[str] permission: SharePermission # viewer | editor created_by: UUID created_at: datetime expires_at: Optional[datetime] last_accessed_at: Optional[datetime] access_count: int ``` #### 4. ProjectVersion(版本表,预留) ```python class ProjectVersion(SQLModel, table=True): id: UUID project_id: UUID version_number: int snapshot_data: dict # JSONB created_by: UUID note: Optional[str] created_at: datetime ``` ### 核心功能实现 #### 1. 搜索和筛选 **实现方式**: - 使用 pg_trgm 扩展支持全文搜索 - 在 name 和 description 字段上创建 GIN 索引 - 使用 ILIKE 进行模糊匹配 **查询条件**: - `type`: 项目类型(mine/collab) - `folder_id`: 所属文件夹 - `content_type`: 内容类型 - `search`: 关键词搜索 **排序支持**: - `created_at`: 创建时间 - `updated_at`: 更新时间 - `name`: 名称 - `display_order`: 自定义顺序 #### 2. 权限管理 **权限级别**: 1. **Owner**:完全控制权(删除、添加成员、创建分享) 2. **Editor**:编辑权限(修改项目、移动项目) 3. **Viewer**:只读权限(查看项目) **权限检查逻辑**: ```python async def check_user_permission(user_id, project_id, required_role): # 1. 检查是否为所有者 if project.owner_id == user_id: return True # 2. 检查成员权限 member = await get_member(project_id, user_id) if member: return compare_role(member.role, required_role) return False ``` #### 3. 分享功能 **分享链接生成**: ```python share_token = secrets.token_urlsafe(32) share_url = f"/share/p/{share_token}" ``` **特性**: - 密码保护(可选) - 过期时间(可选) - 权限控制(viewer/editor) - 访问统计 #### 4. 克隆功能 **当前实现**:同步版本 ```python async def clone_project(source_project, new_name, owner_id, folder_id): # 1. 复制项目基本信息 new_project = Project(...) # 2. TODO: 复制关联资源(分镜、视频、附件) # 需要等待相关模型实现 return new_project ``` **限制**: - 大项目可能超时 - 暂不复制关联资源 **TODO**: - 实现异步任务队列 - 复制关联资源 #### 5. 导出功能 **当前实现**:接口框架 ```python async def export_project(user_id, project_id): return { 'task_id': 'dev-placeholder', 'status': 'pending', 'message': '导出功能开发中,敬请期待' } ``` **TODO**: - 实现异步任务队列 - 实现 ZIP 打包逻辑 - 实现文件下载管理 --- ## API 设计 ### 端点列表 | 方法 | 路径 | 描述 | 权限 | |------|------|------|------| | GET | `/projects` | 获取项目列表 | 认证 | | POST | `/projects` | 创建项目 | 认证 | | GET | `/projects/{id}` | 获取详情 | viewer | | PUT | `/projects/{id}` | 更新项目 | editor | | DELETE | `/projects/{id}` | 删除项目 | owner | | POST | `/projects/{id}/move` | 移动项目 | editor | | POST | `/projects/{id}/clone` | 克隆项目 | viewer | | POST | `/projects/{id}/export` | 导出项目 | viewer | | POST | `/projects/{id}/shares` | 创建分享 | owner | | GET | `/projects/{id}/shares` | 获取分享列表 | viewer | | DELETE | `/projects/{id}/shares/{share_id}` | 撤销分享 | owner | | PUT | `/projects/{id}/order` | 更新排序 | editor | | GET | `/projects/{id}/members` | 获取成员列表 | viewer | | POST | `/projects/{id}/members` | 添加成员 | owner | | DELETE | `/projects/{id}/members/{user_id}` | 移除成员 | owner | ### 请求示例 #### 创建项目 ```http POST /api/v1/projects Content-Type: application/json { "name": "我的广告片", "description": "2026年春节广告", "type": "mine", "folderId": "uuid-here", "contentType": "ad", "aspectRatio": "16:9", "plannedDuration": 60, "settings": { "resolution": "1920x1080", "fps": 30 } } ``` #### 搜索项目 ```http GET /api/v1/projects?search=广告&contentType=ad&sortBy=updated_at&sortOrder=desc&page=1&pageSize=20 ``` #### 创建分享 ```http POST /api/v1/projects/{id}/shares Content-Type: application/json { "password": "optional-password", "permission": "viewer", "expiresAt": "2026-02-01T00:00:00Z" } ``` --- ## 数据库设计 ### 表结构 #### projects 表 ```sql CREATE TABLE projects ( project_id UUID PRIMARY KEY, name VARCHAR(255) NOT NULL, description TEXT, type project_type NOT NULL DEFAULT 'mine', owner_type VARCHAR(20) NOT NULL DEFAULT 'user', owner_id UUID NOT NULL REFERENCES users(user_id), folder_id UUID REFERENCES folders(id), display_order INTEGER NOT NULL DEFAULT 0, thumbnail_url VARCHAR(500), cover_image_id UUID, ai_credits_budget INTEGER NOT NULL DEFAULT 0, budget_consumed INTEGER NOT NULL DEFAULT 0, content_type project_content_type, aspect_ratio aspect_ratio_type, planned_duration INTEGER, actual_duration INTEGER, style_and_characters TEXT, settings JSONB NOT NULL DEFAULT '{}', status project_status NOT NULL DEFAULT 'active', created_at TIMESTAMPTZ NOT NULL DEFAULT now(), updated_at TIMESTAMPTZ NOT NULL DEFAULT now(), deleted_at TIMESTAMPTZ, CONSTRAINT projects_name_unique UNIQUE NULLS NOT DISTINCT (folder_id, name, owner_id) ); ``` ### 索引策略 **基础索引**: - `idx_projects_owner`: (owner_type, owner_id) - `idx_projects_folder_id`: (folder_id) - `idx_projects_type`: (type) - `idx_projects_status`: (status) **时间索引**: - `idx_projects_created_at`: (created_at) - `idx_projects_updated_at`: (updated_at) **全文搜索索引**: - `idx_projects_name_trgm`: GIN (name gin_trgm_ops) - `idx_projects_description_trgm`: GIN (description gin_trgm_ops) **JSONB 索引**: - `idx_projects_settings_gin`: GIN (settings) --- ## 实现细节 ### 文件清单 **新建文件**(6 个): 1. `server/app/models/project.py` - 数据模型 2. `server/app/schemas/project.py` - Schema 定义 3. `server/app/repositories/project_repository.py` - 数据访问层 4. `server/app/services/project_service.py` - 业务逻辑层 5. `server/app/api/v1/projects.py` - API 路由 6. `server/app/migrations/003_project_tables.py` - 数据库迁移 **修改文件**(2 个): 1. `server/app/api/v1/router.py` - 添加路由注册 2. `docs/requirements/backend/04-services/project/project-service.md` - 更新文档 ### 代码统计 - 模型层:~250 行 - Schema 层:~300 行 - Repository 层:~450 行 - Service 层:~500 行 - API 层:~400 行 - 迁移脚本:~250 行 **总计**:~2150 行代码 --- ## 测试策略 ### 单元测试 **Repository 层**: - 测试 CRUD 操作 - 测试查询和筛选 - 测试权限检查 **Service 层**: - 测试业务逻辑 - 测试权限验证 - 测试异常处理 ### 集成测试 **API 层**: - 测试所有端点 - 测试认证和授权 - 测试错误响应 ### 性能测试 - 搜索性能(1000+ 项目) - 分页性能 - 索引效率 --- ## 风险和限制 ### 已知限制 1. **克隆功能**: - 同步执行,大项目可能超时 - 暂不复制关联资源 2. **导出功能**: - 仅返回开发中状态 - 需要异步任务队列支持 3. **全文搜索**: - 使用 ILIKE,性能一般 - 可升级为 similarity 函数 ### 技术债务 1. 权限继承逻辑需要完善 2. 批量操作支持 3. 项目统计信息 4. 搜索性能优化 --- ## 后续工作 ### 短期(1-2 周) 1. 实现异步任务队列(Celery/ARQ) 2. 完善克隆功能(复制关联资源) 3. 实现导出功能 ### 中期(1-2 月) 1. 实现版本控制功能 2. 优化全文搜索性能 3. 实现批量操作 ### 长期(3+ 月) 1. 企业功能支持(V2) 2. 项目模板功能 3. 项目分析和统计 --- ## 参考资料 - [项目服务文档](../../requirements/backend/04-services/project/project-service.md) - [Folder 服务实现](./016-folder-service-implementation.md) - [UUID v7 迁移](../architecture/adrs/001-uuid-v7-migration.md) --- **RFC 状态**:已实现 **实现时间**:2026-01-20