This commit is contained in:
zhaoxinyu
2024-12-06 11:57:18 +08:00
parent c957e2ddd4
commit 185cc5022a
10 changed files with 1824 additions and 266 deletions
+240 -203
View File
@@ -32,6 +32,8 @@
<!-- import Vue before Element -->
<script src="${base!}/assets/platform/plugins/vue/vue.min.js"></script>
<script src="${base!}/assets/platform/plugins/vuex/vuex.js"></script>
<script src="${base!}/assets/platform/plugins/vuex-persistedstate/vuex-persistedstate.umd.js"></script>
<!-- vue-count-to -->
<script src="${base!}/assets/platform/plugins/vue-count-to/vue-count-to.min.js"></script>
@@ -209,6 +211,86 @@
const hasProposalAdminRole = "${@shiro.hasAnyRoles('sysadmin','jdh10')}" === 'true'
</script>
<script>
window.sessionStorage.setItem('moduleMenus', JSON.stringify(${json(@shiro.userModuleMenus())}))
window.sessionStorage.setItem('menus', JSON.stringify(${json(@shiro.getPrincipalProperty('menus'))}))
window.store = new Vuex.Store({
plugins: [
createPersistedState({
key: "zhgh-vuex",
paths: ["openedMenus", "activeMenuIndex", "activeMenuModuleId"],
storage: window.sessionStorage
})
],
state: {
//当前激活的菜单
activeMenuIndex: null,
//激活的菜单模块
activeMenuModuleId: null,
moduleMenus: JSON.parse(window.sessionStorage.getItem("moduleMenus")),
menus: JSON.parse(window.sessionStorage.getItem("menus"))
},
mutations: {
//设置激活的菜单
setActiveMenuIndex(state, payload) {
state.activeMenuIndex = payload
},
//设置激活的菜单模块
setActiveMenuModuleId(state, payload) {
state.activeMenuModuleId = payload
},
//设置打开的菜单
setOpenedMenus(state, payload) {
state.openedMenus = payload
},
},
actions: {
pjaxRoute({commit, dispatch, state, getters}, href) {
const {pathname, search} = new URL(href, window.location.origin)
const matchMenu = state.menus.find(v => v.href === pathname)
if (!matchMenu) {
commit("setActiveMenuIndex", null)
commit("setOpenedMenus", [])
if (!state.activeModuleId && state.moduleMenus) {
commit("setActiveMenuModuleId", state.moduleMenus[0].id)
}
pjaxReplace(pathname === "/platform/home" ? pathname : pathname)
return
}
//拷贝一份
let cloneMenu = JSON.parse(JSON.stringify(matchMenu))
//找出所有父菜单包括自己
let parentMenus = []
while (cloneMenu && cloneMenu.parentId) {
cloneMenu = state.menus.find((m) => m.id === cloneMenu.parentId)
if (cloneMenu) {
parentMenus.unshift(cloneMenu)
}
}
parentMenus.push(matchMenu)
//获取到该菜单所属的模块
const moduleId = state.moduleMenus.find(v=>v.containsMenu.includes(parentMenus[0].id))?.id
//判断下是否跨模块跳转
if (moduleId !== state.activeMenuModuleId) {
commit("setActiveMenuModuleId", moduleId)
}
Vue.nextTick(() => {
//重新设置展开菜单
commit("setOpenedMenus", parentMenus.map((menu) => menu.id))
//设置当前激活菜单
commit("setActiveMenuIndex", matchMenu.id)
//跳转
pjaxReplace(matchMenu.href ? matchMenu.href + (search || "") : "/platform/home")
})
}
}
})
</script>
<style>
#app {
background-color: rgb(240, 242, 245);
@@ -303,13 +385,6 @@
</div>
<ul class="nav navbar-nav">
<!--<li>
<a href="javascript:" slot="reference">
<i class="fa fa-th-large" aria-hidden="true"></i>
系统模块
</a>
</li>-->
<li style="padding:0 10px" class="vivify popIn duration-1500">
<el-popover
width="450"
@@ -337,7 +412,7 @@
<el-row gutter="20">
<el-col v-for="item in entranceModules" :span="8">
<div class="entranceDetail"
:class="item.id==selectEntranceModule.id?'entranceDetail-selected':''"
:class="item.id==selectEntranceModuleId?'entranceDetail-selected':''"
@click="enterEntranceModules(item)">
<div class="entranceIcon">
<el-image :src="APP_DOMAIN+FILE_STREAM_PREVIEW_ADDRESS+'?id='+item.icon[0].id"
@@ -372,56 +447,14 @@
</li>
</ul>
</header>
<section class="layout">
<section class="layout" style="display: flex;">
<!-- sidebar menu -->
<aside class="sidebar offscreen-left" id="asideMenu">
<!-- main navigation -->
<nav class="main-navigation" data-height="auto" data-size="6px" data-distance="0" data-rail-visible="true"
data-wheel-step="10">
<ul id="leftMenu" class="nav leftMenu" style="display: initial;">
<li v-for="fm in headerNavBarVueApp.firstMenus">
<a :href="fm.href && fm.href.startsWith('/')?fm.href:'javascript:;'">
<i v-if="Object.keys(headerNavBarVueApp.secondMenus).includes(fm.path)"
class="toggle-accordion"></i>
<i :class="fm.icon?fm.icon:'ti-map'"></i>
<span>
{{fm.name}}
</span>
</a>
<ul class="sub-menu" v-if="Object.keys(headerNavBarVueApp.secondMenus).includes(fm.path)">
<li v-for="sm in headerNavBarVueApp.secondMenus[fm.path]">
<a :href="sm.href && sm.href.startsWith('/')?sm.href:'javascript:;'">
<i v-if="headerNavBarVueApp.secondMenus[sm.path]"
class="toggle-accordion"></i>
<i :class="sm.icon?sm.icon:'ti-map'" class="leftMenu__twoIcon"></i>
<span>
{{sm.name}}
</span>
</a>
<ul class="sub-menu" v-if="headerNavBarVueApp.secondMenus[sm.path]">
<li v-for="tm in headerNavBarVueApp.secondMenus[sm.path]">
<a :href="tm.href && tm.href.startsWith('/')?tm.href:'javascript:;'">
<span>
<i class="leftMenu__twoIcon fa fa-circle-o"></i>
{{tm.name}}
</span>
</a>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</nav>
</aside>
<div id="asideMenu" class="sidebar">
<el-menu unique-opened :default-active="activeMenuIndex" :default-openeds="openedMenus" @select="menuSelect"
style="width: 250px;">
<menu-list :menus="leftMenus" :depth="0"></menu-list>
</el-menu>
</div>
<!-- main content -->
<section class="main-content" id="container">
${layoutContent}
@@ -430,117 +463,125 @@
</div>
<script>
window.headerNavBarVueApp = new Vue({
const leftMenuApp = new Vue({
el: '#asideMenu',
components: {
"menu-list": {
name: "menu-list",
template:
/*language=HTML*/
`
<div>
<template v-for="(item, index) in menus">
<el-submenu :index="item.id" v-if="item.children && item.children.length > 0">
<template #title>
<i class="fa fa-tags"></i>
<span>{{ item.name }}</span>
</template>
<menu-list :menus="item.children" :depth="depth + 1"/>
</el-submenu>
<el-menu-item :index="item.id" v-else>
<a :href="item.href" data-pjax>
<i :class="item.icon ? item.icon : 'fa fa-link'"></i>
<span>{{ item.name }}</span>
</a>
</el-menu-item>
</template>
</div>
`,
props: ["menus", "depth"]
}
},
store,
data() {
return {}
},
computed: {
leftMenus() {
if (this.selectEntranceModuleId) {
return this.moduleMenus.find(v => v.id === this.selectEntranceModuleId)?.menus
}
return []
},
moduleMenus() {
return this.$store.state.moduleMenus
},
selectEntranceModuleId() {
return this.$store.state.activeMenuModuleId || null
},
selectEntranceModule() {
if (this.selectEntranceModuleId && this.moduleMenus) {
return this.moduleMenus.find(v => v.id === this.selectEntranceModuleId)
}
return {}
},
//当前选中菜单
activeMenuIndex() {
return this.$store.state.activeMenuIndex
},
//当前打开的菜单 数组 包含所有父菜单
openedMenus() {
return this.$store.state.openedMenus
}
},
methods: {
menuSelect(index, indexPath) {
this.$store.commit("setActiveMenuIndex", index)
this.$store.commit("setOpenedMenus", indexPath)
},
goHome() {
},
assignmentMenu() {
const menuIndexPath = window.sessionStorage.getItem('menuIndexPath')
if (menuIndexPath) {
this.openedMenus = JSON.parse(menuIndexPath)
} else {
this.openedMenus = []
}
const menuIndex = window.sessionStorage.getItem('menuIndex')
if (menuIndex) {
this.activeMenuIndex = menuIndex
} else {
this.activeMenuIndex = ''
}
}
},
created() {
this.assignmentMenu()
}
})
const headerNavBarVueApp = new Vue({
el: '#headerNavbar',
store,
data() {
return {
entranceModules: [],
selectEntranceModule: null,
leftMenus: [],
firstMenus: [],
secondMenus: {},
userDefaultModuleId: null,
menuPopover: false,
appModuleId: ""
}
},
computed: {
entranceModules() {
return this.$store.state.moduleMenus
},
selectEntranceModuleId() {
return this.$store.state.activeMenuModuleId || null
},
selectEntranceModule() {
if (this.selectEntranceModuleId && this.moduleMenus) {
return this.moduleMenus.find(v => v.id === this.selectEntranceModuleId)
}
return {}
}
},
methods: {
async getEntranceModule() {
const resp = await $.get('/platform/sys/entranceModule/getEntranceModule')
if (resp.code === 0) {
this.entranceModules = resp.data
if (this.selectEntranceModule) {
if (this.entranceModules.some(v => v.id === this.selectEntranceModule.id)) {
this.selectEntranceModule = this.entranceModules.find(v => v.id === this.selectEntranceModule.id)
this.openFirstMenu()
return
}
}
if (this.entranceModules) {
if (this.userDefaultModuleId) {
this.selectEntranceModule = this.entranceModules.find(v => v.id === this.userDefaultModuleId)
} else {
this.selectEntranceModule = this.entranceModules[0]
}
this.openFirstMenu()
} else {
this.goSetAppCenter()
}
}
},
openFirstMenu() {
if (window.location.pathname === '/platform/home') {
setTimeout(() => {
this.$nextTick(() => {
const aTag = document.querySelector('#leftMenu li a')
if (aTag) {
aTag.click()
}
})
}, 500)
} else {
const pathname = window.location.pathname
const a_selector = "#leftMenu li a[href='" + pathname + "']"
const getCurrentMenu = () => {
const a = document.querySelector(a_selector)
if (a) {
$(a).parent().parents("li").addClass("open")
$(a).parent().parents('ul.sub-menu').attr('style', 'display:block')
$(a).find("i").addClass("fa-dot-circle-o")
clearInterval(getCurrentMenuInterval)
}
}
const getCurrentMenuInterval = setInterval(getCurrentMenu, 100)
}
},
async enterEntranceModules(item) {
window.sessionStorage.setItem('selectEntranceModule', JSON.stringify(item))
this.selectEntranceModule = item
await this.getFirstMenus(item.id)
this.goHome()
this.openFirstMenu()
this.menuPopover = false
},
async getSecondMenus() {
const resp = await $.get('/platform/sys/entranceModule/getSecondMenus')
if (resp.code === 0) {
this.secondMenus = resp.data
}
},
async getFirstMenus(entranceModuleId) {
const resp = await $.get('/platform/sys/entranceModule/getFirstMenus', {entranceModuleId})
if (resp.code === 0) {
this.firstMenus = resp.data
this.setAttr()
}
},
setAttr(afterFunc = () => {
}) {
this.$nextTick(() => {
const aTags = document.querySelectorAll('.main-navigation a')
aTags.forEach(v => {
if (v.href === 'javascript:;') {
v.removeAttribute("data-pjax")
} else {
v.setAttribute("data-pjax", "")
}
if (v.getAttribute('class') === 'active') {
v.setAttribute('class', '')
}
})
const openLiTags = document.querySelectorAll('.main-navigation li.open')
openLiTags.forEach(v => {
v.setAttribute('class', '')
const childNodes = v.childNodes
childNodes.forEach(c => {
if (c.nodeType === 1 && c.tagName && c.tagName.toUpperCase() === 'UL'.toUpperCase() && c.className === 'sub-menu') {
c.style.display = 'none'
}
})
})
afterFunc()
})
this.$store.commit('setActiveMenuModuleId', item.id)
},
goHome() {
$.pjax({
@@ -549,8 +590,10 @@
fragment: '#container',
timeout: 8000
});
this.setAttr()
this.closeAllMenu()
this.$store.commit('setActiveMenuIndex', null)
this.$store.commit("setOpenedMenus", [])
},
goSetAppCenter() {
$.pjax({
@@ -559,23 +602,6 @@
fragment: '#container',
timeout: 8000
});
this.setAttr()
},
closeAllMenu() {
const subMenus = document.querySelectorAll('ul.sub-menu')
subMenus.forEach(v => {
v.style.display = 'none'
})
const menus = document.querySelectorAll('.main-navigation li.open')
menus.forEach(v => {
v.setAttribute('class', '')
})
const aTags = document.querySelectorAll('.main-navigation a.active')
aTags.forEach(v => {
v.setAttribute('class', '')
})
},
async getUserDefaultEntranceModuleId() {
const resp = await $.get('/platform/sys/entranceModule/getUserDefaultEntranceModuleId')
@@ -611,37 +637,48 @@
this.selectEntranceModule = JSON.parse(selectEntranceModuleStr)
this.appModuleId = this.selectEntranceModule.id
}
await this.getEntranceModule()
await this.getFirstMenus(this.selectEntranceModule.id)
await this.getSecondMenus()
this.setAttr()
// let pjax_url = window.sessionStorage.getItem('pjax_url')
// pjax_url = pjax_url.replace(window.location.origin, '')
// $.pjax({
// url: pjax_url,
// container: '#container',
// fragment: '#container',
// timeout: 8000
// });
// const a_selector = '#leftMenu li a[href="' + pjax_url + '"]'
// const a = document.querySelector(a_selector)
// setTimeout(() => {
// $(a).parent().parents("li").addClass("open")
// $(a).parent().parents('ul.sub-menu').attr('style', 'display:block')
// }, 100)
},
findParentNodes(data, targetHref, parents = []) {
for (const node of data) {
if (node && node.href === targetHref) {
return parents.concat(node);
}
if (node && node.children) {
const found = this.findParentNodes(node.children, targetHref, parents.concat(node));
if (found) {
return found;
}
}
}
return null;
},
matchMenu(path = window.location.pathname) {
const parentNodes = this.findParentNodes(JSON.parse(window.sessionStorage.getItem('moduleMenus')).flatMap(v => v.menus), path)
if (parentNodes) {
const menuIndexPath = parentNodes.map(v => v.id)
const menuIndex = menuIndexPath[menuIndexPath.length - 1]
const menuParentIndex = menuIndexPath[0]
const module = JSON.parse(window.sessionStorage.getItem('moduleMenus')).find(v => v.containsMenu.includes(menuParentIndex))
this.enterEntranceModules(module)
this.$store.commit('setActiveMenuIndex', menuIndex)
this.$store.commit("setOpenedMenus", menuIndexPath)
leftMenuApp.assignmentMenu()
} else {
this.enterEntranceModules(JSON.parse(window.sessionStorage.getItem('moduleMenus'))[0])
this.$store.commit('setActiveMenuIndex', null)
this.$store.commit("setOpenedMenus", [])
leftMenuApp.assignmentMenu()
}
}
},
watch: {},
created() {
this.init()
console.log('init')
}
})
// this.matchMenu()
this.$store.dispatch('pjaxRoute', window.location)
new Vue({
el: '#asideMenu',
data() {
return {}
}
})