線上客服系統源碼開發實戰總結:Golang實現CMS內容管理增刪查改功能

来源:https://www.cnblogs.com/taoshihan/archive/2022/11/18/16901834.html
-Advertisement-
Play Games

自己的客服系統做好了,官網頁面也有了,但是沒有介紹性的內容文章。網站被收錄的太少,這樣會導致網站的權重不高,搜索排名比較低。 因此要簡單的加上一個小型的內容管理功能。 設計資料庫 很簡單的兩張表,分類表和內容表 DROP TABLE IF EXISTS `cms_cate`; CREATE TABL ...


自己的客服系統做好了,官網頁面也有了,但是沒有介紹性的內容文章。網站被收錄的太少,這樣會導致網站的權重不高,搜索排名比較低。

因此要簡單的加上一個小型的內容管理功能。

設計資料庫

很簡單的兩張表,分類表和內容表

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的時候,可以格式化時間

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),
    })
}

可以使用介面測試工具,對介面進行測試

 

十年開發經驗程式員,離職全心創業中,歷時三年開發出的產品《唯一客服系統》

一款基於Golang+Vue開發的線上客服系統,軟體著作權編號:2021SR1462600。一套可私有化部署的網站線上客服系統,編譯後的二進位文件可直接使用無需搭開發環境,下載zip解壓即可,僅依賴MySQL資料庫,是一個開箱即用的全渠道線上客服系統,致力於幫助廣大開發者/公司快速部署整合私有化客服功能。 開源地址:唯一客服(開源學習版) 官網地址:唯一客服官網
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 現在要是說mysql是什麼東西,就不禮貌了 雖然有的同學沒有進行系統的深入學習,但應該也有個基本概念 【不瞭解也沒關係,後續會進行mysql專欄講解】簡單來說,存儲數據的 學習mysql,就要先安裝它 上官網 : https://dev.mysql.com/downloads/mysql/ 打開網址 ...
  • 11月15日,HMS Core手語服務在2022(第二十一屆)中國互聯網大會 “互聯網助力經濟社會數字化轉型”案例評選活動中,榮獲“特別推薦案例”。 經過一年多的技術迭代和經驗積累,HMS Core手語服務已與多個行業的開發者合作,將AI手語翻譯能力應用在了教育、社交、新聞、政務辦理等場景,助力開發 ...
  • 項目同步git:https://gitee.com/lixin_ajax/vue3-vite-ts-pinia-vant-less.git 覺得有幫助的小伙伴請點下小心心哦 為避免贅述,過於基礎的點會直接省略或貼圖,比如創建文件夾/文件的路徑/路由一類 配置相應功能,也儘量只貼相關代碼,並不代表整個 ...
  • 這裡給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 視頻通話SDK用的即構的,uniapp插件市場地址 推送用的極光的,uniapp插件市場地址 即構音視頻SDK uniapp插件市場的貌似是有些問題,導入不進項目,直接去官網下載,然後放到項目下的 nativeplugins 目錄下,在配 ...
  • 在工作流頁面中,除了特定的業務表單信息外,往往也需要同時展示通用申請單的相關信息,因此在頁面設計的時候需要使用一些組件化的概念來實現動態的內容展示處理,本篇隨筆介紹Vue3+TypeScript+ElementPus的前端工作流模塊中實現統一的表單編輯和表單詳情查看處理。 ...
  • 前言: 昨天我們學習了 TS 的數據類型,不知道大家回去以後練習沒練習,如果你練習了一定會發現一個問題,我們的 TS 好像和 JS 不太一樣 JS 寫完之後直接就可以放到頁面上,就可以用了,而我們的 TS 需要用 tsc 編譯一下,編譯為 JS 才能在頁面中使用 這時就會有同學說了,誒呀,六扇老師, ...
  • 限流,通常講就是限制流量,也有很多其他的說法,比如:限頻、疲勞度控制等。 原文鏈接:自定義開發限流組件 之 場景需求分析-一隻小Coder 最近遇到一個需求,系統A作為一個專門推送消息給客戶的消息中心系統,對於每個客戶是否能接受消息,能接受多少消息,接收消息的速度,能接受哪些消息等都要進行控制,這也 ...
  • 5.4 介面開發-根據id刪除附件 第2-1-2章 傳統方式安裝FastDFS-附FastDFS常用命令 第2-1-3章 docker-compose安裝FastDFS,實現文件存儲服務 第2-1-5章 docker安裝MinIO實現文件存儲服務-springboot整合minio-minio全網最 ...
一周排行
    -Advertisement-
    Play Games
  • 基於.NET Framework 4.8 開發的深度學習模型部署測試平臺,提供了YOLO框架的主流系列模型,包括YOLOv8~v9,以及其系列下的Det、Seg、Pose、Obb、Cls等應用場景,同時支持圖像與視頻檢測。模型部署引擎使用的是OpenVINO™、TensorRT、ONNX runti... ...
  • 十年沉澱,重啟開發之路 十年前,我沉浸在開發的海洋中,每日與代碼為伍,與演算法共舞。那時的我,滿懷激情,對技術的追求近乎狂熱。然而,隨著歲月的流逝,生活的忙碌逐漸占據了我的大部分時間,讓我無暇顧及技術的沉澱與積累。 十年間,我經歷了職業生涯的起伏和變遷。從初出茅廬的菜鳥到逐漸嶄露頭角的開發者,我見證了 ...
  • C# 是一種簡單、現代、面向對象和類型安全的編程語言。.NET 是由 Microsoft 創建的開發平臺,平臺包含了語言規範、工具、運行,支持開發各種應用,如Web、移動、桌面等。.NET框架有多個實現,如.NET Framework、.NET Core(及後續的.NET 5+版本),以及社區版本M... ...
  • 前言 本文介紹瞭如何使用三菱提供的MX Component插件實現對三菱PLC軟元件數據的讀寫,記錄了使用電腦模擬,模擬PLC,直至完成測試的詳細流程,並重點介紹了在這個過程中的易錯點,供參考。 用到的軟體: 1. PLC開發編程環境GX Works2,GX Works2下載鏈接 https:// ...
  • 前言 整理這個官方翻譯的系列,原因是網上大部分的 tomcat 版本比較舊,此版本為 v11 最新的版本。 開源項目 從零手寫實現 tomcat minicat 別稱【嗅虎】心有猛虎,輕嗅薔薇。 系列文章 web server apache tomcat11-01-官方文檔入門介紹 web serv ...
  • 1、jQuery介紹 jQuery是什麼 jQuery是一個快速、簡潔的JavaScript框架,是繼Prototype之後又一個優秀的JavaScript代碼庫(或JavaScript框架)。jQuery設計的宗旨是“write Less,Do More”,即倡導寫更少的代碼,做更多的事情。它封裝 ...
  • 前言 之前的文章把js引擎(aardio封裝庫) 微軟開源的js引擎(ChakraCore))寫好了,這篇文章整點js代碼來測一下bug。測試網站:https://fanyi.youdao.com/index.html#/ 逆向思路 逆向思路可以看有道翻譯js逆向(MD5加密,AES加密)附完整源碼 ...
  • 引言 現代的操作系統(Windows,Linux,Mac OS)等都可以同時打開多個軟體(任務),這些軟體在我們的感知上是同時運行的,例如我們可以一邊瀏覽網頁,一邊聽音樂。而CPU執行代碼同一時間只能執行一條,但即使我們的電腦是單核CPU也可以同時運行多個任務,如下圖所示,這是因為我們的 CPU 的 ...
  • 掌握使用Python進行文本英文統計的基本方法,並瞭解如何進一步優化和擴展這些方法,以應對更複雜的文本分析任務。 ...
  • 背景 Redis多數據源常見的場景: 分區數據處理:當數據量增長時,單個Redis實例可能無法處理所有的數據。通過使用多個Redis數據源,可以將數據分區存儲在不同的實例中,使得數據處理更加高效。 多租戶應用程式:對於多租戶應用程式,每個租戶可以擁有自己的Redis數據源,以確保數據隔離和安全性。 ...