| | |
| | | <template> |
| | | <el-tabs v-model="activeName" class="demo-tabs min-w-[38rem] flex-column" @tab-click="handleClick"> |
| | | <el-tabs v-model="activeName" class="demo-tabs min-w-[38rem] flex-column"> |
| | | <el-tab-pane class="h-full" label="Chart" name="first"> |
| | | <el-select class="flex-0 w-36" v-model="selectChartType" @change="selectChartTypeChange"> |
| | | <el-option |
| | | v-for="item in Object.keys(chartTypeMapName)" |
| | | :key="item" |
| | | :value="parseInt(item)" |
| | | :label="chartTypeMapName[item]" |
| | | ></el-option> |
| | | </el-select> |
| | | <div class="flex-auto"> |
| | | <div class="flex-auto" v-resize="chartContainerResize"> |
| | | <div ref="chartRef" class="h-full"></div> |
| | | </div> |
| | | </el-tab-pane> |
| | | <el-tab-pane class="h-full" label="Data" name="second"> |
| | | <el-table :data="data.values" style="width: 100%"> |
| | | <el-table :data="data.values" style="width: 100%" cellClassName="text-sm" headerCellClassName="text-sm"> |
| | | <el-table-column v-for="(item, index) in data?.names" :label="item" :key="index"> |
| | | <template #default="scope"> |
| | | {{ scope.row[index] }} |
| | |
| | | </el-tabs> |
| | | </template> |
| | | <script lang="ts" setup> |
| | | import * as echarts from 'echarts'; |
| | | import type { TabsPaneContext } from 'element-plus'; |
| | | import type { PropType } from 'vue'; |
| | | import { onMounted, ref } from 'vue'; |
| | | import { ChartTypeEnum, chartTypeMapEchart, chartTypeMapName } from '../types'; |
| | | import type { RecordSetValues } from '/@/api/ai/chat'; |
| | | import { dateRegex } from '/@/utils/toolsValidate'; |
| | | import type * as echarts from 'echarts'; |
| | | import _ from 'lodash'; |
| | | import { ref } from 'vue'; |
| | | import { SCATTER_SYMBOL_SIZE, chatComProps, getChatChartOption } from '../common'; |
| | | import { useDrawChatChart } from '../hooks/useDrawChatChart'; |
| | | const activeName = ref('first'); |
| | | const chartRef = ref<HTMLDivElement>(null); |
| | | const selectChartType = ref<ChartTypeEnum>(ChartTypeEnum.Line); |
| | | |
| | | const props = defineProps({ |
| | | data: { |
| | | type: Object as PropType<RecordSetValues>, |
| | | }, |
| | | }); |
| | | |
| | | |
| | | |
| | | const selectChartTypeChange = () => { |
| | | drawChart(); |
| | | }; |
| | | |
| | | const handleClick = (tab: TabsPaneContext, event: Event) => {}; |
| | | |
| | | let chartInstance: echarts.ECharts = null; |
| | | |
| | | const getXType = (xData?: any[]) => { |
| | | const xValue = xData?.[0]; |
| | | if (xValue == null) return 'value'; |
| | | if (typeof xValue === 'number') { |
| | | return 'value'; |
| | | } else if (typeof xValue === 'string') { |
| | | const isValidDate = dateRegex.test(xValue); |
| | | return isValidDate ? 'time' : 'category'; |
| | | } else { |
| | | throw '图表x轴数据类型异常'; |
| | | } |
| | | }; |
| | | const defaultChartType = 'line'; |
| | | const props = defineProps(chatComProps); |
| | | |
| | | const drawChart = () => { |
| | | const xData = props.data.values?.map((item) => item[0]); |
| | | const xType = getXType(xData); |
| | | chartInstance.setOption({ |
| | | grid: { |
| | | // bottom: 120, |
| | | right:'15%', |
| | | bottom: '15%', |
| | | }, |
| | | tooltip: { |
| | | show: true, |
| | | }, |
| | | title: { |
| | | text: props.data.title, |
| | | left: 'center', |
| | | |
| | | }, |
| | | xAxis: { |
| | | name: props.data?.names[0], |
| | | type: xType, |
| | | }, |
| | | yAxis: { |
| | | name: props.data?.names[1], |
| | | type: 'value', |
| | | }, |
| | | series: [ |
| | | { |
| | | data: props.data.values, |
| | | type: chartTypeMapEchart[selectChartType.value], |
| | | chartInstance.value.setOption( |
| | | _.defaultsDeep(getChatChartOption(), { |
| | | grid: { |
| | | bottom: '5%', |
| | | }, |
| | | ], |
| | | dataZoom: { |
| | | type: 'inside', |
| | | }, |
| | | }); |
| | | |
| | | toolbox: { |
| | | feature: { |
| | | myBar: { |
| | | onclick: () => { |
| | | chartInstance.value.setOption({ |
| | | series: { |
| | | data: props.data.values, |
| | | type: 'bar', |
| | | symbol: 'none', |
| | | }, |
| | | }); |
| | | }, |
| | | }, |
| | | |
| | | myScatter: { |
| | | onclick: () => { |
| | | chartInstance.value.setOption({ |
| | | data: props.data.values, |
| | | type: 'scatter', |
| | | symbol: 'circle', |
| | | symbolSize: SCATTER_SYMBOL_SIZE, |
| | | }); |
| | | }, |
| | | }, |
| | | myLine: { |
| | | onclick: () => { |
| | | chartInstance.value.setOption({ |
| | | data: props.data.values, |
| | | type: 'line', |
| | | symbol: 'none', |
| | | smooth: true, |
| | | }); |
| | | }, |
| | | }, |
| | | }, |
| | | }, |
| | | |
| | | title: { |
| | | text: props.data.title, |
| | | }, |
| | | xAxis: { |
| | | name: props.data?.names[0], |
| | | }, |
| | | yAxis: { |
| | | name: props.data?.names[1], |
| | | }, |
| | | series: [ |
| | | { |
| | | data: props.data.values, |
| | | symbol: 'none', |
| | | smooth: true, |
| | | type: defaultChartType, |
| | | }, |
| | | ], |
| | | } as echarts.EChartsOption) |
| | | ); |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | setTimeout(() => { |
| | | |
| | | const parent = chartRef.value.parentElement; |
| | | if(!parent){ |
| | | } |
| | | const parentBound = parent.getBoundingClientRect(); |
| | | chartInstance = echarts.init(chartRef.value,undefined,{ |
| | | width:parentBound.width, |
| | | height:parentBound.height |
| | | }); |
| | | |
| | | drawChart(); |
| | | }, 300); |
| | | }); |
| | | const { chartContainerResize, chartInstance } = useDrawChatChart({ chartRef, drawChart }); |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |