3 changed files with 613 additions and 428 deletions
@ -1,201 +1,226 @@ |
|||||
<script setup> |
<script setup> |
||||
import { ref, onMounted, watch, nextTick } from 'vue' |
|
||||
import { ElDialog } from 'element-plus' |
|
||||
import { getReplyStreamAPI } from '../api/AIxiaocaishen' |
|
||||
|
import { ref, onMounted, watch, nextTick } from "vue"; |
||||
|
import { ElDialog } from "element-plus"; |
||||
|
import { getReplyStreamAPI } from "../api/AIxiaocaishen"; |
||||
|
|
||||
// 随机GIF |
// 随机GIF |
||||
const currentGif = ref('') |
|
||||
|
const currentGif = ref(""); |
||||
|
|
||||
// 新闻飘屏数据 |
// 新闻飘屏数据 |
||||
const newsList = ref(Array(10).fill().map((_, i) => ({ |
|
||||
title: `引导提出问题 ${i + 1}`, |
|
||||
content: `新闻 ${i + 1} 的详细内容...` |
|
||||
}))) |
|
||||
|
|
||||
|
const newsList = ref( |
||||
|
Array(10) |
||||
|
.fill() |
||||
|
.map((_, i) => ({ |
||||
|
title: `引导提出问题 ${i + 1}`, |
||||
|
content: `新闻 ${i + 1} 的详细内容...`, |
||||
|
})) |
||||
|
); |
||||
|
|
||||
|
// 定义自定义事件 |
||||
|
const emit = defineEmits(["updateMessage", "sendMessage"]); |
||||
|
|
||||
// 弹窗控制 |
// 弹窗控制 |
||||
const dialogVisible = ref(false) |
|
||||
const currentNews = ref('') |
|
||||
|
|
||||
|
const dialogVisible = ref(false); |
||||
|
const currentNews = ref(""); |
||||
const showNews = (news) => { |
const showNews = (news) => { |
||||
currentNews.value = news |
|
||||
dialogVisible.value = true |
|
||||
} |
|
||||
|
currentNews.value = news; |
||||
|
dialogVisible.value = true; |
||||
|
// 触发自定义事件 |
||||
|
emit("updateMessage", news.title); |
||||
|
emit("sendMessage"); |
||||
|
}; |
||||
|
|
||||
// 获取消息 |
// 获取消息 |
||||
const props = defineProps({ |
const props = defineProps({ |
||||
messages: Array, |
|
||||
}) |
|
||||
|
messages: Array, |
||||
|
}); |
||||
|
|
||||
watch(() => props.messages, async (newVal, oldVal) => { |
|
||||
console.log('消息列表已更新,最新消息:', newVal[newVal.length - 1]) |
|
||||
|
watch( |
||||
|
() => props.messages, |
||||
|
async (newVal, oldVal) => { |
||||
|
console.log("消息列表已更新,最新消息:", newVal[newVal.length - 1]); |
||||
// 在此处添加需要执行的逻辑 |
// 在此处添加需要执行的逻辑 |
||||
const response = await getReplyStreamAPI({ |
const response = await getReplyStreamAPI({ |
||||
"workflow_id": "7480464341100494863", |
|
||||
"parameters": { |
|
||||
"input": newVal[newVal.length - 1].content |
|
||||
} |
|
||||
|
workflow_id: "7480464341100494863", |
||||
|
parameters: { |
||||
|
input: newVal[newVal.length - 1].content, |
||||
|
}, |
||||
}); |
}); |
||||
const reader = response.body.getReader(); |
const reader = response.body.getReader(); |
||||
|
|
||||
console.log(response, 'response') |
|
||||
console.log(reader, 'reader') |
|
||||
|
|
||||
}, { deep: true, immediate: true }) |
|
||||
|
console.log(response, "response"); |
||||
|
console.log(reader, "reader"); |
||||
|
}, |
||||
|
{ deep: true, immediate: true } |
||||
|
); |
||||
|
|
||||
// 初始化随机GIF |
// 初始化随机GIF |
||||
onMounted(() => { |
onMounted(() => { |
||||
const random = Math.floor(Math.random() * 4) + 1 |
|
||||
console.log(random, 'random') |
|
||||
currentGif.value = `src/assets/img/AIchat/AIgif${random}.gif` |
|
||||
}) |
|
||||
|
const random = Math.floor(Math.random() * 4) + 1; |
||||
|
console.log(random, "random"); |
||||
|
currentGif.value = `src/assets/img/AIchat/AIgif${random}.gif`; |
||||
|
}); |
||||
</script> |
</script> |
||||
|
|
||||
<template> |
<template> |
||||
<div class="chat-container"> |
|
||||
<!-- GIF区域 --> |
|
||||
<div class="gif-area"> |
|
||||
<img :src="currentGif" alt="AI动画"> |
|
||||
|
|
||||
<div class="marquee-container"> |
|
||||
<div class="marquee-row top"> |
|
||||
<div v-for="(news, index) in newsList.slice(0, 5)" :key="'top' + index" class="marquee-item" |
|
||||
@click="showNews(news)"> |
|
||||
{{ news.title }} |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="marquee-row bottom"> |
|
||||
<div v-for="(news, index) in newsList.slice(5, 10)" :key="'bottom' + index" class="marquee-item" |
|
||||
@click="showNews(news)"> |
|
||||
{{ news.title }} |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
|
<div class="chat-container"> |
||||
|
<!-- GIF区域 --> |
||||
|
<div class="gif-area"> |
||||
|
<img :src="currentGif" alt="AI动画" /> |
||||
|
|
||||
|
<div class="marquee-container"> |
||||
|
<div class="marquee-row top"> |
||||
|
<div |
||||
|
v-for="(news, index) in newsList.slice(0, 5)" |
||||
|
:key="'top' + index" |
||||
|
class="marquee-item" |
||||
|
@click="showNews(news)" |
||||
|
> |
||||
|
{{ news.title }} |
||||
|
</div> |
||||
</div> |
</div> |
||||
|
|
||||
<!-- 消息区域 --> |
|
||||
<div class="message-area"> |
|
||||
<div v-for="(msg, index) in messages" :key="index" :class="['message-bubble', msg.sender]"> |
|
||||
{{ msg.content }} |
|
||||
</div> |
|
||||
|
<div class="marquee-row bottom"> |
||||
|
<div |
||||
|
v-for="(news, index) in newsList.slice(5, 10)" |
||||
|
:key="'bottom' + index" |
||||
|
class="marquee-item" |
||||
|
@click="showNews(news)" |
||||
|
> |
||||
|
{{ news.title }} |
||||
|
</div> |
||||
</div> |
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
<!-- 新闻弹窗 --> |
|
||||
<el-dialog v-model="dialogVisible" title="新闻详情" width="60%"> |
|
||||
<p>{{ currentNews.content }}</p> |
|
||||
</el-dialog> |
|
||||
|
<!-- 消息区域 --> |
||||
|
<div class="message-area"> |
||||
|
<div |
||||
|
v-for="(msg, index) in messages" |
||||
|
:key="index" |
||||
|
:class="['message-bubble', msg.sender]" |
||||
|
> |
||||
|
{{ msg.content }} |
||||
|
</div> |
||||
</div> |
</div> |
||||
|
|
||||
|
<!-- 新闻弹窗 --> |
||||
|
<el-dialog v-model="dialogVisible" title="新闻详情" width="60%"> |
||||
|
<p>{{ currentNews.content }}</p> |
||||
|
</el-dialog> |
||||
|
</div> |
||||
</template> |
</template> |
||||
|
|
||||
<style scoped> |
<style scoped> |
||||
.chat-container { |
.chat-container { |
||||
display: flex; |
|
||||
flex-direction: column; |
|
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
} |
} |
||||
|
|
||||
.gif-area { |
.gif-area { |
||||
/* position: relative; */ |
|
||||
height: 30vh; |
|
||||
display: flex; |
|
||||
flex-direction: column; |
|
||||
justify-content: center; |
|
||||
align-items: center; |
|
||||
|
/* position: relative; */ |
||||
|
height: 30vh; |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
justify-content: center; |
||||
|
align-items: center; |
||||
} |
} |
||||
|
|
||||
.gif-area img { |
.gif-area img { |
||||
width: 30%; |
|
||||
/* 改为百分比单位 */ |
|
||||
min-width: 200px; |
|
||||
/* 最小尺寸 */ |
|
||||
max-width: 400px; |
|
||||
/* 最大尺寸 */ |
|
||||
height: auto; |
|
||||
left: 50%; |
|
||||
transition: all 0.3s; |
|
||||
/* 添加过渡效果 */ |
|
||||
|
|
||||
|
width: 30%; |
||||
|
/* 改为百分比单位 */ |
||||
|
min-width: 200px; |
||||
|
/* 最小尺寸 */ |
||||
|
max-width: 400px; |
||||
|
/* 最大尺寸 */ |
||||
|
height: auto; |
||||
|
left: 50%; |
||||
|
transition: all 0.3s; |
||||
|
/* 添加过渡效果 */ |
||||
} |
} |
||||
|
|
||||
.marquee-container { |
.marquee-container { |
||||
/* position: absolute; */ |
|
||||
bottom: 0; |
|
||||
width: 100%; |
|
||||
|
/* position: absolute; */ |
||||
|
bottom: 0; |
||||
|
width: 100%; |
||||
} |
} |
||||
|
|
||||
.marquee-row { |
.marquee-row { |
||||
white-space: nowrap; |
|
||||
overflow: visible; |
|
||||
padding: 8px 0; |
|
||||
width: 100%; |
|
||||
|
white-space: nowrap; |
||||
|
overflow: visible; |
||||
|
padding: 8px 0; |
||||
|
width: 100%; |
||||
} |
} |
||||
|
|
||||
.marquee-item { |
.marquee-item { |
||||
display: inline-block; |
|
||||
margin: 0 15px; |
|
||||
padding: 8px 20px; |
|
||||
background: rgba(255, 255, 255, 0.9); |
|
||||
/* 白色背景 */ |
|
||||
border-radius: 10px; |
|
||||
/* 圆角矩形 */ |
|
||||
color: #333; |
|
||||
/* 文字颜色改为深色 */ |
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); |
|
||||
/* 添加阴影 */ |
|
||||
transition: all 0.3s; |
|
||||
transition: color 0.3s; |
|
||||
|
display: inline-block; |
||||
|
margin: 0 15px; |
||||
|
padding: 8px 20px; |
||||
|
background: rgba(255, 255, 255, 0.9); |
||||
|
/* 白色背景 */ |
||||
|
border-radius: 10px; |
||||
|
/* 圆角矩形 */ |
||||
|
color: #333; |
||||
|
/* 文字颜色改为深色 */ |
||||
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); |
||||
|
/* 添加阴影 */ |
||||
|
transition: all 0.3s; |
||||
|
transition: color 0.3s; |
||||
} |
} |
||||
|
|
||||
.top { |
.top { |
||||
animation: marquee 15s linear infinite; |
|
||||
|
animation: marquee 15s linear infinite; |
||||
} |
} |
||||
|
|
||||
.bottom { |
.bottom { |
||||
animation: marquee 15s linear infinite reverse; |
|
||||
|
animation: marquee 15s linear infinite reverse; |
||||
} |
} |
||||
|
|
||||
@keyframes marquee { |
@keyframes marquee { |
||||
0% { |
|
||||
transform: translateX(100%); |
|
||||
} |
|
||||
|
0% { |
||||
|
transform: translateX(100%); |
||||
|
} |
||||
|
|
||||
100% { |
|
||||
transform: translateX(-150%); |
|
||||
} |
|
||||
|
100% { |
||||
|
transform: translateX(-150%); |
||||
|
} |
||||
} |
} |
||||
|
|
||||
.message-area { |
.message-area { |
||||
flex: 1; |
|
||||
overflow: auto; |
|
||||
padding: 20px; |
|
||||
|
flex: 1; |
||||
|
overflow: auto; |
||||
|
padding: 20px; |
||||
} |
} |
||||
|
|
||||
.message-bubble { |
.message-bubble { |
||||
max-width: 70%; |
|
||||
margin: 10px 20px; |
|
||||
padding: 15px 25px; |
|
||||
border-radius: 10px; |
|
||||
position: relative; |
|
||||
|
max-width: 70%; |
||||
|
margin: 10px 20px; |
||||
|
padding: 15px 25px; |
||||
|
border-radius: 10px; |
||||
|
position: relative; |
||||
} |
} |
||||
|
|
||||
.message-bubble.user { |
.message-bubble.user { |
||||
background: #8263f0; |
|
||||
color: white; |
|
||||
margin-left: auto; |
|
||||
/* border-bottom-right-radius: 5px; */ |
|
||||
|
background: #8263f0; |
||||
|
color: white; |
||||
|
margin-left: auto; |
||||
|
/* border-bottom-right-radius: 5px; */ |
||||
} |
} |
||||
|
|
||||
.message-bubble.ai { |
.message-bubble.ai { |
||||
background: #f0f0f0; |
|
||||
color: #333; |
|
||||
margin-right: auto; |
|
||||
border-bottom-left-radius: 5px; |
|
||||
|
background: #f0f0f0; |
||||
|
color: #333; |
||||
|
margin-right: auto; |
||||
|
border-bottom-left-radius: 5px; |
||||
} |
} |
||||
|
|
||||
.message-area { |
.message-area { |
||||
flex: 1; |
|
||||
overflow-y: auto; |
|
||||
padding: 20px; |
|
||||
display: flex; |
|
||||
flex-direction: column; |
|
||||
gap: 15px; |
|
||||
|
flex: 1; |
||||
|
overflow-y: auto; |
||||
|
padding: 20px; |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
gap: 15px; |
||||
} |
} |
||||
</style> |
|
||||
|
</style> |
@ -0,0 +1,40 @@ |
|||||
|
<script setup></script> |
||||
|
<template> |
||||
|
<el-main class="homepage-body"> |
||||
|
<div class="main-wrapper"> |
||||
|
<img |
||||
|
src="src\assets\img\AIchat\AIgif1.gif" |
||||
|
alt="图片加载失败" |
||||
|
class="logo1" |
||||
|
/> |
||||
|
<!-- 一段文字,水平居中,宽度为500px --> |
||||
|
|
||||
|
<div style="width: 500px; margin: 0 auto; text-align: center"> |
||||
|
<p> |
||||
|
欢迎使用AI智能问答系统,本系统基于OpenAI的GPT-3.5模型,为您提供智能问答服务。 |
||||
|
</p> |
||||
|
<p>这个是公告部分</p> |
||||
|
</div> |
||||
|
</div> |
||||
|
</el-main> |
||||
|
</template> |
||||
|
<style scoped> |
||||
|
.homepage-body { |
||||
|
padding: 0px; |
||||
|
height: calc(100% - 70px); |
||||
|
/* 根据底部高度调整 */ |
||||
|
} |
||||
|
.main-wrapper { |
||||
|
height: 100%; |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
} |
||||
|
.logo1 { |
||||
|
/* 居中显示 30%大小 不要拉伸*/ |
||||
|
display: block; |
||||
|
width: 30%; |
||||
|
height: auto; |
||||
|
/* 水平居中 */ |
||||
|
margin: 0 auto; |
||||
|
} |
||||
|
</style> |
Write
Preview
Loading…
Cancel
Save
Reference in new issue