feat(json-schema): ms-json-schema组件-json预览接口&json导入

This commit is contained in:
baiqi 2024-07-03 18:29:57 +08:00 committed by 刘瑞斌
parent d37fe74580
commit 2fc5db0745
8 changed files with 172 additions and 28 deletions

View File

@ -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
*/

View File

@ -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

View File

@ -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);

View File

@ -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,14 +462,23 @@
</MsCodeEditor>
</MsDrawer>
<MsDrawer v-model:visible="previewDrawerVisible" :width="600" :title="t('common.preview')" :footer="false">
<MsCodeEditor
v-model:model-value="activePreviewValue"
theme="vs"
height="100%"
:language="LanguageEnum.JSON"
:show-full-screen="false"
read-only
/>
<a-spin class="block" :loading="previewDrawerLoading">
<MsCodeEditor
v-model:model-value="activePreviewValue"
theme="vs"
height="100%"
: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({

View File

@ -21,4 +21,5 @@ export default {
'ms.json.schema.convertFailed': '数据转换失败,请重试',
'ms.json.schema.minItems': '最小元素数量',
'ms.json.schema.maxItems': '最大元素数量',
'ms.json.schema.illegalJsonConvertFailed': '转换失败请检查输入的json 结构是否合法',
};

View File

@ -17,7 +17,7 @@ export interface JsonSchemaCommon {
}
// json-schema 表格组件的表格项
export interface JsonSchemaTableItem extends JsonSchemaCommon {
required?: string[]; // 是否必填
required?: boolean; // 是否必填
children?: JsonSchemaTableItem[];
parent?: JsonSchemaTableItem; // 父级
enumValues?: string; // 参数值的枚举

View File

@ -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 };
}

View File

@ -276,7 +276,7 @@
};
}
return {
height: 'calc(100vh - 298px)',
height: 'calc(100vh - 250px)',
threshold: 200,
fixedSize: true,
buffer: 15, // 10 padding