App.vue 32 KB

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