62 lines
7.4 KiB
Markdown
62 lines
7.4 KiB
Markdown
# 用户端 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 不再允许任意跨账户引用。
|