diff --git a/frontend/src/api/modules/api-test/management.ts b/frontend/src/api/modules/api-test/management.ts
index 0e87a1da8f..7edc5efe47 100644
--- a/frontend/src/api/modules/api-test/management.ts
+++ b/frontend/src/api/modules/api-test/management.ts
@@ -1,3 +1,5 @@
+import type { JsonSchema } from '@/components/pure/ms-json-schema/types';
+
import MSR from '@/api/http/index';
import {
AddCaseUrl,
@@ -19,6 +21,7 @@ import {
BatchUpdateDefinitionUrl,
CasePageUrl,
CheckDefinitionScheduleUrl,
+ ConvertJsonSchemaToJsonUrl,
CopyMockUrl,
DebugCaseUrl,
DebugDefinitionUrl,
@@ -298,6 +301,11 @@ export function getDefinitionReference(data: DefinitionReferencePageParams) {
return MSR.post({ url: DefinitionReferenceUrl, data });
}
+// 将json-schema转换为 json 数据
+export function convertJsonSchemaToJson(data: JsonSchema) {
+ return MSR.post({ url: ConvertJsonSchemaToJsonUrl, data });
+}
+
/**
* Mock
*/
diff --git a/frontend/src/api/requrls/api-test/management.ts b/frontend/src/api/requrls/api-test/management.ts
index 6011907133..39fa65afa0 100644
--- a/frontend/src/api/requrls/api-test/management.ts
+++ b/frontend/src/api/requrls/api-test/management.ts
@@ -35,6 +35,7 @@ export const OperationHistoryUrl = '/api/definition/operation-history'; // 接
export const SaveOperationHistoryUrl = '/api/definition/operation-history/save'; // 接口定义-另存变更历史为指定版本
export const RecoverOperationHistoryUrl = '/api/definition/operation-history/recover'; // 接口定义-变更历史恢复
export const DefinitionReferenceUrl = '/api/definition/get-reference'; // 获取接口引用关系
+export const ConvertJsonSchemaToJsonUrl = '/api/definition/preview'; // 将json-schema转换为 json 数据
/**
* Mock
diff --git a/frontend/src/components/business/ms-params-input/index.vue b/frontend/src/components/business/ms-params-input/index.vue
index 93a23e289b..f08145d80b 100644
--- a/frontend/src/components/business/ms-params-input/index.vue
+++ b/frontend/src/components/business/ms-params-input/index.vue
@@ -363,7 +363,11 @@
});
const disabledPopover = computed(() => {
- return !innerValue.value || innerValue.value.trim() === '' || isFocusAutoComplete.value;
+ return (
+ !innerValue.value ||
+ (typeof innerValue.value === 'string' && innerValue.value.trim() === '') ||
+ isFocusAutoComplete.value
+ );
});
const paramSettingVisible = ref(false);
diff --git a/frontend/src/components/pure/ms-json-schema/index.vue b/frontend/src/components/pure/ms-json-schema/index.vue
index c4feb4eef1..9f6834bff3 100644
--- a/frontend/src/components/pure/ms-json-schema/index.vue
+++ b/frontend/src/components/pure/ms-json-schema/index.vue
@@ -421,7 +421,7 @@
{{ t('ms.json.schema.preview') }}
-
+
Json
- JsonSchema
+ JsonSchema
@@ -462,14 +462,23 @@
-
+
+
+
+
+ Json
+ JsonSchema
+
+
+
+
@@ -485,13 +494,14 @@
import MsParamsInput from '@/components/business/ms-params-input/index.vue';
import MsQuickInput from '@/components/business/ms-quick-input/index.vue';
+ import { convertJsonSchemaToJson } from '@/api/modules/api-test/management';
import { useI18n } from '@/hooks/useI18n';
import { getGenerateId, traverseTree } from '@/utils';
import { TableKeyEnum } from '@/enums/tableEnum';
- import { JsonSchemaTableItem } from './types';
- import { convertToJsonSchema } from './utils';
+ import { JsonSchema, JsonSchemaTableItem } from './types';
+ import { parseJsonToJsonSchemaTableItem, tableItemToJsonSchema } from './utils';
const { t } = useI18n();
@@ -828,38 +838,52 @@
const batchAddDrawerVisible = ref(false);
const batchAddValue = ref('');
+ const batchAddType = ref<'json' | 'schema'>('json');
function batchAdd() {
batchAddDrawerVisible.value = true;
}
function applyBatchAdd() {
+ if (batchAddType.value === 'json') {
+ const res = parseJsonToJsonSchemaTableItem(batchAddValue.value);
+ if (res.result.length > 0) {
+ data.value = res.result;
+ selectedKeys.value = res.ids;
+ }
+ }
batchAddDrawerVisible.value = false;
}
const settingDrawerVisible = ref(false);
const activeRecord = ref
({});
- const activePreviewValue = ref('');
+ const previewShowType = ref<'json' | 'schema'>('json');
+ const activePreviewJsonValue = ref('');
+ const activePreviewJsonSchemaValue = ref('');
+ const activePreviewValue = computed(() => {
+ return previewShowType.value === 'json' ? activePreviewJsonValue.value : activePreviewJsonSchemaValue.value;
+ });
- function openSetting(record: JsonSchemaTableItem) {
+ async function openSetting(record: JsonSchemaTableItem) {
// 浅拷贝,以保留 parent 和 children 的引用
activeRecord.value = {
...record,
};
try {
- activePreviewValue.value = JSON.stringify(convertToJsonSchema(record, record.id === 'root'));
+ const schema = tableItemToJsonSchema(record, record.id === 'root');
+ activePreviewJsonSchemaValue.value = JSON.stringify(schema);
} catch (error) {
// eslint-disable-next-line no-console
console.log(error);
- activePreviewValue.value = t('ms.json.schema.convertFailed');
+ activePreviewJsonSchemaValue.value = t('ms.json.schema.convertFailed');
} finally {
settingDrawerVisible.value = true;
}
}
function handleSettingFormChange() {
- activePreviewValue.value = JSON.stringify(
- convertToJsonSchema(activeRecord.value, activeRecord.value.id === 'root')
+ activePreviewJsonSchemaValue.value = JSON.stringify(
+ tableItemToJsonSchema(activeRecord.value, activeRecord.value.id === 'root')
);
}
@@ -901,9 +925,24 @@
}
const previewDrawerVisible = ref(false);
- function previewSchema() {
+ const previewDrawerLoading = ref(false);
+
+ async function previewSchema() {
previewDrawerVisible.value = true;
- activePreviewValue.value = JSON.stringify(convertToJsonSchema(data.value[0]));
+ try {
+ previewDrawerLoading.value = true;
+ const schema = tableItemToJsonSchema(data.value[0]);
+ const res = await convertJsonSchemaToJson(schema as JsonSchema);
+ activePreviewJsonValue.value = JSON.stringify(res);
+ activePreviewJsonSchemaValue.value = JSON.stringify(schema);
+ } catch (error) {
+ // eslint-disable-next-line no-console
+ console.log(error);
+ activePreviewJsonValue.value = t('ms.json.schema.convertFailed');
+ activePreviewJsonSchemaValue.value = t('ms.json.schema.convertFailed');
+ } finally {
+ previewDrawerLoading.value = false;
+ }
}
defineExpose({
diff --git a/frontend/src/components/pure/ms-json-schema/locale/zh-CN.ts b/frontend/src/components/pure/ms-json-schema/locale/zh-CN.ts
index d21c5ae5c7..aacb216c39 100644
--- a/frontend/src/components/pure/ms-json-schema/locale/zh-CN.ts
+++ b/frontend/src/components/pure/ms-json-schema/locale/zh-CN.ts
@@ -21,4 +21,5 @@ export default {
'ms.json.schema.convertFailed': '数据转换失败,请重试',
'ms.json.schema.minItems': '最小元素数量',
'ms.json.schema.maxItems': '最大元素数量',
+ 'ms.json.schema.illegalJsonConvertFailed': '转换失败,请检查输入的json 结构是否合法',
};
diff --git a/frontend/src/components/pure/ms-json-schema/types.ts b/frontend/src/components/pure/ms-json-schema/types.ts
index 8014050ae5..d6c5935410 100644
--- a/frontend/src/components/pure/ms-json-schema/types.ts
+++ b/frontend/src/components/pure/ms-json-schema/types.ts
@@ -17,7 +17,7 @@ export interface JsonSchemaCommon {
}
// json-schema 表格组件的表格项
export interface JsonSchemaTableItem extends JsonSchemaCommon {
- required?: string[]; // 是否必填
+ required?: boolean; // 是否必填
children?: JsonSchemaTableItem[];
parent?: JsonSchemaTableItem; // 父级
enumValues?: string; // 参数值的枚举
diff --git a/frontend/src/components/pure/ms-json-schema/utils.ts b/frontend/src/components/pure/ms-json-schema/utils.ts
index 3cd8ca2fdd..8f86b47dbb 100644
--- a/frontend/src/components/pure/ms-json-schema/utils.ts
+++ b/frontend/src/components/pure/ms-json-schema/utils.ts
@@ -1,3 +1,8 @@
+import { Message } from '@arco-design/web-vue';
+
+import { useI18n } from '@/hooks/useI18n';
+import { getGenerateId } from '@/utils';
+
import type { JsonSchema, JsonSchemaItem, JsonSchemaTableItem } from './types';
/**
@@ -5,7 +10,7 @@ import type { JsonSchema, JsonSchemaItem, JsonSchemaTableItem } from './types';
* @param schemaItem 表格组件项
* @param isRoot 是否为根节点
*/
-export function convertToJsonSchema(
+export function tableItemToJsonSchema(
schemaItem: JsonSchemaTableItem,
isRoot: boolean = true
): JsonSchema | JsonSchemaItem {
@@ -41,7 +46,7 @@ export function convertToJsonSchema(
required: [],
};
schemaItem.children.forEach((child) => {
- const childSchema = convertToJsonSchema(child, false);
+ const childSchema = tableItemToJsonSchema(child, false);
schema.properties![child.title] = childSchema as JsonSchemaItem;
if (child.required) {
schema.required!.push(child.title);
@@ -54,11 +59,97 @@ export function convertToJsonSchema(
schema = {
type: 'array',
enable: schemaItem.enable,
- items: schemaItem.children.map((child) => convertToJsonSchema(child, false) as JsonSchemaItem),
+ items: schemaItem.children.map((child) => tableItemToJsonSchema(child, false) as JsonSchemaItem),
};
}
}
return schema;
}
-export default {};
+
+/**
+ * 创建 json-schema 表格组件的表格项
+ * @param key 对象/数组/普通子项的 key名
+ * @param value 对象/数组/普通子项的值
+ * @param parent 父级
+ */
+function createItem(key: string, value: any, parent?: JsonSchemaTableItem): JsonSchemaTableItem {
+ let exampleValue; // 默认情况下,example 值为 undefined
+ const itemType = Array.isArray(value) ? 'array' : typeof value;
+
+ // 如果值不是对象或数组,则直接将值作为 example
+ if (itemType !== 'object' && itemType !== 'array') {
+ exampleValue = typeof value === 'boolean' ? value.toString() : value;
+ }
+
+ return {
+ id: getGenerateId(),
+ title: key,
+ type: itemType,
+ description: '',
+ enable: true,
+ required: true,
+ defaultValue: '',
+ example: exampleValue, // 仅当值不是对象或数组时,才赋予 example 值
+ parent,
+ };
+}
+/**
+ * 将 json 转换为 json-schema 表格组件的表格项
+ * @param json json 字符串或对象或数组
+ * @param parent 父级
+ */
+export function parseJsonToJsonSchemaTableItem(
+ json: string | object | Array,
+ parent?: JsonSchemaTableItem
+): { result: JsonSchemaTableItem[]; ids: Array } {
+ if (typeof json === 'string') {
+ // 尝试将 json 字符串转换为对象
+ try {
+ json = JSON.parse(json);
+ } catch (error) {
+ const { t } = useI18n();
+ Message.warning(t('ms.json.schema.illegalJsonConvertFailed'));
+ return { result: [], ids: [] };
+ }
+ }
+ if (!parent) {
+ // 创建根节点
+ const rootItem: JsonSchemaTableItem = {
+ id: 'root',
+ title: 'root',
+ type: Array.isArray(json) ? 'array' : 'object',
+ description: '',
+ enable: true,
+ required: true,
+ example: '',
+ defaultValue: '',
+ };
+ const children = parseJsonToJsonSchemaTableItem(json, rootItem);
+ rootItem.children = children.result;
+ children.ids.push(rootItem.id);
+ return { result: [rootItem], ids: children.ids };
+ }
+
+ const items: JsonSchemaTableItem[] = [];
+ const type = Array.isArray(json) ? 'array' : 'object';
+ const ids: Array = [];
+
+ if (type === 'object' || type === 'array') {
+ // 遍历对象或数组
+ Object.entries(json).forEach(([key, value]) => {
+ const item: JsonSchemaTableItem = createItem(key, value, parent);
+ if (typeof value === 'object' || Array.isArray(value)) {
+ const children = parseJsonToJsonSchemaTableItem(value, item);
+ item.children = children.result;
+ ids.push(...children.ids);
+ } else {
+ item.example = typeof value === 'boolean' ? value.toString() : value;
+ }
+ items.push(item);
+ ids.push(item.id);
+ });
+ }
+
+ return { result: items, ids };
+}
diff --git a/frontend/src/views/api-test/management/components/moduleTree.vue b/frontend/src/views/api-test/management/components/moduleTree.vue
index 21d6ce649d..0f1ffbe9cc 100644
--- a/frontend/src/views/api-test/management/components/moduleTree.vue
+++ b/frontend/src/views/api-test/management/components/moduleTree.vue
@@ -276,7 +276,7 @@
};
}
return {
- height: 'calc(100vh - 298px)',
+ height: 'calc(100vh - 250px)',
threshold: 200,
fixedSize: true,
buffer: 15, // 缓冲区默认 10 的时候,虚拟滚动的底部 padding 计算有问题