xiaohuo 8 months ago
commit ed8f876488
  1. 3
      ALOps_sys_fe/alops-ui/src/utils/request.js
  2. 190
      ALOps_sys_fe/alops-ui/src/views/QandA/Aiassistant/index.vue
  3. 24
      ALOps_sys_fe/alops-ui/src/views/device/files/index.vue

@ -87,7 +87,8 @@ service.interceptors.response.use(res => {
isRelogin.show = true isRelogin.show = true
MessageBox.confirm('登录状态已过期,您可以继续留在该页面,或者重新登录', '系统提示', { confirmButtonText: '重新登录', cancelButtonText: '取消', type: 'warning' }).then(() => { MessageBox.confirm('登录状态已过期,您可以继续留在该页面,或者重新登录', '系统提示', { confirmButtonText: '重新登录', cancelButtonText: '取消', type: 'warning' }).then(() => {
isRelogin.show = false isRelogin.show = false
store.dispatch('LogOut').then(() => { // 由于user模块使用了namespaced:true,需要添加命名空间调用登出方法
store.dispatch('user/LogOut').then(() => {
// 使用Vue Router进行跳转,确保正确导航到登录页面 // 使用Vue Router进行跳转,确保正确导航到登录页面
import('@/router').then(router => { import('@/router').then(router => {
router.default.push('/login') router.default.push('/login')

@ -31,10 +31,12 @@
@keyup.enter.native="sendMessage" @keyup.enter.native="sendMessage"
></el-input> ></el-input>
<el-button <el-button
type="primary"
@click="sendMessage" @click="sendMessage"
:disabled="!newMessage.trim()" v-if="!isTyping" type="primary" icon="el-icon-position" circle></el-button>
>发送</el-button> <div class="stop-btn " v-if="isTyping"
@click="showFullAnswer">
<div class="el-icon-stop"></div>
</div>
</div> </div>
</div> </div>
</div> </div>
@ -57,24 +59,32 @@ export default {
data() { data() {
return { return {
newMessage: '', newMessage: '',
messages: [ messages: [],
{
text: '您好!我是AI智能助手,请问有什么可以帮您?',
sender: 'service',
time: this.formatTime(new Date())
}
],
faqs: [ faqs: [
{ question: '如何查询订单状态?', answer: '您可以在"我的订单"页面查看订单的当前状态和物流信息。' }, { question: '如何查询订单状态?', answer: '您可以在"我的订单"页面查看订单的当前状态和物流信息。' },
{ question: '如何办理退货?', answer: '请在订单详情页点击"申请退货",填写相关信息后提交申请。' }, { question: '如何办理退货?', answer: '请在订单详情页点击"申请退货",填写相关信息后提交申请。' },
{ question: '支付方式有哪些?', answer: '我们支持支付宝、微信支付、银联等多种支付方式。' }, { question: '支付方式有哪些?', answer: '我们支持支付宝、微信支付、银联等多种支付方式。' },
{ question: '会员有哪些优惠?', answer: '会员可享受购物折扣、专属优惠券、生日特权等多重优惠。' }, { question: '会员有哪些优惠?', answer: '会员可享受购物折扣、专属优惠券、生日特权等多重优惠。' },
{ question: '商品何时发货?', answer: '一般情况下,我们会在订单支付成功后24小时内安排发货。' } { question: '商品何时发货?', answer: '一般情况下,我们会在订单支付成功后24小时内安排发货。' }
] ],
STORAGE_KEY: {
permanent: 'ai_assistant_messages',
temporary: 'ai_assistant_messages_temp'
},
storageType: 'temporary', // 使
typewriterInterval: null, //
isTyping: false, //
currentMessageIndex: -1 //
}; };
},mounted() { },mounted() {
// localStorage
this.loadMessages();
// //
this.scrollToBottom(); this.scrollToBottom();
//
window.addEventListener('beforeunload', this.handleBeforeUnload);
// 使
this.loadMessages(this.storageType);
}, },
methods: { methods: {
sendMessage() { sendMessage() {
@ -149,12 +159,22 @@ export default {
typeWriter(messageIndex, fullText) { typeWriter(messageIndex, fullText) {
let currentIndex = 0; let currentIndex = 0;
//
this.isTyping = true;
this.currentMessageIndex = messageIndex;
// //
this.$nextTick(() => { this.$nextTick(() => {
this.scrollToBottom(); this.scrollToBottom();
}); });
const typeInterval = setInterval(() => { //
if (this.typewriterInterval) {
clearInterval(this.typewriterInterval);
}
//
this.typewriterInterval = setInterval(() => {
if (currentIndex < fullText.length) { if (currentIndex < fullText.length) {
// //
let typeSpeed = 15; // 15/ let typeSpeed = 15; // 15/
@ -184,12 +204,34 @@ export default {
} }
} else { } else {
// //
clearInterval(typeInterval); this.stopTyping();
//
this.scrollToBottom();
} }
}, 15); // 15/ }, 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) { selectFaq(faq) {
// //
this.messages.push({ this.messages.push({
@ -315,12 +357,95 @@ export default {
const hours = date.getHours().toString().padStart(2, '0'); const hours = date.getHours().toString().padStart(2, '0');
const minutes = date.getMinutes().toString().padStart(2, '0'); const minutes = date.getMinutes().toString().padStart(2, '0');
return `${hours}:${minutes}`; 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: { watch: {
messages: { messages: {
handler() { handler() {
// // localStorage
this.saveMessages();
//
this.scrollToBottom(); this.scrollToBottom();
}, },
deep: true deep: true
@ -347,6 +472,13 @@ export default {
border-top-left-radius: 4px; border-top-left-radius: 4px;
border-top-right-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 { .service-container {
display: flex; display: flex;
min-height: 400px; min-height: 400px;
@ -403,9 +535,35 @@ export default {
padding: 15px; padding: 15px;
border-top: 1px solid #e6e6e6; border-top: 1px solid #e6e6e6;
display: flex; display: flex;
gap: 10px;
} }
.chat-input .el-input { .chat-input .el-input {
margin-right: 10px; 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 { .faq-item {
padding: 10px; padding: 10px;

@ -108,7 +108,7 @@
<el-row :gutter="20"> <el-row :gutter="20">
<el-col :span="12"> <el-col :span="12">
<el-form-item label="设备编号" prop="equNumber"> <el-form-item label="设备编号" prop="equNumber">
<el-input v-model="form.equNumber" placeholder="请输入设备名称" maxlength="30" /> <el-input v-model="form.equNumber" placeholder="请输入设备编号" maxlength="30" />
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
@ -131,7 +131,8 @@
reserve-keyword reserve-keyword
placeholder="请输入" placeholder="请输入"
:remote-method="remoteMethod1" :remote-method="remoteMethod1"
:loading="loading1"> :loading="loading1"
style="width: 100%;">
<el-option <el-option
v-for="item in options1" v-for="item in options1"
:key="item.id" :key="item.id"
@ -161,7 +162,8 @@
reserve-keyword reserve-keyword
placeholder="请输入" placeholder="请输入"
:remote-method="remoteMethod2" :remote-method="remoteMethod2"
:loading="loading2"> :loading="loading2"
style="width: 100%;">
<el-option <el-option
v-for="item in options2" v-for="item in options2"
:key="item.id" :key="item.id"
@ -186,7 +188,8 @@
reserve-keyword reserve-keyword
placeholder="请输入" placeholder="请输入"
:remote-method="remoteMethod3" :remote-method="remoteMethod3"
:loading="loading3"> :loading="loading3"
style="width: 100%;">
<el-option <el-option
v-for="item in options3" v-for="item in options3"
:key="item.id" :key="item.id"
@ -202,13 +205,14 @@
v-model="form.installDate" v-model="form.installDate"
type="date" type="date"
value-format="yyyy-MM-dd" value-format="yyyy-MM-dd"
placeholder="选择日期"> placeholder="选择日期"
style="width: 100%;">
</el-date-picker> </el-date-picker>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<el-form-item label="安装楼层" prop="floor"> <el-form-item label="安装楼层" prop="floor">
<el-select v-model="form.floor" placeholder="安装楼层" clearable style="width: 240px"> <el-select v-model="form.floor" placeholder="安装楼层" clearable style="width: 100%;">
<el-option v-for="dict in dict.type.floor_data" :key="dict.value" :label="dict.label" :value="dict.value" /> <el-option v-for="dict in dict.type.floor_data" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select> </el-select>
</el-form-item> </el-form-item>
@ -225,12 +229,16 @@
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<el-form-item label="预计年限" prop="lifeCycle"> <el-form-item label="预计年限" prop="lifeCycle">
<el-input v-model="form.lifeCycle" placeholder="请输入预计年限" maxlength="30" /> <el-input v-model.number="form.lifeCycle" placeholder="请输入预计年限" maxlength="30" type="number" min="1" oninput="value=value.replace(/[^1-9]\d*/g, '')">
<template slot="append"></template>
</el-input>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<el-form-item label="质保年限" prop="warranty"> <el-form-item label="质保年限" prop="warranty">
<el-input v-model="form.warranty" placeholder="请输入质保年限" maxlength="30" /> <el-input v-model.number="form.warranty" placeholder="请输入质保年限" maxlength="30" type="number" min="1" oninput="value=value.replace(/[^1-9]\d*/g, '')">
<template slot="append"></template>
</el-input>
</el-form-item> </el-form-item>
</el-col> </el-col>

Loading…
Cancel
Save