DeepSeek + Vue实战开发
利用DeepSeek V3模型、siliconflow大模型一站式云服务平台以及vue3.0实现一个在线人工智能客服对话系统。
因为deepseek官网的api密钥使用起来比较缓慢,所以可以使用第三方的,具体操作请自行查阅资料。
siliconflow官网
SiliconFlow, Accelerate AGI to Benefit Humanity硅基流动致力于打造规模化、标准化、高效能 AI Infra 平台,提供高效能、低成本的多品类 AI 模型服务,助力开发者和企业聚焦产品创新。https://siliconflow.cn/zh-cn/
完整运行代码
运行之前请先修改请求头(headers)中的密钥(token)以及对话模型(model)
请注意:这里的使用的是siliconflow中的token
<template><div class="chatbot-container"><divclass="avatar"@click="toggleChat":style="{transform: isChatOpen? 'scale(0.9) rotate(-8deg)': 'scale(1) rotate(0)',}"></div><divclass="chat-dialog":class="{ active: isChatOpen }"v-click-outside="closeChat"><div class="dialog-header"><h3>在线客服</h3><div class="close-btn" @click="toggleChat">×</div></div><div class="dialog-body"><div class="message-container" ref="scrollbarRef"><div v-for="(message, index) in messagesWithTimestamps" :key="index"><!-- 时间戳 --><div class="timestamp" v-if="message.showTime">{{ formatSendTime(message.timestamp) }}</div><!-- 消息列表 --><div:class="['message-bubble',message.type === 'user' ? 'user-message' : 'bot-message',]">{{ message.content }}</div></div></div><div class="input-area"><inputv-model="inputMessage"type="text"class="message-input"placeholder="输入消息..."@keypress.enter="sendMessage"/><button class="send-button" @click="sendMessage">发送</button></div></div></div></div>
</template><script setup>
import { nextTick, ref, computed } from "vue";const isChatOpen = ref(false);
const inputMessage = ref("");
const messages = ref([]);//创建新的对话数组,加上属性showTime
const messagesWithTimestamps = computed(() => {return messages.value.map((item, index) => ({...item,showTime: index == 0 || shouldShowTime(index),}));
});
//计算两次会话时间是否超过3分钟方法
const shouldShowTime = (index) => {const current = new Date(messages.value[index - 1].timestamp);const next = new Date(messages.value[index].timestamp);const diff = next ? next - current : 0;return diff > 3 * 60 * 1000; // 如果间隔超过3分钟返回true
};
// 切换聊天窗口
const toggleChat = () => {isChatOpen.value = !isChatOpen.value;if (isChatOpen.value && messages.value.length === 0) {messages.value.push({type: "bot",content: "您好!我是智能客服小助手,很高兴为您服务。请问有什么可以帮您?",timestamp: new Date(), //时间戳});}
};
// 关闭聊天窗口
const closeChat = () => {isChatOpen.value = false;
};
// 发送消息
const sendMessage = () => {const message = inputMessage.value.trim();if (message) {messages.value.push({type: "user",content: message,timestamp: new Date(), //时间戳});inputMessage.value = "";const messageContainer = document.querySelector(".message-container");try {setTimeout(async () => {messages.value.push({type: "bot",content: "正在思考中...",timestamp: new Date(), //时间戳});nextTick(() => {// 滚动到底部messageContainer.scrollTop = messageContainer.scrollHeight;});// 发送请求const response = await fetch("https://api.siliconflow.cn/v1/chat/completions",{method: "POST",headers: {Authorization:"Bearer sk-bnlbdzgfqyqokwboisvheyohbmbhnpzpbyhsuvkpidkncpij","Content-Type": "application/json",},body: JSON.stringify({frequency_penalty: 0,max_tokens: 1024,model: "deepseek-ai/DeepSeek-V3",temperature: 0,top_k: 49,top_p: 0.7,messages: [{role: "user",content: message,},],}),});const data = await response.json();// 过滤 "正在思考中..." 消息messages.value = messages.value.filter((item) => {return item.content.indexOf("正在思考中") === -1;});if (response.choices) {// 处理响应数据messages.value.push({type: "bot",content: data.choices[0].message.content,timestamp: new Date(), //时间戳});} else {// 处理错误情况messages.value.push({type: "bot",content: "抱歉,我现在无法回答您的问题,请稍后再试。",timestamp: new Date(), //时间戳});}nextTick(() => {// 滚动到底部messageContainer.scrollTop = messageContainer.scrollHeight;});}, 1000);// 滚动到底部} catch (error) {console.error("Error:", error);}}
};const formatTime = (date) => {// 格式化时间为“时:分”const hours = date.getHours().toString().padStart(2, "0");const minutes = date.getMinutes().toString().padStart(2, "0");return hours + ":" + minutes;
};
const getWeekday = (date) => {// 获取星期几的中文表示const weekdays = ["星期天","星期一","星期二","星期三","星期四","星期五","星期六",];return weekdays[date.getDay()];
};const formatSendTime = (sendTime) => {const now = new Date();const sendDate = new Date(sendTime);// 计算时间差(以毫秒为单位)const timeDiff = now - sendDate;const startOfToday = new Date(now.getFullYear(),now.getMonth(),now.getDate());const startOfTargetDate = new Date(sendDate.getFullYear(),sendDate.getMonth(),sendDate.getDate());// 一天内的毫秒数const oneDay = 24 * 60 * 60 * 1000;// 如果发送时间在当前时间之前if (timeDiff < 0) {return "Invalid time"; // 或者其他错误处理}// 发生在同一天if (startOfToday.getTime() === startOfTargetDate.getTime()) {return formatTime(sendDate);}// 如果发送时间在一天内if (timeDiff < oneDay) {return "昨天 " + formatTime(sendDate);}// 如果发送时间在二天至七天内if (timeDiff < 7 * oneDay) {const weekday = getWeekday(sendDate);return weekday + " " + formatTime(sendDate);}// 如果发送时间超过七天return (sendDate.toLocaleDateString("zh-CN", {year: "numeric",month: "2-digit",day: "2-digit",}) +" " +formatTime(sendDate));
};</script><style>
/* 原有样式保持不变 */
:root {--primary-color: #4a90e2;--hover-color: #357abd;
}body {display: flex;justify-content: center;align-items: center;min-height: 100vh;background: #f0f2f5;margin: 0;font-family: "Microsoft YaHei", sans-serif;
}.chatbot-container {position: fixed;bottom: 30px;right: 30px;z-index: 1000;
}/* 新增头像样式 */
.avatar {width: 60px;height: 60px;border-radius: 50%;cursor: pointer;box-shadow: 0 8px 20px rgba(0, 0, 0, 0.2);box-shadow: 0 8px 20px rgba(74, 144, 226, 0.3);transition: all 0.3s ease;position: relative;overflow: hidden;background-color: #357abd;
}.avatar:hover {transform: scale(1.1) rotate(8deg);box-shadow: 0 12px 25px rgba(74, 144, 226, 0.4);
}.avatar::before {content: "";position: absolute;top: 50%;left: 50%;transform: translate(-50%, -50%);width: 30px;height: 30px;background: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="white"><path d="M20 2H4c-1.1 0-2 .9-2 2v18l4-4h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-3 12H7v-2h10v2zm0-3H7v-2h10v2zm0-3H7V6h10v2z"/></svg>')no-repeat center;
}/* 聊天对话框 */
.chat-dialog {position: absolute;bottom: 80px;right: 0;width: 320px;background: white;border-radius: 12px;box-shadow: 0 8px 30px rgba(0, 0, 0, 0.1);transform: scale(0);transform-origin: bottom right;transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}.chat-dialog.active {transform: scale(1);
}.dialog-header {padding: 16px;background: var(--primary-color);border-radius: 12px 12px 0 0;color: white;display: flex;align-items: center;
}.dialog-header h3 {margin: 0;font-size: 16px;font-weight: 500;
}.close-btn {margin-left: auto;cursor: pointer;padding: 0px 4px;border-radius: 50%;background: rgba(0, 0, 0, 0.1);
}.dialog-body {padding: 16px;height: 300px;overflow-y: auto;display: flex;flex-direction: column;
}.timestamp {display: flex;align-items: center;justify-content: center;font-size: 10px;margin-bottom: 3px;
}.message-container {flex: 1;overflow-y: auto;margin-bottom: 16px;display: flex;flex-direction: column;
}.input-area {display: flex;gap: 8px;padding-top: 12px;border-top: 1px solid #eee;
}.message-input {flex: 1;padding: 8px 12px;border: 1px solid #ddd;border-radius: 20px;outline: none;transition: border-color 0.3s;
}.message-input:focus {border-color: var(--primary-color);
}.send-button {padding: 8px 16px;background: var(--primary-color);color: white;border: none;border-radius: 20px;cursor: pointer;font-size: 14px;
}.send-button:hover {background: var(--hover-color);
}.message-bubble {padding: 8px 12px;margin-bottom: 8px;border-radius: 4px;animation: fadeIn 0.3s ease;max-width: 80%;display: inline-block;word-break: break-all;box-shadow: 0px 0px 12px rgba(0, 0, 0, 0.12);border: 1px solid #e4e7ed;
}.user-message {background: var(--primary-color);color: #ffffff;float: right;
}.bot-message {background: #ffffff;color: #303133;
}@keyframes fadeIn {from {opacity: 0;transform: translateY(10px);}to {opacity: 1;transform: translateY(0);}
}/* 响应式设计 */
@media (max-width: 480px) {.chatbot-container {bottom: 20px;right: 20px;}.chat-dialog {width: 90vw;bottom: 70px;}.avatar {width: 50px;height: 50px;}
}
</style>
效果在线预览
ps:文本对话请求可能会有连接超时的问题!