368 lines
9.5 KiB
Markdown
368 lines
9.5 KiB
Markdown
|
|
# 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`
|