diff --git a/module/common/lang/zh-cn.php b/module/common/lang/zh-cn.php index 8c0c4f7274..0f80b6d6b5 100644 --- a/module/common/lang/zh-cn.php +++ b/module/common/lang/zh-cn.php @@ -156,7 +156,7 @@ $lang->index->menu->project = "浏览{$lang->projectCommon}|project|browse"; $lang->my = new stdclass(); $lang->my->menu = new stdclass(); -$lang->my->menu->account = ' %s' . $lang->arrow . ''; +$lang->my->menu->account = array('link' => ' %s' . $lang->arrow . '', 'fixed' => true); $lang->my->menu->index = '首页|my|index'; $lang->my->menu->todo = array('link' => '待办|my|todo|', 'subModule' => 'todo'); $lang->my->menu->task = array('link' => '任务|my|task|', 'subModule' => 'task'); @@ -176,7 +176,7 @@ $lang->todo->menu = $lang->my->menu; $lang->product = new stdclass(); $lang->product->menu = new stdclass(); -$lang->product->menu->list = '%s'; +$lang->product->menu->list = array('link' => '%s', 'fixed' => true); $lang->product->menu->index = '首页|product|index|locate=no'; $lang->product->menu->story = array('link' => '需求|product|browse|productID=%s', 'alias' => 'batchedit', 'subModule' => 'story'); $lang->product->menu->dynamic = '动态|product|dynamic|productID=%s'; diff --git a/module/common/model.php b/module/common/model.php index 7325dffc1e..41e974627b 100644 --- a/module/common/model.php +++ b/module/common/model.php @@ -483,7 +483,7 @@ class commonModel extends model /* Cycling to print every sub menus. */ foreach($menu as $menuItem) { - + if($menuItem->hidden) continue; /* Init the these vars. */ if($menuItem->link) { diff --git a/module/custom/control.php b/module/custom/control.php index 5b66b4daee..7d8f98adf4 100644 --- a/module/custom/control.php +++ b/module/custom/control.php @@ -193,18 +193,27 @@ class custom extends control if($_POST) { $account = $this->app->user->account; - $menu = $_POST['menu']; + $menus = $_POST['menus']; + + if(empty($menus)) $this->send(array('result' => 'fail', 'message' => $this->lang->custom->saveFail)); - if(empty($method)) + if(is_array($menus)) { - $this->loadModel('setting')->setItem("$account.menucustom.$module", $menu); + foreach ($menus as $menu) + { + $menu = json_decode($menu); + $this->custom->saveCustomMenu($menu->value, $menu->module, $menu->method); + } } else { - $configKey = 'menucustom' . $module; - $this->loadModel('setting')->setItem("$account.$configKey.$method", $menu); + if(!empty($_POST['module'])) $module = $_POST['module']; + if(!empty($_POST['method'])) $method = $_POST['method']; + + $this->custom->saveCustomMenu($menus, $module, $method); } - $this->send(array('result' => 'success', 'menu' => $menu)); + + $this->send(array('result' => 'success')); } if($this->viewType === 'json') @@ -225,7 +234,7 @@ class custom extends control { $menu = !empty($method) ? customModel::getFeatureMenu($module, $method) : customModel::getModuleMenu($module, true); } - $this->send(array('result' => $menu ? 'success' : 'fail', 'menu' => $menu)); + die(json_encode(array('result' => $menu ? 'success' : 'fail', 'menu' => $menu), JSON_HEX_QUOT | JSON_HEX_APOS)); } else { diff --git a/module/custom/js/menu.js b/module/custom/js/menu.js index 9efc9e6f2c..23aceb80c7 100644 --- a/module/custom/js/menu.js +++ b/module/custom/js/menu.js @@ -13,8 +13,29 @@ $(function() 'feature': {} }; - var updateMenu = function($menu, items) + var updateConfig = function($menu) { + var moduleName = $menu.data('module'), methodName = $menu.data('method'); + var menu = []; + $menu.children('.nav').children('li:not(.drag-shadow)').each(function() + { + var $e = $(this); + var item = $e.children('a').data('menu'); + item.order = $e.attr('data-order'); + menu.push(item); + }); + if(moduleName === 'main') menuConfig.main = menu; + else if(methodName) menuConfig['feature'][moduleName][methodName] = menu; + else menuConfig['module'][moduleName] = menu; + } + + var updateMenu = function(moduleName, methodName, items) + { + var $menu = moduleName === 'main' ? $mainMenu : (methodName ? $featureMenu : $moduleMenu); + var items = items || (moduleName === 'main' ? menuConfig.main : (methodName ? menuConfig['feature'][moduleName][methodName] : menuConfig['module'][moduleName])); + + $menu.data({'module': moduleName, 'method': methodName}); + if(items) { var $nav = $('
'); @@ -24,7 +45,10 @@ $(function() var $a = $('').html(item.text).data('menu', item).append(''); $('').attr('data-id', item.name).toggleClass('right', item.float === 'right').toggleClass('menu-hidden', !!item.hidden).append($a).appendTo($nav); }); - $nav.sortable(); + $nav.sortable({finish: function(e) + { + updateConfig(e.element.closest('nav')); + }}); $menu.children('ul').replaceWith($nav); } else @@ -43,71 +67,125 @@ $(function() $moduleMenu.find('li[data-id="' + methodName + '"]').addClass('active'); }; - var loadData = function(moduleName, methodName, type) + var loadData = function(moduleName, methodName, type, callback) { type = type || ''; var link = createLink('custom', 'menu', 'module=' + moduleName + '&method=' + methodName + '&type=' + type, 'json'); $loadingIcon.addClass('active'); $.get(link, function(data) { - console.log(data); if(data.result === 'success' && data.menu) { var menu = data.menu; - if(menu['main']) + if(menu['main'] && !menuConfig['main']) { - updateMenu($mainMenu, menu['main']); menuConfig['main'] = menu['main']; } - if(menu['module']) + if(menu['module'] && !menuConfig['module'][moduleName]) { - updateMenu($moduleMenu, menu['module']); menuConfig['module'][moduleName] = menu['module']; } - if(menu['feature'] !== undefined) + if(menu['feature'] !== undefined && (!menuConfig['feature'][moduleName] || menuConfig['feature'][moduleName][methodName] === undefined)) { - updateMenu($featureMenu, menu['feature']); if(!menuConfig['feature'][moduleName]) menuConfig['feature'][moduleName] = {}; menuConfig['feature'][moduleName][methodName] = menu['feature']; } + activeCurrent(moduleName, methodName); + callback && callback(true, data); + } + else + { + callback && callback(false, data); } - activeCurrent(moduleName, methodName); $loadingIcon.removeClass('active'); }, 'json'); }; - $menuEditor.on('mouseenter', '.nav > li > a', function() + var formatMenuConfig = function(items) { - // var $a = $(this); - // var item = $a.data('menu'); - // var $menu = $a.closest('nav'); - // var moduleName = item.link && item.link['module'] ? item.link['module'] : item.name; - // var methodName = item.link && item.link['method'] ? item.link['method'] : ''; - // if($menu.is('#modulemenu')) - // { - // moduleName = currentModule; - // methodName = item.name; - // } - // if(moduleName !== currentModule || methodName !== currentMethod) - // { - // if($menu.is('#mainmenu,#modulemenu')) - // { - // if(menuConfig['module'][moduleName] !== undefined && menuConfig['feature'][moduleName] && menuConfig['feature'][moduleName][methodName] !== undefined) - // { - // updateMenu($moduleMenu, menuConfig['module'][moduleName]); - // updateMenu($featureMenu, menuConfig['feature'][moduleName][methodName]); - // activeCurrent(moduleName, methodName); - // } - // else - // { - // loadData(moduleName, methodName, 'all'); - // } - // } - // } + return $.map(items, function(item) + { + var data = {name: item.name, order: parseInt(item.order)}; + if(item.hidden) data.hidden = true; + return data; + }); + }; + + $menuEditor.on('mouseenter', '.nav > li:not(.drag-shadow) > a', function() + { + var $a = $(this); + var item = $a.data('menu'); + var $menu = $a.closest('nav'); + + if($menu.is('#mainmenu')) + { + var moduleName = item.name; + if(moduleName !== currentModule) + { + var methodName = item.link['method']; + if(menuConfig['module'][moduleName]) + { + updateMenu(moduleName); + if(menuConfig['feature'][moduleName] && menuConfig['feature'][moduleName][methodName] !== undefined) + { + updateMenu(moduleName, methodName); + activeCurrent(moduleName, methodName); + } + else + { + loadData(moduleName, methodName, 'all', function(result) + { + if(result) + { + updateMenu(moduleName, methodName); + activeCurrent(moduleName, methodName); + } + }); + } + } + else + { + loadData(moduleName, methodName, 'all', function(result) + { + if(result) + { + updateMenu(moduleName); + updateMenu(moduleName, methodName); + activeCurrent(moduleName, methodName); + } + }); + } + } + } + else if($menu.is('#modulemenu')) + { + var moduleName = currentModule; + var methodName = item.name; + if(methodName !== currentMethod) + { + if(menuConfig['feature'][moduleName] && menuConfig['feature'][moduleName][methodName] !== undefined) + { + updateMenu(moduleName, methodName); + activeCurrent(moduleName, methodName); + } + else + { + loadData(moduleName, methodName, 'all', function(result) + { + if(result) + { + updateMenu(moduleName, methodName); + activeCurrent(moduleName, methodName); + } + }); + } + } + } }).on('click', '.nav > li > a', function() { var $a = $(this); var item = $a.data('menu'); + item.hidden = !!!item.hidden; var $menu = $a.closest('nav'); var moduleName = item.link && item.link['module'] ? item.link['module'] : item.name; var methodName = item.link && item.link['method'] ? item.link['method'] : ''; @@ -116,14 +194,45 @@ $(function() moduleName = currentModule; methodName = item.name; } - $a.parent().toggleClass('menu-hidden'); + $a.parent().toggleClass('menu-hidden', item.hidden); + updateConfig($menu); }); $('#saveMenuBtn').click(function() { - console.log('save', menuConfig); + var postData = [{'module': 'main', value: formatMenuConfig(menuConfig.main)}]; + $.each(menuConfig['module'], function(moduleName, items) + { + postData.push({'module': moduleName, value: formatMenuConfig(items)}); + }); + + $.each(menuConfig['feature'], function(moduleName, feature) + { + if(!feature) return; + $.each(feature, function(methodName, items) + { + if(items) postData.push({'module': moduleName, 'method': methodName, value: formatMenuConfig(items)}); + }); + }); + + postData = $.map(postData, JSON.stringify); + + $.post(createLink('custom', 'menu'), {menus: postData}, function(data) + { + if(data.result === 'success') window.parent.location.reload() + if(data.message) alert(data.message); + }, 'json').error(function(e) {alert(lang.timeout); console.log(e);}); }).on('mouseenter', function() {$menuEditor.addClass('preview')}) .on('mouseout', function() {$menuEditor.removeClass('preview')}); - loadData(currentModule, currentMethod, 'all'); + loadData(currentModule, currentMethod, 'all', function(result) + { + if(result) + { + updateMenu('main'); + updateMenu(currentModule); + updateMenu(currentModule, currentMethod); + activeCurrent(currentModule, currentMethod); + } + }); }); diff --git a/module/custom/lang/en.php b/module/custom/lang/en.php index 49219bd92b..ba5105fa41 100644 --- a/module/custom/lang/en.php +++ b/module/custom/lang/en.php @@ -80,4 +80,5 @@ $lang->custom->productproject->relation['1_1'] = 'Project - Sprint'; $lang->custom->productproject->notice = 'You can change the name of product and project, and the corresponding name display'; -$lang->custom->menuTip = 'Click menu item to toggle display status, drag and drop to change display order.'; +$lang->custom->menuTip = 'Click menu item to toggle display status, drag and drop to change display order.'; +$lang->custom->saveFail = 'Save failed.'; diff --git a/module/custom/lang/zh-cn.php b/module/custom/lang/zh-cn.php index a96e360e41..316367ab90 100644 --- a/module/custom/lang/zh-cn.php +++ b/module/custom/lang/zh-cn.php @@ -80,4 +80,5 @@ $lang->custom->productproject->relation['1_1'] = '项目 - 迭代'; $lang->custom->productproject->notice = '请根据实际情况选择适合自己团队的概念。'; -$lang->custom->menuTip = '点击导航项目来切换显示或隐藏,拖动导航项目来更改显示顺序。'; +$lang->custom->menuTip = '点击导航项目来切换显示或隐藏,拖动导航项目来更改显示顺序。'; +$lang->custom->saveFail = '保存失败!'; diff --git a/module/custom/model.php b/module/custom/model.php index ac7293d1de..35408d538b 100644 --- a/module/custom/model.php +++ b/module/custom/model.php @@ -173,7 +173,6 @@ class customModel extends model $method = ''; $float = ''; $fixed = ''; - $hidden = $isSetMenuConfig && $menuConfigMap[$name] && $menuConfigMap[$name]->hidden; $link = is_array($item) ? $item['link'] : $item; if(strpos($link, '|') !== false) @@ -208,11 +207,12 @@ class customModel extends model $fixed = $item['fixed']; } + $hidden = !$fixed && $isSetMenuConfig && $menuConfigMap[$name] && $menuConfigMap[$name]->hidden; + $menuItem = new stdclass(); $menuItem->name = $name; $menuItem->link = $itemLink; $menuItem->text = $label; - $menuItem->source = $item; $menuItem->order = $isSetMenuConfig && $menuConfigMap[$name] && isset($menuConfigMap[$name]->order) ? $menuConfigMap[$name]->order : $order++; if($float) $menuItem->float = $float; if($fixed) $menuItem->fixed = $fixed; @@ -273,12 +273,39 @@ class customModel extends model { global $app, $lang, $config; $app->loadLang($module); - $configKey = 'menucustom' . $module; - $menuConfig = $config->$configKey->$method; + $configKey = 'feature_' . $module . '_' . $method; + $menuConfig = $config->menucustom->$configKey; if(!empty($menuConfig)) $menuConfig = json_decode($menuConfig); $allMenu = $lang->$module->featurebar[$method]; return $allMenu ? self::buildMenuConfig($allMenu, $menuConfig) : null; } + + /** + * Save custom menu to config + * @param string $menu + * @param string $module + * @param string $method + * @access public + * @return void + */ + public function saveCustomMenu($menu, $module, $method) + { + $account = $this->app->user->account; + $settingKey = ''; + + if(!is_string($menu)) $menu = json_encode($menu); + + if(empty($method)) + { + $settingKey = "$account.common.menucustom.$module"; + } + else + { + $settingKey = "$account.common.menucustom.feature_$module_$method"; + } + + $this->loadModel('setting')->setItem($settingKey, $menu); + } } diff --git a/www/js/my.full.js b/www/js/my.full.js index a6dcbc6d7b..035f38cb8d 100644 --- a/www/js/my.full.js +++ b/www/js/my.full.js @@ -1795,10 +1795,15 @@ function initMainMenu() selector: 'li:not(.custom-item)', finish: function(e) { - var menu = e.list.map(function(){return $(this).data('id');}).get(); - $.post(createLink('custom', 'menu'), {menu: menu.join(',')}, function(data) + var menu = []; + e.list.each(function() { - }, 'json'); + var $e = $(this); + menu.push({name: $e.data('id'), order: $e.attr('data-order')}); + }); + $.post(createLink('custom', 'menu'), {menus: JSON.stringify(menu), "module": 'main'}, function(data) + { + }, 'json').error(function() {alert(lang.timeout)}); } }); }