5-1 路由表
src/routes/roleAccess.ts
import Router from '@koa/router'
import {
addRoleAccessController,
getRoleAccessController,
getAccessByRolesController
} from '../controller/roleAccess'
const router = new Router({
prefix: '/api/role_access'
})
/**
* 添加菜单与角色关联
* post /api/role_access'
*/
router.post('/:id', async ctx => {
const { id } = ctx.params
const { access } = ctx.request.body
ctx.body = await addRoleAccessController(Number(id), access)
})
/**
* 根据角色id获取关联菜单id
* post /api/role_access'
*/
router.get('/:id', async ctx => {
const { id } = ctx.params
ctx.body = await getRoleAccessController(Number(id))
})
router.post('/role/access', async ctx => {
const { roles } = ctx.request.body
const ids = (roles as string[]).map(Number)
ctx.body = await getAccessByRolesController(ids)
// ctx.body = typeof roles
})
export default router
5-2 角色与菜单controller
src/controller/roleAccess.ts
import {
createRoleAccess,
destroyRoleAccessByRoleID,
getRoleAccessByID,
getAccessByRolesService
} from '../services/roleAccess'
import { SuccessResponse, createErrorResponse } from '../utils/Response';
import errorInfo from '../constants/errorInfo'
const {
allocRoleAccessFailInfo,
getRoleAccessFailInfo
} = errorInfo
export const addRoleAccessController = async (id: number, access: number[]) => {
// 先移除之前该角色关联记录
await destroyRoleAccessByRoleID(id)
try {
// 批量插入记录
await createRoleAccess(id, access)
return new SuccessResponse(null, '权限分配成功')
} catch (error) {
console.error(error)
return createErrorResponse(allocRoleAccessFailInfo)
}
}
export const getRoleAccessController = async (id: number) => {
try {
// 批量插入记录
const result = await getRoleAccessByID(id)
return new SuccessResponse(result)
} catch (error) {
return createErrorResponse(getRoleAccessFailInfo)
}
}
export const getAccessByRolesController = async (roles: number[]) => {
try {
// 批量插入记录
const result = await getAccessByRolesService(roles)
return new SuccessResponse(result)
} catch (error) {
return createErrorResponse(getRoleAccessFailInfo)
}
}
5-3 角色与菜单service
import { AccessModel, RoleAccessModel, RolesModel } from '../db/models'
import Sequelize from 'sequelize'
import { AccessRole } from './types'
const Op = Sequelize.Op
/**
* 删除与该角色相关联记录
* @param id 角色id
*/
export const destroyRoleAccessByRoleID = async (id: number) => {
const result = await RoleAccessModel.destroy({
where: {
role_id: id
}
})
return result
}
/**
* 添加与该角色相关联记录
* @param id 角色id
* @param access 菜单id列表
*/
export const createRoleAccess = async (id: number, access: number[]) => {
const records = access.map(aid => ({
role_id: id,
access_id: aid
}))
// 批量插入
const result = await RoleAccessModel.bulkCreate(records)
return result
}
/**
* 获取与该角色相关联记录
* @param id 角色id
*/
export const getRoleAccessByID = async (id: number) => {
const result = await RoleAccessModel.findAll({
attributes: ['id', 'role_id', 'access_id'],
where: {
role_id: id
}
})
return result
}
export const getAccessByRolesService = async (roles: number[]) => {
const { rows } = await AccessModel.findAndCountAll({
// https://blog.csdn.net/Tirst_/article/details/109677451
distinct: true, // 去重 解决findAndCountAll联表查询时 count数不准确问题解决
order: [
['sort_id', 'ASC']
],
include: [
{
model: RoleAccessModel,
attributes: ['id'],
where: {
// [Op.or]: whereProps,
role_id: {
[Op.in]: roles
}
},
include: [
{
model: RolesModel,
attributes: ['id', 'name', 'description']
}
]
}
]
})
const access = rows.map(row => {
const ac = row.toJSON() as AccessRole
ac.roles = ac.RoleAccesses?.map(item => item.Role)
delete ac.RoleAccesses
return ac
})
return {
access
}
}
service下类型文件
src/services/types.ts
import { UserModelProps } from '../db/models/user'
import { AccessModelProps } from '../db/models/access';
export interface UserWhereProps {
username: string;
password?: string;
id?: number;
}
interface Role {
id: number;
name: string;
description: string;
}
interface UserRole {
id: number,
Role: Role
}
// 根据用户id 获取用户以及角色信息
export type UserInfo = UserModelProps & {
UserRoles?: UserRole[];
roles?: Role[];
}
// 根据角色id获取资源
export type AccessRole = AccessModelProps & {
RoleAccesses?: UserRole[];
roles?: Role[];
}