App.vue 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101
  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. .myotctxt {
  815. display: inline-block;
  816. background-color: #37E2EA;
  817. font-family: PingFang SC, PingFang SC;
  818. font-weight: 500;
  819. font-size: 24rpx;
  820. color: #FFFFFF;
  821. padding: 2rpx 14rpx;
  822. border-radius: 6rpx;
  823. }
  824. .no-data-box{
  825. box-sizing: border-box;
  826. width: 100%;
  827. padding: 200rpx 50rpx;
  828. text-align: center;
  829. flex-direction: column;
  830. justify-content: center;
  831. align-items: center;
  832. image{
  833. width: 200upx;
  834. height: 150upx;
  835. }
  836. .empty-title{
  837. margin-top: 20rpx;
  838. font-size: 28rpx;
  839. color: #bbbbbb;
  840. }
  841. }
  842. .doctor-box{
  843. margin-top: 15rpx;
  844. padding: 20rpx 0rpx 0rpx;
  845. display: flex;
  846. flex-direction: column;
  847. align-items: flex-start;
  848. justify-content: flex-start;
  849. .doctor{
  850. width: 100%;
  851. margin-bottom: 15rpx;
  852. background: #fff;
  853. padding: 15rpx;
  854. display: flex;
  855. flex-direction: column;
  856. align-items: flex-start;
  857. justify-content: flex-start;
  858. &:last-child{
  859. margin-bottom: 0rpx;
  860. }
  861. .item{
  862. width: 100%;
  863. display: flex;
  864. align-items: flex-start;
  865. justify-content: flex-start;
  866. .left{
  867. .head-box{
  868. width:92rpx;
  869. height:92rpx;
  870. position: relative;
  871. .isline{
  872. width:92rpx;
  873. height:92rpx;
  874. border-radius: 50%;
  875. border: 2rpx solid #2EDAD4;
  876. display: flex;
  877. align-items: center;
  878. justify-content: center;
  879. position: absolute;
  880. bottom: 0rpx;
  881. .img{
  882. position: absolute;
  883. bottom: 1rpx;
  884. width:75rpx;
  885. height:35rpx;
  886. image{
  887. width:75rpx;
  888. height:35rpx;
  889. }
  890. .name{
  891. width:75rpx;
  892. height:35rpx;
  893. bottom: -3rpx;
  894. text-align: center;
  895. position: absolute;
  896. font-size: 16upx;
  897. font-family: PingFang SC;
  898. font-weight: bold;
  899. color: #ffffff;
  900. }
  901. }
  902. }
  903. .doc-img{
  904. border-radius: 50%;
  905. width:100%;
  906. height:100%;
  907. }
  908. }
  909. }
  910. .right{
  911. width: calc(100% - 100rpx);
  912. margin-left: 20rpx;
  913. display: flex;
  914. flex-direction: column;
  915. align-items: flex-start;
  916. justify-content: flex-start;
  917. .doc-box{
  918. display: flex;
  919. align-items: center;
  920. justify-content: space-between;
  921. .doc-name{
  922. font-size: 32upx;
  923. font-family: PingFang SC;
  924. font-weight: bold;
  925. color: #111111;
  926. }
  927. .doc-position{
  928. margin-left: 16rpx;
  929. font-size: 26upx;
  930. font-weight: bold;
  931. font-family: PingFang SC;
  932. color: #2A2B2E;
  933. }
  934. .doc-dept{
  935. margin-left: 16rpx;
  936. font-size: 26upx;
  937. font-weight: bold;
  938. font-family: PingFang SC;
  939. color: #2A2B2E;
  940. }
  941. }
  942. .hospital-box{
  943. display: flex;
  944. align-items: center;
  945. justify-content: flex-start;
  946. margin-top: 10rpx;
  947. .tag{
  948. display: flex;
  949. align-items: center;
  950. justify-content: center;
  951. background-color: #4FC06B;
  952. border-radius: 10rpx;
  953. padding: 5rpx 10rpx;
  954. font-size: 20upx;
  955. font-weight: bold;
  956. font-family: PingFang SC;
  957. color: #ffffff;
  958. }
  959. .name{
  960. margin-left: 6rpx;
  961. font-size: 26upx;
  962. font-weight: bold;
  963. font-family: PingFang SC;
  964. color: #2A2B2E;
  965. }
  966. }
  967. .doc-spec{
  968. width: 100%;
  969. display: flex;
  970. align-items: center;
  971. justify-content: flex-start;
  972. margin-top: 15rpx;
  973. .spec{
  974. font-size: 26upx;
  975. font-family: PingFang SC;
  976. color: #626468;
  977. }
  978. }
  979. .doc-count{
  980. margin-top: 15rpx;
  981. display: flex;
  982. align-items: center;
  983. justify-content: flex-start;
  984. .name{
  985. font-size: 24upx;
  986. font-family: PingFang SC;
  987. color: #9B9B9B;
  988. }
  989. .count{
  990. margin: 0rpx 5rpx;
  991. font-size: 24upx;
  992. font-family: PingFang SC;
  993. color: #2A2B2E;
  994. }
  995. }
  996. .doc-price{
  997. width: 100%;
  998. margin-top: 15rpx;
  999. display: flex;
  1000. align-items: center;
  1001. justify-content: flex-start;
  1002. .btn{
  1003. display: flex;
  1004. align-items: center;
  1005. justify-content: center;
  1006. background-color: #2583EB;
  1007. padding: 15rpx 30rpx;
  1008. border-radius: 30rpx;
  1009. font-size: 26upx;
  1010. font-family: PingFang SC;
  1011. color: #fff;
  1012. }
  1013. }
  1014. }
  1015. }
  1016. }
  1017. }
  1018. </style>
  1019. <style lang="less">
  1020. /*每个页面公共css */
  1021. @import './assets/iconfont/iconfont.css';
  1022. @import './assets/css/common.less';
  1023. /* 全局flex样式 */
  1024. @import './common/css/flexCommon.css';
  1025. </style>