@dolphinweex/weex-harmony 0.1.25 → 0.1.27
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.
@@ -4,113 +4,107 @@
|
|
4
4
|
:class="{ editMode: data.isEditing }"
|
5
5
|
:style="gridItemStyle"
|
6
6
|
>
|
7
|
-
|
8
|
-
|
7
|
+
<div class="grid-items-wrapper">
|
8
|
+
<transition-group name="grid-fade" tag="div" class="grid-inner-wrapper">
|
9
|
+
<div
|
10
|
+
v-for="(item, index) in processedList"
|
11
|
+
:key="item.itemView.id"
|
12
|
+
class="grid-item"
|
13
|
+
:class="{
|
14
|
+
'being-dragged': draggingIndex === index,
|
15
|
+
hidden: isDragClone && draggingIndex === index,
|
16
|
+
'hover-target': hoverIndex === index && draggingIndex !== index,
|
17
|
+
'disabled-item': item.itemView.enable === false,
|
18
|
+
}"
|
19
|
+
:style="{
|
20
|
+
overflow: data.isEditing ? 'visible' : 'hidden',
|
21
|
+
}"
|
22
|
+
@touchstart="(event) => startLongPress(event, index)"
|
23
|
+
@touchmove="checkLongPressMove"
|
24
|
+
@touchend="endTouch"
|
25
|
+
@touchcancel="endTouch"
|
26
|
+
:data-index="index"
|
27
|
+
>
|
9
28
|
<div
|
10
|
-
v-
|
11
|
-
|
12
|
-
|
13
|
-
:
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
:
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
29
|
+
v-if="item.bgAnimView && item.bgAnimView.animUrl && !data.isEditing"
|
30
|
+
class="lottie-container bg-anim"
|
31
|
+
:style="applyNormalAttribute(item.bgAnimView)"
|
32
|
+
:ref="`bgAnim-${item.itemView.id}`"
|
33
|
+
></div>
|
34
|
+
<div
|
35
|
+
v-if="
|
36
|
+
item.frontAnimView &&
|
37
|
+
item.frontAnimView.animUrl &&
|
38
|
+
!data.isEditing
|
39
|
+
"
|
40
|
+
class="lottie-container front-anim"
|
41
|
+
:style="applyNormalAttribute(item.frontAnimView)"
|
42
|
+
:ref="`frontAnim-${item.itemView.id}`"
|
43
|
+
></div>
|
44
|
+
<div
|
45
|
+
:style="applyNormalAttribute(item.itemView)"
|
46
|
+
class="grid-box"
|
47
|
+
:class="{ shaking: data.isEditing }"
|
48
|
+
@click.stop="(e) => itemViewClick(e, item, index)"
|
49
|
+
|
27
50
|
>
|
28
|
-
<div
|
29
|
-
|
30
|
-
item.
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
<div @click.stop.prevent v-if="!data.isEditing">
|
76
|
-
<img
|
77
|
-
:src="item.rightIcon.url"
|
78
|
-
:style="applyNormalAttribute(item.rightIcon)"
|
79
|
-
@click.stop.prevent="(e) => rightIconClick(e)"
|
80
|
-
/>
|
81
|
-
</div>
|
82
|
-
<div @click.stop.prevent v-if="!data.isEditing">
|
83
|
-
<img
|
84
|
-
class="leftTopIcon"
|
85
|
-
:src="item.leftTopIcon.url"
|
86
|
-
:style="applyNormalAttribute(item.leftTopIcon)"
|
87
|
-
@click.stop.prevent
|
88
|
-
/>
|
89
|
-
</div>
|
90
|
-
<div @click.stop.prevent v-if="data.isEditing">
|
91
|
-
<img
|
92
|
-
class="isSelected"
|
93
|
-
@click.stop.prevent="
|
94
|
-
(e) => selectIconClick(e, item, index)
|
95
|
-
"
|
96
|
-
:src="
|
97
|
-
item.itemView.isSelected
|
98
|
-
? item.selectIcon.selectedUrl
|
99
|
-
: item.selectIcon.url
|
100
|
-
"
|
101
|
-
:style="applyNormalAttribute(item.selectIcon)"
|
102
|
-
/>
|
103
|
-
</div>
|
51
|
+
<div class="flexBox">
|
52
|
+
<img
|
53
|
+
:src="item.iconImage.url"
|
54
|
+
:style="applyNormalAttribute(item.iconImage)"
|
55
|
+
/>
|
56
|
+
<div>
|
57
|
+
<div @click.stop.prevent v-if="!data.isEditing">
|
58
|
+
<button
|
59
|
+
class="actionButton"
|
60
|
+
@click.stop.prevent="(e) => actionClick(e, item, index)"
|
61
|
+
:style="applyNormalAttribute(item.actionButton)"
|
62
|
+
>
|
63
|
+
{{ item.actionButton.text }}
|
64
|
+
</button>
|
65
|
+
<div
|
66
|
+
v-if="item.loadingAnimView && item.loadingAnimView.animUrl"
|
67
|
+
class="loading-anim"
|
68
|
+
:style="applyNormalAttribute(item.loadingAnimView)"
|
69
|
+
:ref="`loadingAnim-${item.itemView.id}`"
|
70
|
+
></div>
|
71
|
+
</div>
|
72
|
+
<div @click.stop.prevent v-if="!data.isEditing">
|
73
|
+
<img
|
74
|
+
:src="item.rightIcon.url"
|
75
|
+
:style="applyNormalAttribute(item.rightIcon)"
|
76
|
+
@click.stop.prevent="(e) => rightIconClick(e)"
|
77
|
+
/>
|
78
|
+
</div>
|
79
|
+
<div @click.stop.prevent v-if="!data.isEditing">
|
80
|
+
<img
|
81
|
+
class="leftTopIcon"
|
82
|
+
:src="item.leftTopIcon.url"
|
83
|
+
:style="applyNormalAttribute(item.leftTopIcon)"
|
84
|
+
@click.stop.prevent
|
85
|
+
/>
|
86
|
+
</div>
|
87
|
+
<div @click.stop.prevent v-if="data.isEditing">
|
88
|
+
<img
|
89
|
+
class="isSelected"
|
90
|
+
@click.stop.prevent="(e) => selectIconClick(e, item, index)"
|
91
|
+
:src="
|
92
|
+
item.itemView.isSelected
|
93
|
+
? item.selectIcon.selectedUrl
|
94
|
+
: item.selectIcon.url
|
95
|
+
"
|
96
|
+
:style="applyNormalAttribute(item.selectIcon)"
|
97
|
+
/>
|
104
98
|
</div>
|
105
99
|
</div>
|
106
|
-
|
107
|
-
|
108
|
-
|
100
|
+
</div>
|
101
|
+
<div class="itemText" :style="[applyNormalAttribute(item.text)]">
|
102
|
+
{{ item.text.text }}
|
109
103
|
</div>
|
110
104
|
</div>
|
111
|
-
</
|
112
|
-
</
|
113
|
-
|
105
|
+
</div>
|
106
|
+
</transition-group>
|
107
|
+
</div>
|
114
108
|
|
115
109
|
<!-- 拖拽克隆元素 -->
|
116
110
|
<div v-if="isDragClone" class="drag-clone" :style="dragCloneStyle">
|
@@ -175,7 +169,7 @@ export default {
|
|
175
169
|
processedList: [],
|
176
170
|
selected: null,
|
177
171
|
longPressTimer: null,
|
178
|
-
longPressDuration:
|
172
|
+
longPressDuration: 400, // 略微延长长按时间,减少误触发
|
179
173
|
longPressStartIndex: null,
|
180
174
|
draggingIndex: null,
|
181
175
|
hoverIndex: null,
|
@@ -184,6 +178,7 @@ export default {
|
|
184
178
|
isAnimating: false,
|
185
179
|
touchStartX: 0,
|
186
180
|
touchStartY: 0,
|
181
|
+
touchStartTime: 0, // 记录触摸开始时间,用于计算滑动速度
|
187
182
|
draggedItemRect: null,
|
188
183
|
isDragClone: false,
|
189
184
|
dragCloneX: 0,
|
@@ -193,13 +188,17 @@ export default {
|
|
193
188
|
gridBoxWidth: 0,
|
194
189
|
lottieAnimations: {},
|
195
190
|
isScrolling: false,
|
196
|
-
scrollThreshold:
|
191
|
+
scrollThreshold: 8, // 增大滚动检测阈值
|
197
192
|
fixedItemWidth: 0,
|
198
193
|
fixedItemHeight: 0,
|
199
194
|
animationFrameId: null,
|
200
195
|
lastBestTarget: null,
|
201
196
|
targetChangeTime: null,
|
202
197
|
pendingTarget: null,
|
198
|
+
weexListInnerEl: null,
|
199
|
+
weexRefreshEl: null,
|
200
|
+
originListInnerStyle: null,
|
201
|
+
originRefreshStyle: null,
|
203
202
|
};
|
204
203
|
},
|
205
204
|
computed: {
|
@@ -207,7 +206,9 @@ export default {
|
|
207
206
|
return {
|
208
207
|
'--grid-cols': this.data.spanCount || this.cols,
|
209
208
|
'--grid-gap': `${this.data.spaceSize || 8}px`,
|
210
|
-
'--grid-margin': `${
|
209
|
+
'--grid-margin': `${
|
210
|
+
this.data.layoutConfig.marginStart + this.data.layoutConfig.marginEnd
|
211
|
+
}px`,
|
211
212
|
marginTop: this.data.layoutConfig.marginTop * scla,
|
212
213
|
marginBottom: this.data.layoutConfig.marginBottom * scla,
|
213
214
|
marginLeft: this.data.layoutConfig.marginStart * scla,
|
@@ -246,121 +247,71 @@ export default {
|
|
246
247
|
console.log('updateListItem收到数据:', JSON.stringify(data));
|
247
248
|
const id = data.itemView.id;
|
248
249
|
const index = this.processedList.findIndex(
|
249
|
-
(item) => item.itemView.id
|
250
|
+
(item) => item.itemView.id == id
|
250
251
|
);
|
251
252
|
const dataIndex = this.data.list.findIndex(
|
252
|
-
(item) => item.itemView.id
|
253
|
+
(item) => item.itemView.id == id
|
253
254
|
);
|
254
|
-
|
255
|
+
// 更新原始数据以确保watch能触发
|
256
|
+
if(dataIndex !== -1) {
|
257
|
+
// 使用Vue的$set确保响应式更新
|
258
|
+
this.$set(this.data.list, dataIndex, JSON.parse(JSON.stringify(data)));
|
259
|
+
}
|
255
260
|
if (index === -1) {
|
256
261
|
return;
|
257
262
|
}
|
258
|
-
|
259
|
-
// 保存更新前的可见性状态用于比较
|
260
|
-
const oldVisibility = this.processedList[index].actionButton.visibility;
|
261
|
-
const newVisibility = data.actionButton.visibility;
|
262
|
-
|
263
|
-
// 检查是否有动画URL的变化
|
264
|
-
const oldBgAnimUrl = this.processedList[index].bgAnimView.animUrl || '';
|
265
|
-
const oldLoadingAnimUrl =
|
266
|
-
this.processedList[index].loadingAnimView.animUrl || '';
|
267
|
-
const oldFrontAnimUrl =
|
268
|
-
this.processedList[index].frontAnimView.animUrl || '';
|
269
|
-
|
270
263
|
const newBgAnimUrl = data.bgAnimView.animUrl || '';
|
271
264
|
const newLoadingAnimUrl = data.loadingAnimView.animUrl || '';
|
272
265
|
const newFrontAnimUrl = data.frontAnimView.animUrl || '';
|
273
|
-
|
274
|
-
const hasAnimUrlChanged =
|
275
|
-
oldBgAnimUrl !== newBgAnimUrl ||
|
276
|
-
oldLoadingAnimUrl !== newLoadingAnimUrl ||
|
277
|
-
oldFrontAnimUrl !== newFrontAnimUrl;
|
278
|
-
|
279
266
|
// 同时更新processedList和原始data.list数据
|
280
267
|
this.processedList[index] = data;
|
281
268
|
this.processedList = [...this.processedList];
|
282
269
|
|
283
|
-
// 更新原始数据以确保watch能触发
|
284
|
-
if (dataIndex !== -1) {
|
285
|
-
// 使用Vue的$set确保响应式更新
|
286
|
-
this.$set(this.data.list, dataIndex, JSON.parse(JSON.stringify(data)));
|
287
|
-
}
|
288
|
-
|
289
|
-
// 如果动画URL有变化,重新初始化相关的Lottie动画
|
290
|
-
if (hasAnimUrlChanged) {
|
291
270
|
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
271
|
+
// 无论是否有URL变化,都处理动画更新
|
272
|
+
// 这样确保任何visibility或其他属性变化也能被处理
|
273
|
+
this.$nextTick(() => {
|
274
|
+
// 清理旧的动画实例
|
275
|
+
const itemId = String(data.itemView.id);
|
276
|
+
// 加载背景动画
|
277
|
+
if (newBgAnimUrl) {
|
278
|
+
this.loadLottieAnimation(
|
279
|
+
data.bgAnimView,
|
280
|
+
`bgAnim-${itemId}`,
|
299
281
|
`bg-${itemId}`,
|
282
|
+
data,
|
283
|
+
dataIndex
|
284
|
+
);
|
285
|
+
}
|
286
|
+
if (newLoadingAnimUrl) {
|
287
|
+
this.loadLottieAnimation(
|
288
|
+
data.loadingAnimView,
|
289
|
+
`loadingAnim-${itemId}`,
|
300
290
|
`loading-${itemId}`,
|
291
|
+
data,
|
292
|
+
dataIndex
|
293
|
+
);
|
294
|
+
}
|
295
|
+
if (newFrontAnimUrl) {
|
296
|
+
this.loadLottieAnimation(
|
297
|
+
data.frontAnimView,
|
298
|
+
`frontAnim-${itemId}`,
|
301
299
|
`front-${itemId}`,
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
anim.removeEventListener('complete');
|
308
|
-
anim.removeEventListener('DOMLoaded');
|
309
|
-
anim.removeEventListener('data_ready');
|
310
|
-
anim.removeEventListener('loaded_images');
|
311
|
-
anim.removeEventListener('loopComplete');
|
312
|
-
} catch (e) {
|
313
|
-
}
|
314
|
-
anim.destroy();
|
315
|
-
delete this.lottieAnimations[key];
|
316
|
-
}
|
317
|
-
});
|
318
|
-
|
319
|
-
|
320
|
-
// 延迟一点时间确保DOM完全更新
|
321
|
-
setTimeout(() => {
|
322
|
-
// 重新初始化背景动画
|
323
|
-
if (newBgAnimUrl) {
|
324
|
-
this.loadLottieAnimation(
|
325
|
-
data.bgAnimView,
|
326
|
-
`bgAnim-${itemId}`,
|
327
|
-
`bg-${itemId}`,
|
328
|
-
data
|
329
|
-
);
|
330
|
-
}
|
331
|
-
|
332
|
-
// 重新初始化加载动画
|
333
|
-
if (newLoadingAnimUrl) {
|
334
|
-
this.loadLottieAnimation(
|
335
|
-
data.loadingAnimView,
|
336
|
-
`loadingAnim-${itemId}`,
|
337
|
-
`loading-${itemId}`,
|
338
|
-
data
|
339
|
-
);
|
340
|
-
}
|
341
|
-
|
342
|
-
// 重新初始化前景动画
|
343
|
-
if (newFrontAnimUrl) {
|
344
|
-
this.loadLottieAnimation(
|
345
|
-
data.frontAnimView,
|
346
|
-
`frontAnim-${itemId}`,
|
347
|
-
`front-${itemId}`,
|
348
|
-
data
|
349
|
-
);
|
350
|
-
}
|
351
|
-
}, 100); // 增加延迟确保DOM已更新和旧动画已完全销毁
|
352
|
-
});
|
353
|
-
}
|
300
|
+
data,
|
301
|
+
dataIndex
|
302
|
+
);
|
303
|
+
}
|
304
|
+
});
|
354
305
|
},
|
355
306
|
getListData(callback) {
|
356
307
|
let data = Array.from(this.processedList);
|
357
|
-
data = data.map((item)=>({
|
308
|
+
data = data.map((item) => ({
|
358
309
|
...item,
|
359
310
|
itemView: {
|
360
311
|
...item.itemView,
|
361
|
-
id:String(item.itemView.id)
|
362
|
-
}
|
363
|
-
}))
|
312
|
+
id: String(item.itemView.id),
|
313
|
+
},
|
314
|
+
}));
|
364
315
|
callback({ listData: data });
|
365
316
|
},
|
366
317
|
rightIconClick(e) {
|
@@ -386,7 +337,7 @@ export default {
|
|
386
337
|
...e,
|
387
338
|
};
|
388
339
|
this.$emit('onClickSelectIcon', target);
|
389
|
-
this.$emit('onSelectItems',target)
|
340
|
+
this.$emit('onSelectItems', target);
|
390
341
|
return false;
|
391
342
|
},
|
392
343
|
|
@@ -401,7 +352,7 @@ export default {
|
|
401
352
|
this.cancelLongPress();
|
402
353
|
if (this.data.isEditing) {
|
403
354
|
item.itemView.isSelected = !item.itemView.isSelected;
|
404
|
-
this.$emit('onSelectItems',target)
|
355
|
+
this.$emit('onSelectItems', target);
|
405
356
|
return;
|
406
357
|
}
|
407
358
|
const target = {
|
@@ -416,10 +367,6 @@ export default {
|
|
416
367
|
actionClick(e, item, index) {
|
417
368
|
e.preventDefault();
|
418
369
|
e.stopPropagation(); // 阻止事件冒泡到itemViewClick
|
419
|
-
|
420
|
-
// 在触发事件前,先清理所有其他项目的动画实例
|
421
|
-
this.cleanupOtherAnimations(item.itemView.id);
|
422
|
-
|
423
370
|
const target = {
|
424
371
|
...item.itemView,
|
425
372
|
id: String(item.itemView.id),
|
@@ -430,51 +377,6 @@ export default {
|
|
430
377
|
return false;
|
431
378
|
},
|
432
379
|
|
433
|
-
// 新增方法:清理除指定项目外的所有动画实例
|
434
|
-
cleanupOtherAnimations(currentItemId) {
|
435
|
-
|
436
|
-
// 遍历所有动画实例
|
437
|
-
Object.keys(this.lottieAnimations).forEach((key) => {
|
438
|
-
// 检查是否为其他项目的动画
|
439
|
-
if (!key.includes(`-${currentItemId}`)) {
|
440
|
-
if (this.lottieAnimations[key]) {
|
441
|
-
const anim = this.lottieAnimations[key];
|
442
|
-
|
443
|
-
// 移除所有事件监听器
|
444
|
-
try {
|
445
|
-
anim.removeEventListener('complete');
|
446
|
-
anim.removeEventListener('DOMLoaded');
|
447
|
-
anim.removeEventListener('data_ready');
|
448
|
-
anim.removeEventListener('loaded_images');
|
449
|
-
anim.removeEventListener('loopComplete');
|
450
|
-
} catch (e) {
|
451
|
-
console.warn(`移除事件监听器失败: ${e.message}`);
|
452
|
-
}
|
453
|
-
|
454
|
-
anim.destroy();
|
455
|
-
delete this.lottieAnimations[key];
|
456
|
-
|
457
|
-
// 提取项目ID和动画类型
|
458
|
-
const parts = key.split('-');
|
459
|
-
if (parts.length === 2) {
|
460
|
-
const animType = parts[0]; // bg, loading, front
|
461
|
-
const itemId = parts[1];
|
462
|
-
|
463
|
-
// 隐藏对应的动画容器
|
464
|
-
this.$nextTick(() => {
|
465
|
-
const refName = `${animType}Anim-${itemId}`;
|
466
|
-
const animContainer =
|
467
|
-
this.$refs[refName] && this.$refs[refName][0];
|
468
|
-
if (animContainer) {
|
469
|
-
animContainer.style.display = 'none';
|
470
|
-
}
|
471
|
-
});
|
472
|
-
}
|
473
|
-
}
|
474
|
-
}
|
475
|
-
});
|
476
|
-
},
|
477
|
-
|
478
380
|
// 生成处理后的数据列表
|
479
381
|
generateDataList() {
|
480
382
|
if (!this.data || !this.data.list || !this.data.globalData) {
|
@@ -574,12 +476,17 @@ export default {
|
|
574
476
|
},
|
575
477
|
// 开始长按
|
576
478
|
startLongPress(e, index) {
|
479
|
+
console.log(e, 'cdj-------startLongPress');
|
577
480
|
if (!this.data.isEditable) {
|
578
481
|
return;
|
579
482
|
}
|
580
|
-
|
483
|
+
|
484
|
+
// 确保事件不被其他处理器抢先处理
|
485
|
+
// e.oriEvent.stopPropagation();
|
486
|
+
|
581
487
|
// 清除任何现有计时器
|
582
488
|
this.cancelLongPress();
|
489
|
+
|
583
490
|
// 记录起始触摸位置和索引
|
584
491
|
const touch = e.changedTouches[0];
|
585
492
|
this.touchStartX = touch.pageX;
|
@@ -587,13 +494,8 @@ export default {
|
|
587
494
|
this.longPressStartIndex = index;
|
588
495
|
this.isScrolling = false; // 重置滚动状态
|
589
496
|
|
590
|
-
//
|
591
|
-
|
592
|
-
passive: true, // 设置为passive:true允许浏览器进行滚动优化
|
593
|
-
});
|
594
|
-
document.removeEventListener('touchend', this.onTouchEnd, {
|
595
|
-
passive: true,
|
596
|
-
});
|
497
|
+
// 记录触摸开始时间,用于判断是否为快速滑动
|
498
|
+
this.touchStartTime = Date.now();
|
597
499
|
|
598
500
|
if (this.isTouchDragging) {
|
599
501
|
this.$emit('drag-end', {
|
@@ -601,23 +503,27 @@ export default {
|
|
601
503
|
});
|
602
504
|
}
|
603
505
|
|
506
|
+
// 通知外部触摸开始事件
|
507
|
+
this.$emit('onDragEventStart', e);
|
604
508
|
|
605
|
-
// 设置新的长按计时器
|
509
|
+
// 设置新的长按计时器 - 延长一点时间避免误触发
|
606
510
|
this.longPressTimer = setTimeout(() => {
|
607
511
|
// 只有在没有滚动的情况下才激活拖拽模式
|
608
512
|
if (!this.isScrolling) {
|
513
|
+
console.log('长按时间到,激活拖拽模式');
|
609
514
|
this.activateDragMode(index);
|
515
|
+
} else {
|
516
|
+
console.log('检测到滚动,取消拖拽激活');
|
610
517
|
}
|
611
518
|
}, this.longPressDuration);
|
612
|
-
// 不阻止默认行为 - 允许滚动
|
613
519
|
},
|
614
520
|
|
615
521
|
// 检查长按过程中的移动
|
616
522
|
checkLongPressMove(e) {
|
617
|
-
this.data.isEditing && e.oriEvent.stopPropagation()
|
618
523
|
if (!this.data.isEditable) {
|
619
524
|
return;
|
620
525
|
}
|
526
|
+
|
621
527
|
const touch = e.changedTouches[0];
|
622
528
|
// 如果已经在拖拽模式,交给onTouchMove处理
|
623
529
|
if (this.isTouchDragging) {
|
@@ -628,68 +534,98 @@ export default {
|
|
628
534
|
const moveX = Math.abs(touch.pageX - this.touchStartX);
|
629
535
|
const moveY = Math.abs(touch.pageY - this.touchStartY);
|
630
536
|
|
631
|
-
//
|
632
|
-
|
633
|
-
|
537
|
+
// 计算触摸移动速度 (像素/毫秒)
|
538
|
+
const currentTime = Date.now();
|
539
|
+
const timeDiff = currentTime - this.touchStartTime;
|
540
|
+
const speedY = moveY / Math.max(1, timeDiff); // 垂直滑动速度
|
541
|
+
|
542
|
+
// 速度检测:快速滑动可能表示滚动意图
|
543
|
+
const isQuickSwipe = speedY > 0.5; // 如果垂直滑动速度大于0.5px/ms,判定为快速滑动
|
544
|
+
|
545
|
+
// 更敏感地检测滚动意图
|
546
|
+
// 1. 垂直移动显著大于水平移动
|
547
|
+
// 2. 垂直移动超过阈值的两倍
|
548
|
+
// 3. 快速垂直滑动
|
549
|
+
if (
|
550
|
+
(moveY > moveX * 1.2 && moveY > this.scrollThreshold) ||
|
551
|
+
moveY > this.scrollThreshold * 2 ||
|
552
|
+
(isQuickSwipe && moveY > this.scrollThreshold)
|
553
|
+
) {
|
554
|
+
console.log('检测到滚动意图,取消长按', { moveY, moveX, speedY });
|
634
555
|
this.isScrolling = true;
|
635
556
|
this.cancelLongPress();
|
636
557
|
return;
|
637
558
|
}
|
638
559
|
|
639
|
-
// 如果移动超过阈值,取消长按
|
560
|
+
// 如果移动超过阈值,取消长按 - 但不阻止默认行为
|
640
561
|
if (moveX > this.scrollThreshold || moveY > this.scrollThreshold) {
|
641
562
|
this.cancelLongPress();
|
563
|
+
return;
|
642
564
|
}
|
643
565
|
|
644
|
-
//
|
566
|
+
// 只有确认不是滚动意图,且在长按倒计时中,才阻止默认行为
|
567
|
+
if (this.longPressTimer && !this.isScrolling) {
|
568
|
+
e.oriEvent.preventDefault();
|
569
|
+
}
|
645
570
|
},
|
646
571
|
|
647
572
|
// 激活拖拽模式
|
648
573
|
activateDragMode(index) {
|
649
574
|
console.log('长按触发,进入编辑模式');
|
650
|
-
// 进入编辑模式
|
651
|
-
this.data.isEditing = true;
|
652
|
-
this.$emit('onEditStateChanged', true);
|
653
|
-
// 设置当前拖拽索引
|
654
|
-
this.draggingIndex = index;
|
655
|
-
this.isTouchDragging = true;
|
656
|
-
|
657
|
-
// 此时添加阻止默认行为的事件监听,但只影响拖拽状态下的行为
|
658
|
-
document.addEventListener('touchmove', this.onTouchMove, {
|
659
|
-
passive: false, // 只有在拖拽模式下才阻止默认行为
|
660
|
-
});
|
661
|
-
document.addEventListener('touchend', this.onTouchEnd, {
|
662
|
-
passive: true,
|
663
|
-
});
|
664
575
|
|
665
|
-
//
|
666
|
-
this.
|
667
|
-
|
668
|
-
|
669
|
-
|
576
|
+
// 先确保编辑模式已开启
|
577
|
+
if (!this.data.isEditing) {
|
578
|
+
// 设置编辑状态并隐藏weex-refresh
|
579
|
+
this.data.isEditing = true;
|
580
|
+
this.$emit('onEditStateChanged', true);
|
581
|
+
} else {
|
582
|
+
// 无论之前是否处于编辑模式,都设置拖拽状态
|
583
|
+
// 设置当前拖拽索引
|
584
|
+
this.draggingIndex = index;
|
585
|
+
this.isTouchDragging = true;
|
586
|
+
// 使用存储的固定宽高
|
587
|
+
this.draggedItemRect = {
|
588
|
+
width: this.fixedItemWidth,
|
589
|
+
height: this.fixedItemHeight,
|
590
|
+
};
|
591
|
+
|
592
|
+
// 获取当前元素位置用于计算偏移
|
593
|
+
const element = document.querySelectorAll('.grid-item')[index];
|
594
|
+
if (element) {
|
595
|
+
const rect = element.getBoundingClientRect();
|
596
|
+
// 计算触摸点相对于元素左上角的偏移
|
597
|
+
this.touchOffsetX = this.touchStartX - rect.left;
|
598
|
+
this.touchOffsetY = this.touchStartY - rect.top;
|
599
|
+
|
600
|
+
// 设置克隆元素的初始位置
|
601
|
+
this.dragCloneX = rect.left;
|
602
|
+
this.dragCloneY = rect.top;
|
603
|
+
|
604
|
+
// 显示拖拽克隆
|
605
|
+
this.isDragClone = true;
|
606
|
+
|
607
|
+
// 禁止页面滚动
|
608
|
+
document.body.style.overflow = 'hidden';
|
609
|
+
document.body.style.touchAction = 'none';
|
610
|
+
|
611
|
+
// 添加全局触摸事件处理,确保捕获所有触摸事件
|
612
|
+
document.addEventListener('touchmove', this.onGlobalTouchMove, {
|
613
|
+
passive: false,
|
614
|
+
capture: true,
|
615
|
+
});
|
616
|
+
document.addEventListener('touchend', this.onTouchEnd, {
|
617
|
+
passive: false,
|
618
|
+
capture: true,
|
619
|
+
});
|
670
620
|
|
671
|
-
|
672
|
-
|
673
|
-
|
674
|
-
|
675
|
-
|
676
|
-
this.touchOffsetX = this.touchStartX - rect.left;
|
677
|
-
this.touchOffsetY = this.touchStartY - rect.top;
|
678
|
-
|
679
|
-
// 设置克隆元素的初始位置
|
680
|
-
this.dragCloneX = rect.left;
|
681
|
-
this.dragCloneY = rect.top;
|
682
|
-
|
683
|
-
// 显示拖拽克隆
|
684
|
-
this.isDragClone = true;
|
685
|
-
|
686
|
-
// 立即执行一次定位以确保初始位置准确
|
687
|
-
requestAnimationFrame(() => {
|
688
|
-
this.dragCloneX = this.touchStartX - this.touchOffsetX;
|
689
|
-
this.dragCloneY = this.touchStartY - this.touchOffsetY;
|
690
|
-
});
|
621
|
+
// 立即执行一次定位以确保初始位置准确
|
622
|
+
requestAnimationFrame(() => {
|
623
|
+
this.dragCloneX = this.touchStartX - this.touchOffsetX;
|
624
|
+
this.dragCloneY = this.touchStartY - this.touchOffsetY;
|
625
|
+
});
|
691
626
|
|
692
|
-
|
627
|
+
console.log('拖拽克隆已创建');
|
628
|
+
}
|
693
629
|
}
|
694
630
|
|
695
631
|
this.longPressTimer = null;
|
@@ -702,12 +638,45 @@ export default {
|
|
702
638
|
this.longPressTimer = null;
|
703
639
|
}
|
704
640
|
this.longPressStartIndex = null;
|
641
|
+
|
642
|
+
// 确保不再阻止滚动
|
643
|
+
if (this.isScrolling) {
|
644
|
+
// 如果已经确定为滚动意图,应该立即恢复系统默认滚动行为
|
645
|
+
document.body.style.overflow = '';
|
646
|
+
document.body.style.touchAction = '';
|
647
|
+
}
|
648
|
+
},
|
649
|
+
|
650
|
+
// 全局触摸移动处理 - 捕获阶段拦截所有触摸移动
|
651
|
+
onGlobalTouchMove(e) {
|
652
|
+
if (this.isTouchDragging) {
|
653
|
+
// 在捕获阶段强制阻止默认行为,防止页面滚动
|
654
|
+
e.preventDefault();
|
655
|
+
e.stopPropagation();
|
656
|
+
|
657
|
+
// 继续处理拖拽逻辑
|
658
|
+
this.handleTouchMove(e);
|
659
|
+
}
|
705
660
|
},
|
706
661
|
|
707
662
|
// 触摸移动处理
|
708
663
|
onTouchMove(e) {
|
709
664
|
if (!this.isTouchDragging) return;
|
710
665
|
|
666
|
+
// 当处于拖拽状态时,阻止默认行为
|
667
|
+
if (this.isTouchDragging) {
|
668
|
+
e.oriEvent.preventDefault();
|
669
|
+
e.oriEvent.stopPropagation();
|
670
|
+
}
|
671
|
+
|
672
|
+
this.handleTouchMove(e);
|
673
|
+
},
|
674
|
+
|
675
|
+
// 抽取通用的触摸移动处理逻辑
|
676
|
+
handleTouchMove(e) {
|
677
|
+
console.log(this.isTouchDragging, 'this.isTouchDragging111111');
|
678
|
+
if (!this.isTouchDragging) return;
|
679
|
+
|
711
680
|
const touch = e.changedTouches[0];
|
712
681
|
|
713
682
|
// 更新目标位置而非直接设置
|
@@ -762,9 +731,9 @@ export default {
|
|
762
731
|
);
|
763
732
|
const centerScore = 1 - distanceFromCenter;
|
764
733
|
|
765
|
-
//
|
766
|
-
//
|
767
|
-
if (centerScore > maxCenterScore && centerScore > 0.
|
734
|
+
// 放宽元素中心区域的判定,让交换更容易触发
|
735
|
+
// 降低阈值,让交换更敏感
|
736
|
+
if (centerScore > maxCenterScore && centerScore > 0.2) {
|
768
737
|
maxCenterScore = centerScore;
|
769
738
|
bestTarget = itemIndex;
|
770
739
|
}
|
@@ -774,36 +743,24 @@ export default {
|
|
774
743
|
// 设置悬停高亮,仅当有合格的目标时才高亮
|
775
744
|
this.hoverIndex = bestTarget;
|
776
745
|
|
777
|
-
//
|
778
|
-
|
779
|
-
|
780
|
-
|
781
|
-
|
782
|
-
|
783
|
-
|
784
|
-
// 只有当目标持续100ms稳定不变时,才认为是有效目标
|
785
|
-
this.lastBestTarget = this.pendingTarget;
|
786
|
-
this.targetChangeTime = null;
|
787
|
-
this.pendingTarget = null;
|
788
|
-
}
|
789
|
-
} else if (bestTarget === null) {
|
790
|
-
// 如果没有目标,清除防抖状态
|
791
|
-
this.targetChangeTime = null;
|
792
|
-
this.pendingTarget = null;
|
746
|
+
// 简化交换防抖动处理,让交换更直接响应
|
747
|
+
if (bestTarget !== null) {
|
748
|
+
// 直接使用当前的最佳目标
|
749
|
+
this.lastBestTarget = bestTarget;
|
750
|
+
} else {
|
751
|
+
// 如果没有目标,清除lastBestTarget
|
752
|
+
this.lastBestTarget = null;
|
793
753
|
}
|
794
754
|
|
795
755
|
// 使用已稳定的目标进行交换
|
796
756
|
bestTarget = this.lastBestTarget;
|
797
757
|
|
798
|
-
//
|
758
|
+
// 控制交换频率,不要太高,但也不要太慢
|
799
759
|
const now = Date.now();
|
800
|
-
if (now - this.lastSwapTime <
|
760
|
+
if (now - this.lastSwapTime < 150 || bestTarget === null) return;
|
801
761
|
|
802
762
|
// 执行交换逻辑
|
803
763
|
if (bestTarget !== this.draggingIndex) {
|
804
|
-
console.log(`交换元素: ${this.draggingIndex} 和 ${bestTarget}`);
|
805
|
-
|
806
|
-
// 使用ES6解构直接交换数组元素
|
807
764
|
[
|
808
765
|
this.processedList[this.draggingIndex],
|
809
766
|
this.processedList[bestTarget],
|
@@ -811,13 +768,16 @@ export default {
|
|
811
768
|
this.processedList[bestTarget],
|
812
769
|
this.processedList[this.draggingIndex],
|
813
770
|
];
|
814
|
-
|
815
|
-
// 同时更新原始数据,保持同步
|
816
771
|
[this.data.list[this.draggingIndex], this.data.list[bestTarget]] = [
|
817
772
|
this.data.list[bestTarget],
|
818
773
|
this.data.list[this.draggingIndex],
|
819
774
|
];
|
820
775
|
|
776
|
+
console.log(this.data.list, 'cdj------this.data.list');
|
777
|
+
|
778
|
+
// 更新processedList以触发视图更新和动画效果
|
779
|
+
this.processedList = this.generateDataList();
|
780
|
+
|
821
781
|
// 更新拖拽索引
|
822
782
|
this.draggingIndex = bestTarget;
|
823
783
|
this.lastSwapTime = now;
|
@@ -827,7 +787,7 @@ export default {
|
|
827
787
|
// 新增:平滑更新拖拽位置的方法
|
828
788
|
updateDragPosition() {
|
829
789
|
// 计算当前位置到目标位置的平滑过渡
|
830
|
-
const easing = 0.
|
790
|
+
const easing = 0.8; // 大幅提高缓动系数,让拖拽更紧跟手指
|
831
791
|
|
832
792
|
this.dragCloneX +=
|
833
793
|
(this.targetTouchX - this.touchOffsetX - this.dragCloneX) * easing;
|
@@ -852,51 +812,74 @@ export default {
|
|
852
812
|
|
853
813
|
// 元素本身的触摸结束
|
854
814
|
endTouch(e) {
|
855
|
-
console.log('
|
815
|
+
console.log('cdj------触摸结束');
|
856
816
|
this.$emit('onDragEventEnd', e);
|
857
817
|
// 如果只是短按(还在计时),就取消长按
|
858
818
|
this.cancelLongPress();
|
859
819
|
|
860
820
|
// 如果正在拖拽中,确保清理状态
|
861
821
|
if (this.isTouchDragging) {
|
822
|
+
// 取消动画帧
|
823
|
+
if (this.animationFrameId) {
|
824
|
+
cancelAnimationFrame(this.animationFrameId);
|
825
|
+
this.animationFrameId = null;
|
826
|
+
}
|
827
|
+
|
862
828
|
// 移除全局事件监听
|
863
|
-
document.removeEventListener('touchmove', this.
|
829
|
+
document.removeEventListener('touchmove', this.onGlobalTouchMove, {
|
864
830
|
passive: false,
|
831
|
+
capture: true,
|
865
832
|
});
|
866
833
|
document.removeEventListener('touchend', this.onTouchEnd, {
|
867
834
|
passive: false,
|
835
|
+
capture: true,
|
868
836
|
});
|
869
837
|
|
870
|
-
//
|
871
|
-
|
872
|
-
|
873
|
-
this.animationFrameId = null;
|
874
|
-
}
|
838
|
+
// 恢复页面滚动
|
839
|
+
document.body.style.overflow = '';
|
840
|
+
document.body.style.touchAction = '';
|
875
841
|
|
876
842
|
this.isTouchDragging = false;
|
877
843
|
this.isDragClone = false;
|
878
844
|
this.hoverIndex = null;
|
879
845
|
this.draggingIndex = null;
|
846
|
+
|
847
|
+
// 如果不再拖拽,恢复touch-action(但保持refresh隐藏,因为仍在编辑状态)
|
848
|
+
const elements = this.findParentElements();
|
849
|
+
if (elements.listInner) {
|
850
|
+
elements.listInner.style.touchAction = this.originListInnerStyle;
|
851
|
+
}
|
880
852
|
}
|
881
853
|
},
|
882
854
|
|
883
855
|
// 触摸结束处理 - 全局事件
|
884
856
|
onTouchEnd(e) {
|
885
|
-
console.log('
|
857
|
+
console.log('cdj------全局触摸结束');
|
858
|
+
|
859
|
+
if (this.isTouchDragging) {
|
860
|
+
// 确保阻止默认行为
|
861
|
+
e.preventDefault();
|
862
|
+
e.stopPropagation();
|
863
|
+
}
|
864
|
+
// 取消动画帧
|
865
|
+
if (this.animationFrameId) {
|
866
|
+
cancelAnimationFrame(this.animationFrameId);
|
867
|
+
this.animationFrameId = null;
|
868
|
+
}
|
886
869
|
|
887
870
|
// 移除全局事件监听
|
888
|
-
document.removeEventListener('touchmove', this.
|
871
|
+
document.removeEventListener('touchmove', this.onGlobalTouchMove, {
|
889
872
|
passive: false,
|
873
|
+
capture: true,
|
890
874
|
});
|
891
875
|
document.removeEventListener('touchend', this.onTouchEnd, {
|
892
876
|
passive: false,
|
877
|
+
capture: true,
|
893
878
|
});
|
894
879
|
|
895
|
-
//
|
896
|
-
|
897
|
-
|
898
|
-
this.animationFrameId = null;
|
899
|
-
}
|
880
|
+
// 恢复页面滚动
|
881
|
+
document.body.style.overflow = '';
|
882
|
+
document.body.style.touchAction = '';
|
900
883
|
|
901
884
|
// 重置拖拽状态
|
902
885
|
this.isTouchDragging = false;
|
@@ -914,7 +897,6 @@ export default {
|
|
914
897
|
if (gridBoxes && gridBoxes.length > 0) {
|
915
898
|
const box = gridBoxes[0];
|
916
899
|
this.gridBoxWidth = box.offsetWidth;
|
917
|
-
console.log('Grid box宽度:', this.gridBoxWidth);
|
918
900
|
|
919
901
|
// 更新text样式,确保不超出
|
920
902
|
const textElements = document.querySelectorAll('.itemText');
|
@@ -927,19 +909,14 @@ export default {
|
|
927
909
|
|
928
910
|
initLottieAnimations() {
|
929
911
|
this.$nextTick(() => {
|
930
|
-
// 清理之前的动画实例
|
931
912
|
Object.keys(this.lottieAnimations).forEach((key) => {
|
932
913
|
const anim = this.lottieAnimations[key];
|
933
914
|
if (anim && typeof anim.destroy === 'function') {
|
934
|
-
console.log(
|
915
|
+
console.log(`cdj------销毁旧动画实例: ${key}`);
|
935
916
|
try {
|
936
917
|
anim.removeEventListener('complete');
|
937
|
-
anim.removeEventListener('DOMLoaded');
|
938
|
-
anim.removeEventListener('data_ready');
|
939
|
-
anim.removeEventListener('loaded_images');
|
940
|
-
anim.removeEventListener('loopComplete');
|
941
918
|
} catch (e) {
|
942
|
-
console.warn(
|
919
|
+
console.warn(`cdj------移除事件监听器失败: ${e.message}`);
|
943
920
|
}
|
944
921
|
anim.destroy();
|
945
922
|
}
|
@@ -950,45 +927,48 @@ export default {
|
|
950
927
|
this.lottieAnimations = {};
|
951
928
|
|
952
929
|
console.log(
|
953
|
-
'
|
930
|
+
'cdj------开始初始化Lottie动画,列表项数量:',
|
954
931
|
this.processedList.length
|
955
932
|
);
|
956
933
|
|
957
|
-
//
|
958
|
-
|
959
|
-
|
960
|
-
|
961
|
-
|
962
|
-
// 加载背景动画
|
934
|
+
// 为每个列表项初始化动画
|
935
|
+
this.processedList.forEach((item) => {
|
936
|
+
const itemId = String(item.itemView.id);
|
937
|
+
// 加载背景动画
|
938
|
+
if (item.bgAnimView && item.bgAnimView.animUrl) {
|
963
939
|
this.loadLottieAnimation(
|
964
940
|
item.bgAnimView,
|
965
941
|
`bgAnim-${itemId}`,
|
966
942
|
`bg-${itemId}`,
|
967
943
|
item
|
968
944
|
);
|
945
|
+
}
|
969
946
|
|
970
|
-
|
947
|
+
// 加载加载中动画
|
948
|
+
if (item.loadingAnimView && item.loadingAnimView.animUrl) {
|
971
949
|
this.loadLottieAnimation(
|
972
950
|
item.loadingAnimView,
|
973
951
|
`loadingAnim-${itemId}`,
|
974
952
|
`loading-${itemId}`,
|
975
953
|
item
|
976
954
|
);
|
955
|
+
}
|
977
956
|
|
978
|
-
|
957
|
+
// 加载前景动画
|
958
|
+
if (item.frontAnimView && item.frontAnimView.animUrl) {
|
979
959
|
this.loadLottieAnimation(
|
980
960
|
item.frontAnimView,
|
981
961
|
`frontAnim-${itemId}`,
|
982
962
|
`front-${itemId}`,
|
983
963
|
item
|
984
964
|
);
|
985
|
-
}
|
986
|
-
}
|
965
|
+
}
|
966
|
+
});
|
987
967
|
});
|
988
968
|
},
|
989
969
|
|
990
970
|
// 抽取公共的loadLottieAnimation方法
|
991
|
-
loadLottieAnimation(animView, refName, animKey, item) {
|
971
|
+
loadLottieAnimation(animView, refName, animKey, item, dataIndex) {
|
992
972
|
if (!animView || !animView.animUrl) {
|
993
973
|
return;
|
994
974
|
}
|
@@ -1010,129 +990,92 @@ export default {
|
|
1010
990
|
typeof animView.visibility !== 'number' ||
|
1011
991
|
animView.visibility !== 0
|
1012
992
|
) {
|
1013
|
-
|
1014
|
-
|
1015
|
-
.
|
1016
|
-
|
1017
|
-
|
1018
|
-
|
1019
|
-
|
1020
|
-
|
1021
|
-
|
1022
|
-
|
1023
|
-
|
1024
|
-
|
993
|
+
if (this.lottieAnimations[animKey]) {
|
994
|
+
this.lottieAnimations[animKey].destroy();
|
995
|
+
delete this.lottieAnimations[animKey];
|
996
|
+
}
|
997
|
+
|
998
|
+
// 创建新的动画实例
|
999
|
+
const anim = lottie.loadAnimation({
|
1000
|
+
container: animEl[0],
|
1001
|
+
renderer: 'svg',
|
1002
|
+
loop: Boolean(item.animRepeatCount) || false,
|
1003
|
+
autoplay: true,
|
1004
|
+
path: animView.animUrl,
|
1005
|
+
rendererSettings: {
|
1006
|
+
preserveAspectRatio: 'xMidYMid slice',
|
1007
|
+
},
|
1008
|
+
});
|
1009
|
+
|
1010
|
+
// 保存动画实例
|
1011
|
+
this.lottieAnimations[animKey] = anim;
|
1012
|
+
|
1013
|
+
// 添加动画事件监听
|
1014
|
+
anim.addEventListener('complete', () => {
|
1015
|
+
// 检查是否需要销毁动画(非循环动画完成后销毁)
|
1016
|
+
if (!item.animRepeatCount) {
|
1017
|
+
// 销毁前再次检查实例是否存在
|
1018
|
+
if (this.lottieAnimations[animKey] === anim) {
|
1019
|
+
// 移除所有事件监听器
|
1020
|
+
anim.removeEventListener('complete');
|
1021
|
+
// 销毁动画实例
|
1022
|
+
anim.destroy();
|
1025
1023
|
delete this.lottieAnimations[animKey];
|
1026
|
-
}
|
1027
1024
|
|
1028
|
-
|
1029
|
-
|
1030
|
-
|
1031
|
-
|
1032
|
-
|
1033
|
-
|
1034
|
-
|
1035
|
-
|
1036
|
-
|
1037
|
-
|
1038
|
-
|
1039
|
-
|
1040
|
-
// 保存动画实例
|
1041
|
-
this.lottieAnimations[animKey] = anim;
|
1042
|
-
|
1043
|
-
// 添加动画事件监听
|
1044
|
-
|
1045
|
-
anim.addEventListener('complete', () => {
|
1046
|
-
// 检查是否需要销毁动画(非循环动画完成后销毁)
|
1047
|
-
if (!item.animRepeatCount) {
|
1048
|
-
// 销毁前再次检查实例是否存在
|
1049
|
-
if (this.lottieAnimations[animKey] === anim) {
|
1050
|
-
anim.removeEventListener('complete');
|
1051
|
-
anim.removeEventListener('DOMLoaded');
|
1052
|
-
anim.removeEventListener('data_ready');
|
1053
|
-
anim.removeEventListener('loaded_images');
|
1054
|
-
anim.removeEventListener('loopComplete');
|
1055
|
-
anim.destroy();
|
1056
|
-
delete this.lottieAnimations[animKey];
|
1057
|
-
|
1058
|
-
// 查找并隐藏对应的动画容器
|
1059
|
-
this.$nextTick(() => {
|
1060
|
-
const animContainer =
|
1061
|
-
this.$refs[refName] && this.$refs[refName][0];
|
1062
|
-
if (animContainer) {
|
1063
|
-
animContainer.style.display = 'none';
|
1064
|
-
}
|
1065
|
-
|
1066
|
-
// 将对应数据中的animUrl清空
|
1067
|
-
const itemId = item.itemView.id;
|
1068
|
-
const index = this.processedList.findIndex(
|
1069
|
-
(i) => i.itemView.id === itemId
|
1070
|
-
);
|
1071
|
-
if (index !== -1) {
|
1072
|
-
// 根据动画类型设置对应的animUrl为空
|
1073
|
-
if (animKey.startsWith('bg-')) {
|
1074
|
-
this.$set(
|
1075
|
-
this.processedList[index].bgAnimView,
|
1076
|
-
'animUrl',
|
1077
|
-
''
|
1078
|
-
);
|
1079
|
-
// 同步更新原始数据
|
1080
|
-
const dataIndex = this.data.list.findIndex(
|
1081
|
-
(i) => i.itemView.id === itemId
|
1082
|
-
);
|
1083
|
-
if (dataIndex !== -1) {
|
1084
|
-
this.$set(
|
1085
|
-
this.data.list[dataIndex].bgAnimView,
|
1086
|
-
'animUrl',
|
1087
|
-
''
|
1088
|
-
);
|
1089
|
-
}
|
1090
|
-
} else if (animKey.startsWith('loading-')) {
|
1091
|
-
this.$set(
|
1092
|
-
this.processedList[index].loadingAnimView,
|
1093
|
-
'animUrl',
|
1094
|
-
''
|
1095
|
-
);
|
1096
|
-
// 同步更新原始数据
|
1097
|
-
const dataIndex = this.data.list.findIndex(
|
1098
|
-
(i) => i.itemView.id === itemId
|
1099
|
-
);
|
1100
|
-
if (dataIndex !== -1) {
|
1101
|
-
this.$set(
|
1102
|
-
this.data.list[dataIndex].loadingAnimView,
|
1103
|
-
'animUrl',
|
1104
|
-
''
|
1105
|
-
);
|
1106
|
-
}
|
1107
|
-
} else if (animKey.startsWith('front-')) {
|
1108
|
-
this.$set(
|
1109
|
-
this.processedList[index].frontAnimView,
|
1110
|
-
'animUrl',
|
1111
|
-
''
|
1112
|
-
);
|
1113
|
-
// 同步更新原始数据
|
1114
|
-
const dataIndex = this.data.list.findIndex(
|
1115
|
-
(i) => i.itemView.id === itemId
|
1116
|
-
);
|
1117
|
-
if (dataIndex !== -1) {
|
1118
|
-
this.$set(
|
1119
|
-
this.data.list[dataIndex].frontAnimView,
|
1120
|
-
'animUrl',
|
1121
|
-
''
|
1122
|
-
);
|
1123
|
-
}
|
1124
|
-
}
|
1125
|
-
}
|
1126
|
-
});
|
1025
|
+
// 查找并清空对应的动画容器,彻底移除所有内容
|
1026
|
+
this.$nextTick(() => {
|
1027
|
+
const animContainer =
|
1028
|
+
this.$refs[refName] && this.$refs[refName][0];
|
1029
|
+
if (animContainer) {
|
1030
|
+
// 隐藏容器
|
1031
|
+
animContainer.style.display = 'none';
|
1032
|
+
// 清空容器内容,确保不显示最后一帧
|
1033
|
+
animContainer.innerHTML = '';
|
1034
|
+
// 确保不会阻止触摸事件
|
1035
|
+
animContainer.style.pointerEvents = 'none';
|
1127
1036
|
}
|
1128
|
-
}
|
1129
|
-
});
|
1130
1037
|
|
1131
|
-
|
1132
|
-
|
1133
|
-
|
1134
|
-
|
1038
|
+
if (animKey.startsWith('bg-') && !item.animRepeatCount) {
|
1039
|
+
this.data.list[dataIndex].bgAnimView = {
|
1040
|
+
...item.bgAnimView,
|
1041
|
+
animUrl: '',
|
1042
|
+
visibility: 0,
|
1043
|
+
};
|
1044
|
+
this.processedList[dataIndex].bgAnimView = {
|
1045
|
+
...item.bgAnimView,
|
1046
|
+
animUrl: '',
|
1047
|
+
visibility: 0,
|
1048
|
+
};
|
1049
|
+
} else if (animKey.startsWith('loading-') && !item.animRepeatCount) {
|
1050
|
+
this.data.list[dataIndex].loadingAnimView = {
|
1051
|
+
...item.loadingAnimView,
|
1052
|
+
animUrl: '',
|
1053
|
+
visibility: 0,
|
1054
|
+
};
|
1055
|
+
this.processedList[dataIndex].loadingAnimView = {
|
1056
|
+
...item.loadingAnimView,
|
1057
|
+
animUrl: '',
|
1058
|
+
visibility: 0,
|
1059
|
+
};
|
1060
|
+
} else if (animKey.startsWith('front-') && !item.animRepeatCount) {
|
1061
|
+
this.data.list[dataIndex].frontAnimView = {
|
1062
|
+
...item.frontAnimView,
|
1063
|
+
animUrl: '',
|
1064
|
+
visibility: 0,
|
1065
|
+
};
|
1066
|
+
this.processedList[dataIndex].frontAnimView = {
|
1067
|
+
...item.frontAnimView,
|
1068
|
+
animUrl: '',
|
1069
|
+
visibility: 0,
|
1070
|
+
};
|
1071
|
+
}
|
1072
|
+
});
|
1073
|
+
}
|
1074
|
+
}
|
1075
|
+
});
|
1076
|
+
}
|
1135
1077
|
} catch (error) {
|
1078
|
+
console.error('加载Lottie动画失败:', error);
|
1136
1079
|
}
|
1137
1080
|
},
|
1138
1081
|
|
@@ -1147,148 +1090,35 @@ export default {
|
|
1147
1090
|
}
|
1148
1091
|
});
|
1149
1092
|
},
|
1150
|
-
|
1151
|
-
|
1152
|
-
|
1153
|
-
|
1154
|
-
|
1155
|
-
|
1156
|
-
|
1093
|
+
// 查找父级元素和refresh元素
|
1094
|
+
findParentElements() {
|
1095
|
+
// 返回存储的元素引用
|
1096
|
+
return {
|
1097
|
+
listInner: this.weexListInnerEl,
|
1098
|
+
refresh: this.weexRefreshEl,
|
1099
|
+
};
|
1157
1100
|
},
|
1158
1101
|
},
|
1159
1102
|
watch: {
|
1160
|
-
// 监听初始数据变化
|
1161
|
-
initialItems: {
|
1162
|
-
handler(newItems) {
|
1163
|
-
if (!this.isTouchDragging) {
|
1164
|
-
this.items = [...newItems];
|
1165
|
-
}
|
1166
|
-
},
|
1167
|
-
deep: true,
|
1168
|
-
},
|
1169
1103
|
// 监听列表数据变化,自动更新处理后的数据
|
1170
1104
|
'data.list': {
|
1171
1105
|
handler(newList, oldList) {
|
1172
1106
|
this.processedList = this.generateDataList();
|
1107
|
+
console.log(newList, this.processedList, 'cdj------数据变化');
|
1173
1108
|
this.$nextTick(() => {
|
1174
1109
|
this.updateGridBoxWidth();
|
1175
1110
|
this.updateFixedItemSize();
|
1176
|
-
this.initLottieAnimations();
|
1177
|
-
});
|
1178
|
-
},
|
1179
|
-
deep: true,
|
1180
|
-
},
|
1181
|
-
// 监听所有动画URL变化,确保能及时更新动画
|
1182
|
-
processedList: {
|
1183
|
-
handler(newList, oldList) {
|
1184
|
-
if (!newList || !newList.length || this.isTouchDragging) return;
|
1185
|
-
|
1186
|
-
// 避免在拖拽过程中重新初始化动画
|
1187
|
-
if (this.draggingIndex !== null) return;
|
1188
|
-
|
1189
|
-
// 检查每个项目的动画URL是否有变化
|
1190
|
-
newList.forEach((item, index) => {
|
1191
|
-
// 如果是新增的项目,直接更新
|
1192
|
-
if (!oldList || !oldList[index]) {
|
1193
|
-
this.$nextTick(() => {
|
1194
|
-
const itemId = item.itemView.id;
|
1195
|
-
this.loadLottieAnimation(
|
1196
|
-
item.bgAnimView,
|
1197
|
-
`bgAnim-${itemId}`,
|
1198
|
-
`bg-${itemId}`,
|
1199
|
-
item
|
1200
|
-
);
|
1201
|
-
this.loadLottieAnimation(
|
1202
|
-
item.loadingAnimView,
|
1203
|
-
`loadingAnim-${itemId}`,
|
1204
|
-
`loading-${itemId}`,
|
1205
|
-
item
|
1206
|
-
);
|
1207
|
-
this.loadLottieAnimation(
|
1208
|
-
item.frontAnimView,
|
1209
|
-
`frontAnim-${itemId}`,
|
1210
|
-
`front-${itemId}`,
|
1211
|
-
item
|
1212
|
-
);
|
1213
|
-
});
|
1214
|
-
return;
|
1215
|
-
}
|
1216
|
-
|
1217
|
-
// 检查bgAnimView.animUrl是否变化
|
1218
|
-
if (
|
1219
|
-
item.bgAnimView &&
|
1220
|
-
oldList[index].bgAnimView &&
|
1221
|
-
item.bgAnimView.animUrl !== oldList[index].bgAnimView.animUrl
|
1222
|
-
) {
|
1223
|
-
this.$nextTick(() => {
|
1224
|
-
const itemId = item.itemView.id;
|
1225
|
-
if (this.lottieAnimations[`bg-${itemId}`]) {
|
1226
|
-
this.lottieAnimations[`bg-${itemId}`].destroy();
|
1227
|
-
delete this.lottieAnimations[`bg-${itemId}`];
|
1228
|
-
}
|
1229
|
-
this.loadLottieAnimation(
|
1230
|
-
item.bgAnimView,
|
1231
|
-
`bgAnim-${itemId}`,
|
1232
|
-
`bg-${itemId}`,
|
1233
|
-
item
|
1234
|
-
);
|
1235
|
-
});
|
1236
|
-
}
|
1237
|
-
|
1238
|
-
// 检查loadingAnimView.animUrl是否变化
|
1239
|
-
if (
|
1240
|
-
item.loadingAnimView &&
|
1241
|
-
oldList[index].loadingAnimView &&
|
1242
|
-
item.loadingAnimView.animUrl !==
|
1243
|
-
oldList[index].loadingAnimView.animUrl
|
1244
|
-
) {
|
1245
|
-
this.$nextTick(() => {
|
1246
|
-
const itemId = item.itemView.id;
|
1247
|
-
if (this.lottieAnimations[`loading-${itemId}`]) {
|
1248
|
-
this.lottieAnimations[`loading-${itemId}`].destroy();
|
1249
|
-
delete this.lottieAnimations[`loading-${itemId}`];
|
1250
|
-
}
|
1251
|
-
this.loadLottieAnimation(
|
1252
|
-
item.loadingAnimView,
|
1253
|
-
`loadingAnim-${itemId}`,
|
1254
|
-
`loading-${itemId}`,
|
1255
|
-
item
|
1256
|
-
);
|
1257
|
-
});
|
1258
|
-
}
|
1259
|
-
|
1260
|
-
// 检查frontAnimView.animUrl是否变化
|
1261
|
-
if (
|
1262
|
-
item.frontAnimView &&
|
1263
|
-
oldList[index].frontAnimView &&
|
1264
|
-
item.frontAnimView.animUrl !== oldList[index].frontAnimView.animUrl
|
1265
|
-
) {
|
1266
|
-
this.$nextTick(() => {
|
1267
|
-
const itemId = item.itemView.id;
|
1268
|
-
if (this.lottieAnimations[`front-${itemId}`]) {
|
1269
|
-
this.lottieAnimations[`front-${itemId}`].destroy();
|
1270
|
-
delete this.lottieAnimations[`front-${itemId}`];
|
1271
|
-
}
|
1272
|
-
this.loadLottieAnimation(
|
1273
|
-
item.frontAnimView,
|
1274
|
-
`frontAnim-${itemId}`,
|
1275
|
-
`front-${itemId}`,
|
1276
|
-
item
|
1277
|
-
);
|
1278
|
-
});
|
1279
|
-
}
|
1280
1111
|
});
|
1281
1112
|
},
|
1282
1113
|
deep: true,
|
1283
1114
|
},
|
1284
1115
|
},
|
1285
1116
|
mounted() {
|
1286
|
-
console.log(this.data, 'djdjdjdjdjdjdj');
|
1117
|
+
console.log(this.data, 'cdj------djdjdjdjdjdjdj');
|
1287
1118
|
// 初始获取grid-box宽度
|
1288
1119
|
this.updateGridBoxWidth();
|
1289
1120
|
// 获取并存储固定宽高
|
1290
1121
|
this.updateFixedItemSize();
|
1291
|
-
|
1292
1122
|
// 监听窗口大小变化,更新grid-box宽度
|
1293
1123
|
window.addEventListener('resize', () => {
|
1294
1124
|
this.updateGridBoxWidth();
|
@@ -1307,6 +1137,19 @@ export default {
|
|
1307
1137
|
document.removeEventListener('touchend', this.onTouchEnd, {
|
1308
1138
|
passive: false,
|
1309
1139
|
});
|
1140
|
+
// 确保全局事件监听也被清理
|
1141
|
+
document.removeEventListener('touchmove', this.onGlobalTouchMove, {
|
1142
|
+
passive: false,
|
1143
|
+
capture: true,
|
1144
|
+
});
|
1145
|
+
document.removeEventListener('touchend', this.onTouchEnd, {
|
1146
|
+
passive: false,
|
1147
|
+
capture: true,
|
1148
|
+
});
|
1149
|
+
// 恢复页面滚动状态
|
1150
|
+
document.body.style.overflow = '';
|
1151
|
+
document.body.style.touchAction = '';
|
1152
|
+
|
1310
1153
|
window.removeEventListener('resize', () => {
|
1311
1154
|
this.updateGridBoxWidth();
|
1312
1155
|
this.updateFixedItemSize();
|
@@ -1324,15 +1167,25 @@ export default {
|
|
1324
1167
|
if (anim && typeof anim.destroy === 'function') {
|
1325
1168
|
try {
|
1326
1169
|
anim.removeEventListener('complete');
|
1327
|
-
anim.removeEventListener('DOMLoaded');
|
1328
|
-
anim.removeEventListener('data_ready');
|
1329
|
-
anim.removeEventListener('loaded_images');
|
1330
|
-
anim.removeEventListener('loopComplete');
|
1331
1170
|
} catch (e) {
|
1171
|
+
console.warn(`移除事件监听器失败: ${e.message}`);
|
1332
1172
|
}
|
1333
1173
|
anim.destroy();
|
1334
1174
|
}
|
1335
1175
|
delete this.lottieAnimations[key];
|
1176
|
+
|
1177
|
+
// 尝试清理对应的DOM容器
|
1178
|
+
const parts = key.split('-');
|
1179
|
+
if (parts.length === 2) {
|
1180
|
+
const animType = parts[0]; // bg, loading, front
|
1181
|
+
const itemId = parts[1];
|
1182
|
+
const refName = `${animType}Anim-${itemId}`;
|
1183
|
+
const animContainer = this.$refs[refName] && this.$refs[refName][0];
|
1184
|
+
if (animContainer) {
|
1185
|
+
animContainer.innerHTML = '';
|
1186
|
+
animContainer.style.display = 'none';
|
1187
|
+
}
|
1188
|
+
}
|
1336
1189
|
});
|
1337
1190
|
|
1338
1191
|
// 确保动画实例对象被清空
|
@@ -1341,11 +1194,6 @@ export default {
|
|
1341
1194
|
created() {
|
1342
1195
|
// 初始化处理后的数据列表
|
1343
1196
|
this.processedList = this.generateDataList();
|
1344
|
-
|
1345
|
-
// 添加测试拖拽模式的方法
|
1346
|
-
window.testDragMode = (index = 0) => {
|
1347
|
-
this.testDragMode(index);
|
1348
|
-
};
|
1349
1197
|
},
|
1350
1198
|
};
|
1351
1199
|
</script>
|
@@ -1377,8 +1225,10 @@ button {
|
|
1377
1225
|
|
1378
1226
|
/* 优化排序过渡效果 */
|
1379
1227
|
.grid-fade-move {
|
1380
|
-
transition: transform 0.
|
1228
|
+
transition: transform 0.3s cubic-bezier(0.2, 0, 0.2, 1);
|
1381
1229
|
will-change: transform;
|
1230
|
+
position: relative;
|
1231
|
+
z-index: 2;
|
1382
1232
|
}
|
1383
1233
|
|
1384
1234
|
.grid-item {
|
@@ -1418,7 +1268,9 @@ button {
|
|
1418
1268
|
top: 0;
|
1419
1269
|
pointer-events: none;
|
1420
1270
|
}
|
1421
|
-
|
1271
|
+
.lottie-container >>> * {
|
1272
|
+
pointer-events: none;
|
1273
|
+
}
|
1422
1274
|
.bg-anim,
|
1423
1275
|
.front-anim {
|
1424
1276
|
z-index: 1;
|