提交 22c306b2 编写于 作者: C c72121122

Sun Mar 30 11:58:00 CST 2025 inscode

上级 aa50c4cb
...@@ -11,4 +11,4 @@ XDG_CONFIG_HOME = "/root/.config" ...@@ -11,4 +11,4 @@ XDG_CONFIG_HOME = "/root/.config"
npm_config_prefix = "/root/${PROJECT_DIR}/.config/npm/node_global" npm_config_prefix = "/root/${PROJECT_DIR}/.config/npm/node_global"
[debugger] [debugger]
program = "main.js" program = "main.js"
\ No newline at end of file
<template>
<div class="container">
<div class="dialog">
<template v-for="(message, index) in chatMessages" :key="index">
<div class="dialog-item" :class="{ 'dialog-item-me': message.sender === '你', 'dialog-item-ai': message.sender === 'AI' }">
<div class="dialog-item-main" v-html="renderMarkdown(message.text)"></div>
</div>
</template>
</div>
<div class="question">
<textarea
v-model="userInput"
placeholder="输入你的消息"
class="input-field"
@keydown.enter="handleKeyDown"
></textarea>
<div class="powered-by">
Powered By liyuzhu
</div>
</div>
</div>
</template>
<script setup> <script setup>
import HelloWorld from './components/HelloWorld.vue' import { ref } from 'vue';
import TheWelcome from './components/TheWelcome.vue' import axios from 'axios';
</script> import MarkdownIt from 'markdown-it';
import { fetchEventSource } from 'fetch-event-source';
<template> const userInput = ref('');
<header> const chatMessages = ref([]);
<img alt="Vue logo" class="logo" src="./assets/logo.svg" width="125" height="125" /> const loading = ref(false);
const md = new MarkdownIt();
<div class="wrapper"> const sendMessage = async () => {
<HelloWorld msg="You did it!" /> if (loading.value || userInput.value.trim() === '') return;
</div> loading.value = true;
</header>
<main> const userMessage = { sender: '', text: userInput.value };
<TheWelcome /> chatMessages.value.push(userMessage);
</main> userInput.value = '';
</template>
let aiResponse = '';
let aiMessageIndex = chatMessages.value.length;
chatMessages.value.push({ sender: 'AI', text: 'AI 思考中...' });
try {
await fetchEventSource('http://localhost:11434/api/generate', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
model: 'gemma3:12b',
prompt: userMessage.text
}),
onmessage: (event) => {
if (event.data === '[DONE]') return;
try {
const data = JSON.parse(event.data);
aiResponse += data.response;
chatMessages.value[aiMessageIndex].text = aiResponse;
} catch (error) {
console.error('解析响应数据出错:', error);
}
},
onclose: () => {
loading.value = false;
},
onerror: (error) => {
console.error('请求出错:', error);
let errorText = '无法连接到模型,请检查服务是否运行。';
if (error.response) {
errorText += ` 服务器响应错误: ${JSON.stringify(error.response.data)}`;
} else if (error.request) {
errorText += ' 没有收到服务器响应。';
} else {
errorText += ` 错误信息: ${error.message}`;
}
const errorMessage = { sender: '错误', text: errorText };
chatMessages.value.push(errorMessage);
loading.value = false;
}
});
} catch (error) {
console.error('请求出错:', error);
let errorText = '无法连接到模型,请检查服务是否运行。';
if (error.response) {
errorText += ` 服务器响应错误: ${JSON.stringify(error.response.data)}`;
} else if (error.request) {
errorText += ' 没有收到服务器响应。';
} else {
errorText += ` 错误信息: ${error.message}`;
}
const errorMessage = { sender: '错误', text: errorText };
chatMessages.value.push(errorMessage);
loading.value = false;
}
};
const handleNewChat = () => {
chatMessages.value = [];
};
const renderMarkdown = (text) => {
return md.render(text);
};
const handleKeyDown = (event) => {
if (event.shiftKey && event.key === 'Enter') {
// Shift + Enter 实现换行
userInput.value += '\n';
event.preventDefault();
} else if (event.key === 'Enter') {
// Enter 发送消息
sendMessage();
event.preventDefault();
}
};
</script>
<style scoped> <style scoped>
header { html, body {
line-height: 1.5; height: 80%;
margin: 0;
padding: 0;
} }
.logo { .container {
display: block; display: flex;
margin: 0 auto 2rem; flex-direction: column;
height: 80vh;
padding: 16px 0;
box-sizing: border-box;
background-color: #f9f9f9;
margin: 0 auto;
max-width: 100%;
/* 设置最小宽度 */
min-width: 1300px;
border-radius: 20px;
} }
@media (min-width: 1024px) { .dialog {
header { flex: 1;
display: flex; overflow-y: auto;
place-items: center; padding: 16px;
padding-right: calc(var(--section-gap) / 2); border: 1px solid #e0e0e0;
} border-radius: 8px;
background-color: #fff;
margin-bottom: 16px;
margin-left: 16px;
margin-right: 16px;
}
.logo { .dialog-item {
margin: 0 2rem 0 0; display: flex;
} margin-bottom: 10px;
}
header .wrapper { .dialog-item-main {
display: flex; max-width: 80%;
place-items: flex-start; padding: 12px;
flex-wrap: wrap; word-wrap: break-word;
} border-radius: 12px;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
position: relative;
}
.dialog-item-me {
justify-content: flex-end;
}
.dialog-item-me .dialog-item-main {
background-color: #dcf8c6;
}
.dialog-item-ai .dialog-item-main {
background-color: #ebebeb;
}
.question {
display: flex;
flex-direction: column;
margin-left: 16px;
margin-right: 16px;
}
.input-field {
padding: 12px;
border: 1px solid #e0e0e0;
border-radius: 8px;
margin-bottom: 16px;
outline: none;
font-size: 16px;
min-height: 80px;
resize: vertical;
}
.button-container {
display: flex;
justify-content: space-between;
margin-bottom: 16px;
}
.button {
padding: 12px 24px;
border: none;
border-radius: 8px;
cursor: pointer;
font-size: 16px;
transition: background-color 0.3s ease;
}
.send-button {
background-color: #007bff;
color: #fff;
}
.send-button:hover {
background-color: #0056b3;
}
.new-chat-button {
background-color: #6c757d;
color: #fff;
}
.new-chat-button:hover {
background-color: #545b62;
}
.powered-by {
text-align: center;
font-size: 14px;
color: #666;
}
.logo {
width: 16px;
height: 16px;
vertical-align: middle;
position: relative;
top: -1px;
} }
</style> </style>
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册