43 lines
5.7 KiB
Markdown
43 lines
5.7 KiB
Markdown
# 合同附件下载开发记录
|
||
|
||
## 2026-09-08浏览器成功路径补验
|
||
|
||
新增`backend/api/internal/logic/client/user/gas_contract_download_remote_test.go`:默认跳过,显式设置HEQI_CONTRACT_DOWNLOAD_FIXTURE=1和当前API文件根目录时,为授权测试账号创建一条独立的已终止测试合同及测试PDF,不修改任何既有合同。最长等待5分钟,收到完成标记或超时均清理独立记录与文件;普通单元测试不连接远程。强制终止进程无法保证defer执行,禁止用强杀结束该夹具。
|
||
|
||
实际验证已通过:浏览器从个人中心进入供气合同,点击“PDF下载验证文件(非业务合同)”的下载按钮,真实鉴权接口返回200,浏览器在Downloads生成619字节PDF。下载文件与服务端原文件SHA-256均为`D5B86BEB045675F863B06D9B75A60FBCEC4E09E8E9CA7543E599672A40AC3820`。PDF经Poppler识别为单页A4、PDF1.4,无JavaScript,已渲染并目视确认“DOWNLOAD TEST ONLY - NOT A BUSINESS CONTRACT”。Poppler报告本机Symbol/ArialUnicode显示字体不可用,但验证页使用Helvetica,文字完整;文件长度以Get-Item和哈希校验为准。
|
||
|
||
测试夹具运行84.42秒后PASS;再次读取真实接口仅剩原MOCK-CONTRACT-001,测试合同数0,服务端测试PDF不存在。Downloads中的测试副本已转存到验收证据并清理原下载位置。相关Go用户逻辑测试与vet通过,无生产代码改动,无需重建既有App产物。
|
||
|
||
证据:[实际下载PDF](视觉验收/A1/合同下载_浏览器测试.pdf)、[下载PDF渲染](视觉验收/A1/合同下载_浏览器测试.png)。**Web下载成功路径已验证;Android/iOS系统保存对话框仍待真机验收。** 原业务合同仍缺附件,不能将本测试文件作为其签署附件。以下保留上一轮实施记录。
|
||
|
||
操作时间:2026-09-08。操作类型:扩展。影响模块:本人合同、受控PDF文件输出及本地保存。
|
||
|
||
## 行为变化与关键代码
|
||
|
||
- backend/api/internal/logic/client/user/gas_contract_attachment.go:新增DownloadGasContractAttachment,GET gas/contracts/:identity/attachment限定JWT本人且未归档合同,不接受路径或外部URL。
|
||
- backend/api/internal/logic/platform/gasorder/contract_attachment.go:抽取ServeAuthorizedContractPDF供已经完成鉴权的调用方复用,保留平台原入口。继续验证合同存储前缀、根目录边界、文件类型与10MiB限制,响应private/no-store、nosniff、sandbox;不公开存储路径。
|
||
- backend/api/internal/routers/client.go及client_test.go:新增受保护附件路由与存在性回归。
|
||
- apps/user_app/lib/data/services/api_client.dart:getBytes新增可选Accept参数,旧图片调用兼容。
|
||
- apps/user_app/lib/data/repositories/client_repository.dart:gasContractPdf校验会话、缺失、大小及%PDF-文件头,错误JSON不能当PDF保存。
|
||
- apps/user_app/lib/ui/features/orders/contract_download_button.dart:读取完成后交给系统保存;防重复点击、文件名清理、取消不报成功、失败可重试。错误原因持续显示在按钮下方并通过liveRegion播报,重试时清除;Web只提示已交给浏览器下载,不声称浏览器已完成落盘。
|
||
- gas_contracts_page.dart、gas_order_sections.dart:合同列表与正文均可下载,常规宽度与查看按钮并排,窄屏大字体分行。
|
||
- pubspec.yaml/lock:新增file_saver 0.4.0(带dio、dio_web_adapter);保留原依赖约束,使用字节保存,不把鉴权令牌或服务端私有路径传给插件。参考[插件官方文档](https://pub.dev/packages/file_saver)。
|
||
|
||
## 测试与当前证据
|
||
|
||
后端gas_contract_attachment_test.go覆盖本人实际文件字节、外部URL拒绝、越界拒绝、文件缺失、非本人合同以及响应头。平台原附件测试、用户逻辑与路由回归通过;Go全量测试、vet及API构建通过。Flutter新增gas_contract_pdf_test.dart与contract_download_button_test.dart,覆盖缺失、错误JSON、迟到会话、失败重试和系统取消。analyze与全量102项测试通过,正文入口增加按钮后两项详情回归通过。
|
||
|
||
图32的8组布局截图已更新,实际查看390普通截图确认查看与下载按钮并排;窄屏大字体按宽度自动分行。平台资源契约同步及检查48项通过。
|
||
|
||
Web Release与Android Debug构建通过,新增插件已参与构建;Android仍有既有Kotlin迁移警告,未阻断产物。合同卡片以identity作为稳定Key,筛选或刷新移除卡片时销毁该下载状态,避免迟到请求在另一份合同卡片上继续保存。
|
||
|
||
远程既有MOCK-CONTRACT-001没有可读取附件,真实GET返回404,匿名请求401。本轮没有修改远程合同、没有生成冒充业务合同的PDF,也没有更改数据库或缓存配置。真实业务PDF成功保存和Android/iOS系统保存对话框仍需有附件的受控测试数据及设备验收,不能用单元测试替代这项结论。
|
||
|
||
最终浏览器版本已点击真实合同的下载按钮,显示持续错误“合同附件暂不可用,请联系供气单位补充”,按钮恢复可重试。最终Web和Android再次构建通过;持续错误反馈的UI回归通过。当前API进程40192,Web端口18571。
|
||
|
||
## 维护与风险
|
||
|
||
服务端导出的ServeAuthorizedContractPDF要求调用者先完成权限校验,禁止直接注册路由。保留10MiB文件上限,避免无界客户端内存下载。系统保存依赖平台支持,取消应保持页面并允许重试;PDF缺失应由供气单位补充,不能从合同正文生成替代签署件。
|
||
|
||
图32继续部分实现:下载代码已接通,但真实文件保存尚未完成设备验收;签署、家庭共享协议、合同服务和完整视觉仍待补。
|