You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
10 KiB
10 KiB
RFC 121: 项目服务实现
状态:已实现
创建时间:2026-01-20
实现时间:2026-01-20
作者:System
概述
实现项目管理服务的核心功能,包括 CRUD 操作、权限管理、成员管理、搜索筛选、分享功能等。
背景
项目(Project)是系统的核心实体,用户通过项目组织和管理分镜、视频等资源。需要实现完整的项目管理功能以支持业务需求。
目标
主要目标
- 实现项目的完整 CRUD 操作
- 实现三级权限管理(owner/editor/viewer)
- 支持协作项目的成员管理
- 实现全文搜索和多条件筛选
- 实现项目分享功能
- 为异步任务预留接口
非目标
- 异步任务队列实现(后续 RFC)
- 版本控制功能(后续 RFC)
- 企业功能(V2)
技术方案
架构设计
采用三层架构:
API Layer (projects.py)
↓
Service Layer (project_service.py)
↓
Repository Layer (project_repository.py)
↓
Model Layer (project.py)
数据模型
1. Project(项目表)
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(成员表)
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(分享表)
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(版本表,预留)
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. 权限管理
权限级别:
- Owner:完全控制权(删除、添加成员、创建分享)
- Editor:编辑权限(修改项目、移动项目)
- Viewer:只读权限(查看项目)
权限检查逻辑:
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. 分享功能
分享链接生成:
share_token = secrets.token_urlsafe(32)
share_url = f"/share/p/{share_token}"
特性:
- 密码保护(可选)
- 过期时间(可选)
- 权限控制(viewer/editor)
- 访问统计
4. 克隆功能
当前实现:同步版本
async def clone_project(source_project, new_name, owner_id, folder_id):
# 1. 复制项目基本信息
new_project = Project(...)
# 2. TODO: 复制关联资源(分镜、视频、附件)
# 需要等待相关模型实现
return new_project
限制:
- 大项目可能超时
- 暂不复制关联资源
TODO:
- 实现异步任务队列
- 复制关联资源
5. 导出功能
当前实现:接口框架
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 |
请求示例
创建项目
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
}
}
搜索项目
GET /api/v1/projects?search=广告&contentType=ad&sortBy=updated_at&sortOrder=desc&page=1&pageSize=20
创建分享
POST /api/v1/projects/{id}/shares
Content-Type: application/json
{
"password": "optional-password",
"permission": "viewer",
"expiresAt": "2026-02-01T00:00:00Z"
}
数据库设计
表结构
projects 表
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 个):
server/app/models/project.py- 数据模型server/app/schemas/project.py- Schema 定义server/app/repositories/project_repository.py- 数据访问层server/app/services/project_service.py- 业务逻辑层server/app/api/v1/projects.py- API 路由server/app/migrations/003_project_tables.py- 数据库迁移
修改文件(2 个):
server/app/api/v1/router.py- 添加路由注册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+ 项目)
- 分页性能
- 索引效率
风险和限制
已知限制
-
克隆功能:
- 同步执行,大项目可能超时
- 暂不复制关联资源
-
导出功能:
- 仅返回开发中状态
- 需要异步任务队列支持
-
全文搜索:
- 使用 ILIKE,性能一般
- 可升级为 similarity 函数
技术债务
- 权限继承逻辑需要完善
- 批量操作支持
- 项目统计信息
- 搜索性能优化
后续工作
短期(1-2 周)
- 实现异步任务队列(Celery/ARQ)
- 完善克隆功能(复制关联资源)
- 实现导出功能
中期(1-2 月)
- 实现版本控制功能
- 优化全文搜索性能
- 实现批量操作
长期(3+ 月)
- 企业功能支持(V2)
- 项目模板功能
- 项目分析和统计
参考资料
RFC 状态:已实现
实现时间:2026-01-20