955 lines
23 KiB
Go
955 lines
23 KiB
Go
package controllers
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"io"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
|
|
"server/models"
|
|
"server/pkg/jwtutil"
|
|
|
|
"github.com/beego/beego/v2/client/orm"
|
|
beego "github.com/beego/beego/v2/server/web"
|
|
)
|
|
|
|
// BackendArticleController CMS 文章管理
|
|
type BackendArticleController struct {
|
|
beego.Controller
|
|
}
|
|
|
|
// BackendArticleCategoryController CMS 文章分类管理
|
|
type BackendArticleCategoryController struct {
|
|
beego.Controller
|
|
}
|
|
|
|
func (c *BackendArticleController) cmsClaims() (*jwtutil.Claims, error) {
|
|
return cmsBackendClaims(&c.Controller)
|
|
}
|
|
|
|
func (c *BackendArticleCategoryController) cmsClaims() (*jwtutil.Claims, error) {
|
|
return cmsBackendClaims(&c.Controller)
|
|
}
|
|
|
|
func cmsBackendClaims(c *beego.Controller) (*jwtutil.Claims, error) {
|
|
auth := c.Ctx.Request.Header.Get("Authorization")
|
|
if auth == "" {
|
|
return nil, fmt.Errorf("未登录")
|
|
}
|
|
parts := strings.SplitN(auth, " ", 2)
|
|
if len(parts) != 2 || parts[0] != "Bearer" {
|
|
return nil, fmt.Errorf("认证信息格式错误")
|
|
}
|
|
claims, err := jwtutil.ParseToken(parts[1])
|
|
if err != nil {
|
|
return nil, fmt.Errorf("无效的token")
|
|
}
|
|
if claims.UserType != "backend" {
|
|
return nil, fmt.Errorf("无权访问")
|
|
}
|
|
return claims, nil
|
|
}
|
|
|
|
func cmsEffectiveTid(c *beego.Controller, claims *jwtutil.Claims) uint64 {
|
|
_ = c.ParseForm(1 << 20)
|
|
if tid, err := c.GetUint64("tid"); err == nil && tid > 0 {
|
|
return tid
|
|
}
|
|
if h := strings.TrimSpace(c.Ctx.Request.Header.Get("X-Tenant-Id")); h != "" {
|
|
if v, e := strconv.ParseUint(h, 10, 64); e == nil {
|
|
return v
|
|
}
|
|
}
|
|
if claims != nil && claims.TenantId > 0 {
|
|
return uint64(claims.TenantId)
|
|
}
|
|
return 0
|
|
}
|
|
|
|
func (c *BackendArticleController) cmsJSONErr(httpStatus, bizCode int, msg string) {
|
|
c.Ctx.Output.SetStatus(httpStatus)
|
|
c.Data["json"] = map[string]interface{}{"code": bizCode, "msg": msg}
|
|
_ = c.ServeJSON()
|
|
}
|
|
|
|
func (c *BackendArticleCategoryController) cmsJSONErr(httpStatus, bizCode int, msg string) {
|
|
c.Ctx.Output.SetStatus(httpStatus)
|
|
c.Data["json"] = map[string]interface{}{"code": bizCode, "msg": msg}
|
|
_ = c.ServeJSON()
|
|
}
|
|
|
|
func cmsEnsureTables(c *beego.Controller) bool {
|
|
if err := models.EnsureCmsArticleTables(); err != nil {
|
|
c.Ctx.Output.SetStatus(500)
|
|
c.Data["json"] = map[string]interface{}{"code": 500, "msg": "初始化文章表失败: " + err.Error()}
|
|
_ = c.ServeJSON()
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
|
|
func cmsParseUintArg(v interface{}) uint64 {
|
|
switch x := v.(type) {
|
|
case float64:
|
|
if x > 0 {
|
|
return uint64(x)
|
|
}
|
|
case string:
|
|
if n, err := strconv.ParseUint(strings.TrimSpace(x), 10, 64); err == nil {
|
|
return n
|
|
}
|
|
}
|
|
return 0
|
|
}
|
|
|
|
func cmsArticleToListItem(row models.CmsArticle, cateName string) map[string]interface{} {
|
|
return map[string]interface{}{
|
|
"id": row.ID,
|
|
"title": row.Title,
|
|
"author": row.Author,
|
|
"cate": cateName,
|
|
"cate_id": row.CateID,
|
|
"status": row.Status,
|
|
"views": row.Views,
|
|
"likes": row.Likes,
|
|
"top": row.Top,
|
|
"recommend": row.Recommend,
|
|
"publish_date": models.CmsFormatTime(row.PublishTime),
|
|
"update_time": models.CmsFormatTime(row.UpdateTime),
|
|
}
|
|
}
|
|
|
|
func cmsArticleToDetail(row models.CmsArticle, cateName string) map[string]interface{} {
|
|
pub := models.CmsFormatTime(row.PublishTime)
|
|
return map[string]interface{}{
|
|
"id": row.ID,
|
|
"title": row.Title,
|
|
"author": row.Author,
|
|
"cate": cateName,
|
|
"cate_id": row.CateID,
|
|
"content": row.Content,
|
|
"desc": row.Desc,
|
|
"image": row.Image,
|
|
"is_trans": row.IsTrans,
|
|
"transurl": row.TransURL,
|
|
"status": row.Status,
|
|
"views": row.Views,
|
|
"view_count": row.Views,
|
|
"likes": row.Likes,
|
|
"top": row.Top,
|
|
"recommend": row.Recommend,
|
|
"publish_time": pub,
|
|
"publish_date": pub,
|
|
"create_time": row.CreateTime.Format("2006-01-02 15:04:05"),
|
|
"update_time": models.CmsFormatTime(row.UpdateTime),
|
|
}
|
|
}
|
|
|
|
func cmsCategoryToMap(row models.CmsArticleCategory) map[string]interface{} {
|
|
return map[string]interface{}{
|
|
"id": row.ID,
|
|
"name": row.Name,
|
|
"label": row.Name,
|
|
"cid": row.Cid,
|
|
"parentId": row.Cid,
|
|
"image": row.Image,
|
|
"desc": row.Desc,
|
|
"remark": row.Desc,
|
|
"sort": row.Sort,
|
|
"status": row.Status,
|
|
}
|
|
}
|
|
|
|
// List GET /backend/articlesList
|
|
func (c *BackendArticleController) List() {
|
|
if !cmsEnsureTables(&c.Controller) {
|
|
return
|
|
}
|
|
claims, err := c.cmsClaims()
|
|
if err != nil {
|
|
c.cmsJSONErr(401, 401, err.Error())
|
|
return
|
|
}
|
|
tid := cmsEffectiveTid(&c.Controller, claims)
|
|
if tid == 0 {
|
|
c.cmsJSONErr(400, 400, "tid不能为空")
|
|
return
|
|
}
|
|
|
|
page, _ := c.GetInt("page", 1)
|
|
pageSize, _ := c.GetInt("pageSize", 10)
|
|
if page < 1 {
|
|
page = 1
|
|
}
|
|
if pageSize < 1 {
|
|
pageSize = 10
|
|
}
|
|
if pageSize > 200 {
|
|
pageSize = 200
|
|
}
|
|
|
|
keyword := strings.TrimSpace(c.GetString("keyword"))
|
|
cateFilter := strings.TrimSpace(c.GetString("cate"))
|
|
|
|
qs := models.Orm.QueryTable(new(models.CmsArticle)).
|
|
Filter("tid", tid).
|
|
Filter("delete_time__isnull", true)
|
|
if keyword != "" {
|
|
qs = qs.Filter("title__icontains", keyword)
|
|
}
|
|
if cateFilter != "" {
|
|
if cid, err := strconv.ParseUint(cateFilter, 10, 64); err == nil && cid > 0 {
|
|
qs = qs.Filter("cate_id", cid)
|
|
}
|
|
}
|
|
|
|
total, _ := qs.Count()
|
|
var rows []models.CmsArticle
|
|
offset := (page - 1) * pageSize
|
|
_, err = qs.OrderBy("-top", "-id").Limit(pageSize, offset).All(&rows)
|
|
if err != nil && err != orm.ErrNoRows {
|
|
c.cmsJSONErr(500, 500, "获取文章列表失败")
|
|
return
|
|
}
|
|
|
|
cateIDs := make([]uint64, 0, len(rows))
|
|
for _, r := range rows {
|
|
if r.CateID > 0 {
|
|
cateIDs = append(cateIDs, r.CateID)
|
|
}
|
|
}
|
|
cateNames := models.CmsCategoryNameMap(tid, cateIDs)
|
|
|
|
list := make([]map[string]interface{}, 0, len(rows))
|
|
for _, r := range rows {
|
|
list = append(list, cmsArticleToListItem(r, cateNames[r.CateID]))
|
|
}
|
|
|
|
c.Data["json"] = map[string]interface{}{
|
|
"code": 200,
|
|
"msg": "success",
|
|
"data": map[string]interface{}{"list": list, "total": total},
|
|
}
|
|
_ = c.ServeJSON()
|
|
}
|
|
|
|
// ListAll GET /backend/allarticles
|
|
func (c *BackendArticleController) ListAll() {
|
|
c.List()
|
|
}
|
|
|
|
// Detail GET /backend/articles/:id
|
|
func (c *BackendArticleController) Detail() {
|
|
if !cmsEnsureTables(&c.Controller) {
|
|
return
|
|
}
|
|
claims, err := c.cmsClaims()
|
|
if err != nil {
|
|
c.cmsJSONErr(401, 401, err.Error())
|
|
return
|
|
}
|
|
tid := cmsEffectiveTid(&c.Controller, claims)
|
|
id, _ := c.GetUint64(":id")
|
|
if id == 0 {
|
|
c.cmsJSONErr(400, 400, "无效ID")
|
|
return
|
|
}
|
|
|
|
var row models.CmsArticle
|
|
err = models.Orm.QueryTable(new(models.CmsArticle)).
|
|
Filter("id", id).
|
|
Filter("tid", tid).
|
|
Filter("delete_time__isnull", true).
|
|
One(&row)
|
|
if err == orm.ErrNoRows {
|
|
c.cmsJSONErr(404, 404, "文章不存在")
|
|
return
|
|
}
|
|
if err != nil {
|
|
c.cmsJSONErr(500, 500, "查询失败")
|
|
return
|
|
}
|
|
|
|
cateName := ""
|
|
if row.CateID > 0 {
|
|
names := models.CmsCategoryNameMap(tid, []uint64{row.CateID})
|
|
cateName = names[row.CateID]
|
|
}
|
|
|
|
c.Data["json"] = map[string]interface{}{
|
|
"code": 200,
|
|
"msg": "success",
|
|
"data": cmsArticleToDetail(row, cateName),
|
|
}
|
|
_ = c.ServeJSON()
|
|
}
|
|
|
|
type cmsArticlePayload struct {
|
|
Title string `json:"title"`
|
|
Author string `json:"author"`
|
|
Cate interface{} `json:"cate"`
|
|
Content string `json:"content"`
|
|
Desc string `json:"desc"`
|
|
Image string `json:"image"`
|
|
IsTrans int8 `json:"is_trans"`
|
|
TransURL *string `json:"transurl"`
|
|
Status int8 `json:"status"`
|
|
IgnoreSimilarity int `json:"ignore_similarity"`
|
|
}
|
|
|
|
// Create POST /backend/createarticle
|
|
func (c *BackendArticleController) Create() {
|
|
if !cmsEnsureTables(&c.Controller) {
|
|
return
|
|
}
|
|
claims, err := c.cmsClaims()
|
|
if err != nil {
|
|
c.cmsJSONErr(401, 401, err.Error())
|
|
return
|
|
}
|
|
tid := cmsEffectiveTid(&c.Controller, claims)
|
|
if tid == 0 {
|
|
c.cmsJSONErr(400, 400, "tid不能为空")
|
|
return
|
|
}
|
|
|
|
raw, err := io.ReadAll(c.Ctx.Request.Body)
|
|
if err != nil {
|
|
c.cmsJSONErr(400, 400, "参数错误")
|
|
return
|
|
}
|
|
var p cmsArticlePayload
|
|
if err := json.Unmarshal(raw, &p); err != nil {
|
|
c.cmsJSONErr(400, 400, "参数错误")
|
|
return
|
|
}
|
|
title := strings.TrimSpace(p.Title)
|
|
if title == "" {
|
|
c.cmsJSONErr(400, 400, "标题不能为空")
|
|
return
|
|
}
|
|
|
|
if p.IgnoreSimilarity != 1 {
|
|
similar, serr := models.CmsSimilarArticles(tid, title, 5)
|
|
if serr == nil && len(similar) > 0 {
|
|
c.Ctx.Output.SetStatus(409)
|
|
c.Data["json"] = map[string]interface{}{
|
|
"code": 409,
|
|
"msg": "检测到相似标题",
|
|
"data": map[string]interface{}{"similar_articles": similar},
|
|
}
|
|
_ = c.ServeJSON()
|
|
return
|
|
}
|
|
}
|
|
|
|
now := time.Now()
|
|
cateID := cmsParseUintArg(p.Cate)
|
|
row := models.CmsArticle{
|
|
Tid: tid,
|
|
Title: title,
|
|
Author: strings.TrimSpace(p.Author),
|
|
CateID: cateID,
|
|
Content: p.Content,
|
|
Desc: strings.TrimSpace(p.Desc),
|
|
Image: strings.TrimSpace(p.Image),
|
|
IsTrans: p.IsTrans,
|
|
TransURL: p.TransURL,
|
|
Status: p.Status,
|
|
CreateTime: now,
|
|
UpdateTime: &now,
|
|
}
|
|
id, err := models.Orm.Insert(&row)
|
|
if err != nil {
|
|
c.cmsJSONErr(500, 500, "创建失败")
|
|
return
|
|
}
|
|
|
|
c.Data["json"] = map[string]interface{}{"code": 200, "msg": "创建成功", "data": map[string]interface{}{"id": id}}
|
|
_ = c.ServeJSON()
|
|
}
|
|
|
|
// Update POST /backend/editarticle/:id
|
|
func (c *BackendArticleController) Update() {
|
|
if !cmsEnsureTables(&c.Controller) {
|
|
return
|
|
}
|
|
claims, err := c.cmsClaims()
|
|
if err != nil {
|
|
c.cmsJSONErr(401, 401, err.Error())
|
|
return
|
|
}
|
|
tid := cmsEffectiveTid(&c.Controller, claims)
|
|
id, _ := c.GetUint64(":id")
|
|
if id == 0 {
|
|
c.cmsJSONErr(400, 400, "无效ID")
|
|
return
|
|
}
|
|
|
|
raw, err := io.ReadAll(c.Ctx.Request.Body)
|
|
if err != nil {
|
|
c.cmsJSONErr(400, 400, "参数错误")
|
|
return
|
|
}
|
|
var p cmsArticlePayload
|
|
if err := json.Unmarshal(raw, &p); err != nil {
|
|
c.cmsJSONErr(400, 400, "参数错误")
|
|
return
|
|
}
|
|
|
|
now := time.Now()
|
|
fields := map[string]interface{}{
|
|
"title": strings.TrimSpace(p.Title),
|
|
"author": strings.TrimSpace(p.Author),
|
|
"cate_id": cmsParseUintArg(p.Cate),
|
|
"content": p.Content,
|
|
"desc": strings.TrimSpace(p.Desc),
|
|
"image": strings.TrimSpace(p.Image),
|
|
"is_trans": p.IsTrans,
|
|
"transurl": p.TransURL,
|
|
"status": p.Status,
|
|
"update_time": now,
|
|
}
|
|
n, err := models.Orm.QueryTable(new(models.CmsArticle)).
|
|
Filter("id", id).
|
|
Filter("tid", tid).
|
|
Filter("delete_time__isnull", true).
|
|
Update(fields)
|
|
if err != nil {
|
|
c.cmsJSONErr(500, 500, "更新失败")
|
|
return
|
|
}
|
|
if n == 0 {
|
|
c.cmsJSONErr(404, 404, "文章不存在")
|
|
return
|
|
}
|
|
|
|
c.Data["json"] = map[string]interface{}{"code": 200, "msg": "更新成功"}
|
|
_ = c.ServeJSON()
|
|
}
|
|
|
|
// Delete DELETE /backend/deletearticle/:id
|
|
func (c *BackendArticleController) Delete() {
|
|
if !cmsEnsureTables(&c.Controller) {
|
|
return
|
|
}
|
|
claims, err := c.cmsClaims()
|
|
if err != nil {
|
|
c.cmsJSONErr(401, 401, err.Error())
|
|
return
|
|
}
|
|
tid := cmsEffectiveTid(&c.Controller, claims)
|
|
id, _ := c.GetUint64(":id")
|
|
if id == 0 {
|
|
c.cmsJSONErr(400, 400, "无效ID")
|
|
return
|
|
}
|
|
|
|
now := time.Now()
|
|
n, err := models.Orm.QueryTable(new(models.CmsArticle)).
|
|
Filter("id", id).
|
|
Filter("tid", tid).
|
|
Filter("delete_time__isnull", true).
|
|
Update(map[string]interface{}{"delete_time": now, "update_time": now})
|
|
if err != nil {
|
|
c.cmsJSONErr(500, 500, "删除失败")
|
|
return
|
|
}
|
|
if n == 0 {
|
|
c.cmsJSONErr(404, 404, "文章不存在")
|
|
return
|
|
}
|
|
|
|
c.Data["json"] = map[string]interface{}{"code": 200, "msg": "删除成功"}
|
|
_ = c.ServeJSON()
|
|
}
|
|
|
|
func (c *BackendArticleController) setArticleFlag(field string, value int8) {
|
|
if !cmsEnsureTables(&c.Controller) {
|
|
return
|
|
}
|
|
claims, err := c.cmsClaims()
|
|
if err != nil {
|
|
c.cmsJSONErr(401, 401, err.Error())
|
|
return
|
|
}
|
|
tid := cmsEffectiveTid(&c.Controller, claims)
|
|
id, _ := c.GetUint64(":id")
|
|
if id == 0 {
|
|
c.cmsJSONErr(400, 400, "无效ID")
|
|
return
|
|
}
|
|
|
|
now := time.Now()
|
|
fields := map[string]interface{}{field: value, "update_time": now}
|
|
n, err := models.Orm.QueryTable(new(models.CmsArticle)).
|
|
Filter("id", id).
|
|
Filter("tid", tid).
|
|
Filter("delete_time__isnull", true).
|
|
Update(fields)
|
|
if err != nil {
|
|
c.cmsJSONErr(500, 500, "操作失败")
|
|
return
|
|
}
|
|
if n == 0 {
|
|
c.cmsJSONErr(404, 404, "文章不存在")
|
|
return
|
|
}
|
|
|
|
c.Data["json"] = map[string]interface{}{"code": 200, "msg": "success"}
|
|
_ = c.ServeJSON()
|
|
}
|
|
|
|
func (c *BackendArticleController) Publish() {
|
|
if !cmsEnsureTables(&c.Controller) {
|
|
return
|
|
}
|
|
claims, err := c.cmsClaims()
|
|
if err != nil {
|
|
c.cmsJSONErr(401, 401, err.Error())
|
|
return
|
|
}
|
|
tid := cmsEffectiveTid(&c.Controller, claims)
|
|
id, _ := c.GetUint64(":id")
|
|
if id == 0 {
|
|
c.cmsJSONErr(400, 400, "无效ID")
|
|
return
|
|
}
|
|
|
|
var uid uint64
|
|
raw, _ := io.ReadAll(c.Ctx.Request.Body)
|
|
if len(raw) > 0 {
|
|
var body struct {
|
|
UID uint64 `json:"uid"`
|
|
}
|
|
_ = json.Unmarshal(raw, &body)
|
|
uid = body.UID
|
|
}
|
|
if uid == 0 && claims != nil {
|
|
uid = uint64(claims.UserID)
|
|
}
|
|
|
|
now := time.Now()
|
|
fields := map[string]interface{}{
|
|
"status": int8(2),
|
|
"publish_time": now,
|
|
"publisher_id": uid,
|
|
"update_time": now,
|
|
}
|
|
n, err := models.Orm.QueryTable(new(models.CmsArticle)).
|
|
Filter("id", id).
|
|
Filter("tid", tid).
|
|
Filter("delete_time__isnull", true).
|
|
Update(fields)
|
|
if err != nil {
|
|
c.cmsJSONErr(500, 500, "发布失败")
|
|
return
|
|
}
|
|
if n == 0 {
|
|
c.cmsJSONErr(404, 404, "文章不存在")
|
|
return
|
|
}
|
|
|
|
c.Data["json"] = map[string]interface{}{"code": 200, "msg": "发布成功"}
|
|
_ = c.ServeJSON()
|
|
}
|
|
|
|
func (c *BackendArticleController) Unpublish() {
|
|
if !cmsEnsureTables(&c.Controller) {
|
|
return
|
|
}
|
|
claims, err := c.cmsClaims()
|
|
if err != nil {
|
|
c.cmsJSONErr(401, 401, err.Error())
|
|
return
|
|
}
|
|
tid := cmsEffectiveTid(&c.Controller, claims)
|
|
id, _ := c.GetUint64(":id")
|
|
if id == 0 {
|
|
c.cmsJSONErr(400, 400, "无效ID")
|
|
return
|
|
}
|
|
|
|
now := time.Now()
|
|
n, err := models.Orm.QueryTable(new(models.CmsArticle)).
|
|
Filter("id", id).
|
|
Filter("tid", tid).
|
|
Filter("delete_time__isnull", true).
|
|
Update(map[string]interface{}{"status": int8(3), "update_time": now})
|
|
if err != nil {
|
|
c.cmsJSONErr(500, 500, "下架失败")
|
|
return
|
|
}
|
|
if n == 0 {
|
|
c.cmsJSONErr(404, 404, "文章不存在")
|
|
return
|
|
}
|
|
|
|
c.Data["json"] = map[string]interface{}{"code": 200, "msg": "下架成功"}
|
|
_ = c.ServeJSON()
|
|
}
|
|
|
|
func (c *BackendArticleController) Recommend() { c.setArticleFlag("recommend", 1) }
|
|
func (c *BackendArticleController) Unrecommend() { c.setArticleFlag("recommend", 0) }
|
|
func (c *BackendArticleController) Top() { c.setArticleFlag("top", 1) }
|
|
func (c *BackendArticleController) Untop() { c.setArticleFlag("top", 0) }
|
|
|
|
// List GET /backend/categories
|
|
func (c *BackendArticleCategoryController) List() {
|
|
if !cmsEnsureTables(&c.Controller) {
|
|
return
|
|
}
|
|
claims, err := c.cmsClaims()
|
|
if err != nil {
|
|
c.cmsJSONErr(401, 401, err.Error())
|
|
return
|
|
}
|
|
tid := cmsEffectiveTid(&c.Controller, claims)
|
|
if tid == 0 {
|
|
c.cmsJSONErr(400, 400, "tid不能为空")
|
|
return
|
|
}
|
|
|
|
page, _ := c.GetInt("page", 1)
|
|
pageSize, _ := c.GetInt("pageSize", 0)
|
|
if pageSize == 0 {
|
|
pageSize, _ = c.GetInt("limit", 1000)
|
|
}
|
|
if page < 1 {
|
|
page = 1
|
|
}
|
|
if pageSize < 1 {
|
|
pageSize = 1000
|
|
}
|
|
|
|
keyword := strings.TrimSpace(c.GetString("keyword"))
|
|
qs := models.Orm.QueryTable(new(models.CmsArticleCategory)).
|
|
Filter("tid", tid).
|
|
Filter("delete_time__isnull", true)
|
|
if keyword != "" {
|
|
qs = qs.Filter("name__icontains", keyword)
|
|
}
|
|
|
|
total, _ := qs.Count()
|
|
var rows []models.CmsArticleCategory
|
|
offset := (page - 1) * pageSize
|
|
_, err = qs.OrderBy("sort", "id").Limit(pageSize, offset).All(&rows)
|
|
if err != nil && err != orm.ErrNoRows {
|
|
c.cmsJSONErr(500, 500, "获取分类失败")
|
|
return
|
|
}
|
|
|
|
list := make([]map[string]interface{}, 0, len(rows))
|
|
for _, r := range rows {
|
|
list = append(list, cmsCategoryToMap(r))
|
|
}
|
|
|
|
c.Data["json"] = map[string]interface{}{
|
|
"code": 200,
|
|
"msg": "success",
|
|
"data": map[string]interface{}{"list": list, "total": total, "records": list},
|
|
}
|
|
_ = c.ServeJSON()
|
|
}
|
|
|
|
// ListAll GET /backend/allcategories
|
|
func (c *BackendArticleCategoryController) ListAll() {
|
|
if !cmsEnsureTables(&c.Controller) {
|
|
return
|
|
}
|
|
claims, err := c.cmsClaims()
|
|
if err != nil {
|
|
c.cmsJSONErr(401, 401, err.Error())
|
|
return
|
|
}
|
|
tid := cmsEffectiveTid(&c.Controller, claims)
|
|
if tid == 0 {
|
|
c.cmsJSONErr(400, 400, "tid不能为空")
|
|
return
|
|
}
|
|
|
|
keyword := strings.TrimSpace(c.GetString("keyword"))
|
|
qs := models.Orm.QueryTable(new(models.CmsArticleCategory)).
|
|
Filter("tid", tid).
|
|
Filter("delete_time__isnull", true)
|
|
if keyword != "" {
|
|
qs = qs.Filter("name__icontains", keyword)
|
|
}
|
|
|
|
var rows []models.CmsArticleCategory
|
|
_, err = qs.OrderBy("sort", "id").All(&rows)
|
|
if err != nil && err != orm.ErrNoRows {
|
|
c.cmsJSONErr(500, 500, "获取分类失败")
|
|
return
|
|
}
|
|
|
|
list := make([]map[string]interface{}, 0, len(rows))
|
|
for _, r := range rows {
|
|
list = append(list, cmsCategoryToMap(r))
|
|
}
|
|
|
|
c.Data["json"] = map[string]interface{}{"code": 200, "msg": "success", "data": list}
|
|
_ = c.ServeJSON()
|
|
}
|
|
|
|
// Detail GET /backend/categories/:id
|
|
func (c *BackendArticleCategoryController) Detail() {
|
|
if !cmsEnsureTables(&c.Controller) {
|
|
return
|
|
}
|
|
claims, err := c.cmsClaims()
|
|
if err != nil {
|
|
c.cmsJSONErr(401, 401, err.Error())
|
|
return
|
|
}
|
|
tid := cmsEffectiveTid(&c.Controller, claims)
|
|
id, _ := c.GetUint64(":id")
|
|
if id == 0 {
|
|
c.cmsJSONErr(400, 400, "无效ID")
|
|
return
|
|
}
|
|
|
|
var row models.CmsArticleCategory
|
|
err = models.Orm.QueryTable(new(models.CmsArticleCategory)).
|
|
Filter("id", id).
|
|
Filter("tid", tid).
|
|
Filter("delete_time__isnull", true).
|
|
One(&row)
|
|
if err == orm.ErrNoRows {
|
|
c.cmsJSONErr(404, 404, "分类不存在")
|
|
return
|
|
}
|
|
if err != nil {
|
|
c.cmsJSONErr(500, 500, "查询失败")
|
|
return
|
|
}
|
|
|
|
c.Data["json"] = map[string]interface{}{"code": 200, "msg": "success", "data": cmsCategoryToMap(row)}
|
|
_ = c.ServeJSON()
|
|
}
|
|
|
|
type cmsCategoryPayload struct {
|
|
Name string `json:"name"`
|
|
Image string `json:"image"`
|
|
Desc string `json:"desc"`
|
|
Sort int `json:"sort"`
|
|
Status int8 `json:"status"`
|
|
Cid uint64 `json:"cid"`
|
|
}
|
|
|
|
// Create POST /backend/createCategory
|
|
func (c *BackendArticleCategoryController) Create() {
|
|
if !cmsEnsureTables(&c.Controller) {
|
|
return
|
|
}
|
|
claims, err := c.cmsClaims()
|
|
if err != nil {
|
|
c.cmsJSONErr(401, 401, err.Error())
|
|
return
|
|
}
|
|
tid := cmsEffectiveTid(&c.Controller, claims)
|
|
if tid == 0 {
|
|
c.cmsJSONErr(400, 400, "tid不能为空")
|
|
return
|
|
}
|
|
|
|
raw, err := io.ReadAll(c.Ctx.Request.Body)
|
|
if err != nil {
|
|
c.cmsJSONErr(400, 400, "参数错误")
|
|
return
|
|
}
|
|
var p cmsCategoryPayload
|
|
if err := json.Unmarshal(raw, &p); err != nil {
|
|
c.cmsJSONErr(400, 400, "参数错误")
|
|
return
|
|
}
|
|
name := strings.TrimSpace(p.Name)
|
|
if name == "" {
|
|
c.cmsJSONErr(400, 400, "分类名称不能为空")
|
|
return
|
|
}
|
|
|
|
now := time.Now()
|
|
row := models.CmsArticleCategory{
|
|
Tid: tid,
|
|
Cid: p.Cid,
|
|
Name: name,
|
|
Image: strings.TrimSpace(p.Image),
|
|
Desc: strings.TrimSpace(p.Desc),
|
|
Sort: p.Sort,
|
|
Status: p.Status,
|
|
CreateTime: now,
|
|
UpdateTime: &now,
|
|
}
|
|
id, err := models.Orm.Insert(&row)
|
|
if err != nil {
|
|
c.cmsJSONErr(500, 500, "创建失败")
|
|
return
|
|
}
|
|
|
|
c.Data["json"] = map[string]interface{}{"code": 200, "msg": "创建成功", "data": map[string]interface{}{"id": id}}
|
|
_ = c.ServeJSON()
|
|
}
|
|
|
|
// Update POST /backend/editCategory/:id
|
|
func (c *BackendArticleCategoryController) Update() {
|
|
if !cmsEnsureTables(&c.Controller) {
|
|
return
|
|
}
|
|
claims, err := c.cmsClaims()
|
|
if err != nil {
|
|
c.cmsJSONErr(401, 401, err.Error())
|
|
return
|
|
}
|
|
tid := cmsEffectiveTid(&c.Controller, claims)
|
|
id, _ := c.GetUint64(":id")
|
|
if id == 0 {
|
|
c.cmsJSONErr(400, 400, "无效ID")
|
|
return
|
|
}
|
|
|
|
raw, err := io.ReadAll(c.Ctx.Request.Body)
|
|
if err != nil {
|
|
c.cmsJSONErr(400, 400, "参数错误")
|
|
return
|
|
}
|
|
var p cmsCategoryPayload
|
|
if err := json.Unmarshal(raw, &p); err != nil {
|
|
c.cmsJSONErr(400, 400, "参数错误")
|
|
return
|
|
}
|
|
|
|
now := time.Now()
|
|
n, err := models.Orm.QueryTable(new(models.CmsArticleCategory)).
|
|
Filter("id", id).
|
|
Filter("tid", tid).
|
|
Filter("delete_time__isnull", true).
|
|
Update(map[string]interface{}{
|
|
"name": strings.TrimSpace(p.Name),
|
|
"image": strings.TrimSpace(p.Image),
|
|
"desc": strings.TrimSpace(p.Desc),
|
|
"sort": p.Sort,
|
|
"status": p.Status,
|
|
"cid": p.Cid,
|
|
"update_time": now,
|
|
})
|
|
if err != nil {
|
|
c.cmsJSONErr(500, 500, "更新失败")
|
|
return
|
|
}
|
|
if n == 0 {
|
|
c.cmsJSONErr(404, 404, "分类不存在")
|
|
return
|
|
}
|
|
|
|
c.Data["json"] = map[string]interface{}{"code": 200, "msg": "更新成功"}
|
|
_ = c.ServeJSON()
|
|
}
|
|
|
|
// Delete DELETE /backend/categories/:id
|
|
func (c *BackendArticleCategoryController) Delete() {
|
|
if !cmsEnsureTables(&c.Controller) {
|
|
return
|
|
}
|
|
claims, err := c.cmsClaims()
|
|
if err != nil {
|
|
c.cmsJSONErr(401, 401, err.Error())
|
|
return
|
|
}
|
|
tid := cmsEffectiveTid(&c.Controller, claims)
|
|
id, _ := c.GetUint64(":id")
|
|
if id == 0 {
|
|
c.cmsJSONErr(400, 400, "无效ID")
|
|
return
|
|
}
|
|
|
|
childCnt, _ := models.Orm.QueryTable(new(models.CmsArticleCategory)).
|
|
Filter("tid", tid).
|
|
Filter("cid", id).
|
|
Filter("delete_time__isnull", true).
|
|
Count()
|
|
if childCnt > 0 {
|
|
c.cmsJSONErr(400, 400, "请先删除子分类")
|
|
return
|
|
}
|
|
|
|
articleCnt, _ := models.Orm.QueryTable(new(models.CmsArticle)).
|
|
Filter("tid", tid).
|
|
Filter("cate_id", id).
|
|
Filter("delete_time__isnull", true).
|
|
Count()
|
|
if articleCnt > 0 {
|
|
c.cmsJSONErr(400, 400, "该分类下还有文章,无法删除")
|
|
return
|
|
}
|
|
|
|
now := time.Now()
|
|
n, err := models.Orm.QueryTable(new(models.CmsArticleCategory)).
|
|
Filter("id", id).
|
|
Filter("tid", tid).
|
|
Filter("delete_time__isnull", true).
|
|
Update(map[string]interface{}{"delete_time": now, "update_time": now})
|
|
if err != nil {
|
|
c.cmsJSONErr(500, 500, "删除失败")
|
|
return
|
|
}
|
|
if n == 0 {
|
|
c.cmsJSONErr(404, 404, "分类不存在")
|
|
return
|
|
}
|
|
|
|
c.Data["json"] = map[string]interface{}{"code": 200, "msg": "删除成功"}
|
|
_ = c.ServeJSON()
|
|
}
|
|
|
|
// UpdateStatus PATCH /backend/categories/:id/status
|
|
func (c *BackendArticleCategoryController) UpdateStatus() {
|
|
if !cmsEnsureTables(&c.Controller) {
|
|
return
|
|
}
|
|
claims, err := c.cmsClaims()
|
|
if err != nil {
|
|
c.cmsJSONErr(401, 401, err.Error())
|
|
return
|
|
}
|
|
tid := cmsEffectiveTid(&c.Controller, claims)
|
|
id, _ := c.GetUint64(":id")
|
|
if id == 0 {
|
|
c.cmsJSONErr(400, 400, "无效ID")
|
|
return
|
|
}
|
|
|
|
raw, err := io.ReadAll(c.Ctx.Request.Body)
|
|
if err != nil {
|
|
c.cmsJSONErr(400, 400, "参数错误")
|
|
return
|
|
}
|
|
var p struct {
|
|
Status int8 `json:"status"`
|
|
}
|
|
if err := json.Unmarshal(raw, &p); err != nil {
|
|
c.cmsJSONErr(400, 400, "参数错误")
|
|
return
|
|
}
|
|
|
|
now := time.Now()
|
|
n, err := models.Orm.QueryTable(new(models.CmsArticleCategory)).
|
|
Filter("id", id).
|
|
Filter("tid", tid).
|
|
Filter("delete_time__isnull", true).
|
|
Update(map[string]interface{}{"status": p.Status, "update_time": now})
|
|
if err != nil {
|
|
c.cmsJSONErr(500, 500, "更新失败")
|
|
return
|
|
}
|
|
if n == 0 {
|
|
c.cmsJSONErr(404, 404, "分类不存在")
|
|
return
|
|
}
|
|
|
|
c.Data["json"] = map[string]interface{}{"code": 200, "msg": "更新成功"}
|
|
_ = c.ServeJSON()
|
|
}
|