Files
kintone-helper-extenstion/features/add-field-label/fields.js
2025-10-17 14:39:35 +08:00

186 lines
5.7 KiB
JavaScript

import {
LAYOUT_TYPES,
FIELD_TYPES,
SYSTEM_STATUS_FIELD_TYPES,
SYSTEM_FIELD_TYPES,
EXCLUDED_GROUP_TYPES
} from '../../utils/constants.js';
import {
sortFieldOptions,
shouldSortOptions,
markLookupCopies,
} from '../../utils/field-utils.js';
/**
* 从属性列表中添加系统状态字段到字段数组中
* @param {Object} properties - 所有字段属性对象
* @param {Array} fields - 要添加字段的数组
*/
const addSystemStatusFields = (properties, fields) => {
const propertyList = Object.values(properties);
SYSTEM_STATUS_FIELD_TYPES.forEach(type => {
const field = propertyList.find(f => f.type === type);
if (field?.enabled) {
fields.push(field);
}
});
};
/**
* 处理常规行布局中的字段
* @param {Array} rowFields - 行中的字段列表
* @param {Object} properties - 字段属性映射
* @param {Array} fields - 要添加字段的数组
* @param {Array} spacers - 要添加间距元素的数组
*/
const processRowFields = (rowFields, properties, fields, spacers) => {
for (const field of rowFields) {
// 跳过标签和分割线布局
if ([LAYOUT_TYPES.LABEL, LAYOUT_TYPES.HR].includes(field.type)) continue;
// 处理间距元素
if (field.type === LAYOUT_TYPES.SPACER) {
spacers.push(field);
continue;
}
const fieldProperty = properties[field.code];
// 跳过子表和分组类型的字段,这些单独处理
if ([FIELD_TYPES.SUBTABLE, FIELD_TYPES.GROUP].includes(fieldProperty.type)) continue;
// 创建处理后的字段对象,支持选项排序的字段添加排序选项
const processedField = shouldSortOptions(fieldProperty.type)
? { ...fieldProperty, sortedOptions: sortFieldOptions(fieldProperty) }
: fieldProperty;
fields.push(processedField);
}
};
/**
* 处理子表字段
* @param {Object} layout - 子表布局对象
* @param {Object} properties - 字段属性映射
* @param {Array} fields - 要添加字段的数组
*/
const processSubtableFields = (layout, properties, fields) => {
const tableCode = layout.code;
const tableField = properties[tableCode];
if (tableField.type !== FIELD_TYPES.SUBTABLE) return;
const subtableFieldsMap = {};
// 处理子表中每个字段
layout.fields.forEach(({ code: fieldCode }) => {
const subField = tableField.fields[fieldCode];
const processedField = shouldSortOptions(subField.type)
? { ...subField, table: tableCode, sortedOptions: sortFieldOptions(subField) }
: { ...subField, table: tableCode };
subtableFieldsMap[fieldCode] = processedField;
fields.push(processedField);
});
// 将完整的子表信息也添加到字段列表中
fields.push({ ...tableField, fields: subtableFieldsMap });
};
/**
* 处理分组字段
* @param {Object} layout - 分组布局对象
* @param {Object} properties - 字段属性映射
* @param {Array} fields - 要添加字段的数组
* @param {Array} spacers - 要添加间距元素的数组
*/
const processGroupFields = (layout, properties, fields, spacers) => {
const groupCode = layout.code;
const groupField = properties[groupCode];
if (groupField.type !== FIELD_TYPES.GROUP) return;
const groupFieldsMap = {};
// 处理分组中的每个字段
layout.layout.forEach(row => {
row.fields.forEach(field => {
// 跳过标签和分割线布局
if ([LAYOUT_TYPES.LABEL, LAYOUT_TYPES.HR].includes(field.type)) return;
// 处理间距元素
if (field.type === LAYOUT_TYPES.SPACER) {
spacers.push({ ...field, group: groupCode });
return;
}
const groupSubField = properties[field.code];
// 跳过排除的字段类型
if (EXCLUDED_GROUP_TYPES.includes(groupSubField.type)) return;
const processedField = shouldSortOptions(groupSubField.type)
? { ...groupSubField, group: groupCode, sortedOptions: sortFieldOptions(groupSubField) }
: { ...groupSubField, group: groupCode };
groupFieldsMap[field.code] = processedField;
fields.push(processedField);
});
});
// 将完整的分组信息也添加到字段列表中
fields.push({ ...groupField, fields: groupFieldsMap });
};
/**
* 添加缺失的系统字段
* @param {Object} properties - 字段属性对象
* @param {Array} fields - 要添加字段的数组
*/
const addMissingSystemFields = (properties, fields) => {
const propertyList = Object.values(properties);
SYSTEM_FIELD_TYPES.forEach(type => {
const field = propertyList.find(f => f.type === type);
// 只添加还没有的系统字段
if (field && !fields.some(f => f.type === type)) {
fields.push(field);
}
});
};
/**
* 从表单属性和布局生成处理后的字段和间距数组
* @param {Object} properties - 字段属性对象
* @param {Array} layouts - 布局定义
* @returns {Object} 包含字段和间距数组的对象
*/
export const generateFields = (properties, layouts) => {
const fields = [];
const spacers = [];
// 首先添加系统状态字段
addSystemStatusFields(properties, fields);
// 处理每个布局项
layouts.forEach(layout => {
switch (layout.type) {
case LAYOUT_TYPES.ROW:
processRowFields(layout.fields, properties, fields, spacers);
break;
case LAYOUT_TYPES.SUBTABLE:
processSubtableFields(layout, properties, fields);
break;
case LAYOUT_TYPES.GROUP:
processGroupFields(layout, properties, fields, spacers);
break;
}
});
markLookupCopies(fields);
addMissingSystemFields(properties, fields);
return { fields, spacers };
};