mirror of
https://gh-proxy.org/https://github.com/klinsmaya/SQLBot.git
synced 2026-11-08 09:17:06 +08:00
Merge remote-tracking branch 'origin/main'
This commit is contained in:
@@ -1,18 +1,37 @@
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import { computed, nextTick, ref } from 'vue'
|
||||
import { endsWith, startsWith } from 'lodash-es'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { chatApi, ChatInfo } from '@/api/chat.ts'
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
recordId?: number
|
||||
currentChat?: ChatInfo
|
||||
questions?: string
|
||||
firstChat?: boolean
|
||||
}>(),
|
||||
{
|
||||
recordId: undefined,
|
||||
currentChat: () => new ChatInfo(),
|
||||
questions: '[]',
|
||||
firstChat: false,
|
||||
}
|
||||
)
|
||||
|
||||
const emits = defineEmits(['clickQuestion', 'update:currentChat'])
|
||||
|
||||
const loading = ref(false)
|
||||
|
||||
const _currentChat = computed({
|
||||
get() {
|
||||
return props.currentChat
|
||||
},
|
||||
set(v) {
|
||||
emits('update:currentChat', v)
|
||||
},
|
||||
})
|
||||
|
||||
const computedQuestions = computed<string>(() => {
|
||||
if (
|
||||
props.questions &&
|
||||
@@ -25,20 +44,98 @@ const computedQuestions = computed<string>(() => {
|
||||
return []
|
||||
})
|
||||
|
||||
const emits = defineEmits(['clickQuestion'])
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
function clickQuestion(question: string): void {
|
||||
emits('clickQuestion', question)
|
||||
}
|
||||
|
||||
async function getRecommendQuestions() {
|
||||
loading.value = true
|
||||
try {
|
||||
const response = await chatApi.recommendQuestions(props.recordId)
|
||||
const reader = response.body.getReader()
|
||||
const decoder = new TextDecoder()
|
||||
|
||||
while (true) {
|
||||
const { done, value } = await reader.read()
|
||||
if (done) {
|
||||
break
|
||||
}
|
||||
|
||||
const chunk = decoder.decode(value)
|
||||
|
||||
let _list = [chunk]
|
||||
|
||||
const lines = chunk.trim().split('}\n\n{')
|
||||
if (lines.length > 1) {
|
||||
_list = []
|
||||
for (let line of lines) {
|
||||
if (!line.trim().startsWith('{')) {
|
||||
line = '{' + line.trim()
|
||||
}
|
||||
if (!line.trim().endsWith('}')) {
|
||||
line = line.trim() + '}'
|
||||
}
|
||||
_list.push(line)
|
||||
}
|
||||
}
|
||||
|
||||
for (const str of _list) {
|
||||
let data
|
||||
try {
|
||||
data = JSON.parse(str)
|
||||
} catch (err) {
|
||||
console.error('JSON string:', str)
|
||||
throw err
|
||||
}
|
||||
|
||||
if (data.code && data.code !== 200) {
|
||||
ElMessage({
|
||||
message: data.msg,
|
||||
type: 'error',
|
||||
showClose: true,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
switch (data.type) {
|
||||
case 'recommended_question':
|
||||
if (
|
||||
data.content &&
|
||||
data.content.length > 0 &&
|
||||
startsWith(data.content.trim(), '[') &&
|
||||
endsWith(data.content.trim(), ']')
|
||||
) {
|
||||
if (_currentChat.value?.records) {
|
||||
for (let record of _currentChat.value.records) {
|
||||
if (record.id === props.recordId) {
|
||||
record.recommended_question = data.content
|
||||
|
||||
await nextTick()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
defineExpose({ getRecommendQuestions, id: () => props.recordId })
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div v-if="computedQuestions.length > 0" class="recommend-questions">
|
||||
<div v-if="computedQuestions.length > 0 || loading" class="recommend-questions">
|
||||
<div v-if="firstChat">{{ t('qa.guess_u_ask') }}</div>
|
||||
<div v-else class="continue-ask">{{ t('qa.continue_to_ask') }}</div>
|
||||
<div class="question-grid">
|
||||
<div v-if="loading">
|
||||
<el-button style="min-width: unset" type="primary" link loading />
|
||||
</div>
|
||||
<div v-else class="question-grid">
|
||||
<div
|
||||
v-for="(question, index) in computedQuestions"
|
||||
:key="index"
|
||||
|
||||
@@ -5,9 +5,9 @@ import { computed, nextTick } from 'vue'
|
||||
import MdComponent from '@/views/chat/component/MdComponent.vue'
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
chatList: Array<ChatInfo>
|
||||
chatList?: Array<ChatInfo>
|
||||
currentChatId?: number
|
||||
currentChat: ChatInfo
|
||||
currentChat?: ChatInfo
|
||||
message?: ChatMessage
|
||||
loading?: boolean
|
||||
}>(),
|
||||
|
||||
@@ -4,9 +4,9 @@ import { Chat, chatApi, ChatInfo, type ChatMessage, ChatRecord, questionApi } fr
|
||||
import { computed, nextTick } from 'vue'
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
chatList: Array<ChatInfo>
|
||||
chatList?: Array<ChatInfo>
|
||||
currentChatId?: number
|
||||
currentChat: ChatInfo
|
||||
currentChat?: ChatInfo
|
||||
message?: ChatMessage
|
||||
loading?: boolean
|
||||
reasoningName: 'sql_answer' | 'chart_answer' | Array<'sql_answer' | 'chart_answer'>
|
||||
|
||||
@@ -5,9 +5,9 @@ import { computed, nextTick } from 'vue'
|
||||
import MdComponent from '@/views/chat/component/MdComponent.vue'
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
chatList: Array<ChatInfo>
|
||||
chatList?: Array<ChatInfo>
|
||||
currentChatId?: number
|
||||
currentChat: ChatInfo
|
||||
currentChat?: ChatInfo
|
||||
message?: ChatMessage
|
||||
loading?: boolean
|
||||
}>(),
|
||||
|
||||
@@ -193,8 +193,9 @@ function addToDashboard() {
|
||||
<template>
|
||||
<div
|
||||
v-if="
|
||||
(!isPredict && (message?.record?.sql || message?.record?.chart)) ||
|
||||
(isPredict && message?.record?.chart && data.length > 0)
|
||||
!message.isTyping &&
|
||||
((!isPredict && (message?.record?.sql || message?.record?.chart)) ||
|
||||
(isPredict && message?.record?.chart && data.length > 0))
|
||||
"
|
||||
class="chart-component-container"
|
||||
:class="{ 'full-screen': enlarge }"
|
||||
|
||||
@@ -93,6 +93,9 @@
|
||||
<ChatRow :current-chat="currentChat" :msg="message" :hide-avatar="message.first_chat">
|
||||
<RecommendQuestion
|
||||
v-if="message.role === 'assistant' && message.first_chat"
|
||||
ref="recommendQuestionRef"
|
||||
:current-chat="currentChat"
|
||||
:record-id="message.record?.id"
|
||||
:questions="message.recommended_question"
|
||||
:first-chat="message.first_chat"
|
||||
@click-question="quickAsk"
|
||||
@@ -181,6 +184,9 @@
|
||||
</template>
|
||||
<template #footer>
|
||||
<RecommendQuestion
|
||||
ref="recommendQuestionRef"
|
||||
:current-chat="currentChat"
|
||||
:record-id="message.record?.id"
|
||||
:questions="message.recommended_question"
|
||||
:first-chat="message.first_chat"
|
||||
@click-question="quickAsk"
|
||||
@@ -303,7 +309,7 @@ import ChatListContainer from './ChatListContainer.vue'
|
||||
import ChatCreator from '@/views/chat/ChatCreator.vue'
|
||||
import ChatToolBar from './ChatToolBar.vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { endsWith, find, startsWith } from 'lodash-es'
|
||||
import { find } from 'lodash-es'
|
||||
import icon_new_chat_outlined from '@/assets/svg/icon_new_chat_outlined.svg'
|
||||
import icon_sidebar_outlined from '@/assets/svg/icon_sidebar_outlined.svg'
|
||||
import icon_replace_outlined from '@/assets/svg/icon_replace_outlined.svg'
|
||||
@@ -373,6 +379,7 @@ const computedMessages = computed<Array<ChatMessage>>(() => {
|
||||
})
|
||||
}
|
||||
|
||||
console.log(messages)
|
||||
return messages
|
||||
})
|
||||
|
||||
@@ -465,72 +472,24 @@ function onChatCreated(chat: ChatInfo) {
|
||||
}
|
||||
}
|
||||
|
||||
async function getRecommendQuestions(record_id?: number) {
|
||||
const response = await chatApi.recommendQuestions(record_id)
|
||||
const reader = response.body.getReader()
|
||||
const decoder = new TextDecoder()
|
||||
const recommendQuestionRef = ref()
|
||||
|
||||
while (true) {
|
||||
const { done, value } = await reader.read()
|
||||
if (done) {
|
||||
break
|
||||
}
|
||||
|
||||
const chunk = decoder.decode(value)
|
||||
|
||||
let _list = [chunk]
|
||||
|
||||
const lines = chunk.trim().split('}\n\n{')
|
||||
if (lines.length > 1) {
|
||||
_list = []
|
||||
for (let line of lines) {
|
||||
if (!line.trim().startsWith('{')) {
|
||||
line = '{' + line.trim()
|
||||
}
|
||||
if (!line.trim().endsWith('}')) {
|
||||
line = line.trim() + '}'
|
||||
}
|
||||
_list.push(line)
|
||||
}
|
||||
}
|
||||
|
||||
for (const str of _list) {
|
||||
let data
|
||||
try {
|
||||
data = JSON.parse(str)
|
||||
} catch (err) {
|
||||
console.error('JSON string:', str)
|
||||
throw err
|
||||
}
|
||||
|
||||
if (data.code && data.code !== 200) {
|
||||
ElMessage({
|
||||
message: data.msg,
|
||||
type: 'error',
|
||||
showClose: true,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
switch (data.type) {
|
||||
case 'recommended_question':
|
||||
if (
|
||||
data.content &&
|
||||
data.content.length > 0 &&
|
||||
startsWith(data.content.trim(), '[') &&
|
||||
endsWith(data.content.trim(), ']')
|
||||
) {
|
||||
if (currentChat.value?.records) {
|
||||
for (let record of currentChat.value.records) {
|
||||
if (record.id === record_id) {
|
||||
record.recommended_question = data.content
|
||||
}
|
||||
}
|
||||
}
|
||||
function getRecommendQuestions(id?: number) {
|
||||
nextTick(() => {
|
||||
if (recommendQuestionRef.value) {
|
||||
if (recommendQuestionRef.value instanceof Array) {
|
||||
for (let i = 0; i < recommendQuestionRef.value.length; i++) {
|
||||
const _id = recommendQuestionRef.value[i].id()
|
||||
if (_id === id) {
|
||||
recommendQuestionRef.value[i].getRecommendQuestions()
|
||||
break
|
||||
}
|
||||
}
|
||||
} else {
|
||||
recommendQuestionRef.value.getRecommendQuestions()
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
@@ -549,7 +508,7 @@ const chartAnswerRef = ref()
|
||||
async function onChartAnswerFinish(id: number) {
|
||||
loading.value = false
|
||||
isTyping.value = false
|
||||
await getRecommendQuestions(id)
|
||||
getRecommendQuestions(id)
|
||||
}
|
||||
|
||||
function onChartAnswerError() {
|
||||
|
||||
Reference in New Issue
Block a user