admin库
就目前为止, lua生态内唯一的一款通用Web后台管理系统开发库.
起因
开发者在使用各类Lua后端开发框架都时候, 业务的繁杂无意占了中间许多开发时间.
即使是不同的项目也都会遇到一个问题: 需要一个后台管理系统来对相关数据进行统计、修改、展示.
可惜的是: 截止到目前为止的后端框架较多, lua生态内尚没有一款集成的通用后台解决方案可以较为便捷的.
作者在与业内一些开发者沟通后, 发现大多数Lua开发者的后台的解决方法如下:
前、后端分离解决方案, 如: iview-admin/vue-admin、React等.
开发者提供数据接口, 由司内后台开发部门专门对接进行开发.
各类开发模式上的优劣无需讨论, 单单对lua开发者技能领域、技能涉及面、经验等都是比较大的挑战. 也从侧面反映出lua在后台页面开发确实是少有的一块短板, 目前市面上也暂无一个较为可靠的解决方案.
那么, 能否在此基础之上为lua的使用者也提供快速后台开发模板呢?
admin库的优势
admin库由layui + X-admin + lua-resty-template + cf httpd库提供底层支持.
admin库支持双语种支持, 用户在开发的时候建议使用locale的key作为相关名称,
admin基于RBAC进行权限管理, 提供了一套基于角色的菜单权限控制.
admin库为使用者的view内置了权限验证, render开发更加安全、简单.
admin库支持菜单栏与导航栏项目的增加与删除, 方便开发者进行相关功能的关联.
admin库最多支持三级菜单, 菜单的icon可以直接填写layui的unicode.
admin库提供了cdn支持, 用户可以轻松将一些静态文件发布到各类CDN平台.
admin库提供了很多配置参数, 如:设置默认语言、添加语言项、设置home首页、开启模板缓存等等.
开始使用admin库之前
请按照以下步奏初始化数据库:
创建一个数据库(名字任意), 并且保持charset一致;
打开lualib/db/database.sql文件, 复制里面的SQL语句在GUI工具中执行一次创建表;
admin API介绍
1. admin.init_db()
此方法将会初始化超级管理员用户与管理员用户组, 账户、密码都是:admin
2. admin.init_home(url)
此方法将设置dashboard的home页, home的地址就是url.
3. admin.init_page(app, db)
此方法将会构建admin库所用到的所有页面、数据接口.
4. admin.static(domain)
此方法可以用来设置静态文件域名前缀, 默认是:http::/localhost:8080/, 结尾一定要加上'/'.
5. admin.cached()
此方法用来确认是否开启全局模板缓存. 开发阶段不要开启! 这个参数可能会导致html模板缓存需要重启才能更新.
6. admin.cookie_timeout(Second)
此方法用来设置admin注入的Cookie超时时间, 可以认为这个时间就是用户登录时间. 单位为: sec.
7. admin.set_locale(lang)
此方法用来设置默认显示语言.(用户自行切换语言后, 浏览器将会记住用户选择语言)
8. admin.add_locale_item(lang, lang_locale_itemt)
admin.add_locale_item('ZH-CN', {
{'login.form.title', '这是登录页Title'},
{'dashboard.header.logo', '仪表盘 Logo'},
})
admin.add_locale_item('EN-US', {
{'login.form.title', 'This is Login Page Title'},
{'dashboard.header.logo', 'dashboard Logo'},
})
此方法用于增加/覆盖现有admin/locale内的语言key-value字典表. 通常用于多语言设置
9. admin.display_lang(boolean)
此方法用来设置dashboard页面的语言切换标签是否显示(默认为显示: true or flase).
view介绍
ctx对象
会在被传入一个httpctx对象, 该对象内置了一些方法:
ctx:get_method, 用户获取客户端请求方法.
ctx:get_args, 获取客户端传参.
ctx:get_path 和 ctx:get_raw_path, 获取请求路径与获取原始请求路径(原始请求路径不会去掉'/admin?a=2&b=2'的参数)
ctx:get_headers, 获取请求头部. key-value表, value永远为string.
db对象
db对象为DB.init初始化后的对象, 使用方法请参考DB
1. view.use(path, function(ctx, db) … end)
此方法类似httpd:use, 从这里开始, 我们统一称use路由为页面路由.
path为路由路径, function为路由回调, 开发者的相关逻辑代码都将在此函数内编写.
默认情况下, '/admin/'前缀开头的页面路由权限验证. 没有权限的使用者将会被重定向到登录页面.
代码示例:
local view = require "admin.view"
view.use('/admin/test', function (ctx, db)
return "this request method = " .. ctx:get_method()
end)
2. view.api(path, function(ctx, db) … end)
此方法类似httpd:api, 从这里开始, 我们统一称api路由为接口路由.
path为路由路径, function为路由回调, 开发者的相关逻辑代码都将在此函数内编写.
默认情况下, '/api/admin'前缀的数据路由会验证header内是否有token. 没传或无效会导致接口返回401/403.
代码示例:
local json = require "json"
local view = require "admin.view"
view.api('/api/admin/test', function (ctx, db)
return json.encode({
code = 200, method = ctx:get_method()
})
end)
3. view.get_locale()
此方法在页面路由中使用, 获取当前用户使用的语言
4. view.get_cdn()
此方法返回admin.static设置的值. 方便使用者配置静态文件前缀.
5. view.template(path){…}
template即lua-resty-template库的渲染方法. 效果等同于template.compile
.
path参数即可以作为html模板路径字符串, 如:"view/tp.html"
. 也可以作为模板字符串如法, 如:"<h1>{{title}}</h1>"
此方法返回一个函数, 函数的参数一个table作为渲染参数. 函数返回值为path渲染后的html内容.
您可以写成这样:
local view = require "admin.view"
view.use('/admin/test', function (ctx, db)
return view.template([[<h1>{*title*}</h1>]]){
title = '这是title!'
}
end)
但是, 这样每次修改模板需要重启cfadmin. 为了每次仅修改html模板时能即时生效, 作者推荐使用者将模板与渲染代码分离.
例如, 您可以写成这样:
-- main.lua
local view = require "admin.view"
view.use('/admin/test', function (ctx, db)
return view.template('view/tp.html'){
title = '这是title!'
}
end)
<!-- view/tp.html -->
<h1>{*title*}</h1>
上述2种写法无任何差异, 唯一的区别仅仅是模块化设计的区别
浏览器打开http://localhost:8080/admin/test
, 即可查看渲染效果.
更多template模板语法, 请在这里查看.
utils介绍
utils内置一些比较常见的方法以供大家使用.
utils导入方式
local utils = require "admin.utils"
1. utils.redirect(location, args)
此方法返回一个重定向的html页面, location为地址字符串(必填), args参数是一个参数数组表(可选).
由于cf框架的httpd实现未提供内置请求重定向方法, 所以为使用者提供一个页面路由请求重定向传参的途径.
假设location为"/admin", args为{{a, 1}, {b, 2}}
. 实际重定向到地址为: /admin?a=1&b=2
.
2. utils.error_404(location)
此方法返回一个404页面, 参数location为404页面跳转路径(不设置则跳转到cf框架首页).
如何使用cf搭建最简单的lua后台开发环境?
作者为开发者提供了一份代码示例在script/test_cfadmin.lua
, 使用者可参考此处进行搭建开发环境.
如何快速对cfadmin后台模板进行二次开发?
为了统一大家习惯. 所有对cfadmin后台的功能增加、修改、删除我们统称为:"二次开发".
1. 快速添加一级菜单
开发者在登录成功后将会看到系统管理, 展开后将会看到"菜单管理"项, 点击"菜单管理"后可以进行即可按照实际情况新建一个菜单.
在新建菜单之前, 我们需要使用view.use建立一个页面路由:
local view = require "admin.view"
view.use('/test', function (ctx, db)
return "<h1>Hello World!</h1>"
end)
建立完成之后, 我们可以开始新建菜单了. 新建菜单可不是那么简单, 它至少需要你确认做以下三件事:
1. 菜单名称(不能重复);
2. 菜单url(不能为空);
3. 菜单icon(需要参考layui图标unicode);
请注意. 菜单url必须对应到您的view.use创建的路由path. 否则将会出现404错误.
在菜单与路由在新建完成之后请刷新当前页面, 如果一切没有问题的话您就可以在左侧菜单栏内看到新建的菜单了.
这时候我们点击新建的菜单项, 就可以看到一个大大多"Hello World"了. 怎么样是不是非常简单?非常Cool?
2. 添加子菜单
如果您参照上述步骤添加完菜单之后, 就会开始思考对菜单进行分级. 没错! 一级菜单一般会作为一个总得分类项(例如系统管理)陈列.
当您项为某项菜单增加子菜单项的时候, 点击该菜单后面的增加"增加菜单". 其它内容按照上一章的内容规则新建菜单与路由即可.
注意:
1. 最多添加三级菜单, 过多的(多级)菜单项对管理还是整合都是无意义的.
2. 菜单管理项目内当你添加到三级菜单后, 将不会出现增加子菜单按钮.
3. 菜单对应权限
当您的菜单功能开发、测试完毕之后, 可能就会开始考虑"菜单权限分配".
admin库是基于RBAC建立的用户角色权限管理, 分离了用户(实体)与菜单(menu)、权限(permissions)之间的管理.
admin库对/api/admin/+的接口路由醉了一层header token验证, 如http request header无token字段则会返回401/403.
admin库对/admin/+的页面路由醉了一层cookie验证, 如cookie无效则会重定向到登录页面.
现在假设我们有如下菜单列表:
|-分析菜单
|——分析用户
|——分析数据
|——分析金额
完成上述列表功能后, 进入"角色管理"开始新建一个"分析角色". 并展开菜单列表在对应菜单前面打'√'. 这样就建立了一个角色. (修改同理)
新建完角色之后, 到'用户管理'页面新建一个用户. 角色选择为"分析角色", 其它内容根据实际情况填写然后提交. (修改同理)
尝试使用新创建的用户登录后台, 这样就可以在页面上看到分析菜单并且进行操作.
流程图
最后
新建菜单、导航项成功之后手动刷新当前页面即可生效.
修改用户信息与密码会导致该用户重新登录.
如果使用admin库, 需要开启httpd的cookie解析功能并且推荐手动设置一下Cookie的secure值, 以防止Cookie被破解.
请根据当前的环境合理的设置admin.cached与httpd:static.
如果在使用期间遇到读取静态文件缓慢, 请考虑分离静态文件(使用nginx做静态文件服务器或上传到CDN).
其它待补充.