前言
本节开始我们实现用户服务中心的其他模块,分别为:
- 系统管理
- 资源管理
- 权限管理
- 角色管理
- 用户管理
这一节基本上是体力劳动,重复集中CRUD
系统管理
现在需要实现schema
来定义创建系统数据的校验
新建helpers/constants.ts
ts
export enum STATUS {
DISABLED = 'DISABLED',
ENABLED = 'ENABLED',
}
新建schemas/system.ts
ts
import { z } from 'zod';
import { STATUS } from '@/helpers/constants';
export const systemSchema = z.object({
name: z.string().min(2),
description: z.string().min(2).optional(),
status: z.enum([STATUS.DISABLED, STATUS.ENABLED]).optional(),
creatorId: z.string(),
updatorId: z.any().optional(),
});
export type systemSchemaType = z.infer<typeof systemSchema>;
定义操作数据库的方法helpers/dbRepo.ts
ts
import prisma from '@/helpers/prisma';
import { systemSchemaType } from '@/schemas/system';
const include = {
creator: {
select: {
id: true,
email: true,
name: true,
},
},
updator: {
select: {
id: true,
email: true,
name: true,
},
},
};
async function create(system: systemSchemaType) {
return await prisma.system.create({
data: system,
include,
});
}
async function update(id: string, system: any) {
return await prisma.system.update({
where: { id },
data: system,
include,
});
}
async function remove(id: string) {
return await prisma.system.delete({
where: { id },
});
}
async function findById(id: string) {
return await prisma.system.findUnique({
where: { id },
include,
});
}
async function findByIds(ids: string[]) {
return await prisma.system.findMany({
where: {
id: {
in: ids,
},
},
include,
});
}
async function list() {
return await prisma.system.findMany({
include,
});
}
const systemRepo = {
create,
update,
remove,
findById,
findByIds,
list,
};
export default systemRepo;
定义接口app/api/system/route.ts
ts
import { apiHandler, transformInterceptor } from '@/helpers';
import systemRepo from '@/helpers/dbRepo/system';
import prisma from '@/helpers/prisma';
import type { NextRequest } from 'next/server';
const create = apiHandler(async (req: NextRequest) => {
const body = await req.json();
const userId = await req.headers.get('userId');
if (userId) {
const user = await prisma.user.findUnique({
where: {
id: userId,
},
});
const result = await systemRepo.create({
...body,
creator: {
connectOrCreate: {
where: {
id: userId,
},
create: {
id: userId,
name: user?.name,
email: user?.email,
password: user?.password,
},
},
},
});
return transformInterceptor({
data: result,
});
} else {
throw new Error('请先登录');
}
});
const list = apiHandler(async (req: NextRequest) => {
const result = await systemRepo.list();
return transformInterceptor({
data: result,
});
});
export const POST = create;
export const GET = list;
定义app/api/systen/[id]/route.ts
ts
import { apiHandler, transformInterceptor } from '@/helpers';
import systemRepo from '@/helpers/dbRepo/system';
import type { NextRequest } from 'next/server';
import prisma from '@/helpers/prisma';
const getSystem = apiHandler(async (req: NextRequest, { params }: { params: any }) => {
const { id } = params;
const result = await systemRepo.findById(id);
return transformInterceptor({
data: result,
});
});
const updateSystem = apiHandler(async (req: NextRequest, { params }: { params: any }) => {
const { id } = params;
const userId = await req.headers.get('userId');
const body = await req.json();
if (userId) {
const user = await prisma.user.findUnique({
where: {
id: userId,
},
});
const result = await systemRepo.update(id, {
...body,
updator: {
connectOrCreate: {
where: {
id: userId,
},
create: {
id: userId,
name: user?.name,
email: user?.email,
password: user?.password,
},
},
},
});
return transformInterceptor({
data: result,
});
} else {
throw new Error('请先登录');
}
});
const removeSystem = apiHandler(async (req: NextRequest, { params }: { params: any }) => {
const { id } = params;
const result = await systemRepo.remove(id);
return transformInterceptor({
data: result,
});
});
export const GET = getSystem;
export const PATCH = updateSystem;
export const DELETE = removeSystem;
分别实现系统的:
- 获取列表
- 获取当前系统详情
- 创建系统
- 更新系统
- 删除系统
资源管理
修改helpers/constants.ts
添加一个枚举,暂时用不到
ts
export enum RESOURCE_TYPE {
MENU = 'MENU',
NORMAL = 'NORMAL',
}
新建helpers/dbRepo/resource.ts
,作数据库操作函数封装,实现增删改查,分页查找
ts
import prisma from '@/helpers/prisma';
const include = {
system: true,
parent: true,
};
async function create(resource: any) {
return await prisma.resource.create({
data: resource,
include,
});
}
async function update(id: string, resource: any) {
return await prisma.resource.update({
where: { id },
data: resource,
include,
});
}
async function remove(id: string) {
return await prisma.resource.delete({
where: { id },
});
}
async function findById(id: string) {
return await prisma.resource.findUnique({
where: { id },
include,
});
}
async function paginate({ page, pageSize, ...params }: { page: number; pageSize: number }) {
const skip = (page - 1) * pageSize;
const take = pageSize;
return await prisma.resource.findMany({
skip,
take,
where: {
...params,
},
include,
});
}
const resourceRepo = {
create,
update,
remove,
findById,
paginate,
};
export default resourceRepo;
先来最基本的创建接口app/api/resource/route.ts
ts
import { apiHandler, transformInterceptor } from '@/helpers';
import resourceRepo from '@/helpers/dbRepo/resource';
import type { NextRequest } from 'next/server';
const create = apiHandler(async (req: NextRequest) => {
const body = await req.json();
const result = await resourceRepo.create(body);
return transformInterceptor({
data: result,
});
});
export const POST = create;
然后是分页查找app/api/resource/paginate/route.ts
, 因为不能在同一个route下面有两个POST接口,所以多了一个路径
ts
import { apiHandler, transformInterceptor } from '@/helpers';
import resourceRepo from '@/helpers/dbRepo/resource';
import type { NextRequest } from 'next/server';
const paginate = apiHandler(async (req: NextRequest) => {
const body = await req.json();
const result = await resourceRepo.paginate(body);
return transformInterceptor({
data: result,
});
});
export const POST = paginate;
最后是针对一个resource的操作app/api/resource/[id]/route.ts
ts
import { apiHandler, transformInterceptor } from '@/helpers';
import resourceRepo from '@/helpers/dbRepo/resource';
import type { NextRequest } from 'next/server';
const getResource = apiHandler(async (req: NextRequest, { params }: { params: any }) => {
const { id } = params;
const result = await resourceRepo.findById(id);
return transformInterceptor({
data: result,
});
});
const removeResource = apiHandler(async (req: NextRequest, { params }: { params: any }) => {
const { id } = params;
const result = await resourceRepo.remove(id);
return transformInterceptor({
data: result,
});
});
const updateResource = apiHandler(async (req: NextRequest, { params }: { params: any }) => {
const { id } = params;
const body = await req.json();
const result = await resourceRepo.update(id, body);
return transformInterceptor({
data: result,
});
});
export const GET = getResource;
export const DELETE = removeResource;
export const PATCH = updateResource;
这也不需要解释了吧,[id]
下面的就可以在{params}
里面拿到这个id
,如下为创建接口测试示例,外键的话就传对应id就行
权限管理
新建helpers/dbRepo/privilege.ts
ts
import prisma from '@/helpers/prisma';
async function create(privilege: any) {
return await prisma.privilege.create({
data: privilege,
});
}
async function update(id: string, privilege: any) {
return await prisma.privilege.update({
where: { id },
data: privilege,
});
}
async function remove(id: string) {
return await prisma.privilege.delete({
where: { id },
});
}
async function findById(id: string) {
return await prisma.privilege.findUnique({
where: { id },
});
}
async function paginate({ page, pageSize, ...params }: { page: number; pageSize: number }) {
const skip = (page - 1) * pageSize;
const take = pageSize;
return await prisma.privilege.findMany({
skip,
take,
where: {
...params,
},
});
}
const privilegeRepo = {
create,
update,
remove,
findById,
paginate,
};
export default privilegeRepo;
新建app/api/privilege/route.ts
实现创建
ts
import { apiHandler, transformInterceptor } from '@/helpers';
import privilegeRepo from '@/helpers/dbRepo/privilege';
import type { NextRequest } from 'next/server';
const create = apiHandler(async (req: NextRequest) => {
const body = await req.json();
const result = await privilegeRepo.create(body);
return transformInterceptor({
data: result,
});
});
export const POST = create;
新建app/api/privilege/paginate/route.ts
实现分页查找
ts
import { apiHandler, transformInterceptor } from '@/helpers';
import privilegeRepo from '@/helpers/dbRepo/privilege';
import type { NextRequest } from 'next/server';
const paginate = apiHandler(async (req: NextRequest) => {
const body = await req.json();
const result = await privilegeRepo.paginate(body);
return transformInterceptor({
data: result,
});
});
export const POST = paginate;
新建app/api/privilege/[id]/route.ts
实现更新,删除,详情
ts
import { apiHandler, transformInterceptor } from '@/helpers';
import privilegeRepo from '@/helpers/dbRepo/privilege';
import type { NextRequest } from 'next/server';
const update = apiHandler(async (req: NextRequest, { params }: { params: any }) => {
const { id } = params;
const body = await req.json();
const result = await privilegeRepo.update(id, body);
return transformInterceptor({
data: result,
});
});
const remove = apiHandler(async (req: NextRequest, { params }: { params: any }) => {
const { id } = params;
const result = await privilegeRepo.remove(id);
return transformInterceptor({
data: result,
});
});
const findById = apiHandler(async (req: NextRequest, { params }: { params: any }) => {
const { id } = params;
const result = await privilegeRepo.findById(id);
return transformInterceptor({
data: result,
});
});
export const PATCH = update;
export const DELETE = remove;
export const GET = findById;
重复劳动,基本copilot都已经自动能生成了
角色管理
新建helpers/dbRepo/role.ts
实现数据库操作函数
ts
import prisma from '@/helpers/prisma';
async function create(role: any) {
return await prisma.role.create({
data: role,
});
}
async function update(id: string, role: any) {
return await prisma.role.update({
where: { id },
data: role,
});
}
async function remove(id: string) {
return await prisma.role.delete({
where: { id },
});
}
async function findById(id: string) {
return await prisma.role.findUnique({
where: { id },
});
}
async function paginate({ page, pageSize, ...params }: { page: number; pageSize: number }) {
const skip = (page - 1) * pageSize;
const take = pageSize;
return await prisma.role.findMany({
skip,
take,
where: {
...params,
},
});
}
const roleRepo = {
create,
update,
remove,
findById,
paginate,
};
export default roleRepo;
新建app/api/role/route.ts
实现创建接口
ts
import { apiHandler, transformInterceptor } from '@/helpers';
import roleRepo from '@/helpers/dbRepo/role';
import type { NextRequest } from 'next/server';
const create = apiHandler(async (req: NextRequest) => {
const { systemId, ...args } = await req.json();
const userId = await req.headers.get('userId');
if (userId) {
const result = await roleRepo.create({
...args,
creator: {
connect: {
id: userId,
},
},
updator: {
connect: {
id: userId,
},
},
system: {
connect: {
id: systemId,
},
},
});
return transformInterceptor({
data: result,
});
} else {
throw new Error('请先登录');
}
});
export const POST = create;
新建app/api/role/paginate/route.ts
实现分页接口
ts
import { apiHandler, transformInterceptor } from '@/helpers';
import roleRepo from '@/helpers/dbRepo/role';
import type { NextRequest } from 'next/server';
const paginate = apiHandler(async (req: NextRequest) => {
const { page, pageSize, ...params } = await req.json();
const result = await roleRepo.paginate({ page, pageSize, ...params });
return transformInterceptor({
data: result,
});
});
export const POST = paginate;
新建app/api/role/[id]/route.ts
实现更新、删除、详情接口
ts
import { apiHandler, transformInterceptor } from '@/helpers';
import roleRepo from '@/helpers/dbRepo/role';
import type { NextRequest } from 'next/server';
const update = apiHandler(async (req: NextRequest, { params }: { params: any }) => {
const { id } = params;
const body = await req.json();
const userId = await req.headers.get('userId');
const result = await roleRepo.update(id, {
...body,
updator: {
connect: {
id: userId,
},
},
});
return transformInterceptor({
data: result,
});
});
const remove = apiHandler(async (req: NextRequest, { params }: { params: any }) => {
const { id } = params;
const result = await roleRepo.remove(id);
return transformInterceptor({
data: result,
});
});
const findById = apiHandler(async (req: NextRequest, { params }: { params: any }) => {
const { id } = params;
const result = await roleRepo.findById(id);
return transformInterceptor({
data: result,
});
});
export const PATCH = update;
export const DELETE = remove;
export const GET = findById;
用户管理
新建helpers/dbRepo/user.ts
封装数据库操作
ts
import prisma from '@/helpers/prisma';
const selectField = {
email: true,
name: true,
userRoles: true,
};
async function create(user: any) {
return await prisma.user.create({
data: user,
select: selectField,
});
}
async function update(id: string, user: any) {
return await prisma.user.update({
where: { id },
data: user,
select: selectField,
});
}
async function remove(id: string) {
return await prisma.user.delete({
where: { id },
});
}
async function findById(id: string) {
return await prisma.user.findUnique({
where: { id },
select: selectField,
});
}
async function paginate({ page, pageSize, ...params }: { page: number; pageSize: number }) {
const skip = (page - 1) * pageSize;
const take = pageSize;
return await prisma.user.findMany({
skip,
take,
where: {
...params,
},
select: selectField,
});
}
const userRepo = {
create,
update,
remove,
findById,
paginate,
};
export default userRepo;
新建app/api/user/route.ts
实现创建用户
ts
import { apiHandler, transformInterceptor } from '@/helpers';
import userRepo from '@/helpers/dbRepo/user';
import type { NextRequest } from 'next/server';
const create = apiHandler(async (req: NextRequest) => {
const body = await req.json();
const result = await userRepo.create(body);
return transformInterceptor({
data: result,
});
});
export const POST = create;
新建app/api/user/paginate/route.ts
实现分页
ts
import { apiHandler, transformInterceptor } from '@/helpers';
import userRepo from '@/helpers/dbRepo/user';
import type { NextRequest } from 'next/server';
const paginate = apiHandler(async (req: NextRequest) => {
const { page, pageSize, ...params } = await req.json();
const result = await userRepo.paginate({ page, pageSize, ...params });
return transformInterceptor({
data: result,
});
});
export const POST = paginate;
新建app/api/user/[id]/route.ts
实现更新、删除、详情
ts
import { apiHandler, transformInterceptor } from '@/helpers';
import userRepo from '@/helpers/dbRepo/user';
import type { NextRequest } from 'next/server';
const update = apiHandler(async (req: NextRequest) => {
const body = await req.json();
const userId = await req.headers.get('userId');
if (!userId) {
throw new Error('请先登录');
}
const result = await userRepo.update(userId, body);
return transformInterceptor({
data: result,
});
});
const remove = apiHandler(async (req: NextRequest) => {
const userId = await req.headers.get('userId');
if (!userId) {
throw new Error('请先登录');
}
const result = await userRepo.remove(userId);
return transformInterceptor({
data: result,
});
});
const findById = apiHandler(async (req: NextRequest) => {
const userId = await req.headers.get('userId');
if (!userId) {
throw new Error('请先登录');
}
const result = await userRepo.findById(userId);
return transformInterceptor({
data: result,
});
});
export const PATCH = update;
export const DELETE = remove;
export const GET = findById;
⭐️用户-角色管理
现在我们来实现用户-角色
管理
新建helpers/dbRepo/user-role.ts
ts
import prisma from '@/helpers/prisma';
const selectField = {
user: {
select: {
email: true,
name: true,
},
},
role: true,
};
async function create(userId: string, roleId: string) {
return await prisma.userRole.create({
data: {
user: {
connect: {
id: userId,
},
},
role: {
connect: {
id: roleId,
},
},
},
select: selectField,
});
}
async function remove(userId: string, roleId: string) {
return await prisma.userRole.delete({
where: {
userId_roleId: {
userId,
roleId,
},
},
});
}
async function findByUserId(userId: string) {
return await prisma.userRole.findMany({
where: {
userId,
},
select: selectField,
});
}
async function findByRoleId(roleId: string) {
return await prisma.userRole.findMany({
where: {
roleId,
},
select: selectField,
});
}
async function paginate({ page, pageSize, ...params }: { page: number; pageSize: number }) {
const skip = (page - 1) * pageSize;
const take = pageSize;
return await prisma.userRole.findMany({
skip,
take,
where: {
...params,
},
select: selectField,
});
}
const userRoleRepo = {
create,
remove,
findByUserId,
findByRoleId,
paginate,
};
export default userRoleRepo;
新建app/api/user-role/route.ts
实现创建、删除、根据userId查询角色
ts
import { apiHandler, transformInterceptor } from '@/helpers';
import userRoleRepo from '@/helpers/dbRepo/user-role';
import type { NextRequest } from 'next/server';
const createUserRole = apiHandler(async (req: NextRequest) => {
const { roleId } = await req.json();
const userId = await req.headers.get('userId');
if (!userId) {
throw new Error('请先登录');
}
const result = await userRoleRepo.create(userId, roleId);
return transformInterceptor({
data: result,
});
});
const removeUserRole = apiHandler(async (req: NextRequest) => {
const { roleId } = await req.json();
const userId = await req.headers.get('userId');
if (!userId) {
throw new Error('请先登录');
}
const result = await userRoleRepo.remove(userId, roleId);
return transformInterceptor({
data: result,
});
});
const findUserRole = apiHandler(async (req: NextRequest) => {
const userId = await req.headers.get('userId');
if (!userId) {
throw new Error('请先登录');
}
const result = await userRoleRepo.findByUserId(userId);
return transformInterceptor({
data: result,
});
});
export const POST = createUserRole;
export const DELETE = removeUserRole;
export const GET = findUserRole;
新建app/api/user-role/paginate/route.ts
实现分页
ts
import { apiHandler, transformInterceptor } from '@/helpers';
import userRoleRepo from '@/helpers/dbRepo/user-role';
import type { NextRequest } from 'next/server';
const paginate = apiHandler(async (req: NextRequest) => {
const { page, pageSize, ...params } = await req.json();
const result = await userRoleRepo.paginate({ page, pageSize, ...params });
return transformInterceptor({
data: result,
});
});
export const POST = paginate;
角色-权限管理
新建helper/dbRepo/role-privilege.ts
实现数据库操作
ts
import prisma from '@/helpers/prisma';
async function create(roleId: string, privilegeId: string) {
return await prisma.rolePrivilege.create({
data: {
role: {
connect: {
id: roleId,
},
},
privilege: {
connect: {
id: privilegeId,
},
},
},
});
}
async function remove(roleId: string, privilegeId: string) {
return await prisma.rolePrivilege.delete({
where: {
roleId_privilegeId: {
roleId,
privilegeId,
},
},
});
}
async function findByRoleId(roleId: string) {
return await prisma.rolePrivilege.findMany({
where: {
roleId,
},
});
}
const rolePrivilegeRepo = {
create,
remove,
findByRoleId,
};
export default rolePrivilegeRepo;
新建app/api/role-privilege/route.ts
实现创建、删除接口
ts
import { apiHandler, transformInterceptor } from '@/helpers';
import rolePrivilegeRoleRepo from '@/helpers/dbRepo/role-privilege';
import type { NextRequest } from 'next/server';
const createRolePrivilege = apiHandler(async (req: NextRequest) => {
const { roleId, privilegeId } = await req.json();
const result = await rolePrivilegeRoleRepo.create(roleId, privilegeId);
return transformInterceptor({
data: result,
});
});
const removeRolePrivilege = apiHandler(async (req: NextRequest) => {
const { roleId, privilegeId } = await req.json();
const result = await rolePrivilegeRoleRepo.remove(roleId, privilegeId);
return transformInterceptor({
data: result,
});
});
export const POST = createRolePrivilege;
export const DELETE = removeRolePrivilege;
新建app/api/role-privilege/[id]/route.ts
实现根据roleId查找
ts
import { apiHandler, transformInterceptor } from '@/helpers';
import rolePrivilegeRoleRepo from '@/helpers/dbRepo/role-privilege';
import type { NextRequest } from 'next/server';
const findRolePrivilege = apiHandler(async (req: NextRequest, { params }: { params: any }) => {
const result = await rolePrivilegeRoleRepo.findByRoleId(params.id);
return transformInterceptor({
data: result,
});
});
export const GET = findRolePrivilege;
现在每个管理模块还是单独的,没有构成完整系统的,下一章我们会基于Next.js开发简单的后台管理系统,将接口串联,也会有一些对应的走流程出现的bug改动