公共的JS组件-告别CURD

  • urls.py

urlpatterns = [
    url('^asset.html$', views.AssetView.as_view()),
    url('^asset-json.html$', views.AssetJsonView.as_view()),
]
  • views.py

# CBV方式
class AssetView(View):
    def get(self,request,*args,**kwargs):
        # 数据库中获取数据
        return render(request, 'asset.html')

class AssetJsonView(View):
    def get(self,request,*args,**kwargs):
        table_config = [
            {
                'q': None,
                'title': '选项',
                'display': True,
                'text': {'content':'<input type="checkbox" />','kwargs': {}},
                'attrs': {},
            },
            {
                'q':'id',
                'title':'ID',
                'display':False,
                'text':{},
                'attrs':{},
             },
            {
                'q': 'asset_type_id',
                'title': '资产类型',
                'display': True,  # 是否显示
                'text': {'content': '{n}', 'kwargs': {'n': '@@asset_type_choices', }},
                'attrs': {},
            },
            {                   # 'edit-type': 'select'可编辑时变成下拉框
                'q': 'status_id',
                'title': '状态',
                'display': True,  # 是否显示
                'text': {'content': '{n}', 'kwargs': {'n': '@@status_choices',}},# 双@表示找选项里对应的内容
                'attrs': {'name':'status_id','origin':'@status_id','edit-enable': 'true', 'edit-type': 'select','global-name':'status_choices'},
            },
            {
                'q': 'idc__id',
                'title': '机房ID',
                'display': False,
                'text': {},
                'attrs': {},
            },
            {
                'q': 'idc__name',  # 一对多跨表操作
                'title': '机房',
                'display': True,  # 是否显示
                'text': {'content': '{n}', 'kwargs': {'n': '@idc__name', }},# 一个@表示取数据库中的信息
                'attrs': {'name':'idc_id','origin':'@idc__id','edit-enable': 'true', 'edit-type': 'select','global-name':'idc_choices'},
            },
            {
                'q': 'cabinet_num',
                'title': '机柜号',
                'display': True,
                'text': {'content':'{n}','kwargs':{'n':'@cabinet_num'}},
                'attrs': {'name':'cabinet_num','origin':'@cabinet_num','edit-enable': 'true', 'edit-type': 'input'},
            },
            {
                'q': 'cabinet_order',
                'title': '机柜位置',
                'display': True,
                'text': {'content': '{n}', 'kwargs': {'n': '@cabinet_order'}},
                'attrs': {},
            },
            {
                'q': None,    # 表示不去数据库取数据
                'title': '操作',
                'display': True,
                'text': {'content': '<a href="/asset_detail-{m}.html">{n}</a>', 'kwargs': {'m':'@id','n':'详细'}},
                'attrs': {},
            },
        ]
        q_list = []
        for i in table_config:
            if not i['q']:
                continue
            q_list.append(i['q'])
        data_list = Asset.objects.all().values(*q_list)
        data_list = list(data_list)
        print(data_list) # [{'id': 1, 'cabinet_num': '12B', 'cabinet_order': '1'}]
        result = {
                'table_config':table_config,
                'data_list':data_list,
                'pager':'''
                        <li><a href="#">1</a></li>
                        <li><a href="#">2</a></li>
                        <li><a href="#">3</a></li>
                        <li><a href="#">4</a></li>
                        <li><a href="#">5</a></li>
                        ''',
                'global_dict':{
                    'asset_type_choices': Asset.asset_type_choices,  # json处理之后,元组会变成列表
                    'status_choices': Asset.status_choices,
                    'idc_choices': list(IDC.objects.values_list('id','name')),
                },
            }
        return HttpResponse(json.dumps(result))


    def put(self,request,*args,**kwargs):
        # 没有request.post
        content = request.body
        val = json.loads(str(content,encoding='utf-8'))
        ret = {'status':True}
        return HttpResponse(json.dumps(ret))
  • html文件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>后台管理</title>
    {% load staticfiles %}
    <link rel="stylesheet" href="{% static 'plugins/bootstrap/css/bootstrap.css' %}"/>
    <link rel="stylesheet" href="{% static 'plugins/font-awesome/css/font-awesome.css' %}"/>
</head>
<body>
<div style="width: 1000px;margin: 0 auto;">
    <h1>资产列表</h1>
    <div class="btn-group" role="group" aria-label="...">
        <button id="idCheckAll" type="button" class="btn btn-default">全选</button>
        <button id="idReverseAll" type="button" class="btn btn-default">反选</button>
        <button id="idCancelAll" type="button" class="btn btn-default">取消</button>
        <button id="idEditMode" type="button" class="btn btn-default">进入编辑模式</button>
        <button type="button" class="btn btn-default">批量删除</button>
        <a id="idAdd" href="asset_add.html" class="btn btn-default">添加</a>
        <button id="idSave" type="button" class="btn btn-default">保存</button>
    </div>
    <table class="table table-bordered">
        <thead id="table_th">
        </thead>
        <tbody id="table_tb">
        </tbody>
    </table>
    <ul id="idPagination" class="pagination">
    </ul>
</div>
<script src="{% static 'js/jquery-3.3.1.js' %}"></script>
<script src="{% static 'js/nbList.js' %}"></script>
<script>
    $(function () {
        $.NB('/asset-json.html');
    });
</script>
</body>
</html>
  • 公共JS组件:主要是调用扩展方法NB

(function () {
    var requestUrl = null;

    //绑定分页事件
    function bindChangePager(){
        $('#idPagination').on('click','a',function () {
            var pageNum = $(this).text();
            init(pageNum);
        })
    }

    //保存
    function bindSave() {
        $('#idSave').click(function () {
            //找到有hasEdit属性的tr标签
            var postList = [];
            $('#table_tb').find('tr[has-edit="true"]').each(function () {
                //$(this)=tr
                var temp = {
                    /*
                    'id':1,
                    'status':1,
                    'order':12,*/
                };
                temp['id'] = $(this).attr('row-id');
                $(this).children('[edit-enable="true"]').each(function () {
                    //$(this)=td
                    var name = $(this).attr('name');  //'name':'cabinet_num'
                    var origin = $(this).attr('origin');
                    var newVal = $(this).attr('new-val');
                    if(origin != newVal){
                        temp[name] = newVal; //'idc_id':2  新的select的value
                    }
                });
                postList.push(temp);
            });
            $.ajax({
                url:requestUrl,
                type:'PUT',
                data:{'post_list':JSON.stringify(postList)},
                dataType: 'JSON',
                success:function (arg) {
                    if(arg.status){
                        init(1); //初始化到第一页
                    }else{
                        alert(arg.error);
                    }
                }
            })
        })
    }

    //全选
    function bindCheckAll() {
        $('#idCheckAll').click(function () {
            $('#table_tb').find(':checkbox').each(function () {
                if($('#idEditMode').hasClass('btn-warning')){
                    if($(this).prop('checked')){
                        //如果当前行已经进入了编辑模式
                    }else{
                        trIntoEditMode($currentTr = $(this).parent().parent());
                        $(this).prop('checked',true);
                    }
                }else{
                    $(this).prop('checked',true);
                }
            })
        })
    }

    //取消
    function bindCancelAll() {
        $('#idCancelAll').click(function () {
            $('#table_tb').find(':checked').each(function () {
                if($('#idEditMode').hasClass('btn-warning')){
                    $(this).prop('checked',false);
                    //取消选中,并退出编辑模式
                    trOutEditMode($(this).parent().parent());
                }else{
                    $(this).prop('checked',false);
                }
            });
        })
    }

    //反选
    function bindReverseAll() {
        $('#idReverseAll').click(function () {
            $('#table_tb').find(':checkbox').each(function () {
                if($('#idEditMode').hasClass('btn-warning')){
                    if($(this).prop('checked')){
                        //如果已经进入编辑模式,选中的要取消,再退出编辑
                        $(this).prop('checked',false);
                        trOutEditMode($(this).parent().parent());
                    }else{
                        //如果已经进入编辑模式,未选中的要选中,再进入编辑
                        $(this).prop('checked',true);
                        trIntoEditMode($(this).parent().parent());
                    }
                }else{
                    if($(this).prop('checked')){
                        $(this).prop('checked',false);
                    }else{
                        $(this).prop('checked',true);
                    }
                }
            })
        })
    }

    //点击进入或退出编辑模式
    function bindEditMode(){
        $('#idEditMode').click(function () {
            if($(this).hasClass('btn-warning')){
                //退出编辑模式
                $(this).removeClass('btn-warning');
                $(this).text('进入编辑模式');
                //找到所有选中的tr,进入编辑模式
                $('#table_tb').find(':checked').each(function () {
                    var $currentTr = $(this).parent().parent();
                    trOutEditMode($currentTr);
                })
            }else{
                //进入编辑模式
                $(this).addClass('btn-warning');
                $(this).text('退出编辑模式');
                //找到所有选中的tr,退出编辑模式
                $('#table_tb').find(':checked').each(function () {
                    var $currentTr = $(this).parent().parent();
                    trIntoEditMode($currentTr);
                })
            }
        })
    }

    //委托绑定:如果用ajax在页面上添加了一行数据,会自动绑定这个事件
    function bindCheckbox(){
        $('#table_tb').on('click',':checkbox',function () {
            if($('#idEditMode').hasClass('btn-warning')){
                var ck = $(this).prop('checked');
                var $currentTr = $(this).parent().parent(); //变量前带$的表示为jQuery对象,只是自己看着方便
                if(ck){
                    //选中状态,进入编辑,给tr加上背景色
                    trIntoEditMode($currentTr);
                }else{
                    trOutEditMode($currentTr);
                }
            }
        })
    }

    //选中,进入编辑模式
    function trIntoEditMode($tr){
        $tr.addClass('success');
        $tr.attr('has-edit','true');  // 只要进入过编辑状态的,都加上这个属性
        $tr.children().each(function () {
            //$(this)就是tr的每一个孩子td
            var editEnable = $(this).attr('edit-enable'); //检查当前是否是可编辑模式
            var editType = $(this).attr('edit-type');
            if(editEnable == 'true'){
                //可以进入编辑模式
                if(editType == 'select'){
                    //生成下拉框
                    var globalName = $(this).attr('global-name'); //global-name = status_choices
                    var origin = $(this).attr('origin'); //1
                    //生成select标签
                    var selectTag = document.createElement('select');
                    selectTag.className = 'form-control';
                    $.each(window[globalName],function (k1,v1) {
                        var optionTag = document.createElement('option');
                        optionTag.setAttribute('value',v1[0]);
                        optionTag.innerHTML = v1[1];
                        $(selectTag).append(optionTag);
                    });
                    $(selectTag).val(origin);
                    $(this).html(selectTag);
                }else if(editType == 'input'){
                    //生成input框
                    var innerText = $(this).text();
                    var tag = document.createElement('input');
                    tag.className = 'form-control';
                    tag.style.width = '100%';
                    tag.value = innerText;
                    $(this).html(tag);
                }
            }
        })
    }

    //取消选中,退出编辑模式
    function trOutEditMode($tr){
        $tr.removeClass('success');
        $tr.children().each(function () {
            //$(this)就是tr的每一个孩子td
            var editEnable = $(this).attr('edit-enable'); //检查当前是否可编辑
            var editType = $(this).attr('edit-type');
            if(editEnable == 'true'){
                //如果是可编辑的
                if(editType == 'select'){
                    //如果是select框
                    var $select = $(this).children().first(); //jQuery对象
                    var newId = $select.val(); //选中的option的id
                    var newText = $select[0].selectedOptions[0].innerHTML;//选中的option的text
                    $(this).html(newText);  //用文本替换原来的select框
                    $(this).attr('new-val',newId); //设置新的value值
                }else{
                    var inputVal = $(this).children().first().val(); //获取input的值
                    $(this).html(inputVal);
                    $(this).attr('new-val',inputVal);
                }
            }
        })
    }

    //自定义string方法,字符串格式化
    String.prototype.format = function (kwargs) {
        return this.replace(/\{(\w+)\}/g,function (km,m) {
            return kwargs[m];
        })
    };

    //初始化
    function init(pager) {
        $.ajax({
            url:requestUrl,
            type:'GET',
            data:{pager:pager},  //把请求的页码告诉后台
            dataType:'JSON',
            success:function (result) {
                initGlobalData(result.global_dict);
                initHeader(result.table_config);
                initBody(result.table_config,result.data_list);
                initPager(result.pager);
            }
        })
    }
    
    //初始化分页
    function initPager(pager) {
        $('#idPagination').html(pager);
    }
    
    //初始化表头生成<tr><th>ID</th></tr>
    var tr = document.createElement('tr');
    function initHeader(table_config) {
        $('#table_th').empty();  ////先清空所有的tr,再添加tr
        $.each(table_config,function (k,item) {
            //k是列表索引,item是字典
            if(item.display){
                th = document.createElement('th');
                th.innerHTML=item.title;
                $(tr).append(th);
            }
        });
        console.log(tr);
        $('#table_th').append(tr);
    }

    //初始化tbody内容
    function initBody(table_config,data_list) {
        $('#table_tb').empty();  //先清空,再添加
        $.each(data_list,function (k,row) {
            //row={'id': 1, 'cabinet_num': '12B', 'cabinet_order': '1'}
            var tr = document.createElement('tr');
            tr.setAttribute('row-id',row['id']); //生成tr标签时,就把行ID传给它,日后更新时根据这个ID更新
            $.each(table_config,function (i,colConfig) {
                /*{
                    'q': 'cabinet_num',
                    'title': '机柜号',
                    'display': True,
                    'text': {'content':'{n}-{m}','kwargs':{'n':'机柜','m':'@xx'}},
                    'sttrs': {'edit-enable': 'true', 'edit-type': 'select'}
                }*/
                if(colConfig.display){
                    var td = document.createElement('td');
                    //table_config.text={'content': '{n}-{m}', 'kwargs': {'n': '机柜', 'm': '@xx'}},
                    //colConfig.q是数据库中的字段名
                    //生成td的文本信息
                    var kwargs = {};
                    $.each(colConfig.text.kwargs,function (key,value) {
                        if(value.substring(0,2) == '@@'){
                            //两个@@开头的,把选项ID转换成内容
                            var globalName = value.substring(2,value.length);//全局变量的名称
                            var currentId = row[colConfig.q];  //获取的数据库中存储的数字类型值
                            var t = getText(globalName,currentId); //根据ID去全局变量中找对应内容
                            kwargs[key] = t;
                        }else if(value[0]=='@'){
                            //以@开头的就只取@后面的字段的值
                            kwargs[key] = row[value.substring(1,value.length)];
                        }else {
                            kwargs[key] = value;
                        }
                    });
                    var temp = colConfig.text.content.format(kwargs);
                    td.innerHTML = temp;
                    //设置td的属性colConfig.attrs = {'origin':'@status_id','edit-enable': 'true', 'edit-type': 'select'},
                    $.each(colConfig.attrs,function (kk,vv) {
                        if(vv[0] == '@'){       //vv=@status_id
                            td.setAttribute(kk,row[vv.substring(1,vv.length)]);//origin=1
                        }else{
                            td.setAttribute(kk,vv);
                        }
                    });
                    tr.append(td);
                }
            });
            $('#table_tb').append(tr);
        });
    }

    //设置全局变量,初始化下拉框里的选择项
    function initGlobalData(global_dict) {
        $.each(global_dict,function (k,v) {
            //设置全局变量
            window[k] = v;
        })
    }

    //根据ID获取全局变量里对应内容
    var ret = null;
    function getText(globalName,currentId) {
        //globalName='asset_type_choices'
        //currentId=1
        $.each(window[globalName],function (k,item) {
            if(currentId == item[0]){
                ret = item[1];
                return
            }
        });
        return ret;
    }

    //扩展方法
    jQuery.extend({
        'NB':function (url) {
            requestUrl = url;
            init();
            bindEditMode();
            bindCheckbox();
            bindCheckAll();
            bindCancelAll();
            bindReverseAll();
            bindSave();
            bindChangePager();
        },
        'changePager':function (num) {
            init(num);
        }
    });
})();

 

posted @ 2019-03-22 21:47  Charlie大夫  阅读(586)  评论(0编辑  收藏  举报