v1.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  1. <?php
  2. /**
  3. * The mainNavbar widget class file of zin module of ZenTaoPMS.
  4. *
  5. * @copyright Copyright 2009-2023 禅道软件(青岛)有限公司(ZenTao Software (Qingdao) Co., Ltd. www.zentao.net)
  6. * @license ZPL(https://zpl.pub/page/zplv12.html) or AGPL(https://www.gnu.org/licenses/agpl-3.0.en.html)
  7. * @author sunhao<sunhao@easycorp.ltd>
  8. * @package zin
  9. * @link http://www.zentao.net
  10. */
  11. namespace zin;
  12. require_once dirname(__DIR__) . DS . 'nav' . DS . 'v1.php';
  13. /**
  14. * 主内容导航(三级导航,mainNavbar)部件类。
  15. * The main navbar widget class.
  16. *
  17. * @author Hao Sun
  18. */
  19. class mainNavbar extends wg
  20. {
  21. /**
  22. * @var mixed[]
  23. */
  24. protected static $defineProps = array
  25. (
  26. 'items' => '?array',
  27. 'itemProps' => '?array',
  28. 'badgeMap' => '?array',
  29. 'active' => '?string',
  30. 'onRenderItem' => '?callback',
  31. );
  32. /**
  33. * Define the blocks.
  34. *
  35. * @var array
  36. * @access protected
  37. */
  38. protected static $defineBlocks = array
  39. (
  40. 'left' => array('map' => 'dropdown'),
  41. 'right' => array('map' => 'toolbar')
  42. );
  43. /**
  44. * Load the css file.
  45. *
  46. * @access public
  47. * @return string|false
  48. */
  49. public static function getPageCSS()
  50. {
  51. return <<<'CSS'
  52. #mainNavbar {padding-left: 1rem; padding-right: 1rem;}
  53. #mainNavbar .main-navbar-left {position: absolute; z-index: 2;}
  54. #mainNavbar .main-navbar-left #switcher {position: relative; top: 5px; border: 1px solid rgb(var(--color-primary-500-rgb));}
  55. #mainNavbar .main-navbar-left #switcher > .dropmenu-btn {background: #FFF;}
  56. #mainNavbar .main-navbar-left #switcher > .dropmenu-btn:before {background: unset;}
  57. #mainNavbar .main-navbar-left #switcher:after, #mainNavbar .main-navbar-left #switcher:before {position: absolute; display: block; width: 0; height: 0; content: ' '; border-style: solid; border-width: 17px 0 17px 8px; top: -1px;}
  58. #mainNavbar .main-navbar-left #switcher:before {border-color: transparent transparent transparent rgb(var(--color-primary-500-rgb)); right: -8px;}
  59. #mainNavbar .main-navbar-left #switcher:after {border-color: transparent transparent transparent #FFF; right: -7px; border-radius: 2px;}
  60. #mainNavbar .main-navbar-left #switcher .icon-angle-right {display: none;}
  61. #mainNavbar .main-navbar-left #switcher .caret {color: rgb(var(--color-link-hover-rgb));}
  62. #mainNavbar .main-navbar-left #switcher .text {color: rgb(var(--color-primary-500-rgb));}
  63. #mainNavbar .nav[z-use-sortable] > li:hover {cursor: grab !important;}
  64. #mainNavbar .nav[z-use-sortable] > li > a:hover {cursor: grab !important;}
  65. CSS;
  66. }
  67. public static function getPageJS()
  68. {
  69. global $lang, $app;
  70. $app->loadLang('index');
  71. jsVar('langData', $lang->index->dock);
  72. return file_get_contents(__DIR__ . DS . 'js' . DS . 'v1.js');
  73. }
  74. /**
  75. * Override the build method.
  76. *
  77. * @access protected
  78. * @return mixed
  79. */
  80. protected function build()
  81. {
  82. global $app, $config;
  83. $moduleName = $app->rawModule;
  84. $methodName = $app->rawMethod;
  85. $activeNavbarMenu = data('actualActiveMenu');
  86. if(!empty($config->sanplexVersion) && $config->vision === 'rnd')
  87. {
  88. $isExecutionView = $activeNavbarMenu === 'view' && $moduleName === 'execution';
  89. $isTaskReport = $methodName === 'report' && $moduleName === 'task';
  90. if($isExecutionView || $isTaskReport) return;
  91. }
  92. $items = $this->prop('items');
  93. if($items === null)
  94. {
  95. $badgeMap = $this->prop('badgeMap');
  96. $onRenderItem = $this->prop('onRenderItem');
  97. $itemProps = $this->prop('itemProps');
  98. $activeItem = $this->prop('active') ?: data('activeMenuItem');
  99. $items = static::getItems(array('badgeMap' => $badgeMap, 'onRenderItem' => $onRenderItem, 'itemProps' => $itemProps, 'active' => $activeItem));
  100. }
  101. if(empty($items) && !in_array("$moduleName-$methodName", $config->hasMainNavBar)) return null;
  102. $leftBlock = $this->block('left');
  103. $rightBlock = $this->block('right');
  104. if(empty($leftBlock)) $leftBlock = $this->buildSwitcher();
  105. return div
  106. (
  107. setID('mainNavbar'),
  108. setClass('shadow'),
  109. div
  110. (
  111. setClass('container'),
  112. empty($leftBlock) ? null : div(setClass('main-navbar-left'), $leftBlock),
  113. nav
  114. (
  115. set::items($items),
  116. set::responsive(['more' => ['text' => $app->lang->other, 'caret' => true]]),
  117. set($this->getRestProps())
  118. ),
  119. $this->children(),
  120. empty($rightBlock) ? null : div(setClass('main-navbar-right'), $rightBlock)
  121. ),
  122. commonModel::isTutorialMode() ? null : on::contextmenu('.nav-item > a')->call('handleMainNavbarContextmenu', jsRaw('event'), jsRaw('this')),
  123. on::init()->call('window.initPageMainNavbar', $items)
  124. );
  125. }
  126. /**
  127. * 构建2.5级下拉菜单。
  128. * Build switcher.
  129. *
  130. * @access protected
  131. * @return array
  132. */
  133. protected function buildSwitcher()
  134. {
  135. global $app, $config;
  136. $moduleName = $app->rawModule;
  137. $methodName = $app->rawMethod;
  138. if(in_array("$moduleName-$methodName", is_array($config->excludeSwitcherList) ? $config->excludeSwitcherList : array())) return null;
  139. if(in_array($moduleName, (isset($config->hasSwitcherModules) && is_array($config->hasSwitcherModules)) ? $config->hasSwitcherModules : array()) || in_array("$moduleName-$methodName", (isset($config->hasSwitcherMethods) && is_array($config->hasSwitcherMethods)) ? $config->hasSwitcherMethods : array()))
  140. {
  141. $ajaxMethod = 'ajaxSwitcherMenu';
  142. if($moduleName == 'testcase' && $app->tab == 'project') $moduleName = 'project';
  143. if($moduleName == 'testcase' && $app->tab == 'execution') $moduleName = 'execution';
  144. if($moduleName == 'testtask') $ajaxMethod = 'ajaxGetDropMenu';
  145. $fetcher = createLink($moduleName, $ajaxMethod, data('switcherParams'));
  146. return array(zui::dropmenu
  147. (
  148. setID("{$moduleName}-menu"),
  149. set('_id', 'switcher'),
  150. set('data', data('data')),
  151. set('_props', array('data-fetcher' => $fetcher)),
  152. set(array('fetcher' => createLink($moduleName, $ajaxMethod, data('switcherParams')), 'text' => data('switcherText'), 'defaultValue' => data('switcherObjectID'))),
  153. set($this->getRestProps())
  154. ));
  155. }
  156. return null;
  157. }
  158. /**
  159. * @return mixed[]|false
  160. * @param mixed[] $props
  161. */
  162. public static function getItems($props = array())
  163. {
  164. global $app;
  165. $items = data('mainNavbarMenuItems');
  166. if($items !== null) return $items;
  167. $currentModule = $app->getModuleName();
  168. $currentMethod = $app->getMethodName();
  169. if($app->tab == 'admin')
  170. {
  171. $groupID = data('groupID');
  172. $app->control->loadModel('admin')->setMenu((int)$groupID);
  173. }
  174. /* When use workflow then set rawModule to moduleName. */
  175. if($currentModule == 'flow') $currentModule = $app->rawModule;
  176. \commonModel::replaceMenuLang();
  177. \commonModel::setMainMenu();
  178. $activeMenu = $props['activeMenu'] ?? \commonModel::getActiveMainMenu();
  179. if(empty($activeMenu)) return false;
  180. $menu = \customModel::getModuleMenu($activeMenu);
  181. if(!$menu) return false;
  182. $menu = json_decode(json_encode($menu), true);
  183. $items = array();
  184. $badgeMap = $props['badgeMap'] ?? array();
  185. $onRenderItem = $props['onRenderItem'] ?? null;
  186. $itemProps = $props['itemProps'] ?? array();
  187. $activeItem = $props['active'] ?? data('activeMenuItem');
  188. foreach($menu as $key => $menuItem)
  189. {
  190. if(empty($menuItem['link']))
  191. {
  192. unset($menu[$key]);
  193. continue;
  194. }
  195. if(empty($menuItem['alias'])) $menuItem['alias'] = '';
  196. if(empty($menuItem['exclude'])) $menuItem['exclude'] = '';
  197. $item = array();
  198. $link = $menuItem['link'];
  199. $name = $menuItem['name'];
  200. $item['text'] = $menuItem['text'];
  201. $item['url'] = commonModel::createMenuLink((object)$menuItem, $app->tab);
  202. $item['hidden'] = !empty($menuItem['hidden']);
  203. $item['data-id'] = $name;
  204. $item['data-app'] = $app->tab;
  205. $item['data-group'] = $app->tab . '-' . $activeMenu;
  206. $item['zui-key'] = $name;
  207. $active = '';
  208. if($activeItem && $activeItem == $name)
  209. {
  210. $active = 'active';
  211. }
  212. else
  213. {
  214. $subModule = isset($menuItem['subModule']) ? explode(',', $menuItem['subModule']) : array();
  215. if($subModule && in_array($currentModule, $subModule)) $active = 'active';
  216. if($link['module'] == $currentModule && $link['method'] == $currentMethod) $active = 'active';
  217. if($link['module'] == $currentModule && strpos(",{$menuItem['alias']},", ",{$currentMethod},") !== false) $active = 'active';
  218. if(strpos(",{$menuItem['exclude']},", ",{$currentModule}-{$currentMethod},") !== false || strpos(",{$menuItem['exclude']},", ",{$currentModule},") !== false) $active = '';
  219. }
  220. $item['active'] = $active;
  221. if($badgeMap && isset($badgeMap[$name])) $item['badge'] = array('text' => $badgeMap[$name], 'class' => 'label rounded gray-pale size-sm');
  222. if($itemProps) $item = array_merge($item, $itemProps);
  223. if(is_callable($onRenderItem)) $item = $onRenderItem($item, $menuItem);
  224. if(isset($menuItem['dropMenu']))
  225. {
  226. $dropItems = array();
  227. $label = $menuItem['text'];
  228. $menuActive = '';
  229. foreach($menuItem['dropMenu'] as $dropMenuKey => $dropMenuItem)
  230. {
  231. if(isset($dropMenuItem['hidden']) && $dropMenuItem['hidden']) continue;
  232. if(empty($dropMenuItem['alias'])) $dropMenuItem['alias'] = '';
  233. if(empty($dropMenuItem['exclude'])) $dropMenuItem['exclude'] = '';
  234. list($dropMenuName, $dropMenuModule, $dropMenuMethod, $dropMenuParams) = explode('|', $dropMenuItem['link']);
  235. $dropActive = '';
  236. $dropModule = isset($dropMenuModule) ? $dropMenuModule : '';
  237. $dropMethod = isset($dropMenuMethod) ? $dropMenuMethod : '';
  238. $dropParams = isset($dropMenuParams) ? $dropMenuParams : '';
  239. $dropLabel = isset($dropMenuName) ? $dropMenuName : '';
  240. $dropLink = helper::createLink($dropModule, $dropMethod, $dropParams);
  241. $subModule = isset($dropMenuItem['subModule']) ? explode(',', $dropMenuItem['subModule']) : array();
  242. if($subModule && in_array($currentModule, $subModule)) $dropActive = 'active';
  243. if($dropModule == $currentModule && $dropMethod == $currentMethod) $dropActive = 'active';
  244. if($dropModule == $currentModule && strpos(",{$dropMenuItem['alias']},", ",{$currentMethod},") !== false) $dropActive = 'active';
  245. if(strpos(",{$dropMenuItem['exclude']},", ",{$currentModule}-{$currentMethod},") !== false || strpos(",{$dropMenuItem['exclude']},", ",{$currentModule},") !== false) $dropActive = '';
  246. if($dropActive)
  247. {
  248. $label = $dropLabel;
  249. $menuActive = 'active';
  250. }
  251. $dropItems[] = array(
  252. 'active' => $dropActive ? true : false,
  253. 'data-id' => $dropMenuKey,
  254. 'url' => $dropLink,
  255. 'text' => $dropLabel,
  256. 'data-app' => $app->tab
  257. );
  258. }
  259. if(empty($dropItems)) continue;
  260. $items[] = array
  261. (
  262. 'type' => 'dropdown',
  263. 'items' => $dropItems,
  264. 'text' => $label,
  265. 'data-id' => $name,
  266. 'data-app' => $app->tab,
  267. 'trigger' => 'hover',
  268. 'class' => $menuActive
  269. );
  270. }
  271. else
  272. {
  273. $items[] = $item;
  274. }
  275. }
  276. $items = array_filter($items, function($item) { return empty($item['hidden']); });
  277. data('mainNavbarMenuItems', $items);
  278. return $items;
  279. }
  280. }