mirror of
https://gitee.com/eolink_admin/postcat.git
synced 2024-11-30 18:57:48 +08:00
API test support send file and response preview file/image (#74)
* fix: extension overflow page not show * feat: api test support send file * feat: response support file Co-authored-by: 夜鹰 <17kungfuboy@gmail.com>
This commit is contained in:
parent
69753f1f1f
commit
f83a674b1f
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "eoapi",
|
"name": "eoapi",
|
||||||
"version": "1.1.1",
|
"version": "1.2.0-beta",
|
||||||
"main": "out/app/electron-main/main.js",
|
"main": "out/app/electron-main/main.js",
|
||||||
"description": "A lightweight, extensible API tool",
|
"description": "A lightweight, extensible API tool",
|
||||||
"homepage": "https://github.com/eolinker/eoapi.git",
|
"homepage": "https://github.com/eolinker/eoapi.git",
|
||||||
@ -68,4 +68,4 @@
|
|||||||
"node-module-alias": {
|
"node-module-alias": {
|
||||||
"eo": "./out"
|
"eo": "./out"
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -12,7 +12,6 @@
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<ace
|
<ace
|
||||||
style="height: 7em; width: 100%"
|
|
||||||
[config]="config"
|
[config]="config"
|
||||||
[disabled]="false"
|
[disabled]="false"
|
||||||
[(value)]="code"
|
[(value)]="code"
|
||||||
|
@ -79,6 +79,9 @@ export class EoEditorComponent implements AfterViewInit, OnInit, OnChanges {
|
|||||||
theme: 'tomorrow_night_eighties',
|
theme: 'tomorrow_night_eighties',
|
||||||
readOnly: false,
|
readOnly: false,
|
||||||
tabSize: 4,
|
tabSize: 4,
|
||||||
|
minLines:5,
|
||||||
|
maxLines: 20
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
constructor(private message: EoMessageService, private electron: ElectronService) {}
|
constructor(private message: EoMessageService, private electron: ElectronService) {}
|
||||||
|
@ -36,18 +36,6 @@ nz-sider {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
eo-api {
|
|
||||||
router-outlet + * {
|
|
||||||
display: block;
|
|
||||||
height: calc(100vh - var(--NAVBAR_HEIGHT) - var(--FOOTER_HEIGHT) - var(--remote-notification-height) - 46px);
|
|
||||||
overflow: auto;
|
|
||||||
}
|
|
||||||
.has_tab_page router-outlet + * {
|
|
||||||
height: calc(
|
|
||||||
100vh - var(--NAVBAR_HEIGHT) - var(--FOOTER_HEIGHT) - var(--remote-notification-height) - 45px - 47px
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.method_text_GET {
|
.method_text_GET {
|
||||||
color: var(--BLUE_TAG_BG);
|
color: var(--BLUE_TAG_BG);
|
||||||
}
|
}
|
||||||
|
@ -111,7 +111,6 @@ export class ApiGroupEditComponent implements OnInit {
|
|||||||
this.modalRef.destroy();
|
this.modalRef.destroy();
|
||||||
this.storage.run('groupBulkRemove', [data.group], (result: StorageRes) => {
|
this.storage.run('groupBulkRemove', [data.group], (result: StorageRes) => {
|
||||||
if (result.status === StorageResStatus.success) {
|
if (result.status === StorageResStatus.success) {
|
||||||
this.messageService.send({ type: 'updateGroupSuccess', data: {} });
|
|
||||||
//delete group api
|
//delete group api
|
||||||
if (data.api.length > 0) {
|
if (data.api.length > 0) {
|
||||||
this.messageService.send({ type: 'gotoBulkDeleteApi', data: { uuids: data.api } });
|
this.messageService.send({ type: 'gotoBulkDeleteApi', data: { uuids: data.api } });
|
||||||
|
@ -4,7 +4,6 @@ import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
|||||||
import { Select } from '@ngxs/store';
|
import { Select } from '@ngxs/store';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
ApiData,
|
|
||||||
RequestMethod,
|
RequestMethod,
|
||||||
RequestProtocol,
|
RequestProtocol,
|
||||||
StorageRes,
|
StorageRes,
|
||||||
|
@ -81,6 +81,7 @@ export class ApiTestService {
|
|||||||
baseFun: {
|
baseFun: {
|
||||||
reduceItemWhenAddChildItem: reduceItemWhenIsOprDepth,
|
reduceItemWhenAddChildItem: reduceItemWhenIsOprDepth,
|
||||||
watchCheckboxChange: opts.watchFormLastChange,
|
watchCheckboxChange: opts.watchFormLastChange,
|
||||||
|
importFile: opts.importFile
|
||||||
},
|
},
|
||||||
itemStructure: Object.assign({}, opts.itemStructure),
|
itemStructure: Object.assign({}, opts.itemStructure),
|
||||||
tdList: [
|
tdList: [
|
||||||
@ -114,8 +115,10 @@ export class ApiTestService {
|
|||||||
|
|
||||||
{
|
{
|
||||||
thKey: '参数值',
|
thKey: '参数值',
|
||||||
type: 'input',
|
type: 'autoCompleteAndFile',
|
||||||
modelKey: 'value',
|
modelKey: 'value',
|
||||||
|
switchVar: 'type',
|
||||||
|
swicthFile: 'file',
|
||||||
placeholder: '参数值',
|
placeholder: '参数值',
|
||||||
width: 300,
|
width: 300,
|
||||||
mark: 'value',
|
mark: 'value',
|
||||||
@ -273,7 +276,6 @@ export class ApiTestService {
|
|||||||
});
|
});
|
||||||
if (inData.history.response.responseType === 'text') {
|
if (inData.history.response.responseType === 'text') {
|
||||||
let bodyInfo = text2UiData(inData.history.response.body);
|
let bodyInfo = text2UiData(inData.history.response.body);
|
||||||
console.log(bodyInfo);
|
|
||||||
result.responseBody = bodyInfo.data;
|
result.responseBody = bodyInfo.data;
|
||||||
result.responseBodyType = bodyInfo.textType;
|
result.responseBodyType = bodyInfo.textType;
|
||||||
result.responseBodyJsonType = bodyInfo.rootType;
|
result.responseBodyJsonType = bodyInfo.rootType;
|
||||||
@ -282,7 +284,7 @@ export class ApiTestService {
|
|||||||
}
|
}
|
||||||
getTestDataFromApi(inData) {
|
getTestDataFromApi(inData) {
|
||||||
let editToTestParams = (arr) => {
|
let editToTestParams = (arr) => {
|
||||||
arr=arr||[];
|
arr = arr || [];
|
||||||
arr.forEach((val) => {
|
arr.forEach((val) => {
|
||||||
val.value = val.example;
|
val.value = val.example;
|
||||||
delete val.example;
|
delete val.example;
|
||||||
@ -334,7 +336,7 @@ export class ApiTestService {
|
|||||||
case 'formData': {
|
case 'formData': {
|
||||||
inData.requestBody.forEach((val) => {
|
inData.requestBody.forEach((val) => {
|
||||||
val.value = val.example;
|
val.value = val.example;
|
||||||
val.type = 'string';
|
val.type = val.type === 'file' ? 'file' : 'string';
|
||||||
delete val.example;
|
delete val.example;
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { Component, OnInit, Input, Output, EventEmitter, OnChanges, OnDestroy } from '@angular/core';
|
import { Component, OnInit, Input, Output, EventEmitter, OnChanges, OnDestroy, ChangeDetectorRef } from '@angular/core';
|
||||||
|
|
||||||
import { Subject } from 'rxjs';
|
import { Subject } from 'rxjs';
|
||||||
import { pairwise, takeUntil, debounceTime } from 'rxjs/operators';
|
import { pairwise, takeUntil, debounceTime } from 'rxjs/operators';
|
||||||
@ -10,7 +10,7 @@ import {
|
|||||||
} from '../../../../shared/services/api-test/api-test-params.model';
|
} from '../../../../shared/services/api-test/api-test-params.model';
|
||||||
import { ApiBodyType, JsonRootType } from '../../../../shared/services/storage/index.model';
|
import { ApiBodyType, JsonRootType } from '../../../../shared/services/storage/index.model';
|
||||||
import { ApiTestService } from '../api-test.service';
|
import { ApiTestService } from '../api-test.service';
|
||||||
import { Message, MessageService } from '../../../../shared/services/message';
|
import { EoMessageService } from 'eo/workbench/browser/src/app/eoui/message/eo-message.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'eo-api-test-body',
|
selector: 'eo-api-test-body',
|
||||||
@ -40,7 +40,11 @@ export class ApiTestBodyComponent implements OnInit, OnChanges, OnDestroy {
|
|||||||
private bodyType$: Subject<string> = new Subject<string>();
|
private bodyType$: Subject<string> = new Subject<string>();
|
||||||
private destroy$: Subject<void> = new Subject<void>();
|
private destroy$: Subject<void> = new Subject<void>();
|
||||||
private rawChange$: Subject<string> = new Subject<string>();
|
private rawChange$: Subject<string> = new Subject<string>();
|
||||||
constructor(private apiTest: ApiTestService, private messageService: MessageService) {
|
constructor(
|
||||||
|
private apiTest: ApiTestService,
|
||||||
|
private cdRef: ChangeDetectorRef,
|
||||||
|
private message: EoMessageService
|
||||||
|
) {
|
||||||
this.bodyType$.pipe(pairwise(), takeUntil(this.destroy$)).subscribe((val) => {
|
this.bodyType$.pipe(pairwise(), takeUntil(this.destroy$)).subscribe((val) => {
|
||||||
this.beforeChangeBodyByType(val[0]);
|
this.beforeChangeBodyByType(val[0]);
|
||||||
});
|
});
|
||||||
@ -168,6 +172,33 @@ export class ApiTestBodyComponent implements OnInit, OnChanges, OnDestroy {
|
|||||||
watchFormLastChange: () => {
|
watchFormLastChange: () => {
|
||||||
this.modelChange.emit(this.model);
|
this.modelChange.emit(this.model);
|
||||||
},
|
},
|
||||||
|
importFile: (inputArg) => {
|
||||||
|
if (inputArg.file.length === 0) return;
|
||||||
|
inputArg.item.value = '';
|
||||||
|
inputArg.item.files = [];
|
||||||
|
for (var i = 0; i < inputArg.file.length; i++) {
|
||||||
|
var val = inputArg.file[i];
|
||||||
|
if (val.size > 2 * 1024 * 1024) {
|
||||||
|
inputArg.item.value = '';
|
||||||
|
this.message.error('文件大小均需小于2M');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (var i = 0; i < inputArg.file.length; i++) {
|
||||||
|
var val = inputArg.file[i];
|
||||||
|
inputArg.item.value = val.name + ',' + inputArg.item.value;
|
||||||
|
let tmpReader = new FileReader();
|
||||||
|
tmpReader.readAsDataURL(val);
|
||||||
|
tmpReader.onload = function (_default) {
|
||||||
|
inputArg.item.files.splice(0, 0, {
|
||||||
|
name: val.name,
|
||||||
|
dataUrl: this.result,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
inputArg.item.value = inputArg.item.value.slice(0, inputArg.item.value.length - 1);
|
||||||
|
this.modelChange.emit(this.model);
|
||||||
|
},
|
||||||
});
|
});
|
||||||
this.cache['listConfSetting'] = Object.assign({}, this.listConf.setting);
|
this.cache['listConfSetting'] = Object.assign({}, this.listConf.setting);
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
</ng-template>
|
</ng-template>
|
||||||
</nz-empty>
|
</nz-empty>
|
||||||
</div>
|
</div>
|
||||||
<div class="p15" *ngIf="model.responseType">
|
<div class="p15" *ngIf="model.responseType" [ngSwitch]="model.responseType">
|
||||||
<div class="mb15 basic_info_bar cw f_row f_js {{ model.statusCode ? codeStatus.class : 'code_red' }}">
|
<div class="mb15 basic_info_bar cw f_row f_js {{ model.statusCode ? codeStatus.class : 'code_red' }}">
|
||||||
<div class="fs16" id="statusCode">{{ model.statusCode || 'No Response' }}</div>
|
<div class="fs16" id="statusCode">{{ model.statusCode || 'No Response' }}</div>
|
||||||
<div class="f_row_ac fs12">
|
<div class="f_row_ac fs12">
|
||||||
@ -13,7 +13,25 @@
|
|||||||
<span id="time">Time: {{ model.testDeny }}ms</span>
|
<span id="time">Time: {{ model.testDeny }}ms</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="text-center" *ngSwitchCase="'stream'">
|
||||||
|
<div *ngIf="!responseIsImg">
|
||||||
|
无法预览非文本类型的数据,您可以
|
||||||
|
<button class="eo_theme_btn_default mlr5" type="button" (click)="downloadResponseText()">下载返回结果</button>
|
||||||
|
,并用其他程序打开。
|
||||||
|
</div>
|
||||||
|
<!-- <div class="mt20" *ngIf="responseIsImg">
|
||||||
|
<img class="maw_100percent" [src]="model.blobUrl" />
|
||||||
|
</div> -->
|
||||||
|
</div>
|
||||||
|
<div class="text-center" *ngSwitchCase="'longText'">
|
||||||
|
响应结果超出可预览的大小,您可以
|
||||||
|
<button class="eo_theme_btn_default mlr5" type="button" (click)="downloadResponseText()">下载返回结果</button>
|
||||||
|
<!-- 或者
|
||||||
|
<button class="eo_theme_btn_default" type="button" (click)="newTabResponseText()">在新标签页中显示返回结果</button>
|
||||||
|
并用其他程序打开。 -->
|
||||||
|
</div>
|
||||||
<eo-editor
|
<eo-editor
|
||||||
|
*ngSwitchDefault
|
||||||
class="mt20"
|
class="mt20"
|
||||||
[autoFormat]="true"
|
[autoFormat]="true"
|
||||||
[(code)]="model.body"
|
[(code)]="model.body"
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { Component, Input, OnInit, OnChanges } from '@angular/core';
|
import { Component, Input, OnInit, OnChanges } from '@angular/core';
|
||||||
|
import { getBlobUrl } from 'eo/workbench/browser/src/app/utils';
|
||||||
import { ApiTestHistoryResponse } from '../../../../shared/services/storage/index.model';
|
import { ApiTestHistoryResponse } from '../../../../shared/services/storage/index.model';
|
||||||
import { ApiTestService } from '../api-test.service';
|
import { ApiTestService } from '../api-test.service';
|
||||||
@Component({
|
@Component({
|
||||||
@ -10,12 +11,33 @@ export class ApiTestResultResponseComponent implements OnInit, OnChanges {
|
|||||||
@Input() model: any | ApiTestHistoryResponse;
|
@Input() model: any | ApiTestHistoryResponse;
|
||||||
codeStatus: { status: string; cap: number; class: string };
|
codeStatus: { status: string; cap: number; class: string };
|
||||||
size: string;
|
size: string;
|
||||||
|
blobUrl:string='';
|
||||||
|
responseIsImg = false;
|
||||||
constructor(private apiTest: ApiTestService) {}
|
constructor(private apiTest: ApiTestService) {}
|
||||||
ngOnChanges(changes) {
|
ngOnChanges(changes) {
|
||||||
if (changes.model) {
|
if (changes.model) {
|
||||||
this.codeStatus = this.apiTest.getHTTPStatus(this.model.statusCode);
|
this.codeStatus = this.apiTest.getHTTPStatus(this.model.statusCode);
|
||||||
|
//show response
|
||||||
|
// this.responseIsImg =/\.((jpg)|(jpeg)|(png)|(gif)|(bmg))/i.test(this.model.blobFileName) || /image/.test(this.model.contentType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ngOnInit(): void {}
|
ngOnInit(): void {}
|
||||||
|
downloadResponseText() {
|
||||||
|
this.blobUrl=getBlobUrl(this.model.body, this.model.contentType);
|
||||||
|
const blobFileName = decodeURI(this.model.blobFileName);
|
||||||
|
const tmpAElem = document.createElement('a');
|
||||||
|
if ('download' in tmpAElem) {
|
||||||
|
tmpAElem.style.visibility = 'hidden';
|
||||||
|
tmpAElem.href = this.blobUrl;
|
||||||
|
tmpAElem.download = blobFileName;
|
||||||
|
document.body.appendChild(tmpAElem);
|
||||||
|
const evt = document.createEvent('MouseEvents');
|
||||||
|
evt.initEvent('click', true, true);
|
||||||
|
tmpAElem.dispatchEvent(evt);
|
||||||
|
document.body.removeChild(tmpAElem);
|
||||||
|
} else {
|
||||||
|
location.href = this.blobUrl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
newTabResponseText() {}
|
||||||
}
|
}
|
||||||
|
@ -1,66 +1,3 @@
|
|||||||
.px-4 {
|
|
||||||
padding-left: 1rem;
|
|
||||||
padding-right: 1rem;
|
|
||||||
}
|
|
||||||
.w-40 {
|
|
||||||
width: 10rem;
|
|
||||||
}
|
|
||||||
.mr-8 {
|
|
||||||
margin-right: 2rem;
|
|
||||||
}
|
|
||||||
.h-40 {
|
|
||||||
height: 10rem;
|
|
||||||
}
|
|
||||||
.block {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
.border {
|
|
||||||
border-width: 1px;
|
|
||||||
}
|
|
||||||
.rounded-lg {
|
|
||||||
border-radius: 0.5rem;
|
|
||||||
}
|
|
||||||
.bg-cover {
|
|
||||||
background-size: cover;
|
|
||||||
}
|
|
||||||
.bg-no-repeat {
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
}
|
|
||||||
.bg-center {
|
|
||||||
background-position: center;
|
|
||||||
}
|
|
||||||
.mb-2 {
|
|
||||||
margin-bottom: 0.5rem;
|
|
||||||
}
|
|
||||||
.text-xl {
|
|
||||||
font-size: 1.25rem;
|
|
||||||
line-height: 1.75rem;
|
|
||||||
}
|
|
||||||
.font-bold {
|
|
||||||
font-weight: 700;
|
|
||||||
}
|
|
||||||
.flex-1 {
|
|
||||||
flex: 1 1 0%;
|
|
||||||
}
|
|
||||||
.flex-col {
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
.flex {
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
.w-full {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
.h-20 {
|
|
||||||
height: 5rem;
|
|
||||||
}
|
|
||||||
.p-8 {
|
|
||||||
padding: 2rem;
|
|
||||||
}
|
|
||||||
.py-4 {
|
|
||||||
padding-top: 1rem;
|
|
||||||
padding-bottom: 1rem;
|
|
||||||
}
|
|
||||||
::ng-deep {
|
::ng-deep {
|
||||||
eo-extension-detail .ant-tabs-content-holder {
|
eo-extension-detail .ant-tabs-content-holder {
|
||||||
padding-top: 20px;
|
padding-top: 20px;
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
{{ item.title }}<span *ngIf="item.showNum"> ({{ extensionService.extensionIDs.length }})</span>
|
{{ item.title }}<span *ngIf="item.showNum"> ({{ extensionService.extensionIDs.length }})</span>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
<section class="right fg1 px-4">
|
<section class="right fg1 pl-4">
|
||||||
<router-outlet></router-outlet>
|
<router-outlet></router-outlet>
|
||||||
</section>
|
</section>
|
||||||
</section>
|
</section>
|
||||||
|
@ -39,7 +39,6 @@
|
|||||||
margin-right: 0.5rem;
|
margin-right: 0.5rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.px-4 {
|
.pl-4 {
|
||||||
padding-left: 1rem;
|
padding-left: 1rem;
|
||||||
padding-right: 1rem;
|
|
||||||
}
|
}
|
@ -18,147 +18,14 @@
|
|||||||
.warn-color {
|
.warn-color {
|
||||||
color: var(--MAIN_THEME_COLOR);
|
color: var(--MAIN_THEME_COLOR);
|
||||||
}
|
}
|
||||||
.px-3 {
|
|
||||||
padding-left: 0.75rem;
|
|
||||||
padding-right: 0.75rem;
|
|
||||||
}
|
|
||||||
.py-4 {
|
|
||||||
padding-top: 1rem;
|
|
||||||
padding-bottom: 1rem;
|
|
||||||
}
|
|
||||||
.px-4 {
|
|
||||||
padding-left: 1rem;
|
|
||||||
padding-right: 1rem;
|
|
||||||
}
|
|
||||||
.flex-1 {
|
|
||||||
flex: 1 1 0%;
|
|
||||||
}
|
|
||||||
.w-60 {
|
|
||||||
width: 15rem;
|
|
||||||
}
|
|
||||||
.grid-cols-4 {
|
|
||||||
grid-template-columns: repeat(4, minmax(0, 1fr));
|
|
||||||
}
|
|
||||||
.gap-6 {
|
|
||||||
grid-gap: 1.5rem;
|
|
||||||
gap: 1.5rem;
|
|
||||||
}
|
|
||||||
.py-5 {
|
|
||||||
padding-top: 1.25rem;
|
|
||||||
padding-bottom: 1.25rem;
|
|
||||||
}
|
|
||||||
.px-3 {
|
|
||||||
padding-left: 0.75rem;
|
|
||||||
padding-right: 0.75rem;
|
|
||||||
}
|
|
||||||
.grid {
|
|
||||||
display: grid;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 1279.9px) {
|
@media (max-width: 1279.9px) {
|
||||||
.grid-cols-4 {
|
.grid-cols-4 {
|
||||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.w-60{
|
||||||
.w-full {
|
width: 15rem;
|
||||||
width: 100%;
|
|
||||||
}
|
}
|
||||||
.px-3 {
|
.h-76{
|
||||||
padding-left: 0.75rem;
|
|
||||||
padding-right: 0.75rem;
|
|
||||||
}
|
|
||||||
.py-2 {
|
|
||||||
padding-top: 0.5rem;
|
|
||||||
padding-bottom: 0.5rem;
|
|
||||||
}
|
|
||||||
.h-76 {
|
|
||||||
height: 17rem;
|
height: 17rem;
|
||||||
}
|
|
||||||
.items-center {
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
.flex-wrap {
|
|
||||||
flex-wrap: wrap;
|
|
||||||
}
|
|
||||||
.flex-col {
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
.flex {
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
.border {
|
|
||||||
border-width: 1px;
|
|
||||||
}
|
|
||||||
.rounded-lg {
|
|
||||||
border-radius: 0.5rem;
|
|
||||||
}
|
|
||||||
.text-green-700 {
|
|
||||||
--tw-text-opacity: 1;
|
|
||||||
color: rgba(4, 120, 87, var(--tw-text-opacity));
|
|
||||||
}
|
|
||||||
.p-1 {
|
|
||||||
padding: 0.25rem;
|
|
||||||
}
|
|
||||||
.text-xs {
|
|
||||||
font-size: 0.75rem;
|
|
||||||
line-height: 1rem;
|
|
||||||
}
|
|
||||||
.border {
|
|
||||||
border-width: 1px;
|
|
||||||
}
|
|
||||||
.rounded-sm {
|
|
||||||
border-radius: 0.125rem;
|
|
||||||
}
|
|
||||||
.border-green-700 {
|
|
||||||
--tw-border-opacity: 1;
|
|
||||||
border-color: rgba(4, 120, 87, var(--tw-border-opacity));
|
|
||||||
}
|
|
||||||
.w-20 {
|
|
||||||
width: 5rem;
|
|
||||||
}
|
|
||||||
.my-3 {
|
|
||||||
margin-top: 0.75rem;
|
|
||||||
margin-bottom: 0.75rem;
|
|
||||||
}
|
|
||||||
.h-20 {
|
|
||||||
height: 5rem;
|
|
||||||
}
|
|
||||||
.block {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
.rounded-lg {
|
|
||||||
border-radius: 0.5rem;
|
|
||||||
}
|
|
||||||
.bg-cover {
|
|
||||||
background-size: cover;
|
|
||||||
}
|
|
||||||
.bg-no-repeat {
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
}
|
|
||||||
.bg-center {
|
|
||||||
background-position: center;
|
|
||||||
}
|
|
||||||
.text-lg {
|
|
||||||
font-size: 1.125rem;
|
|
||||||
line-height: 1.75rem;
|
|
||||||
}
|
|
||||||
.font-bold {
|
|
||||||
font-weight: 700;
|
|
||||||
}
|
|
||||||
.text-gray-400 {
|
|
||||||
--tw-text-opacity: 1;
|
|
||||||
color: rgba(156, 163, 175, var(--tw-text-opacity));
|
|
||||||
}
|
|
||||||
.my-2 {
|
|
||||||
margin-top: 0.5rem;
|
|
||||||
margin-bottom: 0.5rem;
|
|
||||||
}
|
|
||||||
.text-gray-500 {
|
|
||||||
--tw-text-opacity: 1;
|
|
||||||
color: rgba(107, 114, 128, var(--tw-text-opacity));
|
|
||||||
}
|
|
||||||
.my-1 {
|
|
||||||
margin-top: 0.25rem;
|
|
||||||
margin-bottom: 0.25rem;
|
|
||||||
}
|
}
|
@ -1,4 +1,4 @@
|
|||||||
.home_container{
|
.home_container {
|
||||||
height: calc(100vh - var(--NAVBAR_HEIGHT) - var(--remote-notification-height, 0px) - 1px);
|
height: calc(100vh - var(--NAVBAR_HEIGHT) - var(--remote-notification-height, 0px) - 1px);
|
||||||
}
|
}
|
||||||
.home {
|
.home {
|
||||||
@ -14,3 +14,24 @@
|
|||||||
background-color: rgb(255, 219, 7);
|
background-color: rgb(255, 219, 7);
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
::ng-deep {
|
||||||
|
eo-api {
|
||||||
|
router-outlet + * {
|
||||||
|
display: block;
|
||||||
|
height: calc(100vh - var(--NAVBAR_HEIGHT) - var(--FOOTER_HEIGHT) - var(--remote-notification-height) - 46px);
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
.has_tab_page router-outlet + * {
|
||||||
|
height: calc(
|
||||||
|
100vh - var(--NAVBAR_HEIGHT) - var(--FOOTER_HEIGHT) - var(--remote-notification-height) - 45px - 47px
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
eo-extension {
|
||||||
|
router-outlet + * {
|
||||||
|
display: block;
|
||||||
|
height: calc(100vh - var(--NAVBAR_HEIGHT) - var(--FOOTER_HEIGHT) - var(--remote-notification-height));
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
export enum ApiTestParamsTypeFormData {
|
export enum ApiTestParamsTypeFormData {
|
||||||
text = 'string',
|
text = 'string',
|
||||||
// file = 'file',
|
file = 'file',
|
||||||
}
|
}
|
||||||
export enum ApiTestParamsTypeJsonOrXml {
|
export enum ApiTestParamsTypeJsonOrXml {
|
||||||
string = 'string',
|
string = 'string',
|
||||||
@ -32,6 +32,10 @@ export interface ApiTestBody extends BasiApiTestParams {
|
|||||||
* param type
|
* param type
|
||||||
*/
|
*/
|
||||||
type: string;
|
type: string;
|
||||||
|
/**
|
||||||
|
* If value is file,value is base64 string
|
||||||
|
*/
|
||||||
|
files?:string;
|
||||||
/**
|
/**
|
||||||
* XML attribute
|
* XML attribute
|
||||||
*/
|
*/
|
||||||
|
@ -58,6 +58,7 @@ export const eoFormatRequestData = (data, opts = { env: {} }, locale) => {
|
|||||||
checkbox: val.required,
|
checkbox: val.required,
|
||||||
listDepth: val.listDepth || 0,
|
listDepth: val.listDepth || 0,
|
||||||
paramKey: val.name,
|
paramKey: val.name,
|
||||||
|
files:val.files?.map(val=>val.dataUrl),
|
||||||
paramType: typeMUI[val.type],
|
paramType: typeMUI[val.type],
|
||||||
paramInfo: val.value === undefined ? val.example : val.value,
|
paramInfo: val.value === undefined ? val.example : val.value,
|
||||||
});
|
});
|
||||||
@ -100,6 +101,7 @@ export const eoFormatRequestData = (data, opts = { env: {} }, locale) => {
|
|||||||
};
|
};
|
||||||
export const eoFormatResponseData = ({ report, history, id }) => {
|
export const eoFormatResponseData = ({ report, history, id }) => {
|
||||||
let { httpCode, ...response } = history.resultInfo;
|
let { httpCode, ...response } = history.resultInfo;
|
||||||
|
console.log(report, history, id)
|
||||||
response = {
|
response = {
|
||||||
statusCode: httpCode,
|
statusCode: httpCode,
|
||||||
...response,
|
...response,
|
||||||
@ -115,7 +117,7 @@ export const eoFormatResponseData = ({ report, history, id }) => {
|
|||||||
} = {
|
} = {
|
||||||
id: id,
|
id: id,
|
||||||
general: report.general,
|
general: report.general,
|
||||||
response: response,
|
response: {blobFileName:report.blobFileName,...response},
|
||||||
report: {
|
report: {
|
||||||
request: {
|
request: {
|
||||||
requestHeaders: report.request.headers.map((val) => ({ name: val.key, value: val.value })),
|
requestHeaders: report.request.headers.map((val) => ({ name: val.key, value: val.value })),
|
||||||
|
@ -42,6 +42,9 @@ export interface TestLocalNodeData {
|
|||||||
checkbox: boolean;
|
checkbox: boolean;
|
||||||
paramKey: string;
|
paramKey: string;
|
||||||
paramType: string;
|
paramType: string;
|
||||||
|
/**
|
||||||
|
* value
|
||||||
|
*/
|
||||||
paramInfo: string;
|
paramInfo: string;
|
||||||
childList: object[];
|
childList: object[];
|
||||||
}[];
|
}[];
|
||||||
|
@ -110,6 +110,7 @@ export interface ApiTestHistoryResponse {
|
|||||||
body: string;
|
body: string;
|
||||||
contentType: string;
|
contentType: string;
|
||||||
responseType: 'text' | 'longText' | 'stream';
|
responseType: 'text' | 'longText' | 'stream';
|
||||||
|
blobFileName?:string;
|
||||||
responseLength: number;
|
responseLength: number;
|
||||||
testDeny: string;
|
testDeny: string;
|
||||||
/**
|
/**
|
||||||
@ -295,51 +296,51 @@ export enum RequestProtocol {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* API数据对象接口
|
* API Data
|
||||||
*/
|
*/
|
||||||
export interface ApiData extends StorageModel {
|
export interface ApiData extends StorageModel {
|
||||||
/**
|
/**
|
||||||
* 名称
|
* name
|
||||||
* @type {string}
|
* @type {string}
|
||||||
*/
|
*/
|
||||||
name: string;
|
name: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 文档所属项目主键ID
|
* Belongs to which project
|
||||||
*
|
*
|
||||||
* @type {string|number}
|
* @type {string|number}
|
||||||
*/
|
*/
|
||||||
projectID?: string | number;
|
projectID?: string | number;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 文档所属分组主键ID
|
* Belongs to which group
|
||||||
*
|
*
|
||||||
* @type {string|number}
|
* @type {string|number}
|
||||||
*/
|
*/
|
||||||
groupID: string | number;
|
groupID: string | number;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 请求地址
|
* Request url,Usually value is path
|
||||||
*
|
*
|
||||||
* @type {string}
|
* @type {string}
|
||||||
*/
|
*/
|
||||||
uri: string;
|
uri: string;
|
||||||
/**
|
/**
|
||||||
* API协议 [http, https, ...]
|
* API protocol [http, https, ...]
|
||||||
*
|
*
|
||||||
* @type {RequestProtocol|string}
|
* @type {RequestProtocol|string}
|
||||||
*/
|
*/
|
||||||
protocol: RequestProtocol | string;
|
protocol: RequestProtocol | string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 请求方法 [POST, GET, PUT, ...]
|
* Request method [POST, GET, PUT, ...]
|
||||||
*
|
*
|
||||||
* @type {RequestMethod|string}
|
* @type {RequestMethod|string}
|
||||||
*/
|
*/
|
||||||
method: RequestMethod | string;
|
method: RequestMethod | string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 分组排序号
|
* api show order
|
||||||
*
|
*
|
||||||
* @type {number}
|
* @type {number}
|
||||||
*/
|
*/
|
||||||
|
@ -93,3 +93,38 @@ export const getDefaultValue = (list: any[], key) => {
|
|||||||
const [target] = list.filter((it) => it.default);
|
const [target] = list.filter((it) => it.default);
|
||||||
return target[key] || '';
|
return target[key] || '';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const parserProperties = (properties) => Object.keys(properties).map((it) => ({ value: it, ...properties[it] }));
|
||||||
|
const base64ToUint8Array = (inputBase64String) => {
|
||||||
|
const tmpPadding = '='.repeat((4 - (inputBase64String.length % 4)) % 4);
|
||||||
|
const tmpBase64 = (inputBase64String + tmpPadding).replace(/\-/g, '+').replace(/_/g, '/');
|
||||||
|
|
||||||
|
const tmpRawData = window.atob(tmpBase64);
|
||||||
|
const tmpOutputArray = new Uint8Array(tmpRawData.length);
|
||||||
|
for (let i = 0; i < tmpRawData.length; ++i) {
|
||||||
|
tmpOutputArray[i] = tmpRawData.charCodeAt(i);
|
||||||
|
}
|
||||||
|
return tmpOutputArray;
|
||||||
|
};
|
||||||
|
export const getBlobUrl = (inputStream, inputFileType) => {
|
||||||
|
let tmpBlob;
|
||||||
|
try {
|
||||||
|
inputStream = base64ToUint8Array(inputStream);
|
||||||
|
if (typeof window.Blob === 'function') {
|
||||||
|
tmpBlob = new Blob([inputStream], {
|
||||||
|
type: inputFileType,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
//@ts-ignore
|
||||||
|
const tmpBlobBuilder =
|
||||||
|
window.BlobBuilder || window.MozBlobBuilder || window.WebKitBlobBuilder || window.MSBlobBuilder;
|
||||||
|
const tmpBlobClass = new tmpBlobBuilder();
|
||||||
|
tmpBlobClass.append(inputStream);
|
||||||
|
tmpBlob = tmpBlobClass.getBlob(inputFileType);
|
||||||
|
}
|
||||||
|
} catch (GET_BLOB_ERR) {
|
||||||
|
tmpBlob = inputStream;
|
||||||
|
}
|
||||||
|
const tmpUrlObj = window.URL || window.webkitURL;
|
||||||
|
return tmpUrlObj.createObjectURL(tmpBlob);
|
||||||
|
};
|
||||||
|
@ -1252,8 +1252,10 @@ function listBlockController($rootScope, $element, $scope) {
|
|||||||
};
|
};
|
||||||
$scope.importFile = function (inputArg, inputEvent) {
|
$scope.importFile = function (inputArg, inputEvent) {
|
||||||
inputArg.$index = this.$parent.$index;
|
inputArg.$index = this.$parent.$index;
|
||||||
|
inputArg.item=vm.list[inputArg.$index];
|
||||||
vm.mainObject.baseFun.importFile(inputArg);
|
vm.mainObject.baseFun.importFile(inputArg);
|
||||||
if (inputEvent) inputEvent.value = '';
|
// if (inputEvent) inputEvent.value = '';
|
||||||
|
($scope.$root && $scope.$root.$$phase) || $scope.$apply();
|
||||||
};
|
};
|
||||||
/**
|
/**
|
||||||
* @desc 过滤列表函数
|
* @desc 过滤列表函数
|
||||||
|
@ -88,7 +88,6 @@ function selectDefaultController($scope, $element) {
|
|||||||
|
|
||||||
if (vm.mainObject && vm.mainObject.isNeedToResetPosition) {
|
if (vm.mainObject && vm.mainObject.isNeedToResetPosition) {
|
||||||
let tmpObj = vm.data.inputElem[0].getBoundingClientRect();
|
let tmpObj = vm.data.inputElem[0].getBoundingClientRect();
|
||||||
console.log(tmpObj);
|
|
||||||
vm.data.inputX = tmpObj.x;
|
vm.data.inputX = tmpObj.x;
|
||||||
vm.data.inputY = tmpObj.y + 30;
|
vm.data.inputY = tmpObj.y + 30;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user