From 0b0efcebe1f2664187a441aa5d002565c4556ed4 Mon Sep 17 00:00:00 2001 From: ata <17314593+asdxzaaaaa@user.noreply.gitee.com> Date: Fri, 10 Jul 2026 10:06:35 +0000 Subject: [PATCH] Add internal/handler/dashboard.go --- internal/handler/dashboard.go | 281 ++++++++++++++++++++++++++++++++++ 1 file changed, 281 insertions(+) create mode 100644 internal/handler/dashboard.go diff --git a/internal/handler/dashboard.go b/internal/handler/dashboard.go new file mode 100644 index 0000000..045c0a6 --- /dev/null +++ b/internal/handler/dashboard.go @@ -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, "删除成功") +}