mh_goadmin_server/app/admin/apis/message/bus_message.go

564 lines
16 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package message
import (
"encoding/json"
"github.com/gin-gonic/gin"
"go-admin/app/admin/models"
orm "go-admin/common/global"
"go-admin/logger"
"go-admin/tools/app"
"net/http"
"time"
)
// BusMessageCreate 业务消息-新增
// @Summary 业务消息-新增
// @Tags 消息中心V1.5.0
// @Produce json
// @Accept json
// @Param request body models.BusMessageCreateReq true "新增业务消息模型"
// @Success 200 {object} models.BusMessageCreateResp
// @Router /api/v1/bus_message/create [post]
func BusMessageCreate(c *gin.Context) {
var req models.BusMessageCreateReq
if err := c.ShouldBindJSON(&req); err != nil {
app.Error(c, http.StatusBadRequest, err, "参数绑定失败")
return
}
// 校验业务类型、事件类型、模板变量
if err := models.ValidateBizEventAndTemplate(req.BizType, req.Event, req.ContentTemplate); err != nil {
app.Error(c, http.StatusBadRequest, err, "模板校验失败")
return
}
// 创建业务消息配置
msg := models.SystemMessageConfig{
MessageType: models.BusinessMessageType, // 业务消息
Title: req.Title,
ContentTemplate: req.ContentTemplate,
BizType: req.BizType,
Event: req.Event,
Status: req.Status,
}
if err := orm.Eloquent.Create(&msg).Error; err != nil {
app.Error(c, http.StatusInternalServerError, err, "创建业务消息失败")
return
}
// 创建接收对象配置target_type = 2
for _, roleID := range req.RoleID {
target := models.SystemMessageTarget{
MessageConfigID: uint(msg.ID),
TargetType: models.TargetTypeByRole, // 角色
TargetID: roleID,
}
if err := orm.Eloquent.Create(&target).Error; err != nil {
app.Error(c, http.StatusInternalServerError, err, "接收对象配置失败")
return
}
}
app.OK(c, models.BusMessageCreateResp{ID: uint(msg.ID)}, "创建成功")
}
// BusMessageList 业务消息-列表
// @Summary 业务消息-列表
// @Tags 消息中心V1.5.0
// @Accept json
// @Produce json
// @Param request body models.BusMessageListReq true "查询条件"
// @Success 200 {object} models.BusMessageListResp
// @Router /api/v1/bus_message/list [post]
func BusMessageList(c *gin.Context) {
var req models.BusMessageListReq
if err := c.ShouldBindJSON(&req); err != nil {
app.Error(c, http.StatusBadRequest, nil, "参数错误: "+err.Error())
return
}
if req.Page <= 0 {
req.Page = 1
}
if req.PageSize <= 0 {
req.PageSize = 10
}
// 基础查询:业务消息
db := orm.Eloquent.Table("system_message_config").
Where("message_type = ?", models.BusinessMessageType)
if req.BizType != "" {
db = db.Where("biz_type = ?", req.BizType)
}
if req.Event != "" {
db = db.Where("event = ?", req.Event)
}
if req.Status != 0 {
db = db.Where("status = ?", req.Status)
}
// 角色过滤JOIN subquery
if len(req.RoleID) > 0 {
subQuery := orm.Eloquent.Table("system_message_target").
Select("message_config_id").
Where("target_type = ?", models.TargetTypeByRole).
Where("target_id IN (?)", req.RoleID)
db = db.Where("id IN (?)", subQuery)
}
var total int64
if err := db.Count(&total).Error; err != nil {
app.Error(c, http.StatusInternalServerError, nil, "统计失败: "+err.Error())
return
}
var list []models.SystemMessageConfig
if err := db.
Order("created_at DESC").
Offset((req.Page - 1) * req.PageSize).
Limit(req.PageSize).
Find(&list).Error; err != nil {
app.Error(c, http.StatusInternalServerError, nil, "查询失败: "+err.Error())
return
}
//查询全部启用的事件注册表
var eventRegistryList []models.SystemEventRegistry
eventRegistryMap := make(map[string]models.SystemEventRegistry)
if err := orm.Eloquent.
Where("is_enabled = ?", true).
Find(&eventRegistryList).Error; err == nil {
for _, ev := range eventRegistryList {
key := ev.BizType + "#" + ev.Event
eventRegistryMap[key] = ev
}
}
var items []models.BusMessageItem
for _, cfg := range list {
key := cfg.BizType + "#" + cfg.Event
reg := eventRegistryMap[key]
item := models.BusMessageItem{
ID: cfg.ID,
CreatedAt: cfg.CreatedAt,
UpdatedAt: cfg.UpdatedAt,
Title: cfg.Title,
ContentTemplate: cfg.ContentTemplate,
BizType: cfg.BizType,
BizName: reg.BizName,
Event: cfg.Event,
EventName: reg.EventName,
Status: cfg.Status,
}
// 查询该消息绑定的所有角色
var targets []models.SystemMessageTarget
if err := orm.Eloquent.Where("message_config_id = ? AND target_type = ?", cfg.ID,
models.TargetTypeByRole).Find(&targets).Error; err == nil {
for _, t := range targets {
item.RoleID = append(item.RoleID, t.TargetID)
}
}
items = append(items, item)
}
resp := models.BusMessageListResp{
List: items,
Total: total,
Page: req.Page,
PageSize: req.PageSize,
}
app.OK(c, resp, "查询成功")
}
// BusMessageSetStatus 业务消息-设置状态(启用/禁用)
// @Summary 业务消息-设置状态(启用/禁用)
// @Tags 消息中心V1.5.0
// @Accept json
// @Produce json
// @Param request body models.BusMessageSetStatusReq true "状态更新请求"
// @Success 200 {object} app.Response
// @Router /api/v1/bus_message/set_status [post]
func BusMessageSetStatus(c *gin.Context) {
var req models.BusMessageSetStatusReq
if err := c.ShouldBindJSON(&req); err != nil {
app.Error(c, http.StatusBadRequest, nil, "参数错误: "+err.Error())
return
}
var config models.SystemMessageConfig
if err := orm.Eloquent.Where("id = ? AND message_type = ?", req.ID, models.BusinessMessageType).
First(&config).Error; err != nil {
app.Error(c, http.StatusNotFound, nil, "业务消息不存在")
return
}
// 校验状态切换合法性
switch req.Status {
case 1: // 启用
if config.Status != models.MessageStatusOnDisable {
app.Error(c, http.StatusBadRequest, nil, "只有禁用状态才能启用")
return
}
case 2: // 禁用
if config.Status != models.MessageStatusOnStart {
app.Error(c, http.StatusBadRequest, nil, "只有启用状态才能禁用")
return
}
default:
app.Error(c, http.StatusBadRequest, nil, "不支持的目标状态")
return
}
// 状态更新
if err := orm.Eloquent.Model(&config).Update("status", req.Status).Error; err != nil {
app.Error(c, http.StatusInternalServerError, nil, "状态更新失败")
return
}
app.OK(c, nil, "状态更新成功")
}
// BusMessageDelete 业务消息-删除(禁用状态可删)
// @Summary 业务消息-删除(禁用状态可删)
// @Tags 消息中心V1.5.0
// @Accept json
// @Produce json
// @Param request body models.BusMessageDeleteReq true "删除业务消息"
// @Success 200 {object} app.Response
// @Router /api/v1/bus_message/delete [post]
func BusMessageDelete(c *gin.Context) {
var req models.BusMessageDeleteReq
if err := c.ShouldBindJSON(&req); err != nil {
app.Error(c, http.StatusBadRequest, nil, "参数错误: "+err.Error())
return
}
var config models.SystemMessageConfig
if err := orm.Eloquent.Where("id = ? AND message_type = ?", req.ID, models.BusinessMessageType).
First(&config).Error; err != nil {
app.Error(c, http.StatusNotFound, nil, "业务消息不存在")
return
}
if config.Status != models.MessageStatusOnDisable {
app.Error(c, http.StatusBadRequest, nil, "仅禁用状态可删除")
return
}
begin := orm.Eloquent.Begin()
// 删除主配置(软删除)
if err := begin.Delete(&config).Error; err != nil {
begin.Rollback()
app.Error(c, http.StatusInternalServerError, nil, "删除公告失败")
return
}
// 删除接收对象配置
if err := begin.Where("message_config_id = ?", config.ID).
Delete(&models.SystemMessageTarget{}).Error; err != nil {
begin.Rollback()
app.Error(c, http.StatusInternalServerError, nil, "删除公告失败")
return
}
err := begin.Commit().Error
if err != nil {
begin.Rollback()
logger.Error("BusMessageDelete commit err:", logger.Field("err", err))
app.Error(c, http.StatusInternalServerError, nil, "删除公告失败")
return
}
app.OK(c, nil, "删除成功")
}
// BusMessageEdit 业务消息-编辑
// @Summary 业务消息-编辑
// @Tags 消息中心V1.5.0
// @Accept json
// @Produce json
// @Param request body models.BusMessageEditReq true "编辑业务消息"
// @Success 200 {object} app.Response
// @Router /api/v1/bus_message/edit [post]
func BusMessageEdit(c *gin.Context) {
var req models.BusMessageEditReq
if err := c.ShouldBindJSON(&req); err != nil {
app.Error(c, http.StatusBadRequest, nil, "参数错误: "+err.Error())
return
}
if req.ID == 0 {
app.Error(c, http.StatusBadRequest, nil, "缺少消息ID")
return
}
// 校验事件与模板字段是否合法
if err := models.ValidateBizEventAndTemplate(req.BizType, req.Event, req.ContentTemplate); err != nil {
app.Error(c, http.StatusBadRequest, nil, "模板校验失败: "+err.Error())
return
}
// 更新主记录
update := map[string]interface{}{
"title": req.Title,
"biz_type": req.BizType,
"event": req.Event,
"content_template": req.ContentTemplate,
"status": req.Status,
"updated_at": time.Now(),
}
if err := orm.Eloquent.Model(&models.SystemMessageConfig{}).
Where("id = ? AND message_type = ?", req.ID, models.BusinessMessageType).
Updates(update).Error; err != nil {
app.Error(c, http.StatusInternalServerError, nil, "更新失败: "+err.Error())
return
}
// 删除旧的接收对象记录
_ = orm.Eloquent.Where("message_config_id = ?", req.ID).
Delete(&models.SystemMessageTarget{})
// 重建角色接收对象target_type = 2
for _, roleID := range req.RoleID {
target := models.SystemMessageTarget{
MessageConfigID: uint(req.ID),
TargetType: models.TargetTypeByRole, // 角色
TargetID: roleID,
}
_ = orm.Eloquent.Create(&target).Error
}
app.OK(c, nil, "编辑成功")
}
// BusMessageDetail 业务消息-详情
// @Summary 业务消息-详情
// @Tags 消息中心V1.5.0
// @Accept json
// @Produce json
// @Param request body models.BusMessageDetailReq true "业务消息ID"
// @Success 200 {object} models.BusMessageItem
// @Router /api/v1/bus_message/detail [post]
func BusMessageDetail(c *gin.Context) {
var req models.BusMessageDetailReq
if err := c.ShouldBindJSON(&req); err != nil || req.ID == 0 {
app.Error(c, http.StatusBadRequest, nil, "参数错误缺少或非法ID")
return
}
// 查询主表
var cfg models.SystemMessageConfig
if err := orm.Eloquent.
Where("id = ? AND message_type = ?", req.ID, models.BusinessMessageType).
First(&cfg).Error; err != nil {
app.Error(c, http.StatusNotFound, nil, "未找到业务消息")
return
}
// 查询事件注册表,补充 BizName、EventName
var reg models.SystemEventRegistry
if err := orm.Eloquent.
Where("biz_type = ? AND event = ? AND is_enabled = ?", cfg.BizType, cfg.Event, true).
First(&reg).Error; err != nil {
// 可选:未找到事件名称也允许正常返回,只是字段为空
}
// 构建响应
item := models.BusMessageItem{
ID: cfg.ID,
CreatedAt: cfg.CreatedAt,
UpdatedAt: cfg.UpdatedAt,
Title: cfg.Title,
ContentTemplate: cfg.ContentTemplate,
BizType: cfg.BizType,
BizName: reg.BizName,
Event: cfg.Event,
EventName: reg.EventName,
Status: cfg.Status,
}
// 查询角色绑定
var targets []models.SystemMessageTarget
if err := orm.Eloquent.
Where("message_config_id = ? AND target_type = ?", cfg.ID, models.TargetTypeByRole).
Find(&targets).Error; err == nil {
for _, t := range targets {
item.RoleID = append(item.RoleID, t.TargetID)
}
}
app.OK(c, item, "查询成功")
}
// GetBizTypes 业务消息-查询业务类型
// @Summary 业务消息-查询业务类型
// @Tags 消息中心V1.5.0
// @Accept json
// @Produce json
// @Param request body models.BizTypeListReq true "分页请求"
// @Success 200 {object} models.BizTypeListResp
// @Router /api/v1/bus_message/biz_types [post]
func GetBizTypes(c *gin.Context) {
var req models.BizTypeListReq
if err := c.ShouldBindJSON(&req); err != nil {
app.Error(c, http.StatusBadRequest, nil, "参数错误: "+err.Error())
return
}
if req.Page <= 0 {
req.Page = 1
}
if req.PageSize <= 0 {
req.PageSize = 10
}
db := orm.Eloquent.Table("system_event_registry").
Select("biz_type, biz_name, MIN(created_at) as created_at, MAX(updated_at) as updated_at, MAX(is_enabled) as is_enabled").
Where("is_enabled = ?", true).
Group("biz_type, biz_name")
var total int64
err := orm.Eloquent.
Table("(?) as t", db).
Count(&total).Error
if err != nil {
app.Error(c, http.StatusInternalServerError, nil, "统计总数失败")
return
}
var list []models.BizTypeItem
err = orm.Eloquent.
Table("(?) as t", db).
Limit(req.PageSize).
Offset((req.Page - 1) * req.PageSize).
Scan(&list).Error
if err != nil {
app.Error(c, http.StatusInternalServerError, nil, "查询失败")
return
}
resp := models.BizTypeListResp{
List: list,
Total: total,
Page: req.Page,
PageSize: req.PageSize,
}
app.OK(c, resp, "查询成功")
}
// GetEventsByBizType 业务消息-查询事件类型
// @Summary 业务消息-查询事件类型
// @Tags 消息中心V1.5.0
// @Accept json
// @Produce json
// @Param request body models.EventListReq true "分页请求"
// @Success 200 {object} models.EventListResp
// @Router /api/v1/bus_message/events [post]
func GetEventsByBizType(c *gin.Context) {
var req models.EventListReq
if err := c.ShouldBindJSON(&req); err != nil || req.BizType == "" {
app.Error(c, http.StatusBadRequest, nil, "参数错误")
return
}
if req.Page <= 0 {
req.Page = 1
}
if req.PageSize <= 0 {
req.PageSize = 10
}
db := orm.Eloquent.Model(&models.SystemEventRegistry{}).
Where("biz_type = ? AND is_enabled = ?", req.BizType, true)
var total int64
if err := db.Count(&total).Error; err != nil {
app.Error(c, http.StatusInternalServerError, nil, "统计失败")
return
}
var list []models.EventItem
if err := db.Select("event, event_name, description, created_at, updated_at, is_enabled").
Order("created_at DESC").
Limit(req.PageSize).
Offset((req.Page - 1) * req.PageSize).
Scan(&list).Error; err != nil {
app.Error(c, http.StatusInternalServerError, nil, "查询失败")
return
}
resp := models.EventListResp{
List: list,
Total: total,
Page: req.Page,
PageSize: req.PageSize,
}
app.OK(c, resp, "查询成功")
}
// GetTemplateVariables 业务消息-查询模板变量
// @Summary 业务消息-查询模板变量
// @Tags 消息中心V1.5.0
// @Accept json
// @Produce json
// @Param request body models.TemplateVarReq true "模板变量请求参数"
// @Success 200 {object} models.TemplateVarListResp
// @Router /api/v1/bus_message/template_variables [post]
func GetTemplateVariables(c *gin.Context) {
var req models.TemplateVarReq
if err := c.ShouldBindJSON(&req); err != nil {
app.Error(c, http.StatusBadRequest, nil, "参数错误: "+err.Error())
return
}
// 设置默认分页参数
if req.Page <= 0 {
req.Page = 1
}
if req.PageSize <= 0 {
req.PageSize = 10
}
// 查询事件配置
var record models.SystemEventRegistry
err := orm.Eloquent.
Where("biz_type = ? AND event = ? AND is_enabled = ?", req.BizType, req.Event, true).
First(&record).Error
if err != nil {
app.Error(c, http.StatusNotFound, nil, "未找到对应模板配置")
return
}
// 解析模板变量
var allVars []models.TemplateVariable
if err := json.Unmarshal([]byte(record.TemplateVariables), &allVars); err != nil {
app.Error(c, http.StatusInternalServerError, nil, "模板变量解析失败")
return
}
// 分页切片
start := (req.Page - 1) * req.PageSize
end := start + req.PageSize
if start > len(allVars) {
start = len(allVars)
}
if end > len(allVars) {
end = len(allVars)
}
resp := models.TemplateVarListResp{
List: allVars[start:end],
Total: int64(len(allVars)),
Page: req.Page,
PageSize: req.PageSize,
}
app.OK(c, resp, "查询成功")
}