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
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
JSONDataType,
|
|
3
|
+
JSONFlattenOptions,
|
|
4
|
+
JSONFlattenReturnType
|
|
5
|
+
} from "../type";
|
|
6
|
+
|
|
7
|
+
export function emitError(message: string): void {
|
|
8
|
+
throw new Error(`[JsonPretty] ${message}`);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function getDataType(value: unknown): string {
|
|
12
|
+
return Object.prototype.toString.call(value).slice(8, -1).toLowerCase();
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function jsonFlatten(
|
|
16
|
+
data: JSONDataType,
|
|
17
|
+
path = "root",
|
|
18
|
+
level = 0,
|
|
19
|
+
options?: JSONFlattenOptions
|
|
20
|
+
): JSONFlattenReturnType[] {
|
|
21
|
+
const {
|
|
22
|
+
key,
|
|
23
|
+
index,
|
|
24
|
+
type = "content",
|
|
25
|
+
showComma = false,
|
|
26
|
+
length = 1
|
|
27
|
+
} = options || ({} as JSONFlattenOptions);
|
|
28
|
+
const dataType = getDataType(data);
|
|
29
|
+
|
|
30
|
+
if (dataType === "array") {
|
|
31
|
+
const inner = arrFlat(
|
|
32
|
+
(data as JSONDataType[]).map((item, idx, arr) =>
|
|
33
|
+
jsonFlatten(item, `${path}[${idx}]`, level + 1, {
|
|
34
|
+
index: idx,
|
|
35
|
+
showComma: idx !== arr.length - 1,
|
|
36
|
+
length,
|
|
37
|
+
type
|
|
38
|
+
})
|
|
39
|
+
)
|
|
40
|
+
) as JSONFlattenReturnType[];
|
|
41
|
+
return [
|
|
42
|
+
jsonFlatten("[", path, level, {
|
|
43
|
+
showComma: false,
|
|
44
|
+
key,
|
|
45
|
+
length: (data as unknown[]).length,
|
|
46
|
+
type: "arrayStart"
|
|
47
|
+
})[0]
|
|
48
|
+
].concat(
|
|
49
|
+
inner,
|
|
50
|
+
jsonFlatten("]", path, level, {
|
|
51
|
+
showComma,
|
|
52
|
+
length: (data as unknown[]).length,
|
|
53
|
+
type: "arrayEnd"
|
|
54
|
+
})[0]
|
|
55
|
+
);
|
|
56
|
+
} else if (dataType === "object") {
|
|
57
|
+
const keys = Object.keys(data as Record<string, JSONDataType>);
|
|
58
|
+
const inner = arrFlat(
|
|
59
|
+
keys.map((objKey, idx, arr) =>
|
|
60
|
+
jsonFlatten(
|
|
61
|
+
(data as Record<string, JSONDataType>)[objKey],
|
|
62
|
+
/^[a-zA-Z_]\w*$/.test(objKey)
|
|
63
|
+
? `${path}.${objKey}`
|
|
64
|
+
: `${path}["${objKey}"]`,
|
|
65
|
+
level + 1,
|
|
66
|
+
{
|
|
67
|
+
key: objKey,
|
|
68
|
+
showComma: idx !== arr.length - 1,
|
|
69
|
+
length,
|
|
70
|
+
type
|
|
71
|
+
}
|
|
72
|
+
)
|
|
73
|
+
)
|
|
74
|
+
) as JSONFlattenReturnType[];
|
|
75
|
+
return [
|
|
76
|
+
jsonFlatten("{", path, level, {
|
|
77
|
+
showComma: false,
|
|
78
|
+
key,
|
|
79
|
+
index,
|
|
80
|
+
length: keys.length,
|
|
81
|
+
type: "objectStart"
|
|
82
|
+
})[0]
|
|
83
|
+
].concat(
|
|
84
|
+
inner,
|
|
85
|
+
jsonFlatten("}", path, level, {
|
|
86
|
+
showComma,
|
|
87
|
+
length: keys.length,
|
|
88
|
+
type: "objectEnd"
|
|
89
|
+
})[0]
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
return [
|
|
94
|
+
{
|
|
95
|
+
content: data as JSONFlattenReturnType["content"],
|
|
96
|
+
level,
|
|
97
|
+
key,
|
|
98
|
+
index,
|
|
99
|
+
path,
|
|
100
|
+
showComma,
|
|
101
|
+
length,
|
|
102
|
+
type
|
|
103
|
+
}
|
|
104
|
+
];
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export function arrFlat<T extends unknown[]>(arr: T): unknown[] {
|
|
108
|
+
if (typeof Array.prototype.flat === "function") {
|
|
109
|
+
return arr.flat();
|
|
110
|
+
}
|
|
111
|
+
const stack = [...arr];
|
|
112
|
+
const result = [];
|
|
113
|
+
while (stack.length) {
|
|
114
|
+
const first = stack.shift();
|
|
115
|
+
if (Array.isArray(first)) {
|
|
116
|
+
stack.unshift(...first);
|
|
117
|
+
} else {
|
|
118
|
+
result.push(first);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
return result;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export function cloneDeep<T extends unknown>(
|
|
125
|
+
source: T,
|
|
126
|
+
hash = new WeakMap()
|
|
127
|
+
): T {
|
|
128
|
+
if (source === null || source === undefined) return source;
|
|
129
|
+
if (source instanceof Date) return new Date(source) as T;
|
|
130
|
+
if (source instanceof RegExp) return new RegExp(source) as T;
|
|
131
|
+
if (typeof source !== "object") return source;
|
|
132
|
+
if (hash.get(source as Record<string, unknown>))
|
|
133
|
+
return hash.get(source as Record<string, unknown>);
|
|
134
|
+
|
|
135
|
+
if (Array.isArray(source)) {
|
|
136
|
+
const output = source.map((item) => cloneDeep(item, hash));
|
|
137
|
+
hash.set(source, output);
|
|
138
|
+
return output as T;
|
|
139
|
+
}
|
|
140
|
+
const output = {} as T;
|
|
141
|
+
for (const key in source) {
|
|
142
|
+
output[key] = cloneDeep(source[key], hash);
|
|
143
|
+
}
|
|
144
|
+
hash.set(source as Record<string, unknown>, output);
|
|
145
|
+
return output as T;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
export function stringToAutoType(source: string): unknown {
|
|
149
|
+
let value;
|
|
150
|
+
if (source === "null") value = null;
|
|
151
|
+
else if (source === "undefined") value = undefined;
|
|
152
|
+
else if (source === "true") value = true;
|
|
153
|
+
else if (source === "false") value = false;
|
|
154
|
+
else if (
|
|
155
|
+
source[0] + source[source.length - 1] === '""' ||
|
|
156
|
+
source[0] + source[source.length - 1] === "''"
|
|
157
|
+
) {
|
|
158
|
+
value = source.slice(1, -1);
|
|
159
|
+
} else if (
|
|
160
|
+
(typeof Number(source) === "number" && !isNaN(Number(source))) ||
|
|
161
|
+
source === "NaN"
|
|
162
|
+
) {
|
|
163
|
+
value = Number(source);
|
|
164
|
+
} else {
|
|
165
|
+
value = source;
|
|
166
|
+
}
|
|
167
|
+
return value;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
export function isFunction(value: unknown): value is Function {
|
|
171
|
+
return typeof value === "function";
|
|
172
|
+
}
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<view class="network-detail">
|
|
3
|
+
<view class="network-detail-control">
|
|
4
|
+
<Tag
|
|
5
|
+
mode="info"
|
|
6
|
+
v-for="item in selectItems"
|
|
7
|
+
:active="item.value === currentSelect"
|
|
8
|
+
:key="item.value"
|
|
9
|
+
@click="onSelect(item)"
|
|
10
|
+
>
|
|
11
|
+
{{ item.label }}
|
|
12
|
+
</Tag>
|
|
13
|
+
<CloseButton style="margin-left: auto" @click="onClose" />
|
|
14
|
+
</view>
|
|
15
|
+
|
|
16
|
+
<view class="network-detail-header" v-if="currentSelect === 'header'">
|
|
17
|
+
<view class="network-detail-title">常规</view>
|
|
18
|
+
<view class="net-detail-item">
|
|
19
|
+
<view>请求url:</view>
|
|
20
|
+
<view>{{ network.url }}</view>
|
|
21
|
+
</view>
|
|
22
|
+
<view class="net-detail-item">
|
|
23
|
+
<view>请求方法:</view>
|
|
24
|
+
<Tag mode="info">{{ network.method }}</Tag>
|
|
25
|
+
</view>
|
|
26
|
+
<view class="net-detail-item">
|
|
27
|
+
<view>状态代码:</view>
|
|
28
|
+
{{ network.status }}
|
|
29
|
+
</view>
|
|
30
|
+
<view class="network-detail-title">请求头</view>
|
|
31
|
+
<view
|
|
32
|
+
class="net-detail-item"
|
|
33
|
+
v-for="item in network.headers.requestHeader"
|
|
34
|
+
:key="item.key"
|
|
35
|
+
>
|
|
36
|
+
<view>{{ item.key }}:</view>
|
|
37
|
+
{{ item.value }}
|
|
38
|
+
</view>
|
|
39
|
+
<view class="network-detail-title">响应头</view>
|
|
40
|
+
<view
|
|
41
|
+
class="net-detail-item"
|
|
42
|
+
v-for="item in network.headers.responseHeader"
|
|
43
|
+
:key="item.key"
|
|
44
|
+
>
|
|
45
|
+
<view>{{ item.key }}:</view>
|
|
46
|
+
{{ item.value }}
|
|
47
|
+
</view>
|
|
48
|
+
</view>
|
|
49
|
+
|
|
50
|
+
<template v-if="currentSelect === 'payload'">
|
|
51
|
+
<template v-if="payload?.type === 'object'">
|
|
52
|
+
<JsonPretty :data="payload.value" />
|
|
53
|
+
</template>
|
|
54
|
+
<view
|
|
55
|
+
v-else-if="payload?.type === 'string'"
|
|
56
|
+
class="network-detail-payload"
|
|
57
|
+
>
|
|
58
|
+
{{ payload.value }}
|
|
59
|
+
</view>
|
|
60
|
+
<Empty v-else />
|
|
61
|
+
</template>
|
|
62
|
+
|
|
63
|
+
<template v-if="currentSelect === 'response'">
|
|
64
|
+
<template v-if="response?.type === 'object'">
|
|
65
|
+
<JsonPretty :data="response.value" virtual />
|
|
66
|
+
</template>
|
|
67
|
+
<view
|
|
68
|
+
v-else-if="response?.type === 'string'"
|
|
69
|
+
class="network-detail-payload"
|
|
70
|
+
>
|
|
71
|
+
{{ response.value }}
|
|
72
|
+
</view>
|
|
73
|
+
<Empty v-else />
|
|
74
|
+
</template>
|
|
75
|
+
</view>
|
|
76
|
+
</template>
|
|
77
|
+
<script lang="ts" setup>
|
|
78
|
+
import { ref, computed } from 'vue';
|
|
79
|
+
import JsonPretty from '../JsonPretty/index.vue';
|
|
80
|
+
import Tag from '../Tag/index.vue';
|
|
81
|
+
import Empty from '../Empty/index.vue';
|
|
82
|
+
import CloseButton from '../CloseButton/index.vue';
|
|
83
|
+
import type { DevTool } from '../../type';
|
|
84
|
+
const props = defineProps<{ network: DevTool.NetworkItem }>();
|
|
85
|
+
const emit = defineEmits<{ (e: 'close'): void }>();
|
|
86
|
+
const selectItems = [
|
|
87
|
+
{
|
|
88
|
+
label: 'header',
|
|
89
|
+
value: 'header',
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
label: 'payload',
|
|
93
|
+
value: 'payload',
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
label: 'response',
|
|
97
|
+
value: 'response',
|
|
98
|
+
},
|
|
99
|
+
];
|
|
100
|
+
const currentSelect = ref('header');
|
|
101
|
+
|
|
102
|
+
const payload = computed(() => {
|
|
103
|
+
try {
|
|
104
|
+
if (props.network.payload) {
|
|
105
|
+
return {
|
|
106
|
+
value: JSON.parse(props.network.payload),
|
|
107
|
+
type: 'object',
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
return {
|
|
111
|
+
value: {},
|
|
112
|
+
type: 'empty',
|
|
113
|
+
};
|
|
114
|
+
} catch (error) {
|
|
115
|
+
return {
|
|
116
|
+
value: props.network.payload,
|
|
117
|
+
type: props.network.payload ? 'string' : 'empty',
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
const response = computed(() => {
|
|
123
|
+
try {
|
|
124
|
+
if (props.network.response) {
|
|
125
|
+
return {
|
|
126
|
+
value: JSON.parse(JSON.stringify(props.network.response)),
|
|
127
|
+
type: 'object',
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
return {
|
|
131
|
+
value: {},
|
|
132
|
+
type: 'empty',
|
|
133
|
+
};
|
|
134
|
+
} catch (error) {
|
|
135
|
+
return {
|
|
136
|
+
value: props.network.response,
|
|
137
|
+
type: props.network.response ? 'string' : 'empty',
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
function onSelect(item: { label: string; value: string }) {
|
|
143
|
+
currentSelect.value = item.value;
|
|
144
|
+
}
|
|
145
|
+
function onClose() {
|
|
146
|
+
emit('close');
|
|
147
|
+
}
|
|
148
|
+
</script>
|
|
149
|
+
<style scoped>
|
|
150
|
+
.network-detail {
|
|
151
|
+
position: fixed;
|
|
152
|
+
width: 100vw;
|
|
153
|
+
height: 100vh;
|
|
154
|
+
z-index: 10000;
|
|
155
|
+
top: 0;
|
|
156
|
+
left: 0;
|
|
157
|
+
padding: 0 16px;
|
|
158
|
+
/* #ifdef H5 */
|
|
159
|
+
padding: 50px 16px;
|
|
160
|
+
/* #endif */
|
|
161
|
+
|
|
162
|
+
background-color: rgba(255, 255, 255, 0.95);
|
|
163
|
+
box-sizing: border-box;
|
|
164
|
+
}
|
|
165
|
+
.network-detail .network-detail-control {
|
|
166
|
+
display: flex;
|
|
167
|
+
align-items: center;
|
|
168
|
+
margin-bottom: 4px;
|
|
169
|
+
gap: 12px;
|
|
170
|
+
height: 32px;
|
|
171
|
+
border-bottom: 1px solid transparent;
|
|
172
|
+
box-sizing: border-box;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
.network-detail .network-detail-control :deep(.tag) {
|
|
176
|
+
margin-right: 16px;
|
|
177
|
+
}
|
|
178
|
+
.network-detail .network-detail-control :deep(.tag):last-child {
|
|
179
|
+
margin-right: 0;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
.network-detail .network-detail-header .net-detail-item {
|
|
183
|
+
display: flex;
|
|
184
|
+
align-items: center;
|
|
185
|
+
min-height: 28px;
|
|
186
|
+
word-break: break-all;
|
|
187
|
+
}
|
|
188
|
+
.network-detail .network-detail-header .net-detail-item > view:first-child {
|
|
189
|
+
white-space: nowrap;
|
|
190
|
+
margin-right: 8px;
|
|
191
|
+
color: #616161;
|
|
192
|
+
}
|
|
193
|
+
.network-detail .network-detail-payload {
|
|
194
|
+
word-break: break-all;
|
|
195
|
+
max-width: 100%;
|
|
196
|
+
}
|
|
197
|
+
</style>
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<view class="network-item">
|
|
3
|
+
<view class="network-url-row">
|
|
4
|
+
<Tag mode="info">{{ network.method }}</Tag>
|
|
5
|
+
|
|
6
|
+
<view class="network-url" v-html="network.url"> </view>
|
|
7
|
+
|
|
8
|
+
<Tag
|
|
9
|
+
mode="main"
|
|
10
|
+
class="network-detail-icon"
|
|
11
|
+
@click="showDetail = !showDetail"
|
|
12
|
+
>详情</Tag
|
|
13
|
+
>
|
|
14
|
+
</view>
|
|
15
|
+
<view class="network-info">
|
|
16
|
+
<view>
|
|
17
|
+
<Tag
|
|
18
|
+
:mode="
|
|
19
|
+
network.status === 'pending'
|
|
20
|
+
? 'info'
|
|
21
|
+
: /[4,5]\d{2,}/.test(network.status + '') ||
|
|
22
|
+
network.status === 'error'
|
|
23
|
+
? 'error'
|
|
24
|
+
: 'success'
|
|
25
|
+
"
|
|
26
|
+
>{{ network.status }}</Tag
|
|
27
|
+
>
|
|
28
|
+
</view>
|
|
29
|
+
<!-- <view>{{ network.status }}</view> -->
|
|
30
|
+
<view>{{ network.time }}</view>
|
|
31
|
+
<view>{{ network.size }}</view>
|
|
32
|
+
<view
|
|
33
|
+
>开始:
|
|
34
|
+
{{
|
|
35
|
+
network.startTime
|
|
36
|
+
? formatDate(network.startTime, 'HH:mm:ss')
|
|
37
|
+
: '--:--:--'
|
|
38
|
+
}}</view
|
|
39
|
+
>
|
|
40
|
+
<view>
|
|
41
|
+
结束:
|
|
42
|
+
{{
|
|
43
|
+
network.endTime ? formatDate(network.endTime, 'HH:mm:ss') : '--:--:--'
|
|
44
|
+
}}
|
|
45
|
+
</view>
|
|
46
|
+
</view>
|
|
47
|
+
</view>
|
|
48
|
+
<!-- <Transition name="slide-fade"> -->
|
|
49
|
+
<NetworkDetail v-if="showDetail" :network="network" @close="onClose" />
|
|
50
|
+
<!-- </Transition> -->
|
|
51
|
+
</template>
|
|
52
|
+
|
|
53
|
+
<script lang="ts" setup>
|
|
54
|
+
import { ref } from 'vue';
|
|
55
|
+
import Tag from '../Tag/index.vue';
|
|
56
|
+
import NetworkDetail from './NetworkDetail.vue';
|
|
57
|
+
import { formatDate } from '../../utils';
|
|
58
|
+
import type { DevTool } from '../../type';
|
|
59
|
+
defineProps<{
|
|
60
|
+
network: DevTool.NetworkItem;
|
|
61
|
+
}>();
|
|
62
|
+
const showDetail = ref(false);
|
|
63
|
+
function onClose() {
|
|
64
|
+
showDetail.value = false;
|
|
65
|
+
}
|
|
66
|
+
</script>
|
|
67
|
+
<style scoped>
|
|
68
|
+
.network-item {
|
|
69
|
+
padding: 16px;
|
|
70
|
+
border-bottom: 1px solid var(--dev-tool-border-color);
|
|
71
|
+
font-size: var(--dev-tool-base-font-size);
|
|
72
|
+
}
|
|
73
|
+
.network-item .network-url-row {
|
|
74
|
+
display: flex;
|
|
75
|
+
align-items: center;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
.network-item .network-url-row .network-url {
|
|
79
|
+
margin-left: 4px;
|
|
80
|
+
flex: 1;
|
|
81
|
+
overflow: hidden;
|
|
82
|
+
text-overflow: ellipsis;
|
|
83
|
+
}
|
|
84
|
+
.network-item .network-url-row .network-detail-icon {
|
|
85
|
+
margin-left: auto;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
.network-item .network-info {
|
|
89
|
+
display: flex;
|
|
90
|
+
align-items: center;
|
|
91
|
+
justify-content: space-between;
|
|
92
|
+
margin-top: 4px;
|
|
93
|
+
color: #616161;
|
|
94
|
+
}
|
|
95
|
+
.slide-fade-enter-active {
|
|
96
|
+
transition: all 0.8s ease-out;
|
|
97
|
+
}
|
|
98
|
+
.slide-fade-leave-active {
|
|
99
|
+
transition: all 0.8s cubic-bezier(1, 0.5, 0.8, 1);
|
|
100
|
+
}
|
|
101
|
+
.slide-fade-enter-from,
|
|
102
|
+
.slide-fade-leave-to {
|
|
103
|
+
transform: translateY(20px);
|
|
104
|
+
opacity: 0;
|
|
105
|
+
}
|
|
106
|
+
</style>
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<view class="network-content">
|
|
3
|
+
<view class="network-control">
|
|
4
|
+
<FilterInput
|
|
5
|
+
:modelValue="modelValue"
|
|
6
|
+
placeholder="查询url"
|
|
7
|
+
@search="emit('search', $event)"
|
|
8
|
+
@update:modelValue="emit('update:modelValue', $event)"
|
|
9
|
+
/>
|
|
10
|
+
<Tag
|
|
11
|
+
v-for="item in networkFilterItems"
|
|
12
|
+
:mode="item.mode"
|
|
13
|
+
:key="item.value"
|
|
14
|
+
:active="item.value === currentNetworkType"
|
|
15
|
+
@click="onChoose(item.value)"
|
|
16
|
+
>
|
|
17
|
+
{{ item.label }}
|
|
18
|
+
</Tag>
|
|
19
|
+
</view>
|
|
20
|
+
<view class="network-list">
|
|
21
|
+
<NetworkItem
|
|
22
|
+
v-for="item in networkList"
|
|
23
|
+
:network="item"
|
|
24
|
+
:key="item.index"
|
|
25
|
+
/>
|
|
26
|
+
<Empty v-if="!networkList || networkList.length === 0" />
|
|
27
|
+
</view>
|
|
28
|
+
</view>
|
|
29
|
+
</template>
|
|
30
|
+
<script lang="ts" setup>
|
|
31
|
+
import Tag from '../Tag/index.vue';
|
|
32
|
+
import NetworkItem from './NetworkItem.vue';
|
|
33
|
+
import Empty from '../Empty/index.vue';
|
|
34
|
+
import FilterInput from '../FilterInput/index.vue';
|
|
35
|
+
import type { DevTool } from '../../type';
|
|
36
|
+
defineProps<{
|
|
37
|
+
currentNetworkType: string;
|
|
38
|
+
networkList: DevTool.NetworkItem[];
|
|
39
|
+
modelValue: string;
|
|
40
|
+
}>();
|
|
41
|
+
|
|
42
|
+
const emit = defineEmits<{
|
|
43
|
+
(e: 'choose', type: string): void;
|
|
44
|
+
(e: 'update:modelValue', value: string): void;
|
|
45
|
+
(e: 'search', value: string): void;
|
|
46
|
+
}>();
|
|
47
|
+
const networkFilterItems = [
|
|
48
|
+
{
|
|
49
|
+
label: '全部',
|
|
50
|
+
value: 'all',
|
|
51
|
+
mode: 'all',
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
label: 'get',
|
|
55
|
+
value: 'GET',
|
|
56
|
+
mode: 'info',
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
label: 'post',
|
|
60
|
+
value: 'POST',
|
|
61
|
+
mode: 'info',
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
label: 'put',
|
|
65
|
+
value: 'PUT',
|
|
66
|
+
mode: 'info',
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
label: 'del',
|
|
70
|
+
value: 'DELETE',
|
|
71
|
+
mode: 'info',
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
label: 'error',
|
|
75
|
+
value: 'error',
|
|
76
|
+
mode: 'error',
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
label: '清除',
|
|
80
|
+
value: 'clear',
|
|
81
|
+
mode: 'clear',
|
|
82
|
+
},
|
|
83
|
+
];
|
|
84
|
+
|
|
85
|
+
function onChoose(type: string) {
|
|
86
|
+
emit('choose', type);
|
|
87
|
+
}
|
|
88
|
+
</script>
|
|
89
|
+
<style scoped>
|
|
90
|
+
.network-content {
|
|
91
|
+
height: 100%;
|
|
92
|
+
font-size: var(--dev-tool-base-font-size);
|
|
93
|
+
}
|
|
94
|
+
.network-list {
|
|
95
|
+
height: calc(100% - 32px);
|
|
96
|
+
overflow: auto;
|
|
97
|
+
}
|
|
98
|
+
.network-control {
|
|
99
|
+
display: flex;
|
|
100
|
+
align-items: center;
|
|
101
|
+
justify-content: space-between;
|
|
102
|
+
gap: 8px;
|
|
103
|
+
padding: 0 16px;
|
|
104
|
+
height: 32px;
|
|
105
|
+
border-bottom: 1px solid var(--dev-tool-border-color);
|
|
106
|
+
box-sizing: border-box;
|
|
107
|
+
}
|
|
108
|
+
</style>
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<view class="pinia-content">
|
|
3
|
+
<JsonPretty
|
|
4
|
+
:data="piniaList"
|
|
5
|
+
showLength
|
|
6
|
+
editable
|
|
7
|
+
v-if="showJson"
|
|
8
|
+
@update:data="onUpdateData"
|
|
9
|
+
@nodeClick="onNodeClick"
|
|
10
|
+
/>
|
|
11
|
+
<Empty v-else />
|
|
12
|
+
</view>
|
|
13
|
+
</template>
|
|
14
|
+
<script lang="ts" setup>
|
|
15
|
+
import { computed } from 'vue';
|
|
16
|
+
import JsonPretty from '../JsonPretty/index.vue';
|
|
17
|
+
import Empty from '../Empty/index.vue';
|
|
18
|
+
import { getValueByPath } from '../../utils';
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
const props = defineProps<{
|
|
22
|
+
piniaList: Record<string, any>;
|
|
23
|
+
}>();
|
|
24
|
+
const emit = defineEmits<{
|
|
25
|
+
(e: 'update:piniaList', data: Record<string, any>): void;
|
|
26
|
+
(e: 'diffValue', value: any): void;
|
|
27
|
+
}>();
|
|
28
|
+
const showJson = computed(() => {
|
|
29
|
+
try {
|
|
30
|
+
const str = JSON.stringify(props.piniaList);
|
|
31
|
+
if (typeof props.piniaList === 'object' && (str === '' || str === '{}')) {
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
return true;
|
|
35
|
+
} catch (error) {
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
let currentSelect: any;
|
|
41
|
+
function onUpdateData(data: Record<string, any>) {
|
|
42
|
+
try {
|
|
43
|
+
const keys = currentSelect?.path?.slice(5);
|
|
44
|
+
if (!keys) return;
|
|
45
|
+
const newData = getValueByPath(data, keys);
|
|
46
|
+
|
|
47
|
+
emit('update:piniaList', data);
|
|
48
|
+
emit('diffValue', {
|
|
49
|
+
[keys]: newData
|
|
50
|
+
});
|
|
51
|
+
} catch (error) {
|
|
52
|
+
console.log('error: ', error);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
function onNodeClick(node: any) {
|
|
56
|
+
currentSelect = node;
|
|
57
|
+
}
|
|
58
|
+
</script>
|
|
59
|
+
<style scoped>
|
|
60
|
+
.pinia-content {
|
|
61
|
+
padding: 16px;
|
|
62
|
+
font-size: var(--dev-tool-base-font-size);
|
|
63
|
+
}
|
|
64
|
+
</style>
|