工控人成长 | KingFusion 开发实战
一、背景
在 MES 项目中,经常需要维护编码规则表(如:组织→大类→二级分类→形参类的层级关系)。新增编码规则时,遇到一个需求:
-
用户可以选择已有的编码规则作为参考,自动填充下级
-
用户也可以直接输入全新的编码规则
-
代码和名称要同步显示
本文分享的就是这个"可输入可选组合框 + 4级级联"的实现方案。
二、最终效果
组织代码: [▼ 可输入可选] 组织名称: [▼ 可输入可选]
大类代码: [▼ 可输入可选] 大类名称: [▼ 可输入可选]
二级分类代码: [▼ 可输入可选] 二级分类名称: [▼ 可输入可选]
形参类代码: [▼ 可输入可选] 形参类名称: [▼ 可输入可选]
排序号: [自动生成]
[保存] [取消]
用户操作流程:
-
页面加载后,首组(组织代码+组织名称)已填充数据
-
从下拉选择已有代码 → 自动填充名称 → 级联加载大类
-
输入新代码 → 清空名称,让用户手动输入 → 清空下级
-
选完4级后,排序号自动生成
-
点击保存,新增一条编码规则
三、核心设计
3.1 组合框 label/value 互换
KingFusion 的组合框默认配置 valueField: "label"、textField: "value"。即:
-
getValue()取
label字段 -
显示文本取
value字段
为了让代码组合框显示代码、存储名称,名称组合框显示名称、存储代码,两个组合框加载的数据故意互换:
// 加载组织组合框数据
var data = []; // 给代码组合框
var data1 = []; // 给名称组合框
for (var i = 0; i < records.length; i++) {
data.push({
label: records[i].c_OrgName, // label=名称 → getValue()返回名称
value: records[i].c_OrgCode // value=代码 → 显示代码
});
data1.push({
label: records[i].c_OrgCode, // label=代码 → getValue()返回代码
value: records[i].c_OrgName // value=名称 → 显示名称
});
}
$(Cbox_OrgCode.id).combobox('loadData', data); // 代码组合框
$(Cbox_OrgName.id).combobox('loadData', data1); // 名称组合框
这样设计后:
| 组合框 | 显示内容 | getValue() | getText() |
|---|---|---|---|
| 代码组合框 | 代码(如"1") | 名称(如"北京") | 代码(如"1") |
| 名称组合框 | 名称(如"北京") | 代码(如"1") | 名称(如"北京") |
3.2 选择 vs 输入的处理
组合框设置 editable: true 后,用户既可以下拉选择,也可以手动输入。
关键逻辑:区分"选择已有值"和"输入新值"
// ========== 组织代码 onChange ==========
var orgValue = $(Cbox_OrgCode.id).combobox('getValue');
var orgText = $(Cbox_OrgCode.id).combobox('getText');
if (orgValue === '' || orgValue === undefined) {
// 用户输入了新值(不在下拉列表里)
// → 清空名称,让用户手动输入;清空下级组合框
clearLowerLevels();
} else {
// 用户选择了已有值
// → 自动填充名称,级联加载下一级
$(Cbox_OrgName.id).combobox('setValue', orgValue);
loadNextLevel(orgText);
}
判断依据:
-
getValue()有值 → 用户选择了下拉中的已有项
-
getValue()为空 → 用户输入了新值,此时用
getText()获取用户输入的内容
3.3 4级级联加载
每选完一级,根据当前选中的值加载下一级的下拉数据:
// 加载大类(根据组织)
function loadCodeType(orgCode) {
var M = {'type': 29, 'Level': 2, 'OrgCode': orgCode};
requestCalculationPost(数据源, '计算工程名称', M, function(res) {
if (res.Code === 0 && res.errorCode29 === 0) {
var data = [];
var data1 = [];
for (var i = 0; i < res.records29.length; i++) {
data.push({label: res.records29[i].c_CodeTypeName, value: res.records29[i].c_CodeType});
data1.push({label: res.records29[i].c_CodeType, value: res.records29[i].c_CodeTypeName});
}
$(Cbox_CodeType.id).combobox('loadData', data);
$(Cbox_CodeTypeName.id).combobox('loadData', data1);
}
});
}
3.4 名称组合框的双向同步
当用户选择了名称组合框时,也要同步回代码组合框:
// ========== 组织名称 onChange ==========
var orgValue = $(Cbox_OrgName.id).combobox('getValue');
var orgText = $(Cbox_OrgName.id).combobox('getText');
if (orgValue !== '' && orgValue !== undefined) {
// 用户选择了名称 → 自动回填代码
$(Cbox_OrgCode.id).combobox('setValue', orgValue);
}
这样无论是从代码组合框选,还是从名称组合框选,两个组合框的内容始终同步。
3.5 保存时统一用 getText()
由于前面设计好了代码和名称组合框的 label/value 互换,保存时直接用 getText() 取显示文本,不需要复杂的判断:
// ========== 保存按钮 ==========
var orgValue = $(Cbox_OrgCode.id).combobox('getText'); // 代码
var orgName = $(Cbox_OrgName.id).combobox('getText'); // 名称
var typeValue = $(Cbox_CodeType.id).combobox('getText');
var typeName = $(Cbox_CodeTypeName.id).combobox('getText');
// ... 以此类推
if (orgValue === '' || orgName === '' || ...) {
$Function.tip('warning', '请完整填写!');
} else {
// 调用后端保存
requestCalculationPost(数据源, '计算工程名称', M30, function(res) {
if (res.Code === 0 && res.errorCode30 === 0) {
$Function.tip('success', '新增成功!');
// 刷新主界面
// 关闭本页
}
});
}
3.6 排序号自动生成
排序号在父级范围内自动递增,由后端计算:
-- 取当前组织+大类下最大排序号 + 1
SELECT COALESCE(MAX(”i_Seq”), 0) + 1 AS ”nextSeq”
FROM ”编码规则表”
WHERE ”c_OrgCode”='${OrgCode}' AND ”c_CodeType”='${CodeType}'
四、总结
4.1 核心经验
| 经验 | 说明 |
|---|---|
| getValue vs getText | editable=true时,getValue() 判断是否选择已有项,getText() 取实际显示文本 |
| 代码-名称互换 | 两个组合框 label/value 互换,实现"代码显示代码、名称显示名称" |
| 保存用 getText | 统一用 getText() 取显示文本,代码更简洁 |
| 级联加载 | 选完一级后异步加载下一级 |
| 排序号自动生成 | 后端在父级范围内 MAX+1 |
4.2 适用场景
这个设计模式适用于:
-
编码规则维护页面的新增功能
-
类似的层级字典数据维护
-
需要"可选择已有值"或"直接输入新值"的场景
本文首发于【雷工笔记】,一个工控人的成长记录。