App.vue 32 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091
  1. <script>
  2. import { mapGetters, mapActions } from 'vuex';
  3. import IMSDK, { IMMethods, MessageReceiveOptType, MessageType, SessionType } from 'openim-uniapp-polyfill';
  4. import { config } from '@/pages_im/common/config';
  5. import { getDbDir, Igexin, toastWithCallback } from '@/pages_im/util/common.js';
  6. import { conversationSort, secFormat, callingModule, meetingModule, parseMessageByType, prepareConversationState } from '@/pages_im/util/imCommon';
  7. import { PageEvents, UpdateMessageTypes, CustomType, ContactChooseTypes } from '@/pages_im/constant';
  8. import { openImLoginApi } from '@/pages_im/api/imBll';
  9. import NotificationUtil from '@/pages_im/util/notification';
  10. import newMessage from '@/pages_im/static/audio/newMessage.wav';
  11. import { getTlsSig,getDicts } from '@/api/common.js'
  12. import { checkLogin } from '@/api/user.js'
  13. let cacheConversationList = [];
  14. let updateDownloadTask = null;
  15. let notificationIntance = null;
  16. let pausing = false;
  17. let innerAudioContext;
  18. let notification;
  19. let uPushPlugin;
  20. export default {
  21. globalData: {
  22. wsUrl: '',
  23. appId: 'wxd8a9a602e7ddc4ba'
  24. },
  25. onLaunch: function () {
  26. this.checkUpdate()
  27. this.initOpenIm();
  28. var that=this;
  29. uni.$on('refreshIM', () => {
  30. this.checkLogin();
  31. });
  32. this.getDicts()
  33. },
  34. onUnload() {
  35. },
  36. onShow() {
  37. uni.getSystemInfo({
  38. success: (result) => {
  39. // 获取手机系统的状态栏高度(不同手机的状态栏高度不同)
  40. // console.log('当前手机的状态栏高度',result.statusBarHeight)
  41. let statusBarHeight = result.statusBarHeight + 'px'
  42. // 获取右侧胶囊的信息 单位px
  43. //#ifndef H5 || APP-PLUS
  44. const menuButtonInfo = uni.getMenuButtonBoundingClientRect()
  45. //bottom: 胶囊底部距离屏幕顶部的距离
  46. //height: 胶囊高度
  47. //left: 胶囊左侧距离屏幕左侧的距离
  48. //right: 胶囊右侧距离屏幕左侧的距离
  49. //top: 胶囊顶部距离屏幕顶部的距离
  50. //width: 胶囊宽度
  51. // console.log(menuButtonInfo.width, menuButtonInfo.height, menuButtonInfo.top)
  52. // console.log('计算胶囊右侧距离屏幕右边距离', result.screenWidth - menuButtonInfo.right)
  53. let menuWidth = menuButtonInfo.width + 'px'
  54. let menuHeight = menuButtonInfo.height + 'px'
  55. let menuBorderRadius = menuButtonInfo.height / 2 + 'px'
  56. let menuRight = result.screenWidth - menuButtonInfo.right + 'px'
  57. let menuTop = menuButtonInfo.top + 'px'
  58. let contentTop = result.statusBarHeight + 44 + 'px'
  59. let menuInfo = {
  60. statusBarHeight: statusBarHeight,//状态栏高度----用来给自定义导航条页面的顶部导航条设计padding-top使用:目的留出系统的状态栏区域
  61. menuWidth: menuWidth,//右侧的胶囊宽度--用来给自定义导航条页面的左侧胶囊设置使用
  62. menuHeight: menuHeight,//右侧的胶囊高度--用来给自定义导航条页面的左侧胶囊设置使用
  63. menuBorderRadius: menuBorderRadius,//一半的圆角--用来给自定义导航条页面的左侧胶囊设置使用
  64. menuRight: menuRight,//右侧的胶囊距离右侧屏幕距离--用来给自定义导航条页面的左侧胶囊设置使用
  65. menuTop: menuTop,//右侧的胶囊顶部距离屏幕顶部的距离--用来给自定义导航条页面的左侧胶囊设置使用
  66. contentTop: contentTop,//内容区距离页面最上方的高度--用来给自定义导航条页面的内容区定位距离使用
  67. }
  68. uni.setStorageSync('menuInfo', menuInfo)
  69. //#endif
  70. },
  71. fail: (error) => {
  72. console.log(error)
  73. }
  74. })
  75. },
  76. onHide() {
  77. },
  78. computed: {
  79. ...mapGetters([
  80. 'storeConversationList',
  81. 'storeCurrentConversation',
  82. 'storeCurrentUserID',
  83. 'storeSelfInfo',
  84. 'storeRecvFriendApplications',
  85. 'storeRecvGroupApplications',
  86. 'storeHistoryMessageList',
  87. 'storeIsSyncing',
  88. 'storeGroupList'
  89. ]),
  90. contactBadgeRely() {
  91. return {
  92. recvFriendApplications: this.storeRecvFriendApplications,
  93. recvGroupApplications: this.storeRecvGroupApplications,
  94. userKey: this.storeCurrentUserID
  95. };
  96. }
  97. },
  98. methods: {
  99. ...mapActions('message', ['pushNewMessage', 'updateOneMessage', 'updateQuoteMessageRevoke', 'updateMessageNicknameAndFaceUrl']),
  100. ...mapActions('conversation', ['updateCurrentMemberInGroup']),
  101. ...mapActions('contact', [
  102. 'updateFriendInfo',
  103. 'pushNewFriend',
  104. 'updateBlackInfo',
  105. 'pushNewBlack',
  106. 'pushNewGroup',
  107. 'updateGroupInfo',
  108. 'pushNewRecvFriendApplition',
  109. 'updateRecvFriendApplition',
  110. 'pushNewSentFriendApplition',
  111. 'updateSentFriendApplition',
  112. 'pushNewRecvGroupApplition',
  113. 'updateRecvGroupApplition',
  114. 'pushNewSentGroupApplition',
  115. 'updateSentGroupApplition'
  116. ]),
  117. getRandomInt(min, max) {
  118. const minCeiled = Math.ceil(min);
  119. const maxFloored = Math.floor(max);
  120. return Math.floor(Math.random() * (maxFloored - minCeiled + 1) + minCeiled); // 包含最小值和最大值
  121. },
  122. checkLogin(){
  123. var data={};
  124. checkLogin(data).then(
  125. res => {
  126. if(res.code==200){
  127. this.openImLogin();
  128. }
  129. },
  130. rej => {}
  131. );
  132. },
  133. checkUpdate() {
  134. const updateManager = uni.getUpdateManager();
  135. updateManager.onCheckForUpdate(function(res) {
  136. // 请求完新版本信息的回调
  137. console.log('是否有新版本:', res.hasUpdate);
  138. });
  139. updateManager.onUpdateReady(function() {
  140. uni.showModal({
  141. title: '更新提示',
  142. content: '新版本已经准备好,是否重启小程序?',
  143. confirmText: '立即重启',
  144. confirmColor: '#2179f5',
  145. success(res) {
  146. if (res.confirm) {
  147. // 新的版本已经下载好,调用 applyUpdate 应用新版本并重启
  148. updateManager.applyUpdate();
  149. }
  150. }
  151. });
  152. });
  153. updateManager.onUpdateFailed(function() {
  154. // 新的版本下载失败
  155. uni.showModal({
  156. title: '更新提示',
  157. content: '新版本下载失败,请检查网络后重试。',
  158. showCancel: false
  159. });
  160. });
  161. },
  162. initOpenIm() {
  163. innerAudioContext = uni.createInnerAudioContext();
  164. innerAudioContext.autoplay = false;
  165. innerAudioContext.src = newMessage;
  166. this.setGlobalIMlistener();
  167. this.tryLogin();
  168. },
  169. setGlobalIMlistener() {
  170. // init
  171. const kickHander = (message) => {
  172. toastWithCallback(message, () => {
  173. uni.setStorageSync('AppToken',null);
  174. uni.removeStorage({key: "IMToken",});
  175. uni.removeStorage({key: "IMUserID",});
  176. uni.removeStorage({key: "IMHasLogin"});
  177. uni.$emit('loginOut');
  178. //callingModule?.endCall();
  179. //meetingModule?.endCall();
  180. });
  181. };
  182. let that=this;
  183. IMSDK.subscribe(IMSDK.IMEvents.OnKickedOffline, (data) => {
  184. kickHander('您的账号在其他设备登录,请重新登陆!');
  185. //that.removeImData();
  186. //that.openImLogin();
  187. });
  188. IMSDK.subscribe(IMSDK.IMEvents.OnUserTokenExpired, (data) => {
  189. //kickHander('您的登录已过期,请重新登陆!');
  190. that.removeImData();
  191. that.openImLogin();
  192. });
  193. IMSDK.subscribe(IMSDK.IMEvents.OnUserTokenInvalid, (data) => {
  194. //kickHander('您的登录已无效,请重新登陆!');
  195. that.removeImData();
  196. that.openImLogin();
  197. });
  198. // sync
  199. const syncStartHandler = ({ data }) => {
  200. this.$store.commit('user/SET_IS_SYNCING', true);
  201. this.$store.commit('user/SET_REINSTALL', data);
  202. };
  203. const syncProgressHandler = ({ data }) => {
  204. this.$store.commit('user/SET_PROGRESS', data);
  205. };
  206. const syncFinishHandler = () => {
  207. this.$store.dispatch('conversation/getConversationList');
  208. this.$store.dispatch('contact/getFriendList');
  209. this.$store.dispatch('contact/getGrouplist');
  210. this.$store.dispatch('conversation/getUnReadCount');
  211. this.$store.commit('user/SET_IS_SYNCING', false);
  212. uni.hideLoading();
  213. };
  214. const syncFailedHandler = () => {
  215. uni.hideLoading();
  216. uni.$u.toast('同步消息失败');
  217. this.$store.dispatch('conversation/getConversationList');
  218. this.$store.dispatch('conversation/getUnReadCount');
  219. this.$store.commit('user/SET_IS_SYNCING', false);
  220. };
  221. IMSDK.subscribe(IMSDK.IMEvents.OnSyncServerStart, syncStartHandler);
  222. IMSDK.subscribe(IMSDK.IMEvents.OnSyncServerFinish, syncFinishHandler);
  223. IMSDK.subscribe(IMSDK.IMEvents.OnSyncServerFailed, syncFailedHandler);
  224. IMSDK.subscribe(IMSDK.IMEvents.OnSyncServerProgress, syncProgressHandler);
  225. // self
  226. const selfInfoUpdateHandler = ({ data }) => {
  227. this.$store.commit('user/SET_SELF_INFO', {
  228. ...this.storeSelfInfo,
  229. ...data
  230. });
  231. this.updateMessageNicknameAndFaceUrl({
  232. sendID: data.userID,
  233. senderNickname: data.nickname,
  234. senderFaceUrl: data.faceURL
  235. });
  236. };
  237. IMSDK.subscribe(IMSDK.IMEvents.OnSelfInfoUpdated, selfInfoUpdateHandler);
  238. // message
  239. const newMessagesHandler = ({ data }) => {
  240. if (this.storeIsSyncing) {
  241. return;
  242. }
  243. data.forEach(this.handleNewMessage);
  244. };
  245. const c2cReadReceiptHandler = ({ data: receiptList }) => {
  246. if (receiptList[0].userID !== this.storeCurrentConversation.userID) {
  247. return;
  248. }
  249. receiptList.forEach((item) => {
  250. item.msgIDList.forEach((msgID) => {
  251. this.updateOneMessage({
  252. message: {
  253. clientMsgID: msgID
  254. },
  255. type: UpdateMessageTypes.KeyWords,
  256. keyWords: {
  257. key: 'isRead',
  258. value: true
  259. }
  260. });
  261. });
  262. });
  263. };
  264. const groupReadReceiptHandler = ({ data }) => {
  265. if (data.conversationID !== this.storeCurrentConversation.conversationID) {
  266. return;
  267. }
  268. data.groupMessageReadInfo.map((receipt) => {
  269. const oldMessage = this.storeHistoryMessageList.find((msg) => msg.clientMsgID === receipt.clientMsgID);
  270. if (oldMessage) {
  271. uni.$emit(PageEvents.GroupMessageReceipt, receipt);
  272. const newMessage = {
  273. ...oldMessage,
  274. isRead: true,
  275. attachedInfoElem: {
  276. ...oldMessage.attachedInfoElem,
  277. groupHasReadInfo: {
  278. hasReadCount: receipt.hasReadCount,
  279. unreadCount: receipt.unreadCount
  280. }
  281. }
  282. };
  283. console.log(newMessage);
  284. this.updateOneMessage({ message: newMessage });
  285. }
  286. });
  287. console.log(data);
  288. };
  289. const newRecvMessageRevokedHandler = ({ data: revokedMessage }) => {
  290. if (!this.storeCurrentConversation.conversationID) {
  291. return;
  292. }
  293. this.updateOneMessage({
  294. message: { clientMsgID: revokedMessage.clientMsgID },
  295. type: UpdateMessageTypes.KeyWords,
  296. keyWords: [
  297. {
  298. key: 'contentType',
  299. value: MessageType.RevokeMessage
  300. },
  301. {
  302. key: 'notificationElem',
  303. value: {
  304. detail: JSON.stringify(revokedMessage)
  305. }
  306. }
  307. ]
  308. });
  309. this.updateQuoteMessageRevoke({
  310. clientMsgID: revokedMessage.clientMsgID
  311. });
  312. };
  313. const inputStatusChanged = ({ data }) => {
  314. if (data.userID === this.storeCurrentConversation.userID && data.conversationID === this.storeCurrentConversation.conversationID) {
  315. if (data.platformIDs.length > 0) {
  316. uni.$emit(PageEvents.TypingUpdate);
  317. }
  318. }
  319. };
  320. IMSDK.subscribe(IMSDK.IMEvents.OnRecvNewMessages, newMessagesHandler);
  321. IMSDK.subscribe(IMSDK.IMEvents.OnInputStatusChanged, inputStatusChanged);
  322. IMSDK.subscribe(IMSDK.IMEvents.OnRecvC2CReadReceipt, c2cReadReceiptHandler);
  323. IMSDK.subscribe(IMSDK.IMEvents.OnRecvGroupReadReceipt, groupReadReceiptHandler);
  324. IMSDK.subscribe(IMSDK.IMEvents.OnNewRecvMessageRevoked, newRecvMessageRevokedHandler);
  325. // friend
  326. const friendInfoChangeHandler = ({ data }) => {
  327. uni.$emit(IMSDK.IMEvents.OnFriendInfoChanged, { data });
  328. if (data.userID === this.storeCurrentConversation?.userID) {
  329. this.updateMessageNicknameAndFaceUrl({
  330. sendID: data.userID,
  331. senderNickname: data.remark || data.nickname,
  332. senderFaceUrl: data.faceURL
  333. });
  334. this.$store.commit('conversation/SET_CURRENT_CONVERSATION', { ...this.storeCurrentConversation, showName: data.remark || data.nickname });
  335. }
  336. console.log(this.storeConversationList);
  337. this.updateFriendInfo({friendInfo: data});
  338. };
  339. const friendAddedHandler = ({ data }) => {
  340. this.pushNewFriend(data);
  341. };
  342. const friendDeletedHander = ({ data }) => {
  343. this.updateFriendInfo({
  344. friendInfo: data,
  345. isRemove: true
  346. });
  347. };
  348. IMSDK.subscribe(IMSDK.IMEvents.OnFriendInfoChanged, friendInfoChangeHandler);
  349. IMSDK.subscribe(IMSDK.IMEvents.OnFriendAdded, friendAddedHandler);
  350. IMSDK.subscribe(IMSDK.IMEvents.OnFriendDeleted, friendDeletedHander);
  351. // blacklist
  352. const blackAddedHandler = ({ data }) => {
  353. this.pushNewBlack(data);
  354. };
  355. const blackDeletedHandler = ({ data }) => {
  356. this.updateBlackInfo({
  357. blackInfo: data,
  358. isRemove: true
  359. });
  360. };
  361. IMSDK.subscribe(IMSDK.IMEvents.OnBlackAdded, blackAddedHandler);
  362. IMSDK.subscribe(IMSDK.IMEvents.OnBlackDeleted, blackDeletedHandler);
  363. // group
  364. const joinedGroupAddedHandler = ({ data }) => {
  365. uni.$emit(IMSDK.IMEvents.OnJoinedGroupAdded, { data });
  366. this.pushNewGroup(data);
  367. };
  368. const joinedGroupDeletedHandler = ({ data }) => {
  369. uni.$emit(IMSDK.IMEvents.OnJoinedGroupDeleted, { data });
  370. this.updateGroupInfo({
  371. groupInfo: data,
  372. isRemove: true
  373. });
  374. };
  375. const groupInfoChangedHandler = ({ data }) => {
  376. this.updateGroupInfo({
  377. groupInfo: data
  378. });
  379. };
  380. const groupMemberInfoChangedHandler = ({ data }) => {
  381. uni.$emit(IMSDK.IMEvents.OnGroupMemberInfoChanged, { data });
  382. if (data.groupID === this.storeCurrentConversation?.groupID) {
  383. this.updateMessageNicknameAndFaceUrl({
  384. sendID: data.userID,
  385. senderNickname: data.nickname,
  386. senderFaceUrl: data.faceURL
  387. });
  388. this.updateCurrentMemberInGroup(data);
  389. }
  390. };
  391. IMSDK.subscribe(IMSDK.IMEvents.OnJoinedGroupAdded, joinedGroupAddedHandler);
  392. IMSDK.subscribe(IMSDK.IMEvents.OnJoinedGroupDeleted, joinedGroupDeletedHandler);
  393. IMSDK.subscribe(IMSDK.IMEvents.OnGroupInfoChanged, groupInfoChangedHandler);
  394. IMSDK.subscribe(IMSDK.IMEvents.OnGroupMemberInfoChanged, groupMemberInfoChangedHandler);
  395. // application
  396. const friendApplicationNumHandler = ({ data }) => {
  397. const isRecv = data.toUserID === this.storeCurrentUserID;
  398. if (isRecv) {
  399. this.pushNewRecvFriendApplition(data);
  400. } else {
  401. this.pushNewSentFriendApplition(data);
  402. }
  403. };
  404. const friendApplicationAccessHandler = ({ data }) => {
  405. const isRecv = data.toUserID === this.storeCurrentUserID;
  406. if (isRecv) {
  407. this.updateRecvFriendApplition({
  408. application: data
  409. });
  410. } else {
  411. this.updateSentFriendApplition({
  412. application: data
  413. });
  414. }
  415. };
  416. const groupApplicationNumHandler = ({ data }) => {
  417. const isRecv = data.userID !== this.storeCurrentUserID;
  418. if (isRecv) {
  419. this.pushNewRecvGroupApplition(data);
  420. } else {
  421. this.pushNewSentGroupApplition(data);
  422. }
  423. };
  424. const groupApplicationAccessHandler = ({ data }) => {
  425. const isRecv = data.userID !== this.storeCurrentUserID;
  426. if (isRecv) {
  427. this.updateRecvGroupApplition({
  428. application: data
  429. });
  430. } else {
  431. this.updateSentGroupApplition({
  432. application: data
  433. });
  434. }
  435. };
  436. IMSDK.subscribe(IMSDK.IMEvents.OnFriendApplicationAdded, friendApplicationNumHandler);
  437. IMSDK.subscribe(IMSDK.IMEvents.OnFriendApplicationAccepted, friendApplicationAccessHandler);
  438. IMSDK.subscribe(IMSDK.IMEvents.OnFriendApplicationRejected, friendApplicationAccessHandler);
  439. IMSDK.subscribe(IMSDK.IMEvents.OnGroupApplicationAdded, groupApplicationNumHandler);
  440. IMSDK.subscribe(IMSDK.IMEvents.OnGroupApplicationAccepted, groupApplicationAccessHandler);
  441. IMSDK.subscribe(IMSDK.IMEvents.OnGroupApplicationRejected, groupApplicationAccessHandler);
  442. // conversation
  443. const totalUnreadCountChangedHandler = ({ data }) => {
  444. if (this.storeIsSyncing) {
  445. return;
  446. }
  447. this.$store.commit('conversation/SET_UNREAD_COUNT', data);
  448. };
  449. const newConversationHandler = ({ data }) => {
  450. if (this.storeIsSyncing) {
  451. return;
  452. }
  453. const result = [...data, ...this.storeConversationList];
  454. this.$store.commit('conversation/SET_CONVERSATION_LIST', conversationSort(result));
  455. };
  456. const conversationChangedHandler = ({ data }) => {
  457. if (this.storeIsSyncing) {
  458. return;
  459. }
  460. let filterArr = [];
  461. console.log("qxj conversationChangedHandler:::");
  462. console.log(data);
  463. const chids = data.map((ch) => ch.conversationID);
  464. filterArr = this.storeConversationList.filter((tc) => !chids.includes(tc.conversationID));
  465. const idx = data.findIndex((c) => c.conversationID === this.storeCurrentConversation.conversationID);
  466. if (idx !== -1) this.$store.commit('conversation/SET_CURRENT_CONVERSATION', data[idx]);
  467. const result = [...data, ...filterArr];
  468. this.$store.commit('conversation/SET_CONVERSATION_LIST', conversationSort(result));
  469. };
  470. IMSDK.subscribe(IMSDK.IMEvents.OnTotalUnreadMessageCountChanged, totalUnreadCountChangedHandler);
  471. IMSDK.subscribe(IMSDK.IMEvents.OnNewConversation, newConversationHandler);
  472. IMSDK.subscribe(IMSDK.IMEvents.OnConversationChanged, conversationChangedHandler);
  473. const insertInCurrentConversation = (newServerMsg) => {
  474. return newServerMsg.sendID === this.$store.getters.storeCurrentConversation.userID || newServerMsg.recvID === this.$store.getters.storeCurrentConversation.userID;
  475. };
  476. const onNativeCallEndHandler = async ({ invitation, duration, status }) => {
  477. uni.$emit(PageEvents.NativeCallEnd);
  478. if (!status || invitation.groupID) {
  479. return;
  480. }
  481. const type = invitation.mediaType === 'video' ? CustomType.VideoCall : CustomType.VoiceCall;
  482. const customData = {
  483. customType: CustomType.Call,
  484. data: { type, duration: secFormat(duration), status }
  485. };
  486. // uni.clearStorageSync();
  487. const nativeCallList = uni.getStorageSync(`${this.$store.getters.storeCurrentUserID}_nativecall`) || [];
  488. const isSelf = invitation.inviterUserID === this.$store.getters.storeCurrentUserID;
  489. const data = { ...invitation, duration, isSelf, type, time: new Date().getTime() };
  490. uni.setStorage({
  491. key: `${this.$store.getters.storeCurrentUserID}_nativecall`,
  492. data: [...nativeCallList, data]
  493. });
  494. const message = await IMSDK.asyncApi(IMMethods.CreateCustomMessage, IMSDK.uuid(), {
  495. data: JSON.stringify(customData),
  496. extension: '',
  497. description: 'RTC'
  498. });
  499. const recvID = invitation.inviteeUserIDList[0];
  500. IMSDK.asyncApi(IMSDK.IMMethods.InsertSingleMessageToLocalStorage, IMSDK.uuid(), {
  501. message,
  502. recvID,
  503. sendID: invitation.inviterUserID
  504. }).then(({ data }) => {
  505. if (insertInCurrentConversation(data)) {
  506. this.$store.dispatch('message/pushNewMessage', data);
  507. setTimeout(() => uni.$emit(PageEvents.ScrollToBottom, true));
  508. }
  509. }).catch((err) => {
  510. console.log(err);
  511. });
  512. };
  513. const onNativeInviteHandler = async (data) => {
  514. // uni.$u.toast("onNativeInviteHandler")
  515. uni.$u.route('/pages_im/pages/common/contactChoose/index', {
  516. type: ContactChooseTypes.InviteMeeting,
  517. forwardMessage: encodeURIComponent(JSON.stringify(data.data))
  518. });
  519. };
  520. IMSDK.subscribe('onNativeCallEnd', onNativeCallEndHandler);
  521. IMSDK.subscribe('Native_InviteUser', onNativeInviteHandler);
  522. },
  523. openImLogin() {
  524. let that = this;
  525. var userId=uni.getStorageSync('userId');
  526. var avatar=uni.getStorageSync('avatar');
  527. var nickName=uni.getStorageSync('nickName');
  528. var uid = 'U' + userId;
  529. let IMToken = uni.getStorageSync('IMToken');
  530. let IMUserID = uid
  531. let reqData = { userID: uid, nickName: nickName, avatar: avatar };
  532. //if(!!IMToken){
  533. openImLoginApi(
  534. reqData,
  535. IMToken,
  536. IMUserID,
  537. function (token) {
  538. that.tryLogin();
  539. },
  540. function () {}
  541. );
  542. //}
  543. },
  544. async tryLogin() {
  545. const initStore = () => {
  546. uni.setStorageSync('IMHasLogin', 1);
  547. this.$store.dispatch('user/initCache');
  548. this.$store.dispatch('user/getSelfInfo');
  549. //this.$store.dispatch('conversation/getConversationList');
  550. this.$store.dispatch('conversation/getUnReadCount');
  551. // this.$store.dispatch("contact/getFriendList");
  552. // this.$store.dispatch("contact/getGrouplist");
  553. // this.$store.dispatch('contact/getBlacklist');
  554. // this.$store.dispatch('contact/getRecvFriendApplications');
  555. // this.$store.dispatch('contact/getSentFriendApplications');
  556. // this.$store.dispatch('contact/getRecvGroupApplications');
  557. // this.$store.dispatch('contact/getSentGroupApplications');
  558. };
  559. let IMToken = uni.getStorageSync('IMToken');
  560. let IMUserID = uni.getStorageSync('IMUserID');
  561. //1 未登录 2 登录中 3 已登录
  562. const loginStatus = await IMSDK.asyncApi(IMSDK.IMMethods.GetLoginStatus, IMSDK.uuid());
  563. console.log("qxj loginStatus:"+loginStatus);
  564. if (loginStatus === 3) {
  565. initStore();
  566. return;
  567. }
  568. //callingModule?.initModule();
  569. let platformID=5
  570. // #ifdef H5
  571. platformID=5
  572. // #endif
  573. // #ifdef MP-WEIXIN
  574. platformID=6
  575. // #endif
  576. console.log("qxj platformID:"+platformID);
  577. if (IMToken && IMUserID) {
  578. IMSDK.asyncApi(IMSDK.IMMethods.Login, IMSDK.uuid(), {
  579. userID: IMUserID,
  580. token: IMToken,
  581. platformID:platformID,
  582. apiAddr: config.getApiUrl(),
  583. wsAddr: config.getWsUrl(),
  584. logLevel: 1,
  585. }).then(initStore).catch((err) => {
  586. console.log('qxj initStore error:' + JSON.stringify(err));
  587. uni.removeStorage({ key: 'IMToken' });
  588. });
  589. } else{
  590. this.checkLogin()
  591. }
  592. },
  593. async newMessageNotify(newServerMsg) {
  594. if (this.storeIsSyncing) {
  595. return;
  596. }
  597. const disableNotify = uni.getStorageSync(`${this.storeCurrentUserID}_DisableNotify`);
  598. if (disableNotify || this.storeSelfInfo.globalRecvMsgOpt !== MessageReceiveOptType.Nomal) {
  599. return;
  600. }
  601. let cveItem = [...this.storeConversationList, ...cacheConversationList].find((conversation) => {
  602. if (newServerMsg.sessionType === SessionType.WorkingGroup) {
  603. return newServerMsg.groupID === conversation.groupID;
  604. }
  605. return newServerMsg.sendID === conversation.userID;
  606. });
  607. if (!cveItem) {
  608. try {
  609. const { data } = await IMSDK.asyncApi(IMSDK.IMMethods.GetOneConversation, IMSDK.uuid(), {
  610. sourceID: newServerMsg.groupID || newServerMsg.sendID,
  611. sessionType: newServerMsg.sessionType
  612. });
  613. cveItem = data;
  614. cacheConversationList = [...cacheConversationList, data];
  615. } catch (e) {
  616. return;
  617. }
  618. }
  619. if (cveItem.recvMsgOpt !== MessageReceiveOptType.Nomal) {
  620. return;
  621. }
  622. // uni.createPushMessage({
  623. // content: `${newServerMsg.senderNickname}: ${parseMessageByType(newServerMsg)}`,
  624. // payload: {
  625. // sessionType: newServerMsg.sessionType,
  626. // sourceID: newServerMsg.groupID || newServerMsg.sendID,
  627. // }
  628. // });
  629. // const notificationFun = () => {
  630. // const isSelf = newServerMsg.sendID === this.$store.getters.storeCurrentUserID;
  631. // if (isSelf) return;
  632. // const isSingle = newServerMsg.groupID ? false : true;
  633. // console.log(this.storeGroupList, newServerMsg);
  634. // const group = this.storeGroupList.filter((group) => group.groupID === newServerMsg.groupID);
  635. // const title = isSingle ? newServerMsg.senderNickname : group[0].groupName;
  636. // const desc = parseMessageByType(newServerMsg);
  637. // console.log('notification', title, desc);
  638. // notification.showNotice(0, title, desc, () => {
  639. // prepareConversationState(cveItem);
  640. // });
  641. // };
  642. // notificationFun();
  643. // const platform = uni.getSystemInfoSync().platform;
  644. // if (platform == 'ios') {
  645. // if (this.storeSelfInfo.allowVibration === 1) {
  646. // plus.device.vibrate();
  647. // }
  648. // if (this.storeSelfInfo.allowBeep === 1) {
  649. // innerAudioContext.play();
  650. // // plus.device.beep();
  651. // }
  652. // } else if (platform == 'android') {
  653. // if (this.storeSelfInfo.allowVibration === 1) {
  654. // plus.device.vibrate(500);
  655. // }
  656. // if (this.storeSelfInfo.allowBeep === 1) {
  657. // let main = plus.android.runtimeMainActivity();
  658. // let RingtoneManager = plus.android.importClass('android.media.RingtoneManager');
  659. // let uri = RingtoneManager.getActualDefaultRingtoneUri(main, RingtoneManager.TYPE_NOTIFICATION);
  660. // let MediaPlayer = plus.android.importClass('android.media.MediaPlayer');
  661. // let player = MediaPlayer.create(main, uri);
  662. // player.setLooping(false);
  663. // player.prepare();
  664. // player.start();
  665. // }
  666. // }
  667. },
  668. handleNewMessage(newServerMsg) {
  669. console.log("---qxj newServerMsg");
  670. console.log(newServerMsg);
  671. if (this.inCurrentConversation(newServerMsg)) {
  672. const isSingleMessage = newServerMsg.sessionType === SessionType.Single;
  673. if (isSingleMessage) {
  674. uni.$u.throttle(() => uni.$emit(PageEvents.OnlineStateCheck), 2000);
  675. if(newServerMsg.ex!=null&&newServerMsg.ex!=''){
  676. var json=JSON.parse(newServerMsg.ex);
  677. this.$store.commit("timStore/setType",json.type);
  678. this.$store.commit("timStore/setImType", json.imType);
  679. this.$store.commit("timStore/setOrderId",json.orderId);
  680. this.$store.commit("timStore/setOrderType",json.orderType);
  681. this.$store.commit("timStore/setFollowId",json.followId);
  682. if(json.type==="finishInquiry"){
  683. this.$store.commit("timStore/setImType", 0);
  684. uni.navigateTo({ url: "/pages_order/pingOrder?orderId="+json.orderId })
  685. }
  686. else if(json.type==="startInquiry"){
  687. }
  688. else if(json.type==="inquiry"){
  689. }
  690. else if(json.type==="startFollow"){
  691. }
  692. else if(json.type==="follow"){
  693. }
  694. else if(json.type==="finishFollow"){
  695. }
  696. else if(json.type==="startDrugReport"){
  697. }
  698. else if(json.type==="finishDrugReport"){
  699. }
  700. else if(json.type==="drugReport"){
  701. }
  702. }
  703. }
  704. if (newServerMsg.contentType === MessageType.TypingMessage) {
  705. if (isSingleMessage) {
  706. uni.$emit(PageEvents.TypingUpdate);
  707. }
  708. }
  709. else {
  710. if (newServerMsg.contentType === MessageType.RevokeMessage) {
  711. }
  712. else {
  713. newServerMsg.isAppend = true;
  714. this.pushNewMessage(newServerMsg);
  715. setTimeout(() => uni.$emit(PageEvents.ScrollToBottom, true));
  716. }
  717. uni.$u.debounce(this.markConversationAsRead, 2000);
  718. }
  719. }
  720. else {
  721. if (newServerMsg.contentType !== MessageType.TypingMessage) {
  722. console.log("---qxj not inCurrentConversation");
  723. uni.$u.throttle(() => this.newMessageNotify(newServerMsg), 500);
  724. setTimeout(() => {
  725. this.$store.dispatch('conversation/getUnReadCount');
  726. },500);
  727. }
  728. }
  729. },
  730. inCurrentConversation(newServerMsg) {
  731. switch (newServerMsg.sessionType) {
  732. case SessionType.Single:
  733. return (
  734. newServerMsg.sendID === this.storeCurrentConversation.userID ||
  735. (newServerMsg.sendID === this.storeCurrentUserID && newServerMsg.recvID === this.storeCurrentConversation.userID)
  736. );
  737. case SessionType.WorkingGroup:
  738. return newServerMsg.groupID === this.storeCurrentConversation.groupID;
  739. case SessionType.Notification:
  740. return newServerMsg.sendID === this.storeCurrentConversation.userID;
  741. default:
  742. return false;
  743. }
  744. },
  745. markConversationAsRead() {
  746. IMSDK.asyncApi(IMSDK.IMMethods.MarkConversationMessageAsRead, IMSDK.uuid(), this.storeCurrentConversation.conversationID);
  747. },
  748. removeImData(){
  749. uni.removeStorage({ key: 'IMToken' });
  750. uni.removeStorage({ key: 'IMUserID' });
  751. },
  752. getRuntimePlatform() {
  753. const systemInfo = uni.getSystemInfoSync();
  754. const compilePlatform = process.env.UNI_PLATFORM;
  755. //1:iOS,2:Android,3:Windows,4:OSX,5:WEB,6:小程序,7:linux,8:AndroidPad,9:IPad,10:Admin
  756. let platformType=5;
  757. // H5 环境
  758. if (compilePlatform === 'h5') platformType= 5;
  759. // 小程序环境
  760. if (compilePlatform.startsWith('mp-')) {
  761. const mpType = compilePlatform.split('-')[1]; // 如 weixin/alipay
  762. platformType=6;
  763. }
  764. // App 环境
  765. if (compilePlatform === 'app-plus') {
  766. if(systemInfo.platform.toLowerCase() === 'android'){
  767. platformType=2;
  768. }
  769. if(systemInfo.platform.toLowerCase() === 'ios'){
  770. platformType=1;
  771. }
  772. }
  773. console.log("----qxj platformType:"+platformType);
  774. uni.showToast({ title:" platformType:"+platformType,icon:'none', duration: 2000 });
  775. return platformType;
  776. },
  777. getDicts(){
  778. getDicts().then(
  779. res => {
  780. if(res.code==200){
  781. uni.setStorageSync('dicts',JSON.stringify(res));
  782. }
  783. },
  784. rej => {}
  785. );
  786. },
  787. }
  788. };
  789. </script>
  790. <style lang="scss">
  791. @import "@/assets/css/theme.scss";
  792. /*每个页面公共css */
  793. // #ifdef VUE3
  794. @import "@/uni_modules/uview-plus/index.scss";
  795. // #endif
  796. // #ifndef VUE3
  797. @import "uview-ui/index.scss";
  798. // #endif
  799. view{
  800. box-sizing: border-box;
  801. }
  802. .ellipsis{
  803. overflow: hidden;
  804. text-overflow: ellipsis;
  805. white-space: nowrap;
  806. }
  807. .ellipsis2{
  808. overflow:hidden;
  809. text-overflow:ellipsis;
  810. display:-webkit-box;
  811. -webkit-box-orient:vertical;
  812. -webkit-line-clamp:2;
  813. }
  814. .no-data-box{
  815. box-sizing: border-box;
  816. width: 100%;
  817. padding: 200rpx 50rpx;
  818. text-align: center;
  819. flex-direction: column;
  820. justify-content: center;
  821. align-items: center;
  822. image{
  823. width: 200upx;
  824. height: 150upx;
  825. }
  826. .empty-title{
  827. margin-top: 20rpx;
  828. font-size: 28rpx;
  829. color: #bbbbbb;
  830. }
  831. }
  832. .doctor-box{
  833. margin-top: 15rpx;
  834. padding: 20rpx 0rpx 0rpx;
  835. display: flex;
  836. flex-direction: column;
  837. align-items: flex-start;
  838. justify-content: flex-start;
  839. .doctor{
  840. width: 100%;
  841. margin-bottom: 15rpx;
  842. background: #fff;
  843. padding: 15rpx;
  844. display: flex;
  845. flex-direction: column;
  846. align-items: flex-start;
  847. justify-content: flex-start;
  848. &:last-child{
  849. margin-bottom: 0rpx;
  850. }
  851. .item{
  852. width: 100%;
  853. display: flex;
  854. align-items: flex-start;
  855. justify-content: flex-start;
  856. .left{
  857. .head-box{
  858. width:92rpx;
  859. height:92rpx;
  860. position: relative;
  861. .isline{
  862. width:92rpx;
  863. height:92rpx;
  864. border-radius: 50%;
  865. border: 2rpx solid #2EDAD4;
  866. display: flex;
  867. align-items: center;
  868. justify-content: center;
  869. position: absolute;
  870. bottom: 0rpx;
  871. .img{
  872. position: absolute;
  873. bottom: 1rpx;
  874. width:75rpx;
  875. height:35rpx;
  876. image{
  877. width:75rpx;
  878. height:35rpx;
  879. }
  880. .name{
  881. width:75rpx;
  882. height:35rpx;
  883. bottom: -3rpx;
  884. text-align: center;
  885. position: absolute;
  886. font-size: 16upx;
  887. font-family: PingFang SC;
  888. font-weight: bold;
  889. color: #ffffff;
  890. }
  891. }
  892. }
  893. .doc-img{
  894. border-radius: 50%;
  895. width:100%;
  896. height:100%;
  897. }
  898. }
  899. }
  900. .right{
  901. width: calc(100% - 100rpx);
  902. margin-left: 20rpx;
  903. display: flex;
  904. flex-direction: column;
  905. align-items: flex-start;
  906. justify-content: flex-start;
  907. .doc-box{
  908. display: flex;
  909. align-items: center;
  910. justify-content: space-between;
  911. .doc-name{
  912. font-size: 32upx;
  913. font-family: PingFang SC;
  914. font-weight: bold;
  915. color: #111111;
  916. }
  917. .doc-position{
  918. margin-left: 16rpx;
  919. font-size: 26upx;
  920. font-weight: bold;
  921. font-family: PingFang SC;
  922. color: #2A2B2E;
  923. }
  924. .doc-dept{
  925. margin-left: 16rpx;
  926. font-size: 26upx;
  927. font-weight: bold;
  928. font-family: PingFang SC;
  929. color: #2A2B2E;
  930. }
  931. }
  932. .hospital-box{
  933. display: flex;
  934. align-items: center;
  935. justify-content: flex-start;
  936. margin-top: 10rpx;
  937. .tag{
  938. display: flex;
  939. align-items: center;
  940. justify-content: center;
  941. background-color: #4FC06B;
  942. border-radius: 10rpx;
  943. padding: 5rpx 10rpx;
  944. font-size: 20upx;
  945. font-weight: bold;
  946. font-family: PingFang SC;
  947. color: #ffffff;
  948. }
  949. .name{
  950. margin-left: 6rpx;
  951. font-size: 26upx;
  952. font-weight: bold;
  953. font-family: PingFang SC;
  954. color: #2A2B2E;
  955. }
  956. }
  957. .doc-spec{
  958. width: 100%;
  959. display: flex;
  960. align-items: center;
  961. justify-content: flex-start;
  962. margin-top: 15rpx;
  963. .spec{
  964. font-size: 26upx;
  965. font-family: PingFang SC;
  966. color: #626468;
  967. }
  968. }
  969. .doc-count{
  970. margin-top: 15rpx;
  971. display: flex;
  972. align-items: center;
  973. justify-content: flex-start;
  974. .name{
  975. font-size: 24upx;
  976. font-family: PingFang SC;
  977. color: #9B9B9B;
  978. }
  979. .count{
  980. margin: 0rpx 5rpx;
  981. font-size: 24upx;
  982. font-family: PingFang SC;
  983. color: #2A2B2E;
  984. }
  985. }
  986. .doc-price{
  987. width: 100%;
  988. margin-top: 15rpx;
  989. display: flex;
  990. align-items: center;
  991. justify-content: flex-start;
  992. .btn{
  993. display: flex;
  994. align-items: center;
  995. justify-content: center;
  996. background-color: #2583EB;
  997. padding: 15rpx 30rpx;
  998. border-radius: 30rpx;
  999. font-size: 26upx;
  1000. font-family: PingFang SC;
  1001. color: #fff;
  1002. }
  1003. }
  1004. }
  1005. }
  1006. }
  1007. }
  1008. </style>
  1009. <style lang="less">
  1010. /*每个页面公共css */
  1011. @import './assets/iconfont/iconfont.css';
  1012. @import './assets/css/common.less';
  1013. /* 全局flex样式 */
  1014. @import './common/css/flexCommon.css';
  1015. </style>