Go 后台管理系统教程:GoFrame + Vue3 实现 CRUD、RBAC 权限、代码生成器与部署

一、为什么 Go 后台管理系统要先设计 CRUD 与 RBAC 权限

很多同学第一次做 Go 后台管理系统时,会把重点放在接口能不能跑通、页面能不能展示、分页能不能查询。这个方向没有错,但如果项目要长期维护,仅有 CRUD 远远不够。后台系统最常见的返工点不是新增、编辑、删除这几个接口,而是角色权限、菜单权限、按钮权限、接口权限、数据范围、操作日志和部署后的配置管理。

本文用一个 GoFrame + Vue3 的后台管理系统作为教程案例,从表结构设计、CRUD 接口、RBAC 权限、代码生成器思路,到本地运行和部署步骤完整走一遍。文章适合正在搜索 Go 后台管理系统、GoFrame + Vue3、CRUD、RBAC 权限、代码生成器、部署这些关键词的开发者。案例中会参考 XYGo Admin 的工程结构,但重点是讲清楚一套后台系统应该如何落地,而不是简单罗列功能。

技术栈选择如下:

  • 后端:GoFrame v2,用于路由、配置、ORM、服务分层。
  • 前端:Vue3 + TypeScript + Element Plus。
  • 权限:RBAC,覆盖菜单、按钮、接口三个层面。
  • 工程化:通过代码生成器减少重复 CRUD。
  • 部署:本地开发、数据库初始化、生产配置、Nginx 反向代理。

二、数据库表结构:先把业务表和权限表分清楚

教程以客户管理模块为例。业务表不要一开始设计得太复杂,但必须保留审计字段,方便后续接入操作日志和数据权限。

CREATE TABLE biz_customer ( id BIGINT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(100) NOT NULL COMMENT '客户名称', mobile VARCHAR(32) DEFAULT '' COMMENT '手机号', level TINYINT DEFAULT 1 COMMENT '客户等级', status TINYINT DEFAULT 1 COMMENT '状态:1正常 0禁用', remark VARCHAR(255) DEFAULT '' COMMENT '备注', created_by BIGINT DEFAULT 0, updated_by BIGINT DEFAULT 0, created_at DATETIME, updated_at DATETIME, deleted_at DATETIME NULL ) COMMENT='客户表';

权限相关建议拆成菜单、角色、权限关联三部分。实际项目中还可以继续拆按钮权限、接口权限、数据权限。为了教程清晰,这里先给一个简化版结构。

CREATE TABLE sys_role ( id BIGINT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(64) NOT NULL, code VARCHAR(64) NOT NULL, status TINYINT DEFAULT 1, created_at DATETIME, updated_at DATETIME ); CREATE TABLE sys_menu ( id BIGINT PRIMARY KEY AUTO_INCREMENT, parent_id BIGINT DEFAULT 0, type VARCHAR(16) NOT NULL COMMENT 'menu/button/api', title VARCHAR(64) NOT NULL, permission VARCHAR(128) NOT NULL, path VARCHAR(255) DEFAULT '', method VARCHAR(16) DEFAULT '', sort INT DEFAULT 0, status TINYINT DEFAULT 1 ); CREATE TABLE sys_role_menu ( role_id BIGINT NOT NULL, menu_id BIGINT NOT NULL, PRIMARY KEY(role_id, menu_id) );

这里的关键点是 type 字段。很多后台项目一开始只做菜单权限,后来发现按钮、导出、删除、接口调用都需要控制,再回头改表结构就很痛苦。建议从第一天开始就把 menu、button、api 三类权限放进模型里。

三、GoFrame 后端分层:CRUD 不要全部写进 controller

GoFrame 项目建议保持清晰分层。以 customer 模块为例,可以采用下面的目录结构:

internal/ controller/customer.go service/customer.go logic/customer/customer.go dao/customer.go model/entity/customer.go model/input/customer.go api/ customer/v1/customer.go web/ src/views/customer/index.vue src/api/customer.ts

controller 负责接收请求,logic 负责业务逻辑,dao 负责数据访问。这样代码生成器生成出来的 CRUD 才有可维护性,而不是把所有逻辑堆在一个文件里。

type CustomerListReq struct { g.Meta `path:"/customer/list" method:"get" tags:"Customer" summary:"客户列表"` Name string `json:"name" dc:"客户名称"` Status int `json:"status" dc:"状态"` Page int `json:"page" d:"1"` Size int `json:"size" d:"10"` } type CustomerListRes struct { List interface{} `json:"list"` Total int `json:"total"` }

列表查询逻辑可以这样写,注意分页、条件过滤和软删除条件应当统一处理:

func (s *sCustomer) List(ctx context.Context, in model.CustomerListInput) (out *model.CustomerListOutput, err error) { m := dao.BizCustomer.Ctx(ctx).WhereNull("deleted_at") if in.Name != "" { m = m.WhereLike("name", "%"+in.Name+"%") } if in.Status >= 0 { m = m.Where("status", in.Status) } total, err := m.Count() if err != nil { return nil, err } var list []entity.BizCustomer err = m.Page(in.Page, in.Size).OrderDesc("id").Scan(&list) if err != nil { return nil, err } return &model.CustomerListOutput{List: list, Total: total}, nil }

四、RBAC 权限:前端隐藏按钮不等于后端安全

在后台管理系统中,RBAC 权限至少要覆盖三层:菜单是否可见、按钮是否可点、接口是否可调用。Vue3 前端可以根据权限码隐藏按钮,但后端必须再次校验,否则用户可以直接构造 HTTP 请求绕过页面控制。

func PermissionMiddleware() ghttp.HandlerFunc { return func(r *ghttp.Request) { userId := r.GetCtxVar("user_id").Int64() method := r.Method path := r.URL.Path ok, err := service.Permission().CanAccess(r.Context(), userId, method, path) if err != nil { r.Response.WriteJsonExit(g.Map{"code": 500, "msg": "permission check error"}) return } if !ok { r.Response.WriteJsonExit(g.Map{"code": 403, "msg": "forbidden"}) return } r.Middleware.Next() } }

前端按钮可以封装一个指令,例如 v-permission,用于统一控制按钮显示:

app.directive('permission', { mounted(el, binding) { const permissions = useUserStore().permissions const value = binding.value if (value && !permissions.includes(value)) { el.parentNode && el.parentNode.removeChild(el) } } })

页面中使用:

<el-button v-permission="'customer:create'" type="primary">新增客户</el-button> <el-button v-permission="'customer:export'">导出</el-button>

注意:这只是体验层面的控制。真正的权限必须放在 GoFrame 后端中间件里,尤其是导出、删除、批量修改、敏感字段查询这些接口。

五、代码生成器应该生成什么

很多 Go 后台管理系统都带代码生成器,但生成器的质量差异很大。一个可用的 CRUD 代码生成器,不应该只生成后端接口和前端页面,还应该同时生成权限点、路由、菜单、表单校验和列表字段配置。

以客户模块为例,生成器至少应该产出以下内容:

1. GoFrame API 定义 2. controller / logic / dao 基础代码 3. Vue3 列表页、表单弹窗、搜索区域 4. TypeScript API 请求文件 5. 菜单权限:customer:list 6. 按钮权限:customer:create / customer:update / customer:delete / customer:export 7. 接口权限:GET /customer/list、POST /customer/create 等 8. 初始化 SQL 或迁移脚本

如果生成器只生成 CRUD,不处理 RBAC 权限,项目上线前仍然需要大量人工补漏。XYGo Admin 的价值就在于把 GoFrame + Vue3 + TypeScript + Element Plus、代码生成器、RBAC 权限和 AI Skills 放在同一个后台工程里,适合用来学习完整链路。

项目地址:

  • GitHub:https://github.com/z312193608/xygo-admin
  • 官网:XYGo Admin 官网 - Vue3 + GoFrame 开源后台管理系统
  • AI Skills:XYGo Admin AI Skills - Cursor Agent Skills 让 AI 读懂你的项目 - XYGo Admin

六、Vue3 页面:列表、搜索、表单与权限按钮

前端页面建议保持三个区域:搜索表单、操作按钮、数据表格。这样生成器更容易统一模板,后续维护也更简单。

<template> <el-card> <el-form :model="query" inline> <el-form-item label="客户名称"> <el-input v-model="query.name" placeholder="请输入客户名称" /> </el-form-item> <el-form-item> <el-button type="primary" @click="loadData">查询</el-button> </el-form-item> </el-form> <div class="toolbar"> <el-button v-permission="'customer:create'" type="primary" @click="openCreate">新增</el-button> <el-button v-permission="'customer:export'" @click="exportData">导出</el-button> </div> <el-table :data="list" border> <el-table-column prop="name" label="客户名称" /> <el-table-column prop="mobile" label="手机号" /> <el-table-column prop="status" label="状态" /> </el-table> </el-card> </template>

这里的重点仍然是权限一致性。页面上隐藏了导出按钮,后端导出接口也必须校验 customer:export 或对应 API 权限。

七、本地运行与部署步骤

本地运行 GoFrame + Vue3 后台管理系统,一般分为数据库、后端、前端三步。

# 1. 初始化数据库 mysql -uroot -p your_database < deploy/sql/init.sql # 2. 启动后端 cd server go mod tidy go run main.go # 3. 启动前端 cd web pnpm install pnpm dev

生产部署时,建议前端构建静态文件,后端使用 systemd 或 Docker 管理进程,Nginx 做反向代理。

server { listen 80; server_name admin.example.com; location / { root /data/www/admin-web; try_files $uri $uri/ /index.html; } location /api/ { proxy_pass http://127.0.0.1:8000/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } }

上线前还要检查配置文件中的数据库密码、JWT 密钥、跨域域名、日志目录、上传目录、静态资源路径。不要把本地开发配置直接带到生产环境。

八、上线前 checklist

最后给一份 Go 后台管理系统上线前 checklist,适合每次新增 CRUD 模块时复用:

  • 数据库表是否包含 created_at、updated_at、deleted_at、created_by、updated_by。
  • 列表接口是否支持分页,是否限制最大 pageSize。
  • 新增、编辑接口是否做参数校验。
  • 删除接口是否软删除,是否记录操作日志。
  • 菜单权限、按钮权限、接口权限是否全部初始化。
  • 前端按钮权限和后端接口权限是否一致。
  • 导出接口是否单独鉴权。
  • 手机号、金额、成本价等敏感字段是否按角色脱敏。
  • 角色权限变化后是否刷新缓存。
  • Nginx、数据库、后端服务是否有独立生产配置。

九、总结

Go 后台管理系统的核心不是把 CRUD 写出来,而是把 CRUD、RBAC 权限、代码生成器、前端页面和部署流程串成一条可维护的工程链路。GoFrame + Vue3 的组合适合做中后台项目,原因是后端分层清晰,前端生态成熟,配合代码生成器可以显著减少重复劳动。

如果你正在学习或搭建 GoFrame + Vue3 后台管理系统,可以参考 XYGo Admin 的实现方式。它不是本文唯一答案,但作为 GoFrame v2 + Vue3 + TypeScript + Element Plus 的完整工程案例,适合对照学习 CRUD、RBAC 权限、代码生成器和部署流程。

相关链接:

  • GitHub:https://github.com/z312193608/xygo-admin
  • 官网:XYGo Admin 官网 - Vue3 + GoFrame 开源后台管理系统
  • AI Skills:XYGo Admin AI Skills - Cursor Agent Skills 让 AI 读懂你的项目 - XYGo Admin