wwh преди 2 седмици
родител
ревизия
ba57eb1509

+ 1 - 1
baqing-shop/src/main/java/com/ruoyi/web/modules/goods/constant/GoodsConstants.java

@@ -35,7 +35,7 @@ public final class GoodsConstants
35 35
 
36 36
     public static final String MSG_NOT_OWNER = "无权操作该商品";
37 37
 
38
-    public static final String MSG_CATEGORY_INVALID = "请选择本店二级分类";
38
+    public static final String MSG_CATEGORY_INVALID = "请选择平台二级分类";
39 39
 
40 40
     public static final String MSG_SUBMIT_INVALID = "当前状态不可提交上架";
41 41
 

+ 9 - 7
doc/平台后台/关联需求分析.md

@@ -2,12 +2,12 @@
2 2
 
3 3
 > **范围:** 基于 `doc/农资商城web/` 下各模块 **功能需求定稿** 梳理跨模块关系;**不涉及** 数据库表结构、接口路径、技术实现。  
4 4
 > **目录(v3.0):** 组织管理(商户/店铺/店铺设置/入驻审核)、商品管理(主模块 + 分类/服务/审核)、内容管理、会员管理、订单管理;详见 [文档索引.md](文档索引.md)。  
5
-> **依据:** 《商户管理功能需求》v1.3.1、《店铺管理功能需求》v1.3.2、《商品分类功能需求》v1.4、《商品管理功能需求》v1.3.3、《商品服务管理功能需求》v1.0.1、《会员管理功能需求》v1.0、《订单管理功能需求》v1.0.1。  
5
+> **依据:** 《商户管理功能需求》v1.3.1、《店铺管理功能需求》v1.3.2、《商品分类功能需求》v1.5、《商品管理功能需求》v1.3.3、《商品服务管理功能需求》v1.0.1、《会员管理功能需求》v1.0、《订单管理功能需求》v1.0.1。  
6 6
 > **说明:** 不修改任何 `*-草稿.md`;技术方案、测试用例为验收参考,本分析以功能需求为准。  
7 7
 > **v1.1:** 纳入 **商品服务管理**(平台主数据 + 商品勾选快照)。  
8 8
 > **v1.2:** 纳入 **用户链**(会员、订单);定稿 **未完成订单 O10**、待支付自动关闭 **O8**、消费统计 **O11**。  
9 9
 > **v1.3:** 文档目录重组(组织管理 / 商品管理 / 内容管理);路径见 [文档索引.md](文档索引.md) v3.0。  
10
-> **v1.5:** C 端入驻 **审核→公示→建档**;平台添加商户主体字段精简;商户/入驻文档 v1.5/v1.1
10
+> **v1.6:** 发品分类口径:`category_id` = 平台二级;`shop_category_id` = 本店店铺商品二级
11 11
 
12 12
 ---
13 13
 
@@ -76,7 +76,7 @@
76 76
 | **店铺管理** | 平台 | 为合格商户开店、店铺开业/停业、**配置商户级经营账号**、删店;商家端可改店资料(列表同源) | 不维护商品分类;店铺策略见《店铺设置》;不审核商品 |
77 77
 | **店铺设置** | 平台 | 全平台 **商品默认审核**、**子管理员上限**(针对所有店铺) | 非逐店配置;见 `组织管理/店铺设置/` |
78 78
 | **入驻审核** | 平台 + C 端 | 用户商城入驻申请、平台审核→公示→首店创建 | 不替代商户管理日常维护;协议见内容管理 |
79
-| **商品分类** | **平台 + 商家** | 平台维护全平台分类(`shop_id` 为空);商家维护本店二级分类树 | 商品 **不可** 挂一级分类;商品仍挂 **本店** 二级类 |
79
+| **商品分类** | **平台 + 商家** | 平台维护全平台分类(`shop_id` 为空);商家维护本店店铺商品分类树 | 商品 **category_id** 挂 **平台二级**;**shop_category_id** 可选挂本店二级;均 **不可** 挂一级 |
80 80
 | **商品管理** | 平台 + 商家 | 商家发品与状态流转;平台审核、下架、全平台检索;勾选服务并保存 **快照** | 不维护服务目录 |
81 81
 | **商品审核** | 平台 | 待审/出售中商品 **监管列表**、审核、下架(与商品管理同源状态机) | 不重复商家发品表单;见专册或合入商品管理菜单 |
82 82
 | **商品服务管理** | 平台 | 全平台服务目录(名称、简介、图标、默认显示、排序) | 非店铺维度;商家/C 端 **不维护** 目录 |
@@ -147,7 +147,8 @@
147 147
 【商家】商品分类:添加一级 / 二级分类
148 148
149 149
 【商家】商品管理:发布商品 → 未上架(草稿)
150
-    → 选择本店二级分类 → 勾选商品服务(可选,默认显示项预勾选)→ 保存生成快照
150
+    → 选择平台二级「商品分类」(必选);可选本店「店铺商品分类」
151
+    → 勾选商品服务(可选,默认显示项预勾选)→ 保存生成快照
151 152
     → 提交上架
152 153
153 154
     ┌─ 店铺「默认审核通过」= 关 ─► 待审核 ──【平台】审核──► 出售中 / 审核失败
@@ -224,7 +225,8 @@ C 端:该店禁止下单(购物车/立即购买均拦截)
224 225
 
225 226
 | 编号 | 规则 | 说明 |
226 227
 |------|------|------|
227
-| C-P1 | 商品 **仅可关联本店二级分类** | 不可挂一级 |
228
+| C-P1 | 商品 **category_id** **仅可关联平台二级分类** | 不可挂一级 |
229
+| C-P1b | **shop_category_id** 若填写则 **仅可关联本店店铺商品二级** | 见《店铺商品分类功能需求》 |
228 230
 | C-P2 | 删二级分类前须无关联商品 | 须先改商品分类或处理商品 |
229 231
 | C-P3 | 删一级:子级无商品方可删;通过则 **级联删** 下属二级 | 批量删整批失败 |
230 232
 | C-P4 | 改分类显示/排序 **不自动** 改商品上下架状态 | 分类 G8 |
@@ -415,7 +417,7 @@ C 端:该店禁止下单(购物车/立即购买均拦截)
415 417
 | 组织管理/店铺管理/店铺管理功能需求.md | v1.3.5 | 开店、账号、商家端店资料 |
416 418
 | 组织管理/店铺设置/店铺设置功能需求.md | v1.1 | 全平台店铺策略 |
417 419
 | 组织管理/入驻审核/商户入驻审核功能需求.md | v1.1 | C 端完整填报;审核→公示→入驻 |
418
-| 商品管理/商品分类/商品分类功能需求.md | v1.4 | 平台 + 商家分类 |
420
+| 商品管理/商品分类/商品分类功能需求.md | v1.5 | 平台 + 商家分类;发品双字段口径 |
419 421
 | 商品管理/商品管理功能需求.md | v1.3.3 | 商品状态与商家发品 |
420 422
 | 商品管理/商品审核/商品审核功能需求.md | v1.0 | 平台审核/下架 |
421 423
 | 商品管理/商品服务/商品服务管理功能需求.md | v1.0.1 | 平台服务目录 |
@@ -437,4 +439,4 @@ C 端:该店禁止下单(购物车/立即购买均拦截)
437 439
 
438 440
 ---
439 441
 
440
-*文档版本:v1.5 · 仅功能需求关联分析 · 不修改草稿 · 路径对齐文档索引 v3.1*
442
+*文档版本:v1.6 · 仅功能需求关联分析 · 不修改草稿 · 路径对齐文档索引 v3.1*

+ 13 - 9
doc/平台后台/商品管理/商品分类/商品分类功能需求.md

@@ -5,7 +5,8 @@
5 5
 > **说明:** **平台** 维护全平台统一分类(`shop_id` 为空);**商家** 维护本店分类;平台 **商品管理** 按店铺引用商家分类做检索。  
6 6
 > **v1.1:** 商品仅挂二级分类、批量删除整批失败、店铺停业 C 端禁止下单已产品定稿。  
7 7
 > **v1.3:** **不考虑会员体系**;商家端使用 **店铺经营账号** 登录。  
8
-> **v1.4:** 平台端提供分类 CRUD;列表 **分页**;`shop_id` 可空区分平台/店铺分类。
8
+> **v1.4:** 平台端提供分类 CRUD;列表 **分页**;`shop_id` 可空区分平台/店铺分类。  
9
+> **v1.5:** 发品 **商品分类**(`category_id`)挂 **平台二级**;**店铺商品分类**(`shop_category_id`)为并列字段,见《店铺商品分类功能需求》。
9 10
 
10 11
 ---
11 12
 
@@ -33,7 +34,7 @@
33 34
 |----------|------|----------|
34 35
 | 商户管理 v1.3.1 | 无直接操作 | 不维护分类 |
35 36
 | 店铺管理 v1.3.2 | 上游 | 分类 **归属店铺**;商家端 **店铺经营账号** 在开店时由平台配置 |
36
-| 商品管理 | 下游消费 | 商品须关联 **本店二级分类**;平台按店铺名称 + **该店** 商品分类检索 |
37
+| 商品管理 | 下游消费 | 商品 **category_id** 须挂 **平台二级分类**;**shop_category_id** 可选挂本店店铺商品二级;平台检索可按店铺名称 + 分类筛选 |
37 38
 
38 39
 ### 1.3 使用端与角色
39 40
 
@@ -73,7 +74,8 @@
73 74
 | C2 | 添加一级:上级分类为空(或选择「无 / 顶级」) |
74 75
 | C3 | 添加二级:上级分类 **必须** 选择本店某一 **一级分类** |
75 76
 | C4 | 同一店铺、同一上级下,**分类名称不可重复** |
76
-| C5 | 商品发布/编辑时 **须且仅能关联本店二级分类**;**不可** 关联一级分类 |
77
+| C5 | 发品 **商品分类**(`category_id`)**须且仅能关联平台二级分类**(`shop_id IS NULL`);**不可** 关联一级 |
78
+| C6 | **店铺商品分类**(`shop_category_id`)为并列可选字段,规则见 **《店铺商品分类功能需求》** |
77 79
 
78 80
 ---
79 81
 
@@ -244,15 +246,16 @@
244 246
 | 场景 | 行为 |
245 247
 |------|------|
246 248
 | 商品列表检索 | 可按 **商品分类**(展示分类全路径,如「一级 > 二级」)、店铺名称等筛选 |
247
-| 商品数据来源 | 读取各店商家已维护的 **店铺分类**;平台另维护 **平台分类**(与发品分类独立,本期商品仍挂本店二级类) |
249
+| 商品数据来源 | **商品分类** 读平台二级(`shop_id IS NULL`);**店铺商品分类** 读各店维护的店铺分类;两字段并列展示 |
248 250
 
249 251
 ### 10.2 商品发布(商家端 / 与商品管理衔接)
250 252
 
251 253
 ```text
252 254
 商家在当前店铺发布/编辑商品
253
-    → 分类下拉仅展示本店分类
254
-    → 须选择 **二级分类**(仅二级,规则 C5)
255
-    → 保存后平台商品管理可按该分类检索
255
+    → 「商品分类」下拉:平台二级(`GET /agri/seller/goods/categoryOptions`)
256
+    → 「店铺商品分类」下拉:本店二级(`GET /agri/seller/goods/shopCategoryOptions`)
257
+    → 商品分类必选(规则 C5);店铺商品分类视产品是否必填
258
+    → 保存后平台商品管理可按分类、店铺检索
256 259
 ```
257 260
 
258 261
 ### 10.3 C 端展示与下单(定稿)
@@ -313,7 +316,7 @@
313 316
314 317
 商家:经营账号登录 → 选择当前店铺 → 商品分类 → 添加一级 / 二级
315 318
316
-商家:商品管理 → 选二级分类发品
319
+商家:商品管理 → 选平台二级「商品分类发品(可选本店「店铺商品分类」)
317 320
318 321
 平台:商品管理 → 按店铺、分类检索与审核
319 322
 ```
@@ -346,7 +349,8 @@
346 349
 | v1.3 | **不考虑会员**;店铺经营账号 |
347 350
 | v1.3.1 | 同步取消单商户 **3 店** 上限表述 |
348 351
 | v1.4 | 平台端分类 CRUD;`shop_id` 可空;列表分页 |
352
+| v1.5 | 统一发品口径:`category_id` = 平台二级;`shop_category_id` = 本店店铺商品二级 |
349 353
 
350 354
 ---
351 355
 
352
-*文档版本:v1.4(定稿)· 关联《商品分类技术方案.md》v1.2、《商品分类测试用例.md》v1.0 · 草稿保持不变。*
356
+*文档版本:v1.5(定稿)· 关联《商品分类技术方案.md》v1.2、《商品分类测试用例.md》v1.0、《店铺商品分类功能需求.md》v1.1 · 草稿保持不变。*

+ 36 - 24
doc/平台后台/商品管理/商品分类/商品分类技术方案.md

@@ -1,9 +1,9 @@
1 1
 # 商品分类 — 技术方案
2 2
 
3
-> **依据:** 《商品分类功能需求.md》v1.4  
3
+> **依据:** 《商品分类功能需求.md》v1.5  
4 4
 > **关联:** 《商户管理》《店铺管理》《商品管理》功能需求 v1.3.1 / v1.3.2 / v1.3.3;对应技术方案 v1.3 / v1.2.1 / v1.2  
5 5
 > **范围:** **平台端 + 商家端** 分类 CRUD;对商品/C 端提供 **Facade 与协作接口**。  
6
-> **原则:** **仅两级**(一级 + 二级);`shop_id` 为 **NULL** 表示平台分类、非空表示店铺分类;商品发品 **仅挂本店二级类**;商家端复用 **当前店铺** 上下文(`X-Shop-Id`)。
6
+> **原则:** **仅两级**(一级 + 二级);`shop_id` 为 **NULL** 表示平台分类、非空表示店铺分类;发品 **category_id** 挂 **平台二级**、**shop_category_id** 可选挂 **本店二级**;商家端复用 **当前店铺** 上下文(`X-Shop-Id`)。
7 7
 
8 8
 ---
9 9
 
@@ -20,12 +20,13 @@
20 20
 ### 1.1 模块落位
21 21
 
22 22
 ```text
23
-baqing-shop
24
-├── com.ruoyi.web.modules.category.controller.PlatformCategoryController   (平台)
25
-└── com.ruoyi.web.modules.category.controller.SellerCategoryController     (商家)
26
-    ├── domain.BizGoodsCategory
27
-    ├── service.ICategoryService / IPlatformCategoryService
28
-    └── facade.CategoryFacadeImpl  → ICategoryFacade
23
+baqing-shop/src/main/java/com/ruoyi/web/modules/category/
24
+├── controller/PlatformCategoryController.java           # /agri/category(平台 CRUD)
25
+├── controller/SellerShopGoodsCategoryController.java    # /agri/seller/shopCategory(店铺 CRUD)
26
+├── controller/SellerPlatformCategoryController.java     # /agri/seller/category(平台分类只读)
27
+├── service/IPlatformCategoryService、IShopGoodsCategoryService
28
+├── service/impl/CategoryServiceImpl.java
29
+└── facade/CategoryFacadeImpl、ShopGoodsCategoryFacadeImpl
29 30
 ```
30 31
 
31 32
 **前端页面:**
@@ -33,16 +34,17 @@ baqing-shop
33 34
 | 端 | 组件路径 |
34 35
 |----|----------|
35 36
 | 平台 | `agri/category/index` |
36
-| 商家 | `agri/seller/category/index` |
37
+| 商家 · 店铺商品分类 | `agri/seller/shopCategory/index` |
37 38
 
38 39
 ### 1.2 业务链
39 40
 
40 41
 ```text
41 42
 biz_goods_category(shop_id 可空:NULL=平台分类;非空=店铺分类)
42 43
     ├── 平台分类树(shop_id IS NULL)
44
+    │       └── biz_goods.category_id(发品「商品分类」,平台二级)
43 45
     └── biz_shop
44
-            └── 店铺分类树(shop_id = 店铺ID)
45
-                    └── biz_goods.category_id(仅指向 **本店** 二级节点
46
+            └── 店铺商品分类树(shop_id = 店铺ID)
47
+                    └── biz_goods.shop_category_id(发品「店铺商品分类」,本店二级
46 48
 ```
47 49
 
48 50
 | 模块 | 关系 |
@@ -57,9 +59,12 @@ biz_goods_category(shop_id 可空:NULL=平台分类;非空=店铺分类)
57 59
 | 接口 | 提供方 | 调用方 | 方法 |
58 60
 |------|--------|--------|------|
59 61
 | **`ICategoryFacade`** | **分类** | 商品、C端 | `isCategoryVisible(categoryId)` |
60
-| | | | `listLevel2ByShopId(shopId)` — 商家发品下拉 |
62
+| | | | `listPlatformLevel2Options()` — 平台二级下拉 |
63
+| | | | `listLevel2ByShopId(shopId)` — **店铺**二级下拉(`shop_id` 非空) |
61 64
 | | | | `getCategoryPath(categoryId)` → `一级 > 二级` |
62 65
 | | | | `listVisibleByShopId(shopId)` — C 端导航(show_flag=1) |
66
+| **`IPlatformCategoryService`** | **分类** | 商品 | `selectPlatformLevel2Options()` — 发品「商品分类」 |
67
+| **`IShopGoodsCategoryFacade`** | **店铺商品分类** | 商品 | `listOptionsByShopId(shopId, visibleOnly)` |
63 68
 | **`IGoodsFacade`** | 商品 | **分类** | `existsByCategoryId(categoryId)` |
64 69
 | **`IShopFacade`** | 店铺 | 分类 | 校验店铺未逻辑删除 |
65 70
 
@@ -138,13 +143,19 @@ CREATE TABLE `biz_goods_category` (
138 143
 
139 144
 ---
140 145
 
141
-## 3. 接口设计(商家端)
146
+## 3. 接口设计(商家端 · 店铺商品分类
142 147
 
143
-**路径:** `/agri/seller/category`  
144
-**权限:** `agri:seller:category:list|add|edit|remove`  
145
-**数据范围:** `shop_id = 当前店铺`(请求头 `X-Shop-Id`);店铺已逻辑删除则拦截。
148
+> **路径:** `/agri/seller/shopCategory`(**非** `/agri/seller/category`  
149
+> **权限:** `agri:seller:shopCategory:list|add|edit|remove`  
150
+> **数据范围:** `shop_id = 当前店铺`(请求头 `X-Shop-Id`);店铺已逻辑删除则拦截。
146 151
 
147
-### 3.1 接口一览
152
+### 3.0 商家端 · 平台分类只读
153
+
154
+| 方法 | 路径 | 说明 |
155
+|------|------|------|
156
+| GET | `/agri/seller/category/platformLevel2Options` | 平台二级下拉(发品「商品分类」;与商品模块 `/agri/seller/goods/categoryOptions` 同源) |
157
+
158
+### 3.1 接口一览(店铺商品分类 CRUD)
148 159
 
149 160
 | 方法 | 路径 | 说明 |
150 161
 |------|------|------|
@@ -341,21 +352,22 @@ CREATE TABLE `biz_goods_category` (
341 352
 
342 353
 | 场景 | 接口 / Facade |
343 354
 |------|----------------|
344
-| 商家发品选类 | `GET /agri/seller/category/level2Options` 或 `ICategoryFacade.listLevel2ByShopId` |
355
+| 商家发品选「商品分类」 | **`GET /agri/seller/goods/categoryOptions`** 或 `IPlatformCategoryService.selectPlatformLevel2Options()` |
356
+| 同上(分类模块入口) | `GET /agri/seller/category/platformLevel2Options` |
357
+| 商家发品选「店铺商品分类」 | `GET /agri/seller/goods/shopCategoryOptions` 或 `IShopGoodsCategoryFacade.listOptionsByShopId` |
345 358
 | 平台商品列表展示路径 | `ICategoryFacade.getCategoryPath(categoryId)` |
346
-| 平台按店筛分类 | **`GET /agri/goods/categoryOptions?shopId=`**(只读,见 4.1.1) |
359
+| 平台商品列表筛分类 | **`GET /agri/goods/categoryOptions`**(只读,见 4.1.1) |
347 360
 | 删类前置 | `IGoodsFacade.existsByCategoryId`(见 §8.4) |
348 361
 
349 362
 #### 4.1.1 平台只读 `GET /agri/goods/categoryOptions`
350 363
 
351
-挂在 **商品模块** `GoodsController`(平台权限 `agri:goods:list`),**不** 提供分类 CRUD。
364
+挂在 **商品模块** `GoodsController`(平台权限 `agri:goods:query`),**不** 提供分类 CRUD。
352 365
 
353 366
 | Query | 说明 |
354 367
 |-------|------|
355
-| shopId | 必填 |
356
-| level | 可选:`2` 仅二级(默认);`1` 仅一级 |
368
+| shopId | 必填(**当前实现保留参数,返回平台二级分类全量**;按店筛分类为后续扩展) |
357 369
 
358
-返回该店未删除分类,供平台商品列表「按分类筛选」下拉;展示 `label` = 全路径(二级)或名称(一级)
370
+返回 **平台** 未删除二级分类,供平台商品列表「按分类筛选」下拉;展示 `label` = `一级 > 二级`
359 371
 
360 372
 #### 4.1.2 `IGoodsFacade.existsByCategoryId`(商品模块实现,口径定稿)
361 373
 
@@ -554,4 +566,4 @@ List<CategoryVisibleVO> listVisibleByShopId(Long shopId);
554 566
 
555 567
 ---
556 568
 
557
-*文档版本:v1.2 · MySQL 5.7.39 · RuoYi v3.9.2-springboot2 · 关联《商品分类功能需求.md》v1.4、《商品分类测试用例.md》v1.0*
569
+*文档版本:v1.3 · MySQL 5.7.39 · RuoYi v3.9.2-springboot2 · 关联《商品分类功能需求.md》v1.5、《商品分类测试用例.md》v1.0*

+ 9 - 6
doc/平台后台/商品管理/商品审核/商品审核技术方案.md

@@ -67,7 +67,7 @@ biz_shop_global_config(default_audit_pass)
67 67
 |------|--------|------|----------|
68 68
 | `IGoodsFacade` | 商品 | `hasBlockingGoodsForShopDelete(shopId)` | 删店:存在 status∈{1,2} 阻断 |
69 69
 | `IShopGlobalConfigFacade` | 店铺设置 | `getDefaultAuditPass()` | 商家 submit 时用 |
70
-| `ICategoryFacade` | 分类 | `listLevel2ByShopId` | 平台按店查分类筛选项 |
70
+| `ICategoryFacade` | 分类 | `listPlatformLevel2Options` | 检索联动分类下拉(平台二级;`shopId` 预留扩展) |
71 71
 
72 72
 ### 1.4 状态联动
73 73
 
@@ -230,13 +230,16 @@ WHERE g.del_flag = '0'
230 230
 
231 231
 ---
232 232
 
233
-### 4.4 按店查分类(检索联动)`GET /agri/goods/categoryOptions`
233
+### 4.4 分类筛选项(检索联动)`GET /agri/goodsAudit/categoryOptions`
234 234
 
235 235
 | 项 | 说明 |
236 236
 |----|------|
237
-| 权限 | `agri:goods:query` |
238
-| Query | `shopId` 必填 |
239
-| 响应 | 该店二级分类下拉 |
237
+| 权限 | `agri:goodsAudit:query` |
238
+| Query | `shopId` 必填(**当前实现**仍返回全平台二级,参数预留按店扩展) |
239
+| 响应 | 平台二级分类下拉(`label` = `一级 > 二级`) |
240
+| 实现 | `categoryFacade.listPlatformLevel2Options()` |
241
+
242
+> 平台商品管理列表(`/agri/goods`)若提供同类接口,口径与本节一致。
240 243
 
241 244
 ---
242 245
 
@@ -421,4 +424,4 @@ offShelfPlatform(dto, operator)
421 424
 
422 425
 ---
423 426
 
424
-*文档版本:v1.0 · MySQL 5.7.39 · RuoYi v3.9.2-springboot2 · 实现复用 `com.ruoyi.web.modules.goods` · 关联《商品审核功能需求.md》v1.0*
427
+*文档版本:v1.1 · MySQL 5.7.39 · RuoYi v3.9.2-springboot2 · 实现复用 `com.ruoyi.web.modules.goods` · 关联《商品审核功能需求.md》v1.0 · v1.1 对齐发品分类口径(平台二级)*

+ 3 - 3
doc/平台后台/组织管理/店铺管理/店铺管理技术方案.md

@@ -46,11 +46,11 @@ sql/biz_shop.sql                                  # biz_merchant_account + biz_s
46 46
 biz_merchant
47 47
     └── biz_merchant_account(1 商户 1 套经营账号)
48 48
             └── biz_shop(1 商户多店,merchant_id 创建后不可改;本期不设店数上限)
49
-                    ├── biz_goods_category(shop_id = 本店 ID;店铺维度二级分类
50
-                    ├── biz_goods(shop_id;category_id 指向本店二级类;submit 读 **全局** default_audit_pass)
49
+                    ├── biz_goods_category(shop_id = 本店 ID;店铺商品分类二级树
50
+                    ├── biz_goods(shop_id;category_id 指向 **平台** 二级类;shop_category_id 可选指向本店二级类;submit 读 **全局** default_audit_pass)
51 51
                     └── biz_order(shop_id;删店校验)
52 52
 
53
-biz_goods_category(shop_id IS NULL)  ← 平台分类(与店铺无 FK;商品 **不** 引用)
53
+biz_goods_category(shop_id IS NULL)  ← 平台分类(商品 category_id 引用)
54 54
 ```
55 55
 
56 56
 | 模块 | 核心表 | 与店铺关系 |

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

@@ -66,7 +66,7 @@
66 66
 |----------|------|----------|
67 67
 | **店铺管理** | 上游 | 商品 **归属当前店铺**,创建后 **不可换店** |
68 68
 | **店铺设置** | 策略 | **商品默认审核通过** 决定提交上架后进入 **待审核** 或 **出售中** |
69
-| **商品分类(平台文档)** | 发品必选 | 商品须挂 **本店二级「商品分类」** |
69
+| **商品分类(平台文档)** | 发品必选 | 商品须挂 **平台二级「商品分类」**(`biz_goods_category`,`shop_id IS NULL`);商家 **只选不维护** |
70 70
 | **店铺商品分类** | 发品可选/并列字段 | 发品时 **「店铺商品分类」** 数据源来自该模块 |
71 71
 | **商品服务管理** | 发品多选 | 勾选平台服务目录项;保存时生成 **展示快照** |
72 72
 | **商品审核(平台)** | 下游协作 | 待审核 → 平台审;出售中 → 平台/商家均可下架 |
@@ -99,7 +99,7 @@
99 99
 | **§5.1 开业流程** | 须 **先选当前店铺**,再维护分类并发品 |
100 100
 | **§5.4 五态** | 本模块与平台 **共用** 同一套状态机,**不得** 另立规则 |
101 101
 | **§6.2 S-P1~S-P5** | 默认审核策略、停业不自动下架、删店前置、商品不可换店 |
102
-| **§6.3 C-P1** | 商品 **仅挂本店二级商品分类** |
102
+| **§6.3 C-P1** | 商品 **仅挂平台二级「商品分类」**(`category_id`);**店铺商品分类** 为并列可选字段 |
103 103
 | **§6.5 GS-P1~P9** | 服务目录全平台共用;保存写快照;改目录不追溯 |
104 104
 | **§8 不级联** | 店铺停业、分类隐藏、服务目录变更 **不自动** 改商品状态 |
105 105
 | **§9.1 经营账号** | 登录后 **切换当前店铺** 再操作本模块 |
@@ -118,9 +118,9 @@
118 118
 
119 119
 | 项 | 定稿 |
120 120
 |----|------|
121
-| 发品字段「商品分类」 | 必选 **本店二级分类**;不可挂一级 |
122
-| 分类下拉范围 | 仅 **当前店铺**、**未删除** 分类 |
123
-| 删分类 | 有关联商品则 **不可删**(分类模块规则);商家须先改商品分类 |
121
+| 发品字段「商品分类」 | 必选 **平台二级分类**(`shop_id IS NULL`);不可挂一级 |
122
+| 分类下拉范围 | 平台 **未删除** 二级分类;接口 `GET /agri/seller/goods/categoryOptions` |
123
+| 删分类 | 平台删类时,有关联商品则 **不可删**;商家须先改商品 `category_id` |
124 124
 
125 125
 ### 2.4 与《店铺商品分类功能需求》
126 126
 
@@ -169,7 +169,7 @@
169 169
 | **审核失败** | 平台驳回;须查看 **驳回原因** 后修改重提 |
170 170
 | **已下架** | 商家或平台将 **出售中** 商品下架后的状态 |
171 171
 | **提交上架** | 将未上架/审核失败/已下架商品 **送入** 审核或直接出售流程的 **独立动作**(非编辑保存) |
172
-| **商品分类** | 平台文档中的 **本店二级分类**;发品 **必选** |
172
+| **商品分类** | **平台二级分类**(`shop_id IS NULL`);发品 **必选**;展示「一级 > 二级」 |
173 173
 | **店铺商品分类** | 本店 **店铺商品分类** 模块 **二级** 数据;发品 **可选**(是否必填以原型为准) |
174 174
 | **展示快照** | 商品已选 **商品服务** 项在保存时的名称、简介、图标副本 |
175 175
 
@@ -292,7 +292,7 @@
292 292
 | 基础 | 商品编号 | — | **系统生成**,创建后展示 |
293 293
 | 基础 | 商品图片 | 是 | **多张**;首张或指定一张为主图 |
294 294
 | 基础 | 商品名称 | 是 | — |
295
-| 分类 | 商品分类 | 是 | **本店二级分类** |
295
+| 分类 | 商品分类 | 是 | **平台二级分类**(`category_id`) |
296 296
 | 分类 | 店铺商品分类 | 视产品 | **本店二级**;来自 **店铺商品分类** 模块 |
297 297
 | 基础 | 商品重量 | 视产品 | — |
298 298
 | 基础 | 商品条码 | 否 | — |
@@ -319,7 +319,7 @@
319 319
 | 前置 | 说明 |
320 320
 |------|------|
321 321
 | 当前店铺有效 | 停业店仍可发品;**已逻辑删除** 店铺不可用 |
322
-| 商品分类 | 须已维护 **本店二级分类**(至少一条可选) |
322
+| 商品分类 | 平台已维护 **平台二级分类**(至少一条可选);商家 **只选** |
323 323
 | 商品服务 | 平台已配置目录则可选;无目录时服务区域为空 |
324 324
 | 属性模版 | 若启用模版能力,须已有可选模版(**非本期** 则手工维护属性) |
325 325
 
@@ -550,8 +550,8 @@
550 550
 
551 551
 ```text
552 552
 【平台】配置商品服务目录(可选,建议先发品前完成)
553
-【平台】维护平台商品分类树;商家维护本店二级「商品分类」
554
-【商家】维护「店铺商品分类」(可选)
553
+【平台】维护平台商品分类树(`shop_id IS NULL`)
554
+【商家】维护「店铺商品分类」(可选,`/agri/seller/shopCategory`
555 555
556 556
 【商家】商品列表 → 添加商品 → 保存(未上架)
557 557
@@ -593,7 +593,7 @@
593 593
 | **GL8** | 下架:仅 **出售中**;草稿要求 **无未完成订单**(O10)方可下架 |
594 594
 | **GL9** | 删除:仅 **未上架 / 审核失败 / 已下架**;**待审核、出售中不可删** |
595 595
 | **GL10** | 批量提交上架 / 下架 / 删除:**整批失败** 策略与平台一致 |
596
-| **GL11** | 商品 **仅挂本店二级商品分类**;**店铺商品分类** 为并列字段,**仅挂本店店铺商品二级** |
596
+| **GL11** | **商品分类**(`category_id`)**仅挂平台二级**;**店铺商品分类**(`shop_category_id`)为并列字段,**仅挂本店二级** |
597 597
 | **GL12** | 保存商品时写入 **服务展示快照**;改平台目录 **不追溯** |
598 598
 | **GL13** | 状态 **仅** 经提交上架、平台审核、下架变更(P17) |
599 599
 | **GL14** | 商户/店铺/分类/服务目录变更 **不自动** 改商品状态 |
@@ -661,7 +661,8 @@
661 661
 |------|------|
662 662
 | **v1.0** | 首版定稿:店铺商品列表/检索/发品/状态流转;对齐平台五态与关联分析;补店铺上下文与服务/分类协作 |
663 663
 | **v1.1** | 对齐《店铺商品分类功能需求》v1.1:店铺商品分类为 **两级**,发品 **仅挂二级** |
664
+| **v1.2** | 统一「商品分类 = 平台二级 / 店铺商品分类 = 本店二级」口径;与《店铺商品列表技术方案》v1.1 及实现对齐 |
664 665
 
665 666
 ---
666 667
 
667
-*文档版本:v1.1 · 关联《关联需求分析.md》v1.5、《商品审核功能需求.md》v1.0、《商品分类功能需求.md》v1.4、《商品服务管理功能需求.md》v1.0.1、《店铺商品分类功能需求.md》v1.1 · 草稿《商品列表功能需求-草稿.md》保持不变。*
668
+*文档版本:v1.2 · 关联《关联需求分析.md》v1.6、《商品审核功能需求.md》v1.0、《商品分类功能需求.md》v1.5、《商品服务管理功能需求.md》v1.0.1、《店铺商品分类功能需求.md》v1.1 · 草稿《商品列表功能需求-草稿.md》保持不变。*

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

@@ -1,7 +1,7 @@
1 1
 # 店铺商品列表 — 技术方案
2 2
 
3
-> **依据:** 《商品列表功能需求.md》v1.0  
4
-> **关联:** 《关联需求分析.md》v1.5;平台《商品审核技术方案》v1.0、《商品分类技术方案》v1.2、《商品服务管理技术方案》v1.0.1;商家《店铺商品分类技术方案》(`biz_goods_category` 本店二级)  
3
+> **依据:** 《商品列表功能需求.md》v1.2  
4
+> **关联:** 《关联需求分析.md》v1.6;平台《商品审核技术方案》v1.1、《商品分类技术方案》v1.3、《商品服务管理技术方案》v1.0.1;商家《店铺商品分类技术方案》(`biz_goods_category` 本店二级)  
5 5
 > **范围:** 商家端 **当前店铺** 商品列表、检索、发品、编辑、提交上架、下架、删除;**复用** 平台商品主表与状态机,**不另建** 商家商品表。  
6 6
 > **原则:** `goods_status` 仅经 submit / audit / offShelf 变更(P17);`X-Shop-Id` 店铺上下文;批量含非法状态 **整批失败**。
7 7
 
@@ -53,11 +53,11 @@ biz_goods_category
53 53
 | 关联模块 | 协作 |
54 54
 |----------|------|
55 55
 | **商品审核** | 商家 submit 后进入平台待审队列;驳回原因商家详情可读 |
56
-| **商品分类** | `category_id` ← `ICategoryFacade.listPlatformLevel2Options()` |
56
+| **商品分类** | `category_id` ← `IPlatformCategoryService.selectPlatformLevel2Options()` |
57 57
 | **店铺商品分类** | `shop_category_id` ← `IShopGoodsCategoryFacade.listOptionsByShopId()` |
58 58
 | **商品服务** | 发品多选 ← `IGoodsServiceFacade`;保存写快照 |
59 59
 | **店铺设置** | `IShopGlobalConfigFacade.getDefaultAuditPass()` 决定 submit 目标态 |
60
-| **订单管理** | 下架前校验 **O10 未完成订单**(待实现,`IOrderFacade`) |
60
+| **订单管理** | 下架前校验 **O10 未完成订单**(**待实现**,`IGoodsOrderFacade` 占位) |
61 61
 | **店铺管理** | `IGoodsFacade.hasBlockingGoodsForShopDelete` 删店前置 |
62 62
 
63 63
 ### 1.3 模块落位
@@ -71,9 +71,8 @@ baqing-shop/src/main/java/com/ruoyi/web/modules/goods/
71 71
 ├── service/impl/GoodsServiceImpl.java
72 72
 ├── domain/BizGoods.java
73 73
 ├── dto/GoodsSaveDTO.java
74
-├── dto/GoodsSubmitBatchDTO.java               # 待实现 · 批量提交
75
-├── dto/GoodsOffShelfDTO.java                  # 复用 · 批量下架
76
-├── dto/GoodsDeleteDTO.java                    # 待实现 · 批量删除
74
+├── dto/GoodsBatchIdsDTO.java                  # 批量提交 / 批量删除
75
+├── dto/GoodsOffShelfDTO.java                  # 批量下架
77 76
 ├── mapper/BizGoodsMapper.java
78 77
 ├── support/GoodsSnGenerator.java
79 78
 ├── support/GoodsStatusUtils.java
@@ -81,10 +80,8 @@ baqing-shop/src/main/java/com/ruoyi/web/modules/goods/
81 80
 └── constant/GoodsConstants.java
82 81
 
83 82
 resources/mapper/goods/BizGoodsMapper.xml
84
-sql/biz_goods.sql
83
+sql/biz_goods.sql                              # 含 shop_category_id 字段
85 84
 sql/biz_goods_service_snapshot.sql
86
-sql/biz_goods_shop_category_id.sql             # shop_category_id 增量 DDL
87
-sql/agri_seller_goods_menu.sql                 # 商家菜单
88 85
 ```
89 86
 
90 87
 **店铺上下文(已有):** `com.ruoyi.web.modules.store` → `SellerShopContextController`(`/agri/seller/context`)。
@@ -201,10 +198,10 @@ WHERE g.del_flag = '0'
201 198
 | 审核通过 | `auditGoods` | 平台 | 1 | 2 |
202 199
 | 审核驳回 | `auditGoods` | 平台 | 1 | 3 |
203 200
 | 下架 | `offShelfSeller` / `offShelfPlatform` | 商家/平台 | 2 | 4 |
204
-| 删除 | `deleteSellerGoods`² | 商家 | 0/3/4 | del_flag=2 |
201
+| 删除 | `deleteSellerGoodsBatch` | 商家 | 0/3/4 | del_flag=2 |
205 202
 
206 203
 ¹ `default_audit_pass='1'` → **2**,否则 **1**。  
207
**待实现**;出售中/待审核 **阻断**。
204
+² 出售中/待审核 **阻断**;O10 订单校验 **待实现**。
208 205
 
209 206
 **禁止:** 请求体携带 `goodsStatus` 直接改态(`rejectGoodsStatusInBody`)。
210 207
 
@@ -216,7 +213,7 @@ WHERE g.del_flag = '0'
216 213
 
217 214
 | 接口 | 提供方 | 本模块用法 |
218 215
 |------|--------|------------|
219
-| `ICategoryFacade` | 分类 | `listPlatformLevel2Options()` — 发品「商品分类」 |
216
+| `IPlatformCategoryService` | 分类 | `selectPlatformLevel2Options()` — 发品「商品分类」 |
220 217
 | `IShopGoodsCategoryFacade` | 店铺商品分类 | `listOptionsByShopId(shopId, visibleOnly)` — 「店铺商品分类」 |
221 218
 | `IGoodsServiceFacade` | 商品服务 | `listAllEnabled` / `listDefaultShow`;删服务前 `existsByServiceId` |
222 219
 | `IShopGlobalConfigFacade` | 店铺设置 | `getDefaultAuditPass()` |
@@ -358,9 +355,9 @@ WHERE g.del_flag = '0'
358 355
 }
359 356
 ```
360 357
 
361
-#### 5.5.2 批量 `PUT /agri/seller/goods/submit`(实现)
358
+#### 5.5.2 批量 `PUT /agri/seller/goods/submit`(实现)
362 359
 
363
-**Body:** `{ "goodsIds": [10001, 10002] }`  
360
+**Body:** `{ "goodsIds": [10001, 10002] }`(`GoodsBatchIdsDTO`)  
364 361
 规则:含非 {0,3,4} → **整批失败**。
365 362
 
366 363
 ---
@@ -372,7 +369,7 @@ WHERE g.del_flag = '0'
372 369
 | 项 | 说明 |
373 370
 |----|------|
374 371
 | 权限 | `agri:seller:goods:offshelf` |
375
-| 前置 | status=2;**无 O10 未完成订单**(待实现) |
372
+| 前置 | status=2;**无 O10 未完成订单**(**待实现**,当前 `DefaultGoodsOrderFacade` 占位) |
376 373
 
377 374
 #### 5.6.2 批量 `PUT /agri/seller/goods/offShelf`
378 375
 
@@ -387,18 +384,15 @@ WHERE g.del_flag = '0'
387 384
 
388 385
 ### 5.7 删除
389 386
 
390
-#### 5.7.1 单独 `DELETE /agri/seller/goods/{goodsId}`(待实现)
387
+#### 5.7.1 单独 / 批量 `DELETE /agri/seller/goods/{goodsIds}`(已实现)
391 388
 
392 389
 | 项 | 说明 |
393 390
 |----|------|
394 391
 | 权限 | `agri:seller:goods:remove` |
395 392
 | 前置 | status ∈ {0, 3, 4} |
393
+| 路径 | 单条 `1001`;批量 `1001,1002` |
396 394
 
397
-逻辑删除:`del_flag='2'`;同步删快照(可选保留历史)。
398
-
399
-#### 5.7.2 批量 `DELETE /agri/seller/goods/{goodsIds}`(待实现)
400
-
401
-路径:`goodsIds=1,2,3`;含不可删状态 → **整批失败**。
395
+逻辑删除:`del_flag='2'`;含不可删状态 → **整批失败**(`GoodsBatchIdsDTO`)。
402 396
 
403 397
 ---
404 398
 
@@ -406,8 +400,9 @@ WHERE g.del_flag = '0'
406 400
 
407 401
 | 方法 | 路径 | 权限 | 说明 |
408 402
 |------|------|------|------|
409
-| GET | `/agri/seller/goods/categoryOptions` | `list` | 平台二级「商品分类」`ICategoryFacade.listPlatformLevel2Options()` |
410
-| GET | `/agri/seller/goods/shopCategoryOptions` | `list` | 本店二级「店铺商品分类」`IShopGoodsCategoryFacade.listOptionsByShopId(shopId, false)` **待加** |
403
+| GET | `/agri/seller/goods/categoryOptions` | `list` / `add` / `edit` | 平台二级「商品分类」`IPlatformCategoryService.selectPlatformLevel2Options()` |
404
+| GET | `/agri/seller/goods/shopCategoryOptions` | `list` | 本店二级「店铺商品分类」`IShopGoodsCategoryFacade.listOptionsByShopId(shopId, false)` |
405
+| GET | `/agri/seller/category/platformLevel2Options` | 同上 | 与上同源(分类模块只读入口,可选) |
411 406
 | GET | `/agri/seller/goods/serviceOptions` | `list` | `{ all: [], defaultShow: [] }` |
412 407
 
413 408
 ---
@@ -447,9 +442,10 @@ offShelfSeller
447 442
   → [待] orderFacade 校验 O10
448 443
   → status 2 → 4,写 off_shelf_time
449 444
 
450
-deleteSellerGoods [待]
445
+deleteSellerGoodsBatch
451 446
   → status in (0,3,4)
452
-  → logic delete
447
+  → logic delete + 整批失败策略
448
+  → [待] orderFacade 校验 O10(下架时)
453 449
 ```
454 450
 
455 451
 **分类校验口径:**
@@ -482,7 +478,8 @@ deleteSellerGoods [待]
482 478
 | 阶段 | 内容 | 状态 |
483 479
 |------|------|------|
484 480
 | **v1.0** | 列表/详情/单规格 CRUD/单独 submit·offShelf/服务快照/平台分类与服务下拉 | **已实现** |
485
-| **v1.0 补全** | `shop_category_id` 字段 + 店铺分类下拉 + 删除 + 批量 submit/offShelf/delete + 下架 O10 校验 | **待实现** |
481
+| **v1.0 补全** | `shop_category_id` + 店铺分类下拉 + 删除 + 批量 submit/offShelf/delete | **已实现** |
482
+| **v1.0 补全·O10** | 下架前未完成订单校验(`IGoodsOrderFacade`) | **待实现** |
486 483
 | **v1.x** | 多图、多规格 SKU、运费、属性模版引用、关键词检索扩展 | 规划 |
487 484
 
488 485
 ---
@@ -509,7 +506,8 @@ deleteSellerGoods [待]
509 506
 | 版本 | 说明 |
510 507
 |------|------|
511 508
 | **v1.0** | 首版:商家商品列表技术方案;复用 biz_goods 与平台状态机;接口/DDL 与实现对齐并标注待办 |
509
+| **v1.1** | 同步代码:v1.0 补全已实现;统一平台/店铺分类口径;O10 仍标待实现 |
512 510
 
513 511
 ---
514 512
 
515
-*文档版本:v1.0 · 关联《商品列表功能需求.md》v1.1、《商品审核技术方案.md》、《商品分类技术方案.md》v1.2、《商品服务管理技术方案.md》v1.0.1、《店铺商品分类技术方案.md》v1.1 · 技术栈 RuoYi v3.9.2-springboot2 + MySQL 5.7.39。*
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。*

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

@@ -1,11 +1,11 @@
1 1
 # 店铺商品列表 — 测试用例
2 2
 
3
-> **依据:** 《商品列表功能需求.md》v1.1、《店铺商品列表技术方案.md》v1.0  
3
+> **依据:** 《商品列表功能需求.md》v1.2、《店铺商品列表技术方案.md》v1.1  
4 4
 > **关联:** 《商品审核功能需求.md》《商品分类功能需求.md》《店铺商品分类功能需求.md》v1.1、《角色管理测试用例.md》  
5 5
 > **范围:** 商家端 `/agri/seller/goods`;`GoodsServiceImpl`(商家 scope)/ `SellerGoodsController`;`IGoodsFacade` / 服务快照协作  
6 6
 > **排除:** 平台端审核/监管 UI E2E、C 端下单、多规格 SKU/运费模版完整表单、属性模版维护  
7 7
 > **环境:** RuoYi v3.9.2-springboot2;MySQL 5.7.39;请求头 **`X-Shop-Id`** 标识当前店铺  
8
-> **实现分期:** v1.0 已含列表/详情/单规格 CRUD/单独 submit·offShelf/服务快照;**v1.0 补全待实现** 项在用例中标注「待实现」
8
+> **实现分期:** v1.0 + v1.0 补全 **已实现**(含 shopCategoryId、删除、批量 submit/offShelf);**O10 订单阻断仍待实现**
9 9
 
10 10
 ---
11 11
 
@@ -26,13 +26,13 @@
26 26
 | 商户 A | 店铺 **101**(张三农资店)、**102**(李四农资店);经营账号 `13800001001` / 密码见环境 |
27 27
 | 全局配置 | `default_audit_pass=0`(关,提交上架进 **待审核**);测试免审时临时改为 `1` |
28 28
 | 平台二级分类 | `categoryId=1002`(肥料>复合肥,`shop_id IS NULL`,level=2) |
29
-| 店铺商品分类 | `shopCategoryId=2005`(店内专区>热销,`shop_id=101`,level=2;**字段待实现**) |
29
+| 店铺商品分类 | `shopCategoryId=2005`(店内专区>热销,`shop_id=101`,level=2) |
30 30
 | 商品服务 | `serviceId=1`(24小时发货,默认显示)、`serviceId=3`(7天退换) |
31 31
 | 店铺 101 商品 | `1001` 未上架(G001)、`1002` 待审核(G002)、`1003` 出售中(G003)、`1004` 审核失败(G004, reject=资料不全)、`1005` 已下架(G005) |
32 32
 | 跨店商品 | `1006` 未上架,**shop_id=102** |
33 33
 | Token | 经营账号;`X-Shop-Id=101`;含 `agri:seller:goods:*` |
34 34
 | 员工 Token | 子管理员;默认 **无** 商品列表权限 |
35
-| 未完成订单 | `orderId=8001` 关联 `goodsId=1003`,状态待发货(O10 下架阻断用,**待实现**) |
35
+| 未完成订单 | `orderId=8001` 关联 `goodsId=1003`,状态待发货(O10 下架阻断用,**接口待实现**) |
36 36
 
37 37
 **状态码:** 0 未上架 / 1 待审核 / 2 出售中 / 3 审核失败 / 4 已下架
38 38
 
@@ -136,7 +136,7 @@
136 136
 | **测试目的** | 验证 GL11:仅挂平台二级分类 |
137 137
 | **前置条件** | categoryId=1001 为一级或不存在 |
138 138
 | **测试步骤** | insertSellerGoods |
139
-| **预期结果** | 失败;msg 含「请选择本店二级分类」 |
139
+| **预期结果** | 失败;msg 含「请选择平台二级分类」 |
140 140
 
141 141
 ### SGL-UT-008 新建必填项校验
142 142
 
@@ -306,7 +306,7 @@
306 306
 | **测试步骤** | insertSellerGoods |
307 307
 | **预期结果** | 失败;msg 含「存在无效的商品服务项」 |
308 308
 
309
-### SGL-UT-020 店铺商品分类校验(待实现)
309
+### SGL-UT-020 店铺商品分类校验
310 310
 
311 311
 | 要素 | 内容 |
312 312
 |------|------|
@@ -318,23 +318,23 @@
318 318
 | **测试目的** | 验证 GL11:shopCategoryId 须本店二级 |
319 319
 | **前置条件** | shopCategoryId=502 属 102;或传一级分类 ID |
320 320
 | **测试步骤** | insertSellerGoods(101, dto含shopCategoryId) |
321
-| **预期结果** | **待实现** 后失败;msg 提示分类无效 |
321
+| **预期结果** | 失败;msg 提示分类无效 |
322 322
 
323
-### SGL-UT-021 删除可删状态成功(待实现)
323
+### SGL-UT-021 删除可删状态成功
324 324
 
325 325
 | 要素 | 内容 |
326 326
 |------|------|
327 327
 | **用例编号** | SGL-UT-021 |
328 328
 | **测试模块** | 店铺商品列表 |
329
-| **测试项** | deleteSellerGoods |
329
+| **测试项** | deleteSellerGoodsBatch |
330 330
 | **测试类型** | 单元测试 |
331 331
 | **测试工具** | JUnit 5 + Mockito |
332 332
 | **测试目的** | 验证 GL9:0/3/4 可逻辑删除 |
333 333
 | **前置条件** | 1001 status=0 |
334
-| **测试步骤** | deleteSellerGoods(101, 1001) |
335
-| **预期结果** | **待实现**;del_flag=2;快照可同步清除 |
334
+| **测试步骤** | deleteSellerGoodsBatch(101, [1001]) |
335
+| **预期结果** | del_flag=2 |
336 336
 
337
-### SGL-UT-022 删除待审核/出售中失败(待实现)
337
+### SGL-UT-022 删除待审核/出售中失败
338 338
 
339 339
 | 要素 | 内容 |
340 340
 |------|------|
@@ -345,8 +345,8 @@
345 345
 | **测试工具** | JUnit 5 + Mockito |
346 346
 | **测试目的** | 验证 GL9 阻断 |
347 347
 | **前置条件** | 1002 status=1;1003 status=2 |
348
-| **测试步骤** | deleteSellerGoods |
349
-| **预期结果** | **待实现** 后失败;del_flag 不变 |
348
+| **测试步骤** | deleteSellerGoodsBatch |
349
+| **预期结果** | 失败;del_flag 不变 |
350 350
 
351 351
 ### SGL-UT-023 下架 O10 未完成订单阻断(待实现)
352 352
 
@@ -360,7 +360,7 @@
360 360
 | **测试目的** | 验证 GL8 订单约束 |
361 361
 | **前置条件** | 1003 出售中;`hasUnfinishedOrderByGoodsId(1003)=true` |
362 362
 | **测试步骤** | offShelfSeller |
363
-| **预期结果** | **待实现** 后失败;提示存在未完成订单 |
363
+| **预期结果** | **待实现**(`IGoodsOrderFacade` 接入失败;提示存在未完成订单 |
364 364
 
365 365
 ---
366 366
 
@@ -630,9 +630,9 @@
630 630
 | **测试目的** | 验证 GL8 订单阻断 |
631 631
 | **前置条件** | 1003 有 O10 未完成订单 |
632 632
 | **测试步骤** | PUT /1003/offShelf |
633
-| **预期结果** | **待实现** 后失败;明确提示订单未完成 |
633
+| **预期结果** | **待实现**(`IGoodsOrderFacade` 接入失败;明确提示订单未完成 |
634 634
 
635
-### SGL-API-020 删除未上架成功(待实现)
635
+### SGL-API-020 删除未上架成功
636 636
 
637 637
 | 要素 | 内容 |
638 638
 |------|------|
@@ -644,9 +644,9 @@
644 644
 | **测试目的** | 验证 GL9 正常删除 |
645 645
 | **前置条件** | 1001 status=0;`agri:seller:goods:remove` |
646 646
 | **测试步骤** | `DELETE /agri/seller/goods/1001` |
647
-| **预期结果** | **待实现**;code=200;列表不再返回 |
647
+| **预期结果** | code=200;列表不再返回 |
648 648
 
649
-### SGL-API-021 删除出售中失败(待实现)
649
+### SGL-API-021 删除出售中失败
650 650
 
651 651
 | 要素 | 内容 |
652 652
 |------|------|
@@ -658,9 +658,9 @@
658 658
 | **测试目的** | 验证 GL9 |
659 659
 | **前置条件** | 1003 status=2 |
660 660
 | **测试步骤** | DELETE /1003 |
661
-| **预期结果** | **待实现** 后失败;商品仍在列表 |
661
+| **预期结果** | 失败;商品仍在列表 |
662 662
 
663
-### SGL-API-022 批量提交含非法态整批失败(待实现)
663
+### SGL-API-022 批量提交含非法态整批失败
664 664
 
665 665
 | 要素 | 内容 |
666 666
 |------|------|
@@ -672,9 +672,9 @@
672 672
 | **测试目的** | 验证 GL10 |
673 673
 | **前置条件** | 勾选 1001(0) 与 1003(2) |
674 674
 | **测试步骤** | `PUT /agri/seller/goods/submit` body goodsIds |
675
-| **预期结果** | **待实现**;整批失败;data.reasons 非空;**均无** 状态变更 |
675
+| **预期结果** | 整批失败;data.reasons 非空;**均无** 状态变更 |
676 676
 
677
-### SGL-API-023 批量下架整批失败(待实现)
677
+### SGL-API-023 批量下架整批失败
678 678
 
679 679
 | 要素 | 内容 |
680 680
 |------|------|
@@ -685,7 +685,7 @@
685 685
 | **测试工具** | Apifox |
686 686
 | **测试目的** | 验证 GL10 下架批量 |
687 687
 | **前置条件** | goodsIds 含 1003(2) 与 1005(4) |
688
-| **测试步骤** | PUT /offShelf(商家批量接口 **待实现**) |
688
+| **测试步骤** | `PUT /agri/seller/goods/offShelf` |
689 689
 | **预期结果** | 整批失败;1003 **仍为** 出售中 |
690 690
 
691 691
 ### SGL-API-024 商品分类下拉
@@ -700,7 +700,7 @@
700 700
 | **测试目的** | 验证发品「商品分类」数据源 |
701 701
 | **前置条件** | 平台存在二级分类 |
702 702
 | **测试步骤** | GET /agri/seller/goods/categoryOptions |
703
-| **预期结果** | code=200;data **仅二级**;label 含「一级 > 二级」 |
703
+| **预期结果** | code=200;data **仅平台二级**(`shop_id IS NULL`);label 含「一级 > 二级」 |
704 704
 
705 705
 ### SGL-API-025 商品服务下拉
706 706
 
@@ -716,7 +716,7 @@
716 716
 | **测试步骤** | GET /serviceOptions |
717 717
 | **预期结果** | data 含 all、defaultShow;defaultShow 为默认勾选项 |
718 718
 
719
-### SGL-API-026 店铺商品分类下拉(待实现)
719
+### SGL-API-026 店铺商品分类下拉
720 720
 
721 721
 | 要素 | 内容 |
722 722
 |------|------|
@@ -728,7 +728,7 @@
728 728
 | **测试目的** | 验证 GL11 店铺分类下拉 |
729 729
 | **前置条件** | 101 有店铺二级分类 2005 |
730 730
 | **测试步骤** | GET /shopCategoryOptions |
731
-| **预期结果** | **待实现**;仅本店二级;label=`一级 > 二级` |
731
+| **预期结果** | 仅本店二级;label=`一级 > 二级` |
732 732
 
733 733
 ### SGL-API-027 无 list 权限拒绝
734 734
 
@@ -927,10 +927,10 @@
927 927
 | **测试项** | 批量提交上架 |
928 928
 | **测试类型** | 界面测试 |
929 929
 | **测试工具** | Playwright |
930
-| **测试目的** | 验证 GL10(批量 **待实现** 时测 UI 拦截或提示) |
930
+| **测试目的** | 验证 GL10 |
931 931
 | **前置条件** | 勾选 1001(未上架) 与 1003(出售中) |
932 932
 | **测试步骤** | 点「批量提交上架」 |
933
-| **预期结果** | 提示含不可提交状态;**均不变**态(或批量 API 待实现前按钮 disabled) |
933
+| **预期结果** | 提示含不可提交状态;**均不变**态 |
934 934
 
935 935
 ### SGL-UI-013 切换店铺列表刷新
936 936
 
@@ -974,7 +974,7 @@
974 974
 | **测试步骤** | 进入商品列表 |
975 975
 | **预期结果** | 展示空态文案;引导「添加商品」按钮可点 |
976 976
 
977
-### SGL-UI-016 删除确认与状态限制(待实现)
977
+### SGL-UI-016 删除确认与状态限制
978 978
 
979 979
 | 要素 | 内容 |
980 980
 |------|------|
@@ -986,7 +986,7 @@
986 986
 | **测试目的** | 验证 GL9、§12 |
987 987
 | **前置条件** | 1001 未上架可删;1002 待审核不可删 |
988 988
 | **测试步骤** | 未上架点删除→确认;待审核行 **无** 删除或点击提示 |
989
-| **预期结果** | **待实现** 后:前者删除成功;后者不可删 |
989
+| **预期结果** | 前者删除成功;后者不可删 |
990 990
 
991 991
 ### SGL-UI-017 发品默认勾选服务项
992 992
 
@@ -1035,7 +1035,8 @@
1035 1035
 
1036 1036
 | 版本 | 说明 |
1037 1037
 |------|------|
1038
-| **v1.0** | 首版:23 单元 + 28 接口 + 17 UI;覆盖 GL1~GL17 及状态机/检索/权限;标注 v1.0 补全待实现项 |
1038
+| **v1.0** | 首版:23 单元 + 28 接口 + 17 UI;覆盖 GL1~GL17 及状态机/检索/权限 |
1039
+| **v1.1** | 同步代码 v1.0 补全已实现;O10 仍标待实现;统一平台/店铺分类口径 |
1039 1040
 
1040 1041
 ---
1041 1042
 

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

@@ -25,7 +25,7 @@
25 25
 |------|-----------------|----------------------|
26 26
 | 表 | `biz_goods_category`(`shop_id IS NULL`) | **`biz_goods_category`(`shop_id = 当前店铺`)** |
27 27
 | 结构 | 一级 + 二级 | **一级 + 二级**(同表、同层级规则) |
28
-| 商家路径 | `/agri/seller/category` | **`/agri/seller/shopCategory`** |
28
+| 商家路径 | `/agri/seller/shopCategory` | **`/agri/category`**(平台维护)+ **`/agri/seller/category/platformLevel2Options`**(只读) |
29 29
 | 商品字段 | `biz_goods.category_id`(平台二级) | **`biz_goods.shop_category_id`(本店二级)** |
30 30
 | 平台端 | 可维护平台树 + 监管只读 | **不参与** |
31 31
 
@@ -36,7 +36,8 @@
36 36
 ```text
37 37
 baqing-shop/src/main/java/com/ruoyi/web/modules/category/
38 38
 ├── controller/SellerShopGoodsCategoryController.java   # /agri/seller/shopCategory
39
-├── controller/SellerCategoryController.java          # /agri/seller/category(商品分类,非本模块)
39
+├── controller/SellerPlatformCategoryController.java  # /agri/seller/category(平台分类只读,非本模块 CRUD)
40
+├── controller/PlatformCategoryController.java        # /agri/category(平台商品分类 CRUD)
40 41
 ├── service/IShopGoodsCategoryService.java
41 42
 ├── service/impl/CategoryServiceImpl.java               # 平台 + 店铺分类共用实现
42 43
 ├── domain/BizGoodsCategory.java