修改了历史问答的样式,修改了通用问答的样式
This commit is contained in:
parent
2d4eeab6a2
commit
9fc56b7393
|
|
@ -18,9 +18,19 @@
|
||||||
</el-icon>
|
</el-icon>
|
||||||
</el-badge>
|
</el-badge>
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<!-- 导出PDF按钮 -->
|
||||||
|
<div class="export-pdf-button " @click="exportChatToPdf">
|
||||||
|
<el-tooltip content="导出为PDF" placement="left">
|
||||||
|
<el-icon :size="20">
|
||||||
|
<Document/>
|
||||||
|
</el-icon>
|
||||||
|
</el-tooltip>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ChatBox
|
<ChatBox
|
||||||
|
ref="chatBoxRef"
|
||||||
v-if="isDataLoaded"
|
v-if="isDataLoaded"
|
||||||
:chat-type="chatType"
|
:chat-type="chatType"
|
||||||
:user-id="userId"
|
:user-id="userId"
|
||||||
|
|
@ -61,7 +71,7 @@
|
||||||
<div v-else class="no-binding-hint">
|
<div v-else class="no-binding-hint">
|
||||||
<el-empty description="暂未绑定知识库" :image-size="80" />
|
<el-empty description="暂未绑定知识库" :image-size="80" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="add-knowledge">
|
<div class="add-knowledge">
|
||||||
<div class="section-title">添加知识库</div>
|
<div class="section-title">添加知识库</div>
|
||||||
<el-select
|
<el-select
|
||||||
|
|
@ -90,7 +100,7 @@
|
||||||
</el-select>
|
</el-select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<div class="dialog-footer">
|
<div class="dialog-footer">
|
||||||
<el-button @click="closeKnowledgeDialog">取消</el-button>
|
<el-button @click="closeKnowledgeDialog">取消</el-button>
|
||||||
|
|
@ -110,16 +120,33 @@ import { useAclStore } from '@/store/modules/acl'
|
||||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||||
import { useI18n } from 'vue-i18n'
|
import { useI18n } from 'vue-i18n'
|
||||||
import { getRecommendations } from '@/api/prologue'
|
import { getRecommendations } from '@/api/prologue'
|
||||||
import { FullScreen, Close, Collection } from '@element-plus/icons-vue'
|
import {FullScreen, Close, Collection, Download, Document} from '@element-plus/icons-vue'
|
||||||
import {
|
import {
|
||||||
getWorkflowAndDatasetTableData,
|
getWorkflowAndDatasetTableData,
|
||||||
getAllUserDatasets,
|
getAllUserDatasets,
|
||||||
addDatasetsToWorkflow,
|
addDatasetsToWorkflow,
|
||||||
removeDatasetsFromWorkflow
|
removeDatasetsFromWorkflow
|
||||||
} from '@/api/functionKnowledgeConfig'
|
} from '@/api/functionKnowledgeConfig'
|
||||||
|
import { exportElementToPdf } from '@/utils/exportPdf.ts'
|
||||||
|
|
||||||
const { t, locale } = useI18n()
|
const { t, locale } = useI18n()
|
||||||
const aclStore = useAclStore()
|
const aclStore = useAclStore()
|
||||||
|
const chatBoxRef = ref<InstanceType<typeof ChatBox>|null>(null)
|
||||||
|
|
||||||
|
const exportChatToPdf = async () => {
|
||||||
|
if (chatBoxRef.value) {
|
||||||
|
if (chatBoxRef.value.messagesQuantity === 0) {
|
||||||
|
ElMessage.error('当前没有消息可导出,请开始聊天吧')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
await exportElementToPdf(chatBoxRef.value.messagesContainer, 'chat-history.pdf')
|
||||||
|
ElMessage.success('导出成功')
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ElMessage.error('导出失败')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// 状态管理
|
// 状态管理
|
||||||
const placeholder = ref('给AI助手发送消息')
|
const placeholder = ref('给AI助手发送消息')
|
||||||
|
|
@ -154,10 +181,10 @@ const fetchAllKnowledgeBases = async () => {
|
||||||
try {
|
try {
|
||||||
isLoadingKnowledgeBases.value = true
|
isLoadingKnowledgeBases.value = true
|
||||||
const response: any = await getAllUserDatasets()
|
const response: any = await getAllUserDatasets()
|
||||||
|
|
||||||
if (response && response.code === 200 && response.data) {
|
if (response && response.code === 200 && response.data) {
|
||||||
const userDatasets = response.data
|
const userDatasets = response.data
|
||||||
|
|
||||||
// 提取所有唯一的知识库
|
// 提取所有唯一的知识库
|
||||||
const knowledgeBasesMap = new Map()
|
const knowledgeBasesMap = new Map()
|
||||||
userDatasets.forEach((item: any) => {
|
userDatasets.forEach((item: any) => {
|
||||||
|
|
@ -186,17 +213,17 @@ const fetchAllKnowledgeBases = async () => {
|
||||||
const fetchBoundKnowledgeBases = async () => {
|
const fetchBoundKnowledgeBases = async () => {
|
||||||
try {
|
try {
|
||||||
const response: any = await getWorkflowAndDatasetTableData()
|
const response: any = await getWorkflowAndDatasetTableData()
|
||||||
|
|
||||||
if (response && response.code === 200 && response.data) {
|
if (response && response.code === 200 && response.data) {
|
||||||
// 查找当前 APP_ID 对应的数据
|
// 查找当前 APP_ID 对应的数据
|
||||||
const currentApp = response.data.find((item: any) => item.appId === APP_ID)
|
const currentApp = response.data.find((item: any) => item.appId === APP_ID)
|
||||||
|
|
||||||
if (currentApp && currentApp.datasetIds && currentApp.datasetIds.length > 0) {
|
if (currentApp && currentApp.datasetIds && currentApp.datasetIds.length > 0) {
|
||||||
boundKnowledgeBases.value = []
|
boundKnowledgeBases.value = []
|
||||||
for (let i = 0; i < currentApp.datasetIds.length; i++) {
|
for (let i = 0; i < currentApp.datasetIds.length; i++) {
|
||||||
const datasetId = currentApp.datasetIds[i]
|
const datasetId = currentApp.datasetIds[i]
|
||||||
const datasetName = currentApp.datasetNames[i] || datasetId
|
const datasetName = currentApp.datasetNames[i] || datasetId
|
||||||
|
|
||||||
boundKnowledgeBases.value.push({
|
boundKnowledgeBases.value.push({
|
||||||
id: datasetId,
|
id: datasetId,
|
||||||
name: datasetName
|
name: datasetName
|
||||||
|
|
@ -217,7 +244,7 @@ const fetchBoundKnowledgeBases = async () => {
|
||||||
const openKnowledgeDialog = async () => {
|
const openKnowledgeDialog = async () => {
|
||||||
knowledgeDialogVisible.value = true
|
knowledgeDialogVisible.value = true
|
||||||
selectedKnowledgeBaseIds.value = []
|
selectedKnowledgeBaseIds.value = []
|
||||||
|
|
||||||
// 如果还没有加载过知识库列表,则加载
|
// 如果还没有加载过知识库列表,则加载
|
||||||
if (allKnowledgeBases.value.length === 0) {
|
if (allKnowledgeBases.value.length === 0) {
|
||||||
await fetchAllKnowledgeBases()
|
await fetchAllKnowledgeBases()
|
||||||
|
|
@ -236,16 +263,16 @@ const confirmBindKnowledgeBases = async () => {
|
||||||
ElMessage.warning('请选择要绑定的知识库')
|
ElMessage.warning('请选择要绑定的知识库')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
isBinding.value = true
|
isBinding.value = true
|
||||||
|
|
||||||
// 调用API绑定知识库
|
// 调用API绑定知识库
|
||||||
const response: any = await addDatasetsToWorkflow({
|
const response: any = await addDatasetsToWorkflow({
|
||||||
appId: APP_ID,
|
appId: APP_ID,
|
||||||
datasetIds: selectedKnowledgeBaseIds.value
|
datasetIds: selectedKnowledgeBaseIds.value
|
||||||
})
|
})
|
||||||
|
|
||||||
if (response.code === 200) {
|
if (response.code === 200) {
|
||||||
// 更新本地数据
|
// 更新本地数据
|
||||||
selectedKnowledgeBaseIds.value.forEach(id => {
|
selectedKnowledgeBaseIds.value.forEach(id => {
|
||||||
|
|
@ -254,7 +281,7 @@ const confirmBindKnowledgeBases = async () => {
|
||||||
boundKnowledgeBases.value.push(kb)
|
boundKnowledgeBases.value.push(kb)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
ElMessage.success(`成功绑定 ${selectedKnowledgeBaseIds.value.length} 个知识库`)
|
ElMessage.success(`成功绑定 ${selectedKnowledgeBaseIds.value.length} 个知识库`)
|
||||||
selectedKnowledgeBaseIds.value = []
|
selectedKnowledgeBaseIds.value = []
|
||||||
closeKnowledgeDialog()
|
closeKnowledgeDialog()
|
||||||
|
|
@ -277,7 +304,7 @@ const removeKnowledgeBase = async (knowledgeBaseId: string) => {
|
||||||
appId: APP_ID,
|
appId: APP_ID,
|
||||||
datasetIds: [knowledgeBaseId]
|
datasetIds: [knowledgeBaseId]
|
||||||
})
|
})
|
||||||
|
|
||||||
if (response.code === 200) {
|
if (response.code === 200) {
|
||||||
// 更新本地数据
|
// 更新本地数据
|
||||||
const index = boundKnowledgeBases.value.findIndex(kb => kb.id === knowledgeBaseId)
|
const index = boundKnowledgeBases.value.findIndex(kb => kb.id === knowledgeBaseId)
|
||||||
|
|
@ -348,7 +375,7 @@ const handleChatSwitched = (chatIndex: number) => {
|
||||||
// 全屏功能
|
// 全屏功能
|
||||||
const toggleFullscreen = () => {
|
const toggleFullscreen = () => {
|
||||||
isFullscreen.value = !isFullscreen.value
|
isFullscreen.value = !isFullscreen.value
|
||||||
|
|
||||||
// 隐藏或显示布局的其他部分
|
// 隐藏或显示布局的其他部分
|
||||||
const layoutWrapper = document.querySelector('.vue-admin-better-wrapper') as HTMLElement
|
const layoutWrapper = document.querySelector('.vue-admin-better-wrapper') as HTMLElement
|
||||||
if (layoutWrapper) {
|
if (layoutWrapper) {
|
||||||
|
|
@ -375,13 +402,13 @@ const handleEscKey = (event: KeyboardEvent) => {
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
console.log('组件已挂载,开始加载数据...')
|
console.log('组件已挂载,开始加载数据...')
|
||||||
// await fetchRecommendations()
|
// await fetchRecommendations()
|
||||||
|
|
||||||
// 加载已绑定的知识库
|
// 加载已绑定的知识库
|
||||||
await fetchBoundKnowledgeBases()
|
await fetchBoundKnowledgeBases()
|
||||||
|
|
||||||
isDataLoaded.value = true
|
isDataLoaded.value = true
|
||||||
console.log('数据加载完成')
|
console.log('数据加载完成')
|
||||||
|
|
||||||
// 添加键盘事件监听
|
// 添加键盘事件监听
|
||||||
window.addEventListener('keydown', handleEscKey)
|
window.addEventListener('keydown', handleEscKey)
|
||||||
})
|
})
|
||||||
|
|
@ -389,7 +416,7 @@ onMounted(async () => {
|
||||||
// 组件卸载时清理
|
// 组件卸载时清理
|
||||||
onUnmounted(() => {
|
onUnmounted(() => {
|
||||||
window.removeEventListener('keydown', handleEscKey)
|
window.removeEventListener('keydown', handleEscKey)
|
||||||
|
|
||||||
// 确保退出全屏状态
|
// 确保退出全屏状态
|
||||||
if (isFullscreen.value) {
|
if (isFullscreen.value) {
|
||||||
const layoutWrapper = document.querySelector('.vue-admin-better-wrapper') as HTMLElement
|
const layoutWrapper = document.querySelector('.vue-admin-better-wrapper') as HTMLElement
|
||||||
|
|
@ -587,4 +614,40 @@ onUnmounted(() => {
|
||||||
.main-container.fullscreen-mode ~ .v-modal {
|
.main-container.fullscreen-mode ~ .v-modal {
|
||||||
z-index: 19999 !important;
|
z-index: 19999 !important;
|
||||||
}
|
}
|
||||||
|
.export-pdf-button {
|
||||||
|
position: absolute;
|
||||||
|
top: 16px;
|
||||||
|
right: 110px;
|
||||||
|
z-index: 100;
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
background: var(--el-bg-color);
|
||||||
|
border: 1px solid var(--el-border-color);
|
||||||
|
border-radius: 8px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
.export-pdf-button:hover {
|
||||||
|
background: var(--el-color-primary);
|
||||||
|
color: white;
|
||||||
|
border-color: var(--el-color-primary);
|
||||||
|
transform: scale(1.05);
|
||||||
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
||||||
|
}
|
||||||
|
|
||||||
|
.export-pdf-button :deep(.el-icon) {
|
||||||
|
transition: color 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.export-pdf-button:hover :deep(.el-icon) {
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.export-pdf-button :deep(.el-badge__content) {
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -289,7 +289,7 @@
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.conversation-detail {
|
.conversation-detail {
|
||||||
max-width: 800px;
|
max-width: 1000px;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
|
|
@ -547,23 +547,42 @@
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 滚动条样式 */
|
/* 表格样式 */
|
||||||
.timeline-container::-webkit-scrollbar {
|
.message-content :deep(table) {
|
||||||
width: 6px;
|
width: 100%;
|
||||||
|
border-collapse: collapse;
|
||||||
|
margin: 16px 0;
|
||||||
|
display: block;
|
||||||
|
overflow-x: auto;
|
||||||
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
.timeline-container::-webkit-scrollbar-track {
|
.message-content :deep(th),
|
||||||
background: #f1f1f1;
|
.message-content :deep(td) {
|
||||||
border-radius: 3px;
|
padding: 8px 12px;
|
||||||
|
border: 1px solid #eaecef;
|
||||||
|
text-align: left;
|
||||||
}
|
}
|
||||||
|
|
||||||
.timeline-container::-webkit-scrollbar-thumb {
|
.message-content :deep(th) {
|
||||||
background: #c1c1c1;
|
background-color: #f6f8fa;
|
||||||
border-radius: 3px;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
|
|
||||||
.timeline-container::-webkit-scrollbar-thumb:hover {
|
.message-content :deep(tr:nth-child(even)) {
|
||||||
background: #a8a8a8;
|
background-color: #fafbfc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 超过3列的表格特殊处理 */
|
||||||
|
.message-content :deep(table) {
|
||||||
|
max-width: 100%;
|
||||||
|
table-layout: fixed;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-content :deep(th),
|
||||||
|
.message-content :deep(td) {
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
}
|
}
|
||||||
|
|
||||||
.export-btn {
|
.export-btn {
|
||||||
|
|
|
||||||
|
|
@ -463,6 +463,6 @@
|
||||||
.rounded-devlog {
|
.rounded-devlog {
|
||||||
border-radius: 8px; /* 调整圆角大小 */
|
border-radius: 8px; /* 调整圆角大小 */
|
||||||
overflow: hidden; /* 确保内部内容也被圆角裁剪 */
|
overflow: hidden; /* 确保内部内容也被圆角裁剪 */
|
||||||
width: 46%;
|
width:52%;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue