调整结果总览模型区筛选与列表列

This commit is contained in:
wkc
2026-03-20 11:30:08 +08:00
parent e147d6dfee
commit 2285ebd3f0
3 changed files with 176 additions and 4 deletions

View File

@@ -38,6 +38,36 @@
</div>
<div class="filter-bar">
<div class="filter-item filter-item--keyword">
<span class="filter-label">员工姓名或工号</span>
<el-input
v-model.trim="keyword"
size="mini"
clearable
placeholder="请输入员工姓名或工号"
@keyup.enter.native="handleQuery"
/>
</div>
<div class="filter-item filter-item--dept">
<span class="filter-label">部门</span>
<el-select
v-model="deptId"
size="mini"
clearable
filterable
:loading="deptLoading"
placeholder="请选择部门"
>
<el-option
v-for="item in deptOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</div>
<div class="filter-item filter-item--mode">
<span class="filter-label">触发方式</span>
<el-radio-group
@@ -62,12 +92,35 @@
</div>
<el-table v-loading="tableLoading" :data="peopleList" class="model-table">
<template slot="empty">
<el-empty :image-size="80" description="当前筛选条件下暂无命中人员" />
</template>
<el-table-column type="index" label="序号" width="60" />
<el-table-column prop="name" label="姓名" min-width="100" />
<el-table-column prop="staffCode" label="工号" min-width="120" />
<el-table-column prop="idNo" label="身份证号" min-width="180" />
<el-table-column prop="department" label="所属部门" min-width="140" />
<el-table-column prop="warningType" label="预警类型" min-width="120" />
<el-table-column prop="modelName" label="筛查模型" min-width="180" />
<el-table-column label="命中模型" min-width="180">
<template slot-scope="scope">
<span>{{ formatModelNames(scope.row.modelNames) }}</span>
</template>
</el-table-column>
<el-table-column label="异常标签" min-width="220">
<template slot-scope="scope">
<div v-if="scope.row.hitTagList && scope.row.hitTagList.length" class="hit-tag-list">
<el-tag
v-for="(tag, index) in scope.row.hitTagList"
:key="`${scope.row.staffCode || scope.row.idNo || index}-tag-${index}`"
size="mini"
effect="plain"
:type="mapRiskLevelToTagType(tag.riskLevel)"
>
{{ 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">{{
@@ -94,6 +147,7 @@
<script>
import { getOverviewRiskModelPeople } from "@/api/ccdi/projectOverview";
import { deptTreeSelect } from "@/api/system/user";
function normalizePeopleRows(rows) {
if (!Array.isArray(rows)) {
@@ -102,11 +156,29 @@ function normalizePeopleRows(rows) {
return rows.map((item) => ({
...item,
name: item.staffName || item.name || "",
modelName: Array.isArray(item.modelNames) ? item.modelNames.join("、") : item.modelName || "",
warningType: item.warningType || "-",
staffCode: item.staffCode || "",
modelNames: Array.isArray(item.modelNames) ? item.modelNames : [],
hitTagList: Array.isArray(item.hitTagList) ? item.hitTagList : [],
}));
}
function flattenDeptOptions(nodes, result = []) {
if (!Array.isArray(nodes)) {
return result;
}
nodes.forEach((item) => {
const value = item.id || item.deptId;
const label = item.label || item.deptName;
if (value !== undefined && label) {
result.push({ value, label });
}
if (Array.isArray(item.children) && item.children.length) {
flattenDeptOptions(item.children, result);
}
});
return result;
}
export default {
name: "RiskModelSection",
props: {
@@ -125,6 +197,8 @@ export default {
pageSize: 5,
cardLoading: false,
tableLoading: false,
deptLoading: false,
deptOptions: [],
peopleList: [],
total: 0,
};
@@ -163,6 +237,9 @@ export default {
},
},
},
created() {
this.loadDeptOptions();
},
methods: {
isModelSelected(modelCode) {
return this.selectedModelCodes.includes(modelCode);
@@ -207,6 +284,34 @@ export default {
pageSize: this.pageSize,
};
},
formatModelNames(modelNames) {
if (!Array.isArray(modelNames) || !modelNames.length) {
return "-";
}
return modelNames.join("、");
},
mapRiskLevelToTagType(riskLevel) {
const level = String(riskLevel || "").toUpperCase();
if (level === "HIGH") {
return "danger";
}
if (level === "MEDIUM") {
return "warning";
}
return "info";
},
async loadDeptOptions() {
this.deptLoading = true;
try {
const response = await deptTreeSelect();
this.deptOptions = flattenDeptOptions(response && response.data);
} catch (error) {
this.deptOptions = [];
console.error("加载部门选项失败", error);
} finally {
this.deptLoading = false;
}
},
async fetchPeopleList() {
if (!this.projectId) {
this.peopleList = [];
@@ -337,6 +442,16 @@ export default {
flex-wrap: wrap;
}
.filter-item--keyword,
.filter-item--dept {
min-width: 240px;
}
.filter-item--keyword :deep(.el-input),
.filter-item--dept :deep(.el-select) {
width: 220px;
}
.filter-label,
.summary-label {
font-size: 12px;
@@ -376,6 +491,16 @@ export default {
color: #64748b;
}
.hit-tag-list {
display: flex;
flex-wrap: wrap;
gap: 6px;
}
.empty-text {
color: #94a3b8;
}
.pagination-bar {
display: flex;
justify-content: flex-end;

View File

@@ -0,0 +1,23 @@
const assert = require("assert");
const fs = require("fs");
const path = require("path");
const source = fs.readFileSync(
path.resolve(
__dirname,
"../../src/views/ccdiProject/components/detail/RiskModelSection.vue"
),
"utf8"
);
[
"员工姓名或工号",
"部门",
"任意触发",
"同时触发",
].forEach((token) => assert(source.includes(token), token));
[
"筛查模型",
"预警类型",
].forEach((token) => assert(!source.includes(token), token));

View File

@@ -0,0 +1,24 @@
const assert = require("assert");
const fs = require("fs");
const path = require("path");
const source = fs.readFileSync(
path.resolve(
__dirname,
"../../src/views/ccdiProject/components/detail/RiskModelSection.vue"
),
"utf8"
);
[
'label="工号"',
'prop="staffCode"',
"异常标签",
"hitTagList",
"ruleName",
].forEach((token) => assert(source.includes(token), token));
[
'prop="warningType"',
'label="预警类型"',
].forEach((token) => assert(!source.includes(token), token));