- 新增产品动态时间线接口文档,明确前端调用规范 - 定义接口请求参数、响应结构和字段语义说明 - 提供请求示例和错误码说明 - 添加左侧筛选项映射规则和时间格式说明 feat(product): 实现产品首页动态时间线功能 - 重构产品首页布局结构,采用档案横幅型设计 - 新增对象基础概述横幅模块 - 实现产品动态时间线面板组件 - 集成需求池管理概览和最近变化区域 - 添加扩展信息区预留模块位 chore(docs): 更新代理工作说明和前端测试策略 - 添加前端任务测试策略说明 - 更新代理工作流程规范 - 明确git操作执行边界 - 优化组件类型声明更新
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`
|