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.
6.7 KiB
6.7 KiB
测试指南:剧本上传自动创建子项目
功能: 剧本上传时自动创建独立的子项目工作空间
实施日期: 2026-02-06
关联 RFC: RFC 141
测试前准备
1. 环境要求
# 确保服务运行
docker-compose ps
# 预期输出:
# server Running
# postgres Running
# redis Running
# celery Running
2. 获取测试数据
# 获取 Token
TOKEN="your-jwt-token"
# 获取父项目 ID(必须有 editor 权限)
PARENT_PROJECT_ID="019c3456-7890-7abc-def0-000000000000"
测试场景
场景 1:自动创建子项目(默认行为)
测试步骤
# 上传 PDF 文件(异步解析)
curl -X POST http://localhost:6170/api/v1/screenplays/file \
-H "Authorization: Bearer $TOKEN" \
-F "project_id=$PARENT_PROJECT_ID" \
-F "name=测试剧本-自动子项目" \
-F "file=@test-screenplay.pdf"
预期响应
{
"code": 201,
"message": "文件上传成功,正在解析...",
"data": {
"screenplayId": "019c3456-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"name": "测试剧本-自动子项目",
"type": "file",
"projectId": "019c3456-yyyy-yyyy-yyyy-yyyyyyyyyyyy", // ← 子项目 ID
"fileUrl": "screenplays/source/2026/02/06/xxx.pdf",
"parsingStatus": "parsing",
"taskId": "celery-task-xxx",
"subproject": { // ← 子项目信息
"projectId": "019c3456-yyyy-yyyy-yyyy-yyyyyyyyyyyy",
"name": "测试剧本-自动子项目",
"parentProjectId": "019c3456-7890-7abc-def0-000000000000",
"screenplayId": "019c3456-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"type": 1,
"description": "基于剧本《测试剧本-自动子项目》的制作项目",
"folderId": "...",
"createdAt": "2026-02-06T..."
}
}
}
验证数据库
-- 1. 验证子项目创建
SELECT
id,
name,
parent_project_id,
screenplay_id,
description
FROM projects
WHERE name = '测试剧本-自动子项目';
-- 预期结果:
-- parent_project_id = <父项目ID>
-- screenplay_id = <剧本ID>
-- 2. 验证剧本关联
SELECT
screenplay_id,
name,
project_id
FROM screenplays
WHERE name = '测试剧本-自动子项目';
-- 预期结果:
-- project_id = <子项目ID>(而非父项目ID)
场景 2:禁用自动创建子项目
测试步骤
# 上传 TXT 文件(同步解析),禁用自动创建
curl -X POST http://localhost:6170/api/v1/screenplays/file \
-H "Authorization: Bearer $TOKEN" \
-F "project_id=$PARENT_PROJECT_ID" \
-F "name=测试剧本-无子项目" \
-F "file=@test-screenplay.txt" \
-F "auto_create_subproject=false"
预期响应
{
"code": 201,
"message": "文件上传成功",
"data": {
"screenplayId": "019c3456-zzzz-zzzz-zzzz-zzzzzzzzzzzz",
"name": "测试剧本-无子项目",
"type": "file",
"projectId": "019c3456-7890-7abc-def0-000000000000", // ← 父项目 ID
"parsingStatus": "completed",
"content": "...",
"subproject": null // ← 无子项目
}
}
验证数据库
-- 验证剧本直接归属父项目
SELECT
screenplay_id,
name,
project_id
FROM screenplays
WHERE name = '测试剧本-无子项目';
-- 预期结果:
-- project_id = <父项目ID>(而非子项目ID)
-- 验证没有创建子项目
SELECT COUNT(*) FROM projects
WHERE name = '测试剧本-无子项目';
-- 预期结果:0
场景 3:协作项目权限继承
测试步骤
# 1. 创建协作项目(type=2)
COLLAB_PROJECT_ID="..."
# 2. 添加成员到协作项目
# (通过项目管理 API)
# 3. 上传剧本,自动创建子项目
curl -X POST http://localhost:6170/api/v1/screenplays/file \
-H "Authorization: Bearer $TOKEN" \
-F "project_id=$COLLAB_PROJECT_ID" \
-F "name=协作剧本" \
-F "file=@test.pdf"
验证权限继承
-- 1. 获取父项目成员
SELECT user_id, role FROM project_members
WHERE project_id = '<协作项目ID>';
-- 2. 验证子项目成员
SELECT user_id, role FROM project_members
WHERE project_id = '<子项目ID>';
-- 预期:子项目成员列表与父项目一致
场景 4:事务回滚测试
测试步骤
# 故意传入无效的父项目 ID
curl -X POST http://localhost:6170/api/v1/screenplays/file \
-H "Authorization: Bearer $TOKEN" \
-F "project_id=invalid-uuid" \
-F "name=测试事务" \
-F "file=@test.pdf"
预期行为
- ❌ 返回错误响应(400 或 404)
- ✅ 数据库中没有创建任何记录(剧本、子项目、附件)
- ✅ MinIO 中没有上传文件
性能测试
响应时间测试
# 测试 10 次上传,计算平均响应时间
for i in {1..10}; do
time curl -X POST http://localhost:6170/api/v1/screenplays/file \
-H "Authorization: Bearer $TOKEN" \
-F "project_id=$PARENT_PROJECT_ID" \
-F "name=性能测试-$i" \
-F "file=@test.pdf" \
> /dev/null 2>&1
done
预期性能
- 同步解析(TXT): < 300ms
- 异步解析(PDF): < 500ms
- 增量开销: +50-100ms(相比不创建子项目)
常见问题排查
问题 1:响应中 subproject 为 null
可能原因:
- 设置了
auto_create_subproject=false - Service 层抛出异常但被捕获
排查步骤:
# 检查服务器日志
docker-compose logs server | grep "剧本创建"
# 预期日志:
# "子项目创建成功 | 子项目ID: ..."
# "剧本创建成功 | 剧本ID: ... | 子项目ID: ..."
问题 2:数据库中子项目的 screenplay_id 为 NULL
可能原因:
- 更新子项目的步骤失败
排查步骤:
-- 检查子项目状态
SELECT id, name, screenplay_id, parent_project_id
FROM projects
WHERE parent_project_id IS NOT NULL
ORDER BY created_at DESC
LIMIT 10;
问题 3:权限错误
错误信息: "没有权限在此项目中创建子项目"
解决方案:
- 确保用户在父项目中拥有
editor权限 - 检查
project_members表
回滚方案
如需临时禁用自动创建子项目:
方法 1:修改 API 默认值
# server/app/api/v1/screenplays.py
auto_create_subproject: bool = Form(False) # ← 改为 False
方法 2:前端传参
// 在所有上传请求中添加
formData.append('auto_create_subproject', 'false');