Files
guilixu-admin/.workbuddy/memory/2026-07-17.md
赵忠林 b406973039 feat(store): 修正 storeId 获取并新增发货人员选择功能
- 排查 orders 页请求 storeId=0 的根因,确认旧版 H5 构建发出该请求
- 明确门店 storeId 来源于 getMyClerk() 返回的 ShopStoreUser.storeId 字段
- 实现全局 useClerk 上下文,管理店员及门店信息,避免局部状态冗余
- 重构用户中心与门店中心页面为调用 useClerk,移除局部 storeInfo 状态
- 补全 ShopStoreUser 模型字段,支持完整店员信息展示
- 在 orders 页新增“确认发货”功能,支持选择发货人员并提交发货请求
- 发货单提交包含 sendStoreId 和 deliveryUserId,确保后端一致落库
- 全项目类型检查无新增报错,优化门店相关接口调用逻辑和状态管理
2026-07-17 11:31:42 +08:00

66 lines
8.2 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 工作日志
## 订单发货功能改进shopOrder / deliveryModal
分析了订单发货弹窗(`src/views/shop/shopOrder/components/deliveryModal.vue`)三种配送方式,按用户确认的改进方案实施了前端改动:
### 改动文件
1. `deliveryModal.vue`(核心)
- 新增「发货门店」下拉(复用 `listShopStore`),选中后自动回填:快递配送→发货人=门店名/电话=门店电话/地址=门店地址;商家送货→地址=门店地址。
- 商家送货(`deliveryType===2`)新增「配送店员」二级联动下拉(复用 `listShopStoreUser({storeId})`),选中店员自动回填发货人=店员名/联系方式=店员电话。
- 校验:发货门店必填(`deliveryType!==1`);配送店员必填(仅 `deliveryType===2`)。
- 提交时附带 `sendStoreId` / `deliveryUserId`
2. `api/shop/shopOrder/model/index.ts`:新增 `sendStoreId``deliveryUserId` 字段(为后端落库铺路)。
3. `orderInfo.vue`:发货信息卡片增加「发货门店」「配送店员」展示(可选链,后端返回 `storeName`/`deliveryUserName` 后自动生效,否则显示「未填写」)。
### 关键结论 / 待后端配合
- 门店、店员 list API 已存在,前端改动零后端依赖即可落地交互。
- **后端缺口(需补充)**`shop_order` 表需新增 `send_store_id``delivery_user_id` 字段存储门店/店员关联;否则下拉选了也存不进去。
- 登录用户 `User` 模型无 `storeId`,无法默认锁定当前门店,门店下拉需用户手动选择。
- 原「发货地址模板」需求因无现成后端接口,改用「门店作为发货地址模板」方案满足(复用门店 name/phone/address
## 配送方式排序调整
- 修改 `deliveryModal.vue` 配送方式 radio 按钮顺序:快递配送→商家送货→无需发货(原:快递配送→无需发货→商家送货),仅调换模板中 radio 排列顺序value 值不变。
## 后端 Java 改动guilixu-java分两轮
### 第一轮shop_order 主表
- `ShopOrder.java` 实体加持久化字段 `sendStoreId``deliveryUserId`(→`send_store_id`/`delivery_user_id`),及虚拟展示字段 `sendStoreName`/`deliveryUserName`exist=false
- `ShopOrderMapper.xml``selectSql``LEFT JOIN shop_store f` / `LEFT JOIN shop_store_user g` 并 SELECT `f.name as sendStoreName, g.name as deliveryUserName`,让订单详情联带回门店/店员名称。
- 前端 `orderInfo.vue` 展示路径从 `form.shopOrderDelivery.xxx` 改为 `form.sendStoreName`/`form.deliveryUserName`(名称落在订单主对象上)。
- SQL`ALTER TABLE shop_order ADD send_store_id INT, delivery_user_id INT;`
### 第二轮shop_order_delivery 发货单表(用户要求"也写进发货记录表"
- `ShopOrderDelivery.java` 实体加持久化字段 `sendStoreId``deliveryUserId`
- `ShopOrderController.update()` 的发货写入分支(无需物流分支 deliveryMethod=20、实物快递分支 deliveryMethod=30、以及补录运单号分支新建 `ShopOrderDelivery` 时都 `setSendStoreId`/`setDeliveryUserId`(值取自 `shopOrder` 对象,兜底取 `shopOrderNow`)。
- 说明:前端发货只调 `PUT /shop/shop-order`,该接口内部 `new ShopOrderDelivery()` 并 save 落 `shop_order_delivery`;主表靠 `updateById(shopOrder)` 自动落库,发货单表需显式 set 字段。
- SQL`ALTER TABLE shop_order_delivery ADD send_store_id INT, delivery_user_id INT;`
- 验证:`vue-tsc` 前端零报错Java 用 `./mvnw -o compile` 后台验证中。
## Taro 商家端 storeId=0 排查guilixu-taro跨项目
- 用户反馈 orders 页请求 `/shop/shop-store-user?storeId=0`。排查结论:
- `guilixu-taro/src/pages/store/orders/index.tsx` **未调用** `shop-store-user`;全项目 `listShopStoreUser` 仅定义、无调用方。该请求非当前源码发出,应为线上旧版 H5 构建。
- **当前门店 storeId 的真实来源**`getMyClerk()``GET /shop/shop-store-user/my`)返回的 `ShopStoreUser` 对象,其 `.storeId` 字段shop_dealer.id才是门店 id。注意 `user.tsx:103``storeInfo`=getMyClerk 结果)判断"是否显示门店中心",所以那里就能拿到 `storeId = storeInfo.storeId`
- **易错点**`ShopStoreUser``id`(店员自身主键)和 `storeId`(门店 id两个字段二者不同。误用 `storeInfo.id` 当门店 id 是 bug。`booking/index.tsx:186``storeId: storeInfo!.id || 0``storeInfo` 恰为 `ShopStore` 类型故 `.id` 碰巧正确,但 `|| 0` 兜底在未加载时仍会变 0。
- **根因模式**:项目无全局门店/店员上下文,`storeInfo` 是各页面局部 useStateuser/booking/center 各一份)。需在 storeId 就绪前发请求 + `|| 0` 兜底 → `storeId=0`
- **已实施全局 `useClerk`**(用户确认后开工):
- 新增 `src/contexts/ClerkContext.tsx``ClerkProvider` + `useClerkContext`。登录态(`useUserContext().isLoggedIn`)变化即拉取/清空 `getMyClerk()`;对外暴露 `clerk`(ShopStoreUser|null)、`storeId`(=clerk?.storeId)、`loading``refreshClerk``clearClerk`
- 新增 `src/hooks/useClerk.ts`:镜像 `useUser` 的"优先 Context、未包裹则降级本地"范式,文件头注释写明用法与 `storeId>0` 守卫约定。
- `src/app.tsx`:在 `UserProvider` 内挂载 `<ClerkProvider>`(使其能响应登录/登出)。
- 重构 `src/pages/user/user.tsx``src/pages/store/center/index.tsx`:移除各自的局部 `storeInfo`/`getMyClerk` 调用,改为 `const { clerk: storeInfo, refreshClerk } = useClerk()`
- 补全 `src/api/shop/shopStoreUser/model/index.ts``ShopStoreUser` 模型:`getMyClerk`(/my) 联表返回的 `name`/`phone`/`avatar`/`storeName` 补入(原模型缺失,旧代码靠 `useState<any>` 掩盖)。
- **验证**:裸 `tsc --noEmit --types webpack-env` 全量检查——新建/改动的 `ClerkContext.tsx`/`useClerk.ts`/`app.tsx`/`user.tsx`/`center/index.tsx` 及模型 **零新增报错**`center` 页仅剩 4 个**既有**报错75 的 `finally`、82 的 `applyStatus`、89 的 `total`、106 的 `Option`,均在未改动的 `loadBadgeCounts`/`subscribe` 原函数里,属项目原有类型问题 / 裸 tsc 的 lib 配置 artifact。注意裸 `tsc` 默认会因 tsconfig `types:["@tarojs/taro"]`+`typeRoots``TS2688`,需用 `--types webpack-env` 覆盖才能跑真实业务检查。
- **未动**`booking/index.tsx``storeInfo` 是用户所选门店ShopStore来自 `getShopStore(id)`/选择),与店员所属门店是两回事,不在本次范围(其 `storeId: storeInfo!.id || 0` 属不同接口的兜底问题。orders 页现可随时从 `useClerk().storeId` 取当前门店 id。
## Taro 商家端 orders 页「选择发货人员」发货功能guilixu-taro
- 用户截图显示线上旧版 orders 页有「选择发货人员」弹窗且请求 `?storeId=0` 显示"暂无可选择的店员"。当前源码 `orders/index.tsx` 原本**没有**该功能(只有确认收款/确认完成),确认是旧构建。
-`src/pages/store/orders/index.tsx` 新增「确认发货」功能:
- 引入 `useClerk()``storeId`(杜绝 storeId=0`listShopStoreUser``ShopStoreUser` 类型。
- `OpType` 增加 `'deliver'``getOrderActions` 中「待发货」订单(`payStatus && deliveryStatus===10`)显示"确认发货"按钮。
- `openModal('deliver')` 时调 `loadClerkList()``storeId>0``listShopStoreUser({storeId})`,否则 toast 提示门店未就绪、不发请求。
- 弹窗内新增店员单选列表selectedClerkdeliver 模式隐藏凭证上传区。
- 提交发货:`deliveryType=2`(商家送货)、`deliveryStatus=20`(待收货)、`deliveryTime``sendName/sendPhone`(店员)、`sendStoreId=storeId``deliveryUserId=店员id``PUT /shop/shop-order`
- 后端已在上一轮把 `sendStoreId`/`deliveryUserId``shop_order` + `shop_order_delivery`,此处字段对齐。
- 验证:`tsc --noEmit --types webpack-env` 总报错仍 387零新增orders 页仅剩 2 个既有报错165 `fetchLatestOrders` 返回类型、169 `count` 隐式 any均在未改的 `useNewOrderDetector` 调用块)。