调整结果总览模型区筛选与列表列
This commit is contained in:
@@ -38,6 +38,36 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="filter-bar">
|
<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">
|
<div class="filter-item filter-item--mode">
|
||||||
<span class="filter-label">触发方式</span>
|
<span class="filter-label">触发方式</span>
|
||||||
<el-radio-group
|
<el-radio-group
|
||||||
@@ -62,12 +92,35 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<el-table v-loading="tableLoading" :data="peopleList" class="model-table">
|
<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 type="index" label="序号" width="60" />
|
||||||
<el-table-column prop="name" label="姓名" min-width="100" />
|
<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="idNo" label="身份证号" min-width="180" />
|
||||||
<el-table-column prop="department" label="所属部门" min-width="140" />
|
<el-table-column prop="department" label="所属部门" min-width="140" />
|
||||||
<el-table-column prop="warningType" label="预警类型" min-width="120" />
|
<el-table-column label="命中模型" min-width="180">
|
||||||
<el-table-column prop="modelName" 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">
|
<el-table-column label="操作" width="100" align="right">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<el-button type="text" size="mini">{{
|
<el-button type="text" size="mini">{{
|
||||||
@@ -94,6 +147,7 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { getOverviewRiskModelPeople } from "@/api/ccdi/projectOverview";
|
import { getOverviewRiskModelPeople } from "@/api/ccdi/projectOverview";
|
||||||
|
import { deptTreeSelect } from "@/api/system/user";
|
||||||
|
|
||||||
function normalizePeopleRows(rows) {
|
function normalizePeopleRows(rows) {
|
||||||
if (!Array.isArray(rows)) {
|
if (!Array.isArray(rows)) {
|
||||||
@@ -102,11 +156,29 @@ function normalizePeopleRows(rows) {
|
|||||||
return rows.map((item) => ({
|
return rows.map((item) => ({
|
||||||
...item,
|
...item,
|
||||||
name: item.staffName || item.name || "",
|
name: item.staffName || item.name || "",
|
||||||
modelName: Array.isArray(item.modelNames) ? item.modelNames.join("、") : item.modelName || "",
|
staffCode: item.staffCode || "",
|
||||||
warningType: item.warningType || "-",
|
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 {
|
export default {
|
||||||
name: "RiskModelSection",
|
name: "RiskModelSection",
|
||||||
props: {
|
props: {
|
||||||
@@ -125,6 +197,8 @@ export default {
|
|||||||
pageSize: 5,
|
pageSize: 5,
|
||||||
cardLoading: false,
|
cardLoading: false,
|
||||||
tableLoading: false,
|
tableLoading: false,
|
||||||
|
deptLoading: false,
|
||||||
|
deptOptions: [],
|
||||||
peopleList: [],
|
peopleList: [],
|
||||||
total: 0,
|
total: 0,
|
||||||
};
|
};
|
||||||
@@ -163,6 +237,9 @@ export default {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
created() {
|
||||||
|
this.loadDeptOptions();
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
isModelSelected(modelCode) {
|
isModelSelected(modelCode) {
|
||||||
return this.selectedModelCodes.includes(modelCode);
|
return this.selectedModelCodes.includes(modelCode);
|
||||||
@@ -207,6 +284,34 @@ export default {
|
|||||||
pageSize: this.pageSize,
|
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() {
|
async fetchPeopleList() {
|
||||||
if (!this.projectId) {
|
if (!this.projectId) {
|
||||||
this.peopleList = [];
|
this.peopleList = [];
|
||||||
@@ -337,6 +442,16 @@ export default {
|
|||||||
flex-wrap: wrap;
|
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,
|
.filter-label,
|
||||||
.summary-label {
|
.summary-label {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
@@ -376,6 +491,16 @@ export default {
|
|||||||
color: #64748b;
|
color: #64748b;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.hit-tag-list {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.empty-text {
|
||||||
|
color: #94a3b8;
|
||||||
|
}
|
||||||
|
|
||||||
.pagination-bar {
|
.pagination-bar {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
|
|||||||
23
ruoyi-ui/tests/unit/preliminary-check-model-filters.test.js
Normal file
23
ruoyi-ui/tests/unit/preliminary-check-model-filters.test.js
Normal 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));
|
||||||
@@ -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));
|
||||||
Reference in New Issue
Block a user