Files
shj-app/store/modules/menu.js
T
2026-08-11 14:09:26 +08:00

172 lines
4.4 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import {
defineStore
} from 'pinia'
import {
ref,
computed,
watch
} from 'vue'
import {pastelColors,defaultApps,postMenuPermissions,scanPathFuncKeyMap} from '@/utils/constant.js'
import {reqMenuPowerList} from '@/api/auth.js'
import { useUserStore } from '@/store'
export const useMenuStore = defineStore('menu', () => {
// 持久化:仅缓存快捷应用的 menuId 列表,不缓存全部菜单
const quickAppIds = ref([])
// 根据默认配置 + 持久化状态重建应用列表
const buildAppsList = () => {
return defaultApps.map(app => ({
...app,
selected: quickAppIds.value.includes(app.path)
}))
}
// 应用列表(从默认配置构建 + 持久化 selected 状态)
const appsList = ref(buildAppsList())
// 持久化恢复后,appsList 需重新根据 quickAppIds 构建
watch(quickAppIds, (ids) => {
if (ids && ids.length > 0) {
appsList.value = buildAppsList()
}
}, { deep: true })
// 编辑时的临时缓存
const editCache = ref([])
// 菜单的权限列表(后端返回的有权限的菜单 code 数组)
const menuProwerList = ref([])
/**
* 取岗位某功能的数据权限级别(仅按 WorkPostName)
* @returns {'view'|'edit'|null} null 表示无菜单权限
* - WorkPostName 为空:仅可查看(view)
* - 在权限表中:按表配置
* - 有岗位名但不在表中:不限制(edit)
*/
const getPostFuncLevel = (funcKey) => {
if (!funcKey) return null
const userStore = useUserStore()
const postName = String(userStore.userInfo?.WorkPostName || '').trim()
if (!postName) return 'view'
const map = postMenuPermissions[postName]
if (!map) return 'edit'
return map[funcKey] || null
}
/**
* 岗位菜单权限(仅按 WorkPostName)
* @param {string} funcKey 功能 key;空表示非扫码类(pipe),不按岗位拦截,走后端 menuId
*/
const hasPostPermission = (funcKey) => {
if (!funcKey) return true
return !!getPostFuncLevel(funcKey)
}
/**
* 岗位数据权限:是否可编辑(提交/保存);仅可查看时返回 false
*/
const canEditFunc = (funcKey) => getPostFuncLevel(funcKey) === 'edit'
/**
* 校验扫码跳转的页面路径是否有岗位权限(非扫码类路径不限制)
*/
const canAccessPath = (path) => {
const funcKey = scanPathFuncKeyMap[path]
if (!funcKey) return true
return hasPostPermission(funcKey)
}
/**
* 校验页面路径是否可编辑
*/
const canEditPath = (path) => {
const funcKey = scanPathFuncKeyMap[path]
if (!funcKey) return true
return canEditFunc(funcKey)
}
// 应用是否可见:后端菜单权限 + 岗位权限双重过滤
const appVisible = (app) => hasMenuPermission(app.menuId) && hasPostPermission(app.funcKey)
// 快捷应用列表(已选择的)
const quickApps = computed(() => appsList.value.filter(app => app.selected && appVisible(app)))
// 业务查询列表(未选择的)
const queryApps = computed(() => appsList.value.filter(app => !app.selected && appVisible(app)))
/**
* 打开编辑弹窗(备份当前状态)
*/
const openEdit = () => {
editCache.value = appsList.value.filter(appVisible)
}
/**
* 切换应用选择状态
*/
const toggleSelect = (item) => {
item.selected = !item.selected
}
/**
* 确认编辑(保存更改)
*/
const confirmEdit = () => {
appsList.value = editCache.value.map(app => ({ ...app }))
// 只持久化快捷应用的 menuId 列表
quickAppIds.value = appsList.value
.filter(app => app.selected)
.map(app => app.path)
}
/**
* 请求菜单权限列表
*/
const fetchMenuPowerList = async (userId, projectId) => {
if (!userId || !projectId) return
try {
const res = await reqMenuPowerList(userId, projectId)
menuProwerList.value = res.data || []
} catch (err) {
console.error('获取菜单权限失败:', err)
menuProwerList.value = []
}
}
/**
* 判断菜单是否有权限打开
* @param {string} menuCode - 菜单编码/标识
* @returns {boolean} 是否有权限
*/
const hasMenuPermission = (menuCode) => {
if (!menuCode) return true
return menuProwerList.value.includes(menuCode)
}
return {
appsList,
quickAppIds,
editCache,
quickApps,
queryApps,
menuProwerList,
pastelColors,
openEdit,
toggleSelect,
confirmEdit,
fetchMenuPowerList,
hasMenuPermission,
hasPostPermission,
canEditFunc,
canAccessPath,
canEditPath
}
}, {
persist: {
enabled: true,
strategies: [{
key: 'menu',
paths: ['quickAppIds'],
}]
},
})