go-viee-fetch-Demo/src/packages/components/Charts/ConfinedSpace/PieCircleCommen/index.vue

160 lines
4.2 KiB
Vue
Raw Normal View History

<template>
2025-08-27 10:01:26 +08:00
<div class="go-border-box">
<SmallBaorder01 :titleText="option.titleText" :title-option="option.titleOption"
:select-option="option.selectOption" :header-option="option.headerOption" @change="handleBorderSelectChange">
<v-chart class=" chart" ref="vChartRef" :theme="themeColor" :init-options="initOptions" :option="option"
autoresize> </v-chart>
</SmallBaorder01>
2025-08-27 10:01:26 +08:00
</div>
</template>
<script setup lang="ts">
import { computed, PropType, watch, onMounted } from 'vue'
import VChart from 'vue-echarts'
import { useCanvasInitOptions } from '@/hooks/useCanvasInitOptions.hook'
import { use } from 'echarts/core'
import { CanvasRenderer } from 'echarts/renderers'
import { PieChart } from 'echarts/charts'
import { mergeTheme } from '@/packages/public/chart'
import config, { includes } from './config'
import { useChartDataFetch } from '@/hooks'
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
import SmallBaorder01 from '../SmallBorder01Co/index.vue'
import {
DatasetComponent,
GridComponent,
TooltipComponent,
LegendComponent,
2025-08-27 10:01:26 +08:00
TitleComponent, GraphicComponent
} from 'echarts/components'
2025-08-27 10:01:26 +08:00
const props = defineProps({
themeSetting: {
type: Object,
required: true
},
themeColor: {
type: Object,
required: true
},
chartConfig: {
type: Object as PropType<config>,
required: true
}
})
const initOptions = useCanvasInitOptions(props.chartConfig.option, props.themeSetting)
2025-08-27 10:01:26 +08:00
use([
DatasetComponent,
CanvasRenderer,
PieChart,
GridComponent,
TooltipComponent,
LegendComponent,
TitleComponent,
GraphicComponent
])
const option = computed(() => {
return mergeTheme(props.chartConfig.option, props.themeSetting, includes)
})
// 总数计算
const calculateTotal = (data: any) => {
if (!data || !data.source) return 0
return data.source.reduce((total: number, item: any) => {
return total + (item[data.dimensions[1]] || 0)
}, 0)
}
// 计算百分比
const calculatePercentage = (value: number, total: number) => {
if (total === 0) return '0.0%';
const percentage = (value / total * 100).toFixed(1);
return `${percentage}%`;
};
// 处理数据更新
const dataHandle = (newData: any) => {
if (!newData) return
const total = calculateTotal(newData)
// 更新标题总数
props.chartConfig.option.title.text = `${total}`
// 更新图例格式化器,确保使用最新数据
props.chartConfig.option.legend.formatter = (name: string) => {
const item = newData.source.find((it: any) => it[newData.dimensions[0]] === name)
if (!item) return name;
const value = item[newData.dimensions[1]] ?? 0
const percentage = calculatePercentage(value, total)
// const value = item[newData.dimensions[1]];
// const percentage = calculatePercentage(value, total);
return `{title|${name}}\n{detail|${value}\t${percentage}}`;
};
// 更新tooplip
props.chartConfig.option.tooltip.formatter = (params: any) => {
// 获取当前数据项的名称和值
const name = params.name;
const item = newData.source.find((it: any) => it[newData.dimensions[0]] === name);
if (!item) return `${name}: 0(0.0%)`;
const value = item[newData.dimensions[1]] ?? 0;
const percentage = calculatePercentage(value, total);
return `${name}: ${value}(${percentage})`;
};
}
const handleBorderSelectChange = (newValue: string) => {
props.chartConfig.option.selectOption.selectValue = newValue // <--- 更新本地的响应式数据
console.log('选择器值已更改为:', newValue)
// 更新图表数据
}
// 监听配置中的数据集变化(配置时)
watch(
() => props.chartConfig.option.dataset,
(newData) => {
try {
dataHandle(newData)
} catch (error) {
console.error('数据处理错误:', error)
}
},
{
immediate: true,
deep: false
}
)
const { vChartRef } = useChartDataFetch(props.chartConfig, useChartEditStore, (newData: any) => {
props.chartConfig.option.dataset = newData
dataHandle(newData)
})
onMounted(() => {
dataHandle(props.chartConfig.option.dataset)
})
</script>
2025-08-27 10:01:26 +08:00
<style lang="scss" scoped>
@include go(border-box) {
width: 100%;
height: 100%;
}
.chart {
// position: relative;
z-index: 2;
width: 100%;
height: 100%;
}
2025-08-27 10:01:26 +08:00
</style>