更新UI
This commit is contained in:
121
src/App.vue
121
src/App.vue
@@ -1,15 +1,10 @@
|
||||
<template>
|
||||
<div class="app">
|
||||
<!-- 头部 -->
|
||||
<header class="header">🍳 私厨 AI</header>
|
||||
<header class="header">食刻 AI</header>
|
||||
|
||||
<!-- 聊天区域 -->
|
||||
<main v-if="messages.length" class="chat-box" ref="chatBox">
|
||||
<div v-if="loading" class="loading">
|
||||
<el-icon class="is-loading"><Loading /></el-icon>
|
||||
思考中…
|
||||
</div>
|
||||
|
||||
<main v-if="messages.length" class="chat-box">
|
||||
<div v-for="(item, index) in messages" :key="index" class="message" :class="item.role">
|
||||
<!-- 用户 -->
|
||||
<div v-if="item.role === 'user'" class="bubble">
|
||||
@@ -19,6 +14,11 @@
|
||||
<!-- AI -->
|
||||
<MdPreview v-else :modelValue="item.text" class="md"/>
|
||||
</div>
|
||||
|
||||
<div v-if="loading" class="loading">
|
||||
<el-icon class="is-loading"><Loading /></el-icon>
|
||||
思考中…
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<!-- 输入区 -->
|
||||
@@ -30,7 +30,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, nextTick } from "vue";
|
||||
import { ref } from "vue";
|
||||
import { Loading } from "@element-plus/icons-vue";
|
||||
import { MdPreview } from 'md-editor-v3';
|
||||
import 'md-editor-v3/lib/preview.css';
|
||||
@@ -43,7 +43,6 @@ interface Message {
|
||||
const input = ref("");
|
||||
const messages = ref<Message[]>([]);
|
||||
const loading = ref(false);
|
||||
const chatBox = ref<HTMLElement>();
|
||||
|
||||
const send = async () => {
|
||||
if (!input.value.trim()) return;
|
||||
@@ -52,10 +51,7 @@ const send = async () => {
|
||||
input.value = "";
|
||||
|
||||
messages.value.push({ role: "user", text: userMsg });
|
||||
messages.value.push({ role: "ai", text: "" });
|
||||
|
||||
loading.value = true;
|
||||
await nextTick();
|
||||
|
||||
try {
|
||||
const response = await fetch(
|
||||
@@ -67,6 +63,7 @@ const send = async () => {
|
||||
}
|
||||
);
|
||||
|
||||
messages.value.push({ role: "ai", text: "" });
|
||||
const reader = response.body!.getReader();
|
||||
const decoder = new TextDecoder("utf-8");
|
||||
let aiText = "";
|
||||
@@ -77,8 +74,6 @@ const send = async () => {
|
||||
|
||||
aiText += decoder.decode(value, { stream: true });
|
||||
messages.value[messages.value.length - 1].text = aiText;
|
||||
|
||||
chatBox.value!.scrollTop = chatBox.value!.scrollHeight;
|
||||
}
|
||||
} finally {
|
||||
loading.value = false;
|
||||
@@ -86,67 +81,65 @@ const send = async () => {
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
<style lang="scss" scoped>
|
||||
.app {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
gap: 10px;
|
||||
padding: 5px;
|
||||
|
||||
.header {
|
||||
padding: 14px;
|
||||
text-align: center;
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
}
|
||||
.header {
|
||||
text-align: center;
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.chat-box {
|
||||
background-color: #FBF9F5;
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
padding: 12px;
|
||||
}
|
||||
.chat-box {
|
||||
background-color: #FBF9F5;
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
padding: 10px;
|
||||
|
||||
.message {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
.message {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.user {
|
||||
text-align: right;
|
||||
}
|
||||
.user {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.ai {
|
||||
text-align: left;
|
||||
}
|
||||
.ai {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.bubble {
|
||||
display: inline-block;
|
||||
padding: 10px 14px;
|
||||
border-radius: 14px;
|
||||
max-width: 85%;
|
||||
word-break: break-word;
|
||||
font-size: 15px;
|
||||
line-height: 1.6;
|
||||
background: #409eff;
|
||||
color: #fff;
|
||||
}
|
||||
.bubble {
|
||||
display: inline-block;
|
||||
padding: 5px 10px;
|
||||
border-radius: 14px;
|
||||
max-width: 85%;
|
||||
word-break: break-word;
|
||||
line-height: 1.6;
|
||||
background: #409eff;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.md {
|
||||
background: #f0f2f5;
|
||||
border-radius: 14px;
|
||||
padding: 8px;
|
||||
}
|
||||
.md {
|
||||
background: #f0f2f5;
|
||||
border-radius: 14px;
|
||||
padding: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.input-area {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
padding: 10px;
|
||||
background: #fff;
|
||||
}
|
||||
.input-area {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.loading {
|
||||
text-align: center;
|
||||
color: #909399;
|
||||
font-size: 14px;
|
||||
margin: 8px 0;
|
||||
.loading {
|
||||
text-align: center;
|
||||
color: #909399;
|
||||
font-size: 14px;
|
||||
margin: 8px 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user