修复(08-28-reimbursement-detail-material-preview-fixes): 收紧撤回展示并校正材料图片尺寸
这个提交包含在:
@@ -689,10 +689,18 @@ reply.header(
|
||||
- PDF originals contribute every original page; JPG/PNG/WebP materials are
|
||||
normalized with `sharp` and embedded one per page. The merged PDF is a
|
||||
derived approval view, never an original or digital-signature fact source.
|
||||
- Image page geometry must use the width and height returned by Sharp's final
|
||||
normalized output (`toBuffer({ resolveWithObject: true }).info`), not input
|
||||
`metadata()`. `rotate()` applies EXIF orientation during output, so input
|
||||
metadata may describe the opposite portrait/landscape shape.
|
||||
- A stable collection hash covers the explicitly ordered material type, ID,
|
||||
file hash, MIME and byte count. The cache key also includes reimbursement ID
|
||||
and merger version. Fix CreationDate, ModificationDate, Creator, Producer and
|
||||
save options so identical input produces byte-identical output.
|
||||
- Any visible merge-algorithm change, including corrected image page geometry,
|
||||
increments the merger version. Byte determinism is required across repeated
|
||||
generation within one version; different versions may intentionally produce
|
||||
different bytes for the same ordered source collection.
|
||||
- The in-memory bundle is bounded to 20 materials, 50 MiB source bytes, 40
|
||||
pages, 40 megapixels per image, 50 MiB output and 100 MiB process cache.
|
||||
Worker execution has a fixed timeout; concurrent requests for one collection
|
||||
@@ -732,6 +740,7 @@ reply.header(
|
||||
### 6. Tests Required
|
||||
|
||||
- Service tests assert deterministic bytes, all-page copy, image embedding,
|
||||
EXIF orientation 6/8 output geometry, ordinary JPG/PNG/WebP geometry,
|
||||
20–30-page worker behavior, concurrent deduplication, expiry and limits.
|
||||
- Route tests assert authorization, reason gate, token binding, cache miss,
|
||||
issue/access audit, audit-failure fail-closed behavior and exact PDF size.
|
||||
@@ -748,6 +757,12 @@ reply.header(
|
||||
const pages = await rasterizeEveryPdfOnThePhone(); // slow, blank-prone and duplicates PDF rendering
|
||||
```
|
||||
|
||||
```js
|
||||
const metadata = await sharp(source).rotate().metadata();
|
||||
// metadata describes the input and can disagree with the rotated output.
|
||||
const page = output.addPage([metadata.width, metadata.height]);
|
||||
```
|
||||
|
||||
#### Correct
|
||||
|
||||
```tsx
|
||||
@@ -755,6 +770,14 @@ const bundle = await fetchReimbursementMaterialPreviewBundle(reimbursementId);
|
||||
await previewFileInWecom({ url: bundle.signedUrl, name: bundle.originalName, size: bundle.fileSize });
|
||||
```
|
||||
|
||||
```js
|
||||
const { data, info } = await sharp(source)
|
||||
.rotate()
|
||||
.jpeg()
|
||||
.toBuffer({ resolveWithObject: true });
|
||||
const page = output.addPage([info.width, info.height]);
|
||||
```
|
||||
|
||||
## Scenario: Lightweight Travel Summary On Reimbursements
|
||||
|
||||
### 1. Scope / Trigger
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
# 设计:报销详情权限与材料预览缺陷修复
|
||||
|
||||
## 边界与原则
|
||||
|
||||
本任务是两个小型缺陷修复加一项生产只读诊断,不改变业务权限、审批状态或数据模型。前端修复负责把服务端已有的对象资格正确投影为可见动作;后端修复只校正图片规范化结果的尺寸事实。真实材料诊断与代码修复分离,诊断结果不能成为扩大实现范围的默许授权。
|
||||
|
||||
## R1 动作资格数据流
|
||||
|
||||
```text
|
||||
报销详情 DTO ownerId / submitterId + 当前用户 me.id
|
||||
-> isReimbursementParticipant
|
||||
-> ReimbursementActions.showWithdrawAction
|
||||
-> reviewing 状态下按“参与人 AND 状态”显示撤回
|
||||
```
|
||||
|
||||
- 复用 `ReimbursementDetailPage` 已有 `isReimbursementParticipant`,不新增页面级权限枚举或 API 字段。
|
||||
- `ReimbursementActions.showWithdrawAction` 改为必填 prop 并移除默认值。全仓库当前只有 PC 报销详情一个调用点,由 TypeScript 强制调用方显式传入参与人资格,后续新增调用也默认 fail-closed。
|
||||
- owner/submitter 的既有交互、默认撤回说明、mutation 和反馈不变。
|
||||
- Playwright 使用两类合成身份验证:现有 owner 夹具继续看到撤回;复用 `r102-reimbursement-main-flow.spec.ts` 中 `adminMe + ownerId=employee-other-r102 + status=reviewing + scope=all` 的非参与管理员夹具断言撤回不可见。管理员覆盖当前 fail-open 权限面的最宽视角,服务端既有 403 测试继续作为真正安全边界。
|
||||
|
||||
## R2 图片规范化数据流
|
||||
|
||||
```text
|
||||
源 JPG/PNG/WebP
|
||||
-> sharp(source).rotate() 应用 EXIF
|
||||
-> flatten + JPEG 编码
|
||||
-> toBuffer({ resolveWithObject: true })
|
||||
-> info.width / info.height(实际输出尺寸)
|
||||
-> fitPage
|
||||
-> PDF page + drawImage
|
||||
```
|
||||
|
||||
- 不再在输出前使用 Sharp 输入 metadata 作为页面尺寸。
|
||||
- `resolveWithObject` 同时返回规范化 buffer 和实际输出 info,避免为了取尺寸再解码一次。
|
||||
- 输出宽高仍执行存在性、整数性和 `maxImagePixels` 检查;输入解码继续由 Sharp 的 `limitInputPixels` 限制。若 Sharp 输出缺少合法尺寸,沿用 `material_preview_image_invalid`。
|
||||
- 合并器版本从 `pdf-v1` 升级为下一稳定版本,使集合哈希和 cache key 明确区分旧算法。缓存仍只在进程内、按 grant 生命周期管理,不迁移数据。
|
||||
- 测试用 Sharp 生成无敏感内容的方向 6/8 JPEG。除页数和确定性外,读取合并 PDF page size,断言其纵横方向等于自动旋转后的实际输出;保留普通 PNG/JPG/WebP 基线。
|
||||
|
||||
## R3 真实单据只读诊断
|
||||
|
||||
```text
|
||||
受控生产只读定位业务单号
|
||||
-> 冻结有序材料最小元数据
|
||||
-> 必要时流式读取材料到安全临时目录/内存
|
||||
-> 读取 EXIF 和规范化输出尺寸
|
||||
-> 用当前合并器生成临时派生 PDF
|
||||
-> 核对页序、页数、目标页尺寸与是否存在图像对象
|
||||
-> 删除临时材料
|
||||
-> 仅保留脱敏结论
|
||||
```
|
||||
|
||||
- 现有顺序与单据事实已确认两张单页 PDF 发票在前、两张 JPG 附件在后,因此用户口中的“第一张图”固定对应合并 PDF 第 3 页;诊断直接从第 3 页开始,同时核对总页数,避免把 PDF 第 1 页误作目标图片。
|
||||
- 只在元数据不足以定因时读取最小原件字节;不进行 OCR、不展示内容、不输出完整文件名和存储路径。
|
||||
- 诊断记录只允许:材料类别、相对顺序、MIME、脱敏尺寸/方向、合并页数/页尺寸、错误类别和修复覆盖结论。
|
||||
- 若现象可由旋转后尺寸不一致完整解释,R2 为修复;若 PDF 页本身缺少可复制内容或存在表单/可选内容依赖,停止在证据结论,另行规划兼容方案。
|
||||
|
||||
## 兼容性与回滚
|
||||
|
||||
- 无 API、schema、迁移、权限或状态机变更。
|
||||
- 前端回滚:同时恢复 prop 默认值和调用点合同才会恢复旧投影;正常修复不允许只移除调用点参数,因为必填类型应在编译期阻断该回退错误。服务端安全边界始终不变。
|
||||
- 后端回滚:恢复旧图片尺寸读取并回退 merger version。已签发短时 bundle 本就随进程/TTL 失效,无持久化产物迁移。
|
||||
- 未部署前仅能报告本地验证与只读诊断结论;公网修复需要单独批准部署并完成构建号和关键路径检查。
|
||||
|
||||
## 关键权衡
|
||||
|
||||
- 选择复用现有参与人布尔值,而不是增加新的通用授权抽象:当前只有一个明确调用缺口,扩大抽象不会增加安全性。
|
||||
- 选择读取 Sharp 输出 info,而不是交换 metadata 宽高:EXIF 不只有 6/8,输出事实比枚举推断更可靠。
|
||||
- 不在本任务替换 `pdf-lib`:首图的 PDF 特殊内容兼容仍未被证据确认,且更换渲染链会改变确定性、资源上限和签名事实边界。
|
||||
@@ -0,0 +1,59 @@
|
||||
# 实施清单:报销详情权限与材料预览缺陷修复
|
||||
|
||||
## 1. 实施前只读诊断
|
||||
|
||||
- [x] 确认当前任务已获最终方案实施批准,并加载 `trellis-before-dev`。
|
||||
- [x] 使用受控只读路径冻结 `BX-20260828-0017` 的材料顺序与最小元数据,不打印敏感字段;按“两张单页 PDF 发票在前、两张 JPG 附件在后”的既有事实,将第一张图片锁定为合并 PDF 第 3 页。
|
||||
- [x] 在运行中 server 容器内以只读事务和内存缓冲复现当前合并结果,从第 3 页核对目标图片的 EXIF、规范化输出尺寸、PDF 页序和页尺寸;未写生产、未落临时原件。
|
||||
- [x] 诊断确认两张 JPG 均无 EXIF 方向标记,第 3/4 页比例正确且存在图像内容;两张源 PDF 也均有普通内容流,不存在 AcroForm/可选内容层依赖。当前数据无法复现“第 3 页无内容”,因此 EXIF 修复不宣称解决 `0017` 现象,本轮不扩展 PDF 引擎。
|
||||
|
||||
## 2. PC 撤回动作资格
|
||||
|
||||
- [x] 将 `ReimbursementActions.showWithdrawAction` 改为无默认值的必填 prop,并在 PC 报销详情调用点显式传入 `showWithdrawAction={isReimbursementParticipant}`。
|
||||
- [x] 保留 owner/submitter reviewing 状态的撤回能力、mutation 和反馈,不改组件外的权限或状态判断。
|
||||
- [x] 在 `r102-reimbursement-main-flow.spec.ts` 复用现有 admin 非参与人全范围夹具,断言撤回按钮和意见框均不存在;保留现有 owner 可见回归和 PWA Service Worker 隔离合同。
|
||||
|
||||
## 3. EXIF 合并修复
|
||||
|
||||
- [x] 调整图片规范化函数,从实际 JPEG 输出 info 读取宽高并校验合法性。
|
||||
- [x] 更新材料合并器版本,确保缓存身份与算法版本一致。
|
||||
- [x] 增加 orientation 6/8 合成图片回归,断言合并页方向/比例;保留普通图片、页数、确定性、限额和失败路径测试。
|
||||
|
||||
## 脱敏只读诊断结论
|
||||
|
||||
- 材料顺序为 2 张单页 PDF 发票、2 张 JPEG 附件,共 4 页;用户所称“第一张图”为第 3 页。
|
||||
- 两张 JPEG 的输入与规范化尺寸比例一致,均无 EXIF orientation;当前合并 PDF 第 3、4 页均存在内容,页面比例与图片一致。
|
||||
- 两张源 PDF 均存在普通页面内容流,未发现 AcroForm 或可选内容层;当前合并结果也保留对应页面内容。
|
||||
- 因而:代码中的 EXIF 尺寸读取缺陷成立并应修复,但不是 `BX-20260828-0017` 当前材料的直接原因;该单的“第一张图未显示”在本次只读内存复现中未重现,可能与当时的短时 bundle/阅读器状态有关,不能无证据归因。
|
||||
- 下一步:服务端材料链路已排除。若现象复现,需向用户确认具体页码、浏览器或企业微信 WebView 版本,以及是否稳定复现,再决定是否创建新的客户端诊断任务;本轮不在服务端继续扩面。
|
||||
|
||||
## 4. 验证与只读复核
|
||||
|
||||
- [x] 运行聚焦后端 Vitest、修改文件 `node --check` 和 Prisma validate。
|
||||
- [x] 运行前端 typecheck/build 与聚焦 Playwright。
|
||||
- [x] 运行流程、文档、Trellis 治理及 `git diff --check`。
|
||||
- [x] 只读检查 diff,确认未改变服务端撤回授权、权限矩阵、审批状态机、材料顺序、授权 grant、审计或原件降级合同。
|
||||
- [x] 按 `trellis-update-spec` 将“旋转后以输出尺寸建页”和“可见算法变化升级 merger version”沉淀到报销材料规约。
|
||||
|
||||
## 5. 交付与回滚点
|
||||
|
||||
- [x] 汇总代码变化、合成测试结果和 `BX-20260828-0017` 脱敏诊断结论,不附真实原件或敏感标识。
|
||||
- [x] 将 `BX-20260828-0017` 的真实处置作为单独业务决定提醒:按现行 PDF-only 规则由业务选择退回重传或财务留痕例外接受,本任务不代为处理。
|
||||
- [ ] 提交信息使用中文并引用 `08-28-reimbursement-detail-material-preview-fixes`。
|
||||
- [x] 未经单独批准不部署;如后续批准部署,必须完成公网构建号和关键路径只读检查后才能通知用户测试。
|
||||
|
||||
## 关键文件
|
||||
|
||||
- `client/src/pages/ReimbursementDetailPage.tsx`:PC 撤回动作资格投影。
|
||||
- 覆盖 PC 报销详情的现有或聚焦 Playwright spec:owner/财务双视角回归。
|
||||
- `server/src/services/reimbursementMaterialPdf.js`:Sharp 输出尺寸读取。
|
||||
- `server/src/services/reimbursementMaterialPreview.js`:合并器版本。
|
||||
- `server/tests/unit/services/reimbursementMaterialPreview.test.js`:EXIF、页面尺寸和确定性回归。
|
||||
|
||||
## 验证记录
|
||||
|
||||
- 聚焦后端:3 个测试文件、23 项测试全部通过;含材料合并、附件路由和非参与人撤回 403 回归。
|
||||
- 前端:typecheck 与 production build 通过;admin 非参与人撤回不可见、owner 撤回可用两条聚焦 Playwright 均通过。
|
||||
- 完整 `r102-reimbursement-main-flow.spec.ts` 为 5/6:本次新增用例通过;唯一失败为既有用例仍查找旧按钮名“编辑”,当前页面实际为“编辑报销日期”,与本次修改无关,未在本任务扩面修复。
|
||||
- 全量后端为 179 个测试文件通过、2 个失败,1295/1298 项通过;3 项失败均来自既有付款单 BIFF8 生成器在当前环境不可用,本任务未修改付款单代码。
|
||||
- process contract 与 Trellis governance 通过;docs registry 为 0 error、既有 22 个未登记文档 warning;敏感内容检查与 `git diff --check` 通过。
|
||||
@@ -0,0 +1,84 @@
|
||||
# 报销详情权限与材料预览缺陷修复
|
||||
|
||||
## Goal
|
||||
|
||||
修复报销只读查看者误看到“撤回报销”操作,以及带 EXIF 方向信息的图片进入材料合并预览后页面尺寸错误的问题;同时对 `BX-20260828-0017` 的首张图片未正常显示现象做受控、脱敏、只读诊断,让财务只看到职责内动作,并让图片材料在合并 PDF 中保持正确方向和比例。
|
||||
|
||||
## Background
|
||||
|
||||
- PC 报销详情已经计算 `isReimbursementParticipant`,但调用 `ReimbursementActions` 时未传 `showWithdrawAction`;该组件默认允许在 `reviewing` 状态显示撤回,因此具备全量查看权限的财务人员也会看到撤回入口。
|
||||
- 服务端撤回接口仍按 owner/submitter 做对象资格校验,非参与人会被拒绝;当前问题是前端动作资格投影错误,不是服务端越权或数据损坏。
|
||||
- 移动报销详情当前没有撤回操作,本轮只修复存在缺陷的 PC 入口,不增加移动操作。
|
||||
- 材料合并服务先对图片执行 Sharp `rotate()` 自动应用 EXIF 方向,但页面尺寸读取自旋转前 metadata。方向为 6/8 的手机图片会出现“输出像素已转向、PDF 页面仍按原宽高”的不一致。
|
||||
- 现有合并预览按发票在前、补充附件在后排序;`BX-20260828-0017` 有两张 PDF 发票和两张 JPG 补充附件。此前只读核查已确认 JPG 实际为发票图片,但未打开或持久化原件,尚不能仅凭附件列表断定“首张图片未显示”的最终技术原因。
|
||||
- 现行业务规则要求:只读审批人不得看到编辑、解绑、删除等数据变更动作;图片各占合并 PDF 一页,合并失败时保留逐份原件查看路径。
|
||||
|
||||
## Scope
|
||||
|
||||
- 修复 PC 报销详情中 owner/submitter 与财务只读查看者的撤回动作可见性。
|
||||
- 修复服务端材料合并时 EXIF 自动旋转后仍沿用输入尺寸的问题,并更新合并器版本。
|
||||
- 使用合成数据覆盖前后端回归;对 `BX-20260828-0017` 仅执行受控、脱敏、生产只读诊断。
|
||||
- 保持服务端授权、审批状态机、材料顺序、原件查看与失败降级合同不变。
|
||||
|
||||
## Requirements
|
||||
|
||||
### R1 PC 撤回动作资格投影
|
||||
|
||||
- PC 报销详情仅在当前用户是报销单 owner 或 submitter 且状态为 `reviewing` 时显示“撤回报销”。
|
||||
- 财务、审批人、管理员等因 `expense.view_all` 或当前审批职责获得只读详情访问时,不得看到撤回输入框或按钮。
|
||||
- owner/submitter 在 `reviewing` 状态下继续看到并可使用现有撤回入口;草稿、驳回、已通过、已支付等既有状态行为不变。
|
||||
- `ReimbursementActions.showWithdrawAction` 必须改为无默认值的必填 prop,让遗漏资格投影在 TypeScript 编译期失败,不保留 fail-open 默认行为。
|
||||
- 服务端撤回资格校验、权限矩阵、审批状态机和审计合同保持不变,前端不能把隐藏按钮当作安全边界。
|
||||
|
||||
### R2 EXIF 图片合并尺寸修复
|
||||
|
||||
- 图片经 Sharp 自动旋转、扁平化和 JPEG 规范化后,必须使用实际输出的宽高创建 PDF 页面和绘制图片,不得使用旋转前 metadata。
|
||||
- 方向为 6/8 的合成 JPEG 应在输出 PDF 中保持正确的纵横方向和比例;无 EXIF 或无需旋转的 PNG/JPG/WebP 行为保持不变。
|
||||
- 继续执行现有图片像素、页数、输出大小、确定性字节、整包失败和逐份原件降级合同;不引入新依赖、不把合并件当作原件。
|
||||
- 合并算法的可见输出发生变化后应更新 merger version,避免新旧算法产物共用同一集合缓存身份。
|
||||
|
||||
### R3 `BX-20260828-0017` 首图只读诊断
|
||||
|
||||
- 在实施获批后,使用既有受控生产只读访问,确认材料实际顺序、MIME、字节/像素元数据、EXIF 方向、合并页数和对应页尺寸;现有事实已将用户所称“第一张图”锁定为合并 PDF 第 3 页,诊断从该页开始,仅在必要时生成短生命周期的本地临时派生预览。
|
||||
- 诊断不得写生产数据库、报销、审批、付款、对象存储或企业微信;不得把原始票据、图片、完整票号、存储位置、签名 URL、原始 payload 或凭据写入仓库、任务文档或聊天。
|
||||
- 临时原件或渲染页若确有必要,只能放在明确的安全临时目录,诊断完成即删除;交付只记录脱敏元数据和结论。
|
||||
- 若证据确认问题由 EXIF 尺寸错误造成,使用 R2 修复覆盖;若属于 PDF `AcroForm`、可选内容组、损坏源文件或其他超出当前图片合并边界的原因,只形成证据并返回规划,不临时替换 PDF 引擎或扩大任务。
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
- [x] 复用现有 `adminMe + ownerId=employee-other-r102 + status=reviewing + scope=all` 合成场景;管理员作为非参与只读查看者打开报销详情时,页面不存在 `reimbursement-withdraw` 和撤回意见输入框。
|
||||
- [x] 同一状态下,合成 owner/submitter 仍能看到现有撤回入口;其他状态的既有动作投影不变。
|
||||
- [x] 服务端非 owner/submitter 撤回拒绝合同保持通过,未修改权限矩阵、状态机、工作流或数据库结构。
|
||||
- [x] 带 EXIF orientation 6 和 8 的合成图片合并后,PDF 页面宽高与规范化输出一致,方向和比例正确;普通横图、普通竖图和 PNG/WebP 回归通过。
|
||||
- [x] 相同有序材料在同一 merger version 内重复生成时字节完全一致;跨 merger version 允许因修复产生不同字节。材料顺序、页数上限、整包失败和原件降级合同不变。
|
||||
- [x] merger version 随算法修复更新,新的集合缓存身份不会复用旧算法产物。
|
||||
- [x] `BX-20260828-0017` 首图形成一份不含原件和敏感字段的只读诊断结论,明确材料顺序、问题类别、是否由 EXIF 修复覆盖,以及未覆盖时的下一步。
|
||||
- [x] 前端 typecheck/build、后端聚焦 Vitest/语法检查、相关 Playwright、Trellis 治理和 `git diff --check` 通过。
|
||||
- [x] 未经另行批准不部署公网;部署与公网检查完成前不告知用户线上可测试。
|
||||
|
||||
## Out of Scope
|
||||
|
||||
- 财务审批页一页式重构、按钮“处理”的改名或待办信息结构调整。
|
||||
- 费用类型、会计科目、发票—明细关联、票面金额差异门禁、多票拆分、图片发票上传提示或附件用途治理;这些属于 Task B。
|
||||
- 修改、撤回、退回、审批或付款任何真实报销;重分类或重新上传 `BX-20260828-0017` 的图片附件。
|
||||
- 修改服务端撤回授权、角色/权限矩阵、审批规则、状态机、schema、迁移或生产配置。
|
||||
- 引入 PDF.js、Poppler、新 PDF 引擎,或在未重新规划时处理 PDF 表单域/可选内容组兼容。
|
||||
- 修改 `ReimbursementActions` 现有撤回默认说明文案“申请撤回并补充说明后重提”。
|
||||
- 对 `BX-20260828-0017` 执行真实单据处置,包括退回、例外接受、重传 PDF、重分类附件或修正票面合计;该单据应按现行规则另行作出业务处理决定。
|
||||
- 公网部署、生产写入、企微写入和真实付款。
|
||||
|
||||
## Risks and Constraints
|
||||
|
||||
- 隐藏动作只能改善正确性和体验,安全仍由服务端对象资格校验负责。
|
||||
- EXIF 修复可以解决旋转后尺寸不一致,但不能预先证明 `BX-20260828-0017` 的首图问题只有一个原因。
|
||||
- 真实材料含敏感信息,诊断必须最小读取、只保留脱敏摘要,并对临时文件 fail closed。
|
||||
- 现有视觉回归夹具中 owner 视角明确期待撤回按钮可见,修复不能简单删除该操作;需要新增非参与高权限查看者断言。
|
||||
|
||||
## Test Plan
|
||||
|
||||
- 后端聚焦:`cd server && npx vitest run tests/unit/services/reimbursementMaterialPreview.test.js tests/unit/routes/reimbursements.attachments.test.js`。
|
||||
- 后端基础:`cd server && node --check src/services/reimbursementMaterialPdf.js && node --check src/services/reimbursementMaterialPreview.js && npm run prisma:validate`。
|
||||
- 前端:`cd client && npm run typecheck && npm run build`。
|
||||
- Playwright:复用 `r102-reimbursement-main-flow.spec.ts` 的 admin 非参与人全范围夹具增加撤回不可见断言,并保留现有 owner 可见断言;route mock 场景继续阻断 Service Worker。
|
||||
- 只读诊断:以脱敏元数据核对 `BX-20260828-0017` 材料顺序、EXIF/像素和合并页尺寸,不保留真实材料证据。
|
||||
- 治理:`node scripts/qa/check-process-contract.mjs --baseline --json`、`node scripts/qa/audit-docs.mjs --check-registry`、`node scripts/qa/check-trellis-governance.mjs`、`git diff --check`。
|
||||
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"id": "reimbursement-detail-material-preview-fixes",
|
||||
"name": "reimbursement-detail-material-preview-fixes",
|
||||
"title": "报销详情权限与材料预览缺陷修复",
|
||||
"description": "修复财务只读查看报销时误显示撤回操作、EXIF 图片材料合并尺寸错误,并对 BX-20260828-0017 首图异常做脱敏只读诊断。",
|
||||
"status": "in_progress",
|
||||
"dev_type": null,
|
||||
"scope": "client reimbursement action projection; server material PDF image normalization; production read-only preview diagnostics",
|
||||
"package": null,
|
||||
"priority": "P0",
|
||||
"creator": "shunli",
|
||||
"assignee": "shunli",
|
||||
"createdAt": "2026-08-28",
|
||||
"completedAt": null,
|
||||
"branch": null,
|
||||
"base_branch": "main",
|
||||
"worktree_path": null,
|
||||
"commit": null,
|
||||
"pr_url": null,
|
||||
"subtasks": [],
|
||||
"children": [],
|
||||
"parent": null,
|
||||
"relatedFiles": [],
|
||||
"notes": "任务范围内聚焦验证通过。完整 r102 为 5/6,唯一失败是既有用例仍查找已不存在的‘编辑’按钮;本任务新增的管理员撤回不可见断言通过,不把该历史失败静默视为绿色基线。",
|
||||
"meta": {}
|
||||
}
|
||||
在新工单中引用
屏蔽一个用户