Files
Situation-Awareness-Platfor…/src/views/Jyh/KnowledgeHub/Components/AIModal.vue

280 lines
6.6 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<d-modal
v-model="visible"
title="AI问答"
@ok="handleClose"
:cancel="handleClose"
style="width: 900px;"
>
<div class="log-content">
<McLayout>
<!-- <McLayoutHeader>
<McHeader :logoImg="'/logo.svg'" :title="'MateChat'"></McHeader>
</McLayoutHeader>-->
<McLayoutContent v-if="visible" style="margin: 16px 0;">
<div ref="conversationRef" class="conversation-area">
<!-- 欢迎提示 -->
<div v-if="messages.length === 0" class="welcome-message">
<div class="welcome-page">
<div class="home-title">
<img src="@/assets/imgs/jyh/aiLogo2.png" alt="logo" />
<h1>TcodeAI助手</h1>
</div>
<div class="home-detail">
<div class="home-detail-1">Hi欢迎使用TcodeAI助手</div>
<div class="home-detail-2">TcodeAI助手 可以辅助研发人员进行软件查询批量校验查看软件详情等</div>
<div class="home-detail-2">作为AI模型TcodeAI助手 提供的答案可能不总是确定或准确的但您的反馈可以帮助 TcodeAI助手 做得更好</div>
</div>
</div>
<!-- <div class="welcome-icon">-->
<!-- <i class="fa fa-comment-dots"></i>-->
<!-- </div>-->
<!-- <div class="welcome-text">-->
<!-- <h3>请输入你想问的内容</h3>-->
<!-- <p>与AI助手开始对话获取智能回答</p>-->
<!-- </div>-->
</div>
<template v-for="(msg, idx) in messages" :key="idx">
<McBubble v-if="msg.role === 'user'" :content="msg.content" :align="'right'"></McBubble>
<McBubble v-else :loading="msg.loading ?? false">
<McMarkdownCard :content="msg.content" :theme="theme"></McMarkdownCard>
</McBubble>
</template>
</div>
</McLayoutContent>
<McLayoutSender>
<McInput :value="inputValue" :maxLength="2000" @submit="onSubmit" showCount></McInput>
</McLayoutSender>
</McLayout>
</div>
</d-modal>
</template>
<script setup>
import { ref, watch,nextTick } from 'vue';
import { Message } from 'vue-devui';
import axios from 'axios';
import {uvdV1Chat} from "@/api/inboundTask/inboundTaskApi";
const messages = ref([]);
const history = ref([]);
const resultInfo = ref(null);
const inputValue = ref('');
const conversationRef = ref(null);
// 组件状态
const visible = ref(false);
const VITE_AI_API_HOST = import.meta.env.VITE_AI_API_HOST;
// 打开弹框时调用接口
const open = async (id) => {
if (!id) return Message.error('缺少result_id参数');
visible.value = true;
resultInfo.value = id
};
const onSubmit = (e) => {
if(e === '') {
return;
}
if(messages.value[messages.value.length-1]?.loading) return;
inputValue.value = '';
messages.value.push({
role: 'user',
content: e,
});
nextTick(() => {
conversationRef.value?.scrollTo({
top: conversationRef.value.scrollHeight,
behavior: 'smooth',
});
});
getAIAnswer(e);
};
const getAIAnswer = async (content) => {
messages.value.push({
role: 'assistant',
content: '',
loading: true,
});
const res = await uvdV1Chat({
"resultInfo": resultInfo.value,
"query": content,
"history": history.value || []
});
let reply = res?.data?.data?.reply || '';
history.value.push({role: "user", content: content});
history.value.push({role: "assistant", content: reply});
messages.value[messages.value.length - 1].content = reply;
messages.value[messages.value.length - 1].loading = false;
nextTick(() => {
conversationRef.value?.scrollTo({
top: conversationRef.value.scrollHeight
});
});
/* 模拟流式数据返回 */
// setTimeout(async () => {
// messages.value.at(-1).loading = false;
// for (let i = 0; i < reply.length;) {
// await new Promise(r => setTimeout(r, 300 * Math.random()));
// messages.value[messages.value.length - 1].content = reply.slice(0, i += Math.random() * 10);
// nextTick(() => {
// conversationRef.value?.scrollTo({
// top: conversationRef.value.scrollHeight
// });
// });
// }
// }, 1000);
};
// 暴露给父组件的方法
defineExpose({
open // 通过ref调用open方法传递resultId
});
// 关闭弹框
const handleClose = () => {
messages.value = [];
history.value = [];
result_id.value = null;
inputValue.value = '';
visible.value = false;
};
</script>
<style lang="scss" scoped>
.log-content {
padding: 24px;
line-height: 1.6;
white-space: pre-wrap; // 保留日志换行
word-break: break-all; // 自动换行长单词
min-height: 200px;
p {
margin: 0;
color: #333;
}
}
.conversation-area,
.welcome-page {
flex: 1;
display: flex;
flex-direction: column;
overflow: auto;
padding: 0 12px;
min-height: 400px;
max-height: 600px;
overflow-y: auto;
}
.conversation-area {
gap: 8px;
}
.welcome-message {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100%;
padding: 32px;
text-align: center;
.welcome-icon {
width: 64px;
height: 64px;
background-color: #e6f4ff;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 16px;
i {
font-size: 28px;
color: #1677ff;
}
}
.welcome-text {
h3 {
font-size: 18px;
font-weight: 500;
color: #333;
margin-bottom: 8px;
}
p {
font-size: 14px;
color: #666;
}
}
}
.home-title {
display: flex;
flex-shrink: 0;
justify-content: center;
align-items: center;
gap: 20px;
h1 {
color: #191919;
font-family: Huawei Sans;
font-weight: bold;
font-size: 32px;
line-height: 48px;
letter-spacing: 0px;
text-align: center;
}
img {
width: 64px;
//filter: brightness(0);
}
}
.home-detail {
.home-detail-1 {
color: #191919;
font-family: HarmonyOS Sans SC;
font-weight: medium;
font-size: 24px;
line-height: 32px;
letter-spacing: 0px;
text-align: center;
margin-bottom: 24px;
}
.home-detail-2 {
color: #777777;
font-family: HarmonyOS Sans SC;
font-weight: regular;
font-size: 14px;
line-height: 22px;
letter-spacing: 0px;
text-align: center;
}
}
.welcome-page {
//height: 90%;
width: 100%;
flex: 1;
display: flex;
flex-direction: column;
overflow: auto;
padding: 0 12px;
}
.welcome-page {
gap: 16px;
justify-content: center;
}
</style>