@dolphinweex/weex-harmony 0.1.26 → 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,7 +188,7 @@ 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,
|
@@ -211,7 +206,9 @@ export default {
|
|
211
206
|
return {
|
212
207
|
'--grid-cols': this.data.spanCount || this.cols,
|
213
208
|
'--grid-gap': `${this.data.spaceSize || 8}px`,
|
214
|
-
'--grid-margin': `${
|
209
|
+
'--grid-margin': `${
|
210
|
+
this.data.layoutConfig.marginStart + this.data.layoutConfig.marginEnd
|
211
|
+
}px`,
|
215
212
|
marginTop: this.data.layoutConfig.marginTop * scla,
|
216
213
|
marginBottom: this.data.layoutConfig.marginBottom * scla,
|
217
214
|
marginLeft: this.data.layoutConfig.marginStart * scla,
|
@@ -246,148 +243,75 @@ export default {
|
|
246
243
|
},
|
247
244
|
},
|
248
245
|
methods: {
|
249
|
-
searchDom(){
|
250
|
-
//在 slider组件内部时 阻止默认行为和冒泡都无法在长按的时候 阻止其滚动行为 只能查找去禁止
|
251
|
-
const currentEl = this.$el;
|
252
|
-
let parentEl = currentEl.parentElement;
|
253
|
-
let searchDepth = 0; // 搜索深度计数器
|
254
|
-
while (parentEl && !parentEl.classList.contains('weex-list-inner') && searchDepth < 5) {
|
255
|
-
parentEl = parentEl.parentElement;
|
256
|
-
searchDepth++;
|
257
|
-
}
|
258
|
-
|
259
|
-
if (parentEl) {
|
260
|
-
this.weexListInnerEl = parentEl;
|
261
|
-
this.originListInnerStyle = parentEl.style.touchAction || '';
|
262
|
-
|
263
|
-
// 在weex-list-inner中查找weex-refresh子元素
|
264
|
-
const refreshEl = parentEl.querySelector('.weex-refresh');
|
265
|
-
if (refreshEl) {
|
266
|
-
this.weexRefreshEl = refreshEl;
|
267
|
-
this.originRefreshStyle = refreshEl.style.height || '';
|
268
|
-
}
|
269
|
-
}
|
270
|
-
},
|
271
246
|
updateListItem(data) {
|
272
247
|
console.log('updateListItem收到数据:', JSON.stringify(data));
|
273
248
|
const id = data.itemView.id;
|
274
249
|
const index = this.processedList.findIndex(
|
275
|
-
(item) => item.itemView.id
|
250
|
+
(item) => item.itemView.id == id
|
276
251
|
);
|
277
252
|
const dataIndex = this.data.list.findIndex(
|
278
|
-
(item) => item.itemView.id
|
253
|
+
(item) => item.itemView.id == id
|
279
254
|
);
|
280
255
|
// 更新原始数据以确保watch能触发
|
281
|
-
if
|
256
|
+
if(dataIndex !== -1) {
|
282
257
|
// 使用Vue的$set确保响应式更新
|
283
258
|
this.$set(this.data.list, dataIndex, JSON.parse(JSON.stringify(data)));
|
284
259
|
}
|
285
260
|
if (index === -1) {
|
286
261
|
return;
|
287
262
|
}
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
// 检查是否有动画URL的变化
|
292
|
-
const oldBgAnimUrl = this.processedList[index].bgAnimView.animUrl || '';
|
293
|
-
const oldLoadingAnimUrl =
|
294
|
-
this.processedList[index].loadingAnimView.animUrl || '';
|
295
|
-
const oldFrontAnimUrl =
|
296
|
-
this.processedList[index].frontAnimView.animUrl || '';
|
297
263
|
const newBgAnimUrl = data.bgAnimView.animUrl || '';
|
298
264
|
const newLoadingAnimUrl = data.loadingAnimView.animUrl || '';
|
299
265
|
const newFrontAnimUrl = data.frontAnimView.animUrl || '';
|
300
|
-
|
301
|
-
const hasAnimUrlChanged =
|
302
|
-
oldBgAnimUrl !== newBgAnimUrl ||
|
303
|
-
oldLoadingAnimUrl !== newLoadingAnimUrl ||
|
304
|
-
oldFrontAnimUrl !== newFrontAnimUrl;
|
305
|
-
|
306
266
|
// 同时更新processedList和原始data.list数据
|
307
267
|
this.processedList[index] = data;
|
308
268
|
this.processedList = [...this.processedList];
|
309
269
|
|
310
|
-
// 更新原始数据以确保watch能触发
|
311
|
-
if (dataIndex !== -1) {
|
312
|
-
// 使用Vue的$set确保响应式更新
|
313
|
-
this.$set(this.data.list, dataIndex, JSON.parse(JSON.stringify(data)));
|
314
|
-
}
|
315
|
-
|
316
|
-
// 如果动画URL有变化,重新初始化相关的Lottie动画
|
317
|
-
if (hasAnimUrlChanged) {
|
318
270
|
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
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}`,
|
326
281
|
`bg-${itemId}`,
|
282
|
+
data,
|
283
|
+
dataIndex
|
284
|
+
);
|
285
|
+
}
|
286
|
+
if (newLoadingAnimUrl) {
|
287
|
+
this.loadLottieAnimation(
|
288
|
+
data.loadingAnimView,
|
289
|
+
`loadingAnim-${itemId}`,
|
327
290
|
`loading-${itemId}`,
|
291
|
+
data,
|
292
|
+
dataIndex
|
293
|
+
);
|
294
|
+
}
|
295
|
+
if (newFrontAnimUrl) {
|
296
|
+
this.loadLottieAnimation(
|
297
|
+
data.frontAnimView,
|
298
|
+
`frontAnim-${itemId}`,
|
328
299
|
`front-${itemId}`,
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
anim.removeEventListener('complete');
|
335
|
-
anim.removeEventListener('DOMLoaded');
|
336
|
-
anim.removeEventListener('data_ready');
|
337
|
-
anim.removeEventListener('loaded_images');
|
338
|
-
anim.removeEventListener('loopComplete');
|
339
|
-
} catch (e) {
|
340
|
-
}
|
341
|
-
anim.destroy();
|
342
|
-
delete this.lottieAnimations[key];
|
343
|
-
}
|
344
|
-
});
|
345
|
-
|
346
|
-
|
347
|
-
// 延迟一点时间确保DOM完全更新
|
348
|
-
setTimeout(() => {
|
349
|
-
// 重新初始化背景动画
|
350
|
-
if (newBgAnimUrl) {
|
351
|
-
this.loadLottieAnimation(
|
352
|
-
data.bgAnimView,
|
353
|
-
`bgAnim-${itemId}`,
|
354
|
-
`bg-${itemId}`,
|
355
|
-
data
|
356
|
-
);
|
357
|
-
}
|
358
|
-
|
359
|
-
// 重新初始化加载动画
|
360
|
-
if (newLoadingAnimUrl) {
|
361
|
-
this.loadLottieAnimation(
|
362
|
-
data.loadingAnimView,
|
363
|
-
`loadingAnim-${itemId}`,
|
364
|
-
`loading-${itemId}`,
|
365
|
-
data
|
366
|
-
);
|
367
|
-
}
|
368
|
-
|
369
|
-
// 重新初始化前景动画
|
370
|
-
if (newFrontAnimUrl) {
|
371
|
-
this.loadLottieAnimation(
|
372
|
-
data.frontAnimView,
|
373
|
-
`frontAnim-${itemId}`,
|
374
|
-
`front-${itemId}`,
|
375
|
-
data
|
376
|
-
);
|
377
|
-
}
|
378
|
-
}, 100); // 增加延迟确保DOM已更新和旧动画已完全销毁
|
379
|
-
});
|
380
|
-
}
|
300
|
+
data,
|
301
|
+
dataIndex
|
302
|
+
);
|
303
|
+
}
|
304
|
+
});
|
381
305
|
},
|
382
306
|
getListData(callback) {
|
383
307
|
let data = Array.from(this.processedList);
|
384
|
-
data = data.map((item)=>({
|
308
|
+
data = data.map((item) => ({
|
385
309
|
...item,
|
386
310
|
itemView: {
|
387
311
|
...item.itemView,
|
388
|
-
id:String(item.itemView.id)
|
389
|
-
}
|
390
|
-
}))
|
312
|
+
id: String(item.itemView.id),
|
313
|
+
},
|
314
|
+
}));
|
391
315
|
callback({ listData: data });
|
392
316
|
},
|
393
317
|
rightIconClick(e) {
|
@@ -413,7 +337,7 @@ export default {
|
|
413
337
|
...e,
|
414
338
|
};
|
415
339
|
this.$emit('onClickSelectIcon', target);
|
416
|
-
this.$emit('onSelectItems',target)
|
340
|
+
this.$emit('onSelectItems', target);
|
417
341
|
return false;
|
418
342
|
},
|
419
343
|
|
@@ -428,7 +352,7 @@ export default {
|
|
428
352
|
this.cancelLongPress();
|
429
353
|
if (this.data.isEditing) {
|
430
354
|
item.itemView.isSelected = !item.itemView.isSelected;
|
431
|
-
this.$emit('onSelectItems',target)
|
355
|
+
this.$emit('onSelectItems', target);
|
432
356
|
return;
|
433
357
|
}
|
434
358
|
const target = {
|
@@ -443,10 +367,6 @@ export default {
|
|
443
367
|
actionClick(e, item, index) {
|
444
368
|
e.preventDefault();
|
445
369
|
e.stopPropagation(); // 阻止事件冒泡到itemViewClick
|
446
|
-
|
447
|
-
// 在触发事件前,先清理所有其他项目的动画实例
|
448
|
-
this.cleanupOtherAnimations(item.itemView.id);
|
449
|
-
|
450
370
|
const target = {
|
451
371
|
...item.itemView,
|
452
372
|
id: String(item.itemView.id),
|
@@ -457,51 +377,6 @@ export default {
|
|
457
377
|
return false;
|
458
378
|
},
|
459
379
|
|
460
|
-
// 新增方法:清理除指定项目外的所有动画实例
|
461
|
-
cleanupOtherAnimations(currentItemId) {
|
462
|
-
|
463
|
-
// 遍历所有动画实例
|
464
|
-
Object.keys(this.lottieAnimations).forEach((key) => {
|
465
|
-
// 检查是否为其他项目的动画
|
466
|
-
if (!key.includes(`-${currentItemId}`)) {
|
467
|
-
if (this.lottieAnimations[key]) {
|
468
|
-
const anim = this.lottieAnimations[key];
|
469
|
-
|
470
|
-
// 移除所有事件监听器
|
471
|
-
try {
|
472
|
-
anim.removeEventListener('complete');
|
473
|
-
anim.removeEventListener('DOMLoaded');
|
474
|
-
anim.removeEventListener('data_ready');
|
475
|
-
anim.removeEventListener('loaded_images');
|
476
|
-
anim.removeEventListener('loopComplete');
|
477
|
-
} catch (e) {
|
478
|
-
console.warn(`移除事件监听器失败: ${e.message}`);
|
479
|
-
}
|
480
|
-
|
481
|
-
anim.destroy();
|
482
|
-
delete this.lottieAnimations[key];
|
483
|
-
|
484
|
-
// 提取项目ID和动画类型
|
485
|
-
const parts = key.split('-');
|
486
|
-
if (parts.length === 2) {
|
487
|
-
const animType = parts[0]; // bg, loading, front
|
488
|
-
const itemId = parts[1];
|
489
|
-
|
490
|
-
// 隐藏对应的动画容器
|
491
|
-
this.$nextTick(() => {
|
492
|
-
const refName = `${animType}Anim-${itemId}`;
|
493
|
-
const animContainer =
|
494
|
-
this.$refs[refName] && this.$refs[refName][0];
|
495
|
-
if (animContainer) {
|
496
|
-
animContainer.style.display = 'none';
|
497
|
-
}
|
498
|
-
});
|
499
|
-
}
|
500
|
-
}
|
501
|
-
}
|
502
|
-
});
|
503
|
-
},
|
504
|
-
|
505
380
|
// 生成处理后的数据列表
|
506
381
|
generateDataList() {
|
507
382
|
if (!this.data || !this.data.list || !this.data.globalData) {
|
@@ -601,12 +476,17 @@ export default {
|
|
601
476
|
},
|
602
477
|
// 开始长按
|
603
478
|
startLongPress(e, index) {
|
479
|
+
console.log(e, 'cdj-------startLongPress');
|
604
480
|
if (!this.data.isEditable) {
|
605
481
|
return;
|
606
482
|
}
|
607
|
-
|
483
|
+
|
484
|
+
// 确保事件不被其他处理器抢先处理
|
485
|
+
// e.oriEvent.stopPropagation();
|
486
|
+
|
608
487
|
// 清除任何现有计时器
|
609
488
|
this.cancelLongPress();
|
489
|
+
|
610
490
|
// 记录起始触摸位置和索引
|
611
491
|
const touch = e.changedTouches[0];
|
612
492
|
this.touchStartX = touch.pageX;
|
@@ -614,13 +494,8 @@ export default {
|
|
614
494
|
this.longPressStartIndex = index;
|
615
495
|
this.isScrolling = false; // 重置滚动状态
|
616
496
|
|
617
|
-
//
|
618
|
-
|
619
|
-
passive: true, // 设置为passive:true允许浏览器进行滚动优化
|
620
|
-
});
|
621
|
-
document.removeEventListener('touchend', this.onTouchEnd, {
|
622
|
-
passive: true,
|
623
|
-
});
|
497
|
+
// 记录触摸开始时间,用于判断是否为快速滑动
|
498
|
+
this.touchStartTime = Date.now();
|
624
499
|
|
625
500
|
if (this.isTouchDragging) {
|
626
501
|
this.$emit('drag-end', {
|
@@ -628,15 +503,19 @@ export default {
|
|
628
503
|
});
|
629
504
|
}
|
630
505
|
|
506
|
+
// 通知外部触摸开始事件
|
507
|
+
this.$emit('onDragEventStart', e);
|
631
508
|
|
632
|
-
// 设置新的长按计时器
|
509
|
+
// 设置新的长按计时器 - 延长一点时间避免误触发
|
633
510
|
this.longPressTimer = setTimeout(() => {
|
634
511
|
// 只有在没有滚动的情况下才激活拖拽模式
|
635
512
|
if (!this.isScrolling) {
|
513
|
+
console.log('长按时间到,激活拖拽模式');
|
636
514
|
this.activateDragMode(index);
|
515
|
+
} else {
|
516
|
+
console.log('检测到滚动,取消拖拽激活');
|
637
517
|
}
|
638
518
|
}, this.longPressDuration);
|
639
|
-
// 不阻止默认行为 - 允许滚动
|
640
519
|
},
|
641
520
|
|
642
521
|
// 检查长按过程中的移动
|
@@ -644,47 +523,66 @@ export default {
|
|
644
523
|
if (!this.data.isEditable) {
|
645
524
|
return;
|
646
525
|
}
|
526
|
+
|
647
527
|
const touch = e.changedTouches[0];
|
648
528
|
// 如果已经在拖拽模式,交给onTouchMove处理
|
649
529
|
if (this.isTouchDragging) {
|
650
530
|
this.onTouchMove(e);
|
651
531
|
return;
|
652
532
|
}
|
533
|
+
|
653
534
|
const moveX = Math.abs(touch.pageX - this.touchStartX);
|
654
535
|
const moveY = Math.abs(touch.pageY - this.touchStartY);
|
655
536
|
|
656
|
-
//
|
657
|
-
|
658
|
-
|
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 });
|
659
555
|
this.isScrolling = true;
|
660
556
|
this.cancelLongPress();
|
661
557
|
return;
|
662
558
|
}
|
663
559
|
|
664
|
-
// 如果移动超过阈值,取消长按
|
560
|
+
// 如果移动超过阈值,取消长按 - 但不阻止默认行为
|
665
561
|
if (moveX > this.scrollThreshold || moveY > this.scrollThreshold) {
|
666
562
|
this.cancelLongPress();
|
563
|
+
return;
|
667
564
|
}
|
668
|
-
this.data.isEditing && e.oriEvent.stopPropagation()
|
669
|
-
this.data.isEditing && e.oriEvent.preventDefault()
|
670
565
|
|
566
|
+
// 只有确认不是滚动意图,且在长按倒计时中,才阻止默认行为
|
567
|
+
if (this.longPressTimer && !this.isScrolling) {
|
568
|
+
e.oriEvent.preventDefault();
|
569
|
+
}
|
671
570
|
},
|
672
571
|
|
673
572
|
// 激活拖拽模式
|
674
573
|
activateDragMode(index) {
|
675
574
|
console.log('长按触发,进入编辑模式');
|
676
|
-
|
677
|
-
|
678
|
-
|
679
|
-
|
680
|
-
|
681
|
-
|
682
|
-
}
|
683
|
-
|
575
|
+
|
576
|
+
// 先确保编辑模式已开启
|
577
|
+
if (!this.data.isEditing) {
|
578
|
+
// 设置编辑状态并隐藏weex-refresh
|
579
|
+
this.data.isEditing = true;
|
580
|
+
this.$emit('onEditStateChanged', true);
|
581
|
+
} else {
|
582
|
+
// 无论之前是否处于编辑模式,都设置拖拽状态
|
684
583
|
// 设置当前拖拽索引
|
685
584
|
this.draggingIndex = index;
|
686
585
|
this.isTouchDragging = true;
|
687
|
-
|
688
586
|
// 使用存储的固定宽高
|
689
587
|
this.draggedItemRect = {
|
690
588
|
width: this.fixedItemWidth,
|
@@ -706,6 +604,20 @@ export default {
|
|
706
604
|
// 显示拖拽克隆
|
707
605
|
this.isDragClone = true;
|
708
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
|
+
});
|
620
|
+
|
709
621
|
// 立即执行一次定位以确保初始位置准确
|
710
622
|
requestAnimationFrame(() => {
|
711
623
|
this.dragCloneX = this.touchStartX - this.touchOffsetX;
|
@@ -714,16 +626,9 @@ export default {
|
|
714
626
|
|
715
627
|
console.log('拖拽克隆已创建');
|
716
628
|
}
|
717
|
-
|
718
|
-
this.longPressTimer = null;
|
719
|
-
}
|
720
|
-
// 进入编辑模式
|
721
|
-
if (!this.data.isEditing) {
|
722
|
-
// 设置编辑状态并隐藏weex-refresh
|
723
|
-
this.data.isEditing = true;
|
724
|
-
this.$emit('onEditStateChanged', true);
|
725
|
-
this.applyDragModeStyles(); // 应用编辑模式样式(隐藏refresh)
|
726
629
|
}
|
630
|
+
|
631
|
+
this.longPressTimer = null;
|
727
632
|
},
|
728
633
|
|
729
634
|
// 取消长按计时器
|
@@ -733,12 +638,45 @@ export default {
|
|
733
638
|
this.longPressTimer = null;
|
734
639
|
}
|
735
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
|
+
}
|
736
660
|
},
|
737
661
|
|
738
662
|
// 触摸移动处理
|
739
663
|
onTouchMove(e) {
|
740
664
|
if (!this.isTouchDragging) return;
|
741
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
|
+
|
742
680
|
const touch = e.changedTouches[0];
|
743
681
|
|
744
682
|
// 更新目标位置而非直接设置
|
@@ -793,9 +731,9 @@ export default {
|
|
793
731
|
);
|
794
732
|
const centerScore = 1 - distanceFromCenter;
|
795
733
|
|
796
|
-
//
|
797
|
-
//
|
798
|
-
if (centerScore > maxCenterScore && centerScore > 0.
|
734
|
+
// 放宽元素中心区域的判定,让交换更容易触发
|
735
|
+
// 降低阈值,让交换更敏感
|
736
|
+
if (centerScore > maxCenterScore && centerScore > 0.2) {
|
799
737
|
maxCenterScore = centerScore;
|
800
738
|
bestTarget = itemIndex;
|
801
739
|
}
|
@@ -805,36 +743,24 @@ export default {
|
|
805
743
|
// 设置悬停高亮,仅当有合格的目标时才高亮
|
806
744
|
this.hoverIndex = bestTarget;
|
807
745
|
|
808
|
-
//
|
809
|
-
|
810
|
-
|
811
|
-
|
812
|
-
|
813
|
-
|
814
|
-
|
815
|
-
// 只有当目标持续100ms稳定不变时,才认为是有效目标
|
816
|
-
this.lastBestTarget = this.pendingTarget;
|
817
|
-
this.targetChangeTime = null;
|
818
|
-
this.pendingTarget = null;
|
819
|
-
}
|
820
|
-
} else if (bestTarget === null) {
|
821
|
-
// 如果没有目标,清除防抖状态
|
822
|
-
this.targetChangeTime = null;
|
823
|
-
this.pendingTarget = null;
|
746
|
+
// 简化交换防抖动处理,让交换更直接响应
|
747
|
+
if (bestTarget !== null) {
|
748
|
+
// 直接使用当前的最佳目标
|
749
|
+
this.lastBestTarget = bestTarget;
|
750
|
+
} else {
|
751
|
+
// 如果没有目标,清除lastBestTarget
|
752
|
+
this.lastBestTarget = null;
|
824
753
|
}
|
825
754
|
|
826
755
|
// 使用已稳定的目标进行交换
|
827
756
|
bestTarget = this.lastBestTarget;
|
828
757
|
|
829
|
-
//
|
758
|
+
// 控制交换频率,不要太高,但也不要太慢
|
830
759
|
const now = Date.now();
|
831
|
-
if (now - this.lastSwapTime <
|
760
|
+
if (now - this.lastSwapTime < 150 || bestTarget === null) return;
|
832
761
|
|
833
762
|
// 执行交换逻辑
|
834
763
|
if (bestTarget !== this.draggingIndex) {
|
835
|
-
console.log(`交换元素: ${this.draggingIndex} 和 ${bestTarget}`);
|
836
|
-
|
837
|
-
// 使用ES6解构直接交换数组元素
|
838
764
|
[
|
839
765
|
this.processedList[this.draggingIndex],
|
840
766
|
this.processedList[bestTarget],
|
@@ -842,25 +768,26 @@ export default {
|
|
842
768
|
this.processedList[bestTarget],
|
843
769
|
this.processedList[this.draggingIndex],
|
844
770
|
];
|
845
|
-
|
846
|
-
// 同时更新原始数据,保持同步
|
847
771
|
[this.data.list[this.draggingIndex], this.data.list[bestTarget]] = [
|
848
772
|
this.data.list[bestTarget],
|
849
773
|
this.data.list[this.draggingIndex],
|
850
774
|
];
|
851
775
|
|
776
|
+
console.log(this.data.list, 'cdj------this.data.list');
|
777
|
+
|
778
|
+
// 更新processedList以触发视图更新和动画效果
|
779
|
+
this.processedList = this.generateDataList();
|
780
|
+
|
852
781
|
// 更新拖拽索引
|
853
782
|
this.draggingIndex = bestTarget;
|
854
783
|
this.lastSwapTime = now;
|
855
784
|
}
|
856
|
-
this.data.isEditing && e.oriEvent.stopPropagation()
|
857
|
-
this.data.isEditing && e.oriEvent.preventDefault()
|
858
785
|
},
|
859
786
|
|
860
787
|
// 新增:平滑更新拖拽位置的方法
|
861
788
|
updateDragPosition() {
|
862
789
|
// 计算当前位置到目标位置的平滑过渡
|
863
|
-
const easing = 0.
|
790
|
+
const easing = 0.8; // 大幅提高缓动系数,让拖拽更紧跟手指
|
864
791
|
|
865
792
|
this.dragCloneX +=
|
866
793
|
(this.targetTouchX - this.touchOffsetX - this.dragCloneX) * easing;
|
@@ -885,32 +812,38 @@ export default {
|
|
885
812
|
|
886
813
|
// 元素本身的触摸结束
|
887
814
|
endTouch(e) {
|
888
|
-
console.log('
|
815
|
+
console.log('cdj------触摸结束');
|
889
816
|
this.$emit('onDragEventEnd', e);
|
890
817
|
// 如果只是短按(还在计时),就取消长按
|
891
818
|
this.cancelLongPress();
|
892
819
|
|
893
820
|
// 如果正在拖拽中,确保清理状态
|
894
821
|
if (this.isTouchDragging) {
|
822
|
+
// 取消动画帧
|
823
|
+
if (this.animationFrameId) {
|
824
|
+
cancelAnimationFrame(this.animationFrameId);
|
825
|
+
this.animationFrameId = null;
|
826
|
+
}
|
827
|
+
|
895
828
|
// 移除全局事件监听
|
896
|
-
document.removeEventListener('touchmove', this.
|
829
|
+
document.removeEventListener('touchmove', this.onGlobalTouchMove, {
|
897
830
|
passive: false,
|
831
|
+
capture: true,
|
898
832
|
});
|
899
833
|
document.removeEventListener('touchend', this.onTouchEnd, {
|
900
834
|
passive: false,
|
835
|
+
capture: true,
|
901
836
|
});
|
902
837
|
|
903
|
-
//
|
904
|
-
|
905
|
-
|
906
|
-
this.animationFrameId = null;
|
907
|
-
}
|
838
|
+
// 恢复页面滚动
|
839
|
+
document.body.style.overflow = '';
|
840
|
+
document.body.style.touchAction = '';
|
908
841
|
|
909
842
|
this.isTouchDragging = false;
|
910
843
|
this.isDragClone = false;
|
911
844
|
this.hoverIndex = null;
|
912
845
|
this.draggingIndex = null;
|
913
|
-
|
846
|
+
|
914
847
|
// 如果不再拖拽,恢复touch-action(但保持refresh隐藏,因为仍在编辑状态)
|
915
848
|
const elements = this.findParentElements();
|
916
849
|
if (elements.listInner) {
|
@@ -921,24 +854,32 @@ export default {
|
|
921
854
|
|
922
855
|
// 触摸结束处理 - 全局事件
|
923
856
|
onTouchEnd(e) {
|
924
|
-
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
|
+
}
|
925
869
|
|
926
|
-
// 恢复拖拽模式前的样式
|
927
|
-
this.restoreDragModeStyles();
|
928
|
-
|
929
870
|
// 移除全局事件监听
|
930
|
-
document.removeEventListener('touchmove', this.
|
871
|
+
document.removeEventListener('touchmove', this.onGlobalTouchMove, {
|
931
872
|
passive: false,
|
873
|
+
capture: true,
|
932
874
|
});
|
933
875
|
document.removeEventListener('touchend', this.onTouchEnd, {
|
934
876
|
passive: false,
|
877
|
+
capture: true,
|
935
878
|
});
|
936
879
|
|
937
|
-
//
|
938
|
-
|
939
|
-
|
940
|
-
this.animationFrameId = null;
|
941
|
-
}
|
880
|
+
// 恢复页面滚动
|
881
|
+
document.body.style.overflow = '';
|
882
|
+
document.body.style.touchAction = '';
|
942
883
|
|
943
884
|
// 重置拖拽状态
|
944
885
|
this.isTouchDragging = false;
|
@@ -956,7 +897,6 @@ export default {
|
|
956
897
|
if (gridBoxes && gridBoxes.length > 0) {
|
957
898
|
const box = gridBoxes[0];
|
958
899
|
this.gridBoxWidth = box.offsetWidth;
|
959
|
-
console.log('Grid box宽度:', this.gridBoxWidth);
|
960
900
|
|
961
901
|
// 更新text样式,确保不超出
|
962
902
|
const textElements = document.querySelectorAll('.itemText');
|
@@ -969,19 +909,14 @@ export default {
|
|
969
909
|
|
970
910
|
initLottieAnimations() {
|
971
911
|
this.$nextTick(() => {
|
972
|
-
// 清理之前的动画实例
|
973
912
|
Object.keys(this.lottieAnimations).forEach((key) => {
|
974
913
|
const anim = this.lottieAnimations[key];
|
975
914
|
if (anim && typeof anim.destroy === 'function') {
|
976
|
-
console.log(
|
915
|
+
console.log(`cdj------销毁旧动画实例: ${key}`);
|
977
916
|
try {
|
978
917
|
anim.removeEventListener('complete');
|
979
|
-
anim.removeEventListener('DOMLoaded');
|
980
|
-
anim.removeEventListener('data_ready');
|
981
|
-
anim.removeEventListener('loaded_images');
|
982
|
-
anim.removeEventListener('loopComplete');
|
983
918
|
} catch (e) {
|
984
|
-
console.warn(
|
919
|
+
console.warn(`cdj------移除事件监听器失败: ${e.message}`);
|
985
920
|
}
|
986
921
|
anim.destroy();
|
987
922
|
}
|
@@ -992,45 +927,48 @@ export default {
|
|
992
927
|
this.lottieAnimations = {};
|
993
928
|
|
994
929
|
console.log(
|
995
|
-
'
|
930
|
+
'cdj------开始初始化Lottie动画,列表项数量:',
|
996
931
|
this.processedList.length
|
997
932
|
);
|
998
933
|
|
999
|
-
//
|
1000
|
-
|
1001
|
-
|
1002
|
-
|
1003
|
-
|
1004
|
-
// 加载背景动画
|
934
|
+
// 为每个列表项初始化动画
|
935
|
+
this.processedList.forEach((item) => {
|
936
|
+
const itemId = String(item.itemView.id);
|
937
|
+
// 加载背景动画
|
938
|
+
if (item.bgAnimView && item.bgAnimView.animUrl) {
|
1005
939
|
this.loadLottieAnimation(
|
1006
940
|
item.bgAnimView,
|
1007
941
|
`bgAnim-${itemId}`,
|
1008
942
|
`bg-${itemId}`,
|
1009
943
|
item
|
1010
944
|
);
|
945
|
+
}
|
1011
946
|
|
1012
|
-
|
947
|
+
// 加载加载中动画
|
948
|
+
if (item.loadingAnimView && item.loadingAnimView.animUrl) {
|
1013
949
|
this.loadLottieAnimation(
|
1014
950
|
item.loadingAnimView,
|
1015
951
|
`loadingAnim-${itemId}`,
|
1016
952
|
`loading-${itemId}`,
|
1017
953
|
item
|
1018
954
|
);
|
955
|
+
}
|
1019
956
|
|
1020
|
-
|
957
|
+
// 加载前景动画
|
958
|
+
if (item.frontAnimView && item.frontAnimView.animUrl) {
|
1021
959
|
this.loadLottieAnimation(
|
1022
960
|
item.frontAnimView,
|
1023
961
|
`frontAnim-${itemId}`,
|
1024
962
|
`front-${itemId}`,
|
1025
963
|
item
|
1026
964
|
);
|
1027
|
-
}
|
1028
|
-
}
|
965
|
+
}
|
966
|
+
});
|
1029
967
|
});
|
1030
968
|
},
|
1031
969
|
|
1032
970
|
// 抽取公共的loadLottieAnimation方法
|
1033
|
-
loadLottieAnimation(animView, refName, animKey, item) {
|
971
|
+
loadLottieAnimation(animView, refName, animKey, item, dataIndex) {
|
1034
972
|
if (!animView || !animView.animUrl) {
|
1035
973
|
return;
|
1036
974
|
}
|
@@ -1052,129 +990,92 @@ export default {
|
|
1052
990
|
typeof animView.visibility !== 'number' ||
|
1053
991
|
animView.visibility !== 0
|
1054
992
|
) {
|
1055
|
-
|
1056
|
-
|
1057
|
-
.
|
1058
|
-
|
1059
|
-
|
1060
|
-
|
1061
|
-
|
1062
|
-
|
1063
|
-
|
1064
|
-
|
1065
|
-
|
1066
|
-
|
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();
|
1067
1023
|
delete this.lottieAnimations[animKey];
|
1068
|
-
}
|
1069
1024
|
|
1070
|
-
|
1071
|
-
|
1072
|
-
|
1073
|
-
|
1074
|
-
|
1075
|
-
|
1076
|
-
|
1077
|
-
|
1078
|
-
|
1079
|
-
|
1080
|
-
|
1081
|
-
|
1082
|
-
// 保存动画实例
|
1083
|
-
this.lottieAnimations[animKey] = anim;
|
1084
|
-
|
1085
|
-
// 添加动画事件监听
|
1086
|
-
|
1087
|
-
anim.addEventListener('complete', () => {
|
1088
|
-
// 检查是否需要销毁动画(非循环动画完成后销毁)
|
1089
|
-
if (!item.animRepeatCount) {
|
1090
|
-
// 销毁前再次检查实例是否存在
|
1091
|
-
if (this.lottieAnimations[animKey] === anim) {
|
1092
|
-
anim.removeEventListener('complete');
|
1093
|
-
anim.removeEventListener('DOMLoaded');
|
1094
|
-
anim.removeEventListener('data_ready');
|
1095
|
-
anim.removeEventListener('loaded_images');
|
1096
|
-
anim.removeEventListener('loopComplete');
|
1097
|
-
anim.destroy();
|
1098
|
-
delete this.lottieAnimations[animKey];
|
1099
|
-
|
1100
|
-
// 查找并隐藏对应的动画容器
|
1101
|
-
this.$nextTick(() => {
|
1102
|
-
const animContainer =
|
1103
|
-
this.$refs[refName] && this.$refs[refName][0];
|
1104
|
-
if (animContainer) {
|
1105
|
-
animContainer.style.display = 'none';
|
1106
|
-
}
|
1107
|
-
|
1108
|
-
// 将对应数据中的animUrl清空
|
1109
|
-
const itemId = item.itemView.id;
|
1110
|
-
const index = this.processedList.findIndex(
|
1111
|
-
(i) => i.itemView.id === itemId
|
1112
|
-
);
|
1113
|
-
if (index !== -1) {
|
1114
|
-
// 根据动画类型设置对应的animUrl为空
|
1115
|
-
if (animKey.startsWith('bg-')) {
|
1116
|
-
this.$set(
|
1117
|
-
this.processedList[index].bgAnimView,
|
1118
|
-
'animUrl',
|
1119
|
-
''
|
1120
|
-
);
|
1121
|
-
// 同步更新原始数据
|
1122
|
-
const dataIndex = this.data.list.findIndex(
|
1123
|
-
(i) => i.itemView.id === itemId
|
1124
|
-
);
|
1125
|
-
if (dataIndex !== -1) {
|
1126
|
-
this.$set(
|
1127
|
-
this.data.list[dataIndex].bgAnimView,
|
1128
|
-
'animUrl',
|
1129
|
-
''
|
1130
|
-
);
|
1131
|
-
}
|
1132
|
-
} else if (animKey.startsWith('loading-')) {
|
1133
|
-
this.$set(
|
1134
|
-
this.processedList[index].loadingAnimView,
|
1135
|
-
'animUrl',
|
1136
|
-
''
|
1137
|
-
);
|
1138
|
-
// 同步更新原始数据
|
1139
|
-
const dataIndex = this.data.list.findIndex(
|
1140
|
-
(i) => i.itemView.id === itemId
|
1141
|
-
);
|
1142
|
-
if (dataIndex !== -1) {
|
1143
|
-
this.$set(
|
1144
|
-
this.data.list[dataIndex].loadingAnimView,
|
1145
|
-
'animUrl',
|
1146
|
-
''
|
1147
|
-
);
|
1148
|
-
}
|
1149
|
-
} else if (animKey.startsWith('front-')) {
|
1150
|
-
this.$set(
|
1151
|
-
this.processedList[index].frontAnimView,
|
1152
|
-
'animUrl',
|
1153
|
-
''
|
1154
|
-
);
|
1155
|
-
// 同步更新原始数据
|
1156
|
-
const dataIndex = this.data.list.findIndex(
|
1157
|
-
(i) => i.itemView.id === itemId
|
1158
|
-
);
|
1159
|
-
if (dataIndex !== -1) {
|
1160
|
-
this.$set(
|
1161
|
-
this.data.list[dataIndex].frontAnimView,
|
1162
|
-
'animUrl',
|
1163
|
-
''
|
1164
|
-
);
|
1165
|
-
}
|
1166
|
-
}
|
1167
|
-
}
|
1168
|
-
});
|
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';
|
1169
1036
|
}
|
1170
|
-
}
|
1171
|
-
});
|
1172
1037
|
|
1173
|
-
|
1174
|
-
|
1175
|
-
|
1176
|
-
|
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
|
+
}
|
1177
1077
|
} catch (error) {
|
1078
|
+
console.error('加载Lottie动画失败:', error);
|
1178
1079
|
}
|
1179
1080
|
},
|
1180
1081
|
|
@@ -1189,198 +1090,35 @@ export default {
|
|
1189
1090
|
}
|
1190
1091
|
});
|
1191
1092
|
},
|
1192
|
-
|
1193
|
-
// 暂未使用,但保留用于将来扩展
|
1194
|
-
leftTopIconClick(e) {
|
1195
|
-
e.preventDefault();
|
1196
|
-
e.stopPropagation();
|
1197
|
-
// 这里可以添加将来的处理逻辑
|
1198
|
-
return false;
|
1199
|
-
},
|
1200
|
-
|
1201
1093
|
// 查找父级元素和refresh元素
|
1202
1094
|
findParentElements() {
|
1203
1095
|
// 返回存储的元素引用
|
1204
1096
|
return {
|
1205
1097
|
listInner: this.weexListInnerEl,
|
1206
|
-
refresh: this.weexRefreshEl
|
1098
|
+
refresh: this.weexRefreshEl,
|
1207
1099
|
};
|
1208
1100
|
},
|
1209
|
-
|
1210
|
-
// 进入拖拽模式时应用样式
|
1211
|
-
applyDragModeStyles() {
|
1212
|
-
const elements = this.findParentElements();
|
1213
|
-
|
1214
|
-
// 设置weex-list-inner的touch-action: none(只在拖拽时)
|
1215
|
-
if (elements.listInner && this.isTouchDragging) {
|
1216
|
-
elements.listInner.style.touchAction = 'none';
|
1217
|
-
}
|
1218
|
-
},
|
1219
|
-
|
1220
|
-
// 退出拖拽模式时恢复样式
|
1221
|
-
restoreDragModeStyles() {
|
1222
|
-
const elements = this.findParentElements();
|
1223
|
-
|
1224
|
-
// 恢复weex-list-inner的touch-action(只在拖拽时修改)
|
1225
|
-
if (elements.listInner && this.isTouchDragging) {
|
1226
|
-
elements.listInner.style.touchAction = this.originListInnerStyle;
|
1227
|
-
}
|
1228
|
-
|
1229
|
-
// 如果不在编辑状态,恢复weex-refresh的display
|
1230
|
-
if (elements.refresh && !this.data.isEditing) {
|
1231
|
-
elements.refresh.style.display = 'flex';
|
1232
|
-
}
|
1233
|
-
},
|
1234
1101
|
},
|
1235
1102
|
watch: {
|
1236
|
-
// 监听初始数据变化
|
1237
|
-
initialItems: {
|
1238
|
-
handler(newItems) {
|
1239
|
-
if (!this.isTouchDragging) {
|
1240
|
-
this.items = [...newItems];
|
1241
|
-
}
|
1242
|
-
},
|
1243
|
-
deep: true,
|
1244
|
-
},
|
1245
1103
|
// 监听列表数据变化,自动更新处理后的数据
|
1246
1104
|
'data.list': {
|
1247
1105
|
handler(newList, oldList) {
|
1248
1106
|
this.processedList = this.generateDataList();
|
1107
|
+
console.log(newList, this.processedList, 'cdj------数据变化');
|
1249
1108
|
this.$nextTick(() => {
|
1250
1109
|
this.updateGridBoxWidth();
|
1251
1110
|
this.updateFixedItemSize();
|
1252
|
-
this.initLottieAnimations();
|
1253
|
-
});
|
1254
|
-
},
|
1255
|
-
deep: true,
|
1256
|
-
},
|
1257
|
-
// 监听所有动画URL变化,确保能及时更新动画
|
1258
|
-
processedList: {
|
1259
|
-
handler(newList, oldList) {
|
1260
|
-
if (!newList || !newList.length || this.isTouchDragging) return;
|
1261
|
-
|
1262
|
-
// 避免在拖拽过程中重新初始化动画
|
1263
|
-
if (this.draggingIndex !== null) return;
|
1264
|
-
|
1265
|
-
// 检查每个项目的动画URL是否有变化
|
1266
|
-
newList.forEach((item, index) => {
|
1267
|
-
// 如果是新增的项目,直接更新
|
1268
|
-
if (!oldList || !oldList[index]) {
|
1269
|
-
this.$nextTick(() => {
|
1270
|
-
const itemId = item.itemView.id;
|
1271
|
-
this.loadLottieAnimation(
|
1272
|
-
item.bgAnimView,
|
1273
|
-
`bgAnim-${itemId}`,
|
1274
|
-
`bg-${itemId}`,
|
1275
|
-
item
|
1276
|
-
);
|
1277
|
-
this.loadLottieAnimation(
|
1278
|
-
item.loadingAnimView,
|
1279
|
-
`loadingAnim-${itemId}`,
|
1280
|
-
`loading-${itemId}`,
|
1281
|
-
item
|
1282
|
-
);
|
1283
|
-
this.loadLottieAnimation(
|
1284
|
-
item.frontAnimView,
|
1285
|
-
`frontAnim-${itemId}`,
|
1286
|
-
`front-${itemId}`,
|
1287
|
-
item
|
1288
|
-
);
|
1289
|
-
});
|
1290
|
-
return;
|
1291
|
-
}
|
1292
|
-
|
1293
|
-
// 检查bgAnimView.animUrl是否变化
|
1294
|
-
if (
|
1295
|
-
item.bgAnimView &&
|
1296
|
-
oldList[index].bgAnimView &&
|
1297
|
-
item.bgAnimView.animUrl !== oldList[index].bgAnimView.animUrl
|
1298
|
-
) {
|
1299
|
-
this.$nextTick(() => {
|
1300
|
-
const itemId = item.itemView.id;
|
1301
|
-
if (this.lottieAnimations[`bg-${itemId}`]) {
|
1302
|
-
this.lottieAnimations[`bg-${itemId}`].destroy();
|
1303
|
-
delete this.lottieAnimations[`bg-${itemId}`];
|
1304
|
-
}
|
1305
|
-
this.loadLottieAnimation(
|
1306
|
-
item.bgAnimView,
|
1307
|
-
`bgAnim-${itemId}`,
|
1308
|
-
`bg-${itemId}`,
|
1309
|
-
item
|
1310
|
-
);
|
1311
|
-
});
|
1312
|
-
}
|
1313
|
-
|
1314
|
-
// 检查loadingAnimView.animUrl是否变化
|
1315
|
-
if (
|
1316
|
-
item.loadingAnimView &&
|
1317
|
-
oldList[index].loadingAnimView &&
|
1318
|
-
item.loadingAnimView.animUrl !==
|
1319
|
-
oldList[index].loadingAnimView.animUrl
|
1320
|
-
) {
|
1321
|
-
this.$nextTick(() => {
|
1322
|
-
const itemId = item.itemView.id;
|
1323
|
-
if (this.lottieAnimations[`loading-${itemId}`]) {
|
1324
|
-
this.lottieAnimations[`loading-${itemId}`].destroy();
|
1325
|
-
delete this.lottieAnimations[`loading-${itemId}`];
|
1326
|
-
}
|
1327
|
-
this.loadLottieAnimation(
|
1328
|
-
item.loadingAnimView,
|
1329
|
-
`loadingAnim-${itemId}`,
|
1330
|
-
`loading-${itemId}`,
|
1331
|
-
item
|
1332
|
-
);
|
1333
|
-
});
|
1334
|
-
}
|
1335
|
-
|
1336
|
-
// 检查frontAnimView.animUrl是否变化
|
1337
|
-
if (
|
1338
|
-
item.frontAnimView &&
|
1339
|
-
oldList[index].frontAnimView &&
|
1340
|
-
item.frontAnimView.animUrl !== oldList[index].frontAnimView.animUrl
|
1341
|
-
) {
|
1342
|
-
this.$nextTick(() => {
|
1343
|
-
const itemId = item.itemView.id;
|
1344
|
-
if (this.lottieAnimations[`front-${itemId}`]) {
|
1345
|
-
this.lottieAnimations[`front-${itemId}`].destroy();
|
1346
|
-
delete this.lottieAnimations[`front-${itemId}`];
|
1347
|
-
}
|
1348
|
-
this.loadLottieAnimation(
|
1349
|
-
item.frontAnimView,
|
1350
|
-
`frontAnim-${itemId}`,
|
1351
|
-
`front-${itemId}`,
|
1352
|
-
item
|
1353
|
-
);
|
1354
|
-
});
|
1355
|
-
}
|
1356
1111
|
});
|
1357
1112
|
},
|
1358
1113
|
deep: true,
|
1359
1114
|
},
|
1360
|
-
// 添加对编辑状态的监听
|
1361
|
-
'data.isEditing': {
|
1362
|
-
handler(newValue) {
|
1363
|
-
const elements = this.findParentElements();
|
1364
|
-
if (elements.refresh) {
|
1365
|
-
if (newValue) {
|
1366
|
-
elements.refresh.style.maxHeight = '0px';
|
1367
|
-
} else {
|
1368
|
-
elements.refresh.style.maxHeight = '999px'
|
1369
|
-
}
|
1370
|
-
}
|
1371
|
-
},
|
1372
|
-
immediate: true
|
1373
|
-
},
|
1374
1115
|
},
|
1375
1116
|
mounted() {
|
1376
|
-
console.log(this.data, 'djdjdjdjdjdjdj');
|
1117
|
+
console.log(this.data, 'cdj------djdjdjdjdjdjdj');
|
1377
1118
|
// 初始获取grid-box宽度
|
1378
1119
|
this.updateGridBoxWidth();
|
1379
1120
|
// 获取并存储固定宽高
|
1380
1121
|
this.updateFixedItemSize();
|
1381
|
-
|
1382
|
-
this.searchDom()
|
1383
|
-
|
1384
1122
|
// 监听窗口大小变化,更新grid-box宽度
|
1385
1123
|
window.addEventListener('resize', () => {
|
1386
1124
|
this.updateGridBoxWidth();
|
@@ -1399,6 +1137,19 @@ export default {
|
|
1399
1137
|
document.removeEventListener('touchend', this.onTouchEnd, {
|
1400
1138
|
passive: false,
|
1401
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
|
+
|
1402
1153
|
window.removeEventListener('resize', () => {
|
1403
1154
|
this.updateGridBoxWidth();
|
1404
1155
|
this.updateFixedItemSize();
|
@@ -1416,15 +1167,25 @@ export default {
|
|
1416
1167
|
if (anim && typeof anim.destroy === 'function') {
|
1417
1168
|
try {
|
1418
1169
|
anim.removeEventListener('complete');
|
1419
|
-
anim.removeEventListener('DOMLoaded');
|
1420
|
-
anim.removeEventListener('data_ready');
|
1421
|
-
anim.removeEventListener('loaded_images');
|
1422
|
-
anim.removeEventListener('loopComplete');
|
1423
1170
|
} catch (e) {
|
1171
|
+
console.warn(`移除事件监听器失败: ${e.message}`);
|
1424
1172
|
}
|
1425
1173
|
anim.destroy();
|
1426
1174
|
}
|
1427
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
|
+
}
|
1428
1189
|
});
|
1429
1190
|
|
1430
1191
|
// 确保动画实例对象被清空
|
@@ -1433,11 +1194,6 @@ export default {
|
|
1433
1194
|
created() {
|
1434
1195
|
// 初始化处理后的数据列表
|
1435
1196
|
this.processedList = this.generateDataList();
|
1436
|
-
|
1437
|
-
// 添加测试拖拽模式的方法
|
1438
|
-
window.testDragMode = (index = 0) => {
|
1439
|
-
this.testDragMode(index);
|
1440
|
-
};
|
1441
1197
|
},
|
1442
1198
|
};
|
1443
1199
|
</script>
|
@@ -1469,8 +1225,10 @@ button {
|
|
1469
1225
|
|
1470
1226
|
/* 优化排序过渡效果 */
|
1471
1227
|
.grid-fade-move {
|
1472
|
-
transition: transform 0.
|
1228
|
+
transition: transform 0.3s cubic-bezier(0.2, 0, 0.2, 1);
|
1473
1229
|
will-change: transform;
|
1230
|
+
position: relative;
|
1231
|
+
z-index: 2;
|
1474
1232
|
}
|
1475
1233
|
|
1476
1234
|
.grid-item {
|
@@ -1510,7 +1268,9 @@ button {
|
|
1510
1268
|
top: 0;
|
1511
1269
|
pointer-events: none;
|
1512
1270
|
}
|
1513
|
-
|
1271
|
+
.lottie-container >>> * {
|
1272
|
+
pointer-events: none;
|
1273
|
+
}
|
1514
1274
|
.bg-anim,
|
1515
1275
|
.front-anim {
|
1516
1276
|
z-index: 1;
|