ChatBox.js 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. import LoginModal from "@/components/LoginModal";
  2. import MarkdownIt from "markdown-it";
  3. import { pcInnerAi } from "@/api/api";
  4. const md = new MarkdownIt();
  5. export default {
  6. components: {
  7. LoginModal,
  8. },
  9. data() {
  10. return {
  11. messages: [
  12. {
  13. user: "bot",
  14. messageType: "TEXT",
  15. message: "欢迎使用轻良智能AI助理",
  16. html: "",
  17. time: "",
  18. done: true,
  19. },
  20. ],
  21. generating: false,
  22. userInput: "",
  23. websocket: null,
  24. wsUrl:'http://58.246.234.210:7860/api/v1/run/2f1faff2-99df-4821-87d6-43d693084c4b?stream=false',
  25. tweaks:{},
  26. showLoginModal: false,
  27. isLoggedIn: false, // 添加登录状态标志
  28. };
  29. },
  30. created() {
  31. this.connectWebSocket();
  32. },
  33. mounted() {
  34. if(this.$route.name=='ai'){
  35. /* 外部知识库 */
  36. const AIData=JSON.parse(localStorage.getItem("AIData"))
  37. this.wsUrl=AIData.data.url
  38. this.tweaks=AIData.data.tweaks
  39. }else{
  40. /* 内部知识库 */
  41. pcInnerAi().then(res=>{
  42. if(res.status!==200) return
  43. this.wsUrl=res.data.url
  44. this.tweaks=res.data.tweaks
  45. })
  46. }
  47. },
  48. methods: {
  49. handleLoginSuccess() {
  50. this.showLoginModal = false;
  51. this.isLoggedIn = true;
  52. // 登录成功后,可以继续发送消息
  53. this.sendMessage();
  54. },
  55. getUuid() {
  56. return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(
  57. /[xy]/g,
  58. function (c) {
  59. var r = (Math.random() * 16) | 0,
  60. v = c == "x" ? r : (r & 0x3) | 0x8;
  61. return v.toString(16);
  62. }
  63. );
  64. },
  65. connectWebSocket() {
  66. const wsUrl = this.wsUrl//'http://58.246.234.210:7860/api/v1/run/951e3ba4-c66a-496c-9497-7dbddc2647f8?stream=false'
  67. // 这里做一个简单的鉴权,只有符合条件的鉴权才能握手成功
  68. // 移除这里的fetch调用,改用WebSocket
  69. this.websocket = new WebSocket(wsUrl);
  70. this.websocket.onerror = (event) => {
  71. console.error("WebSocket 连接错误:", event);
  72. };
  73. this.websocket.onclose = (event) => {
  74. console.log("WebSocket 连接关闭:", event);
  75. };
  76. this.websocket.onopen = (event) => {
  77. console.log("WebSocket 连接已建立:", event);
  78. };
  79. this.websocket.onmessage = (event) => {
  80. // 解析收到的消息
  81. const result = JSON.parse(event.data);
  82. console.log(result.content);
  83. // 检查消息是否完结
  84. if (result.done) {
  85. this.messages[this.messages.length - 1].done = true;
  86. return;
  87. }
  88. if (this.messages[this.messages.length - 1].done) {
  89. // 添加新的消息
  90. this.messages.push({
  91. time: Date.now(),
  92. message: result.content,
  93. messageType: "TEXT",
  94. user: "bot",
  95. done: false,
  96. });
  97. } else {
  98. // 更新最后一条消息
  99. let lastMessage = this.messages[this.messages.length - 1];
  100. lastMessage.message += result.content;
  101. this.messages[this.messages.length - 1] = lastMessage;
  102. }
  103. };
  104. },
  105. async sendMessage() {
  106. if(this.$route.name=='ai'){
  107. if(!localStorage.getItem('AIData')){
  108. this.showLoginModal=true
  109. return
  110. }
  111. }
  112. const chatId = this.getUuid();
  113. const wsUrl =this.wsUrl//'http://58.246.234.210:7860/api/v1/run/951e3ba4-c66a-496c-9497-7dbddc2647f8?stream=false'
  114. let message = this.userInput.trim();
  115. if (message) {
  116. // Markdown换行:在每个换行符之前添加两个空格
  117. message = message.replace(/(\r\n|\r|\n)/g, " \n");
  118. this.messages.push({
  119. time: Date.now(),
  120. message: message,
  121. messageType: "TEXT",
  122. user: "user",
  123. done: true,
  124. });
  125. this.userInput = "";
  126. console.log(this.messages);
  127. // 通过 HTTP 发送消息
  128. try {
  129. ///send-message
  130. const response = await fetch(`${wsUrl}`, {
  131. method: "POST",
  132. headers: {
  133. "Content-Type": "application/json",
  134. },
  135. body: JSON.stringify({
  136. chatId: chatId,
  137. input_value: message,
  138. output_type: "chat",
  139. input_type: "chat",
  140. tweaks:this.tweaks/* {
  141. "ChatInput-dDbhW": {},
  142. "Prompt-1stgH": {},
  143. "ChatOutput-b1zWw": {},
  144. "OllamaModel-5n7vc": {},
  145. "Milvus-1X7fT": {},
  146. "OllamaEmbeddings-V29wK": {},
  147. "Memory-GrHZr": {},
  148. "ParseData-0dk9n": {}
  149. } */,
  150. }),
  151. });
  152. if (!response.ok) {
  153. const errorText = await response.text(); // 获取错误文本
  154. throw new Error(
  155. `HTTP error! status: ${response.status}, message: ${errorText}`
  156. );
  157. }
  158. const result = await response.json();
  159. this.handleResponse(result);
  160. } catch (error) {
  161. console.error("Error sending message:", error);
  162. }
  163. }
  164. },
  165. handleResponse(value) {
  166. const data =value.outputs[0].outputs[0].results.message
  167. this.messages.push({
  168. user: "bot",
  169. messageType: data.text_key,
  170. message: data.text,
  171. html: "",
  172. time: data.timestamp,
  173. done: true,
  174. });
  175. },
  176. renderMarkdown(rawMarkdown) {
  177. return md.render(rawMarkdown);
  178. },
  179. handleKeydown(event) {
  180. // Check if 'Enter' is pressed without the 'Alt' key
  181. if (event.key === "Enter" && !(event.shiftKey || event.altKey)) {
  182. event.preventDefault(); // Prevent the default action to avoid line break in textarea
  183. this.sendMessage();
  184. } else if (event.key === "Enter" && event.altKey) {
  185. // Allow 'Alt + Enter' to insert a newline
  186. const cursorPosition = event.target.selectionStart;
  187. const textBeforeCursor = this.userInput.slice(0, cursorPosition);
  188. const textAfterCursor = this.userInput.slice(cursorPosition);
  189. // Insert the newline character at the cursor position
  190. this.userInput = textBeforeCursor + "\n" + textAfterCursor;
  191. // Move the cursor to the right after the inserted newline
  192. this.$nextTick(() => {
  193. event.target.selectionStart = cursorPosition + 1;
  194. event.target.selectionEnd = cursorPosition + 1;
  195. });
  196. }
  197. },
  198. beforeDestroy() {
  199. if (this.websocket) {
  200. this.websocket.close();
  201. }
  202. },
  203. },
  204. updated() {
  205. const messagesContainer = this.$el.querySelector(".messages");
  206. messagesContainer.scrollTop = messagesContainer.scrollHeight;
  207. },
  208. };