338 lines
7.5 KiB
Vue
338 lines
7.5 KiB
Vue
<template>
|
|
<div class="chat-header">
|
|
<div class="header-content">
|
|
<div class="title">
|
|
<el-button
|
|
class="desktop-sidebar-toggle"
|
|
:icon="Expand"
|
|
@click="settingsStore.toggleSidebar"
|
|
text
|
|
/>
|
|
<span class="title-text">{{ title }}</span>
|
|
|
|
<el-tag v-if="chatStore.currentConversation?.conversationStatus === 'typing'"
|
|
size="small"
|
|
class="status-tag"
|
|
type="warning"
|
|
>
|
|
对话中
|
|
</el-tag>
|
|
</div>
|
|
<div class="actions">
|
|
<HistoryButton :icon-only="false" class="title-history-btn" />
|
|
<el-tooltip content="删除会话" placement="bottom" v-if="chatStore.conversationId">
|
|
<el-button
|
|
class="action-btn delete-btn"
|
|
:icon="Delete"
|
|
@click="handleDelete"
|
|
text
|
|
>
|
|
</el-button>
|
|
</el-tooltip>
|
|
<!-- <el-tooltip content="设置" placement="bottom">
|
|
<el-button
|
|
class="action-btn"
|
|
:icon="Setting"
|
|
@click="handleSettings"
|
|
text
|
|
>
|
|
</el-button>
|
|
</el-tooltip> -->
|
|
<el-tooltip :content="hasBackground ? '客户背景' : '暂无客户背景信息'" placement="bottom" v-if="hasBackground">
|
|
<el-button
|
|
class="action-btn"
|
|
:icon="User"
|
|
@click="showUserInfo = true"
|
|
text
|
|
>
|
|
</el-button>
|
|
</el-tooltip>
|
|
</div>
|
|
</div>
|
|
|
|
<CustomerBackground v-model="showUserInfo" ref="customerBackgroundRef" />
|
|
</div>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { ref, computed, onMounted, onUnmounted } from 'vue'
|
|
import { useChatStore } from '@/store/chat'
|
|
import { useSettingsStore } from '@/store/settings'
|
|
import { Delete, Setting, User, Expand } from '@element-plus/icons-vue'
|
|
import { ElMessageBox } from 'element-plus'
|
|
import HistoryButton from '@/components/chat/HistoryButton.vue'
|
|
import CustomerBackground from '@/components/chat/CustomerBackground.vue'
|
|
|
|
const chatStore = useChatStore()
|
|
const settingsStore = useSettingsStore()
|
|
const showUserInfo = ref(false)
|
|
const customerBackgroundRef = ref(null)
|
|
const isMobile = ref(false)
|
|
|
|
const title = computed(() => {
|
|
const conversation = chatStore.currentConversation
|
|
if (!conversation) return '新会话'
|
|
// 使用第一条消息作为标题
|
|
if (conversation.chatMessages && conversation.chatMessages.length > 0) {
|
|
return conversation.chatMessages[0].question
|
|
}
|
|
return '新会话'
|
|
})
|
|
|
|
const hasBackground = computed(() => {
|
|
return customerBackgroundRef.value?.hasBackground ?? false
|
|
})
|
|
|
|
const handleDelete = async () => {
|
|
console.log(chatStore.conversationId)
|
|
if (!chatStore.conversationId) return
|
|
|
|
try {
|
|
await ElMessageBox.confirm(
|
|
'确定要删除当前会话吗?删除后无法恢复。',
|
|
'删除确认',
|
|
{
|
|
confirmButtonText: '确定',
|
|
cancelButtonText: '取消',
|
|
type: 'warning',
|
|
confirmButtonClass: 'el-button--danger'
|
|
}
|
|
)
|
|
chatStore.deleteConversation(chatStore.conversationId)
|
|
} catch {
|
|
// 用户取消操作
|
|
}
|
|
}
|
|
|
|
const handleSettings = () => {
|
|
// TODO: 实现设置功能
|
|
console.log('打开设置')
|
|
}
|
|
|
|
const checkMobile = () => {
|
|
isMobile.value = window.innerWidth <= 768
|
|
}
|
|
|
|
onMounted(() => {
|
|
checkMobile()
|
|
window.addEventListener('resize', checkMobile)
|
|
})
|
|
|
|
onUnmounted(() => {
|
|
window.removeEventListener('resize', checkMobile)
|
|
})
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
.chat-header {
|
|
height: 60px;
|
|
border-bottom: 1px solid var(--el-border-color-light);
|
|
background: var(--el-color-primary-light-8);
|
|
padding: 0 20px;
|
|
flex-shrink: 0;
|
|
|
|
.header-content {
|
|
height: 100%;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
}
|
|
|
|
.title {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 4px;
|
|
height: 100%;
|
|
|
|
.mobile-sidebar-toggle {
|
|
height: 24px;
|
|
width: 24px;
|
|
padding: 0;
|
|
color: var(--el-text-color-secondary);
|
|
transition: all 0.3s ease;
|
|
border: none;
|
|
background: transparent !important;
|
|
font-size: 14px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
margin-left: -4px;
|
|
|
|
&:hover {
|
|
color: var(--el-color-primary);
|
|
background: transparent !important;
|
|
}
|
|
|
|
&:focus {
|
|
outline: none;
|
|
box-shadow: none;
|
|
}
|
|
|
|
:deep(.el-icon) {
|
|
font-size: 18px;
|
|
margin-top: 1px;
|
|
}
|
|
}
|
|
|
|
.title-text {
|
|
font-size: 16px;
|
|
font-weight: 500;
|
|
color: var(--el-text-color-primary);
|
|
max-width: 500px;
|
|
white-space: nowrap;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
line-height: 24px;
|
|
padding-top: 1px;
|
|
}
|
|
|
|
.desktop-sidebar-toggle {
|
|
height: 24px;
|
|
width: 24px;
|
|
padding: 0;
|
|
color: var(--el-text-color-secondary);
|
|
transition: all 0.3s ease;
|
|
border: none;
|
|
background: transparent !important;
|
|
font-size: 14px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
&:hover {
|
|
color: var(--el-color-primary);
|
|
background: transparent !important;
|
|
}
|
|
|
|
&:focus {
|
|
outline: none;
|
|
box-shadow: none;
|
|
}
|
|
|
|
:deep(.el-icon) {
|
|
font-size: 18px;
|
|
margin-top: 1px;
|
|
}
|
|
}
|
|
|
|
.status-tag {
|
|
font-weight: normal;
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
.title-history-btn {
|
|
:deep(.history-btn) {
|
|
height: 32px;
|
|
padding: 0 12px;
|
|
color: var(--el-text-color-secondary);
|
|
transition: all 0.3s ease;
|
|
font-size: 14px;
|
|
|
|
&:hover {
|
|
color: var(--el-color-primary);
|
|
background-color: var(--el-color-primary-light-9);
|
|
}
|
|
|
|
:deep(.el-icon) {
|
|
font-size: 16px;
|
|
margin-right: 4px;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
.actions {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 4px;
|
|
|
|
.action-btn {
|
|
height: 32px;
|
|
width: 32px;
|
|
padding: 0;
|
|
color: var(--el-text-color-secondary);
|
|
transition: all 0.3s ease;
|
|
border: none;
|
|
background: transparent !important;
|
|
font-size: 14px;
|
|
|
|
&:hover {
|
|
color: var(--el-color-primary);
|
|
background: transparent !important;
|
|
}
|
|
|
|
&.delete-btn {
|
|
&:hover {
|
|
color: var(--el-color-danger) !important;
|
|
background-color: var(--el-color-danger-light-9) !important;
|
|
}
|
|
}
|
|
|
|
&:focus {
|
|
outline: none;
|
|
box-shadow: none;
|
|
}
|
|
|
|
:deep(.el-icon) {
|
|
font-size: 16px;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Dark mode override
|
|
html.dark .chat-header {
|
|
background: var(--el-color-primary-dark-1);
|
|
border-bottom-color: var(--el-border-color-dark);
|
|
}
|
|
|
|
.user-info-content {
|
|
padding: 20px;
|
|
|
|
.info-section {
|
|
margin-bottom: 24px;
|
|
|
|
&:last-child {
|
|
margin-bottom: 0;
|
|
}
|
|
|
|
h3 {
|
|
font-size: 16px;
|
|
font-weight: 500;
|
|
color: #333;
|
|
margin: 0 0 12px 0;
|
|
padding-bottom: 8px;
|
|
border-bottom: 1px solid #eee;
|
|
}
|
|
|
|
.info-item {
|
|
display: flex;
|
|
margin-bottom: 8px;
|
|
line-height: 1.6;
|
|
|
|
&:last-child {
|
|
margin-bottom: 0;
|
|
}
|
|
|
|
&.description {
|
|
flex-direction: column;
|
|
gap: 8px;
|
|
}
|
|
|
|
.label {
|
|
color: #666;
|
|
min-width: 80px;
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
.value {
|
|
color: #333;
|
|
flex: 1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
.dialog-footer {
|
|
padding-top: 20px;
|
|
}
|
|
</style> |