- 新增 GET /project/product/{id}/activities/page 接口用于产品动态时间线分页查询
- 添加 ProductActivityTimelinePageReqVO 和 ProductActivityTimelineRespVO 数据传输对象
- 实现 ProductActivityTimelineQueryService 服务处理动态时间线查询逻辑
- 在 BizAuditLogMapper 中新增按业务类型和动作类型查询的方法
- 在 ProductStatusLogMapper 中新增按产品ID和动作类型查询的方法
- 将硬编码的活动类型常量抽取到 ObjectActivityConstants 统一管理
- 重构 ProductActivityQueryService 使用统一的常量和查询方法
- 更新 ProductMemberServiceImpl 和 ProductServiceImpl 使用新的活动常量
- 添加相应的单元测试验证新接口和查询逻辑的正确性
- 新增产品对象首页改版设计文档和产品动态时间线接口需求说明文档
271 lines
6.8 KiB
Markdown
271 lines
6.8 KiB
Markdown
# 产品动态时间线后端接口需求说明
|
||
|
||
日期:2026-04-23
|
||
|
||
## 1. 背景
|
||
|
||
当前产品对象首页中的“产品动态时间线”模块,用户期望不是展示几条前端拼装的摘要,而是一个可以在首页内直接查询的正式动态模块。
|
||
|
||
本轮已确认的目标能力包括:
|
||
|
||
- 首页内直接展示产品动态时间线
|
||
- 默认查询最近 `30 天`
|
||
- 支持自定义起止时间筛选
|
||
- 支持事件类型多选筛选
|
||
- 支持分页
|
||
- 第一版事件范围收敛在产品对象与团队关系,不混入需求池事件
|
||
|
||
## 2. 当前前端现状
|
||
|
||
当前前端可直接使用的真实接口只有:
|
||
|
||
- `GET /project/product/get`
|
||
- `GET /project/product/{id}/settings`
|
||
- `GET /project/product/{id}/members`
|
||
|
||
这些接口目前只能提供:
|
||
|
||
- 产品当前状态
|
||
- 最近一次状态原因
|
||
- 产品经理
|
||
- 成员加入时间
|
||
- 成员退出时间
|
||
- 当前成员角色
|
||
|
||
它们可以勉强拼出少量“最近动态摘要”,但不足以支撑正式时间线查询模块。
|
||
|
||
## 3. 当前接口为什么不够
|
||
|
||
如果继续只依赖现有接口,前端存在以下硬缺口:
|
||
|
||
1. 没有统一的产品动态分页接口
|
||
2. 没有事件类型维度,无法支持类型筛选
|
||
3. 没有统一发生时间字段集合,无法稳定支持时间筛选
|
||
4. 没有事件操作人字段,无法明确展示“谁做了什么”
|
||
5. 没有统一的事件摘要字段,前端只能自己硬拼文案
|
||
6. 没有产品状态变更前后值,无法展示“从什么状态变更为什么状态”
|
||
7. 没有产品经理变更前后值,无法展示交接关系
|
||
8. 没有分页总数字段,无法做首页内翻页
|
||
|
||
因此,现有接口只适合做“概览摘要”,不适合做“可查询产品动态时间线”。
|
||
|
||
## 4. 后端接口交付要求
|
||
|
||
后端必须新增一条专用分页接口:
|
||
|
||
`GET /project/product/{id}/activities/page`
|
||
|
||
这条接口只服务“产品动态时间线”能力,不承担需求池动态,不承担首页其它概览指标。
|
||
|
||
前端要求后端单独提供这条接口,原因如下:
|
||
|
||
- 语义清晰,前后端都容易维护
|
||
- 首页时间线可直接消费
|
||
- 后续如果要做独立的产品动态页,也可以继续复用这条接口
|
||
- 不需要继续让前端从多个接口里拼装事件
|
||
|
||
## 5. 第一版事件范围
|
||
|
||
第一版事件类型确认收敛为 5 类:
|
||
|
||
- `product_created`:产品创建
|
||
- `product_status_changed`:产品状态变更
|
||
- `product_manager_changed`:产品经理变更
|
||
- `product_member_joined`:成员加入
|
||
- `product_member_removed`:成员移出
|
||
|
||
第一版明确不纳入:
|
||
|
||
- 成员角色调整
|
||
- 需求新增
|
||
- 需求状态流转
|
||
- 需求关闭
|
||
- 里程碑事件
|
||
- 风险点事件
|
||
|
||
## 6. 查询参数要求
|
||
|
||
接口必须支持以下查询参数:
|
||
|
||
- `pageNo`:页码
|
||
- `pageSize`:每页数量
|
||
- `startTime`:开始时间
|
||
- `endTime`:结束时间
|
||
- `types`:事件类型数组,多选
|
||
|
||
补充要求:
|
||
|
||
- 当前端未传时间范围时,后端默认按最近 `30 天` 返回
|
||
- 返回结果按 `occurredAt desc` 倒序排列
|
||
- `types` 支持多选,不要求前端单选
|
||
|
||
示例:
|
||
|
||
```http
|
||
GET /project/product/1001/activities/page?pageNo=1&pageSize=10&startTime=2026-03-24 00:00:00&endTime=2026-04-23 23:59:59&types=product_status_changed&types=product_manager_changed
|
||
```
|
||
|
||
## 7. 返回结构要求
|
||
|
||
接口返回必须支持分页,分页结构至少应满足:
|
||
|
||
```json
|
||
{
|
||
"total": 128,
|
||
"list": [
|
||
{
|
||
"id": "act_001",
|
||
"type": "product_status_changed",
|
||
"title": "产品状态变更",
|
||
"operatorId": "10001",
|
||
"operatorName": "张敏",
|
||
"occurredAt": "2026-04-23 10:32:15",
|
||
"summary": "产品状态由暂停变更为启用",
|
||
"reason": "测试恢复",
|
||
"beforeStatus": "paused",
|
||
"afterStatus": "active"
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
分页顶层字段至少包括:
|
||
|
||
- `total`
|
||
- `list`
|
||
|
||
如果后端已有统一分页模型,可以沿用现有分页结构,但前端必须能稳定拿到总数和列表。
|
||
|
||
## 8. 事件通用字段要求
|
||
|
||
无论哪种事件类型,后端都应统一返回以下字段:
|
||
|
||
- `id`:事件唯一 ID
|
||
- `type`:事件类型编码
|
||
- `title`:事件标题
|
||
- `operatorId`:操作人 ID
|
||
- `operatorName`:操作人名称
|
||
- `occurredAt`:发生时间
|
||
- `summary`:事件摘要
|
||
- `reason`:原因或备注,可为空
|
||
|
||
这些字段是首页时间线最小可展示集合。
|
||
|
||
## 9. 各事件类型的专属字段要求
|
||
|
||
### 9.1 产品创建 `product_created`
|
||
|
||
必须补充:
|
||
|
||
- `creatorUserId`
|
||
- `creatorUserName`
|
||
|
||
### 9.2 产品状态变更 `product_status_changed`
|
||
|
||
这是当前最关键的一类事件,后端必须返回:
|
||
|
||
- `beforeStatus`
|
||
- `afterStatus`
|
||
- `reason`
|
||
|
||
前端需要用这组字段明确表达:
|
||
|
||
- 变更前状态
|
||
- 变更后状态
|
||
- 本次变更原因
|
||
|
||
例如:
|
||
|
||
- `暂停 -> 启用`
|
||
- `启用 -> 归档`
|
||
|
||
### 9.3 产品经理变更 `product_manager_changed`
|
||
|
||
必须返回:
|
||
|
||
- `beforeManagerUserId`
|
||
- `beforeManagerUserName`
|
||
- `afterManagerUserId`
|
||
- `afterManagerUserName`
|
||
- `reason`
|
||
|
||
否则前端无法准确展示交接关系,只能看到当前经理,不能看到变更前后关系。
|
||
|
||
### 9.4 成员加入 `product_member_joined`
|
||
|
||
必须返回:
|
||
|
||
- `memberUserId`
|
||
- `memberUserName`
|
||
- `roleId`
|
||
- `roleName`
|
||
- `remark`
|
||
|
||
### 9.5 成员移出 `product_member_removed`
|
||
|
||
必须返回:
|
||
|
||
- `memberUserId`
|
||
- `memberUserName`
|
||
- `roleId`
|
||
- `roleName`
|
||
- `reason`
|
||
|
||
## 10. 前端展示口径
|
||
|
||
前端首页时间线模块第一版会直接基于这条接口支持:
|
||
|
||
- 默认最近 `30 天`
|
||
- 自定义时间范围筛选
|
||
- 事件类型多选筛选
|
||
- 分页切换
|
||
|
||
每条记录最少展示:
|
||
|
||
- 事件类型
|
||
- 事件标题
|
||
- 操作人
|
||
- 发生时间
|
||
- 变更摘要
|
||
- 原因/备注
|
||
|
||
其中“产品状态变更”需要明确体现:
|
||
|
||
- 变更前状态
|
||
- 变更后状态
|
||
- 变更原因
|
||
|
||
## 11. 为什么不建议继续让前端拼装
|
||
|
||
如果继续沿用当前前端拼装方案,会有这些问题:
|
||
|
||
- 产品状态变更前后值无法补齐
|
||
- 产品经理变更前后值无法补齐
|
||
- 无法支持分页
|
||
- 无法支持统一时间筛选
|
||
- 无法支持统一类型筛选
|
||
- 不同事件文案会在前端散落拼装,长期维护成本高
|
||
|
||
因此这里的前后端边界应明确为:
|
||
|
||
- 后端提供统一产品动态分页接口
|
||
- 前端负责筛选条件组织、分页交互和时间线展示
|
||
|
||
## 12. 本轮需求结论
|
||
|
||
本轮给后端的结论可以直接收敛为:
|
||
|
||
1. 当前前端已有接口不满足正式产品动态时间线需求
|
||
2. 后端新增 `GET /project/product/{id}/activities/page`
|
||
3. 接口必须支持分页、默认最近 `30 天`、自定义时间范围、事件类型多选
|
||
4. 第一版事件类型只做:
|
||
- 产品创建
|
||
- 产品状态变更
|
||
- 产品经理变更
|
||
- 成员加入
|
||
- 成员移出
|
||
5. 产品状态变更必须提供前后状态和原因
|
||
6. 产品经理变更必须提供前后经理信息
|
||
|
||
这条接口交付后,前端才能把当前“产品动态时间线”从拼装摘要升级成正式可查询模块。
|