線上客服系統源碼開發實戰總結: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 MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...