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,556 +1,589 @@
1
- <template>
2
- <view class="network-send" :style="customStyle">
3
- <view class="network-send-control">
4
- <DevToolTitle>{{ t('network.sendRequest') }}</DevToolTitle>
5
- <CircularButton style="margin-left: auto" text="×" @click="onClose" />
6
- </view>
7
- <scroll-view scroll-y class="network-send-form">
8
- <view class="network-send-control">
9
- <DevToolTitle>{{ t('network.timeout') }}</DevToolTitle>
10
- </view>
11
- <input
12
- class="network-input"
13
- :value="state.timeout"
14
- @input="onChangeState($event, 'timeout')" />
15
- <view class="network-send-control">
16
- <DevToolTitle>{{ t('network.requestMethod') }}</DevToolTitle>
17
- </view>
18
- <radio-group class="radio-group" @change="onChangeRequestMethod">
19
- <label
20
- class="radio-group-item"
21
- v-for="item in requestMethods"
22
- :key="item.value">
23
- <radio
24
- size
25
- style="transform: scale(0.8)"
26
- :color="themeColor"
27
- :value="item.value"
28
- :checked="item.value === state.method" />
29
-
30
- <view>{{ item.name }}</view>
31
- </label>
32
- </radio-group>
33
- <view class="network-send-control">
34
- <DevToolTitle>{{ t('network.requestHeaders') }}</DevToolTitle>
35
- <CircularButton
36
- style="margin-left: auto"
37
- text="+"
38
- @click="onAddHeader" />
39
- </view>
40
-
41
- <view class="network-header-list">
42
- <checkbox-group
43
- v-if="headerList.length > 0"
44
- @change="onChangeHeaderChecked">
45
- <view
46
- class="network-header-item"
47
- v-for="(item, index) in headerList"
48
- :key="item.id">
49
- <checkbox color="#9254de" :checked="item.checked" />
50
- <input
51
- class="network-input"
52
- :placeholder="t('network.placeholderHeaderName')"
53
- :value="item.key"
54
- @input="onChangeHeader($event, 'key', index)" />
55
- <input
56
- class="network-input"
57
- :placeholder="t('network.placeholderHeaderValue')"
58
- :value="item.value"
59
- @input="onChangeHeader($event, 'value', index)" />
60
- <CircularButton
61
- style="margin-left: 6px"
62
- text="一"
63
- @click="onDeleteHeader(item)" />
64
- </view>
65
- </checkbox-group>
66
-
67
- <view class="network-empty" v-else>
68
- {{ t('network.noRequestHeaders') }}
69
- </view>
70
- </view>
71
- <DevToolTitle>{{ t('network.requestUrl') }}</DevToolTitle>
72
- <textarea
73
- :placeholder="t('network.placeholderUrl')"
74
- class="network-textarea"
75
- :value="state.url"
76
- @input="onChangeUrl" />
77
- <view class="form-error-message">
78
- {{ hasUrl ? '' : t('network.toastEnterUrl') }}
79
- </view>
80
-
81
- <view class="network-send-control">
82
- <DevToolTitle>{{ t('network.requestParams') }}</DevToolTitle>
83
- <CircularButton
84
- style="margin-left: auto"
85
- text=""
86
- @click="onAddQuery" />
87
- </view>
88
- <view class="network-param-list">
89
- <checkbox-group
90
- v-if="queryList.length > 0"
91
- @change="handleQueryCheckedChange">
92
- <view
93
- class="network-param-item"
94
- v-for="(item, index) in queryList"
95
- :key="item.id">
96
- <checkbox
97
- :color="themeColor"
98
- :checked="item.checked"
99
- :value="item.id" />
100
- <input
101
- class="network-input"
102
- :placeholder="t('network.placeholderParamName')"
103
- :value="item.key"
104
- @input="onChangeQuery($event, 'key', index)" />
105
- <input
106
- class="network-input"
107
- :placeholder="t('network.placeholderParamValue')"
108
- :value="item.value"
109
- @input="onChangeQuery($event, 'value', index)" />
110
- <CircularButton
111
- text=""
112
- style="margin-left: 6px"
113
- @click="onDeleteQuery(item)" />
114
- </view>
115
- </checkbox-group>
116
-
117
- <view class="network-empty" v-else>
118
- {{ t('network.emptyParams') }}
119
- </view>
120
- </view>
121
-
122
- <template v-if="!noBodyRequestMethods.includes(state.method)">
123
- <view class="network-send-control">
124
- <DevToolTitle>{{ t('network.requestBody') }}</DevToolTitle>
125
- </view>
126
-
127
- <textarea
128
- :placeholder="t('network.placeholderBody')"
129
- class="network-textarea"
130
- :value="state.bodyText"
131
- @input="onChangeState($event, 'bodyText')" />
132
- </template>
133
- </scroll-view>
134
- <view class="network-send-buttons">
135
- <button
136
- size="mini"
137
- :disabled="!isFinished"
138
- class="network-send-button"
139
- @click="emit('openDetail', currentNetwork)">
140
- {{ t('network.detail') }}
141
- </button>
142
- <button size="mini" class="network-send-button" @click="onReset">
143
- {{ t('network.reset') }}
144
- </button>
145
- <button size="mini" class="network-send-button-last" @click="onSend">
146
- {{ t('network.send') }}
147
- </button>
148
- </view>
149
- </view>
150
- </template>
151
- <script lang="ts" setup>
152
- import { computed, ref, reactive, onMounted } from 'vue';
153
- import CircularButton from '../CircularButton/index.vue';
154
- import DevToolTitle from '../DevToolTitle/index.vue';
155
- import type { DevTool } from '../../type';
156
- import { useI18n } from '../../i18n';
157
- import { getThemeMainColor } from '../styles/theme';
158
- const { t } = useI18n();
159
- const themeColor = computed(() => getThemeMainColor(props.theme));
160
-
161
- const props = defineProps<{
162
- theme?: string;
163
- network: DevTool.NetworkItem;
164
- zIndex?: number;
165
- interceptNetworkList?: DevTool.NetworkItem[];
166
- customStyle?: Record<string, any>;
167
- }>();
168
-
169
- const emit = defineEmits<{
170
- (e: 'close'): void;
171
- (e: 'openDetail', v: DevTool.NetworkItem): void;
172
- }>();
173
-
174
- import {
175
- requestMethods,
176
- noBodyRequestMethods,
177
- defaultHeader,
178
- arrayToObject,
179
- objectToArray,
180
- arrayToUrlParams,
181
- urlParamsToObject,
182
- unionArrayByKey,
183
- } from './utils';
184
- import { useKeyValueList, useNetworkState } from './hooks/useNetworkForm';
185
-
186
- const { state, hasUrl, onChangeState, parseUrlToList, parseListToUrl } =
187
- useNetworkState({
188
- method: 'GET',
189
- url: 'http://192.168.0.1:8080/a?a=123',
190
- bodyText: '',
191
- timeout: 3 * 1000,
192
- });
193
-
194
- const {
195
- list: headerList,
196
- onAdd: onAddHeader,
197
- onDelete: onDeleteHeader,
198
- onChangeChecked: onChangeHeaderChecked,
199
- onChangeValue: onChangeHeaderItem,
200
- setList: setHeaderList,
201
- } = useKeyValueList(defaultHeader);
202
-
203
- const {
204
- list: queryList,
205
- onAdd: onAddQuery,
206
- onDelete: onDeleteQuery,
207
- onChangeChecked: onChangeQueryChecked,
208
- onChangeValue: onChangeQueryItem,
209
- setList: setQueryList,
210
- } = useKeyValueList([
211
- {
212
- id: '1',
213
- key: 'a',
214
- value: '123',
215
- checked: true,
216
- },
217
- ]);
218
-
219
- const isFinished = ref(false);
220
-
221
- const currentNetwork = reactive<DevTool.NetworkItem>({
222
- index: 0,
223
- url: '',
224
- name: '',
225
- method: '',
226
- status: '',
227
- time: '',
228
- startTime: 0,
229
- endTime: 0,
230
- size: '',
231
- headers: {
232
- requestHeader: [],
233
- responseHeader: [],
234
- },
235
- response: {
236
- data: undefined,
237
- statusCode: 0,
238
- header: {},
239
- cookies: [],
240
- errMsg: '',
241
- },
242
- payload: undefined,
243
- intercepted: false,
244
- sponsor: 'dev_tool',
245
- });
246
-
247
- function onChangeHeader(e: any, key: 'key' | 'value', index: number) {
248
- onChangeHeaderItem(index, key, e.detail.value);
249
- }
250
-
251
- function onChangeUrl(e: any) {
252
- const url = e.detail.value;
253
- state.url = url;
254
- const list = parseUrlToList(url);
255
- setQueryList(list);
256
- }
257
-
258
- function onReset() {
259
- isFinished.value = false;
260
- hasUrl.value = true;
261
- state.method = 'GET';
262
- state.url = '';
263
- state.bodyText = '';
264
- setHeaderList(defaultHeader);
265
- setQueryList([]);
266
- }
267
-
268
- function onClose() {
269
- emit('close');
270
- onReset();
271
- }
272
-
273
- function onSend() {
274
- if (!state.url) {
275
- hasUrl.value = false;
276
- uni.showToast({
277
- title: t('network.toastEnterUrl'),
278
- icon: 'none',
279
- });
280
- return;
281
- }
282
- hasUrl.value = true;
283
-
284
- const header = arrayToObject(headerList);
285
- const query = arrayToUrlParams(queryList.filter((q) => q.checked));
286
-
287
- const requestOptions: UniNamespace.RequestOptions = {
288
- url: state.url,
289
- method: state.method,
290
- timeout: state.timeout,
291
- header: {
292
- ...header,
293
- /** 标记请求发起人 devTool */
294
- 'dev-tool-sponsor': Date.now(),
295
- },
296
- };
297
-
298
- if (noBodyRequestMethods.includes(state.method)) {
299
- // 不支持携带 body 参数
300
- requestOptions.data = {};
301
- state.url = parseListToUrl(state.url, queryList);
302
- } else {
303
- // 支持 url 中携带参数
304
-
305
- if (state.url.includes('?')) {
306
- requestOptions.url = state.url + '&' + query;
307
- } else {
308
- requestOptions.url = state.url + '?' + query;
309
- }
310
-
311
- // 支持携带 body 参数
312
- if (state.bodyText?.trim()) {
313
- try {
314
- const bodyJson = JSON.parse(state.bodyText);
315
- requestOptions.data = bodyJson;
316
- } catch (_error) {
317
- uni.showToast({
318
- title: t('network.toastBodyJson'),
319
- icon: 'none',
320
- });
321
- return;
322
- }
323
- }
324
- }
325
-
326
- isFinished.value = false;
327
-
328
- uni.showLoading({
329
- title: t('network.sending'),
330
- mask: true,
331
- });
332
-
333
- const baseUrl = requestOptions.url?.split('?')[0] || '';
334
- const lastSlashIndex = baseUrl.lastIndexOf('/');
335
- const name = lastSlashIndex !== -1 ? baseUrl.slice(lastSlashIndex + 1) : '';
336
-
337
- currentNetwork.startTime = Date.now();
338
-
339
- uni.request({
340
- ...requestOptions,
341
- complete: (res: any) => {
342
- // 赋值结果
343
- currentNetwork.url = requestOptions.url;
344
- currentNetwork.name = name;
345
- currentNetwork.method = requestOptions.method as string;
346
- currentNetwork.payload = requestOptions.data
347
- ? JSON.stringify(requestOptions.data)
348
- : '';
349
- currentNetwork.endTime = Date.now();
350
- currentNetwork.status = res.statusCode ?? 'error';
351
- const diff = currentNetwork.endTime - currentNetwork.startTime;
352
- currentNetwork.time = diff < 1000 ? diff + 'ms' : diff / 1000 + 's';
353
- const len =
354
- res?.header?.['Content-Length'] || res?.header?.['content-length'] || 0;
355
- currentNetwork.size =
356
- len > 1024 ? (len / 1024).toFixed(2) + 'k' : len + 'b';
357
- currentNetwork.response = res;
358
- currentNetwork.headers.requestHeader = objectToArray(
359
- requestOptions?.header ?? {},
360
- );
361
- currentNetwork.headers.responseHeader = objectToArray(res.header ?? {});
362
-
363
- currentNetwork.intercepted =
364
- props.interceptNetworkList?.some((item) => {
365
- const key = `${item.method?.toUpperCase()}|${item.url?.split('?')[0]}`;
366
- const curKey = `${currentNetwork.method?.toUpperCase()}|${currentNetwork.url?.split('?')[0]}`;
367
- return key === curKey;
368
- }) ?? false;
369
-
370
- // 完成
371
- uni.hideLoading();
372
- isFinished.value = true;
373
- uni.showToast({
374
- title: t('network.toastRequestSuccess'),
375
- icon: 'none',
376
- });
377
- },
378
- });
379
- }
380
-
381
- function onChangeRequestMethod(e: any) {
382
- const method = e.detail.value;
383
- state.method = method;
384
- }
385
-
386
- function onChangeQuery(e: any, key: 'key' | 'value', index: number) {
387
- onChangeQueryItem(index, key, e.detail.value);
388
- state.url = parseListToUrl(state.url, queryList);
389
- }
390
-
391
- function handleQueryCheckedChange(e: any) {
392
- onChangeQueryChecked(e);
393
- state.url = parseListToUrl(state.url, queryList);
394
- }
395
-
396
- /**
397
- * 处理重发参数
398
- */
399
- function handleResendNetwork() {
400
- // 如果没有网络数据或尚未开始,则直接返回
401
- if (!props.network || props.network.startTime === 0) return;
402
-
403
- // 设置基础请求信息
404
- state.url = props.network.url;
405
- state.method = props.network.method?.toUpperCase() ?? 'GET';
406
-
407
- // 初始化请求头
408
- const requestHeaders =
409
- props.network.headers?.requestHeader?.map((item, index) => {
410
- return {
411
- ...item,
412
- checked: true,
413
- id: index.toString(),
414
- };
415
- }) ?? [];
416
-
417
- setHeaderList(requestHeaders);
418
-
419
- setQueryList([]);
420
-
421
- // 解析参数
422
- if (noBodyRequestMethods.includes(state.method)) {
423
- // 参数在 query 中
424
- if (props.network.url.includes('?')) {
425
- const urlParams = objectToArray(
426
- urlParamsToObject(props.network.url.split('?')?.[1] ?? ''),
427
- );
428
- const payloadParams = objectToArray(props.network.payload);
429
-
430
- const list = unionArrayByKey(urlParams, payloadParams, 'key');
431
-
432
- setQueryList(list);
433
- }
434
- } else {
435
- // 参数在 query 中
436
- if (props.network.url.includes('?')) {
437
- const urlParams = objectToArray(
438
- urlParamsToObject(props.network.url.split('?')?.[1] ?? ''),
439
- );
440
- setQueryList(urlParams);
441
- }
442
- state.bodyText = JSON.stringify(props.network.payload);
443
- }
444
- }
445
-
446
- onMounted(() => {
447
- handleResendNetwork();
448
- });
449
- </script>
450
-
451
- <style scoped>
452
- .network-send {
453
- position: fixed;
454
- width: 100vw;
455
- height: 100%;
456
- z-index: 5;
457
- top: 0;
458
- left: 0;
459
- padding: 0 16px;
460
-
461
- /* #ifdef H5 || APP-PLUS */
462
- padding: 50px 16px;
463
-
464
- /* #endif */
465
- overflow: auto;
466
- background-color: var(--dev-tool-bg3-color);
467
- box-sizing: border-box;
468
- }
469
-
470
- .network-send-form {
471
- height: calc(100% - 32px - 42px);
472
- overflow: auto;
473
- }
474
-
475
- .network-send-control {
476
- display: flex;
477
- align-items: center;
478
- gap: 12px;
479
- height: 32px;
480
- border-bottom: 1px solid transparent;
481
- box-sizing: border-box;
482
- }
483
-
484
- .radio-group {
485
- display: flex;
486
- flex-wrap: wrap;
487
- }
488
-
489
- .radio-group-item {
490
- display: flex;
491
- align-items: center;
492
- width: 25%;
493
- margin-bottom: 6px;
494
- }
495
-
496
- .network-input {
497
- padding: 0 6px;
498
- height: 24px;
499
- border: 1px solid var(--dev-tool-border-color);
500
- }
501
-
502
- .network-textarea {
503
- padding: 6px;
504
- width: 100%;
505
- box-sizing: border-box;
506
- font-size: 12px;
507
- border: 1px solid var(--dev-tool-border-color);
508
- }
509
-
510
- .form-error-message {
511
- padding: 0 6px;
512
- height: 24px;
513
- line-height: 24px;
514
- color: red;
515
- }
516
-
517
- .network-header-item {
518
- display: flex;
519
- align-items: center;
520
- }
521
-
522
- .network-empty {
523
- color: var(--dev-tool-info-color);
524
- text-align: center;
525
- }
526
-
527
- .network-param-item {
528
- display: flex;
529
- align-items: center;
530
- }
531
-
532
- .network-body-data-item {
533
- display: flex;
534
- align-items: center;
535
- }
536
-
537
- .network-send-buttons {
538
- position: sticky;
539
- display: flex;
540
- justify-content: space-between;
541
-
542
- /* gap: 6px; */
543
- width: 100%;
544
- margin-top: 12px;
545
- background-color: var(--dev-tool-bg3-color);
546
- }
547
-
548
- .network-send-button {
549
- width: 100%;
550
- margin-right: 6px;
551
- }
552
-
553
- .network-send-button-last {
554
- width: 100%;
555
- }
556
- </style>
1
+ <template>
2
+ <view class="network-send" :style="customStyle">
3
+ <view class="network-send-control">
4
+ <DevToolTitle>{{ t('network.sendRequest') }}</DevToolTitle>
5
+ <CircularButton style="margin-left: auto" text="×" @click="onClose" />
6
+ </view>
7
+ <scroll-view scroll-y class="network-send-form">
8
+ <view class="network-send-control">
9
+ <DevToolTitle>{{ t('network.timeout') }}</DevToolTitle>
10
+ </view>
11
+ <input
12
+ class="network-input"
13
+ :value="state.timeout"
14
+ @input="onChangeState($event, 'timeout')" />
15
+ <view class="network-send-control">
16
+ <DevToolTitle>{{ t('network.requestMethod') }}</DevToolTitle>
17
+ </view>
18
+ <radio-group class="radio-group" @change="onChangeRequestMethod">
19
+ <label
20
+ class="radio-group-item"
21
+ v-for="item in requestMethods"
22
+ :key="item.value">
23
+ <radio
24
+ size
25
+ style="transform: scale(0.8)"
26
+ :color="themeColor"
27
+ :value="item.value"
28
+ :checked="item.value === state.method" />
29
+
30
+ <view>{{ item.name }}</view>
31
+ </label>
32
+ </radio-group>
33
+ <view class="network-send-control">
34
+ <DevToolTitle>{{ t('network.requestHeaders') }}</DevToolTitle>
35
+ <CircularButton
36
+ style="margin-left: auto"
37
+ text="+"
38
+ @click="onAddHeader" />
39
+ </view>
40
+
41
+ <view class="network-header-list">
42
+ <checkbox-group
43
+ v-if="headerList.length > 0"
44
+ @change="onChangeHeaderChecked">
45
+ <view
46
+ class="network-header-item"
47
+ v-for="(item, index) in headerList"
48
+ :key="item.id">
49
+ <checkbox color="#9254de" :checked="item.checked" />
50
+ <input
51
+ class="network-input"
52
+ :placeholder="t('network.placeholderHeaderName')"
53
+ :value="item.key"
54
+ @input="onChangeHeader($event, 'key', index)" />
55
+ <input
56
+ class="network-input"
57
+ :placeholder="t('network.placeholderHeaderValue')"
58
+ :value="item.value"
59
+ @input="onChangeHeader($event, 'value', index)" />
60
+ <CircularButton text="一" @click="onDeleteHeader(item)" />
61
+ </view>
62
+ </checkbox-group>
63
+
64
+ <view class="network-empty" v-else>
65
+ {{ t('network.noRequestHeaders') }}
66
+ </view>
67
+ </view>
68
+ <DevToolTitle>{{ t('network.requestUrl') }}</DevToolTitle>
69
+ <textarea
70
+ :placeholder="t('network.placeholderUrl')"
71
+ class="network-textarea"
72
+ :value="state.url"
73
+ @input="onChangeUrl" />
74
+ <view class="form-error-message">
75
+ {{ hasUrl ? '' : t('network.toastEnterUrl') }}
76
+ </view>
77
+
78
+ <view class="network-send-control">
79
+ <DevToolTitle>{{ t('network.requestParams') }}</DevToolTitle>
80
+ <CircularButton
81
+ style="margin-left: auto"
82
+ text="+"
83
+ @click="onAddQuery" />
84
+ </view>
85
+ <view class="network-param-list">
86
+ <checkbox-group
87
+ v-if="queryList.length > 0"
88
+ @change="handleQueryCheckedChange">
89
+ <view
90
+ class="network-param-item"
91
+ v-for="(item, index) in queryList"
92
+ :key="item.id">
93
+ <checkbox
94
+ :color="themeColor"
95
+ :checked="item.checked"
96
+ :value="item.id" />
97
+ <input
98
+ class="network-input"
99
+ :placeholder="t('network.placeholderParamName')"
100
+ :value="item.key"
101
+ @input="onChangeQuery($event, 'key', index)" />
102
+ <input
103
+ class="network-input"
104
+ :placeholder="t('network.placeholderParamValue')"
105
+ :value="item.value"
106
+ @input="onChangeQuery($event, 'value', index)" />
107
+ <CircularButton text="一" @click="onDeleteQuery(item)" />
108
+ </view>
109
+ </checkbox-group>
110
+
111
+ <view class="network-empty" v-else>
112
+ {{ t('network.emptyParams') }}
113
+ </view>
114
+ </view>
115
+
116
+ <template v-if="!noBodyRequestMethods.includes(state.method)">
117
+ <view class="network-send-control">
118
+ <DevToolTitle>{{ t('network.requestBody') }}</DevToolTitle>
119
+ </view>
120
+
121
+ <textarea
122
+ :placeholder="t('network.placeholderBody')"
123
+ class="network-textarea"
124
+ :value="state.bodyText"
125
+ @input="onChangeState($event, 'bodyText')" />
126
+ </template>
127
+ </scroll-view>
128
+ <view class="network-send-buttons">
129
+ <button
130
+ size="mini"
131
+ :disabled="!isFinished"
132
+ class="network-send-button"
133
+ @click="emit('openDetail', currentNetwork)">
134
+ {{ t('network.detail') }}
135
+ </button>
136
+ <button size="mini" class="network-send-button" @click="onReset">
137
+ {{ t('network.reset') }}
138
+ </button>
139
+ <button size="mini" class="network-send-button-last" @click="onSend">
140
+ {{ t('network.send') }}
141
+ </button>
142
+ </view>
143
+ </view>
144
+ </template>
145
+ <script lang="ts" setup>
146
+ import { computed, ref, reactive, onMounted } from 'vue';
147
+ import CircularButton from '../../../components/CircularButton/index.vue';
148
+ import DevToolTitle from '../DevToolTitle/index.vue';
149
+ import type { DevTool } from '../../../../type';
150
+ import { useI18n } from '../../../../i18n';
151
+ import { getThemeMainColor } from '../../../styles/theme';
152
+ const { t } = useI18n();
153
+ const themeColor = computed(() => getThemeMainColor(props.theme));
154
+
155
+ const props = defineProps<{
156
+ theme?: string;
157
+ network: DevTool.NetworkItem;
158
+ zIndex?: number;
159
+ interceptNetworkList?: DevTool.NetworkItem[];
160
+ customStyle?: Record<string, any>;
161
+ }>();
162
+
163
+ const emit = defineEmits<{
164
+ (e: 'close'): void;
165
+ (e: 'openDetail', v: DevTool.NetworkItem): void;
166
+ }>();
167
+
168
+ import {
169
+ requestMethods,
170
+ noBodyRequestMethods,
171
+ defaultHeader,
172
+ arrayToObject,
173
+ objectToArray,
174
+ arrayToUrlParams,
175
+ urlParamsToObject,
176
+ unionArrayByKey,
177
+ } from './utils';
178
+ import { useKeyValueList, useNetworkState } from './hooks/useNetworkForm';
179
+
180
+ const { state, hasUrl, onChangeState, parseUrlToList, parseListToUrl } =
181
+ useNetworkState({
182
+ method: 'GET',
183
+ url: 'http://192.168.0.1:8080/a?a=123',
184
+ bodyText: '',
185
+ timeout: 3 * 1000,
186
+ });
187
+
188
+ const {
189
+ list: headerList,
190
+ onAdd: onAddHeader,
191
+ onDelete: onDeleteHeader,
192
+ onChangeChecked: onChangeHeaderChecked,
193
+ onChangeValue: onChangeHeaderItem,
194
+ setList: setHeaderList,
195
+ } = useKeyValueList(defaultHeader);
196
+
197
+ const {
198
+ list: queryList,
199
+ onAdd: onAddQuery,
200
+ onDelete: onDeleteQuery,
201
+ onChangeChecked: onChangeQueryChecked,
202
+ onChangeValue: onChangeQueryItem,
203
+ setList: setQueryList,
204
+ } = useKeyValueList([
205
+ {
206
+ id: '1',
207
+ key: 'a',
208
+ value: '123',
209
+ checked: true,
210
+ },
211
+ ]);
212
+
213
+ const isFinished = ref(false);
214
+
215
+ const currentNetwork = reactive<DevTool.NetworkItem>({
216
+ index: 0,
217
+ url: '',
218
+ name: '',
219
+ method: '',
220
+ status: '',
221
+ time: '',
222
+ startTime: 0,
223
+ endTime: 0,
224
+ size: '',
225
+ headers: {
226
+ requestHeader: [],
227
+ responseHeader: [],
228
+ },
229
+ response: {
230
+ data: undefined,
231
+ statusCode: 0,
232
+ header: {},
233
+ cookies: [],
234
+ errMsg: '',
235
+ },
236
+ payload: undefined,
237
+ intercepted: false,
238
+ sponsor: 'dev_tool',
239
+ });
240
+
241
+ function onChangeHeader(e: any, key: 'key' | 'value', index: number) {
242
+ onChangeHeaderItem(index, key, e.detail.value);
243
+ }
244
+
245
+ function onChangeUrl(e: any) {
246
+ const url = e.detail.value;
247
+ state.url = url;
248
+ const list = parseUrlToList(url);
249
+ setQueryList(list);
250
+ }
251
+
252
+ function onReset() {
253
+ isFinished.value = false;
254
+ hasUrl.value = true;
255
+ state.method = 'GET';
256
+ state.url = '';
257
+ state.bodyText = '';
258
+ setHeaderList(defaultHeader);
259
+ setQueryList([]);
260
+ }
261
+
262
+ function onClose() {
263
+ emit('close');
264
+ onReset();
265
+ }
266
+
267
+ function onSend() {
268
+ if (!state.url) {
269
+ hasUrl.value = false;
270
+ uni.showToast({
271
+ title: t('network.toastEnterUrl'),
272
+ icon: 'none',
273
+ });
274
+ return;
275
+ }
276
+ hasUrl.value = true;
277
+
278
+ const header = arrayToObject(headerList);
279
+ const query = arrayToUrlParams(queryList.filter((q) => q.checked));
280
+
281
+ const requestOptions: UniNamespace.RequestOptions = {
282
+ url: state.url,
283
+ method: state.method,
284
+ timeout: state.timeout,
285
+ header: {
286
+ ...header,
287
+ /** 标记请求发起人 devTool */
288
+ 'dev-tool-sponsor': Date.now(),
289
+ },
290
+ };
291
+
292
+ if (noBodyRequestMethods.includes(state.method)) {
293
+ // 不支持携带 body 参数
294
+ requestOptions.data = {};
295
+ state.url = parseListToUrl(state.url, queryList);
296
+ } else {
297
+ // 支持 url 中携带参数
298
+
299
+ if (state.url.includes('?')) {
300
+ requestOptions.url = state.url + '&' + query;
301
+ } else {
302
+ requestOptions.url = state.url + '?' + query;
303
+ }
304
+
305
+ // 支持携带 body 参数
306
+ if (state.bodyText?.trim()) {
307
+ try {
308
+ const bodyJson = JSON.parse(state.bodyText);
309
+ requestOptions.data = bodyJson;
310
+ } catch (_error) {
311
+ uni.showToast({
312
+ title: t('network.toastBodyJson'),
313
+ icon: 'none',
314
+ });
315
+ return;
316
+ }
317
+ }
318
+ }
319
+
320
+ isFinished.value = false;
321
+
322
+ uni.showLoading({
323
+ title: t('network.sending'),
324
+ mask: true,
325
+ });
326
+
327
+ const baseUrl = requestOptions.url?.split('?')[0] || '';
328
+ const lastSlashIndex = baseUrl.lastIndexOf('/');
329
+ const name = lastSlashIndex !== -1 ? baseUrl.slice(lastSlashIndex + 1) : '';
330
+
331
+ currentNetwork.startTime = Date.now();
332
+
333
+ uni.request({
334
+ ...requestOptions,
335
+ complete: (res: any) => {
336
+ // 赋值结果
337
+ currentNetwork.url = requestOptions.url;
338
+ currentNetwork.name = name;
339
+ currentNetwork.method = requestOptions.method as string;
340
+ currentNetwork.payload = requestOptions.data
341
+ ? JSON.stringify(requestOptions.data)
342
+ : '';
343
+ currentNetwork.endTime = Date.now();
344
+ currentNetwork.status = res.statusCode ?? 'error';
345
+ const diff = currentNetwork.endTime - currentNetwork.startTime;
346
+ currentNetwork.time = diff < 1000 ? diff + 'ms' : diff / 1000 + 's';
347
+ const len =
348
+ res?.header?.['Content-Length'] || res?.header?.['content-length'] || 0;
349
+ currentNetwork.size =
350
+ len > 1024 ? (len / 1024).toFixed(2) + 'k' : len + 'b';
351
+ currentNetwork.response = res;
352
+ currentNetwork.headers.requestHeader = objectToArray(
353
+ requestOptions?.header ?? {},
354
+ );
355
+ currentNetwork.headers.responseHeader = objectToArray(res.header ?? {});
356
+
357
+ currentNetwork.intercepted =
358
+ props.interceptNetworkList?.some((item) => {
359
+ const key = `${item.method?.toUpperCase()}|${item.url?.split('?')[0]}`;
360
+ const curKey = `${currentNetwork.method?.toUpperCase()}|${currentNetwork.url?.split('?')[0]}`;
361
+ return key === curKey;
362
+ }) ?? false;
363
+
364
+ // 完成
365
+ uni.hideLoading();
366
+ isFinished.value = true;
367
+ uni.showToast({
368
+ title: t('network.toastRequestSuccess'),
369
+ icon: 'none',
370
+ });
371
+ },
372
+ });
373
+ }
374
+
375
+ function onChangeRequestMethod(e: any) {
376
+ const method = e.detail.value;
377
+ state.method = method;
378
+ }
379
+
380
+ function onChangeQuery(e: any, key: 'key' | 'value', index: number) {
381
+ onChangeQueryItem(index, key, e.detail.value);
382
+ state.url = parseListToUrl(state.url, queryList);
383
+ }
384
+
385
+ function handleQueryCheckedChange(e: any) {
386
+ onChangeQueryChecked(e);
387
+ state.url = parseListToUrl(state.url, queryList);
388
+ }
389
+
390
+ /**
391
+ * 处理重发参数
392
+ */
393
+ function handleResendNetwork() {
394
+ // 如果没有网络数据或尚未开始,则直接返回
395
+ if (!props.network || props.network.startTime === 0) return;
396
+
397
+ // 设置基础请求信息
398
+ state.url = props.network.url;
399
+ state.method = props.network.method?.toUpperCase() ?? 'GET';
400
+
401
+ // 初始化请求头
402
+ const requestHeaders =
403
+ props.network.headers?.requestHeader?.map((item, index) => {
404
+ return {
405
+ ...item,
406
+ checked: true,
407
+ id: index.toString(),
408
+ };
409
+ }) ?? [];
410
+
411
+ setHeaderList(requestHeaders);
412
+
413
+ setQueryList([]);
414
+
415
+ // 解析参数
416
+ if (noBodyRequestMethods.includes(state.method)) {
417
+ // 参数在 query 中
418
+ if (props.network.url.includes('?')) {
419
+ const urlParams = objectToArray(
420
+ urlParamsToObject(props.network.url.split('?')?.[1] ?? ''),
421
+ );
422
+ const payloadParams = objectToArray(props.network.payload);
423
+
424
+ const list = unionArrayByKey(urlParams, payloadParams, 'key');
425
+
426
+ setQueryList(list);
427
+ }
428
+ } else {
429
+ // 参数在 query 中
430
+ if (props.network.url.includes('?')) {
431
+ const urlParams = objectToArray(
432
+ urlParamsToObject(props.network.url.split('?')?.[1] ?? ''),
433
+ );
434
+ setQueryList(urlParams);
435
+ }
436
+ state.bodyText = JSON.stringify(props.network.payload);
437
+ }
438
+ }
439
+
440
+ onMounted(() => {
441
+ handleResendNetwork();
442
+ });
443
+ </script>
444
+
445
+ <style scoped>
446
+ .network-send {
447
+ position: fixed;
448
+ width: 100vw;
449
+ height: 100%;
450
+ z-index: 5;
451
+ top: 0;
452
+ left: 0;
453
+ padding: 0 16px;
454
+
455
+ /* #ifdef H5 || APP-PLUS */
456
+ padding: 50px 16px;
457
+
458
+ /* #endif */
459
+ overflow: auto;
460
+ background-color: var(--dev-tool-bg3-color);
461
+ box-sizing: border-box;
462
+ }
463
+
464
+ .network-send-form {
465
+ height: calc(100% - 32px - 56px);
466
+ overflow: auto;
467
+ }
468
+
469
+ .network-send-control {
470
+ display: flex;
471
+ align-items: center;
472
+ gap: 12px;
473
+ height: 32px;
474
+ border-bottom: 1px solid transparent;
475
+ box-sizing: border-box;
476
+ }
477
+
478
+ .network-send-control:first-child {
479
+ margin-top: 0;
480
+ }
481
+
482
+ .radio-group {
483
+ display: flex;
484
+ flex-wrap: wrap;
485
+ gap: 8px 0; /* Add gap between rows if wrapped */
486
+ }
487
+
488
+ .radio-group-item {
489
+ display: flex;
490
+ align-items: center;
491
+ width: 25%;
492
+ font-size: 14px;
493
+ }
494
+
495
+ .network-input {
496
+ width: 100%;
497
+ box-sizing: border-box;
498
+ padding: 0 8px;
499
+ height: 24px;
500
+ font-size: 14px;
501
+ border-radius: 4px;
502
+ border: 1px solid var(--dev-tool-border-color);
503
+ background-color: transparent;
504
+ transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);
505
+ color: var(--dev-tool-text-color, inherit);
506
+ }
507
+
508
+ .network-input:focus {
509
+ border-color: var(--dev-tool-primary-color, #9254de);
510
+ box-shadow: 0 0 0 2px rgb(146 84 222 / 10%);
511
+ }
512
+
513
+ .network-textarea {
514
+ padding: 8px;
515
+ width: 100%;
516
+ box-sizing: border-box;
517
+ font-size: 14px;
518
+ border-radius: 4px;
519
+ border: 1px solid var(--dev-tool-border-color);
520
+ background-color: transparent;
521
+ transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);
522
+ color: var(--dev-tool-text-color, inherit);
523
+ min-height: 80px;
524
+ }
525
+
526
+ .network-textarea:focus {
527
+ border-color: var(--dev-tool-primary-color, #9254de);
528
+ box-shadow: 0 0 0 2px rgb(146 84 222 / 10%);
529
+ }
530
+
531
+ .form-error-message {
532
+ padding: 4px 6px;
533
+ height: 24px;
534
+ line-height: 24px;
535
+ color: #ff4d4f; /* softer red */
536
+ font-size: 12px;
537
+ }
538
+
539
+ .network-header-list,
540
+ .network-param-list {
541
+ display: flex;
542
+ flex-direction: column;
543
+ gap: 8px;
544
+ margin-bottom: 8px;
545
+ }
546
+
547
+ .network-header-item,
548
+ .network-param-item {
549
+ display: flex;
550
+ align-items: center;
551
+ gap: 8px;
552
+ }
553
+
554
+ .network-header-item .network-input,
555
+ .network-param-item .network-input {
556
+ flex: 1;
557
+ min-width: 0; /* Prevents flex item from overflowing */
558
+ }
559
+
560
+ .network-empty {
561
+ color: var(--dev-tool-info-color);
562
+ text-align: center;
563
+ padding: 12px 0;
564
+ font-size: 13px;
565
+ }
566
+
567
+ .network-body-data-item {
568
+ display: flex;
569
+ align-items: center;
570
+ }
571
+
572
+ .network-send-buttons {
573
+ position: sticky;
574
+ display: flex;
575
+ justify-content: space-between;
576
+ gap: 12px;
577
+ width: 100%;
578
+ margin-top: 16px;
579
+ padding-bottom: 16px;
580
+ background-color: var(--dev-tool-bg3-color);
581
+ }
582
+
583
+ .network-send-button,
584
+ .network-send-button-last {
585
+ flex: 1;
586
+ margin: 0 !important; /* override default margin */
587
+ border-radius: 6px;
588
+ }
589
+ </style>