3 changed files with 898 additions and 34 deletions
|
Before Width: | Height: | Size: 8.7 KiB After Width: | Height: | Size: 17 KiB |
@ -0,0 +1,542 @@ |
|||
<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> |
|||
Loading…
Reference in new issue