Skip to content

Commit

Permalink
fix: api插件配置项映射组件错误问题修复 #86
Browse files Browse the repository at this point in the history
# Reviewed, transaction id: 28994
  • Loading branch information
ywywZhou committed Jan 10, 2025
1 parent 602d4e0 commit fadc9c2
Showing 1 changed file with 152 additions and 125 deletions.
277 changes: 152 additions & 125 deletions frontend/src/utils/jsonFormSchema.js
Original file line number Diff line number Diff line change
@@ -1,140 +1,167 @@
import tools from './tools';

function getProperties(data = [], config = {}) {
return data.reduce((acc, cur) => {
const { key, name, desc, type, required, form_type: formType, options, meta_desc: metaDesc, multiple } = cur;
function getDataType(type) {
if (type === 'bool') return 'boolean';
if (type === 'int') return 'number';
if (type === 'list') return 'array';
return 'string';
}

let dataType = type === 'bool' ? 'boolean' : 'string';
dataType = type === 'int' ? 'number' : dataType;
acc[key] = {
title: name,
type: dataType,
sourceType: type,
formType,
description: desc || '',
extend: {
can_hook: 'can_hook' in config ? config.can_hook : true,
hook: false,
},
};
function createBaseProperty(cur, type, formType, config) {
const { name, desc, options } = cur;

if (metaDesc) {
acc[key].metaDesc = metaDesc;
}
const dataType = getDataType(type);
const compType = getCompType(type, formType, options);

if (required) {
let validRules = type === 'bool' ? '{{ typeof $self.value === "boolean" }}' : '{{ $self.value?.length > 0 }}';
validRules = type === 'int' ? '{{ $self.value >= 0 }}' : validRules;
acc[key]['ui:rules'] = [{
validator: validRules,
message: '值不能为空',
}];
}
return {
title: name,
type: dataType,
sourceType: type,
formType,
description: desc || '',
extend: {
can_hook: 'can_hook' in config ? config.can_hook : true,
hook: false,
},
'ui:component': {
name: compType,
props: {},
},
};
}

if (cur.default) {
let defaultVal = cur.default;
if (type === 'json' && !tools.checkIsJSON(defaultVal)) {
defaultVal = JSON.stringify(cur.default, null, 4);
}
acc[key].default = defaultVal;
}
function createValidationRules(type) {
let validRules = type === 'bool' ? '{{ typeof $self.value === "boolean" }}' : '{{ $self.value?.length > 0 }}';
validRules = type === 'int' ? '{{ $self.value >= 0 }}' : validRules;
return [{
validator: validRules,
message: '值不能为空',
}];
}

if (type === 'list') {
acc[key].type = 'array';
if (formType === 'table') {
const properties = getProperties(cur.table.fields, {
...cur.table.meta,
...config,
});
const tableColumnProps = { showOverflowTooltip: { interactive: true } };
Object.values(properties).forEach((item) => {
if (item['ui:props']) {
item['ui:props'].tableColumnProps = tableColumnProps;
} else {
item['ui:props'] = { tableColumnProps };
}
/* 特殊处理!!!
* 表格下单元格如果为下拉框,则popover宽度默认为auto
* 设置为字符串类型宽度是为了避免select组件使用默认宽度
*/
if (item['ui:component'].name === 'select') {
item['ui:component'].props['popover-width'] = 'max-content';
}
});
acc[key].items = {
type: 'object',
properties,
};
acc[key]['ui:props'] = {
...config,
};
} else if (formType !== 'time_range') {
// checkbox为数组类型
acc[key]['ui:props'] = {
...config,
};
const dataSource = options.map(item => ({
label: item.text || item,
value: item.value || item,
})) || [];
acc[key]['ui:component'] = {
name: 'checkbox',
props: { datasource: dataSource },
};
return acc;
}
}
function getDefaultVal(defaultVal, type) {
if (type === 'json' && !tools.checkIsJSON(defaultVal)) {
return JSON.stringify(defaultVal, null, 4);
}
return defaultVal;
}

function getCompType(type, formType, options) {
let compType = 'bfInput';
// 支持表单类型
if (formType) {
compType = ['input', 'textarea'].includes(formType) ? compType : formType;
} else if (type === 'list') {
compType = formType === 'time_range' ? 'datetimerange' : 'checkbox';
compType = formType === 'table' ? 'table' : compType;
} else {
compType = ['int', 'string'].includes(type) && options?.length ? 'select' : compType;
compType = type === 'bool' ? 'switcher' : compType;
}
return compType;
}

let compType = 'bfInput';
// 支持表单类型
if (formType) {
if (!['input', 'textarea'].includes(formType)) {
compType = formType;
}
function setComponentProps(acc, cur, key, config) {
const { multiple, hint, allow_create: allowCreate, options, type, form_type: formType } = cur;
const { name: compType } = acc[key]['ui:component'];

if (compType === 'select') {
const dataSource = options.map((item) => {
const result = {
label: item.text || item,
value: item.value || item,
};
return result;
}) || [];
acc[key].type = multiple ? 'array' : acc[key].type;
acc[key]['ui:component'].props = {
...config,
datasource: dataSource,
multiple,
allowCreate,
searchable: true,
};
} else if (compType === 'checkbox') {
acc[key]['ui:props'] = {
...config,
};
const dataSource = options.map(item => ({
label: item.text || item,
value: item.value || item,
})) || [];
acc[key]['ui:component'].props = { datasource: dataSource };
} else if (['int', 'string', 'textarea'].includes(type)) {
// 区分文本框和数字框
let inputType = type === 'int' ? 'number' : 'text';
inputType = formType === 'textarea' ? 'textarea' : inputType;
acc[key]['ui:component'].props = {
...config,
placeholder: hint,
type: inputType,
};
} else if (type === 'json') {
acc[key]['ui:component'].props = {
...config,
placeholder: hint || '请输入JSON格式数据{ "xxx": "xxx" }',
type: 'textarea',
extCls: 'json-textarea',
};
} else if (formType === 'time_range') {
acc[key]['ui:component'].name = 'bk-date-picker';
acc[key]['ui:component'].props = {
...config,
type: 'datetimerange',
placeholder: hint || '请选择时间范围',
transfer: true,
multiple: false,
};
}
}

function setTableProps(acc, cur, key, config) {
const properties = getProperties(cur.table.fields, {
...cur.table.meta,
...config,
});
const tableColumnProps = { showOverflowTooltip: { interactive: true } };
Object.values(properties).forEach((item) => {
if (item['ui:props']) {
item['ui:props'].tableColumnProps = tableColumnProps;
} else {
compType = ['int', 'string'].includes(type) && options?.length ? 'select' : compType;
compType = type === 'bool' ? 'switcher' : compType;
item['ui:props'] = { tableColumnProps };
}
acc[key]['ui:component'] = {
name: compType,
props: {
...config,
},
};
if (options && options.length) {
const dataSource = options.map((item) => {
const result = {
label: item.text || item,
value: item.value || item,
};
return result;
}) || [];
acc[key]['ui:component'].props.datasource = dataSource;
acc[key].type = multiple ? 'array' : acc[key].type;
acc[key]['ui:component'].props.multiple = multiple;
} else if (['int', 'string', 'textarea'].includes(type)) {
// 区分文本框和数字框
let inputType = type === 'int' ? 'number' : 'text';
inputType = formType === 'textarea' ? 'textarea' : inputType;
acc[key]['ui:component'].props.type = inputType;
} else if (type === 'json') {
acc[key]['ui:component'].props = {
...config,
placeholder: '请输入JSON格式数据{ "xxx": "xxx" }',
type: 'textarea',
extCls: 'json-textarea',
};
} else if (formType && formType === 'time_range') {
acc[key]['ui:component'].name = 'bk-date-picker';
acc[key]['ui:component'].props = {
...config,
type: 'datetimerange',
placeholder: '请选择时间范围',
transfer: true,
multiple: false,
};
/* 特殊处理!!!
* 表格下单元格如果为下拉框,则popover宽度默认为auto
* 设置为字符串类型宽度是为了避免select组件使用默认宽度
*/
if (item['ui:component'].name === 'select') {
item['ui:component'].props['popover-width'] = 'max-content';
}
});
acc[key].items = {
type: 'object',
properties,
};
acc[key]['ui:props'] = {
...config,
};
}

function getProperties(data = [], config = {}) {
return data.reduce((acc, cur) => {
const { key, type, required, form_type: formType, meta_desc: metaDesc } = cur;

acc[key] = createBaseProperty(cur, type, formType, config);

if (metaDesc) acc[key].metaDesc = metaDesc;
if (required) acc[key]['ui:rules'] = createValidationRules(type);
if (cur.default) acc[key].default = getDefaultVal(cur.default, type);

if (formType === 'table') {
setTableProps(acc, cur, key, config);
} else {
setComponentProps(acc, cur, key, config);
}
return acc;
}, {});
}
Expand Down

0 comments on commit fadc9c2

Please sign in to comment.