diff --git a/ALOps_sys_fe/alops-ui/src/views/QandA/Aiassistant/index.vue b/ALOps_sys_fe/alops-ui/src/views/QandA/Aiassistant/index.vue
index a5ec32da..2ba1a4d2 100644
--- a/ALOps_sys_fe/alops-ui/src/views/QandA/Aiassistant/index.vue
+++ b/ALOps_sys_fe/alops-ui/src/views/QandA/Aiassistant/index.vue
@@ -30,11 +30,13 @@
placeholder="请输入您的问题..."
@keyup.enter.native="sendMessage"
>
- 发送
+ v-if="!isTyping" type="primary" icon="el-icon-position" circle>
+
@@ -57,24 +59,32 @@ export default {
data() {
return {
newMessage: '',
- messages: [
- {
- text: '您好!我是AI智能助手,请问有什么可以帮您?',
- sender: 'service',
- time: this.formatTime(new Date())
- }
- ],
+ messages: [],
faqs: [
{ question: '如何查询订单状态?', answer: '您可以在"我的订单"页面查看订单的当前状态和物流信息。' },
{ question: '如何办理退货?', answer: '请在订单详情页点击"申请退货",填写相关信息后提交申请。' },
{ question: '支付方式有哪些?', answer: '我们支持支付宝、微信支付、银联等多种支付方式。' },
{ question: '会员有哪些优惠?', answer: '会员可享受购物折扣、专属优惠券、生日特权等多重优惠。' },
{ question: '商品何时发货?', answer: '一般情况下,我们会在订单支付成功后24小时内安排发货。' }
- ]
+ ],
+ STORAGE_KEY: {
+ permanent: 'ai_assistant_messages',
+ temporary: 'ai_assistant_messages_temp'
+ },
+ storageType: 'temporary', // 默认使用临时存储
+ typewriterInterval: null, // 存储打字效果的定时器引用
+ isTyping: false, // 标记是否正在打字
+ currentMessageIndex: -1 // 当前正在打字的消息索引
};
},mounted() {
+ // 从localStorage加载历史消息
+ this.loadMessages();
// 初始化时滚动到底部,符合大模型聊天体验
this.scrollToBottom();
+ // 监听页面卸载事件,可以在这里清除数据
+ window.addEventListener('beforeunload', this.handleBeforeUnload);
+ // 初始化时使用默认存储类型加载消息
+ this.loadMessages(this.storageType);
},
methods: {
sendMessage() {
@@ -149,12 +159,22 @@ export default {
typeWriter(messageIndex, fullText) {
let currentIndex = 0;
+ // 设置打字状态
+ this.isTyping = true;
+ this.currentMessageIndex = messageIndex;
+
// 优化滚动:先滚动到底部
this.$nextTick(() => {
this.scrollToBottom();
});
- const typeInterval = setInterval(() => {
+ // 清除之前可能存在的定时器
+ if (this.typewriterInterval) {
+ clearInterval(this.typewriterInterval);
+ }
+
+ // 存储定时器引用
+ this.typewriterInterval = setInterval(() => {
if (currentIndex < fullText.length) {
// 优化打字速度:根据文本长度动态调整速度
let typeSpeed = 15; // 加快速度到15毫秒/字符
@@ -184,12 +204,34 @@ export default {
}
} else {
// 打字完成
- clearInterval(typeInterval);
- // 最终滚动到底部
- this.scrollToBottom();
+ this.stopTyping();
}
}, 15); // 加快打字速度到15毫秒/字符
},
+ // 停止打字效果
+ stopTyping() {
+ if (this.typewriterInterval) {
+ clearInterval(this.typewriterInterval);
+ this.typewriterInterval = null;
+ }
+ this.isTyping = false;
+ this.currentMessageIndex = -1;
+ // 最终滚动到底部
+ this.scrollToBottom();
+ },
+ // 立即显示完整答案并停止打字效果
+ showFullAnswer() {
+ if (this.isTyping && this.currentMessageIndex >= 0 && this.currentMessageIndex < this.messages.length) {
+ // 获取当前正在处理的service消息
+ const currentMessage = this.messages[this.currentMessageIndex];
+ if (currentMessage && currentMessage.sender === 'service') {
+ // 停止打字效果
+ this.stopTyping();
+ // 这里我们无法直接获取完整文本,所以只保留已有的部分
+ // 在实际应用中,你可能需要将完整文本存储在某个地方以便快速显示
+ }
+ }
+ },
selectFaq(faq) {
// 添加用户选择的常见问题
this.messages.push({
@@ -315,12 +357,95 @@ export default {
const hours = date.getHours().toString().padStart(2, '0');
const minutes = date.getMinutes().toString().padStart(2, '0');
return `${hours}:${minutes}`;
+ },
+ // 处理页面卸载前的事件
+ handleBeforeUnload() {
+ // 只在临时存储时清除记录
+ if (this.storageType === 'temporary') {
+ this.clearChatHistory('temporary');
+ }
+ },
+ // 清除聊天记录
+ clearChatHistory() {
+ // 保留第一条欢迎消息
+ this.messages = [{...this.messages[0]}];
+ // 清空输入框
+ this.newMessage = '';
+ // 滚动到底部
+ this.scrollToBottom();
+ },
+ // 从存储加载消息
+ loadMessages(type = this.storageType) {
+ try {
+ const storage = type === 'permanent' ? localStorage : sessionStorage;
+ const savedMessages = storage.getItem(this.STORAGE_KEY[type]);
+ if (savedMessages) {
+ this.messages = JSON.parse(savedMessages);
+ } else {
+ // 如果没有保存的消息,显示欢迎消息
+ this.messages = [{
+ text: '您好!我是AI智能助手,请问有什么可以帮您?',
+ sender: 'service',
+ time: this.formatTime(new Date())
+ }];
+ }
+ } catch (error) {
+ console.error('加载消息失败:', error);
+ // 加载失败时显示默认消息
+ this.messages = [{
+ text: '您好!我是AI智能助手,请问有什么可以帮您?',
+ sender: 'service',
+ time: this.formatTime(new Date())
+ }];
+ }
+ },
+ // 保存消息到存储
+ saveMessages(type = this.storageType) {
+ try {
+ const storage = type === 'permanent' ? localStorage : sessionStorage;
+ storage.setItem(this.STORAGE_KEY[type], JSON.stringify(this.messages));
+ } catch (error) {
+ console.error('保存消息失败:', error);
+ }
+ },
+ // 清除对话记录
+ clearChatHistory(type = this.storageType) {
+ try {
+ const storage = type === 'permanent' ? localStorage : sessionStorage;
+ storage.removeItem(this.STORAGE_KEY[type]);
+ this.messages = [{
+ text: '您好!我是AI智能助手,请问有什么可以帮您?',
+ sender: 'service',
+ time: this.formatTime(new Date())
+ }];
+ this.scrollToBottom();
+ } catch (error) {
+ console.error('清除消息失败:', error);
+ }
+ },
+ // 设置存储类型
+ setStorageType(type) {
+ if (['permanent', 'temporary'].includes(type)) {
+ this.storageType = type;
+ // 切换存储类型时重新加载消息
+ this.loadMessages(type);
+ return true;
+ }
+ return false;
+ },
+ // 处理页面卸载前的事件
+ handleBeforeUnload() {
+ // 这里可以根据需求决定是否在关闭浏览器时清除数据
+ // 如果需要清除,可以取消下面这行代码的注释
+ // this.clearChatHistory();
}
},
watch: {
messages: {
handler() {
- // 当消息数组发生变化时,滚动到底部,确保最新消息可见
+ // 当消息数组发生变化时,保存到localStorage
+ this.saveMessages();
+ // 滚动到底部,确保最新消息可见
this.scrollToBottom();
},
deep: true
@@ -347,6 +472,13 @@ export default {
border-top-left-radius: 4px;
border-top-right-radius: 4px;
}
+ .service-header h2 {
+ margin: 0 0 5px 0;
+ }
+ .service-header p {
+ margin: 0;
+ opacity: 0.9;
+ }
.service-container {
display: flex;
min-height: 400px;
@@ -403,9 +535,35 @@ export default {
padding: 15px;
border-top: 1px solid #e6e6e6;
display: flex;
+ gap: 10px;
}
.chat-input .el-input {
margin-right: 10px;
+ flex: 1;
+ }
+ .chat-input .el-button {
+ white-space: nowrap;
+ }
+
+ .stop-btn {
+ align-items: center;
+ border: 2px solid rgba(73, 113, 245, .5);
+ border-radius: 20px;
+ display: flex;
+ height: 36px;
+ justify-content: center;
+ width: 36px;
+ cursor: pointer;
+ transition: all .2s;
+ }
+
+ .stop-btn .el-icon-stop {
+ background: linear-gradient(0deg, #4971f5, #4971f5), #fff;
+ border-radius: 4px;
+ flex-shrink: 0;
+ height: 13px;
+ width: 13px;
+
}
.faq-item {
padding: 10px;