店铺主页 — 前端技术方案(C 端 · shop-app)
依据: 《店铺主页功能需求.md》v1.0、《店铺主页技术方案.md》v1.0(仅作接口对照,本文档独立维护)
关联: 《搜索页前端技术方案》、《商品分类前端技术方案》、《商品详情内页前端技术方案》
范围: C 端 店铺介绍、关注、店内分类浏览、店内搜索、进商品详情;不 改后端、不 实现全站搜索/购物车/我的关注列表页。
实现状态: 页面与 API 封装已落地,待与 /api/shop/** 联调。
1. 技术栈与约定
| 项 |
说明 |
| 框架 |
uni-app Vue 3 + uview-plus |
| 请求 |
@/utils/request;读接口 header: { isToken: false };关注写接口 须 Token |
| 商品列表响应 |
TableDataInfo:rows + total(与分类/搜索一致) |
| 分类 VO |
与平台分类相同 CategoryVisibleVO;商品筛选参数名为 shopCategoryId(二级 ID) |
| 排序 |
后端固定 销量降序;前端 不提供 sortBy Tab |
| 虚拟 Tab |
一级导航首项 「全部商品」 由前端常量注入,不调分类接口 |
| 参考组件 |
GoodsGrid、category/level1 Tab 样式、search/index 搜索栏 |
2. 页面与路由
| 页面 |
需求代号 |
路径 |
入口 |
| 店铺主页 |
A |
subpackage/shop/index |
搜索页店铺 Tab、详情「进店」、带 shopId 链入 |
| 店内搜索 |
B+C |
subpackage/shop/search |
A 页「搜索本店商品」;B 输入 + C 结果 同页 |
pages.json 分包: pkg-shop → root: subpackage/shop
| 页面 |
navigationBarTitleText |
| index |
店铺(加载成功后改为店名) |
| search |
搜本店商品 |
Query:
| 页面 |
参数 |
说明 |
| A |
shopId(必填) |
缺失 → 提示并返回 |
| B+C |
shopId(必填) |
同上 |
| B+C |
keyword(可选) |
预填并自动发起搜索 |
路径常量: utils/pageRoute.js → PAGE_SHOP_HOME、PAGE_SHOP_SEARCH
跳转工具: utils/shopNav.js
| 方法 |
行为 |
goShopHome(shopId) |
navigateTo A 页 |
goShopSearch(shopId, keyword?) |
navigateTo 店内搜索页 |
3. 文件清单
| 类型 |
路径 |
说明 |
| A 页 |
shop-app/subpackage/shop/index.vue |
介绍区 + 关注 + 一二级 Tab + 商品列表 |
| 店内搜索 |
shop-app/subpackage/shop/search.vue |
输入 + 结果列表(同页) |
| 商品列表块 |
shop-app/components/shop/ShopGoodsBlock.vue |
分页、GoodsGrid、重试 |
| 店铺 API |
shop-app/api/shop.js |
/api/shop/** |
| 展示映射 |
shop-app/utils/shopDisplay.js |
介绍区、分类树、搜索店卡片 |
| 导航 |
shop-app/utils/shopNav.js |
进店跳转 |
| 常量 |
shop-app/constants/shop.js |
营业态、全部 Tab、分页、占位文案 |
已改入口(联调):
| 文件 |
改动 |
subpackage/search/result.vue |
店铺 Tab @item-click → goShopHome |
subpackage/goods/detail.vue |
onEnterShop → goShopHome(shopId) |
4. 接口封装(api/shop.js)
基路径: /api/shop
| 方法 |
HTTP |
路径 |
鉴权 |
页面 |
getShopProfile |
GET |
/{shopId} |
匿名(Token 可选) |
A |
getShopCategories |
GET |
/{shopId}/categories |
匿名 |
A |
getShopLevel2Tabs |
GET |
/{shopId}/categories/{level1Id}/level2-tabs |
匿名 |
A |
getShopGoods |
GET |
/{shopId}/goods |
匿名 |
A / 店内搜索 |
followShop |
POST |
/{shopId}/follow |
须 Token |
A |
unfollowShop |
DELETE |
/{shopId}/follow |
须 Token |
A |
4.1 商品列表 Query
| 场景 |
参数 |
| 全部商品 |
仅 pageNum、pageSize |
| 某二级分类 |
shopCategoryId |
| 店内搜索 |
keyword(不传 shopCategoryId) |
空关键词:前端 不请求;后端 trim 后空白会报错。
4.2 关注交互
| 规则 |
前端实现 |
| SH-F1 未登录 |
ensureApiToken() → 跳转登录 |
| SH-F2/F3 |
成功后本地更新 followed、fansCount ±1 |
| 失败 |
request Toast;不 改按钮态 |
5. 页面逻辑说明
5.1 A. 店铺主页 index.vue
onLoad(shopId)
→ loadProfile(失败:整页错误 + 重试/返回)
→ loadCategories(一级树,不含「全部」)
→ 默认「全部商品」→ ShopGoodsBlock 无 shopCategoryId
切换一级(非全部)
→ loadLevel2Tabs
→ 有二级:展示二级 Tab,传 shopCategoryId
→ 无二级:不请求商品,空态「该分类下暂无商品」
点击商品 → goGoodsDetail(goodsId)
点击搜索条 → goShopSearch(shopId)
| 展示 |
说明 |
停业 shopStatus=1 |
名称旁 「休息中」 标签;列表仍展示(SH8) |
| 评分 |
rating 为 null 时不展示评分行 |
| 粉丝 |
始终展示数字(无统计为 0) |
| 描述 |
两行截断展示 |
5.2 店内搜索 search.vue
| 规则 |
实现 |
| SH-S2 空关键词 |
Toast,不展示结果区 |
| SH-S3/S4 |
ShopGoodsBlock 带 keyword |
| 无匹配 |
emptyText="暂无相关" |
| 回车 |
@confirm 等同点搜索 |
5.3 ShopGoodsBlock.vue
- 监听
shopId、shopCategoryId、keyword、scrollTopKey、enabled
- 上拉
scrolltolower 加载更多
loadFailed 时显示「点击重试」
- 卡片字段经
mapGoodsCardList:主图、名称、售价、店名
6. 数据映射(shopDisplay.js)
| 函数 |
用途 |
mapShopProfile |
介绍区:头像 URL、isClosed、showRating、followed |
mapShopCategoryTree |
复用 mapCategoryTree |
mapShopLevel2Tabs |
复用 mapLevel2Tabs |
sortShopTabsWithHot |
hot_flag=1 靠前 |
mapShopCard |
全站搜索店铺 Tab(已有) |
7. 异常与边界(前端)
| 情形 |
行为 |
| shopId 缺失 |
Toast + smartNavigateBack |
| 店铺 404 |
pageError + 重试 / 返回 |
| 分类/列表失败 |
分类树空;列表块内重试 |
| 一级无二级 |
goodsBlockEnabled=false,专用空态文案 |
| 浏览 vs 下单 |
本模块不加购;停业/四条件在 详情页 拦截 |
8. 联调检查清单
9. 非本期(前端不实现)
| 项 |
说明 |
| 全站搜索 / 搜索历史 |
搜索分包 |
| 店内按价格排序 |
需求未要求 |
| 我的关注列表页 |
我的服务另册 |
| 电话一键拨打、分享 |
可选增强 |
10. 修订记录
| 版本 |
说明 |
| v1.0 |
首版:A 主页 + 店内搜索同页、API/组件/入口联调说明 |
文档版本:v1.0 · 不修改《店铺主页技术方案.md》(后端方案)。