diff --git a/backend/controller/menu.py b/backend/controller/menu.py index b97ec60..145f285 100644 --- a/backend/controller/menu.py +++ b/backend/controller/menu.py @@ -1,6 +1,7 @@ from fastapi import Query -from dbhelper.menu import del_menu, get_menus, insert_menu, put_menu +from core.utils import list_to_tree +from dbhelper.menu import del_menu, get_menus, get_tree_menu, insert_menu, put_menu from schemas import ListAll, MenuIn, MenuRead, Response @@ -11,10 +12,9 @@ async def menu_add(data: MenuIn) -> Response[MenuRead]: async def menu_arr( offset: int = Query(default=1, description="偏移量"), limit: int = Query(default=10, description="数量"), -) -> Response[ListAll[list[MenuRead]]]: - skip = (offset - 1) * limit - menus, count = await get_menus(skip, limit) - return Response(data=ListAll(total=count, items=menus)) +) -> Response: + menus = await get_tree_menu() + return Response(data=list_to_tree(menus)) async def menu_del(pk: int) -> Response: diff --git a/backend/controller/role.py b/backend/controller/role.py index c103ccd..4204a5c 100644 --- a/backend/controller/role.py +++ b/backend/controller/role.py @@ -16,7 +16,9 @@ from schemas import ListAll, Response, RoleIn, RoleInfo, RoleMenuIn, RoleQuery, async def role_add(data: RoleIn) -> Response[RoleInfo]: - return Response(data=await new_role(data)) + if result := await new_role(data): + return Response(data=result) + return Response(code=400, msg="菜单不存在") async def role_has_menu(rid: int): diff --git a/backend/controller/user.py b/backend/controller/user.py index 058ac64..5f0ca22 100644 --- a/backend/controller/user.py +++ b/backend/controller/user.py @@ -19,10 +19,10 @@ async def user_add(data: UserAdd) -> Response[UserRead]: """新增用户并分配角色 一步到位""" if await get_user({"username": data.username}) is not None: return Response(code=400, msg="用户名已存在") - roles = data.rids - del data.rids + rids = data.roles + del data.roles data.password = get_password_hash(data.password) - result = await insert_user(data, roles) + result = await insert_user(data, rids) if isinstance(result, int): return Response(code=400, msg=f"角色{result}不存在") return Response(data=result) diff --git a/backend/dbhelper/menu.py b/backend/dbhelper/menu.py index b59c069..5369052 100644 --- a/backend/dbhelper/menu.py +++ b/backend/dbhelper/menu.py @@ -25,7 +25,11 @@ async def get_menus(skip: int, limit: int, kwargs: dict = None): else: kwargs = {} result = MenuModel.filter(status__not=9, **kwargs).all().order_by("-created") - return await result.offset(skip).limit(limit), await result.count() + return await result.offset(skip).limit(limit) + + +async def get_tree_menu(): + return await MenuModel.filter(status__not=9).all().values() async def get_menu(kwargs): diff --git a/backend/dbhelper/role.py b/backend/dbhelper/role.py index 512d6fe..db78eed 100644 --- a/backend/dbhelper/role.py +++ b/backend/dbhelper/role.py @@ -1,6 +1,6 @@ from tortoise import connections -from models import RoleModel +from models import MenuModel, RoleMenuModel, RoleModel from schemas.role import RoleIn @@ -20,7 +20,16 @@ async def get_role_menus(rid: int): async def new_role(role: RoleIn): """新增角色""" - return await RoleModel.create(**role.dict()) + # 校验菜单是否存在 + if not all([await MenuModel.filter(id=mid).first() for mid in role.menus]): + return False + + obj = await RoleModel.create(name=role.name, remark=role.remark) + # 写入菜单 + await RoleMenuModel.bulk_create( + [RoleMenuModel(rid=obj.id, mid=mid) for mid in role.menus] + ) + return obj async def get_roles(skip: int, limit: int, kwargs: dict = None): diff --git a/backend/dbhelper/user.py b/backend/dbhelper/user.py index c0fc401..ce10bb4 100644 --- a/backend/dbhelper/user.py +++ b/backend/dbhelper/user.py @@ -32,19 +32,9 @@ async def get_user_info(user: UserModel): [user.id], ) - # 当前激活角色的按钮权限列表 - perm_result = await db.execute_query_dict( - """ - select m.identifier from sys_role_menu as rm, sys_menu as m where rm.mid = m.id and rm.rid = (?) and - m.identifier not null and m.identifier != "" and rm.status != 9 - """, - [sql_result[0]["id"]], - ) - return { **jsonable_encoder(user), "roles": sql_result, - "permissions": [i["identifier"] for i in perm_result], } @@ -64,7 +54,6 @@ async def get_users(skip: int, limit: int, kwargs: dict = None): else: kwargs = {} result = UserModel.filter(**kwargs).all().order_by("-created") - print(await result.offset(skip).limit(limit)) return await result.offset(skip).limit(limit), await result.count() diff --git a/backend/mini.db b/backend/mini.db index 5bd9955..bdd6874 100644 Binary files a/backend/mini.db and b/backend/mini.db differ diff --git a/backend/mini.db-shm b/backend/mini.db-shm new file mode 100644 index 0000000..dff6755 Binary files /dev/null and b/backend/mini.db-shm differ diff --git a/backend/mini.db-wal b/backend/mini.db-wal new file mode 100644 index 0000000..bc8e865 Binary files /dev/null and b/backend/mini.db-wal differ diff --git a/backend/schemas/role.py b/backend/schemas/role.py index fa11675..0478c99 100644 --- a/backend/schemas/role.py +++ b/backend/schemas/role.py @@ -20,7 +20,7 @@ class RoleBasic(BaseModel): class RoleIn(RoleBasic): - pass + menus: list[int] = Field(..., description="菜单id列表") class RoleRead(RoleBasic, ReadBase): diff --git a/backend/schemas/user.py b/backend/schemas/user.py index d795419..eda3c62 100644 --- a/backend/schemas/user.py +++ b/backend/schemas/user.py @@ -41,7 +41,6 @@ class UserInfo(UserRead): """用户信息模型""" roles: list[UserHasRole] = Field(..., description="用户拥有角色") - permissions: list[str] = Field(..., description="角色拥有的按钮权限标识") class RoleActive(BaseModel): @@ -52,7 +51,7 @@ class RoleActive(BaseModel): class UserAdd(UserIn): """新增用户模型""" - rids: list[RoleActive] = Field(..., description="选择角色列表") + roles: list[RoleActive] = Field(..., description="选择角色列表") class UserQuery(QueryData): diff --git a/frontend/src/stores/menu.js b/frontend/src/stores/menu.js new file mode 100644 index 0000000..e69de29 diff --git a/frontend/src/stores/role.js b/frontend/src/stores/role.js new file mode 100644 index 0000000..e69de29 diff --git a/frontend/src/stores/user.js b/frontend/src/stores/user.js index 38132a0..1604aeb 100644 --- a/frontend/src/stores/user.js +++ b/frontend/src/stores/user.js @@ -3,7 +3,7 @@ import { defineStore } from 'pinia' import { message } from 'ant-design-vue' import router from '@/router' -import { loadRouter, loadDefaultMenu } from '@/utils/loadCpn' +import { loadRouter, getPermissions } from '@/utils/loadCpn' import { getMenus, getUserInfo, login, selectRole } from '@/service/user' export const userStore = defineStore( @@ -12,6 +12,7 @@ export const userStore = defineStore( const token = ref('') const userInfo = ref({}) const userMenus = ref([]) + const permissions = ref([]) const selectKey = ref(null) @@ -26,6 +27,7 @@ export const userStore = defineStore( token.value = '' userInfo.value = {} userMenus.value = [] + permissions.value = [] } /** @@ -41,16 +43,19 @@ export const userStore = defineStore( const menus = await getMenus(info.data.roles[0].id) userMenus.value = menus.data - // 3.1 加载权限 + // 3.1 加载路由权限 loadRouter(menus.data) - // 3.2 默认跳转路由 - const defaultMenu = loadDefaultMenu(menus.data) + // 3.2 加载按钮权限 + const [btnPermissions, firstMenu] = getPermissions(menus.data) + permissions.value = btnPermissions - selectKey.value = [defaultMenu.id] - // 4. 跳转 - if (defaultMenu.path) { - router.push(defaultMenu.path) + // 3.2 默认打开菜单 + selectKey.value = [firstMenu.id] + + // 4. 跳转路由 + if (firstMenu?.path) { + router.push(firstMenu.path) } else { router.push('/main') } @@ -82,6 +87,7 @@ export const userStore = defineStore( accessToken, userInfo, userMenus, + permissions, isLoading, selectKey, $reset, diff --git a/frontend/src/utils/directive.js b/frontend/src/utils/directive.js index fe809a6..9ca1fa1 100644 --- a/frontend/src/utils/directive.js +++ b/frontend/src/utils/directive.js @@ -6,7 +6,7 @@ export default (app) => { mounted(el, binding) { if ( // 是否存在 - userStore().userInfo.permissions.indexOf(binding.value) === -1 + userStore().permissions.indexOf(binding.value) === -1 ) { // 删除元素 el.parentNode && el.parentNode.removeChild(el) diff --git a/frontend/src/utils/loadCpn.js b/frontend/src/utils/loadCpn.js index 1233931..c9cf42d 100644 --- a/frontend/src/utils/loadCpn.js +++ b/frontend/src/utils/loadCpn.js @@ -35,11 +35,26 @@ function loadRouter(menus) { } } -// 默认打开第一个 -function loadDefaultMenu(menus) { - for (const menu of menus) { - return menu.children.find((e) => e.type === 1) +// 获取按钮权限列表,和第一个选中菜单 +function getPermissions(menuArr) { + let arr = [] + let firstMenu = null + + function _forMenu(menus) { + for (const menu of menus) { + if (menu.type === 1 && firstMenu === null) { + firstMenu = menu + } + if (menu.type !== 2 && menu.children) { + _forMenu(menu.children) + } else { + arr.push(menu.identifier) + } + } } + + _forMenu(menuArr) + return [arr.filter((e) => e !== null), firstMenu] } -export { loadIconCpn, loadRouter, loadDefaultMenu } +export { loadIconCpn, loadRouter, getPermissions } diff --git a/frontend/src/views/main/system/menu/menu.vue b/frontend/src/views/main/system/menu/menu.vue index 03b8044..852b872 100644 --- a/frontend/src/views/main/system/menu/menu.vue +++ b/frontend/src/views/main/system/menu/menu.vue @@ -1,13 +1,16 @@