已完成用户APP首期功能开发

交付用户端首期页面、配套接口、后台资源及测试文档。用户APP构建、静态分析和三个管理后台构建通过;完整测试仍有2项失败,后端模型注释检查未通过,详见交付记录。
This commit is contained in:
czl231
2026-09-13 00:57:32 +08:00
parent a0a4bb1218
commit 3ef33b531d
793 changed files with 40959 additions and 1204 deletions

View File

@@ -153,7 +153,7 @@ apps/user_app/lib/
- `/shop`、`/shop/products/:identity`、`/cart`、`/checkout`
- `/orders`、`/orders/:identity`、`/orders/:identity/delivery`
- `/me`、`/me/wallet`、`/me/records`、`/me/settings`
- `/valves` 与 `/favorites` 属于后续路由;对应 Client API 未落地前不得注册可操作页面或用 Mock 数据占据主导航。
- `/valves` 仍属于后续路由,API未落地前不得注册可操作页面。`/favorites` 于2026-09-08随真实用户收藏API落地进入个人中心与商城流程;禁止使用Mock数据替代远程收藏状态。
- 登录、协议版本确认和首次安全宣导使用根级守卫;涉及设备、订单、钱包、地址的页面必须在 redirect 中校验会话,不能依靠按钮隐藏。
- 邀请二维码、订单通知、支付结果和安全通知使用白名单深链。Android App Links 与 iOS Universal Links 均须校验域名归属;深链参数只接受 `identity` 和短期签名上下文。
- 高风险开阀被拦截时导航到可解释的限制页面或安全事件详情,不允许通过返回栈、群控入口或手工深链绕过。

View File

@@ -125,6 +125,25 @@
- 支付密码独立于登录密码,仅允许六位数字,使用 bcrypt 保存;连续失败达到阈值后在 Redis 短时锁定。绑卡、解绑、余额支付和提现均要求支付密码或限定用途的一次性验证码。
- 公共上传接口 `/upload/file` 必须携带平台、气站、配送点、用户或工作人员任一合法 JWT;图片/PDF 最大 10MB,视频上限从配置读取。上传只返回资源 URI,业务接口负责建立关联并记录操作者、采集与接收时间。
- 平台账户资料头像使用专用 `/upload/avatar` 上传入口,仅允许真实 JPG/PNG、最大 2MB、最大 4096×4096,并在服务端完成扩展名、MIME、尺寸和完整图片解码校验。后台头像读取通过 `/heqi/platform/v1/{staff_account|user_account|platform_account}/:identity/avatar` 受 JWT、菜单和对象角色权限保护;用户 App 仅可通过 `/heqi/client/v1/user/auth/avatar` 读取当前登录用户自己的头像。通用列表及详情响应继续移除 `avatar` 字段,头像文件目录不得作为公开静态目录。平台总后台的工作人员、用户和平台账户列表可对当前可视记录调用受控接口展示缩略图,必须限制并发、按页缓存、离页取消请求并释放本地 Blob URL。普通资料更新未提交 `avatar` 时保持原头像,只有明确上传或恢复默认头像时才修改该字段。
- 用户 App 地址维护的最小例外:`GET /heqi/client/v1/user/addresses` 仅在用户 JWT 和账户归属过滤后返回本人的完整地址、收货联系人、联系电话及坐标,供本人编辑和下单使用;App 列表遮蔽手机号中间四位。此例外不允许读取他人地址,也不改变订单列表、其他终端资源的脱敏规则。地址新增可携带 request_no 幂等号,编辑、归档及默认切换均先锁本账户并校验对象归属;归档保留历史订单快照。
- 充值、支付、提现、工单证据、轨迹点、内容确认等写入均携带幂等号;资金入账在数据库事务内锁定钱包并同时写不可变流水。
- 用户商城结算可提交 expected_payable_amount(整数分)作为报价确认,金额始终由数据库单价和数量计算。价格变化返回 2401 并回滚,库存不足或下架返回 2402。金额乘加先检查溢出;请求最多100项,每项1至999件。本人同请求号已创建订单优先恢复,不再依赖当前地址和库存;此行为不会返回他人订单。
- 用户商城订单的取消/收货动作由 allowed_actions 发布,客户端确认后提交,服务端锁定本人订单再校验。取消仅允许订单状态16,状态22重试不再返库存;收货仅允许订单状态18且物流20,物流30重试不覆盖首次收货时间。取消或退款中的订单不能凭旧物流状态确认收货。
- 用户工单列表兼容原数组与原字段,新增 `status_name`、`allowed_actions`,仅返回本人且未归档记录,移除内部主键。取消沿用既有32/18/11/21/34状态范围,22重复返回成功;确认仅允许34,23重复返回成功且不覆盖首次完成时间。两种动作在事务内锁定本人工单,其他用户、归档和非法状态均拒绝。App详情当前复用本人列表查询,不另外开放人员隐私或照片静态链接。
- 报修创建新增可选fault_type(leak/valve/alarm/other),contact_name/contact_phone由服务端从本人地址取快照,历史空联系人回退本人账户,不能任意提交他人地址。创建事务按账户串行;本人重复request_no返回首次工单,不因原地址已归档或预约时间已过而重复创建。首次创建拒绝空白描述、空白/过长请求号和过去预约时间。新增cs_ticket字段使用migrate-ticket-contact定向迁移,原接口兼容省略fault_type和address_identity。
- 报修照片使用用户JWT保护的POST ticket-photos,真实JPG/PNG、每张2MiB以内、4096像素边界,内容摘要绑定账户目录保证重复上传复用。POST tickets可附photos(最多3项,旧客户端允许省略),只关联本人已上传资源并与工单同事务;非法照片整体回滚。读取通过GET tickets/:identity/photos/:photoIdentity同时校验本人、工单和证据关联,返回private/no-store,禁止将ticket-photos文件夹映射为公开静态资源。
- 用户添加照片复用cs_ticket_evidence,evidence_type=reported、source=user_camera/user_gallery、integrity_status=capture_time_unknown。此类记录的captured_at暂存客户端添加时间,API明确输出added_at,不能被解释为已验证原始拍摄时间;longitude/latitude未采集则为空,不能伪造现场位置。后续原始时间/定位能力须保留来源和完整性标记,不能覆盖工作人员原有证据语义。
- 钱包可提现余额是当前总余额的子集,始终满足 `0 <= 可提现余额 <= 总余额`。普通消费扣减总余额后,必须同步把可提现余额限制在剩余总余额以内。
- 提现申请在同一数据库事务内锁定钱包、同时预扣总余额和可提现余额并写入不可变流水;驳回只返还该申请实际预扣的两类余额,完成打款只确认外部结果,不得再次扣款。
- 商品详情 `GET /heqi/client/v1/user/public/products/:identity` 为匿名只读接口,只读取启用且未删除商品及关联的启用图片/属性。售罄仍可查看,下架/不存在返回1112。响应白名单不包含内部主键或订单数据。详情价格不作为交易授权,结算重新读价,创建订单仍校验库存、报价、归属及幂等号。
- 收藏`GET shop/favorites`、`GET/PUT shop/favorites/items/:identity`均使用用户JWT。identity为商品公开标识;EcFavorite以(user_account_id,ec_product_id)唯一关联,取消设置status=3,已收藏status=1。PUT接受favorite布尔值及原revision,相同目标无写入,过期版本返回2404;版本为收藏UUID与正整数序号,每次状态变化递增。下架商品不允许新增收藏,但已收藏内容继续展示并允许取消;列表用available禁用加购,不伪造销量、优惠或规格。上限1000条有效收藏;所有字段和表有中文数据库注释。
- 推荐`GET shop/recommendations`要求用户JWT;参数source为cart(默认)或favorites,page为1至10000,page_size为1至20(默认2)。返回items、page、page_size、has_more;item字段为identity、name、price_amount(整数分)、stock_quantity、image_url、category_name。排除本人有效购物车、已删除/停用/无库存商品;favorites另排除本人有效收藏,同场景关联分类优先。账户ID只由JWT读取,不接收调用方传入;分类排序表名为固定枚举,图片/分类批量查询。接口只读,无数据库迁移或外部推荐服务。客户端丢弃跨账号迟到响应,加购继续使用原购物车条件版本接口。
- 商城订单详情`GET shop/orders/:identity`要求用户JWT,查询绑定订单公开identity与当前账户,跨账户与不存在均返回1112。只公开订单号、业务状态/允许动作、成交明细、收货联系人/地址快照、商品/优惠/应付整数分金额、实际支付/发货/收货时间、备注和物流公司/单号。明细名称及商品公开identity来自成交JSON快照,单价为sale_amount;不联查当前商品替换历史值,也不直接输出完整原始快照或内部主键。列表与详情共享shopOrderState动作定义,详情写操作仍复用原状态校验接口。没有已记录的付款时间时不显示“实付成功”,缺失资料不编造。
- 收藏列表支持既有page/page_size分页协议。状态写入按账户锁串行,不接受他人关系主键。客户端仅广播服务端已确认状态,若账号已切换则丢弃旧请求的迟到结果;取消收藏不影响购物车或订单。
- 购物车 `GET shop/cart`、`GET/PUT shop/cart/items/:identity` 均要求用户JWT,identity为商品公开标识;数据库按当前账户关联条目。PUT提交quantity(0—999)、selected和读取时的revision,零数量归档。相同目标重试不写入,过期目标返回2403;新增/增加数量受库存限制,最多100条有效商品。revision由购物车公开UUID和微秒精度更新时间构成,归档仍保留版本,旧重试不能复活已删除商品。全选/批量删除逐项提交,部分失败后重读真实状态。
- POST shop/orders可为每个item附cart_revision;服务端核对本人有效勾选条目的版本和数量,并在订单事务中归档,任何价格/库存/版本失败均回滚。多商品按公开identity固定顺序锁定,拒绝重复商品、零或负数量。金额仍为整数分,expected_payable_amount、request_no及旧单商品调用兼容;已创建请求优先返回原订单。未配置押金、优惠与配送费用时不将设计样例金额写入订单。
- `GET /heqi/client/v1/user/deposits` 只依据当前 JWT 用户查询押金汇总和明细,支持 `all/using/refunding/returned` 状态筛选;不接受客户端传入的用户标识。总后台 `/deposit_policy` 允许维护规则,`/deposit_record` 只读,避免后台通用表单直接改写资金事实。
- `POST /heqi/client/v1/user/deposit-returns` 只锁定本人使用中押金和本人完整地址,校验预约时段、四项确认与幂等号。后台退瓶处理按 `10待上门→20待验收→30待退款→40已完成` 单向流转;扣减不得超过原押金。退款时锁定钱包和押金记录,余额、押金状态、申请状态及不可变 `deposit_refund` 流水同事务提交。
- `GET /heqi/client/v1/user/gas/order-options` 只返回JWT用户有效供气合同下未被未完成订单占用的合同气瓶,以及服务端合同价、押金规则、本人地址和可预约时段。缺押金规则的规格必须返回明确不可下单原因,客户端不得推测金额。
- `POST /heqi/client/v1/user/gas/orders` 接收地址、合同气瓶公开标识集合、预约时间、客户端预期金额和幂等号;服务端重新校验归属、占用、价格、押金及金额后创建待支付订单。下单时以 `gasorder_deposit` 锁定每只气瓶的押金规则快照;余额或第三方支付成功后,在同一事务内生成 `deposit_record`。取消未支付订单同时释放气瓶占用并取消待支付押金快照。
- 报修草稿照片通过 `GET /heqi/client/v1/user/ticket-photos/:name` 读取;JWT校验后用当前账户构造文件目录,仅接受内容摘要文件名,不能由请求指定账户目录。响应禁止公开缓存。草稿在平台安全存储中按API地址和认证账户隔离,仅含表单、地址快照、照片URI和幂等号,不含令牌及图片字节。恢复不会自动提交;未知提交结果须沿用原请求号。删除草稿只清理本地记录,不删除可能已经关联工单的照片文件。

View File

@@ -116,7 +116,7 @@ Design System 不负责:
- 登录/注册:品牌区 → 表单 → 单一主操作 → 协议与辅助入口。
- 首页:页面介绍 → 当前服务/安全概览 → 内容区块。
- 商城:商品列表为同组 Surface,商品是独立 Row;价格和购买操作优先于装饰。
- 商城:2026-09 用户端最新设计优先采用双列商品网格;窄屏保持可读,宽屏最多三列。价格和购买操作优先于装饰。
- 订单:顶层 Tab 管理分类,子列表使用 embedded 模式,不嵌套 AppBar。
- 我的:身份概览 → 资产概览 → 账户与服务列表 → 独立退出操作。
@@ -156,4 +156,5 @@ Design System 不负责:
| 版本 | 日期 | 内容 |
| --- | --- | --- |
| 0.1.1 | 2026-09-07 | 用户端明确蓝白容器与文字对比色、一级标题居中;Surface 使用 Material 保证点击墨水层可见;筛选标签显式文字颜色与边框。公共 API 保持兼容,两个 App 回归通过。 |
| 0.1.0 | 2026-08-10 | 建立共享 Flutter 包、双品牌 Material 3 主题、基础 Token 与布局/状态组件。 |

View File

@@ -23,7 +23,8 @@
| 文档 | 用途 |
| --- | --- |
| [用户端 App 全量功能开发](项目文档_用户端APP全量功能开发_v1.0.md) | 将最新 58 张用户端产品设计图落实为页面路由、UI 规范、Client API、数据模型、测试和分阶段交付方案 |
| [用户端 App 全量功能开发](项目文档_用户端APP全量功能开发_v1.1.md) | 58 张设计图的实施基线;v1.1 增补 A1 代码、兼容接口和远程联调事实,v1.0 保留归档 |
| [用户端 App 开发进度](开发进度_用户端APP全量功能开发.md) | 58 张逐页状态、测试证据、未完成视觉项和下一批起点 |
| [用户端 App 全量开发 AI 提示词](开发提示词_用户端APP全量功能开发_v1.0.md) | 可直接交给开发 AI 使用,包含项目路径、设计与需求事实源、开发批次、接口规则、视觉验收、测试和交付要求 |
| [服务端 App 三岗位全量功能开发](项目文档_服务端APP三岗位全量功能开发_v1.0.md) | 将安装维修、配送、安全检查共 122 张最新设计图落实为角色路由、UI、Staff Client API、状态机、离线、安全、测试和交付方案 |

View File

@@ -0,0 +1,27 @@
# 用户APP首期功能交付记录
操作日期:2026-09-13
交付说明:已完成用户APP首期功能开发,保存本地仓库并提交远端。此处首期指本次已实现代码范围,不代表全部58张设计图、真实支付渠道、设备联调及严格视觉验收全部完成。
## 本次范围
- 用户端登录、首页、商城、购物车、订单、合同、报修、资料、地址、钱包及相关页面和接口。
- 设备列表、设备分组、家庭共享、消息和用气统计等当前实现。
- 配套后端模型、路由、管理后台资源、测试与视觉对照资料。
- 具体文件、函数和行数以本次Git提交差异及各功能开发日志为准。
## 本次验证
- 用户APP `flutter analyze --no-pub` 通过。
- 用户APP `flutter build web --release --no-pub` 构建通过。
- 用户APP完整测试:187项通过,2项失败,尚未全部通过。
- 后端 `go test ./...` 未全部通过:模型中文字段注释检查失败;用户业务、公共逻辑及路由等测试通过。
- 后端 `go vet ./...` 与构建通过。
- 平台后台52项资源契约检查通过;平台、气站、配送点后台发布构建通过。
## 保留事项
- 失败测试及模型注释需后续修复,当前提交作为首期开发成果快照。
- 真实支付、设备及双账号联调和严格视觉验收以开发进度文档中的实际状态为准。
- 本地运行日志及可执行文件备份不纳入提交;本次推送不等于生产部署。

View File

@@ -0,0 +1,23 @@
# 一键报修视觉与紧急入口开发日志
操作时间:2026-09-11
操作类型:修改、扩展
影响模块:用户端 App 一键报修
操作前状态:图05已有三步报修、照片上传、本人地址、草稿恢复和幂等提交,但顶部更多入口、故障图标和紧急电话缺失;表单纵向尺寸与最新设计稿存在明显偏差。
具体操作:重校步骤条与表单间距、故障行、描述区、照片区、联系地址和底部按钮;增加报修说明与本人报修工单菜单;增加燃气泄漏安全提示。紧急电话只在用户点击后请求系统拨号器打开119,无法打开时显示人工拨号提示。菜单离开前先保存当前草稿,避免丢失填写内容。
操作后状态:图05的首屏结构与最新设计稿基本一致。照片数量继续显示真实状态,视觉夹具没有伪造原稿中的阀门照片和联系人。
代码变更:
- `apps/user_app/lib/ui/features/tickets/repair_page.dart`:顶部菜单、草稿安全跳转、紧急拨号、故障图标、固定底部操作。
- `apps/user_app/lib/ui/features/tickets/repair_layout.dart`:紧凑联系地址区和燃气泄漏提示。
- `apps/user_app/lib/ui/features/tickets/repair_speech_button.dart`:压缩语音按钮占位。
- `apps/user_app/lib/ui/features/tickets/repair_photos.dart`:照片采集状态文案与布局对齐。
- `apps/user_app/test/ui/repair_page_test.dart`:验证拨号仅由用户点击触发且目标为119。
验证结果:图05在320、360、390、430像素宽度及1.0、1.3文字倍率下共8组视觉测试通过;报修、草稿与语音共12项定向测试通过,Flutter全量162项测试及静态分析通过,带本地API地址的Web Release构建通过。内置浏览器完成密码登录,验证必填提示、报修说明以及跳转本人报修工单;紧急电话不在浏览器中实际拨打。已重新生成等比并排对照图。
风险评估:系统拨号、语音识别、相机原始拍摄时间和定位需要Android/iOS真机权限与系统应用配合。当前不自动拨号,也不伪造未采集的拍摄元数据。

View File

@@ -0,0 +1,42 @@
# 个人中心视觉与真实资料开发日志
操作时间:2026-09-11
操作类型:修改、扩展
影响模块:用户资料模型、个人中心、个人资料、视觉fixture与验收文档
## 操作前状态
图25的主要分组已经存在,但个人中心未读取服务端 `real_name`,实名认证始终缺失;紧急联系人没有真实数量。常用功能行高偏大,390×844只能显示部分入口,底部还有设计稿之外的重复维修和退出按钮。个人资料页即使接口已有实名也显示“认证状态尚未接入”。
## 具体操作
- `UserProfile` 增加向下兼容的 `realName` 字段并解析服务端 `real_name`。
- 个人中心在实名存在时显示绿色“已认证”,个人资料页同步显示实名,不再与接口事实矛盾。
- 并行读取紧急联系人数量;该辅助接口失败时不阻断资料、钱包和其他入口。
- 常用功能行高、资产区内边距和标题字号按图25收敛,使全部入口在390×844首屏显示。
- 删除设计稿外重复的“申请维修”和“退出登录”按钮;报修入口及设置页退出保持可用。
- 当前未接入的家庭共享、用气统计、电子发票、押金、客服和关于入口继续显示“暂未开放”,点击给出明确原因。
## 操作后状态
远程资料中的姓名、脱敏手机号、实名、钱包余额和联系人数量均按接口事实展示。当前测试账号头像为空、联系人数量为0,因此页面显示首字头像和“0人”;头像编辑页仍提供拍照和相册上传,不把设计稿头像当成用户头像。
## 代码变更
- `apps/user_app/lib/domain/models/client_models.dart`:增加实名字段解析。
- `apps/user_app/lib/ui/features/profile/profile_page.dart`:实名、联系人数量和图25布局密度。
- `apps/user_app/lib/ui/features/profile/profile_edit_page.dart`:同步显示真实认证状态。
- `apps/user_app/test/support/a1_fixture.dart`:增加认证与联系人视觉fixture。
- `apps/user_app/test/domain/client_models_test.dart`、`test/ui/profile_edit_page_test.dart`:实名解析和页面回归。
## 验证结果
- Flutter静态分析通过;全量166项测试通过。
- 图25在320、360、390、430宽及1.0/1.3文本比例共8组fixture生成通过;已查看390×844官方并排图。
- Flutter Web release构建通过。
- 内置浏览器读取远程数据,确认“已认证 陈示例”、联系人0人、全部入口、暂未开放弹层以及拍照/相册头像菜单。
## 风险评估
- 设计稿中的头像、200元可退押金、2张优惠券和2条消息属于示例或尚无接口数据,当前页面不伪造。
- 常用功能采用较紧凑行高以匹配图25;320宽和1.3倍文字已通过无溢出fixture,仍需Android/iOS真机复核系统字体差异。

View File

@@ -0,0 +1,34 @@
# 供气订单详情视觉与功能状态开发日志
操作时间:2026-09-11 22:15
操作类型:修改、扩展
影响模块:用户端供气订单详情、视觉验收
## 操作前状态
订单详情能读取地址、费用、气站、配送员、合同与状态历史,但页面分组和密度与图21差异明显,联系、配送与售后入口缺失,单个确认收货按钮没有形成设计稿操作区。
## 具体操作
- 按设计稿重排配送状态与时间轴、地址、气站商品、费用明细、订单信息、四项服务和底部操作。
- 订单信息展示真实支付渠道和供气合同编号,订单号及合同编号均可复制;合同正文继续通过本人鉴权接口读取。
- 查看配送、联系气站、联系配送员及押金保留首期入口并显示“暂未开放”;申请售后明确属于二期并显示“即将开放”。
- 待签收订单保留幂等确认收货,并补充封签和编号核对提示。
- 气瓶订单接口没有商品图片字段时使用标准缺图图标,不截取设计图或伪造商品图片。
## 代码变更
- `apps/user_app/lib/ui/features/orders/shop_order_detail_page.dart`:新增供气订单专用视觉分组、功能状态弹层、服务操作及紧凑信息行。
- `apps/user_app/lib/ui/features/orders/gas_order_sections.dart`:压缩四节点时间轴并保持窄屏纵向降级。
- `apps/user_app/test/ui/gas_order_detail_test.dart`、`apps/user_app/test/ui/shop_order_detail_test.dart`:适配可滚动详情与文字复制操作。
## 验证结果
- `flutter analyze` 通过。
- Flutter全量171项测试通过;订单详情定向3项通过。
- 320、360、390、430像素宽度与1.0、1.3文字缩放共8种供气详情视觉检查通过;并排图已重新生成。
- Web以本地API地址重新构建成功。内置浏览器读取远程订单 `MOCK-GASORDER-001`,现场展示主页面、“查看配送暂未开放”和“申请售后即将开放”弹层;未确认收货或写入远程数据。
## 风险评估
远程示例订单完成时间早于下单时间,属于现有数据质量问题;客户端按服务端事实展示,没有改写时间。供气订单详情接口尚无气瓶图片、气站服务电话、受控配送员电话、配送详情和押金明细,相关区域不能判定全功能完成。

View File

@@ -0,0 +1,32 @@
# 商品详情视觉与后台数据开发日志
操作时间:2026-09-11 22:35
操作类型:修改、扩展
影响模块:用户端商城商品详情、后台商品图片与属性展示、视觉验收
## 操作前状态
商品详情只有图片、标题、价格库存、数量和参数的纵向列表,缺少设计稿中的商品信息卡、规格、配送服务、四项保障和带文字的底部入口。分享入口不存在,后台未配置数据与未开放服务没有明确状态。
## 具体操作
- 按图12重排商品图片、信息、规格、配送服务、保障、说明和底部购买区。
- 分享按钮复制当前商品深链;收藏、购物车、数量、加购和立即购买继续使用真实功能。
- 读取登录用户的真实气站服务归属;规格与商品说明继续读取已有商品属性后台资源。
- 后台未配置规格或参数时显示“暂未配置”;预约送达、配送前联系及四项服务标准作为首期缺口显示“暂未开放”。
- 后台商品图片直接渲染并支持点击预览,不展示图片地址。
## 代码变更
- `apps/user_app/lib/ui/features/shop/product_detail_page.dart`:重建商品详情布局,新增分享、服务归属、规格状态、配送及保障提示。
- `apps/user_app/test/ui/product_detail_page_test.dart`:保留数量和参数验证并适配完整页面滚动。
## 验证结果
- `flutter analyze` 通过,Flutter全量171项测试通过。
- 320、360、390、430像素宽度及1.0、1.3文字缩放共8种视觉检查通过,并排图已重新生成。
- Web使用本地API地址构建成功。内置浏览器读取真实商品10,后台上传图片显示成功;分享显示“商品链接已复制”,配送入口显示“配送服务暂未开放”。未加购或提交订单。
## 风险评估
真实商品10未配置规格和参数,上传图片内容是商城页面截图,并非设计稿中的正式气瓶商品素材。客户端只能忠实显示后台数据;要达到素材级1:1,需要后台上传对应商品原图并补充商品属性。配送预约、配送前联系和服务标准仍缺服务端契约,因此本页保持部分实现状态。

View File

@@ -0,0 +1,10 @@
# 商城分类拖动修复
- 操作时间:2026-09-13
- 操作类型:修复
- 影响模块:用户端商城分类栏
- 原因:Flutter 默认滚动行为不接受鼠标拖动,桌面内置浏览器无法按住分类栏横向滑动。
- 代码变更:`apps/user_app/lib/ui/features/shop/shop_page.dart` 的分类栏局部添加 ScrollConfiguration,保留现有输入设备并加入鼠标;不改变全局滚动行为和分类筛选逻辑。
- 验证:`test/ui/shop_category_scroll_test.dart` 两项测试通过,分别验证鼠标与触屏拖动后的滚动位置和分类筛选结果;Web release 构建通过。
- 风险范围:仅分类横向滚动容器;未修改 API、数据库或商品数据。
- 浏览器验证:内置浏览器 18578 商城实际鼠标拖动成功,从分类10、9移动至分类4、3、2;随后点击分类2,仅显示对应商品,筛选正常。

View File

@@ -0,0 +1,53 @@
# 商城商品图片上传
## 2026年9月11日最终浏览器复核
使用带本地API地址的最新Release Web构建,在内置浏览器重新登录并读取远程数据库。公开商品接口中“示例配送商品 10”的 `image_url` 为有效受控路径,商城卡片和商品详情均已显示该图片;其余当前可见商品的 `image_url` 为空,因此页面正确显示“暂无商品图片”。这不是数据库崩溃,也不是App仍然无法加载图片,而是只有一个商品完成了图片关联。
本轮没有用设计稿或生成素材批量覆盖远程商品。后续需由后台为每个正式商品分别上传并启用素材,App会按接口结果显示;商品图片地址继续只在接口内部传输,后台列表、详情和App均以图片预览呈现。
## App图片跨域缓存故障定位与修复
2026年9月11日内置浏览器对照验证:商品接口code0并返回正确上传路径;后台img显示正常。关闭HTML回退后,Flutter报HTTP request failed, statusCode: 0;原图片响应无Origin请求时缺少Vary,但Cache-Control为public,max-age=86400。这使后台普通图片缓存可被后续App跨域XHR复用,缓存中缺少允许跨域响应头。
仅为同一图片追加image_cache=2避开旧缓存,保持Flutter默认解码(无HTML回退),详情立即显示成功,DOM中img数量为0,支持缓存污染结论。修复ServeProductImage为所有成功图片响应添加Vary: Origin;ProductImage仅为/uploads/product-images/路径附加固定缓存版本,迁移旧24小时缓存。移除临时诊断开关、异常打印及先前未解决根因的HTML回退。
新增TestProductImageRoundTrip无Origin缓存头回归断言;go test ./internal/logic/upload ./internal/routers通过。API已重建并启动PID39956,继续使用既有远程数据库配置。线上本机接口实测普通请求与Origin=18572请求均200、Vary: Origin,后者具有正确Access-Control-Allow-Origin。不修改商品、图片或交易数据。正式商品素材、购物车浏览器验证及全量视觉验收仍不属于此次根因修复通过结论。
## 商品名称展示修正
resources.ts中ec_product_image的ec_product_identity关系字段增加商品名称展示配置,列表与表单标题统一为“商品”,保留内部标识和复制能力,不变更API或数据。修正前列表显示截短编号,修正后显示“示例配送商品 10”;内置浏览器确认名称可点击并进入对应商品详情(尾号002015)。pnpm run type:check通过。改动仅影响商品图片资源的展示配置。
## 商品图片入口补正
此前仅取消路由隐藏不足以让服务端菜单显示图片入口:store/modules/app/index.ts的indexClientMenus按menuCode只保留首个路由,商品与商品图片共用ec_product,图片路由被去重。此前“菜单已显示”的结论不准确。为保留现有权限和菜单契约,在CrudListPage.vue商品列表工具栏新增“商品图片”按钮,导航至ec-images。内置浏览器已从商品管理点击该按钮到达图片列表,类型检查通过。使用路径:电商平台管理→商品管理→右上角商品图片→新建/编辑。App图片显示问题仍待定位。
## 2026年9月11日后台实测与展示修正
后续联调:测试图片已通过后台“审核→启用”操作;App指定示例配送商品10仍显示图片加载失败。公开图片GET返回200、image/png、正确跨域响应头,后台图片可见。shop_page.dart的ProductImage增加WebHtmlElementStrategy.fallback,作为公开商品图的Web显示回退;Flutter analyze通过,Web构建通过(51.3秒),但浏览器刷新后仍未验证成功,不能视作故障已修复。
继续核对时,商品详情公开接口返回业务code500,原因为远程PostgreSQL连接超时。按项目测试环境停止条件暂停依赖数据库的验证,不切换本机数据库。测试图片记录最后已执行启用,尚未恢复待审核或清除;恢复环境后优先核对该记录当前状态和真实图片URI,再完成商城、详情、购物车显示和测试数据清理。上传素材为设计截图,仅用于联调,不是正式商品素材。
后台18573已由用户启动;内置浏览器使用初始化模拟管理员成功登录。真实上传 shop-source.png(仅作为联调测试素材,不是正式商品照片),接口返回图片路径,保存到示例配送商品10,图片记录01a08f0f-d398-728a-b344-ff04bfbb8ec1,状态待审核。未审核上线,未验证App展示,不能称为商城全链路通过。
用户要求直接上传、显示图片而非地址。ProductImageField.vue删除地址输入框,保留选图、重传及预览;新增ProductImagePreview.vue,将CrudListPage.vue商品图片列及ResourceDetailContent.vue商品图片字段改为缩略图和大图预览,失败显示“图片加载失败”。resources.ts将本资源字段名称改为“商品图片”。platform.ts取消商品图片列表菜单隐藏,仍沿用ec_product权限。
验证:pnpm run type:check通过;内置浏览器确认列表缩略图、详情160像素图片和编辑页上传按钮,编辑页已无地址输入框。历史mock图片路径不存在,正确显示加载失败,未用测试图片覆盖原记录。图片仍通过原image_uri字段保存,接口与既有数据兼容。本次测试记录保持待审核,后续需用实际商品素材替换或删除;App商城、详情和购物车显示仍待验证。
后台已有ec_product_image资源及商品关联,但仅手填image_uri;新增平台后台ProductImageField.vue,提供选图、上传、预览、错误提示和URI回填。资源保存继续绑定ec_product_identity、sort_no、is_cover,不变更数据库结构。
新增POST /upload/product-image,仅允许platform_admin鉴权主体上传公开商品素材,限制JPG/PNG、2MB、4096像素并完整解码。GET /uploads/product-images/:name仅读取独立商品目录内UUID文件名的普通文件,匿名可读并设置nosniff;不公开头像、工单或整个上传目录。
涉及文件:backend/api/internal/logic/upload/product_image.go、product_image_test.go、routers/upload.go;frontend/platform_admin/src/views/resource/ProductImageField.vue及ResourceFieldForm.vue。
Go上传与路由测试通过。新增测试在临时目录执行后台上传、匿名读回、字节一致和普通用户上传拒绝;不连接远程数据库或缓存。平台后台pnpm run type:check通过。
尚未部署新构建或在内置浏览器完成后台上传→保存商品关联→App商城/详情/购物车显示的真实联调。封面唯一性、删除关联后的文件清理策略及运营素材仍需核查。现有业务素材不以生成的假商品照片替代;功能属于首期补齐,不划到二期。
上传成功但未保存记录会留下未关联图片,本批不擅自删除资源。上传控件支持保留旧地址,失败不覆盖;不同账号迟到响应不回填。
后续修复:关闭编辑窗口时AbortController取消上传,组件卸载后不回填。新增公开读取路径测试,拒绝头像/工单路径穿越、绝对路径、SVG及空文件名,上传与路由测试通过(上传包0.751秒)。后台正式pnpm run build通过,后端新可执行文件构建通过;git diff --check通过。
部署操作未执行成功:自动审批拒绝了停止旧API并启动新API及后台预览的命令,理由仅为blocked by policy。未绕过拒绝;端口复核12426仍为原进程1060,18572仍为34588。故不能声称新上传功能已在内置浏览器完成联调。正式构建默认API地址不是本次本机联调地址,部署前必须按实际环境明确配置,不能直接用构建成功替代连接核查。
用户明确要求重启API及启动预览后:旧API已停止,新商品图片API首次启动因initdb返回unexpected EOF退出;确认退出后重试,进程31980已监听12426。后台预览启动命令再次被自动审批拒绝,仅返回策略阻止,未绕过。商品图片后台浏览器联调仍未完成。

View File

@@ -0,0 +1,27 @@
# 安全内容中心开发记录
## 单篇详情接口
随后内置浏览器在contents=3新构建加载公告列表,点击“模拟公告9”成功进入内容详情并显示远程正文,真实阅读路径已验证。首轮超时未持续阻断,仍不代表远程环境稳定性已验收。
新增GET /heqi/client/v1/user/public/contents/:identity,使用identity、status=1、publish_status=published及notice/safety_article/law类型约束读取,软删除沿用GORM过滤;不存在返回1112。响应白名单仅identity/title/body/content_type/version_no。ClientRepository.safetyContent与页面详情加载接入该接口,避免每次读取全部内容,1112显示已下架说明,其他错误保留重试。
content_detail.go/对应测试及routers/client.go为后端变更;App仓储、页面和fixture测试同步更新。后端SQLMock覆盖发布约束和最小字段、无记录返回1112;用户逻辑与路由测试通过;三个Flutter页面测试、analyze及Web构建通过。API已更新至PID45776,仍连接原远程数据库,无迁移或数据写入。首次HTTP联调超时,不以单元测试替代真实联调证据。
## 后续扩展:安全宣传与法律法规文本内容
后台resources.ts的cms_content新增safety_article(安全宣传)和law(法律法规)选项,沿用已有varchar内容类型及发布/启用流程,不改变原notice/agreement接口契约,无数据库迁移。App安全内容中心支持这两类的筛选与独立正文;协议仍不进入安全内容,视频仍暂未开放。后台表单浏览器已看到新增选项,未发布测试法规或安全知识。三个widget测试、后台类型检查、Flutter analyze与Web构建通过。
注意:这仅补齐文本分类维护,不代表图43-1/43-3视觉和完整功能通过;宣传配图、法规级别/文号/施行日期/原文链接、内容分页和公开响应最小化仍待完成。正式发布内容需由运营提供,不能用自动编写的安全法律内容替代。
## 范围与实现
对照43-4-平台公告设计图,新增安全内容中心与独立公告正文路由。当前后台仅支持notice、agreement,因此仅开放真实公告搜索和阅读,安全宣传、视频、法律法规保留入口并标“暂未开放”,不自行归为二期。
核心文件:apps/user_app/lib/ui/features/home/safety_contents_page.dart负责已发布公告筛选、标题搜索、正文、空状态及下架提示;app/router.dart增加公开/contents及/contents/:identity路由;首页新增查看更多并把公告弹窗改为独立详情;设置增加安全内容入口。沿用PrimaryRepository与公开已发布内容接口,无数据库结构或内容变更。刷新详情会重新读取发布状态,协议不能通过公告详情标识被展示。
## 验证与缺项
Flutter analyze通过,两项widget测试通过,覆盖公告搜索、协议隔离和非公告详情拒绝。Web构建通过;内置浏览器实测列表显示远程模拟公告,搜索“公告 9”仅剩匹配记录。
此页未完成1:1验收:缺少设计稿的公告子分类、置顶、摘要、已读状态、发布时间及配图,后台字段和接口仍需补齐。当前列表为已发布内容全集本地搜索,需后续增加分页与服务端筛选。无新增依赖,不将测试公告当正式安全知识内容。图43及43-4只计新增部分实现,不计验收完成。

View File

@@ -0,0 +1,51 @@
# 家庭成员与设备共享首期开发日志
操作时间:2026-09-13
操作类型:新增、扩展
影响模块:用户端 App、用户端 API、远程开发数据库
## 操作前状态
个人中心仅显示“家庭成员与设备共享”暂未开放,没有独立页面、家庭关系、邀请确认、设备授权或审计接口。紧急联系人只能维护资料,并明确不代表设备控制或告警通知授权。
## 具体操作
- 新增家庭成员邀请模型。邀请七天有效,受邀手机号对应的账号本人接受后才建立成员关系。
- 新增按成员、按设备保存的查看、告警和控制权限。告警或控制权限必须同时具备查看权限。
- 新增邀请、接受、拒绝、权限调整和撤销审计。审计摘要不记录完整手机号。
- 新增 `/family` 页面,按设计稿展示家庭概览、成员状态、共享设备、安全规则和固定邀请按钮。
- 个人中心入口改为真实路由。邀请、撤回和权限编辑均以服务端成功响应为准。
- 远程开发数据库执行 `migrate-family-sharing` 增量迁移,只创建家庭共享三张表、索引和中文注释。
## 行为变化
变更前:点击入口只显示“暂未开放”。
变更后:房主可以邀请手机号、预设设备范围、撤回待确认邀请、调整成员权限或移除成员;受邀账号可以接受或拒绝。普通紧急联系人不会自动成为家庭成员,也不会自动获得设备权限。
## 代码变更
- `backend/api/internal/models/user_family_member.go`:家庭成员、设备共享和审计模型。
- `backend/api/internal/logic/client/user/family.go`:本人隔离、邀请确认、权限替换、撤销和审计业务。
- `backend/api/internal/routers/client.go`:家庭共享用户端路由。
- `backend/api/cmd/cli/family_migration.go`、`main.go`:可重复执行的增量迁移命令。
- `apps/user_app/lib/domain/models/family_sharing.dart`:页面领域模型。
- `apps/user_app/lib/data/repositories/client_repository.dart`:家庭共享仓储调用。
- `apps/user_app/lib/ui/features/profile/family_sharing_page.dart`:独立页面及邀请、权限、撤销交互。
- `apps/user_app/lib/app/router.dart`、`profile_page.dart`:路由和个人中心入口。
- `apps/user_app/test/ui/family_sharing_page_test.dart`、`test/support/a1_fixture.dart`、`tool/a1_visual_test.dart`:页面和视觉验证。
## 验证结果
- Go:`go test ./internal/logic/client/user ./internal/routers ./cmd/cli` 通过。
- Flutter:`flutter analyze` 无问题;家庭共享页面 2 项测试通过;320/360/390/430 宽度及 1.0/1.3 字体倍率共 8 组无溢出。
- 构建:带本地 API 地址的 Flutter Web Release 构建通过。
- 远程联调:真实账号创建待确认邀请,响应状态为 10,列表仅显示脱敏手机号;撤回成功并从活动列表消失。
- 内置浏览器:完成登录、打开 `/family`、打开邀请表单、发送邀请、查看待确认状态、二次确认撤回,并停留在撤回后的真实页面。
## 风险评估
- 远程测试账号当前没有智能设备,未在真实数据上执行按设备授权。
- 当前只有一个已知用户端测试账号,接受/拒绝接口尚未完成双账号浏览器联调。
- 页面使用真实姓名首字头像;成员受控头像资源接口尚未接入,因此与设计稿人物照片存在差异。
- 设备远程控制能力本身仍由设备控制页面和物联网映射决定,本页授权不会绕过二次确认或设备可用性检查。

View File

@@ -0,0 +1,27 @@
# 我的收藏视觉与真实推荐开发日志
操作时间:2026-09-11 22:05
操作类型:修改、扩展
影响模块:用户端我的收藏
## 操作前状态
图15已有真实收藏、分类筛选、取消收藏、下架保留、加购和推荐,但顶部多出购物车按钮,商品卡过高,首屏看不到“猜你喜欢”;缺图时还以文字占据图片区域。
## 具体操作
- 移除产品设计中不存在的顶部购物车按钮,保留返回和管理操作。
- 压缩筛选区、商品卡边距和图片槽高度,使五条设计状态下的“猜你喜欢”入口进入首屏。
- 规格使用浅灰标签;接口没有规格时显示“规格暂未配置”。月销量缺少可信统计接口,显示“月售暂未开放”,不伪造设计示例数值。
- 商品图片继续读取后台封面;无图使用标准缺图图标,不显示图片地址。
- 保留真实分类筛选、详情、取消收藏、下架删除、条件版本加购和推荐分页。
## 验证结果
- Flutter analyze通过;收藏2项交互测试通过;320/360/390/430宽度及1.0/1.3文本缩放的8项视觉测试通过。
- 内置浏览器真实账号显示1条收藏、后台封面、实际分类和价格;分类筛选可切换,“猜你喜欢”弹层加载真实推荐商品9和8。未加购或取消收藏。
- Web使用`API_BASE_URL=http://127.0.0.1:12426`重新构建并在18572展示。
## 风险评估
当前收藏数量与产品图示例不同属于真实数据差异。商品10封面是此前上传的联调截图,不是正式商品素材;月销量没有统计口径。页面结构已接近原稿,但在正式素材与销量接口补齐前不判定严格1:1通过。

View File

@@ -0,0 +1,28 @@
# 我的记录聚合页开发日志
操作时间:2026-09-12(Asia/Shanghai)
操作类型:新增、扩展
影响模块:用户端 App 个人中心、记录聚合、视觉验收
## 操作前状态
图26只在需求和设计图中存在,App没有独立路由和可操作页面。供气订单与报修工单已有本人查询接口,设备操作和告警聚合接口尚未落地,发票记录明确属于二期。
## 具体操作
- 新增`UserRecordsPage`和`/records`路由,并在个人中心常用功能中增加“我的记录”入口。
- 并行读取本人供气订单和报修工单,按时间排序,支持全部、用气、报修筛选及真实详情跳转。
- 按图26还原页头、本月概览、六宫格和最近记录。未获取的设备操作数量显示“—”,不写虚假零值。
- 角阀操作、告警记录保留入口并提示“暂未开放”;发票记录提示“即将开放”。
## 验证结果
- `flutter analyze`通过。
- 页面聚合、筛选和两类未开放提示共2项定向测试通过。
- 320、360、390、430宽度及1.0、1.3文字倍率共8组视觉测试通过,已生成并检查图26并排对照。
- Web Release按`API_BASE_URL=http://127.0.0.1:12426`构建通过。
- 内置浏览器从个人中心实际点入,远程返回3条本月报修记录、共5条最近记录;报修筛选成功,首期缺项和二期提示均已点击确认。
## 风险评估
图26已有可操作页面,但仍为部分实现。设备操作、告警、押金和发票记录尚无统一服务端聚合事实;真实账号数据与设计示例不同,不能据此判定严格1:1和全功能验收通过。

View File

@@ -0,0 +1,28 @@
# 我的设备列表
## 实现
新增用户鉴权接口 `GET /heqi/client/v1/user/devices`,与产品档案查询共享归属和分页边界,仅返回当前用户启用且未报废、分类为智能阀或报警器的档案。返回分类和是否已配置厂商映射,不返回厂商编号、内部主键或自由参数。未分类和钢瓶均不计入设备数量。
图34新增 `/devices` 页面,个人中心“我的设备”进入。支持真实设备总数、名称或编号搜索、全部/角阀/报警器筛选、基本资料查看,并按用户真实分组展示。未知在线、离线和告警数量用缺省符号,不填零;控制、扫码添加与状态筛选明确暂未开放。
## 变更文件
- `backend/api/internal/logic/client/user/owned_products.go`:分类设备查询。
- `backend/api/internal/logic/client/user/owned_products_test.go`:本人、分类、状态与响应字段约束。
- `backend/api/internal/routers/client.go`:设备接口。
- `apps/user_app/lib/data/repositories/client_repository.dart`:分页读取与会话保护。
- `apps/user_app/lib/ui/features/profile/devices_page.dart`:新设备页面。
- `apps/user_app/lib/app/router.dart`、`ui/features/profile/profile_page.dart`:路由和入口。
- `apps/user_app/test/ui/devices_page_test.dart`:筛选、未知状态和三种宽度大字体。
## 验证
Go用户逻辑和路由测试通过;Flutter静态检查、四项设备页面测试通过;Web构建通过。初轮测试发现背景容器遮挡ListTile点击反馈,补透明Material后通过。顺带修正此前联系人页面及测试自身的三处lint。
新版API为 `heqi-user-devices-api.exe`,继续连接原远程数据库,无新增迁移。
## 联调记录与限制
后台经实际表单创建独立测试档案:`QA-DEVICE-20260911-01`,identity `01a08f7f-5110-7268-93e6-342fce9eccc0`,分类智能阀,归属模拟账户陈女士,不关联厂商硬件编号。停用时用户页显示零设备;已在后台审核启用,继续验证用户页。
实际后续验证:启用后从个人中心“我的设备”进入,显示1台及测试名称/编号;切换报警器为空,切换角阀恢复记录;点击控制出现暂未开放说明。测试结束通过后台审核恢复停用,测试档案保留用于追溯,不删除或改动原有产品。
设备分组已在后续批次接入真实新建、改名、删除和设备归组,见 `开发日志_设备分组_20260911.md`。尚未接通真实遥测、远程控制与设备添加;当前远程空数据与设计稿5台设备状态不同,图34不判完整通过。

View File

@@ -0,0 +1,33 @@
# 开发日志:押金管理首期底座与真实空态
操作时间:2026-09-11 22:25
操作类型:新增/扩展
影响模块:用户端 App、Client API、平台总后台、远程 PostgreSQL 表结构
## 操作前状态
个人中心的押金入口只能提示缺失,没有独立页、用户端接口、押金规则或押金记录后台入口。
## 具体操作
- 新增 `deposit_policy` 和 `deposit_record` 模型及增量迁移,迁移为表和每个字段添加中文注释。
- 新增登录用户的 `GET /heqi/client/v1/user/deposits`,只按 JWT 当前账号返回可退金额、在押数量、状态明细和规则。
- 新增 `/deposits` 页面,按最新图16实现汇总、四筛选项、明细卡和规则查看。
- 总后台新增“押金规则”和“押金记录”菜单;规则可新建编辑,记录只读。
- 修复后台新资源的字段中文名和显式编辑规则,消除启动时空白页。
## 操作后状态
内置浏览器可见后台押金规则空列表,App 真实账号显示 `¥0.00`、`0个`和“暂无押金记录”。没有伪造产品稿的示例金额或记录。
## 验证结果
- Flutter analyze、押金页定向测试、8组视觉尺寸和 Web release 构建通过。
- Go 客户逻辑、路由和平台资源测试通过,真实登录读取返回空列表。
- 后台资源合同检查、类型检查和生产构建通过;既有 lint 仍有2个旧错误和203个旧警告。
## 风险评估
后续图17批次已建立退瓶申请、上门回收、验收扣减、余额退款和不可变资金流水,本日志中的初始缺口已关闭。当前剩余风险为远程账号没有真实押金数据,尚不能进行一次不伪造数据的端到端演练。

View File

@@ -0,0 +1,34 @@
# 提交订单视觉与支付衔接开发日志
操作时间:2026-09-11 21:20
操作类型:修改、扩展
影响模块:用户端商城结算、订单支付路由、视觉验收
## 操作前状态
提交订单页仅覆盖基础地址、数量、金额和备注,页面分组与最新产品设计差异明显;创建订单后返回订单列表,没有进入支付确认流程。预约、优惠、押金和发票缺少可见的交付状态。
## 具体操作
- 按图14重排地址、配送时间、气站商品、费用明细、订单服务、支付方式和底部提交栏。
- 单品与购物车结算读取真实商品、气站、地址和钱包余额;商品存在后台图片时直接显示图片。
- 下单成功校验订单公开标识并进入 `/payment/shop/:identity`;未知结果保留幂等重试状态。
- 预约、优惠和押金显示“暂未开放”;明确属于二期的电子发票显示“即将开放”,点击均给出说明。
- 内置浏览器检查远程默认地址,确认旧数据缺少联系人时如实显示“待补充联系人”,未新增、编辑或提交地址。
## 代码变更
- `apps/user_app/lib/ui/features/shop/checkout_page.dart`:重建结算布局、接入气站与钱包读取、补充功能状态及支付跳转。
- `apps/user_app/tool/a1_visual_test.dart`:图14改用双商品购物车状态做视觉夹具。
- `apps/user_app/test/ui/shop_address_selection_test.dart`、`apps/user_app/test/ui/cart_page_test.dart`:验证下单成功进入支付确认页。
## 验证结果
- Flutter全量测试171项通过。
- 图14在320、360、390、430像素宽度及1.0、1.3文字缩放共8种组合通过视觉溢出检查。
- Web构建通过;390×844并排图已生成。
- 内置浏览器真实检查地址、商品图片、气站、钱包余额、“暂未开放”和“即将开放”弹层。未点击提交订单,未产生远程写入。
## 风险评估
配送预约、押金、优惠仍缺服务端契约;当前配送费按既有接口结果显示0元。电子发票属于二期。远程默认地址缺联系人,需用户在地址管理补全后才能用于下单。以上差异均在页面明示,没有伪造设计稿金额或业务状态。

View File

@@ -0,0 +1,23 @@
# 开发日志:气瓶下单首期闭环
操作时间:2026-09-11 23:25
操作类型:新增、扩展
影响模块:用户端 App、Client API、供气订单、支付与押金、平台字段展示
操作前状态:设计图18没有独立页面和用户创建供气订单接口;合同气瓶、价格、押金、地址和预约时段无法形成用户下单闭环,钢瓶只可用近似图标表示。
具体操作:
- 新增 `/gas/order`,实现气站信息、规格数量、真实钢瓶商品图、配送信息、押金说明、费用明细和二次确认。
- 新增 `GET /gas/order-options` 与 `POST /gas/orders`,按JWT账户校验有效合同、气瓶占用、本人地址、预约时间、服务端金额和幂等冲突。
- 为供气订单增加地址、预约时间和押金金额快照;新增 `gasorder_deposit`,支付成功后原子生成正式押金记录。
- 取消未支付订单时同步释放气瓶占用并取消待支付押金;缺押金规则时返回可见规格和明确原因,但禁止提交。
- 生成透明背景液化气钢瓶商品图并纳入 Flutter 资产,完成390×844并排比较和8组响应式视觉检查。
操作后状态:用户可从首页进入真实气瓶下单页;配置完整时可创建待支付订单并进入支付确认,配置不完整时明确显示首期缺项。远程账号未写入演示订单。
代码变更:`gas_order_create.go`、`gasorder_basic.go`、`gasorder_deposit.go`、`gas_deposit.go`、`gasorder.go`、`callback.go`、`client.go`、`gas_order_checkout.dart`、`gas_order_create_page.dart`、`client_repository.dart`、`router.dart`、`home_page.dart`、支付确认和订单详情页面、三套后台字段配置及测试文件。
验证结果:Go用户逻辑、支付及路由测试通过;Go Vet与构建通过;Flutter Analyze、气瓶下单Widget测试和8组视觉变体通过;远程只读接口确认返回气站、15kg合同气瓶、地址及6个预约时段,并准确指出押金规则未配置。
风险评估:下单范围受现有供气合同及合同已绑定实体气瓶约束。未配置押金规则的首次用瓶不得下单;需运营人员在平台后台“押金规则”完成配置后再做真实创建与支付验收。

View File

@@ -0,0 +1,29 @@
# 消息中心首期闭环
操作时间:2026-09-12 23:50(北京时间)
操作类型:新增、扩展
影响模块:用户消息 API、消息已读回执、用户端消息中心
## 操作前状态
个人中心消息按钮仅弹出“暂未开放”,仓库没有用户消息表、查询接口、已读状态和独立页面。产品设计图30要求安全、订单、服务、公告总览,分类筛选、未读状态、全部已读和对象跳转。
## 具体操作
- 新增 `user_message_read`,只保存本人对稳定消息键的已读回执;消息标题和正文继续由订单、工单及已发布公告事实生成。
- 新增 `GET /heqi/client/v1/user/messages` 和 `PUT /heqi/client/v1/user/messages/read`。查询按当前令牌账号限制订单和工单;公告仅取启用且已发布记录。写入前重新生成本人可见键集合,拒绝任意或他人对象。
- 新增 `/messages` 页面和个人中心真实入口,完成四类总览、全部/未读/安全/订单/服务筛选、单条已读、全部已读及订单、工单、公告跳转。
- 安全告警当前没有权威事件表,真实账号显示“暂无消息”,不构造演示报警。通知偏好入口跳转设置页;设置页继续将尚无服务端能力的项目标为“暂未开放”。
- 通过增量迁移在远程数据库创建 `dev_usage_stat` 与 `user_message_read`,包含表级、字段级中文注释及必要索引;未写入虚构计量或消息数据。
## 验证结果
- Go 用户端逻辑及路由测试通过。
- Flutter 消息中心两项测试通过,覆盖分类渲染、未读筛选和真实仓储已读动作。
- 320、360、390、430宽度与1.0、1.3文字比例共八组视觉测试通过。
- 内置浏览器读取远程账号:6条订单、4条服务、9条公告消息;点击第一条进入本人商城订单详情,返回后订单未读由6降为5;订单筛选只保留订单消息。
- 对照图:[30_并排对照.png](视觉验收/A1/30_并排对照.png)。
## 风险与剩余项
消息是业务快照的当前状态,不是每次状态迁移的历史事件;后续接入 Outbox/Worker 后需改为不可变事件消息。安全告警无权威用户事件接口,首期仍显示真实空状态。通知偏好服务端及严格1:1验收尚未完成,因此图30判为部分实现。

View File

@@ -0,0 +1,25 @@
# 用户产品归属查询
操作时间:2026-09-11
操作类型:新增
影响模块:用户 App API
## 行为与接口
新增受用户端 JWT 和客户端类型校验保护的 `GET /heqi/client/v1/user/owned-products`。
只读取当前登录用户拥有且启用、未软删除的 `product_info`,不使用历史归属授予访问权,也不接受请求参数指定其他用户。
返回 `items`、`page`、`page_size`、`has_more`。默认每页 30 条,显式分页沿用现有范围校验,最多 100 条。
每项仅含 `identity`、`name`、`code`、`product_status`、`control_available`、`telemetry_available`。
两个能力标志均为 false;产品档案同时涵盖钢瓶和瓶阀,不能据此宣称存在可控制设备或实时遥测。
## 代码和验证
- `backend/api/internal/logic/client/user/owned_products.go`:新增当前归属查询和分页响应。
- `backend/api/internal/routers/client.go`:新增一个鉴权路由。
- `backend/api/internal/logic/client/user/owned_products_test.go`:校验登录用户隔离、默认和显式分页、响应白名单及未开放能力。
- `go test ./internal/logic/client/user ./internal/routers` 通过。
## 当前限制
此轮仅完成接口基础,不代表“我的设备”页面完成或通过设计验收。尚未接入前端、重启 API 或进行远程数据和浏览器联调。未改动远程数据库结构或数据,也没有启动本地数据库。设备类型分类和真实遥测来源还需继续核对现有协议与实现。

View File

@@ -0,0 +1,24 @@
# 用气统计历史日期查询
操作时间:2026-09-12
操作类型:补齐首期功能
## 变更
`apps/user_app/lib/ui/features/profile/usage_statistics_page.dart` 新增 `_anchor` 和 `_selectDate()`,右上角日历由“暂未开放”改为日期选择器。确认选择后将日期传给既有统计接口;切换设备和日、周、月、年周期时保留该日期。取消或重复选择不额外查询,不能选择未来日期。
接口继续使用既有 `anchor=YYYY-MM-DD` 参数,无接口兼容性变更,无数据库写入。
## 验证
`apps/user_app/test/ui/usage_statistics_page_test.dart` 新增数据层参数捕获测试,覆盖取消不查询、确认传入日期、切换周期保留日期。三项页面测试通过。
## 尚未完成
后续修复:应用此前没有配置 Flutter 本地化委托,日期控件默认英文。已在 `lib/app/app.dart` 配置简体中文区域和官方本地化委托,在 `pubspec.yaml` / `pubspec.lock` 添加 SDK 自带 `flutter_localizations` 及其 `intl` 依赖,统一应用日期、时间和系统控件文案。日期页面三项回归测试通过。
中文修复验收:静态检查无问题,Release 构建通过。内置浏览器18575预览已打开日历,截图和语义树均显示“2026年9月”“周六”“上个月”“取消”“确定”,未来日期禁用。仅对该日历完成实际中文核对,其他日期页面仍需逐页验收。
补充验证:Flutter analyze 无问题,Web Release 构建通过。内置浏览器在18574独立预览中实际打开日期选择器,选择9月11日并确认返回;18572仍存在旧静态资源缓存。日期控件的月份和星期仍为英文,需要补齐应用中文本地化。当前账号无设备,浏览器验证未覆盖有数据查询,参数传递由页面测试覆盖。
本项完成不代表图27全页验收。真实计量数据闭环、安全趋势和严格视觉还原仍需继续;没有设备的账号继续显示真实空态。

View File

@@ -0,0 +1,23 @@
# 用气统计联调恢复
操作时间:2026-09-12 23:30(北京时间)
操作类型:修复、验证
影响模块:平台后台资源初始化、用气统计预览
## 原因与变更
后台白屏由 `src/api/resources.ts` 的 `f()` 初始化校验触发:新增 `stat_date` 等字段虽设置局部 label,但未注册公共 `fieldLabels`,抛出“资源字段缺少中文名称”并阻止整个后台加载。
在 `frontend/platform_admin/src/api/resources.ts` 的字段字典补充统计日期、四项用气量、口径版本和计算时间,共七个名称。保留公共字段校验,未改动权限和业务写入接口。
## 验证
- 新版 API 已启动于 12426,沿用远程数据库与 Redis 配置。
- 后台预览 18573 和 App 预览 18572 已恢复。
- 内置浏览器登录后台,进入“智能气阀管理 → 用气统计数据”,正常显示列表及 0 条记录。
- 内置浏览器点击新建,设备、日期、用气量、来源、口径版本、计算时间全部显示;未提交虚构计量数据。
- App 测试账号登录后进入 `/usage`,显示“尚无可统计设备”;历史日期按钮显示“暂未开放”。
## 剩余验收
本次证明后台初始化和两个预览已恢复,不证明有设备账号的统计闭环。真实设备归属、计量数据、历史日期选择、安全趋势及严格视觉对照仍待完成。图27仍为部分实现,全量目标继续执行。

View File

@@ -0,0 +1,29 @@
# 开发日志:电子发票二期入口
操作时间:2026-09-12(Asia/Shanghai)
操作类型:新增、扩展
影响模块:用户端订单、电子发票占位页、视觉验收
## 操作前状态
订单中心“开发票”只弹出通用二期提示,图24没有独立页面,用户无法看到该功能的产品形态和真实订单关联。
## 具体操作
- 新增`/invoice/:business/:identity`页面,从本人商城或供气订单详情读取订单号、商品和订单商品金额。
- 供气订单明确展示“押金不计入发票金额”,但不开具或推算可开票金额;开票金额显示“待二期规则确认”。
- 按产品图保留发票类型、抬头类型、单位名称、税号、发票内容、邮箱、手机号、常用抬头和提交按钮。
- 页面顶部、字段状态和提交弹窗统一标识“二期功能 · 即将开放”;不创建静态成功响应,不新增发票记录或税务接口。
- 已完成订单列表和订单详情均可进入该页面。
## 验证结果
- `flutter analyze`通过。
- 电子发票页面、订单列表及订单详情共9项定向组件测试通过。
- 320、360、390、430宽度与1.0、1.3文字倍率共8组视觉检查通过;已生成图24并排对照图。
- Web Release构建通过。
- 内置浏览器从远程真实已完成气瓶订单点击“开发票”进入,显示真实订单`MOCK-GASORDER-001`和订单商品金额98元;点击提交后显示“电子发票即将开放”,没有远程写入。
## 风险评估
发票抬头、税号校验、开票资格、金额口径、申请、税务回执、作废红冲、预览与下载均属于二期,本轮没有伪造。页面视觉已按相同结构对照,但因二期真实字段为空,不能判定严格1:1验收完成。

View File

@@ -0,0 +1,43 @@
# 登录页视觉对照
## 本轮修改
来源:`doc/用户端APP-最新参考产品设计/01-登录页.png`。
在内置浏览器以 390×844 核对旧页面,发现登录方式分隔线、输入框和主按钮整体偏下,输入框边框偏淡,主按钮和登录方式文字偏小。
修改 `apps/user_app/lib/ui/features/auth/login_page.dart` 的 `build`、`_modeTab`:
- 品牌宽度从 150 调整到 140,缩短品牌到登录方式的垂直间距。
- 标签 14、登录方式 16、主按钮 18 字号;输入区约 50 高,边框改为设计图的浅灰色。
- 主按钮使用更接近来源图的蓝色及五像素圆角。
- 协议说明移回忘记密码下方,保留真实协议查看;注册入口移到其后,未删除原有注册功能。
- 调整协议区域按钮内边距,避免手机宽度下多余换行。
额外修正此前新增设备卡测试中的一处字符串插值 lint,不改变测试行为。
## 验证
登录页八项现有测试通过,涵盖登录方式切换、凭据和焦点保护、校验、提交及验证码请求关联。
Flutter 静态检查通过。
内置浏览器实际切换到密码登录,并空提交,确认显示手机号和密码必填提示,没有提交登录请求。
390×844 的主布局已实际截图核对,主要控件位置比修改前接近来源图。
## 验收边界
尚未判定图 01 完全通过:仍需更细的字体与来源图差异核对,以及其他宽度、放大文字、真实登录和协议内容验收。原图没有注册入口,现有注册功能保留在协议区下方,此处是明确保留的功能差异。
短信供应商尚未接入,验证码不能宣称已真实发送。
设备方面,本轮检查 `product_info` 与 `iot_device_message`:前者含钢瓶等实体档案,后者使用厂商 `device_id`,尚未确认可直接用于用户端的可靠映射。没有将产品档案冒充设计图 34 的在线设备列表,控制和遥测继续提示未开放。此前新增归属接口仍未部署到当前运行 API。
## 最终复核:2026-09-11 17:00后
操作类型:修改、验证
影响模块:登录页视觉、验证码交付状态、视觉验收夹具
- 事实源929×1693保持比例缩放到390像素宽,放入390×844画布;没有再用满高拉伸图判断间距。
- 登录页恢复与事实源一致的紧凑纵向节奏,并修正按钮文字样式继承。视觉夹具中的标签、验证码按钮、登录和忘记密码不再显示方框。
- `UserSession.sendCode`识别服务端`delivery_status=not_sent`,抛出稳定2410提示;页面显示“短信验证码暂未开放”,不启动60秒倒计时。
- 内置浏览器真实验证:Mock验证码请求显示暂未开放;切换密码模式后使用授权测试账号登录成功并进入首页。
- 九项登录页面测试、八组320/360/390/430宽度及1.3倍文字视觉用例、Flutter静态检查和Web Release构建通过;全量Flutter 160项测试通过。
最终共同区域未发现P0、P1或P2布局问题,品牌尺寸、标签分隔线和局部字重存在P3差异。“首次使用?注册账号”按用户明确要求保留,但不在设计源中;真实短信供应商仍未配置,因此图01最终状态为blocked,不能宣称整页严格1:1和完整功能通过。

View File

@@ -0,0 +1,34 @@
# 紧急联系人开发
## 范围与行为
参照图10新增 `/safety/contacts`,个人中心入口进入真实列表。支持姓名、手机号、关系资料的新增、编辑、归档删除,最多五位,列表隐藏手机号中间四位。告警通知、设备查看、远程控制和顺延通知均明确“暂未开放”,不因联系人保存而授权。
后端新增鉴权 `GET/POST /emergency-contacts`、`PUT/DELETE /emergency-contacts/:identity`。所有查询限定当前登录账户;写入持有账户行锁,保证五人上限及电话号码去重。新增必须带UUID请求号,相同请求重试返回原记录,已归档记录不能因重试恢复。删除为状态归档。
独立迁移命令 `migrate-emergency-contacts` 已对现有远程配置执行成功,只创建 `user_emergency_contact` 及相应注释和唯一索引,未执行全库迁移或初始化。
## 文件
- `backend/api/internal/models/user_emergency_contact.go`:联系人资料模型。
- `backend/api/internal/logic/client/user/emergency_contacts.go`:本人CRUD与边界校验。
- `backend/api/internal/logic/client/user/emergency_contacts_test.go`:输入、上限、越权与响应能力测试。
- `backend/api/internal/routers/client.go`:四条用户鉴权路由。
- `backend/api/cmd/cli/emergency_contact_migration.go`、`main.go`:独立事务迁移命令。
- `apps/user_app/lib/data/repositories/client_repository.dart`:联系人接口和会话保护。
- `apps/user_app/lib/ui/features/profile/emergency_contacts_page.dart`:列表、编辑和删除确认。
- `apps/user_app/lib/app/router.dart`、`ui/features/profile/profile_page.dart`:路由及入口。
- `apps/user_app/test/ui/emergency_contacts_page_test.dart`:失败保留输入和请求号、成功刷新及权限未开放。
## 验证及限制
Go用户逻辑、路由和CLI测试通过;Flutter静态检查、联系人页面测试、Web构建通过。当前API进程已切换为 `heqi-contacts-api.exe`,仍连接原远程数据库。
尚未完成告警联动、联系人顺序调整、设备授权审计、后台治理及真机拨号验收;不将这些首期缺项归为二期。图10仍需完善图标、字体、布局和真实状态对照,未判完整通过。
内置浏览器390×844实际完成:模拟账号登录后空列表→新增测试联系人→列表显示脱敏手机号→编辑姓名并保存→列表显示新姓名→删除确认→恢复空列表。仅本次新增的测试记录被状态归档,数据库保留幂等记录;未拨打电话、未发短信、未授予设备权限。卡片密度和权限提示布局仍与原图不同,保持部分实现状态。
后续视觉修正:恢复蓝底白字编号和关系标签;“权限 · 暂未开放”统一显示在权限行上方,每项仍可点击查看说明。电话、编辑与权限按钮按原图并排,320宽或放大文字时分行。320/390/430宽度、1.3倍字体及长姓名/关系描述测试通过,新增实际点击远程控制后未开放提示的断言。仍未判整页视觉通过。
新版Web在内置浏览器390宽用独立“视觉测试”联系人核对,编号、标签及五个操作入口同排可见,远程控制弹出未开放说明。补充后端新增请求重放测试,验证启用记录重试不重复插入、归档记录不能被重试复活,测试通过。
错误反馈修正:新增稳定业务码2501(五人上限)、2502(本人列表号码重复)、2503(原请求已处理且资料不一致或已归档)。前端只对明确业务拒绝显示原因,未知网络错误保留“结果未确认”,删除失败使用删除文案。后端联系人测试及七项前端联系人测试通过;新版API已重启,数据库结构未改动。此轮错误分支主要由自动测试验证,不代表所有异常均已完成浏览器联调。

View File

@@ -0,0 +1,51 @@
# 订单中心视觉与气瓶操作开发日志
操作时间:2026-09-11
操作类型:修改、扩展
影响模块:用户端订单中心、用户订单接口、商城订单成交快照、视觉验收脚本
## 操作前状态
订单中心使用搜索框和稀疏卡片,和图20的页头搜索图标、横向状态标签、商品信息及底部操作差异明显。气瓶订单列表没有气站名称,已分配但未付款状态显示“待处理”,气瓶取消接口已存在但列表未发布取消动作。商城成交快照没有封面地址,新订单详情无法稳定展示成交时图片。
## 具体操作
- 用户端改为“我的订单”居中页头和搜索图标,保留气瓶订单、商城订单、报修工单三标签。
- 增加订单号及商品名称搜索,三类列表共同响应搜索条件;状态区保留设计稿固定状态并合并服务端实际状态。
- 订单卡展示订单号、下单时间、状态、商品、气站、规格、金额及服务端允许动作;点击卡片仍可进入详情。
- 气瓶取消调用专用接口并要求二次确认;待付款状态同时显示取消订单和去支付。
- 再次购买、申请售后、电子发票属于后续阶段,入口保留并统一展示“该功能将在后续版本开放,敬请期待。”
- 气瓶订单接口批量读取气站名称,状态16统一为“待付款”,创建态和已分配态发布取消动作。
- 商城新订单读取后台商品封面并写入 `product_snapshot.image_url`,保证后台后续改图不会改变历史成交快照。历史订单的空快照保持真实,不进行猜测补图。
- 视觉脚本补入商城订单分支,气瓶与商城均生成320、360、390、430宽和1.0/1.3文本比例截图。
## 操作后状态
首期已有订单列表、搜索、状态筛选、详情跳转、气瓶取消、商城取消/收货和既有支付/退款动作均有真实接口或页面连接。远程气瓶完成订单可显示气站和15kg规格;商城历史订单可正常读取,之后新建的商城订单能够展示成交时封面。
当前气瓶商品类型及订单明细没有图片字段,远程账号也只有1笔完成气瓶订单,因此没有伪造设计稿中的钢瓶图和3笔不同状态数据。图20仍为部分实现,不能标记严格1:1通过。
## 代码变更
- `apps/user_app/lib/ui/features/orders/orders_page.dart`:三标签控制、页头搜索和列表查询传递。
- `apps/user_app/lib/ui/features/orders/order_list.dart`:状态筛选、订单卡字段、紧凑操作及后续功能提示。
- `apps/user_app/lib/domain/models/order_summary.dart`:订单号、气站、规格和图片快照解析。
- `apps/user_app/lib/data/repositories/client_repository.dart`、`order_action_handler.dart`:气瓶取消接口和动作分流。
- `backend/api/internal/logic/client/user/gasorder.go`、`gas_detail.go`:气站名称、状态名称及允许动作。
- `backend/api/internal/logic/client/user/shop.go`、`cart.go`:商品封面读取和成交快照固化。
- `apps/user_app/test/ui/orders_page_test.dart`、`backend/api/internal/logic/client/user/gas_order_list_test.go`、`checkout_test.go`:真实动作路由、搜索、后续提示及图片快照回归。
## 验证结果
- Flutter静态分析通过;随后加入个人中心认证解析回归后,全量166项测试通过。
- Flutter Web release构建通过,API地址为本地12426端口。
- Go全量测试、`go vet ./...` 和API可执行文件构建通过。
- API已在12426重启并通过健康检查;继续使用 `etc/heqi_dev.yaml` 中既有远程PostgreSQL和Redis,没有启动本地数据库容器。
- 160项视觉fixture生成通过;已查看图20气瓶与商城390×844并排对照。
- 内置浏览器以远程账号验证气瓶订单真实字段、搜索空态、后续版本弹层、商城订单列表及详情;未执行支付、取消或其他写操作。
## 风险评估
- 历史商城订单没有 `image_url` 的成交快照,无法无依据补回原商品图;新订单已修复。
- 气瓶商品图片尚无正式数据模型和后台维护入口,继续显示真实的无图状态。
- 取消和支付属于写操作,本轮浏览器只验证入口与自动测试,没有改变远程业务订单。

View File

@@ -0,0 +1,45 @@
# 订单支付确认开发日志
操作时间:2026-09-11 20:55:00
操作类型:新增/扩展
影响模块:用户端订单、钱包支付、气瓶订单、视觉验收
## 操作前状态
订单动作使用底部菜单直接选择渠道,没有图19独立支付确认页。气瓶订单支付只处理外部渠道,商城余额支付没有写入统一支付单,退款链路无法找到该支付事实。
## 具体操作
- 新增`/payment/:business/:identity`,同时读取本人订单详情和钱包,展示应付金额、商品快照、订单号、支付方式、安全验证和金额明细。
- 余额支付使用六位脱敏圆点输入,扣款前再次确认订单号、渠道和金额;未知结果保留原幂等请求号。
- 气瓶和商城余额支付均在数据库事务内锁定订单与钱包,校验支付密码,写入订单状态、支付单和钱包记录。
- 订单不在可支付状态时禁用底部按钮。优惠券无服务端接口,保留位置并显示“暂未开放”及原因弹层。
- 支付页复用服务端充值渠道就绪配置:当前Web环境未配置商户证书时,微信和支付宝直接显示“暂未开放”并禁用,不再允许用户提交后才得到配置错误。
- 气瓶订单使用真实钢瓶位图;服务端订单快照有图片时优先显示快照,普通商城商品缺图时保持缺图图标,不伪造商品照片。
- 按最新图19重校卡片高度、支付方式图标/单选位置、密码圆点、订单明细和固定底部按钮。
## 代码变更
- `apps/user_app/lib/ui/features/orders/payment_confirmation_page.dart`:支付页与交互。
- `apps/user_app/lib/ui/core/payment_pin_field.dart`:共用六位支付密码组件。
- `apps/user_app/lib/app/router.dart`、`apps/user_app/lib/ui/features/orders/order_action_handler.dart`:支付路由与订单入口。
- `apps/user_app/lib/data/repositories/client_repository.dart`:支付密码、商城/气瓶参数校验与余额结果校验。
- `backend/api/internal/logic/client/user/gasorder.go`、`shop.go`:原子余额支付、幂等重试和支付事实。
- `apps/user_app/test/ui/payment_confirmation_page_test.dart`、`backend/api/internal/logic/client/user/wallet_order_payment_test.go`:页面和重试测试。
- `apps/user_app/test/support/a1_fixture.dart`:视觉夹具提供明确的渠道就绪状态,不访问真实支付渠道。
- `apps/user_app/tool/a1_visual_test.dart`、`scripts/compare-user-app-a1.ps1`:图19多尺寸截图和并排对照。
## 验证结果
- Flutter analyze通过,Flutter全量171项通过。
- 图19在320/360/390/430宽、1.0/1.3文字缩放共8项通过;当前视觉集合共184项通过。
- Go全量`go test ./...`、`go vet ./...`和API构建通过。
- Flutter Web Release构建通过,API使用仓库现有远程PostgreSQL/Redis配置重启成功。
- 内置浏览器展示远程真实订单金额、钱包余额、全部分组和优惠券未开放弹层。
- 2026-09-11 23:55再次在内置浏览器打开真实已取消订单`EC1788842040900189900`:金额与余额来自远程数据,微信/支付宝显示“暂未开放”,优惠券弹层可见,订单不可支付按钮禁用;未产生订单或资金写入。
## 风险评估
- 当前测试账号无待付款订单,浏览器展示使用真实已取消订单,没有执行远程扣款。待付款成功路径由组件测试和服务端事务测试覆盖。
- 微信、支付宝仍依赖环境的真实商户配置与回调;页面按服务端配置状态判定是否可选,尚未做真实渠道回调验收。
- 优惠券缺少接口和后台配置,当前只显示首期缺失状态,不计为完成。

View File

@@ -0,0 +1,26 @@
# 设备分类与厂商映射
## 问题与变更
现有产品档案既包含钢瓶,也包含瓶阀;原有厂商上行消息使用独立16位设备编号,不能靠名称推测归属关系。
新增 `product_info.device_kind`(未分类、智能阀、报警器、钢瓶)和 `vendor_device_id`(可为空的厂商编号)。历史记录默认未分类且未关联,不改写现有用户归属。
后台产品新建、编辑与详情加入两项配置。后端写入白名单和校验同时扩展:只有智能阀/报警器允许厂商编号,编号必须为16位数字且非全零;非空编号由数据库全局唯一索引约束。空编号表示尚未关联,不代表设备离线。
## 文件与验证
- 模型:`backend/api/internal/models/product_info.go`。
- 写入校验:`backend/api/internal/logic/platform/product/product.go`、`device_mapping.go`。
- 测试:`device_mapping_test.go`。
- 独立迁移:`backend/api/cmd/cli/device_mapping_migration.go`,命令 `migrate-device-mapping`。
- 后台字段:`frontend/platform_admin/src/api/resources.ts`。
产品逻辑、路由、CLI测试通过,后台类型与48项资源契约检查通过。
迁移已在原远程配置执行成功,只新增两列、注释和唯一索引;API已切换到 `heqi-device-mapping-api.exe`。
浏览器首次检查发现通用字段函数要求在中文名称字典注册,即便调用处已有label也不能省略,已补齐并验证列表恢复显示“未分类/未关联”。
内置浏览器实际进入新建表单,展开分类选项并选择“智能阀”,确认四项分类及厂商编号输入区可见。此次只检查表单,没有提交新产品或修改已有产品。
## 尚未完成
此变更只建立明确映射配置,用户“我的设备”页面和遥测读取还未接入,不开放远程控制。未将现有示例产品自动映射到真实厂商编号。配置保存、重复编号及实际设备联调还需继续验证,不能据此宣称设备闭环完成。

View File

@@ -0,0 +1,47 @@
# 设备分组开发日志
操作时间:2026-09-11 16:00—17:00
操作类型:新增、扩展
影响模块:用户端设备、平台产品归属、远程 PostgreSQL
## 操作前状态
图08没有独立页面,图34的“设备分组”仅弹出暂未开放提示。产品档案已有本人归属和设备分类,但没有用户分组资料或归组字段。在线状态、安全检查、扫码添加和远程控制没有可用物联网接口。
## 具体操作
- 新增 `user_device_group`,保存本人分组名称、顺序和新增幂等号;为每个字段及表补充中文数据库注释。
- 为 `product_info` 增加 `device_group_id`。平台转移产品归属时自动清空旧用户分组,避免新用户继承旧分组。
- 新增本人分组列表、新建、改名、删除和设备归组接口。所有查询都从登录令牌确定用户,客户端传入其他用户标识无效。
- 删除分组时在同一事务内把组内设备移回未分组;分组新增限制20个,同名和幂等重放返回稳定错误码。
- 新增图08页面,完成新建、编辑、删除、查看组内设备及设备归组。群控、安全检查明确提示“暂未开放”。
- 图34改为真实分组卡片,并按设计稿补齐统计图标、分隔线和427像素Web手机画布;最终轮继续收紧搜索框、筛选控件和统计卡高度。
## 代码变更
- `backend/api/internal/models/user_device_group.go`:设备分组模型。
- `backend/api/internal/models/product_info.go`:产品归组字段。
- `backend/api/internal/logic/client/user/device_groups.go`:分组与设备归组业务。
- `backend/api/internal/routers/client.go`:五条分组相关路由。
- `backend/api/cmd/cli/device_group_migration.go`:独立可重复远程迁移。
- `apps/user_app/lib/ui/features/profile/device_groups_page.dart`:图08页面。
- `apps/user_app/lib/ui/features/profile/devices_page.dart`:图34分组布局。
- `apps/user_app/lib/domain/models/device_group.dart`、`data/repositories/client_repository.dart`:分组模型与接口适配。
- `apps/user_app/lib/app/app.dart`、`app/router.dart`:427像素Web预览画布和页面路由。
## 操作后状态
用户可创建、改名和删除本人分组,并把本人启用的智能阀或报警器移入或移出分组。删除分组后设备自动回到未分组。页面不展示虚构在线、离线、安全或控制结果。
## 验证结果
- 远程迁移 `migrate-device-groups` 成功,未启动本机 PostgreSQL、Redis 或 Docker。
- `go test ./...`、`go vet ./...` 和API构建全量通过;新增输入边界、本人隔离、响应白名单和路由检查。
- Flutter `analyze` 无问题;设备与分组9项定向测试通过,320/390/430宽度及1.3倍文字无溢出;全量159项Flutter测试通过。
- Web Release 使用浏览器API地址构建成功。
- 内置浏览器真实完成:创建“厨房”→测试设备归组→改名“厨房组”→删除→设备回到未分组。测试分组已删除,测试设备已恢复停用,最终为0设备、0分组。
- 视觉证据:`视觉验收/08-设备分组_并排对照_20260911.jpg`、`视觉验收/34-我的设备_并排对照_20260911.jpg`。
## 风险评估
遥测、安全检查、扫码添加和远程控制仍缺服务端及厂商能力,页面明确显示暂未开放。源图是5台设备和3个分组,当前远程测试结束后为空状态,无法进行同内容像素验收,因此图08、34仍为视觉验收阻塞状态。

View File

@@ -0,0 +1,9 @@
# 设置页未开放提示
修改 `apps/user_app/lib/ui/features/settings/settings_page.dart` 中账号认证、登录设备、通知、权限、隐私与注销入口的状态说明,统一为“暂未开放”,点击继续使用现有统一提示弹窗。
此前安全告警通知显示“安全告警不可关闭”,但通知通道尚未接入,会让用户误以为已在接收告警。本次改为明确的未开放状态,未增加虚假的开关或通知成功状态。
现有两项设置回归测试通过,覆盖缓存清除确认、取消与退出,以及登录密码校验与失败处理。此修改不代表通知、认证或设备功能已完成,也未将它们改归二期。页面整体仍待设计与功能完整验收。
Web 构建通过。内置浏览器使用已授权模拟账号完成密码登录,回跳设置页;390×844截图核对未开放状态可见,并点击“安全告警通知”,实际出现“该功能暂未开放,目前无法使用。”。对照图31,分组基本对应,但行高、图标和通知控件仍有差异,未判整页通过。

View File

@@ -0,0 +1,27 @@
# 购物车视觉与首期状态开发日志
操作时间:2026-09-11 21:50
操作类型:扩展
影响模块:用户端购物车、商品图片空状态、购物车模型
## 操作前状态
图13已有真实购物车增删改查、推荐和结算,但缺气站配送、服务保障、规格与押金状态区,页面层级与产品设计差异明显。
## 具体操作
- `cart_page.dart` 增加真实服务归属配送卡、服务保障区、商品规格兼容展示和固定栏押金状态;配送、保障和押金缺少首期服务端能力时统一显示“暂未开放”。
- `cart_item.dart` 兼容解析后续接口可返回的分类与规格字段,旧接口不受影响。
- `shop_page.dart` 将缺图和加载失败改为标准图片状态图标,不再把图片地址或错误文本当作商品图。
- 保留原购物车条件版本、服务端确认数量、管理删除、推荐和多商品结算行为。
## 验证结果
- Flutter analyze 通过;购物车3项交互测试通过;图13在320/360/390/430宽度及1.0/1.3文本缩放的8项视觉测试通过。
- 已生成 `docs/视觉验收/A1/13_并排对照.png` 并逐项查看。
- API继续连接既有远程数据库与Redis,本地API重建后在12426监听;Web使用本地API配置重建。
- 内置浏览器真实账号显示“和气示例气站”、原购物车商品、后台推荐图片、真实金额和状态提示;点击预计送达显示“该功能暂未开放”。未提交订单或修改购物车。
## 风险评估
原购物车商品未配置封面与规格,真实页面按事实显示缺图图标和“规格暂未配置”。后台已有图片的推荐商品能够显示,但当前上传素材是联调截图,不是正式商品素材。押金、配送时效和服务保障规则仍缺服务端模型,不能伪造设计稿金额或承诺,因此严格1:1仍未通过。

View File

@@ -0,0 +1,27 @@
# 开发日志:退瓶退押金首期闭环
操作时间:2026-09-11 22:50
操作类型:新增/扩展
影响模块:用户端 App、Client API、平台总后台、远程 PostgreSQL 增量表
## 具体操作
- App 新增 `/deposits/return`,只列出服务端允许退瓶的本人押金记录。
- 地址只能选本人有效地址;预约须晚于30分钟后、时段不超过4小时且不超过31天。
- 用户需逐项确认瓶体、阀门、停止使用和规则,并通过最终确认对话框后才提交。
- Client API 新增幂等创建、本人查询和未上门取消;取消后可用新请求号重新申请。
- 总后台新增“退瓶处理”,状态严格按待上门、待验收、待退款、已完成流转。
- 验收扣减不得超过原押金;退款与钱包余额、押金状态、退瓶状态及 `deposit_refund` 流水同事务提交。
## 验证结果
- Go 预约边界、路由、客户逻辑和平台逻辑测试通过,`go vet` 及构建通过。
- Flutter analyze、押金页和退瓶页定向测试通过;320/360/390/430 与 1.0/1.3 文字缩放共8组视觉变体通过。
- 总后台资源合同、类型检查和生产构建通过。
- 远程账号当前无押金记录,因此内置浏览器只能验证真实空态,没有写入伪造押金或退款记录。
## 风险评估
最近安检合格日期尚无用户端权威查询接口,页面保留位置并标明“暂未开放”。真实资金闭环已实现,但上线前仍需用业务押金数据完成实际端到端演练。

View File

@@ -0,0 +1,40 @@
# 开发日志:配送详情与隐私化轨迹
操作时间:2026-09-12 00:05(Asia/Shanghai)
操作类型:新增、扩展
影响模块:用户端 App、Client API、视觉验收
## 操作前状态
图22和图23没有独立用户页面。订单详情的“查看配送”只能进入未开放提示,用户端也没有本人订单的配送人员、有效资质或简化轨迹接口。
## 具体操作
- 新增本人供气订单配送详情接口,读取订单、气站、配送点、当前配送员、有效资质、最新轨迹摘要和商品;不下发员工内部账号或明文手机号。
- 新增本人供气订单配送轨迹接口,复用配送端已经上报的不可变轨迹点和订单状态历史。经纬度约化到三位小数后下发,最多返回最近一次配送尝试的200个顺序点。
- 新增图22配送详情页和图23配送轨迹页,并将订单详情、配送详情、配送轨迹三页串联。轨迹页支持真实刷新,地图背景为项目本地位图,蓝色路线只根据服务端隐私化坐标绘制。
- 车辆后台资料、受控电话、订单消息和配送问题上报目前没有完整服务,入口保留并明确显示“暂未开放”。这些是首期缺项,没有标为二期。
- 增加图22、图23的390×844对照图及320、360、390、430四种宽度和1.0、1.3两种文字倍率截图。
## 代码变更
- `backend/api/internal/logic/client/user/delivery_detail.go`:本人配送详情聚合与能力状态。
- `backend/api/internal/logic/client/user/delivery_track.go`:本人轨迹、坐标约化和履约节点。
- `backend/api/internal/routers/client.go`:新增配送详情及轨迹只读路由。
- `apps/user_app/lib/domain/models/delivery_detail.dart`、`delivery_track.dart`:严格解析服务端事实。
- `apps/user_app/lib/ui/features/orders/delivery_detail_page.dart`、`delivery_track_page.dart`:图22和图23页面。
- `apps/user_app/lib/app/router.dart`、`client_repository.dart`:路由和仓储接入。
- `apps/user_app/assets/staff/delivery-worker.png`、`assets/design/delivery-route-map.png`:视觉夹具人员图和无文字地图底图。
## 验证结果
- Go:`go test ./internal/logic/client/user ./internal/routers`、`go vet ./...`、`go build`通过。
- Flutter:`flutter analyze`、配送详情/轨迹组件测试、图23八组视觉测试和Web Release构建通过。
- 真实只读联调:远程样例订单返回“已完成”、王师傅、脱敏电话、1个隐私化位置点和1个履约节点;未创建或修改订单、资金、轨迹及人员资料。
- 内置浏览器:从图22页面点击“查看实时轨迹”进入图23,地图、状态、时间线、人员和底部按钮均可见;刷新可重新读取数据;电话入口显示“电话联系暂未开放”。
## 风险评估
- 远程样例订单只有一个轨迹点,真实页不能形成完整道路折线;Fixture仅用于同状态视觉对照,不能替代真实多点联调。
- 当前地图是无地名的本地背景,路线表达为隐私化坐标的相对进度,不声称提供精确导航。
- 配送车辆、头像资源代理、受控呼叫/消息和配送异常上报仍是首期待办,因此图22和图23均记为“部分实现”。

View File

@@ -0,0 +1,40 @@
# 钱包提现与银行卡开发日志
操作时间:2026-09-11 19:40
操作类型:扩展
影响模块:用户端钱包、银行卡、提现申请、Client API、钱包数据模型
## 操作前状态
图28已有余额、账单和充值入口,但提现仍弹“暂未开放”,银行卡入口没有页面。服务端已有本人银行卡绑定、解绑、提现申请和提现记录接口,Flutter未接入;银行卡没有默认到账卡字段和切换接口。
## 具体操作
- 新增`WalletBank`、`WalletWithdrawal`强类型模型,金额继续使用整数分,银行卡只读取脱敏卡号。
- 新增`/wallet/withdraw`和`/wallet/banks`页面,接入真实余额、到账卡、提现记录、支付密码、二次确认、绑定和安全解绑。
- 图28的提现和银行卡入口改为真实导航;押金、优惠券、待退款仍保留“暂未开放”入口,不填写设计样例金额。
- 新增默认到账卡服务端字段与切换接口;首张新卡自动设为默认,解绑默认卡后选择下一张,待处理提现仍禁止解绑。
- 提现提交只显示服务端返回的待审核或实际状态,不把申请成功写成已到账。
## 代码变更
- `apps/user_app/lib/domain/models/wallet_account.dart`:银行卡、提现记录及金额解析。
- `apps/user_app/lib/data/repositories/client_repository.dart`:银行卡、默认卡和提现接口适配。
- `apps/user_app/lib/ui/features/wallet/wallet_page.dart`:图28真实入口和视觉文案。
- `apps/user_app/lib/ui/features/wallet/withdrawal_page.dart`:图39完整首期页面。
- `apps/user_app/lib/ui/features/wallet/bank_cards_page.dart`:图40列表、添加、默认卡和解绑。
- `backend/api/internal/models/wallet_bank.go`、`internal/logic/common/client_wallet.go`、`internal/routers/client.go`:默认卡字段、接口和事务规则。
- `apps/user_app/test/data/wallet_account_test.dart`、`test/ui/withdrawal_page_test.dart`、`tool/a1_visual_test.dart`:契约、交互和多尺寸视觉测试。
## 验证结果
- `flutter analyze`通过;Flutter全量170项测试通过;Web Release构建通过。
- 图39修复窄屏银行卡下拉和到账时间溢出;图39、40纳入320/360/390/430宽及1.0/1.3倍文字截图。
- `go test ./...`、`go vet ./...`和API构建通过;新API已在12426重启,继续使用既有远程数据库配置。
- 内置浏览器确认真实余额、真实可提现余额、脱敏银行卡、添加表单和押金未开放提示;没有提交提现、绑定、解绑或切换现有银行卡。
## 风险评估
银行卡渠道验证回执、短信验证码供应商和提现到账渠道仍依赖外部服务配置;当前首期支持支付密码校验和平台审核状态。图28的押金、优惠券、待退款仍无真实业务接口,严格1:1与全功能验收继续不通过。

View File

@@ -0,0 +1,49 @@
# 首页视觉与入口开发日志
操作时间:2026-09-11
操作类型:修改、扩展
影响模块:用户端首页、公告领域模型、共享底部导航
## 操作前状态
首页能读取服务归属和公告,但设备卡、快捷入口、安全记录、公告列表与产品设计图的高度和信息层级差异明显。“查看详情”仍弹未开放提示,已完成的设备列表和设备分组无法从首页进入;公告只显示版本号,没有服务端已有的摘要和日期。游客服务归属没有使用设计卡片。
## 具体操作
1. 将服务归属卡内边距和图标尺寸收敛到设计比例,并让游客状态复用同一张卡片。
2. 重排设备未接入状态,保留四项指标结构且不展示虚构遥测。
3. 将设备详情、设备分组和一键报修接入现有真实路由;受保护入口保留登录回跳。
4. 快捷入口和安全信息使用设计稿相同的信息层级;未实现能力通过点击弹层说明“暂未开放”。
5. 公告领域模型读取服务端`created_at`,首页展示前两条真实标题、摘要和日期并进入公告正文。
6. 用户端底部导航高度调整为64像素,并恢复选中项浅蓝背景。
## 代码变更
- `apps/user_app/lib/ui/features/home/home_page.dart`:首页布局、真实入口、公告行和未开放入口。
- `apps/user_app/lib/ui/features/home/service_relation_card.dart`:紧凑布局及游客可点击状态。
- `apps/user_app/lib/ui/features/home/device_status_placeholder.dart`:诚实设备缺项结构。
- `apps/user_app/lib/ui/core/feature_entry.dart`:新增紧凑和状态文字显示选项,默认行为保持兼容。
- `apps/user_app/lib/domain/models/primary_models.dart`、`apps/user_app/lib/data/repositories/primary_repository.dart`:公告日期映射。
- `apps/heqi_design_system/lib/src/theme.dart`:用户端底部导航视觉。
- `apps/user_app/test/support/a1_fixture.dart`、`apps/user_app/test/ui/primary_pages_test.dart`:公告双行数据及入口测试。
## 行为变化
修改前:首页“查看详情”无法打开已完成设备页,分组入口仍显示未开放,公告显示版本号。
修改后:首页能进入设备、设备分组、报修及公告正文;公告显示真实摘要和日期;没有接口的设备值仍显示“暂不可查询”,其余未接入入口点击后明确说明当前不可用。
## 验证结果
- `flutter analyze`:通过。
- `flutter test --no-pub`:161项通过。
- 图03视觉用例:320、360、390、430像素宽,1.0与1.3倍文字共8项通过。
- `flutter build web --release --dart-define=API_BASE_URL=http://127.0.0.1:12426`:通过。
- 内置浏览器:远程公告标题、摘要、日期显示成功;扫码添加弹出“暂未开放”;设备详情游客路径进入登录页。
- 并排检查:设计图保持宽高比,主要卡片的顺序、宽度、圆角和密度已收敛。
## 风险评估
设备遥测、扫码、蓝牙、安全告警与气瓶详情尚无首期接口,首页不能显示设计稿中的示例状态。公告日期使用现有`created_at`,服务端后续若增加独立发布时间,应改为优先读取发布时间。共享导航仅调整用户端品牌,服务端App保持原高度。

View File

@@ -0,0 +1,183 @@
# 用户端 App 全量功能开发进度
更新时间:2026-09-13。58张设计中,36张已有页面实现(其中34张部分实现、2张首期功能闭环),22张尚无对应独立完整页面,0张通过严格1:1全功能验收。一级入口存在或弹出“暂未开放”均不计为功能完成。最新浏览器实查见[58页清单](验收清单_用户端58页功能与视觉_20260911.md)。
## 已确认范围
- 2026-09-12图26“我的记录”:新增`/records`独立页,并行聚合本人供气订单和报修工单,显示本月真实数量、六类入口、最近记录与类型筛选。设备操作、告警记录缺首期接口,点击明确“暂未开放”;发票记录明确属于二期,点击显示“即将开放”。内置浏览器从个人中心实际点入,读取远程数据并完成筛选和两类提示验证。图26仍为部分实现,不判严格1:1验收通过。
- 2026-09-11图19支付确认:新增`/payment/:business/:identity`,商城和气瓶订单的应付金额、订单号、商品快照、钱包余额和可支付动作均重读服务端。余额支付接入六位支付密码、二次确认和幂等号;气瓶余额支付与商城支付记录补齐原子交易事实。优惠券缺接口,页面显示“暂未开放”并可查看原因;微信/支付宝读取服务端商户配置就绪状态,未配置时明确显示“暂未开放”并禁用。钢瓶场景使用真实位图,费用明细区分气费、可退押金和配送费。定向功能测试、8组多尺寸视觉、Flutter analyze/Web构建通过。内置浏览器使用远程真实已取消订单展示真实金额、禁用状态和优惠券弹层;当前账号无待付款订单,未提交远程扣款。见[支付确认日志](开发日志_订单支付确认_20260911.md)。
- 2026-09-11图28、39、40钱包批次:图28提现和银行卡从占位改为真实路由;图39接入服务端可提现余额、到账卡、提现记录、支付密码、幂等申请和二次确认;图40接入脱敏银行卡列表、绑定、默认到账卡和安全解绑。API新增`POST wallet/banks/:identity/default`并为银行卡增加默认标记。Flutter全量170项、analyze、Web构建及Go全量测试/vet/build通过;内置浏览器只读检查真实远程余额和银行卡,未提交资金或银行卡写操作。押金、优惠券、待退款和外部渠道回执仍缺,三页均未通过严格1:1。见[钱包提现与银行卡日志](开发日志_钱包提现与银行卡_20260911.md)。
- 2026-09-11图03第二轮:按最新原稿重新压缩首页服务卡、设备卡、四宫格、安全记录和公告列表;公告展示服务端真实摘要与创建日期,最多显示两条并进入全文。查看设备、分组控制、一键报修已接现有真实路由;扫码、蓝牙、安全告警和气瓶详情点击后明确提示首期“暂未开放”。游客服务归属保持设计卡片并登录回跳。8组多宽度/文字缩放、161项Flutter测试、analyze和Web Release构建通过;内置浏览器读取远程公告并验证未开放弹层。设备遥测接口缺失,图03仍为部分实现,不判严格1:1通过。
- 2026-09-11图05第二轮:按原稿重校顶部更多菜单、故障图标、描述框、三格照片、联系地址、橙色燃气泄漏提示和固定底部操作。更多菜单可查看本人报修工单或打开报修说明;紧急电话只在用户明确点击后调用系统拨号器,失败提示手动拨打119。视觉夹具保持真实空照片状态0/3,不伪造原稿中的阀门照片。8组多宽度/文字缩放截图、12项报修定向测试及162项Flutter全量测试通过,analyze与Web Release构建通过;内置浏览器验证必填提示、报修说明和本人报修工单跳转。原生语音、拍照时间与定位仍需真机验收,因此图05保持部分实现。
- 2026-09-11本轮全量Flutter回归160项通过。设备分组和登录短信状态改动后同时完成 `flutter analyze`、Web构建、Go全量测试、`go vet ./...` 和API构建。内置浏览器确认设备空态、分组闭环、登录成功和未开放提示;不以测试全绿替代58页功能与视觉验收。
- 2026-09-11图01再次按保持事实源宽高比的390×844官方并排图复核:共同区域已对齐品牌、标签、输入、按钮、记住状态、忘记密码和协议;修复视觉夹具按钮中文方框。后端返回Mock短信`not_sent`时不再显示虚假倒计时,改为“短信验证码暂未开放”。内置浏览器真实密码登录成功。注册入口按明确要求保留,真实短信未配置,图01保持blocked。
- 2026-09-11图03恢复未开放设备区域结构:新增device_status_placeholder.dart,首页保留四个指标名称并展示不可查询状态;调整说明与安全/气瓶入口可见状态。四种宽度×1.3文字测试通过,Flutter analyze通过。不填写原稿模拟遥测,不把占位状态计作设备能力完成。原始批次A1仍未验收通过,后续继续补一级页面差异。
- 本轮浏览器验证:新版Web首页的扫码添加、蓝牙连接、分组控制显示“暂未开放”;点击扫码添加显示“该功能暂未开放,目前无法使用。”。一键报修不显示未开放标记。此为状态提示验证,不改变这些功能尚未实现的结论。
- 2026-09-11未开放提示规则接入:feature_entry.dart新增显式UnavailableStage,默认首期“暂未开放”,只有传入明确二期状态才显示“即将开放”和后续版本说明;无处理回调的图标入口直接显示状态,个人中心_pending列表显示“暂未开放”。不因缺接口推定二期。两项widget测试覆盖默认状态、二期说明和已开放回调,均通过;这不代表缺失业务功能已完成。其余自定义入口和设置文案仍需继续统一。
- 2026-09-11商城图11继续视觉调整:shop_page.dart的商品卡片改为图片/名称入口、16号价格、右下角收藏,去掉稿外购买按钮(购买仍经详情进入结算),明确卡片边框和间距。Flutter analyze和Web构建通过,内置浏览器390×844核对;原稿服务栏、真实素材、规格和销量等未完成,仍为部分实现。上传图片跨域缓存问题已修复,商城/详情已验证可显示,详见商品图片日志;购物车显示仍待本轮完整验收。
- 2026-09-11商品图片最终复核:内置浏览器中商城卡片和商品详情均已显示“示例配送商品 10”的远程上传图片。公开接口确认该商品有非空 `image_url`,其余当前商品的 `image_url` 为空,所以显示“暂无商品图片”;数据库和App读取链路正常,剩余差异是后台尚未为每个商品配置正式素材。
- 按首期补齐要求新增平台后台商品图片上传预览控件及专用上传/公开读取接口,Go测试和后台类型检查通过;真实绑定与App显示尚待内置浏览器联调,见[商品图片开发日志](开发日志_商城商品图片上传_20260911.md)。
- 2026-09-11充值页面接入协议版本确认,确认失败不创建充值,契约测试通过;真实记录联调仍待完成,见[充值协议接入](操作日志_用户端APP_充值协议接入_20260911.md)。
- 2026-09-11阅读确认接口新增客户端版本匹配及幂等内容核对,用户逻辑测试通过;充值留痕尚待接入,见[协议版本确认](操作日志_用户端APP_协议版本确认_20260911.md)。
- 2026-09-11补充充值配置后端边界测试,覆盖未配置渠道、协议缺失、配置路径与鉴权失败,见[充值配置边界测试](操作日志_用户端APP_充值配置边界测试_20260911.md)。
- 2026-09-11补齐充值重试1112、查询异常及账号切换分支验证:仅明确不存在允许原请求重发,其余不发单,流程测试通过。
- 2026-09-11充值原订单重试增加入账前置查询,已到账不再次拉起支付;见[充值重试入账检查](操作日志_用户端APP_充值重试入账检查_20260911.md)。
- 2026-09-11充值页320/390窄屏及1.3倍字体无溢出测试通过,全量Flutter135项通过;视觉1:1仍未通过,见[充值窄屏回归](操作日志_用户端APP_充值窄屏回归_20260911.md)。
- 2026-09-11对照图38补充自定义选项、清空金额及确认按钮金额,交互测试通过;浏览器旧构建路由问题已复现,完整验收未完成,见[充值金额控件](操作日志_用户端APP_充值金额控件_20260911.md)。
- 2026-09-11修复充值已到账后余额刷新失败被误报未确认,回归测试通过,见[充值到账提示修复](操作日志_用户端APP_充值到账提示修复_20260911.md)。
- 2026-09-11充值表单已接入路由及钱包入口,缺协议禁用支付、待确认订单查询测试通过;尚未部署和视觉核对,图38仍不计验收,见[充值表单接入](操作日志_用户端APP_充值表单接入_20260911.md)。
- 2026-09-11补充充值待确认请求安全存储和恢复流程,3项测试通过;尚待页面接入,见[充值请求恢复](操作日志_用户端APP_充值请求恢复_20260911.md)。
- 2026-09-11接入钱包充值记录页,支持分页、去重、刷新和断网恢复,交互测试及静态检查通过;充值表单与图38视觉验收仍待完成,见[充值记录页面](操作日志_用户端APP_充值记录页面_20260911.md)。
- 2026-09-11补充充值渠道配置查询及客户端严格金额、协议和到账状态校验,新增3项测试通过;图38界面仍待接入,见[充值配置校验](操作日志_用户端APP_充值配置校验_20260911.md)。
- 2026-09-11补充充值结果、记录及请求号恢复查询,修复同请求号变更金额或渠道的冲突;远程独立事务验证一次入账并整体回滚。图38页面和渠道交互仍未完成,见[充值接口记录](操作日志_用户端APP_充值查询与幂等_20260911.md)。
- 2026-09-11修复登录输入连接切换及重复点击清空密码;新构建浏览器已验证遮蔽输入直接登录回到钱包,未新增此前的Web输入空值异常。详见[登录输入记录](操作日志_用户端APP_登录输入连接_20260911.md)。
- 设置支付密码已接通首次设置、旧密码修改与验证码找回,增加并发更新保护、一次性验证码和五次输错锁定;远程独立夹具回滚验证通过。真实短信供应商仍未配置,首次设置和找回仅完成Mock联调,不计真实短信可用。见[支付密码日志](操作日志_用户端APP_支付密码_20260908.md)。
- 图21已接入商城及气瓶订单详情。气瓶分支读取真实状态历史、配送费、气站、配送员姓名、成功支付记录和本人合同正文;待签收支持本人确认、事务释放占用及幂等重试。常规宽度时间轴按原图横向排列;配送轨迹、押金、受控联系、完整合同及严格视觉仍待补,图21只计部分实现。见 [订单详情日志](操作日志_用户端APP_订单详情_20260908.md)、[供气详情日志](操作日志_用户端APP_供气订单详情_20260908.md)。
- 图15已新增受保护收藏列表、真实分类数量、取消收藏、管理批量取消及从收藏加购;商城和详情收藏按钮、个人中心入口均接通。下架商品保留但不可加购,服务端版本防止过期请求复活收藏。远程此前仅定向新增ec_favorite表及注释;原图中的月销和商品素材仍有差异,详见 [收藏日志](操作日志_用户端APP_商品收藏_20260908.md)。
- 图13购物车已有真实条目、数量、单选全选、失效提示、管理删除,以及图12加入购物车和多商品结算。条件版本更新避免重试累加;订单事务消费对应购物车行,失败整体回滚。仍缺优惠、押金、配送承诺、服务保障配置和严格视觉还原。见 [购物车日志](操作日志_用户端APP_购物车_20260908.md)。
- 2026-09-11图13按最新原稿补齐服务归属配送卡、商品规格/押金状态、服务保障区和固定结算栏层级;真实归属、金额、数量、推荐及后台封面继续来自接口。押金、配送时效和保障规则缺服务端能力,入口显示“暂未开放”,严格1:1仍未通过。见 [视觉与状态日志](开发日志_购物车视觉与首期状态_20260911.md)。
- 图13推荐区、图15“猜你喜欢”入口已接入真实在售商品分页、换一换、详情和条件加购;排除本人购物车,收藏场景另排除本人收藏,同类优先。窄屏大字体购物车金额单独成行,详情返回重读购物车。此轮无数据库迁移,见 [推荐商品日志](操作日志_用户端APP_推荐商品_20260908.md)。
- 2026-09-11图15按最新原稿去除多余顶部按钮,压缩筛选与商品卡,使推荐入口进入首屏;规格缺失和月销量缺口分别显示“规格暂未配置”“月售暂未开放”。内置浏览器验证真实收藏、分类筛选、后台封面及推荐弹层。正式商品素材和销量接口未补齐,仍为部分实现。见 [收藏视觉日志](开发日志_我的收藏视觉与真实推荐_20260911.md)。
- 2026-09-08图05更新编号步骤、故障表单、三格照片和可操作的第一步联系地址预览;当时64项用户端测试及8组该页视觉检查通过。其后语音输入已接入,真实设备识别、真实采集信息、紧急电话和精细样式仍待验收,详见 [视觉对齐日志](操作日志_用户端APP_报修视觉对齐_20260908.md)、[语音输入日志](操作日志_用户端APP_报修语音输入_20260908.md)。
- 图05已有三步故障/联系地址/确认提交表单,故障类型与联系人快照落库,预约选填,重复提交返回首次工单。照片选择、预览、上传和工单关联已接入;报修草稿已按账户及API环境持久化,恢复保留原请求号,成功提交后清理。语音已接入并有自动回归,真实设备识别及采集定位/拍摄时间未验收。远程此前仅新增cs_ticket三个字段,照片复用既有证据表,草稿无数据库变更。见 [报修提交日志](操作日志_用户端APP_报修提交_20260907.md)、[照片日志](操作日志_用户端APP_报修照片_20260907.md)、[草稿日志](操作日志_用户端APP_报修草稿_20260907.md)。
- 工单列表可打开独立详情,读取真实地址、预约、处理结果及本人提交照片;取消与确认完成均需用户确认,服务端校验所有权和状态并支持重复操作。图42尚缺工程师联系、完整进度、改期和补充资料,仍为部分实现。见 [工单操作日志](操作日志_用户端APP_工单操作_20260907.md)。
- 商城订单取消、确认收货已接入页面,后端新增动作发布及幂等边界保护;详情见 [订单操作日志](操作日志_用户端APP_订单操作_20260907.md)。图20仍为部分实现。
- 2026-09-11图20二次实现:订单中心改为设计稿三标签和紧凑卡片,补订单号/商品搜索、固定状态筛选、气站与规格、气瓶取消入口;后端列表补气站名称,气瓶待付款状态与可取消动作统一。商城新订单会把后台商品封面固化到成交快照,历史空快照不伪造补图。再次购买、申请售后和电子发票按既定后续阶段保留入口并提示“即将开放”。165项Flutter测试、Go全量测试/vet/build、160组布局图与内置浏览器真实远程数据走查通过;气瓶商品图片模型及原稿三笔同状态数据仍缺,图20继续记为部分实现。见 [订单中心日志](开发日志_订单中心视觉与气瓶操作_20260911.md)。
- 2026-09-11图25二次实现:个人中心读取真实实名认证和紧急联系人数量,压缩资产、家庭及常用功能布局,使全部设计入口在390×844首屏可见;重复维修/退出按钮移除,原功能保留在报修入口和设置页。当前远程账号头像为空、联系人0人,页面如实显示首字头像和0人;头像拍照/相册上传入口已在内置浏览器打开。未接入功能保留“暂未开放”标签与弹层。Flutter全量166项测试、160项视觉fixture及Web release构建通过,图25仍因资产和消息等业务缺失保持部分实现。见 [个人中心日志](开发日志_个人中心视觉与真实资料_20260911.md)。
- 后续功能入口不隐藏,点击解释当前未开放;设备控制与遥测仍归 B,不模拟在线、关阀或电量。
- 37 邀请注册补入 A2。现有 /register、ClientRecord 和旧 API 均保留。
- 头像与昵称编辑已在浏览器通过实际选图、上传、保存、受保护图片读取验证;测试资料已恢复。2026-09-08 Android Debug APK构建通过,之前Maven下载与缓存阻塞已解除;原生相机、语音和iOS设备仍未验收。详情见 [纠偏日志](操作日志_用户端APP_头像与视觉纠偏_20260907.md)、[语音输入日志](操作日志_用户端APP_报修语音输入_20260908.md)。
- 使用 backend/api/etc/heqi_dev.yaml 中既有远程 PostgreSQL、Redis。本地仅运行 API 与 Flutter Web;地址管理已执行三个字段的定向新增迁移,未执行全库迁移、清库或 mock-data。
- 远程只读检查已确认基础角色、管理员、指定测试账号、上架商品存在,Redis PING 通过。
## 逐页状态
状态针对最新设计的独立页面;“未开始”不表示旧仓库没有同类基础接口。所有接口相对于 /heqi/client/v1/user;测试位于 apps/user_app/test,视觉测试统一为 tool/a1_visual_test.dart。未落地的路由和接口不编造为已存在。
| 设计图 | 批次 | 状态 | 已有路由/入口 | 对应接口 | 测试 | 视觉截图 |
| --- | --- | --- | --- | --- | --- | --- |
| 01-登录页.png | A1 | 部分实现 | /login;密码登录、协议、忘记密码、注册入口及安全回跳;短信未发送明确暂未开放 | POST auth/login、auth/verification-code、auth/reset-password;GET public/contents | login_page_test.dart 9项、8组多尺寸视觉、内置浏览器真实密码登录 | [390×844](视觉验收/A1/01_390_1.0.png)、[官方对照](视觉验收/A1/01_并排对照.png)、[浏览器截图](视觉验收/01-登录页_实现_20260911.jpg);注册入口和真实短信使整页保持blocked |
| 02-1-安全案例.png | D | 未开始 | 尚未建立独立页 | 待该批次核对 | 未建立该页验收 | 未生成 |
| 02-2-法律法规.png | D | 未开始 | 尚未建立独立页 | 待该批次核对 | 未建立该页验收 | 未生成 |
| 02-3-气价信息.png | D | 未开始 | 尚未建立独立页 | 待该批次核对 | 未建立该页验收 | 未生成 |
| 02-智能角阀功能介绍.png | D | 未开始 | 尚未建立独立页 | 待该批次核对 | 未建立该页验收 | 未生成 |
| 03-首页.png | A1 | 部分实现 | /home | GET public/contents、service-relation | primary_pages_test.dart、service_relation_card_test.dart | [390×844](视觉验收/A1/03_390_1.0.png)、[对照](视觉验收/A1/03_并排对照.png) |
| 04-智能角阀控制.png | B | 未开始 | 尚未建立独立页 | 待该批次核对 | 未建立该页验收 | 未生成 |
| 05-一键报修.png | B | 部分实现 | /repair | POST tickets;GET addresses | repair_page_test.dart、ticket_create_test.go | [390×844](视觉验收/A1/05_390_1.0.png),未通过严格1:1 |
| 06-1-扫码添加确认.png | B | 未开始 | 尚未建立独立页 | 待该批次核对 | 未建立该页验收 | 未生成 |
| 06-2-蓝牙连接设备.png | B | 未开始 | 尚未建立独立页 | 待该批次核对 | 未建立该页验收 | 未生成 |
| 06-3-手动输入设备码.png | B | 未开始 | 尚未建立独立页 | 待该批次核对 | 未建立该页验收 | 未生成 |
| 07-气瓶基本信息.png | B | 未开始 | 尚未建立独立页 | 待该批次核对 | 未建立该页验收 | 未生成 |
| 08-设备分组控制.png | B | 部分实现 | `/device-groups`;分组新增、改名、删除、设备归组真实可用;群控与安全检查暂未开放 | 内置浏览器427宽真实新建、归组、改名、删除闭环 | Go权限/幂等与Flutter交互、大字体测试通过;同状态视觉验收受真实数据限制 | [并排对照](视觉验收/08-设备分组_并排对照_20260911.jpg)、[日志](开发日志_设备分组_20260911.md) |
| 09-安全告警与报警器.png | B | 未开始 | 尚未建立独立页 | 待该批次核对 | 未建立该页验收 | 未生成 |
| 10-紧急联系人.png | B | 部分实现 | 本人联系人资料新增、编辑、归档及五人上限;授权和通知未开放 | 内置浏览器390宽真实资料操作,布局仍有差异 | API边界与前端重试测试通过,未完成全页验收 | 开发日志_紧急联系人_20260911.md |
| 11-燃气商城.png | A1 | 部分实现 | /shop | GET public/products;POST shop/orders | primary_pages_test.dart、primary_repository_test.dart | [390×844](视觉验收/A1/11_390_1.0.png)、[对照](视觉验收/A1/11_并排对照.png) |
| 12-商品详情.png | C | 部分实现:后台商品图、预览、价格库存、数量、分享、收藏、加购结算、服务归属及设计分组;规格/参数读取后台配置,配送预约与保障标准显示“暂未开放” | /products/:identity | GET public/products/:identity、GET service-relation;既有商品图片与属性后台资源 | product_detail_page_test.dart、product_detail_test.go、router_test.dart;Flutter全量171项、视觉8视口与内置浏览器真实商品核对 | [390×844](视觉验收/A1/12_390_1.0.png)、[并排图](视觉验收/A1/12_并排对照.png)、[日志](开发日志_商品详情视觉与后台数据_20260911.md) |
| 13-购物车.png | C | 部分实现 | /cart、/cart/checkout;详情加入购物车、推荐区 | GET shop/cart、GET/PUT shop/cart/items/:identity;GET shop/recommendations;POST shop/orders | cart_page_test.dart、cart_test.dart、cart_test.go、product_recommendations_test.dart、recommendation_test.go | [截图](视觉验收/A1/13_390_1.0.png)、[对照](视觉验收/A1/13_并排对照.png),未通过严格1:1 |
| 14-提交订单.png | A2 | 部分实现:地址、气站与商品、数量、费用、备注、钱包余额和下单后支付衔接;预约/优惠/押金显示“暂未开放”,二期发票显示“即将开放” | /checkout/:identity、/cart/checkout、/payment/shop/:identity | GET addresses、service-relation、wallet;POST shop/orders、cart/checkout(可选 expected_payable_amount) | checkout_test.go、shop_address_selection_test.dart、cart_page_test.dart;Flutter全量171项、视觉8视口及内置浏览器真实数据核对 | [390×844](视觉验收/A1/14_390_1.0.png)、[并排图](视觉验收/A1/14_并排对照.png)、[日志](开发日志_提交订单视觉与支付衔接_20260911.md) |
| 15-我的收藏.png | C | 部分实现 | /favorites;商城/详情收藏、个人中心入口、推荐弹层 | GET shop/favorites;GET/PUT shop/favorites/items/:identity;GET shop/recommendations | favorite_test.go、favorite_test.dart、favorites_page_test.dart、product_recommendations_test.dart | [截图](视觉验收/A1/15_390_1.0.png)、[对照](视觉验收/A1/15_并排对照.png),未通过严格1:1 |
| 16-押金管理.png | A2 | 部分实现:真实汇总、状态筛选、押金明细、规则查看和管理后台;远程当前为空数据 | /deposits | GET deposits;后台 deposit_policy/deposit_record | deposit_page_test.dart、8组视觉变体、Go路由/逻辑测试、内置浏览器真实空态 | [并排图](视觉验收/A1/16_并排对照.png)、[日志](开发日志_押金管理首期底座与真实空态_20260911.md);退瓶、验收、扣减、退款流水未完成 |
| 17-退瓶退押金.png | A2 | 已实现首期闭环:选择本人可退气瓶、上门地址、预约时段、瓶况确认、二次确认、取消、后台回收/验收/扣减/余额入账 | /deposits/return?deposit=:identity | POST/GET/cancel deposit-returns;后台 confirm-pickup/inspect/complete-refund | deposit_return_page_test.dart、预约边界与路由测试、8组视觉变体;真实账号无可退气瓶故未提交业务记录 | [并排图](视觉验收/A1/17_并排对照.png)、[日志](开发日志_退瓶退押金首期闭环_20260911.md);安检最新结论接口仍缺,页面标“暂未开放” |
| 18-气瓶下单.png | C | 已实现首期闭环 | /gas/order;首页“气瓶下单”入口 | GET /gas/order-options;POST /gas/orders;支付成功转正式押金 | gas_order_create_page_test.dart、预约边界、路由测试、8组视觉变体 | [并排图](视觉验收/A1/18_并排对照.png)、[日志](开发日志_气瓶下单首期闭环_20260911.md);远程账号押金规则未配置,真实页明确显示“押金规则暂未配置”并禁止下单 |
| 19-支付确认.png | A2 | 部分实现 | /payment/:business/:identity;余额/微信/支付宝、渠道就绪状态、六位支付密码、二次确认;优惠券暂未开放 | GET shop/gas orders/:identity、wallet、wallet/recharge-options;POST shop/gas orders/:identity/pay | payment_confirmation_page_test.dart、wallet_order_payment_test.go、8组视觉及内置浏览器真实取消订单只读走查 | [390×844](视觉验收/A1/19_390_1.0.png)、[对照](视觉验收/A1/19_并排对照.png);真实待付订单、外部支付页和回调仍待验收 |
| 20-订单中心.png | A1 | 部分实现 | /orders;三业务标签、搜索、状态筛选、真实字段、详情与服务端允许动作;后续功能明确提示 | GET shop/orders、gas/orders、refunds、tickets;POST gas/orders/:identity/cancel;既有支付/退款/商城取消与收货 | orders_page_test.dart 6项、gas_order_list_test.go、checkout_test.go;内置浏览器远程列表/搜索/详情/二期提示 | [气瓶390×844](视觉验收/A1/20_390_1.0.png)、[气瓶对照](视觉验收/A1/20_并排对照.png)、[商城对照](视觉验收/A1/20-shop_并排对照.png);气瓶图片模型和同状态数据仍缺,未通过严格1:1 |
| 21-订单详情.png | A2 | 部分实现:配送状态、地址、气站商品、费用、支付方式、合同、服务操作及本人签收;首期配送轨迹/受控联系/押金显示“暂未开放”,二期售后显示“即将开放” | /gas/orders/:identity、/shop/orders/:identity | GET gas/orders/:identity、GET gas/contracts/:identity、POST gas/orders/:identity/confirm-receipt | gas_detail_test.go、gas_order_detail_test.dart、shop_order_detail_test.dart;Flutter全量171项、视觉8视口与内置浏览器真实订单核对 | [商城对照](视觉验收/A1/21_并排对照.png)、[供气并排图](视觉验收/A1/21-gas_并排对照.png)、[日志](开发日志_供气订单详情视觉与功能状态_20260911.md) |
| 22-配送详情.png | A2 | 部分实现:本人订单、配送状态、预约、配送员、有效资质、气站/配送点、商品、地址、脱敏联系人和安全交付提示;车辆及受控联系明确“暂未开放” | /gas/orders/:identity/delivery | GET gas/orders/:identity/delivery | delivery_detail_test.go、delivery_detail_page_test.dart、8组视觉变体;内置浏览器真实订单核对 | [并排图](视觉验收/A1/22_并排对照.png)、[日志](开发日志_配送详情与隐私化轨迹_20260912.md);配送车辆后台配置、真实员工头像资源、受控电话/消息仍缺 |
| 23-配送轨迹.png | A2 | 部分实现:本人订单鉴权、约百米隐私化坐标、地图路线、履约节点、更新时间、刷新、配送员与未开放能力提示 | /gas/orders/:identity/delivery/track | GET gas/orders/:identity/delivery/track;复用配送端轨迹上报 | 坐标约化/状态节点Go测试、delivery_track_page_test.dart、8组视觉变体;内置浏览器从22页进入并刷新 | [390×844](视觉验收/A1/23_390_1.0.png)、[并排图](视觉验收/A1/23_并排对照.png)、[日志](开发日志_配送详情与隐私化轨迹_20260912.md);远程样例仅1个轨迹点,受控电话和配送问题上报仍缺 |
| 24-电子发票.png | C | 部分实现:已完成订单保留入口、读取本人真实订单、展示订单号/商品/商品金额/押金排除说明和完整二期表单结构;所有申请动作明确“即将开放”且不写入 | /invoice/:business/:identity;订单列表和详情入口 | 复用GET gas/shop orders/:identity;未新增伪开票接口 | invoice_preview_page_test.dart、订单入口回归、8组视觉变体;内置浏览器从真实已完成订单进入并点击提交提示 | [390×844](视觉验收/A1/24_390_1.0.png)、[并排图](视觉验收/A1/24_并排对照.png)、[日志](开发日志_电子发票二期入口_20260912.md);开票、抬头、税务回执、预览下载均属于二期 |
| 25-个人中心.png | A1 | 部分实现 | /me;真实头像入口、实名认证、联系人数量、资产/服务/家庭/常用入口及缺项提示 | GET auth/profile、auth/avatar、wallet、emergency-contacts;既有订单/设备/合同/地址/收藏/报修动作 | profile_edit_page_test.dart、client_models_test.dart、160项多尺寸视觉;内置浏览器真实资料/提示/头像菜单 | [390×844](视觉验收/A1/25_390_1.0.png)、[对照](视觉验收/A1/25_并排对照.png);远程为空头像和0联系人,押金/券/消息等仍缺 |
| 26-我的记录.png | D | 部分实现 | /records;供气和报修聚合、筛选及详情 | 本人订单与工单查询 | 页面测试、内置浏览器检查 | 设备与告警记录待补,严格1:1待验收 |
| 27-用气统计.png | D | 部分实现 | /usage;设备、周期、图表、明细及后台计量管理 | GET user/usage-statistics;平台dev_usage_stat | 内置浏览器后台列表/新建表单、App无设备空态;后台类型检查通过 | 历史日期、安全趋势、真实计量闭环及严格1:1待验收 |
| 28-我的钱包.png | A2 | 部分实现 | /wallet、/records/wallet、/wallet/recharge、/wallet/withdraw、/wallet/banks | GET wallet、wallet/bills;充值、本人银行卡和提现接口 | 金额、会话、分页、隐私、银行卡及提现二次确认测试;内置浏览器真实只读检查 | [对照](视觉验收/A1/28_并排对照.png)、[日志](开发日志_钱包提现与银行卡_20260911.md);押金/券/待退款及严格1:1待补 |
| 29-地址管理.png | A2 | 部分实现:增删改与默认切换可用,范围判定/定位待补 | /addresses、/addresses?select=1 | GET/POST addresses;PUT/DELETE addresses/:identity;POST addresses/:identity/default | addresses_page_test.dart、address_test.go、真实远程读写恢复 | [390×844](视觉验收/A1/29_390_1.0.png)、[日志](操作日志_用户端APP_地址管理_20260907.md) |
| 30-消息中心.png | D | 部分实现 | /messages;四类总览、筛选、已读及真实对象跳转 | GET messages、PUT messages/read;订单、工单、已发布公告事实聚合 | 页面2项、8组视觉;内置浏览器远程读取、单条已读、订单详情与筛选 | [对照](视觉验收/A1/30_并排对照.png);安全事件、通知偏好、不可变历史消息及严格1:1待补 |
| 31-设置.png | D | 部分实现 | /settings、/settings/password、/settings/payment-password | 登录及支付密码、已发布协议、真实版本、图片缓存及退出 | 改密版本保护、原子验证码、五次锁定、远程回滚及页面布局测试 | [对照](视觉验收/A1/31_并排对照.png)、[支付密码日志](操作日志_用户端APP_支付密码_20260908.md),真实短信、通知、权限、注销及严格1:1待补 |
| 32-供气合同.png | A2 | 部分实现 | /records/contracts;个人中心入口与深链 | 本人列表、正文、受控PDF、状态历史;搜索筛选;申请变更、气站答复、取消/确认 | 列表/附件/历史/申请权限及幂等测试;远程申请答复确认回滚;Web下载哈希一致;8组布局 | [对照](视觉验收/A1/32_并排对照.png)、[申请日志](操作日志_用户端APP_合同申请与个人中心复核_20260908.md),原生保存、签署、地址快照、续签提醒及严格1:1待补 |
| 33-家庭成员与设备共享.png | D | 部分实现:独立家庭页、手机号邀请、受邀账号接受/拒绝、待确认撤回、成员移除、按设备查看/告警/控制授权及不可变审计;紧急联系人不自动获权 | /family;个人中心入口 | GET /family、POST/DELETE /family-members、PUT device-permissions、GET/POST family-invitations | Go逻辑/路由/CLI测试,Flutter页面2项及8组宽度/字体视觉测试;远程邀请和撤回真实联调;内置浏览器可见操作 | [并排图](视觉验收/A1/33_并排对照.png)、[日志](开发日志_家庭成员与设备共享首期闭环_20260913.md);远程账号无设备且无第二账号,接受和真实设备权限执行未做双账号联调,成员头像资源也未接入,故暂不判完整闭环或严格1:1 |
| 34-我的设备.png | B | 部分实现 | 本人已分类设备列表、搜索、分类、分组和档案;遥测、扫码及控制暂未开放 | 内置浏览器427宽后台启用到App显示、归组、删组回退联调 | 查询隔离、分类、分组与大字体测试通过;源图为5设备状态,当前远程空状态未判1:1 | [并排对照](视觉验收/34-我的设备_并排对照_20260911.jpg)、[日志](开发日志_我的设备列表_20260911.md) |
| 35-安全记录详情.png | B | 未开始 | 尚未建立独立页 | 待该批次核对 | 未建立该页验收 | 未生成 |
| 36-申请售后.png | C | 未开始 | 尚未建立独立页 | 待该批次核对 | 未建立该页验收 | 未生成 |
| 37-邀请注册.png | A2 | 未开始 | /register(旧基础) | 待该批次核对 | 未建立该页验收 | 未生成 |
| 38-余额充值.png | A2 | 部分实现,真实支付不可用 | /wallet/recharge、/wallet/recharge-records | 充值配置、创建、记录及请求恢复;协议确认代码 | 金额、恢复、页面及配置测试 | 浏览器已实查,缺卡片/插图且渠道不可用,未通过1:1 |
| 39-余额提现.png | A2 | 部分实现 | /wallet/withdraw;余额、到账卡、金额、支付密码、记录和二次确认 | GET/POST wallet/withdrawals;GET wallet/banks | wallet_account_test.dart、withdrawal_page_test.dart、8组多尺寸视觉;浏览器只读检查 | [对照](视觉验收/A1/39_并排对照.png);外部到账回执及严格1:1待补 |
| 40-银行卡管理.png | A2 | 部分实现 | /wallet/banks;脱敏列表、绑定、默认卡、解绑 | GET/POST/DELETE wallet/banks;POST wallet/banks/:identity/default | 接口契约、路由、8组多尺寸视觉;浏览器打开添加表单 | [对照](视觉验收/A1/40_并排对照.png);银行验证回执和短信供应商待补 |
| 41-个人资料.png | A2 提前修复 | 部分实现 | /profile/edit;点击个人中心头像或资料行 | GET/PUT auth/profile、GET auth/avatar、POST /upload/avatar、GET service-relation/addresses | profile_edit_page_test.dart、avatar_upload_test.dart、profile_test.go、avatar_test.go | [390×844](视觉验收/A1/41_390_1.0.png)、[对照](视觉验收/A1/41_并排对照.png) |
| 42-报修工单详情.png | A2 | 部分实现 | /tickets/:identity;订单内报修标签 | GET tickets、POST tickets/:identity/cancel、confirm | ticket_detail_page_test.dart、ticket_actions_test.go | [390×844](视觉验收/A1/42_390_1.0.png),未通过严格1:1 |
| 43-1-安全宣传.png | D | 未开始 | 尚未建立独立页 | 待该批次核对 | 未建立该页验收 | 未生成 |
| 43-2-安全视频.png | D | 未开始 | 尚未建立独立页 | 待该批次核对 | 未建立该页验收 | 未生成 |
| 43-3-法律法规.png | D | 未开始 | 尚未建立独立页 | 待该批次核对 | 未建立该页验收 | 未生成 |
| 43-4-平台公告.png | D | 部分实现 | `/contents/:identity`;读取本人可见的已发布公告正文 | GET public/contents/:identity;按发布状态、类型和identity读取 | content_detail_test.go、safety_contents_page_test.dart、内置浏览器真实公告正文 | 尚缺摘要、已读、时间、图片与严格1:1;见开发日志_安全内容中心_20260911.md |
| 43-安全内容中心.png | D | 部分实现 | `/contents`;公告、安全宣传、法律法规筛选与标题搜索,视频暂未开放 | GET public/contents、public/contents/:identity | 内容权限、下架、搜索与页面测试 | 内置浏览器真实公告列表;尚缺分页、运营内容和严格1:1 |
| 44-自动关阀设置.png | B | 未开始 | 尚未建立独立页 | 待该批次核对 | 未建立该页验收 | 未生成 |
| 45-电子保修卡.png | D | 未开始 | 尚未建立独立页 | 待该批次核对 | 未建立该页验收 | 未生成 |
| 46-设备健康月报.png | D | 未开始 | 尚未建立独立页 | 待该批次核对 | 未建立该页验收 | 未生成 |
| 47-安全知识考试.png | D | 未开始 | 尚未建立独立页 | 待该批次核对 | 未建立该页验收 | 未生成 |
| 48-服务评价.png | C | 未开始 | 尚未建立独立页 | 待该批次核对 | 未建立该页验收 | 未生成 |
| 49-预约安全巡检.png | C | 未开始 | 尚未建立独立页 | 待该批次核对 | 未建立该页验收 | 未生成 |
共58张:34张部分实现、22张尚无对应完整页面、2张已完成首期功能闭环、0张严格验收通过。历史A1五页记录仅代表当时批次,不代替当前逐页状态。
## 本批次验证
- 改动前:用户端 analyze 无问题、33 项测试通过;Go 全量测试通过。
- 改动后:用户端 analyze 无问题、44 项测试通过;40 组页面截图和滚动溢出检查通过(320/360/390/430 × 844,文本 1.0/1.3)。Web Release 构建通过。
- 共享包 analyze 与 3 项测试通过;服务端 App analyze 与 21 项测试通过。
- Go test ./...、go vet ./...、go build 通过;新增协议重复确认测试定向通过。
- 平台 contract:check 通过 48 个资源;未修改模型、注册路由、后台资源或权限菜单,无需生成契约变更。
- 远程真实联调:密码登录,公开内容、分页商品、用户资料、钱包、地址、商城/供气订单、服务归属全部返回 code=0。
- Mock 商品下单两次复用同一 request_no,只生成同一订单且只扣库存一次;取消后库存恢复。保留已取消订单 identity:01a07bc0-6237-7ec2-8cbc-1c05f16ad10b。未调用支付、退款或资金删除。
- 浏览器实测:游客首页与未开放弹窗、受保护订单登录回跳、本人订单、脱敏个人资料、钱包摘要、商品搜索、未记住会话刷新失效及重复进入报修通过。
## 视觉结论与差异
见 [A1 视觉验收记录](视觉验收/A1/视觉验收记录_A1.md)。截图生成和不溢出通过不等于设计一致性通过。
设计图尺寸比例并不完全相同,对照左侧保持原图等比缩放,右侧固定 390×844;不是强行拉伸后的像素差分。Fixture 仅在 test/tool 中,未进入运行代码。远程商品缺图、无已发布 agreement,不能用设计稿的人像、金额、宣传图或协议正文充当真实数据。
## 已知限制及下一步
- 已按并排核对将验证码发送改为独立按钮、订单改为三类主 Tab 并保留退款入口、个人中心资产区收敛为三列。商家图片、原品牌资产和宣传位当前没有对应可用素材,原图完整设备/配送状态也没有同状态数据,因此严格视觉一致性仍未标“已验收”。
- 商城/订单虽有分页 HTTP 契约,兼容仓储暂时顺序读完各页再筛选,大数据量下需在 A2 改为逐页加载与服务端筛选。
- 页面内幂等号在结果未知时保留,跨页面销毁/应用重启的持久化重试归 A2;当前旧地址接口没有 request_no,不把新增地址声称为完整幂等闭环。
- allowed_actions 由服务端生成,实际写入仍重新校验状态、归属、库存、支付与退款规则;完整详情与细粒度错误码归 A2。
- 远程没有已发布协议,真实协议版本留痕用 SQL Mock 验证,未在远程伪造运营内容。正式投用前由平台发布真实用户协议与隐私政策。
- 无 Android 设备/模拟器、无 macOS,未进行 Android/iOS 实机验收;本次没有新增移动插件。
- 本次曾误建 heqi-a1-postgres、heqi-a1-redis,未建表或导入数据。Docker daemon 后来不可用,删除未能确认;不要启动 Docker 或动现有其他容器来绕过用户的远程环境要求。
下一起点:先完成 A1 剩余视觉收敛,再进入 A2,包含 37 邀请注册。每批保留测试、真实接口与视觉证据,不创建空白页面占位。

View File

@@ -0,0 +1,102 @@
# 用户端 App A1 操作日志
操作时间:2026-09-07,收尾核对 20:17(Asia/Shanghai)。
操作类型:扩展、缺陷修复。影响模块:Flutter 用户端、共享设计系统、Go Client API;平台资源定义不变。
## 操作前状态
git 初始无既有业务改动;先读仓库规范、主开发文档、产品说明与 5 张最新 PNG。用户端已有登录、首页、商城、订单、我的及部分二级能力。基线 analyze 无问题、Flutter 33 项通过、Go 全量通过。尚无 58 页进度文件。
确认:未开放功能入口不隐藏;37 邀请注册归 A2;持久化环境使用仓库既有远程 PostgreSQL 与 Redis。
## 关键变更
以下路径相对 D:/5k/platforms;增删行为 20:17 的 git diff --numstat 快照,后续视觉收敛补记见表后,不将格式化行数等同业务功能数。
| 文件 | 核心函数/类 | 行数(新增/删除,或新文件总行) | 变化与理由 |
| --- | --- | --- | --- |
| apps/heqi_design_system/lib/src/theme.dart | HeqiTheme._theme | +23/-3 | 明确蓝白容器与对比色、一级标题位置、筛选标签可读性 |
| apps/heqi_design_system/lib/src/components.dart | HeqiSurfaceSection.build | +6/-4 | Material 承载 ListTile 点击墨水层 |
| apps/heqi_design_system/pubspec.yaml | version | +1/-1 | 0.1.1 补丁版本,无公共 API 破坏 |
| apps/user_app/lib/app/dependencies.dart | UserSession.login/resetPassword | +44/-1 | 显式记住登录、实际同意版本和展示时间,复用密码重置接口 |
| apps/user_app/lib/app/router.dart | createRouter | +25/-6 | 首页/商城游客可见,受保护页安全回跳、服务入口定位 |
| apps/user_app/lib/data/repositories/client_repository.dart | _readPages/products/_records | +20/-2 | 可选分页兼容旧数组,不将异常降级为空 |
| apps/user_app/lib/data/repositories/primary_repository.dart | PrimaryRepository | 新 53 | 公开内容/商品/归属强类型适配;非法金额失败而非变零 |
| apps/user_app/lib/domain/models/primary_models.dart | PublishedContent/ProductSummary/ServiceRelation | 新 35 | 明确首页和商城字段 |
| apps/user_app/lib/domain/models/order_summary.dart | OrderSummary.fromRecord/OrderItemSummary.fromJson | 新 65 | 隔离状态、金额、动作和成交快照,缺少权限默认不显示操作 |
| apps/user_app/lib/ui/core/async_content.dart | AsyncContentState.refresh/build | 新 79 | 首次、刷新、空、错误、重试;迟到请求不覆盖最新结果 |
| apps/user_app/lib/ui/core/feature_entry.dart | showUnavailableFeature/FeatureEntry | 新 36 | 保留功能入口并明确不可办理 |
| apps/user_app/lib/ui/core/text_entry_dialog.dart | TextEntryDialog | 新 59 | 弹窗自行释放控制器,避免关闭动画报错 |
| apps/user_app/lib/ui/features/auth/login_page.dart | _login/_sendCode/_modeTab/build | +221/-45 | 验证码/密码登录、冷却、协议确认、可见标签与横排品牌 |
| apps/user_app/lib/ui/features/auth/login_support.dart | showPublishedAgreements/ResetPasswordDialog | 新 174 | 读取后台协议、现有验证码重置闭环,不写死政策正文 |
| apps/user_app/lib/ui/features/home/home_page.dart | _load/build | +147/-86 | 服务归属和公开内容,设备保留入口,真实维修跳转 |
| apps/user_app/lib/ui/features/home/service_relation_card.dart | ServiceRelationCard.typed | +8/-0 | 保留旧 Map 构造方式并新增强类型入口 |
| apps/user_app/lib/ui/features/shop/shop_page.dart | _buy/build | +195/-134 | 后台分类/搜索/图片/库存、显式下单和页面内幂等重试 |
| apps/user_app/lib/ui/features/orders/orders_page.dart | _openActions/_performActions | +38/-26 | 服务端动作控制、提交锁、跨 Tab 刷新、原请求号重试 |
| apps/user_app/lib/ui/features/orders/order_list.dart | OrderList | 新 124 | 订单搜索/状态筛选/快照/时间与金额 |
| apps/user_app/lib/ui/features/profile/profile_page.dart | _load/_addAddress/_createTicket/didUpdateWidget | +202/-99 | 并行读取、手机脱敏、账户与服务入口、表单生命周期和点击锁 |
| backend/api/internal/logic/client/user/auth.go | Login/loginRequest | +10/-5 | 可选同意版本写入,旧登录兼容 |
| backend/api/internal/logic/client/user/shop.go | PublicProducts/ListShopOrders | +49/-9 | 修复公开商品误查私有订单明细;分类/图片/分页/订单动作 |
| backend/api/internal/logic/client/user/gasorder.go | ListGasOrders | +26/-2 | 本人订单项、状态名、允许动作、分页 |
| backend/api/internal/logic/client/user/list_response.go | paginateClientList/respondClientPage/clientOrderState | 新 50 | 分页上下限、旧数组响应、状态标签 |
| backend/api/internal/logic/client/user/login_consent.go | recordLoginConsents | 新 48 | 发布版本锁定,保留实际展示时间,阅读唯一键幂等 |
测试改动:login_page_test.dart、orders_page_test.dart;新增 primary_pages_test.dart、primary_repository_test.dart、test/support/a1_fixture.dart、tool/a1_visual_test.dart、primary_api_test.go。
视觉收敛补记:login_page.dart 使用独立验证码按钮;orders_page.dart 的 _openRefunds 将退款列表保留在筛选入口,主 Tab 收敛为三类,旧 initialTab 映射保留;profile_page.dart 的 _assetSummary 改为三列资产摘要,_openRequestedRepair 消费一次性 query,修复重复从首页报修无法再开表单的问题。新增 scripts/compare-user-app-a1.ps1 复现并排图;末次增删行统计以 git diff 为准。
文档改动:58 页开发进度、新 v1.1 项目文档(v1.0 原件保留)、本日志、A1 视觉记录、docs/13 与文档导航。生成 40 张实现截图和 5 张并排对照。未新增生产依赖、表或路由;开发配置和凭据未改写。
## 代码行为示例
公开商品原先用商品 ID 查询 ec_order_item,可能读到同 ID 的无关订单项;现在只查询关联的商品图片、分类,响应继续剔除内部主键。
```go
// backend/api/internal/logic/client/user/shop.go,PublicProducts
impl.DBService.Where("ec_product_id = ? AND status = ?", product.ID, common.StatusEnable)
```
```dart
// apps/user_app/lib/domain/models/order_summary.dart,权限缺失时不自行推导
actions: Set.unmodifiable((raw['allowed_actions'] as List? ?? []).whereType<String>()),
```
## 验证结果
| 验证 | 结果 |
| --- | --- |
| 用户端 flutter analyze | 无问题 |
| 用户端 flutter test --no-pub | 44 项通过,比基线增加 11 项 |
| flutter test --no-pub --update-goldens tool/a1_visual_test.dart | 40 项尺寸/缩放/滚动检查通过,视觉差异另列 |
| flutter build web --release --no-pub --dart-define=API_BASE_URL=http://127.0.0.1:12426 | 通过 |
| 共享包 analyze/test | 无问题,3 项通过 |
| 服务端 App analyze/test | 无问题,21 项通过 |
| Go go test ./... / go vet ./... / go build | 均通过 |
| Go 协议重复确认、旧版本拒绝测试 | 通过;重复请求使用内容版本唯一键 |
| 平台 pnpm contract:check | 48 个资源通过 |
中间测试曾发现:订单新增搜索框使旧退款测试选择器多匹配;登录 hint 与 error 文案相同使旧测试多匹配;新 HTTP Fixture 默认 Latin-1 不支持中文。已分别限定弹窗输入、直接验证 errorText、使用 UTF-8;负向测试验证具体 1714 码以防错误通过。不是忽略失败或降低断言。
共享包分析曾引起本机包源及 SDK 间接锁版本自动变化,已恢复本次产生的无关 pubspec.lock 改动,保留有意义的包版本与代码变更。
## 远程联调事实
1. 只读事务核对既有角色、管理员、指定测试用户、商品,Redis 仅 PING。
2. 启动 API 前确认不自动迁移表;基础初始化所需记录已存在。未执行 migrate/mock-data。
3. 使用任务指定账号登录;公开内容、商品分页、资料、钱包、地址、订单、服务归属返回 code=0。令牌、密码没有写入仓库、日志说明或截图。
4. 对现有 MOCK 商品创建未支付订单,同 request_no 重试返回同一 identity,价格按整数分由服务器计算,库存只扣一次。
5. 使用现有取消接口恢复库存,保留已取消订单 01a07bc0-6237-7ec2-8cbc-1c05f16ad10b,没有删除订单/支付/资金事实。
6. 浏览器验证游客入口提示、受保护订单跳转登录并回跳、订单记录、个人中心实际余额与脱敏手机号、商品关键词筛选。
7. 未勾选“记住登录状态”后刷新浏览器,访问订单重新进入登录页,确认没有恢复旧持久会话。
8. 最终 Web 构建中再次登录后,三类订单主标签正常;连续两次从首页进入报修均打开表单并消费查询参数,均取消而未新建工单。390×844 个人中心截图无溢出,预览保留供试用。
本机仅运行 API(12426)与 Web 预览(18571);数据库与缓存保持原远程地址。曾因误解创建两个本任务容器,未初始化或使用;Docker 后来停止,删除结果未确认,未启动 Docker 强行处理,更未删除既有 workbuddy 容器。
## 风险与当前状态
业务实现和测试已落地,A1 严格视觉一致性仍未验收;详见视觉记录。没有进入 A2 或创建 53 个空页面。设计素材/完整设备与交易规则按后续批次推进。
分页门面暂读完所有页,数据多时延迟和查询量增加;A2 应改为显式逐页加载。商品关联查询目前逐项执行,不将本次小样本验证声称为压力测试。页面内幂等号不能保证跨重启恢复,旧地址接口幂等扩展仍待 A2。
现有退款/支付的允许动作是候选能力,执行时仍可能因状态并发或业务限制拒绝;最终结果以服务端为准。未验证正式商户、短信供应商、Android/iOS 实机。远程缺已发布协议与商品图,未造运营数据填空。

View File

@@ -0,0 +1,30 @@
# 供气合同列表开发记录
操作时间:2026-09-08。操作类型:扩展及缺陷修复。影响模块:图32、本人合同接口。
操作前:个人中心合同入口仅为通用记录列表。ListGasContracts错误地用合同ID查询订单气瓶,数值碰撞时可能返回无关订单明细。
操作后:独立合同页面支持搜索编号/标题/气站、筛选真实业务状态、下拉刷新、失败重试、查看合同正文。保留原路由和旧contracts()仓储接口。
## 代码与接口
- backend/api/internal/logic/client/user/gasorder.go:ListGasContracts改查gasorder_contract_product并按合同归组,气站批量读取,避免逐合同查询。本人过滤保留,file_uri兼容字段置空,不再发送私有存储地址,新增station_name、has_attachment。
- apps/user_app/lib/domain/models/gas_order_detail.dart:GasContractSummary保留业务状态、供气单位与日期,不将草稿推断成待签署。
- apps/user_app/lib/data/repositories/client_repository.dart:gasContracts增加强类型适配和会话切换保护。
- apps/user_app/lib/ui/features/orders/gas_contracts_page.dart:列表、搜索、筛选、卡片、有效期和正文查看;app/router.dart替换原通用页面。
- 后端gas_contract_list_test.go新增归属与绑定查询回归、空列表不查关联;Flutter新增gas_contracts_page_test.dart及gas_contracts_test.dart,Fixture与tool/a1_visual_test.dart新增图32。
- scripts/compare-user-app-a1.ps1加入图32,现16组对照对应15张设计。
## 验证
Go全量测试、vet及构建通过。Flutter analyze通过,原99项全量测试通过,随后新增合同类型/跨会话测试1项通过。UI测试覆盖首读失败重试、到期筛选空态、编号搜索和正文打开。图32在320/360/390/430与1.0/1.3字体的8组截图检查通过,已查看390与320大字体,并将筛选样式修正为原图蓝色圆角按钮。
Web Release和Android Debug构建通过。新API读取远程MOCK-CONTRACT-001返回和气示例气站、状态11、1条合同绑定且原始附件地址为空;本轮只读远程业务数据,没有迁移或修改现有合同。浏览器已验证合同深链登录回跳、已到期筛选空态、编号搜索、查看真实合同正文,控制台无错误或警告。API进程42232提供新接口,18571提供更新后的Web。
新增页面gas_contracts_page.dart共191行;后端ListGasContracts修改约40行,新增两项SQL查询回归。其余兼容文件已有前序改动,不能将工作树累计差异算成本轮修改行数。
## 未完成及维护边界
图32仍为部分实现:无签署工作流、家庭共享协议、用气地址快照、PDF下载、合同服务与完整签署历史。保留真实草稿/生效/到期/终止状态,不用设计演示合同、地址或法律效力声明补空。15张设计部分实现、43张无完整对应页、0张严格全功能1:1通过。
后续附件下载必须先校验本人合同并复用受控文件读取,不能将存储路径拼成公开URL;签署须衔接实名与审计契约,不可本地改变状态。修改绑定关联时应运行新增SQL作用域测试,防止合同ID与订单ID再次混用。

View File

@@ -0,0 +1,50 @@
# 用户端供气订单详情开发与验证
操作时间:2026-09-08。操作类型:扩展。影响模块:用户端订单、本人合同读取、供气签收。
## 行为变化
此前气瓶订单只有列表与通用操作。本次增加独立详情:历史气瓶明细、供气单位、配送员姓名、配送费、实际支付记录、状态发生时间及本人合同正文。订单列表点击详情进入 `/gas/orders/:identity`。只对待签收订单发布确认收货动作,用户确认后服务端事务记录本人签收、完成订单并释放气瓶占用;重复确认不重复写证据。
## 文件与职责
| 文件(相对仓库) | 函数及变更 |
| --- | --- |
| backend/api/internal/logic/client/user/gas_detail.go | GetGasOrder、GetGasContract;所有权过滤、显式公开字段与统一状态动作 |
| backend/api/internal/logic/client/user/gas_confirm.go | ConfirmGasReceipt;行锁、状态校验、签收证据、占用释放和历史记录 |
| backend/api/internal/logic/client/user/gasorder.go | ListGasOrders复用状态及动作定义 |
| backend/api/internal/models/gasorder_confirm.go | 中文注释补充user_app签收方式;无表结构变更 |
| backend/api/internal/routers/client.go | 增加受保护详情、合同和签收路由,原接口兼容保留 |
| apps/user_app/lib/domain/models/gas_order_detail.dart | 强类型详情、整数分支付、合同正文模型 |
| apps/user_app/lib/data/repositories/client_repository.dart | gasOrderDetail、gasContractDetail、confirmGasReceipt;会话与响应归属校验 |
| apps/user_app/lib/ui/features/orders/gas_order_sections.dart | 真实状态时间轴、服务资料、合同读取及失败重试 |
| apps/user_app/lib/ui/features/orders/shop_order_detail_page.dart | 兼容商城页面并增加供气分支 |
| apps/user_app/lib/ui/features/orders/order_action_handler.dart、orders_page.dart | 签收确认、稳定请求号重试、详情返回刷新 |
| apps/user_app/lib/app/router.dart | 本人供气订单深链与登录回跳 |
| scripts/compare-user-app-a1.ps1 | 图21气瓶与商城分支分别配对原图,十五组对照对应十四张设计 |
新增后端测试gas_detail_test.go、gas_confirm_test.go、gas_receipt_remote_test.go,前端test/data及test/ui/gas_order_detail_test.dart;视觉Fixture明确与真实数据分离。
## 接口与边界
- `GET /heqi/client/v1/user/gas/orders/:identity`、`GET gas/contracts/:identity`:JWT本人范围,缺失或非本人1112,匿名HTTP401。详情不返回内部主键、员工手机号、操作人身份或内部处理备注。
- `POST gas/orders/:identity/confirm-receipt`:只接受request_no,长度1—128;仅状态34可签收,已完成23幂等返回,其他状态1704。收货人取当前账户,不能由请求冒用;写入user_app证据,不伪造手写签名或图片。
- 合同仅阅读既有正文,附件地址不外泄;完整合同列表筛选、签署和附件下载仍未完成,不能把正文弹层计为图32完整页面。
- 支付记录只读本订单、本付款人的成功支付;不能从履约状态推断实付。订单无押金、ETA及受控联系方式契约时不填设计演示数值。
## 验证证据
- 本轮Go全量测试、vet和API构建通过;Flutter全量98项及analyze通过。时间轴调整后analyze与5项详情定向测试再次通过。
- 气瓶/商城订单列表与详情32组布局检查通过;时间轴调整后图21-gas的320/360/390/430宽度、1.0/1.3字号8组再次通过。已实际查看390常规、320大字体及最新原图,常规宽度改为横向时间轴,窄屏/大字体保留竖向完整历史。
- 一次不带`--update-goldens`的全视觉检查出现22项旧截图差异失败,不能当成全视觉回归通过;此次仅更新并核对气瓶详情8组。生成截图不等于1:1断言。
- 远程数据库显式回滚事务测试通过:临时订单、气瓶、合同绑定、占用明细均在同一事务,验证签收、重复确认、证据与占用释放,再回滚并确认临时记录数为0。无迁移、种子或本机数据库/缓存操作。
- 真实HTTP读取MOCK-GASORDER-001:1条气瓶、1条历史、1条支付,配送费500分;合同MOCK-CONTRACT-001正文读取成功。缺失订单1112、匿名401。没有对既有真实订单执行签收。
- 浏览器验证登录回跳、气瓶列表进入详情、读取合同正文及关闭。示例数据的完成时间早于建单时间,保留原值并记录为数据异常,不篡改历史。Web Release及Android Debug构建通过;平台契约同步与检查通过48个资源。
## 视觉结论与维护
**图21仍未通过严格1:1。** 时间轴已按真实数据横向排列;气站与商品分组、原始商品图片、押金、预计送达、地图配送、受控联系、完整售后和部分密度仍有差异。图32仍无完整对应页面。58图仍为14张部分实现、44张无完整页面、0张严格全功能验收通过。
证据:[气瓶详情对照](视觉验收/A1/21-gas_并排对照.png)、[390截图](视觉验收/A1/21-gas_390_1.0.png)、[320大字体](视觉验收/A1/21-gas_320_1.3.png)。
签收规则变更须同时回归原配送签收、订单占用释放与幂等。远程回滚测试默认跳过,仅明确设置HEQI_REMOTE_RECEIPT_TEST=1时执行;不得去掉外层回滚或运行全库初始化。新字段必须继续使用白名单和本人过滤。

View File

@@ -0,0 +1,11 @@
# 充值到账提示修复
操作时间:2026-09-11。操作类型:修复。
`apps/user_app/lib/ui/features/wallet/recharge_page.dart` 的到账查询已确认状态23后会再次读取余额。原实现将余额刷新异常落入充值查询失败提示,错误否认已经确认的到账事实。现将余额刷新单独处理,保留已到账结论并提示重新进入页面刷新余额。
`test/ui/recharge_page_test.dart` 注入首次余额成功、到账后余额读取失败,验证请求仍清除、金额解锁且不显示未确认提示;测试通过。改动不涉及支付调用、数据库或缓存写入。
充值表单仍未通过设计图视觉验收,协议版本留痕及完整真实支付测试待完成。
Go后端构建通过,已将12426服务更新为临时目录的 `heqi-recharge-options-api.exe`,进程1060,继续使用原dev远程配置。Web构建通过(88.9秒),18572预览服务返回HTTP200。这里只证明构建与服务响应,不代表已完成浏览器充值交互或渠道联调。

View File

@@ -0,0 +1,11 @@
# 充值协议接入
操作时间:2026-09-11。操作类型:扩展充值前置确认。
`client_repository.dart` 新增confirmRechargeAgreement,向既有阅读确认接口提交内容标识、实际版本和账号版本稳定幂等号;响应必须包含有效阅读记录标识及相同版本,并检查会话未变化。
`recharge_page.dart` 在创建充值前调用确认接口;确认失败中止创建,不新增待确认订单状态。版本错误不能以成功处理。
新增 `test/data/recharge_agreement_test.dart` 验证POST路径、版本和稳定请求号,错误版本响应拒绝,测试通过。页面既有3项测试通过,静态检查通过。没有真实协议确认或支付请求。
尚未部署新前后端,真实协议记录联调、并发版本保护及跨入口幂等情况仍需验证;因此不将协议留痕认定为最终完成。图38视觉及真实渠道等验收仍未完成。

View File

@@ -0,0 +1,43 @@
# 充值查询与幂等接口开发记录
操作时间:2026-09-11
操作类型:扩展、修复
影响模块:共用客户端钱包充值接口。
## 操作前后
原充值接口只有创建和Mock确认,客户端无法查询本人充值记录或恢复未知结果。创建时遇到重复请求号直接返回旧记录,没有核对本次金额与渠道;重复提交不同金额可能得到旧金额支付参数。
现在以请求号唯一约束配合`ON CONFLICT DO NOTHING`,重复时核对主体类型、主体标识、金额和渠道。同请求同参数返回同充值单;金额、渠道或归属不一致返回2411“充值请求已存在,请保持原金额和支付方式”。不通过异常插入破坏外层事务,不创建重复充值记录。原返回字段保持兼容,真实渠道响应增加`recharge_identity`、`recharge_no`、`recharge_status`。
新增本人充值记录、单条结果及按原请求号恢复查询。钱包入账状态与支付单状态分别返回,缺少支付单时不推测已经支付。所有读取限定主体类型及身份,不返回钱包内部主键、操作者、密钥或支付调起参数。
## 接口契约
相对路径基于`/heqi/client/v1/user`,现有服务端客户端也复用同一能力。
| 方法与路径 | 参数 | 返回与边界 |
| --- | --- | --- |
| POST wallet/recharges | 既有amount、channel、request_no、pay_type等 | 同请求号重试必须保持金额和渠道,冲突2411 |
| GET wallet/recharges | 可选cursor,服务端返回的正整数游标 | items最多50条,next_cursor为空表示无后续页 |
| GET wallet/recharges/:identity | 公开充值标识 | 本人充值字段,可选payment_status、expires_at |
| GET wallet/recharge-requests/:request | 原始request_no | 网络结果未知时恢复本人充值记录,不修改状态 |
充值字段:identity、recharge_no、recharge_status、amount(整数分)、channel、created_at、completed_at。`recharge_status=23`才是已入账,不能仅凭支付客户端返回成功宣称到账。原图10至5000元不是已确认的服务端业务规则,本轮没有改写现有限额配置或凭空发布充值协议。
## 核心文件
- `backend/api/internal/logic/common/client_wallet.go`:CreateRecharge冲突处理及响应补充;ConfirmMockRecharge补齐主体类型过滤。
- `backend/api/internal/logic/common/recharge_query.go`:GetRecharge、ListRecharges及白名单投影rechargePublic。
- `backend/api/internal/routers/client.go`:增加三个读取路由,旧接口保留。
- `backend/api/internal/logic/common/recharge_remote_test.go`:显式开启的远程事务回滚测试。
## 验证和风险
`HEQI_REMOTE_RECHARGE_TEST=1`远程测试通过(16.17秒):独立用户与零余额钱包,创建同参重试、修改金额/渠道冲突、按请求号恢复、跨主体类型拒绝、Mock重复确认仅入账一次、只生成一笔流水。完成后整体回滚,确认测试充值单和钱包均不存在;没有实际调用微信/支付宝,也没有修改已有账户资金。普通测试默认跳过远程用例。
本轮无数据库结构变更,不启动本机PostgreSQL或Redis。真实渠道返回可能未知,客户端应保留原请求号查询;本轮不修改支付SDK的渠道重试逻辑,不宣称渠道侧恰好一次请求已得到完整验证。
图38充值页面及完整渠道交互仍未完成,本轮提供其必需的结果查询和幂等保证,不能据此把图38计为完成或改变全量17张部分实现、41张无对应完整页、0张严格通过的状态。
后端全量go test、go vet和API构建通过。新API进程42452监听12426;实际授权账户读取充值记录返回成功及1条既有记录,未知请求号返回业务码1112。SDK错误响应仍使用HTTP200包装业务码,客户端必须读取code,不能单靠HTTP状态判断存在或成功。本轮实测只读,没有创建真实充值单或发送真实支付请求。

View File

@@ -0,0 +1,11 @@
# 充值窄屏与全量回归
操作时间:2026-09-11。操作类型:验证扩展。
`apps/user_app/test/ui/recharge_page_test.dart` 增加320及390逻辑像素宽度、844高度、1.3倍字体测试,检查首次加载及滚动至充值按钮无Flutter布局异常。两项均通过;同文件原有异常恢复和金额控件测试通过。
全量 `flutter test` 共135项通过(32秒);`git diff --check`通过。运行中的12426后端进程1060和18572预览进程34588已核对。此次没有数据库、缓存或支付写入。
布局异常检查不证明与设计图1:1一致,也不替代真机支付、浏览器操作或图片资产核对。图38整体样式、协议留痕、真实渠道等仍未验收,统计不调整为通过。
Web构建通过(61.4秒),最新金额控件已输出至18572服务使用的build/web目录;打开旧标签页需整页重新加载才能取得新代码。浏览器登录后的交互尚未验证。

View File

@@ -0,0 +1,18 @@
# 充值表单接入
操作时间:2026-09-11。操作类型:新增页面、扩展钱包入口。
## 代码和行为
- `apps/user_app/lib/ui/features/wallet/recharge_page.dart`:新增余额显示与隐藏、100/300/500金额选择、自定义金额、渠道就绪展示、协议查看与勾选、原请求继续支付及到账查询。
- `apps/user_app/lib/app/router.dart`:增加 `/wallet/recharge` 路由。
- `apps/user_app/lib/ui/features/wallet/wallet_page.dart`:两个充值入口转入表单。
- 创建与恢复使用现有 `RechargeFlow`;仅实际充值完成状态清除待确认请求并刷新余额。协议缺失禁止创建,但不阻止已有请求查询。
## 验证与不足
新增页面测试通过,覆盖缺少协议时禁用支付、恢复订单时锁定金额、查询到账后删除待确认请求并解锁金额。首次检查发现新增回调位于const组件内,已去掉const;测试补充显式列表滚动定位后通过。
最终Flutter静态检查返回No issues found(93秒),进程退出码0;`git diff --check`通过。
本批尚未构建部署预览、未进行浏览器与设计图视觉核对,不计图38完整验收。协议版本尚未提交服务端留痕;关闭订单的后续处理、跨窗口重复提交和实际原生支付仍待完成。充值配置接口需要部署后端新构建。没有执行真实支付或改动远程资金。

View File

@@ -0,0 +1,19 @@
# 充值记录页面
操作时间:2026-09-11。操作类型:新增。
## 变更
- 新增 `apps/user_app/lib/ui/features/wallet/recharge_records_page.dart`,通过现有充值查询接口读取当前账号记录,支持游标分页、标识去重、刷新和失败重试。
- `apps/user_app/lib/app/router.dart` 增加 `/wallet/recharge-records`;钱包标题栏增加充值记录入口。
- 失败保留已显示记录;刷新使用新请求世代,忽略较早请求的迟到响应。充值完成状态才显示已到账,测试渠道历史记录明确标注测试充值。
## 验证
`test/ui/recharge_records_page_test.dart` 验证分页参数、重复记录去重、刷新失败保留数据及重试使用首页参数,1项通过。Flutter静态检查通过。
钱包原有交互和充值金额测试另5项通过;Web构建通过(78.8秒),预览服务18572仍在运行并指向构建目录。尚未用浏览器验证新页面,不能据构建结果认定视觉通过。
## 未完成
余额充值表单、渠道拉起及请求持久化恢复尚未完成;本页不代表图38完整实现,也未完成浏览器操作和设计图视觉验收。本次未请求支付或写入远程数据库、缓存。

View File

@@ -0,0 +1,10 @@
# 充值请求恢复
操作时间:2026-09-11。操作类型:扩展客户端充值数据层。
- 新增 `recharge_draft_store.dart`,使用独立安全存储命名空间保存请求号、整数分金额、渠道和支付类型,按API地址及服务端账号标识隔离。损坏数据报错,不静默丢弃。
- 新增 `recharge_flow.dart`,先保存再创建充值;已有不同待确认请求时拒绝另发订单。查询未到账或响应异常时保留原请求,仅核对金额、渠道且确认入账后删除。
- `client_repository.dart` 新增 `rechargeDraftOwner`,检查请求前后会话状态。
- 新增存储和流程测试3项,通过;静态检查通过。测试覆盖存储失败不发单、响应丢失保留、不同请求阻止、未到账保留和已到账清除,以及账号环境隔离。
本批未调用真实支付或改写远程资金。页面尚未接入该流程;多窗口并发、支付关闭后的新订单处理、协议版本留痕和真实渠道仍待补齐,不能认定完整充值可用。单实例忙碌保护不等于跨窗口互斥。

View File

@@ -0,0 +1,18 @@
# 充值配置和客户端校验
操作时间:2026-09-11
操作类型:扩展
影响模块:充值配置接口、客户端充值数据层。
## 行为与文件
- `backend/api/internal/logic/common/recharge_options.go`:新增渠道配置就绪状态、实际充值限额及已发布充值协议查询;不返回密钥,不提供Mock支付入口。文件存在仅表示配置条件满足,不证明支付渠道连接成功。
- `apps/user_app/lib/domain/models/recharge.dart`:十进制金额直接转分,拒绝超精度、负数和指数输入;只有充值状态23表示已到账。协议缺少标识、正文或有效版本时拒绝使用。
- `apps/user_app/lib/data/repositories/client_repository.dart`:扩展配置、记录、详情、请求恢复和创建接口,保留会话校验与创建结果核对。
- `apps/user_app/test/domain/recharge_test.dart`:增加3个测试,覆盖金额边界、支付状态与入账状态区别、协议及限额异常。
## 验证与限制
后端 `go test ./internal/logic/common` 通过;新增Flutter测试3项通过。静态检查发现两个缺少花括号的提示,已修复并重新检查。
本次未发起真实充值、未变更数据库或缓存。新增配置接口尚未部署到预览后端。图38页面、支付拉起、持久化请求恢复与视觉验收仍待完成,不计完整功能,不调整17张部分实现、41张待实现、0张严格验收的统计。

View File

@@ -0,0 +1,11 @@
# 充值配置边界测试
操作时间:2026-09-11。操作类型:增加后端回归验证。
新增 `backend/api/internal/logic/common/recharge_options_test.go`:使用SQLMock确认账户鉴权、已发布充值协议查询条件与版本排序;未配置渠道返回不可用,协议不存在不伪造协议内容,不提供Mock渠道。账户不存在时不返回渠道信息,也不继续访问协议查询。
另验证空路径、缺失路径和目录不能被视作可用密钥文件。测试不会连接远程数据库,不读取或打印真实密钥。定向测试通过;公共模块完整测试结果以本次执行输出为准。
这些测试只证明配置接口边界,不能证明真实支付供应商可用。页面样式、协议留痕、渠道联调等未完工作仍保留。
最终 `go test ./internal/logic/common` 通过(8.578秒),包含上述鉴权失败分支。

View File

@@ -0,0 +1,11 @@
# 充值重试入账检查
操作时间:2026-09-11。操作类型:修复充值重试。
`recharge_flow.dart` 在已有待确认请求重试前查询服务端充值事实,核对金额、渠道和账号;已到账返回状态23,不调用创建接口。明确业务码1112表示订单不存在时允许原请求号重发,其他查询异常保留请求且不发起支付。
`recharge_page.dart` 接收已到账状态后走到账查询及余额刷新,不调用支付SDK。`recharge_flow_test.dart` 增加到账后重试不增加创建次数、仍由恢复确认清理请求的断言。
相关流程和页面4项测试通过,静态检查通过;加入1112分支后流程测试再次通过。此次未请求真实支付,没有远程数据库或缓存写入。尚未重新构建预览,协议留痕及视觉等剩余验收不变。
后续补充异常分支测试:业务码1112允许同请求创建一次;500查询失败不创建;查询期间账号改变不创建,三种情况均保留待确认记录。测试首次使用Exception匹配StateError不准确,改为按分支匹配具体类型后,两项流程测试通过。验证使用内存夹具,没有远程请求。

View File

@@ -0,0 +1,11 @@
# 充值金额控件补齐
操作时间:2026-09-11。操作类型:扩展。
对照原图 `38-余额充值.png`,补充独立自定义选项、金额清空按钮和确认按钮实时金额。输入变化同步刷新选中态和按钮金额,待确认订单期间禁止修改。涉及 `recharge_page.dart`,增加并释放金额输入FocusNode。
页面测试增加清空、输入200.29及确认按钮精确显示金额的验证,通过;Flutter静态检查通过。未修改真实资金。
浏览器检查发现原标签页仍运行旧构建,直接跳充值路由显示Page Not Found;带新查询参数整页加载后进入登录页。尚未完成登录后的充值交互验证,不能将此记录作为浏览器验收通过。此次金额控件修改尚未重新构建部署。
整体卡片布局、图标及其他设计细节仍不一致,图38未通过严格视觉验收。后续继续核对完整页面及渠道流程。

View File

@@ -0,0 +1,9 @@
# 协议版本确认
操作时间:2026-09-11。操作类型:兼容扩展。
`backend/api/internal/logic/client/user/basic.go` 的ConfirmContentRead新增可选 `content_version`。提供时必须大于0并精确匹配发布且启用的内容版本;不提供时保留旧客户端行为。同一请求号重试还须匹配原内容ID和版本,不允许拿其他阅读记录冒充成功。
新增 `content_read_test.go` 验证过期版本与无效版本不能确认,不触发写入。`go test ./internal/logic/client/user`通过(0.514秒)。验证使用SQLMock,没有远程数据库、缓存或支付写入。
此为协议留痕前置修复,充值页面尚未提交阅读确认,接口尚未部署新构建;协议版本并发更新的事务保护和完整充值接入仍需继续。不能认定充值协议留痕已完成。

View File

@@ -0,0 +1,28 @@
# 合同变更记录开发日志
操作时间:2026-09-08。操作类型:扩展。影响模块:本人供气合同。
## 行为变化
原合同页面无法查看历史状态与有效期变更。现在每份合同提供“变更记录”,独立读取不可变快照,支持失败重试、下拉刷新与空态。现有正文、PDF下载、搜索、筛选和旧路由保留。
## 关键文件
- backend/api/internal/logic/client/user/gas_contract_history.go:GetGasContractHistory先按公开identity、JWT用户及未归档状态限定合同,再按合同ID读取变更记录,发生时间与identity倒序。响应白名单仅包含identity、action、contract_status、occurred_at、effective_at、expired_at,不发送内部主键、员工身份或内部原因。
- backend/api/internal/routers/client.go、client_test.go:增加受保护GET `/heqi/client/v1/user/gas/contracts/:identity/history`及路由回归。
- apps/user_app/lib/domain/models/gas_order_detail.dart:GasContractEvent强类型适配,区分activate/renew/terminate等真实动作,未知动作仍显示通用变更而非成功签署。
- apps/user_app/lib/data/repositories/client_repository.dart:gasContractHistory读取本人记录并丢弃跨会话迟到响应。
- apps/user_app/lib/ui/features/orders/gas_contract_history.dart:历史弹层、状态及有效期快照、错误重试、空态和关闭;gas_contracts_page.dart增加入口。
- 后端gas_contract_history_test.go覆盖归属SQL、顺序和内部字段不外泄;前端gas_contract_history_test.dart覆盖重试、真实变更含义及关闭。
## 验证
Go全量测试、vet与API构建通过。Flutter analyze、全量103项测试通过。图32在320/360/390/430宽度与1.0/1.3字体的8组截图检查通过,已查看390截图,更新并排证据。平台资源契约同步和48项检查通过。
真实API读取MOCK-CONTRACT-001,返回activate记录:发生时间2026-06-30 09:00,状态11,有效期至2027-07-01 09:00;匿名HTTP401。无数据库迁移或远程业务写入。
浏览器已完成登录回跳、列表“变更记录”入口、真实合同生效记录及关闭;桌面和390手机宽度均实际查看,控制台无错误/警告。Web Release和Android Debug构建通过。新API进程43912,Web端口18571。
## 边界
变更记录不等于电子签署证据,也不代表已实现合同变更申请、续签提醒或签署工作流。历史内部原因未区分公开/私有口径,因此不下发;不能把内部操作员姓名当作用户签名。图32仍为部分实现,严格视觉与完整合同服务仍待补。

View File

@@ -0,0 +1,37 @@
# 合同申请与个人中心复核
操作时间:2026-09-08。操作类型:扩展、修复。影响模块:用户合同、气站工单、平台工单、个人资料。
## 实际差异
已打开图25、图32原稿,与390宽运行页面及截图逐项核对。个人中心仍缺认证、押金、优惠券、设置、消息、紧急联系人、家庭共享等完整能力,分组密度和图标素材未达到1:1。设计中的示例头像不能替代登录用户的真实头像;无头像账户使用姓名占位。图32仍缺共享授权协议签署、地址快照、续签提醒及原稿合同服务布局。
头像可从个人中心资料区域进入“更换头像”,真实浏览器已核对拍照、相册和取消入口。既有上传成功证据保留在此前日志,本次没有重复改写远程用户头像。新增修复:服务端清空头像后下拉刷新,编辑页清除旧图片缓存。个人中心消息、联系人、家庭和收藏图标按原稿语义调整。
## 合同申请行为
原来只有合同正文、PDF和状态历史。现在每份本人合同可填写变更内容,提交至所属气站工单队列,读取状态、取消申请、查看答复并确认处理完成。申请不会直接变更合同条款或产生电子签名。
同账户锁、稳定请求号和同合同进行中申请检查防止重复待办。转出用户不能继续向原气站新申请条款变更。气站只能答复本站关联合同申请,待受理/处理中可答复,答复后待用户确认;相同答复可幂等重试。平台和气站普通工单编辑不得改换关联申请的用户或业务分类。普通维修工单原接口保持兼容,App报修列表不混入合同申请。
## 文件与接口
- `backend/api/internal/models/cs_ticket.go`:可选内部合同关联字段,0表示普通工单。
- `backend/api/cmd/cli/address_migration.go`、`main.go`:`migrate-ticket-contract`只增加远程`cs_ticket.gasorder_contract_id`、索引及中文注释,已执行;未运行全库迁移或本机数据库。
- `backend/api/internal/logic/client/user/gas_contract_request.go`:CreateGasContractRequest、ListGasContractRequests;GET/POST `/heqi/client/v1/user/gas/contracts/:identity/requests`。
- `backend/api/internal/logic/gas/contract_request.go`、`ticket.go`:气站答复、原气站权限范围、处理按钮状态投影;POST `cs_ticket/:identity/resolve-contract-request`。
- `backend/api/internal/logic/platform/contract_ticket_guard.go`、`routers/platform.go`:保留普通CRUD行为,保护关联申请归属。
- `frontend/gas_admin/src/api/resources.ts`、资源契约:合同变更分类及“答复合同申请”详情操作。
- `apps/user_app/lib/ui/features/orders/contract_change_requests.dart`:申请表单、状态、答复、确认/取消及错误重试;`gas_contracts_page.dart`增加入口。
- `apps/user_app/lib/domain/models/gas_order_detail.dart`、`data/repositories/client_repository.dart`:类型适配、会话校验及请求方法。
- `apps/user_app/lib/ui/features/profile/profile_edit_page.dart`:头像刷新清理;`profile_page.dart`:图标调整。
## 验证与风险
Go全量测试、vet、API构建通过。Flutter全量105项测试及analyze通过,包含头像清空刷新、申请失败重试保持请求号、取消二次确认。图25/32共16组宽度及文字缩放截图检查通过,已查看390图片并更新并排对照,截图生成不等于视觉验收。
气站管理端contract同步/检查及构建通过,平台48资源契约检查通过。远程数据库回滚测试验证提交、气站两次幂等答复、用户确认,原合同未变化,测试申请整体回滚无残留。正常测试运行默认跳过该远程用例,显式HEQI_REMOTE_CONTRACT_REQUEST_TEST=1才启用。
新Web及Android调试包构建通过,API已切换至本次构建并继续连接远程数据库/缓存。浏览器390×844实际完成登录→合同→申请提交→待受理→取消二次确认→已取消,测试单`TK1788877123489796400`保留已取消审计记录,无待办残留。气站答复本次为真实远程回滚事务验证,未声称气站浏览器人工处理已经验收。浏览器预览地址为 http://127.0.0.1:18571/。
新增列旧记录默认0,普通工单继续按既有服务关系授权;关联申请保留原气站归属。数据库结构与新API需一同发布。Android/iOS真实相机、相册和文件保存对话框仍待真机验证。全量状态仍为15张部分实现、43张未完成对应页面、0张严格全功能与1:1验收通过。

View File

@@ -0,0 +1,42 @@
# 合同附件下载开发记录
## 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继续部分实现:下载代码已接通,但真实文件保存尚未完成设备验收;签署、家庭共享协议、合同服务和完整视觉仍待补。

View File

@@ -0,0 +1,66 @@
# 商品收藏开发操作日志
操作时间:2026-09-08。操作类型:新增和扩展。影响模块:Go用户Client API、Flutter商城/详情/个人中心、远程收藏表及设计验收记录。
## 操作前状态
已打开最新15-我的收藏原图,核对分类计数、收藏卡片、取消收藏、下架保留和加购;已阅读03需求及当前商城、购物车、迁移实现。仓库无收藏模型或用户接口,商城、详情和个人中心的收藏均是未开放入口。保留已有工作区变更,没有重置、提交或执行mock-data。
## 代码变更
| 文件(仓库相对路径) | 职责/位置 | 行数 |
| --- | --- | --- |
| backend/api/internal/models/ec_favorite.go | EcFavorite、唯一账户商品关系、revision | 新增17 |
| backend/api/cmd/cli/favorite_migration.go | migrateEcFavorite,单表事务迁移及9字段/表中文注释 | 新增30 |
| backend/api/cmd/cli/main.go | 新增migrate-ec-favorite命令与帮助 | 扩展原CLI |
| backend/api/internal/logic/client/user/favorite.go | 30行FavoriteState、52行SetFavorite、120行ListFavorites | 新增140 |
| backend/api/internal/logic/client/user/favorite_list.go | favoriteRows,按页批量关联商品、图片、分类及参数 | 新增81 |
| backend/api/internal/routers/client.go、client_test.go | 3条受保护路由及存在断言 | 扩展用户JWT组 |
| backend/api/internal/logic/client/user/favorite_test.go | 幂等、归档版本、所有权过滤、下架列表白名单及批量关联 | 新增138 |
| apps/user_app/lib/domain/models/product_favorite.dart | ProductFavoriteState和ProductFavorite,整数金额/协议校验 | 新增62 |
| apps/user_app/lib/data/repositories/client_repository.dart | 22行favorites、29行favoriteState、setFavorite和确认事件流 | 保留原接口 |
| apps/user_app/lib/data/services/api_client.dart | 116行captureSessionGuard,不暴露令牌的会话一致性检查 | 扩展共享HTTP工具 |
| apps/user_app/lib/ui/features/shop/favorite_button.dart | 初始化读取、条件收藏/取消、跨页面状态同步 | 新增152 |
| apps/user_app/lib/ui/features/shop/favorites_page.dart | 分类数量、管理取消、下架条目、加购重试 | 新增338 |
| apps/user_app/lib/ui/features/shop/shop_page.dart、product_detail_page.dart | 替换收藏占位按钮 | 接入共用FavoriteButton |
| apps/user_app/lib/ui/features/profile/profile_page.dart、lib/app/router.dart | 我的收藏入口及/favorites登录守卫 | 保留一级导航 |
| apps/user_app/test/ui/favorites_page_test.dart、test/data/favorite_test.dart | 分类/取消/加购、同步、账号迟到响应、分页契约 | 新增136/126 |
| apps/user_app/test/support/a1_fixture.dart、tool/a1_visual_test.dart | 测试收藏及图15多视口截图 | 测试数据不进入运行入口 |
| scripts/compare-user-app-a1.ps1 | 增加图15并排对照,现13组设计图 | 仅差异检查 |
## 服务端行为与迁移
- `GET shop/favorites`沿用page/page_size兼容分页;`GET shop/favorites/items/:identity`读取单品收藏状态;`PUT`提交favorite布尔值和读取时的revision。路径相对于`/heqi/client/v1/user`,均要求用户JWT。
- 每个账户和商品只有一条关系,取消设置status=3,收藏status=1;下架商品仍在收藏列表,不允许新增收藏或加购,但可以取消。已收藏的重复true/已取消的重复false无写入。
- revision由收藏公开UUID和正整数版本组成;同目标重试不递增,真实状态变化才递增。过期条件返回2404,不能通过旧请求复活已取消收藏。账户行锁串行写入,最多1000条有效收藏。
- 列表只返回商品公开标识、价格、图片、分类及实际参数,不暴露内部主键或其他账户数据。取消收藏不影响购物车和订单。
- 列表资料按当前页批量读取:商品、图片、分类、参数共四次查询,不随页面商品数量增加数据库往返。测试验证两商品主图/规格隔离、原列表顺序和每商品最多两条规格,避免N+1远程查询。
- 使用原有远程PostgreSQL配置执行`go run ./cmd/cli migrate-ec-favorite`两次均通过,验证定向迁移可重复执行。只新增ec_favorite及约束/注释;没有全库迁移、清库、初始化示例数据或本机数据库/Redis容器。
- ec_favorite是用户私有关系,不开放平台通用任意改写入口。资源契约同步与检查通过,平台公开资源仍为48个。
## 前端行为
- 游客点击收藏进入登录并保留站内回跳;登录后由用户再次明确点击执行写入。加载失败显示重试图标,未收到成功响应不伪造已收藏。
- 商城和详情共用FavoriteButton,仓储广播服务端已确认状态;迟到读取不能覆盖已确认的新状态,账号切换后旧响应不广播。
- 收藏页按后台真实分类展示数量,下架/缺货显示暂不可售。管理模式支持按当前分类全选后批量取消,失败后重读实际列表,不宣称全部成功。
- 收藏加购沿用购物车条件版本,结果未知时保留原绝对目标,当前页面重试不会再次累加。跨页面重建后的未知请求恢复仍是后续待完善项。
## 自动和远程验证
- Go全量`go test ./...`、`go vet ./...`、构建通过。定向测试覆盖8种收藏状态写入情形、缺少必填布尔参数和下架商品保留/公开字段。
- 批量读取改动后,收藏定向测试、相关包vet和重新构建通过;新增双商品四次资料查询的回归测试通过。运行API已切换到包含批量读取的新构建。
- Flutter analyze通过;完整84项用户端测试通过;布局调整后2项收藏交互测试再次通过。
- 图11/12/15/25在320、360、390、430宽度和1.0、1.3文字缩放下共32项布局检查通过。查看图15的390与320大字体截图后修正分类按钮及价格/加购排列,图15的8项复查通过,已重新生成并排图。
- Web Release和Android Debug构建通过。本机API12426运行新后端,18571提供新Web产物;Android测试包API地址为127.0.0.1,真机需adb reverse或使用可访问的API地址构建,不能仅凭构建通过声称已验收真机。
- 远程HTTP实测商品10收藏版本从`01a07f64-bbc6-7672-b49b-21ef882647b7:1`取消为`:2`;重复收藏保留原版本,旧请求返回2404,分页列表只出现一条该商品。匿名访问HTTP401。接口联调新增收藏已取消归档,没有更改商品价格、库存或上下架状态。
- 浏览器390×844实测游客点收藏后跳登录并回商品详情;再次点击后显示已收藏。个人中心“我的收藏”打开真实列表,显示全部1及对应分类1,价格10500分;从收藏加购后购物车新增该商品1件,合计20800分(含原有10300分商品)。随后浏览器取消测试收藏,HTTP复核收藏为空;测试加购条目已归档,原购物车仍为原有商品1件且已勾选。本轮没有创建或支付订单。
## 视觉核对与风险
原稿中的蓝色分类按钮、爱心、商品列表和价格/加购结构已按图调整。分类、金额和库存展示真实数据,原图的示例月销量没有后端口径,未编造。商品图片缺失仍显示空态,推荐区和精确素材/间距仍未完成,因此图15和全量验收继续failed。当前逐页状态为13张部分实现、45张尚无完整页面、0张通过严格1:1全功能验收。
本轮新增数据库表有外键与唯一约束;后续数据维护必须保留账户隔离和归档事实。批量取消为逐项条件操作,存在局部成功时通过重新加载展示。原生相机/语音及iOS设备仍未在本轮验收;Android构建仍提示speech_to_text/tobias未来Kotlin插件兼容警告,当前不影响构建。
## 维护指南
后续销量、推荐或优惠应由所属业务服务提供可信数据,不能直接复制设计稿数字。收藏字段、版本和路由变化须更新本日志、项目文档及契约,继续验证重复/过期请求、下架保留、账号切换和分页。数据库部署仅运行定向迁移,不用全库迁移代替。

View File

@@ -0,0 +1,37 @@
# 商品详情开发日志
操作时间:2026-09-08。操作类型:新增及兼容扩展。影响模块:图11商城、图12详情、图14结算及游客登录回跳。
## 操作前后
原商城只能直接购买,没有独立商品详情。现在点击商品图片或名称进入 `/products/:identity`;游客可直接查看,购买时先登录,登录后保留商品和数量进入结算。原商品购买按钮继续直接进入结算,已有调用不删除。
新增 `GET /heqi/client/v1/user/public/products/:identity`,查询启用且未删除商品,允许查看零库存商品;图片、属性只读取该商品启用记录并按后台顺序排列。白名单返回identity/name/price_amount/stock_quantity/category_name/images/attributes,不返回内部主键,不查询订单。不存在或下架返回1112,客户端显示“商品已下架或不存在”;首次联调发现通用500后已修正并实测。
详情支持后台图片翻页、缩放预览、参数、数量1—min(库存,999)、售罄禁购及加载重试。金额使用整数分。结算仍重新查询商品价格与库存,提交由服务端校验,不信任详情页数据。直接打开详情或结算也有可用返回入口。
## 代码职责
- `backend/api/internal/logic/client/user/product_detail.go`:`PublicProduct` 公开详情;新增文件,无模型迁移。
- `backend/api/internal/routers/client.go`:注册匿名详情路由。
- `apps/user_app/lib/domain/models/product_detail.dart`:公开字段、图片/属性集合、金额与库存校验。
- `apps/user_app/lib/data/repositories/client_repository.dart`:`productDetail` 匿名读取、图片地址解析、中文错误映射。
- `apps/user_app/lib/ui/features/shop/product_detail_page.dart`:详情图片、参数、数量、售罄、购买入口。
- `shop_page.dart`:图片/名称打开详情;游客购买使用根级登录跳转,解决页面内push后登录刷新停留问题。
- `checkout_page.dart`、`app/router.dart`:向后兼容的initialQuantity默认1,解析站内数量参数,结算重新读价。
- `test/ui/product_detail_page_test.dart`、`test/data/product_detail_test.dart`、`test/app/router_test.dart`、后端`product_detail_test.go`:页面、数据、鉴权回跳及公开数据边界。
- `tool/a1_visual_test.dart` 与 `scripts/compare-user-app-a1.ps1`:加入图12的8组截图及并排图。
## 验证
Go全量测试、vet、build通过,修改不存在错误码后两项详情专项复测通过。Flutter全量72项通过,新增数据解析/错误映射2项定向测试通过;analyze无问题,Web Release构建通过。平台contract:sync/check通过48个资源。图12的320/360/390/430宽、文本1.0/1.3共8组截图及溢出检查通过;已实际查看390截图和设计源图,严格1:1未通过。
远程只读接口:商品 `00000000-0000-7000-8000-000000002015` 返回“示例配送商品10”、10500分、库存30;该商品没有图片和参数,按空状态展示,没有把设计稿气瓶图冒充其真实商品图。不存在商品实测code=1112。
浏览器:新构建以游客打开真实详情,选2件,点击立即购买跳登录,测试账户登录后进入同一商品结算,数量2、应付¥210.00。没有提交订单、修改库存、支付或修改数据库。API仍使用原远程PostgreSQL与Redis,本机仅API/Web进程。
## 差异与风险
当前商品模型没有可选规格组合、月销量、押金、配送承诺和售后保障字段,因此只展示后台实际参数。收藏、客服和购物车入口继续明确说明未开放;尚未实现加购及分享。图片列表和参数接口已存在,但真实商品内容需要平台维护,不能填入与商品无关的样例。
整体更新为11张部分实现、47张尚无完整对应页,0张严格全功能与1:1通过。新详情不等同于完整商城闭环。

View File

@@ -0,0 +1,50 @@
# 用户端地址管理开发与验证
操作时间:2026-09-07。操作类型:扩展。影响模块:用户地址、个人中心、商城下单。
## 变更前后
此前地址入口只弹出详细地址输入框,缺少列表、联系人、编辑、删除和默认切换;商城直接使用第一条地址和账户联系人。本次增加 `/addresses` 管理页及编辑页,下单显式选择地址,收货联系人随地址保存。
图 29 的顶部添加、地址卡片、默认标签、编辑区、服务说明和底部新增按钮均有对应组件;服务范围尚无可用的配置/判定契约,当前明确显示待气站确认,不能计作该项完成,也不把服务关系存在当作可配送证明。
## 代码与接口
- `apps/user_app/lib/domain/models/shipping_address.dart`:地址领域字段与列表手机号脱敏。
- `apps/user_app/lib/data/repositories/client_repository.dart`:新增 `shippingAddresses`、`saveShippingAddress`、`setDefaultAddress`、`deleteAddress`;保留旧 `addresses` 和 `addAddress`。
- `apps/user_app/lib/ui/features/address/addresses_page.dart`:列表、失败重试、默认切换、编辑及下单选择。
- `apps/user_app/lib/ui/features/address/address_edit_page.dart`:联系人、电话、地址、可选坐标、表单校验、稳定新增请求号、删除确认、未保存退出确认。
- `profile_page.dart`、`profile_edit_page.dart`、`shop_page.dart`、`app/router.dart`:接入管理和选择流程。
- `backend/api/internal/logic/client/user/address.go`:新增、更新、归档、设置默认;先锁当前账户行,再查地址归属及写入,事务失败回滚。列表函数仍在 `address_ticket.go`,旧工单逻辑保留。
- `backend/api/internal/models/user_address.go`:新增 `contact_name`、`contact_phone`、`request_no`;请求号不进入响应。
- `backend/api/cmd/cli/address_migration.go`:`migrate-user-address` 只执行上述三个新增字段及中文列注释,不运行全库 AutoMigrate、初始化或 seed。
| 方法 | 相对于 `/heqi/client/v1/user` 的路径 | 行为 |
| --- | --- | --- |
| GET | `/addresses` | 本账户未归档地址;兼容原数组结构 |
| POST | `/addresses` | 新增;可选 request_no 在本账户范围内幂等 |
| PUT | `/addresses/:identity` | 更新本人有效地址及独立联系人 |
| POST | `/addresses/:identity/default` | 原默认与新默认在同一事务切换 |
| DELETE | `/addresses/:identity` | 归档并取消默认;重复删除成功,订单快照保留 |
新增/更新字段:address、contact_name、contact_phone、longitude、latitude、is_default。新增还接受 request_no。省略联系人时兼容旧客户端,采用地址原值或账户值;历史空联系人在新页面要求补齐。坐标允许同时为空;有值时必须成对、有限且经度在 ±180、纬度在 ±90 内。新增重试返回原地址,不把后续已变更的默认状态重置。
## 环境与验证
- 本机 Go API 使用既有 `heqi_dev.yaml` 的远程 PostgreSQL、Redis;未使用 Docker 或本机数据库。新增三列的定向迁移已执行成功,旧行保留。
- 远程测试账户完成新增、同请求号重试、联系人持久化、编辑、设置默认、重复删除;测试地址已归档,原默认地址及列表数量已验证恢复。
- 用户端完整回归 52 项通过;地址专项覆盖空表单、失败草稿、同请求号重试、默认设置失败不假更新、删除确认。后续样式修改再跑地址专项通过。
- 后端专项验证坐标边界、他人地址拒绝、默认变更失败回滚、创建重试不重复写入。全库测试发现新字段缺少源代码中文注释,补齐后模型与用户逻辑测试通过。
- 资源契约同步与检查通过,48 个资源;新增 Client 路由有注册测试。
- 图 29 已生成 320、360、390、430 宽度及 1.0/1.3 文字缩放共 8 张截图,检查滚动后无溢出;截图是独立 Fixture,不是运行时数据。
- 最终 Go 全量测试、vet 和 Flutter 静态检查通过,Web 正式构建成功。浏览器已验证鉴权回跳、新增、编辑保存及列表真实刷新,并在 390×844 下查看实际页面。旧预览进程已停止后重新启动本机 API 与 Web;远程连接配置保持一致。
- 浏览器随后验证默认切换、恢复原默认及删除确认,最终只剩原地址;控制台无 error/warn。商城专项 `shop_address_selection_test.dart` 通过,确认前不写订单,提交选中地址的联系人,而非账号姓名/手机号。累计现有用户端 52 项加此专项 1 项通过。
- 视觉证据:[图 29 并排对照](视觉验收/A1/29_并排对照.png)。原稿左侧、实现右侧,仍有地图图标、字号及服务范围显示差异,当前不通过严格 1:1。
## 风险与剩余事项
本次核心文件行数:地址后端逻辑 173 行,地址模型 21 行,定向迁移 42 行,地址列表页 240 行,编辑页 232 行,地址领域模型 40 行。现有 CLI 扩展命令、Client 路由新增 3 条,资源契约生成物已同步;未添加新的运行依赖。
删除采用归档而非物理删除,不修改旧订单的地址快照;删除默认地址后不会自行选择另一地址。旧联系人为空的地址可以保留和设为默认,但下单选择时需先补齐联系人。坐标当前为手动录入,尚未接入地图定位;配送范围判定、原生端完整验证仍未完成。页面局部图标、字体与原稿仍需继续对齐,不能以接口或截图检查通过声称严格 1:1。
维护时使用现有远程开发环境配置运行 `go run ./cmd/cli migrate-user-address`,切勿为这一功能运行全库迁移。测试地址只使用指定开发测试账号,验证后归档测试记录并恢复原默认。新增接口的所有权校验必须保持在默认状态写入之前。

View File

@@ -0,0 +1,61 @@
# 用户端 App 头像与视觉纠偏
操作时间:2026-09-07。
操作类型:扩展及缺陷修复。
影响模块:用户端个人中心、个人资料、登录品牌、商城图片、头像上传及资料更新。
## 核对结论
用户指出的问题成立。此前没有图 41 的个人资料页和头像上传入口,多个一级入口只是未开放提示;布局、品牌图标、宣传图片和商品图片也没有达到 1:1。此前“已实现”的口径过宽,现按实际业务能力记录,不能将构建成功或截图生成视为验收。
| 设计范围 | 实际能力 | 仍未完成的设计功能 |
| --- | --- | --- |
| 01 登录 | 密码/验证码接口、密码显隐、发送冷却、忘记密码、会话、真实协议读取;品牌改为原稿像素 | 真实短信渠道及协议同版本同状态验收;表单尺寸仍有差异 |
| 03 首页 | 真实服务归属和已发布内容、导航及维修申请入口 | 设备遥测、扫码绑定、蓝牙、分组、阀门控制及各安全详情 |
| 11 商城 | 公开商品、后台分类、搜索、价格库存、单品确认下单;宣传图复用原稿 | 购物车、收藏、完整商品详情和多商品结算;远程多条商品未配置图像,不能冒用参考样例 |
| 20 订单 | 气瓶/商城/工单列表、退款记录、服务端允许的支付/退款操作 | 设计中的完整详情、配送轨迹、发票和售后闭环 |
| 25 个人中心 | 钱包、资料/头像编辑、订单、合同、地址新增、维修和退出 | 设置、消息、押金、优惠券、家庭共享、紧急联系人、用气统计、收藏、发票、客服/关于独立页;地址管理目前仍只是新增弹窗 |
| 41 个人资料 | 选图、预览、上传、昵称保存、错误重试、取消草稿、返回刷新、真实服务归属和默认地址 | 手机换绑、性别、生日、实名认证状态及证件脱敏字段;不能用图中演示认证冒充用户事实 |
## 代码与行为变化
- `apps/user_app/lib/ui/features/profile/profile_edit_page.dart`:新增资料页、`_chooseAvatar`、`_save`、`_leave`。支持相机/相册;2MB、JPG/PNG 检查;保存失败保留草稿,重试复用已上传 URI;退出确认。
- `apps/user_app/lib/app/router.dart`:新增受登录守卫保护的 `/profile/edit`。
- `apps/user_app/lib/ui/features/profile/profile_page.dart`:头像资料行可点击;保存返回后刷新服务端头像;分组标题、行顺序、分隔线和图标调整。
- `apps/user_app/lib/ui/features/profile/profile_avatar.dart`:头像增加可配置尺寸,保留加载错误回退。
- `apps/user_app/lib/data/services/api_client.dart`:增加鉴权 multipart 上传,统一处理会话失效和后端错误。
- `apps/user_app/lib/data/repositories/client_repository.dart`:新增上传/保存资料;同 API 域名的图片绝对路径可正确解析。昵称保存省略头像时不覆盖旧图。
- `backend/api/internal/logic/upload/avatar.go`:头像写入登录客户端和账户摘要对应的目录;`OwnsAvatar` 拒绝跨账户、跨客户端、伪造及穿越路径。旧 URI 仍可读取。
- `backend/api/internal/logic/client/user/auth.go`:资料更新保留省略的头像;新头像只能引用本人受控上传文件;纯空白昵称被拒绝。旧头像原值和显式清空兼容。
- `apps/user_app/lib/ui/core/reference_image.dart`、`assets/design/`:保留用户提供的两张原 PNG,只在品牌和宣传位显示指定图像区域。未用整张截图替代页面;表单、价格、账户和交互均为真实 Flutter 组件。
- 新增 `image_picker` 及平台实现依赖;iOS 加入相机/相册用途说明。数据库模型和 API 路由未变,无迁移。
## 验证证据
关键代码定位:`profile_edit_page.dart` 新增 399 行,选图 `_chooseAvatar` 第 64 行、保存 `_save` 第 136 行;`profile_page.dart` 的 `_editProfile` 第 44 行;`api_client.dart` 的上传方法第 148 行(新增 13 行);`avatar.go` 的 `OwnsAvatar` 第 109 行(新增 28 行、替换 1 行);`auth.go` 的 `UpdateProfile` 第 148 行。行数是当前快照,后续格式化后以符号名定位。
资料更新请求仅提交实际编辑内容:
```dart
await widget.repository.updateProfile(_name.text, avatar: _uploadedUri);
```
- Flutter 全量 50 项测试通过。新增测试覆盖 multipart 鉴权、过期、超限、相对图片路径、头像选取取消、保存失败重试、昵称校验及草稿退出。
- Go 全量测试、vet、构建通过。资料 SQL Mock 验证省略头像不覆盖旧值、跨账户拒绝、旧 URI 保留和空昵称拒绝。
- 平台契约检查 48 个资源通过。
- 六页、四种宽度(320/360/390/430)、两种字体缩放(1.0/1.3)共 48 项截图及溢出检查通过;已打开实际截图与原稿查看,严格视觉验收仍不通过。
- 浏览器实测发现 Web 构建缓存中的插件注册文件未更新,首次选图失败。已定位到生成文件缺少 `ImagePickerPlugin.registerWith`,通过失效对应的 `web_entrypoint.stamp` 重新生成,不手改生成源码。
- 修复缓存后,浏览器系统文件选择器实际选入测试 PNG;预览变更,点击保存后返回个人中心并显示新图。再次调用真实 API 确认资料 URI 属于 owners 目录、受保护图片 GET 返回 HTTP 200、88 字节。随后恢复测试账户原昵称与头像,未留下演示头像替代用户资料。
- 共享组件 3 项、工作人员 App 21 项回归通过;用户端蓝色描边按钮、10dp 圆角和无胶囊选中背景的底栏样式仅对 consumer 品牌调整。列表触控高度保留 48dp,部分设计图等比缩放后的行距低于这个尺寸,因此不能以压缩点击区域换取截图一致。
- 远程数据库与 Redis 沿用既有 dev 配置。本次没有启动本地数据库,没有执行迁移、种子或清库。
- 最终 Web Release 构建通过、用户端 analyze 无问题。Android 构建未通过:在线解析 Kotlin `kotlin-build-tools-compat:2.3.20` 出现 Maven TLS 握手失败,正常 HTTPS 补下载也失败;离线构建确认 `androidx.profileinstaller:profileinstaller:1.3.1`、`androidx.core:core-ktx:1.13.1` 等依赖未缓存。没有降低 TLS 校验,不能宣称 APK 或原生相机验收通过。NDK 28.2、Build-Tools 36、CMake 3.22.1 已由标准 SDK 构建流程安装;未改数据库环境。
## 风险与维护
- 所有尚未开放项继续保留可见入口,按照用户此前决定展示明确未开放提示;不计为已完成。
- 原图的固定宣传内容作为随包静态素材;真实商品图片仍由后台提供,不根据名称猜测图片、不覆盖远程商品记录。
- 实测远程 10 条商品中,9 条没有图片 URI,另 1 条 `/mock/products/lpg-15kg.png` 返回 HTTP 404;前端路径解析修复不能补造不存在的后台文件。
- 上传成功但资料保存失败会保留文件以便重试;文件清理需要后续按引用关系和保留期实现,不能直接删历史资源。
- 增加插件后需要确认 Web 生成注册文件包含插件,避免仅凭 Flutter 构建返回成功判定功能有效。
- 个人资料页下拉刷新时,若存在草稿、正在选图或正在保存,保留当前草稿,防止昵称或选图被旧服务端值覆盖;保存失败重试测试同时覆盖该行为。
- 原头像可读兼容;出于权限修复,新 URI 不再允许任意跨账户引用。

View File

@@ -0,0 +1,45 @@
# 用户端 App 工单详情与操作日志
操作时间:2026-09-07。操作类型:扩展、修复。影响模块:Flutter 用户端、Go 用户工单 API。
## 操作前后
原报修标签只有只读记录,确认和取消虽已有接口但未接入页面,重复提交动作返回错误,归档记录没有被动作查询排除。
新增 `/tickets/:identity` 独立页面,由订单的报修标签进入。详情重新查询本人列表,展示编号、中文状态、服务类型、描述、地址快照、预约时间、开始处理时间、结果和完成时间。只展示已存在的时间,不生成受理或工程师到达记录。返回后列表刷新。
用户先确认,再调用取消或完成接口。失败保留详情并允许重试;成功重新读取状态和许可动作。后端事务锁定本人工单;取消沿用既有32/18/11/21/34范围,22重复成功;确认仅允许34,23重复成功并保留首次完成时间。归档、越权及其他状态拒绝。列表增加 `status_name` 和 `allowed_actions`,兼容原字段并移除内部主键。
## 核心文件
| 文件 | 关键位置及职责 |
| --- | --- |
| backend/api/internal/logic/client/user/address_ticket.go | 第80行 ListTickets 增加展示契约;第100行 ticketState 集中已有许可;第128行 changeTicketState 处理事务、所有权、状态和幂等 |
| backend/api/internal/logic/client/user/ticket_actions_test.go | 新增10种动作边界、终态许可、列表归属和内部ID剥离测试 |
| apps/user_app/lib/domain/models/service_ticket.dart | 第5行 ServiceTicket 适配真实字段与本地时间,未知状态不自行授权 |
| apps/user_app/lib/data/repositories/client_repository.dart | 第115行 ticket 兼容列表读取详情;第124/128行取消与确认请求 |
| apps/user_app/lib/ui/features/tickets/ticket_detail_page.dart | 新增详情;第24行 _act 控制确认、失败和刷新;第185行 _field 对齐原稿左右字段布局 |
| apps/user_app/lib/app/router.dart | 增加受已有登录守卫保护的工单路由 |
| apps/user_app/lib/ui/features/orders/orders_page.dart | 报修记录可点击,详情返回刷新 |
| apps/user_app/lib/ui/core/widgets.dart | RecordCard 优先使用服务端中文状态,保留旧状态回退 |
| apps/user_app/test/ui/ticket_detail_page_test.dart | 取消确认不写、失败不丢详情、重试成功刷新、终态动作消失 |
| apps/user_app/test/support/a1_fixture.dart、tool/a1_visual_test.dart | 独立测试工单;图42八组截图,不作为运行时数据 |
| scripts/compare-user-app-a1.ps1 | 纳入图42并排对照 |
没有新增运行依赖、后端路由或数据库字段,本阶段无需迁移。后续照片、人员与预约能力仍应沿用既有工单模型和服务端权限边界,不将前端演示数据写入业务表。
## 验证结果
- `go test ./...`、`go vet ./...`、API构建通过;追加列表契约测试后,`go test ./internal/logic/client/user -run Ticket -count=1` 通过。
- Flutter 全部57项测试通过;布局调整后两个工单动作测试再次通过。`flutter analyze --no-pub` 无问题,Web release构建通过。
- 图42在320/360/390/430宽度和1.0/1.3文字缩放共8项截图与滚动溢出检查通过。已实际打开原图和390截图,不能解释为1:1通过。
- 本地 API 连接原配置的远程 PostgreSQL、Redis;未启动或使用本机数据库/缓存,未执行迁移、清库、种子或容器操作。
- 远程测试账号创建临时工单 `TK1788792440299487600`,初态待受理、许可cancel。浏览器从报修列表进入,查看真实描述,确认取消,详情变为已取消、按钮消失;返回列表也为已取消。只操作本次临时工单,未改原MOCK-TICKET-001。临时记录保留为取消状态,不物理删除。
- 浏览器 error/warn 控制台为空。真实完成确认没有通过篡改工作人员工单状态来制造测试数据,当前证据为SQLMock与Widget测试。
- 测试期间修复确认弹窗背后的多余加载动画;发送请求时才显示进度。调整初版字段上下布局为左右布局,长地址自然换行。
## 视觉与功能差距
图42仍缺现场照片、工程师资料与受控电话、完整历史进度、预约改期、补充资料、紧急联系链路。图05仍是旧文字报修弹窗,未实现三步表单、照片及采集时间/定位、语音和草稿;创建接口的完整幂等与表单快照也待该阶段处理。此次只是详情和已有动作闭环,不能算完整报修功能或严格还原。
当前58图统计更新为9张部分实现、49张尚无对应完整页面、0张严格全功能与1:1通过。维护时先核对05/42原图和跨端工单字段,扩展上传必须保护证据所有权和访问权限;不能把设计中的样例照片当作用户提交证据。

View File

@@ -0,0 +1,45 @@
# 用户端 App 报修提交日志
操作时间:2026-09-07。操作类型:扩展、修复。影响模块:Flutter 用户端报修、Go 工单创建、cs_ticket三个字段。
## 本次变化
个人中心和首页报修入口原来打开只有描述的弹窗,现在进入 `/repair`,按故障信息、联系与地址、确认提交分三步。故障可选阀门、报警器、泄漏、其他;描述必填,地址必须有完整联系人;预约时间选填且必须在将来。确认前不写工单,上一步和地址页返回保留输入。发送期间禁止重复点击,未知结果冻结原请求并使用同一UUID重试;明确校验错误后可返回修改。
后端保存fault_type、contact_name、contact_phone。联系人由当前用户地址生成快照,兼容历史地址时回退本人账户;不接受其他账户地址。创建在账户行锁事务内执行,同一用户相同request_no返回首次工单,地址归档或预约时间已过不影响重复请求。首次创建拒绝空白描述、空白/超过128字符请求号、非法故障枚举、过去预约时间;服务归属数据库错误不再被忽略。旧category/description请求兼容。
## 文件与职责
| 文件 | 主要改动 |
| --- | --- |
| apps/user_app/lib/ui/features/tickets/repair_page.dart | 新增三步表单、地址/时间选择、确认、失败保持、离开提示 |
| apps/user_app/lib/ui/features/profile/profile_page.dart | _createTicket由文字弹窗改为导航 |
| apps/user_app/lib/app/router.dart | 新增/repair,沿用登录守卫 |
| apps/user_app/lib/data/repositories/client_repository.dart | submitRepair返回工单UUID,保留旧createTicket |
| apps/user_app/lib/domain/models/service_ticket.dart | 故障枚举中文映射 |
| apps/user_app/lib/ui/features/tickets/ticket_detail_page.dart | 显示故障类型与提交时联系人快照 |
| backend/api/internal/models/cs_ticket.go | 新增fault_type、contact_name、contact_phone,默认空字符串,旧记录不回填 |
| backend/api/internal/logic/client/user/address_ticket.go | CreateTicket事务、幂等、校验与快照 |
| backend/api/cmd/cli/address_migration.go、main.go | 通用定向字段迁移执行器与migrate-ticket-contact命令,无全表初始化 |
| backend/api/internal/logic/client/user/ticket_create_test.go | 重试、空值、非法枚举、地址越权回归 |
| apps/user_app/test/ui/repair_page_test.dart | 分步校验、地址返回、确认前零写入、未知结果同UUID重试 |
| apps/user_app/tool/a1_visual_test.dart | 新增05,多尺寸截图仍是独立Fixture |
| frontend/platform_admin/src/contracts/platform-resources.json | 通过同步脚本更新新增工单字段 |
## 实际验证
- Go全包测试、vet、CLI和API构建通过;新增创建测试后Ticket相关测试通过。
- Flutter58项测试通过,analyze无问题,Web release构建通过。
- 05与42分别在320/360/390/430宽度及1.0/1.3文本缩放检查,共16项截图/溢出检查通过,已打开05原图与实现截图,差距仍明显,未通过严格1:1。
- 已在既有远程数据库执行migrate-ticket-contact,只增加三个字段及中文COMMENT;事务锁超时5秒。未修改旧工单内容、未运行全库迁移或种子,未使用本机PostgreSQL/Redis容器。
- contract:sync和contract:check通过,48个资源。
- 远程临时地址与工单 `TK1788793274954000000` 验证:故障、联系人、地址、预约快照一致;地址归档后重复提交返回同一UUID,列表仅一笔;工单取消及重复取消均成功。临时地址已归档,工单保留取消状态,原地址及原工单未修改。
- 浏览器验证登录回跳/repair、空描述拦截、输入后进入联系地址、打开真实地址列表、返回及上一步保留输入;控制台error/warn为空。当前原地址缺联系人,未为了浏览器测试改写用户原地址。成功提交路径证据为Widget测试加真实API验证,并非浏览器整条提交验收。
## 未完成与风险
现场照片仍是可见的未开放入口,未声称上传可用。语音、采集定位、原始照片时间、持久化草稿和跨重启请求恢复尚未实现。预约目前是用户请求时间,不代表气站已承诺时段;照片与工程师完整链路也未完成。下一阶段需专用受控上传和工单证据授权,不能使用头像接口或把原图示例照片写成真实证据。
字段迁移是向后兼容的加法,回退旧API时可保留列;不要删除列损失已保存快照。新增联系人会包含个人信息,沿用本人Client访问与后台脱敏保护。维护时保留首次请求号语义,结果未知时不能重生成号自动重发。
当前10图部分实现、48图尚无对应完整页面、0图严格全功能1:1通过。操作日志记录的是本阶段实际事实,不缩小58图总目标。

View File

@@ -0,0 +1,45 @@
# 用户端 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通过。远程数据库保存证据记录不代表多实例共享文件存储已部署;后续迁移必须保留资源归属与受保护读取。

View File

@@ -0,0 +1,38 @@
# 用户端 App 报修草稿操作日志
操作时间:2026-09-07(开发环境时区)。操作类型:扩展。影响模块:图05报修表单、本人照片读取。
## 操作前后
原先页面销毁会丢失表单和请求号。现在生产依赖注入 `SecureRepairDraftStore`,按 API 地址与认证账户隔离保存;照片先上传,草稿只保存 URI。点击暂存退出才离开,失败保留表单。提交前持久化请求号与待确认标记,未知结果恢复后复用原请求号;恢复不自动提交,成功才尝试清理草稿。
未发出的草稿恢复时重新查询本人地址,已删除地址回到选择步骤;未知提交保留首次地址快照。照片或草稿损坏不会自动删除,用户明确清除前提示先检查已有工单。
## 关键代码
- `apps/user_app/lib/data/services/repair_draft_store.dart`:新建安全存储接口与实现,schema=1,只保留一个账户草稿。
- `apps/user_app/lib/ui/features/tickets/repair_page.dart`:`_loadDraft`(49行)、`_persistDraft`(173行)、`_saveAndExit`(194行)、`_next`(291行),扩展恢复、保存、清理及发送顺序。
- `apps/user_app/lib/app/dependencies.dart`、`router.dart`:注入存储;测试可显式不持久化。
- `apps/user_app/lib/data/repositories/client_repository.dart`:认证草稿所属账户、受保护照片字节读取。
- `backend/api/internal/logic/upload/ticket_photo.go`:`ServeOwnedTicketPhoto`(23行),只构造当前账户目录。
- `backend/api/internal/logic/client/user/ticket_photo.go`:`UploadedTicketPhoto`(34行),先校验登录用户。
- `backend/api/internal/routers/client.go`:新增第35行 GET `/ticket-photos/:name`。原有上传、工单照片和提交接口兼容。
- `test/data/repair_draft_store_test.dart`、`test/ui/repair_draft_test.dart`:隔离、恢复重试、写入失败、清理和损坏恢复覆盖。
- `tool/a1_visual_test.dart`:保留生产暂存入口的内存夹具。`scripts/compare-user-app-a1.ps1` 纳入图05并排核对。
仓库此前已有大量未提交变更,以上为本次职责范围;不把累积 Git 行数当作本次改动统计。没有新增依赖、数据库列、迁移或容器。
## 验证
- 用户端 analyze 无问题;全量63项测试通过后新增损坏草稿案例,草稿组件5项定向测试全部通过,另有安全存储隔离1项通过。
- Go `test ./...`、`vet ./...` 通过;新草稿图片读取测试覆盖本人200、他人404、路径穿越404、无效文件名404。`go build ./cmd/main` 通过。
- 平台契约同步与检查通过,48个资源。
- 图05的8组宽度/文本缩放截图通过;已实际打开设计源图及390像素实现图。步骤条、表单分区、照片占位和联系地址预览仍不同,严格1:1未通过。
- Web Release 构建使用 `--dart-define=API_BASE_URL=http://127.0.0.1:12426`。首次遗漏该参数导致浏览器连接模拟器默认地址失败,已重新构建修正。
- 浏览器真实验证:授权测试账户填写“草稿恢复浏览器验收:只暂存,不提交工单。”并选择既有蓝白验收图,暂存返回个人中心。完整刷新后重新登录同一账户,出现恢复提示;选择恢复后文字与照片均正确显示。API运行日志记录一次草稿照片读取、零次工单创建请求。验收结束通过“不保存”删除本次草稿。
## 风险和维护
草稿保存在当前设备及浏览器存储,不跨设备同步;暂存照片需要网络。删除本地草稿不会删除可能已关联工单的照片,未关联文件的过期清理仍需独立实现。提交已成功但本地清理失败时保留原请求号,下次重试由后端返回原工单,避免重复创建。
继续使用原远程 PostgreSQL、Redis,本机只运行 API 与 Web。语音、真实采集位置/时间、原生设备和完整设计还原仍未验收,不能将本次草稿完成等同于图05或全部58图完成。

View File

@@ -0,0 +1,23 @@
# 报修页面视觉对齐
操作时间:2026-09-08。操作类型:修改及扩展。影响模块:图05一键报修。
操作前:步骤为普通文字,故障类型和描述各自分散,照片只有一个添加按钮,第一步没有联系人预览。操作后:编号圆形步骤、统一白色故障分区、外置必填标签、三格照片区域;第一步可以打开本人地址选择,显示选中联系人和真实地址。没有虚构示例手机号、定位成功或故障照片。
## 文件与职责
- `apps/user_app/lib/ui/features/tickets/repair_layout.dart`:新增 `RepairStepHeader`、`RepairSection`、`RequiredRepairLabel`、`RepairContactPreview`。展示层无网络、上传或提交状态。
- `repair_page.dart`:引用上述组件,故障下拉、描述、照片置于同一分区;第一步地址入口复用 `_chooseAddress`。减少顶部与计数器占位,保持2000字限制。
- `repair_photos.dart`:每张实际照片占一格,其余格均可选图,总数仍限制3张。保留删除、预览、重复照片判断和选图忙碌保护。
- `test/ui/repair_page_test.dart`:选择入口改按可读标签定位,并验证初始三格;提交按钮按按钮类型定位,避免与步骤标题混淆。
- `docs/视觉验收/A1/05_*.png`:更新8组实际截图及设计并排图。
## 验证与限制
用户端64项全量测试通过,报修及草稿6项定向回归通过,analyze无问题。320/360/390/430像素宽、文字1.0/1.3共8组截图和溢出检查通过。已实际查看390普通文字及320放大文字截图,390视图中可见暂存按钮。窄屏放大文字时允许自然换行和滚动,不缩小用户文字偏好。
中途发现白色容器遮挡ListTile点击反馈,已为分区内部添加透明Material并复测。Web Release使用本机API地址构建;后端、远程数据库、缓存、公共接口均未修改,无迁移。
浏览器在390×844实际打开最终构建,三格照片和底部两个按钮均可见。点击第一步报修地址进入本人地址列表,看到现有真实地址及“待补充联系人”,随后返回报修页。本次没有修改地址、提交工单或写入数据库;完整地址选择后的提交由原报修组件回归测试覆盖。
语音、真实拍摄定位/时间、紧急电话入口、照片虚线和其他精细间距仍未完成。设计图中的故障实拍属于用户内容,不能作为生产默认照片。严格1:1状态继续为未通过;整体10张部分实现、48张无完整对应页的口径不变。

View File

@@ -0,0 +1,31 @@
# 报修语音输入操作日志
操作时间:2026-09-08。操作类型:扩展。影响模块:图05故障描述、系统权限。
## 实现
`speech_to_text 7.4.0` 调用设备系统识别服务;只在点击语音输入时初始化和申请权限。应用不保存录音文件,不向业务后端发送音频,系统识别服务可能使用网络。识别结果进入原故障描述,可在结束后校对编辑,再沿用既有草稿与报修提交接口。
`RepairSpeech` 接口隔离平台和组件测试;`SystemRepairSpeech.instance` 复用唯一系统实例,优先匹配设备提供的 zh-CN 语种。`RepairSpeechButton` 保存启动时的文本与选区,将本轮完整识别结果替换同一区域,避免中间结果重复追加。保留前后文字,按字符簇限制2000字,避免截断表情。拒绝权限、不可用、网络错误、无识别结果均有中文反馈,已有文字保留。
识别期间禁止下一步、暂存、地址切换及照片操作;用户可结束识别。初始化时的系统授权窗口可能触发 inactive,不能误判为切后台;paused、离页和50秒兜底超时会取消识别,迟到回调不再修改输入。
## 变更文件
- `apps/user_app/lib/data/services/repair_speech.dart`:系统单例适配、识别回调、停止与取消。
- `apps/user_app/lib/ui/features/tickets/repair_speech_button.dart`:文字选区保护、状态、权限错误与生命周期。
- `apps/user_app/lib/ui/features/tickets/repair_page.dart`:描述框内语音入口、识别中操作约束。
- `apps/user_app/android/app/src/main/AndroidManifest.xml`:麦克风权限及 RecognitionService 查询;显式禁用蓝牙识别支持,未额外申请蓝牙权限。
- `apps/user_app/ios/Runner/Info.plist`:麦克风和语音识别用途;相机/相册用途补充实际报修照片功能。
- `apps/user_app/pubspec.yaml`、`pubspec.lock`:新增speech_to_text及3项传递依赖,未升级其他既有依赖。
- `apps/user_app/test/ui/repair_speech_test.dart`:5项语音组件测试。
## 验证
analyze无问题,全量68项测试通过;随后增加权限弹窗/切后台边界,语音5项定向测试全部通过。8组图05视觉与滚动溢出检查通过,已打开390×844实际截图,语音按钮位于故障描述框右下。Web Release构建通过,API地址为127.0.0.1:12426。
Android Debug构建通过(174.4秒),产物 `apps/user_app/build/app/outputs/flutter-apk/app-debug.apk`,159209325字节。本次APK编译的API地址为127.0.0.1:12426,设备运行需通过adb reverse转发12426端口或重新构建指定设备可访问的API地址,不能直接把手机环回地址当开发电脑。该构建仍提示speech_to_text/tobias的旧Kotlin Gradle插件兼容性警告,未阻止当前构建;未来升级Flutter需复核。
原API/Web进程已退出且旧临时API文件不存在,已重新编译启动API与Web预览,仍读取原远程配置。浏览器重新登录测试账户后实际看到描述框中的语音输入入口,控制台无警告/错误;本轮未开启麦克风,没有采集现场声音、修改地址或提交工单。
识别平台能力以[插件官方说明](https://pub.dev/packages/speech_to_text/versions/7.4.0)为准。自动化测试注入可控识别结果,不等同于真实麦克风语音成功;Android/iOS设备和实际语音采集仍未验收。没有新增数据库字段、后端接口或迁移;PostgreSQL和Redis保持原远程配置。

View File

@@ -0,0 +1,52 @@
# 推荐商品开发与视觉检查记录
操作时间:2026-09-08。操作类型:新增、扩展和布局修复。影响模块:用户推荐API、购物车、收藏、商品详情返回刷新。沿用远程PostgreSQL与Redis,本轮没有数据库迁移、容器操作、全库初始化或商品资料写入。
## 操作前后
已打开并检查最新图13购物车和图15我的收藏。操作前购物车缺少“猜你喜欢”和换一换,收藏缺少底部推荐入口。操作后购物车显示真实推荐商品,收藏推荐入口打开可滚动弹层,均可查看详情、换一批及加购。实际价格、库存、图片来自既有后台,不用原图示例金额代替业务数据。
截图检查还发现320宽度、1.3倍字体时购物车金额会逐字换行,已改为金额独立一行。从推荐或已有购物车商品进入详情后返回会重读购物车,避免详情加购后合计仍显示旧值。
## 文件与职责
| 文件(仓库相对路径) | 关键函数与变更 |
| --- | --- |
| backend/api/internal/logic/client/user/recommendation.go | 新增90行,Recommendations、recommendationValues,归属过滤、分类排序、分页、批量图片与分类 |
| backend/api/internal/logic/client/user/recommendation_test.go | 新增96行,双入口归属/排序、分页、公开字段与非法参数回归 |
| backend/api/internal/routers/client.go、client_test.go | 新增受JWT保护的GET shop/recommendations和路由回归 |
| apps/user_app/lib/domain/models/product_recommendations.dart | 新增49行,ProductRecommendations校验分页与整数分金额 |
| apps/user_app/lib/data/repositories/client_repository.dart | recommendations;cart/cartItem/setCartItem补充会话一致性检查 |
| apps/user_app/lib/ui/features/shop/product_recommendations.dart | 新增283行,ProductRecommendationSection、showFavoriteRecommendations,读取、换页、条件加购和错误恢复 |
| apps/user_app/lib/ui/features/shop/cart_page.dart | build/_busy,内嵌推荐、加购时阻止结算、金额响应式布局、详情返回刷新 |
| apps/user_app/lib/ui/features/shop/favorites_page.dart | build增加推荐入口,关闭弹层后刷新收藏 |
| apps/user_app/test/ui/product_recommendations_test.dart | 新增195行,分页、未知加购重试、库存、结算阻止、详情返回与收藏弹层 |
| apps/user_app/test/data/product_recommendations_test.dart、cart_test.dart | 新增推荐契约与购物车旧账号迟到响应回归 |
| apps/user_app/test/support/a1_fixture.dart | 仅自动测试用推荐数据,不进入运行入口 |
## 接口行为
`GET /heqi/client/v1/user/shop/recommendations?source=cart&page=1&page_size=2`:source只接受cart、favorites;page范围1至10000,page_size范围1至20。未登录HTTP401。服务端只选择status=1、未软删除且stock_quantity>0商品,始终排除本人有效购物车,收藏场景再排除本人有效收藏。
同入口关联分类优先,其余按商品更新时间倒序、公开标识排序。通过GORM的clause.OrderBy.Expression绑定账户参数,避免Order(gorm.Expr)被忽略;表名只取固定枚举,禁止拼接用户输入。每页商品元数据只需一次图片和一次分类查询,返回字段白名单,不暴露内部ID。
客户端换一换读取下一页,末页回到第一页。加购读取购物车快照并提交绝对目标数量和原revision;未知响应在当前组件保留原目标,重试不重复加量,成功后重读购物车及推荐。加购期间禁用购物车结算与批量操作。401交由会话路由处理,旧账号迟到响应不更新当前界面。
## 验证与实际数据
- Go全量测试、vet、API构建通过;新增测试验证双入口SQL归属、分类排序实际生效、分页多读一条、主图与分类隔离、公开字段及空页/非法参数。
- Flutter analyze、全量90项测试通过;补充详情返回刷新后,购物车及推荐的7项定向测试再次通过。所有测试使用生产主题,Fixture不修改远程数据。
- 图13/15在320、360、390、430宽度及1.0/1.3文字缩放共16项布局检查通过;修复金额换行后图13的8项复查通过,并实际查看390普通、320大字体截图。并排对照已更新。
- Web Release与Android Debug构建通过;原生设备操作未据此声明已验收。Android仍有speech_to_text/tobias未来Kotlin插件兼容提示。
- 远程接口首批实际返回后台现有“示例配送商品10/9”,下一批8/7;原购物车1件商品被排除。临时收藏商品10后,favorites推荐排除它,测试收藏已取消恢复;未登录HTTP401。
- 浏览器390×844验证换一换、查看商品8详情、返回、推荐商品10加购:购物车由1件变2件,合计从10300分变20800分,推荐列表移除商品10。通过管理仅删除本轮新增条目,保留原商品1件;本轮未创建订单、支付或改变库存。
- 收藏页实际打开推荐弹层,显示真实价格与可操作的换一换、详情和加购入口;关闭正常,浏览器错误/警告日志为空。最终HTTP复核收藏为空、购物车仅原商品1件且已勾选,基线恢复通过。
- 最终详情返回修复已重新构建Web与Android Debug;API进程32148运行本轮后端,Web继续由18571提供。构建通过不代表原生设备验收完成。
## 视觉结果与剩余风险
严格验收仍为failed。58图仍是13张部分实现、45张无完整页、0张通过严格全功能1:1。商品图片为空或404、月销量无口径、押金与配送服务承诺尚未实现,卡片密度和精细样式仍有差异。图13推荐双列及图15推荐入口已补,不能据此声称整个购物车/收藏页面还原完成。
证据:[图13并排](视觉验收/A1/13_并排对照.png)、[图15并排](视觉验收/A1/15_并排对照.png)、[320大字体修复](视觉验收/A1/13_320_1.3.png)。图片缺失保留明确提示,不把设计截图当成真实商品照片。未知加购结果只在当前组件保留;跨页面重建恢复、全商品图片运营配置、其余45页仍需继续实现。
维护时扩展推荐条件应更新双入口归属测试,继续使用字段白名单和参数绑定;不可把推荐服务改成客户端上传完整私有购物车。测试单独执行`flutter test test/ui/product_recommendations_test.dart test/data/product_recommendations_test.dart`,Go使用`go test ./internal/logic/client/user ./internal/routers`。

View File

@@ -0,0 +1,38 @@
# 支付密码开发与验证记录
操作时间:2026-09-08
操作类型:扩展、修复
影响模块:用户设置、钱包密码、各业务端共用验证码与支付密码校验。
## 操作前后
设置中的支付密码原为未开放入口。现接通`/settings/payment-password`,读取当前钱包的`payment_password_set`,区分首次设置、旧密码修改、验证码找回;状态缺失进入错误重试,不能推断为未设置。密码限定六位数字、二次确认、请求中禁止重复提交,错误保留表单,仅收到`changed=true`才提示成功。
后端更新增加旧散列条件,防止并发覆盖;密码散列不进入SQL日志。输错计数与十五分钟锁定改为Redis原子脚本,五次失败后拒绝正确密码;缓存不可用也拒绝验证。验证码绑定客户端、手机号及用途,并在同一原子操作中校验和消费,防止并发重复使用。成功重置后清除本人锁定;若清锁失败,响应独立返回`lock_cleared=false`,页面明确区分密码已更新与锁仍可能生效。
## 短信限制
仓库仅有Mock验证码写入Redis,没有真实短信供应商。用户确认不知道现成配置路径;不重复索要密钥,也未擅自接入付费服务。接口保留原字段并新增`delivery_mode=mock`、`delivery_status=not_sent`及`retry_after`,关闭Mock时返回2410“短信验证服务尚未配置”。支付密码和注册页面不再把请求建立描述为短信已发送。首次设置与找回已通过隔离Mock联调,但真实手机收码仍未完成,不能计为生产可用短信流程。
## 代码与接口
- `apps/user_app/lib/ui/features/settings/payment_password_page.dart`:新增页面;`_load`状态读取、`_sendCode`用途及冷却、`_save`明确响应确认。
- `apps/user_app/lib/data/repositories/client_repository.dart`:`wallet`、`requestPaymentPasswordCode`、`setPaymentPassword`增加会话保护,验证码手机号来自当前资料;不会接受页面传入钱包归属。
- `apps/user_app/lib/domain/models/client_models.dart`:可空密码状态及验证码请求结果模型,保持旧构造调用兼容。
- `apps/user_app/lib/app/router.dart`、`ui/features/settings/settings_page.dart`:受保护路由及设置入口;`register_page.dart`修正Mock提示。
- `backend/api/internal/logic/common/client_wallet.go`:`SetPaymentPassword`严格数字、锁感知验证、条件更新及清锁结果;原接口字段兼容。
- `backend/api/internal/logic/common/payment_password_guard.go`:抽出原共用校验并增加原子计数。
- `backend/api/internal/logic/common/client_auth.go`:短信未配置拒绝、交付元数据及验证码原子消费。
- 新增`payment_password_test.go`、`payment_password_remote_test.go`、`verification_availability_test.go`;Flutter新增`test/data/payment_password_test.dart`与`test/ui/payment_password_page_test.dart`。视觉工具增加`31-payment`,沿用明确测试数据,不从真实账户生成密码截图。
## 验证与风险
Flutter analyze及全量117项测试通过;页面8组320/360/390/430宽度、1.0/1.3文本缩放检查通过,已查看320放大截图无溢出。后端全量go test、go vet、API构建通过;新增短信不可用拒绝测试通过。
Web使用`--pwa-strategy=none`构建成功,Android调试包构建成功。浏览器加载新包后,支付密码深链跳转登录并在登录后回到原页面,读取真实已设置状态;空表单出现三处六位数字提示,找回模式正确切换为手机验证码,控制台无error/warn。未在真实用户钱包提交改密或发送验证码,成功变更由上述独立远程回滚测试覆盖。API进程39900监听12426,健康检查200;18571继续提供新Web产物。Android构建仍有既有插件Kotlin迁移提示,本轮未升级依赖,真机键盘及输入尚待验证。
显式开启`HEQI_REMOTE_PAYMENT_PASSWORD_TEST=1`的远程测试通过:独立临时用户与零余额钱包、首次设置、旧密码修改、验证码重置、错误格式、用途不匹配、16并发验证码仅一次成功、8并发错误密码触发五次锁定、重置解锁。数据库整体回滚后确认账户和钱包均不存在,仅清理本轮独立Redis键。没有修改真实账户支付密码、余额、数据库结构或远程缓存配置。
原子校验为共用逻辑,会影响所有调用支付密码或验证码的业务端,因此运行后端全量回归。Redis故障时相关验证不可用属于预期拒绝行为。网络中断后密码更新结果仍可能不确定,现有接口没有操作号查询;页面不把未知结果表述为密码未变更。
该子页没有独立一比一原稿,不把通用表单截图算作图31全量视觉验收。图31及全量App仍未完成严格1:1与全部功能验收,当前计数仍为16张部分实现、42张未完成对应完整页面、0张严格验收通过。

View File

@@ -0,0 +1,25 @@
# 登录输入连接修复记录
操作时间:2026-09-11
操作类型:修复
影响模块:用户端登录页验证码、密码输入及显隐切换。
## 问题与范围
钱包浏览器联调中,验证码/密码共用输入框曾出现键入未生效,控制台捕获Flutter Web输入配置操作空DOM的异常。编译栈与本地引擎`text_editing.dart`的`applyConfiguration`相符,但仅凭栈不能断定引擎是唯一根因。
代码同时存在可稳定复现的问题:点击已选中的“密码登录”也会清空用户刚输入的密码。本轮处理登录页输入连接切换,不改Flutter SDK、账户密码、数据库或缓存配置。
## 代码变化
- `apps/user_app/lib/ui/features/auth/login_page.dart`:密码字段按登录方式和显隐状态设置独立键;`_configureSecretInput`先失焦结束旧连接,再更新状态,必要时下一帧恢复焦点。显隐保留控制器文本,方式切换清除上个方式凭据;当前已选方式点击不再清空输入。
- 自动填充提示区分一次性验证码和密码,避免验证码框使用密码自动填充语义。
- `apps/user_app/test/ui/login_page_test.dart`:新增显隐、焦点、重复选择及有焦点时切换方式的回归测试。
## 验证
登录页8项测试通过,Flutter analyze无问题,Web构建完成。浏览器在12:06:23之后的新构建中实测:聚焦验证码框、切换密码模式、直接在遮蔽输入框键入授权测试密码、重复点击当前方式、填写手机号、登录成功回到钱包。该路径没有要求先显示密码才能输入。
控制台最后的输入空值异常时间为12:05:54,早于新构建;新登录路径后没有新增error/warn。因此本轮确认修复后的路径未复现,不把历史日志仍存在误判为新异常,也不推断所有浏览器和原生输入法已全部验收。
最终Flutter全量125项测试通过,Android Debug APK构建成功;没有后端代码、接口或资金变更,远程数据库与Redis继续沿用原配置。全量设计验收状态仍为17张部分实现、41张未完成对应完整页面、0张严格通过。

View File

@@ -0,0 +1,36 @@
# 用户端结算流程扩展
操作时间:2026-09-07。操作类型:扩展。影响模块:商城结算、库存事务与幂等恢复。
## 操作前后
原商城只能单件购买,以弹窗确认地址和金额。本次接入 `/checkout/:identity` 独立提交订单页面,选择地址、调整数量、填写配送备注、查看商品金额及合计,提交成功进入商城订单列表。游客登录回跳保留商品公开标识。图 12、14 原稿均已检查;本轮实现图 14 的基础结算链路,图 12 仍未实现,不能将商品摘要称作商品详情页。
## 关键代码
- `apps/user_app/lib/ui/features/shop/checkout_page.dart`:按标识加载商品和默认地址,数量范围 1 至 min(库存,999),提交前不写订单;结果未知时冻结原数量、地址、备注,重试沿用原请求号。价格或库存明确变化时允许刷新后再确认。
- `shop_page.dart`、`app/router.dart`:购买进入独立结算页,路由继续受登录保护。
- `data/repositories/client_repository.dart`:新增 `submitShopOrder`,保留旧 `createShopOrder` 方法兼容调用。
- `backend/api/internal/logic/client/user/shop.go`:可选 expected_payable_amount;依据数据库价格计算,报价不符回滚库存。校验单项数量 ≤999、最多100项及备注长度。乘加之前检查整数溢出。优先查找本人同请求号订单,地址随后归档或库存归零不影响成功请求的恢复。
- `backend/api/internal/logic/client/user/checkout_test.go`:金额按数量结算、报价变化回滚、溢出不扣库存、已创建订单不再依赖地址。
- `apps/user_app/test/ui/shop_address_selection_test.dart`:确认前不下单、选择地址联系人、数量两件与金额一致、失败冻结输入、同请求号重试。
## 接口兼容与环境
原 `POST /heqi/client/v1/user/shop/orders` 接受新增可选 `expected_payable_amount`(整数分);旧客户端可省略。客户端传入金额只用于确认,不代替服务端计算。错误 2401 表示价格变化,2402 表示库存不足或商品下架。错误对象在包初始化注册,避免并发请求修改 SDK 全局错误表。
本轮不修改数据库表,不运行迁移或 seed。本机 API 继续使用远程 PostgreSQL、Redis;没有启动本机数据库/缓存容器。
## 验证
- Go 结算专项通过,SQL Mock 验证失败时回滚,不连接真实数据库。
- 远程指定开发账户对 `MOCK-EC-PRODUCT-010` 验证错误报价拒绝、两件金额、备注持久化、重复提交恢复同一订单及库存只扣一次。临时订单已取消,库存恢复,未支付或配送。
- Widget 结算流程通过;图 14 已生成四种手机宽度与两种文字缩放的 8 张截图,检查滚动后无溢出。
- 用户端全量 53 项测试、Flutter 静态检查、Go 全量测试及 vet 通过;Web 最新构建成功。[图 14 对照](视觉验收/A1/14_并排对照.png)继续用于记录缺项,不是通过证明。
- 浏览器验证登录回到指定商品结算、数量由1变2时金额由105元变210元、打开地址选择后返回仍保留数量;390×844实际页面已核对。真实创建/取消验证由 API 完成,浏览器未再次创建订单。结算页285行、后端结算专项68行;无新增依赖。
## 未完成项与风险
图 14 中的预约配送、押金、优惠券、发票、结算前支付方式选择和多商品合并仍未接入。本页没有把设计示例金额当作真实收费规则。商品原图缺失仍需后台素材补齐;当前截图不通过严格 1:1。订单创建与付款分开,成功后进入既有订单页付款,不代表付款或配送已经成功。
单项数量/条目上限是本次输入保护,可能拒绝旧客户端超过上限的超大请求;正常用户端购买不受影响。后续购物车接入必须继续服务端计算总额,保留事务回滚与请求幂等测试。

View File

@@ -0,0 +1,35 @@
# 商城订单取消与收货
操作时间:2026-09-07。类型:扩展与状态边界修复。影响:用户商城订单列表、取消、确认收货。
## 变更前后
此前用户端仅显示支付和退款操作,即使已有取消/确认收货接口也没有对应入口。本次服务端通过 allowed_actions 发布 cancel、confirm_receipt,列表显示直接操作按钮,同时保留操作菜单;用户明确确认后调用接口,成功重新读取订单列表。
原确认收货只检查物流状态20,未校验订单业务状态;已取消订单残留物流状态时也可能被确认。现在在事务内锁定本人订单,仅业务状态18且物流状态20允许首次收货;物流30重试不改写时间。取消仅允许状态16,状态22重试返回成功且不再次返还库存。
## 文件与方法
- `backend/api/internal/logic/client/user/shop.go`:ListShopOrders、CancelShopOrder、ConfirmShopReceipt。已支付发货订单显示待收货,收货后显示已收货;仍保持原订单/物流双状态模型。
- `apps/user_app/lib/data/repositories/client_repository.dart`:cancelShopOrder、confirmShopReceipt,使用公开订单标识。
- `apps/user_app/lib/ui/features/orders/order_list.dart`:新增 onAction,显示取消/收货及去支付入口,保留菜单。
- `apps/user_app/lib/ui/features/orders/orders_page.dart`:复用原提交锁,二次确认、失败保留状态、成功刷新商城列表。
- `backend/api/internal/logic/client/user/order_actions_test.go`:八项状态/所有权/幂等场景,SQL Mock 验证不发生额外库存写入。
- `apps/user_app/test/ui/orders_page_test.dart`:增加取消与收货确认/返回/刷新测试,原退款跨标签刷新测试保留。
## 契约与兼容
继续使用原 POST shop/orders/:identity/cancel 和 POST shop/orders/:identity/confirm-receipt,未新增接口或表字段。allowed_actions 为增量字段值,旧客户端继续可读。客户端不按状态数字自行推断权限,服务端再次校验归属与实时状态。气瓶订单取消未在本轮开放;其分派、支付和履约模型需单独核对,不套用商城逻辑。
## 验证记录
- Go 全量测试与 vet 通过,八项新边界测试覆盖取消重试、已支付拒绝取消、越权拒绝、已取消拒绝收货、未发货拒绝、首次收货及重试时间保护。
- Widget 订单专项三项通过,包含原退款功能;Flutter 静态检查及 Web 构建通过。
- 远程开发环境创建一笔指定示例商品临时订单,列表已返回 pay/cancel;浏览器取消与库存恢复结果在后续条目记录。
- 浏览器已取消本轮临时订单,刷新后为“已取消”且取消/支付入口消失。公开商品接口确认指定示例商品库存为30,与此前已验证恢复的基线一致;未付款、未发货。
- 用户端全量55项测试通过;商城订单标签新增四宽度、两种文字缩放共8张截图。初次截图发现全宽取消按钮导致换行,已为订单操作指定紧凑宽度,继续保留48px触控高度。
- 修正后8项截图检查、Flutter静态检查、最终Web构建通过;[390px截图](视觉验收/A1/20-shop_390_1.0.png)中操作按钮已并排。订单列表159行、订单页338行、后端新专项55行;未新增运行依赖或数据库迁移。
## 剩余项
图20仍不是严格1:1:配送轨迹、联系配送员、发票、再次购买、订单图片等尚未齐全。确认收货未改动远程已有真实履约订单,只通过隔离 SQL Mock 验证;不得为浏览器演示把未付款测试订单改成已发货。接口新增事务锁仅作用于本次操作的本人订单,不修改支付或退款规则。

View File

@@ -0,0 +1,55 @@
# 商城订单详情开发与验证记录
操作时间:2026-09-08。操作类型:新增详情、提取共用操作、修复底栏。影响模块:用户商城订单接口、订单列表、详情路由。数据库与缓存继续连接既有远程服务;本轮无迁移、无本机数据库容器、无订单或库存写入。
## 操作前后
已打开最新21-订单详情原图,检查状态、配送进度、联系人、商品、费用、订单信息及操作入口。原订单列表只能打开操作弹层,没有独立详情。新增`/shop/orders/:identity`,点击商城订单或“查看详情”进入;直接深链需登录,登录后返回原订单。气瓶订单仍沿用旧入口,本轮未把商城详情冒充气瓶完整详情。
详情独立读取本人订单。商品名称、数量、单价与收货信息来自成交快照;资料缺失明确显示空态,不读取当前商品/地址覆盖历史。仅展示真实记录的下单、支付、发货及收货时间,电话按原图脱敏,应付金额不标为已实付。
## 代码变更
| 文件(仓库相对路径) | 职责/函数及行数 |
| --- | --- |
| backend/api/internal/logic/client/user/shop_detail.go | 新增73行;GetShopOrder本人详情,shopOrderState共用动作与状态 |
| backend/api/internal/logic/client/user/shop.go | ListShopOrders复用shopOrderState,原响应及操作规则保持兼容 |
| backend/api/internal/logic/client/user/shop_detail_test.go | 新增73行;归属条件、成交快照、白名单、非法订单和状态动作 |
| backend/api/internal/routers/client.go、client_test.go | 新增受JWT保护的GET shop/orders/:identity及路由检查 |
| apps/user_app/lib/domain/models/shop_order_detail.dart | 新增89行;ShopOrderDetail、ShopOrderLine,整数分金额、成交数量、时间与OrderSummary适配 |
| apps/user_app/lib/data/repositories/client_repository.dart | shopOrderDetail独立读取,校验返回identity及会话一致性 |
| apps/user_app/lib/ui/features/orders/order_action_handler.dart | 新增217行;从原订单页提取确认、支付、退款及退款原因对话框,不重复实现交易规则 |
| apps/user_app/lib/ui/features/orders/orders_page.dart、order_list.dart | 列表点击进入详情;保留“查看操作”,详情返回刷新订单和退款列表 |
| apps/user_app/lib/ui/features/orders/shop_order_detail_page.dart | 新增302行;_load、_act、_copy、_footer,独立加载、操作前刷新、复制反馈、底栏布局 |
| apps/user_app/lib/app/router.dart | 新增受会话守卫保护的/shop/orders/:identity |
| apps/user_app/test/ui/shop_order_detail_test.dart、test/data/shop_order_detail_test.dart | 新增137/70行;失败重试、复制、确认取消、过期动作、金额、响应归属 |
| apps/user_app/test/support/a1_fixture.dart、tool/a1_visual_test.dart | 明确独立测试Fixture及图21多尺寸截图 |
| scripts/compare-user-app-a1.ps1 | 加入图21,现14组并排设计证据 |
## 接口及交互边界
- `GET /heqi/client/v1/user/shop/orders/:identity`在SQL中同时限定公开identity和JWT对应user_account_id,未命中返回1112,未登录HTTP401。
- 响应显式列出订单信息和商品快照字段,不返回内部主键、用户外键或完整任意JSON快照。商品已改价/删除不会改变成交明细。暂无历史图片的订单继续显示缺失状态。
- 商城状态16发布pay/cancel,18发布refund,18且物流20发布confirm_receipt,取消订单不发布动作;详情与列表共用定义。服务端动作接口仍负责最终状态及所有权校验。
- 详情操作前重新读取订单,原动作已失效时不提交。取消/收货必须确认,未知错误显示失败并重读,不伪造成功。支付与退款复用原请求号策略;本轮没有执行真实支付或退款。
- 操作栏放在Scaffold底栏,避免SnackBar遮挡按钮;按容器宽度约束两个按钮,修复原主题最小宽度导致申请退款独占整行的问题。
## 验证
- Go全量`go test ./...`、`go vet ./...`与API构建通过;路由与业务测试覆盖本人过滤、历史名称/金额、字段白名单、缺失订单及五组状态动作。
- Flutter analyze通过,全量95项测试通过。原订单取消、确认收货、退款刷新回归保留;新增详情测试覆盖深链、首读失败重试、复制内容、确认取消、失败重试、已失效动作不提交、整数分及跨账号迟到响应。
- 图20(两种标签)和21的320/360/390/430宽度与1.0/1.3字号共24项布局检查通过。查看图21的390普通和320大字体截图后修复按钮布局,图21再次8项通过,并实际查看修复截图。
- Web Release与Android Debug构建通过;Android仍提示既有插件Kotlin和SDK XML版本兼容警告,未影响当前产物。构建通过不代表真机相机/语音或支付验收完成。
- 本机API进程6884运行新后端,端口12426;18571提供Web。读取此前已取消测试订单`EC1788842040900189900`:商品9/10各2件,单价10400/10500分,总金额41800分,动作列表为空。不存在订单返回1112,匿名访问HTTP401。
- 浏览器390×844实际验证深链跳登录并回原订单,显示已取消、历史联系人与地址、两项商品、418元费用和订单备注;点击复制显示“已复制订单号”。订单及库存未改变。
- 浏览器返回商城订单列表后再点击“查看详情”,重新进入同一订单并独立读取;没有回退到旧操作弹层。浏览器错误/警告日志为空。
## 视觉结果与待办
整页验收仍failed。原图是气瓶配送中的示例,商城分支尚不能提供押金、配送员、预计送达、供气合同、服务联系与地图轨迹;历史商品图缺失,时间轴结构和页面密度仍有差异。未填入设计示例时间、照片、合同或实付数据。58图中现14张部分实现、44张无完整页面、0张严格全功能1:1通过。
证据:[图21并排](视觉验收/A1/21_并排对照.png)、[390截图](视觉验收/A1/21_390_1.0.png)、[320大字体](视觉验收/A1/21_320_1.3.png)。后续需继续补气瓶订单详情与配送业务,不能仅将路由存在视为完成。
## 维护方式
订单列表与详情的允许动作只能修改shopOrderState并补状态测试,写操作继续保留服务端锁和幂等边界。公共字段扩展使用白名单,不直接透传模型或JSON快照;详情显示历史资料的含义不得变成当前商品信息。运行`flutter test test/ui/orders_page_test.dart test/ui/shop_order_detail_test.dart test/data/shop_order_detail_test.dart`与Go用户逻辑/路由测试后,使用图21多视口截图核对布局。

View File

@@ -0,0 +1,38 @@
# 设置与登录密码开发日志
操作时间:2026-09-08。类型:扩展与修复。影响模块:图31设置、登录密码、个人中心。
## 行为与实现
个人中心设置从不可用提示改为`/settings`,支持深链登录回跳。按最新图31组织账号、消息、设备、通用、协议分组,增加`/settings/password`,当前密码、新密码和再次确认必须校验通过才提交;失败保留输入,只有服务端明确确认changed=true后清空表单并退出本机会话。
版本读取当前安装包/Web构建元数据,不使用设计稿的1.6.0。缓存大小来自Flutter可恢复图片缓存,清理二次确认后刷新数值,不清空令牌、报修草稿或文件。协议沿用后台已发布内容和真实版本,资料读取失败不阻断清缓存和退出。图31的手机号与提示在窄屏大字体上下排列,避免末位数字断行;所有深链均提供返回。
后端保留`PUT /heqi/client/v1/user/auth/password`字段契约,更新条件增加旧密码散列版本,避免并发改密覆盖新值;该更新关闭SQL参数日志以保护密码散列。错误密码、并发旧版本不会产生成功响应。
## 核心文件
- `apps/user_app/lib/ui/features/settings/settings_page.dart`:SettingsPage分组、独立附属加载、缓存与退出确认。
- `apps/user_app/lib/ui/features/settings/login_password_page.dart`:LoginPasswordPage密码内存草稿、UTF-8长度边界、二次确认、错误与成功退出。
- `apps/user_app/lib/data/services/app_settings_service.dart`:版本与图片缓存平台适配;新增`package_info_plus 10.2.1`依赖。
- `apps/user_app/lib/data/repositories/client_repository.dart`:changeLoginPassword校验响应和会话世代;不接受缺少成功标记的响应。
- `apps/user_app/lib/app/router.dart`、`ui/features/profile/profile_page.dart`:设置及改密路由和入口。
- `apps/user_app/lib/ui/features/auth/login_support.dart`:协议阅读支持注入当前仓储,保持登录页调用兼容。
- `backend/api/internal/logic/client/user/auth.go:179`:ChangePassword,200行增加条件更新,随后确认影响行数;接口参数保持兼容。
- 前端新增`settings_page_test.dart`、`change_login_password_test.dart`,扩展`router_test.dart`和`tool/a1_visual_test.dart`;后端新增`change_password_test.go`及显式开启的`change_password_remote_test.go`。
## 验证
Go全量测试、vet、API构建通过。Flutter全量110项测试及analyze通过;图31共8组320/360/390/430宽度及1.0/1.3字号布局检查通过,实际查看390及320放大截图后修复手机号断行和返回入口。
远程回滚测试显式设置`HEQI_REMOTE_PASSWORD_TEST=1`执行;仅在持锁事务内临时设置授权测试账户密码夹具,验证错误旧密码、正确改密和旧密码失效,整体回滚后比对原散列一致。未发送验证码、未改写远程真实密码、无数据结构迁移;普通测试默认跳过远程用例。
浏览器390宽实测错误旧密码被拒绝且保留表单和会话,图片缓存6.0MB→0.0MB,退出确认后回到登录页。协议接口无已发布协议,确认显示真实空态。运行时曾出现版本读取失败,改为Web显式页面目录并用`--pwa-strategy=none`构建本地预览、消除旧Service Worker缓存影响后,浏览器已真实读取`1.0.0 (1)`,与构建version.json一致。不能把第一轮对插件路径的推断单独当作已证实根因;版本成功以最后实际页面为证据。Web和Android调试包构建通过,原生版本读取仍待真机确认。
## 未完成与维护
图31仍未全量完成:实名认证、支付密码设置/重置、换手机号、设备登录撤销、通知投递偏好、原生权限入口、隐私偏好和注销审核尚待接入。未绘制假生效开关。协议与隐私当前共用已发布协议列表,后台缺少明确的细分类契约;未发布时显示真实空态。安全用气指南尚缺独立内容类型与后台承接。
当前改密只退出本机会话,不能宣称其他设备令牌已撤销;设备会话管理需后续统一补齐。网络中断可能无法确认改密是否生效,现有接口不提供请求号查询;不把重试失败声称为密码未变更。缓存统计仅为图片内存缓存,不代表系统或浏览器全部占用。
运行前端使用现有18571预览,API12426连接已有远程PostgreSQL/Redis。全量计数现为16张部分实现、42张未完成对应页面、0张严格全功能与1:1验收通过。

View File

@@ -0,0 +1,58 @@
# 用户端 App 购物车操作日志
操作时间:2026-09-08。操作类型:扩展。影响模块:Flutter用户端、Go商城Client API、接口契约与视觉记录。
## 操作前状态
已阅读最新13-购物车原图及03需求。既有ec_cart表没有用户端接口;商城/详情购物车按钮弹出未开放提示,详情没有加入购物车;结算页面只接收单一商品。工作区已有大量前序变更,本轮未重置、清理或提交。数据库和缓存继续使用原配置的远程服务,本机只运行API和Web。
## 本次变更
| 文件(仓库相对路径) | 位置与职责 | 行数说明 |
| --- | --- | --- |
| backend/api/internal/logic/client/user/cart.go | 51行ListCart、80行GetCartItem、104行SetCartItem;本人条目和条件数量写入 | 新增186行 |
| backend/api/internal/logic/client/user/shop.go | 65行CreateShopOrder;items校验、固定锁顺序、购物车版本消费 | 扩展既有函数,不替换支付和退款 |
| backend/api/internal/routers/client.go、client_test.go | 用户鉴权组新增GET shop/cart、GET/PUT shop/cart/items/:identity | 3条路由和路由注册断言 |
| apps/user_app/lib/domain/models/cart_item.dart | 强类型条目、整数金额、库存和版本 | 新增49行 |
| apps/user_app/lib/data/repositories/client_repository.dart | 18行cart及条件写入;40行submitCartOrder | 追加接口,保留submitShopOrder签名 |
| apps/user_app/lib/ui/features/shop/cart_page.dart | 购物车、失效提示、单选全选、管理删除、真实金额 | 新增350行 |
| apps/user_app/lib/ui/features/shop/product_detail_page.dart | 37行_add;未知结果保留目标数量,重试不重新累加 | 扩展底部动作 |
| apps/user_app/lib/ui/features/shop/checkout_page.dart | fromCart模式和103行_submit;多商品快照、地址和金额确认 | 文件现355行,单商品流程保留 |
| apps/user_app/lib/ui/features/shop/shop_page.dart、lib/app/router.dart | 商城购物车按钮;/cart和/cart/checkout及登录守卫 | 扩展现有导航 |
| backend/api/internal/logic/client/user/cart_test.go | 幂等、账户过滤、版本、数量、归档及多商品事务 | 新增178行 |
| apps/user_app/test/ui/cart_page_test.dart、test/data/cart_test.dart | 交互、未知结果、选中地址、整数金额、HTTP鉴权 | 新增182和64行 |
| apps/user_app/test/support/a1_fixture.dart、tool/a1_visual_test.dart | 独立购物车测试数据及图13视觉截图 | 不进入运行中的商品数据 |
| scripts/compare-user-app-a1.ps1 | 图13并排图,现12组原图对照 | 输出仅用于检查差异 |
## 行为与数据边界
- 所有购物车读写按JWT账户过滤,商品使用公开identity。账户行锁串行保护创建、改量和归档;不新增远程表、字段或容器。
- PUT提交绝对quantity、selected和revision;相同目标无副作用,过期版本返回2403。版本采用购物车公开UUID和微秒精度时间,已通过真实PostgreSQL写后重读验证。
- quantity=0归档。数据库仍保留正数量以兼容旧CHECK,API把归档行解释为零并保留版本,避免旧请求复活已删除商品。新增/增加受库存和999上限限制;最多100条有效商品。
- 全选和批量删除逐项写入,部分失败后重新加载服务端状态;不能把局部成功描述为整体成功。
- 订单可提交多个不同商品,按identity排序锁库存,拒绝重复商品及非法数量。cart_revision必须与本人的有效勾选条目及数量一致;移除购物车、扣库存、创建订单在同一事务,任一步失败整体回滚。
- 原订单request_no优先恢复已有结果,原单商品客户端不传cart_revision仍兼容。用户点击提交前不创建订单,不支付、不触发真实配送。
## 验证结果
- `go test ./...`、`go vet ./...`、`go build -o %TEMP%/heqi-cart-api.exe ./cmd/main/main.go`通过;之后补充首次加购false勾选和非法订单items两项测试,定向测试通过。
- `flutter analyze --no-pub`通过;用户端完整79项测试通过。视觉发现生产主题的FilledButton在Row内无限宽约束,修复为受约束宽度,并让新增交互测试使用真实AppTheme,3项交互回归再次通过。
- 图12、13各在320/360/390/430宽度、1.0/1.3文字缩放下共16项视觉检查通过,已打开390图13及320大字体图12核对。原图和截图并排生成成功;这仅证明无布局溢出,不代表原稿一致。
- Flutter Web Release重新构建通过,本地18571使用新产物;Go API本地12426连接既有远程PostgreSQL/Redis。`pnpm contract:sync`与`pnpm contract:check`通过,48个资源。
- 匿名GET shop/cart实测HTTP401。授权测试账户原有一条15kg配送服务购物车记录,数量1/勾选true,本次保留。
- 远程HTTP联调给商品9和10各加入2件,同一数量请求重试不累加。创建订单 **EC1788842040900189900**(identity `01a07f4b-5e44-72e5-893d-6b194089cf13`),两商品应付41800分;重复提交返回同一订单,已结算购物车条目被原子移除。
- 上述联调订单已取消,临时地址已归档,两种商品库存恢复29和30;没有支付或实际履约。
- 浏览器390×844实测游客加购跳登录并回商品详情,登录后加购成功;购物车将测试商品从1改为2,合计20800分变为31300分,多商品结算显示原有商品10300分×1和新增商品10500分×2。未在浏览器提交订单;完整创建/重试/取消已由上述HTTP真实联调覆盖。
- 重新打开最新Web构建并重新登录后,新增商品仍为2件,验证了远程持久化;手机截图已核对最新分组与底部按钮。随后通过管理、单选和删除确认归档本次测试商品,HTTP复核仅剩原有商品数量1/勾选true。
## 视觉差异与未完成项
整体仍为failed/部分实现,不能写“图13已1:1完成”。原图有配送承诺、规格、押金提示、保障区和推荐区,当前后台模型及接口没有完整支持;本次未编造承诺、押金或优惠。原图128+169+100与展示合计425不一致,实际结算必须服从服务端整数金额。
远程示例商品9/10没有图片,原有15kg商品图片URL返回404,仍显示明确空/失败状态,没有把设计稿里的其他商品图当成真实商品照片。基础白色商品分组、分隔线、圆形勾选和底部金额已调整;图片、上下分区、规格及精确间距仍不一致。
详情收藏、客服、分享及购物车优惠/推荐/押金配置未完成;全量状态更新为12张部分实现、46张尚无完整页面、0张通过严格全功能1:1验收。订单未知结果在当前页面复用请求号,跨页面重建持久化恢复仍须继续完善;本轮没有将原生Android/iOS购物车交互标为验收通过。
## 维护说明
后续增加SKU、促销、押金与推荐应扩展对应领域服务,金额和库存继续服务端确认。修改购物车必须复用条件版本契约,并覆盖失效条目、并发版本、所有权和事务回滚测试。批量动作若改为原子接口需同步契约和失败提示。继续沿用当前技术栈和环境;禁止通过全库迁移或重置数据修复展示差异。

View File

@@ -0,0 +1,41 @@
# 钱包与账单开发记录
操作时间:2026-09-11
操作类型:扩展、修复
影响模块:用户钱包主页、钱包账单、本人流水读取。
## 功能变化
个人中心的钱包原先直接打开通用流水列表。现新增`/wallet`,按图28组织账户余额、资产、快捷服务、最近账单和资金安全入口;可隐藏余额与最近账单金额,支付密码接入已完成页面。`/records/wallet`地址保持兼容,改为专用账单页,支持全部、收入、支出筛选、游标续页、下拉刷新和账单详情。刷新失败保留原账单并允许重试,账户切换丢弃迟到响应。
资产数据没有已确认接口时显示“暂未提供”,不写入原图的200元押金、两张券和100元待退款。充值、提现、银行卡等入口保留,但尚未完成办理流程,图28只能计部分实现,不能宣称钱包全部可用或严格1:1通过。
## 核心变更
- `backend/api/internal/logic/common/wallet_bills.go`:新增`ListWalletBills`,本人钱包范围、每页50条、按序号倒序及显式下一页游标,白名单输出,不返回内部请求号和操作者信息。
- `backend/api/internal/routers/client.go`:增加`GET /wallet/bills`,既有`/wallet/records`接口不删除。
- `apps/user_app/lib/domain/models/wallet_bill.dart`:账单金额必须为整数分,收支及时间不完整时拒绝解析,不伪装成空账单或零金额。
- `apps/user_app/lib/data/repositories/client_repository.dart`:新增`walletBills`,会话保护与严格响应检查;`wallet`拒绝小数、负数、缺失金额及可提现额超过余额。
- `apps/user_app/lib/ui/features/wallet/wallet_page.dart`:钱包主页、隐私开关和独立账单重试;`wallet_bills_page.dart`:筛选、分页、详情。
- `apps/user_app/lib/app/router.dart`、`ui/features/profile/profile_page.dart`:受保护钱包路由与个人中心入口。
- 新增后端`wallet_bills_test.go`、前端`wallet_bill_test.dart`和`wallet_page_test.dart`;视觉夹具和并排脚本增加图28。
## 关键纠偏
远程只读检查发现旧种子充值流水使用`direction=in`,当前业务使用`income`。新接口在收入筛选和响应中兼容这一已确认旧值,不重写任何历史资金事实。首次测试还发现账单重试的`setState`箭头回调返回Future,已改为同步块并保留回归测试。
没有数据库迁移,没有充值、提现或余额改写。测试环境仍为原远程PostgreSQL及Redis;本机仅运行API和Web预览。
## 验证记录
上次执行因会话中断未保留最终日志,2026-09-11重新运行当前代码的Go全量测试、vet、Flutter全量测试、图28八组布局检查。以本轮最终工具结果更新结论,旧执行意图不算通过证据。
本轮结果:Go全量测试、vet和API构建通过;Flutter全量123项测试通过。资产区压缩及金额右对齐修正后,重新执行2项页面测试及8组320/360/390/430宽度、1.0/1.3文本布局检查,10项均通过,analyze无问题。已查看最终并排图,仍有卡片高度、图标、资产数据和缺失办理流程差异,严格视觉仍为failed。
Web与Android Debug APK构建成功。Android工具链仍提示既有插件Kotlin迁移及SDK XML版本差异,未升级依赖或修改原生业务。浏览器在18571仍加载到旧路由,新产物中确认存在钱包路由后,使用独立端口18572验证新包:登录回跳钱包,真实余额500元、可提现余额300元、历史充值500元;金额隐藏同步覆盖最近账单与详情。接口实测全部1条、收入1条、支出0条,旧`in`读取兼容已生效。本轮未创建或改写资金流水。
运行入口:http://127.0.0.1:18572/#/wallet;API12426进程24552,继续读取既有远程配置。所有截图夹具金额均与真实运行事实分开记录。
浏览器追加验证:收入筛选显示历史500元充值,支出筛选显示“暂无账单”。控制台在登录输入期间捕获`Null check operator used on a null value`,编译栈对应Flutter Web输入配置的DOM元素操作;自动输入曾多次未生效,切换显示模式并逐键输入后登录成功。根因尚未确认,不能宣称运行时完全无错误;需要继续排查登录输入与可访问模式的组合。该问题不由账单回归测试覆盖。
后续登录输入连接已单独修复并完成浏览器复核,遮蔽密码输入可直接登录,未新增同类错误;详见[登录输入记录](操作日志_用户端APP_登录输入连接_20260911.md),保留上段作为发现过程,不代表当前最新状态。

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 265 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 73 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 73 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 404 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Some files were not shown because too many files have changed in this diff Show More