1,简介:go-admin是go和vue配合开发的。

2,如何五分钟搭建一个后台管理系统。

# 代码拉取 并且 创建 Project
cd Project
git clone https://github.com/go-admin-team/go-admin.git # 服务端
git clone https://github.com/go-admin-team/go-admin-ui.git # 前端 vue-element-admin 魔改的

# 假设目前在Project目录
# 服务端项目部署:
cd go-admin
go build . # 编译
./go-admin migrate -c config/settings.yml # settings.yml 配置数据库信息,执行数据库迁移
./go-admin server -c config/settings.yml # 服务启动

# 前端项目部署
cd go-admin-ui
yarn install # 安装依赖包
npm run dev # 开发模式
npm run build:prod # 生产环境 build

# 执行完就能访问了

3,重点:如何增加自己的功能

# 这是五分钟以外的事情了,我就做个城市管理的demo

# 服务端方向:教你一个小技巧,做业务需求以路由为起点
# 1,新增路由: 路由路径go-admin/app/admin/router
cd app/admin/router
vim province.go # 我是把城市的东西都扔这了,其实可以分开,复制其他的路由文件
# 这是导入的东西,可以自己在做定义
import (
	"github.com/gin-gonic/gin"
	jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth"

	"go-admin/app/admin/apis"
	"go-admin/common/middleware"
)
# 需认证的路由代码 还有一种可以不需要认证的,routerCheckRole和noCheck都在router.go里
func init() {
	routerCheckRole = append(routerCheckRole, registerProvinceRouter)
}
func registerProvinceRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) {
	api := apis.Province{}
	r := v1.Group("/city").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole())
	{
		r.GET("", api.GetPage)
		r.GET("/:id", api.GetCity)
		r.POST("", api.InsertCity)
		r.PUT("", api.UpdateCity)
		r.DELETE("", api.DeleteCity)
	}

	r1 := v1.Group("/province").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole())
	{
		r1.GET("/:id", api.Get) // ok
		r1.POST("", api.Insert) // ok
		r1.PUT("", api.Update) // ok
		r1.DELETE("", api.Delete)
	}
}

#2,定义接口:这是我看的最惊艳的地方,抽象出整个RunTime,然后在Http请求中将整个抽象的实现进行整合。api接口路径:go-admin/app/admin/apis
vim province.go # 可以和路由文件同名,识别度高
import (
	"github.com/gin-gonic/gin" 
	"github.com/gin-gonic/gin/binding" # gin框架http参数的抽象定义
	"go-admin/app/admin/models" # 数据模型,这里定义的是你写的 gorm 的东西
	"go-admin/app/admin/service" # 模型查询方法
	"go-admin/app/admin/service/dto" # dto 放的基本是请求参数定义

	"github.com/go-admin-team/go-admin-core/sdk/api" # 这个api放的就是RunTime到了Http的核心,关注头部结构体
	"github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth/user" # jwt 鉴权
)
# 获取城市城市列表
func (p Province) GetPage(c *gin.Context) {
	s := service.City{} # service 的 City 我会在下面写,作用是绑定模型查询
	req := dto.CityGetPageReq{} # 请求参数模型 在service/dto下面
	err := p.MakeContext(c). // 绑定上下文,数据库日志权限都在这,必须加
		MakeOrm(). // 初始化Gorm 这里需要改造,现在只能是单库,作者估计也没想好怎么加,我给配置文件加了两个数据库配置,然后在handler里面将上下文的key他这里是用*改成read和write也能做读写分离,但不是最优解,这个等待好思路
		Bind(&req, binding.Form). # 参数解析,binding 有多种抽象,各个实现都不同,具体看实现了
		MakeService(&s.Service). # 绑定模型查询服务
		Errors # error
	if err != nil {
		p.Logger.Error(err) # 日志信息
		p.Error(500, err, err.Error()) # 这里就是Response了,作者将response做了封装
		return
	}
	//数据权限检查
	list := make([]models.Province, 0) # 这里就是返回的数据结构了,并不是一定要使用models的东西,你可以自己封装一个dto同级的response,正好对应request和response
	var count int64 # 分页用的 total
	err = s.GetPage(&req, &list, &count) # 查询实体逻辑
	if err != nil {
		p.Error(500, err, "查询失败")
		return
	}
    # 跟上面的Error一样的
	p.PageOK(list, int(count), req.GetPageIndex(), req.GetPageSize(), "查询成功")
}

# 3,接下来就是service,也就是上面的City的定义,路径:go-admin/app/admin/service
vim city.go
import (
	"github.com/go-admin-team/go-admin-core/sdk/service" # 这里面也是一个接口,封装数据库实例,多库就是要改这里,还有日志,错误信息之类,都可以加,看自己使用
	"go-admin/app/admin/models" # 模型
	"go-admin/app/admin/service/dto" # 查询参数
	cDto "go-admin/common/dto" # 通用查询结构,分页各种条件封装,这块对应的是dto里面的请求参数,参数里面加了各种条件然后再去cDto里面用反射组装了sql

	"errors"
	"gorm.io/gorm"
)
type City struct {
	service.Service
}

// GetPage 获取city列表
func (e *City) GetPage(c *dto.CityGetPageReq, list *[]models.Province, count *int64) error {
	var err error
	var data models.Province # 这模型是专门做绑定的
	err = e.Orm.Debug().Model(&data).Preload("City")./*Preload("City.CityArea").*/
		Scopes(
			cDto.MakeCondition(c.GetNeedSearch()),
			cDto.Paginate(c.GetPageSize(), c.GetPageIndex()),
		).
		Find(list).Limit(-1).Offset(-1).
		Count(count).Error # gorm 的用法我就不多介绍了
	if err != nil {
		e.Log.Errorf("Service GetCityPage error:%s", err)
		return err
	}
	return nil
}

# 4,接下来看一下dto的定义,路径go-admin/app/admin/service/dto
vim city.go
import (
	"go-admin/app/admin/models" # 模型
	"go-admin/common/dto" # common 的 dto 放了一些通用查询排序,分页参数之类的,用的着就加
	common "go-admin/common/models" # 模型通用字段 id create_by之类
)
// CityGetPageReq 功能列表请求参数
type CityGetPageReq struct {
	dto.Pagination `search:"-"` # search 就是 上文提到的将会被反射使用的tag
	Name          string `form:"name"   search:"type:contains;column:name;table:province" comment:"名称"` # form 就是表单参数
	Pinyin           string `form:"pinyin"  search:"type:contains;column:pinyin;table:province" comment:"拼音"` # type,column,table,除了type会分多钟,column,table跟随语义
	// CityOrder # 排序参数 ,看需求
}
type CityOrder struct {
	TitleOrder     string `search:"type:order;column:title;table:sys_api" form:"titleOrder"`
	PathOrder      string `search:"type:order;column:path;table:sys_api" form:"pathOrder"`
	CreatedAtOrder string `search:"type:order;column:created_at;table:sys_api" form:"createdAtOrder"`
}

# 5,顺序好像有点问题,其实路由过后就应该做models定义,路径go-admin/app/admin/models
vim city.go
import (
	"go-admin/common/models" # 下面用的呢
)

type City struct {
	models.Model
	Name 		string `json:"name" gorm:"size:128;comment:name"`
	Fullname  	string `json:"fullname" gorm:"size:128;comment:标题"`
	ProvinceId  int    `json:"provinceId" gorm:"column:provinceId;size:128;comment:地址"`
	DistrictId 	int    `json:"districtId" gorm:"column:districtId;size:16;comment:区域ID"`
	CityPy   	string `json:"cityPy" gorm:"column:cityPy;size:16;comment:城市拼音"`
	Py   		string `json:"py" gorm:"column:py;size:16;comment:短拼"`
	Pinyin   	string `json:"pinyin" gorm:"column:pinyin;size:16;comment:全拼"`
	Longitude   string `json:"longitude" gorm:"column:longitude;size:16;comment:经度"`
	Latitude   	string `json:"latitude" gorm:"column:latitude;size:16;comment:纬度"`
	IsHot   	int `json:"isHot" gorm:"column:isHot;size:16;comment:是否热门"`
	CityArea 	[]CityArea `json:"city_area"`
	models.ModelTime # 时间,逻辑删除也在这
	models.ControlBy # 创建更新账号
}

func (City) TableName() string {
	return "city"
}

# 增加更新这里用的着,可以直接把request绑定到models上
func (e *City) Generate() models.ActiveRecord {
	o := *e
	return &o
}
# 取更新后的id,增加不会返回,还没找到原因,但是到这肯定是够用了
func (e *City) GetId() interface{} {
	return e.Id
}

# 6,我把整个城市管理的模型给大家发一下,上面有城市的了,代码就不发了太多了,逻辑写法基本没有区别,复制粘贴就可以快速实现你的后台功能
# 城区
type CityArea struct {
	Id     int    `json:"id" gorm:"primaryKey;autoIncrement;comment:主键编码"`
	Code string `json:"code" gorm:"size:128;comment:code"`
	Fullname  string `json:"fullname" gorm:"size:128;comment:全名称"`
	Pinyin   string `json:"pinyin" gorm:"size:128;comment:完整拼音"`
	Py string `json:"py" gorm:"size:16;comment:短拼音"`
	CityId   string `json:"cityId" gorm:"column:cityId;size:16;comment:城市id"`
	Longitude   string `json:"longitude" gorm:"size:16;comment:经度"`
	Latitude   string `json:"latitude" gorm:"size:16;comment:纬度"`
	Rank   string `json:"rank" gorm:"size:16;comment:排序"`
	models.ModelTime
	models.ControlBy
}
# 省份
type Province struct {
	models.Model
	Name 		string `json:"name" gorm:"size:128;comment:name"`
	Pinyin  	string `json:"pinyin" gorm:"size:128;comment:拼音"`
	Pyshort   	string `json:"pyshort" gorm:"size:128;comment:短拼音"`
	DistrictId 	int    `json:"districtId" gorm:"column:districtId;size:16;comment:地区ID"`
	Sort   		string `json:"sort" gorm:"size:16;comment:排序"`

	City        []City `json:"city"`

	models.ModelTime
	models.ControlBy
}

# 7,此止:后台的基本功能就可以了,重新编译启动后,用postman访问一下你的新接口

# 前端方向:也是以路由为起点,千万记得路由起点。
# 1,定义路由
cd go-admin-ui
npm run dev 
# 接口路径:go-admin-ui/src/api复制粘贴一个
vim city.js
import request from '@/utils/request'

// 查询provinnce-city列表
export function listCityApi(query) {
  return request({
    url: '/api/v1/city',
    method: 'get',
    params: query
  })
} # 我这都是打样,都一样的写法

# 2,定义页面:这个页面需要和后台的菜单管理做对应,这样才能完整的使用到权限管理。假如说我是二级目录,那么创建跟系统管理的菜单:内容管理<目录类型,路由路径 /cms(这个cms就是你将来在iviews下面要加的顶级目录)组件路径:顶级的都是Layout,要用左边和上边的公共组件> -- 城市管理<菜单类型,路由路径 /cms/city(这个cms就是你将来在iviews下面要加的顶级目录)组件路径:/cms/city/index>,再去index里面去制作你的页面和接口的逻辑

# 3,到这就可以测试了。下面看下最后的实现效果。

4,结束语:不加班是提高生产力的唯一动力。

Logo

前往低代码交流专区

更多推荐