api-render-ui 1.0.0 → 1.0.2

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/api-render-ui.js CHANGED
@@ -27,6 +27,37 @@
27
27
  throw new Error('Invalid mount point specified');
28
28
  }
29
29
 
30
+ // 默认值生成器函数
31
+ function getDefaultValues(fieldSchema) {
32
+ // 优先使用schema中定义的默认值
33
+ if ('default' in fieldSchema) {
34
+ return fieldSchema.default;
35
+ }
36
+
37
+ // 处理类型数组(如anyOf情况)
38
+ const types = Array.isArray(fieldSchema.type) ? fieldSchema.type : [fieldSchema.type];
39
+
40
+ for (const type of types) {
41
+ switch (type) {
42
+ case 'string':
43
+ case 'string': case 'password': case 'email':
44
+ return '';
45
+ case 'number': case 'float': case 'double': case 'integer':
46
+ return 0;
47
+ case 'boolean':
48
+ return false;
49
+ case 'array':
50
+ return [];
51
+ case 'object':
52
+ return {};
53
+ case 'null':
54
+ return null;
55
+ }
56
+ }
57
+
58
+ // 默认返回null(安全处理)
59
+ return null;
60
+ }
30
61
 
31
62
  // 解析OpenAPI规范并构建API操作列表
32
63
  function parseOpenAPI(openapiSpec) {
@@ -40,24 +71,53 @@
40
71
  const apiOperator = {
41
72
  method: method.toUpperCase(),
42
73
  url: path,
43
- parametersQueryOrPath: [],
44
- parametersBody: null
74
+ apiDetailInfo: null,
75
+ requestBody: null,
76
+ response: {},
77
+ auths: [
78
+ {
79
+ type: "No Auth"
80
+ },
81
+ {
82
+ type: "Basic Auth",
83
+ parameters: [
84
+ {
85
+ name: "userName",
86
+ value: ""
87
+ },
88
+ {
89
+ name: "password",
90
+ value: ""
91
+ }
92
+ ]
93
+ }
94
+ ]
45
95
  };
46
96
 
47
- // 处理参数
48
- if (operation.parameters) {
49
- operation.parameters.forEach(param => {
50
- // 处理path/query参数
51
- if (param.in === 'path' || param.in === 'query') {
52
- apiOperator.parametersQueryOrPath.push(param);
53
- }
54
- // 处理body参数
55
- else if (param.in === 'body') {
56
- apiOperator.parametersBody = param;
97
+ // requestBody
98
+ if (operation.requestBody) {
99
+
100
+ const content = operation.requestBody.content['application/json'];
101
+ if (!content) return;
102
+
103
+ const schema = content.schema;
104
+ if (schema.$ref) {
105
+ const modelName = schema.$ref.split('/').pop();
106
+ const modelSchema = openapiSpec.components.schemas[modelName];
107
+
108
+ if (modelSchema) {
109
+ const model = {};
110
+
111
+ // 处理所有属性
112
+ Object.entries(modelSchema.properties).forEach(([field, fieldSchema]) => {
113
+ model[field] = getDefaultValues(fieldSchema);
114
+ });
115
+
116
+ apiOperator.requestBody = model;
57
117
  }
58
- });
118
+ }
59
119
  }
60
-
120
+ apiOperator.apiDetailInfo = operation;
61
121
  // 添加到结果列表
62
122
  apiOperatorList.push(apiOperator);
63
123
  });
@@ -71,7 +131,7 @@
71
131
  console.log('解析结果:', apiOperatorList);
72
132
 
73
133
  // 生成内容
74
- apiOperatorList.forEach(item => {
134
+ apiOperatorList.forEach(apiOperator => {
75
135
  const reqOperator = document.createElement('div');
76
136
  reqOperator.setAttribute('data-layer', 'apioperator');
77
137
  reqOperator.className = 'Apioperator codigma-apioperator';
@@ -86,9 +146,9 @@
86
146
  methodType.className = 'Methodtype codigma-methodtype';
87
147
 
88
148
  const methodValue = document.createElement('div');
89
- methodValue.setAttribute('data-layer', item.method.toLowerCase());
90
- methodValue.className = `${item.method} codigma-${item.method.toLowerCase()}`;
91
- methodValue.textContent = item.method;
149
+ methodValue.setAttribute('data-layer', apiOperator.method.toLowerCase());
150
+ methodValue.className = `${apiOperator.method} codigma-${apiOperator.method.toLowerCase()}`;
151
+ methodValue.textContent = apiOperator.method;
92
152
 
93
153
  methodType.appendChild(methodValue);
94
154
  methodContainer.appendChild(methodType);
@@ -98,24 +158,25 @@
98
158
  const urlElement = document.createElement('div');
99
159
  urlElement.setAttribute('data-layer', 'requrl');
100
160
  urlElement.className = 'Requrl codigma-requrl';
101
- urlElement.textContent = item.url;
161
+ urlElement.textContent = apiOperator.url;
102
162
  reqOperator.appendChild(urlElement);
103
163
 
104
164
  this.container.appendChild(reqOperator);
105
165
 
106
166
  // 添加点击事件
107
- reqOperator.addEventListener('click', renderApiUnit(item, this.container, elementMap));
167
+ reqOperator.addEventListener('click', renderApiUnit(apiOperator, this.container, elementMap));
108
168
  });
109
169
 
110
170
  // 清空挂载点并插入新内容
111
171
  mountElement.innerHTML = '';
112
172
  mountElement.appendChild(this.container);
113
173
 
114
- function renderApiUnit(item, containerRef, elementMap) {
174
+ function renderApiUnit(apiOperator, containerRef, elementMap) {
175
+ let responseSectionRef = null;
115
176
  return function (evt) {
116
177
  console.log('点击的API操作:');
117
- console.log('方法:', item.method);
118
- console.log('URL:', item.url);
178
+ console.log('方法:', apiOperator.method);
179
+ console.log('URL:', apiOperator.url);
119
180
  console.log('------------------------');
120
181
 
121
182
  const currentTarget = evt.currentTarget;
@@ -126,22 +187,47 @@
126
187
  elementMap.delete(currentTarget); // 清除映射
127
188
  return;
128
189
  }
129
-
130
- // 示例变量赋值(根据实际需要使用)
131
- let method = item.method;
132
- let url = item.url;
133
- let parametersQueryOrPath = item.parametersQueryOrPath;
134
- let parametersBody = item.parametersBody;
135
- let contentType = 'application/json';
136
- let acceptType = 'application/json';
137
- let userName = 'admin';
138
- let password = 'secret';
139
190
 
140
191
  // 创建根容器
141
192
  const apiContainer = document.createElement('div');
142
193
  apiContainer.setAttribute('data-layer', 'apiunit');
143
194
  apiContainer.className = 'Requnit codigma-apiunit';
144
195
  // 请求操作区
196
+ const reqOperator = createReqOperator();
197
+ apiContainer.appendChild(reqOperator);
198
+ // 请求内容区
199
+ const reqContent = document.createElement('div');
200
+ reqContent.setAttribute('data-layer', 'reqcontent');
201
+ reqContent.className = 'Reqcontent codigma-apiunit-reqcontent';
202
+ // 参数部分
203
+ const paramSection = createSection(apiOperator);
204
+ // 头部部分
205
+ const headerSection = createSectionHeader(apiOperator);
206
+ // 授权部分
207
+ const authSection = createSectionAuth(apiOperator);
208
+ // 请求体部分
209
+ const bodySection = createSectionRequestBody(apiOperator.requestBody);
210
+
211
+ reqContent.append(paramSection, headerSection, authSection, bodySection);
212
+ apiContainer.appendChild(reqContent);
213
+ // 响应部分
214
+ const responseSection = createSectionResponse(apiOperator);
215
+ responseSectionRef = responseSection
216
+ apiContainer.appendChild(responseSection);
217
+
218
+ // 添加到文档
219
+ // 插入到当前元素后面
220
+ if (currentTarget.nextSibling) {
221
+ containerRef.insertBefore(apiContainer, currentTarget.nextSibling);
222
+ } else {
223
+ containerRef.appendChild(apiContainer);
224
+ }
225
+
226
+ // 存储映射关系
227
+ elementMap.set(currentTarget, apiContainer);
228
+ }
229
+
230
+ function createReqOperator() {
145
231
  const reqOperator = document.createElement('div');
146
232
  reqOperator.setAttribute('data-layer', 'apioperator');
147
233
  reqOperator.className = 'Reqoperator codigma-apiunit-apioperator';
@@ -152,7 +238,7 @@
152
238
  const methodTypeInner = document.createElement('div');
153
239
  methodTypeInner.setAttribute('data-layer', 'methodtype');
154
240
  methodTypeInner.className = 'Methodtype codigma-apiunit-methodtype';
155
- methodTypeInner.textContent = method;
241
+ methodTypeInner.textContent = apiOperator.method;
156
242
  methodType.appendChild(methodTypeInner);
157
243
  // 方法选项图标 - 使用内联SVG
158
244
  const methodOpt = document.createElement('div');
@@ -161,29 +247,21 @@
161
247
  methodOpt.className = 'Methodopt';
162
248
 
163
249
  // 创建内联SVG
164
- const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
165
- svg.setAttribute('width', '21');
166
- svg.setAttribute('height', '22');
167
- svg.setAttribute('viewBox', '0 0 21 22');
168
- svg.setAttribute('fill', 'none');
169
- svg.setAttribute('xmlns', 'http://www.w3.org/2000/svg');
170
-
171
- const path = document.createElementNS('http://www.w3.org/2000/svg', 'path');
172
- path.setAttribute('d', 'M5.5 8.5L10.5 13.5L15.5 8.5');
173
- path.setAttribute('stroke', 'var(--Labels---Vibrant---Controls-Primary--, #404040)');
174
- path.setAttribute('stroke-width', '2');
175
- path.setAttribute('stroke-linecap', 'round');
176
- path.setAttribute('stroke-linejoin', 'round');
177
-
178
- svg.appendChild(path);
250
+ const svg = createSvg();
179
251
  methodOpt.appendChild(svg);
180
252
  methodType.appendChild(methodOpt);
181
253
  reqOperator.appendChild(methodType);
182
254
  // 请求URL
183
- const reqUrl = document.createElement('div');
255
+ const reqUrl = createInputElement();
184
256
  reqUrl.setAttribute('data-layer', 'requrl');
185
257
  reqUrl.className = 'Requrl codigma-apiunit-requrl';
186
- reqUrl.textContent = url;
258
+ reqUrl.value = apiOperator.url; // 绑定初始值
259
+ // 可选:添加输入事件监听(根据需求)
260
+ reqUrl.addEventListener('input', (e) => {
261
+ console.log('当前值:', e.target.value);
262
+ // 这里可以添加保存逻辑(如更新状态/发送请求
263
+ apiOperator.url = e.target.value
264
+ });
187
265
  reqOperator.appendChild(reqUrl);
188
266
  // 发送按钮
189
267
  const sendButton = document.createElement('div');
@@ -194,23 +272,28 @@
194
272
  sendText.className = 'Send codigma-apiunit-send';
195
273
  sendText.textContent = 'Send';
196
274
  sendButton.appendChild(sendText);
275
+
276
+ sendButton.addEventListener('click', (e) => {
277
+ console.log('当前值:', e.target.value);
278
+ // 这里可以添加保存逻辑(如更新状态/发送请求
279
+ sendRequest(apiOperator, responseSectionRef)
280
+ });
281
+
197
282
  reqOperator.appendChild(sendButton);
198
- apiContainer.appendChild(reqOperator);
199
- // 请求内容区
200
- const reqContent = document.createElement('div');
201
- reqContent.setAttribute('data-layer', 'reqcontent');
202
- reqContent.className = 'Reqcontent codigma-apiunit-reqcontent';
203
- // 参数部分
283
+ return reqOperator;
284
+ }
285
+
286
+ function createSection(apiOperator) {
204
287
  const paramSection = document.createElement('div');
205
288
  paramSection.setAttribute('data-layer', 'paramters-section');
206
- paramSection.className = 'ParamtersSection codigma-apiunit-paramters-section';
289
+ paramSection.className = 'codigma-apiunit-paramters-section';
207
290
  // 参数容器头
208
291
  const paramCnr = document.createElement('div');
209
292
  paramCnr.setAttribute('data-layer', 'parameters-cnr');
210
- paramCnr.className = 'ParametersCnr codigma-apiunit-parameters-cnr';
293
+ paramCnr.className = 'codigma-apiunit-parameters-cnr';
211
294
  const paramText = document.createElement('div');
212
295
  paramText.setAttribute('data-layer', 'parameters');
213
- paramText.className = 'Parameters codigma-apiunit-send';
296
+ paramText.className = 'codigma-apiunit-send';
214
297
  paramText.textContent = 'Parameters';
215
298
  paramCnr.appendChild(paramText);
216
299
  paramSection.appendChild(paramCnr);
@@ -218,20 +301,25 @@
218
301
  const paramValues = document.createElement('div');
219
302
  paramValues.setAttribute('data-layer', 'paraKeyValues');
220
303
  paramValues.className = 'Parakeyvalues codigma-apiunit-parakeyvalues';
221
- const parameterRows = parametersQueryOrPath.map(parameterQueryOrPath => createRow(parameterQueryOrPath['name'], "000"))
304
+ let parameters = apiOperator.apiDetailInfo.parameters || [];
305
+ const parameterRows = parameters.filter(parameter => isPathOrQueryParam(parameter))
306
+ .map(parameter => createRow(parameter));
222
307
  paramValues.append(...parameterRows);
223
308
  paramSection.append(paramCnr, paramValues);
224
- // 头部部分
309
+ return paramSection;
310
+ }
311
+
312
+ function createSectionHeader(apiOperator) {
225
313
  const headerSection = document.createElement('div');
226
314
  headerSection.setAttribute('data-layer', 'headers-section');
227
- headerSection.className = 'HeadersSection codigma-apiunit-paramters-section';
315
+ headerSection.className = 'codigma-apiunit-paramters-section';
228
316
  // 头部容器头
229
317
  const headerCnr = document.createElement('div');
230
318
  headerCnr.setAttribute('data-layer', 'headers-cnr');
231
- headerCnr.className = 'HeadersCnr codigma-apiunit-parameters-cnr';
319
+ headerCnr.className = 'codigma-apiunit-parameters-cnr';
232
320
  const headerText = document.createElement('div');
233
321
  headerText.setAttribute('data-layer', 'headers');
234
- headerText.className = 'Headers codigma-apiunit-send';
322
+ headerText.className = 'codigma-apiunit-send';
235
323
  headerText.textContent = 'Headers';
236
324
  headerCnr.appendChild(headerText);
237
325
  headerSection.appendChild(headerCnr);
@@ -239,35 +327,15 @@
239
327
  const headerValues = document.createElement('div');
240
328
  headerValues.setAttribute('data-layer', 'paraKeyValues');
241
329
  headerValues.className = 'Parakeyvalues codigma-apiunit-parakeyvalues';
242
- // Content-Type
243
- const contentTypeRow = document.createElement('div');
244
- contentTypeRow.setAttribute('data-layer', 'keyValue1');
245
- contentTypeRow.className = 'Keyvalue1 codigma-apiunit-keyvalue';
246
- const contentTypeLabel = document.createElement('div');
247
- contentTypeLabel.setAttribute('data-layer', 'Content-Type:');
248
- contentTypeLabel.className = 'ContentType codigma-apiunit-send';
249
- contentTypeLabel.textContent = 'Content-Type:';
250
- const contentTypeValue = document.createElement('div');
251
- contentTypeValue.setAttribute('data-layer', 'valueText');
252
- contentTypeValue.className = 'Valuetext codigma-apiunit-valuetext';
253
- contentTypeValue.textContent = contentType;
254
- contentTypeRow.append(contentTypeLabel, contentTypeValue);
255
- // Accept
256
- const acceptRow = document.createElement('div');
257
- acceptRow.setAttribute('data-layer', 'keyValue2');
258
- acceptRow.className = 'Keyvalue2 codigma-apiunit-keyvalue';
259
- const acceptLabel = document.createElement('div');
260
- acceptLabel.setAttribute('data-layer', 'Accept:');
261
- acceptLabel.className = 'Accept codigma-apiunit-send';
262
- acceptLabel.textContent = 'Accept:';
263
- const acceptValue = document.createElement('div');
264
- acceptValue.setAttribute('data-layer', 'valueText');
265
- acceptValue.className = 'Valuetext codigma-apiunit-valuetext';
266
- acceptValue.textContent = acceptType;
267
- acceptRow.append(acceptLabel, acceptValue);
268
- headerValues.append(contentTypeRow, acceptRow);
330
+ let parameters = apiOperator.apiDetailInfo.parameters || [];
331
+ const headerRows = parameters.filter(parameter => isHeaderParam(parameter))
332
+ .map(parameter => createRow(parameter));
333
+ headerValues.append(...headerRows);
269
334
  headerSection.append(headerCnr, headerValues);
270
- // 授权部分
335
+ return headerSection;
336
+ }
337
+
338
+ function createSectionAuth(apiOperator) {
271
339
  const authSection = document.createElement('div');
272
340
  authSection.setAttribute('data-layer', 'authorization-section');
273
341
  authSection.className = 'AuthorizationSection codigma-apiunit-paramters-section';
@@ -285,35 +353,20 @@
285
353
  const authValues = document.createElement('div');
286
354
  authValues.setAttribute('data-layer', 'paraKeyValues');
287
355
  authValues.className = 'Parakeyvalues codigma-apiunit-parakeyvalues';
288
- // 用户名
289
- const userRow = document.createElement('div');
290
- userRow.setAttribute('data-layer', 'keyValue1');
291
- userRow.className = 'Keyvalue1 codigma-apiunit-keyvalue';
292
- const userLabel = document.createElement('div');
293
- userLabel.setAttribute('data-layer', 'Username:');
294
- userLabel.className = 'Username codigma-apiunit-send';
295
- userLabel.textContent = 'Username:';
296
- const userValue = document.createElement('div');
297
- userValue.setAttribute('data-layer', 'valueText');
298
- userValue.className = 'Valuetext codigma-apiunit-valuetext';
299
- userValue.textContent = userName;
300
- userRow.append(userLabel, userValue);
301
- // 密码
302
- const passRow = document.createElement('div');
303
- passRow.setAttribute('data-layer', 'keyValue2');
304
- passRow.className = 'Keyvalue2 codigma-apiunit-keyvalue';
305
- const passLabel = document.createElement('div');
306
- passLabel.setAttribute('data-layer', 'Password:');
307
- passLabel.className = 'Password codigma-apiunit-send';
308
- passLabel.textContent = 'Password:';
309
- const passValue = document.createElement('div');
310
- passValue.setAttribute('data-layer', 'valueText');
311
- passValue.className = 'Valuetext codigma-apiunit-valuetext';
312
- passValue.textContent = password;
313
- passRow.append(passLabel, passValue);
314
- authValues.append(userRow, passRow);
356
+
357
+ let auths = apiOperator.auths || []
358
+ const authTypeRow = createSelectRow(auths, authValues)
359
+ if(auths.length > 0) {
360
+ let parameters = apiOperator.auths[0].parameters || [];
361
+ const authRows = parameters.map(parameter => createRow(parameter));
362
+ authValues.append(authTypeRow, ...authRows);
363
+ }
364
+
315
365
  authSection.append(authCnr, authValues);
316
- // 请求体部分
366
+ return authSection;
367
+ }
368
+
369
+ function createSectionRequestBody(requestBody) {
317
370
  const bodySection = document.createElement('div');
318
371
  bodySection.setAttribute('data-layer', 'request-body-section');
319
372
  bodySection.className = 'RequestBodySection codigma-apiunit-request-body-section';
@@ -328,15 +381,15 @@
328
381
  bodyCnr.appendChild(bodyText);
329
382
  bodySection.appendChild(bodyCnr);
330
383
  // 请求体内容
331
- const bodyValue = document.createElement('div');
384
+ const bodyValue = document.createElement('textarea');
332
385
  bodyValue.setAttribute('data-layer', 'bodyTextValue');
333
- bodyValue.className = 'Id0CategoryId0NameNamePhotourlsTagsId0NameStatusAvailable codigma-apiunit-requrl';
334
- bodyValue.textContent = JSON.stringify(parametersBody);
386
+ bodyValue.className = 'Id0CategoryId0NameNamePhotourlsTagsId0NameStatusAvailable codigma-apiunit-parakeyvalues';
387
+ bodyValue.value = JSON.stringify(requestBody);
335
388
  bodySection.appendChild(bodyValue);
389
+ return bodySection;
390
+ }
336
391
 
337
- reqContent.append(paramSection, headerSection, authSection, bodySection);
338
- apiContainer.appendChild(reqContent);
339
- // 响应部分
392
+ function createSectionResponse(apiOperator) {
340
393
  const responseSection = document.createElement('div');
341
394
  responseSection.setAttribute('data-layer', 'reqresponse');
342
395
  responseSection.className = 'Reqresponse codigma-apiunit-reqresponse';
@@ -357,44 +410,95 @@
357
410
  responseText.textContent = 'Response';
358
411
  responseCnr.appendChild(responseText);
359
412
  responseTitle.appendChild(responseCnr);
360
- const timeStatus = document.createElement('div');
361
- timeStatus.setAttribute('data-layer', 'Time Status:0');
362
- timeStatus.className = 'TimeStatus0 codigma-apiunit-send';
363
- timeStatus.textContent = 'Time Status:0';
364
- responseDesc.append(responseTitle, timeStatus);
413
+ const timeStatusElement = createTimeStatusElement(apiOperator);
414
+ responseDesc.append(responseTitle, timeStatusElement);
365
415
  // 响应体
366
416
  const responseBody = document.createElement('div');
367
417
  responseBody.setAttribute('data-layer', 'responsebody');
368
418
  responseBody.className = 'Responsebody codigma-apiunit-responsebody';
369
419
  responseSection.append(responseDesc, responseBody);
370
- apiContainer.appendChild(responseSection);
420
+ return responseSection;
421
+ }
371
422
 
372
- // 添加到文档
373
- // 插入到当前元素后面
374
- if (currentTarget.nextSibling) {
375
- containerRef.insertBefore(apiContainer, currentTarget.nextSibling);
376
- } else {
377
- containerRef.appendChild(apiContainer);
378
- }
423
+ function createTimeStatusElement(apiOperator) {
424
+ const timeStatus = document.createElement('div');
425
+ timeStatus.setAttribute('data-layer', 'TimeStatus');
426
+ timeStatus.className = 'TimeStatus0 codigma-apiunit-send';
427
+ updateTimeStatus(timeStatus, apiOperator);
428
+ return timeStatus;
429
+ }
379
430
 
380
- // 存储映射关系
381
- elementMap.set(currentTarget, apiContainer);
431
+ function createRow(parameter) {
432
+ const petIdRow = document.createElement('div');
433
+ petIdRow.setAttribute('data-layer', 'keyValue');
434
+ petIdRow.className = 'Keyvalue codigma-apiunit-keyvalue';
435
+ const petIdLabel = document.createElement('div');
436
+ petIdLabel.setAttribute('data-layer', parameter["name"]);
437
+ petIdLabel.className = parameter["name"] + ' codigma-apiunit-send';
438
+ petIdLabel.textContent = parameter["name"] + ':';
439
+ const petIdValue = createInputElement();
440
+ petIdValue.setAttribute('data-layer', 'valueText');
441
+ petIdValue.className = 'Valuetext codigma-apiunit-valuetext';
442
+ petIdValue.value = parameter["value"] || "";
382
443
 
383
- function createRow(parameterName, parameter) {
384
- const petIdRow = document.createElement('div');
385
- petIdRow.setAttribute('data-layer', 'keyValue');
386
- petIdRow.className = 'Keyvalue codigma-apiunit-keyvalue';
387
- const petIdLabel = document.createElement('div');
388
- petIdLabel.setAttribute('data-layer', parameterName);
389
- petIdLabel.className = parameterName + ' codigma-apiunit-send';
390
- petIdLabel.textContent = parameterName + ':';
391
- const petIdValue = document.createElement('div');
392
- petIdValue.setAttribute('data-layer', 'valueText');
393
- petIdValue.className = 'Valuetext codigma-apiunit-valuetext';
394
- petIdValue.textContent = parameter;
395
- petIdRow.append(petIdLabel, petIdValue);
396
- return petIdRow;
397
- }
444
+ // 可选:添加输入事件监听(根据需求)
445
+ petIdValue.addEventListener('input', (e) => {
446
+ console.log('当前值:', e.target.value);
447
+ // 这里可以添加保存逻辑(如更新状态/发送请求
448
+ parameter["value"] = e.target.value
449
+ });
450
+ petIdRow.append(petIdLabel, petIdValue);
451
+ return petIdRow;
452
+ }
453
+
454
+ function createInputElement() {
455
+ const inputText = document.createElement('input');
456
+ inputText.setAttribute('type', 'text');
457
+ inputText.setAttribute('name', 'text-input');
458
+ inputText.setAttribute('label', 'text-input');
459
+ inputText.setAttribute('autocomplete', 'off');
460
+ return inputText;
461
+ }
462
+
463
+ function createSelectRow(auths, authValues) {
464
+ // 创建外层容器div
465
+ const container = document.createElement('div');
466
+ container.setAttribute('data-layer', 'keyValue');
467
+ container.className = 'Keyvalue codigma-apiunit-keyvalue';
468
+
469
+ // 创建type显示div
470
+ const typeLabel = document.createElement('div');
471
+ typeLabel.setAttribute('data-layer', "type");
472
+ typeLabel.className = 'type codigma-apiunit-send';
473
+ typeLabel.textContent = 'Type:';
474
+
475
+ // 创建select元素
476
+ const selectElement = document.createElement('select');
477
+ selectElement.name = 'text-select';
478
+ selectElement.label = 'text-select';
479
+ selectElement.setAttribute('data-layer', 'valueText');
480
+
481
+ // 示例选项(可根据实际需求添加
482
+ auths.forEach(auth => {
483
+ const option1 = document.createElement('option');
484
+ option1.value = auth["type"];
485
+ option1.textContent = auth["type"];
486
+ selectElement.appendChild(option1);
487
+ })
488
+
489
+ // 添加选择事件监听
490
+ selectElement.addEventListener('change', function (event) {
491
+ //切换前先移除掉原来的元素
492
+ authValues && Array.from(authValues.children).slice(1).forEach(el => el.remove());
493
+ const auth = auths[event.target.selectedIndex];
494
+ let parameters = auth.parameters || [];
495
+ const authRows = parameters.map(parameter => createRow(parameter));
496
+ authValues.append(...authRows);
497
+ });
498
+ // 组装DOM结构
499
+ container.appendChild(typeLabel);
500
+ container.appendChild(selectElement);
501
+ return container;
398
502
  }
399
503
  }
400
504
  };
@@ -405,4 +509,364 @@
405
509
  } else {
406
510
  global.ApiRenderer = ApiRenderer;
407
511
  }
408
- })(window);
512
+ })(window);
513
+
514
+ function isPathOrQueryParam(param) {
515
+ return param.in === 'path' || param.in === 'query';
516
+ }
517
+
518
+ function isHeaderParam(param) {
519
+ return param.in === 'header';
520
+ }
521
+
522
+ /**
523
+ *
524
+ *const apiDetailInfo: any = {
525
+ customQueryparameters: [
526
+ {
527
+ name: '',
528
+ value: ''
529
+ }
530
+ ],
531
+ customHeaderparameters: [
532
+ {
533
+ name: '',
534
+ value: ''
535
+ }
536
+ ],
537
+ bodyModel: ""
538
+ };
539
+
540
+ const apiInfo: any = {
541
+ index: this.getRandomInt(10000, 20000),
542
+ id: this.uuid(),
543
+ serviceName: "",
544
+ method: "get",
545
+ symbol: "GET",
546
+ path: "",
547
+ apiUrl: "",
548
+ summary: "",
549
+ label: "Untitle",
550
+ tabLabel: "Untitle",
551
+ apiDetailInfo: apiDetailInfo,
552
+ server: "",
553
+ symbolColor: "green",
554
+ custom: true,
555
+ isActive: true,
556
+ response: {}
557
+ }
558
+ *
559
+ *
560
+ * const apiOperator = {
561
+ method: method.toUpperCase(),
562
+ url: path,
563
+ apiDetailInfo: null,
564
+ requestBody: null
565
+ }
566
+
567
+ * @param {*} apiOperator
568
+ * @param {*} apiInfo
569
+ */
570
+
571
+ function sendRequest(apiOperator, responseSectionRef) {
572
+ let reuqestUrl = getRequestUrl(apiOperator);
573
+ const result = checkIfParameter(apiOperator);
574
+
575
+ let header = result.hasRequestBody ? 'application/json' :
576
+ (result.hasRequestFormData ? 'application/x-www-form-urlencoded' : 'application/json');
577
+ let headers = {
578
+ 'Content-Type': header
579
+ }
580
+
581
+ //TODO
582
+ if (apiOperator.custom) {
583
+ for (let index = 0; index < apiOperator.apiDetailInfo.customHeaderparameters.length; index++) {
584
+ const paras = apiOperator.apiDetailInfo.customHeaderparameters[index];
585
+ if (paras.name != '' && paras.value != '' && paras.name != null && paras.value != null) {
586
+ headers[paras.name] = paras.value
587
+ }
588
+ }
589
+ }
590
+
591
+ let body = result.hasRequestBody ? apiOperator.requestBody :
592
+ (result.hasRequestFormData ? getRequestFormData(apiOperator.apiDetailInfo) : null);
593
+
594
+ //TODO
595
+ if (apiOperator.custom) {
596
+ if (apiOperator.method.toUpperCase() == "POST" || apiOperator.method.toUpperCase() == "PUT") {
597
+ body = apiOperator.apiDetailInfo.bodyModel;
598
+ }
599
+ }
600
+
601
+ apiOperator.ifSendingRequest = true;
602
+ const startTime = Date.now(); // 记录开始时间
603
+
604
+ apiOperator.controller = new AbortController();
605
+ const signal = apiOperator.controller.signal;
606
+
607
+ //正在发送请求时创建遮罩层
608
+ const overlayLayerContainer = createRequestOverlayLayer(apiOperator, responseSectionRef);
609
+
610
+ // 使用 fetch 发送请求,并传递 signal
611
+ fetch(reuqestUrl, {
612
+ method: apiOperator.method.toUpperCase(),
613
+ headers: headers,
614
+ body: body != null ? JSON.stringify(body) : null,
615
+ signal: signal
616
+ })
617
+ .then(response => {
618
+ if (!response.ok) {
619
+ apiOperator.response = {
620
+ status: response.status,
621
+ statusText: response.statusText
622
+ }
623
+
624
+ const endTime = Date.now(); // 即使在错误的情况下也记录结束时间
625
+ apiOperator.requestDuration = formatDuration(endTime - startTime);
626
+ apiOperator.ifSendingRequest = false;
627
+ // apiOperator.responseJsoneditor.value = "";
628
+ throw new Error('Network response was not ok.');
629
+ }
630
+ const endTime = Date.now(); // 记录结束时间
631
+ apiOperator.requestDuration = formatDuration(endTime - startTime); // 计算耗时
632
+
633
+ const responsebodyElement = responseSectionRef.querySelector('[data-layer="responsebody"]');
634
+ responsebodyElement.removeChild(overlayLayerContainer);
635
+
636
+ apiOperator.ifSendingRequest = false;
637
+ apiOperator.response = {
638
+ status: response.status,
639
+ statusText: response.statusText
640
+ }
641
+
642
+ // 在responseSectionRef元素范围内查找TimeStatus元素
643
+ const timeStatusElement = responseSectionRef.querySelector('[data-layer="TimeStatus"]');
644
+ if (timeStatusElement) {
645
+ updateTimeStatus(timeStatusElement, apiOperator);
646
+ } else {
647
+ console.log("在reqresponse范围内未找到TimeStatus元素");
648
+ }
649
+
650
+ let responseClone = response.clone();
651
+ return response.json() // 解析为json
652
+ .catch(error => {
653
+ // 如果解析 JSON 失败,则回退到文本解析
654
+ return responseClone.text();
655
+ });
656
+ })
657
+ .then(data => {
658
+ apiOperator.gotResponse = true;
659
+ // 此时 data 可能是 JSON 对象,也可能是文本字符串
660
+ if (typeof data === 'object') {
661
+ // 假设 data 是 JSON 对象,你可以在这里处理它
662
+ console.log('Received JSON:', data);
663
+ const responsebodyElement = responseSectionRef.querySelector('[data-layer="responsebody"]');
664
+ responsebodyElement.textContent = JSON.stringify(data, null, 4)
665
+ } else {
666
+ // 假设 data 是文本字符串,你可以在这里处理它
667
+ console.log('Received text:', data);
668
+ responsebodyElement.textContent = data;
669
+ }
670
+ })
671
+ .catch(error => {
672
+ // 错误处理
673
+ console.error('There has been a problem with your fetch operation:', error);
674
+ });
675
+ }
676
+
677
+ function updateTimeStatus(timeStatus, apiOperator) {
678
+ timeStatus.textContent
679
+ = `Status: ${apiOperator.response.status || ""} ${apiOperator.response.statusText || ""} Time: ${apiOperator.requestDuration || ""}`;
680
+ }
681
+
682
+ function createRequestOverlayLayer(apiOperator, responseSectionRef) {
683
+ // 创建主容器
684
+ const container = document.createElement('div');
685
+ Object.assign(container.style, {
686
+ position: 'absolute',
687
+ top: 0,
688
+ width: '100%',
689
+ height: '100%',
690
+ display: 'flex',
691
+ justifyContent: 'center',
692
+ alignItems: 'center',
693
+ backgroundColor: 'rgb(255, 255, 255)',
694
+ opacity: 0.8
695
+ });
696
+
697
+ // 创建内容容器
698
+ const contentDiv = document.createElement('div');
699
+ Object.assign(contentDiv.style, {
700
+ display: 'flex',
701
+ gap: '5px',
702
+ alignItems: 'center',
703
+ });
704
+
705
+ // 创建文本div
706
+ const textDiv = document.createElement('div');
707
+ textDiv.textContent = 'Sending request...';
708
+
709
+ // 创建取消按钮
710
+ const cancelBtn = document.createElement('button');
711
+ cancelBtn.className = 'request-cancel-btn';
712
+ Object.assign(cancelBtn.style, {
713
+ border: '0px'
714
+ });
715
+ cancelBtn.textContent = 'Cancel';
716
+
717
+ const responsebodyElement = responseSectionRef.querySelector('[data-layer="responsebody"]');
718
+ // 组装DOM结构
719
+ contentDiv.appendChild(textDiv);
720
+ contentDiv.appendChild(cancelBtn);
721
+ container.appendChild(contentDiv);
722
+ responsebodyElement.appendChild(container);
723
+
724
+ // 添加点击事件
725
+ cancelBtn.addEventListener('click', (e) => {
726
+ // 如果你想取消请求,调用 controller 的 abort 方法
727
+ if (apiOperator.controller) {
728
+ apiOperator.controller.abort();
729
+ apiOperator.ifSendingRequest = false;
730
+ container.style.display = 'none';
731
+ responsebodyElement.removeChild(container);
732
+ }
733
+ });
734
+
735
+ return container
736
+ }
737
+
738
+ function checkIfParameter(apiOperator) {
739
+ let hasRequestBody = false;
740
+ let hasRequestFormData = false;
741
+ const parameters = apiOperator.apiDetailInfo.parameters;
742
+ if (parameters) {
743
+ for (let index = 0; index < parameters.length; index++) {
744
+ const parameter = parameters[index];
745
+ if (parameter.in == "query" || parameter.in == "path") {
746
+ } else if (parameter.in == "body") {
747
+ hasRequestBody = true;
748
+ parameter.name = parameter.name.charAt(0).toUpperCase() + parameter.name.slice(1);
749
+ } else if (parameter.in == "formData") {
750
+ hasRequestFormData = true;
751
+ }
752
+ }
753
+ }
754
+
755
+ //support openapi 3.0
756
+ const requestBody = apiOperator.apiDetailInfo.requestBody;
757
+ if (requestBody) {
758
+ hasRequestBody = true;
759
+ }
760
+ // 返回包含两个状态的对象
761
+ return { hasRequestBody, hasRequestFormData };
762
+ }
763
+
764
+ function formatDuration(milliseconds) {
765
+ let totalSeconds = Math.floor(milliseconds / 1000);
766
+ let seconds = totalSeconds % 60;
767
+ let minutes = Math.floor(totalSeconds / 60) % 60;
768
+ let hours = Math.floor(totalSeconds / (60 * 60));
769
+
770
+ // 毫秒部分
771
+ let millisecondsPart = Math.floor(milliseconds % 1000);
772
+ // 毫秒不足三位时前面补0
773
+ millisecondsPart = millisecondsPart.toString().padStart(3, '0');
774
+
775
+ // 时分秒不足两位时前面补0
776
+ hours = hours.toString().padStart(2, '0');
777
+ minutes = minutes.toString().padStart(2, '0');
778
+ seconds = seconds.toString().padStart(2, '0');
779
+
780
+ // 返回格式化的字符串
781
+ return `${hours}h${minutes}m${seconds}s${millisecondsPart}ms`;
782
+ }
783
+
784
+ function getRequestUrl(apiOperator) {
785
+ let reuqestUrl = apiOperator.url;
786
+
787
+ const requestParameters = apiOperator.apiDetailInfo.parameters || [];
788
+ if (requestParameters == null) {
789
+ return reuqestUrl;
790
+ }
791
+
792
+ for (const element of requestParameters) {
793
+ if (element.in == "path") {
794
+ reuqestUrl = reuqestUrl.replace("{" + element.name + "}", element.value);
795
+ }
796
+ }
797
+
798
+ let queryParams = getQueryParams(apiOperator, requestParameters);
799
+ reuqestUrl = queryParams.length > 0 ? (reuqestUrl + "?" + queryParams.join("&")) : reuqestUrl;
800
+
801
+ return reuqestUrl;
802
+ }
803
+
804
+ function getQueryParams(apiOperator, requestParameters) {
805
+ let queryParams = [];
806
+ for (const element of requestParameters) {
807
+ if (element.in == "query") {
808
+ if (element.type == "array" || (element.schema != null && element.schema.type == 'array')) {
809
+ if (element.value != null) {
810
+ for (let index = 0; index < element.value.length; index++) {
811
+ queryParams.push(element.name + "=" + element.value[index].value);
812
+ }
813
+ }
814
+ } else {
815
+ queryParams.push(element.name + "=" + element.value);
816
+ }
817
+ }
818
+ }
819
+
820
+ if (apiOperator.custom) {
821
+ for (let index = 0; index < apiOperator.apiDetailInfo.customQueryparameters.length; index++) {
822
+ const paras = apiOperator.apiDetailInfo.customQueryparameters[index];
823
+ if (paras.name != '' && paras.value != '' && paras.name != null && paras.value != null) {
824
+ queryParams.push(paras.name + "=" + paras.value)
825
+ }
826
+ }
827
+ }
828
+
829
+ return queryParams;
830
+ }
831
+
832
+ function getRequestFormData(apiDetailInfo) {
833
+ let formData = '';
834
+ const requestParameters = apiDetailInfo.parameters;
835
+ if (requestParameters == null) {
836
+ return "";
837
+ }
838
+
839
+ let first = 0;
840
+ for (const element of requestParameters) {
841
+ if (element.in == "formData") {
842
+ if (first == 0) {
843
+ formData = element.name + "=" + element.value;
844
+ } else {
845
+ formData = formData + "&" + element.name + "=" + element.value;
846
+ }
847
+ first++;
848
+ }
849
+ }
850
+ return formData;
851
+ }
852
+
853
+
854
+
855
+ function createSvg() {
856
+ const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
857
+ svg.setAttribute('width', '21');
858
+ svg.setAttribute('height', '22');
859
+ svg.setAttribute('viewBox', '0 0 21 22');
860
+ svg.setAttribute('fill', 'none');
861
+ svg.setAttribute('xmlns', 'http://www.w3.org/2000/svg');
862
+
863
+ const path = document.createElementNS('http://www.w3.org/2000/svg', 'path');
864
+ path.setAttribute('d', 'M5.5 8.5L10.5 13.5L15.5 8.5');
865
+ path.setAttribute('stroke', 'var(--Labels---Vibrant---Controls-Primary--, #404040)');
866
+ path.setAttribute('stroke-width', '2');
867
+ path.setAttribute('stroke-linecap', 'round');
868
+ path.setAttribute('stroke-linejoin', 'round');
869
+
870
+ svg.appendChild(path);
871
+ return svg;
872
+ }