# 大屏 — 交易销售统计 — 测试用例

> 依据：`大屏交易销售功能需求.md`（v1.0）、`大屏交易销售技术方案.md`（v1.0）  
> **接口 Base Path**：`/bigScreen/tradeSales`（含 `context-path`、网关前缀须补齐）。鉴权：若依 Cookie / `Authorization` Token；权限 `bigScreen:tradeSales:query`。

**通用前置（无特殊说明）**：已执行 `sql/biz_trade_order.sql`、`sql/biz_supplier.sql`、`sql/biz_distributor.sql`、`sql/biz_market_daily_quote.sql`、`sql/biz_trade_market.sql`、`sql/biz_grade_weight_config.sql`；明细表已含 `grade_code`；测试账号具备大屏交易销售查询权限；时区 `Asia/Shanghai`。

**口径摘要**

| 域 | 规则 |
| --- | --- |
| 统计年 **Y** | 切换后交易类区块一致；默认当前自然年 |
| 统计日 | `Y`=当前年→今日；历史年→`Y-12-31` |
| 已完成订单 | `order_status=1`、`del_flag=0`；`finish_time` 在 **Y** 年内且 ≤ `statDate 23:59:59` |
| 待支付 | **不参与**任何统计 |
| 按月图表 | 固定 12 月；缺月、当前年未来月=**0** |
| 入驻商铺 | `biz_supplier` 有效条数；**不随 Y** |
| 产地行情 | `[statDate−6, statDate]` 共 7 日；默认市场「巴青牦牛交易市场」；**与 Y 无关** |
| 销售去向 | 承销商 `sales_destination` 1/2/3；汇总**头数** |
| 品质等级 | 已完成明细 `grade_code`；名称来自 `biz_grade_weight_config` |

**本期不测**：农资订单/销售额/品类/店铺/词云等（功能需求 **§3.2**）。

**UI 测试**：**Playwright** + **Chromium**，`playwright.config` 中 `use: { channel: 'chrome' }` 调用本机 **Google Chrome**。

**自动化对照（建议）**：`com.ruoyi.web.modules.screen.**.*TradeSales*`（JUnit5 / MockMvc / Playwright）。

---

## 测试数据样本

| 代号 | 说明 |
| --- | --- |
| **MKT-DEF** | `biz_trade_market` 存在 `market_name=巴青牦牛交易市场` 且 `del_flag=0` |
| **MKT-MISS** | 库内无配置名对应市场（测行情空态） |
| **SUP-SNAP** | 有效供应商 5 家（`del_flag=0`） |
| **ORD-Y** | **2026** 已完成订单：3 月 2 笔共 5 头/10 万、8 月 1 笔 3 头/6 万；`finish_time` 在对应月 |
| **ORD-PEND** | **2026** 待支付 1 笔（头数/金额更大） | 不应计入 |
| **ORD-EMPTY** | **2025** 无已完成订单 |
| **ORD-HIST** | **2024** 已完成 1 笔 2 头，与 2026 不同 |
| **DIST-MIX** | 承销商三档去向各至少 1 单已完成且头数已知（本市 10、本省 8、外省 5） |
| **QUOTE-7D** | 默认市场近 7 日：至少 2 个行情日、同日多维度（公母/重量档）各 1 条 |
| **QUOTE-EMPTY** | 近 7 日无登记 |
| **QUOTE-GAP** | 7 日内仅第 1、7 日有登记，中间 5 日无 |
| **GRADE-MIX** | 2026 已完成明细含 A/B 各若干头，`grade_code` 已填 |
| **GRADE-NULL** | 2026 有已完成订单但部分明细 `grade_code` 为空 |

---

## 一、单元测试用例

| 用例编号 | 测试模块 | 测试项 | 测试类型 | 测试工具 | 测试目的 | 前置条件 | 测试步骤 | 预期结果 |
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
| DP-JY-UT-001 | 参数校验 | statYear 合法 | 单元测试 | JUnit5 | 年份解析 | 无 | 传入 `2026`、`2000` | 解析为整数通过 |
| DP-JY-UT-002 | 参数校验 | statYear 非法 | 单元测试 | JUnit5 | 异常入参 | 无 | 空、`26`、`abcd`、`1899` | 抛 `ServiceException` 或等价失败 |
| DP-JY-UT-003 | 统计日 | 当前年 statDate | 单元测试 | JUnit5 | §2.2、SY-JY-01 | Mock 当前日 2026-05-20 | `resolveStatDate(2026)` | 返回 `2026-05-20` |
| DP-JY-UT-004 | 统计日 | 历史年 statDate | 单元测试 | JUnit5 | §2.2 | 无 | `resolveStatDate(2024)` | 返回 `2024-12-31` |
| DP-JY-UT-005 | 订单口径 | 排除待支付 | 单元测试 | JUnit5 | §2.5 | `ORD-Y`+`ORD-PEND` | `sumCompletedOrders(2026)` | 仅 `ORD-Y` 笔数/头数/金额 |
| DP-JY-UT-006 | 订单口径 | 当前年上界 | 单元测试 | JUnit5 | 技术§1 | 2026-05-20 完成 1 笔；05-21 完成 1 笔 | `loadTradeOverview(2026)` | 仅含 05-20 及之前完成单 |
| DP-JY-UT-007 | 按月趋势 | 12 条补零 | 单元测试 | JUnit5 | §2.3、SY-JY-05 | `ORD-Y` 仅 3、8 月 | `buildTradeMonthlyTrend(2026, statDate)` | `length=12`；非 3/8 月 `tradeHeads=tradeAmount=0` |
| DP-JY-UT-008 | 按月趋势 | 未来月为 0 | 单元测试 | JUnit5 | §2.3 | 当前年 statDate=5 月 | 检查 `month=6..12` | 均为 0 |
| DP-JY-UT-009 | 入驻商铺 | 切年不变 | 单元测试 | JUnit5 | §2.10、SY-JY-03 | 固定 `SUP-SNAP` | `loadDashboard(2025)` 与 `2026` | `supplierCount` 相同 |
| DP-JY-UT-010 | 销售去向 | 三档固定桶 | 单元测试 | JUnit5 | §2.8、SY-JY-06 | `DIST-MIX` | `buildSalesDestination` | 3 项；`sum(tradeHeads)`=当年总头数 |
| DP-JY-UT-011 | 销售去向 | 占比计算 | 单元测试 | JUnit5 | §2.11 | 三档 10/8/5 头 | `calcDestinationRatio` | 占比之和≈100（1 位小数） |
| DP-JY-UT-012 | 品质等级 | 四档固定返回 | 单元测试 | JUnit5 | 技术§2.4 | `GRADE-MIX`；配置表 4 档 | `buildQualityGrade` | `items.length=4`；`sum(ratio)≈100` |
| DP-JY-UT-013 | 品质等级 | 无 grade 空态 | 单元测试 | JUnit5 | §7.1 | `GRADE-NULL` 全空 | `buildQualityGrade` | `hasGradeData=false` |
| DP-JY-UT-014 | 行情聚合 | 同日多维度 | 单元测试 | JUnit5 | §2.7 | 同日 min 30/32、max 35/36、avg 31/33 | `aggregateDailyQuote` | 当日 min=30、max=36、avg=32 |
| DP-JY-UT-015 | 行情聚合 | 7 日卡片 | 单元测试 | JUnit5 | SY-JY-04 | `QUOTE-7D` 两日有均价 | `buildOriginQuoteSummary` | `avgPrice7d` 为两日当日均价算术平均 |
| DP-JY-UT-016 | 行情聚合 | 缺日走势图填 0 | 单元测试 | JUnit5 | §5.3.2 | `QUOTE-GAP` | `buildDailyTrend(statDate)` | `dailyTrend.length=7`；无登记日三价为 0 |
| DP-JY-UT-017 | 行情聚合 | 7 日卡片不含无登记日 | 单元测试 | JUnit5 | §2.7 | `QUOTE-GAP` | `avgPrice7d` 计算 | 仅对有登记日「当日均价」求平均（与折线缺日 0 区分） |
| DP-JY-UT-018 | 行情窗口 | 与 Y 无关 | 单元测试 | JUnit5 | SY-JY-02 | 固定 `QUOTE-7D` | `loadOriginQuote(2025)` 与 `2026` | `originQuote` 相同（同 statDate） |
| DP-JY-UT-019 | 默认市场 | 未配置市场 | 单元测试 | JUnit5 | 技术§2.2 | `MKT-MISS` | `resolveDefaultMarketId` | `hasQuoteData=false` |
| DP-JY-UT-020 | 可选年份 | 并集含当前年 | 单元测试 | JUnit5 | §2.1 | Mock 完成年 `[2025]`；当前 2026 | `buildAvailableYears` | 含 `2026`；降序 |
| DP-JY-UT-021 | 一致性 | 总览与趋势合计 | 单元测试 | JUnit5 | §6 | `ORD-Y` | 对比 `tradeOverview.tradeHeads` 与 `sum(monthly.tradeHeads)` | 一致（允许四舍五入） |
| DP-JY-UT-022 | 约束 | 只读无写 | 单元测试 | JUnit5 | §3.3、SY-JY-10 | 检查 Controller/Service | 无 insert/update/delete | 仅 `dashboard` 查询 |
| DP-JY-UT-023 | 约束 | 无农资字段 | 单元测试 | JUnit5 | §3.2、SY-JY-08 | 检查 VO/响应结构 | 无农资相关属性 | 仅牦牛五区块字段 |
| DP-JY-UT-024 | 缓存 | forceRefresh | 单元测试 | JUnit5 | 技术§2.3 | 启用缓存未过期 | `loadDashboard(2026,true)` | 跳过缓存重新聚合 |

---

## 二、接口测试用例

| 用例编号 | 测试模块 | 测试项 | 测试类型 | 测试工具 | 测试目的 | 前置条件 | 测试步骤 | 预期结果 |
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
| DP-JY-API-001 | 看板 | 满数据正常 | 接口测试 | Postman/curl | SY-JY-01 | 已登录；`ORD-Y`+`QUOTE-7D`+`GRADE-MIX` | `GET .../dashboard?statYear=2026` | `code` 成功；含 `tradeOverview`～`qualityGrade`；`statDate` 为今日 |
| DP-JY-API-002 | 看板 | 交易总览四项 | 接口测试 | Postman | SY-JY-03 | `ORD-Y`+`SUP-SNAP` | `GET dashboard` | `orderCount`/`tradeHeads`/`tradeAmount` 与 SQL 手工一致；`supplierCount=5` |
| DP-JY-API-003 | 看板 | 入驻商铺切年不变 | 接口测试 | Postman | §2.10 | `SUP-SNAP` 固定 | `statYear=2025` 与 `2026` | `supplierCount` 相同 |
| DP-JY-API-004 | 看板 | 排除待支付 | 接口测试 | Postman | §2.5 | `ORD-Y`+`ORD-PEND` | `GET dashboard` 2026 | 总览不含待支付笔数/头数/金额 |
| DP-JY-API-005 | 看板 | 历史年 statDate | 接口测试 | Postman | §2.2 | `ORD-HIST` | `statYear=2024` | `statDate=2024-12-31`；总览仅 2024 完成单 |
| DP-JY-API-006 | 看板 | 按月趋势 12 条 | 接口测试 | Postman | SY-JY-05 | `ORD-Y` | `GET dashboard` | `tradeMonthlyTrend.length=12`；3、8 月有值；未来月为 0 |
| DP-JY-API-007 | 看板 | 销售去向三档 | 接口测试 | Postman | SY-JY-06 | `DIST-MIX` | `GET dashboard` | `salesDestination.length=3`；`sum(tradeHeads)`=总览 `tradeHeads` |
| DP-JY-API-008 | 看板 | 品质占比 | 接口测试 | Postman | SY-JY-07 | `GRADE-MIX` | `GET dashboard` | `hasGradeData=true`；`sum(ratio)≈100`；含 `gradeName` |
| DP-JY-API-009 | 看板 | 产地行情 7 日 | 接口测试 | Postman | SY-JY-04 | `QUOTE-7D`+`MKT-DEF` | `GET dashboard` | `hasQuoteData=true`；`dailyTrend.length=7`；含三价字段 |
| DP-JY-API-010 | 看板 | 行情与 Y 无关 | 接口测试 | Postman | SY-JY-02 | 固定 `QUOTE-7D` | `statYear=2025` 与 `2026` | `originQuote` 一致（同日请求） |
| DP-JY-API-011 | 看板 | 无订单空态 | 接口测试 | Postman | §7.1 | `ORD-EMPTY` 2025 | `GET dashboard` | 总览前三项 0；趋势 12 月全 0 或空态标记；去向三档 0 |
| DP-JY-API-012 | 看板 | 无行情空态 | 接口测试 | Postman | §7.1 | `QUOTE-EMPTY` 或 `MKT-MISS` | `GET dashboard` | `hasQuoteData=false`；`lastQuoteDate` 为 null |
| DP-JY-API-013 | 看板 | 无品质空态 | 接口测试 | Postman | §7.1 | `GRADE-NULL` | `GET dashboard` | `hasGradeData=false` |
| DP-JY-API-014 | 看板 | 缺 statYear | 接口测试 | Postman | 异常 | 已登录 | 不传 `statYear` | 失败或默认当前年（与实现一致并文档统一） |
| DP-JY-API-015 | 看板 | 非法 statYear | 接口测试 | Postman | 异常 | 已登录 | `statYear=abc` | 失败；`msg` 参数错误 |
| DP-JY-API-016 | 看板 | statYear 回显 | 接口测试 | Postman | 一致性 | 已登录 | `statYear=2025` | `data.statYear=2025` |
| DP-JY-API-017 | 看板 | availableYears | 接口测试 | Postman | §2.1 | 完成订单年 2025、2026 | `GET dashboard` | 含各年+当前年；降序 |
| DP-JY-API-018 | 看板 | 切年不串 | 接口测试 | Postman | SY-JY-02 | `ORD-HIST` 与 `ORD-Y` | 分别 `2024`、`2026` | 总览/趋势/去向/品质互不混入 |
| DP-JY-API-019 | 看板 | forceRefresh | 接口测试 | Postman | 技术§2.3 | 已启用缓存 | `?statYear=2026&forceRefresh=true` | 成功；与库最新一致 |
| DP-JY-API-020 | 范围 | 无维护接口 | 接口测试 | Postman | §3.3、SY-JY-10 | 已登录 | `POST/PUT/DELETE .../bigScreen/tradeSales/**` | 404/405 或无权限 |
| DP-JY-API-021 | 范围 | 无农资接口 | 接口测试 | Postman | §3.2、SY-JY-08 | 已登录 | 探测农资路径 | 无大屏农资统计接口 |
| DP-JY-API-022 | 联动 | 完成支付后 | 接口测试 | Postman | SY-JY-09 | 2026 原 `ORD-EMPTY` | 后台完成 1 笔支付→`GET dashboard` | `orderCount` 等增加 |
| DP-JY-API-023 | 联动 | 登记行情后 | 接口测试 | Postman | SY-JY-09 | `QUOTE-EMPTY` | 后台登记默认市场日行情→刷新 | `hasQuoteData=true` |
| DP-JY-API-024 | 鉴权 | 未登录 | 接口测试 | curl | 安全 | 无 Token | `GET dashboard` | 401 或统一未登录 |
| DP-JY-API-025 | 权限 | 无大屏权限 | 接口测试 | Postman | 越权 | 无 `bigScreen:tradeSales:query` | `GET dashboard` | 403 或无权限 |
| DP-JY-API-026 | 约束 | 价格单位 | 接口测试 | Postman | §2.11 | `QUOTE-7D` 含元/斤 | `GET dashboard` | `priceUnit`、`priceUnitLabel` 有值且与登记一致 |
| DP-JY-API-027 | 约束 | ratio 为百分数值 | 接口测试 | Postman | 技术§3.1.4 | 有去向/品质数据 | 检查 `ratio` 字段 | 为 0～100 数值（非 0～1） |

---

## 三、界面测试用例（UI）

| 用例编号 | 测试模块 | 测试项 | 测试类型 | 测试工具 | 测试目的 | 前置条件 | 测试步骤 | 预期结果 |
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
| DP-JY-UI-001 | 页面 | 默认当前年加载 | UI 测试 | Playwright+Chrome | SY-JY-01 | 已登录有权限；2026 有样本 | 打开「大屏交易销售」路由 | 年份为当前自然年；请求 `dashboard`；五区块同年 |
| DP-JY-UI-002 | 筛选 | 切换年份整页刷新 | UI 测试 | Playwright+Chrome | SY-JY-02 | 含 2025、2026 数据 | 年份 2025→2026 | 总览/趋势/去向/品质同步更新；**产地行情**仍按当日 7 日 |
| DP-JY-UI-003 | 筛选 | 加载中防残留 | UI 测试 | Playwright+Chrome | §7.2 | 已登录 | 切年（可 `route.fulfill` 延迟） | Loading/遮罩；完成后无上年残留 |
| DP-JY-UI-004 | 交易总览 | 四卡与单位 | UI 测试 | Playwright+Chrome | §5.2、SY-JY-03 | `ORD-Y`+`SUP-SNAP` | 查看交易总览区 | 订单数(单)/交易量(头)/交易额(元)/入驻商铺(家)正确 |
| DP-JY-UI-005 | 交易总览 | 入驻商铺切年不变 | UI 测试 | Playwright+Chrome | §2.10 | `SUP-SNAP` 固定 | 2025→2026 | 第四卡数值不变（未改主数据前提下） |
| DP-JY-UI-006 | 产地行情 | 7 日指标卡 | UI 测试 | Playwright+Chrome | SY-JY-04 | `QUOTE-7D` | 查看行情指标区 | 7 日均价/最低/最高、最近行情日期；标注元/头或元/斤 |
| DP-JY-UI-007 | 产地行情 | 三曲线 7 日 | UI 测试 | Playwright+Chrome | SY-JY-04 | `QUOTE-7D` | 查看走势图+悬停 | 7 个横轴刻度；最低/最高/均价三图例；悬停显示三价 |
| DP-JY-UI-008 | 图表 | 数额趋势双系列 12 月 | UI 测试 | Playwright+Chrome | SY-JY-05 | `ORD-Y` | 查看趋势图+悬停 | 12 月；销售量(头)+销售额(元)；3、8 月有值 |
| DP-JY-UI-009 | 图表 | 销售去向饼图 | UI 测试 | Playwright+Chrome | SY-JY-06 | `DIST-MIX` | 查看销售去向 | 本市/本省/外省三档；头数与占比 |
| DP-JY-UI-010 | 图表 | 品质等级饼图 | UI 测试 | Playwright+Chrome | SY-JY-07 | `GRADE-MIX` | 查看品质占比 | 一级/二级等中文标签；占比之和 100% |
| DP-JY-UI-011 | 空态 | 无订单 | UI 测试 | Playwright+Chrome | §7.1 | `ORD-EMPTY` 年 | 切换该年 | 总览前三项 0；趋势空态或全 0；去向/品质空态 |
| DP-JY-UI-012 | 空态 | 无行情 | UI 测试 | Playwright+Chrome | §7.1 | `QUOTE-EMPTY` | 进入页 | 行情指标「—」或 0；走势图空态 |
| DP-JY-UI-013 | 空态 | 无品质 | UI 测试 | Playwright+Chrome | §7.1 | `GRADE-NULL` | 切换 2026 | 品质区块空态；其余正常 |
| DP-JY-UI-014 | 范围 | 无农资占位 | UI 测试 | Playwright+Chrome | SY-JY-08、§3.2 | 已登录 | 扫描全页文案与卡片 | **无**农资订单/销售额/品类/店铺/词云等区域 |
| DP-JY-UI-015 | 只读 | 无维护按钮 | UI 测试 | Playwright+Chrome | SY-JY-10、§3.3 | 已登录 | 扫描全页 | 无新增订单/登记行情/支付/结算按钮；可有刷新 |
| DP-JY-UI-016 | 错误 | 接口失败重试 | UI 测试 | Playwright+Chrome | §7.2 | Mock `dashboard` 500 | 进入或切年 | 失败提示+重试；不长期显示旧年数据 |
| DP-JY-UI-017 | 联动 | 后台支付后刷新 | UI 集成 | Playwright+Chrome | SY-JY-09 | 2026 原无完成单 | 后台完成支付→F5 或刷新 | 总览与趋势更新 |
| DP-JY-UI-018 | 联动 | 后台行情后刷新 | UI 集成 | Playwright+Chrome | SY-JY-09 | 原无 7 日行情 | 后台登记→刷新 | 行情区出现数据 |
| DP-JY-UI-019 | 权限 | 无菜单不可进 | UI 测试 | Playwright+Chrome | 安全 | 无大屏菜单账号 | 登录查侧栏/直链 | 无入口或 403 |
| DP-JY-UI-020 | 端到端 | 按年查阅全流程 | UI 集成 | Playwright+Chrome | §4、SY-JY-01～10 | 2026 完整样本 | 登录→进页→默认年→切年→悬停各图 | 五区块正确；无控制台报错 |
| DP-JY-UI-021 | 刷新 | 手动刷新 | UI 测试 | Playwright+Chrome | §7.3 | 已打开；后台改数据 | 点刷新 | 重新请求 `dashboard`；数据更新 |

---

## Playwright 实施提示

```javascript
// playwright.config.ts 片段
use: { channel: 'chrome', headless: false }

// 登录后进入交易销售大屏（路由以实际为准）
await page.goto('/#/bigScreen/tradeSales/index');

// 切年：监听 dashboard
await Promise.all([
  page.waitForResponse('**/bigScreen/tradeSales/dashboard**'),
  page.getByRole('combobox', { name: /统计年份|年份/ }).selectOption('2026'),
]);

// 交易总览卡片（文案以原型为准）
await expect(page.getByText(/牦牛交易订单数/)).toBeVisible();
await expect(page.getByText(/入驻商铺/)).toBeVisible();

// 确认无农资占位（SY-JY-08）
await expect(page.getByText(/农资订单|农资销售|热销农资|消费区域排名|评价词云/)).toHaveCount(0);

// 悬停趋势图（选择器按 ECharts 容器调整）
await page.locator('.trade-monthly-chart').hover();

// 接口失败（UI-016）
await page.route('**/bigScreen/tradeSales/dashboard**', route =>
  route.fulfill({ status: 500, body: '{}' })
);
```

---

## 覆盖对照

| 类别 | 单元 UT | 接口 API | 界面 UI |
| --- | --- | --- | --- |
| 正常流程 | UT-003～008、010～012、014～016、021 | API-001～010、022～023 | UI-001～010、017～018、020～021 |
| 异常流程 | UT-002、013、019 | API-011～015、024～025 | UI-011～013、016、019 |
| 业务约束 | UT-005～006、009、011、017～018、020～023 | API-003～004、007～008、018、026～027 | UI-004～005、014～015、020 |

---

## 功能需求追溯（SY-JY / 章节）

| 追溯 | 要点 | 主要用例 |
| --- | --- | --- |
| SY-JY-01 | 默认当前年 | UI-001；API-001 |
| SY-JY-02 | 切年；行情不按 Y | UT-018；API-010、018；UI-002 |
| SY-JY-03 | 交易总览+商铺不随 Y | UT-009；API-002～003；UI-004～005 |
| SY-JY-04 | 产地行情 7 日 | UT-014～017；API-009；UI-006～007 |
| SY-JY-05 | 按月双系列 12 月 | UT-007～008；API-006；UI-008 |
| SY-JY-06 | 销售去向三档 | UT-010～011；API-007；UI-009 |
| SY-JY-07 | 品质占比 | UT-012～013；API-008；UI-010 |
| SY-JY-08 | 无农资 | UT-023；API-021；UI-014 |
| SY-JY-09 | 后台刷新 | API-022～023；UI-017～018、021 |
| SY-JY-10 | 只读 | UT-022；API-020；UI-015 |
| §2.5 | 仅已完成 | UT-005；API-004 |
| §2.10 | 供应商快照 | UT-009；API-003 |
| §7.1 | 空态 | UT-013；API-011～013；UI-011～013 |
| §7.2 | 加载失败 | UI-003、016 |

---

## 修订记录

| 版本 | 说明 |
| --- | --- |
| 1.0 | 初版：单元 24、接口 27、UI 21；覆盖 SY-JY-01～10 与正常/异常/约束；不含农资；Playwright+Chrome；Base `/bigScreen/tradeSales` |
