Files
web_hghl_server/app/service/questionnaireser/questionnaire.go
T
2026-10-26 16:28:14 +08:00

80 lines
2.3 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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)
}