|
|
|
<template>
|
|
|
|
<div class="chat-embed layout-bg">
|
|
|
|
<div class="chat-embed__header">
|
|
|
|
<div class="chat-width flex align-center" style="height: 56px;align-items: center;line-height: 56px">
|
|
|
|
<div class="mr-12 ml-24 flex">
|
|
|
|
<el-avatar
|
|
|
|
shape="square"
|
|
|
|
:size="32"
|
|
|
|
style="background: none"
|
|
|
|
>
|
|
|
|
<img src="@/assets/logo/deepseek.png" alt="" />
|
|
|
|
</el-avatar>
|
|
|
|
</div>
|
|
|
|
<h4 style="color: #1f2329;font-size: 16px; font-style: normal; font-weight: bold;margin: 0; -webkit-font-smoothing: antialiased">果知小助手</h4>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div class="chat-embed__main">
|
|
|
|
<AiChat
|
|
|
|
ref="AiChatRef"
|
|
|
|
:record="currentRecordList"
|
|
|
|
:is_large="is_large"
|
|
|
|
:cookieSessionId = "sessionId"
|
|
|
|
class="AiChat-embed"
|
|
|
|
@scroll="handleScroll"
|
|
|
|
></AiChat>
|
|
|
|
</div>
|
|
|
|
<el-link class="chat-popover-button" :underline="false" @click.prevent.stop="showChatHistory">
|
|
|
|
<i class="ri-history-line"></i>
|
|
|
|
</el-link>
|
|
|
|
<el-link style="z-index: 100; position: absolute; top: 18px; right: 120px; font-size: 20px;" :underline="false" @click.prevent.stop="newChat" :disabled="currentRecordList.length === 0">
|
|
|
|
<el-icon><Plus /></el-icon>
|
|
|
|
</el-link>
|
|
|
|
<el-collapse-transition>
|
|
|
|
<div v-show="show" class="chat-popover w-full" style="width: 100%;" v-click-outside="clickoutside">
|
|
|
|
<div class="border-b p-16-24" style="border-bottom: 1px solid #dee0e3; padding: 16px 24px; font-size: 14px">
|
|
|
|
<span>历史记录</span>
|
|
|
|
</div>
|
|
|
|
<el-scrollbar max-height="300">
|
|
|
|
<div class="p-8" style="padding: 8px">
|
|
|
|
<common-list
|
|
|
|
:data="chatLogeData"
|
|
|
|
:mouseId="mouseId"
|
|
|
|
:defaultActive="sessionId"
|
|
|
|
@click="clickListHandle"
|
|
|
|
@mouseenter="mouseenter"
|
|
|
|
@mouseleave="mouseId = ''"
|
|
|
|
>
|
|
|
|
<template #default="{ row }">
|
|
|
|
<div class="flex-between" style="display: flex; justify-content: space-between; align-items: center;">
|
|
|
|
<auto-tooltip :content="row.sessionName">
|
|
|
|
{{ row.sessionName }}
|
|
|
|
</auto-tooltip>
|
|
|
|
<div @click.stop v-if="mouseId === row.sessionId">
|
|
|
|
<el-button style="padding: 0" link @click.stop="deleteLog(row)">
|
|
|
|
<el-icon><Delete /></el-icon>
|
|
|
|
</el-button>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</template>
|
|
|
|
<template #empty>
|
|
|
|
<div class="text-center">
|
|
|
|
<el-text type="info">暂无历史记录</el-text>
|
|
|
|
</div>
|
|
|
|
</template>
|
|
|
|
</common-list>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div v-if="chatLogeData.length" class="gradient-divider lighter mt-8" style="font-weight: 400; margin-top: 8px">
|
|
|
|
<span>仅显示最近 20 条对话</span>
|
|
|
|
</div>
|
|
|
|
</el-scrollbar>
|
|
|
|
</div>
|
|
|
|
</el-collapse-transition>
|
|
|
|
<div class="chat-popover-mask" v-show="show"></div>
|
|
|
|
</div>
|
|
|
|
</template>
|
|
|
|
|
|
|
|
<script setup>
|
|
|
|
import { ref, onMounted, reactive, nextTick, computed } from 'vue'
|
|
|
|
import { v4 as uuidv4 } from 'uuid';
|
|
|
|
import Cookies from 'js-cookie'
|
|
|
|
import CommonList from './common-list.vue'
|
|
|
|
import AiChat from './aichat.vue'
|
|
|
|
import AutoTooltip from './auto-tooltip.vue'
|
|
|
|
import { useRoute } from 'vue-router'
|
|
|
|
import { listChatHistory, getChatList, DeleteChatSession } from "@/api/aichat/aichat";
|
|
|
|
const route = useRoute()
|
|
|
|
const { proxy } = getCurrentInstance();
|
|
|
|
const {
|
|
|
|
params: { accessToken }
|
|
|
|
} = route
|
|
|
|
const props = defineProps({
|
|
|
|
is_large: Boolean,
|
|
|
|
chatDataList: Array,
|
|
|
|
})
|
|
|
|
const AiChatRef = ref()
|
|
|
|
const chatLogeData = ref([])
|
|
|
|
const show = ref(false)
|
|
|
|
const currentRecordList = ref([])
|
|
|
|
const sessionId = ref(Cookies.get("chatSessionId")) // 当前历史记录Id 默认为'new'
|
|
|
|
const mouseId = ref('')
|
|
|
|
|
|
|
|
function mouseenter(row) {
|
|
|
|
mouseId.value = row.sessionId
|
|
|
|
}
|
|
|
|
function deleteLog(row) {
|
|
|
|
let sessionId = row.sessionId
|
|
|
|
DeleteChatSession(sessionId).then(res=>{
|
|
|
|
listChatHistory(sessionId).then(response =>{
|
|
|
|
chatLogeData.value = response.data
|
|
|
|
})
|
|
|
|
proxy.$modal.msgSuccess("删除成功");
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
function clickoutside() {
|
|
|
|
show.value = false
|
|
|
|
}
|
|
|
|
|
|
|
|
function showChatHistory(){
|
|
|
|
show.value = true
|
|
|
|
listChatHistory(sessionId.value).then(response =>{
|
|
|
|
chatLogeData.value = response.data
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function newChat() {
|
|
|
|
currentRecordList.value = []
|
|
|
|
sessionId.value = uuidv4()
|
|
|
|
Cookies.set("chatSessionId",sessionId.value)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
function handleScroll(event) {
|
|
|
|
if (event.scrollTop === 0 && currentRecordList.value.length>0) {
|
|
|
|
const history_height = event.dialogScrollbar.offsetHeight
|
|
|
|
event.scrollDiv.setScrollTop(event.dialogScrollbar.offsetHeight - history_height)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function clickListHandle(item){
|
|
|
|
getChatList(item.sessionId).then(res=>{
|
|
|
|
currentRecordList.value = []
|
|
|
|
let array = res.data
|
|
|
|
for (let i = 0; i < array.length; i++) {
|
|
|
|
if (array[i].type === 'answer'){
|
|
|
|
array[i].content = JSON.parse(array[i].content)
|
|
|
|
}
|
|
|
|
if (array[i].type === 'question'){
|
|
|
|
array[i].file = JSON.parse(array[i].file)
|
|
|
|
}
|
|
|
|
currentRecordList.value.push(array[i])
|
|
|
|
AiChatRef.value.setScrollBottom()
|
|
|
|
}
|
|
|
|
show.value = false
|
|
|
|
sessionId.value = item.sessionId
|
|
|
|
Cookies.set("chatSessionId",sessionId.value)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
watch(() => props.chatDataList, value => currentRecordList.value = JSON.parse(JSON.stringify(value)))
|
|
|
|
onMounted(
|
|
|
|
()=>{
|
|
|
|
if (Cookies.get("chatSessionId")){
|
|
|
|
//调用子页面的赋值方法,给子页面赋值
|
|
|
|
getChatList(Cookies.get("chatSessionId")).then(res=>{
|
|
|
|
let array = res.data
|
|
|
|
if (array && array.length >0){
|
|
|
|
for (let i = 0; i < array.length; i++) {
|
|
|
|
if (array[i].type === 'answer'){
|
|
|
|
array[i].content = JSON.parse(array[i].content)
|
|
|
|
}
|
|
|
|
if (array[i].type === 'question'){
|
|
|
|
array[i].file = JSON.parse(array[i].file)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
currentRecordList.value = array
|
|
|
|
}).then(()=>{
|
|
|
|
AiChatRef.value.setScrollBottom()
|
|
|
|
})
|
|
|
|
}else {
|
|
|
|
Cookies.set("chatSessionId",uuidv4())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
)
|
|
|
|
</script>
|
|
|
|
|
|
|
|
<style lang="scss">
|
|
|
|
.chat-embed {
|
|
|
|
overflow: hidden;
|
|
|
|
height: 100%;
|
|
|
|
&__header {
|
|
|
|
background: linear-gradient(90deg, #ebf1ff 24.34%, #e5fbf8 56.18%, #f2ebfe 90.18%);;
|
|
|
|
position: absolute;
|
|
|
|
width: 100%;
|
|
|
|
left: 0;
|
|
|
|
top: 0;
|
|
|
|
z-index: 100;
|
|
|
|
height: 56px;
|
|
|
|
line-height: 56px;
|
|
|
|
box-sizing: border-box;
|
|
|
|
border-bottom: 1px solid #dee0e3;
|
|
|
|
}
|
|
|
|
&__main {
|
|
|
|
padding-top: 80px;
|
|
|
|
height: 100%;
|
|
|
|
overflow: hidden;
|
|
|
|
}
|
|
|
|
.new-chat-button {
|
|
|
|
z-index: 11;
|
|
|
|
}
|
|
|
|
// 历史对话弹出层
|
|
|
|
.chat-popover {
|
|
|
|
position: absolute;
|
|
|
|
top: 56px;
|
|
|
|
background: #ffffff;
|
|
|
|
padding-bottom: 24px;
|
|
|
|
z-index: 2009;
|
|
|
|
}
|
|
|
|
.chat-popover-button {
|
|
|
|
z-index: 100;
|
|
|
|
position: absolute;
|
|
|
|
top: 18px;
|
|
|
|
right: 85px;
|
|
|
|
font-size: 20px;
|
|
|
|
}
|
|
|
|
.chat-popover-mask {
|
|
|
|
background-color: var(--el-overlay-color-lighter);
|
|
|
|
bottom: 0;
|
|
|
|
height: 100%;
|
|
|
|
left: 0;
|
|
|
|
overflow: auto;
|
|
|
|
position: absolute;
|
|
|
|
right: 0;
|
|
|
|
top: 56px;
|
|
|
|
z-index: 2008;
|
|
|
|
}
|
|
|
|
.gradient-divider {
|
|
|
|
position: relative;
|
|
|
|
text-align: center;
|
|
|
|
color: var(--el-color-info);
|
|
|
|
::before {
|
|
|
|
content: '';
|
|
|
|
width: 17%;
|
|
|
|
height: 1px;
|
|
|
|
background: linear-gradient(90deg, rgba(222, 224, 227, 0) 0%, #dee0e3 100%);
|
|
|
|
position: absolute;
|
|
|
|
left: 16px;
|
|
|
|
top: 50%;
|
|
|
|
}
|
|
|
|
::after {
|
|
|
|
content: '';
|
|
|
|
width: 17%;
|
|
|
|
height: 1px;
|
|
|
|
background: linear-gradient(90deg, #dee0e3 0%, rgba(222, 224, 227, 0) 100%);
|
|
|
|
position: absolute;
|
|
|
|
right: 16px;
|
|
|
|
top: 50%;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
.AiChat-embed {
|
|
|
|
.ai-chat__operate {
|
|
|
|
padding-top: 12px;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
.chat-width {
|
|
|
|
max-width: 860px;
|
|
|
|
margin: 0 auto;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
.flex {
|
|
|
|
display: flex;
|
|
|
|
}
|
|
|
|
|
|
|
|
.mr-12 {
|
|
|
|
margin-right: 12px;
|
|
|
|
|
|
|
|
}
|
|
|
|
.ml-24 {
|
|
|
|
margin-left: 24px;
|
|
|
|
}
|
|
|
|
</style>
|