来源:hgdjnet-server 9bfbafe10d417deea959bd53117bc88a10e60a83 项目身份 HKDJ / JHA-216,独立官网仓库,Jenkins 守卫键 hkdjnet 测试目录 /server/hkdj_net,App/Web API 30331/30332 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
274 lines
8.1 KiB
Go
274 lines
8.1 KiB
Go
package srv_contactus
|
|
|
|
import (
|
|
"context"
|
|
"hkdj-web-server/pub/common/response"
|
|
"hkdj-web-server/pub/common/srvdef"
|
|
"hkdj-web-server/pub/models/contactusmod"
|
|
"hkdj-web-server/pub/models/usermod"
|
|
"hkdj-web-server/web/api/proto"
|
|
"regexp"
|
|
"strings"
|
|
"time"
|
|
|
|
"go.mongodb.org/mongo-driver/bson"
|
|
"go.mongodb.org/mongo-driver/mongo/options"
|
|
)
|
|
|
|
const (
|
|
// contactUsDefaultPageSize web端联系我们列表默认每页数量
|
|
contactUsDefaultPageSize int64 = 10
|
|
// contactUsMaxPageSize web端联系我们列表最大每页数量,避免单次请求拉取过多数据
|
|
contactUsMaxPageSize int64 = 100
|
|
)
|
|
|
|
var (
|
|
// contactUsWebProjection 只读取web联系我们列表需要展示的字段,减少MongoDB传输开销。
|
|
contactUsWebProjection = bson.D{
|
|
{Key: contactusmod.FN.ContactUs.Id, Value: 1},
|
|
{Key: contactusmod.FN.ContactUs.UserId, Value: 1},
|
|
{Key: contactusmod.FN.ContactUs.Email, Value: 1},
|
|
{Key: contactusmod.FN.ContactUs.QuestionType, Value: 1},
|
|
{Key: contactusmod.FN.ContactUs.Title, Value: 1},
|
|
{Key: contactusmod.FN.ContactUs.Content, Value: 1},
|
|
{Key: contactusmod.FN.ContactUs.Attachments, Value: 1},
|
|
{Key: contactusmod.FN.ContactUs.Status, Value: 1},
|
|
{Key: contactusmod.FN.ContactUs.Remark, Value: 1},
|
|
{Key: contactusmod.FN.ContactUs.CreatedAt, Value: 1},
|
|
{Key: contactusmod.FN.ContactUs.UpdatedAt, Value: 1},
|
|
}
|
|
|
|
// contactUsWebSort web端联系我们列表按创建时间倒序返回。
|
|
contactUsWebSort = bson.D{
|
|
{Key: contactusmod.FN.ContactUs.CreatedAt, Value: -1},
|
|
{Key: contactusmod.FN.ContactUs.Id, Value: -1},
|
|
}
|
|
)
|
|
|
|
// ListContactUs 分页查询联系我们列表
|
|
func ListContactUs(ctx context.Context, req *proto.ContactUsListReq) (*proto.ContactUsListPageResp, *srvdef.SrvErr) {
|
|
if req == nil {
|
|
return nil, srvdef.New(srvdef.ErrParamError, "", "")
|
|
}
|
|
filter, filterErr := buildContactUsListFilter(req)
|
|
if filterErr != nil {
|
|
return nil, filterErr
|
|
}
|
|
pageNum, pageSize := normalizeContactUsPage(req.PageNum, req.PageSize)
|
|
totalCount, err := contactusmod.CountContactUs(ctx, filter)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
resp := &proto.ContactUsListPageResp{
|
|
BasePageResp: response.BasePageResp{
|
|
TotalCount: totalCount,
|
|
PageSize: int(pageSize),
|
|
PageNum: int(pageNum),
|
|
List: make([]*proto.ContactUsListResp, 0),
|
|
},
|
|
}
|
|
if totalCount == 0 {
|
|
return resp, nil
|
|
}
|
|
list, err := contactusmod.FindManyContactUs(ctx, filter, options.Find().
|
|
SetProjection(contactUsWebProjection).
|
|
SetSort(contactUsWebSort).
|
|
SetSkip((pageNum-1)*pageSize).
|
|
SetLimit(pageSize))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
userNameMap, err := buildContactUsUserNameMap(ctx, list)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
resp.List = contactUsListToWebResp(list, userNameMap)
|
|
return resp, nil
|
|
}
|
|
|
|
// HandleContactUs 批量更新联系我们处理状态
|
|
func HandleContactUs(ctx context.Context, req *proto.ContactUsHandleReq) (*proto.ContactUsHandleResp, *srvdef.SrvErr) {
|
|
if req == nil || len(req.Ids) == 0 {
|
|
return nil, srvdef.New(srvdef.ErrParamError, "ids不能为空")
|
|
}
|
|
if req.Status != 0 && req.Status != 1 {
|
|
return nil, srvdef.New(srvdef.ErrParamError, "status无效")
|
|
}
|
|
ids, err := normalizeContactUsIds(req.Ids)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
matchedCount, modifiedCount, err := contactusmod.UpdateManyContactUsWithResult(ctx, bson.M{
|
|
contactusmod.FN.ContactUs.Id: bson.M{"$in": ids},
|
|
}, bson.M{
|
|
"$set": bson.M{
|
|
contactusmod.FN.ContactUs.Status: req.Status,
|
|
contactusmod.FN.ContactUs.Remark: strings.TrimSpace(req.Remark),
|
|
contactusmod.FN.ContactUs.UpdatedAt: time.Now(),
|
|
},
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if matchedCount == 0 {
|
|
return nil, srvdef.New(srvdef.ErrNoData, "", "")
|
|
}
|
|
return &proto.ContactUsHandleResp{
|
|
MatchedCount: matchedCount,
|
|
ModifiedCount: modifiedCount,
|
|
}, nil
|
|
}
|
|
|
|
// buildContactUsListFilter 构造web端联系我们列表查询条件
|
|
func buildContactUsListFilter(req *proto.ContactUsListReq) (bson.M, *srvdef.SrvErr) {
|
|
filter := bson.M{}
|
|
if req.UserId != nil && *req.UserId > 0 {
|
|
filter[contactusmod.FN.ContactUs.UserId] = *req.UserId
|
|
}
|
|
if email := strings.TrimSpace(req.Email); email != "" {
|
|
filter[contactusmod.FN.ContactUs.Email] = bson.M{"$regex": regexp.QuoteMeta(email)}
|
|
}
|
|
if req.Type != nil {
|
|
if !isValidContactUsType(*req.Type) {
|
|
return nil, srvdef.New(srvdef.ErrParamError, "type无效")
|
|
}
|
|
filter[contactusmod.FN.ContactUs.QuestionType] = *req.Type
|
|
}
|
|
if req.Status != nil {
|
|
if *req.Status != 0 && *req.Status != 1 {
|
|
return nil, srvdef.New(srvdef.ErrParamError, "status无效")
|
|
}
|
|
filter[contactusmod.FN.ContactUs.Status] = *req.Status
|
|
}
|
|
createdAt, err := buildContactUsTimeFilter(req.CreateStartTime, req.CreateEndTime)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if len(createdAt) > 0 {
|
|
filter[contactusmod.FN.ContactUs.CreatedAt] = createdAt
|
|
}
|
|
return filter, nil
|
|
}
|
|
|
|
// buildContactUsTimeFilter 按开始时间和结束时间构造createdAt范围查询
|
|
func buildContactUsTimeFilter(startTime, endTime string) (bson.M, *srvdef.SrvErr) {
|
|
filter := bson.M{}
|
|
startTime = strings.TrimSpace(startTime)
|
|
endTime = strings.TrimSpace(endTime)
|
|
if startTime != "" {
|
|
startAt, err := parseContactUsWebTime(startTime)
|
|
if err != nil {
|
|
return nil, srvdef.New(srvdef.ErrParamError, "createStartTime格式错误")
|
|
}
|
|
filter["$gte"] = startAt
|
|
}
|
|
if endTime != "" {
|
|
endAt, err := parseContactUsWebTime(endTime)
|
|
if err != nil {
|
|
return nil, srvdef.New(srvdef.ErrParamError, "createEndTime格式错误")
|
|
}
|
|
filter["$lte"] = endAt
|
|
}
|
|
return filter, nil
|
|
}
|
|
|
|
func parseContactUsWebTime(value string) (time.Time, error) {
|
|
return time.ParseInLocation("2006-01-02 15:04:05", value, time.Local)
|
|
}
|
|
|
|
func normalizeContactUsPage(pageNum, pageSize int64) (int64, int64) {
|
|
if pageNum <= 0 {
|
|
pageNum = 1
|
|
}
|
|
if pageSize <= 0 {
|
|
pageSize = contactUsDefaultPageSize
|
|
}
|
|
if pageSize > contactUsMaxPageSize {
|
|
pageSize = contactUsMaxPageSize
|
|
}
|
|
return pageNum, pageSize
|
|
}
|
|
|
|
func normalizeContactUsIds(rawIds []int64) ([]int64, *srvdef.SrvErr) {
|
|
ids := make([]int64, 0, len(rawIds))
|
|
seen := make(map[int64]struct{}, len(rawIds))
|
|
for _, id := range rawIds {
|
|
if id <= 0 {
|
|
return nil, srvdef.New(srvdef.ErrParamError, "ids包含无效id")
|
|
}
|
|
if _, ok := seen[id]; ok {
|
|
continue
|
|
}
|
|
seen[id] = struct{}{}
|
|
ids = append(ids, id)
|
|
}
|
|
if len(ids) == 0 {
|
|
return nil, srvdef.New(srvdef.ErrParamError, "ids不能为空")
|
|
}
|
|
return ids, nil
|
|
}
|
|
|
|
func isValidContactUsType(questionType int32) bool {
|
|
return questionType >= 1 && questionType <= 5
|
|
}
|
|
|
|
// buildContactUsUserNameMap 批量查询用户名称,避免列表转换时逐条查询用户。
|
|
func buildContactUsUserNameMap(ctx context.Context, list contactusmod.ContactUsList) (map[int64]string, *srvdef.SrvErr) {
|
|
userIds := make([]int64, 0, len(list))
|
|
seen := make(map[int64]struct{}, len(list))
|
|
for _, item := range list {
|
|
if item == nil || item.UserId <= 0 {
|
|
continue
|
|
}
|
|
if _, ok := seen[item.UserId]; ok {
|
|
continue
|
|
}
|
|
seen[item.UserId] = struct{}{}
|
|
userIds = append(userIds, item.UserId)
|
|
}
|
|
userNameMap := make(map[int64]string, len(userIds))
|
|
if len(userIds) == 0 {
|
|
return userNameMap, nil
|
|
}
|
|
users, err := usermod.FindManyUser(ctx, bson.M{
|
|
usermod.FN.User.Id: bson.M{"$in": userIds},
|
|
}, options.Find().SetProjection(bson.M{
|
|
usermod.FN.User.Id: 1,
|
|
usermod.FN.User.NickName: 1,
|
|
}))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
for _, user := range users {
|
|
if user != nil {
|
|
userNameMap[user.Id] = user.NickName
|
|
}
|
|
}
|
|
return userNameMap, nil
|
|
}
|
|
|
|
// contactUsListToWebResp 转换联系我们列表响应
|
|
func contactUsListToWebResp(list contactusmod.ContactUsList, userNameMap map[int64]string) []*proto.ContactUsListResp {
|
|
resp := make([]*proto.ContactUsListResp, 0, len(list))
|
|
for _, item := range list {
|
|
if item == nil {
|
|
continue
|
|
}
|
|
resp = append(resp, &proto.ContactUsListResp{
|
|
Id: item.Id,
|
|
UserId: item.UserId,
|
|
UserName: userNameMap[item.UserId],
|
|
Email: item.Email,
|
|
Type: item.QuestionType,
|
|
Title: item.Title,
|
|
Content: item.Content,
|
|
Attachments: item.Attachments,
|
|
Status: item.Status,
|
|
Remark: item.Remark,
|
|
CreatedAt: item.CreatedAt,
|
|
UpdatedAt: item.UpdatedAt,
|
|
})
|
|
}
|
|
return resp
|
|
}
|