【Lua】Lua + LWT + ExtJS构建目录树

  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))))

  看看效果:

  这样就显示了一个空文件夹,问题解决!

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。