mirror of
https://gh-proxy.org/https://github.com/klinsmaya/SQLBot.git
synced 2026-11-08 01:06:59 +08:00
Merge remote-tracking branch 'origin/main'
This commit is contained in:
@@ -66,6 +66,7 @@ template:
|
||||
其中“y”和“series”必须从SQL查询列中提取。
|
||||
- 如果答案未知或者与生成JSON无关,则生成的 JSON 格式应为:
|
||||
{{"type":"error", "reason": "抱歉,我无法回答您的问题。"}}
|
||||
- JSON中生成的标题需要尽量精简
|
||||
|
||||
### 示例:
|
||||
如果 SQL 为: SELECT products_sales_data.category, AVG(products_sales_data.price) AS average_price FROM products_sales_data GROUP BY products_sales_data.category;
|
||||
|
||||
+33
-17
@@ -75,20 +75,28 @@
|
||||
"qa": {
|
||||
"new_chat": "New Chat",
|
||||
"start_sqlbot": "Start SQLBot",
|
||||
"title": "Smart Query",
|
||||
"placeholder": "Enter your question",
|
||||
"title": "Smart Data Query",
|
||||
"placeholder": "Please enter your question",
|
||||
"ask": "Ask",
|
||||
"loading": "Loading...",
|
||||
"no_data": "No Data",
|
||||
"no_data": "No data available",
|
||||
"error": "An error occurred, please try again later",
|
||||
"question_placeholder": "Press Enter to submit, or use Ctrl + Enter for new line",
|
||||
"greeting": "Hi, I'm SQLBot, nice to serve you",
|
||||
"hint_description": "I can help query data, generate charts, detect data anomalies, predict data, etc. Please select a data source to start smart querying~",
|
||||
"question_placeholder": "Press Enter to submit, or use Ctrl + Enter for a new line",
|
||||
"greeting": "Hello, I'm SQLBot. How can I assist you today?",
|
||||
"hint_description": "I can query data, generate charts, detect anomalies, predict trends, and more. Please select a data source to begin!",
|
||||
"select_datasource": "Select Data Source",
|
||||
"view_more": "View More",
|
||||
"selected_datasource": "Selected Data Source",
|
||||
"empty_datasource": "No data source available, please create one first!",
|
||||
"datasource_not_exist": "Data source does not exist"
|
||||
"empty_datasource": "No data sources available. Please create one before starting Smart Data Query!",
|
||||
"datasource_not_exist": "Data source does not exist",
|
||||
"guess_u_ask": "You might want to ask:",
|
||||
"continue_to_ask": "Continue asking:",
|
||||
"data_analysis": "Data Analysis",
|
||||
"data_predict": "Data Prediction",
|
||||
"chat_search": "Search",
|
||||
"thinking": "Thinking",
|
||||
"thinking_step": "Thought Process",
|
||||
"ask_again": "Regenerate"
|
||||
},
|
||||
"ds": {
|
||||
"title": "Data Source",
|
||||
@@ -353,19 +361,27 @@
|
||||
"no_fields_yet": "No fields yet"
|
||||
},
|
||||
"chat": {
|
||||
"type": "Chart Type",
|
||||
"chart_type": {
|
||||
"table": "Table",
|
||||
"bar": "Bar",
|
||||
"column": "Column",
|
||||
"line": "Line",
|
||||
"pie": "Pie"
|
||||
"table": "Detail Table",
|
||||
"bar": "Bar Chart",
|
||||
"column": "Column Chart",
|
||||
"line": "Line Chart",
|
||||
"pie": "Pie Chart"
|
||||
},
|
||||
"sql_generation": "SQL Generation",
|
||||
"chart_generation": "Chart Generation",
|
||||
"inference_process": "Inference process",
|
||||
"show_sql": "View SQL",
|
||||
"export_to": "Export As",
|
||||
"excel": "Excel",
|
||||
"picture": "Image",
|
||||
"add_to_dashboard": "Add to Dashboard",
|
||||
"full_screen": "Full Screen",
|
||||
"exit_full_screen": "Exit Full Screen",
|
||||
"sql_generation": "Generate SQL",
|
||||
"chart_generation": "Generate Chart",
|
||||
"inference_process": "Thought Process",
|
||||
"thinking": "Thinking",
|
||||
"data_analysis": "Data Analysis",
|
||||
"data_predict": "Data Predict"
|
||||
"data_predict": "Data Prediction"
|
||||
},
|
||||
"about": {
|
||||
"title": "About",
|
||||
|
||||
@@ -98,8 +98,8 @@
|
||||
"datasource_not_exist": "数据源不存在",
|
||||
"guess_u_ask": "猜你想问:",
|
||||
"continue_to_ask": "继续提问:",
|
||||
"data_analysis": "数据预测",
|
||||
"data_predict": "数据分析",
|
||||
"data_analysis": "数据分析",
|
||||
"data_predict": "数据预测",
|
||||
"chat_search": "搜索",
|
||||
"thinking": "思考中",
|
||||
"thinking_step": "思考过程",
|
||||
|
||||
@@ -1,357 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
import type { ChatMessage } from '@/api/chat.ts'
|
||||
import { computed, ref } from 'vue'
|
||||
import { Loading } from '@element-plus/icons-vue'
|
||||
import MdComponent from './component/MdComponent.vue'
|
||||
import DisplayChartBlock from './component/DisplayChartBlock.vue'
|
||||
import type { ChartTypes } from '@/views/chat/component/BaseChart.ts'
|
||||
import { ArrowDown } from '@element-plus/icons-vue'
|
||||
import ICON_BAR from '@/assets/svg/chart/icon_bar_outlined.svg'
|
||||
import ICON_COLUMN from '@/assets/svg/chart/icon_dashboard_outlined.svg'
|
||||
import ICON_LINE from '@/assets/svg/chart/icon_chart-line.svg'
|
||||
import ICON_PIE from '@/assets/svg/chart/icon_pie_outlined.svg'
|
||||
import ICON_TABLE from '@/assets/svg/chart/icon_form_outlined.svg'
|
||||
import { find } from 'lodash-es'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
const { t } = useI18n()
|
||||
const props = defineProps<{
|
||||
message?: ChatMessage
|
||||
}>()
|
||||
|
||||
const settings = ref<{
|
||||
type: 'chart' | 'sql'
|
||||
showAnswer: boolean
|
||||
}>({
|
||||
type: 'chart',
|
||||
showAnswer: false,
|
||||
})
|
||||
|
||||
const renderSqlThinking = computed(() => {
|
||||
return props.message?.record?.sql_answer ?? ''
|
||||
})
|
||||
|
||||
const renderChartThinking = computed(() => {
|
||||
return props.message?.record?.chart_answer ?? ''
|
||||
})
|
||||
|
||||
const renderSQL = computed(() => {
|
||||
return props.message?.record?.sql
|
||||
? `\`\`\`sql
|
||||
|
||||
${props.message?.record?.sql}
|
||||
`
|
||||
: ''
|
||||
})
|
||||
|
||||
const dataObject = computed<{
|
||||
fields: Array<string>
|
||||
data: Array<{ [key: string]: any }>
|
||||
}>(() => {
|
||||
if (props.message?.record?.data) {
|
||||
if (typeof props.message?.record?.data === 'string') {
|
||||
return JSON.parse(props.message.record.data)
|
||||
} else {
|
||||
return props.message.record.data
|
||||
}
|
||||
}
|
||||
return {}
|
||||
})
|
||||
|
||||
const chartObject = computed<{
|
||||
type: ChartTypes
|
||||
title: 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) {
|
||||
return JSON.parse(props.message.record.chart)
|
||||
}
|
||||
return {}
|
||||
})
|
||||
|
||||
const currentChartType = ref<ChartTypes | undefined>(undefined)
|
||||
|
||||
const chartType = computed<ChartTypes>({
|
||||
get() {
|
||||
if (currentChartType.value) {
|
||||
return currentChartType.value
|
||||
}
|
||||
return chartObject.value.type ?? 'table'
|
||||
},
|
||||
set(v) {
|
||||
currentChartType.value = v
|
||||
},
|
||||
})
|
||||
|
||||
function clickTab(type: 'chart' | 'sql') {
|
||||
settings.value.type = type
|
||||
}
|
||||
|
||||
const chartSelectRef = ref()
|
||||
|
||||
function openChartSelect() {
|
||||
chartSelectRef.value.toggleMenu()
|
||||
}
|
||||
|
||||
const chartTypeList = computed(() => {
|
||||
const _list = [
|
||||
{
|
||||
value: 'table',
|
||||
name: t('chat.chart_type.table'),
|
||||
icon: ICON_TABLE,
|
||||
},
|
||||
]
|
||||
if (chartObject.value) {
|
||||
switch (chartObject.value.type) {
|
||||
case 'table':
|
||||
break
|
||||
case 'column':
|
||||
case 'bar':
|
||||
case 'line':
|
||||
_list.push({
|
||||
value: 'column',
|
||||
name: t('chat.chart_type.column'),
|
||||
icon: ICON_COLUMN,
|
||||
})
|
||||
_list.push({
|
||||
value: 'bar',
|
||||
name: t('chat.chart_type.bar'),
|
||||
icon: ICON_BAR,
|
||||
})
|
||||
_list.push({
|
||||
value: 'line',
|
||||
name: t('chat.chart_type.line'),
|
||||
icon: ICON_LINE,
|
||||
})
|
||||
break
|
||||
case 'pie':
|
||||
_list.push({
|
||||
value: 'pie',
|
||||
name: t('chat.chart_type.pie'),
|
||||
icon: ICON_PIE,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return _list
|
||||
})
|
||||
|
||||
const currentChartTypeIcon = computed(() => {
|
||||
return find(chartTypeList.value, (c) => c.value === chartType.value)?.icon ?? ICON_TABLE
|
||||
})
|
||||
|
||||
const chartRef = ref()
|
||||
|
||||
function onTypeChange() {
|
||||
chartRef.value?.onTypeChange()
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<el-container v-if="message">
|
||||
<el-header style="display: flex; align-items: center; flex-direction: row">
|
||||
<div style="flex: 1">
|
||||
<div v-if="message.isTyping">{{ t('chat.thinking') }} ...</div>
|
||||
<div v-if="chartObject.title && !message.isTyping">{{ chartObject.title }}</div>
|
||||
</div>
|
||||
<div class="tab-container">
|
||||
<div class="base-chart-choose-btn" @click="clickTab('chart')">
|
||||
<div
|
||||
class="chart-choose-btn"
|
||||
:class="{ active: settings.type === 'chart', 'no-click': settings.type !== 'chart' }"
|
||||
@click="openChartSelect"
|
||||
>
|
||||
<el-icon size="34">
|
||||
<component :is="currentChartTypeIcon" />
|
||||
</el-icon>
|
||||
<el-icon>
|
||||
<ArrowDown />
|
||||
</el-icon>
|
||||
</div>
|
||||
<el-select
|
||||
ref="chartSelectRef"
|
||||
v-model="chartType"
|
||||
class="inner-select"
|
||||
:disabled="settings.type !== 'chart'"
|
||||
@change="onTypeChange"
|
||||
>
|
||||
<el-option v-for="t in chartTypeList" :key="t.value" :value="t.value">
|
||||
<div class="inner-chart-option">
|
||||
<el-icon size="34">
|
||||
<component :is="t.icon" />
|
||||
</el-icon>
|
||||
{{ t.name }}
|
||||
</div>
|
||||
</el-option>
|
||||
</el-select>
|
||||
</div>
|
||||
<div
|
||||
class="chart-choose-btn"
|
||||
:class="{ active: settings.type !== 'chart' }"
|
||||
@click="clickTab('sql')"
|
||||
>
|
||||
SQL
|
||||
</div>
|
||||
</div>
|
||||
</el-header>
|
||||
<el-container direction="vertical">
|
||||
<template v-if="message.record">
|
||||
<el-collapse expand-icon-position="left">
|
||||
<el-collapse-item name="1" class="md-collapse">
|
||||
<template #title>
|
||||
{{ t('chat.inference_process') }}
|
||||
<el-icon v-if="props.message?.isTyping">
|
||||
<Loading />
|
||||
</el-icon>
|
||||
</template>
|
||||
<div>
|
||||
<template v-if="message.record.sql_answer">
|
||||
<div style="font-weight: 500">{{ t('chat.sql_generation') }}:</div>
|
||||
<MdComponent
|
||||
v-if="message.record.sql_answer"
|
||||
:message="renderSqlThinking"
|
||||
></MdComponent>
|
||||
</template>
|
||||
<template v-if="message.record.chart_answer">
|
||||
<el-divider></el-divider>
|
||||
<div style="font-weight: 500">{{ t('chat.chart_generation') }}:</div>
|
||||
<MdComponent :message="renderChartThinking"></MdComponent>
|
||||
</template>
|
||||
</div>
|
||||
</el-collapse-item>
|
||||
</el-collapse>
|
||||
<div class="answer-content">
|
||||
<template v-if="settings.type === 'sql'">
|
||||
<div>
|
||||
<MdComponent v-if="message.record.sql" :message="renderSQL"></MdComponent>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else-if="settings.type === 'chart'">
|
||||
<DisplayChartBlock
|
||||
:id="message.record.id"
|
||||
ref="chartRef"
|
||||
:chart-type="chartType"
|
||||
:message="message"
|
||||
:data="dataObject.data"
|
||||
/>
|
||||
<div v-if="message.record.error" style="color: red">
|
||||
{{ message.record.error }}
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
</el-container>
|
||||
<slot :data="{ id: message.record?.id, chartType: chartType, chartObject: chartObject }"></slot>
|
||||
</el-container>
|
||||
</template>
|
||||
|
||||
<style scoped lang="less">
|
||||
:deep(.ed-tabs__nav-scroll) {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.answer-content {
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
.type-tabs {
|
||||
margin-right: 24px;
|
||||
}
|
||||
|
||||
.chart-base-container {
|
||||
padding: 20px;
|
||||
background: rgba(224, 224, 226, 0.29);
|
||||
}
|
||||
|
||||
.tab-container {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.md-collapse {
|
||||
:deep(.ed-collapse-item__content) {
|
||||
padding: 16px 22px;
|
||||
}
|
||||
}
|
||||
|
||||
.base-chart-choose-btn {
|
||||
cursor: pointer;
|
||||
color: var(--ed-color-primary);
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
height: 34px;
|
||||
|
||||
border-radius: 4px;
|
||||
|
||||
position: relative;
|
||||
|
||||
&:hover {
|
||||
background: var(--ed-color-primary-light-5);
|
||||
color: var(--ed-color-primary-light-9);
|
||||
}
|
||||
|
||||
.inner-select {
|
||||
position: absolute;
|
||||
|
||||
:deep(.ed-select__wrapper) {
|
||||
height: 0;
|
||||
padding: unset;
|
||||
min-height: unset;
|
||||
line-height: unset;
|
||||
}
|
||||
|
||||
:deep(.ed-select__suffix) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
:deep(.ed-select__selected-item) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.inner-chart-option {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-direction: row;
|
||||
padding-right: 4px;
|
||||
}
|
||||
|
||||
.chart-choose-btn {
|
||||
cursor: pointer;
|
||||
color: var(--ed-color-primary);
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
height: 34px;
|
||||
|
||||
border-radius: 4px;
|
||||
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 0 4px;
|
||||
|
||||
&.no-click {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
&.active {
|
||||
background: var(--ed-color-primary-light-7);
|
||||
color: var(--ed-color-primary);
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background: var(--ed-color-primary-light-5);
|
||||
color: var(--ed-color-primary-light-9);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -193,7 +193,12 @@ defineExpose({ sendMessage, index: index.value, chatList: _chatList })
|
||||
>
|
||||
<MdComponent :message="message.record?.analysis" style="margin-top: 12px" />
|
||||
<slot></slot>
|
||||
<slot name="footer"></slot>
|
||||
<template #tool>
|
||||
<slot name="tool"></slot>
|
||||
</template>
|
||||
<template #footer>
|
||||
<slot name="footer"></slot>
|
||||
</template>
|
||||
</BaseAnswer>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -62,9 +62,9 @@ function clickShow() {
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
if (props.loading) {
|
||||
show.value = true
|
||||
}
|
||||
// if (props.loading) {
|
||||
// show.value = true
|
||||
// }
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -91,6 +91,9 @@ onMounted(() => {
|
||||
</div>
|
||||
<div class="answer-container">
|
||||
<slot></slot>
|
||||
<el-button v-if="message.isTyping" style="min-width: unset" type="primary" link loading />
|
||||
<slot name="tool"></slot>
|
||||
<slot name="footer"></slot>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -223,7 +223,12 @@ defineExpose({ sendMessage, index: index.value })
|
||||
<template>
|
||||
<BaseAnswer v-if="message" :message="message" :reasoning-name="reasoningName" :loading="_loading">
|
||||
<slot></slot>
|
||||
<slot name="footer"></slot>
|
||||
<template #tool>
|
||||
<slot name="tool"></slot>
|
||||
</template>
|
||||
<template #footer>
|
||||
<slot name="footer"></slot>
|
||||
</template>
|
||||
</BaseAnswer>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -194,7 +194,12 @@ defineExpose({ sendMessage, index: index.value, chatList: _chatList })
|
||||
<BaseAnswer v-if="message" :message="message" :reasoning-name="['predict']" :loading="_loading">
|
||||
<MdComponent :message="message.record?.predict_content" style="margin-top: 12px" />
|
||||
<slot></slot>
|
||||
<slot name="footer"></slot>
|
||||
<template #tool>
|
||||
<slot name="tool"></slot>
|
||||
</template>
|
||||
<template #footer>
|
||||
<slot name="footer"></slot>
|
||||
</template>
|
||||
</BaseAnswer>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ import icon_into_item_outlined from '@/assets/svg/icon_into-item_outlined.svg'
|
||||
import icon_window_max_outlined from '@/assets/svg/icon_window-max_outlined.svg'
|
||||
import icon_window_mini_outlined from '@/assets/svg/icon_window-mini_outlined.svg'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import MdComponent from '@/views/chat/component/MdComponent.vue'
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
@@ -178,9 +179,12 @@ function onExitFullScreen() {
|
||||
dialogVisible.value = false
|
||||
}
|
||||
|
||||
const sqlShow = ref(false)
|
||||
|
||||
function showSql() {
|
||||
console.log('todo')
|
||||
sqlShow.value = true
|
||||
}
|
||||
|
||||
function addToDashboard() {
|
||||
console.log('todo')
|
||||
}
|
||||
@@ -234,7 +238,7 @@ function addToDashboard() {
|
||||
|
||||
<div>
|
||||
<el-tooltip effect="dark" :content="t('chat.show_sql')" placement="top">
|
||||
<el-button class="tool-btn" text @click="showSql">
|
||||
<el-button v-if="message?.record?.sql" class="tool-btn" text @click="showSql">
|
||||
<el-icon size="16">
|
||||
<icon_sql_outlined />
|
||||
</el-icon>
|
||||
@@ -309,6 +313,21 @@ function addToDashboard() {
|
||||
@exit-full-screen="onExitFullScreen"
|
||||
/>
|
||||
</el-dialog>
|
||||
|
||||
<el-drawer
|
||||
v-model="sqlShow"
|
||||
size="600"
|
||||
:title="t('chat.show_sql')"
|
||||
direction="rtl"
|
||||
body-class="chart-sql-drawer-body"
|
||||
>
|
||||
<div>
|
||||
<MdComponent
|
||||
:message="'```sql\n' + message.record?.sql + '\n```'"
|
||||
style="margin-top: 12px"
|
||||
/>
|
||||
</div>
|
||||
</el-drawer>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -322,6 +341,9 @@ function addToDashboard() {
|
||||
.chart-fullscreen-dialog-body {
|
||||
padding: 0;
|
||||
}
|
||||
.chart-sql-drawer-body {
|
||||
padding: 24px;
|
||||
}
|
||||
</style>
|
||||
<style scoped lang="less">
|
||||
.chart-component-container {
|
||||
@@ -358,6 +380,7 @@ function addToDashboard() {
|
||||
|
||||
align-items: center;
|
||||
flex-direction: row;
|
||||
gap: 16px;
|
||||
|
||||
.tool-btn {
|
||||
width: 24px;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, onMounted, onUnmounted } from 'vue'
|
||||
import { computed, nextTick, onMounted, onUnmounted } from 'vue'
|
||||
import { getChartInstance } from '@/views/chat/component/index.ts'
|
||||
import type { BaseChart, ChartAxis, ChartData } from '@/views/chat/component/BaseChart.ts'
|
||||
import { useEmitt } from '@/utils/useEmitt.ts'
|
||||
@@ -78,7 +78,9 @@ defineExpose({
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
renderChart()
|
||||
nextTick(() => {
|
||||
renderChart()
|
||||
})
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import md from '@/utils/markdown.ts'
|
||||
import 'highlight.js/styles/github-dark-dimmed.min.css'
|
||||
import 'highlight.js/styles/github.min.css'
|
||||
import 'github-markdown-css/github-markdown-light.css'
|
||||
import { computed } from 'vue'
|
||||
|
||||
|
||||
@@ -123,59 +123,62 @@
|
||||
>
|
||||
{{ message.record?.error }}
|
||||
</div>
|
||||
<ChatToolBar :message="message">
|
||||
<div class="tool-btns">
|
||||
<el-tooltip effect="dark" :content="t('qa.ask_again')" placement="top">
|
||||
<el-button
|
||||
class="tool-btn"
|
||||
text
|
||||
:disabled="isTyping"
|
||||
@click="askAgain(message)"
|
||||
>
|
||||
<el-icon size="18">
|
||||
<icon_replace_outlined />
|
||||
</el-icon>
|
||||
</el-button>
|
||||
</el-tooltip>
|
||||
<template v-if="message.record?.chart">
|
||||
<div class="divider"></div>
|
||||
<div>
|
||||
|
||||
<template #tool>
|
||||
<ChatToolBar :message="message">
|
||||
<div class="tool-btns">
|
||||
<el-tooltip effect="dark" :content="t('qa.ask_again')" placement="top">
|
||||
<el-button
|
||||
class="tool-btn"
|
||||
text
|
||||
:disabled="isTyping"
|
||||
@click="clickAnalysis(message.record?.id)"
|
||||
@click="askAgain(message)"
|
||||
>
|
||||
<span class="tool-btn-inner">
|
||||
<el-icon size="18">
|
||||
<icon_screen_outlined />
|
||||
</el-icon>
|
||||
<span class="btn-text">
|
||||
{{ t('chat.data_analysis') }}
|
||||
</span>
|
||||
</span>
|
||||
<el-icon size="18">
|
||||
<icon_replace_outlined />
|
||||
</el-icon>
|
||||
</el-button>
|
||||
</div>
|
||||
<div>
|
||||
<el-button
|
||||
class="tool-btn"
|
||||
text
|
||||
:disabled="isTyping"
|
||||
@click="clickPredict(message.record?.id)"
|
||||
>
|
||||
<span class="tool-btn-inner">
|
||||
<el-icon size="18">
|
||||
<icon_start_outlined />
|
||||
</el-icon>
|
||||
<span class="btn-text">
|
||||
{{ t('chat.data_predict') }}
|
||||
</el-tooltip>
|
||||
<template v-if="message.record?.chart">
|
||||
<div class="divider"></div>
|
||||
<div>
|
||||
<el-button
|
||||
class="tool-btn"
|
||||
text
|
||||
:disabled="isTyping"
|
||||
@click="clickAnalysis(message.record?.id)"
|
||||
>
|
||||
<span class="tool-btn-inner">
|
||||
<el-icon size="18">
|
||||
<icon_screen_outlined />
|
||||
</el-icon>
|
||||
<span class="btn-text">
|
||||
{{ t('chat.data_analysis') }}
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</ChatToolBar>
|
||||
</el-button>
|
||||
</div>
|
||||
<div>
|
||||
<el-button
|
||||
class="tool-btn"
|
||||
text
|
||||
:disabled="isTyping"
|
||||
@click="clickPredict(message.record?.id)"
|
||||
>
|
||||
<span class="tool-btn-inner">
|
||||
<el-icon size="18">
|
||||
<icon_start_outlined />
|
||||
</el-icon>
|
||||
<span class="btn-text">
|
||||
{{ t('chat.data_predict') }}
|
||||
</span>
|
||||
</span>
|
||||
</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</ChatToolBar>
|
||||
</template>
|
||||
<template #footer>
|
||||
<RecommendQuestion
|
||||
:questions="message.recommended_question"
|
||||
@@ -204,7 +207,9 @@
|
||||
>
|
||||
{{ message.record?.error }}
|
||||
</div>
|
||||
<ChatToolBar :message="message" />
|
||||
<template #tool>
|
||||
<ChatToolBar :message="message" />
|
||||
</template>
|
||||
</AnalysisAnswer>
|
||||
<PredictAnswer
|
||||
v-if="
|
||||
@@ -227,7 +232,9 @@
|
||||
>
|
||||
{{ message.record?.error }}
|
||||
</div>
|
||||
<ChatToolBar :message="message" />
|
||||
<template #tool>
|
||||
<ChatToolBar :message="message" />
|
||||
</template>
|
||||
</PredictAnswer>
|
||||
</template>
|
||||
</ChatRow>
|
||||
|
||||
Reference in New Issue
Block a user