chat.vue 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628
  1. <template>
  2. <view>
  3. <u-navbar
  4. title="客服消息"
  5. @leftClick="leftClick"
  6. :autoBack="true"
  7. :placeholder="true"
  8. >
  9. </u-navbar>
  10. <!-- <view>
  11. <view class="search" v-if="search_btn">
  12. <view @tap="openSearch">
  13. <icon type="search" size="12"></icon>
  14. <text>搜索</text>
  15. </view>
  16. </view>
  17. </view> -->
  18. <view class="chat_list_wraper">
  19. <scroll-view scroll-y="true"
  20. :class="'chat_list_wraper ' + (gotop ? (isIPX ? 'goTopX' : 'goTop') : 'goback')"
  21. :style="'padding-bottom: ' + (isIPX ? '270rpx' : '226rpx')">
  22. <view class="search_input" v-if="search_chats">
  23. <view>
  24. <icon type="search" size="12"></icon>
  25. <input placeholder="搜索" placeholder-style="color:#9B9B9B;line-height:21px;font-size:15px;"
  26. auto-focus confirm-type="search" type="text" @confirm="onSearch" @input="onInput"
  27. :value="input_code" />
  28. <icon type="clear" size="12" @tap.stop="clearInput" v-if="show_clear"></icon>
  29. </view>
  30. <text @tap="cancel">取消</text>
  31. </view>
  32. <view v-for="(item, index) in arr" :key="index" class="chat_list" :data-item="item" @tap.stop="del_chat"
  33. @longpress="longpress">
  34. <swipe-delete>
  35. <view class="tap_mask" @tap.stop="into_chatRoom" :data-item="item">
  36. <!-- 消息列表 -->
  37. <view class="list_box">
  38. <view class="list_left" :data-username="item.your.nickname">
  39. <view class="list_pic">
  40. <view class="em-msgNum"
  41. v-if="item.unReadCount > 0 || item.unReadCount == '99+'">
  42. {{ item.unReadCount }}</view>
  43. <image :src="item.your.avatarurl?item.your.avatarurl:'/static/images/theme2x.png'"></image>
  44. </view>
  45. <view class="list_text">
  46. <text class="list_user text_hide">{{item.your.nickname?item.your.nickname:item.username}}</text>
  47. <text class="list_word" v-if="item.msg.data[0].data">{{
  48. item.msg.data[0].data
  49. }}</text>
  50. <text class="list_word" v-if="item.msg.type == 'img'">[图片]</text>
  51. <text class="list_word" v-if="item.msg.type == 'audio'">[语音]</text>
  52. <!-- <text class="list_word" v-if="item.msg.type == 'video'"
  53. >[视频]</text
  54. > -->
  55. </view>
  56. </view>
  57. <view class="list_right">
  58. <text :data-username="item.username">{{ item.time }}</text>
  59. </view>
  60. </view>
  61. </view>
  62. </swipe-delete>
  63. </view>
  64. <long-press-modal :winSize="winSize" :popButton="popButton" @change="pickerMenuChange"
  65. :showPop="showPop" @hidePop="hidePop" :popStyle="popStyle" />
  66. <view v-if="!arr" class="chat_noChat">
  67. <image class="ctbg" src="/static/images/ctbg.png"></image>
  68. 暂无聊天消息
  69. </view>
  70. <!-- </view> -->
  71. </scroll-view>
  72. <!-- bug: margin-bottom 不生效 需要加一个空标签-->
  73. <view style="height: 1px"></view>
  74. <view class="mask" @tap="close_mask" v-if="show_mask"></view>
  75. <!-- <view :class="isIPX ? 'chatRoom_tab_X' : 'chatRoom_tab'"> -->
  76. <!-- <view class="tableBar">
  77. <view v-if="unReadSpotNum > 0 || unReadSpotNum == '99+'"
  78. :class="'em-unread-spot ' +(unReadSpotNum == '99+' ? 'em-unread-spot-litleFont' : '')">
  79. {{ unReadSpotNum == '99+'?unReadSpotNum:unReadSpotNum+ unReadTotalNotNum }}</view>
  80. <image :class="unReadSpotNum > 0 || unReadSpotNum == '99+' ? 'haveSpot' : ''"
  81. src="@/static/images/sessionhighlight2x.png"></image>
  82. <text class="activeText">消息</text>
  83. </view>
  84. <view class="tableBar" @tap="tab_contacts">
  85. <image src="/static/images/comtacts2x.png"></image>
  86. <text>联系人</text>
  87. </view> -->
  88. <!-- <view class="tableBar" @tap="tab_notification">
  89. <view v-if="unReadTotalNotNum > 0" class="em-unread-spot">{{
  90. unReadTotalNotNum
  91. }}</view>
  92. <image
  93. :class="unReadTotalNotNum > 0 ? 'haveSpot' : ''"
  94. src="/static/images/notice.png"
  95. ></image>
  96. <text>通知</text>
  97. </view> -->
  98. <!-- <view class="tableBar" @tap="tab_setting">
  99. <image src="/static/images/setting2x.png"></image>
  100. <text>我的</text>
  101. </view> -->
  102. <!-- </view> -->
  103. </view>
  104. </view>
  105. </template>
  106. <script>
  107. let disp = require("@/utils/broadcast");
  108. var WebIM = require("@/utils/WebIM")["default"];
  109. let isfirstTime = true;
  110. import swipeDelete from "@/components/swipedelete/swipedelete";
  111. import longPressModal from "@/components/longPressModal/index";
  112. export default {
  113. data() {
  114. return {
  115. search_btn: true,
  116. search_chats: false,
  117. show_mask: false,
  118. yourname: "",
  119. unReadSpotNum: 0,
  120. unReadNoticeNum: 0,
  121. messageNum: 0,
  122. unReadTotalNotNum: 0,
  123. arr: [],
  124. show_clear: false,
  125. member: "",
  126. isIPX: false,
  127. gotop: false,
  128. input_code: "",
  129. groupName: {},
  130. winSize: {},
  131. popButton: ["删除该聊天"],
  132. showPop: false,
  133. popStyle: "",
  134. currentVal: ''
  135. };
  136. },
  137. components: {
  138. swipeDelete,
  139. longPressModal,
  140. },
  141. props: {},
  142. onLoad() {
  143. this.getWindowSize();
  144. let me = this;
  145. //监听加好友申请
  146. disp.on("em.subscribe", function() {
  147. me.getChatList();
  148. /* me.setData({
  149. messageNum: getApp().globalData.saveFriendList.length,
  150. unReadTotalNotNum: getApp().globalData.saveFriendList.length +
  151. getApp().globalData.saveGroupInvitedList.length,
  152. }); */
  153. });
  154. //监听解散群
  155. disp.on("em.invite.deleteGroup", function() {
  156. me.listGroups();
  157. me.getRoster();
  158. me.getChatList();
  159. me.messageNum= getApp().globalData.saveFriendList.length
  160. });
  161. //监听未读消息数
  162. disp.on("em.unreadspot", function(message) {
  163. me.getChatList();
  164. me.unReadSpotNum= getApp().globalData.unReadMessageNum > 99 ?
  165. "99+" :
  166. getApp().globalData.unReadMessageNum
  167. });
  168. //监听未读加群“通知”
  169. disp.on("em.invite.joingroup", function() {
  170. me.unReadNoticeNum= getApp().globalData.saveGroupInvitedList.length
  171. me.unReadTotalNotNum= getApp().globalData.saveFriendList.length +
  172. getApp().globalData.saveGroupInvitedList.length
  173. });
  174. disp.on("em.contacts.remove", function() {
  175. me.getChatList();
  176. me.getRoster();
  177. });
  178. this.getRoster();
  179. },
  180. onShow: function() {
  181. uni.hideHomeButton();
  182. this.getChatList();
  183. this.unReadSpotNum =
  184. getApp().globalData.unReadMessageNum > 99 ?
  185. "99+" :
  186. getApp().globalData.unReadMessageNum
  187. this.messageNum = getApp().globalData.saveFriendList.length
  188. this.unReadNoticeNum = getApp().globalData.saveGroupInvitedList.length
  189. this.unReadTotalNotNum =
  190. getApp().globalData.saveFriendList.length +
  191. getApp().globalData.saveGroupInvitedList.length
  192. if (getApp().globalData.isIPX) {
  193. this.isIPX = true
  194. }
  195. },
  196. methods: {
  197. listGroups() {
  198. var me = this;
  199. return WebIM.conn.getGroup({
  200. limit: 50,
  201. success: function(res) {
  202. let groupName = {};
  203. let listGroup = res.data || [];
  204. listGroup.forEach((item) => {
  205. groupName[item.groupid] = item.groupname;
  206. });
  207. me.groupName= groupName,
  208. uni.setStorage({
  209. key: "listGroup",
  210. data: res.data,
  211. });
  212. me.getChatList();
  213. },
  214. error: function(err) {
  215. console.log(err);
  216. },
  217. });
  218. },
  219. getRoster() {
  220. let me = this;
  221. let rosters = {
  222. success(roster) {
  223. var member = [];
  224. for (let i = 0; i < roster.length; i++) {
  225. if (roster[i].subscription == "both") {
  226. member.push(roster[i]);
  227. }
  228. }
  229. uni.setStorage({
  230. key: "member",
  231. data: member,
  232. });
  233. me.member= member
  234. me.listGroups();
  235. //if(!systemReady){
  236. disp.fire("em.main.ready");
  237. //systemReady = true;
  238. //}
  239. me.arr= me.getChatList(),
  240. me.unReadSpotNum= getApp().globalData.unReadMessageNum > 99 ?
  241. "99+" :
  242. getApp().globalData.unReadMessageNum
  243. },
  244. error(err) {
  245. console.log(err);
  246. },
  247. };
  248. WebIM.conn.getRoster(rosters);
  249. },
  250. // 包含陌生人版本
  251. getChatList() {
  252. var myName = uni.getStorageSync("myUsername");
  253. var array = [];
  254. const me = this;
  255. uni.getStorageInfo({
  256. success: function(res) {
  257. let storageKeys = res.keys;
  258. let newChatMsgKeys = [];
  259. let historyChatMsgKeys = [];
  260. let len = myName.length;
  261. storageKeys.forEach((item) => {
  262. if (item.slice(-len) == myName && item.indexOf("rendered_") == -1) {
  263. newChatMsgKeys.push(item);
  264. } else if (
  265. item.slice(-len) == myName &&
  266. item.indexOf("rendered_") > -1
  267. ) {
  268. historyChatMsgKeys.push(item);
  269. } else if (item === "INFORM") {
  270. newChatMsgKeys.push(item);
  271. }
  272. });
  273. cul.call(me, newChatMsgKeys, historyChatMsgKeys);
  274. },
  275. });
  276. function cul(newChatMsgKeys, historyChatMsgKeys) {
  277. let array = [];
  278. let lastChatMsg;
  279. for (let i = historyChatMsgKeys.length; i > 0, i--;) {
  280. let index = newChatMsgKeys.indexOf(historyChatMsgKeys[i].slice(9));
  281. if (index > -1) {
  282. let newChatMsgs = uni.getStorageSync(newChatMsgKeys[index]) || [];
  283. if (newChatMsgKeys.includes()) {}
  284. if (newChatMsgs.length) {
  285. lastChatMsg = newChatMsgs[newChatMsgs.length - 1];
  286. lastChatMsg.unReadCount = newChatMsgs.length;
  287. if (lastChatMsg.unReadCount > 99) {
  288. lastChatMsg.unReadCount = "99+";
  289. }
  290. let dateArr = lastChatMsg.time.split(" ")[0].split("-");
  291. let timeArr = lastChatMsg.time.split(" ")[1].split(":");
  292. let month = dateArr[2] < 10 ? "0" + dateArr[2] : dateArr[2];
  293. lastChatMsg.dateTimeNum = `${dateArr[1]}${month}${timeArr[0]}${timeArr[1]}${timeArr[2]}`;
  294. lastChatMsg.time = `${dateArr[1]}月${dateArr[2]}日 ${timeArr[0]}:${timeArr[1]}`;
  295. newChatMsgKeys.splice(index, 1);
  296. } else {
  297. let historyChatMsgs = uni.getStorageSync(historyChatMsgKeys[i]);
  298. if (historyChatMsgs.length) {
  299. lastChatMsg = historyChatMsgs[historyChatMsgs.length - 1];
  300. let dateArr = lastChatMsg.time.split(" ")[0].split("-");
  301. let timeArr = lastChatMsg.time.split(" ")[1].split(":");
  302. let month = dateArr[2] < 10 ? "0" + dateArr[2] : dateArr[2];
  303. lastChatMsg.dateTimeNum =
  304. `${dateArr[1]}${month}${timeArr[0]}${timeArr[1]}${timeArr[2]}`;
  305. lastChatMsg.time = `${dateArr[1]}月${dateArr[2]}日 ${timeArr[0]}:${timeArr[1]}`;
  306. }
  307. }
  308. } else {
  309. let historyChatMsgs = uni.getStorageSync(historyChatMsgKeys[i]);
  310. if (historyChatMsgs.length) {
  311. lastChatMsg = historyChatMsgs[historyChatMsgs.length - 1];
  312. let dateArr = lastChatMsg.time.split(" ")[0].split("-");
  313. let timeArr = lastChatMsg.time.split(" ")[1].split(":");
  314. let month = dateArr[2] < 10 ? "0" + dateArr[2] : dateArr[2];
  315. lastChatMsg.dateTimeNum = `${dateArr[1]}${month}${timeArr[0]}${timeArr[1]}${timeArr[2]}`;
  316. lastChatMsg.time = `${dateArr[1]}月${dateArr[2]}日 ${timeArr[0]}:${timeArr[1]}`;
  317. }
  318. }
  319. if (
  320. lastChatMsg &&
  321. (lastChatMsg.chatType == "groupchat" ||
  322. lastChatMsg.chatType == "chatRoom")
  323. ) {
  324. lastChatMsg.groupName = me.groupName[lastChatMsg.info.to];
  325. }
  326. lastChatMsg && lastChatMsg.username != myName &&
  327. array.push(lastChatMsg);
  328. }
  329. for (let i = newChatMsgKeys.length; i > 0, i--;) {
  330. let newChatMsgs = uni.getStorageSync(newChatMsgKeys[i]) || [];
  331. if (newChatMsgs.length) {
  332. lastChatMsg = newChatMsgs[newChatMsgs.length - 1];
  333. lastChatMsg.unReadCount = newChatMsgs.length;
  334. if (lastChatMsg.unReadCount > 99) {
  335. lastChatMsg.unReadCount = "99+";
  336. }
  337. let dateArr = lastChatMsg.time.split(" ")[0].split("-");
  338. let timeArr = lastChatMsg.time.split(" ")[1].split(":");
  339. let month = dateArr[2] < 10 ? "0" + dateArr[2] : dateArr[2];
  340. lastChatMsg.dateTimeNum = `${dateArr[1]}${month}${timeArr[0]}${timeArr[1]}${timeArr[2]}`;
  341. lastChatMsg.time = `${dateArr[1]}月${dateArr[2]}日 ${timeArr[0]}:${timeArr[1]}`;
  342. if (
  343. lastChatMsg.chatType == "groupchat" ||
  344. lastChatMsg.chatType == "chatRoom"
  345. ) {
  346. lastChatMsg.groupName = me.groupName[lastChatMsg.info.to];
  347. }
  348. lastChatMsg.username != myName && array.push(lastChatMsg);
  349. }
  350. }
  351. array.sort((a, b) => {
  352. return b.dateTimeNum - a.dateTimeNum;
  353. });
  354. this.arr= array
  355. console.log(this.arr);
  356. }
  357. },
  358. openSearch: function() {
  359. this.search_btn= false
  360. this.search_chats= true
  361. this.gotop= true
  362. },
  363. onSearch: function(val) {
  364. let searchValue = val.detail.value;
  365. var myName = uni.getStorageSync("myUsername");
  366. const me = this;
  367. let serchList = [];
  368. let arr = [];
  369. uni.getStorageInfo({
  370. success: function(res) {
  371. let storageKeys = res.keys;
  372. let chatKeys = [];
  373. let len = myName.length;
  374. storageKeys.forEach((item) => {
  375. if (item.slice(-len) == myName) {
  376. chatKeys.push(item);
  377. }
  378. });
  379. chatKeys.forEach((item, index) => {
  380. if (item.indexOf(searchValue) != -1) {
  381. serchList.push(item);
  382. }
  383. });
  384. let lastChatMsg = "";
  385. serchList.forEach((item, index) => {
  386. let chatMsgs = uni.getStorageSync(item) || [];
  387. if (chatMsgs.length) {
  388. lastChatMsg = chatMsgs[chatMsgs.length - 1];
  389. let dateArr = lastChatMsg.time.split(" ")[0].split("-");
  390. let timeArr = lastChatMsg.time.split(" ")[1].split(":");
  391. let month = dateArr[2] < 10 ? "0" + dateArr[2] : dateArr[2];
  392. lastChatMsg.dateTimeNum =
  393. `${dateArr[1]}${month}${timeArr[0]}${timeArr[1]}${timeArr[2]}`;
  394. lastChatMsg.time =
  395. `${dateArr[1]}月${dateArr[2]}日 ${timeArr[0]}:${timeArr[1]}`;
  396. arr.push(lastChatMsg);
  397. }
  398. });
  399. me.arr = arr
  400. },
  401. });
  402. },
  403. leftClick() {},
  404. cancel: function() {
  405. this.getChatList();
  406. this.search_btn= true
  407. this.search_chats= false
  408. //arr: this.getChatList(),
  409. this.unReadSpotNum= getApp().globalData.unReadMessageNum > 99 ? "99+" : getApp().globalData.unReadMessageNum
  410. this.gotop= false
  411. },
  412. clearInput: function() {
  413. this.input_code= ""
  414. this.show_clear= false
  415. },
  416. onInput: function(e) {
  417. let inputValue = e.detail.value;
  418. if (inputValue) {
  419. this.show_clear= true
  420. } else {
  421. this.show_clear= false
  422. }
  423. },
  424. tab_contacts: function() {
  425. uni.redirectTo({
  426. url: "../main/main?myName=" + uni.getStorageSync("myUsername"),
  427. });
  428. },
  429. close_mask: function() {
  430. this.search_btn= true
  431. this.search_chats= false
  432. this.show_mask= false
  433. },
  434. tab_setting: function() {
  435. uni.redirectTo({
  436. url: "../setting/setting",
  437. });
  438. },
  439. tab_notification: function() {
  440. uni.redirectTo({
  441. url: "../notification/notification",
  442. });
  443. },
  444. into_chatRoom: function(event) {
  445. let detail = event.currentTarget.dataset.item;
  446. if (
  447. detail.chatType == "groupchat" ||
  448. detail.chatType == "chatRoom" ||
  449. detail.groupName
  450. ) {
  451. this.into_groupChatRoom(detail);
  452. } else {
  453. this.into_singleChatRoom(detail);
  454. }
  455. },
  456. // 单聊
  457. into_singleChatRoom: function(detail) {
  458. var my = uni.getStorageSync("myUsername");
  459. var nameList = {
  460. myName: my,
  461. your: detail.username,
  462. };
  463. uni.navigateTo({
  464. url: "/pages/chatroom/chatroom?username=" + JSON.stringify(nameList),
  465. });
  466. },
  467. // 群聊 和 聊天室 (两个概念)
  468. into_groupChatRoom: function(detail) {
  469. var my = uni.getStorageSync("myUsername");
  470. var nameList = {
  471. myName: my,
  472. your: detail.groupName,
  473. groupId: detail.info.to,
  474. };
  475. uni.navigateTo({
  476. url: "../groupChatRoom/groupChatRoom?username=" + JSON.stringify(nameList),
  477. });
  478. },
  479. into_inform: function() {
  480. uni.redirectTo({
  481. url: "../notification/notification",
  482. });
  483. },
  484. removeAndRefresh: function(event) {
  485. let removeId = event.currentTarget.dataset.item.info.from
  486. let ary = getApp().globalData.saveFriendList
  487. let idx
  488. if (ary.length > 0) {
  489. ary.forEach((v, k) => {
  490. if (v.from == removeId) {
  491. idx = k
  492. }
  493. })
  494. getApp().globalData.saveFriendList.splice(idx, 1);
  495. }
  496. uni.removeStorageSync('INFORM')
  497. },
  498. del_chat: function(event) {
  499. let detail = event.currentTarget.dataset.item;
  500. let nameList = {};
  501. let me = this;
  502. // 删除当前选中群组聊天列表
  503. if (detail.chatType == "groupchat" || detail.chatType == "chatRoom") {
  504. nameList = {
  505. your: detail.info.to,
  506. };
  507. //删除当前选中通知列表
  508. } else if (detail.chatType === "INFORM") {
  509. nameList = {
  510. your: "INFORM",
  511. };
  512. }
  513. //删除当前选中好友聊天列表
  514. else {
  515. nameList = {
  516. your: detail.username,
  517. };
  518. }
  519. var myName = uni.getStorageSync("myUsername");
  520. var currentPage = getCurrentPages();
  521. uni.showModal({
  522. title: "确认删除?",
  523. confirmText: "删除",
  524. success: function(res) {
  525. if (res.confirm) {
  526. uni.removeStorageSync(nameList.your + myName);
  527. uni.removeStorageSync("rendered_" + nameList.your + myName);
  528. nameList.your === 'INFORM' && me.removeAndRefresh(event);
  529. // if (Object.keys(currentPage[0]).length>0) {
  530. // currentPage[0].onShow();
  531. // }
  532. disp.fire("em.chat.session.remove");
  533. me.getChatList();
  534. }
  535. },
  536. fail: function(err) {
  537. console.log('删除列表', err);
  538. },
  539. });
  540. },
  541. longpress: function(e) {
  542. //将当前选中的值存在data中方便后续操作
  543. this.currentVal = e
  544. let [touches, style, index] = [e.touches[0], "", e.currentTarget.dataset.index, ];
  545. /* 因 非H5端不兼容 style 属性绑定 Object ,所以拼接字符 */
  546. if (touches.clientY > this.winSize.height / 2) {
  547. style = `bottom:${this.winSize.height - touches.clientY}px;`;
  548. } else {
  549. style = `top:${touches.clientY}px;`;
  550. }
  551. if (touches.clientX > this.winSize.witdh / 2) {
  552. style += `right:${this.winSize.witdh - touches.clientX}px`;
  553. } else {
  554. style += `left:${touches.clientX}px`;
  555. }
  556. this.popStyle = style;
  557. // this.pickerUserIndex = Number(index);
  558. this.showShade = true;
  559. this.$nextTick(() => {
  560. setTimeout(() => {
  561. this.showPop = true;
  562. }, 10);
  563. });
  564. },
  565. /* 获取窗口尺寸 */
  566. getWindowSize() {
  567. uni.getSystemInfo({
  568. success: (res) => {
  569. this.winSize = {
  570. witdh: res.windowWidth,
  571. height: res.windowHeight,
  572. };
  573. },
  574. });
  575. },
  576. hidePop() {
  577. this.showPop = false;
  578. },
  579. pickerMenuChange() {
  580. console.log("当前选中>>", this.currentVal);
  581. this.del_chat(this.currentVal)
  582. },
  583. },
  584. };
  585. </script>
  586. <style>
  587. @import "./chat.css";
  588. </style>