Files
xinlong-shop-taro/.workbuddy/memory/2026-07-14.md
赵忠林 596fa27d60 fix(order): 修复订单与用户页面登录校验和跳转逻辑
- 订单列表页未登录时弹出登录引导弹窗,而非直接跳转
- 登录页登录成功添加订单列表为白名单,支持登录后回跳订单页
- 我的页面菜单和订单按钮未登录时增加登录弹窗拦截
- 需登录菜单项添加 requireAuth 标记并视觉降级为半透明
- 订单快捷入口增加登录拦截和登录后回跳逻辑
- 修改“联系电话”为新号码,更新联系信息
2026-07-14 01:48:12 +08:00

134 lines
9.6 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-14
### 问题
购物车页面pages/shop/cart商品显示异常
- 商品名称/图片/价格信息缺失
- 加入购物车后无法正确显示
### 根因
`CartContext.refresh()` 方法在将后端 API 返回的购物车项映射为前端 `CartItem` 时,**遗漏了 `product`(商品详情)和 `sku`SKU 详情)嵌套对象的映射**。导致页面中 `item.product?.name/image/price``item.sku?.price/image` 均为 `undefined`UI 只能显示硬编码的默认值。
### 修改
1. **`src/contexts/CartContext.tsx`**(核心修复)
- `refresh()``mappedItems` 映射中补充 `product``sku` 字段
- 使用 `(item as any).product` / `(item as any).sku` 获取后端返回的嵌套对象
2. **`src/utils/image.ts`**(增强健壮性)
- 新增 `ensureFullUrl()` 辅助函数:相对路径自动补全 OSS 域名 `https://oss.wsdns.cn`
- `getCompressedImageUrl()` 内部调用 `ensureFullUrl` 确保 URL 完整性
3. **`src/pages/shop/cart.tsx`**(补充图片回退源)
- 图片 `src` 回退链增加 `(item.sku as any)?.image`
- 完整回退链:`goodsImage -> product.image -> sku.image -> ''`
## 收藏列表图片/价格不显示修复2026-07-14
### 问题
`pages/user/favorite-list/index` 收藏列表:商品图片、价格、名称均空白。
### 根因
后端 `/api/shop/goods/favorite/list`(前端 `/shop/goods/favorite/list`)走 `ShopGoodsFavoriteServiceImpl.listRel``selectListRel`SQL 只 `SELECT a.*` 未关联商品表,返回字段仅 `id/userId/goodsId/merchantId/tenantId/createTime`,不含商品信息。前端依赖 `goodsImage/goodsName/price/salePrice` 均为 undefined。
### 修改方案1后端返回商品信息
1. **后端** `guilixu-java`
- `ShopGoodsFavorite.java`:新增 4 个 `@TableField(exist=false)` 非持久化字段 `goodsName(String)``goodsImage(String)``price(BigDecimal)``salePrice(BigDecimal)`,并补 `BigDecimal`/`TableField` import。
- `ShopGoodsFavoriteMapper.xml``selectSql``SELECT a.*, g.name AS goods_name, g.image AS goods_image, g.price AS price, g.sale_price AS sale_price``LEFT JOIN shop_goods g ON a.goods_id = g.goods_id`(已确认 `map-underscore-to-camel-case: true`,别名可映射)。
- 注意:本机无 maven 无法编译,改动为常规 MyBatis/MP 写法,需用户自行编译部署。
2. **前端**
- `src/api/shop/shopGoodsFavorite/model.ts``favoriteId` 改为 `id`(后端实际返回 `id`);新增 `price?: string|number``salePrice` 改为 `string|number`
- `pages/user/favorite-list/index.tsx`:图片用 `item.goodsImage`;价格改为优先 `item.price`(到手价),`salePrice` 作为划线价(`salePrice > price` 时显示);`key` 改用 `item.id ?? item.goodsId`(原 `favoriteId` 始终 undefined 会导致 key 重复)。
- 注:`src/pages/favorite-list.tsx` 为未注册路由的重复文件,未改动。
### 遗留(非本次范围,供参考)
adapter `/list` 接口忽略分页,一次返回全部收藏;前端 `listShopGoodsFavorite({page,limit:20})` 的无限滚动在收藏>20条时会重复追加。如需彻底解决建议改前端走 `/page` 接口或后端 `/list` 支持分页。
## 购物车更新 API 请求方式修复2026-07-14
### 问题
`PUT /api/shop/shop-cart/{id}` 返回 `HttpRequestMethodNotSupportedException: Request method 'PUT' not supported`
### 根因
`src/api/shop/shopCart/index.ts` 中 3 个函数用了非标准 URL 模式 `PUT /shop/shop-cart/{id}`,而项目所有其他 APIshopOrder、shopArticle 等)的更新操作统一走 `PUT /shop/shop-cart`(基础 URLid 放 body
### 修改
1. `updateCartNum``PUT /shop/shop-cart/{id}` + `{quantity}``PUT /shop/shop-cart` + `{id, num}`
2. `updateCartChecked``PUT /shop/shop-cart/{id}` + `{selected}``PUT /shop/shop-cart` + `{id, checked}`(同时修正字段名 `selected``checked` 与 model 一致)
3. `updateCartAllChecked``PUT /shop/shop-cart/selected` + `{selected}``POST /shop/shop-cart/selected` + `{checked}`(改用 POST自定义批量操作更可能支持 POSTCartContext 已有静默 catch 兜底)
## 购物车后端 SQL 关联查询修复2026-07-14
### 问题
`GET /api/shop/shop-cart` 返回的数据没有商品图片、价格等信息。前端 `CartContext.refresh()` 已映射 `goodsName/goodsImage/skuPrice/skuSpec/stock` 等字段,但后端根本没返回这些字段。
### 根因
后端 `ShopCartMapper.xml` 的 SQL 只做 `SELECT a.* FROM shop_cart a`,没有 JOIN 商品表和 SKU 表。
### 后端修改(`guilixu-java` 项目)
1. **`ShopCart.java`**:新增 7 个 `@TableField(exist = false)` 非持久化字段:`goodsName``goodsImage``skuPrice``skuSpec``stock``salePrice``dealerPrice`;补充 `TableField` import
2. **`ShopCartMapper.xml`**SQL 改为 `LEFT JOIN shop_goods g ON a.goods_id = g.goods_id` + `LEFT JOIN shop_goods_sku s ON a.sku_id = s.id`SELECT 别名映射到新字段(`COALESCE(s.price, g.price) AS sku_price``COALESCE(s.stock, g.stock) AS stock`);同时修复 `userId/goodsId/merchantId``LIKE` 改为 `=`(原 LIKE 会导致 userId=1 匹配到 10/11/21 等)
3. **`ShopCartController.java`**`list()` 方法自动按当前登录用户过滤(`param.setUserId(loginUser.getUserId().longValue())`
### 前端修改
4. **`src/api/shop/shopCart/model/index.ts`**`ShopCart` 接口新增 `salePrice``dealerPrice` 字段
5. **`src/contexts/CartContext.tsx`**`CartItem` 新增 `salePrice``dealerPrice``refresh()` 映射这两个字段;`calcPrice()` VIP 优先用扁平 `i.dealerPrice`(之前只看 `i.product?.dealerPrice`
6. **`src/pages/shop/cart.tsx`** + **`src/pages/shop/checkout.tsx`**:价格显示逻辑同步更新,优先使用扁平 `item.dealerPrice` / `item.salePrice`
## 购物车前后端字段名对齐修复2026-07-14
### 问题
修改购物车数量时后端报 `UPDATE shop_cart WHERE id=?`SET 子句为空MyBatis-Plus 找不到要更新的字段。
### 根因
前后端字段名不匹配:
- 前端发送 `num`,后端实体字段是 `cartNum` → Jackson 反序列化时 `cartNum` 为 null → 空 UPDATE
- 前端发送 `checked`,后端实体字段是 `selected` → 同样不匹配
- 列表返回 `cartNum`,前端读 `item.num` → 数量永远为默认值 1
### 修改文件
1. **`src/api/shop/shopCart/model/index.ts`**`ShopCart.num``cartNum`;新增 `selected` 字段;`AddToCartParam.num``cartNum``UpdateCartNumParam.num``cartNum`
2. **`src/api/shop/shopCart/index.ts`**`updateCartNum``{id, cartNum}``updateCartChecked``{id, selected}`
3. **`src/contexts/CartContext.tsx`**`refresh()``item.cartNum``item.selected``addItem()``cartNum``updateQuantity` 调用 `{id, cartNum}`
4. **`src/pages/shop/index.tsx`** + **`src/pages/shop/category.tsx`**`addToCart` 参数 `num``cartNum`
## 禁用 loginByOpenId 静默登录2026-07-14
### 改动
- **`src/contexts/UserContext.tsx`**:移除"情况3"静默登录块(`Taro.login` + `loginByOpenId`),无 token 时直接保持未登录状态;清理 `loginByOpenId``TenantId` 无用导入
- **`src/hooks/useUser.ts`**:移除降级方案中的 `loginByOpenId` 调用,仅从 storage 读取;清理 `loginByOpenId``TenantId` 无用导入
- `src/api/layout/index.ts``loginByOpenId` 函数定义保留,仅不再被调用
## 商城分类页价格登录可见2026-07-14
### 改动
- **`src/pages/shop/index.tsx`**:价格显示从手写 `Text` 改为 `Price` 组件 + `loginMask` 属性(与首页一致),游客看到"登录后查看价格"VIP 划线价逻辑保留在 `original` prop 中;单位 `unitName` 仅登录后显示
## 订单列表页未登录可查看订单 Bug 修复2026-07-14
### 问题
`pages/order/list` 未登录用户也能看到订单数据。
### 根因
页面缺少登录校验——`useEffect` 直接调用 `loadOrders`,未登录时 `user?.userId``undefined`,后端未按用户过滤直接返回了订单。
### 修改
- **`src/pages/order/list.tsx`**
1.`useUser()` 获取 `isLoggedIn`
2. `useEffect` 中未登录时调用 `requireLogin({ action: 'viewOrder', redirect: '/pages/order/list', content: '登录后才能查看订单,是否前往登录?' })` 弹窗引导,而不是直接跳转
3. render 中 `if (!isLoggedIn) return null` 兜底,避免未登录时渲染订单内容
- **`src/passport/login.tsx`**:登录成功后的 `tabBarUrls` 白名单补全 `pages/order/list`,确保从订单入口登录后能 `switchTab` 回订单页
## 我的页面未登录可点击需登录功能 Bug 修复2026-07-14
### 问题
`pages/user/user` 未登录时,点击「我的订单」下的按钮(待付款/待发货/待收货/已完成、「全部订单」、以及菜单中的「升级VIP会员」「我的钱包」「收货地址」「我的收藏」都能直接跳转页面。
### 修改
- **`src/pages/user/user.tsx`**
1. 导入 `requireLogin` from `@/utils/login-guard`
2. 给需要登录的菜单项加 `requireAuth: true` 标记升级VIP会员/门店中心/我的钱包/收货地址/我的收藏)
3. 新增 `handleMenuClick(item)``requireAuth` 项调用 `requireLogin` 弹窗拦截,已登录才 `navigateTo`
4. 新增 `handleOrderTabClick(status)``handleViewAllOrders()`:订单入口 `requireLogin` 拦截,并加 `redirect: '/pages/order/list'` 让登录后回跳订单页
5. 未登录时需登录的菜单项和订单按钮加 `opacity-50` 视觉降级
6. 「帮助中心」「设置」不需要登录,保持原样