(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')); } }