diff --git a/internal/api/activity/lottery_app.go b/internal/api/activity/lottery_app.go index 699b3e3..d0799b4 100644 --- a/internal/api/activity/lottery_app.go +++ b/internal/api/activity/lottery_app.go @@ -298,8 +298,9 @@ type resultQueryRequest struct { } type resultResponse struct { - Result map[string]any `json:"result"` - Receipt map[string]any `json:"receipt"` + Result map[string]any `json:"result"` + Results []map[string]any `json:"results"` + Receipt map[string]any `json:"receipt"` } // GetLotteryResult 抽奖结果查询 @@ -377,6 +378,28 @@ func (h *handler) GetLotteryResult() core.HandlerFunc { } return "" }()} + // Also fetch all draw logs for this order to include doubled rewards + if orderID > 0 { + allLogs, _ := h.readDB.ActivityDrawLogs.WithContext(ctx.RequestContext()).Where(h.readDB.ActivityDrawLogs.OrderID.Eq(orderID)).Find() + for _, lg := range allLogs { + rwi, _ := h.readDB.ActivityRewardSettings.WithContext(ctx.RequestContext()).Where(h.readDB.ActivityRewardSettings.ID.Eq(lg.RewardID)).First() + rsp.Results = append(rsp.Results, map[string]any{ + "reward_id": lg.RewardID, + "reward_name": func() string { + if rwi != nil { + return rwi.Name + } + return "" + }(), + "image": func() string { + if rwi != nil { + return rwi.Image + } + return "" + }(), + }) + } + } } else if cfgMode == "instant" { // 即时开奖必须绑定订单且校验归属与支付状态 if orderID == 0 || ord == nil { @@ -496,6 +519,26 @@ func (h *handler) GetLotteryResult() core.HandlerFunc { } return "" }()} + // Fetch all draw logs for this order to include doubled/upgraded rewards + allLogs, _ := h.readDB.ActivityDrawLogs.WithContext(ctx.RequestContext()).Where(h.readDB.ActivityDrawLogs.OrderID.Eq(orderID)).Find() + for _, lg := range allLogs { + rwi, _ := h.readDB.ActivityRewardSettings.WithContext(ctx.RequestContext()).Where(h.readDB.ActivityRewardSettings.ID.Eq(lg.RewardID)).First() + rsp.Results = append(rsp.Results, map[string]any{ + "reward_id": lg.RewardID, + "reward_name": func() string { + if rwi != nil { + return rwi.Name + } + return "" + }(), + "image": func() string { + if rwi != nil { + return rwi.Image + } + return "" + }(), + }) + } } } } diff --git a/internal/api/user/addresses_update_app.go b/internal/api/user/addresses_update_app.go new file mode 100644 index 0000000..0a3d849 --- /dev/null +++ b/internal/api/user/addresses_update_app.go @@ -0,0 +1,71 @@ +package app + +import ( + "net/http" + "strconv" + + "bindbox-game/internal/code" + "bindbox-game/internal/pkg/core" + "bindbox-game/internal/pkg/validation" + usersvc "bindbox-game/internal/service/user" +) + +type updateAddressRequest struct { + Name string `json:"name"` + Mobile string `json:"mobile"` + Province string `json:"province"` + City string `json:"city"` + District string `json:"district"` + Address string `json:"address"` + IsDefault bool `json:"is_default"` +} + +// UpdateUserAddress 更新用户地址 +// @Summary 更新用户地址 +// @Description 更新当前登录用户的指定收货地址 +// @Tags APP端.用户 +// @Accept json +// @Produce json +// @Param user_id path integer true "用户ID" +// @Param address_id path integer true "地址ID" +// @Security LoginVerifyToken +// @Param RequestBody body updateAddressRequest true "请求参数" +// @Success 200 {object} okResponse +// @Failure 400 {object} code.Failure "参数错误" +// @Failure 401 {object} code.Failure "未授权" +// @Failure 500 {object} code.Failure "服务器内部错误" +// @Router /api/app/users/{user_id}/addresses/{address_id} [put] +func (h *handler) UpdateUserAddress() core.HandlerFunc { + return func(ctx core.Context) { + req := new(updateAddressRequest) + if err := ctx.ShouldBindJSON(req); err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err))) + return + } + if req.Name == "" || req.Mobile == "" || req.Province == "" || req.City == "" || req.District == "" || req.Address == "" { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "缺少必要参数")) + return + } + userID := int64(ctx.SessionUserInfo().Id) + idStr := ctx.Param("address_id") + addrID, err := strconv.ParseInt(idStr, 10, 64) + if err != nil || addrID <= 0 { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "地址ID错误")) + return + } + in := usersvc.UpdateAddressInput{ + Name: req.Name, + Mobile: req.Mobile, + Province: req.Province, + City: req.City, + District: req.District, + Address: req.Address, + IsDefault: req.IsDefault, + } + if err := h.user.UpdateAddress(ctx.RequestContext(), userID, addrID, in); err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, 10012, err.Error())) + return + } + ctx.Payload(okResponse{Ok: true}) + } +} diff --git a/internal/router/router.go b/internal/router/router.go index 13a1e54..d9439cf 100644 --- a/internal/router/router.go +++ b/internal/router/router.go @@ -342,6 +342,7 @@ func NewHTTPMux(logger logger.CustomLogger, db mysql.Repo) (core.Mux, func(), er appAuthApiRouter.POST("/users/:user_id/addresses", userHandler.AddUserAddress()) appAuthApiRouter.GET("/users/:user_id/addresses", userHandler.ListUserAddresses()) appAuthApiRouter.PUT("/users/:user_id/addresses/:address_id/default", userHandler.SetDefaultUserAddress()) + appAuthApiRouter.PUT("/users/:user_id/addresses/:address_id", userHandler.UpdateUserAddress()) appAuthApiRouter.DELETE("/users/:user_id/addresses/:address_id", userHandler.DeleteUserAddress()) appAuthApiRouter.POST("/pay/wechat/jsapi/preorder", userHandler.WechatJSAPIPreorder()) diff --git a/internal/service/user/addresses.go b/internal/service/user/addresses.go index e6ee41f..1cc569a 100644 --- a/internal/service/user/addresses.go +++ b/internal/service/user/addresses.go @@ -86,3 +86,38 @@ func (s *service) DeleteAddress(ctx context.Context, userID int64, addressID int _, err := s.writeDB.UserAddresses.WithContext(ctx).Where(s.writeDB.UserAddresses.UserID.Eq(userID), s.writeDB.UserAddresses.ID.Eq(addressID)).Delete(&model.UserAddresses{}) return err } + +type UpdateAddressInput struct { + Name string + Mobile string + Province string + City string + District string + Address string + IsDefault bool +} + +func (s *service) UpdateAddress(ctx context.Context, userID int64, addressID int64, in UpdateAddressInput) error { + tx := s.writeDB.Begin() + updates := map[string]interface{}{ + "name": in.Name, + "mobile": in.Mobile, + "province": in.Province, + "city": in.City, + "district": in.District, + "address": in.Address, + } + if in.IsDefault { + // 先将其他地址设为非默认 + if _, err := tx.UserAddresses.WithContext(ctx).Where(tx.UserAddresses.UserID.Eq(userID), tx.UserAddresses.IsDefault.Eq(1)).Updates(tx.UserAddresses.IsDefault.Value(0)); err != nil { + _ = tx.Rollback() + return err + } + updates["is_default"] = 1 + } + if _, err := tx.UserAddresses.WithContext(ctx).Where(tx.UserAddresses.UserID.Eq(userID), tx.UserAddresses.ID.Eq(addressID)).Updates(updates); err != nil { + _ = tx.Rollback() + return err + } + return tx.Commit() +} diff --git a/internal/service/user/user.go b/internal/service/user/user.go index ca6cad8..af5f5cf 100644 --- a/internal/service/user/user.go +++ b/internal/service/user/user.go @@ -40,6 +40,7 @@ type Service interface { AddAddress(ctx context.Context, userID int64, in AddAddressInput) (*model.UserAddresses, error) ListAddresses(ctx context.Context, userID int64, page, pageSize int) (items []*model.UserAddresses, total int64, err error) SetDefaultAddress(ctx context.Context, userID int64, addressID int64) error + UpdateAddress(ctx context.Context, userID int64, addressID int64, in UpdateAddressInput) error DeleteAddress(ctx context.Context, userID int64, addressID int64) error CreateUser(ctx context.Context, in CreateUserInput) (*model.Users, error) DeleteUser(ctx context.Context, userID int64) error diff --git a/logs/mini-chat-access.log b/logs/mini-chat-access.log index 05072cf..be13a32 100644 --- a/logs/mini-chat-access.log +++ b/logs/mini-chat-access.log @@ -1665,3 +1665,10 @@ {"level":"info","time":"2025-12-26 12:16:02","caller":"logger/logger.go:309","msg":"Processing event","domain":"mini-chat[fat]","type":"order_paid","worker_id":4} {"level":"info","time":"2025-12-26 12:16:59","caller":"logger/logger.go:309","msg":"Processing event","domain":"mini-chat[fat]","type":"order_paid","worker_id":0} {"level":"info","time":"2025-12-26 12:17:46","caller":"logger/logger.go:309","msg":"Processing event","domain":"mini-chat[fat]","type":"order_paid","worker_id":4} +{"level":"info","time":"2025-12-26 12:33:31","caller":"logger/logger.go:309","msg":"Connected to Redis","domain":"mini-chat[fat]","addr":"118.25.13.43:8379"} +{"level":"info","time":"2025-12-26 12:33:31","caller":"logger/logger.go:309","msg":"Task center worker started","domain":"mini-chat[fat]"} +{"level":"info","time":"2025-12-26 12:33:31","caller":"logger/logger.go:309","msg":"Worker routine started","domain":"mini-chat[fat]","worker_id":4} +{"level":"info","time":"2025-12-26 12:33:31","caller":"logger/logger.go:309","msg":"Worker routine started","domain":"mini-chat[fat]","worker_id":3} +{"level":"info","time":"2025-12-26 12:33:31","caller":"logger/logger.go:309","msg":"Worker routine started","domain":"mini-chat[fat]","worker_id":2} +{"level":"info","time":"2025-12-26 12:33:31","caller":"logger/logger.go:309","msg":"Worker routine started","domain":"mini-chat[fat]","worker_id":1} +{"level":"info","time":"2025-12-26 12:33:31","caller":"logger/logger.go:309","msg":"Worker routine started","domain":"mini-chat[fat]","worker_id":0}