# 首页 Banner 设置 — 技术方案

> **依据：** 《首页banner设置功能需求.md》v1.0.1  
> **关联：** 《商品服务管理技术方案.md》v1.0.1、《会员管理技术方案.md》v1.0、《关联需求分析.md》v1.2；内容管理兄弟模块（商城服务协议/入驻协议草稿）  
> **范围：** 本文以 **Banner 主数据**、**平台端 CRUD**、**C 端只读列表** 为主；**无** 商户/店铺/商品/订单表关联。  
> **原则：** 全平台单表（非 `shop_id`）；逻辑删除；批量删除 **无关联阻断**；C 端 `@Anonymous` 读启用列表。

---

## 1. 技术架构

| 项 | 选型 |
|----|------|
| 基础框架 | RuoYi **v3.9.2**（`springboot2` 分支） |
| 数据库 | **MySQL 5.7.39** |
| ORM / 权限 / 响应 | MyBatis；`@PreAuthorize`；`AjaxResult` / `TableDataInfo` |
| 图片 | `CommonController` 上传（`/common/upload`），库内存 URL |
| 日志 | 增删改、改排序 `@Log` |

### 1.1 模块落位

```text
baqing-shop
├── com.ruoyi.web.modules.content
│   ├── controller.BannerController              # 平台端 /agri/banner
│   ├── domain.BizHomeBanner
│   ├── mapper.BizHomeBannerMapper
│   ├── service.IBannerService
│   └── constant.BannerConstants
├── com.ruoyi.web.modules.home
│   └── controller.HomeAppController             # C 端 GET /api/home/banners
│       └── mapper.HomeAppMapper                 # 直读 biz_home_banner（Anonymous）
sql/
└── biz_home_banner.sql
```

> **无** Facade 对外暴露（BN8～BN10：与供给链/订单无耦合）。C 端 Banner **列表** 由 **home** 模块提供；平台 CRUD 仍走 **content** 模块 `IBannerService`。

### 1.2 业务链

```text
biz_home_banner（本模块 · 平台维护）
        │
        ├── 平台 Web ── CRUD / 行内改序
        │
        └── C 端首页 ── GET /api/home/banners（Anonymous · `HomeAppController`）
                └── 前端过滤无效图、零条隐藏轮播区（BN13，客户端）
```

| 模块 | 关系 |
|------|------|
| 商户/店铺/商品/分类/订单 | **无表关联**；状态 **不级联** |
| 商品服务管理 | 同属平台 **内容/主数据**；表独立 |
| 会员管理 | C 端 **Anonymous** 可读 Banner；禁用会员 **不拦** 本接口 |
| 商城服务/入驻协议（草稿） | 同「内容管理」菜单域；表独立 |

### 1.3 跨模块接口（本模块对外）

| 类型 | 说明 |
|------|------|
| **无 Java Facade** | 其他模块 **不依赖** Banner |
| **C 端 HTTP** | `HomeAppController`（`com.ruoyi.web.modules.home`）提供 `GET /api/home/banners` |

### 1.4 状态联动

| 事件 | `biz_home_banner` | 商户/店铺/商品/订单 |
|------|-------------------|---------------------|
| 增/改/删/启停/改序 | 变更本表 | **不变** |
| 商户冻结、店停业、商品下架 | — | **不变** Banner |

---

## 2. 数据库设计

### 2.1 本模块表

| 表名 | 说明 |
|------|------|
| `biz_home_banner` | 首页轮播 Banner 主数据（全平台一份） |

### 2.2 字段

| 字段 | 类型 | 说明 |
|------|------|------|
| banner_id | bigint PK | 自增 |
| banner_name | varchar(64) | 图片名称；**`del_flag=0` 时唯一**（应用层 BN3） |
| banner_image | varchar(512) | 图片 URL；非空 |
| enable_flag | char(1) | `0` 否 `1` 是；默认 **1** |
| sort_no | int | 升序；默认 **0** |
| del_flag | char(1) | `0` 存在 `2` 逻辑删除 |
| create_by, create_time, update_by, update_time, remark | | RuoYi 审计 |

> **本期不存** 跳转链接、定时上下线、渠道维度字段。

### 2.3 索引

| 索引 | 字段 | 用途 |
|------|------|------|
| PRIMARY | banner_id | |
| idx_list | del_flag, enable_flag, sort_no, create_time | 平台列表、C 端启用列表 |
| — | banner_name + del_flag | 唯一性 **应用层** 校验 |

### 2.4 DDL

脚本：`sql/biz_home_banner.sql`

```sql
CREATE TABLE `biz_home_banner` (
  `banner_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'BannerID',
  `banner_name` varchar(64) NOT NULL COMMENT '图片名称',
  `banner_image` varchar(512) NOT NULL COMMENT '图片URL',
  `enable_flag` char(1) NOT NULL DEFAULT '1' COMMENT '0否1是',
  `sort_no` int(11) NOT NULL DEFAULT '0' COMMENT '排序升序',
  `del_flag` char(1) NOT NULL DEFAULT '0' COMMENT '0存在2删除',
  `create_by` varchar(64) DEFAULT '',
  `create_time` datetime DEFAULT NULL,
  `update_by` varchar(64) DEFAULT '',
  `update_time` datetime DEFAULT NULL,
  `remark` varchar(500) DEFAULT NULL,
  PRIMARY KEY (`banner_id`),
  KEY `idx_list` (`del_flag`,`enable_flag`,`sort_no`,`create_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='首页Banner';
```

### 2.5 字典

| dict_type | 用途 | 值 |
|-----------|------|-----|
| yes_no | `enable_flag` 列表展示 | 0 否 / 1 是 |

---

## 3. 平台端接口设计

**基路径：** `/agri/banner`  
**权限：** `agri:banner:list` | `add` | `edit` | `remove`

统一响应：`AjaxResult`（`code`、`msg`、`data`）/ `TableDataInfo`（`rows`、`total`）。

### 3.1 接口一览

| 方法 | 路径 | 权限 | 说明 |
|------|------|------|------|
| GET | `/list` | list | 分页列表 + 检索 |
| GET | `/{bannerId}` | list | 详情（编辑回显） |
| POST | `/` | add | 新增 |
| PUT | `/` | edit | 编辑（全字段） |
| PUT | `/sortNo` | edit | **行内改排序**（BN12） |
| DELETE | `/{bannerIds}` | remove | 逻辑删除；`bannerIds` 逗号分隔 |

### 3.2 列表 `GET /list`

| Query | 说明 |
|-------|------|
| pageNum, pageSize | 分页 |
| bannerName | 可选；`banner_name` 模糊 |
| enableFlag | 可选；`0` / `1`；不传查全部 |

**WHERE：** `del_flag = '0'`  
**ORDER BY：** `sort_no ASC`, `create_time ASC`

**rows 字段：**

| 字段 | 说明 |
|------|------|
| bannerId, bannerName, bannerImage | |
| enableFlag, enableFlagLabel | 字典 yes_no |
| sortNo | 支持行内编辑 |
| createTime | 可选展示 |

### 3.3 详情 `GET /{bannerId}`

返回单条；`del_flag=2` 或不存在 → 业务异常「Banner 不存在或已删除」。

### 3.4 新增 `POST /`

```json
{
  "bannerName": "春耕主推",
  "bannerImage": "/profile/upload/2026/05/banner1.jpg",
  "enableFlag": "1",
  "sortNo": 0
}
```

| 字段 | 校验 |
|------|------|
| bannerName | 非空 ≤64；`del_flag=0` 唯一 |
| bannerImage | 非空；后缀 `jpg/jpeg/png`；上传阶段 ≤5MB |
| enableFlag | `0` / `1` |
| sortNo | 整数 ≥0 |

**成功 `data`（可选）：**

```json
{
  "bannerId": 1,
  "warnAspectRatio": true
}
```

`warnAspectRatio`：服务端根据图片宽高判断非 **2:1** 时返回 `true`（**不阻断**保存，对齐 BN11）；无法读取尺寸则省略。

### 3.5 编辑 `PUT /`

Body 同新增 + `bannerId`；名称唯一（排除自身）。

### 3.6 行内改排序 `PUT /sortNo`

```json
{
  "bannerId": 1,
  "sortNo": 10
}
```

| 规则 | 说明 |
|------|------|
| 仅更新 | `sort_no`、`update_by`、`update_time` |
| 校验 | `sortNo` ≥0；记录须 `del_flag=0` |
| C 端 | 保存成功后 **即时** 按新序展示 |

> 列表行内改序 **只调本接口**；不提供拖拽、批量改序接口。

### 3.7 删除 `DELETE /{bannerIds}`

```text
前端二次确认
    → foreach bannerId:
         存在且 del_flag=0 → UPDATE del_flag='2'
         已删/不存在 → 记入 skipped（可选）
    → 返回成功；msg「删除成功」或「部分记录已删除，已跳过 N 条」
```

**定稿：** **无** `existsXxxRef` 阻断；**不** 采用商品服务整批失败策略（功能需求 §7.2）。

---

## 4. C 端接口设计

**基路径：** `/api/home`  
**鉴权：** `@Anonymous`（首页公开浏览，对齐功能需求 §8.2）

### 4.1 首页 Banner 列表 `GET /api/home/banners`

| 项 | 说明 |
|----|------|
| 过滤 | `del_flag=0` AND `enable_flag=1` |
| 排序 | `sort_no ASC`, `create_time ASC` |
| 分页 | **不分页**；全量返回（运营配置量小，建议 ≤20 条，超出可在 Service 加 `LIMIT 50`） |

**响应 `data`：**

```json
[
  {
    "bannerId": 1,
    "bannerImage": "/profile/upload/2026/05/banner1.jpg",
    "sortNo": 0
  }
]
```

| 字段 | 说明 |
|------|------|
| bannerId | 前端预览大图可用 |
| bannerImage | 完整 URL（相对路径由前端拼 `VUE_APP_BASE_API` 或 CDN） |
| bannerName | **不下发**（后台管理用，BN 需求） |

**C 端职责（不在本接口实现）：**

- 图片 404/解码失败 → **跳过** 该条（BN13）
- 过滤后 `length=0` → **不渲染** 轮播容器
- 点击 → 预览大图，**无** 路由跳转（BN14）

### 4.2 与会员登录的关系

| 接口 | 鉴权 |
|------|------|
| `GET /api/home/banners` | **无需** Token |
| `POST /api/member/login` 等 | 会员模块 |

---

## 5. Service 要点

```text
insert  → 名称唯一 → enable_flag 默认 1 → sort_no 默认 0
update  → 名称唯一（排除自身）→ 可改图/启停/排序
updateSortNo → 仅改 sort_no
remove  → UPDATE del_flag='2'（无关联校验）
listForApp → enable_flag=1 AND del_flag=0 ORDER BY sort_no
```

| 场景 | msg（示例） |
|------|-------------|
| 名称为空 | 请输入图片名称 |
| 名称重复 | 图片名称已存在 |
| 未上传图 | 请上传图片 |
| 图片格式/大小 | 仅支持 jpg/png/jpeg，单张不超过 5MB |
| 排序非法 | 排序须为非负整数 |
| 记录不存在 | Banner 不存在或已删除 |

**图片规格（BN11）：**

- 上传：复用 RuoYi `CommonController`，扩展名白名单 + 5MB（与商户/商品图一致）。
- 比例：保存时若可读取宽高且 `width/height ≠ 2`，`data.warnAspectRatio=true`。

---

## 6. 业务规则映射

| 编号 | 实现 |
|------|------|
| BN1～BN2 | 单表；仅 `BannerController` + 菜单权限 |
| BN3 | `countByBannerName(name, excludeId)` |
| BN4 | list / listForApp `ORDER BY sort_no, create_time` |
| BN5 | C 端 SQL 过滤 `enable_flag=1` |
| BN6 | 无发布表；读写同一表即时生效 |
| BN7 | `DELETE` → `del_flag=2` |
| BN8～BN10 | 无 Facade、无 FK |
| BN11 | 上传校验 + 可选 `warnAspectRatio` |
| BN12 | `PUT /sortNo` |
| BN13～BN14 | C 端前端实现 |

---

## 7. 菜单权限

| 菜单（建议） | 权限标识 |
|--------------|----------|
| 首页 Banner 设置 | `agri:banner:list` |
| 新增 | `agri:banner:add` |
| 修改 | `agri:banner:edit`（含 `/sortNo`） |
| 删除 | `agri:banner:remove` |

**上级菜单：** 农资管理 → **内容管理** → 首页 Banner 设置（与协议子菜单并列）。

---

## 8. 关联方案摘要

```text
【平台】POST /agri/banner → 维护素材
    ↓
【C 端】GET /api/home/banners → 首页轮播（Anonymous）
    ↓
【C 端】浏览商品/下单 → 商品/店铺/订单模块（与 Banner 无关）

【并行】商品服务目录、会员注册、商户供给链 — 无表依赖
```

| 对比项 | 商品服务管理 | 本模块 |
|--------|--------------|--------|
| 表 | `biz_goods_service` | `biz_home_banner` |
| 消费方 | 商品发品、快照 | **仅 C 端首页** |
| 删除阻断 | `existsGoodsRef` 整批失败 | **无** |
| C 端接口 | 无独立 Anonymous 列表 | `GET /api/home/banners` |
| 改序 | 编辑页 sortNo | 编辑 + **`PUT /sortNo`** |

---

## 9. 非本期实现

跳转链接、定时启停、分渠道 Banner、Redis 缓存、恢复已删、点击统计、视频 Banner、`IBannerFacade`。

---

## 10. 文档索引

| 文档 | 版本 |
|------|------|
| 首页banner设置功能需求.md | v1.0.1 |
| 商城首页技术方案.md | v1.1 |
| 商品服务管理技术方案.md | v1.0.1 |
| 会员管理技术方案.md | v1.0 |
| 关联需求分析.md | v1.2 |

---

## 11. 修订记录

| 版本 | 说明 |
|------|------|
| **v1.0** | 首版 |
| **v1.0.1** | C 端 `GET /api/home/banners` 落位 **`home.HomeAppController`**；平台 CRUD 仍 **content**；修正包路径 |

---

*文档版本：v1.0.1 · MySQL 5.7.39 · RuoYi v3.9.2-springboot2 · 关联《首页banner设置功能需求.md》v1.0.1*
