在现代网页开发中,集成智能助手或聊天机器人已经成为提升用户体验的重要手段之一。本文将详细介绍如何通过HTML、CSS和JavaScript代码,将DeepSeek模态框集成到你的网页中,并实现与DeepSeek API的交互。
1. HTML结构
首先,我们来看一下HTML部分。HTML代码定义了网页的基本结构,包括一个触发模态框的图标和模态框本身。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Integrate DeepSeek Modal</title>
<!-- CSS样式部分 -->
<style>
/* 样式代码将在下文详细解释 */
</style>
</head>
<body>
<!-- 触发模态框的小图标 -->
<div class="message-board-icon" onclick="toggleModal()"></div>
<!-- 模态框 -->
<div id="myModal" class="modal">
<!-- 模态框内容 -->
<div class="modal-content">
<span class="close" onclick="toggleModal()">×</span>
<h2>DeepSeek Assistant</h2>
<form id="queryForm">
<input
type="text"
name="question"
placeholder="Ask me anything..."
required
/>
<button type="submit">Submit</button>
</form>
<div id="response"></div>
</div>
</div>
<!-- JavaScript代码部分 -->
<script>
// JavaScript代码将在下文详细解释
</script>
</body>
</html>
-
触发图标:
<div class="message-board-icon" onclick="toggleModal()"></div>
是一个固定在页面右下角的圆形图标,点击它会触发模态框的显示和隐藏。 -
模态框:
<div id="myModal" class="modal">
是一个固定在页面右侧的模态框,默认是隐藏的。模态框内包含一个表单,用户可以在表单中输入问题并提交。
2. CSS样式
CSS部分定义了网页的样式,包括背景、图标、模态框及其内容的样式。
body {
width: 100vw;
height: 100vh;
background-color: rgba(0, 0, 0, 0.4);
}
/* 图标样式 */
.message-board-icon {
width: 100px;
height: 100px;
background: url("/assets/pointer.png") center/cover;
position: fixed;
bottom: 20px;
right: 20px;
border-radius: 50%;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
cursor: pointer;
z-index: 1000;
}
/* 模态框样式 */
.modal {
display: none; /* 默认隐藏 */
position: fixed; /* 根据浏览器定位 */
z-index: 1; /* 放在顶部 */
right: 0;
top: 0;
width: 30%; /* 全宽 */
height: 100%; /* 全高 */
overflow: auto; /* 允许滚动 */
background-color: rgba(255, 255, 255); /* 背景色 */
}
.modal-content {
background-color: #fefefe;
padding: 20px;
margin: 2% auto;
border: 1px solid #888;
width: 86%;
}
.close {
color: #aaa;
float: right;
font-size: 28px;
font-weight: bold;
}
.close:hover,
.close:focus {
color: black;
text-decoration: none;
cursor: pointer;
}
-
背景:
body
元素的背景设置为半透明的黑色,以突出模态框。 -
图标:
.message-board-icon
类定义了图标的样式,包括大小、位置、圆角、阴影等。 -
模态框:
.modal
类定义了模态框的样式,包括位置、大小、背景色等。默认情况下,模态框是隐藏的(display: none;
)。 -
模态框内容:
.modal-content
类定义了模态框内容的样式,包括内边距、背景色、边框等。 -
关闭按钮:
.close
类定义了关闭按钮的样式,包括颜色、大小、悬停效果等。
3. JavaScript功能
JavaScript部分负责处理模态框的显示与隐藏、表单提交以及与DeepSeek API的交互。
const apiKey = "sk-xxxx"; // 替换为你的DeepSeek API密钥
const responseElement = document.getElementById("response");
// 切换模态框显示状态
function toggleModal() {
var modal = document.getElementById("myModal");
modal.style.display =
modal.style.display === "block" ? "none" : "block";
}
// 处理表单提交事件
document
.getElementById("queryForm")
.addEventListener("submit", function (event) {
event.preventDefault();
var question = document.getElementsByName("question")[0].value;
fetchDeepSeekResponse(question).then(function (responseText) {
document.getElementById("response").innerText = responseText;
});
});
// 向DeepSeek API发送请求
async function fetchDeepSeekResponse(question) {
let params = {
model: "deepseek-r1:14b",
messages: [],
};
params.messages.push({ role: "user", content: question });
const apiUrl = "xxx"; // 替换为实际的API URL
const response = await fetch(apiUrl, {
method: "POST",
headers: {
Authorization: `Bearer ${apiKey}`,
"Content-Type": "application/json",
},
body: JSON.stringify(params),
});
console.log("response", response);
processJsonStreamForUI(response.body, responseElement);
}
function appendToElement(element, text) {
element.textContent += text;
}
async function processJsonStreamForUI(stream, targetElement) {
const reader = stream.getReader();
let buffer = ""; // 用于存储未解析的 JSON 数据
try {
while (true) {
const { done, value } = await reader.read();
if (done) break;
const chunk = new TextDecoder().decode(value);
buffer += chunk;
while (buffer) {
const jsonStart = buffer.indexOf("{");
if (jsonStart === -1) break;
let jsonEnd = findMatchingBracket(buffer, jsonStart);
if (jsonEnd === -1) break;
const jsonString = buffer.substring(jsonStart, jsonEnd + 1);
const jsonData = JSON.parse(jsonString);
if (jsonData.message && jsonData.message.content) {
const decodedContent = decodeURIComponent(
jsonData.message.content
);
appendToElement(targetElement, decodedContent.replace(/\u003cthink\u003e/, "<div>").replace(/\u003c\/think\u003e/, "</div>")); // 实时更新 UI
}
if (jsonData.done) {
console.log("Stream processing completed.");
break;
}
buffer = buffer.substring(jsonEnd + 1);
}
}
} catch (error) {
console.error("读取流时发生错误:", error);
} finally {
await reader.releaseLock();
}
}
// 辅助函数:找到与 "{" 匹配的 "}" 的位置
function findMatchingBracket(str, start) {
let bracketCount = 0;
for (let i = start; i < str.length; i++) {
if (str[i] === "{") {
bracketCount++;
} else if (str[i] === "}") {
bracketCount--;
if (bracketCount === 0) {
return i; // 找到匹配的 "}"
}
}
}
return -1; // 没有找到匹配的 "}"
}
-
切换模态框:
toggleModal()
函数用于切换模态框的显示和隐藏状态。 -
表单提交:当用户提交表单时,
fetchDeepSeekResponse(question)
函数会向DeepSeek API发送请求,并将返回的响应显示在页面上。 -
处理API响应:
processJsonStreamForUI()
函数用于处理从API返回的JSON流数据,并实时更新页面内容。
通过以上代码,你可以轻松地将DeepSeek模态框集成到你的网页中,并实现与DeepSeek API的交互。这种集成不仅可以提升用户体验,还能为用户提供智能化的问答服务。你可以根据需要进一步定制样式和功能,以满足特定的业务需求。
完整代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Integrate DeepSeek Modal</title>
<style>
body {
width: 100vw;
height: 100vh;
background-color: rgba(0, 0, 0, 0.4);
}
/* 图标样式 */
.message-board-icon {
width: 100px;
height: 100px;
background: url("/assets/pointer.png") center/cover; /* 替换为你的图标的路径 */
position: fixed;
bottom: 20px;
right: 20px;
border-radius: 50%;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
cursor: pointer;
z-index: 1000;
}
/* 模态框样式 */
.modal {
display: none; /* 默认隐藏 */
position: fixed; /* 根据浏览器定位 */
z-index: 1; /* 放在顶部 */
right: 0;
top: 0;
width: 30%; /* 全宽 */
height: 100%; /* 全高 */
overflow: auto; /* 允许滚动 */
background-color: rgba(255, 255, 255); /* 背景色 */
}
.modal-content {
background-color: #fefefe;
padding: 20px;
margin: 2% auto;
border: 1px solid #888;
width: 86%;
}
.close {
color: #aaa;
float: right;
font-size: 28px;
font-weight: bold;
}
.close:hover,
.close:focus {
color: black;
text-decoration: none;
cursor: pointer;
}
</style>
</head>
<body>
<!-- 触发模态框的小图标 -->
<div class="message-board-icon" onclick="toggleModal()"></div>
<!-- 模态框 -->
<div id="myModal" class="modal">
<!-- 模态框内容 -->
<div class="modal-content">
<span class="close" onclick="toggleModal()">×</span>
<h2>DeepSeek Assistant</h2>
<form id="queryForm">
<input
type="text"
name="question"
placeholder="Ask me anything..."
required
/>
<button type="submit">Submit</button>
</form>
<div id="response"></div>
</div>
</div>
<script>
const apiKey = "sk-xxxx"; // 替换为你的DeepSeek API密钥
const responseElement = document.getElementById("response");
// 切换模态框显示状态
function toggleModal() {
var modal = document.getElementById("myModal");
modal.style.display =
modal.style.display === "block" ? "none" : "block";
}
// 处理表单提交事件
document
.getElementById("queryForm")
.addEventListener("submit", function (event) {
event.preventDefault();
var question = document.getElementsByName("question")[0].value;
fetchDeepSeekResponse(question).then(function (responseText) {
document.getElementById("response").innerText = responseText;
});
});
// 向DeepSeek API发送请求
async function fetchDeepSeekResponse(question) {
let params = {
model: "deepseek-r1:14b",
messages: [],
};
params.messages.push({ role: "user", content: question });
const apiUrl = "xxx"; // 替换为实际的API URL
const response = await fetch(apiUrl, {
method: "POST",
headers: {
Authorization: `Bearer ${apiKey}`,
"Content-Type": "application/json",
},
body: JSON.stringify(params),
});
console.log("response", response);
processJsonStreamForUI(response.body, responseElement);
}
function appendToElement(element, text) {
element.textContent += text;
}
async function processJsonStreamForUI(stream, targetElement) {
const reader = stream.getReader();
let buffer = ""; // 用于存储未解析的 JSON 数据
try {
while (true) {
const { done, value } = await reader.read();
if (done) break;
const chunk = new TextDecoder().decode(value);
buffer += chunk;
while (buffer) {
const jsonStart = buffer.indexOf("{");
if (jsonStart === -1) break;
let jsonEnd = findMatchingBracket(buffer, jsonStart);
if (jsonEnd === -1) break;
const jsonString = buffer.substring(jsonStart, jsonEnd + 1);
const jsonData = JSON.parse(jsonString);
if (jsonData.message && jsonData.message.content) {
const decodedContent = decodeURIComponent(
jsonData.message.content
);
appendToElement(targetElement, decodedContent.replace(/\u003cthink\u003e/, "<div>").replace(/\u003c\/think\u003e/, "</div>")); // 实时更新 UI
}
if (jsonData.done) {
console.log("Stream processing completed.");
break;
}
buffer = buffer.substring(jsonEnd + 1);
}
}
} catch (error) {
console.error("读取流时发生错误:", error);
} finally {
await reader.releaseLock();
}
}
// 辅助函数:找到与 "{" 匹配的 "}" 的位置
function findMatchingBracket(str, start) {
let bracketCount = 0;
for (let i = start; i < str.length; i++) {
if (str[i] === "{") {
bracketCount++;
} else if (str[i] === "}") {
bracketCount--;
if (bracketCount === 0) {
return i; // 找到匹配的 "}"
}
}
}
return -1; // 没有找到匹配的 "}"
}
</script>
</body>
</html>