feat: add pie chart

This commit is contained in:
ulleo
2025-06-10 17:38:00 +08:00
parent 3fd9e976c2
commit 167505a74c
10 changed files with 89 additions and 24 deletions
+2 -2
View File
@@ -55,10 +55,10 @@ template:
{{"type":"bar", "title": "标题", "axis": {{"x": {{"name":"x轴的中文名称", "value": "SQL 查询 x 轴的列(有别名用别名)"}}, "y": {{"name":"y轴的中文名称","value": "SQL 查询 y 轴的列(有别名用别名)"}}}}
必须从 SQL 查询列中提取“x”和“y”。
- 如果需要折线图,则生成的 JSON 格式应为:
{{"type":"line", "title": "标题", "axis": {{"x": {{"name":"x轴的中文名称","value": "x轴的SQL查询列(有别名用别名)"}}, "y": {{"name":"y轴的中文名称","value": "y轴的SQL查询列(有别名用别名)"}}}}
{{"type":"line", "title": "标题", "axis": {{"x": {{"name":"x轴的中文名称","value": "SQL 查询 x 轴的列(有别名用别名)"}}, "y": {{"name":"y轴的中文名称","value": "SQL 查询 y 轴的列(有别名用别名)"}}}}
其中“x”和“y”必须从SQL查询列中提取。
- 如果需要饼图,则生成的 JSON 格式应为:
{{"type":"pie", "title": "标题", "columns": [{{"name":"中文字段名1","value":"SQL查询列1(有别名用别名)"}},{{"name":"中文字段名2","value":"SQL查询列2(有别名用别名)"}}]}}
{{"type":"pie", "title": "标题", "axis": {{"y": {{"值轴的中文名称","value":"SQL 查询数值的列(有别名用别名)"}}, "series": {{"name":"分类的中文名称","value":"SQL 查询分类的列(有别名用别名)"}}}}
其中“column”必须从SQL查询列中提取。
- 如果答案未知或者与生成JSON无关,则生成的 JSON 格式应为:
{{"type":"error", "reason": "抱歉,我无法回答您的问题。"}}
+17 -5
View File
@@ -5,6 +5,7 @@ import {computed, nextTick, ref} from "vue";
import type {TabsPaneContext} from 'element-plus-secondary'
import {Loading} from "@element-plus/icons-vue";
import Component from "./component/Component.vue"
import type {ChartTypes} from "@/views/chat/component/BaseChart.ts";
const props = defineProps<{
message?: ChatMessage
@@ -43,9 +44,13 @@ const dataObject = computed<{
})
const chartObject = computed<{
type: "table" | "bar" | "line" | "pie"
type: ChartTypes
title: string
axis: { x: { name: string, value: string }, y: { name: string, value: string } }
axis: {
x: { name: string, value: string },
y: { name: string, value: string },
series: { name: string, value: string }
}
columns: Array<{ name: string, value: string }>
}>(() => {
if (props.message?.record?.chart) {
@@ -66,10 +71,16 @@ const yAxis = computed(() => {
}
return []
})
const series = computed(() => {
if (chartObject.value?.axis?.series) {
return [chartObject.value.axis.series]
}
return []
})
const currentChartType = ref<"table" | "bar" | 'column' | "line" | "pie" | undefined>(undefined)
const currentChartType = ref<ChartTypes | undefined>(undefined)
const chartType = computed<"table" | "bar" | 'column' | "line" | "pie">({
const chartType = computed<ChartTypes>({
get() {
if (currentChartType.value) {
return currentChartType.value
@@ -158,6 +169,7 @@ function onTypeChange(type: string) {
:columns="chartObject?.columns"
:x="xAxis"
:y="yAxis"
:series="series"
:data="dataObject.data"/>
</div>
</div>
@@ -189,6 +201,6 @@ function onTypeChange(type: string) {
.chart-base-container {
padding: 20px;
background: rgba(224,224,226,0.29);
background: rgba(224, 224, 226, 0.29);
}
</style>
+15 -3
View File
@@ -1,15 +1,27 @@
export interface ChartAxis {
name: string,
value: string,
type?: 'x' | 'y' | 'series'
}
export interface ChartData {
[key: string]: any
}
export type ChartTypes = "table" | "bar" | 'column' | "line" | "pie"
export abstract class BaseChart {
id: string;
_name: string = 'base-chart';
axis: Array<{ name: string, value: string, type?: 'x' | 'y' }> = [];
data: Array<{ [key: string]: any }> = [];
axis: Array<ChartAxis> = [];
data: Array<ChartData> = [];
constructor(id: string, name: string) {
this.id = id;
this._name = name;
}
init(axis: Array<{ name: string, value: string, type?: 'x' | 'y' }>, data: Array<{ [key: string]: any }>): void {
init(axis: Array<ChartAxis>, data: Array<ChartData>): void {
this.axis = axis;
this.data = data;
}
@@ -1,20 +1,22 @@
<script setup lang="ts">
import {computed, onMounted, onUnmounted} from "vue";
import {getChartInstance} from "@/views/chat/component/index.ts";
import type {BaseChart} from "@/views/chat/component/BaseChart.ts";
import type {BaseChart, ChartAxis, ChartData} from "@/views/chat/component/BaseChart.ts";
const params = withDefaults(defineProps<{
id: string | number
type: string
data?: Array<{ [key: string]: any }>
columns?: Array<{ name: string, value: string }>
x?: Array<{ name: string, value: string }>
y?: Array<{ name: string, value: string }>
data?: Array<ChartData>
columns?: Array<ChartAxis>
x?: Array<ChartAxis>
y?: Array<ChartAxis>
series?: Array<ChartAxis>
}>(), {
data: () => [],
columns: () => [],
x: () => [],
y: () => [],
series: () => [],
})
const chartId = computed(() => {
@@ -22,7 +24,7 @@ const chartId = computed(() => {
})
const axis = computed(() => {
const _list: Array<{ name: string, value: string, type?: 'x' | 'y' }> = []
const _list: Array<ChartAxis> = []
params.columns.forEach(column => {
_list.push({name: column.name, value: column.value})
})
@@ -32,6 +34,9 @@ const axis = computed(() => {
params.y.forEach(column => {
_list.push({name: column.name, value: column.value, type: 'y'})
})
params.series.forEach(column => {
_list.push({name: column.name, value: column.value, type: 'series'})
})
return _list
})
@@ -1,4 +1,5 @@
import {BaseG2Chart} from "@/views/chat/component/BaseG2Chart.ts";
import type {ChartAxis, ChartData} from "@/views/chat/component/BaseChart.ts";
export class Bar extends BaseG2Chart {
@@ -6,7 +7,7 @@ export class Bar extends BaseG2Chart {
super(id, "bar");
}
init(axis: Array<{ name: string; value: string; type: "x" | "y" }>, data: Array<{ [key: string]: any }>) {
init(axis: Array<ChartAxis>, data: Array<ChartData>) {
super.init(axis, data);
const x = this.axis.filter(item => item.type === "x");
const y = this.axis.filter(item => item.type === "y");
@@ -26,7 +27,7 @@ export class Bar extends BaseG2Chart {
.scale('y', {
nice: true,
})
.interaction('elementHighlight', { background: true });
.interaction('elementHighlight', {background: true});
}
@@ -1,4 +1,5 @@
import {BaseG2Chart} from "@/views/chat/component/BaseG2Chart.ts";
import type {ChartAxis, ChartData} from "@/views/chat/component/BaseChart.ts";
export class Column extends BaseG2Chart {
@@ -6,7 +7,7 @@ export class Column extends BaseG2Chart {
super(id, "column");
}
init(axis: Array<{ name: string; value: string; type: "x" | "y" }>, data: Array<{ [key: string]: any }>) {
init(axis: Array<ChartAxis>, data: Array<ChartData>) {
super.init(axis, data);
const x = this.axis.filter(item => item.type === "x");
@@ -26,7 +27,7 @@ export class Column extends BaseG2Chart {
.scale('y', {
nice: true,
})
.interaction('elementHighlight', { background: true });
.interaction('elementHighlight', {background: true});
}
@@ -1,4 +1,5 @@
import {BaseG2Chart} from "@/views/chat/component/BaseG2Chart.ts";
import type {ChartAxis, ChartData} from "@/views/chat/component/BaseChart.ts";
export class Line extends BaseG2Chart {
@@ -6,7 +7,7 @@ export class Line extends BaseG2Chart {
super(id, "line");
}
init(axis: Array<{ name: string; value: string; type: "x" | "y" }>, data: Array<{ [key: string]: any }>) {
init(axis: Array<ChartAxis>, data: Array<ChartData>) {
super.init(axis, data);
const x = this.axis.filter(item => item.type === "x");
@@ -0,0 +1,32 @@
import {BaseG2Chart} from "@/views/chat/component/BaseG2Chart.ts";
import type {ChartAxis, ChartData} from "@/views/chat/component/BaseChart.ts";
export class Pie extends BaseG2Chart {
constructor(id: string) {
super(id, "pie");
}
init(axis: Array<ChartAxis>, data: Array<ChartData>) {
super.init(axis, data);
const y = this.axis.filter(item => item.type === "y");
const series = this.axis.filter(item => item.type === "series");
if (series.length == 0 || y.length == 0) {
return;
}
this.chart.coordinate({type: 'theta', outerRadius: 0.8});
this.chart?.interval()
.transform({type: 'stackY'})
.data(data)
.encode('y', y[0].value)
.encode('color', series[0].value)
.legend('color', {position: 'bottom', layout: {justifyContent: 'center'}})
;
}
}
@@ -1,4 +1,4 @@
import {BaseChart} from "@/views/chat/component/BaseChart.ts";
import {BaseChart, type ChartAxis, type ChartData} from "@/views/chat/component/BaseChart.ts";
import {TableSheet, type S2Options, type S2DataConfig, type S2MountContainer} from "@antv/s2";
import {debounce} from "lodash-es";
@@ -33,7 +33,7 @@ export class Table extends BaseChart {
}
}
init(axis: Array<{ name: string; value: string; type: "x" | "y" }>, data: Array<{ [key: string]: any }>) {
init(axis: Array<ChartAxis>, data: Array<ChartData>) {
super.init(axis, data);
const s2DataConfig: S2DataConfig = {
+2 -1
View File
@@ -3,13 +3,14 @@ import {Bar} from "@/views/chat/component/charts/Bar.ts";
import {Column} from "@/views/chat/component/charts/Column.ts";
import {Line} from "@/views/chat/component/charts/Line.ts";
import {Table} from "@/views/chat/component/charts/Table.ts";
import {Pie} from "@/views/chat/component/charts/Pie.ts";
const CHART_TYPE_MAP: { [key: string]: any } = {
"table": Table,
"column": Column,
"bar": Bar,
"line": Line,
"pie": undefined
"pie": Pie
}
const isParent = (type: any, parentType: any) => {