- 十多年前我开发了一个平台,除了一些插件,从底层框架到上层系统,从前端到后端,全部自研,至今已在此基础上开发了几十个项目,这次遇到国产化改革,我们的所有系统迁移即可,省了不少工作量,也少赚不少钱。。。哈哈。
- 当时设计的时候考虑到经常为一家单位开发好几套系统,但是每次都要把重复的内容配置一遍,用户还得记住N个账号密码、登录地址,所以前端采用了类操作系统的设计方案,每个账号进入平台后显示不同的授权应用(图标),点击图标后打开应用。
- 权限分两大块:一个是平台级的权限,另一个是应用级的权限,应用级的权限下放到应用自身,这样平台只需要管好不同的应用配置,把有权限的账号传递给应用就行了,而每个应用开发小组自己去定义权限和设计界面,整体有点类似单点登录,但又不完全相同。
- 当时舍弃了应用的概念,因为开发初代的时候发现应用下面还能套应用,可能这个应用只是个目录,而那个应用只打开个iframe,嵌入一个别的网站应用~~所以我引入了节点的概念,到处都是节点(与本文后面提到的节点还不是一个概念,更像是一个综合体),就像一张网,没有什么所谓的应用,第一层的node就显示在桌面,相当于应用了,如果还有第二层node就相当于文件夹,再打开一层。。。当时把node设计了五种类型,分别是 内容显示 、 快捷方式 、 节点夹 、 应用 、 执行功能。。。等等等等吧。
- 不过现在准备重构一遍系统,细节就不多说啦,我将把node硬拆成 App(应用)、Node(功能节点)、Menu(菜单) ,并分别落入概念中,三条路线进入权限系统。这里把它们之间的关系理顺一下,也算是分享一点思路。
重新定义系统结构
系统中包含多个 App(应用),每个应用下有多个 Node(功能节点),而 Menu(菜单) 则用于界面导航。通过权限管理系统来控制用户对不同 App、Node 和 Menu 的访问权限。
可以将系统抽象成以下几个层级:
- App(应用):系统中的独立模块,如培训应用、信息报送应用等。
- Node(功能节点):每个 App 下的具体功能点,如报名系统、证书系统、发送信息等。Node 可以跨应用共享。
- Menu(菜单):界面导航结构,用于展示用户可见的功能入口。Menu 可以与 Node 关联,也可以独立存在。
- 权限(Permission):权限需要控制到 App、Node、Menu 三个层面。
系统设计思路
为了实现需求,可采用以下的设计方案。这个方案将 App、Node、Menu 和 权限控制 统一到一个灵活的权限体系中。
数据库设计
我们需要设计以下几张核心表:
- App 表(应用表)
- Node 表(节点表)
- Menu 表(菜单表)
- Role 表(角色表)
- User 表(用户表)
- Permission 表(权限表,用于控制 App、Node 和 Menu 的访问)
- App_Node_Menu 表(关联表,用于定义 App、Node 和 Menu 之间的关系)
1. App
表(应用表)
CREATE TABLE App (
id INT PRIMARY KEY AUTO_INCREMENT,
app_name VARCHAR(50) NOT NULL,
description VARCHAR(255),
is_active BOOLEAN DEFAULT TRUE
);
字段解释:
id
: 应用的唯一标识。app_name
: 应用名称(如“培训应用”、“信息报送应用”)。description
: 应用描述。is_active
: 是否激活应用。
2. Node
表(功能节点表)
CREATE TABLE Node (
id INT PRIMARY KEY AUTO_INCREMENT,
node_name VARCHAR(50) NOT NULL,
description VARCHAR(255),
path VARCHAR(100), -- 对应功能的路由或 API
is_shared BOOLEAN DEFAULT FALSE, -- 是否为跨应用共享节点
is_active BOOLEAN DEFAULT TRUE
);
字段解释:
id
: 节点的唯一标识。node_name
: 节点名称(如“报名系统”、“发送信息”)。path
: 节点对应的路径或 API。is_shared
: 是否为跨应用共享节点。is_active
: 是否激活节点。
3. Menu
表(菜单表)
CREATE TABLE Menu (
id INT PRIMARY KEY AUTO_INCREMENT,
menu_name VARCHAR(50) NOT NULL,
app_id INT,
parent_id INT DEFAULT NULL,
node_id INT DEFAULT NULL, -- 可以关联到 Node
icon VARCHAR(50),
sort_order INT DEFAULT 0,
is_active BOOLEAN DEFAULT TRUE,
FOREIGN KEY (app_id) REFERENCES App(id),
FOREIGN KEY (node_id) REFERENCES Node(id)
);
字段解释:
id
: 菜单的唯一标识。menu_name
: 菜单名称。app_id
: 所属的应用 ID。parent_id
: 父级菜单 ID(用于菜单层级)。node_id
: 关联的节点 ID(可选)。icon
: 菜单图标。sort_order
: 菜单排序。is_active
: 是否激活菜单。
4. Role
表(角色表)
CREATE TABLE Role (
id INT PRIMARY KEY AUTO_INCREMENT,
role_name VARCHAR(50) NOT NULL,
description VARCHAR(255),
is_active BOOLEAN DEFAULT TRUE
);
5. User
表(用户表)
CREATE TABLE User (
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(50) NOT NULL,
password VARCHAR(100) NOT NULL,
role_id INT,
email VARCHAR(100),
is_active BOOLEAN DEFAULT TRUE,
FOREIGN KEY (role_id) REFERENCES Role(id)
);
6. Permission
表(权限表)
CREATE TABLE Permission (
id INT PRIMARY KEY AUTO_INCREMENT,
role_id INT,
app_id INT DEFAULT NULL,
node_id INT DEFAULT NULL,
menu_id INT DEFAULT NULL,
can_access BOOLEAN DEFAULT TRUE,
FOREIGN KEY (role_id) REFERENCES Role(id),
FOREIGN KEY (app_id) REFERENCES App(id),
FOREIGN KEY (node_id) REFERENCES Node(id),
FOREIGN KEY (menu_id) REFERENCES Menu(id)
);
字段解释:
role_id
: 角色 ID。app_id
: 应用 ID(可为空)。node_id
: 节点 ID(可为空)。menu_id
: 菜单 ID(可为空)。can_access
: 是否有权限访问。
7. App_Node_Menu
表(关联表)
CREATE TABLE App_Node_Menu (
id INT PRIMARY KEY AUTO_INCREMENT,
app_id INT,
node_id INT,
menu_id INT,
FOREIGN KEY (app_id) REFERENCES App(id),
FOREIGN KEY (node_id) REFERENCES Node(id),
FOREIGN KEY (menu_id) REFERENCES Menu(id)
);
业务逻辑
-
App、Node 和 Menu 的关系:
- App 表示独立的应用模块。
- Node 表示具体的功能点,可以在多个 App 之间共享。
- Menu 用于前端导航,可以关联到 Node,也可以是纯粹的目录。
-
权限控制:
- 用户基于 Role 拥有不同的权限。
- 权限控制可以细化到 App、Node 和 Menu 三个层面。
- 通过
Permission
表,可以灵活配置用户对不同应用、功能和菜单的访问权限。
-
跨应用共享功能:
- 通过设置 Node 的
is_shared
属性,可以在多个 App 之间共享功能。 App_Node_Menu
表可以帮助定义跨应用的 Node 和 Menu 关系。
- 通过设置 Node 的
示例场景
假设有以下场景:
-
培训应用 包含:
- 报名系统(Node)
- 证书管理(Node)
-
信息报送应用 包含:
- 发送信息(Node,与内容管理应用共享)
- 查看报表(Node)
-
权限配置:
- 管理员可以访问所有 App 和 Node。
- 普通用户只能访问培训应用的“报名系统”功能。
查询逻辑示例
-
获取用户可见的应用:
SELECT a.* FROM App a JOIN Permission p ON p.app_id = a.id WHERE p.role_id = ? AND p.can_access = TRUE;
-
获取应用下的菜单:
SELECT m.* FROM Menu m JOIN Permission p ON p.menu_id = m.id WHERE p.role_id = ? AND p.can_access = TRUE AND m.app_id = ?;
-
判断用户是否有权限访问某个 Node:
SELECT COUNT(*) FROM Permission p WHERE p.role_id = ? AND p.node_id = ? AND p.can_access = TRUE;
总结
这个设计方案较为简单地实现了 App、Node 、 Menu 和 User 之间的关系,通过 Permission 表实现了灵活的权限控制。这样不仅支持跨应用的功能共享,还能通过权限配置实现更细粒度的访问控制。
当然这套方案相对还是比较简单地,实际应用时,应用节点和菜单之间并不完全独立,比如node
要绑定app
,menu
要分配多个node,user
可以设置多个role
。。。等等吧,只有这样才能真正满足实际需求,至少功能不能比以前的少太多吧😊