feat: support dingtalk push
This commit is contained in:
@@ -3,6 +3,7 @@ module message-nest
|
||||
go 1.20
|
||||
|
||||
require (
|
||||
github.com/blinkbean/dingtalk v0.0.0-20230927120905-796332ac4ba1
|
||||
github.com/dgrijalva/jwt-go v3.1.0+incompatible
|
||||
github.com/gin-gonic/gin v1.9.1
|
||||
github.com/go-ini/ini v1.32.1-0.20180214101753-32e4be5f41bb
|
||||
@@ -11,7 +12,6 @@ require (
|
||||
github.com/go-playground/validator/v10 v10.16.0
|
||||
github.com/google/uuid v1.5.0
|
||||
github.com/jinzhu/gorm v0.0.0-20180213101209-6e1387b44c64
|
||||
github.com/markbates/pkger v0.17.1
|
||||
github.com/robfig/cron/v3 v3.0.1
|
||||
github.com/sirupsen/logrus v1.9.3
|
||||
github.com/unknwon/com v1.0.1
|
||||
@@ -19,7 +19,6 @@ require (
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/blinkbean/dingtalk v0.0.0-20230927120905-796332ac4ba1 // indirect
|
||||
github.com/bytedance/sonic v1.10.2 // indirect
|
||||
github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d // indirect
|
||||
github.com/chenzhuoyu/iasm v0.9.1 // indirect
|
||||
@@ -28,12 +27,12 @@ require (
|
||||
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
|
||||
github.com/gin-contrib/sse v0.1.0 // indirect
|
||||
github.com/go-sql-driver/mysql v1.4.1-0.20190510102335-877a9775f068 // indirect
|
||||
github.com/gobuffalo/here v0.6.0 // indirect
|
||||
github.com/goccy/go-json v0.10.2 // indirect
|
||||
github.com/jinzhu/inflection v0.0.0-20170102125226-1c35d901db3d // indirect
|
||||
github.com/jinzhu/now v1.0.1 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.6 // indirect
|
||||
github.com/kr/pretty v0.1.0 // indirect
|
||||
github.com/leodido/go-urn v1.2.4 // indirect
|
||||
github.com/lib/pq v1.2.0 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
@@ -52,6 +51,7 @@ require (
|
||||
google.golang.org/appengine v1.6.3 // indirect
|
||||
google.golang.org/protobuf v1.32.0 // indirect
|
||||
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect
|
||||
gopkg.in/ini.v1 v1.47.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
||||
@@ -37,8 +37,6 @@ github.com/go-playground/validator/v10 v10.16.0 h1:x+plE831WK4vaKHO/jpgUGsvLKIqR
|
||||
github.com/go-playground/validator/v10 v10.16.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU=
|
||||
github.com/go-sql-driver/mysql v1.4.1-0.20190510102335-877a9775f068 h1:q2kwd9Bcgl2QpSi/Wjcx9jzwyICt3EWTP5to43QhwaA=
|
||||
github.com/go-sql-driver/mysql v1.4.1-0.20190510102335-877a9775f068/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
||||
github.com/gobuffalo/here v0.6.0 h1:hYrd0a6gDmWxBM4TnrGw8mQg24iSVoIkHEk7FodQcBI=
|
||||
github.com/gobuffalo/here v0.6.0/go.mod h1:wAG085dHOYqUpf+Ap+WOdrPTp5IYcDAs/x7PLa8Y5fM=
|
||||
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
|
||||
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
||||
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY=
|
||||
@@ -75,8 +73,6 @@ github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q=
|
||||
github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4=
|
||||
github.com/lib/pq v1.2.0 h1:LXpIM/LZ5xGFhOpXAQUIMM1HdyqzVYM13zNdjCEEcA0=
|
||||
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/markbates/pkger v0.17.1 h1:/MKEtWqtc0mZvu9OinB9UzVN9iYCwLWuyUv4Bw+PCno=
|
||||
github.com/markbates/pkger v0.17.1/go.mod h1:0JoVlrol20BSywW79rN3kdFFsE5xYM+rSCQDXbLhiuI=
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mattn/go-sqlite3 v1.11.0 h1:LDdKkqtYlom37fkvqs8rMPFKAMe8+SgjbwZ6ex1/A/Q=
|
||||
@@ -104,7 +100,6 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
@@ -161,8 +156,6 @@ gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df h1:n7WqCuqOuCbNr617RXOY0AW
|
||||
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df/go.mod h1:LRQQ+SO6ZHR7tOkpBDuZnXENFzX8qRjMDMyPD6BRkCw=
|
||||
gopkg.in/ini.v1 v1.47.0 h1:XAVsOWcIxjm6JVEbCbSZgSBZIF0BrCzXs4orAQr6uc8=
|
||||
gopkg.in/ini.v1 v1.47.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
||||
+5
-1
@@ -14,7 +14,11 @@ type SendTasksIns struct {
|
||||
// InsEmailConfig 实例里面的邮箱config
|
||||
type InsEmailConfig struct {
|
||||
ToAccount string `json:"to_account" validate:"required,email" label:"收件邮箱"`
|
||||
Title string `json:"title" validate:"required,max=150" label:"邮箱标题"`
|
||||
//Title string `json:"title" validate:"required,max=150" label:"邮箱标题"`
|
||||
}
|
||||
|
||||
// InsEmailConfig 实例里面的邮箱config
|
||||
type InsDtalkConfig struct {
|
||||
}
|
||||
|
||||
// ManyAddTaskIns 批量添加实例
|
||||
|
||||
@@ -122,6 +122,7 @@ func GetTasksIns(id string) (TaskIns, error) {
|
||||
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.task_id = ?", insTable), id).
|
||||
Order(fmt.Sprintf("%s.created_on DESC", insTable)).
|
||||
Scan(&taskIns)
|
||||
|
||||
taskResult.ID = task.ID
|
||||
|
||||
+83
-3
@@ -1,9 +1,89 @@
|
||||
package message
|
||||
|
||||
type DTalkMessage struct {
|
||||
WebhookUrl string
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/hmac"
|
||||
"crypto/sha256"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
type response struct {
|
||||
Code int `json:"errcode"`
|
||||
Msg string `json:"errmsg"`
|
||||
}
|
||||
|
||||
func (d *DTalkMessage) send(content string) {
|
||||
type Dtalk struct {
|
||||
AccessToken string
|
||||
Secret string
|
||||
}
|
||||
|
||||
func (t *Dtalk) Request(msg interface{}) ([]byte, error) {
|
||||
b, err := json.Marshal(msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resp, err := http.Post(t.getURL(), "application/json", bytes.NewBuffer(b))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer resp.Body.Close()
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var r response
|
||||
err = json.Unmarshal(body, &r)
|
||||
if err != nil {
|
||||
return body, err
|
||||
}
|
||||
if r.Code != 0 {
|
||||
return body, errors.New(fmt.Sprintf("response error: %s", string(body)))
|
||||
}
|
||||
return body, err
|
||||
}
|
||||
|
||||
// SendMessageText Function to send message
|
||||
func (t *Dtalk) SendMessageText(text string, at ...string) ([]byte, error) {
|
||||
msg := map[string]interface{}{
|
||||
"msgtype": "text",
|
||||
"text": map[string]string{
|
||||
"content": text,
|
||||
},
|
||||
}
|
||||
resp, err := t.Request(msg)
|
||||
return resp, err
|
||||
}
|
||||
|
||||
func (t *Dtalk) SendMessageMarkdown(title, text string, at ...string) ([]byte, error) {
|
||||
msg := map[string]interface{}{
|
||||
"msgtype": "markdown",
|
||||
"markdown": map[string]string{
|
||||
"title": title,
|
||||
"text": text,
|
||||
},
|
||||
}
|
||||
resp, err := t.Request(msg)
|
||||
return resp, err
|
||||
}
|
||||
|
||||
func (t *Dtalk) hmacSha256(stringToSign string, secret string) string {
|
||||
h := hmac.New(sha256.New, []byte(secret))
|
||||
h.Write([]byte(stringToSign))
|
||||
return base64.StdEncoding.EncodeToString(h.Sum(nil))
|
||||
}
|
||||
|
||||
func (t *Dtalk) getURL() string {
|
||||
wh := "https://oapi.dingtalk.com/robot/send?access_token=" + t.AccessToken
|
||||
timestamp := time.Now().UnixNano() / 1e6
|
||||
stringToSign := fmt.Sprintf("%d\n%s", timestamp, t.Secret)
|
||||
sign := t.hmacSha256(stringToSign, t.Secret)
|
||||
url := fmt.Sprintf("%s×tamp=%d&sign=%s", wh, timestamp, sign)
|
||||
return url
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
type SendMessageReq struct {
|
||||
TaskID string `json:"task_id" validate:"required,len=36" label:"任务id"`
|
||||
Text string `json:"text" validate:"required" label:"文本内容"`
|
||||
Title string `json:"title" label:"消息标题"`
|
||||
HTML string `json:"html" label:"html内容"`
|
||||
MarkDown string `json:"markdown" label:"markdown内容"`
|
||||
Mode string `json:"mode" label:"是否异步发送"`
|
||||
@@ -31,11 +32,12 @@ func DoSendMassage(c *gin.Context) {
|
||||
|
||||
msgService := send_message_service.SendMessageService{
|
||||
TaskID: req.TaskID,
|
||||
Title: req.Title,
|
||||
Text: req.Text,
|
||||
HTML: req.HTML,
|
||||
MarkDown: req.MarkDown,
|
||||
}
|
||||
if req.Mode != "async" {
|
||||
if req.Mode == "sync" {
|
||||
// 同步发送
|
||||
err := msgService.Send()
|
||||
if err != "" {
|
||||
|
||||
@@ -44,6 +44,7 @@ func ClearLogs() {
|
||||
|
||||
// 启动注册清除任务定时任务
|
||||
func (cs *CronService) InitLogsCronRun() {
|
||||
// 注册任务
|
||||
setting, err := models.GetSettingByKey(constant.LogsCleanSectionName, constant.LogsCleanCronKeyName)
|
||||
if err != nil {
|
||||
logging.Logger.Error(fmt.Sprintf("获取日志的cron失败,原因:%s", err))
|
||||
@@ -52,6 +53,12 @@ func (cs *CronService) InitLogsCronRun() {
|
||||
Schedule: setting.Value,
|
||||
Job: ClearLogs,
|
||||
})
|
||||
|
||||
// 添加任务
|
||||
err = models.AddSendTaskWithID("日志定时清除", constant.CleanLogsTaskId, "admin")
|
||||
if err != nil {
|
||||
logging.Logger.Error(fmt.Sprintf("添加日志定时清除任务失败,原因:%s", err))
|
||||
}
|
||||
}
|
||||
|
||||
// 更新清除任务定时任务
|
||||
|
||||
@@ -30,6 +30,10 @@ func (sw *SendTaskInsService) ValidateDiffIns(ins models.SendTasksIns) (string,
|
||||
_, Msg := app.CommonPlaygroundValid(emailConfig)
|
||||
return Msg, emailConfig
|
||||
}
|
||||
if ins.WayType == "Dtalk" {
|
||||
var Config models.InsDtalkConfig
|
||||
return "", Config
|
||||
}
|
||||
return "未知的渠道的config校验", empty
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
package send_message_service
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"message-nest/models"
|
||||
"message-nest/pkg/message"
|
||||
"message-nest/service/send_ins_service"
|
||||
"message-nest/service/send_way_service"
|
||||
)
|
||||
|
||||
type DtalkService struct {
|
||||
}
|
||||
|
||||
// SendDtalkMessage 执行发送钉钉
|
||||
func (s *DtalkService) SendDtalkMessage(auth send_way_service.WayDetailDTalk, ins models.SendTasksIns, typeC string, title string, content string) string {
|
||||
insService := send_ins_service.SendTaskInsService{}
|
||||
errStr, c := insService.ValidateDiffIns(ins)
|
||||
if errStr != "" {
|
||||
return errStr
|
||||
}
|
||||
_, ok := c.(models.InsDtalkConfig)
|
||||
if !ok {
|
||||
return "钉钉config校验失败"
|
||||
}
|
||||
|
||||
errMsg := ""
|
||||
cli := message.Dtalk{
|
||||
AccessToken: auth.AccessToken,
|
||||
Secret: auth.Secret,
|
||||
}
|
||||
if typeC == "text" {
|
||||
_, err := cli.SendMessageText(content)
|
||||
if err != nil {
|
||||
errMsg = fmt.Sprintf("发送失败:%s", ins.ContentType)
|
||||
}
|
||||
} else if typeC == "markdown" {
|
||||
_, err := cli.SendMessageMarkdown(title, content)
|
||||
if err != nil {
|
||||
errMsg = fmt.Sprintf("发送失败:%s", ins.ContentType)
|
||||
}
|
||||
} else {
|
||||
errMsg = fmt.Sprintf("未知的钉钉发送内容类型:%s", ins.ContentType)
|
||||
}
|
||||
return errMsg
|
||||
}
|
||||
@@ -12,7 +12,7 @@ type EmailService struct {
|
||||
}
|
||||
|
||||
// SendTaskEmail 执行发送邮件
|
||||
func (s *EmailService) SendTaskEmail(auth send_way_service.WayDetailEmail, ins models.SendTasksIns, typeC string, content string) string {
|
||||
func (s *EmailService) SendTaskEmail(auth send_way_service.WayDetailEmail, ins models.SendTasksIns, typeC string, title string, content string) string {
|
||||
insService := send_ins_service.SendTaskInsService{}
|
||||
errStr, c := insService.ValidateDiffIns(ins)
|
||||
if errStr != "" {
|
||||
@@ -27,9 +27,9 @@ func (s *EmailService) SendTaskEmail(auth send_way_service.WayDetailEmail, ins m
|
||||
errMsg := ""
|
||||
emailer.Init(auth.Server, auth.Port, auth.Account, auth.Passwd)
|
||||
if typeC == "text" {
|
||||
errMsg = emailer.SendTextMessage(config.ToAccount, config.Title, content)
|
||||
errMsg = emailer.SendTextMessage(config.ToAccount, title, content)
|
||||
} else if typeC == "html" {
|
||||
errMsg = emailer.SendHtmlMessage(config.ToAccount, config.Title, content)
|
||||
errMsg = emailer.SendHtmlMessage(config.ToAccount, title, content)
|
||||
} else {
|
||||
errMsg = fmt.Sprintf("未知的邮件发送内容类型:%s", ins.ContentType)
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ func errStrIsSuccess(errStr string) int {
|
||||
|
||||
type SendMessageService struct {
|
||||
TaskID string
|
||||
Title string
|
||||
Text string
|
||||
HTML string
|
||||
MarkDown string
|
||||
@@ -46,6 +47,7 @@ func (sm *SendMessageService) Send() string {
|
||||
errStr := ""
|
||||
|
||||
sm.LogsAndStatusMark(fmt.Sprintf("开始任务[%s]的发送", sm.TaskID), sm.Status)
|
||||
sm.LogsAndStatusMark(fmt.Sprintf("发送标题:%s \n", sm.Title), sm.Status)
|
||||
|
||||
sendTaskService := send_task_service.SendTaskService{
|
||||
ID: sm.TaskID,
|
||||
@@ -93,13 +95,21 @@ func (sm *SendMessageService) Send() string {
|
||||
// 邮箱类型的实例发送
|
||||
emailAuth, ok := msgObj.(send_way_service.WayDetailEmail)
|
||||
if ok {
|
||||
//continue
|
||||
es := EmailService{}
|
||||
errMsg := es.SendTaskEmail(emailAuth, ins.SendTasksIns, typeC, content)
|
||||
errMsg := es.SendTaskEmail(emailAuth, ins.SendTasksIns, typeC, sm.Title, content)
|
||||
sm.LogsAndStatusMark(sm.TransError(errMsg), errStrIsSuccess(errMsg))
|
||||
continue
|
||||
}
|
||||
|
||||
sm.LogsAndStatusMark(fmt.Sprintf("未知渠道的发信实例: %s", ins.ID), sm.Status)
|
||||
// 钉钉类型的实例发送
|
||||
dtalkAuth, ok := msgObj.(send_way_service.WayDetailDTalk)
|
||||
if ok {
|
||||
es := DtalkService{}
|
||||
errMsg := es.SendDtalkMessage(dtalkAuth, ins.SendTasksIns, typeC, sm.Title, content)
|
||||
sm.LogsAndStatusMark(sm.TransError(errMsg), errStrIsSuccess(errMsg))
|
||||
continue
|
||||
}
|
||||
sm.LogsAndStatusMark(fmt.Sprintf("发送失败:未知渠道的发信实例: %s\n", ins.ID), SendFail)
|
||||
|
||||
}
|
||||
|
||||
@@ -165,6 +175,7 @@ func (sm *SendMessageService) GetSendMsg(ins models.SendTasksIns) (string, strin
|
||||
logging.Logger.Error("text节点数据为空!")
|
||||
return "text", ""
|
||||
} else {
|
||||
logging.Logger.Error(fmt.Sprintf("没有找到%s对应的消息,使用text消息替代!", ins.ContentType))
|
||||
return "text", content
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/blinkbean/dingtalk"
|
||||
"message-nest/models"
|
||||
"message-nest/pkg/app"
|
||||
"message-nest/pkg/message"
|
||||
@@ -33,7 +34,9 @@ type WayDetailEmail struct {
|
||||
|
||||
// WayDetailDTalk 钉钉渠道明细字段
|
||||
type WayDetailDTalk struct {
|
||||
WebhookUrl string `validate:"required,url" label:"钉钉webhookUrl地址"`
|
||||
AccessToken string `json:"access_token" validate:"required,max=100" label:"钉钉access_token"`
|
||||
Keys string `json:"keys" validate:"max=200" label:"钉钉关键字"`
|
||||
Secret string `json:"secret" validate:"max=100" label:"钉钉加签秘钥"`
|
||||
}
|
||||
|
||||
func (sw *SendWay) GetByID() (interface{}, error) {
|
||||
@@ -106,12 +109,22 @@ func (sw *SendWay) ValidateDiffWay() (string, interface{}) {
|
||||
|
||||
// TestSendWay 尝试带发信测试连通性
|
||||
func (sw *SendWay) TestSendWay(msgObj interface{}) string {
|
||||
testMsg := "This is a test message from message-nest."
|
||||
emailAuth, ok := msgObj.(WayDetailEmail)
|
||||
if ok {
|
||||
var emailer message.EmailMessage
|
||||
emailer.Init(emailAuth.Server, 465, emailAuth.Account, emailAuth.Passwd)
|
||||
errMsg := emailer.SendTextMessage(emailAuth.Account, "test", "This is a test email from message-nest.")
|
||||
errMsg := emailer.SendTextMessage(emailAuth.Account, "test email", testMsg)
|
||||
return errMsg
|
||||
}
|
||||
dtalkAuth, ok := msgObj.(WayDetailDTalk)
|
||||
if ok {
|
||||
cli := dingtalk.InitDingTalkWithSecret(dtalkAuth.AccessToken, dtalkAuth.Secret)
|
||||
err := cli.SendTextMessage(testMsg + dtalkAuth.Keys)
|
||||
if err != nil {
|
||||
return fmt.Sprintf("发送失败:%s", err)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
return fmt.Sprintf("未知的发信渠道校验: %s", sw.Type)
|
||||
}
|
||||
|
||||
+39
-9
@@ -13,24 +13,54 @@ const CONSTANT = {
|
||||
type: 'Email',
|
||||
label: '邮箱',
|
||||
inputs: [
|
||||
{ subLabel: 'smtp服务地址', value: '', col: 'server' },
|
||||
{ subLabel: 'smtp服务端口', value: '', col: 'port' },
|
||||
{ subLabel: '邮箱账号', value: '', col: 'account' },
|
||||
{ subLabel: '邮箱密码', value: '', col: 'passwd' },
|
||||
{ subLabel: '渠道名', value: '', col: 'name' },
|
||||
]
|
||||
{ subLabel: 'smtp服务地址', value: '', col: 'server', desc: "smtp@xyz.com" },
|
||||
{ subLabel: 'smtp服务端口', value: '', col: 'port', desc: "port" },
|
||||
{ subLabel: '邮箱账号', value: '', col: 'account', desc: "邮箱账号" },
|
||||
{ subLabel: '邮箱密码', value: '', col: 'passwd', desc: "邮箱密码" },
|
||||
{ subLabel: '渠道名', value: '', col: 'name', desc: "想要设置的渠道名字" },
|
||||
],
|
||||
taskInsRadios: [
|
||||
{ subLabel: 'text', content: 'text' },
|
||||
{ subLabel: 'html', content: 'html' },
|
||||
],
|
||||
taskInsInputs: [
|
||||
{ value: '', col: 'to_account', desc: "目的邮箱账号(发给谁)" },
|
||||
// { value: '', col: 'title', desc: "邮箱标题" },
|
||||
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'Dtalk',
|
||||
label: '钉钉',
|
||||
inputs: [
|
||||
{ subLabel: 'webhook地址', value: '', col: 'webhook_url' },
|
||||
{ subLabel: '渠道名', value: '', col: 'name' },
|
||||
]
|
||||
{ subLabel: 'access_token', value: '', col: 'access_token', desc: "钉钉webhook中的access_token" },
|
||||
// { subLabel: '关键字过滤', value: '', col: 'keys', desc: "使用的关键字过滤,多个使用|隔开" },
|
||||
{ subLabel: '加签', value: '', col: 'secret', desc: "加签的签名,SEC开头" },
|
||||
{ subLabel: '渠道名', value: '', col: 'name', desc: "想要设置的渠道名字" },
|
||||
],
|
||||
tips: {
|
||||
text: "输入框说明", desc: "钉钉支持加签和关键字过滤,如果是配置了关键字过滤,只需要消息里面包含了关键字,就会发送"
|
||||
},
|
||||
taskInsRadios: [
|
||||
{ subLabel: 'text', content: 'text' },
|
||||
{ subLabel: 'markdown', content: 'markdown' },
|
||||
],
|
||||
taskInsInputs: [
|
||||
// { value: '', col: 'to_account', desc: "目的邮箱账号(发给fsfsf谁)" },
|
||||
// { value: '', col: 'title', desc: "邮箱标题fsfsf" },
|
||||
],
|
||||
},
|
||||
],
|
||||
LOGO: `<svg t="1702547210136" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1861" width="200" height="200"><path d="M970.091313 224.033616a14.201535 14.201535 0 0 0-14.100687-3.631838c-88.419556-13.429657-142.919111-12.953859-248.242424 23.762747-69.454869 24.217859-109.056 79.873293-135.267556 116.712728-6.692202 9.403475-18.949172 26.625293-23.77309 29.509818-5.70699-1.303273-21.929374-16.036202-31.762101-24.965172-28.626747-25.994343-64.252121-58.353778-106.767516-58.757172-0.312889-0.005172-0.627071-0.005172-0.939959-0.005171-29.62101 0-54.798222 13.434828-72.857859 38.89907-13.222788 18.651798-17.914828 37.388929-18.106182 38.176323a14.31402 14.31402 0 0 0 2.893576 12.515556 14.336 14.336 0 0 0 11.782465 5.095434l0.409858-0.024565c19.192242-1.152 59.141172-3.545212 65.807516 81.857939 4.288646 54.899071 29.742545 108.631919 69.833697 147.419798 45.499475 44.025535 106.237414 67.298263 175.650909 67.298263 98.97503 0 166.222869-24.480323 205.207272-45.015919 43.172202-22.742626 62.621737-45.918384 63.429819-46.898425a14.170505 14.170505 0 0 0 1.529535-15.874586 14.191192 14.191192 0 0 0-14.166626-7.337373c-37.924202 4.443798-92.767677 6.09099-138.666667-11.298909-7.580444-2.872889-13.878303-5.893172-18.959515-8.691071 20.273131-9.964606 51.000889-28.383677 83.621495-59.93503 34.186343-33.065374 37.722505-69.908687 40.838464-102.423273 2.297535-23.919192 4.666182-48.651636 18.500526-73.091879 28.807758-50.883232 66.645333-74.489535 74.560646-79.035475a14.201535 14.201535 0 0 0 12.135434-7.776969 14.193778 14.193778 0 0 0-2.59103-16.484849z" fill="" p-id="1862"></path><path d="M674.834101 716.481939c-33.422222 4.90796-74.989899 16.884364-117.22602-8.102787-34.843152-20.613172-53.056646-20.993293-77.783919-18.49794-0.156444 0.015515-0.312889 0.015515-0.469334 0.034909-0.274101 0.033616-0.548202 0.060768-0.822303 0.094384-4.697212 0.487434-9.65301 1.065374-14.995394 1.62004-6.702545 0.649051-13.414141 1.19596-20.133495 1.634263-75.333818 4.102465-136.860444-5.381172-163.012525-10.404202-49.488162-9.872808-86.57196-23.921778-108.946101-33.970424-59.832889-26.868364-87.080081-56.671677-87.080081-72.989738 0-1.873455 0.384-2.222545 0.787394-2.585858 2.196687-1.974303 10.616242-6.520242 41.302626-6.004364 24.793212 0.418909 56.970343 3.858101 94.308849 7.853253 40.722101 4.348121 86.873212 9.283232 136.348444 11.686788 6.913293 0.333576 13.959758 0.625778 20.93899 0.858505 9.510788 0.307717 17.545051-7.182222 17.868283-16.707233 0.319354-9.535354-7.175758-17.550222-16.705939-17.868282a1386.24 1386.24 0 0 1-20.419233-0.839112c-48.521051-2.358303-94.161455-7.236525-134.434909-11.544565-90.868364-9.712485-139.353212-13.818828-162.333737 6.833131-8.02004 7.21196-12.262141 17.004606-12.262141 28.317737 0 0.672323 0.029737 1.348525 0.065939 2.026021l0.005172 0.100848c-0.045253 0.524929-0.071111 1.039515-0.071111 1.539879 0 41.464242 9.561212 81.661414 28.414707 119.484768 17.493333 35.088808 42.251636 66.663434 73.583192 93.927434 9.169455-6.551273 20.155475-13.604202 32.524929-20.050748 49.737697-25.921939 97.838545-29.339152 139.099798-9.884444 101.590626 47.906909 142.060606 47.837091 206.198949-0.364606 5.70699-4.287354 13.814949-3.140525 18.103596 2.567758 4.289939 5.708283 3.140525 13.813657-2.567757 18.103595-38.425859 28.877576-69.968162 41.279354-105.143596 41.280647-0.484848 0-0.969697-0.002586-1.457132-0.007758-32.760242-0.316768-69.311354-11.381657-126.16404-38.190545-51.905939-24.47903-106.215434 1.008485-139.548444 23.465374 64.611556 47.922424 146.341495 74.101657 232.704 74.101656 117.55701 0 226.204444-48.934788 292.761858-131.362909l0.002586-0.002586c18.79402-14.959192 12.028121-41.362101-23.442101-36.152889z" fill="" p-id="1863"></path></svg>`,
|
||||
|
||||
}
|
||||
|
||||
|
||||
CONSTANT.WAYS_DATA_MAP = {};
|
||||
CONSTANT.WAYS_DATA.forEach(element => {
|
||||
CONSTANT.WAYS_DATA_MAP[element.type] = element
|
||||
});
|
||||
|
||||
console.log('xxxxxxxx', CONSTANT.WAYS_DATA_MAP)
|
||||
|
||||
export { CONSTANT }
|
||||
@@ -0,0 +1,39 @@
|
||||
|
||||
|
||||
|
||||
class CommonUtils {
|
||||
|
||||
|
||||
// static getCurlString(task_id, options) {
|
||||
// let data = { task_id: task_id };
|
||||
// data.title = 'message title';
|
||||
// data.text = 'Hello World!';
|
||||
// if (options.html) {
|
||||
// data.html = '<h1> Hello World! </h1>';
|
||||
// }
|
||||
// if (options.markdown) {
|
||||
// data.html = '**Hello World!**';
|
||||
// }
|
||||
// let dataStr = JSON.stringify(data, null, 4);
|
||||
// let example = `curl -X POST --location '${gethttpOrigin()}/api/v1/message/send' \\
|
||||
// --header 'Content-Type: application/json' \\
|
||||
// --data '${dataStr}'`;
|
||||
// return example;
|
||||
// }
|
||||
|
||||
static formatInsConfigDisplay = (scope) => {
|
||||
if (!scope.row.config) {
|
||||
return ""
|
||||
}
|
||||
if (scope.row.way_type == "Email") {
|
||||
let config = JSON.parse(scope.row.config)
|
||||
let info = `发送账号:${config.to_account}`
|
||||
return info
|
||||
} else {
|
||||
return "暂无"
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export { CommonUtils };
|
||||
@@ -8,13 +8,14 @@ class ApiStrGenerate {
|
||||
|
||||
|
||||
static getCurlString(task_id, options) {
|
||||
let data = { task_id: task_id, mode: "async" };
|
||||
let data = { task_id: task_id };
|
||||
data.title = 'message title';
|
||||
data.text = 'Hello World!';
|
||||
if (options.html) {
|
||||
if (options.html ) {
|
||||
data.html = '<h1> Hello World! </h1>';
|
||||
}
|
||||
if (options.markdown) {
|
||||
data.html = '** Hello World! **';
|
||||
if (options.markdown ) {
|
||||
data.markdown = '**Hello World!**';
|
||||
}
|
||||
let dataStr = JSON.stringify(data, null, 4);
|
||||
let example = `curl -X POST --location '${gethttpOrigin()}/api/v1/message/send' \\
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
<template>
|
||||
<div class="tips">
|
||||
<el-text size="small">{{ text }}</el-text>
|
||||
<el-tooltip v-if="desc" placement="top">
|
||||
<template #content>
|
||||
<div v-html="desc"></div>
|
||||
</template>
|
||||
<el-icon>
|
||||
<QuestionFilled />
|
||||
</el-icon>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { defineComponent } from 'vue';
|
||||
import { QuestionFilled } from '@element-plus/icons-vue'
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
QuestionFilled,
|
||||
},
|
||||
props: {
|
||||
text: String,
|
||||
desc: String,
|
||||
},
|
||||
methods: {
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
@@ -6,7 +6,7 @@
|
||||
</div>
|
||||
<hr />
|
||||
<div ref="refContainer">
|
||||
<el-table :data="tableData" empty-text="发信日志为空" :row-style="rowStyle()">
|
||||
<el-table :data="tableData" stripe empty-text="发信日志为空" :row-style="rowStyle()">
|
||||
<el-table-column label="ID" prop="id" width="100px" />
|
||||
<el-table-column label="任务名" prop="task_name" show-overflow-tooltip width="150px" />
|
||||
<el-table-column label="发信日志" prop="log">
|
||||
|
||||
@@ -13,16 +13,24 @@
|
||||
<hr />
|
||||
|
||||
<div ref="refContainer">
|
||||
<el-table :data="tableData" empty-text="发信任务为空" :row-style="rowStyle()">
|
||||
<el-table :data="tableData" stripe empty-text="发信任务为空" :row-style="rowStyle()">
|
||||
<el-table-column label="ID" prop="id" width="320px" />
|
||||
<el-table-column label="任务名" prop="name" />
|
||||
<el-table-column label="创建时间" prop="created_on" />
|
||||
<el-table-column fixed="right" label="操作" width="190px">
|
||||
<template #default="scope">
|
||||
<el-button link size="small" type="primary" @click="handleViewAPI(scope.$index, scope.row)">接口</el-button>
|
||||
<el-button link size="small" type="primary" @click="handleViewLogs(scope.$index, scope.row)">日志</el-button>
|
||||
<el-button link size="small" type="primary" @click="handleEdit(scope.$index, scope.row)">编辑</el-button>
|
||||
<tableDeleteButton @customHandleDelete="handleDelete(scope.$index, scope.row)" />
|
||||
<div v-if="sysKeptTaskIds.includes(scope.row.id)">
|
||||
<el-button link size="small" type="primary"
|
||||
@click="handleViewLogs(scope.$index, scope.row)">日志</el-button>
|
||||
<el-text class="mx-1" type="info" size="small" style="margin-left: 15px;">系统保留任务</el-text>
|
||||
</div>
|
||||
<div v-if="!sysKeptTaskIds.includes(scope.row.id)">
|
||||
<el-button link size="small" type="primary" @click="handleViewAPI(scope.$index, scope.row)">接口</el-button>
|
||||
<el-button link size="small" type="primary"
|
||||
@click="handleViewLogs(scope.$index, scope.row)">日志</el-button>
|
||||
<el-button link size="small" type="primary" @click="handleEdit(scope.$index, scope.row)">编辑</el-button>
|
||||
<tableDeleteButton @customHandleDelete="handleDelete(scope.$index, scope.row)" />
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
@@ -75,7 +83,7 @@ export default {
|
||||
// confirmBtnVisible: false,
|
||||
tableData: [],
|
||||
total: CONSTANT.TOTAL,
|
||||
pageSize: CONSTANT.PAGE_SIZE,
|
||||
pageSize: CONSTANT.PAGE_SIZE,
|
||||
currPage: CONSTANT.PAGE,
|
||||
displayCols: [
|
||||
{ 'col': 'id', 'label': '任务ID' },
|
||||
@@ -86,7 +94,9 @@ export default {
|
||||
options: [
|
||||
{ label: '邮箱', value: 'Email' },
|
||||
{ label: '钉钉', value: 'Dtalk' }
|
||||
]
|
||||
],
|
||||
sysKeptTaskIds: [CONSTANT.LOG_TASK_ID],
|
||||
|
||||
});
|
||||
|
||||
const handleEdit = (index, row) => {
|
||||
@@ -122,7 +132,7 @@ export default {
|
||||
}
|
||||
|
||||
const handleViewLogs = (index, row) => {
|
||||
router.push('/sendlogs?name=' + row.name, { replace: true });
|
||||
router.push('/sendlogs?taskid=' + row.id, { replace: true });
|
||||
}
|
||||
|
||||
const filterFunc = async () => {
|
||||
|
||||
@@ -37,19 +37,21 @@
|
||||
<el-text class="mx-1" size="small">渠道创建时间:{{ currWayTmp.created_on }}</el-text><br />
|
||||
</div>
|
||||
|
||||
<el-radio-group v-model="currInsInput.content_type" class="ml-4">
|
||||
<el-radio label="text" size="small">text</el-radio>
|
||||
<el-radio label="html" size="small">html</el-radio>
|
||||
<el-radio-group v-model="currInsInputContentType">
|
||||
<el-radio v-for="item in CONSTANT.WAYS_DATA_MAP[currWayTmp.type].taskInsRadios" :label="item.subLabel"
|
||||
size="small">
|
||||
{{ item.content }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
|
||||
<div>
|
||||
<el-input v-model="currInsInput.toAccount" placeholder="目的邮箱账号(发给谁)" size="small"
|
||||
style="width: 200px; margin: 10px 40px 5px 0;" class="searchInput"></el-input>
|
||||
<el-input v-model="currInsInput.title" placeholder="邮箱标题" size="small"
|
||||
style="width: 200px; margin: 0px 40px 5px 0;" class="searchInput"></el-input>
|
||||
<el-button @click="clickStore()" size="small" style="width: 200px">暂存</el-button>
|
||||
<el-input v-model="currInsInput[item.col]"
|
||||
v-for="item in CONSTANT.WAYS_DATA_MAP[currWayTmp.type].taskInsInputs" :placeholder="item.desc" size="small"
|
||||
style="width: 200px; margin: 10px 40px 5px 0;" class="searchInput">
|
||||
</el-input>
|
||||
</div>
|
||||
|
||||
<el-button @click="clickStore()" size="small" style="width: 200px">暂存</el-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -97,6 +99,7 @@ import { QuestionFilled } from '@element-plus/icons-vue'
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import { usePageState } from '@/store/page_sate.js';
|
||||
import { request } from '@/api/api'
|
||||
import { CONSTANT } from '@/constant'
|
||||
|
||||
|
||||
export default defineComponent({
|
||||
@@ -114,9 +117,8 @@ export default defineComponent({
|
||||
isShowAddBox: false,
|
||||
searchWayID: '',
|
||||
currWayTmp: {},
|
||||
currInsInput: {
|
||||
content_type: 'text'
|
||||
},
|
||||
currInsInput: {},
|
||||
currInsInputContentType: 'text',
|
||||
currTaskInput: {
|
||||
taskName: '',
|
||||
taskId: uuidv4(),
|
||||
@@ -139,7 +141,8 @@ export default defineComponent({
|
||||
// 页面每次弹出,重置数据
|
||||
const resetPageInitData = () => {
|
||||
state.insTableData = [];
|
||||
state.currInsInput = { content_type: 'text' };
|
||||
state.currInsInputContentType = 'text';
|
||||
state.currInsInput = {};
|
||||
state.currWayTmp = {};
|
||||
state.searchWayID = '';
|
||||
state.isShowAddBox = false;
|
||||
@@ -163,8 +166,8 @@ export default defineComponent({
|
||||
way_id: state.currWayTmp.id,
|
||||
way_type: state.currWayTmp.type,
|
||||
way_name: state.currWayTmp.name,
|
||||
content_type: state.currInsInput.content_type,
|
||||
config: JSON.stringify({ to_account: state.currInsInput.toAccount, title: state.currInsInput.title })
|
||||
content_type: state.currInsInputContentType,
|
||||
config: JSON.stringify(state.currInsInput)
|
||||
};
|
||||
state.insTableData.push(insData);
|
||||
}
|
||||
@@ -175,6 +178,10 @@ export default defineComponent({
|
||||
state.isShowAddBox = Boolean(data.data);
|
||||
if (data.data) {
|
||||
state.currWayTmp = data.data;
|
||||
// 初始化currInsInput
|
||||
CONSTANT.WAYS_DATA_MAP[data.data.type].taskInsInputs.forEach(element => {
|
||||
state.currInsInput[element.col] = ""
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -184,8 +191,6 @@ export default defineComponent({
|
||||
return postData
|
||||
}
|
||||
|
||||
|
||||
|
||||
const handleSubmit = async () => {
|
||||
let postData = getFinalData();
|
||||
const rsp = await request.post('/sendtasks/ins/addmany', postData);
|
||||
@@ -196,17 +201,12 @@ export default defineComponent({
|
||||
}
|
||||
|
||||
const formatExtraInfo = (scope) => {
|
||||
if (!scope.row.config) {
|
||||
return ""
|
||||
}
|
||||
let config = JSON.parse(scope.row.config)
|
||||
let info = `发送账号:${config.to_account}\n标题:${config.title}`
|
||||
return info
|
||||
return CommonUtils.formatInsConfigDisplay(scope);
|
||||
}
|
||||
|
||||
return {
|
||||
...toRefs(state), handleCancer, handleSubmit,
|
||||
searchID, formatExtraInfo,
|
||||
searchID, formatExtraInfo, CONSTANT,
|
||||
clickStore, insRowStyle
|
||||
};
|
||||
},
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
<el-dialog v-model="isShow" width="58%" :close-on-press-escape="false" :before-close="() => { }" :show-close="false">
|
||||
<template #header="">
|
||||
<el-text class="mx-1">编辑发信任务</el-text>
|
||||
<el-tooltip placement="top">
|
||||
</el-tooltip>
|
||||
</template>
|
||||
|
||||
<div class="add-top">
|
||||
@@ -29,15 +27,19 @@
|
||||
<el-text class="mx-1" size="small">渠道创建时间:{{ currWayTmp.created_on }}</el-text><br />
|
||||
</div>
|
||||
|
||||
<el-radio-group v-model="currInsInput.content_type" class="ml-4">
|
||||
<el-radio label="text" size="small">text</el-radio>
|
||||
<el-radio label="html" size="small">html</el-radio>
|
||||
<el-radio-group v-model="currInsInputContentType">
|
||||
<el-radio v-for="item in CONSTANT.WAYS_DATA_MAP[currWayTmp.type].taskInsRadios" :label="item.subLabel"
|
||||
size="small">
|
||||
{{ item.content }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
|
||||
<div>
|
||||
<el-input v-model="currInsInput.toAccount" placeholder="目的邮箱账号(发给谁)" size="small"
|
||||
style="width: 200px; margin: 10px 40px 5px 0;" class="searchInput"></el-input>
|
||||
<el-input v-model="currInsInput.title" placeholder="邮箱标题" size="small"
|
||||
style="width: 200px; margin: 0px 40px 5px 0;" class="searchInput"></el-input>
|
||||
<el-input v-model="currInsInput[item.col]"
|
||||
v-for="item in CONSTANT.WAYS_DATA_MAP[currWayTmp.type].taskInsInputs" :placeholder="item.desc" size="small"
|
||||
style="width: 200px; margin: 10px 40px 5px 0;" class="searchInput">
|
||||
</el-input>
|
||||
|
||||
</div>
|
||||
<div>
|
||||
<el-button @click="handleAddSubmit()" size="small" style="width: 200px">添加</el-button>
|
||||
@@ -87,6 +89,8 @@ import { usePageState } from '@/store/page_sate.js';
|
||||
import { request } from '@/api/api'
|
||||
import tableDeleteButton from '@/views/common/tableDeleteButton.vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { CONSTANT } from '@/constant'
|
||||
import { CommonUtils } from "@/util/commonUtils.js";
|
||||
|
||||
|
||||
export default defineComponent({
|
||||
@@ -104,6 +108,7 @@ export default defineComponent({
|
||||
isShow: false,
|
||||
isShowAddBox: false,
|
||||
searchWayID: '',
|
||||
currInsInputContentType: '',
|
||||
currWayTmp: {},
|
||||
currInsInput: {},
|
||||
currTaskInput: {
|
||||
@@ -140,7 +145,9 @@ export default defineComponent({
|
||||
state.insTableData = [];
|
||||
state.currInsInput = {};
|
||||
state.currWayTmp = {};
|
||||
state.currInsInput = {};
|
||||
state.searchWayID = '';
|
||||
state.currInsInputContentType = '';
|
||||
state.isShowAddBox = false;
|
||||
state.currTaskInput = {
|
||||
taskName: '',
|
||||
@@ -162,12 +169,7 @@ export default defineComponent({
|
||||
}
|
||||
|
||||
const formatExtraInfo = (scope) => {
|
||||
if (!scope.row.config) {
|
||||
return ""
|
||||
}
|
||||
let config = JSON.parse(scope.row.config)
|
||||
let info = `发送账号:${config.to_account}\n标题:${config.title}`
|
||||
return info
|
||||
return CommonUtils.formatInsConfigDisplay(scope);
|
||||
}
|
||||
|
||||
const searchID = async () => {
|
||||
@@ -186,8 +188,8 @@ export default defineComponent({
|
||||
way_id: state.currWayTmp.id,
|
||||
way_type: state.currWayTmp.type,
|
||||
way_name: state.currWayTmp.name,
|
||||
content_type: state.currInsInput.content_type,
|
||||
config: JSON.stringify({ to_account: state.currInsInput.toAccount, title: state.currInsInput.title })
|
||||
content_type: state.currInsInputContentType,
|
||||
config: JSON.stringify(state.currInsInput)
|
||||
}
|
||||
return postData
|
||||
}
|
||||
@@ -210,7 +212,7 @@ export default defineComponent({
|
||||
}
|
||||
|
||||
return {
|
||||
...toRefs(state), handleCancer, handleAddSubmit, handleEditTask,
|
||||
...toRefs(state), handleCancer, handleAddSubmit, handleEditTask,CONSTANT,
|
||||
searchID, handleDelete, insRowStyle, formatExtraInfo
|
||||
};
|
||||
},
|
||||
|
||||
@@ -8,9 +8,9 @@
|
||||
<br />
|
||||
实例的内容类型大体上可以可以分为text、html、markdown
|
||||
<br />
|
||||
发送的消息会优先现在相应的类型消息进行发送,如果没有,将使用传的text消息进行发送
|
||||
发送的消息会优先现在相应的类型消息进行发送,如果没有,将使用传的text消息进行发送
|
||||
<br />
|
||||
** text节点必传,指定mode=async将异步发送,否则同步发送
|
||||
** text节点必传,指定mode=sync将同步发送,默认异步发送
|
||||
</template>
|
||||
<el-icon>
|
||||
<QuestionFilled />
|
||||
@@ -40,6 +40,7 @@ import { usePageState } from '@/store/page_sate.js';
|
||||
import Prism from "prismjs";
|
||||
import { ApiStrGenerate } from "@/util/viewApi.js";
|
||||
import { QuestionFilled } from '@element-plus/icons-vue'
|
||||
import { request } from '@/api/api'
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
@@ -70,10 +71,24 @@ export default defineComponent({
|
||||
}
|
||||
}
|
||||
|
||||
const renderApiString = () => {
|
||||
// 获取接口查看格式
|
||||
const getViewOptions = async (taskId) => {
|
||||
let params = { id: taskId };
|
||||
const rsp = await request.get('/sendtasks/ins/gettask', { params: params });
|
||||
let insTableData = await rsp.data.data.ins_data;
|
||||
|
||||
let viewOptions = {}
|
||||
insTableData.forEach(element => {
|
||||
viewOptions[element.content_type] = 1;
|
||||
});
|
||||
return viewOptions
|
||||
}
|
||||
|
||||
const renderApiString = async () => {
|
||||
let task_id = pageState.ShowDialogData[props.componentName].rowData.id;
|
||||
let options = await getViewOptions(task_id)
|
||||
if (state.activeName == 'curl') {
|
||||
state.currCode = ApiStrGenerate.getCurlString(task_id, {});
|
||||
state.currCode = ApiStrGenerate.getCurlString(task_id, options);
|
||||
}
|
||||
setTimeout(() => {
|
||||
Prism.highlightAll()
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
<hr />
|
||||
<div ref="refContainer">
|
||||
<el-table :data="tableData" empty-text="发信渠道为空" :row-style="rowStyle()">
|
||||
<el-table :data="tableData" stripe empty-text="发信渠道为空" :row-style="rowStyle()">
|
||||
<el-table-column label="ID" width="320px">
|
||||
<template #default="scope">
|
||||
{{ scope.row.id }}
|
||||
|
||||
@@ -8,34 +8,23 @@
|
||||
<el-form label-width="100px" v-for="item in waysLabelData">
|
||||
<el-tab-pane :label="item.label" :name="item.type">
|
||||
<el-form-item :label="one.subLabel" v-for="one in item.inputs">
|
||||
<el-input v-model="one.value" />
|
||||
<el-input size="small" v-model="one.value" :placeholder="one.desc" />
|
||||
</el-form-item>
|
||||
<textTips v-if="item.tips" :text="item.tips.text" :desc="item.tips.desc" />
|
||||
</el-tab-pane>
|
||||
</el-form>
|
||||
</el-tabs>
|
||||
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="testMseeageDialogVisible = true" size="small">测试发信</el-button>
|
||||
<el-button @click="handleCancer()" size="small">取消</el-button>
|
||||
<testSendButton @customhandleSubmit="handleTest()" />
|
||||
<el-button type="primary" size="small" @click="handleSubmit()">
|
||||
确定添加
|
||||
</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<el-dialog v-model="testMseeageDialogVisible" width="50%" align-center>
|
||||
<span>将发送一条测试信息,将注意查收</span>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button size="small" @click="testMseeageDialogVisible = false">取消</el-button>
|
||||
<el-button size="small" type="primary" @click="(testMseeageDialogVisible = false) || handleTest()">
|
||||
确定发送
|
||||
</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
@@ -45,9 +34,15 @@ import { request } from '@/api/api'
|
||||
import { CONSTANT } from '@/constant'
|
||||
import { _ } from 'lodash';
|
||||
import { ElMessage } from 'element-plus'
|
||||
import textTips from '@/views/common/textTips.vue'
|
||||
import testSendButton from './testSendButton.vue'
|
||||
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
textTips,
|
||||
testSendButton,
|
||||
},
|
||||
props: {
|
||||
componentName: String
|
||||
},
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<el-form label-width="100px" v-for="item in waysLabelData">
|
||||
<!-- <el-tab-pane :label="item.label" :name="item.type"> -->
|
||||
<el-form-item :label="one.subLabel" v-for="one in item.inputs">
|
||||
<el-input v-model="one.value" />
|
||||
<el-input size="small" v-model="one.value" :placeholder="one.desc" />
|
||||
</el-form-item>
|
||||
<!-- </el-tab-pane> -->
|
||||
</el-form>
|
||||
@@ -18,26 +18,14 @@
|
||||
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="testMseeageDialogVisible = true" size="small">测试发信</el-button>
|
||||
<el-button @click="handleCancer()" size="small">取消</el-button>
|
||||
<testSendButton @customhandleSubmit="handleTest()" />
|
||||
<el-button type="primary" size="small" @click="handleSubmit()">
|
||||
确定编辑
|
||||
</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<el-dialog v-model="testMseeageDialogVisible" width="50%" align-center>
|
||||
<span>将发送一条测试信息,将注意查收</span>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button size="small" @click="testMseeageDialogVisible = false">取消</el-button>
|
||||
<el-button size="small" type="primary" @click="(testMseeageDialogVisible = false) || handleTest()">
|
||||
确定发送
|
||||
</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
@@ -47,9 +35,13 @@ import { request } from '@/api/api'
|
||||
import { CONSTANT } from '@/constant'
|
||||
import { _ } from 'lodash';
|
||||
import { ElMessage } from 'element-plus'
|
||||
import testSendButton from './testSendButton.vue'
|
||||
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
testSendButton,
|
||||
},
|
||||
props: {
|
||||
componentName: String
|
||||
},
|
||||
@@ -57,7 +49,6 @@ export default defineComponent({
|
||||
const pageState = usePageState();
|
||||
const state = reactive({
|
||||
isShow: false,
|
||||
testMseeageDialogVisible: false,
|
||||
waysLabelData: [],
|
||||
editData: {},
|
||||
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
|
||||
<template>
|
||||
<el-popconfirm width="400px" confirm-button-text="确定" cancel-button-text="算了" icon-color="#626AEF"
|
||||
title="将往添加的渠道发送一条测试消息,请注意查收!" @confirm="handleSubmit()">
|
||||
<template #reference>
|
||||
<el-button size="small" type="primary">点击测试</el-button>
|
||||
</template>
|
||||
</el-popconfirm>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { defineComponent } from 'vue';
|
||||
|
||||
export default defineComponent({
|
||||
methods: {
|
||||
handleSubmit() {
|
||||
this.$emit('customhandleSubmit');
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<div class="buttom">
|
||||
<div class="tips">
|
||||
<el-text size="small">版本功能说明</el-text>
|
||||
<el-tooltip placement="top">
|
||||
<el-tooltip v-if="desc" placement="top">
|
||||
<template #content>
|
||||
<div v-html="desc"></div>
|
||||
</template>
|
||||
|
||||
Reference in New Issue
Block a user