212 lines
6.5 KiB
Vue
212 lines
6.5 KiB
Vue
<script setup lang="ts">
|
||
import SmallTitle from '../smallTitle/smallTitle.vue';
|
||
import './CustomerConsumptionPreferences.less'
|
||
import * as echarts from 'echarts/core';
|
||
import { BarChart } from 'echarts/charts';
|
||
import {
|
||
GridComponent,
|
||
TitleComponent,
|
||
TooltipComponent,
|
||
LegendComponent
|
||
} from 'echarts/components';
|
||
import { CanvasRenderer } from 'echarts/renderers';
|
||
import { onBeforeUnmount, onMounted, watch } from 'vue';
|
||
import { handleGetCustomerSaleRatio } from '../../service';
|
||
import moment from 'moment';
|
||
|
||
// 注册组件
|
||
echarts.use([
|
||
BarChart,
|
||
GridComponent,
|
||
TitleComponent,
|
||
TooltipComponent,
|
||
LegendComponent,
|
||
CanvasRenderer
|
||
]);
|
||
|
||
let myChart: echarts.ECharts;
|
||
|
||
onMounted(async () => {
|
||
|
||
await handleGoMounted()
|
||
});
|
||
|
||
// 传入的数据
|
||
const props = defineProps<{
|
||
currentService?: any;
|
||
}>();
|
||
|
||
// 监听传入的选中服务区
|
||
watch(
|
||
() => props.currentService,
|
||
(newVal, oldVal) => {
|
||
handleGoMounted()
|
||
},
|
||
{ deep: true }
|
||
);
|
||
|
||
// 初始运行的方法
|
||
const handleGoMounted = async () => {
|
||
const res = await handleGetData()
|
||
|
||
const chartDom = document.getElementById('CustomerConsumptionPreferencesCharts');
|
||
if (!chartDom) return;
|
||
|
||
myChart = echarts.init(chartDom);
|
||
|
||
const option = {
|
||
xAxis: {
|
||
type: 'category',
|
||
data: res.category,
|
||
axisLabel: {
|
||
width: 40, // 限制标签宽度为60px
|
||
overflow: 'truncate', // 超出部分显示为省略号
|
||
ellipsis: '...', // 自定义省略符号(可选)
|
||
interval: 0 // 强制显示所有标签
|
||
// rotate: 30, // 标签旋转30度(防止重叠)
|
||
},
|
||
axisLine: {
|
||
show: true,
|
||
lineStyle: {
|
||
color: '#fff'
|
||
}
|
||
},
|
||
// data: res.category
|
||
},
|
||
yAxis: {
|
||
type: 'value',
|
||
name: "万辆",
|
||
axisLine: {
|
||
show: true,
|
||
lineStyle: {
|
||
color: '#fff'
|
||
}
|
||
},
|
||
splitLine: { show: false } // 隐藏刻度线
|
||
},
|
||
series: [
|
||
{
|
||
// data: [120, 200, 150, 80, 70, 110, 130],
|
||
data: res.seriesData,
|
||
realData: res.realData,
|
||
type: 'bar',
|
||
barWidth: '6',
|
||
showBackground: true,
|
||
smooth: true,
|
||
backgroundStyle: {
|
||
borderRadius: [4, 4, 0, 0],
|
||
color: 'rgba(23, 42, 70, 1)'
|
||
},
|
||
itemStyle: {
|
||
borderRadius: [4, 4, 0, 0],
|
||
// 动态返回渐变颜色
|
||
color: function (params: any) {
|
||
const index = params.dataIndex; // 当前数据的索引
|
||
// 前3条(Mon, Tue, Wed)使用渐变1
|
||
if (index < 3) {
|
||
return new echarts.graphic.LinearGradient(
|
||
0, 0, 0, 1, // 渐变方向(垂直)
|
||
[
|
||
{ offset: 0, color: '#FF4F00' }, // 渐变起始色
|
||
{ offset: 1, color: '#D3B70E' } // 渐变结束色
|
||
]
|
||
);
|
||
}
|
||
// 后3条(Thu, Fri, Sat)使用渐变2
|
||
else {
|
||
return new echarts.graphic.LinearGradient(
|
||
0, 0, 0, 1,
|
||
[
|
||
{ offset: 0, color: '#018FFF' }, // 渐变起始色
|
||
{ offset: 1, color: '#00F4FF' } // 渐变结束色
|
||
]
|
||
);
|
||
}
|
||
}
|
||
}
|
||
},
|
||
],
|
||
grid: {
|
||
left: '0', // 左侧间距
|
||
right: '0', // 右侧间距
|
||
bottom: '0', // 底部间距
|
||
top: '10', // 顶部间距
|
||
containLabel: true // 确保坐标轴标签在grid内
|
||
},
|
||
tooltip: { // 新增 tooltip 配置
|
||
trigger: 'axis', // 触发类型:坐标轴触发
|
||
axisPointer: { // 坐标轴指示器配置
|
||
type: 'shadow' // 阴影指示器(适合柱状图)
|
||
},
|
||
formatter: function (params: any) { // 自定义提示框内容
|
||
// params 是数组,包含当前 hover 的所有系列数据
|
||
const data = params[0];
|
||
let realData = res.realData[params[0].dataIndex]
|
||
|
||
return `
|
||
<div style="font-weight:bold">${data.name}</div>
|
||
<div>车流量:${realData ? realData + '%' : data.value + '%'} </div>
|
||
`;
|
||
}
|
||
},
|
||
};
|
||
|
||
|
||
myChart.setOption(option);
|
||
window.addEventListener('resize', resizeChart);
|
||
}
|
||
|
||
const handleGetData = async () => {
|
||
const req: any = {
|
||
statisticsType: 1,
|
||
startMonth: moment().subtract(1, 'd').startOf('y').format('YYYYMM'),
|
||
endMonth: moment().subtract(1, 'm').format('YYYYMM'),
|
||
provinceCode: '530000',
|
||
serverpartId: props.currentService?.SERVERPART_ID || "",
|
||
sortStr: 'TOTAL_COUNT desc'
|
||
}
|
||
|
||
const data = await handleGetCustomerSaleRatio(req)
|
||
|
||
|
||
let category: string[] = []
|
||
let seriesData: number[] = []
|
||
let realData: string[] = []
|
||
|
||
|
||
if (data.CustomerSaleList && data.CustomerSaleList.length > 0) {
|
||
let list = data.CustomerSaleList.slice(0, 10)
|
||
list.forEach((item: any) => {
|
||
category.push(item.BusinessTradeName)
|
||
seriesData.push(item.TotalRatio)
|
||
realData.push(item.TotalRatio)
|
||
})
|
||
}
|
||
|
||
return {
|
||
category: category,
|
||
seriesData: seriesData,
|
||
realData: realData,
|
||
}
|
||
}
|
||
|
||
const resizeChart = () => {
|
||
myChart?.resize();
|
||
};
|
||
|
||
onBeforeUnmount(() => {
|
||
window.removeEventListener('resize', resizeChart);
|
||
myChart?.dispose();
|
||
});
|
||
|
||
</script>
|
||
|
||
<template>
|
||
<div class="CustomerConsumptionPreferencesBox">
|
||
<SmallTitle title="客群消费偏好" />
|
||
|
||
<div class="CustomerConsumptionPreferencesContent">
|
||
<div class="CustomerConsumptionPreferencesCharts" id="CustomerConsumptionPreferencesCharts"></div>
|
||
</div>
|
||
</div>
|
||
</template> |