|
|
<template>
|
|
|
<div class="app-containere">
|
|
|
<el-scrollbar ref="scrollbar" height="530px">
|
|
|
<div class="one-AI" v-if="textOne">
|
|
|
<img src="@/assets/images/ai.png" alt="" />
|
|
|
<div class="AI-item">
|
|
|
<h2>你好,我是AI助手</h2>
|
|
|
<p>作为你的智能伙伴,我既能写文章、想点子,又能陪你聊天、答疑解惑。</p>
|
|
|
<p>想知道我还能做什么?点这里快速上手!可以浏览器收藏网站,下次使用更高效哦 ~</p>
|
|
|
<div class="examples">
|
|
|
<div style="flex-basis: 100%;">
|
|
|
<p>你可以试着问我:</p>
|
|
|
</div>
|
|
|
<div class="example-item" v-for="item in itemData" :key="item" @click="sendExample(item)">
|
|
|
<div style="display:flex">
|
|
|
<img :src="getImg(item.img)" alt="">
|
|
|
<span>{{item.title}}</span>
|
|
|
</div>
|
|
|
<p>{{item.text}}</p>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
<div
|
|
|
v-for="(message, index) in messages"
|
|
|
:key="index"
|
|
|
:class="['message', message.type]"
|
|
|
>
|
|
|
<div class="items-end" v-if="message.type === 'ai-main'">
|
|
|
<img src="@/assets/images/ai.png" alt="" />
|
|
|
</div>
|
|
|
<div
|
|
|
:class="['items-text', message.type]"
|
|
|
:id="'text-container-' + message.id"
|
|
|
>
|
|
|
<p>{{ message.displayContent }}</p>
|
|
|
</div>
|
|
|
</div>
|
|
|
</el-scrollbar>
|
|
|
<div class="main-input">
|
|
|
<form @submit.prevent="sendText">
|
|
|
<el-scrollbar height="140px">
|
|
|
<div class="inputCode" style="display: flex">
|
|
|
<el-input
|
|
|
@keydown="handleKeyDown"
|
|
|
v-model="input"
|
|
|
type="textarea"
|
|
|
rows="6"
|
|
|
resize="none"
|
|
|
placeholder="文件拖拽进来,使用“/”调用指令,可通过shift+回车换行"
|
|
|
/>
|
|
|
<el-button
|
|
|
class="sendButton"
|
|
|
:disabled="input === '' || butFlag"
|
|
|
@click="sendText"
|
|
|
>
|
|
|
<img src="@/assets/images/发送.png" />
|
|
|
</el-button>
|
|
|
</div>
|
|
|
</el-scrollbar>
|
|
|
</form>
|
|
|
</div>
|
|
|
</div>
|
|
|
</template>
|
|
|
|
|
|
<script setup>
|
|
|
import { ref, reactive } from "vue";
|
|
|
import * as AI from "@/api/AI.js";
|
|
|
import {getAssetsFile} from "@/utils/index.js"
|
|
|
const input = ref("");
|
|
|
const butFlag = ref(false);
|
|
|
const messages = reactive([]);
|
|
|
const scrollbar = ref(null);
|
|
|
const isRequestPending = ref(false);
|
|
|
const textOne=ref(true)
|
|
|
const getImg=(img)=>{
|
|
|
return getAssetsFile(img)
|
|
|
}
|
|
|
const itemData=[
|
|
|
{
|
|
|
title:'热点文章编写',
|
|
|
text:'你是一位编辑,请从数学老师王闰秋鼓励支持其发挥数学…',
|
|
|
img:'热点.png'
|
|
|
},
|
|
|
{
|
|
|
title:'暑期实践活动安排',
|
|
|
text:'仿照这些优秀范例,设计一份初中生2024年暑期社会实践…',
|
|
|
img:'安排.png'
|
|
|
},
|
|
|
{
|
|
|
title:'PPT内容框架',
|
|
|
text:'现在你需要制作一份PPT,你需要按照我给出的主题来准备…',
|
|
|
img:'框架.png'
|
|
|
},{
|
|
|
title:'最新学术论文检索',
|
|
|
text:'帮我检索一下今年6月的人工智能领域的最新论文,记得给…',
|
|
|
img:'检索.png'
|
|
|
},{
|
|
|
title:'期末备考计划',
|
|
|
text:'你是大学期末备考专家,我是一名学【工商管理】的学生…',
|
|
|
img:'科研论文.png'
|
|
|
},{
|
|
|
title:'科普2024世界人工智能大会',
|
|
|
text:'阅读下面这些链接,科普一下:2024世界人工智能大会究…',
|
|
|
img:'新闻01.png'
|
|
|
},
|
|
|
]
|
|
|
const sendExample=(item)=>{
|
|
|
textOne.value=false
|
|
|
input.value=item.text
|
|
|
sendText()
|
|
|
}
|
|
|
const sendText = async() => {
|
|
|
if (input.value.trim() === '' || isRequestPending.value) return;
|
|
|
if (input.value.trim() === "") return;
|
|
|
isRequestPending.value = true;
|
|
|
let text = input.value;
|
|
|
textOne.value=false
|
|
|
input.value = "";
|
|
|
|
|
|
// 添加用户消息
|
|
|
messages.push({ id: Date.now(), type: "user-main", displayContent: text });
|
|
|
const sendData = [
|
|
|
{
|
|
|
content: text,
|
|
|
functionCall: {
|
|
|
arguments: "",
|
|
|
name: "",
|
|
|
thoughts: "",
|
|
|
},
|
|
|
name: "",
|
|
|
role: "user",
|
|
|
userId: "487",
|
|
|
},
|
|
|
];
|
|
|
const messageId = Date.now();
|
|
|
const newMessage = reactive({ id: messageId, type: 'ai-main', displayContent: '' });
|
|
|
messages.push(newMessage);
|
|
|
const resp=await fetch('http://192.168.2.16:9868/api/bigModule/createArticleByAi',{
|
|
|
method: 'POST',
|
|
|
headers: {
|
|
|
'Content-Type': 'application/json',
|
|
|
},
|
|
|
body: JSON.stringify(sendData),
|
|
|
})
|
|
|
const reader=resp.body.getReader()
|
|
|
while(1){
|
|
|
const {done,value}=await reader.read()
|
|
|
if(done){
|
|
|
break
|
|
|
}
|
|
|
const decoder=new TextDecoder()
|
|
|
const tet=decoder.decode(value)
|
|
|
newMessage.displayContent+=tet
|
|
|
console.log(tet);
|
|
|
}
|
|
|
nextTick(() => {
|
|
|
setTimeout(() => {
|
|
|
const scrollContainer = scrollbar.value?.$el.querySelector('.el-scrollbar__wrap');
|
|
|
if (scrollContainer) {
|
|
|
scrollContainer.scrollTop = scrollContainer.scrollHeight;
|
|
|
}
|
|
|
}, 10);
|
|
|
});
|
|
|
isRequestPending.value = false;
|
|
|
};
|
|
|
|
|
|
const handleKeyDown = (event) => {
|
|
|
if (event.key === "Enter" && !event.shiftKey) {
|
|
|
event.preventDefault();
|
|
|
sendText();
|
|
|
}
|
|
|
};
|
|
|
</script>
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
|
.app-containere {
|
|
|
margin: 10px 4px 10px 10px;
|
|
|
box-shadow: 0px 0px 13px 0px #0452c6;
|
|
|
border-radius: 10px;
|
|
|
padding: 25px;
|
|
|
}
|
|
|
.message {
|
|
|
display: flex;
|
|
|
align-items: flex-start;
|
|
|
margin-bottom: 10px;
|
|
|
clear: both;
|
|
|
}
|
|
|
.main-input {
|
|
|
background: #011031;
|
|
|
border-radius: 10px;
|
|
|
border: 1px solid #003e7c;
|
|
|
padding: 10px;
|
|
|
}
|
|
|
.inputCode {
|
|
|
.el-button {
|
|
|
margin-top: auto;
|
|
|
background: #ffffff00;
|
|
|
border-color: #ffffff00;
|
|
|
}
|
|
|
.el-textarea {
|
|
|
--el-input-bg-color: #ffffff00 !important;
|
|
|
--el-input-border-color: #ffffff00;
|
|
|
--el-input-hover-border-color: #ffffff00;
|
|
|
--el-input-focus-border-color: #ffffff00;
|
|
|
--el-input-text-color: #ffffff;
|
|
|
}
|
|
|
}
|
|
|
.ai-main {
|
|
|
display: flex;
|
|
|
justify-content: flex-start;
|
|
|
gap: 1rem;
|
|
|
max-width: 94rem;
|
|
|
clear: both;
|
|
|
.items-end {
|
|
|
align-items: flex-start;
|
|
|
flex-direction: column;
|
|
|
flex-shrink: 0;
|
|
|
display: flex;
|
|
|
position: relative;
|
|
|
}
|
|
|
.items-text {
|
|
|
max-width: calc(100% - 400px);
|
|
|
color: #ffffff;
|
|
|
padding: 0px 20px 0px 10px;
|
|
|
flex-direction: column;
|
|
|
min-width: 0;
|
|
|
background: #011031;
|
|
|
border-radius: 10px;
|
|
|
border: 1px solid #003e7c;
|
|
|
}
|
|
|
}
|
|
|
.user-main {
|
|
|
justify-content: flex-end;
|
|
|
margin-top: 15px;
|
|
|
display: flex;
|
|
|
float: right;
|
|
|
gap: 1rem;
|
|
|
max-width: 94rem;
|
|
|
clear: both;
|
|
|
.items-text {
|
|
|
color: #ffffff;
|
|
|
padding: 0px 20px 0px 10px;
|
|
|
flex-direction: column;
|
|
|
min-width: 0;
|
|
|
background: #011031;
|
|
|
border-radius: 10px;
|
|
|
border: 1px solid #003e7c;
|
|
|
margin-right: 15px;
|
|
|
}
|
|
|
}
|
|
|
.one-AI{
|
|
|
display: flex;
|
|
|
width: 100%;
|
|
|
img{
|
|
|
width: 31px;
|
|
|
height: 31px;
|
|
|
}
|
|
|
.AI-item{
|
|
|
width: calc(100% - 200px);
|
|
|
margin-left: 10px;
|
|
|
background: #011031;
|
|
|
border-radius: 10px;
|
|
|
border: 1px solid #003E7C;
|
|
|
padding: 10px 15px;
|
|
|
color:#FFFFFF;
|
|
|
p{
|
|
|
font-size: 12px;
|
|
|
}
|
|
|
.examples{
|
|
|
display: flex;
|
|
|
flex-wrap: wrap;
|
|
|
margin-top: 60px;
|
|
|
width: calc(100% - 300px);
|
|
|
.example-item{
|
|
|
margin: 0 25px 15px 0;
|
|
|
cursor: pointer;
|
|
|
width: 349px;
|
|
|
height: 72px;
|
|
|
background: #002C5B;
|
|
|
border-radius: 10px;
|
|
|
padding: 10px;
|
|
|
img{
|
|
|
width: 20px;
|
|
|
height: 20px;
|
|
|
}
|
|
|
span{
|
|
|
margin-left: 5px;
|
|
|
font-weight: 400;
|
|
|
font-size: 16px;
|
|
|
color: #FFFFFF;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
</style>
|
|
|
|