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

315 lines
9.1 KiB
Vue
Raw Normal View History

<template>
<div class="preliminary-check-container">
2026-03-19 10:35:40 +08:00
<div v-if="pageState === 'loading'" class="preliminary-check-state">
2026-03-19 10:39:24 +08:00
<div class="state-card">
<el-skeleton animated :rows="6" />
</div>
2026-03-19 10:35:40 +08:00
</div>
<div v-else-if="pageState === 'empty'" class="preliminary-check-state">
2026-03-19 10:39:24 +08:00
<div class="state-card">
<el-empty description="暂无结果总览数据" />
</div>
2026-03-19 10:35:40 +08:00
</div>
<div v-else class="preliminary-check-page">
<section class="section-card risk-overview-card">
<div class="section-header">
<div>
<div class="section-title">风险总览</div>
<div class="section-subtitle">集中展示项目风险统计与命中人员总览</div>
</div>
</div>
<overview-stats :summary="currentData.summary" />
<risk-people-section
:project-id="projectId"
:section-data="currentData.riskPeople"
:selected-model-codes="selectedModelCodes"
@view-project-analysis="handleRiskPeopleProjectAnalysis"
/>
</section>
<risk-model-section
:section-data="currentData.riskModels"
@selection-change="handleRiskModelSelectionChange"
@view-project-analysis="handleRiskModelProjectAnalysis"
/>
2026-04-21 16:46:47 +08:00
<risk-detail-section
:section-data="currentData.riskDetails"
@evidence-confirm="$emit('evidence-confirm', $event)"
/>
</div>
<project-analysis-dialog
:visible.sync="projectAnalysisDialogVisible"
:project-id="projectId"
:person="currentProjectAnalysisPerson"
:source="projectAnalysisSource"
:model-summary="projectAnalysisModelSummary"
:project-name="projectInfo.projectName"
@close="handleProjectAnalysisDialogClose"
2026-04-21 16:46:47 +08:00
@evidence-confirm="$emit('evidence-confirm', $event)"
/>
</div>
</template>
<script>
2026-03-19 15:40:43 +08:00
import {
createOverviewLoadedData,
mockOverviewData,
mockOverviewStateData,
} from "./preliminaryCheck.mock";
import {
getOverviewDashboard,
getOverviewEmployeeCreditNegative,
2026-03-19 15:40:43 +08:00
getOverviewRiskPeople,
getOverviewRiskModelCards,
getOverviewSuspiciousTransactions,
2026-03-19 15:40:43 +08:00
} from "@/api/ccdi/projectOverview";
import OverviewStats from "./OverviewStats";
import RiskPeopleSection from "./RiskPeopleSection";
import RiskModelSection from "./RiskModelSection";
import RiskDetailSection from "./RiskDetailSection";
import ProjectAnalysisDialog from "./ProjectAnalysisDialog";
2026-03-19 10:35:40 +08:00
export default {
name: "PreliminaryCheck",
2026-03-19 10:35:40 +08:00
components: {
OverviewStats,
RiskPeopleSection,
RiskModelSection,
RiskDetailSection,
ProjectAnalysisDialog,
2026-03-19 10:35:40 +08:00
},
props: {
projectId: {
type: [String, Number],
default: null,
},
projectInfo: {
type: Object,
default: () => ({
projectName: "",
updateTime: "",
projectStatus: "0",
}),
},
},
2026-03-19 10:35:40 +08:00
data() {
return {
2026-03-19 15:40:43 +08:00
pageState: "loading",
selectedModelCodes: [],
2026-03-19 10:35:40 +08:00
mockData: mockOverviewData,
2026-03-19 10:39:24 +08:00
stateDataMap: mockOverviewStateData,
2026-03-19 15:40:43 +08:00
realData: mockOverviewData,
projectAnalysisDialogVisible: false,
currentProjectAnalysisPerson: null,
projectAnalysisSource: "riskPeople",
projectAnalysisModelSummary: {
modelCount: 0,
currentModel: "-",
riskTags: [],
},
2026-03-19 10:35:40 +08:00
};
},
2026-03-19 10:39:24 +08:00
computed: {
currentData() {
2026-03-19 15:40:43 +08:00
if (this.pageState === "loaded") {
return this.realData;
}
return this.stateDataMap[this.pageState] || this.realData;
},
},
watch: {
projectId(newVal) {
if (newVal) {
this.loadOverviewData();
return;
}
this.realData = this.stateDataMap.empty;
this.pageState = "empty";
this.selectedModelCodes = [];
this.resetProjectAnalysisDialog();
2026-03-19 15:40:43 +08:00
},
},
created() {
if (this.projectId) {
this.loadOverviewData();
return;
}
this.realData = this.stateDataMap.empty;
this.pageState = "empty";
this.resetProjectAnalysisDialog();
2026-03-19 15:40:43 +08:00
},
methods: {
handleRiskModelSelectionChange(modelCodes) {
this.selectedModelCodes = Array.isArray(modelCodes) ? [...modelCodes] : [];
},
handleRiskPeopleProjectAnalysis(row) {
this.openProjectAnalysisDialog("riskPeople", row);
},
handleRiskModelProjectAnalysis(row) {
this.openProjectAnalysisDialog("riskModelPeople", row);
},
openProjectAnalysisDialog(source, person) {
this.projectAnalysisSource = source || "riskPeople";
this.currentProjectAnalysisPerson = person || null;
this.projectAnalysisModelSummary = this.buildProjectAnalysisModelSummary(
this.projectAnalysisSource,
this.currentProjectAnalysisPerson
);
this.projectAnalysisDialogVisible = true;
},
handleProjectAnalysisDialogClose() {
this.projectAnalysisDialogVisible = false;
this.resetProjectAnalysisDialog();
},
resetProjectAnalysisDialog() {
this.projectAnalysisDialogVisible = false;
this.currentProjectAnalysisPerson = null;
this.projectAnalysisSource = "riskPeople";
this.projectAnalysisModelSummary = {
modelCount: 0,
currentModel: "-",
riskTags: [],
};
},
buildProjectAnalysisModelSummary(source, person) {
const safePerson = person || {};
const riskTags = Array.isArray(safePerson.riskPointTagList)
? safePerson.riskPointTagList
: Array.isArray(safePerson.hitTagList)
? safePerson.hitTagList
: [];
return {
staffIdCard: safePerson.idNo || safePerson.staffIdCard || "",
modelCount: safePerson.modelCount || (Array.isArray(safePerson.modelNames) ? safePerson.modelNames.length : 0),
currentModel: source === "riskModelPeople"
? (Array.isArray(safePerson.modelNames) && safePerson.modelNames.length
? safePerson.modelNames.join("、")
: safePerson.modelName || "-")
: ((riskTags[0] && riskTags[0].modelName) || "-"),
riskTags,
};
},
2026-03-19 15:40:43 +08:00
async loadOverviewData() {
if (!this.projectId) {
this.realData = this.stateDataMap.empty;
this.pageState = "empty";
this.selectedModelCodes = [];
this.resetProjectAnalysisDialog();
2026-03-19 15:40:43 +08:00
return;
}
this.pageState = "loading";
this.selectedModelCodes = [];
this.resetProjectAnalysisDialog();
2026-03-19 15:40:43 +08:00
try {
const [dashboardRes, riskPeopleRes, riskModelCardsRes, suspiciousRes, creditNegativeRes] = await Promise.all([
2026-03-19 15:40:43 +08:00
getOverviewDashboard(this.projectId),
getOverviewRiskPeople({
projectId: this.projectId,
pageNum: 1,
pageSize: 5,
}),
getOverviewRiskModelCards(this.projectId),
getOverviewSuspiciousTransactions({
projectId: this.projectId,
suspiciousType: "ALL",
pageNum: 1,
pageSize: 5,
}),
getOverviewEmployeeCreditNegative({
projectId: this.projectId,
pageNum: 1,
pageSize: 5,
}),
2026-03-19 15:40:43 +08:00
]);
const dashboardData = (dashboardRes && dashboardRes.data) || {};
const riskPeopleData = (riskPeopleRes && riskPeopleRes.data) || {};
const riskModelCardsData = (riskModelCardsRes && riskModelCardsRes.data) || {};
const suspiciousData = (suspiciousRes && suspiciousRes.data) || {};
const creditNegativeData = (creditNegativeRes && creditNegativeRes.data) || {};
2026-03-19 15:40:43 +08:00
this.realData = createOverviewLoadedData({
projectId: this.projectId,
2026-03-19 15:40:43 +08:00
dashboardData,
riskPeopleData,
riskModelCardsData,
suspiciousData,
creditNegativeData,
2026-03-19 15:40:43 +08:00
});
const hasOverviewData = Boolean(
(Array.isArray(dashboardData.stats) && dashboardData.stats.length) ||
(Array.isArray(riskPeopleData.rows) && riskPeopleData.rows.length) ||
(Array.isArray(riskModelCardsData.cardList) && riskModelCardsData.cardList.length)
2026-03-19 15:40:43 +08:00
);
this.pageState = hasOverviewData ? "loaded" : "empty";
} catch (error) {
this.realData = this.stateDataMap.empty;
this.pageState = "empty";
this.selectedModelCodes = [];
this.resetProjectAnalysisDialog();
2026-03-19 15:40:43 +08:00
console.error("加载结果总览失败", error);
}
2026-03-19 10:39:24 +08:00
},
},
};
</script>
<style lang="scss" scoped>
.preliminary-check-container {
min-height: 400px;
padding: 0 0 24px;
}
2026-03-19 10:35:40 +08:00
.preliminary-check-state {
2026-03-19 10:39:24 +08:00
min-height: 400px;
}
.state-card {
padding: 32px 24px;
2026-04-03 11:00:33 +08:00
border-radius: 14px;
2026-03-19 10:35:40 +08:00
background: #fff;
2026-04-03 11:00:33 +08:00
border: 1px solid var(--ccdi-border);
box-shadow: var(--ccdi-shadow);
2026-03-19 10:35:40 +08:00
}
2026-03-19 10:35:40 +08:00
.preliminary-check-page {
min-height: 400px;
}
.section-card {
padding: 20px;
2026-04-03 11:00:33 +08:00
border-radius: 14px;
background: #fff;
2026-04-03 11:00:33 +08:00
border: 1px solid var(--ccdi-border);
box-shadow: var(--ccdi-shadow);
}
.risk-overview-card {
margin-bottom: 16px;
padding: 24px 20px 20px;
}
.section-header {
margin-bottom: 18px;
padding-left: 12px;
2026-04-03 11:00:33 +08:00
border-left: 4px solid var(--ccdi-primary);
}
.section-title {
font-size: 20px;
line-height: 28px;
font-weight: 700;
2026-04-03 11:00:33 +08:00
color: var(--ccdi-text-primary);
}
.section-subtitle {
margin-top: 6px;
font-size: 12px;
2026-04-03 11:00:33 +08:00
color: var(--ccdi-text-muted);
}
</style>