<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                ![](https://box.kancloud.cn/19f471fce14ecfe3338ea6dd6c2e3249_1687x743.png) 客戶需要這種左側樹形分類,點擊子節點后 顯示對應分類下列表的表格 我看海豚自帶jstree, 就研究了一下官網demo sitebrowser。 ## 樹的問題 ### 樹的展示 首先復制一份common下的builder table對應的layout,在js_list那塊后面加上樹的js ~~~ <script src="__LIBS__/jstree/jstree.min.js"></script> <script> $(document).ready(function(){ var post_url = '{:url("material/operation", [], false, false)}'; $('#jstree').jstree({ core : { 'data' : { url : post_url+'?operation=get_node&prop=1&cid={:input("cid", 0)}', data : function (node) { return { 'id' : node.id }; } }, check_callback : true, themes : { responsive : false }, }, force_text : true, plugins: ["contextmenu", "dnd"], contextmenu: { "items": { "新建菜單": { "label": "新增", "action": function(data) { var ref = $('#jstree').jstree(true), sel = ref.get_selected(); if(!sel.length) { return false; } sel = sel[0]; sel = ref.create_node(sel, { // type: "file", // icon: "glyphicon glyphicon-folder-open", }); if(sel) { ref.edit(sel); } } }, "編輯菜單": { "label": "編輯", "action": function(data) { console.log(data); var ref = $('#jstree').jstree(true), sel = ref.get_selected(); if(!sel.length) { return false; } sel = sel[0]; ref.edit(sel); } }, "刪除菜單": { "label": "刪除", "action": function(data) { console.log(data); var ref = $('#jstree').jstree(true), sel = ref.get_selected(); if(!sel.length) { return false; } ref.delete_node(sel); } }, }, select_mode:false } }) .on("loaded.jstree", function (event, data) { data.instance.open_node(-1); }) .on('click.jstree', function (e, data) { console.log(e); }) .on('changed.jstree', function (e, data) { console.log(e); console.log(data) if(data && data.selected && data.selected.length) { // 非右鍵時跳轉 if(data.event.which !== 3){ location.href = dolphin.curr_url+'/cid/'+data.selected; } }else { location.href = dolphin.curr_url; } return ; }) .on('delete_node.jstree', function (e, data) { $.get(post_url+'?operation=delete_node', { 'id' : data.node.id }) .fail(function () { data.instance.refresh(); }); }) .on('create_node.jstree', function (e, data) { $.get(post_url+'?operation=create_node', { 'id' : data.node.parent, 'position' : data.position, 'text' : data.node.text }) .done(function (d) { data.instance.set_id(data.node, d.id); }) .fail(function () { data.instance.refresh(); }); }) .on('rename_node.jstree', function (e, data) { $.get(post_url+ '?operation=rename_node', { 'id' : data.node.id, 'text' : data.text }) .fail(function () { data.instance.refresh(); }); }) ; }); </script> ~~~ 這個其實海豚自帶的util/Tree類的toLayer方法就能實現 但是遇到一個問題,如何加載樹就全展開,試了好多參數都不行,干脆sql查詢時加上 state:{opened:true} ### 點擊分類后跳轉 demo里有change 事件,想法是拿到節點id 自己拼url,然后跳轉。 但是遇到問題是,點右鍵也觸發change,看上面代碼,排除which == 3 的情況。 ### 右鍵的定制 從網上找了個文章覆蓋 開了右鍵插件后的 contextmenu 屬性 ### 樹的節點操作 先將官方的類修改了一通,改成tp5的db操作。不過沒有實現剪切、粘貼 ~~~ <?php namespace util; use think\Db; /** * 樹結構生成類 * @author CaiWeiMing <314013107@qq.com> */ class JsTree { protected static $instance; /** * 架構函數 * @param array $config */ public function __construct($config = []) { self::$config = array_merge(self::$config, $config); // trace(self::$config); } /** * 配置參數 * @var array */ protected static $config = [ 'table' => '', 'id' => 'id', // id名稱 'pid' => 'pid', // pid名稱 'left' => 'left', 'right' => 'right', 'level' => 'level', 'title' => 'title', // 標題名稱 'child' => 'children', // 子元素鍵名 'position' => 'pos', 'html' => '┝ ', // 層級標記 'step' => 4, // 層級步進數量 ]; /** * 配置參數 * @param array $config * @return object */ public static function config($config = []) { if (!empty($config)) { $config = array_merge(self::$config, $config); } if (is_null(self::$instance)) { self::$instance = new static($config); } return self::$instance; } /** * 將數據集格式化成層次結構 * @param array/object $lists 要格式化的數據集,可以是數組,也可以是對象 * @param int $pid 父級id * @param int $max_level 最多返回多少層,0為不限制 * @param int $curr_level 當前層數 * @author 蔡偉明 <314013107@qq.com> * @return array */ public static function toLayer($lists = [], $pid = 0, $max_level = 0, $curr_level = 0) { $trees = []; $lists = array_values($lists); foreach ($lists as $key => $value) { if ($value[self::$config['pid']] == $pid) { if ($max_level > 0 && $curr_level == $max_level) { return $trees; } unset($lists[$key]); $child = self::toLayer($lists, $value[self::$config['id']], $max_level, $curr_level + 1); if (!empty($child)) { $value[self::$config['child']] = $child; } $trees[] = $value; } } return $trees; } public function get_node($id, $options = ['with_children'=>true]) { $node = db(self::$config['table'])->where(self::$config['id'], $id)->find(); if(!$node) { throw new \Exception('Node does not exist'); } if(isset($options['with_children'])) { $node['children'] = $this->get_children($id, isset($options['deep_children'])); } if(isset($options['with_path'])) { $node['path'] = $this->get_path($id); } return $node; } public function get_children($id, $recursive = false) { $config = self::$config; if($recursive) { $node = $this->get_node($id); return db(self::$config['table']) ->where($config['left'], 'gt', (int)$node[$config['left']]) ->where($config['right'], 'lt', (int)$node[$config['right']]) ->order($config['left']) ->select(); }else { return db($config['table']) ->where($config['pid'], (int)$id) ->order($config['position']) ->select(); } } public function get_path($id) { $node = $this->get_node($id); $config = self::$config; if($node) { return db($config['table']) ->where($config['left'], 'lt', (int)$node[$config['left']]) ->where($config['right'], 'gt', (int)$node[$confg['right']]) ->order($config['left']) ->select(); }else{ return false; } } public function mk($parent, $position = 0, $data = []) { $parent = (int)$parent; if($parent == 0) { throw new Exception('Parent is 0'); } $parent = $this->get_node($parent, ['with_children'=> true]); if(!$parent['children']) { $position = 0; } if($parent['children'] && $position >= count($parent['children'])) { $position = count($parent['children']); } $sql = []; $par = []; // PREPARE NEW PARENT // update positions of all next elements $config = self::$config; db($config['table'])->where($config['position'], 'gt', $position) ->setInc($config['position'], 1); // update left indexes $ref_lft = false; if(!$parent['children']) { $ref_lft = $parent[$config['right']]; }else if(!isset($parent['children'][$position])) { $ref_lft = $parent[$config['right']]; }else { $ref_lft = $parent['children'][(int)$position][$config['left']]; } db($config['table'])->where($config['left'], 'egt', (int)$ref_lft) ->setInc($config['left'], 2); // update right indexes $ref_rgt = false; if(!$parent['children']) { $ref_rgt = $parent[$config['right']]; }else if(!isset($parent['children'][$position])) { $ref_rgt = $parent[$config['right']]; }else { $ref_rgt = $parent['children'][(int)$position][$config['left']] + 1; } db($config['table'])->where($config['right'], 'egt', (int)$ref_rgt)->setInc($config['right'], 2); $tmp = [ $config['left'] => (int)$ref_lft, $config['right'] => (int)$ref_lft+1, $config['level'] => (int)$parent[$config['level']]+1, $config['pid'] => $parent[$config['id']], $config['position'] => $position, ]; $id = db($config['table'])->insertGetId($tmp); if($data && count($data)) { $node = $id; if(!$this->rn($node, $data)) { $this->rm($node); throw new \Exception('Could not rename after create'); } } return $node; } public function mv($id, $parent, $position = 0) { $id = (int)$id; $parent = (int)$parent; if($parent == 0 || $id == 0 || $id == 1) { throw new \Exception('Cannot move inside 0, or move root node'); } $config = self::$config; $parent = $this->get_node($parent, ['with_children'=> true, 'with_path' => true]); $id = $this->get_node($id, ['with_children'=> true, 'deep_children' => true, 'with_path' => true]); if(!$parent['children']) { $position = 0; } if($id[$config['pid']] == $parent[$config['id']] && $position > $id[$config['position']]) { $position ++; } if($parent['children'] && $position >= count($parent['children'])) { $position = count($parent['children']); } if($id[$config['left']] < $parent[$config['left']] && $id[$config['right']] > $parent[$config['right']]) { throw new \Exception('Could not move parent inside child'); } $tmp = []; $tmp[] = (int)$id[$config['id']]; if($id['children'] && is_array($id['children'])) { foreach($id['children'] as $c) { $tmp[] = (int)$c[$config['id']]; } } $width = (int)$id[$config['right']] - (int)$id[$config['left']] + 1; // PREPARE NEW PARENT // update positions of all next elements db($config['table']) ->where($config['id'], 'neq', (int)$id[$config['id']]) ->where($config['pid'], 'eq', (int)$parent[$config['id']]) ->where($config['position'], 'egt', $position) ->setInc($config['position'], 1); // update left indexes $ref_lft = false; if(!$parent['children']) { $ref_lft = $parent[$config['right']]; }else if(!isset($parent['children'][$position])) { $ref_lft = $parent[$config['right']]; }else { $ref_lft = $parent['children'][(int)$position][$config['left']]; } db($config['table']) ->where($config['left'], 'egt', (int)$ref_lft) ->where($config['id'], 'not in', $tmp) ->setInc($config['left'], $width); // update right indexes $ref_rgt = false; if(!$parent['children']) { $ref_rgt = $parent[$cofnig['right']]; }else if(!isset($parent['children'][$position])) { $ref_rgt = $parent[$cofnig['right']]; }else { $ref_rgt = $parent['children'][(int)$position][$config['left']] + 1; } db($config['table']) ->where($config['right'], 'egt', (int)$ref_rgt) ->where($config['id'], 'not in', $tmp) ->setInc($config['right'], $width); // MOVE THE ELEMENT AND CHILDREN // left, right and level $diff = $ref_lft - (int)$id[$config['left']]; if($diff > 0) { $diff = $diff - $width; } $ldiff = ((int)$parent[$config['level']] + 1) - (int)$id[$config['level']]; db($config['table']) ->where($config['id'], 'in'. $tmp) ->update([ $config['right'] => Db::raw("{$config['right']}+{$diff}"), $config['left'] => Db::raw("{$config['left']}+{$diff}"), $config['level'] => Db::raw("{$config['level']}+{$ldiff}") ]); // position and parent_id db($config['table']) ->where($config['id'], (int)$id[$config['id']]) ->update([ $config['position'] => $position, $config['pid'] => (int)$parent[$config['id']] ]); // CLEAN OLD PARENT // position of all next elements db($config['table']) ->where($config['pid'], (int)$id[$config['pid']]) ->where($config['position'], (int)$config['position']) ->setDec($config['position'], 1); // left indexes db($config['table']) ->where($config['left'], 'gt', (int)$id[$config['right']]) ->where($config['id'], 'not in', $tmp) ->setDec($config['left'], $width); // right indexes db($config['table']) ->where($config['right'], 'gt', (int)$id[$config['right']]) ->where($config['id'], 'not in', $tmp) ->setDec($config['right'], $width); return true; } public function rm($id) { $id = (int)$id; if(!$id || $id === 1) { throw new \Exception('Could not create inside roots'); } $config = self::$config; $data = $this->get_node($id, ['with_children' => true, 'deep_children' => true]); $lft = (int)$data[$config['left']]; $rgt = (int)$data[$config['right']]; $pid = (int)$data[$config['pid']]; $pos = (int)$data[$config['position']]; $dif = $rgt - $lft + 1; // deleting node and its children from structure db($config['table']) ->where($config['left'], 'egt', (int)$lft) ->where($config['right'], '<=', (int)$rgt) ->delete(); // shift left indexes of nodes right of the node db($config['table']) ->where($config['left'], 'gt', (int)$rgt) ->setDec($config['left'], (int)$dif); // shift right indexes of nodes right of the node and the node's parents db($config['table']) ->where($config['right'], 'gt', (int)$lft) ->setDec($config['right'], (int)$dif); // Update position of siblings below the deleted node db($config['table']) ->where($config['pid'], $pid) ->where($config['position'], 'gt', (int)$pos) ->setDec($config['position'], 1); return true; } public function rn($id, $data) { $config = self::$config; if(!$exist = db($config['table'])->find($id)) { throw new \Exception('Could not rename non-existing node'); } $data = array_merge($exist, $data); $ret = db($config['table'])->insertAll([$data], true); if(false === $ret){ throw new \Exception('Could not rename'); } return true; } } ~~~ 然后一個控制的方法實現operation ~~~ public function operation(){ $fs = new JsTree(['table' => 'document_category', 'title'=>'text']); if(isset($_GET['operation'])) { try { $rslt = null; switch($_GET['operation']) { case 'get_node': $node = isset($_GET['id']) && $_GET['id'] !== '#' ? (int)$_GET['id'] : 0; if($node == 0){ $list = db('document_category')->field('*,title text')->where('prop', $_GET['prop'])->select(); if($list){ foreach ($list as &$li) { $li['state']['opened'] = true; $cid = input('cid', 0); if($cid && $cid == $li['id']){ $li['state']['selected'] = true; } } } $rslt = JsTree::config(['child'=>'children', 'title'=>'text'])->toLayer($list); }else{ $temp = $fs->get_children($node); $rslt = []; foreach($temp as $v) { $rslt[] = [ 'id' => $v['id'], 'text' => $v['text'], 'children' => ($v['right'] - $v['left'] > 1) ]; } } break; case 'create_node': $node = isset($_GET['id']) && $_GET['id'] !== '#' ? (int)$_GET['id'] : 0; $temp = $fs->mk($node, isset($_GET['position']) ? (int)$_GET['position'] : 0, ['nm' => isset($_GET['text']) ? $_GET['text'] : 'New node']); $rslt = ['id' => $temp]; break; case 'rename_node': $node = isset($_GET['id']) && $_GET['id'] !== '#' ? (int)$_GET['id'] : 0; $rslt = $fs->rn($node, ['title' => isset($_GET['text']) ? $_GET['text'] : 'Renamed node']); break; case 'delete_node': $node = isset($_GET['id']) && $_GET['id'] !== '#' ? (int)$_GET['id'] : 0; $rslt = $fs->rm($node); break; default: throw new \Exception('Unsupported operation: ' . $_GET['operation']); break; } header('Content-Type: application/json; charset=utf-8'); return json($rslt); }catch (\Exception $e) { header($_SERVER["SERVER_PROTOCOL"] . ' 500 Server Error'); header('Status: 500 Server Error'); return $e->getMessage().PHP_EOL.$e->getTraceAsString(); } } } ~~~ 對應表結構 ```[sql] CREATE TABLE `document_category` ( `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT, `pid` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '上級菜單id', `title` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '菜單標題', `prop` int(1) UNSIGNED NULL DEFAULT 1 COMMENT '1-招標 2-投標', `icon` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '菜單圖標', `online_hide` tinyint(4) UNSIGNED NOT NULL DEFAULT 0 COMMENT '網站上線后是否隱藏', `create_time` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '創建時間', `update_time` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '更新時間', `status` tinyint(2) NOT NULL DEFAULT 1 COMMENT '狀態', `left` int(10) UNSIGNED NOT NULL DEFAULT 0, `right` int(10) UNSIGNED NOT NULL DEFAULT 0, `level` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '層級', `pos` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '位置 相當于順序', PRIMARY KEY (`id`) USING BTREE ) ENGINE = MyISAM AUTO_INCREMENT = 18 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; ``` 前端部分:on相關事件,直接參照官方示列。一定要實現get_node方法。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看