feat: 添加 Permission Store 实现权限数据管理
This commit is contained in:
@@ -0,0 +1,167 @@
|
||||
import { describe, it, expect, beforeEach } from 'vitest'
|
||||
import { setActivePinia, createPinia } from 'pinia'
|
||||
import { usePermissionStore } from '@/stores/permission'
|
||||
|
||||
describe('Permission Store', () => {
|
||||
beforeEach(() => {
|
||||
setActivePinia(createPinia())
|
||||
localStorage.clear()
|
||||
})
|
||||
|
||||
describe('基础功能', () => {
|
||||
it('应该正确初始化状态', () => {
|
||||
const store = usePermissionStore()
|
||||
|
||||
expect(store.roles).toEqual([])
|
||||
expect(store.permissions).toEqual([])
|
||||
expect(store.menus).toEqual([])
|
||||
expect(store.loaded).toBe(false)
|
||||
})
|
||||
|
||||
it('应该正确设置权限数据', () => {
|
||||
const store = usePermissionStore()
|
||||
|
||||
store.setPermissionData({
|
||||
roles: ['admin'],
|
||||
permissions: ['user:read', 'user:delete'],
|
||||
menus: [
|
||||
{
|
||||
id: 1,
|
||||
name: '仪表盘',
|
||||
path: '/dashboard',
|
||||
icon: 'Odometer',
|
||||
sort: 1
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
expect(store.roles).toEqual(['admin'])
|
||||
expect(store.permissions).toEqual(['user:read', 'user:delete'])
|
||||
expect(store.menus).toHaveLength(1)
|
||||
expect(store.loaded).toBe(true)
|
||||
})
|
||||
|
||||
it('应该正确清除权限数据', () => {
|
||||
const store = usePermissionStore()
|
||||
|
||||
store.setPermissionData({
|
||||
roles: ['admin'],
|
||||
permissions: ['user:read'],
|
||||
menus: []
|
||||
})
|
||||
|
||||
store.clearPermissionData()
|
||||
|
||||
expect(store.roles).toEqual([])
|
||||
expect(store.permissions).toEqual([])
|
||||
expect(store.menus).toEqual([])
|
||||
expect(store.loaded).toBe(false)
|
||||
})
|
||||
})
|
||||
|
||||
describe('权限检查方法', () => {
|
||||
it('应该正确检查单个角色', () => {
|
||||
const store = usePermissionStore()
|
||||
store.setPermissionData({
|
||||
roles: ['admin', 'user'],
|
||||
permissions: [],
|
||||
menus: []
|
||||
})
|
||||
|
||||
expect(store.hasRole('admin')).toBe(true)
|
||||
expect(store.hasRole('manager')).toBe(false)
|
||||
})
|
||||
|
||||
it('应该正确检查多个角色(满足任一即可)', () => {
|
||||
const store = usePermissionStore()
|
||||
store.setPermissionData({
|
||||
roles: ['user'],
|
||||
permissions: [],
|
||||
menus: []
|
||||
})
|
||||
|
||||
expect(store.hasRole(['admin', 'user'])).toBe(true)
|
||||
expect(store.hasRole(['admin', 'manager'])).toBe(false)
|
||||
})
|
||||
|
||||
it('应该正确检查单个权限', () => {
|
||||
const store = usePermissionStore()
|
||||
store.setPermissionData({
|
||||
roles: [],
|
||||
permissions: ['user:read', 'user:delete'],
|
||||
menus: []
|
||||
})
|
||||
|
||||
expect(store.hasPermission('user:read')).toBe(true)
|
||||
expect(store.hasPermission('user:create')).toBe(false)
|
||||
})
|
||||
|
||||
it('应该正确检查多个权限(满足任一即可)', () => {
|
||||
const store = usePermissionStore()
|
||||
store.setPermissionData({
|
||||
roles: [],
|
||||
permissions: ['user:read'],
|
||||
menus: []
|
||||
})
|
||||
|
||||
expect(store.hasPermission(['user:read', 'user:create'])).toBe(true)
|
||||
expect(store.hasPermission(['user:create', 'user:update'])).toBe(false)
|
||||
})
|
||||
})
|
||||
|
||||
describe('localStorage 持久化', () => {
|
||||
it('应该正确保存到 localStorage', () => {
|
||||
const store = usePermissionStore()
|
||||
|
||||
store.setPermissionData({
|
||||
roles: ['admin'],
|
||||
permissions: ['user:read'],
|
||||
menus: [
|
||||
{
|
||||
id: 1,
|
||||
name: '仪表盘',
|
||||
path: '/dashboard',
|
||||
sort: 1
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
const stored = localStorage.getItem('permission')
|
||||
expect(stored).toBeTruthy()
|
||||
|
||||
const data = JSON.parse(stored!)
|
||||
expect(data.roles).toEqual(['admin'])
|
||||
expect(data.permissions).toEqual(['user:read'])
|
||||
expect(data.menus).toHaveLength(1)
|
||||
})
|
||||
|
||||
it('应该正确从 localStorage 恢复', () => {
|
||||
localStorage.setItem('permission', JSON.stringify({
|
||||
roles: ['user'],
|
||||
permissions: ['user:read:self'],
|
||||
menus: []
|
||||
}))
|
||||
|
||||
const store = usePermissionStore()
|
||||
store.initFromStorage()
|
||||
|
||||
expect(store.roles).toEqual(['user'])
|
||||
expect(store.permissions).toEqual(['user:read:self'])
|
||||
expect(store.loaded).toBe(true)
|
||||
})
|
||||
|
||||
it('清除数据时应该同时清除 localStorage', () => {
|
||||
const store = usePermissionStore()
|
||||
|
||||
store.setPermissionData({
|
||||
roles: ['admin'],
|
||||
permissions: [],
|
||||
menus: []
|
||||
})
|
||||
|
||||
store.clearPermissionData()
|
||||
|
||||
expect(localStorage.getItem('permission')).toBeNull()
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,91 @@
|
||||
import { defineStore } from 'pinia'
|
||||
|
||||
export interface MenuItem {
|
||||
id: number
|
||||
name: string
|
||||
path: string
|
||||
icon?: string
|
||||
parentId?: number
|
||||
sort: number
|
||||
children?: MenuItem[]
|
||||
}
|
||||
|
||||
interface PermissionState {
|
||||
roles: string[]
|
||||
permissions: string[]
|
||||
menus: MenuItem[]
|
||||
loaded: boolean
|
||||
}
|
||||
|
||||
export const usePermissionStore = defineStore('permission', {
|
||||
state: (): PermissionState => ({
|
||||
roles: [],
|
||||
permissions: [],
|
||||
menus: [],
|
||||
loaded: false
|
||||
}),
|
||||
|
||||
getters: {
|
||||
hasRole: (state) => (role: string | string[]) => {
|
||||
if (Array.isArray(role)) {
|
||||
return role.some(r => state.roles.includes(r))
|
||||
}
|
||||
return state.roles.includes(role)
|
||||
},
|
||||
|
||||
hasPermission: (state) => (permission: string | string[]) => {
|
||||
if (Array.isArray(permission)) {
|
||||
return permission.some(p => state.permissions.includes(p))
|
||||
}
|
||||
return state.permissions.includes(permission)
|
||||
}
|
||||
},
|
||||
|
||||
actions: {
|
||||
setPermissionData(data: {
|
||||
roles: string[]
|
||||
permissions: string[]
|
||||
menus: MenuItem[]
|
||||
}) {
|
||||
this.roles = data.roles
|
||||
this.permissions = data.permissions
|
||||
this.menus = data.menus
|
||||
this.loaded = true
|
||||
|
||||
this.saveToStorage()
|
||||
},
|
||||
|
||||
clearPermissionData() {
|
||||
this.roles = []
|
||||
this.permissions = []
|
||||
this.menus = []
|
||||
this.loaded = false
|
||||
|
||||
localStorage.removeItem('permission')
|
||||
},
|
||||
|
||||
saveToStorage() {
|
||||
const data = {
|
||||
roles: this.roles,
|
||||
permissions: this.permissions,
|
||||
menus: this.menus
|
||||
}
|
||||
localStorage.setItem('permission', JSON.stringify(data))
|
||||
},
|
||||
|
||||
initFromStorage() {
|
||||
const stored = localStorage.getItem('permission')
|
||||
if (stored) {
|
||||
try {
|
||||
const data = JSON.parse(stored)
|
||||
this.roles = data.roles || []
|
||||
this.permissions = data.permissions || []
|
||||
this.menus = data.menus || []
|
||||
this.loaded = true
|
||||
} catch (error) {
|
||||
console.error('从 localStorage 恢复权限数据失败:', error)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -20,20 +20,42 @@ Object.defineProperty(window, 'matchMedia', {
|
||||
})),
|
||||
})
|
||||
|
||||
const localStorageMock = (() => {
|
||||
let store: Record<string, string> = {}
|
||||
return {
|
||||
getItem: vi.fn((key: string) => store[key] || null),
|
||||
setItem: vi.fn((key: string, value: string) => {
|
||||
store[key] = value
|
||||
}),
|
||||
removeItem: vi.fn((key: string) => {
|
||||
delete store[key]
|
||||
}),
|
||||
clear: vi.fn(() => {
|
||||
store = {}
|
||||
}),
|
||||
}
|
||||
})()
|
||||
|
||||
Object.defineProperty(window, 'localStorage', {
|
||||
value: {
|
||||
getItem: vi.fn(),
|
||||
setItem: vi.fn(),
|
||||
removeItem: vi.fn(),
|
||||
clear: vi.fn(),
|
||||
},
|
||||
value: localStorageMock,
|
||||
})
|
||||
|
||||
const sessionStorageMock = (() => {
|
||||
let store: Record<string, string> = {}
|
||||
return {
|
||||
getItem: vi.fn((key: string) => store[key] || null),
|
||||
setItem: vi.fn((key: string, value: string) => {
|
||||
store[key] = value
|
||||
}),
|
||||
removeItem: vi.fn((key: string) => {
|
||||
delete store[key]
|
||||
}),
|
||||
clear: vi.fn(() => {
|
||||
store = {}
|
||||
}),
|
||||
}
|
||||
})()
|
||||
|
||||
Object.defineProperty(window, 'sessionStorage', {
|
||||
value: {
|
||||
getItem: vi.fn(),
|
||||
setItem: vi.fn(),
|
||||
removeItem: vi.fn(),
|
||||
clear: vi.fn(),
|
||||
},
|
||||
value: sessionStorageMock,
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user