Skip to content

Commit 2512276

Browse files
committed
feat: chart type select
1 parent 7b2695e commit 2512276

File tree

7 files changed

+209
-24
lines changed

7 files changed

+209
-24
lines changed
Lines changed: 7 additions & 0 deletions
Loading
Lines changed: 7 additions & 0 deletions
Loading
Lines changed: 5 additions & 0 deletions
Loading
Lines changed: 4 additions & 0 deletions
Loading
Lines changed: 12 additions & 0 deletions
Loading

frontend/src/views/chat/ChatAnswer.vue

Lines changed: 174 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,16 @@
22
33
import type {ChatMessage} from "@/api/chat.ts";
44
import {computed, nextTick, ref} from "vue";
5-
import type {TabsPaneContext} from 'element-plus-secondary'
65
import {Loading} from "@element-plus/icons-vue";
7-
import Component from "./component/Component.vue"
6+
import ChartComponent from "./component/ChartComponent.vue"
87
import type {ChartTypes} from "@/views/chat/component/BaseChart.ts";
8+
import {ArrowDown} from "@element-plus/icons-vue";
9+
import ICON_BAR from "@/assets/svg/chart/bar.svg"
10+
import ICON_COLUMN from "@/assets/svg/chart/column.svg"
11+
import ICON_LINE from "@/assets/svg/chart/line.svg"
12+
import ICON_PIE from "@/assets/svg/chart/pie.svg"
13+
import ICON_TABLE from "@/assets/svg/chart/table.svg"
14+
import {find} from "lodash-es";
915
1016
const props = defineProps<{
1117
message?: ChatMessage
@@ -29,10 +35,6 @@ const renderChartThinking = computed(() => {
2935
return props.message?.record?.chart_answer
3036
})
3137
32-
const handleClick = (tab: TabsPaneContext, event: Event) => {
33-
console.log(tab, event)
34-
}
35-
3638
const dataObject = computed<{
3739
fields: Array<string>,
3840
data: Array<{ [key: string]: any }>,
@@ -92,10 +94,59 @@ const chartType = computed<ChartTypes>({
9294
}
9395
})
9496
97+
function clickTab(type: "chart" | "sql") {
98+
settings.value.type = type
99+
}
100+
101+
const chartSelectRef = ref()
102+
103+
function openChartSelect() {
104+
chartSelectRef.value.toggleMenu()
105+
}
106+
107+
const chartTypeList = computed(() => {
108+
const _list = [{
109+
value: "table",
110+
icon: ICON_TABLE
111+
}]
112+
if (chartObject.value) {
113+
switch (chartObject.value.type) {
114+
case "table":
115+
break
116+
case "column":
117+
case "bar":
118+
case "line":
119+
_list.push({
120+
value: "column",
121+
icon: ICON_COLUMN
122+
})
123+
_list.push({
124+
value: "bar",
125+
icon: ICON_BAR
126+
})
127+
_list.push({
128+
value: "line",
129+
icon: ICON_LINE
130+
})
131+
break
132+
case "pie":
133+
_list.push({
134+
value: "pie",
135+
icon: ICON_PIE
136+
})
137+
}
138+
}
139+
140+
return _list;
141+
})
142+
143+
const currentChartTypeIcon = computed(() => {
144+
return find(chartTypeList.value, c => c.value === chartType.value)?.icon ?? ICON_TABLE
145+
})
146+
95147
const chartRef = ref()
96148
97-
function onTypeChange(type: string) {
98-
console.log(type)
149+
function onTypeChange() {
99150
nextTick(() => {
100151
chartRef.value?.destroyChart()
101152
chartRef.value?.renderChart()
@@ -112,21 +163,36 @@ function onTypeChange(type: string) {
112163
<div v-if="message.isTyping">Thinking ...</div>
113164
<div v-if="chartObject.title && !message.isTyping">{{ chartObject.title }}</div>
114165
</div>
115-
<el-tabs v-model="settings.type" class="type-tabs" @tab-click="handleClick" tab-position="top">
116-
<el-tab-pane label="Chart" name="chart">
117-
<template #label>
118-
<el-select v-model="chartType" style="width: 80px" :disabled="settings.type!== 'chart'"
119-
@change="onTypeChange">
120-
<el-option value="table">table</el-option>
121-
<el-option value="column">column</el-option>
122-
<el-option value="bar">bar</el-option>
123-
<el-option value="line">line</el-option>
124-
<el-option value="pie">pie</el-option>
125-
</el-select>
126-
</template>
127-
</el-tab-pane>
128-
<el-tab-pane label="SQL" name="sql"></el-tab-pane>
129-
</el-tabs>
166+
<div class="tab-container">
167+
<div class="base-chart-choose-btn" @click="clickTab('chart')">
168+
<div class="chart-choose-btn"
169+
:class="{'active': settings.type === 'chart', 'no-click': settings.type !== 'chart'}"
170+
@click="openChartSelect">
171+
<el-icon size="34">
172+
<component :is="currentChartTypeIcon"/>
173+
</el-icon>
174+
<el-icon>
175+
<ArrowDown/>
176+
</el-icon>
177+
</div>
178+
<el-select v-model="chartType" class="inner-select" :disabled="settings.type!== 'chart'"
179+
ref="chartSelectRef"
180+
@change="onTypeChange">
181+
<el-option v-for="t in chartTypeList " :key="t.value" :value="t.value">
182+
<div class="inner-chart-option">
183+
<el-icon size="34">
184+
<component :is="t.icon"/>
185+
</el-icon>
186+
{{ t.value }}
187+
</div>
188+
</el-option>
189+
</el-select>
190+
191+
</div>
192+
<div class="chart-choose-btn" :class="{'active': settings.type !== 'chart'}" @click="clickTab('sql')">
193+
SQL
194+
</div>
195+
</div>
130196
</el-header>
131197
<el-container direction="vertical">
132198
<template v-if="message.record">
@@ -163,7 +229,7 @@ function onTypeChange(type: string) {
163229
<div>
164230
<div v-if="message.record.chart" class="chart-base-container">
165231
<div>
166-
<Component
232+
<ChartComponent
167233
ref="chartRef"
168234
v-if="message.record.id"
169235
:id="message.record.id"
@@ -205,4 +271,88 @@ function onTypeChange(type: string) {
205271
padding: 20px;
206272
background: rgba(224, 224, 226, 0.29);
207273
}
274+
275+
.tab-container {
276+
display: flex;
277+
flex-direction: row;
278+
align-items: center;
279+
gap: 4px;
280+
}
281+
282+
.base-chart-choose-btn {
283+
cursor: pointer;
284+
color: var(--ed-color-primary);
285+
font-size: 16px;
286+
font-weight: 500;
287+
height: 34px;
288+
289+
border-radius: 4px;
290+
291+
position: relative;
292+
293+
&:hover {
294+
background: var(--ed-color-primary-light-5);
295+
color: var(--ed-color-primary-light-9);
296+
}
297+
298+
.inner-select {
299+
300+
position: absolute;
301+
302+
:deep(.ed-select__wrapper) {
303+
height: 0;
304+
padding: unset;
305+
min-height: unset;
306+
line-height: unset;
307+
}
308+
309+
:deep(.ed-select__suffix) {
310+
display: none;
311+
}
312+
313+
:deep(.ed-select__selected-item) {
314+
display: none;
315+
}
316+
317+
}
318+
319+
}
320+
321+
.inner-chart-option {
322+
display: flex;
323+
align-items: center;
324+
flex-direction: row;
325+
padding-right: 4px;
326+
}
327+
328+
.chart-choose-btn {
329+
330+
cursor: pointer;
331+
color: var(--ed-color-primary);
332+
font-size: 16px;
333+
font-weight: 500;
334+
height: 34px;
335+
336+
border-radius: 4px;
337+
338+
display: flex;
339+
flex-direction: row;
340+
align-items: center;
341+
justify-content: center;
342+
padding: 0 4px;
343+
344+
&.no-click {
345+
pointer-events: none;
346+
}
347+
348+
&.active {
349+
background: var(--ed-color-primary-light-7);
350+
color: var(--ed-color-primary);
351+
}
352+
353+
&:hover {
354+
background: var(--ed-color-primary-light-5);
355+
color: var(--ed-color-primary-light-9);
356+
}
357+
}
208358
</style>

0 commit comments

Comments
 (0)