1.说明
在平台中用户可以方便的添加自定义控件,每一个自定义控件,都有一下特点:
- 字段权限
- 编辑和只读两种状态
- 有自定义的数据
在平台中,我们的自定义控件一般为单值和双值,他们指的是,比如输入框控件这个属于单值控件,用户控件属于双值控件。当然我们也可以有多值控件,比如 用户地址控件,这种控件的数据我们使用多个字段进行存储,主要是为了方便查询。
我们以地址控件为例,我们怎么自定义添加一个控件。
2. 实现自定义控件步骤
实现一个自定义表单控件分为前端和后端的实现,大家按照这个步骤,可以实现自己的表单控件。
下面我们以平台中实现的地址控件为例说明以下这个控件实现的过程。
2.1 需求分析
地址控件是表单中常用的控件,如果我们使用下拉框连到也是可以实现的,但是这个会很复杂,因此我们需要定制一个控件。
数据存储:
地址控件的数据存储其实可以有两种方式:
1.使用一个字段存储JSON
如果只是使用一个字段存储问题是不方便查询。
2.使用多个字段存储
逻辑处理复杂一些,但是可以方便数据查询,比如根据地区查询。
在平台中实现的话使用的是第二种。
2.2 前端实现
控件实现的功能是:
- 只读的情况显示
- 无权限的时候的隐藏
- 编辑数据的时候显示
地址控件有七个值,数据格式为:
{
province: "",
province_code: "",
city: "",
city_code: "",
county: "",
county_code: "",
address: ""
}
控件在表单的样式为
控件的代码为:
<rx-address class="rx-address active" type="main" ctltype="rx-address" id="rqavfwy836397" :readonly="readonly" :permission="getPermission('main','dz')" :valid="validFunc("main","dz")" v-model="data.dz" :required="false" style="width:80%"></rx-address>
这里我们实现了v-model的方式,具体可以参考vue 的组件实现文档。
属性说明:
属性 | 说明 |
---|---|
type | 这个表示控件所在的是主表还是子表 main 主表字段,onetomany 一对多子表,onetoone 一对一子表 |
ctltype | 这个表示为控件类型 |
readonly | 是否只读,比如在明细的时候,这个值为true |
permission | 这个为字段权限 分别为 “none”无权限,”r”:只读权限,”w”编辑权限 |
valid | 字段权限计算 |
v-model | 表单字段 ,通过v-model 的方式实现表单数据的双向绑定 |
下面写下如何在设计器中添加控件的步骤:
2.2.1 设计控件
参考代码
/components/controllers/rxAddress.vue
2.2.2 在左侧工具栏中添加控件。
这里需要修改 controllers.js
{
type: 'rxAddress',
label: '地址控件',
icon: 'iconbiaoge',
disabled: false,
form:true
}
如果控件还未实现,那么 disabled 为true 。
2.2.3 响应点击控件
在点击控件时,会在表单中增加控件,我们需要编辑代码 addCtls.js
我们增加添加控件的代码如下:
ControllerUtil.rxAddress=function(){
var id=Util.randomId();
var input=`<rx-address class="rx-address" type="main" ctltype="rx-address" id="${id}"></rx-address>`;
return input;
};
2.2.4 编辑控件对应的属性设置组件
在点击控件时,我们需要对控件做属性的配置,因此我们对于每一个控件,都会增加一个相应的控件设置组件。
设置配置组件的名字 为 “控件类型” +-config
控件配置组件名字定义如下:
rx-address-config
代码参考:
/components/config/rxAddressConfig.vue
2.2.5 在设置控件时使 html 生效
在属性配置进行配置时,系统会修改设计器中的html,一般做法如下:
编辑 modifyControllers.js 代码
增加代码如下:
CtlEdit["rx-address"] = function(curEl, config, type, tablename) {
var isMain = type == "main";
var permission =`getPermission('${tablename}','${config.name}')`;
var validFunc = `validFunc("${type}","${config.name}")`;
var model = CtlEdit.getModel(config, type, tablename);
var conf = {
":readonly": "readonly",
":permission": permission,
":valid": validFunc,
"v-model": model,
"type": type,
":required": config.required,
"style":'width:'+config.width
};
CtlEdit.setAttribute(conf, curEl);
}
样式展示
样式文件iframe.css
2.3 后端实现
这里我们可以看到,实际上,我们这个控件 接收的数据是一个JSON。通过解析JSON,将控件进行显示。但是 我们的控件在后端实际不是使用json存储,当然这样也可以,我们为了查询和统计的方便,我们是将控件作为 7个字段进行存储。
所以这里设计到的几个问题:
- 在设计表单时,我们需要在创建的物理表中生成7个字段。
- 在数据提交时我们需要将 JSON解析成 7个字段进行存储。
- 在获取表单数据时,我们需要将这七个字段合成一个JSON,方便前端控件显示。
在后端我们也是使用组件对应一个策略的方式来解决以上的几个问题。
在后台我们增加了一个类:
AddressAttrHandler.java
这个类继承了 BaseAttrHandler.java
2.3.1.parseAttrSetting
protected void parseAttrSetting(FormBoAttr field, Element el, JSONObject jsonObject) {
field.setDataType(Column.COLUMN_TYPE_VARCHAR);
field.setLength(100);
}
方法作用:
用来设置控件的BO属性数据,比如地址控件,我们需要设置他的数据库类型为字符串,长度为100个长度。
这个方法参数如下:
参数 | 说明 |
---|---|
field | 字段属性 |
el | 这个表示控件的HTML对象 |
jsonObject | 这个表示控件的元数据属性数据,比如控件类型,控件长度等等 |
2.3.2.getPluginName
返回控件的类型
2.3.3. getDescription
返回控件的描述
2.3.4. getColumns(FormBoAttr attr)
这个方法的作用是返回控件的需要生成数据库的字段。
2.3.5. getFieldEntity(FormBoAttr attr, JSONObject json)
这个方法的作用是在表单插入或者修改时,这个方法用于从表单json数据中,解析出需要插入到数据库的字段。
2.3.6. getValue(FormBoAttr attr, Map<String, Object> rowData, boolean isExternal)
这个方法的作用是将 从数据中查出的数据合并成一个JSON数据,用于前端控件进行显示。
参数说明:
参数 | 备注 |
---|---|
attr | 表示一个BO属性 |
rowData | 从数据库中查出的一行数据 |
isExternal | 是否是外部表 |
3. 总结
在平台中开发一个控件,需要在前端设计器中扩展代码,在后端继承 BaseAttrHandler 类,就可以完成一个控件的开发。