fix(all): 修复严重 bug
This commit is contained in:
parent
00ee3a53a3
commit
5fb59a66f7
|
@ -102,6 +102,7 @@ module.exports = {
|
||||||
'^localforage$',
|
'^localforage$',
|
||||||
'vue-draggable-plus',
|
'vue-draggable-plus',
|
||||||
'jsonpath-plus',
|
'jsonpath-plus',
|
||||||
|
'lossless-json',
|
||||||
], // node依赖
|
], // node依赖
|
||||||
['.*/assets/.*', '^@/assets$'], // 项目静态资源
|
['.*/assets/.*', '^@/assets$'], // 项目静态资源
|
||||||
['^@/components/pure/.*', '^@/components/business/.*', '.*\\.vue$'], // 组件
|
['^@/components/pure/.*', '^@/components/business/.*', '.*\\.vue$'], // 组件
|
||||||
|
|
|
@ -63,6 +63,7 @@
|
||||||
"jsonpath-plus": "^8.0.0",
|
"jsonpath-plus": "^8.0.0",
|
||||||
"localforage": "^1.10.0",
|
"localforage": "^1.10.0",
|
||||||
"lodash-es": "^4.17.21",
|
"lodash-es": "^4.17.21",
|
||||||
|
"lossless-json": "^4.0.1",
|
||||||
"mitt": "^3.0.1",
|
"mitt": "^3.0.1",
|
||||||
"monaco-editor": "^0.39.0",
|
"monaco-editor": "^0.39.0",
|
||||||
"nprogress": "^0.2.0",
|
"nprogress": "^0.2.0",
|
||||||
|
|
|
@ -743,7 +743,7 @@
|
||||||
.arco-switch-type-circle.arco-switch-checked:not(:disabled) {
|
.arco-switch-type-circle.arco-switch-checked:not(:disabled) {
|
||||||
background-color: rgb(var(--primary-5)) !important;
|
background-color: rgb(var(--primary-5)) !important;
|
||||||
}
|
}
|
||||||
.arco-switch-disabled {
|
.arco-switch-type-circle.arco-switch-disabled {
|
||||||
background-color: rgb(var(--primary-3)) !important;
|
background-color: rgb(var(--primary-3)) !important;
|
||||||
}
|
}
|
||||||
.arco-switch-type-line.arco-switch-small {
|
.arco-switch-type-line.arco-switch-small {
|
||||||
|
|
|
@ -438,7 +438,7 @@
|
||||||
variableType: RequestExtractEnvType.TEMPORARY,
|
variableType: RequestExtractEnvType.TEMPORARY,
|
||||||
extractScope: RequestExtractScope.BODY,
|
extractScope: RequestExtractScope.BODY,
|
||||||
expression: '',
|
expression: '',
|
||||||
extractType: RequestExtractExpressionEnum.REGEX,
|
extractType: RequestExtractExpressionEnum.JSON_PATH,
|
||||||
expressionMatchingRule: RequestExtractExpressionRuleType.EXPRESSION,
|
expressionMatchingRule: RequestExtractExpressionRuleType.EXPRESSION,
|
||||||
resultMatchingRule: RequestExtractResultMatchingRule.RANDOM,
|
resultMatchingRule: RequestExtractResultMatchingRule.RANDOM,
|
||||||
resultMatchingRuleNum: 1,
|
resultMatchingRuleNum: 1,
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="flex items-center">
|
<div v-if="caseLevel" class="flex items-center">
|
||||||
<div
|
<div
|
||||||
class="mr-[4px] h-[8px] w-[8px] rounded-full"
|
class="mr-[4px] h-[8px] w-[8px] rounded-full"
|
||||||
:style="{
|
:style="{
|
||||||
|
@ -15,7 +15,7 @@
|
||||||
import { CaseLevel } from './types';
|
import { CaseLevel } from './types';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
caseLevel: CaseLevel;
|
caseLevel?: CaseLevel;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const caseLevelMap = {
|
const caseLevelMap = {
|
||||||
|
@ -41,7 +41,7 @@
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const caseLevel = computed(() => caseLevelMap[props.caseLevel] || {});
|
const caseLevel = computed(() => (props.caseLevel ? caseLevelMap[props.caseLevel] : undefined));
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped></style>
|
<style lang="less" scoped></style>
|
||||||
|
|
|
@ -26,14 +26,7 @@
|
||||||
></a-input>
|
></a-input>
|
||||||
<div class="config-card-footer">
|
<div class="config-card-footer">
|
||||||
<div>
|
<div>
|
||||||
<a-button
|
<a-button type="outline" class="px-[8px]" size="mini" :loading="testApiLoading" @click="testApi">
|
||||||
type="outline"
|
|
||||||
class="px-[8px]"
|
|
||||||
size="mini"
|
|
||||||
:disabled="apiConfig.userUrl.trim() === ''"
|
|
||||||
:loading="testApiLoading"
|
|
||||||
@click="testApi"
|
|
||||||
>
|
|
||||||
{{ t('ms.personal.test') }}
|
{{ t('ms.personal.test') }}
|
||||||
</a-button>
|
</a-button>
|
||||||
<a-button
|
<a-button
|
||||||
|
|
|
@ -81,7 +81,7 @@
|
||||||
import MsCodeEditorTheme from './themes';
|
import MsCodeEditorTheme from './themes';
|
||||||
import { CustomTheme, editorProps, Language, LanguageEnum, Theme } from './types';
|
import { CustomTheme, editorProps, Language, LanguageEnum, Theme } from './types';
|
||||||
import * as monaco from 'monaco-editor/esm/vs/editor/editor.api';
|
import * as monaco from 'monaco-editor/esm/vs/editor/editor.api';
|
||||||
import * as XmlBeautify from 'xml-beautify';
|
import XmlBeautify from 'xml-beautify';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'MonacoEditor',
|
name: 'MonacoEditor',
|
||||||
|
@ -235,7 +235,7 @@
|
||||||
} else if (currentLanguage.value === LanguageEnum.XML) {
|
} else if (currentLanguage.value === LanguageEnum.XML) {
|
||||||
// XML需要手动格式化
|
// XML需要手动格式化
|
||||||
const value = editor.getValue();
|
const value = editor.getValue();
|
||||||
const formattedCode = new XmlBeautify({ parser: DOMParser }).beautify(value);
|
const formattedCode = new XmlBeautify().beautify(value);
|
||||||
editor.setValue(formattedCode);
|
editor.setValue(formattedCode);
|
||||||
emit('update:modelValue', formattedCode);
|
emit('update:modelValue', formattedCode);
|
||||||
emit('change', formattedCode);
|
emit('change', formattedCode);
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { onMounted, onUnmounted, Ref, ref, watch } from 'vue';
|
import { onMounted, onUnmounted, Ref, ref, watch } from 'vue';
|
||||||
import { JSONPath } from 'jsonpath-plus';
|
import { JSONPath } from 'jsonpath-plus';
|
||||||
|
import { isSafeNumber, parse } from 'lossless-json';
|
||||||
|
|
||||||
import JPPicker from '@/assets/js/jsonpath-picker-vanilla/jsonpath-picker-vanilla';
|
import JPPicker from '@/assets/js/jsonpath-picker-vanilla/jsonpath-picker-vanilla';
|
||||||
|
|
||||||
|
@ -28,14 +29,20 @@
|
||||||
);
|
);
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(e: 'pick', path: string, result: any[]): void;
|
(e: 'pick', path: string, parseJson: string | Record<string, any>, result: any[]): void;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
function initJsonPathPicker() {
|
function initJsonPathPicker() {
|
||||||
try {
|
try {
|
||||||
json.value = props.data;
|
json.value = props.data;
|
||||||
if (typeof props.data === 'string') {
|
if (typeof props.data === 'string') {
|
||||||
json.value = JSON.parse(props.data);
|
json.value = parse(props.data, undefined, (value) => {
|
||||||
|
if (!isSafeNumber(value) || Number(value).toString().length < value.length) {
|
||||||
|
// 大数、超长小数、科学计数法、小数位全为 0 等情况下,JS 精度丢失,所以需要用字符串存储
|
||||||
|
return `Number(${value.toString()})`;
|
||||||
|
}
|
||||||
|
return Number(value);
|
||||||
|
}) as Record<string, any>;
|
||||||
}
|
}
|
||||||
JPPicker.jsonPathPicker(jr.value, json.value, [ip.value], props.opt);
|
JPPicker.jsonPathPicker(jr.value, json.value, [ip.value], props.opt);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
@ -61,8 +68,15 @@
|
||||||
if (ev.target && ev.target.classList.contains('pick-path')) {
|
if (ev.target && ev.target.classList.contains('pick-path')) {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
if (ip.value) {
|
if (ip.value) {
|
||||||
jsonPath.value = ip.value.value;
|
jsonPath.value = `$${ip.value.value}`;
|
||||||
emit('pick', jsonPath.value, JSONPath({ json: json.value, path: jsonPath.value }));
|
emit(
|
||||||
|
'pick',
|
||||||
|
jsonPath.value,
|
||||||
|
json.value,
|
||||||
|
JSONPath({ json: json.value, path: jsonPath.value }).map((e) =>
|
||||||
|
e.toString().replace(/Number\(([^)]+)\)/g, '$1')
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}, 0);
|
}, 0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,21 +48,27 @@
|
||||||
const sameNodesIndex = document.evaluate(
|
const sameNodesIndex = document.evaluate(
|
||||||
`count(ancestor-or-self::*/preceding-sibling::${node.nodeName}) + 1`,
|
`count(ancestor-or-self::*/preceding-sibling::${node.nodeName}) + 1`,
|
||||||
node,
|
node,
|
||||||
null,
|
(prefix) => {
|
||||||
|
// 获取 XML 文档的根元素
|
||||||
|
const root = node.ownerDocument.documentElement;
|
||||||
|
// 从根元素获取命名空间的 URI
|
||||||
|
const nsUri = root.getAttributeNS('http://www.w3.org/2000/xmlns/', prefix || '');
|
||||||
|
return nsUri || null;
|
||||||
|
},
|
||||||
XPathResult.NUMBER_TYPE,
|
XPathResult.NUMBER_TYPE,
|
||||||
null
|
null
|
||||||
).numberValue; // 这里是执行 XPATH 表达式,获取当前节点在同级节点中的下标
|
).numberValue; // 这里是执行 XPATH 表达式,获取当前节点在同级节点中的下标
|
||||||
|
|
||||||
const xpath = `${currentPath}/${node.tagName}[${sameNodesIndex}]`; // 拼接规则:当前路径/当前节点名[当前节点在同级同名节点中的下标]
|
const xpath = `${currentPath}/${node.nodeName}[${sameNodesIndex}]`; // 拼接规则:当前路径/当前节点名[当前节点在同级同名节点中的下标]
|
||||||
tempXmls.value.push({ content: node.tagName, xpath });
|
tempXmls.value.push({ content: node.nodeName, xpath });
|
||||||
const children = Array.from(node.children);
|
const children = Array.from(node.children);
|
||||||
children.forEach((child) => {
|
children.forEach((child) => {
|
||||||
flattenXml(child, xpath); // 递归处理子节点
|
flattenXml(child, xpath); // 递归处理子节点
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
// 同级的同名节点数量等于 1 时,不需要给当前节点名的 xpath 添加下标,因为这个标签是唯一的
|
// 同级的同名节点数量等于 1 时,不需要给当前节点名的 xpath 添加下标,因为这个标签是唯一的
|
||||||
const xpath = `${currentPath}/${node.tagName}`;
|
const xpath = `${currentPath}/${node.nodeName}`;
|
||||||
tempXmls.value.push({ content: node.tagName, xpath });
|
tempXmls.value.push({ content: node.nodeName, xpath });
|
||||||
const children = Array.from(node.children);
|
const children = Array.from(node.children);
|
||||||
children.forEach((child) => {
|
children.forEach((child) => {
|
||||||
flattenXml(child, xpath);
|
flattenXml(child, xpath);
|
||||||
|
|
|
@ -12,8 +12,17 @@ export function matchXMLWithXPath(xmlText: string, xpathQuery: string): xpath.Se
|
||||||
// 解析 XML 文本
|
// 解析 XML 文本
|
||||||
const xmlDoc = new DOMParser().parseFromString(xmlText, 'text/xml');
|
const xmlDoc = new DOMParser().parseFromString(xmlText, 'text/xml');
|
||||||
|
|
||||||
|
// 创建一个命名空间解析器
|
||||||
|
const resolver = (prefix: string) => {
|
||||||
|
// 获取 XML 文档的根元素
|
||||||
|
const root = xmlDoc.documentElement;
|
||||||
|
// 从根元素获取命名空间的 URI
|
||||||
|
const nsUri = root.getAttributeNS('http://www.w3.org/2000/xmlns/', prefix);
|
||||||
|
return nsUri || null;
|
||||||
|
};
|
||||||
|
|
||||||
// 使用 XPath 查询匹配的节点
|
// 使用 XPath 查询匹配的节点
|
||||||
const nodes = xpath.select(xpathQuery, xmlDoc);
|
const nodes = xpath.selectWithResolver(xpathQuery, xmlDoc, { lookupNamespaceURI: resolver });
|
||||||
|
|
||||||
// 返回匹配结果
|
// 返回匹配结果
|
||||||
return nodes;
|
return nodes;
|
||||||
|
|
|
@ -48,9 +48,9 @@
|
||||||
<div class="flex items-center justify-between">
|
<div class="flex items-center justify-between">
|
||||||
<a-radio-group v-model="condition.enableCommonScript" class="mb-[8px]" @change="emit('change')">
|
<a-radio-group v-model="condition.enableCommonScript" class="mb-[8px]" @change="emit('change')">
|
||||||
<a-radio :value="false">{{ t('apiTestDebug.manual') }}</a-radio>
|
<a-radio :value="false">{{ t('apiTestDebug.manual') }}</a-radio>
|
||||||
<a-radio v-if="hasAnyPermission(['PROJECT_CUSTOM_FUNCTION:READ'])" :value="true">{{
|
<a-radio v-if="hasAnyPermission(['PROJECT_CUSTOM_FUNCTION:READ'])" :value="true">
|
||||||
t('apiTestDebug.quote')
|
{{ t('apiTestDebug.quote') }}
|
||||||
}}</a-radio>
|
</a-radio>
|
||||||
</a-radio-group>
|
</a-radio-group>
|
||||||
<div v-if="props.showAssociatedScene" class="flex items-center">
|
<div v-if="props.showAssociatedScene" class="flex items-center">
|
||||||
<a-switch
|
<a-switch
|
||||||
|
@ -134,7 +134,6 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="flex items-center gap-[8px]">
|
<div class="flex items-center gap-[8px]">
|
||||||
<a-button
|
<a-button
|
||||||
v-if="props.isFormat"
|
|
||||||
:disabled="props.disabled"
|
:disabled="props.disabled"
|
||||||
type="outline"
|
type="outline"
|
||||||
class="arco-btn-outline--secondary p-[0_8px]"
|
class="arco-btn-outline--secondary p-[0_8px]"
|
||||||
|
@ -146,18 +145,6 @@
|
||||||
</template>
|
</template>
|
||||||
{{ t('project.commonScript.formatting') }}
|
{{ t('project.commonScript.formatting') }}
|
||||||
</a-button>
|
</a-button>
|
||||||
<!-- <a-button-->
|
|
||||||
<!-- :disabled="props.disabled"-->
|
|
||||||
<!-- type="outline"-->
|
|
||||||
<!-- class="arco-btn-outline--secondary p-[0_8px]"-->
|
|
||||||
<!-- size="mini"-->
|
|
||||||
<!-- @click="undoScript"-->
|
|
||||||
<!-- >-->
|
|
||||||
<!-- <template #icon>-->
|
|
||||||
<!-- <MsIcon type="icon-icon_undo_outlined" class="text-var(--color-text-4)" size="12" />-->
|
|
||||||
<!-- </template>-->
|
|
||||||
<!-- {{ t('common.revoke') }}-->
|
|
||||||
<!-- </a-button>-->
|
|
||||||
<a-button
|
<a-button
|
||||||
:disabled="props.disabled"
|
:disabled="props.disabled"
|
||||||
type="outline"
|
type="outline"
|
||||||
|
@ -312,14 +299,8 @@
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="sql-table-container">
|
<div class="sql-table-container">
|
||||||
<div class="mb-[8px] flex items-center text-[var(--color-text-1)]">
|
<div class="mb-[8px] text-[var(--color-text-1)]">
|
||||||
{{ t('apiTestDebug.extractParameter') }}
|
{{ t('apiTestDebug.extractParameter') }}
|
||||||
<a-tooltip position="right" :content="t('apiTestDebug.storageResultTip')">
|
|
||||||
<icon-question-circle
|
|
||||||
class="ml-[4px] text-[var(--color-text-brand)] hover:text-[rgb(var(--primary-5))]"
|
|
||||||
size="16"
|
|
||||||
/>
|
|
||||||
</a-tooltip>
|
|
||||||
</div>
|
</div>
|
||||||
<paramTable
|
<paramTable
|
||||||
:params="condition.extractParams"
|
:params="condition.extractParams"
|
||||||
|
@ -331,7 +312,15 @@
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="mt-[16px]">
|
<div class="mt-[16px]">
|
||||||
<div class="mb-[8px] text-[var(--color-text-1)]">{{ t('apiTestDebug.storageByResult') }}</div>
|
<div class="mb-[8px] flex items-center text-[var(--color-text-1)]">
|
||||||
|
{{ t('apiTestDebug.storageByResult') }}
|
||||||
|
<a-tooltip position="right" :content="t('apiTestDebug.storageResultTip')">
|
||||||
|
<icon-question-circle
|
||||||
|
class="ml-[4px] text-[var(--color-text-brand)] hover:text-[rgb(var(--primary-5))]"
|
||||||
|
size="16"
|
||||||
|
/>
|
||||||
|
</a-tooltip>
|
||||||
|
</div>
|
||||||
<a-input
|
<a-input
|
||||||
v-model:model-value="condition.resultVariable"
|
v-model:model-value="condition.resultVariable"
|
||||||
:disabled="props.disabled"
|
:disabled="props.disabled"
|
||||||
|
@ -398,7 +387,7 @@
|
||||||
@change="() => handleExpressionChange(rowIndex)"
|
@change="() => handleExpressionChange(rowIndex)"
|
||||||
>
|
>
|
||||||
<template #suffix>
|
<template #suffix>
|
||||||
<a-tooltip :disabled="!disabledExpressionSuffix">
|
<a-tooltip v-if="!props.disabled" :disabled="!!props.response">
|
||||||
<template #content>
|
<template #content>
|
||||||
<div>{{ t('apiTestDebug.expressionTip1') }}</div>
|
<div>{{ t('apiTestDebug.expressionTip1') }}</div>
|
||||||
<div>{{ t('apiTestDebug.expressionTip2') }}</div>
|
<div>{{ t('apiTestDebug.expressionTip2') }}</div>
|
||||||
|
@ -407,11 +396,7 @@
|
||||||
<MsIcon
|
<MsIcon
|
||||||
type="icon-icon_flashlamp"
|
type="icon-icon_flashlamp"
|
||||||
:size="15"
|
:size="15"
|
||||||
:class="
|
:class="!props.response ? 'ms-params-input-suffix-icon--disabled' : 'ms-params-input-suffix-icon'"
|
||||||
disabledExpressionSuffix || props.disabled
|
|
||||||
? 'ms-params-input-suffix-icon--disabled'
|
|
||||||
: 'ms-params-input-suffix-icon'
|
|
||||||
"
|
|
||||||
@click.stop="() => showFastExtraction(record)"
|
@click.stop="() => showFastExtraction(record)"
|
||||||
/>
|
/>
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
|
@ -522,7 +507,6 @@
|
||||||
requestRadioTextProps?: Record<string, any>; // 前后置请求前后置按钮文本
|
requestRadioTextProps?: Record<string, any>; // 前后置请求前后置按钮文本
|
||||||
showPrePostRequest?: boolean; // 是否展示前后置请求忽略
|
showPrePostRequest?: boolean; // 是否展示前后置请求忽略
|
||||||
totalList?: ExecuteConditionProcessor[]; // 总列表
|
totalList?: ExecuteConditionProcessor[]; // 总列表
|
||||||
isFormat?: boolean;
|
|
||||||
}>(),
|
}>(),
|
||||||
{
|
{
|
||||||
showAssociatedScene: false,
|
showAssociatedScene: false,
|
||||||
|
@ -744,10 +728,6 @@ if (!result){
|
||||||
dataIndex: 'extractType',
|
dataIndex: 'extractType',
|
||||||
slotName: 'extractType',
|
slotName: 'extractType',
|
||||||
typeOptions: [
|
typeOptions: [
|
||||||
{
|
|
||||||
label: t('apiTestDebug.regular'),
|
|
||||||
value: RequestExtractExpressionEnum.REGEX,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
label: 'JSONPath',
|
label: 'JSONPath',
|
||||||
value: RequestExtractExpressionEnum.JSON_PATH,
|
value: RequestExtractExpressionEnum.JSON_PATH,
|
||||||
|
@ -756,6 +736,10 @@ if (!result){
|
||||||
label: 'XPath',
|
label: 'XPath',
|
||||||
value: RequestExtractExpressionEnum.X_PATH,
|
value: RequestExtractExpressionEnum.X_PATH,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
label: t('apiTestDebug.regular'),
|
||||||
|
value: RequestExtractExpressionEnum.REGEX,
|
||||||
|
},
|
||||||
],
|
],
|
||||||
width: 120,
|
width: 120,
|
||||||
},
|
},
|
||||||
|
@ -822,7 +806,6 @@ if (!result){
|
||||||
width: 80,
|
width: 80,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
const disabledExpressionSuffix = ref(false);
|
|
||||||
|
|
||||||
function handleExtractParamTableChange(resultArr: any[], isInit?: boolean) {
|
function handleExtractParamTableChange(resultArr: any[], isInit?: boolean) {
|
||||||
condition.value.extractors = [...resultArr];
|
condition.value.extractors = [...resultArr];
|
||||||
|
@ -838,7 +821,7 @@ if (!result){
|
||||||
variableType: RequestExtractEnvType.TEMPORARY,
|
variableType: RequestExtractEnvType.TEMPORARY,
|
||||||
extractScope: RequestExtractScope.BODY,
|
extractScope: RequestExtractScope.BODY,
|
||||||
expression: '',
|
expression: '',
|
||||||
extractType: RequestExtractExpressionEnum.REGEX,
|
extractType: RequestExtractExpressionEnum.JSON_PATH,
|
||||||
expressionMatchingRule: RequestExtractExpressionRuleType.EXPRESSION,
|
expressionMatchingRule: RequestExtractExpressionRuleType.EXPRESSION,
|
||||||
resultMatchingRule: RequestExtractResultMatchingRule.RANDOM,
|
resultMatchingRule: RequestExtractResultMatchingRule.RANDOM,
|
||||||
resultMatchingRuleNum: 1,
|
resultMatchingRuleNum: 1,
|
||||||
|
@ -849,7 +832,7 @@ if (!result){
|
||||||
const activeRecord = ref({ ...defaultExtractParamItem }); // 用于暂存当前操作的提取参数表格项
|
const activeRecord = ref({ ...defaultExtractParamItem }); // 用于暂存当前操作的提取参数表格项
|
||||||
|
|
||||||
function showFastExtraction(record: ExpressionConfig) {
|
function showFastExtraction(record: ExpressionConfig) {
|
||||||
if (props.disabled) return;
|
if (props.disabled || !props.response) return;
|
||||||
activeRecord.value = { ...record };
|
activeRecord.value = { ...record };
|
||||||
fastExtractionVisible.value = true;
|
fastExtractionVisible.value = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,6 +60,7 @@
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { useVModel } from '@vueuse/core';
|
import { useVModel } from '@vueuse/core';
|
||||||
|
import { cloneDeep } from 'lodash-es';
|
||||||
|
|
||||||
import MsList from '@/components/pure/ms-list/index.vue';
|
import MsList from '@/components/pure/ms-list/index.vue';
|
||||||
import { ActionsItem } from '@/components/pure/ms-table-more-action/types';
|
import { ActionsItem } from '@/components/pure/ms-table-more-action/types';
|
||||||
|
@ -155,7 +156,7 @@
|
||||||
*/
|
*/
|
||||||
function copyListItem(item: ExecuteConditionProcessor) {
|
function copyListItem(item: ExecuteConditionProcessor) {
|
||||||
let copyItem = {
|
let copyItem = {
|
||||||
...item,
|
...cloneDeep(item),
|
||||||
id: new Date().getTime(),
|
id: new Date().getTime(),
|
||||||
};
|
};
|
||||||
const isExistPre = data.value.filter(
|
const isExistPre = data.value.filter(
|
||||||
|
@ -171,7 +172,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
copyItem = {
|
copyItem = {
|
||||||
...item,
|
...cloneDeep(item),
|
||||||
beforeStepScript: !isExistPre,
|
beforeStepScript: !isExistPre,
|
||||||
id: new Date().getTime(),
|
id: new Date().getTime(),
|
||||||
};
|
};
|
||||||
|
|
|
@ -115,7 +115,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="match-result">
|
<div class="match-result">
|
||||||
<div v-if="isMatched && matchResult.length === 0">{{ t('apiTestDebug.noMatchResult') }}</div>
|
<div v-if="isMatched && matchResult.length === 0">{{ t('apiTestDebug.noMatchResult') }}</div>
|
||||||
<pre v-for="(e, i) of matchResult" :key="i">{{ e }}</pre>
|
<pre v-for="(e, i) of matchResult" :key="i">{{ `${e}` }}</pre>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<a-collapse
|
<a-collapse
|
||||||
|
@ -184,6 +184,7 @@
|
||||||
const innerVisible = useVModel(props, 'visible', emit);
|
const innerVisible = useVModel(props, 'visible', emit);
|
||||||
const expressionForm = ref({ ...props.config });
|
const expressionForm = ref({ ...props.config });
|
||||||
const expressionFormRef = ref<typeof FormInstance>();
|
const expressionFormRef = ref<typeof FormInstance>();
|
||||||
|
const parseJson = ref<string | Record<string, any>>({});
|
||||||
const matchResult = ref<any[]>([]); // 当前匹配结果
|
const matchResult = ref<any[]>([]); // 当前匹配结果
|
||||||
const isMatched = ref(false); // 是否执行过匹配
|
const isMatched = ref(false); // 是否执行过匹配
|
||||||
|
|
||||||
|
@ -198,8 +199,9 @@
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
function handlePathPick(xpath: string) {
|
function handlePathPick(path: string, _parseJson: string | Record<string, any>) {
|
||||||
expressionForm.value.expression = xpath;
|
expressionForm.value.expression = path;
|
||||||
|
parseJson.value = _parseJson;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -231,9 +233,9 @@
|
||||||
try {
|
try {
|
||||||
matchResult.value =
|
matchResult.value =
|
||||||
JSONPath({
|
JSONPath({
|
||||||
json: props.response ? JSON.parse(props.response) : '',
|
json: parseJson.value,
|
||||||
path: expressionForm.value.expression,
|
path: expressionForm.value.expression,
|
||||||
}) || [];
|
})?.map((e) => e.toString().replace(/Number\(([^)]+)\)/g, '$1')) || [];
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
matchResult.value = JSONPath({ json: props.response || '', path: expressionForm.value.expression }) || [];
|
matchResult.value = JSONPath({ json: props.response || '', path: expressionForm.value.expression }) || [];
|
||||||
}
|
}
|
||||||
|
|
|
@ -113,7 +113,6 @@
|
||||||
:disabled="props.disabledExceptParam"
|
:disabled="props.disabledExceptParam"
|
||||||
:placeholder="t('apiTestDebug.commonPlaceholder')"
|
:placeholder="t('apiTestDebug.commonPlaceholder')"
|
||||||
class="ms-form-table-input"
|
class="ms-form-table-input"
|
||||||
:max-length="255"
|
|
||||||
size="mini"
|
size="mini"
|
||||||
@input="() => addTableLine(rowIndex, columnConfig.addLineDisabled)"
|
@input="() => addTableLine(rowIndex, columnConfig.addLineDisabled)"
|
||||||
/>
|
/>
|
||||||
|
@ -205,7 +204,6 @@
|
||||||
:disabled="props.disabledParamValue"
|
:disabled="props.disabledParamValue"
|
||||||
class="ms-form-table-input"
|
class="ms-form-table-input"
|
||||||
:placeholder="t('apiTestDebug.commonPlaceholder')"
|
:placeholder="t('apiTestDebug.commonPlaceholder')"
|
||||||
:max-length="255"
|
|
||||||
size="mini"
|
size="mini"
|
||||||
@input="() => addTableLine(rowIndex)"
|
@input="() => addTableLine(rowIndex)"
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -140,7 +140,11 @@
|
||||||
function searchDataSource() {
|
function searchDataSource() {
|
||||||
propsRes.value.data = cloneDeep(currentEnvConfig?.value.dataSources) as any[];
|
propsRes.value.data = cloneDeep(currentEnvConfig?.value.dataSources) as any[];
|
||||||
if (keyword.value.trim() !== '') {
|
if (keyword.value.trim() !== '') {
|
||||||
propsRes.value.data = propsRes.value.data.filter((e) => e.dataSource.includes(keyword.value));
|
propsRes.value.data = currentEnvConfig?.value.dataSources.filter((e) =>
|
||||||
|
e.dataSource.includes(keyword.value)
|
||||||
|
) as any[];
|
||||||
|
} else {
|
||||||
|
propsRes.value.data = cloneDeep(currentEnvConfig?.value.dataSources) as any[];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -72,23 +72,28 @@
|
||||||
hasAnyPermission([props.permissionMap.execute])
|
hasAnyPermission([props.permissionMap.execute])
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<a-dropdown-button
|
<template v-if="hasLocalExec">
|
||||||
v-if="hasLocalExec"
|
<a-dropdown-button
|
||||||
:disabled="requestVModel.executeLoading || (isHttpProtocol && !requestVModel.url)"
|
v-if="!requestVModel.executeLoading"
|
||||||
class="exec-btn"
|
:disabled="requestVModel.executeLoading || (isHttpProtocol && !requestVModel.url)"
|
||||||
@click="() => execute(isPriorityLocalExec ? 'localExec' : 'serverExec')"
|
class="exec-btn"
|
||||||
@select="execute"
|
@click="() => execute(isPriorityLocalExec ? 'localExec' : 'serverExec')"
|
||||||
>
|
@select="execute"
|
||||||
{{ isPriorityLocalExec ? t('apiTestDebug.localExec') : t('apiTestDebug.serverExec') }}
|
>
|
||||||
<template #icon>
|
{{ isPriorityLocalExec ? t('apiTestDebug.localExec') : t('apiTestDebug.serverExec') }}
|
||||||
<icon-down />
|
<template #icon>
|
||||||
</template>
|
<icon-down />
|
||||||
<template #content>
|
</template>
|
||||||
<a-doption :value="isPriorityLocalExec ? 'serverExec' : 'localExec'">
|
<template #content>
|
||||||
{{ isPriorityLocalExec ? t('apiTestDebug.serverExec') : t('apiTestDebug.localExec') }}
|
<a-doption :value="isPriorityLocalExec ? 'serverExec' : 'localExec'">
|
||||||
</a-doption>
|
{{ isPriorityLocalExec ? t('apiTestDebug.serverExec') : t('apiTestDebug.localExec') }}
|
||||||
</template>
|
</a-doption>
|
||||||
</a-dropdown-button>
|
</template>
|
||||||
|
</a-dropdown-button>
|
||||||
|
<a-button v-else type="primary" class="mr-[12px]" @click="stopDebug">
|
||||||
|
{{ t('common.stop') }}
|
||||||
|
</a-button>
|
||||||
|
</template>
|
||||||
<a-button
|
<a-button
|
||||||
v-else-if="!requestVModel.executeLoading"
|
v-else-if="!requestVModel.executeLoading"
|
||||||
class="mr-[12px]"
|
class="mr-[12px]"
|
||||||
|
@ -162,7 +167,7 @@
|
||||||
class="no-content relative mt-[8px] border-b"
|
class="no-content relative mt-[8px] border-b"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div ref="splitContainerRef" class="request-and-response h-[calc(100%-87px)]">
|
<div ref="splitContainerRef" class="request-and-response h-[calc(100%-100px)]">
|
||||||
<MsSplitBox
|
<MsSplitBox
|
||||||
ref="horizontalSplitBoxRef"
|
ref="horizontalSplitBoxRef"
|
||||||
:size="!props.isCase && props.isDefinition ? 0.7 : 1"
|
:size="!props.isCase && props.isDefinition ? 0.7 : 1"
|
||||||
|
@ -551,9 +556,9 @@
|
||||||
import { getPluginScript, getProtocolList } from '@/api/modules/api-test/common';
|
import { getPluginScript, getProtocolList } from '@/api/modules/api-test/common';
|
||||||
import { addCase } from '@/api/modules/api-test/management';
|
import { addCase } from '@/api/modules/api-test/management';
|
||||||
import { getSocket } from '@/api/modules/project-management/commonScript';
|
import { getSocket } from '@/api/modules/project-management/commonScript';
|
||||||
import { getLocalConfig } from '@/api/modules/user/index';
|
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
import { useAppStore } from '@/store';
|
import useAppStore from '@/store/modules/app';
|
||||||
|
import useUserStore from '@/store/modules/user';
|
||||||
import { filterTree, getGenerateId, parseQueryParams } from '@/utils';
|
import { filterTree, getGenerateId, parseQueryParams } from '@/utils';
|
||||||
import { scrollIntoView } from '@/utils/dom';
|
import { scrollIntoView } from '@/utils/dom';
|
||||||
import { registerCatchSaveShortcut, removeCatchSaveShortcut } from '@/utils/event';
|
import { registerCatchSaveShortcut, removeCatchSaveShortcut } from '@/utils/event';
|
||||||
|
@ -646,6 +651,7 @@
|
||||||
const emit = defineEmits(['addDone', 'execute']);
|
const emit = defineEmits(['addDone', 'execute']);
|
||||||
|
|
||||||
const appStore = useAppStore();
|
const appStore = useAppStore();
|
||||||
|
const userStore = useUserStore();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
const loading = defineModel<boolean>('detailLoading', { default: false });
|
const loading = defineModel<boolean>('detailLoading', { default: false });
|
||||||
|
@ -814,26 +820,9 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const hasLocalExec = ref(false); // 是否配置了api本地执行
|
const hasLocalExec = computed(() => userStore.hasLocalExec); // 是否配置了api本地执行
|
||||||
const isPriorityLocalExec = ref(false); // 是否优先本地执行
|
const isPriorityLocalExec = computed(() => userStore.isPriorityLocalExec); // 是否优先本地执行
|
||||||
const localExecuteUrl = ref('');
|
const localExecuteUrl = computed(() => userStore.localExecuteUrl); // 本地执行地址
|
||||||
async function initLocalConfig() {
|
|
||||||
if (hasLocalExec.value) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
const res = await getLocalConfig();
|
|
||||||
const apiLocalExec = res.find((e) => e.type === 'API');
|
|
||||||
if (apiLocalExec) {
|
|
||||||
hasLocalExec.value = true;
|
|
||||||
isPriorityLocalExec.value = apiLocalExec.enable || false;
|
|
||||||
localExecuteUrl.value = apiLocalExec.userUrl || '';
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
// eslint-disable-next-line no-console
|
|
||||||
console.log(error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const pluginScriptMap = ref<Record<string, PluginConfig>>({}); // 存储初始化过后的插件配置
|
const pluginScriptMap = ref<Record<string, PluginConfig>>({}); // 存储初始化过后的插件配置
|
||||||
const temporaryPluginFormMap: Record<string, any> = {}; // 缓存插件表单,避免切换tab导致动态表单数据丢失
|
const temporaryPluginFormMap: Record<string, any> = {}; // 缓存插件表单,避免切换tab导致动态表单数据丢失
|
||||||
|
@ -1300,7 +1289,7 @@
|
||||||
requestVModel.value.executeLoading = true;
|
requestVModel.value.executeLoading = true;
|
||||||
requestVModel.value.response = cloneDeep(defaultResponse);
|
requestVModel.value.response = cloneDeep(defaultResponse);
|
||||||
const res = await props.executeApi(makeRequestParams(executeType));
|
const res = await props.executeApi(makeRequestParams(executeType));
|
||||||
if (executeType === 'localExec' && props.localExecuteApi) {
|
if (executeType === 'localExec' && props.localExecuteApi && localExecuteUrl.value) {
|
||||||
await props.localExecuteApi(localExecuteUrl.value, res);
|
await props.localExecuteApi(localExecuteUrl.value, res);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
@ -1318,7 +1307,7 @@
|
||||||
requestVModel.value.executeLoading = true;
|
requestVModel.value.executeLoading = true;
|
||||||
requestVModel.value.response = cloneDeep(defaultResponse);
|
requestVModel.value.response = cloneDeep(defaultResponse);
|
||||||
const res = await props.executeApi(makeRequestParams(executeType));
|
const res = await props.executeApi(makeRequestParams(executeType));
|
||||||
if (executeType === 'localExec' && props.localExecuteApi) {
|
if (executeType === 'localExec' && props.localExecuteApi && localExecuteUrl.value) {
|
||||||
await props.localExecuteApi(localExecuteUrl.value, res);
|
await props.localExecuteApi(localExecuteUrl.value, res);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
@ -1661,12 +1650,6 @@
|
||||||
saveModalFormRef.value?.resetFields();
|
saveModalFormRef.value?.resetFields();
|
||||||
}
|
}
|
||||||
|
|
||||||
onBeforeMount(() => {
|
|
||||||
if (!props.isCase) {
|
|
||||||
initLocalConfig();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
if (!props.isDefinition) {
|
if (!props.isDefinition) {
|
||||||
registerCatchSaveShortcut(handleSaveShortcut);
|
registerCatchSaveShortcut(handleSaveShortcut);
|
||||||
|
@ -1681,7 +1664,6 @@
|
||||||
|
|
||||||
defineExpose({
|
defineExpose({
|
||||||
execute,
|
execute,
|
||||||
isPriorityLocalExec,
|
|
||||||
makeRequestParams,
|
makeRequestParams,
|
||||||
changeVerticalExpand,
|
changeVerticalExpand,
|
||||||
});
|
});
|
||||||
|
|
|
@ -206,7 +206,7 @@
|
||||||
const responseTabs = defineModel<ResponseItem[]>('responseDefinition', {
|
const responseTabs = defineModel<ResponseItem[]>('responseDefinition', {
|
||||||
required: true,
|
required: true,
|
||||||
});
|
});
|
||||||
const activeResponse = ref<ResponseItem>(responseTabs.value[0]);
|
const activeResponse = ref<ResponseItem>(responseTabs.value[0] || defaultResponseItem);
|
||||||
|
|
||||||
function addResponseTab(defaultProps?: Partial<ResponseItem>) {
|
function addResponseTab(defaultProps?: Partial<ResponseItem>) {
|
||||||
responseTabs.value.push({
|
responseTabs.value.push({
|
||||||
|
@ -267,7 +267,7 @@
|
||||||
break;
|
break;
|
||||||
case 'copy':
|
case 'copy':
|
||||||
addResponseTab({
|
addResponseTab({
|
||||||
..._tab,
|
...cloneDeep(_tab),
|
||||||
id: new Date().getTime(),
|
id: new Date().getTime(),
|
||||||
label: `copy_${t(_tab.label || _tab.name)}`,
|
label: `copy_${t(_tab.label || _tab.name)}`,
|
||||||
name: `copy_${t(_tab.label || _tab.name)}`,
|
name: `copy_${t(_tab.label || _tab.name)}`,
|
||||||
|
|
|
@ -11,8 +11,6 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref } from 'vue';
|
|
||||||
|
|
||||||
import MsBaseTable from '@/components/pure/ms-table/base-table.vue';
|
import MsBaseTable from '@/components/pure/ms-table/base-table.vue';
|
||||||
import { MsTableColumn } from '@/components/pure/ms-table/type';
|
import { MsTableColumn } from '@/components/pure/ms-table/type';
|
||||||
import useTable from '@/components/pure/ms-table/useTable';
|
import useTable from '@/components/pure/ms-table/useTable';
|
||||||
|
|
|
@ -23,8 +23,6 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref } from 'vue';
|
|
||||||
|
|
||||||
import MsCodeEditor from '@/components/pure/ms-code-editor/index.vue';
|
import MsCodeEditor from '@/components/pure/ms-code-editor/index.vue';
|
||||||
import { LanguageEnum } from '@/components/pure/ms-code-editor/types';
|
import { LanguageEnum } from '@/components/pure/ms-code-editor/types';
|
||||||
import MsIcon from '@/components/pure/ms-icon-font/index.vue';
|
import MsIcon from '@/components/pure/ms-icon-font/index.vue';
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
class="mr-[8px] w-[240px]"
|
class="mr-[8px] w-[240px]"
|
||||||
@search="loadApiList"
|
@search="loadApiList"
|
||||||
@press-enter="loadApiList"
|
@press-enter="loadApiList"
|
||||||
|
@clear="loadApiList"
|
||||||
/>
|
/>
|
||||||
<a-button type="outline" class="arco-btn-outline--secondary !p-[8px]" @click="loadApiList">
|
<a-button type="outline" class="arco-btn-outline--secondary !p-[8px]" @click="loadApiList">
|
||||||
<template #icon>
|
<template #icon>
|
||||||
|
|
|
@ -140,6 +140,7 @@
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
import useModal from '@/hooks/useModal';
|
import useModal from '@/hooks/useModal';
|
||||||
import useAppStore from '@/store/modules/app';
|
import useAppStore from '@/store/modules/app';
|
||||||
|
import useUserStore from '@/store/modules/user';
|
||||||
import { hasAnyPermission } from '@/utils/permission';
|
import { hasAnyPermission } from '@/utils/permission';
|
||||||
|
|
||||||
import { ProtocolItem } from '@/models/apiTest/common';
|
import { ProtocolItem } from '@/models/apiTest/common';
|
||||||
|
@ -174,14 +175,14 @@
|
||||||
(e: 'deleteApi', id: string): void;
|
(e: 'deleteApi', id: string): void;
|
||||||
(e: 'import'): void;
|
(e: 'import'): void;
|
||||||
}>();
|
}>();
|
||||||
const refreshModuleTree: (() => Promise<any>) | undefined = inject('refreshModuleTree');
|
|
||||||
|
|
||||||
const currentEnvConfig = inject<Ref<EnvConfig>>('currentEnvConfig');
|
|
||||||
|
|
||||||
|
const userStore = useUserStore();
|
||||||
const appStore = useAppStore();
|
const appStore = useAppStore();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const { openModal } = useModal();
|
const { openModal } = useModal();
|
||||||
|
|
||||||
|
const refreshModuleTree: (() => Promise<any>) | undefined = inject('refreshModuleTree');
|
||||||
|
const currentEnvConfig = inject<Ref<EnvConfig>>('currentEnvConfig');
|
||||||
const apiTabs = defineModel<RequestParam[]>('apiTabs', {
|
const apiTabs = defineModel<RequestParam[]>('apiTabs', {
|
||||||
required: true,
|
required: true,
|
||||||
});
|
});
|
||||||
|
@ -387,7 +388,7 @@
|
||||||
activeApiTab.value.definitionActiveKey = 'definition';
|
activeApiTab.value.definitionActiveKey = 'definition';
|
||||||
activeApiTab.value.isExecute = true;
|
activeApiTab.value.isExecute = true;
|
||||||
activeApiTab.value.mode = 'debug';
|
activeApiTab.value.mode = 'debug';
|
||||||
requestCompositionRef.value?.execute(requestCompositionRef.value?.isPriorityLocalExec ? 'localExec' : 'serverExec');
|
requestCompositionRef.value?.execute(userStore.localExecuteUrl ? 'localExec' : 'serverExec');
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleDelete() {
|
function handleDelete() {
|
||||||
|
|
|
@ -319,19 +319,23 @@
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<a-spin v-else :loading="previewDetail.executeLoading" class="h-[calc(100%-45px)] w-full pb-[18px]">
|
<a-spin v-else :loading="previewDetail.executeLoading" class="h-[calc(100%-45px)] w-full pb-[18px]">
|
||||||
<result
|
<div
|
||||||
v-show="
|
v-show="
|
||||||
previewDetail.protocol === 'HTTP' || previewDetail.response?.requestResults[0]?.responseResult.responseCode
|
previewDetail.protocol === 'HTTP' || previewDetail.response?.requestResults[0]?.responseResult.responseCode
|
||||||
"
|
"
|
||||||
v-model:active-tab="previewDetail.responseActiveTab"
|
class="h-full"
|
||||||
:request-result="previewDetail.response?.requestResults[0]"
|
>
|
||||||
:console="previewDetail.response?.console"
|
<result
|
||||||
:is-http-protocol="previewDetail.protocol === 'HTTP'"
|
v-model:active-tab="previewDetail.responseActiveTab"
|
||||||
:is-priority-local-exec="props.isPriorityLocalExec"
|
:request-result="previewDetail.response?.requestResults[0]"
|
||||||
:request-url="previewDetail.url"
|
:console="previewDetail.response?.console"
|
||||||
is-definition
|
:is-http-protocol="previewDetail.protocol === 'HTTP'"
|
||||||
@execute="emit('execute', props.isPriorityLocalExec ? 'localExec' : 'serverExec')"
|
:is-priority-local-exec="props.isPriorityLocalExec"
|
||||||
/>
|
:request-url="previewDetail.url"
|
||||||
|
is-definition
|
||||||
|
@execute="emit('execute', props.isPriorityLocalExec ? 'localExec' : 'serverExec')"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</a-spin>
|
</a-spin>
|
||||||
</a-collapse-item>
|
</a-collapse-item>
|
||||||
</a-collapse>
|
</a-collapse>
|
||||||
|
|
|
@ -456,15 +456,15 @@
|
||||||
{
|
{
|
||||||
polymorphicName: 'MsCommonElement', // 协议多态名称,写死MsCommonElement
|
polymorphicName: 'MsCommonElement', // 协议多态名称,写死MsCommonElement
|
||||||
assertionConfig: {
|
assertionConfig: {
|
||||||
enableGlobal: true,
|
enableGlobal: false,
|
||||||
assertions: [],
|
assertions: [],
|
||||||
},
|
},
|
||||||
postProcessorConfig: {
|
postProcessorConfig: {
|
||||||
enableGlobal: true,
|
enableGlobal: false,
|
||||||
processors: [],
|
processors: [],
|
||||||
},
|
},
|
||||||
preProcessorConfig: {
|
preProcessorConfig: {
|
||||||
enableGlobal: true,
|
enableGlobal: false,
|
||||||
processors: [],
|
processors: [],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -9,26 +9,28 @@
|
||||||
@close="handleClose"
|
@close="handleClose"
|
||||||
@cancel="handleDrawerCancel"
|
@cancel="handleDrawerCancel"
|
||||||
>
|
>
|
||||||
<div class="ml-[16px] mt-[10px]">
|
<div class="flex h-full flex-col">
|
||||||
<!-- <stepTypeVue v-if="props.step" :step="props.step" /> -->
|
<div class="ml-[16px] mt-[10px]">
|
||||||
{{ t('apiScenario.scriptOperationName') }}
|
<!-- <stepTypeVue v-if="props.step" :step="props.step" /> -->
|
||||||
</div>
|
{{ t('apiScenario.scriptOperationName') }}
|
||||||
<div class="ml-[16px] mt-[3px] max-w-[70%]">
|
</div>
|
||||||
<a-input
|
<div class="ml-[16px] mt-[3px] max-w-[70%]">
|
||||||
v-model="scriptName"
|
<a-input
|
||||||
:placeholder="t('apiScenario.scriptOperationNamePlaceholder')"
|
v-model="scriptName"
|
||||||
:max-length="255"
|
:placeholder="t('apiScenario.scriptOperationNamePlaceholder')"
|
||||||
size="small"
|
:max-length="255"
|
||||||
/>
|
size="small"
|
||||||
</div>
|
/>
|
||||||
<div class="mt-[10px] flex flex-1 gap-[8px]">
|
</div>
|
||||||
<conditionContent v-if="visible" v-model:data="activeItem" :is-build-in="true" :is-format="true" />
|
<div class="mt-[10px] flex flex-1 gap-[8px]">
|
||||||
</div>
|
<conditionContent v-if="visible" v-model:data="activeItem" :is-build-in="true" />
|
||||||
<div v-if="currentResponse?.console" class="p-[8px]">
|
</div>
|
||||||
<div class="mb-[8px] font-medium text-[var(--color-text-1)]">{{ t('apiScenario.executionResult') }}</div>
|
<div v-if="currentResponse?.console" class="p-[8px]">
|
||||||
<loopPagination v-model:current-loop="currentLoop" :loop-total="loopTotal" />
|
<div class="mb-[8px] font-medium text-[var(--color-text-1)]">{{ t('apiScenario.executionResult') }}</div>
|
||||||
<div class="h-[300px] bg-[var(--color-text-n9)] p-[12px]">
|
<loopPagination v-model:current-loop="currentLoop" :loop-total="loopTotal" />
|
||||||
<pre class="response-header-pre">{{ currentResponse?.console }}</pre>
|
<div class="h-[300px] bg-[var(--color-text-n9)] p-[12px]">
|
||||||
|
<pre class="response-header-pre">{{ currentResponse?.console }}</pre>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<template v-if="!props.detail" #footer>
|
<template v-if="!props.detail" #footer>
|
||||||
|
|
|
@ -66,12 +66,12 @@
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<div v-if="!checkedAll && !indeterminate" class="action-group ml-auto">
|
<div v-if="!checkedAll && !indeterminate" class="action-group ml-auto">
|
||||||
<a-input
|
<!-- <a-input
|
||||||
v-model:model-value="keyword"
|
v-model:model-value="keyword"
|
||||||
:placeholder="t('apiScenario.searchByName')"
|
:placeholder="t('apiScenario.searchByName')"
|
||||||
allow-clear
|
allow-clear
|
||||||
class="w-[200px]"
|
class="w-[200px]"
|
||||||
/>
|
/> -->
|
||||||
<a-tooltip v-if="!props.isNew" position="left" :content="t('apiScenario.refreshRefScenario')">
|
<a-tooltip v-if="!props.isNew" position="left" :content="t('apiScenario.refreshRefScenario')">
|
||||||
<a-button type="outline" class="arco-btn-outline--secondary !mr-0 !p-[8px]" @click="refreshStepInfo">
|
<a-button type="outline" class="arco-btn-outline--secondary !mr-0 !p-[8px]" @click="refreshStepInfo">
|
||||||
<template #icon>
|
<template #icon>
|
||||||
|
|
|
@ -5,9 +5,8 @@
|
||||||
v-model:model-value="innerData.delay"
|
v-model:model-value="innerData.delay"
|
||||||
class="max-w-[500px] px-[8px]"
|
class="max-w-[500px] px-[8px]"
|
||||||
size="mini"
|
size="mini"
|
||||||
:step="1"
|
:step="1000"
|
||||||
:min="0"
|
:min="0"
|
||||||
hide-button
|
|
||||||
:precision="0"
|
:precision="0"
|
||||||
model-event="input"
|
model-event="input"
|
||||||
:disabled="props.disabled"
|
:disabled="props.disabled"
|
||||||
|
|
Loading…
Reference in New Issue