ui-page-list.vue 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  1. <template>
  2. <view class="page-list">
  3. <slot></slot>
  4. <u-no-network v-if="offNetwork" @connected="tryAgain" @retry="tryAgain"></u-no-network>
  5. <template v-else>
  6. <view class="text-center ui-flex ui-flex-align-center ui-flex-center" v-if="isLoad && !silent" style="height: 50px;">
  7. <u-loading-icon size="40"></u-loading-icon>
  8. </view>
  9. <view v-if="!isLoad && showPageText">
  10. <view v-if="showType == 2">
  11. <slot name="empty">
  12. <u-empty text="当前记录为空" iconSize="160" textSize="32" mode="data" show></u-empty>
  13. <!-- <text>当前记录为空</text> -->
  14. </slot>
  15. </view>
  16. <view v-if="showType == 3" @click="next()" class="ui-flex ui-flex-align-center ui-flex-center" style="height: 50px;">
  17. <text class="u-tips-color f16 text-center">点击继续加载信息</text>
  18. </view>
  19. <slot name="info">
  20. <view v-if="showType == 4" class="ui-flex ui-flex-align-center ui-flex-center" style="height: 50px;">
  21. <text class="u-tips-color f16 text-center">显示{{((page || 1)-1) * size + 1}}到{{page * size}},共{{total}}记录</text>
  22. </view>
  23. </slot>
  24. </view>
  25. </template>
  26. </view>
  27. </template>
  28. <script>
  29. const globalData = getApp().globalData;
  30. export default {
  31. props : {
  32. url : String,
  33. showPageText : {
  34. type : Boolean,
  35. default : true
  36. },
  37. start : {
  38. type : Boolean,
  39. default : true
  40. },
  41. method : {
  42. type : String,
  43. default : 'POST'
  44. },
  45. refreshRate : { //多少秒自动刷新页面
  46. type : Number,
  47. default : null
  48. },
  49. params : {
  50. type: Object,
  51. default: function () {
  52. return {}
  53. }
  54. },
  55. value : {
  56. type: Array,
  57. default: function () {
  58. return []
  59. }
  60. },
  61. format : {
  62. type : Function,
  63. default : function(){
  64. return function(){}
  65. }
  66. }
  67. },
  68. data : function(){
  69. return {
  70. init : false,
  71. // url : '',
  72. // params : {},
  73. size : 10,
  74. page : 0,
  75. // rows : [],
  76. total : 0,
  77. isLoad : false,
  78. silent : false,
  79. // lastTime : 0,
  80. lazyLoadPage : null,
  81. showCount : 0,
  82. offNetwork : false,
  83. }
  84. },
  85. created : function(){
  86. this.start && this.url && this.get();
  87. },
  88. computed: {
  89. showType : function(){
  90. // console.log('来计算');
  91. // if(this.isLoad){
  92. // return 1; //加载中
  93. // }
  94. if(this.total == 0 && this.page == 1){
  95. return 2; //记录空
  96. }
  97. if(this.total/this.size > this.page){
  98. return 3; //点击继续
  99. }
  100. if(this.page){
  101. return 4; //全完成
  102. }
  103. }
  104. },
  105. //#ifndef H5
  106. onShow() { // mp-vue执行
  107. if(this.showCount){
  108. this.view_show();
  109. }
  110. this.showCount ++
  111. },
  112. //#endif
  113. //#ifdef H5
  114. activated : function(){ // web-vue执行
  115. // console.log('web-vue执行')
  116. this.view_show();
  117. },
  118. //#endif
  119. methods : {
  120. view_show : function(){
  121. // console.log('我来了')
  122. var time = Date.parse(new Date())/1000;
  123. var fresh = false;
  124. this.lastTime = this.lastTime || time;
  125. if(this.lastTime && this.refreshRate && time - this.lastTime > this.refreshRate){
  126. if(this.lastTime){
  127. this.fresh(Object.assign(
  128. this.params,
  129. {$silent : true}
  130. ));
  131. // this.fresh({
  132. // ...this.params,
  133. // ...{$silent : true}
  134. // });
  135. }
  136. this.lastTime = time;
  137. fresh = true;
  138. }
  139. if(!fresh && this.lazyLoadPage !== null){
  140. this.get(null, Object.assign(
  141. this.params,
  142. {page : this.lazyLoadPage, $silent : true}
  143. ), (res)=>{
  144. this.lazyLoadPage = null;
  145. })
  146. // this.get(null, {...this.params, ...{page : this.lazyLoadPage, $silent : true}}, (res)=>{
  147. // this.lazyLoadPage = null;
  148. // })
  149. }
  150. },
  151. intoItem : function(index, $pageTo, data){ //进入了这个条目,算出属于第几页,返回的时候需要重新加载此页
  152. console.log(data)
  153. this.lazyLoadPage = Math.ceil( (index + 1) / this.size);
  154. if($pageTo){
  155. this.$nextTick(()=>{
  156. this.$pageTo($pageTo, data);
  157. })
  158. }
  159. },
  160. next : function(fn){
  161. if(this.size * this.page >= this.total){
  162. return;
  163. }
  164. if(this.isLoad){ return; }
  165. var params = this.params;
  166. params.page = params.page ? params.page + 1 : 1;
  167. this.get(this.url, params, fn);
  168. },
  169. fresh : function(params, url, fn){
  170. url = url || this.url;
  171. params = params || this.params;
  172. this.size = params.size || this.size;
  173. if(!params.$silent){
  174. this.$emit('input', []);
  175. this.total = 0;
  176. }
  177. this.get(url, params, fn);
  178. },
  179. tryAgain : function(){
  180. this.offNetwork = false;
  181. this.isLoad = true;
  182. setTimeout(() => {
  183. this.fresh(null, null, this._again_data_fn)
  184. }, 300)
  185. },
  186. get : function(url, params, fn){
  187. this.init = true;
  188. url = url || this.url;
  189. params = params || this.params;
  190. if(params.$silent){
  191. this.silent = true;
  192. delete params.$silent;
  193. }else{
  194. this.silent = false;
  195. this.isLoad = true;
  196. }
  197. this._again_data_fn = fn;
  198. // this.get.CancelDo && this.get.CancelDo.cancel('Operation canceled by the user.');
  199. // this.get.CancelDo = axios.CancelToken.source();
  200. // params.cancelToken = this.get.CancelDo.token;
  201. // console.log('检查网路');
  202. uni.getNetworkType({
  203. success : res => {
  204. // console.log(res);
  205. if(res.networkType == "none"){
  206. this.$emit('input', []);
  207. uni.stopPullDownRefresh();
  208. this.offNetwork = true;
  209. }else{
  210. this.offNetwork = false;
  211. }
  212. }
  213. })
  214. this.$api.sendRequest({
  215. url: url,
  216. method: this.method,
  217. data: params,
  218. success: res => {
  219. this.dataCallBack(url, params, fn, res.data)
  220. },
  221. fail : (res) => {
  222. this.isLoad = false;
  223. }
  224. })
  225. },
  226. dataCallBack(url, params, fn, res){
  227. Object.assign(this.params, params);
  228. res.size = res.size || res.per_page;
  229. res.page = res.page || res.current_page;
  230. res.rows = res.rows || res.data;
  231. this.isLoad = false;
  232. this.$emit('onget', res);
  233. this.params.page = ~~res.page;
  234. this.page = ~~res.page;
  235. this.size = ~~res.size;
  236. this.total = ~~res.total;
  237. // 局部条目更新 self.page 会变成是当前页
  238. if(this.lazyLoadPage && res.rows.length){ //静默去更新下一页
  239. if(this.size * this.page < this.total){
  240. this.get(url, Object.assign(params, {page : ++params.page, $silent : true}))
  241. }
  242. }else{
  243. this.value.splice((this.page - 1) * this.size);
  244. }
  245. this.format(res.rows)
  246. var index = (this.page - 1) * this.size;
  247. var len = res.rows.length;
  248. for (var i = 0; i < len; i++) {
  249. if(this.value[index + i]){
  250. this.value.splice(index + i, 1, res.rows[i]);
  251. }else{
  252. this.value.push(res.rows[i]);
  253. }
  254. }
  255. this.$emit('input', this.value);
  256. fn && fn(res);
  257. }
  258. }
  259. }
  260. </script>
  261. <style>
  262. .page-list{
  263. /* margin-top: 15px; */
  264. margin-bottom: 15px;
  265. border-top: 1px solid transparent;
  266. border-bottom: 1px solid transparent;
  267. }
  268. </style>