# 产品动态时间线后端接口需求说明

日期：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. 产品经理变更必须提供前后经理信息

这条接口交付后，前端才能把当前“产品动态时间线”从拼装摘要升级成正式可查询模块。
