ylj20011123 a922a57525 update
2025-07-14 16:14:21 +08:00

576 lines
22 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<script setup lang="ts">
import SmallTitle from '../smallTitle/smallTitle.vue'
import './VehiclesEntering.less'
import { onMounted, onBeforeUnmount, watch } from 'vue';
import * as echarts from 'echarts/core';
import { BarChart, LineChart } from 'echarts/charts';
import {
GridComponent,
TitleComponent,
TooltipComponent,
LegendComponent
} from 'echarts/components';
import { CanvasRenderer } from 'echarts/renderers';
import moment from 'moment';
import { handleGetMonthAnalysis, handleGetSPBayonetList } from '../../service';
// 注册组件
echarts.use([
BarChart,
LineChart,
GridComponent,
TitleComponent,
TooltipComponent,
LegendComponent,
CanvasRenderer
]);
let myChart: echarts.ECharts;
let myChart2: echarts.ECharts;
onMounted(async () => {
await handleGoMounted()
})
// 传入的数据
const props = defineProps<{
currentService?: any;
}>();
// 监听传入的选中服务区
watch(
() => props.currentService,
(newVal, oldVal) => {
handleGoMounted()
},
{ deep: true }
);
// 初始运行的方法
const handleGoMounted = async () => {
const res: any = await handleGetSectionFlowCount()
const chartDom = document.getElementById('VehiclesEntering');
if (!chartDom) return;
myChart = echarts.init(chartDom);
const chartDom2 = document.getElementById('TrendCustomerRevenue');
if (!chartDom2) return;
myChart2 = echarts.init(chartDom2);
const option = handleSetConfig(res)
const option2 = handleSetConfig2(res)
myChart.setOption(option);
myChart2.setOption(option2);
myChart.resize();
myChart2.resize();
window.addEventListener('resize', resizeChart);
window.addEventListener('resize', resizeChart2);
}
const handleSetConfig = (res: any) => {
const option = {
tooltip: {
trigger: 'axis', // 触发类型:坐标轴触发
axisPointer: { // 坐标轴指示器配置
type: 'shadow' // 阴影指示器(适合柱状图)
},
formatter: function (params: any) { // 自定义提示框内容
return `<div>
<div>${params[0].seriesName}${res?.realDataCar[params[0]?.dataIndex].toLocaleString()}辆</div>
<div>${params[1].seriesName}${res?.yesRealDataCar[params[1]?.dataIndex].toLocaleString()}辆</div>
</div>`
// return `
// <div>车流量:${realData ? realData + '辆' : data.value + '万辆'} </div>
// `;
}
},
legend: {
data: [`${res.currentYear}年车流量`, `${res.yesYear}年车流量`, `${res.currentYear}年交易额`, `${res.yesYear}年交易额`],
textStyle: {
color: '#fff',
fontSize: 12 // 设置图例文字大小为12px
},
right: '4%',
top: '0%',
orient: 'horizontal',
type: 'scroll' // 如果图例过长,启用滚动
},
grid: {
left: '0',
right: '0',
bottom: '0',
top: '40',
containLabel: true
},
xAxis: {
type: 'category',
boundaryGap: true,
data: res.category,
axisPointer: {
type: 'shadow'
},
axisLabel: {
color: '#fff',
formatter: '{value}' // 刻度值保持纯数字
},
axisLine: {
lineStyle: {
color: '#fff' // 设置 y 轴线颜色为白色(可选)
}
},
},
yAxis: [
{
type: 'value',
name: '万辆', // 仅在此处显示单位
nameTextStyle: {
color: '#fff',
padding: [0, 30, 0, 0] // 调整单位位置
},
axisLabel: {
width: 60,
color: '#fff',
formatter: '{value}' // 刻度值保持纯数字
},
axisLine: {
show: true, // 显示 y 轴线
lineStyle: {
color: '#fff' // 设置 y 轴线颜色为白色(可选)
}
},
splitLine: { show: false },
splitNumber: 5,
},
// {
// type: 'value',
// name: '交易金额(万元)',
// splitLine: { show: false },
// nameTextStyle: {
// color: '#666',
// padding: [0, 0, 0, 30] // 调整单位位置
// },
// splitNumber: 4,
// }
],
series: [
{
name: `${res.currentYear}年车流量`,
type: 'bar',
barWidth: 5,
data: res.seriesDataCar,
yAxisIndex: 0,
itemStyle: {
borderRadius: [3, 3, 0, 0],
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: '#46B8F3' }, // 顶部颜色
{ offset: 1, color: '#1A4AF6' } // 底部颜色
])
},
label: {
show: true,
position: 'top',
formatter: function (params: any) {
// 自定义显示内容
return res.carAdd && res.carAdd[params.dataIndex] ? `${res.carAdd[params.dataIndex]}%` : '';
},
color: '#fff', // 文字颜色
fontSize: 10 // 文字大小
}
},
{
name: `${res.yesYear}年车流量`,
type: 'bar',
smooth: true,
data: res.yesSeriesDataCar,
yAxisIndex: 0,
barWidth: 5,
itemStyle: {
borderRadius: [3, 3, 0, 0],
color: "#3CD495"
}
},
// {
// name: `${res.currentYear}年交易额`,
// type: 'line',
// data: res.seriesDataRevenue,
// yAxisIndex: 1,
// symbol: 'circle',
// symbolSize: 6,
// lineStyle: {
// width: 2
// }
// },
// {
// name: `${res.yesYear}年交易额`,
// type: 'line',
// data: res.yesSeriesDataRevenue,
// yAxisIndex: 1,
// symbol: 'circle',
// symbolSize: 6,
// lineStyle: {
// width: 2
// }
// }
],
color: ['#008CFF', '#69BCFF', '#FF5E5E', '#FF9500'] // Custom colors for each series
};
return option
}
const handleSetConfig2 = (res: any) => {
const option2 = {
tooltip: {
trigger: 'axis', // 触发类型:坐标轴触发
axisPointer: { // 坐标轴指示器配置
type: 'shadow' // 阴影指示器(适合柱状图)
},
formatter: function (params: any) { // 自定义提示框内容
return `<div>
<div>${params[0].seriesName}${res?.realDataRevenue[params[0]?.dataIndex].toLocaleString()}元</div>
<div>${params[1].seriesName}${res?.yesRealDataRevenue[params[1]?.dataIndex].toLocaleString()}元</div>
</div>`
}
},
legend: {
data: [`${res.currentYear}年交易额`, `${res.yesYear}年交易额`],
textStyle: {
color: '#fff',
fontSize: 12 // 设置图例文字大小为12px
},
right: '4%',
top: '0%',
orient: 'horizontal',
type: 'scroll' // 如果图例过长,启用滚动
},
grid: {
left: '0',
right: '0',
bottom: '0',
top: '30',
containLabel: true
},
xAxis: {
type: 'category',
boundaryGap: true,
data: res.category,
axisPointer: {
type: 'shadow'
},
axisLabel: {
color: '#fff',
formatter: '{value}' // 刻度值保持纯数字
},
axisLine: {
lineStyle: {
color: '#fff' // 设置 y 轴线颜色为白色(可选)
}
},
},
yAxis: [
{
type: 'value',
name: '万元',
splitLine: { show: false },
splitNumber: 4,
nameTextStyle: {
color: '#fff',
padding: [0, 0, 0, 0] // 调整单位位置
},
axisLabel: {
width: 60,
color: '#fff',
formatter: '{value}' // 刻度值保持纯数字
},
axisLine: {
show: true, // 显示 y 轴线
lineStyle: {
color: '#fff' // 设置 y 轴线颜色为白色(可选)
}
},
}
],
series: [
{
name: `${res.currentYear}年交易额`,
type: 'line',
data: res.seriesDataRevenue,
symbol: 'circle',
symbolSize: 6,
lineStyle: {
width: 2,
color: new echarts.graphic.LinearGradient(0, 0, 1, 0, [
{ offset: 0, color: '#46B8F3' }, // 左端颜色
{ offset: 1, color: '#1A4AF6' } // 右端颜色
])
},
label: {
show: true,
position: 'top',
formatter: function (params: any) {
// 自定义显示内容
return res.revenueAdd && res.revenueAdd[params.dataIndex] ? `${res.revenueAdd[params.dataIndex]}%` : '';
},
color: '#fff', // 文字颜色
fontSize: 10 // 文字大小
}
},
{
name: `${res.yesYear}年交易额`,
type: 'line',
data: res.yesSeriesDataRevenue,
symbol: 'circle',
symbolSize: 6,
lineStyle: {
width: 2,
color: "#FFB006"
},
itemStyle: {
color: '#FFB006' // 确保标记点与线条同色
}
}
],
}
return option2
}
// 拿到入区车辆的趋势
const handleGetSectionFlowCount = async () => {
// const req: any = {
// Province_Code: '340000',
// Statistics_Date: moment().subtract(1, 'd').format('YYYY-MM-DD'),
// GroupType: 2,
// Serverpart_ID: props.currentService?.SERVERPART_ID || "",
// }
// const data = await handleGetSPBayonetList(req)
const req: any = {
StartDate: moment().startOf('y').format('YYYY-MM-DD'),
EndDate: moment().subtract(1, 'd').format('YYYY-MM-DD'),
ProvinceCode: 530000
// Serverpart_ID: props.currentService?.SERVERPART_ID || "1143,1144,1186,1188,1189,1190,1191,1192,1193,979,999,1023,1029,1030,1031,1033,1037,1041,1078,1087,1095,1137,1141,1147,1157,1159,1164,1165,1170,1174,981,985,987,994,1007,1009,1010,1012,1016,971,996,1002,1017,1018,1022,1027,1032,1073,1076,1099,1118,1122,1140,1142,1150,1171,970,969,978,1001,1005,1015,1050,1051,1052,1053,1064,1066,1096,1097,1101,1103,1104,1105,1106,1109,1112,1114,1115,1116,1117,991,995,1039,1080,1094,1100,1107,1123,1127,1133,1154,1155,1161,1163,1179,1180,1019,1021,1048,1049,1056,1059,1062,1063,1069,1093,1067,1228,1008,1070,1072,1166,1113,1148,1153,986,1086,1075,1182,1068,1226,1218,1088,1090,1058,1044,1084,1077,1089,1081,1091,1083,1162,1036,1092,988,993,1111,1158,1194,1202,1230,1198,1207,1216,1221,1203,1206,1209,1215,1227,1201,1205,1208,1214,1217,1229,1212,1065,1085,1055,1071,982,1168,1185,1110,977,1169,973,974,1011,1151,1121,1046,1045,1172,1146,976,1187,1156,1181,1136,1138,1211,983,1195,1131,1176,1167,1223,997,1252,1225,1043,1129,992,1149,975,1382,989,1047,1197,1025,1199,1183,1222,1178,1003,1013,1224,1139,1125,1173,1135,1038,1177,1060,1175,1184,1035,1026,1028,1079,1119,1120,1489"
}
let VehiclesEntering = sessionStorage.getItem('VehiclesEntering')
let data: any = []
if (VehiclesEntering) {
data = JSON.parse(VehiclesEntering)
} else {
data = await handleGetMonthAnalysis(req)
sessionStorage.setItem("VehiclesEntering", JSON.stringify(data))
}
// const data = await handleGetMonthAnalysis(req)
const yesReq: any = {
StartDate: moment().subtract(1, 'y').startOf('y').format('YYYY-MM-DD'),
EndDate: moment().subtract(1, 'y').endOf('y').format('YYYY-MM-DD'),
ProvinceCode: 530000
// Serverpart_ID: props.currentService?.SERVERPART_ID || "1143,1144,1186,1188,1189,1190,1191,1192,1193,979,999,1023,1029,1030,1031,1033,1037,1041,1078,1087,1095,1137,1141,1147,1157,1159,1164,1165,1170,1174,981,985,987,994,1007,1009,1010,1012,1016,971,996,1002,1017,1018,1022,1027,1032,1073,1076,1099,1118,1122,1140,1142,1150,1171,970,969,978,1001,1005,1015,1050,1051,1052,1053,1064,1066,1096,1097,1101,1103,1104,1105,1106,1109,1112,1114,1115,1116,1117,991,995,1039,1080,1094,1100,1107,1123,1127,1133,1154,1155,1161,1163,1179,1180,1019,1021,1048,1049,1056,1059,1062,1063,1069,1093,1067,1228,1008,1070,1072,1166,1113,1148,1153,986,1086,1075,1182,1068,1226,1218,1088,1090,1058,1044,1084,1077,1089,1081,1091,1083,1162,1036,1092,988,993,1111,1158,1194,1202,1230,1198,1207,1216,1221,1203,1206,1209,1215,1227,1201,1205,1208,1214,1217,1229,1212,1065,1085,1055,1071,982,1168,1185,1110,977,1169,973,974,1011,1151,1121,1046,1045,1172,1146,976,1187,1156,1181,1136,1138,1211,983,1195,1131,1176,1167,1223,997,1252,1225,1043,1129,992,1149,975,1382,989,1047,1197,1025,1199,1183,1222,1178,1003,1013,1224,1139,1125,1173,1135,1038,1177,1060,1175,1184,1035,1026,1028,1079,1119,1120,1489"
}
let VehiclesEntering2 = sessionStorage.getItem('VehiclesEntering2')
let yesData: any = []
if (VehiclesEntering2) {
yesData = JSON.parse(VehiclesEntering2)
} else {
yesData = await handleGetMonthAnalysis(yesReq)
console.log('yesDatayesDatayesDatayesDatayesDatayesDatayesData', yesData);
sessionStorage.setItem("VehiclesEntering2", JSON.stringify(yesData))
}
// const yesData = await handleGetMonthAnalysis(yesReq)
let category: string[] = []
let seriesDataCar: number[] = []
let seriesDataRevenue: number[] = []
let realDataCar: number[] = []
let realDataRevenue: number[] = []
let aiObj: any = {}
let aiRevenueObj: any = {}
console.log('dnasfhuaidhsdaghsakjlhsldk', data);
if (data && data.length > 0) {
data.forEach((item: any) => {
category.push(`${item.Statistics_Month < 10 ? '0' + item.Statistics_Month : item.Statistics_Month}`)
seriesDataCar.push(Number((item.Vehicle_Count / 10000).toFixed(2)))
realDataCar.push(item.Vehicle_Count)
seriesDataRevenue.push(Number((item.RevenueAmount / 10000).toFixed(2)))
realDataRevenue.push(item.RevenueAmount)
aiObj[`${item.Statistics_Month < 10 ? '0' + item.Statistics_Month : item.Statistics_Month}月入区车流`] = item.Vehicle_Count + '辆'
aiRevenueObj[`${item.Statistics_Month < 10 ? '0' + item.Statistics_Month : item.Statistics_Month}月对客营收`] = item.RevenueAmount + '元'
})
}
let yesSeriesDataCar: number[] = []
let yesSeriesDataRevenue: number[] = []
let yesRealDataCar: number[] = []
let yesRealDataRevenue: number[] = []
let yesAiObj: any = {}
let yesAiRevenueObj: any = {}
if (yesData && yesData.length > 0) {
yesData.forEach((item: any) => {
yesSeriesDataCar.push(Number((item.Vehicle_Count / 10000).toFixed(2)))
yesSeriesDataRevenue.push(Number((item.RevenueAmount / 10000).toFixed(2)))
yesRealDataCar.push(item.Vehicle_Count)
yesRealDataRevenue.push(item.RevenueAmount)
yesAiObj[`${item.Statistics_Month < 10 ? '0' + item.Statistics_Month : item.Statistics_Month}月入区车流`] = item.Vehicle_Count + '辆'
yesAiRevenueObj[`${item.Statistics_Month < 10 ? '0' + item.Statistics_Month : item.Statistics_Month}月对客营收`] = item.RevenueAmount + '元'
})
}
let carAdd: string[] = []
let revenueAdd: string[] = []
if (category && category.length > 0) {
for (let i = 0; i < category.length; i++) {
let currentCar: number = realDataCar[i]
let yesCar: number = yesRealDataCar[i]
let add: string = ''
if (currentCar > 0 && yesCar > 0) {
add = (((currentCar - yesCar) / yesCar) * 100).toFixed(2)
}
carAdd.push(add)
let addRenvenue: string = ""
let currentRevenue: number = realDataRevenue[i]
let yesRevenue: number = yesRealDataRevenue[i]
if (currentRevenue > 0 && yesRevenue > 0) {
addRenvenue = (((currentRevenue - yesRevenue) / yesRevenue) * 100).toFixed(2)
}
revenueAdd.push(addRenvenue)
}
}
let res: any = {
category: category,// x轴的内容
seriesDataCar: seriesDataCar, // 入区车流量 万
seriesDataRevenue: seriesDataRevenue,// 营收 万
realDataCar: realDataCar,// 入区车流量 实际
realDataRevenue: realDataRevenue,// 营收 实际
yesSeriesDataCar: yesSeriesDataCar,// 入区车流量 万 去年
yesSeriesDataRevenue: yesSeriesDataRevenue,// 营收 万 去年
yesRealDataCar: yesRealDataCar,// 入区车流量 实际 去年
yesRealDataRevenue: yesRealDataRevenue,// 营收 实际 去年
currentYear: moment().format('YYYY'), // 当前年份
yesYear: moment().subtract(1, 'y').format('YYYY'),// 去年年份
carAdd: carAdd,// 入区车流的增长
revenueAdd: revenueAdd,// 对客营收的增长
}
console.log('fdshufahsudifhasdjkfh', res);
let VehiclesEnteringAI = sessionStorage.getItem('VehiclesEnteringAI')
if (VehiclesEnteringAI) { } else {
let result: any = {}
result[`${res.currentYear}年入区车流`] = aiObj
result[`${res.yesYear}年入区车流`] = yesAiObj
sessionStorage.setItem("VehiclesEnteringAI", JSON.stringify(result))
}
let VehiclesEnteringAI2 = sessionStorage.getItem('VehiclesEnteringAI2')
if (VehiclesEnteringAI2) { } else {
let result: any = {}
result[`${res.currentYear}年对客营收`] = aiRevenueObj
result[`${res.yesYear}年对客营收`] = yesAiRevenueObj
sessionStorage.setItem("VehiclesEnteringAI2", JSON.stringify(result))
}
return res
}
const resizeChart = () => {
myChart?.resize();
};
const resizeChart2 = () => {
myChart2?.resize();
};
onBeforeUnmount(() => {
window.removeEventListener('resize', resizeChart);
myChart?.dispose();
myChart2?.dispose();
});
// 更新图表数据
const handleUpdatePie = async () => {
const res: any = await handleGetSectionFlowCount()
myChart.setOption({
series: [], // 清空 series
}, { replaceMerge: 'series' }); // 替换 series 部分
myChart2.setOption({
series: [], // 清空 series
}, { replaceMerge: 'series' }); // 替换 series 部分
const option = handleSetConfig(res)
const option2 = handleSetConfig2(res)
myChart.setOption(option)
myChart2.setOption(option2)
}
defineExpose({
handleUpdatePie
});
</script>
<template>
<div class="VehiclesEnteringBox">
<SmallTitle :title="'入区车流'">
<!-- <template #extra>
<div class="legendBox" style="display: flex;align-items: center;">
<div class="legendItem" style="display: flex;align-items: center;margin-right: 20px;">
<div class="legendIcon"
style="width: 14px;height: 14px;background: #7D4CD2;border-radius: 3px 3px 3px 3px;margin-right: 10px;">
</div>
<div class="legendName" style="font-size: 12px;color: #FFFFFF;">小型车辆</div>
</div>
<div class="legendItem" style="display: flex;align-items: center;margin-right: 20px;">
<div class="legendIcon"
style="width: 14px;height: 14px;background: #0094FF;border-radius: 3px 3px 3px 3px;margin-right: 10px;">
</div>
<div class="legendName" style="font-size: 12px;color: #FFFFFF;">中型车辆</div>
</div>
<div class="legendItem" style="display: flex;align-items: center;">
<div class="legendIcon"
style="width: 14px;height: 14px;background: #FF9500;border-radius: 3px 3px 3px 3px;margin-right: 10px;">
</div>
<div class="legendName" style="font-size: 12px;color: #FFFFFF;">大型车辆 </div>
</div>
</div>
</template> -->
</SmallTitle>
<div class="VehiclesEnteringCharts">
<!-- <div class="VehiclesEnteringUnit"></div> -->
<div class="VehiclesEntering" id="VehiclesEntering"></div>
</div>
<SmallTitle :title="'对客营收'" style="margin-top: 23px;" />
<div class="TrendCustomerRevenueCharts">
<div class="TrendCustomerRevenue" id="TrendCustomerRevenue"></div>
</div>
</div>
</template>