feat: support ticket settings in OMC
This commit is contained in:
@@ -1,6 +1,5 @@
|
|||||||
ticket:
|
ticket:
|
||||||
notifcation:
|
ticketNotification:
|
||||||
smtp:
|
|
||||||
enabled: true
|
enabled: true
|
||||||
host: mail.smtp.com
|
host: mail.smtp.com
|
||||||
port: 25
|
port: 25
|
||||||
@@ -11,10 +10,8 @@ ticket:
|
|||||||
password: 123456
|
password: 123456
|
||||||
tlsSkipVerify: true
|
tlsSkipVerify: true
|
||||||
from: omc@psap
|
from: omc@psap
|
||||||
to: # 可以是多个收件人
|
to: "admin@psap.com,user1@psap.com" # 注意:可以是多个收件人,使用逗号分隔
|
||||||
- admin@psap.com
|
ticketTimeout: # 超时设置
|
||||||
- user1@psap.com
|
|
||||||
timeout: # 超时设置
|
|
||||||
# 这些时间单位是分钟
|
# 这些时间单位是分钟
|
||||||
# 注意:这些时间是相对于工单创建时间的
|
# 注意:这些时间是相对于工单创建时间的
|
||||||
# 例如:new: 60分钟,inProgress: 60分钟
|
# 例如:new: 60分钟,inProgress: 60分钟
|
||||||
|
|||||||
@@ -56,12 +56,12 @@ omc:
|
|||||||
display: "Alarm SMS Forward Interface"
|
display: "Alarm SMS Forward Interface"
|
||||||
sort: 4
|
sort: 4
|
||||||
list:
|
list:
|
||||||
- name: "enable"
|
- name: "enabled"
|
||||||
type: "bool"
|
type: "bool"
|
||||||
value: "true"
|
value: "true"
|
||||||
access: "rw"
|
access: "rw"
|
||||||
filter: "true;false"
|
filter: "true;false"
|
||||||
display: "Enable"
|
display: "Enabled"
|
||||||
comment: "Is it enabled forward alarm with SMS interface"
|
comment: "Is it enabled forward alarm with SMS interface"
|
||||||
- name: "mobileList"
|
- name: "mobileList"
|
||||||
type: "string"
|
type: "string"
|
||||||
@@ -112,3 +112,102 @@ omc:
|
|||||||
filter: "3~20"
|
filter: "3~20"
|
||||||
display: "Service Number"
|
display: "Service Number"
|
||||||
comment: "It is the source address, the length is between 3 and 20"
|
comment: "It is the source address, the length is between 3 and 20"
|
||||||
|
ticketNotification:
|
||||||
|
display: "Ticket Notification Settings"
|
||||||
|
sort: 5
|
||||||
|
list:
|
||||||
|
- name: "enabled"
|
||||||
|
type: "bool"
|
||||||
|
value: "true"
|
||||||
|
access: "rw"
|
||||||
|
filter: "true;false"
|
||||||
|
display: "Enabled"
|
||||||
|
comment: "Is it enabled notifcation ticket with Email interface"
|
||||||
|
- name: "host"
|
||||||
|
type: "string"
|
||||||
|
value: ""
|
||||||
|
access: "rw"
|
||||||
|
filter: ""
|
||||||
|
display: "SMTP Host Server"
|
||||||
|
comment: "Email SMTP server"
|
||||||
|
- name: "port"
|
||||||
|
type: "int"
|
||||||
|
value: ""
|
||||||
|
access: "rw"
|
||||||
|
filter: "0~65535"
|
||||||
|
display: "Port"
|
||||||
|
comment: ""
|
||||||
|
- name: "username"
|
||||||
|
type: "string"
|
||||||
|
value: ""
|
||||||
|
access: "rw"
|
||||||
|
filter: ""
|
||||||
|
display: "Username"
|
||||||
|
comment: ""
|
||||||
|
- name: "password"
|
||||||
|
type: "string"
|
||||||
|
value: ""
|
||||||
|
access: "rw"
|
||||||
|
filter: ""
|
||||||
|
display: "Password"
|
||||||
|
comment: ""
|
||||||
|
- name: "tlsSkipVerify"
|
||||||
|
type: "bool"
|
||||||
|
value: "true"
|
||||||
|
access: "rw"
|
||||||
|
filter: "true;false"
|
||||||
|
display: "TLS Skip Verify"
|
||||||
|
comment: "If skip TLS verify (true/false)"
|
||||||
|
- name: "from"
|
||||||
|
type: "string"
|
||||||
|
value: "omc@psap"
|
||||||
|
access: "rw"
|
||||||
|
filter: ""
|
||||||
|
display: "From"
|
||||||
|
comment: "The sender email address, default is omc@psap"
|
||||||
|
- name: "to"
|
||||||
|
type: "string"
|
||||||
|
value: ""
|
||||||
|
access: "rw"
|
||||||
|
filter: ""
|
||||||
|
display: "To"
|
||||||
|
comment: "The addition receiver email address, multiple addresses separated by commas"
|
||||||
|
ticketTimeout:
|
||||||
|
display: "Ticket Timeout Settings"
|
||||||
|
sort: 7
|
||||||
|
list:
|
||||||
|
- name: "new"
|
||||||
|
type: int
|
||||||
|
value: 60
|
||||||
|
access: "rw"
|
||||||
|
filter: "0~1440"
|
||||||
|
display: "New Ticket Timeout (min)"
|
||||||
|
comment: "New ticket timeout in minutes, default is 60 minutes"
|
||||||
|
- name: "inProgress"
|
||||||
|
type: int
|
||||||
|
value: 60
|
||||||
|
access: "rw"
|
||||||
|
filter: "0~1440"
|
||||||
|
display: "In Progress Timeout (min)"
|
||||||
|
comment: "In progress ticket timeout in minutes, default is 60 minutes"
|
||||||
|
- name: "noAnswer1"
|
||||||
|
type: int
|
||||||
|
value: 240
|
||||||
|
access: "rw"
|
||||||
|
filter: "0~1440"
|
||||||
|
display: "No Answer 1 Timeout (min)"
|
||||||
|
comment: "No answer 1 ticket timeout in minutes, default is 240 minutes"
|
||||||
|
- name: "noAnswer2"
|
||||||
|
type: int
|
||||||
|
value: 480
|
||||||
|
access: "rw"
|
||||||
|
filter: "0~1440"
|
||||||
|
display: "No Answer 2 Timeout (min)"
|
||||||
|
comment: "No answer 2 ticket timeout in minutes, default is 480 minutes"
|
||||||
|
- name: "nearlyTimeout"
|
||||||
|
type: int
|
||||||
|
value: 20
|
||||||
|
access: "rw"
|
||||||
|
filter: "0~1440"
|
||||||
|
display: "Nearly Timeout (min)"
|
||||||
|
comment: "Nearly timeout in minutes, default is 20 minutes"
|
||||||
@@ -150,14 +150,14 @@ func PostCDREventFrom(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
// 添加配置中的原始收件人(如管理员、监控人员等)
|
// 添加配置中的原始收件人(如管理员、监控人员等)
|
||||||
if len(emailConfig.To) > 0 {
|
if len(emailConfig.To) > 0 {
|
||||||
recipients = append(recipients, emailConfig.To...)
|
recipients = append(recipients, strings.Split(emailConfig.To, ",")...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 添加当前工单的座席邮箱
|
// 添加当前工单的座席邮箱
|
||||||
recipients = append(recipients, ticket.AgentEmail)
|
recipients = append(recipients, ticket.AgentEmail)
|
||||||
|
|
||||||
// 去重处理(避免重复邮箱)
|
// 去重处理(避免重复邮箱)
|
||||||
emailCopy.To = email.RemoveDuplicateEmails(recipients)
|
emailCopy.To = strings.Join(email.RemoveDuplicateEmails(recipients), ",")
|
||||||
|
|
||||||
// 设置邮件主题和内容
|
// 设置邮件主题和内容
|
||||||
emailCopy.Subject = "新工单分配通知"
|
emailCopy.Subject = "新工单分配通知"
|
||||||
|
|||||||
@@ -22,6 +22,13 @@ func (o *ConfigOMC) Query(paramName string) (any, error) {
|
|||||||
result := config.GetYamlConfig().Alarm.SMSCForward
|
result := config.GetYamlConfig().Alarm.SMSCForward
|
||||||
result.Password = PASSWORD_MASK
|
result.Password = PASSWORD_MASK
|
||||||
results = append(results, result)
|
results = append(results, result)
|
||||||
|
case "ticketNotification":
|
||||||
|
result := config.GetPsapConfig().Ticket.TicketNotification
|
||||||
|
result.Password = PASSWORD_MASK
|
||||||
|
results = append(results, result)
|
||||||
|
case "ticketTimeout":
|
||||||
|
result := config.GetPsapConfig().Ticket.TicketTimeout
|
||||||
|
results = append(results, result)
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("invalid source parameter")
|
return nil, fmt.Errorf("invalid source parameter")
|
||||||
}
|
}
|
||||||
@@ -57,6 +64,26 @@ func (o *ConfigOMC) Modify(paramName string, paramData map[string]any) (any, err
|
|||||||
fmt.Println("failed to write config yaml file:", err)
|
fmt.Println("failed to write config yaml file:", err)
|
||||||
return results, err
|
return results, err
|
||||||
}
|
}
|
||||||
|
case "ticketNotification":
|
||||||
|
param := &(config.GetPsapConfig().Ticket.TicketNotification)
|
||||||
|
config.UpdatePsapStructFromMap(param, paramData)
|
||||||
|
result := *param
|
||||||
|
results = append(results, result)
|
||||||
|
err := config.WritePsapOriginalConfig(config.PsapYamlConfigInfo.FilePath, paramName, paramData)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("failed to write config yaml file:", err)
|
||||||
|
return results, err
|
||||||
|
}
|
||||||
|
case "ticketTimeout":
|
||||||
|
param := &(config.GetPsapConfig().Ticket.TicketTimeout)
|
||||||
|
config.UpdatePsapStructFromMap(param, paramData)
|
||||||
|
result := *param
|
||||||
|
results = append(results, result)
|
||||||
|
err := config.WritePsapOriginalConfig(config.PsapYamlConfigInfo.FilePath, paramName, paramData)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("failed to write config yaml file:", err)
|
||||||
|
return results, err
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("invalid source parameter")
|
return nil, fmt.Errorf("invalid source parameter")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package mf_callback_ticket
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"be.ems/lib/config"
|
"be.ems/lib/config"
|
||||||
@@ -391,14 +392,14 @@ func (s *CallbackTicketService) UpdateTicketToTimeout(ticket *CallbackTicket, or
|
|||||||
|
|
||||||
// 添加配置中的原始收件人(如管理员、监控人员等)
|
// 添加配置中的原始收件人(如管理员、监控人员等)
|
||||||
if len(emailConfig.To) > 0 {
|
if len(emailConfig.To) > 0 {
|
||||||
recipients = append(recipients, emailConfig.To...)
|
recipients = append(recipients, strings.Split(emailConfig.To, ",")...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 添加当前工单的座席邮箱
|
// 添加当前工单的座席邮箱
|
||||||
recipients = append(recipients, ticket.AgentEmail)
|
recipients = append(recipients, ticket.AgentEmail)
|
||||||
|
|
||||||
// 去重处理(避免重复邮箱)
|
// 去重处理(避免重复邮箱)
|
||||||
emailCopy.To = email.RemoveDuplicateEmails(recipients)
|
emailCopy.To = strings.Join(email.RemoveDuplicateEmails(recipients), ",")
|
||||||
|
|
||||||
// 设置邮件主题和内容
|
// 设置邮件主题和内容
|
||||||
emailCopy.Subject = "新工单自动重建通知"
|
emailCopy.Subject = "新工单自动重建通知"
|
||||||
@@ -484,14 +485,14 @@ func (s *CallbackTicketService) BatchUpdateTimeoutTickets(tickets []CallbackTick
|
|||||||
|
|
||||||
// 添加配置中的原始收件人(如管理员、监控人员等)
|
// 添加配置中的原始收件人(如管理员、监控人员等)
|
||||||
if len(emailConfig.To) > 0 {
|
if len(emailConfig.To) > 0 {
|
||||||
recipients = append(recipients, emailConfig.To...)
|
recipients = append(recipients, strings.Split(emailConfig.To, ",")...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 添加当前工单的座席邮箱
|
// 添加当前工单的座席邮箱
|
||||||
recipients = append(recipients, ticket.AgentEmail)
|
recipients = append(recipients, ticket.AgentEmail)
|
||||||
|
|
||||||
// 去重处理(避免重复邮箱)
|
// 去重处理(避免重复邮箱)
|
||||||
emailCopy.To = email.RemoveDuplicateEmails(recipients)
|
emailCopy.To = strings.Join(email.RemoveDuplicateEmails(recipients), ",")
|
||||||
|
|
||||||
// 设置邮件主题和内容
|
// 设置邮件主题和内容
|
||||||
emailCopy.Subject = "新工单自动重建通知"
|
emailCopy.Subject = "新工单自动重建通知"
|
||||||
|
|||||||
@@ -264,7 +264,13 @@ func InitPsapConfig() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := ReadPsapConfig(yamlConfig.PsapConfig.File)
|
// 确保使用正确的配置文件路径
|
||||||
|
configFile := yamlConfig.PsapConfig.File
|
||||||
|
if configFile == "" {
|
||||||
|
configFile = "./etc/psap.yaml" // 默认路径
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := ReadPsapConfig(configFile)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -320,6 +326,12 @@ func WriteOrignalConfig(configFile string, paramName string, paramData map[strin
|
|||||||
for k, v := range paramData {
|
for k, v := range paramData {
|
||||||
// find the first line nearby the paramName
|
// find the first line nearby the paramName
|
||||||
for j := i + 1; j < len(lines); j++ {
|
for j := i + 1; j < len(lines); j++ {
|
||||||
|
// ignore comment lines
|
||||||
|
trimmedLine := strings.TrimSpace(lines[j])
|
||||||
|
if strings.HasPrefix(trimmedLine, "#") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
if strings.Contains(lines[j], k+":") {
|
if strings.Contains(lines[j], k+":") {
|
||||||
index := strings.Index(lines[j], k)
|
index := strings.Index(lines[j], k)
|
||||||
// Determine the type of v
|
// Determine the type of v
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
package config
|
package config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bufio"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
"reflect"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"be.ems/lib/email"
|
"be.ems/lib/email"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
@@ -11,24 +14,27 @@ import (
|
|||||||
// PsapConfig PSAP配置结构体
|
// PsapConfig PSAP配置结构体
|
||||||
type PsapConfig struct {
|
type PsapConfig struct {
|
||||||
Ticket struct {
|
Ticket struct {
|
||||||
Notification struct {
|
TicketNotification email.EmailConfig `yaml:"ticketNotification" json:"ticketNotification"` // 注意:配置文件中是 "ticketNotification",保持一致
|
||||||
SMTP email.EmailConfig `yaml:"smtp"`
|
TicketTimeout TicketTimeout `yaml:"ticketTimeout" json:"ticketTimeout"` // 注意:配置文件中是 "ticketTimeout",保持一致{
|
||||||
} `yaml:"notifcation"` // 注意:配置文件中是 "notifcation",保持一致
|
} `yaml:"ticket" json:"ticket"` // PSAP工单相关配置
|
||||||
Timeout struct {
|
}
|
||||||
// 时间单位为分钟
|
|
||||||
New int `yaml:"new"` // NEW状态超时时间(分钟)
|
type TicketTimeout struct {
|
||||||
InProgress int `yaml:"inProgress"` // IN_PROGRESS状态超时时间(分钟)
|
New int `yaml:"new" json:"new"` // NEW状态超时时间(分钟)
|
||||||
NoAnswer1 int `yaml:"noAnswer1"` // NO_ANSWER_1状态超时时间(分钟)
|
InProgress int `yaml:"inProgress" json:"inProgress"` // IN_PROGRESS状态超时时间(分钟)
|
||||||
NoAnswer2 int `yaml:"noAnswer2"` // NO_ANSWER_2状态超时时间(分钟)
|
NoAnswer1 int `yaml:"noAnswer1" json:"noAnswer1"` // NO_ANSWER_1状态超时时间(分钟)
|
||||||
NearlyTimeout int `yaml:"nearlyTimeout"` // 提前提醒时间(分钟)
|
NoAnswer2 int `yaml:"noAnswer2" json:"noAnswer2"` // NO_ANSWER_2状态超时时间(分钟)
|
||||||
} `yaml:"timeout"`
|
NearlyTimeout int `yaml:"nearlyTimeout" json:"nearlyTimeout"` // 提前提醒时间(分钟)
|
||||||
} `yaml:"ticket"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var psapConfig *PsapConfig
|
var psapConfig *PsapConfig
|
||||||
|
|
||||||
|
var PsapYamlConfigInfo YamlConfigFile = YamlConfigFile{}
|
||||||
|
|
||||||
// ReadPsapConfig 读取PSAP配置文件
|
// ReadPsapConfig 读取PSAP配置文件
|
||||||
func ReadPsapConfig(configFile string) (*PsapConfig, error) {
|
func ReadPsapConfig(configFile string) (*PsapConfig, error) {
|
||||||
|
PsapYamlConfigInfo.FilePath = configFile
|
||||||
|
|
||||||
yamlFile, err := os.ReadFile(configFile)
|
yamlFile, err := os.ReadFile(configFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("read psap config file error: %w", err)
|
return nil, fmt.Errorf("read psap config file error: %w", err)
|
||||||
@@ -41,9 +47,110 @@ func ReadPsapConfig(configFile string) (*PsapConfig, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
psapConfig = &config
|
psapConfig = &config
|
||||||
|
// PsapYamlConfigInfo.ConfigLines = config
|
||||||
|
|
||||||
|
// 读取原始文件行
|
||||||
|
err = ReadPsapOriginalConfig(configFile)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("read psap original config error: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
return &config, nil
|
return &config, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ReadPsapOriginalConfig 读取PSAP原始配置文件行
|
||||||
|
func ReadPsapOriginalConfig(configFile string) error {
|
||||||
|
inputFile, err := os.Open(configFile)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to open psap config file: %w", err)
|
||||||
|
}
|
||||||
|
defer inputFile.Close()
|
||||||
|
|
||||||
|
// 清空之前的内容
|
||||||
|
PsapYamlConfigInfo.OrignalLines = nil
|
||||||
|
|
||||||
|
scanner := bufio.NewScanner(inputFile)
|
||||||
|
for scanner.Scan() {
|
||||||
|
PsapYamlConfigInfo.OrignalLines = append(PsapYamlConfigInfo.OrignalLines, scanner.Text())
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := scanner.Err(); err != nil {
|
||||||
|
return fmt.Errorf("failed to scan psap config file: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// WritePsapOriginalConfig 写回PSAP原始配置文件
|
||||||
|
func WritePsapOriginalConfig(configFile string, paramName string, paramData map[string]any) error {
|
||||||
|
lines := PsapYamlConfigInfo.OrignalLines
|
||||||
|
for i, line := range lines {
|
||||||
|
if strings.Contains(line, paramName) {
|
||||||
|
for k, v := range paramData {
|
||||||
|
// 在paramName附近查找对应的字段
|
||||||
|
for j := i + 1; j < len(lines); j++ {
|
||||||
|
// 跳过注释行
|
||||||
|
trimmedLine := strings.TrimSpace(lines[j])
|
||||||
|
if strings.HasPrefix(trimmedLine, "#") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if strings.Contains(lines[j], k+":") {
|
||||||
|
index := strings.Index(lines[j], k)
|
||||||
|
// 根据v的类型确定格式
|
||||||
|
switch v := v.(type) {
|
||||||
|
case string:
|
||||||
|
lines[j] = lines[j][:index] + fmt.Sprintf("%s: \"%s\"", k, v)
|
||||||
|
case bool:
|
||||||
|
lines[j] = lines[j][:index] + fmt.Sprintf("%s: %t", k, v)
|
||||||
|
default:
|
||||||
|
lines[j] = lines[j][:index] + fmt.Sprintf("%s: %v", k, v)
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 写回yaml文件
|
||||||
|
outputFile, err := os.Create(configFile)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to create psap config file: %w", err)
|
||||||
|
}
|
||||||
|
defer outputFile.Close()
|
||||||
|
|
||||||
|
writer := bufio.NewWriter(outputFile)
|
||||||
|
for _, line := range PsapYamlConfigInfo.OrignalLines {
|
||||||
|
writer.WriteString(line + "\n")
|
||||||
|
}
|
||||||
|
return writer.Flush()
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdatePsapStructFromMap 更新PSAP结构体字段
|
||||||
|
func UpdatePsapStructFromMap(s any, updates map[string]any) {
|
||||||
|
v := reflect.ValueOf(s).Elem()
|
||||||
|
t := v.Type()
|
||||||
|
|
||||||
|
for key, value := range updates {
|
||||||
|
for i := 0; i < t.NumField(); i++ {
|
||||||
|
field := t.Field(i)
|
||||||
|
if field.Tag.Get("json") == key {
|
||||||
|
structField := v.FieldByName(field.Name)
|
||||||
|
if structField.IsValid() && structField.CanSet() {
|
||||||
|
// 转换值为适当的类型
|
||||||
|
convertedValue := reflect.ValueOf(value).Convert(structField.Type())
|
||||||
|
if structField.Type() == convertedValue.Type() {
|
||||||
|
structField.Set(convertedValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// GetPsapConfig 获取PSAP配置
|
// GetPsapConfig 获取PSAP配置
|
||||||
func GetPsapConfig() *PsapConfig {
|
func GetPsapConfig() *PsapConfig {
|
||||||
if psapConfig == nil {
|
if psapConfig == nil {
|
||||||
@@ -64,22 +171,16 @@ func GetSMTPConfig() *email.EmailConfig {
|
|||||||
if config == nil {
|
if config == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return &config.Ticket.Notification.SMTP
|
return &config.Ticket.TicketNotification
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetTimeoutConfig 获取超时配置
|
// GetTimeoutConfig 获取超时配置
|
||||||
func GetTimeoutConfig() *struct {
|
func GetTimeoutConfig() *TicketTimeout {
|
||||||
New int `yaml:"new"`
|
|
||||||
InProgress int `yaml:"inProgress"`
|
|
||||||
NoAnswer1 int `yaml:"noAnswer1"`
|
|
||||||
NoAnswer2 int `yaml:"noAnswer2"`
|
|
||||||
NearlyTimeout int `yaml:"nearlyTimeout"`
|
|
||||||
} {
|
|
||||||
config := GetPsapConfig()
|
config := GetPsapConfig()
|
||||||
if config == nil {
|
if config == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return &config.Ticket.Timeout
|
return &config.Ticket.TicketTimeout
|
||||||
}
|
}
|
||||||
|
|
||||||
// 以下是具体的配置获取方法
|
// 以下是具体的配置获取方法
|
||||||
|
|||||||
@@ -11,16 +11,16 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type EmailConfig struct {
|
type EmailConfig struct {
|
||||||
Enabled bool `yaml:"enabled"` // 是否启用邮件发送
|
Enabled bool `yaml:"enabled" json:"enabled"` // 是否启用邮件发送
|
||||||
Host string `yaml:"host"`
|
Host string `yaml:"host" json:"host"` // SMTP服务器地址
|
||||||
Port int `yaml:"port"`
|
Port int `yaml:"port" json:"port"` // SMTP服务器端口
|
||||||
Username string `yaml:"username"`
|
Username string `yaml:"username" json:"username"` // SMTP用户名
|
||||||
Password string `yaml:"password"`
|
Password string `yaml:"password" json:"password"` // SMTP密码
|
||||||
TLSSkipVerify bool `yaml:"tlsSkipVerify"`
|
TLSSkipVerify bool `yaml:"tlsSkipVerify" json:"tlsSkipVerify"` // 是否跳过TLS证书验证
|
||||||
From string `yaml:"from"`
|
From string `yaml:"from" json:"from"` // 发件人邮箱地址
|
||||||
To []string `yaml:"to"`
|
To string `yaml:"to" json:"to"` // 收件人邮箱地址列表
|
||||||
Subject string `yaml:"subject"`
|
Subject string `yaml:"subject" json:"subject"` // 邮件主题
|
||||||
Body string `yaml:"body"`
|
Body string `yaml:"body" json:"body"` // 邮件正文内容
|
||||||
}
|
}
|
||||||
|
|
||||||
// 简单邮件发送函数
|
// 简单邮件发送函数
|
||||||
@@ -31,7 +31,7 @@ func SendEmail(email EmailConfig) error {
|
|||||||
username := email.Username
|
username := email.Username
|
||||||
from := email.From
|
from := email.From
|
||||||
password := email.Password
|
password := email.Password
|
||||||
to := strings.Join(email.To, ",") // 将多个收件人用逗号连接
|
to := email.To
|
||||||
subject := email.Subject
|
subject := email.Subject
|
||||||
body := email.Body
|
body := email.Body
|
||||||
smtpHost := email.Host
|
smtpHost := email.Host
|
||||||
@@ -48,7 +48,7 @@ func SendEmail(email EmailConfig) error {
|
|||||||
func SendEmailWithGomail(email EmailConfig) error {
|
func SendEmailWithGomail(email EmailConfig) error {
|
||||||
m := gomail.NewMessage()
|
m := gomail.NewMessage()
|
||||||
m.SetHeader("From", email.From)
|
m.SetHeader("From", email.From)
|
||||||
m.SetHeader("To", email.To...)
|
m.SetHeader("To", strings.Split(email.To, ",")...) // 支持多个收件人
|
||||||
m.SetHeader("Subject", email.Subject)
|
m.SetHeader("Subject", email.Subject)
|
||||||
m.SetBody("text/plain", email.Body)
|
m.SetBody("text/plain", email.Body)
|
||||||
|
|
||||||
|
|||||||
@@ -1,24 +1,21 @@
|
|||||||
ticket:
|
ticket:
|
||||||
notifcation:
|
ticketNotification:
|
||||||
smtp:
|
enabled: false
|
||||||
enabled: true
|
|
||||||
host: mail.agrandtech.com
|
host: mail.agrandtech.com
|
||||||
port: 25
|
port: 25
|
||||||
username: smtpext@agrandtech.com
|
username: smtpext@agrandtech.com
|
||||||
# 注意:密码中如果包含特殊字符(如@、#、$等),
|
# 注意:密码中如果包含特殊字符(如@、#、$等),
|
||||||
# 需要使用双引号括起来,避免解析错误
|
# 需要使用双引号括起来,避免解析错误
|
||||||
# 例如:password: "1000smtp@omc!"
|
# 例如:password: "123456"
|
||||||
password: Smtp123@agt
|
password: Smtp123@agt
|
||||||
tlsSkipVerify: true
|
tlsSkipVerify: true
|
||||||
from: restagent@localhost
|
from: omc@psap
|
||||||
to:
|
to: "simonzhangsz@outlook.com,shuzone@126.com,a@b.com"
|
||||||
- simonzhangsz@outlook.com # 可以是多个收件人
|
ticketTimeout: # 超时设置
|
||||||
- shuzone@126.com
|
|
||||||
timeout: # 超时设置
|
|
||||||
# 这些时间单位是分钟
|
# 这些时间单位是分钟
|
||||||
# 注意:这些时间是相对于工单创建时间的
|
# 注意:这些时间是相对于工单创建时间的
|
||||||
# 例如:new: 60分钟,inProgress: 60分钟
|
# 例如:new: 60分钟,inProgress: 60分钟
|
||||||
new: 1
|
new: 60
|
||||||
inProgress: 60
|
inProgress: 60
|
||||||
noAnswer1: 240
|
noAnswer1: 240
|
||||||
noAnswer2: 480
|
noAnswer2: 480
|
||||||
|
|||||||
@@ -209,14 +209,14 @@ func (s *PsapTicketMonitor) handleNearlyTimeoutTickets(status string, timeoutMic
|
|||||||
|
|
||||||
// 添加配置中的原始收件人(如管理员、监控人员等)
|
// 添加配置中的原始收件人(如管理员、监控人员等)
|
||||||
if len(emailConfig.To) > 0 {
|
if len(emailConfig.To) > 0 {
|
||||||
recipients = append(recipients, emailConfig.To...)
|
recipients = append(recipients, strings.Split(emailConfig.To, ",")...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 添加当前工单的座席邮箱
|
// 添加当前工单的座席邮箱
|
||||||
recipients = append(recipients, ticket.AgentEmail)
|
recipients = append(recipients, ticket.AgentEmail)
|
||||||
|
|
||||||
// 去重处理(避免重复邮箱)
|
// 去重处理(避免重复邮箱)
|
||||||
emailCopy.To = email.RemoveDuplicateEmails(recipients)
|
emailCopy.To = strings.Join(email.RemoveDuplicateEmails(recipients), ",")
|
||||||
|
|
||||||
// 设置邮件主题和内容
|
// 设置邮件主题和内容
|
||||||
emailCopy.Subject = "工单即将超时提醒"
|
emailCopy.Subject = "工单即将超时提醒"
|
||||||
|
|||||||
Reference in New Issue
Block a user