# 补贴发放记录 — 技术方案

> 依据：同目录 `补贴发放记录功能需求.md`。本模块为**台账类 CRUD**，无发布/下架状态；本文给出库表与 HTTP 接口约定。

---

## 1. 技术架构

| 项 | 说明 |
| --- | --- |
| **后端** | RuoYi **v3.9.2**（**springboot2** 分支）：JDK 8、Spring Boot 2.x、Spring MVC、MyBatis、Druid |
| **数据库** | MySQL **5.7.39**，InnoDB，`utf8mb4` |
| **前端** | 若依 Vue2（路由、菜单、按钮权限按项目惯例） |

**分层**：`Controller`（校验、权限、`AjaxResult` / `TableDataInfo`）→ `Service`（字段校验、脱敏可选）→ `Mapper`/XML → `domain`。

**业务特征（摘要）**

- 新增 / 修改 / 删除 / 查询**无状态前置**（与产业政策宣传不同）。
- 列表默认按 **`grant_date` 倒序**，其次 `create_time` 倒序。
- 身份证、手机号、银行账户：**库内明文存储**（或按项目加密规范）；列表/详情可按角色 **脱敏返回**（实现阶段与 §3.4 一致）。

---

## 2. 数据库设计

### 2.1 表 `biz_subsidy_grant_record`（补贴发放记录）

| 字段 | 类型 | 非空 | 默认值 | 说明 |
| --- | --- | --- | --- | --- |
| `id` | `bigint(20)` | Y | 自增 | 主键 |
| `subsidy_project_name` | `varchar(64)` | Y | — | 补贴项目名称（需求 **1～20** 字） |
| `subsidy_type` | `tinyint(4)` | Y | — | `1` 农业生产，`2` 住房基建，`3` 民生保障 |
| `recipient_name` | `varchar(32)` | Y | — | 受补贴人姓名（需求 **1～10** 字） |
| `id_card` | `varchar(18)` | Y | — | 身份证号（18 位，末位 X/x） |
| `contact_phone` | `varchar(20)` | Y | — | 联系电话（手机号） |
| `bank_account` | `varchar(32)` | Y | — | 银行账户（建议存数字串，**16～19** 位） |
| `subsidy_amount` | `decimal(12,2)` | Y | — | 补贴金额（&gt; 0） |
| `grant_date` | `date` | Y | — | 发放日期 |
| `create_by` / `create_time` / `update_by` / `update_time` | 若依惯例 | — | — | 审计字段 |
| `remark` | `varchar(500)` | N | NULL | 备注 |

**索引**：`PRIMARY KEY (id)`；`KEY idx_grant_date (grant_date)`；`KEY idx_subsidy_type (subsidy_type)`；`KEY idx_recipient_name (recipient_name)`；可选 `KEY idx_id_card (id_card)`（统计/去重扩展用）。

**DDL（MySQL 5.7）**

```sql
CREATE TABLE `biz_subsidy_grant_record` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
  `subsidy_project_name` varchar(64) NOT NULL COMMENT '补贴项目名称',
  `subsidy_type` tinyint(4) NOT NULL COMMENT '1农业生产 2住房基建 3民生保障',
  `recipient_name` varchar(32) NOT NULL COMMENT '受补贴人姓名',
  `id_card` varchar(18) NOT NULL COMMENT '身份证号',
  `contact_phone` varchar(20) NOT NULL COMMENT '联系电话',
  `bank_account` varchar(32) NOT NULL COMMENT '银行账户',
  `subsidy_amount` decimal(12,2) NOT NULL COMMENT '补贴金额',
  `grant_date` date NOT NULL COMMENT '发放日期',
  `create_by` varchar(64) DEFAULT '' COMMENT '创建者',
  `create_time` datetime DEFAULT NULL COMMENT '创建时间',
  `update_by` varchar(64) DEFAULT '' COMMENT '更新者',
  `update_time` datetime DEFAULT NULL COMMENT '更新时间',
  `remark` varchar(500) DEFAULT NULL COMMENT '备注',
  PRIMARY KEY (`id`),
  KEY `idx_grant_date` (`grant_date`),
  KEY `idx_subsidy_type` (`subsidy_type`),
  KEY `idx_recipient_name` (`recipient_name`),
  KEY `idx_id_card` (`id_card`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='补贴发放记录';
```

### 2.2 枚举常量

| 字段 | 值 | 含义 |
| --- | --- | --- |
| `subsidy_type` | `1` | 农业生产 |
| | `2` | 住房基建 |
| | `3` | 民生保障 |

---

## 3. 接口设计

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

**权限标识（示例）**：`industryPolicy:subsidyRecord:list|query|add|edit|remove|export`

**Base Path（示例）**：`/industryPolicy/subsidyRecord`

| # | 说明 | Method | URI | 权限 | 要点 |
| --- | --- | --- | --- | --- | --- |
| 3.1 | 分页列表 | GET | `/industryPolicy/subsidyRecord/list` | `industryPolicy:subsidyRecord:list` | Query 见 **3.1.1**；排序 `grant_date DESC, create_time DESC, id DESC` |
| 3.2 | 详情 | GET | `/industryPolicy/subsidyRecord/{id}` | `industryPolicy:subsidyRecord:query` | 全字段；敏感字段可按角色脱敏 |
| 3.3 | 新增 | POST | `/industryPolicy/subsidyRecord` | `industryPolicy:subsidyRecord:add` | Body 见 **3.3.1** |
| 3.4 | 修改 | PUT | `/industryPolicy/subsidyRecord` | `industryPolicy:subsidyRecord:edit` | Body 含 `id`；全字段可改 |
| 3.5 | 删除 | DELETE | `/industryPolicy/subsidyRecord/{ids}` | `industryPolicy:subsidyRecord:remove` | 支持逗号分隔批量 id |

#### 3.1.1 列表 Query 参数

| 参数 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `pageNum` | int | N | 默认 `1` |
| `pageSize` | int | N | 默认 `20` |
| `recipientName` | string | N | 受补贴人姓名**模糊**匹配 |
| `subsidyType` | int | N | `1`～`3` 精确匹配，空则不过滤 |
| `startDate` | string | N | 发放日期起 `yyyy-MM-dd`（闭区间，含当日） |
| `endDate` | string | N | 发放日期止 `yyyy-MM-dd`（闭区间，含当日） |

**区间校验**：`startDate`、`endDate` 同时存在时，`startDate` ≤ `endDate`；否则返回参数错误，不查库。

#### 3.3.1 新增 / 修改 Body（JSON，驼峰）

| 字段 | 必填 | 说明 |
| --- | --- | --- |
| `id` | 修改必填 | 主键 |
| `subsidyProjectName` | Y | 1～20 字符 |
| `subsidyType` | Y | `1`～`3` |
| `recipientName` | Y | 1～10 字符 |
| `idCard` | Y | 18 位身份证校验 |
| `contactPhone` | Y | 大陆手机号校验 |
| `bankAccount` | Y | 数字，长度 16～19（与项目校验器一致） |
| `subsidyAmount` | Y | &gt; 0，`decimal(12,2)` |
| `grantDate` | Y | `yyyy-MM-dd`，默认不允许 &gt; 当天 |
| `remark` | N | 备注 |

**列表行字段（示例）**：`id`、`subsidyProjectName`、`subsidyType`、`recipientName`、`subsidyAmount`、`grantDate`、`contactPhone`（可脱敏）、`createTime`。

### 3.4 脱敏（可选，建议）

| 字段 | 列表/无特权详情 | 完整查看权限 |
| --- | --- | --- |
| `idCard` | 保留前 4 + 后 4，中间 `*` | 明文 |
| `contactPhone` | 前 3 + `****` + 后 4 | 明文 |
| `bankAccount` | 仅后 4 位或全 `*` | 明文 |

脱敏在 Service 或 VO 层处理；**入库仍为明文**（除非项目统一字段加密）。

### 3.5 服务端校验（摘要）

| 项 | 规则 |
| --- | --- |
| 补贴项目名称 | 非空，1～20 字符 |
| 补贴类型 | ∈ {1,2,3} |
| 受补贴人姓名 | 非空，1～10 字符 |
| 身份证号 | 格式 + 校验位（复用项目 `IdCard` 校验） |
| 联系电话 | 11 位手机号规则 |
| 银行账户 | 非空，16～19 位数字 |
| 补贴金额 | &gt; 0，最多 2 位小数 |
| 发放日期 | 合法日期；默认 `grant_date` ≤ 当天 |
| 列表日期 | `startDate` ≤ `endDate` |

---

## 4. 菜单与权限 SQL（示例）

| 类型 | 名称 | 权限标识 |
| --- | --- | --- |
| 菜单 | 补贴发放记录 | `industryPolicy:subsidyRecord:list` |
| 按钮 | 查询 | `industryPolicy:subsidyRecord:query` |
| 按钮 | 新增 | `industryPolicy:subsidyRecord:add` |
| 按钮 | 修改 | `industryPolicy:subsidyRecord:edit` |
| 按钮 | 删除 | `industryPolicy:subsidyRecord:remove` |
| 按钮 | 导出 | `industryPolicy:subsidyRecord:export` |

组件路径建议：`policy/subsidyRecord/index`（与前端目录约定一致即可）。

---

## 5. 交付清单

- [ ] `biz_subsidy_grant_record` DDL、菜单与按钮权限 SQL  
- [ ] `BizSubsidyGrantRecord` Domain / Mapper / Service / Controller  
- [ ] 身份证、手机号、金额、日期校验与列表区间校验  
- [ ] 前端列表（姓名、类型、日期范围）、表单、详情、批量删除  
- [ ] （可选）导出 Excel、敏感字段脱敏  

---

## 6. 修订记录

| 日期 | 说明 |
| --- | --- |
| — | 初稿：对齐功能需求；台账 CRUD；`subsidy_type` 1～3；排序按 `grant_date` |
