文件
hyb-oa/.trellis/tasks/09-08-reimbursement-payment-closeout/design.md
T
wangsli b7d2285d8d
ci-e2e / e2e (push) Canceled after 0s
ci-minimal / check-minimal (push) Canceled after 0s
fix: 完善回单失败引导及真实认证验证(09-08-reimbursement-payment-closeout)
2026-09-15 15:26:08 +08:00

27 KiB
原始文件 Blame 文件历史

业务闭环方案(分阶段实施,发布状态见执行记录)

2026-09-15 系统失败引导最小收口

从未归档附件投影是否存在system_failed/key_failed/snapshot_failed;仅在现有readiness未满足横幅中优先展示管理员排障引导,不修改canRegisterPaymentComplete或服务端资格。其他可用证据满足readiness时不因旧失败附件新增阻断。重新核对按钮仍只读refetch,不发OCR。恢复沿用修复前提后另批重新上传原件的现有路径,旧附件与审计保留,不引入新的管理员角色权限或批量SQL重排队。

2026-09-13 回单核对增量设计

2026-09-14 人工核验执行细化

最终占用实施:PaymentReceiptClaim补具体人工提案外键,另增交易身份别名唯一表,原/新身份均绑定同一个claim及item。自动和人工路径共用事务advisory锁;别名与claim一起回滚,登记前再次检查人工原证据、提案版本、当前审核人角色/权限及全部参与人关系。银行渠道只核银行项,不把现金历史强改为银行。占用服务、execute及UI readiness已接线并完成本地定向验证;不允许通过测试mock绕过业务门禁。整批独立复核及生产验收仍未完成。

页面接线:沿既有回单卡打开核验对话框,不新建中心。只读详情返回版本、页数、逐页识别摘要及人工提案摘要,账号始终掩码;原件继续用既有受控预览。默认保留识别字段,只选对应付款明细;更正时仅提交有变化的字段,服务端在当前版本原证据上合并,不让前端回传掩码覆盖完整账号。未知/失败/处理中状态不默认成功,修改内容与复核理由不入普通日志。详情查询绑定当前身份并传AbortSignal,切账号/批次关闭对话框,不共享上一身份数据。页面操作不调用execute。

持久化顺序:新增独立人工提案表,绑定原verification、附件SHA和递增版本,原证据不覆盖。保存更正为pending_review;仅消歧为association_ready,不冒充独立审核通过。复核只能处理当前版本pending_review,拒绝为rejected、批准为approved;更正内容整包加密,API仅安全摘要。保存与决定均与审计同事务,审核前重建匹配并检查当前交易占用。此表不是paid或claim凭证,后续execute需重新核版本、提案和原/新指纹。新增迁移只在一次性数据库验证;生产不执行,存在提案后不得删表回退,前向修复为默认。

execute接线的硬约束:人工提案先获批不等于已占用银行交易;两个批次先后核验通过仍须在登记时串行化重查。若更正了可识别的原付款账号/参考,最终登记除保存新指纹外还需持久保留原身份的唯一占用关系,不能只在提案时查一次原claim,否则以后使用原参考的另一回单可能绕过重复检测。最终claim须关联具体人工提案版本/批准记录,不仅引用原OCR结果。此部分已通过具体提案外键及交易身份别名实现,并验证登记事务回滚与自动/人工竞争;不代表生产已启用。

先实现内部人工提案校验,不先开付款旁路。输入为服务端读取的原识别证据、冻结候选以及逐页人工字段和明细选择;页数完整、每页唯一明细、交易身份唯一,金额/币种/完整账号仍重新精确匹配。只做同额消歧且未改识别事实的关联不增加日常审批;任何字段更正或OCR不可用均进入独立复核。原证据的明确失败/处理中不能由人工改成成功;状态别名冲突中出现失败/处理中也保留否决线索。

人工提案保留原证据引用及规范化字段来源,内部敏感结果必须加密后落库,不能直接序列化为API响应。纯函数结果不构成授权或付款凭证;后续事务接口须校验当前附件版本/SHA、审批角色与非经办/非申请人身份,审计与提案同事务落库。未接这些接口和前端前,execute不接半成品门禁,不部署。

此节为已采纳方向的技术拆解,未改变运行时。旧制单与布局内容作为历史阶段保留;不把旧“未实施”标题当成当前全部功能状态。

接入与边界

2026-09-14接线更新:新上传与附件记录同事务置queued,启动路径在jobsEnabled下分别接cron/pgboss独立回单tick;历史legacy不自动处理。显式重试采用expectedVersion CAS(批次→附件锁),已排队/已匹配不重排,processing达到15分钟或legacy/ocr_failed/needs_review才可重试,递增版本使旧结果立即失效并写审计。读取接口投影状态/版本/开始时间和同源重试资格,不返回规范化账号;PC/手机沿原回单卡片展示及5秒有界到终态轮询。该段替代下方历史“未接线”描述,不表示人工核验或execute守卫已经接入。

后台单次执行器采用数据库queued/processing状态及版本化领取,既有附件默认legacy不自动重识别;claim在短事务内完成,文件读取和外调在事务外,结果另起事务核版本。进程中断留下processing供后续明确重试,不能在不知道腾讯是否已处理时无限自动重传。最终cron/pgboss只作为唤醒机制,数据库领取是共同排他事实源;调度与上传入队尚未接线。

  • 复用paymentBatches回单上传/预览/作废/execute入口及现有权限、部门范围、制单人和复核人分离规则,不新建回单中心。
  • 专用BankSlipOCR适配,不调用发票落库/绑定/归档业务。复用腾讯SDK配置与有界后台作业机制前,先核实现有队列的任务隔离和幂等合同。
  • 官方腾讯SDK确认交易金额/币种/账号/流水/手续费/日期等字段及PDF逐页请求;不承诺所有建行版式都有明确成功状态、置信度或流水。WEBP等已接受文件需安全转换或标待核验,不将旧上传格式悄悄禁用。
  • 原始文件保持私有;腾讯请求走服务端受控传输,不建公开下载URL。只持久化必要规范化字段,账户加密及交易身份带密钥摘要方案须结合既有加密合同细化;日志只留原因码和请求标识,不保存整个OCR响应。

核验模型与一致性

2026-09-13 持久化实施:PaymentReceiptVerification绑定附件SHA、receipt_ocr_version与页数,规范化白名单字段整包加密;PaymentReceiptMatch按页关联batch item;PaymentReceiptClaim以HMAC(CCB域、付款账号、交易参考)为主键且item唯一。指纹使用现有fieldEncryptionKey并存key ID;若历史claim使用其他key ID则阻断,必须另审密钥轮换迁移,禁止换密钥绕过去重。流水号优先、凭证号为备选,缺失/冲突待核验;这不是银行验真。

storeReceiptRecognition由已授权内部调用方在事务内调用,锁批次后锁附件,再核状态/批次关联/SHA/版本;晚到作业不能恢复作废或新版核验。未来重试/人工更正须先在同锁序下递增receipt_ocr_version。claimVerifiedReceipts要求调用方先锁批次,随后固定命名空间1002的事务advisory锁串行化占用,再锁附件;重新解密核验当前冻结付款数据,只接受最新同版本有效完整结果。claim与最终登记必须同事务提交/回滚,数据库双唯一约束为最后保护。

迁移为新增三个表及附件默认0版本列,不回填历史paid核验结果、不删除业务资料。回退空的新结构可仅在隔离环境或另批操作下逆向删除;一旦生成证据/claim,生产不允许直接删表或退无门禁旧应用继续登记,需保持写入隔离并前向修复/兼容修订。当前服务未接路由、队列及人工复核,数据库测试通过不代表授权/公网业务链通过。

  • 文件安全治理与交易核验必须独立;现有governance_status=approved不表示金额/付款已核验。另建核验版本、处理状态、页/交易记录及付款明细关联,不复用附件标签表示业务放行。
  • 区分等待识别、处理中、待核验、匹配、不符、识别失败;多页完整性、页内交易数量及未知格式均显式处理。晚到作业需比对版本和作废状态,不复活过期证据。
  • 金额用精确十进制或最小货币单位比较;不合并同人多单。账户身份和交易币种/本金为必要证据,编号和日期用于消歧但不能覆盖硬性不符。
  • 重复交易以银行/付款账户/交易身份建立持久化占用和事务约束;哈希相同不足以判断全部重复,换文件/重传也不能重复登记。同额歧义进入人工关联而非按列表顺序猜。
  • 上传和OCR不写paid。execute在现有锁/事务边界重新核有效证据、匹配版本、来源单状态/金额、重复交易占用,再允许现有登记流程;前端禁用不代替后端守卫。
  • 人工更正保留字段来源和历史;确需OCR故障例外时采用独立非经办复核,不免除明确不符/重复/失败交易约束。具体接口/权限与数据约束在实施前补齐,不能先发布可绕过的临时入口。

历史与发布

已executed/已付款不重开、不自动回填“已核验”。尚未登记的旧批次不能仅因旧附件存在绕过新门禁,需适用新核验或明确受控人工核验。迁移采用附加结构,不删除原件或改历史金额。

本增量会增加登记安全门:旧镜像可能忽略核验结果,回退不能只以schema兼容判安全。发布前必须冻结新候选、核备份/迁移/回退策略;已产生核验数据后禁止未经评估直接退旧版继续登记。

已读取的外部依据与自限

2026-09-13腾讯云官方Python SDK:ocr/v20181119/ocr_client.py的BankSlipOCR及models.py的BankSlipOCRRequest/Response。支持银行回单字段识别和PdfPageNumber逐页请求;它不是银行交易查询或验真接口。链接:https://github.com/TencentCloud/tencentcloud-sdk-python/tree/master/tencentcloud/ocr/v20181119 。未取得可靠建行验真或国内产品详细规则资料,不虚构行业强制规则;真实建行样式与外调效果仍待专门授权验证。

2026-09-11 已批准备注增量

最新确认仅修改buildPaymentOrderRows的备注列,使用“报销款 ”与已验证且已trim的entityCode拼接,不再拼接姓名。收款户名列的payeeName仍来自组批冻结的snapshot_json.payee.name;路由将归属人的收款信息冻结为payee,生成器不另查现职员工/提交人。每个batch item保持一行,即使姓名/收款账号相同也不合并;一个批次仍允许多张报销单。姓名或单号为空沿现有blockers整批拒绝。

不改模板列宽/格式、不缩写或截断、不引入未经银行证明的长度阈值。测试使用合成姓名,逐列xlrd读回用途、备注及文字类型,并证明同名两单独立对应、旧序号不重排。BX/PB编号规则本轮不改;编号说明以PRD最新节为准,不将日期前缀误当每日重置的证据。

1. 复用而非重建

现有入口是付款页面的待组批、付款批次、复核及“下载银行制单”。后端 POST /api/payment-batches/:id/payment-order 要求财务角色与 payment.order.export,批次 reviewed,完整且可用的同源收付款快照。生成成功会更新导出计数和审计;不能把这个 POST 当作生产只读预检。

代码入口:server/src/routes/paymentBatches.js、server/src/services/paymentOrderXls.js、server/src/scripts/fill-payment-order-template.py、client/src/pages/PaymentBatchesPage.tsx。历史范围见 archive/2026-08/08-02-corporate-bank-account-payment-order,本 task 不重开已完成实现。

2. 模板映射

列 模板字段 报销付款来源/行为
1 序号 稳定排序的批次行号,文本
2–3 付款方账号/账户名称 复核批次冻结的公司付款账户
4 收款方行别代码 CCB 本行固定文本 01,不生成他行 02
5–7 收款账号/名称/开户行名称 同一批次的收款快照
8 收款方联行号 沿现有本行制单合同留空
9 客户方流水号 批次号+行号,稳定、唯一并满足长度限制
10 金额 已批准批次项金额,数值且两位小数
11 用途 报销款,不复制工资/公积金用途
12 备注 “报销款 ”+完整报销单号,不重复姓名(09-12最新确认)
13–15 短信标志/手机/附加信息 0、不通知,后两列空;不读样例手机号

用户三个 input 文档的表头完全一致,空白模板与内置模板相同,账号列为文本。检查原件只提取结构与摘要,原件不改、不重新保存、不复制真实行到测试夹具。工资及公积金样例仅用于确定文件格式,不暗中扩为新业务。

3. 两条业务线

A:0014 当前已审批待付款 → 核定归属/主体 → 管理员直接维护真实 CCB 收款资料 → 财务重查 readiness → 财务组批 → 独立付款复核 → 财务下载 .xls → 授权人员网银导入核对并付款 → 回单与实际结果匹配 → 系统登记。

B:三张 rejected → 本人逐张修改 → 本人重提 → 实际审批人处理 → 通过后进入下一批付款。不等 A 或 AP 发布;未通过不能直接放入付款批次。

4. 停止条件与授权

  • 身份、单号、原值不一致,或收付款资料非 CCB:停止对应操作,不按名字/唯一主体猜值。
  • 生产 legal_entity_id 修正:单人单字段、前置锁定和原值检查、条件写入、提交后独立回读;须单独授权。失败不自动反复重试,回退另批。
  • 银行真实资料由管理员/获授权维护人直接在系统录入;不让财务通过聊天转交卡号给执行端。
  • 解密/生成真实制单涉及敏感数据;按明确范围批准,只输出脱敏验收结果。正式下载由财务操作且保留审计,不用管理员或伪身份抵扣。
  • 已存在批次、复核不通过、资料变动或旧快照缺失:核实实际状态,不删批次或改数据库状态绕过。是否重建批次另行决定。
  • 银行导入失败、部分成功或回单未核对:不标全批成功,不因重下载重复付款。

5. AP 发布独立处理

AP task 保留原实施写入面和已通过用户复核。提交/推送后冻结包含 CEO 撤权的完整新 SHA,重新核对发布所需时效、回滚制品和生产漂移;旧 58dcee0 不再是正确候选。没有新发布授权就不部署,不能因业务急付款而默认豁免门禁。

6. 验证层级

  1. 首轮规划完成静态源码与原件结构检查;用户追加技术审查/修复授权后运行定向合成测试,并在当前生产容器以独立合成密钥和纯合成资料验证制单运行环境。后者不访问数据库、不用真实密钥、不读取真实银行卡、不调用正式导出接口、不落制单文件。
  2. 执行阶段先用合成收付款数据核验模板、BIFF8、金额与文本类型、未复核拒绝、非建行拒绝、重下载与审计、付款角色分离;已有测试能复用则不另造。
  3. 获准核实生产模板摘要、Python/固定依赖等运行前提时,不顺手触发真实导出;代码基线存在功能不等于生产运行时可用。
  4. 真实财务路径、银行导入结果与最终回单属于业务验收,合成测试不能抵扣;分别记录未执行/通过/阻断,不提前全绿。

7. 八角度复核与修订

角度 审查结论 处理
业务优先级 已审批 0014 和退回三单是不同状态,不互等 维持两条业务线,不把 AP/门禁作为重提前置
角色职责 财务可制单不等于可改员工银行卡;admin 通配也不替代制单路由的财务角色要求 管理员录资料,真实财务组批/导出,非制单人复核;不加权限
资料与隐私 付款方账户已有,但个人收款资料和所属主体缺失仍是真实阻断 按原值另批补 0014 归属人,不批量关联 smoke;敏感资料不进聊天
财务操作顺序 当前详情页未制单先把上传回单作为主动作,下载藏在更多,与原银行制单合同及本轮顺序冲突 最小修复动作模型:首次下载→上传回单→登记完成;人工上传保留在更多,不添加硬门禁
格式兼容 原件和内置模板一致;既有测试只验文件头、行数、总额等,缺少独立逐列读回 新增 xlrd 对生成文件的表头、列宽、工作表、前导零文本、金额与用途/备注读回断言
运行环境 本地普通 Python 可能无 BIFF8 依赖,不能据此推断生产缺失 使用既有固定 venv;生产容器合成生成/独立读回 PASS,不安装新依赖,不改生产
失败与重试 下载有审计写入;导出不等于付款,网络失败后的重下载也不能重复银行划款 补下载原因/取消零请求、文件成功下载、重下载警示、失败不推进状态、手工回单入口测试
发布与实际付款 当前正确 AP 修订与本轮界面补丁都未部署;银行文件“验证”和真正导入可能不分离 新候选另批;只有网银明确支持不提交的校验模式才做真实文件格式校验,否则不为测试上传文件,实际付款须按业务批准办理

本轮界面修复仅改变已选付款详情的动作优先级,继续使用既有按钮/更多/移动端固定操作区,不重画页面、不调整角色、审批、付款状态机、数据快照或后台接口。保留现金/历史批次人工付款、已有回单直接登记及回单查询失败时不冒充空状态的行为。

报销主体和收款资料应在组批前补齐,因为批次冻结的是当时的账户快照;生成文件不能静默取之后变更的个人账号替换已复核快照。已有批次若需取消/重建,重新交审,不直接更新旧快照。

2026-09-09 后续主线综合方案(规划,非部署授权)

范围与归属

付款体验沿用本 task;退回单删除/历史可见性归 09-04-reimbursement-state-gap-finance-view;选票后自动生成明细与关联归 08-29-reimbursement-expense-policy-invoice-guard。用户已确认该默认操作取向,本轮按要求更新规划;撤回上一版正常路径的“待关联区→手工建明细→再关联”。验证随对应功能共同交付,不为每个按钮、测试或部署后检查新建 task,不启动 09-07 认证任务的历史批量迁移。各 task PRD 的同日增量是本次需求入口,本文组织跨任务依赖,不覆盖旧阶段事实。

当前生产已发布 b87cc55;用户确认付款复核及文件下载可用,尚无实际支付完成证据。原主工作树含其他未提交治理/状态差异,实施从最新已发布/已推送基线的干净独立副本开始;按官方 task current/start 对齐实际执行目录,已部署副本及冻结包不改。两个报销子项有共享文件,可在同一已批准的报销修复副本协调,但必须有各自验收和可审增量;付款变更单独副本,不能将路径隔离冒充文件不重叠。

第一批:报销录入与退回重建

先核实删除事务、workflow 历史、材料关系、占用/去重、查询投影及绑定接口,再完成最小设计补充。界面“删除退回单”,存储层保留历史,优先复用能表达该语义的已有机制;不得假定只有删除按钮变化或无需 schema。若发现必须迁移或实质扩大历史访问/数据修复范围,明确变更清单与回滚后再交审,不偷偷切状态掩盖删除。

退回原单修改重提保持可用;不再使用的单据确认删除后停止流转,解除合法发票的有效占用。软删除/取消历史如何读取、原附件如何保留、财务查询/待办如何排除均列入服务端合同。禁止把“可读历史”误扩成“可继续操作旧单”。撤回变 draft 但有历史的单据要单列,保护原审批留痕。

默认点击“添加发票”打开“我的发票”面板,选择可用旧票或上传新 PDF;新票自动腾讯 OCR,识别成功默认勾选且尊重用户取消。点击“添加到报销单”才触发一票一条可编辑明细并自动关联,多选批量生成;不是 OCR 完成就悄悄创建明细。票面价税合计、开票日期、项目说明作可编辑初值,类型仅可靠时推荐,不确定只补必要字段。用户无需再关联,正常明细仅显示发票数量/预览;手动关联仅保留为异常修复。已有明细入口则直接添加票到指定明细,不生成新明细或覆盖原值。允许提前存票,池和报销内使用同一数据来源。明细生成/票据占用原子完成,失败逐票解释、重试幂等;票据门禁仍严格。费用发生日期不能被开票日期无提示替代,不虚构缺失金额/类型;详细数据兼容与事务方案在发票 task 收敛。

第二批:付款下载与详情体验

后端输出中文文件名并使用兼容的 Content-Disposition 编码;前端解析中文 filename*,本地回退名一致,浏览器实测下载名而非只断言 toast。保持 BIFF8 模板、列顺序、格式、金额与批次内容不变,文件名不引入敏感资料。

制单接口单独调整原因合同,不放宽共享 REASON_SCHEMA。系统记录用途来源、操作者、批次、生成序次、成功/失败等必要审计;用户不填理由,不以固定文字假装用户说明。首次确认敏感文件用途,再次确认重复付款风险,权限/状态门禁与防双击保留。取消批次、查看完整账号、回单下载/作废的现有理由策略不在本轮改变。

只将 ProcessingProgress 移到付款页操作卡片下方,复用既有组件/样式,桌面与窄屏验证阅读和键盘顺序。本地未提供 frontend-design skill,不引入新视觉系统;不顺手改报销页壳或进行大文件重构。

验证先行,执行端负责

  1. 实施前用合成数据复现空单添加发票和退回不能删除的原状,明确测试预期是新业务要求还是既有回归;先有可复现用例,避免按现状写出假绿。
  2. 每个改动有单测/路由测试,状态、权限、并发、历史可见性有反例。单测可 mock,但证明业务闭环的端到端测试必须使用真实应用后端、隔离 PostgreSQL、附件存储与合法登录;不 mock 核心业务 API 后声称真实流程通过。
  3. 使用专用合成申请人、审批人、财务,按角色分别登录操作。独立复核约束必须保留,不能全程拿 admin 通配抵扣角色验收。合成票据不得含真实银行资料;真实腾讯 OCR 自动识别是交付要求,关闭/误配属于异常,不再作为正常成功分支。需要获准样票和调用条件,缺条件时由执行端准备补齐方案,不能用 mock 或数据库 provider 标记冒充真实识别成功,不擅自改生产密钥或发真实票据。
  4. 浏览器必跑空单→我的发票弹窗上传→自动 OCR→选新/旧票→自动生成明细并关联→刷新→核对/补必要项→提交→审批→独立付款复核→下载,以及提前存票、多选票、取消选择、已有明细多票、部分失败/重试/并发、退回修改重提、删除退回→释放发票→新单重用→提交。不允许测试夹具预造明细或手工补一次关联来掩盖默认路径失败。网银付款不自动执行,回单/付款登记仅在完全隔离测试环境使用明确标记的合成资料。
  5. 桌面/窄屏核验右侧进度布局,实际下载文件名、BIFF8 结构及重复下载提示;截图/日志脱敏,不能输出真实票据、银行账号或凭证。
  6. 涉及状态/权限/数据合同,需只读独立复核;inline 不能派 implement/check 代理,准备明确交审包,不能把主会话复测冒充独立复核。

发布与部署后验证合同

每批独立提交、集成验证、冻结候选;提交/推送/部署分别按明确授权执行。两批可以分别交付,不让付款的小优化必须等报销模型改造,但不能积压多批未提交差异。既有完整候选门禁仍有缺口,局部业务链全绿不等于完整候选全绿;发布资格按完整门禁或新的明确例外处理,旧 b87cc55 例外不复用。

上线前先确认可执行的部署后检查方式,不能部署完才发现没有测试账号。执行端负责公网版本/资源、权限、接口及浏览器验证,不把员工的日常业务操作当 QA。

生产写入验证必须先形成并获批测试数据清单:专用账户与角色、测试业务主数据/主体及付款资料、标记、允许接口、预期记录数、通知去向和收尾方式。能保证隔离才执行;专用账号本身不保证隔离,要防止真实审批派给员工、真实通知、预算/报表污染及测试制单流入网银。不改真实账号角色、不拿当前真人单据做删除/重提测试。

若生产无法安全隔离写入,先提供与候选同制品的隔离环境完整验证,再做公网只读/无副作用检查;明确生产写入链未验证,不声称等价,也不让员工补测。缺条件时执行端准备补齐方案,需新增权限或生产写入授权才向用户提出具体请求,不反复索取同范围许可。

每批回执分列:代码/本地单测/真实后端 E2E/独立复核/部署/公网验证/剩余缺口/下一动作。未执行、被环境阻断或失败均不能算通过。测试数据只按获批收尾规则处理,不能为清理测试痕迹物理删除审计或正式单据。

暂不扩展

不修改六个 view_all、不启用 R1/合同阶段 B、不逐条修 58 条、不实施通用软删除框架、不重构全部报销页面。统一待办投影是后续主线,本轮只保证本次删除/提交产生的待办正确更新;不以此另造待办引擎。错误豁免 10-05 到期事项沿原任务继续跟踪,不能因本轮反馈被遗忘或统一延期。生产磁盘已清理至足够余量的近期观测只是发布输入,下一次发布仍需检查时效,不追加清理。

2026-09-10 付款体验实施补记

  • 制单接口使用专用可选原因合同;空对象有效,旧客户端的合法真实原因兼容,非法原因/未知字段仍拒绝。共享必填原因合同不变。
  • 成功、重复和生成失败审计标明系统用途及来源;不以固定文本冒充用户原因。权限失败/请求校验失败沿既有位置拒绝,不虚报进入生成审计。
  • 文件名使用现有安全 Content-Disposition 工具,UTF-8 中文名和 ASCII fallback;前端缺少响应文件名时使用批次号兜底,模板和二进制生成不变。
  • 保留敏感文件确认、重下载警告、取消零请求与 pending 防重复点击。下载次数更新后主动作仍切换上传回单,不表示付款完成。
  • 右侧操作卡与进度卡相邻;移动端保留底栏快捷动作且正文操作/进度可达。操作卡不独立 sticky,避免滚动覆盖紧随其后的进度。
  • 验证:路由与 BIFF8 单测、mock 桌面/移动端真实下载、隔离 PostgreSQL/真实认证 HTTP 创建复核下载,再与退回删除做同候选验证;禁止真实网银付款和伪造回单。