feat: add permission control for material list page
Co-authored-by: aider (openai/DeepSeek-V3.2-Thinking) <aider@aider.chat>
This commit is contained in:
@ -62,6 +62,17 @@ class PermissionService:
|
|||||||
def get_role_permissions(role_code):
|
def get_role_permissions(role_code):
|
||||||
"""获取指定角色拥有的所有权限Code"""
|
"""获取指定角色拥有的所有权限Code"""
|
||||||
try:
|
try:
|
||||||
|
# === 新增逻辑:超级管理员上帝模式 ===
|
||||||
|
if role_code == 'SUPER_ADMIN':
|
||||||
|
# 直接获取所有菜单和元素,无视配置表
|
||||||
|
all_menus = [m.code for m in SysMenu.query.all()]
|
||||||
|
all_elements = [e.code for e in SysElement.query.all()]
|
||||||
|
return {
|
||||||
|
'menus': all_menus,
|
||||||
|
'elements': all_elements
|
||||||
|
}
|
||||||
|
# =================================
|
||||||
|
|
||||||
perms = SysRolePermission.query.filter_by(role_code=role_code).all()
|
perms = SysRolePermission.query.filter_by(role_code=role_code).all()
|
||||||
|
|
||||||
menu_codes = []
|
menu_codes = []
|
||||||
@ -135,4 +146,4 @@ class PermissionService:
|
|||||||
raise e
|
raise e
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
session.rollback()
|
session.rollback()
|
||||||
raise e
|
raise e
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import { defineStore } from 'pinia'
|
import { defineStore } from 'pinia'
|
||||||
import { login } from '@/api/auth'
|
import { login } from '@/api/auth'
|
||||||
|
import { getRolePermissions } from '@/api/system/permission'
|
||||||
import { ref } from 'vue'
|
import { ref } from 'vue'
|
||||||
|
|
||||||
export const useUserStore = defineStore('user', () => {
|
export const useUserStore = defineStore('user', () => {
|
||||||
@ -7,6 +8,7 @@ export const useUserStore = defineStore('user', () => {
|
|||||||
const token = ref(localStorage.getItem('token') || '')
|
const token = ref(localStorage.getItem('token') || '')
|
||||||
const role = ref(localStorage.getItem('role') || '')
|
const role = ref(localStorage.getItem('role') || '')
|
||||||
const username = ref(localStorage.getItem('username') || '')
|
const username = ref(localStorage.getItem('username') || '')
|
||||||
|
const permissions = ref<string[]>(JSON.parse(localStorage.getItem('permissions') || '[]'))
|
||||||
|
|
||||||
// 2. Actions
|
// 2. Actions
|
||||||
// 登录逻辑
|
// 登录逻辑
|
||||||
@ -44,6 +46,25 @@ export const useUserStore = defineStore('user', () => {
|
|||||||
// 持久化存储 Token
|
// 持久化存储 Token
|
||||||
localStorage.setItem('token', data.access_token)
|
localStorage.setItem('token', data.access_token)
|
||||||
|
|
||||||
|
// 登录成功后,根据角色获取权限
|
||||||
|
if (role.value) {
|
||||||
|
try {
|
||||||
|
const permRes = await getRolePermissions(role.value)
|
||||||
|
const permData = permRes.data || permRes
|
||||||
|
// 合并 menus 和 elements 两个数组
|
||||||
|
const allPerms = [
|
||||||
|
...(permData.menus || []),
|
||||||
|
...(permData.elements || [])
|
||||||
|
]
|
||||||
|
permissions.value = allPerms
|
||||||
|
localStorage.setItem('permissions', JSON.stringify(allPerms))
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取权限失败:', error)
|
||||||
|
permissions.value = []
|
||||||
|
localStorage.setItem('permissions', '[]')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return true // 返回 true 表示登录成功
|
return true // 返回 true 表示登录成功
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -53,11 +74,13 @@ export const useUserStore = defineStore('user', () => {
|
|||||||
token.value = ''
|
token.value = ''
|
||||||
role.value = ''
|
role.value = ''
|
||||||
username.value = ''
|
username.value = ''
|
||||||
|
permissions.value = []
|
||||||
|
|
||||||
// 2. 清空 LocalStorage (硬盘)
|
// 2. 清空 LocalStorage (硬盘)
|
||||||
localStorage.removeItem('token')
|
localStorage.removeItem('token')
|
||||||
localStorage.removeItem('role')
|
localStorage.removeItem('role')
|
||||||
localStorage.removeItem('username')
|
localStorage.removeItem('username')
|
||||||
|
localStorage.removeItem('permissions')
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. Getters / Helpers
|
// 3. Getters / Helpers
|
||||||
@ -66,12 +89,19 @@ export const useUserStore = defineStore('user', () => {
|
|||||||
return roles.includes(role.value)
|
return roles.includes(role.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 判断当前用户是否拥有某个权限(菜单或元素)
|
||||||
|
const hasPermission = (code: string) => {
|
||||||
|
return permissions.value.includes(code)
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
token,
|
token,
|
||||||
role,
|
role,
|
||||||
username,
|
username,
|
||||||
|
permissions,
|
||||||
handleLogin,
|
handleLogin,
|
||||||
logout,
|
logout,
|
||||||
hasRole
|
hasRole,
|
||||||
|
hasPermission
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@ -214,7 +214,7 @@
|
|||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="操作" min-width="150" fixed="right" align="center">
|
<el-table-column v-if="userStore.hasPermission('operation')" label="操作" min-width="150" fixed="right" align="center">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-button link type="primary" size="small" @click="handleEdit(scope.row)">编辑</el-button>
|
<el-button link type="primary" size="small" @click="handleEdit(scope.row)">编辑</el-button>
|
||||||
<el-button link type="danger" size="small" @click="handleDelete(scope.row)">删除</el-button>
|
<el-button link type="danger" size="small" @click="handleDelete(scope.row)">删除</el-button>
|
||||||
@ -420,6 +420,7 @@ import { ref, reactive, onMounted, nextTick } from 'vue';
|
|||||||
import { Plus, Document, Refresh, Setting, Rank, Camera, Link, Download } from '@element-plus/icons-vue';
|
import { Plus, Document, Refresh, Setting, Rank, Camera, Link, Download } from '@element-plus/icons-vue';
|
||||||
import { ElMessage, ElMessageBox, ElLoading } from 'element-plus';
|
import { ElMessage, ElMessageBox, ElLoading } from 'element-plus';
|
||||||
import type { FormInstance, FormRules } from 'element-plus';
|
import type { FormInstance, FormRules } from 'element-plus';
|
||||||
|
import { useUserStore } from '@/stores/user';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
listMaterialBase,
|
listMaterialBase,
|
||||||
@ -432,6 +433,8 @@ import {
|
|||||||
import { uploadFile, deleteFile } from '@/api/common/upload';
|
import { uploadFile, deleteFile } from '@/api/common/upload';
|
||||||
import WebRtcCamera from '@/components/Camera/WebRtcCamera.vue';
|
import WebRtcCamera from '@/components/Camera/WebRtcCamera.vue';
|
||||||
|
|
||||||
|
const userStore = useUserStore();
|
||||||
|
|
||||||
// --- 类型定义 ---
|
// --- 类型定义 ---
|
||||||
interface MaterialBaseVO {
|
interface MaterialBaseVO {
|
||||||
id: number;
|
id: number;
|
||||||
@ -1043,4 +1046,4 @@ onMounted(() => {
|
|||||||
.long-dropdown .el-select-dropdown__wrap {
|
.long-dropdown .el-select-dropdown__wrap {
|
||||||
max-height: 600px !important; /* 可以根据屏幕大小适当调整 */
|
max-height: 600px !important; /* 可以根据屏幕大小适当调整 */
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
Reference in New Issue
Block a user