Add internal/handler/dashboard.go

This commit is contained in:
ata
2026-07-10 10:06:35 +00:00
committed by Gitee
parent 94cb03ce67
commit 0b0efcebe1

View File

@@ -0,0 +1,281 @@
package handler
import (
"strconv"
"gotest/internal/model"
"github.com/gin-gonic/gin"
"gorm.io/gorm"
)
// tableRegistry 映射前端模块名 → GORM 模型(用于通用 CRUD)
var tableRegistry = map[string]interface{}{
// 企业模块
"enterprise_company": &model.Company{},
"enterprise_news": &model.EnterpriseNews{},
"enterprise_services": &model.EnterpriseService{},
"enterprise_team": &model.TeamMember{},
// 电商模块
"shop_products": &model.Product{},
"shop_categories": &model.ProductCategory{},
// 外卖模块
"food_restaurants": &model.Restaurant{},
"food_categories": &model.RestaurantCategory{},
"food_menu_items": &model.MenuItem{},
"food_menu_categories": &model.MenuCategory{},
// 游戏模块
"game_games": &model.Game{},
"game_categories": &model.GameCategory{},
// 应用模块
"app_apps": &model.App{},
"app_categories": &model.AppCategory{},
// 音乐模块
"music_songs": &model.Song{},
"music_categories": &model.MusicCategory{},
}
// tableLabels 模块中文标签(用于前端展示)
var tableLabels = map[string]string{
"enterprise_company": "企业信息",
"enterprise_news": "企业新闻",
"enterprise_services": "企业服务",
"enterprise_team": "团队成员",
"shop_products": "商品管理",
"shop_categories": "商品分类",
"food_restaurants": "餐厅管理",
"food_categories": "餐厅分类",
"food_menu_items": "菜品管理",
"food_menu_categories": "菜品分类",
"game_games": "游戏管理",
"game_categories": "游戏分类",
"app_apps": "应用管理",
"app_categories": "应用分类",
"music_songs": "歌曲管理",
"music_categories": "音乐分类",
}
// DashboardHandler 管理后台仪表盘处理器(通用 CRUD + 统计)
type DashboardHandler struct {
db *gorm.DB
}
// NewDashboardHandler 创建仪表盘处理器
func NewDashboardHandler(db *gorm.DB) *DashboardHandler {
return &DashboardHandler{db: db}
}
// GetStats 获取仪表盘统计数据 GET /api/v1/admin/dashboard/stats
func (h *DashboardHandler) GetStats(c *gin.Context) {
stats := gin.H{}
// 用户统计
var userCount int64
h.db.Model(&model.User{}).Count(&userCount)
stats["users"] = userCount
// 各业务模块统计
for table, modelType := range tableRegistry {
var count int64
h.db.Model(modelType).Count(&count)
stats[table] = count
}
// 按业务线分组
grouped := gin.H{
"enterprise": gin.H{
"label": "企业官网",
"items": gin.H{
"company": stats["enterprise_company"],
"news": stats["enterprise_news"],
"services": stats["enterprise_services"],
"team": stats["enterprise_team"],
},
},
"shop": gin.H{
"label": "跨境电商",
"items": gin.H{
"products": stats["shop_products"],
"categories": stats["shop_categories"],
},
},
"food": gin.H{
"label": "外卖平台",
"items": gin.H{
"restaurants": stats["food_restaurants"],
"categories": stats["food_categories"],
"menu_items": stats["food_menu_items"],
"menu_categories": stats["food_menu_categories"],
},
},
"game": gin.H{
"label": "游戏平台",
"items": gin.H{
"games": stats["game_games"],
"categories": stats["game_categories"],
},
},
"app": gin.H{
"label": "应用商店",
"items": gin.H{
"apps": stats["app_apps"],
"categories": stats["app_categories"],
},
},
"music": gin.H{
"label": "音乐平台",
"items": gin.H{
"songs": stats["music_songs"],
"categories": stats["music_categories"],
},
},
}
Success(c, gin.H{
"total_counts": stats,
"grouped": grouped,
"tables": getTableList(),
})
}
// getTableList 返回所有可管理的表列表
func getTableList() []gin.H {
list := make([]gin.H, 0, len(tableRegistry))
for key := range tableRegistry {
list = append(list, gin.H{
"key": key,
"label": tableLabels[key],
})
}
return list
}
// ListItems 通用列表查询 GET /api/v1/admin/dashboard/:table
func (h *DashboardHandler) ListItems(c *gin.Context) {
table := c.Param("table")
modelType, ok := tableRegistry[table]
if !ok {
FailBadRequest(c, "无效的数据表: "+table)
return
}
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "20"))
keyword := c.Query("keyword")
status := c.Query("status")
if page < 1 {
page = 1
}
if pageSize < 1 || pageSize > 100 {
pageSize = 20
}
offset := (page - 1) * pageSize
query := h.db.Model(modelType)
// 关键词搜索(按 name 或 title 字段)
if keyword != "" {
query = query.Where("name LIKE ? OR title LIKE ?", "%"+keyword+"%", "%"+keyword+"%")
}
// 状态过滤
if status != "" {
query = query.Where("status = ?", status)
}
var total int64
query.Count(&total)
var results []map[string]interface{}
if err := query.Order("sort ASC, id DESC").Offset(offset).Limit(pageSize).Find(&results).Error; err != nil {
FailInternal(c, "查询失败: "+err.Error())
return
}
Success(c, gin.H{
"list": results,
"total": total,
"page": page,
"page_size": pageSize,
})
}
// CreateItem 通用创建 POST /api/v1/admin/dashboard/:table
func (h *DashboardHandler) CreateItem(c *gin.Context) {
table := c.Param("table")
modelType, ok := tableRegistry[table]
if !ok {
FailBadRequest(c, "无效的数据表: "+table)
return
}
var body map[string]interface{}
if err := c.ShouldBindJSON(&body); err != nil {
FailBadRequest(c, "参数解析失败")
return
}
if err := h.db.Model(modelType).Create(&body).Error; err != nil {
FailBadRequest(c, "创建失败: "+err.Error())
return
}
Success(c, body)
}
// UpdateItem 通用更新 PUT /api/v1/admin/dashboard/:table/:id
func (h *DashboardHandler) UpdateItem(c *gin.Context) {
table := c.Param("table")
modelType, ok := tableRegistry[table]
if !ok {
FailBadRequest(c, "无效的数据表: "+table)
return
}
id, err := strconv.ParseUint(c.Param("id"), 10, 64)
if err != nil {
FailBadRequest(c, "无效的 ID")
return
}
var body map[string]interface{}
if err := c.ShouldBindJSON(&body); err != nil {
FailBadRequest(c, "参数解析失败")
return
}
// 移除不允许更新的字段
delete(body, "id")
delete(body, "created_at")
if err := h.db.Model(modelType).Where("id = ?", id).Updates(body).Error; err != nil {
FailBadRequest(c, "更新失败: "+err.Error())
return
}
SuccessMsg(c, "更新成功")
}
// DeleteItem 通用删除 DELETE /api/v1/admin/dashboard/:table/:id
func (h *DashboardHandler) DeleteItem(c *gin.Context) {
table := c.Param("table")
modelType, ok := tableRegistry[table]
if !ok {
FailBadRequest(c, "无效的数据表: "+table)
return
}
id, err := strconv.ParseUint(c.Param("id"), 10, 64)
if err != nil {
FailBadRequest(c, "无效的 ID")
return
}
if err := h.db.Model(modelType).Where("id = ?", id).Delete(nil).Error; err != nil {
FailBadRequest(c, "删除失败: "+err.Error())
return
}
SuccessMsg(c, "删除成功")
}