You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
543 lines
15 KiB
543 lines
15 KiB
|
5 months ago
|
<template>
|
||
|
|
<div class="address_edit">
|
||
|
|
<!-- 导航栏 -->
|
||
|
|
<!-- <div class="header_body">
|
||
|
|
<header-nav
|
||
|
|
:slefBack="true"
|
||
|
|
@goBack="goBack"
|
||
|
|
:titelText="`统计分析`"
|
||
|
|
>
|
||
|
|
</header-nav>
|
||
|
|
</div> -->
|
||
|
|
<!-- 中间 -->
|
||
|
|
<div class="warp_body">
|
||
|
|
<div class="countbox">
|
||
|
|
<span class="count-tit">本月执法</span>
|
||
|
|
<span class="count-tot"><b>{{ data.allTotal }}</b>件</span>
|
||
|
|
<span class="count-com"><i>投诉:</i><b>{{ data.complaintCount }}</b>件</span>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="analybox">
|
||
|
|
<div class="title">执法类别</div>
|
||
|
|
<div id="echartRing" class="chartbox"></div>
|
||
|
|
<div id="echartLine" class="chartbox"></div>
|
||
|
|
</div>
|
||
|
|
<div class="analybox">
|
||
|
|
<div class="title">执法人员</div>
|
||
|
|
<div id="echartLineUser" class="chartbox" style="height: 10rem;"></div>
|
||
|
|
</div>
|
||
|
|
<div class="analybox">
|
||
|
|
<div class="title">案件数量</div>
|
||
|
|
<div id="echarCount" class="chartbox"></div>
|
||
|
|
</div>
|
||
|
|
<div class="analybox">
|
||
|
|
<div class="title">企业类型</div>
|
||
|
|
<div id="echartLineCompany" class="chartbox"></div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
</div>
|
||
|
|
|
||
|
|
</div>
|
||
|
|
</template>
|
||
|
|
|
||
|
|
<script setup name="addressEdit">
|
||
|
|
|
||
|
|
import {onBeforeUnmount} from 'vue';
|
||
|
|
import util from "@/util/area";
|
||
|
|
import {queryStatisticalData} from '@/api/enforce';
|
||
|
|
import * as echarts from 'echarts';
|
||
|
|
|
||
|
|
const {useCommon, useShopCard} = $globalStore;
|
||
|
|
const router = useRouter();
|
||
|
|
const route = useRoute();
|
||
|
|
let queryaddressId = ref("");
|
||
|
|
const data = reactive({
|
||
|
|
searchResult: [],
|
||
|
|
areaList: util.areaList,
|
||
|
|
addressInfo: {},
|
||
|
|
areaColumns: ["请选择", "请选择", "请选择"],
|
||
|
|
allTotal: 0,
|
||
|
|
complaintCount: 0
|
||
|
|
});
|
||
|
|
|
||
|
|
// 返回
|
||
|
|
const goBack = () => {
|
||
|
|
router.go(-1);
|
||
|
|
};
|
||
|
|
|
||
|
|
onBeforeUnmount(() => {
|
||
|
|
// 当前路由不是首页,且用户确认离开时
|
||
|
|
router.replace('/enforceHome'); // 替换到首页
|
||
|
|
});
|
||
|
|
|
||
|
|
onUnmounted(() => {
|
||
|
|
console.log("=============销毁完毕=============")
|
||
|
|
const chartEle = document.getElementById("echartRing");
|
||
|
|
console.log(chartEle)
|
||
|
|
// chartEle.removeAttribute('_echarts_instance_')
|
||
|
|
});
|
||
|
|
|
||
|
|
// 保存地址操作
|
||
|
|
const onSave = () => {
|
||
|
|
router.replace({name: "addressList"});
|
||
|
|
};
|
||
|
|
|
||
|
|
// 删除地址操作
|
||
|
|
const onDelete = () => {
|
||
|
|
router.replace({name: "addressList"});
|
||
|
|
};
|
||
|
|
|
||
|
|
// 修改详细地址
|
||
|
|
const onChangeDetail = () => {
|
||
|
|
};
|
||
|
|
|
||
|
|
const echartInit = (data, targetId) => {
|
||
|
|
var container = document.getElementById(targetId);
|
||
|
|
var myChart = echarts.getInstanceByDom(container);
|
||
|
|
if (myChart) {
|
||
|
|
myChart.dispose();
|
||
|
|
}
|
||
|
|
myChart = echarts.init(document.getElementById(targetId));
|
||
|
|
// 指定图表的配置项和数据
|
||
|
|
let option = {
|
||
|
|
tooltip: {
|
||
|
|
trigger: 'item'
|
||
|
|
},
|
||
|
|
series: [
|
||
|
|
{
|
||
|
|
name: '统计图表',
|
||
|
|
type: 'pie',
|
||
|
|
silent: true, // 设置所有的点击事件为静默模式
|
||
|
|
radius: ['33%', '50%'],
|
||
|
|
avoidLabelOverlap: false,
|
||
|
|
itemStyle: {
|
||
|
|
borderRadius: 0,
|
||
|
|
borderColor: '#fff',
|
||
|
|
borderWidth: 1
|
||
|
|
},
|
||
|
|
emphasis: {
|
||
|
|
label: {
|
||
|
|
show: true,
|
||
|
|
fontSize: '14',
|
||
|
|
fontWeight: 'bold'
|
||
|
|
}
|
||
|
|
},
|
||
|
|
label: {
|
||
|
|
normal: {
|
||
|
|
show: true,
|
||
|
|
position: 'outside', // 标签显示在外部
|
||
|
|
formatter: '{b}\n{c} ({d}%)', // 标签格式化,b是数据名,c是数值,d是百分比
|
||
|
|
textStyle: {
|
||
|
|
fontSize: 14,
|
||
|
|
rich: {
|
||
|
|
a: {
|
||
|
|
width: 100,
|
||
|
|
overflow: 'truncate', // 文字超出宽度时截断
|
||
|
|
textOverflow: 'ellipsis', // 文字超出宽度时显示省略号
|
||
|
|
},
|
||
|
|
},
|
||
|
|
},
|
||
|
|
},
|
||
|
|
},
|
||
|
|
// ... 其他配置项
|
||
|
|
data: data,
|
||
|
|
color: ['#0038bb', '#0047eb', '#1c60ff', '#3f78ff', '#6592ff', '#8aadff'],
|
||
|
|
}
|
||
|
|
]
|
||
|
|
};
|
||
|
|
// 使用刚指定的配置项和数据显示图表。
|
||
|
|
myChart.setOption(option);
|
||
|
|
};
|
||
|
|
|
||
|
|
const initSchedule = (dataAll, targetId) => {
|
||
|
|
var container = document.getElementById(targetId);
|
||
|
|
var myChartLine = echarts.getInstanceByDom(container);
|
||
|
|
if (myChartLine) {
|
||
|
|
myChartLine.dispose();
|
||
|
|
}
|
||
|
|
myChartLine = echarts.init(document.getElementById(targetId));
|
||
|
|
let myColor = ['#3C83FF']
|
||
|
|
var option = {
|
||
|
|
tooltip: {
|
||
|
|
trigger: 'item',
|
||
|
|
},
|
||
|
|
grid: { // 直角坐标系内绘图网格
|
||
|
|
top: '-5%',
|
||
|
|
bottom: '5%',
|
||
|
|
left: '25%', //grid 组件离容器左侧的距离,
|
||
|
|
//left的值可以是80这样具体像素值,
|
||
|
|
//也可以是'80%'这样相对于容器高度的百分比
|
||
|
|
right: '25%',
|
||
|
|
//containLabel: true //gid区域是否包含坐标轴的刻度标签。为true的时候,
|
||
|
|
// left/right/top/bottom/width/height决定的是包括了坐标轴标签在内的
|
||
|
|
//所有内容所形成的矩形的位置.常用于【防止标签溢出】的场景
|
||
|
|
},
|
||
|
|
xAxis: { //直角坐标系grid中的x轴,
|
||
|
|
//一般情况下单个grid组件最多只能放上下两个x轴,
|
||
|
|
//多于两个x轴需要通过配置offset属性防止同个位置多个x轴的重叠。
|
||
|
|
type: 'value', //坐标轴类型,分别有:
|
||
|
|
//'value'-数值轴;'category'-类目轴;
|
||
|
|
//'time'-时间轴;'log'-对数轴
|
||
|
|
splitLine: {
|
||
|
|
show: false
|
||
|
|
}, //坐标轴在 grid 区域中的分隔线
|
||
|
|
axisLabel: {
|
||
|
|
show: false
|
||
|
|
}, //坐标轴刻度标签
|
||
|
|
axisTick: {
|
||
|
|
show: false
|
||
|
|
}, //坐标轴刻度
|
||
|
|
axisLine: {
|
||
|
|
show: false
|
||
|
|
}, //坐标轴轴线
|
||
|
|
},
|
||
|
|
yAxis: {
|
||
|
|
type: 'category',
|
||
|
|
axisTick: {
|
||
|
|
show: false
|
||
|
|
},
|
||
|
|
axisLine: {
|
||
|
|
show: false
|
||
|
|
},
|
||
|
|
axisLabel: {
|
||
|
|
color: 'rgba(0,0,0,.7)',
|
||
|
|
fontSize: 14,
|
||
|
|
formatter: function (data) {
|
||
|
|
var traceValue;
|
||
|
|
for (var i = 0; i < dataAll.dataX.length; i++) {
|
||
|
|
if (data === dataAll.dataX[i]) {
|
||
|
|
traceValue = dataAll.dataY[i]
|
||
|
|
break
|
||
|
|
}
|
||
|
|
}
|
||
|
|
var arr = [
|
||
|
|
'{a|' + data + '}',
|
||
|
|
'{b|' + traceValue + '}',
|
||
|
|
'{c|件}'
|
||
|
|
]
|
||
|
|
return arr.join('')
|
||
|
|
},
|
||
|
|
formatter: function (params) {
|
||
|
|
var maxLength = 6;
|
||
|
|
//判断长度,超出使用...代替
|
||
|
|
if (params && params.length > maxLength) {
|
||
|
|
return params.substring(0, maxLength - 1) + '.';
|
||
|
|
} else {
|
||
|
|
return params;
|
||
|
|
}
|
||
|
|
},
|
||
|
|
textStyle: {
|
||
|
|
rich: {
|
||
|
|
a: {
|
||
|
|
fontSize: 14,
|
||
|
|
//width: 100
|
||
|
|
},
|
||
|
|
b: {
|
||
|
|
fontSize: 14,
|
||
|
|
align: 'center',
|
||
|
|
color: '#3C83FF',
|
||
|
|
fontWeight: 600,
|
||
|
|
},
|
||
|
|
c: {
|
||
|
|
padding: [0, 0, 0, 5],
|
||
|
|
fontSize: 14,
|
||
|
|
align: 'center',
|
||
|
|
}
|
||
|
|
}
|
||
|
|
},
|
||
|
|
},
|
||
|
|
data: dataAll.dataX //类目数据,在类目轴(type: 'category')中有效。
|
||
|
|
//如果没有设置 type,但是设置了axis.data,则认为type 是 'category'。
|
||
|
|
},
|
||
|
|
series: [ //系列列表。每个系列通过 type 决定自己的图表类型
|
||
|
|
{
|
||
|
|
name: '', //系列名称
|
||
|
|
type: 'bar', //柱状、条形图
|
||
|
|
silent: true, // 设置所有柱子的点击事件为静默模式
|
||
|
|
barWidth: 15, //柱条的宽度,默认自适应
|
||
|
|
data: dataAll.dataPercent, //系列中数据内容数组
|
||
|
|
label: { //图形上的文本标签
|
||
|
|
show: true,
|
||
|
|
position: 'right', //标签的位置
|
||
|
|
offset: [0, 40], //标签文字的偏移,此处表示向上偏移40
|
||
|
|
//formatter: '{c}{a}',//标签内容格式器 {a}-系列名,{b}-数据名,{c}-数据值
|
||
|
|
formatter: function (data) {
|
||
|
|
//.toFixed(0)去掉小数位,如果为2就是保留两位小数
|
||
|
|
//let b = data.percent.toFixed(0) + "%";
|
||
|
|
//subText = b;
|
||
|
|
return '';
|
||
|
|
},
|
||
|
|
color: 'rgba(0,0,0,.7)', //标签字体颜色
|
||
|
|
fontSize: 26 //标签字号
|
||
|
|
},
|
||
|
|
itemStyle: { //图形样式
|
||
|
|
normal: { //normal 图形在默认状态下的样式;
|
||
|
|
//emphasis图形在高亮状态下的样式
|
||
|
|
barBorderRadius: 10, //柱条圆角半径,单位px.
|
||
|
|
//此处统一设置4个角的圆角大小;
|
||
|
|
//也可以分开设置[10,10,10,10]顺时针左上、右上、右下、左下
|
||
|
|
color: function (params) {
|
||
|
|
let num = myColor.length; //得到myColor颜色数组的长度
|
||
|
|
return myColor[params.dataIndex % num]; //返回颜色数组中的一个对应的颜色值
|
||
|
|
},
|
||
|
|
}
|
||
|
|
},
|
||
|
|
dataZoom: [
|
||
|
|
{
|
||
|
|
type: 'inside', // 设置为 inside 类型
|
||
|
|
orient: 'vertical', // 设置为垂直滚动条
|
||
|
|
start: 0,
|
||
|
|
end: 100,
|
||
|
|
left: "93%",
|
||
|
|
yAxisIndex: [0],
|
||
|
|
}
|
||
|
|
],
|
||
|
|
zlevel: 1 //柱状图所有图形的 zlevel 值,
|
||
|
|
//zlevel 大的 Canvas 会放在 zlevel 小的 Canvas 的上面
|
||
|
|
},
|
||
|
|
{
|
||
|
|
name: '',
|
||
|
|
type: 'bar',
|
||
|
|
silent: true, // 设置所有柱子的点击事件为静默模式
|
||
|
|
label: { //图形上的文本标签
|
||
|
|
show: true,
|
||
|
|
position: 'right', //标签的位置
|
||
|
|
offset: [0, 0], //标签文字的偏移,此处表示向上偏移40
|
||
|
|
//formatter: '{c}{a}',//标签内容格式器 {a}-系列名,{b}-数据名,{c}-数据值
|
||
|
|
formatter: function (data) {
|
||
|
|
//.toFixed(0)去掉小数位,如果为2就是保留两位小数
|
||
|
|
var traceValue;
|
||
|
|
for (var i = 0; i < dataAll.dataX.length; i++) {
|
||
|
|
if (data.name === dataAll.dataX[i]) {
|
||
|
|
traceValue = dataAll.dataPercent[i]
|
||
|
|
break
|
||
|
|
}
|
||
|
|
}
|
||
|
|
var arr = [
|
||
|
|
'{a|' + traceValue + '}',
|
||
|
|
'{b|%}'
|
||
|
|
]
|
||
|
|
return arr.join('');
|
||
|
|
},
|
||
|
|
textStyle: {
|
||
|
|
rich: {
|
||
|
|
a: {
|
||
|
|
fontSize: 14,
|
||
|
|
color: 'rgba(0,0,0,0.7)',
|
||
|
|
fontWeight: 560,
|
||
|
|
padding: [0, 0, 0, 15],
|
||
|
|
},
|
||
|
|
b: {
|
||
|
|
fontSize: 14,
|
||
|
|
color: 'rgba(0,0,0,0.7)',
|
||
|
|
padding: [0, 0, 0, 3],
|
||
|
|
align: 'center',
|
||
|
|
},
|
||
|
|
}
|
||
|
|
},
|
||
|
|
},
|
||
|
|
barGap: '-100%', //不同系列的柱间距离,为百分比。
|
||
|
|
// 在同一坐标系上,此属性会被多个 'bar' 系列共享。
|
||
|
|
// 此属性应设置于此坐标系中最后一个 'bar' 系列上才会生效,
|
||
|
|
//并且是对此坐标系中所有 'bar' 系列生效。
|
||
|
|
barWidth: 15,
|
||
|
|
data: dataAll.dataSum,
|
||
|
|
|
||
|
|
color: '#DEE0E3', //柱条颜色
|
||
|
|
itemStyle: {
|
||
|
|
normal: {
|
||
|
|
barBorderRadius: 10
|
||
|
|
}
|
||
|
|
}
|
||
|
|
},
|
||
|
|
|
||
|
|
]
|
||
|
|
};
|
||
|
|
myChartLine.setOption(option, true);
|
||
|
|
};
|
||
|
|
|
||
|
|
const initData = (dataX, dataY, dataPercent, targetId) => {
|
||
|
|
|
||
|
|
// var dataX = ['生态环境执法', '卫生健康执法', '商务领域执法', '财务领域执法', '水务领域执法']
|
||
|
|
// var dataY = ['30', '20', '15', '25', '10'];
|
||
|
|
// var dataPercent = ['30', '20', '15', '25', '10'];
|
||
|
|
var dataSum = new Array(dataX.length).fill(100);
|
||
|
|
var data = {
|
||
|
|
dataX: dataX,
|
||
|
|
dataY: dataY,
|
||
|
|
dataSum: dataSum,
|
||
|
|
dataPercent: dataPercent,
|
||
|
|
}
|
||
|
|
initSchedule(data, targetId);
|
||
|
|
};
|
||
|
|
|
||
|
|
|
||
|
|
onMounted(() => {
|
||
|
|
|
||
|
|
queryStatisticalData({
|
||
|
|
"dataScopeId": useCommon.userId
|
||
|
|
}, success => {
|
||
|
|
var arrData = [];
|
||
|
|
var arrCompanyData = [];
|
||
|
|
var countTotal = 0;
|
||
|
|
var userTotal = 0;
|
||
|
|
//执法类别参数
|
||
|
|
var dataX = [];
|
||
|
|
var dataY = [];
|
||
|
|
var dataPercent = [];
|
||
|
|
//执法人员
|
||
|
|
var userDataX = [];
|
||
|
|
var userDataY = [];
|
||
|
|
var userDataPercent = [];
|
||
|
|
|
||
|
|
//本月案件数量
|
||
|
|
var arrCountData = [];
|
||
|
|
|
||
|
|
console.log(success.data.item)
|
||
|
|
|
||
|
|
success.data.item.forEach(res => {
|
||
|
|
countTotal += res.total;
|
||
|
|
})
|
||
|
|
success.data.lawEnforcer.forEach(res => {
|
||
|
|
userTotal += res.total;
|
||
|
|
})
|
||
|
|
success.data.item.forEach(res => {
|
||
|
|
console.log(res)
|
||
|
|
arrData.push({
|
||
|
|
"name": res.lawEnforcementItem,
|
||
|
|
"value": res.total
|
||
|
|
})
|
||
|
|
dataX.push(res.lawEnforcementItem);
|
||
|
|
dataY.push(res.total);
|
||
|
|
dataPercent.push((res.total / countTotal * 100).toFixed(2));
|
||
|
|
})
|
||
|
|
|
||
|
|
success.data.lawEnforcer.forEach(res => {
|
||
|
|
console.log(res)
|
||
|
|
userDataX.push(res.lawEnforcer);
|
||
|
|
userDataY.push(res.total);
|
||
|
|
userDataPercent.push((res.total / userTotal * 100).toFixed(2));
|
||
|
|
})
|
||
|
|
console.log(userDataPercent)
|
||
|
|
success.data.enterpriseType.forEach(res => {
|
||
|
|
console.log(res)
|
||
|
|
arrCompanyData.push({
|
||
|
|
"name": res.dictLabel,
|
||
|
|
"value": res.total
|
||
|
|
})
|
||
|
|
})
|
||
|
|
data.allTotal = success.data.mouth.total;
|
||
|
|
data.complaintCount = success.data.mouth.complaintCount;
|
||
|
|
arrCountData.push({
|
||
|
|
"name": "本月执法数量",
|
||
|
|
"value": data.allTotal
|
||
|
|
})
|
||
|
|
arrCountData.push({
|
||
|
|
"name": "本月执法投诉数量",
|
||
|
|
"value": data.complaintCount
|
||
|
|
})
|
||
|
|
|
||
|
|
nextTick(() => {
|
||
|
|
echartInit(arrData, 'echartRing');
|
||
|
|
//执法类别统计
|
||
|
|
initData(dataX, dataY, dataPercent, "echartLine");
|
||
|
|
//执法人员
|
||
|
|
initData(userDataX, userDataY, userDataPercent, "echartLineUser");
|
||
|
|
//企业类型统计
|
||
|
|
echartInit(arrCompanyData, 'echartLineCompany');
|
||
|
|
//本月案件数量
|
||
|
|
echartInit(arrCountData, 'echarCount');
|
||
|
|
});
|
||
|
|
}, error => {
|
||
|
|
})
|
||
|
|
|
||
|
|
});
|
||
|
|
</script>
|
||
|
|
|
||
|
|
|
||
|
|
<style lang="less" scoped>
|
||
|
|
.address_edit {
|
||
|
|
display: flex;
|
||
|
|
flex-direction: column;
|
||
|
|
height: 100%;
|
||
|
|
overflow: hidden;
|
||
|
|
background-color: #ebf3fb;
|
||
|
|
}
|
||
|
|
|
||
|
|
.warp_body {
|
||
|
|
background-image: linear-gradient(to bottom, #ebf3fb, transparent);
|
||
|
|
margin-top: 0.15rem;
|
||
|
|
}
|
||
|
|
|
||
|
|
.countbox, .analybox {
|
||
|
|
position: relative;
|
||
|
|
margin: 2% 3%;
|
||
|
|
padding: 2% 0 0;
|
||
|
|
width: 94%;
|
||
|
|
height: 3rem;
|
||
|
|
background: #fff url("../../assets/images/bg_count.jpg") no-repeat right;
|
||
|
|
background-size: auto 100%;
|
||
|
|
border-radius: 0.25rem;
|
||
|
|
}
|
||
|
|
|
||
|
|
.countbox span {
|
||
|
|
display: block;
|
||
|
|
margin: 1.75% 4.5%;
|
||
|
|
color: #999;
|
||
|
|
font-size: 0.3rem;
|
||
|
|
line-height: 1.25;
|
||
|
|
}
|
||
|
|
|
||
|
|
.countbox span.count-tit {
|
||
|
|
color: #666;
|
||
|
|
font-size: 0.40rem;
|
||
|
|
}
|
||
|
|
|
||
|
|
.countbox span.count-tot {
|
||
|
|
font-size: 0.3rem;
|
||
|
|
|
||
|
|
b {
|
||
|
|
margin-right: 0.15rem;
|
||
|
|
color: #085dff;
|
||
|
|
font-size: 0.85rem;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
.countbox span.count-com {
|
||
|
|
float: right;
|
||
|
|
margin-top: -0.1rem;
|
||
|
|
font-size: 0.3rem;
|
||
|
|
|
||
|
|
i {
|
||
|
|
font-size: 0.4rem;
|
||
|
|
font-style: normal;
|
||
|
|
}
|
||
|
|
|
||
|
|
b {
|
||
|
|
margin-right: 5px;
|
||
|
|
color: #f00;
|
||
|
|
font-size: 0.6rem;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
.analybox {
|
||
|
|
height: auto;
|
||
|
|
min-height: 7rem;
|
||
|
|
background: #fff none;
|
||
|
|
|
||
|
|
.title {
|
||
|
|
margin: 2% 2.5%;
|
||
|
|
font-size: 0.42rem;
|
||
|
|
font-weight: 600;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
.chartbox {
|
||
|
|
margin: 2% 5% 3%;
|
||
|
|
width: 90%;
|
||
|
|
height: 7rem;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
</style>
|