ソースを参照

英文研报列表加载速度优化

hsun 10 ヶ月 前
コミット
7c72b8ad8e

+ 58 - 40
controllers/english_report/email.go

@@ -726,17 +726,19 @@ func (this *EnglishReportEmailController) Send() {
 		r.ReportContent = overview
 		r.ReportShareLink = l
 		r.ReportTime = t
-		sendData = append(sendData, r)
-
-		// 日志
-		logData = append(logData, &models.EnglishReportEmailLog{
+		logItem := &models.EnglishReportEmailLog{
 			ReportId:   reportInfo.Id,
 			EmailId:    emails[i].Id,
 			Email:      emails[i].Email,
 			Source:     models.EnglishReportEmailLogSourceAli,
 			SendStatus: models.EnglishReportEmailLogStatusIng,
 			CreateTime: nowTime,
-		})
+		}
+		r.EmailLog = logItem
+		sendData = append(sendData, r)
+
+		// 日志
+		logData = append(logData, logItem)
 	}
 	if len(sendData) == 0 {
 		br.Msg = "无邮件可推送"
@@ -744,12 +746,19 @@ func (this *EnglishReportEmailController) Send() {
 	}
 
 	// 写入日志
-	emailLog := new(models.EnglishReportEmailLog)
-	if e = emailLog.InsertMulti(logData); e != nil {
-		br.Msg = "操作失败"
-		br.ErrMsg = "批量写入群发邮件日志失败, Err: " + e.Error()
-		return
+	for _, v := range logData {
+		if e = v.Create(); e != nil {
+			br.Msg = "操作失败"
+			br.ErrMsg = "写入群发邮件日志失败, Err: " + e.Error()
+			return
+		}
 	}
+	//emailLog := new(models.EnglishReportEmailLog)
+	//if e = emailLog.InsertMulti(logData); e != nil {
+	//	br.Msg = "操作失败"
+	//	br.ErrMsg = "批量写入群发邮件日志失败, Err: " + e.Error()
+	//	return
+	//}
 
 	// 修改推送状态
 	updateCols := []string{"EmailState", "ModifyTime"}
@@ -1499,17 +1508,19 @@ func (this *EnglishReportEmailController) Resend() {
 		r.ReportContent = reportInfo.Overview
 		r.ReportShareLink = l
 		r.ReportTime = t
-		sendData = append(sendData, r)
-
-		// 日志
-		logData = append(logData, &models.EnglishReportEmailLog{
+		logItem := &models.EnglishReportEmailLog{
 			ReportId:   reportInfo.Id,
 			EmailId:    emails[i].Id,
 			Email:      emails[i].Email,
 			Source:     models.EnglishReportEmailLogSourceAli,
 			SendStatus: models.EnglishReportEmailLogStatusIng,
 			CreateTime: nowTime,
-		})
+		}
+		r.EmailLog = logItem
+		sendData = append(sendData, r)
+
+		// 日志
+		logData = append(logData, logItem)
 	}
 
 	// 标记原有日志为已删除
@@ -1522,11 +1533,12 @@ func (this *EnglishReportEmailController) Resend() {
 	}
 
 	// 写入新的日志
-	emailLog := new(models.EnglishReportEmailLog)
-	if e = emailLog.InsertMulti(logData); e != nil {
-		br.Msg = "操作失败"
-		br.ErrMsg = "批量写入群发邮件日志失败, Err: " + e.Error()
-		return
+	for _, v := range logData {
+		if e = v.Create(); e != nil {
+			br.Msg = "操作失败"
+			br.ErrMsg = "写入群发邮件日志失败, Err: " + e.Error()
+			return
+		}
 	}
 
 	// 群发邮件
@@ -1810,10 +1822,7 @@ func (this *EnglishReportEmailController) VideoSend() {
 		r.ReportContent = overview
 		r.ReportShareLink = l
 		r.ReportTime = t
-		sendData = append(sendData, r)
-
-		// 日志
-		logData = append(logData, &models.EnglishReportEmailLog{
+		logItem := &models.EnglishReportEmailLog{
 			ReportId:   videoInfo.Id,
 			ReportType: 1,
 			EmailId:    emails[i].Id,
@@ -1821,7 +1830,12 @@ func (this *EnglishReportEmailController) VideoSend() {
 			Source:     models.EnglishReportEmailLogSourceAli,
 			SendStatus: models.EnglishReportEmailLogStatusIng,
 			CreateTime: nowTime,
-		})
+		}
+		r.EmailLog = logItem
+		sendData = append(sendData, r)
+
+		// 日志
+		logData = append(logData, logItem)
 	}
 	if len(sendData) == 0 {
 		br.Msg = "无邮件可推送"
@@ -1829,11 +1843,12 @@ func (this *EnglishReportEmailController) VideoSend() {
 	}
 
 	// 写入日志
-	emailLog := new(models.EnglishReportEmailLog)
-	if e = emailLog.InsertMulti(logData); e != nil {
-		br.Msg = "操作失败"
-		br.ErrMsg = "批量写入群发邮件日志失败, Err: " + e.Error()
-		return
+	for _, v := range logData {
+		if e = v.Create(); e != nil {
+			br.Msg = "操作失败"
+			br.ErrMsg = "写入群发邮件日志失败, Err: " + e.Error()
+			return
+		}
 	}
 
 	// 修改推送状态
@@ -2040,10 +2055,7 @@ func (this *EnglishReportEmailController) VideoResend() {
 		r.ReportContent = reportInfo.Overview
 		r.ReportShareLink = l
 		r.ReportTime = t
-		sendData = append(sendData, r)
-
-		// 日志
-		logData = append(logData, &models.EnglishReportEmailLog{
+		logItem := &models.EnglishReportEmailLog{
 			ReportId:   reportInfo.Id,
 			ReportType: 1,
 			EmailId:    emails[i].Id,
@@ -2051,7 +2063,12 @@ func (this *EnglishReportEmailController) VideoResend() {
 			Source:     models.EnglishReportEmailLogSourceAli,
 			SendStatus: models.EnglishReportEmailLogStatusIng,
 			CreateTime: nowTime,
-		})
+		}
+		r.EmailLog = logItem
+		sendData = append(sendData, r)
+
+		// 日志
+		logData = append(logData, logItem)
 	}
 
 	// 标记原有日志为已删除
@@ -2064,11 +2081,12 @@ func (this *EnglishReportEmailController) VideoResend() {
 	}
 
 	// 写入新的日志
-	emailLog := new(models.EnglishReportEmailLog)
-	if e = emailLog.InsertMulti(logData); e != nil {
-		br.Msg = "操作失败"
-		br.ErrMsg = "批量写入群发邮件日志失败, Err: " + e.Error()
-		return
+	for _, v := range logData {
+		if e = v.Create(); e != nil {
+			br.Msg = "操作失败"
+			br.ErrMsg = "写入群发邮件日志失败, Err: " + e.Error()
+			return
+		}
 	}
 
 	// 群发邮件

+ 63 - 139
controllers/english_report/report.go

@@ -16,7 +16,6 @@ import (
 	"html"
 	"strconv"
 	"strings"
-	"sync"
 	"time"
 )
 
@@ -461,143 +460,71 @@ func (this *EnglishReportController) ListReport() {
 			return
 		}
 	}
-	// 未群发邮件(包含推送邮件失败的)
-	if emailState == 1 {
-		failIds, e := models.GetHasFailEmailLogReportIds()
-		if e != nil {
-			br.Msg = "获取失败"
-			br.ErrMsg = "获取存在邮件推送失败记录的英文报告IDs失败, Err:" + e.Error()
-			return
-		}
-		condition += ` AND email_state = 0`
-		if len(failIds) > 0 {
-			condition += ` OR id IN (` + utils.GetOrmInReplace(len(failIds)) + `)`
-			pars = append(pars, failIds)
-		}
-	}
-	// 已群发邮件
-	if emailState == 2 {
-		successIds, e := models.GetSuccessEmailLogReportIds()
-		if e != nil {
-			br.Msg = "获取失败"
-			br.ErrMsg = "获取邮件推送记录均为成功的英文报告IDs失败, Err:" + e.Error()
-			return
+
+	// 群发邮件状态筛选
+	{
+		// 未群发邮件(包含推送邮件失败的)
+		if emailState == 1 {
+			condition += ` AND email_state = 0 AND email_has_fail = 1`
 		}
-		condition += ` AND email_state = 1`
-		if len(successIds) > 0 {
-			condition += ` AND id IN (` + utils.GetOrmInReplace(len(successIds)) + `)`
-			pars = append(pars, successIds)
+		// 已群发邮件
+		if emailState == 2 {
+			condition += ` AND email_state = 1 AND email_has_fail = 0`
 		}
 	}
 
-	var total int
-	var errCount, errList, errOther error
 	var authOk bool
-	list := make([]*models.EnglishReportList, 0)
-	failMap := make(map[int]bool, 0)    // 有群发失败记录的研报
 	adminMap := make(map[int]string, 0) // 编辑中的研究员姓名
 
-	wg := sync.WaitGroup{}
-	wg.Add(3)
-
-	// 列表总数
-	go func() {
-		defer func() {
-			wg.Done()
-		}()
-
-		t, e := models.GetEnglishReportListCount(condition, pars, companyType)
-		if e != nil {
-			errCount = fmt.Errorf("获取英文研报Count失败, Err: %s", e.Error())
-			return
-		}
-		total = t
-	}()
-
-	// 列表数据
-	go func() {
-		defer func() {
-			wg.Done()
-		}()
-
-		// 限制一下富文本字段, 列表用不到
-		fieldArr := []string{
-			"id", "add_type", "classify_id_first", "classify_name_first", "classify_id_second", "classify_name_second", "title", "abstract", "author",
-			"frequency", "create_time", "modify_time", "state", "publish_time", "pre_publish_time", "stage", "msg_is_send", "report_code", "pv", "share_url",
-			"pv_email", "email_state", "from_report_id", "key_takeaways", "admin_id", "admin_real_name", "approve_time",
-		}
-		items, e := models.GetEnglishReportList(condition, pars, companyType, startSize, pageSize, fieldArr)
-		if e != nil {
-			errList = fmt.Errorf("获取英文研报列表失败, Err: %s", e.Error())
-			return
-		}
-		list = items
-	}()
-
-	// 群发权限/失败记录
-	go func() {
-		defer func() {
-			wg.Done()
-		}()
-
-		// 获取邮件配置-是否有权限群发
-		conf := new(models.EnglishReportEmailConf)
-		authKey := "english_report_email_conf"
-		confAuth, e := company.GetConfigDetailByCode(authKey)
-		if e != nil {
-			errOther = fmt.Errorf("获取群发邮件权限失败, Err: %s", e.Error())
-			return
-		}
-		if confAuth.ConfigValue == "" {
-			errOther = fmt.Errorf("群发邮件配置为空")
-			return
-		}
-		if e := json.Unmarshal([]byte(confAuth.ConfigValue), &conf); e != nil {
-			errOther = fmt.Errorf("群发邮件配置有误")
-			return
-		}
-		authArr := strings.Split(conf.SendAuthGroup, ",")
-		if utils.InArrayByStr(authArr, sysUser.RoleTypeCode) {
-			authOk = true
-		}
-
-		// 是否有群发邮件失败的记录,标记红点
-		failList, e := models.GetEnglishReportEmailLogFailList(0)
-		if e != nil {
-			errOther = fmt.Errorf("获取群发邮件记录失败, Err: %s", e.Error())
-			return
-		}
-		for i := range failList {
-			failMap[failList[i].ReportId] = true
-		}
+	total, e := models.GetEnglishReportListCount(condition, pars, companyType)
+	if e != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取英文研报Count失败, Err: " + e.Error()
+		return
+	}
 
-		// 获取admin, 用于匹配编辑中的研究员姓名
-		admins, e := system.GetSysAdminList("", make([]interface{}, 0), []string{"admin_id", "real_name"}, "")
-		if e != nil {
-			errOther = fmt.Errorf("获取系统用户列表失败, Err: %s", e.Error())
-			return
-		}
-		for _, a := range admins {
-			adminMap[a.AdminId] = a.RealName
-		}
-	}()
-	wg.Wait()
+	list, e := models.GetEnglishReportList(condition, pars, companyType, startSize, pageSize, []string{})
+	if e != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取英文研报列表失败, Err: " + e.Error()
+		return
+	}
 
-	if errCount != nil {
+	// 获取邮件配置-是否有权限群发
+	conf := new(models.EnglishReportEmailConf)
+	authKey := "english_report_email_conf"
+	confAuth, e := company.GetConfigDetailByCode(authKey)
+	if e != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取群发邮件权限失败, Err: " + e.Error()
+		return
+	}
+	if confAuth.ConfigValue == "" {
 		br.Msg = "获取失败"
-		br.ErrMsg = errCount.Error()
+		br.ErrMsg = "群发邮件配置为空"
 		return
 	}
-	if errList != nil {
+	if e = json.Unmarshal([]byte(confAuth.ConfigValue), &conf); e != nil {
 		br.Msg = "获取失败"
-		br.ErrMsg = errList.Error()
+		br.ErrMsg = "群发邮件配置有误, Err: " + e.Error()
 		return
 	}
-	if errOther != nil {
+	authArr := strings.Split(conf.SendAuthGroup, ",")
+	if utils.InArrayByStr(authArr, sysUser.RoleTypeCode) {
+		authOk = true
+	}
+
+	// 获取admin, 用于匹配编辑中的研究员姓名
+	admins, e := system.GetSysAdminList("", make([]interface{}, 0), []string{"admin_id", "real_name"}, "")
+	if e != nil {
 		br.Msg = "获取失败"
-		br.ErrMsg = errOther.Error()
+		br.ErrMsg = "获取系统用户列表失败, Err: " + e.Error()
 		return
 	}
+	for _, a := range admins {
+		adminMap[a.AdminId] = a.RealName
+	}
+
 	// 查询分类信息
 	var classifyIdSecondSlice []int
 	for _, item := range list {
@@ -615,21 +542,17 @@ func (this *EnglishReportController) ListReport() {
 			classifyNameMap[v.Id] = v
 		}
 	}
-	for _, item := range list {
-		if item.State == 2 {
-			item.ShareUrl = "https://share.hzinsights.com/reportEn?code=" + item.ReportCode
-		}
-		item.EmailAuth = authOk
-		item.EmailHasFail = failMap[item.Id]
-
-		// 邮箱PV大于0的时候, 不展示最初版本的PV
-		if item.PvEmail > 0 {
-			item.Pv = 0
+	respList := make([]*models.EnglishReportList, 0)
+	for _, v := range list {
+		t := models.FormatEnglishReport2ListItem(v)
+		if v.State == 2 {
+			t.ShareUrl = "https://share.hzinsights.com/reportEn?code=" + v.ReportCode
 		}
+		t.EmailAuth = authOk
 
 		// 报告是否正在编辑中
 		var opUser models.MarkReportItem
-		key := fmt.Sprint(`crm:enReport:edit:`, item.Id)
+		key := fmt.Sprint(`crm:enReport:edit:`, v.Id)
 		opUserId, e := utils.Rc.RedisInt(key)
 		if e != nil {
 			str, te := utils.Rc.RedisString(key)
@@ -651,27 +574,28 @@ func (this *EnglishReportController) ListReport() {
 			ret.Editor = editor
 		}
 		if ret.Status == 0 {
-			item.CanEdit = true
+			t.CanEdit = true
 		} else {
-			item.Editor = ret.Editor
+			t.Editor = ret.Editor
 		}
 
 		//处理分类名
-		if n, ok := classifyNameMap[item.ClassifyIdSecond]; ok {
+		if n, ok := classifyNameMap[v.ClassifyIdSecond]; ok {
 			if n.RootId == 0 {
-				item.FullClassifyName = strings.Join([]string{n.ParentName, n.ClassifyName}, "/")
+				t.FullClassifyName = strings.Join([]string{n.ParentName, n.ClassifyName}, "/")
 			} else {
-				item.FullClassifyName = strings.Join([]string{n.RootName, n.ParentName, n.ClassifyName}, "/")
+				t.FullClassifyName = strings.Join([]string{n.RootName, n.ParentName, n.ClassifyName}, "/")
 			}
-			item.ClassifyIdRoot = n.RootId
-			item.ClassifyNameRoot = n.RootName
+			t.ClassifyIdRoot = n.RootId
+			t.ClassifyNameRoot = n.RootName
 		}
+		respList = append(respList, t)
 	}
 
 	page := paging.GetPaging(currentIndex, pageSize, total)
 	resp := new(models.EnglishReportListResp)
 	resp.Paging = page
-	resp.List = list
+	resp.List = respList
 	br.Ret = 200
 	br.Success = true
 	br.Msg = "获取成功"

+ 54 - 1
models/english_report.go

@@ -44,6 +44,7 @@ type EnglishReport struct {
 	AdminRealName      string    `description:"创建者姓名"`
 	ApproveTime        time.Time `description:"审批时间"`
 	ApproveId          int       `description:"审批ID"`
+	EmailHasFail       int       `description:"是否存在邮件发送失败的记录: 0-否; 1-是"`
 }
 
 func GetEnglishReportStage(classifyIdFirst, classifyIdSecond int) (count int, err error) {
@@ -292,7 +293,7 @@ func GetEnglishReportListCount(condition string, pars []interface{}, companyType
 	return
 }
 
-func GetEnglishReportList(condition string, pars []interface{}, companyType string, startSize, pageSize int, fieldArr []string) (items []*EnglishReportList, err error) {
+func GetEnglishReportList(condition string, pars []interface{}, companyType string, startSize, pageSize int, fieldArr []string) (items []*EnglishReport, err error) {
 	o := orm.NewOrmUsingDB("rddp")
 	//产品权限
 	companyTypeSqlStr := ``
@@ -913,3 +914,55 @@ func (classifyInfo *EnglishClassify) SetEnabled(id, enabled int) (err error) {
 	}
 	return
 }
+
+func FormatEnglishReport2ListItem(origin *EnglishReport) (item *EnglishReportList) {
+	if origin == nil {
+		return
+	}
+	item = new(EnglishReportList)
+	item.Id = origin.Id
+	item.AddType = origin.AddType
+	item.ClassifyIdFirst = origin.ClassifyIdFirst
+	item.ClassifyNameFirst = origin.ClassifyNameFirst
+	item.ClassifyIdSecond = origin.ClassifyIdSecond
+	item.ClassifyNameSecond = origin.ClassifyNameSecond
+	item.Title = origin.Title
+	item.Abstract = origin.Abstract
+	item.Author = origin.Author
+	item.Frequency = origin.Frequency
+	item.CreateTime = origin.CreateTime
+	item.ModifyTime = origin.ModifyTime
+	item.State = origin.State
+	item.PublishTime = utils.TimeTransferString(utils.FormatDateTime, origin.PublishTime)
+	item.PrePublishTime = utils.TimeTransferString(utils.FormatDateTime, origin.PrePublishTime)
+	item.Stage = origin.Stage
+	//item.Content = origin.Content
+	item.VideoUrl = origin.VideoUrl
+	item.VideoName = origin.VideoName
+	item.VideoPlaySeconds = origin.VideoPlaySeconds
+	item.ContentSub = origin.ContentSub
+	item.ReportCode = origin.ReportCode
+	item.Pv = origin.Pv
+	item.PvEmail = origin.PvEmail
+	// 邮箱PV大于0的时候, 不展示最初版本的PV
+	if item.PvEmail > 0 {
+		item.Pv = 0
+	}
+	item.EmailState = origin.EmailState
+	if origin.EmailHasFail == 1 {
+		item.EmailHasFail = true
+	}
+	item.FromReportId = origin.FromReportId
+	item.AdminId = origin.AdminId
+	item.AdminRealName = origin.AdminRealName
+	item.ApproveTime = utils.TimeTransferString(utils.FormatDateTime, origin.ApproveTime)
+	return
+}
+
+// UpdateEnglishReportEmailHasFail 标记报告邮件发送失败
+func UpdateEnglishReportEmailHasFail(reportId int) (err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	sql := `UPDATE english_report SET email_has_fail = 1 WHERE id = ?`
+	_, err = o.Raw(sql, reportId).Exec()
+	return
+}

+ 26 - 15
models/english_report_email_log.go

@@ -30,7 +30,7 @@ type EnglishReportEmailLog struct {
 	Source       int       `description:"服务商:1-阿里云;2-腾讯云"`
 	IsDeleted    int       `description:"是否已删除: 0-正常; 1-已删除"`
 	CallbackData string    `description:"回调信息"`
-	ErrMsg       string    `description:"错误信息(Result/CallbackData里面的取起来麻烦=_=!)"`
+	ErrMsg       string    `description:"错误信息"`
 }
 
 func (item *EnglishReportEmailLog) TableName() string {
@@ -39,7 +39,12 @@ func (item *EnglishReportEmailLog) TableName() string {
 
 func (item *EnglishReportEmailLog) Create() (err error) {
 	o := orm.NewOrmUsingDB("rddp")
-	_, err = o.Insert(item)
+	id, e := o.Insert(item)
+	if e != nil {
+		err = e
+		return
+	}
+	item.Id = int(id)
 	return
 }
 
@@ -113,8 +118,12 @@ func GetEnglishReportEmailLogById(id int) (item *EnglishReportEmailLog, err erro
 
 // DeleteEnglishReportEmailLogByIds IDs删除日志
 func DeleteEnglishReportEmailLogByIds(logIds []int) (err error) {
+	if len(logIds) == 0 {
+		return
+	}
 	o := orm.NewOrmUsingDB("rddp")
-	sql := `UPDATE english_report_email_log SET is_deleted = 1 WHERE id IN (` + utils.GetOrmInReplace(len(logIds)) + `)`
+	sql := `DELETE FROM english_report_email_log WHERE id IN (` + utils.GetOrmInReplace(len(logIds)) + `)`
+	//sql := `UPDATE english_report_email_log SET is_deleted = 1 WHERE id IN (` + utils.GetOrmInReplace(len(logIds)) + `)`
 	_, err = o.Raw(sql, logIds).Exec()
 	return
 }
@@ -143,18 +152,20 @@ func GetEnglishReportEmailLog(condition string, pars []interface{}) (item *Engli
 	return
 }
 
-// GetHasFailEmailLogReportIds 获取存在邮件推送失败记录的英文报告IDs
-func GetHasFailEmailLogReportIds() (reportIds []int, err error) {
+func (item *EnglishReportEmailLog) MultiUpdateResult(items []*EnglishReportEmailLog) (err error) {
 	o := orm.NewOrmUsingDB("rddp")
-	sql := `SELECT DISTINCT report_id FROM english_report_email_log WHERE is_deleted = 0 AND send_status = 0`
-	_, err = o.Raw(sql).QueryRows(&reportIds)
-	return
-}
-
-// GetSuccessEmailLogReportIds 获取邮件推送记录均为成功的英文报告IDs
-func GetSuccessEmailLogReportIds() (reportIds []int, err error) {
-	o := orm.NewOrmUsingDB("rddp")
-	sql := `SELECT DISTINCT report_id FROM english_report_email_log WHERE is_deleted = 0 AND (send_status != 0 AND send_status != -1)`
-	_, err = o.Raw(sql).QueryRows(&reportIds)
+	p, err := o.Raw("UPDATE english_report_email_log SET send_data = ?, result = ?, send_status = ?, err_msg = ? WHERE id = ?").Prepare()
+	if err != nil {
+		return
+	}
+	defer func() {
+		_ = p.Close()
+	}()
+	for _, v := range items {
+		_, err = p.Exec(v.SendData, v.Result, v.SendStatus, v.ErrMsg, v.Id)
+		if err != nil {
+			return
+		}
+	}
 	return
 }

+ 2 - 2
services/aliyun_email.go

@@ -111,10 +111,10 @@ func (em *AliyunEmail) BatchSendEmail(list []*EnglishReportSendEmailRequest) (re
 	}
 
 	// sendSingleMail接口有QPS100的限制, 保险起见每秒只请求50次接口
-	max := 50
+	secondMax := 50
 	c := 0
 	for i := range list {
-		if c >= max {
+		if c >= secondMax {
 			time.Sleep(time.Second)
 			c = 0
 		}

+ 88 - 68
services/english_report.go

@@ -78,17 +78,18 @@ type IEnglishEmailSend interface {
 
 // EnglishReportSendEmailRequest 英文研报-推送邮件请求体
 type EnglishReportSendEmailRequest struct {
-	ReportId        int    `description:"英文报告ID"`
-	EmailId         int    `description:"邮箱ID"`
-	Email           string `description:"邮箱地址"`
-	Subject         string `description:"邮件主题"`
-	FromAlias       string `description:"发信人昵称"`
-	ReportTitle     string `description:"报告标题"`
-	ReportAbstract  string `description:"报告摘要"`
-	ReportContent   string `description:"报告内容"`
-	ReportShareLink string `description:"报告分享链接"`
-	ReportTime      string `description:"报告时间"`
-	HtmlBody        string `description:"模板内容主体"`
+	ReportId        int                           `description:"英文报告ID"`
+	EmailId         int                           `description:"邮箱ID"`
+	Email           string                        `description:"邮箱地址"`
+	Subject         string                        `description:"邮件主题"`
+	FromAlias       string                        `description:"发信人昵称"`
+	ReportTitle     string                        `description:"报告标题"`
+	ReportAbstract  string                        `description:"报告摘要"`
+	ReportContent   string                        `description:"报告内容"`
+	ReportShareLink string                        `description:"报告分享链接"`
+	ReportTime      string                        `description:"报告时间"`
+	HtmlBody        string                        `description:"模板内容主体"`
+	EmailLog        *models.EnglishReportEmailLog `description:"日志记录"`
 }
 
 // EnglishReportSendEmailResult 英文研报-推送邮件响应体
@@ -106,15 +107,18 @@ type EnglishReportSendEmailResult struct {
 func BatchSendAliEnglishReportEmail(list []*EnglishReportSendEmailRequest) (err error) {
 	defer func() {
 		if err != nil {
-			go alarm_msg.SendAlarmMsg("阿里云群发英文研报邮件失败, Err: "+err.Error(), 3)
+			tips := fmt.Sprintf("阿里云群发英文研报邮件失败 err: %s\n", err.Error())
+			utils.FileLog.Info(tips)
+			fmt.Println(tips)
+			go alarm_msg.SendAlarmMsg(tips, 3)
 		}
 	}()
 	if len(list) == 0 {
 		return
 	}
 	requestMap := make(map[int]*EnglishReportSendEmailRequest, 0)
-	for i := range list {
-		requestMap[list[i].EmailId] = list[i]
+	for _, v := range list {
+		requestMap[v.EmailId] = v
 	}
 
 	// 请求阿里云接口批量推送
@@ -128,29 +132,30 @@ func BatchSendAliEnglishReportEmail(list []*EnglishReportSendEmailRequest) (err
 	// 返回的结果更新日志
 	resendList := make([]*EnglishReportSendEmailRequest, 0)
 	failLogIds := make([]int, 0)
-	updateCols := []string{"SendData", "Result", "SendStatus", "ErrMsg"}
-	for i := range resultList {
-		var cond string
-		var pars []interface{}
-		cond = ` AND is_deleted = 0 AND report_id = ? AND email_id = ? AND source = ? AND send_status = ?`
-		pars = append(pars, resultList[i].ReportId, resultList[i].EmailId, models.EnglishReportEmailLogSourceAli, models.EnglishReportEmailLogStatusIng)
-		l, e := models.GetEnglishReportEmailLog(cond, pars)
-		if e != nil {
+	updateLogs := make([]*models.EnglishReportEmailLog, 0)
+	for _, v := range resultList {
+		req := requestMap[v.EmailId]
+		if req == nil {
+			continue
+		}
+		l := req.EmailLog
+		if l == nil {
 			continue
 		}
-		l.SendData = resultList[i].SendData
-		l.Result = resultList[i].ResultData
-		if resultList[i].Ok {
+
+		//l.SendData = v.SendData
+		l.Result = v.ResultData
+		if v.Ok {
 			l.SendStatus = models.EnglishReportEmailLogStatusSuccess
 		} else {
 			l.SendStatus = models.EnglishReportEmailLogStatusFail
 			failLogIds = append(failLogIds, l.Id)
-			if requestMap[resultList[i].EmailId] != nil {
-				resendList = append(resendList, requestMap[resultList[i].EmailId])
+			if requestMap[v.EmailId] != nil {
+				resendList = append(resendList, requestMap[v.EmailId])
 			}
 			// 取出错误信息
 			r := new(AliyunEmailResult)
-			if e = json.Unmarshal([]byte(resultList[i].ResultData), &r); e != nil {
+			if e = json.Unmarshal([]byte(v.ResultData), &r); e != nil {
 				continue
 			}
 			rd := new(AliyunEmailResultData)
@@ -160,23 +165,40 @@ func BatchSendAliEnglishReportEmail(list []*EnglishReportSendEmailRequest) (err
 			}
 			l.ErrMsg = rd.Message
 		}
-		if e = l.Update(updateCols); e != nil {
-			continue
-		}
+		updateLogs = append(updateLogs, l)
+	}
+
+	// 更新日志
+	logOb := new(models.EnglishReportEmailLog)
+	if e = logOb.MultiUpdateResult(updateLogs); e != nil {
+		err = fmt.Errorf("批量更新日志信息失败, Err: " + e.Error())
+		return
 	}
 
 	// 推送失败的重新腾讯云, 若腾讯云也失败将不再自动重推, 用户手动去重推
 	if len(resendList) > 0 && len(failLogIds) > 0 {
-		_ = ResendTencentEnglishReportEmail(resendList, failLogIds)
+		hasFail, _ := ResendTencentEnglishReportEmail(resendList, failLogIds)
+		//fmt.Printf("hasFail: %v", hasFail)
+		// 存在发送失败则更新报告标识
+		if hasFail {
+			if e = models.UpdateEnglishReportEmailHasFail(list[0].ReportId); e != nil {
+				err = fmt.Errorf("UpdateEnglishReportEmailHasFail err: %s", e.Error())
+				return
+			}
+		}
 	}
 	return
 }
 
 // ResendTencentEnglishReportEmail 腾讯云邮件重新推送
-func ResendTencentEnglishReportEmail(resendList []*EnglishReportSendEmailRequest, failLogIds []int) (err error) {
+func ResendTencentEnglishReportEmail(resendList []*EnglishReportSendEmailRequest, failLogIds []int) (hasFail bool, err error) {
 	defer func() {
 		if err != nil {
-			go alarm_msg.SendAlarmMsg("腾讯云重发英文研报邮件失败, Err: "+err.Error(), 3)
+			hasFail = true
+			tips := fmt.Sprintf("腾讯云重发英文研报邮件失败 err: %s\n", err.Error())
+			utils.FileLog.Info(tips)
+			fmt.Println(tips)
+			go alarm_msg.SendAlarmMsg(tips, 3)
 		}
 	}()
 	if len(resendList) == 0 || len(failLogIds) == 0 {
@@ -194,61 +216,59 @@ func ResendTencentEnglishReportEmail(resendList []*EnglishReportSendEmailRequest
 	// 写入新的日志
 	nowTime := time.Now().Local()
 	logData := make([]*models.EnglishReportEmailLog, 0)
-	for i := range resendList {
-		sendByte, e := json.Marshal(resendList[i])
-		if e != nil {
-			err = errors.New("sendByte json.Marshal Err, Err: " + e.Error())
-			return
-		}
-
-		logData = append(logData, &models.EnglishReportEmailLog{
-			ReportId:   resendList[i].ReportId,
-			EmailId:    resendList[i].EmailId,
-			Email:      resendList[i].Email,
-			SendData:   string(sendByte),
+	logMap := make(map[int]*models.EnglishReportEmailLog, 0)
+	for _, v := range resendList {
+		logItem := &models.EnglishReportEmailLog{
+			ReportId:   v.ReportId,
+			EmailId:    v.EmailId,
+			Email:      v.Email,
 			Source:     models.EnglishReportEmailLogSourceTencent,
 			SendStatus: models.EnglishReportEmailLogStatusIng,
 			CreateTime: nowTime,
-		})
+		}
+		logData = append(logData, logItem)
+		logMap[v.EmailId] = logItem
 	}
-	emailLog := new(models.EnglishReportEmailLog)
-	if e := emailLog.InsertMulti(logData); e != nil {
-		err = errors.New("批量写入群发邮件日志失败, Err: " + e.Error())
-		return
+	for _, v := range logData {
+		if e := v.Create(); e != nil {
+			err = fmt.Errorf("写入群发邮件日志失败, err: %s", e.Error())
+			return
+		}
 	}
 
 	// 请求腾讯云
-	tecentEmail := new(TencentEmail)
-	resultList, e := tecentEmail.BatchSendEmail(resendList)
+	tencentEmail := new(TencentEmail)
+	resultList, e := tencentEmail.BatchSendEmail(resendList)
 	if e != nil {
 		err = e
 		return
 	}
-	updateCols := []string{"SendData", "Result", "SendStatus", "ErrMsg"}
-	for i := range resultList {
-		var cond string
-		var pars []interface{}
-		cond = ` AND is_deleted = 0 AND report_id = ? AND email_id = ? AND source = ? AND send_status = ?`
-		pars = append(pars, resultList[i].ReportId, resultList[i].EmailId, models.EnglishReportEmailLogSourceTencent, models.EnglishReportEmailLogStatusIng)
-		l, e := models.GetEnglishReportEmailLog(cond, pars)
-		if e != nil {
+	updateLogs := make([]*models.EnglishReportEmailLog, 0)
+	for _, v := range resultList {
+		l := logMap[v.EmailId]
+		if l == nil {
 			continue
 		}
-		l.SendData = resultList[i].SendData
-		l.Result = resultList[i].ResultData
-		if resultList[i].Ok {
+		l.Result = v.ResultData
+		if v.Ok {
 			l.SendStatus = models.EnglishReportEmailLogStatusSuccess
 		} else {
 			l.SendStatus = models.EnglishReportEmailLogStatusFail
 			r := new(TencentEmailResult)
-			if e = json.Unmarshal([]byte(resultList[i].ResultData), &r); e != nil {
+			if e = json.Unmarshal([]byte(v.ResultData), &r); e != nil {
 				continue
 			}
 			l.ErrMsg = r.Message
+			hasFail = true
 		}
-		if e = l.Update(updateCols); e != nil {
-			continue
-		}
+		updateLogs = append(updateLogs, l)
+	}
+
+	// 更新日志
+	logOb := new(models.EnglishReportEmailLog)
+	if e = logOb.MultiUpdateResult(updateLogs); e != nil {
+		err = fmt.Errorf("批量更新日志信息失败, Err: " + e.Error())
+		return
 	}
 	return
 }