diff --git a/lib/zin/wg/docmenu/v1.php b/lib/zin/wg/docmenu/v1.php index 397f6c3b97..14afc57564 100644 --- a/lib/zin/wg/docmenu/v1.php +++ b/lib/zin/wg/docmenu/v1.php @@ -24,6 +24,8 @@ class docMenu extends wg 'objectType?: string', 'objectID?: int=0', 'hover?: bool=true', + 'sortable?: array', + 'onSort?: function' ); public static function getPageCSS(): ?string @@ -111,7 +113,8 @@ class docMenu extends wg if(empty($items)) $items = $this->modules; if(empty($items)) return array(); - $activeKey = $this->prop('activeKey'); + $activeKey = $this->prop('activeKey'); + $sortTree = $this->prop('sortable') || $this->prop('onSort'); $parentItems = array(); foreach($items as $setting) { @@ -141,6 +144,8 @@ class docMenu extends wg 'actions' => $this->getActions($setting) ); + if($sortTree && $setting->type == 'module') $item['trailingIcon'] = 'move muted cursor-move'; + $children = zget($setting, 'children', array()); if(!empty($children)) { @@ -214,6 +219,7 @@ class docMenu extends wg private function getActions($item): array|null { $versionBtn = array(); + $sortTree = $this->prop('sortable') || $this->prop('onSort'); if(isset($item->versions) && $item->versions) { global $lang; @@ -428,7 +434,7 @@ class docMenu extends wg $title = $this->getTitle(); $menuLink = $this->prop('menuLink', ''); $objectID = $this->prop('objectID', 0); - $treeProps = set($this->props->pick(array('items', 'activeClass', 'activeIcon', 'activeKey', 'onClickItem', 'defaultNestedShow', 'changeActiveKey', 'isDropdownMenu', 'hover'))); + $treeProps = $this->props->pick(array('items', 'activeClass', 'activeIcon', 'activeKey', 'onClickItem', 'defaultNestedShow', 'changeActiveKey', 'isDropdownMenu', 'hover', 'sortable', 'onSort')); $preserve = $this->prop('preserve', $app->getModuleName() . '-' . $app->getMethodName()); $isInSidebar = $this->parent instanceof sidebar; @@ -442,6 +448,8 @@ class docMenu extends wg $title ) ); + + $treeType = (!empty($treeProps['onSort']) || !empty($treeProps['sortable'])) ? 'sortableTree' : 'tree'; return array ( $isInSidebar && !$menuLink ? $header : null, @@ -463,12 +471,12 @@ class docMenu extends wg setClass($menuLink ? 'pt-3' : ''), setClass('col scrollbar-thin scrollbar-hover flex-auto overflow-y-auto overflow-x-hidden pl-2 pr-1 py-1'), setStyle('--menu-selected-bg', 'none'), - zui::tree + zui::$treeType ( set::_tag('menu'), set::lines(), set::preserve($preserve), - $treeProps + set($treeProps) ) ), $this->buildBtns() diff --git a/module/doc/control.php b/module/doc/control.php index dc576c584d..a699256ca3 100755 --- a/module/doc/control.php +++ b/module/doc/control.php @@ -997,4 +997,22 @@ class doc extends control $this->display(); } + + /** + * 目录排序 + * Catalog sorting. + * + * @access public + * @return void + */ + public function sortCatalog() + { + if($_SERVER['REQUEST_METHOD'] == 'POST') + { + foreach($_POST['orders'] as $id => $order) $this->doc->updateOrder($id, (int)$order); + + if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError())); + return $this->send(array('result' => 'success')); + } + } } diff --git a/module/doc/js/common.ui.js b/module/doc/js/common.ui.js index f19bfc1939..92e795cce8 100644 --- a/module/doc/js/common.ui.js +++ b/module/doc/js/common.ui.js @@ -236,3 +236,11 @@ $(document).on('mousedown', '.ajaxCollect', function (event) }, 'json'); return false; }); + +window.updateOrder = function(event, orders) +{ + let sortedIdList = {}; + for(let i in orders) sortedIdList['orders[' + orders[i] + ']'] = i; + + $.post($.createLink('doc', 'sortCatalog'), sortedIdList); +} diff --git a/module/doc/model.php b/module/doc/model.php index 0b238f1697..a3b6961110 100644 --- a/module/doc/model.php +++ b/module/doc/model.php @@ -2790,4 +2790,20 @@ class docModel extends model return $this->dao->select('*')->from($table)->where('id')->eq($objectID)->fetch(); } + + /** + * 更新目录顺序。 + * Update catalog order. + * + * @param int $catalogID + * @param int $order + * @access public + * @return bool + */ + public function updateOrder(int $catalogID, int $order): bool + { + $this->dao->update(TABLE_MODULE)->set('`order`')->eq($order)->where('id')->eq($catalogID)->andWhere('type')->eq('doc')->exec(); + + return !dao::isError(); + } } diff --git a/module/doc/test/lib/doc.unittest.class.php b/module/doc/test/lib/doc.unittest.class.php index a7b31a14eb..0a864cbce2 100644 --- a/module/doc/test/lib/doc.unittest.class.php +++ b/module/doc/test/lib/doc.unittest.class.php @@ -1412,4 +1412,21 @@ class docTest if(dao::isError()) return dao::getError(); return $editors; } + + /** + * 更新目录顺序。 + * Update catalog order. + * + * @param int $catalogID + * @param int $order + * @access public + * @return int|false + */ + public function updateOrderTest(int $catalogID, int $order): int|false + { + $this->objectModel->updateOrder($catalogID, $order); + + if(dao::isError()) return dao::getError(); + return $this->objectModel->dao->select('`order`')->from(TABLE_MODULE)->where('id')->eq($catalogID)->fetch('order'); + } } diff --git a/module/doc/test/model/updateorder.php b/module/doc/test/model/updateorder.php new file mode 100755 index 0000000000..48228d7009 --- /dev/null +++ b/module/doc/test/model/updateorder.php @@ -0,0 +1,28 @@ +#!/usr/bin/env php +updateOrder(); +timeout=0 +cid=1 + +- 测试ID为1的目录,order值不变的情况 @10 +- 测试ID为2的目录,order值需要更新的情况 @1 +- 测试目录ID不存在的情况 @~~ + +*/ +include dirname(__FILE__, 5) . '/test/lib/init.php'; +include dirname(__FILE__, 2) . '/lib/doc.unittest.class.php'; + +zenData('module')->loadYaml('module')->gen(10); + +$catalogOrderList = array(); +$catalogOrderList[] = array('id' => 1, 'order' => 10); +$catalogOrderList[] = array('id' => 2, 'order' => 1); +$catalogOrderList[] = array('id' => 11, 'order' => 100); + +$docTester = new docTest(); +r($docTester->updateOrderTest($catalogOrderList[0]['id'], $catalogOrderList[0]['order'])) && p() && e(10); // 测试ID为1的目录,order值不变的情况 +r($docTester->updateOrderTest($catalogOrderList[1]['id'], $catalogOrderList[1]['order'])) && p() && e(1); // 测试ID为2的目录,order值需要更新的情况 +r($docTester->updateOrderTest($catalogOrderList[2]['id'], $catalogOrderList[2]['order'])) && p() && e('~~'); // 测试目录ID不存在的情况 diff --git a/module/doc/ui/lefttree.html.php b/module/doc/ui/lefttree.html.php index 6b684c77a7..297923d4fd 100644 --- a/module/doc/ui/lefttree.html.php +++ b/module/doc/ui/lefttree.html.php @@ -23,6 +23,7 @@ if($app->rawModule == 'doc' && $app->rawMethod == 'myspace') } } +$canSort = hasPriv('doc', 'sortCatalog'); sidebar ( set::preserve(false), @@ -37,6 +38,8 @@ sidebar set::spaceType($spaceType), set::objectType(isset($type) ? $type : ''), set::objectID(isset($objectID) ? $objectID : 0), + set::sortable(array('handle' => '.icon-move')), + set::onSort(jsRaw('window.updateOrder')), set::title(!empty($objectDropdown['text']) ? $objectDropdown['text'] : $moduleTitle), set::menuLink(isset($objectDropdown['link']) ? $objectDropdown['link'] : ''), set::settingLink($app->rawModule == 'doc' && $app->rawMethod == 'view' && common::hasPriv('doc', 'displaySetting') ? inlink('displaySetting') : ''),