This commit is contained in:
2026-05-27 22:33:41 +08:00
parent fa8787c77a
commit 41ef49a04f
7 changed files with 68 additions and 91 deletions

View File

@@ -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>