vite-uni-dev-tool 1.0.0 → 1.1.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 (168) hide show
  1. package/README.md +46 -0
  2. package/dist/const.cjs +1 -1
  3. package/dist/const.d.ts +12 -0
  4. package/dist/const.d.ts.map +1 -1
  5. package/dist/const.js +1 -1
  6. package/dist/core-shared.d.ts +1 -1
  7. package/dist/core-shared.d.ts.map +1 -1
  8. package/dist/core-shared.js +1 -1
  9. package/dist/core.d.ts +10 -3
  10. package/dist/core.d.ts.map +1 -1
  11. package/dist/core.js +2 -2
  12. package/dist/i18n/locales/en.cjs +1 -1
  13. package/dist/i18n/locales/en.d.ts +81 -0
  14. package/dist/i18n/locales/en.d.ts.map +1 -1
  15. package/dist/i18n/locales/en.js +1 -1
  16. package/dist/i18n/locales/zh-Hans.cjs +1 -1
  17. package/dist/i18n/locales/zh-Hans.d.ts +82 -1
  18. package/dist/i18n/locales/zh-Hans.d.ts.map +1 -1
  19. package/dist/i18n/locales/zh-Hans.js +1 -1
  20. package/dist/modules/devConsole/index.cjs +1 -1
  21. package/dist/modules/devConsole/index.js +3 -3
  22. package/dist/modules/devEvent/index.cjs +3 -3
  23. package/dist/modules/devEvent/index.d.ts +1 -0
  24. package/dist/modules/devEvent/index.d.ts.map +1 -1
  25. package/dist/modules/devEvent/index.js +3 -3
  26. package/dist/modules/devIntercept/index.cjs +14 -13
  27. package/dist/modules/devIntercept/index.d.ts +19 -0
  28. package/dist/modules/devIntercept/index.d.ts.map +1 -1
  29. package/dist/modules/devIntercept/index.js +14 -13
  30. package/dist/modules/devStore/index.cjs +1 -1
  31. package/dist/modules/devStore/index.d.ts +21 -0
  32. package/dist/modules/devStore/index.d.ts.map +1 -1
  33. package/dist/modules/devStore/index.js +1 -1
  34. package/dist/plugins/uniDevTool/transform/transformMain.cjs +1 -1
  35. package/dist/plugins/uniDevTool/transform/transformMain.js +1 -1
  36. package/dist/type.d.ts +47 -2
  37. package/dist/type.d.ts.map +1 -1
  38. package/dist/utils/language.cjs +1 -1
  39. package/dist/utils/language.d.ts.map +1 -1
  40. package/dist/utils/language.js +1 -1
  41. package/dist/utils/object.cjs +1 -1
  42. package/dist/utils/object.d.ts.map +1 -1
  43. package/dist/utils/object.js +1 -1
  44. package/dist/v3/DevTool/components/BluetoothList/BluetoothItem.vue +199 -0
  45. package/dist/v3/DevTool/components/BluetoothList/BluetoothTool.vue +730 -0
  46. package/dist/v3/DevTool/components/BluetoothList/index.vue +167 -0
  47. package/dist/v3/{CaptureScreen → DevTool/components/CaptureScreen}/index.vue +109 -109
  48. package/dist/v3/{ConsoleList → DevTool/components/ConsoleList}/ConsoleItem.vue +225 -224
  49. package/dist/v3/{ConsoleList → DevTool/components/ConsoleList}/RunJSInput.vue +247 -249
  50. package/dist/v3/{ConsoleList → DevTool/components/ConsoleList}/index.vue +171 -160
  51. package/dist/v3/{ConsoleList → DevTool/components/ConsoleList}/staticTips.ts +1145 -1145
  52. package/dist/v3/{DevToolButton → DevTool/components/DevToolButton}/index.vue +7 -4
  53. package/dist/v3/{DevToolTitle → DevTool/components/DevToolTitle}/index.vue +24 -24
  54. package/dist/v3/{DevToolWindow → DevTool/components/DevToolWindow}/DevToolOverlay.vue +197 -182
  55. package/dist/v3/{DevToolWindow → DevTool/components/DevToolWindow}/const.ts +28 -5
  56. package/dist/v3/{DevToolWindow → DevTool/components/DevToolWindow}/hooks/dataUtils.ts +48 -48
  57. package/dist/v3/{DevToolWindow → DevTool/components/DevToolWindow}/hooks/useDevToolData.ts +387 -338
  58. package/dist/v3/{DevToolWindow → DevTool/components/DevToolWindow}/hooks/useDevToolHandlers.ts +629 -549
  59. package/dist/v3/{DevToolWindow → DevTool/components/DevToolWindow}/hooks/useDevToolOverlay.ts +197 -184
  60. package/dist/v3/{DevToolWindow → DevTool/components/DevToolWindow}/index.vue +67 -16
  61. package/dist/v3/{ElEvent → DevTool/components/ElEvent}/ElEventItem.vue +105 -105
  62. package/dist/v3/{ElEvent → DevTool/components/ElEvent}/index.vue +106 -109
  63. package/dist/v3/{Instance → DevTool/components/Instance}/components/InstanceTreeNode.vue +265 -265
  64. package/dist/v3/{Instance → DevTool/components/Instance}/flatten.ts +226 -226
  65. package/dist/v3/{Instance → DevTool/components/Instance}/index.vue +94 -94
  66. package/dist/v3/{Instance → DevTool/components/Instance}/registry.ts +49 -49
  67. package/dist/v3/{Instance → DevTool/components/Instance}/transformTree.ts +375 -375
  68. package/dist/v3/{Instance → DevTool/components/Instance}/transformTreeCtx.ts +268 -268
  69. package/dist/v3/{Instance → DevTool/components/Instance}/typing.d.ts +43 -43
  70. package/dist/v3/{InstanceDetail → DevTool/components/InstanceDetail}/index.vue +485 -485
  71. package/dist/v3/{JsonDetail → DevTool/components/JsonDetail}/index.vue +70 -70
  72. package/dist/v3/{NFCList → DevTool/components/NFCList}/NFCItem.vue +112 -113
  73. package/dist/v3/{NFCList → DevTool/components/NFCList}/NFCTool.vue +454 -478
  74. package/dist/v3/{NFCList → DevTool/components/NFCList}/const.ts +56 -56
  75. package/dist/v3/{NFCList → DevTool/components/NFCList}/index.vue +94 -98
  76. package/dist/v3/{NetworkList → DevTool/components/NetworkList}/InterceptConfig.vue +624 -608
  77. package/dist/v3/{NetworkList → DevTool/components/NetworkList}/InterceptItem.vue +140 -140
  78. package/dist/v3/{NetworkList → DevTool/components/NetworkList}/NetworkDetail.vue +287 -296
  79. package/dist/v3/{NetworkList → DevTool/components/NetworkList}/NetworkIntercept.vue +88 -93
  80. package/dist/v3/{NetworkList → DevTool/components/NetworkList}/NetworkItem.vue +163 -167
  81. package/dist/v3/{NetworkList → DevTool/components/NetworkList}/NetworkSend.vue +589 -556
  82. package/dist/v3/{NetworkList → DevTool/components/NetworkList}/const.ts +4 -4
  83. package/dist/v3/{NetworkList → DevTool/components/NetworkList}/hooks/useNetworkForm.ts +86 -86
  84. package/dist/v3/{NetworkList → DevTool/components/NetworkList}/index.vue +160 -160
  85. package/dist/v3/{NetworkList → DevTool/components/NetworkList}/utils.ts +101 -101
  86. package/dist/v3/{Performance → DevTool/components/Performance}/index.vue +498 -495
  87. package/dist/v3/{Performance → DevTool/components/Performance}/modules/PerformanceMetrics.vue +153 -153
  88. package/dist/v3/{Performance → DevTool/components/Performance}/modules/PerformanceWidget.vue +12 -9
  89. package/dist/v3/{Performance → DevTool/components/Performance}/modules/usePerformanceChart.ts +460 -460
  90. package/dist/v3/{Performance → DevTool/components/Performance}/modules/usePerformanceData.ts +258 -258
  91. package/dist/v3/{PiniaList → DevTool/components/PiniaList}/index.vue +93 -94
  92. package/dist/v3/{RouteList → DevTool/components/RouteList}/index.vue +21 -24
  93. package/dist/v3/{RunJS → DevTool/components/RunJS}/index.vue +148 -148
  94. package/dist/v3/{ScanCodeList → DevTool/components/ScanCodeList}/ScanCodeItem.vue +97 -98
  95. package/dist/v3/{ScanCodeList → DevTool/components/ScanCodeList}/index.vue +100 -104
  96. package/dist/v3/{SettingButton → DevTool/components/SettingButton}/index.vue +45 -45
  97. package/dist/v3/{SettingList → DevTool/components/SettingList}/index.vue +218 -150
  98. package/dist/v3/DevTool/components/SettingList/modules/SettingBarrage.vue +304 -0
  99. package/dist/v3/{SettingList → DevTool/components/SettingList}/modules/SettingDevTool.vue +212 -208
  100. package/dist/v3/{SettingList → DevTool/components/SettingList}/modules/SettingInfo.vue +157 -119
  101. package/dist/v3/{SettingList → DevTool/components/SettingList}/modules/SettingLanguage.vue +74 -74
  102. package/dist/v3/{SettingList → DevTool/components/SettingList}/modules/SettingLog.vue +230 -230
  103. package/dist/v3/{SettingList → DevTool/components/SettingList}/modules/SettingNetwork.vue +3 -3
  104. package/dist/v3/{SettingList → DevTool/components/SettingList}/modules/SettingTheme.vue +37 -7
  105. package/dist/v3/{SettingList → DevTool/components/SettingList}/typing.d.ts +2 -2
  106. package/dist/v3/{SourceCode → DevTool/components/SourceCode}/Line.vue +127 -116
  107. package/dist/v3/{SourceCode → DevTool/components/SourceCode}/index.vue +8 -8
  108. package/dist/v3/{SourceCode → DevTool/components/SourceCode}/parseCode.ts +609 -701
  109. package/dist/v3/{StorageList → DevTool/components/StorageList}/index.vue +174 -174
  110. package/dist/v3/{TransferList → DevTool/components/TransferList}/TransferDetail.vue +268 -268
  111. package/dist/v3/{TransferList → DevTool/components/TransferList}/TransferItem.vue +4 -4
  112. package/dist/v3/{TransferList → DevTool/components/TransferList}/index.vue +8 -8
  113. package/dist/v3/{UniEvent → DevTool/components/UniEvent}/UniEventItem.vue +6 -7
  114. package/dist/v3/{UniEvent → DevTool/components/UniEvent}/index.vue +6 -6
  115. package/dist/v3/{VuexList → DevTool/components/VuexList}/index.vue +84 -84
  116. package/dist/v3/{WebSocket → DevTool/components/WebSocket}/WebSocketDetail.vue +8 -8
  117. package/dist/v3/{WebSocket → DevTool/components/WebSocket}/WebSocketItem.vue +4 -4
  118. package/dist/v3/{WebSocket → DevTool/components/WebSocket}/index.vue +8 -8
  119. package/dist/v3/DevTool/index.vue +179 -5
  120. package/dist/v3/{AppTransition → components/AppTransition}/index.vue +176 -170
  121. package/dist/v3/{AutoSizer → components/AutoSizer}/index.vue +192 -192
  122. package/dist/v3/{AutoSizer → components/AutoSizer}/index1.vue +184 -184
  123. package/dist/v3/{AutoSizer → components/AutoSizer}/utils.ts +49 -49
  124. package/dist/v3/components/Barrage/BarrageItem.vue +137 -0
  125. package/dist/v3/components/Barrage/index.vue +202 -0
  126. package/dist/v3/{CircularButton → components/CircularButton}/index.vue +84 -84
  127. package/dist/v3/{CustomSwiper → components/CustomSwiper}/CustomSwiperItem.vue +49 -49
  128. package/dist/v3/{CustomSwiper → components/CustomSwiper}/index.vue +104 -104
  129. package/dist/v3/{DraggableContainer → components/DraggableContainer}/index.vue +1 -1
  130. package/dist/v3/{Empty → components/Empty}/index.vue +29 -29
  131. package/dist/v3/{FilterInput → components/FilterInput}/index.vue +1 -1
  132. package/dist/v3/{FilterSelect → components/FilterSelect}/index.vue +179 -179
  133. package/dist/v3/{JsonPretty → components/JsonPretty}/components/Brackets/index.vue +27 -27
  134. package/dist/v3/{JsonPretty → components/JsonPretty}/components/Carets/index.vue +59 -59
  135. package/dist/v3/{JsonPretty → components/JsonPretty}/components/CheckController/index.vue +136 -136
  136. package/dist/v3/{JsonPretty → components/JsonPretty}/components/TreeNode/index.vue +387 -381
  137. package/dist/v3/{JsonPretty → components/JsonPretty}/hooks/useClipboard.ts +21 -21
  138. package/dist/v3/{JsonPretty → components/JsonPretty}/hooks/useError.ts +21 -21
  139. package/dist/v3/{JsonPretty → components/JsonPretty}/index.vue +16 -13
  140. package/dist/v3/{JsonPretty → components/JsonPretty}/type.ts +127 -126
  141. package/dist/v3/{JsonPretty → components/JsonPretty}/utils/index.ts +169 -169
  142. package/dist/v3/{MovableContainer → components/MovableContainer}/index.vue +1 -1
  143. package/dist/v3/{Pick → components/Pick}/index.vue +322 -322
  144. package/dist/v3/{Tabs → components/Tabs}/index.vue +30 -4
  145. package/dist/v3/{Tag → components/Tag}/index.vue +113 -113
  146. package/dist/v3/{VirtualList → components/VirtualList}/AutoSize.vue +40 -40
  147. package/dist/v3/{VirtualList → components/VirtualList}/index.vue +416 -412
  148. package/dist/v3/hooks/useBluetooth/index.ts +561 -0
  149. package/dist/v3/hooks/useContainerStyle.ts +153 -153
  150. package/dist/v3/hooks/useNFC/index.ts +107 -107
  151. package/dist/v3/hooks/useNFC/typing.d.ts +396 -396
  152. package/dist/v3/hooks/useNFC/useNFCAndroid.ts +966 -966
  153. package/dist/v3/hooks/useNFC/useNFCMpWeiXin.ts +812 -812
  154. package/dist/v3/hooks/useNFC/utils.ts +754 -754
  155. package/dist/v3/hooks/useRequest/index.ts +586 -573
  156. package/dist/v3/hooks/useRequest/utils.ts +267 -267
  157. package/dist/v3/hooks/useScanCode/index.ts +206 -206
  158. package/dist/v3/hooks/useWebsocket/README.md +79 -0
  159. package/dist/v3/hooks/useWebsocket/index.ts +253 -0
  160. package/dist/v3/styles/theme.css +17 -10
  161. package/dist/v3/styles/theme.ts +12 -12
  162. package/package.json +59 -64
  163. package/dist/plugins/uniParseStock/index.d.ts +0 -10
  164. package/dist/plugins/uniParseStock/index.d.ts.map +0 -1
  165. /package/dist/v3/{DevToolWindow → DevTool/components/DevToolWindow}/index.css +0 -0
  166. /package/dist/v3/{SettingList → DevTool/components/SettingList}/index.css +0 -0
  167. /package/dist/v3/{Empty → components/Empty}/empty.png +0 -0
  168. /package/dist/v3/{VirtualList → components/VirtualList}/readme.md +0 -0
@@ -1,375 +1,375 @@
1
- import { isArray, isObject, isString } from '../../utils';
2
- import {
3
- type ComponentInternalInstance,
4
- type VNode,
5
- isRef,
6
- isReactive,
7
- } from 'vue';
8
- import { getRecordedChildren } from './registry';
9
-
10
- // 类型守卫函数,检查是否为VNode类型
11
- function isVNode(child: any): child is VNode {
12
- return child != null && typeof child === 'object' && 'type' in child;
13
- }
14
-
15
- // 类型守卫函数,检查是否为包含component属性的对象
16
- function hasComponentProperty(
17
- child: any,
18
- ): child is VNode & { component?: ComponentInternalInstance } {
19
- return isVNode(child) && 'component' in child;
20
- }
21
-
22
- // 类型守卫函数,检查是否为Symbol类型且具有description属性
23
- function isSymbolWithDescription(
24
- value: any,
25
- ): value is symbol & { description?: string } {
26
- return typeof value === 'symbol';
27
- }
28
-
29
- interface SimpleTreeNode {
30
- type: string;
31
- uid: string | number;
32
- children?: SimpleTreeNode[];
33
- content?: string;
34
- hasChildren?: boolean;
35
- // 分类存储属性
36
- props?: Record<string, any>;
37
- styles?: Record<string, any>;
38
- other?: Record<string, any>;
39
- provides?: Record<string, any>;
40
- data?: Record<string, any>;
41
- functions?: Record<string, any>;
42
- emits?: Record<string, any>;
43
- }
44
-
45
- /**
46
- * 分类提取属性
47
- */
48
- function extractCategorizedData(vnode: any): {
49
- props: Record<string, any>;
50
- styles: Record<string, any>;
51
- other: Record<string, any>;
52
- provides: Record<string, any>;
53
- data: Record<string, any>;
54
- functions: Record<string, any>;
55
- emits: Record<string, any>;
56
- } {
57
- const styles: any = {};
58
- const props: any = {};
59
- const other: any = {};
60
- const provides: any = {};
61
- const data: any = {};
62
- const emits: any = {};
63
-
64
- const vnodeProps = vnode.props || {};
65
-
66
- // 1. 提取样式相关 (id, style)
67
- const styleKeys = ['id', 'style'];
68
-
69
- // 处理样式属性
70
- styleKeys.forEach((key) => {
71
- let val = vnodeProps[key];
72
- if (val !== undefined && val !== null && val !== '') {
73
- if (key === 'style' && isObject(val)) {
74
- val = Object.entries(val)
75
- .filter(([_, v]) => v !== undefined && v !== null && v !== '')
76
- .map(([k, v]) => `${k}: ${v}`)
77
- .join('; ');
78
- }
79
- if (val !== '') {
80
- styles[key] = val;
81
- }
82
- }
83
- });
84
-
85
- // 处理 Props 属性 (包括 class, data- 以及其他)
86
- Object.keys(vnodeProps).forEach((key) => {
87
- // 排除已处理的样式属性
88
- if (!styleKeys.includes(key)) {
89
- // 统一处理 className -> class
90
- const finalKey = key === 'className' ? 'class' : key;
91
- props[finalKey] = vnodeProps[key];
92
- }
93
- });
94
-
95
- // 3. 提取其他元数据
96
- other.uid = vnode.uid;
97
- if (vnode.type) {
98
- other.type = isString(vnode.type)
99
- ? vnode.type
100
- : isObject(vnode.type)
101
- ? (vnode.type as any).name || (vnode.type as any).__name || 'Component'
102
- : String(vnode.type);
103
-
104
- if (isObject(vnode.type) && (vnode.type as any).__file) {
105
- other.file = (vnode.type as any).__file;
106
- }
107
- }
108
-
109
- // 如果有 slots
110
- if (vnode.children && !isArray(vnode.children) && isObject(vnode.children)) {
111
- other.slots = Object.keys(vnode.children);
112
- }
113
-
114
- // 4. 提取 provides
115
- const currentProvides = vnode.provides;
116
-
117
- if (currentProvides) {
118
- Reflect.ownKeys(currentProvides).forEach((key) => {
119
- // 排除 Vue 内部属性
120
- if (typeof key === 'string' && key.startsWith('__v')) return;
121
-
122
- const value = currentProvides[key];
123
- const keyStr = typeof key === 'symbol' ? String(key) : key;
124
- provides[keyStr] = value;
125
- });
126
- }
127
-
128
- // 5. 提取 data (仅当 vnode.component 存在时)
129
- const functions: any = {};
130
- if (vnode.setupState || vnode.data) {
131
- // 优先取 setupState (Script Setup / Composition API), 其次取 data (Options API)
132
- // 注意:setupState 包含了响应式引用的解包值
133
- const allData: any = {};
134
-
135
- // 处理 setupState
136
- if (isObject(vnode.setupState)) {
137
- Object.assign(allData, vnode.setupState);
138
- }
139
-
140
- // 处理 Options API data
141
- if (isObject(vnode.data)) {
142
- Object.assign(allData, vnode.data);
143
- }
144
-
145
- if (isObject(allData)) {
146
- Reflect.ownKeys(allData).forEach((key) => {
147
- // 排除 Vue 内部属性
148
- if (
149
- typeof key === 'string' &&
150
- (key.startsWith('__v') || key.startsWith('$') || key.startsWith('_'))
151
- )
152
- return;
153
-
154
- const value = (allData as any)[key];
155
- let keyStr = typeof key === 'symbol' ? String(key) : key;
156
-
157
- // 标记 Ref 和 Reactive
158
- // 优先检查 devtoolsRawSetupState 获取原始 Ref
159
- const rawSetupState = (vnode as any).devtoolsRawSetupState || {};
160
- const rawValue = rawSetupState[key];
161
-
162
- if (rawValue && isRef(rawValue)) {
163
- keyStr += ' (Ref)';
164
- } else if (isReactive(value)) {
165
- keyStr += ' (Reactive)';
166
- }
167
-
168
- if (typeof value === 'function') {
169
- functions[keyStr] = value;
170
- } else {
171
- // 尝试区分类型(Ref, Reactive, Computed 等在 setupState 中通常已被解包,难以直接判断原始类型,
172
- // 除非使用 devtools 专用钩子。这里暂只做基础值存储)
173
- data[keyStr] = value;
174
- }
175
- });
176
- }
177
- }
178
-
179
- // 6. 提取 emits
180
- // 优先从组件实例获取归一化的 emitsOptions, 其次从类型定义获取
181
- const emitsOptions = vnode?.emitsOptions || vnode.type?.emits;
182
- if (emitsOptions) {
183
- if (isArray(emitsOptions)) {
184
- emitsOptions.forEach((emit: string) => {
185
- emits[emit] = 'function(...args) {...}'; // 简单标记存在
186
- });
187
- } else if (isObject(emitsOptions)) {
188
- Reflect.ownKeys(emitsOptions).forEach((key) => {
189
- if (typeof key === 'string') {
190
- emits[key] = 'function(...args) {...}';
191
- }
192
- });
193
- }
194
- }
195
-
196
- return { props, styles, other, provides, data, functions, emits };
197
- }
198
-
199
- let uidCount = 0;
200
- // 导出重置函数,供外部调用
201
- export function resetUidCount() {
202
- uidCount = 0;
203
- }
204
-
205
- function getNextUid() {
206
- return `manual-${++uidCount}`;
207
- }
208
-
209
- function extractNameFromFile(file: string): string | undefined {
210
- if (!file) return undefined;
211
- const match = file.match(/([^/|\\]+)\.[^.]+$/);
212
- return match ? match[1] : undefined;
213
- }
214
-
215
- function getComponentName(type: any): string {
216
- if (!type) return 'Anonymous';
217
- if (typeof type === 'string') return type;
218
- if (typeof type === 'object') {
219
- return (
220
- type.name ||
221
- type.__name ||
222
- (type.__file ? extractNameFromFile(type.__file) : undefined) ||
223
- 'Anonymous'
224
- );
225
- }
226
- if (typeof type === 'function') {
227
- return type.name || type.__name || 'Anonymous';
228
- }
229
- return 'Anonymous';
230
- }
231
-
232
- // ... existing code ...
233
-
234
- // ... types ...
235
-
236
- export function simpleTree(vNode?: any, depth = 0): SimpleTreeNode | null {
237
- // ... check valid ...
238
- if (vNode === null || typeof vNode !== 'object' || depth > 40) {
239
- return null;
240
- }
241
- // ... rest of simpleTree func ...
242
-
243
- // 确保只使用必需的属性
244
- const simplifiedInstance: InstanceTree.SimplifiedComponentInternalInstance = {
245
- type: vNode.type,
246
- subTree: vNode.subTree,
247
- uid: vNode.uid,
248
- ...(vNode.component && { component: vNode.component }),
249
- ...(vNode.children && { children: vNode.children }),
250
- };
251
-
252
- const children: SimpleTreeNode[] = [];
253
-
254
- // 获取子节点
255
- if (simplifiedInstance.subTree) {
256
- if ('data-dev-tool' in (simplifiedInstance.subTree.props ?? {})) {
257
- return null;
258
- } else {
259
- children.push(
260
- ...getSimpleChildrenFromVNode(simplifiedInstance.subTree, depth),
261
- );
262
- }
263
- }
264
-
265
- // 插槽 fallback
266
- if (children.length === 0 && simplifiedInstance.children) {
267
- if (isArray(simplifiedInstance.children)) {
268
- const slotChildren = getSimpleChildrenFromVNode(
269
- {
270
- children: simplifiedInstance.children,
271
- },
272
- depth,
273
- );
274
- children.push(...slotChildren);
275
- }
276
- }
277
-
278
- // GLOBAL fallback
279
- if (children.length === 0 && vNode.uid !== undefined) {
280
- const recordedChildren = getRecordedChildren(vNode.uid);
281
- recordedChildren.forEach((childInst) => {
282
- const childTree = simpleTree(childInst, depth + 1);
283
- if (childTree) {
284
- children.push(childTree);
285
- }
286
- });
287
- }
288
-
289
- const hasChildrenFlag = children.length > 0;
290
- const uid = vNode.uid !== undefined ? vNode.uid : getNextUid();
291
- const typeName = getComponentName(simplifiedInstance.type);
292
-
293
- const nodeInfo: SimpleTreeNode = {
294
- type: typeName,
295
- uid,
296
- children,
297
- hasChildren: hasChildrenFlag,
298
- ...extractCategorizedData(vNode),
299
- };
300
-
301
- return nodeInfo;
302
- }
303
-
304
- /**
305
- * 从 VNode 获取简化的子节点 (仅保留组件节点)
306
- */
307
- function getSimpleChildrenFromVNode(
308
- vnode: any,
309
- depth: number = 0,
310
- ): SimpleTreeNode[] {
311
- const children: SimpleTreeNode[] = [];
312
- if (vnode.children) {
313
- // 统一转为数组处理,兼容单节点和多节点
314
- const rawChildren = isArray(vnode.children)
315
- ? vnode.children
316
- : isObject(vnode.children)
317
- ? [vnode.children]
318
- : isString(vnode.children)
319
- ? [vnode.children]
320
- : [];
321
-
322
- for (const child of rawChildren) {
323
- if (
324
- child &&
325
- typeof child === 'object' &&
326
- 'props' in child &&
327
- child.props &&
328
- 'data-dev-tool' in child.props
329
- ) {
330
- continue;
331
- }
332
-
333
- // 1. 如果是组件实例,直接处理
334
- if (hasComponentProperty(child) && child?.component) {
335
- const childTree = simpleTree(child.component, depth + 1);
336
- if (childTree) {
337
- children.push(childTree);
338
- }
339
- }
340
- // 2. 如果是函数式组件
341
- else if (isVNode(child) && typeof child.type === 'function') {
342
- const uid =
343
- (child as any).uid !== undefined ? (child as any).uid : getNextUid();
344
- const typeName = getComponentName(child.type);
345
- children.push({
346
- type: typeName,
347
- uid,
348
- children: [],
349
- hasChildren: false,
350
- ...extractCategorizedData(child),
351
- });
352
- }
353
- // 3. 如果是 VNode 且是 Fragmentation/Block (带 children 的非组件节点),需要深入查找内部的组件
354
- else if (isVNode(child)) {
355
- // 如果是 Fragment,递归查找子节点
356
- if (child.type && isSymbolWithDescription(child.type)) {
357
- const desc = child.type.description;
358
- const isFragment = desc === 'v-fgt' || desc === 'Fragment';
359
- if (isFragment) {
360
- const fragmentChildren = getSimpleChildrenFromVNode(child, depth);
361
- children.push(...fragmentChildren);
362
- }
363
- }
364
- // 如果是普通 HTML 元素或其他容器,也需要递归查找其 children 中的组件
365
- // 例如 <view><MyComponent /></view>,我们需要找到 MyComponent
366
- else if (isString(child.type) || isObject(child.type)) {
367
- // 递归查找子节点中的组件,但不把当前节点加入树中(因为我们只关心组件)
368
- const subChildren = getSimpleChildrenFromVNode(child, depth);
369
- children.push(...subChildren);
370
- }
371
- }
372
- }
373
- }
374
- return children;
375
- }
1
+ import { isArray, isObject, isString } from '../../../../utils';
2
+ import {
3
+ type ComponentInternalInstance,
4
+ type VNode,
5
+ isRef,
6
+ isReactive,
7
+ } from 'vue';
8
+ import { getRecordedChildren } from './registry';
9
+
10
+ // 类型守卫函数,检查是否为VNode类型
11
+ function isVNode(child: any): child is VNode {
12
+ return child != null && typeof child === 'object' && 'type' in child;
13
+ }
14
+
15
+ // 类型守卫函数,检查是否为包含component属性的对象
16
+ function hasComponentProperty(
17
+ child: any,
18
+ ): child is VNode & { component?: ComponentInternalInstance } {
19
+ return isVNode(child) && 'component' in child;
20
+ }
21
+
22
+ // 类型守卫函数,检查是否为Symbol类型且具有description属性
23
+ function isSymbolWithDescription(
24
+ value: any,
25
+ ): value is symbol & { description?: string } {
26
+ return typeof value === 'symbol';
27
+ }
28
+
29
+ interface SimpleTreeNode {
30
+ type: string;
31
+ uid: string | number;
32
+ children?: SimpleTreeNode[];
33
+ content?: string;
34
+ hasChildren?: boolean;
35
+ // 分类存储属性
36
+ props?: Record<string, any>;
37
+ styles?: Record<string, any>;
38
+ other?: Record<string, any>;
39
+ provides?: Record<string, any>;
40
+ data?: Record<string, any>;
41
+ functions?: Record<string, any>;
42
+ emits?: Record<string, any>;
43
+ }
44
+
45
+ /**
46
+ * 分类提取属性
47
+ */
48
+ function extractCategorizedData(vnode: any): {
49
+ props: Record<string, any>;
50
+ styles: Record<string, any>;
51
+ other: Record<string, any>;
52
+ provides: Record<string, any>;
53
+ data: Record<string, any>;
54
+ functions: Record<string, any>;
55
+ emits: Record<string, any>;
56
+ } {
57
+ const styles: any = {};
58
+ const props: any = {};
59
+ const other: any = {};
60
+ const provides: any = {};
61
+ const data: any = {};
62
+ const emits: any = {};
63
+
64
+ const vnodeProps = vnode.props || {};
65
+
66
+ // 1. 提取样式相关 (id, style)
67
+ const styleKeys = ['id', 'style'];
68
+
69
+ // 处理样式属性
70
+ styleKeys.forEach((key) => {
71
+ let val = vnodeProps[key];
72
+ if (val !== undefined && val !== null && val !== '') {
73
+ if (key === 'style' && isObject(val)) {
74
+ val = Object.entries(val)
75
+ .filter(([_, v]) => v !== undefined && v !== null && v !== '')
76
+ .map(([k, v]) => `${k}: ${v}`)
77
+ .join('; ');
78
+ }
79
+ if (val !== '') {
80
+ styles[key] = val;
81
+ }
82
+ }
83
+ });
84
+
85
+ // 处理 Props 属性 (包括 class, data- 以及其他)
86
+ Object.keys(vnodeProps).forEach((key) => {
87
+ // 排除已处理的样式属性
88
+ if (!styleKeys.includes(key)) {
89
+ // 统一处理 className -> class
90
+ const finalKey = key === 'className' ? 'class' : key;
91
+ props[finalKey] = vnodeProps[key];
92
+ }
93
+ });
94
+
95
+ // 3. 提取其他元数据
96
+ other.uid = vnode.uid;
97
+ if (vnode.type) {
98
+ other.type = isString(vnode.type)
99
+ ? vnode.type
100
+ : isObject(vnode.type)
101
+ ? (vnode.type as any).name || (vnode.type as any).__name || 'Component'
102
+ : String(vnode.type);
103
+
104
+ if (isObject(vnode.type) && (vnode.type as any).__file) {
105
+ other.file = (vnode.type as any).__file;
106
+ }
107
+ }
108
+
109
+ // 如果有 slots
110
+ if (vnode.children && !isArray(vnode.children) && isObject(vnode.children)) {
111
+ other.slots = Object.keys(vnode.children);
112
+ }
113
+
114
+ // 4. 提取 provides
115
+ const currentProvides = vnode.provides;
116
+
117
+ if (currentProvides) {
118
+ Reflect.ownKeys(currentProvides).forEach((key) => {
119
+ // 排除 Vue 内部属性
120
+ if (typeof key === 'string' && key.startsWith('__v')) return;
121
+
122
+ const value = currentProvides[key];
123
+ const keyStr = typeof key === 'symbol' ? String(key) : key;
124
+ provides[keyStr] = value;
125
+ });
126
+ }
127
+
128
+ // 5. 提取 data (仅当 vnode.component 存在时)
129
+ const functions: any = {};
130
+ if (vnode.setupState || vnode.data) {
131
+ // 优先取 setupState (Script Setup / Composition API), 其次取 data (Options API)
132
+ // 注意:setupState 包含了响应式引用的解包值
133
+ const allData: any = {};
134
+
135
+ // 处理 setupState
136
+ if (isObject(vnode.setupState)) {
137
+ Object.assign(allData, vnode.setupState);
138
+ }
139
+
140
+ // 处理 Options API data
141
+ if (isObject(vnode.data)) {
142
+ Object.assign(allData, vnode.data);
143
+ }
144
+
145
+ if (isObject(allData)) {
146
+ Reflect.ownKeys(allData).forEach((key) => {
147
+ // 排除 Vue 内部属性
148
+ if (
149
+ typeof key === 'string' &&
150
+ (key.startsWith('__v') || key.startsWith('$') || key.startsWith('_'))
151
+ )
152
+ return;
153
+
154
+ const value = (allData as any)[key];
155
+ let keyStr = typeof key === 'symbol' ? String(key) : key;
156
+
157
+ // 标记 Ref 和 Reactive
158
+ // 优先检查 devtoolsRawSetupState 获取原始 Ref
159
+ const rawSetupState = (vnode as any).devtoolsRawSetupState || {};
160
+ const rawValue = rawSetupState[key];
161
+
162
+ if (rawValue && isRef(rawValue)) {
163
+ keyStr += ' (Ref)';
164
+ } else if (isReactive(value)) {
165
+ keyStr += ' (Reactive)';
166
+ }
167
+
168
+ if (typeof value === 'function') {
169
+ functions[keyStr] = value;
170
+ } else {
171
+ // 尝试区分类型(Ref, Reactive, Computed 等在 setupState 中通常已被解包,难以直接判断原始类型,
172
+ // 除非使用 devtools 专用钩子。这里暂只做基础值存储)
173
+ data[keyStr] = value;
174
+ }
175
+ });
176
+ }
177
+ }
178
+
179
+ // 6. 提取 emits
180
+ // 优先从组件实例获取归一化的 emitsOptions, 其次从类型定义获取
181
+ const emitsOptions = vnode?.emitsOptions || vnode.type?.emits;
182
+ if (emitsOptions) {
183
+ if (isArray(emitsOptions)) {
184
+ emitsOptions.forEach((emit: string) => {
185
+ emits[emit] = 'function(...args) {...}'; // 简单标记存在
186
+ });
187
+ } else if (isObject(emitsOptions)) {
188
+ Reflect.ownKeys(emitsOptions).forEach((key) => {
189
+ if (typeof key === 'string') {
190
+ emits[key] = 'function(...args) {...}';
191
+ }
192
+ });
193
+ }
194
+ }
195
+
196
+ return { props, styles, other, provides, data, functions, emits };
197
+ }
198
+
199
+ let uidCount = 0;
200
+ // 导出重置函数,供外部调用
201
+ export function resetUidCount() {
202
+ uidCount = 0;
203
+ }
204
+
205
+ function getNextUid() {
206
+ return `manual-${++uidCount}`;
207
+ }
208
+
209
+ function extractNameFromFile(file: string): string | undefined {
210
+ if (!file) return undefined;
211
+ const match = file.match(/([^/|\\]+)\.[^.]+$/);
212
+ return match ? match[1] : undefined;
213
+ }
214
+
215
+ function getComponentName(type: any): string {
216
+ if (!type) return 'Anonymous';
217
+ if (typeof type === 'string') return type;
218
+ if (typeof type === 'object') {
219
+ return (
220
+ type.name ||
221
+ type.__name ||
222
+ (type.__file ? extractNameFromFile(type.__file) : undefined) ||
223
+ 'Anonymous'
224
+ );
225
+ }
226
+ if (typeof type === 'function') {
227
+ return type.name || type.__name || 'Anonymous';
228
+ }
229
+ return 'Anonymous';
230
+ }
231
+
232
+ // ... existing code ...
233
+
234
+ // ... types ...
235
+
236
+ export function simpleTree(vNode?: any, depth = 0): SimpleTreeNode | null {
237
+ // ... check valid ...
238
+ if (vNode === null || typeof vNode !== 'object' || depth > 40) {
239
+ return null;
240
+ }
241
+ // ... rest of simpleTree func ...
242
+
243
+ // 确保只使用必需的属性
244
+ const simplifiedInstance: InstanceTree.SimplifiedComponentInternalInstance = {
245
+ type: vNode.type,
246
+ subTree: vNode.subTree,
247
+ uid: vNode.uid,
248
+ ...(vNode.component && { component: vNode.component }),
249
+ ...(vNode.children && { children: vNode.children }),
250
+ };
251
+
252
+ const children: SimpleTreeNode[] = [];
253
+
254
+ // 获取子节点
255
+ if (simplifiedInstance.subTree) {
256
+ if ('data-dev-tool' in (simplifiedInstance.subTree.props ?? {})) {
257
+ return null;
258
+ } else {
259
+ children.push(
260
+ ...getSimpleChildrenFromVNode(simplifiedInstance.subTree, depth),
261
+ );
262
+ }
263
+ }
264
+
265
+ // 插槽 fallback
266
+ if (children.length === 0 && simplifiedInstance.children) {
267
+ if (isArray(simplifiedInstance.children)) {
268
+ const slotChildren = getSimpleChildrenFromVNode(
269
+ {
270
+ children: simplifiedInstance.children,
271
+ },
272
+ depth,
273
+ );
274
+ children.push(...slotChildren);
275
+ }
276
+ }
277
+
278
+ // GLOBAL fallback
279
+ if (children.length === 0 && vNode.uid !== undefined) {
280
+ const recordedChildren = getRecordedChildren(vNode.uid);
281
+ recordedChildren.forEach((childInst) => {
282
+ const childTree = simpleTree(childInst, depth + 1);
283
+ if (childTree) {
284
+ children.push(childTree);
285
+ }
286
+ });
287
+ }
288
+
289
+ const hasChildrenFlag = children.length > 0;
290
+ const uid = vNode.uid !== undefined ? vNode.uid : getNextUid();
291
+ const typeName = getComponentName(simplifiedInstance.type);
292
+
293
+ const nodeInfo: SimpleTreeNode = {
294
+ type: typeName,
295
+ uid,
296
+ children,
297
+ hasChildren: hasChildrenFlag,
298
+ ...extractCategorizedData(vNode),
299
+ };
300
+
301
+ return nodeInfo;
302
+ }
303
+
304
+ /**
305
+ * 从 VNode 获取简化的子节点 (仅保留组件节点)
306
+ */
307
+ function getSimpleChildrenFromVNode(
308
+ vnode: any,
309
+ depth: number = 0,
310
+ ): SimpleTreeNode[] {
311
+ const children: SimpleTreeNode[] = [];
312
+ if (vnode.children) {
313
+ // 统一转为数组处理,兼容单节点和多节点
314
+ const rawChildren = isArray(vnode.children)
315
+ ? vnode.children
316
+ : isObject(vnode.children)
317
+ ? [vnode.children]
318
+ : isString(vnode.children)
319
+ ? [vnode.children]
320
+ : [];
321
+
322
+ for (const child of rawChildren) {
323
+ if (
324
+ child &&
325
+ typeof child === 'object' &&
326
+ 'props' in child &&
327
+ child.props &&
328
+ 'data-dev-tool' in child.props
329
+ ) {
330
+ continue;
331
+ }
332
+
333
+ // 1. 如果是组件实例,直接处理
334
+ if (hasComponentProperty(child) && child?.component) {
335
+ const childTree = simpleTree(child.component, depth + 1);
336
+ if (childTree) {
337
+ children.push(childTree);
338
+ }
339
+ }
340
+ // 2. 如果是函数式组件
341
+ else if (isVNode(child) && typeof child.type === 'function') {
342
+ const uid =
343
+ (child as any).uid !== undefined ? (child as any).uid : getNextUid();
344
+ const typeName = getComponentName(child.type);
345
+ children.push({
346
+ type: typeName,
347
+ uid,
348
+ children: [],
349
+ hasChildren: false,
350
+ ...extractCategorizedData(child),
351
+ });
352
+ }
353
+ // 3. 如果是 VNode 且是 Fragmentation/Block (带 children 的非组件节点),需要深入查找内部的组件
354
+ else if (isVNode(child)) {
355
+ // 如果是 Fragment,递归查找子节点
356
+ if (child.type && isSymbolWithDescription(child.type)) {
357
+ const desc = child.type.description;
358
+ const isFragment = desc === 'v-fgt' || desc === 'Fragment';
359
+ if (isFragment) {
360
+ const fragmentChildren = getSimpleChildrenFromVNode(child, depth);
361
+ children.push(...fragmentChildren);
362
+ }
363
+ }
364
+ // 如果是普通 HTML 元素或其他容器,也需要递归查找其 children 中的组件
365
+ // 例如 <view><MyComponent /></view>,我们需要找到 MyComponent
366
+ else if (isString(child.type) || isObject(child.type)) {
367
+ // 递归查找子节点中的组件,但不把当前节点加入树中(因为我们只关心组件)
368
+ const subChildren = getSimpleChildrenFromVNode(child, depth);
369
+ children.push(...subChildren);
370
+ }
371
+ }
372
+ }
373
+ }
374
+ return children;
375
+ }