80 lines
2.3 KiB
Go
80 lines
2.3 KiB
Go
package questionnaireser
|
||
|
||
import (
|
||
"context"
|
||
"fmt"
|
||
"time"
|
||
|
||
"videoweb/app/api/proto"
|
||
"videoweb/pub/common/enum/redisconst"
|
||
"videoweb/pub/common/log"
|
||
"videoweb/pub/common/srvdef"
|
||
"videoweb/pub/models/questionnairemod"
|
||
"videoweb/pub/redis"
|
||
|
||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||
)
|
||
|
||
const (
|
||
maxFiles = 3
|
||
)
|
||
|
||
// Submit 提交问卷(App端)
|
||
// ip:客户端真实 IP;req.UserId 为 0 表示匿名用户,仅按 IP 限流
|
||
func Submit(ctx context.Context, ip string, req *proto.QuestionnaireSubmitReq) *srvdef.SrvErr {
|
||
// IP 维度:同一 IP 每分钟只能提交一次
|
||
ipCount, err := redis.Incr(redisconst.QuestionnaireLimitIpKey(ip), redisconst.QuestionnaireLimitExpire)
|
||
if err != nil {
|
||
log.Error("问卷提交IP限频Redis异常", log.E(err))
|
||
}
|
||
if ipCount > 1 {
|
||
return srvdef.New(srvdef.ErrOperationTooFrequently, "user operation is too frequent", "提交太频繁,请稍后再试")
|
||
}
|
||
|
||
// 用户维度:登录用户(userId > 0)每分钟只能提交一次
|
||
if req.UserId > 0 {
|
||
userCount, err := redis.Incr(redisconst.QuestionnaireLimitUserKey(req.UserId), redisconst.QuestionnaireLimitExpire)
|
||
if err != nil {
|
||
log.Error("问卷提交用户限频Redis异常", log.E(err))
|
||
}
|
||
if userCount > 1 {
|
||
return srvdef.New(srvdef.ErrOperationTooFrequently, "user operation is too frequent", "提交太频繁,请稍后再试")
|
||
}
|
||
}
|
||
|
||
// 校验附件数量限制
|
||
fileCount := 0
|
||
if req.Attachments != nil && len(req.Attachments) > 0 {
|
||
fileCount = len(req.Attachments)
|
||
}
|
||
if fileCount > maxFiles {
|
||
return srvdef.New(srvdef.ErrParamError, fmt.Sprintf("文件不超过%d个", fileCount), "")
|
||
}
|
||
attachments := req.Attachments
|
||
if attachments == nil {
|
||
attachments = []questionnairemod.Attachment{}
|
||
}
|
||
|
||
now := time.Now()
|
||
doc := &questionnairemod.QuestionnaireModel{
|
||
Id: primitive.NewObjectID(),
|
||
UserId: req.UserId,
|
||
QuestionType: req.QuestionType,
|
||
Frequency: req.Frequency,
|
||
Province: req.Province,
|
||
City: req.City,
|
||
Operator: req.Operator,
|
||
NetworkType: req.NetworkType,
|
||
DeviceType: req.DeviceType,
|
||
DeviceModel: req.DeviceModel,
|
||
Description: req.Description,
|
||
Contact: req.Contact,
|
||
Status: questionnairemod.StatusPending,
|
||
Attachments: attachments,
|
||
CreatedAt: now,
|
||
UpdatedAt: now,
|
||
}
|
||
|
||
return questionnairemod.InsertOne(ctx, doc)
|
||
}
|