Files
cn-rdms-web/10-产品动态时间线_前端API文档.md

368 lines
9.5 KiB
Markdown
Raw Normal View History

# 10-产品动态时间线 前端 API 文档
## 0. 文档定位
本文档是给前端产品首页“产品动态展示区域”单独使用的接口文档。
目标:
- 明确前端当前应该调用哪个接口
- 明确左侧筛选项如何映射到后端参数
- 明确接口返回字段、时间格式、边界规则
- 避免继续混用设置页最近动态和首页正式时间线
说明:
- 设置页原最近动态接口 `GET /project/product/{id}/activities` 继续保留
- 产品首页正式动态时间线请统一使用本文档中的新接口
- 当前首页动态时间线不包含需求池变动,需求池由独立区域承载
---
## 1. 接口概览
### 1.1 接口信息
- 接口名称:获取产品动态时间线分页
- 请求方法:`GET`
- 请求路径:`/project/product/{id}/activities/page`
- 权限码:`project:product:query`
- 适用页面:产品首页动态时间线区域
### 1.2 接口用途
该接口用于返回产品首页动态展示区域的正式时间线数据,支持:
- 默认最近 30 天
- 左侧类型筛选
- 动作多选筛选
- 分页查询
- 创建初始化噪音去除
### 1.3 当前纳入首页时间线的事件范围
当前只包含以下 5 类:
- 产品创建
- 产品状态变更
- 产品经理变更
- 成员加入
- 成员移出
当前明确不包含:
- 需求池变动
- `update_member`
- 普通产品主数据编辑 `update`
- 删除产品动态
---
## 2. 请求定义
### 2.1 路径参数
| 参数名 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `id` | `integer(int64)` | 是 | 产品 ID |
### 2.2 查询参数
| 参数名 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `pageNo` | `integer` | 是 | 页码,从 `1` 开始 |
| `pageSize` | `integer` | 是 | 每页条数 |
| `activityType` | `string` | 否 | 分类,可选 `status` / `product` / `member` |
| `actionTypes` | `array<string>` | 否 | 动作编码数组,支持多选 |
| `startTime` | `string` | 否 | 开始时间,格式 `yyyy-MM-dd HH:mm:ss` |
| `endTime` | `string` | 否 | 结束时间,格式 `yyyy-MM-dd HH:mm:ss` |
### 2.3 参数规则
#### 2.3.1 时间参数规则
- `startTime``endTime` 必须同时传,或者同时不传
- 都不传时,后端默认查询最近 `30`
- 只传一个时,后端返回参数错误
- `startTime > endTime` 时,后端返回参数错误
#### 2.3.2 筛选参数规则
- `activityType` 是分类筛选
- `actionTypes` 是动作细筛选
- 两者同时传时,按交集处理
- 如果前端未来需要做跨类型多选,可以不传 `activityType`,只传 `actionTypes`
#### 2.3.3 `actionTypes` 传参方式
GET 场景请按重复参数方式传递,例如:
```text
/project/product/1024/activities/page?pageNo=1&pageSize=10&activityType=status&actionTypes=pause&actionTypes=resume&actionTypes=archive&actionTypes=abandon
```
---
## 3. 左侧筛选映射
首页左侧当前 5 个筛选项,前端请按下表映射到请求参数:
| 前端筛选项 | `activityType` | `actionTypes` |
| --- | --- | --- |
| 产品创建 | `product` | `create` |
| 产品状态变更 | `status` | `pause` / `resume` / `archive` / `abandon` |
| 产品经理变更 | `product` | `change_manager` |
| 成员加入 | `member` | `add_member` |
| 成员移出 | `member` | `remove_member` |
补充说明:
- 首页时间线当前不展示需求池变动
- 需求池的展示由独立模块负责,不要通过本接口混查
---
## 4. 响应定义
### 4.1 响应包装
接口统一返回 `CommonResult<PageResult<ProductActivityTimelineRespVO>>`
成功响应结构:
```json
{
"code": 0,
"msg": "",
"data": {
"total": 0,
"list": []
}
}
```
### 4.2 `data` 结构
| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `total` | `integer(int64)` | 总条数 |
| `list` | `array<object>` | 当前页数据 |
### 4.3 单条动态结构
| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `id` | `string` | 动态唯一标识,格式 `type:sourceId`,例如 `status:11` |
| `type` | `string` | 动态类型,取值 `status` / `product` / `member` |
| `actionType` | `string` | 动作编码 |
| `actionName` | `string` | 动作中文名称 |
| `operatorUserId` | `integer(int64)` | 操作人用户 ID可为 `null` |
| `operatorName` | `string` | 操作人名称,可为空字符串 |
| `occurredAt` | `integer(int64)` | 动态发生时间,毫秒时间戳 |
| `summary` | `string` | 可直接展示的摘要文案 |
| `reason` | `string` | 原因说明,可为 `null` |
| `fromStatus` | `string` | 原状态编码,可为 `null` |
| `toStatus` | `string` | 目标状态编码,可为 `null` |
| `details` | `string` | 补充明细,当前为 JSON 字符串 |
### 4.4 时间格式说明
这个接口当前有两个时间口径:
- 请求里的 `startTime``endTime`:字符串,格式 `yyyy-MM-dd HH:mm:ss`
- 响应里的 `occurredAt`:毫秒时间戳 `number`
前端需要按这个真实口径处理,不要把 `occurredAt` 当成格式化字符串读取。
---
## 5. 字段语义说明
### 5.1 `type` 取值说明
| 取值 | 说明 | 数据来源 |
| --- | --- | --- |
| `status` | 产品状态变更 | `rdms_product_status_log` |
| `product` | 产品对象动态 | `rdms_biz_audit_log``bizType=product` |
| `member` | 产品团队动态 | `rdms_biz_audit_log``bizType=rdms_user_object_role` |
### 5.2 `actionType` 取值范围
当前首页时间线只会出现以下动作:
| `type` | `actionType` | 说明 |
| --- | --- | --- |
| `product` | `create` | 产品创建 |
| `product` | `change_manager` | 产品经理变更 |
| `status` | `pause` | 暂停 |
| `status` | `resume` | 恢复 |
| `status` | `archive` | 归档 |
| `status` | `abandon` | 废弃 |
| `member` | `add_member` | 成员加入 |
| `member` | `remove_member` | 成员移出 |
### 5.3 `details` 当前口径
`details` 当前不做统一结构化建模,按来源原样返回字符串:
- `type=status`
- 返回状态日志补充信息
- 当前包含 `productCodeSnapshot``productNameSnapshot`
- `type=product`
- 返回产品审计 `fieldChanges`
- `type=member`
- 返回成员审计 `fieldChanges`
前端建议:
- 首版先不依赖 `details` 做复杂渲染
- 先以 `actionName + summary + operatorName + occurredAt` 跑通展示
---
## 6. 后端聚合规则
为了让前端看到的是“可直接展示的正式时间线”,后端已固定以下规则:
### 6.1 创建去噪
产品创建时通常会伴随初始化动作:
- 初始化 `change_manager`
- 初始化 `add_member`
这两类初始化动作不会单独出现在首页时间线里,最终只保留一条 `create`
### 6.2 状态日志优先
如果同一状态动作同时存在:
- 产品审计日志
- 状态日志
则首页时间线只取状态日志,不重复展示产品审计里的同类状态动作。
### 6.3 成员调整排除
`update_member` 当前不进入首页正式时间线。
原因:
- 首页当前只需要展示“加入”和“移出”
- 角色调整、备注调整等细节先不进入首页主时间线
---
## 7. 请求示例
### 7.1 默认查询首页动态
```http
GET /project/product/1024/activities/page?pageNo=1&pageSize=6
```
### 7.2 查询“产品状态变更”
```http
GET /project/product/1024/activities/page?pageNo=1&pageSize=10&activityType=status&actionTypes=pause&actionTypes=resume&actionTypes=archive&actionTypes=abandon
```
### 7.3 查询“成员移出”并限制时间范围
```http
GET /project/product/1024/activities/page?pageNo=1&pageSize=10&activityType=member&actionTypes=remove_member&startTime=2026-03-24 00:00:00&endTime=2026-04-23 23:59:59
```
---
## 8. 响应示例
```json
{
"code": 0,
"msg": "",
"data": {
"total": 2,
"list": [
{
"id": "product:22",
"type": "product",
"actionType": "change_manager",
"actionName": "切换产品经理",
"operatorUserId": 10002,
"operatorName": "李四",
"occurredAt": 1776812345000,
"summary": "李四执行了【切换产品经理】",
"reason": null,
"fromStatus": null,
"toStatus": null,
"details": "{\"managerUserId\":{\"before\":10001,\"after\":10002}}"
},
{
"id": "status:11",
"type": "status",
"actionType": "resume",
"actionName": "恢复",
"operatorUserId": 10001,
"operatorName": "张三",
"occurredAt": 1776812984000,
"summary": "张三执行了【恢复】:可以继续开展",
"reason": "可以继续开展",
"fromStatus": "paused",
"toStatus": "active",
"details": "{\"productCodeSnapshot\":\"CNPD2026001\",\"productNameSnapshot\":\"统一交付平台\"}"
}
]
}
}
```
---
## 9. 错误码
| `code` | 说明 |
| --- | --- |
| `0` | 成功 |
| `400` | 请求参数错误,例如只传了一侧时间,或开始时间晚于结束时间 |
| `401` | 未登录 |
| `403` | 没有该产品查询权限 |
| `1008001000` | 产品不存在 |
参数错误示例:
```json
{
"code": 400,
"msg": "开始时间和结束时间必须同时传入",
"data": null
}
```
---
## 10. 前端接入建议
首页动态区域首版建议直接消费以下字段:
- `actionName`
- `summary`
- `operatorName`
- `occurredAt`
左侧筛选建议直接使用:
- `activityType`
- `actionTypes`
当前不建议首版依赖:
- `details` 的深度结构化解析
- 需求池事件混入本接口
- 自行从 `actionType` 反推新的派生事件类型
一句话结论:
- 设置页最近动态继续调 `/activities`
- 产品首页正式动态时间线统一调 `/activities/page`