当前位置: 首页 > news >正文

用 Vue + DeepSeek 打造一个智能聊天网站(完整前后端项目开源)

🌟 一、项目简介

最近我利用业余时间开发了一个 AI 聊天网站
前端使用 Vue 3 + Vite,后端使用 Express 构建 API 代理,
通过 DeepSeek 提供的接口实现了一个可以像 ChatGPT 一样流畅交流的网页端聊天系统。

项目目标很简单:

  • 提供一个 前端可视化聊天界面

  • 实现 安全调用 DeepSeek API(后端隐藏密钥)

  • 支持 连续对话、上下文记忆、流式输出

  • 让任何人都能在本地快速搭建自己的智能聊天网站!

🧩 二、项目结构

项目包含前后端两个部分:

ai-chat-vue/ # 前端 (Vite + Vue 3)
├─ index.html
├─ package.json
├─ vite.config.js
├─ src/
│ ├─ main.js
│ ├─ App.vue
│ ├─ api/
│ │ └─ ai.js
│ ├─ components/
│ │ └─ ChatBox.vue
│ └─ styles.css
└─ .gitignoreai-server/ # 后端 (Node + Express)
├─ server.js
├─ package.json
└─ .env

🖥️ 三、前端部分(Vue 3 + Vite)

前端采用 Vue 3 + Composition API 构建,
界面简洁、响应式良好,并支持滚动对话、输入区和加载动画。

主要功能组件

  • ChatBox.vue:显示消息记录、输入框和发送按钮

  • api.js:封装与后端交互的接口(调用 /api/chat

  • 流式输出:利用 ReadableStream 实现逐字输出效果

✨ 样例界面

  • 左侧是聊天窗口

  • 右下角输入框输入内容按回车即可发送

  • AI 响应实时滚动输出

src/api/ai.js

import axios from 'axios'
const API_BASE = import.meta.env.VITE_API_BASE || 'http://localhost:7666'
export async function getAIReply(question) {
const res = await axios.post(`${API_BASE}/api/chat`, { question })
if (res.data && res.data.reply) return res.data.reply
throw new Error('无效的后端响应')
}

src/components/ChatBox.vue

<template>
<div>
<div class="messages" ref="msgBox">
<div v-for="(m, i) in messages" :key="i" class="message" :class="m.role === 'user' ? 'msg-user' : 'msg-ai'">
<div><strong>{{ m.role === 'user' ? '你' : 'AI' }}:</strong></div>
<div>{{ m.content }}</div>
</div>
</div><textarea v-model="input" @keydown.enter.prevent="sendIfEnter($event)" placeholder="输入你想问的问题,按 Enter 发送(Shift+Enter 换行)"></textarea>
<div style="display:flex;gap:8px;justify-content:flex-end;">
<button @click="send">发送</button>
</div>
</div>
</template><script setup>
import { ref, nextTick } from 'vue'
import { getAIReply } from '../api/ai'const input = ref('')
const messages = ref([])
const msgBox = ref(null)function scrollToBottom() {
nextTick(() => {
if (msgBox.value) {
msgBox.value.scrollTop = msgBox.value.scrollHeight
}
})
}function sendIfEnter(e) {
if (!e.shiftKey) send()
}async function send() {
const text = input.value.trim()
if (!text) return
messages.value.push({ role: 'user', content: text })
input.value = ''
scrollToBottom()// 显示一个占位的 AI 消息(可替换为流式)
messages.value.push({ role: 'ai', content: '正在生成回复...' })
scrollToBottom()try {
const reply = await getAIReply(text)
// 把最后一条 ai 占位替换
const lastIdx = messages.value.map(m => m.role).lastIndexOf('ai')
if (lastIdx >= 0) messages.value[lastIdx].content = reply
} catch (err) {
const lastIdx = messages.value.map(m => m.role).lastIndexOf('ai')
if (lastIdx >= 0) messages.value[lastIdx].content = '请求失败:' + (err.message || '未知错误')
}
scrollToBottom()
}
</script><style scoped>
.messages { margin-bottom: 8px }
.msg-user { color: #0b72ff }
.msg-ai { color: #111 }
textarea { font-family: inherit }
button { background: #0b72ff; color: white }
</style>

src/App.vue

<template>
<div>
<h1>AI 聊天</h1>
<div class="chat-wrap">
<ChatBox />
</div>
</div>
</template><script setup>
import ChatBox from './components/ChatBox.vue'
</script><style scoped>
h1 { margin-bottom: 12px }
</style>

 src/main.js

import { createApp } from 'vue'
import App from './App.vue'
import './styles.css'createApp(App).mount('#app')

 src/styles.css

body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial; margin: 0; padding: 20px; background: #f7f9fc; }
#app { max-width: 800px; margin: 0 auto; }
h1 { text-align: center; }
.chat-wrap { background: white; border-radius: 8px; padding: 16px; box-shadow: 0 4px 14px rgba(0,0,0,0.08); }
.messages { height: 420px; overflow-y: auto; padding: 8px; border: 1px solid #eee; border-radius: 6px; }
.message { margin: 8px 0; }
.msg-user { text-align: right; }
.msg-ai { text-align: left; }
textarea { width: 100%; min-height: 80px; margin-top: 8px; padding: 8px; }
button { margin-top: 8px; padding: 8px 14px; border: none; border-radius: 6px; cursor: pointer; }

index.html

<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>AI 聊天 (Vue + OpenAI)</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.js"></script>
</body>
</html>

package.json


{"type": "module","name":"ai-chat-vue","version":"1.0.0","scripts":{"dev":"vite","build":"vite build","preview":"vite preview"},"dependencies":{"axios":"^1.5.0","vue":"^3.3.0"},"devDependencies":{"@vitejs/plugin-vue":"^6.0.1","vite":"^5.0.0"}}

vite.config.mjs

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'export default defineConfig({plugins: [vue()],server: {host: '0.0.0.0',port: 5173}
})


⚙️ 四、后端部分(Express + DeepSeek Proxy)

为了安全起见,我们不在前端直接暴露 DeepSeek 的 API Key,
而是通过 Node.js 后端中转请求。

.env

PORT=7666
DEEPSEEK_API_KEY=这里改为你的deepseek api

server.js

import express from 'express'
import cors from 'cors'
import axios from 'axios'
import dotenv from 'dotenv'dotenv.config()
const app = express()
app.use(cors())
app.use(express.json())const PORT = process.env.PORT || 7666
const DEEPSEEK_KEY = process.env.DEEPSEEK_API_KEY
if (!DEEPSEEK_KEY) console.warn('⚠️ DEEPSEEK_API_KEY 未设置,将无法调用 DeepSeek API')app.post('/api/chat', async (req, res) => {
const { question } = req.body
if (!question) return res.status(400).json({ error: 'missing question' })try {
const resp = await axios.post('https://api.deepseek.com/v1/chat/completions',{model: 'deepseek-chat', // 也可以换成 deepseek-reasoner
messages: [
{ role: 'system', content: '你是一个友好的助理。用中文回复。' },
{ role: 'user', content: question }
],
max_tokens: 800
},
{
headers: {
'Authorization': `Bearer ${DEEPSEEK_KEY}`,
'Content-Type': 'application/json'
}
}
)const reply = resp.data.choices?.[0]?.message?.content || ''
res.json({ reply })
} catch (err) {
console.error(err?.response?.data || err.message)
res.status(500).json({ reply: '调用出错,请检查后端日志。' })
}
})app.listen(PORT, () => console.log(`✅ Server listening on http://localhost:${PORT}`))

package.json


{"name": "ai-server","version": "1.0.0","type": "module","scripts": {"start": "node server.js"},"dependencies": {"axios": "^1.5.0","cors": "^2.8.5","dotenv": "^16.0.0","express": "^4.18.2"}
}

🔐 五、安全设计

  1. 后端代理调用 DeepSeek,防止 API Key 暴露。

  2. CORS 控制:仅允许特定前端域名访问。

  3. 环境变量配置:所有密钥都放在 .env 文件中,项目安全性更高。


🌈 六、项目运行效果

当用户输入问题时,例如:

“请帮我写一段介绍 Vue 的开场白”

系统会流式输出 DeepSeek 的回答,
在几秒钟内完成自然语言回复。

🧠 七、技术要点与难点

功能技术实现
前端聊天界面Vue 3 + Tailwind CSS
实时响应ReadableStream 流式读取
API 代理Node.js + Express
安全性.env 隐藏密钥,CORS 限制
模型调用DeepSeek Chat Completion API

🚀 八、部署方式

1️⃣ 本地运行

# 前端cd ai-chat-vuenpm installnpm run dev# 后端 (另开终端)cd ai-servernpm install# 填写 .env 中的 DEEPSEEK_API_KEYnode server.js

访问前端页面(默认 http://localhost:5173)开始聊天。

2️⃣ 部署到线上

  • 后端:Render / Vercel / Railway / 自建服务器

  • 前端:Netlify / Vercel / GitHub Pages

💬 九、项目亮点总结

前后端完全开源
DeepSeek API 集成示例
流式聊天效果
安全 API Key 管理机制
适合二次开发、博客展示或课程作业

🔗 十、项目仓库地址

GitHub 地址:
👉 13536309143/Build-an-intelligent-chat-website-with-Vue-DeepSeek


❤️ 十一、结语

这是一个轻量、易扩展的 AI 聊天网站项目,
既能展示前后端交互能力,也能体验 DeepSeek 的强大对话性能。

如果你正在学习:

  • Vue 3 前端开发

  • Node.js 后端接口代理

  • AI 聊天网站架构

那么这个项目非常适合作为你的入门实战!

http://www.dtcms.com/a/581135.html

相关文章:

  • 昌吉市建设局网站游戏工作室招聘信息
  • 基于MATLAB/Simulink的500kW三相光伏逆变器仿真
  • 大数据python招聘数据分析预测系统 招聘数据平台 +爬虫+可视化 +django框架+vue框架 大数据技术✅
  • 教育培训机构如何搭建自己的在线教育小程序?
  • Vue3+vant4+Webpack+yarn项目创建+vant4使用注意明细
  • 中山网站建设网站网站开发结构图
  • NumPy 简介与安装
  • AWS CloudFront 可观测最佳实践
  • 化学结构式乱码?InDraw与ChemDraw/Word/WPS兼容性完整指南
  • npm run 的工作原理和工作流程
  • 本地搭建Flinkcdc-mysql-kafka-flink-Doris实时数据集成
  • 极简风网站网站制作周期
  • 【Hadoop】hadoop3.3.1完全分布式配置
  • 如何安装 PDF Reader Pro for Mac v3.2.1.0?超简单DMG安装步骤(附安装包)
  • XML与CSS:构建现代网页的关键技术
  • 无锡品牌学会网站建设wordpress账号注册页面
  • 一次由 PageHelper 分页污染引发的 Bug 排查实录
  • 记录一个IDEA的神奇bug
  • Spark-3.5.7文档3 - Spark SQL、DataFrame 和 Dataset 指南
  • 无需 iTunes,将 iPhone 语音备忘录传输到电脑
  • 三个好思路:SQL并行化处理、混淆矩阵和特征交叉
  • 5 种无需 iTunes 将 iPad 照片传输到电脑的方法
  • 网站制作网站设计自助建站网站程序源码
  • Jenkins 定时触发(cron)使用说明
  • Kubernetes 架构
  • 自己做有趣的网站娱乐网站名字
  • 黑马JAVAWeb-09 文件上传-文件存储到服务器本地磁盘-文件存储在阿里云
  • 医疗小程序04添加就诊人
  • uboot下查看分区
  • 微信小程序camera相机帧转图片base64