fix: 添加角色增加菜单id”

This commit is contained in:
zy7y 2022-09-16 11:52:08 +08:00
parent 65f1d7d2bc
commit 7ba3f23684
20 changed files with 106 additions and 49 deletions

View File

@ -1,6 +1,7 @@
from fastapi import Query 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 from schemas import ListAll, MenuIn, MenuRead, Response
@ -11,10 +12,9 @@ async def menu_add(data: MenuIn) -> Response[MenuRead]:
async def menu_arr( async def menu_arr(
offset: int = Query(default=1, description="偏移量"), offset: int = Query(default=1, description="偏移量"),
limit: int = Query(default=10, description="数量"), limit: int = Query(default=10, description="数量"),
) -> Response[ListAll[list[MenuRead]]]: ) -> Response:
skip = (offset - 1) * limit menus = await get_tree_menu()
menus, count = await get_menus(skip, limit) return Response(data=list_to_tree(menus))
return Response(data=ListAll(total=count, items=menus))
async def menu_del(pk: int) -> Response: async def menu_del(pk: int) -> Response:

View File

@ -16,7 +16,9 @@ from schemas import ListAll, Response, RoleIn, RoleInfo, RoleMenuIn, RoleQuery,
async def role_add(data: RoleIn) -> Response[RoleInfo]: 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): async def role_has_menu(rid: int):

View File

@ -19,10 +19,10 @@ async def user_add(data: UserAdd) -> Response[UserRead]:
"""新增用户并分配角色 一步到位""" """新增用户并分配角色 一步到位"""
if await get_user({"username": data.username}) is not None: if await get_user({"username": data.username}) is not None:
return Response(code=400, msg="用户名已存在") return Response(code=400, msg="用户名已存在")
roles = data.rids rids = data.roles
del data.rids del data.roles
data.password = get_password_hash(data.password) data.password = get_password_hash(data.password)
result = await insert_user(data, roles) result = await insert_user(data, rids)
if isinstance(result, int): if isinstance(result, int):
return Response(code=400, msg=f"角色{result}不存在") return Response(code=400, msg=f"角色{result}不存在")
return Response(data=result) return Response(data=result)

View File

@ -25,7 +25,11 @@ async def get_menus(skip: int, limit: int, kwargs: dict = None):
else: else:
kwargs = {} kwargs = {}
result = MenuModel.filter(status__not=9, **kwargs).all().order_by("-created") 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): async def get_menu(kwargs):

View File

@ -1,6 +1,6 @@
from tortoise import connections from tortoise import connections
from models import RoleModel from models import MenuModel, RoleMenuModel, RoleModel
from schemas.role import RoleIn from schemas.role import RoleIn
@ -20,7 +20,16 @@ async def get_role_menus(rid: int):
async def new_role(role: RoleIn): 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): async def get_roles(skip: int, limit: int, kwargs: dict = None):

View File

@ -32,19 +32,9 @@ async def get_user_info(user: UserModel):
[user.id], [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 { return {
**jsonable_encoder(user), **jsonable_encoder(user),
"roles": sql_result, "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: else:
kwargs = {} kwargs = {}
result = UserModel.filter(**kwargs).all().order_by("-created") 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() return await result.offset(skip).limit(limit), await result.count()

Binary file not shown.

BIN
backend/mini.db-shm Normal file

Binary file not shown.

BIN
backend/mini.db-wal Normal file

Binary file not shown.

View File

@ -20,7 +20,7 @@ class RoleBasic(BaseModel):
class RoleIn(RoleBasic): class RoleIn(RoleBasic):
pass menus: list[int] = Field(..., description="菜单id列表")
class RoleRead(RoleBasic, ReadBase): class RoleRead(RoleBasic, ReadBase):

View File

@ -41,7 +41,6 @@ class UserInfo(UserRead):
"""用户信息模型""" """用户信息模型"""
roles: list[UserHasRole] = Field(..., description="用户拥有角色") roles: list[UserHasRole] = Field(..., description="用户拥有角色")
permissions: list[str] = Field(..., description="角色拥有的按钮权限标识")
class RoleActive(BaseModel): class RoleActive(BaseModel):
@ -52,7 +51,7 @@ class RoleActive(BaseModel):
class UserAdd(UserIn): class UserAdd(UserIn):
"""新增用户模型""" """新增用户模型"""
rids: list[RoleActive] = Field(..., description="选择角色列表") roles: list[RoleActive] = Field(..., description="选择角色列表")
class UserQuery(QueryData): class UserQuery(QueryData):

View File

View File

View File

@ -3,7 +3,7 @@ import { defineStore } from 'pinia'
import { message } from 'ant-design-vue' import { message } from 'ant-design-vue'
import router from '@/router' import router from '@/router'
import { loadRouter, loadDefaultMenu } from '@/utils/loadCpn' import { loadRouter, getPermissions } from '@/utils/loadCpn'
import { getMenus, getUserInfo, login, selectRole } from '@/service/user' import { getMenus, getUserInfo, login, selectRole } from '@/service/user'
export const userStore = defineStore( export const userStore = defineStore(
@ -12,6 +12,7 @@ export const userStore = defineStore(
const token = ref('') const token = ref('')
const userInfo = ref({}) const userInfo = ref({})
const userMenus = ref([]) const userMenus = ref([])
const permissions = ref([])
const selectKey = ref(null) const selectKey = ref(null)
@ -26,6 +27,7 @@ export const userStore = defineStore(
token.value = '' token.value = ''
userInfo.value = {} userInfo.value = {}
userMenus.value = [] userMenus.value = []
permissions.value = []
} }
/** /**
@ -41,16 +43,19 @@ export const userStore = defineStore(
const menus = await getMenus(info.data.roles[0].id) const menus = await getMenus(info.data.roles[0].id)
userMenus.value = menus.data userMenus.value = menus.data
// 3.1 加载权限 // 3.1 加载路由权限
loadRouter(menus.data) loadRouter(menus.data)
// 3.2 默认跳转路由 // 3.2 加载按钮权限
const defaultMenu = loadDefaultMenu(menus.data) const [btnPermissions, firstMenu] = getPermissions(menus.data)
permissions.value = btnPermissions
selectKey.value = [defaultMenu.id] // 3.2 默认打开菜单
// 4. 跳转 selectKey.value = [firstMenu.id]
if (defaultMenu.path) {
router.push(defaultMenu.path) // 4. 跳转路由
if (firstMenu?.path) {
router.push(firstMenu.path)
} else { } else {
router.push('/main') router.push('/main')
} }
@ -82,6 +87,7 @@ export const userStore = defineStore(
accessToken, accessToken,
userInfo, userInfo,
userMenus, userMenus,
permissions,
isLoading, isLoading,
selectKey, selectKey,
$reset, $reset,

View File

@ -6,7 +6,7 @@ export default (app) => {
mounted(el, binding) { mounted(el, binding) {
if ( if (
// 是否存在 // 是否存在
userStore().userInfo.permissions.indexOf(binding.value) === -1 userStore().permissions.indexOf(binding.value) === -1
) { ) {
// 删除元素 // 删除元素
el.parentNode && el.parentNode.removeChild(el) el.parentNode && el.parentNode.removeChild(el)

View File

@ -35,11 +35,26 @@ function loadRouter(menus) {
} }
} }
// 默认打开第一个 // 获取按钮权限列表,和第一个选中菜单
function loadDefaultMenu(menus) { function getPermissions(menuArr) {
let arr = []
let firstMenu = null
function _forMenu(menus) {
for (const menu of menus) { for (const menu of menus) {
return menu.children.find((e) => e.type === 1) if (menu.type === 1 && firstMenu === null) {
firstMenu = menu
}
if (menu.type !== 2 && menu.children) {
_forMenu(menu.children)
} else {
arr.push(menu.identifier)
}
} }
} }
export { loadIconCpn, loadRouter, loadDefaultMenu } _forMenu(menuArr)
return [arr.filter((e) => e !== null), firstMenu]
}
export { loadIconCpn, loadRouter, getPermissions }

View File

@ -1,13 +1,16 @@
<script setup> <script setup>
import { ref } from 'vue'
import { PlusOutlined } from '@ant-design/icons-vue' import { PlusOutlined } from '@ant-design/icons-vue'
import { columns } from './conf' import { columns } from './conf'
import { formatTime } from '@/utils/format' import { formatTime } from '@/utils/format'
import { userStore } from '@/stores/user'
import { loadIconCpn } from '@/utils/loadCpn' import { loadIconCpn } from '@/utils/loadCpn'
import { getMenus } from '@/service/menu'
// //
const dataSource = userStore().userMenus const dataSource = ref([])
getMenus().then((res) => (dataSource.value = res.data))
// //

View File

@ -44,6 +44,7 @@ export const addRoleRules = [
remark: [ remark: [
{ required: true, message: '请输入描述', trigger: 'blur' }, { required: true, message: '请输入描述', trigger: 'blur' },
{ min: 1, max: 20, message: '1~20', trigger: 'blur' } { min: 1, max: 20, message: '1~20', trigger: 'blur' }
] ],
menus: [{ required: true, message: '请选择菜单', trigger: 'blur' }]
} }
] ]

View File

@ -4,6 +4,7 @@ import { ref, reactive, onMounted } from 'vue'
import { PlusOutlined } from '@ant-design/icons-vue' import { PlusOutlined } from '@ant-design/icons-vue'
import { getRoles, queryRole, delRole, putRole, addRole } from '@/service/role' import { getRoles, queryRole, delRole, putRole, addRole } from '@/service/role'
import { getMenus } from '@/service/menu'
import { columns, addRoleRules } from './conf' import { columns, addRoleRules } from './conf'
import { formatTime } from '@/utils/format' import { formatTime } from '@/utils/format'
import { message } from 'ant-design-vue' import { message } from 'ant-design-vue'
@ -81,17 +82,22 @@ const addVisible = ref(false)
const formRef = ref(null) const formRef = ref(null)
const newRoleForm = reactive({ const newRoleForm = reactive({
name: '', name: '',
remark: '' remark: '',
menus: []
}) })
const addClick = () => { const addClick = () => {
addVisible.value = !addVisible.value addVisible.value = !addVisible.value
// modal
getMenus().then((res) => (treeData.value = res.data))
} }
// modal // modal
const onOk = () => { const onOk = () => {
formRef.value.validateFields().then(() => { formRef.value.validateFields().then(() => {
// //
console.log(newRoleForm.menus)
newRoleForm.menus = newRoleForm.menus.map((e) => e.id)
addRole(newRoleForm).then((res) => { addRole(newRoleForm).then((res) => {
if (res.msg === '请求成功') { if (res.msg === '请求成功') {
message.success('新增成功') message.success('新增成功')
@ -116,10 +122,14 @@ const onCancel = () => {
const putClick = (record) => { const putClick = (record) => {
// modal // modal
getMenus().then((res) => (treeData.value = res.data))
putVisible.value = !putVisible.value putVisible.value = !putVisible.value
putId.value = record.id putId.value = record.id
putRoleForm.name = record.name putRoleForm.name = record.name
putRoleForm.remark = record.remark putRoleForm.remark = record.remark
console.log(record)
} }
const putVisible = ref(false) const putVisible = ref(false)
@ -127,7 +137,8 @@ const putVisible = ref(false)
const putRoleFormRef = ref() const putRoleFormRef = ref()
const putRoleForm = reactive({ const putRoleForm = reactive({
name: '', name: '',
remark: '' remark: '',
menus: []
}) })
const putId = ref() const putId = ref()
@ -153,6 +164,15 @@ const onOkPut = () => {
const onCancelPut = () => { const onCancelPut = () => {
putRoleFormRef.value.resetFields() putRoleFormRef.value.resetFields()
} }
// tree
const treeData = ref()
//
const check = (key, { checkedNodesPositions }) => {
// console.log(checkedNodesPositions)
newRoleForm.menus = checkedNodesPositions.map((e) => ({ key: e.pos, id: e.node.id }))
}
</script> </script>
<template> <template>
@ -172,7 +192,7 @@ const onCancelPut = () => {
<!-- 列表 --> <!-- 列表 -->
<div class="data"> <div class="data">
<a-card title="用户列表" <a-card title="角色列表"
><template #extra> ><template #extra>
<a-button type="primary" v-per="'role:create'" @click="addClick"> <a-button type="primary" v-per="'role:create'" @click="addClick">
<template #icon><plus-outlined /></template> <template #icon><plus-outlined /></template>
@ -229,6 +249,11 @@ const onCancelPut = () => {
<a-form-item name="remark" label="描述"> <a-form-item name="remark" label="描述">
<a-input v-model:value="newRoleForm.remark" /> <a-input v-model:value="newRoleForm.remark" />
</a-form-item> </a-form-item>
<a-form-item name="menus" label="菜单">
<a-tree checkable :tree-data="treeData" @check="check">
<template #title="{ name }"> {{ name }} </template>
</a-tree>
</a-form-item>
</a-form> </a-form>
</a-modal> </a-modal>
@ -248,6 +273,11 @@ const onCancelPut = () => {
<a-form-item name="remark" label="描述"> <a-form-item name="remark" label="描述">
<a-input v-model:value="putRoleForm.remark" /> <a-input v-model:value="putRoleForm.remark" />
</a-form-item> </a-form-item>
<a-form-item name="menus" label="菜单">
<a-tree checkable :tree-data="treeData" @check="check">
<template #title="{ name }"> {{ name }} </template>
</a-tree>
</a-form-item>
</a-form> </a-form>
</a-modal> </a-modal>
</div> </div>

View File

@ -106,9 +106,8 @@ const addClick = () => {
const onOk = () => { const onOk = () => {
formRef.value.validateFields().then(() => { formRef.value.validateFields().then(() => {
// //
const { username, nickname, password, roles } = newUserForm newUserForm.roles = newUserForm.roles.map((e, i) => ({ rid: e, status: i === 0 ? 5 : 1 }))
let rids = roles.map((e, i) => ({ rid: e, status: i === 0 ? 5 : 1 })) addUser(newUserForm).then((res) => {
addUser({ username, nickname, password, rids }).then((res) => {
if (res.msg === '请求成功') { if (res.msg === '请求成功') {
message.success('新增成功') message.success('新增成功')
// 1. modal // 1. modal