首先,将数据库表转换为结构体,在线转结构体
// Model/user.go
type UserRole struct {
Id int `gorm:"column:id" db:"id" json:"id" form:"id"`
Keyword string `gorm:"column:keyword" db:"keyword" json:"keyword" form:"keyword"` //角色关键字
Name string `gorm:"column:name" db:"name" json:"name" form:"name"` //角色名称
Level int `gorm:"column:level" db:"level" json:"level" form:"level"` //角色等级
CreateBy string `gorm:"column:create_by" db:"create_by" json:"createBy" form:"create_by"` //创建人
CreateTime string `gorm:"column:create_time" db:"create_time" json:"createTime" form:"create_time"` //创建时间
UpdateBy string `gorm:"column:update_by" db:"update_by" json:"updateBy" form:"update_by"` //更新人
UpdateTime string `gorm:"column:update_time" db:"update_time" json:"updateTime" form:"update_time"` //更新时间
}
数据库dataTime格式转换为结构体为Time.time,处理起来极为麻烦,还要修改mysql的配置,建议手动修改为string
如果与前端交互的字段为驼峰格式,手动修改json
// Service/user.go
type UserService struct {
}
// 相当于声明一个命名空间
var UserServer UserService
// 查询
func (t *UserService) RoleList(params string, pageNo int, pageSize int) ([]Model.UserRole, int) {
var total int
db := GetDb().Model(&Model.UserRole{}).Where(params).Count(&total).Limit(pageSize).Offset((pageNo - 1) * pageSize)
var list []Model.UserRole
db = db.Find(&list)
if db.Error != nil {
fmt.Println(db.Error)
}
return list, total
}
// 新增、编辑
func (t *UserService) RoleEdit(model Model.UserRole, isEdit bool) error {
db := GetDb()
if isEdit {
db = db.Save(model)
} else {
// 如果id是自增的,务必带&
db = db.Create(&model)
}
if db.Error != nil {
return db.Error
}
return nil
}
// 删除
func (t *UserService) RoleDel(ids []int) error {
db := GetDb().Model(&Model.UserRole{})
db = db.Delete(Model.UserRole{}, ids)
if db.Error != nil {
return db.Error
}
return nil
}
// Controller/user.go
type UserController struct {
}
var UserControl = &UserController{}
func (t *UserController) RoleList(c *gin.Context) {
// 解析前端参数
params, pageNo, pageSize := PackageRequestParams(c)
res, total := Service.UserServer.RoleList(params, pageNo, pageSize)
ResponseSuccessMap(c, map[string]interface{}{
"records": res,
"total": total,
})
}
func (t *UserController) RoleEdit(c *gin.Context) {
data, err := ioutil.ReadAll(c.Request.Body)
CheckError(err)
var msg Model.UserRole
json.Unmarshal(data, &msg)
user, _ := GetCurUserinfo(c)
// time.Time 与数据库与前端三者之间转换实在太麻烦,所以定义为string, updateTime为空时指定一个特定时间,前端显示时过滤掉
if msg.Id == 0 {
msg.CreateBy = user.Username
msg.CreateTime = time.Now().Format("2006-01-02 15:04:05")
msg.UpdateTime = "1010-10-10 00:00:00"
} else {
msg.UpdateBy = user.Username
msg.UpdateTime = time.Now().Format("2006-01-02 15:04:05")
}
if err := Service.UserServer.RoleEdit(msg, msg.Id != 0); err == nil {
ResponseSuccess(c, "success")
} else {
ResponseError(c, err.Error())
}
}
func (t *UserController) RoleDel(c *gin.Context) {
data, err := ioutil.ReadAll(c.Request.Body)
CheckError(err)
var msg struct {
Ids []int
}
json.Unmarshal(data, &msg)
if err := Service.UserServer.RoleDel(msg.Ids); err == nil {
ResponseSuccess(c, "success")
} else {
ResponseError(c, err.Error())
}
}
// Controller/common.go
type RequestCondition struct {
Column string
Value string
Type string
}
// 前端列表请求参数格式
type RequestListData struct {
PageNo int
PageSize int
Condition []RequestCondition
}
func ResponseSuccess(c *gin.Context, data string) {
c.JSON(http.StatusOK, gin.H{
"code": "200",
"message": "success",
"data": data,
"success": true,
})
}
func ResponseSuccessMap(c *gin.Context, data map[string]interface{}) {
c.JSON(http.StatusOK, gin.H{
"code": "200",
"message": "success",
"data": data,
"success": true,
})
}
func ResponseError(c *gin.Context, data string) {
c.JSON(http.StatusOK, gin.H{
"code": "500",
"message": data,
"data": "",
"success": false,
})
}
func CheckError(e error) {
if e != nil {
fmt.Println(e.Error())
}
}
// 将前端请求参数转换为 grom where语句
func PackageRequestParams(c *gin.Context) (string, int, int) {
data, err := ioutil.ReadAll(c.Request.Body)
CheckError(err)
var req RequestListData
json.Unmarshal(data, &req)
var res []string
for _, value := range req.Condition {
var c string
key := snakeString(value.Column)
switch value.Type {
case "eq":
c = key + " = " + "'" + value.Value + "'"
break
case "like":
c = key + " like " + "'%" + value.Value + "%'"
break
case "gt":
c = key + " > " + value.Value
break
case "lt":
c = key + " < " + value.Value
break
}
res = append(res, c)
}
return strings.Join(res, " and "), req.PageNo, req.PageSize
}
// 驼峰转蛇形
func snakeString(s string) string {
data := make([]byte, 0, len(s)*2)
j := false
num := len(s)
for i := 0; i < num; i++ {
d := s[i]
// or通过ASCII码进行大小写的转化
// 65-90(A-Z),97-122(a-z)
//判断如果字母为大写的A-Z就在前面拼接一个_
if i > 0 && d >= 'A' && d <= 'Z' && j {
data = append(data, '_')
}
if d != '_' {
j = true
}
data = append(data, d)
}
//ToLower把大写字母统一转小写
return strings.ToLower(string(data[:]))
}
刚入门,不知如何写一个公用方法,只需要传入不同的struct
则返回不同的结果,这样就避免了多次重复代码,研究中…