简介
本模块面向DouPHP小程序的商品页面,覆盖商品列表页、商品分类页与商品详情页的完整实现。重点说明:
- 商品数据的获取、展示与交互逻辑
- 列表筛选与排序(按价格、销量、评分等维度)及关键词搜索能力
- 详情页图片轮播、规格选择(SKU管理)、库存显示、价格计算
- 性能优化策略(图片懒加载、分页加载、数据缓存)
- 完整的页面开发示例(API调用、收藏、分享)
- 常见问题解决方案(图片加载失败、库存实时更新、价格变动同步)
项目结构
小程序端采用多主题结构(default、company),商品相关页面位于 miniprogram//pages/product;后端API控制器位于 api/controller/product;路由定义在 api/route/product.php;业务服务在前端服务层 front/service/product/ProductService.php。
graph TB
subgraph "小程序端"
PList["商品分类页<br/>product_category.ts"]
PDetail["商品详情页<br/>product.ts"]
end
subgraph "API层"
R["路由<br/>api/route/product.php"]
C["控制器<br/>ProductController.php"]
end
subgraph "服务层"
S["产品服务<br/>ProductService.php"]
end
PList --> R --> C --> S
PDetail --> R --> C --> S
核心组件
- 商品列表/分类页(product_category.ts)
- 负责分类树切换、品牌过滤、排序维度(by/sort)、分页加载、分享标题设置
- 通过 product API 拉取商品列表、分类树、排序选项与当前分类信息
- 商品详情页(product.ts)
- 负责商品详情加载、图片轮播、规格选择(SKU)、评论分页、收藏、优惠券领取、加入购物车/立即购买、分享
- 通过 product.show 与 product.attribute_list 接口获取详情与规格数据
- 后端控制器(ProductController.php)
- index:商品列表(支持分类、品牌、排序、分页、归档时间)
- show:商品详情(含是否开启订单功能、优惠券列表)
- attribute_list:根据已选规格动态返回可选属性、价格、库存等
架构总览
小程序页面通过统一HTTP客户端调用API路由,路由将请求分发至ProductController对应方法,控制器调用前端服务层进行数据组装与业务处理,最终返回JSON给小程序渲染。
sequenceDiagram
participant U as "用户"
participant M as "小程序页面<br/>product.ts / product_category.ts"
participant H as "HTTP客户端"
participant R as "API路由<br/>product.php"
participant C as "控制器<br/>ProductController.php"
participant S as "服务层<br/>ProductService.php"
U->>M : 打开商品列表/详情
M->>H : 发起GET/POST请求
H->>R : 路由匹配
R->>C : 调用index/show/attribute_list
C->>S : 构建数据列表/详情/SKU
S-->>C : 返回结构化数据
C-->>H : ApiResponse : : success(...)
H-->>M : 解析并更新UI
详细组件分析
商品分类页(列表)
- 功能要点
- 分类树切换:点击左侧分类项刷新右侧列表
- 品牌过滤:支持 brand_id 参数
- 排序:by/sort 控制排序维度与方向
- 分页:onReachBottom 触发下一页加载
- 分享:设置 shareTitle 为当前分类标题
- 关键流程
- onLoad/onShow 初始化并加载数据
- loadData 调用 product 接口,传入 category_id、brand_id、by、sort、page
- 下拉刷新与上拉加载更多
flowchart TD
Start(["进入商品分类页"]) --> Init["初始化参数<br/>category_id, brand_id"]
Init --> Load["loadData() 请求 product 接口"]
Load --> Data{"返回数据?"}
Data -- 否 --> Error["提示错误并停止加载"]
Data -- 是 --> Render["渲染列表/分类树/排序选项"]
Render --> Sort{"用户点击排序?"}
Sort -- 是 --> Reset["重置页码=1, nomore=false"] --> Load
Sort -- 否 --> More{"触底加载更多?"}
More -- 是 --> NextPage["page+1"] --> Load
More -- 否 --> End(["结束"])
商品详情页
- 功能要点
- 详情加载:product.show 返回商品基础信息、是否开启订单、优惠券列表
- 规格选择:product.attribute_list 根据已选属性动态返回可选属性、价格、库存、SKU盒信息
- 图片轮播:swiper 自动播放与手动切换,监听 imageLoad 计算高度避免抖动
- 评论分页:comment.list 支持拼接加载
- 收藏:favorites.user.store 切换收藏状态
- 购物车/购买:order.cart.store 支持加入购物车或立即购买
- 分享:设置分享标题
- 关键流程
sequenceDiagram
participant P as "详情页<br/>product.ts"
participant A as "API : product.show"
participant B as "API : product.attribute_list"
participant F as "API : favorites.user.store"
participant O as "API : order.cart.store"
P->>A : GET 商品详情(id)
A-->>P : 返回商品数据/开关/优惠券
P->>B : GET 规格属性(含已选attribute_data)
B-->>P : 返回attribute_list/box(价格/库存/SKU)
P->>F : POST 收藏(可取消)
F-->>P : 返回最新收藏状态
P->>O : POST 加入购物车/立即购买
O-->>P : 跳转结算或购物车
后端控制器与数据构建
- index(商品列表)
- 接收 id/category_slug、year/month(归档)、brand_id、by、sort、page
- 使用 ProductService.buildProductListData 构建列表数据,包含分页、排序、分类树、标题等
- show(商品详情)
- 校验id后调用 buildProductShowData,返回商品详情、开关配置、优惠券列表
- attribute_list(规格属性)
- 解析 attribute_data,调用 buildApiAttributeData 返回可选属性、价格、库存、SKU盒等信息
classDiagram
class ProductController {
+index(request)
+show(request)
+attributeList(request)
-buildProductCategoryInfo(catId)
}
class FrontProductService {
+buildProductListData(...)
+buildProductShowData(...)
+buildApiAttributeData(...)
+findCategoryById(...)
}
ProductController --> FrontProductService : "依赖"
依赖关系分析
- 小程序页面依赖
- HTTP客户端 services/http.js
- 路由工具 utils/route.js
- 全局状态 stores/commonStore(features、site、lang等)
- 认证 stores/authStore(登录态检查)
- API层依赖
- 路由 api/route/product.php 映射到 ProductController
- 控制器依赖前端服务层 front/service/product/ProductService.php
- 外部模块
- 优惠券模块(coupon):在详情中提供可用优惠券列表
- 收藏模块(favorites):收藏/取消收藏
graph LR
M["小程序页面"] --> H["http.js"]
M --> R["route.js"]
M --> S["stores/*"]
H --> API["/api/product/*"]
API --> CTRL["ProductController"]
CTRL --> SVC["FrontProductService"]
CTRL --> MOD["Coupon/Favorites 模块"]
性能考虑
- 图片懒加载
- 详情页监听 imageLoad 计算高度,避免大图导致布局抖动;建议结合小程序原生 lazy-load 与缩略图策略
- 分页加载
- 列表与评论均实现 onReachBottom 分页加载,减少首屏数据量
- 数据缓存
- 使用 wx.setStorageSync 缓存分享标题、购买模式等轻量数据;对分类树、排序选项等可考虑本地缓存提升二次打开速度
- 网络优化
- 合理拆分请求:详情与规格属性分离,按需加载;对频繁访问的分类/品牌结果做短期缓存
- 渲染优化
- 列表项使用虚拟滚动或分页;图片尺寸统一,避免重排
故障排查指南
- 图片加载失败
- 现象:详情页图片不显示或占位异常
- 排查:检查图片URL有效性、CDN可达性;确认 imageLoad 回调是否正确计算高度;必要时降级显示占位图
- 库存实时更新
- 现象:选择规格后库存未变化或显示不一致
- 排查:确认 attribute_list 返回的 box/attribute_list 包含最新库存;检查 selectAttribute 是否正确更新 attribute_data_box 并重新请求
- 价格变动同步
- 现象:切换规格后价格未更新
- 排查:确保 attribute_list 返回的价格字段正确绑定;检查前端是否重复使用旧数据或未刷新
- 收藏状态不同步
- 现象:收藏按钮状态与实际不符
- 排查:确认 favorites.user.store 返回的 favorites 对象已更新到 data;检查登录态是否正常
- 评论分页卡顿
- 现象:加载更多无响应或重复加载
- 排查:检查 loadpage 标志位与 nomore 状态;确保 onReachBottom 节流有效
结论
本模块以小程序页面与后端控制器/服务分层清晰的方式实现了商品列表、分类与详情页的核心能力。通过统一的API与模块化服务,支撑了筛选排序、规格选择、库存与价格联动、收藏与分享等功能。建议在现有基础上进一步完善图片懒加载、数据缓存与错误重试机制,以提升用户体验与系统稳定性。
附录:接口与示例
- 商品列表接口
- 路径:/api/product
- 方法:GET
- 参数:category_id、brand_id、by、sort、page、year、month
- 返回:product_list、product_category、sort_list、cate_info、title、category_id
- 参考:ProductController.php:48-84
- 商品详情接口
- 路径:/api/product/show
- 方法:GET
- 参数:id、category_slug、slug
- 返回:product、defined、open、coupon_list
- 参考:ProductController.php:87-113
- 规格属性接口
- 路径:/api/product/attribute_list
- 方法:GET
- 参数:id、mode、attribute_data
- 返回:attribute_list、box
- 参考:ProductController.php:116-137
- 收藏接口
- 路径:/api/favorites/user/store
- 方法:POST
- 参数:module、item_id
- 返回:favorites、__message
- 参考:product.ts(默认主题):210-229
- 购物车/购买接口
- 路径:/api/order/cart.store
- 方法:POST
- 参数:post(JSON字符串)、mode、action
- 返回:mode、跳转指示
- 参考:product.ts(默认主题):101-128