docs: update task management design based on review
修正内容: - 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 <noreply@anthropic.com>
This commit is contained in:
parent
770ca0e512
commit
ceb0159290
@ -78,7 +78,7 @@
|
|||||||
| 展示收益发放 | 统一到次日 05:00 自动发放,支持手动领取 |
|
| 展示收益发放 | 统一到次日 05:00 自动发放,支持手动领取 |
|
||||||
| 展示收益计算 | 由调用方(galleryService)计算后传入 |
|
| 展示收益计算 | 由调用方(galleryService)计算后传入 |
|
||||||
| 每日任务 scope | 每个 (user_id, star_id) 各自独立 |
|
| 每日任务 scope | 每个 (user_id, star_id) 各自独立 |
|
||||||
| InitUserTasks | 只打新用户标记,不预创建任务进度 |
|
| InitUserTasks | 创建 user_onboarding_status + 该 star_id 下的每日任务进度;新增粉丝身份时创建对应进度 |
|
||||||
| 重置日志 | 记录到 task_reset_log 表 |
|
| 重置日志 | 记录到 task_reset_log 表 |
|
||||||
| 旧字段处理 | is_first_login_bonus_claimed、has_friend_display_bonus 标记废弃 |
|
| 旧字段处理 | is_first_login_bonus_claimed、has_friend_display_bonus 标记废弃 |
|
||||||
| 奖励发放失败 | 记录日志 + 本地重试 N 次(可配置),仍失败标记 failed |
|
| 奖励发放失败 | 记录日志 + 本地重试 N 次(可配置),仍失败标记 failed |
|
||||||
@ -311,15 +311,18 @@ CREATE TABLE task_reset_log (
|
|||||||
| 方法 | 路径 | 请求 | 说明 |
|
| 方法 | 路径 | 请求 | 说明 |
|
||||||
|------|------|------|------|
|
|------|------|------|------|
|
||||||
| GET | `/api/tasks/daily` | `star_id` | 获取每日任务列表及进度 |
|
| 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` | `{ task_key, star_id }` | 领取单个任务奖励 |
|
||||||
| POST | `/api/tasks/daily/claim-all` | `star_id` | 一键领取所有已完成任务奖励 |
|
| POST | `/api/tasks/daily/claim-all` | `star_id` | 一键领取所有已完成任务奖励 |
|
||||||
|
|
||||||
**GET /api/tasks/daily 响应:**
|
**GET /api/tasks/daily 响应:**
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
|
"star_id": 1,
|
||||||
"tasks": [
|
"tasks": [
|
||||||
{
|
{
|
||||||
"task_key": "daily_login",
|
"task_key": "daily_login",
|
||||||
|
"star_id": 1,
|
||||||
"name": "每日首次登录",
|
"name": "每日首次登录",
|
||||||
"description": "每日首次登录 App",
|
"description": "每日首次登录 App",
|
||||||
"crystal_reward": 20,
|
"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": [
|
"items": [
|
||||||
{
|
{
|
||||||
"id": 123,
|
"id": 123,
|
||||||
|
"star_id": 1,
|
||||||
"exhibition_id": 456,
|
"exhibition_id": 456,
|
||||||
"asset_id": 789,
|
"asset_id": 789,
|
||||||
"slot_id": 1,
|
"slot_id": 1,
|
||||||
@ -415,12 +437,9 @@ CREATE TABLE task_reset_log (
|
|||||||
|
|
||||||
```protobuf
|
```protobuf
|
||||||
service TaskInternalService {
|
service TaskInternalService {
|
||||||
// 用户注册时调用,只打新用户标记
|
// 用户注册时调用,创建 onboarding_status + 该 star_id 下的每日任务进度
|
||||||
rpc InitUserTasks(InitUserTasksRequest) returns (InitUserTasksResponse);
|
rpc InitUserTasks(InitUserTasksRequest) returns (InitUserTasksResponse);
|
||||||
|
|
||||||
// 任务事件上报
|
|
||||||
rpc ReportTaskEvent(ReportTaskEventRequest) returns (ReportTaskEventResponse);
|
|
||||||
|
|
||||||
// 展品到期完成(galleryService 调用)
|
// 展品到期完成(galleryService 调用)
|
||||||
rpc OnExhibitionCompleted(OnExhibitionCompletedRequest) returns (OnExhibitionCompletedResponse);
|
rpc OnExhibitionCompleted(OnExhibitionCompletedRequest) returns (OnExhibitionCompletedResponse);
|
||||||
}
|
}
|
||||||
@ -431,6 +450,7 @@ service TaskInternalService {
|
|||||||
```protobuf
|
```protobuf
|
||||||
message InitUserTasksRequest {
|
message InitUserTasksRequest {
|
||||||
int64 user_id = 1;
|
int64 user_id = 1;
|
||||||
|
int64 star_id = 2; // 注册时选择的第一个 star_id
|
||||||
}
|
}
|
||||||
|
|
||||||
message InitUserTasksResponse {
|
message InitUserTasksResponse {
|
||||||
@ -438,19 +458,6 @@ message InitUserTasksResponse {
|
|||||||
bool success = 2;
|
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 {
|
message OnExhibitionCompletedRequest {
|
||||||
int64 exhibition_id = 1;
|
int64 exhibition_id = 1;
|
||||||
int64 asset_id = 2;
|
int64 asset_id = 2;
|
||||||
@ -497,13 +504,16 @@ rpc AddExperience(AddExperienceRequest) returns (AddExperienceResponse);
|
|||||||
### 5.1 每日任务流程
|
### 5.1 每日任务流程
|
||||||
|
|
||||||
```
|
```
|
||||||
1. 用户登录 → 前端调用 GET /api/tasks/daily?star_id=xxx
|
1. 用户注册 → userService 调用 taskService.InitUserTasks
|
||||||
2. 后端返回该用户的每日任务列表(含 status)
|
- 创建 user_onboarding_status(新用户标记)
|
||||||
3. 用户完成行为(如浏览展品)→ 前端调用 ReportTaskEvent
|
- 创建该 star_id 下的每日任务进度记录(status=pending)
|
||||||
4. 后端自动标记任务完成(status=completed)
|
2. 用户登录 → 前端调用 GET /api/tasks/daily?star_id=xxx
|
||||||
5. 用户点击"领取" → POST /api/tasks/daily/claim
|
3. 后端返回该用户的每日任务列表(含 status)
|
||||||
6. 后端验证任务已完成 → 调用 userService.UpdateCrystalBalance → 调用 AddExperience → 更新状态为 claimed
|
4. 用户完成行为(如浏览展品)→ 前端调用 POST /api/tasks/report-event
|
||||||
7. 每日 05:00 Asia/Shanghai:
|
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))
|
a. Advisory Lock 获取锁(pg_advisory_lock(YYYYMMDD))
|
||||||
b. 查询 task_reset_log,如今天已有记录则跳过
|
b. 查询 task_reset_log,如今天已有记录则跳过
|
||||||
c. 所有非 pending 状态的记录恢复为 pending
|
c. 所有非 pending 状态的记录恢复为 pending
|
||||||
@ -540,8 +550,10 @@ rpc AddExperience(AddExperienceRequest) returns (AddExperienceResponse);
|
|||||||
b. 分批处理(每批 N 条,可配置)
|
b. 分批处理(每批 N 条,可配置)
|
||||||
c. 调用 userService.UpdateCrystalBalance 发放水晶
|
c. 调用 userService.UpdateCrystalBalance 发放水晶
|
||||||
d. 成功则更新 status=claimed,失败则重试 N 次
|
d. 成功则更新 status=claimed,失败则重试 N 次
|
||||||
e. 仍失败则标记 status=failed
|
e. 仍失败则标记 status=failed(对用户不可见,运营可查)
|
||||||
5. 用户打开移动端 → GET /api/tasks/exhibition-revenue
|
5. 用户打开移动端 → GET /api/tasks/exhibition-revenue
|
||||||
|
- 前端只显示 claimable 和 claimed 状态的记录
|
||||||
|
- failed 记录对用户不可见
|
||||||
6. 用户点击领取 → POST /api/tasks/exhibition-revenue/claim
|
6. 用户点击领取 → POST /api/tasks/exhibition-revenue/claim
|
||||||
7. 后端调用 userService.UpdateCrystalBalance → 更新状态
|
7. 后端调用 userService.UpdateCrystalBalance → 更新状态
|
||||||
```
|
```
|
||||||
@ -626,7 +638,7 @@ func (w *Worker) autoClaimExhibitionRevenue() {
|
|||||||
| 引导任务进度 | `/tasks/onboarding-progress` | 查询各用户的引导任务完成情况 |
|
| 引导任务进度 | `/tasks/onboarding-progress` | 查询各用户的引导任务完成情况 |
|
||||||
| 任务统计 | `/tasks/stats` | 任务完成率/领取率统计图表,支持 star_id、时间范围筛选 |
|
| 任务统计 | `/tasks/stats` | 任务完成率/领取率统计图表,支持 star_id、时间范围筛选 |
|
||||||
| 手动重置 | `/tasks/reset` | 手动触发每日任务重置 |
|
| 手动重置 | `/tasks/reset` | 手动触发每日任务重置 |
|
||||||
| 收益记录 | `/tasks/revenue` | 查看展示收益记录 |
|
| 收益记录 | `/tasks/revenue` | 查看展示收益记录(含 failed),支持手动补发 |
|
||||||
|
|
||||||
**统计页面指标:**
|
**统计页面指标:**
|
||||||
- 每日任务:完成人数、领取人数、完成率、领取率
|
- 每日任务:完成人数、领取人数、完成率、领取率
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user