From 8e725d3f78224963b9efc3494f667ab332f94585 Mon Sep 17 00:00:00 2001 From: zy7y <13271962515@163.com> Date: Fri, 16 Sep 2022 17:37:24 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E5=88=87=E6=8D=A2=E8=A7=92=E8=89=B2&?= =?UTF-8?q?=E6=9B=B4=E6=96=B0=E8=A7=92=E8=89=B2=E8=8F=9C=E5=8D=95=E5=9B=9E?= =?UTF-8?q?=E6=98=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/controller/menu.py | 11 +-- backend/controller/role.py | 21 +++-- backend/dbhelper/role.py | 11 ++- backend/dbhelper/user.py | 32 +++++--- backend/mini.db | Bin 45056 -> 45056 bytes backend/mini.db-shm | Bin 32768 -> 0 bytes backend/mini.db-wal | Bin 37112 -> 0 bytes backend/router/url.py | 9 +-- backend/schemas/user.py | 2 +- backend/tests/test_case.py | 77 +++++++------------ frontend/src/main.js | 2 + frontend/src/views/main/system/menu/conf.js | 15 ++++ frontend/src/views/main/system/menu/menu.vue | 50 ++++++++---- frontend/src/views/main/system/role/conf.js | 31 ++++---- frontend/src/views/main/system/role/role.vue | 74 +++++++++++++----- frontend/src/views/main/system/user/user.vue | 7 +- 16 files changed, 201 insertions(+), 141 deletions(-) delete mode 100644 backend/mini.db-shm delete mode 100644 backend/mini.db-wal diff --git a/backend/controller/menu.py b/backend/controller/menu.py index 145f285..09080c7 100644 --- a/backend/controller/menu.py +++ b/backend/controller/menu.py @@ -1,18 +1,13 @@ -from fastapi import Query - 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 +from dbhelper.menu import del_menu, get_tree_menu, insert_menu, put_menu +from schemas import MenuIn, MenuRead, Response async def menu_add(data: MenuIn) -> Response[MenuRead]: return Response(data=await insert_menu(data)) -async def menu_arr( - offset: int = Query(default=1, description="偏移量"), - limit: int = Query(default=10, description="数量"), -) -> Response: +async def menu_arr() -> Response: menus = await get_tree_menu() return Response(data=list_to_tree(menus)) diff --git a/backend/controller/role.py b/backend/controller/role.py index 4204a5c..81abfb5 100644 --- a/backend/controller/role.py +++ b/backend/controller/role.py @@ -3,7 +3,7 @@ import json from fastapi import Query from core.utils import list_to_tree -from dbhelper.relation import role_assigned_menu +from dbhelper.menu import get_menu from dbhelper.role import ( del_role, get_role, @@ -12,7 +12,7 @@ from dbhelper.role import ( new_role, put_role, ) -from schemas import ListAll, Response, RoleIn, RoleInfo, RoleMenuIn, RoleQuery, RoleRead +from schemas import ListAll, Response, RoleIn, RoleInfo, RoleQuery, RoleRead async def role_add(data: RoleIn) -> Response[RoleInfo]: @@ -40,15 +40,6 @@ async def role_arr( return Response(data=ListAll(total=count, items=roles)) -async def assigned_menu(data: RoleMenuIn) -> Response: - """分配菜单给角色""" - if await get_role({"id": data.rid, "status__not": 9}) is None: - return Response(code=400, msg="角色不存在") - if isinstance(await role_assigned_menu(data), int): - return Response(code=400, msg=f"菜单不存在") - return Response() - - async def role_del(pk: int) -> Response: if await del_role(pk) == 0: return Response(code=400, msg="角色不存在") @@ -57,6 +48,14 @@ async def role_del(pk: int) -> Response: async def role_put(pk: int, data: RoleIn) -> Response: """更新角色""" + print(await get_role({"id": pk})) + if await get_role({"id": pk}) is None: + + return Response(code=400, msg="角色不存在") + # 如果不为ture -> 有菜单id不存在 + if not all([await get_menu({"id": mid}) for mid in data.menus]): + return Response(code=400, msg="菜单不存在") + if await put_role(pk, data) == 0: return Response(code=400, msg="角色不存在") return Response() diff --git a/backend/dbhelper/role.py b/backend/dbhelper/role.py index db78eed..3ab6e98 100644 --- a/backend/dbhelper/role.py +++ b/backend/dbhelper/role.py @@ -68,6 +68,11 @@ async def del_role(rid: int): return await RoleModel.filter(id=rid).update(status=9) -async def put_role(pk: int, data): - """更新角色""" - return await RoleModel.filter(id=pk).update(**data.dict()) +async def put_role(pk, data): + """更新角色 菜单""" + await RoleModel.filter(id=pk).update(name=data.name, remark=data.remark) + await RoleMenuModel.filter(rid=pk).update(status=9) + + await RoleMenuModel.bulk_create( + [RoleMenuModel(rid=pk, mid=mid) for mid in data.menus] + ) diff --git a/backend/dbhelper/user.py b/backend/dbhelper/user.py index ce10bb4..cc193f1 100644 --- a/backend/dbhelper/user.py +++ b/backend/dbhelper/user.py @@ -23,11 +23,11 @@ async def get_user_info(user: UserModel): 根据id查用户角色列表 按激活角色倒序显示 """ db = connections.get("default") + # 查角色表 用户角色表中 角色状态 = 1, 关联表中 状态 != 9 为有效角色 sql_result = await db.execute_query_dict( """ - select r.id, r.name, ur.status from sys_role as r - left join sys_user_role as ur on r.id = ur.rid where - ur.uid = (?) and ur.status != 9 and r.status != 9 order by ur.status desc + select r.id, r.name, ur.status from sys_role as r , sys_user_role as ur where r.id = ur.rid and + ur.uid = (?) and r.status = 1 and ur.status !=9 order by ur.status desc """, [user.id], ) @@ -65,7 +65,7 @@ async def insert_user(user, roles): # 创建用户 obj = await UserModel.create(**user.dict()) - + # 已有角色 关联 角色id 和是否选中状态 await UserRoleModel.bulk_create( [UserRoleModel(rid=role.rid, uid=obj.id, status=role.status) for role in roles] ) @@ -81,8 +81,8 @@ async def put_user(uid: int, data: UserPut): """更新用户""" from core.security import get_password_hash - roles = data.rids - del data.rids + roles = data.roles + del data.roles for role in roles: if await get_role({"id": role.rid, "status__not": 9}) is None: return role.rid @@ -96,13 +96,27 @@ async def put_user(uid: int, data: UserPut): # todo 1. 先前有的角色,这次更新成没有 2. 先前没有的角色 这次更新成有, 3. 只更新了状态 db = connections.get("default") - # 1. 先把所有数据做删除 - await db.execute_query_dict( + # 1. 先把用户有的角色做删除 + has_roles = await db.execute_query_dict( """ - update sys_user_role set status = 9 where uid = (?) + select r.id from sys_role as r , sys_user_role as ur where r.id = ur.rid and + ur.uid = (?) and r.status = 1 and ur.status !=9 """, [uid], ) + print(has_roles) + + # 2. 将先有的数据标记 删除 + [ + await db.execute_query_dict( + """ + update sys_user_role set status = 9 where rid = (?) + """, + [role["id"]], + ) + for role in has_roles + ] + # 2. 新增次此更新的数据 await UserRoleModel.bulk_create( [UserRoleModel(uid=uid, **role.dict()) for role in roles] diff --git a/backend/mini.db b/backend/mini.db index bdd6874c10ae4a462e311977890a1d3720d31945..9b5f6120537e2bad9f96576c9b07c0d082ed1aaf 100644 GIT binary patch literal 45056 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 literal 45056 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 diff --git a/backend/router/url.py b/backend/router/url.py index d0d6d51..b7cc7cb 100644 --- a/backend/router/url.py +++ b/backend/router/url.py @@ -5,7 +5,6 @@ from fastapi import Depends, routing from controller.common import about, login from controller.menu import menu_add, menu_arr, menu_del, menu_put from controller.role import ( - assigned_menu, role_add, role_arr, role_del, @@ -122,6 +121,7 @@ class Route(routing.APIRoute): has_perm = {"dependencies": [Depends(check_permissions)]} +# has_perm = {} routes = [ Route.post("/login", endpoint=login, tags=["公共"], summary="登录"), @@ -163,13 +163,6 @@ routes = [ Route.post( "/role/query", endpoint=role_query, tags=["角色管理"], summary="角色条件查询", **has_perm ), - Route.post( - "/role/assigned/menu", - endpoint=assigned_menu, - tags=["角色管理"], - summary="角色分配菜单", - **has_perm - ), # 菜单新增 Route.get("/menu", endpoint=menu_arr, tags=["菜单管理"], summary="菜单列表", **has_perm), Route.post("/menu", endpoint=menu_add, tags=["菜单管理"], summary="菜单新增", **has_perm), diff --git a/backend/schemas/user.py b/backend/schemas/user.py index eda3c62..c28ec43 100644 --- a/backend/schemas/user.py +++ b/backend/schemas/user.py @@ -66,4 +66,4 @@ class UserPut(BaseModel): nickname: str = Field(..., description="用户昵称") password: str = Field(..., description="密码") - rids: list[RoleActive] = Field(..., description="选择角色列表") + roles: list[RoleActive] = Field(..., description="选择角色列表") diff --git a/backend/tests/test_case.py b/backend/tests/test_case.py index 8e68bc3..df7c710 100644 --- a/backend/tests/test_case.py +++ b/backend/tests/test_case.py @@ -3,42 +3,13 @@ import requests as client from core.log import logger from schemas.menu import MenuIn -from schemas.role import RoleIn, RoleMenuIn +from schemas.role import RoleIn from schemas.user import RoleActive, UserAdd base = "http://localhost:8000" - params = [ - # 创建角色 - ("/role", RoleIn(name="super", remark="全部权限").dict()), - ("/role", RoleIn(name="user", remark="用户权限").dict()), - # 创建用户 - ( - "/user", - UserAdd( - username="admin", - nickname="管理员", - password="123456", - rids=[ - RoleActive(rid=1, status=5), - RoleActive(rid=2), - ], - ).dict(), - ), - ( - "/user", - UserAdd( - username="tester", - nickname="测试员", - password="123456", - rids=[ - RoleActive(rid=2, status=5), - ], - ).dict(), - ), # 创建菜单 - # 目录 ( "/menu", MenuIn( # id 1 @@ -252,20 +223,6 @@ params = [ method="POST", ).dict(), ), - ( - "/menu", - MenuIn( - name="分配权限", - meta={"icon": "Delete"}, - path=None, - type=2, - component=None, - pid=4, - identifier="role:assign", - api="/role/assigned/menu", - method="POST", - ).dict(), - ), ( "/menu", MenuIn( @@ -309,17 +266,41 @@ params = [ method="DELETE", ).dict(), ), - # 分配权限 +] + +datas = [ ( - "/role/assigned/menu", - RoleMenuIn(rid=1, menus=[num for num in range(1, 20)]).dict(), + "/role", + RoleIn( + name="super", + remark="全部权限", + menus=[num for num in range(1, len(params) + 1)], + ).dict(), + ), + # 创建用户 + ( + "/user", + UserAdd( + username="admin", + nickname="管理员", + password="123456", + roles=[RoleActive(rid=1, status=5)], + ).dict(), ), - ("/role/assigned/menu", RoleMenuIn(rid=2, menus=[1, 3, 7, 8, 9, 11]).dict()), ] @pytest.mark.parametrize("path, data", params) def test_add_data(path, data): + """注册菜单""" + res = client.post(url=base + path, json=data) + logger.info(res.json()) + assert res.status_code == 200 + + +@pytest.mark.parametrize("path, data", datas) +def test_add_user(path, data): + """添加账号""" res = client.post(url=base + path, json=data) logger.info(res.json()) assert res.status_code == 200 diff --git a/frontend/src/main.js b/frontend/src/main.js index 4c19d62..702cdf6 100644 --- a/frontend/src/main.js +++ b/frontend/src/main.js @@ -11,9 +11,11 @@ import '@/assets/css/base.css' import 'ant-design-vue/dist/antd.css' import hasPermisson from '@/utils/directive' +import { formatTime } from './utils/format' const app = createApp(App) hasPermisson(app) +app.config.globalProperties.$formatTime = (value) => formatTime(value) app.use(store) userStore().loadRoleRouter() diff --git a/frontend/src/views/main/system/menu/conf.js b/frontend/src/views/main/system/menu/conf.js index 4a6d970..0599e8d 100644 --- a/frontend/src/views/main/system/menu/conf.js +++ b/frontend/src/views/main/system/menu/conf.js @@ -65,3 +65,18 @@ export const columns = [ width: 120 } ] + +// 菜单类型映射 +export const menuType = { + 0: '目录', + 1: '菜单', + 2: '按钮' +} + +// 请求方法颜色映射 +export const methodColor = { + GET: '#61AFFE', + POST: '#49CC90', + DELETE: '#F93E3E', + PUT: '#FCA130' +} diff --git a/frontend/src/views/main/system/menu/menu.vue b/frontend/src/views/main/system/menu/menu.vue index 852b872..c613f0a 100644 --- a/frontend/src/views/main/system/menu/menu.vue +++ b/frontend/src/views/main/system/menu/menu.vue @@ -2,8 +2,7 @@ import { ref } from 'vue' import { PlusOutlined } from '@ant-design/icons-vue' -import { columns } from './conf' -import { formatTime } from '@/utils/format' +import { columns, menuType, methodColor } from './conf' import { loadIconCpn } from '@/utils/loadCpn' import { getMenus } from '@/service/menu' @@ -14,23 +13,36 @@ getMenus().then((res) => (dataSource.value = res.data)) // 菜单类型隐射 -const menuType = { - 0: '目录', - 1: '菜单', - 2: '按钮' -} +// 展开行 https://blog.csdn.net/weixin_52691965/article/details/120494451 +const expandedRowKeys = ref([]) -const methodColor = { - GET: '#61AFFE', - POST: '#49CC90', - DELETE: '#F93E3E', - PUT: '#FCA130' +const zi = (expanded, record) => { + if (expandedRowKeys.value.length > 0) { + let index = expandedRowKeys.value.indexOf(record.id) + if (index > -1) { + expandedRowKeys.value.splice(index, 1) + } else { + expandedRowKeys.value.splice(0, expandedRowKeys.value.length) + expandedRowKeys.value.push(record.id) + } + } else { + expandedRowKeys.value.push(record.id) + } } // const addClick = () => { console.log('点击') } + +// +const putClick = () => { + console.log('点击') +} + +const delClick = () => { + console.log('点击') +}