vite-uni-dev-tool 1.2.0 → 1.2.2

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.
Files changed (104) hide show
  1. package/README.md +17 -1
  2. package/dist/const.cjs +1 -1
  3. package/dist/const.d.ts +1 -1
  4. package/dist/const.js +1 -1
  5. package/dist/core-shared.d.ts +2 -3
  6. package/dist/core.d.ts +8 -8
  7. package/dist/core.js +1 -1
  8. package/dist/i18n/index.d.ts +0 -1
  9. package/dist/i18n/instance.d.ts +0 -1
  10. package/dist/i18n/locales/en.cjs +1 -1
  11. package/dist/i18n/locales/en.d.ts +1 -1
  12. package/dist/i18n/locales/en.js +1 -1
  13. package/dist/i18n/locales/zh-Hans.cjs +1 -1
  14. package/dist/i18n/locales/zh-Hans.d.ts +1 -1
  15. package/dist/i18n/locales/zh-Hans.js +1 -1
  16. package/dist/index.d.ts +0 -1
  17. package/dist/modules/devConsole/index.cjs +4 -4
  18. package/dist/modules/devConsole/index.d.ts +6 -107
  19. package/dist/modules/devConsole/index.js +4 -4
  20. package/dist/modules/devEvent/index.cjs +3 -3
  21. package/dist/modules/devEvent/index.d.ts +2 -3
  22. package/dist/modules/devEvent/index.js +3 -3
  23. package/dist/modules/devIntercept/index.cjs +14 -14
  24. package/dist/modules/devIntercept/index.d.ts +33 -5
  25. package/dist/modules/devIntercept/index.js +14 -14
  26. package/dist/modules/devStore/index.cjs +1 -1
  27. package/dist/modules/devStore/index.d.ts +48 -40
  28. package/dist/modules/devStore/index.js +1 -1
  29. package/dist/modules/devToolInfo/index.cjs +1 -1
  30. package/dist/modules/devToolInfo/index.d.ts +6 -25
  31. package/dist/modules/devToolInfo/index.js +1 -1
  32. package/dist/plugins/uniDevTool/transform/transformApp.d.ts +0 -1
  33. package/dist/plugins/uniDevTool/transform/transformMain.d.ts +0 -1
  34. package/dist/plugins/uniDevTool/transform/transformVue.d.ts +0 -1
  35. package/dist/plugins/uniDevTool/uniDevTool.d.ts +0 -1
  36. package/dist/plugins/uniGlobalComponents/uniGlobalComponents.d.ts +0 -1
  37. package/dist/plugins/utils/index.d.ts +0 -1
  38. package/dist/shims-uni.d.ts +26 -22
  39. package/dist/type.d.ts +44 -43
  40. package/dist/utils/array.d.ts +0 -1
  41. package/dist/utils/date.d.ts +0 -1
  42. package/dist/utils/file.d.ts +0 -1
  43. package/dist/utils/function.d.ts +0 -1
  44. package/dist/utils/index.d.ts +0 -1
  45. package/dist/utils/ip.d.ts +0 -1
  46. package/dist/utils/language.d.ts +14 -15
  47. package/dist/utils/object.cjs +1 -1
  48. package/dist/utils/object.d.ts +7 -8
  49. package/dist/utils/object.js +1 -1
  50. package/dist/utils/openLink.d.ts +0 -1
  51. package/dist/utils/page.d.ts +0 -1
  52. package/dist/utils/platform.d.ts +0 -1
  53. package/dist/utils/string.d.ts +0 -1
  54. package/dist/utils/utils.d.ts +0 -1
  55. package/dist/v3/DevTool/components/DevToolButton/index.vue +42 -6
  56. package/dist/v3/DevTool/components/DevToolWindow/hooks/useDevToolData.ts +36 -12
  57. package/dist/v3/DevTool/components/DevToolWindow/hooks/useDevToolHandlers.ts +16 -1
  58. package/dist/v3/DevTool/components/DevToolWindow/index.vue +27 -64
  59. package/dist/v3/DevTool/components/Instance/transformTree.ts +156 -138
  60. package/dist/v3/DevTool/components/SettingList/index.vue +8 -0
  61. package/dist/v3/DevTool/components/SettingList/modules/SettingBarrage.vue +16 -0
  62. package/dist/v3/DevTool/index.vue +87 -138
  63. package/dist/v3/components/AppTransition/index.vue +33 -53
  64. package/dist/v3/components/Barrage/BarrageItem.vue +66 -9
  65. package/dist/v3/components/Barrage/index.vue +3 -0
  66. package/dist/v3/components/DevErrorBoundary/index.vue +13 -5
  67. package/dist/v3/components/DraggableContainer/index.vue +186 -73
  68. package/dist/v3/components/MovableContainer/index.vue +2 -0
  69. package/dist/v3/components/Pick/index.vue +29 -30
  70. package/dist/v3/hooks/useContainerStyle.ts +15 -73
  71. package/package.json +4 -1
  72. package/dist/const.d.ts.map +0 -1
  73. package/dist/core-shared.d.ts.map +0 -1
  74. package/dist/core.d.ts.map +0 -1
  75. package/dist/i18n/index.d.ts.map +0 -1
  76. package/dist/i18n/instance.d.ts.map +0 -1
  77. package/dist/i18n/locales/en.d.ts.map +0 -1
  78. package/dist/i18n/locales/zh-Hans.d.ts.map +0 -1
  79. package/dist/index.d.ts.map +0 -1
  80. package/dist/modules/devConsole/index.d.ts.map +0 -1
  81. package/dist/modules/devEvent/index.d.ts.map +0 -1
  82. package/dist/modules/devIntercept/index.d.ts.map +0 -1
  83. package/dist/modules/devStore/index.d.ts.map +0 -1
  84. package/dist/modules/devToolInfo/index.d.ts.map +0 -1
  85. package/dist/plugins/uniDevTool/transform/transformApp.d.ts.map +0 -1
  86. package/dist/plugins/uniDevTool/transform/transformMain.d.ts.map +0 -1
  87. package/dist/plugins/uniDevTool/transform/transformVue.d.ts.map +0 -1
  88. package/dist/plugins/uniDevTool/uniDevTool.d.ts.map +0 -1
  89. package/dist/plugins/uniGlobalComponents/uniGlobalComponents.d.ts.map +0 -1
  90. package/dist/plugins/utils/index.d.ts.map +0 -1
  91. package/dist/type.d.ts.map +0 -1
  92. package/dist/utils/array.d.ts.map +0 -1
  93. package/dist/utils/date.d.ts.map +0 -1
  94. package/dist/utils/file.d.ts.map +0 -1
  95. package/dist/utils/function.d.ts.map +0 -1
  96. package/dist/utils/index.d.ts.map +0 -1
  97. package/dist/utils/ip.d.ts.map +0 -1
  98. package/dist/utils/language.d.ts.map +0 -1
  99. package/dist/utils/object.d.ts.map +0 -1
  100. package/dist/utils/openLink.d.ts.map +0 -1
  101. package/dist/utils/page.d.ts.map +0 -1
  102. package/dist/utils/platform.d.ts.map +0 -1
  103. package/dist/utils/string.d.ts.map +0 -1
  104. package/dist/utils/utils.d.ts.map +0 -1
@@ -1,11 +1,12 @@
1
1
  <template>
2
2
  <view data-dev-tool :class="`dev-tool dev-tool-${theme}`">
3
+ <!-- are you ok ? -->
3
4
  <DevToolButton
4
- v-if="devToolButtonVisible"
5
5
  :zIndex="zIndex"
6
6
  :customStyle="customStyle"
7
7
  :contentHeight="contentHeight"
8
8
  :devToolVersion="devToolVersion"
9
+ :devToolButtonVisible="devToolButtonVisible"
9
10
  @click="onDevToolButtonClick" />
10
11
 
11
12
  <DevToolWindow
@@ -41,6 +42,7 @@
41
42
  <!-- Barrage -->
42
43
  <Barrage
43
44
  ref="barrageRef"
45
+ :allowDrag="windowData.barrageAllowDrag"
44
46
  :zIndex="zIndex + 100"
45
47
  :maxTracks="windowData.barrageMaxTracks"
46
48
  :trackHeight="windowData.barrageTrackHeight"
@@ -231,147 +233,94 @@ function onSendMessage(param: { type: string; data: Record<string, any> }) {
231
233
  sendCommand(param.type, param.data);
232
234
  }
233
235
 
234
- function onDevOptionSend(data: DevTool.WindowData) {
235
- if (data) {
236
- // 采用合并策略而不是直接替换,防止丢失部分本地状态
237
- windowData.value = { ...windowData.value, ...data };
238
-
239
- if (data.devToolVersion !== undefined)
240
- devToolVersion.value = data.devToolVersion;
241
-
242
- if (data.sourceFileServers !== undefined)
243
- sourceFileServers.value = data.sourceFileServers;
244
-
245
- if (data.mode !== undefined) mode.value = data.mode;
246
-
247
- if (data.useDevSource !== undefined) useDevSource.value = data.useDevSource;
248
-
249
- if (data.zIndex !== undefined) zIndex.value = data.zIndex;
250
-
251
- if (data.baseFontSize !== undefined) baseFontSize.value = data.baseFontSize;
252
-
253
- if (data.tagFontSize !== undefined) tagFontSize.value = data.tagFontSize;
254
- if (data.tipsFontSize !== undefined) tipsFontSize.value = data.tipsFontSize;
255
- if (data.fontFamily !== undefined) fontFamily.value = data.fontFamily;
256
- if (data.fontWeight !== undefined) fontWeight.value = data.fontWeight;
257
- if (data.performanceVisible !== undefined)
258
- performanceVisible.value = data.performanceVisible;
259
-
260
- // 弹幕配置
261
- if (data.barrageVisible !== undefined)
262
- windowData.value.barrageVisible = data.barrageVisible;
263
- if (data.barrageShowWhenOpen !== undefined)
264
- windowData.value.barrageShowWhenOpen = data.barrageShowWhenOpen;
265
- if (data.barrageMaxTracks !== undefined)
266
- windowData.value.barrageMaxTracks = data.barrageMaxTracks;
267
- if (data.barrageTrackHeight !== undefined)
268
- windowData.value.barrageTrackHeight = data.barrageTrackHeight;
269
- if (data.barrageStartTop !== undefined)
270
- windowData.value.barrageStartTop = data.barrageStartTop;
271
- if (data.barrageDuration !== undefined)
272
- windowData.value.barrageDuration = data.barrageDuration;
273
- if (data.barrageMaxLength !== undefined)
274
- windowData.value.barrageMaxLength = data.barrageMaxLength;
275
-
276
- if (data.barrageTypes !== undefined) {
277
- if (Array.isArray(data.barrageTypes)) {
278
- windowData.value.barrageTypes = data.barrageTypes;
279
- } else {
280
- console.warn(
281
- '[DevTool] Received invalid barrageTypes in windowData:',
282
- data.barrageTypes,
283
- );
284
- }
285
- }
286
- }
287
- }
288
-
289
- function onChangeTheme(t: string) {
236
+ const onChangeTheme = (t: string) => {
290
237
  theme.value = t;
291
- }
238
+ };
292
239
 
293
- /**
294
- * 处理来自核心模块的消息
295
- */
296
- // 处理消息
297
- function handleCoreMessage(msg: any) {
298
- let type, data;
299
- try {
300
- const payload = typeof msg === 'string' ? JSON.parse(msg) : msg;
301
- type = payload.type;
302
- data = payload.data;
303
- } catch (e) {
304
- console.error('DevTool parse error', e);
305
- return;
240
+ const onDevOptionSend = (data: DevTool.WindowData) => {
241
+ if (!data) return;
242
+ windowData.value = { ...windowData.value, ...data };
243
+
244
+ if (data.devToolVersion !== undefined)
245
+ devToolVersion.value = data.devToolVersion;
246
+ if (data.sourceFileServers !== undefined)
247
+ sourceFileServers.value = data.sourceFileServers;
248
+ if (data.mode !== undefined) mode.value = data.mode;
249
+ if (data.useDevSource !== undefined) {
250
+ useDevSource.value =
251
+ (data.useDevSource as any) === 'undefined' ? false : !!data.useDevSource;
306
252
  }
253
+ if (data.zIndex !== undefined) zIndex.value = data.zIndex;
254
+ if (data.baseFontSize !== undefined) baseFontSize.value = data.baseFontSize;
255
+ if (data.tagFontSize !== undefined) tagFontSize.value = data.tagFontSize;
256
+ if (data.tipsFontSize !== undefined) tipsFontSize.value = data.tipsFontSize;
257
+ if (data.fontFamily !== undefined) fontFamily.value = data.fontFamily;
258
+ if (data.fontWeight !== undefined) fontWeight.value = data.fontWeight;
259
+ if (data.performanceVisible !== undefined)
260
+ performanceVisible.value = data.performanceVisible;
261
+
262
+ const barrageKeys: (keyof DevTool.WindowData)[] = [
263
+ 'barrageVisible',
264
+ 'barrageShowWhenOpen',
265
+ 'barrageMaxTracks',
266
+ 'barrageTrackHeight',
267
+ 'barrageStartTop',
268
+ 'barrageDuration',
269
+ 'barrageMaxLength',
270
+ 'barrageTypes',
271
+ ];
272
+ barrageKeys.forEach((k) => {
273
+ if (data[k] !== undefined) (windowData.value as any)[k] = data[k];
274
+ });
275
+ };
307
276
 
308
- // 避免 DevToolWindow 处理同样的数据消息(如果是广播的话)
309
- // 注意:DevToolWindow 也会收到这个消息并在内部处理
310
-
311
- switch (type) {
312
- case MSG_TYPE.BUTTON_VISIBLE:
313
- onShowDevToolButton(data);
314
- break;
315
- case MSG_TYPE.WINDOW_VISIBLE:
316
- onShowDevToolWindow(data);
317
- break;
318
- case MSG_TYPE.PERF_VISIBLE:
319
- performanceVisible.value = data;
320
- break;
321
- case MSG_TYPE.DATA_UPDATE:
322
- case MSG_TYPE.OPTION_UPDATE:
323
- onDevOptionSend(data);
324
- break;
325
- case MSG_TYPE.BARRAGE_VISIBLE:
326
- windowData.value.barrageVisible = data;
327
- break;
328
- case MSG_TYPE.BARRAGE_SHOW_WHEN_OPEN:
329
- windowData.value.barrageShowWhenOpen = data;
330
- break;
331
- case MSG_TYPE.BARRAGE_ADD:
332
- if (barrageFinalVisible.value && barrageRef.value) {
333
- const itemsList = data.items || [];
334
- itemsList.forEach((item: any) => {
335
- // 检查类型是否在允许列表中
336
- if (!windowData.value.barrageTypes?.includes(item.type || 'log'))
337
- return;
338
-
339
- if (item.type === 'network') {
340
- const status = item.status;
341
- // 异常定义:已完成(非 pending)且 (状态码非 2xx 或 为 'ERR')
342
- const isPending = status === 'pending';
343
- const isSuccess =
344
- typeof status === 'number'
345
- ? status >= 200 && status < 300
346
- : typeof status === 'string' && /^[2]\d{2}$/.test(status);
347
-
348
- if (!isPending && !isSuccess) {
349
- barrageRef.value.add(
350
- `[${item.method || 'GET'}] ${status} - ${item.url}`,
351
- 'network',
352
- );
353
- }
354
- } else if (item.type === 'transfer') {
355
- barrageRef.value.add(`Transfer Failed: ${item.url}`, 'error');
356
- } else if (item.type === 'websocket') {
357
- barrageRef.value.add(`WS: ${item.data}`, 'info');
358
- } else {
359
- const args = item.args || [];
360
- const text = args
361
- .map((arg: any) =>
362
- typeof arg?.value === 'string'
363
- ? arg.value
364
- : JSON.stringify(arg?.value ?? ''),
365
- )
366
- .join(' ');
367
- barrageRef.value.add(text, item.type || 'log');
368
- }
369
- });
370
- }
371
- break;
372
- // ... 其他消息处理
373
- }
374
- }
277
+ const handleCoreMessage = (msg: any) => {
278
+ const { type, data } = typeof msg === 'string' ? JSON.parse(msg) : msg;
279
+
280
+ const handlers: Record<string, () => void> = {
281
+ [MSG_TYPE.BUTTON_VISIBLE]: () => onShowDevToolButton(data),
282
+ [MSG_TYPE.WINDOW_VISIBLE]: () => onShowDevToolWindow(data),
283
+ [MSG_TYPE.PERF_VISIBLE]: () => (performanceVisible.value = data),
284
+ [MSG_TYPE.DATA_UPDATE]: () => onDevOptionSend(data),
285
+ [MSG_TYPE.OPTION_UPDATE]: () => onDevOptionSend(data),
286
+ [MSG_TYPE.BARRAGE_VISIBLE]: () => (windowData.value.barrageVisible = data),
287
+ [MSG_TYPE.BARRAGE_SHOW_WHEN_OPEN]: () =>
288
+ (windowData.value.barrageShowWhenOpen = data),
289
+ [MSG_TYPE.BARRAGE_ADD]: () => {
290
+ if (!barrageFinalVisible.value || !barrageRef.value) return;
291
+ (data.items || []).forEach((item: any) => {
292
+ if (!windowData.value.barrageTypes?.includes(item.type || 'log'))
293
+ return;
294
+ if (item.type === 'network') {
295
+ if (item.status === 'pending') return;
296
+ const ok =
297
+ typeof item.status === 'number'
298
+ ? item.status < 300
299
+ : !/ERR/.test(item.status);
300
+ if (!ok)
301
+ barrageRef.value.add(
302
+ `[${item.method || 'GET'}] ${item.status} - ${item.url}`,
303
+ 'network',
304
+ );
305
+ } else if (item.type === 'transfer') {
306
+ barrageRef.value.add(`Transfer Failed: ${item.url}`, 'error');
307
+ } else if (item.type === 'websocket') {
308
+ barrageRef.value.add(`WS: ${item.data}`, 'info');
309
+ } else {
310
+ const text = (item.args || [])
311
+ .map((a: any) =>
312
+ typeof a?.value === 'string'
313
+ ? a.value
314
+ : JSON.stringify(a?.value ?? ''),
315
+ )
316
+ .join(' ');
317
+ barrageRef.value.add(text, item.type || 'log');
318
+ }
319
+ });
320
+ },
321
+ };
322
+ handlers[type]?.();
323
+ };
375
324
 
376
325
  onBeforeMount(() => {
377
326
  const devToolInfo = getDevToolInfo();
@@ -64,76 +64,56 @@ const mergedStyle = computed(() => {
64
64
  });
65
65
 
66
66
  const transitionStyle = computed(() => {
67
- const styles: Record<string, string> = {
67
+ const active = isActive.value && !isLeaving.value;
68
+ const { x = 0, y = 0 } = props.origin || {};
69
+ const s: Record<string, string> = {
68
70
  transition: props.animated
69
71
  ? 'transform var(--transition-duration) var(--transition-timing), opacity var(--transition-duration) var(--transition-timing), clip-path var(--transition-duration) var(--transition-timing)'
70
72
  : 'none',
71
73
  };
72
74
 
73
- const active = isActive.value && !isLeaving.value;
74
- const x = props.origin?.x || 0;
75
- const y = props.origin?.y || 0;
76
-
77
- if (props.origin) {
78
- styles.transformOrigin = `${x}px ${y}px`;
79
- }
80
-
81
- if (props.name === 'fade') {
82
- styles.opacity = active ? '1' : '0';
83
- } else if (props.name === 'slide-bottom') {
84
- styles.transform = active ? 'translateY(0)' : 'translateY(100%)';
85
- } else if (props.name === 'slide-top') {
86
- styles.transform = active ? 'translateY(0)' : 'translateY(-100%)';
87
- } else if (props.name === 'slide-left') {
88
- styles.transform = active ? 'translateX(0)' : 'translateX(-100%)';
89
- } else if (props.name === 'slide-right') {
90
- styles.transform = active ? 'translateX(0)' : 'translateX(100%)';
91
- } else if (props.name === 'zoom') {
92
- styles.transform = active ? 'scale(1)' : 'scale(0)';
93
- styles.opacity = active ? '1' : '0';
94
- } else if (props.name === 'reveal') {
95
- styles.clipPath = active
96
- ? `circle(150% at ${x}px ${y}px)`
97
- : `circle(0% at ${x}px ${y}px)`;
75
+ if (props.origin) s.transformOrigin = `${x}px ${y}px`;
76
+
77
+ const name = props.name || 'fade';
78
+ if (name === 'fade') s.opacity = active ? '1' : '0';
79
+ else if (name === 'zoom') {
80
+ s.transform = `scale(${active ? 1 : 0})`;
81
+ s.opacity = active ? '1' : '0';
82
+ } else if (name === 'reveal')
83
+ s.clipPath = `circle(${active ? '150%' : '0%'} at ${x}px ${y}px)`;
84
+ else if (name.startsWith('slide-')) {
85
+ const dir = name.replace('slide-', '');
86
+ const axis = dir === 'left' || dir === 'right' ? 'X' : 'Y';
87
+ const val = dir === 'left' || dir === 'top' ? '-100%' : '100%';
88
+ s.transform = `translate${axis}(${active ? 0 : val})`;
98
89
  }
99
-
100
- return styles;
90
+ return s;
101
91
  });
102
92
 
103
93
  watch(
104
94
  () => props.show,
105
- (val, oldVal) => {
95
+ (val, old) => {
106
96
  if (val) {
107
97
  renderShow.value = true;
108
98
  isLeaving.value = false;
109
-
110
- if (!props.animated) {
111
- isActive.value = true;
112
- emit('after-enter');
113
- return;
114
- }
115
-
116
- // 必须分两步:1. 插入DOM 2. 触发Transition
117
- nextTick(() => {
99
+ if (!props.animated)
100
+ return ((isActive.value = true), emit('after-enter'));
101
+ nextTick(() =>
118
102
  setTimeout(() => {
119
103
  isActive.value = true;
120
- const duration = props.animated ? props.duration : 0;
121
- setTimeout(() => {
122
- emit('after-enter');
123
- }, duration);
124
- }, 30);
125
- });
126
- } else if (oldVal !== undefined) {
104
+ setTimeout(() => emit('after-enter'), props.duration);
105
+ }, 30),
106
+ );
107
+ } else if (old !== undefined) {
127
108
  isLeaving.value = true;
128
109
  isActive.value = false;
129
-
130
- const duration = props.animated ? props.duration : 0;
131
-
132
- setTimeout(() => {
133
- renderShow.value = false;
134
- isLeaving.value = false;
135
- emit('after-leave');
136
- }, duration);
110
+ setTimeout(
111
+ () => {
112
+ renderShow.value = isLeaving.value = false;
113
+ emit('after-leave');
114
+ },
115
+ props.animated ? props.duration : 0,
116
+ );
137
117
  }
138
118
  },
139
119
  { immediate: true },
@@ -1,6 +1,17 @@
1
1
  <template>
2
2
  <view class="barrage-item" :style="itemStyle" @animationend="onAnimationEnd">
3
- <view class="barrage-content" :class="type">
3
+ <view
4
+ class="barrage-content"
5
+ :class="type"
6
+ :style="contentStyle"
7
+ @mousedown.stop="onTouchStart"
8
+ @mousemove.stop="onTouchMove"
9
+ @mouseup.stop="onTouchEnd"
10
+ @mouseleave.stop="onTouchEnd"
11
+ @touchstart.stop="onTouchStart"
12
+ @touchmove.stop.prevent="onTouchMove"
13
+ @touchend.stop="onTouchEnd"
14
+ @touchcancel.stop="onTouchEnd">
4
15
  <view class="barrage-type-tag">
5
16
  {{ typeTag }}
6
17
  </view>
@@ -10,16 +21,17 @@
10
21
  </template>
11
22
 
12
23
  <script setup lang="ts">
13
- import { computed } from 'vue';
24
+ import { computed, ref } from 'vue';
14
25
 
15
26
  const props = defineProps<{
16
27
  text: string;
17
28
  type: string;
18
29
  top: number;
19
30
  duration: number;
20
- delay?: number; // 新增延迟属性,毫秒单位
31
+ delay?: number; // 毫秒单位
21
32
  maxLength?: number;
22
33
  color?: string;
34
+ allowDrag?: boolean; // 是否允许拖动
23
35
  }>();
24
36
 
25
37
  const emit = defineEmits<{
@@ -38,11 +50,53 @@ const itemStyle = computed(() => ({
38
50
  '--barrage-delay': `${props.delay || 0}ms`,
39
51
  '--barrage-max-width': props.maxLength ? 'none' : '300px',
40
52
  color: props.color || 'inherit',
53
+ 'animation-play-state': isPaused.value ? 'paused' : 'running', // 支持触控暂停
41
54
  }));
42
55
 
43
56
  function onAnimationEnd() {
44
57
  emit('remove');
45
58
  }
59
+
60
+ // 触屏滑动/鼠标拖拽时暂停动画并支持拖拽
61
+ const isPaused = ref(false);
62
+ const transformOffset = ref(0);
63
+ let startX = 0;
64
+ let lastOffset = 0;
65
+
66
+ function getClientX(e: TouchEvent | MouseEvent) {
67
+ if (
68
+ typeof (e as TouchEvent).touches !== 'undefined' &&
69
+ (e as TouchEvent).touches.length > 0
70
+ ) {
71
+ return (
72
+ (e as TouchEvent).touches[0].pageX || (e as TouchEvent).touches[0].clientX
73
+ );
74
+ }
75
+ return (e as MouseEvent).pageX || (e as MouseEvent).clientX || 0;
76
+ }
77
+
78
+ function onTouchStart(e: TouchEvent | MouseEvent) {
79
+ isPaused.value = true;
80
+ if (props.allowDrag === false) return; // 不允许拖动时直接返回
81
+ startX = getClientX(e);
82
+ lastOffset = transformOffset.value;
83
+ }
84
+
85
+ function onTouchMove(e: TouchEvent | MouseEvent) {
86
+ if (props.allowDrag === false || !isPaused.value) return;
87
+ const currentX = getClientX(e);
88
+ if (currentX === 0) return; // 防止无效的移动触发跳动
89
+ const deltaX = currentX - startX;
90
+ transformOffset.value = lastOffset + deltaX;
91
+ }
92
+
93
+ function onTouchEnd() {
94
+ isPaused.value = false;
95
+ }
96
+
97
+ const contentStyle = computed(() => ({
98
+ transform: `translateX(${transformOffset.value}px)`,
99
+ }));
46
100
  </script>
47
101
 
48
102
  <style scoped>
@@ -55,12 +109,15 @@ function onAnimationEnd() {
55
109
  z-index: 10001;
56
110
  display: flex;
57
111
  will-change: transform;
58
- animation: barrage-move var(--barrage-duration) linear var(--barrage-delay)
59
- forwards;
112
+ animation-name: barrage-move;
113
+ animation-duration: var(--barrage-duration);
114
+ animation-timing-function: linear;
115
+ animation-delay: var(--barrage-delay);
116
+ animation-fill-mode: forwards;
60
117
  }
61
118
 
62
119
  .barrage-item:hover {
63
- animation-play-state: paused;
120
+ animation-play-state: paused !important;
64
121
  z-index: 20000;
65
122
  }
66
123
 
@@ -127,11 +184,11 @@ function onAnimationEnd() {
127
184
  padding: 2px 4px;
128
185
  background: rgb(0 0 0 / 5%);
129
186
  border-radius: 4px;
187
+ flex-shrink: 0; /* 保证标签不被压缩 */
130
188
  }
131
189
 
190
+ /* 移除截断,使其完整展示,通过滑动外面来查看 */
132
191
  .barrage-text {
133
- max-width: var(--barrage-max-width, 300px);
134
- overflow: hidden;
135
- text-overflow: ellipsis;
192
+ white-space: nowrap;
136
193
  }
137
194
  </style>
@@ -12,6 +12,7 @@
12
12
  :duration="item.duration"
13
13
  :delay="item.delay"
14
14
  :maxLength="props.maxLength"
15
+ :allowDrag="props.allowDrag"
15
16
  @remove="removeItem(item.id)" />
16
17
  </view>
17
18
  </template>
@@ -30,6 +31,7 @@ const props = withDefaults(
30
31
  maxLength?: number;
31
32
  visible?: boolean;
32
33
  zIndex?: number;
34
+ allowDrag?: boolean;
33
35
  }>(),
34
36
  {
35
37
  maxTracks: 10,
@@ -39,6 +41,7 @@ const props = withDefaults(
39
41
  maxLength: 100,
40
42
  visible: true,
41
43
  zIndex: 10000,
44
+ allowDrag: true,
42
45
  },
43
46
  );
44
47
 
@@ -67,8 +67,8 @@ const handleError = (err: any, info?: string) => {
67
67
  err?.stack || err?.message || err?.toString() || 'Unknown Error';
68
68
 
69
69
  // 手动打印到控制台
70
- console.error(`[ErrorBoundary]`, err);
71
- if (info) console.warn(`[ErrorBoundary] Info: ${info}`);
70
+ console.error('[ErrorBoundary]', err);
71
+ if (info) console.warn('[ErrorBoundary] Info: ' + info);
72
72
 
73
73
  // 强制下一帧显示
74
74
  nextTick(() => {
@@ -77,8 +77,8 @@ const handleError = (err: any, info?: string) => {
77
77
  };
78
78
 
79
79
  onMounted(() => {
80
- // #ifndef H5
81
80
  // 在非 H5 环境(小程序、APP),由于 onErrorCaptured 可能失效,启用全局监听作为核心捕获方案
81
+ // #ifndef H5
82
82
  const mountedPath = getCurrentPagePath();
83
83
  uni.$on(DEV_ERROR_BOUNDARY_TRIGGER, (data: any) => {
84
84
  const currentPath = getCurrentPagePath();
@@ -148,7 +148,11 @@ defineExpose({
148
148
  width: 400rpx;
149
149
  height: 400rpx;
150
150
  border-radius: 50%;
151
- background: radial-gradient(circle, rgb(255 77 79 / 5%) 0%, transparent 70%);
151
+ background: radial-gradient(
152
+ circle,
153
+ rgb(255 77 79 / 5%) 0%,
154
+ transparent 70%
155
+ );
152
156
  top: -100rpx;
153
157
  right: -100rpx;
154
158
  z-index: 1;
@@ -159,7 +163,11 @@ defineExpose({
159
163
  width: 300rpx;
160
164
  height: 300rpx;
161
165
  border-radius: 50%;
162
- background: radial-gradient(circle, rgb(24 144 255 / 5%) 0%, transparent 70%);
166
+ background: radial-gradient(
167
+ circle,
168
+ rgb(24 144 255 / 5%) 0%,
169
+ transparent 70%
170
+ );
163
171
  bottom: -50rpx;
164
172
  left: -50rpx;
165
173
  z-index: 1;