20260904232445
This commit is contained in:
1 parent
4e167df0f0
commit
1b01a31252
19 files changed
+1099
-1013
No files matched your search
@@ -0,0 +1,120 @@
|
||||
import { computed, ref, watch } from 'vue'
|
||||
import { defineStore } from 'pinia'
|
||||
import { loadDataApi } from '@/services/api'
|
||||
import { useAuthStore } from './auth'
|
||||
import { buildTree, sortTree } from '@/utils/tree'
|
||||
|
||||
/**
|
||||
* 动态导航菜单 store(侧栏菜单数据源)。
|
||||
*
|
||||
* 菜单树由「菜单管理」维护在 s_menu 表,含目录 / 页面 / 外链三类节点。
|
||||
* 可见性规则由前端执行(不改后端):
|
||||
* - g3soft(管理员)可见全部启用菜单;
|
||||
* - 其他账号隐藏编码为 module 的菜单(模块管理入口)及其整棵子树;
|
||||
* - 目录仅当存在可见子菜单时渲染(空目录不显示)。
|
||||
* 与权限 store 一致:同一登录主体加载去重、并发请求复用、登录主体切换清空缓存。
|
||||
*/
|
||||
export const useMenuStore = defineStore('menus', () => {
|
||||
const authStore = useAuthStore()
|
||||
/** s_menu 原始记录(b_canuse = 1,接口按 b_xh / b_id 排序返回) */
|
||||
const rawMenus = ref([])
|
||||
const loadedPrincipalKey = ref('')
|
||||
let loadingPromise = null
|
||||
let loadingPrincipalKey = ''
|
||||
let loadVersion = 0
|
||||
|
||||
const isG3soft = computed(() => {
|
||||
return (
|
||||
String(authStore.loginInfo.user?.account || '')
|
||||
.trim()
|
||||
.toLowerCase() === 'g3soft'
|
||||
)
|
||||
})
|
||||
|
||||
/**
|
||||
* 加载菜单数据;同一主体重复调用去重,并发调用共享同一请求。
|
||||
*/
|
||||
async function load() {
|
||||
const userId = String(authStore.loginInfo.user?.id || '')
|
||||
const principalKey = `${String(authStore.userInfo.orgId || '')}:${userId}`
|
||||
|
||||
if (!authStore.isAuthenticated) return
|
||||
if (loadedPrincipalKey.value === principalKey) return
|
||||
if (loadingPromise && loadingPrincipalKey === principalKey) return loadingPromise
|
||||
|
||||
const requestVersion = ++loadVersion
|
||||
loadingPrincipalKey = principalKey
|
||||
const request = loadDataApi('s_menu', 'b_canuse = 1', 'b_xh ASC, b_id ASC')
|
||||
.then((res) => {
|
||||
if (requestVersion !== loadVersion) return
|
||||
rawMenus.value = res.data || []
|
||||
loadedPrincipalKey.value = principalKey
|
||||
})
|
||||
.finally(() => {
|
||||
if (requestVersion !== loadVersion) return
|
||||
loadingPromise = null
|
||||
loadingPrincipalKey = ''
|
||||
})
|
||||
loadingPromise = request
|
||||
return request
|
||||
}
|
||||
|
||||
/**
|
||||
* 当前主体可见的菜单树(s_menu 原始行结构,含 children 子树)。
|
||||
*/
|
||||
const visibleMenus = computed(() => {
|
||||
if (!rawMenus.value.length) return []
|
||||
const tree = sortTree(buildTree(JSON.parse(JSON.stringify(rawMenus.value))))
|
||||
return pruneByAccess(tree)
|
||||
})
|
||||
|
||||
/** 递归按可见性裁剪菜单树:非 g3soft 隐藏 module 菜单(含其整棵子树),并剪掉空目录 */
|
||||
function pruneByAccess(nodes) {
|
||||
const result = []
|
||||
for (const node of nodes) {
|
||||
// 模块管理(菜单编码 module)仅 g3soft 可见
|
||||
if (!isG3soft.value && String(node.b_code || '').toLowerCase() === 'module') continue
|
||||
const children = node.children?.length ? pruneByAccess(node.children) : []
|
||||
// 目录:没有可访问子菜单时不渲染
|
||||
if (node.b_menu_type === 'directory') {
|
||||
if (children.length) result.push({ ...node, children })
|
||||
continue
|
||||
}
|
||||
result.push(children.length ? { ...node, children } : { ...node })
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
function clear() {
|
||||
// 仅当“正在进行中的请求属于别的主体”时才作废它(如切换账号),
|
||||
// 否则保留进行中请求、只清空已加载数据,交由后续 load 结果填充。
|
||||
const userId = String(authStore.loginInfo.user?.id || '')
|
||||
const principalKey = `${String(authStore.userInfo.orgId || '')}:${userId}`
|
||||
if (loadingPrincipalKey && loadingPrincipalKey !== principalKey) {
|
||||
loadVersion++
|
||||
loadingPromise = null
|
||||
loadingPrincipalKey = ''
|
||||
}
|
||||
loadedPrincipalKey.value = ''
|
||||
rawMenus.value = []
|
||||
}
|
||||
|
||||
// 登录主体变化(退出/切换账号)时清空菜单缓存
|
||||
watch(
|
||||
() => [
|
||||
authStore.userInfo.orgId,
|
||||
authStore.loginInfo.user?.id,
|
||||
authStore.loginInfo.user?.account,
|
||||
authStore.loginInfo.token,
|
||||
],
|
||||
clear,
|
||||
)
|
||||
|
||||
return {
|
||||
load,
|
||||
clear,
|
||||
isG3soft,
|
||||
rawMenus,
|
||||
visibleMenus,
|
||||
}
|
||||
})
|
||||
Reference in new issue
Block a user