Skip to content

Commit 94591f8

Browse files
committed
fix: 修复无法展示提案同意数量的问题
1 parent 489c1c4 commit 94591f8

File tree

16 files changed

+284
-170
lines changed

16 files changed

+284
-170
lines changed

api/handler/auth.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ import (
2929
// @Produce json
3030
// @Param body body dto.SignInReq true "SignInReq"
3131
// @Success 200 {object} dto.SignInResp
32-
// @Router /api/sign_in [post]
32+
// @Router /api/auth/sign_in [post]
3333
func SignIn(c *gin.Context) {
3434
var err error
3535
var req dto.SignInReq

api/handler/like.go

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,18 +23,24 @@ import (
2323
)
2424

2525
// ToggleLike godoc
26-
// @Summary 点赞或取消点赞
27-
// @Description 点赞或取消点赞
28-
// @Tags action
26+
// @Summary 点赞 / 取消点赞
27+
// @Description 对指定目标(提案或评论)进行点赞或取消点赞操作;若已点赞则取消,未点赞则新增
28+
// @Tags like
29+
// @Accept json
2930
// @Produce json
30-
// @Param id path string true "目标ID(提案/评论)"
31-
// @Success 200 {object} dto.ToggleLikeResp
32-
// @Router /api/action/like/{likeId} [post]
31+
// @Param likeId path string true "目标ID(提案ID或评论ID)"
32+
// @Param body body dto.ToggleLikeReq true "点赞请求参数"
33+
// @Success 200 {object} dto.ToggleLikeResp "操作成功"
34+
// @Router /api/like/{likeId} [post]
3335
func ToggleLike(c *gin.Context) {
3436
var req dto.ToggleLikeReq
3537
var resp *dto.ToggleLikeResp
3638
var err error
3739

40+
if err = c.ShouldBindJSON(&req); err != nil {
41+
PostProcess(c, &req, nil, err)
42+
return
43+
}
3844
req.TargetID = c.Param(consts.CtxLikeID)
3945
c.Set(consts.CtxUserID, token.GetUserID(c))
4046

api/handler/proposal.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ func CreateProposal(c *gin.Context) {
5353
// @Param page query int true "页码"
5454
// @Param pageSize query int true "每页数量"
5555
// @Success 200 {object} dto.ListProposalResp
56-
// @Router /api/proposal/query [get]
56+
// @Router /api/proposal/list [get]
5757
func ListProposals(c *gin.Context) {
5858
var req dto.ListProposalReq
5959
var resp *dto.ListProposalResp
@@ -90,19 +90,19 @@ func GetProposal(c *gin.Context) {
9090
}
9191

9292
// ApproveProposal 审批提案
93-
// @router /api/proposal/:id/approve [POST]
93+
// @router /api/proposal/{proposalId}/approve [POST]
9494
func ApproveProposal(c *gin.Context) {
9595
// TODO: not implemented
9696
}
9797

9898
// UpdateProposal 修改提案
99-
// @router /api/proposal/:id/update [POST]
99+
// @router /api/proposal/{proposalId}/update [POST]
100100
func UpdateProposal(c *gin.Context) {
101101
// TODO: not implemented
102102
}
103103

104104
// DeleteProposal 删除提案
105-
// @router /api/proposal/:id/delete [POST]
105+
// @router /api/proposal/{proposalId}/delete [POST]
106106
func DeleteProposal(c *gin.Context) {
107107
// TODO: not implemented
108108
}

api/router/register.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,8 @@ func SetupRoutes() *gin.Engine {
6565
proposalGroup := router.Group("/api/proposal")
6666
{
6767
proposalGroup.POST("/add", handler.CreateProposal)
68-
proposalGroup.GET("/:id", handler.GetProposal)
6968
proposalGroup.GET("/list", handler.ListProposals)
69+
proposalGroup.GET("/:proposalId", handler.GetProposal)
7070
proposalGroup.POST("/:proposalId/update", handler.UpdateProposal)
7171
proposalGroup.POST("/:proposalId/delete", handler.DeleteProposal)
7272
proposalGroup.POST("/suggest", handler.GetProposalSuggestions)

application/assembler/proposal.go

Lines changed: 84 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -19,22 +19,25 @@ import (
1919

2020
"github.com/Boyuan-IT-Club/Meowpick-Backend/application/dto"
2121
"github.com/Boyuan-IT-Club/Meowpick-Backend/infra/model"
22+
"github.com/Boyuan-IT-Club/Meowpick-Backend/infra/repo"
2223
"github.com/Boyuan-IT-Club/Meowpick-Backend/infra/util/mapping"
24+
"github.com/Boyuan-IT-Club/Meowpick-Backend/types/consts"
2325
"github.com/Boyuan-IT-Club/go-kit/logs"
2426
"github.com/google/wire"
2527
)
2628

2729
var _ IProposalAssembler = (*ProposalAssembler)(nil)
2830

2931
type IProposalAssembler interface {
30-
ToProposalVO(ctx context.Context, db *model.Proposal) (*dto.ProposalVO, error)
31-
ToProposalVOArray(ctx context.Context, dbs []*model.Proposal) ([]*dto.ProposalVO, error)
32+
ToProposalVO(ctx context.Context, db *model.Proposal, userId string) (*dto.ProposalVO, error)
33+
ToProposalVOArray(ctx context.Context, dbs []*model.Proposal, userId string) ([]*dto.ProposalVO, error)
3234
ToProposalDB(ctx context.Context, vo *dto.ProposalVO) (*model.Proposal, error)
3335
ToProposalDBArray(ctx context.Context, vos []*dto.ProposalVO) ([]*model.Proposal, error)
3436
}
3537

3638
type ProposalAssembler struct {
3739
CourseAssembler *CourseAssembler
40+
LikeRepo *repo.LikeRepo
3841
}
3942

4043
var ProposalAssemblerSet = wire.NewSet(
@@ -43,7 +46,7 @@ var ProposalAssemblerSet = wire.NewSet(
4346
)
4447

4548
// ToProposalVO 单个ProposalDB转ProposalVO (DB to VO)
46-
func (a *ProposalAssembler) ToProposalVO(ctx context.Context, db *model.Proposal) (*dto.ProposalVO, error) {
49+
func (a *ProposalAssembler) ToProposalVO(ctx context.Context, db *model.Proposal, userId string) (*dto.ProposalVO, error) {
4750
var courseVO *dto.CourseVO
4851
if db.Course != nil {
4952
var err error
@@ -54,37 +57,100 @@ func (a *ProposalAssembler) ToProposalVO(ctx context.Context, db *model.Proposal
5457
}
5558
}
5659

60+
// 获得点赞目标类型
61+
targetType := mapping.Data.GetLikeTargetTypeIDByName(consts.LikeTargetTypeProposal)
62+
63+
// 获取点赞信息
64+
likeCnt, err := a.LikeRepo.CountByTarget(ctx, db.ID, targetType)
65+
if err != nil {
66+
logs.CtxErrorf(ctx, "[LikeRepo] [CountByID] error: %v", err)
67+
return nil, err
68+
}
69+
70+
// 这里的userId是查看评论的用户
71+
active, err := a.LikeRepo.IsLike(ctx, userId, db.ID, targetType)
72+
if err != nil {
73+
logs.CtxErrorf(ctx, "[LikeRepo] [IsLike] error: %v", err)
74+
return nil, err
75+
}
76+
5777
return &dto.ProposalVO{
58-
ID: db.ID,
59-
UserID: db.UserID,
60-
Title: db.Title,
61-
Content: db.Content,
62-
Course: courseVO,
63-
Status: mapping.Data.GetProposalStatusNameByID(db.Status),
64-
Deleted: db.Deleted,
65-
AgreeCnt: db.AgreeCnt,
78+
ID: db.ID,
79+
UserID: db.UserID,
80+
Title: db.Title,
81+
Content: db.Content,
82+
Course: courseVO,
83+
Status: mapping.Data.GetProposalStatusNameByID(db.Status),
84+
Deleted: db.Deleted,
85+
LikeVO: &dto.LikeVO{
86+
Like: active,
87+
LikeCnt: likeCnt,
88+
},
6689
CreatedAt: db.CreatedAt,
6790
UpdatedAt: db.UpdatedAt,
6891
}, nil
6992
}
7093

7194
// ToProposalVOArray ProposalDB数组转ProposalVO数组 (DB Array to VO Array)
72-
func (a *ProposalAssembler) ToProposalVOArray(ctx context.Context, dbs []*model.Proposal) ([]*dto.ProposalVO, error) {
95+
func (a *ProposalAssembler) ToProposalVOArray(ctx context.Context, dbs []*model.Proposal, userId string) ([]*dto.ProposalVO, error) {
7396
if len(dbs) == 0 {
7497
logs.CtxWarnf(ctx, "[ProposalAssembler] [ToProposalVOArray] empty proposal db array")
7598
return []*dto.ProposalVO{}, nil
7699
}
77100

101+
// 提取所有 proposalIds
102+
ids := make([]string, len(dbs))
103+
for i, db := range dbs {
104+
ids[i] = db.ID
105+
}
106+
107+
// 获得点赞目标类型
108+
targetType := mapping.Data.GetLikeTargetTypeIDByName(consts.LikeTargetTypeProposal)
109+
110+
// 批量获取点赞数
111+
likeCntMap, err := a.LikeRepo.CountByTargets(ctx, ids, targetType)
112+
if err != nil {
113+
logs.CtxErrorf(ctx, "[LikeRepo] [CountByTargets] error: %v", err)
114+
return nil, err
115+
}
116+
117+
// 批量获取点赞状态
118+
likeStatusMap, err := a.LikeRepo.GetLikesByUserIDAndTargets(ctx, userId, ids, targetType)
119+
if err != nil {
120+
logs.CtxErrorf(ctx, "[LikeRepo] [GetLikesByUserIDAndTargets] error: %v", err)
121+
return nil, err
122+
}
123+
124+
// 构建结果
78125
vos := make([]*dto.ProposalVO, 0, len(dbs))
79126
for _, db := range dbs {
80-
vo, err := a.ToProposalVO(ctx, db)
81-
if err != nil {
82-
logs.CtxErrorf(ctx, "[ProposalAssembler] [ToProposalVO] error: %v", err)
83-
return nil, err
127+
// 从批量查询结果中获取点赞信息
128+
likeCnt := likeCntMap[db.ID] // 如果不存在则为0
129+
active := likeStatusMap[db.ID] // 如果不存在则为false
130+
var courseVO *dto.CourseVO
131+
if db.Course != nil {
132+
courseVO, err = a.CourseAssembler.ToCourseVO(ctx, db.Course)
133+
if err != nil {
134+
logs.CtxErrorf(ctx, "[CourseAssembler] [ToCourseVO] error: %v", err)
135+
return nil, err
136+
}
84137
}
85-
if vo != nil {
86-
vos = append(vos, vo)
138+
proposalVO := &dto.ProposalVO{
139+
ID: db.ID,
140+
Content: db.Content,
141+
Title: db.Title,
142+
UserID: db.UserID,
143+
Status: mapping.Data.GetProposalStatusNameByID(db.Status),
144+
Deleted: db.Deleted,
145+
LikeVO: &dto.LikeVO{
146+
Like: active,
147+
LikeCnt: likeCnt,
148+
},
149+
Course: courseVO,
150+
CreatedAt: db.CreatedAt,
151+
UpdatedAt: db.UpdatedAt,
87152
}
153+
vos = append(vos, proposalVO)
88154
}
89155

90156
return vos, nil
@@ -110,7 +176,6 @@ func (a *ProposalAssembler) ToProposalDB(ctx context.Context, vo *dto.ProposalVO
110176
Course: courseDB,
111177
Status: mapping.Data.GetProposalStatusIDByName(vo.Status),
112178
Deleted: vo.Deleted,
113-
AgreeCnt: vo.AgreeCnt,
114179
CreatedAt: vo.CreatedAt,
115180
UpdatedAt: vo.UpdatedAt,
116181
}, nil

application/dto/auth.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@ package dto
1616

1717
// SignInReq 前端传来的登录请求
1818
type SignInReq struct {
19-
AuthID string `json:"authId" binding:"required"` // 微信开放平台ID
20-
AuthType string `json:"authType" binding:"required"` // 认证类型(wechat/phone等)
21-
Code string `json:"verifyCode" binding:"required"` // res.code
19+
AuthID string `json:"authId" binding:"required"` // 微信开放平台ID
20+
AuthType string `json:"authType" binding:"required"` // 认证类型(wechat/phone等)
21+
VerifyCode string `json:"verifyCode" binding:"required"` // res.code
2222
}
2323

2424
// SignInResp 返回给前端的响应 包含了accessToken

application/dto/course.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ package dto
1818
type CourseVO struct {
1919
ID string `json:"id"`
2020
Name string `json:"name"`
21-
Code string `json:"code"` // 暂未使用
21+
Code string `json:"code"`
2222
Category string `json:"category"`
2323
Campuses []string `json:"campuses"`
2424
Department string `json:"department"`

application/dto/proposal.go

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ import "time"
2020
type CreateProposalReq struct {
2121
Title string `json:"title" binding:"required"`
2222
Content string `json:"content" binding:"required"`
23-
Status string `json:"status" binding:"required"`
2423
Course *CourseVO `json:"course" binding:"required"`
2524
}
2625

@@ -31,13 +30,13 @@ type CreateProposalResp struct {
3130
}
3231

3332
type ProposalVO struct {
34-
ID string `json:"id"`
35-
UserID string `json:"userId"`
36-
Title string `json:"title"`
37-
Content string `json:"content"`
38-
Status string `json:"status"` // pending / approved / rejected
39-
Deleted bool `json:"deleted"`
40-
AgreeCnt int64 `json:"agreeCnt"`
33+
ID string `json:"id"`
34+
UserID string `json:"userId"`
35+
Title string `json:"title"`
36+
Content string `json:"content"`
37+
Status string `json:"status"` // pending / approved / rejected
38+
Deleted bool `json:"deleted"`
39+
*LikeVO
4140
Course *CourseVO `json:"course"`
4241
CreatedAt time.Time `json:"createdAt"`
4342
UpdatedAt time.Time `json:"updatedAt"`

application/service/auth.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,14 +51,14 @@ var AuthServiceSet = wire.NewSet(
5151
func (s *AuthService) SignIn(ctx context.Context, req *dto.SignInReq) (Resp *dto.SignInResp, err error) {
5252
// 查找或创建用户
5353
var openId string
54-
if req.Code == "test123" {
54+
if req.VerifyCode == "test123" {
5555
openId = "debug-openid-001" // 测试环境固定openid
5656
} else {
5757
// 为微信API调用设置超时
5858
openId = openid.GetWeChatOpenID(
5959
config.GetConfig().WeApp.AppID,
6060
config.GetConfig().WeApp.AppSecret,
61-
req.Code,
61+
req.VerifyCode,
6262
)
6363
}
6464
if openId == "" {

application/service/proposal.go

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ func (s *ProposalService) CreateProposal(ctx context.Context, req *dto.CreatePro
6464
}
6565

6666
// 转换为 courseModel
67+
req.Course.ID = primitive.NewObjectID().Hex()
6768
course, err := s.CourseAssembler.ToCourseDB(ctx, req.Course)
6869
if err != nil {
6970
return nil, errorx.WrapByCode(err, errno.ErrCourseCvtFailed,
@@ -103,17 +104,18 @@ func (s *ProposalService) CreateProposal(ctx context.Context, req *dto.CreatePro
103104
}
104105

105106
// 使用Assembler转换提案
107+
now := time.Now()
106108
proposalVO := &dto.ProposalVO{
107-
ID: primitive.NewObjectID().Hex(),
108-
UserID: userId,
109-
Title: req.Title,
110-
Content: req.Content,
111-
Deleted: false,
112-
Status: consts.ProposalStatusPending,
113-
AgreeCnt: 0,
109+
ID: primitive.NewObjectID().Hex(),
110+
UserID: userId,
111+
Title: req.Title,
112+
Content: req.Content,
113+
Deleted: false,
114+
Status: consts.ProposalStatusPending,
115+
CreatedAt: now,
116+
UpdatedAt: now,
114117
// 这里不设置Course,因为上面已经获得过CourseDB了
115-
CreatedAt: time.Now(),
116-
UpdatedAt: time.Now(),
118+
117119
}
118120

119121
proposal, err := s.ProposalAssembler.ToProposalDB(ctx, proposalVO)
@@ -167,7 +169,7 @@ func (s *ProposalService) ListProposals(ctx context.Context, req *dto.ListPropos
167169
}
168170

169171
// 转换为VO
170-
vos, err := s.ProposalAssembler.ToProposalVOArray(ctx, proposals)
172+
vos, err := s.ProposalAssembler.ToProposalVOArray(ctx, proposals, userId)
171173
if err != nil {
172174
logs.CtxErrorf(ctx, "[ProposalAssembler] [ToProposalVOArray] error: %v", err)
173175
return nil, errorx.WrapByCode(err, errno.ErrProposalCvtFailed,
@@ -197,12 +199,12 @@ func (s *ProposalService) GetProposal(ctx context.Context, req *dto.GetProposalR
197199
return nil, errorx.WrapByCode(err, errno.ErrProposalFindFailed, errorx.KV("proposalId", proposalId))
198200
}
199201
if proposal == nil {
200-
return nil, errorx.WrapByCode(err, errno.ErrProposalFindFailed,
201-
errorx.KV("key", consts.ReqProposalID), errorx.KV("value", proposalId))
202+
logs.CtxWarnf(ctx, "[ProposalRepo] [FindByID] proposal not found, proposalId: %s", proposalId)
203+
return nil, errorx.New(errno.ErrProposalNotFound, errorx.KV("key", consts.ReqProposalID), errorx.KV("value", proposalId))
202204
}
203205

204206
// 转换为VO
205-
vo, err := s.ProposalAssembler.ToProposalVO(ctx, proposal)
207+
vo, err := s.ProposalAssembler.ToProposalVO(ctx, proposal, userId)
206208
if err != nil {
207209
logs.CtxErrorf(ctx, "[ProposalAssembler] [ToProposalVO] error: %v, proposalId: %s", err, proposalId)
208210
return nil, errorx.WrapByCode(err, errno.ErrProposalCvtFailed,

0 commit comments

Comments
 (0)