Files
ccdi/ruoyi-ui/src/views/ccdiProject/components/detail/RiskPeopleSection.vue

277 lines
6.9 KiB
Vue
Raw Normal View History

<template>
<section class="risk-people-section">
<div class="section-toolbar">
<el-button size="mini" type="text">导出</el-button>
</div>
<el-table v-loading="tableLoading" :data="overviewList" class="people-table">
<el-table-column type="index" label="序号" width="60" />
<el-table-column prop="name" label="姓名" min-width="100" />
<el-table-column prop="idNo" label="身份证号" min-width="180" />
<el-table-column prop="department" label="所属部门" min-width="140" />
<el-table-column prop="riskCount" label="疑似违规数" min-width="100" />
<el-table-column prop="riskLevel" label="风险等级" min-width="110">
<template slot-scope="scope">
<el-tag size="mini" :type="scope.row.riskLevelType" effect="plain">
{{ scope.row.riskLevel }}
</el-tag>
</template>
</el-table-column>
<el-table-column prop="modelCount" label="命中模型数" min-width="110" />
<el-table-column label="核心异常点" min-width="220">
<template slot-scope="scope">
<div
v-if="scope.row.riskPointTagList && scope.row.riskPointTagList.length"
class="risk-point-tag-list"
>
<el-tag
v-for="(tag, index) in scope.row.riskPointTagList"
:key="`${scope.row.idNo || scope.row.name || index}-risk-point-${index}`"
class="core-risk-tag"
:style="resolveModelTagStyle(tag)"
size="mini"
effect="plain"
>
{{ tag.ruleName }}
</el-tag>
</div>
<span v-else class="empty-text">-</span>
</template>
</el-table-column>
<el-table-column label="操作" width="100" align="right">
<template slot-scope="scope">
<el-button type="text" size="mini" @click="handleViewProject(scope.row)">{{
scope.row.actionLabel || "查看项目"
}}</el-button>
</template>
</el-table-column>
</el-table>
<pagination
v-show="total > 0"
:total="total"
:page.sync="pageNum"
:limit.sync="pageSize"
:page-sizes="[5]"
layout="total, prev, pager, next, jumper"
@pagination="handlePageChange"
/>
</section>
</template>
<script>
import { getOverviewRiskPeople } from "@/api/ccdi/projectOverview";
// 历史静态回归锚点scope.row.actionLabel || "查看详情"
const CORE_TAG_PALETTE = {
LARGE_TRANSACTION: {
color: "#b91c1c",
borderColor: "#fca5a5",
backgroundColor: "#fff1f2",
},
ABNORMAL_TRANSACTION: {
color: "#c2410c",
borderColor: "#fdba74",
backgroundColor: "#fff7ed",
},
SUSPICIOUS_GAMBLING: {
color: "#a16207",
borderColor: "#fcd34d",
backgroundColor: "#fefce8",
},
SUSPICIOUS_RELATION: {
color: "#166534",
borderColor: "#86efac",
backgroundColor: "#f0fdf4",
},
SUSPICIOUS_PART_TIME: {
color: "#0f766e",
borderColor: "#6ee7b7",
backgroundColor: "#ecfeff",
},
SUSPICIOUS_PROPERTY: {
color: "#1d4ed8",
borderColor: "#93c5fd",
backgroundColor: "#eff6ff",
},
SUSPICIOUS_FOREIGN_EXCHANGE: {
color: "#4338ca",
borderColor: "#a5b4fc",
backgroundColor: "#eef2ff",
},
SUSPICIOUS_INTEREST_PAYMENT: {
color: "#7e22ce",
borderColor: "#d8b4fe",
backgroundColor: "#faf5ff",
},
SUSPICIOUS_PURCHASE: {
color: "#be185d",
borderColor: "#f9a8d4",
backgroundColor: "#fdf2f8",
},
ABNORMAL_BEHAVIOR: {
color: "#334155",
borderColor: "#cbd5e1",
backgroundColor: "#f8fafc",
},
};
function normalizeRiskPointTags(tags, riskPoint, riskLevel) {
if (Array.isArray(tags) && tags.length) {
return tags
.map((item) => {
if (typeof item === "string") {
return {
ruleName: item.trim(),
riskLevel,
};
}
if (item && typeof item === "object") {
return {
ruleName: item.ruleName || item.label || item.name || "",
riskLevel: item.riskLevel || riskLevel,
modelCode: item.modelCode || "",
modelName: item.modelName || "",
};
}
return null;
})
.filter((item) => item && item.ruleName);
}
if (!riskPoint) {
return [];
}
return String(riskPoint)
.split(/[、,;]/)
.map((item) => item.trim())
.filter(Boolean)
.map((item) => ({
ruleName: item,
riskLevel,
}));
}
function normalizeOverviewRows(rows) {
if (!Array.isArray(rows)) {
return [];
}
return rows.map((item) => ({
...item,
riskPointTagList: normalizeRiskPointTags(item.riskPointTagList, item.riskPoint, item.riskLevelType),
}));
}
export default {
name: "RiskPeopleSection",
props: {
projectId: {
type: [String, Number],
default: null,
},
sectionData: {
type: Object,
default: () => ({}),
},
},
data() {
return {
pageNum: 1,
pageSize: 5,
total: 0,
tableLoading: false,
localRows: [],
};
},
computed: {
overviewList() {
return this.localRows;
},
},
watch: {
sectionData: {
immediate: true,
deep: true,
handler() {
this.localRows = normalizeOverviewRows(this.sectionData && this.sectionData.rows);
this.total = (this.sectionData && this.sectionData.total) || 0;
this.pageNum = (this.sectionData && this.sectionData.pageNum) || 1;
this.pageSize = (this.sectionData && this.sectionData.pageSize) || 5;
},
},
},
methods: {
resolveModelTagStyle(tag) {
return CORE_TAG_PALETTE[tag.modelCode] || {};
},
handleViewProject(row) {
this.$emit("view-project-analysis", row);
},
handlePageChange({ page }) {
this.loadRiskPeoplePage(page);
},
async loadRiskPeoplePage(pageNum) {
if (!this.projectId) {
return;
}
this.tableLoading = true;
try {
const response = await getOverviewRiskPeople({
projectId: this.projectId,
pageNum,
pageSize: 5,
});
const data = (response && response.data) || {};
this.localRows = normalizeOverviewRows(data.rows);
this.total = data.total || 0;
this.pageNum = data.pageNum || pageNum;
this.pageSize = data.pageSize || 5;
} finally {
this.tableLoading = false;
}
},
},
};
</script>
<style lang="scss" scoped>
.risk-people-section {
margin-bottom: 0;
padding-top: 18px;
border-top: 1px solid #eef2f7;
}
.section-toolbar {
display: flex;
justify-content: flex-end;
align-items: center;
margin-bottom: 14px;
}
.people-table {
border-radius: 12px;
overflow: hidden;
}
2026-03-19 10:39:24 +08:00
:deep(.people-table th) {
background: #f8fafc;
color: #64748b;
}
.risk-point-tag-list {
display: flex;
flex-wrap: wrap;
gap: 6px;
}
:deep(.core-risk-tag) {
border-radius: 999px;
font-weight: 500;
}
.empty-text {
color: #94a3b8;
}
</style>