成果
KFormDesign是什么
基于vue和ant-design-vue实现的表单设计器,样式使用less作为开发语言,主要功能是能通过简单操作来生成配置表单,生成可保存的JSON数据,并能将JSON还原成表单,使表单开发更简单更快速
KFormDesign主要分为两部分,k-form-design和k-form-build
k-form-design表单设计器,通过拖拽或点击设计生成表单json配置信息
k-form-build表单构建组件,将表单设计器生成的json数据构建成表单
官网:>https://www.kcz66.com/k-form-design/#/zh-cn/components/design
基本使用按照官网,讲的很详细
使用
我是先集成了源码,但是领导说不能集成源码,要为升级做考虑,然后又把它去了,功能实现没有动源码
1、前端用k-form-design作了表单设计器
2、后端把表单设计器生成的json数据存入数据库,表结构如下(重点)
DROP TABLE IF EXISTS `wf_form`;
CREATE TABLE `wf_form` (
`id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
`code` VARCHAR(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '表单代号',
`name` VARCHAR(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '表单名称',
`type` TINYINT(2) NOT NULL DEFAULT 0 COMMENT '表单类型。0:简单表单;1:复杂表单;',
`theme` VARCHAR(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '表单主题。不配置默认为表单名称',
`design_data` TEXT CHARACTER SET utf8 COLLATE utf8_general_ci NULL COMMENT '表单设计数据。',
`js_code` TEXT CHARACTER SET utf8 COLLATE utf8_general_ci NULL COMMENT '表单js代码。仅当复杂表单才有',
`create_time` DATETIME(0) NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` DATETIME(0) NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP(0) COMMENT '更新时间',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = INNODB AUTO_INCREMENT = 10 CHARACTER SET = utf8 COMMENT = '表单设计表' ROW_FORMAT = DYNAMIC;
重点说下js_code字段
js_code这个字段是我从生成的design_data表单设计数据中提取出来的动态配置信息,这是重点,为后续的初始化事件,级联字段,切换字段做准备
不叨叨了,上代码
提取逻辑
private String splitJscode (String designJson){
// 定义规则
String pattern = "(\"dynamicKey\":\")([^\"]+)(\")";
//Pattern.compile函数
Set sets =new HashSet();
Matcher matcher = Pattern.compile(pattern, Pattern.CASE_INSENSITIVE).matcher(designJson);
while (matcher.find()) { //表示往下遍历
sets.add(matcher.group(2));
}
return String.join(",", sets);
};
其实这个我是想,如果可以直接获取就好了,这个动态信息应该是必须要的,期待官网大大提供更好的方案,当然这个获取方法也很陋,欢迎分享更高效的提取方案
3、表单构建组件(重点)
初始化json信息
this.jsonData = JSON.parse(res.data.FORM_CONFIG_KEY.jsonData)
表单构建组件初始化配置信息
一个是获取DynamicData的动态配置信息,另一个是为了添加监控节点
associatedField
if (res.data.FORM_CONFIG_KEY.jsCode) {
this.wkFormDynamicData(res.data.FORM_CONFIG_KEY.jsCode)
}
wkFormDynamicData (jsCode) {
if (jsCode) {
this.dynamicData = {}
this.associatedField = []
const jsCodeArr = jsCode.split(',')
window.console.log(jsCodeArr)
jsCodeArr.forEach(dynamicValue => {
const typedata = dynamicValue.split('-')
if (typedata[0] === 'dict') {
this.SysDictTypeDropDown(typedata[1]).then((res) => {
const dictArr = []
res.data.forEach(dict => dictArr.push({ value: dict.code, label: dict.value }))
this.$set(this.dynamicData, dynamicValue, dictArr)
})
if (typedata[2]) {
switch (typedata[2]) {
case 'switch': {
// switch 事件 dict-字典code-switch-监控节点字段-case字段值_case字段名|case字段值_case字段名
// 添加监控节点字段
this.associatedField.push({ associatedCode: typedata[3], key: dynamicValue, value: typedata })
break
}
default:
{
window.console.log('未定义事件' + typedata[2])
}
}
}
} else if (typedata[0] === 'address_province') {
this.SysTenantProvinceSelector().then((res) => {
const addressArr = []
res.forEach(province => {
addressArr.push({ value: province.code, label: province.name })
})
this.$set(this.dynamicData, dynamicValue, addressArr)
}).catch((err) => {
this.$message.error('启动错误:' + err.message)
})
} else if (typedata[0] === 'business_type') {
// 添加监控字段
this.SysTenantIndustryTypeSelector().then((res) => {
const industryTypeArr = []
res.forEach(industryType => {
industryTypeArr.push({ value: industryType.code, label: industryType.name })
})
this.$set(this.dynamicData, dynamicValue, industryTypeArr)
}).catch((err) => {
this.$message.error('启动错误:' + err.message)
})
} else if (typedata[0] === 'address_city' || typedata[0] === 'business_name') {
// 子节点添加父节点监控,父节点变动获取子节点信息 子节点级联动态数据规范:子节点级联类型-父节点字段名-子节点字段名 父节点级联动态数据规范:父节点级联类型
this.associatedField.push({ associatedCode: typedata[1], key: dynamicValue, value: typedata })
}
})
}
},
信息回显
先处理监控节点信息,再信息回显
setTimeout(() => {
this.setDataInit(res.data.FORM_CONFIG_KEY.wkFormvalues)
}, 10)
setDataInit(wkFormvalues) {
window.console.log('wkFormvalues', wkFormvalues)
// 表单回显初始化
this.associatedField.forEach(item => {
if (wkFormvalues[item.associatedCode]) {
this.getSelectorInfo(item, wkFormvalues[item.associatedCode], item.associatedCode)
}
})
// 表单回显
this.$refs.kfb.setData(wkFormvalues)
window.console.log('this.associatedField', this.associatedField)
window.console.log('this.jsonData', this.jsonData)
window.console.log('this.dynamicData', this.dynamicData)
},
监控节点事件(主要是级联事件)
handleChange(value, key) {
this.associatedField.forEach(item => this.getSelectorInfo(item, value, key))
},
getSelectorInfo(item, value, key, clearFlag) {
if (item.associatedCode === key) {
// 数据变化时触发
if (item.value[0] === 'address_city') {
// 父节点前清除关联信息
if (clearFlag) {
const json = {}
json[item.value[2]] = ''
this.$refs.kfb.setData(json)
}
// 存在
this.SysTenantCitySelector(value).then((res) => {
const cityArr = []
res.forEach(city => {
cityArr.push({ value: city.code, label: city.name })
})
this.$set(this.dynamicData, item.key, cityArr)
})
} else if (item.value[0] === 'business_name') {
// 父节点前清除关联信息
if (clearFlag) {
const json = {}
json[item.value[2]] = ''
this.$refs.kfb.setData(json)
}
// 存在
this.SysIndustrySelector(value).then((res) => {
const industryArr = []
res.forEach(industry => {
industryArr.push({ value: industry.code, label: industry.name })
})
this.$set(this.dynamicData, item.key, industryArr)
})
} else if (item.value[0] === 'dict') {
this.switchCase(item, value, key)
}
}
},
动态节点切换关联事件(不知道这玩意叫啥,反正出现了这个场景,那就要开发)
switchCase (item, value, key) {
switch (item.value[2]) {
case 'switch': {
// switch 事件 dict-字典code-switch-监控节点字段-case字段值_case字段名|case字段值_case字段名
if (value) {
window.console.log('switch')
item.value[4].split('|').forEach(switchCase => {
const switchCaseSplit = switchCase.split('_')
// case字段隐藏
this.jsonData.list.forEach((datalist, datalistIndex) => {
if (datalist) {
if (datalist.type === 'tabs') {
datalist.columns.forEach((tabs, tabsIndex) => {
const listIndex = tabs.list.findIndex(modelInfo => modelInfo.model === switchCaseSplit[1])
if (listIndex > -1) {
this.jsonData.list[datalistIndex].columns[tabsIndex].list[listIndex].options.hidden = true
if (value === switchCaseSplit[0]) {
// 匹配case字段开启
this.jsonData.list[datalistIndex].columns[tabsIndex].list[listIndex].options.hidden = false
}
}
})
}
}
})
})
}
break
}
default:
{
window.console.log('未定义事件' + item.value[2])
}
}
},
总结
k-form-design生成jsondata数据,通过抽取jscode获取动态数据
k-form-build根据jsondata构建表单
通过jscode生成dynamic-data选项控件的动态配置数据
并通过jscode获取监听节点通过change监控表单数据改变时触发事件
在通过setData回显数据