工作项解决「做什么」,规划解决「什么时候做」,里程碑和迭代解决「做到什么程度算一个阶段」。但团队成员还需要回答一个问题:「最近发生了什么?」------谁创建了工作项、谁开始了迭代、谁关闭了里程碑、谁编辑了文档。这些操作留痕需要被实时记录、按时间轴聚合、按维度筛选,让团队成员快速了解项目动态。本篇记录动态模块的数据模型、注解+切面写入机制、层级归集查询、视图 Tab、前端公共组件,以及多入口接入与概览预览改造。
一、动态要解决什么问题
1.1 痛点:两处「假动态」
在动态模块上线之前,平台有两处「假动态」:
| 位置 | 问题 |
|---|---|
| 迭代概览「动态」 | 用迭代+工作项+当前登录人在前端现拼,含捏造条目,无存储、无历史 |
| 项目概览「动态」 | 硬编码 mock 数据(张明/李雷...),纯占位 |
这两处都无法提供真实、持久、可追溯的活动流。用户看到的「动态」既不准确也不完整。
1.2 目标
用真实活动流替换假数据,实现:
- 持久化存储:所有关键操作落库,可追溯
- 层级归集:项目动态上卷子域(迭代/里程碑/知识库事件),企业动态上卷全项目
- 个人视图:支持「全部 / 我创建的 / 我负责的 / 我参与的」四个视图 Tab
- 分组与筛选:按天/按人/按业务域分组,支持人员、项目、迭代/里程碑筛选
- 瀑布分页:无限滚动加载,而非传统分页
- 公共组件:封装统一组件,多入口复用

二、数据模型
2.1 与审计日志解耦
平台已有审计日志模块,但动态选择独立建表,原因如下:
| 维度 | 审计日志 | 动态 |
|---|---|---|
| 目的 | 安全审计、合规追溯 | 团队协作、信息同步 |
| 粒度 | 每次操作逐字段变更记录 | 已渲染摘要,面向人类阅读 |
| 查询 | 按操作人/业务编号 | 按作用域/时间轴/关系人 |
| 展示 | 表格 + 字段变更对比 | 时间轴 + 摘要 + 头像 |
| 保留 | 30 天 | 永久(逻辑删除) |
两者解耦后,动态可以面向用户体验做摘要渲染、关系人冗余、层级归集,不影响审计日志的合规性设计。
2.2 实体结构
动态实体继承基础业务实体,核心字段如下:
| 字段 | 类型 | 说明 |
|---|---|---|
| 所属企业 | String | 企业编码(归集根) |
| 所属项目 | Long | 项目 ID(归集层;企业级无项目事件可空) |
| 作用域类型 | String | 企业/项目/迭代/里程碑/知识库/工作项 |
| 作用域 ID | Long | 精确容器 ID |
| 冗余迭代 ID | Long | 项目下按迭代筛选 |
| 冗余里程碑 ID | Long | 项目下按里程碑筛选 |
| 操作者 | String | 操作者用户名(展示 + 按人分组) |
| 操作者展示名 | String | 冗余存储,免 join |
| 目标创建人 | String | 目标实体的创建人(「我创建的」视图) |
| 目标负责人 | String | 目标实体的负责人(「我负责的」视图) |
| 协办人 | String | 目标实体协办人用户名逗号串(「我参与的」视图) |
| 动作类型 | String | 创建/更新/删除/开始/完成/关闭/移入/移出等 |
| 目标类型 | String | 工作项/迭代/里程碑/知识库节点/项目/成员 |
| 目标 ID | Long | 目标实体 ID |
| 摘要 | String | 已渲染摘要(如「创建了迭代「迭代 3 · 实时看板升级」」) |
| 扩展 JSON | String | 字段变更/纳入移出信息/评论摘要等 |
设计要点:摘要在后端渲染后落库,而非前端拼接------确保历史记录不因前端版本变更而失真。操作者展示名冗余存储,避免每次查询都 join 用户表。关系人字段(创建人/负责人/协办人)描述的是「当前用户与目标实体的关系」,与操作者解耦。
2.3 作用域与归集
动态通过「作用域类型 + 作用域 ID」实现三级归集:
ini
┌──────────────────────────────────────────────────────────────┐
│ 归集层级 │
├──────────────────────────────────────────────────────────────┤
│ │
│ 企业动态(作用域 = 企业) │
│ ├── 归集:企业下全部项目的全部事件 │
│ ├── 查询条件:企业编码 = 当前企业 │
│ └── 筛选:项目下拉 + 人员下拉 │
│ │
│ 项目动态(作用域 = 项目) │
│ ├── 归集:项目下全部子域事件(迭代/里程碑/知识库/工作项) │
│ ├── 查询条件:项目 ID = 当前项目 │
│ └── 筛选:迭代/里程碑下拉 + 人员下拉 │
│ │
│ 容器动态(作用域 = 迭代/里程碑) │
│ ├── 归集:精确容器事件 + 冗余列上的子对象事件 │
│ │ 例:迭代动态 = 迭代自身事件 + 工作项在该迭代上的纳入/移出 │
│ ├── 查询条件:作用域匹配 OR 冗余列匹配 │
│ └── 筛选:人员下拉 │
│ │
└──────────────────────────────────────────────────────────────┘
冗余列的作用:一条工作项「纳入迭代」的动态,其作用域是「迭代」,但同时冗余了项目 ID 和迭代 ID。这样项目动态页可以按项目 ID 归集到这条动态,迭代动态页也可以按冗余的迭代 ID 归集到这条动态------无需 join。
三、写入机制
3.1 注解 + 切面
动态的写入采用自研注解 + AOP 切面模式,与平台已有的审计日志注解套路一致:
- 注解:声明动态的元数据(作用域、动作、目标、摘要等),支持表达式从方法入参、返回值、上下文变量中动态取值
- 切面:拦截注解方法,方法成功返回且事务提交后,解析表达式 → 组装记录 → 异步落库
注解属性支持三类值:
- 表达式 :以
#开头,从方法入参、返回值、上下文变量中取值 - 静态方法调用:调用登录工具等获取当前用户等运行时信息
- 字面量:不含上述标记的字符串,直接使用
3.2 事务提交后落库
切面在方法成功返回且事务提交后才执行落库,原因:
- 事务回滚时不记录动态(业务操作失败了,不应留下「成功」的动态)
- 避免动态落库与业务操作在同一事务中,动态写失败导致业务回滚
落库失败时静默吞掉异常------动态是旁路记录,不应影响主业务流程。
3.3 栈式上下文
动态埋点支持嵌套场景 ------一个业务操作可能触发多个注解方法。为防止内层方法清除外层的上下文变量,采用栈式 Frame 设计:
ini
┌──────────────────────────────────────────────────┐
│ 线程局部栈(ThreadLocal<Deque<Map>>) │
│ │
│ ┌──────────────────┐ ← 栈顶(内层 Frame) │
│ │ key: _skip=true │ │
│ │ key: itemTitle=X │ │
│ └──────────────────┘ │
│ ┌──────────────────┐ ← 外层 Frame │
│ │ key: projectName=Y│ │
│ └──────────────────┘ │
│ │
│ 快照:自底向上合并,上层覆盖下层 │
│ → { projectName: Y, itemTitle: X, _skip: true }│
└──────────────────────────────────────────────────┘
- 切面进入时
push新 Frame,退出时pop - 业务代码通过
put写入栈顶 Frame - 表达式解析时
snapshot合并所有 Frame,上层覆盖下层 - 内层可通过
_skip = true跳过自身记录,不影响外层
3.4 Support Bean 模式
动态注解通过 AOP 代理生效,这意味着同类内部方法调用不会触发切面。为此,每个业务域抽取独立的 Support Bean:
| Support Bean | 职责 |
|---|---|
| 迭代动态支持 | 创建/更新/删除/开始/完成迭代 |
| 里程碑动态支持 | 创建/更新/删除/置顶/开始/关闭/重开里程碑 |
| 工作项动态支持 | 创建/编辑/删除(回收站)/恢复/彻底删除/状态流转工作项 |
| 工作项移动支持 | 纳入/移出迭代·里程碑 + 容器关闭批量回池 |
| 工作项协办人支持 | 查询协办人逗号串写入上下文(供 SpEL #collab) |
| 知识库动态支持 | 创建文件夹/文档/上传/编辑/重命名/移动/删除/恢复/彻底删除/分享 |
| 项目动态支持 | 创建项目/更新设置/状态变更/成员加入/退出/身份变更 |
| 测试动态支持 | 用例/计划/评审/报告全生命周期埋点 |
Service 完成业务操作后,调用对应 Support Bean 的方法记录动态。Support Bean 内部通过上下文工具写入临时变量(如项目名、工作项标题、类型标签),注解的表达式从入参和上下文中取值组装摘要。
python
┌──────────────────────────────────────────────────┐
│ Service 业务方法 │
│ │
│ 1. 业务操作(保存迭代) │
│ │
│ 2. 调用 Support Bean 记录动态 │
│ iterationSupport.recordCreate(projectId, iter)│
│ │
│ └─ 动态注解方法 │
│ ├── 表达式解析入参:迭代 ID、序号、名称 │
│ ├── 表达式解析上下文:临时变量 │
│ ├── 表达式调用静态方法:获取当前登录用户 │
│ └── 组装摘要:"创建了迭代「迭代 3 · 实时看板升级」"│
│ │
│ 3. 切面拦截 → 事务提交后 → 落库 │
└──────────────────────────────────────────────────┘
四、埋点接入
4.1 事件目录
v1 接入的动态事件按业务域分类:
迭代:
| 动作 | 摘要示例 |
|---|---|
| 创建 | 创建了迭代「迭代 3 · 实时看板升级」 |
| 更新 | 更新了迭代「迭代 3 · 实时看板升级」 |
| 删除 | 删除了迭代「迭代 3 · 实时看板升级」 |
| 开始 | 开始了迭代「迭代 3 · 实时看板升级」 |
| 完成 | 完成了迭代「迭代 3 · 实时看板升级」 |
里程碑:
| 动作 | 摘要示例 |
|---|---|
| 创建 | 创建了里程碑「V1.0 发布」 |
| 更新 | 更新了里程碑「V1.0 发布」 |
| 删除 | 删除了里程碑「V1.0 发布」 |
| 置顶/取消置顶 | 置顶了/取消了置顶里程碑「V1.0 发布」 |
| 开始 | 开始了里程碑「V1.0 发布」 |
| 关闭 | 关闭了里程碑「V1.0 发布」 |
| 重新开启 | 重新开启了里程碑「V1.0 发布」 |
工作项:
| 动作 | 摘要示例 |
|---|---|
| 创建 | 创建了需求「用户登录优化」 |
| 编辑 | 编辑了任务「接口联调」 |
| 状态流转 | 将缺陷状态改为进行中「登录页白屏」 |
| 删除(回收站) | 删除了任务「废弃需求」 |
| 恢复 | 恢复了任务「废弃需求」 |
| 彻底删除 | 彻底删除了任务「废弃需求」 |
| 纳入迭代 | 纳入了工作项「用户登录优化」(含容器链接) |
| 移出迭代 | 移出了工作项「用户登录优化」(含容器链接) |
| 纳入里程碑 | 纳入了工作项「用户登录优化」(含容器链接) |
| 移出里程碑 | 移出了工作项「用户登录优化」(含容器链接) |
| 批量回池 | 迭代/里程碑关闭时批量移出 N 个工作项(聚合一条) |
知识库:
| 动作 | 摘要示例 |
|---|---|
| 创建文件夹 | 创建了文件夹「需求文档」 |
| 创建文档 | 创建了文档「接口规格说明」 |
| 上传附件 | 上传了附件「架构图.png」 |
| 编辑文档 | 更新了文档「接口规格说明」 |
| 重命名 | 重命名了「API 设计文档」 |
| 移动 | 移动了「API 设计文档」 |
| 删除(回收站) | 删除了「旧版说明」 |
| 恢复 | 恢复了「旧版说明」 |
| 彻底删除 | 彻底删除了「旧版说明」 |
| 分享 | 分享了「架构图.png」 |
项目:
| 动作 | 摘要示例 |
|---|---|
| 创建项目 | 创建了项目「DevOps 平台」 |
| 更新设置 | 更新了项目「DevOps 平台」 |
| 状态变更 | 将项目状态改为进行中「DevOps 平台」 |
| 成员加入 | 将「张三」加入了项目 |
| 成员退出 | 将「李四」移出了项目 |
| 身份变更 | 将「王五」身份改为项目管理员 |
4.2 扩展 JSON
部分动态携带扩展信息,以 JSON 字符串存储:
| 扩展类型 | 场景 | 内容 |
|---|---|---|
| 字段变更 | 工作项更新 | 字段名、旧值、新值 |
| 纳入/移出 | 工作项移入/移出迭代·里程碑 | 方向(IN/OUT)、容器类型、容器 ID、容器展示名、批量回池数量 |
| 评论摘要 | 评论相关操作 | 评论内容摘要 |
前端根据扩展 JSON 渲染字段变更标签、容器跳转链接等富信息。
五、查询设计
5.1 两种查询模式
| 模式 | 用途 | 特点 |
|---|---|---|
| 分页查询 | 动态全量页 | 支持瀑布分页,每页 20 条 |
| 最新 N 条 | 概览预览 | 固定取最近 6 条,无分页 |
两种模式共享同一套查询条件(归集 + 筛选 + 视图),通过 SQL 片段复用,避免条件漂移。
5.2 查询条件
ini
┌──────────────────────────────────────────────────────────┐
│ 查询条件层叠 │
│ │
│ 1. 归集条件(必选其一) │
│ ├── 精确容器:作用域类型 + 作用域 ID │
│ │ 迭代/里程碑特殊:OR 冗余列匹配 │
│ ├── 项目归集:项目 ID = ? │
│ └── 企业归集:企业编码 = ?(租户插件自动追加) │
│ │
│ 2. 筛选条件(可选) │
│ ├── 迭代筛选:冗余迭代 ID = ? OR 作用域匹配 │
│ ├── 里程碑筛选:冗余里程碑 ID = ? OR 作用域匹配 │
│ ├── 人员筛选:操作者 = ? │
│ ├── 动作类型筛选:动作类型 = ? │
│ └── 目标类型筛选:目标类型 = ? │
│ │
│ 3. 视图 Tab(可选) │
│ ├── 全部:无条件 │
│ ├── 我创建的:目标创建人 = 当前用户 │
│ ├── 我负责的:目标负责人 = 当前用户 │
│ └── 我参与的:目标负责人 = 当前用户 │
│ OR 当前用户 IN (协办人列表) │
│ │
│ 4. 排序:创建时间倒序 + ID 倒序(稳定排序) │
└──────────────────────────────────────────────────────────┘
设计要点:迭代/里程碑的动态查询做了特殊处理------不仅匹配作用域为「迭代/里程碑」的动态,还匹配冗余列上指向该迭代/里程碑的子对象动态(如工作项纳入/移出动态)。这样迭代详情页的动态 Tab 能展示完整的活动流。
5.3 视图 Tab 的关系人语义
四个视图 Tab 描述的是「当前用户与目标实体的关系」,而非与操作者的关系:
| 视图 | 语义 | 查询条件 |
|---|---|---|
| 全部动态 | 当前作用域内全部活动 | 无额外条件 |
| 我创建的 | 目标实体的创建人 = 我 | 目标创建人 = 当前用户 |
| 我负责的 | 目标实体的负责人 = 我 | 目标负责人 = 当前用户 |
| 我参与的 | 我是负责人或协办人 | 目标负责人 = 当前用户 OR 当前用户在协办人列表中 |
操作者(actor)仅用于展示和按人分组,不参与视图过滤------即使操作者是别人,只要目标实体与我有关系,就会出现在我的视图中。
5.4 项目名补齐
企业动态 Feed 需要展示每条动态所属的项目名。为避免逐条查询,采用批量补齐策略:
- 收集结果集中所有不重复的项目 ID
- 一次性查询这些项目的名称
- 在内存中按 ID 映射回每条动态
六、前端公共组件
6.1 组件设计
动态模块封装了统一的公共组件,支持两种模式:
| 模式 | 触发场景 | 特点 |
|---|---|---|
| 全量模式 | 动态页/动态 Tab | 显示视图 Tab + 筛选 + 瀑布分页 |
| 预览模式 | 概览页/概览 Tab | 仅展示最近 N 条 + 「全部动态」按钮,无 Tab/筛选/分页 |
组件通过属性控制行为:
| 属性 | 说明 |
|---|---|
| 作用域类型 | 企业/项目/迭代/里程碑/知识库 |
| 作用域 ID | 对应的实体 ID |
| 项目 ID | 迭代/里程碑场景下兜底用 |
| 是否显示视图 Tab | 概览预览时可关闭 |
| 默认视图 | 初始视图 Tab |
| 筛选项显隐 | 控制项目/人员/迭代里程碑筛选下拉的显示 |
| 是否预览 | 预览模式开关 |
| 预览条数 | 预览模式下的条数(默认 6) |
6.2 数据流
scss
┌──────────────────────────────────────────────────────┐
│ ActivityFeed 组件 │
│ │
│ Props → useActivityFeed 组合式函数 │
│ ├── 作用域类型/ID → 构建基础查询 │
│ ├── 视图 Tab 变化 → 重置列表 │
│ ├── 筛选变化 → 重置列表 │
│ └── 加载更多 → 页码+1,追加列表 │
│ │
│ 分组计算(computed) │
│ └── groupActivities(已加载列表, 'day') │
│ → 按天分组 → 天内按人分组 │
│ │
│ 渲染 │
│ ├── 预览头(预览模式) │
│ ├── 视图 Tab(全量模式) │
│ ├── 筛选栏(全量模式) │
│ ├── 按天分组列表 │
│ │ ├── 天标题(今天/昨天/日期 + 条数标签) │
│ │ └── 人员块 │
│ │ ├── 头像 + 操作人名 │
│ │ └── 操作列表(折叠/展开) │
│ │ ├── 图标 + 摘要 + 时间 │
│ │ ├── 字段变更标签 │
│ │ ├── 纳入/移出容器链接 │
│ │ └── 评论摘要 │
│ └── 加载更多 / 没有更多了 │
└──────────────────────────────────────────────────────┘
6.3 筛选项
不同入口的筛选项不同:
| 入口 | 项目筛选 | 迭代/里程碑筛选 | 人员筛选 |
|---|---|---|---|
| 企业动态 | ✅ | --- | ✅ |
| 项目动态 | --- | ✅ | ✅ |
| 迭代动态 | --- | --- | ✅ |
| 里程碑动态 | --- | --- | ✅ |
人员筛选在视图 Tab 为「全部动态」时显示,切换到个人视图(我创建的/我负责的/我参与的)时自动隐藏------个人视图已经隐含了人员过滤。
七、分组与折叠
7.1 按天 → 天内按人
动态列表默认按天分组,天标题显示「今天/昨天/日期」+ 条数标签。同一天内再按操作人分组,人员块按其最新一条动态的时间倒序排列。
ini
┌──────────────────────────────────────────────────┐
│ 今天 [12] │
│ │
│ 👤 张三 │
│ ┃ ● 创建了迭代「迭代 3 · 实时看板升级」 10:32 │
│ ┃ ● 开始了迭代「迭代 3 · 实时看板升级」 10:35 │
│ ┃ ● 纳入了工作项「用户登录优化」 10:38 │
│ ┃ └→ 迭代 3 · 实时看板升级 │
│ ┃ │
│ 👤 李四 │
│ ┃ ● 创建了需求「接口联调」 09:15 │
│ ┃ ● 更新了任务「前端适配」 09:20 │
│ ┃ 字段: 负责人 张三 → 李四 │
│ │
│ 昨天 [5] │
│ 👤 王五 │
│ ┃ ● 关闭了里程碑「V1.0 发布」 18:00 │
│ ┃ ... │
└──────────────────────────────────────────────────┘
7.2 人员块折叠
当某个人在一天内的操作超过 5 条时,默认折叠为前 3 + 后 2,中间显示折叠按钮。点击展开后显示全部操作,按钮变为「收起」。
ini
折叠态:
┃ ● 操作1 10:30
┃ ● 操作2 10:31
┃ ● 操作3 10:32
┃ [已折叠 8 条,点击展开]
┃ ● 操作11 10:45
┃ ● 操作12 10:46
展开态:
┃ ● 操作1 10:30
┃ ● 操作2 10:31
┃ ● 操作3 10:32
┃ [收起]
┃ ● 操作4 10:33
┃ ● 操作5 10:34
┃ ...(全部展示)
7.3 瀑布分页
分页采用瀑布模式(无限滚动),而非传统分页:
- 每页 20 条,追加到列表末尾
- 滚动到底部自动加载下一页(也可点击「加载更多」按钮)
- 显示「已展示 N / 总数」计数
- 加载完毕显示「没有更多了」
筛选/视图/作用域变化时重置列表,从第一页开始重新加载。
八、多入口接入
8.1 接入清单
| 入口 | 作用域 | 模式 | 筛选 |
|---|---|---|---|
| 企业动态侧栏 | 企业 | 全量 | 项目 + 人员 |
| 项目动态页 | 项目 | 全量 | 迭代/里程碑 + 人员 |
| 迭代详情动态 Tab | 迭代 | 全量 | 人员 |
| 里程碑详情动态 Tab | 里程碑 | 全量 | 人员 |
| 项目概览预览 | 项目 | 预览 | --- |
| 迭代概览预览 | 迭代 | 预览 | --- |
| 里程碑概览预览 | 里程碑 | 预览 | --- |
8.2 概览预览改造
动态模块上线后,原有的两处假动态被替换:
| 改造点 | 改造前 | 改造后 |
|---|---|---|
| 项目概览动态 | 硬编码 mock | 预览模式,取最近 6 条真实动态 |
| 迭代概览动态 | 前端拼装 | 预览模式,取最近 6 条真实动态 |
| 里程碑概览动态 | 无 | 预览模式,取最近 6 条真实动态 |
预览模式下展示扁平时间轴 + 「全部动态」按钮,点击跳转到对应的动态全量页。
8.3 企业动态侧栏
企业工作台的主侧栏在「统计」与「成员」之间新增「动态」入口,点击进入企业动态页,展示全企业的操作留痕,跨项目按时间轴聚合。
8.4 项目动态页
项目侧栏的「动态」导航项之前为占位状态(显示「模块规划中」),动态模块上线后接入真实页面,展示项目下全部子域事件,支持迭代/里程碑和人员筛选。
九、设计要点总结
javascript
┌──────────────────────────────────────────────────────────────┐
│ 动态模块设计要点 │
├──────────────────────────────────────────────────────────────┤
│ │
│ 1. 与审计日志解耦:独立活动表,面向用户体验 │
│ 摘要后端渲染落库,历史不因前端版本失真 │
│ │
│ 2. 注解+切面写入:自定义注解 + 表达式 + 事务提交后落库 │
│ 落库失败静默吞掉,不影响主业务 │
│ │
│ 3. 栈式上下文:ThreadLocal<Deque<Map>> 嵌套 Frame │
│ 内层 put 不清除外层,_skip 不影响外层 │
│ │
│ 4. Support Bean 模式:每域独立 Bean,保证代理生效 │
│ Service 调 Support,Support 带注解 │
│ │
│ 5. 三级归集:企业→项目→迭代/里程碑/知识库 │
│ 冗余列双路径:精确作用域 + 冗余迭代/里程碑 ID │
│ │
│ 6. 视图 Tab:全部/我创建的/我负责的/我参与的 │
│ 关系人字段与操作者解耦,描述用户与目标实体的关系 │
│ │
│ 7. 两种查询:分页(瀑布)+ 最新 N 条(预览) │
│ 共用 SQL 片段,条件不漂移 │
│ │
│ 8. 公共组件:ActivityFeed 统一组件 │
│ 预览/全量双模式,视图 Tab + 筛选 + 瀑布分页 │
│ │
│ 9. 分组折叠:按天→天内按人,人员块折叠/展开 │
│ >5 条折叠为前3+后2,点击展开 │
│ │
│ 10. 多入口接入:企业侧栏/项目页/迭代Tab/里程碑Tab/概览预览 │
│ 替换两处假动态,概览预览取真实数据 │
│ │
│ 11. 事件目录:迭代/里程碑/工作项/知识库/项目/测试域 │
│ v1 接入六大域,版本预留枚举暂不埋点 │
│ │
│ 12. 扩展 JSON:字段变更/纳入移出/评论摘要 │
│ 富信息渲染,容器跳转链接 │
│ │
└──────────────────────────────────────────────────────────────┘
附:测试域接入(用例 / 评审 / 计划 / 报告)
测试域四类实体沿用同一套注解 + 切面机制,新增 ActivityTestSupport 独立 Bean,作用域按实体细分,避免 ID 撞车:
| 实体 | scopeType / targetType | 冗余字段 | 主要动作 |
|---|---|---|---|
| 用例 | TEST_CASE |
projectId | 创建 / 编辑 / 新版本 / 复制 / 归档 / 恢复 / 回滚 |
| 计划 | TEST_PLAN |
projectId + iterationId + milestoneId | 创建 / 更新 / 复制 / 添加用例 / 移除用例 / 指派 / 取消指派 / 开始 / 挂起 / 继续 / 结束 / 作废 / 执行 / 修改执行结果 |
| 评审 | TEST_REVIEW |
projectId | 创建 / 更新 / 添加用例版本 / 提交评审结论 / 开始 / 挂起 / 继续 / 结束 / 作废 |
| 报告 | TEST_REPORT |
projectId | 生成 / 更新 |
三个设计要点:
- 作用域细分 :
scope_type使用TEST_*而非单一TEST,详情页可用scope_type + scope_id精确查询,且idx_act_scope_time直接复用。 - 目标可跨域 :计划内「移除用例 / 指派 / 执行」与评审「提交结论」的
scope仍属于计划/评审,但targetType + targetId指向用例。用例详情按targetType + targetId聚合,即可同时看到本用例的编辑、评审结论与执行记录。 - 报告无详情入口 :报告详情是列表页抽屉,动态只落库,在项目 / 企业动态中查看;点击报告动态会带
reportId深链到报告列表并自动打开抽屉。
新增查询参数 targetId(与 targetType 搭配)及索引 idx_act_target_time (target_type, target_id, create_time DESC);前端 ActivityFeed 增加 targetType / targetId 两个可选属性与「按业务域筛选」能力。
测试域动态当前未使用 extJson 扩展字段------摘要已自包含足够信息(如执行结果「通过/失败/受阻」、评审结论「通过/不通过」、指派人名等),均通过 SpEL 在后端渲染后落库 summary。后续若需携带字段级变更(如用例步骤对比),可复用与工作项相同的 extJson.change 结构。
附二:按天查询与逐日累积(v2)
动态流由「分页瀑布」调整为「按天查询 + 逐日向前加载」:
- 新增
GET /companies/{companyCode}/activities/day?date=YYYY-MM-DD,返回该日[00:00:00, 次日 00:00:00)的全部事件(半开区间 ,避免23:59:59.999漏数据),不分页 - 其余筛选参数(作用域 / 项目 / 人员 / 视图 / 目标 / 迭代 / 里程碑)完全复用
- 前端默认加载今天;「加载前一天数据」按钮常驻,点击后按最旧已加载日期继续向前追加一天
- 展示分三级:按天分组 → 天内按人分组 → 组内时间倒序;没有数据的日期不渲染分组
- 每条记录的操作时间
HH:mm:ss紧贴摘要文本展示(非右对齐),悬停显示完整YYYY-MM-DD HH:mm:ss - 概览预览仍走
/latest(最新 N 条),行为不变
日期边界与时区:前端发送浏览器本地 YYYY-MM-DD,后端按服务器默认时区解释为当天 00:00 至次日 00:00;部署时需保证两端时区一致。