1-1 用户路由表
src/routes/user.ts
import Router from '@koa/router'import {getAllUserController,updateUserController,allocUserRoleController,removeUserController} from '../controller/user'const router = new Router({prefix: '/api/user'})/*** 获取用户列表* get /api/user*/router.get('/', async ctx => {const { pageNum = 0, pageSize = 10, ...query } = ctx.request.queryctx.body = await getAllUserController({offset: Number(pageNum),limit: Number(pageSize),query})})/*** 编辑用户* post /api/user/:id*/router.put('/:id', async ctx => {const { id } = ctx.paramsctx.body = await updateUserController(Number(id), ctx.request.body)})/*** 给用户分配角色* post /api/user/role/:id*/router.post('/role/:id', async ctx => {const { id } = ctx.paramsconst { roles } = ctx.request.bodyctx.body = await allocUserRoleController(Number(id), roles)})/*** 删除用户* delete /api/user/:id*/router.delete('/:id', async ctx => {const { id } = ctx.paramsctx.body = await removeUserController(Number(id))})export default router
1-2 用户controller
src/controller/user.ts
import {getAllUserService,updateUserService,allocUserRoleService,destroyUserRoleByUserID,removeUserService} from '../services/user'import { createErrorResponse, SuccessResponse } from '../utils/Response'import errorInfo from '../constants/errorInfo'import { RegisterModel } from '../db/models/user'import { getUserInfo } from '../services/auth'import { RegisterPropsWithRoles } from './types'const {updateUserExistFailInfo,getUserListFailInfo,allocUserRoleFailInfo,deleteUserInfoFailInfo} = errorInfo// 获取全部菜单export interface WhereQuery {name: string;status: number;mobile: string;}export interface UserListParams {offset: number;limit: number;query: Record<string, any>;}// 获取全部用户列表export const getAllUserController = async ({ offset, limit, query }: UserListParams) => {try {const result = await getAllUserService(offset, limit, query)return new SuccessResponse(result)} catch (error) {console.error(error.message)return createErrorResponse(getUserListFailInfo)}}// 更改用户信息export const updateUserController = async (id: number, data: RegisterPropsWithRoles) => {const {username,email,mobile,description,status,roleIds,} = dataconsole.log('roleIds',roleIds)// 判断修改后的用户名是否已经存在其他重名用户const userInfo = await getUserInfo({ username })if (userInfo && userInfo.id !== id) {return createErrorResponse(updateUserExistFailInfo)}try {await updateUserService(id, {username,email,mobile,description,status} as RegisterModel)await allocUserRoleController(id, roleIds)return new SuccessResponse(null, '用户信息修改成功')} catch (error) {console.error(error.message)return createErrorResponse(getUserListFailInfo)}}// 分配用户角色export const allocUserRoleController = async (id: number, roles: number[] = []) => {// 移除之前该用户与角色记录await destroyUserRoleByUserID(id)try {await allocUserRoleService(id, roles)return new SuccessResponse(null, '用户角色分配成功')} catch (error) {console.error(error.message)return createErrorResponse(allocUserRoleFailInfo)}}// 删除用户export const removeUserController = async (id: number) => {try {await removeUserService(id)return new SuccessResponse(null, '用户删除成功')} catch (error) {console.error(error.message)return createErrorResponse(deleteUserInfoFailInfo)}}
1-3 用户services
src/services/user.ts
import { UserInfo } from './types'import { RolesModel, UserModel, UserRoleModel } from '../db/models'import { RegisterModel } from '../db/models/user'// 获取全部用户export const getAllUserService = async (offset = 0, limit = 10, query: Record<string, any>) => {const whereProps = {} as Record<string, any>// 检索条件处理if (query.mobile) {whereProps.mobile = query.mobile}if (query.username) {whereProps.username = query.username}if (!isNaN(query.status)) {whereProps.status = Number(query.status)}const { count, rows } = await UserModel.findAndCountAll({attributes: ['id', 'username', 'email', 'mobile', 'isSuper', 'status', 'avatar', 'description', 'createdAt'],where: whereProps,limit,offset: limit * offset,// https://blog.csdn.net/Tirst_/article/details/109677451distinct: true, //去重 解决findAndCountAll联表查询时 count数不准确问题解决include: [ // 联表查询{model: UserRoleModel,attributes: ['id'],include: [{model: RolesModel,attributes: ['id', 'name', 'description']}]}]})// 数据格式化const users = rows.map(row => {const user = row.toJSON() as UserInfouser.roles = user.UserRoles?.map(item => item.Role)delete user.UserRolesreturn user})return {users,count}}// 修改用户export const updateUserService = async (id: number, data: RegisterModel) => {const result = await UserModel.update(data, {where: {id}})return result}/*** 删除与该用户相关联记录* @param id 角色id*/export const destroyUserRoleByUserID = async (id: number) => {const result = await UserRoleModel.destroy({where: {user_id: id}})return result}// 分配用户角色export const allocUserRoleService = async (id: number, data: number[]) => {const roles = data.map(rid => ({user_id: id,role_id: rid}))const result = await UserRoleModel.bulkCreate(roles)return result}// 根据用户id删除用户export const removeUserService = async (id: number) => {const result = await UserModel.destroy({where: {id}})return result}
1-4 auth services
src/services/auth.ts
import UserModel, { RegisterModel, UserModelProps } from '../db/models/user'import { UserWhereProps } from './types'import { createMd5 } from '../utils/createMD5'import { RolesModel, UserRoleModel } from '../db/models'import { UserInfo } from './types'/*** 创建用户*/export const createUser = async ({ username, password, email, mobile, status, avatar }: RegisterModel): Promise<UserModelProps> => {const result = await UserModel.create({username,password,email,mobile,status})return result.toJSON() as UserModelProps}/*** 根据用户名 获取用户信息* @param username 用户名* @param password 密码* @param id 用户id* @returns 用户信息*/export const getUserInfo = async ({ username, password, id }: UserWhereProps): Promise<UserModelProps | null> => {const where: UserWhereProps = {username}if (password) {where.password = createMd5(password)}if (typeof id != 'undefined') {where.id = id}const result = await UserModel.findOne({attributes: {exclude: ['password', 'createdAt', 'updatedAt']},where,})if (result == null) return nullreturn result.toJSON() as UserModelProps}// 获取用户信息 包含 角色信息export const getUserInfoAndRoles = async (id: number) => {const result = await UserModel.findOne({attributes: ['id', 'username', 'email', 'mobile', 'isSuper', 'status', 'avatar', 'description'],where: {id},include: [ // 联表查询{model: UserRoleModel,attributes: ['id'],include: [{model: RolesModel,attributes: ['id', 'name', 'description']}]}]})if (!result) return nullconst user = result.toJSON() as UserInfouser.roles = user.UserRoles?.map(item => item.Role)delete user.UserRolesreturn user}
1-5 user model
src/db/models/user.ts
import {Model,DataTypes,Optional} from 'sequelize'import seq from '../seq'// sequelize+typescript 参考文档// https://sequelize.org/master/manual/typescript.html// model类型export interface UserModelProps {id: number;username: string;password: string;email: string | null;mobile: string | null;avatar: string;description: string;isSuper: 0 | 1;status: 0 | 1;}// 注册接口params类型 id 和 isSuper创建时候可以不用定义自动分配export type RegisterModel = Omit<UserModelProps, 'id'|'isSuper'>// 在“User.build”和“User.create”调用中,有些属性是可选的interface UserCreationAttributes extends Optional<UserModelProps, "id" | "isSuper" | "status" | "avatar"|"description"> {}// Model实例接口interface UserInstanceextends Model<UserModelProps, UserCreationAttributes>,UserModelProps {}// 创建User模型 数据表的名字是usersconst User = seq.define<UserInstance>('User', {id: {primaryKey: true,type: DataTypes.INTEGER.UNSIGNED,autoIncrement: true},// id会自动创建 并设为主键、自增username: {type: DataTypes.STRING,allowNull: false,comment: '用户名'},password: {type: DataTypes.STRING,allowNull: false,comment: '密码'},email: {type: DataTypes.STRING,comment: '用户邮箱'},mobile: {type: DataTypes.STRING,comment: '手机号'},avatar: {type: DataTypes.STRING,comment: '头像'},isSuper: {type: DataTypes.BOOLEAN, // TINYINT(1)comment: '超级管理员 1是 0不是',defaultValue: 0},description: {type: DataTypes.TEXT,comment: '描述说明'},status: {type: DataTypes.BOOLEAN, // TINYINT(1)comment: '账户禁用状态 1正常 0禁用',defaultValue: 1}})export default User
导入models/index
src/db/models/index.ts
import UserModel from './user'export {UserModel,}
同步下model信息
npm run db
1-6 errorinfo
目前最新错误信息
src/constants/errorInfo.ts
/*** @description 失败信息集合,包括 code 和 message* @author 拔都*/export default {// 用户名已存在registerUserNameExistInfo: {code: 10001,message: '用户名已存在'},// 注册失败registerFailInfo: {code: 10002,message: '注册失败,请重试'},// 用户名不存在registerUserNameNotExistInfo: {code: 10003,message: '用户名未存在'},// 登录失败loginFailInfo: {code: 10004,message: '登录失败,用户名或密码错误'},// 未登录loginCheckFailInfo: {code: 10005,message: '您尚未登录'},// 修改密码失败changePasswordFailInfo: {code: 10006,message: '修改密码失败,请重试'},// 用户信息失败getUserInfoFailInfo: {code: 10007,message: '用户信息获取失败 token验证无效'},getUserListFailInfo: {code: 10008,message: '用户列表获取失败, 请重试'},editUserInfoFailInfo: {code: 10009,message: '用户信息修改失败, 请重试'},deleteUserInfoFailInfo: {code: 10010,message: '用户删除失败, 请重试'},updateUserRoleFailInfo: {code: 10011,message: '用户角色修改失败,请重试'},addAccessFailInfo: {code: 10012,message: '菜单添加失败'},getAccessAllFailInfo: {code: 10013,message: '获取全部菜单失败'},removeAccessFailInfo: {code: 10014,message: '删除菜单失败'},updateAccessFailInfo: {code: 10015,message: '编辑菜单失败'},addRoleFailInfo: {code: 10016,message: '添加角色失败'},addRoleNameExistInfo: {code: 10017,message: '角色已存在, 不能重复添加'},updateRoleFailInfo: {code: 10018,message: '编辑角色失败'},updateRoleNameExistInfo: {code: 10019,message: '编辑失败,已存在同名角色'},removeRoleFailInfo: {code: 10020,message: '角色删除失败'},allocRoleAccessFailInfo: {code: 10021,message: '角色分配权限失败'},getRoleAccessFailInfo: {code: 10022,message: '根据角色获取权限失败'},updateUserExistFailInfo: {code: 10023,message: '用户信息修改失败,已存在同名用户'},allocUserRoleFailInfo: {code: 10024,message: '用户角色分配失败'},accountForbiddenFailInfo: {code: 10027,message: '登录失败,账号已被禁用!'}}


