feat: add cronmessage sendNow
This commit is contained in:
@@ -161,3 +161,40 @@ func EditCronMsgTask(c *gin.Context) {
|
|||||||
cron_msg_service.UpdateCronMsgToCronServer(msg)
|
cron_msg_service.UpdateCronMsgToCronServer(msg)
|
||||||
appG.CResponse(http.StatusOK, "编辑定时消息成功!", nil)
|
appG.CResponse(http.StatusOK, "编辑定时消息成功!", nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type SendNowCronMsgReq struct {
|
||||||
|
TaskID string `json:"task_id" validate:"required,max=100,min=1" label:"关联的任务id"`
|
||||||
|
Title string `json:"title" validate:"required,max=100,min=1" label:"消息标题"`
|
||||||
|
Content string `json:"content" validate:"required,max=10000,min=1" label:"消息内容"`
|
||||||
|
Url string `json:"url" validate:"" label:"消息详情地址"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// SendNowCronMsg 立即发送定时消息
|
||||||
|
func SendNowCronMsg(c *gin.Context) {
|
||||||
|
var (
|
||||||
|
appG = app.Gin{C: c}
|
||||||
|
req SendNowCronMsgReq
|
||||||
|
)
|
||||||
|
|
||||||
|
errCode, errMsg := app.BindJsonAndPlayValid(c, &req)
|
||||||
|
if errCode != e.SUCCESS {
|
||||||
|
appG.CResponse(errCode, errMsg, nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
CronMsgService := cron_msg_service.CronMsgService{
|
||||||
|
TaskID: req.TaskID,
|
||||||
|
Title: req.Title,
|
||||||
|
Content: req.Content,
|
||||||
|
Url: req.Url,
|
||||||
|
}
|
||||||
|
|
||||||
|
// 调用立即发送服务
|
||||||
|
err := CronMsgService.SendNowByParams(c.ClientIP())
|
||||||
|
if err != nil {
|
||||||
|
appG.CResponse(http.StatusBadRequest, err.Error(), nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
appG.CResponse(http.StatusOK, "发送成功!", nil)
|
||||||
|
}
|
||||||
|
|||||||
@@ -93,6 +93,7 @@ func InitRouter(f embed.FS) *gin.Engine {
|
|||||||
apiV1.GET("/cronmessages/list", v1.GetCronMsgList)
|
apiV1.GET("/cronmessages/list", v1.GetCronMsgList)
|
||||||
apiV1.POST("/cronmessages/delete", v1.DeleteCronMsgTask)
|
apiV1.POST("/cronmessages/delete", v1.DeleteCronMsgTask)
|
||||||
apiV1.POST("/cronmessages/edit", v1.EditCronMsgTask)
|
apiV1.POST("/cronmessages/edit", v1.EditCronMsgTask)
|
||||||
|
apiV1.POST("/cronmessages/sendnow", v1.SendNowCronMsg)
|
||||||
|
|
||||||
// hostedMessage
|
// hostedMessage
|
||||||
apiV1.GET("/hostedmessages/list", v1.GetHostMessageList)
|
apiV1.GET("/hostedmessages/list", v1.GetHostMessageList)
|
||||||
|
|||||||
@@ -85,3 +85,29 @@ func GetCronNextTime(cronExpr string) string {
|
|||||||
nextTime := schedule.Next(time.Now()).Format("2006-01-02 15:04:05")
|
nextTime := schedule.Next(time.Now()).Format("2006-01-02 15:04:05")
|
||||||
return nextTime
|
return nextTime
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SendNow 立即发送定时消息(根据定时消息ID)
|
||||||
|
func (st *CronMsgService) SendNow(callerIP string) error {
|
||||||
|
// 获取定时消息详情
|
||||||
|
msg, err := st.GetByID()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 调用发送服务
|
||||||
|
return SendCronMessage(msg, callerIP)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SendNowByParams 立即发送定时消息(根据传入的参数)
|
||||||
|
func (st *CronMsgService) SendNowByParams(callerIP string) error {
|
||||||
|
// 直接使用传入的参数构造消息对象
|
||||||
|
msg := models.CronMessages{
|
||||||
|
TaskID: st.TaskID,
|
||||||
|
Title: st.Title,
|
||||||
|
Content: st.Content,
|
||||||
|
Url: st.Url,
|
||||||
|
}
|
||||||
|
|
||||||
|
// 调用发送服务
|
||||||
|
return SendCronMessage(msg, callerIP)
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package cron_msg_service
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
"message-nest/models"
|
"message-nest/models"
|
||||||
"message-nest/pkg/constant"
|
"message-nest/pkg/constant"
|
||||||
@@ -106,3 +107,44 @@ func RemoveCronMsgToCronServer(msg models.CronMessages) {
|
|||||||
func StartUpMsgCronTask() {
|
func StartUpMsgCronTask() {
|
||||||
MsgCronTask{}.Register()
|
MsgCronTask{}.Register()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SendCronMessage 发送定时消息(用于立即发送)
|
||||||
|
func SendCronMessage(msg models.CronMessages, callerIP string) error {
|
||||||
|
// 查询关联的发信任务
|
||||||
|
task, err := models.GetTaskByID(msg.TaskID)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("发信任务不存在: %s", msg.TaskID)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建发送服务
|
||||||
|
sender := send_message_service.SendMessageService{
|
||||||
|
TaskID: task.ID,
|
||||||
|
Title: msg.Title,
|
||||||
|
Text: msg.Content,
|
||||||
|
URL: msg.Url,
|
||||||
|
CallerIp: callerIP,
|
||||||
|
DefaultLogger: logrus.WithFields(logrus.Fields{
|
||||||
|
"prefix": "[Manual Send Cron Message]",
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
|
||||||
|
// 预检查
|
||||||
|
taskData, err := sender.SendPreCheck()
|
||||||
|
if err != nil {
|
||||||
|
errMsg := err.Error()
|
||||||
|
// 如果是没有关联实例的错误,返回更友好的提示
|
||||||
|
if strings.Contains(errMsg, "没有关联任何实例") {
|
||||||
|
return fmt.Errorf("该发信任务尚未配置发送实例,请先在【发信任务】页面为任务 [%s] 添加至少一个发送实例", task.Name)
|
||||||
|
}
|
||||||
|
return fmt.Errorf("发送预检查失败: %s", errMsg)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 发送消息
|
||||||
|
_, err = sender.Send(taskData)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("发送失败: %s", err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
logrus.Infof("立即发送定时消息成功,消息id: %s,消息名: %s", msg.ID, msg.Name)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -69,6 +69,44 @@ const handleCancel = () => {
|
|||||||
emit('cancel')
|
emit('cancel')
|
||||||
emit('update:open', false)
|
emit('update:open', false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 立即发送(新增模式也支持,可以在创建前测试发送效果)
|
||||||
|
const handleSendNow = async () => {
|
||||||
|
// 验证必填字段
|
||||||
|
if (!formData.task_id) {
|
||||||
|
toast.error('请先选择关联的发信任务')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!formData.title) {
|
||||||
|
toast.error('请先填写消息标题')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!formData.content) {
|
||||||
|
toast.error('请先填写消息内容')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
loading.value = true
|
||||||
|
try {
|
||||||
|
const postData = {
|
||||||
|
task_id: formData.task_id,
|
||||||
|
title: formData.title,
|
||||||
|
content: formData.content,
|
||||||
|
url: formData.url
|
||||||
|
}
|
||||||
|
|
||||||
|
const rsp = await request.post('/cronmessages/sendnow', postData)
|
||||||
|
if (rsp.data.code === 200) {
|
||||||
|
toast.success(rsp.data.msg)
|
||||||
|
} else {
|
||||||
|
toast.error(rsp.data.msg)
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
toast.error('发送失败,请稍后重试')
|
||||||
|
} finally {
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -82,6 +120,7 @@ const handleCancel = () => {
|
|||||||
:loading="loading"
|
:loading="loading"
|
||||||
@submit="handleSubmit"
|
@submit="handleSubmit"
|
||||||
@cancel="handleCancel"
|
@cancel="handleCancel"
|
||||||
|
@send-now="handleSendNow"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import { Textarea } from '@/components/ui/textarea'
|
|||||||
import { request } from '@/api/api'
|
import { request } from '@/api/api'
|
||||||
|
|
||||||
interface CronMessageFormData {
|
interface CronMessageFormData {
|
||||||
id?: number
|
id?: string
|
||||||
name: string
|
name: string
|
||||||
cron_expression: string
|
cron_expression: string
|
||||||
title: string
|
title: string
|
||||||
@@ -27,6 +27,7 @@ interface Emits {
|
|||||||
(e: 'update:modelValue', value: CronMessageFormData): void
|
(e: 'update:modelValue', value: CronMessageFormData): void
|
||||||
(e: 'submit'): void
|
(e: 'submit'): void
|
||||||
(e: 'cancel'): void
|
(e: 'cancel'): void
|
||||||
|
(e: 'sendNow'): void
|
||||||
}
|
}
|
||||||
|
|
||||||
const props = withDefaults(defineProps<Props>(), {
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
@@ -92,6 +93,11 @@ const handleCancel = () => {
|
|||||||
emit('cancel')
|
emit('cancel')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 立即发送
|
||||||
|
const handleSendNow = () => {
|
||||||
|
emit('sendNow')
|
||||||
|
}
|
||||||
|
|
||||||
// 组件挂载时加载数据
|
// 组件挂载时加载数据
|
||||||
loadAvailableTasks()
|
loadAvailableTasks()
|
||||||
</script>
|
</script>
|
||||||
@@ -117,6 +123,9 @@ loadAvailableTasks()
|
|||||||
</SelectGroup>
|
</SelectGroup>
|
||||||
</SelectContent>
|
</SelectContent>
|
||||||
</Select>
|
</Select>
|
||||||
|
<p class="text-xs text-gray-500">
|
||||||
|
⚠️ 请确保所选任务已配置至少一个发送实例,否则无法发送
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="space-y-1">
|
<div class="space-y-1">
|
||||||
@@ -152,6 +161,9 @@ loadAvailableTasks()
|
|||||||
<Button variant="outline" @click="handleCancel" size="sm" :disabled="loading">
|
<Button variant="outline" @click="handleCancel" size="sm" :disabled="loading">
|
||||||
取消
|
取消
|
||||||
</Button>
|
</Button>
|
||||||
|
<Button variant="secondary" @click="handleSendNow" size="sm" :disabled="loading">
|
||||||
|
立即发送
|
||||||
|
</Button>
|
||||||
<Button @click="handleSubmit" size="sm" :disabled="loading">
|
<Button @click="handleSubmit" size="sm" :disabled="loading">
|
||||||
{{ mode === 'add' ? '创建定时消息' : '更新定时消息' }}
|
{{ mode === 'add' ? '创建定时消息' : '更新定时消息' }}
|
||||||
</Button>
|
</Button>
|
||||||
|
|||||||
@@ -89,6 +89,44 @@ const handleCancel = () => {
|
|||||||
emit('update:open', false)
|
emit('update:open', false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 立即发送
|
||||||
|
const handleSendNow = async () => {
|
||||||
|
// 验证必填字段
|
||||||
|
if (!formData.task_id) {
|
||||||
|
toast.error('请先选择关联的发信任务')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!formData.title) {
|
||||||
|
toast.error('请先填写消息标题')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!formData.content) {
|
||||||
|
toast.error('请先填写消息内容')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
loading.value = true
|
||||||
|
try {
|
||||||
|
const postData = {
|
||||||
|
task_id: formData.task_id,
|
||||||
|
title: formData.title,
|
||||||
|
content: formData.content,
|
||||||
|
url: formData.url
|
||||||
|
}
|
||||||
|
|
||||||
|
const rsp = await request.post('/cronmessages/sendnow', postData)
|
||||||
|
if (rsp.data.code === 200) {
|
||||||
|
toast.success(rsp.data.msg)
|
||||||
|
} else {
|
||||||
|
toast.error(rsp.data.msg)
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
toast.error('发送失败,请稍后重试')
|
||||||
|
} finally {
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 监听 cronMessage 变化,更新表单数据
|
// 监听 cronMessage 变化,更新表单数据
|
||||||
watch(
|
watch(
|
||||||
() => props.cronMessage,
|
() => props.cronMessage,
|
||||||
@@ -114,6 +152,7 @@ watch(
|
|||||||
:loading="loading"
|
:loading="loading"
|
||||||
@submit="handleSubmit"
|
@submit="handleSubmit"
|
||||||
@cancel="handleCancel"
|
@cancel="handleCancel"
|
||||||
|
@send-now="handleSendNow"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user