# 草畜平衡计算 — 技术方案 > 依据:同目录 `草畜平衡计算功能需求.md`。本期为**无状态测算服务**:接收参数、服务端按公式计算并返回结果;**不落库**测算记录。 --- ## 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`(草场管理) | **分层**:`Controller` → `GrassLivestockBalanceService`(`GrassLivestockBalanceValidation` 校验 + `GrassLivestockBalanceCalculator` 纯计算)→ 可选读 `BizGrasslandMapper` 校验草场有效。 **代码位置(建议)**:`baqing-admin` → `com.ruoyi.web.modules.industryservice`(`GrassLivestockBalanceController`、`support/GrassLivestockBalance*`)。 **业务摘要** | 场景 | 行为 | | --- | --- | | 草场下拉/带出 | **复用**草场管理接口或本模块只读查询;`del_flag='0'` | | 计算 | `POST` 入参 → 校验 → 计算 11 项指标 → 返回 DTO;**不写库** | | 清空 | **前端**重置表单;无后端接口 | | 默认值 | 羊单位年需草量、折算系数可从 `sys_config` 读取(可选) | --- ## 2. 数据库设计 ### 2.1 本期:无新增业务表 功能需求 **§3** 明确本期不保存测算历史;计算过程**无持久化**,仅依赖已有草场台账。 | 依赖表 | 用途 | | --- | --- | | `biz_grassland` | 草场下拉、选定后带出 `area_mu`、`grass_yield_per_mu`、`utilization_rate`、`grassland_name` | ### 2.2 关联表字段(`biz_grassland` 摘录) | 字段 | 类型 | 测算用途 | | --- | --- | --- | | `id` | `bigint(20)` | 入参 `grasslandId` | | `grassland_name` | `varchar(32)` | 展示 | | `area_mu` | `decimal(12,2)` | 草场面积(亩) | | `grass_yield_per_mu` | `decimal(12,2)` | 亩产草量(kg/亩) | | `utilization_rate` | `decimal(5,4)` | 利用率 0~1 | | `del_flag` | `char(1)` | 仅 `0` 可选 | ### 2.3 系统参数(可选,非必须建表) | 配置键(示例) | 说明 | 默认值(示例) | | --- | --- | --- | | `grass.balance.sheepUnitAnnualForageKg` | 羊单位年需草量 kg/SU | 按县级规范配置 | | `grass.balance.sheepUnitConvertCoeff` | 羊单位折算系数 SU/头 | 如牦牛折算系数 | 存于若依 `sys_config`,由 `GET .../defaults` 下发给前端初始填充。 ### 2.4 后续扩展(本期不建) 若需测算留痕,可增表 `biz_grass_livestock_balance_record`(输入快照 + 结果 JSON + 操作人/时间);本期不实现。 --- ## 3. 接口设计 **统一响应**:`AjaxResult`(`code` / `msg` / `data`)。 **权限标识**:`dataModel:grassLivestockBalance:query`(进入模块、计算、读默认值) **Base Path**:`/dataModel/grassLivestockBalance` | # | 说明 | Method | URI | 权限 | 要点 | | --- | --- | --- | --- | --- | --- | | 3.1 | 执行计算 | POST | `/dataModel/grassLivestockBalance/calculate` | `query` | Body **3.1.1**;返回 **3.1.2** | | 3.2 | 羊单位默认参数 | GET | `/dataModel/grassLivestockBalance/defaults` | `query` | 读 `sys_config`,可选 | | 3.3 | 草场台账(复用) | GET | `/dataModel/grassland/list` | 草场 `list` 权限 | 下拉;`keyword` 模糊名称 | | 3.4 | 草场参数带出(复用) | GET | `/dataModel/grassland/{id}` | 草场 `query` 权限 | 选定草场后取面积、产草、利用率 | 本期**不提供**测算记录的增删改查接口;**清空**为前端行为。 #### 3.1.1 计算请求 Body | 字段 | 类型 | 必填 | 说明 | | --- | --- | --- | --- | | `grasslandId` | long | Y | 关联 `biz_grassland.id`,须 `del_flag='0'` | | `areaMu` | decimal | Y | 草场面积(亩),> 0 | | `grassYieldPerMu` | decimal | Y | 亩产草量(kg/亩),≥ 0 | | `utilizationRate` | decimal | Y | 利用率 0~1(前端传 % 时先换算) | | `sheepUnitAnnualForageKg` | decimal | Y | 羊单位年需草量(kg/SU),> 0 | | `sheepUnitConvertCoeff` | decimal | Y | 折算系数(SU/头),> 0 | | `breedingHeadCount` | int | Y | 养殖数量(头),≥ 0 | > 面积、产草、利用率允许与台账不一致(用户调整后测算);`grasslandId` 用于校验草场有效及回显名称。 #### 3.1.2 计算响应 `data` | 字段 | 类型 | 说明 | | --- | --- | --- | | `grasslandId` | long | 回显 | | `grasslandName` | string | 来自台账 | | `availableForageKg` | decimal | 可利用饲草量(kg) | | `theoreticalCarryingSu` | decimal | 理论载畜量(SU) | | `actualCarryingSu` | decimal | 实际载畜量(SU) | | `balanceIndex` | decimal | 草畜平衡指数 | | `overloadRate` | decimal | 超载率(%,已×100) | | `balanceLevel` | int | 等级码 **§3.2** | | `balanceLevelName` | string | 等级中文 | | `overloadSu` | decimal | 超载羊单位(SU);未超载可为负 | | `annualForageDemandKg` | decimal | 全年需草量(kg) | | `forageGapKg` | decimal | 饲草缺口(kg) | | `theoreticalSuitableHeads` | decimal | 理论适宜放牧(头) | | `actualOverloadHeads` | int | 实际超载数量(头),未超载为 0 | | `warning` | string | 边界提示(如理论载畜量为 0),可选 | 数值:**金额类指标保留 2 位小数**;`actualOverloadHeads` 为整数;`overloadRate` 保留 2 位小数。 #### 3.2 等级码 `balance_level` | 值 | `balanceLevelName` | 超载率 R(比较前保留 4 位小数) | | --- | --- | --- | | `1` | 未超载 | R ≤ 0 | | `2` | 基本平衡 | 0 < R ≤ 0.15 | | `3` | 超载 | 0.15 < R ≤ 0.50 | | `4` | 严重超载 | R > 0.50 | 其中 `R = balanceIndex - 1`(与需求「超载率 = (指数−1)×100%」一致,判定用未乘 100 的比率)。 #### 3.3 服务端计算公式(与需求 §5.3 一致) ``` availableForageKg = areaMu × grassYieldPerMu × utilizationRate theoreticalCarryingSu = availableForageKg / sheepUnitAnnualForageKg actualCarryingSu = breedingHeadCount × sheepUnitConvertCoeff balanceIndex = actualCarryingSu / theoreticalCarryingSu // theoretical=0 见 §3.4 overloadRate = (balanceIndex - 1) × 100 overloadSu = actualCarryingSu - theoreticalCarryingSu annualForageDemandKg = actualCarryingSu × sheepUnitAnnualForageKg forageGapKg = annualForageDemandKg - availableForageKg theoreticalSuitableHeads = theoreticalCarryingSu / sheepUnitConvertCoeff actualOverloadHeads = max(0, breedingHeadCount - floor(theoreticalSuitableHeads)) // 头数取整策略见 §3.4 balanceLevel = resolveLevel(overloadRate/100) ``` #### 3.4 边界实现约定 | 情形 | 实现 | | --- | --- | | `sheepUnitAnnualForageKg` 或 `sheepUnitConvertCoeff` ≤ 0 | 校验失败,`ServiceException` | | `theoreticalCarryingSu = 0` 且 `breedingHeadCount > 0` | `balanceIndex`、`overloadRate` 置 `null`;`balanceLevel=4`;`warning="无饲草供给"` | | `theoreticalCarryingSu = 0` 且 `breedingHeadCount = 0` | `balanceIndex=0`;等级 **未超载** | | `breedingHeadCount = 0` | 实际载畜量、全年需草量为 0;超载率为 −100%;等级 **未超载** | | `theoreticalSuitableHeads` 取整 | 默认 **四舍五入保留 2 位小数**参与比较;`actualOverloadHeads` 用 `breedingHeadCount - theoreticalSuitableHeads` 向上取整为整数且 `<0` 则 0 | | 超载羊单位/饲草缺口为负 | **原值返回**(保留 2 位小数),前端可标注「余量」 | #### 3.5 校验(`GrassLivestockBalanceValidation`) 与需求 **§5.1** 一致;`grasslandId` 须 `selectBizGrasslandById` 存在且 `del_flag='0'`。 --- ## 4. 菜单与权限(示例) | 类型 | 名称 | 权限标识 | | --- | --- | --- | | 菜单 | 草畜平衡计算 | `dataModel:grassLivestockBalance:query` | | 按钮 | 计算 | `dataModel:grassLivestockBalance:query` | 组件路径:`dataModel/grassLivestockBalance/index`(产业数据体系目录下)。 草场下拉另需:`dataModel:grassland:list`、`dataModel:grassland:query`。 --- ## 5. 交付清单 - [ ] `GrassLivestockBalanceValidation`、`GrassLivestockBalanceCalculator`、`GrassLivestockBalanceRules` - [ ] `GrassLivestockBalanceController`、`IGrassLivestockBalanceService` - [ ] 单元测试:公式、等级区间、边界(理论载畜量 0、存栏 0) - [ ] MockMvc:`POST /calculate` 成功/校验失败 - [ ] (可选)`sys_config` 初始化 SQL 与 `GET /defaults` --- ## 6. 修订记录 | 版本 | 说明 | | --- | --- | | 1.0 | 初稿:无新表;POST 计算 + 复用草场接口;等级码 1~4;公式与功能需求 §5.3 对齐 |