西藏巴青项目

市场进栏登记技术方案.md 13KB

市场进栏登记 — 技术方案

依据:市场进栏登记功能需求.md(同目录)
实现参照:baqing-admin 模块 com.ruoyi.web.modules.tradingBizMarketEntry*


1. 技术架构

层级 说明
整体 RuoYi v3.9.2springboot2 分支)单体后端 + 若依 Vue2 前端(与分支配套)
运行时 JDK 8、Spring Boot 2.x、Spring MVC、MyBatis、Druid
数据库 MySQL 5.7.39,存储引擎 InnoDB,字符集 utf8mb4

后端分层(与若依一致)

  • BizMarketEntryController:参数绑定、权限注解、返回 AjaxResult / TableDataInfo
  • IBizMarketEntryService / BizMarketEntryServiceImpl:事务、主从表保存、R1~R6 校验编排
  • MarketEntryValidationMarketEntryEarTagResolverMarketEntryReferenceChecker:规则与可选耳标池
  • BizMarketEntryMapperBizMarketEntryEarTagMapper + XML:持久化
  • domainBizMarketEntryBizMarketEntryEarTag;复用 EarTagCodec

业务摘要(与功能需求对齐)

场景 行为
新增/修改 校验栏位、供应商;R1~R6;主表落库 → 子表 batchInsert;修改时先按 entry_id 删子表再插入;quantity = 子表行数
列表/详情 主表 del_flag=0supplier_name JOIN;子表聚合 earTags / 组装 earTagList
删除 主表 del_flag=2;子表保留;占用查询以主表 del_flag 过滤
辅助接口 stallOptionssupplierEarTagsA−B,仅 supplierId,见 §5

初始化脚本sql/biz_market_entry.sql


2. 源码位置

类型 路径
Controller baqing-admin/src/main/java/com/ruoyi/web/modules/trading/controller/BizMarketEntryController.java
Service .../service/IBizMarketEntryService.java.../service/impl/BizMarketEntryServiceImpl.java
校验/解析 .../support/MarketEntryValidation.javaMarketEntryEarTagResolver.javaMarketEntryRules.java
Mapper .../mapper/BizMarketEntryMapper.javaBizMarketEntryEarTagMapper.java
XML baqing-admin/src/main/resources/mapper/trading/BizMarketEntryMapper.xmlBizMarketEntryEarTagMapper.xml
实体 .../domain/BizMarketEntry.javaBizMarketEntryEarTag.java
VO .../domain/vo/MarketStallOptionVo.java

3. 数据库设计

3.1 主表:biz_market_entry(进栏记录)

字段名 类型 非空 默认值 说明
id bigint(20) Y 自增 主键
entry_time datetime Y 进栏时间
stall_id bigint(20) Y 关联 biz_market_stall.id
stall_code char(2) Y 栏位编号冗余,列表模糊筛选
supplier_id bigint(20) Y 关联 biz_supplier.id
quantity int(11) Y 数量(头),= 子表耳标行数
del_flag char(1) Y '0' 删除标记,见 3.4
create_by / create_time / update_by / update_time 若依惯例 审计
remark varchar(500) N NULL 备注

索引PRIMARY KEY (id)KEY idx_entry_timeKEY idx_stall_codeKEY idx_supplierKEY idx_del_flag

主表不存 ear_tags 文本字段;耳标明细见 3.2

3.2 子表:biz_market_entry_ear_tag(耳标明细)

字段名 类型 非空 默认值 说明
id bigint(20) Y 自增 主键
entry_id bigint(20) Y 关联主表 biz_market_entry.id
supplier_id bigint(20) Y 供应商 ID(与主表一致,便于占用查询)
ear_tag varchar(32) Y 耳标号,单段 1~32 字

索引与约束

  • PRIMARY KEY (id)
  • UNIQUE KEY uk_entry_ear (entry_id, ear_tag) — 同单内耳标不重复
  • KEY idx_entry_id (entry_id)KEY idx_supplier_id (supplier_id)KEY idx_ear_tag (ear_tag)

维护策略:新增/修改主表成功后批量插入子表;修改时 DELETE FROM biz_market_entry_ear_tag WHERE entry_id=? 后重插。

3.3 关联表(只读,本模块不建)

用途
biz_market_stall 栏位下拉、stall_code 冗余写入
biz_supplier 供应商校验、列表 supplier_name
biz_entry_isolation 可选耳标池 A(主表 ear_tags,隔离已结束)
biz_entry_isolation_alloc 入场隔离分圈(本模块耳标池 B 使用)
biz_isolation_patrol 可选耳标池 B(全表病死病害耳标,selectSickDeadEarTagRows

3.4 删除标记 del_flag(主表)

含义
0 正常
2 已逻辑删除

3.5 DDL(MySQL 5.7)

完整脚本见 sql/biz_market_entry.sql。核心结构如下:

CREATE TABLE `biz_market_entry` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `entry_time` datetime NOT NULL,
  `stall_id` bigint(20) NOT NULL,
  `stall_code` char(2) NOT NULL,
  `supplier_id` bigint(20) NOT NULL,
  `quantity` int(11) NOT NULL,
  `del_flag` char(1) NOT NULL DEFAULT '0',
  `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 (`id`),
  KEY `idx_entry_time` (`entry_time`),
  KEY `idx_stall_code` (`stall_code`),
  KEY `idx_supplier` (`supplier_id`),
  KEY `idx_del_flag` (`del_flag`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='市场进栏登记';

CREATE TABLE `biz_market_entry_ear_tag` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `entry_id` bigint(20) NOT NULL,
  `supplier_id` bigint(20) NOT NULL,
  `ear_tag` varchar(32) NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_entry_ear` (`entry_id`,`ear_tag`),
  KEY `idx_entry_id` (`entry_id`),
  KEY `idx_supplier_id` (`supplier_id`),
  KEY `idx_ear_tag` (`ear_tag`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='市场进栏登记耳标明细';

4. 字段命名约定(接口 JSON)

与前端、持久化 小驼峰(camelCase) 对齐;库表为下划线。

前端 / JSON(camelCase) 库表字段 说明
id id 主键
entryTime entry_time 进栏时间
stallId stall_id 市场栏位 ID
stallCode stall_code 栏位编号(服务端冗余写入)
supplierId supplier_id 供应商 ID
supplierName 列表/详情 JOIN 展示,非主表列
quantity quantity 头数
earTagList 子表 ear_tag 请求/响应数组;入库拆为多行
earTags 子表聚合 列表/详情逗号拼接展示用
entryDateStart / entryDateEnd 列表筛选,映射 DATE(entry_time)
earTag 子表 ear_tag 列表筛选,子表 LIKE
remark remark 备注

子表行(内部/扩展):entryIdsupplierIdearTag


5. 可选耳标池(MarketEntryEarTagResolver

与功能需求 §4 一致。耳标字段均为逗号分隔文本,经 EarTagCodec.parse 拆分去重。

集合 规则 实现要点
A 入场隔离主表耳标;supplier_iddel_flag=0隔离已结束 BizEntryIsolationMapper.selectEndedMainEarTagRowsBySupplierexpected_release_date <= CURDATE()
B 全部巡查;del_flag=0sick_dead_qty>0 且耳标非空 BizIsolationPatrolMapper.selectSickDeadEarTagRows supplierId 条件)
C 他单进栏占用 BizMarketEntryEarTagMapper.selectOccupiedEarTags;主表 del_flag=0entry_id <> excludeEntryId

隔离已结束:当前日期 预计解除日期。

5.1 下拉接口 listSupplierEarTagOptionsGET /supplierEarTags

  • 入参:仅 supplierId(必填);校验供应商存在且未删除。
  • 返回:A − B,升序 string[]
  • 不含 C;已被他单占用的耳标仍可能出现在下拉中。

5.2 保存校验 listEligible(新增/修改 R4)

  • 返回:(A − B) − C
  • excludeEntryId:新增为 null;修改传当前主表 id,释放本条已选耳标占用。

6. 业务校验与事务

MarketEntryValidation(保存时 R1~R6)

规则 实现要点
R1 进栏时间、栏位、供应商、至少 1 个耳标
R2 entry_time <= now()
R3 biz_market_stallbiz_supplier 存在且 del_flag=0
R4 每个耳标 ∈ listEligible(supplierId, excludeEntryId)
R5 EarTagCodec 去重,单段 1~32 字
R6 quantity = earTagList.size()

事务insert / update 使用 @Transactional;主表与子表在同一事务内提交。

删除MarketEntryReferenceChecker.hasReference(id) 为 true 时拒绝;否则主表 del_flag=2


7. 接口设计

统一响应AjaxResultcodemsgdata)/ TableDataInforowstotal)。

权限标识tradeMarket:marketEntry:list|query|add|edit|remove

Base Path/tradeMarket/marketEntry

路由注册顺序:/stallOptions/supplierEarTags 须在 /{id} 之前

接口说明 HTTP URI(相对 Base Path) 权限
分页列表 GET /list list
详情 GET /{id} query
新增 POST / add
修改 PUT / edit
删除 DELETE /{ids} remove
栏位下拉 GET /stallOptions listquery
可选耳标 GET /supplierEarTags listquery

7.1 列表 GET /list

参数 类型 必填 说明
pageNum / pageSize int N 默认 1 / 20
entryDateStart / entryDateEnd string N yyyy-MM-dd;闭区间;均填时须 start <= end
stallCode string N stall_code LIKE %stallCode%
supplierId long N 精确
earTag string N 子表 ear_tag LIKE %earTag%EXISTS

条件del_flag='0'排序entry_time DESC, id DESC

行字段identryTimestallIdstallCodesupplierIdsupplierNameearTagsearTagList(可选)、quantity、审计字段。

7.2 详情 GET /{id}

data:主表全字段 + earTagList + supplierName(子表组装)。

7.3 新增 POST /

Body 字段 必填 说明
entryTime Y yyyy-MM-dd HH:mm:ss,≤ 当前时间
stallId Y 服务端写入 stallCode
supplierId Y
earTagList Y ≥1;或与 earTags 逗号串二选一,经 EarTagCodec 解析
quantity N 服务端以耳标数为准覆盖
remark N ≤500 字

7.4 修改 PUT /

7.3id 必填;保存时服务端以 id 作为 excludeEntryId 参与 §5.2 占用校验(与 supplierEarTags 无关)。

7.5 删除 DELETE /{ids}

单条可只传一个 id;更新主表 del_flag='2';有下游引用返回「存在关联业务,无法删除」。

7.6 栏位下拉 GET /stallOptions

data[{ stallId, stallCode }]biz_market_stalldel_flag=0stall_code ASC

7.7 可选耳标 GET /supplierEarTags

参数 类型 必填 说明
supplierId long Y 供应商

datastring[]A−B,见 §5.1)。供应商无效时业务异常。

计算步骤(与需求 §4.1、§4.2 一致)

  1. supplierIdbiz_entry_isolationdel_flag=0expected_release_date <= CURDATE(),汇总主表 ear_tags(逗号拆分去重)→ A
  2. biz_isolation_patroldel_flag=0sick_dead_qty>0、耳标非空(全表,不按 supplierId),汇总 ear_tagsB
  3. 返回 A − B(升序)。剔除他单进栏占用 C(保存时见 §5.2§6 R4)

7.8 供应商搜索(前端联调)

登记表单模糊搜索:复用 /tradeMarket/supplier/listsupplierName 模糊);列表筛选使用本模块 supplierId 精确条件。


8. 菜单与权限(示例)

类型 名称 权限标识
菜单 市场进栏登记 tradeMarket:marketEntry:list
按钮 查询 tradeMarket:marketEntry:query
按钮 新增 tradeMarket:marketEntry:add
按钮 修改 tradeMarket:marketEntry:edit
按钮 删除 tradeMarket:marketEntry:remove

组件路径(前端):tradeMarket/marketEntry/index


9. 交付清单

  • sql/biz_market_entry.sql(主表 + 子表)
  • BizMarketEntryBizMarketEntryEarTag、Mapper/XML、Service、Controller
  • MarketEntryValidationMarketEntryEarTagResolverMarketEntryRules
  • 单元测试 / MockMvc(com.ruoyi.web.modules.trading.**.*MarketEntry*

10. 修订记录

日期 说明
初稿:单表 ear_tags 文本存储
v2.0:耳标池 A−B−C;关联入场隔离、隔离巡查
v2.1:主从表 biz_market_entry + biz_market_entry_ear_tag
版式对齐《养殖标准管理技术方案》《养殖标准管理技术前端方案》;接口/库表/源码路径分章
v2.2:supplierEarTagssupplierId,返回 A−B;B 为全表巡查病死耳标;保存 (A−B)−C