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) }