Lua处理后台逻辑,Lua lwt搭建后台程序,ExtJS根据后台传来的json数据构建目录树。
前台html和ExtJS代码不用多讲,直接上代码:
treePanel.html
1 <html> 2 <head> 3 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 4 5 <title>ExtJS TreePanel</title> 6 <link rel="stylesheet" type="text/css" href="../../ext-5.0.0/examples/shared/example.css" /> 7 8 9 <script type="text/javascript" src="../ext-5.0.0/examples/shared/include-ext.js"></script> 10 <script type="text/javascript" src="../ext-5.0.0/examples/shared/options-toolbar.js"></script> 11 12 <script type="text/javascript" src="treePanel.js" charset="utf-8" ></script> 13 14 </head> 15 <body style=" margin: 0; padding: 0;"> 16 </body> 17 </html>
treePanel.js
1 Ext.require(‘Ext.tree.Panel‘) 2 3 Ext.onReady(function(){ 4 Ext.Ajax.request({ 5 url: ‘treePanel.lua‘, 6 method: ‘post‘, 7 params: { 8 id: "123", 9 action: ‘getDir‘ 10 }, 11 success: function(response){ 12 var text = response.responseText; 13 var obj = eval(‘(‘ + text + ‘)‘); 14 var treePanel = Ext.create(‘Ext.tree.Panel‘,{ 15 width: 200, 16 rootVisible: false, 17 store: obj, 18 renderTo: Ext.getBody(), 19 }); 20 }, 21 failure: function() { 22 Ext.Msg.alert("失败","失败了"); 23 } 24 }); 25 });
在treePanel.js中,通过后台传递过来的json字符串无法直接使用,需要将其转化为json对象才可以作为treePanel的数据源。
转换方法:jsonObj = eval(‘(‘+jsonString‘+)‘)
接下来是逻辑处理部分,也就是遍历目录数据的部分。
一开始我使用的方法是先将所有文件path遍历至一个table内,然后处理table将其转化为treePanel可以用的json格式,这样遍历过程比较简单,不过处理过程太过繁琐,处理方法结构脆弱且BUG不断,效率也是惨不忍睹。最后还是放弃了。
其实最合适的方法是直接在遍历时就生成所需要的json格式,好吧,现在就来实现他:
lua遍历目录需要达成的格式为:
1 local s = {root = { 2 text = "rootNode", 3 expanded = true, 4 leaf = false, 5 children = { 6 { 7 text = ‘book1‘, 8 leaf = false, 9 children = nil 10 }, 11 { 12 text = "book2", 13 leaf = false, 14 expanded = true, 15 children = { 16 { 17 text = "con1", 18 leaf = false, 19 children = { 20 { 21 text = "ccc1", 22 leaf = true 23 } 24 } 25 },{ 26 text = "con2", 27 leaf = true 28 } 29 } 30 }, 31 { 32 text = "book3", 33 expanded = true, 34 leaf = true 35 } 36 } 37 } 38 }
用lfs模块提供的方法遍历目录,并创建一个table,操作table使之成为这样的结构。其中:
"leaf = true"表示这个节点是一个文件,所以不必加上"children = {}"属性;
如果节点是一个文件夹,那给节点设置"leaf = false"表示为文件夹(如果不设置这个属性默认为文件夹,不过这里用来作为判断的条件,所以加上),并且加上"children = {}" 用来作为该文件夹下文件的根节点。
方法getDirTable(filePath)用以遍历目录,并生成指定的table结构数据:
1 function getDirTable(filePath) 2 local table = {root = {text = "rootNode", leaf = false, children = {}}} 3 function getDir(path,table) 4 for file in lfs.dir(path) do 5 if file ~= "." and file ~= ".." then 6 p = path .. "/" .. file 7 if isDir(p) == "directory" then 8 local node = {text = file, leaf = false, children = {}} 9 table[#table + 1] = node 10 local nObj = table[#table].children 11 local nPath = path .. file .. "/" 12 getDir(nPath, nObj) 13 else 14 local node = {text = file, leaf = true} 15 table[#table + 1] = node 16 end 17 end 18 end 19 end 20 getDir(filePath,table.root.children) 21 return table 22 end
其中遍历了当下文件夹,如果文件夹下存在子文件夹,则递归遍历子文件夹,并且将子文件夹下的文件和文件夹依照规则添加到该文件夹节点的"children = {}"内。
在这个方法中,还有一个辅助方法,用来判断path是文件还是文件夹:
1 function isDir(path) 2 return lfs.attributes(path).mode 3 end
获取目录遍历table后,使用cjson方法转换为json字符串:
1 function table2Json(table) 2 local cjson = require("cjson") 3 return cjson.encode(table) 4 end
最后通过lwt将json字符串传到前台:
1 httpd.set_content_type("text/json") 2 if request.method == "POST" then 3 if args.action == "getDir" then 4 httpd.write(table2Json(getDirTable(request.filedir))) 5 end 6 elseif request.method == "GET" then 7 httpd.write("是个字符串") 8 end
完整代码:
1 require "lfs" 2 require "httpd" 3 4 request, args = ... 5 6 function isDir(path) 7 return lfs.attributes(path).mode 8 end 9 10 function table2Json(table) 11 local cjson = require("cjson") 12 return cjson.encode(table) 13 end 14 15 function getDirTable(filePath) 16 local table = {root = {text = "rootNode", leaf = false, children = {}}} 17 function getDir(path,table) 18 for file in lfs.dir(path) do 19 if file ~= "." and file ~= ".." then 20 p = path .. "/" .. file 21 if isDir(p) == "directory" then 22 local node = {text = file, leaf = false, children = {}} 23 table[#table + 1] = node 24 local nObj = table[#table].children 25 local nPath = path .. file .. "/" 26 getDir(nPath, nObj) 27 else 28 local node = {text = file, leaf = true} 29 table[#table + 1] = node 30 end 31 end 32 end 33 end 34 getDir(filePath,table.root.children) 35 return table 36 end 37 38 httpd.set_content_type("text/json") 39 if request.method == "POST" then 40 if args.action == "getDir" then 41 httpd.write(table2Json(reTable(getDirTable(request.filedir)))) 42 end 43 elseif request.method == "GET" then 44 httpd.write("GET请求") 45 end
访问treePanel.html
这里有一个问题,看asd.sda文件夹下
这里出现了一个没有名字的空文件夹。这是由于遍历时,检测到是目录时默认给其赋值了"children = {}"的缘故,由于在treePanel中,当不设置"leaf: true"时,默认leaf为false,即将其认为是一个文件夹。所以ExtJS给这个文件夹节点添加了一个没有名字的空子文件夹。
要解决这个问题,只要将为空的文件夹设置为children = nil,这样就可以了。
1 function reTable(table) 2 local obj = table.root.children 3 function re(obj) 4 if #obj == 0 then 5 obj = nil 6 else 7 for i = 1, #obj do 8 if obj[i].leaf == false then 9 if #(obj[i].children) == 0 then 10 obj[i].children = nil 11 else 12 re(obj[i].children) 13 end 14 end 15 end 16 end 17 end 18 re(obj) 19 return table 20 end
最后把lwt响应改一下:
httpd.write(table2Json(reTable(getDirTable(request.filedir))))
看看效果:
这样就显示了一个空文件夹,问题解决!