mh_goadmin_server/app/admin/models/message.go
chenlin 70b823b413 1、优化零售明细相关支付金额不能为负值的缺陷,根据实际情况展示;
2、优化门店销售对比,时间改成审核时间;避免跨月订单统计不准确;
3、新增业务消息相关接口;
2025-07-01 11:54:23 +08:00

299 lines
14 KiB
Go
Raw 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 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
}