<template>
|
<div class="container" ref="Container">
|
<div class="case-box" ref="caseBox">
|
<div class="box">
|
<div class="title" ref="alertBoxTitle">
|
<div>值班信息(当日)</div>
|
</div>
|
<div class="table-box">
|
<el-table size="small" :height="tableHeight" :data="schedulingList" style="width: 100%"
|
:header-cell-style="{ 'text-align': 'center' }"
|
:cell-style="{ 'text-align': 'center', 'borderColor': '#324e75' }"
|
:row-class-name="tableRowClassName">
|
<el-table-column prop="station" label="岗位"></el-table-column>
|
<el-table-column prop="name" label="姓名"></el-table-column>
|
<el-table-column prop="contact" label="联系方式"></el-table-column>
|
</el-table>
|
</div>
|
</div>
|
|
<svg class="border-svg">
|
<use stroke-width="2" xlink:href="#border-box-8-path-974b4d7cfafa444396861ca1d1173c8c"
|
mask="url(#border-box-8-mask-974b4d7cfafa444396861ca1d1173c8c)" stroke="#4fd2dd">
|
<animate attributeName="stroke-dasharray" from="0, 1442" to="1442, 0" dur="8s"
|
repeatCount="indefinite" />
|
</use>
|
</svg>
|
</div>
|
|
<div class="alert-box" ref="alertBox ">
|
<div class="box">
|
<div class="title">
|
案件统计
|
<div class="timer">
|
<el-date-picker :clearable="false" v-model="eventTime" type="daterange" align="right"
|
unlink-panels range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期"
|
@change="caseTimeChange" :picker-options="pickerOptions"></el-date-picker>
|
</div>
|
</div>
|
<div id="EventChangeEcharts" class="echarts-box"></div>
|
</div>
|
|
<svg class="border-svg">
|
<use stroke-width="2" xlink:href="#border-box-8-path-974b4d7cfafa444396861ca1d1173c8c"
|
mask="url(#border-box-8-mask-974b4d7cfafa444396861ca1d1173c8c)" stroke="#4fd2dd">
|
<animate attributeName="stroke-dasharray" from="0, 1442" to="1442, 0" dur="8s"
|
repeatCount="indefinite" />
|
</use>
|
</svg>
|
</div>
|
|
<!-- <div class="alert-box" ref="alertBox">
|
<div class="title" ref="alertBoxTitle">
|
<div>安保活动</div>
|
<div class="title-tab">
|
<span :class="{ choosed: acttype == 0 }" @click="actTabClick(0)">正在进行</span>/
|
<span :class="{ choosed: acttype == 1 }" @click="actTabClick(1)">历史活动</span>
|
</div>
|
</div>
|
<div id="peopleList" class="echarts-box">
|
<el-table
|
size="small"
|
:height="tableHeight"
|
:data="acttype == 0 ? underwayArr : historyArr"
|
style="width: 100%"
|
:header-cell-style="{ 'text-align': 'center', 'background-color': '#203c60', 'borderColor': '#324e75' }"
|
:cell-style="{ 'text-align': 'center', 'borderColor': '#324e75' }"
|
:row-class-name="tableRowClassName"
|
ref="activityTable"
|
@row-click="activityRowClick"
|
>
|
<el-table-column prop="activityName" label="活动名称"></el-table-column>
|
<el-table-column prop="startTime" label="开始时间"></el-table-column>
|
<el-table-column prop="endTime" label="结束时间"></el-table-column>
|
<el-table-column prop="scale" label="规模"></el-table-column>
|
</el-table>
|
</div>
|
</div>-->
|
|
<div class="crowd-box" ref="crowdBox">
|
<div class="box">
|
<div class="title">
|
<div>现有设备</div>
|
<div class="title-tab">
|
<span :class="{ choosed: linetype == 0 }" @click="lineTabClick(0)">设备种类</span>/
|
<span :class="{ choosed: linetype == 1 }" @click="lineTabClick(1)">设备状态</span>
|
</div>
|
</div>
|
<div style="overflow: hidden;" id="EquipmentEcharts" class="echarts-box"></div>
|
</div>
|
|
<svg class="border-svg">
|
<use stroke-width="2" xlink:href="#border-box-8-path-974b4d7cfafa444396861ca1d1173c8c"
|
mask="url(#border-box-8-mask-974b4d7cfafa444396861ca1d1173c8c)" stroke="#4fd2dd">
|
<animate attributeName="stroke-dasharray" from="0, 1442" to="1442, 0" dur="8s"
|
repeatCount="indefinite" />
|
</use>
|
</svg>
|
</div>
|
</div>
|
</template>
|
|
<script>
|
const oneColor = ['#4caf50', '#2979ff', '#ffd600', '#0d47a1', '#b71c1c']
|
const twoColor = ['#5470FE', '#91cc75', '#fac858', '#ee6666', '#73c0de', '#3ba272', '#fc8452', '#9a60b4', '#ea7ccc']
|
|
let equipmentmyChart
|
let eventchangemychart
|
let timer
|
let equimentDataLength = 0
|
|
import recorderArr from '@/assets/data/equimentsDate/recorder.js'
|
import { getSchedulingList } from '@/api/home/index.js'
|
import { fontSize } from '@/utils/fontSize.js'
|
|
import { getCaseAll, getEquipment } from "@/api/home/index.js"
|
|
const timeEvents = []
|
|
export default {
|
inject: ['userInfo'],
|
|
data () {
|
return {
|
eventTime: [],
|
pickerOptions: {
|
shortcuts: [{
|
text: '最近一周',
|
onClick (picker) {
|
const end = new Date()
|
const start = new Date()
|
start.setTime(start.getTime() - 3600 * 1000 * 24 * 7)
|
picker.$emit('pick', [start, end])
|
}
|
}, {
|
text: '最近一个月',
|
onClick (picker) {
|
const end = new Date()
|
const start = new Date()
|
start.setTime(start.getTime() - 3600 * 1000 * 24 * 30)
|
picker.$emit('pick', [start, end])
|
}
|
}, {
|
text: '最近三个月',
|
onClick (picker) {
|
const end = new Date()
|
const start = new Date()
|
start.setTime(start.getTime() - 3600 * 1000 * 24 * 90)
|
picker.$emit('pick', [start, end])
|
}
|
}]
|
},
|
regionTotal: 0,
|
linetype: 0,
|
tableHeight: 0,
|
schedulingList: [],
|
|
}
|
},
|
created () {
|
this.pickerOptions = {
|
...this.pickerOptions,
|
disabledDate (time) {
|
// 设置可选择的日期为今天之后的一个月内
|
let curDate = (new Date()).getTime()
|
return time.getTime() > curDate
|
}
|
}
|
|
this.defaultDate()
|
|
this.getSchedulingList()
|
},
|
|
mounted () {
|
this.initEquipmentEcharts()
|
this.initEventChangeEcharts()
|
this.clickEquimentChart()
|
|
this.$nextTick(() => {
|
window.addEventListener("resize", this.echartsResize)
|
this.tableHeight = this.$refs.Container.offsetHeight - this.$refs.caseBox.offsetHeight - this.$refs.crowdBox.offsetHeight - this.$refs.alertBoxTitle.offsetHeight - 62
|
})
|
|
},
|
methods: {
|
// actTabClick (type) {
|
// this.acttype = type
|
// this.$refs.activityTable.bodyWrapper.scrollTop = 0
|
// this.$emit('changeActivityType', type)
|
// this.$emit('activityChange')
|
// },
|
|
getSchedulingList () {
|
getSchedulingList().then(res => {
|
this.schedulingList = res.data.data.records
|
})
|
},
|
|
echartsResize () {
|
equipmentmyChart && equipmentmyChart != null && equipmentmyChart.resize()
|
eventchangemychart && eventchangemychart != null && eventchangemychart.resize()
|
},
|
|
// 案件统计中时间变化
|
async caseTimeChange (e) {
|
const date = e.map(item => {
|
return this.dateFormat(item)
|
})
|
|
eventchangemychart.clear()
|
const optionsData = await this.getCaseAll(date[0], date[1])
|
eventchangemychart.setOption(this.initEventChangeOption(optionsData.xData, optionsData.yData))
|
},
|
|
// 设置默认时间
|
defaultDate () {
|
var current = new Date()
|
|
var seven = new Date(current.getTime() - 7 * 24 * 60 * 60 * 1000)
|
|
this.eventTime = [seven, current] //将值设置给插件绑定的数据
|
},
|
|
// 获取当前日期
|
dateFormat (dateData) {
|
var date = new Date(dateData)
|
var y = date.getFullYear()
|
var m = date.getMonth() + 1
|
m = m < 10 ? ('0' + m) : m
|
var d = date.getDate()
|
d = d < 10 ? ('0' + d) : d
|
const time = y + '-' + m + '-' + d
|
return time
|
},
|
|
// 获取案件统计值
|
getCaseAll (start, end) {
|
const caseAll = getCaseAll(start, end, this.userInfo.dept_id).then(res => {
|
if (res.data.length > 0) {
|
return res.data.reduce((previous, current) => {
|
previous.xData.push(current.days)
|
previous.yData.push(current.cout)
|
return previous
|
}, { xData: [], yData: [] })
|
} else {
|
return { xData: [], yData: [] }
|
}
|
})
|
|
return caseAll
|
},
|
|
// 初始化案件统计
|
async initEventChangeEcharts () {
|
var chartDom = document.getElementById('EventChangeEcharts')
|
eventchangemychart = this.$echarts.init(chartDom)
|
|
const date = this.eventTime.map(item => {
|
return this.dateFormat(item)
|
})
|
|
const optionsData = await this.getCaseAll(date[0], date[1])
|
|
eventchangemychart.setOption(this.initEventChangeOption(optionsData.xData, optionsData.yData))
|
},
|
|
// 案件统计的options
|
initEventChangeOption (xData, yData) {
|
let option
|
if (xData.length == 0) { //暂无数据
|
option = {
|
title: {
|
text: '暂无数据',
|
x: 'center',
|
y: 'center',
|
textStyle: {
|
color: "#fff",
|
fontSize: fontSize(14),
|
fontWeight: 'normal',
|
}
|
}
|
}
|
} else {
|
option = {
|
tooltip: {
|
trigger: 'item',
|
formatter: ' <span style="display: inline-block; margin-right: 4px; border-radius: 10px; width: 10px; height: 10px;background-color: #91cc75;"></span> {b0}<strong style="margin-left:10px;color:#5c7bd9">{c0}起</strong>'
|
},
|
xAxis: {
|
type: 'category',
|
data: xData,
|
axisLabel: {
|
color: "#fff",
|
fontSize: fontSize(14)
|
},
|
axisLine: {
|
lineStyle: {
|
color: "#fff"
|
}
|
}
|
},
|
yAxis: {
|
type: 'value',
|
|
minInterval: 1,
|
|
splitLine: {
|
show: false
|
},
|
axisLabel: {
|
color: "#fff",
|
fontSize: fontSize(14)
|
},
|
axisLine: {
|
lineStyle: {
|
color: "#fff"
|
}
|
}
|
},
|
series: [
|
{
|
data: yData,
|
type: 'line',
|
smooth: true,
|
areaStyle: {
|
normal: {
|
//渐变色
|
color: new this.$echarts.graphic.LinearGradient(
|
0,
|
0,
|
0,
|
1,
|
[
|
{
|
//波形图渐变色样式
|
offset: 0,
|
color: "rgba(3, 108, 255, 0.7)"
|
},
|
{
|
offset: 0.8,
|
color: "rgba(3, 108, 255, 0.1)"
|
}
|
],
|
false
|
)
|
}
|
},
|
itemStyle: {
|
normal: {
|
color: 'red', //改变折线点的颜色
|
lineStyle: {
|
color: 'rgba(3, 108, 255, 1)' //改变折线颜色
|
}
|
}
|
}
|
}
|
],
|
grid: {
|
top: '4%',
|
left: '3%',
|
right: '2%',
|
bottom: '4%',
|
containLabel: true
|
},
|
}
|
}
|
|
return option
|
},
|
|
// 现有设备统计
|
getEquipment () {
|
const typeData = {
|
carCount: '警车',
|
monitorCount: '摄像头',
|
recorderCount: '手台',
|
phoneCount: '手持记录仪'
|
}
|
|
let data = []
|
this.regionTotal = 0
|
|
const dataAll = getEquipment().then(res => {
|
|
if (this.linetype == 0) {
|
data = res.data.map((item, index) => {
|
|
this.regionTotal += item.count
|
|
return {
|
equimentType: item.type == '车辆' ? 0 : 1,
|
name: item.type,
|
value: item.count,
|
working: item.online,
|
fault: item.offline,
|
label: twoColor[index]
|
}
|
})
|
|
equimentDataLength = data.length
|
|
return data
|
} else {
|
let normalData = { value: 0, name: '正常', color: '#4caf50', online: true, label: { color: oneColor[0] } }
|
let faultData = { value: 0, name: '故障', color: '#ffd600', online: false, label: { color: oneColor[2] } }
|
|
res.data.forEach(item => {
|
this.regionTotal += item.count
|
|
normalData.value += item.online
|
|
for (let key in typeData) {
|
if (item.type == typeData[key]) {
|
normalData[key] = item.online
|
faultData[key] = item.offline
|
}
|
}
|
|
faultData.value += item.offline
|
})
|
|
data = [normalData, faultData]
|
|
equimentDataLength = data.length
|
|
return data
|
}
|
})
|
|
return dataAll
|
},
|
|
// 设备种类,设备状态切换
|
async lineTabClick (type) {
|
this.linetype = type
|
|
const data = await this.getEquipment()
|
|
equipmentmyChart.setOption(this.initEquipmentOptions(data), true)
|
},
|
|
// 现有设备饼图初始化
|
async initEquipmentEcharts () {
|
var chartDom = document.getElementById('EquipmentEcharts')
|
equipmentmyChart = this.$echarts.init(chartDom)
|
|
const data = await this.getEquipment()
|
|
equipmentmyChart.setOption(this.initEquipmentOptions(data))
|
|
this.equipmentEchartsCarousel()
|
},
|
|
// 现有设备options饼图数据
|
initEquipmentOptions (dataArr) {
|
return {
|
tooltip: {
|
trigger: 'item',
|
confine: true,
|
formatter: function (params) {
|
let tipHtml = ``
|
|
if ('carCount' in params.data) {
|
tipHtml = `
|
${params.marker}
|
<strong style="color: ${params.color}">${params.data.name} ${params.data.value}台</strong>
|
<br />
|
<strong style="margin-left:10px;color:#5c7bd9">占比:${params.percent}%</strong>
|
<br />
|
<span style="color:#5470c6">警车:${params.data.carCount}台</span>
|
<br />
|
<span style="margin-left:10px;color:#91cc75">摄像头:${params.data.monitorCount}台</span>
|
`
|
} else {
|
tipHtml = `${params.marker} <strong style="color: ${params.color}">${params.data.name} ${params.data.value}台</strong><br /><span style="color:#4caf50">正常:${params.data.working}台</span><br /><span style="color:#ccc">故障:${params.data.fault}台</span><br /><span style="margin-left:10px;color:#ccc">设备故障率:${Math.floor(params.data.fault / (params.data.working + params.data.fault) * 100)}%</span><br />`
|
}
|
return tipHtml
|
},
|
backgroundColor: 'rgba(8, 56, 185, 0.9)',
|
borderColor: 'rgba(8, 56, 185, 0.9)',
|
textStyle: {
|
fontSize: fontSize(14)
|
}
|
},
|
graphic: {
|
type: "text",
|
// left: "36.5%",
|
top: "40%",
|
left: "center",
|
style: {
|
text: "设备总数",
|
textAlign: "center",
|
fill: "#fff",
|
fontSize: fontSize(18),
|
fontWeight: 700
|
}
|
},
|
title: {
|
text: `${this.regionTotal}`,
|
top: "52%",
|
left: "center",
|
textStyle: {
|
color: "#27D9C8",
|
fontSize: fontSize(20),
|
fontWeight: 700,
|
align: "center"
|
}
|
},
|
series: [
|
{
|
name: '',
|
type: 'pie',
|
radius: ['90%', '136%'],
|
top: 'middle',
|
left: 'center',
|
data: dataArr,
|
avoidLabelOverlap: false,
|
labelLine: {
|
normal: {
|
length: fontSize(15),
|
lineStyle: {
|
width: fontSize(3)
|
}
|
}
|
},
|
emphasis: {
|
label: {
|
color: 'red',
|
fontSize: fontSize(16)
|
}
|
},
|
label: {
|
color: function (params) {
|
let colorList = []
|
if ('carCount' in params.data) {
|
colorList = ['#4caf50', '#787878']
|
} else {
|
colorList = ['#5470FE', '#91cc75', '#fac858', '#ee6666', '#73c0de', '#3ba272', '#fc8452', '#9a60b4', '#ea7ccc']
|
}
|
return colorList[params.dataIndex]
|
},
|
fontSize: fontSize(16)
|
|
},
|
itemStyle: {
|
normal: {
|
color: function (params) {
|
let colorList = []
|
if ('carCount' in params.data) {
|
colorList = ['#4caf50', '#787878']
|
} else {
|
colorList = ['#5470FE', '#91cc75', '#fac858', '#ee6666', '#73c0de', '#3ba272', '#fc8452', '#9a60b4', '#ea7ccc']
|
}
|
return colorList[params.dataIndex]
|
}
|
}
|
}
|
}
|
]
|
}
|
},
|
|
// 饼图轮播
|
equipmentEchartsCarousel () {
|
let curIndex = 0
|
if (timer) {
|
clearInterval(timer)
|
}
|
|
timer = setInterval(() => {
|
equipmentmyChart.dispatchAction({ type: 'downplay', seriesIndex: 0, dataIndex: curIndex })
|
curIndex = (curIndex + 1) % equimentDataLength
|
equipmentmyChart.dispatchAction({
|
type: 'highlight', seriesIndex: 0, dataIndex: curIndex
|
})
|
}, 1000)
|
|
equipmentmyChart.on('mouseover', function (param) {
|
clearInterval(timer)
|
equipmentmyChart.dispatchAction({
|
type: 'downplay',
|
seriesIndex: 0,
|
dataIndex: curIndex
|
})
|
equipmentmyChart.dispatchAction({
|
type: 'highlight',
|
seriesIndex: 0,
|
dataIndex: param.dataIndex
|
})
|
curIndex = param.dataIndex
|
})
|
|
equipmentmyChart.on('mouseout', function (param) {
|
curIndex = param.dataIndex
|
if (timer) {
|
clearInterval(timer)
|
}
|
timer = setInterval(() => {
|
equipmentmyChart.dispatchAction({ type: 'downplay', seriesIndex: 0, dataIndex: curIndex })
|
curIndex = (curIndex + 1) % equimentDataLength
|
equipmentmyChart.dispatchAction({
|
type: 'highlight', seriesIndex: 0, dataIndex: curIndex
|
})
|
}, 1000)
|
})
|
},
|
|
// 现有设备的点击事件(显示弹窗表格)
|
clickEquimentChart () {
|
equipmentmyChart.on('click', params => {
|
// 设备类型,摄像头弹窗显示,其他弹窗显示,【记录仪列显示,警车列显示,手台列显示】,遍历数组
|
if (params.equimentType) {
|
this.$emit('showequimentdetail', params.name, params.equimentType, 'type')
|
} else {
|
this.$emit('showequimentdetail', params.name, params.equimentType, 'online')
|
}
|
})
|
},
|
},
|
|
destroyed () {
|
window.removeEventListener("resize", this.echartsResize)
|
|
if (equipmentmyChart) {
|
equipmentmyChart.dispose()
|
equipmentmyChart = null
|
}
|
|
if (eventchangemychart) {
|
eventchangemychart.dispose()
|
eventchangemychart = null
|
}
|
clearInterval(timer)
|
}
|
}
|
</script>
|
|
<style scoped lang="scss">
|
.container {
|
display: flex;
|
position: relative;
|
height: 100%;
|
width: 100%;
|
|
.case-box,
|
.alert-box,
|
.crowd-box {
|
position: relative;
|
margin: 8px;
|
flex: 1;
|
display: flex;
|
flex-direction: column;
|
// background: $bg-color;
|
|
background-image: url(/img/box/box-bg.png);
|
background-size: 100% 100%;
|
background-repeat: no-repeat;
|
|
// .title::after {
|
// content: '';
|
// position: absolute;
|
// top: 13px;
|
// left: 6px;
|
// width: 10px;
|
// height: 10px;
|
// border-radius: 50%;
|
// background: #43bafe;
|
// box-shadow: 0px 0px 8px 2px #43bafe;
|
// margin-left: 8px;
|
// }
|
|
.box {
|
display: flex;
|
position: absolute;
|
flex-direction: column;
|
top: 0;
|
left: 0;
|
width: 100%;
|
height: 100%;
|
z-index: 11;
|
}
|
|
.title {
|
display: flex;
|
align-items: center;
|
justify-content: space-between;
|
|
padding: 0 18px 0 18px;
|
position: relative;
|
|
font-size: 16px;
|
font-weight: bold;
|
font-style: oblique;
|
letter-spacing: 2px;
|
color: #fff;
|
// background-image: linear-gradient(to right, #2e4aba, #010d3e);
|
|
.title-tab {
|
color: #99cccc;
|
|
span {
|
cursor: pointer;
|
}
|
|
span.choosed {
|
color: #fff;
|
}
|
}
|
|
.timer {
|
width: 250px;
|
}
|
|
.regionTotal {
|
color: #fff;
|
font-size: 22px;
|
font-weight: 700;
|
margin-left: 50%;
|
letter-spacing: 1px;
|
}
|
}
|
|
.sub-title {
|
display: flex;
|
justify-content: space-between;
|
height: 36px;
|
}
|
|
.sub-tab {
|
padding: 10px;
|
display: flex;
|
|
.tab {
|
margin: 0 10px;
|
flex: 1;
|
background: $sub-tab-bg-color;
|
cursor: pointer;
|
|
&>div {
|
height: 26px;
|
line-height: 26px;
|
}
|
}
|
}
|
|
.echarts-box {
|
padding: 12px;
|
flex: 1;
|
}
|
|
.table-box {
|
padding: 0 12px;
|
flex: 1;
|
}
|
|
#peopleList {
|
height: 100%;
|
}
|
}
|
|
.alert-box {
|
margin-top: 0;
|
margin-bottom: 0;
|
|
.title {
|
height: 54px;
|
line-height: 54px;
|
}
|
|
.echarts-box {
|
overflow-x: hidden;
|
overflow-y: auto;
|
}
|
|
:deep(.el-table__header-wrapper) {
|
height: 40px;
|
}
|
}
|
|
.border-svg {
|
position: absolute;
|
top: 0;
|
left: 0;
|
width: 100%;
|
height: 100%;
|
z-index: 1;
|
}
|
}
|
</style>
|