feat(接口测试): json-schema功能补充&批量添加参数问题修复
This commit is contained in:
parent
5b01adde1c
commit
0619578403
|
@ -38,7 +38,7 @@
|
|||
label=""
|
||||
:rules="{
|
||||
validator: (value, callback) => {
|
||||
validRepeat(rowIndex, item.dataIndex as string, value, callback);
|
||||
validRepeat(rowIndex, item.dataIndex as string, record[item.dataIndex as string], record, callback);
|
||||
},
|
||||
}"
|
||||
:disabled="props.disabled || item.disabled || record.disabled"
|
||||
|
@ -354,17 +354,31 @@
|
|||
|
||||
// 校验重复
|
||||
const formRef = ref<FormInstance>();
|
||||
async function validRepeat(rowIndex: number, dataIndex: string, value: any, callback: (error?: string) => void) {
|
||||
async function validRepeat(
|
||||
rowIndex: number,
|
||||
dataIndex: string,
|
||||
value: any,
|
||||
record: Record<string, any>,
|
||||
callback: (error?: string) => void
|
||||
) {
|
||||
const currentColumn = props.columns.find((item) => item.dataIndex === dataIndex);
|
||||
if (!currentColumn?.needValidRepeat) {
|
||||
callback();
|
||||
return;
|
||||
}
|
||||
propsRes.value.data?.forEach((row, index) => {
|
||||
if (row[dataIndex].length && index !== rowIndex && row[dataIndex] === value) {
|
||||
callback(`${t(currentColumn?.title as string)}${t('msFormTable.paramRepeatMessage')}`);
|
||||
}
|
||||
});
|
||||
if (record.parent) {
|
||||
(record.parent.children as Record<string, any>[])?.forEach((row, index) => {
|
||||
if (row[dataIndex].length && index !== rowIndex && row[dataIndex] === value) {
|
||||
callback(`${t(currentColumn?.title as string)}${t('msFormTable.paramRepeatMessage')}`);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
propsRes.value.data?.forEach((row, index) => {
|
||||
if (row[dataIndex].length && index !== rowIndex && row[dataIndex] === value) {
|
||||
callback(`${t(currentColumn?.title as string)}${t('msFormTable.paramRepeatMessage')}`);
|
||||
}
|
||||
});
|
||||
}
|
||||
callback();
|
||||
}
|
||||
|
||||
|
|
|
@ -6,12 +6,7 @@
|
|||
:columns="columns"
|
||||
show-empty-tree
|
||||
:selectable="false"
|
||||
:row-selection="{
|
||||
type: 'checkbox',
|
||||
showCheckedAll: true,
|
||||
checkStrictly: true,
|
||||
width: 32,
|
||||
}"
|
||||
:row-selection="rowSelection"
|
||||
:table-key="TableKeyEnum.JSON_SCHEMA"
|
||||
:scroll="{ x: 'max-content' }"
|
||||
:disabled="props.disabled"
|
||||
|
@ -521,7 +516,7 @@
|
|||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { SelectOptionData, TableData } from '@arco-design/web-vue';
|
||||
import { SelectOptionData, TableData, TableRowSelection } from '@arco-design/web-vue';
|
||||
import { cloneDeep } from 'lodash-es';
|
||||
|
||||
import MsButton from '@/components/pure/ms-button/index.vue';
|
||||
|
@ -578,6 +573,17 @@
|
|||
default: () => ['root'],
|
||||
});
|
||||
|
||||
const rowSelection = computed<TableRowSelection | undefined>(() => {
|
||||
if (props.disabled) {
|
||||
return undefined;
|
||||
}
|
||||
return {
|
||||
type: 'checkbox',
|
||||
showCheckedAll: true,
|
||||
checkStrictly: true,
|
||||
width: 32,
|
||||
};
|
||||
});
|
||||
// 初始化根节点
|
||||
watchEffect(() => {
|
||||
if (data.value.length === 0) {
|
||||
|
@ -676,6 +682,7 @@
|
|||
size: 'medium',
|
||||
columnSelectorDisabled: true,
|
||||
fixed: 'left',
|
||||
needValidRepeat: true,
|
||||
},
|
||||
{
|
||||
title: t('ms.json.schema.type'),
|
||||
|
@ -866,6 +873,7 @@
|
|||
if (!selectedKeys.value.includes(child.id)) {
|
||||
selectedKeys.value.push(child.id);
|
||||
}
|
||||
data.value = [...data.value];
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -11,10 +11,11 @@ import type { JsonSchema, JsonSchemaItem, JsonSchemaTableItem } from './types';
|
|||
* @param isRoot 是否为根节点
|
||||
*/
|
||||
export function parseTableDataToJsonSchema(
|
||||
schemaItem: JsonSchemaTableItem,
|
||||
schemaItem?: JsonSchemaTableItem,
|
||||
isRoot: boolean = true
|
||||
): JsonSchema | JsonSchemaItem | undefined {
|
||||
try {
|
||||
if (!schemaItem) return undefined;
|
||||
let schema: JsonSchema | JsonSchemaItem = { type: schemaItem.type };
|
||||
|
||||
// 对于 null 类型,只设置 type 和 enable 属性
|
||||
|
@ -84,7 +85,10 @@ export function parseTableDataToJsonSchema(
|
|||
*/
|
||||
function createItem(key: string, value: any, parent?: JsonSchemaTableItem): JsonSchemaTableItem {
|
||||
let exampleValue; // 默认情况下,example 值为 undefined
|
||||
const itemType = Array.isArray(value) ? 'array' : typeof value;
|
||||
let itemType = Array.isArray(value) ? 'array' : typeof value;
|
||||
if (value === null) {
|
||||
itemType = 'null';
|
||||
}
|
||||
|
||||
// 如果值不是对象或数组,则直接将值作为 example
|
||||
if (itemType !== 'object' && itemType !== 'array') {
|
||||
|
@ -110,7 +114,7 @@ function createItem(key: string, value: any, parent?: JsonSchemaTableItem): Json
|
|||
* @param parent 父级
|
||||
*/
|
||||
export function parseJsonToJsonSchemaTableData(
|
||||
json: string | object | Array<any>,
|
||||
json: string | object | Array<any> | null,
|
||||
parent?: JsonSchemaTableItem
|
||||
): { result: JsonSchemaTableItem[]; ids: Array<string> } {
|
||||
if (typeof json === 'string') {
|
||||
|
@ -145,11 +149,11 @@ export function parseJsonToJsonSchemaTableData(
|
|||
const type = Array.isArray(json) ? 'array' : 'object';
|
||||
const ids: Array<string> = [];
|
||||
|
||||
if (type === 'object' || type === 'array') {
|
||||
if ((type === 'object' || type === 'array') && json !== null) {
|
||||
// 遍历对象或数组
|
||||
Object.entries(json).forEach(([key, value]) => {
|
||||
const item: JsonSchemaTableItem = createItem(key, value, parent);
|
||||
if (typeof value === 'object' || Array.isArray(value)) {
|
||||
if ((typeof value === 'object' && value !== null) || Array.isArray(value)) {
|
||||
const children = parseJsonToJsonSchemaTableData(value, item);
|
||||
item.children = children.result;
|
||||
ids.push(...children.ids);
|
||||
|
|
|
@ -71,6 +71,7 @@
|
|||
disabled?: boolean;
|
||||
typeTitle?: string;
|
||||
hasStandard?: boolean; // 是否有标准模式
|
||||
acceptTypes?: RequestParamsType[]; // 可接受的参数类型
|
||||
}>(),
|
||||
{
|
||||
noParamType: false,
|
||||
|
@ -179,7 +180,9 @@
|
|||
id: getGenerateId(),
|
||||
...cloneDeep(props.defaultParamItem), // 深拷贝,避免有嵌套引用类型,数据隔离
|
||||
key: key.trim(),
|
||||
paramType: Object.values(RequestParamsType).includes(type?.trim() as unknown as RequestParamsType)
|
||||
paramType: (props.acceptTypes || Object.values(RequestParamsType)).includes(
|
||||
type?.trim() as unknown as RequestParamsType
|
||||
)
|
||||
? type?.trim()
|
||||
: RequestParamsType.STRING,
|
||||
required: stringToBoolean(required),
|
||||
|
|
|
@ -86,7 +86,7 @@
|
|||
</div> -->
|
||||
</div>
|
||||
<a-spin v-else :loading="bodyLoading" class="block h-[calc(100%-34px)]">
|
||||
<div class="mb-[8px] flex items-center justify-between">
|
||||
<div v-if="innerParams.bodyType === RequestBodyFormat.JSON" class="mb-[8px] flex items-center justify-between">
|
||||
<div class="flex items-center gap-[8px]">
|
||||
<MsButton
|
||||
type="text"
|
||||
|
@ -126,7 +126,7 @@
|
|||
</a-button>
|
||||
</div>
|
||||
<MsJsonSchema
|
||||
v-if="innerParams.jsonBody.enableJsonSchema"
|
||||
v-if="innerParams.jsonBody.enableJsonSchema && innerParams.bodyType === RequestBodyFormat.JSON"
|
||||
ref="jsonSchemaRef"
|
||||
v-model:data="innerParams.jsonBody.jsonSchemaTableData"
|
||||
v-model:selectedKeys="innerParams.jsonBody.jsonSchemaTableSelectedRowKeys"
|
||||
|
@ -140,16 +140,17 @@
|
|||
height="100%"
|
||||
:show-full-screen="false"
|
||||
:show-theme-change="false"
|
||||
:show-code-format="true"
|
||||
:show-code-format="!(props.disabledExceptParam || props.disabledParamValue)"
|
||||
:language="currentCodeLanguage"
|
||||
is-adaptive
|
||||
>
|
||||
<template #rightTitle>
|
||||
<a-button
|
||||
v-if="innerParams.bodyType === RequestBodyFormat.JSON"
|
||||
type="outline"
|
||||
class="arco-btn-outline--secondary p-[0_8px]"
|
||||
size="mini"
|
||||
:disabled="props.disabledParamValue"
|
||||
:disabled="props.disabledExceptParam || props.disabledParamValue"
|
||||
@click="autoMakeJson"
|
||||
>
|
||||
<div class="text-[var(--color-text-1)]">{{ t('apiTestManagement.autoMake') }}</div>
|
||||
|
@ -163,6 +164,7 @@
|
|||
:disabled="props.disabledExceptParam"
|
||||
:params="currentTableParams"
|
||||
:default-param-item="defaultBodyParamsItem"
|
||||
:accept-types="innerParams.bodyType === RequestBodyFormat.WWW_FORM ? wwwFormParamsTypes : undefined"
|
||||
has-standard
|
||||
@apply="handleBatchParamApply"
|
||||
/>
|
||||
|
@ -432,6 +434,9 @@
|
|||
return LanguageEnum.PLAINTEXT;
|
||||
});
|
||||
|
||||
const wwwFormParamsTypes = Object.values(RequestParamsType).filter(
|
||||
(val) => ![RequestParamsType.JSON, RequestParamsType.FILE].includes(val)
|
||||
);
|
||||
/**
|
||||
* 批量参数代码转换为参数表格数据
|
||||
*/
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
:params="innerParams"
|
||||
:disabled="props.disabledExceptParam"
|
||||
:default-param-item="defaultRequestParamsItem"
|
||||
:accept-types="queryParamsTypes"
|
||||
has-standard
|
||||
@apply="handleBatchParamApply"
|
||||
/>
|
||||
|
@ -62,6 +63,9 @@
|
|||
const { t } = useI18n();
|
||||
|
||||
const innerParams = useVModel(props, 'params', emit);
|
||||
const queryParamsTypes = Object.values(RequestParamsType).filter(
|
||||
(val) => ![RequestParamsType.JSON, RequestParamsType.FILE].includes(val)
|
||||
);
|
||||
const columns = computed<ParamTableColumn[]>(() => [
|
||||
{
|
||||
title: 'apiTestDebug.paramName',
|
||||
|
@ -74,12 +78,10 @@
|
|||
dataIndex: 'paramType',
|
||||
slotName: 'paramType',
|
||||
hasRequired: true,
|
||||
options: Object.values(RequestParamsType)
|
||||
.filter((val) => ![RequestParamsType.JSON, RequestParamsType.FILE].includes(val))
|
||||
.map((val) => ({
|
||||
label: val,
|
||||
value: val,
|
||||
})),
|
||||
options: queryParamsTypes.map((val) => ({
|
||||
label: val,
|
||||
value: val,
|
||||
})),
|
||||
width: 120,
|
||||
},
|
||||
{
|
||||
|
|
|
@ -147,7 +147,9 @@
|
|||
"
|
||||
>
|
||||
<MsJsonSchema
|
||||
v-if="activeResponse.body.jsonBody.enableJsonSchema"
|
||||
v-if="
|
||||
activeResponse.body.jsonBody.enableJsonSchema && activeResponse.body.bodyType === ResponseBodyFormat.JSON
|
||||
"
|
||||
ref="jsonSchemaRef"
|
||||
v-model:data="activeResponse.body.jsonBody.jsonSchemaTableData"
|
||||
v-model:selectedKeys="selectedKeys"
|
||||
|
@ -165,7 +167,13 @@
|
|||
show-code-format
|
||||
>
|
||||
<template #rightTitle>
|
||||
<a-button type="outline" class="arco-btn-outline--secondary p-[0_8px]" size="mini" @click="autoMakeJson">
|
||||
<a-button
|
||||
v-if="activeResponse.body.bodyType === ResponseBodyFormat.JSON"
|
||||
type="outline"
|
||||
class="arco-btn-outline--secondary p-[0_8px]"
|
||||
size="mini"
|
||||
@click="autoMakeJson"
|
||||
>
|
||||
<div class="text-[var(--color-text-1)]">{{ t('apiTestManagement.autoMake') }}</div>
|
||||
</a-button>
|
||||
</template>
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
:params="innerParams"
|
||||
:disabled="props.disabledExceptParam"
|
||||
:default-param-item="defaultRequestParamsItem"
|
||||
:accept-types="restParamsTypes"
|
||||
has-standard
|
||||
@apply="handleBatchParamApply"
|
||||
/>
|
||||
|
@ -62,7 +63,9 @@
|
|||
const { t } = useI18n();
|
||||
|
||||
const innerParams = useVModel(props, 'params', emit);
|
||||
|
||||
const restParamsTypes = Object.values(RequestParamsType).filter(
|
||||
(val) => ![RequestParamsType.JSON, RequestParamsType.FILE].includes(val)
|
||||
);
|
||||
const columns = computed<ParamTableColumn[]>(() => [
|
||||
{
|
||||
title: 'apiTestDebug.paramName',
|
||||
|
|
|
@ -818,4 +818,7 @@
|
|||
box-shadow: 0 0 7px 0 rgb(15 0 78 / 9%);
|
||||
}
|
||||
}
|
||||
:deep(.arco-table-td-content) {
|
||||
padding: 5px 8px;
|
||||
}
|
||||
</style>
|
||||
|
|
Loading…
Reference in New Issue