手把手教你写项目之“家政到家”小程序全栈开发---第七章:运筹帷幄——后台管理系统功能解析

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

小程序效果预览:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

第七章:运筹帷幄——后台管理系统功能解析

欢迎来到“上帝视角”!在体验了普通用户和服务提供者(家政员)的视角后,我们终于来到了权力的巅峰——后台管理系统。这里是整个“家政到家”平台的“中央控制室”,管理员在这里掌控着平台的所有核心数据和业务流程。

后台管理系统虽然界面朴素,但功能最为强大。它负责管理家政员的入驻、审核,查看所有用户的预约订单,发布公告,以及进行系统级的配置。这一章,我们将重点剖析后台的登录机制和最核心的“家政员管理”与“预约管理”功能,看看管理员是如何“运筹帷幄之中,决胜千里之外”的。

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方法中,当一个家政员被创建后,它立刻调用了WorkMeetServiceeditMeet方法。editMeet正是我们上一章分析过的家政员自己用来修改排班的服务。这里,管理员在创建家政员的同时,直接“替”他完成了一次排班设置。这再次展示了服务层(Service)良好封装和复用的强大威力。
  • CURD操作:后台管理系统的核心,本质上就是对各个数据模型进行增(insert)、改(edit/status)、查(getMeetList)、删(delMeet)的一系列操作。这些操作最终都映射到对MeetModelDayModel等数据库表的调用上。

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

THMAIL

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值