Layui(4) 增刪改查 完整案例

鄭清發表於2018-12-24

分享一下最近花了2天時間來做的一個layui前端的CURD,先來看看效果是不是自己想要的吧...    【程式碼放最後了】

因為每天還要上課,所以雖然花了2天時間來弄,但實際上寫的時間比較少,有些功能做的不是很好,還請大佬見諒

可參考layui官方開發文件https://www.layui.com/doc/

以及線上示例https://www.layui.com/demo/ 

layui前端頁面資料展示:已解決資料格式化問題

新增 :有驗證

修改:已做資料回顯

刪除:有單獨點選一個刪除以及批量刪除

高階查詢:

以及一些擴充套件小功能

   


程式碼部分

JSP頁面   

溫馨小提示:引入的js,css等可根據自己的檔案位置修改。

注意 :

layui的資原始檔建議是從官網下載的最新版本 https://www.layui.com/   ,在這裡因為我用的基於layui的X-admin框架去搭建的前端,而框架裡面的layui樣式不是最新版,導致期間出現一些功能不能實現,真的很坑人...

前端資料表格的展示注意後端返回的json資料格式建議必須如下  code,msg,count,data code返回的值不能為空,data裡面裝頁面顯示資料

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%-- 此部分程式碼做如果專案配置執行時有path的時候使用 --%>
<%
    String basePath = request.getScheme() + "://" + request.getServerName() + ":" +     request.getServerPort() + request.getContextPath();
    System.out.println(basePath);
%>
<html>
<head>
    <base href="<%=basePath%>"/>
    <title>選單管理</title>
    <%@ include file="/WEB-INF/views/head.jsp"%>
    <%@ include file="/WEB-INF/views/common.jsp"%>
    <script type="text/javascript" src="/static/js/common.js"></script>
    <script type="text/javascript" src="/static/js/model/menu.js"></script>
    <style>
        body{margin: 10px;}
        .demo-carousel{height: 200px; line-height: 200px; text-align: center;}
    </style>
</head>
<body class="layui-anim layui-anim-up">
    <div class="x-nav">
        <span class="layui-breadcrumb">
    <a href="/main">首頁</a>
    <a href="/main">系統管理</a>
    <a><cite>選單管理</cite></a>
    </span>
        <a class="layui-btn layui-btn-small" style="line-height:1.6em;margin-top:3px;float:right" href="javascript:location.replace(location.href);" title="重新整理">
        <i class="layui-icon" style="line-height:30px">ဂ</i></a>
    </div>

    <div class="x-body">
        <%--<div class="layui-row">
            <form class="layui-form layui-col-md12 x-so">
            <input class="layui-input" placeholder="開始日" name="start" id="start">
            <input class="layui-input" placeholder="截止日" name="end" id="end">
            <input type="text" name="username"  placeholder="請輸入使用者名稱" autocomplete="off" class="layui-input">
            <button class="layui-btn"  lay-submit="" lay-filter="sreach"><i class="layui-icon">&#xe615;</i></button>
            </form>
        </div>--%>
    <div class="layui-row">
        <form class="layui-form layui-col-md12 x-so" id="zq_search">
            選單:<input id="name" type="text" name="name"  placeholder="請輸入選單" autocomplete="off" class="layui-input">
            <button id="search" class="layui-btn"  lay-submit="" lay-filter="search"><i class="layui-icon">&#xe615;</i></button>
        </form>
    </div>

        <table class="layui-hide" id="zq_table" lay-filter="zq_table"></table>

    </div>

    <div class="layui-row" id="zq_formpopbox" style="display:none;position: absolute;
    top: 0; left: 0; bottom: 0; right: 0;">
        <div class="layui-col-md11">
            <form id="zq_form" class="layui-form" action="" style="margin-top: 20px;align:center;">
                <%--隱藏欄位id,區分新增和修改--%>
                <input type="hidden" name="id"/>
                   <%--lay-verify驗證的值:
                    required(必填項),phone(手機號),email(郵箱)
                    url(網址),number(數字),date(日期),identity(身份證)
                    自定義值--%>
                <div class="layui-form-item">
                    <label class="layui-form-label">選單名稱</label>
                    <div class="layui-input-block">
                        <input type="text" name="name" id="name" lay-verify="required" placeholder="請輸入選單名稱" autocomplete="off" class="layui-input">
                    </div>
                </div>
                <div class="layui-form-item">
                    <label class="layui-form-label">選單路徑</label>
                    <div class="layui-input-block">
                        <input type="text" name="url" id="url" lay-verify="" placeholder="請輸入選單路徑" autocomplete="off" class="layui-input">
                    </div>
                </div>
                <div class="layui-form-item">
                    <label class="layui-form-label">選單圖示</label>
                    <div class="layui-input-block">
                        <input type="text" name="icon" lay-verify="" placeholder="請輸入選單圖示" autocomplete="off" class="layui-input">
                    </div>
                </div>
               <div class="layui-form-item">
                    <label class="layui-form-label">選單</label>
                    <div class="layui-input-block">
                        <input type="text" name="parent" lay-verify="" placeholder="請輸入選單" autocomplete="off" class="layui-input">
                    </div>
                </div>
                <div class="layui-form-item">
                    <label class="layui-form-label">子選單</label>
                    <div class="layui-input-block">
                        <input type="text" name="children" lay-verify="" placeholder="請輸入子選單" autocomplete="off" class="layui-input">
                    </div>
                </div>

                <div class="layui-form-item">
                    <div class="layui-input-block">
                        <button class="layui-btn layui-btn-radius layui-btn-normal" lay-submit="" lay-filter="zq_submit" <%--onclick="zq_submit()"--%>>確認</button>
                        <%--<input type="button" class="layui-btn layui-btn-radius layui-btn-normal" value="確認" onclick="zq_submit()" />--%>
                        <button type="reset" class="layui-btn layui-btn-radius layui-btn-primary">重置</button>
                    </div>
                </div>
            </form>
        </div>
    </div>

  <%-- 解決物件格式化問題
    注意:{{d.id}} 是動態內容,它對應資料介面返回的欄位名。除此之外,你還可以讀取到以下額外欄位:
        序號:{{ d.LAY_INDEX }} (該額外欄位為 layui 2.2.0 新增)--%>
    <script type="text/html" id="zq_formatter">
        {{#  if( d.parent != null){ }}
        {{d.parent.name}}
        {{#  }  }}
    </script>


    <%-- 這裡放頭工具欄按鈕 id和table頭的toolbar屬性繫結--%>
    <script type="text/html" id="zq_toolbar">
        <div class="layui-btn-container">
            <button class="layui-btn layui-btn-danger layui-btn-sm" lay-event="delAll"><i class="layui-icon"></i>批量刪除</button>
            <button class="layui-btn layui-btn-sm" lay-event="add"  <%--onclick=""--%>><i class="layui-icon"></i>新增</button>
        </div>
    </script>

    <%-- 這裡放CRUD行工具欄按鈕 id和table行的toolbar屬性繫結--%>
    <script type="text/html" id="zq_bar">
        <a <%--class="layui-btn layui-btn-primary layui-btn-xs"--%> lay-event="detail" title="檢視"><i class="layui-icon">&#xe63c;</i></a>
        <a <%--class="layui-btn layui-btn-xs"--%> lay-event="edit" title="編輯"><i class="layui-icon">&#xe642;</i></a>
        <a <%--class="layui-btn layui-btn-danger layui-btn-xs"--%> lay-event="del" title="刪除"><i class="layui-icon">&#xe640;</i></a>
    </script>

    <!--_footer 作為公共模版分離出去-->
    <%@ include file="/WEB-INF/views/footer.jsp"%>
    </body>
</html>

這裡放一個抽取出來的公共 common.js

//序列化form表單欄位為json物件格式
$.fn.serializeFormToJson = function(){
    var arr = $(this).serializeArray();//form表單資料 name:value
    var param = {};
    $.each(arr,function(i,obj){ //將form表單資料封裝成json物件
        param[obj.name] = obj.value;
    })
    return param;
}

/**
 * 注意:這裡使用了上面的方式,沒有使用這種-------------------------------------------
 * 將form裡面的內容序列化成json
 * 相同的checkbox用分號拼接起來
 * @param {dom} 指定的選擇器
 * @param {obj} 需要拼接在後面的json物件
 * @method serializeJson
 * */
$.fn.serializeJson=function(otherString){
    var serializeObj={},
        array=this.serializeArray();
    $(array).each(function(){
        if(serializeObj[this.name]){
            serializeObj[this.name]+=';'+this.value;
        }else{
            serializeObj[this.name]=this.value;
        }
    });
    if(otherString!=undefined){
        var otherArray = otherString.split(';');
        $(otherArray).each(function(){
            var otherSplitArray = this.split(':');
            serializeObj[otherSplitArray[0]]=otherSplitArray[1];
        });
    }
    return serializeObj;
};

/**
 * 將josn物件賦值給form
 * @param {dom} 指定的選擇器
 * @param {obj} 需要給form賦值的json物件
 * @method serializeJson
 * */
$.fn.setForm = function(jsonValue){
    var obj = this;
    $.each(jsonValue,function(name,ival){
        var $oinput = obj.find("input[name="+name+"]");
        if($oinput.attr("type")=="checkbox"){
            if(ival !== null){
                var checkboxObj = $("[name="+name+"]");
                var checkArray = ival.split(";");
                for(var i=0;i<checkboxObj.length;i++){
                    for(var j=0;j<checkArray.length;j++){
                        if(checkboxObj[i].value == checkArray[j]){
                            checkboxObj[i].click();
                        }
                    }
                }
            }
        }
        else if($oinput.attr("type")=="radio"){
            $oinput.each(function(){
                var radioObj = $("[name="+name+"]");
                for(var i=0;i<radioObj.length;i++){
                    if(radioObj[i].value == ival){
                        radioObj[i].click();
                    }
                }
            });
        }
        else if($oinput.attr("type")=="textarea"){
            obj.find("[name="+name+"]").html(ival);
        }
        else{
            obj.find("[name="+name+"]").val(ival);
        }
    })
}

JSP頁面對應所需js程式碼

$(function () {
    layui.config({
        version: '1545041465480' //為了更新 js 快取,可忽略
    });
    //注意:這裡是資料表格的載入資料,必須寫
    layui.use(['table', 'layer', 'form', 'laypage', 'laydate'], function () {
        var table = layui.table //表格
            ,layer = layui.layer //彈層
            ,form = layui.form //form表單
            ,laypage = layui.laypage //分頁
            ,laydate = layui.laydate;//日期

        //執行一個laydate例項
        laydate.render({
            elem: '#start' //指定元素
        });

        //執行一個laydate例項
        laydate.render({
            elem: '#end' //指定元素
        });

        //執行一個 table 例項
        table.render({
            elem: '#zq_table'
            ,id: 'tableReload'//過載資料表格
            ,url: '/menu/page' //資料介面
            ,toolbar: '#zq_toolbar' //開啟頭工具欄,此處default:顯示預設圖示,可以自定義模板,詳見文件
            ,title: 'xx表'
            ,page: true //開啟分頁
            // ,totalRow: true //開啟合計行
            ,cols: [[ //表頭
                {type: 'checkbox', fixed: 'left'}
                ,{field: 'id', title: 'ID', width:80, sort: true, fixed: 'left', totalRowText: '合計:'} //totalRow:true則代表這列資料要合計
                ,{field: 'name', title: '選單名稱',edit: 'text'}
                ,{field: 'url', title: '選單路徑',  sort: true, totalRow: true,edit: 'text'}
                ,{field: 'icon', title: '選單圖示', sort: true,edit: 'text'}
                ,{field: 'parent', title: '選單', sort: true, totalRow: true,edit: 'text',templet: '#zq_formatter'}
                ,{field: 'children', title: '子選單',edit: 'text'}
                ,{fixed: 'right', width: 165, align:'center', toolbar: '#zq_bar'}
            ]]
        });

        //監聽頭工具欄事件
        table.on('toolbar(zq_table)', function(obj){
            var checkStatus = table.checkStatus(obj.config.id)
                ,data = checkStatus.data; //獲取選中的資料
            //json字串轉換成Json資料 eval("("+jsonStr+")")  /JSON.parse(jsonStr)
            data = eval("("+JSON.stringify(data)+")");
            switch(obj.event){
                case 'delAll':
                    if(data.length === 0){
                        layer.msg('請至少選擇1行', { icon: 2, time: 1500 });
                    }else {
                        layer.alert('您確認要刪除'+data.length+'條資料嗎?', {
                            skin: 'layui-layer-molv' //樣式類名layui-layer-lan或layui-layer-molv  自定義樣式
                            ,closeBtn: 1    // 是否顯示關閉按鈕
                            ,anim: 1 //動畫型別
                            ,btn: ['確定','取消'] //按鈕
                            ,icon: 2    // icon
                            ,yes:function(){
                                // layer.msg('確定', { icon: 1, time: 1500 });
                                for (var i=0;i<data.length;i++){
                                    console.debug("id:======"+data[i].id)
                                    //傳送請求到後臺
                                    $.post("menu/delete", { id: data[i].id }, function (result) {
                                        if (result.code == "1") {//刪除成功,重新整理當前頁表格
                                            // obj.del(); //刪除對應行(tr)的DOM結構,並更新快取
                                            layer.msg(result.msg, { icon: 1, time: 1500 });
                                            // layer.close(index);
                                            $(".layui-laypage-btn").click();//點選分頁重新整理當前頁
                                        }else  if(result.code == "-1"){  //刪除失敗
                                            layer.alert(result.msg, { icon: 2},function () {
                                                $(".layui-laypage-btn").click();
                                                window.location.reload();
                                            });
                                        }
                                    });
                                }
                                /*   //捉到所有被選中的,發非同步進行刪除
                                   layer.msg('刪除成功', {icon: 1});
                                   $(".layui-form-checked").not('.header').parents('tr').remove();*/
                            }
                            ,btn2:function(){
                                layer.msg('好的,暫時不給您刪除。',{ icon: 1, time: 1500 });
                            }
                        });
                    }
                    break;
                case 'add':
                    zq_form('新增選單','url這個值不管','','');
                    //資料回顯
                    // $("#zq_form").setForm({id:data.id,name: data.name, url: data.url,icon:data.icon,parent:data.parent,children:data.children});
                    $("#zq_form").setForm({id:''});
                    break;
            }
        });

        //監聽行工具事件
        table.on('tool(zq_table)', function(obj){ //注:tool 是工具條事件名,zq_table 是 table 原始容器的屬性 lay-filter="對應的值"
            var data = obj.data //獲得當前行資料
                ,layEvent = obj.event; //獲得 lay-event 對應的值(也可以是表頭的 event 引數對應的值)
            var tr = obj.tr; //獲得當前行 tr 的DOM物件
            switch(layEvent){
                case 'detail':
                    //json字串轉換成Json資料 eval("("+jsonStr+")")  /JSON.parse(jsonStr)
                    var jsonstr = JSON.stringify(data);//json資料轉字串  JSON.stringify(obj)
                    layer.alert(jsonstr);
                    break;
                case 'del':
                    layer.confirm('您確定刪除id:'+data.id+'的資料嗎?', function(index){
                        //向服務端傳送刪除指令,在這裡可以使用Ajax非同步
                        $.post("menu/delete", { id: data.id }, function (ret) {
                            if (ret.code == "1") {//刪除成功,重新整理當前頁表格
                                layer.msg(ret.msg, { icon: 1, time: 1500 }, function () {
                                    obj.del(); //刪除對應行(tr)的DOM結構,並更新快取
                                    layer.close(index);
                                    // $(".layui-laypage-btn").click();//點選分頁重新整理當前頁
                                });
                            }else  if(ret.code == "-1"){  //刪除失敗
                                layer.alert(ret.msg, { icon: 2},function () {
                                    layer.close(index);
                                    // $(".layui-laypage-btn").click();
                                    window.location.reload();
                                });
                            }
                        });
                    });
                    break;
                case 'edit':
                    console.debug(data);
                    zq_form('編輯選單','url這個值不管',500,400);
                    //資料回顯
                    $("#zq_form").setForm({id:data.id,name: data.name, url: data.url,icon:data.icon,parent:data.parent,children:data.children});
                    break;
            }
        });

        //監聽單元格編輯   zq_table 對應 <table> 中的 lay-filter="zq_table"       做可編輯表格使用
        table.on('edit(zq_table)', function(obj){
            var value = obj.value //得到修改後的值
                ,data = obj.data //得到所在行所有鍵值
                ,field = obj.field; //得到欄位
            layer.msg('[ID: '+ data.id +'] ' + field + ' 欄位更改為:'+ value);
        });

        /*
        //監聽顯示操作
        form.on('switch(isShow)', function(obj) {
            var t = this;
            layer.tips(t.value + ' ' + t.name + ':' + obj.elem.checked, obj.othis);
        });*/

        //監聽提交 lay-filter="zq_submit"
        form.on('submit(zq_submit)', function(data){
            // console.log(data.elem) //被執行事件的元素DOM物件,一般為button物件
            // console.log(data.form) //被執行提交的form物件,一般在存在form標籤時才會返回
            console.log(data.field) //當前from表單所提交的所有欄位, 名值對形式:{name: value}
            layer.msg(JSON.stringify(data.field));//表格資料序列化
            var formData = data.field;
            var id = formData.id,
                name = formData.name,
                url=formData.url,
                icon=formData.icon,
                parent_id=formData.parent_id;
            $.ajax({
                type: "post",  //資料提交方式(post/get)
                url: "/menu/save",  //提交到的url
                data: {"id":id,"name":name,"url":url,"icon":icon,"parent_id":parent_id},//提交的資料
                dataType: "json",//返回的資料型別格式
                success: function(msg){
                    if (msg.success){  //成功
                        layer.msg(msg.msg, { icon: 1, time: 1500 });
                        table.reload('tableReload');//資料表格過載
                        layer.close(index);//關閉彈出層
                    }else {  //失敗
                        layer.alert(msg.msg, { icon: 2},function () {
                            // $(".layui-laypage-btn").click();//執行分頁重新整理當前頁
                            layer.close(index);
                            // window.location.reload();
                        });
                    }
                }
            });
            return false;//false:阻止表單跳轉  true:表單跳轉
        });

        //監聽提交 lay-filter="search"
        form.on('submit(search)', function(data){
            layer.msg(JSON.stringify(data.field));//表格資料序列化
            var formData = data.field;
            console.debug(formData);
            var name = formData.name,
                url=formData.url,
                icon=formData.icon,
                parent_id=formData.parent_id;
            //資料表格過載
            table.reload('tableReload', {
                page: {
                    curr: 1 //重新從第 1 頁開始
                }
                , where: {//這裡傳參  向後臺
                    name: name,
                    url:url
                }
                , url: '/menu/page'//後臺做模糊搜尋介面路徑
                , method: 'post'
            });
            return false;//false:阻止表單跳轉  true:表單跳轉
        });
    });
});

var index;//layer.open 開啟視窗後的索引,通過layer.close(index)的方法可關閉
//表單彈出層
function zq_form(title,url,w,h){
    if (title == null || title == '') { title=false; };
    if (url == null || url == '') {  };// url="404.html";
    if (w == null || w == '') {  w=($(window).width()*0.9);  };
    if (h == null || h == '') {  h=($(window).height() - 50);  };
    index = layer.open({  //layer提供了5種層型別。可傳入的值有:0(資訊框,預設)1(頁面層)2(iframe層)3(載入層)4(tips層)
        type:1,
        title:title,
        area: ['25%','55%'],//型別:String/Array,預設:'auto'  只有在寬高都定義的時候才不會自適應
        // area: [w+'px', h +'px'],
        fix: false, //不固定
        maxmin: true,//開啟最大化最小化按鈕
        shadeClose: true,//點選陰影處可關閉
        shade:0.4,//背景灰度
        skin: 'layui-layer-rim', //加上邊框
        content:$("#zq_formpopbox").html()
    });
}

後端的程式碼我就不放了,根據自己的需要來吧

相關文章