2021SC@SDUSC
首先我们将用几周的时间解读controller中cmswing文件夹中的代码:
本周先看admin文件中关于后台管理员登陆与数据条目管理的部分。
一、关于登陆
首先要登陆验证是管理员账号在登陆后台:
const is_login = await this.islogin();
if (!is_login) {
return this.redirect('/admin/public/signin');
}
登陆成功后弹出后台菜单并验证权限:
const url = `${this.ctx.controller}/${this.ctx.action}`;
// console.log(url);
if (!this.is_admin) {
const auth = this.service('cmswing/rbac', this.user.uid);
const res = await auth.check(url);
if (!res) {
const error = this.controller('cmswing/error');
return error.noAction('未授权访问!');
}
}
this.active = this.ctx.controller + '/' + this.ctx.action;
登陆验证与权限验证都是运用了设置变量用if方法判断所登陆账号是否与要求一致。
二、数据条目管理
主部分主要由几个异步函数来完成:
1.
async editRow(model, data, where, msg) {
let id = this.para('id');
id = think.isArray(id) ? id : id;
// 如存在id字段,则加入该条件
let fields = await this.model(model).getSchema();
console.log(fields);
if (in_array('id', fields) && !think.isEmpty(id)) {
where = think.extend({ 'id': ['IN', id] }, where);
}
此方法对数据表中的单行或多行记录执行修改,GET参数id为数字或逗号分隔的数字。model是参数名称,供M函数使用的参数;data是要修改的数据;where是查询时where()方法的参数;msg是执行正确和错误的消息 {'success':'','error':'', 'url':'','ajax':false} ,其中, url为跳转页面,ajax是否ajax方式(数字则为倒数计时秒数)。
有了这个方法,我们就可以更新修改频道缓存信息、全站的分类缓存信息还有栏目缓存。
2.
async forbid(model, where, msg) {
where = where || {}, msg = msg || { 'success': '状态禁用成功!', 'error': '状态禁用失败!' };
const data = { 'status': 0 };
await this.editRow(model, data, where, msg);
}
async resume(model, where, msg) {
where = where || {}, msg = msg || { 'success': '状态恢复成功!', 'error': '状态恢复失败!' };
const data = { 'status': 1 };
await this.editRow(model, data, where, msg);
}
async restore(model, where, msg) {
where = where || {}, msg = msg || { 'success': '状态还原成功!', 'error': '状态还原失败!' };
const data = { 'status': 1 };
where = think.extend({ 'status': -1 }, where);
await this.editRow(model, data, where, msg);
}
async delete(model, where, msg) {
where = where || {}, msg = msg || { 'success': '删除成功!', 'error': '删除失败!' };
const data = { 'status': -1 };
await this.editRow(model, data, where, msg);
}
这四个方法分别是用来禁用、恢复、还原、删除一些条目,model是模型名称,供D函数使用的参数;where与msg同editRow方法。本质是通过editRow方法来修改数据表中的记录,并在禁用/恢复/还原/删除方法使用成功后会返回成功或失败的提示。
同时还会有let变量status来表示数据条目的状态:
switch (status) {
case -1:
await this.delete(model, map, { 'success': '删除成功', 'error': '删除失败' });
break;
case 0:
await this.forbid(model, map, { 'success': '禁用成功', 'error': '禁用失败' });
break;
case 1:
await this.resume(model, map, { 'success': '启用成功', 'error': '启用失败' });
break;
default:
this.fail('参数错误');
break;
}
}
管理员在后台管理时选中相应的条目,操作后获得变量status的值:后台若status为-1,则执行delete方法删除条目;若为0,则执行forbid方法禁用条目;若为1则执行resume方法启用条目。然后方法执行,提示信息返回给后台管理员。
3.
async sortAction(model, id = 'id') {
model = model || this.ctx.controller.substring(6);
const param = this.para('sort');
const sort = JSON.parse(param);
const data = [];
for (const v of sort) {
const map = {};
map[id] = v.id;
map.sort = v.sort;
data.push(map);
}
const res = await this.model(model).updateMany(data);
if (res.length > 0) {
// 更新缓存
switch (model) {
case 'channel':// 更新频道缓存信息
await update_cache('channel');// 更新频道缓存信息
break;
case 'category':// 更新全站分类缓存
await update_cache('category');// 更新栏目缓存
break;
}
return this.success({ name: '更新排序成功!'});
} else {
return this.success({ name: '更新排序成功!'});
// return this.fail('排序失败!');
}
}
这一部分主要是负责条目的排序,通过for循环将数据表中的条目重新排序,然后再通过if更新数据表,更新成功会返回提示“排序成功”,否则会返回失败的提示。
三、返回后台节点数据
async returnnodes(tree) {
tree = tree || true;
// let modelname = http.module;
let tree_nodes = [];
if (tree && !think.isEmpty(tree_nodes)) {
return tree_nodes;
}
let nodes;
if (tree) {
var list = await this.model('menu').field('id,pid,title,url,tip,hide').order('sort asc').select();
nodes = get_children(list, 0);
} else {
nodes = await this.model('menu').field('title,url,tip,pid').order('sort asc').select();
}
tree_nodes = nodes;
return nodes;
}
变量tree用来判断是否返回多维数组结构(生成菜单时用到),为false返回一维数组(生成权限节点时用到)。若返回的主菜单节点数组中有'controller'元素,可以用来区分子节点和主节点