@dolphinweex/weex-harmony 0.1.100 → 0.1.102

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": "@dolphinweex/weex-harmony",
3
- "version": "0.1.100",
3
+ "version": "0.1.102",
4
4
  "description": "weex harmony adapter",
5
5
  "main": "index.js",
6
6
  "files": [
@@ -46,6 +46,10 @@ export default {
46
46
  type: String,
47
47
  default: '确认'
48
48
  },
49
+ userInteractionEnabled:{
50
+ type: Boolean,
51
+ default: false
52
+ }
49
53
  },
50
54
  computed: {
51
55
  hosSameLayerArgs() {
@@ -60,6 +64,7 @@ export default {
60
64
  onAudioInputCancel: this.onAudioInputCancel,
61
65
  onAudioInputFail: this.onAudioInputFail,
62
66
  onAudioInputComplete: this.onAudioInputComplete,
67
+ userInteractionEnabled: this.userInteractionEnabled
63
68
  };
64
69
  },
65
70
  },
@@ -1,7 +1,6 @@
1
1
  <template>
2
2
  <div>
3
3
  <div class="progress-container" v-if="progressText">
4
- <img class="progress-loading" src="data:image/gif;base64,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" alt="loading" />
5
4
  <text class="progress-text">{{progressText}}</text>
6
5
  </div>
7
6
  <iframe
@@ -33,7 +32,7 @@ const weexModule = weex.requireModule("weexModule");
33
32
  export default {
34
33
  data() {
35
34
  return {
36
- isDebug: false, // 调试开关
35
+ isDebug: true, // 调试开关
37
36
  url: "",
38
37
  pluginType: "weex",
39
38
  backgroundColor: "transparent",
@@ -50,6 +49,10 @@ export default {
50
49
  _useChildrenTotalHeight: false,
51
50
  _parentElement: null, // 符合条件的父级元素
52
51
  _mutationObserver: null,
52
+ _debounceTimer: null,
53
+ _isInternalUpdating: false, // 内部更新锁,防止反馈回路导致反复刷新
54
+ _pendingUpdate: false, // 锁期间是否有待处理的更新
55
+ _applyTimer: null,
53
56
  };
54
57
  },
55
58
  components: {
@@ -246,63 +249,6 @@ export default {
246
249
  return height;
247
250
  },
248
251
 
249
- isSafeHeightFallbackTarget(el, scroller) {
250
- if (!el || !scroller) return false;
251
- if (el === scroller) return false;
252
- if (!scroller.contains(el)) return false;
253
- if (!el.children || el.children.length === 0) return false;
254
-
255
- const className = `${el.className || ''}`;
256
- const unsafeKeywords = ['weex-scroller-inner', 'weex-waterfall-inner', 'weex-waterfall-inner-columns'];
257
- if (unsafeKeywords.some(keyword => className.includes(keyword))) {
258
- this.debugWarn(`fallback 目标命中不安全关键字,放弃使用: ${className}`);
259
- return false;
260
- }
261
-
262
- const firstChild = el.children[0];
263
- if (!firstChild) return false;
264
-
265
- const firstChildClassName = `${firstChild.className || ''}`;
266
- if (firstChildClassName.includes('weex-root')) {
267
- this.debugLog(`fallback 目标首子节点已是 weex-root,可安全使用: ${className}`);
268
- return true;
269
- }
270
-
271
- if (el.children.length === 1) {
272
- this.debugLog(`fallback 目标仅有一个子节点,允许临时使用: ${className}`);
273
- return true;
274
- }
275
-
276
- this.debugWarn(`fallback 目标存在多个子节点且无 weex-root 标识,放弃使用: ${className}`);
277
- return false;
278
- },
279
-
280
- findWeexHeightTarget(doc) {
281
- if (!doc) return null;
282
- const globalRoot = doc.querySelector('.weex-root');
283
- const scroller = doc.querySelector('.weex-scroller-inner');
284
- if (scroller) {
285
- this.debugLog(`找到 .weex-scroller-inner`);
286
- const scrollerRoot = scroller.querySelector('.weex-root');
287
- if (scrollerRoot) {
288
- this.debugLog(`在 .weex-scroller-inner 内找到 .weex-root`);
289
- return scrollerRoot;
290
- }
291
- const fallbackTarget = scroller.children && scroller.children[0];
292
- if (this.isSafeHeightFallbackTarget(fallbackTarget, scroller)) {
293
- this.debugLog(`使用安全 fallback 容器: ${fallbackTarget.className || fallbackTarget.tagName}`);
294
- return fallbackTarget;
295
- }
296
- this.debugWarn(`.weex-scroller-inner 内未找到可用目标,继续等待`);
297
- }
298
- if (globalRoot) {
299
- this.debugLog(`使用全局 .weex-root`);
300
- return globalRoot;
301
- }
302
- return null;
303
- },
304
-
305
-
306
252
  // 监听 iframe 内容高度变化
307
253
  startWeexRootHeightMonitoring() {
308
254
  this.debugLog(`startWeexRootHeightMonitoring 开始: embedId=${this.embedId}`);
@@ -318,7 +264,17 @@ export default {
318
264
 
319
265
  try {
320
266
  const doc = iframe.contentDocument || iframe.contentWindow.document;
321
- const target = this.findWeexHeightTarget(doc);
267
+ let target = null;
268
+
269
+ // 1. 优先找 weex-scroller-inner 及其内部的 weex-root
270
+ const scroller = doc.querySelector('.weex-scroller-inner');
271
+ if (scroller) {
272
+ this.debugLog(`找到 .weex-scroller-inner`);
273
+ target = scroller.querySelector('.weex-root') || scroller.children[0];
274
+ } else {
275
+ // 2. 备选找全局 weex-root
276
+ target = doc.querySelector('.weex-root');
277
+ }
322
278
 
323
279
  if (!target) {
324
280
  if (attempts >= maxAttempts) {
@@ -353,8 +309,21 @@ export default {
353
309
  this.debugLog(`设置 Observers: target=${target ? (target.className || target.tagName) : 'null'}`);
354
310
 
355
311
  const onUpdate = () => {
312
+ // 如果正在内部更新高度引起的重排,记录下有变化发生,然后直接跳过
313
+ if (this._isInternalUpdating) {
314
+ this._pendingUpdate = true;
315
+ return;
316
+ }
317
+
356
318
  this.debugLog(`变化触发更新`);
357
- this.updateIframeHeightFromElement(target);
319
+ if (this._debounceTimer) {
320
+ clearTimeout(this._debounceTimer);
321
+ }
322
+ this._debounceTimer = setTimeout(() => {
323
+ this.debugLog(`防抖后执行更新`);
324
+ this.updateIframeHeightFromElement(target);
325
+ this._debounceTimer = null;
326
+ }, 200);
358
327
  };
359
328
 
360
329
  if (this._resizeObserver) this._resizeObserver.disconnect();
@@ -400,8 +369,16 @@ export default {
400
369
  this.debugLog(`计算得到elementHeight=${elementHeight}px`);
401
370
 
402
371
  if (elementHeight > 0) {
403
- const finalHeight = elementHeight;
404
- this.debugLog(`finalHeight=${finalHeight}px (elementHeight=${elementHeight})`);
372
+ // isPluginMenu=false:始终不按视口裁剪,保持原逻辑不变。
373
+ // isPluginMenu=true:改为不裁剪,避免多组件时下方 iframe 被裁成一条线、且裁剪值同步到父级压扁整块。
374
+ let maxHeight = Number.POSITIVE_INFINITY;
375
+ if (this.isPluginMenu) {
376
+ maxHeight = Number.POSITIVE_INFINITY; // 仅对 plugin-menu 取消视口裁剪,不影响 isPluginMenu=false
377
+ }
378
+ this.debugLog(`maxHeight=${maxHeight} (isPluginMenu=${this.isPluginMenu})`);
379
+
380
+ const finalHeight = elementHeight > maxHeight ? maxHeight : elementHeight;
381
+ this.debugLog(`finalHeight=${finalHeight}px (elementHeight=${elementHeight}, maxHeight=${maxHeight})`);
405
382
 
406
383
  // 更新 iframe 高度(考虑 weex scale)
407
384
  const scale = weex.config.env.scale || 1;
@@ -432,9 +409,34 @@ export default {
432
409
 
433
410
  const newHeight = `${newHeightValue}px`;
434
411
  this.debugLog(`计算newHeight=${newHeight} (finalHeight=${finalHeight}, scale=${scale}), 当前height=${this.height}`);
412
+
413
+ // 增大误差容忍度:如果差距小于 3px,认为没有实质变化,不触发属性更新。
414
+ // 3px 足以过滤 Weex 在处理 rem 布局时产生的浮点数舍入误差。
415
+ const currentHeightValue = parseFloat(this.height) || 0;
416
+ if (Math.abs(currentHeightValue - newHeightValue) < 3 && this.height !== '0px') {
417
+ this.debugLog(`⚠️ 高度微小抖动(${Math.abs(currentHeightValue - newHeightValue)}px),忽略微调以稳定布局`);
418
+ return;
419
+ }
420
+
435
421
  if (this.height !== newHeight) {
436
- this.height = newHeight;
437
- this.debugLog(`✅ iframe 高度已更新: ${finalHeight}px -> ${newHeight} (embedId: ${this.embedId})`);
422
+ this._isInternalUpdating = true; // 加锁
423
+
424
+ // 使用异步应用机制,确保在一轮布局周期内只应用最后一次高度结果
425
+ if (this._applyTimer) clearTimeout(this._applyTimer);
426
+ this._applyTimer = setTimeout(() => {
427
+ this.height = newHeight;
428
+ this.debugLog(`✅ [FINAL] iframe 高度已应用: ${newHeight} (embedId: ${this.embedId})`);
429
+
430
+ // 给 Weex 引擎留出更充分的布局响应时间,随后解锁并检查是否有遗漏
431
+ setTimeout(() => {
432
+ this._isInternalUpdating = false;
433
+ if (this._pendingUpdate) {
434
+ this._pendingUpdate = false;
435
+ this.debugLog(`补测锁期间拦截的变化`);
436
+ this.updateIframeHeightFromElement(element);
437
+ }
438
+ }, 600);
439
+ }, 50); // 极短的延迟即可实现一轮内的覆盖
438
440
  } else {
439
441
  this.debugLog(`⚠️ 高度未变化,不更新 (当前=${this.height}, 新值=${newHeight})`);
440
442
  }
@@ -505,10 +507,22 @@ export default {
505
507
 
506
508
  // 清理定时器
507
509
  if (this._heightCheckTimer) {
508
- this.debugLog(`清理定时器`);
510
+ this.debugLog(`清理高度检查定时器`);
509
511
  clearInterval(this._heightCheckTimer);
510
512
  this._heightCheckTimer = null;
511
513
  }
514
+
515
+ // 清理防抖定时器
516
+ if (this._debounceTimer) {
517
+ this.debugLog(`清理防抖定时器`);
518
+ clearTimeout(this._debounceTimer);
519
+ this._debounceTimer = null;
520
+ }
521
+
522
+ if (this._applyTimer) {
523
+ clearTimeout(this._applyTimer);
524
+ this._applyTimer = null;
525
+ }
512
526
 
513
527
  // 清理引用
514
528
  this._weexRoot = null;
@@ -559,4 +573,4 @@ export default {
559
573
  text-align: center;
560
574
  font-weight: 400;
561
575
  }
562
- </style>
576
+ </style>
@@ -88,7 +88,7 @@
88
88
  <div v-if="showDeleteConfirm" class="modal-mask">
89
89
  <div class="modal">
90
90
  <div class="modal-title">温馨提示</div>
91
- <div class="modal-content">删除所选关注视角后,相关的智能场景将执行失败</div>
91
+ <div class="modal-content">删除所选常看视角后,相关的智能场景将执行失败</div>
92
92
  <div class="modal-actions">
93
93
  <text class="btn cancel" @click="onDeleteCancel">取消</text>
94
94
  <div class="btn-divider"></div>