From ceb01592904836cefe51c34ac91c761a4b3234c2 Mon Sep 17 00:00:00 2001 From: zheng020 Date: Wed, 8 Apr 2026 19:01:45 +0800 Subject: [PATCH] docs: update task management design based on review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 修正内容: - InitUserTasks 粒度:改为创建 onboarding_status + 每日任务进度 - ReportTaskEvent:从内部 RPC 改为移动端 API POST /api/tasks/report-event - InitUserTasksRequest 增加 star_id 字段 - 每日任务流程:补充用户注册 → InitUserTasks 步骤 - 展示收益流程:补充 failed 记录对用户不可见的说明 - 展示收益响应:补充 star_id 字段 - activity-admin 收益记录页面:支持查看 failed 记录和手动补发 Co-Authored-By: Claude Opus 4.6 --- ...026-04-08-task-management-system-design.md | 66 +++++++++++-------- 1 file changed, 39 insertions(+), 27 deletions(-) diff --git a/docs/superpowers/specs/2026-04-08-task-management-system-design.md b/docs/superpowers/specs/2026-04-08-task-management-system-design.md index 36a94da..fba082d 100644 --- a/docs/superpowers/specs/2026-04-08-task-management-system-design.md +++ b/docs/superpowers/specs/2026-04-08-task-management-system-design.md @@ -78,7 +78,7 @@ | 展示收益发放 | 统一到次日 05:00 自动发放,支持手动领取 | | 展示收益计算 | 由调用方(galleryService)计算后传入 | | 每日任务 scope | 每个 (user_id, star_id) 各自独立 | -| InitUserTasks | 只打新用户标记,不预创建任务进度 | +| InitUserTasks | 创建 user_onboarding_status + 该 star_id 下的每日任务进度;新增粉丝身份时创建对应进度 | | 重置日志 | 记录到 task_reset_log 表 | | 旧字段处理 | is_first_login_bonus_claimed、has_friend_display_bonus 标记废弃 | | 奖励发放失败 | 记录日志 + 本地重试 N 次(可配置),仍失败标记 failed | @@ -311,15 +311,18 @@ CREATE TABLE task_reset_log ( | 方法 | 路径 | 请求 | 说明 | |------|------|------|------| | GET | `/api/tasks/daily` | `star_id` | 获取每日任务列表及进度 | +| POST | `/api/tasks/report-event` | `{ event_type, star_id }` | 上报任务事件(如浏览展品、铸造等) | | POST | `/api/tasks/daily/claim` | `{ task_key, star_id }` | 领取单个任务奖励 | | POST | `/api/tasks/daily/claim-all` | `star_id` | 一键领取所有已完成任务奖励 | **GET /api/tasks/daily 响应:** ```json { + "star_id": 1, "tasks": [ { "task_key": "daily_login", + "star_id": 1, "name": "每日首次登录", "description": "每日首次登录 App", "crystal_reward": 20, @@ -331,6 +334,24 @@ CREATE TABLE task_reset_log ( } ``` +**POST /api/tasks/report-event 请求:** +```json +{ + "event_type": "daily_browse_asset", + "star_id": 1 +} +``` + +**POST /api/tasks/report-event 响应:** +```json +{ + "success": true, + "task_key": "daily_browse_asset", + "task_completed": true, + "message": "任务完成" +} +``` + #### 引导任务 | 方法 | 路径 | 请求 | 说明 | @@ -390,6 +411,7 @@ CREATE TABLE task_reset_log ( "items": [ { "id": 123, + "star_id": 1, "exhibition_id": 456, "asset_id": 789, "slot_id": 1, @@ -415,12 +437,9 @@ CREATE TABLE task_reset_log ( ```protobuf service TaskInternalService { - // 用户注册时调用,只打新用户标记 + // 用户注册时调用,创建 onboarding_status + 该 star_id 下的每日任务进度 rpc InitUserTasks(InitUserTasksRequest) returns (InitUserTasksResponse); - // 任务事件上报 - rpc ReportTaskEvent(ReportTaskEventRequest) returns (ReportTaskEventResponse); - // 展品到期完成(galleryService 调用) rpc OnExhibitionCompleted(OnExhibitionCompletedRequest) returns (OnExhibitionCompletedResponse); } @@ -431,6 +450,7 @@ service TaskInternalService { ```protobuf message InitUserTasksRequest { int64 user_id = 1; + int64 star_id = 2; // 注册时选择的第一个 star_id } message InitUserTasksResponse { @@ -438,19 +458,6 @@ message InitUserTasksResponse { bool success = 2; } -message ReportTaskEventRequest { - int64 user_id = 1; - int64 star_id = 2; - string event_type = 3; - int64 timestamp = 4; -} - -message ReportTaskEventResponse { - topfans.common.BaseResponse base = 1; - bool task_completed = 2; - string task_key = 3; -} - message OnExhibitionCompletedRequest { int64 exhibition_id = 1; int64 asset_id = 2; @@ -497,13 +504,16 @@ rpc AddExperience(AddExperienceRequest) returns (AddExperienceResponse); ### 5.1 每日任务流程 ``` -1. 用户登录 → 前端调用 GET /api/tasks/daily?star_id=xxx -2. 后端返回该用户的每日任务列表(含 status) -3. 用户完成行为(如浏览展品)→ 前端调用 ReportTaskEvent -4. 后端自动标记任务完成(status=completed) -5. 用户点击"领取" → POST /api/tasks/daily/claim -6. 后端验证任务已完成 → 调用 userService.UpdateCrystalBalance → 调用 AddExperience → 更新状态为 claimed -7. 每日 05:00 Asia/Shanghai: +1. 用户注册 → userService 调用 taskService.InitUserTasks + - 创建 user_onboarding_status(新用户标记) + - 创建该 star_id 下的每日任务进度记录(status=pending) +2. 用户登录 → 前端调用 GET /api/tasks/daily?star_id=xxx +3. 后端返回该用户的每日任务列表(含 status) +4. 用户完成行为(如浏览展品)→ 前端调用 POST /api/tasks/report-event +5. 后端自动标记任务完成(status=completed) +6. 用户点击"领取" → POST /api/tasks/daily/claim +7. 后端验证任务已完成 → 调用 userService.UpdateCrystalBalance → 调用 AddExperience → 更新状态为 claimed +8. 每日 05:00 Asia/Shanghai: a. Advisory Lock 获取锁(pg_advisory_lock(YYYYMMDD)) b. 查询 task_reset_log,如今天已有记录则跳过 c. 所有非 pending 状态的记录恢复为 pending @@ -540,8 +550,10 @@ rpc AddExperience(AddExperienceRequest) returns (AddExperienceResponse); b. 分批处理(每批 N 条,可配置) c. 调用 userService.UpdateCrystalBalance 发放水晶 d. 成功则更新 status=claimed,失败则重试 N 次 - e. 仍失败则标记 status=failed + e. 仍失败则标记 status=failed(对用户不可见,运营可查) 5. 用户打开移动端 → GET /api/tasks/exhibition-revenue + - 前端只显示 claimable 和 claimed 状态的记录 + - failed 记录对用户不可见 6. 用户点击领取 → POST /api/tasks/exhibition-revenue/claim 7. 后端调用 userService.UpdateCrystalBalance → 更新状态 ``` @@ -626,7 +638,7 @@ func (w *Worker) autoClaimExhibitionRevenue() { | 引导任务进度 | `/tasks/onboarding-progress` | 查询各用户的引导任务完成情况 | | 任务统计 | `/tasks/stats` | 任务完成率/领取率统计图表,支持 star_id、时间范围筛选 | | 手动重置 | `/tasks/reset` | 手动触发每日任务重置 | -| 收益记录 | `/tasks/revenue` | 查看展示收益记录 | +| 收益记录 | `/tasks/revenue` | 查看展示收益记录(含 failed),支持手动补发 | **统计页面指标:** - 每日任务:完成人数、领取人数、完成率、领取率