topfans/docs/superpowers/specs/2026-04-08-task-management-system-design.md
zheng020 ceb0159290 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>
2026-04-08 20:49:53 +08:00

745 lines
28 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 任务管理系统设计文档
> **创建日期:** 2026-04-08
> **项目:** TopFans 任务管理系统
> **服务:** activity-admin (Python FastAPI) + taskService (Go Dubbo-go) + 共享 PostgreSQL
---
## 一、整体架构
```
┌─────────────────────────────────────────────────────────────────┐
│ 移动端 │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────────────┐ │
│ │ 每日任务页面 │ │ 引导任务页面 │ │ 展示收益/奖励领取 │ │
│ └──────┬───────┘ └──────┬───────┘ └──────────┬───────────┘ │
└─────────┼─────────────────┼─────────────────────┼───────────────┘
│ │ │
│ Triple/HTTP │ │
▼ ▼ ▼
┌─────────────────────────────────────────────────────────────────┐
│ taskService (新服务,端口 20005) │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ Mobile API Handler (HTTP/Triple) │ │
│ │ /api/tasks/daily/* /api/tasks/guide/* /api/tasks/* │ │
│ └──────────────────────────────────────────────────────────┘ │
│ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │
│ │ DailyTaskService│ │OnboardingService│ │ RevenueService │ │
│ └────────┬────────┘ └────────┬────────┘ └────────┬────────┘ │
│ │ │ │ │
│ ┌────────▼─────────────────────▼─────────────────────▼────────┐ │
│ │ Repository Layer (GORM) │ │
│ └───────────────────────────────────────────────────────────┘ │
│ │ │
│ ┌─────────────▼─────────────┐ │
│ │ DailyResetWorker │ │
│ │ + RevenueAutoClaimWorker │ │
│ │ (PostgreSQL Advisory │ │
│ │ Lock05:00 Asia/Shanghai)│ │
│ └───────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
│ ▲ ▲
│ Triple RPC │ │
▼ │ │
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ galleryService │ │ userService │ │ activity-admin │
│ (OnExhibition │ │ (UpdateCrystal │ │ (任务定义管理) │
│ Completed RPC)│ │ Balance + │ │ 直接操作DB │
│ │ │ AddExperience)│ │ │
└─────────────────┘ └─────────────────┘ └─────────────────┘
│ ▲ ▲
└────────────────────▼────────────────────┘
PostgreSQL
```
---
## 二、设计决策汇总
### 2.1 服务职责划分
| 服务 | 职责 |
|------|------|
| activity-admin (Python) | 任务定义管理、进度查询、统计、手动重置 |
| taskService (Go) | 移动端 API、内部 RPC、奖励发放、定时任务 |
| PostgreSQL | 共用数据库 |
### 2.2 核心设计决策
| 决策项 | 选择 |
|--------|------|
| 移动端 API 提供方 | 新建独立 taskService 微服务 |
| 引导完成上报 | 前端每步完成立即调用 `/api/tasks/guide/complete` |
| 每日任务重置 | PostgreSQL Advisory Lock每天 05:00 Asia/Shanghai 执行 |
| 引导阶段推进 | 前端主动调用 `/api/tasks/onboarding/advance-stage` |
| 每日任务奖励 | 手动领取(单个或一键领取) |
| 引导任务奖励 | 阶段切换时统一发放 |
| 展示收益发放 | 统一到次日 05:00 自动发放,支持手动领取 |
| 展示收益计算 | 由调用方galleryService计算后传入 |
| 每日任务 scope | 每个 (user_id, star_id) 各自独立 |
| InitUserTasks | 创建 user_onboarding_status + 该 star_id 下的每日任务进度;新增粉丝身份时创建对应进度 |
| 重置日志 | 记录到 task_reset_log 表 |
| 旧字段处理 | is_first_login_bonus_claimed、has_friend_display_bonus 标记废弃 |
| 奖励发放失败 | 记录日志 + 本地重试 N 次(可配置),仍失败标记 failed |
| 重置时区判断 | 按自然天,每天 05:00 执行一次 |
| 重置范围 | 全局所有用户所有 star_id |
| 引导上报 key | 动态配置,数据库存什么 key前端就上报什么 key |
| 阶段切换检查 | 后端检查当前阶段所有任务是否已完成,未完成拒绝切换 |
| 引导任务 | 不允许重复完成,不重置 |
| claimed 状态 | 每日重置时也重置回 pending |
| 收益自动发放 | 分批发放,每条记录结果保存,失败重试 N 次(可配置) |
| 统计页面 | 多指标完成率、领取率等、多维度star_id、时间范围 |
| Worker 设计 | 共用一个 Worker05:00 先重置再发收益 |
| 日志监控 | 接入现有日志和监控体系 |
| 健康检查 | 不实现,复用 Dubbo-go 框架自带能力 |
| 错误码 | 复用现有 BaseResponse.code 体系 |
| 分页规范 | page + page_size + total |
| 引导状态返回 | POST `/api/tasks/guide/complete` 返回当前引导完整状态 |
| 锁 key 设计 | pg_advisory_lock(YYYYMMDD) |
| taskService 端口 | 20005 |
| taskService 调用 userService | 直接调用UpdateCrystalBalance + AddExperience |
| activity-admin | 直接操作数据库,不通过 taskService API |
---
## 三、数据库设计
### 3.1 ER 图
```
┌─────────────────────────┐ ┌─────────────────────────────┐
│ task_definitions │ │ onboarding_stage_config │
├─────────────────────────┤ ├─────────────────────────────┤
│ id (PK) │ │ id (PK) │
│ star_id │ │ stage │
│ task_key │────▶│ required_task_keys (TEXT[]) │
│ task_type │ │ crystal_reward │
│ name │ │ exp_reward │
│ description │ │ ... │
│ crystal_reward │ └─────────────────────────────┘
│ exp_reward │ ▲
│ ... │ │
└─────────────────────────┘ │
│ │
│ 1:N 1:N │
▼ │
┌─────────────────────────┐ ┌─────────────────────────────┐
│ user_daily_task_progress│ │ user_onboarding_progress │
├─────────────────────────┤ ├─────────────────────────────┤
│ id (PK) │ │ id (PK) │
│ user_id │ │ user_id │
│ star_id │ │ task_key ───────────────────┘
│ task_key │◀────│
│ status │ │ ┌─────────────────────────┐
│ completed_at │ │ │user_onboarding_status │
│ claimed_at │ │ ├─────────────────────────┤
│ ... │ │ │ user_id (PK) │
└─────────────────────────┘ │ │ current_stage │
│ │ status │
│ │ is_first_login_bonus_ │
│ │ claimed (废弃) │
│ │ has_friend_display_bonus│
│ │ (废弃) │
│ └─────────────────────────┘
┌─────────────────────────────┐ │
│ exhibition_revenue_records │ │
├─────────────────────────────┤ │
│ id (PK) │ │
│ user_id │ │
│ star_id │ │
│ exhibition_id │ │
│ asset_id │ │
│ slot_id │ │
│ slot_owner_uid │ │
│ slot_type ('own'/'friend') │ │
│ crystal_amount │ │
│ cycle_start_time │ │
│ cycle_end_time │ │
│ status ('claimable'/'...') │ │
│ claimed_at │ │
│ created_at │ │
└─────────────────────────────┘
┌─────────────────────────────┐
│ task_reset_log │
├─────────────────────────────┤
│ id (PK) │
│ reset_type │
│ last_reset_at │
│ created_at │
└─────────────────────────────┘
```
### 3.2 表结构
#### task_definitions任务定义表
```sql
CREATE TABLE task_definitions (
id BIGSERIAL PRIMARY KEY,
star_id BIGINT, -- NULL=全局默认
task_key VARCHAR(50) NOT NULL,
task_type VARCHAR(20) NOT NULL, -- 'daily' | 'onboarding'
name VARCHAR(100) NOT NULL,
description TEXT,
crystal_reward BIGINT DEFAULT 0,
exp_reward BIGINT DEFAULT 0,
sort_order INT DEFAULT 0,
is_active BOOLEAN DEFAULT true,
created_at BIGINT,
updated_at BIGINT
);
CREATE UNIQUE INDEX ix_task_def_star_key ON task_definitions(star_id, task_key);
```
#### user_daily_task_progress每日任务进度表
```sql
CREATE TABLE user_daily_task_progress (
id BIGSERIAL PRIMARY KEY,
user_id BIGINT NOT NULL,
star_id BIGINT NOT NULL,
task_key VARCHAR(50) NOT NULL,
status VARCHAR(20) DEFAULT 'pending', -- pending/completed/claimed
completed_at BIGINT,
claimed_at BIGINT,
created_at BIGINT,
updated_at BIGINT
);
CREATE UNIQUE INDEX ix_daily_progress_user_star_key
ON user_daily_task_progress(user_id, star_id, task_key);
```
#### user_onboarding_progress引导任务进度表
```sql
CREATE TABLE user_onboarding_progress (
id BIGSERIAL PRIMARY KEY,
user_id BIGINT NOT NULL,
task_key VARCHAR(50) NOT NULL,
status VARCHAR(20) DEFAULT 'pending',
completed_at BIGINT,
claimed_at BIGINT,
created_at BIGINT,
updated_at BIGINT
);
CREATE UNIQUE INDEX ix_onboard_progress_user_key
ON user_onboarding_progress(user_id, task_key);
```
#### user_onboarding_status引导流程状态表
```sql
CREATE TABLE user_onboarding_status (
user_id BIGINT PRIMARY KEY,
current_stage INT DEFAULT 0, -- 0=未开始1~N=阶段
status VARCHAR(20) DEFAULT 'pending',
-- 以下字段标记废弃,但仍保留
is_first_login_bonus_claimed BOOLEAN DEFAULT false,
has_friend_display_bonus BOOLEAN DEFAULT false,
completed_at BIGINT,
claimed_at BIGINT,
created_at BIGINT,
updated_at BIGINT
);
```
#### onboarding_stage_config引导阶段配置表
```sql
CREATE TABLE onboarding_stage_config (
id BIGSERIAL PRIMARY KEY,
stage INT NOT NULL,
name VARCHAR(100) NOT NULL,
description TEXT,
required_task_keys TEXT[], -- PostgreSQL 数组类型
crystal_reward BIGINT DEFAULT 0,
exp_reward BIGINT DEFAULT 0,
sort_order INT DEFAULT 0,
is_active BOOLEAN DEFAULT true,
created_at BIGINT,
updated_at BIGINT
);
```
#### exhibition_revenue_records展示收益记录表
```sql
CREATE TABLE exhibition_revenue_records (
id BIGSERIAL PRIMARY KEY,
user_id BIGINT NOT NULL,
star_id BIGINT NOT NULL,
exhibition_id BIGINT NOT NULL,
asset_id BIGINT NOT NULL,
slot_id BIGINT NOT NULL,
slot_owner_uid BIGINT NOT NULL,
slot_type VARCHAR(20) NOT NULL, -- 'own' | 'friend'
crystal_amount BIGINT NOT NULL,
cycle_start_time BIGINT NOT NULL,
cycle_end_time BIGINT NOT NULL,
status VARCHAR(20) DEFAULT 'claimable',
claimed_at BIGINT,
created_at BIGINT
);
CREATE INDEX ix_revenue_user_star_status
ON exhibition_revenue_records(user_id, star_id, status);
CREATE INDEX ix_revenue_star_status
ON exhibition_revenue_records(star_id, status);
```
#### task_reset_log重置日志表
```sql
CREATE TABLE task_reset_log (
id BIGSERIAL PRIMARY KEY,
reset_type VARCHAR(20) NOT NULL, -- 'daily'
last_reset_at BIGINT NOT NULL,
created_at BIGINT
);
```
---
## 四、API 设计
### 4.1 移动端 APItaskService HTTP/Triple
#### 每日任务
| 方法 | 路径 | 请求 | 说明 |
|------|------|------|------|
| 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,
"exp_reward": 20,
"status": "pending",
"can_claim": false
}
]
}
```
**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": "任务完成"
}
```
#### 引导任务
| 方法 | 路径 | 请求 | 说明 |
|------|------|------|------|
| POST | `/api/tasks/guide/complete` | `{ task_key }` | 上报引导步骤完成 |
| GET | `/api/tasks/onboarding/status` | - | 获取引导状态 |
| POST | `/api/tasks/onboarding/advance-stage` | `{ target_stage }` | 切换阶段 |
| POST | `/api/tasks/onboarding/claim-reward` | `{ stage }` | 领取当前阶段奖励 |
**POST /api/tasks/guide/complete 响应:**
```json
{
"user_id": 123,
"current_stage": 1,
"status": "in_progress",
"stages": [
{
"stage": 1,
"name": "入门引导",
"required_task_keys": ["square_home", "profile_edit"],
"crystal_reward": 0,
"exp_reward": 0
}
]
}
```
**GET /api/tasks/onboarding/status 响应:**
```json
{
"user_id": 123,
"current_stage": 1,
"status": "in_progress",
"stages": [
{
"stage": 1,
"name": "入门引导",
"required_task_keys": ["square_home", "profile_edit"],
"crystal_reward": 0,
"exp_reward": 0
}
]
}
```
#### 展示收益
| 方法 | 路径 | 请求 | 说明 |
|------|------|------|------|
| GET | `/api/tasks/exhibition-revenue` | `star_id`, `status`, `page`, `page_size` | 获取收益记录列表 |
| POST | `/api/tasks/exhibition-revenue/claim` | `{ revenue_id, star_id }` | 领取单个收益 |
| POST | `/api/tasks/exhibition-revenue/claim-all` | `star_id` | 一键领取所有可领取收益 |
**GET /api/tasks/exhibition-revenue 响应:**
```json
{
"items": [
{
"id": 123,
"star_id": 1,
"exhibition_id": 456,
"asset_id": 789,
"slot_id": 1,
"slot_type": "own",
"crystal_amount": 100,
"cycle_start_time": 1712607600000,
"cycle_end_time": 1712694000000,
"status": "claimable",
"can_claim": true
}
],
"total": 10,
"page": 1,
"page_size": 20
}
```
### 4.2 Dubbo 内部 RPC
#### taskService 作为服务端(被调用)
**TaskInternalService**
```protobuf
service TaskInternalService {
// 用户注册时调用,创建 onboarding_status + 该 star_id 下的每日任务进度
rpc InitUserTasks(InitUserTasksRequest) returns (InitUserTasksResponse);
// 展品到期完成galleryService 调用)
rpc OnExhibitionCompleted(OnExhibitionCompletedRequest) returns (OnExhibitionCompletedResponse);
}
```
**消息定义:**
```protobuf
message InitUserTasksRequest {
int64 user_id = 1;
int64 star_id = 2; // 注册时选择的第一个 star_id
}
message InitUserTasksResponse {
topfans.common.BaseResponse base = 1;
bool success = 2;
}
message OnExhibitionCompletedRequest {
int64 exhibition_id = 1;
int64 asset_id = 2;
int64 slot_id = 3;
int64 occupier_uid = 4;
int64 occupier_star_id = 5;
int64 slot_owner_uid = 6;
int64 crystal_amount = 7;
int64 start_time = 8;
int64 expire_at = 9;
}
message OnExhibitionCompletedResponse {
topfans.common.BaseResponse base = 1;
int64 revenue_record_id = 2;
}
```
#### taskService 作为客户端(调用 userService
**userService 新增 RPC**
```protobuf
// 更新经验值请求内部RPC调用用于taskService发放经验奖励
message AddExperienceRequest {
int64 user_id = 1;
int64 star_id = 2;
int64 delta = 3;
}
message AddExperienceResponse {
topfans.common.BaseResponse base = 1;
int64 new_experience = 2;
}
// 在 service UserSocialService 中添加:
rpc AddExperience(AddExperienceRequest) returns (AddExperienceResponse);
```
---
## 五、业务流程
### 5.1 每日任务流程
```
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
d. 记录 task_reset_log
e. 释放锁
```
### 5.2 引导任务流程
```
1. 用户首次登录 → 前端调用 GET /api/tasks/onboarding/status
2. 返回 { current_stage: 0, status: 'pending', stages: [...] }
3. 前端根据 stage 配置显示引导步骤
4. 用户完成引导步骤(如 square_home
5. → POST /api/tasks/guide/complete { task_key: "square_home" }
6. 后端更新 user_onboarding_progress.status = 'completed'
7. 前端引导流程中,用户点击"进入下一阶段"
8. → POST /api/tasks/onboarding/advance-stage { target_stage: 2 }
9. 后端检查 stage 1 所有 task_key 是否都已 completed
- 如未全部完成,返回错误
- 如全部完成current_stage++,返回最新状态
10. 前端调用 POST /api/tasks/onboarding/claim-reward 领取阶段奖励
11. 重复 3-10直到所有引导完成
```
### 5.3 展示收益流程
```
1. galleryService 的 CleanupWorker 扫描到过期展品
2. → 调用 taskService.OnExhibitionCompleted RPC
3. taskService 创建 exhibition_revenue_recordsstatus=claimable
4. 每日 05:00紧接重置后
a. 查询所有 status=claimable 的记录
b. 分批处理(每批 N 条,可配置)
c. 调用 userService.UpdateCrystalBalance 发放水晶
d. 成功则更新 status=claimed失败则重试 N 次
e. 仍失败则标记 status=failed对用户不可见运营可查
5. 用户打开移动端 → GET /api/tasks/exhibition-revenue
- 前端只显示 claimable 和 claimed 状态的记录
- failed 记录对用户不可见
6. 用户点击领取 → POST /api/tasks/exhibition-revenue/claim
7. 后端调用 userService.UpdateCrystalBalance → 更新状态
```
---
## 六、分页规范
所有列表查询统一分页参数:
| 参数 | 类型 | 说明 |
|------|------|------|
| page | int | 页码,从 1 开始 |
| page_size | int | 每页条数,最大 100 |
响应结构:
```json
{
"items": [...],
"total": 100,
"page": 1,
"page_size": 20
}
```
---
## 七、Worker 设计
### 7.1 DailyResetWorker + RevenueAutoClaimWorker
**共用一个 Worker每天 05:00 Asia/Shanghai 执行。**
```go
// 伪代码
func (w *Worker) run() {
// 尝试获取锁日期作为锁ID
lockID := time.Now().Format("20060102") // 如 "20230409"
if !w.acquireAdvisoryLock(lockID) {
return // 其他实例在执行
}
defer w.releaseAdvisoryLock(lockID)
// 1. 执行每日任务重置
w.resetDailyTasks()
// 2. 执行展示收益自动发放
w.autoClaimExhibitionRevenue()
}
func (w *Worker) resetDailyTasks() {
// 查询 task_reset_log如今天已有记录则跳过
// 更新所有 status != 'pending' 的记录为 'pending'
// 记录 task_reset_log
}
func (w *Worker) autoClaimExhibitionRevenue() {
// 查询所有 status='claimable' 的记录
// 分批处理batch_size 可配置)
// 每批:调用 userService.UpdateCrystalBalance
// - 成功:更新 status='claimed'
// - 失败:重试 N 次(可配置),仍失败标记 status='failed'
// 每条记录处理结果保存到日志
}
```
### 7.2 Advisory Lock 设计
- **锁 key** 日期格式 `YYYYMMDD`(如 `20230409`
- **获取锁:** `pg_try_advisory_lock(lockID)`
- **释放锁:** `pg_advisory_unlock(lockID)`
- **作用:** 保证多实例环境下每天只执行一次重置和自动发放
---
## 八、activity-admin 页面
| 页面 | 路由 | 功能 |
|------|------|------|
| 任务定义列表 | `/tasks/definitions` | 查看、新建、编辑、删除、启用/禁用任务定义 |
| 每日任务进度 | `/tasks/daily-progress` | 查询各用户的每日任务完成情况 |
| 引导任务进度 | `/tasks/onboarding-progress` | 查询各用户的引导任务完成情况 |
| 任务统计 | `/tasks/stats` | 任务完成率/领取率统计图表,支持 star_id、时间范围筛选 |
| 手动重置 | `/tasks/reset` | 手动触发每日任务重置 |
| 收益记录 | `/tasks/revenue` | 查看展示收益记录(含 failed支持手动补发 |
**统计页面指标:**
- 每日任务:完成人数、领取人数、完成率、领取率
- 引导任务:各 stage 完成人数、总体完成率
- 收益统计:总发放水晶数、待领取水晶数、已领取水晶数
**筛选维度:**
- star_id
- 时间范围近7天、近30天、自定义
- 任务类型daily/onboarding
---
## 九、项目结构
### 9.1 目录结构
```
backend/
├── proto/
│ ├── user.proto # 修改:新增 AddExperience RPC
│ └── task.proto # 新增TaskInternalService
├── services/
│ ├── taskService/ # 新增
│ │ ├── main.go
│ │ ├── config/
│ │ │ └── task_config.go
│ │ ├── repository/
│ │ │ └── task_repository.go
│ │ ├── service/
│ │ │ ├── daily_task_service.go
│ │ │ ├── onboarding_service.go
│ │ │ └── exhibition_revenue_service.go
│ │ ├── provider/
│ │ │ ├── task_mobile_provider.go # 移动端 API
│ │ │ └── task_internal_provider.go # 内部 RPC
│ │ ├── worker/
│ │ │ └── daily_reset_worker.go
│ │ └── client/
│ │ └── user_rpc_client.go
│ │
│ └── userService/ # 修改
│ ├── repository/
│ │ └── fan_profile_repository.go # 新增 UpdateExperience
│ ├── service/
│ │ └── user_service.go # 新增 AddExperience
│ └── provider/
│ ├── user_provider.go # 新增 AddExperience
│ └── unified_provider.go # 新增 AddExperience
├── pkg/
│ └── proto/
│ ├── user/
│ │ └── *.go # 重新生成
│ └── task/
│ └── *.go # 新生成
└── scripts/
└── v001_init_task_tables.sql
```
### 9.2 前端文件activity-admin
```
frontend/src/
├── api/
│ └── admin.js # 修改:新增任务相关 API
├── views/
│ ├── TaskDefinitionList.vue
│ ├── TaskProgress.vue
│ ├── TaskStats.vue
│ ├── TaskReset.vue
│ └── RevenueList.vue
└── router/
└── index.js # 修改:新增路由
```
---
## 十、后续迭代项
以下内容在当前设计中预留扩展点,后续可根据业务需求添加:
1. **引导任务细分** - `square_home` 等 key 是否需要与 star_id 关联
2. **任务事件扩展** - ReportTaskEvent 的 event_type 可继续扩展
3. **收益周期细分** - 当前 cycle_start/end_time 为基础字段,可扩展 cycle_name 等
4. **统计图表扩展** - 当前预留 ECharts 位置,可扩展更多图表类型
5. **手动重置扩展** - 当前支持全局重置,可扩展按 star_id 重置
---
## 十一、错误码规范
复用现有 `BaseResponse.code` 体系,不新增自定义业务错误码。
| 场景 | 处理方式 |
|------|----------|
| 领取未完成任务 | 静默返回成功,前端根据 status 阻止 |
| 领取已领取任务 | 静默返回成功,前端根据 status 阻止 |
| 阶段切换但任务未完成 | 返回错误,前端提示 |
| RPC 超时 | 记录日志,不自动重试(可手动补发) |
| 重置时其他实例在执行 | 跳过本次执行 |