コードはあまりにも醜いので、それをコピーすることはお勧めできません。普遍的な RBAC の実装アイデアを参照してください。
git clone https://github.com/wjkang/d2-admin-pm.git
npm install
npm start
バックエンドのモックサービスからのサポートが必要です
git clone https://github.com/wjkang/d2-admin-server.git
npm install
npm start
main.js
でcreated
内容をrouter/index.js
に転送し、関連するロジックを追加します。
axios関連のコードplugin/axios/index.js
変更して、インターフェイス レベルの権限制御をサポートし、エフェクトの読み込み設定をサポートするようにしました。
メニューモジュールを vuex ストアに追加し、 fullAsideを追加します。フル パスはstore.state.d2admin.menu.fullAside
です。
権限モジュールを vuex ストアに追加して、ユーザーの機能権限コード、ロール コード、アクセス権限を持つインターフェイス、および管理者 ID が有効であるかどうかを保存します。
export default {
namespaced : true ,
state : {
//功能编码
functions : [ ] ,
//角色编码
roles : [ ] ,
//接口
interfaces : {
GET : [ ] ,
POST : [ ] ,
PUT : [ ] ,
DELETE : [ ]
} ,
//是否管理员
isAdmin : false
} ,
mutations : {
set ( state , data ) {
state . functions = data . functions ;
state . roles = data . roles ;
state . isAdmin = data . isAdmin ;
state . interfaces = data . interfaces ;
}
}
}
vuex ストアのaccount
モジュールのload
アクションのこの部分:
// DB -> store 持久化数据加载上次退出时的多页列表
await dispatch ( 'd2admin/page/openedLoad' , null , { root : true } )
router/index.js
に移動します。許可ルートをロードした後に実行する必要があります。
菜单
情報功能
格納します。メニューには複数の機能が存在します。菜单
タイプのpermission
フィールドはpermission
このメニューにアクセスするために必要な功能
権限を識別します。この関数のエイリアス、つまり菜单
タイプpermission
フィールドは、功能
タイプの子ノードのpermission
値です。permission
フィールドを介してアクセスできるルートをフィルターで除外します。グローバル ルーティング ガードは、 d2admin
の元のログイン ロジックを使用して、権限情報が取得されたかどうかを判断し、取得後にその情報を取得済みとしてマークします。
バックエンドが返す必要のある権限情報には、権限フィルタリング後のロールコードセット、機能コードセット、インタフェース情報セット、メニューリスト、ルーティングリスト、システム管理者の識別の有無などが含まれる。形式は次のとおりです
{
"statusCode" : 200 ,
"msg" : "" ,
"data" : {
"userName" : "MenuManager" ,
"userRoles" : [
"R_MENUADMIN"
] ,
"userPermissions" : [
"p_menu_view" ,
"p_menu_edit" ,
"p_menu_menu"
] ,
"accessMenus" : [
{
"title" : "系统" ,
"path" : "/system" ,
"icon" : "cogs" ,
"children" : [
{
"title" : "系统设置" ,
"icon" : "cogs" ,
"children" : [
{
"title" : "菜单管理" ,
"path" : "/system/menu" ,
"icon" : "th-list"
}
]
} ,
{
"title" : "组织架构" ,
"icon" : "pie-chart" ,
"children" : [
{
"title" : "部门管理" ,
"icon" : "html5"
} ,
{
"title" : "职位管理" ,
"icon" : "opencart"
}
]
}
]
}
] ,
"accessRoutes" : [
{
"name" : "System" ,
"path" : "/system" ,
"component" : "layoutHeaderAside" ,
"componentPath" : "layout/header-aside/layout" ,
"meta" : {
"title" : "系统设置" ,
"cache" : true
} ,
"children" : [
{
"name" : "MenuPage" ,
"path" : "/system/menu" ,
"component" : "menu" ,
"componentPath" : "pages/sys/menu/index" ,
"meta" : {
"title" : "菜单管理" ,
"cache" : true
}
} ,
{
"name" : "RoutePage" ,
"path" : "/system/route" ,
"component" : "route" ,
"componentPath" : "pages/sys/route/index" ,
"meta" : {
"title" : "路由管理" ,
"cache" : true
}
} ,
{
"name" : "RolePage" ,
"path" : "/system/role" ,
"component" : "role" ,
"componentPath" : "pages/sys/role/index" ,
"meta" : {
"title" : "角色管理" ,
"cache" : true
}
} ,
{
"name" : "UserPage" ,
"path" : "/system/user" ,
"component" : "user" ,
"componentPath" : "pages/sys/user/index" ,
"meta" : {
"title" : "用户管理" ,
"cache" : true
}
} ,
{
"name" : "InterfacePage" ,
"path" : "/system/interface" ,
"component" : "interface" ,
"meta" : {
"title" : "接口管理"
}
}
]
}
] ,
"accessInterfaces" : [
{
"path" : "/menu/:id" ,
"method" : "get"
} ,
{
"path" : "/menu" ,
"method" : "get"
} ,
{
"path" : "/menu/save" ,
"method" : "post"
} ,
{
"path" : "/interface/paged" ,
"method" : "get"
}
] ,
"isAdmin" : 0 ,
"avatarUrl" : "https://api.adorable.io/avatars/85/[email protected]"
}
}
固定メニュー ( /menu/header
、 /menu/aside
) をバックエンドから返された権限メニュー ( accessMenus
) とマージし、対応する vuex ストア モジュールに保存します。
...
let allMenuAside = [ ... menuAside , ... permissionMenu ]
let allMenuHeader = [ ... menuHeader , ... permissionMenu ]
. . .
// 设置顶栏菜单
store . commit ( 'd2admin/menu/headerSet' , allMenuHeader )
// 设置侧边栏菜单
store . commit ( 'd2admin/menu/fullAsideSet' , allMenuAside )
// 初始化菜单搜索功能
store . commit ( 'd2admin/search/init' , allMenuHeader )
デフォルトでは、 routerMapComponents
バックエンドから返された許可ルートを処理するために使用されます。
//处理动态添加的路由
const formatRoutes = function ( routes ) {
routes . forEach ( route => {
route . component = routerMapComponents [ route . component ]
if ( route . children ) {
formatRoutes ( route . children )
}
} )
}
. . .
formatRoutes ( permissionRouter )
//动态添加路由
router . addRoutes ( permissionRouter ) ;
// 处理路由 得到每一级的路由设置
store . commit ( 'd2admin/page/init' , [ ... frameInRoutes , ... permissionRouter ] )
ルーティングの処理方法や違いについては、後述の関連記事を参照してください。
役割コーディング セット、機能コーディング セット、インターフェイス情報セット、およびシステム管理者 ID が対応する vuex ストア モジュールに保存されているかどうかを保存します。
...
permission . functions = userPermissionInfo . userPermissions
permission . roles = userPermissionInfo . userRoles
permission . interfaces = util . formatInterfaces ( userPermissionInfo . accessInterfaces )
permission . isAdmin = userPermissionInfo . isAdmin == 1
. . .
// 设置权限信息
store . commit ( 'd2admin/permission/set' , permission )
次のように、ロールコーディング、関数コーディング、インターフェイス権限を使用した制御をサポートします。
export function getMenuList ( ) {
return request ( {
url : '/menu' ,
method : 'get' ,
interfaceCheck : true ,
permission : [ "p_menu_view" ] ,
loading : {
type : 'loading' ,
options : {
fullscreen : true ,
lock : true ,
text : '加载中...' ,
spinner : 'el-icon-loading' ,
background : 'rgba(0, 0, 0, 0.8)'
}
} ,
success : {
type : 'message' ,
options : {
message : '加载菜单成功' ,
type : 'success'
}
}
} )
}
interfaceCheck: true
は、vuex ストアに保存されているインターフェイス情報が現在リクエストされているインターフェイスと一致する場合、リクエストを開始できます。そうでない場合、リクエストはインターセプトされます。
permission:["p_menu_view"]
権限の検証にロール コーディングと関数コーディングを使用することを意味します。vuex ストアに保存されているロール コーディングまたは関数コーディングが現在表現されているコーディングと一致する場合、リクエストを開始できます。そうでない場合、リクエストはインターセプトされます。
ソース コードはlibs/permission.js
にあり、必要に応じて変更できます。
loading
設定に関連するソース コードsuccess
libs/loading.js
にあり、必要に応じて設定できます。 ソース コードはlibs/loading.js
にあります。 このアイデアに従って、リクエストの失敗などの他の機能を自分で設定できます。
ディレクティブv-permission
を使用します。
< el-button
v-permission:function.all =" ['p_menu_edit'] "
type =" primary "
icon =" el-icon-edit "
size =" mini "
@click =" batchEdit "
>批量编辑</ el-button >
パラメーターはfunction
またはrole
にすることができ、関数コーディングまたはロールコーディングが検証に使用されることを示します。これが空の場合、両方が検証に使用されます。
修飾子all
命令値内のすべてのコードが一致する必要があることを意味します。
ソース コードはplugin/permission/index.js
にあり、実際のニーズに応じて変更できます。
v-if
+ グローバルメソッドを使用します。
< el-button
v-if =" canAdd "
type =" primary "
icon =" el-icon-circle-plus-outline "
size =" mini "
@click =" add "
>添加</ el-button >
data ( ) {
return {
canAdd : this . hasPermissions ( [ "p_menu_edit" ] )
} ;
} ,
デフォルトでは、ロールコーディングと関数コーディングの両方が検証に使用され、そのうちの 1 つだけが一致します。
同様のメソッドには、 hasFunctions
およびhasRoles
も含まれます。
ソース コードはplugin/permission/index.js
にあり、実際のニーズに応じて変更できます。
v-if="hasPermissions(['p_menu_edit'])"
は使用しないでください。メソッドが複数回実行されることになります。
コンポーネント内の vuex ストアから権限情報を直接読み取り、検証することもできます。
ページレベルのコンポーネントは、 pages/
ディレクトリに配置され、 routerMapCompnonents/index.js
のキーと値の形式でエクスポートされます。
権限制御を必要としない固定メニューはmenu/aside.js
とmenu/header.js
に配置されます。
権限制御を必要としないルートはrouter/routes.js
のframeIn
に配置されます。
権限制御が必要なメニューおよびルートは、インターフェイスの管理機能を通じて追加されます。ルートのname
がページ コンポーネントのname
と一致する場合にのみ、メニューのpath
がルートのpath
に対応するようにしてください。 keep-alive
有効になります。ルートのcomponent
routerMapCompnonents/index.js
。
開発段階でのメニューやルートの追加は開発者自身が保守でき、オンライン化後はリストを保守のために関係者に引き渡すことができます。
それが面倒でバックエンドからメニューとルートを返したくない場合は、フロントエンドでメニューとルートを維持することができます (ルート内の
component
まだ文字列を使用しています。mockmock/permissionMenuAndRouter.js
を参照してください)。メニューとルートの対応する権限 コーディングでは、通常、関数型コーディングが使用されます。バックエンドはメニューやルーティング情報を返す必要はありませんが、ロールコーディングや関数コーディングなどの他の許可情報は依然として必要です。バックエンドによって返された関数コード リストを通じて、ユーザーがアクセス許可を持っているメニューとルートがフロントエンドでフィルタリングされ、フィルタリングされたメニューとルートの形式は、バックエンドによって以前に返された形式と一致し、その後、処理されたメニューになります。ルートはバックエンドとして使用され、クライアントから返されたものと同じように処理します。
データ モックは、lazy-mock から変更された d2-admin-server を使用します。他のツールと比較して、データの永続化をサポートしており、データベースをインストールする必要はありません。簡単な設定で、追加、削除、変更、クエリ用のインターフェースを自動生成できます。詳しい使用方法については、lazy-mock のドキュメントを参照してください。
バックエンドは、次のようなミドルウェアを使用してアクセス許可を制御します。
. get ( '/menu' , PermissionCheck ( ) , controllers . menu . getMenuList )
PermissionCheck
デフォルトで検証用のインターフェイスを使用して、ユーザーがアクセスできる API が現在の API と一致するかどうかを検証します。検証用の関数コーディングとロール コーディングの使用をPermissionCheck(["p_menu_edit"],["r_menu_admin"],true)
します。 , 第 1 章のパラメータは機能コード、2 番目は役割コード、3 番目は検証にインターフェイスを使用するかどうかです。
フロントエンドのコード生成はまだ開発中です...
vue パーミッションルーティング実装方法のまとめ vue パーミッションルーティング実装方法のまとめ 2. エンタープライズ管理システム フロントエンド・バックエンド分離アーキテクチャ設計シリーズ 1. パーミッションモデル