- 在微信客服按钮补全必要属性 sessionFrom、onContact、showMessageCard 和 sendMessageTitle - 将按钮样式由 Tailwind 类改为内联样式,避免 border-0 干扰原生按钮渲染 - 添加真机预览测试提示,解决开发者工具无法使用问题 - `ShopChatMessage` 和相关接口新增 conversationId 字段支持消息会话关联 - 消息发送时补全 conversationId 和发送人 ID,保证消息关联准确 - 将会话列表中引用的不存在字段 lastMessage 替换为 content - 移除无用的 useReachBottom,改用 ScrollView 的 onScrollToLower 事件加载历史消息 - 删除未使用的 scrollToBottom ref - 增加条件守卫避免非历史展开时加载更多消息
19 KiB
购物车功能修复(2026-07-14)
问题
购物车页面(pages/shop/cart)商品显示异常:
- 商品名称/图片/价格信息缺失
- 加入购物车后无法正确显示
根因
CartContext.refresh() 方法在将后端 API 返回的购物车项映射为前端 CartItem 时,遗漏了 product(商品详情)和 sku(SKU 详情)嵌套对象的映射。导致页面中 item.product?.name/image/price 和 item.sku?.price/image 均为 undefined,UI 只能显示硬编码的默认值。
修改
-
src/contexts/CartContext.tsx(核心修复)refresh()的mappedItems映射中补充product和sku字段- 使用
(item as any).product/(item as any).sku获取后端返回的嵌套对象
-
src/utils/image.ts(增强健壮性)- 新增
ensureFullUrl()辅助函数:相对路径自动补全 OSS 域名https://oss.wsdns.cn getCompressedImageUrl()内部调用ensureFullUrl确保 URL 完整性
- 新增
-
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:后端返回商品信息)
-
后端
guilixu-java:ShopGoodsFavorite.java:新增 4 个@TableField(exist=false)非持久化字段goodsName(String)、goodsImage(String)、price(BigDecimal)、salePrice(BigDecimal),并补BigDecimal/TableFieldimport。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 写法,需用户自行编译部署。
-
前端:
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},而项目所有其他 API(shopOrder、shopArticle 等)的更新操作统一走 PUT /shop/shop-cart(基础 URL,id 放 body)。
修改
updateCartNum:PUT /shop/shop-cart/{id}+{quantity}→PUT /shop/shop-cart+{id, num}updateCartChecked:PUT /shop/shop-cart/{id}+{selected}→PUT /shop/shop-cart+{id, checked}(同时修正字段名selected→checked与 model 一致)updateCartAllChecked:PUT /shop/shop-cart/selected+{selected}→POST /shop/shop-cart/selected+{checked}(改用 POST,自定义批量操作更可能支持 POST;CartContext 已有静默 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 项目)
ShopCart.java:新增 7 个@TableField(exist = false)非持久化字段:goodsName、goodsImage、skuPrice、skuSpec、stock、salePrice、dealerPrice;补充TableFieldimportShopCartMapper.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 等)ShopCartController.java:list()方法自动按当前登录用户过滤(param.setUserId(loginUser.getUserId().longValue()))
前端修改
src/api/shop/shopCart/model/index.ts:ShopCart接口新增salePrice、dealerPrice字段src/contexts/CartContext.tsx:CartItem新增salePrice、dealerPrice;refresh()映射这两个字段;calcPrice()VIP 优先用扁平i.dealerPrice(之前只看i.product?.dealerPrice)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
修改文件
src/api/shop/shopCart/model/index.ts:ShopCart.num→cartNum;新增selected字段;AddToCartParam.num→cartNum;UpdateCartNumParam.num→cartNumsrc/api/shop/shopCart/index.ts:updateCartNum发{id, cartNum};updateCartChecked发{id, selected}src/contexts/CartContext.tsx:refresh()读item.cartNum和item.selected;addItem()发cartNum;updateQuantity调用{id, cartNum}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 划线价逻辑保留在originalprop 中;单位unitName仅登录后显示
订单列表页未登录可查看订单 Bug 修复(2026-07-14)
问题
pages/order/list 未登录用户也能看到订单数据。
根因
页面缺少登录校验——useEffect 直接调用 loadOrders,未登录时 user?.userId 为 undefined,后端未按用户过滤直接返回了订单。
修改
src/pages/order/list.tsx:- 从
useUser()获取isLoggedIn useEffect中未登录时调用requireLogin({ action: 'viewOrder', redirect: '/pages/order/list', content: '登录后才能查看订单,是否前往登录?' })弹窗引导,而不是直接跳转- 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:- 导入
requireLoginfrom@/utils/login-guard - 给需要登录的菜单项加
requireAuth: true标记(升级VIP会员/门店中心/我的钱包/收货地址/我的收藏) - 新增
handleMenuClick(item):requireAuth项调用requireLogin弹窗拦截,已登录才navigateTo - 新增
handleOrderTabClick(status)和handleViewAllOrders():订单入口requireLogin拦截,并加redirect: '/pages/order/list'让登录后回跳订单页 - 未登录时需登录的菜单项和订单按钮加
opacity-50视觉降级 - 「帮助中心」「设置」不需要登录,保持原样
- 导入
订单列表页登录后仍看到别人订单 Bug 修复(2026-07-14)
问题
pages/order/list 刚登录成功后仍能看到别人的订单,刷新重进后才正常。
根因
loadOrders 的 useCallback 依赖数组为 [updateTabState],未包含 user,导致闭包过期——登录后 isLoggedIn 变 true 触发 effect 调用 loadOrders,但闭包中的 user 仍是初始渲染时的 null,userId: user?.userId 传了 undefined,后端未按用户过滤返回了全部订单。
修改
src/pages/order/list.tsx:- 新增
userIdRef(useRef(user?.userId)),每渲染同步userIdRef.current = user?.userId,避免闭包过期 loadOrders开头从userIdRef.current取 userId,if (!userId) return硬拦截——没有当前登录用户 userId 就禁止加载useEffect中增加if (!user?.userId) return判断,已登录但 userId 还没拿到时等待下次渲染useEffect依赖数组加user?.userId,userId 变化时重新触发加载
- 新增
商城列表页浮动购物车按钮(2026-07-14)
需求
pages/shop/index 页面右下角添加浮动购物车按钮,显示购物车商品数量角标。
实现
src/pages/shop/index.tsx:- 从
useCartContext()额外解构totalCount - 页面末尾添加 fixed 定位浮动按钮:绿色圆形(48px),
bottom:80px right:16px(避开 tabBar) totalCount > 0时右上角显示红色角标,超过 99 显示99+- 点击
Taro.navigateTo跳转购物车页(cart 非 tabBar 页) - 数量实时更新:
addItem内部调refresh()→totalCount派生值自动重渲染
- 从
购物车页面进入不刷新 Bug 修复(2026-07-14)
问题
从商品列表页/分类页加入购物车后,进入购物车页面,新加的商品不显示,只有之前已在购物车里的商品。
根因
- 购物车页面缺少
useDidShow:cart.tsx仅在useEffect([isLoggedIn])中调用refresh(),登录状态不变时不会重新拉取数据。从其他页面返回购物车时,页面不刷新。 - 商品列表页/分类页直接调 API 加购:
shop/index.tsx和shop/category.tsx直接调用addToCartAPI,未通过CartContext.addItem,导致 CartContext 状态不同步(addItem内部会调refresh())。
修改
src/pages/shop/cart.tsx:导入useDidShow,添加useDidShow(() => { if (isLoggedIn) refresh() }),页面每次显示时从服务端拉取最新购物车数据src/pages/shop/index.tsx:导入useCartContext,handleAddToCart改用addItem(product, undefined, product.step || 1)代替直接调addToCartAPI;移除addToCart导入src/pages/shop/category.tsx:同上,改用useCartContext的addItem
需求
首页顶部搜索栏右侧铃铛图标,门店店员有新订单时能收到提醒。
改动
src/pages/index/index.tsx:- 导入
useNewOrderDetector、getMyClerk、pageShopOrder、useDidShow、useCallback、useRef - 登录后调
getMyClerk()检测店员身份,存isClerkstate +isClerkRefref(ref 用于轮询回调中读取最新值,避免闭包过期) useDidShow时也刷新店员身份- 接入
useNewOrderDetector:30秒轮询pageShopOrder({page:1,limit:5});fetchLatestOrders内用isClerkRef.current网关——非店员直接返回空数组(不建 baseline,无副作用) - 新订单回调:
Taro.vibrateShort震动 +Taro.showToast提示"您有 N 条新订单" - 铃铛角标从静态红点改为动态:
newOrderCount > 0显示数字角标(>99 显示 99+),=== 0时显示小圆点 - 点击处理:店员 →
navigateTo门店订单页(有新订单时先clearUnread());普通用户 → 通知页
- 导入
设计要点
isClerkRef解决 hooks 闭包过期问题——fetchLatestOrders的useCallback依赖空数组,但通过 ref 读取最新店员状态- 非店员时
fetchLatestOrders返回[],hook 内doCheck在list.length === 0时 return,knownOrderIdsRef保持null不建 baseline;店员身份确认后首次真实请求才建 baseline,不会误报 useNewOrderDetector内部已处理useDidShow/useDidHide生命周期,tabBar 页切走自动停轮询
商品分类页浮动购物车图标优化(2026-07-14)
问题
商品分类页(pages/shop/index)右下角绿色圆形浮动购物车按钮,使用 emoji 🛒 作为图标,在绿色背景上对比度不足、线条不清晰。
修改
- 新增白色线条购物车 SVG 图标:
src/assets/icons/cart.svg - 导出 base64 数据 URI 常量:
src/assets/icons/index.ts中CART_ICON_WHITE src/pages/shop/index.tsx浮动购物车按钮改用Image组件加载CART_ICON_WHITE(28×28px,mode='aspectFit'),图标更清晰
商品详情页出现孤立 "0" 排查修复(2026-07-14)
问题
pages/shop/product-detail 价格区域下方出现一个不归属任何标签的孤立 0。
根因
src/pages/shop/product-detail.tsx 中赚取积分行的条件渲染写成:
{product.gainIntegral && Number(product.gainIntegral) > 0 && (...)}
当后端返回 gainIntegral 为数字 0 时,JSX 短路与运算直接返回 0,React 会把它渲染成一个纯文本节点。这就是页面上那个孤立的 0。
修改
src/pages/shop/product-detail.tsx:- 去掉条件里的
product.gainIntegral &&,改成{Number(product.gainIntegral) > 0 && (...)},避免0泄漏。 - 顺手把配送区域
goodsWeight的同类写法也改成{Number(product.goodsWeight) > 0 && (...)},防止重量为 0 时同样泄漏。 - 另按用户要求「是 0 就不显示」,把销量行也改为
{Number(product.sales) > 0 && (...)},销量为 0 时整条「销量: 0」不渲染。
- 去掉条件里的
订单列表页下单后不自动刷新修复(2026-07-14)
问题
pages/order/list 下单后从 checkout 页 Taro.switchTab 跳过来,订单列表不刷新,看不到新订单。
根因
订单列表页是 tabBar 页,switchTab 不会重新挂载组件。useEffect 依赖 [tabIndex, isLoggedIn, user?.userId],这些值不变就不会重新触发;且 effect 内有 if (!tabStates[tabIndex].initialized) 守卫,页面已初始化过就直接跳过。
修改
src/pages/order/list.tsx:新增Taro.useDidShow生命周期钩子- 用
isFirstShowref 跳过首次显示(由useEffect处理初始加载) - 后续每次显示时:标记所有 tab 为
initialized: false(切 tab 时会重新加载),并立即loadOrders(tabIndex, 1)刷新当前 tab - 与之前购物车页
useDidShow刷新是同一模式
- 用
商品详情页底部购物车角标(2026-07-14)
需求
pages/shop/product-detail 底部操作栏的购物车入口需要显示当前购物车商品数量角标。
修改
src/pages/shop/product-detail.tsx:- 从
useCartContext额外解构totalCount、refresh - 引入
useDidShow,页面显示时(已登录)调refresh()拉取最新购物车,保证角标准确 - 购物车图标外包一层
relative容器,totalCount > 0时右上角显示红色圆角角标(>99 显示99+),样式与商城列表页浮动购物车角标一致
- 从
在线客服功能修复(2026-07-14)
问题
pages/user/customer-service/index 在线客服功能使用不了,用户已在微信后台添加客服人员。
根因(多个问题叠加)
openType="contact"按钮缺少关键属性:缺少sessionFrom(会话来源标识)、onContact(客服回调)、showMessageCard/sendMessageTitle(客服消息卡片),且按钮被 Tailwindborder-0类可能干扰原生渲染- 开发者工具限制:
open-type="contact"在微信开发者工具中不生效,只能在真机上使用,页面缺少提示 - 自定义聊天系统消息发送缺失
conversationId:addShopChatMessage调用未传conversationId,消息无法关联到会话;ShopChatMessage模型本身也缺少该字段 - 消息发送缺失
formUserId:发送人 ID 未设置 conv.lastMessage字段不存在:ShopChatConversation模型只有content字段,代码引用了不存在的lastMessageuseReachBottom用错场景:页面使用ScrollView组件,useReachBottom是页面级滚动钩子,对 ScrollView 无效,应改用onScrollToLowerscrollToBottomref 设了但从未使用:死代码
修改
src/api/shop/shopChatMessage/model/index.ts:ShopChatMessage接口新增conversationId?: numberShopChatMessageParam接口新增conversationId?: number
src/pages/user/customer-service/index.tsx(全面修复):- 微信客服按钮补全
sessionFrom="customer_service"、onContact、showMessageCard、sendMessageTitle - 按钮样式从 Tailwind 类改为 inline style(避免
border-0干扰原生按钮),显式设置border: 'none' - 添加"需真机预览测试"提示文字
addShopChatMessage调用补全conversationId和formUserId(从Taro.getStorageSync('UserId')获取)conv.lastMessage全部改为conv.content- 会话列表更新
lastMessage: text改为content: text - 移除
useReachBottom,改用 ScrollViewonScrollToLower+lowerThreshold={50} - 移除未使用的
scrollToBottomref pageShopChatMessage参数去掉as any断言(模型已支持conversationId)- 新增
getCurrentUserId()辅助函数 handleScrollToLower增加showHistory条件守卫(仅展开历史时才加载更多)
- 微信客服按钮补全