jufubao-movie 1.0.39-beta1 → 1.0.39-beta2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jufubao-movie",
3
- "version": "1.0.39-beta1",
3
+ "version": "1.0.39-beta2",
4
4
  "private": false,
5
5
  "description": "聚福宝在线选座业务组件插件包",
6
6
  "main": "index.js",
@@ -4,7 +4,7 @@
4
4
  class="image"
5
5
  :style="{marginRight: outSpacing + 'rpx',borderRadius:borderRadius+'rpx'}"
6
6
  >
7
- <image :src="item['poster']" :alt="item['show_name']"></image>
7
+ <image :src="item['poster']" :alt="item['show_name']" @error="handleError(item)"></image>
8
8
  </view>
9
9
  <view class="middle">
10
10
  <view class="name">{{item['show_name']}}</view>
@@ -84,6 +84,9 @@
84
84
 
85
85
  },
86
86
  methods:{
87
+ handleError(item){
88
+ item['poster'] = 'https://img.jufubao.cn/common/error_movie.png?v20'
89
+ },
87
90
  handleDetail(item){
88
91
  console.log('handleDetail.item',item,item.id);
89
92
  this.$emit('on-film-detail',item.id);
@@ -142,10 +145,9 @@
142
145
  align-items: flex-end;
143
146
  justify-content: flex-end;
144
147
  flex-flow: wrap;
145
- height: 100%;
146
148
  box-sizing: border-box;
147
149
  width: 160rpx;
148
- min-height: 200rpx;
150
+ height: 200rpx;
149
151
 
150
152
  & .score {
151
153
  height: 40rpx;
@@ -81,11 +81,16 @@
81
81
  </view>
82
82
  </view>
83
83
  <!--poster-->
84
+ <view id="content-ref" class="content-ref"></view>
84
85
  <!--film hot|rightnow-->
85
86
  <view
86
87
  v-if="type === 'hot' || type === 'rightnow'"
87
88
  class="list-cont"
88
- :style="{marginTop:outSpacing + 'rpx'}"
89
+ :style="{
90
+ marginTop:outSpacing + 'rpx',
91
+ paddingTop:paddingTop,
92
+ paddingBottom:paddingBottom,
93
+ }"
89
94
  >
90
95
  <view class="skeleton-wrap" v-if="dataList === null">
91
96
  <view
@@ -230,6 +235,37 @@
230
235
  ></view>
231
236
  </template>
232
237
  </view>
238
+ <view
239
+ id="preRendering"
240
+ class="preRendering"
241
+ v-if="type === 'list' && preRendering.length >0"
242
+ :style="{padding:outSpacing + 'rpx'}"
243
+ >
244
+ <view
245
+ class="list-cont-item"
246
+ v-for="(film,index) in preRendering"
247
+ :key="film.cinema_id"
248
+ :data-index="index"
249
+ :style="{
250
+ marginBottom:outSpacing + 'rpx',
251
+ padding:contMarginComp,
252
+ borderRadius:contRradius+ 'rpx',
253
+ border:contBorder,
254
+ boxShadow:contShadow,
255
+ backgroundColor:contBgColor,
256
+ height: 'auto'
257
+ }"
258
+ >
259
+ <content-cinema
260
+ style="width: 100%;height: 100%"
261
+ :item="film"
262
+ :out-spacing="outSpacing"
263
+ :color="{SEAT:mainColor,CODE:subMainColor,SELL:successColor}"
264
+ :type="type"
265
+ :border-radius="imgRradius"
266
+ ></content-cinema>
267
+ </view>
268
+ </view>
233
269
  <!--cinema-->
234
270
  <view class="hasNoData" v-if="dataList && dataList.length > 0 && pageToken === ''">已经到底没有更多数据了</view>
235
271
  </view>
@@ -260,6 +296,7 @@
260
296
  import XdQueryFilter from "./XdQueryFilter.vue";
261
297
  import {mapState} from "vuex";
262
298
  import Color from "color";
299
+ import VirtualList from "@/lib/VirtualList";
263
300
 
264
301
  export default {
265
302
  name: "JfbMovieTfkFilmList",
@@ -276,6 +313,8 @@
276
313
  ],
277
314
  data() {
278
315
  return {
316
+ /**@type {VirtualList}**/
317
+ virtualList:null,
279
318
  options: {},
280
319
  //hideMask: true,
281
320
  type:'', //hot rightnow
@@ -284,7 +323,7 @@
284
323
  backgroundColor:'',
285
324
  isPreview: false,
286
325
  pageToken:'1',
287
- pageSize: 20,
326
+ pageSize: 10,
288
327
  total: null,
289
328
  isFirstLoadingData: false,
290
329
  dataList:null,
@@ -347,7 +386,9 @@
347
386
 
348
387
  buyPath:'',
349
388
  fimeDetailPath:'',
350
-
389
+ paddingTop: 0,
390
+ paddingBottom: 0,
391
+ preRendering:[],
351
392
 
352
393
  }
353
394
  },
@@ -447,6 +488,17 @@
447
488
  this.clearDataVar();
448
489
  this.getList();
449
490
  },
491
+ preRendering(){
492
+ this.$nextTick(()=>{
493
+ const query = uni.createSelectorQuery().in(this);
494
+ query
495
+ .select('#preRendering > .list-cont-item')
496
+ .boundingClientRect((data) => {
497
+ console.log("得到布局位置信息" + JSON.stringify(data));
498
+ })
499
+ .exec();
500
+ })
501
+ }
450
502
  },
451
503
  created() {
452
504
  this.isPreview = this.$configProject.isPreview;
@@ -597,6 +649,7 @@
597
649
  //过滤之后不够分页直接返回值
598
650
  if(fitlerData.length <= this.pageSize) {
599
651
  this.dataList = this.$xdUniHelper.cloneDeep(fitlerData);
652
+ this.preRendering = this.$xdUniHelper.cloneDeep(fitlerData);
600
653
  this.pageToken = ''
601
654
  return;
602
655
  }
@@ -611,6 +664,7 @@
611
664
  return;
612
665
  }
613
666
 
667
+ this.preRendering = this.$xdUniHelper.cloneDeep(list);
614
668
  this.dataList = (this.dataList||[]).concat(this.$xdUniHelper.cloneDeep(list));
615
669
  if(this.pageSize < list.length) this.pageToken = '';
616
670
  else this.pageToken = (Number(this.pageToken)+1) + '';
@@ -618,6 +672,9 @@
618
672
 
619
673
  handleTab(value){
620
674
  if(value === this.type) return;
675
+ if(value === 'hot' || value === 'rightnow' ) {
676
+ this.virtualList.onChangeTab();
677
+ }
621
678
  this.type = value;
622
679
  this.dataList = null;
623
680
  this.pageToken = '1';
@@ -667,9 +724,11 @@
667
724
  }).then(res => {
668
725
  if(this.isFirstLoadingData) this.$xdHideLoading({});
669
726
 
727
+
670
728
  //影片列表处理
671
729
  if(this.type === 'rightnow' || this.type==='hot'){
672
- this.dataList = (this.dataList||[]).concat(res['list']);
730
+ //this.dataList = (this.dataList||[]).concat(res['list']);
731
+ this.virtualList.pushVirtualData(res['list']);
673
732
  this.pageToken = res.next_page_token;
674
733
  return;
675
734
  }
@@ -684,6 +743,7 @@
684
743
  //小于数量页面显示记录
685
744
  if(res['list'].length <= this.pageSize) {
686
745
  this.dataList = res['list'];
746
+ this.preRendering = this.$xdUniHelper.cloneDeep(res['list']);
687
747
  this.pageToken = '';
688
748
  return
689
749
  }
@@ -701,6 +761,33 @@
701
761
  onJfbLoad(options) {
702
762
  this.options = options;
703
763
 
764
+ this.virtualList = new VirtualList(this, '#content-ref', {
765
+ fixedHeight: 240 + Number(this.outSpacing) + 20 * 2 ,
766
+ otherHeight: Number(this.outSpacing),
767
+ //获取节点数据
768
+ getDom:(id)=>{
769
+ return new Promise((resolve,reject)=>{
770
+ uni.createSelectorQuery().in(this).select(id)
771
+ .boundingClientRect((data)=>{
772
+ if(data && data.top !== undefined) resolve(data);
773
+ else reject(null)
774
+ }).exec()
775
+ });
776
+ },
777
+ //获取当前this
778
+ getParentThis(){
779
+ return this
780
+ },
781
+ callback: ({data, paddingTop, paddingBottom}) =>{
782
+ if(this.type === 'hot' ||this.type ==='rightnow' ) {
783
+ this.paddingTop = paddingTop;
784
+ this.paddingBottom = paddingBottom;
785
+ this.dataList = data;
786
+ }
787
+
788
+ },
789
+ });
790
+
704
791
  jfbRootExec('getTFKPosterContent', {
705
792
  vm: this,
706
793
  data: {
@@ -782,6 +869,12 @@
782
869
  this.setShowTypeList();
783
870
  },
784
871
 
872
+ onJfbScroll(options){
873
+ if(this.type === 'hot' || this.type === 'rightnow'){
874
+ this.virtualList.onScrollEvent(options.e.scrollTop);
875
+ }
876
+ },
877
+
785
878
  setShowTypeList(){
786
879
  let list = [];
787
880
  if(this.showHot === 'Y') list.push(this.typeList["hot"]);
@@ -811,6 +904,7 @@
811
904
  this.$xdUniHelper.navigateBack();
812
905
  }
813
906
  },
907
+
814
908
  //重新回去广告位置工
815
909
  onJfbUpdate() {
816
910
  this.onJfbLoad(this.options)
@@ -853,6 +947,7 @@
853
947
  .list-cont {
854
948
  position: relative;
855
949
  z-index: 2;
950
+ min-height: 600rpx;
856
951
  .skeleton-wrap {
857
952
  .skeleton-wrap-item {
858
953
  height: 240rpx;
@@ -1011,6 +1106,17 @@
1011
1106
  font-size: 26rpx;
1012
1107
  }
1013
1108
 
1109
+ .preRendering {
1110
+ position: fixed;
1111
+ top: -9999px;
1112
+ left: -9999px;
1113
+ opacity: 0;
1114
+ z-index: 0;
1115
+ width: 100%;
1116
+ box-sizing: border-box;
1117
+ overflow: hidden;
1118
+ }
1119
+
1014
1120
  .hasNoData {
1015
1121
  height: 80rpx;
1016
1122
  line-height: 80rpx;
@@ -106,7 +106,7 @@
106
106
  @click="toFilmInfo(item.id)"
107
107
  >
108
108
  <view class="tfk-scroll-item-image" :style="{borderRadius:contItemRradius + 'rpx'}">
109
- <image :src="item.poster" :alt="item.show_name" mode="scaleToFill"></image>
109
+ <image :src="item.poster" :alt="item.show_name" mode="scaleToFill" @error="handleError(item)"></image>
110
110
  </view>
111
111
  <view class="tfk-scroll-item-title">{{item.show_name}}</view>
112
112
  <view class="tfk-scroll-item-btn">
@@ -310,6 +310,9 @@
310
310
  this.init(this.container);
311
311
  },
312
312
  methods: {
313
+ handleError(item){
314
+ item['poster'] = 'https://img.jufubao.cn/common/error_movie.png?v20'
315
+ },
313
316
  toFilmInfo(film_id){
314
317
  console.warn(`toFilmInfo(影片详情).${film_id}`)
315
318
  if(!this.fimeDetailPath) {
@@ -0,0 +1,184 @@
1
+ 'use strict';
2
+ //原点对象
3
+ let __orgUpdateTop = null;
4
+
5
+ export default class VirtualList {
6
+ virtualType='fixed';
7
+ virtualBufferHeight= 300;
8
+ virtualFixedItemHeight; //固定模式高度设置
9
+ virtualVue; //当前组件vm实例
10
+ virtualTotalData=[]; //数组长度
11
+ virtualHeightObj = {}; //高度序列index: {max:xx,min:xx}
12
+ $el= null; //开始点元素
13
+ offsetTop= null;//开始点元素的偏移量
14
+ eqMaxTimer = 0;//
15
+ otherHeight= 0; //调节高度
16
+ orgUpdateTop = 0; //开始点元素原点偏移量
17
+ isFirst = true;
18
+ startIndex= 0;
19
+ endIndex= 0;
20
+ screenHeight=0;//全屏高度
21
+
22
+ top=0;
23
+ bottom=0;
24
+ virtualCallback= ()=>{};
25
+ status= false
26
+
27
+ /**
28
+ * @description 初始化或者重置对象
29
+ * @param $vm {Vue} vue对象
30
+ * @param $el {string}
31
+ * @param params {Object}
32
+ * @param params.type {string} 元素高度为固定或者非固定 其值:auto|fixed
33
+ * @param params.fixedHeight {number} 固定(rpx)(fixed)模式 (必选)
34
+ * @param params.bufferHeight {number} 缓冲高度(rpx)
35
+ * @param params.otherHeight {number} 其他高度(rpx)
36
+ * @param params.callback {Function} 回调方法
37
+ */
38
+ constructor($vm,$el, params ) {
39
+ this.virtualVue = $vm;
40
+ this.virtualBufferHeight = 480 * this.virtualVue.$rpxNum;
41
+ if(params.type && ['auto','fixed'].includes(params.type)) this.virtualType = params.type;
42
+ if(params.bufferHeight) this.virtualBufferHeight = params.bufferHeight * this.virtualVue.$rpxNum;
43
+ if(params.otherHeight) this.otherHeight = params.otherHeight * this.virtualVue.$rpxNum;
44
+ if(this.virtualType === 'fixed'){
45
+ if(params.fixedHeight === undefined) throw new Error(`FixedHeight is require, got is ${params.fixedHeight}`);
46
+ else this.virtualFixedItemHeight = params.fixedHeight * this.virtualVue.$rpxNum;
47
+ }
48
+ this.virtualTotalData = [];
49
+ this.virtualVue.virtualViewData = null;
50
+ this.$el = $el;
51
+ this.virtualVue.$nextTick(()=>{
52
+ this.checkOffsetTop();
53
+ });
54
+ this.screenHeight = uni.getSystemInfoSync().safeArea.height;
55
+ if(typeof params.callback !== 'function') {
56
+ throw new Error(`FixedHeight is require, got is ${params.fixedHeight}`);
57
+ }else this.virtualCallback = params.callback;
58
+
59
+ }
60
+
61
+ checkOffsetTop(){
62
+ if(__orgUpdateTop) {
63
+ this.orgUpdateTop = __orgUpdateTop;
64
+ this.status = true;
65
+ return;
66
+ }
67
+ //相对了10次不在检查
68
+ if(this.eqMaxTimer >= 3) {
69
+ this.status = true;
70
+ __orgUpdateTop = this.orgUpdateTop;
71
+ return
72
+ }
73
+ if(this.virtualVue.$refs[this.$el]) {
74
+ let offsetTop = this.virtualVue.$refs[this.$el].$el.getBoundingClientRect().top;
75
+ if(this.offsetTop === offsetTop) {
76
+ this.eqMaxTimer++;
77
+ }
78
+ else this.offsetTop = offsetTop;
79
+ this.orgUpdateTop = offsetTop + this.otherHeight;
80
+ if(this.virtualType === 'fixed') this.computedMinAndMaxFixed();
81
+ }
82
+ setTimeout(()=>{
83
+ this.checkOffsetTop();
84
+ }, 200)
85
+ }
86
+
87
+ cloneDeep(data){
88
+ return JSON.parse(JSON.stringify(data));
89
+ }
90
+
91
+ computedMinAndMaxFixed(){
92
+ let itemHeight = this.virtualFixedItemHeight;
93
+ this.virtualTotalData.map((item,index)=>{
94
+ if(index === 0) {
95
+ this.virtualHeightObj[index] = {
96
+ min: this.orgUpdateTop,
97
+ max: this.orgUpdateTop + itemHeight
98
+ }
99
+ }
100
+ else {
101
+ let prev = this.virtualHeightObj[index-1];
102
+ this.virtualHeightObj[index] = {
103
+ min: prev.max,
104
+ max: prev.max + itemHeight
105
+ }
106
+ }
107
+ });
108
+ }
109
+
110
+ pushVirtualData(data, height){
111
+ //清空响应对象
112
+ this.virtualVue.virtualViewData = null;
113
+ if(this.virtualTotalData.length > 0) this.isFirst = false;
114
+
115
+ //非固定模式
116
+ if(this.virtualType === 'auto') {
117
+ if(!height) throw new Error(`height is require, got is ${height}`);
118
+ this.virtualHeightObj = Object.assign({},this.virtualHeightObj, this.cloneDeep(height));
119
+ }
120
+
121
+ //固定模式
122
+ if(this.virtualType === 'fixed') {
123
+ this.virtualTotalData = this.virtualTotalData.concat(this.cloneDeep(data));
124
+ this.computedMinAndMaxFixed();
125
+ if(this.isFirst) this.onScrollEvent(0);
126
+ }
127
+
128
+ this.isFirst = false
129
+ }
130
+
131
+ /**
132
+ * @description 滚动事件
133
+ * @param scrollTop
134
+ */
135
+ onScrollEvent(scrollTop) {
136
+ //非固定计算索引
137
+ let time = new Date().getTime();
138
+ //计算开始索引
139
+ Object.keys(this.virtualHeightObj).map((key,index)=>{
140
+ let top = scrollTop - this.virtualBufferHeight;
141
+
142
+ //滚动高度小于元素顶部与屏幕顶部偏移量直接取值0索引
143
+ if(top <= this.orgUpdateTop) {
144
+ this.startIndex = 0;
145
+ return;
146
+ }
147
+
148
+
149
+ ////距离底部有1屏幕高度
150
+ let maxScroll = this.virtualHeightObj[this.virtualTotalData.length -1].max - this.screenHeight;
151
+ if(scrollTop >= maxScroll) {
152
+ top = maxScroll;
153
+ }
154
+
155
+ if(top >= this.virtualHeightObj[key].min && top < this.virtualHeightObj[key].max){
156
+ this.startIndex = Number(key);
157
+ }
158
+ })
159
+
160
+ //计算结束索引
161
+ this.endIndex = this.virtualTotalData.length;
162
+ Object.keys(this.virtualHeightObj).map((key,index)=>{
163
+ let top = scrollTop <= this.orgUpdateTop ? this.orgUpdateTop : scrollTop
164
+ let endScrollTop = top + this.screenHeight + this.virtualBufferHeight;
165
+ if(endScrollTop >= this.virtualHeightObj[key].min && endScrollTop < this.virtualHeightObj[key].max){
166
+ this.endIndex = Number(key);
167
+ }
168
+ });
169
+
170
+
171
+ this.top = this.virtualHeightObj[this.startIndex].min - this.orgUpdateTop.toString() + 'px'
172
+ this.bottom = this.virtualHeightObj[this.virtualTotalData.length-1].max - this.virtualHeightObj[this.endIndex-1].max.toString() + 'px'
173
+ console.log('onScrollEvent.index',this.endIndex - this.startIndex, this.startIndex,this.endIndex, this.top, this.bottom)
174
+
175
+ /**@type Function **/
176
+ this.virtualCallback({
177
+ paddingTop:this.top,
178
+ paddingBottom: this.bottom,
179
+ data:this.cloneDeep(this.virtualTotalData).slice(this.startIndex, this.endIndex + 1)}
180
+ );
181
+ }
182
+ }
183
+
184
+