| | |
| | | <template> |
| | | <div v-show="!tableIsShow"> |
| | | <div> |
| | | <div> |
| | | <div class="h-full" v-loading="chartLoading" v-resize="chartContainerResize"> |
| | | <div ref="chartRef"></div> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup lang="ts" name="ChartDisplay"> |
| | | import { ref } from 'vue'; |
| | | import { defaultsDeep, groupBy } from 'lodash-es'; |
| | | import { computed, onMounted, ref, watch } from 'vue'; |
| | | import { getChatChartOption, SCATTER_SYMBOL_SIZE } from '../../../chatComponents/common'; |
| | | import { ChartTypeEnum } from '../../../chatComponents/types'; |
| | | import { useDrawChatChart } from '/@/components/chat/chatComponents/hooks/useDrawChatChart'; |
| | | |
| | | const props = defineProps({ |
| | | tableIsShow: { |
| | | type: Boolean, |
| | | default: false, |
| | | tableSchema: { |
| | | type: Object as any, |
| | | default: () => {}, |
| | | }, |
| | | records: { |
| | | type: Object as any, |
| | | default: () => {}, |
| | | }, |
| | | }); |
| | | const chartRef = ref<HTMLDivElement>(); |
| | | |
| | | const drawChart = () => { |
| | | const columns = props.tableSchema?.columns ?? []; |
| | | if (columns.length === 0) return; |
| | | |
| | | const xRow = columns.find((item) => item.chart_type === 'time'); |
| | | const yRow = columns.find((item) => item.chart_type === 'value'); |
| | | const seriesNameRow = columns.find((item) => item.chart_type === 'name'); |
| | | const combineOption = defaultsDeep( |
| | | { |
| | | grid: { |
| | | bottom: 20, |
| | | }, |
| | | legend: { |
| | | top: 19, |
| | | show: true, |
| | | type: 'scroll', |
| | | }, |
| | | tooltip: { |
| | | // valueFormatter: tooltipValueFormatter, |
| | | }, |
| | | toolbox: { |
| | | show: true, |
| | | feature: { |
| | | myBar: { |
| | | onclick: () => { |
| | | activeChartType = ChartTypeEnum.Bar; |
| | | chartInstance.value.setOption({ |
| | | series: seriesInfo.value.map((item) => ({ |
| | | ...item, |
| | | ...getChartTypeSeriesOption(activeChartType), |
| | | })), |
| | | }); |
| | | }, |
| | | }, |
| | | |
| | | myScatter: { |
| | | onclick: () => { |
| | | activeChartType = ChartTypeEnum.Scatter; |
| | | |
| | | chartInstance.value.setOption({ |
| | | series: seriesInfo.value.map((item) => ({ |
| | | ...item, |
| | | ...getChartTypeSeriesOption(activeChartType), |
| | | })), |
| | | }); |
| | | }, |
| | | }, |
| | | myLine: { |
| | | onclick: () => { |
| | | activeChartType = ChartTypeEnum.Line; |
| | | chartInstance.value.setOption({ |
| | | series: seriesInfo.value.map((item) => ({ |
| | | ...item, |
| | | ...getChartTypeSeriesOption(activeChartType), |
| | | })), |
| | | }); |
| | | }, |
| | | }, |
| | | }, |
| | | }, |
| | | |
| | | title: { |
| | | text: props.tableSchema?.title, |
| | | }, |
| | | xAxis: { |
| | | name: xRow?.title, |
| | | }, |
| | | yAxis: { |
| | | name: yRow?.title, |
| | | |
| | | /** @description 不强制保留 */ |
| | | scale: true, |
| | | }, |
| | | series: seriesInfo.value, |
| | | } as echarts.EChartsOption, |
| | | getChatChartOption() |
| | | ); |
| | | chartInstance.value?.setOption(combineOption, { |
| | | notMerge: true, |
| | | }); |
| | | }; |
| | | |
| | | const getChartTypeSeriesOption = (type: ChartTypeEnum) => { |
| | | let result = {}; |
| | | switch (type) { |
| | | case ChartTypeEnum.Bar: |
| | | result = { |
| | | type: 'bar', |
| | | symbol: 'none', |
| | | }; |
| | | |
| | | break; |
| | | case ChartTypeEnum.Line: |
| | | result = { |
| | | type: 'line', |
| | | symbol: 'none', |
| | | smooth: true, |
| | | }; |
| | | |
| | | break; |
| | | |
| | | case ChartTypeEnum.Scatter: |
| | | result = { |
| | | type: 'scatter', |
| | | symbol: 'circle', |
| | | symbolSize: SCATTER_SYMBOL_SIZE, |
| | | }; |
| | | |
| | | break; |
| | | case ChartTypeEnum.Score: |
| | | result = { |
| | | type: 'bar', |
| | | symbol: 'none', |
| | | }; |
| | | |
| | | break; |
| | | |
| | | default: |
| | | break; |
| | | } |
| | | |
| | | return result; |
| | | }; |
| | | let activeChartType: ChartTypeEnum = ChartTypeEnum.Line; |
| | | |
| | | const seriesInfo = computed(() => { |
| | | const columns = props.tableSchema.columns ?? []; |
| | | if (columns.length === 0) return []; |
| | | const xProp = columns.find((item) => item.chart_type === 'time')?.name; |
| | | const yProp = columns.find((item) => item.chart_type === 'value')?.name; |
| | | const seriesNameProp = columns.find((item) => item.chart_type === 'name')?.name; |
| | | const groupedValues = groupBy(props.records, (item) => item[seriesNameProp]); |
| | | const series = Object.entries(groupedValues).map(([key, value]) => { |
| | | return { |
| | | name: key, |
| | | data: value |
| | | .toSorted((b, a) => { |
| | | return b[xProp]?.localeCompare(a[xProp]); |
| | | }) |
| | | .map((item) => [item[xProp], item[yProp]]), |
| | | ...getChartTypeSeriesOption(activeChartType), |
| | | }; |
| | | }); |
| | | |
| | | return series; |
| | | }); |
| | | |
| | | const chartLoading = ref(false); |
| | | const { chartContainerResize, chartInstance } = useDrawChatChart({ chartRef, drawChart }); |
| | | |
| | | watch( |
| | | () => props.records, |
| | | (val) => { |
| | | drawChart(); |
| | | } |
| | | ); |
| | | </script> |
| | | <style scoped lang="scss"></style> |