Browse Source

目录调整--赋分机制合并

master
parent
commit
b523311246
  1. 675
      src/views/sensitivePerception/GradingRules.vue

675
src/views/sensitivePerception/GradingRules.vue

@ -0,0 +1,675 @@
<template>
<div class="container">
<!-- 标签页组件 -->
<el-tabs v-model="activeTab" class="mb-20">
<!-- 个人极端赋分标签 -->
<el-tab-pane label="个人极端赋分" name="riskScoreRule">
<!-- 个人极端赋分内容 -->
<div class="tab-content" v-loading="riskScoreLoading">
<header class="mb-20">
<div class="flex between">
<div>
<el-button type="primary" @click="handleAddRiskScoreRule">
<template #icon>
<icon name="el-icon-Plus" />
</template>
新增
</el-button>
</div>
<div style="width: 50%">
<el-row> </el-row>
</div>
</div>
<div class="flex between mt-10 v-center">
<div>
<div>
<span class="text-primary">个人极端暴力风险指数</span> = ((基础因素得分 × 权重诱发因素得分 × 权重行为因素得分 × 权重管控因素得分 × 权重)) × 20
</div>
</div>
<a
class="flex v-center gap file-link"
:href="`${BASE_PATH}/templates/【工作机制】个人极端暴力风险数字督察灵敏感知体系风险赋分及预警处置机制.doc`"
target="__blank"
>
<icon name="local-icon-pdf" :size="38" />
<span>个人极端风险赋分规则.pdf</span>
</a>
</div>
</header>
<div class="table-container">
<el-table
ref="riskScoreTableRef"
:default-expand-all="false"
:data="scoreRules"
:expand-row-keys="[]"
:tree-props="{
children: 'children',
hasChildren: 'hasChildren',
}"
row-key="id"
>
<el-table-column
label="问题条目"
prop="riskName"
show-overflow-tooltip
width="180"
/>
<el-table-column
label="一级指标"
prop="riskIndex"
show-overflow-tooltip
width="180"
/>
<el-table-column
label="因素分值"
prop="score"
width="200"
align="center"
>
</el-table-column>
<el-table-column
label="赋分规则"
prop="ruleDesc"
show-overflow-tooltip
>
</el-table-column>
<el-table-column label="因素权重" width="100" align="center">
<template #default="{ row }">
<span v-if="row.level === 1">{{ getChildWeightSum(row) }}</span>
<span v-if="row.level === 2">{{ row.weight }}</span>
</template>
</el-table-column>
<el-table-column label="开启状态" width="100">
<template #default="{ row }">
<el-tag type="success" v-if="row.status === true">开启</el-tag>
<el-tag type="danger" v-if="row.status === false">关闭</el-tag>
</template>
</el-table-column>
<el-table-column
label="最后更新时间"
prop="updateTime"
width="180"
/>
<el-table-column label="操作" width="160">
<template #default="{ row }">
<el-button type="primary" link @click="handleEditRiskScoreRule(row)">编辑</el-button>
<el-button type="danger" link @click="handleDeleteRiskScoreRule(row)">删除</el-button>
</template>
</el-table-column>
</el-table>
</div>
</div>
</el-tab-pane>
<!-- 问题赋分标签 -->
<el-tab-pane label="问题赋分" name="dictContent">
<!-- 问题赋分内容 -->
<div class="tab-content" v-loading="dictContentLoading">
<header class="mb-20">
<div class="flex between">
<div>
<el-button type="primary" @click="handleAddDictContent">
<template #icon>
<icon name="el-icon-Plus" />
</template>
新增
</el-button>
</div>
<div style="width: 50%">
<el-row>
<el-col :span="12"></el-col>
<el-col :span="12">
<div class="flex end">
<el-button type="primary" @click="handleCalculateDictContent">重新计算分值</el-button>
</div>
</el-col>
</el-row>
</div>
</div>
<div class="flex between mt-10">
<div>
<div class="text-primary mt-10 mb-10">赋分分公式如下</div>
<div>问题风险值 = 基础风险值+(基础风险值×问题严重等级系数)+(基础风险值×问题发生频次系数)</div>
</div>
<a
class="flex v-center gap file-link"
:href="`${BASE_PATH}/templates/长沙公安数字督察灵敏感知体系问题赋分及风险预警机制.pdf`"
target="__blank"
>
<icon name="local-icon-pdf" :size="38" />
<span>问题赋分机制.pdf</span>
</a>
</div>
</header>
<div class="table-container">
<el-table :data="dictContents" row-key="id" :default-expand-all="false">
<el-table-column
label="问题条目"
prop="name"
show-overflow-tooltip
/>
<el-table-column label="基础分值" prop="score" width="200" align="center">
<template #default="{ row }">
<span v-if="row.level === 1">{{ getScoreRange(row) }}</span>
<span v-else>{{ row.score }}</span>
</template>
</el-table-column>
<el-table-column
label="问题严重等级"
prop="isActiveLevel"
align="center"
>
<template #default="{ row }">
<el-tag type="success" v-if="row.isActiveLevel === true">开启</el-tag>
<el-tag type="danger" v-if="row.isActiveLevel === false">关闭</el-tag>
</template>
</el-table-column>
<el-table-column
label="序号"
prop="sort"
width="100"
align="center"
/>
<el-table-column label="最后更新时间" prop="updTime" />
<el-table-column label="操作">
<template #default="{ row }">
<el-button type="primary" link @click="handleEditDictContent(row)">编辑</el-button>
<el-button type="danger" link @click="handleDeleteDictContent(row)">删除</el-button>
</template>
</el-table-column>
</el-table>
</div>
<div class="mt-40">
<div>基础分值设定规则</div>
<p>1二级问题条目设定的基础分值作为其下属三级问题条目的默认基础分值</p>
<p>2若三级问题条目已单独设置基础分值则赋分时以该三级条目的基础分值为准</p>
<p>3如三级问题条目未设置基础分值则采用其所属二级问题条目的基础分值进行赋分</p>
</div>
</div>
</el-tab-pane>
</el-tabs>
<!-- 个人极端赋分编辑对话框 -->
<el-dialog
v-model="riskScoreShow"
:title="riskScoreMode === 'add' ? '新增赋分规则' : '编辑赋分规则'"
width="600"
>
<el-form label-width="120" ref="riskScoreFormRef" :model="riskScoreFormData">
<el-form-item
label="父级节点"
:rules="{
required: true,
message: '请选择父级节点',
}"
prop="pid"
>
<el-tree-select
class="flex-1"
v-model="riskScoreFormData.pid"
:data="treeOptions"
clearable
node-key="id"
:props="{
label: 'riskName',
}"
:default-expanded-keys="[MENU_ROOT_ID]"
placeholder="请选择父级节点"
check-strictly
filterable
@node-click="(node) => riskScoreFormData.pLevel = node.level"
/>
</el-form-item>
<el-form-item
label="一级指标"
prop="riskIndex"
:rules="{
required: true,
message: '请选择一级值班',
}"
v-if="riskScoreFormData.pLevel === 1"
>
<el-select clearable v-model="riskScoreFormData.riskIndex">
<el-option
v-for="item in dict.riskIndex"
:key="item.id"
:label="item.dictLabel"
:value="item.dictValue"
/>
</el-select>
</el-form-item>
<el-form-item
label="风险因素"
prop="riskName"
:rules="{
required: true,
message: '请输入风险因素',
}"
>
<el-input
v-model="riskScoreFormData.riskName"
placeholder="请输入"
clearable
/>
</el-form-item>
<el-form-item label="因素分值" prop="score">
<el-input
v-model="riskScoreFormData.score"
placeholder="请输入序号"
type="number"
clearable
/>
</el-form-item>
<el-form-item label="赋分规则" prop="ruleDesc">
<el-input
v-model="riskScoreFormData.ruleDesc"
placeholder="请输入序号"
type="textarea"
clearable
/>
</el-form-item>
<el-form-item label="因素权重" prop="weight">
<el-input
v-model="riskScoreFormData.weight"
placeholder="请输入权重"
type="number"
clearable
/>
</el-form-item>
</el-form>
<footer class="flex end">
<el-button @click="riskScoreShow = false">取消</el-button>
<el-button type="primary" @click="submitRiskScoreRule">确定</el-button>
</footer>
</el-dialog>
<!-- 问题赋分编辑对话框 -->
<el-dialog
v-model="dictContentShow"
:title="dictContentMode === 'add' ? '新增问题类型' : '编辑问题类型'"
width="600"
>
<el-form label-width="120" ref="dictContentFormRef" :model="dictContentFormData">
<el-form-item
label="父级节点"
:rules="{
required: true,
message: '请选择父级节点',
}"
prop="parentCode"
>
<el-tree-select
class="flex-1"
v-model="dictContentFormData.parentCode"
:data="dictContentOptions"
clearable
node-key="id"
:props="{
label: 'name',
}"
:default-expanded-keys="[DICT_CONTENT_ROOT_ID]"
placeholder="请选择父级节点"
check-strictly
filterable
/>
</el-form-item>
<el-form-item
label="问题条目"
prop="name"
:rules="{
required: true,
message: '请输入问题条目',
}"
>
<el-input
v-model="dictContentFormData.name"
placeholder="请输入问题条目"
clearable
/>
</el-form-item>
<el-form-item label="基础分值" prop="score" v-if="dictContentFormData.parentCode != DICT_CONTENT_ROOT_ID">
<el-input
v-model="dictContentFormData.score"
placeholder="请输入序号"
type="number"
clearable
/>
</el-form-item>
<el-form-item label="序号" prop="sort">
<el-input
v-model="dictContentFormData.sort"
placeholder="请输入序号"
type="number"
clearable
/>
</el-form-item>
<el-form-item
label="问题严重等级"
prop="isActiveLevel"
:rules="{
required: true,
message: '请选择问题严重等级',
trigger: ['blur'],
}"
>
<el-switch
v-model="dictContentFormData.isActiveLevel"
inline-prompt
active-text="开启"
inactive-text="关闭"
:active-value="true"
:inactive-value="false"
/>
</el-form-item>
</el-form>
<footer class="flex end">
<el-button @click="dictContentShow = false">取消</el-button>
<el-button type="primary" @click="submitDictContent">确定</el-button>
</footer>
</el-dialog>
</div>
</template>
<script lang="ts" setup>
import { ref, watch, onMounted } from 'vue';
import { BASE_PATH } from "@/api/request";
import feedback from "@/utils/feedback";
import useCatchStore from "@/stores/modules/catch";
import { MENU_ROOT_ID } from "@/enums/appEnums";
import { DICT_CONTENT_ROOT_ID } from "@/enums/appEnums";
import { calculateScore } from "@/api/work/negative";
//
import {
listRiskScoreRuleTreeOld,
addRiskScoreRule,
updateRiskScoreRule,
delRiskScoreRule,
} from "@/api/sensitivePerception/riskScoreRule";
//
import {
listDictContentTree,
addDictContent,
updateDictContent,
delDictContent,
} from "@/api/system/dictContent";
//
const activeTab = ref('riskScoreRule');
//
const riskScoreLoading = ref(false);
const scoreRules = ref([]);
const treeOptions = ref([
{
id: MENU_ROOT_ID,
riskName: "顶级",
children: [],
},
]);
const riskScoreShow = ref(false);
const riskScoreFormData = ref({});
const riskScoreFormRef = ref();
const riskScoreMode = ref<string>("add");
//
const dictContentLoading = ref(false);
const dictContents = ref([]);
const dictContentOptions = ref([
{
id: DICT_CONTENT_ROOT_ID,
name: "顶级",
children: [],
},
]);
const dictContentShow = ref(false);
const dictContentFormData = ref({});
const dictContentFormRef = ref();
const dictContentMode = ref<string>("add");
//
const catchStore = useCatchStore();
const dict = catchStore.getDicts(["riskIndex"]);
//
//
function getRiskScoreList() {
riskScoreLoading.value = true;
listRiskScoreRuleTreeOld().then((data) => {
scoreRules.value = data;
treeOptions.value[0].children = data.map((item) => {
return {
id: item.id,
riskName: item.riskName,
level: item.level
};
});
riskScoreLoading.value = false;
});
}
//
watch(riskScoreMode, (val) => {
if (val === "add") {
riskScoreFormData.value = {};
if (riskScoreFormRef.value) {
riskScoreFormRef.value.resetFields();
}
}
});
//
async function submitRiskScoreRule() {
await riskScoreFormRef.value.validate();
if (riskScoreMode.value === "add") {
await addRiskScoreRule(riskScoreFormData.value);
const parentCode = riskScoreFormData.value.parentCode;
riskScoreFormData.value = {};
riskScoreFormRef.value.resetFields();
riskScoreFormData.value.parentCode = parentCode;
} else {
await updateRiskScoreRule(riskScoreFormData.value);
}
riskScoreShow.value = false;
getRiskScoreList();
}
//
function handleAddRiskScoreRule() {
riskScoreShow.value = true;
riskScoreMode.value = "add";
}
//
function handleEditRiskScoreRule(row) {
riskScoreShow.value = true;
riskScoreMode.value = "edit";
riskScoreFormData.value = { ...row };
}
//
const handleDeleteRiskScoreRule = async (row) => {
await feedback.confirm(`确定要删除 "${row.name}"?`);
await delRiskScoreRule(row.id);
getRiskScoreList();
feedback.msgSuccess("删除成功");
};
//
function getChildWeightSum(row) {
const arr = row.children
.filter((item) => item.status)
.map((item) => item.weight || 0);
if (arr.length === 0) {
return 0;
}
return arr.reduce((a, b) => a + b).toFixed(2);
}
//
//
function getDictContentList() {
dictContentLoading.value = true;
listDictContentTree().then((data) => {
dictContents.value = data;
dictContentOptions.value[0].children = data;
dictContentLoading.value = false;
});
}
//
watch(dictContentMode, (val) => {
if (val === "add") {
dictContentFormData.value = {};
if (dictContentFormRef.value) {
dictContentFormRef.value.resetFields();
}
}
});
//
async function submitDictContent() {
await dictContentFormRef.value.validate();
if (dictContentMode.value === "add") {
await addDictContent(dictContentFormData.value);
const parentCode = dictContentFormData.value.parentCode;
dictContentFormData.value = {};
dictContentFormRef.value.resetFields();
dictContentFormData.value.parentCode = parentCode;
} else {
await updateDictContent(dictContentFormData.value);
}
dictContentShow.value = false;
getDictContentList();
}
//
function handleAddDictContent() {
dictContentShow.value = true;
dictContentMode.value = "add";
}
//
function handleEditDictContent(row) {
dictContentShow.value = true;
dictContentMode.value = "edit";
dictContentFormData.value = { ...row };
}
//
const handleDeleteDictContent = async (row) => {
await feedback.confirm(`确定要删除 "${row.name}"?`);
await delDictContent(row.id);
getDictContentList();
feedback.msgSuccess("删除成功");
};
//
function getScoreRange(row) {
const sorceSet = new Set();
row.children.forEach((item) => {
if (item.score) {
sorceSet.add(item.score);
}
item.children.forEach((j) => {
if (j.score) {
sorceSet.add(j.score);
}
});
});
if (sorceSet.size === 0) {
return ''
}
if (sorceSet.size === 1) {
return sorceSet.values().next().value
}
const min = Math.min(...sorceSet);
const max = Math.max(...sorceSet);
return `${min}-${max}`
}
//
async function handleCalculateDictContent() {
await feedback.confirm("确定要重新计算风险指数?");
dictContentLoading.value = true
await calculateScore()
feedback.msgSuccess("风险指数计算完成");
dictContentLoading.value = false
}
//
onMounted(() => {
getRiskScoreList();
getDictContentList();
});
</script>
<style lang="scss" scoped>
.file-link {
font-size: 16px;
text-decoration: none;
color: #19257d;
padding: 0 8px;
border-radius: 8px;
&:hover {
background-color: #eee;
}
}
.tab-content {
background: #fff;
padding: 20px;
border-radius: 8px;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
}
header {
margin-bottom: 20px;
}
.table-container {
margin-bottom: 20px;
}
.flex {
display: flex;
}
.between {
justify-content: space-between;
}
.v-center {
align-items: center;
}
.mt-10 {
margin-top: 10px;
}
.mb-10 {
margin-bottom: 10px;
}
.mb-20 {
margin-bottom: 20px;
}
.mt-40 {
margin-top: 40px;
}
.gap {
gap: 8px;
}
.text-primary {
color: #1989fa;
}
.end {
justify-content: flex-end;
}
</style>
<!-- 这是ai生成的页面 -->
Loading…
Cancel
Save