表单中有一个接管明细的子列表,html:

<div class="layui-col-md12">            <div class="layui-card">                <div class="layui-card-header" style="background-color: #e6e6e6">接管明细</div>                <div class="layui-card-body" style="height: 200px;">                    <table class="layui-hide" id="companyPaperRecordDetailListTable" lay-filter="companyPaperRecordDetailListTable"></table>                    <script type="text/html" id="companyPaperRecordDetailListTable-toolbar">                        <div class="layui-btn-container">                            <button class="layui-btn layui-btn-xs" data-type="addRec">增加</button>                        </div>                    </script>                    <script type="text/html" id="companyPaperRecordDetailListTable-bar">                        <a class="layui-btn layui-btn-xs" lay-event="editRec">编辑</a>                        <button class="layui-btn layui-btn-xs layui-btn-danger" lay-event="delRec">删除</button>                    </script>                </div>            </div>        </div>

js :

var detailList = [];        var detailTable = table.render({            elem:'#companyPaperRecordDetailListTable'            ,data:detailList            ,cellMinWidth: 80            ,toolbar: '#companyPaperRecordDetailListTable-toolbar'            ,defaultToolbar: []            ,cols: [[                ,{field:'licenceName', title: '证照名称', align: 'center',minWidth:150 }                ,{field:'certType', title: '证件类型', align: 'center',width:130,templet:tplCertType}                ,{field:'cnt', title: '数量', align: 'center',width:130}                ,{field:'attachment', title: '附件', align: 'center',width:160,templet:tplAttachment }                ,{title:'操作', toolbar: '#companyPaperRecordDetailListTable-bar', width:150}            ]]            ,height: '200'            ,done: function(res, curr, count){            }        });

监听表格事件:

table.on('tool(companyPaperRecordDetailListTable)', function(obj){            switch(obj.event){                case 'editRec':                    active.editRec(obj);                    break;                case 'showRec':                    active.showRec(obj);                    break;                case 'delRec':                    active.delRec(obj);                    break;            }        });

对应的事件:

 var active = {                        getSubData:function () {                var cnt  = 0;                $.each(detailList,function (index,item) {                    cnt+=parseInt(item.cnt);                })                return {attachment:attachmentList.join(","),detailJson:JSON.stringify(detailList),detailLen:detailList.length,cnt:cnt}            },            addRec: function(){                window.formData = {};                var dialog = layer.open({                    type: 2                    ,title: '接管明细'                    ,content: 'companyPaperRecordDetailForm.jsp'                    ,maxmin: true                    ,area: ['95%','95%']                    ,offset:'t'                    ,btn: ['确定', '勾销']                    ,btnAlign: 'c'                    ,yes: function(index, layero){                        var iframeWindow = window['layui-layer-iframe'+ index]                            ,submit = layero.find('iframe').contents().find("#companyPaperRecordDetailForm-submit");                        iframeWindow.layui.form.on('submit(companyPaperRecordDetailForm-submit)', function(data){                            var field = data.field;                            var certType = field.certType;                            try{                                var subAttachment = window._active.getDetailAttachment();                                if(certType==2){                                    if(!subAttachment){                                        return layer.msg('电子档要上传附件');                                    }                                }                                if(subAttachment){                                    field = $.extend(field,subAttachment);                                }                            }catch (err){ }                            detailList.push(field);                            detailTable.reload({data:detailList});                            layer.close(index);                        });                        submit.trigger('click');                    }                });//                layer.full(dialog)            },            editRec:function(obj){                var rowIndex = obj.tr.data('index');                var rec = obj.data;                window.formData = rec;                var dialog = layer.open({                    type: 2                    ,title: '接管明细'                    ,content: 'companyPaperRecordDetailForm.jsp'                    ,maxmin: true                    ,area: ['95%','95%']                    ,offset:'t'                    ,btn: ['确定', '勾销']                    ,btnAlign: 'c'                    ,yes: function(index, layero){                        var iframeWindow = window['layui-layer-iframe'+ index]                            ,submit = layero.find('iframe').contents().find("#companyPaperRecordDetailForm-submit");                        iframeWindow.layui.form.on('submit(companyPaperRecordDetailForm-submit)', function(data){                            var field = data.field;                            var certType = field.certType;                            try{                                var subAttachment = window._active.getDetailAttachment();                                if(certType==2){                                    if(!subAttachment){                                        return layer.msg('电子档要上传附件');                                    }                                }                                if(subAttachment){                                    field = $.extend(field,subAttachment);                                }                            }catch (err){ }                            obj.update($.extend({},field));                            detailList = detailList.map(function (_item,_index) {                                if(_index==rowIndex){                                    _item = $.extend({},field);                                }                                return _item;                            })                            layer.close(index);                        });                        submit.trigger('click');                    }                });//                layer.full(dialog)            },            delRec:function (obj) {                var rowIndex = obj.tr.data('index');                obj.del();                detailList.splice(rowIndex,1);                active.setDataList();            },            reload: function(){                detailTable.reload();            },        };

页面相干按钮事件:

$("body").on('click','.layui-btn-container .layui-btn', function(){            var type = $(this).data('type');            active[type] ? active[type].call(this) : '';        });

子表单编辑页面内容:

<%@ page contentType="text/html;charset=UTF-8" language="java" %><%@ include file="/common/taglibs.jsp"%><%@taglib prefix="shiro" uri="http://shiro.apache.org/tags"%><!DOCTYPE html><html ><head>    <meta charset="utf-8">    <title>公司证照记录明细</title>    <meta name="renderer" content="webkit">    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">    <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=0">    <link rel="stylesheet" href="${ctxLayui}/layuiadmin/layui/css/layui.css" media="all">    <link rel="stylesheet" href="${ctxLayui}/layuiadmin/style/myStyle.css" media="all"></head><body><div class="layui-form" lay-filter="companyPaperRecordDetailForm" id="companyPaperRecordDetailForm" style="padding: 20px 10px 0 0;">    <div class="layui-form-item layui-form-item-45" >        <label class="layui-form-label">证照名称<span style="color:red">*</span></label>        <div class="layui-input-block">            <div id="licenceSel"></div>            <input type="hidden" name="licenceId">            <input type="hidden" name="licenceName">        </div>    </div>    <div class="layui-form-item layui-form-item-45" >        <label class="layui-form-label">证件类型<span style="color:red">*</span></label>        <div class="layui-input-block">            <select name="certType" lay-verify="required" id="certType" lay-filter="certType">            </select>        </div>    </div>    <div class="layui-form-item layui-form-item-45" >        <label class="layui-form-label">数量<span style="color:red">*</span></label>        <div class="layui-input-block">            <input type="text" name="cnt" lay-verify="v_number|required" placeholder="" autocomplete="off" class="layui-input">        </div>    </div>    <div class="layui-form-item  layui-form-item-90" >        <label class="layui-form-label">附件</label>        <div class="layui-input-block">            <%--<input type="text" name="attachment"  placeholder="" autocomplete="off" class="layui-input">--%>            <div class="layui-upload">                <button type="button" class="layui-btn layui-btn-sm layui-btn-normal" id="attachment-upload">上传图片</button>                <div class="layui-upload-list">                    <table class="layui-table">                        <thead>                        <tr><th>文件名</th>                            <th>状态</th>                            <th>操作</th>                        </tr></thead>                        <tbody id="attachmentList"></tbody>                    </table>                </div>            </div>        </div>    </div>    <div class="layui-form-item layui-hide">        <input type="button" lay-submit lay-filter="companyPaperRecordDetailForm-submit" id="companyPaperRecordDetailForm-submit" value="增加">    </div></div><script src="${ctxLayui}/layuiadmin/layui/layui.js"></script><script>    layui.config({        base: '${ctxLayui}/layuiadmin/'    }).extend({        index: 'lib/index'    }).use(['index', 'form','dict','laydate','util','xmSelect','upload'], function(){        var $ = layui.$ ,form = layui.form;        var dict = layui.dict;        var laydate = layui.laydate;        var util = layui.util;        var admin = layui.admin;        var xmSelect = layui.xmSelect;        var upload = layui.upload;        var formData = window.parent.formData;        if(formData){            form.val("companyPaperRecordDetailForm",$.extend({},formData))        }        dict.setSelect("certType","company_paper_certType",formData?formData.certType:1);        form.verify({            v_number:admin.v_number,        });        var url = ctx+'/base/licence/queryByAll'        var licenceData = [];        var rtnLicence = admin.syncReq(url,{parentId:0});        if(rtnLicence.code==0){            licenceData = rtnLicence.data;        }        //===================start ============        var licenceXmSelect = xmSelect.render({            el: '#licenceSel',            autoRow: true,            filterable: true,            remoteSearch:true,            remoteMethod:function (val,cb,show) {                if(val){                    var rtnSearch = admin.syncReq(url,{name:val,sqlWhere:' and parentId!=0 '});                    cb(rtnSearch.data)                }else{                    cb([])                }            },            tree: {                show: true,                showFolderIcon: true,                showLine: true,                indent: 20,                expandedKeys: [],                strict: false,                lazy: true,                load:function (item,cb) {                    if(item.parentId!=0){                        cb([])                    }else{                        if(!item.children || item.children.length==0){                            var _rtn=admin.syncReq(url,{parentId:item.id});                            if(_rtn.data && _rtn.data.length>0){                                var children = _rtn.data;                                $.each(children,function (index,_item) {                                    _item.children = null;                                    var _parent = {name:item.name,id:item.id}                                    if(item.parent){                                        _parent = $.extend(_parent,{parent:item.parent});                                    }                                    _item = $.extend(_item,{ parent:_parent });                                })                                cb(children);                            }                        }else{                            cb([])                        }                    }                }            },            prop:{                name:'name',                value:'id'            },            height: '350px',            radio:true,            clickClose:true,            data(){                return licenceData;            },            show:function () {                licenceXmSelect.update();            },            on:function (data) {                var arr = data.arr;                if(arr && arr.length>0){                    var node = arr[0];                    /*if(node.parentId!=0){                        licenceXmSelect.closed();                    }else{                    }*/                    var parentId  = node.parentId;                    if(parentId!=0){                        form.val('companyPaperRecordDetailForm',{                            licenceName:node.name,                            licenceId:node.id,                        });                    }                }            }        });        var licenceId = formData?(formData.licenceId?formData.licenceId:null):null;        if(licenceId){            var _rtn=admin.syncReq(ctx+'/base/licence/queryById',{id:licenceId});            var selRec = _rtn.data;            if(selRec && selRec.parentId!=0){                var rtn1 = admin.syncReq(url,{parentId:selRec.parentId});                var children = rtn1.data;                $.each(licenceData,function (index,item) {                    if(item.id==selRec.parentId){                        item.children = children;                        return false;                    }                })            }            licenceXmSelect.reset();            licenceXmSelect.setValue([licenceId])        }else{            licenceXmSelect.update();        }        //=======================end==================        var attachment = formData.attachment;        var attachmentList = [];        var attachmentListView = $('#attachmentList')        var uploadListIns = upload.render({            elem: '#attachment-upload'            ,url: ctx+'/upload/uploadImages'            ,accept: 'images'            ,acceptMime: 'image/*'            ,exts: 'jpg|jpeg|png|bmp|gif' //只容许上传压缩文件            ,multiple: true            ,choose: function(obj){                var files = this.files = obj.pushFile(); //将每次抉择的文件追加到文件队列                //读取本地文件                obj.preview(function(index, file, result){                    var tr = $(['<tr id="upload-'+ index +'">'                        ,'<td><a href="#" style="color:#1E9FFF" id="img_open_'+index+'" data-url="">'+ file.name +'</a></td>'                        ,'<td>待上传</td>'                        ,'<td>'                        ,'<button class="layui-btn layui-btn-mini test-upload-demo-reload layui-hide">重传</button>'                        ,'<button class="layui-btn layui-btn-mini layui-btn-danger test-upload-demo-delete">删除</button>'                        ,'</td>'                        ,'</tr>'].join(''));                    //单个重传                    tr.find('.test-upload-demo-reload').on('click', function(){                        obj.upload(index, file);                    });                    tr.find("a#img_open_"+index).on('click',function () {                        var url = $(this).attr("data-url");                        if(url){                            window.open(url);                        }                    })                    //删除                    tr.find('.test-upload-demo-delete').on('click', function(){                        delete files[index]; //删除对应的文件                        tr.remove();                        attachmentList.splice(index,1);                        uploadListIns.config.elem.next()[0].value = ''; //清空 input file 值,免得删除后呈现同名文件不可选                    });                    attachmentListView.append(tr);                });            }            ,done: function(res, index, upload){                if(res.code == 0){ //上传胜利                    var tr = attachmentListView.find('tr#upload-'+ index)                        ,tds = tr.children();                    var attachmentData = res.data;                    tds.eq(0).find("a#img_open_"+index).attr("data-url",attachmentData.url);                    tds.eq(1).html('<span style="color: #5FB878;">已上传</span>');                    tds.eq(2).find('.test-upload-demo-reload').addClass('layui-hide'); //重传操作hide                    attachmentList.push(attachmentData.url);                    return delete this.files[index]; //删除文件队列曾经上传胜利的文件                }                this.error(index, upload);            }            ,error: function(index, upload){                var tr = attachmentListView.find('tr#upload-'+ index)                    ,tds = tr.children();                tds.eq(1).html('<span style="color: #FF5722;">上传失败</span>');                tds.eq(2).find('.test-upload-demo-reload').removeClass('layui-hide'); //显示重传            }        });        var active = {            getDetailAttachment:function () {                return {attachment:(attachmentList&&attachmentList.length>0)?attachmentList.join(","):null}            },            setAttachmentListView:function(_attachmentList){                $.each(_attachmentList,function (index,item) {                    var tr = $(['<tr id="upload-'+ index +'">'                        ,'<td><a style="color:#1E9FFF" href="#" style="color:#1E9FFF" id="img_open_'+index+'" data-url="'+item+'">附件'+(index+1)+'</a></td>'                        ,'<td>已上传</td>'                        ,'<td>'                        ,'<button class="layui-btn layui-btn-mini layui-btn-danger test-upload-demo-delete">删除</button>'                        ,'</td>'                        ,'</tr>'].join(''));                    //单个重传                    tr.find('.test-upload-demo-reload').on('click', function(){                        obj.upload(index, file);                    });                    tr.find("a#img_open_"+index).on('click',function () {                        var url = $(this).attr("data-url");                        if(url){                            window.open(url);                        }                    })                    //删除                    tr.find('.test-upload-demo-delete').on('click', function(){                        tr.remove();                        attachmentList.splice(index,1);                        uploadListIns.config.elem.next()[0].value = '';                    });                    attachmentListView.append(tr);                });//                active.setDataList();            },        }        if(attachment){            $.each(attachment.split(","),function (index,item) {                attachmentList.push(item);            })            active.setAttachmentListView(attachmentList)        }        window.parent._active = active;    })</script></body></html>

主页面增加记录(companyPaperRecordTabList.jsp):

addRec: function(){                window.formData = {companyId:id};                var dialog = layer.open({                    type: 2                    ,title: '公司证照记录'                    ,content: 'companyPaperRecordForm.jsp'                    ,maxmin: true                    ,area: ['95%','95%']                    ,offset:'t'                    ,btn: ['确定', '勾销']                    ,btnAlign: 'c'                    ,yes: function(index, layero){                        var iframeWindow = window['layui-layer-iframe'+ index]                            ,submit = layero.find('iframe').contents().find("#companyPaperRecordForm-submit");                        iframeWindow.layui.form.on('submit(companyPaperRecordForm-submit)', function(data){                            var field = data.field;                            field.companyId = id;                            try{                                var subData = window._active.getSubData();                                if(!subData.detailLen || subData.detailLen==0){                                    return layer.msg('请增加接管明细!')                                }                                var cnt = field.cnt;                                if(cnt!=subData.cnt){                                    return layer.msg('填写的数量和接管明细的数量共计不相等!')                                }                                if(subData){                                    field = $.extend(field,subData);                                }                            }catch (err){}                            var rtn = admin.syncReq(ctx+"/company/companyPaperRecord/add",field);                            if(rtn && rtn.code==0){                                layer.close(index);                                layer.msg('操作胜利');                                setTimeout(function () { active.reload() },0);                            }else{                                layer.msg('操作失败');                            }                        });                        submit.trigger('click');                    }                });//                layer.full(dialog)            },

后盾接管实体类,CompanyPaperRecordPo, 要有一个如下属性:

private String detailJson;public String getDetailJson() {        return detailJson;    }    public void setDetailJson(String detailJson) {        this.detailJson = detailJson;    }

而后将detailJson 转为 对应的实体子列表,并保留:

CommonJsonUtils jsonUtils = new CommonJsonUtils();        String detailJson = po.getDetailJson();        if(StringUtils.isNotEmpty(detailJson)){            List<CompanyPaperRecordDetailPo> detailList = jsonUtils.toBeanList(detailJson, CompanyPaperRecordDetailPo.class);            if(detailList!=null && detailList.size()>0){                for(CompanyPaperRecordDetailPo detail:detailList){                    detail.setRecordId(po.getId());                    detail.setCreateTime(now);                    detail.setModifyTime(now);                    detail.setStatus(1);                    detail.setCompanyId(po.getCompanyId());                    detail.setAgentId(po.getAgentId());                    detail.setBusinessId(po.getBusinessId());                    detail.setId(IdUtils.id());                    result+=savePaper(po,detail,insert);                }                result+=companyPaperRecordDetailMapper.insertByBatch(detailList);            }        }

CommonJsonUtils 工具类,可在我博客其余文章找到:
工具类CommonJsonUtils:json 与 bean的转换