index.vue 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. <template>
  2. <view class="container">
  3. <mescroll-body ref="mescrollRef" @init="mescrollInit" @down="downCallback" @up="upCallback" :down="downOption" :up="upOption">
  4. <u-swipe-action ref="swipeWrapperRef" class="swipe_wrapper">
  5. <block v-if="keyword!=null && keyword.length>0">
  6. <conversation-item v-for="item in filteredList" :key="item.conversationID" @closeAllSwipe="closeAllSwipe" :source="item" ref="conversationItem" />
  7. </block>
  8. <block v-else>
  9. <conversation-item v-for="item in storeConversationList" :key="item.conversationID" @closeAllSwipe="closeAllSwipe" :source="item" ref="conversationItem" />
  10. </block>
  11. </u-swipe-action>
  12. </mescroll-body>
  13. <view class="loading_wrap" v-if="storeProgress > 0 && storeProgress < 100">
  14. <u-loading-icon :vertical="true" :text="storeProgress + '%'"></u-loading-icon>
  15. </view>
  16. </view>
  17. </template>
  18. <script>
  19. import { mapGetters } from 'vuex';
  20. // import ChatHeader from './components/ChatHeader.vue';
  21. import ConversationItem from './components/ConversationItem.vue';
  22. import MescrollMixin from '@/uni_modules/mescroll-uni/components/mescroll-uni/mescroll-mixins.js';
  23. export default {
  24. mixins: [MescrollMixin],
  25. components: {
  26. // ChatHeader,
  27. ConversationItem
  28. },
  29. data() {
  30. return {
  31. scrollTop: 0,
  32. old: {
  33. scrollTop: 0
  34. },
  35. lastClickTime: 0,
  36. doubleClick: 0,
  37. triggered: false,
  38. refreshing: false,
  39. keyword: '',
  40. mescroll: null,
  41. downOption: {
  42. //下拉刷新
  43. use: true,
  44. auto: false // 不自动加载 (mixin已处理第一个tab触发downCallback)
  45. },
  46. upOption: {
  47. onScroll: false,
  48. use: true, // 是否启用上拉加载; 默认true
  49. page: {
  50. pae: 0, // 当前页码,默认0,回调之前会加1,即callback(page)会从1开始
  51. size: 50 // 每页数据的数量,默认10
  52. },
  53. noMoreSize: 10, // 配置列表的总数量要大于等于5条才显示'-- END --'的提示
  54. textNoMore: '已经到底了',
  55. empty: {
  56. icon: 'https://bjyjb-1362704775.cos.ap-chongqing.myqcloud.com/app/newImages/empty_icon.png',
  57. tip: '暂无数据'
  58. }
  59. },
  60. filteredList:[],
  61. }
  62. },
  63. computed: {
  64. ...mapGetters(['storeConversationList', 'storeIsSyncing', 'storeProgress'])
  65. },
  66. onReady() {
  67. },
  68. onShow() {
  69. this.$store.dispatch('conversation/getUnReadCount');
  70. },
  71. onLoad() {
  72. // this._freshing = false;
  73. // this.triggered = true;
  74. // this.mescroll.resetUpScroll();
  75. },
  76. onTabItemTap(item) {
  77. const currentTime = Date.now();
  78. if (item.index == 0 && currentTime - this.lastClickTime < 300) {
  79. this.scrollToTop();
  80. } else {
  81. this.lastClickTime = currentTime;
  82. }
  83. },
  84. methods: {
  85. scroll(e) {
  86. this.old.scrollTop = e.detail.scrollTop;
  87. },
  88. scrollToTop() {
  89. const conversationItem = this.$refs.conversationItem;
  90. if (conversationItem) {
  91. uni.createSelectorQuery()
  92. .in(this)
  93. .select(`.conversation_item`)
  94. .boundingClientRect(async (rect) => {
  95. if (rect) {
  96. const itemHeight = rect.height;
  97. const index = await this.getNextUnReadIndex(itemHeight);
  98. const totalHeight = itemHeight * index;
  99. this.scrollTop = this.old.scrollTop;
  100. this.$nextTick(function () {
  101. this.scrollTop = totalHeight;
  102. });
  103. }
  104. }).exec();
  105. }
  106. },
  107. getNextUnReadIndex(itemHeight) {
  108. return new Promise((resolve) => {
  109. uni.createSelectorQuery()
  110. .in(this)
  111. .select('.scroll-view')
  112. .scrollOffset((res) => {
  113. let start = Math.ceil(res.scrollTop / itemHeight);
  114. if (res.scrollTop % itemHeight === 0) {
  115. start++;
  116. }
  117. this.doubleClick = this.storeConversationList.slice(0, start).filter((item) => item.unreadCount > 0).length;
  118. const unReadList = this.storeConversationList.filter((item) => item.unreadCount > 0);
  119. const current = unReadList[(this.doubleClick %= unReadList.length)];
  120. const index = this.storeConversationList.findIndex((item) => item.conversationID === current.conversationID);
  121. resolve(index);
  122. })
  123. .exec();
  124. });
  125. },
  126. onRefresh() {
  127. if (this._freshing) return;
  128. this._freshing = true;
  129. this.queryList(true);
  130. },
  131. onRestore() {
  132. this.triggered = 'restore';
  133. },
  134. scrolltolower() {
  135. this.queryList();
  136. },
  137. async queryList(isFirstPage = false) {
  138. await this.$store.dispatch('conversation/getConversationList', isFirstPage);
  139. this.triggered = false;
  140. this._freshing = false;
  141. },
  142. async queryListNew(page) {
  143. const list = await this.$store.dispatch('conversation/getConversationList', page.num==1);
  144. if(list.length>0){
  145. this.mescroll.endSuccess(list.length, list.length==page.size);
  146. }else{
  147. this.mescroll.endSuccess(list.length, false);
  148. }
  149. },
  150. mescrollInit(mescroll) {
  151. this.mescroll = mescroll;
  152. },
  153. /*下拉刷新的回调 */
  154. downCallback(mescroll) {
  155. mescroll.resetUpScroll();
  156. },
  157. upCallback(page) {
  158. //联网加载数据
  159. this.queryListNew(page);
  160. },
  161. toSearch() {
  162. if (!this.keyword) {
  163. this.filteredList = this.storeConversationList; // 如果关键词为空,显示全部
  164. return;
  165. }
  166. this.filteredList = this.storeConversationList.filter((item) => {
  167. // 检查 showName 是否包含关键词
  168. const showNameMatch = item.showName.toLowerCase().includes(this.keyword.toLowerCase());
  169. console.log(showNameMatch);
  170. // 检查 latestMsg 中 textElem 的 content 是否包含关键词
  171. const latestMsg = JSON.parse(item.latestMsg);
  172. const contentMatch =latestMsg.textElem && latestMsg.textElem.content.toLowerCase()
  173. .includes(this.keyword.toLowerCase());
  174. return showNameMatch || contentMatch;
  175. });
  176. //uni.$u.route("/pages_im/pages/common/globalSearch/index");
  177. },
  178. closeAllSwipe() {
  179. this.$refs.swipeWrapperRef.closeAll();
  180. }
  181. }
  182. };
  183. </script>
  184. <style lang="scss" scoped>
  185. .container {
  186. @include colBox(false);
  187. height: 100vh;
  188. width: 100%;
  189. overflow-y: hidden;
  190. box-sizing: border-box;
  191. background-repeat: no-repeat;
  192. background-size: 100%;
  193. position: relative;
  194. z-index: 2;
  195. background: #f5f7fa;
  196. .bg-img {
  197. position: absolute;
  198. width: 100%;
  199. height: 524rpx;
  200. top: 0;
  201. left: 0;
  202. right: 0;
  203. bottom: 0;
  204. z-index: 0;
  205. }
  206. }
  207. .search-cont {
  208. padding: 16upx 30upx;
  209. background-color: #ffffff;
  210. .inner {
  211. box-sizing: border-box;
  212. width: 100%;
  213. height: 72upx;
  214. background: #f7f7f7;
  215. border-radius: 36upx;
  216. display: flex;
  217. align-items: center;
  218. padding: 0 30upx;
  219. .icon-search {
  220. width: 28upx;
  221. height: 28upx;
  222. margin-right: 20upx;
  223. }
  224. input {
  225. height: 60upx;
  226. line-height: 60upx;
  227. flex: 1;
  228. }
  229. }
  230. }
  231. .z-paging-content {
  232. flex: 1;
  233. }
  234. .swipe_wrapper {
  235. @include colBox(false);
  236. flex: 1;
  237. width: 100%;
  238. overflow-y: auto;
  239. }
  240. .scroll-view {
  241. height: 0;
  242. flex: 1;
  243. background: transparent;
  244. }
  245. .loading_wrap {
  246. position: absolute;
  247. top: 50%;
  248. left: 50%;
  249. transform: translate(-50%, -50%);
  250. }
  251. ::v-deep .u-swipe-action-item__right__button__wrapper__text {
  252. -webkit-line-clamp: 2 !important;
  253. max-width: 32px;
  254. }
  255. </style>