feat(json-schema): ms-json-schema组件-json预览接口&json导入
This commit is contained in:
parent
d37fe74580
commit
2fc5db0745
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -421,7 +421,7 @@
|
|||
<div>
|
||||
<div class="mb-[8px]">{{ t('ms.json.schema.preview') }}</div>
|
||||
<MsCodeEditor
|
||||
v-model:model-value="activePreviewValue"
|
||||
v-model:model-value="activePreviewJsonSchemaValue"
|
||||
theme="vs"
|
||||
height="500px"
|
||||
:show-full-screen="false"
|
||||
|
@ -447,9 +447,9 @@
|
|||
:show-full-screen="false"
|
||||
>
|
||||
<template #leftTitle>
|
||||
<a-radio-group default-value="json" type="button" @change="batchAddValue = ''">
|
||||
<a-radio-group v-model:model-value="batchAddType" type="button" @change="batchAddValue = ''">
|
||||
<a-radio value="json">Json</a-radio>
|
||||
<a-radio value="jsonSchema">JsonSchema</a-radio>
|
||||
<a-radio value="schema">JsonSchema</a-radio>
|
||||
</a-radio-group>
|
||||
</template>
|
||||
<template #rightTitle>
|
||||
|
@ -462,6 +462,7 @@
|
|||
</MsCodeEditor>
|
||||
</MsDrawer>
|
||||
<MsDrawer v-model:visible="previewDrawerVisible" :width="600" :title="t('common.preview')" :footer="false">
|
||||
<a-spin class="block" :loading="previewDrawerLoading">
|
||||
<MsCodeEditor
|
||||
v-model:model-value="activePreviewValue"
|
||||
theme="vs"
|
||||
|
@ -469,7 +470,15 @@
|
|||
:language="LanguageEnum.JSON"
|
||||
:show-full-screen="false"
|
||||
read-only
|
||||
/>
|
||||
>
|
||||
<template #leftTitle>
|
||||
<a-radio-group v-model:model-value="previewShowType" type="button" @change="batchAddValue = ''">
|
||||
<a-radio value="json">Json</a-radio>
|
||||
<a-radio value="schema">JsonSchema</a-radio>
|
||||
</a-radio-group>
|
||||
</template>
|
||||
</MsCodeEditor>
|
||||
</a-spin>
|
||||
</MsDrawer>
|
||||
</template>
|
||||
|
||||
|
@ -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<any>({});
|
||||
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({
|
||||
|
|
|
@ -21,4 +21,5 @@ export default {
|
|||
'ms.json.schema.convertFailed': '数据转换失败,请重试',
|
||||
'ms.json.schema.minItems': '最小元素数量',
|
||||
'ms.json.schema.maxItems': '最大元素数量',
|
||||
'ms.json.schema.illegalJsonConvertFailed': '转换失败,请检查输入的json 结构是否合法',
|
||||
};
|
||||
|
|
|
@ -17,7 +17,7 @@ export interface JsonSchemaCommon {
|
|||
}
|
||||
// json-schema 表格组件的表格项
|
||||
export interface JsonSchemaTableItem extends JsonSchemaCommon {
|
||||
required?: string[]; // 是否必填
|
||||
required?: boolean; // 是否必填
|
||||
children?: JsonSchemaTableItem[];
|
||||
parent?: JsonSchemaTableItem; // 父级
|
||||
enumValues?: string; // 参数值的枚举
|
||||
|
|
|
@ -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<any>,
|
||||
parent?: JsonSchemaTableItem
|
||||
): { result: JsonSchemaTableItem[]; ids: Array<string> } {
|
||||
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<string> = [];
|
||||
|
||||
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 };
|
||||
}
|
||||
|
|
|
@ -276,7 +276,7 @@
|
|||
};
|
||||
}
|
||||
return {
|
||||
height: 'calc(100vh - 298px)',
|
||||
height: 'calc(100vh - 250px)',
|
||||
threshold: 200,
|
||||
fixedSize: true,
|
||||
buffer: 15, // 缓冲区默认 10 的时候,虚拟滚动的底部 padding 计算有问题
|
||||
|
|
Loading…
Reference in New Issue