Appearance
JPwise 布局优化规则
本文档与 列表配置规范 相互配合,提供完整的布局优化解决方案。
表单布局智能优化
字段分组策略
javascript
const fieldGrouping = {
// 基本信息组
basic: {
title: "基本信息",
patterns: ['NAME', 'CODE', 'TYPE', 'STATUS', 'TITLE'],
icon: "icon-ym icon-ym-generator-group",
span: 12,
priority: 1
},
// 联系信息组
contact: {
title: "联系信息",
patterns: ['PHONE', 'EMAIL', 'ADDRESS', 'CONTACT', 'TEL'],
icon: "icon-ym icon-ym-generator-group",
span: 8,
priority: 3
},
// 财务信息组
financial: {
title: "财务信息",
patterns: ['AMOUNT', 'PRICE', 'COST', 'TAX', 'CURRENCY', 'FEE', 'MONEY'],
icon: "icon-ym icon-ym-generator-group",
span: 8,
priority: 2
},
// 时间信息组
timeline: {
title: "时间信息",
patterns: ['DATE', 'TIME', 'START', 'END', 'DEADLINE', 'PERIOD'],
icon: "icon-ym icon-ym-generator-group",
span: 12,
priority: 4
},
// 人员信息组
personnel: {
title: "人员信息",
patterns: ['USER', 'PERSON', 'STAFF', 'EMPLOYEE', 'CREATOR', 'MODIFIER'],
icon: "icon-ym icon-ym-generator-group",
span: 8,
priority: 2
},
// 组织信息组
organization: {
title: "组织信息",
patterns: ['DEPT', 'DEPARTMENT', 'ORGANIZE', 'BRANCH', 'DIVISION'],
icon: "icon-ym icon-ym-generator-group",
span: 8,
priority: 3
},
// 附加信息组
additional: {
title: "附加信息",
patterns: ['REMARK', 'NOTE', 'ATTACHMENT', 'COMMENT', 'DESC', 'DETAIL'],
icon: "icon-ym icon-ym-generator-group",
span: 24,
priority: 5
}
}
自动分组算法
javascript
function autoGroupFields(fields) {
const groups = {};
const ungrouped = [];
fields.forEach(field => {
let grouped = false;
// 检查字段是否匹配任何分组模式
for (const [groupKey, groupConfig] of Object.entries(fieldGrouping)) {
if (matchesGroupPattern(field.name, groupConfig.patterns)) {
if (!groups[groupKey]) {
groups[groupKey] = {
...groupConfig,
fields: []
};
}
groups[groupKey].fields.push(field);
grouped = true;
break;
}
}
if (!grouped) {
ungrouped.push(field);
}
});
// 将未分组的字段添加到基本信息组
if (ungrouped.length > 0) {
if (!groups.basic) {
groups.basic = { ...fieldGrouping.basic, fields: [] };
}
groups.basic.fields.push(...ungrouped);
}
return groups;
}
栅格布局优化
javascript
const spanCalculation = {
// 基于组件类型
byComponent: {
'comInput': 8, // 普通输入框
'numInput': 8, // 数字输入框
'JPWInput': 8, // 统计数值
'select': 8, // 下拉选择
'date': 8, // 日期选择
'userSelect': 8, // 用户选择
'depSelect': 8, // 部门选择
'switch': 8, // 开关
'textarea': 24, // 多行文本
'editor': 24, // 富文本
'uploadFz': 24, // 文件上传
'uploadImg': 24, // 图片上传
'table': 24, // 子表
'popupSelect': 12 // 弹窗选择
},
// 基于字段重要性
byImportance: {
'high': 12, // 重要字段(名称、编号等)
'medium': 8, // 普通字段
'low': 6 // 次要字段
},
// 基于字段组
byGroup: {
'basic': 8, // 基本信息
'financial': 8, // 财务信息
'contact': 8, // 联系信息
'timeline': 12, // 时间信息
'additional': 24 // 附加信息
}
}
// 智能span计算(与 component-mapping.md 中的策略保持一致)
function calculateSpan(field, component, group) {
// 1. 检查特殊组件类型(最高优先级)
if (spanCalculation.byComponent[component]) {
return spanCalculation.byComponent[component];
}
// 2. 检查字段类型模式
if (spanCalculation.byFieldType) {
for (const [pattern, span] of Object.entries(spanCalculation.byFieldType)) {
if (field.field && field.field.includes(pattern)) {
return span;
}
}
}
// 3. 检查字段重要性
const importance = getFieldImportance(field);
if (spanCalculation.byImportance[importance]) {
return spanCalculation.byImportance[importance];
}
// 4. 检查字段组
if (spanCalculation.byGroup[group]) {
return spanCalculation.byGroup[group];
}
// 5. 默认值(统一为 12)
return 12;
}
// 字段重要性判断函数
function getFieldImportance(field) {
const criticalPatterns = ['TITLE', 'CONTENT', 'DETAIL', 'REMARK', 'NOTE', 'DESC'];
const highPatterns = ['NAME', 'CODE', 'NO'];
const fieldName = field.field || field.fieldName || '';
if (criticalPatterns.some(pattern => fieldName.includes(pattern))) {
return 'critical';
}
if (highPatterns.some(pattern => fieldName.includes(pattern))) {
return 'high';
}
return 'medium';
}
折叠面板生成规则
javascript
function generateCollapsePanels(groupedFields) {
const panels = [];
// 按优先级排序分组
const sortedGroups = Object.entries(groupedFields)
.sort((a, b) => a[1].priority - b[1].priority);
sortedGroups.forEach(([groupKey, groupConfig], index) => {
panels.push({
title: groupConfig.title,
name: index.toString(),
isHide: ["pc", "app"],
__config__: {
children: groupConfig.fields.map(field =>
generateFormComponent(field, groupConfig.span)
)
}
});
});
return panels;
}
列表布局优化
详细的列表配置规范请参考 列表配置规范,本节重点介绍布局优化算法。
列宽智能计算
javascript
const columnWidthRules = {
// 基于字段类型
byFieldType: {
'ID': 0, // ID列隐藏
'CODE': 120, // 编码列
'NAME': 150, // 名称列
'TITLE': 200, // 标题列
'AMOUNT': 100, // 金额列
'DATE': 120, // 日期列
'TIME': 100, // 时间列
'STATUS': 80, // 状态列
'STATE': 80, // 状态列
'TYPE': 100, // 类型列
'REMARK': 200, // 备注列
'NOTE': 200, // 说明列
'USER': 100, // 用户列
'PERSON': 100, // 人员列
'DEPT': 120, // 部门列
'PHONE': 120, // 电话列
'EMAIL': 150, // 邮箱列
'ADDRESS': 200 // 地址列
},
// 基于数据类型
byDataType: {
'varchar': (length) => Math.min(Math.max(length * 1.2, 80), 300),
'decimal': 100,
'int': 80,
'datetime': 120,
'date': 100,
'time': 80,
'text': 200
},
// 基于字段名长度
byLabelLength: (label) => Math.max(label.length * 12, 80)
}
function calculateColumnWidth(field) {
// 1. 检查字段名称模式
for (const [pattern, width] of Object.entries(columnWidthRules.byFieldType)) {
if (field.field.includes(pattern)) {
return width;
}
}
// 2. 检查数据类型
const typeRule = columnWidthRules.byDataType[field.dataType];
if (typeRule) {
return typeof typeRule === 'function'
? typeRule(field.dataLength)
: typeRule;
}
// 3. 基于标签长度
return columnWidthRules.byLabelLength(field.fieldName || field.field);
}
搜索字段智能选择
javascript
const searchFieldRules = {
// 自动添加搜索的字段模式
autoSearch: [
{ pattern: /.*NAME.*/, type: 'LK', component: 'comInput' },
{ pattern: /.*TITLE.*/, type: 'LK', component: 'comInput' },
{ pattern: /.*CODE.*/, type: 'EQ', component: 'comInput' },
{ pattern: /.*NO.*/, type: 'EQ', component: 'comInput' },
{ pattern: /.*STATUS.*/, type: 'EQ', component: 'select' },
{ pattern: /.*STATE.*/, type: 'EQ', component: 'select' },
{ pattern: /.*TYPE.*/, type: 'EQ', component: 'select' },
{ pattern: /.*DATE.*/, type: 'RANGE', component: 'date' },
{ pattern: /.*TIME.*/, type: 'RANGE', component: 'date' }
],
// 快速查询字段
quickQuery: [
/.*NAME.*/,
/.*TITLE.*/,
/.*CODE.*/
]
}
function generateSearchConfig(fields) {
const searchList = [];
const quickQueryFields = [];
fields.forEach(field => {
// 检查是否应该添加搜索
searchFieldRules.autoSearch.forEach(rule => {
if (rule.pattern.test(field.field)) {
searchList.push({
...field,
searchType: rule.type,
searchJnpfKey: rule.component,
search: true
});
}
});
// 检查是否应该添加到快速查询
searchFieldRules.quickQuery.forEach(pattern => {
if (pattern.test(field.field)) {
quickQueryFields.push(field.field);
}
});
});
// 智能统计字段选择
const summaryFields = fields
.filter(field => {
const isNumericField = ['decimal', 'int', 'float', 'number'].includes(field.dataType);
const isAmountField = ['AMOUNT', 'MONEY', 'PRICE', 'COST', 'FEE', 'SALARY'].some(pattern =>
field.field.includes(pattern)
);
return isNumericField && isAmountField;
})
.map(field => field.field);
return {
searchList,
quickQuery: quickQueryFields.join(','),
summaryFields // 添加统计字段
};
}
列显示优化
javascript
const columnDisplayRules = {
// 默认隐藏的字段
hidden: [
'ID',
'CREATORUSER',
'LASTMODIFYUSER',
'DELETEUSER',
'ORGANIZE',
'SORTCODE'
],
// 默认显示的字段(按优先级)
visible: {
high: ['NAME', 'TITLE', 'CODE', 'STATUS'],
medium: ['TYPE', 'AMOUNT', 'DATE', 'USER', 'DEPT'],
low: ['REMARK', 'NOTE', 'CREATETIME']
},
// 固定列配置
fixed: {
left: ['NAME', 'CODE'],
right: ['OPERATION']
}
}
function optimizeColumnDisplay(fields) {
return fields.map(field => {
const isHidden = columnDisplayRules.hidden.some(pattern =>
field.field.includes(pattern)
);
const fixedPosition = getFixedPosition(field.field);
return {
...field,
showtable: !isHidden,
fixed: fixedPosition,
sortable: !isHidden && field.dataType !== 'text'
};
});
}
按钮配置智能优化
javascript
const buttonOptimizationRules = {
// 按钮显示优先级
buttonPriority: {
// 行按钮优先级(数字越小优先级越高)
row: {
'btn_row_detail': 1, // 详情按钮优先显示
'btn_row_edit': 2, // 编辑按钮
'btn_row_remove': 3, // 删除按钮
'btn_row_copy': 4 // 复制按钮可选
},
// 顶部按钮优先级
top: {
'btn_top_add': 1, // 新增按钮优先
'btn_top_refresh': 2, // 刷新按钮
'btn_top_download': 3, // 导出按钮
'btn_top_edit': 4, // 批量编辑
'btn_top_batchRemove': 5, // 批量删除
'btn_top_importExcel': 6, // 导入按钮
'btn_top_search': 7 // 高级搜索
}
},
// 基于业务场景的按钮配置
scenarioButtons: {
financial: {
required: ['btn_row_detail', 'btn_top_add', 'btn_top_download'],
optional: ['btn_row_edit', 'btn_top_batchRemove', 'btn_top_importExcel'],
hidden: ['btn_row_remove'] // 财务数据通常不允许直接删除
},
workflow: {
required: ['btn_row_detail', 'btn_top_add', 'btn_top_refresh'],
optional: ['btn_row_edit', 'btn_top_download'],
hidden: ['btn_top_batchRemove'] // 工作流数据不允许批量删除
},
general: {
required: ['btn_row_edit', 'btn_row_detail', 'btn_top_add', 'btn_top_refresh'],
optional: ['btn_row_remove', 'btn_top_batchRemove', 'btn_top_download'],
hidden: []
}
}
}
// 智能按钮配置生成算法
function optimizeButtonConfiguration(businessScenario, permissions) {
const scenario = buttonOptimizationRules.scenarioButtons[businessScenario] ||
buttonOptimizationRules.scenarioButtons.general;
const buttonConfig = {
customBtnsList: [],
customTopBtnsList: []
};
// 生成行按钮配置
const rowButtons = [...scenario.required, ...scenario.optional]
.filter(btnValue => btnValue.startsWith('btn_row_'))
.filter(btnValue => !scenario.hidden.includes(btnValue))
.filter(btnValue => hasButtonPermission(permissions, btnValue))
.sort((a, b) =>
(buttonOptimizationRules.buttonPriority.row[a] || 99) -
(buttonOptimizationRules.buttonPriority.row[b] || 99)
);
rowButtons.forEach(btnValue => {
const button = generateOptimizedRowButton(btnValue, businessScenario);
if (button) {
buttonConfig.customBtnsList.push(button);
}
});
// 生成顶部按钮配置
const topButtons = [...scenario.required, ...scenario.optional]
.filter(btnValue => btnValue.startsWith('btn_top_'))
.filter(btnValue => !scenario.hidden.includes(btnValue))
.filter(btnValue => hasButtonPermission(permissions, btnValue))
.sort((a, b) =>
(buttonOptimizationRules.buttonPriority.top[a] || 99) -
(buttonOptimizationRules.buttonPriority.top[b] || 99)
);
topButtons.forEach(btnValue => {
const button = generateOptimizedTopButton(btnValue, businessScenario);
if (button) {
buttonConfig.customTopBtnsList.push(button);
}
});
return buttonConfig;
}
// 权限检查辅助函数
function hasButtonPermission(permissions, buttonValue) {
const permissionMapping = {
'btn_row_edit': 'edit',
'btn_row_remove': 'delete',
'btn_row_detail': 'read',
'btn_row_copy': 'add',
'btn_top_add': 'add',
'btn_top_edit': 'edit',
'btn_top_batchRemove': 'delete',
'btn_top_download': 'export',
'btn_top_importExcel': 'import'
};
const requiredPermission = permissionMapping[buttonValue];
return !requiredPermission || permissions.includes(requiredPermission);
}
综合布局优化算法
javascript
// 综合布局优化主函数
function optimizeCompleteLayout(fields, businessScenario, permissions) {
return {
// 表单布局优化
formLayout: {
groupedFields: autoGroupFields(fields),
collapsePanels: generateCollapsePanels(autoGroupFields(fields)),
spanOptimization: fields.map(field => ({
...field,
span: calculateSpan(field, getOptimalComponent(field), getFieldGroup(field))
}))
},
// 列表布局优化
listLayout: {
columnConfig: generateSearchConfig(fields),
columnDisplay: optimizeColumnDisplay(fields),
columnWidths: fields.map(field => ({
...field,
width: calculateColumnWidth(field)
})),
buttonConfig: optimizeButtonConfiguration(businessScenario, permissions)
}
};
}