index.vue 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422
  1. <template>
  2. <view>
  3. <!-- <em-chat /> -->
  4. <z-paging
  5. ref="paging"
  6. v-model="dataList"
  7. use-chat-record-mode
  8. :default-page-size="20"
  9. :safe-area-inset-bottom="true"
  10. @query="queryList"
  11. use-page-scroll
  12. >
  13. <template #top>
  14. <em-chat-navbar :targetId="targetId" :chatType="chatType" />
  15. </template>
  16. <!-- 聊天item,:id="`z-paging-${index}`"必须加 -->
  17. <view
  18. class="click_more_history_box"
  19. v-if="isLoadingLocalMsgList"
  20. @click="onClickLoadMore"
  21. >如无更多,试试点击加载更多</view
  22. >
  23. <view
  24. v-for="(msgBody, index) in dataList"
  25. :key="msgBody.id"
  26. :id="'mid' + msgBody.id"
  27. >
  28. <em-message-list-container
  29. ref="emMessageListComps"
  30. v-show="
  31. isShowMessageItem(msgBody) &&
  32. msgBody.type !== MESSAGE_TYPE.GRAY_INFORM
  33. "
  34. :msgBody="msgBody"
  35. :isNeedShowMessageTime="isNeedShowMessageTime(msgBody, index)"
  36. :quoteMsgId="quoteMsgId"
  37. @alertMessagePopup="alertMessagePopup"
  38. @scrollToQuoteMessge="scrollToQuoteMessge"
  39. />
  40. <!-- 灰色系统通知类型消息 -->
  41. <em-gray-message-container
  42. v-show="
  43. !isShowMessageItem(msgBody) ||
  44. msgBody.type === MESSAGE_TYPE.GRAY_INFORM
  45. "
  46. :msgBody="msgBody"
  47. @reEditTextMessage="reEditTextMessage"
  48. />
  49. </view>
  50. <!-- 底部聊天输入框 -->
  51. <template #bottom>
  52. <em-input-bar-container
  53. ref="emInputBarComps"
  54. @resetScrollHeight="resetScrollHeight"
  55. :checkedPopupMsgBody="checkedPopupMsgBody"
  56. />
  57. <em-message-popup
  58. ref="emMessagePopupComps"
  59. @callReplyMessage="callReplyMessage"
  60. @callEditMessage="callEditMessage"
  61. />
  62. </template>
  63. </z-paging>
  64. </view>
  65. </template>
  66. <script>
  67. import EmChatNavbar from "./emChatNavbar";
  68. import EmMessageListContainer from "./emMessageListContainer";
  69. import EmInputBarContainer from "./emInputBarContainer";
  70. import EmGrayMessageContainer from "./emGrayMessageContainer";
  71. import EmMessagePopup from "./emMessagePopup";
  72. import { CHAT_TYPE, MESSAGE_STATUS } from "@/EaseIM/constant";
  73. import { EVENT_BUS_NAME } from "@/constant";
  74. import { MESSAGE_TYPE } from "../../EaseIM/constant";
  75. import { ZPaging } from "@/uni_modules/z-paging/components/z-paging/z-paging";
  76. export default {
  77. components: {
  78. EmChatNavbar,
  79. EmMessageListContainer,
  80. EmInputBarContainer,
  81. EmGrayMessageContainer,
  82. EmMessagePopup,
  83. ZPaging
  84. },
  85. data() {
  86. return {
  87. MESSAGE_STATUS,
  88. MESSAGE_TYPE,
  89. targetId: "",
  90. chatType: "",
  91. //v-model绑定的这个变量不要在分页请求结束中自己赋值!!!
  92. dataList: [],
  93. isLoadingLocalMsgList: false,
  94. checkedPopupMsgBody: {}, //当msg popup弹起时选中的消息体
  95. quoteMsgId: "",
  96. };
  97. },
  98. onLoad(option) {
  99. console.log(option);
  100. this.targetId = option.targetId;
  101. this.chatType = option.chatType;
  102. this.$store.commit("SET_CHATING_USER_INFO", {
  103. targetId: this.targetId,
  104. chatType: this.chatType,
  105. });
  106. },
  107. onPageScroll(e) {
  108. //更新z-paging内部scrollTop
  109. this.$refs.paging.updatePageScrollTop(e.scrollTop);
  110. //如果滚动到顶部,触发加载更多聊天记录
  111. if (e.scrollTop < 10) {
  112. this.$refs.paging.doChatRecordLoadMore();
  113. }
  114. },
  115. provide() {
  116. return {
  117. targetId: () => this.targetId,
  118. chatType: () => this.chatType,
  119. };
  120. },
  121. mounted() {
  122. uni.$on(
  123. EVENT_BUS_NAME.EASEIM_MESSAGE_COLLECTION_UPDATE,
  124. this.appentNewMessage
  125. );
  126. uni.$on(
  127. EVENT_BUS_NAME.EASEIM_MESSAGE_COLLECTION_DELETE,
  128. this.onDeleteMessage
  129. );
  130. uni.$on(
  131. EVENT_BUS_NAME.EASEIM_MESSAGE_COLLECTION_MODIFY,
  132. this.onModifyMessage
  133. );
  134. },
  135. computed: {
  136. joinedGroupList() {
  137. return this.$store.state.GroupStore.joinedGroupList;
  138. },
  139. friendUserInfoCollection() {
  140. return this.$store.getters.friendUserInfoCollection;
  141. },
  142. messageList() {
  143. return this.$store.state.MessageStore.messageCollection[this.targetId];
  144. },
  145. messageCollectionStatus() {
  146. return this.$store.getters.messageStatusCollection;
  147. },
  148. //recall delete 两种消息状态不展示对应消息item
  149. isShowMessageItem() {
  150. return (msgBody) => {
  151. if (!msgBody.id) return false;
  152. if (
  153. this.messageCollectionStatus &&
  154. this.messageCollectionStatus[msgBody.id] === MESSAGE_STATUS.DELETE
  155. ) {
  156. return false;
  157. } else if (
  158. this.messageCollectionStatus &&
  159. this.messageCollectionStatus[msgBody.id] === MESSAGE_STATUS.RECALL
  160. ) {
  161. return false;
  162. } else {
  163. return true;
  164. }
  165. };
  166. },
  167. //两条消息之差大于5min,方可展示消息时间。
  168. isNeedShowMessageTime() {
  169. return (msgBody, index) => {
  170. const { time } = msgBody;
  171. if (index !== 0) {
  172. const lastTime = this.dataList[index - 1]?.time;
  173. if (time - lastTime > 300000) {
  174. return true;
  175. } else {
  176. return false;
  177. }
  178. } else {
  179. return true;
  180. }
  181. };
  182. },
  183. },
  184. watch: {
  185. messageList() {
  186. console.log(">>>>监听到消息列表变化");
  187. this.$store.dispatch("updateConversationLastMsg", {
  188. conversationId: this.targetId,
  189. });
  190. },
  191. },
  192. methods: {
  193. getGroupName(groupid) {
  194. let groupName = "";
  195. if (this.joinedGroupList.length) {
  196. this.joinedGroupList.forEach((item) => {
  197. if (item.groupid === groupid) {
  198. console.log(item.groupname);
  199. return (groupName = item.groupname);
  200. }
  201. });
  202. console.log("groupName", groupName);
  203. return groupName;
  204. } else {
  205. return groupid;
  206. }
  207. },
  208. getTheIdName(targetId, chatType) {
  209. if (chatType === CHAT_TYPE.SINGLE_CHAT) {
  210. const friendInfo = this.friendUserInfoCollection[targetId];
  211. return friendInfo?.nickname || targetId;
  212. }
  213. if (chatType === CHAT_TYPE.GROUP_CHAT) {
  214. return this.getGroupName(targetId);
  215. }
  216. switch (chatType) {
  217. case CHAT_TYPE.SINGLE_CHAT:
  218. const friendInfo = this.friendUserInfoCollection[targetId];
  219. friendInfo?.nickname || targetId;
  220. break;
  221. case CHAT_TYPE.GROUP_CHAT:
  222. console.log(">>>>>>> Group");
  223. this.getGroupName(targetId);
  224. break;
  225. default:
  226. return null;
  227. }
  228. },
  229. async queryList(pageNo, pageSize, from) {
  230. /* from 0.用户主动下拉刷新 1.通过reload触发 2.通过refresh触发 3.通过滚动到底部加载更多或点击底部加载更多触发) */
  231. console.log(pageNo, pageSize, from);
  232. /* 初始化时获取数据 */
  233. if (from === 1) {
  234. if (!this.messageList?.length) {
  235. try {
  236. const messages = await this.getMoreHistoryMessages();
  237. this.$refs.paging.complete([...messages]);
  238. //补充滚动置底,防止图片消息撑开内容导致,未滚动置底
  239. setTimeout(() => {
  240. this.$refs.paging.scrollToBottom();
  241. }, 500);
  242. } catch (error) {
  243. console.log("漫游加载失败", error);
  244. this.$refs.paging.complete(false);
  245. }
  246. } else {
  247. /* 设置本地分页,请求结束(成功或者失败)调用此方法,将请求的结果传递给z-paging作分页处理 */
  248. this.isLoadingLocalMsgList = true;
  249. this.$refs.paging.setLocalPaging([...this.messageList]);
  250. //补充滚动置底,防止图片消息撑开内容导致,未滚动置底
  251. setTimeout(() => {
  252. this.$refs.paging.scrollToBottom();
  253. }, 500);
  254. console.log(">>>>加载本地已有历史记录。");
  255. }
  256. }
  257. if (from === 2) {
  258. return;
  259. }
  260. /* 触顶加载更多消息时获取数据 */
  261. if (from === 3) {
  262. console.log(">>>>触顶加载更多");
  263. try {
  264. const messages = await this.getMoreHistoryMessages();
  265. this.$refs.paging.complete([...messages]);
  266. } catch (error) {
  267. console.log("漫游加载失败", error);
  268. this.$refs.paging.complete(false);
  269. }
  270. }
  271. },
  272. async getMoreHistoryMessages() {
  273. const params = {
  274. targetId: this.targetId,
  275. chatType: this.chatType,
  276. };
  277. return new Promise((resolve, reject) => {
  278. this.$store
  279. .dispatch("fetchHistroyMessageListFromServer", params)
  280. .then((res) => {
  281. resolve(res.messages);
  282. })
  283. .catch((err) => {
  284. console.log(err);
  285. reject(err);
  286. });
  287. });
  288. },
  289. //执行新增消息
  290. appentNewMessage(data) {
  291. console.log(">>>>>新消息添加", data);
  292. const { msgBody } = data;
  293. this.$refs.paging.addChatRecordData({
  294. ...msgBody,
  295. });
  296. },
  297. //监听删除消息更新当前list
  298. async onDeleteMessage() {
  299. this.isLoadingLocalMsgList = true;
  300. const res = await this.$refs.paging.setLocalPaging([...this.messageList]);
  301. },
  302. //监听编辑消息更新item
  303. onModifyMessage(data) {
  304. /**
  305. * @function updateChatRecordData
  306. * @description 此方法为自己往插件库中新增的一个方法,主要为更新本地分页数据中已存在的消息体。
  307. */
  308. // updateChatRecordData(data) {
  309. // if (!this.useChatRecordMode) return;
  310. // const _index = this.totalData.findIndex((o) => o.id === data.id);
  311. // _index >= 0 && (this.totalData[_index] = data);
  312. // }
  313. this.$refs.paging.updateChatRecordData(data);
  314. },
  315. async onClickLoadMore() {
  316. try {
  317. const messages = await this.getMoreHistoryMessages();
  318. if (messages.length) {
  319. this.$refs.paging.addDataFromTop([...messages]);
  320. this.$refs.paging.doChatRecordLoadMore();
  321. } else {
  322. this.isLoadingLocalMsgList = false;
  323. uni.showToast({
  324. title: "真的没有更多了",
  325. icon: "none",
  326. duration: 2000,
  327. });
  328. return;
  329. }
  330. } catch (error) {
  331. console.log("漫游加载失败", error);
  332. this.$refs.paging.complete(false);
  333. }
  334. },
  335. //重新编辑
  336. reEditTextMessage(msgContent) {
  337. this.$refs.emInputBarComps.appendReEditTextMessage(msgContent);
  338. },
  339. resetScrollHeight(height) {
  340. this.$nextTick(() => {
  341. this.$refs.paging.updatePageScrollTopHeight();
  342. console.log(this.scrollHeight);
  343. });
  344. },
  345. //弹出消息对应popup
  346. alertMessagePopup(msgBody) {
  347. this.$refs.emMessagePopupComps.alertMessagePopup(msgBody);
  348. this.checkedPopupMsgBody = msgBody;
  349. },
  350. //调起消息回复模式
  351. callReplyMessage() {
  352. this.$refs.emInputBarComps.onShowReplyMessageContainer();
  353. },
  354. callEditMessage(msgBody) {
  355. this.$refs.emInputBarComps.onShowEditMessageContainer(msgBody);
  356. },
  357. //滚动至引用消息所在位置
  358. scrollToQuoteMessge(msgQuote) {
  359. const { msgID } = msgQuote;
  360. if (msgID) {
  361. const dom = uni
  362. .createSelectorQuery()
  363. .in(this)
  364. .select("#mid" + msgID);
  365. dom
  366. .boundingClientRect((data) => {
  367. if (data) {
  368. this.$refs.paging.scrollIntoViewByNodeTop(data.top, 50);
  369. //闪烁该条引用消息
  370. this.setQuoteMessageId(msgID);
  371. } else {
  372. uni.showToast({
  373. icon: "none",
  374. title: "没有回复的消息",
  375. });
  376. }
  377. })
  378. .exec();
  379. }
  380. },
  381. //设置引用消息ID从而引起消息气泡闪烁
  382. setQuoteMessageId(quoteMsgId) {
  383. this.quoteMsgId = quoteMsgId;
  384. //引起子组件增加闪烁样式后,延时半秒自定清空设置的引用消息id
  385. setTimeout(() => {
  386. this.quoteMsgId = "";
  387. }, 500);
  388. },
  389. },
  390. onUnload() {
  391. //置空正在沟通中的用户信息
  392. this.$store.commit("SET_CHATING_USER_INFO", {});
  393. uni.$off(
  394. EVENT_BUS_NAME.EASEIM_MESSAGE_COLLECTION_UPDATE,
  395. this.appentNewMessage
  396. );
  397. uni.$off(
  398. EVENT_BUS_NAME.EASEIM_MESSAGE_COLLECTION_DELETE,
  399. this.onDeleteMessage
  400. );
  401. uni.$off(
  402. EVENT_BUS_NAME.EASEIM_MESSAGE_COLLECTION_MODIFY,
  403. this.onModifyMessage
  404. );
  405. },
  406. };
  407. </script>
  408. <style scoped>
  409. @import "./index.css";
  410. </style>