如何集成DeepSeek模态框到你的网页中

在现代网页开发中,集成智能助手或聊天机器人已经成为提升用户体验的重要手段之一。本文将详细介绍如何通过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()">&times;</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()">&times;</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>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值