messagesHook.js 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. import { useWebRTCStore } from "@/stores/modules/webrtcStore";
  2. import { MSG_TYPE, MSG_TYPE_MAP } from "@/common/constant/msgType";
  3. import * as Constant from "@/common/constant/Constant";
  4. // 发送消息处理
  5. export const setMessageHook = (message, state) => {
  6. // 文本消息
  7. if (message.contentType == MSG_TYPE.TEXT) {
  8. state.messages.push({
  9. ...message,
  10. toUsername: message.friendUsername,
  11. });
  12. }
  13. // 音频消息
  14. if (message.contentType === MSG_TYPE.AUDIO) {
  15. const blob = new Blob([message.file], { type: message.fileSuffix });
  16. const url = URL.createObjectURL(blob);
  17. state.messages.push({
  18. ...message,
  19. toUsername: message.to,
  20. localUrl: url,
  21. });
  22. }
  23. // 图片
  24. if (message.contentType === MSG_TYPE.IMAGE) {
  25. const blob = new Blob([message.file], { type: message.fileSuffix });
  26. const url = URL.createObjectURL(blob);
  27. state.messages.push({
  28. ...message,
  29. toUsername: message.to,
  30. localUrl: url,
  31. });
  32. }
  33. };
  34. // 接收到消息处理
  35. export const handleMessageHook = (message, state) => {
  36. // 文本消息
  37. message.avatar = state.toUserInfo.avatar;
  38. if (message.contentType === MSG_TYPE.TEXT) {
  39. state.messages.push({
  40. ...message,
  41. toUsername: message.to,
  42. });
  43. }
  44. // 音频消息
  45. if (message.contentType === MSG_TYPE.AUDIO) {
  46. const audioBlob = new Blob([message.file], {
  47. type: `audio/${message.fileSuffix}`,
  48. });
  49. // 生成可播放的 ObjectURL
  50. const audioUrl = URL.createObjectURL(audioBlob);
  51. state.messages.push({
  52. ...message,
  53. file: audioUrl,
  54. toUsername: message.to,
  55. });
  56. }
  57. // 图片
  58. if (message.contentType === MSG_TYPE.IMAGE) {
  59. const blob = new Blob([message.file], { type: message.fileSuffix });
  60. const url = URL.createObjectURL(blob);
  61. state.messages.push({
  62. ...message,
  63. file: url,
  64. toUsername: message.to,
  65. });
  66. }
  67. // 音频在线:拨号
  68. if (
  69. message.contentType === Constant.DIAL_AUDIO_ONLINE ||
  70. message.contentType === Constant.DIAL_VIDEO_ONLINE
  71. ) {
  72. console.log("收到播号")
  73. const rtcStore = useWebRTCStore();
  74. rtcStore.imSate = {
  75. videoCallModal: true,
  76. callName: message.fromUsername,
  77. fromUserUuid: message.from,
  78. callAvatar: message.avatar
  79. };
  80. return
  81. }
  82. // 音频在线:取消
  83. if (
  84. message.contentType === Constant.CANCELL_AUDIO_ONLINE ||
  85. message.contentType === Constant.CANCELL_VIDEO_ONLINE
  86. ) {
  87. console.log("音频在线:取消")
  88. const rtcStore = useWebRTCStore();
  89. rtcStore.imSate.videoCallModal = false;
  90. return;
  91. }
  92. // 音频在线:拒接
  93. if (
  94. message.contentType === Constant.REJECT_AUDIO_ONLINE ||
  95. message.contentType === Constant.REJECT_VIDEO_ONLINE
  96. ) {
  97. console.log("音频在线:拒接")
  98. const rtcStore = useWebRTCStore();
  99. rtcStore.imSate.videoCallModal = false;
  100. return;
  101. }
  102. // 音频在线:接听
  103. if (
  104. message.contentType === Constant.ACCEPT_VIDEO_ONLINE ||
  105. message.contentType === Constant.ACCEPT_AUDIO_ONLINE
  106. ) {
  107. console.log("音频在线:接听")
  108. const video = message.contentType == Constant.ACCEPT_AUDIO_ONLINE
  109. startAudioOnline(video, state);
  110. return;
  111. }
  112. // 音频通话
  113. if (message.type === Constant.MESSAGE_TRANS_TYPE) {
  114. if (
  115. message.contentType >= Constant.DIAL_MEDIA_START &&
  116. message.contentType <= Constant.DIAL_MEDIA_END
  117. ) {
  118. console.log("音频通话")
  119. // 媒体通话处理
  120. // dealMediaCall(message);
  121. return;
  122. }
  123. const rtcStore = useWebRTCStore();
  124. const { type, sdp, iceCandidate } = JSON.parse(message.content);
  125. // 接收answer:设置对端sdp
  126. if (type === "answer") {
  127. const answerSdp = new RTCSessionDescription({ type, sdp });
  128. rtcStore.setRemoteDescription(answerSdp);
  129. }
  130. // 处理 ICE 候选(统一处理offer_ice和answer_ice)
  131. if (type.endsWith("_ice")) {
  132. const candidate = new RTCIceCandidate(iceCandidate);
  133. rtcStore
  134. .addIceCandidate(candidate)
  135. .catch((error) => console.error("添加ICE候选失败:", error));
  136. return;
  137. }
  138. // 响应对端offer
  139. if (type === "offer") {
  140. // 检查媒体权限是否开启
  141. // let preview = null;
  142. if (!rtcStore.peerConnection) {
  143. rtcStore.initConnection(false); // false表示是Answer方
  144. }
  145. let video = false;
  146. if (message.contentType === Constant.VIDEO_ONLINE) {
  147. // preview = document.getElementById("localVideoReceiver");
  148. video = true;
  149. // // 屏幕共享
  150. }
  151. if (message.contentType === Constant.AUDIO_ONLINE) {
  152. // preview = document.getElementById("audioPhone");
  153. // 音频电话
  154. }
  155. navigator.mediaDevices
  156. .getUserMedia({ audio: true, video: video })
  157. .then((stream) => {
  158. rtcStore.addLocalStream(stream);
  159. const offer = new RTCSessionDescription({ type, sdp });
  160. return rtcStore.setRemoteDescription(offer);
  161. })
  162. .then(() => rtcStore.createAnswer())
  163. .then((answer) => {
  164. state.sendMessage({
  165. content: JSON.stringify(answer),
  166. type: Constant.MESSAGE_TRANS_TYPE,
  167. messageType: message.contentType,
  168. });
  169. });
  170. }
  171. }
  172. };
  173. // 消息回调
  174. const messageCallback = (contentType, state)=>{
  175. state.sendMessage({
  176. contentType, // 消息内容类型
  177. content: "callback", //
  178. type: Constant.MESSAGE_TRANS_TYPE,
  179. });
  180. }
  181. // 创建呼叫:开启语音电话
  182. const startAudioOnline = (video, state) => {
  183. const rtcStore = useWebRTCStore();
  184. // 初始化webrtc连接
  185. rtcStore.initConnection(true);
  186. navigator.mediaDevices
  187. .getUserMedia({ audio: true, video: video })
  188. .then((stream) => {
  189. rtcStore.addLocalStream(stream);
  190. return rtcStore.createOffer();
  191. })
  192. .then((offer) => {
  193. // 发送offer
  194. state.sendMessage({
  195. contentType: Constant.AUDIO_ONLINE, // 消息内容类型
  196. content: JSON.stringify(offer),
  197. type: Constant.MESSAGE_TRANS_TYPE,
  198. });
  199. })
  200. .catch((error) => {
  201. console.error("发起呼叫失败:", error);
  202. });
  203. };