Golang实现小型CMS内容管理功能(一):Gin框架搭配Gorm实现增删查改功能

我自己开发了一款在线客服系统,最近一直琢磨把客服系统官网做好。因为访客来的人不少,大部分人可能就是看看官网界面就走了,怎样把这些访客留存下来,去测试试用客服系统,是我一直琢磨的问题。

官网是一个企业的门面,也是一个系统的门面,还是需要把门面的内容整理总结一下,让大家能清楚看到系统的功能。网站的内容少,那么搜索引擎收录的就少,这样会导致网站的权重不高,搜索排名比较低。

因此要简单的加上一个小型的内容管理功能。

大家感兴趣也可以去看看唯一客服系统

设计数据库

很简单的两张表,分类表和内容表

DROP TABLE IF EXISTS `cms_cate`;
CREATE TABLE `cms_cate` (
 `id` int(11) NOT NULL AUTO_INCREMENT,
 `cat_name` varchar(50) NOT NULL DEFAULT '' COMMENT '分类名称',
 `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP  COMMENT '创建时间',
 PRIMARY KEY (`id`) COMMENT '自增主键索引'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT 'CMS分类表';
DROP TABLE IF EXISTS `cms_news`;
CREATE TABLE `cms_news` (
 `id` int(11) NOT NULL AUTO_INCREMENT,
 `title` varchar(500) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '标题',
 `content` text COLLATE utf8mb4_general_ci COMMENT '内容',
 `cat_id` int(11) NOT NULL DEFAULT '0' COMMENT '分类ID',
 `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP  COMMENT '创建时间',
 PRIMARY KEY (`id`) COMMENT '自增主键索引'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT 'CMS内容表';

编写数据库操作gorm Model部分

设计两个结构体

type CmsCate struct {
    Id        uint       `json:"id"`
    CatName   string     `json:"cat_name"`
    CreatedAt types.Time `json:"created_at"`
}
type CmsNews struct {
    Id        uint       `json:"id"`
    Title     string     `json:"title"`
    Content   string     `json:"content"`
    CreatedAt types.Time `json:"created_at"`
}

types.Time类型是我对time.Time类型的包装,用于在序列化为json的时候,可以格式化时间。

默认的Time类型,JSON序列化出来后是UTC格式,不符合观看习惯

package types

import (
    "database/sql/driver"
    "fmt"
    "time"
)

type Time struct {
    time.Time
}

func (t Time) MarshalJSON() ([]byte, error) {
    localTime := t.Format("2006-01-02 15:04:05")
    return []byte(fmt.Sprintf(`"%s"`, localTime)), nil
}
func (t Time) Value() (driver.Value, error) {
    var zeroTime time.Time
    if t.Time.UnixNano() == zeroTime.UnixNano() {
        return nil, nil
    }
    return t.Time, nil
}
func (t *Time) Scan(v interface{}) error {
    value, ok := v.(time.Time)
    if ok {
        *t = Time{Time: value}
        return nil
    }
    return fmt.Errorf("can not convert %v to timestamp", v)
}

分类表和内容表的增删查改

DB就是*gorm.DB类型,这是在链接数据库的时候,已经赋值好的全局变量

/*内容表*/
//根据条件查询条数
func CountCmsNews(query interface{}, args ...interface{}) uint {
    var v uint
    DB.Table("cms_news").Where(query, args...).Count(&v)
    return v
}

//根据条件更新
func (this *CmsNews) SaveCmsNews(query interface{}, args ...interface{}) error {
    db := DB.Table("cms_news").Where(query, args...).Update(this)
    return db.Error
}

//增加数据
func (this *CmsNews) AddCmsNews() error {
    return DB.Create(this).Error
}

//根据条件查询分页列表
func FindCmsNews(page, pagesize int, query interface{}, args ...interface{}) []CmsNews {
    offset := (page - 1) * pagesize
    var res []CmsNews
    DB.Table("cms_news").Where(query, args...).Order("id desc").Offset(offset).Limit(pagesize).Find(&res)
    return res
}

//根据条件删除
func DelCmsNews(query interface{}, args ...interface{}) error {
    return DB.Where(query, args...).Delete(&CmsNews{}).Error
}

/*分类表*/
//根据条件分类
func (this *CmsCate) SaveCmsCate(query interface{}, args ...interface{}) error {
    db := DB.Table("cms_cate").Where(query, args...).Update(this)
    return db.Error
}

//增加分类
func (this *CmsCate) AddCmsCate() error {
    return DB.Create(this).Error
}

//根据条件查询分类列表
func FindCmsCate(page, pagesize int, query interface{}, args ...interface{}) []CmsCate {
    offset := (page - 1) * pagesize
    var res []CmsCate
    DB.Table("cms_cate").Where(query, args...).Order("id desc").Offset(offset).Limit(pagesize).Find(&res)
    return res
}

//根据条件删除分类
func DelCmsCate(query interface{}, args ...interface{}) error {
    return DB.Where(query, args...).Delete(&CmsCate{}).Error
}

编写gin路由处理部分

gin路由入口

 //系统相关
    systemGroup := engine.Group("/system")
    systemGroup.Use()
    {
        //分类列表
        systemGroup.GET("/cmsCate", controller.GetCmsCate)
        //删除分类
        systemGroup.GET("/delCmsCate", controller.DelCmsCate)
        //增加或编辑分类
        systemGroup.POST("/cmsCate", controller.PostCmsCate)
        //CMS内容列表
        systemGroup.GET("/cmsNews", controller.GetCmsNews)
        //增加或编辑内容
        systemGroup.POST("/cmsNews", controller.PostCmsNews)
        //删除内容
        systemGroup.GET("/delCmsNews", controller.DelCmsNews)

    }

gin框架路由处理逻辑

返回参数部分,我进行了小的封装,可以参考去掉。

只看调用model部分的处理逻辑

package controller

import (
    "github.com/gin-gonic/gin"
    "kefu/models"
    "kefu/types"
    "strconv"
)

type CmsCateForm struct {
    Id       uint   `form:"id" json:"id" uri:"id" xml:"id"`
    CateName string `form:"cate_name" json:"cate_name" uri:"cate_name" xml:"cate_name" binding:"required"`
}

//分类列表(暂不分页)
func GetCmsCate(c *gin.Context) {
    list := models.FindCmsCate(1, 1000, "")
    c.JSON(200, gin.H{
        "code":   types.ApiCode.SUCCESS,
        "msg":    types.ApiCode.GetMessage(types.ApiCode.SUCCESS),
        "result": list,
    })
}

//编辑CMS分类
func PostCmsCate(c *gin.Context) {
    var form CmsCateForm
    err := c.Bind(&form)

    if err != nil {
        c.JSON(200, gin.H{
            "code":   types.ApiCode.FAILED,
            "msg":    types.ApiCode.GetMessage(types.ApiCode.INVALID),
            "result": err.Error(),
        })
        return
    }
    modelCms := &models.CmsCate{
        Id:      form.Id,
        CatName: form.CateName,
    }
    //添加分类
    if form.Id == 0 {
        err := modelCms.AddCmsCate()
        if err != nil {
            c.JSON(200, gin.H{
                "code": types.ApiCode.FAILED,
                "msg":  err.Error(),
            })
            return
        }
    } else {
        //修改分类
        err := modelCms.SaveCmsCate("id = ?", form.Id)
        if err != nil {
            c.JSON(200, gin.H{
                "code": types.ApiCode.FAILED,
                "msg":  err.Error(),
            })
            return
        }
    }

    c.JSON(200, gin.H{
        "code": types.ApiCode.SUCCESS,
        "msg":  types.ApiCode.GetMessage(types.ApiCode.SUCCESS),
    })
}

type CmsNewsForm struct {
    Id      uint   `form:"id" json:"id" uri:"id" xml:"id"`
    CateId  string `form:"cate_id" json:"cate_id" uri:"cate_id" xml:"cate_id" binding:"required"`
    Content string `form:"content" json:"content" uri:"content" xml:"content" binding:"required"`
    Title   string `form:"title" json:"title" uri:"title" xml:"title" binding:"required"`
}

//CMS内容列表
func GetCmsNews(c *gin.Context) {
    //分页处理
    page, _ := strconv.Atoi(c.Query("page"))
    if page <= 0 {
        page = 1
    }
    pagesize, _ := strconv.Atoi(c.Query("pagesize"))
    if pagesize <= 0 || pagesize > 50 {
        pagesize = 10
    }
    //判断分类ID条件
    catId := c.Query("cat_id")
    query := "1=1 "
    args := make([]interface{}, 0)

    if catId != "" {
        query += "and cat_id = ? "
        args = append(args, catId)
    }
    //分页查询
    count := models.CountCmsNews(query, args...)
    list := models.FindCmsNews(page, pagesize, query, args...)

    c.JSON(200, gin.H{
        "code": types.ApiCode.SUCCESS,
        "msg":  types.ApiCode.GetMessage(types.ApiCode.SUCCESS),
        "result": gin.H{
            "list":     list,
            "count":    count,
            "pagesize": pagesize,
            "page":     page,
        },
    })
}

//编辑CMS内容
func PostCmsNews(c *gin.Context) {
    var form CmsNewsForm
    err := c.Bind(&form)

    if err != nil {
        c.JSON(200, gin.H{
            "code":   types.ApiCode.FAILED,
            "msg":    types.ApiCode.GetMessage(types.ApiCode.INVALID),
            "result": err.Error(),
        })
        return
    }
    modelCms := &models.CmsNews{
        Id:    form.Id,
        CatId: form.CateId,
        Title: form.Title,
    }
    //添加
    if form.Id == 0 {
        err := modelCms.AddCmsNews()
        if err != nil {
            c.JSON(200, gin.H{
                "code": types.ApiCode.FAILED,
                "msg":  err.Error(),
            })
            return
        }
    } else {
        //修改
        err := modelCms.SaveCmsNews("id = ?", form.Id)
        if err != nil {
            c.JSON(200, gin.H{
                "code": types.ApiCode.FAILED,
                "msg":  err.Error(),
            })
            return
        }
    }

    c.JSON(200, gin.H{
        "code": types.ApiCode.SUCCESS,
        "msg":  types.ApiCode.GetMessage(types.ApiCode.SUCCESS),
    })
}

//删除分类
func DelCmsCate(c *gin.Context) {
    id := c.Query("id")
    err := models.DelCmsCate("id = ?", id)
    if err != nil {
        c.JSON(200, gin.H{
            "code": types.ApiCode.FAILED,
            "msg":  err.Error(),
        })
        return
    }
    c.JSON(200, gin.H{
        "code": types.ApiCode.SUCCESS,
        "msg":  types.ApiCode.GetMessage(types.ApiCode.SUCCESS),
    })
}

//删除内容
func DelCmsNews(c *gin.Context) {
    id := c.Query("id")
    err := models.DelCmsNews("id = ?", id)
    if err != nil {
        c.JSON(200, gin.H{
            "code": types.ApiCode.FAILED,
            "msg":  err.Error(),
        })
        return
    }
    c.JSON(200, gin.H{
        "code": types.ApiCode.SUCCESS,
        "msg":  types.ApiCode.GetMessage(types.ApiCode.SUCCESS),
    })
}

可以使用接口测试工具,对接口进行测试

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
下面是一个简单的学生信息管理系统的实现增删改查)的示例代码: ```go package main import ( "fmt" ) // 学生结构体 type Student struct { id int // 学号 name string // 姓名 age int // 年龄 } // 学生列表 var studentList []Student // 添加学生 func addStudent() { var id, age int var name string fmt.Println("请输入学生信息:") fmt.Print("学号:") fmt.Scanln(&id) fmt.Print("姓名:") fmt.Scanln(&name) fmt.Print("年龄:") fmt.Scanln(&age) student := Student{id, name, age} studentList = append(studentList, student) fmt.Println("添加成功!") } // 删除学生 func deleteStudent() { var id int fmt.Println("请输入要删除的学生学号:") fmt.Scanln(&id) for i, student := range studentList { if student.id == id { studentList = append(studentList[:i], studentList[i+1:]...) fmt.Println("删除成功!") return } } fmt.Println("未找到该学生!") } // 修改学生 func modifyStudent() { var id, age int var name string fmt.Println("请输入要修改的学生学号:") fmt.Scanln(&id) for i, student := range studentList { if student.id == id { fmt.Print("请输入新的姓名:") fmt.Scanln(&name) fmt.Print("请输入新的年龄:") fmt.Scanln(&age) studentList[i].name = name studentList[i].age = age fmt.Println("修改成功!") return } } fmt.Println("未找到该学生!") } // 查询学生 func queryStudent() { var id int fmt.Println("请输入要查询的学生学号:") fmt.Scanln(&id) for _, student := range studentList { if student.id == id { fmt.Printf("学号:%d\t姓名:%s\t年龄:%d\n", student.id, student.name, student.age) return } } fmt.Println("未找到该学生!") } // 显示学生列表 func showStudentList() { fmt.Printf("学号\t姓名\t年龄\n") for _, student := range studentList { fmt.Printf("%d\t%s\t%d\n", student.id, student.name, student.age) } } func main() { for { var choice int fmt.Println("1. 添加学生信息") fmt.Println("2. 删除学生信息") fmt.Println("3. 修改学生信息") fmt.Println("4. 查询学生信息") fmt.Println("5. 显示学生列表") fmt.Println("0. 退出程序") fmt.Print("请选择操作:") fmt.Scanln(&choice) switch choice { case 1: addStudent() case 2: deleteStudent() case 3: modifyStudent() case 4: queryStudent() case 5: showStudentList() case 0: fmt.Println("程序退出!") return default: fmt.Println("输入错误,请重新输入!") } } } ``` 这个程序使用了一个学生结构体,包含学号、姓名和年龄属性。使用了一个学生列表来存储所有的学生信息。然后实现了增加、删除、修改、查询、显示学生列表几个功能。用户可以根据菜单进行选择。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值