一、重点
通过管理员的增删改查来实现与角色表的关联。
下边只展示重点,schema、service 等完整代码请看下方。
基于 NestJS 框架结合 Mongoose 数据库实现管理员增删改查功能,涵盖 Controller 路由设计、Service 层数据操作、Schema 模型定义及前端页面交互。核心流程包括管理员注册时的用户名校验与密码 MD5 加密、列表展示时通过聚合管道关联角色表信息、编辑时条件更新密码以及删除操作。代码示例展示了完整的模块配置与接口实现细节。
通过管理员的增删改查来实现与角色表的关联。
下边只展示重点,schema、service 等完整代码请看下方。
@Get('add') @Render('admin/manager/add')
async add() {
let result = await this.roleService.find({});
return { roleResult: result };
}
@Post('doAdd')
async doAdd(@Body() body, @Response() res) {
console.log('body: ', body);
if (body.username == '' || body.password.length < 2) {
this.toolsService.error(res, '用户名或密码长度不合法', `/${Config.adminPath}/manager/add`);
} else {
// 从数据库查询当前用户名是否存在
let adminResult = await this.adminService.find({'username': body.username});
if (adminResult.length > 0) {
this.toolsService.error(res, '此管理员已存在', `/${Config.adminPath}/manager/add`);
} else {
body.password = this.toolsService.getMd5(body.password);
let result = await this.adminService.add(body);
console.log('result: ', result);
if (result) {
this.toolsService.success(res, `/${Config.adminPath}/manager`);
} else {
this.toolsService.error(res, '增加失败', `/${Config.adminPath}/manager/add`);
}
}
}
}
<form action="/<%=config.adminPath%>/manager/doAdd" method="post">
<ul>
<li>管理员名称:<input type="text" name="username"/></li>
<li>管理员密码:<input type="text" name="password"/></li>
<li>管理员电话:<input type="text" name="mobile"/></li>
<li>管理员邮箱:<input type="text" name="email"/></li>
<li>管理员角色:
<select name="role_id" id="role_id">
<%for(var i=0; i<roleResult.length; i++){%>
<option value="<%=roleResult[i]._id%>"><%=roleResult[i].title%></option>
<%}%>
</select>
</li>
<li><button type='submit' class="btn btn-default">提交</button></li>
</ul>
</form>
@Get()
@Render('admin/manager/index')
async index() {
// 获取 admin 表以及 role 表关联数据
var result = await this.adminService.getModel().aggregate([
{
$lookup: {
from: "role",
localField: "role_id",
foreignField: "_id",
as: "role"
}
}
]);
console.log('result: ', JSON.stringify(result));
return { adminResult: result };
}
<table class="table table-bordered">
<thead>
<tr class="th">
<th>管理员名称</th>
<th>管理员电话</th>
<th>管理员邮箱</th>
<th>管理员角色</th>
<th class="text-center">操作</th>
</tr>
</thead>
<tbody>
<%for(var i=0;i<adminResult.length;i++){%>
<tr>
<td><%=adminResult[i].username%></td>
<td><%=adminResult[i].mobile%></td>
<td><%=adminResult[i].email%></td>
<!-- adminResult[i].role[0].title -->
<td><%=adminResult[i].role[0]%></td>
<td class="text-center">
<a href="/<%=config.adminPath%>/manager/edit?id=<%=adminResult[i]._id%>">修改</a>
<a class="" href="/<%=config.adminPath%>/manager/delete?id=<%=adminResult[i]._id%>">删除</a>
</td>
</tr>
<%}%>
</tbody>
</table>
若需要用户表和角色表关联,则需要定 schema 时这样写,否则关联不上:
role_id: { type: mongoose.Types.ObjectId },
@Get('edit')
@Render('admin/manager/edit')
async edit(@Query() query) {
let roleResult = await this.roleService.find();
let adminResult = await this.adminService.find({_id: query.id});
return { roleResult: roleResult, adminResult: adminResult[0] };
}
@Post('doEdit')
async doEdit(@Body() body, @Response() res) {
let id = body._id;
let password = body.password;
let mobile = body.mobile;
let email = body.email;
let role_id = body.role_id;
let params:any = { mobile, email, role_id };
// 密码不为空时更新密码
if (password != "") {
if (password.length <= 2) {
this.toolsService.error(res, '密码长度不合法', `/${Config.adminPath}/manager/edit?id=${body._id}`);
}
params.password = this.toolsService.getMd5(password);
}
let result = await this.adminService.update({'_id': id}, params);
if (result) {
this.toolsService.success(res, `/${Config.adminPath}/manager`);
}
}
重点:角色的选中
<form action="/<%=config.adminPath%>/manager/doEdit" method="post">
<ul>
<input type="hidden" name="_id" value="<%=adminResult._id%>"/>
<li>管理员名称:<input readonly type="text" name="username" value="<%=adminResult.username%>"/></li>
<li>管理员密码:<input type="text" name="password"/></li>
<li>管理员电话:<input type="text" name="mobile" value="<%=adminResult.mobile%>"/></li>
<li>管理员邮箱:<input type="text" name="email" value="<%=adminResult.email%>"/></li>
<li>管理员角色:
<select name="role_id" id="role_id">
<%for(var i=0; i<roleResult.length; i++){%>
<%if(roleResult[i]._id.toString() == adminResult.role_id){%>
<option selected value="<%=roleResult[i]._id%>"><%=roleResult[i].title%></option>
<%}else {%>
<option value="<%=roleResult[i]._id%>"><%=roleResult[i].title%></option>
<%}%>
<%}%>
</select>
</li>
<li><button type='submit' class="btn btn-default">提交</button></li>
</ul>
</form>
@Get('delete')
async delete(@Query() query, @Response() res ) {
let result = await this.adminService.delete({"_id": query.id});
this.toolsService.success(res, `/${Config.adminPath}/manager`);
}
<a class='delete' href="/<%=config.adminPath%>/manager/delete?id=<%=adminResult[i]._id%>">删除</a>
import { Module } from '@nestjs/common';
import { MainController } from './main/main.controller';
import { LoginController } from './login/login.controller';
import { ManagerController } from './manager/manager.controller';
import { ToolsService } from '../../service/tools/tools.service';
// 配置 schema1
import { MongooseModule } from '@nestjs/mongoose';
import { AdminSchema } from '../../schema/admin.schema';
import { RoleSchema } from '../../schema/role.schema';
// 引入服务
import { AdminService } from '../../service/admin/admin.service';
import { RoleService } from '../../service/role/role.service';
import { RoleController } from './role/role.controller';
@Module({
imports: [
MongooseModule.forFeature([
{ name: "Admin", schema: AdminSchema, collection: 'admin' },
{ name: "Role", schema: RoleSchema, collection: 'role' }
])
],
controllers: [MainController, LoginController, ManagerController, RoleController],
providers: [ToolsService, AdminService, RoleService]
})
export class AdminModule {}
@filename(admin.schema)
import * as mongoose from 'mongoose';
const Schema = mongoose.Schema;
const d = new Date();
export const AdminSchema = new mongoose.Schema({
username: { type: String },
password: { type: String },
mobile: { type: String },
email: { type: String },
status: { type: String },
role_id: { type: mongoose.Types.ObjectId },
add_time: { type: Number, default: d.getTime() },
is_super: { type: Number },
});
import { Injectable } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import { AdminInterface } from '../../interface/admin.interface';
@Injectable()
export class AdminService {
constructor(@InjectModel('Admin') private adminModel) {}
async find(json: AdminInterface = {}) {
let result = await this.adminModel.find(json);
return result;
}
async add(json: AdminInterface) {
let role = new this.adminModel(json);
let result = await role.save();
return result;
}
async update(json1: AdminInterface, json2: AdminInterface) {
let result = await this.adminModel.updateOne(json1, json2);
return result;
}
async delete(json: AdminInterface) {
let result = await this.adminModel.deleteOne(json);
return result;
}
getModel() {
return this.adminModel;
}
}
@filename(admin.interface)
export interface AdminInterface {
_id?: String;
username?: String;
password?: String;
mobile?: String;
email?: String;
status?: String;
role_id?: String;
add_time?: Number;
is_super?: Number;
}
import { Controller, Get, Render, Post, Body, Response } from '@nestjs/common';
import { Config } from '../../../config/config';
import { AdminService } from '../../../service/admin/admin.service';
import { RoleService } from '../../../service/role/role.service';
import { ToolsService } from '../../../service/tools/tools.service';
@Controller(`${Config.adminPath}/manager`)
export class ManagerController {
constructor(
private adminService: AdminService,
private roleService: RoleService,
private toolsService: ToolsService
) {}
@Get()
@Render('admin/manager/index')
async index() {
return {};
}
@Get('add')
@Render('admin/manager/add')
async add() {
let result = await this.roleService.find({});
return { roleResult: result };
}
@Post('doAdd')
async doAdd(@Body() body, @Response() res) {
console.log('body: ', body);
if (body.username == '' || body.password.length < 2) {
this.toolsService.error(res, '用户名或密码长度不合法', `/${Config.adminPath}/manager/add`);
} else {
// 从数据库查询当前用户名是否存在
let adminResult = await this.adminService.find({'username': body.username});
if (adminResult.length > 0) {
this.toolsService.error(res, '此管理员已存在', `/${Config.adminPath}/manager/add`);
} else {
body.password = this.toolsService.getMd5(body.password);
let result = await this.adminService.add(body);
console.log('result: ', result);
if (result) {
this.toolsService.success(res, `/${Config.adminPath}/manager`);
} else {
this.toolsService.error(res, '增加失败', `/${Config.adminPath}/manager/add`);
}
}
}
}
@Get('edit')
@Render('admin/manager/edit')
edit() {
return {};
}
}

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online
将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online
通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online
将JSON字符串修饰为友好的可读格式。 在线工具,JSON美化和格式化在线工具,online