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

@@ -871,21 +871,12 @@ export async function getDashboardData(ownerUserid?: string) {
(SELECT c.body FROM contents c WHERE c.task_id = t.id ORDER BY c.source_row LIMIT 1) AS instructions,
(SELECT COUNT(*) FROM distributions d WHERE d.task_id = t.id) AS dist_total,
(SELECT COUNT(*) FROM distributions d WHERE d.task_id = t.id AND d.status = 'complete') AS dist_complete,
(SELECT COUNT(*) FROM distributions d WHERE d.task_id = t.id AND d.result_submitted_at IS NOT NULL) AS dist_submitted,
(SELECT rt.name FROM tasks rt WHERE rt.id = t.related_task_id) AS related_task_name,
(SELECT COUNT(*) FROM distributions d WHERE d.task_id = t.related_task_id) AS related_dist_total,
(SELECT COUNT(*) FROM distributions d WHERE d.task_id = t.related_task_id AND d.status = 'complete') AS related_dist_complete,
(SELECT rt2.id FROM tasks rt2 WHERE rt2.related_task_id = t.id LIMIT 1) AS reverse_related_task_id,
(SELECT rt2.name FROM tasks rt2 WHERE rt2.related_task_id = t.id LIMIT 1) AS reverse_related_task_name,
(SELECT COUNT(*) FROM distributions d WHERE d.task_id = (SELECT rt2.id FROM tasks rt2 WHERE rt2.related_task_id = t.id LIMIT 1)) AS reverse_dist_total,
(SELECT COUNT(*) FROM distributions d WHERE d.task_id = (SELECT rt2.id FROM tasks rt2 WHERE rt2.related_task_id = t.id LIMIT 1) AND d.result_submitted_at IS NOT NULL) AS reverse_dist_submitted
(SELECT COUNT(*) FROM distributions d WHERE d.task_id = t.id AND d.result_submitted_at IS NOT NULL) AS dist_submitted
FROM tasks t
LEFT JOIN projects pj ON pj.id = t.project_id`;
const distributionsBase = `SELECT
d.*,
c.title AS content_title,
c.related_content_id AS related_content_id,
rc.title AS related_content_title,
p.name AS partner_name,
cl.claimant_name AS claimant_name,
a.nickname AS account_nickname,
@@ -898,7 +889,6 @@ export async function getDashboardData(ownerUserid?: string) {
t.due_at AS due_at
FROM distributions d
JOIN contents c ON c.id = d.content_id
LEFT JOIN contents rc ON rc.id = c.related_content_id
JOIN partners p ON p.id = d.partner_id
LEFT JOIN claims cl ON cl.id = d.claim_id
JOIN tasks t ON t.id = d.task_id