chat.html 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. <!DOCTYPE html>
  2. <html lang="zh">
  3. <head>
  4. <meta charset="UTF-8"/>
  5. <title>客服聊天测试</title>
  6. <style>
  7. body {
  8. font-family: sans-serif;
  9. }
  10. #messages {
  11. border: 1px solid #ccc;
  12. height: 300px;
  13. overflow-y: auto;
  14. padding: 8px;
  15. }
  16. #typingIndicator {
  17. color: gray;
  18. font-style: italic;
  19. margin-top: 5px;
  20. }
  21. </style>
  22. </head>
  23. <body>
  24. <h2>客服聊天测试</h2>
  25. <div id="messages"></div>
  26. <div id="typingIndicator"></div>
  27. <input type="text" id="msgInput" placeholder="输入消息"/>
  28. <button onclick="sendMessage()">发送</button>
  29. <input type="text" id="adminId" placeholder="输入客服ID"/>
  30. <script>
  31. const userId = prompt("请输入您的用户ID");
  32. fetch('/chat/getToken', {
  33. method: "GET"
  34. }).then(response => response.json())
  35. .then(token => {
  36. const customInfo = { token: token.data };
  37. const queryParams = new URLSearchParams();
  38. Object.entries(customInfo).forEach(([key, value]) => {
  39. queryParams.append(key, value);
  40. });
  41. const wsUrl = `ws://localhost:8081/ws?${queryParams.toString()}`;
  42. const ws = new WebSocket(wsUrl);
  43. const messagesDiv = document.getElementById("messages");
  44. const typingIndicator = document.getElementById("typingIndicator");
  45. let typingTimeout = null; // 停止输入的定时器
  46. let lastTypingSent = 0; // 防抖用
  47. const TYPING_INTERVAL = 500; // 最小间隔
  48. const STOP_DELAY = 2000; // 超过2秒没输入则发送 stop
  49. ws.onopen = () => {
  50. console.log("已连接");
  51. ws.send(JSON.stringify({from: userId, type: "login", role: "user"}));
  52. };
  53. ws.onmessage = (e) => {
  54. const msg = JSON.parse(e.data);
  55. if (msg.type === "typing") {
  56. typingIndicator.textContent = msg.from + " 正在输入...";
  57. } else if (msg.type === "typingStop") {
  58. typingIndicator.textContent = "";
  59. } else if (msg.type === "chat") {
  60. const p = document.createElement("p");
  61. p.textContent = msg.from + ": " + msg.content;
  62. messagesDiv.appendChild(p);
  63. typingIndicator.textContent = ""; // 收到消息时清掉 typing
  64. }
  65. };
  66. window.sendMessage = function () {
  67. const input = document.getElementById("msgInput");
  68. const content = input.value;
  69. if (content.trim()) {
  70. const adminIdInput = document.getElementById("adminId");
  71. const toAdminId = adminIdInput.value.trim();
  72. ws.send(JSON.stringify({
  73. from: userId,
  74. to: toAdminId,
  75. type: "chat",
  76. content: content,
  77. role: "user"
  78. }));
  79. input.value = "";
  80. }
  81. };
  82. // 🔥 监听输入框 typing
  83. const input = document.getElementById("msgInput");
  84. input.addEventListener("input", () => {
  85. const now = Date.now();
  86. if (now - lastTypingSent > TYPING_INTERVAL) {
  87. const adminIdInput = document.getElementById("adminId");
  88. const toAdminId = adminIdInput.value.trim();
  89. ws.send(JSON.stringify({
  90. from: userId,
  91. to: toAdminId,
  92. type: "typing",
  93. role: "user"
  94. }));
  95. lastTypingSent = now;
  96. }
  97. // 重置停止输入的定时器
  98. if (typingTimeout) clearTimeout(typingTimeout);
  99. typingTimeout = setTimeout(() => {
  100. const adminIdInput = document.getElementById("adminId");
  101. const toAdminId = adminIdInput.value.trim();
  102. ws.send(JSON.stringify({
  103. from: userId,
  104. to: toAdminId,
  105. type: "typingStop",
  106. role: "user"
  107. }));
  108. }, STOP_DELAY);
  109. });
  110. })
  111. .catch(error => {
  112. console.error('获取token失败:', error);
  113. alert('获取token失败,无法建立连接');
  114. });
  115. </script>
  116. </body>
  117. </html>