前言

在《LUCI启动流程介绍》里,我们介绍了LUCI的启动主体是dispatcher.lua的dispatch()函数,他通过解析controller目录下的lua文件,定义node节点,构建node-tree来进行页面管理。本节将详细介绍M(model)、V(view)、C(controller)各个文件的功能以及如果添加新的node节点。

  1. controller目录
  2. model目录
  3. view目录
  4. 新页面添加流程
  5. 官方及参考网址
controller目录

因为dispatch()函数通过解析controller目录下的lua文件构建node-tree,所以我们优先看一下这个目录的lua脚本是如何定义的。以controller/admin/status.lua的部分代码为例。

module("luci.controller.admin.status", package.seeall)function index()entry({"admin", "status"}, alias("admin", "status", "overview"), _("Status"), 20).index = trueentry({"admin", "status", "overview"}, template("admin_status/index"), _("Overview"), 1)entry({"admin", "status", "iptables"}, call("action_iptables"), _("Firewall"), 2).leaf = trueentry({"admin", "status", "processes"}, cbi("admin_status/processes"), _("Processes"), 6)
endfunction action_iptables()......
end

1、定义模块入口---> module("luci.controller.admin.status", package.seeall)

此行说明了程序和模块的路径名称,比如在controller/admin目录创建一个status.lua,那么就可以写成“luci.controller.admin.status”

2、添加index()函数,在index()函数中定义node节点属性

createtree()函数调用lua文件中的index()函数创建node-tree,同时index()引用entry函数定义node节点

3、entry (path, target, title, order)函数

(1)path:地址栏访问路径,通常也定义菜单分配,如:“{"admin", "一级菜单名", "菜单项名"}”

-- 定义菜单栏的一级菜单名
entry({"admin", "status"}, alias("admin", "status", "overview"), _("Status"), 20).index = true
-- 定义status下的overview菜单项
entry({"admin", "status", "overview"}, template("admin_status/index"), _("Overview"), 1)

(2)target:指定节点被调度(即用户点击)时的行为,主要有三种:call、template 和 cbi。

  • alias:别名,指向别的entry函数
  • call:调用指定函数,例如上述代码直接调用action_iptables函数
  • template:调用指定页面,例如 template(“admin_status/index”)表示调用/usr/lib/lua/luci/view/admin_status/index.htm页面
  • cbi:调用指定lua文件,这个页面的生成与LUA脚本及UCI配置文件息息相关,具体联系后文介绍。此时命令cbi(“admin_status/processes”)表示调用/usr/lib/lua/luci/model/cbi/admin_status/processes.lua文件。

(3)title:标题,即我们在网页中看到的菜单名(可选)

(4)order:同级节点的显示顺序,越小越靠前,反之越靠后(可选)

model目录

在entry函数中,使用cbi方式调用model下的lua文件。在这部分主要介绍model目录的lua脚本是如何定义的,他与UCI配置文件到底有何联系,保存生效如何能连接启动脚本。

1、model页面

model的页面是通过其目录下的LUA脚本与配置文件一起生成的。在LUA脚本的开头,通过 Map("配置文件文件名", "配置页面标题", "配置页面说明") 函数连接相应的配置文件;然后使用类型或者名称查找对应的section及option;最后根据页面需求,将option转换成HTML元素。以上操作就完成了model页面的配置,LUA脚本的详细介绍可以参考下列网址,这里只贴部分代码进行说明。

https://blog.csdn.net/qq_19004627/article/details/80364099
(1)/etc/config/example配置文件内容如下

config interface 'test'option enable '1'option addr '192.168.1.1'

(2)model目录的lua脚本内容如下,因为页面内容是由配置文件生成的,所以当修改完页面点击保存按钮时,修改的值也会同步到底层配置文件中。

--m = Map("配置文件文件名", "配置页面标题", "配置页面说明")
--第一个参数为配置文件存储的文件名,不包含路径,默认在/etc/config目录下
--第二个参数为页面的标题
--第三个参数为页面的描述
m = Map("example", translate("LUA Example"))--创建与配置文件中对应的section
--section的创建分为两种:NamedSection和TypedSection
--s = m:section(NamedSection, name, type, title, description)
--s = m:section(TypedSection, type, title, description)
--前者根据配置文件中的section名,例如上述配置文件中的test
--后者根据配置文件中的section类型,例如上述配置文件中的interface
s = m:section(TypedSection, "interface", translate("Example Info"))
s.anonymous = true --获取section对应的option,并转换成HTML元素
addr = s:option(Value, "addr", translate("Address"))
enable = s:option(Flag, "enable", translate("Enable"))--一定要记得return,才会有页面显示,否则是空页面
return m

(3)保存生效按钮与脚本的关联方法有二,一是捕获保存生效按钮,如果发现用户点击保存生效按钮,则调用底层脚本;

local apply = luci.http.formvalue("cbi.apply")
if apply thenluci.sys.call("/etc/init.d/example restart")
end

二是底层脚本监听配置文件是否有修改,如果发现有改动,脚本重新启动。具体操作可以参考下列网址:
https://www.cnblogs.com/mayswind/p/3468124.html

view目录

在entry函数中,主要通过template方式调用view下的HTML文件。在这部分主要介绍页面框架是如何搭建的。注:view目录下的文件虽然是HTML文件,但是文件尾缀必须要写成.htm形式

1、顶部<%- 内容 -%>: 此部分主要包含lua脚本的调用,在这里获取的变量可以直接在后文HTML中进行引用。

2、中部:此部分完成CGI post及get的处理,主要使用JS语言进行编写

<script type="text/javascript" src="<%=resource%>/cbi.js"></script>
<script type="text/javascript"..></script>

3、html部分:此部分完成页面内容的显示,与常规HTML编写相同

新页面添加流程

例:在状态菜单下添加测试页面

1、在controller目录下定义node节点

entry({"admin", "status", "example"}, cbi("admin_status/example"), _("Example"), 6)

2、在/etc/config下添加配置文件example

config interface 'test'option enable '1'option addr '192.168.1.1'

3、在model目录下添加example.lua脚本

m = Map("example", translate("LUA Example"))
s = m:section(TypedSection, "interface", translate("Example Info"))
s.anonymous = true
addr = s:option(Value, "addr", translate("Address"))
enable = s:option(Flag, "enable", translate("Enable"))
return m

4、生成页面如下:

官方及参考网址

1、开发OpenWrt路由器上LuCI的模块(https://www.cnblogs.com/mayswind/p/3468124.html)
2、luci cbi 模块函数详解(https://blog.csdn.net/qq_19004627/article/details/80364099)
3、openWRT官网,保存生效调用脚本(https://oldwiki.archive.openwrt.org/doc/devel/config-scripting)
4、LUCI简单说明教程(https://wenku.baidu.com/view/7cfb0d17e518964bcf847c76.html)
5、OpenWrt自定义luci页面来修改配置文件(https://blog.csdn.net/lvshaorong/article/details/53939138)
6、LUA的详细总结(https://www.cnblogs.com/rohens-hbg/category/743186.html)

OPENWRT-LUCI开发总结-LUCI添加新页面总结相关推荐

  1. pdf怎么删除其中一页与添加新页面

    PDF文件格式是目前使用非常广泛的一种文件格式,那么小伙伴们知道如何删除pdf文件中不需要的页面吗?又应该如何给pdf文件添加新的页面呢?如果想知道这两个问题的答案的话,那就继续往下阅读吧. 操作软件 ...

  2. 【Vue】添加新页面

    在[src\components\]路径下添加新vue文件,例如下图(图省事直接就复制了HelloWorld.vue,修改了一下里面的内容,需要懂html基础即可) 注意修改name 在[src\ro ...

  3. ios开发描述文件添加新设备

    我们经常用到真机测试,再development证书中添加新的设备. 首先在devices中 添加上自己的设备,然后需要获取uuid号.起个名字,填上你设备的uuid号 然后到描述文件里,重新生成一下描 ...

  4. 在开源UOJ的导航栏中添加新页面链接

    前言 刚用开源UOJ搭建OJ成功时就想在导航栏那里添加一个站内页面链接,无奈当时乱搞水平低,网上也没有教程,不晓得怎么弄 今天突然来了闲情乱搞一通,结果还真乱搞成了...特意写下为后来人少走点弯路 前 ...

  5. 批量给 PDF 文件的末尾添加一个新页面

    概要:我们有时候需要批量给 PDF 文件的末尾添加一个新的页面,比如说我们需要给最后一页添加一个联系页面等.对于 PDF 这种文件格式来说,我们还需要安装额外的编辑软件,但是这里不需要安装专业的 PD ...

  6. Android:如何添加一个页面,如何跳转页面

    一.如何为安卓添加多个页面 新建一个工程 打开这样 然后删掉 @Override     public boolean onCreateOptionsMenu(Menu menu) {        ...

  7. ecshop后台首页mysql_ecshop 添加后台页面以及设置权限

    ecshop 添加新页面 给ecshop后台增加管理功能页面 比如我们增加一个统计报表叫做 物流费用统计报表 放在后台"报表统计"栏目中 具体操作步骤: 第一步,我们要添加一个菜单 ...

  8. 名编辑电子杂志大师教程 | 插入新页面、替换或删除页面、调整页面顺序

    名编辑电子杂志大师是一款集编辑与转换于一身的电子杂志制作软件,我们既可以直接将PDF或图片转换成flash电子杂志,也可以从零开始制作我们独一无二的杂志.无论是哪种制作方式,我们都可以自由地添加新页面 ...

  9. [Pandas] 添加新列

    美图欣赏2022/06/18 数据准备 import pandas as pddf = pd.DataFrame([['ABC'],['FJZ'],['FOC']],columns=['Site']) ...

  10. OpenWrt路由器上的LuCI模块开发

    [一.LuCI配置界面开发的框架] LuCI是OpenWrt上的Web管理界面,LuCI采用了MVC三层架构,同时其使用Lua脚本开发,所以开发LuCI的配置界面不需要编辑任何的Html代码,除非想自 ...

最新文章

  1. 安装esp8266库_基于ESP8266,DIY低成本智能远程开关灯小装置
  2. rocketmq-flink
  3. 提高显微镜分辨率方法_超分辨显微镜研究获进展
  4. c语言一整行一整行读取文件
  5. java 线程同时启动_java多个线程同时启动的两种方式
  6. Spring学习(九)Spring 和数据库编程【了解】
  7. qpython3编辑器怎么用_Python快速入门系列:Pyqt5界面开发好帮手-Qss样式编辑器介绍...
  8. python网络编程内容_Python网络编程
  9. php redis 传递闭包,php进程daemon化的正确做法
  10. Could not read JSON: Cannot construct instance of `java.util.ArrayList$SubList`Redis反序列化异常
  11. 关于:将日文键盘设置为英文键盘
  12. 2017 Multi-University Training Contest 3 solutions BY 洪华敦
  13. Guawa的Splitter的工具类
  14. 2018.7.18 上半年课程总结 4- 高级英语
  15. 我见过最“骚”的代码注释!神兽版都来了
  16. Drools-决策表
  17. android sqlite动态创建表,QT下如何实现SQLite动态创建表
  18. 在华为云ECS上部署openGauss
  19. 苹果Mac电脑L2TP连接公司内部网络失败解决方案
  20. 多重利好袭来,“东数西算”的背后意义深远

热门文章

  1. 80psi等于多少kpa_1公斤的气压是多少KPA?
  2. Zepto中touch模块的使用(移动端)
  3. Spring Security OAuth2 开发指南
  4. html 鼠标划过 ie导致白屏,win7系统IE浏览器网页出现白屏的解决方法
  5. 【PC攻略】炎炎夏日,让你的显卡风扇不再“偷懒!”
  6. LNMP 平台的 redis 对接安装
  7. When Work Becomes a Game
  8. excel 删除重复项_在Excel 2007中删除重复项
  9. 服务器名称指示SNI
  10. 专科学习计算机应用需要学的课本,计算机应用技术