vite-uni-dev-tool 1.1.0 → 1.2.0

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 (135) hide show
  1. package/README.md +8 -0
  2. package/dist/const.cjs +1 -1
  3. package/dist/const.d.ts +1 -0
  4. package/dist/const.d.ts.map +1 -1
  5. package/dist/const.js +1 -1
  6. package/dist/core.d.ts.map +1 -1
  7. package/dist/core.js +2 -2
  8. package/dist/i18n/locales/en.cjs +1 -1
  9. package/dist/i18n/locales/en.d.ts +5 -0
  10. package/dist/i18n/locales/en.d.ts.map +1 -1
  11. package/dist/i18n/locales/en.js +1 -1
  12. package/dist/i18n/locales/zh-Hans.cjs +1 -1
  13. package/dist/i18n/locales/zh-Hans.d.ts +5 -0
  14. package/dist/i18n/locales/zh-Hans.d.ts.map +1 -1
  15. package/dist/i18n/locales/zh-Hans.js +1 -1
  16. package/dist/modules/devIntercept/index.cjs +9 -9
  17. package/dist/modules/devIntercept/index.d.ts +1 -1
  18. package/dist/modules/devIntercept/index.d.ts.map +1 -1
  19. package/dist/modules/devIntercept/index.js +9 -9
  20. package/dist/modules/devStore/index.cjs +1 -1
  21. package/dist/modules/devStore/index.d.ts.map +1 -1
  22. package/dist/modules/devStore/index.js +1 -1
  23. package/dist/plugins/uniDevTool/transform/transformMain.cjs +3 -3
  24. package/dist/plugins/uniDevTool/transform/transformMain.d.ts +2 -1
  25. package/dist/plugins/uniDevTool/transform/transformMain.d.ts.map +1 -1
  26. package/dist/plugins/uniDevTool/transform/transformMain.js +3 -3
  27. package/dist/plugins/uniDevTool/transform/transformVue.cjs +31 -25
  28. package/dist/plugins/uniDevTool/transform/transformVue.d.ts +2 -1
  29. package/dist/plugins/uniDevTool/transform/transformVue.d.ts.map +1 -1
  30. package/dist/plugins/uniDevTool/transform/transformVue.js +30 -24
  31. package/dist/plugins/uniDevTool/uniDevTool.cjs +3 -3
  32. package/dist/plugins/uniDevTool/uniDevTool.d.ts +3 -1
  33. package/dist/plugins/uniDevTool/uniDevTool.d.ts.map +1 -1
  34. package/dist/plugins/uniDevTool/uniDevTool.js +3 -3
  35. package/dist/type.d.ts +3 -0
  36. package/dist/type.d.ts.map +1 -1
  37. package/dist/v3/DevTool/components/BluetoothList/BluetoothItem.vue +199 -199
  38. package/dist/v3/DevTool/components/BluetoothList/BluetoothTool.vue +730 -730
  39. package/dist/v3/DevTool/components/BluetoothList/index.vue +167 -167
  40. package/dist/v3/DevTool/components/CaptureScreen/index.vue +109 -109
  41. package/dist/v3/DevTool/components/ConsoleList/ConsoleItem.vue +230 -225
  42. package/dist/v3/DevTool/components/ConsoleList/RunJSInput.vue +247 -247
  43. package/dist/v3/DevTool/components/ConsoleList/index.vue +171 -171
  44. package/dist/v3/DevTool/components/ConsoleList/staticTips.ts +1145 -1145
  45. package/dist/v3/DevTool/components/DevToolTitle/index.vue +24 -24
  46. package/dist/v3/DevTool/components/DevToolWindow/DevToolOverlay.vue +197 -197
  47. package/dist/v3/DevTool/components/DevToolWindow/hooks/dataUtils.ts +48 -48
  48. package/dist/v3/DevTool/components/DevToolWindow/hooks/useDevToolData.ts +387 -387
  49. package/dist/v3/DevTool/components/DevToolWindow/hooks/useDevToolHandlers.ts +629 -629
  50. package/dist/v3/DevTool/components/DevToolWindow/hooks/useDevToolOverlay.ts +201 -197
  51. package/dist/v3/DevTool/components/ElEvent/ElEventItem.vue +105 -105
  52. package/dist/v3/DevTool/components/ElEvent/index.vue +106 -106
  53. package/dist/v3/DevTool/components/Instance/components/InstanceTreeNode.vue +265 -265
  54. package/dist/v3/DevTool/components/Instance/flatten.ts +226 -226
  55. package/dist/v3/DevTool/components/Instance/index.vue +94 -94
  56. package/dist/v3/DevTool/components/Instance/registry.ts +49 -49
  57. package/dist/v3/DevTool/components/Instance/transformTree.ts +375 -375
  58. package/dist/v3/DevTool/components/Instance/transformTreeCtx.ts +268 -268
  59. package/dist/v3/DevTool/components/Instance/typing.d.ts +43 -43
  60. package/dist/v3/DevTool/components/InstanceDetail/index.vue +485 -485
  61. package/dist/v3/DevTool/components/JsonDetail/index.vue +70 -70
  62. package/dist/v3/DevTool/components/NFCList/NFCItem.vue +112 -112
  63. package/dist/v3/DevTool/components/NFCList/NFCTool.vue +454 -454
  64. package/dist/v3/DevTool/components/NFCList/const.ts +56 -56
  65. package/dist/v3/DevTool/components/NFCList/index.vue +94 -94
  66. package/dist/v3/DevTool/components/NetworkList/InterceptConfig.vue +624 -624
  67. package/dist/v3/DevTool/components/NetworkList/InterceptItem.vue +140 -140
  68. package/dist/v3/DevTool/components/NetworkList/NetworkDetail.vue +287 -287
  69. package/dist/v3/DevTool/components/NetworkList/NetworkIntercept.vue +88 -88
  70. package/dist/v3/DevTool/components/NetworkList/NetworkItem.vue +163 -163
  71. package/dist/v3/DevTool/components/NetworkList/NetworkSend.vue +589 -589
  72. package/dist/v3/DevTool/components/NetworkList/const.ts +4 -4
  73. package/dist/v3/DevTool/components/NetworkList/hooks/useNetworkForm.ts +86 -86
  74. package/dist/v3/DevTool/components/NetworkList/index.vue +160 -160
  75. package/dist/v3/DevTool/components/NetworkList/utils.ts +101 -101
  76. package/dist/v3/DevTool/components/Performance/index.vue +498 -498
  77. package/dist/v3/DevTool/components/Performance/modules/PerformanceMetrics.vue +153 -153
  78. package/dist/v3/DevTool/components/Performance/modules/usePerformanceChart.ts +460 -460
  79. package/dist/v3/DevTool/components/Performance/modules/usePerformanceData.ts +258 -258
  80. package/dist/v3/DevTool/components/PiniaList/index.vue +93 -93
  81. package/dist/v3/DevTool/components/RunJS/index.vue +148 -148
  82. package/dist/v3/DevTool/components/ScanCodeList/ScanCodeItem.vue +97 -97
  83. package/dist/v3/DevTool/components/ScanCodeList/index.vue +100 -100
  84. package/dist/v3/DevTool/components/SettingButton/index.vue +45 -45
  85. package/dist/v3/DevTool/components/SettingList/index.vue +218 -218
  86. package/dist/v3/DevTool/components/SettingList/modules/SettingBarrage.vue +304 -304
  87. package/dist/v3/DevTool/components/SettingList/modules/SettingDevTool.vue +212 -212
  88. package/dist/v3/DevTool/components/SettingList/modules/SettingInfo.vue +157 -157
  89. package/dist/v3/DevTool/components/SettingList/modules/SettingLanguage.vue +74 -74
  90. package/dist/v3/DevTool/components/SettingList/modules/SettingLog.vue +230 -230
  91. package/dist/v3/DevTool/components/SettingList/typing.d.ts +2 -2
  92. package/dist/v3/DevTool/components/SourceCode/Line.vue +127 -127
  93. package/dist/v3/DevTool/components/SourceCode/parseCode.ts +609 -609
  94. package/dist/v3/DevTool/components/StorageList/index.vue +174 -174
  95. package/dist/v3/DevTool/components/TransferList/TransferDetail.vue +268 -268
  96. package/dist/v3/DevTool/components/VuexList/index.vue +84 -84
  97. package/dist/v3/DevTool/index.vue +1 -0
  98. package/dist/v3/components/AppTransition/index.vue +176 -176
  99. package/dist/v3/components/AutoSizer/index.vue +192 -192
  100. package/dist/v3/components/AutoSizer/index1.vue +184 -184
  101. package/dist/v3/components/AutoSizer/utils.ts +49 -49
  102. package/dist/v3/components/Barrage/BarrageItem.vue +137 -137
  103. package/dist/v3/components/Barrage/index.vue +202 -202
  104. package/dist/v3/components/CircularButton/index.vue +84 -84
  105. package/dist/v3/components/CustomSwiper/CustomSwiperItem.vue +49 -49
  106. package/dist/v3/components/CustomSwiper/index.vue +104 -104
  107. package/dist/v3/components/DevErrorBoundary/index.vue +380 -0
  108. package/dist/v3/components/Empty/index.vue +29 -29
  109. package/dist/v3/components/FilterSelect/index.vue +179 -179
  110. package/dist/v3/components/JsonPretty/components/Brackets/index.vue +27 -27
  111. package/dist/v3/components/JsonPretty/components/Carets/index.vue +59 -59
  112. package/dist/v3/components/JsonPretty/components/CheckController/index.vue +136 -136
  113. package/dist/v3/components/JsonPretty/components/TreeNode/index.vue +387 -387
  114. package/dist/v3/components/JsonPretty/hooks/useClipboard.ts +21 -21
  115. package/dist/v3/components/JsonPretty/hooks/useError.ts +21 -21
  116. package/dist/v3/components/JsonPretty/type.ts +127 -127
  117. package/dist/v3/components/JsonPretty/utils/index.ts +169 -169
  118. package/dist/v3/components/MovableContainer/index.vue +8 -4
  119. package/dist/v3/components/Pick/index.vue +322 -322
  120. package/dist/v3/components/Tag/index.vue +113 -113
  121. package/dist/v3/components/VirtualList/AutoSize.vue +40 -40
  122. package/dist/v3/components/VirtualList/index.vue +416 -416
  123. package/dist/v3/hooks/useBluetooth/index.ts +561 -561
  124. package/dist/v3/hooks/useContainerStyle.ts +153 -153
  125. package/dist/v3/hooks/useNFC/index.ts +107 -107
  126. package/dist/v3/hooks/useNFC/typing.d.ts +396 -396
  127. package/dist/v3/hooks/useNFC/useNFCAndroid.ts +966 -966
  128. package/dist/v3/hooks/useNFC/useNFCMpWeiXin.ts +812 -812
  129. package/dist/v3/hooks/useNFC/utils.ts +754 -754
  130. package/dist/v3/hooks/useRequest/index.ts +586 -586
  131. package/dist/v3/hooks/useRequest/utils.ts +267 -267
  132. package/dist/v3/hooks/useScanCode/index.ts +206 -206
  133. package/dist/v3/hooks/useWebsocket/index.ts +253 -253
  134. package/dist/v3/styles/theme.ts +12 -12
  135. package/package.json +9 -1
@@ -1,498 +1,498 @@
1
- <template>
2
- <view class="performance-content">
3
- <view class="performance-control">
4
- <DevToolTitle>{{ t('performance.title') }}</DevToolTitle>
5
- </view>
6
- <view class="performance-item">
7
- <!-- 图表容器 -->
8
- <canvas
9
- canvas-id="fpsChartTab"
10
- class="fps-chart-container"
11
- :style="{ backgroundColor: chartBgColor }"
12
- id="fpsChartTab"></canvas>
13
- <PerformanceMetrics
14
- :is-tab="true"
15
- :fps="fps"
16
- :cpuLoad="cpuLoad"
17
- :memory="memory"
18
- :showFps="showFps"
19
- :showCpu="showCpu"
20
- :showMemory="showMemory" />
21
-
22
- <view class="performance-item-content">
23
- <!-- 平台限制提示 -->
24
- <view
25
- class="performance-tips"
26
- style="
27
- color: #e6a23c;
28
- background: rgb(230 162 60 / 10%);
29
- padding: 8px;
30
- border-radius: 4px;
31
- margin-bottom: 12px;
32
- font-size: 11px;
33
- "
34
- v-if="!isH5">
35
- {{ t('performance.platformTip') }}
36
- </view>
37
- <DevToolTitle>{{ t('performance.settings') }}</DevToolTitle>
38
- <view class="performance-row">
39
- <view>{{ t('performance.enable') }}</view>
40
- <switch
41
- :checked="performanceMonitorEnabled"
42
- @change="toggleMonitor"
43
- :color="themeColor"
44
- style="transform: scale(0.7)" />
45
- </view>
46
- <view class="performance-tips">
47
- {{ t('performance.enableTip') }}
48
- </view>
49
- <view class="performance-row">
50
- <view>{{ t('performance.widget') }}</view>
51
- <switch
52
- :disabled="!performanceMonitorEnabled"
53
- :checked="performanceVisible"
54
- @change="togglePerformanceVisible"
55
- :color="themeColor"
56
- style="transform: scale(0.7)" />
57
- </view>
58
- <view class="performance-tips">
59
- {{ t('performance.widgetTip') }}
60
- </view>
61
- <view class="performance-row">
62
- <view>{{ t('performance.fps') }}</view>
63
- <switch
64
- :disabled="!performanceMonitorEnabled"
65
- :checked="showFps"
66
- @change="toggleFps"
67
- :color="themeColor"
68
- style="transform: scale(0.7)" />
69
- </view>
70
- <view class="performance-tips">
71
- {{ t('performance.fpsTip') }}
72
- </view>
73
- <view class="performance-row">
74
- <view>{{ t('performance.cpu') }}</view>
75
- <switch
76
- :disabled="!performanceMonitorEnabled"
77
- :checked="showCpu"
78
- @change="toggleCpu"
79
- :color="themeColor"
80
- style="transform: scale(0.7)" />
81
- </view>
82
- <view class="performance-tips">
83
- {{ t('performance.cpuTip') }}
84
- </view>
85
- <view class="performance-row">
86
- <view>{{ t('performance.memory') }}</view>
87
- <switch
88
- :disabled="!performanceMonitorEnabled"
89
- :checked="showMemory"
90
- @change="toggleMemory"
91
- :color="themeColor"
92
- style="transform: scale(0.7)" />
93
- </view>
94
- <view class="performance-tips">
95
- {{ t('performance.memoryTip') }}
96
- </view>
97
-
98
- <!-- CPU Profile / Long Tasks List -->
99
- <view
100
- class="performance-item-content"
101
- style="margin-top: 16px"
102
- v-if="longTasksHistory.length > 0">
103
- <DevToolTitle>{{ t('performance.longTaskTitle') }}</DevToolTitle>
104
- <view class="performance-tips">
105
- {{ t('performance.longTaskTip') }}
106
- </view>
107
- <view class="long-tasks-list">
108
- <view
109
- v-for="(task, index) in longTasksHistory.slice().reverse()"
110
- :key="index"
111
- class="long-task-item">
112
- <view class="task-info">
113
- <text
114
- class="task-type"
115
- :class="`type-${task.type?.toLowerCase()}`">
116
- {{
117
- task.type === 'Logic'
118
- ? t('performance.logic')
119
- : t('performance.ui')
120
- }}
121
- </text>
122
- <text class="task-time">{{ formatTaskTime(task.ts) }}</text>
123
- </view>
124
- <view
125
- class="task-duration"
126
- :class="getDurationClass(task.duration)">
127
- {{ task.duration }}ms
128
- </view>
129
- </view>
130
- </view>
131
- </view>
132
- </view>
133
- </view>
134
- </view>
135
- </template>
136
-
137
- <script setup lang="ts">
138
- import { ref, computed, onMounted, onUnmounted, getCurrentInstance } from 'vue';
139
- import {
140
- getDevToolInfo,
141
- setDevToolInfo,
142
- } from '../../../../modules/devToolInfo';
143
- import PerformanceMetrics from './modules/PerformanceMetrics.vue';
144
- import { usePerformanceData } from './modules/usePerformanceData';
145
- import { usePerformanceChart } from './modules/usePerformanceChart';
146
- import { MSG_TYPE, DEV_CORE_MESSAGE } from '../../../../const';
147
- import DevToolTitle from '../DevToolTitle/index.vue';
148
- import { useI18n } from '../../../../i18n';
149
- import { getThemeMainColor } from '../../../styles/theme';
150
- const { t } = useI18n();
151
- const themeColor = computed(() => getThemeMainColor(props.theme));
152
-
153
- // 无需声明 renderScript
154
-
155
- const props = withDefaults(
156
- defineProps<{
157
- mode?: 'tab';
158
- zIndex?: number;
159
- customStyle?: Record<string, any>;
160
- contentHeight?: number;
161
- theme?: string;
162
- }>(),
163
- {
164
- zIndex: 1000,
165
- theme: 'light',
166
- },
167
- );
168
-
169
- const showFps = ref(true);
170
- const showCpu = ref(true);
171
- const showMemory = ref(true);
172
- const performanceVisible = ref(false);
173
- const isH5 = ref(false);
174
-
175
- function loadSettings() {
176
- // #ifdef H5
177
- isH5.value = true;
178
- // #endif
179
-
180
- const info = getDevToolInfo();
181
- if (info && info.performanceSettings) {
182
- showFps.value = info.performanceSettings.showFps ?? true;
183
- showCpu.value = info.performanceSettings.showCpu ?? true;
184
- showMemory.value = info.performanceSettings.showMemory ?? true;
185
- performanceMonitorEnabled.value =
186
- info.performanceSettings.enableMonitor ?? false;
187
- }
188
- if (info && info.performanceVisible !== undefined) {
189
- performanceVisible.value = info.performanceVisible;
190
- }
191
- }
192
-
193
- function saveSettings() {
194
- setDevToolInfo({
195
- performanceSettings: {
196
- showFps: showFps.value,
197
- showCpu: showCpu.value,
198
- showMemory: showMemory.value,
199
- enableMonitor: performanceMonitorEnabled.value,
200
- },
201
- performanceVisible: performanceVisible.value,
202
- });
203
- }
204
-
205
- function toggleFps(e: any) {
206
- showFps.value = e.detail.value;
207
- saveSettings();
208
- }
209
-
210
- function toggleCpu(e: any) {
211
- showCpu.value = e.detail.value;
212
- saveSettings();
213
- }
214
-
215
- function toggleMemory(e: any) {
216
- showMemory.value = e.detail.value;
217
- saveSettings();
218
- }
219
-
220
- function togglePerformanceVisible(e: any) {
221
- performanceVisible.value = e.detail.value;
222
-
223
- // 如果关闭悬浮窗,同时关闭监测功能
224
- if (!performanceVisible.value && performanceMonitorEnabled.value) {
225
- performanceMonitorEnabled.value = false;
226
- performanceData.stopHeartbeat();
227
- performanceChart.stopRenderLoop();
228
- // 通知 PerformanceWidget 停止监测
229
- uni.$emit(MSG_TYPE.PERF_MONITOR, false);
230
- }
231
-
232
- saveSettings();
233
- // 通知 DevTool 组件更新性能弹窗可见性
234
- uni.$emit(DEV_CORE_MESSAGE, {
235
- type: MSG_TYPE.PERF_VISIBLE,
236
- data: performanceVisible.value,
237
- });
238
- }
239
-
240
- function toggleMonitor(e: any) {
241
- performanceMonitorEnabled.value = e.detail.value;
242
- if (!performanceMonitorEnabled.value) {
243
- performanceVisible.value = false;
244
- }
245
- saveSettings();
246
- uni.$emit(MSG_TYPE.PERF_MONITOR, performanceMonitorEnabled.value);
247
- if (performanceMonitorEnabled.value) {
248
- performanceData.initData(
249
- Math.ceil(performanceChart.canvasWidth.value / stepSize) + 4,
250
- );
251
- performanceData.startHeartbeat();
252
- performanceChart.startRenderLoop();
253
- uni.$emit(DEV_CORE_MESSAGE, {
254
- type: MSG_TYPE.PERF_VISIBLE,
255
- data: performanceVisible.value,
256
- });
257
- } else {
258
- performanceData.stopHeartbeat();
259
- performanceChart.stopRenderLoop();
260
- uni.$emit(DEV_CORE_MESSAGE, {
261
- type: MSG_TYPE.PERF_VISIBLE,
262
- data: false,
263
- });
264
- }
265
- }
266
-
267
- // 根据主题计算颜色
268
- const isDark = computed(() => {
269
- return props.theme === 'dark';
270
- });
271
- const chartBgColor = computed(() =>
272
- isDark.value ? 'rgba(255, 255, 255, 0.08)' : 'rgba(0, 0, 0, 0.05)',
273
- );
274
-
275
- const instance = getCurrentInstance();
276
- const stepSize = 5;
277
-
278
- // Hooks
279
- const performanceData = usePerformanceData();
280
- const { fps, cpuLoad, memory, performanceMonitorEnabled, longTasksHistory } =
281
- performanceData;
282
-
283
- const performanceChart = usePerformanceChart({
284
- theme: props.theme,
285
- isDark,
286
- instance,
287
- canvasIdFn: () => 'fpsChartTab',
288
- stepSize,
289
- data: performanceData,
290
- config: {
291
- showFps,
292
- showCpu,
293
- showMemory,
294
- },
295
- props: { mode: 'tab' },
296
- });
297
-
298
- function formatTaskTime(ts: number) {
299
- const date = new Date(ts);
300
- return `${date.getHours().toString().padStart(2, '0')}:${date
301
- .getMinutes()
302
- .toString()
303
- .padStart(2, '0')}:${date.getSeconds().toString().padStart(2, '0')}.${date
304
- .getMilliseconds()
305
- .toString()
306
- .padStart(3, '0')}`;
307
- }
308
-
309
- function getDurationClass(duration: number) {
310
- if (duration > 200) return 'task-danger';
311
- if (duration > 100) return 'task-warning';
312
- return '';
313
- }
314
-
315
- onMounted(() => {
316
- loadSettings();
317
-
318
- performanceChart.initCanvas(() => {
319
- performanceData.initData(
320
- Math.ceil(performanceChart.canvasWidth.value / stepSize) + 4,
321
- );
322
- // 只有在监控开启且窗口可见时,才启动 Tab 的渲染循环
323
- if (performanceMonitorEnabled.value) {
324
- performanceChart.startRenderLoop();
325
- }
326
- });
327
-
328
- // 如果监测状态是开启的,恢复执行
329
- if (performanceMonitorEnabled.value) {
330
- performanceData.startHeartbeat();
331
- // @ts-ignore
332
- if (performanceData.startLogicMonitor) {
333
- // @ts-ignore
334
- performanceData.startLogicMonitor();
335
- }
336
- }
337
-
338
- // 监听核心模块消息
339
- uni.$on(DEV_CORE_MESSAGE, handleCoreMessage);
340
- // 监听监测状态变化(来自 PerformanceWidget)
341
- uni.$on(MSG_TYPE.PERF_MONITOR, onMonitorStateChange);
342
- });
343
-
344
- // 监测状态变化处理(来自 PerformanceWidget 的通知)
345
- function onMonitorStateChange(enabled: boolean) {
346
- performanceMonitorEnabled.value = enabled;
347
- if (!enabled) {
348
- performanceData.stopHeartbeat();
349
- performanceChart.stopRenderLoop();
350
- } else {
351
- // 补全开启逻辑
352
- performanceData.startHeartbeat();
353
- // 只有主窗口可见时才恢复绘制
354
- const { devToolWindowVisible = false } = getDevToolInfo();
355
- if (devToolWindowVisible) {
356
- performanceChart.startRenderLoop();
357
- }
358
- }
359
- }
360
-
361
- // 处理核心模块消息
362
- function handleCoreMessage(msg: string | { type: string; data: any }) {
363
- let type: string | undefined;
364
- let data: any;
365
- try {
366
- const payload = typeof msg === 'string' ? JSON.parse(msg) : msg;
367
- type = payload.type;
368
- data = payload.data;
369
- } catch (_e) {
370
- return;
371
- }
372
-
373
- if (type === MSG_TYPE.WINDOW_VISIBLE) {
374
- onWindowVisibleChange(data);
375
- }
376
- }
377
-
378
- // 窗口可见性变化处理
379
- function onWindowVisibleChange(visible: boolean) {
380
- if (!visible) {
381
- // 窗口关闭时,仅停止 Tab 页面的渲染绘制,节省性能
382
- performanceChart.stopRenderLoop();
383
- // 逻辑层监控和心跳不再随窗口关闭而停止(只要 performanceMonitorEnabled 为 true)
384
- } else {
385
- // 窗口打开时,如果监控开启了,恢复 Tab 的渲染绘制
386
- if (performanceMonitorEnabled.value) {
387
- performanceChart.startRenderLoop();
388
- }
389
- }
390
- }
391
-
392
- onUnmounted(() => {
393
- performanceChart.resetCanvas();
394
- uni.$off(DEV_CORE_MESSAGE, handleCoreMessage);
395
- uni.$off(MSG_TYPE.PERF_MONITOR, onMonitorStateChange);
396
- });
397
- </script>
398
-
399
- <style scoped>
400
- .performance-content {
401
- height: 100%;
402
- overflow: auto;
403
- font-size: var(--dev-tool-base-font-size);
404
- }
405
-
406
- .performance-control {
407
- padding: 0 16px;
408
- }
409
-
410
- .performance-item {
411
- padding: 0 16px;
412
- box-sizing: border-box;
413
- }
414
-
415
- .performance-row {
416
- display: flex;
417
- align-items: center;
418
- justify-content: space-between;
419
- min-height: 18px;
420
- }
421
-
422
- .fps-chart-container {
423
- width: 100%;
424
- flex: 1;
425
- min-height: 50px;
426
- margin-bottom: 4px;
427
- border-radius: 4px;
428
- overflow: hidden;
429
- height: 300px;
430
- }
431
-
432
- .performance-tips {
433
- color: #616161;
434
- font-size: var(--dev-tool-tips-font-size);
435
- margin-bottom: 8px;
436
- }
437
-
438
- .long-tasks-list {
439
- background: var(--dev-tool-bg2-color);
440
- border-radius: 4px;
441
- padding: 8px;
442
- max-height: 200px;
443
- overflow-y: auto;
444
- }
445
-
446
- .long-task-item {
447
- display: flex;
448
- justify-content: space-between;
449
- align-items: center;
450
- padding: 4px 0;
451
- border-bottom: 1px solid var(--dev-tool-border-color);
452
- font-family: monospace;
453
- }
454
-
455
- .long-task-item:last-child {
456
- border-bottom: none;
457
- }
458
-
459
- .task-info {
460
- display: flex;
461
- align-items: center;
462
- font-size: 11px;
463
- }
464
-
465
- .task-type {
466
- font-size: 10px;
467
- padding: 0 4px;
468
- border-radius: 2px;
469
- color: #fff;
470
- background: #909399;
471
- margin-right: 6px;
472
- line-height: 1.4;
473
- }
474
-
475
- .type-logic {
476
- background: #9254de;
477
- }
478
-
479
- .type-ui {
480
- background: #67c23a;
481
- }
482
-
483
- .task-time {
484
- color: #888;
485
- }
486
-
487
- .task-duration {
488
- font-weight: bold;
489
- }
490
-
491
- .task-warning {
492
- color: #e6a23c;
493
- }
494
-
495
- .task-danger {
496
- color: #f56c6c;
497
- }
498
- </style>
1
+ <template>
2
+ <view class="performance-content">
3
+ <view class="performance-control">
4
+ <DevToolTitle>{{ t('performance.title') }}</DevToolTitle>
5
+ </view>
6
+ <view class="performance-item">
7
+ <!-- 图表容器 -->
8
+ <canvas
9
+ canvas-id="fpsChartTab"
10
+ class="fps-chart-container"
11
+ :style="{ backgroundColor: chartBgColor }"
12
+ id="fpsChartTab"></canvas>
13
+ <PerformanceMetrics
14
+ :is-tab="true"
15
+ :fps="fps"
16
+ :cpuLoad="cpuLoad"
17
+ :memory="memory"
18
+ :showFps="showFps"
19
+ :showCpu="showCpu"
20
+ :showMemory="showMemory" />
21
+
22
+ <view class="performance-item-content">
23
+ <!-- 平台限制提示 -->
24
+ <view
25
+ class="performance-tips"
26
+ style="
27
+ color: #e6a23c;
28
+ background: rgb(230 162 60 / 10%);
29
+ padding: 8px;
30
+ border-radius: 4px;
31
+ margin-bottom: 12px;
32
+ font-size: 11px;
33
+ "
34
+ v-if="!isH5">
35
+ {{ t('performance.platformTip') }}
36
+ </view>
37
+ <DevToolTitle>{{ t('performance.settings') }}</DevToolTitle>
38
+ <view class="performance-row">
39
+ <view>{{ t('performance.enable') }}</view>
40
+ <switch
41
+ :checked="performanceMonitorEnabled"
42
+ @change="toggleMonitor"
43
+ :color="themeColor"
44
+ style="transform: scale(0.7)" />
45
+ </view>
46
+ <view class="performance-tips">
47
+ {{ t('performance.enableTip') }}
48
+ </view>
49
+ <view class="performance-row">
50
+ <view>{{ t('performance.widget') }}</view>
51
+ <switch
52
+ :disabled="!performanceMonitorEnabled"
53
+ :checked="performanceVisible"
54
+ @change="togglePerformanceVisible"
55
+ :color="themeColor"
56
+ style="transform: scale(0.7)" />
57
+ </view>
58
+ <view class="performance-tips">
59
+ {{ t('performance.widgetTip') }}
60
+ </view>
61
+ <view class="performance-row">
62
+ <view>{{ t('performance.fps') }}</view>
63
+ <switch
64
+ :disabled="!performanceMonitorEnabled"
65
+ :checked="showFps"
66
+ @change="toggleFps"
67
+ :color="themeColor"
68
+ style="transform: scale(0.7)" />
69
+ </view>
70
+ <view class="performance-tips">
71
+ {{ t('performance.fpsTip') }}
72
+ </view>
73
+ <view class="performance-row">
74
+ <view>{{ t('performance.cpu') }}</view>
75
+ <switch
76
+ :disabled="!performanceMonitorEnabled"
77
+ :checked="showCpu"
78
+ @change="toggleCpu"
79
+ :color="themeColor"
80
+ style="transform: scale(0.7)" />
81
+ </view>
82
+ <view class="performance-tips">
83
+ {{ t('performance.cpuTip') }}
84
+ </view>
85
+ <view class="performance-row">
86
+ <view>{{ t('performance.memory') }}</view>
87
+ <switch
88
+ :disabled="!performanceMonitorEnabled"
89
+ :checked="showMemory"
90
+ @change="toggleMemory"
91
+ :color="themeColor"
92
+ style="transform: scale(0.7)" />
93
+ </view>
94
+ <view class="performance-tips">
95
+ {{ t('performance.memoryTip') }}
96
+ </view>
97
+
98
+ <!-- CPU Profile / Long Tasks List -->
99
+ <view
100
+ class="performance-item-content"
101
+ style="margin-top: 16px"
102
+ v-if="longTasksHistory.length > 0">
103
+ <DevToolTitle>{{ t('performance.longTaskTitle') }}</DevToolTitle>
104
+ <view class="performance-tips">
105
+ {{ t('performance.longTaskTip') }}
106
+ </view>
107
+ <view class="long-tasks-list">
108
+ <view
109
+ v-for="(task, index) in longTasksHistory.slice().reverse()"
110
+ :key="index"
111
+ class="long-task-item">
112
+ <view class="task-info">
113
+ <text
114
+ class="task-type"
115
+ :class="`type-${task.type?.toLowerCase()}`">
116
+ {{
117
+ task.type === 'Logic'
118
+ ? t('performance.logic')
119
+ : t('performance.ui')
120
+ }}
121
+ </text>
122
+ <text class="task-time">{{ formatTaskTime(task.ts) }}</text>
123
+ </view>
124
+ <view
125
+ class="task-duration"
126
+ :class="getDurationClass(task.duration)">
127
+ {{ task.duration }}ms
128
+ </view>
129
+ </view>
130
+ </view>
131
+ </view>
132
+ </view>
133
+ </view>
134
+ </view>
135
+ </template>
136
+
137
+ <script setup lang="ts">
138
+ import { ref, computed, onMounted, onUnmounted, getCurrentInstance } from 'vue';
139
+ import {
140
+ getDevToolInfo,
141
+ setDevToolInfo,
142
+ } from '../../../../modules/devToolInfo';
143
+ import PerformanceMetrics from './modules/PerformanceMetrics.vue';
144
+ import { usePerformanceData } from './modules/usePerformanceData';
145
+ import { usePerformanceChart } from './modules/usePerformanceChart';
146
+ import { MSG_TYPE, DEV_CORE_MESSAGE } from '../../../../const';
147
+ import DevToolTitle from '../DevToolTitle/index.vue';
148
+ import { useI18n } from '../../../../i18n';
149
+ import { getThemeMainColor } from '../../../styles/theme';
150
+ const { t } = useI18n();
151
+ const themeColor = computed(() => getThemeMainColor(props.theme));
152
+
153
+ // 无需声明 renderScript
154
+
155
+ const props = withDefaults(
156
+ defineProps<{
157
+ mode?: 'tab';
158
+ zIndex?: number;
159
+ customStyle?: Record<string, any>;
160
+ contentHeight?: number;
161
+ theme?: string;
162
+ }>(),
163
+ {
164
+ zIndex: 1000,
165
+ theme: 'light',
166
+ },
167
+ );
168
+
169
+ const showFps = ref(true);
170
+ const showCpu = ref(true);
171
+ const showMemory = ref(true);
172
+ const performanceVisible = ref(false);
173
+ const isH5 = ref(false);
174
+
175
+ function loadSettings() {
176
+ // #ifdef H5
177
+ isH5.value = true;
178
+ // #endif
179
+
180
+ const info = getDevToolInfo();
181
+ if (info && info.performanceSettings) {
182
+ showFps.value = info.performanceSettings.showFps ?? true;
183
+ showCpu.value = info.performanceSettings.showCpu ?? true;
184
+ showMemory.value = info.performanceSettings.showMemory ?? true;
185
+ performanceMonitorEnabled.value =
186
+ info.performanceSettings.enableMonitor ?? false;
187
+ }
188
+ if (info && info.performanceVisible !== undefined) {
189
+ performanceVisible.value = info.performanceVisible;
190
+ }
191
+ }
192
+
193
+ function saveSettings() {
194
+ setDevToolInfo({
195
+ performanceSettings: {
196
+ showFps: showFps.value,
197
+ showCpu: showCpu.value,
198
+ showMemory: showMemory.value,
199
+ enableMonitor: performanceMonitorEnabled.value,
200
+ },
201
+ performanceVisible: performanceVisible.value,
202
+ });
203
+ }
204
+
205
+ function toggleFps(e: any) {
206
+ showFps.value = e.detail.value;
207
+ saveSettings();
208
+ }
209
+
210
+ function toggleCpu(e: any) {
211
+ showCpu.value = e.detail.value;
212
+ saveSettings();
213
+ }
214
+
215
+ function toggleMemory(e: any) {
216
+ showMemory.value = e.detail.value;
217
+ saveSettings();
218
+ }
219
+
220
+ function togglePerformanceVisible(e: any) {
221
+ performanceVisible.value = e.detail.value;
222
+
223
+ // 如果关闭悬浮窗,同时关闭监测功能
224
+ if (!performanceVisible.value && performanceMonitorEnabled.value) {
225
+ performanceMonitorEnabled.value = false;
226
+ performanceData.stopHeartbeat();
227
+ performanceChart.stopRenderLoop();
228
+ // 通知 PerformanceWidget 停止监测
229
+ uni.$emit(MSG_TYPE.PERF_MONITOR, false);
230
+ }
231
+
232
+ saveSettings();
233
+ // 通知 DevTool 组件更新性能弹窗可见性
234
+ uni.$emit(DEV_CORE_MESSAGE, {
235
+ type: MSG_TYPE.PERF_VISIBLE,
236
+ data: performanceVisible.value,
237
+ });
238
+ }
239
+
240
+ function toggleMonitor(e: any) {
241
+ performanceMonitorEnabled.value = e.detail.value;
242
+ if (!performanceMonitorEnabled.value) {
243
+ performanceVisible.value = false;
244
+ }
245
+ saveSettings();
246
+ uni.$emit(MSG_TYPE.PERF_MONITOR, performanceMonitorEnabled.value);
247
+ if (performanceMonitorEnabled.value) {
248
+ performanceData.initData(
249
+ Math.ceil(performanceChart.canvasWidth.value / stepSize) + 4,
250
+ );
251
+ performanceData.startHeartbeat();
252
+ performanceChart.startRenderLoop();
253
+ uni.$emit(DEV_CORE_MESSAGE, {
254
+ type: MSG_TYPE.PERF_VISIBLE,
255
+ data: performanceVisible.value,
256
+ });
257
+ } else {
258
+ performanceData.stopHeartbeat();
259
+ performanceChart.stopRenderLoop();
260
+ uni.$emit(DEV_CORE_MESSAGE, {
261
+ type: MSG_TYPE.PERF_VISIBLE,
262
+ data: false,
263
+ });
264
+ }
265
+ }
266
+
267
+ // 根据主题计算颜色
268
+ const isDark = computed(() => {
269
+ return props.theme === 'dark';
270
+ });
271
+ const chartBgColor = computed(() =>
272
+ isDark.value ? 'rgba(255, 255, 255, 0.08)' : 'rgba(0, 0, 0, 0.05)',
273
+ );
274
+
275
+ const instance = getCurrentInstance();
276
+ const stepSize = 5;
277
+
278
+ // Hooks
279
+ const performanceData = usePerformanceData();
280
+ const { fps, cpuLoad, memory, performanceMonitorEnabled, longTasksHistory } =
281
+ performanceData;
282
+
283
+ const performanceChart = usePerformanceChart({
284
+ theme: props.theme,
285
+ isDark,
286
+ instance,
287
+ canvasIdFn: () => 'fpsChartTab',
288
+ stepSize,
289
+ data: performanceData,
290
+ config: {
291
+ showFps,
292
+ showCpu,
293
+ showMemory,
294
+ },
295
+ props: { mode: 'tab' },
296
+ });
297
+
298
+ function formatTaskTime(ts: number) {
299
+ const date = new Date(ts);
300
+ return `${date.getHours().toString().padStart(2, '0')}:${date
301
+ .getMinutes()
302
+ .toString()
303
+ .padStart(2, '0')}:${date.getSeconds().toString().padStart(2, '0')}.${date
304
+ .getMilliseconds()
305
+ .toString()
306
+ .padStart(3, '0')}`;
307
+ }
308
+
309
+ function getDurationClass(duration: number) {
310
+ if (duration > 200) return 'task-danger';
311
+ if (duration > 100) return 'task-warning';
312
+ return '';
313
+ }
314
+
315
+ onMounted(() => {
316
+ loadSettings();
317
+
318
+ performanceChart.initCanvas(() => {
319
+ performanceData.initData(
320
+ Math.ceil(performanceChart.canvasWidth.value / stepSize) + 4,
321
+ );
322
+ // 只有在监控开启且窗口可见时,才启动 Tab 的渲染循环
323
+ if (performanceMonitorEnabled.value) {
324
+ performanceChart.startRenderLoop();
325
+ }
326
+ });
327
+
328
+ // 如果监测状态是开启的,恢复执行
329
+ if (performanceMonitorEnabled.value) {
330
+ performanceData.startHeartbeat();
331
+ // @ts-ignore
332
+ if (performanceData.startLogicMonitor) {
333
+ // @ts-ignore
334
+ performanceData.startLogicMonitor();
335
+ }
336
+ }
337
+
338
+ // 监听核心模块消息
339
+ uni.$on(DEV_CORE_MESSAGE, handleCoreMessage);
340
+ // 监听监测状态变化(来自 PerformanceWidget)
341
+ uni.$on(MSG_TYPE.PERF_MONITOR, onMonitorStateChange);
342
+ });
343
+
344
+ // 监测状态变化处理(来自 PerformanceWidget 的通知)
345
+ function onMonitorStateChange(enabled: boolean) {
346
+ performanceMonitorEnabled.value = enabled;
347
+ if (!enabled) {
348
+ performanceData.stopHeartbeat();
349
+ performanceChart.stopRenderLoop();
350
+ } else {
351
+ // 补全开启逻辑
352
+ performanceData.startHeartbeat();
353
+ // 只有主窗口可见时才恢复绘制
354
+ const { devToolWindowVisible = false } = getDevToolInfo();
355
+ if (devToolWindowVisible) {
356
+ performanceChart.startRenderLoop();
357
+ }
358
+ }
359
+ }
360
+
361
+ // 处理核心模块消息
362
+ function handleCoreMessage(msg: string | { type: string; data: any }) {
363
+ let type: string | undefined;
364
+ let data: any;
365
+ try {
366
+ const payload = typeof msg === 'string' ? JSON.parse(msg) : msg;
367
+ type = payload.type;
368
+ data = payload.data;
369
+ } catch (_e) {
370
+ return;
371
+ }
372
+
373
+ if (type === MSG_TYPE.WINDOW_VISIBLE) {
374
+ onWindowVisibleChange(data);
375
+ }
376
+ }
377
+
378
+ // 窗口可见性变化处理
379
+ function onWindowVisibleChange(visible: boolean) {
380
+ if (!visible) {
381
+ // 窗口关闭时,仅停止 Tab 页面的渲染绘制,节省性能
382
+ performanceChart.stopRenderLoop();
383
+ // 逻辑层监控和心跳不再随窗口关闭而停止(只要 performanceMonitorEnabled 为 true)
384
+ } else {
385
+ // 窗口打开时,如果监控开启了,恢复 Tab 的渲染绘制
386
+ if (performanceMonitorEnabled.value) {
387
+ performanceChart.startRenderLoop();
388
+ }
389
+ }
390
+ }
391
+
392
+ onUnmounted(() => {
393
+ performanceChart.resetCanvas();
394
+ uni.$off(DEV_CORE_MESSAGE, handleCoreMessage);
395
+ uni.$off(MSG_TYPE.PERF_MONITOR, onMonitorStateChange);
396
+ });
397
+ </script>
398
+
399
+ <style scoped>
400
+ .performance-content {
401
+ height: 100%;
402
+ overflow: auto;
403
+ font-size: var(--dev-tool-base-font-size);
404
+ }
405
+
406
+ .performance-control {
407
+ padding: 0 16px;
408
+ }
409
+
410
+ .performance-item {
411
+ padding: 0 16px;
412
+ box-sizing: border-box;
413
+ }
414
+
415
+ .performance-row {
416
+ display: flex;
417
+ align-items: center;
418
+ justify-content: space-between;
419
+ min-height: 18px;
420
+ }
421
+
422
+ .fps-chart-container {
423
+ width: 100%;
424
+ flex: 1;
425
+ min-height: 50px;
426
+ margin-bottom: 4px;
427
+ border-radius: 4px;
428
+ overflow: hidden;
429
+ height: 300px;
430
+ }
431
+
432
+ .performance-tips {
433
+ color: #616161;
434
+ font-size: var(--dev-tool-tips-font-size);
435
+ margin-bottom: 8px;
436
+ }
437
+
438
+ .long-tasks-list {
439
+ background: var(--dev-tool-bg2-color);
440
+ border-radius: 4px;
441
+ padding: 8px;
442
+ max-height: 200px;
443
+ overflow-y: auto;
444
+ }
445
+
446
+ .long-task-item {
447
+ display: flex;
448
+ justify-content: space-between;
449
+ align-items: center;
450
+ padding: 4px 0;
451
+ border-bottom: 1px solid var(--dev-tool-border-color);
452
+ font-family: monospace;
453
+ }
454
+
455
+ .long-task-item:last-child {
456
+ border-bottom: none;
457
+ }
458
+
459
+ .task-info {
460
+ display: flex;
461
+ align-items: center;
462
+ font-size: 11px;
463
+ }
464
+
465
+ .task-type {
466
+ font-size: 10px;
467
+ padding: 0 4px;
468
+ border-radius: 2px;
469
+ color: #fff;
470
+ background: #909399;
471
+ margin-right: 6px;
472
+ line-height: 1.4;
473
+ }
474
+
475
+ .type-logic {
476
+ background: #9254de;
477
+ }
478
+
479
+ .type-ui {
480
+ background: #67c23a;
481
+ }
482
+
483
+ .task-time {
484
+ color: #888;
485
+ }
486
+
487
+ .task-duration {
488
+ font-weight: bold;
489
+ }
490
+
491
+ .task-warning {
492
+ color: #e6a23c;
493
+ }
494
+
495
+ .task-danger {
496
+ color: #f56c6c;
497
+ }
498
+ </style>