# 市场行情登记 — 技术方案 > 依据:同目录 `市场行情登记功能需求.md`。日度行情 **CRUD** + **逻辑删除**;**渠道**关联 `biz_trade_market`;**均价**服务端按 `(最低价+最高价)/2` 计算;概率合计 **100%**。 --- ## 1. 技术架构 | 项 | 说明 | | --- | --- | | **后端** | RuoYi **v3.9.2**(**springboot2** 分支):JDK 8、Spring Boot 2.x、Spring MVC、MyBatis、Druid | | **数据库** | MySQL **5.7.39**,InnoDB,`utf8mb4` | | **前端** | 若依 Vue2;产地 `RegionCascader`;渠道下拉;字段 **小驼峰**(本方案不展开页面) | **分层**:`Controller` → `Service`(`MarketDailyQuoteValidation`、**均价计算**、维度唯一校验)→ `Mapper`/XML → `domain`。 **代码包(建议)**:`com.ruoyi.web.modules.trademarket` **关联主数据**:`biz_trade_market`(畜牧流通 · 交易市场管理);仅 `del_flag=0` 且 `operate_status=1` 的市场可作为渠道。 **业务摘要** | 场景 | 行为 | | --- | --- | | 新增/修改 | 校验维度与概率;**重算** `avg_price`;可选字段空存 `NULL` | | 列表/详情 | 仅 `del_flag=0`;关联市场名称;排序 `quote_date DESC, create_time DESC, id DESC` | | 列表筛选 | 日期区间、`trade_market_id` 精确、`county_code` 精确(产地至县) | | 删除 | `del_flag=2`;有关联时 `ServiceException` | | 唯一性 | 同 **§2.4** 维度组合在 `del_flag=0` 内唯一(Service 校验) | --- ## 2. 数据库设计 ### 2.1 表 `biz_market_daily_quote`(日度行情) | 字段 | 类型 | 非空 | 默认值 | 说明 | | --- | --- | --- | --- | --- | | `id` | `bigint(20)` | Y | 自增 | 主键 | | `quote_date` | `date` | Y | — | 行情日期 | | `province_code` | `varchar(12)` | Y | — | 省编码 | | `province_name` | `varchar(64)` | Y | — | 省名称 | | `city_code` | `varchar(12)` | Y | — | 市编码 | | `city_name` | `varchar(64)` | Y | — | 市名称 | | `county_code` | `varchar(12)` | Y | — | 县编码 | | `county_name` | `varchar(64)` | Y | — | 县名称 | | `trade_market_id` | `bigint(20)` | Y | — | 渠道(交易市场 id) | | `cattle_gender` | `tinyint(4)` | Y | `1` | 公母 **§2.3** | | `weight_grade` | `tinyint(4)` | N | NULL | 重量档 | | `growth_stage` | `tinyint(4)` | N | NULL | 生长阶段 | | `age_month_grade` | `tinyint(4)` | N | NULL | 月龄档 | | `fat_grade` | `tinyint(4)` | N | NULL | 膘情 | | `price_min` | `decimal(12,2)` | Y | — | 最低价 | | `price_max` | `decimal(12,2)` | Y | — | 最高价 | | `price_unit` | `tinyint(4)` | Y | `2` | 单位:1 元/头 2 元/斤 | | `avg_price` | `decimal(12,2)` | Y | — | 均价(服务端计算落库) | | `supply_status` | `tinyint(4)` | Y | — | 出栏情况 | | `change_factors` | `varchar(128)` | Y | — | 变化因素,逗号分隔枚举码,如 `1,3,5` | | `prob_rise` | `decimal(5,2)` | Y | — | 看涨概率 % | | `prob_flat` | `decimal(5,2)` | Y | — | 看平概率 % | | `prob_fall` | `decimal(5,2)` | Y | — | 看跌概率 % | | `outbound_advice` | `varchar(500)` | Y | — | 出栏建议 | | `del_flag` | `char(1)` | Y | `'0'` | `0` 存在 `2` 删除 | | `create_by` / `create_time` / `update_by` / `update_time` | 若依惯例 | — | — | 审计 | **索引**:`PRIMARY KEY (id)`;`KEY idx_quote_date (quote_date)`;`KEY idx_trade_market_id (trade_market_id)`;`KEY idx_county_code (county_code)`;`KEY idx_del_flag (del_flag)`;`KEY idx_quote_dim (quote_date, county_code, trade_market_id, cattle_gender)`(辅助查重,唯一性以 Service 为准,因可空维度需归一化)。 ### 2.2 DDL(MySQL 5.7) ```sql CREATE TABLE `biz_market_daily_quote` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键', `quote_date` date NOT NULL COMMENT '行情日期', `province_code` varchar(12) NOT NULL COMMENT '省编码', `province_name` varchar(64) NOT NULL COMMENT '省名称', `city_code` varchar(12) NOT NULL COMMENT '市编码', `city_name` varchar(64) NOT NULL COMMENT '市名称', `county_code` varchar(12) NOT NULL COMMENT '县编码', `county_name` varchar(64) NOT NULL COMMENT '县名称', `trade_market_id` bigint(20) NOT NULL COMMENT '交易市场ID', `cattle_gender` tinyint(4) NOT NULL DEFAULT '1' COMMENT '1公牛2母牛3混合', `weight_grade` tinyint(4) DEFAULT NULL COMMENT '重量档', `growth_stage` tinyint(4) DEFAULT NULL COMMENT '生长阶段', `age_month_grade` tinyint(4) DEFAULT NULL COMMENT '月龄档', `fat_grade` tinyint(4) DEFAULT NULL COMMENT '膘情', `price_min` decimal(12,2) NOT NULL COMMENT '最低价', `price_max` decimal(12,2) NOT NULL COMMENT '最高价', `price_unit` tinyint(4) NOT NULL DEFAULT '2' COMMENT '1元/头2元/斤', `avg_price` decimal(12,2) NOT NULL COMMENT '均价', `supply_status` tinyint(4) NOT NULL COMMENT '出栏情况', `change_factors` varchar(128) NOT NULL COMMENT '变化因素枚举码逗号分隔', `prob_rise` decimal(5,2) NOT NULL COMMENT '看涨%', `prob_flat` decimal(5,2) NOT NULL COMMENT '看平%', `prob_fall` decimal(5,2) NOT NULL COMMENT '看跌%', `outbound_advice` varchar(500) NOT NULL COMMENT '出栏建议', `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 '更新时间', PRIMARY KEY (`id`), KEY `idx_quote_date` (`quote_date`), KEY `idx_trade_market_id` (`trade_market_id`), KEY `idx_county_code` (`county_code`), KEY `idx_del_flag` (`del_flag`), KEY `idx_quote_dim` (`quote_date`,`county_code`,`trade_market_id`,`cattle_gender`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='日度市场行情'; ``` ### 2.3 枚举(存库 tinyint / 码串) **公母 `cattle_gender`** | 值 | 标签 | | --- | --- | | 1 | 公牛 | | 2 | 母牛 | | 3 | 公母混合 | **重量 `weight_grade`** | 值 | 标签 | | --- | --- | | 1 | 50斤以下 | | 2 | 50-100斤 | | 3 | 100-200斤 | | 4 | 200-300斤 | | 5 | 300-500斤 | | 6 | 500-800斤 | | 7 | 800斤以上 | **生长阶段 `growth_stage`** | 值 | 标签 | | --- | --- | | 1 | 犊牛 | | 2 | 架子牛 | | 3 | 屠宰牛 | **月龄 `age_month_grade`** | 值 | 标签 | | --- | --- | | 1 | 1月龄 | | 2 | 2-3月龄 | | 3 | 4-5月龄 | | 4 | 6-7月龄 | | 5 | 8-9月龄 | | 6 | 10-11月龄 | | 7 | 12月龄 | **膘情 `fat_grade`** | 值 | 标签 | | --- | --- | | 1 | 43% | | 2 | 45% | | 3 | 50% | | 4 | 53% | **单位 `price_unit`** | 值 | 标签 | | --- | --- | | 1 | 元/头 | | 2 | 元/斤 | **出栏情况 `supply_status`** | 值 | 标签 | | --- | --- | | 1 | 货源充足 | | 2 | 货源减少 | | 3 | 货源增多 | **变化因素 `change_factors`(多选,库存逗号分隔码)** | 码 | 标签 | | --- | --- | | 1 | 天气 | | 2 | 节日 | | 3 | 政策 | | 4 | 供大于求 | | 5 | 供不应求 | | 6 | 其他产地冲击 | | 7 | 产地抬价 | | 8 | 其他 | **删除标记 `del_flag`** | 值 | 含义 | | --- | --- | | 0 | 正常 | | 2 | 已逻辑删除 | ### 2.4 维度唯一(Service) 查重键:`quote_date` + `county_code` + `trade_market_id` + `cattle_gender` + `IFNULL(weight_grade,0)` + `IFNULL(growth_stage,0)` + `IFNULL(age_month_grade,0)` + `IFNULL(fat_grade,0)`,在 `del_flag=0` 且排除当前 `id`(修改时)下 `count>0` 则拒绝。 --- ## 3. 接口设计 **统一响应**:`AjaxResult` / `TableDataInfo`。 **权限标识**:`tradeMarket:marketQuote:list|query|add|edit|remove` **Base Path**:`/tradeMarket/marketQuote` | # | 说明 | Method | URI | 权限 | | --- | --- | --- | --- | --- | | 3.1 | 分页列表 | GET | `/tradeMarket/marketQuote/list` | `list` | | 3.2 | 详情 | GET | `/tradeMarket/marketQuote/{id}` | `query` | | 3.3 | 新增 | POST | `/tradeMarket/marketQuote` | `add` | | 3.4 | 修改 | PUT | `/tradeMarket/marketQuote` | `edit` | | 3.5 | 删除 | DELETE | `/tradeMarket/marketQuote/{ids}` | `remove` | | 3.6 | 渠道下拉 | GET | `/tradeMarket/marketQuote/tradeMarketOptions` | `list` 或 `add` | #### 3.1.1 列表 Query | 参数 | 类型 | 必填 | 说明 | | --- | --- | --- | --- | | `pageNum` / `pageSize` | int | N | 默认 `1` / `20` | | `quoteDate` | date | N | 单日精确 `quote_date = ?` | | `beginQuoteDate` / `endQuoteDate` | date | N | 区间(与 `quoteDate` 二选一或区间优先) | | `tradeMarketId` | long | N | 渠道精确 | | `countyCode` | string | N | 县编码精确(产地筛选) | **列表行扩展(驼峰)**:`tradeMarketName`、`cattleGenderName`、`weightGradeName` 等标签字段由 Service/字典填充;`changeFactorNames`(码转中文列表)。 **排序**:`quote_date DESC, create_time DESC, id DESC`。 #### 3.2.1 详情 `data` 含 **§2.1** 全部业务字段 + 上述 `*Name` 扩展 + 审计字段。 #### 3.3.1 新增 / 修改 Body(驼峰) | 字段 | 新增 | 修改 | 说明 | | --- | --- | --- | --- | | `id` | — | Y | 主键 | | `quoteDate` | Y | Y | `yyyy-MM-dd`;≤ 今天 | | `provinceCode` / `provinceName` | Y | Y | 省 | | `cityCode` / `cityName` | Y | Y | 市 | | `countyCode` / `countyName` | Y | Y | 县 | | `tradeMarketId` | Y | Y | 须存在且市场 `operate_status=1` | | `cattleGender` | Y | Y | 1/2/3;缺省 1 | | `weightGrade` | N | N | 1~7 或 null | | `growthStage` | N | N | 1~3 或 null | | `ageMonthGrade` | N | N | 1~7 或 null | | `fatGrade` | N | N | 1~4 或 null | | `priceMin` / `priceMax` | Y | Y | >0;min≤max | | `priceUnit` | Y | Y | 1/2;缺省 2 | | `avgPrice` | N | N | **可不传**;以服务端计算为准 | | `supplyStatus` | Y | Y | 1~3 | | `changeFactors` | Y | Y | 整型码数组 `[1,3,5]` 或逗号串,至少 1 项 | | `probRise` / `probFlat` / `probFall` | Y | Y | 合计 100(±0.01) | | `outboundAdvice` | Y | Y | 1~500 字 | #### 3.4 渠道下拉 `tradeMarketOptions` - 返回 `{ id, marketName }[]`:`biz_trade_market` 且 `del_flag=0`、`operate_status=1`,按 `market_name` 排序。 - 亦可前端直调 `/livestock/tradeMarket/list?operateStatus=1&pageSize=500`(需跨模块权限时由菜单统一授权)。 #### 3.5 服务端校验(`MarketDailyQuoteValidation`) | 项 | 规则 | | --- | --- | | 行情日期 | 非空;≤ 当前日期 | | 区划 | 省/市/县码、名齐全 | | 渠道 | `trade_market_id` 有效且正常 | | 枚举 | 各字段 ∈ **§2.3** | | 价格 | `price_min`≤`price_max`;`avg_price = (min+max)/2` 四舍五入 2 位 | | 变化因素 | 至少 1 个合法码;去重排序后入库逗号串 | | 概率 | `prob_rise+prob_flat+prob_fall` ∈ [99.99, 100.01] 或整数 100 | | 出栏建议 | trim 后 1~500 字 | | 维度唯一 | **§2.4** | | 删除 | `MarketDailyQuoteReferenceChecker.hasReference(id)` 为 false(本期可占位 `false`) | #### 3.6 Mapper 约定 - 条件均带 `del_flag='0'`。 - 日期:`quote_date BETWEEN #{beginQuoteDate} AND #{endQuoteDate}` 或 `quote_date = #{quoteDate}`。 - 列表 `LEFT JOIN biz_trade_market` 取 `market_name`(`del_flag=0`)。 - 逻辑删除:`UPDATE … SET del_flag='2' WHERE id=? AND del_flag='0'`。 --- ## 4. 菜单与权限(示例) | 类型 | 名称 | 权限标识 | | --- | --- | --- | | 菜单 | 市场行情登记 | `tradeMarket:marketQuote:list` | | 按钮 | 查询 | `tradeMarket:marketQuote:query` | | 按钮 | 新增 | `tradeMarket:marketQuote:add` | | 按钮 | 修改 | `tradeMarket:marketQuote:edit` | | 按钮 | 删除 | `tradeMarket:marketQuote:remove` | 组件路径:`tradeMarket/marketQuote/index`(「交易市场平台」目录下)。 --- ## 5. 模块对照 | 项 | 交易市场管理 | 市场行情登记(本模块) | | --- | --- | --- | | 表 | `biz_trade_market` | `biz_market_daily_quote` | | Base Path | `/livestock/tradeMarket` | `/tradeMarket/marketQuote` | | 关系 | 主档 | 外键 `trade_market_id` 引用主档 | --- ## 6. 交付清单 - [ ] `sql/biz_market_daily_quote.sql`、菜单权限 SQL - [ ] `BizMarketDailyQuote`、Mapper/XML、Service、Controller - [ ] `MarketDailyQuoteValidation`、均价与概率、维度唯一 - [ ] `tradeMarketOptions` 或文档化复用 livestock 列表 - [ ] 单元测试(均价、概率合计、查重、日期 SQL) - [ ] MockMvc(list 筛选、CRUD) --- ## 7. 修订记录 | 版本 | 说明 | | --- | --- | | 1.0 | 初稿:`biz_market_daily_quote`;`/tradeMarket/marketQuote`;关联 `biz_trade_market`;枚举与均价/概率规则 |