Files
PropertyDeployment/resources/Web/MicroCommunityWeb/html/components/frame/menu2/menu2.js
Anfioo 727d6a3a54 version9
2
2025-12-18 18:54:48 +08:00

261 lines
11 KiB
JavaScript

/**
菜单 处理
**/
(function(vc) {
var vm = new Vue({
el: '#menu-nav',
data: {
menus: [],
subMenus: [],
curMenuName: '',
logo: '',
},
mounted: function() {
this._initSysInfo();
//监听 菜单目录改变
document.body.addEventListener('loadMenu', function(_param) {
vm.curMenuName = '';
vm.subMenus = [];
vm.getMenus(_param.detail);
}, false);
// 点击页面空白处自动关闭二级菜单
document.addEventListener('click', (e) => {
const menuNav = document.getElementById('menu-nav'); // 整个菜单区域(包含一级和二级)
const flyoutMenu = document.querySelector('.vc-menu-sub.flyout');
// 如果点击的是菜单区域内部(一级菜单或二级菜单),不关闭
if (menuNav && menuNav.contains(e.target)) {
return;
}
// 点击的是页面其他地方 → 关闭二级菜单
if (flyoutMenu && flyoutMenu.classList.contains('active')) {
this._closeSubMenu();
}
});
},
methods: {
_initSysInfo: function () {
let sysInfo = vc.getData("java110SystemInfo");
let _that = this;
if (!sysInfo) {
setTimeout(function () {
sysInfo = vc.getData("java110SystemInfo");
_that.logo = sysInfo.systemSimpleTitle;
}, 2000);
return;
}
this.logo = sysInfo.systemSimpleTitle;
},
_gotoIndex: function() {
vc.jumpToPage("/")
},
getMenus: function(_catalog) {
let _param = {
params: {
caId: _catalog.caId,
communityId: vc.getCurrentCommunity().communityId
}
}
//发送get请求
vc.http.apiGet('/menu.listCatalogMenus',
_param,
function(json, res) {
let _menuData = JSON.parse(json);
if (_menuData.code != 0) {
return;
}
let _menus = _menuData.data;
if (_menus == null || _menus.length == 0) {
return;
}
_menus.sort(function(a, b) {
return a.seq - b.seq
});
//var _currentMenusId = vc.getCurrentMenu() == null ? _menus[0].id : vc.getCurrentMenu();
//let _currentMenusId = _menus[0].id;
vm.menus = vm.refreshMenuActive(_menus, '');
vc.setMenus(vm.menus);
// vm.switchMenu(_menus[0]);
},
function(errInfo, error) {
console.log('请求失败处理');
}
);
},
refreshMenuActive: function(jsonArray, _id) {
for (var menuIndex = 0; menuIndex < jsonArray.length; menuIndex++) {
if (jsonArray[menuIndex].hasOwnProperty('childs')) {
let _childs = jsonArray[menuIndex].childs;
_childs.sort(function(_child, _newChild) {
return _child.seq - _newChild.seq
});
jsonArray[menuIndex].childs = _childs;
}
if (_id === jsonArray[menuIndex].id) {
//如果当前本身是打开状态,说明 需要关闭
jsonArray[menuIndex].active = true;
continue;
}
jsonArray[menuIndex].active = false;
}
return jsonArray;
},
switchMenu: function(_menu) {
//设置菜单ID
vc.setCurrentMenu(_menu.id);
vm.menus = vm.refreshMenuActive(vm.menus, _menu.id);
vc.setMenus(vm.menus);
vm.subMenus = _menu.childs;
vm.curMenuName = _menu.name;
// 二级菜单样式调整
vm.$nextTick(() => {
const activeItem = document.querySelector('.vc-menu-main li.active');
const flyoutMenu = document.querySelector('.vc-menu-sub.flyout');
const mainMenu = document.querySelector('.vc-menu-main'); // 一级菜单容器
if (activeItem && flyoutMenu && mainMenu) {
const itemTop = activeItem.offsetTop;
const itemHeight = activeItem.offsetHeight;
const menuHeight = flyoutMenu.offsetHeight;
const mainMenuRect = mainMenu.getBoundingClientRect();
const availableBottom = mainMenuRect.bottom - 20; // 距离视口底部留20px边距
// 理想位置:垂直居中对齐当前项
let desiredTop = itemTop + (itemHeight - menuHeight) / 2;
// 限制:不能超出顶部
if (desiredTop < 10) {
desiredTop = 10;
}
// 限制:底部不能超过一级菜单可见底部
const maxTop = window.innerHeight - menuHeight - 60; // 留出顶部导航和底部安全距
if (desiredTop > maxTop) {
desiredTop = maxTop;
}
flyoutMenu.style.top = desiredTop + 'px';
flyoutMenu.classList.add('active');
}
});
if (!_menu.childs || _menu.childs.length < 1) {
return;
}
//选中第一个
vm._gotoPage(_menu.childs[0].href, _menu.childs[0].name);
//vc._fix_height()
},
miniMenu: function() {
//菜单默认为打开方式
if (!vc.notNull(vc.getMenuState())) {
vc.setMenuState('ON');
}
if (vc.notNull(vc.getMenuState()) && vc.getMenuState() == 'ON') {
return;
}
$("body").toggleClass("mini-navbar");
vc.setMenuState('OFF');
},
_gotoPage: function(_href, _tabName) {
// 子菜单默认选中
this._setSelectedMenusChild(_href);
if (_href.indexOf('?') > -1) {
_href += ("&tab=" + _tabName)
} else {
_href += ("?tab=" + _tabName)
}
vc.jumpToPage(_href);
},
// 子菜单默认选中
_setSelectedMenusChild(_href) {
for (var menuIndex = 0; menuIndex < this.menus.length; menuIndex++) {
if (this.menus[menuIndex].hasOwnProperty('childs')) {
var _childs = this.menus[menuIndex].childs;
for (var childIndex = 0; childIndex < _childs.length; childIndex++) {
if (_href == _childs[childIndex].href) {
this.menus[menuIndex].childs[childIndex].active = true;
} else {
this.menus[menuIndex].childs[childIndex].active = false;
}
}
}
}
this.$forceUpdate();
},
_closeSubMenu: function() {
vm.curMenuName = '';
vm.subMenus = [];
vm.menus.forEach(item => {
item.active = false;
});
},
// 新增:鼠标进入一级菜单项
hoverMenu: function(_menu) {
// 高亮当前一级菜单
this.menus = this.refreshMenuActive(this.menus, _menu.id);
vc.setMenus(this.menus);
// 显示对应的二级菜单
this.subMenus = _menu.childs || [];
this.curMenuName = _menu.name;
// Vue渲染完成后定位并显示二级菜单
this.$nextTick(() => {
const hoveredItem = document.querySelector('.vc-menu-main li.active');
const flyoutMenu = document.querySelector('.vc-menu-sub.flyout');
if (hoveredItem && flyoutMenu) {
const itemTop = hoveredItem.offsetTop;
const itemHeight = hoveredItem.offsetHeight;
const menuHeight = flyoutMenu.offsetHeight;
// 垂直居中对齐当前项
let desiredTop = itemTop + (itemHeight - menuHeight) / 2;
if (desiredTop < 10) desiredTop = 10;
const maxTop = window.innerHeight - menuHeight - 60;
if (desiredTop > maxTop) desiredTop = maxTop;
flyoutMenu.style.top = desiredTop + 'px';
flyoutMenu.classList.add('active');
}
});
},
// 新增:鼠标离开一级菜单项时隐藏二级菜单
leaveMenu: function() {
// 延迟隐藏,防止鼠标快速移到二级菜单时闪烁
setTimeout(() => {
const flyoutMenu = document.querySelector('.vc-menu-sub.flyout');
const menuNav = document.getElementById('menu-nav');
// 如果鼠标当前不在整个菜单区域内,才关闭
if (flyoutMenu && menuNav && !menuNav.matches(':hover')) {
this.subMenus = [];
this.curMenuName = '';
this.menus.forEach(item => item.active = false);
flyoutMenu.classList.remove('active');
}
}, 200); // 200ms 延迟,给用户时间把鼠标移到二级菜单上
},
// 鼠标在二级菜单上时保持打开
keepMenuOpen: function() {
// 可以什么都不做,只是阻止 leaveMenu 的定时器触发关闭
// 实际通过 :hover 判断已足够
},
},
});
})(window.vc)