360 lines
13 KiB
Go
360 lines
13 KiB
Go
package model
|
|
|
|
import (
|
|
"backend/client"
|
|
"backend/msg"
|
|
util "backend/util"
|
|
"fmt"
|
|
"log"
|
|
"sort"
|
|
)
|
|
|
|
const (
|
|
MailStatusPending = 1
|
|
MailStatusApproved = 2
|
|
MailStatusRejected = 3
|
|
)
|
|
|
|
type Mail struct {
|
|
AuditId int `json:"audit_id" db:"id"`
|
|
AppId int `json:"AppId" db:"app_id"`
|
|
ServerId int `json:"ServerId" db:"server_id"`
|
|
PageSize int `json:"PageSize"`
|
|
CurrentPage int `json:"CurrentPage"`
|
|
|
|
MailId int `json:"mail_id" db:"mail_id"`
|
|
Title string `json:"title" db:"title"`
|
|
SubTitle string `json:"subtitle" db:"subTitle"`
|
|
Content string `json:"content" db:"content"`
|
|
|
|
TitleEn string `json:"title_en" db:"title_en"`
|
|
SubTitleEn string `json:"subtitle_en" db:"subTitle_en"`
|
|
ContentEn string `json:"content_en" db:"content_en"`
|
|
|
|
TitlePtBr string `json:"title_ptbr" db:"title_ptbr"`
|
|
SubTitlePtBr string `json:"subtitle_ptbr" db:"subTitle_ptbr"`
|
|
ContentPtBr string `json:"content_ptbr" db:"content_ptbr"`
|
|
|
|
TitleEsLatam string `json:"title_es_latam" db:"title_es_latam"`
|
|
SubTitleEsLatam string `json:"subtitle_es_latam" db:"subTitle_es_latam"`
|
|
ContentEsLatam string `json:"content_es_latam" db:"content_es_latam"`
|
|
|
|
StartTime int64 `json:"start_time" db:"start_time"`
|
|
EndTime int64 `json:"end_time" db:"end_time"`
|
|
Items string `json:"items" db:"items"`
|
|
RegisterTime int64 `json:"register_time" db:"register_time"`
|
|
MailType int `json:"mail_type" db:"mail_type"`
|
|
SendType int `json:"send_type" db:"send_type"`
|
|
ToUids string `json:"to_uids" db:"to_uids"`
|
|
CreateTime int64 `json:"create_time" db:"create_time"`
|
|
MinLevel int `json:"min_level" db:"level"`
|
|
Status int `json:"status" db:"status"`
|
|
Applicant string `json:"applicant" db:"applicant"`
|
|
Reviewer string `json:"reviewer" db:"reviewer"`
|
|
ReviewRemark string `json:"review_remark" db:"review_remark"`
|
|
ReviewTime int64 `json:"review_time" db:"review_time"`
|
|
}
|
|
|
|
type Result struct {
|
|
Data interface{} `json:"data"`
|
|
Total int `json:"total"`
|
|
OperationList []string `json:"operationList,omitempty"`
|
|
}
|
|
|
|
func (m *Mail) MailList() (*Result, error) {
|
|
auditDb := util.MPool.GetGameDB()
|
|
if auditDb == nil {
|
|
return nil, fmt.Errorf("failed to get audit db")
|
|
}
|
|
defer auditDb.Close()
|
|
if err := ensureMailAuditTable(auditDb); err != nil {
|
|
return nil, err
|
|
}
|
|
if m.PageSize <= 0 {
|
|
m.PageSize = 20
|
|
}
|
|
if m.CurrentPage <= 0 {
|
|
m.CurrentPage = 1
|
|
}
|
|
|
|
var auditMails []*Mail
|
|
err := auditDb.Select(&auditMails, "SELECT `id`, `app_id`, `server_id`, `mail_id`, `title`, `content`, `start_time`, `end_time`, `items`, `register_time`, `mail_type`, `send_type`, `to_uids`, `create_time`, `subTitle`, `subTitle_en`, `content_en`, `title_en`, `title_ptbr`, `subTitle_ptbr`, `content_ptbr`, `title_es_latam`, `subTitle_es_latam`, `content_es_latam`, `level`, `status`, `applicant`, `reviewer`, `review_remark`, `review_time` FROM mail_audit WHERE `app_id` = ? AND `server_id` = ? ORDER BY `create_time` DESC, `id` DESC", m.AppId, m.ServerId)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to query audit mails: %v", err)
|
|
}
|
|
|
|
AppCfg, err := util.GetAppConfig(m.AppId)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
Db := util.MPool.GetMysqlDB(AppCfg, m.ServerId)
|
|
if Db == nil {
|
|
return nil, fmt.Errorf("failed to get mysql db")
|
|
}
|
|
defer Db.Close()
|
|
|
|
var serverMails []*Mail
|
|
err = Db.Select(&serverMails, "SELECT `mail_id`, `title`, `content`, `start_time`, `end_time`, `items`, `register_time`, `mail_type`, `send_type`, `to_uids`, `create_time`, `subTitle`, `subTitle_en`, `content_en`, `title_en`, `title_ptbr`, `subTitle_ptbr`, `content_ptbr`, `title_es_latam`, `subTitle_es_latam`, `content_es_latam`, `level` FROM system_mail_info ORDER BY mail_id DESC")
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to scan rows: %v", err)
|
|
}
|
|
|
|
approvedMailMap := map[int]struct{}{}
|
|
combined := make([]*Mail, 0, len(auditMails)+len(serverMails))
|
|
for _, v := range auditMails {
|
|
v.AppId = m.AppId
|
|
v.ServerId = m.ServerId
|
|
combined = append(combined, v)
|
|
if v.Status == MailStatusApproved && v.MailId > 0 {
|
|
approvedMailMap[v.MailId] = struct{}{}
|
|
}
|
|
}
|
|
for _, v := range serverMails {
|
|
if _, ok := approvedMailMap[v.MailId]; ok {
|
|
continue
|
|
}
|
|
v.AppId = m.AppId
|
|
v.ServerId = m.ServerId
|
|
v.Status = MailStatusApproved
|
|
v.Applicant = "历史数据"
|
|
v.Reviewer = "系统"
|
|
combined = append(combined, v)
|
|
}
|
|
|
|
sort.Slice(combined, func(i, j int) bool {
|
|
if combined[i].CreateTime == combined[j].CreateTime {
|
|
if combined[i].ReviewTime == combined[j].ReviewTime {
|
|
return combined[i].MailId > combined[j].MailId
|
|
}
|
|
return combined[i].ReviewTime > combined[j].ReviewTime
|
|
}
|
|
return combined[i].CreateTime > combined[j].CreateTime
|
|
})
|
|
|
|
total := len(combined)
|
|
start := (m.CurrentPage - 1) * m.PageSize
|
|
if start > total {
|
|
start = total
|
|
}
|
|
end := start + m.PageSize
|
|
if end > total {
|
|
end = total
|
|
}
|
|
|
|
return &Result{
|
|
Data: combined[start:end],
|
|
Total: total,
|
|
}, nil
|
|
}
|
|
|
|
func (m *Mail) SendMail() error {
|
|
auditDb := util.MPool.GetGameDB()
|
|
if auditDb == nil {
|
|
return fmt.Errorf("failed to get audit db")
|
|
}
|
|
defer auditDb.Close()
|
|
if err := ensureMailAuditTable(auditDb); err != nil {
|
|
return err
|
|
}
|
|
m.CreateTime = util.Now()
|
|
m.Status = MailStatusPending
|
|
_, err := auditDb.Exec("INSERT INTO mail_audit (`app_id`, `server_id`, `mail_id`, `title`, `content`, `title_en`, `content_en`, `start_time`, `end_time`, `items`, `register_time`, `mail_type`, `send_type`, `to_uids`, `create_time`, `subTitle`, `subTitle_en`, `title_ptbr`, `content_ptbr`, `subTitle_ptbr`, `title_es_latam`, `subTitle_es_latam`, `content_es_latam`, `level`, `status`, `applicant`, `reviewer`, `review_remark`, `review_time`) VALUES (?, ?, 0, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, '', '', 0)", m.AppId, m.ServerId, m.Title, m.Content, m.TitleEn, m.ContentEn, m.StartTime, m.EndTime, m.Items, m.RegisterTime, m.MailType, m.SendType, m.ToUids, m.CreateTime, m.SubTitle, m.SubTitleEn, m.TitlePtBr, m.ContentPtBr, m.SubTitlePtBr, m.TitleEsLatam, m.SubTitleEsLatam, m.ContentEsLatam, m.MinLevel, m.Status, m.Applicant)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to create mail audit: %v", err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (m *Mail) ApproveMail() error {
|
|
auditMail, auditDb, err := m.getAuditMailForUpdate()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer auditDb.Close()
|
|
|
|
mailId, err := auditMail.sendMailToServer()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
_, err = auditDb.Exec("UPDATE mail_audit SET `status` = ?, `reviewer` = ?, `review_remark` = ?, `review_time` = ?, `mail_id` = ? WHERE `id` = ?", MailStatusApproved, m.Reviewer, m.ReviewRemark, util.Now(), mailId, m.AuditId)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to update audit status: %v", err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (m *Mail) RejectMail() error {
|
|
_, auditDb, err := m.getAuditMailForUpdate()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer auditDb.Close()
|
|
_, err = auditDb.Exec("UPDATE mail_audit SET `status` = ?, `reviewer` = ?, `review_remark` = ?, `review_time` = ? WHERE `id` = ?", MailStatusRejected, m.Reviewer, m.ReviewRemark, util.Now(), m.AuditId)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to reject mail audit: %v", err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (m *Mail) sendMailToServer() (int64, error) {
|
|
AppCfg, err := util.GetAppConfig(m.AppId)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
Db := util.MPool.GetMysqlDB(AppCfg, m.ServerId)
|
|
if Db == nil {
|
|
return 0, fmt.Errorf("failed to get mysql db")
|
|
}
|
|
defer Db.Close()
|
|
if m.CreateTime == 0 {
|
|
m.CreateTime = util.Now()
|
|
}
|
|
result, err := Db.Exec("INSERT INTO system_mail_info (`title`, `content`, `title_en`, `content_en`, `start_time`, `end_time`, `items`, `register_time`, `mail_type`, `send_type`, `to_uids`, `create_time`, `subTitle`, `subTitle_en`, `title_ptbr`,`content_ptbr`,`subTitle_ptbr`, `title_es_latam`, `subTitle_es_latam`, `content_es_latam`, `level`) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", m.Title, m.Content, m.TitleEn, m.ContentEn, m.StartTime, m.EndTime, m.Items, m.RegisterTime, m.MailType, m.SendType, m.ToUids, m.CreateTime, m.SubTitle, m.SubTitleEn, m.TitlePtBr, m.ContentPtBr, m.SubTitlePtBr, m.TitleEsLatam, m.SubTitleEsLatam, m.ContentEsLatam, m.MinLevel)
|
|
if err != nil {
|
|
return 0, fmt.Errorf("failed to insert mail: %v", err)
|
|
}
|
|
mailId, err := result.LastInsertId()
|
|
if err != nil {
|
|
return 0, fmt.Errorf("failed to get mail id: %v", err)
|
|
}
|
|
m.reloadMail()
|
|
return mailId, nil
|
|
}
|
|
|
|
func (m *Mail) reloadMail() error {
|
|
ServerList := util.GetServerInfo(m.AppId, 0)
|
|
for _, server := range ServerList {
|
|
go func(serverInfo util.ServerConfig) {
|
|
req := &msg.ReqReloadServerMail{}
|
|
_, err := client.ReloadMail(serverInfo.AppId, serverInfo.ServerId, req)
|
|
if err != nil {
|
|
log.Printf("failed to send admin message: %v", err)
|
|
}
|
|
log.Printf("sent reload mail message to server %d", serverInfo.ServerId)
|
|
}(server)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (m *Mail) DeleteMail() error {
|
|
if m.AuditId > 0 {
|
|
auditDb := util.MPool.GetGameDB()
|
|
if auditDb == nil {
|
|
return fmt.Errorf("failed to get audit db")
|
|
}
|
|
defer auditDb.Close()
|
|
if err := ensureMailAuditTable(auditDb); err != nil {
|
|
return err
|
|
}
|
|
var auditMail Mail
|
|
err := auditDb.Get(&auditMail, "SELECT `id`, `app_id`, `server_id`, `mail_id`, `status` FROM mail_audit WHERE `id` = ?", m.AuditId)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to get audit mail: %v", err)
|
|
}
|
|
if auditMail.Status == MailStatusApproved && auditMail.MailId > 0 {
|
|
if err := deleteMailFromServer(auditMail.AppId, auditMail.ServerId, auditMail.MailId); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
_, err = auditDb.Exec("DELETE FROM mail_audit WHERE `id` = ?", m.AuditId)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to delete audit mail: %v", err)
|
|
}
|
|
m.reloadMail()
|
|
return nil
|
|
}
|
|
|
|
err := deleteMailFromServer(m.AppId, m.ServerId, m.MailId)
|
|
if err == nil {
|
|
m.reloadMail()
|
|
}
|
|
return err
|
|
}
|
|
|
|
func (m *Mail) getAuditMailForUpdate() (*Mail, *util.Db, error) {
|
|
if m.AuditId <= 0 {
|
|
return nil, nil, fmt.Errorf("audit_id is required")
|
|
}
|
|
auditDb := util.MPool.GetGameDB()
|
|
if auditDb == nil {
|
|
return nil, nil, fmt.Errorf("failed to get audit db")
|
|
}
|
|
if err := ensureMailAuditTable(auditDb); err != nil {
|
|
auditDb.Close()
|
|
return nil, nil, err
|
|
}
|
|
var auditMail Mail
|
|
err := auditDb.Get(&auditMail, "SELECT `id`, `app_id`, `server_id`, `mail_id`, `title`, `content`, `title_en`, `content_en`, `start_time`, `end_time`, `items`, `register_time`, `mail_type`, `send_type`, `to_uids`, `create_time`, `subTitle`, `subTitle_en`, `title_ptbr`, `content_ptbr`, `subTitle_ptbr`, `title_es_latam`, `subTitle_es_latam`, `content_es_latam`, `level`, `status`, `applicant`, `reviewer`, `review_remark`, `review_time` FROM mail_audit WHERE `id` = ?", m.AuditId)
|
|
if err != nil {
|
|
auditDb.Close()
|
|
return nil, nil, fmt.Errorf("failed to get audit mail: %v", err)
|
|
}
|
|
if auditMail.Status != MailStatusPending {
|
|
auditDb.Close()
|
|
if auditMail.Status == MailStatusApproved {
|
|
return nil, nil, fmt.Errorf("邮件已审核通过")
|
|
}
|
|
return nil, nil, fmt.Errorf("邮件已被驳回")
|
|
}
|
|
return &auditMail, auditDb, nil
|
|
}
|
|
|
|
func deleteMailFromServer(appId, serverId, mailId int) error {
|
|
AppCfg, err := util.GetAppConfig(appId)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
Db := util.MPool.GetMysqlDB(AppCfg, serverId)
|
|
if Db == nil {
|
|
return fmt.Errorf("failed to get mysql db")
|
|
}
|
|
defer Db.Close()
|
|
_, err = Db.Exec("DELETE FROM system_mail_info WHERE `mail_id` = ?", mailId)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to delete mail: %v", err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func ensureMailAuditTable(db *util.Db) error {
|
|
_, err := db.Exec(`CREATE TABLE IF NOT EXISTS mail_audit (
|
|
id INT NOT NULL AUTO_INCREMENT,
|
|
app_id INT NOT NULL DEFAULT 0,
|
|
server_id INT NOT NULL DEFAULT 0,
|
|
mail_id INT NOT NULL DEFAULT 0,
|
|
title VARCHAR(255) NOT NULL DEFAULT '',
|
|
subTitle VARCHAR(255) NOT NULL DEFAULT '',
|
|
content TEXT,
|
|
title_en VARCHAR(255) NOT NULL DEFAULT '',
|
|
subTitle_en VARCHAR(255) NOT NULL DEFAULT '',
|
|
content_en TEXT,
|
|
title_ptbr VARCHAR(255) NOT NULL DEFAULT '',
|
|
subTitle_ptbr VARCHAR(255) NOT NULL DEFAULT '',
|
|
content_ptbr TEXT,
|
|
title_es_latam VARCHAR(255) NOT NULL DEFAULT '',
|
|
subTitle_es_latam VARCHAR(255) NOT NULL DEFAULT '',
|
|
content_es_latam TEXT,
|
|
items TEXT,
|
|
start_time BIGINT NOT NULL DEFAULT 0,
|
|
end_time BIGINT NOT NULL DEFAULT 0,
|
|
register_time BIGINT NOT NULL DEFAULT 0,
|
|
mail_type INT NOT NULL DEFAULT 1,
|
|
send_type INT NOT NULL DEFAULT 1,
|
|
to_uids TEXT,
|
|
create_time BIGINT NOT NULL DEFAULT 0,
|
|
level INT NOT NULL DEFAULT 0,
|
|
status INT NOT NULL DEFAULT 1,
|
|
applicant VARCHAR(100) NOT NULL DEFAULT '',
|
|
reviewer VARCHAR(100) NOT NULL DEFAULT '',
|
|
review_remark VARCHAR(500) NOT NULL DEFAULT '',
|
|
review_time BIGINT NOT NULL DEFAULT 0,
|
|
PRIMARY KEY (id),
|
|
KEY idx_mail_audit_app_server (app_id, server_id),
|
|
KEY idx_mail_audit_status (status)
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4`)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to ensure mail_audit table: %v", err)
|
|
}
|
|
return nil
|
|
}
|