46 lines
4.7 KiB
Markdown
46 lines
4.7 KiB
Markdown
# 用户端 App 报修照片日志
|
||
|
||
操作时间:2026-09-07。操作类型:扩展。影响模块:用户App、Client照片接口、受控文件存储、既有工单证据表。
|
||
|
||
## 操作前后
|
||
|
||
现场照片原为未开放按钮,现支持相册/相机来源选择、1—3张照片、预览、删除、去重、上传和工单关联。客户端要求至少一张,旧API客户端仍可省略photos。每张JPG/PNG不超过2MiB;服务端再次验证扩展名、MIME、完整解码和4096像素边界。
|
||
|
||
上传使用独立账户与内容摘要目录,不复用头像目录或权限。完整临时文件写入后原子移动,相同内容重复上传复用URI。工单与reported照片证据在同一事务中,越权或无效照片导致整张工单回滚。客户端缓存上传结果,提交失败重试不重复上传成功照片。
|
||
|
||
详情批量查询证据,只返回UUID、添加时间、来源和完整性标记。读取同时验证用户、工单归属和证据关联,返回private/no-store及nosniff,并记录访问日志。页面支持读取失败重试与放大预览。
|
||
|
||
## 代码变更
|
||
|
||
| 文件 | 关键函数与位置 |
|
||
| --- | --- |
|
||
| backend/api/internal/logic/upload/ticket_photo.go | 新增存储;UploadTicketPhoto第43行、ServeTicketPhoto第95行;摘要路径和账户归属 |
|
||
| backend/api/internal/logic/client/user/ticket_photo.go | saveTicketPhotos第34行事务关联;TicketPhoto第74行双重授权;ticketPhotosForList批量元数据 |
|
||
| backend/api/internal/logic/client/user/address_ticket.go | 创建可选photos及事务;列表照片元数据 |
|
||
| backend/api/internal/routers/client.go、client_test.go | POST ticket-photos、GET tickets/:identity/photos/:photoIdentity与路由测试 |
|
||
| apps/user_app/lib/ui/features/tickets/repair_photos.dart | 第27行RepairPhotos选择、删除、预览;RepairPhoto缓存上传URI |
|
||
| apps/user_app/lib/ui/features/tickets/repair_page.dart | 图片必填、上传期间保护、重试复用、确认摘要 |
|
||
| apps/user_app/lib/ui/features/tickets/ticket_photos.dart、ticket_detail_page.dart | 第8行TicketPhotos鉴权缩略图、重试、预览和添加时间 |
|
||
| apps/user_app/lib/data/services/api_client.dart | 第153行uploadImage共用鉴权;保持旧头像方法和错误提示兼容 |
|
||
| apps/user_app/lib/data/repositories/client_repository.dart、domain/models/service_ticket.dart | 上传/读取照片、submitRepair可选photos、安全解析元数据 |
|
||
| backend/api/internal/logic/upload/ticket_photo_test.go、client/user/ticket_photo_test.go | 格式、大小、尺寸、路径、归属、事务回滚与读取缓存测试 |
|
||
| apps/user_app/test/ui/repair_page_test.dart | 选图注入,失败重试UUID相同且上传次数为1 |
|
||
|
||
没有新增数据库字段或表、迁移、种子或本机数据库/缓存。复用cs_ticket_evidence;文件沿用API工作目录runtime/uploads,可用HEQI_UPLOAD_DIR指定受控存储,不能公开映射该目录。
|
||
|
||
## 验证结果
|
||
|
||
- Go全包测试、vet、API构建通过;格式伪造、2MiB限制、4096像素边界、目录穿越、头像URI误用、跨账户/工单读取、关联失败整体回滚均有测试。
|
||
- Flutter58项测试通过,analyze无问题;05/42的16组宽度/文本缩放截图通过,Web release构建通过。旧头像提示回归发现后已保持兼容。
|
||
- contract:sync和contract:check通过48个资源,新路由纳入测试。
|
||
- 浏览器从系统文件选择器选取64×64蓝白验收图案,描述注明验收无需派单;选择临时完整地址后确认提交,自动进入详情,照片能重新读取并放大。
|
||
- 工单TK1788794635076747500,UUID为01a07c78-0344-7b67-acba-b3e3f289974d。随后浏览器确认取消,已取消且按钮消失,证据保留。
|
||
- 鉴权GET=200、image/png、Cache-Control含no-store/private;匿名GET=401。读取图片与原验收图尺寸相同,64×64全部像素差异为0;SHA256不同,不能声称原文件字节保真。
|
||
- 临时地址01a07c74-5c76-7805-873a-4d82b8c48977已归档,列表恢复仅原默认地址。没有修改原地址、原工单或其他账户。浏览器error/warn为空。
|
||
|
||
## 剩余范围与维护
|
||
|
||
来源user_camera/user_gallery,完整性capture_time_unknown;captured_at暂存客户端添加时间,只以added_at输出。页面明确提示拍摄时间/位置未核实,不伪造现场取证。原始拍摄时间、真实定位、原生相机验收、语音、持久化草稿、补充照片、工作人员查看用户照片的完整入口、联系工程师与改期仍待完成。
|
||
|
||
当前10图部分实现、48图尚无完整对应页面、0图严格全功能1:1通过。远程数据库保存证据记录不代表多实例共享文件存储已部署;后续迁移必须保留资源归属与受保护读取。
|