效果
代码:
index.vue
<template>
<div class="pageBox">
<div class="oneLineBox">
<div class="fourColorImgBox">
<div class="titleBox">企业风险四色图</div>
<div class="contentBox">
<picView></picView>
</div>
</div>
<div class="riskStatisticsBox">
<div class="titleBox">风险统计</div>
<div class="contentBox">
<div class="selectGroupBox">
<div class="categoryBox">
<span>风险类别: </span>
<a-select
v-model:value="RiskPointType"
@change="changePointType"
>
<a-select-option value="Device">设备设施</a-select-option>
<a-select-option value="Operation">作业活动</a-select-option>
<a-select-option value="ProcessNode">工业节点</a-select-option>
</a-select>
</div>
<div class="gradeBox">
<span>风险等级: </span>
<a-select
v-model:value="RiskLevelType"
@change="changeLeveType"
>
<a-select-option value="">全部</a-select-option>
<a-select-option value="ExtremeRisk">重大风险</a-select-option>
<a-select-option value="LargerRisk">较大风险</a-select-option>
<a-select-option value="GeneralRisk">一般风险</a-select-option>
<a-select-option value="LowRisk">低风险</a-select-option>
</a-select>
</div>
</div>
<div :class="!piedata.length ? 'emptyBox' : ''">
<riskStatistics
:piedata="piedata"
v-if="piedata.length"
:allCounts="allCounts"
></riskStatistics>
<a-empty
v-else
:image="Empty.PRESENTED_IMAGE_SIMPLE"
class="ant-empty-normal"
/>
</div>
</div>
</div>
<div class="riskStatisticsGroup">
<a-tabs
@change="changeTab"
v-model:activeKey="activeKey"
:tabBarStyle="{ paddingLeft: '20px' }"
>
<a-tab-pane key="department" tab="部门风险统计"></a-tab-pane>
<a-tab-pane key="regional" tab="区域风险统计"></a-tab-pane>
</a-tabs>
<div class="contentBox">
<div class="selectBox">
<span
>{{ activeKey == "department" ? "主管部门" : "区域" }}:
</span>
<a-select
@click="openDepartment"
:open="false"
v-model:value="selectVal"
></a-select>
</div>
<div :class="departData.obj.length==0 ? 'emptyBox' : ''">
<riskStatisticsGroup :departData="departData" v-if="departData.obj.length!=0"></riskStatisticsGroup>
<a-empty
v-else
:image="Empty.PRESENTED_IMAGE_SIMPLE"
class="ant-empty-normal"
/>
</div>
</div>
<modealForm
ref="modelFormR"
@setParentRegionalValue="setParentRegionalValue"
:FormStatekey="FormStatekey"
:api1="getRegionTree"
:api2="getViolationOrganizationRoot"
:api3="getViolationOrganization"
/>
<!-- <div class="departmentRiskBox">
<div class="titleBox">部门风险统计</div>
<div class="contentBox">部门风险统计图</div>
</div>
<div class="regionalRiskBox">
<div class="titleBox">区域风险统计</div>
<div class="contentBox">区域风险统计图</div>
</div> -->
</div>
</div>
<div class="twoLineBox">
<div class="riskNoticeBox">
<div class="titleBox">重大风险公示</div>
<div class="contentBox">
<TableList
:loading="loading"
ref="tablistRef"
:hasImport="false"
:hasExport="false"
@getData="getData"
:columns="columns"
:MaxResultCount="8"
></TableList>
</div>
</div>
<div class="byLawBox">
<div class="titleBox">规章制度公示</div>
<div class="contentBox">
<TableList
:loading="byLawloading"
ref="byLawtablistRef"
:hasImport="false"
:hasExport="false"
@getData="byLawgetData"
:columns="byLawcolumns"
:showHeader="false"
:MaxResultCount="10"
>
<template #customtable="{ column, record }">
<template v-if="column.key === 'icon'">
<file-word-outlined
style="color: #1683ff"
v-if="
findFileType(record.FilePath[0]?.DisPlayName) == '.doc' ||
findFileType(record.FilePath[0]?.DisPlayName) == '.docx'
" />
<file-ppt-outlined
style="color: #f57b11"
v-if="
findFileType(record.FilePath[0]?.DisPlayName) == '.ppt' ||
findFileType(record.FilePath[0]?.DisPlayName) == '.pptx'
" />
<file-excel-outlined
style="color: #15c34f"
v-if="
findFileType(record.FilePath[0]?.DisPlayName) == '.xlsx' ||
findFileType(record.FilePath[0]?.DisPlayName) == '.xLs'
" />
<file-pdf-outlined
style="color: #e83c35"
v-if="
findFileType(record.FilePath[0]?.DisPlayName) == '.pdf'
"
/></template>
</template>
<template #operation="{ column, record }">
<!-- <a> 预览</a>
<a-divider type="vertical" /> -->
<a @click="downLoadEvent(record)"> 下载</a>
</template></TableList
>
</div>
</div>
<div class="activityScoreBox">
<div class="titleBox">作业活动对比</div>
<div class="contentBox">
<div class="selectBox">
<span>区域:</span>
<a-select
@click="openRegional"
:open="false"
v-model:value="workVal"
></a-select>
</div>
<div :class="workData.obj.length==0 ? 'emptyBox' : ''">
<activityScore :workData="workData" v-if="workData.obj.length!=0"></activityScore>
<a-empty
v-else
:image="Empty.PRESENTED_IMAGE_SIMPLE"
class="ant-empty-normal"
/>
</div>
</div>
</div>
</div>
</div>
</template>
<script setup>
import { findFileType } from "@/utils/function/index.js";
import { message, Modal, Empty } from "ant-design-vue";
import { onMounted, ref, reactive } from "vue";
import modealForm from "./components/modalForm.vue";
import {
getActivityScore,
getDepartMarge,
getRegionMarge,
} from "@/api/activityScore.js";
import { getRegionTree } from "@/api/regional";
import {
getViolationOrganizationRoot,
getViolationOrganization,
} from "@/api/uacapi";
import riskStatisticsGroup from "./components/riskStatisticsGroup.vue";
import activityScore from "./components/activityScore.vue";
import TableList from "@/components/ComtableListR.vue";
import { majorRisk, byLaw } from "@/api/home.js";
import picView from "@/components/Whiteboard/homePic.vue";
import { getRiskIchnography } from "@/api/riskHazardControl";
const simpleImage = Empty.PRESENTED_IMAGE_SIMPLE;
import axios from "axios";
// onMounted(() => {
// getData();
// byLawgetData();
// getDataRisk();
// });
// 风险统计
import riskStatistics from "./components/riskStatistics.vue";
import { getRiskStatistics } from "@/api/riskStatistics.js";
const RiskPointType = ref("Device");
const RiskLevelType = ref("");
const piedata = ref([]);
const allCounts = ref(0);
const changePointType = () => {
getDataRisk();
};
const changeLeveType = () => {
getDataRisk();
};
const selectVal = ref();
const selectId = ref();
const workVal = ref();
const workId = ref("");
const getRegion = async () => {
const res = await getRegionTree();
workId.value = res.ChildrenNodes[0].CurrentNode.Id;
workVal.value = res.ChildrenNodes[0].CurrentNode.DisplayName;
};
const cDname = ref();
const cDId = ref();
const getDepart = async () => {
const id = await getViolationOrganizationRoot();
const res = await getViolationOrganization({ id: id.items[0].id });
cDname.value = res.currentNode.name;
cDId.value = res.currentNode.id;
selectId.value = res.currentNode.id;
selectVal.value = res.currentNode.name;
};
const getDataRisk = () => {
getRiskStatistics({
RiskPointType: RiskPointType.value,
RiskLevelType: RiskLevelType.value,
})
.then((res) => {
piedata.value = res.map(function (item) {
return {
name: item.RiskPointStatisticGroupName,
value:
RiskLevelType.value == "ExtremeRisk"
? item.ExtremeCount
: RiskLevelType.value == "LargerRisk"
? item.LargerCount
: RiskLevelType.value == "GeneralRisk"
? item.GeneralCount
: RiskLevelType.value == "LowRisk"
? item.LowCount
: item.TotalCount,
};
});
allCounts.value = res.reduce((prev, cur) => {
return (
prev +
Number(
RiskLevelType.value == "ExtremeRisk"
? cur.ExtremeCount
: RiskLevelType.value == "LargerRisk"
? cur.LargerCount
: RiskLevelType.value == "GeneralRisk"
? cur.GeneralCount
: RiskLevelType.value == "LowRisk"
? cur.LowCount
: cur.TotalCount
)
);
}, 0);
})
.catch((err) => {
console.log(err);
});
};
// onMounted(() => {
// getData();
// //
// });
// 重大风险公告
// const riskCurrentPage = ref(1); //分页
let loading = ref(false);
let tablistRef = ref();
const columns = [
{
title: "风险点",
dataIndex: "DisplayName",
ellipsis: true,
key: "DisplayName",
align: "center",
},
{
title: "所属区域",
dataIndex: "RiskRegion",
key: "RiskRegion",
align: "center",
ellipsis: true,
customRender: ({ text }) => text?.DisplayName,
},
{
title: "管辖部门",
dataIndex: "ChargeOrganization",
key: "ChargeOrganization",
align: "center",
ellipsis: true,
customRender: ({ text }) => text?.DisplayName,
},
{
title: "主管人",
dataIndex: "ChargeUser",
key: "ChargeUser",
align: "center",
ellipsis: true,
customRender: ({ text }) => text?.DisplayName,
},
];
let pageobj = reactive({ MaxResultCount: 8, SkipCount: 0 });
const getData = async (from, param2) => {
if (param2) {
pageobj.MaxResultCount = param2?.pageSize ? param2?.pageSize : 8;
pageobj.SkipCount =
((param2?.current ? param2?.current : 1) - 1) *
(param2?.pageSize ? param2?.pageSize : 8);
}
let params = {
CurrentRiskLevelType: "ExtremeRisk",
SkipCount: pageobj.SkipCount,
MaxResultCount: pageobj.MaxResultCount,
};
loading.value = true;
const res = await majorRisk(params);
if (res.Items.length === 0 && pageobj.SkipCount > 0) {
pageobj.SkipCount = pageobj.SkipCount - pageobj.MaxResultCount;
tablistRef.value.setpage({
current: pageobj.SkipCount / pageobj.MaxResultCount + 1,
pageSize: pageobj.MaxResultCount,
});
getData();
}
loading.value = false;
tablistRef.value.getData([...res.Items], Number(res.TotalCount));
};
// 部门风险统计、区域风险统计
let activeKey = ref("department");
// 点击选择器打开弹层
const modelFormR = ref(null);
let FormStatekey = ref("");
const openDepartment = () => {
if (activeKey.value == "department") {
modelFormR.value.selectDeclare("", "ViolationOrganization");
FormStatekey.value = "ViolationOrganization";
} else {
modelFormR.value.selectDeclare("", "ViolationArea");
FormStatekey.value = "ViolationArea";
}
};
const openRegional = () => {
modelFormR.value.selectDeclare("", "ViolationArea");
FormStatekey.value = "workArea";
};
//弹窗点击确定
const setParentRegionalValue = (param, userModal) => {
if (FormStatekey.value != "workArea") {
selectId.value = param[0].id;
selectVal.value = param[0].name;
getDepartData();
} else {
workVal.value = param[0].name;
workId.value = param[0].id;
getWorkData();
}
};
//切换tab清空选中值
const changeTab = (val) => {
if (activeKey.value == "regional") {
selectVal.value = workVal.value;
selectId.value = workId.value;
} else {
selectId.value = cDId.value;
selectVal.value = cDname.value;
}
getDepartData();
};
const workData = reactive({ obj: [] });
const getWorkData = async () => {
workData.obj = await getActivityScore({ RiskRegionId: workId.value });
};
const departData = reactive({ obj: [] });
const getDepartData = async () => {
if (activeKey.value == "department") {
departData.obj = await getDepartMarge({
RiskOrganizationId: selectId.value,
});
} else {
departData.obj = await getRegionMarge({ RiskRegionId: selectId.value });
}
// console.log(departData.obj);
};
// 规章制度公告
let byLawloading = ref(false);
let byLawtablistRef = ref();
const byLawcolumns = [
{
title: "图标",
dataIndex: "icon",
key: "icon",
align: "right",
width: 20,
},
{
title: "文件名",
dataIndex: "FilePath",
ellipsis: true,
key: "FilePath",
align: "left",
customRender: ({ text }) => text[0].DisPlayName,
},
{
title: "操作",
dataIndex: "operation",
key: "operation",
align: "right",
width: 60,
},
];
let byLawpageobj = reactive({ MaxResultCount: 10, SkipCount: 0 });
const byLawgetData = async (from, param2) => {
if (param2) {
byLawpageobj.MaxResultCount = param2?.pageSize ? param2?.pageSize : 10;
byLawpageobj.SkipCount =
((param2?.current ? param2?.current : 1) - 1) *
(param2?.pageSize ? param2?.pageSize : 10);
}
let params = {
IsTop: true,
SkipCount: byLawpageobj.SkipCount,
MaxResultCount: byLawpageobj.MaxResultCount,
};
loading.value = true;
const res = await byLaw(params);
if (res.Items.length === 0 && byLawpageobj.SkipCount > 0) {
byLawpageobj.SkipCount =
byLawpageobj.SkipCount - byLawpageobj.MaxResultCount;
byLawtablistRef.value.setpage({
current: byLawpageobj.SkipCount / byLawpageobj.MaxResultCount + 1,
pageSize: byLawpageobj.MaxResultCount,
});
byLawgetData();
}
loading.value = false;
byLawtablistRef.value.getData([...res.Items], Number(res.TotalCount));
};
const downLoadEvent = (param2) => {
//下载操作
if (
Array.isArray(param2.FilePath) &&
param2?.FilePath?.length &&
param2?.FilePath[0]?.FileId
) {
axios
.get(
window.defaultconfig.fileUrl +
"/api/FileManage/Download" +
`?Id=${param2.FilePath[0].FileId}`,
{ responseType: "arraybuffer" }
)
.then((res) => {
const blob = new Blob([res.data], { type: "application/vnd.ms-excel" });
const objectUrl = URL.createObjectURL(blob);
const a = document.createElement("a");
a.download = param2.FilePath[0].DisPlayName;
a.href = objectUrl;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
})
.catch((error) => {
message.error("系统异常,请联系管理员");
});
} else {
message.error("文件不存在,无法下载");
}
};
onMounted(async () => {
getData();
byLawgetData();
getDataRisk();
await getDepart();
await getRegion();
await getWorkData();
await getDepartData();
});
</script>
<style lang="less" scoped>
:deep(.ant-empty) {
margin-top: 50px;
}
.pageBox {
display: flex;
flex-wrap: wrap;
.oneLineBox {
width: 100%;
display: flex;
justify-content: space-around;
.fourColorImgBox {
flex: 1;
background-color: #fff;
// padding: 10px;
border: solid 1px #e8e8e8;
margin-right: 10px;
margin-bottom: 10px;
overflow: hidden;
.contentBox {
padding: 0 10px;
}
}
.riskStatisticsBox {
flex: 1;
background-color: #fff;
// padding: 10px;
border: solid 1px #e8e8e8;
margin-right: 10px;
margin-bottom: 10px;
.ant-empty-normal {
margin: auto;
width: 100%;
}
.contentBox {
height: 100%;
}
.emptyBox {
height: 80%;
display: flex;
}
.selectGroupBox {
display: flex;
margin-left: 3%;
.categoryBox {
flex: 0 0 40%;
flex-wrap: nowrap;
display: flex;
align-items: center;
}
.gradeBox {
flex: 0 0 40%;
flex-wrap: nowrap;
display: flex;
align-items: center;
}
}
}
.riskStatisticsGroup {
flex: 1;
background-color: #fff;
// padding: 0 10px 10px;
border: solid 1px #e8e8e8;
margin-bottom: 10px;
.contentBox {
height: 100%;
margin: 0 10px 10px;
.selectBox {
text-align: right;
}
}
.ant-empty-normal {
margin: auto;
width: 100%;
}
.emptyBox {
height: 80%;
display: flex;
}
}
}
.twoLineBox {
width: 100%;
display: flex;
justify-content: space-around;
.riskNoticeBox {
flex: 1;
background-color: #fff;
// padding: 10px;
border: solid 1px #e8e8e8;
margin-right: 10px;
margin-bottom: 10px;
.contentBox {
padding: 0 18px;
}
}
.byLawBox {
flex: 1;
background-color: #fff;
// padding: 10px;
border: solid 1px #e8e8e8;
margin-right: 10px;
margin-bottom: 10px;
.contentBox {
padding: 0 18px;
}
}
.activityScoreBox {
flex: 1;
background-color: #fff;
// padding: 10px;
border: solid 1px #e8e8e8;
margin-bottom: 10px;
.ant-empty-normal {
margin: auto;
width: 100%;
}
.emptyBox {
height: 80%;
display: flex;
}
.contentBox {
// padding: 0 10px 0 10px;
// margin: 0 10px 10px;
height: 80%;
padding-left: 20px;
.selectBox {
margin-right: 10px;
text-align: right;
}
}
}
}
// 公共样式
.titleBox {
padding: 12px 20px;
border-bottom: solid 1px #f0f0f0;
margin-bottom: 16px;
font-size: 16px;
}
:deep(.ant-select-selector) {
min-width: 120px;
}
.tableBox {
margin-top: 0 !important;
:deep(.ant-table-wrapper) {
min-height: auto !important;
}
}
:deep(.ant-tabs-tab) {
font-size: 16px !important;
}
}
</style>
riskStatisticsGroup.vue
<template>
<div id="main" style="height: 400px"></div>
</template>
<script setup>
import { onMounted, nextTick, ref, watch } from "vue";
import * as echarts from "echarts";
import { Empty } from "ant-design-vue";
const simpleImage = Empty.PRESENTED_IMAGE_SIMPLE;
const props = defineProps({
departData: {
type: Object,
default: () => {},
},
});
const xdata = ref([]);
const dataFirst = ref([]);
const dataSec = ref([]);
const dataThist = ref([]);
const dataFour = ref([]);
function loaddata(data1, data2, data3, data4, data5) {
nextTick(() => {
var chartDom = document.getElementById("main");
var myChart = echarts.init(chartDom);
var option;
window.addEventListener("resize", () => {
// 监听浏览器窗口大小改变
// 浏览器变化执行动作
if (myChart) {
myChart.resize();
}
});
option = {
dataZoom: [
{
type: "slider",
realtime: true, // 拖动时,是否实时更新系列的视图
startValue: 0,
endValue: 5,
width: 5,
height: "90%",
top: "5%",
right: 0,
// orient: 'vertical', // 设置横向还是纵向, 但是官方不太建议如此使用,建议使用 yAxisIndex 具体指明
yAxisIndex: [0, 1], // 控制y轴滚动对象
fillerColor: "#0093ff", // 滚动条颜色
borderColor: "rgba(17, 100, 210, 0.12)",
backgroundColor: "#cfcfcf", //两边未选中的滑动条区域的颜色
handleSize: 0, // 两边手柄尺寸
showDataShadow: false, //是否显示数据阴影 默认auto
showDetail: false, // 拖拽时是否展示滚动条两侧的文字
zoomLock: true,
moveHandleStyle: {
opacity: 0,
},
},
{
type: "inside",
// width: 0,
startValue: 0,
endValue: 10,
minValueSpan: 10,
yAxisIndex: [0],
zoomOnMouseWheel: false, // 关闭滚轮缩放
moveOnMouseWheel: true, // 开启滚轮平移
moveOnMouseMove: true, // 鼠标移动能触发数据窗口平移
},
],
title: {
text: "",
},
tooltip: {
trigger: "axis",
axisPointer: {
type: "shadow",
},
},
legend: {
x: "center",
y: "bottom",
// pageIconSize: 8,
// itemWidth: 18,
// itemHeight: 8
type: "scroll",
},
grid: {
top: "3%",
left: "3%",
right: "15%",
bottom: "13%",
containLabel: true,
},
xAxis: {
name: "数量(个)",
nameLocation: "end",
type: "value",
show: true,
minInterval: 1,
axisTick: {
alignWithLabel: true,
},
axisTick: {
show: true, // 不显示坐标轴刻度线
},
axisLine: {
show: true, // 不显示坐标轴线
},
axisLabel: {
show: true, // 不显示坐标轴上的文字
},
splitLine: {
show: true, // 不显示网格线
},
},
yAxis: {
type: "category",
data: data1,
},
series: [
{
name: "重大风险",
type: "bar",
data: data2,
color: "#ff0000",
},
{
name: "较大风险",
type: "bar",
data: data3,
color: "#ff6100",
},
{
name: "一般风险",
type: "bar",
data: data4,
color: "#ffff00",
},
{
name: "低风险",
type: "bar",
data: data5,
color: "#0000ff",
},
],
};
option && myChart.setOption(option);
});
}
watch(
() => props.departData,
() => {
xdata.value = [];
dataFirst.value = [];
dataSec.value = [];
dataThist.value = [];
dataFour.value = [];
props.departData.obj.forEach((e) => {
xdata.value.push(e.RiskPointStatisticGroupName);
dataFirst.value.push(e.ExtremeCount);
dataSec.value.push(e.LargerCount);
dataThist.value.push(e.GeneralCount);
dataFour.value.push(e.LowCount);
// ydata.value.push(e.Score);
});
loaddata(
xdata.value,
dataFirst.value,
dataSec.value,
dataThist.value,
dataFour.value
);
},
{ deep: true, immediate: true }
);
</script>
<style lang="less" scoped>
// #main {
// margin-top: 16px;
// height: 400px !important;
// }
</style>
activityScore.vue
<template>
<div id="activeId"></div>
</template>
<script setup>
import { onMounted, nextTick, ref, watch } from "vue";
import * as echarts from "echarts";
import { Empty } from "ant-design-vue";
const simpleImage = Empty.PRESENTED_IMAGE_SIMPLE;
const props = defineProps({
workData: {
type: Object,
default: () => {},
},
});
const xdata = ref([]);
const ydata = ref([]);
// console.log(333, props.workData.obj);
// props.workData.obj.forEach((e) => {
// console.log(444, e);
// });
// props.workData((item) => {
// });
function loaddata(data1, data2) {
nextTick(() => {
var chartDom = document.getElementById("activeId");
var myChart = echarts.init(chartDom);
var option;
window.addEventListener("resize", () => {
// 监听浏览器窗口大小改变
// 浏览器变化执行动作
if (myChart) {
myChart.resize();
}
});
option = {
grid: {
top: "3%",
left: "3%",
right: "15%",
bottom: "13%",
containLabel: true,
},
dataZoom: [
{
type: "slider",
realtime: true, // 拖动时,是否实时更新系列的视图
startValue: 0,
endValue: 5,
width: 5,
height: "90%",
top: "5%",
right: 0,
// orient: 'vertical', // 设置横向还是纵向, 但是官方不太建议如此使用,建议使用 yAxisIndex 具体指明
yAxisIndex: [0, 1], // 控制y轴滚动对象
fillerColor: "#0093ff", // 滚动条颜色
borderColor: "rgba(17, 100, 210, 0.12)",
backgroundColor: "#cfcfcf", //两边未选中的滑动条区域的颜色
handleSize: 0, // 两边手柄尺寸
showDataShadow: false, //是否显示数据阴影 默认auto
showDetail: false, // 拖拽时是否展示滚动条两侧的文字
zoomLock: true,
moveHandleStyle: {
opacity: 0,
},
},
{
type: "inside",
// width: 0,
startValue: 0,
endValue: 10,
minValueSpan: 10,
yAxisIndex: [0],
zoomOnMouseWheel: false, // 关闭滚轮缩放
moveOnMouseWheel: true, // 开启滚轮平移
moveOnMouseMove: true, // 鼠标移动能触发数据窗口平移
},
],
yAxis: {
type: "category",
data: data1,
},
xAxis: {
type: "value",
name: "分值", //名称。
show: true,
minInterval: 1,
axisTick: {
show: true, // 不显示坐标轴刻度线
},
axisLine: {
show: true, // 不显示坐标轴线
},
axisLabel: {
show: true, // 不显示坐标轴上的文字
},
splitLine: {
show: true, // 不显示网格线
},
},
color: ["#5494f2"],
series: [
{
data: data2,
type: "bar",
},
],
};
option && myChart.setOption(option);
});
}
watch(
() => props.workData,
() => {
xdata.value = [];
ydata.value = [];
props.workData.obj.forEach((e) => {
xdata.value.push(e.RiskPointName);
ydata.value.push(e.Score);
});
loaddata(xdata.value, ydata.value);
},
{ deep: true, immediate: true }
);
</script>
<style lang="less" scoped>
#activeId {
height: 300px;
margin-top: 16px;
// margin-left: 10px;
// padding-left:10px ;
// box-sizing: border-box;
}
</style>
另一个饼图组件在上上篇文章