<template>
<div class="content" :style="{ right: visible ? '10px' : '-100%' }">
<el-row style="width:100%;height:100%;">
<el-col :span="24" style="height:100%;padding: 20px;">
<!-- 聊天界面 -->
<div style="width: 100%; display: flex; flex-direction: column;height: 100%;" @click="closeHistory">
<!-- 打开历史记录按钮 -->
<!-- <div
style="text-align: left; height:80%; padding: 10px; position: absolute; top: 10px; right: 10px; display: none;">
<div class="historyBtn" @click="toggleDrawer" @click.stop :style="{
color: drawerVisible ? '#409EFF' : '#45a268'
}">
{{ drawerVisible ? '隐藏历史记录' : '显示历史记录' }}
</div>
</div> -->
<!-- 聊天列表 -->
<div :class="historyShow=== false?'chat-container':'chat-container-act'" style="flex: 1; height:77%; overflow-y: auto;">
<template v-if="chatMessages.length > 0">
<div class="answer-box-item" v-for="(item, index) in chatMessages" :key="index">
<div v-if="item.isUser" class="notes-item" style="justify-content: flex-end">
<div>
<p style="text-align: right;">{{ item.content }}</p>
</div>
<img :src="zhiNengAnswer" alt="">
</div>
<div v-else class="notes-item">
<img class="xiaozhi-icon" :src="imgXiaoZhi" alt="">
<div>
<div>
<p v-loading="item.loading" element-loading-spinner="el-icon-loading"
element-loading-background="rgba(0, 0, 0, 0.3)"
style="text-align: left;">
{{ item.content }}
</p>
</div>
</div>
</div>
</div>
</template>
</div>
<!-- 输入框和发送按钮 -->
</div>
</el-col>
</el-row>
</div>
</template>
<script>
import { getAction, postAction } from '@/api/manage' // 引入api
export default {
props: {
visible: {
type: Boolean,
default: false
}
},
data() {
return {
tipList: this.type === 'airForce'
? ['11111111111?', '2222222222222222?', '3333333333333333']
: ['11111111111111111', '22222222222', '33333333333333'],
activeTab: 'files', // 当前激活的 Tab
tabLoading: false, // tab切换加载中
files: [], // 文件列表
pointList: [], // 要点列表
question: '', // 当前输入框内容
sendDisabled: false, // 发送按钮是否禁用
historyShow: false,
minSpeed: 50, // 最小打字速度
maxSpeed: 100,
chatId: '', // 当前对话的id
chatMessages: [{ isUser: false, content: '' },], // 聊天内容列表
history: [{ id: 1, title: '历史对话1' }, { id: 2, title: '历史对话2' }], // 历史聊天记录
drawerVisible: false, // 控制历史记录显示或隐藏,
zhiNengAnswer: require('@/views/ykzmdmxDir/qbzh/img/zhinenghuida.png'), // 智能体图
imgXiaoZhi: require('@/views/ykzmdmxDir/imgs/xiaozhi.png'), // 小智图
uploadParams: { // 上传文件参数
action: '/navy/big-api/file/fileInfo/multifileListUpload?kbId=e2e67764ad2f11efb1300242ac120002',
name: 'files',
accept: '.doc,.docx,.txt,.pdf',
headers: {
'Content-Type': 'multipart/form-data', // 设置请求头
},
},
}
},
mounted() {
},
watch: {
visible(newVal) {
if (newVal) {
if(this.sendDisabled) return;
this.chatMessages = [{ isUser: false, content: '' },] // 清空聊天记录
this.sendDisabled = true; // 发送按钮可用
this.typeEffect(
this.chatMessages.length - 1,
'eiuroieuroiueoiru需要显示的内容'
);
}
},
type(newVal) {
this.tipList = newVal === 'airForce'
? ['2323333?', '12343444?', '23423749']
: ['34234234444', '2222222222', '33333333333'];
}
},
computed: {
},
methods: {
// 气泡点击发送
tipHandle(item){
if (this.sendDisabled) return this.$message.info('正在回答中');
this.question = item
this.sendQue()
},
// 新建会话
handelCreatNewChat() {
this.creatNewChat() // 创建新会话
},
// 新建对话
creatNewChat(callback) {
this.chatMessages = [{ isUser: false, content: '有关于的问题,可以向我提问' }] // 清空消息列表
this.sendDisabled = false;
this.historyShow = false;
postAction('/navy/dbct-catalog/ManagementModel/knowledgeChat/newChat').then(result => {
if (result.data.code == 200) {
this.chatId = result.data.data // 聊天ID
if (callback) {
callback() // 回调
}
}
})
},
// 删除会话
deleteHistory(packet) {
postAction('/navy/dbct-catalog/ManagementModel/knowledgeChat/deleteGroup', { packet }).then(result => {
this.getHistoryList()
})
},
// 关闭历史记录
closeHistory() {
this.drawerVisible = false; // 关闭
},
// 获取历史记录
getHistoryList() {
postAction('/navy/dbct-catalog/ManagementModel/knowledgeChat/historyByGroup', {}).then(result => {
if (result.data.code == 200) {
this.history = result.data.data
}
})
},
// 选择历史记录
selectHistory(id) {
this.chatId = id; // 聊天记录id
this.chatMessages = [] // 清空聊天记录
this.sendDisabled = true;
this.historyShow = true;
postAction('/navy/dbct-catalog/ManagementModel/knowledgeChat/multiFileHistoryChatByGroup', { packet: id }).then(result => {
if (result.status == 200) {
this.chatMessages = result.data.data.map(item => {
return {
...item,
loading: false,
isUser: item.role == 'user'
}
}) // 聊天记录
}
})
},
// 控制历史记录的显示与隐藏
toggleDrawer() {
this.drawerVisible = !this.drawerVisible; // 切换显示与隐藏
if (this.drawerVisible) {
this.getHistoryList()
}
},
// 发送消息
sendQue() {
if (this.question.trim()) { // 判断输入框是否为空
this.sendDisabled = true;
this.chatMessages.push({ content: this.question, isUser: true }); // 发送消息
this.replyFromModel(this.question); // 模拟大模型的回复
this.question = ''; // 清空输入框
} else {
if (this.sendDisabled) return this.$message.info('正在回答中');
this.$message.info('请输入问题');
}
},
// 大模型的回复
replyFromModel(query) {
this.chatMessages.push({ content: '', isUser: false, loading: true }); // 发送消息
let params = {
packet: this.chatId,
question: query,
}
const fileId = this.type === 'airForce' ? 1008 : 1010;
getAction(`/navy/dbct-catalog/ManagementModel/getFileData4/${fileId}`, params).then(result => {
console.log(result)
if (result.data.answer) {
this.typeEffect(this.chatMessages.length - 1, result.data.answer)
} else {
this.chatMessages[this.chatMessages.length - 1].content = '暂无回答';
}
this.chatMessages[this.chatMessages.length - 1].loading = false;
})
},
// 模拟打字
typeEffect(arrindex, text) {
let index = 0;
const typeNextChar = () => {
if (index < text.length) {
// 每次增加一个字符
if (this.chatMessages[arrindex]) {
this.chatMessages[arrindex].content += text[index];
index++;
// 随机生成下一个字符的打字速度
const randomSpeed = this.getRandomSpeed(this.minSpeed, this.maxSpeed);
// 动态定时调用下一个字符输出
setTimeout(typeNextChar, randomSpeed);
} else {
// 输出完毕,显示发送按钮
return this.sendDisabled = false
}
} else {
this.sendDisabled = false
}
};
typeNextChar();
},
// 生成随机速度
getRandomSpeed(min, max) {
// 生成范围[min, max]内的随机数
return Math.floor(Math.random() * (max - min + 1)) + min;
},
}
}
</script>
<style scoped>
.content {
width: 810px;
height: 35vh;
color:#fff;
position:absolute;
top: 50%;
/* right:-100%; */
transition: all 0.3s ease;
transform: translateY( -50%);
border: 1px solid #45a268;
background: rgba(28, 82, 51, 1);
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
border-radius: 20px;
}
.tip{
height:7%;
width:100%;
margin-bottom:5px;
display: flex;
cursor: pointer;
}
.tip >span{
border: 1px solid #45a268;
background: rgba(28, 82, 51, 1);
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
border-radius: 5px;
padding:5px;
margin-right:5px;
}
.chat-container {
border: 1px solid #45a268;
overflow-y: auto;
border-radius: 10px;
padding: 20px 20px 0;
margin-bottom: 10px;
}
.chat-container-act {
border: 1px solid #45a268;
overflow-y: auto;
border-radius: 10px;
padding: 20px 20px 0;
}
.notes-item {
display: flex;
align-items: flex-start;
margin-bottom: 20px;
}
.notes-item .xiaozhi-icon {
width: 38px;
height: 33px;
vertical-align: text-top;
}
.notes-item img {
width: 30px;
vertical-align: middle;
/*height: 42px;*/
}
.notes-item p {
display: inline-block;
vertical-align: text-top;
margin-left: 14px;
margin-right: 14px;
background: linear-gradient(360deg, #063428 0%, #377540 100%);
color: #ffffff;
padding: 7px 12px;
line-height: 21px;
white-space: pre-wrap;
/*margin-top: 4px;*/
border-radius: 5px;
}
.notes-item span {
display: inline-block;
margin-left: 14px;
color: #ffffff;
padding: 11px 0;
}
.right-bottom {
background: url("@/views/ykzmdmxDir/zszx/image/bg-4.png") no-repeat;
background-size: 100% 100%;
height: 100%;
/* margin-top: 16px; */
padding: 12px 12px;
text-align: left;
color: #fff;
width: 100%;
position: relative;
box-sizing: border-box;
}
.qbzh-transparent-input {
width: 100%;
height: 100%;
background-color: transparent;
/* 透明背景 */
border: none;
/* 移除边框 */
color: white;
/* 继承父元素的文本颜色 */
outline: none;
/* 移除聚焦时的外边框 */
}
.bottom-btn {
background: url("@/views/ykzmdmxDir/zszx/image/icon-2.png") 100% 100% no-repeat;
background-size: 100% 100%;
height: 32px;
width: 62px;
display: inline-block;
position: absolute;
right: 10px;
bottom: 10px;
cursor: pointer;
}
.qbzh-transparent-input::placeholder {
color: white;
/* 占位符颜色设置为白色 */
opacity: 0.7;
/* 占位符透明度(可选,根据需要调整) */
}
.historyBtn {
cursor: pointer;
color: #45a268;
user-select: none;
}
.title {
background-size: auto 100%;
color: #ffffff;
background-image: url("@/views/ykzmdmxDir/imgs/descTittleBox.png");
font-size: 0.55rem;
font-family: YouSheBiaoTiHei;
width: 100%;
text-align: center;
margin-bottom: 20px;
}
.titleBtn {
color: #ffffff;
background: url("@/assets/image/btn-bg-green.png") center no-repeat;
width: 105px;
height: 35px;
background-size: 100% 100%;
line-height: 30px;
cursor: pointer;
position: relative;
left: 50%;
transform: translateX(-50%);
margin-bottom: 10px;
}
.warp-radio-item {
background: linear-gradient(360deg, #063428 0%, #377540 100%);
margin-bottom: 10px;
padding: 10px 20px 10px 10px;
display: flex;
justify-content: space-between;
}
.warp-radio-item-active {
/*background: url("@/assets/image/radio-bg.png") center center no-repeat;*/
/*background-size: 100% 100%;*/
border: 1px solid #3d9c6c;
}
</style>