mh_goadmin_server/app/admin/models/message.go

299 lines
14 KiB
Go
Raw Normal View History

package models
import (
"encoding/json"
"errors"
"fmt"
orm "go-admin/common/global"
"regexp"
"time"
)
const (
AnnouncementMessageType = 1 // 公告消息
BusinessMessageType = 2 // 业务消息
TargetTypeByAll = 1 // 接收对象类型1=全员
TargetTypeByRole = 2 // 接收对象类型2=角色
TargetTypeByUser = 3 // 接收对象类型3=用户
MessageStatusOnDraft = 0 // 草稿
MessageStatusOnStart = 1 // 启用
MessageStatusOnDisable = 2 // 禁用
MessageStatusOnExpire = 3 // 已过期
MessageStart = 1 // 启用
MessageStop = 2 // 禁用
)
// SystemMessageConfig 消息配置主表(公告 + 业务统一)
type SystemMessageConfig struct {
Model
MessageType uint8 `json:"message_type"` // 消息类型1=公告2=业务
Title string `json:"title"` // 消息标题
ContentTemplate string `json:"content_template"` // 消息模板内容,支持{{变量}}
Level uint8 `json:"level"` // 消息等级1=普通2=重要3=紧急
DisplayMode uint8 `json:"display_mode"` // 展示方式1=弹窗2=滚动3=弹窗+滚动
StartTime *time.Time `json:"start_time,omitempty"` // 公告生效时间
EndTime *time.Time `json:"end_time,omitempty"` // 公告失效时间
BizType string `json:"biz_type,omitempty"` // 业务类型
Event string `json:"event,omitempty"` // 事件类型
Status uint8 `json:"status"` // 状态0=草稿1=启用2=禁用3=已过期
}
// SystemMessageTarget 接收对象配置表(支持角色/部门/用户/全员)
type SystemMessageTarget struct {
Model
MessageConfigID uint `json:"message_config_id"` // 对应消息配置 ID
TargetType uint8 `json:"target_type"` // 接收对象类型1=全员2=角色3=用户
TargetID int64 `json:"target_id,omitempty"` // 对象ID角色ID/用户ID
}
// SystemEventRegistry 业务事件注册表(用于事件枚举管理)
type SystemEventRegistry struct {
Model
BizType string `json:"biz_type"` // 业务类型
Event string `json:"event"` // 事件名
BizName string `json:"biz_name"` // 业务名称(展示用)
EventName string `json:"event_name"` // 事件名称(展示用)
Description string `json:"description"` // 说明
TemplateVariables string `json:"template_variables"` // 可用变量 JSON 字符串
IsEnabled bool `json:"is_enabled"` // 是否启用
}
type TemplateVarItem struct {
Key string `json:"key"`
Desc string `json:"desc"`
}
// SystemUserMessage 用户收到的消息记录表(实际发送记录)
type SystemUserMessage struct {
Model
UserID int64 `json:"user_id"` // 接收用户ID
MessageConfigID uint `json:"message_config_id"` // 对应消息配置ID可为空被删时保留记录
MessageType uint8 `json:"message_type"` // 消息类型1=公告2=业务
Title string `json:"title"` // 消息标题快照
Content string `json:"content"` // 渲染后内容
IsRead bool `json:"is_read"` // 是否阅读
ReadTime *time.Time `json:"read_time,omitempty"` // 阅读时间
IsVisible bool `json:"is_visible"` // 是否展示给用户
}
// SysMessageCreateReq 新增公告请求结构体
type SysMessageCreateReq struct {
Title string `json:"title" binding:"required"` // 消息标题
ContentTemplate string `json:"content_template" binding:"required"` // 消息内容
Level uint8 `json:"level" binding:"required,oneof=1 2 3"` // 消息等级1=普通2=重要3=紧急
DisplayMode uint8 `json:"display_mode" binding:"required,oneof=1 2 3"` // 展示方式1=弹窗2=滚动3=弹窗+滚动
StartTime string `json:"start_time,omitempty"` // 公告生效时间
EndTime string `json:"end_time,omitempty"` // 公告失效时间
Status uint8 `json:"status"` // 状态0=草稿1=启用
TargetType uint8 `json:"target_type" binding:"required,oneof=1 2 3"` // 接收对象类型1=全员2=角色3=用户
TargetIDs []int64 `json:"target_id,omitempty"` // 对象ID角色ID/用户ID
}
// SysMessageCreateResp 创建成功响应
type SysMessageCreateResp struct {
ID uint32 `json:"id"`
}
// SysMessageEditReq 编辑公告消息-入参
type SysMessageEditReq struct {
ID uint `json:"id" binding:"required"` // 公告ID必须
Title string `json:"title" binding:"required"` // 标题
ContentTemplate string `json:"content_template" binding:"required"` // 内容模板
Level uint8 `json:"level" binding:"required,oneof=1 2 3"` // 重要等级
DisplayMode uint8 `json:"display_mode" binding:"required,oneof=1 2 3"` // 展示模式
StartTime string `json:"start_time"` // 生效时间(可空)
EndTime string `json:"end_time"` // 失效时间(可空)
Status uint8 `json:"status"` // 状态0 草稿、1 启用
TargetType uint8 `json:"target_type" binding:"required,oneof=1 2 3"` // 接收对象类型1=全员2=角色3=用户
TargetID int64 `json:"target_id,omitempty"` // 接收对象ID
}
// SysMessageListReq 公告消息列表-入参
type SysMessageListReq struct {
Title string `form:"title"` // 消息标题
Level uint8 `form:"level"` // 消息等级1=普通2=重要3=紧急
DisplayMode uint8 `form:"display_mode"` // 展示方式1=弹窗2=滚动3=弹窗+滚动
Status uint8 `form:"status"` // 状态0=草稿1=启用2=禁用3=已过期
TargetType uint8 `form:"target_type"` // 从接收对象配置表中筛选
Page int `form:"page,default=1"` // 页码
PageSize int `form:"page_size,default=10"` // 每页条数
}
// SysMessageListResp 公告消息列表-出参
type SysMessageListResp struct {
List []SysAnnouncementItem `json:"list"`
Total int64 `json:"total"` // 总条数
Page int `json:"page"` // 页码
PageSize int `json:"page_size"` // 每页条数
}
// SysAnnouncementItem 公告消息展示结构体
type SysAnnouncementItem struct {
ID uint32 `json:"id"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
Title string `json:"title"` // 消息标题
ContentTemplate string `json:"content_template"` // 消息内容
Level uint8 `json:"level"` // 消息等级1=普通2=重要3=紧急
DisplayMode uint8 `json:"display_mode"` // 展示方式1=弹窗2=滚动3=弹窗+滚动
StartTime *time.Time `json:"start_time,omitempty"` // 公告生效时间
EndTime *time.Time `json:"end_time,omitempty"` // 公告失效时间
Status uint8 `json:"status"` // 状态0=草稿1=启用2=禁用3=已过期
TargetType uint8 `json:"target_type"` // 接收对象类型1=全员2=角色3=用户
TargetID []int64 `json:"target_id,omitempty"` // 对象ID角色ID/用户ID
}
// SysMessageSetStatusReq 设置公告消息状态
type SysMessageSetStatusReq struct {
ID uint `json:"id" binding:"required"`
Status uint8 `json:"status" binding:"required"` // 目标状态1=启用2=禁用
}
// SysMessageDeleteReq 删除公告消息
type SysMessageDeleteReq struct {
ID uint `json:"id" binding:"required"`
}
// SysMessageDetailReq 公告详情请求
type SysMessageDetailReq struct {
ID uint `json:"id" binding:"required"`
}
// SysMessageDetailResp 公告详情响应
type SysMessageDetailResp struct {
ID uint `json:"id"`
Title string `json:"title"`
Content string `json:"content"`
Level uint8 `json:"level"`
DisplayMode uint8 `json:"display_mode"`
Status uint8 `json:"status"`
StartTime *time.Time `json:"start_time,omitempty"` // 公告生效时间
EndTime *time.Time `json:"end_time,omitempty"` // 公告失效时间
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
Target *SystemMessageTarget `json:"target,omitempty"` // 接收对象信息
}
// UserMessageListReq 用户消息列表-入参
type UserMessageListReq struct {
IsRead int `json:"is_read"` // 0-全部1-已读2-未读
Page int `json:"page"` // 页码
PageSize int `json:"page_size"` // 每页数量
}
// UserMessageListResp 用户消息列表-出参
type UserMessageListResp struct {
List []UserMessageDetailRespItem `json:"list"`
Total int64 `json:"total"`
Page int `json:"page"`
PageSize int `json:"page_size"`
}
type UserMessageDetailRespItem struct {
ID uint `json:"id"`
UserID int64 `json:"user_id"` // 接收用户ID
MessageConfigID uint `json:"message_config_id"` // 对应消息配置ID可为空被删时保留记录
MessageType uint8 `json:"message_type"` // 消息类型1=公告2=业务
Title string `json:"title"` // 消息标题快照
Content string `json:"content"` // 渲染后内容
IsRead bool `json:"is_read"` // 是否阅读
ReadTime *time.Time `json:"read_time,omitempty"` // 阅读时间
IsVisible bool `json:"is_visible"` // 是否展示给用户
Level uint8 `json:"level,omitempty"` // 公告消息字段消息等级1=普通2=重要3=紧急
DisplayMode uint8 `json:"display_mode,omitempty"` // 公告消息字段展示方式1=弹窗2=滚动3=弹窗+滚动
StartTime *time.Time `json:"start_time,omitempty"` // 公告消息字段,公告生效时间
EndTime *time.Time `json:"end_time,omitempty"` // 公告消息字段,公告失效时间
}
// UserMessageSetStatusReq 用户阅读消息-入参
type UserMessageSetStatusReq struct {
ID uint `json:"id"` // 消息ID可选read_all 为 false 时必传)
ReadAll bool `json:"read_all"` // 是否设为全部已读
}
// BusMessageCreateReq 新增业务消息-入参
type BusMessageCreateReq struct {
Title string `json:"title" binding:"required"` // 消息标题
ContentTemplate string `json:"content_template" binding:"required"` // 消息模板
BizType string `json:"biz_type" binding:"required"` // 业务类型
Event string `json:"event" binding:"required"` // 事件类型
TargetType uint8 `json:"target_type" binding:"required"` // 接收对象类型1全员2角色3用户
TargetID int64 `json:"target_id,omitempty"` // 接收对象ID角色ID或用户ID
Status uint8 `json:"status" binding:"required"` // 消息状态0草稿1启用2禁用
}
// BusMessageCreateResp 新增业务消息-出参
type BusMessageCreateResp struct {
ID uint `json:"id"`
}
// BusMessageListReq 业务消息列表 - 入参
type BusMessageListReq struct {
BizType string `json:"biz_type"` // 业务类型
Event string `json:"event"` // 事件类型
Status uint8 `json:"status"` // 状态1启用2禁用
RoleID []int64 `json:"role_id"` // 角色ID
Page int `json:"page"` // 页码
PageSize int `json:"page_size"` // 每页条数
}
// BusMessageListResp 业务消息列表 - 出参
type BusMessageListResp struct {
List []BusMessageItem `json:"list"`
Total int64 `json:"total"`
Page int `json:"page"`
PageSize int `json:"page_size"`
}
// BusMessageItem 单条业务消息展示项
type BusMessageItem struct {
ID uint32 `json:"id"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
ContentTemplate string `json:"content_template"` // 消息模版
BizType string `json:"biz_type"` // 业务类型
Event string `json:"event"` // 事件类型
Status uint8 `json:"status"` // 状态1启用2禁用
RoleID []int64 `json:"role_id"` // 角色ID
}
// ValidateBizEventAndTemplate 校验业务类型、事件类型以及模板变量是否合法
func ValidateBizEventAndTemplate(bizType, event, contentTemplate string) error {
var registry SystemEventRegistry
err := orm.Eloquent.Where("biz_type = ? AND event = ? AND is_enabled = ?", bizType, event, true).First(&registry).Error
if err != nil {
return errors.New("业务类型或事件类型无效")
}
// 支持结构体数组格式:[{"key":"user_name","desc":"用户名"}]
var allowedItems []TemplateVarItem
if err := json.Unmarshal([]byte(registry.TemplateVariables), &allowedItems); err != nil {
return errors.New("事件注册表中变量格式非法")
}
// 提取合法 key
allowedMap := make(map[string]bool)
for _, item := range allowedItems {
allowedMap[item.Key] = true
}
// 提取模板中的变量名
varRegex := regexp.MustCompile(`\{\{\s*(\w+)\s*\}\}`)
matches := varRegex.FindAllStringSubmatch(contentTemplate, -1)
for _, match := range matches {
varName := match[1]
if !allowedMap[varName] {
return fmt.Errorf("模板中使用了未注册变量:%s", varName)
}
}
return nil
}