Golang企业级后台管理系统常用模型代码
·
这是一套基于 GORM v2 的企业级后台管理系统常用模型代码。按照国内主流后台框架(如 RuoYi、Gin-Vue-Admin)的最佳实践设计,包含完整的 GORM 标签、列名映射、注释、JSON 序列化及软删除支持。
为方便阅读与直接复制,代码已按业务模块拆分,并附带了工程结构建议与运行时组件说明。
📦 基础工程结构建议
models/
├── base.go # 公共基础模型
├── sys_auth.go # 用户、部门、岗位、菜单、角色
├── sys_dict_config.go # 字典、参数
├── sys_log_notice.go # 通知、操作日志、登录日志
├── sys_job.go # 定时任务及日志
└── sys_gen.go # 代码生成元数据
1. 公共基础模型 (base.go)
package models
import (
"time"
"gorm.io/gorm"
)
// BaseModel 公共字段,建议嵌入到所有模型中
type BaseModel struct {
ID uint `gorm:"primaryKey;autoIncrement;comment:主键ID" json:"id"`
CreateBy string `gorm:"size:64;comment:创建者" json:"createBy"`
CreateTime time.Time `gorm:"autoCreateTime;comment:创建时间" json:"createTime"`
UpdateBy string `gorm:"size:64;comment:更新者" json:"updateBy"`
UpdateTime time.Time `gorm:"autoUpdateTime;comment:更新时间" json:"updateTime"`
Remark string `gorm:"size:500;comment:备注" json:"remark"`
DeletedAt gorm.DeletedAt `gorm:"index;comment:软删除标记" json:"-"`
}
2. 核心权限模型 (sys_auth.go)
package models
import "gorm.io/gorm"
// SysUser 用户管理表
type SysUser struct {
BaseModel
DeptID uint `gorm:"column:dept_id;comment:所属部门ID" json:"deptId"`
UserName string `gorm:"column:user_name;size:30;not null;comment:用户账号" json:"userName"`
NickName string `gorm:"column:nick_name;size:30;not null;comment:用户昵称" json:"nickName"`
UserType string `gorm:"column:user_type;size:2;default:'00';comment:用户类型(00系统用户)" json:"userType"`
Email string `gorm:"column:email;size:50;default:'';comment:用户邮箱" json:"email"`
Phonenumber string `gorm:"column:phonenumber;size:11;default:'';comment:手机号码" json:"phonenumber"`
Sex string `gorm:"column:sex;size:1;default:'0';comment:性别(0男 1女 2未知)" json:"sex"`
Avatar string `gorm:"column:avatar;size:100;default:'';comment:头像地址" json:"avatar"`
Password string `gorm:"column:password;size:100;not null;comment:密码" json:"-"`
Status string `gorm:"column:status;size:1;default:'0';comment:帐号状态(0正常 1停用)" json:"status"`
DelFlag string `gorm:"column:del_flag;size:1;default:'0';comment:删除标志(0代表存在 2代表删除)" json:"-"`
LoginIP string `gorm:"column:login_ip;size:128;default:'';comment:最后登录IP" json:"loginIP"`
LoginDate string `gorm:"column:login_date;comment:最后登录时间" json:"loginDate"`
PostID string `gorm:"column:post_ids;type:varchar(255);default:'';comment:岗位ID组(逗号分隔)" json:"postIds"`
}
func (SysUser) TableName() string { return "sys_user" }
// SysDept 部门管理表 (树形结构)
type SysDept struct {
BaseModel
ParentID uint `gorm:"column:parent_id;default:0;comment:父部门ID" json:"parentId"`
Ancestors string `gorm:"column:ancestors;size:50;default:'';comment:祖级列表" json:"ancestors"`
DeptName string `gorm:"column:dept_name;size:30;not null;comment:部门名称" json:"deptName"`
OrderNum int `gorm:"column:order_num;default:0;comment:显示顺序" json:"orderNum"`
Leader string `gorm:"column:leader;size:20;comment:负责人" json:"leader"`
Phone string `gorm:"column:phone;size:11;comment:联系电话" json:"phone"`
Email string `gorm:"column:email;size:50;comment:邮箱" json:"email"`
Status string `gorm:"column:status;size:1;default:'0';comment:部门状态(0正常 1停用)" json:"status"`
}
func (SysDept) TableName() string { return "sys_dept" }
// SysPost 岗位管理表
type SysPost struct {
BaseModel
PostCode string `gorm:"column:post_code;size:64;not null;comment:岗位编码" json:"postCode"`
PostName string `gorm:"column:post_name;size:50;not null;comment:岗位名称" json:"postName"`
PostSort int `gorm:"column:post_sort;default:0;comment:显示顺序" json:"postSort"`
Status string `gorm:"column:status;size:1;default:'0';comment:状态(0正常 1停用)" json:"status"`
}
func (SysPost) TableName() string { return "sys_post" }
// SysMenu 菜单管理表
type SysMenu struct {
MenuID uint `gorm:"primaryKey;autoIncrement;column:menu_id;comment:菜单ID" json:"menuId"`
MenuName string `gorm:"column:menu_name;size:50;not null;comment:菜单名称" json:"menuName"`
ParentID uint `gorm:"column:parent_id;default:0;comment:父菜单ID" json:"parentId"`
OrderNum int `gorm:"column:order_num;default:0;comment:显示顺序" json:"orderNum"`
Path string `gorm:"column:path;size:200;default:'';comment:路由地址" json:"path"`
Component string `gorm:"column:component;size:255;comment:组件路径" json:"component"`
Query string `gorm:"column:query;size:255;default:'';comment:路由参数" json:"query"`
RouteName string `gorm:"column:route_name;size:50;default:'';comment:路由名称" json:"routeName"`
IsFrame int `gorm:"column:is_frame;default:1;comment:是否为外链(0是 1否)" json:"isFrame"`
IsCache int `gorm:"column:is_cache;default:0;comment:是否缓存(0缓存 1不缓存)" json:"isCache"`
MenuType string `gorm:"column:menu_type;size:1;default:'M';comment:菜单类型(M目录 C菜单 F按钮)" json:"menuType"`
Visible string `gorm:"column:visible;size:1;default:'0';comment:菜单状态(0显示 1隐藏)" json:"visible"`
Status string `gorm:"column:status;size:1;default:'0';comment:菜单状态(0正常 1停用)" json:"status"`
Perms string `gorm:"column:perms;size:100;comment:权限标识" json:"perms"`
Icon string `gorm:"column:icon;size:100;default:'#';comment:菜单图标" json:"icon"`
BaseModel `gorm:"embedded"` // 使用嵌套避免重复ID
}
func (SysMenu) TableName() string { return "sys_menu" }
// SysRole 角色管理表 (含数据权限)
type SysRole struct {
BaseModel
RoleName string `gorm:"column:role_name;size:30;not null;comment:角色名称" json:"roleName"`
RoleKey string `gorm:"column:role_key;size:100;not null;comment:角色权限字符串" json:"roleKey"`
RoleSort int `gorm:"column:role_sort;default:0;comment:显示顺序" json:"roleSort"`
DataScope string `gorm:"column:data_scope;size:1;default:'1';comment:数据范围(1全部数据权限 2自定 3本部门 4本部门及以下 5仅本人)" json:"dataScope"`
MenuCheckStrictly int `gorm:"column:menu_check_strictly;default:1;comment:菜单树选择项是否关联显示" json:"menuCheckStrictly"`
DeptCheckStrictly int `gorm:"column:dept_check_strictly;default:1;comment:部门树选择项是否关联显示" json:"deptCheckStrictly"`
Status string `gorm:"column:status;size:1;default:'0';comment:角色状态(0正常 1停用)" json:"status"`
}
func (SysRole) TableName() string { return "sys_role" }
// 关联表提示(GORM 多对多自动管理)
type SysUserRole struct {
UserID uint `gorm:"primaryKey;column:user_id"`
RoleID uint `gorm:"primaryKey;column:role_id"`
}
func (SysUserRole) TableName() string { return "sys_user_role" }
type SysRoleMenu struct {
RoleID uint `gorm:"primaryKey;column:role_id"`
MenuID uint `gorm:"primaryKey;column:menu_id"`
}
func (SysRoleMenu) TableName() string { return "sys_role_menu" }
type SysRoleDept struct {
RoleID uint `gorm:"primaryKey;column:role_id"`
DeptID uint `gorm:"primaryKey;column:dept_id"`
}
func (SysRoleDept) TableName() string { return "sys_role_dept" }
3. 字典与参数模型 (sys_dict_config.go)
package models
// SysDictType 字典类型表
type SysDictType struct {
BaseModel
DictName string `gorm:"column:dict_name;size:100;default:'';comment:字典名称" json:"dictName"`
DictType string `gorm:"column:dict_type;size:100;uniqueIndex;not null;comment:字典类型" json:"dictType"`
Status string `gorm:"column:status;size:1;default:'0';comment:状态(0正常 1停用)" json:"status"`
}
func (SysDictType) TableName() string { return "sys_dict_type" }
// SysDictData 字典数据表
type SysDictData struct {
BaseModel
DictSort int `gorm:"column:dict_sort;default:0;comment:字典排序" json:"dictSort"`
DictLabel string `gorm:"column:dict_label;size:100;comment:字典标签" json:"dictLabel"`
DictValue string `gorm:"column:dict_value;size:100;comment:字典键值" json:"dictValue"`
DictType string `gorm:"column:dict_type;size:100;index;comment:字典类型" json:"dictType"`
CSSClass string `gorm:"column:css_class;size:100;comment:样式属性" json:"cssClass"`
ListClass string `gorm:"column:list_class;size:100;comment:表格回显样式" json:"listClass"`
IsDefault string `gorm:"column:is_default;size:1;default:'N';comment:是否默认(Y是 N否)" json:"isDefault"`
Status string `gorm:"column:status;size:1;default:'0';comment:状态(0正常 1停用)" json:"status"`
}
func (SysDictData) TableName() string { return "sys_dict_data" }
// SysConfig 参数管理表
type SysConfig struct {
BaseModel
ConfigName string `gorm:"column:config_name;size:100;default:'';comment:参数名称" json:"configName"`
ConfigKey string `gorm:"column:config_key;size:100;uniqueIndex;comment:参数键名" json:"configKey"`
ConfigValue string `gorm:"column:config_value;size:500;default:'';comment:参数键值" json:"configValue"`
ConfigType string `gorm:"column:config_type;size:1;default:'N';comment:系统内置(Y是 N否)" json:"configType"`
}
func (SysConfig) TableName() string { return "sys_config" }
4. 通知公告与日志模型 (sys_log_notice.go)
package models
import "time"
// SysNotice 通知公告表
type SysNotice struct {
NoticeID uint `gorm:"primaryKey;autoIncrement;column:notice_id;comment:公告ID" json:"noticeId"`
NoticeTitle string `gorm:"column:notice_title;size:50;not null;comment:公告标题" json:"noticeTitle"`
NoticeType string `gorm:"column:notice_type;size:1;comment:公告类型(1通知 2公告)" json:"noticeType"`
NoticeContent string `gorm:"column:notice_content;type:longtext;comment:公告内容" json:"noticeContent"`
Status string `gorm:"column:status;size:1;default:'0';comment:公告状态(0正常 1关闭)" json:"status"`
BaseModel `gorm:"embedded"`
}
func (SysNotice) TableName() string { return "sys_notice" }
// SysOperLog 操作日志表
type SysOperLog struct {
OperID uint `gorm:"primaryKey;autoIncrement;column:oper_id;comment:日志主键" json:"operId"`
Title string `gorm:"column:title;size:50;default:'';comment:模块标题" json:"title"`
BusinessType string `gorm:"column:business_type;size:20;default:'0';comment:业务类型(0其它 1新增 2修改 3删除)" json:"businessType"`
Method string `gorm:"column:method;size:100;default:'';comment:方法名称" json:"method"`
RequestMethod string `gorm:"column:request_method;size:10;default:'';comment:请求方式" json:"requestMethod"`
OperatorType string `gorm:"column:operator_type;size:1;default:'0';comment:操作类别" json:"operatorType"`
OperName string `gorm:"column:oper_name;size:50;default:'';comment:操作人员" json:"operName"`
DeptName string `gorm:"column:dept_name;size:50;default:'';comment:部门名称" json:"deptName"`
OperURL string `gorm:"column:oper_url;size:255;default:'';comment:请求URL" json:"operUrl"`
OperIP string `gorm:"column:oper_ip;size:128;default:'';comment:主机地址" json:"operIp"`
OperLocation string `gorm:"column:oper_location;size:255;default:'';comment:操作地点" json:"operLocation"`
OperParam string `gorm:"column:oper_param;type:longtext;default:'';comment:请求参数" json:"operParam"`
JSONResult string `gorm:"column:json_result;type:longtext;default:'';comment:返回参数" json:"jsonResult"`
Status string `gorm:"column:status;size:1;default:'0';comment:操作状态(0正常 1异常)" json:"status"`
ErrorMsg string `gorm:"column:error_msg;size:2000;default:'';comment:错误消息" json:"errorMsg"`
OperTime time.Time `gorm:"column:oper_time;comment:操作时间" json:"operTime"`
}
func (SysOperLog) TableName() string { return "sys_oper_log" }
// SysLogininfor 登录日志表
type SysLogininfor struct {
InfoID uint `gorm:"primaryKey;autoIncrement;column:info_id;comment:访问ID" json:"infoId"`
UserName string `gorm:"column:user_name;size:50;default:'';comment:用户账号" json:"userName"`
Ipaddr string `gorm:"column:ipaddr;size:128;default:'';comment:登录IP地址" json:"ipaddr"`
LoginLocation string `gorm:"column:login_location;size:255;default:'';comment:登录地点" json:"loginLocation"`
Browser string `gorm:"column:browser;size:50;default:'';comment:浏览器类型" json:"browser"`
OS string `gorm:"column:os;size:50;default:'';comment:操作系统" json:"os"`
Status string `gorm:"column:status;size:1;default:'0';comment:登录状态(0成功 1失败)" json:"status"`
Msg string `gorm:"column:msg;size:255;default:'';comment:提示消息" json:"msg"`
LoginTime time.Time `gorm:"column:login_time;comment:访问时间" json:"loginTime"`
}
func (SysLogininfor) TableName() string { return "sys_logininfor" }
5. 定时任务模型 (sys_job.go)
package models
import "time"
// SysJob 定时任务调度表
type SysJob struct {
JobID uint `gorm:"primaryKey;autoIncrement;column:job_id;comment:任务ID" json:"jobId"`
JobName string `gorm:"column:job_name;size:64;default:'';comment:任务名称" json:"jobName"`
JobGroup string `gorm:"column:job_group;size:64;default:'DEFAULT';comment:任务组名" json:"jobGroup"`
InvokeTarget string `gorm:"column:invoke_target;size:500;not null;comment:调用目标字符串" json:"invokeTarget"`
CronExpression string `gorm:"column:cron_expression;size:255;default:'';comment:cron执行表达式" json:"cronExpression"`
MisfirePolicy string `gorm:"column:misfire_policy;size:20;default:'3';comment:计划执行错误策略(1立即执行 2执行一次 3放弃执行)" json:"misfirePolicy"`
Concurrent string `gorm:"column:concurrent;size:1;default:'1';comment:是否并发执行(0允许 1禁止)" json:"concurrent"`
Status string `gorm:"column:status;size:1;default:'0';comment:状态(0正常 1暂停)" json:"status"`
BaseModel `gorm:"embedded"`
}
func (SysJob) TableName() string { return "sys_job" }
// SysJobLog 定时任务调度日志表
type SysJobLog struct {
JobLogID uint `gorm:"primaryKey;autoIncrement;column:job_log_id;comment:任务日志ID" json:"jobLogId"`
JobName string `gorm:"column:job_name;size:64;comment:任务名称" json:"jobName"`
JobGroup string `gorm:"column:job_group;size:64;comment:任务组名" json:"jobGroup"`
InvokeTarget string `gorm:"column:invoke_target;size:500;comment:调用目标字符串" json:"invokeTarget"`
JobMessage string `gorm:"column:job_message;size:500;comment:日志信息" json:"jobMessage"`
Status string `gorm:"column:status;size:1;default:'0';comment:执行状态(0正常 1失败)" json:"status"`
ExceptionInfo string `gorm:"column:exception_info;type:longtext;default:'';comment:异常信息" json:"exceptionInfo"`
StartTime time.Time `gorm:"column:start_time;comment:开始时间" json:"startTime"`
StopTime time.Time `gorm:"column:stop_time;comment:停止时间" json:"stopTime"`
}
func (SysJobLog) TableName() string { return "sys_job_log" }
6. 代码生成元数据模型 (sys_gen.go)
package models
// SysGenTable 代码生成表定义
type SysGenTable struct {
TableID uint `gorm:"primaryKey;autoIncrement;column:table_id;comment:编号" json:"tableId"`
TableName string `gorm:"column:table_name;size:200;default:'';comment:表名称" json:"tableName"`
TableComment string `gorm:"column:table_comment;size:500;default:'';comment:表描述" json:"tableComment"`
SubTableName string `gorm:"column:sub_table_name;size:64;comment:关联子表的表名" json:"subTableName"`
SubTableFKName string `gorm:"column:sub_table_fk_name;size:64;comment:子表关联的外键列" json:"subTableFKName"`
ClassName string `gorm:"column:class_name;size:100;default:'';comment:实体类名称" json:"className"`
TplCategory string `gorm:"column:tpl_category;size:200;default:'crud';comment:使用的模板" json:"tplCategory"`
PackageName string `gorm:"column:package_name;size:100;comment:生成包路径" json:"packageName"`
ModuleName string `gorm:"column:module_name;size:30;comment:生成模块名" json:"moduleName"`
BusinessName string `gorm:"column:business_name;size:30;comment:生成业务名" json:"businessName"`
FunctionName string `gorm:"column:function_name;size:50;comment:生成功能名" json:"functionName"`
FunctionAuthor string `gorm:"column:function_author;size:50;comment:生成功能作者" json:"functionAuthor"`
GenType string `gorm:"column:gen_type;size:1;default:'0';comment:生成代码方式(0zip压缩包 1自定义路径)" json:"genType"`
GenPath string `gorm:"column:gen_path;size:200;comment:生成路径" json:"genPath"`
Options string `gorm:"column:options;type:longtext;comment:其它生成选项" json:"options"`
BaseModel `gorm:"embedded"`
}
func (SysGenTable) TableName() string { return "sys_gen_table" }
// SysGenColumn 代码生成业务字段
type SysGenColumn struct {
ColumnID uint `gorm:"primaryKey;autoIncrement;column:column_id;comment:编号" json:"columnId"`
TableID uint `gorm:"column:table_id;index:idx_table;comment:归属表编号" json:"tableId"`
ColumnName string `gorm:"column:column_name;size:200;comment:列名称" json:"columnName"`
ColumnComment string `gorm:"column:column_comment;size:500;comment:列描述" json:"columnComment"`
ColumnType string `gorm:"column:column_type;size:100;comment:列类型" json:"columnType"`
GoType string `gorm:"column:go_type;size:500;comment:Go类型" json:"goType"`
GoField string `gorm:"column:go_field;size:200;comment:Go字段名" json:"goField"`
DictType string `gorm:"column:dict_type;size:200;comment:字典类型" json:"dictType"`
IsPK string `gorm:"column:is_pk;size:1;default:'N';comment:是否主键(1是)" json:"isPk"`
IsIncrement string `gorm:"column:is_increment;size:1;default:'N';comment:是否自增(1是)" json:"isIncrement"`
IsRequired string `gorm:"column:is_required;size:1;default:'N';comment:是否必填(1是)" json:"isRequired"`
IsInsert string `gorm:"column:is_insert;size:1;default:'N';comment:是否插入字段(1是)" json:"isInsert"`
IsEdit string `gorm:"column:is_edit;size:1;default:'N';comment:是否编辑字段(1是)" json:"isEdit"`
IsList string `gorm:"column:is_list;size:1;default:'Y';comment:是否列表字段(1是)" json:"isList"`
IsQuery string `gorm:"column:is_query;size:1;default:'Y';comment:是否查询字段(1是)" json:"isQuery"`
QueryType string `gorm:"column:query_type;size:200;default:'EQ';comment:查询方式(EQ等于/NE不等于/GT大于/LT小于/LIKE/BEWEEN)" json:"queryType"`
HTMLType string `gorm:"column:html_type;size:200;comment:显示类型(input/textarea/select/checkbox/radio/editor)" json:"htmlType"`
}
func (SysGenColumn) TableName() string { return "sys_gen_column" }
💡 针对您需求中非持久化模块的说明
| 功能模块 | 实现建议 | 是否需建表 |
|---|---|---|
| 在线用户 | 基于 Redis 存储 Token 信息(Key: access_tokens:{uuid}),查询时遍历或分页获取,退出/踢出直接 DEL |
❌ |
| 系统接口 | 使用 swag init 自动生成 Swagger 文档,路由扫描依赖 gin-swagger 中间件,无需单独表 |
❌ |
| 服务监控 | 调用 github.com/shirou/gopsutil/v3 实时读取 CPU/内存/磁盘,前端轮询或 WebSocket 推送 |
❌ |
| 缓存监控 | 直接连接 Redis 实例,通过 INFO, DBSIZE, CLIENT LIST 命令获取指标,支持 FLUSHDB 清理 |
❌ |
| 在线构建器 | 纯前端实现(如 Formily、BPMN.js),拖拽结果通常以 JSON 字符串存在业务表或 localStorage,无需专属系统表 |
❌ |
🛠 GORM 使用最佳实践
- 自动迁移:启动时调用
db.AutoMigrate(&models.SysUser{}, &models.SysDept{}...)即可同步表结构。 - 关联预加载:
db.Preload("Roles").Preload("Dept").First(&user, id) - 索引优化:日志类表(
SysOperLog、SysLogininfor、SysJobLog)数据量极大,建议按CreateTime或OperTime进行 按月/季度分表,或定期归档到冷数据库。 - 数据权限实现:在
GORM插件层或全局中间件中拦截Where条件,根据当前用户的Role.DataScope动态注入dept_id IN (...)过滤条件,避免在业务代码中硬编码。
如需配套的 Service/Dao 层 封装、权限中间件或 Swagger 路由配置代码,可提供具体技术栈版本(如 Gin/Echo + GORM v2),我将继续补充。
这套核心权限模型遵循经典的 RBAC(基于角色的访问控制)+ 数据权限 架构。在关系型数据库与 GORM 的语境下,实体间的对应关系可分为 一对一/多对一、一对多、多对多 以及 自关联树形 四类。
以下是详细的关系映射、GORM 实现方式及业务含义:
📊 核心关系总览表
| 实体 A | 实体 B | 关系类型 | 物理存储/外键 | GORM 映射方式 | 业务含义 |
|---|---|---|---|---|---|
SysDept |
SysUser |
一对多 (1 Dept → N Users) | sys_user.dept_id |
BelongsTo / HasMany |
一个部门包含多名员工 |
SysUser |
SysRole |
多对多 (N Users ↔ N Roles) | sys_user_role 中间表 |
Many2Many |
用户可兼任多个角色 |
SysUser |
SysPost |
多对多 (逻辑) | sys_user.post_ids (逗号分隔) |
手动 Split 或自定义 Join |
员工可担任多个岗位(简化设计) |
SysRole |
SysMenu |
多对多 (N Roles ↔ N Menus) | sys_role_menu 中间表 |
Many2Many |
角色分配菜单/按钮操作权限 |
SysRole |
SysDept |
多对多 (N Roles ↔ N Depts) | sys_role_dept 中间表 |
Many2Many |
角色数据范围(可见哪些部门的数据) |
SysMenu |
SysMenu |
自关联一对多 (树形) | sys_menu.parent_id |
HasMany / BelongsTo |
菜单多级嵌套(目录→菜单→按钮) |
SysDept |
SysDept |
自关联一对多 (树形) | sys_dept.parent_id + ancestors |
HasMany / BelongsTo |
组织架构树(公司→部门→小组) |
🔍 详细关系拆解与 GORM 实现
1. 用户 ⇄ 部门:多对一 / 一对多
- 关系:一个用户只能属于一个主部门,一个部门下有多名用户。
- GORM 定义示例:
// SysUser 侧(多对一) type SysUser struct { DeptID uint `gorm:"column:dept_id;comment:所属部门ID"` Dept SysDept `gorm:"foreignKey:DeptID;references:ID;comment:关联部门"` } // SysDept 侧(一对多) type SysDept struct { Users []SysUser `gorm:"foreignKey:DeptID;references:ID;comment:部门成员"` } - 业务用法:查询用户时预加载部门信息
db.Preload("Dept").First(&user);统计部门人数直接db.Model(&SysDept{}).Association("Users").Count()。
2. 用户 ⇄ 角色:多对多(标准 RBAC)
- 关系:用户可拥有多个角色,角色可分配给多个用户。通过
sys_user_role解耦。 - GORM 定义示例:
type SysUser struct { // ... Roles []SysRole `gorm:"many2many:sys_user_role;joinForeignKey:UserID;joinReferences:RoleID"` } type SysRole struct { // ... Users []SysUser `gorm:"many2many:sys_user_role;joinForeignKey:RoleID;joinReferences:UserID"` } - 业务用法:GORM 自动管理中间表。登录时获取用户权限链:
db.Preload("Roles").First(&user)→ 遍历角色获取菜单权限。
注意,RuoYi模型为用户N-1角色,简化了业务逻辑(规则更清晰)
3. 用户 ⇄ 岗位:多对多(非规范化设计)
- 关系:逻辑上是多对多,但模型中使用了
post_ids string(如"1,3,5")。 - 设计考量:企业后台中岗位变动频率低,且前端多为多选下拉框。使用逗号分隔可避免频繁
JOIN,提升列表查询性能。若需强一致性,可改为标准中间表sys_user_post。 - GORM 处理:不直接定义关联,业务层用
strings.Split(postIds, ",")转换,或通过自定义Hook序列化/反序列化。
4. 角色 ⇄ 菜单:多对多(功能权限)
- 关系:决定角色能访问哪些路由、显示哪些按钮。通过
sys_role_menu维护。 - GORM 定义:同用户角色,使用
Many2Many:sys_role_menu。 - 业务用法:权限拦截中间件会读取
sys_role_menu生成perms列表(如["system:user:add", "system:user:edit"]),前端通过v-hasPermi指令控制按钮显隐。
5. 角色 ⇄ 部门:多对多(数据权限)
- 关系:控制角色能查看哪些部门产生的数据。由
SysRole.DataScope字段配合sys_role_dept实现。 - DataScope 策略:
值 含义 SQL 过滤逻辑 1全部数据 不追加条件 2自定义部门 WHERE dept_id IN (SELECT dept_id FROM sys_role_dept WHERE role_id=?)3本部门数据 WHERE dept_id = 当前用户dept_id4本部门及以下 WHERE dept_id IN (SELECT id FROM sys_dept WHERE ancestors LIKE '%当前用户dept_id,%')5仅本人数据 WHERE create_by = 当前用户username - GORM 实现:通常封装为 GORM 插件或全局
Where拦截器,根据DataScope动态注入WHERE子句,实现行级数据隔离。
6. 菜单 & 部门:自关联树形结构
- 关系:自身引用自身形成层级树。
- 关键字段:
parent_id:指向父节点 ID,根节点为0。ancestors(部门特有):祖级链路,如0,100,101。用于避免递归查询,直接LIKE '0,100,%'即可查出所有子孙节点。
- GORM 查询树:
// 方式1:递归加载(适合小数据量) db.Preload("Children").Where("parent_id = 0").Find(&menus) // 方式2:一次性查平铺 + 内存组装树(推荐,性能高) var allDepts []SysDept db.Find(&allDepts) tree := BuildTree(allDepts, 0) // 自定义函数递归组装
🧩 权限校验完整数据流向示例
当一个用户请求 POST /api/system/user 时:
- 身份认证:解析 Token → 获取
UserID - 功能权限:
UserID→sys_user_role→sys_role_menu→ 匹配perms: "system:user:add"→ 放行请求 - 数据权限:拦截器读取当前角色
DataScope=2(自定义)→ 查sys_role_dept获取允许的DeptID列表 → 自动在业务 SQL 追加WHERE dept_id IN (101,102) - 结果返回:仅返回该角色权限范围内的数据,越权请求返回
403 Forbidden
💡 架构建议
- 避免 N+1 查询:权限树、用户列表等高频场景,优先使用单次查询 + 内存构建树,而非 GORM 递归
Preload。 - 中间表显式声明:虽然 GORM 支持隐式多对多,但显式定义
SysUserRole等结构体便于后续扩展字段(如create_time,assign_by)。 - 数据权限插件化:建议封装 GORM Callback,在
gorm:query阶段自动拼接数据权限WHERE条件,业务代码无需关心过滤逻辑。
如需我提供 GORM 数据权限拦截插件代码、树形结构内存组装算法 或 权限中间件完整实现,可告知具体需求。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐

所有评论(0)