Merge branch 'feat-IRONFANS-210-Robin' into release-20241017

This commit is contained in:
Leufolium 2024-10-17 20:24:15 +08:00
commit 50df41672d
18 changed files with 453 additions and 4 deletions

View File

@ -67,6 +67,8 @@ const (
AuditTaskCollectionReflectKey = "audit_task_collection_reflect"
StreamerFilterKey = "streamer_filter"
SmsSplitRatioKey = "sms_split_ratio"
RavenIQTestEmailConfigKey = "Raven_IQ_test_email_config"
OfficialEmailKey = "official_email"
)
// del_flag

View File

@ -321,3 +321,10 @@ const (
VideoManuallyReview_Passed = 1 //已复审通过
VideoManuallyReview_Rejected = 2 //已复审拒绝
)
// 邮件
const (
Email_Created = 0 // 已创建
Email_Success = 1 // 已发送
Email_Fail = 2 // 发送失败
)

View File

@ -246,6 +246,9 @@ var ErrCodeMsgMap = map[ErrCode]string{
ErrCodeVideoModerationSrvFail: "视频审核服务错误",
ErrCodeVideoModerationNotExist: "视频审核不存在",
ErrCodeEmailSrvFail: "电子邮件表服务错误",
ErrCodeEmailNotExist: "电子邮件表不存在",
ErrCodeRavenIQTestSrvFail: "瑞文智商测试表服务错误",
ErrCodeRavenIQTestNotExist: "瑞文智商测试表不存在",
ErrCodeRavenIQTestQuestionNotExist: "瑞文智商测试表题目不存在",
@ -584,6 +587,11 @@ const (
ErrCodeVideoModerationSrvFail ErrCode = -44001 // 视频审核服务错误
ErrCodeVideoModerationNotExist ErrCode = -44002 // 视频审核不存在
// Email: 45xxx
ErrCodeEmailSrvOk ErrCode = ErrCodeOk
ErrCodeEmailSrvFail ErrCode = -45001 // 电子邮件表服务错误
ErrCodeEmailNotExist ErrCode = -45002 // 电子邮件表不存在
// Media: 60xxx
ErrCodeMediaSrvOk ErrCode = ErrCodeOk
ErrCodeMediaSrvFail ErrCode = -60001 // 媒体服务错误

View File

@ -0,0 +1,20 @@
package proto
import (
"service/api/base"
"service/dbstruct"
)
// op 创建
type ApiCreateReq struct {
base.BaseRequest
*dbstruct.Email
}
type ApiCreateData struct {
}
type ApiCreateResp struct {
base.BaseResponse
Data *ApiCreateData `json:"data"`
}

View File

@ -0,0 +1,66 @@
package proto
import (
"service/api/base"
"service/dbstruct"
)
// op 创建
type OpCreateReq struct {
base.BaseRequest
*dbstruct.Email
}
type OpCreateData struct {
}
type OpCreateResp struct {
base.BaseResponse
Data *OpCreateData `json:"data"`
}
// op 删除
type OpDeleteReq struct {
base.BaseRequest
Id int64 `json:"id"`
}
type OpDeleteData struct {
}
type OpDeleteResp struct {
base.BaseResponse
Data *OpDeleteData `json:"data"`
}
// op 更新
type OpUpdateReq struct {
base.BaseRequest
*dbstruct.Email
}
type OpUpdateData struct {
}
type OpUpdateResp struct {
base.BaseResponse
Data *OpUpdateData `json:"data"`
}
// op 列表
type OpListReq struct {
base.BaseRequest
Offset int `json:"offset"`
Limit int `json:"limit"`
}
type OpListData struct {
List []*dbstruct.Email `json:"list"`
Offset int `json:"offset"`
More int `json:"more"`
}
type OpListResp struct {
base.BaseResponse
Data *OpListData `json:"data"`
}

View File

@ -0,0 +1,11 @@
package proto
import "service/library/validator"
func (p *ApiCreateReq) ProvideNotNullValue() (params []*validator.JsonParam) {
params = make([]*validator.JsonParam, 0)
params = append(params, validator.NewStringPtrParam("请输入您的邮箱地址!", p.Email.To))
return
}

View File

@ -0,0 +1,13 @@
package apollostruct
type EmailContentConfig struct {
Subject string `json:"subject"`
Text string `json:"text"`
}
type EmailInfoConfig struct {
Host string `json:"host"`
Port int `json:"port"`
Address string `json:"address"`
Password string `json:"password"`
}

View File

@ -0,0 +1,23 @@
package controller
import (
"service/api/errcode"
emailproto "service/api/proto/email/proto"
"service/app/mix/service"
"service/bizcommon/util"
"service/library/logger"
"github.com/gin-gonic/gin"
)
func ApiSendRavenIQTestResultAsEmail(ctx *gin.Context) {
req := ctx.MustGet("client_req").(*emailproto.ApiCreateReq)
ec := service.DefaultService.ApiSendRavenIQTestResultAsEmail(ctx, req)
if ec != errcode.ErrCodeEmailSrvOk {
logger.Error("ApiSendRavenIQTestResultAsEmail fail, req: %v, ec: %v", util.ToJson(req), ec)
ReplyErrCodeMsg(ctx, ec)
return
}
ReplyOk(ctx, nil)
}

View File

@ -30,6 +30,7 @@ import (
contact_customer_service_sessionproto "service/api/proto/contact_customer_service_session/proto"
daily_statementproto "service/api/proto/daily_statement/proto"
daily_statement_zone_info_proto "service/api/proto/daily_statement_zone_info/proto"
emailproto "service/api/proto/email/proto"
feedbackproto "service/api/proto/feedback/proto"
footprintproto "service/api/proto/footprint/proto"
hvyogoproto "service/api/proto/hvyogo/proto"
@ -290,6 +291,10 @@ func Init(r *gin.Engine) {
apiHvyogoGroup.POST("single_distribute", middleware.JSONParamValidator(hvyogoproto.ApiSingleDistributeReq{}), middleware.JwtAuthenticator(), middleware.RequestDecryptor(), ApiHvyogoSingleDistribute)
apiHvyogoGroup.POST("worker_update", middleware.JSONParamValidator(hvyogoproto.ApiWorkerUpdateReq{}), middleware.JwtAuthenticator(), middleware.RequestDecryptor(), ApiHvyogoWorkerUpdate)
// 电子邮件表
apiEmailGroup := r.Group("/api/email", PrepareToC())
apiEmailGroup.POST("send_Raven_IQ_test_result", middleware.JSONParamValidator(emailproto.ApiCreateReq{}), ApiSendRavenIQTestResultAsEmail)
// 瑞文智商测试表
apiRavenIQTestGroup := r.Group("/api/Raven_IQ_test", PrepareToC())
apiRavenIQTestGroup.POST("create", middleware.JSONParamValidator(Raven_IQ_testproto.ApiCreateReq{}), ApiCreateRavenIQTest)

View File

@ -28,6 +28,7 @@ import (
contact_customer_service_sessionproto "service/api/proto/contact_customer_service_session/proto"
daily_statementproto "service/api/proto/daily_statement/proto"
daily_statement_zone_info_proto "service/api/proto/daily_statement_zone_info/proto"
emailproto "service/api/proto/email/proto"
feedbackproto "service/api/proto/feedback/proto"
footprintproto "service/api/proto/footprint/proto"
imageaudittaskproto "service/api/proto/imageaudittask/proto"
@ -238,6 +239,9 @@ const (
COLSingleDistributeHis = "single_distribute_his"
COLSingleDistributeLock = "single_distribute_lock"
DBEmail = "email"
COLEmail = "email"
DBRavenIQTest = "Raven_IQ_test"
COLRavenIQTest = "Raven_IQ_test"
)
@ -621,6 +625,11 @@ func (m *Mongo) getColSingleDistributeLock() *qmgo.Collection {
return m.clientMix.Database(DBSingleDistributeHis).Collection(COLSingleDistributeLock)
}
// 电子邮件表表
func (m *Mongo) getColEmail() *qmgo.Collection {
return m.clientMix.Database(DBEmail).Collection(COLEmail)
}
// 瑞文智商测试表表
func (m *Mongo) getColRavenIQTest() *qmgo.Collection {
return m.clientMix.Database(DBRavenIQTest).Collection(COLRavenIQTest)
@ -6204,6 +6213,49 @@ func (m *Mongo) GetSingleDistributeHisById(ctx *gin.Context, id string) (*dbstru
return one, err
}
// 电子邮件表相关
func (m *Mongo) CreateEmail(ctx *gin.Context, email *dbstruct.Email) error {
col := m.getColEmail()
_, err := col.InsertOne(ctx, email)
return err
}
func (m *Mongo) UpdateEmail(ctx *gin.Context, email *dbstruct.Email) error {
col := m.getColEmail()
set := util.EntityToM(email)
set["ut"] = time.Now().Unix()
up := qmgo.M{
"$set": set,
}
err := col.UpdateId(ctx, email.Id, up)
return err
}
func (m *Mongo) DeleteEmail(ctx *gin.Context, id int64) error {
col := m.getColEmail()
update := qmgo.M{
"$set": qmgo.M{
"del_flag": 1,
},
}
err := col.UpdateId(ctx, id, update)
return err
}
func (m *Mongo) GetEmailList(ctx *gin.Context, req *emailproto.OpListReq) ([]*dbstruct.Email, error) {
list := make([]*dbstruct.Email, 0)
col := m.getColEmail()
query := qmgo.M{
"del_flag": 0,
}
err := col.Find(ctx, query).Sort("-ct").Skip(int64(req.Offset)).Limit(int64(req.Limit)).All(&list)
if err == qmgo.ErrNoSuchDocuments {
err = nil
return list, err
}
return list, err
}
// 瑞文智商测试表相关
func (m *Mongo) CreateRavenIQTest(ctx *gin.Context, Raven_IQ_test *dbstruct.RavenIQTest) error {
col := m.getColRavenIQTest()

View File

@ -15,6 +15,7 @@ import (
appconfigproto "service/api/proto/app_config/proto"
contact_customer_service_proto "service/api/proto/contact_customer_service/proto"
contact_customer_service_sessionproto "service/api/proto/contact_customer_service_session/proto"
emailproto "service/api/proto/email/proto"
feedbackproto "service/api/proto/feedback/proto"
hvyogoproto "service/api/proto/hvyogo/proto"
loginproto "service/api/proto/login/proto"
@ -47,7 +48,9 @@ import (
"service/bizcommon/util"
"service/dbstruct"
"service/library/apollo"
"service/library/email"
"service/library/logger"
"service/library/mediafiller"
"service/library/redis"
interceptor "service/library/taginterceptor"
"strconv"
@ -4092,6 +4095,75 @@ func (s *Service) ApiHvyogoWorkerUpdate(ctx *gin.Context, req *hvyogoproto.ApiWo
return
}
// Email
func (s *Service) ApiSendRavenIQTestResultAsEmail(ctx *gin.Context, req *emailproto.ApiCreateReq) (ec errcode.ErrCode) {
ec = errcode.ErrCodeEmailSrvOk
emailContentCfg := apollostruct.EmailContentConfig{}
err := apollo.GetJson(consts.RavenIQTestEmailConfigKey, &emailContentCfg, apollo.ApolloOpts().SetNamespace("application"))
if err != nil {
logger.Error("Apollo read failed : %v", err)
ec = errcode.ErrCodeApolloReadFail
return
}
emailInfoCfg := apollostruct.EmailInfoConfig{}
err = apollo.GetJson(consts.OfficialEmailKey, &emailInfoCfg, apollo.ApolloOpts().SetNamespace("application"))
if err != nil {
logger.Error("Apollo read failed : %v", err)
ec = errcode.ErrCodeApolloReadFail
return
}
req.Email.Mid = goproto.Int64(req.BaseRequest.Mid)
req.Email.From = goproto.String(emailInfoCfg.Address)
req.Email.Subject = goproto.String(emailContentCfg.Subject)
req.Email.Text = goproto.String(emailContentCfg.Text)
req.Email.Status = goproto.Int64(consts.Email_Created)
err = _DefaultEmail.OpCreate(ctx, &emailproto.OpCreateReq{
BaseRequest: req.BaseRequest,
Email: req.Email,
})
if err != nil {
logger.Error("OpCreate fail, req: %v, err: %v", util.ToJson(req), err)
ec = errcode.ErrCodeEmailSrvFail
return
}
// 填充媒体获取资源
err = mediafiller.FillEntity(ctx, req.Email.MediaComponent)
if err != nil {
logger.Error("FillEntity fail, req: %v, err: %v", util.ToJson(req), err)
ec = errcode.ErrCodeMediaSrvFail
return
}
go func(eml *dbstruct.Email, emailInfoCfg apollostruct.EmailInfoConfig) {
err = email.SendRavenIQTestResult(eml, emailInfoCfg.Host, emailInfoCfg.Port, emailInfoCfg.Address, emailInfoCfg.Password)
if err != nil {
logger.Error("SendRavenIQTestResult fail, req: %v, err: %v", util.ToJson(req), err)
// 更新状态为失败
_DefaultEmail.OpUpdate(ctx, &emailproto.OpUpdateReq{
Email: &dbstruct.Email{
Id: req.Id,
Status: goproto.Int64(consts.Email_Fail),
},
})
return
}
// 更新状态为成功
_DefaultEmail.OpUpdate(ctx, &emailproto.OpUpdateReq{
Email: &dbstruct.Email{
Id: req.Id,
Status: goproto.Int64(consts.Email_Success),
},
})
}(req.Email, emailInfoCfg)
return
}
// RavenIQTest
func (s *Service) ApiCreateRavenIQTest(ctx *gin.Context, req *Raven_IQ_testproto.ApiCreateReq) (id int64, ec errcode.ErrCode) {
ec = errcode.ErrCodeRavenIQTestSrvOk

View File

@ -0,0 +1,65 @@
package logic
import (
"service/api/consts"
emailproto "service/api/proto/email/proto"
"service/app/mix/dao"
"service/dbstruct"
"service/library/idgenerator"
"service/library/logger"
"time"
"github.com/gin-gonic/gin"
goproto "google.golang.org/protobuf/proto"
)
type Email struct {
store *dao.Store
}
func NewEmail(store *dao.Store) (a *Email) {
a = &Email{
store: store,
}
return
}
func (p *Email) OpCreate(ctx *gin.Context, req *emailproto.OpCreateReq) error {
req.Email.Id = goproto.Int64(idgenerator.GenEmailId())
req.Email.Ct = goproto.Int64(time.Now().Unix())
req.Email.Ut = goproto.Int64(time.Now().Unix())
req.Email.DelFlag = goproto.Int64(consts.Exist)
err := p.store.CreateEmail(ctx, req.Email)
if err != nil {
logger.Error("CreateEmail fail, err: %v", err)
return err
}
return nil
}
func (p *Email) OpUpdate(ctx *gin.Context, req *emailproto.OpUpdateReq) error {
err := p.store.UpdateEmail(ctx, req.Email)
if err != nil {
logger.Error("UpdateEmail fail, err: %v", err)
return err
}
return nil
}
func (p *Email) OpDelete(ctx *gin.Context, id int64) error {
err := p.store.DeleteEmail(ctx, id)
if err != nil {
logger.Error("DeleteEmail fail, err: %v", err)
return err
}
return nil
}
func (p *Email) OpList(ctx *gin.Context, req *emailproto.OpListReq) ([]*dbstruct.Email, error) {
list, err := p.store.GetEmailList(ctx, req)
if err != nil {
logger.Error("GetEmailList fail, err: %v", err)
return make([]*dbstruct.Email, 0), err
}
return list, nil
}

View File

@ -150,6 +150,7 @@ var (
_DefaultWorkerId *logic.WorkerId
_DefaultSingleDistributeHis *logic.SingleDistributeHis
_DefaultAutoResponseCreateTimes *logic.AutoResponseCreateTimes
_DefaultEmail *logic.Email
_DefaultRavenIQTest *logic.RavenIQTest
_DefaultStreamerDecrtByEs *logic.StreamerDecrtByEs
@ -254,6 +255,7 @@ func (s *Service) Init(c any) (err error) {
_DefaultWorkerId = logic.NewWorkerId(store)
_DefaultSingleDistributeHis = logic.NewSingleDistributeHis(store)
_DefaultAutoResponseCreateTimes = logic.NewAutoResponseCreateTimes(store)
_DefaultEmail = logic.NewEmail(store)
_DefaultRavenIQTest = logic.NewRavenIQTest(store)
_DefaultVas = logic.NewVas(store, _DefaultStreamer, _DefaultAccount, _DefaultZone, _DefaultZoneThirdPartner, _DefaultZoneCollaborator)

View File

@ -9,10 +9,10 @@ import (
func main() {
genSource := &generator.GenSource{
EntityName: "RavenIQTest",
ModuleName: "Raven_IQ_test",
EntityCNName: "瑞文智商测试表",
ErrCodeSeq: "101",
EntityName: "Email",
ModuleName: "email",
EntityCNName: "电子邮件表",
ErrCodeSeq: "45",
}
generator.CreateFileDirectory(genSource)

43
dbstruct/email.go Normal file
View File

@ -0,0 +1,43 @@
package dbstruct
type Email struct {
Id *int64 `json:"id" bson:"_id"` // 电子邮件表id
Mid *int64 `json:"mid" bson:"mid"` // 用户id
From *string `json:"from" bson:"from"` // 发送人邮箱
To *string `json:"to" bson:"to"` // 收件人邮箱
Subject *string `json:"subject" bson:"subject"` // 标题
Text *string `json:"text" bson:"text"` // 文本
MediaComponent *MediaComponent `json:"media_component" bson:"media_component"` // 媒体
Status *int64 `json:"status" bson:"status"` // 状态
Ct *int64 `json:"ct" bson:"ct"` // 创建时间
Ut *int64 `json:"ut" bson:"ut"` // 更新时间
DelFlag *int64 `json:"del_flag" bson:"del_flag"` // 删除标记
}
func (p *Email) GetFrom() string {
if p == nil || p.From == nil {
return ""
}
return *p.From
}
func (p *Email) GetTo() string {
if p == nil || p.To == nil {
return ""
}
return *p.To
}
func (p *Email) GetSubject() string {
if p == nil || p.Subject == nil {
return ""
}
return *p.Subject
}
func (p *Email) GetText() string {
if p == nil || p.Text == nil {
return ""
}
return *p.Text
}

53
library/email/send.go Normal file
View File

@ -0,0 +1,53 @@
package email
import (
"fmt"
"io"
"net/http"
"service/dbstruct"
"service/library/logger"
"strings"
"gopkg.in/gomail.v2"
)
func SendRavenIQTestResult(mail *dbstruct.Email, host string, port int, address, password string) error {
url := mail.MediaComponent.Images[0].Urls[0]
format := mail.MediaComponent.Images[0].Fmt
body := &strings.Builder{}
h2 := fmt.Sprintf("<h2>%v</h2>", mail.GetText())
img := fmt.Sprintf("<img border=\"0\" src=\"%v\" alt=\"图片加载错误,请联系管理员\">", url)
body.WriteString(h2)
body.WriteString(img)
response, err := http.Get(url)
if err != nil {
return err
}
attach, err := io.ReadAll(response.Body)
response.Body.Close()
if err != nil {
return err
}
attachName := fmt.Sprintf("测评结果.%v", format[6:])
m := gomail.NewMessage()
m.SetHeader("From", mail.GetFrom())
m.SetHeader("To", mail.GetTo())
m.SetHeader("Subject", mail.GetSubject())
m.SetBody("text/html", body.String())
m.Attach(attachName, gomail.SetCopyFunc(func(w io.Writer) error { //设置邮件附件 第一个参数是附件名称 第二个参数是二进制文件流
_, err := w.Write(attach)
return err
}))
err = gomail.NewDialer(host, port, address, password).DialAndSend(m)
if err != nil {
logger.Error("Send Email Fail", err)
return err
}
return nil
}

View File

@ -56,6 +56,7 @@ const (
NodeYeepayRefund // node 易宝支付退款
NodeWorkerId // node 用户职业者id映射表
NodeSingleDistributeHis // node 慧用工下发打款历史表
NodeEmail // node 电子邮件表
)
func GenIdInt64(node int64) (int64, error) {
@ -273,3 +274,9 @@ func GenSingleDistributeHisId() string {
id, _ := GenIdString(NodeSingleDistributeHis)
return id
}
// email
func GenEmailId() int64 {
id, _ := GenIdInt64(NodeEmail)
return id
}