| | |
| | | import request from '@/utils/request' |
| | | |
| | | // 运维监控报表 |
| | | export function video(data) { |
| | | return request({ |
| | | url: '/home/video', |
| | | method: 'get', |
| | | params: data |
| | | }) |
| | | } |
| | | |
| | | // 运维监控报表 |
| | | export function car(data) { |
| | | return request({ |
| | | url: '/home/car', |
| | | method: 'get', |
| | | params: data |
| | | }) |
| | | } |
| | | |
| | | // 运维监控报表 |
| | | export function face(data) { |
| | | return request({ |
| | | url: '/home/face', |
| | | method: 'get', |
| | | params: data |
| | | }) |
| | | } |
| | | |
| | | // 运维公司下拉 |
| | | export function ywUnitList() { |
| | | return request({ |
| | |
| | | method: 'get', |
| | | params: { category } |
| | | }) |
| | | } |
| | | } |
New file |
| | |
| | | <template> |
| | | <div class="data-chart-container"> |
| | | <el-card class="data-card" :body-style="{ height: '100%' }"> |
| | | <div class="card-content"> |
| | | <div class="title-container"> |
| | | <h1>车辆报表</h1> |
| | | <div class="select-container"> |
| | | <el-select v-model="params.examineTag" placeholder="考核标签" @change="getChart" clearable> |
| | | <el-option v-for="item in options" :key="item.label" :label="item.label" :value="item.value"> |
| | | </el-option> |
| | | </el-select> |
| | | </div> |
| | | <div> |
| | | <el-date-picker v-model="date" format="yyyy-MM" value-format="yyyy-MM" type="month" placeholder="选择月份" |
| | | @change="dateChange"> |
| | | </el-date-picker> |
| | | </div> |
| | | </div> |
| | | <div class="chart-container"> |
| | | <div id="chartContent" ref="chartContent"></div> |
| | | </div> |
| | | </div> |
| | | </el-card> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import * as echarts from 'echarts'; |
| | | import {car} from "../../../api/platform/home"; |
| | | |
| | | var chartDom = document.getElementById('main'); |
| | | var myChart = echarts.init(chartDom); |
| | | var option; |
| | | let observer = null; |
| | | export default { |
| | | name: 'DataCar', |
| | | data() { |
| | | return { |
| | | date: '', |
| | | params: { |
| | | month: '', |
| | | }, |
| | | options: [ |
| | | {label: '省厅', value: 1}, |
| | | {label: '公安部', value: 2} |
| | | ], |
| | | dataList: [], |
| | | } |
| | | }, |
| | | methods: { |
| | | dateChange() { |
| | | this.params.date = this.date; |
| | | this.getChart(); |
| | | }, |
| | | getChart() { |
| | | this.loading = true; |
| | | myChart.showLoading() |
| | | car(this.params).then(res => { |
| | | myChart = echarts.init(this.$refs.chartContent); |
| | | this.initChart(res.data); |
| | | this.observe(); |
| | | }) |
| | | }, |
| | | groupByData(data) { |
| | | if (!data || data.length === 0) { |
| | | return this.getAllDay().map((item) => [item, []]); |
| | | } |
| | | const tempGroup = {}; |
| | | data.forEach((item) => { |
| | | let {createDate} = item; |
| | | let tempTime = createDate.split('-'); |
| | | createDate = tempTime[1] + '-' + tempTime[2]; |
| | | if (!tempGroup[createDate]) { |
| | | tempGroup[createDate] = []; |
| | | } |
| | | tempGroup[createDate].push(item); |
| | | }) |
| | | const tempArray = Object.entries(tempGroup).sort(([keyA], [keyB]) => new Date([keyA]) - new Date([keyB])); |
| | | return tempArray; |
| | | }, |
| | | getAllDay() { |
| | | const currentDate = this.date.split('-'); |
| | | const currentYear = currentDate[0]; |
| | | const currentMonth = currentDate[1]; |
| | | const daysInMonth = new Date(currentYear, currentMonth, 0).getDate(); |
| | | const datesOfMonth = []; |
| | | for (var day = 1; day <= daysInMonth; day++) { |
| | | const formattedDate = currentMonth + '-' + (day.toString().padStart(2, '0')); |
| | | datesOfMonth.push(formattedDate); |
| | | } |
| | | return datesOfMonth; |
| | | }, |
| | | initChart(data) { |
| | | const dataList = this.groupByData(data.list); |
| | | const baseLine = data.baseLine == null ? 0 : data.baseLine; |
| | | // 选择较大的值作为Y轴的最大值 |
| | | var snapCount |
| | | if (!data.list || data.list.length === 0) { |
| | | snapCount = 0; |
| | | }else { |
| | | snapCount = data.list[data.list.length - 1].snapCount |
| | | } |
| | | const yMax = Math.max(snapCount, baseLine * 1.2); |
| | | const colors = ['#5470C6', '#66CC99', '#EE6666']; |
| | | option = { |
| | | color: colors, |
| | | tooltip: { |
| | | trigger: "axis", // 鼠标移入到柱子里面就会有一个提示,默认是item方式,如果有多个柱状图,堆在一块item就不太好了,个人喜欢axis方式的 |
| | | axisPointer: { |
| | | type: 'cross', |
| | | label:{ |
| | | precision: 0 |
| | | } |
| | | }, |
| | | formatter: function (params) { |
| | | // 创建一个变量来存储最终的 HTML 字符串 |
| | | var tooltipHtml = ''; |
| | | |
| | | // 首先,添加分类名(或轴值)的显示 |
| | | if (params.length > 0) { |
| | | tooltipHtml += "<div style='padding:0 12px;width:100%;height:24px;line-height:24px;'><p>" + params[0].name + "</p></div>"; |
| | | } |
| | | |
| | | var pointsHtml = params.map(function (item) { |
| | | // 使用 toLocaleString() 来格式化 value |
| | | var formattedValue = item.value? item.value.toLocaleString() : '-'; |
| | | return `<div style="display: flex; align-items: center; font-size: 14px; padding: 0 12px; line-height: 24px;"> |
| | | <span style="display: inline-block; margin-right: 5px; border-radius: 2px; width: 10px; height: 10px; background-color: ${item.color || '#ccc'};"></span> |
| | | <span style="margin-right: 10px;">${item.seriesName}</span> |
| | | <span style="font-weight: bold;display: inline-block; min-width: 60px; margin-left: auto; text-align: right;">${formattedValue}</span> |
| | | </div>`; |
| | | }).join(''); |
| | | tooltipHtml = `${tooltipHtml}${pointsHtml}`; |
| | | tooltipHtml += `<div style="font-weight: bold; margin-top: 10px;padding:0 12px;">抓拍量参考值: ${baseLine.toLocaleString()}</div>`; |
| | | |
| | | return tooltipHtml; |
| | | } |
| | | }, |
| | | grid: { |
| | | left: 10, |
| | | right: 0, |
| | | bottom: 0, |
| | | top: '20%', |
| | | containLabel: true |
| | | }, |
| | | legend: { |
| | | data: ['点位在线', '抓拍量'] |
| | | }, |
| | | xAxis: [ |
| | | { |
| | | type: 'category', |
| | | axisTick: { |
| | | alignWithLabel: true |
| | | }, |
| | | data: dataList.map((item) => item[0]), |
| | | } |
| | | ], |
| | | yAxis: [ |
| | | { |
| | | type: 'value', |
| | | name: '点位数', |
| | | position: 'left', |
| | | alignTicks: true, |
| | | axisLine: { |
| | | show: true, |
| | | lineStyle: { |
| | | color: colors[0] |
| | | } |
| | | |
| | | }, |
| | | axisLabel: { |
| | | formatter: function (value) { |
| | | // 返回整数部分,或使用其他逻辑来格式化标签 |
| | | return Math.floor(value); |
| | | } |
| | | } |
| | | }, |
| | | { |
| | | type: 'value', |
| | | name: '抓拍量', |
| | | max: yMax, |
| | | min: 0, |
| | | position: 'right', |
| | | alignTicks: true, |
| | | axisLine: { |
| | | show: true, |
| | | lineStyle: { |
| | | color: colors[1] |
| | | } |
| | | }, |
| | | axisLabel: { |
| | | formatter: function (value) { |
| | | // 返回整数部分,或使用其他逻辑来格式化标签 |
| | | return Math.floor(value); |
| | | } |
| | | } |
| | | } |
| | | ], |
| | | series: [ |
| | | { |
| | | type: 'line', |
| | | yAxisIndex: 1, |
| | | markLine: { |
| | | symbol: 'none', |
| | | data: [ |
| | | { |
| | | yAxis: baseLine, // 自定义下限值 |
| | | name: '参考抓拍量', // 基准线名称 |
| | | label: { // 不显示基准线名称 |
| | | show: false, |
| | | }, |
| | | lineStyle: { |
| | | type: 'dashed', // 基准线样式为虚线 |
| | | color: '#b17063', |
| | | }, |
| | | }, |
| | | ], |
| | | }, |
| | | }, |
| | | { |
| | | name: '点位在线', |
| | | type: 'line', |
| | | yAxisIndex: 0, |
| | | color: colors[0], |
| | | tooltip: { |
| | | valueFormatter: function (value) { |
| | | return value; |
| | | } |
| | | }, |
| | | data: data.list.map(item => { |
| | | return item['online'] ? item['online'] : null; |
| | | }) |
| | | }, |
| | | { |
| | | name: '抓拍量', |
| | | type: 'bar', |
| | | yAxisIndex: 1, |
| | | color: colors[1], |
| | | tooltip: { |
| | | valueFormatter: function (value) { |
| | | return value; |
| | | } |
| | | }, |
| | | data: data.list.map(item => { |
| | | return item['snapCount'] ? item['snapCount'] : null; |
| | | }) |
| | | }, |
| | | ] |
| | | }; |
| | | |
| | | myChart.setOption(option); |
| | | myChart.hideLoading(); |
| | | }, |
| | | |
| | | // 监听变化 |
| | | observe() { |
| | | if (!observer) { |
| | | observer = new ResizeObserver(entries => { |
| | | this.handleResize(); |
| | | }) |
| | | } |
| | | observer.observe(this.$refs.chartContent); |
| | | }, |
| | | // 窗口变换 |
| | | handleResize() { |
| | | if (myChart) { |
| | | myChart.resize(); |
| | | } |
| | | } |
| | | |
| | | }, |
| | | mounted() { |
| | | const date = new Date(); |
| | | const year = date.getFullYear(); |
| | | const month = (date.getMonth() + 1) >= 10 ? date.getMonth() + 1 : '0' + (date.getMonth() + 1); |
| | | this.date = year + '-' + month; |
| | | this.params.date = this.date; |
| | | this.getChart(); |
| | | this.observe(); |
| | | }, |
| | | beforeDestroy() { |
| | | if (myChart) { |
| | | myChart.dispose(); |
| | | observer.unobserve(this.$refs.chartContent); |
| | | } |
| | | }, |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .data-chart-container { |
| | | height: 400px; |
| | | margin-bottom: 20px; |
| | | |
| | | .data-card { |
| | | height: 100%; |
| | | |
| | | .card-content { |
| | | width: 100%; |
| | | height: 100%; |
| | | position: relative; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .title-container { |
| | | position: absolute; |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | z-index: 2; |
| | | |
| | | .more-button { |
| | | cursor: pointer; |
| | | font-size: 16px; |
| | | padding: 0 10px; |
| | | } |
| | | } |
| | | |
| | | .chart-container { |
| | | |
| | | width: 100%; |
| | | height: 100%; |
| | | |
| | | #chartContent { |
| | | width: 100%; |
| | | height: 100%; |
| | | } |
| | | } |
| | | |
| | | .select-container { |
| | | margin: 0 20px; |
| | | width: 180px; |
| | | } |
| | | </style> |
New file |
| | |
| | | <template> |
| | | <div class="data-chart-container"> |
| | | <el-card class="data-card" :body-style="{ height: '100%' }"> |
| | | <div class="card-content"> |
| | | <div class="title-container"> |
| | | <h1>人脸报表</h1> |
| | | <div class="select-container"> |
| | | <el-select v-model="params.examineTag" placeholder="考核标签" @change="getChart" clearable> |
| | | <el-option v-for="item in options" :key="item.label" :label="item.label" :value="item.value"> |
| | | </el-option> |
| | | </el-select> |
| | | </div> |
| | | <div> |
| | | <el-date-picker v-model="date" format="yyyy-MM" value-format="yyyy-MM" type="month" placeholder="选择月份" |
| | | @change="dateChange"> |
| | | </el-date-picker> |
| | | </div> |
| | | </div> |
| | | <div class="chart-container"> |
| | | <div id="chartContent" ref="chartContent"></div> |
| | | </div> |
| | | </div> |
| | | </el-card> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import * as echarts from 'echarts'; |
| | | import {car, face} from "../../../api/platform/home"; |
| | | |
| | | var chartDom = document.getElementById('main'); |
| | | var myChart = echarts.init(chartDom); |
| | | var option; |
| | | let observer = null; |
| | | export default { |
| | | name: 'DataCar', |
| | | data() { |
| | | return { |
| | | date: '', |
| | | params: { |
| | | month: '', |
| | | }, |
| | | options: [ |
| | | {label: '省厅', value: 1}, |
| | | {label: '公安部', value: 2} |
| | | ], |
| | | dataList: [], |
| | | } |
| | | }, |
| | | methods: { |
| | | dateChange() { |
| | | this.params.date = this.date; |
| | | this.getChart(); |
| | | }, |
| | | getChart() { |
| | | this.loading = true; |
| | | myChart.showLoading() |
| | | face(this.params).then(res => { |
| | | myChart = echarts.init(this.$refs.chartContent); |
| | | this.initChart(res.data); |
| | | this.observe(); |
| | | }) |
| | | }, |
| | | groupByData(data) { |
| | | if (!data || data.length === 0) { |
| | | return this.getAllDay().map((item) => [item, []]); |
| | | } |
| | | const tempGroup = {}; |
| | | data.forEach((item) => { |
| | | let {createDate} = item; |
| | | let tempTime = createDate.split('-'); |
| | | createDate = tempTime[1] + '-' + tempTime[2]; |
| | | if (!tempGroup[createDate]) { |
| | | tempGroup[createDate] = []; |
| | | } |
| | | tempGroup[createDate].push(item); |
| | | }) |
| | | const tempArray = Object.entries(tempGroup).sort(([keyA], [keyB]) => new Date([keyA]) - new Date([keyB])); |
| | | return tempArray; |
| | | }, |
| | | getAllDay() { |
| | | const currentDate = this.date.split('-'); |
| | | const currentYear = currentDate[0]; |
| | | const currentMonth = currentDate[1]; |
| | | const daysInMonth = new Date(currentYear, currentMonth, 0).getDate(); |
| | | const datesOfMonth = []; |
| | | for (var day = 1; day <= daysInMonth; day++) { |
| | | const formattedDate = currentMonth + '-' + (day.toString().padStart(2, '0')); |
| | | datesOfMonth.push(formattedDate); |
| | | } |
| | | return datesOfMonth; |
| | | }, |
| | | initChart(data) { |
| | | const dataList = this.groupByData(data.list); |
| | | const baseLine = data.baseLine == null ? 0 : data.baseLine; |
| | | // 选择较大的值作为Y轴的最大值 |
| | | var snapCount |
| | | if (!data.list || data.list.length === 0) { |
| | | snapCount = 0; |
| | | }else { |
| | | snapCount = data.list[data.list.length - 1].snapCount |
| | | } |
| | | const yMax = Math.max(snapCount, baseLine * 1.2); |
| | | const colors = ['#5470C6', '#66CC99', '#EE6666']; |
| | | option = { |
| | | color: colors, |
| | | tooltip: { |
| | | trigger: "axis", // 鼠标移入到柱子里面就会有一个提示,默认是item方式,如果有多个柱状图,堆在一块item就不太好了,个人喜欢axis方式的 |
| | | axisPointer: { |
| | | type: 'cross', |
| | | label:{ |
| | | precision: 0 |
| | | } |
| | | }, |
| | | formatter: function (params) { |
| | | // 创建一个变量来存储最终的 HTML 字符串 |
| | | var tooltipHtml = ''; |
| | | |
| | | // 首先,添加分类名(或轴值)的显示 |
| | | if (params.length > 0) { |
| | | tooltipHtml += "<div style='padding:0 12px;width:100%;height:24px;line-height:24px;'><p>" + params[0].name + "</p></div>"; |
| | | } |
| | | |
| | | var pointsHtml = params.map(function (item) { |
| | | // 使用 toLocaleString() 来格式化 value |
| | | var formattedValue = item.value? item.value.toLocaleString() : '-'; |
| | | return `<div style="display: flex; align-items: center; font-size: 14px; padding: 0 12px; line-height: 24px;"> |
| | | <span style="display: inline-block; margin-right: 5px; border-radius: 2px; width: 10px; height: 10px; background-color: ${item.color || '#ccc'};"></span> |
| | | <span style="margin-right: 10px;">${item.seriesName}</span> |
| | | <span style="font-weight: bold;display: inline-block; min-width: 60px; margin-left: auto; text-align: right;">${formattedValue}</span> |
| | | </div>`; |
| | | }).join(''); |
| | | tooltipHtml = `${tooltipHtml}${pointsHtml}`; |
| | | tooltipHtml += `<div style="font-weight: bold; margin-top: 10px;padding:0 12px;">抓拍量参考值: ${baseLine.toLocaleString()}</div>`; |
| | | |
| | | return tooltipHtml; |
| | | } |
| | | }, |
| | | grid: { |
| | | left: 10, |
| | | right: 0, |
| | | bottom: 0, |
| | | top: '20%', |
| | | containLabel: true |
| | | }, |
| | | legend: { |
| | | data: ['点位在线', '抓拍量'] |
| | | }, |
| | | xAxis: [ |
| | | { |
| | | type: 'category', |
| | | axisTick: { |
| | | alignWithLabel: true |
| | | }, |
| | | data: dataList.map((item) => item[0]), |
| | | } |
| | | ], |
| | | yAxis: [ |
| | | { |
| | | type: 'value', |
| | | name: '点位数', |
| | | position: 'left', |
| | | alignTicks: true, |
| | | axisLine: { |
| | | show: true, |
| | | lineStyle: { |
| | | color: colors[0] |
| | | } |
| | | }, |
| | | |
| | | axisLabel: { |
| | | formatter: function (value) { |
| | | // 返回整数部分,或使用其他逻辑来格式化标签 |
| | | return Math.floor(value); |
| | | } |
| | | } |
| | | |
| | | }, |
| | | { |
| | | type: 'value', |
| | | name: '抓拍量', |
| | | max: yMax, |
| | | min: 0, |
| | | position: 'right', |
| | | alignTicks: true, |
| | | axisLine: { |
| | | show: true, |
| | | lineStyle: { |
| | | color: colors[1] |
| | | } |
| | | }, |
| | | axisLabel: { |
| | | formatter: function (value) { |
| | | // 返回整数部分,或使用其他逻辑来格式化标签 |
| | | return Math.floor(value); |
| | | } |
| | | } |
| | | } |
| | | ], |
| | | series: [ |
| | | { |
| | | type: 'line', |
| | | yAxisIndex: 1, |
| | | markLine: { |
| | | symbol: 'none', |
| | | data: [ |
| | | { |
| | | yAxis: baseLine, // 自定义下限值 |
| | | name: '参考抓拍量', // 基准线名称 |
| | | label: { // 不显示基准线名称 |
| | | show: false, |
| | | }, |
| | | lineStyle: { |
| | | type: 'dashed', // 基准线样式为虚线 |
| | | color: '#b17063', |
| | | }, |
| | | }, |
| | | ], |
| | | }, |
| | | }, |
| | | { |
| | | name: '点位在线', |
| | | type: 'line', |
| | | yAxisIndex: 0, |
| | | color: colors[0], |
| | | tooltip: { |
| | | valueFormatter: function (value) { |
| | | return value; |
| | | } |
| | | }, |
| | | data: data.list.map(item => { |
| | | return item['online'] ? item['online'] : null; |
| | | }) |
| | | }, |
| | | { |
| | | name: '抓拍量', |
| | | type: 'bar', |
| | | yAxisIndex: 1, |
| | | color: colors[1], |
| | | tooltip: { |
| | | valueFormatter: function (value) { |
| | | return value; |
| | | } |
| | | }, |
| | | data: data.list.map(item => { |
| | | return item['snapCount'] ? item['snapCount'] : null; |
| | | }) |
| | | }, |
| | | ] |
| | | }; |
| | | |
| | | myChart.setOption(option); |
| | | myChart.hideLoading(); |
| | | }, |
| | | |
| | | // 监听变化 |
| | | observe() { |
| | | if (!observer) { |
| | | observer = new ResizeObserver(entries => { |
| | | this.handleResize(); |
| | | }) |
| | | } |
| | | observer.observe(this.$refs.chartContent); |
| | | }, |
| | | // 窗口变换 |
| | | handleResize() { |
| | | if (myChart) { |
| | | myChart.resize(); |
| | | } |
| | | } |
| | | |
| | | }, |
| | | mounted() { |
| | | const date = new Date(); |
| | | const year = date.getFullYear(); |
| | | const month = (date.getMonth() + 1) >= 10 ? date.getMonth() + 1 : '0' + (date.getMonth() + 1); |
| | | this.date = year + '-' + month; |
| | | this.params.date = this.date; |
| | | this.getChart(); |
| | | this.observe(); |
| | | }, |
| | | beforeDestroy() { |
| | | if (myChart) { |
| | | myChart.dispose(); |
| | | observer.unobserve(this.$refs.chartContent); |
| | | } |
| | | }, |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .data-chart-container { |
| | | height: 400px; |
| | | margin-bottom: 20px; |
| | | |
| | | .data-card { |
| | | height: 100%; |
| | | |
| | | .card-content { |
| | | width: 100%; |
| | | height: 100%; |
| | | position: relative; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .title-container { |
| | | position: absolute; |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | z-index: 2; |
| | | |
| | | .more-button { |
| | | cursor: pointer; |
| | | font-size: 16px; |
| | | padding: 0 10px; |
| | | } |
| | | } |
| | | |
| | | .chart-container { |
| | | |
| | | width: 100%; |
| | | height: 100%; |
| | | |
| | | #chartContent { |
| | | width: 100%; |
| | | height: 100%; |
| | | } |
| | | } |
| | | |
| | | .select-container { |
| | | margin: 0 20px; |
| | | width: 180px; |
| | | } |
| | | </style> |
New file |
| | |
| | | <template> |
| | | <div class="data-chart-container"> |
| | | <el-card class="data-card" :body-style="{ height: '100%' }"> |
| | | <div class="card-content"> |
| | | <div class="title-container"> |
| | | <h1>视频报表</h1> |
| | | <div class="select-container"> |
| | | <el-select v-model="params.examineTag" placeholder="考核标签" @change="getChart" clearable> |
| | | <el-option v-for="item in options" :key="item.label" :label="item.label" :value="item.value"> |
| | | </el-option> |
| | | </el-select> |
| | | </div> |
| | | <div > |
| | | <el-date-picker v-model="date" format="yyyy-MM" value-format="yyyy-MM" type="month" placeholder="选择月份" |
| | | @change="dateChange"> |
| | | </el-date-picker> |
| | | </div> |
| | | </div> |
| | | <div class="chart-container"> |
| | | <div id="chartContent" ref="chartContent"></div> |
| | | </div> |
| | | </div> |
| | | </el-card> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import * as echarts from 'echarts'; |
| | | import {video} from "../../../api/platform/home"; |
| | | var chartDom = document.getElementById('main'); |
| | | var myChart = echarts.init(chartDom); |
| | | var option; |
| | | let observer = null; |
| | | export default { |
| | | name: 'DataVideo', |
| | | data() { |
| | | return { |
| | | date: '', |
| | | params: { |
| | | month: '', |
| | | }, |
| | | options: [ |
| | | {label: '省厅', value: 1}, |
| | | {label: '公安部', value: 2} |
| | | ], |
| | | dataList: [], |
| | | } |
| | | }, |
| | | methods: { |
| | | dateChange() { |
| | | this.params.date = this.date; |
| | | this.getChart(); |
| | | }, |
| | | getChart() { |
| | | this.loading = true; |
| | | myChart.showLoading(); |
| | | video(this.params).then(res => { |
| | | myChart = echarts.init(this.$refs.chartContent); |
| | | this.initChart(res.data); |
| | | this.observe(); |
| | | }) |
| | | }, |
| | | groupByData(data) { |
| | | if (!data || data.length ===0) { |
| | | return this.getAllDay().map((item) => [item, []]); |
| | | } |
| | | const tempGroup = {}; |
| | | data.forEach((item) => { |
| | | let {createDate} = item; |
| | | let tempTime = createDate.split('-'); |
| | | createDate = tempTime[1] + '-' + tempTime[2]; |
| | | if (!tempGroup[createDate]) { |
| | | tempGroup[createDate] = []; |
| | | } |
| | | tempGroup[createDate].push(item); |
| | | }) |
| | | const tempArray = Object.entries(tempGroup).sort(([keyA], [keyB]) => new Date([keyA]) - new Date([keyB])); |
| | | return tempArray; |
| | | }, |
| | | getAllDay() { |
| | | const currentDate = this.date.split('-'); |
| | | const currentYear = currentDate[0]; |
| | | const currentMonth = currentDate[1]; |
| | | const daysInMonth = new Date(currentYear, currentMonth, 0).getDate(); |
| | | const datesOfMonth = []; |
| | | for (var day = 1; day <= daysInMonth; day++) { |
| | | const formattedDate = currentMonth + '-' + (day.toString().padStart(2, '0')); |
| | | datesOfMonth.push(formattedDate); |
| | | } |
| | | return datesOfMonth; |
| | | }, |
| | | initChart(data) { |
| | | const dataList = this.groupByData(data.list); |
| | | const baseLine = data.baseLine == null ? 0 : data.baseLine; |
| | | const colors = ['#5470C6', '#66CC99', '#EE6666']; |
| | | option = { |
| | | color: colors, |
| | | tooltip: { |
| | | trigger: 'axis', |
| | | axisPointer: { |
| | | type: 'cross', |
| | | label:{ |
| | | precision: 0 |
| | | } |
| | | }, |
| | | formatter: function (params) { |
| | | // 创建一个变量来存储最终的 HTML 字符串 |
| | | var tooltipHtml = ''; |
| | | |
| | | // 首先,添加分类名(或轴值)的显示 |
| | | if (params.length > 0) { |
| | | tooltipHtml += "<div style='padding:0 12px;width:100%;height:24px;line-height:24px;'><p>" + params[0].name + "</p></div>"; |
| | | } |
| | | |
| | | var pointsHtml = params.map(function (item) { |
| | | // 使用 toLocaleString() 来格式化 value |
| | | var formattedValue = item.value? item.value.toLocaleString() : '-'; |
| | | return `<div style="display: flex; align-items: center; font-size: 14px; padding: 0 12px; line-height: 24px;"> |
| | | <span style="display: inline-block; margin-right: 5px; border-radius: 2px; width: 10px; height: 10px; background-color: ${item.color || '#ccc'};"></span> |
| | | <span style="margin-right: 10px;">${item.seriesName}</span> |
| | | <span style="font-weight: bold;display: inline-block; min-width: 60px; margin-left: auto; text-align: right;">${formattedValue}</span> |
| | | </div>`; |
| | | }).join(''); |
| | | tooltipHtml = `${tooltipHtml}${pointsHtml}`; |
| | | tooltipHtml += `<div style="font-weight: bold; margin-top: 10px;padding:0 12px;">录像正常参考值: ${baseLine.toLocaleString()}</div>`; |
| | | |
| | | return tooltipHtml; |
| | | } |
| | | }, |
| | | grid: { |
| | | left: 10, |
| | | right: 0, |
| | | bottom: 0, |
| | | top: '20%', |
| | | containLabel: true |
| | | }, |
| | | legend: { |
| | | data: ['点位在线', '录像完整', '录像缺失'] |
| | | }, |
| | | xAxis: [ |
| | | { |
| | | type: 'category', |
| | | axisTick: { |
| | | alignWithLabel: true |
| | | }, |
| | | data: dataList.map((item) => item[0]), |
| | | } |
| | | ], |
| | | yAxis: [ |
| | | { |
| | | type: 'value', |
| | | name: '录像数', |
| | | position: 'right', |
| | | alignTicks: true, |
| | | axisLine: { |
| | | show: true, |
| | | lineStyle: { |
| | | color: colors[1] |
| | | } |
| | | }, |
| | | axisLabel: { |
| | | formatter: function (value) { |
| | | // 返回整数部分,或使用其他逻辑来格式化标签 |
| | | return Math.floor(value); |
| | | } |
| | | } |
| | | }, |
| | | { |
| | | type: 'value', |
| | | name: '点位数', |
| | | position: 'left', |
| | | alignTicks: true, |
| | | axisLine: { |
| | | show: true, |
| | | lineStyle: { |
| | | color: colors[0] |
| | | } |
| | | }, |
| | | axisLabel: { |
| | | formatter: function (value) { |
| | | // 返回整数部分,或使用其他逻辑来格式化标签 |
| | | return Math.floor(value); |
| | | } |
| | | } |
| | | } |
| | | ], |
| | | series: [ |
| | | { |
| | | yAxisIndex: 0, |
| | | type: 'line', |
| | | markLine: { |
| | | symbol: 'none', |
| | | data: [ |
| | | { |
| | | yAxis: baseLine, // 自定义下限值 |
| | | name: '参考录像正常数', // 基准线名称 |
| | | label: { // 不显示基准线名称 |
| | | show: false, |
| | | }, |
| | | lineStyle: { |
| | | type: 'dashed', // 基准线样式为虚线 |
| | | color: '#b17063', |
| | | }, |
| | | }, |
| | | ], |
| | | }, |
| | | }, |
| | | { |
| | | name: '录像完整', |
| | | yAxisIndex: 0, |
| | | type: 'bar', |
| | | data: data.list.map(item => { |
| | | return item['integrityNum']; |
| | | }) |
| | | }, |
| | | { |
| | | name: '录像缺失', |
| | | type: 'bar', |
| | | yAxisIndex: 0, |
| | | data: data.list.map(item => { |
| | | return item['loseNum']; |
| | | }) |
| | | }, |
| | | { |
| | | name: '点位在线', |
| | | type: 'line', |
| | | yAxisIndex: 1, |
| | | data: data.list.map(item => { |
| | | return item['online']; |
| | | }) |
| | | }, |
| | | ] |
| | | }; |
| | | |
| | | option && myChart.setOption(option); |
| | | myChart.hideLoading(); |
| | | }, |
| | | |
| | | |
| | | // 监听变化 |
| | | observe() { |
| | | if (!observer) { |
| | | observer = new ResizeObserver(entries => { |
| | | this.handleResize(); |
| | | }) |
| | | } |
| | | observer.observe(this.$refs.chartContent); |
| | | }, |
| | | // 窗口变换 |
| | | handleResize() { |
| | | if (myChart) { |
| | | myChart.resize(); |
| | | } |
| | | } |
| | | |
| | | }, |
| | | mounted() { |
| | | const date = new Date(); |
| | | const year = date.getFullYear(); |
| | | const month = (date.getMonth() + 1) >= 10 ? date.getMonth() + 1 : '0' + (date.getMonth() + 1); |
| | | this.date = year + '-' + month; |
| | | this.params.date = this.date; |
| | | this.getChart(); |
| | | this.observe(); |
| | | }, |
| | | beforeDestroy() {b |
| | | if (myChart) { |
| | | myChart.dispose(); |
| | | observer.unobserve(this.$refs.chartContent); |
| | | } |
| | | }, |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .data-chart-container { |
| | | height: 400px; |
| | | margin-bottom: 20px; |
| | | |
| | | .data-card { |
| | | height: 100%; |
| | | |
| | | .card-content { |
| | | width: 100%; |
| | | height: 100%; |
| | | position: relative; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .title-container { |
| | | position: absolute; |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | z-index: 2; |
| | | |
| | | .more-button { |
| | | cursor: pointer; |
| | | font-size: 16px; |
| | | padding: 0 10px; |
| | | } |
| | | } |
| | | |
| | | .chart-container { |
| | | |
| | | width: 100%; |
| | | height: 100%; |
| | | |
| | | #chartContent { |
| | | width: 100%; |
| | | height: 100%; |
| | | } |
| | | } |
| | | |
| | | .select-container { |
| | | margin: 0 20px; |
| | | width: 180px; |
| | | } |
| | | </style> |
| | |
| | | <template> |
| | | <div class="data-container"> |
| | | <div> |
| | | <data-video></data-video> |
| | | </div> |
| | | <div> |
| | | <data-car></data-car> |
| | | </div> |
| | | <div> |
| | | <data-face></data-face> |
| | | </div> |
| | | <el-row :gutter="40"> |
| | | <el-col :xs='24' :md="24" :sm="24" :lg="24" :xl="12"> |
| | | <data-chart></data-chart> |
| | |
| | | import DataCheck from '../data-check/index.vue'; |
| | | import WorkOrder from '../work-order/index.vue'; |
| | | import DataChart from '../data-chart/index.vue'; |
| | | import DataVideo from '../data-video/index.vue'; |
| | | import DataCar from '../data-car/index.vue'; |
| | | import DataFace from '../data-face/index.vue'; |
| | | export default { |
| | | name: 'DataWrapper', |
| | | components: { |
| | |
| | | DataCheck, |
| | | WorkOrder, |
| | | Examine, |
| | | DataChart |
| | | DataChart, |
| | | DataVideo, |
| | | DataCar, |
| | | DataFace |
| | | } |
| | | } |
| | | </script> |
| | |
| | | |
| | | dateChange() { |
| | | this.queryParams.date = this.date; |
| | | console.log(this.queryParams); |
| | | this.getChart(this.queryParams.deptId); |
| | | } |
| | | |
| | |
| | | label: '纬度异常数' |
| | | }, |
| | | { |
| | | label: '合格率' |
| | | label: '今日合格率' |
| | | }, |
| | | ] |
| | | } |
| | |
| | | label: '纬度异常数' |
| | | }, |
| | | { |
| | | label: '注册率' |
| | | label: '今日注册率' |
| | | }, |
| | | ] |
| | | } |
| | |
| | | ], |
| | | }, |
| | | { |
| | | title: '考核档案比', |
| | | title: '档案考核比', |
| | | index: 'archives_rate', |
| | | columns: [ |
| | | { |
| | |
| | | label: '纬度异常数' |
| | | }, |
| | | { |
| | | label: '考核比' |
| | | label: '今日考核比' |
| | | }, |
| | | ] |
| | | } |
| | |
| | | label: '设备总数' |
| | | }, |
| | | { |
| | | label: '在线率' |
| | | label: '今日在线率' |
| | | }, |
| | | ] |
| | | } |
| | |
| | | label: '设备总数' |
| | | }, |
| | | { |
| | | label: '在线率' |
| | | label: '今日在线率' |
| | | }, |
| | | ] |
| | | } |
| | |
| | | label: '异常' |
| | | }, |
| | | { |
| | | label: '可用率' |
| | | label: '今日可用率' |
| | | }, |
| | | ] |
| | | } |
| | |
| | | label: '异常' |
| | | }, |
| | | { |
| | | label: '可用率' |
| | | label: '今日可用率' |
| | | }, |
| | | ] |
| | | } |
| | |
| | | label: '设备总数' |
| | | }, |
| | | { |
| | | label: '在线率' |
| | | label: '今日在线率' |
| | | }, |
| | | ] |
| | | } |
| | |
| | | label: '异常' |
| | | }, |
| | | { |
| | | label: '可用率' |
| | | label: '今日重点可用率' |
| | | }, |
| | | ] |
| | | } |
| | |
| | | label: 'osd时间标注错误数' |
| | | }, |
| | | { |
| | | label: '标注正确率' |
| | | label: '今日标注正确率' |
| | | }, |
| | | ] |
| | | } |
| | |
| | | label: 'osd时间标注错误数' |
| | | }, |
| | | { |
| | | label: '校时正确率' |
| | | label: '今日校时正确率' |
| | | }, |
| | | ] |
| | | } |
| | |
| | | label: '设备总数' |
| | | }, |
| | | { |
| | | label: '在线率' |
| | | label: '今日在线率' |
| | | }, |
| | | ] |
| | | } |
| | |
| | | label: '数据量少' |
| | | }, |
| | | { |
| | | label: '稳定性' |
| | | label: '今日稳定性' |
| | | }, |
| | | ] |
| | | } |
| | |
| | | label: '设备总数' |
| | | }, |
| | | { |
| | | label: '在线率' |
| | | label: '今日在线率' |
| | | }, |
| | | ] |
| | | } |
| | |
| | | label: '纬度异常数' |
| | | }, |
| | | { |
| | | label: '一致率' |
| | | label: '今日一致率' |
| | | }, |
| | | ] |
| | | } |
| | |
| | | label: '精度过低' |
| | | }, |
| | | { |
| | | label: '准确率' |
| | | label: '今日准确率' |
| | | }, |
| | | ] |
| | | } |
| | |
| | | icon: 'el-icon-truck', |
| | | dataList: [ |
| | | { |
| | | label: '完整性' |
| | | label: '今日完整性' |
| | | } |
| | | ] |
| | | } |
| | |
| | | icon: 'el-icon-truck', |
| | | dataList: [ |
| | | { |
| | | label: '准确性' |
| | | label: '今日准确性' |
| | | } |
| | | ] |
| | | } |
| | |
| | | label: '数据量少' |
| | | }, |
| | | { |
| | | label: '准确性' |
| | | label: '今日准确性' |
| | | }, |
| | | ] |
| | | } |
| | |
| | | icon: 'el-icon-truck', |
| | | dataList: [ |
| | | { |
| | | label: '及时性' |
| | | label: '今日及时性' |
| | | } |
| | | ] |
| | | } |
| | |
| | | icon: 'el-icon-truck', |
| | | dataList: [ |
| | | { |
| | | label: '可用性' |
| | | label: '今日可用性' |
| | | } |
| | | ] |
| | | } |
| | |
| | | icon: 'el-icon-truck', |
| | | dataList: [ |
| | | { |
| | | label: '可用性' |
| | | label: '今日可用性' |
| | | } |
| | | ] |
| | | } |
| | |
| | | label: '数据量少' |
| | | }, |
| | | { |
| | | label: '稳定性' |
| | | label: '今日稳定性' |
| | | }, |
| | | ] |
| | | } |
| | |
| | | label: '设备总数' |
| | | }, |
| | | { |
| | | label: '在线率' |
| | | label: '今日在线率' |
| | | }, |
| | | ] |
| | | } |
| | |
| | | label: '纬度异常数' |
| | | }, |
| | | { |
| | | label: '一致率' |
| | | label: '今日一致率' |
| | | }, |
| | | ] |
| | | } |
| | |
| | | label: '精度过低' |
| | | }, |
| | | { |
| | | label: '准确率' |
| | | label: '今日准确率' |
| | | }, |
| | | ] |
| | | } |
| | |
| | | label: '精度过低' |
| | | }, |
| | | { |
| | | label: '合格性' |
| | | label: '今日合格性' |
| | | }, |
| | | ] |
| | | } |
| | |
| | | label: '数据量少' |
| | | }, |
| | | { |
| | | label: '准确性' |
| | | label: '今日准确性' |
| | | }, |
| | | ] |
| | | } |
| | |
| | | label: '数据量少' |
| | | }, |
| | | { |
| | | label: '及时性' |
| | | label: '今日及时性' |
| | | }, |
| | | ] |
| | | } |
| | |
| | | icon: 'el-icon-truck', |
| | | dataList: [ |
| | | { |
| | | label: '可用性' |
| | | label: '今日可用性' |
| | | } |
| | | ] |
| | | } |