Files
ccdi/docs/prototypes/external-risk-overview-prototype.html

913 lines
25 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>结果总览 - 外部人员预警原型</title>
<style>
:root {
--bg: #f5f7fa;
--panel: #ffffff;
--line: #dcdfe6;
--line-soft: #ebeef5;
--text: #303133;
--sub: #606266;
--muted: #909399;
--primary: #2f6fed;
--primary-soft: #eaf1ff;
--danger: #d93026;
--danger-soft: #fdecea;
--warning: #b56a00;
--warning-soft: #fff4df;
--success: #1f7a45;
--success-soft: #e8f5ee;
--orange: #c75c00;
--orange-soft: #fff0e3;
--shadow: 0 8px 22px rgba(31, 45, 61, 0.08);
}
* {
box-sizing: border-box;
}
body {
margin: 0;
color: var(--text);
background: var(--bg);
font-family: "Microsoft YaHei", "PingFang SC", Arial, sans-serif;
font-size: 14px;
letter-spacing: 0;
}
button,
input,
select {
font: inherit;
}
.page {
min-height: 100vh;
padding: 18px 24px 28px;
}
.topbar {
display: flex;
align-items: center;
justify-content: space-between;
gap: 16px;
margin-bottom: 14px;
}
.breadcrumbs {
color: var(--muted);
font-size: 13px;
margin-bottom: 6px;
}
h1 {
margin: 0;
font-size: 22px;
line-height: 1.3;
font-weight: 650;
letter-spacing: 0;
}
.project-meta {
display: flex;
flex-wrap: wrap;
gap: 10px 16px;
margin-top: 8px;
color: var(--sub);
font-size: 13px;
}
.toolbar {
display: flex;
align-items: center;
gap: 10px;
flex-wrap: wrap;
justify-content: flex-end;
}
.btn {
height: 34px;
border: 1px solid var(--line);
border-radius: 4px;
padding: 0 12px;
background: var(--panel);
color: var(--text);
cursor: pointer;
}
.btn.primary {
border-color: var(--primary);
background: var(--primary);
color: #fff;
}
.btn.ghost {
color: var(--primary);
border-color: #b8cdfd;
background: #fff;
}
.overview {
display: grid;
grid-template-columns: repeat(6, minmax(0, 1fr));
gap: 12px;
margin-bottom: 14px;
}
.metric {
min-height: 86px;
padding: 14px;
background: var(--panel);
border: 1px solid var(--line-soft);
border-radius: 6px;
box-shadow: var(--shadow);
}
.metric-title {
color: var(--sub);
font-size: 13px;
margin-bottom: 10px;
white-space: nowrap;
}
.metric-value {
font-size: 26px;
line-height: 1;
font-weight: 700;
margin-bottom: 8px;
}
.metric-note {
color: var(--muted);
font-size: 12px;
white-space: nowrap;
}
.metric.danger .metric-value {
color: var(--danger);
}
.metric.warning .metric-value {
color: var(--warning);
}
.metric.primary .metric-value {
color: var(--primary);
}
.grid {
display: grid;
grid-template-columns: minmax(0, 1fr) 360px;
gap: 14px;
align-items: start;
}
.section {
background: var(--panel);
border: 1px solid var(--line-soft);
border-radius: 6px;
box-shadow: var(--shadow);
margin-bottom: 14px;
overflow: hidden;
}
.section-head {
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
padding: 14px 16px;
border-bottom: 1px solid var(--line-soft);
}
.section-title {
font-size: 16px;
font-weight: 650;
}
.section-body {
padding: 14px 16px 16px;
}
.segmented {
display: inline-grid;
grid-template-columns: repeat(2, minmax(112px, 1fr));
height: 34px;
border: 1px solid var(--line);
border-radius: 4px;
overflow: hidden;
background: #f8f9fb;
}
.segmented button {
border: 0;
border-right: 1px solid var(--line);
background: transparent;
color: var(--sub);
cursor: pointer;
padding: 0 12px;
}
.segmented button:last-child {
border-right: 0;
}
.segmented button.active {
background: var(--primary);
color: #fff;
}
.filters {
display: flex;
gap: 10px;
flex-wrap: wrap;
align-items: center;
margin-bottom: 12px;
}
.field {
height: 34px;
min-width: 148px;
border: 1px solid var(--line);
border-radius: 4px;
padding: 0 10px;
background: #fff;
color: var(--text);
}
.field.search {
min-width: 220px;
flex: 1;
}
table {
width: 100%;
border-collapse: collapse;
table-layout: fixed;
}
th {
height: 40px;
background: #f5f7fa;
color: var(--sub);
font-weight: 600;
border-bottom: 1px solid var(--line);
text-align: left;
padding: 0 10px;
white-space: nowrap;
}
td {
height: 48px;
border-bottom: 1px solid var(--line-soft);
padding: 8px 10px;
vertical-align: middle;
color: var(--text);
word-break: break-word;
}
tr.selected {
background: #f4f8ff;
}
tr:hover {
background: #f8fbff;
}
.col-name {
width: 15%;
}
.col-type {
width: 12%;
}
.col-cert {
width: 20%;
}
.col-level {
width: 10%;
}
.col-count {
width: 10%;
}
.col-risk {
width: 24%;
}
.col-action {
width: 9%;
text-align: right;
}
.link {
border: 0;
background: transparent;
color: var(--primary);
cursor: pointer;
padding: 0;
}
.tag {
display: inline-flex;
align-items: center;
min-height: 24px;
padding: 0 8px;
border-radius: 3px;
font-size: 12px;
line-height: 1.2;
white-space: nowrap;
border: 1px solid transparent;
}
.tag + .tag {
margin-left: 6px;
}
.tag.danger {
color: var(--danger);
background: var(--danger-soft);
border-color: #f5c7c3;
}
.tag.warning {
color: var(--warning);
background: var(--warning-soft);
border-color: #ffd994;
}
.tag.primary {
color: var(--primary);
background: var(--primary-soft);
border-color: #c7d8ff;
}
.tag.success {
color: var(--success);
background: var(--success-soft);
border-color: #b7e0c9;
}
.tag.orange {
color: var(--orange);
background: var(--orange-soft);
border-color: #ffd0a8;
}
.tags {
display: flex;
flex-wrap: wrap;
gap: 6px;
}
.tags .tag {
margin: 0;
}
.models {
display: grid;
grid-template-columns: repeat(4, minmax(0, 1fr));
gap: 10px;
}
.model-item {
min-height: 92px;
border: 1px solid var(--line-soft);
border-radius: 6px;
padding: 12px;
background: #fbfcff;
}
.model-name {
color: var(--sub);
font-size: 13px;
margin-bottom: 10px;
}
.model-count {
font-size: 24px;
line-height: 1;
font-weight: 700;
margin-bottom: 8px;
}
.model-foot {
color: var(--muted);
font-size: 12px;
}
.side-panel {
position: sticky;
top: 14px;
}
.identity {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 10px;
margin-bottom: 14px;
}
.kv {
min-height: 58px;
border: 1px solid var(--line-soft);
border-radius: 5px;
padding: 9px 10px;
background: #fbfcff;
}
.kv-label {
color: var(--muted);
font-size: 12px;
margin-bottom: 6px;
white-space: nowrap;
}
.kv-value {
color: var(--text);
font-size: 14px;
font-weight: 600;
word-break: break-word;
}
.detail-title {
font-weight: 650;
margin: 18px 0 10px;
}
.mini-table th {
height: 34px;
font-size: 12px;
padding: 0 8px;
}
.mini-table td {
height: 42px;
font-size: 12px;
padding: 7px 8px;
}
.risk-text {
color: var(--sub);
line-height: 1.55;
}
.empty-graph {
height: 126px;
border: 1px dashed #c9cdd4;
border-radius: 6px;
display: flex;
align-items: center;
justify-content: center;
color: var(--muted);
background: #fafbfc;
}
.detail-table .col-date {
width: 13%;
}
.detail-table .col-subject {
width: 12%;
}
.detail-table .col-party {
width: 16%;
}
.detail-table .col-labels {
width: 27%;
}
.detail-table .col-amount {
width: 12%;
text-align: right;
}
.amount {
text-align: right;
font-variant-numeric: tabular-nums;
white-space: nowrap;
}
.footer-note {
color: var(--muted);
font-size: 12px;
padding: 0 2px;
}
@media (max-width: 1280px) {
.overview {
grid-template-columns: repeat(3, minmax(0, 1fr));
}
.grid {
grid-template-columns: 1fr;
}
.side-panel {
position: static;
}
}
@media (max-width: 760px) {
.page {
padding: 14px;
}
.topbar,
.section-head {
align-items: flex-start;
flex-direction: column;
}
.toolbar {
width: 100%;
justify-content: flex-start;
}
.overview,
.models,
.identity {
grid-template-columns: 1fr;
}
.field,
.field.search,
.segmented {
width: 100%;
}
table {
min-width: 880px;
}
.table-wrap {
overflow-x: auto;
}
}
</style>
</head>
<body>
<main class="page">
<header class="topbar">
<div>
<div class="breadcrumbs">初核项目 / 流水分析 / 结果总览</div>
<h1>结果总览</h1>
<div class="project-meta">
<span>项目编号HZ20260624001</span>
<span>导入流水18,426 笔</span>
<span>分析批次2026-06-24 09:38</span>
</div>
</div>
<div class="toolbar">
<button class="btn">导出结果</button>
<button class="btn ghost">专项排查</button>
<button class="btn primary">重新分析</button>
</div>
</header>
<section class="overview" aria-label="结果总览统计">
<div class="metric">
<div class="metric-title">分析主体数</div>
<div class="metric-value">126</div>
<div class="metric-note">员工、亲属及外部人员</div>
</div>
<div class="metric danger">
<div class="metric-title">高风险主体</div>
<div class="metric-value">8</div>
<div class="metric-note">较上批次 +2</div>
</div>
<div class="metric warning">
<div class="metric-title">中风险主体</div>
<div class="metric-value">21</div>
<div class="metric-note">待人工复核</div>
</div>
<div class="metric primary">
<div class="metric-title">外部人员预警</div>
<div class="metric-value">12</div>
<div class="metric-note">中介 5 人,其他 7 人</div>
</div>
<div class="metric">
<div class="metric-title">命中模型</div>
<div class="metric-value">17</div>
<div class="metric-note">含外部人员模型 4 个</div>
</div>
<div class="metric">
<div class="metric-title">涉疑交易金额</div>
<div class="metric-value">286.4万</div>
<div class="metric-note">按交易标签汇总</div>
</div>
</section>
<section class="grid">
<div>
<section class="section">
<div class="section-head">
<div class="section-title">风险主体</div>
<div class="segmented" role="tablist" aria-label="风险主体类型">
<button class="active" type="button" data-subject-tab="external">外部人员预警</button>
<button type="button" data-subject-tab="staff">员工风险</button>
</div>
</div>
<div class="section-body">
<div class="filters">
<input class="field search" type="text" value="" placeholder="搜索姓名、证件号、账户" />
<select class="field">
<option>全部主体类型</option>
<option>中介</option>
<option>外部人员</option>
</select>
<select class="field">
<option>全部风险等级</option>
<option>高风险</option>
<option>中风险</option>
<option>低风险</option>
</select>
<button class="btn primary">查询</button>
</div>
<div class="table-wrap">
<table>
<thead>
<tr>
<th class="col-name">风险主体</th>
<th class="col-type">主体类型</th>
<th class="col-cert">证件号</th>
<th class="col-level">风险等级</th>
<th class="col-count">命中模型数</th>
<th class="col-risk">核心风险点</th>
<th class="col-action">操作</th>
</tr>
</thead>
<tbody id="subjectRows">
<tr class="selected" data-name="王某" data-type="中介" data-cert="330************1234" data-level="高风险" data-models="4" data-risk="与员工亲属资金往来、大额转账、特殊金额交易" data-tags="外部人员大额交易,外部人员异常交易,外部人员可疑关系,特殊金额交易">
<td>王某</td>
<td><span class="tag primary">中介</span></td>
<td>330************1234</td>
<td><span class="tag danger">高风险</span></td>
<td>4</td>
<td>与员工亲属资金往来、大额转账、特殊金额交易</td>
<td class="col-action"><button class="link" type="button">详情</button></td>
</tr>
<tr data-name="李某" data-type="外部人员" data-cert="341************6612" data-level="中风险" data-models="2" data-risk="疑似赌博敏感交易、同日多笔转账" data-tags="外部人员异常交易,可疑赌博">
<td>李某</td>
<td><span class="tag orange">外部人员</span></td>
<td>341************6612</td>
<td><span class="tag warning">中风险</span></td>
<td>2</td>
<td>疑似赌博敏感交易、同日多笔转账</td>
<td class="col-action"><button class="link" type="button">详情</button></td>
</tr>
<tr data-name="赵某" data-type="外部人员" data-cert="320************4789" data-level="中风险" data-models="2" data-risk="与员工多次互转、夜间集中交易" data-tags="外部人员异常交易,外部人员可疑关系">
<td>赵某</td>
<td><span class="tag orange">外部人员</span></td>
<td>320************4789</td>
<td><span class="tag warning">中风险</span></td>
<td>2</td>
<td>与员工多次互转、夜间集中交易</td>
<td class="col-action"><button class="link" type="button">详情</button></td>
</tr>
<tr data-name="陈某" data-type="中介" data-cert="362************9021" data-level="低风险" data-models="1" data-risk="单笔交易金额超过外部人员阈值" data-tags="外部人员大额交易">
<td>陈某</td>
<td><span class="tag primary">中介</span></td>
<td>362************9021</td>
<td><span class="tag success">低风险</span></td>
<td>1</td>
<td>单笔交易金额超过外部人员阈值</td>
<td class="col-action"><button class="link" type="button">详情</button></td>
</tr>
</tbody>
</table>
</div>
</div>
</section>
<section class="section">
<div class="section-head">
<div class="section-title">风险模型</div>
<button class="btn">模型配置</button>
</div>
<div class="section-body">
<div class="models">
<div class="model-item">
<div class="model-name">外部人员大额交易</div>
<div class="model-count">9</div>
<div class="model-foot">单笔或累计金额超过阈值</div>
</div>
<div class="model-item">
<div class="model-name">外部人员异常交易</div>
<div class="model-count">6</div>
<div class="model-foot">频次、时间、金额形态异常</div>
</div>
<div class="model-item">
<div class="model-name">外部人员可疑赌博</div>
<div class="model-count">3</div>
<div class="model-foot">命中赌博敏感交易特征</div>
</div>
<div class="model-item">
<div class="model-name">外部人员可疑关系</div>
<div class="model-count">2</div>
<div class="model-foot">涉及员工或员工亲属资金往来</div>
</div>
</div>
</div>
</section>
<section class="section">
<div class="section-head">
<div class="section-title">涉疑交易明细</div>
<button class="btn">查看全部</button>
</div>
<div class="section-body">
<div class="table-wrap">
<table class="detail-table">
<thead>
<tr>
<th class="col-date">交易时间</th>
<th class="col-subject">风险主体</th>
<th>主体类型</th>
<th class="col-party">交易对手</th>
<th>对手类型</th>
<th class="col-labels">异常标签</th>
<th class="col-amount">金额</th>
</tr>
</thead>
<tbody>
<tr>
<td>2026-05-18 10:42</td>
<td>王某</td>
<td><span class="tag primary">中介</span></td>
<td>刘某某</td>
<td><span class="tag warning">员工亲属</span></td>
<td>
<div class="tags">
<span class="tag danger">外部人员可疑关系</span>
<span class="tag warning">特殊金额交易</span>
</div>
</td>
<td class="amount">180,000.00</td>
</tr>
<tr>
<td>2026-05-22 21:16</td>
<td>李某</td>
<td><span class="tag orange">外部人员</span></td>
<td>周某</td>
<td><span class="tag orange">外部人员</span></td>
<td>
<div class="tags">
<span class="tag warning">可疑赌博</span>
<span class="tag primary">夜间集中交易</span>
</div>
</td>
<td class="amount">52,000.00</td>
</tr>
<tr>
<td>2026-06-03 09:27</td>
<td>赵某</td>
<td><span class="tag orange">外部人员</span></td>
<td>张三</td>
<td><span class="tag primary">员工</span></td>
<td>
<div class="tags">
<span class="tag danger">外部人员可疑关系</span>
<span class="tag primary">多次互转</span>
</div>
</td>
<td class="amount">36,800.00</td>
</tr>
</tbody>
</table>
</div>
</div>
</section>
</div>
<aside class="side-panel">
<section class="section">
<div class="section-head">
<div class="section-title">外部人员风险详情</div>
<span class="tag danger" id="detailLevel">高风险</span>
</div>
<div class="section-body">
<div class="identity">
<div class="kv">
<div class="kv-label">风险主体</div>
<div class="kv-value" id="detailName">王某</div>
</div>
<div class="kv">
<div class="kv-label">主体类型</div>
<div class="kv-value" id="detailType">中介</div>
</div>
<div class="kv">
<div class="kv-label">证件号</div>
<div class="kv-value" id="detailCert">330************1234</div>
</div>
<div class="kv">
<div class="kv-label">命中模型数</div>
<div class="kv-value" id="detailModels">4</div>
</div>
</div>
<div class="detail-title">命中标签</div>
<div class="tags" id="detailTags">
<span class="tag danger">外部人员大额交易</span>
<span class="tag warning">外部人员异常交易</span>
<span class="tag primary">外部人员可疑关系</span>
<span class="tag orange">特殊金额交易</span>
</div>
<div class="detail-title">核心风险点</div>
<div class="risk-text" id="detailRisk">与员工亲属资金往来、大额转账、特殊金额交易</div>
<div class="detail-title">关联交易</div>
<table class="mini-table">
<thead>
<tr>
<th>对手方</th>
<th>对手类型</th>
<th>金额</th>
</tr>
</thead>
<tbody>
<tr>
<td>刘某某</td>
<td>员工亲属</td>
<td class="amount">180,000.00</td>
</tr>
<tr>
<td>张三</td>
<td>员工</td>
<td class="amount">36,800.00</td>
</tr>
</tbody>
</table>
<div class="detail-title">关系图谱</div>
<div class="empty-graph">外部人员图谱暂未接入</div>
</div>
</section>
<div class="footer-note">外部人员口径:本方证件号未命中员工及员工亲属,命中中介库本人证件号时标记为中介。</div>
</aside>
</section>
</main>
<script>
const rows = Array.from(document.querySelectorAll("#subjectRows tr"));
const detailName = document.getElementById("detailName");
const detailType = document.getElementById("detailType");
const detailCert = document.getElementById("detailCert");
const detailModels = document.getElementById("detailModels");
const detailRisk = document.getElementById("detailRisk");
const detailLevel = document.getElementById("detailLevel");
const detailTags = document.getElementById("detailTags");
function tagClass(text) {
if (text.includes("大额") || text.includes("可疑关系")) return "danger";
if (text.includes("异常") || text.includes("赌博")) return "warning";
if (text.includes("特殊")) return "orange";
return "primary";
}
function selectRow(row) {
rows.forEach((item) => item.classList.remove("selected"));
row.classList.add("selected");
detailName.textContent = row.dataset.name;
detailType.textContent = row.dataset.type;
detailCert.textContent = row.dataset.cert;
detailModels.textContent = row.dataset.models;
detailRisk.textContent = row.dataset.risk;
detailLevel.textContent = row.dataset.level;
detailLevel.className = "tag " + (row.dataset.level === "高风险" ? "danger" : row.dataset.level === "中风险" ? "warning" : "success");
detailTags.innerHTML = "";
row.dataset.tags.split(",").forEach((text) => {
const tag = document.createElement("span");
tag.className = "tag " + tagClass(text);
tag.textContent = text;
detailTags.appendChild(tag);
});
}
rows.forEach((row) => {
row.addEventListener("click", () => selectRow(row));
});
document.querySelectorAll("[data-subject-tab]").forEach((button) => {
button.addEventListener("click", () => {
document.querySelectorAll("[data-subject-tab]").forEach((item) => item.classList.remove("active"));
button.classList.add("active");
});
});
</script>
</body>
</html>