# Plan: 商户端看板 — 商户筛选下拉框 ## Context 商户看板需要支持筛选:全部 / 本商户 / 各子商户,默认"全部"(本商户+子商户),今日数据和近30天数据两张卡片同步联动。 ## 实现策略 现有查询通过 `merchant_id IN (SELECT id FROM merchant WHERE id = #{tenantId} OR parent_merchant_id = #{tenantId})` 实现租户级聚合。在此之上叠加一个 `scopeId` 参数:当非空时追加 `AND merchant_id = #{scopeId}`,精确过滤到指定商户。 - `scopeId = null` → 全部(当前行为不变) - `scopeId = loggedInMerchantId` → 仅本商户自己的交易 - `scopeId = subMerchantId` → 仅该子商户 ## 改动清单 ### 1. MerchantMapper — 新增子商户查询 - `selectSubMerchants(@Param("merchantId") Long merchantId)` 返回 `List>` - XML: `SELECT id, merchant_name AS merchantName FROM merchant WHERE parent_merchant_id = #{merchantId} AND status = 1 ORDER BY id` ### 2. TransactionMapper — 6 个方法增加 scopeId 参数 - `getTenantTodayStats` — 加 `@Param("scopeId") Long scopeId` - `getTenantTodayRefundStats` — 同上 - `getTenantTodayDisputeCount` — 同上 - `getTransactionTrend` — 同上 - `getPaymentMethodDistribution` — 同上 - `getStatusDistribution` — 同上 ### 3. TransactionMapper.xml — 6 个查询增加 scopeId 条件 每个查询在 tenantId 条件之后追加: ```xml AND merchant_id = #{scopeId} ``` ### 4. MerchantDashboardController — 3 处变更 - 新增 `@GetMapping("/merchants")` 返回子商户列表供下拉框 - `/today` 端点:`merchantId` → `resolvedId`(根据 scopeId 决定),所有 mapper 调用传入 `scopeId` - `/transaction-trend`、`/payment-method-distribution`、`/status-distribution` 各加 `@RequestParam(required = false) Long scopeId` ### 5. 前端 dashboard.js — API 全部加 scopeId 参数 - `getSubMerchants()` 新增 - `getTransactionTrend(params)` — 已有 params,传 scopeId - `getPaymentMethodDistribution(params)` — 加 params - `getStatusDistribution(params)` — 加 params - `getTodayStats(params)` — 加 params ### 6. DashboardView.vue — 顶部加下拉框 - `el-select` 三个 option:全部、本商户、各子商户 - selectedMerchantId 响应式变量,默认 null(全部) - `watch` 监听变化,重新 fetch 全部数据 - 今日和近30天卡片都使用同一个 selectedMerchantId ## 不涉及 - admin 看板 - 非看板相关的 merchant 接口 ## 验证 1. 下拉默认"全部",数据与改造前一致 2. 选"本商户",两个卡片数据更新为仅该商户 3. 选子商户,两个卡片数据更新为仅该子商户 4. 下拉切换后两个区域同步刷新