先來完成樹目錄的顯示。開始前,現在解決方案中建立一個Upload目錄用來存放上傳的圖片,為了便於測試,在Upload目錄下隨便添加兩個目錄,這裡添加1和2。好,現在建立一個名為FolderController的控制器,添加必要的引用後,先添加一個字串常量,用來表示根目錄:stringroot = "../upload"; 在這裡使用虛擬目錄是因為可以結合提交資料直接轉換為實際目錄。這裡要注意,當放到伺服器上的時候,可能目錄結構會根據需要進行調整,因而好的方式是在項目的Web.Config檔案中添加一個定義變數,然後從檔案中提取目錄,從而避免因目錄改動造成的代碼修改。然後將Index方法修改為List,修改返回結果為JObject,並添加許可權特性聲明和一些用到的變數,代碼如下:[AjaxAuthorize(Roles= "普通使用者,系統管理員")]publicJObject List(){ bool success = false; string msg = ""; JArray ja = new JArray(); int total = 0; try { } catch(Exception e) { msg = e.Message; } returnHelper.MyFunction.WriteJObjectResult(success, total, msg, ja);} 現在要考慮怎麼返回目錄結構了,問題的關鍵是,如何為目錄構建一個唯一id以標識目錄。每一個目錄,只有在其父目錄下,其名稱是唯一的,因而不能直接作為id,因而,必須加上父目錄才是唯一的id。樹展開的時候,預設會以node作為關鍵字將樹節點的id提交到伺服器,因而,在伺服器端,只要從node中提取資料,就是將要列的目錄了,具體代碼如下:stringpath = Request["node"] ?? "/";DirectoryInfodir = new DirectoryInfo(Server.MapPath(root + path));foreach(var c in dir.GetDirectories()){ ja.Add(new JObject { newJProperty("id",path+c.Name +"/"), new JProperty("text",c.Name), newJProperty("parentId",path) }); total++;}success = true; 現在產生應用,並在瀏覽器查看,可看到32所示,檔案目錄已經列出來了。650) this.width=650;" src="http://www.bkjia.com/uploads/allimg/131228/123AK914-0.PNG" alt="" />
圖32 樹目錄
下面切換到PicManager.js檔案,為樹添加操作按鈕。在建立樹的配置項定義中,添加以下代碼:tbar:[ {iconCls:"folder-add",handler:me.onAddFolder,scope:me,tooltip:"添加目錄"}, {iconCls:"folder-delete",handler:me.onDeleteFolder,scope:me,disabled:true,tooltip:"刪除目錄"}, {iconCls:"refresh",handler:me.onRefreshFolder,scope:me,tooltip:"重新整理分類樹"}] 以上代碼在樹面板頂部添加了一個工具條,工具條裡有添加、刪除和重新整理3個按鈕。要正確顯示按鈕,還需要在app.css中添加按鈕的樣式代碼,代碼如下:.folder-add{ background:url("../images/folder_add.png")!important;}.folder-delete{ background:url("../images/folder_delete.png")!important;}.refresh{ background:url("../../../extjs/resources/themes/images/default/grid/refresh.gif")!important;} 當然,別忘記將需要的圖片複製到相應的目錄。現在重新整理一下頁面,會看到樹頂部多了3個按鈕。現在為樹添加2個事件,第1個是viewready事件,其作用是在樹重新整理後選擇第1個節點。第2個是選擇改變的時候,改變刪除按鈕的狀態。在這裡,不能通過id來尋找組件,因為這個組件會複用,使用的id就會有重複id。要尋找也不難,直接使用down方法找按鈕就行,唯一能區別刪除按鈕的屬性有iconCls和tooltip,在這裡將使用tooltip。具體代碼如下:listeners:{ scope: me, viewready: function (panel) { var view = panel.getView(); view.getSelectionModel().select(0); }, selectionchange: function (model, sels) { var me=this; me.tree.down("button[tooltip=刪除目錄]").setDisabled(sels.length ==0); }} 現在重新整理頁面,會看到樹顯示後會選擇“根目錄”,而刪除按鈕也處於開啟狀態了。現在來完成添加操作,方法有2種。第1種方法是使用預設的目錄名先建立一個目錄,然後再讓使用者修改目錄名。第2種方法是顯示一個提示框,讓使用者輸入目錄名,然後再建立目錄。簡單點,這裡將使用第1種方法,在PicManager.js的底部,添加一個onAddFolder方法。首先要做的是擷取選擇節點,以便知道是在那個目錄下建立目錄,代碼如下:onAddFolder:function () { var tree=this.tree, parent=tree.getSelectionModel().getSelection()[0]; if(! parent){ parent=tree.getRootNode(); }} 這裡添加了一個判斷,以防止沒有選擇目錄時,使用根目錄作為新目錄的父目錄。接著建立一個新的Folder模型並儲存它,代碼如下:varrec=new Folder({ text:"建立檔案夾", id:"", parentId:parent.data.id});rec.save({ url:"Folder/Add", parentNode:parent, success:function(rec,opt){ if(opt.parentNode.isExpanded()) opt.parentNode.appendChild(rec); else opt.parentNode.expand(); }, failure: SimpleCMS.ModelException, scope:tree}); 代碼中,會發現在save方法內的設定物件中添加了一個parentNode關鍵字,它會指向父節點,這樣的好處是,在伺服器端成功添加目錄後,就可直接調用parentNode通過其appendChild方法添加1個子節點。現在,在服務端Folder控制器添加一個Add方法。在之前的文章中,可以知道,資料會以data關鍵字進行提交,形式是JSON資料,因而,在方法內,要先從data提取資料,然後將其轉換為JArray,再在JArray中擷取資料進行處理,具體代碼如下:[AjaxAuthorize(Roles= "普通使用者,系統管理員")]publicJObject Add(){ bool success = false; string msg = ""; JArray ja = null; try { string data = Request["data"]?? ""; if (string.IsNullOrEmpty(data)) { msg = "錯誤的提交資料。"; } else { ja = JArray.Parse(data); if (ja.Count > 0) { JObject jo = (JObject)ja[0]; string parentDir=(string)jo["parentId"]; string foldername= (string)jo["text"]; string dirPath =Server.MapPath(root + parentDir); if (Directory.Exists(dirPath +foldername)) { msg = "目錄已經存在"; } else { DirectoryInfo di =Directory.CreateDirectory(dirPath + foldername); jo["id"] =parentDir + foldername + "/"; success = true; } } else { msg = "錯誤的提交資料。"; } } } catch (Exception e) { msg = e.Message; } return Helper.MyFunction.WriteJObjectResult(success,0, msg, ja);}} 代碼中,如果目錄已經存在,就返回一個錯誤資訊,說明目錄已經存在。否則,建立新目錄,並修改目錄的id返回。這裡一定要修改id返回,不然,新的節點的id就為空白,在它下面建立目錄就會出問題。下面完成刪除操作,與刪除使用者的代碼差不多,具體代碼如下:onDeleteFolder:function () { var me = this, tree = me.tree, rs =tree.getSelectionModel().getSelection(); if (rs.length > 0) { rs = rs[0]; if (rs.data.root) { Ext.Msg.alert("刪除檔案夾", "根目錄不允許刪除!"); return; } var content = "確定刪除目錄“" + rs.data.text + "”?<br/><p style='color:red'>注意:目錄下的檔案及子目錄都會被刪除。</p>"; Ext.Msg.confirm("刪除目錄", content, function (btn) { if (btn == "yes") { var rs =this.getSelectionModel().getSelection(); if (rs.length > 0) { rs = rs[0]; rs.remove(); this.store.sync({ success: function (e, opt) { varme=this; me.store.commitChanges(); me.view.select(0); me.view.focus(false); }, failure:SimpleCMS.ModelException, scope: tree }); } } }, tree) }}, 下面在Folder控制器添加一個Delete方法,代碼與Add類似,不同的是在判斷目錄存在之後,調用Directory對象的Delete方法刪除目錄下的檔案及其子目錄,代碼如下;[AjaxAuthorize(Roles= "普通使用者,系統管理員")]publicJObject Delete(){ bool success = false; string msg = ""; JArray ja = null; try { string data = Request["data"]?? ""; if (string.IsNullOrEmpty(data)) { msg = "錯誤的提交資料。"; } else { ja = JArray.Parse(data); if (ja.Count > 0) { JObject jo = (JObject)ja[0]; string parentDir =(string)jo["parentId"]; string foldername =(string)jo["text"]; string dirPath =Server.MapPath(root + parentDir); if (Directory.Exists(dirPath +foldername)) { Directory.Delete(dirPath +foldername, true); success = true; } else { msg = "目錄已被刪除"; } } else { msg = "錯誤的提交資料。"; } } } catch (Exception e) { msg = e.Message; } returnHelper.MyFunction.WriteJObjectResult(success, 0, msg, ja);} 接著完成重新整理操作,這個不難,重新載入Store就行了,代碼如下:onRefreshFolder:function () { this.tree.store.load();} 現在,目錄的操作就剩下編輯操作了,這個比較複雜,下文再說。 BTW:代碼我已該放到新浪微盤了原始碼:http://vdisk.weibo.com/s/g7Z33
本文出自 “黃燈橋的部落格” 部落格,請務必保留此出處http://dqhuang.blog.51cto.com/2522725/1032603