阅读前请先下载项目源码,边读边看源码以加深理解和实操,
源码地址已放于文章末尾!
小程序效果预览:




第七章:运筹帷幄——后台管理系统功能解析
欢迎来到“上帝视角”!在体验了普通用户和服务提供者(家政员)的视角后,我们终于来到了权力的巅峰——后台管理系统。这里是整个“家政到家”平台的“中央控制室”,管理员在这里掌控着平台的所有核心数据和业务流程。
后台管理系统虽然界面朴素,但功能最为强大。它负责管理家政员的入驻、审核,查看所有用户的预约订单,发布公告,以及进行系统级的配置。这一章,我们将重点剖析后台的登录机制和最核心的“家政员管理”与“预约管理”功能,看看管理员是如何“运筹帷幄之中,决胜千里之外”的。
7.1 管理员的“秘密入口”与权限分级
与家政员端类似,后台管理系统也有一套独立的、基于Token的登录和认证体系。
- 前端登录页:
/miniprogram/projects/workhome/pages/admin/index/login/admin_login.js - 后端登录接口:
.../controller/admin/admin_mgr_controller.js->adminLogin() - 后端服务:
.../service/admin/admin_mgr_service.js->adminLogin() - 身份校验基类:
.../framework/platform/controller/base_admin_controller.js
admin_mgr_service.js - 管理员登录
// 位置: /cloudfunctions/mcloud/project/workhome/service/admin/admin_mgr_service.js
const AdminModel = require('../../../../framework/platform/model/admin_model.js');
// ...
class AdminMgrService extends BaseProjectAdminService {
//**管理员登录 */
async adminLogin(name, password) {
// 判断是否存在
let where = {
ADMIN_STATUS: 1,
ADMIN_NAME: name,
ADMIN_PASSWORD: md5Lib.md5(password)
}
let fields = 'ADMIN_ID,ADMIN_NAME,ADMIN_DESC,ADMIN_TYPE,...';
let admin = await AdminModel.getOne(where, fields);
if (!admin) this.AppError('管理员不存在或者已停用');
// 生成token
let token = dataUtil.genRandomString(32);
// ... 更新token到AdminModel ...
return {
token,
name: admin.ADMIN_NAME,
type: admin.ADMIN_TYPE, // 1=超级管理员
// ...
}
}
}
代码讲解:
- 独立的
AdminModel:与家政员不同,管理员拥有一个独立的admin数据集合,由AdminModel定义。这体现了职责分离的原则,管理员的账户体系和业务数据(meet)是解耦的。 ADMIN_TYPE权限分级:admin表中有一个ADMIN_TYPE字段,用于区分不同级别的管理员。例如,1代表拥有所有权限的“超级管理员”,其他数字可以代表只能管理部分模块的“普通管理员”。在adminLogin成功后,后端会将这个type返回给前端,前端可以据此来控制界面上某些按钮(如“删除管理员”)的显示与隐藏,实现了简单的RBAC(基于角色的权限控制)。
base_admin_controller.js - 统一身份认证
所有后台接口的Controller都继承自BaseAdminController,它与BaseProjectWorkController的作用类似,通过在initSetup(或类似方法)中调用isAdmin()服务,实现了对所有后台接口的自动鉴权。
// 位置: /cloudfunctions/mcloud/framework/platform/controller/base_admin_controller.js
class BaseAdminController extends BaseController {
// ...
/** 是否管理员 */
async isAdmin() {
let service = new BaseAdminService();
let admin = await service.isAdmin(this._token); // 校验token
this._admin = admin;
this._adminId = admin._id;
}
/** 是否超级管理员 */
async isSuperAdmin() {
// ... 类似逻辑,但会进一步检查 admin.ADMIN_TYPE === 1
}
}
7.2 家政员管理:服务的“源头活水”
后台最核心的功能之一就是管理家政员(服务)。这包括添加新的家政员、编辑他们的资料、修改状态(启用/禁用)等。
- 前端页面:
/miniprogram/projects/workhome/pages/admin/meet/list/admin_meet_list.js - 后端控制器:
.../controller/admin/admin_meet_controller.js - 后端服务:
.../service/admin/admin_meet_service.js
admin_meet_service.js - 增改家政员
// 位置: /cloudfunctions/mcloud/project/workhome/service/admin/admin_meet_service.js
class AdminMeetService extends BaseProjectAdminService {
/**
* 添加家政员
*/
async insertMeet(adminId, { title, cateId, cateName, joinForms, daysSet }) {
// ... 数据校验 ...
let data = {
MEET_ADMIN_ID: adminId,
MEET_TITLE: title,
MEET_CATE_ID: cateId,
MEET_CATE_NAME: cateName,
MEET_JOIN_FORMS: joinForms,
// ... 更多业务字段
};
let meetId = await MeetModel.insert(data);
// 同时,也需要为他创建排班日历数据
let workService = new WorkMeetService();
await workService.editMeet(meetId, { daysSet });
return { result: 'ok' };
}
/**
* 修改家政员状态
*/
async statusMeet(id, status) {
let data = { MEET_STATUS: Number(status) };
await MeetModel.edit(id, data);
}
}
代码讲解:
- 服务复用:在
insertMeet方法中,当一个家政员被创建后,它立刻调用了WorkMeetService的editMeet方法。editMeet正是我们上一章分析过的家政员自己用来修改排班的服务。这里,管理员在创建家政员的同时,直接“替”他完成了一次排班设置。这再次展示了服务层(Service)良好封装和复用的强大威力。 - CURD操作:后台管理系统的核心,本质上就是对各个数据模型进行增(
insert)、改(edit/status)、查(getMeetList)、删(delMeet)的一系列操作。这些操作最终都映射到对MeetModel、DayModel等数据库表的调用上。
7.3 预约管理:平台的“上帝之眼”
管理员需要能够看到平台上所有的预约记录,以便进行统计、处理纠纷或进行数据导出。
- 前端页面:
/miniprogram/projects/workhome/pages/admin/meet/join_list/admin_meet_join_list.js - 后端接口:
.../controller/admin/admin_meet_controller.js->getJoinList()
admin_meet_controller.js - 查看所有预约
// 位置: /cloudfunctions/mcloud/project/workhome/controller/admin/admin_meet_controller.js
class AdminMeetController extends BaseProjectAdminController {
/** 预约名单列表 */
async getJoinList() {
await this.isAdmin(); // 鉴权
// 取得分页参数
let [page, size, sortType, sortVal] = this.GetParams('page', 'size', 'sortType', 'sortVal');
let service = new AdminMeetService();
let result = await service.getJoinList(this._meetId, { page, size, sortType, sortVal });
// ... 返回结果 ...
}
}
// 在 service/admin/admin_meet_service.js 中
class AdminMeetService extends BaseProjectAdminService {
async getJoinList(meetId, { search, sortType, sortVal, orderBy, page, size, isTotal, oldTotal }) {
// ... 复杂的查询条件组装 ...
let where = {
// 这里可以根据 search, sortType 等参数动态构建查询条件
// 比如按手机号搜索,按预约日期筛选等
};
return await JoinModel.getList(where, fields, orderBy, page, size, isTotal, oldTotal);
}
}
代码讲解:
- 无差别查询:与用户端只能查询
JOIN_USER_ID为自己的记录、家政员端只能查询JOIN_MEET_ID为自己的记录不同,管理员端的getJoinList服务在构建where查询条件时,没有任何用户或家政员ID的限制。它直接从JoinModel中查询所有数据(可以加上搜索和筛选条件)。这就是“上帝视角”的体现。 - 复杂查询与分页:后台列表通常伴随着复杂的搜索(按姓名、手机号)、筛选(按日期、状态)和分页功能。这些逻辑主要在
Service层的getJoinList中,通过动态构建where对象来实现。
至此,我们已经快速浏览了后台管理系统的核心功能。你会发现,一旦核心的业务模型和用户端流程搭建完毕,服务者端和管理端的功能开发,很多时候就是对现有服务和模型的复用与组合,并加上一层更严格的权限控制。
下一章,也是我们系列教程的最后一章,我们将讨论如何将我们的“家政到家”小程序正式发布上线,并对整个项目做一次全面的复盘和总结。最终的曙光就在眼前!
游戏源码下载地址:
https://thmail.lanzouu.com/iNlWs345lk9i

被折叠的 条评论
为什么被折叠?



