From 7ab6958538320bae8527fcc99fcf3afdbdff386a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E5=BF=97=E5=BC=BA?= <357099073@qq.com> Date: Fri, 17 Jul 2026 11:57:10 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- go/controllers/backend_article.go | 83 +++++++++++++++++++++++++++++++ go/routers/backend/backend.go | 1 + go/services/tenant_lookup.go | 30 +++++------ 3 files changed, 96 insertions(+), 18 deletions(-) diff --git a/go/controllers/backend_article.go b/go/controllers/backend_article.go index d9e070b..e50b448 100644 --- a/go/controllers/backend_article.go +++ b/go/controllers/backend_article.go @@ -4,6 +4,7 @@ import ( "encoding/json" "fmt" "io" + "sort" "strconv" "strings" "time" @@ -162,6 +163,88 @@ func cmsCategoryToMap(row models.CmsArticleCategory) map[string]interface{} { } } + // ContentStats GET /backend/contentstats +func (c *BackendArticleController) ContentStats() { + 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 + } + + // 统计已发布且未删除的文章,避免把草稿、下架文章计入内容数据。 + var rows []models.CmsArticle + _, err = models.Orm.QueryTable(new(models.CmsArticle)). + Filter("tid", tid). + Filter("status", 2). + Filter("delete_time__isnull", true). + All(&rows) + if err != nil && err != orm.ErrNoRows { + c.cmsJSONErr(500, 500, "获取内容统计失败") + return + } + + totalArticles := len(rows) + now := time.Now() + year, month, _ := now.Date() + totalLikes := 0 + totalViews := 0 + monthArticles := 0 + for _, row := range rows { + totalLikes += row.Likes + totalViews += row.Views + if row.PublishTime != nil { + publishYear, publishMonth, _ := row.PublishTime.Date() + if publishYear == year && publishMonth == month { + monthArticles++ + } + } + } + + // 按阅读量倒序返回热门文章。 + sort.SliceStable(rows, func(i, j int) bool { + if rows[i].Views == rows[j].Views { + return rows[i].ID > rows[j].ID + } + return rows[i].Views > rows[j].Views + }) + if len(rows) > 5 { + rows = rows[:5] + } + + cateIDs := make([]uint64, 0, len(rows)) + for _, row := range rows { + if row.CateID > 0 { + cateIDs = append(cateIDs, row.CateID) + } + } + cateNames := models.CmsCategoryNameMap(tid, cateIDs) + hotArticles := make([]map[string]interface{}, 0, len(rows)) + for _, row := range rows { + hotArticles = append(hotArticles, cmsArticleToListItem(row, cateNames[row.CateID])) + } + + c.Data["json"] = map[string]interface{}{ + "code": 200, + "msg": "success", + "data": map[string]interface{}{ + "total_articles": totalArticles, + "month_articles": monthArticles, + "total_likes": totalLikes, + "total_views": totalViews, + "hot_articles": hotArticles, + }, + } + _ = c.ServeJSON() +} + // List GET /backend/articlesList func (c *BackendArticleController) List() { if !cmsEnsureTables(&c.Controller) { diff --git a/go/routers/backend/backend.go b/go/routers/backend/backend.go index c990dc5..6745ca8 100644 --- a/go/routers/backend/backend.go +++ b/go/routers/backend/backend.go @@ -110,6 +110,7 @@ func RegisterAuthRoutes() { // 文章管理 beego.Router("/backend/articlesList", &controllers.BackendArticleController{}, "get:List") + beego.Router("/backend/contentstats", &controllers.BackendArticleController{}, "get:ContentStats") beego.Router("/backend/allarticles", &controllers.BackendArticleController{}, "get:ListAll") beego.Router("/backend/articles/:id", &controllers.BackendArticleController{}, "get:Detail") beego.Router("/backend/createarticle", &controllers.BackendArticleController{}, "post:Create") diff --git a/go/services/tenant_lookup.go b/go/services/tenant_lookup.go index 211527d..609e15c 100644 --- a/go/services/tenant_lookup.go +++ b/go/services/tenant_lookup.go @@ -8,31 +8,25 @@ import ( "server/models" ) - func findTenantByLoginName(loginName string) (*models.SystemTenant, error) { loginName = strings.TrimSpace(loginName) if loginName == "" { return nil, orm.ErrNoRows } - - qs := models.Orm.QueryTable(new(models.SystemTenant)). - Filter("status", 1). - Filter("delete_time__isnull", true) - tenant := &models.SystemTenant{} - err := qs.Filter("tenant_name", loginName).One(tenant) - if err == nil { - return tenant, nil + baseQuery := func() orm.QuerySeter { + return models.Orm.QueryTable(new(models.SystemTenant)). + Filter("status", 1). + Filter("delete_time__isnull", true) } - tenant = &models.SystemTenant{} - err = models.Orm.QueryTable(new(models.SystemTenant)). - Filter("status", 1). - Filter("delete_time__isnull", true). - Filter("tenant_code", loginName). - One(tenant) - if err != nil { - return nil, err + // 登录时支持租户全称、租户简称和租户编码。 + for _, field := range []string{"tenant_name", "tenant_short_name", "tenant_code"} { + tenant := &models.SystemTenant{} + if err := baseQuery().Filter(field, loginName).One(tenant); err == nil { + return tenant, nil + } } - return tenant, nil + + return nil, orm.ErrNoRows }