java學習筆記——衆籌項目練習——後臺manager程序--權限管理的全部功能,模糊查詢數據的分頁顯示,全選與單選的聯動,模態框與zTree的聯合使用,RBAC權限模型的簡單使用

                                                    權限管理

在前面我練習了管理員的註冊和登錄,併成功的登錄到了控制面板main.jsp頁面,今天我們就來試着實現一下控制面板頁面中的功能。在控制面板中,我們最先注意到的也是最重要的功能就是權限管理,並且在前面的文章中也介紹了RBAC權限模型的概念與數據庫中表的實現。

好,我們一起一點一點的來完善控制面板頁面的功能吧。

首先我們已經可以成功的跳轉到了main.jsp頁面,可是現在的控制面板頁面還不具備任何功能,就連界面中顯示的功能也都是原型頁面中自帶的假數據。所以我們要一點一點的改造。

那麼我們從哪裏開始呢?就從左邊顯示的功能菜單開始吧!!!

我的這個頁面中左邊的權限管理菜單應該是,單擊就會顯示子菜單的,但是我這裏點擊後沒有效果完全點不開,與原型頁面不符,可能是哪裏出了問題。我們檢測頁面元素看看問題出在了哪裏?發現是bootstrap加載出現了問題,路徑有問題。

應該改成正確的加載路徑。我們的bootstrap被放在了plugin文件夾下,所以需要修改路徑。

好了,修改後就可以看見子菜單了。

雖然左邊的菜單欄可以顯示出來了,不過顯示的都是原型頁面中固定寫死的假信息。我們需要將這個菜單欄改造成可以根據數據庫表中的數據進行動態變化的菜單欄,因爲我們菜單欄中有哪些菜單,不應該在頁面中規定,而是在數據庫中存儲,數據庫中有哪些菜單,頁面的菜單欄中就應該顯示哪些菜單,這樣更加靈活,也更加貼合我們的需求,修改或者添加菜單時也更方便。

 

                                                菜單欄改造

我們可以看出左邊的菜單欄其實是一個用於子父級關係的樹形結構,並且每個父節點的後邊還有一個標識這自己有一個子節點的數字標識。既然要將菜單欄存儲在數據庫表中,那麼數據庫中肯定是要有相應的菜單表嘍,並且要實現樹形結構就要根據子父級關係進行存儲,我們數據庫中的t_permission表正就是用來存儲菜單的,我們先根據原型頁面中的菜單在t_permission表中創建菜單數據(菜單名、圖標、以及請求地址)。這裏爲了省事,值寫了權限管理、用戶維護、角色維護、許可維護的圖標信息和請求信息(因爲點擊菜單操作需要跳轉頁面,所以會有請求信息,比如點擊用戶維護會跳轉到用戶列表頁面)。

好,數據有了,現在我們來實現程序中的取得菜單數據。那我們應該在哪裏獲取菜單數據呢?因爲登錄後就回來到控制面板頁面,並顯示左側的菜單欄。所以我們應該在登錄成功的時候就獲取到菜單數據,並保存到session域中爲跳轉到的控制面板頁面使用。爲了給頁面減少計算的壓力,我們應該在程序中就組裝好菜單的子父級關係。可是如何給頁面傳遞一個帶有子父級關係的樹形結構呢?我們需要對tPermission類稍加改造---添加一個List<tPermission> childs類型的成員變量來保存子菜單信息;這樣我們就可以返還一個具有子父級關係的樹形結構了,並且頁面使用時也省了不少功夫。

好了,在程序中獲取菜單信息並傳達到控制面板頁面代碼完成。

先我們來修改頁面,再頁面中動態的顯示這些菜單信息(我們默認菜單的樹形結構只有兩級)

原來的main.jsp頁面

將顯示左側菜單欄的部分出取出來加以改造,因爲左側的菜單欄有好幾個頁面會使用,所以還是抽取成公共顯示部分比較好。

然後再原來的控制面板頁面中顯示左側菜單欄的位置引入我們公共的左側菜單欄頁面即可。

好了,頁面也改造完畢,運行一下試試吧 。

噹噹噹當,成功!!!!(因爲圖省事,只在數據庫的t_permission表中填入了權限管理的圖標和請求地址,所以別的菜單才光禿禿的,需要的時候會全部加上,嘻嘻)。

現在左側的菜單還不能點擊,因爲點擊菜單後會跳轉頁面,可是我們只在數據庫中爲用戶權限中的幾個菜單添加了url請求地址,並且請求地址中相應的界面也沒有創建,所有點擊菜單後不是現實找不到頁面的錯誤就是返回首頁。

讓我們一點一點的實現接下來的功能吧!首先我們要保證點擊左側的菜單後可以成功的跳轉頁面,先來完成權限管理中用戶維護、角色維護、許可維護這三個菜單的頁面跳轉吧。

 

                                             點擊菜單權限管理跳轉頁面

想要成功的跳轉頁面,需要修改兩個地方:一,跳轉到的jsp頁面存在。二,請求地址正確。

一,跳轉到的jsp頁面存在:我們現在還沒有跳轉後的頁面,不過我們有原型頁面,我們可以看看,點擊相關的菜單後會跳轉到哪個頁面,這樣我們把相關的原型頁面轉換爲我們需要的jsp頁面再加入到我們的項目中就可以了。前面的文章中我們知道了如何將html原型頁面轉換爲jsp頁面(先修改html文件的中的文件編碼,再修改後綴爲jsp就可以了)。

添加到eclipse後添加jsp文件頭,然後修改文件後綴爲.jsp。

同樣的方式修改另外兩個文件。

要跳轉的jsp界面添加完畢。接下來我們修改點擊菜單時發送跳轉頁面的請求,因爲我們不同菜單的請求是房子數據庫中存儲的,菜單欄只是在數據庫中取出而已,所以我們要修改數據庫中 的數據。

爲用戶維護菜單添加請求後,還要有相應的處理controller來返回相關的頁面,因爲我們的用戶維護頁面在WEB-INF文件夾中,不能再瀏覽器中直接被訪問。

並且修改頁面中的依賴庫路徑,不然頁面會亂掉的。

在控制面板點擊左側菜單欄跳轉到user.jsp頁面顯示用戶信息,這裏需要注意的是,user頁面與main頁面都有左側的菜單欄,但此時他們卻不是同一個菜單欄,他們分別屬於不同的頁面。我們前面將左側的菜單欄抽取成一個單獨的jsp文件,就是爲了可以讓不同的頁面在需要菜單欄時可以共用。

 

                                          user.jsp頁面使用公共的菜單欄

引入公共的菜單欄文件。

再次訪問user.jsp頁面,發現菜單欄沒有自動展開也沒有變紅。

既然我們點擊了用戶維護菜單,訪問了user.jsp頁面,那麼左邊的菜單欄中應該有相應的顯示纔對,權限管理自動展開並且用戶維護菜單變色表示選中狀態。這個需要實現起來也不難,並且html的原型頁面也已經實現了,只需要改變相關菜單的樣式就可以了。但是這裏我們既然已經將左側的菜單欄抽取成了一個公共的功能,那麼我們就不能像之前在原型頁面中那樣設置相關菜單的樣式了。我們需要封裝一個公共的方法,用來設置不同菜單的選中樣式,這樣我們在菜單欄中訪問所有頁面時就都可以簡單設置選中時應該顯示的狀態了。

 

                               添加公共的改變選中菜單欄中菜單狀態方法

添加JavaScript方法實現父菜單展開,子菜單變紅的方法,參數是菜單中請求的地址,因爲菜單中的請求地址是唯一的,所以以此來區別點擊了那個菜單。使用時在跳轉到的相關頁面傳入本頁面的請求地址就好了。

在user.jsp頁面中只需要在pageContext域中保存跳轉到本頁面時的請求地址,然後加載上面的user_menu.jsp公共的菜單欄文件就可以了。

左側菜單欄部分的功能差不多就調好了,我們繼續。。。

接下來我們來實現user.jsp頁面中右半部分的功能,右半部分的列表是用戶列表,所有的用戶都顯示在這個列表中。我們的數據庫中有一張t_user表,正是用來保存用戶信息的,所有我們只需要將t_user表中的數據全部查出來並顯示在user.jsp頁面右半部分的用戶列表中就可以了。

注意,這裏的展示是有分頁功能的,並不是所有數據全部都顯示在每一頁中。所以我們在顯示用戶列表的時候還要添加一個分頁功能。

 

                                          添加獲取用戶列表功能並分頁

我們現在t_user表中創建一些用戶信息,畢竟用戶信息太少的話也沒有辦法分頁顯示的嘛。

用戶列表是在點擊用戶維護菜單後顯示的,所以我們應該在處理用戶維護請求/permission/user/list中獲取用戶信息,所以應該在controller中的users()方法中去獲取用戶信息。

添加獲取用戶信息的實現代碼。這裏分頁數據中pn表示顯示第幾頁,默認賦值1。ps表示每頁顯示幾條數據,默認賦值5。還有就是頁腳分頁菜單處,一共可以顯示3個連續頁面。

修改界面,顯示我們傳過來的用戶信息。

顯示用戶列表也很簡單,for循環打印就可以了。

 

還有頁腳處的分頁按鈕,都可以在我們傳過來的PageInfo類型的user_info數據中找到相關的信息。要保證分頁按鈕與傳輸過來的用戶數據的頁數保持同步外,還要發送其他頁用戶數據的請求。每一個分頁按鈕都是一個用戶數據頁的請求。

顯示用戶數據和分頁功能代碼完成,我們去運行一下看看效果。。

點擊用戶維護,顯示用戶列表第一頁,每頁顯示5條數據。

點擊第二頁、第三頁,會重新發送用戶信息分頁數據的請求,改變用戶數據顯示,並且分頁按鈕也相應改變,但始終只顯示3個頁面的按鈕(因爲我們只設置了顯示3個分頁按鈕)。

 

 

ok,用戶列表展示,並分頁功能完成。。

接下來,我們繼續。在我們的user.jsp頁面中還有一個查詢的功能。用戶列表可以根據查詢的不同關鍵字來展示不同的信息。這個功能實現起來也不難,都是查詢用戶列表嘛,與之前的區別就是之前是查全部,而這個是根據條件查詢。既然兩個都是查詢,那我們來優化一下,讓他們合併爲一個根據關鍵字查詢的方法,如果關鍵字爲空,我們就查全部。查詢的方式應該使用模糊查詢,並且我們這裏只根據關鍵字去查詢賬號和用戶名。就是說只要賬號與用戶名中存在關鍵字,我們就顯示。

 

                                     查詢優化:根據關鍵字查詢用戶列表

修改controller中的查詢代碼。添加根據條件查詢,查詢條件會作爲參數傳遞過來,查詢之後還要講查詢條件返回給頁面用於回顯。

修改user.jsp頁面中條件查詢form表單的參數,添加請求地址,將查詢條件作爲提交項,並可以從域中取得查詢條件完成回顯效果。

根據條件查詢時當然不能忘了分頁按鈕啦!因爲分頁按鈕也是會發送查詢請求的,我們之前發送的是查詢所有的分頁請求,現在需要再添加上根據條件查詢的分頁請求,如何實現呢?我們可以寫一個腳本,在點擊分頁按鈕的時候爲這個按鈕的請求追加一個條件查詢的參數(&sh=xxx)就行啦!

再運行試試看。。

輸入模糊查詢條件爲s,點擊查詢

點擊下一頁。

ok,一切正常,呦呦呦完成了一個小功能。。。。

接下來我們來實現用戶數據的刪除功能。在做刪除功能之前呢!有一個小功能需要實現,那就是用戶數據的全選與單個數據選擇的聯動功能,在刪除的時候很可能需要刪除多項或者全部刪除,全選與單選的聯動功能可以方便我們的刪除功能的使用。當然了這個聯動的功能不光是刪除需要,其他的功能也可以需要。總之,這個聯動的功能雖小,但是很實用。

 

                                          全選與單個用戶數據選擇的聯動功能

這個功能實現起來也很簡單,直接使用JavaScript腳本就可以完成,由於這個功能可能會在很多的地方被使用,所以應該是一個公共的方法來讓別人使用。首先檢查單個用戶數據選擇框全中的個數如果等於全部,那麼全選框也爲選中狀態,否則爲不選中狀態。再檢查如果全選框的狀態爲選中狀態,那麼所有的單選框都變爲選中狀態,否則爲不選中狀態。

在user.jsp頁面中引用這個common-js.jsp文件並調用這個公共的聯動方法,傳入全選框和單選框作爲參數。

運行效果。點擊全選按鈕,下邊所有的單選框也會跟着全部選中。

下邊的單選框只要有一個沒有選中,全選框就會取消選中。

ok。。。

有了這個全選的功能,那麼接下來我們實現的這個批量刪除功能就容易多了。

 

                                                         批量刪除功能

這個功能該如何實現呢?因爲我們的用戶列表中的id都是數據庫中存儲的真實id,所以我們根據id去刪除再好不過了。我們只需要在點擊批量刪除按鈕時,去獲取所有被選中的用戶信息中的id,並以這些id作爲刪除請求的參數告訴程序刪除即可。

先爲批量刪除按鈕添加一個id=“delAllBtn”,用於爲批量刪除按鈕綁定點擊事件。再在每個用戶的單選框元素中添加一個隱藏屬性del_id=“${user.id}”,用於保存該用戶的真實id,方便我們使用。

然後編寫JavaScript腳本,爲批量刪除添加點擊事件,獲取所有選中的用戶id併發送刪除請求。

好,user.jsp頁面修改好了,下面我們來實現刪除數據庫表中相關信息的代碼。

根據頁面請求地址與參數創建controller請求處理方法。

在UserServiceImpl的具體實現中爲了嚴謹一點,我們當然要區分是刪除單個id還是多個id啦!這樣比較通用。

好了,批量刪除功能的代碼碼完啦,運行一下試試看。。

先看看數據庫總的用戶數據,此時這一個用戶信息還存在。

點擊刪除後,第4頁消失了。

數據庫中的數據也正確刪除啦。

ok,批量刪除這個功能我們也這麼愉快的完成了。。。。

我們看批量刪除按鈕的旁邊還有一個新建的按鈕,這個按鈕是用來新建用戶的。新建用戶這個功能實現起來很簡單,基本與註冊功能一樣。只是多了一個頁面跳轉需要先跳轉到adduser.jsp頁面,然後基本與註冊功能一模一樣,這裏就不是實現了。

接下來我們再往下看,看看還有什麼功能。在用戶列表中,每一條用戶信息最後的操作列都有三個按鈕。依次分別是角色分配、編輯、與刪除三個按鈕。

那我們就先來說說角色分配按鈕吧!顧名思義,角色分配按鈕就是用來爲用戶分配角色的。還記得我們之前講過的權限管理RBAC模型嗎?就是基於角色的權限管理模型。角色與權限是多對多的關係,每個角色可以有多個權限,同時一個權限也可以被多個角色同時擁有。那麼用戶與權限是怎麼形成聯繫的呢?答案是用戶不與權限有直接的聯繫,而是通過角色間接的與權限關聯。那麼用戶與角色是什麼關係呢?角色與用戶當然也是多對多的關係啦,一個用戶可以有多種身份,同時一個身份也可以被很多人擁有。就比如人民解放軍這個身份被很多人擁有,但是他們每個人不光有解放軍這一個身份,同時他們還可以是一個父親、丈夫等等。

好了,扯得有點遠了。這裏的角色分配按鈕就是讓我們的用戶,與左側角色維護菜單中的某一個或某幾個角色產生聯繫的功能按鈕。接下來我們就來實現這個功能吧!

 

                                                             角色分配

我們回憶一下之前講過的RBAC權限模型,大家就會想起用戶與角色之間是多對多的關係。在數據庫中想要爲他們倆建立關聯關係,就需要一張中間表。這張中間表不幹別的,只需要記錄用戶與角色的對應關係即可。而角色分配這個功能正是用來操作這張表,已達到爲用戶分配角色的作用。

既然角色分配按鈕具有角色分配功能,那麼這個按鈕肯定是可以跳轉到角色分配頁面啦!我們先來看看角色分配頁面長什麼樣子吧!

頁面比較簡單,只有已分配角色和未分配角色兩個列表,和兩個分配與撤回的按鈕。

我們先把角色分配頁面添加到我們的項目中,讓角色分配按鈕可以跳轉到角色分配頁面之後再來實現別的功能吧!

在項目中添加原型頁面很簡單,這裏就不多說了,前面的我們有過詳細的講解,只需要三步就可以了。一,將原型頁面代碼中所有關於編碼的代碼統統改成UTF-8,並將頁面文件的編碼格式也改成UTF-8。二,拷貝到項目中,並添加jsp文件頭,保存、關閉文件。三,直接修改html文件後綴爲jsp就可以了。

先爲用戶列表中每個用戶的角色分配按鈕添加一個保存本用戶id的隱藏屬性u_id="${user.id}",再爲每個用戶的角色分配按鈕綁定點擊事件。因爲我們的用戶可能會很多,那麼用戶的角色分配按鈕同時也會很多,再爲按鈕綁定點擊事件是根據id綁定肯定是不明智的,應該根據class綁定。因爲class是可以充分出現的,而id不行,類型選擇器可以找到所有相同class的元素爲他們共同綁定事件。所以我們要爲所有用戶的角色分配按鈕定義一個共同的class=“assignBtn”。

爲所有角色分配按鈕綁定點擊事件,並添加請求,還要將原有的角色分配按鈕點擊事件刪除,否則他會給我們搗亂的。

刪除原有的角色分配按鈕點擊事件。

接下來我們去添加處理這個跳轉到角色分配頁面的請求controller,並可以正確跳轉都角色分配頁面。

添加好了,去試一下看看。。

ok,可以正常跳轉了。但是界面是花的,這是因爲我們把原型頁面添加到項目中是,只轉換了文件格式與後綴,並沒有修改樣式庫的依賴路徑,我們項目中的樣式依賴路徑與原型頁面的路徑不相同。找不到已添加的樣式所以纔會亂的。

修改依賴樣式庫的路徑非常簡單,根據我們項目的路徑自行修改就可以了。

好,可以正確的來到角色分配頁面啦。現在頁面中顯示的數據都是一些假數據。接下來我們要爲頁面添加真實的數據。真實的數據從哪來呢?當然是從數據庫表中查詢得到的啦!我們在處理角色分配按鈕點擊後發送的請求時,去數據庫中查詢某一個用戶已經擁有的角色和未分配的角色信息,並添加到域對象中,這樣跳轉到角色分配界面後就可以使用某一用戶的這些角色信息並且顯示出來了。

還記得我們爲每個用戶的角色分配按鈕都添加了一個隱藏的u_id=“${user.id}”嗎?就是爲了在點擊角色分配按鈕後發送請求的時候更方便的帶上這個用戶的id去查詢用戶的角色信息。既然用戶id已經傳遞過來了,那麼我們只要查詢相關的角色信息並且添加到域對象中即可。

那麼用戶已經擁有的角色和未擁有的角色應該如何查詢呢?已經擁有的可以訪問用戶和角色的中間表進行查詢。那麼未擁有的角色如何查詢呢?我們可以把角色表中的所有角色全部取出來減去用戶已擁有的角色不就得到了未擁有的角色嘛!

好,那我們就來先取得所有的角色信息與某一用戶已擁有的角色信息。

取得所有的角色信息比較簡單,只需要訪問角色表,查詢所有角色就可以了。

取得用戶已擁有的角色信息要稍微麻煩一點,因爲我們需要返回一個角色信息的list列表,而我們光去查詢用戶與角色的中間表的話,只能得到角色的id,這樣的話我們還要根據角色id去角色表中查詢角色然後才返回角色list。這樣做比較麻煩!我乾脆在角色表自動生成dao層的TRoleMapper中自定義添加一個多表聯合查詢方法好了,利用用戶id查詢擁有的角色id,再根據角色id返回角色list。

RoleServiceImpl.java中實現getAllRole()與getUserRole(Integer uid)兩個功能。getAllRole()不必多說,只需要調用自動生成的dao層接口roleMapper查詢所有角色返回list即可。

getUserRole(Integer uid)這個功能如何實現呢?自動生成的dao層接口roleMapper沒有現成的接口供我們使用,我們又不想先去查用戶與角色的關聯表後取得角色id,在根據角色id去查角色表,獲取角色list。這樣比較麻煩!我們乾脆在roleMapper中自定義一個可以多表聯合查詢的接口供我們使用。

光定義接口是沒有用的,我們還要去實現具體的sql語句,實現如何查詢。

好了,代碼的取得未分配角色與有分配角色的實現我們寫好了,並且添加到了域對象中,接下來我們修改角色分配頁面assignRole.jsp來域對象中取得數據,並顯示。

在修改assignRole.jsp時別忘了添加我們編寫的公共的左側菜單欄user_menu.jsp和設置展開與選中並高亮的樣式呦!

當然在assignRole.jsp中取得角色信息的時候會用到JSTL的東西<c:forEach>,我們也是在user_menu.jsp中引用的,所以只要引用user_menu.jsp就可以了,不需要再重新引用JSTL庫啦。

角色分配頁面assignRole.jsp我們也已經修改了。可是我們的數據庫表中還沒有數據,我需要造一些數據用於顯示。

爲角色表創建8個角色。

爲用戶與角色的關聯表,添加用戶id爲12的兩個角色信息,用戶12同時擁有5號與7號角色。

ok,我們去頁面看看效果。

哈哈,很好,是我們想要的效果。

接下來呢,我們看到角色分配頁面中有左、右兩個按鈕。他們他們分別代表分配角色、與撤回角色功能。某一用戶所擁有的真實角色信息顯示在了列表框中。下面我們就來實現一下角色的分配與撤回功能吧!

其實這兩個功能還是很好實現的,不過就是數據庫的添加與 刪除操作嘛!

角色分配頁面有兩個列表,左邊是未分配角色列表,右邊是已分配角色列表。那麼分配角色與撤銷角色功能都是相對於用戶而言的,也就是相對於右邊的已分配角色列表而做的操作。分配功能:就是講左邊未分配角色列表中醫選中的角色移動到右邊的已分配角色列表中。撤銷功能就是將右邊已分配角色列表中選中的角色移動到左邊的未分配角色列表中。同時還要對數據庫的用戶與角色關聯表進行添加月刪除操作,以實現真實數據的分配與撤銷。

在角色分配頁面assignRole.jsp中添加JavaScript腳本,爲分配與撤銷按鈕綁定單擊事件,實現點擊時將未分配列表中選擇了的角色數據移動到已分配列表中,或者將已分配列表中選擇了的角色數據移動到未分配列表中,並已用戶id與需要移動的角色id作爲參數發送添加或者刪除角色信息的請求。

找角色分配頁面中到分配與撤銷的按鈕,和兩個角色列表,併爲他們添加可以定位的標識。

爲分配角色和撤銷角色按鈕綁定點擊事件,併發送ajax請求。

這裏有個需要地方需要注意一下。var uid = "${param.uid}";是不是很奇怪,這個param.uid是哪來的?我們什麼時候設置的域對象?其實我們並沒有在域對象中添加過這個參數,而是本來就有這個param。這句話的意思是取出當前頁面的請求地址中的參數uid的值。param代表當前頁面請求地址中的所有參數。

我們繼續。接下來是controller,還記得我們在頁面中發送的事ajax請求嘛,也不需要返回什麼數據,但是我們希望ajax中的回調函數會被執行,用以提示所做的操作成功了,所以需要用到@ResponseBody這個註解。@ResponseBody的作用請參考:https://www.cnblogs.com/daimajun/p/7152970.html。

好,代碼寫完了。我們試一下。

再看看數據庫。

妥了,角色分配功能完成。

好了,接下來我們來實現角色維護這個功能。

 

                                                             角色維護

角色維護這個功能主要就是對角色的增刪改查功能,打開原型頁面看看。

大家有沒有覺得這個角色維護的角色列表界面也用戶維護的用戶列表頁面很像呢!事實也確實如此,除了顯示的數據列表中的數據不同外,他們基本相同。

所以這裏就不詳細的說具體實現啦!直接上圖吧。

添加角色頁面,修改依賴庫路徑。

添加左側公共菜單欄並設置選中高亮

爲查詢條件form添加請求連接,回顯查詢條件。爲批量刪除添加id,用於綁定點擊事件。顯示角色信息時,在域對象中取出所有角色數據並循環顯示。

修改原有的分頁菜單,每一個分頁按鈕都要添加請求地址並綁定相應頁面參數。

添加JavaScript腳本,爲批量刪除綁定點擊事件,攜帶刪除參數併發送批量刪除請求。

點分頁按鈕發送相關頁面查詢請求時,爲每個按鈕綁定項目的查詢信息。

設置全選框與單選框的聯動效果。

修改左側菜單欄中角色維護的請求地址。讓它訪問RoleController中的/permission/role/list請求。

在RoleController中處理頁面的角色列表查詢請求和批量刪除請求。

在RoleServiceImpl中添加按條件查詢角色和批量刪除兩個功能代碼。

完成了 。我們感受一下吧!

呵呵,有了前邊用戶維護功能的鋪墊,這個功能完全就是照着重寫了一下,很簡單。所以很快就完成啦。

那麼重點來了,接下來呢,我們要實現的功能是爲角色分配權限(也是分配維護)。之前實現用戶角色分配功能的做法是,點擊用戶的分配角色按鈕,跳轉到角色分配頁面進行分配角色。我們已經拿到了角色列表,也可以像之前爲用戶分配角色那樣去跳轉頁面,然後進行分配權限。不過,那種方式我們已經實現過了,照着之前的功能完全重寫一下顯然不是我們在這寫文章浪費時間的目的。這裏我們使用一種新方法,bootstrap的模態框以彈出框的形式顯示頁面,可以使頁面更炫酷,不用像之前那樣需要編寫controller的頁面跳轉,也更有逼格。嘻嘻。。下面我們來一起實現一下吧。

 

                                           角色分配權限並採用模態框顯示

我們先來試着顯示一個模態框吧!打開bootstrap的中文說明文檔查看一下。

經過查看文檔我們發現模態框是有靜態與動態之分的,我使用動態模態框就好了。使用方法也很簡單,只需要向下面一樣爲模態框的<div id=“myModal”>綁定事件,添加相應的顯示div,並且爲按鈕添加data-toggle="modal" 和data-target="#myModal"兩個屬性就可以了。

 

在角色維護頁面添加模態框的相關代碼。

爲角色的權限分配按鈕添加data-toggle="modal" 和data-target="#myModal"兩個屬性。

添加模態框中將要顯示的div,並且id與權限分配按鈕中相關屬性一致。添加JavaScript腳本綁定事件監聽。

還有就是,如果按鈕之前有定義點擊事件的話,需要禁用。

運行一下。

哈哈,成了。

這裏我們要做一個小修改,因爲這個模態框默認有一個關閉行爲,就是點擊模態框外邊的背景頁就會自動關閉。這個行爲對我們來說不是很友好。所以我們需要禁用這個點擊模態框外邊的背景就自動關閉的行爲。

怎麼禁用呢?呵呵,當然是查看說明文檔啦!

照着這個方法,我們在權限分配按鈕上添加data-backdrop="static"。

接下來我們來修改這個模態框的顯示,讓它變成我們需要的權限分配頁面的顯示。

首先我們的權限列表是一個樹形結構,還記得前一篇的文章中介紹過的zTree插件嗎?我們正是使用zTree來顯示一個樹的。

那我們先來顯示一個簡單的樹,然後再在樹中顯示真實的權限數據吧!

添加zTree需要的js與css,還有zTree依賴jQuery,所以需要添加jQuery的js。修改模態框中顯示權限樹的位置並設置id="permissionTree" class="ztree"。

使用簡單數據模式創建一棵樹,樹的節點與父節點對應的字段分別是id和pid。

ok,顯示一下。

好的,假數據可以顯示了,那下一步就是顯示我們需要的真實數據啦。

不過呢,這裏有一個地方需要做一下修改,那就是模態框的顯示方式需要修改。現在的做法是讓按鈕直接觸發模態框的同時並且爲模態框綁定監聽器,模態框顯示後向其中添加樹結構,這樣做對於我們獲取分配權限按鈕中r_id屬性的值很不方便。因爲我們在模態框中顯示的權限樹結構是根據角色id進行獲取的,所以我們採用另一種方式,直接爲按鈕綁定點擊事件,在JavaScript腳本事件中初始化樹結構並且以js的方式顯示模態框。

先將權限分配按鈕中之前添加的屬性刪除。

在爲按鈕綁定點擊事件。在事件中初始化權限樹,並主動顯示模態框。初始化權限樹時應該以當前按鈕所在角色的id做爲參數,獲取不同角色的權限樹。

運行看看,獲取的角色id正不正確?

ok,可以正確的獲取到權限分配按鈕所在角色的相關id啦。現在要在模態框中顯示真實的權限樹,並且顯示不同角色已經擁有的權限信息。

初始化權限樹時發生ajax請求獲取全部權限的JSON數據,並且指定zTree的配置信息idKey和pidKey的值,要與我們真實的權限數據中的id與pid對應起來,這樣才能正確的顯示出一棵權限樹(我們的已經在寫假數據時就指定並對應好了)。取得全部權限JSON數據後,我們還要在每個父節點中添加open:true屬性,使權限樹顯示時父節點自動展開。

獲取全部權限數據並返回JSON。

成功。

現在我們在模態框中顯示了全部的權限信息,那麼怎麼才能在這個全部信息的樹中看出某個角色擁有那些權限呢?我們可以爲整個權限樹的每個權限節點前面添加一個單選框,讓已擁有的權限前邊的單選框爲選中狀態,未擁有的爲未選中狀態,不就行啦!這樣爲某一角色分配未擁有的權限或者撤銷已擁有的權限時,只需要點擊單選框就可以啦。而這個整顆的每個節點前面都添加單選框的功能zTree已經幫我們實現啦,只需要在配置信息中設置一下就好啦。是不是很方便!!!所以,需要就去查文檔吧。

而且不光是在所有節點前添加了單選框,zTree還幫我們嗎做了子父節點單選框的關聯功能,默認是開啓的。

接下來我們將一號角色所擁有的權限顯示在這個權限樹中。

我們需要將初始化後的整顆權限樹保存起來,用以爲已擁有的權限做選中操作。選中操作zTree已經爲我們提供了,需要先根據樹中某個節點的信息取得這個節點,然後再對這個節點執行選中操作。注意這裏用來操作的樹!必須是我們之前初始化的對象,否則不行!

發送取得某個角色所擁有權限的請求,並根據返回的權限數據設置權限樹中那些是已擁有的,已擁有的爲勾選狀態。

處理根據角色rid取得權限JSON的請求。這裏爲了方便,自定義了一個多表聯查的dao層的數據庫查詢方法。

service層定義

dao層定義

編寫sql語句。

爲id爲1的角色創建權限信息。

運行。

好了,已經可以顯示某一角色已擁有的權限啦。接下來我們來實現爲這個角色分配權限的功能。權限樹我們可以操作,並且根據zTree的說明文檔可以獲取我們勾選後的所有權限節點,那麼我們如何分配權限呢?最簡單的方法就是,先刪除某一角色的所有權限,然後再將新分配的所有權限設置進去就行了,這樣做的優點就是:不需要考慮當前的權限分配操作對於已擁有的是新增還是刪除。

我們需要在模態框中點擊分配權限按鈕時獲取當前操作角色的id,以方便更新操作。角色列表的權限分配按鈕時由角色id數據的,我們要將這個數據傳遞給模態框中的分配權限按鈕。這樣在點擊模態框中分配權限按鈕時就可以輕易的拿到角色id啦。

先爲模態框中的分配權限按鈕綁定點擊事件。以權限樹中選中的所有權限id和角色id作爲參數,發送更新請求。在ajax的成功回調中隱藏模態框。

controller層處理更新請求。

service層處理更新的邏輯,應該先刪除,再添加。最好加上事務控制,這樣即使哪一步操作數據庫失敗了,也可以回滾,不會讓數據丟失啦。

運行試試。。

修改id爲1的角色的權限並點擊分配權限按鈕。

成功。。。

角色的權限分配功能我們實現了,可是我們打開權限分配的模態框會發現兩個小問題。一,點擊權限樹中的某個節點時,會發生頁面跳轉。二,權限樹中每個節點前面雖然有圖標,但並不是我們的圖標。那我們就來解決這兩個小問題吧 。

一,點擊權限樹中的某個節點時,發生頁面跳轉其實是發送了對某個頁面的請求,還記得我們數據庫中權限表是存在url屬性列的嘛!url列中保存的正是對某個頁面的請求地址,我們在取得權限信息時將某一權限的所有屬性都放到了某一個權限節點中,那麼這個節點也就擁有了以對某個頁面請求爲值的url屬性。而zTree在我們點擊某個樹的節點時,恰恰會訪問當前節點中的url屬性的地址。這個行爲是默認的,但是我們可以自行指定點擊樹節點時訪問url的key名稱。如果我們想點擊時不發生頁面跳轉,只需要將url的key名稱指定爲一個不存在的屬性名即可。

將 treeNode 的 haha屬性當做節點鏈接的目標 URL(haha屬性不存在),所以不會發送這個URL請求,也不會發生頁面跳轉。

二,樹中節點的圖標並不是我們自己定義並且想顯示的圖標。zTree默認會開啓圖標的顯示,並且也已經顯示了圖標,只是顯示的圖標是zTree默認定義的圖標,並不是我們需要的。如果我想顯示成我們自己定義的圖標的話,需要自定義顯示效果,添加JavaScript方法,並且在方法中可以隨意的修改節點的樣式,想怎麼改就怎麼改。

zTree的初始化設置中開啓自定義顯示效果,並指定自定義效果顯示函數名稱爲showIcon。在showIcon方法中我們根據當前節點所有屬性信息的命名規律確定圖標的id,然後爲當前節點的圖標屬性設置樣式(樣式信息我們是從數據庫中拿過來,並已經保存到了當前節點中的)。

我們的數據庫中只保存了前四個權限的icon信息。所以現在的模態框中其他的權限是沒有icon信息的。

好了,到這裏爲止,我們的角色維護功能就全部都完成啦。

至於下面的許可維護功能呢?我們已經實現了用戶維護和角色維護,不管是頁面跳轉還是使用模態框的形式,顯示數據列表或者顯示樹結構,我們都實現過了。無非就是權限數據表的crud。這裏就不再實現啦!只是有一個功能沒有實現,那就是帶按鈕的樹節點,這裏可以參考https://www.cnblogs.com/my-freedom/p/6627204.html。和zTree的說明文檔。

 

最後再附上例子程序,以供需要時查看:https://download.csdn.net/download/qq_25106373/11192181

 

 

 

 

 

 

                                                         

 

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