feat: add message template

This commit is contained in:
engigu
2025-12-06 00:28:18 +08:00
parent ff194daef2
commit a511512793
21 changed files with 2608 additions and 155 deletions
+149
View File
@@ -0,0 +1,149 @@
package models
import (
"fmt"
"message-nest/pkg/util"
)
// GenerateTemplateUniqueID 生成模板唯一ID
func GenerateTemplateUniqueID() string {
newUUID := util.GenerateUniqueID()
return fmt.Sprintf("TP%s", newUUID)
}
// MessageTemplate 消息模板
type MessageTemplate struct {
UUIDModel
Name string `json:"name" gorm:"type:varchar(200);not null;index" binding:"required"`
Description string `json:"description" gorm:"type:text"`
// 模板内容(带占位符)
TextTemplate string `json:"text_template" gorm:"type:text"`
HTMLTemplate string `json:"html_template" gorm:"type:text"`
MarkdownTemplate string `json:"markdown_template" gorm:"type:text"`
// 占位符定义(JSON格式)
Placeholders string `json:"placeholders" gorm:"type:text"`
// @提醒配置
AtMobiles string `json:"at_mobiles" gorm:"type:text;comment:'@手机号列表,逗号分隔'"`
AtUserIds string `json:"at_user_ids" gorm:"type:text;comment:'@用户ID列表,逗号分隔'"`
IsAtAll bool `json:"is_at_all" gorm:"default:false;comment:'是否@所有人'"`
// 状态:enabled/disabled
Status string `json:"status" gorm:"type:varchar(20);default:'enabled';index"`
}
// Add 添加消息模板
func (t *MessageTemplate) Add() error {
if err := db.Create(&t).Error; err != nil {
return err
}
return nil
}
// Update 更新消息模板
func (t *MessageTemplate) Update() error {
if err := db.Model(&MessageTemplate{}).Where("id = ?", t.ID).Updates(t).Error; err != nil {
return err
}
return nil
}
// Delete 删除消息模板
func (t *MessageTemplate) Delete() error {
if err := db.Where("id = ?", t.ID).Delete(&MessageTemplate{}).Error; err != nil {
return err
}
return nil
}
// MessageTemplateResult 消息模板查询结果
type MessageTemplateResult struct {
ID string `json:"id"`
Name string `json:"name"`
Description string `json:"description"`
TextTemplate string `json:"text_template"`
HTMLTemplate string `json:"html_template"`
MarkdownTemplate string `json:"markdown_template"`
Placeholders string `json:"placeholders"`
AtMobiles string `json:"at_mobiles"`
AtUserIds string `json:"at_user_ids"`
IsAtAll bool `json:"is_at_all"`
Status string `json:"status"`
CreatedBy string `json:"created_by"`
ModifiedBy string `json:"modified_by"`
CreatedOn util.Time `json:"created_on"`
ModifiedOn util.Time `json:"modified_on"`
}
// GetMessageTemplates 获取消息模板列表
func GetMessageTemplates(pageNum int, pageSize int, text string, maps map[string]interface{}) ([]MessageTemplateResult, error) {
var datas []MessageTemplateResult
templateT := GetSchema(MessageTemplate{})
query := db.Table(templateT)
query = query.Where(maps)
if text != "" {
query = query.Where("name LIKE ? OR description LIKE ?",
fmt.Sprintf("%%%s%%", text),
fmt.Sprintf("%%%s%%", text))
}
query = query.Order("created_on DESC")
if pageSize > 0 || pageNum > 0 {
query = query.Offset(pageNum).Limit(pageSize)
}
query.Scan(&datas)
return datas, nil
}
// GetMessageTemplatesTotal 获取消息模板总数
func GetMessageTemplatesTotal(text string, maps map[string]interface{}) (int64, error) {
var total int64
templateT := GetSchema(MessageTemplate{})
query := db.Table(templateT)
query = query.Where(maps)
if text != "" {
query = query.Where("name LIKE ? OR description LIKE ?",
fmt.Sprintf("%%%s%%", text),
fmt.Sprintf("%%%s%%", text))
}
query.Count(&total)
return total, nil
}
// GetMessageTemplateByID 根据ID获取消息模板
func GetMessageTemplateByID(id string) (*MessageTemplateResult, error) {
var data MessageTemplateResult
templateT := GetSchema(MessageTemplate{})
err := db.Table(templateT).Where("id = ?", id).First(&data).Error
if err != nil {
return nil, err
}
return &data, nil
}
// ExistMessageTemplateByID 检查模板是否存在
func ExistMessageTemplateByID(id string) (bool, error) {
var template MessageTemplate
err := db.Select("id").Where("id = ?", id).First(&template).Error
if err != nil {
return false, err
}
if template.ID != "" {
return true, nil
}
return false, nil
}
+23
View File
@@ -1,9 +1,12 @@
package models
import "fmt"
type SendTasksIns struct {
UUIDModel
TaskID string `json:"task_id" gorm:"type:varchar(12) ;default:'';index"`
TemplateID string `json:"template_id" gorm:"type:varchar(12) ;default:'';index"` // 模板ID
WayID string `json:"way_id" gorm:"type:varchar(12) ;default:'';index"`
WayType string `json:"way_type" gorm:"type:varchar(100) ;default:'';index"`
ContentType string `json:"content_type" gorm:"type:varchar(100) ;default:'';index"`
@@ -82,3 +85,23 @@ func UpdateMsgTaskIns(id string, data map[string]interface{}) error {
}
return nil
}
// GetTemplateInsList 获取模板关联的实例列表(包含渠道名称)
func GetTemplateInsList(templateID string) ([]SendTasksInsRes, error) {
insTable := GetSchema(SendTasksIns{})
waysTable := GetSchema(SendWays{})
var insList []SendTasksInsRes
err := db.
Table(insTable).
Select(fmt.Sprintf("%s.*, %s.name as way_name", insTable, waysTable)).
Joins(fmt.Sprintf("JOIN %s ON %s.way_id = %s.id", waysTable, insTable, waysTable)).
Where(fmt.Sprintf("%s.template_id = ?", insTable), templateID).
Order(fmt.Sprintf("%s.created_on DESC", insTable)).
Scan(&insList).Error
if err != nil {
return nil, err
}
return insList, nil
}
+69 -12
View File
@@ -9,6 +9,8 @@ import (
type SendTasksLogs struct {
ID int `gorm:"primaryKey" json:"id" `
TaskID string `json:"task_id" gorm:"type:varchar(12) ;default:'';index:task_id"`
Type string `json:"type" gorm:"type:varchar(20) ;default:'task';comment:'类型:task-任务,template-模板'"`
Name string `json:"name" gorm:"type:varchar(256) ;default:'';comment:'任务或模板名称'"`
Log string `json:"log" gorm:"type:text ;"`
Status *int `json:"status" gorm:"type:int ;default:0;"`
CallerIp string `json:"caller_ip" gorm:"type:varchar(256) ;default:'';"`
@@ -29,10 +31,11 @@ func (log *SendTasksLogs) Add() error {
type LogsResult struct {
ID int `json:"id"`
TaskID string `json:"task_id"`
Type string `json:"type"`
Name string `json:"name"`
Log string `json:"log"`
CreatedOn util.Time `json:"created_on"`
ModifiedOn util.Time `json:"modified_on"`
TaskName string `json:"task_name"`
Status int `json:"status"`
CallerIp string `json:"caller_ip"`
}
@@ -41,12 +44,9 @@ type LogsResult struct {
func GetSendLogs(pageNum int, pageSize int, name string, taskId string, maps map[string]interface{}) ([]LogsResult, error) {
var logs []LogsResult
logt := GetSchema(SendTasksLogs{})
taskt := GetSchema(SendTasks{})
query := db.
Table(logt).
Select(fmt.Sprintf("%s.*, %s.name as task_name", logt, taskt)).
Joins(fmt.Sprintf("LEFT JOIN %s ON %s.task_id = %s.id", taskt, logt, taskt))
// 简化查询,只查询日志表
query := db.Table(logt)
dayVal, ok := maps["day_created_on"]
if ok {
@@ -55,8 +55,10 @@ func GetSendLogs(pageNum int, pageSize int, name string, taskId string, maps map
}
query = query.Where(maps)
// 按名称搜索(搜索日志表的 name 字段)
if name != "" {
query = query.Where(fmt.Sprintf("%s.name like ?", taskt), fmt.Sprintf("%%%s%%", name))
query = query.Where(fmt.Sprintf("%s.name like ?", logt), fmt.Sprintf("%%%s%%", name))
}
if taskId != "" {
query = query.Where(fmt.Sprintf("%s.task_id = ?", logt), taskId)
@@ -66,18 +68,71 @@ func GetSendLogs(pageNum int, pageSize int, name string, taskId string, maps map
query = query.Offset(pageNum).Limit(pageSize)
}
query.Scan(&logs)
//v1 接口的历史日志数据兼容处理
// 应用层处理:为历史数据(type=task 且 name 为空)补充任务名称
fillTaskNamesForLogs(&logs)
return logs, nil
}
// fillTaskNamesForLogs 为历史日志数据补充任务名称
func fillTaskNamesForLogs(logs *[]LogsResult) {
if logs == nil || len(*logs) == 0 {
return
}
// 收集需要查询的 task_id
taskIdsMap := make(map[string]bool)
for _, log := range *logs {
// 只处理 type=task 且 name 为空的记录
if (log.Type == "" || log.Type == "task") && log.Name == "" && log.TaskID != "" {
taskIdsMap[log.TaskID] = true
}
}
// 如果没有需要查询的任务,直接返回
if len(taskIdsMap) == 0 {
return
}
// 批量查询任务名称
taskIds := make([]string, 0, len(taskIdsMap))
for taskId := range taskIdsMap {
taskIds = append(taskIds, taskId)
}
var tasks []SendTasks
taskt := GetSchema(SendTasks{})
db.Table(taskt).
Select("id, name").
Where("id IN ?", taskIds).
Scan(&tasks)
// 构建 taskId -> name 的映射
taskNameMap := make(map[string]string)
for _, task := range tasks {
taskNameMap[task.ID] = task.Name
}
// 填充日志的 name 字段
for i := range *logs {
log := &(*logs)[i]
if (log.Type == "" || log.Type == "task") && log.Name == "" && log.TaskID != "" {
if taskName, exists := taskNameMap[log.TaskID]; exists {
log.Name = taskName
}
}
}
}
// GetSendLogsTotal 获取所有日志总数
func GetSendLogsTotal(name string, taskId string, maps map[string]interface{}) (int64, error) {
var total int64
logt := GetSchema(SendTasksLogs{})
taskt := GetSchema(SendTasks{})
query := db.
Table(logt).
Joins(fmt.Sprintf("LEFT JOIN %s ON %s.task_id = %s.id", taskt, logt, taskt))
// 简化查询,只查询日志表
query := db.Table(logt)
dayVal, ok := maps["day_created_on"]
if ok {
@@ -86,8 +141,10 @@ func GetSendLogsTotal(name string, taskId string, maps map[string]interface{}) (
}
query = query.Where(maps)
// 按名称搜索(搜索日志表的 name 字段)
if name != "" {
query = query.Where(fmt.Sprintf("%s.name like ?", taskt), fmt.Sprintf("%%%s%%", name))
query = query.Where(fmt.Sprintf("%s.name like ?", logt), fmt.Sprintf("%%%s%%", name))
}
if taskId != "" {
query = query.Where(fmt.Sprintf("%s.task_id = ?", logt), taskId)