From 7ba3f23684b64e564ef0ab7045d96726e0a40440 Mon Sep 17 00:00:00 2001 From: zy7y <13271962515@163.com> Date: Fri, 16 Sep 2022 11:52:08 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E6=B7=BB=E5=8A=A0=E8=A7=92=E8=89=B2?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E8=8F=9C=E5=8D=95id=E2=80=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/controller/menu.py | 10 +++--- backend/controller/role.py | 4 ++- backend/controller/user.py | 6 ++-- backend/dbhelper/menu.py | 6 +++- backend/dbhelper/role.py | 13 +++++-- backend/dbhelper/user.py | 11 ------ backend/mini.db | Bin 45056 -> 45056 bytes backend/mini.db-shm | Bin 0 -> 32768 bytes backend/mini.db-wal | Bin 0 -> 37112 bytes backend/schemas/role.py | 2 +- backend/schemas/user.py | 3 +- frontend/src/stores/menu.js | 0 frontend/src/stores/role.js | 0 frontend/src/stores/user.js | 22 +++++++----- frontend/src/utils/directive.js | 2 +- frontend/src/utils/loadCpn.js | 25 ++++++++++--- frontend/src/views/main/system/menu/menu.vue | 7 ++-- frontend/src/views/main/system/role/conf.js | 3 +- frontend/src/views/main/system/role/role.vue | 36 +++++++++++++++++-- frontend/src/views/main/system/user/user.vue | 5 ++- 20 files changed, 106 insertions(+), 49 deletions(-) create mode 100644 backend/mini.db-shm create mode 100644 backend/mini.db-wal create mode 100644 frontend/src/stores/menu.js create mode 100644 frontend/src/stores/role.js 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 5bd99555016972d85659a2fa507bb2e3629619e8..bdd6874c10ae4a462e311977890a1d3720d31945 100644 GIT binary patch delta 2103 zcmb7FU1%It6rR6LGP`s45@K2QL5&cpBAwo!xi>R|sBIdP4%tmhY_=(4Ns}d{ZniO- zsCmg`-$X=;3)P3nzNLtWVj!gWU>}519}1;HUiwg>KbGc61Rs3RyED5byECB(%iP`l z&VKhh=X~ev`aNa+p7O)(qerz~RXr?MRx9UMD#fMqOP5N;q$Ei|Z+x{-EUy@{`h0*l zAn+s7&gu!?SS485i+mM!?tG$!EEiWm0F*V%B~>|LKL108A++xl};c z*GY$6%1p!uiH-KtJ!OmFLYkl(Nd|NPw6gKTbcy3K%d~8pAsWXQ#dCVBFcCbm09 zSuPIBW^){?E`npx1Uiuj*s@uI{QaiGqIlTE4k1n~T@?Rgz53vb@5AT2TEP0^%k3$l zzzPmSwi8pqSE(Bfc>L{G4|gs<+WhI!)y;<+U*ErW`N7U7TYKe0GK3c;4fIK%FMTKd zCiqUwkP1@OjI1|?D08@4`?;Q}edgPmXeq7z;=k@!p%#LfYNB14NQa5u+Kl41nP{0f zikGIvYzL14a$x|Iftl0eZ+rIa%;~}<=bef9A@V`KU=}C6p%df7C-Nt~74Dy+Qxg^E z6q_0^mxjE>`9*8B+N%bVve|Y?*tLkun8_TQ(wI4j#i>PFucjz8MV4nTR?ZwB8!n%H z#XCNCw(!xhxfOfbux|US4a(JiOc)MJzEEkuQ9yOy+&o0cD0r*Br8fyx8 z4!j5Z)1Ri_0Dl_4!fjYG){dIw}05>+Ob#{^VJ>C+0TDw37)n)KO#+ z61AQ$_CJXPBs5QqZ5&zCrw+FmiQ58ETyTkDjkX{(n9EF#k%R0gS<8X@aYco~HetPL z*XwW9`s+DA+|F`m+6On~fSx2q!@c}JnMCy>S1FDE>m=Nf;6Lyd{0rWI*Wn(#5AVX? y;EwS41|03yWLefgvP;v2IrZRBdJ>wh%iSTC=xUyc;8YbYI2A<=gB48#>;D0K-^2|7 delta 236 zcmZp8z|`=7X~RW*eI`L>W_8Bm%HsIa;?$z}qWqjxW(EcZUQUouZfagB4kR0$Dw7Dh%!CMIS! N7ETb&!otbP2>_nZKkEPh diff --git a/backend/mini.db-shm b/backend/mini.db-shm new file mode 100644 index 0000000000000000000000000000000000000000..dff675523465ab679d927b75e91d5b4d5524e09d GIT binary patch literal 32768 zcmeI*%LxK86a~=u|AK-W3vee2g6^gYTd)PO5W5lWz^xV7f_pWA5yYKK&AIT%WEeu; zDd5fcIt#B~!wqE${Esb1hb@ zTpMw1#_E>)w5B@=0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FqgD0+l#(C`}v^0t5&U z$VZ@_Ppdj5@F9@qD++-;1*&0V1dX3@e+Zk@j?U>qruQcBJ=^}sfqf{H`{G@W)?5A(S)1{ z?dk5B{m+@-Og3fD|2r)|oqaAf@KaAJ)sgbI+kaP1K3qCs?3&Azw~k+3M4n2|etw0! zDy@CF<6a3(q%!DW3SCDZqp#68`4KiC00e*l5C8%|00;m9AOHk_01yBIK;XY8P|T$7 zVn(-&uG#q5x{)>OM>cHg6}j|$`jr2uB(n8Kn?^@Aa>aCgcmEN6O@Y)b@xFq;yU5h{ z_T^-f%8@T&`tySMouA|vzq)WtB2UV~Qz>)^RpqPlYqBH#BJGog#XrPxajn=ZoFPfr zfB+Bx0zd!=00AHX1b_e#NJyY6=TdyNS}I``;{nwf(5!w{ca5^EsftxLw6eZXRb5q$ z&zqWM1bGeXGGfBTia zJ6AGPxI0EzQ?Ox`?eP8H5N^(oZhCxVOH3iujx;MUm)Sz zJG>kS00AHX1b_e#00KY&2mk>f00e+Qdk94R0)1`u3uOE|BW*jPnCLnzd&F9 z?i4zP)}saTck=740Kgl2DSMpN+!~7HE zWv~GOAOHk_01yBIw>W`HAMIK&Orzg2-Qm<#()7bvjqT=;4rnMZXDjn=Dy98})J$Gx zE4^WY*b+$>V(<`<~spxgINvXp_ZBjyBU{y#?T=oK&LUJX^ z3;YSml|(P_CL~u9yug-_T&ds%zJ%mTycbv!k}KuCz>bhyDdz=Fgyc$DFK{6wSIT&S z^&q(t=LI%{8bn{AN6}fd8hwQBM<>zyXc)bN4xM$ef00e*l5C8%|00;m9AOHj?fgHy$Ojhork(KAsD6qXW@@x-{dA6Iz96OiB zG~1Qsc!pu;WI2XsN+lXPJ838uY3S&n0U;V>nFdLsK@@2a1R4qj8hDf00e*l5C8%|00;m9AkaPnL!=?kRI3a#)AytnBr^4YtWw8hJ+={E zINc&Iaen)oXz_fe;b5WrVqy#;GYo8-tnUsPhg#%4(u@r$1r8OmPTW+8|47rr3;SE- z>kZ;rr`KY~M#(MmERxTsDr6kRtPXLD>Kjrm@VrWYR7UVNzWB`*3a+z#BW@t>a9E~hX<_q{c2lEB~1Q89q1ONa4 literal 0 HcmV?d00001 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 @@