# 商品详情内页 — 技术方案（C 端）

> **依据：** 《商品详情内页功能需求.md》v1.0  
> **关联：** 平台《商品管理技术方案》v1.3、《店铺商品列表技术方案》v1.x、《商品服务管理技术方案》v1.0.1、《商品分类技术方案》v1.2、《店铺管理技术方案》v1.3.6、《商城首页技术方案》v1.1、《商品分类技术方案（C 端）》v1.0、《关联需求分析.md》v1.6  
> **范围：** C 端 **`/api/goods/**`** 只读（详情聚合、可购校验、评价列表）；**无** 加购/下单写接口、**无** 平台/商家商品 CRUD。  
> **原则：** 复用 `biz_goods` 及快照表、`biz_shop`；**`biz_goods_pic`** 商家副图 **已实现**（见商家《店铺商品列表技术方案》）；**`biz_goods_review`** 评价 **规划**；浏览 **不过滤** 出售中/店态/库存；可购 **四条件** 走 **`IGoodsPurchaseFacade`**；全部读接口 **`@Anonymous`**。

---

## 1. 技术架构

| 项 | 选型 |
|----|------|
| 基础框架 | RuoYi **v3.9.2**（`springboot2` 分支） |
| 数据库 | **MySQL 5.7.39** |
| ORM / 响应 | MyBatis；详情/可购 `AjaxResult`；评价 `TableDataInfo`（分页） |
| 鉴权 | 读接口 **`@Anonymous`**；加购/立即购买 **不在本模块**（购物车/确认订单需登录） |
| 缓存 | **本期不做** Redis |
| 规格 | **v1.0 统一规格**：价格/库存读 **`biz_goods`**；`biz_goods_attr` 仅 **展示** |

### 1.1 模块落位

```text
baqing-shop/src/main/java/com/ruoyi/web/modules/home/
├── controller/GoodsAppController.java          # /api/goods/**
├── service/IGoodsAppService.java
├── service/impl/GoodsAppServiceImpl.java
├── mapper/GoodsAppMapper.java                  # 详情 JOIN SQL（可选薄封装）
├── mapper/BizGoodsPicMapper.java               # 读副图（goods 模块已实现写；C 端读待实现 §2.3）
├── vo/GoodsDetailAppVO.java                    # C 端详情（无商家/平台操作字段）
├── vo/GoodsShopBriefAppVO.java
├── vo/GoodsLogisticsAppVO.java                 # v1 可空
└── constant/GoodsAppConstants.java

resources/mapper/home/
└── GoodsAppMapper.xml

已有（goods 模块 · 复用，不暴露 C 端 HTTP）：
├── facade/IGoodsPurchaseFacade.canPurchase      # 四条件（GD15）
├── mapper/BizGoodsServiceSnapshotMapper         # selectVisibleByGoodsId（P20）
├── mapper/BizGoodsAttrMapper                    # 属性/展示规格快照
├── mapper/BizGoodsMapper
└── support/GoodsAttrSupport.groupByItem

已有（category / store）：
├── ICategoryFacade.getCategoryPath / isCategoryVisible
└── IAgriShopFacade.isShopOpenForOrder
```

> **说明：** C 端详情与首页/分类 **同属 `home` 包**、基路径 **`/api/goods`**（与 `/api/home`、`/api/category` 并列）。商家 `/agri/seller/goods`、平台 `/agri/goods` **不复用** HTTP，仅复用 Facade/Mapper。

### 1.2 协作链

```text
biz_goods（del=0）
    ├── JOIN biz_shop（店名/头像/电话/状态）
    ├── biz_goods_pic → 副图 gallery（§2.3；商家已落库 subPics）
    ├── biz_goods_service_snapshot → 服务说明区（过滤已删目录 P20）
    ├── biz_goods_attr（attr_type=1 参数，2 展示规格项）
    ├── biz_goods_review → 评价列表（§2.4；未落库时 reviews 空分页）
    └── ICategoryFacade → categoryPath、可购分类校验

GET /api/goods/{goodsId}           → 详情聚合 + purchase 块
GET /api/goods/{goodsId}/can-purchase → 可购校验（加购/购买前可重调）
GET /api/goods/{goodsId}/reviews   → 评价分页（表待建，见 §2.4）

【页面】
    首页/分类/店铺 ──goodsId──► 详情
    底栏加购/购买 ──► 购物车/确认订单（另模块）；本模块仅 can-purchase
```

| 关联模块 | 协作 |
|----------|------|
| **店铺商品列表** | 发品写 `biz_goods`、快照；C 端 **只读** |
| **商品服务管理** | 快照 `selectVisibleByGoodsId`；删目录 C 端不展示 |
| **商品分类 Facade** | 路径展示；`isCategoryVisible` 纳入可购 |
| **店铺管理** | `shop_name/avatar/phone/status` **实时**；停业禁购 |
| **商城首页 / C 端分类** | 列表 **仅出售中**；详情 **可展示** 非出售中（直链 GD10） |
| **购物车 / 确认订单** | **待建设**；本模块 **不提供** POST |
| **评价管理** | **待建设**；评价接口预留 |

### 1.3 跨模块 Facade

| 接口 | 本模块用法 |
|------|------------|
| **`IGoodsPurchaseFacade.canPurchase(goodsId)`** | 详情 `purchase` 块；`/can-purchase` |
| **`ICategoryFacade.getCategoryPath`** | 详情 `categoryPath` |
| **`ICategoryFacade.isCategoryVisible`** | 已含于 `canPurchase` |
| **`IAgriShopFacade.isShopOpenForOrder`** | 已含于 `canPurchase` |
| **`IGoodsService.selectSellerDetail`** | **不直接** 暴露；C 端专用 VO **剔除** 审核/操作字段 |

---

## 2. 数据库设计

### 2.1 原则

**已有表只读；扩展表按 §2.3、§2.4 规划落地。** DDL 见 `sql/`。

| 表 | 状态 | 本模块用途 | 权威 DDL |
|----|------|------------|----------|
| `biz_goods` | **已有** | 主图、名称、价/库/销量、状态、图文详情 | `sql/biz_goods.sql` |
| `biz_goods_service_snapshot` | **已有** | 服务说明（快照） | `sql/biz_goods.sql` |
| `biz_goods_attr` | **已有** | 商品参数、展示规格项 | `sql/biz_goods_attr.sql` |
| `biz_shop` | **已有** | 进店区、售后电话 | `sql/biz_shop.sql` |
| `biz_goods_category` | **已有** | 分类路径（经 Facade） | `sql/biz_goods_category.sql` |
| `biz_goods_pic` | **商家已实现** | 商品 **副图**（不含主图）；C 端轮播合并读 | `sql/biz_goods_pic.sql` |
| `biz_goods_review` | **规划** | 商品评价列表（GD14） | `sql/biz_goods_review.sql` |

### 2.2 本模块读字段与条件

**`biz_goods` + `biz_shop`**

| 场景 | SQL 条件 | 输出 / 说明 |
|------|----------|-------------|
| **详情** | `g.goods_id = #{goodsId}` AND `g.del_flag = '0'` AND `s.del_flag = '0'` | **不强制** `goods_status = '2'`（浏览层 GD15） |
| 主图轮播 | `g.main_pic` + `biz_goods_pic` | `pics[]` 见 §2.3：`[mainPic]` + 副图有序 URL |
| 简述 v1 | — | 库表 **暂无** `goods_brief`；返回 `null`，前端 **不展示** |
| 价/库/销量 | `sale_price, stock, sales_count` | 统一规格 **直接输出** |
| 状态 | `goods_status` | 映射标签；非出售中 **purchase.allowed=false** |
| 图文 | `detail_content` | 原样返回（前端渲染） |

**`biz_goods_service_snapshot`**

```sql
-- 与 BizGoodsServiceSnapshotMapper.selectVisibleByGoodsId 一致
-- LEFT JOIN biz_goods_service 过滤 del_flag=2（P20）
ORDER BY sort_no ASC, snapshot_id ASC
```

**`biz_goods_attr`**

| attr_type | 含义 | C 端用途 |
|-----------|------|----------|
| **`1`** | 属性项 | §4.3 **商品参数** `attributes[]` |
| **`2`** | 规格项（模版维度） | **展示** `specDisplay[]`；**v1 不参与** SKU 价库 |

> **v1.0 定稿：** 可购 **四条件** 库存取自 **`biz_goods.stock`**；`attr_type=2` **不是** 可购买 SKU 矩阵（与商家发品 v1 单规格一致）。

**`biz_shop`**

| 字段 | 用途 |
|------|------|
| shop_id, shop_name, shop_avatar | 进店区（GD13） |
| shop_phone | 售后说明 **客服电话**（GD8） |
| shop_status | `0` 开业 / `1` 停业；可购校验 |

**物流说明（GD7）— v1 数据源**

| 字段 | v1.0 |
|------|------|
| 承诺发货时间 | 从服务快照 **名称匹配**（如含「发货」）或 **null** |
| 运费 | **无** `biz_goods_freight` → `freightDesc = null`，前端 **隐藏** 或占位 |
| 发货地 | **无** 字段 → `shipCity = null` |

### 2.3 商品副图 gallery — `biz_goods_pic`

> **关联：** 商家《店铺商品列表技术方案》§2.5；需求 **GD4** 图片轮播；C 端详情 `pics[]`。  
> **商家写侧：** `GoodsSaveDTO.subPics` → `biz_goods_pic`（**已实现**）。  
> **C 端读侧：** `GoodsAppServiceImpl` 合并 `mainPic` + 副图（**已实现**）。

#### 2.3.1 与 `biz_goods.main_pic` 的关系

| 项 | 定稿 |
|----|------|
| **主图** | `biz_goods.main_pic`：**必填**；列表/搜索/卡片权威主图 |
| **副图** | `biz_goods_pic` 仅存 **副图 URL**（**不含** 主图）；商家 `subPics[]` 写入 |
| **数量** | 副图 **非必填**；最多 **10** 张（`GoodsConstants.MAX_SUB_PIC_COUNT`） |
| **C 端 `pics[]`** | **主图 + 副图合集**：`[mainPic]` + 副图（按 `sort_no ASC`）；无副图时 `pics=[mainPic]` |
| **删除商品** | 商家删商品时 **物理删除** 该商品全部副图行 |

#### 2.3.2 字段说明

| 字段 | 类型 | 说明 |
|------|------|------|
| `pic_id` | bigint PK | 图片行 ID |
| `goods_id` | bigint | 商品 ID（`biz_goods.goods_id`） |
| `pic_url` | varchar(512) | 副图 URL（与 `main_pic` 同存储规范） |
| `sort_no` | int | 副图顺序，**升序**；从 0 起 |
| `del_flag` | char(1) | `0` 正常；C 端 **仅读** `del_flag=0` |
| 审计字段 | | `create_by/create_time/update_by/update_time` |

**约束与索引：**

| 项 | 说明 |
|----|------|
| 单商品副图上限 | **10** 张（Service 校验） |
| 索引 | `idx_goods_gallery (goods_id, del_flag, sort_no)` |

#### 2.3.3 C 端读取 SQL

```sql
SELECT pic_url
FROM biz_goods_pic
WHERE goods_id = #{goodsId}
  AND del_flag = '0'
ORDER BY sort_no ASC, pic_id ASC
```

**聚合逻辑（Service · 已实现）：**

```text
subUrls = BizGoodsPicMapper.selectPicUrlsByGoodsId(goodsId)
pics = [ goods.mainPic ] + subUrls    -- 主图+副图合集；主图始终首张
```

#### 2.3.4 商家写侧约定（已实现）

| 操作 | 行为 |
|------|------|
| POST/PUT 保存 | `subPics` **全量替换**：先 `deleteByGoodsId`，再 `batchInsert` |
| 不传 / 空数组 | 清空副图；**不影响** `main_pic` |
| 删商品 | 同步 `deleteByGoodsId` 副图行 |

**权威 DDL：** [`sql/biz_goods_pic.sql`](../../../sql/biz_goods_pic.sql)

---

### 2.4 商品评价 — `biz_goods_review`（规划）

> **关联：** 需求 **GD14**、§10 评价区；订单 **完成后** 发表（评价写接口 **另册**）；本模块 **只读** 列表。

#### 2.4.1 业务规则

| 项 | 定稿 |
|----|------|
| 可见范围 | C 端 **仅展示** `show_flag=1` 且 `del_flag=0` 的评价 |
| 排序 | **`create_time DESC, review_id DESC`**（最新优先，GD14） |
| 详情摘要 | 前端 `pageSize=2`；全部评价页默认 `pageSize=10` |
| 发表入口 | **不在** 详情页；订单完成 → 评价模块 POST（待建） |
| 商家回复 | `reply_content` 非空时 C 端展示；维护在 **评价管理**（待建） |
| 一行一评 | 同一 `order_item_id` **至多一条** 评价（`uk_order_item_review`） |
| 商品图展示 | 读 **`goods_main_pic` 快照**（评价提交时写入，不随商品改图变化） |

#### 2.4.2 字段说明

| 字段 | 类型 | 说明 |
|------|------|------|
| `review_id` | bigint PK | 评价 ID |
| `goods_id` | bigint | 被评商品 ID（`biz_goods.goods_id`）；列表/统计主键 |
| `order_id` | bigint | 来源订单 ID（`biz_order.order_id`）；冗余便于追溯 |
| `order_item_id` | bigint | 来源明细行 ID（`biz_order_item.item_id`）；**唯一**，防重复评价 |
| `member_id` | bigint | 评价人会员 ID（`biz_member.member_id`） |
| `shop_id` | bigint | 店铺 ID **冗余**（`biz_shop.shop_id`）；商家 **评价管理** 列表按店过滤 |
| `member_nick_name` | varchar(64) | 评价时会员 **昵称快照**；C 端展示，支持脱敏策略 |
| `member_avatar` | varchar(512) | 评价时会员 **头像快照**；C 端展示 |
| `content` | varchar(1000) | 评价正文；**必填** |
| `score` | tinyint | 评分 **1～5** 星；可为 null（若产品不要求星级） |
| `review_pics` | varchar(2000) | **晒图** URL，**英文逗号** 分隔；最多建议 9 张（应用层校验） |
| `goods_main_pic` | varchar(512) | 评价关联 **商品主图快照**（对应需求 §10.1「商品图片」） |
| `goods_spec` | varchar(64) | 规格文案快照；首期单规格可「默认」；多 SKU 后填当时规格 |
| `reply_content` | varchar(500) | **商家回复** 正文；null 表示未回复 |
| `reply_by` | varchar(64) | 回复操作人（商家账号） |
| `reply_time` | datetime | 商家回复时间 |
| `show_flag` | char(1) | **C 端可见**：`1` 显示 `0` 隐藏（平台/商家屏蔽差评等） |
| `del_flag` | char(1) | `0` 正常 `2` 逻辑删除 |
| `create_time` | datetime | **评价提交时间**；列表排序字段 |
| `update_time` | datetime | 最后更新时间（回复、屏蔽时更新） |

#### 2.4.3 C 端读取 SQL

```sql
SELECT review_id, member_nick_name, member_avatar, content, score,
       review_pics, goods_main_pic, goods_spec,
       reply_content, reply_time, create_time
FROM biz_goods_review
WHERE goods_id = #{goodsId}
  AND show_flag = '1'
  AND del_flag = '0'
ORDER BY create_time DESC, review_id DESC
```

**VO 映射：** `review_pics` 拆为 `pics: string[]`；`memberNickName` / `memberAvatar` 直接输出。

#### 2.4.4 索引

| 索引 | 用途 |
|------|------|
| `uk_order_item_review (order_item_id)` | 一行一评 |
| `idx_order_id (order_id)` | 按订单查评价 |
| `idx_goods_list (goods_id, show_flag, del_flag, create_time)` | C 端商品评价分页 |
| `idx_shop_list (shop_id, show_flag, del_flag, create_time)` | 商家评价管理列表 |

**未建表时：** `GET .../reviews` 返回 `rows=[]`、`total=0`（**不** 404）。

**权威 DDL：** [`sql/biz_goods_review.sql`](../../../sql/biz_goods_review.sql)

---

### 2.5 其它扩展表（非首期）

| 表 | 用途 | 关联需求 |
|----|------|----------|
| `biz_goods_freight` | 固定运费 / 模版 ID | 物流说明 §4.4 |
| `biz_goods_sku` | 多规格 SKU：价/库/规格组合 | 多规格加购 |
| `biz_shop_stats` | 评分、粉丝数 | 店铺主页 |

### 2.6 建议索引（已有表）

现有 `uk_goods_sn`、`idx_shop_status`、`idx_category_id` 一般够用；§2.3、§2.4 新表索引见各节。

---

## 3. C 端接口设计

**基路径：** `/api/goods`  
**鉴权：** 读接口 **`@Anonymous`**

### 3.1 接口一览

| 方法 | 路径 | 说明 |
|------|------|------|
| GET | `/{goodsId}` | 商品详情聚合 |
| GET | `/{goodsId}/can-purchase` | 可购四条件校验（轻量） |
| GET | `/{goodsId}/reviews` | 评价分页（**表待建** §2.4） |

**本期不提供：** 加购 POST、立即购买 POST、搜索、店铺主页 API。

### 3.2 商品详情 `GET /api/goods/{goodsId}`

| 项 | 说明 |
|----|------|
| Path | `goodsId` |
| 校验 | 商品 **存在** 且 `del_flag=0`；店铺 **未删**；否则 **404 业务提示**「商品不存在」 |

**`data`：** `GoodsDetailAppVO`

| 字段 | 类型 | 说明 |
|------|------|------|
| goodsId | long | |
| goodsSn | string | |
| goodsName | string | |
| goodsBrief | string | v1 **常 null** |
| pics | string[] | **主图+副图合集**（§2.3）：`[mainPic]` + 副图；无副图时仅 `[mainPic]` |
| salePrice | decimal | 统一规格售价 |
| stock | int | 统一规格库存 |
| salesCount | int | |
| goodsStatus | string | `0`～`4` |
| goodsStatusLabel | string | 字典文案 |
| categoryPath | string | 一级 > 二级 |
| detailContent | string | 图文详情 HTML/JSON |
| attributes | GoodsAttrItemDTO[] | `attr_type=1` |
| specDisplay | GoodsAttrItemDTO[] | `attr_type=2`，**展示用** |
| services | GoodsServiceSnapshotVO[] | 快照；已删目录项 **过滤** |
| logistics | object | `{ shipPromise, freightDesc, shipCity }`；v1 可 **全 null** |
| shop | object | 见下表 |
| purchase | object | `{ allowed: bool, reason: string }` |
| afterSalePhone | string | `shop_phone`；空则 **null** |

**`shop` 子对象：**

| 字段 | 说明 |
|------|------|
| shopId, shopName, shopAvatar | 实时 |
| shopStatus | `0` 开业 / `1` 停业 |
| shopPhone | 同 afterSalePhone |
| rating, fansCount | v1 **null**（店铺统计待建） |

**实现要点：**

1. 查 `biz_goods` + `biz_shop` JOIN。  
2. `pics` ← `[main_pic]` + `BizGoodsPicMapper.selectPicUrlsByGoodsId`（goods 模块 Mapper 复用）。  
3. `services` ← `selectVisibleByGoodsId`。  
4. `attributes` / `specDisplay` ← `GoodsAttrSupport.groupByItem`。  
5. `purchase` ← `IGoodsPurchaseFacade.canPurchase(goodsId)`。  
6. **不返回** `rejectReason、canAudit、merchantName` 等 B 端字段。

**浏览 vs 可购：**

| goods_status | 详情 HTTP | purchase.allowed |
|--------------|-----------|------------------|
| **2** 出售中 | 200 | 另看店态/分类/库存 |
| **4** 已下架 | 200 | **false**，reason 含「非出售中」 |
| 0/1/3 | 200（直链） | **false** |

### 3.3 可购校验 `GET /api/goods/{goodsId}/can-purchase`

| 项 | 说明 |
|----|------|
| 用途 | 加购/购买 **点击前** 重校验（GD15） |
| 实现 | 直接 `IGoodsPurchaseFacade.canPurchase` |

**`data`：** `GoodsPurchaseVO`

| 字段 | 说明 |
|------|------|
| allowed | true/false |
| reason | 失败原因：商品不存在 / 商品非出售中 / 库存不足 / 店铺已停业 / 商品分类不可见 |

**校验顺序（与 Facade 实现一致）：**

```text
商品存在 → goods_status=2（出售中）→ stock>0 → 店铺开业 → 分类可见
```

> v1 **无 skuId** 参数；多规格 SKU 落地后扩展 Query `skuId`。

### 3.4 商品评价 `GET /api/goods/{goodsId}/reviews`

| 项 | 说明 |
|----|------|
| Query | `pageNum`、`pageSize`（RuoYi 默认） |
| 响应 | **`TableDataInfo`** `{ code, msg, rows, total }` |
| v1 未建表 | `rows=[]`，`total=0`；**不** 404 |

**`rows` 元素（`biz_goods_review` 落地后 · 见 §2.4）：**

| 字段 | 说明 |
|------|------|
| reviewId | |
| memberAvatar | `member_avatar` 快照 |
| memberNickName | `member_nick_name` 快照（可脱敏） |
| content | 评价内容 |
| pics | `review_pics` 拆分为 string[] |
| score | 1～5 星 |
| goodsMainPic | `goods_main_pic` 快照 |
| goodsSpec | 规格快照；可 null |
| replyContent | 商家回复 |
| replyTime | 回复时间 |
| createTime | 评价时间；**最新倒序** |

**详情页摘要：** 前端调本接口 `pageSize=2`；「全部评价」页 **`pageSize` 默认 10**。

---

## 4. Service 分层

```text
GoodsAppController
    → IGoodsAppService.getDetail(goodsId)
    → IGoodsAppService.canPurchase(goodsId)
    → IGoodsAppService.listReviews(goodsId)    # 分页由 Controller startPage

GoodsAppServiceImpl
    → GoodsAppMapper.selectDetailBase(goodsId)   # 或 BizGoodsMapper + ShopMapper
    → BizGoodsPicMapper.selectPicUrlsByGoodsId   # 副图；C 端合并 mainPic（goods 模块已实现写）
    → BizGoodsServiceSnapshotMapper.selectVisibleByGoodsId
    → BizGoodsAttrMapper.selectByGoodsId + GoodsAttrSupport
    → ICategoryFacade.getCategoryPath
    → IGoodsPurchaseFacade.canPurchase
    → BizGoodsReviewMapper.selectByGoodsId         # §2.4；未建表则空列表
```

| 方法 | 说明 |
|------|------|
| `getDetail` | 聚合 VO；**不** 因非出售中抛异常 |
| `canPurchase` | 透传 Facade |
| `listReviews` | v1 返回空列表 |

---

## 5. 与平台后台对照

| 平台/商家操作 | 影响的 C 端接口 |
|---------------|-----------------|
| 商家保存商品 / 副图 | 详情 `pics[]`（主图+副图）、`main_pic` 更新 |
| 商品下架 | `purchase.allowed=false` |
| 平台审核通过 | 状态 → 出售中，可购可能变 true |
| 店铺改名/头像/电话 | `shop`、`afterSalePhone` **即时** |
| 店铺停业 | `can-purchase` 失败 |
| 平台分类 hide | `can-purchase` 失败 |
| 平台删服务项 | 详情 **不展示** 该快照行 |
| 改服务目录文案 | **不追溯** 已有快照 |

---

## 6. 业务规则映射

| 规则 | 实现 |
|------|------|
| GD4 | `biz_goods_pic` → `pics[]`（§2.3） |
| GD1～GD3、GD5～GD13 | `/api/goods/{id}` 字段与分区 |
| GD10 | 非出售中 / 缺货：`purchase` + 前端置灰 |
| GD11～GD12 | **前端 + 购物车/订单**；本模块仅 `can-purchase` |
| GD13 | `shop` 对象 |
| GD14 | `biz_goods_review` → `/reviews`（§2.4） |
| GD15 | `IGoodsPurchaseFacade` |
| GD16 | 停业：`isShopOpenForOrder` |
| GD17 | `selectVisibleByGoodsId` 过滤已删服务 |

---

## 7. 前端接口调用建议

| 场景 | 调用 |
|------|------|
| 进入详情 | `GET /api/goods/{goodsId}` |
| 渲染加购/购买按钮 | 读 `data.purchase`；点击前可再调 `/can-purchase` |
| 评价摘要 2 条 | `GET /api/goods/{goodsId}/reviews?pageNum=1&pageSize=2` |
| 全部评价 | 同接口，`pageSize=10` |
| 加购 | **购物车模块** POST（待建） |
| 立即购买 | **确认订单模块**（待建） |

---

## 8. 实现状态

| 项 | 状态 |
|----|------|
| `GET /api/goods/{goodsId}` | **已实现** |
| `GET /api/goods/{goodsId}/can-purchase` | **已实现**（复用 `IGoodsPurchaseFacade`） |
| `GET /api/goods/{goodsId}/reviews` | **已实现**（表 **待建**，当前返空分页） |
| `GoodsAppController` / `GoodsAppServiceImpl` | **已创建**（`modules/home/`） |
| `GoodsAppMapper.xml` | **已创建** |
| `GoodsPicSupport.buildGalleryPics` | **已实现**（主图+副图合集） |
| `sql/biz_goods_pic.sql` | **已提供** |
| `sql/biz_goods_review.sql` | **已规划** |
| `BizGoodsPicMapper`（goods 模块） | **已实现**（C 端读复用） |
| `BizGoodsReviewMapper` | **待创建**（表落地后） |
| 单元/API 测试 | **已通过**（`GoodsAppServiceImplTest`、`GoodsAppControllerTest`、`GoodsPicSupportTest`） |
| C 端详情前端 | **已实现**（见《商品详情内页前端技术方案.md》v1.0） |

---

## 9. 非本期

| 项 | 说明 |
|------|------|
| POST 加购 / 立即购买 | 购物车、确认订单 |
| `biz_goods_sku` / freight | §2.5 |
| 评价 **发表** / 商家回复写接口 | 订单完成链、评价管理 |
| 店铺评分粉丝 | 店铺主页 / stats 表 |
| Redis 缓存 | — |
| 聚合 `/api/goods/{id}/index` | 前端分调即可 |

---

## 10. 修订记录

| 版本 | 说明 |
|------|------|
| **v1.0** | 首版；三读接口；复用 `IGoodsPurchaseFacade` 与快照；v1 统一规格 |
| **v1.1** | 补全 **`biz_goods_pic`** / **`biz_goods_review`** DDL 与字段 COMMENT |
| **v1.2** | 对齐商家 **副图** 实现：`subPics` 存 `biz_goods_pic`；C 端 `pics=主图+副图合集` |
| **v1.3** | 对齐需求 **GD4**：明确轮播为 **主图、副图合集**（主图首张） |
| **v1.4** | **C 端后端已实现**：`GoodsApp*` + `GoodsPicSupport`；`pics` 主图+副图合并 |
| **v1.5** | 评价表改 **一行一评**（`uk_order_item_review`）；见 [`sql/biz_goods_review_order_item_uk.sql`](../../../sql/biz_goods_review_order_item_uk.sql) |

---

*文档版本：v1.5 · MySQL 5.7.39 · RuoYi v3.9.2-springboot2 · 关联《商品详情内页功能需求.md》v1.1*
