Files
zentao-flow/prds/ai-sop-20260723-1024/dev_log.md
T

967 lines
98 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 开发交付记录(dev_log)
## 一期:zt_story_expand 加列 ai_participation_rate(2026-07-23,依据 prd_final v1.24 FR-004 / dev_plan v4.0 §2)
### 改动文件
| 文件 | 动作 | 说明 |
|---|---|---|
| codes/zentao/sql/20260724_alter_zt_story_expand_add_ai_rate.sql | 新增 | DDL(说明头+回滚+可重入 INFORMATION_SCHEMA 判断) |
| codes/zentao/src/main/java/com/sa/zentao/entity/ZtStoryExpand.java | 修改 | 加 `private String aiParticipationRate;`(紧随 aiEfficiencyCoefficient) |
| codes/zentao/src/test/java/com/sa/zentao/service/ZtStoryExpandServiceTest.java | 新增 | 回归测试 2 场景 |
### 单元测试记录
| # | 场景 | 结果 |
|---|---|---|
| 1 | 新增路径:实体带 aiParticipationRate 透传到 insert | ✅ 通过 |
| 2 | 更新路径:selectById 命中后透传到 updateById | ✅ 通过 |
执行:`mvn test -Dtest=ZtStoryExpandServiceTest` → **Tests run: 2, Failures: 0, Errors: 0 / BUILD SUCCESS**(JDK 21,tmp/jdk-21.0.2)
### 排障记录(后续跑测试必看)
1. **surefire fork 失败**(Boot Manifest-JAR / 'other' has different root,Windows+JDK21):需加 `-Dsurefire.useManifestOnlyJar=false`。建议团队在 pom.xml 固化该配置(未擅改团队构建文件)
2. **MyBatis-Plus 单测**:需 `@BeforeAll` 手工 `TableInfoHelper.initTableInfo(...)` 初始化实体缓存
3. **MP 3.5.5 saveOrUpdate 行为**:先 selectById 判断存在性再决定 insert/updateById——mock 需覆盖 selectById
### 未做(按约定)
- git 操作(分支/提交由用户处理);生产 DDL 执行(待 D2 窗口+备份);W 值与 PRD 附件上传(待 storyId)
---
## 二期开发(2026-07-23,dev_plan v4.0 §3,任务见 tasks.md)
### 后端(agent-3 实施,DT1-DT4+DT10)
- DT1:`sql/` 新增 3 个 DDL(zt_file.url、zt_meeting.url、zt_story 8 列,含说明头+回滚+可重入)
- DT2:FileTypes +6 类;实体 ZtFile/ZtMeeting/ZtStory 补字段;`POST /common/uploadBind`(上传+绑定+按类型刷新主表 url/status,非法回滚不落盘)
- DT3:`POST /zt-task/aiBatchAdd`(事务/整批拒绝/防重 skipped/status=wait/创建人 ai/estimate 映射/返回 taskIds)
- DT4:userReview 补写 activateddate(:567);`sql/20260724_insert_ai_user.sql`(可重入,MD5 默认密,注释建议改密)
- DT10 单测:**Tests run: 19, Failures: 0, Errors: 0**(UploadBindRefreshOwnerUrlTest 13 例 + AiBatchAddServiceTest 4 例 + 既有回归 2 例);编译 BUILD SUCCESS
- 遗留:鉴权未实施(必决项待用户定);uploadBind 回滚可能留孤儿文件(低危);insert_ai_user.sql 生产执行前先测试库跑
### 前端(agent-4 实施,DT5-DT8)
- DT5:新增 `components/MdPreview`(markdown-it 渲染,禁注入;**依赖需 npm i markdown-it**);uploads 组件向后兼容扩展(可切 /common/uploadBind,34 处现有调用零影响);api/base.js 补 uploadBind
- DT6:用户需求详情加「需求讨论会议」tab(懒加载+storyIds 过滤,TODO 待后端 FIND_IN_SET);顺手修复了模板引用不存在的方法 handleClick
- DT7:会议 add/editDialog 渲染 uploads(objectType=meeting);详情附件区块(操作人/时间/.md 在线查看/下载)
- DT8:研发需求详情 7 区块(需求 ID+复制 / AI 指标 12 字段 / 用例+模版查看下载 / 提交测试报告(未 pass 禁用)/ 其他文档 / 代码审查报告(轮次+状态)/ 工作日志)
- 验证:SFC 解析+模板编译+babel 全过;eslint 零新增 error
- 待联调:markdown-it 未装;uploadBind 响应结构假设;会议 pageList 前端兜底过滤;AI 指标当月匹配
### 框架侧(DT9)
- `.claude/skills/tgassist/scripts/upload_md.py`:通用上传脚本(file+objectType+objectId+reviewResult,BASE_URL 可配)
---
## DDL 测试库执行(2026-07-23,192.168.1.161/zentao_dev)
执行 5 个脚本(4 DDL + ai 账户)并逐列验证通过:
| 项 | 验证 |
|---|---|
| zt_story_expand.ai_participation_rate | ✅ |
| zt_file.url / zt_meeting.url | ✅ |
| zt_story 8 列(7 url + code_review_status) | ✅ 8/8 |
| zt_user ai 账户 | ✅ |
**教训记录**:首次用 pymysql 自写分隔器执行时,脚本内"注释里的分号"导致每个文件首个语句被静默跳过(守卫变量 @c 为 NULL → IF 走 SELECT 1 空操作)。已直接补执行缺失语句并复核。**生产执行请用标准 mysql 客户端**(脚本本身含说明头+可重入守卫,客户端执行无此问题)。192.168.3.200 库按用户指示未做任何连接/写入。
---
## 端到端冒烟(2026-07-28,8086 端口连 161 测试库)
| 项 | 结果 | 证据 |
|---|---|---|
| uploadBind(aiCodeReview+reviewResult=pass) | ✅ | code=0;zt_file.url 生成;zt_story.code_review_url 写入、**code_review_status=pass**(story 6566) |
| aiBatchAdd(devel+test 两任务) | ✅ | code=0,created=2,taskIds=[5263,5264];zt_task:status=wait、openedby=ai、estimate=1.0/0.5 |
| aiBatchAdd 幂等(重复提交) | ✅ | created=0,两任务全部 skipped |
**排障记录**:aiBatchAdd 首次冒烟报"失败",日志(F:/logs/zentao/zentao.log)显示实为 `HttpMessageNotReadableException: Invalid UTF-8`——**是 curl -d 中文未按 UTF-8 编码所致,非接口问题**。改用 `--data-binary @file.json`(UTF-8 文件)后通过。排查过程曾误排:zt_task `left` 保留字(实体已有 `@TableField("`left`")` 反引号处理)、161/200 库表结构差异(161 zt_task 列为 camelCase,与实体一致)。
8086 冒烟实例已关闭(8085 为用户自有实例,未触碰)。冒烟数据(story 6566 的审查附件 id=220、任务 5263/5264)保留在 161 测试库,可随手清理。
---
## 前端联调(2026-07-28,playwright+系统Chrome headless 真机验证)
**最终:全套 10/11 + 聚焦 4/4 通过**(唯一未过项为旧脚本的过时按钮文案定位,已由聚焦脚本验证功能正常)。验证环境:后端 8086(连 161)+ 前端 dev server 8088(代理 8086)。
### 联调发现并已修复的 BUG
| # | BUG | 修复 |
|---|---|---|
| 1 | 审查状态显示"未审"、提交按钮卡死 | 后端:ZtStoryDTO 补 8 个新字段(BeanUtils 才带得出去) |
| 2 | AI 指标区块"暂无数据"(queryByMonth 的 projectId 过滤不匹配) | 后端:新增 `GET /zt-story-expand/queryByStoryId`;前端改调该接口(api/count.js 补路径) |
| 3 | 前端读 `code_review_status`(snake)而后端出 `codeReviewStatus`(camel) | 前端 product.vue 5 处统一 camelCase |
| 4 | .md 判断只认标题后缀(冒烟文件标题无 .md 后缀) | isMd 改认 extension 字段 |
| 5 | uploadBind 的 url 用 baseUrl 绝对地址 → 跨域加载失败 | url 改存相对路径 `/zentao/img/...`(经前端源/代理可达,生产同源同样成立) |
| 6 | markdown-it v14 纯 ESM 与 webpack4 不兼容(8 编译错误) | 降级 markdown-it@12.3.2(package.json 已改) |
### 页面级验证点(截图 tmp/pw_*.png)
登录跳转 ✅;研发详情 6 区块(需求ID/AI指标实数 8.5+0.6+人员/审查报告**通过绿标**/提交测试报告**按钮可用**/工作日志/测试用例)✅;**MD 在线渲染出完整 markdown**(标题/列表/加粗)✅;用户需求「需求讨论会议」tab ✅;会议详情附件区块 ✅;冒烟任务在「关联任务」可见(郭其兵/张富斌)✅
### 给用户/运维的注意事项
- 用户 8085 实例跑的是**修复前旧代码**(重启即得修复)
- `file.baseUrl` 拓扑:uploadBind 现存相对路径,跨域问题已消;`/common/upload` 老接口仍用绝对 baseUrl(历史行为未动)
- 161 冒烟残留:zt_file 220(deleted)/221、zt_task 5263/5264、story 6566 的 expand 改写、url 字段改动
- 运行中:后端 8086(含全部修复)、dev server 8088(供点击验收)
---
## 真实点击测试(2026-07-28,playwright 真实 UI 交互,全部通过)
**研发详情页(8/8)**:登录 ✅;点「复制」出提示 ✅;**UI 上传工作日志** → zt_file(222)+zt_story.work_log_url 刷新(相对路径)✅;**UI 提交测试报告** → zt_file(223)+test_report_submit_url 刷新 ✅;卡点反例(未审需求 6565 显示"不可提交")✅
**会议链路(4/4+渲染)**:UI 新建会议(产品/类型/时间/地点/参会人/主题/3 个必填富文本)→ zt_meeting 落库 ✅;编辑弹窗上传 MD → zt_file(228) 落库 ✅;**zt_meeting.url 刷新** ✅;会议详情附件区块显示 + MD 在线渲染出内容 ✅
**本轮修复**:老式两段式上传(/common/upload+updateFile)不刷新 zt_meeting.url → ZtMeetingServiceImpl 加 `refreshMeetingUrl`(add/modify 均挂,与 uploadBind 的 refreshOwnerUrl 双通道一致)。
**测试脚本资产**(可复用回归):tmp/pw_ui_test.py(页面区块)、pw_ui_test2.py(AI指标+MD渲染)、pw_real_click.py(上传+卡点)、pw_real_click2.py(会议链路);运行器 tmp/pw-venv。
---
## 三期:绩效消费(2026-07-28 用户授权"全跑",批1+批2+前端完成)
**口径默认锁定**(decision_log 2026-07-28):总分=0~100×权重;Bug率按‰;severity 1~2 重大/3~4 普通;申诉=系统入口+人工复核;产品助理验收链补写字段。
### 批1:数据与计算基座(agent-5)
- DDL×3:zt_perf_config(uk_role_item)、zt_doc_check(uk_story_month_doc,含申诉状态流字段)、init 62 行规则(9 岗位,权重合计均=1.00)——**已执行 161:61 行生效(1 行 INSERT IGNORE 去重)**
- calculators 18 个(策略模式+linear/threshold/manual 规则):双完成率(PRD/团队)、版本计划、双 Bug 率、Bug 密度、检出率、双及时率、准时率、饱和度、代码质量(MD 头部正则解析 round/flat 双模式)、运维 4 项、双文档齐备
- 完成率接入:`GET /count/workloadRate`;月末核查 job(每月 28 日 02:00)+ `POST /count/generateDocCheck`/`docCheckAppeal`/`docCheckAppealResolve`
- FR-014 全套:五路判定+zt_doc_check 快照+扣分合并 scopeJson+申诉回滚
- 测试:44 例(PerfTestSupport 手工 TableInfo 初始化)
### 批2:报表引擎+接口(agent-6)
- PerfScoreEngine:linear(封顶/segments)/threshold 分档/manual 透传/bonus 条件/refund 连续 N 月返还
- `ZtPerfController`(/zt-perf):report(落库读/实时算)、generateMonthScore(保留人工分重算)、manualScore、appeal(scopeJson.appeals)、appealReview(overturned 回滚满分防重复)、config CRUD(admin 限定)
- scopeJson 统一结构(PerfMonthScope POJO)
- 测试:引擎 7+服务 3
### 前端(agent-7)
- src/views/perf/ 4 页面:report.vue(9 岗位 tab+总分卡+申诉/复核)、docCheck.vue(五列 ✓/✗+月度确认锁定)、manualScoreDialog.vue、config.vue(规则行内编辑+JSON 校验)
- src/api/perf.js + router/modules/perf.js 注册;eslint 0 error、模板编译全过
### 全量验证
- `mvn test`:**Tests run: 73, Failures: 0, Errors: 0 / BUILD SUCCESS**(批1 44+批2 10+一二期 19)
- 并行碰撞已对齐(zt_perf_config 实体/服务以批1 版本为准;批2 最小修复批1 文件 2 处编译错误)
### 遗留/待办
- 岗位细分(前后端 userType 同为 KFZ,resolveRole 默认 backendDev,TODO);FR-014 扣分归属(现取 story.assignedTo,待 IT 经理确认);docCheckConfirm 接口占位 TODO(前端已留);申诉 account 为空场景口径;菜单权限码需在 base_role 配置(perf-report/doccheck/config 等)后页面可见
- 待联调:启动 8086 加载三期代码 → perf 页面真实验证 + 对拍(最近月份 vs 线下 Excel)
---
## 三期联调(2026-07-28,161 环境,全部通过)
**接口**:完成率(当月无迭代 rate=0+remark 口径)✅;/zt-perf/report(backendDev 实算 total=10+auto/manual 徽标)✅;FR-014 generateDocCheck(6566 置指数 25 后:五路判定 3✓2✗ 扣 4 分,判定源正确)✅;docCheckMatrix(docs map+deduct+status 契约一致)✅;docCheckConfirm ✅。
**页面(真实浏览器验证)**:/perf/report(9 岗位 tab+总分卡+auto/manual 徽标+申诉/编辑列)✅;/perf/docCheck(6566 行 3✓2✗ 扣4 状态 pending)✅;/perf/config(规则 61 行表格+编辑)✅。
**联调修复(7 处)**:①新增 docCheckMatrix/docCheckConfirm 接口(前端契约缺数据源);②岗位 tab 中文→编码映射(report/config 页 roleList 改 label+value 双轨);③总分卡岗位显示加 roleLabel 中文映射;④report 空账号(全部人员)→ 兜底当前登录人(service);⑤controller account 参数 required=false;⑥菜单注册(base_menu 父级+3页+7按钮,授 3 角色,admin 全量自动可见);⑦dev server 重启识别新 views/perf 目录。
**注意(对拍时关注)**:空数据月份 auto 项 raw=0→score=0 的语义(如 bugDensity 扣满)需真实数据验证规则合理性;完成率分母"当月无迭代"口径待真实迭代数据验证;FR-014 扣分归集依赖 story.assignedTo(6566 无负责人故 deductByAccount 为空,符合预期但生产需关注)。
**可视化验收后调整(用户反馈)**:研发详情「需求 ID」区块+复制按钮移除(页面顶部已有 ID+标题,冗余;方法 copyStoryId 一并删)。dev_plan §3.5 已同步。
---
## 会议纪要 MD 预览修复链(2026-07-29,161 环境,实测通过)
**问题**:用户需求详情会议纪要 tab 点 MD 在线查看失败/下载 0KB;fileList 一度返回空。
**根因与修复**:
1. `CommonsController.downLoad` 硬编码 linuxFilePath → 改 OS 感知路径(Windows 下 0KB 的根因)。
2. legacy `/common/upload` 不写 url 字段 → 现在写入相对路径 `/zentao/img/...`(与 uploadBind 一致)。
3. zt_file 历史数据:234/235/236 手工补 objecttype='meeting'(老 upload 不传 objectType,靠保存时 updateFile 绑定);230/232/233 曾被 updateFile 清理逻辑标 deleted='1'(当时 objecttype 未绑定,editDialog fileList 查不到 → 视为已移除)。
4. MdPreview 组件由纯文本 pre 改为 **mavon-editor 预览模式**(只读/代码高亮/表格/引用,PM 与 F:\zd 均已装 mavon-editor@2.10.4)。
**防误删核查**:meeting editDialog 打开时 fileList(objectType='meeting') 装入 form.files(editDialog.vue:345-353),保存时 getParam 拼 id 串 → updateFile 的 notIn 清理不会误删已绑定附件。闭环安全。
**实测(8089 前端 + 8085 后端,真实浏览器)**:用户需求 324 详情 → 会议纪要 tab(会议卡 84:时间/操作人/需求会议 tag/MD 按钮齐全,tab 不再粘连)→ 点 MD → rich_demo.md 富文本渲染通过(表格/SQL 代码块高亮/引用/嵌套列表)。接口层:fileList 返回 3 条 deleted='0' 附件;GET /zentao/img/....md 200/598B(8085/8086 均通)。截图 tmp/pw_324_meeting_tab.png、tmp/pw_324_md_preview.png。
---
## 指标公式验证 + 5‰ 豁免阈值修复(2026-07-29,P0 关闭)
**验证范围**:SRC-002 新版考核 xlsx 全部 9 岗位 sheet × zt_perf_config 61 行规则 × calculators 代码,逐条对照(此前只做过单测与接口级验证,未做全量公式核对)。
**一致项(56/61 行)**:9 岗位权重合计均=1.0;linear/threshold/manual 参数与 xlsx 全部吻合,含易错点——后端代码质量 round 模式(初审严重3/错误超6扣3/复审严重5/错误1)vs 前端 flat(每问题扣3);前端饱和度 0.3 vs 后端 0.2;王宇航表无 PRD 项且稳定性 0.2;UI 三档 threshold(100/40/0);tester 线上Bug 普通扣5、重大扣100=该项0分;opsMajorTask 百分制换算=及时率×20 与 xlsx 一致(deductPerStep=1 在百分制下等价,非错误)。
**P0 差异(4 行)**:xlsx/PRD §7.3 规定线上Bug率与产品缺陷率「≤5‰ 得满分」,实现缺豁免阈值——有 1 个普通 Bug 就扣 3 分。影响 id 4(projectManager/onlineBugRate)、11(projectManagerWyh/onlineBugRate)、19(productManager/productDefectRate)、24(productAssistant/productDefectRate)。
**修复**:AbstractWeightedBugCalculator 增加 exemptPerMille 分支——分子=当月上线需求(releaseddate 当月)的 prod Bug 数,分母=当月上线需求 estimate 和,率≤5‰ 满分豁免、超才按个扣分;tester(id45,xlsx 无豁免口径)及无该参数的规则走原逻辑不受影响。4 行 rule_json 已加 `"exemptPerMille":5`(161 库 + sql/20260728_init_zt_perf_config.sql 同步)。
**单测**:BugIndicatorCalculatorsTest 新增 3 用例(1‰ 豁免满分 / 10‰ 超阈值扣 6 分 / 无上线需求边界满分),perf 包 54 个测试全绿。
**遗留(已在 PRD 标注待确认,非本次新增)**:加分项 4 条默认停用(id34/41/48/52,待 IT 经理确认口径);acceptOnTime 走 manual(zt_story_user 验收时间链断裂);AC-013-2 与线下真实考核 Excel 对拍未做(需用户提供线下 Excel/真实月份)。
---
## CHG-027 框架验收指标新字段+接口(2026-07-29,161 环境,实测通过)
**背景**:用户拍板——老验收标准(zt_storyspec.verify)不动,AI 框架验收指标走新字段+接口。
**改动**:
1. DDL:`zt_story_expand` 加 `acceptance_criteria` MEDIUMTEXT(Given/When/Then MD),161 已执行 + `sql/20260729_alter_zt_story_expand_acceptance.sql` 迁移文件。
2. 实体 `ZtStoryExpand.acceptanceCriteria` + mapper XML resultMap 补映射;service 零改动(updateById 空值不覆盖,新字段随 saveOrUpdate 自然透传)。
3. 上传通道=现有 `/zt-story-expand/saveOrUpdate`(框架指标同通道),不新增端点(避免与 saveOrUpdate 重复设计)。
**验证**:单测+1(insert 透传 acceptanceCriteria,3/3 绿);真实接口(8086)——324 上传 Given/When/Then 中文 MD → code:0,queryByStoryId 回读字段完整;6566(finished)→ 正确拒绝"该需求已完成,不可再修改";zt_storyspec.verify 确认不受影响。
**注意**:用户 8085 需重启加载本次改动(本字段 + 5‰ 豁免修复 + MdPreview/mavon 相关)。
---
## QA 测试文档生成(2026-07-29)
`06_test_docs/` 建成:test_cases.md(36 条用例:33 AC + CHG-027 补充 + TC-002-4 附件防误删回归,14 FR + CHG-027 全覆盖,含环境/账号/前置数据/覆盖矩阵/执行记录表/阻塞依赖)、defects.md、regression.md(模板待执行填充)。已知阻塞:TC-013-2 依赖线下 Excel;上传类用例前置=8085 重启加载 CHG-026/027。
---
## 研发详情上传按钮位置修正(2026-07-29)
用户反馈:4 个文档区块(提交测试报告/其他测试文档/代码审查报告/工作日志)上传按钮浮在文件列表上方 → storyinfo/components/product.vue 调整为文件列表在前、上传按钮在最后(测试用例/模版为只读区无上传钮,不动)。已同步 F:\zd,8089 热更新实测截图 tmp/pw_6566_review_sec.png 确认。另:测试用例文档(zt_file 238)已 uploadBind 挂 6566,test_case_url 刷新,下载 200/12566B(curl 中文 title GBK 乱码已 DB 修正——框架 python 上传无此问题)。
---
## AI 指标区块撤掉三个人员字段(2026-07-29,用户拍板)
productPerson/developPerson/testPerson 三字段无自动数据源(打分弹窗手填,6566 为 SQL 调试数据)→ 研发详情 AI 指标区块撤下这三项展示(storyinfo/components/product.vue,9 项保留)。**不动**:zt_story_expand 三列、打分弹窗、需求报表列(属工时统计功能);右侧基本信息的产品经理/测试人员为 zt_story 自有字段,保留。已同步 F:\zd,8089 实测截图 tmp/pw_6566_ai_block.png。
---
## 测试报告模版生成+传禅道(2026-07-29)
`06_test_docs/test_report_template.md`(7 节:概述/环境/执行汇总/36 条明细空表/缺陷统计/回归/结论签字)→ uploadBind(objectType=testReport) 挂 6566(zt_file 239,test_report_download_url 刷新,下载 200/2348B)。6566 测试类文档现状:用例✓ 模版✓ 提交件✗(待执行)其他✗。
---
## 200→161 全库复制 + zentao_dev_2026 增量 DDL(2026-07-29)
**复制**:200 zentao_dev(只读,94 表 2.6GB)→ 161 zentao_dev_2026。zt_action/zt_actionrecent 按计划只建空表;其余 92 表行数对拍全部一致;中文抽查正常。过程排障:161 元数据锁(残留事务→DROP TABLE 排队→新连接挂起),KILL 阻塞线程后恢复;max_allowed_packet=64MB 导致大字段表断连 → 脚本按 12MB 分包+断点续跑+重试(tmp/db_copy_200_to_161.py)。
**增量 DDL(用户指定只加字段不含数据)**:zt_file.url、zt_meeting.url、zt_story 7 url 列+code_review_status、zt_story_expand ai_participation_rate+acceptance_criteria 共 12 列 + zt_perf_config/zt_doc_check 两空表,幂等脚本 tmp/apply_ddl_2026.py,验证通过。**未加(属数据)**:zt_perf_config 61 行规则种子、ai 用户、绩效菜单 base_menu——跑绩效功能前需补。
---
## CHG-028 饱和度达标工时口径修正(2026-07-29)
用户发现:郭尚雨 6 月老月报 91% vs 新绩效 104%——排查为分子差异(老=分配工时 estimate、新=实绩 consumed),属口径并存(老报表不动)。另发现实现误用老系统分母(工作日×8−请假)×0.75,与 xlsx/PRD §7.3「团队总工作天数×5」不符 → 用户拍板改为 **(当月工作天数 − 请假小时÷8)×5**(半天=0.5 天),分子维持 zt_effort.consumed。WorkSaturationCalculator 已改;单测 15/15 绿(新增请假半天用例);规则配置无需改(百分比规则不变)。PRD v1.26、decision_log 已录。**注意**:8085 重启后生效;分母变小(5h/天 vs 6h/天)→ 饱和度百分比整体上升,历史月份重算分数会变高,属预期。
---
## CHG-029 老模块饱和度统一(2026-07-29,8086 实测一致)
用户拍板"再老的改"。排查发现 91/104 均为老模块(IZtCountService)两方法口径分叉:月报分子排除 closed/cancel 任务、地盘不排除。统一为新口径:分子=实绩工时(zt_task.consumed,全状态任务)、分母=(工作天数−请假小时÷8)×5。改动 IZtCountService 5 处(setUserWorkTime、buildKFZScore 分子+workTime 全集、地盘方法分母+分子、项目组汇总分子、buildXMZLScore 显示)。**8086(2026 库)实测郭尚雨 2026-06:月报列表 saturation=1.25、地盘绩效 saturation=1.25,完全一致**(131h÷105h)。注意:①老模块分子用 zt_task.consumed(131h),新绩效模块用 zt_effort(86.5h)——两表数据不一致导致老页面 125% vs 新绩效 82.4% 得分 64,属数据源差异,后续要么对齐数据源要么老页面淘汰;②8085 需用户 IDE 重编译重启生效;③前端 axios 带 Authorization 头,curl 直调需 -H "Authorization: token"("token" 头过滤器不读)。
---
## CHG-030 aiBatchAdd 工时预算校验(2026-07-29,8086 实测通过)
用户拍板"拆的任务工时不能比研发需求总工时高"。aiBatchAdd 新增预算校验:已有任务 estimate 合计 + 本批新增(dup 跳过项不计)> zt_story_expand.evaluation_time → 整批拒绝(报文明细:已有Xh+新增Yh>预算Zh);无评估工时不设防。单测+4(预算内放行/超额拒绝/已有任务计入/无预算放行,8/8 绿)。**8086 实测**:22h 已有下 12h 新增被拒(消息正确含"新增0h"重复项剔除)、22+2>10 被拒、调 30h 后 24≤30 放行(created=1+skipped 重复项)。测试数据已清理。注意:2026 库(200 镜像)zt_story_expand.evaluation_time 全列为空 → 预算校验在该库当前不触发(无预算数据),生产/老库有评估工时后才生效;8085 需 IDE 重编译重启。
---
## CHG-032 撤销禅道侧工时校验(2026-07-29)
用户明确"禅道不能做校验" → CHG-030 全部回滚:ZtTaskServiceImpl.aiBatchAdd 恢复原状(预算校验+storyExpandService 注入移除),AiBatchAddServiceTest 4 个预算用例移除(回 4/4 绿)。工时匹配纪律只在框架侧:拆任务时 Σ任务工时=需求评估工时(PRD FR-006 规则5、tgassist PJM 纪律,均已去掉"禅道兜底"表述)。8085 重编译后 aiBatchAdd 回到无校验状态。
---
## CHG-029 全量验证闭环(2026-07-29,8086 实测)
补改最后一处漏网:workDetailsCount(开发者工作统计)saturation 分子 storyTotalTime(estimate)→workTime(consumed)。四处实测(郭尚雨 2026-06,2026 库):月报(全产品集)=1.25、月报(119 中道救援)=1.09、地盘绩效=1.25、开发者工作统计(119)=1.09——公式全统一(consumed÷(21×5=105h)),109 vs 125 纯产品集筛选范围差异(119 线下 114h vs 全部 131h),与用户页面所见完全吻合。buildXMZLScore 达标工时显示同步新口径。
---
## CHG-034 达标工时团队口径(2026-07-29)
用户指出 CHG-028 实现不符 xlsx 字面("完全不是一个东西")→ 改严格团队口径。新模块 WorkSaturationCalculator 与老模块 4 处(setUserWorkTime/地盘方法/XMZL 显示/项目组汇总经 dto 传递)统一 teamExamineTime。单测 15/15 绿(新增团队平摊用例:(w×2−0.5)×5÷2)。8086 实测:2026 库 KFZ=13 人、6 月无请假 → 团队口径=(21×13−0)×5÷13=105h,地盘绩效 examineTime=105.0/saturation=1.25 一致(无请假时与个人口径同值)。**未能实测请假平摊**:os_system.it_approval 是 join 视图不可写,且 2026 全年无请假记录;单测已覆盖。**遗留口径疑点**:getApprovalTime 同日分支直接累加 apply_days(单位疑为小时,与老代码用法一致按小时/8 折算;OA 无数据可校,若实际为天需改折算);张富斌(测试)user_type=KFZ 被计入团队人数——xlsx 要求"后端+前端",若其为测试应改 user_type 或另行排除,待用户确认。
---
## 前端老口径描述改新 Excel(2026-07-29)
用户指出月报点击查看仍显示老描述。改 3 文件:performance.vue(KFZ 考核表:月度达标工时公式→团队总工作天数×5÷开发人数/请假全团队摊、数据映射 有效工时allocationTime→实际产出工时workTime;代码质量 5%→10%且规则改 xlsx 初审/复审两段;文档质量 15%→10%;不规范行为描述改 xlsx 六维度)、reportForms.vue(工作饱和度 tooltip+注释块→实绩÷月度达标工时)、monthReport.vue(列头"可用工时(6*工作天数)"→"月度达标工时",数据列 haveTime 本就是团队口径 105h)。已同步 F:\zd,8089 热更新编译通过。**注意**:地盘绩效页得分计算(saturationScore 等)仍是老规则,与页面上新 Excel 描述并存——完整新算分在 /perf/report,老页淘汰前存在此割裂,已在 PRD 7.5 标注 ❌/🔶 项。
---
## CHG-035 三期绩效页面下线(2026-07-29,用户拍板)
用户:"不需要这些页面,月报的绩效按钮就是人工评分"。2026 库删除绩效菜单 13 行+授权 37 行;恢复备份 sql/20260729_insert_perf_menu.sql(列名完整,50 INSERT)。页面代码/zt_perf_config 61 规则/zt_doc_check 保留未删。人工评分=月报「绩效」按钮(老 editDialog 流程)。8085 重新登录后菜单消失。FR-012/013/014 功能本体保留,仅入口下线。
---
## CHG-036 老弹窗得分改新 Excel(2026-07-29,8086 实测通过)
方案经用户确认后实施:utils/PerfScoreRules 纯函数(及时完成25:95段扣1/94段扣2 分段累计;Bug密度30:>15%每增1%扣3分无截断;饱和度20:<100%每减1%扣2分)+ IZtCountService.buildKFZScore 接入(punctuality/bugDensity/saturation 三分项替换,codeQuality 5→10、documentQuality 15→10、workAttitude 5 满分默认)。**弹窗路径核实**:月报 查看/绩效按钮 → performance.vue → myWorkScore → buildKFZScore(KFZ),总分由前端 sum(六得分项+两加分项)自动合成。PerfScoreRulesTest 3/3 绿(分段/截断/科学计数 BigDecimal 归一)。**8086 实测郭尚雨 2026-06**:saturation 1.25→20、及时率 1.0→25、bugDensity 4%→30、三项人工满分,总分=100,与新 Excel 逐项吻合。月报列表 DTO 不带得分字段(只展示比率列)不受影响。buildCsScore(标注"老的")无调用方,顺带对齐不影响任何页面。8085 需 IDE 重编译重启。
---
## CHG-037 老绩效弹窗全岗位改新 Excel(2026-07-30,8086 实测通过)
**背景**:CHG-036 只改了 KFZ 弹窗得分;本次把月报「绩效」弹窗其余岗位全部切到新 Excel(SRC-002)口径,岗位得分改由新绩效引擎(zt_perf_config 规则)按 score×weight 加权产出。
**后端**:
- PerformanceDTO 新增 7 字段:workloadPrdScore/workloadTeamScore/opsMajorTaskScore/opsMonitorScore/opsInspectScore/opsBackupScore/otherOpsScore。
- IZtCountService 新增 perfItemScore(scope, itemKey, default):按岗位 itemKey 从 perfReportService.report 取加权得分;指标无数据/人工项(score=null)给满分默认。
- buildXMJLScore(项目经理)重写:PRD完成率20/团队完成率30/版本计划10/线上Bug10/文档齐备10/问题管理5/稳定性10/技能5;王宇航按 account 走 projectManagerWyh 变体(无 PRD 项、团队40、稳定性20);旧 programCount/任务管理/Bug管理/会议管理 附加计算废弃。
- buildCPJLScore(产品经理):PRD完成率40/团队完成率20/项目准时率10/产品缺陷率15/问题响应10/主动性5;展示字段(计划/准时上线数、严重/普通 Bug 数)保留原取数。
- buildXMZLScore(产品助理):PRD完成率50/及时验收20(人工默认满分,zt_story_user 验收链断裂维持人工)/产品缺陷率15/问题响应10/主动性5。
- buildYwScore(运维,新增方法+UserType.YW 调度分支):大项任务20/监控15/巡检10/备份10 走引擎(opsEngineer 4 项 calculator),其他运维15/稳定性20/不规范行为10 人工满分默认。
- buildCScore(测试)及时完成改 PerfScoreRules.testerPlanScore(=100%得20,每减1%扣2分);buildUiScore 改 uiPunctualityScore(=100%得50/90%+得40/<90%得0)。
**前端**(performance.vue,已同步 F:\zd\web_zentao):XMGLY/CPJL/XMZL 三区块按 xlsx 全量重写(行/权重/评分标准/得分说明逐字对齐 SRC-002);新增 YW 区块(含创新贡献加分项);新增王宇航变体块(account 判断先于 userType switch);juedgeRole 加 YW;各区块总计 amountTo 同步新得分字段。
**验证**:
- 单测:PerfScoreRulesTest +2(testerPlan/uiPunctuality 分段边界,5/5 绿);perf 包+Ops/Bug 计算回归 33 绿。
- 8086(2026 库)myWorkScore 六账号实测:王宇航 workloadTeamScore=35.6、孙世超 26.7、魏冬霞 workloadTeamScore=15.6/productBugRate=15、李语嫣 releaseScore=20/productBugRate=15、岑海峰 opsMonitor=12.75/opsInspect=7.5/opsBackup=9.7/otherOps=15、刘圣清 designScore=40/workAttitude=10——各岗位得分字段均按新口径产出。
- 8089 弹窗截图四岗位通过:王宇航(tmp/pw_chg037_wangyuhang.png,总分 85.6)、蒋恒·项目经理(tmp/pw_chg037_jiangheng.png,总分 66.7)、李语嫣·产品助理(tmp/pw_chg037_liyuyan.png,总分 50)、刘圣清·UI(tmp/pw_chg037_liushengqing.png,总分 50)。
**注意/遗留**:
1. 8085 需用户 IDE 重编译重启生效;本次验证用 8086(已含本改动)+ 8088(8089 dev server 默认端口 8088,临时以 VUE_APP_BACK_REST_URL=8086 启动,未改 .env.local)。
2. CPJL(魏冬霞)/YW(岑海峰)在 2026 库 2026 全年无任务,月报列表不出行,弹窗未截图;两岗位得分字段已经 8086 API 实测,前端结构经语法+字段绑定核对。
3. 版本计划完成率多人为 0:2026 库版本发布数据稀疏,引擎按实数算出 0(非默认值缺失),生产数据下另行观察。
4. 人工评审项(其他运维/稳定性/不规范行为/问题管理/技能等)满分默认,IT 经理弹窗手改后提交,老流程不变。
---
## CHG-038 KFZ 前后端工程师分流(2026-07-30,8086 实测通过)
**背景**:用户拍板——新 Excel 前端/后端工程师是两张表(前端:饱和度30%、无文档质量项、代码质量 flat 每问题扣3;其余逐项相同),系统 user_type 只有 KFZ 无法区分 → 加「开发方向」标识,用户拍板维护入口=用户新增/编辑表单下拉。
**DDL**:`zt_user` 加 `dev_direction` varchar(16)(frontend=前端/backend=后端,NULL 按后端口径,仅 KFZ 有效),161 zentao_dev+zentao_dev_2026 已执行 + `sql/20260730_alter_zt_user_dev_direction.sql` 迁移文件。
**后端**:
- ZtUser/ZtUserDTO 加 devDirection;addUser 非 KFZ 置空、modifyUser 同步 setter(非 KFZ 置空);pageList/登录返回自然带出。
- PerfScoreRules.saturationScore 参数化满分(rate, full),新增 FULL_SATURATION_FRONT=30;原 20 满分重载委托保持 CHG-036 行为。
- buildKFZScore 分流:frontend → 饱和度满分 30、文档质量项不设(DTO 初始 0,前端表无此项)、devDirection 透出;backend/NULL → 原口径不变。PerformanceDTO 加 devDirection。
**前端**:
- 用户新增/编辑弹窗(user/dialog/addDialog.vue、editDialog.vue):用户属性=开发者时出现「开发方向」下拉(前端/后端,必填校验仅 KFZ 生效);编辑经 leftCopy 自动带出已存值。
- performance.vue:KFZ case 按 isFrontDev()(优先 myWorkScore DTO.devDirection,其次行数据/登录用户)分流两个区块——前端块:饱和度30%、无文档质量行、代码质量 flat 描述、amountTo 剔除 documentQualityScore;后端块维持原样;getMyWorkScore 拿到 DTO 后重建表格保证方向准确。已同步 F:\zd\web_zentao。
**验证**:
- 单测 PerfScoreRulesTest +1(前端饱和度 30/20/0 边界+默认 20 兼容,6/6 绿)。
- 8086(2026 库)实测:郭尚雨临时标 frontend → myWorkScore 返回 devDirection=frontend、saturation 1.25→**saturationScore=30**(后端口径应为 20)、documentQualityScore=0(不计);弹窗截图 tmp/pw_chg038_guoshangyu_front.png——饱和度 30% 得 30、无文档质量行、代码质量 flat 描述、总分 100。金亮(NULL)对照截图 tmp/pw_chg038_jinliang_backend.png——后端块不变(文档质量行在、初审/复审描述)。用户编辑弹窗截图 tmp/pw_chg038_user_form.png——开发者属性下出现「开发方向」下拉且正确带出「前端」。测试后郭尚雨 dev_direction 已复位 NULL。
- myWorkScore 注意:zt_month_score 有已存快照的月份返回快照不重算(既有行为),分流只对未保存月份生效。
**待办**:现有 KFZ 人员 dev_direction 全 NULL(=后端口径),等用户提供前后端名单后一次性 SQL 初始化。
---
## CHG-037 补测:CS 测试工程师(2026-07-30,8086 实测通过)
首轮验证漏掉 CS 分支,补测:API——孙庆方 2026-06 及时率 96%→punctualityScore=12(testerPlanScore 20−4×2,CHG-037 新口径生效)、文洋洋 80%→0、检出率 29%/53%→bugFindScore=30、无线上 Bug→bugScore=20、测试文档 25/不规范行为 5 人工满分默认;弹窗截图 tmp/pw_chg037_cs_sunqingfang.png(五项得分 12/30/20/25/5、总计 92 与 API 一致)。admin(GSGC)API 确认走 buildXMJLScore 项目经理口径。**注意**:CS 分支 myWorkScore 响应约 8~10s(getBugFindScore 重查询,既有行为非本次引入),弹窗需等待数据返回;首轮截图空数据即等待不足所致,非缺陷。至此 9 张岗位表全部实测覆盖。
---
## CHG-038 前后端名单初始化(2026-07-30,用户拍板)
用户提供名单:**前端=周林芳、张富斌、孟冉**,其余 KFZ 一律后端。两库已刷:zentao_dev 前端 3/后端 13、zentao_dev_2026 前端 3/后端 10(含原 NULL 全部补齐 backend,无 NULL 遗留)。张富斌 CHG-034 遗留疑点一并关闭——确认为前端开发(维持 KFZ,不改 CS)。8086 实测周林芳(6 月 139%)弹窗=前端块:饱和度 30% 得 30、无文档质量行,截图 tmp/pw_chg038_zhoulinfang.png。
---
## 月报出行机制澄清 + 运维入口解决(2026-07-30,用户拍板"找个迭代加一下")
**机制定论**(修正 CHG-037 遗留#2 的表述):月报列表=产品集→项目→执行(zt_executionproject)→过滤「begin 或 end 落在当月」的执行→取执行团队成员(zt_team)。三点推论:①产品经理挂在执行团队里就会出行,**跟有无任务无关**——魏冬霞 6 月不出行只是因为她在 139 飞侠车服而非当时查看的 119,切到 139 即在列(弹窗实测 45.6 分:团队15.6/缺陷15/响应10/主动5/准时0——计划45上线32);②长期迭代(如 146 代驾主流程 2025-02~2027-03)begin/end 永不落当月 → 成员任何月份都不出行(既有逻辑,未动);③生产 161 当前(2026-07)无任何 begin/end 落 7 月的执行,月报 7 月暂空属数据现状。
**运维入口**:岑海峰两库原本 0 任务 0 团队。按用户拍板:zentao_dev_2026 加入 车服-20260730(307,7/6-7/30 窗口内)→ 7 月 139 列表出行,YW 弹窗实测总分 74.8(监控12.3/巡检7.5/备份10/其他15/稳定20/行为10),截图 tmp/pw_yw_cenhaifeng.png;zentao_dev(生产)同步加 146(占位,窗口外不出行,待 8 月新迭代建立后把运维加进当月迭代即可)。**至此 9 张岗位表弹窗全部实测通过**(CPJL=魏冬霞 tmp/pw_cpjl_weidongxia.png、YW=岑海峰)。
---
## CHG-039 workloadRatePrd 人员匹配修复(2026-07-30,8086 实测通过)
**发现**:用户质疑"魏冬霞 6 月工作量指数为 0 对吗"→ 排查:WorkloadRatePrdCalculator 按 `product_person LIKE account` 过滤,但该列实际存**中文姓名**("魏冬霞",多人逗号分隔如"蒋恒,李淑敏")→ 恒不匹配,分子恒 0 → 项目经理/产品经理/产品助理的 PRD 完成率得分恒 0(假"未达标")。
**修复**:scopeStoryIds 改按昵称匹配(userService.getByAccount→nickname),account 兜底(未来写英文账号也兼容)。单测 +1(昵称路径+验证 getByAccount 调用;account 兜底由原用例覆盖),WorkloadRateCalculatorsTest 5/5 绿。
**8086(2026 库)实测**:魏冬霞 workloadPrdScore 0→**40**(6 月指数 314.03÷105=299% 满分);孙世超 0→**20**(满分);李语嫣仍 0——她两库 expand 都是 0 行(无任何需求把 product_person 写成她),属数据缺失非匹配问题,若业务上 PRD 归她需补 product_person 数据。
**注意**:8085 需再次重编译重启加载本修复;生产 zentao_dev 的 zt_story_expand 仅 6 行(含"产品""张三"等脏数据),PRD 完成率指标要等评估流程把 product_person 写起来才真正可用。
---
## 0 分专项排查 + CHG-040 opsMajorTask 匹配修复(2026-07-31)
**背景**:用户要求"所有得分为 0 的认真检查"。对 9 个代表账号(2026 库,2026-06)逐项下钻,分类定论:
| 得分项 | 账号 | 判定 |
|---|---|---|
| UI 任务及时 punctualityScore=0 | 刘圣清 | 真 0(6 月无任务,规则内) |
| 版本计划 versionPlanFinishedRate=0 | 孙世超/王宇航 | **口径问题**:6 月发布需求 123 个但 estimate 全 0/NULL → 分母 0 → percent() 按 0% 扣分;非"没按时发布"。待用户拍板(补 estimate / 分母 0 按个数算 / 给满分豁免 / 维持) |
| 项目准时率 productProjectOnTimeRateScore=0 | 魏冬霞 | 真 0(计划 45 准时 32=71%,<90% 每减 1% 扣 2 → 扣完) |
| PRD 完成率 workloadPrdScore=0 | 李语嫣 | 数据缺失(无需求 product_person 写她名,两库均 0 行) |
| 大项任务 opsMajorTaskScore=0 | 岑海峰 | **bug**:zt_yw_task.belong_to_user 存中文姓名按 account 匹配恒空(CHG-039 同类) |
**CHG-040 修复**:OpsMajorTaskCalculator 按昵称匹配(注入 IZtUserService,and 嵌套 OR+final 变量),account 兜底;单测+1(OpsCalculatorsTest 9/9 绿)。8086 实测:6 月=0(真 0,1 任务未完成)、7 月=**13.2**(3 任务 2 及时→66 分×0.2,与手算一致)。zt_yw_fwqsearch/patrol/backups 三表经核实存 account,监控/巡检/备份三项不受影响。
**8085 需再次重编译重启**(本修复+CHG-039)。
---
## CHG-041 绩效弹窗「绩效数据」列补过程值(2026-07-31,8086 实测通过)
**背景**:用户要求"所有人的绩效数据那一列给值(分子分母等)"——CHG-037 各岗位弹窗的绩效数据列大量留空,得分看不到依据。
**链路**:计算器(ThreadLocal rawDetail,compute 入口清除防串)→ PerfIndicatorCalculator.consumeRawDetail(接口默认 null)→ ZtPerfReportServiceImpl.computeScope 收集并挂到 PerfMonthScope.Item.rawDetail(随 scopeJson 落库快照也带)→ IZtCountService.fillRawDetail 拷入 PerformanceDTO.perfRawDetail(buildXMJL/CPJL/XMZL/YW 四方法)→ 弹窗模板:data 绑定值以 `#itemKey` 开头时渲染 dataObj.perfRawDetail[itemKey](无数据显示 —,rawDetailOf 方法)。
**各指标明细格式**:工作量指数 "Σ指数 X / 达标 Yh = Z%";版本计划 "按时 Xh / 总发布 Yh = Z%(发布 n 个)";线上Bug/缺陷率 "Bug n 个(重大 x/普通 y)/ Σ工时 Yh = Z‰(豁免线 5‰)"(非豁免口径="按个扣分");项目准时率 "准时 x / 规划 y = Z%";运维大项 "及时 x / 到期 y = Z%";运维周频次 "实做 x / 应做 y(缺 z 次)";文档齐备 "缺失 n 份 × 扣 x 分 / 缺失 0 份 / 当月无核查记录"。
**弹窗绑定**:XMGLY/wyh/CPJL/XMZL/YW 五区块 19 行挂上明细(线上Bug 行原绑定的 普通/重大BUG数量(后端不赋值恒 0 误导)一并替换为明细;CPJL 准时率/缺陷率保留原展示字段追加明细)。CS/KFZ/UI 区块本就有 DTO 实值,不动。
**验证**:单测 63 全绿(rawDetail 调用不影响既有断言);8086 实测——孙世超 workloadRatePrd "Σ指数 242.8 / 达标 105h = 231.24%"→20、workloadRateTeam "Σ指数 1076.53 / 达标 1365h = 78.87%"→26.7、versionPlanRate "按时 0h / 总发布 0h = 0%(发布 123 个)"→0(估算口径问题直接可见);蒋恒弹窗截图 tmp/pw_chg041_jiangheng.png 五行明细全渲染。
**注意**:8085 需重编译重启(含 CHG-039/040/041 三批);老快照月份(zt_month_score 已存)明细为空显示 —,属正常。
---
## CHG-042 项目经理 PRD 完成率改团队口径(2026-07-31,用户拍板)
**背景**:用户指出"孙世超是项目管理员,他的(PRD 完成率)不是他一个人的,是项目所有人"——xlsx 项目经理表 PRD 完成率与团队完成率同公式(分母"团队可用工作天数×5"、"除测试人员外其他岗位都作为工作量产出方纳入统计"),个人口径理解有误。
**改动**:WorkloadRatePrdCalculator 按岗位分流——projectManager/projectManagerWyh:范围=全部需求(不按 product_person 过滤)、分母=工作天数×5×产出人数(devProducerCount,KFZ 全员);产品经理/产品助理维持个人口径(product_person 昵称匹配+个人工时)不变。
**验证**:单测+1(团队口径不过滤+分母乘人数+不查 expand,6/6 绿);8086 实测 6 月——孙世超/蒋恒 workloadPrdScore 20→**15.6**(Σ指数 1076.53/达标 1365h=78.87%,每减 1% 扣 1 → 78×0.2),魏冬霞(产品经理)40 不变(个人口径 299.08%),李语嫣 0 不变(个人口径无数据)。
**注意**:8085 需重编译重启(含 CHG-039~042 四批)。
---
## CHG-043 项目经理两项完成率改项目口径(2026-07-31,用户拍板"按照迭代来")
**背景**:CHG-042 把项目经理 PRD 完成率改成全部门口径(分母=全部 13 KFZ)后,用户拍板应按"他下面的开发"算——即他当月窗口内参与的迭代(执行)成员。
**口径**:项目经理(含王宇航变体)的 workloadRatePrd 与 workloadRateTeam 两项统一为项目口径——
- 分子 = 他**当月窗口内**(迭代 begin 或 end 落当月,与月报列表过滤同一约定,长期迭代不算)参与的执行 → 关联产品的需求 workload_index 和;
- 分母 = 工作天数×5×**这些执行的 KFZ 成员去重数**(测试不计;他本人 XMGLY 非 KFZ 天然不含);
- 无在窗执行 → 分子 0/分母 0 → 该项 0 分。产品经理/助理维持个人口径、产品/其他岗位的"团队完成率"维持部门口径不变。
**实现**:AbstractWorkloadRateCalculator 新增 projectExecs/projectScopeStoryIds/projectProducerCount 三方法(team→execution→project→product→story 链),producerCount 钩子加 month 参数;Prd/Team 两计算器按 isProjectManager 分流。单测重写 1 例(项目口径全链路 mock+不查 expand 断言),6/6 绿。
**8086 实测 6 月**:孙世超 Σ556.83/525h(5 人)=106.06% → PRD 20/团队 30 双满分;蒋恒 Σ519.7/945h(9 人)=54.99% → PRD 10.8/团队 23.1;王宇航 Σ0/630h=0% → 按规则 50 分×0.4=20(项目当月无产出记录,非满分豁免);魏冬霞(产品经理)不变。
**注意**:8085 需重编译重启(CHG-039~043 五批);蒋恒/孙世超人数差异源于各自在窗执行不同成员集;代码窗口约定(begin/end 落当月)不含跨月长期迭代,与月报列表一致。
---
## CHG-044 达标工时全链路上弹窗(2026-07-31,8086 实测通过)
**背景**:用户要求"分子分母都要列出来"——KFZ 弹窗工作量饱和度行原来只有 实绩/人均达标工时/饱和度,看不到团队口径的中间量。
**改动**:PerformanceDTO +3 字段(teamWorkDays 团队总工作天数·人天、teamLeaveDays 团队请假折算天数、teamTargetTime 团队达标总工时);IZtCountService 新增 fillTeamExamine(setUserWorkTime 调用,KFZ/CS/UI/XMJL 链路全覆盖),teamExamineTime 与请假折算抽取 teamLeaveDays 共用;performance.vue 两个 KFZ 块饱和度行绑定补齐五行。
**展示效果**(郭尚雨 6 月):实际产出工时 131 / 团队总工作天数 273 / 团队达标总工时 1365 / 月度达标工时 105 / 工作饱和度 125% → 得分 20。截图 tmp/pw_chg044_guoshangyu.png。8086 API 同值验证;单测无回归(Misc/PerfScoreRules 21 绿)。8085 需重编译重启。
---
## CHG-045 版本计划完成率改工作量指数加权(2026-07-31,用户拍板"workload_index 用这个")
**背景**:版本计划完成率原按 zt_story.estimate 加权,123 个 6 月发布需求 estimate 全 0 → 分母 0 → 孙世超/王宇航该项恒 0(假"未达标");用户拍板改用 zt_story_expand.workload_index。
**改动**:VersionPlanRateCalculator 加权源 estimate → expand.workload_index(String 列,parseIndex 非数字/空按 0;无 expand 行自然不进分子分母);明细改"按时 X / 总发布 Y(指数加权,发布 n 个)= Z%"。单测改写+新增各 1(指数加权正常值、无指数分母 0 边界),Misc 16/16 绿。
**8086 实测 6 月**:孙世超 versionPlanFinishedRate 0→**5.4**(按时 477.1/总 658.21=72.48% → 100−23×2=54 → ×0.1)。覆盖说明:123 个发布需求仅 34 个有 expand 指数,无指数需求按 0 权重不进分子分母(占比失真风险随评估流程覆盖率提升自然消解)。8085 需重编译重启。
---
## CHG-046 《AI项目文档更新记录》独立承载全链路(2026-07-31,用户拍板"加字段+功能完善+前端展示")
**背景**:五类文档中仅《AI项目文档更新记录》无独立承载(原设计寄身 aiWorkLog 的 doc_update 类,从未产出,全库零命中)。
**改动**:
1. DDL:zt_story 加 `ai_doc_update_url` varchar(512),161 两库已执行 + `sql/20260731_alter_zt_story_doc_update.sql`。
2. FileTypes 增 `aiDocUpdate("aiDocUpdate","AI项目文档更新记录")`;uploadBind(refreshOwnerUrl) 增该类型→刷新 zt_story.ai_doc_update_url;ZtStory 实体加字段(MP 自动映射,无需 XML)。
3. FR-014 核查判定改通道:DOC_DOC_UPDATE 由"zt_file(aiWorkLog) doc_update 类"改为 **zt_file(aiDocUpdate)**,detail 同步;DocCheckServiceTest 断言更新(4/4 绿)。
4. 前端 storyinfo/components/product.vue 研发需求详情新增《AI项目文档更新记录》区块(工作日志与交付物之间):文件列表+上传按钮(aiDocUpdate),aiDocUpdateFiles+fileFieldMap+fetchObjectFiles 三处接线。已同步 F:\zd。
**8086 全链路实测**:multipart 上传测试 MD 到 6566 → code:0(zt_file 8799)→ zt_story.ai_doc_update_url 刷新 → fileList 返回该文件(注意:fileList 无 @RequestBody,必须 form 表单传参,JSON 体不绑定)→ 6566 详情页新区块渲染文件+上传按钮(截图 tmp/pw_chg046_6566.png)。curl 上传中文 title GBK 乱码已 DB 修正(已知 curl 老问题,框架/浏览器上传无此问题)。**8085 需重编译重启**。
**说明**:①快照/实时判定之争本轮不动(用户问的是承载);②框架侧生产 doc_update 内容仍待 DT9 挂钩点补齐(现以手动上传为主);③zt_doc_check 六月快照范围不含 6566(其月工作量不在 6 月),核查翻牌效果待真实大型需求上传后自然呈现。
---
## CHG-047 文档齐备改实时字段判定+项目口径(2026-07-31,用户拍板"需求的 url 字段直接判断")
**背景**:①快照归属错位——项目经理"文档齐备"按 assignedTo 归集,孙世超项目 4 个大型需求五类全缺(20 份),扣分却挂在 luoyong/sunying(其考核表无此项),孙世超反显满分;②用户拍板不要快照表/月末 job,直接读需求 url 字段实时判。
**改动**:DocReadyScoreCalculator 重写(继承 AbstractWorkloadRateCalculator 复用 CHG-043 项目口径取数)——
- 判定:大型需求(当月有指数记录且指数>20)的 **zt_story 五个 url 字段**(testCaseUrl/testReportSubmitUrl/aiDocUpdateUrl/codeReviewUrl/workLogUrl)非空即在,缺失 n 份 × 扣 2 分扣完截止;
- 归属:projectManager/projectManagerWyh ∩ 他当月窗口内执行关联产品的大型需求;其他岗位=全量大型需求;
- 明细:"大型需求 m 个,缺失 n 份(8930缺[用例,报告,更新记录,审查,日志] …)";
- 不再读 zt_doc_check 快照(表与手动触发接口保留,矩阵页已下线);TestDocReadyCalculator(CS 测试文档项)不动。
**验证**:单测改写 2 例+新增 1 例(项目口径缺 2→96/无指数记录→100/无在窗执行→100),Misc 17/17 绿。8086 实测 6 月:**孙世超 满分 10 → 6**(4 个大型需求×5 类全缺=20 份×2=扣 40,明细逐需求列出缺失类型);王宇航 10(项目范围当月无大型需求)。8085 需重编译重启。
**后续提醒**:zt_doc_check 快照表与 generateDocCheck 接口已成摆设(仅矩阵页用,已下线),可择机清理;异议流程随快照一并闲置。
---
## CHG-048 PRD 完成率项目口径扩到产品经理/助理(2026-07-31,用户拍板"跟项目管理员一样的方案")
**背景**:魏冬霞 PRD 完成率原按个人口径(product_person 名下 314.03/105h=299.08%),用户指出 xlsx 该公式与项目管理员同文字("团队可用工作天数×5"、"除测试外都纳入统计"),应同方案。核实:她与孙世超同属车服团队(在窗执行同为 286/297/300/301 → 产品 150)。
**改动**:WorkloadRatePrdCalculator 项目口径分支由 projectManager/projectManagerWyh 扩到 productManager/productAssistant(isProjectScopedRole 四角色统一:范围=当月窗口内执行关联产品的需求、分母=执行内 KFZ 成员数×天数×5);product_person 个人口径保留为其余角色兜底(实际已无使用者)。团队完成率(workloadRateTeam)维持 CHG-043 不变(项目经理=项目口径,其余=部门口径)。
**验证**:单测默认角色改 backendDev(个人兜底路径保持覆盖)+新增 CPJL 项目口径用例,WorkloadRate 7/7、Misc 17/17 绿。8086 实测 6 月:魏冬霞 314.03/105(299.08%) → **556.83/525h=106.06% → 40 满分**(与孙世超同数据源,数值收敛合理);李语嫣 0 不变(她项目产品 145 当月无指数记录,属数据缺失);孙世超不变。
**注意**:①李语嫣的 0 根因=产品 145 无工作量数据(非口径);②四角色的 PRD 完成率与团队完成率现在数据源差异=项目 vs 部门,xlsx 两行得以区分;③8085 需重编译重启。
---
## CHG-049 版本计划完成率改项目口径(2026-07-31,用户拍板"孙世超是飞侠的为啥不区分")
**背景**:versionPlanRate 原全表统计(145/150/161 三产品混算 72.48%),且指数覆盖严重不均(150 占 30/34 权重、145 道路救援 72 个发布仅 1 个有指数)——孙世超是飞侠车服项目经理,应按其项目产品区分。
**改动**:VersionPlanRateCalculator 继承 AbstractWorkloadRateCalculator 复用 CHG-043 项目口径:projectManager/projectManagerWyh 只统计他当月窗口内执行关联产品的发布需求(其余角色=全表兜底,当前无使用者);指数加权逻辑(CHG-045)不变。单测版本正常用例补项目 mock(Misc 17/17 绿)。
**8086 实测 6 月**:
- 孙世超 5.4→**9.4**:按时 477.1/总发布 516.61(发布 38 个·产品 150)=92.35%,每减 1% 扣 2 → 94×0.1
- 王宇航 0:按时 0/总发布 33(发布 72 个·产品 145 道路救援)=0%——他项目是道路救援,72 个发布仅 1 个有指数(权重 33 且未按时),覆盖率不足致其版本率失真(单需求决定 100%)
**注意**:145 产品线指数覆盖率 1/72,王宇航的版本率在该产品评估流程跑起来前不可用于考核;8085 需重编译重启。
---
## CHG-050 Bug 率 5‰ 豁免复活:分母改任务工时+项目口径(2026-07-31,用户拍板"需求工时是任务sum")
**背景**:线上Bug率/产品缺陷率的 5‰ 豁免分母原取 zt_story.estimate(全库未填)→ 率恒 0‰ 恒豁免,用户在车服加 6 月线上 Bug(zt_bug 2566,普通,挂 8277)验证发现扣分不触发。
**改动**(AbstractWeightedBugCalculator 继承 AbstractWorkloadRateCalculator 复用项目口径):
1. 分母 zt_story.estimate → **当月上线需求的 devel 任务 estimate 合计**(用户拍板"需求工时是任务sum");
2. 四角色(项目经理/王宇航/产品经理/产品助理)上线需求范围 ∩ 当月窗口内执行关联产品(同 CHG-043 项目口径);
3. 无上线需求 → 满分并注明(项目范围)。
**验证**:单测 exempt 两例改任务工时 mock+项目 mock(Bug 12、Workload 7、Misc 17 全绿;排障一例:mock 执行时间跨月末边界致项目范围为空)。8086 实测 6 月(测试 Bug 2566 在库):孙世超 **9.7**(1 普通/165.5h=6.04‰>5‰ → 扣 3 → 97×0.1,明细"Bug 1 个(重大 0/普通 1)/ Σ工时 165.5h = 6.04‰");王宇航 10(项目 0 Bug/275.5h 豁免);魏冬霞产品缺陷率 **14.55**(同 Bug,97×0.15)。
**注意**:①测试 Bug id=2566 标题含"【测试】…可删",影响孙世超/魏冬霞 6 月该项得分,不要时直接删行即可;②150 单产品 165.5h 的分母较小,1 个普通 Bug 即破 5‰ 线——项目口径下该指标对小团队偏敏感,属口径本身特性;③8085 需重编译重启。
---
## CHG-051 引擎扣分统一为加权尺度(2026-07-31,用户拍板"10分满分 10-2")
**背景**:用户质疑"缺 20 份为啥还是 6 分"——引擎原按 100 分制扣分再 ×权重(扣分量只有 xlsx 字面 1/10 效果),与 KFZ(CHG-036 起即加权尺度)两套尺度并存。
**改动**:AbstractPerfIndicatorCalculator 新增 scaleDeduct——配置权重注入 rule(`__w`),扣分按 1/权重 放大到 100 分制再扣(最终 ×权重=xlsx 字面加权扣分);接入 applyLinear(全部 rate 类)、perBugScore(Bug 类)、OpsCount(运维周频次)、DocReady(文档齐备)四处扣分点;threshold 分档与 PerfScoreRules(KFZ/CS/UI)本就加权尺度不变。**结果对齐 xlsx**:10 分项缺 1 份=扣 2(10−2=8),缺 20 份=扣完=0。
**单测**:新增加权用例 3(docReady 缺 2→60、Bug 超线 2 普通→40、监控缺 2→60),全量 93 绿(旧用例配置无 weight 不走缩放,行为不变)。
**预期效果(孙世超 6 月,手算)**:文档齐备 6→**0**(20 份×2/0.1=400 扣完);线上Bug 9.7→**7**(3/0.1=30→70×0.1);团队完成率 26.7→**19.0**(11/0.3=36.7→63.3×0.3);版本计划 9.4→**4**(6/0.1=60→40×0.1);PRD 完成率 20(满分项不受影响)。
**实测状态**:8086 重启时 161 数据库 Too many connections(共享开发库连接耗尽,HikariCP checkFailFast;pymysql 同样 1040),待连接释放后补实测。**8085 需重编译重启**。
---
## CHG-053 绩效弹窗跟随月报选中产品集(2026-07-31,用户拍板"按照当前选择产品")
**背景**:用户拍板公式"按理说都是根据某个产品来算的"——弹窗不再只按本人项目,而跟随月报下拉选中的产品集。
**链路**:monthReport.vue 把 `dataForm.project`(下拉选中的 program id)→ editDialog `:program` → performance.vue `program` prop → myWorkScore 请求加 `project` 参数;后端 IZtCountService.myWorkScore:`project` 非空时 pids=该 program 的产品集(替代本人授权产品),并在调度分支外裹 `AbstractPerfIndicatorCalculator.setCurrentProgram/clearCurrentProgram`(try/finally);AbstractWorkloadRateCalculator 的 projectScopeStoryIds/projectProducerCount 优先走选中产品集(新增 currentProgramProductIds/execsOfProducts,选中时不再要求本人是该迭代成员),null 时回退 CHG-043 本人路径。影响范围:任务/需求取数(pids)+ 引擎全部项目口径指标(工作量/版本/Bug率/齐备)。
**验证**:单测 93 全绿无回归。**8086 API 实测**(孙世超 6 月):program=139 → prd 20/team 30(556.83/525h=106.06%)、vp 4(92.35%)、bug 7(6.04‰)、doc 0;program=119 → prd/team 0(Σ0/630h)、vp 0(72 发布仅 33 权重按时 0)、bug 10 豁免、doc 10(无大型需求)——同一人两套分随切换。**8089 UI 实测**:下拉 139 弹窗含 556.83/525h/92.35%(截图 tmp/pw_chg053_139_jun.png);119 无本项目数据。已同步 F:\zd。
**注意**:①快照月(zt_month_score 已存)仍返回旧存值;②8085 需重编译重启+前端发版;③附带修正 playwright 脚本月份控制(直填月份输入框替代「上月」按钮)。
**CHG-053 补充(同日)**:用户实测发现魏冬霞在 139 下团队完成率仍显 1365h——WorkloadRateTeamCalculator 的项目口径分支只开了项目经理 → 同步改 isProjectScopedRole 四角色(CHG-052 的正确归位,随"按当前选择产品"生效)。复测:魏冬霞 program=139 → 团队完成率 1365h/78.87%/0 → **525h/106.06%/满分 20**;program=119 → 0(Σ0/630h)。WorkloadRate 7/7 绿。
---
## CHG-054 CS 测试需求范围修正:assignedTo ∪ expand.test_person(2026-07-31,用户拍板"先修复")
**背景**:孙颖缺陷检出率恒 0 排查——当前测试需求范围仅 zt_story.assignedTo(她 6 月 3 个),而 zt_story_expand.test_person 指定她测的 6 月有 24 个(其中 21 个 assignedTo 是开发);全量 134 个指定需求中 assignedTo 是她的仅 12 个,assignedTo 口径严重漏算。
**改动**:IZtCountService 新增 testStoriesOf(注入 IZtStoryExpandService,test_person 中文姓名 like 匹配,assignedTo 池∪expand 指定,均按产品+releaseddate 当月过滤);三处 buildCScore 调用点(newPerformanceCount/programCount/myWorkScore 的 CS 分支)统一替换原 assignedTo 二次过滤。
**8086 实测(孙颖)**:6 月 检出率 0.0%(24 个需求已纳入计算、devSlightBug=0,真无检出,此前是"取不到数不算");**5 月 检出率 48%(12 个普通 Bug)→ bugFindScore 满分 30**(修复前恒 0)。其余 CS 账号同享修正。8085 需重编译重启。
---
## CHG-055 检出率得分不为空(2026-07-31,用户拍板"得分不能为空 要么为0")
getBugFindScore 三条空值路径统一显式赋 0:无测试需求、无开发工时、检出率 i≤0,均 set bugFindRate=0 + bugFindScore=0(原不赋值弹窗显示空)。8086 实测孙颖 6 月 bugFindScore=0(不再是 null)。
---
## CHG-057 需求详情页撤审查状态显示(2026-08-06,用户拍板"代码审查报告不需要通过或者不通过在需求详情页面")
**改动**:storyinfo/components/product.vue——「代码审查报告」区块标题旁状态徽标(通过绿/未通过红/未审)移除;`codeReviewStatusText` computed 一并删除(全文件无其他引用)。**保留不动**:①提交测试报告卡点(`codeReviewStatus !== 'pass'` 时提示"代码审查未通过,不可提交"+隐藏上传按钮,FR-008 SOP 卡点);②后端 `code_review_status` 字段与 uploadBind 解析写入(代码质量考核取数依赖)。
**验证**:vue-template-compiler 模板编译 errors=none;script 块 @babel/core 解析 ok。两副本已同步(codes/web_zentao + F:\zd\web_zentao)。**⚠️ 页面级验证待补**:8085/8086 后端当前未运行(8088/8089 dev server 在线,热更新已生效),8085 启动后刷新需求详情页确认。
**补记(留痕补齐,证据指引)**:
- CHG-056(08-04,Bug 分级 severity 1=重大、2/3/4=普通):IZtCountService.java:1339 注释处 + AbstractWeightedBugCalculator/DefectFindRateCalculator 两处同步修改;decision_log 已录。
- CHG-058(08-05,AI 代码审查/工作日志/文档更新记录三区块前端上传入口移除,上传只走 AI 框架通道):product.vue 三处 CHG-058 注释;同会话另完成 mermaid 流程图渲染(public/mermaid.min.js 静态引入 + MdPreview window.mermaid 渲染,8088 实测 9130 流程图通过)。
---
## CHG-059 aiBatchAdd 补历史留痕(2026-08-06,用户报"AI 拆的任务历史记录没有")
**根因**:aiBatchAdd 只 insert zt_task,不写 zt_action——且全库从未有过 task 级 action(手工建任务也不写),需求详情的「历史记录」区块(actionList 按 objecttype+objectid 查)只见 story 级动态,故 AI 拆任务完全无痕迹。
**改动**:ZtTaskServiceImpl.aiBatchAdd 每个新建任务写一条需求级动态(与 uploadBind 上传留痕同模式:ActionType.XQ + ActionStatus.BJ,actor=ai,product=需求产品,extra=指派账号由前端映射昵称),comment="AI拆分任务:{名称}(开发/测试,工时Xh)";skipped 防重项不写。actionService 为类内既有注入,无新依赖。
**单测**:AiBatchAddServiceTest +1(留痕用例:新建写动态/comment 含任务名与工时/extra=指派账号/skipped 不写),setUp 补 actionService mock。**Tests run: 5, Failures: 0, Errors: 0**。
**8086 实测**:临时 2 任务上传 → zt_action+zt_actionrecent 各写 2 条(comment/extra 正确)→ 临时任务与 action 行已清理;18563/18564(修复前创建)按原创建时间补录动态 2 条(comment 标注"补录")。
**注意**:8085 为用户实例,跑的是修复前代码——**需 IDE 重编译重启**后 aiBatchAdd 才有留痕;历史里 18563/18564 的补录记录已可直接看到。
---
## CHG-060 aiBatchAdd 补任务级留痕(2026-08-06,用户指出"任务侧历史也要有,手工拆任务本来有")
**更正 CHG-059 的误判**:此前"全库零 task 级 action"系 2026 库复制时 zt_action 按计划清空所致——手工建任务本就写 RW+XJ(ZtTaskServiceImpl:681,actor=登录人)。
**改动**:aiBatchAdd 在 CHG-059 需求级动态之外,每个新建任务再写一条任务级动态(ActionType.RW + ActionStatus.XJ,objectId=taskId,actor=ai,comment 空,与手工建任务同一形状),任务详情页历史可见。
**单测**:留痕用例补 RW+XJ 断言(mock insert 不回填 id,objectId 为 null 校验形状),**5/5 全绿**。
**8086 实测**:临时任务 18567 → story 级(edited+comment)与 task 级(opened,product=150)双写成功,actionrecent 同步;临时数据已清理。18563/18564 按原创建时间补录 task 级动态 2 条。
**注意**:8085 需 IDE 重编译重启后生效(含 CHG-059/060 两批)。
---
## CHG-061 AI 通道接口鉴权 + ai 永久 token(2026-08-06,用户拍板"创建人都要 token 的")
**背景**:AI 上传三接口(saveOrUpdate/aiBatchAdd/uploadBind)此前无鉴权直连(R-003/DT4 二期必决项)。JwtUtil.sign 本无过期设计,token 天然永久。
**改动**:
1. 鉴权门禁——saveOrUpdateExpand、aiBatchAdd:限 ai 账户 token(非 ai 登录用户也拒);uploadBind:需任意有效登录态(前端上传组件在用,不能限 ai)。
2. 创建人改取 token 身份——aiBatchAdd 的 openedby 与两级 zt_action actor、refreshOwnerUrl 的上传动态 actor(无登录态兜底 ai 兼容直调)、zt_file.addedby 沿用既有 token 取值。
3. ai 永久 token 已生成:HMAC256(account=ai),存 `.claude/ai_token.txt`(已用 8085 验证:真 token 放行 / 伪造 token"请登录")。
4. 框架脚本:`submit_assessment.py`、`upload_md.py` 自动带 Authorization(读 ZENTAO_AI_TOKEN → .claude/ai_token.txt);**两脚本默认地址改正线→本地 8085**(用户拍板"别用正线的 url"),打正线需显式设 ZENTAO_BASE_URL。
**单测**:AiBatchAdd +1(非ai整批拒绝且零写入)、ZtStoryExpand +2(非ai/无token拒绝、ai放行)、UploadBind 测试补 actionService mock(修复 08-05 留痕上线时未补 mock 的既有断点)。**三类 6+5+13=24 全绿**。
**8086 实测 3×3 矩阵**:无 token 三接口全拒;admin token 仅 uploadBind 放行(zt_file.addedby=admin);ai token 全通(任务 openedby=ai、action actor=ai/admin 各归各)。测试数据已清理(zt_file 8815/8816 软删、任务 18569 软删、action 行删除、9130 test_other_url 恢复 08-05 值;上传目录留 2 个探针 MD 孤儿文件,低危)。
**注意**:①8085 需 IDE 重编译重启后门禁生效(重启前旧代码照旧放行,脚本带 token 向下兼容);②生产 itsm 仍为无鉴权旧代码,发版前该口子都在;③ai 账户密码仍是默认 MD5(123456),建议改密——改密不影响已签 token(checkToken 只验签不查库)。
---
## 9130 任务换新流程重建(2026-08-06,用户指出原任务建于修改前)
18563/18564(无 token 时代创建+手工补录留痕)软删、补录行清除 → 8085 新代码下以 ai token 重传 aiBatchAdd:**18570(devel/6h/罗勇)+ 18571(test/3h/未指派)**,openedby=ai,需求级+任务级动态由系统自动双写(119044-119047),9130 链路数据全部为真实流程产出,无手工补录。
---
## CHG-062 批拆留痕合并为一条(2026-08-06,用户拍板"一次上传多个任务应该就一条记录")
**改动**:aiBatchAdd 需求级留痕由"每任务一条"改为"每批次一条"——循环内只写任务级(RW+opened)并收集文案,循环结束写一条需求级动态:`AI拆分任务 N 个:①名称(开发,工时6.0h,指派:罗勇);②名称(测试,工时3.0h,未指派)`;有重复跳过项追加";重复跳过 M 个";指派经 userService.getByAccount 转中文名(查不到兜底账号);extra 不再携带指派(文案内嵌)。
**单测**:留痕用例改写为聚合断言(个数/序号/指派/跳过数),AiBatchAdd 6/6 绿。
**8086 实测**:2 任务批拆 → 需求级 1 条+任务级 2 条;未指派文案"未指派"(无冗余前缀)。9130 既有 2 条单任务记录已合并重写成一条(原创建时间保留)。截图 tmp/pw_9130_history.png。
**注意**:8085 需 IDE 重编译重启生效。
---
## CHG-063 文档区块归集「需求文档」tab(2026-08-06,用户拍板"放在需求的一生后面加一个 tab 需求文档")
**改动**:storyinfo/components/product.vue——测试用例/测试报告模版、提交测试报告、其他测试文档、代码审查报告、工作日志、AI项目文档更新记录 共 6 个文档区块由左栏(span16)整体迁移至右栏 el-tabs 新增第三个 pane「需求文档」(位于 需求的一生 之后);左栏保留 需求描述/验收标准/附件/AI指标/交付物/历史记录。数据与方法零改动(fetchBlockFile/uploadForm/卡点逻辑原样)。
**验证**:vue-template-compiler errors=none(移动时丢失 需求的一生 pane 闭合标签一处,已修);六区块 tab 内齐全、左栏无残留(程序化断言);8088+8085 实测 9130 页面:tabs=[基本信息/需求的一生/需求文档],六区块渲染正常、上传按钮/卡点状态正确。截图 tmp/pw_9130_doctab.png。已同步 F:\zd。
**已知**:tab 头在 span8 窄栏下标签偏挤(el-tabs 默认样式,功能性影响无);提交测试报告上传按钮因 9130 code_review_status=pass 正常可用。
---
## CHG-064 产品助理弹窗前后端对齐(2026-08-06,用户报"产品助理的前端页面显示有问题")
**根因**:08-05 用户拍板"绩效的除了产品和项目经理其他撤回到 git 提交版本",08-05 会话完成了后端 IZtCountService 还原(buildXMZLScore 等回老版),但**前端 performance.vue 的 XMZL 区块未同步还原**——新版区块绑定的 workloadPrdScore/productBugRate/productProblemResponse/productResponsibilityScore 老后端不产出 → 弹窗得分全空。全角色对齐核查:CS/UI=老+老✓;CPJL/XMGLY/KFZ/YW=新+新✓(按拍板保留);**XMZL 是唯一前后端错配**。
**改动**:performance.vue 的 case 'XMZL' 块还原为 git HEAD 版(及时验收20/项目文档50/会议管理30,绑定 releaseCount/releaseOnTimeCount/releaseOnTimeRate/documentQualityProblem/projectDocumentScore/meetWeek/meetStory/meetScore 老字段)。已同步 F:\zd。
**验证**:编译 errors=none;字段交叉核对(HEAD 绑定 10 字段 ↔ 老后端 getReleaseScore/getMeetScore 全部有产出,documentQualityProblem DTO 默认 0);8088+8085 实测李语嫣(145 道路救援 2026-06)弹窗:及时验收 0/项目文档 50/会议管理 30/总计 80 渲染正常。截图 tmp/pw_xmzl_liyuyan.png。纯前端改动,8085 无需重启(dev server 热更新)。
---
## CHG-065 产品助理+UI 弹窗改新 Excel 口径(2026-08-06,用户拍板"不对 按照新的excel来"、"还有ui人员的也更新掉")
**背景**:撤销 CHG-064/08-05 对 XMZL 的老版还原,产品助理与 UI 均按新 Excel(SRC-002)执行。
**改动**:
1. `buildXMZLScore` 重建为新口径:scope=perfReportService.report(month, "productAssistant", account) + fillRawDetail;workloadPrdScore=perfItemScore(workloadRatePrd,50)、releaseScore=20(人工默认满分)、productBugRate=perfItemScore(productDefectRate,15)、productProblemResponse=10、productResponsibilityScore=5(后两项人工满分默认);移除老版 getReleaseScore/getMeetScore/documentQualityScore=50/projectDocumentScore=50 与 0.75 达标工时。
2. `buildUiScore` 及时率得分:老内联公式(90 边界漏判:90%→0)改走 `PerfScoreRules.uiPunctualityScore`(=100%→50/≥90%→40/<90%→0,CHG-037 规则类幸存);designScore=40/workAttitude=10 本已符合新 Excel 不动。
3. 前端 performance.vue:XMZL 区块恢复新 Excel 版(撤销 CHG-064 老版还原);UI 区块无需改(git 版行/权重/字段本就与新 Excel 一致)。已同步 F:\zd。
**验证**:前端编译 errors=none;后端 PerfScoreRulesTest 6/6 绿。**8086 API 实测(2026-06)**:李语嫣 workloadPrdScore=0(真0,145 无指数记录)/releaseScore=20/productBugRate=15/productProblemResponse=10/productResponsibilityScore=5,perfRawDetail 两键齐——与 CHG-037 时期实测值一致;刘圣清 punctualityScore=0(真0,无任务)/designScore=40/workAttitude=10。8088 弹窗结构核验:两角色新行齐全、无旧版残留(截图 tmp/pw_chg065_xmzl.png、pw_chg065_ui.png)。
**注意**:8085 当前跑的是老后端,弹窗数值要 **IDE 重编译重启**后才按新口径显示(现在页面显示的是老后端值:PRD完成率空/及时验收0/问题响应15 等 DTO 默认值)。
---
## CHG-066 XMZL 弹窗列错位修复(2026-08-06,用户报"分项跑到绩效数据那一列")
**根因**:performance.vue 模板 `<td v-if="item.category">` 仅在行配置含 category 时渲染类目格——XMZL 区块「项目绩效」rowspan=2 只覆盖前两行,产品缺陷率/问题响应和解决两行无类目格 → 单元格少一个整行左移,得分值落进「绩效数据」列。全角色扫描:仅 XMZL 有此配置缺陷(KFZ/CS/UI/YW/XMGLY/CPJL 覆盖均正常)。
**改动**:XMZL 区块首行 rowspan 2→4(项目绩效覆盖 完成率/验收/缺陷率/响应 四行,与新 Excel 结构一致)。已同步 F:\zd。
**验证**:编译 errors=none;8088 实拍李语嫣弹窗:项目绩效跨四行分组正确、各列对齐、得分 0/20/15/10/5 落「得分」列、总计 50、首行明细"Σ指数 0 / 达标 630h = 0%"正常(截图 tmp/pw_chg065_xmzl.png)。同期 8085 已带 CHG-065 新后端(弹窗数值与 8086 API 实测一致)。
---
## CHG-067 Bug 需求关联字段 story→toStory(2026-08-06,用户拍板"story 字段应该没用 启用的是toStory")
**数据证据**:全库 prod Bug 76 个 story>0 的 **0 个**、toStory>0 的 23 个;dev Bug 2433 个 story>0 的 **0 个**、toStory>0 的 2251 个——story 列全库未用,需求关联实际全走 toStory。
**改动(4 处死字段修复)**:
1. `AbstractWeightedBugCalculator.computeWithExempt`:5‰豁免分子取数 `.in(getStory)` → `.in(getTostory)`(线上Bug率/产品缺陷率核心修复,此前结构性漏算恒满分);
2. `IZtCountService:1350`(buildCPJLScore 展示严重/普通 Bug 数)同改;
3. `ZtBugServiceImpl:527`:入参本就是 toStory 的 ID,查询列同步改(按需求查 Bug 列表此前恒空);
4. `ZtStoryServiceImpl:1982`:关闭需求联动关闭未关闭 Bug(此前永远找不到 Bug)。
已用 toStory 的(检出率 getBugFindScore/DefectFindRateCalculator/ZtStoryServiceImpl:2363)不动。
**验证**:perf 计算器套件 13+7+10 全绿。**8086 新代码实测**:王宇航 2026-02 onlineBugRate 100→**40**(2 普通 Bug/336.2h=5.95‰ 超豁免线,扣 6→加权尺度 40,与手算一致);无回归——李语嫣 6月=15(真0)、孙世超 6月=7(同 CHG-051)。排障:首轮实测误打 CHG-065 残留 8086 实例(占端口新实例未起),杀旧重启后复测通过。王宇航 2 月快照已恢复原值(备份 tmp/wyh_202602_snapshot_backup.json),历史月份是否统一重算待用户拍板。
**注意**:8085 需 IDE 重编译重启生效; prod Bug story=0 的录入习惯意味着**仍有 17 个历史 prod Bug 两字段都空**(任何口径都够不着,含 6 月的 2411)——要么补关联,要么接受豁免。
---
## CHG-068 需求文档 tab 视觉重设计 + tab 头间距(2026-08-06,用户拍板"tab 靠太近"、"需求文档页面太丑你优化他")
**tab 头间距根因**:App.vue 全局 `.el-tabs__item{width:4rem!important}` 定宽,5 字标题(需求的一生)溢出 63px 盒子与下一个 tab 粘连;另有来历不明的 rem padding 覆盖。修复:`.filterInfo` 作用域 `width:auto!important` 解除定宽 + 兄弟选择器 `margin-left:16px`(绕开 padding 覆盖链)。
**需求文档 tab 重设计**(数据绑定零改动,测试断言全部保留):六类文档由"白卡片堆叠+hr"改为**分节卡片**——节标题(蓝色竖条+16px 标题+份数徽章)、文件行(文档图标+文件名悬停变色+灰色小字 操作人·时间+查看/下载)、子分组(测试用例/模版)、卡点提示改 el-alert 风格黄条、审查轮次改蓝色徽章、空态文案统一"暂无附件(由 AI 框架上传)"。
**验证**:编译 errors=none(生成器脚本四重大括号事故 14 处已修);13 项关键绑定程序化断言无缺;8088 实拍:tab 头间距正常、六分节渲染正确、计数徽章正确(2/1/2/1/2/2 份)。截图 tmp/pw_9130_doctab.png。已同步 F:\zd。
### CHG-068 补充(同日):
- **meta 行字段大小写修复**:fileList 接口返回 addedby/addeddate(全小写),新旧模板都绑的 item.addedBy/addedDate(驼峰)恒空——老设计空 span 不可见,新设计 meta 行暴露为吊着的孤「·」。改绑正确字段名 + 空值整行不渲染(7 处)。实拍:文件名+「ai · 2026-08-05 17:14」完整对齐。
- **tab 间距收敛**:margin-left 16px→6px(用户反馈"间隔又太远"),文本对文本约 31px。
---
## CHG-069 saveScopeJson 登录态 NPE 修复 + 打包(2026-08-06)
**根因**:`ZtPerfReportServiceImpl.saveScopeJson:356` 无防御读 `RiskUserThreadLocal.get().getName()`——该写法一直靠 ThreadLocal 静态初始化块预置 admin 的隐性 quirk 撑着;CHG-061 给 AiBatchAddServiceTest 加的 tearDown clean() 把这个默认值清掉,同线程后续跑的 ZtPerfReportServiceTest 即 NPE(测试顺序依赖暴露)。
**修复**:①saveScopeJson 空值兜底 "system"(生产侧同样防未来调度线程无登录态 NPE);②ZtPerfReportServiceTest 补 BeforeEach 登录态/AfterEach 清理(测试自给自足)。
**验证**:ZtPerfReportServiceTest 3/3、AiBatchAddServiceTest 6/6、ZtStoryExpandServiceTest 5/5 全绿。
**打包**:`mvn package -DskipTests` → `codes/zentao/target/zentao.jar`(154MB,2026-08-06 15:54,含 CHG-039~069 全部改动)。
---
## mermaid 发布包缺失修复(2026-08-06,用户报"打包发布到测试环境流程图没有正常显示")
**根因**:mermaid 三件套(public/mermaid.min.js、index.html `<%= BASE_URL %>mermaid.min.js` 引用、MdPreview mermaid 渲染逻辑)08-05 会话只加在 codes 副本,F:\zd 副本一直没有——用户从 zd 打发布包,包里无 mermaid。
**处理**:三件套同步 zd;清 webpack 缓存重打 `F:\zd\web_zentao\dist`(mermaid.min.js ✓ / index.html head 引用(先于 app bundle,window.mermaid 可用)✓ / MdPreview 代码入 chunk-37091a66、chunk-56c8e14c ✓ 全量搜索证实)。注意点:publicPath='/',mermaid 以 /mermaid.min.js 绝对路径引用,前端须部署在域名根路径。
---
## CHG-070 productPageList 性能修复(2026-08-06,用户报"接口要5秒")
**定位(161 实测)**:产品列表页统计拉的 3 张全量表——zt_story(*) 3447行/923ms、**zt_bug(*) 未关闭 954行/7340ms(steps MEDIUMTEXT 共 44MB,均值 46KB/行)**、zt_story_user(*) 2273行/498ms。zt_bug 全字段拉取是唯一主因。
**改动**:ZtProductServiceImpl.productPageList 三处查询修剪 select 列(story: id/product/status/stage;bug: id/product/status;story_user: id/product/status),统计逻辑零改动。
**验证**:修剪后 SQL 预演 50/27/93ms;8086 端到端实测 **0.49/0.19/0.23s(原约 5s,~20 倍提升)**,结果集正确(total=10)。已重打 target/zentao.jar(17:02),发布 8015 即可生效。
---
## CHG-071 exportScope 快照三格式兼容(2026-08-06,用户问"exportScope 要按新修改调整吗"+NPE 报错)
**根因**:zt_month_score.scope_json 三种格式并存——①老 DTO 平铺(弹窗提交时代)②引擎 PerfMonthScope(generateMonthScore)③docCheck 专项(FR-014 扣分合并);exportScope 一律按老 DTO 解析 → 后两种全 null → generatorDevlopExcel 取 delayTask.toString() NPE(luoyong 2026-06=docCheck 格式实锤)。
**改动**:exportScope 解析改走新助手 resolveScoreDto——引擎格式=新算 DTO 为底+人工项(source=manual)按 score×weight 覆盖;老 DTO 格式=直接反序列化+统计字段缺失从新算回填(backfillStats 13 字段);其他格式=新算 DTO。
**验证**:8086 导出 2026-06(原 NPE 场景)HTTP 200/13.6s/有效 xlsx——罗勇开发考核表完整渲染(任务 9/超期 2/及时率 88%→8 分、Bug 密度 0→30 分),统计字段齐。已重打 target/zentao.jar(17:28)。
**同族遗留**:myWorkScore 弹窗对引擎/docCheck 格式快照同样按老 DTO 解析会空值——弹窗出现历史月份空分时同一招修(resolveScoreDto 可直接复用),待用户指示。
---
## CHG-072 myWorkScore 快照分流 + CHG-073 userList 脱敏(2026-08-06,用户拍板"1 2 都做")
**CHG-072**(exportScope 同族):myWorkScore 拆为薄壳+myWorkScoreCompute——老 DTO 平铺快照维持快路径;引擎/docCheck 格式快照不再按老格式解析(全空),改走新算+人工项以快照覆盖(overlayManualScores 复用)。实测:luoyong 6月(docCheck 快照)修复前全空→修复后 punctualityScore=8/delayTask=2/totalTask=9 等新算值;sunying 5月(老快照)快路径快照值原样。
**CHG-073**:userList 响应剔除 password 列(MD5 哈希不下发),其余 51 字段全保留兼容。排障:实体 `@TableField("\`password\`")` 列名带反引号,首版按 getColumn() 匹配失效,改按 getProperty() 匹配后实测 password 不再泄露。
**打包**:target/zentao.jar(2026-08-06 17:54,含 CHG-070~073)。
---
## CHG-074 月报列表达标工时与弹窗对齐(2026-08-07,用户指出"月度达标应该跟详情的一致")
**根因**:08-05 还原波及 pageMonthReport——月度达标工时退回老个人口径((21×8)×0.75=126),且饱和度分子用 storyTotalTime(estimate);而弹窗 myWorkScore 走团队口径(21×5=105)+实绩 consumed。两处不一致。
**改动**:pageMonthReport 的 haveTime 改 `teamExamineTime(accountIds,...)`(在窗 KFZ 人均,无 KFZ 退回个人口径兜底);饱和度分子 storyTotalTime→workTime(实绩)。
**验证**:8086 实测月报 139/2026-06——全员达标=105.0(与弹窗一致);陈浩 126/105=120%、罗勇 25/105=24%、孙颖 84/105=80%。jar 已重打(17:5x 见时间戳)。
---
## CHG-075 exportScope 静默空响应修复(2026-08-07,用户报"没有文件导出")
**根因(双重)**:①方法尾部 `catch(Exception){log.error}` 静默吞异常——"未查询到数据"(当月无在窗执行/任务)等异常被吞成**空 200**,前端拿到 0B 响应即无文件也无提示;②无快照人员 `continue` 跳过——当月(如 8 月)没人有快照时一个文件都不产。
**改动**:①BusinessException 重新抛出交全局异常处理器回 JSON(前端弹"未查询到数据"等真实原因),其他异常包装"导出失败";②无快照人员用新算 DTO 导出(自动分+人工满分默认),有快照走 CHG-071 三格式解析。
**验证**:8086 实测——2026-08+139 返回 JSON 错误(前端可提示)0.4s;2026-06+139 文件 23.5KB→44.4KB(无快照人员补齐,含陈浩表)。jar 已重打。
---
## CHG-076 aiBatchAdd 中文姓名指派映射(2026-08-07,用户拍板"指派中文要查数据库")
**改动**:aiBatchAdd 建任务前解析 assignedTo——非既有账号时按 `zt_user.nickname` 查库映射为账号(AI 框架传中文名场景);账号原样、查不到原样保留。需求级留痕文案的指派展示用映射后账号取昵称。
**验证**:单测+1(中文名映射用例,7/7 绿);8086 实测 assignedTo="罗勇" → 落库 assignedto=luoyong(验证数据已清理)。jar 已重打。
---
## CHG-056 绩效导出换新版式 + 并行改动合并修复(2026-08-10,用户拍板"改")
**导出换新版式**:9 份新模版(9 岗位 sheet 全量,含王宇航变体/前后端分离/新增运维)由 `tmp/make_perf_templates.py` 从 SRC-002 xlsx 生成(占位符 {name}/{date}/{得分键}/{total}/detail_*);IZtCountService 7 个 generator 重写(新键名+devDirection 分流前后端模版+perfRawDetail 明细入「绩效数据」列)、新增 generatorYwExcel + exportScope YW 分支、helper(scoreStr/scoreTotal/perfDetail 等)。
**排障两个坑**:①openpyxl 生成的 xlsx 是 **inlineStr 单元格**,POI setCellValue 会残留旧 `<is>` 内联串导致读回旧值(占位符零替换)→ writeXlsx 先 setCellType(BLANK) 再写值修复;②**并行改动撞车**:另一会话在 IZtCountService 上做了"选中产品集 KFZ 成员"口径(buildKFZScore 加 accountIds 参数+fillTeamExamine(accountIds)),但底版偏旧,把 CHG-036/038(PerfScoreRules 算分、前后端分流)与 CHG-054/055(testStoriesOf/检出率赋 0)覆盖丢失 → 已全部合并还原(保留 accountIds 团队口径新逻辑,恢复 PerfScoreRules 算分+devDirection+testStoriesOf+显式 0 分),补回 PerfScoreRules import;pom.xml 的 surefire skipTests 硬编码块(为绕 AOT 报错加的)已移除(lombok 1.18.34 已治本)。
**验证**:单测 92 全绿(surefire 恢复可跑);8086 实测——郭尚雨 devDir=backend/docQ=10/饱和 20、孟冉 devDir=frontend/无文档质量项、孙颖检出率显式 0;导出全量 28 sheet 无残留占位符,孙世超 sheet 得分+明细全对(20/30/4/10/0/5/10/5,总 84),孟冉前端模版无文档质量行,郭尚雨后端 sheet 总分 100。
**注意**:①王宇航 sheet 走变体模版(无 PRD 行);②岑海峰 6 月不在窗口执行内不出 sheet(7 月起正常);③导出列路径(exportScope)不读 zt_month_score 快照、实时算;④8085 需重编译重启+前端发版。
---
## CHG-057 CS 测试文档齐备改实时字段判定(2026-08-10,用户拍板口径)
**口径(用户定)**:范围=zt_story_expand.test_person 指定 ∪ assignedTo 且本月发布的需求(复用 CHG-054 testStoriesOf);判定=test_case_url(用例)+ test_report_submit_url(**提交件**,AI 模版 testReportDownload 不计)非空;每缺一份扣 3 分(25 分项直接扣完截止);本月无需求→满分 25。
**改动**:buildCScore 弃写死 25,实时遍历 testedStory 两个 url 字段计数,documentQualityProblem=缺失数透出展示。
**8086 实测**:孙颖 6 月 缺失 46(23 需求×2)→ 0;孙庆方 缺失 34 → 0(2026 库这些需求确实没人传测试文档,非误判);孙颖 2025-12(无测试需求月)→ 满分 25 ✓。8085 需重编译重启。
**注**:引擎的 TestDocReadyCalculator(快照版,归属按 account 匹配中文名列本就失效)自此彻底废弃,仅 CS 弹窗路径生效;原 CS 弹窗「测试文档」行 data 绑定 documentQualityProblem(问题个数)直接显示缺失份数。
---
## CHG-058 需求文档拆独立区块 + 前端改动恢复(2026-08-11,用户拍板"可以加类型/入口处改/顺带前端")
**改动**:FileTypes 增 `storyPrd("storyPrd","需求文档")`;uploadBind 刷新 prd_url(storyPrd 与 story 同字段);upload_md.py VALID_TYPES+用法注释(需求文档一律 storyPrd,story 保留给手动附件,互不影响他人接入);storyinfo/product.vue「需求文档」归位到右侧「需求文档」tab 顶部 section(复用 dc0b5a5 doc-sec 版式),无上传按钮、纯 AI 框架上传,空态文案"暂无附件(由 AI 框架上传)"。6566 实测:上传→prd_url 刷新→fileList 返回→tab 渲染;9130 需求文档已传(zt_file 8824,内容由 zt_storyspec 真实 spec 生成,curl GBK 乱码 title 已 SQL 修正),截图 tmp/pw_9130_prd_tab。已同步 F:\zd\web_zentao。
**并行会话撞车处置**:郭其兵 08-11 13:10 提交 dc0b5a5「新版绩效」(main_2026 分支),收编了我 13:10 前的前端工作(CHG-036~053/046/会议等)+他自己的三期绩效页面(views/perf/*);工作区被切到该提交后,我 14 点的 CHG-058 前端编辑(未提交)丢失 → 从 F:\zd\web_zentao(14:16 同步版)拷回 product.vue,diff 验证恰好是 CHG-058 那 49 行、无其他损失。codes/web_zentao 当前状态=dc0b5a5 + product.vue(M, CHG-058),建议尽快提交避免再次被冲。
**环境备忘**:用户的 8085 IDE 后端与我的 8086 当前都连 zentao_dev_2026(IDE run config 带 2026 覆盖);8088 前端由用户在 codes/web_zentao 启动。生产 itsm 未动。
---
## CHG-077 uploadBind 入口 story→storyPrd 归一化 + 8 需求错传数据修复(2026-08-17,用户拍板"改"+"一起")
**起因**:200 库 9209 用户报"上传的 md 落到了附件"。排查实证:AI 通道把 PRD/验收标准用 objectType=story 调 uploadBind(zt_action 留痕"上传需求"),而「需求文档」区块只认 storyPrd(product.vue fileFieldMap);且 refreshOwnerUrl 中 story 与 storyPrd 同写 prd_url,last-write-wins 致 prd_url 被后传的验收标准覆盖。误用源头:对外接口文档 §5.2 只列 story 未列 storyPrd(CHG-058 只改了 upload_md.py 客户端,管不住外部调用方)。
**改动**:UploadDTO 增 normalizeObjectTypeForBind()(story 归一 storyPrd);CommonsController.uploadBind 校验后调用,一处生效(refreshOwnerUrl 与 zt_file 落库同读 DTO)。原生两段式上传不受影响(UI 手动附件不走 uploadBind,前端全项目无 story 传参)。
**单测**:新增 UploadBindNormalizeTest 4 条(story→storyPrd / storyPrd 不变 / 其他类型不变 / null 安全);回归 UploadBindRefreshOwnerUrlTest 13 条。**17/17 绿**。
**200 库数据修复(已提交回读验证)**:18 条 ai 误传 story 文件改 storyPrd(9143×4/9179×3/9180×1/9208×2/9209×2/9213×2/9226×2/9238×2);8 需求 prd_url 从"验收标准"校正回 PRD/需求说明/需求文档(9143→9395、9179→9343、9180→9335、9208→9435、9209→9428、9213→9416、9226→9404、9238→9397 的 url)。
**待办**:代码改动在本地 codes/zentao,需郭其兵提交+部署后归一化才在线生效;对外接口文档 §5.2 仍只列 story——归一化上线后文档与行为一致,可不急改。
---
## CHG-078 用户需求导出/分页加「迭代版本」列(2026-08-17,用户拍板)
**需求**:/zt-story-user/export 与 pageList 加迭代版本列,参照分页列表 execList 字段,只要迭代名称、多迭代拼接。
**现状**:列表页已有该列(userstory/product.vue 用 execList 渲染);缺口在导出(execList 标 @ExcelIgnore)。
**改动**:ZtStoryUserDTO 增 execNames(@ExcelProperty "迭代版本" index=5,后续列 index 顺移+1);ZtStoryUserServiceImpl 增静态 buildExecNames(名称去重排序逗号拼接,空→null),pageList 与 storyListByProductId 两处填充点接入。前端零改动。
**单测**:BuildExecNamesTest 4/4 绿(多迭代拼接/单迭代/空/空白名过滤)。
**待办**:代码在本地 codes/zentao,需郭其兵提交+部署生效。
---
## CHG-079 modifyTask 后端权限校验:创建人/项目管理员/admin(2026-08-28,**已撤销——用户拍板"后端不用改"**)
**背景**:代码勘察发现 /zt-task/modifyTask 后端无任何归属/角色校验(前端仅按钮显隐控制:openedby 本人 或 XMGLY/GSGC),任何登录用户可直调接口改任意任务——而 estimate/left/consumed 是绩效算分输入,存在越权篡改风险。
**改动**:`ZtTaskServiceImpl.modifyTask`(selectById 判空后)加门禁:当前用户为 `admin`、任务 `openedby` 本人、或 `userType==XMGLY`(项目管理员)三者其一放行,否则抛"仅任务创建人或项目管理员可修改任务"。原有的状态卡点(cancel/closed/done 拒改)与 KFZ 评审流转不受影响。
**口径说明**:①GSGC(公司高层)未纳入后端白名单——用户本次只点名项目管理员,前端 GSGC 按钮(doing/wait 可编辑)与后端将不一致,如需放开再说;②ai 创建的任务 openedby=ai,此后仅项目管理员/admin 可改;③startTask 原有的指派人校验、aiBatchAdd/saveOrUpdate 的 ai 门禁均不受影响。
**验证**:JDK17 mvn compile BUILD SUCCESS。未写单测(modifyTask 为重 DB 依赖方法,现测试体系无对应基建)。
**待办**:8085 需重编译重启生效;代码需郭其兵提交部署(同 CHG-077/078 一并)。
**撤销记录(同日)**:用户确认后端不用改(modifyTask 加门禁会挡住前端已放开的 GSGC 编辑 doing/wait 等既有路径,回归风险>收益),代码已还原,编译状态回到改动前。
---
## CHG-080 任务编辑放开 XMJL 项目经理(前端,2026-08-28,用户拍板"项目经理也可以修改、只用改前端")
**背景**:任务编辑按钮的角色白名单此前只有 XMGLY(项目管理员)/GSGC(公司高层),XMJL(项目经理,如孙世超)在全前端都改不了别人创建的任务。用户确认后端不动(CHG-079 已撤销),仅放前端。
**改动**(三处,编辑按钮 userType 白名单加 `XMJL`):
1. `implement/task/components/product.vue:312`(研发任务列表)
2. `territory/task/components/product.vue:321`(地盘任务列表)
3. `implement/taskinfo/components/product.vue:608`(任务详情页)——顺带修笔误:`waiting`(不存在的状态)→ `wait`,否则详情页 XMJL/XMGLY 对 wait 状态任务仍无编辑入口(与列表页口径不一致)
**未动**:`implement/look/tab/content.vue` 编辑菜单项本就无角色门槛(仅 task-edit 权限键);testtask 页无角色限制。前提:XMJL 角色的菜单权限需含 `task-edit` 键(BaseRoleAuthority 数据配置),无键则按钮仍不显示。
**同步**:三文件已同步 F:\zd\web_zentao(diff 核对仅本次改动)。
**待办**:8088 前端热更新/重启生效;代码需随 CHG-077/078 一并提交。
---
## CHG-082 aiBatchAdd 放行 affair 事务任务(后端,2026-09-16,用户拍板"就事务 开始开发")
**背景**:AI 拆批接口 `/zt-task/aiBatchAdd` 的类型白名单原为 devel/test(后 CHG-081 放行 design,未入本档)。事务型任务(affair)此前传参会整批拒绝 `任务类型仅支持devel/test/design:affair`。
**改动**(两处 + 测试):
1. `ZtTaskServiceImpl.java:1382-1390`:白名单加 `TaskType.affair`,报错文案同步为 `devel/test/design/affair`
2. `ZtTaskAiBatchDTO.java:26`:type 注释补 affair
3. `AiBatchAddServiceTest`:新增 `aiBatchAdd_affair_createsTask`(仿 design 用例,断言留痕显示「事务」);`aiBatchAdd_illegalType_rejectsAll` DisplayName 同步
**已核对不受影响**(affair 与 design 同路径,天然隔离):
- 需求计划时间回写:`batchAddTask:1314-1324` 只对 devel/test 回写,affair 跳过
- 绩效专项公式:取数按类型显式过滤(如 `IZtCountService.java:1256` 只查 `type="devel"`),affair 不进
- 需求级留痕:`ZtTaskServiceImpl.java:1471` 按 TaskType 枚举动态取中文名,affair 自动显示「事务」
- 看板挂载:`ZtKanbanlaneServiceImpl.addTask` 按任务状态分列,与类型无关
**已知行为(与 design 一致,用户已知情)**:
- 需求状态联动 `taskFinishChangeStatus` else 分支(`ZtStoryServiceImpl.java:1623-1645`):需求下无活跃 devel/test 任务时,affair 任务会把需求看板列置 backlog/ready
- 指派 affair 任务会触发微信指派通知(`taskSendZpMessage`,与类型无关)
**验证**:`mvn test -Dtest=AiBatchAddServiceTest` → 10/10 通过(JDK 17)。
---
## CHG-083 三个统计接口性能优化(后端,2026-09-16,用户要求"不要影响老的代码/其他业务,先留存正线数据再比对")
**背景**:`/zt-project/projectTeamTimeWork`、`/count/storyBarChart`、`/count/bugBarChart` 正线耗时 7~19s。
**根因**:
1. 两个柱状图在 6 个月循环内每月调用全量绩效 `newPerformanceCount`(全岗位算分、逐人 bug/审批/文档查询),而图表只用 KFZ 成员的 allocationTime/examineTime 两个字段;
2. `storyBarChart` 逐月 `userMapByIds(null)` 全用户表扫描 ×6、`allProductList()` ×6、逐用户 filter 任务全表;
3. `projectTeamTimeWork` 任务查询无日期条件捞全量历史、全用户表扫描、天数×人数×任务数三层 O(n³) 扫描。
**改动**(老共享方法 `newPerformanceCount`/`fillTeamExamine`/`getApprovalTime` 等一行未动,其他业务路径不受影响):
1. `IZtCountService` 新增私有 `kfzMonthTimesLite()`:复刻图表实际消费口径(成员集合同 newPerformanceCount 798-840 行;allocationTime 同 buildKFZScore 的 Σestimate 剔除 closed/cancel;examineTime 团队人均口径公式同 fillTeamExamine),跳过无关算分;任务按指派人预分组
2. 新增批量请假查询 `ZtTaskMapper.itApprovalsByNames`(XML 条件与 itApprovalByUserName 完全一致,name 改 IN;老 SQL 未动)+ `IZtTaskService/ZtTaskServiceImpl` 透传——原逐人逐月跨库查 os_system.it_approval(date() 函数不走索引,约 人数×6 次),现每月 1 次
3. `storyBarChart`:`allProductList` 提出循环按需取一次;多部门成员实绩工时按指派人预分组(floatBatchAdd 两位精度口径保持一致)
4. `bugBarChart`:仅需 allocationTime,needExamine=false 跳过达标工时/请假计算
5. `ZtProjectServiceImpl.projectTeamTimeWork`:任务 SQL 加 estStarted 当月范围(按天循环本就只匹配当月任务,口径不变);用户表只查团队成员∪任务相关人(原全表);任务按 `yyyy-MM-dd#账号` 预分组替代三层扫描
**验证**(证据:F:\zentao\1\PM\perf-snapshots\20260916\):
- 留存正线基线(8013,老代码)→ 本地起新代码直连正线库(application-local.yml 用户已指向 192.168.3.200/zentao_dev)→ 同一时刻背靠背比对:
- storyBarChart:16.6s → 3.9s,data **IDENTICAL**
- bugBarChart:14.1s → 1.1s,data **IDENTICAL**
- projectTeamTimeWork:6.9s → 0.12s,data **IDENTICAL**
- 对照组 monthScopeByProgram(未改动路径):IDENTICAL,耗时不变(4.1s vs 4.9s)
- 单测 103/103 通过(JDK 17)
- 中途插曲:增量编译导致 v2 实例 baseMapper 绑定异常(NPE),clean compile 后消失;8085 dev 库与正线库数据不同,8085 基线仅用于过程验证
**注意**:本地验证期间本地实例曾直连正线库运行约 15 分钟(只读接口验证),已关停。