vant-list实现下拉加载更多

  1 <template>
  2   <div class="home-wrapper">
  3     <div class="swipe-box">
  4       <van-swipe :autoplay="3000">
  5         <van-swipe-item v-for="(image, index) in images" :key="index">
  6           <img v-lazy="image" class="swipe-img" />
  7         </van-swipe-item>
  8       </van-swipe>
  9     </div>
 10     <div class="tab-box">
 11       <div class="tab-box-header" :class="{'is-fixed': isFixed}">
 12         <van-tabs  v-model="currentType"  @click="selectTab" :ellipsis="false" :border="false" swipeable>
 13           <van-tab v-for="(item, idx) in tabList" :key="idx" :title="item.name"></van-tab>
 14         </van-tabs>
 15         <van-dropdown-menu>
 16           <van-dropdown-item v-model="todoType" :options="todoTypeList" @change="changeStatus" />
 17         </van-dropdown-menu>
 18       </div>
 19       <div class="tab-content" :class="{'is-fixed': isFixed}">
 20         <ul class="status-list" v-if="todoType !== 0">
 21           <li
 22             v-for="(item, index) in statusList"
 23             :key="index"
 24             :class="[{ active: currentStatus == item.workflowStatus }, 'status-item']"
 25             @click="selectStatusTab(item)"
 26           >{{ item.name }}</li>
 27         </ul>
 28         <van-pull-refresh v-model="refreshing" @refresh="onRefresh">
 29           <van-list :finished="finished"  @load="loadMore" class="todo-list" >
 30             <li class="todo-item" v-for="item in todoList" :key="item.id" @click="jumpDetail(item)">
 31               <div class="todo-top">
 32                 <div class="title-box">
 33                   <i class="icon-urgent" v-if="item.message && item.message.length > 0"></i>
 34                   <div class="app-name ">{{ item.menu_name }}</div>
 35                   <div class="app-title txt-ellipsis">{{ item.title }}</div>
 36                 </div>
 37                 <div class="content-box">
 38                   <div class="todo-container" :style="{color: computedColor(item).color, background: computedColor(item).bg}">
 39                     <span class="icon-qi" :style="{background: computedColor(item).color}">企</span> {{ item.spaceName }}
 40                   </div>
 41                   <div class="system-name">{{ item.systemName }}</div>
 42                 </div>
 43                 <div class="todo-launcher">{{item.start_handler}} 发起于 {{ item.created_at.substring(5, 16) }}</div>
 44               </div>
 45               <div class="todo-body">
 46                 <span class="update-time"> 更新于{{ item.update_at.substring(5, 16) }} </span>
 47                 <span class="node-name"> {{ item.step_title }} </span>
 48               </div>
 49             </li>
 50           </van-list>
 51         </van-pull-refresh>
 52         <div class="loading4" v-if="loading">
 53           <div class="three1"></div>
 54           <div class="three2"></div>
 55           <div class="three3"></div>
 56         </div>
 57         <div class="no-data"  v-if="!loading && finished">没有数据啦</div>
 58       </div>
 59     </div>
 60   </div>
 61 </template>
 62 
 63 <script>
 64 import { jsBridgeReady } from '@qycloud/js-bridge';
 65 import { $http } from '@commonbox/utils';
 66 import { Lazyload } from 'vant';
 67 
 68 Vue.use(Lazyload);
 69 
 70 export default {
 71   name: 'Home',
 72   data() {
 73     return {
 74       images: [
 75         require('../../assets/images/swipe-img1.png'),
 76         require('../../assets/images/swipe-img1.png'),
 77         require('../../assets/images/swipe-img1.png'),
 78         require('../../assets/images/swipe-img1.png'),
 79       ],
 80       tabList: [{
 81         name: '全部企业',
 82         enterprise_id: '',
 83         id: 0,
 84       }],
 85       currentType: 0,
 86       enterpriseId: '',
 87       todoTypeList: [
 88         { text: '待办工作', value: 0 },
 89         { text: '最近处理', value: 1 },
 90         { text: '我发起的', value: 2 },
 91       ],
 92       todoType: 0, // 默认代办
 93       statusList: [{
 94         name: '进行中',
 95         workflowStatus: 'running',
 96       }, {
 97         name: '已完成',
 98         workflowStatus: 'finished',
 99       }],
100       currentStatus: 'running',
101       todoList: [],
102       isFixed: false,
103       scrollTop: 0,
104 
105       refreshing: false,
106       loading: false, // 加载状态
107       finished: false, // 是否加载
108 
109       pageIndex1: 0, // 页数
110       pageIndex2: 0, // 页数
111       pageIndex3: 0, // 页数
112       pageSize: 10 // 条数
113     };
114   },
115   computed: {
116     isNoData() {
117       return this.todoList && this.todoList.length > 0;
118     },
119     computedColor() {
120       const containerColorList = [
121         {
122           name: '物流事业部', bg: '#EEF0FF', color: '#3E3C9E', id: 'wuliushiyebu',
123         },
124         {
125           name: '中化南通', bg: '#FFE9F2', color: '#FF2C7F', id: 'zhonghuanantonggang',
126         },
127         {
128           name: '中化兴中', bg: '#E5F2F1', color: '#007F7A', id: 'zhonghuazhoushan',
129         },
130         {
131           name: '中化运营', bg: '#344051', color: '#4380F0', id: 'zhonghuayunying',
132         },
133         {
134           name: '天津仓储', bg: '#F8F2EE', color: '#B9805E', id: 'zhonghuatianjin',
135         },
136         {
137           name: '中化扬州', bg: '#E7EDFF', color: '#6075B7', id: 'zhonghuayangzhou',
138         },
139         {
140           name: '中化东方', bg: '#F5ECFC', color: '#945FB9', id: 'zhonghuadongfang',
141         },
142         {
143           name: '应急基地', bg: '#E7F6EC', color: '#18A549', id: 'yingjijidi',
144         },
145         {
146           name: '舟山国储', bg: '#EAF7FF', color: '#0050B3', id: 'zhoushanguochu',
147         },
148         {
149           name: '中化兴海', bg: '#FFE6E8', color: '#FF0D1A', id: 'zhonghuaxinghai',
150         },
151       ];
152       return (item) => {
153         const tempItem = containerColorList.filter(res => res.id === item.spanSpace);
154         return tempItem[0];
155       }
156     },
157   },
158   methods: {
159     jumpDetail(item) {
160       const appIdList = [
161         'donghuozuoyexukeguan',
162         'dongtuzuoyexukeguanl',
163         'diaozhuangzuoyexukeg',
164         'gaochuzuoyexukeguanl',
165         'shouxiankongjianzuoy',
166         'linshiyongdianzuoyex',
167         'mangbanchouduzuoyexu',
168         'duanluzuoyexukeguanl',
169         'renkongkaiqizuoyexuk',
170         'shexianzuoyexukeguan',
171       ]
172       if (appIdList.includes(item.workflow_id)) {
173         // 调大钊哥页面
174         /* eslint-disable */
175         const url = `${location.protocol}//${location.host}/bee/mobileportal/${item.spanSpace}/lego-app-form?spaceId=${item.spanSpace}&module=workflow&appId=${item.workflow_id}&appName=${item.title}&formId=${item.instance_id}&node=${item.step_id}&back=todo&scId=`
176         jsBridgeReady((bridge) => {
177           bridge.callHandler('openWebview', { url })
178         });
179       } else {
180         jsBridgeReady((bridge) => {
181           bridge.callHandler(
182             'openFormDetail',
183             {
184               appType: 'workflow',
185               appId: item.workflow_id,
186               action: 2, // 查看
187               instanceId: item.instance_id,
188               entId: item.spanSpace,
189               title: item.title,
190               nodeId: item.step_id,
191             },
192             (res) => {
193               console.log('成功');
194             },
195           );
196         });
197       }
198     },
199     selectTab(index) {
200       this.currentType = index;
201       for (let i = 0; i < this.tabList.length; i++) {
202         const item = this.tabList[i];
203         if (item.id === index) {
204           this.enterpriseId = item.enterprise_id;
205         }
206       }
207       this.currentStatus = 'running';
208       this.queryNum();
209       if (this.todoType === 0) {
210         this.todoList = [];
211         this.pageIndex1 = 1;
212         this.getPendingWorkList();
213       } else if (this.todoType === 1) {
214         this.todoList = [];
215         this.pageIndex2 = 1;
216         this.getRecentlyProcessedList();
217       } else if (this.todoType === 2) {
218          this.todoList = [];
219         this.pageIndex3 = 1;
220         this.getInitiatedList();
221       }
222     },
223     selectStatusTab(item) {
224       this.currentStatus = item.workflowStatus;
225       if (this.todoType === 0) {
226         this.todoList = [];
227         this.pageIndex1 = 1;
228         this.getPendingWorkList();
229       } else if (this.todoType === 1) {
230         this.todoList = [];
231         this.pageIndex2 = 1;
232         this.getRecentlyProcessedList();
233       } else if (this.todoType === 2) {
234         this.todoList = [];
235         this.pageIndex3 = 1;
236         this.getInitiatedList();
237       }
238     },
239     // 获取可切换容器列表
240     getUserSpaceList() {
241       $http.get('/sdkuser/pendingWorkApi/getUserSpaceList').then((res) => {
242         if (res.data.status === 200) {
243           res.data.data.forEach((item, index) => {
244             this.tabList.push({
245               name: item.name,
246               enterprise_id: item.enterprise_id,
247               id: index + 1,
248             })
249           });
250         }
251       });
252     },
253     // 获取待办数据
254     queryNum() {
255       const queryParams = {
256         entIdApp: this.enterpriseId,
257       };
258       $http.get('/sdkuser/pendingWorkApi/getWorkTotalCountWithApp', {
259         params: queryParams,
260       }).then((res) => {
261         if (res.data.status === 200) {
262           this.todoTypeList[0].text = `待办工作(${res.data.data.pendingTotalCount})`;
263           this.todoTypeList[1].text = `最近处理(${res.data.data.recentlyProcessedTotalCount})`;
264           this.todoTypeList[2].text = `我发起的(${res.data.data.initiatedTotalCount})`;
265         }
266       });
267     },
268     changeStatus(val) {
269       if (val === 0) {
270         this.todoList = [];
271         this.pageIndex1 = 1;
272         this.getPendingWorkList();
273       } else if (val === 1) {
274         this.todoList = [];
275         this.pageIndex2 = 1;
276         this.getRecentlyProcessedList();
277       } else if (val === 2) {
278         this.todoList = [];
279         this.pageIndex3 = 1;
280         this.getInitiatedList();
281       }
282     },
283     loadMore() {
284       if (this.todoType === 0 && !this.loading) {
285         this.pageIndex1 += 1; 
286         this.getPendingWorkList();
287       } else if (this.todoType === 1 && !this.loading) {
288         this.pageIndex2 += 1; 
289         this.getRecentlyProcessedList();
290       } else if (this.todoType === 2 && !this.loading) {
291         this.pageIndex3 += 1; 
292         this.getInitiatedList();
293       }
294     },
295     onRefresh() {
296       this.finished = false; // 不写这句会导致你上拉到底过后在下拉刷新将不能触发下拉加载事件
297       this.pageIndex1 = 0;
298       this.pageIndex2 = 0;
299       this.pageIndex3 = 0;
300       this.todoList = [];
301       this.loadMore();
302     },
303     // 获取待办数据
304     getPendingWorkList() {
305       if(this.loading) { return; }
306       this.loading = true;
307       const queryParams = {
308         entIdApp: this.enterpriseId,
309       };
310       $http.get('/sdkuser/pendingWorkApi/getPendingWorkListWithApp', {
311         params: queryParams,
312       }).then((res) => {
313         if (res.data.status === 200) {
314           this.loading = false;
315           let tempTodoList = res.data.result.result.slice( (this.pageIndex1-1) * this.pageSize, this.pageIndex1 * this.pageSize );
316           this.todoList = this.todoList.concat(tempTodoList);
317           if (this.pageIndex1 * this.pageSize  >= res.data.result.totalCount) {  
318             this.finished = true;
319           } else {
320             this.finished = false;
321           };
322         }
323       }).catch((error) => {
324           console.log(error);
325         })
326         .finally(() => {
327           this.refreshing = false;
328           this.loading = false;
329         });
330     },
331     // 获取过往数据
332     getRecentlyProcessedList() {
333       if(this.loading) {
334         return;
335       };
336       this.loading = true;
337       const queryParams = {
338         entIdApp: this.enterpriseId,
339         workflowStatus: this.currentStatus,
340       };
341       $http.get('/sdkuser/pendingWorkApi/getRecentlyProcessedListWithApp', {
342         params: queryParams,
343       }).then((res) => {
344         if (res.data.status === 200) {
345           this.loading = false;
346           let tempTodoList = res.data.result.result.slice( (this.pageIndex2-1) * this.pageSize, this.pageIndex2 * this.pageSize );
347           this.todoList = this.todoList.concat(tempTodoList);
348           if (this.pageIndex2 * this.pageSize  >= res.data.result.totalCount) {  //数据全部加载完成
349             this.finished = true;
350           } else {
351             this.finished = false;
352           }   
353         }
354       }).catch((error) => {
355           console.log(error);
356         })
357         .finally(() => {
358           this.refreshing = false;
359           this.loading = false;
360         });
361     },
362     // 获取我发起的数据
363     getInitiatedList() {
364       if(this.loading) {
365         return;
366       };
367       this.loading = true;
368       const queryParams = {
369         entIdApp: this.enterpriseId,
370         workflowStatus: this.currentStatus,
371       };
372       $http.get('/sdkuser/pendingWorkApi/getInitiatedListWithApp', {
373         params: queryParams,
374       }).then((res) => {
375         if (res.data.status === 200) {
376           this.loading = false;
377           let tempTodoList = res.data.result.result.slice( (this.pageIndex3-1)*this.pageSize, this.pageIndex3*this.pageSize );
378           this.todoList = this.todoList.concat(tempTodoList);
379           if (this.pageIndex3 * this.pageSize  >= res.data.result.totalCount) {  //数据全部加载完成
380             this.finished = true;
381           } else {
382             this.finished = false;
383           }   
384         }
385       }).catch((error) => {
386         console.log(error);
387       }).finally(() => {
388         this.refreshing = false;
389         this.loading = false;
390       });
391     },
392     dataScroll() {
393       this.scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
394       this.isFixed = this.scrollTop > 150;
395     },
396   },
397   mounted() {
398     this.getUserSpaceList();
399     this.queryNum();
400     window.addEventListener('scroll', this.dataScroll);
401   },
402   destroyed() {
403     window.removeEventListener('scroll', this.dataScroll, false);
404   },
405 };
406 </script>
407 
408 <style lang="scss" scoped>
409 // 单行溢出省略
410 .txt-ellipsis {
411   white-space: nowrap;
412   overflow: hidden;
413   text-overflow: ellipsis;
414 }
415 .home-wrapper {
416   background: #f6f8fa;
417   .swipe-box {
418      100%;
419     height: 150px;
420     .van-swipe {
421       height: 100%;
422     }
423     .swipe-img {
424        100%;
425       height: 100%;
426     }
427   }
428   .tab-box {
429     margin-top: 5px;
430   }
431   .tab-box-header {
432     &.is-fixed {
433       position: fixed;
434       top: 0;
435       z-index: 10;
436        100%;
437       box-shadow: 0 5px 5px #ccc;
438     }
439   }
440   /deep/ .van-tabs__wrap {
441     height: 45px;
442     border-bottom: 1px solid #eee;
443     .van-tab--active {
444       color: #4982fe;
445     }
446     .van-tabs__line {
447        background: #4982fe;
448     }
449     /deep/ .van-tab {
450       height: 45px;
451     }
452   }
453 
454   /deep/ .van-dropdown-menu__bar {
455     height: 40px;
456   }
457   /deep/ .van-dropdown-menu__title {
458     padding: 0 20px;
459   }
460   /deep/ .van-dropdown-menu__item {
461     justify-content: flex-start;
462   }
463   /deep/ .van-tabs__wrap--scrollable .van-tab--complete {
464     margin: 0 10px;
465   }
466   .tab-content {
467     padding: 8px;
468      &.is-fixed {
469        padding-top: 110px;
470      }
471     .status-list {
472       display: flex;
473       margin-bottom: 8px;
474       .status-item {
475         margin-right: 10px;
476         font-size: 14px;
477         padding: 5px 8px;
478         color: #666;
479         border-radius: 3px;
480         &.active {
481           color: #fff;
482           background: #4982fe;
483         }
484       }
485     }
486     .todo-list {
487       .todo-item {
488         list-style: none;
489         background: #fff;
490         margin-bottom: 8px;
491         border-radius: 2px;
492         border: 1px solid #eaebec;
493         .todo-top {
494           border-bottom: 1px solid #eaebec;
495           padding: 0 8px;
496           .title-box {
497             height: 42px;
498             display: flex;
499             align-items: center;
500             .icon-urgent {
501               display: inline-block;
502                20px;
503               height: 20px;
504               background: url('../../assets/images/icon-urgent.png') no-repeat left top;
505               background-size: 100%;
506               margin-right: 4px;
507             }
508             .app-name {
509               background: #5b8ff9;
510               color: #fff;
511               font-size: 12px;
512               padding: 4px 5px;
513               margin-right: 6px;
514               white-space: nowrap;
515             }
516             .app-title {
517               font-size: 15px;
518               color: #333;
519               font-weight:600;
520             }
521           }
522           .content-box {
523             height: 32px;
524             display: flex;
525             align-items: center;
526             .todo-container {
527               font-size: 12px;
528               color: #0b0983;
529               background: #eceeff;
530               padding: 4px;
531               white-space: nowrap;
532               .icon-qi {
533                 font-size: 12px;
534                 background: #0b0983;
535                 color: #fff;
536                 padding: 1px 3px;
537                 border-radius: 2px;
538               }
539             }
540             .system-name {
541               margin: 0 8px;
542               font-size: 12px;
543               color: #373839;
544               background: #edf2f8;
545               padding:  4px;
546               white-space: nowrap;
547             }
548           }
549           .todo-launcher {
550               height: 26px;
551               line-height: 26px;
552               margin-bottom: 6px;
553               font-size: 13px;
554               color: #666;
555             }
556         }
557         .todo-body {
558           height: 36px;
559           padding: 0 8px;
560           display: flex;
561           align-items: center;
562           justify-content: space-between;
563           .update-time {
564             font-size: 13px;
565             color: #666;
566           }
567           .node-name {
568             font-size: 13px;
569             color: #FA8C15;
570           }
571         }
572       }
573     }
574     .no-data {
575        100%;
576       height: 40px;
577       line-height: 40px;
578       text-align: center;
579       color: #999;
580     }
581   }
582   .loading4 {
583      150px;
584     margin: 20px auto;
585     text-align: center;
586     div {
587        16px;
588       height: 16px;
589       border-radius: 100%;
590       display: inline-block;
591       margin: 0 5px;
592       background-color: #4982fe;
593       -webkit-animation: three 1.4s infinite ease-in-out;
594       animation: three 1.4s infinite ease-in-out;
595       -webkit-animation-fill-mode: both;
596       animation-fill-mode: both;
597       &:nth-of-type(1) {
598         background-color: #8588A9;
599       }
600       &:nth-of-type(2) {
601         background-color: #3BB3C4;
602       }
603       &:nth-of-type(3) {
604         background-color: #3572B1;
605       }
606     }
607     @-webkit-keyframes three {
608       0%, 80%, 100% {-webkit-transform: scale(0.0) }
609       40% { -webkit-transform: scale(1.0) }
610     }
611     @keyframes three {
612       0%, 80%, 100% {-webkit-transform: scale(0.0) }
613       40% { -webkit-transform: scale(1.0) }
614     }
615     .three1 {
616       -webkit-animation-delay: -0.30s;
617       animation-delay: -0.30s;
618     }
619     .three2{
620       -webkit-animation-delay: -0.15s;
621       animation-delay: -0.15s;
622     }
623   }
624   
625 }
626 </style>
 
原文地址:https://www.cnblogs.com/guwufeiyang/p/13962804.html