Files
ccdi/docs/plans/frontend/2026-03-27-development-risk-suspicious-transaction-detail-frontend-implementation.md

9.6 KiB
Raw Blame History

开发风险明细涉疑交易明细前端 Implementation Plan

For agentic workers: REQUIRED: Use superpowers:subagent-driven-development (if subagents available) or superpowers:executing-plans to implement this plan. Steps use checkbox (- [ ]) syntax for tracking.

Repo note: 本仓库 AGENTS.md 明确禁止开启 subagent执行本计划时请在当前会话使用 superpowers:executing-plans

Goal: 在结果总览页的“风险明细”区块内实现真实“涉疑交易明细”表格,支持来源切换、导出和查看详情,并保持表格与流水详情样式和“流水明细查询”页面一致。

Architecture: 前端继续以 PreliminaryCheck.vue 作为结果总览入口,通过 projectOverview.js 新增结果总览涉疑交易接口封装,在父组件加载后将数据注入 RiskDetailSection.vueRiskDetailSection.vue 负责呈现筛选下拉、真实业务列、详情弹窗与导出按钮;详情接口直接复用 ccdiProjectBankStatement.js 中已有的 getBankStatementDetail

Tech Stack: Vue 2, Element UI, RuoYi 全局 download, Node assert 单测, axios request 封装


Task 1: 新增结果总览涉疑交易前端 API 契约

Files:

  • Modify: ruoyi-ui/src/api/ccdi/projectOverview.js

  • Test: ruoyi-ui/tests/unit/project-overview-api.test.js

  • Step 1: 先补 API 契约测试,锁定新接口名和参数透传

[
  "getOverviewSuspiciousTransactions",
  "/ccdi/project/overview/suspicious-transactions",
  "projectId: params.projectId",
  "suspiciousType: params.suspiciousType",
  "pageNum: params.pageNum",
  "pageSize: params.pageSize",
].forEach((token) => assert(source.includes(token), token));
  • Step 2: 运行测试,确认新接口尚未接入

Run:

node ruoyi-ui/tests/unit/project-overview-api.test.js

Expected: FAIL提示缺少 getOverviewSuspiciousTransactions

  • Step 3: 写最小 API 封装
export function getOverviewSuspiciousTransactions(params) {
  return request({
    url: "/ccdi/project/overview/suspicious-transactions",
    method: "get",
    params: {
      projectId: params.projectId,
      suspiciousType: params.suspiciousType,
      pageNum: params.pageNum,
      pageSize: params.pageSize,
    },
  });
}
  • Step 4: 回跑 API 契约测试

Run:

node ruoyi-ui/tests/unit/project-overview-api.test.js

Expected: PASS

  • Step 5: 提交本任务
git add ruoyi-ui/src/api/ccdi/projectOverview.js \
  ruoyi-ui/tests/unit/project-overview-api.test.js
git commit -m "新增结果总览涉疑交易前端接口"

Task 2: 把结果总览父组件接到真实涉疑交易数据

Files:

  • Modify: ruoyi-ui/src/views/ccdiProject/components/detail/PreliminaryCheck.vue

  • Modify: ruoyi-ui/src/views/ccdiProject/components/detail/preliminaryCheck.mock.js

  • Test: ruoyi-ui/tests/unit/preliminary-check-model-and-detail.test.js

  • Create: ruoyi-ui/tests/unit/preliminary-check-suspicious-transaction-load.test.js

  • Step 1: 先写失败测试,锁定父组件加载新接口和风险明细数据结构

assert(source.includes("getOverviewSuspiciousTransactions"), "结果总览应加载涉疑交易接口");
assert(source.includes("riskDetails"), "结果总览应继续向 RiskDetailSection 注入 riskDetails");
assert(source.includes("suspiciousTransactionList"), "mock 归一化应保留涉疑交易列表");
  • Step 2: 运行测试,确认当前仍是 mock 空数组

Run:

node ruoyi-ui/tests/unit/preliminary-check-model-and-detail.test.js
node ruoyi-ui/tests/unit/preliminary-check-suspicious-transaction-load.test.js

Expected:

  • 旧测试仍只认“涉险交易明细”

  • 新测试提示未加载涉疑交易接口

  • Step 3: 在父组件中并行加载涉疑交易接口,并改造 mock 归一化函数

const [dashboardRes, riskPeopleRes, riskModelCardsRes, suspiciousRes] = await Promise.all([
  getOverviewDashboard(this.projectId),
  getOverviewRiskPeople(this.projectId),
  getOverviewRiskModelCards(this.projectId),
  getOverviewSuspiciousTransactions({
    projectId: this.projectId,
    suspiciousType: "ALL",
    pageNum: 1,
    pageSize: 10,
  }),
]);
riskDetails: {
  suspiciousTransactionList: normalizeSuspiciousTransactions(suspiciousData && suspiciousData.rows),
  suspiciousType: "ALL",
  total: suspiciousData && suspiciousData.total ? suspiciousData.total : 0,
  abnormalAccountList: [],
}
  • Step 4: 回跑父组件相关测试

Run:

node ruoyi-ui/tests/unit/preliminary-check-model-and-detail.test.js
node ruoyi-ui/tests/unit/preliminary-check-suspicious-transaction-load.test.js

Expected: PASS

  • Step 5: 提交本任务
git add ruoyi-ui/src/views/ccdiProject/components/detail/PreliminaryCheck.vue \
  ruoyi-ui/src/views/ccdiProject/components/detail/preliminaryCheck.mock.js \
  ruoyi-ui/tests/unit/preliminary-check-model-and-detail.test.js \
  ruoyi-ui/tests/unit/preliminary-check-suspicious-transaction-load.test.js
git commit -m "接通结果总览涉疑交易数据加载"

Task 3: 重写 RiskDetailSection 的涉疑交易表格列和筛选交互

Files:

  • Modify: ruoyi-ui/src/views/ccdiProject/components/detail/RiskDetailSection.vue

  • Test: ruoyi-ui/tests/unit/preliminary-check-model-and-detail.test.js

  • Create: ruoyi-ui/tests/unit/risk-detail-suspicious-transaction-layout.test.js

  • Step 1: 先写失败测试,锁定下拉项、业务列和新标题

[
  "涉疑交易明细",
  "全部可疑人员类型",
  "名单库命中",
  "模型规则命中",
  "可疑人员",
  "关联人",
  "关联员工",
  "关系",
  "摘要/交易类型",
].forEach((token) => assert(source.includes(token), token));
  • Step 2: 运行测试,确认当前仍是旧占位表格

Run:

node ruoyi-ui/tests/unit/preliminary-check-model-and-detail.test.js
node ruoyi-ui/tests/unit/risk-detail-suspicious-transaction-layout.test.js

Expected: FAIL提示仍存在“涉险交易明细 / 对手方 / 方向 / 账号”

  • Step 3: 写最小 UI 改造
<el-dropdown @command="handleSuspiciousTypeChange">
  <span class="el-dropdown-link">{{ currentSuspiciousTypeLabel }}</span>
</el-dropdown>

<el-table-column prop="trxDate" label="交易时间" />
<el-table-column prop="suspiciousPersonName" label="可疑人员" />
<el-table-column prop="relatedPersonName" label="关联人" />
<el-table-column label="关联员工">
  <template slot-scope="scope">{{ formatRelatedStaff(scope.row) }}</template>
</el-table-column>
  • Step 4: 回跑布局测试

Run:

node ruoyi-ui/tests/unit/preliminary-check-model-and-detail.test.js
node ruoyi-ui/tests/unit/risk-detail-suspicious-transaction-layout.test.js

Expected: PASS

  • Step 5: 提交本任务
git add ruoyi-ui/src/views/ccdiProject/components/detail/RiskDetailSection.vue \
  ruoyi-ui/tests/unit/preliminary-check-model-and-detail.test.js \
  ruoyi-ui/tests/unit/risk-detail-suspicious-transaction-layout.test.js
git commit -m "改造结果总览涉疑交易表格结构"

Task 4: 复用流水详情弹窗与导出能力,并做前端回归

Files:

  • Modify: ruoyi-ui/src/views/ccdiProject/components/detail/RiskDetailSection.vue

  • Modify: ruoyi-ui/src/api/ccdi/projectOverview.js

  • Reuse: ruoyi-ui/src/api/ccdiProjectBankStatement.js

  • Test: ruoyi-ui/tests/unit/risk-detail-suspicious-transaction-layout.test.js

  • Create: ruoyi-ui/tests/unit/risk-detail-suspicious-transaction-detail-dialog.test.js

  • Step 1: 先写失败测试,锁定详情复用与导出路径

[
  "getBankStatementDetail",
  "detailVisible",
  "handleViewDetail",
  "this.download(",
  "ccdi/project/overview/suspicious-transactions/export",
].forEach((token) => assert(source.includes(token), token));
  • Step 2: 运行测试,确认详情与导出还未接通

Run:

node ruoyi-ui/tests/unit/risk-detail-suspicious-transaction-layout.test.js
node ruoyi-ui/tests/unit/risk-detail-suspicious-transaction-detail-dialog.test.js

Expected: FAIL提示未复用 getBankStatementDetail 或未指向新导出路径

  • Step 3: 在 RiskDetailSection 中复用 DetailQuery 的详情弹窗结构和金额/标签格式化
import { getBankStatementDetail } from "@/api/ccdiProjectBankStatement";

async handleViewDetail(row) {
  const response = await getBankStatementDetail(row.bankStatementId);
  this.detailData = normalizeDetailData(response.data);
  this.detailVisible = true;
}

handleExport() {
  this.download(
    "ccdi/project/overview/suspicious-transactions/export",
    { projectId: this.projectId, suspiciousType: this.currentSuspiciousType },
    `涉疑交易明细_${new Date().getTime()}.xlsx`
  );
}
  • Step 4: 跑前端回归检查

Run:

node ruoyi-ui/tests/unit/project-overview-api.test.js
node ruoyi-ui/tests/unit/preliminary-check-model-and-detail.test.js
node ruoyi-ui/tests/unit/preliminary-check-suspicious-transaction-load.test.js
node ruoyi-ui/tests/unit/risk-detail-suspicious-transaction-layout.test.js
node ruoyi-ui/tests/unit/risk-detail-suspicious-transaction-detail-dialog.test.js
cd ruoyi-ui && npm run build:prod

Expected:

  • 所有 Node 断言测试 PASS

  • npm run build:prod 成功产出构建结果

  • Step 5: 提交本任务

git add ruoyi-ui/src/views/ccdiProject/components/detail/RiskDetailSection.vue \
  ruoyi-ui/src/api/ccdi/projectOverview.js \
  ruoyi-ui/tests/unit/risk-detail-suspicious-transaction-layout.test.js \
  ruoyi-ui/tests/unit/risk-detail-suspicious-transaction-detail-dialog.test.js
git commit -m "接通结果总览涉疑交易详情与导出"