CMDB,告別數(shù)據(jù)庫的CURD(基于django)

為什么要設(shè)計CMDB粹污?
目標(biāo)是搭建自動化平臺段多,包括裝機(jī),軟件壮吩,平臺进苍,代碼,基礎(chǔ)是資產(chǎn)管理鸭叙,
運(yùn)維平臺觉啊, 首要目的是對資產(chǎn)管理,自動更新數(shù)據(jù)沈贝,記錄變更記錄

相對于
1.Excel表格杠人,麻煩
2.一套系統(tǒng),自動更新數(shù)據(jù)宋下,拿到資產(chǎn)變更記錄

CMDB 是運(yùn)維自動化項目
運(yùn)維管理服務(wù)器嗡善,絕大多數(shù)運(yùn)維人員都不會開發(fā)
運(yùn)維工作:采購服務(wù)器,采購器件

運(yùn)維自動化項目
減少人工干預(yù)杨凑,降低人員成本
- 資產(chǎn)管理
- 操作管理

CMDB -- 存儲基礎(chǔ)信息
- 運(yùn)維自動化基礎(chǔ)
- 資產(chǎn)管理滤奈,,對于資產(chǎn)信息撩满,沒必要實(shí)時更新蜒程,只需要隔一段時間再去取就行了

電腦--裝機(jī)--系統(tǒng)--軟件(環(huán)境),CMDB 工具使得可以快速自動化完成

多個系統(tǒng)部署

公司里指定自動化運(yùn)維時伺帘,先制定規(guī)則昭躺,
規(guī)定,公司的服務(wù)器系統(tǒng)版本伪嫁,內(nèi)核领炫,各個模版,

主機(jī)名不能重復(fù)张咳,
主板的sn號帝洪,每個主機(jī)的主板sn號都是唯一的,
--不過脚猾,如果主機(jī)開啟虛擬機(jī)葱峡,
--虛擬機(jī)的sn號跟主機(jī)是相同的,

java等強(qiáng)類型語言是編譯運(yùn)行的龙助,也就是整個運(yùn)行之前先編譯一遍砰奕,看看哪里有問題,一旦出現(xiàn)問題就會運(yùn)行不起來。
而python是弱類型語言军援,邊解釋邊運(yùn)行仅淑,程序出現(xiàn)問題只會在程序運(yùn)行到那個部分時才報錯,要不然不會報錯胸哥。

對于記錄日志涯竟,日志路徑最好寫成可修改形式的,也就是配置文件內(nèi)烘嘱,
日志不要和程序放在一起昆禽,因?yàn)槿罩疚募兊迷絹碓酱螅筮w移很麻煩

采集資產(chǎn)
--1.agent 形式
--2.ssh 類方式
--3.saltstack 方式

cmdb.png

agent 形式蝇庭,特定:需要agent客戶端

import subprocess
import requests
# pip3 install requests

# ################## 采集數(shù)據(jù) ##################
# result = subprocess.getoutput('ipconfig')
# result正則處理獲取想要數(shù)據(jù)

# 整理資產(chǎn)信息
# data_dict ={
#     'nic': {},
#     'disk':{},
#     'mem':{}
# }

# ##################  發(fā)送數(shù)據(jù) ##################
# requests.post('http://www.127.0.0.1:8000/assets.html',data=data_dict)
# 這里只是簡寫,具體還要完善

ssh 類方式捡硅,特點(diǎn):慢

# 基于paramiko模塊哮内, pip3 install paramiko
import requests
import paramiko

# ################## 獲取今日未采集主機(jī)名 ##################
#result = requests.get('http://www.127.0.0.1:8000/assets.html')
# result = ['c1.com','c2.com']


# ################## 通過paramiko連接遠(yuǎn)程服務(wù)器,執(zhí)行命令 ##################
# 創(chuàng)建SSH對象
ssh = paramiko.SSHClient()
# 允許連接不在know_hosts文件中的主機(jī)
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# 連接服務(wù)器
ssh.connect(hostname='192.168.14.36', port=22, username='wupeiqi', password='123')

# 執(zhí)行命令
# stdin, stdout, stderr = ssh.exec_command('df')

# 獲取命令結(jié)果
# result = stdout.read()

# 關(guān)閉連接
# ssh.close()
# print(result)

# data_dict = {result}

# ##################  發(fā)送數(shù)據(jù) ##################
# requests.post('http://www.127.0.0.1:8000/assets.html',data=data_dict)

saltstack 方式壮韭,很多都在用

我在Centos 7 安裝 saltstack 的過程中北发,發(fā)現(xiàn) rpm 添加不了,可以換一種方式安裝喷屋,
參考:https://blog.csdn.net/wanglei_storage/article/details/50574621

這里下面的只是供參考琳拨,,

# 1. 安裝saltstack
#       rpm --import https://repo.saltstack.com/yum/redhat/6/x86_64/latest/SALTSTACK-GPG-KEY.pub
#
#
"""
        Master: yum install salt-master
       Master準(zhǔn)備:
            a. 配置文件屯曹,監(jiān)聽本機(jī)IP
                vim /etc/salt/master
                interface: 本機(jī)IP地址
            b. 啟動master
                /etc/init.d/salt-master start


        Slave:  yum install salt-minion
        Slave準(zhǔn)備:
            a. 配置文件狱庇,連接那個master
                vim /etc/salt/minion
                master: 遠(yuǎn)程master地址
            b. 啟動slave
                /etc/init.d/salt-minion start

2. 創(chuàng)建關(guān)系
    查看
    Master:salt-key -L
        Accepted Keys:
        Denied Keys:
        Unaccepted Keys:
            c1.com
            c2.com
            c3.com
        Rejected Keys:
    接受
    Master:salt-key -a c1.com
        Accepted Keys:
            c1.com
            c2.com
        Denied Keys:
        Unaccepted Keys:
            c3.com
        Rejected Keys:


3. 執(zhí)行命令
    master:
        salt 'c1.com' cmd.run  'ifconfig'

    import salt.client
    local = salt.client.LocalClient()
    result = local.cmd('c2.salt.com', 'cmd.run', ['ifconfig'])

"""
# ################## 獲取今日未采集主機(jī)名 ##################
#result = requests.get('http://www.127.0.0.1:8000/assets.html')
# result = ['c1.com','c2.com']


# ################## 遠(yuǎn)程服務(wù)器執(zhí)行命令 ##################
# import subprocess
# result = subprocess.getoutput("salt 'c1.com' cmd.run  'ifconfig'")
#
# import salt.client
# local = salt.client.LocalClient()
# result = local.cmd('c2.salt.com', 'cmd.run', ['ifconfig'])


# ##################  發(fā)送數(shù)據(jù) ##################
# requests.post('http://www.127.0.0.1:8000/assets.html',data=data_dict)

鏈接:https://pan.baidu.com/s/1EtOF1t_9sA3Ey6WWJjQNdQ 密碼:snsc




告別數(shù)據(jù)庫的CURD

也就是用這一套模版,就可以實(shí)現(xiàn)各種models的操作恶耽,對各個不同的models密任,可以很快的做出一個增刪改查的頁面出來

CMDB總結(jié):

  1. 三種采集資產(chǎn)方式
    --唯一標(biāo)識
  2. API
    --API驗(yàn)證(tornado源碼,加密cookie+時間限制+訪問記錄)
    --數(shù)據(jù)庫表結(jié)構(gòu)
  3. 后臺管理
    --告別CURD偷俭,公共組件(前端+后端配置)

運(yùn)維自動化項目
減少人工干預(yù)浪讳,降低人員成本
-- 資產(chǎn)管理
-- 操作管理

CMDB
- 運(yùn)維自動化基礎(chǔ)
- 資產(chǎn)管理

功能:
---- Agent或中控機(jī)
---- 字典套字典 =》 數(shù)據(jù)
---- 認(rèn)證API
-------------a. 時間超時
-------------b. 訪問記錄
-------------c. 加密后進(jìn)行比較
====> Tornado:源碼中來了 <====
- API
- 后臺管理(10分鐘完成CURD)
- 對于數(shù)據(jù)庫表數(shù)據(jù)進(jìn)行增刪改查
==》 組件:基本增刪改查 《===

通用的數(shù)據(jù)庫增刪改查的插件,只需要修改config配置列表 涌萤,就可以實(shí)現(xiàn)對各種models的操作

注意:在js文件中淹遵,我沒有寫添加和刪除事件,添加可以另起一個html頁面负溪,需要自定制透揣,刪除只需要傳遞一個id到后臺就行了,笙以,淌实,
保存?zhèn)鬟f到django中的數(shù)據(jù)也需要修改一下,,拆祈,也就是PUT那里恨闪。。放坏。咙咽。

models.py 文件


class Asset(models.Model):
    """
    資產(chǎn)信息表,所有資產(chǎn)公共信息(交換機(jī)淤年,服務(wù)器钧敞,防火墻等)
    """
    device_type_choices = (
        (1, '服務(wù)器'),
        (2, '交換機(jī)'),
        (3, '防火墻'),
    )
    device_status_choices = (
        (1, '上架'),
        (2, '在線'),
        (3, '離線'),
        (4, '下架'),
    )

    device_type_id = models.IntegerField(choices=device_type_choices, default=1)
    device_status_id = models.IntegerField(choices=device_status_choices, default=1)

    cabinet_num = models.CharField('機(jī)柜號', max_length=30, null=True, blank=True)
    cabinet_order = models.CharField('機(jī)柜中序號', max_length=30, null=True, blank=True)

    idc = models.ForeignKey('IDC', verbose_name='IDC機(jī)房', null=True, blank=True,on_delete=models.CASCADE)
    business_unit = models.ForeignKey('BusinessUnit', verbose_name='屬于的業(yè)務(wù)線', null=True, blank=True,on_delete=models.CASCADE)

    tag = models.ManyToManyField('Tag')

    latest_date = models.DateField(null=True)
    create_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        verbose_name_plural = "資產(chǎn)表"

    def __str__(self):
        return "%s-%s-%s" % (self.idc.name, self.cabinet_num, self.cabinet_order)

views.py 文件

from django.shortcuts import render,HttpResponse
from django.views import View
import json

class AssetView(View):

    def get(self,request,*args,**kwargs):
        # 數(shù)據(jù)庫中獲取數(shù)據(jù)
        return render(request,'asset.html')

class AssetJsonView(View):
    def get(self,request,*args,**kwargs):
        # 數(shù)據(jù)庫中獲取數(shù)據(jù)
        table_config = [
            {
                'q': None,
                'title': "選項",
                'display': True,  # content 中的值會賦給td標(biāo)簽
                'text': {'content': "<input type='checkbox' />","kwargs": {}},
                'attrs': {}
            },
            {
                'q': 'id',
                'title': 'ID',
                'display': False,  # 不顯示
                'text':{},
                'attrs': {}
            },
            {
                'q': 'device_type_id', # 這個字段用于去數(shù)據(jù)庫中取值
                'title': '資產(chǎn)類型', # 顯示的字段名
                'display': True,    # 兩個@ 表示去全局變量中取值,@@之后的字符串是全局變量名稱
                'text': {'content': "{n}", 'kwargs': {'n': "@@device_type_choices"}},
                'attrs': {} # attrs 中的數(shù)據(jù)會稱為td的屬性
            },
            {
                'q': 'device_status_id',
                'title': '狀態(tài)',
                'display': True,
                'text': {'content': "{n}", 'kwargs': {'n': "@@device_status_choices"}},
                'attrs': {'name':'device_status_id','origin':"@device_status_id",'edit-enable': 'true', 'edit-type': 'select',"global-name": 'device_status_choices'}
            },
            {
                'q': 'idc__id',
                'title': 'IDC',
                'display': False,
                'text': {},
                'attrs': {}
            },
            {
                'q': 'idc__name',
                'title': 'IDC',
                'display': True, # 一個@ 代表從當(dāng)前的一組數(shù)據(jù)中取值
                '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_order',
                'title': '機(jī)柜位置',
                'display': True,
                'text': {'content': "{n}",'kwargs': {'n': "@cabinet_order"}},
                'attrs': {'name':'cabinet_order','origin':"@cabinet_order",'edit-enable': 'true', 'edit-type': 'input'}
            },
            {
                'q': 'cabinet_num',
                'title': '機(jī)柜號',
                'display': True,
                'text': {'content': "{n}", 'kwargs': {'n': "@cabinet_num"}},
                'attrs': {},
            },
            {
                'q': None,
                'title': '操作',
                'display': True,
                'text': {'content': "<a href='/assetdetail-{m}.html'>{n}</a>", 'kwargs': {'n': '查看詳細(xì)','m': '@id'}},
                'attrs': {},
            }
        ]

        q_list = []
        for i in table_config:  # 去數(shù)據(jù)庫中取值
            if not i['q']:
                continue
            q_list.append(i['q'])

        from repository import models
        # 分頁組件用戶獲取數(shù)據(jù)
        data_list = models.Asset.objects.all().values(*q_list)
        data_list = list(data_list)

        result = {
            'table_config':table_config,
            'data_list':data_list,
            'global_dict': {
                'device_type_choices': models.Asset.device_type_choices,
                'device_status_choices': models.Asset.device_status_choices,
                'idc_choices': list(models.IDC.objects.values_list('id','name'))
            },
            # 分頁組件生成頁碼信息
            'pager': """<li><a>1</a></li><li><a>2</a></li><li><a>3</a></li><li><a>4</a></li><li><a>5</a></li>"""

        }
        return HttpResponse(json.dumps(result))

    def put(self,request,*args,**kwargs):
        content = request.body
        v = json.loads(str(content,encoding='utf-8'))
        print(v)
        ret = {
            'status':True
        }
        return HttpResponse(json.dumps(ret))

所定制的 js麸粮,全部都封裝到里面了溉苛,而我們引用時只需要引入js文件,并傳入url路徑就行了弄诲,而所操作的表格就需要在view中修改了愚战,
文檔中有很多要注意的點(diǎn),留作以后參考

nbList.js 文件


(function () {
        var requestUrl = null;
        function bindChangePager() {
            $('#idPagination').on('click','a',function () {  // 為頁碼綁定點(diǎn)擊事件
                var num = $(this).text(); // 事件為獲取頁碼中l(wèi)i標(biāo)簽的text齐遵,也就是1,2,3,4,5
                init(num);   // 執(zhí)行 init 發(fā)送ajax寂玲,并更新table
            })
        }

        function bindSave() {  // 綁定保存按鈕
            $('#idSave').click(function () {
                var postList = [];
                //找到已經(jīng)編輯過的tr,tr has-edit='true'
                $('#table_tb').find('tr[has-edit="true"]').each(function () {
                    // $(this) => tr
                    var temp = {};
                    var id = $(this).attr('row-id');
                    temp['id'] = id;
                    // 找到編輯過的tr標(biāo)簽梗摇,查找其中修改的值拓哟,原值存放在origin中,修改的值放在new-val
                    $(this).children('[edit-enable="true"]').each(function () {
                        // $(this) = > td
                        var name = $(this).attr('name');
                        var origin = $(this).attr('origin');
                        var newVal = $(this).attr('new-val');
                        if (origin != newVal){  // 修改過的伶授,才發(fā)送到服務(wù)器
                            temp[name] = newVal;
                        }
                    });
                    postList.push(temp);
                });

                $.ajax({
                    url:requestUrl,
                    type: 'PUT',
                    data: {'post_list': JSON.stringify(postList)}, //json 發(fā)送不了字典,得首先格式字符串
                    dataType: 'JSON',
                    success:function (arg) {
                        if(arg.status){
                            init(1);
                        }else{
                            alert(arg.error);
                        }
                    }
                })
            })
        }

        function bindReverseAll() {  // 綁定反選按鈕
            $('#idReverseAll').click(function () {
                $('#table_tb').find(':checkbox').each(function () {
                    // $(this) => checkbox
                    if($('#idEditMode').hasClass('btn-warning')) { // 進(jìn)入編輯模式的狀態(tài)
                        if($(this).prop('checked')){  // 獲取checkbox的狀態(tài)
                            $(this).prop('checked',false);  // 設(shè)定checkbox 為不選中
                            trOutEditMode($(this).parent().parent()); // 必須傳遞tr標(biāo)簽過去
                        }else{
                            $(this).prop('checked',true);
                            trIntoEditMode($(this).parent().parent());
                        }
                    }else{  // 未進(jìn)入編輯模式断序,就只有checkbox的反向選擇了
                        if($(this).prop('checked')){
                            $(this).prop('checked',false);
                        }else{
                            $(this).prop('checked',true);
                        }
                    }
                })
            })
        }

        function bindCancelAll() { // 綁定取消按鈕
            $('#idCancelAll').click(function () {
                $('#table_tb').find(':checked').each(function () { // 找到所有選中的checkbox
                    // $(this) => checkbox ,谎砾,逢倍,使之變?yōu)閒alse
                    if($('#idEditMode').hasClass('btn-warning')){
                        $(this).prop('checked',false);
                        // 退出編輯模式
                        trOutEditMode($(this).parent().parent());
                    }else{
                        $(this).prop('checked',false);
                    }
                });
            })
        }

        function bindCheckAll() {  // 綁定全選按鈕
            $('#idCheckAll').click(function () {
                $('#table_tb').find(':checkbox').each(function () {
                    // $(this)  = checkbox
                    if($('#idEditMode').hasClass('btn-warning')){
                        if($(this).prop('checked')){
                            // 當(dāng)前行已經(jīng)進(jìn)入編輯模式了
                        }else{
                            // 進(jìn)入編輯模式
                            var $currentTr = $(this).parent().parent();
                            trIntoEditMode($currentTr);
                            $(this).prop('checked',true);
                        }
                    }else{
                        $(this).prop('checked',true);
                    }
                })
            })
        }

        function bindEditMode() {  // 綁定進(jìn)入編輯模式按鈕
            $('#idEditMode').click(function () {
                var editing = $(this).hasClass('btn-warning');
                if(editing){
                    // 退出編輯模式
                    $(this).removeClass('btn-warning');
                    $(this).text('進(jìn)入編輯模式');

                    $('#table_tb').find(':checked').each(function () { //找到所有選中的checkbox進(jìn)入編輯模式
                        var $currentTr = $(this).parent().parent();
                        trOutEditMode($currentTr);
                    })

                }else{
                    // 進(jìn)入編輯模式
                    $(this).addClass('btn-warning');
                    $(this).text('退出編輯模式');
                    $('#table_tb').find(':checked').each(function () {  //找到所有選中的checkbox退出編輯模式
                        var $currentTr = $(this).parent().parent();
                        trIntoEditMode($currentTr);
                    })
                }
            })
        }

        function bindCheckbox() {  // 為每一個checkbox綁定事件,這里為了避免之后添加的checkbox沒有點(diǎn)擊事件
            // $('#table_tb').find(':checkbox').click()景图,较雕,(這個程序沒有添加之后的checkbox),采用事件委托的方式綁定事件
            $('#table_tb').on('click',':checkbox',function () {

                if($('#idEditMode').hasClass('btn-warning')){  // 要一直檢測是否進(jìn)入了編輯模式
                    var ck = $(this).prop('checked');
                    var $currentTr = $(this).parent().parent();
                    if(ck){
                        // 進(jìn)入編輯模式
                        trIntoEditMode($currentTr);
                    }else{
                        // 退出編輯模式
                        trOutEditMode($currentTr)
                    }
                }
            })
        }

        function trIntoEditMode($tr) {  // $tr 是tr標(biāo)簽
            $tr.addClass('success');  // success 是顏色效果
            $tr.attr('has-edit','true'); // 設(shè)置編輯過的標(biāo)志
            $tr.children().each(function () {
                // $(this) => td
                var editEnable = $(this).attr('edit-enable');
                var editType = $(this).attr('edit-type');
                if(editEnable=='true'){
                    if(editType == 'select'){  // select 標(biāo)簽挚币,在views中必須要把choice傳遞過來
                        var globalName = $(this).attr('global-name'); //  "device_status_choices"
                        var origin = $(this).attr('origin'); // 1
                        // 生成select標(biāo)簽
                        var sel = document.createElement('select');
                        sel.className = "form-control";
                        $.each(window[globalName],function(k1,v1){
                            var op = document.createElement('option');
                            op.setAttribute('value',v1[0]);
                            op.innerHTML = v1[1];
                            $(sel).append(op);
                        });
                        $(sel).val(origin);  // 這樣可以設(shè)定select的選定值****

                        $(this).html(sel);

                        // 下拉框
                        /*
                        *  <select>
                        *      <option value='1'>在線</option>
                        *      <option value='2'>下線</option>
                        *      <option value='3'>離線</option>
                        *  </select>
                        *
                        * */
                        //  在線


                    }else if(editType == 'input'){
                        // input文本框
                        // *******可以進(jìn)入編輯模式*******
                        var innerText = $(this).text();
                        var tag = document.createElement('input');
                        tag.className = "form-control";
                        tag.value = innerText;
                        $(this).html(tag);
                    }
                }
            })
        }

        function trOutEditMode($tr){  // 退出編輯模式
            $tr.removeClass('success');
            $tr.children().each(function () {
                // $(this) => 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();
                        // 獲取選中的option的value
                        var newId = $select.val();
                        // 獲取選中的option的文本內(nèi)容
                        var newText = $select[0].selectedOptions[0].innerHTML;
                        // 在td中設(shè)置文本內(nèi)容
                        $(this).html(newText);
                        $(this).attr('new-val',newId); // 設(shè)置屬性中更新的值

                    }else if(editType == 'input') {
                        // *******可以退出編輯模式*******
                        var $input = $(this).children().first();
                        var inputValue = $input.val();
                        $(this).html(inputValue);
                        $(this).attr('new-val',inputValue);
                    }

                }
            })
        }

        String.prototype.format = function (kwargs) {  // 自定制的string 的 format 方法
            // this ="laiying: {age} - {gender}";
            // kwargs =  {'age':18,'gender': '女'}
            var ret = this.replace(/\{(\w+)\}/g,function (km,m) {
                return kwargs[m];
            });
            return ret;
        };

        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);  // 添加中views 傳遞過來的頁碼亮蒋,也就是那一堆li標(biāo)簽
        }

        function initHeader(table_config) {
            /*
            table_config = [
                {
                    'q': 'id',
                    'title': 'ID',
                    'display':false
                },
                {
                    'q': 'name',
                    'title': '隨便',
                    'display': true
                }
            ]
             */

             /*
            <tr>
                <th>ID</th>
                <th>用戶名</th>
            </tr>
            */
            var tr = document.createElement('tr');
            $.each(table_config,function (k,item) {
                if(item.display){  // display 的值就是view中傳遞過來,確定是否展示
                    var th = document.createElement('th');
                    th.innerHTML = item.title;
                    $(tr).append(th);
                }

            });
            $('#table_th').empty();  // 添加之前需要先清空之前的值
            $('#table_th').append(tr);
        }

        function initBody(table_config,data_list){  // 添加數(shù)據(jù)妆毕,用鍵值對的方式慎玖,list 列表有序
            $('#table_tb').empty();
            for(var i=0;i<data_list.length;i++){
                var row = data_list[i];
                // row = {'cabinet_num': '12B', 'cabinet_order': '1', 'id': 1},
                var tr = document.createElement('tr');
                tr.setAttribute('row-id',row['id']);
                $.each(table_config,function (i,colConfig) {
                   if(colConfig.display){
                       var td = document.createElement('td');
                       /* 生成文本信息 */
                       var kwargs = {};
                       $.each(colConfig.text.kwargs,function (key,value) {

                           if(value.substring(0,2) == '@@'){  // 兩個@ 代表去全局變量中取值
                               var globalName = value.substring(2,value.length); // 全局變量的名稱
                               var currentId = row[colConfig.q]; // 獲取的數(shù)據(jù)庫中存儲的數(shù)字類型值
                               var t = getTextFromGlobalById(globalName,currentId);
                               kwargs[key] = t;
                           }
                           else if (value[0] == '@'){ // 一個@ 代表從當(dāng)前 的一組數(shù)據(jù)中取值
                                kwargs[key] = row[value.substring(1,value.length)]; //cabinet_num
                           }else{
                                kwargs[key] = value;
                           }
                       });
                       var temp = colConfig.text.content.format(kwargs);  // format 是自定制的string方法
                       td.innerHTML = temp;                               // 格式化字符串,
                                             // 'content': "{n}", 'kwargs': {'n': "@@device_type_choices"}
                                            // 如同上面的字符串笛粘,用kwargs 中的 n 代替 {n}


                       /* 屬性colConfig.attrs = {'edit-enable': 'true','edit-type': 'select'}  */
                        $.each(colConfig.attrs,function (kk,vv) {
                            if(vv[0] == '@'){ //還必須為td設(shè)置屬性趁怔,標(biāo)識
                                td.setAttribute(kk,row[vv.substring(1,vv.length)]);
                            }else{
                                td.setAttribute(kk,vv);
                            }
                        });

                       $(tr).append(td);
                   }
                });

                $('#table_tb').append(tr);
            }
        }

        function initGlobalData(global_dict) {
            $.each(global_dict,function (k,v) {
                // k = "device_type_choices"
                // v= [[0,'xx'],[1,'xxx']]
                // device_type_choices = 123;
                window[k] = v;  // k 是一個字符串湿硝,這里是定義為全局變量,需要加 window
            })                  // 全局變量用來存儲select_choice,foreignkey choice
        }

        function getTextFromGlobalById(globalName,currentId) {  // 從全局變量中獲取值
            // globalName = "device_type_choices"
            // currentId = 1
            var ret = null;
            $.each(window[globalName],function (k,item) {
                if(item[0] == currentId){
                    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);
                // 頁碼
            }
        })
})();

// 整個封裝到j(luò)s內(nèi)部空間润努,不為外部展示

使用時非常簡便关斜,

template 模版文件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="/static/bootstrap-3.3.7-dist/css/bootstrap.css" />
    <style>

    </style>
</head>
<body>
{#    <select id="i1">#}
{#        <option>上阿海</option>#}
{#        <option>北京</option>#}
{#        <option>廣州</option>#}
{#    </select>#}

    <div style="width: 800px;margin: 0 auto;">
        <h1>資產(chǎn)列表</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">進(jìn)入編輯模式</button>
          <button type="button" class="btn btn-default">批量刪除</button>
          <button id="idSave" type="button" class="btn btn-default">保存</button>
          <a id="idAdd" href="/web/asset-add.html" class="btn btn-default">添加</a>
{#            添加按鈕需要自定制#}
        </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.1.1.js"></script>
    <script src="/static/js/nbList.js"></script>

    <script>
        $(function () {
            $.NB("/web/asset-json.html");  // 這樣就行了
        });
    </script>
    
</body>
</html>

最終的效果圖:


cmdb.png


cmdb,就到這里結(jié)束了铺浇,痢畜,,鳍侣,

分享文件:
cmdb--告別CURD
鏈接:https://pan.baidu.com/s/1UHnJtC6xQAFWBk2QxQs9TQ 密碼:hi3s
cmdb--LNH
鏈接:https://pan.baidu.com/s/1ZWOd2z4hadlEYjzvyjXk8Q 密碼:tle2
模版文件效果圖:

cmdb.png

參看博客:http://www.cnblogs.com/wupeiqi/articles/6192986.html

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末丁稀,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子倚聚,更是在濱河造成了極大的恐慌线衫,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,372評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件秉沼,死亡現(xiàn)場離奇詭異桶雀,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)唬复,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來全肮,“玉大人敞咧,你說我怎么就攤上這事」枷伲” “怎么了休建?”我有些...
    開封第一講書人閱讀 162,415評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長评疗。 經(jīng)常有香客問我测砂,道長,這世上最難降的妖魔是什么百匆? 我笑而不...
    開封第一講書人閱讀 58,157評論 1 292
  • 正文 為了忘掉前任砌些,我火速辦了婚禮,結(jié)果婚禮上加匈,老公的妹妹穿的比我還像新娘存璃。我一直安慰自己,他們只是感情好雕拼,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,171評論 6 388
  • 文/花漫 我一把揭開白布纵东。 她就那樣靜靜地躺著,像睡著了一般啥寇。 火紅的嫁衣襯著肌膚如雪偎球。 梳的紋絲不亂的頭發(fā)上洒扎,一...
    開封第一講書人閱讀 51,125評論 1 297
  • 那天,我揣著相機(jī)與錄音衰絮,去河邊找鬼袍冷。 笑死,一個胖子當(dāng)著我的面吹牛岂傲,可吹牛的內(nèi)容都是我干的难裆。 我是一名探鬼主播,決...
    沈念sama閱讀 40,028評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼镊掖,長吁一口氣:“原來是場噩夢啊……” “哼乃戈!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起亩进,我...
    開封第一講書人閱讀 38,887評論 0 274
  • 序言:老撾萬榮一對情侶失蹤症虑,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后归薛,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體谍憔,經(jīng)...
    沈念sama閱讀 45,310評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,533評論 2 332
  • 正文 我和宋清朗相戀三年主籍,在試婚紗的時候發(fā)現(xiàn)自己被綠了习贫。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,690評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡千元,死狀恐怖苫昌,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情幸海,我是刑警寧澤祟身,帶...
    沈念sama閱讀 35,411評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站物独,受9級特大地震影響袜硫,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜挡篓,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,004評論 3 325
  • 文/蒙蒙 一婉陷、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧瞻凤,春花似錦憨攒、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至蛛壳,卻和暖如春杏瞻,著一層夾襖步出監(jiān)牢的瞬間所刀,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評論 1 268
  • 我被黑心中介騙來泰國打工捞挥, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留浮创,地道東北人。 一個月前我還...
    沈念sama閱讀 47,693評論 2 368
  • 正文 我出身青樓砌函,卻偏偏與公主長得像斩披,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子讹俊,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,577評論 2 353