關於樹形結構---無限層級通訊錄

(1)表的設計

父級的id作爲子級的parentid也就是說,父子級的關係用parentid這個字段關聯

通訊錄分組表:

通訊錄聯繫人表:

聯繫人 存儲分組id,因爲需求,設計了部門字段,以最低部門選擇的分組id,作爲該條記錄的groupid

(02)實現樹形展示的方式一  jsTree樹形插件

這個插件是基於jQuery的,通訊錄,分組需要添加,修改,刪除。可以滿足需求,並有較好的體驗、美觀

jsTree: https://www.jstree.com/

引入css

<link rel="stylesheet" href="dist/themes/default/style.min.css" />

引入js

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.1/jquery.min.js"></script>

<script src="dist/jstree.min.js"></script>

前端html:

<!--通訊錄內容 start-->
<div class="box-body">
     <div class="tab-content">
         <div class="row">
             <div class="col-md-8" id="container"></div>//樹形結構容器
             <div class="col-md-4">
                 <h4 id="curr_op_title">新增</h4>
                 <hr/>
                 <form  role="form" id="objform" method="post" action="{buildurl('contacts_group_save','index','contacts')}">
                     <div class="form-group">
                         <label class="control-label">分組名稱</label>
                         <input type="text" name="name" id="curr_op_name" placeholder="請輸入分組名稱" class="form-control"/>
                     </div>
                     <div class="form-group" style="text-align: right;">
                         <button class="btn btn-info" type="button" id="save">全部保存</button>
                     </div>
                 </form>
             </div>
         </div>
     </div>
</div>
<!--通訊錄內容 end-->

編輯區的作用是,修改當前操作的節點名稱。Form表單中隱藏着相應的節點操作數據,每點擊了節點。就會生成,並記錄。

類似:

type:是指定 節點之前的圖標樣式

var op_obj = '';//標記當前操作的對象

//生成結構樹
$('#container').jstree({
    'core': { 'check_callback': true,'data':jstreelist,multiple:false },
    'plugins': ['types','dnd','contextmenu'],
    'types': {
        'default': { 'icon': 'fa fa-folder' },
        'show': { 'icon': 'fa fa-eye-slash text-muted' }
    },
    'contextmenu' : {
        'items' : function(o, cb) {
            var items = {
                createAfter: {"label": "插入節點","action": function (data) {createNode(data, 'after');}},
                createChildren: {"label": "插入子節點","action": function (data) {createNode(data, 'last');}},
                deleteItem: {"label": "刪除節點","action": function (data) {deleteNode(data);}}
            };
            return items;
        }
    }
}).bind("select_node.jstree", function (event, node) {
    $('#objform').find('input[name=name]').focus();
    //點擊已有節點。。編輯
    var currnode = node.node;
    $('#curr_op_name').val(currnode.text);
    //添加隱藏域和記錄當前操作的對象
    if(currnode.id.indexOf('new')=='-1'){
        $('#curr_op_title').text('編輯');
        //添加隱藏域,用於記錄修改的分組名
        if($("#update_"+currnode.id).length==0){
            $('#objform').append('<input type="hidden" name="update['+currnode.id+'][name]" id="update_'+currnode.id+'" value="'+currnode.text+'"  />');
        }
        //記錄當前操作的對象
        op_obj = $("#update_"+currnode.id);
    }else{
        //新增節點編輯
        //記錄當前操作的對象
        $('#curr_op_title').text('新增');
        op_obj = $("#add_"+currnode.id);
    }
});

//監聽修改的分組名,寫入隱藏域
$('#curr_op_name').on('input',function () {
    var value = $.trim($(this).val());
    var ref = $('#container').jstree(true);
    var sel = ref.get_selected();
    //有選中節點 纔去更新數據
    if(sel.length!=0){
        //同步更新隱藏域和節點的文本值
        op_obj.val(value);
        ref.set_text(sel, value);
    }
});

//插入節點或插入子節點
var newId = 1;
function createNode(data, pos) {
    var inst = $.jstree.reference(data.reference);
    var obj = inst.get_node(data.reference);//獲取當前樹節點
    obj.data.type = 'default';
    var pid= pos=='after' ? obj.parent : obj.id;
    var data={};
    data.id='new'+(newId++);
    data.name='自定義分組';
    data.parentid=pid;
    //把以上數據寫入表單
    $('#objform').append('<input type="hidden" name="add['+data.id+'][name]" id="add_'+data.id+'" value="'+data.name+'" /><input type="hidden" name="add['+data.id+'][parentid]" value="'+pid+'" id="add_pid_'+data.id +'"/>');
    inst.create_node(obj, {
            id:data.id,
            text: data.name,
            data: { data:data,jstree:{type: "show"}},
        }, pos, function (new_node) {
            inst.deselect_all();
            inst.select_node(new_node, true);
            inst.select_node(new_node);
        }
    );
    $('#objform').find('input[name=name]').focus();
}

//刪除節點
function deleteNode(data) {
    var inst = $.jstree.reference(data.reference),
    obj = inst.get_node(data.reference);
    //當前刪除節點的id
    var id = obj.id;
    //刪除表單中的隱藏域
    if(id.indexOf('new')=='-1'){
        //原節點
        $('#update_'+id).remove();

    }else{
        //新增的節點
        $('#add_'+id).remove();
        $('#add_pid_'+id).remove();
    }
    //在表單中添加隱藏域,標記刪除的節點
    $('#objform').append('<input type="hidden" name="del['+id+']" value="'+id+'" />');
    inst.delete_node(obj);
    //編輯框的值清除
    $('#curr_op_name').val('');
}

//表單提交驗證,所有修改或新增的分組名不能爲空
$('#save').click(function () {
    $flag = true;//標記是否通過驗證
    $('#objform input:hidden').each(function (key,obj) {
      if(!$(obj).val()){
          alert('所有分組名稱不能爲空!');
          return false;
          $flag = false;
      }
    });
    if($flag){
        alert('此操作將對所有變更做保存,包括刪除節點,您確認要進行此操作?')
        $('#objform').submit();
    }
});

後臺就可以針對傳過來的數據,變更通訊錄分組

/**
 * @todo 通訊錄保存,包含新增、修改、刪除
 */
public function contacts_group_save(){
    $userid = param::get_cookie('_userid');     //獲取當前用戶編號
    $data = $_POST;
    if(!$data['update'] && !$data['add'] && !$data['del']){
        showmessage('數據沒有任何修改', buildurl('contacts_group_list', 'index', 'contacts'));
    }
    //操作
    if($data['update']){
        //修改,驗證數據
        foreach ($data['update'] as $key=>$value){
            if(empty($value['name'])){
                showmessage('分組名稱不能爲空!', buildurl('contacts_group_list', 'index', 'contacts'));
            }
            $info = $this->group_db->get_one(['id'=>$key]);
            if(!$info){
                showmessage('分組信息不存在!', buildurl('contacts_group_list', 'index', 'contacts'));
            }
            //當要修改的的分組名,和原組名一致,不進行修改
            $is_update = $this->group_db->get_one(['id'=>$key,'name'=>$value['name']]);
            if(!$is_update){
                //修改時,需要驗證,同級別(parentid相同) 組名不能重複
                $is_update_again = $this->group_db->get_one(['parentid'=>$info['parentid'],'name'=>$value['name']]);
                if($is_update_again){
                    showmessage('同級部門已存在相同分組名稱!', buildurl('contacts_group_list', 'index', 'contacts'));
                }
                $flag = $this->group_db->update(['name'=>$value['name'],'time'=>date('Y-m-d H:i:s',time())],['id'=>$key]);
            }else{
                $flag = true; //標記修改,實際未修改,爲了顯示修改成功
            }
        }
    }
    if($data['add']){
        //添加 驗證數據
        foreach ($data['add'] as $key=>$value){
            if(empty($value['name'])){
                showmessage('分組名稱不能爲空!', buildurl('contacts_group_list', 'index', 'contacts'));
            }
            $is_add = $this->group_db->get_one(['name'=>$value['name'],'parentid'=>$value['parentid']]);
            if($is_add){
                showmessage('同級部門已存在相同分組名稱!', buildurl('contacts_group_list', 'index', 'contacts'));
            }
            $data = array(
                'uid'=> $userid,
                'name'=>$value['name'],
                'time'=>date('Y-m-d H:i:s',time()),
                'parentid'=>$value['parentid'],
            );
            $flag = $this->group_db->insert($data);

        }

    }
    if($data['del']){
        //刪除 軟刪除
        foreach ($data['del'] as $key=>$value){
            $flag = $this->group_db->update(['is_del'=>1,'time'=>date('Y-m-d H:i:s',time())],['id'=>$value]);
        }

    }
    if($flag){
        showmessage('用戶分組更新成功!', buildurl('contacts_group_list', 'index', 'contacts'));
    }else{
        showmessage('用戶分組更新失敗!', buildurl('contacts_group_list', 'index', 'contacts'));
    }

}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章