瀏覽代碼

会员管理代码

wwh 2 周之前
父節點
當前提交
bacafcb528

+ 11 - 3
doc/店铺后台/商品管理/商品列表/商品列表前端技术方案.md

@@ -70,12 +70,15 @@
70 70
 └── 添加/编辑弹窗(720px · v1.0 单规格)
71 71
     ├── 商品分类 categoryId(必填,平台二级)
72 72
     ├── 店铺商品分类 shopCategoryId(选填,本店二级)
73
+    ├── 属性模版 attrTemplateId(选填;下拉 `/agri/seller/attrTemplate/options`)
73 74
     ├── 商品名称、主图、销售价、库存
74 75
     ├── 商品详情 detailContent(Editor 富文本)
75 76
     └── 服务说明 serviceIds(多选;新建默认勾选 defaultShow)
76 77
 ```
77 78
 
78
-**v1.0 未实现(后续扩展):** 多图 gallery、多规格 SKU、运费模版、属性模版、独立 form 路由页。
79
+**v1.0 未实现(后续扩展):** 多图 gallery、多规格 SKU、运费模版、属性/规格明细编辑(`biz_goods_attr`)、独立 form 路由页。
80
+
81
+**v1.0 后端已支持:** 保存/详情 `attrTemplateId`(模版引用 ID);前端发品表单待接入下拉与回显。
79 82
 
80 83
 ---
81 84
 
@@ -98,6 +101,7 @@
98 101
 | `listSellerGoods` | GET | `/list` | 分页列表 |
99 102
 | `sellerGoodsCategoryOptions` | GET | `/categoryOptions` | 平台二级分类 |
100 103
 | `sellerGoodsShopCategoryOptions` | GET | `/shopCategoryOptions` | 本店二级店铺分类 |
104
+| `sellerAttrTemplateOptions` | GET | `/agri/seller/attrTemplate/options` | 本店属性模版(属性模版模块) |
101 105
 | `sellerGoodsServiceOptions` | GET | `/serviceOptions` | `{ all, defaultShow }` |
102 106
 | `getSellerGoods` | GET | `/{goodsId}` | 详情 |
103 107
 | `addSellerGoods` | POST | `/` | 新增 → status=0 |
@@ -135,6 +139,7 @@
135 139
 |------|------|------|------|
136 140
 | categoryId | 必填 | 必填 | 平台二级 |
137 141
 | shopCategoryId | 选填 | 选填 | 本店二级 |
142
+| attrTemplateId | 选填 | 选填 | 本店有效属性模版 |
138 143
 | goodsName | 必填 | 必填 | max 200 |
139 144
 | mainPic | 必填 | 必填 | image-upload |
140 145
 | detailContent | 必填 | 必填 | 富文本 |
@@ -164,6 +169,7 @@
164 169
 | rejectReason | 审核失败展示 |
165 170
 | services[] | 服务快照;编辑时回显 `serviceIds` |
166 171
 | shopCategoryPath | 店铺分类路径 |
172
+| attrTemplateId / attrTemplateName | 属性模版引用与名称 |
167 173
 
168 174
 ---
169 175
 
@@ -188,7 +194,8 @@
188 194
 - [ ] 添加 → 未上架 → 提交上架(免审开/关两种策略)
189 195
 - [ ] 出售中编辑保存后状态不变
190 196
 - [ ] 批量操作含非法状态时后端报错
191
-- [ ] 分类/店铺分类/服务下拉数据正确
197
+- [ ] 分类/店铺分类/属性模版/服务下拉数据正确
198
+- [ ] 保存带 attrTemplateId 后详情回显 attrTemplateName
192 199
 
193 200
 ---
194 201
 
@@ -197,7 +204,8 @@
197 204
 | 版本 | 说明 |
198 205
 |------|------|
199 206
 | v1.0 | 首版:列表 + v1.0 单规格发品弹窗 + 详情抽屉 + 状态流转操作 |
207
+| v1.1 | 对齐后端 `attrTemplateId`:保存体/详情字段;下拉走属性模版模块 |
200 208
 
201 209
 ---
202 210
 
203
-*文档版本:v1.0 · 关联《商品列表功能需求.md》v1.1、《店铺商品列表技术方案.md》v1.0*
211
+*文档版本:v1.1 · 关联《商品列表功能需求.md》v1.3、《店铺商品列表技术方案.md》v1.2*

+ 9 - 6
doc/店铺后台/商品管理/商品列表/商品列表功能需求.md

@@ -26,7 +26,7 @@
26 26
 | **平台 · 商品审核** | 见平台 **商品审核**;平台对待审核商品通过/驳回、对出售中商品下架 |
27 27
 | **平台 · 商品分类 / 服务目录维护** | 见平台 **商品分类**、**商品服务管理**;商家 **只选** 不维护目录 |
28 28
 | **店铺商品分类维护** | 见 **店铺商品分类**;本模块 **消费** 其数据 |
29
-| **属性模版维护** | 模版配置 **非本期**(若后续单独立项);发品时 **选用** 已有模版 |
29
+| **属性模版维护** | 见 **属性模版** 模块(已实现);本模块发品时 **选用** 并保存引用 |
30 30
 | **C 端下单 / 订单履约** | 见 **订单管理**;本模块不处理发货、退款 |
31 31
 
32 32
 ### 1.2 与草稿的对应关系
@@ -266,7 +266,7 @@
266 266
 | 类别 | 内容 |
267 267
 |------|------|
268 268
 | 基础信息 | 编号、名称、主图/详情图、售价、库存、销量、重量、条码、关键词、简述等 |
269
-| 分类 | **商品分类**(一级 > 二级)、**店铺商品分类**(一级 > 二级,若有) |
269
+| 分类 | **商品分类**(一级 > 二级)、**店铺商品分类**(一级 > 二级,若有)、**属性模版**(名称,若选用) |
270 270
 | 规格与运费 | 销售规格(统一/多规格)、规格明细(市场价、库存);快递运费(固定/模版) |
271 271
 | 属性 | 基于 **属性模版** 扩展的属性项、规格项及其值 |
272 272
 | 详情内容 | 图文详情(图片块 + 文本块) |
@@ -298,7 +298,7 @@
298 298
 | 基础 | 商品条码 | 否 | — |
299 299
 | 基础 | 搜索关键词 | 否 | — |
300 300
 | 基础 | 商品简述 | 视产品 | — |
301
-| 属性 | 属性模版 | 视产品 | 在模版基础上 **可增删** 属性项、属性值、规格项、规格值 |
301
+| 属性 | 属性模版 | 否 | 下拉选用本店模版(数据源见 **属性模版** 模块);保存 **引用 ID**;属性/规格键值明细 **v1.x** |
302 302
 | 销售 | 销售规格 | 是 | **统一规格 / 多规格** |
303 303
 | 销售 | 规格明细 | 是 | 每种规格:**市场价、库存**(首期单规格时一行) |
304 304
 | 物流 | 快递运费 | 是 | **固定运费 / 运费模版** |
@@ -321,7 +321,7 @@
321 321
 | 当前店铺有效 | 停业店仍可发品;**已逻辑删除** 店铺不可用 |
322 322
 | 商品分类 | 平台已维护 **平台二级分类**(至少一条可选);商家 **只选** |
323 323
 | 商品服务 | 平台已配置目录则可选;无目录时服务区域为空 |
324
-| 属性模版 | 若启用模版能力,须已有可选模版(**非本期** 则手工维护属性) |
324
+| 属性模版 | 可选;下拉来自 **属性模版** 模块 `/agri/seller/attrTemplate/options`;无模版时可不传 |
325 325
 
326 326
 ---
327 327
 
@@ -600,6 +600,7 @@
600 600
 | **GL15** | 须携带 **当前店铺上下文**;切换店铺后数据范围随之变化 |
601 601
 | **GL16** | 商品创建后 **不可换店** |
602 602
 | **GL17** | **任意状态** 均可 **查看详情**;审核失败须展示 **驳回原因** |
603
+| **GL18** | 发品可选 **属性模版**;若传须为 **当前店铺** 有效模版;保存写入引用;模版项/值快照 **biz_goods_attr** 另案(v1.x) |
603 604
 
604 605
 ---
605 606
 
@@ -624,7 +625,8 @@
624 625
 
625 626
 | 项 | 说明 |
626 627
 |----|------|
627
-| 属性模版 **维护** | 仅 **选用**;模版 CRUD 单独立项 |
628
+| 属性模版 **维护** | 见 **属性模版** 模块;本模块 **仅选用 + 保存引用** |
629
+| 属性/规格 **明细落库** | `biz_goods_attr` 写入 **v1.x**;当前仅 `attr_template_id` |
628 630
 | 运费模版 **维护** | 假定平台或它模块已提供可选模版 |
629 631
 | 多规格 SKU 完整能力 | 草稿含多规格字段;复杂 SKU 以商品管理全模块为准 |
630 632
 | 平台代商家改价/改库存 | 平台侧能力 |
@@ -662,7 +664,8 @@
662 664
 | **v1.0** | 首版定稿:店铺商品列表/检索/发品/状态流转;对齐平台五态与关联分析;补店铺上下文与服务/分类协作 |
663 665
 | **v1.1** | 对齐《店铺商品分类功能需求》v1.1:店铺商品分类为 **两级**,发品 **仅挂二级** |
664 666
 | **v1.2** | 统一「商品分类 = 平台二级 / 店铺商品分类 = 本店二级」口径;与《店铺商品列表技术方案》v1.1 及实现对齐 |
667
+| **v1.3** | 对齐属性模版协作:发品可选 `attrTemplateId` 并保存引用;属性/规格明细 `biz_goods_attr` 仍标 v1.x |
665 668
 
666 669
 ---
667 670
 
668
-*文档版本:v1.2 · 关联《关联需求分析.md》v1.6、《商品审核功能需求.md》v1.0、《商品分类功能需求.md》v1.5、《商品服务管理功能需求.md》v1.0.1、《店铺商品分类功能需求.md》v1.1 · 草稿《商品列表功能需求-草稿.md》保持不变。*
671
+*文档版本:v1.3 · 关联《关联需求分析.md》v1.6、《商品审核功能需求.md》v1.0、《商品分类功能需求.md》v1.5、《商品服务管理功能需求.md》v1.0.1、《店铺商品分类功能需求.md》v1.1、《属性模版功能需求.md》v1.0 · 草稿《商品列表功能需求-草稿.md》保持不变。*

+ 91 - 24
doc/店铺后台/商品管理/商品列表/店铺商品列表技术方案.md

@@ -1,7 +1,7 @@
1 1
 # 店铺商品列表 — 技术方案
2 2
 
3
-> **依据:** 《商品列表功能需求.md》v1.2  
4
-> **关联:** 《关联需求分析.md》v1.6;平台《商品审核技术方案》v1.1、《商品分类技术方案》v1.3、《商品服务管理技术方案》v1.0.1;商家《店铺商品分类技术方案》(`biz_goods_category` 本店二级)  
3
+> **依据:** 《商品列表功能需求.md》v1.3  
4
+> **关联:** 《关联需求分析.md》v1.6;平台《商品审核技术方案》v1.1、《商品分类技术方案》v1.3、《商品服务管理技术方案》v1.0.1;商家《店铺商品分类技术方案》v1.2、《属性模版技术方案》v1.2  
5 5
 > **范围:** 商家端 **当前店铺** 商品列表、检索、发品、编辑、提交上架、下架、删除;**复用** 平台商品主表与状态机,**不另建** 商家商品表。  
6 6
 > **原则:** `goods_status` 仅经 submit / audit / offShelf 变更(P17);`X-Shop-Id` 店铺上下文;批量含非法状态 **整批失败**。
7 7
 
@@ -56,35 +56,78 @@ biz_goods_category
56 56
 | **商品分类** | `category_id` ← `IPlatformCategoryService.selectPlatformLevel2Options()` |
57 57
 | **店铺商品分类** | `shop_category_id` ← `IShopGoodsCategoryFacade.listOptionsByShopId()` |
58 58
 | **商品服务** | 发品多选 ← `IGoodsServiceFacade`;保存写快照 |
59
+| **属性模版** | `attr_template_id` ← 保存时 `assertAttrTemplateIfPresent`;下拉 ← `/agri/seller/attrTemplate/options` 或 `IAttrTemplateFacade` |
59 60
 | **店铺设置** | `IShopGlobalConfigFacade.getDefaultAuditPass()` 决定 submit 目标态 |
60 61
 | **订单管理** | 下架前校验 **O10 未完成订单**(**待实现**,`IGoodsOrderFacade` 占位) |
61
-| **店铺管理** | `IGoodsFacade.hasBlockingGoodsForShopDelete` 删店前置 |
62
+| **店铺管理** | `IGoodsShopFacade.hasBlockingGoodsForShopDelete`(`GoodsFacadeImpl`)删店前置 |
62 63
 
63 64
 ### 1.3 模块落位
64 65
 
66
+**本模块包:** `com.ruoyi.web.modules.goods`
67
+
65 68
 ```text
66 69
 baqing-shop/src/main/java/com/ruoyi/web/modules/goods/
67
-├── controller/SellerGoodsController.java      # /agri/seller/goods(本方案)
68
-├── controller/GoodsController.java            # 平台监管(已实现)
69
-├── controller/GoodsAuditController.java       # 平台审核菜单(可选薄封装)
70
-├── service/IGoodsService.java
71
-├── service/impl/GoodsServiceImpl.java
72
-├── domain/BizGoods.java
73
-├── dto/GoodsSaveDTO.java
74
-├── dto/GoodsBatchIdsDTO.java                  # 批量提交 / 批量删除
75
-├── dto/GoodsOffShelfDTO.java                  # 批量下架
76
-├── mapper/BizGoodsMapper.java
77
-├── support/GoodsSnGenerator.java
78
-├── support/GoodsStatusUtils.java
79
-├── facade/IGoodsFacade.java                   # 删店/分类删校验
70
+├── controller/
71
+│   ├── SellerGoodsController.java           # /agri/seller/goods(本方案)
72
+│   ├── GoodsController.java                 # /agri/goods(平台监管)
73
+│   └── GoodsAuditController.java            # /agri/goodsAudit(平台审核菜单薄封装)
74
+├── service/
75
+│   ├── IGoodsService.java
76
+│   └── impl/GoodsServiceImpl.java           # 商家 + 平台共用;注入 template 模块 Mapper 校验 attrTemplateId
77
+├── domain/
78
+│   ├── BizGoods.java
79
+│   └── BizGoodsServiceSnapshot.java
80
+├── dto/
81
+│   ├── GoodsSaveDTO.java
82
+│   ├── GoodsAuditDTO.java
83
+│   ├── GoodsBatchIdsDTO.java                # 批量提交 / 批量删除
84
+│   └── GoodsOffShelfDTO.java                # 批量下架
85
+├── vo/
86
+│   ├── GoodsListVO.java
87
+│   ├── GoodsDetailVO.java
88
+│   ├── GoodsServiceSnapshotVO.java
89
+│   └── GoodsPurchaseVO.java                 # C 端/采购 Facade 用
90
+├── mapper/
91
+│   ├── BizGoodsMapper.java
92
+│   └── BizGoodsServiceSnapshotMapper.java
93
+├── facade/
94
+│   ├── IGoodsOrderFacade.java               # 下架 O10(DefaultGoodsOrderFacade 占位)
95
+│   ├── IGoodsPurchaseFacade.java
96
+│   └── impl/
97
+│       ├── GoodsFacadeImpl.java             # 实现 category.IGoodsFacade、store.IGoodsShopFacade
98
+│       ├── DefaultGoodsOrderFacade.java
99
+│       ├── GoodsPurchaseFacadeImpl.java
100
+│       └── GoodsSnapshotFacadeImpl.java
101
+├── support/
102
+│   ├── GoodsSnGenerator.java
103
+│   ├── GoodsStatusUtils.java
104
+│   └── GoodsBatchResponseSupport.java
105
+├── exception/GoodsBatchOperationException.java
80 106
 └── constant/GoodsConstants.java
81 107
 
82
-resources/mapper/goods/BizGoodsMapper.xml
83
-sql/biz_goods.sql                              # 含 shop_category_id 字段
108
+baqing-shop/src/main/resources/mapper/goods/
109
+├── BizGoodsMapper.xml
110
+└── BizGoodsServiceSnapshotMapper.xml
111
+
112
+sql/biz_goods.sql                              # 含 shop_category_id、attr_template_id
84 113
 sql/biz_goods_service_snapshot.sql
85 114
 ```
86 115
 
87
-**店铺上下文(已有):** `com.ruoyi.web.modules.store` → `SellerShopContextController`(`/agri/seller/context`)。
116
+**跨模块依赖(接口与实现分离):**
117
+
118
+| 能力 | 接口位置 | 实现 / 调用 |
119
+|------|----------|-------------|
120
+| 删分类/模版/店前校验 | `category/facade/IGoodsFacade.java` | `goods/facade/impl/GoodsFacadeImpl.java` |
121
+| 店铺商品分类下拉 | `category/facade/IShopGoodsCategoryFacade.java` | `category/facade/impl/ShopGoodsCategoryFacadeImpl.java` |
122
+| 平台二级分类下拉 | `category/service/IPlatformCategoryService.java` | `SellerGoodsController` 或 `SellerPlatformCategoryController` |
123
+| 分类路径 | `category/facade/ICategoryFacade.java` | `CategoryFacadeImpl` |
124
+| 属性模版校验 | `template/mapper/BizGoodsAttrTemplateMapper.java` | `GoodsServiceImpl` 直接注入 |
125
+| 属性模版下拉 | `template/facade/IAttrTemplateFacade.java` | 前端亦可调 `/agri/seller/attrTemplate/options` |
126
+| 商品服务目录 | `goodsservice/facade/IGoodsServiceFacade.java` | 发品 `serviceOptions` |
127
+| 店铺上下文 | `category/support/SellerShopContext.java` | 拦截器 `SellerShopContextInterceptor` |
128
+| 店铺上下文 API | `store/controller/SellerShopContextController.java` | `GET /agri/seller/context` |
129
+
130
+**关联模块(并列包,非本模块源码):** `modules/category`、`modules/template`、`modules/goodsservice`、`modules/store`。
88 131
 
89 132
 ---
90 133
 
@@ -110,6 +153,7 @@ sql/biz_goods_service_snapshot.sql
110 153
 | shop_id | bigint NOT NULL | **创建时写入当前店铺**;不可 UPDATE 换店 |
111 154
 | category_id | bigint NOT NULL | **平台二级分类**(`biz_goods_category`,`shop_id IS NULL`) |
112 155
 | shop_category_id | bigint NULL | **店铺商品分类**(`biz_goods_category` 本店二级);可空 |
156
+| attr_template_id | bigint NULL | **属性模版**(`biz_goods_attr_template` 本店);可空;删模版校验 |
113 157
 | goods_sn | varchar(32) UK | Redis 生成,全平台唯一 |
114 158
 | goods_name | varchar(200) | |
115 159
 | main_pic | varchar(512) | 主图 URL |
@@ -125,7 +169,7 @@ sql/biz_goods_service_snapshot.sql
125 169
 | del_flag | char(1) | 0 存在 2 逻辑删除 |
126 170
 | create_by / create_time / update_by / update_time | | 审计 |
127 171
 
128
-**首期未落库、后续扩展(需求 §8 完整表单):** 多图、重量、条码、关键词、简述、多规格 SKU、运费模版、属性项等 → 见 §2.5,**不阻塞 v1.0 列表/单规格发品**
172
+**首期未落库、后续扩展(需求 §8 完整表单):** 多图、重量、条码、关键词、简述、多规格 SKU、运费模版、**属性/规格键值(`biz_goods_attr`)** 等 → 见 §2.5;**`attr_template_id` 引用已实现**,不阻塞 v1.0 列表/单规格发品
129 173
 
130 174
 ### 2.3 增量 DDL
131 175
 
@@ -134,6 +178,11 @@ sql/biz_goods_service_snapshot.sql
134 178
 ALTER TABLE `biz_goods`
135 179
   ADD COLUMN `shop_category_id` bigint(20) DEFAULT NULL COMMENT '店铺商品分类ID(本店二级 biz_goods_category)' AFTER `category_id`,
136 180
   ADD KEY `idx_shop_category_id` (`shop_category_id`, `del_flag`);
181
+
182
+-- sql/biz_goods_attr_template.sql(商品侧扩展)
183
+ALTER TABLE `biz_goods`
184
+  ADD COLUMN `attr_template_id` bigint(20) DEFAULT NULL COMMENT '属性模版ID' AFTER `shop_category_id`,
185
+  ADD KEY `idx_attr_template_id` (`attr_template_id`, `del_flag`);
137 186
 ```
138 187
 
139 188
 完整建表见 `sql/biz_goods.sql`。
@@ -168,6 +217,7 @@ v1.0 **仅** 使用主表 `sale_price`/`stock`/`main_pic`/`detail_content`。
168 217
 | idx_shop_status | shop_id, goods_status, del_flag | 商家列表 + 状态 Tab |
169 218
 | idx_category_id | category_id, del_flag | 分类检索 |
170 219
 | idx_shop_category_id | shop_category_id, del_flag | 店铺分类删校验 |
220
+| idx_attr_template_id | attr_template_id, del_flag | 属性模版删校验 |
171 221
 | idx_submit_time | submit_time | 待审核排序(平台侧) |
172 222
 
173 223
 ### 2.7 商家列表 SQL 约定
@@ -215,10 +265,12 @@ WHERE g.del_flag = '0'
215 265
 |------|--------|------------|
216 266
 | `IPlatformCategoryService` | 分类 | `selectPlatformLevel2Options()` — 发品「商品分类」 |
217 267
 | `IShopGoodsCategoryFacade` | 店铺商品分类 | `listOptionsByShopId(shopId, visibleOnly)` — 「店铺商品分类」 |
268
+| `IAttrTemplateFacade` | 属性模版 | 发品下拉 `listOptionsByShopId`;删模版时 `IGoodsFacade.existsByAttrTemplateId` |
218 269
 | `IGoodsServiceFacade` | 商品服务 | `listAllEnabled` / `listDefaultShow`;删服务前 `existsByServiceId` |
219 270
 | `IShopGlobalConfigFacade` | 店铺设置 | `getDefaultAuditPass()` |
220 271
 | `IShopFacade` | 店铺 | 删店时 `assertShopMaintable` |
221
-| `IGoodsFacade` | 商品 | `hasBlockingGoodsForShopDelete`;`existsByShopCategoryId` |
272
+| `IGoodsFacade` | 商品 | `existsByShopCategoryId`;`existsByAttrTemplateId`(接口在 **category**,实现在 **goods**) |
273
+| `IGoodsShopFacade` | 商品 | `hasBlockingGoodsForShopDelete`(`GoodsFacadeImpl`) |
222 274
 | `IOrderFacade`³ | 订单 | `hasUnfinishedOrderByGoodsId(goodsId)` — 下架前置 |
223 275
 
224 276
 ³ 订单模块 Facade,下架 O10 校验 **待对接**。
@@ -284,6 +336,7 @@ WHERE g.del_flag = '0'
284 336
 |------|------|
285 337
 | 列表字段 | 同 §5.1 |
286 338
 | shopId, categoryId, shopCategoryId | |
339
+| attrTemplateId, attrTemplateName | 选用模版 ID 与名称(详情回显) |
287 340
 | detailContent, stock | |
288 341
 | rejectReason, submitTime, auditTime, offShelfTime | |
289 342
 | services[] | 服务快照列表 |
@@ -304,6 +357,7 @@ WHERE g.del_flag = '0'
304 357
 {
305 358
   "categoryId": 1002,
306 359
   "shopCategoryId": 2005,
360
+  "attrTemplateId": 4,
307 361
   "goodsName": "复合肥 50kg",
308 362
   "mainPic": "/profile/upload/2026/05/01/a.jpg",
309 363
   "detailContent": "<p>详情</p>",
@@ -317,6 +371,7 @@ WHERE g.del_flag = '0'
317 371
 |------|------|
318 372
 | categoryId | 须为 **平台二级** 有效分类 |
319 373
 | shopCategoryId | 若传,须属 **当前店** 二级分类 |
374
+| attrTemplateId | 若传,须属 **当前店** 有效属性模版 |
320 375
 | serviceIds | 须全部存在于未删除服务目录 |
321 376
 | goodsStatus | **禁止** 传入 |
322 377
 
@@ -404,6 +459,9 @@ WHERE g.del_flag = '0'
404 459
 | GET | `/agri/seller/goods/shopCategoryOptions` | `list` | 本店二级「店铺商品分类」`IShopGoodsCategoryFacade.listOptionsByShopId(shopId, false)` |
405 460
 | GET | `/agri/seller/category/platformLevel2Options` | 同上 | 与上同源(分类模块只读入口,可选) |
406 461
 | GET | `/agri/seller/goods/serviceOptions` | `list` | `{ all: [], defaultShow: [] }` |
462
+| GET | `/agri/seller/attrTemplate/options` | 属性模版模块 | 本店属性模版下拉(**非** goods 子路径;见《属性模版技术方案》§3.6) |
463
+
464
+> **规划(可选挂载):** `GET /agri/seller/goods/attrTemplateOptions` 委托 `IAttrTemplateFacade`,与上同源。
407 465
 
408 466
 ---
409 467
 
@@ -428,8 +486,9 @@ insertSellerGoods
428 486
   → requireShopId
429 487
   → validateSaveFields + assertPlatformCategoryLevel2(categoryId)
430 488
   → assertShopCategoryIfPresent(shopCategoryId)
489
+  → assertAttrTemplateIfPresent(attrTemplateId)
431 490
   → goodsSn = GoodsSnGenerator.next()
432
-  → insert status=0
491
+  → insert status=0(含 attr_template_id)
433 492
   → saveServiceSnapshots
434 493
 
435 494
 submitGoods
@@ -454,6 +513,9 @@ deleteSellerGoodsBatch
454 513
 |------|----------|
455 514
 | category_id | `biz_goods_category.category_id`,`shop_id IS NULL`,`parent_id > 0` |
456 515
 | shop_category_id | `biz_goods_category.category_id`,`shop_id = #{shopId}`,`parent_id > 0` |
516
+| attr_template_id | `biz_goods_attr_template.template_id`,`shop_id = #{shopId}`,`del_flag = '0'` |
517
+
518
+**错误 msg(属性模版):** 无效或非本店模版 → `请选择本店有效属性模版`(`GoodsConstants.MSG_ATTR_TEMPLATE_INVALID`)。
457 519
 
458 520
 ---
459 521
 
@@ -479,8 +541,10 @@ deleteSellerGoodsBatch
479 541
 |------|------|------|
480 542
 | **v1.0** | 列表/详情/单规格 CRUD/单独 submit·offShelf/服务快照/平台分类与服务下拉 | **已实现** |
481 543
 | **v1.0 补全** | `shop_category_id` + 店铺分类下拉 + 删除 + 批量 submit/offShelf/delete | **已实现** |
544
+| **v1.0 补全·模版引用** | `attr_template_id` 保存/详情回显 + 本店模版校验 | **已实现** |
482 545
 | **v1.0 补全·O10** | 下架前未完成订单校验(`IGoodsOrderFacade`) | **待实现** |
483
-| **v1.x** | 多图、多规格 SKU、运费、属性模版引用、关键词检索扩展 | 规划 |
546
+| **v1.x** | 多图、多规格 SKU、运费、`biz_goods_attr` 写入、关键词检索扩展 | 规划 |
547
+| **v1.x·可选** | `/agri/seller/goods/attrTemplateOptions` 挂载 | 规划 |
484 548
 
485 549
 ---
486 550
 
@@ -498,6 +562,7 @@ deleteSellerGoodsBatch
498 562
 | T8 | 删除出售中 → 失败 |
499 563
 | T9 | 跨店 goodsId → MSG_NOT_OWNER |
500 564
 | T10 | 服务快照:保存后详情与目录变更隔离 |
565
+| T11 | attrTemplateId:本店有效模版写入;跨店/无效 ID → 失败 |
501 566
 
502 567
 ---
503 568
 
@@ -507,7 +572,9 @@ deleteSellerGoodsBatch
507 572
 |------|------|
508 573
 | **v1.0** | 首版:商家商品列表技术方案;复用 biz_goods 与平台状态机;接口/DDL 与实现对齐并标注待办 |
509 574
 | **v1.1** | 同步代码:v1.0 补全已实现;统一平台/店铺分类口径;O10 仍标待实现 |
575
+| **v1.2** | 同步 `attr_template_id`:GoodsSaveDTO/详情/Mapper/校验;下拉走属性模版模块 `/options` |
576
+| **v1.3** | §1.3 模块落位与代码对齐:`IGoodsFacade` 跨包、`template` 依赖、快照/订单 Facade |
510 577
 
511 578
 ---
512 579
 
513
-*文档版本:v1.1 · 关联《商品列表功能需求.md》v1.2、《商品审核技术方案.md》v1.1、《商品分类技术方案.md》v1.3、《商品服务管理技术方案.md》v1.0.1、《店铺商品分类技术方案.md》v1.1 · 技术栈 RuoYi v3.9.2-springboot2 + MySQL 5.7.39。*
580
+*文档版本:v1.3 · 关联《商品列表功能需求.md》v1.3、《商品审核技术方案.md》v1.1、《商品分类技术方案.md》v1.3、《商品服务管理技术方案.md》v1.0.1、《店铺商品分类技术方案.md》v1.2、《属性模版技术方案.md》v1.2 · 技术栈 RuoYi v3.9.2-springboot2 + MySQL 5.7.39。*

+ 37 - 6
doc/店铺后台/商品管理/商品列表/店铺商品列表测试用例.md

@@ -1,11 +1,11 @@
1 1
 # 店铺商品列表 — 测试用例
2 2
 
3
-> **依据:** 《商品列表功能需求.md》v1.2、《店铺商品列表技术方案.md》v1.1  
4
-> **关联:** 《商品审核功能需求.md》《商品分类功能需求.md》《店铺商品分类功能需求.md》v1.1、《角色管理测试用例.md》  
5
-> **范围:** 商家端 `/agri/seller/goods`;`GoodsServiceImpl`(商家 scope)/ `SellerGoodsController`;`IGoodsFacade` / 服务快照协作  
6
-> **排除:** 平台端审核/监管 UI E2E、C 端下单、多规格 SKU/运费模版完整表单、属性模版维护  
3
+> **依据:** 《商品列表功能需求.md》v1.3、《店铺商品列表技术方案.md》v1.2  
4
+> **关联:** 《商品审核功能需求.md》《商品分类功能需求.md》《店铺商品分类功能需求.md》v1.1、《属性模版功能需求.md》、《角色管理测试用例.md》  
5
+> **范围:** 商家端 `/agri/seller/goods`;`GoodsServiceImpl`(商家 scope)/ `SellerGoodsController`;`IGoodsFacade` / 服务快照 / 属性模版引用协作  
6
+> **排除:** 平台端审核/监管 UI E2E、C 端下单、多规格 SKU/运费模版完整表单、属性模版 **维护** UI、**biz_goods_attr** 明细写入  
7 7
 > **环境:** RuoYi v3.9.2-springboot2;MySQL 5.7.39;请求头 **`X-Shop-Id`** 标识当前店铺  
8
-> **实现分期:** v1.0 + v1.0 补全 **已实现**(含 shopCategoryId、删除、批量 submit/offShelf);**O10 订单阻断仍待实现**
8
+> **实现分期:** v1.0 + v1.0 补全 **已实现**(含 shopCategoryId、attrTemplateId、删除、批量 submit/offShelf);**O10 订单阻断仍待实现**
9 9
 
10 10
 ---
11 11
 
@@ -27,6 +27,7 @@
27 27
 | 全局配置 | `default_audit_pass=0`(关,提交上架进 **待审核**);测试免审时临时改为 `1` |
28 28
 | 平台二级分类 | `categoryId=1002`(肥料>复合肥,`shop_id IS NULL`,level=2) |
29 29
 | 店铺商品分类 | `shopCategoryId=2005`(店内专区>热销,`shop_id=101`,level=2) |
30
+| 属性模版 | `attrTemplateId=4`(「手机」,`shop_id=101`);跨店模版 `templateId=99`(`shop_id=102`) |
30 31
 | 商品服务 | `serviceId=1`(24小时发货,默认显示)、`serviceId=3`(7天退换) |
31 32
 | 店铺 101 商品 | `1001` 未上架(G001)、`1002` 待审核(G002)、`1003` 出售中(G003)、`1004` 审核失败(G004, reject=资料不全)、`1005` 已下架(G005) |
32 33
 | 跨店商品 | `1006` 未上架,**shop_id=102** |
@@ -320,6 +321,34 @@
320 321
 | **测试步骤** | insertSellerGoods(101, dto含shopCategoryId) |
321 322
 | **预期结果** | 失败;msg 提示分类无效 |
322 323
 
324
+### SGL-UT-024 保存写入 attrTemplateId
325
+
326
+| 要素 | 内容 |
327
+|------|------|
328
+| **用例编号** | SGL-UT-024 |
329
+| **测试模块** | 店铺商品列表 |
330
+| **测试项** | assertAttrTemplateIfPresent + insert |
331
+| **测试类型** | 单元测试 |
332
+| **测试工具** | JUnit 5 + Mockito |
333
+| **测试目的** | 验证 GL18:合法 attrTemplateId 写入 biz_goods |
334
+| **前置条件** | attrTemplateId=4 属 shop 101;categoryId=1002 有效 |
335
+| **测试步骤** | insertSellerGoods(101, dto含attrTemplateId=4) |
336
+| **预期结果** | insert 成功;BizGoods.attrTemplateId=4 |
337
+
338
+### SGL-UT-025 无效 attrTemplateId 拒绝保存
339
+
340
+| 要素 | 内容 |
341
+|------|------|
342
+| **用例编号** | SGL-UT-025 |
343
+| **测试模块** | 店铺商品列表 |
344
+| **测试项** | assertAttrTemplateIfPresent |
345
+| **测试类型** | 单元测试 |
346
+| **测试工具** | JUnit 5 + Mockito |
347
+| **测试目的** | 验证 GL18:跨店或不存在模版拒绝 |
348
+| **前置条件** | attrTemplateId=99 属 102 或不存在 |
349
+| **测试步骤** | insertSellerGoods(101, dto含attrTemplateId) |
350
+| **预期结果** | 失败;msg 含「属性模版」;不调用 insert |
351
+
323 352
 ### SGL-UT-021 删除可删状态成功
324 353
 
325 354
 | 要素 | 内容 |
@@ -1019,6 +1048,7 @@
1019 1048
 | GL9 删除状态限制 | UT-021,022 | API-020,021 | UI-016 |
1020 1049
 | GL10 批量整批失败 | — | API-022,023 | UI-012 |
1021 1050
 | GL11 分类二级/店铺分类 | UT-007,020 | API-024,026 | UI-004 |
1051
+| GL18 属性模版引用 | UT-024,025 | — | — |
1022 1052
 | GL12 服务快照 | UT-018,019 | API-025 | UI-017 |
1023 1053
 | GL13 保存不可改态 | UT-006 | API-010 | — |
1024 1054
 | GL14 外部变更不级联 | — | API-028 | — |
@@ -1037,7 +1067,8 @@
1037 1067
 |------|------|
1038 1068
 | **v1.0** | 首版:23 单元 + 28 接口 + 17 UI;覆盖 GL1~GL17 及状态机/检索/权限 |
1039 1069
 | **v1.1** | 同步代码 v1.0 补全已实现;O10 仍标待实现;统一平台/店铺分类口径 |
1070
+| **v1.2** | 新增 GL18 / UT-024、025:attrTemplateId 保存与校验 |
1040 1071
 
1041 1072
 ---
1042 1073
 
1043
-*文档版本:v1.0 · 关联《商品列表功能需求.md》v1.1、《店铺商品列表技术方案.md》v1.0*
1074
+*文档版本:v1.2 · 关联《商品列表功能需求.md》v1.3、《店铺商品列表技术方案.md》v1.2*

+ 2 - 1
doc/店铺后台/商品管理/属性模版/属性模版功能需求.md

@@ -540,7 +540,8 @@
540 540
 | 版本 | 说明 |
541 541
 |------|------|
542 542
 | **v1.0** | 首版定稿:对齐草稿 §1~§6 及原型;关联《关联需求分析》《店铺管理》《商品列表》及平台商品相关需求 |
543
+| **v1.1** | 对齐商品列表协作:发品保存 `attr_template_id` 已实现(见《店铺商品列表技术方案》v1.2) |
543 544
 
544 545
 ---
545 546
 
546
-*文档版本:v1.0 · 关联《属性模版功能需求-草稿》· 平台侧见《关联需求分析.md》《商品分类功能需求.md》《商品服务管理功能需求.md》《商品审核功能需求.md》· 商家侧见《商品列表功能需求.md》《店铺商品分类功能需求.md》*
547
+*文档版本:v1.1 · 关联《属性模版功能需求-草稿》· 平台侧见《关联需求分析.md》《商品分类功能需求.md》《商品服务管理功能需求.md》《商品审核功能需求.md》· 商家侧见《商品列表功能需求.md》v1.3、《店铺商品分类功能需求.md》*

+ 49 - 25
doc/店铺后台/商品管理/属性模版/属性模版技术方案.md

@@ -1,7 +1,7 @@
1 1
 # 属性模版 — 技术方案
2 2
 
3 3
 > **依据:** 《属性模版功能需求.md》v1.0  
4
-> **关联:** 《关联需求分析.md》v1.6;平台《商品服务管理技术方案》v1.0.1、《商品分类技术方案》v1.3、《商品审核技术方案》v1.1;商家《店铺商品列表技术方案》v1.1、《店铺商品分类技术方案》v1.1  
4
+> **关联:** 《关联需求分析.md》v1.6;平台《商品服务管理技术方案》v1.0.1、《商品分类技术方案》v1.3、《商品审核技术方案》v1.1;商家《店铺商品列表技术方案》v1.3、《店铺商品分类技术方案》v1.2  
5 5
 > **范围:** 商家端 **当前店铺** 属性模版 CRUD;为 **商品列表 · 属性模版** 字段提供下拉与详情预填;**平台不参与** 模版维护。  
6 6
 > **原则:** `shop_id` 店铺隔离;逻辑删除;批量删除 **整批失败**;编辑模版 **不 UPDATE** 已有商品属性/规格(快照原则)。
7 7
 
@@ -55,41 +55,62 @@ biz_goods_attr_template(shop_id = 当前店铺)
55 55
 
56 56
 ### 1.3 模块落位
57 57
 
58
+> **包名说明:** Java 包为 **`template`**(非 `attrtemplate`),与 URL 路径 `/attrTemplate` 区分。
59
+
60
+**本模块包:** `com.ruoyi.web.modules.template`
61
+
58 62
 ```text
59
-baqing-shop/src/main/java/com/ruoyi/web/modules/attrtemplate/
63
+baqing-shop/src/main/java/com/ruoyi/web/modules/template/
60 64
 ├── controller/SellerAttrTemplateController.java    # /agri/seller/attrTemplate
61
-├── service/IAttrTemplateService.java
62
-├── service/impl/AttrTemplateServiceImpl.java
63
-├── domain/BizGoodsAttrTemplate.java
64
-├── domain/BizGoodsAttrTemplateItem.java
65
-├── domain/BizGoodsAttrTemplateValue.java
66
-├── dto/AttrTemplateSaveDTO.java
67
-├── vo/AttrTemplateListVO.java
68
-├── vo/AttrTemplateDetailVO.java
69
-├── vo/AttrTemplateOptionVO.java
70
-├── mapper/BizGoodsAttrTemplateMapper.java
71
-├── mapper/BizGoodsAttrTemplateItemMapper.java
72
-├── mapper/BizGoodsAttrTemplateValueMapper.java
73
-├── facade/IAttrTemplateFacade.java
74
-├── facade/impl/AttrTemplateFacadeImpl.java
65
+├── service/
66
+│   ├── IAttrTemplateService.java
67
+│   └── impl/AttrTemplateServiceImpl.java
68
+├── domain/
69
+│   ├── BizGoodsAttrTemplate.java
70
+│   ├── BizGoodsAttrTemplateItem.java
71
+│   └── BizGoodsAttrTemplateValue.java
72
+├── dto/
73
+│   ├── AttrTemplateSaveDTO.java
74
+│   └── AttrTemplateItemDTO.java
75
+├── vo/
76
+│   ├── AttrTemplateListVO.java
77
+│   ├── AttrTemplateDetailVO.java
78
+│   └── AttrTemplateOptionVO.java
79
+├── mapper/
80
+│   ├── BizGoodsAttrTemplateMapper.java
81
+│   ├── BizGoodsAttrTemplateItemMapper.java
82
+│   └── BizGoodsAttrTemplateValueMapper.java
83
+├── facade/
84
+│   ├── IAttrTemplateFacade.java
85
+│   └── impl/AttrTemplateFacadeImpl.java
75 86
 ├── exception/AttrTemplateBatchDeleteException.java
76 87
 └── constant/AttrTemplateConstants.java
77 88
 
78
-resources/mapper/attrtemplate/*.xml
79
-sql/biz_goods_attr_template.sql
80
-sql/biz_goods_attr_template_goods.sql          # biz_goods 扩展 + biz_goods_attr
81
-sql/agri_seller_attr_template_menu.sql
89
+baqing-shop/src/main/resources/mapper/template/
90
+├── BizGoodsAttrTemplateMapper.xml
91
+├── BizGoodsAttrTemplateItemMapper.xml
92
+└── BizGoodsAttrTemplateValueMapper.xml
93
+
94
+sql/biz_goods_attr_template.sql                  # 模版三表 + biz_goods.attr_template_id 扩展
95
+sql/agri_seller_attr_template_menu.sql             # 菜单(待补)
82 96
 ```
83 97
 
84 98
 **前端页面:** `agri/seller/attrTemplate/index`(列表 + 添加/编辑弹窗,对齐原型)。
85 99
 
100
+**跨模块协作(商品侧):**
101
+
102
+| 场景 | 商品模块代码 |
103
+|------|--------------|
104
+| 保存校验 `attrTemplateId` | `goods/service/impl/GoodsServiceImpl` 注入 `BizGoodsAttrTemplateMapper` |
105
+| 删模版引用校验 | `category/facade/IGoodsFacade.existsByAttrTemplateId` ← `goods/facade/impl/GoodsFacadeImpl` |
106
+
86 107
 ### 1.4 跨模块 Facade
87 108
 
88 109
 | 接口 | 提供方 | 调用方 | 方法 |
89 110
 |------|--------|--------|------|
90 111
 | **`IAttrTemplateFacade`** | **本模块** | 商品 | `listOptionsByShopId(shopId)` — 发品下拉 |
91 112
 | | | | `getDetailForGoods(templateId, shopId)` — 选用后预填 |
92
-| **`IGoodsFacade`** | 商品 | **本模块** | `existsByAttrTemplateId(templateId)` — 删模版前置 |
113
+| **`IGoodsFacade`** | 商品(`category/facade/IGoodsFacade` + `goods/facade/impl/GoodsFacadeImpl`) | **本模块** | `existsByAttrTemplateId(templateId)` — 删模版前置 |
93 114
 | **`IShopFacade`** | 店铺 | 本模块 | `assertShopMaintable` / `getShopName` |
94 115
 
95 116
 ---
@@ -386,7 +407,7 @@ INSERT 新 item/value(sort_no 按数组顺序 0,1,2…)
386 407
 |------|------|
387 408
 | 发品下拉 | `GET /options` 或 Facade |
388 409
 | 选用预填 | `GET /{templateId}` / `getDetailForGoods` |
389
-| 保存商品 | 写 `biz_goods.attr_template_id`;**先删后插** `biz_goods_attr`(v1.x) |
410
+| 保存商品 | 写 `biz_goods.attr_template_id`(**已实现**);**先删后插** `biz_goods_attr`(v1.x) |
390 411
 | 删模版校验 | `IGoodsFacade.existsByAttrTemplateId` |
391 412
 
392 413
 **`existsByAttrTemplateId` SQL:**
@@ -520,8 +541,9 @@ buildNameList(templateId)      // 列表聚合列
520 541
 
521 542
 | 阶段 | 内容 | 状态 |
522 543
 |------|------|------|
523
-| **v1.0** | 模版三表 CRUD;`/options`;`IGoodsFacade.existsByAttrTemplateId`;菜单权限 | **待实现** |
524
-| **v1.x** | 商品列表:`attr_template_id`、`biz_goods_attr` 写入;`/goods/attrTemplateOptions` | 规划 |
544
+| **v1.0** | 模版三表 CRUD;`/options`;`IGoodsFacade.existsByAttrTemplateId`;菜单权限 | **已实现** |
545
+| **v1.0·商品协作** | 商品保存/详情 `attr_template_id`;`assertAttrTemplateIfPresent` | **已实现** |
546
+| **v1.x** | `biz_goods_attr` 写入;`/agri/seller/goods/attrTemplateOptions` 挂载 | 规划 |
525 547
 | **非本期** | 模版导入导出、版本历史、平台代维、与分类自动绑定 | — |
526 548
 
527 549
 ---
@@ -531,7 +553,9 @@ buildNameList(templateId)      // 列表聚合列
531 553
 | 版本 | 说明 |
532 554
 |------|------|
533 555
 | **v1.0** | 首版:三表模型;`/agri/seller/attrTemplate`;与商品列表/平台审核协作;对齐《属性模版功能需求》v1.0 |
556
+| **v1.1** | 同步实现:模版 CRUD + 删引用校验;商品侧 `attr_template_id` 保存/回显已实现 |
557
+| **v1.2** | §1.3 模块落位与代码对齐:包名 `template`、Mapper XML 路径、跨模块 Facade 说明 |
534 558
 
535 559
 ---
536 560
 
537
-*文档版本:v1.0 · 关联《属性模版功能需求.md》v1.0 · 技术栈 RuoYi v3.9.2-springboot2 + MySQL 5.7.39*
561
+*文档版本:v1.2 · 关联《属性模版功能需求.md》v1.1 · 技术栈 RuoYi v3.9.2-springboot2 + MySQL 5.7.39*

+ 2 - 1
doc/店铺后台/商品管理/属性模版/属性模版测试用例.md

@@ -968,7 +968,8 @@
968 968
 | 版本 | 说明 |
969 969
 |------|------|
970 970
 | **v1.0** | 首版:28 单元 + 19 接口 + 17 UI;覆盖 AT1~AT12 及正常/异常/协作流程 |
971
+| **v1.1** | 商品协作:`attr_template_id` 保存/回显已实现;`biz_goods_attr` 仍标 v1.x |
971 972
 
972 973
 ---
973 974
 
974
-*文档版本:v1.0 · 关联《属性模版功能需求.md》v1.0、《属性模版技术方案.md》v1.0*
975
+*文档版本:v1.1 · 关联《属性模版功能需求.md》v1.1、《属性模版技术方案.md》v1.1*

+ 43 - 10
doc/店铺后台/商品管理/店铺商品分类/店铺商品分类技术方案.md

@@ -33,23 +33,55 @@
33 33
 
34 34
 ### 1.2 模块落位
35 35
 
36
+> **说明:** 平台分类与店铺商品分类 **共用** `category` 包;本方案 CRUD 入口为 `SellerShopGoodsCategoryController`。
37
+
38
+**本模块包:** `com.ruoyi.web.modules.category`(店铺分类相关子集)
39
+
36 40
 ```text
37 41
 baqing-shop/src/main/java/com/ruoyi/web/modules/category/
38
-├── controller/SellerShopGoodsCategoryController.java   # /agri/seller/shopCategory
39
-├── controller/SellerPlatformCategoryController.java  # /agri/seller/category(平台分类只读,非本模块 CRUD)
40
-├── controller/PlatformCategoryController.java        # /agri/category(平台商品分类 CRUD)
41
-├── service/IShopGoodsCategoryService.java
42
-├── service/impl/CategoryServiceImpl.java               # 平台 + 店铺分类共用实现
42
+├── controller/
43
+│   ├── SellerShopGoodsCategoryController.java    # /agri/seller/shopCategory(本方案 CRUD)
44
+│   ├── SellerPlatformCategoryController.java     # /agri/seller/category(平台分类只读)
45
+│   └── PlatformCategoryController.java           # /agri/category(平台商品分类 CRUD)
46
+├── service/
47
+│   ├── IShopGoodsCategoryService.java              # 店铺商品分类 Service 接口
48
+│   ├── ICategoryService.java                       # 平台分类 Service 接口
49
+│   ├── IPlatformCategoryService.java               # 平台二级下拉
50
+│   └── impl/CategoryServiceImpl.java               # 平台 + 店铺分类共用实现
43 51
 ├── domain/BizGoodsCategory.java
44 52
 ├── mapper/BizGoodsCategoryMapper.java
45
-├── facade/ShopGoodsCategoryFacadeImpl.java             # IShopGoodsCategoryFacade
46
-└── vo/CategoryRowVO、CategoryTreeVO、CategoryLevel2OptionVO 等
47
-
48
-resources/mapper/category/BizGoodsCategoryMapper.xml
53
+├── facade/
54
+│   ├── IShopGoodsCategoryFacade.java
55
+│   ├── ICategoryFacade.java                        # 分类路径(商品详情 join)
56
+│   ├── IGoodsFacade.java                           # 删分类前商品引用校验(实现在 goods 模块)
57
+│   ├── IShopFacade.java
58
+│   └── impl/
59
+│       ├── ShopGoodsCategoryFacadeImpl.java        # IShopGoodsCategoryFacade 实现
60
+│       ├── CategoryFacadeImpl.java
61
+│       ├── DefaultShopFacade.java
62
+│       └── DefaultGoodsFacade.java                 # IGoodsFacade 占位(可被 GoodsFacadeImpl 覆盖)
63
+├── support/
64
+│   ├── SellerShopContext.java
65
+│   └── SellerShopContextInterceptor.java           # X-Shop-Id 拦截
66
+├── config/CategoryWebConfig.java                   # 注册店铺上下文拦截器
67
+├── exception/CategoryBatchDeleteException.java
68
+├── constant/CategoryConstants.java
69
+└── vo/
70
+    ├── CategoryRowVO.java、CategoryTreeVO.java、CategoryLevel2OptionVO.java
71
+    └── ShopGoodsCategoryOptionVO.java              # 商品发品下拉
72
+
73
+baqing-shop/src/main/resources/mapper/category/BizGoodsCategoryMapper.xml
49 74
 sql/biz_goods_category.sql
50 75
 sql/agri_seller_shop_category_menu.sql
51 76
 ```
52 77
 
78
+**关联包(非本模块 CRUD,但协作):**
79
+
80
+| 包 | 协作 |
81
+|----|------|
82
+| `modules/goods` | `GoodsFacadeImpl` 实现 `IGoodsFacade.existsByShopCategoryId` |
83
+| `modules/store` | `SellerShopContextController` — `GET /agri/seller/context` |
84
+
53 85
 **前端页面:** `agri/seller/shopCategory/index`
54 86
 
55 87
 ### 1.3 关联协作链
@@ -412,7 +444,8 @@ logicDeleteByIds()
412 444
 |------|------|
413 445
 | **v1.0** | 首版:独立表 `biz_shop_goods_category` 单层方案(已废弃) |
414 446
 | **v1.1** | **与实现对齐**:复用 `biz_goods_category`(`shop_id` 非空);两级结构;`/agri/seller/shopCategory`;批量删除;商品挂二级 |
447
+| **v1.2** | §1.2 模块落位与代码对齐:Facade 在 `impl/`、店铺上下文 support、跨包 `IGoodsFacade` |
415 448
 
416 449
 ---
417 450
 
418
-*文档版本:v1.1 · 关联《店铺商品分类功能需求.md》v1.1 · 技术栈 RuoYi v3.9.2-springboot2 + MySQL 5.7.39。*
451
+*文档版本:v1.2 · 关联《店铺商品分类功能需求.md》v1.1 · 技术栈 RuoYi v3.9.2-springboot2 + MySQL 5.7.39。*