310 lines
6.6 KiB
Vue
310 lines
6.6 KiB
Vue
<template>
|
||
<!-- AI聊天弹窗 -->
|
||
<view v-if="showPopup" class="ai-chat-popup">
|
||
<!-- 遮罩层 -->
|
||
<view class="popup-mask" @click="closePopup"></view>
|
||
|
||
<!-- 弹窗内容 -->
|
||
<view class="popup-content" :class="{ 'full-screen': isFullScreen }">
|
||
<!-- 弹窗头部 -->
|
||
<view class="popup-header">
|
||
<view class="header-left">
|
||
<view class="ai-avatar">🤖</view>
|
||
<view class="header-info">
|
||
<text class="ai-name">AI智能客服</text>
|
||
<text class="ai-status">{{ isOnline ? '在线' : '离线' }}</text>
|
||
</view>
|
||
</view>
|
||
<view class="header-right">
|
||
<button class="header-btn" @click="toggleFullScreen">
|
||
<text class="icon-text">{{ isFullScreen ? '↗' : '↘' }}</text>
|
||
</button>
|
||
<button class="header-btn" @click="closePopup">
|
||
<text class="icon-text">×</text>
|
||
</button>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 聊天消息区域 -->
|
||
<view class="chat-area">
|
||
<!-- 使用ai-chat-message组件 -->
|
||
<ai-chat-message
|
||
ref="chatMessage"
|
||
:initial-messages="messages"
|
||
:user-avatar="userAvatar"
|
||
:ai-avatar="aiAvatar"
|
||
:show-load-more="false"
|
||
@message-sent="onMessageSent"
|
||
@ai-response="onAIResponse"
|
||
@unread-update="onUnreadUpdate"
|
||
@popup-open="onPopupOpen"
|
||
@popup-close="onPopupClose"
|
||
class="chat-message-component" />
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
import aiChatMessage from '@/components/ai-chat-message/ai-chat-message.vue'
|
||
|
||
export default {
|
||
name: 'ai-chat-popup',
|
||
components: {
|
||
aiChatMessage
|
||
},
|
||
props: {
|
||
// 是否显示弹窗
|
||
show: {
|
||
type: Boolean,
|
||
default: false
|
||
},
|
||
// 用户头像
|
||
userAvatar: {
|
||
type: String,
|
||
default: ''
|
||
},
|
||
// AI头像
|
||
aiAvatar: {
|
||
type: String,
|
||
default: ''
|
||
}
|
||
},
|
||
data() {
|
||
return {
|
||
showPopup: false,
|
||
isFullScreen: false,
|
||
isOnline: true,
|
||
unreadCount: 0,
|
||
messages: []
|
||
}
|
||
},
|
||
watch: {
|
||
show(newVal) {
|
||
this.showPopup = newVal
|
||
if (newVal) {
|
||
this.unreadCount = 0
|
||
this.$store.commit('setAiUnreadCount', 0)
|
||
this.$emit('popup-open')
|
||
} else {
|
||
this.$emit('popup-close')
|
||
}
|
||
}
|
||
},
|
||
methods: {
|
||
// 打开弹窗
|
||
openPopup() {
|
||
this.showPopup = true
|
||
this.$emit('update:show', true)
|
||
},
|
||
|
||
// 关闭弹窗
|
||
closePopup() {
|
||
this.showPopup = false
|
||
this.$emit('update:show', false)
|
||
this.isFullScreen = false
|
||
},
|
||
|
||
// 切换全屏模式
|
||
toggleFullScreen() {
|
||
this.isFullScreen = !this.isFullScreen
|
||
this.$emit('fullscreen-toggle', this.isFullScreen)
|
||
},
|
||
|
||
// 消息发送事件处理
|
||
onMessageSent(message) {
|
||
this.$emit('message-sent', message)
|
||
},
|
||
|
||
// AI回复事件处理
|
||
onAIResponse(message) {
|
||
this.$emit('ai-response', message)
|
||
|
||
// 如果弹窗关闭,增加未读消息计数
|
||
if (!this.showPopup) {
|
||
this.unreadCount++
|
||
this.$store.commit('setAiUnreadCount', this.unreadCount)
|
||
this.$emit('unread-update', this.unreadCount)
|
||
}
|
||
},
|
||
|
||
// 未读消息更新事件处理
|
||
onUnreadUpdate(count) {
|
||
this.unreadCount = count
|
||
this.$emit('unread-update', count)
|
||
},
|
||
|
||
// 弹窗打开事件处理
|
||
onPopupOpen() {
|
||
this.$emit('popup-open')
|
||
},
|
||
|
||
// 弹窗关闭事件处理
|
||
onPopupClose() {
|
||
this.$emit('popup-close')
|
||
},
|
||
|
||
// 添加未读消息
|
||
addUnreadMessage() {
|
||
if (!this.showPopup) {
|
||
this.unreadCount++
|
||
this.$emit('unread-update', this.unreadCount)
|
||
}
|
||
},
|
||
|
||
// 清空未读消息
|
||
clearUnreadMessages() {
|
||
this.unreadCount = 0
|
||
this.$emit('unread-update', 0)
|
||
},
|
||
|
||
// 添加消息到聊天记录
|
||
addMessage(message) {
|
||
this.messages.push(message)
|
||
},
|
||
|
||
// 清空聊天记录
|
||
clearMessages() {
|
||
this.messages = []
|
||
},
|
||
|
||
// 获取聊天消息组件实例
|
||
getChatMessageInstance() {
|
||
return this.$refs.chatMessage
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
.ai-chat-popup {
|
||
position: fixed;
|
||
top: 0;
|
||
left: 0;
|
||
right: 0;
|
||
bottom: 0;
|
||
z-index: 1000;
|
||
}
|
||
|
||
.popup-mask {
|
||
position: absolute;
|
||
top: 0;
|
||
left: 0;
|
||
right: 0;
|
||
bottom: 0;
|
||
background-color: rgba(0, 0, 0, 0.5);
|
||
}
|
||
|
||
.popup-content {
|
||
position: absolute;
|
||
right: 30rpx;
|
||
bottom: 300rpx;
|
||
width: 600rpx;
|
||
height: 800rpx;
|
||
background-color: white;
|
||
border-radius: 20rpx;
|
||
box-shadow: 0 10rpx 50rpx rgba(0, 0, 0, 0.3);
|
||
display: flex;
|
||
flex-direction: column;
|
||
transition: all 0.3s ease;
|
||
|
||
&.full-screen {
|
||
right: 0;
|
||
bottom: 0;
|
||
width: 100%;
|
||
height: 100%;
|
||
border-radius: 0;
|
||
}
|
||
}
|
||
|
||
.popup-header {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
padding: 30rpx;
|
||
border-bottom: 2rpx solid #eeeeee;
|
||
background-color: #f8f8f8;
|
||
border-radius: 20rpx 20rpx 0 0;
|
||
|
||
.header-left {
|
||
display: flex;
|
||
align-items: center;
|
||
|
||
.ai-avatar {
|
||
width: 80rpx;
|
||
height: 80rpx;
|
||
border-radius: 50%;
|
||
margin-right: 20rpx;
|
||
}
|
||
|
||
.header-info {
|
||
.ai-name {
|
||
display: block;
|
||
font-size: 32rpx;
|
||
font-weight: bold;
|
||
color: #333;
|
||
}
|
||
|
||
.ai-status {
|
||
display: block;
|
||
font-size: 24rpx;
|
||
color: #666;
|
||
margin-top: 5rpx;
|
||
}
|
||
}
|
||
}
|
||
|
||
.header-right {
|
||
display: flex;
|
||
align-items: center;
|
||
|
||
.header-btn {
|
||
width: 60rpx;
|
||
height: 60rpx;
|
||
border-radius: 50%;
|
||
background-color: rgba(0, 0, 0, 0.1);
|
||
margin-left: 15rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
|
||
.iconfont {
|
||
font-size: 28rpx;
|
||
color: #666;
|
||
}
|
||
|
||
&:active {
|
||
background-color: rgba(0, 0, 0, 0.2);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
.chat-area {
|
||
flex: 1;
|
||
overflow: hidden;
|
||
|
||
.chat-message-component {
|
||
height: 100%;
|
||
width: 100%;
|
||
}
|
||
}
|
||
|
||
/* 响应式适配 */
|
||
@media (max-width: 750rpx) {
|
||
.popup-content {
|
||
right: 20rpx;
|
||
left: 20rpx;
|
||
width: auto;
|
||
height: 70vh;
|
||
bottom: 20rpx;
|
||
|
||
&.full-screen {
|
||
right: 0;
|
||
left: 0;
|
||
bottom: 0;
|
||
height: 100%;
|
||
}
|
||
}
|
||
}
|
||
</style> |