ylj20011123 d829c7bc93 update
2025-06-23 19:16:56 +08:00

264 lines
7.6 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 './BusinessStructure.less'
import { onMounted, onBeforeUnmount, ref, watch } from 'vue';
import * as echarts from 'echarts/core';
import { PieChart } from 'echarts/charts';
import {
GridComponent,
TitleComponent,
TooltipComponent,
LegendComponent,
GraphicComponent
} from 'echarts/components';
import { CanvasRenderer } from 'echarts/renderers';
import businessFormatCenterIcon from '../../../../assets/image/businessFormatCenterIcon.png'
import moment from 'moment';
import { handleGetBusinessTradeRevenue } from '../../service';
// 注册组件
echarts.use([
PieChart,
GridComponent,
TitleComponent,
TooltipComponent,
LegendComponent,
GraphicComponent,
CanvasRenderer
]);
let myChart: echarts.ECharts;
// 自定义颜色列表
const colorList = ['#FF9500', '#00FFB7', '#0094FF', '#7D4CD2', '#69BCFF'];
// 图例数据
let lengedList = ref<any>([])
onMounted(async () => {
await handleGoMounted()
})
// 初始运行的方法
const handleGoMounted = async () => {
const res: any = await handleGetData()
const chartDom = document.getElementById('BusinessStructure');
if (!chartDom) return;
myChart = echarts.init(chartDom);
const rect = chartDom.getBoundingClientRect();
const width = rect.width;
const height = rect.height;
// 计算center位置20%50%)对应的实际像素
const centerX = width * 0.2;
const centerY = height * 0.5;
const option = {
tooltip: { // 新增 tooltip 配置
trigger: 'item', // 触发类型:坐标轴触发
axisPointer: { // 坐标轴指示器配置
type: 'shadow' // 阴影指示器(适合柱状图)
},
formatter: function (params: any) { // 自定义提示框内容
return `
<div style="font-weight:bold">${params.data.name} ${params?.percent}% ${res.realData[params.dataIndex]}</div>
`;
}
},
graphic: { // 关键配置:在图表中心添加图片
elements: [
{
type: 'image',
style: {
image: businessFormatCenterIcon,
width: 83,
height: 83
},
left: centerX - 41.5,
top: centerY - 41.5,
z: 10
}
]
},
series: [
{
name: 'Access From',
type: 'pie',
radius: ['85%', '100%'],
center: ['20%', '50%'], // 图形向左偏移
avoidLabelOverlap: false,
itemStyle: {
color: function (params: any) {
return colorList[params.dataIndex];
}
},
label: {
show: false
},
emphasis: false,
labelLine: {
show: false
},
data: res.seriesData
}
],
legend: {
orient: 'vertical',
left: 160,
top: 'center',
align: 'left',
itemGap: 10,
itemWidth: 12,
itemHeight: 12,
textStyle: {
color: '#fff',
rich: {
name: {
width: 90, // 固定名称宽度
align: 'left',
padding: [0, 10, 0, 0]
},
percent: {
width: 50, // 固定百分比宽度
align: 'right',
padding: [0, 10, 0, 0]
}
}
},
formatter: function (name: any) {
let percentData: any = res.lengedData.filter((item: any) => item.name === name)
return `{name|${name}}{percent|${percentData[0].value}%}`; // 使用rich样式
}
}
};
myChart.setOption(option);
myChart.resize();
window.addEventListener('resize', resizeChart);
}
// 拿到传入的数据
const props = defineProps<{
currentService?: any;
}>();
// 监听传入的选中服务区
watch(
() => props.currentService,
(newVal, oldVal) => {
handleGoMounted()
},
{ deep: true }
);
// 业态结构占比
const handleGetData = async () => {
const req: any = {
ProvinceCode: '530000',
StatisticsDate: moment().subtract(1, 'd').format('YYYY-MM-DD'),
// StatisticsDate: '2025-04-30',
BusinessTradeIds: -1,
ServerpartId: props.currentService?.SERVERPART_ID || ""
}
let BusinessStructure = sessionStorage.getItem('BusinessStructure')
let data: any = []
if (BusinessStructure) {
data = JSON.parse(BusinessStructure)
} else {
data = await handleGetBusinessTradeRevenue(req)
sessionStorage.setItem("BusinessStructure", JSON.stringify(data))
}
// const data = await handleGetBusinessTradeRevenue(req)
let aiObj: any = {}
let list: any = data.BusinessTradeRank
let seriesData: any = []
let realData: any = []
let category: any = []
let lengedLists: any = []
let lengedData: any = []
if (list && list.length > 0) {
list.forEach((item: any) => {
seriesData.push({ value: Number(item.value), name: item.name })
realData.push(item.data)
category.push(item.name)
lengedLists.push({
name: item.name,
percent: Number(item.value),
value: item.data
})
lengedData.push({
name: item.name,
value: item.value
})
aiObj[item.name] = item.data
})
}
let res: any = {
category: category,// x轴的内容
seriesData: seriesData,// y轴的数据
realData: realData,// 真实数据
lengedData: lengedData
}
lengedList.value = lengedLists
let BusinessStructureAI = sessionStorage.getItem('BusinessStructureAI')
if (BusinessStructureAI) { } else {
sessionStorage.setItem("BusinessStructureAI", JSON.stringify(aiObj))
}
return res
}
const resizeChart = () => {
myChart?.resize();
};
onBeforeUnmount(() => {
window.removeEventListener('resize', resizeChart);
myChart?.dispose();
});
</script>
<template>
<div class="BusinessStructureBox">
<SmallTitle :title="'业态结构占比'"></SmallTitle>
<div class="BusinessStructureCharts">
<!-- <div class="BusinessStructureUnit">万元</div> -->
<div class="BusinessStructure" id="BusinessStructure"></div>
<!-- <div class="BusinessStructureDataList">
<div class="BusinessStructureDataBox" v-for="(item, index) in lengedList" :key="index">
<div class="BusinessStructureDataLeftBox">
<div class="BusinessStructureItem">
<div class="BusinessStructureItemLeged" :style="{ background: colorList[index] }"></div>
<div class="BusinessStructureItemLabel">{{ item.name }}</div>
<div class="BusinessStructureItemLabel" style="margin-left: 8px;">{{ item.percent }}%
</div>
</div>
</div>
</div>
</div> -->
</div>
</div>
</template>