feat: 任务模型物理合并,发布+回收并为单任务双阶段

- tasks 新增 recovery_enabled/recovery_due_at/recovery_instructions/recovery_example_images,回收挂自己名下(先发布后交截图),不再置 complete
- 存量 screenshot_collect 迁移并入父任务后删除(mysql/0020 含 DELETE,生产执行前务必备份)
- 新 action task_enable_recovery:ghost 面板一键开通回收,截止默认=发布截止
- 企微催办双阶段(待发布/截图待提交);超期自动释放仅发布阶段
- admin 删 groupTaskMasters 聚合改单卡双面板;portal 详情页回收截图区块+批次回收进度
- 测试 309 全绿 + Playwright E2E 20/20
This commit is contained in:
ABAPPLO
2026-09-24 15:52:45 +08:00
parent ab78b187c0
commit e2a93e22cf
29 changed files with 2219 additions and 2195 deletions

View File

@@ -78,7 +78,7 @@ test("project-owner management actions gate on project ownership", () => {
"project_delete",
"project_ensure_main_chat",
"create_task",
"create_screenshot_task",
"task_enable_recovery",
]) {
const body = section(actionRoute, action);
assert.match(
@@ -319,7 +319,7 @@ test("project detail exposes inline main-chat member management", () => {
assert.match(globalsCss, /\.project-member-remove/);
});
test("every project_save payload carries parentProjectId(改总群成员不得清空层级)", () => {
test("no project_save payload carries parentProjectId(项目层级已移除)", () => {
const adminApp = readFileSync(
new URL("../app/admin-app.tsx", import.meta.url),
"utf8",
@@ -330,10 +330,9 @@ test("every project_save payload carries parentProjectId(改总群成员不得
assert.ok(starts.length >= 2, "至少应有两处 project_save 调用(编辑器/总群成员)");
for (const start of starts) {
const payload = adminApp.slice(start, start + 600);
assert.match(
payload,
/parentProjectId/,
"project_save 载荷缺 parentProjectId,会把 parent_id 重置为空",
assert.ok(
!/parentProjectId/.test(payload),
"project_save 载荷不应再带 parentProjectId(项目层级已移除)",
);
}
});