App.vue 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706
  1. <script>
  2. let WebIM = (wx.WebIM = require("./utils/WebIM")["default"]);
  3. let msgStorage = require("./components/chat/msgstorage");
  4. let msgType = require("./components/chat/msgtype");
  5. let disp = require("./utils/broadcast");
  6. let logout = false;
  7. function ack(receiveMsg) {
  8. // 处理未读消息回执
  9. var bodyId = receiveMsg.id; // 需要发送已读回执的消息id
  10. var ackMsg = new WebIM.message("read", WebIM.conn.getUniqueId());
  11. ackMsg.set({
  12. id: bodyId,
  13. to: receiveMsg.from,
  14. });
  15. WebIM.conn.send(ackMsg.body);
  16. }
  17. function onMessageError(err) {
  18. if (err.type === "error") {
  19. uni.showToast({
  20. title: err.errorText,
  21. });
  22. return false;
  23. }
  24. return true;
  25. }
  26. function getCurrentRoute() {
  27. let pages = getCurrentPages();
  28. if (pages.length > 0) {
  29. let currentPage = pages[pages.length - 1];
  30. return currentPage.route;
  31. }
  32. return "/";
  33. }
  34. // 包含陌生人版本
  35. function calcUnReadSpot(message) {
  36. let myName = uni.getStorageSync("myUsername");
  37. uni.getStorageInfo({
  38. success: function (res) {
  39. let storageKeys = res.keys;
  40. let newChatMsgKeys = [];
  41. let historyChatMsgKeys = [];
  42. storageKeys.forEach((item) => {
  43. if (item.indexOf(myName) > -1 && item.indexOf("rendered_") == -1) {
  44. newChatMsgKeys.push(item);
  45. }
  46. });
  47. let count = newChatMsgKeys.reduce(function (result, curMember, idx) {
  48. let chatMsgs;
  49. chatMsgs = uni.getStorageSync(curMember) || [];
  50. return result + chatMsgs.length;
  51. }, 0);
  52. getApp().globalData.unReadMessageNum = count;
  53. disp.fire("em.unreadspot", message);
  54. },
  55. });
  56. }
  57. function saveGroups() {
  58. var me = this;
  59. return WebIM.conn.getGroup({
  60. limit: 50,
  61. success: function (res) {
  62. uni.setStorage({
  63. key: "listGroup",
  64. data: res.data,
  65. });
  66. },
  67. error: function (err) {
  68. console.log(err);
  69. },
  70. });
  71. }
  72. import amap from '@/static/js/amap-wx.130.js'
  73. var amapPlugin = new amap.AMapWX({
  74. key: 'bb69713f3c3d3c85e2662d313daa47b9'
  75. });
  76. import webIM from './utils/WebIM.js'
  77. var that = ''
  78. export default {
  79. globalData: {
  80. unReadMessageNum: 0,
  81. userInfo: null,
  82. saveFriendList: [],
  83. saveGroupInvitedList: [],
  84. isIPX: false, //是否为iphone X
  85. conn: {
  86. closed: false,
  87. curOpenOpt: {},
  88. open(opt) {
  89. uni.showLoading({
  90. title: "正在初始化客户端..",
  91. mask: true,
  92. });
  93. this.curOpenOpt = opt;
  94. WebIM.conn.open(opt);
  95. this.closed = false;
  96. },
  97. reopen() {
  98. if (this.closed) {
  99. //this.open(this.curOpenOpt);
  100. WebIM.conn.open(this.curOpenOpt);
  101. this.closed = false;
  102. }
  103. },
  104. },
  105. onLoginSuccess: function(myName) {
  106. uni.hideLoading();
  107. uni.redirectTo({
  108. url: "../chat/chat?myName=" + myName,
  109. });
  110. },
  111. getUserInfo(cb) {
  112. var me = this;
  113. if (this.userInfo) {
  114. typeof cb == "function" && cb(this.userInfo);
  115. } else {
  116. // 调用登录接口
  117. uni.login({
  118. success() {
  119. uni.getUserInfo({
  120. success(res) {
  121. me.userInfo = res.userInfo;
  122. typeof cb == "function" && cb(me.userInfo);
  123. },
  124. });
  125. },
  126. });
  127. }
  128. },
  129. checkIsIPhoneX: function() {
  130. const me = this;
  131. uni.getSystemInfo({
  132. success: function(res) {
  133. // 根据 model 进行判断
  134. if (res.model && res.model.search("iPhone X") != -1) {
  135. me.isIPX = true;
  136. }
  137. },
  138. });
  139. },
  140. getLoca: function() {
  141. var city = uni.getStorageSync('city')
  142. return new Promise((resolve, reject) => {
  143. if(!city) {
  144. uni.authorize({
  145. scope: 'scope.userLocation',
  146. success() {
  147. uni.getLocation({
  148. type: 'wgs84',
  149. success(res) {
  150. amapPlugin.getRegeo({
  151. success(data) {
  152. console.log('获取当前所在位置',data[0].regeocodeData.addressComponent);
  153. uni.setStorageSync("location",data[0].regeocodeData.addressComponent)
  154. resolve(data)
  155. },
  156. fail(err) {
  157. console.log('err=',err)
  158. }
  159. })
  160. },
  161. fail(err){
  162. console.log('err=',err)
  163. }
  164. })
  165. },
  166. fail(err) {
  167. console.log('error',err)
  168. uni.showModal({
  169. title: '提示',
  170. content: '需要获取用户位置信息权限',
  171. confirmText: '前往设置',
  172. confirmColor: '#3CC51F',
  173. success(res) {
  174. if (res.confirm) {
  175. uni.openSetting(); // 打开小程序设置页面,可以让用户开启需要的权限
  176. }
  177. }
  178. })
  179. }
  180. })
  181. }
  182. })
  183. }
  184. },
  185. onLoad() {
  186. that = this
  187. },
  188. onLaunch: function() {
  189. console.log('App Launch')
  190. this.HXlogin()
  191. var me = this;
  192. var logs = uni.getStorageSync("logs") || [];
  193. logs.unshift(Date.now());
  194. uni.setStorageSync("logs", logs); //
  195. disp.on("em.main.ready", function() {
  196. calcUnReadSpot();
  197. });
  198. disp.on("em.chatroom.leave", function() {
  199. calcUnReadSpot();
  200. });
  201. disp.on("em.chat.session.remove", function() {
  202. calcUnReadSpot();
  203. });
  204. disp.on("em.chat.audio.fileLoaded", function() {
  205. calcUnReadSpot();
  206. });
  207. disp.on("em.main.deleteFriend", function() {
  208. calcUnReadSpot();
  209. });
  210. disp.on("em.chat.audio.fileLoaded", function() {
  211. calcUnReadSpot();
  212. }); //
  213. WebIM.conn.listen({
  214. onOpened(message) {
  215. console.log('>>>>>>环信登录成功啦')
  216. },
  217. onReconnect() {
  218. /* uni.showToast({
  219. title: "重连中...",
  220. duration: 2000,
  221. }); */
  222. },
  223. onSocketConnected() {
  224. /* uni.showToast({
  225. title: "socket连接成功",
  226. duration: 2000,
  227. }); */
  228. },
  229. onClosed() {
  230. /* uni.showToast({
  231. title: "网络已断开",
  232. icon: "none",
  233. duration: 2000,
  234. }); */
  235. uni.redirectTo({
  236. url: "/pages/login/codeLogin/codeLogin",
  237. });
  238. me.globalData.conn.closed = true;
  239. WebIM.conn.close();
  240. },
  241. onInviteMessage(message) {
  242. me.globalData.saveGroupInvitedList.push(message);
  243. disp.fire("em.invite.joingroup", message); // uni.showModal({
  244. // title: message.from + " 已邀你入群 " + message.roomid,
  245. // success(){
  246. // disp.fire("em.invite.joingroup", message);
  247. // },
  248. // error(){
  249. // disp.fire("em.invite.joingroup", message);
  250. // }
  251. // });
  252. },
  253. onReadMessage(message) {
  254. //console.log('已读', message)
  255. },
  256. //onPresence为旧版 ,建议参考最新增删好友api文档 :http://docs-im.easemob.com/im/web/basics/buddy
  257. onPresence(message) {
  258. switch (message.type) {
  259. case "unsubscribe":
  260. break;
  261. // 好友邀请列表
  262. case "subscribe":
  263. for (let i = 0; i < me.globalData.saveFriendList.length; i++) {
  264. if (me.globalData.saveFriendList[i].from === message.from) {
  265. me.globalData.saveFriendList[i] = message;
  266. disp.fire("em.subscribe");
  267. return;
  268. }
  269. }
  270. msgStorage.saveReceiveMsg(message, 'INFORM'); //存添加好友消息,方便展示通知
  271. me.globalData.saveFriendList.push(message);
  272. disp.fire("em.subscribe");
  273. break;
  274. case "subscribed":
  275. /* uni.showToast({
  276. title: "添加成功",
  277. duration: 1000,
  278. }); */
  279. disp.fire("em.subscribed");
  280. break;
  281. case "unsubscribed":
  282. disp.fire("em.unsubscribed");
  283. break;
  284. case "direct_joined":
  285. saveGroups();
  286. /* uni.showToast({
  287. title: "已进群",
  288. duration: 1000,
  289. }); */
  290. break;
  291. case "memberJoinPublicGroupSuccess":
  292. saveGroups();
  293. /* uni.showToast({
  294. title: "已进群",
  295. duration: 1000,
  296. }); */
  297. break;
  298. case "invite":
  299. // 防止重复添加
  300. for (let i = 0; i < me.globalData.saveGroupInvitedList.length; i++) {
  301. if (me.globalData.saveGroupInvitedList[i].from === message.from) {
  302. me.globalData.saveGroupInvitedList[i] = message;
  303. disp.fire("em.invite.joingroup")
  304. return;
  305. }
  306. }
  307. me.globalData.saveGroupInvitedList.push(message);
  308. disp.fire("em.invite.joingroup");
  309. msgStorage.saveReceiveMsg(message, 'INFORM'); //存添加好友消息,方便展示通知
  310. break;
  311. case "unavailable":
  312. disp.fire("em.contacts.remove");
  313. disp.fire("em.group.leaveGroup", message);
  314. break;
  315. case "deleteGroupChat":
  316. disp.fire("em.invite.deleteGroup", message);
  317. break;
  318. case "leaveGroup":
  319. disp.fire("em.group.leaveGroup", message);
  320. break;
  321. case "removedFromGroup":
  322. disp.fire("em.group.leaveGroup", message);
  323. break;
  324. default:
  325. break;
  326. }
  327. },
  328. onRoster(message) {
  329. // let pages = getCurrentPages();
  330. // if(pages[0]){
  331. // pages[0].onShow();
  332. // }
  333. },
  334. onVideoMessage(message) {
  335. console.log("onVideoMessage: ", message);
  336. if (message) {
  337. msgStorage.saveReceiveMsg(message, msgType.VIDEO);
  338. }
  339. calcUnReadSpot(message);
  340. ack(message);
  341. },
  342. onAudioMessage(message) {
  343. console.log("onAudioMessage", message);
  344. if (message) {
  345. if (onMessageError(message)) {
  346. msgStorage.saveReceiveMsg(message, msgType.AUDIO);
  347. }
  348. calcUnReadSpot(message);
  349. ack(message);
  350. }
  351. },
  352. onCmdMessage(message) {
  353. console.log("onCmdMessage", message);
  354. if (message) {
  355. if (onMessageError(message)) {
  356. msgStorage.saveReceiveMsg(message, msgType.CMD);
  357. }
  358. calcUnReadSpot(message);
  359. ack(message);
  360. }
  361. },
  362. // onLocationMessage(message){
  363. // console.log("Location message: ", message);
  364. // if(message){
  365. // msgStorage.saveReceiveMsg(message, msgType.LOCATION);
  366. // }
  367. // },
  368. onTextMessage(message) {
  369. console.log("onTextMessage", message);
  370. if (message) {
  371. if (onMessageError(message)) {
  372. msgStorage.saveReceiveMsg(message, msgType.TEXT);
  373. }
  374. calcUnReadSpot(message);
  375. ack(message);
  376. }
  377. },
  378. onEmojiMessage(message) {
  379. console.log("onEmojiMessage", message);
  380. if (message) {
  381. if (onMessageError(message)) {
  382. msgStorage.saveReceiveMsg(message, msgType.EMOJI);
  383. }
  384. calcUnReadSpot(message);
  385. ack(message);
  386. }
  387. },
  388. onPictureMessage(message) {
  389. console.log("onPictureMessage", message);
  390. if (message) {
  391. if (onMessageError(message)) {
  392. msgStorage.saveReceiveMsg(message, msgType.IMAGE);
  393. }
  394. calcUnReadSpot(message);
  395. ack(message);
  396. }
  397. },
  398. onFileMessage(message) {
  399. console.log("onFileMessage", message);
  400. if (message) {
  401. if (onMessageError(message)) {
  402. msgStorage.saveReceiveMsg(message, msgType.FILE);
  403. }
  404. calcUnReadSpot(message);
  405. ack(message);
  406. }
  407. },
  408. // 各种异常
  409. onError(error) {
  410. console.log(error); // 16: server-side close the websocket connection
  411. // if (error.type == WebIM.statusCode.WEBIM_CONNCTION_DISCONNECTED) {
  412. // // if(error.type == WebIM.statusCode.WEBIM_CONNCTION_DISCONNECTED && !logout){
  413. // // if(WebIM.conn.autoReconnectNumTotal < WebIM.conn.autoReconnectNumMax){
  414. // // return;
  415. // // }
  416. // uni.showToast({
  417. // title: "websocket 断开",
  418. // duration: 1000
  419. // });
  420. // uni.redirectTo({
  421. // url: "../login/login"
  422. // });
  423. // logout = true;
  424. // return;
  425. // } // 8: offline by multi login
  426. // if (error.type == WebIM.statusCode.WEBIM_CONNCTION_SERVER_ERROR) {
  427. // uni.showToast({
  428. // title: "offline by multi login",
  429. // duration: 1000
  430. // });
  431. // uni.redirectTo({
  432. // url: "../login/login"
  433. // });
  434. // }
  435. if (error.type == WebIM.statusCode.WEBIM_CONNCTION_OPEN_ERROR) {
  436. uni.hideLoading();
  437. disp.fire("em.error.passwordErr"); // uni.showModal({
  438. // title: "用户名或密码错误",
  439. // confirmText: "OK",
  440. // showCancel: false
  441. // });
  442. }
  443. if (error.type == WebIM.statusCode.WEBIM_CONNCTION_AUTH_ERROR) {
  444. uni.hideLoading();
  445. disp.fire("em.error.tokenErr");
  446. }
  447. if (error.type == "socket_error") {
  448. ///sendMsgError
  449. console.log("socket_errorsocket_error", error);
  450. /* uni.showToast({
  451. title: "网络已断开",
  452. icon: "none",
  453. duration: 2000,
  454. }); */
  455. disp.fire("em.error.sendMsgErr", error);
  456. }
  457. },
  458. });
  459. this.globalData.checkIsIPhoneX();
  460. },
  461. onShow: function() {
  462. console.log('App Show')
  463. },
  464. onHide: function() {
  465. console.log('App Hide')
  466. },
  467. methods: {
  468. /* HXlisten(){
  469. console.log('<<<<<<环信监听',uni.WebIM)
  470. uni.WebIM.conn.listen({
  471. onOpened: function () {
  472. console.log('>>>>>>环信登录成功啦')
  473. }, //连接成功回调
  474. onClosed: function () {
  475. console.log("<<<<<连接关闭");
  476. }, //连接关闭回调
  477. onTextMessage: function ( message ) {
  478. console.log("收到文本消息",message);
  479. }, //收到文本消息
  480. onEmojiMessage: function ( message ) {
  481. console.log("收到表情消息",message);
  482. }, //收到表情消息
  483. onPictureMessage: function ( message ) {
  484. console.log("收到图片消息",message);
  485. }, //收到图片消息
  486. onCmdMessage: function ( message ) {
  487. console.log("收到命令消息",message);
  488. }, //收到命令消息
  489. onAudioMessage: function ( message ) {
  490. console.log("收到音频消息",message);
  491. }, //收到音频消息
  492. onLocationMessage: function ( message ) {
  493. console.log("收到位置消息",message);
  494. },//收到位置消息
  495. onFileMessage: function ( message ) {
  496. console.log("收到文件消息",message);
  497. }, //收到文件消息
  498. onCustomMessage: function ( message ) {
  499. console.log("收到自定义消息",message);
  500. }, //收到自定义消息
  501. onVideoMessage: function (message) {
  502. var node = document.getElementById('privateVideo');
  503. var option = {
  504. url: message.url,
  505. headers: {
  506. 'Accept': 'audio/mp4'
  507. },
  508. onFileDownloadComplete: function (response) {
  509. var objectURL = uni.WebIM.utils.parseDownloadResponse.call(conn, response);
  510. node.src = objectURL;
  511. },
  512. onFileDownloadError: function () {
  513. console.log('File down load error.')
  514. }
  515. };
  516. uni.WebIM.utils.download.call(conn, option);
  517. }, //收到视频消息
  518. onPresence: function ( message ) {
  519. console.log('处理“广播”或“发布-订阅”消息',message);
  520. }, //处理“广播”或“发布-订阅”消息,如联系人订阅请求、处理群组、聊天室被踢解散等消息
  521. onRoster: function ( message ) {
  522. console.log('处理好友申请',message);
  523. }, //处理好友申请
  524. onInviteMessage: function ( message ) {
  525. console.log('处理群组邀请',message);
  526. }, //处理群组邀请
  527. onOnline: function () {
  528. console.log('本机网络连接成功');
  529. }, //本机网络连接成功
  530. onOffline: function () {
  531. console.log("本机网络掉线",message);
  532. }, //本机网络掉线
  533. onError: function ( message ) {
  534. console.log("失败回调:",message);
  535. }, //失败回调
  536. onBlacklistUpdate: function (list) { //黑名单变动
  537. // 查询黑名单,将好友拉黑,将好友从黑名单移除都会回调这个函数,list则是黑名单现有的所有好友信息
  538. console.log(list);
  539. },
  540. onRecallMessage: function(message){
  541. console.log("收到撤回消息回调",message);
  542. }, //收到撤回消息回调
  543. onReceivedMessage: function(message){
  544. console.log("收到消息送达服务器回执",message);
  545. }, //收到消息送达服务器回执
  546. onDeliveredMessage: function(message){
  547. console.log("收到消息送达客户端回执",message);
  548. }, //收到消息送达客户端回执
  549. onReadMessage: function(message){
  550. console.log("收到消息已读回执",message);
  551. }, //收到消息已读回执
  552. onCreateGroup: function(message){
  553. console.log("创建群组成功回执",message);
  554. }, //创建群组成功回执(需调用createGroupNew)
  555. onMutedMessage: function(message){
  556. console.log("禁言",message);
  557. }, //如果用户在A群组被禁言,在A群发消息会走这个回调并且消息不会传递给群其它成员
  558. onChannelMessage: function(message){
  559. console.log("收到整个会话已读的回执",message);
  560. } //收到整个会话已读的回执,在对方发送channel ack时会在这个回调里收到消息
  561. });
  562. }, */
  563. HXlogin() {
  564. var userId = uni.getStorageSync('myUsername')
  565. var options = {
  566. user: userId,
  567. pwd : '12345678',
  568. appKey: uni.WebIM.config.appkey,
  569. success: function() {
  570. var lianjie = uni.WebIM.conn.isOpened()
  571. var my = uni.getStorageSync("myUsername");
  572. uni.setStorageSync('myUsername',my)
  573. },
  574. error: function() {
  575. }
  576. }
  577. uni.WebIM.conn.open(options);
  578. }
  579. }
  580. }
  581. </script>
  582. <style lang="scss">
  583. /*每个页面公共css */
  584. @import "uview-ui/index.scss";
  585. .content {
  586. background-color: #ffffff;
  587. width: 100%;
  588. min-height: 100vh;
  589. display: flex;
  590. flex-direction: column;
  591. font-size: 28rpx;
  592. color: #333;
  593. box-sizing: border-box;
  594. }
  595. .hflex {
  596. display: flex;
  597. flex-direction: row;
  598. flex-wrap: nowrap;
  599. }
  600. .vflex {
  601. display: flex;
  602. flex-direction: column;
  603. flex-wrap: nowrap;
  604. }
  605. .jbetween {
  606. justify-content: space-between;
  607. }
  608. .jaround {
  609. justify-content: space-around;
  610. }
  611. .jend {
  612. justify-content: flex-end;
  613. }
  614. .jcenter {
  615. justify-content: center;
  616. }
  617. .acenter {
  618. align-items: center;
  619. }
  620. .abetween {
  621. align-content: space-between;
  622. }
  623. .astart {
  624. align-items: flex-start;
  625. }
  626. .aend {
  627. align-items: flex-end;
  628. }
  629. .fwrap {
  630. flex-wrap: wrap;
  631. }
  632. .text_hide {
  633. overflow: hidden;
  634. white-space: nowrap;
  635. text-overflow: ellipsis;
  636. }
  637. .text_hide2 {
  638. text-overflow: -o-ellipsis-lastline;
  639. overflow: hidden;
  640. text-overflow: ellipsis;
  641. display: -webkit-box;
  642. -webkit-line-clamp: 2;
  643. line-clamp: 2;
  644. -webkit-box-orient: vertical;
  645. }
  646. </style>