<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 class="select-container">
|
<el-select v-model="params.category" placeholder="数据类型" @change="getChart" clearable>
|
<el-option v-for="item in categories" :key="item.label" :label="item.label" :value="item.value">
|
</el-option>
|
</el-select>
|
</div>
|
<div class="select-container">
|
<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 myChart = null;
|
var option;
|
let observer = null;
|
export default {
|
name: 'DataCar',
|
data() {
|
return {
|
date: '',
|
params: {
|
month: '',
|
category: 1
|
},
|
categories: [
|
{label: '累计数据', value: 1},
|
{label: '每日数据', value: 2},
|
],
|
options: [
|
{label: '省厅', value: 1}
|
],
|
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 = new Date();
|
const currentYear = currentDate.getFullYear();
|
const currentMonth = (currentDate.getMonth() + 1).toString().padStart(2, '0'); // 月份从0开始,需要加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.reduce((max, item) => Math.max(max, item.snapCount), 0)
|
}
|
const yMax = Math.max(snapCount * 1.2, baseLine * 1.2);
|
let interval = 1;
|
while ((yMax) / interval > 100) { // 这里的 100 是一个阈值,您可以根据需要调整
|
interval *= 10;
|
}
|
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 / interval) * interval;
|
}
|
}
|
}
|
],
|
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;
|
myChart = echarts.init(this.$refs.chartContent);
|
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-left: 20px;
|
width: 180px;
|
}
|
</style>
|