package service import ( "errors" "strconv" "github.com/flipped-aurora/gin-vue-admin/server/global" "github.com/flipped-aurora/gin-vue-admin/server/plugin/wechat-integration/model" "github.com/silenceper/wechat/v2/officialaccount/menu" "gorm.io/gorm" ) type MpMenuService struct{} // GetMenuList 获取菜单列表 func (m *MpMenuService) GetMenuList() ([]model.MpMenu, error) { var menus []model.MpMenu err := global.GVA_DB.Order("id asc").Find(&menus).Error if err != nil { return nil, err } return menus, nil } // CreateMenu 创建菜单 func (m *MpMenuService) CreateMenu(menuData *model.MpMenu) error { err := global.GVA_DB.Create(menuData).Error if err != nil { global.GVA_LOG.Error("创建菜单失败: " + err.Error()) return err } return nil } // UpdateMenu 更新菜单 func (m *MpMenuService) UpdateMenu(menuData *model.MpMenu) error { err := global.GVA_DB.Save(menuData).Error if err != nil { global.GVA_LOG.Error("更新菜单失败: " + err.Error()) return err } return nil } // DeleteMenu 删除菜单 func (m *MpMenuService) DeleteMenu(id uint) error { err := global.GVA_DB.Delete(&model.MpMenu{}, id).Error if err != nil { global.GVA_LOG.Error("删除菜单失败: " + err.Error()) return err } return nil } // GetMenuByID 根据ID获取菜单 func (m *MpMenuService) GetMenuByID(id uint) (*model.MpMenu, error) { var menuItem model.MpMenu err := global.GVA_DB.Where("id = ?", id).First(&menuItem).Error if err != nil { return nil, err } return &menuItem, nil } // PublishMenu 发布菜单到微信服务器 func (m *MpMenuService) PublishMenu() error { // 获取所有菜单 menus, err := m.GetMenuList() if err != nil { return err } // 构建微信菜单结构 wechatMenus := m.buildWechatMenus(menus) // 获取微信公众号实例 mpUserService := &MpUserService{} oa, err := mpUserService.GetOfficialAccount() if err != nil { return err } // 发布菜单 err = oa.GetMenu().SetMenu(wechatMenus) if err != nil { global.GVA_LOG.Error("发布菜单到微信服务器失败: " + err.Error()) return err } global.GVA_LOG.Info("菜单发布成功") return nil } // DeleteWechatMenu 删除微信服务器上的菜单 func (m *MpMenuService) DeleteWechatMenu() error { mpUserService := &MpUserService{} oa, err := mpUserService.GetOfficialAccount() if err != nil { return err } err = oa.GetMenu().DeleteMenu() if err != nil { global.GVA_LOG.Error("删除微信菜单失败: " + err.Error()) return err } global.GVA_LOG.Info("微信菜单删除成功") return nil } // buildWechatMenus 构建微信菜单结构 func (m *MpMenuService) buildWechatMenus(menus []model.MpMenu) []*menu.Button { var buttons []*menu.Button // 找出一级菜单 for _, menuItem := range menus { if !menuItem.HasParent() { button := &menu.Button{ Name: *menuItem.Name, Type: menuItem.Type, } // 设置菜单属性 if menuItem.IsClickType() && menuItem.MenuKey != nil { button.Key = *menuItem.MenuKey } else if menuItem.IsViewType() && menuItem.URL != nil { button.URL = *menuItem.URL } else if menuItem.IsMiniProgramType() { if menuItem.URL != nil { button.URL = *menuItem.URL } if menuItem.MiniProgramAppID != nil { button.AppID = *menuItem.MiniProgramAppID } if menuItem.MiniProgramPagePath != nil { button.PagePath = *menuItem.MiniProgramPagePath } } // 查找子菜单 subButtons := m.findSubMenus(menus, menuItem.ID) if len(subButtons) > 0 { button.SubButtons = subButtons // 有子菜单时,清除父菜单的类型和属性 button.Type = "" button.Key = "" button.URL = "" } buttons = append(buttons, button) } } return buttons } // findSubMenus 查找子菜单 func (m *MpMenuService) findSubMenus(menus []model.MpMenu, parentID uint) []*menu.Button { var subButtons []*menu.Button parentIDStr := strconv.FormatUint(uint64(parentID), 10) for _, menuItem := range menus { if menuItem.ParentID != nil && *menuItem.ParentID == parentIDStr { button := &menu.Button{ Name: *menuItem.Name, Type: menuItem.Type, } // 设置菜单属性 if menuItem.IsClickType() && menuItem.MenuKey != nil { button.Key = *menuItem.MenuKey } else if menuItem.IsViewType() && menuItem.URL != nil { button.URL = *menuItem.URL } else if menuItem.IsMiniProgramType() { if menuItem.URL != nil { button.URL = *menuItem.URL } if menuItem.MiniProgramAppID != nil { button.AppID = *menuItem.MiniProgramAppID } if menuItem.MiniProgramPagePath != nil { button.PagePath = *menuItem.MiniProgramPagePath } } subButtons = append(subButtons, button) } } return subButtons } // ProcessMenuClick 处理菜单点击事件 func (m *MpMenuService) ProcessMenuClick(openid, menuKey string) error { // 查找菜单项 var menuItem model.MpMenu err := global.GVA_DB.Where("menu_key = ?", menuKey).First(&menuItem).Error if err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { global.GVA_LOG.Warn("未找到菜单项: " + menuKey) return nil } return err } // 如果有回复内容,发送回复 if menuItem.ReplyMessageType != nil && menuItem.ReplyContent != nil { messageService := &MpMessageService{} switch *menuItem.ReplyMessageType { case "text": err = messageService.SendTextMessage(openid, *menuItem.ReplyContent) if err != nil { global.GVA_LOG.Error("发送菜单回复失败: " + err.Error()) return err } } } return nil }