# 草场使用记录 — 技术方案 > 依据:同目录 `草场使用记录功能需求.md`。使用记录 **CRUD** + 主数据关联校验 + **使用天数服务端计算** + **逻辑删除**。 --- ## 1. 技术架构 | 项 | 说明 | | --- | --- | | **后端** | RuoYi **v3.9.2**(**springboot2** 分支):JDK 8、Spring Boot 2.x、Spring MVC、MyBatis、Druid | | **数据库** | MySQL **5.7.39**,InnoDB,`utf8mb4` | | **前端** | 若依 Vue2(本方案不展开页面实现) | | **依赖主数据** | `biz_grassland`(草场管理)、`biz_pasture`(牧场管理 / 养殖主体) | **分层**:`Controller` → `Service`(`GrasslandUsageValidation`、天数计算、主数据校验)→ `Mapper`/XML(列表 **JOIN** 主数据取名称)→ `domain`。 **代码位置(建议)**:`baqing-admin` → `com.ruoyi.web.modules.industryservice`(`BizGrasslandUsageRecord`、Mapper、Service、Controller)。 **业务摘要** | 场景 | 行为 | | --- | --- | | 新增/修改 | 校验草场、主体 `del_flag='0'`;`usage_area_mu ≤ grassland.area_mu`;重算 `actual_use_days`;`del_flag='0'` | | 列表/详情 | 仅 `del_flag='0'`;JOIN 展示 `grasslandName`、`pastureName`;排序 `create_time DESC, id DESC` | | 删除 | **逻辑删除**:`del_flag` 置 `'2'` | | 使用天数 | 服务端:`actual_use_days = DATEDIFF(end, start) + 1`(含起止日);忽略客户端传入天数 | --- ## 2. 数据库设计 ### 2.1 表 `biz_grassland_usage_record`(草场使用记录) | 字段 | 类型 | 非空 | 默认值 | 说明 | | --- | --- | --- | --- | --- | | `id` | `bigint(20)` | Y | 自增 | 主键 | | `grassland_id` | `bigint(20)` | Y | — | 关联 `biz_grassland.id` | | `pasture_id` | `bigint(20)` | Y | — | 关联 `biz_pasture.id`(养殖主体) | | `usage_area_mu` | `decimal(12,2)` | Y | — | 使用面积(**亩**),> 0 | | `use_start_date` | `date` | Y | — | 开始使用日期 | | `use_end_date` | `date` | Y | — | 结束使用日期;≥ 开始日 | | `actual_use_days` | `int(11)` | Y | — | 实际使用天数(**服务端计算**入库) | | `grazing_head_count` | `int(11)` | Y | — | 放牧数量(**头**),≥ 1 | | `grazing_method` | `tinyint(4)` | Y | — | 放牧方式 **§2.2** | | `del_flag` | `char(1)` | Y | `'0'` | `0` 存在 `2` 删除 | | `create_by` / `create_time` / `update_by` / `update_time` | 若依惯例 | — | — | 审计;列表「预约日期」筛 `create_time` | | `remark` | `varchar(500)` | N | NULL | 备注(可选扩展) | **索引**:`PRIMARY KEY (id)`;`KEY idx_grassland_id (grassland_id)`;`KEY idx_pasture_id (pasture_id)`;`KEY idx_create_time (create_time)`;`KEY idx_del_flag (del_flag)`;`KEY idx_use_start (use_start_date)`。 **关联约定**:逻辑外键,不在库层强制 `FOREIGN KEY`(与项目其他业务表一致);保存前 Service 校验主数据存在且 `del_flag='0'`。 **DDL(MySQL 5.7)** ```sql CREATE TABLE `biz_grassland_usage_record` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键', `grassland_id` bigint(20) NOT NULL COMMENT '草场ID biz_grassland', `pasture_id` bigint(20) NOT NULL COMMENT '养殖主体ID biz_pasture', `usage_area_mu` decimal(12,2) NOT NULL COMMENT '使用面积(亩)', `use_start_date` date NOT NULL COMMENT '开始使用日期', `use_end_date` date NOT NULL COMMENT '结束使用日期', `actual_use_days` int(11) NOT NULL COMMENT '实际使用天数', `grazing_head_count` int(11) NOT NULL COMMENT '放牧数量(头)', `grazing_method` tinyint(4) NOT NULL COMMENT '放牧方式1轮牧2自由3季节', `del_flag` char(1) NOT NULL DEFAULT '0' COMMENT '0存在 2删除', `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_grassland_id` (`grassland_id`), KEY `idx_pasture_id` (`pasture_id`), KEY `idx_create_time` (`create_time`), KEY `idx_del_flag` (`del_flag`), KEY `idx_use_start` (`use_start_date`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='草场使用记录'; ``` ### 2.2 枚举常量 | 字段 | 值 | 含义 | | --- | --- | --- | | `grazing_method` | `1` | 轮牧 | | | `2` | 自由放牧 | | | `3` | 季节性放牧 | | `del_flag` | `0` | 正常 | | | `2` | 已逻辑删除 | ### 2.3 列表查询 JOIN(示意) 列表、详情需展示名称时关联主表(仅有效主数据用于**新增**校验;历史记录列表仍展示当时关联 id 对应名称,主数据已删时名称可为空或仍显示冗余策略由实现约定): ```sql -- 列表片段 FROM biz_grassland_usage_record r LEFT JOIN biz_grassland g ON r.grassland_id = g.id LEFT JOIN biz_pasture p ON r.pasture_id = p.id WHERE r.del_flag = '0' ``` --- ## 3. 接口设计 **统一响应**:`AjaxResult`(`code` / `msg` / `data`)或分页 `TableDataInfo`(`rows`、`total`)。 **权限标识**:`dataModel:grasslandUsage:list|query|add|edit|remove|export` **Base Path**:`/dataModel/grasslandUsage` | # | 说明 | Method | URI | 权限 | 要点 | | --- | --- | --- | --- | --- | --- | | 3.1 | 分页列表 | GET | `/dataModel/grasslandUsage/list` | `dataModel:grasslandUsage:list` | Query **3.1.1**;JOIN 名称;`create_time DESC, id DESC` | | 3.2 | 详情 | GET | `/dataModel/grasslandUsage/{id}` | `dataModel:grasslandUsage:query` | 含 `grasslandId`、`pastureId` 及名称展示字段 | | 3.3 | 新增 | POST | `/dataModel/grasslandUsage` | `dataModel:grasslandUsage:add` | Body **3.3.1**;服务端算天数 | | 3.4 | 修改 | PUT | `/dataModel/grasslandUsage` | `dataModel:grasslandUsage:edit` | Body 含 `id`;忽略客户端 `actualUseDays` | | 3.5 | 删除 | DELETE | `/dataModel/grasslandUsage/{ids}` | `dataModel:grasslandUsage:remove` | 逻辑删除;`ids` 逗号分隔批量 | **主数据下拉(复用,不重复建设)** | 用途 | 建议接口 | 说明 | | --- | --- | --- | | 草场选择 | `GET /dataModel/grassland/list` | `keyword` 模糊名称;仅 `del_flag=0`;前端取 `id`、`grasslandName`、`areaMu` | | 养殖主体选择 | `GET /dataModel/pasture/list` | `keyword` 模糊 `pastureName`;仅有效主体 | 若需轻量选项列表,可增加 `GET .../optionList`(返回 `id`+`name`),本期非必须。 #### 3.1.1 列表 Query | 参数 | 类型 | 必填 | 说明 | | --- | --- | --- | --- | | `pageNum` / `pageSize` | int | N | 默认 `1` / `20` | | `keyword` | string | N | 关联**草场名称**模糊(`g.grassland_name`);空不过滤 | | `startDate` | string | N | 创建日期起 `yyyy-MM-dd`(界面「预约日期」起) | | `endDate` | string | N | 创建日期止 `yyyy-MM-dd`;`date(create_time)` 闭区间 | **日期区间 Service 校验**:若 `startDate`、`endDate` 均非空且 `startDate > endDate`,抛业务异常。 #### 3.3.1 新增 / 修改 Body(驼峰) | 字段 | 必填 | 说明 | | --- | --- | --- | | `id` | 修改 Y | 主键 | | `grasslandId` | Y | 草场主键 | | `pastureId` | Y | 养殖主体主键 | | `usageAreaMu` | Y | 正数(亩);≤ 该草场 `area_mu` | | `useStartDate` | Y | `yyyy-MM-dd` | | `useEndDate` | Y | `yyyy-MM-dd`;≥ `useStartDate` | | `actualUseDays` | N | **服务端覆盖**;客户端传值忽略 | | `grazingHeadCount` | Y | 正整数(头) | | `grazingMethod` | Y | `1`~`3` | | `remark` | N | 备注 | **列表/详情响应扩展字段(非表字段)**:`grasslandName`、`pastureName`(JOIN 或二次查询填充)。 ### 3.4 使用天数计算(服务端) ```text actual_use_days = (use_end_date - use_start_date) 的自然日差 + 1 ``` - Java 实现:`GrasslandUsageValidation.resolveActualUseDays(start, end)`。 - 保存前统一调用,写入 `actual_use_days`。 ### 3.5 Mapper 约定 - 业务表 CRUD 均带 `r.del_flag = '0'`(列表、详情、更新)。 - 逻辑删除:`update ... set del_flag='2', update_by=?, update_time=now() where del_flag='0' and id in (...)`。 - 列表按 **§3.1.1** 过滤;`keyword` 作用在 `biz_grassland.grassland_name`。 ### 3.6 服务端校验(摘要) | 项 | 规则 | | --- | --- | | 草场 / 主体 | `grasslandId`、`pastureId` 非空;对应记录存在且 `del_flag='0'` | | 使用面积 | > 0;≤ 所选草场 `area_mu` | | 使用日期 | 非空;`useStartDate ≤ useEndDate` | | 实际使用天数 | 由 **§3.4** 计算后入库 | | 放牧数量 | ≥ 1 整数 | | 放牧方式 | ∈ {1, 2, 3} | | 列表创建日期区间 | `startDate ≤ endDate`(均填时) | 校验类建议:`GrasslandUsageRules`、`GrasslandUsageValidation`(`validateRowForSave`、`validateDateRangeForList`)。 --- ## 4. 菜单与权限(示例) | 类型 | 名称 | 权限标识 | | --- | --- | --- | | 菜单 | 草场使用记录 | `dataModel:grasslandUsage:list` | | 按钮 | 查询 | `dataModel:grasslandUsage:query` | | 按钮 | 新增 | `dataModel:grasslandUsage:add` | | 按钮 | 修改 | `dataModel:grasslandUsage:edit` | | 按钮 | 删除 | `dataModel:grasslandUsage:remove` | | 按钮 | 导出 | `dataModel:grasslandUsage:export` | 组件路径建议:`dataModel/grasslandUsage/index`(挂载在「产业数据模型及体系」下)。 --- ## 5. 交付清单 - [ ] `sql/biz_grassland_usage_record.sql`、菜单与按钮权限 SQL - [ ] `BizGrasslandUsageRecord` Domain / Mapper(含 JOIN 列表)/ Service / Controller - [ ] `GrasslandUsageRules`、`GrasslandUsageValidation`(主数据、面积上限、天数计算) - [ ] 逻辑删除 - [ ] 单元测试 / 接口测试(MockMvc) --- ## 6. 修订记录 | 版本 | 说明 | | --- | --- | | 1.0 | 初稿:对齐功能需求;`biz_grassland_usage_record`;关联 `biz_grassland`/`biz_pasture`;天数服务端计算;逻辑删除 |