背景:接了一个老项目,SSM2.0框架,业务表单有大量字段,包括输入框、下拉框、时间选择框、文本区域和图片字段(包括图片名、上传、下载、删除、查看按钮)
需求:用户填完表单后可以复制当前表单,复制的表单继承原表单的所有内容并可以任意修改,不同表单之间可以任意切换,彼此独立,可以保存,保存退出重新打开可以复现
实现:核心思路是直接复制修改原表单html代码的方式实现表单的复用。实在不熟悉js,写的很潦草。
1、复用
(1)使用nthTab插件取原表单做0号表单
var nthTabs;
nthTabs = $("#editor-tabs").nthTabs();
nthTabs.addTab({
id:'0',
title:'表单名称0',
content:$("#formModel").html(),
allowClose:false,
}).setActTab("#0");
//用完删掉
$("#formModel").remove();
(2)新增和删除尾页按钮
<div class="form-actions">
<input class="btn btn-primary " type="button"value="新增" onclick="addTab();"/>
<input class="btn btn-primary " type="button"value="删除尾页" onclick="deleteAddedTab();"/>
</div>
(3)addTab(),复制当前表单
前端:
//表单复用,新增表单
function addTab(){
//最多复用10个表单
if (num < 10){
parent.$.jBox.confirm("确定复用表单吗?", '系统提示', function (v, h, f) {
if (v == 'ok') {
$('.form-actions .btn').attr('disabled', true);
var id = nthTabs.getActiveId();
console.log("当前选项卡id: "+id)
num++;
//调用addTab()方法,处理数据,存入数据库(del_flag = 1)
$.post("${ctx}/xxx/xxx/addTab",
$("#inputForm"+id).serialize(), function (result) {
if (result.code == 200) {
nthTabs.addTab({
id:num,
title:'表单名称'+num,
//根据当前tab页的id生成新tab,更新表单id,主tab页id为 inputForm0
content:$('#'+id).html().replaceAll('inputForm'+id,'inputForm'+num),
allowClose:false
})
nthTabs.setActTab("#"+num);
//是否为新增数据
$('#inputForm'+num+' input[name="manuallyAdd"]').remove()
//为空则为原始表单,不为空为新增tab
$('#inputForm'+num+' input[name="inputFormId"]').remove()
//后台生成的新增表单id
$('#inputForm'+num+' input[name="newId"]').remove()
//inputFormCode
$('#inputForm'+num+' input[name="inputFormCode"]').remove()
var input02 = "<input style='display: none' name='manuallyAdd' value='1'/>";
var input03 = "<input style='display: none' name='inputFormId' value='"+num+"' />";
var input04 = "<input style='display: none' name='newId' value='"+result.data.newId+"'/>";
var inputFormCode = 'inputFormCode'+num;
var input05 = "<input style='display: none' id='"+inputFormCode+"' name='inputFormCode' value='' type='hidden' />";
$("#inputForm"+(num)).append(input02).append(input03).append(input04).append(input05);
//初始化下拉框
$('select').select2();
// 删除复用tab页中直接复制来的冗余下拉框
$("#inputForm"+num+" .myselect div:nth-child(1)").remove();
// 编辑复用tab页中文本框内容时改变代码value
$("#inputForm"+num+" input[type='text']" ).bind( 'input propertychange' , function (){
$(this).attr("value",$(this).val())
})
// 绑定文本区域的值,表单复用后能继承当前tab中文本区域中的值
$("#inputForm"+num+" textarea" ).bind( 'input propertychange' , function (){
// $(this).attr("text",$(this).val())
$(this).text($(this).val())
})
// 上传图片按钮维护
$("#inputForm"+num+" .up-img").each(function (){
let str = $(this).attr("onclick")
// console.log("原始str:"+str)
let startIndex = str .lastIndexOf("('")
let endIndex = str.lastIndexOf("',")
// console.log("开始下标:"+startIndex)
// console.log("结束下标:"+endIndex)
str = str .substring(startIndex+2,endIndex);
// console.log("截取的id:"+str)
$(this).attr("onclick","imageUploadPage('"+str+"','"+num+"');");
})
// 删除图片按钮维护
$("#inputForm"+num+" .del-img").each(function (){
let str = $(this).attr("onclick")
// console.log("原始str:"+str)
let startIndex = str .lastIndexOf("('")
let endIndex = str.lastIndexOf("',")
// console.log("开始下标:"+startIndex)
// console.log("结束下标:"+endIndex)
str = str .substring(startIndex+2,endIndex);
// console.log("截取的id:"+str)
$(this).attr("onclick","deleteImage('"+str+"','"+num+"');");
})
// 下载图片按钮维护
$("#inputForm"+num+" .download-img").each(function (){
let str = $(this).attr("onclick")
// console.log("原始str:"+str)
let startIndex = str .lastIndexOf("('")
let endIndex = str.lastIndexOf("',")
// console.log("开始下标:"+startIndex)
// console.log("结束下标:"+endIndex)
str = str .substring(startIndex+2,endIndex);
// console.log("截取的id:"+str)
$(this).attr("onclick","imageDownload('"+str+"','"+num+"');");
})
// 查看图片按钮维护
$("#inputForm"+num+" .check-img").each(function (){
let str = $(this).attr("onclick")
let startIndex = str .lastIndexOf("('")
let endIndex = str.lastIndexOf("',")
str = str .substring(startIndex+2,endIndex);
$(this).attr("onclick","viewImage('"+str+"','"+num+"');");
})
//新增之后自动保存
var result = saveCae();
if (result == false){
$('.btn').attr('disabled', false);
parent.$.jBox.tip('表单复用保存失败,请联系管理员');
document.location.reload();
}else {
setTimeout(function () {
// $('.btn').attr('disabled', false);
parent.$.jBox.tip('表单复用成功');
document.location.reload();
}, 1000);
}
} else {
$('.btn').attr('disabled', false);
parent.$.jBox.tip('表单复用新增失败,请联系管理员'+result.message);
}
}, "json");
} else {
return;
}
})
}else {
parent.$.jBox.tip("最多新增10个复用表单!");
}
}
后端:
public void addTab(xxx cae){
//为复用的新增数据获取id
String newId = IdGen.uuid();
String parentCaeFormId0 = cae.getId();
//复制原tab页所有附件复用表单
if (cae.getNewId() == null){ //复用的表单是主表单
caePublicService.copyAllAttachments(cae.getId(), newId);
}else { //复用的表单是复用出来的表单
cae.setId(cae.getNewId()); //设置被复用的服用表单的真实id
caePublicService.copyAllAttachments(cae.getId(), newId);
}
//添加复用数据标记
cae.setIsReuseData("1");
//记录父id,提交校对时根据主表单id来获取所有的复用出来的数据
cae.setParentCaeFormId(parentCaeFormId0);
//记录新id,保存时通过id找到该数据
cae.setId(newId);
cae.setNewId(newId);
//清空复用数据的流程id(否则可能TooManyResultsException)
cae.setProcInstId("");
//修改create_by
cae.setCreator(UserUtils.getUser().getName());
cae.setCreateBy(UserUtils.getUser());
//设置创建时间和更新时间
cae.setUpdateDate(new Date());
cae.setCreateDate(cae.getUpdateDate());
caeStructuralFrameOilpanDao.addTab(cae);
}
坑:下拉框select2组件需要重新初始化;下拉框用的<form:select组件,需要添加监听事件来动态修改html代码中的selected属性位置
//监听所有下拉框选择事件
$(".myselect select").change(function(){
//获取value值
var selectedId=$(this).find("option:selected").val();
$(this).find("option").each(function () {
if ($(this).val() == selectedId) {
$(this).attr("selected", true);
}else {
$(this).attr("selected", false);
}
}
);
});
注意:编辑input、textArea、wdatePicker内容时html代码不会自动更新value值;处理图片上传、删除、下载、查看按钮的相关代码,保证不同表单彼此独立;ajax是异步请求,根据需求可改成同步$.ajaxSettings.async = false
2、保存
for循环所有tab页,主表单正常保存,复用表单需要保存表单代码用来复现,保存时需要转义特殊字符:StringEscapeUtils.unescapeHtml4(cae.getInputFormCode())
3、复现
思路是根据保存的父表单id和页面代码获取复用表单的数量和页面代码,修改num值for循环复现出所有复用表单。下拉框,文本框等需要初始化。
var reuseFormNum = ${caeStructuralFrameOilpan.reuseFormNum};
for (var i = 1; i <= reuseFormNum; i++){
nthTabs.addTab({
id:i,
title:'框架式油底壳'+i,
content:$("#formModel"+i).html(),
allowClose:false
}).setActTab("#"+i)
// 删除复用tab页中直接复制来的冗余下拉框
$("#inputForm"+i+" .myselect div:nth-child(1)").remove();
//删除暂存inputFormCode信息的div
$("#formModel"+i).remove();
}
if (reuseFormNum != '0'){
num = reuseFormNum;
}