mirror of
https://gh-proxy.org/https://github.com/klinsmaya/SQLBot.git
synced 2026-11-08 01:06:59 +08:00
perf: Assistant base
This commit is contained in:
@@ -11,7 +11,7 @@ import DashboardPreview from '@//views/dashboard/preview/SQPreviewSingle.vue'
|
||||
import Dashboard from '@/views/dashboard/index.vue'
|
||||
import Model from '@/views/system/model/Model.vue'
|
||||
import Embedded from '@/views/system/embedded/index.vue'
|
||||
import assistant from '@/views/embedded/assistant.vue'
|
||||
import assistant from '@/views/embedded/index.vue'
|
||||
import Member from '@/views/system/member/index.vue'
|
||||
import Permission from '@/views/system/permission/index.vue'
|
||||
import User from '@/views/system/user/User.vue'
|
||||
|
||||
@@ -15,15 +15,16 @@
|
||||
@on-click-side-bar-btn="hideSideBar"
|
||||
/>
|
||||
</el-aside>
|
||||
<div v-if="!isAssistant && !chatListSideBarShow" class="hidden-sidebar-btn">
|
||||
<div
|
||||
v-if="isAssistant || !chatListSideBarShow"
|
||||
class="hidden-sidebar-btn"
|
||||
:class="{ 'assistant-popover-sidebar': isAssistant }"
|
||||
>
|
||||
<el-popover
|
||||
:visible="isAssistant ? floatPopoverVisible : null"
|
||||
:width="280"
|
||||
placement="bottom-start"
|
||||
popper-style="padding: 0;
|
||||
height: 654px;
|
||||
border: 1px solid rgba(222, 224, 227, 1);
|
||||
border-radius: 6px;
|
||||
"
|
||||
:popper-style="{ ...defaultFloatPopoverStyle }"
|
||||
>
|
||||
<template #reference>
|
||||
<el-button link type="primary" class="icon-btn" @click="showSideBar">
|
||||
@@ -264,11 +265,11 @@
|
||||
<template v-if="currentChat.datasource && currentChat.datasource_name">
|
||||
{{ t('qa.selected_datasource') }}:
|
||||
<img
|
||||
v-if="currentChatEngineType"
|
||||
style="margin-left: 4px; margin-right: 4px"
|
||||
:src="currentChatEngineType"
|
||||
width="16px"
|
||||
height="16px"
|
||||
v-if="currentChatEngineType"
|
||||
alt=""
|
||||
/>
|
||||
<span class="name">
|
||||
@@ -339,8 +340,14 @@ import { useAssistantStore } from '@/stores/assistant'
|
||||
const props = defineProps<{
|
||||
startChatDsId?: number
|
||||
}>()
|
||||
|
||||
const floatPopoverVisible = ref(false)
|
||||
const assistantStore = useAssistantStore()
|
||||
const defaultFloatPopoverStyle = ref({
|
||||
padding: '0',
|
||||
height: '654px',
|
||||
border: '1px solid rgba(222, 224, 227, 1)',
|
||||
borderRadius: '6px',
|
||||
})
|
||||
|
||||
const isAssistant = computed(() => assistantStore.getAssistant)
|
||||
|
||||
@@ -444,26 +451,6 @@ const currentChatEngineType = computed(() => {
|
||||
return (dsTypeWithImg.find((ele) => currentChat.value.ds_type === ele.type) || {}).img
|
||||
})
|
||||
|
||||
function toAssistantHistory(chat: Chat) {
|
||||
currentChat.value = new ChatInfo(chat)
|
||||
if (chat !== undefined && chat.id !== undefined && !loading.value) {
|
||||
currentChatId.value = chat.id
|
||||
loading.value = true
|
||||
chatApi
|
||||
.get(chat.id)
|
||||
.then((res) => {
|
||||
const info = chatApi.toChatInfo(res)
|
||||
if (info) {
|
||||
currentChat.value = info
|
||||
onClickHistory(info)
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
function onChatDeleted(id: number) {
|
||||
console.log('deleted', id)
|
||||
}
|
||||
@@ -474,6 +461,10 @@ function onChatRenamed(chat: Chat) {
|
||||
|
||||
const chatListSideBarShow = ref<boolean>(true)
|
||||
function hideSideBar() {
|
||||
if (isAssistant.value) {
|
||||
floatPopoverVisible.value = false
|
||||
return
|
||||
}
|
||||
chatListSideBarShow.value = false
|
||||
}
|
||||
|
||||
@@ -714,13 +705,6 @@ const handleCtrlEnter = (e: KeyboardEvent) => {
|
||||
})
|
||||
}
|
||||
|
||||
const getHistoryList = () => {
|
||||
return chatList.value
|
||||
}
|
||||
const getCurrentChatId = () => {
|
||||
return currentChatId.value
|
||||
}
|
||||
|
||||
const inputRef = ref()
|
||||
|
||||
function clickInput() {
|
||||
@@ -768,12 +752,24 @@ function stop(func?: (...p: any[]) => void, ...param: any[]) {
|
||||
func(...param)
|
||||
}
|
||||
}
|
||||
|
||||
const showFloatPopover = () => {
|
||||
if (isAssistant.value && !floatPopoverVisible.value) {
|
||||
floatPopoverVisible.value = true
|
||||
}
|
||||
}
|
||||
const assistantPrepareInit = () => {
|
||||
if (!isAssistant.value) {
|
||||
return
|
||||
}
|
||||
Object.assign(defaultFloatPopoverStyle.value, {
|
||||
height: '100% !important',
|
||||
inset: '0px auto auto 0px',
|
||||
})
|
||||
goEmpty()
|
||||
}
|
||||
defineExpose({
|
||||
getHistoryList,
|
||||
toAssistantHistory,
|
||||
getCurrentChatId,
|
||||
createNewChat,
|
||||
showFloatPopover,
|
||||
})
|
||||
|
||||
const hiddenChatCreatorRef = ref()
|
||||
@@ -791,6 +787,7 @@ function jumpCreatChat() {
|
||||
|
||||
onMounted(() => {
|
||||
getChatList(jumpCreatChat)
|
||||
assistantPrepareInit()
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -800,7 +797,11 @@ onMounted(() => {
|
||||
position: relative;
|
||||
|
||||
border-radius: 12px;
|
||||
|
||||
.assistant-popover-sidebar {
|
||||
button {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
.hidden-sidebar-btn {
|
||||
z-index: 1;
|
||||
position: absolute;
|
||||
|
||||
@@ -1,69 +1,33 @@
|
||||
<template>
|
||||
<div class="sqlbot-assistant-container">
|
||||
<div class="head">
|
||||
<div class="flex align-center">
|
||||
<div class="head-img-div">
|
||||
<img :src="AssistantGif" />
|
||||
</div>
|
||||
<h4>SQLBot 小助手</h4>
|
||||
</div>
|
||||
<div class="header">
|
||||
<el-icon size="20" @click="openHistory">
|
||||
<icon_sidebar_outlined></icon_sidebar_outlined>
|
||||
</el-icon>
|
||||
<img :src="LOGO" class="logo" width="30px" height="30px" alt="" />
|
||||
<span class="tite">{{ $t('embedded.intelligent_customer_service') }}</span>
|
||||
|
||||
<el-tooltip
|
||||
effect="dark"
|
||||
:content="$t('embedded.new_conversation')"
|
||||
placement="top"
|
||||
@click="createChat"
|
||||
>
|
||||
<el-icon class="new-chat" size="20">
|
||||
<icon_new_chat_outlined></icon_new_chat_outlined>
|
||||
</el-icon>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
<chat-component v-if="!loading" ref="chatRef" class="sqlbot-chat-container" />
|
||||
</div>
|
||||
<div class="sqlbot-top-btn">
|
||||
<el-icon style="cursor: pointer" @click="createChat">
|
||||
<icon_new_chat_outlined />
|
||||
</el-icon>
|
||||
<el-icon style="cursor: pointer" @click="openHistory">
|
||||
<history></history>
|
||||
</el-icon>
|
||||
</div>
|
||||
<div class="sqlbot-history-container">
|
||||
<el-drawer
|
||||
v-model="drawer"
|
||||
:append-to-body="false"
|
||||
class="sqlbot-history-drawer"
|
||||
modal-class="sqlbot-history-modal"
|
||||
title=""
|
||||
direction="ttb"
|
||||
:with-header="false"
|
||||
>
|
||||
<div class="sqlbot-history-title">
|
||||
<span>历史记录</span>
|
||||
</div>
|
||||
<div class="sqlbot-history-content">
|
||||
<div v-if="!chatList.length" class="history-empty">
|
||||
<span>暂无历史记录</span>
|
||||
</div>
|
||||
<div v-else class="sqlbot-chat-list-inner">
|
||||
<el-scrollbar max-height="350px" class="sqlbot-chat-scroller">
|
||||
<template v-for="chat in chatList" :key="chat.id">
|
||||
<div
|
||||
class="chat-list-item"
|
||||
:class="{ 'is-active-chat': currentId === chat.id }"
|
||||
@click="onClickHistory(chat)"
|
||||
>
|
||||
<span class="title">{{ chat.brief ?? 'Untitled' }}</span>
|
||||
<!-- <div class="history-operate">
|
||||
<el-icon @click="EditPen(chat)"><IconOpeEdit /></el-icon>
|
||||
<el-icon @click="Delete(chat)"><IconOpeDelete /></el-icon>
|
||||
</div> -->
|
||||
</div>
|
||||
</template>
|
||||
</el-scrollbar>
|
||||
</div>
|
||||
</div>
|
||||
</el-drawer>
|
||||
<div class="drawer-assistant" @click="openHistory"></div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { onBeforeMount, onBeforeUnmount, ref } from 'vue'
|
||||
import ChatComponent from '@/views/chat/index.vue'
|
||||
import AssistantGif from '@/assets/img/assistant.gif'
|
||||
import history from '@/assets/svg/chart/history.svg'
|
||||
import LOGO from '@/assets/embedded/LOGO.png'
|
||||
import icon_sidebar_outlined from '@/assets/embedded/icon_sidebar_outlined.svg'
|
||||
import icon_new_chat_outlined from '@/assets/svg/icon_new_chat_outlined.svg'
|
||||
/* import IconOpeEdit from '@/assets/svg/operate/ope-edit.svg'
|
||||
import IconOpeDelete from '@/assets/svg/operate/ope-delete.svg' */
|
||||
import { useRoute } from 'vue-router'
|
||||
import { assistantApi } from '@/api/assistant'
|
||||
import { useAssistantStore } from '@/stores/assistant'
|
||||
@@ -72,28 +36,14 @@ const assistantStore = useAssistantStore()
|
||||
const route = useRoute()
|
||||
|
||||
const chatRef = ref()
|
||||
const chatList = ref<Array<any>>([])
|
||||
const drawer = ref(false)
|
||||
const currentId = ref()
|
||||
|
||||
const createChat = () => {
|
||||
chatRef.value?.createNewChat()
|
||||
}
|
||||
const openHistory = () => {
|
||||
chatList.value = chatRef.value?.getHistoryList()
|
||||
currentId.value = chatRef.value?.getCurrentChatId()
|
||||
drawer.value = true
|
||||
}
|
||||
const onClickHistory = (chat: any) => {
|
||||
chatRef.value?.toAssistantHistory(chat)
|
||||
chatRef.value?.showFloatPopover()
|
||||
}
|
||||
|
||||
/* const EditPen = (chat: any) => {
|
||||
chatRef.value?.onChatRenamed(chat)
|
||||
}
|
||||
const Delete = (chat: any) => {
|
||||
chatRef.value?.onChatDeleted(chat.id)
|
||||
} */
|
||||
const validator = ref({
|
||||
id: '',
|
||||
valid: false,
|
||||
@@ -151,31 +101,58 @@ onBeforeUnmount(() => {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
color: rgb(31, 35, 41);
|
||||
.flex {
|
||||
display: flex;
|
||||
}
|
||||
.head {
|
||||
background: linear-gradient(90deg, #ebf1ff 24.34%, #e5fbf8 56.18%, #f2ebfe 90.18%);
|
||||
position: fixed;
|
||||
.header {
|
||||
width: 100%;
|
||||
left: 0;
|
||||
top: 0;
|
||||
z-index: 100;
|
||||
height: 56px;
|
||||
line-height: 56px;
|
||||
box-sizing: border-box;
|
||||
border-bottom: 1px solid #dee0e3;
|
||||
.align-center {
|
||||
align-items: center;
|
||||
.head-img-div {
|
||||
display: flex;
|
||||
margin-left: 24px;
|
||||
img {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
background: #1cba9014;
|
||||
height: 56px;
|
||||
padding: 0 16px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
position: fixed;
|
||||
.logo {
|
||||
margin: 0 8px 0 16px;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-weight: 500;
|
||||
font-size: 16px;
|
||||
line-height: 24px;
|
||||
}
|
||||
|
||||
.ed-icon {
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
|
||||
&::after {
|
||||
content: '';
|
||||
background-color: #1f23291a;
|
||||
position: absolute;
|
||||
border-radius: 6px;
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
transform: translate(-50%, -50%);
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
display: none;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
&::after {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.new-chat {
|
||||
position: absolute;
|
||||
right: 88px;
|
||||
top: 17px;
|
||||
}
|
||||
}
|
||||
.sqlbot-chat-container {
|
||||
padding-top: 56px;
|
||||
@@ -183,82 +160,17 @@ onBeforeUnmount(() => {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
.sqlbot-top-btn {
|
||||
right: 85px;
|
||||
z-index: 2009;
|
||||
position: fixed;
|
||||
top: 16px;
|
||||
display: flex;
|
||||
column-gap: 16px;
|
||||
// right: 16px;
|
||||
font-size: 22px;
|
||||
i:first-child {
|
||||
color: var(--primary-color);
|
||||
}
|
||||
}
|
||||
.sqlbot-history-container {
|
||||
width: 100%;
|
||||
:deep(.sqlbot-history-modal) {
|
||||
top: 56px !important;
|
||||
}
|
||||
:deep(.sqlbot-history-title) {
|
||||
border-bottom: 1px solid #dee0e3;
|
||||
padding: 16px 24px;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
color: #1f2329;
|
||||
}
|
||||
:deep(.ed-drawer__body) {
|
||||
padding: 0 !important;
|
||||
}
|
||||
:deep(.sqlbot-history-drawer) {
|
||||
height: fit-content !important;
|
||||
.sqlbot-history-content {
|
||||
padding: 16px;
|
||||
.history-empty {
|
||||
height: 60px;
|
||||
color: #8f959e !important;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 14px;
|
||||
}
|
||||
.is-active-chat {
|
||||
background-color: #ebf1ff;
|
||||
color: #3370ff;
|
||||
font-weight: 500;
|
||||
}
|
||||
.chat-list-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 10px 8px;
|
||||
font-size: 14px;
|
||||
color: #1f2329;
|
||||
justify-content: space-between;
|
||||
.history-operate {
|
||||
display: none;
|
||||
}
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
border-radius: 4px;
|
||||
background: rgba(31, 35, 41, 0.1);
|
||||
.history-operate {
|
||||
padding-right: 16px;
|
||||
display: flex;
|
||||
column-gap: 16px;
|
||||
align-items: center;
|
||||
font-size: 18px;
|
||||
i {
|
||||
color: #8f959e;
|
||||
&:hover {
|
||||
color: #8f959e99;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.drawer-assistant {
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 50%;
|
||||
background: #f5f6f7;
|
||||
box-shadow: 0px 6px 24px 0px #1f232914;
|
||||
padding: 16px;
|
||||
border-right: 1px solid #dee0e3;
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -426,9 +426,9 @@ const saveHandler = () => {
|
||||
<el-button :class="[btnSelect === 'd' && 'is-active']" text @click="btnSelect = 'd'">
|
||||
{{ t('embedded.embedded_assistant') }}
|
||||
</el-button>
|
||||
<el-button :class="[btnSelect === 'q' && 'is-active']" text @click="btnSelect = 'q'">
|
||||
<!-- <el-button :class="[btnSelect === 'q' && 'is-active']" text @click="btnSelect = 'q'">
|
||||
{{ t('embedded.embedded_page') }}
|
||||
</el-button>
|
||||
</el-button> -->
|
||||
</div>
|
||||
<div>
|
||||
<el-input
|
||||
|
||||
Reference in New Issue
Block a user