vite-uni-dev-tool 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +120 -0
- package/dev/components/Button/index.vue +34 -0
- package/dev/components/Checkbox/index.vue +40 -0
- package/dev/components/CloseButton/index.vue +25 -0
- package/dev/components/Connection/index.vue +98 -0
- package/dev/components/ConsoleList/ConsoleItem.vue +89 -0
- package/dev/components/ConsoleList/index.vue +98 -0
- package/dev/components/DevTool/index.vue +165 -0
- package/dev/components/DevToolButton/index.vue +213 -0
- package/dev/components/DevToolWindow/index.vue +847 -0
- package/dev/components/DeviceInfo/index.vue +32 -0
- package/dev/components/Empty/empty.png +0 -0
- package/dev/components/Empty/index.vue +28 -0
- package/dev/components/FilterInput/index.vue +86 -0
- package/dev/components/JsonPretty/components/Brackets/index.vue +23 -0
- package/dev/components/JsonPretty/components/Carets/index.vue +63 -0
- package/dev/components/JsonPretty/components/CheckController/index.vue +108 -0
- package/dev/components/JsonPretty/components/TreeNode/index.vue +348 -0
- package/dev/components/JsonPretty/hooks/useClipboard.ts +21 -0
- package/dev/components/JsonPretty/hooks/useError.ts +21 -0
- package/dev/components/JsonPretty/index.vue +463 -0
- package/dev/components/JsonPretty/type.ts +123 -0
- package/dev/components/JsonPretty/utils/index.ts +172 -0
- package/dev/components/NetworkList/NetworkDetail.vue +197 -0
- package/dev/components/NetworkList/NetworkItem.vue +106 -0
- package/dev/components/NetworkList/index.vue +108 -0
- package/dev/components/PiniaList/index.vue +64 -0
- package/dev/components/RouteList/index.vue +98 -0
- package/dev/components/SettingList/index.vue +235 -0
- package/dev/components/StorageList/index.vue +170 -0
- package/dev/components/SystemInfo/index.vue +34 -0
- package/dev/components/Tabs/index.vue +110 -0
- package/dev/components/Tag/index.vue +89 -0
- package/dev/components/UploadList/UploadDetail.vue +208 -0
- package/dev/components/UploadList/UploadItem.vue +111 -0
- package/dev/components/UploadList/index.vue +94 -0
- package/dev/components/VuexList/index.vue +54 -0
- package/dev/components/WebSocket/WebSocketItem.vue +98 -0
- package/dev/components/WebSocket/WebSocketList.vue +176 -0
- package/dev/components/WebSocket/index.vue +99 -0
- package/dev/components/WindowInfo/index.vue +33 -0
- package/dev/const.ts +95 -0
- package/dev/core.ts +103 -0
- package/dev/devConsole/index.ts +334 -0
- package/dev/devEvent/index.ts +665 -0
- package/dev/devIntercept/index.ts +629 -0
- package/dev/devStore/index.ts +581 -0
- package/dev/index.d.ts +6 -0
- package/dev/index.d.ts.map +1 -0
- package/dev/index.js +1 -0
- package/dev/plugins/uniDevTool/uniDevTool.d.ts +66 -0
- package/dev/plugins/uniDevTool/uniDevTool.d.ts.map +1 -0
- package/dev/plugins/uniDevTool/uniDevTool.js +13 -0
- package/dev/plugins/uniGlobalComponents/uniGlobalComponents.d.ts +28 -0
- package/dev/plugins/uniGlobalComponents/uniGlobalComponents.d.ts.map +1 -0
- package/dev/plugins/uniGlobalComponents/uniGlobalComponents.js +5 -0
- package/dev/shims-uni.d.ts +43 -0
- package/dev/type.ts +188 -0
- package/dev/utils/date.ts +75 -0
- package/dev/utils/file.ts +121 -0
- package/dev/utils/function.ts +192 -0
- package/dev/utils/index.ts +25 -0
- package/dev/utils/ip.ts +79 -0
- package/dev/utils/language.ts +19 -0
- package/dev/utils/object.ts +235 -0
- package/dev/utils/page.ts +13 -0
- package/dev/utils/string.ts +23 -0
- package/dev/utils/utils.ts +198 -0
- package/package.json +34 -0
package/dev/utils/ip.ts
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
export function getWifiIp() {
|
|
2
|
+
// #ifdef APP-PLUS
|
|
3
|
+
const manActivity: any = plus.android.runtimeMainActivity();
|
|
4
|
+
const context: any = plus.android.importClass('android.content.Context');
|
|
5
|
+
plus.android.importClass('android.net.wifi.WifiManager');
|
|
6
|
+
plus.android.importClass('android.net.wifi.WifiInfo');
|
|
7
|
+
plus.android.importClass('android.net.wifi.ScanResult');
|
|
8
|
+
const wifiManger = manActivity.getSystemService(context.WIFI_SERVICE);
|
|
9
|
+
const wifiInfo = wifiManger.getConnectionInfo();
|
|
10
|
+
const ipAddress = wifiInfo.getIpAddress();
|
|
11
|
+
const wifiIp =
|
|
12
|
+
(ipAddress & 0xff) +
|
|
13
|
+
'.' +
|
|
14
|
+
((ipAddress >> 8) & 0xff) +
|
|
15
|
+
'.' +
|
|
16
|
+
((ipAddress >> 16) & 0xff) +
|
|
17
|
+
'.' +
|
|
18
|
+
((ipAddress >> 24) & 0xff);
|
|
19
|
+
|
|
20
|
+
return wifiIp;
|
|
21
|
+
|
|
22
|
+
// #endif
|
|
23
|
+
return '';
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function getLanIp() {
|
|
27
|
+
// #ifdef APP-PLUS
|
|
28
|
+
const manActivity: any = plus.android.runtimeMainActivity();
|
|
29
|
+
const context: any = plus.android.importClass('android.content.Context');
|
|
30
|
+
plus.android.importClass('android.net.ConnectivityManager');
|
|
31
|
+
const lanManager = manActivity.getSystemService(context.CONNECTIVITY_SERVICE);
|
|
32
|
+
const lanInfo = lanManager.getLinkProperties(lanManager.getActiveNetwork());
|
|
33
|
+
const lanIpAddress = plus.android.invoke(lanInfo, 'getLinkAddress');
|
|
34
|
+
const lanIpAddressStr = lanIpAddress?.toString();
|
|
35
|
+
const lanIpAddressArr = lanIpAddressStr?.split(',');
|
|
36
|
+
const lanIp = lanIpAddressArr?.[1]?.split('/')?.[0];
|
|
37
|
+
return lanIp;
|
|
38
|
+
|
|
39
|
+
// #endif
|
|
40
|
+
return '';
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export function getMicroAppIp() {
|
|
44
|
+
// #ifdef MP-WEIXIN
|
|
45
|
+
return new Promise((resolve) => {
|
|
46
|
+
uni.getLocalIPAddress({
|
|
47
|
+
success: (res) => {
|
|
48
|
+
resolve(res.localip);
|
|
49
|
+
},
|
|
50
|
+
fail: (err) => {
|
|
51
|
+
resolve('');
|
|
52
|
+
},
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
// #endif
|
|
56
|
+
|
|
57
|
+
return Promise.resolve('');
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export function getDeviceMac() {
|
|
61
|
+
var deviceMac = '';
|
|
62
|
+
var net: any = plus.android.importClass('java.net.NetworkInterface');
|
|
63
|
+
var wl0 = net.getByName('wlan0');
|
|
64
|
+
var macByte = wl0.getHardwareAddress();
|
|
65
|
+
for (var i = 0; i < macByte.length; i++) {
|
|
66
|
+
var tmp = '';
|
|
67
|
+
var num = macByte[i];
|
|
68
|
+
if (num < 0) {
|
|
69
|
+
tmp = (255 + num + 1).toString(16);
|
|
70
|
+
} else {
|
|
71
|
+
tmp = num.toString(16);
|
|
72
|
+
}
|
|
73
|
+
if (tmp.length == 1) {
|
|
74
|
+
tmp = '0' + tmp;
|
|
75
|
+
}
|
|
76
|
+
deviceMac += tmp;
|
|
77
|
+
}
|
|
78
|
+
// console.log(deviceMac);
|
|
79
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export function isNil(value: any): value is null | undefined {
|
|
2
|
+
return value === null || value === undefined;
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
export function isBoolean(value: any): value is boolean {
|
|
6
|
+
return typeof value === 'boolean';
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function isNumber(value: any): value is number {
|
|
10
|
+
return typeof value === 'number' && !isNaN(value);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function isObject(value: any): value is object {
|
|
14
|
+
return typeof value === 'object' && value !== null;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function isArray(value: any): value is any[] {
|
|
18
|
+
return Array.isArray(value);
|
|
19
|
+
}
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 自定义set函数 - 安全地设置嵌套对象属性
|
|
3
|
+
* @param obj 目标对象
|
|
4
|
+
* @param path 属性路径数组
|
|
5
|
+
* @param value 要设置的值
|
|
6
|
+
*/
|
|
7
|
+
export function setValueByPath(obj: any, path: string, value: any) {
|
|
8
|
+
if (obj == null || typeof path !== 'string') {
|
|
9
|
+
return;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
// 支持两种路径格式: "a.b.c" 或 "a[0].b"
|
|
13
|
+
const segments = path
|
|
14
|
+
|
|
15
|
+
.replace(/\[(\d+)\]/g, '.$1') // 将 a[0] 转换为 a.0
|
|
16
|
+
.split('.')
|
|
17
|
+
.filter((segment) => segment !== ''); // 过滤空段
|
|
18
|
+
|
|
19
|
+
if (segments.length === 0) {
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
let current = obj;
|
|
24
|
+
const lastIndex = segments.length - 1;
|
|
25
|
+
|
|
26
|
+
for (let i = 0; i < lastIndex; i++) {
|
|
27
|
+
const key = segments[i];
|
|
28
|
+
// 如果路径不存在且不是最后一个属性,创建对象或数组
|
|
29
|
+
if (!current[key]) {
|
|
30
|
+
// 判断下一级是否为数字索引(数组)
|
|
31
|
+
const nextKey = segments[i + 1];
|
|
32
|
+
current[key] = /^\d+$/.test(nextKey) ? [] : {};
|
|
33
|
+
}
|
|
34
|
+
current = current[key];
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// 设置最终值
|
|
38
|
+
current[segments[lastIndex]] = value;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function getValueByPath(obj: any, path: string, defaultValue?: any) {
|
|
42
|
+
if (obj == null || typeof path !== 'string') {
|
|
43
|
+
return defaultValue;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// 支持两种路径格式: "a.b.c" 或 "a[0].b"
|
|
47
|
+
const segments = path
|
|
48
|
+
.replace(/\[(\d+)\]/g, '.$1') // 将 a[0] 转换为 a.0
|
|
49
|
+
.split('.')
|
|
50
|
+
.filter((segment) => segment !== ''); // 过滤空段
|
|
51
|
+
|
|
52
|
+
let current = obj;
|
|
53
|
+
for (const segment of segments) {
|
|
54
|
+
if (current == null) {
|
|
55
|
+
return defaultValue;
|
|
56
|
+
}
|
|
57
|
+
current = current[segment];
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return current !== undefined ? current : defaultValue;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* 计算对象在内存中的近似大小
|
|
65
|
+
* @param obj 要计算大小的对象
|
|
66
|
+
* @returns 对象的近似大小(以字节为单位)
|
|
67
|
+
*/
|
|
68
|
+
export function calculateObjectSize(obj: any): number {
|
|
69
|
+
// 处理基本类型
|
|
70
|
+
if (obj === null || obj === undefined) {
|
|
71
|
+
return 0;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// 处理原始类型
|
|
75
|
+
const type = typeof obj;
|
|
76
|
+
if (type === 'boolean') {
|
|
77
|
+
return 4; // 布尔值通常占4字节
|
|
78
|
+
}
|
|
79
|
+
if (type === 'number') {
|
|
80
|
+
return 8; // JavaScript 数字是双精度浮点数(8字节)
|
|
81
|
+
}
|
|
82
|
+
if (type === 'string') {
|
|
83
|
+
// 假设每个 UTF-16 字符占2字节
|
|
84
|
+
return obj.length * 2;
|
|
85
|
+
}
|
|
86
|
+
if (type === 'symbol') {
|
|
87
|
+
// 符号在内存中的大小通常与引用大小相同
|
|
88
|
+
return 8;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// 处理日期对象
|
|
92
|
+
if (obj instanceof Date) {
|
|
93
|
+
return 8; // 日期内部表示为时间戳(8字节)
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// 处理正则表达式
|
|
97
|
+
if (obj instanceof RegExp) {
|
|
98
|
+
return calculateObjectSize(obj.source) + calculateObjectSize(obj.flags);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// 处理数组和普通对象
|
|
102
|
+
let totalSize = 0;
|
|
103
|
+
|
|
104
|
+
// 对象头部信息(简化估算)
|
|
105
|
+
totalSize += 24; // 假设对象头部占24字节
|
|
106
|
+
|
|
107
|
+
if (Array.isArray(obj)) {
|
|
108
|
+
// 数组的长度属性
|
|
109
|
+
totalSize += 4;
|
|
110
|
+
|
|
111
|
+
// 计算每个元素的大小
|
|
112
|
+
for (const item of obj) {
|
|
113
|
+
// 数组元素引用(假设每个引用占8字节)
|
|
114
|
+
totalSize += 8;
|
|
115
|
+
// 元素本身的大小
|
|
116
|
+
totalSize += calculateObjectSize(item);
|
|
117
|
+
}
|
|
118
|
+
} else {
|
|
119
|
+
// 计算对象每个属性的大小
|
|
120
|
+
for (const key in obj) {
|
|
121
|
+
if (obj.hasOwnProperty(key)) {
|
|
122
|
+
// 属性名的大小(假设每个字符占2字节)
|
|
123
|
+
totalSize += key.length * 2;
|
|
124
|
+
// 属性引用(假设每个引用占8字节)
|
|
125
|
+
totalSize += 8;
|
|
126
|
+
// 属性值的大小
|
|
127
|
+
totalSize += calculateObjectSize(obj[key]);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
return totalSize;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* 存储单位转换
|
|
137
|
+
* @param bytes 字节数
|
|
138
|
+
* @param options 转换选项
|
|
139
|
+
* @returns 转换后的存储大小字符串
|
|
140
|
+
*/
|
|
141
|
+
interface FormatStorageOptions {
|
|
142
|
+
precision?: number; // 精度,默认为2
|
|
143
|
+
useBinary?: boolean; // 是否使用二进制单位,默认为true
|
|
144
|
+
includeUnit?: boolean; // 是否包含单位,默认为true
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
export function formatStorageSize(
|
|
148
|
+
bytes: number,
|
|
149
|
+
options: FormatStorageOptions = {},
|
|
150
|
+
): string {
|
|
151
|
+
const { precision = 2, useBinary = true, includeUnit = true } = options;
|
|
152
|
+
|
|
153
|
+
if (bytes === 0) {
|
|
154
|
+
return includeUnit ? `0 Bytes` : `0`;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
const units = useBinary
|
|
158
|
+
? ['B', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB']
|
|
159
|
+
: ['B', 'KB', 'MB', 'GB', 'TB', 'PB'];
|
|
160
|
+
|
|
161
|
+
const base = useBinary ? 1024 : 1000;
|
|
162
|
+
let unitIndex = 0;
|
|
163
|
+
|
|
164
|
+
while (bytes >= base && unitIndex < units.length - 1) {
|
|
165
|
+
bytes /= base;
|
|
166
|
+
unitIndex++;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
const formattedSize = bytes.toFixed(precision);
|
|
170
|
+
return includeUnit ? `${formattedSize} ${units[unitIndex]}` : formattedSize;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* 序列化包含循环引用的对象
|
|
175
|
+
* @param {Object} obj - 要序列化的对象
|
|
176
|
+
* @param {WeakMap} [visited] - 用于记录已处理的对象(内部递归使用)
|
|
177
|
+
* @returns {string} - 序列化后的字符串
|
|
178
|
+
*/
|
|
179
|
+
export function serializeCircular(
|
|
180
|
+
obj: any,
|
|
181
|
+
options: { maxDepth: number; visited: WeakMap<any, true> } = {
|
|
182
|
+
maxDepth: 10,
|
|
183
|
+
visited: new WeakMap(),
|
|
184
|
+
},
|
|
185
|
+
): string {
|
|
186
|
+
const { maxDepth, visited } = options;
|
|
187
|
+
|
|
188
|
+
// 处理 null 和基本类型
|
|
189
|
+
if (obj === null || typeof obj !== 'object') {
|
|
190
|
+
return JSON.stringify(obj);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// 检测循环引用
|
|
194
|
+
if (visited.has(obj)) {
|
|
195
|
+
return '[Circular]';
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// 记录当前对象已处理
|
|
199
|
+
visited.set(obj, true);
|
|
200
|
+
|
|
201
|
+
// 处理日期对象
|
|
202
|
+
if (obj instanceof Date) {
|
|
203
|
+
return `"${obj.toISOString()}"`;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// 处理正则表达式
|
|
207
|
+
if (obj instanceof RegExp) {
|
|
208
|
+
return `/^${obj.source}$/${obj.flags}`;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// 检查是否达到最大深度
|
|
212
|
+
if (maxDepth <= 0) {
|
|
213
|
+
return typeof obj === 'object' ? '{}' : '[]';
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// 递归处理数组
|
|
217
|
+
if (Array.isArray(obj)) {
|
|
218
|
+
const serializedItems = obj.map((item) =>
|
|
219
|
+
serializeCircular(item, { maxDepth: maxDepth - 1, visited }),
|
|
220
|
+
);
|
|
221
|
+
return `[${serializedItems.join(', ')}]`;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
// 递归处理普通对象
|
|
225
|
+
const keys = Object.keys(obj);
|
|
226
|
+
const serializedProps = keys.map((key) => {
|
|
227
|
+
const value = serializeCircular(obj[key], {
|
|
228
|
+
maxDepth: maxDepth - 1,
|
|
229
|
+
visited,
|
|
230
|
+
});
|
|
231
|
+
return `"${key}": ${value}`;
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
return `{${serializedProps.join(', ')}}`;
|
|
235
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 将匹配到的字符串高亮显示
|
|
3
|
+
*
|
|
4
|
+
* @export
|
|
5
|
+
* @param {string} [str='']
|
|
6
|
+
* @param {string} [search='']
|
|
7
|
+
* @return {*}
|
|
8
|
+
*/
|
|
9
|
+
export function hightLight(str: string = '', search: string = '') {
|
|
10
|
+
if (!str) return '';
|
|
11
|
+
if (!search) return str;
|
|
12
|
+
|
|
13
|
+
// 转义特殊字符,确保正则表达式安全
|
|
14
|
+
const escapedSearch = search.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
15
|
+
const regex = new RegExp(escapedSearch, 'g');
|
|
16
|
+
|
|
17
|
+
const html = str.replace(
|
|
18
|
+
regex,
|
|
19
|
+
`<span style="color:#fff; background-color: var(--dev-tool-main-color);">${search}</span>`
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
return html;
|
|
23
|
+
}
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 获取当前页面地址
|
|
3
|
+
*
|
|
4
|
+
* @return {*}
|
|
5
|
+
*/
|
|
6
|
+
export function getCurrentPagePath() {
|
|
7
|
+
let pages = getCurrentPages();
|
|
8
|
+
let item = pages[pages.length - 1];
|
|
9
|
+
if (item && item.route) {
|
|
10
|
+
return item.route;
|
|
11
|
+
}
|
|
12
|
+
return '';
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/** 截图 */
|
|
16
|
+
export function screenshot() {
|
|
17
|
+
if (!plus) return;
|
|
18
|
+
if (!plus.nativeObj) return;
|
|
19
|
+
if (!plus.nativeObj.Bitmap) return;
|
|
20
|
+
|
|
21
|
+
let pages = getCurrentPages();
|
|
22
|
+
let page = pages[pages.length - 1];
|
|
23
|
+
|
|
24
|
+
let ws = page.$getAppWebview?.();
|
|
25
|
+
let bitmap = new plus.nativeObj.Bitmap('drawScreen');
|
|
26
|
+
|
|
27
|
+
// 将webview内容绘制到Bitmap对象中
|
|
28
|
+
ws?.draw(
|
|
29
|
+
bitmap,
|
|
30
|
+
() => {
|
|
31
|
+
// 保存图片到本地
|
|
32
|
+
bitmap.save(
|
|
33
|
+
`pictures/${Date.now()}.jpg`,
|
|
34
|
+
{
|
|
35
|
+
overwrite: true,
|
|
36
|
+
},
|
|
37
|
+
(res) => {
|
|
38
|
+
console.log('res.target' + res.target); // 图片地址
|
|
39
|
+
uni.showToast({
|
|
40
|
+
title: '截图成功:' + res.target,
|
|
41
|
+
icon: 'none',
|
|
42
|
+
duration: 60 * 1000,
|
|
43
|
+
});
|
|
44
|
+
bitmap.clear(); // 清除Bitmap对象
|
|
45
|
+
},
|
|
46
|
+
(error) => {
|
|
47
|
+
console.log('[DevTool] 截图失败:' + JSON.stringify(error)); // 保存失败信息
|
|
48
|
+
uni.showToast({
|
|
49
|
+
title: '[DevTool] 截图失败:' + JSON.stringify(error),
|
|
50
|
+
icon: 'none',
|
|
51
|
+
duration: 60 * 1000,
|
|
52
|
+
});
|
|
53
|
+
bitmap.clear(); // 清除Bitmap对象
|
|
54
|
+
},
|
|
55
|
+
);
|
|
56
|
+
// bitmap.clear(); // 清除Bitmap对象
|
|
57
|
+
},
|
|
58
|
+
(error) => {
|
|
59
|
+
console.log('[DevTool] 绘制失败:' + JSON.stringify(error)); // 绘制失败
|
|
60
|
+
uni.showToast({
|
|
61
|
+
title: '绘制失败:' + JSON.stringify(error),
|
|
62
|
+
icon: 'none',
|
|
63
|
+
duration: 60 * 1000,
|
|
64
|
+
});
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
check: true, // 设置为检测白屏
|
|
68
|
+
},
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// 截屏函数
|
|
73
|
+
export function captureScreen(option: { success?: () => void }) {
|
|
74
|
+
const ctx = uni.createCanvasContext('fullscreenCanvas');
|
|
75
|
+
const { windowWidth, windowHeight } = uni.getSystemInfoSync();
|
|
76
|
+
// 绘制需要截屏的内容(示例:绘制一个矩形)
|
|
77
|
+
ctx.setFillStyle('#ffffff');
|
|
78
|
+
ctx.fillRect(0, 0, windowWidth, windowHeight); // 画布尺寸
|
|
79
|
+
ctx.setFillStyle('#000000');
|
|
80
|
+
ctx.setFontSize(20);
|
|
81
|
+
ctx.fillText('这是截屏内容', 100, 100);
|
|
82
|
+
|
|
83
|
+
ctx.draw(false, () => {
|
|
84
|
+
// 生成图片
|
|
85
|
+
uni.canvasToTempFilePath({
|
|
86
|
+
canvasId: 'fullscreenCanvas',
|
|
87
|
+
width: windowWidth,
|
|
88
|
+
height: windowHeight,
|
|
89
|
+
destWidth: windowWidth * 2, // 提高清晰度
|
|
90
|
+
destHeight: windowHeight * 2,
|
|
91
|
+
fileType: 'png',
|
|
92
|
+
success: (res) => {
|
|
93
|
+
console.log('res: ', res);
|
|
94
|
+
console.log('全屏截屏成功:', res.tempFilePath);
|
|
95
|
+
},
|
|
96
|
+
fail: (err) => {
|
|
97
|
+
console.error('全屏截屏失败:', err);
|
|
98
|
+
},
|
|
99
|
+
});
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
type Primitive = string | number | boolean | null | undefined | symbol | bigint;
|
|
104
|
+
|
|
105
|
+
function isPrimitive(value: unknown): value is Primitive {
|
|
106
|
+
return (
|
|
107
|
+
value === null || (typeof value !== 'object' && typeof value !== 'function')
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export interface DeepEqualOptions {
|
|
112
|
+
maxDepth?: number;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export function deepEqual(
|
|
116
|
+
a: unknown,
|
|
117
|
+
b: unknown,
|
|
118
|
+
options: DeepEqualOptions = { maxDepth: 10 },
|
|
119
|
+
): boolean {
|
|
120
|
+
const { maxDepth = 10 } = options;
|
|
121
|
+
const seen = new WeakMap<object, number>();
|
|
122
|
+
let nextStamp = 1;
|
|
123
|
+
return deepEqualInternal(a, b, seen, () => nextStamp++, 1, maxDepth);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function deepEqualInternal(
|
|
127
|
+
a: unknown,
|
|
128
|
+
b: unknown,
|
|
129
|
+
seen: WeakMap<object, number>,
|
|
130
|
+
getNextStamp: () => number,
|
|
131
|
+
currentDepth: number,
|
|
132
|
+
maxDepth: number,
|
|
133
|
+
): boolean {
|
|
134
|
+
// 超过最大深度
|
|
135
|
+
if (currentDepth > maxDepth) return false;
|
|
136
|
+
|
|
137
|
+
// 处理原始值
|
|
138
|
+
if (isPrimitive(a) || isPrimitive(b)) {
|
|
139
|
+
// 特殊处理 NaN(两个 NaN 被视为相等)
|
|
140
|
+
if (typeof a === 'number' && typeof b === 'number' && isNaN(a) && isNaN(b))
|
|
141
|
+
return true;
|
|
142
|
+
return a === b;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// 处理对象和数组
|
|
146
|
+
if (a instanceof Date && b instanceof Date)
|
|
147
|
+
return a.getTime() === b.getTime();
|
|
148
|
+
if (a instanceof RegExp && b instanceof RegExp)
|
|
149
|
+
return a.toString() === b.toString();
|
|
150
|
+
|
|
151
|
+
// 确保都是对象
|
|
152
|
+
if (
|
|
153
|
+
typeof a !== 'object' ||
|
|
154
|
+
typeof b !== 'object' ||
|
|
155
|
+
a === null ||
|
|
156
|
+
b === null
|
|
157
|
+
)
|
|
158
|
+
return false;
|
|
159
|
+
|
|
160
|
+
// 检查循环引用
|
|
161
|
+
const aStamp = seen.get(a as object);
|
|
162
|
+
const bStamp = seen.get(b as object);
|
|
163
|
+
|
|
164
|
+
if (aStamp !== undefined || bStamp !== undefined) {
|
|
165
|
+
return aStamp === bStamp;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// 标记已访问对象
|
|
169
|
+
const stamp = getNextStamp();
|
|
170
|
+
seen.set(a as object, stamp);
|
|
171
|
+
seen.set(b as object, stamp);
|
|
172
|
+
|
|
173
|
+
// 获取所有属性(包括不可枚举属性,但排除 Symbol 类型)
|
|
174
|
+
const aKeys = Object.getOwnPropertyNames(a);
|
|
175
|
+
const bKeys = Object.getOwnPropertyNames(b);
|
|
176
|
+
|
|
177
|
+
// 检查属性数量是否相同
|
|
178
|
+
if (aKeys.length !== bKeys.length) return false;
|
|
179
|
+
|
|
180
|
+
// 检查属性值是否相同
|
|
181
|
+
for (const key of aKeys) {
|
|
182
|
+
if (!bKeys.includes(key)) return false;
|
|
183
|
+
// @ts-ignore 允许索引访问
|
|
184
|
+
if (
|
|
185
|
+
!deepEqualInternal(
|
|
186
|
+
(a as any)?.[key],
|
|
187
|
+
(b as any)?.[key],
|
|
188
|
+
seen,
|
|
189
|
+
getNextStamp,
|
|
190
|
+
currentDepth + 1,
|
|
191
|
+
maxDepth,
|
|
192
|
+
)
|
|
193
|
+
)
|
|
194
|
+
return false;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
return true;
|
|
198
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "vite-uni-dev-tool",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "vite-uni-dev-tool, debug, uni-app, 一处编写,到处调试",
|
|
5
|
+
"repositories": [
|
|
6
|
+
{
|
|
7
|
+
"type": "gitee",
|
|
8
|
+
"url": "https://gitee.com/cloud_l/vite-uni-dev-tool.git"
|
|
9
|
+
}
|
|
10
|
+
],
|
|
11
|
+
"license": "MIT",
|
|
12
|
+
"main": "dev/index.js",
|
|
13
|
+
"types": "dev/index.d.ts",
|
|
14
|
+
"files": [
|
|
15
|
+
"./dev/"
|
|
16
|
+
],
|
|
17
|
+
"scripts": {
|
|
18
|
+
"build:lib": "vite build && vue-tsc"
|
|
19
|
+
},
|
|
20
|
+
"peerDependencies": {
|
|
21
|
+
"vue": ">=3.4.21",
|
|
22
|
+
"@dcloudio/uni-app": ">=3.0.0-4020920240930001",
|
|
23
|
+
"@dcloudio/uni-h5": ">=3.0.0-4020920240930001",
|
|
24
|
+
"@dcloudio/uni-components": "3.0.0-4020920240930001"
|
|
25
|
+
},
|
|
26
|
+
"dependencies": {},
|
|
27
|
+
"devDependencies": {},
|
|
28
|
+
"authors": [
|
|
29
|
+
"1264174856@qq.com"
|
|
30
|
+
],
|
|
31
|
+
"publishConfig": {
|
|
32
|
+
"access": "public"
|
|
33
|
+
}
|
|
34
|
+
}
|