- 前端参考了很多框架,可谓百花齐放,但很多封装过剩,不利于学习和应用,最终我选择了 [vue-pure-admin](https://github.com/pure-admin/vue-pure-admin)
- 后端我将使用 go-zero 来带领大家一步步实现一个权限管理系统
- 本系列项目存放在 purezeroadmin 中,每一部分我都将打tag,并保证每个tag能正常运行。请多点赞和评论。
- 后面示例均为
purezeroadmin
项目为例,你们可以根据需要自建工程来进行试验。均采用vscode
进行试验。
go-zero
常用命令我将放入其对应的 makefile
文件中。
前端模拟的接口在 mock
文件夹中,后端可参照修改
- 公共api创建
前端返回接口均为
{success: true, data: xxx}
, 所以创建公共api `
api:
type Base {
Success bool `json:"success"`
}
- 依照前章示例,创建
user.api
文件
cat `user-api/api/user.api`
api:
syntax = "v1"
info (
title: "q9090960bnb3"
desc: "haha"
date: "2024-10-31"
)
import "../../base-api/base.api"
type UserLoginData {
Avatar string `json:"avatar"`
Username string `json:"username"`
Nickname string `json:"nickname"`
Roles []string `json:"roles"`
Permissions []string `json:"permissions"`
AccessToken string `json:"accessToken"`
RefreshToken string `json:"refreshToken"`
Expires string `json:"expires"`
}
type (
UserLoginReq {
UserName string `json:"username"`
Password string `json:"password"`
}
UserLoginResp {
Base
Data UserLoginData `json:"data"`
}
)
service user-api {
@doc "用户登录"
@handler userLogin
post /login (UserLoginReq) returns (UserLoginResp)
}
- 生成代码
goctl api go --api user-api/api/user.api --dir user-api
- 参考前端mock数据,修改
user-api/internal/logic/userloginlogic.go
中的函数
func (l *UserLoginLogic) UserLogin(req *types.UserLoginReq) (resp *types.UserLoginResp, err error) {
if req.UserName == "admin" {
return &types.UserLoginResp{
Base: types.Base{
Success: true,
},
Data: types.UserLoginData{
Avatar: "https://avatars.githubusercontent.com/u/44761321",
Username: "admin",
Nickname: "小铭",
Roles: []string{"admin"},
Permissions: []string{"*:*:*"},
AccessToken: "eyJhbGciOiJIUzUxMiJ9.admin",
RefreshToken: "eyJhbGciOiJIUzUxMiJ9.adminRefresh",
Expires: "2030/10/30 00:00:00",
},
}, nil
}
return &types.UserLoginResp{
Base: types.Base{
Success: true,
},
Data: types.UserLoginData{
Avatar: "https://avatars.githubusercontent.com/u/52823142",
Username: "common",
Nickname: "小林",
Roles: []string{"common"},
Permissions: []string{"permission:btn:add", "permission:btn:edit"},
AccessToken: "eyJhbGciOiJIUzUxMiJ9.common",
RefreshToken: "eyJhbGciOiJIUzUxMiJ9.commonRefresh",
Expires: "2030/10/30 00:00:00",
},
}, nil
}
- 在
user.api
中添加
type UserRefreshTokenData {
AccessToken string `json:"accessToken"`
RefreshToken string `json:"refreshToken"`
Expires string `json:"expires"`
}
type (
UserRefreshTokenReq {
RefreshToken string `json:"refreshToken"`
}
UserRefreshTokenResp {
Base
Data UserRefreshTokenData `json:"data"`
}
)
service user-api {
@doc "用户登录"
@handler UserRefreshToken
post /refresh-token (UserRefreshTokenReq) returns (UserRefreshTokenResp)
}
- 参考前端mock数据,修改
user-api/internal/logic/userrefreshtokenlogic.go
中的函数
func (l *UserRefreshTokenLogic) UserRefreshToken(req *types.UserRefreshTokenReq) (resp *types.UserRefreshTokenResp, err error) {
if req.RefreshToken != "" {
return &types.UserRefreshTokenResp{
Base: types.Base{
Success: true,
},
Data: types.UserRefreshTokenData{
AccessToken: "",
RefreshToken: "",
Expires: "",
},
}, nil
}
return &types.UserRefreshTokenResp{}, nil
}
- 在
user.api
中添加
type RouterData {
Path string `json:"path"`
Name string `json:"name,omitempty"`
Component string `json:"component,omitemty"`
Meta Meta `json:"meta"`
Children []RouterData `json:"children,omitempty"`
}
type Meta {
Title string `json:"title"`
Icon string `json:"icon,omitempty"`
Rank int64 `json:"rank,omitempty"`
Roles []string `json:"roles,omitempty"`
Auths []string `json:"auths,omitempty"`
}
type (
UserRouterReq {}
UserRouterResp {
Base
Data []RouterData `json:"data"`
}
)
service user-api {
@doc "用户登出"
@handler userRouter
get /get-async-routes (UserRouterReq) returns (UserRouterResp)
}
- 参考前端mock数据,修改
user-api/internal/logic/userrouterlogic.go
中的函数
func (l *UserRouterLogic) UserRouter(req *types.UserRouterReq) (resp *types.UserRouterResp, err error) {
return &types.UserRouterResp{
Base: types.Base{
Success: true,
},
Data: []types.RouterData{
{
Path: "/permission",
Meta: types.Meta{
Title: "权限管理",
Icon: "ep:lollipop",
Rank: 10,
},
Children: []types.RouterData{
{
Path: "/permission/page/index",
Name: "PermissionPage",
Meta: types.Meta{
Title: "页面权限",
Roles: []string{"admin", "common"},
},
},
{
Path: "/permission/button",
Meta: types.Meta{
Title: "按钮权限",
Roles: []string{"admin", "common"},
},
Children: []types.RouterData{
{
Path: "/permission/button/router",
Component: "permission/button/index",
Name: "PermissionButtonRouter",
Meta: types.Meta{
Title: "路由返回按钮权限",
Auths: []string{
"permission:btn:add",
"permission:btn:edit",
"permission:btn:delete",
},
},
},
{
Path: "/permission/button/login",
Component: "permission/button/perms",
Name: "PermissionButtonLogin",
Meta: types.Meta{
Title: "登录返回按钮权限",
},
},
},
},
},
},
},
}, nil
}
参考 如何关闭mock
在 vite.config.ts
中配置转发
// 本地跨域代理 https://cn.vitejs.dev/config/server-options.html#server-proxy
proxy: {
"^/(login|refresh-token|get-async-routes)": {
target: "http://localhost:8888",
changeOrigin: true,
},
},
- 启动后端服务
# vue-pure-admin工程下执行
❯ cd back-end/user-api
❯ go run user.go
Starting server at 0.0.0.0:8888...
- 启动前端服务
# vue-pure-admin工程下执行
❯ cd front-end
❯ pnpm dev
purezeroadmin
项目下
目前,前端请求路由太自由了,最好采用统一前缀去访问后端系统