第三次版本迭代更新

This commit is contained in:
andy
2026-06-18 15:54:47 +08:00
parent 10fbd0390c
commit 898a1e1577
14 changed files with 400 additions and 75 deletions

101
docs/frontend-practices.md Normal file
View File

@@ -0,0 +1,101 @@
# 员工端 H5 前端经验总结
这份文档记录当前员工端 H5 在页面规划、接口接入、移动端兼容、扫码核销和部署上的经验。后续改页面时,优先按这里的约定处理,避免重复踩坑。
## 页面规划
- 第一版页面以业务闭环为主,不做后台管理式的大而全页面。
- 当前核心页面包括:登录、工作台、订单列表、订单详情、扫码核销、核销确认、核销结果、事件列表、发布事件、我的。
- 工作台上的统计数据必须有明确后端依据。没有独立统计接口时,可以展示列表接口能稳定支持的指标,例如待确认订单、生效事件、近期订单、近期事件。
- 不要把 mock 推导出的数据当成真实业务指标。比如订单表没有可直接查询的核销状态或核销时间时,不要在工作台展示“今日核销”这类指标。
- 页面文案保持员工端视角,产品名称统一使用“员工端”。
## 登录与组织关系
- 登录使用手机号验证码流程,登录成功后必须主动调用 `/hotelStaff/organizationMember/bindUserInfoAndGetUserMemberInfoByPhone` 获取当前用户组织关系。
- 如果组织关系获取失败,统一提示“未绑定组织,请联系管理员”。
- 当前不需要调用 `/user/checkUserHasBindPhone`
- 登录态只代表认证成功,不代表用户一定拥有员工端组织关系,业务页面入口应以后续组织关系接口成功为准。
- 接口返回“请求令牌已过期”、`401` 或 token 失效类错误时,要统一清理本地登录态并跳转 `/login`,同时带上当前页面作为 `redirect`,避免用户继续停留在失效页面。
## 接口路径
- 所有真实接口都通过后端网关访问,由网关按路由转发到具体服务。
- 本地开发使用 Vite proxy当前开发网关是 `http://192.168.3.211:9999`
- 员工端接口前缀是 `/hotelStaff`,订单接口路径是 `/hotelStaff/order/...`,事件接口路径是 `/hotelStaff/event/...`
- 登录接口走 `/auth`,验证码和用户相关接口走 `/admin`
- 不要在业务代码里硬编码完整网关地址,统一从环境变量和 `src/utils/env.ts` 读取。
## 环境与部署
- 本地开发使用 `.env.local`,测试打包使用 `.env.test`,生产打包使用 `.env.production`
- `VITE_API_BASE_URL` 为空时,前端会按当前站点同源请求接口,适合 Nginx 反向代理部署。
- 前后端分离部署时,优先用 Nginx 把 `/auth``/admin``/hotelStaff``/hotelBiz` 等路径代理到后端网关,这样浏览器看到的是同源请求,跨域问题最少。
- 如果直接把 `VITE_API_BASE_URL` 配成后端网关 IP 或域名,跨域就需要后端网关正确返回 CORS 头;这不是前端代码能完全解决的。
- SPA 路由需要 Nginx `location / { try_files $uri $uri/ /index.html; }`
## 移动端布局
- H5 页面不要依赖固定宽度,所有主容器都应具备 `width: 100%``max-width: 100%``min-width: 0` 这类约束。
- flex 或 grid 中承载长文本的区域要使用 `min-width: 0`grid 列建议用 `minmax(0, 1fr)`,否则长订单号、手机号、商品名容易撑出横向滚动。
- `html``body``#app` 可以限制 `overflow-x: hidden`,但这只是兜底。真正要处理的是子元素宽度、长文本换行和 flex 收缩。
- 图片、视频、canvas 必须有 `max-width: 100%`,避免媒体元素撑破视口。
- 固定底部导航、按钮区域需要考虑 `safe-area-inset-bottom`,兼容 iPhone 底部安全区。
## 输入框兼容
- iOS Safari 和微信内置浏览器中,输入框字号小于 16px 时,聚焦输入框会触发页面自动放大,容易出现横向滚动和布局错位。
- 全局真实输入控件,包括 `input``textarea``select``.van-field__control`,应保持 `font-size: 16px`
- 不建议通过 `maximum-scale=1``user-scalable=no` 禁止用户缩放,这会影响可访问性,也不能从根上解决布局问题。
- 搜索框、登录手机号、验证码、日期时间输入都要按真实输入控件处理,不要只调整外层字体。
## Vant 组件样式
- 修改全局样式时要避免过宽的选择器,例如 `.meta-row span` 会误伤 Vant 的 `van-tag`,导致“生效中”“已取消”等标签在 Chrome 里被拉伸或错位。
- 对普通文本列可以使用 `.meta-row > span:not(.van-tag)`,状态标签应单独设置 `flex: 0 0 auto``white-space: nowrap`
- Vant 组件内部结构可能使用 `span``button``input` 等基础标签,写全局选择器时要先确认是否会影响组件内部 DOM。
- 共享样式要放在 `src/styles/main.css`,页面个性化样式放在对应 `.vue` 的 scoped style。
## 扫码核销
- 当前二维码内容规则是 `orderId&packageName`,其中 `packageName` 是套餐名称。
- 前端解析时必须兼容只有 `orderId` 的情况。
- 扫码流程是:点击进行扫码 -> 调起摄像头 -> 解析二维码 -> 查询订单详情 -> 展示核销确认 -> 调用核销接口。
- 当前核销入口不提供手动输入订单号兜底,页面文案保持“点击进行扫码”。
- 扫码内容带 `packageName` 时,核销确认页只能展示并核销当前扫码进入的套餐商品;不能让员工切换到其他套餐。
- 扫码内容只有 `orderId` 时,核销确认页可以按订单详情里的套餐配置展示可选套餐。
- 浏览器扫码优先使用原生 `BarcodeDetector`,不支持时使用 `jsQR` 读取视频画面进行解析。
- 摄像头能力通常要求 HTTPS 或 localhost。微信内置浏览器如果 `getUserMedia` 受限,后续可以考虑接入微信 JSSDK 的 `scanQRCode`,但需要公众号配置、签名接口和 JS 安全域名配合。
## 订单与核销记录
- 订单列表当前保留手机号搜索和订单状态筛选。
- 订单详情可以发起核销,核销确认页需要展示订单核心信息,避免员工误核销。
- 核销确认页必须展示可核销商品数、已核销商品数、总数量,优先使用后端套餐配置里的 `count``writeOffCount``packageStatus` 字段。
- 当可核销商品数为 0 时,确认核销按钮应禁用,并提示当前套餐商品已核销完。
- `/hotelStaff/order/writeOff` 返回值是 `Boolean`,前端不能只看 HTTP 成功;如果返回 `false`,必须按核销失败处理。
- 后端状态机会限制超量核销并控制核销记录数量,前端职责是正确展示剩余数量并正确处理失败态。后端如果能透传“该套餐商品已被核销完”等具体错误,会让前端提示更准确。
- 订单详情的核销记录中,如果后端返回套餐名称,要展示套餐名称,便于员工核对。
- “使用信息”里不要展示核销地点,当前后端和页面需求不需要这个字段。
## 事件模块
- 发布事件页面里的“实体名称”已改为“事件标题”。
- 事件列表搜索提示文案为“搜索事件标题”。
- 事件列表不需要开启和关闭按钮,也不需要以开启/关闭作为主要筛选交互。
- 列表上的状态展示要谨慎处理样式,不能影响 Vant 标签的自然宽度。
## 验证清单
每次改动移动端布局、表单、列表或扫码能力后,至少检查:
- `yarn typecheck`
- `yarn build:test`
- 320px 和 375px 宽度下是否出现横向滚动
- 登录页输入框聚焦后是否自动放大
- 订单搜索输入框聚焦后是否自动放大
- Chrome 里订单状态、事件状态标签是否保持正常宽度
- 真机或微信内置浏览器里扫码入口是否能正常申请摄像头权限
- 扫码带套餐进入核销确认页时,只能看到当前套餐
- 核销确认页的可核销商品数、已核销商品数、总数量和后端返回一致
- `/writeOff` 返回 `false` 或失败时,前端不能展示核销成功