vite-uni-dev-tool 0.0.16 → 0.0.17

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 (37) hide show
  1. package/README.md +6 -0
  2. package/dist/devIntercept/index.d.ts.map +1 -1
  3. package/dist/devIntercept/index.js +139 -137
  4. package/dist/devStore/index.js +1 -1
  5. package/dist/type.d.ts +5 -1
  6. package/dist/type.d.ts.map +1 -1
  7. package/dist/v2/{CloseButton → CircularButton}/index.vue +5 -2
  8. package/dist/v2/NetworkList/NetworkDetail.vue +3 -3
  9. package/dist/v2/NetworkList/NetworkItem.vue +5 -3
  10. package/dist/v2/SettingList/index.vue +1 -1
  11. package/dist/v2/SourceCode/index.vue +3 -3
  12. package/dist/v2/StorageList/index.vue +7 -3
  13. package/dist/v2/Tabs/index.vue +3 -3
  14. package/dist/v2/UploadList/UploadDetail.vue +3 -3
  15. package/dist/v2/WebSocket/WebSocketList.vue +3 -3
  16. package/dist/v3/{CloseButton → CircularButton}/index.vue +4 -2
  17. package/dist/v3/ConsoleList/ConsoleItem.vue +44 -96
  18. package/dist/v3/ConsoleList/index.vue +2 -0
  19. package/dist/v3/DevTool/index.vue +4 -4
  20. package/dist/v3/DevToolWindow/index.vue +162 -14
  21. package/dist/v3/FilterSelect/index.vue +165 -0
  22. package/dist/v3/NetworkList/NetworkDetail.vue +11 -8
  23. package/dist/v3/NetworkList/NetworkItem.vue +56 -26
  24. package/dist/v3/NetworkList/NetworkSend.vue +819 -0
  25. package/dist/v3/NetworkList/const.d.ts +5 -0
  26. package/dist/v3/NetworkList/const.d.ts.map +1 -0
  27. package/dist/v3/NetworkList/const.ts +4 -0
  28. package/dist/v3/NetworkList/index.vue +104 -21
  29. package/dist/v3/SettingList/index.vue +1 -1
  30. package/dist/v3/SourceCode/index.vue +22 -8
  31. package/dist/v3/StorageList/index.vue +7 -6
  32. package/dist/v3/Tabs/index.vue +2 -2
  33. package/dist/v3/UniEvent/UniEventItem.vue +6 -54
  34. package/dist/v3/UniEvent/index.vue +2 -0
  35. package/dist/v3/UploadList/UploadDetail.vue +2 -2
  36. package/dist/v3/WebSocket/WebSocketList.vue +2 -2
  37. package/package.json +1 -1
@@ -0,0 +1,819 @@
1
+ <template>
2
+ <view class="network-send" :style="{ zIndex: zIndex }">
3
+ <view class="network-send-form">
4
+ <view class="network-send-control">
5
+ <DevToolTitle>请求方式</DevToolTitle>
6
+ <CircularButton style="margin-left: auto" text="×" @click="onClose" />
7
+ </view>
8
+ <radio-group class="radio-group" @change="onChangeRequestMethod">
9
+ <label
10
+ class="radio-group-item"
11
+ v-for="(item, index) in requestMethods"
12
+ :key="item.value"
13
+ >
14
+ <radio
15
+ size
16
+ style="transform: scale(0.8)"
17
+ :value="item.value"
18
+ :checked="item.value === state.method"
19
+ />
20
+
21
+ <view>{{ item.name }}</view>
22
+ </label>
23
+ </radio-group>
24
+ <DevToolTitle>请求地址</DevToolTitle>
25
+ <input
26
+ placeholder="请输入请求地址"
27
+ placeholderStyle="font-size: 12px"
28
+ class="network-input"
29
+ v-model="state.url"
30
+ />
31
+ <view class="form-error-message">
32
+ {{ hasUrl ? '' : '请输入请求地址' }}
33
+ </view>
34
+
35
+ <view class="network-send-control">
36
+ <DevToolTitle>请求头</DevToolTitle>
37
+ <CircularButton
38
+ style="margin-left: auto"
39
+ text="+"
40
+ @click="onAddHeader"
41
+ />
42
+ </view>
43
+
44
+ <view class="network-header-list">
45
+ <template v-if="headerList.length > 0">
46
+ <view
47
+ class="network-header-item"
48
+ v-for="(item, index) in headerList"
49
+ :key="item.id"
50
+ >
51
+ <checkbox :checked="item.checked" />
52
+ <input
53
+ v-model="item.key"
54
+ class="network-input"
55
+ placeholder="请输入请求头名称"
56
+ placeholderStyle="font-size: 12px"
57
+ />
58
+ <input
59
+ v-model="item.value"
60
+ class="network-input"
61
+ placeholder="请输入请求头值"
62
+ placeholderStyle="font-size: 12px"
63
+ />
64
+ <CircularButton
65
+ style="margin-left: 6px"
66
+ text="一"
67
+ @click="onDeleteHeader(item)"
68
+ />
69
+ </view>
70
+ </template>
71
+
72
+ <view class="network-empty" v-else> 暂无请求头 </view>
73
+ </view>
74
+
75
+ <view class="network-send-control">
76
+ <DevToolTitle>请求参数(query)</DevToolTitle>
77
+ <CircularButton
78
+ style="margin-left: auto"
79
+ text="+"
80
+ @click="onAddQuery"
81
+ />
82
+ </view>
83
+ <view class="network-param-list">
84
+ <checkbox-group
85
+ v-if="queryList.length > 0"
86
+ @change="onChangeQueryChecked"
87
+ >
88
+ <view
89
+ class="network-param-item"
90
+ v-for="(item, index) in queryList"
91
+ :key="item.id"
92
+ >
93
+ <checkbox :checked="item.checked" :value="item.id" />
94
+ <input
95
+ v-model="item.key"
96
+ class="network-input"
97
+ placeholder="请输入参数名称"
98
+ placeholderStyle="font-size: 12px"
99
+ />
100
+ <input
101
+ v-model="item.value"
102
+ class="network-input"
103
+ placeholder="请输入参数值"
104
+ placeholderStyle="font-size: 12px"
105
+ />
106
+ <CircularButton
107
+ text="一"
108
+ style="margin-left: 6px"
109
+ @click="onDeleteQuery(item)"
110
+ />
111
+ </view>
112
+ </checkbox-group>
113
+
114
+ <view class="network-empty" v-else> 暂无请求参数 </view>
115
+ </view>
116
+
117
+ <template v-if="state.method === 'POST' || state.method === 'PUT'">
118
+ <view class="network-send-control">
119
+ <DevToolTitle>请求体(body)</DevToolTitle>
120
+ <CircularButton
121
+ v-if="
122
+ state.bodyType == 'form-data' ||
123
+ state.bodyType == 'x-www-form-urlencoded'
124
+ "
125
+ style="margin-left: auto"
126
+ text="+"
127
+ @click="onAddBody"
128
+ />
129
+ </view>
130
+
131
+ <radio-group class="radio-group" @change="onChangeBodyType">
132
+ <label
133
+ class="radio-group-item"
134
+ v-for="(item, index) in bodyTypes"
135
+ :key="item.value"
136
+ >
137
+ <radio
138
+ size
139
+ style="transform: scale(0.8)"
140
+ :value="item.value"
141
+ :checked="item.value === state.bodyType"
142
+ />
143
+
144
+ <view>{{ item.name }}</view>
145
+ </label>
146
+ </radio-group>
147
+
148
+ <view
149
+ class="network-body-data"
150
+ v-if="
151
+ state.bodyType == 'form-data' ||
152
+ state.bodyType == 'x-www-form-urlencoded'
153
+ "
154
+ >
155
+ <template v-if="bodyList.length > 0">
156
+ <checkbox-group
157
+ class="network-body-data-item"
158
+ v-for="(item, index) in bodyList"
159
+ :key="item.id"
160
+ @change="onChangeBodyChecked"
161
+ >
162
+ <checkbox v-model="item.checked" />
163
+ <input
164
+ v-model="item.key"
165
+ class="network-input"
166
+ placeholder="请输入参数名称"
167
+ placeholderStyle="font-size: 12px"
168
+ />
169
+ <input
170
+ v-model="item.value"
171
+ class="network-input"
172
+ placeholder="请输入参数值"
173
+ placeholderStyle="font-size: 12px"
174
+ />
175
+ <CircularButton
176
+ text="一"
177
+ style="margin-left: 6px"
178
+ @click="onDeleteBody(item)"
179
+ />
180
+ </checkbox-group>
181
+ </template>
182
+
183
+ <view class="network-empty" v-else> 暂无请求参数 </view>
184
+ </view>
185
+
186
+ <textarea
187
+ v-else-if="state.bodyType == 'Raw text'"
188
+ v-model="state.bodyText"
189
+ placeholder="请输入请求体"
190
+ class="network-body-textarea"
191
+ placeholderStyle="font-size: 12px"
192
+ />
193
+ <view class="network-empty" v-else> 暂无请求参数 </view>
194
+ </template>
195
+
196
+ <view class="network-send-buttons">
197
+ <button size="mini" :disabled="!isFinished" @click="onDetail">
198
+ 详情
199
+ </button>
200
+ <button size="mini" @click="onReset">重置</button>
201
+ <button size="mini" @click="onSend">发送</button>
202
+ </view>
203
+
204
+ <NetworkDetail
205
+ v-show="showDetail"
206
+ :network="network"
207
+ @close="onCloseDetail"
208
+ />
209
+ </view>
210
+ </view>
211
+ </template>
212
+ <script lang="ts" setup>
213
+ import { ref, reactive, onMounted } from 'vue';
214
+
215
+ import CircularButton from '../CircularButton/index.vue';
216
+ import DevToolTitle from '../DevToolTitle/index.vue';
217
+ import NetworkDetail from './NetworkDetail.vue';
218
+ import type { DevTool } from '../../type';
219
+ import { isObject, isString } from '../../utils';
220
+ const props = defineProps<{ network: DevTool.NetworkItem; zIndex?: number }>();
221
+
222
+ const emit = defineEmits<{ (e: 'close'): void }>();
223
+
224
+ const requestMethods = [
225
+ { name: 'GET', value: 'GET' },
226
+ { name: 'POST', value: 'POST' },
227
+ { name: 'PUT', value: 'PUT' },
228
+ { name: 'DELETE', value: 'DELETE' },
229
+ { name: 'PATCH', value: 'PATCH' },
230
+ { name: 'OPTIONS', value: 'OPTIONS' },
231
+ { name: 'HEAD', value: 'HEAD' },
232
+ ];
233
+
234
+ const bodyTypes = [
235
+ { name: 'none', value: 'none' },
236
+ { name: 'form-data', value: 'form-data' },
237
+ { name: 'x-www-form-urlencoded', value: 'x-www-form-urlencoded' },
238
+ { name: 'Raw text', value: 'Raw text' },
239
+ ];
240
+
241
+ const hasUrl = ref(true);
242
+
243
+ const state = reactive<{
244
+ method: any;
245
+ bodyType: any;
246
+ url: string;
247
+ bodyText: string;
248
+ }>({
249
+ method: 'GET',
250
+ bodyType: 'none',
251
+ url: '192.168.0.1:8080/a?a=123',
252
+ bodyText: '',
253
+ });
254
+
255
+ const defaultHeader = [
256
+ {
257
+ id: 1,
258
+ key: 'Accept',
259
+ value: '*/*',
260
+ checked: false,
261
+ },
262
+ {
263
+ id: 2,
264
+ key: 'Accept-Language',
265
+ value: 'zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6',
266
+ checked: false,
267
+ },
268
+ {
269
+ id: 3,
270
+ key: 'Cache-Control',
271
+ value: 'no-cache',
272
+ checked: false,
273
+ },
274
+ {
275
+ id: 4,
276
+ key: 'Content-Type',
277
+ value: 'application/x-www-form-urlencoded',
278
+ checked: true,
279
+ },
280
+ ];
281
+
282
+ const headerList = reactive([...defaultHeader]);
283
+
284
+ const defaultQuery = [
285
+ {
286
+ id: 1,
287
+ key: 'name',
288
+ value: '',
289
+ checked: false,
290
+ },
291
+ ];
292
+
293
+ const queryList = reactive([...defaultQuery]);
294
+
295
+ const defaultBody = [
296
+ {
297
+ id: 1,
298
+ key: 'name',
299
+ value: '',
300
+ checked: false,
301
+ },
302
+ ];
303
+
304
+ const bodyList = reactive([...defaultBody]);
305
+
306
+ const isFinished = ref(false);
307
+
308
+ const showDetail = ref(false);
309
+
310
+ const network = reactive<DevTool.NetworkItem>({
311
+ index: 0,
312
+ url: '',
313
+ name: '',
314
+ method: '',
315
+ status: '',
316
+ time: '',
317
+ startTime: 0,
318
+ endTime: 0,
319
+ size: '',
320
+ headers: {
321
+ requestHeader: [],
322
+ responseHeader: [],
323
+ },
324
+ response: '',
325
+ payload: undefined,
326
+ });
327
+
328
+ function onDetail() {
329
+ showDetail.value = true;
330
+ }
331
+
332
+ function onCloseDetail() {
333
+ showDetail.value = false;
334
+ }
335
+
336
+ function onReset() {
337
+ isFinished.value = false;
338
+ hasUrl.value = true;
339
+ state.method = 'GET';
340
+ state.bodyType = 'none';
341
+ state.url = '';
342
+ state.bodyText = '';
343
+ headerList.splice(0, headerList.length, ...defaultHeader);
344
+ queryList.splice(0, queryList.length, ...defaultQuery);
345
+ bodyList.splice(0, bodyList.length);
346
+ }
347
+
348
+ function onClose() {
349
+ emit('close');
350
+ onReset();
351
+ }
352
+
353
+ function onSend() {
354
+ if (!state.url) {
355
+ hasUrl.value = false;
356
+ uni.showToast({
357
+ title: '请输入请求地址',
358
+ icon: 'none',
359
+ });
360
+ return;
361
+ }
362
+ hasUrl.value = true;
363
+
364
+ const header = arrayToObject(headerList);
365
+ const query = arrayToObject(queryList);
366
+
367
+ const body = arrayToObject(bodyList);
368
+ const formData = new FormData();
369
+
370
+ const requestOptions: UniNamespace.RequestOptions = {
371
+ url: state.url,
372
+ method: state.method,
373
+ timeout: 60 * 1000,
374
+ header,
375
+ };
376
+
377
+ console.log('state: ', state);
378
+
379
+ if (state.bodyType === 'form-data') {
380
+ for (const key in body) {
381
+ formData.append(key, body[key]);
382
+ }
383
+ requestOptions.data = formData;
384
+ } else if (state.bodyType === 'x-www-form-urlencoded') {
385
+ const urlencoded = objectToUrlParams(body);
386
+ requestOptions.data = urlencoded;
387
+ } else if (state.bodyType === 'Raw text') {
388
+ try {
389
+ const bodyJson = JSON.parse(state.bodyText);
390
+ requestOptions.data = bodyJson;
391
+ } catch (error) {
392
+ uni.showToast({
393
+ title: '请求体请输入正确的JSON格式',
394
+ icon: 'none',
395
+ });
396
+ return;
397
+ }
398
+ } else {
399
+ console.log('------------state: ', state);
400
+ const urlQuery = urlParamsToObject(state.url.split('?')?.[1] ?? '');
401
+ console.log('urlQuery: ', urlQuery);
402
+ requestOptions.data = {
403
+ ...query,
404
+ ...urlQuery,
405
+ };
406
+ }
407
+
408
+ console.log('requestOptions: ', requestOptions);
409
+
410
+ isFinished.value = false;
411
+
412
+ uni.showLoading({
413
+ title: '发送中...',
414
+ mask: true,
415
+ });
416
+
417
+ const baseUrl = requestOptions.url?.split('?')[0] || '';
418
+ const lastSlashIndex = baseUrl.lastIndexOf('/');
419
+ const name = lastSlashIndex !== -1 ? baseUrl.slice(lastSlashIndex + 1) : '';
420
+
421
+ network.startTime = Date.now();
422
+
423
+ uni.request({
424
+ ...requestOptions,
425
+ complete: (res: any) => {
426
+ // 赋值结果
427
+ network.url = requestOptions.url;
428
+ network.name = name;
429
+ network.method = requestOptions.method as string;
430
+ network.payload = requestOptions.data
431
+ ? JSON.stringify(requestOptions.data)
432
+ : '';
433
+ network.endTime = Date.now();
434
+ network.status = res.statusCode ?? 'error';
435
+ const diff = network.endTime - network.startTime;
436
+ network.time = diff < 1000 ? diff + 'ms' : diff / 1000 + 's';
437
+ const len =
438
+ res?.header?.['Content-Length'] || res?.header?.['content-length'] || 0;
439
+ network.size = len > 1024 ? (len / 1024).toFixed(2) + 'k' : len + 'b';
440
+ network.response = res;
441
+ network.headers.requestHeader = Object.entries(
442
+ requestOptions?.header ?? {},
443
+ ).map(([key, value]) => ({
444
+ key,
445
+ value,
446
+ }));
447
+ network.headers.responseHeader = Object.entries(res?.header ?? {}).map(
448
+ ([key, value]) => ({
449
+ key,
450
+ value,
451
+ }),
452
+ );
453
+
454
+ // 完成
455
+ uni.hideLoading();
456
+ isFinished.value = true;
457
+ uni.showToast({
458
+ title: '请求完成,点击左下角详情进行查看结果',
459
+ icon: 'none',
460
+ });
461
+ },
462
+ });
463
+ }
464
+
465
+ function onChangeRequestMethod(e: any) {
466
+ const method = e.detail.value;
467
+ state.method = method;
468
+
469
+ if (method === 'POST' || method === 'PUT') {
470
+ bodyList.splice(0, bodyList.length);
471
+ state.bodyType = 'none';
472
+ }
473
+ }
474
+
475
+ function onChangeBodyType(e: any) {
476
+ const bodyType = e.detail.value;
477
+ state.bodyType = bodyType;
478
+ const ctIndex = headerList.findIndex((h) =>
479
+ ['Content-Type', 'Content-type', 'content-Type', 'content-type'].includes(
480
+ h.key,
481
+ ),
482
+ );
483
+
484
+ if (bodyType === 'form-data' || bodyType === 'x-www-form-urlencoded') {
485
+ if (ctIndex === -1) {
486
+ headerList.push({
487
+ id: Date.now(),
488
+ key: 'Content-Type',
489
+ value: 'application/x-www-form-urlencoded',
490
+ checked: true,
491
+ });
492
+ } else {
493
+ headerList[ctIndex].checked = true;
494
+ headerList[ctIndex].value = 'application/x-www-form-urlencoded';
495
+ }
496
+ } else {
497
+ bodyList.splice(0, bodyList.length);
498
+
499
+ if (ctIndex === -1) {
500
+ headerList.push({
501
+ id: Date.now(),
502
+ key: 'Content-Type',
503
+ value: 'application/json;charset:utf-8;',
504
+ checked: true,
505
+ });
506
+ } else {
507
+ headerList[ctIndex].checked = true;
508
+ headerList[ctIndex].value = 'application/json;charset:utf-8;';
509
+ }
510
+ }
511
+ }
512
+
513
+ function onChangeBodyChecked(e: any) {
514
+ const list = e.detail?.value ?? [];
515
+ bodyList.forEach((h) => {
516
+ list?.includes(h.id) ? (h.checked = true) : (h.checked = false);
517
+ });
518
+ }
519
+
520
+ function onDeleteHeader(item: any) {
521
+ const index = headerList.findIndex((i) => i.id === item.id);
522
+ headerList.splice(index, 1);
523
+ }
524
+
525
+ function onAddHeader() {
526
+ const id = Date.now();
527
+ headerList.push({
528
+ id,
529
+ key: '',
530
+ value: '',
531
+ checked: false,
532
+ });
533
+ }
534
+
535
+ function onDeleteQuery(item: any) {
536
+ const index = queryList.findIndex((i) => i.id === item.id);
537
+ queryList.splice(index, 1);
538
+ }
539
+ function onAddQuery() {
540
+ const id = Date.now();
541
+ queryList.push({
542
+ id,
543
+ key: '',
544
+ value: '',
545
+ checked: false,
546
+ });
547
+ }
548
+ function onChangeQueryChecked(e: any) {
549
+ const list = e.detail?.value ?? [];
550
+ queryList.forEach((q) => {
551
+ list?.includes(q.id) ? (q.checked = true) : (q.checked = false);
552
+ });
553
+ }
554
+
555
+ function onDeleteBody(item: any) {
556
+ const index = bodyList.findIndex((i) => i.id === item.id);
557
+ bodyList.splice(index, 1);
558
+ }
559
+
560
+ function onAddBody() {
561
+ const id = Date.now();
562
+ bodyList.push({
563
+ id,
564
+ key: '',
565
+ value: '',
566
+ checked: false,
567
+ });
568
+ }
569
+
570
+ function arrayToObject(arr: any[]) {
571
+ return arr.reduce((acc, cur) => {
572
+ if (cur.checked) {
573
+ acc[cur.key] = cur.value;
574
+ }
575
+ return acc;
576
+ }, {});
577
+ }
578
+
579
+ function objectToArray<T extends Record<string, any>>(obj: T) {
580
+ return Object.entries(obj).map(([key, value]) => ({
581
+ id: Date.now(),
582
+ key,
583
+ value,
584
+ checked: true,
585
+ }));
586
+ }
587
+
588
+ function objectToUrlParams(obj: any) {
589
+ return Object.keys(obj)
590
+ .map((key) => `${key}=${encodeURIComponent(obj[key])}`)
591
+ .join('&');
592
+ }
593
+
594
+ function formDataToObject(data: Record<string, any>) {
595
+ const obj: Record<string, any> = {};
596
+ for (const key in data) {
597
+ if (data.hasOwnProperty(key)) {
598
+ obj[key] = data[key];
599
+ }
600
+ }
601
+ return obj;
602
+ }
603
+
604
+ function urlParamsToObject(urlParams: string) {
605
+ return urlParams.split('&').reduce(
606
+ (acc, cur) => {
607
+ const [key, value] = cur.split('=');
608
+ acc[key] = value;
609
+ return acc;
610
+ },
611
+ {} as Record<string, any>,
612
+ );
613
+ }
614
+
615
+ /**
616
+ * 处理重发参数
617
+ */
618
+ function handleResendNetwork() {
619
+ // 如果没有网络数据或尚未开始,则直接返回
620
+ if (!props.network || props.network.startTime === 0) return;
621
+
622
+ // 设置基础请求信息
623
+ state.url = props.network.url;
624
+ state.method = props.network.method?.toUpperCase() ?? 'GET';
625
+
626
+ // 初始化请求头
627
+ const requestHeaders =
628
+ props.network.headers?.requestHeader?.map((item, index) => {
629
+ return {
630
+ ...item,
631
+ checked: true,
632
+ id: index,
633
+ };
634
+ }) ?? [];
635
+
636
+ headerList.splice(0, headerList.length, ...requestHeaders);
637
+
638
+ // 查找 Content-Type 头部
639
+ const contentType = requestHeaders.find((h) =>
640
+ ['Content-Type', 'content-type', 'Content-type', 'content-Type'].includes(
641
+ h.key,
642
+ ),
643
+ )?.value;
644
+
645
+ queryList.splice(0, queryList.length);
646
+
647
+ // 参数在 query 中
648
+ if (props.network.url.includes('?')) {
649
+ queryList.splice(
650
+ 0,
651
+ queryList.length,
652
+ ...objectToArray(
653
+ urlParamsToObject(props.network.url.split('?')?.[1] ?? ''),
654
+ ),
655
+ );
656
+ }
657
+
658
+ // 根据 Content-Type 设置请求体类型和内容
659
+ if (contentType?.includes('application/json')) {
660
+ if (state.method === 'GET' || state.method === 'DELETE') {
661
+ state.bodyType = 'none';
662
+
663
+ // 参数在 payload 中
664
+ if (props.network.payload) {
665
+ queryList.splice(
666
+ queryList.length,
667
+ 0,
668
+ ...objectToArray(urlParamsToObject(props.network.payload)),
669
+ );
670
+ }
671
+ } else {
672
+ state.bodyType = 'Raw text';
673
+ try {
674
+ state.bodyText = isString(props.network.payload)
675
+ ? props.network.payload
676
+ : JSON.stringify(props.network.payload);
677
+ } catch (error) {
678
+ console.error('Failed to parse payload as JSON:', error);
679
+
680
+ state.bodyText = '请求体非JSON格式';
681
+
682
+ uni.showToast({
683
+ title: '请求体JSON格式错误',
684
+ icon: 'none',
685
+ });
686
+ }
687
+ }
688
+ } else if (contentType?.includes('application/x-www-form-urlencoded')) {
689
+ if (isString(props.network.payload)) {
690
+ state.bodyType = 'x-www-form-urlencoded';
691
+ const payloadObject = urlParamsToObject(props.network.payload);
692
+ bodyList.splice(0, bodyList.length, ...objectToArray(payloadObject));
693
+ } else {
694
+ state.bodyType = 'form-data';
695
+ // 对于非字符串负载,尝试转换为对象形式
696
+ const payloadObject = props.network.payload
697
+ ? isObject(props.network.payload)
698
+ ? props.network.payload
699
+ : formDataToObject(props.network.payload)
700
+ : {};
701
+ bodyList.splice(0, bodyList.length, ...objectToArray(payloadObject));
702
+ }
703
+ } else {
704
+ // 默认为无请求体 无法解析请求体
705
+ state.bodyType = 'none';
706
+ }
707
+ }
708
+
709
+ onMounted(() => {
710
+ handleResendNetwork();
711
+ });
712
+ </script>
713
+
714
+ <style scoped>
715
+ .network-send {
716
+ position: fixed;
717
+ width: 100vw;
718
+ height: 100%;
719
+ z-index: 5;
720
+ top: 0;
721
+ left: 0;
722
+ padding: 0 16px;
723
+ overflow: auto;
724
+
725
+ background-color: var(--dev-tool-bg3-color);
726
+ box-sizing: border-box;
727
+ }
728
+ .network-send .network-send-control {
729
+ display: flex;
730
+ align-items: center;
731
+ gap: 12px;
732
+ height: 32px;
733
+ border-bottom: 1px solid transparent;
734
+ box-sizing: border-box;
735
+ }
736
+
737
+ .network-send .network-send-control :deep(.tag) {
738
+ margin-right: 16px;
739
+ }
740
+ .network-send .network-send-control :deep(.tag):last-child {
741
+ margin-right: 0;
742
+ }
743
+
744
+ .radio-group {
745
+ display: flex;
746
+ flex-wrap: wrap;
747
+ }
748
+
749
+ .radio-group .radio-group-item {
750
+ display: flex;
751
+ align-items: center;
752
+ width: 25%;
753
+ margin-bottom: 6px;
754
+ }
755
+
756
+ .network-input {
757
+ padding: 0 6px;
758
+ height: 24px;
759
+ font-size: 12px;
760
+ border: 1px solid var(--dev-tool-border-color);
761
+ }
762
+ .network-body-textarea {
763
+ padding: 6px;
764
+ width: 100%;
765
+ box-sizing: border-box;
766
+ font-size: 12px;
767
+ border: 1px solid var(--dev-tool-border-color);
768
+ }
769
+ .form-error-message {
770
+ padding: 0 6px;
771
+ height: 24px;
772
+ line-height: 24px;
773
+ color: red;
774
+ }
775
+
776
+ .network-header-list {
777
+ }
778
+
779
+ .network-header-item {
780
+ display: flex;
781
+ align-items: center;
782
+ }
783
+
784
+ .network-empty {
785
+ color: var(--dev-tool-info-color);
786
+ text-align: center;
787
+ }
788
+
789
+ .network-param-list {
790
+ }
791
+ .network-param-item {
792
+ display: flex;
793
+ align-items: center;
794
+ }
795
+
796
+ .network-body-data {
797
+ }
798
+ .network-body-data-item {
799
+ display: flex;
800
+ align-items: center;
801
+ }
802
+
803
+ .network-send-buttons {
804
+ position: sticky;
805
+ display: flex;
806
+ justify-content: space-between;
807
+ /* gap: 6px; */
808
+ width: 100%;
809
+ margin-top: 12px;
810
+ background-color: var(--dev-tool-bg3-color);
811
+ }
812
+ .network-send-buttons button {
813
+ width: 100%;
814
+ margin-right: 6px;
815
+ }
816
+ .network-send-buttons button:last-child {
817
+ margin: 0;
818
+ }
819
+ </style>