Files
xinlong-shop-taro/.workbuddy/memory/2026-07-17.md
赵忠林 0d0c4b327a feat(store): 恢复门店端独立改价按钮和弹窗
- 去除确认收款弹窗中的“实付金额”输入框
- 改价功能从合并回独立弹窗及按钮
- 新增改价相关状态和函数处理逻辑
- 线下付款未付款状态显示“改价”与“确认收款”按钮
- 改价弹窗包含订单信息、新金额输入及改价备注
- 改价按钮样式调整为橙色背景白字
- 改价提交时更新订单金额及备注并刷新列表
2026-07-17 16:50:18 +08:00

152 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 2026-07-17 工作日志
## 门店订单管理页改造src/pages/store/orders/index.tsx
### 1. 删除订单改为关闭订单
- 原"删除订单"按钮调用 `removeShopOrder`(物理删除),改为"关闭订单"调用 `updateShopOrder({ orderId, orderStatus: 2 })`(逻辑关闭)
- 确认弹窗文案从"删除后无法恢复"改为"关闭后无法恢复"
- 移除 `removeShopOrder` 导入,新增 `confirmOfflinePayment` 导入
### 2. 待付款订单加确认收款按钮
- **背景**:线下付款(payType=9)且未付款的订单,门店需要"确认收款"功能与后台管理guilixu-admin对齐
- **后端接口**`PUT /shop/shop-order/confirm-offline-payment/{id}?remarks=xxx&paymentVoucher=xxx`
- 后端 `ShopOrderController.confirmOfflinePayment()``ShopOrderServiceImpl.confirmOfflinePayment()`
- 校验payType必须为9(线下付款)、orderStatus不能为2(已关闭)、不能重复确认
- 确认后设置 payStatus=true、payTime=now(),可选保存 remarks(merchantRemarks) 和 paymentVoucher
- **前端API**:在 `src/api/shop/shopOrder/index.ts` 新增 `confirmOfflinePayment(id, remarks?, paymentVoucher?)` 函数
- 注意Taro 的 `request.put` 不支持 `params` 参数,需手动拼接 query string
- **ShopOrder Model**:新增 `paymentVoucher?: string` 字段
- **页面改动**
- OpType 从 `'pay'|'complete'|'editPrice'` 改为 `'confirmPay'|'complete'|'editPrice'`
- `getOrderActions` 新增条件:`!payStatus && payType===9 && orderStatus===0` → 显示"确认收款"按钮
- 弹窗新增备注 Textarea仅 confirmPay 显示凭证图片限制1张confirmPay必填校验
- `submitOperation` 新增 confirmPay 分支,调用 `confirmOfflinePayment` API
- 新增 `payRemarks` state
### 3. 订单详情页金额明细0隐藏src/pages/order/detail.tsx
- **Bug**React 经典陷阱 `{order.reducePrice && Number(order.reducePrice) > 0 && (...)}`,当 reducePrice 为数字 0 时,`0 && ...` 短路求值为 0React 渲染文本"0"
- **修复**:改为 `{Number(order.reducePrice || 0) > 0 && (...)}`,始终返回 boolean
### 验证
- `npx taro build --type weapp` 构建成功
## 地址/购物车问题修复
### 5. 地图选择首次打开列表不显示src/pages/user/address-edit.tsx
- **问题**:鸿蒙手机首次打开 `Taro.chooseLocation` 时地图 POI 列表不显示,需拖动才出现
- **根因**:未传入经纬度时地图默认定位到北京,鸿蒙系统不会自动获取用户位置
- **修复**:调 `chooseLocation` 前先 `Taro.getLocation({ type: 'gcj02' })` 获取当前位置,将 latitude/longitude 传给地图确保首次打开就在用户位置附近POI 列表立即加载
### 6. 收货地址编辑不加载旧数据
- **Bug 1API 路径不匹配)**:前端 `updateShopUserAddress``PUT /shop/shop-user-address/{id}`,但后端 `@PutMapping()``/{id}` 路径 → 404
- 修复:改为 `PUT /shop/shop-user-address`(去掉 `/{id}`id 通过 body 传递)
- **Bug 2加载防御**`setFormData(addr)` 直接替换 state若后端返回 null 字段会覆盖初始 `''`
- 修复:改为 `setFormData(prev => ({...prev, ...addr, name: addr.name || '', ...}))` 保证字段非 null
### 7. 新用户注册后首次加购购物车不刷新
- **根因**:注册页 `register.tsx` 和登录页 `login.tsx` 只调 `saveStorageByLoginUser()` 存 storage未调 `UserContext.loginUser()` 更新 React 状态 → `isLoggedIn` 仍为 `false` → 购物车页 `useDidShow``if (isLoggedIn) refresh()` 不执行
- **修复**
1. `register.tsx``login.tsx``saveStorageByLoginUser` 后加 `loginUser(token, user)` 同步 UserContext
2. `sms-login.tsx``loginBySms` 后加 `syncFromStorage()` 同步状态
3. 防御性措施:`cart.tsx``product-detail.tsx``index/index.tsx``useDidShow``syncFromStorage()` 确保页面显示时从 storage 同步用户状态
## 门店订单页 Tab 改造src/pages/store/orders/index.tsx
- **需求**:原「全部 / 已完成 / 已关闭」Tab 改为「待处理 / 已完成 / 已关闭」
- 待处理 = 待付款(0) + 待发货(1) + 待核销(2) + 待收货(3),按用户确认把待核销(2)也并入
- 已完成 = statusFilter 5不变已关闭 = statusFilter 8不变
- **TabKey 类型**`'all' | 'pending' | 'completed'``'pending' | 'completed' | 'closed'`
- **TABS 配置**:删除原「全部」无筛选 Tab待处理用 params 数组 `[{statusFilter:0},{1},{2},{3}]` 并行请求合并去重loadOrders 已支持)
- **默认选中**`useState<TabKey>('all')``'pending'`
- **新订单角标**`tab.key === 'all'``tab.key === 'pending'`(移到待处理 Tab
- **statusFilter 后端映射参考**ShopOrderMapper.xml 第240-282行0待支付=未付款、1待发货=pay1&delivery10&order0、2待核销=pay1&order0、3待收货=delivery20&order!=1、5已完成=order1、8已取消=order2
- **验证**tsc 仅剩预存 `@tarojs/taro` 类型缺失环境报错,本文件无新错误
- ⚠️ 注意原「全部」Tab 显示的「待评价(statusFilter=4)」订单在改版后无 Tab 承接(用户确认不含待评价),如需可见后续可并入待处理
## 门店订单页「收货信息」一键导航src/pages/store/orders/index.tsx
- **需求**:订单卡片里的收货信息区域点击可一键导航
- **实现**`renderOrderCard` 的「收货信息」整块 View 加 `onClick={() => handleNavigate(order)}`,右侧加绿色「› 导航」标识提示可点
- **新增 `handleNavigate(order)`**:读取 `order.addressLat`/`order.addressLng`(模型里为 string`parseFloat` 转 number坐标有效则 `Taro.openLocation({ latitude, longitude, name: realName, address, scale: 16 })`(微信内置地图,自带导航选 App坐标缺失/非法则 toast「该订单未记录定位信息无法导航」兜底
- **注意**`Taro.openLocation` 是地图展示类 API不在微信 `requiredPrivateInfos` 受限清单内,无需在小程序后台声明、无需 `ensurePrivacyAuthorized` 预检(与 chooseImage/getPhoneNumber 不同)
- **验证**tsc 仅剩预存 `@tarojs/taro` 类型缺失环境报错,本文件无新错误
## 订单详情页「过期时间」→「送达时间」src/pages/order/detail.tsx
- **需求**:订单信息区原「过期时间」(order.expirationTime) 行改为「送达时间」
- **字段确认**:用户选择「送达时间」用 `order.deliveryTime`,且**保留**现有「发货时间」行 → `deliveryTime` 在两行各显示一次(用户明知并接受)
- **改动**第408-413行 `{order.expirationTime && ...过期时间}` 改为 `{order.deliveryTime && ...送达时间}`,数据用 `formatTime(order.deliveryTime)`
## 门店订单页「发货」按钮 + 选发货人员写 shopOrderDelivery解决物流页发货信息为空
- **根因**:物流页 `pages/order/logistics.tsx` 的「发货信息」卡片依赖 `shopOrderDelivery` 发货单;门店「确认完成」只改订单状态、不建发货单 → `delivery` 为 null → 卡片不渲染(空白)
- **方案**:在「确认收款」之后加「发货」按钮,选门店店员作为发货人,写入 `shopOrderDelivery`,从源头让物流页有数据
- **后端可行性(已确认)**`POST /shop/shop-order-delivery`(save) 已存在,实体字段全可空最少传 orderId`listShopStoreUser({storeId})` 已存在;请求层自动注入 `TenantId` 请求头(无需手动传租户);`ShopOrderDelivery` 实体有 orderId/deliveryMethod/sendName/sendPhone/sendAddress
- **前端改动**
- 新增 `src/api/shop/shopOrderDelivery/index.ts``saveShopOrderDelivery(data)` 封装 `POST /shop/shop-order-delivery`
- 补全 `src/api/shop/shopStoreUser/model``ShopStoreUser` 类型缺的 `name`/`phone`/`roleType`/`storeName`/`image`(前端模型此前不完整,后端实体有)
- `src/pages/store/orders/index.tsx`
- `OpType` 增加 `'ship'``OP_LABEL`/`OP_DESC` 补 ship
- `getOrderActions`:已付款 且 `deliveryStatus<20`(或未发货)且 `orderStatus!==1` 时显示「发货」(紫色 `bg-purple-500`)
- 新增状态 `showShipModal`/`clerkList`/`selectedClerkId`/`loadingClerks`/`shipping`
- 新增 `openShipModal(order)`(拉 `listShopStoreUser({storeId: order.storeId})`)与 `handleConfirmShip()`(先 `saveShopOrderDelivery({orderId, deliveryMethod:20, sendName:clerk.name, sendPhone:clerk.phone, sendAddress:order.storeName})`,再 `updateShopOrder({orderId, deliveryStatus:20, deliveryTime})`
- 渲染「选择发货人员」底部弹层(店员列表可点选,确认发货按钮置灰直到选中)
- **设计决策(用户确认)**:① 发货即把订单置「已发货」(deliveryStatus=20);② 发货人可选门店全部店员(经理+店员)
- **物流页**:无需改动,`shopOrderDelivery` 存在即自动渲染发货人
- **验证**tsc 仅剩预存 `@tarojs/taro` 类型缺失环境报错,本文件无新错误
- ⚠️ 行为说明:已付款未发货时「发货」与「确认完成」两个按钮同时显示;店员可跳过发货直接确认完成(该订单仍无发货单,物流页空白,与旧行为一致);如需强制「先发货才能确认完成」,可隐藏未发货订单的「确认完成」按钮(一行判断改动),待用户决定
### 验证
- `npx taro build --type weapp` 构建成功
## 门店中心右上角扫码登录 PC 后台src/pages/store/center/index.tsx
- **需求**:门店中心顶部绿色渐变区右上角加一个二维码扫码图标,点击后调起微信扫码,扫码结果解析出 token 后调 `confirmWechatQRLogin` 确认 PC 端登录
- **参考**`/Users/gxwebsoft/VUE/template-10584/src/pages/user/components/UserCard.tsx` 中的 `UnifiedQRButton` 组件
- **实现**
- 复用已有 API`parseQRContent` + `confirmWechatQRLogin``@/api/passport/qr-login`),与 `src/components/QRLoginScanner.tsx` 同款
- 新增 `handleScanLogin` callback`Taro.scanCode``parseQRContent` → 校验 token/userId → `confirmWechatQRLogin` → 成功弹窗
- 右上角按钮用 `absolute top-3 right-4 z-20` 定位,半透明白色圆形背景 + base64 SVG 图标
- 小程序不支持 `<svg>` 标签,用 `Image` 组件 + `data:image/svg+xml;base64,...` data URI 渲染图标
- 用户取消扫码errMsg 含 'cancel')静默处理
## 修复未付款已发货订单状态显示错误
- **问题**订单列表卡片OrderCard和详情页detail.tsx状态判断时 `!payStatus`(待付款)优先于 `deliveryStatus` 判断,导致"未付款但已发货"(payStatus=false + deliveryStatus=20) 的订单显示"待付款"而非"待收货"
- **修改文件**
- `src/components/common/OrderCard/index.tsx``getCardStatus``deliveryStatus===20/30` 判断提前到 `!payStatus` 之前
- `src/pages/order/detail.tsx``getOrderDisplayStatus``getOrderPhase` 两个函数都做同样调整,物流状态优先于付款状态
- **影响范围**:仅影响"未付款但已发货"的异常场景,正常流程不受影响
### 状态描述对齐已发货待收款payType=9 + deliveryStatus=20 + 未付款)
- **需求**:线下付款(payType=9)已发货但未确认收款的订单,用户端应与门店端一致显示"已发货待收款"(红色),而非"待收货"(蓝色)
- **修改文件**
- `src/components/common/OrderCard/index.tsx``getCardStatus``deliveryStatus===20` 之前加 `!payStatus && payType===9 && deliveryStatus===20` → "已发货待收款"(红色)
- `src/pages/order/detail.tsx``getOrderDisplayStatus` 在物流状态判断前加 `isOffline && !payStatus && (deliveryStatus===20||30)` → "已发货待收款"红色subtitle: 商品已发货,请尽快转账付款)
- `src/pages/store/orders/index.tsx``getStatusText` 恢复 `payType===9 && deliveryStatus===20` → "已发货待收款"`getStatusColor` 对应红色
- **最终统一**:三端状态文案完全对齐
| 场景 | 用户端列表 | 用户端详情 | 门店端 |
|------|-----------|-----------|--------|
| 线下付款+已发货+未付款 | 已发货待收款(红) | 已发货待收款(红) | 已发货待收款(红) |
| 其他已发货 | 待收货(蓝) | 待收货(蓝) | 待收货(蓝) |
### 门店端:拆分"确认完成"为"送达"和"确认完成"两个操作
- **新增操作类型** `deliver`送达deliveryStatus=20已发货且无 sendEndImg 时显示,上传送达照片后按钮自动隐藏(用 sendEndImg 判断,不改变 deliveryStatus
- **修改** `complete`(确认完成):仅已付款才可操作,只标记 orderStatus=1已完成不需要上传凭证
- ⚠️ `deliveryStatus=30` 是"部分发货"含义,不能用来表示"已送达",所有相关判断已清除
- **按钮显示逻辑**
| 场景 | 送达 | 确认完成 | 确认收款 |
|------|:---:|:---:|:---:|
| 线下付款+未付款+已发货(无送达照片) | ✅ | ❌ | ✅ |
| 线下付款+未付款+已发货(有送达照片) | ❌ | ❌ | ✅ |
| 已付款+已发货(无送达照片) | ✅ | ✅ | ❌ |
| 已付款+已发货(有送达照片) | ❌ | ✅ | ❌ |
- **deliveryStatus 含义**10=待发货, 20=已发货, 30=部分发货(未使用)
- **状态文案**deliveryStatus=20+未付款+线下付款 → "已发货待收款"deliveryStatus=20+已付款 → "待收货"(蓝)
### 门店端:改价功能合并到确认收款弹窗 → 又改回来了
- 先去掉了独立的"改价"按钮和修改金额弹窗(`editPrice` OpType、`showEditPriceModal``editReason` 等)
- 在确认收款弹窗中增加了"实付金额"输入框
- **2026-07-17 下午**:用户要求改回来,恢复独立的改价按钮和弹窗
- OpType 加回 `editPrice`
- `getOrderActions` 中线下付款未付款时显示「改价」+「确认收款」两个按钮
- 恢复 `showEditPriceModal`/`editPriceOrder`/`editPriceValue`/`editPriceRemarks`/`editingPrice` 状态
- 恢复 `openEditPriceModal`/`closeEditPriceModal`/`submitEditPrice` 函数
- 恢复独立改价弹窗(订单信息 + 新金额输入 + 改价原因备注)
- 确认收款弹窗去掉「实付金额」输入框,`submitOperation` 中 confirmPay 分支去掉改价逻辑
- 改价按钮样式:橙色背景白字 `bg-orange-500`