use-websocket-chat.js 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. import { ref } from 'vue';
  2. import { kuky_Authorization } from '../../base/storage';
  3. /**
  4. * 获取websocket连接的地址
  5. * @param {string} type - 对话类型,可选值:report/excel/chat
  6. * @param {string} agent_id - 对话使用的agent ID
  7. * @param {string} chat_id - 对话记录的ID
  8. * @returns
  9. */
  10. function getWSUrl(type, agent_id, chat_id) {
  11. const host = location.host;
  12. const token = kuky_Authorization.get();
  13. if (type === 'report') {
  14. return `ws://${host}/api/${type}/ws/${agent_id}/${chat_id}?token=${token}`;
  15. } else if (type === 'chat') {
  16. return `ws://${host}/api/${type}/ws/${agent_id}/${chat_id}?token=${token}`;
  17. } else if (type === 'excel') {
  18. return `ws://${host}/api/document/ws/excel`;
  19. } else {
  20. return `ws://${host}/api/chat/ws/${agent_id}/${chat_id}?token=${token}`;
  21. }
  22. }
  23. /**
  24. * 确保一个值是函数
  25. * 如果值本身是函数,则返回值本身
  26. * 如果值本身不是函数,则返回一个空函数
  27. * @param {function} fn
  28. * @returns
  29. */
  30. function protectedFunction(fn) {
  31. if (typeof fn === 'function') {
  32. return fn;
  33. }
  34. return Function.prototype;
  35. }
  36. /**
  37. * 使用websocket进行对话
  38. * @see https://developer.mozilla.org/zh-CN/docs/Web/API/WebSockets_API
  39. * @param {string} agent_id - agent id
  40. * @param {string} chat_id - 对话ID
  41. * @param {string} type - 对话类型,可选值:report/excel/chat
  42. * @param {object} trigger - 触发的方法
  43. * @param {function} trigger.onMessage - 当收到消息时触发的方法
  44. * @param {function} trigger.onClose - 当websocket关闭时触发的方法
  45. * @param {function} trigger.onError - 当websocket出错时触发的方法
  46. * @returns
  47. */
  48. export default function useWebSocketChat(trigger) {
  49. let delay_message_list = [];
  50. const onMessage = protectedFunction(trigger.onMessage);
  51. const onClose = protectedFunction(trigger.onClose);
  52. const onError = protectedFunction(trigger.onError);
  53. /**
  54. * websocket当前状态
  55. * @see https://developer.mozilla.org/zh-CN/docs/Web/API/WebSocket/readyState
  56. * 0 CONNECTING 套接字已经创建,但是连接尚未打开
  57. * 1 OPEN 连接已经打开,准备进行通信
  58. * 2 CLOSING 连接正在关闭中
  59. * 3 CLOSED 连接已关闭或者无法打开
  60. * -1 此处自定义值,未启动
  61. */
  62. const websocket_status = ref(-1);
  63. /**
  64. * 创建一个websocket连接
  65. * @returns
  66. */
  67. function createWSConnection(agent_id, chat_id, type) {
  68. const wsUrl = getWSUrl(type, agent_id, chat_id);
  69. const wskt = new WebSocket(wsUrl);
  70. // 当 WebSocket 打开时...
  71. wskt.onopen = function (event) {
  72. delay_message_list.forEach((item) => {
  73. wskt.send(item);
  74. });
  75. // 所有消息发送完成后,清空消息队列
  76. delay_message_list = [];
  77. };
  78. // 当 WebSocket 关闭时...
  79. wskt.onclose = function (event) {
  80. onClose(event);
  81. };
  82. // 当有错误发生时...
  83. wskt.onerror = function (error) {
  84. onError(error);
  85. };
  86. /**
  87. * 当收到websocket消息时
  88. * @param {WebSocketEvent} event
  89. */
  90. wskt.onmessage = (event) => {
  91. onMessage(event);
  92. };
  93. return wskt;
  94. }
  95. let websocket = null;
  96. return {
  97. /**
  98. * 初始化websocket连接
  99. * @param {string} agent_id
  100. * @param {string} chat_id
  101. * @param {string} type
  102. */
  103. initWSConnection(agent_id, chat_id, type) {
  104. if (websocket === null) {
  105. // websocket未创建:立即创建
  106. websocket = createWSConnection(agent_id, chat_id, type);
  107. }
  108. return websocket;
  109. },
  110. /**
  111. * 发送会话消息
  112. * @param {string} msg
  113. */
  114. sendWSMessage(msg) {
  115. if (websocket === null) {
  116. // websocket未创建:立即创建
  117. websocket = createWSConnection();
  118. }
  119. // 判断socket是否开启
  120. // 如果开启,则直接发送,如果没有开启,则将数据推入消息队列
  121. if (websocket.readyState === 0) {
  122. delay_message_list.push(msg);
  123. }
  124. if (websocket.readyState === 1) {
  125. websocket.send(msg);
  126. }
  127. if (websocket.readyState === 2) {
  128. // 正在关闭
  129. console.log('web socket正在关闭');
  130. }
  131. if (websocket.readyState === 3) {
  132. delay_message_list.push(msg);
  133. // 已关闭: 重新创建socket
  134. websocket = createWSConnection();
  135. }
  136. },
  137. /**
  138. * 获取websocket实例本身
  139. * @returns
  140. */
  141. getWSInstance() {
  142. return websocket;
  143. },
  144. /**
  145. * 结束对话,断开websocket连接
  146. */
  147. closeWSConnect() {
  148. if (websocket === null) {
  149. return;
  150. }
  151. websocket.close();
  152. }
  153. };
  154. }