MVC 樹節點Table格式授權

      這幾夜心裏頗不平靜, 奈何 JS水平有限,前臺效果耗時四天,後臺傳值一天,直至昨夜丑時測試初步完成,其實就是一個給tree來授權,網上開源的插件很多,如treejs、easyui 等等,只是這裏授權稍有不同,如下圖,只能放在Table中去實現。一行一行的寫js,最後寫的差不多有個100多行。

項目原界面不方便截圖,這裏隨手寫個原生態的 Demo 

 如圖所示,首先這是一個Table,無論枝節點還是葉節點都作爲一行(tr),功能菜單列表中葉節點(無分支) 後對應新增、修改等六個功能(複選框)

先來說說前臺需要實現的效果:

①點擊枝節點,其下所有的節點(枝/葉)收縮/展開

②點擊枝節點前的複選框,其下所有節點(枝/葉)、葉節點所在行的新增、修改等複選框勾選/取消

 eg: 點擊藍圈中的複選框,則紅框內所有的複選框都被勾選/取消 

針對JQ,只要能給每個標籤一個值,name、id之類的用以區別,就能使用Jquery選擇器來確定該元素

給所有枝節點嵌套一個 id 爲 spid 的標籤<span>用來標識

複製代碼

<tr id="11000">    <td colspan="7"><input name="c0" id="1-0000c" type="checkbox"/><span id="spid" >1-0000</span></td></tr><tr id="11-000" style="text-indent: 10px">
    <td><input name="c1" id="11-000c" type="checkbox"/><span>11-000</span></td>
    <td><input name="A" id="11-000cA" type="checkbox"/></td>
    <td><input name="B" id="11-000cB" type="checkbox"/></td>
    <td><input name="C" id="11-000cC" type="checkbox"/></td>
    <td><input name="D" id="11-000cD" type="checkbox"/></td>
    <td><input name="E" id="11-000cE" type="checkbox"/></td>
    <td><input name="F" id="11-000cF" type="checkbox"/></td>
 </tr>

複製代碼

 

 說白了,就是用Table的方式來實現一個Tree的效果,這裏子節點和葉節點是用<tr>的縮進長度來達到層級節點的效果

針對收縮/展開

     只要能夠選擇到枝節點裏面的span標籤,既可用toggle()來隱藏/展開子節點。根據命名的特點使用拼接id的方法來選擇子節點,即可實現.

然後分情況,依次判斷是鼠標點擊的是幾級枝節點,如果是一級,則只需要隱藏/展開其下的葉節點;如果是兩級,要隱藏/展開其下的枝節點、葉節點;以此類推

比如當點擊籃框所在的枝節點23-000時,葉節點231-00、23200、枝節點23300及葉節點2331-0、2332-0 均要隱藏/展開。

var lenth = $(this).parent().parent().attr('id').indexOf("-");                      
var s = $(this).parent().parent().attr('id').substring(0, lenth);

判斷前,先得到當前對象所在的 tr 的 id 中的字符 - 的位置,根據該位置可知當前鼠標點擊的是何級枝節點,然後隱藏/展開其下節點即可,此時對應的 lenth == 2 ,則有 

複製代碼

$(this).parent().parent().siblings("#" + s + i + '-' + '00').toggle();   for (var q = 1; q < 6; q++) {      if ($("#" + s + i + q + '-' + '0').is(":hidden")){
           $(this).parent().parent().siblings("#" + s + i + q + '-' + '0').toggle();
          }
       $(this).parent().parent().siblings("#" + s + i + q + '-' + '0').toggle();
   }

複製代碼

若lenth == 3 ,即爲最裏層枝節點,則有

$(this).parent().parent().siblings("#" + s + i + '-' + '0').toggle();

若lenth ==1 ,即爲最外面的枝節點(根節點),同樣是按照id的拼接方法來判斷,不同的是,需要多循環一層而已

複製代碼

$(this).parent().parent().siblings("#" + s + i + '-' + '000').toggle();      for (var j = 1; j < 6; j++) {      if ($("#" + s + i + j + '-' + '00').is(":hidden")) {
            $(this).parent().parent().siblings("#" + s + i + j + '-' + '00').toggle();
         }
      $(this).parent().parent().siblings("#" + s + i + j + '-' + '00').toggle();      for (var p = 1; p < 6; p++) {          if ($("#" + s + i + j + p + '-' + '0').is(":hidden")) {
                $(this).parent().parent().siblings("#" + s + i + j + p + '-' + '0').toggle();
           }
          $(this).parent().parent().siblings("#" + s + i + j + p + '-' + '0').toggle();
     }
 }

複製代碼

根據觀察比較,發現就是一層一層的去選擇節點,節點越靠外,最外是根節點,那麼需要遍歷的層次就越多,同理,越內側,遍歷次數就越少。用到了大量的 if else 語句,其中又和 for 語句相互嵌套,層層相扣,寫完之後,我的感覺是,除了自己,估計很難有另外一個人能在短時間內明白,自己再也不要去維護自己寫的這個菜單授權。仔細思索,其實是可以進行大量優化代碼,比如:點擊第三層需要循環第二層和第一層,點擊第二層需要循環第一層,點擊第一層需要循環其下的葉節點,那麼我最後的解決方案時採用 直接放在一個方法裏面,然後用$.each() 來遍歷,把葉節點放在最下面,一層一層,這樣一來,代碼果然看的很舒服,質量也提高不少。

 

而對於單選/多選/全選/反選

     相對來說判斷的情況複雜一些,主要是需要結合後臺邏輯,比如說:

    三級葉節點勾選,則三級枝節點勾選、二級枝節點勾選、一級枝節點勾選

    二級枝節點勾選,則其下所有子節點勾選,其上一級枝節點勾選

首先還是分情況討論,思路如下

if 勾選授權行(葉節點)所在的第一列(11-000、12-000)

    其所在行的每一個節點均勾選(新增、修改、刪除等)

    其上 各級直系枝節點勾選

else

    if 勾選授權行所在的其他列(新增、修改、刪除、修改、上傳、下載)

      當個數不少於1一個時,其第一列也要勾選(涉及到後臺的傳值), 其上 各級直系枝節點勾選

      當個數爲0時(點擊兩下),其第一列不勾選,其上父級節點的兄弟節點(大爹、二爹、小爹)若均無勾選,則祖父節點不勾選,

      所有其一勾選,則祖父節點仍勾選,依次類推,直至根節點

   else 勾選枝節點時

       if 一級節點 逐級遍歷,其下所有子節點勾選,其上若兄弟節點均無勾選,則父節點不勾選,若有其一勾選,則父節點勾選

       if 二級節點 逐級遍歷,其下所有子節點勾選,其上若兄弟節點均無勾選,則父節點不勾選,若有其一勾選,則父節點勾選,以此類推,直至祖父節點

       if 三級節點 逐級遍歷,其下所有子節點勾選,其上若兄弟節點均無勾選,則父節點不勾選,若有其一勾選,則父節點勾選,以此類推,直至曾祖父節點

如此,就把所有的情況都考慮進去,按部就班,一行一行的碼js,即可達到要求,代碼有點多,思路就是這樣,這裏就不貼詳細代碼

上面都是前臺的效果,下面來說說後臺傳值,這裏有些技巧,值得一說,我給每個授權對應的td 都賦有name 值,這裏其值對應的是角色表中某功能數據中一個列,比如,選擇11-000,新增、刪除;則表中會授權列會記錄 A、B 。寫到這裏,無非就是一些傳值,直接記錄用Ajax傳遞後臺接受即可,用Push方法,具體的在 MVC與Ajax應用 中刪除一節有詳細記錄。這裏也不再贅述。寫到這裏,文中唯一值得說兩句的便是下文。當對某個角色的權限進行修改時,初次加載該界面,Table 表中的複選框 會對照 該角色本身的功能及權限,會有勾選。說白了就是點擊修改的時候,會有傳值的動作,先去數據庫中 根據該角色的主鍵信息,撈取其擁有的功能和對應的權限,根據這些數據Table表中的Checkbox 會有一個初始值。

這裏用到了Each,不得不說真方便。

先在後臺拿到 兩列(功能列表、權限)的集合,然後傳到前臺View中(Authlist)

緊接着根據 @Html.Raw(Json.Encode(Authlist)) 將其轉換爲Json 數組

再對其遍歷,最後根據其值給授權複選框一個初始值,具體如下:

複製代碼

         function getcheck() {
            $("input[type=checkbox]").prop("checked", false);            var [email protected](Json.Encode(Authlist));
            $.each(data,function(i, item) {                var array = item.WebFunctItem.toString().split(',');                var local = item.FunctID.toString().indexOf("0");                var sfunctid = item.FunctID.toString().substring(0, local);                var lastnumber = item.FunctID.toString().substr(item.FunctID.length-1, 1);                if (lastnumber === "0") {
                    $("#" + sfunctid + '-' + Getzero(local) + 'u').prop("checked", true);                    for (var i = 0; i < array.length; i++) {
                        $("#" + sfunctid + '-' +Getzero(local) + 'u'+array[i]).prop("checked", true);
                    }
                }                else {
                    $("#" + item.FunctID.toString() + '-' + 'u').prop("checked", true);                    for (var i = 0; i < array.length; i++) {
                        $("#" + item.FunctID.toString() + "-u" + array[i]).prop("checked", true);
                    }
                }
            });
        }

複製代碼

寫到這裏,自然並沒有結束,對於前臺來說,效果僅僅實現了三分之一,其實最麻煩的是 ,挨個節點去做判斷,這裏是Table標籤,只能挨個去遍歷,新增的話還好說,當對角色權限做修改操作時,因較難判斷出複選框狀態的改變/不改變。比如,未做修改,或者僅對已存在的功能菜單作部分權限(增、刪、改、查等)調整時,這時Ajax 傳值,後臺Update語句有效;如果勾選新的功能菜單,這是ajax傳值,後臺的Update語句無法完成,只能對新增的功能菜單執行Insert 方有效,此時,前臺就需要判斷哪些是對原有菜單的功能進行修改,哪些是新增的菜單及菜單下被授權的功能,如此,是很難做出判斷,對此,後臺邏輯控制爲: 先刪除該角色所有的功能,然後逐個新增 ,刪除 和 新增的 sql 進行疊加,然後調用一個事物,以免中途語句執行失敗可回滾至原始值。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章