2026-05-12 09:53:20 +08:00

188 lines
6.3 KiB
Go

package http
import (
"hyapp/services/gateway-service/internal/transport/http/httpkit"
"net/http"
"strings"
activityv1 "hyapp.local/api/proto/activity/v1"
"hyapp/services/gateway-service/internal/auth"
)
type taskSectionData struct {
Section string `json:"section"`
Items []taskItemData `json:"items"`
ServerTimeMS int64 `json:"server_time_ms"`
NextRefreshAtMS int64 `json:"next_refresh_at_ms"`
}
type taskItemData struct {
TaskID string `json:"task_id"`
TaskType string `json:"task_type"`
Category string `json:"category"`
MetricType string `json:"metric_type"`
Title string `json:"title"`
Description string `json:"description"`
TargetValue int64 `json:"target_value"`
TargetUnit string `json:"target_unit"`
ProgressValue int64 `json:"progress_value"`
RewardCoinAmount int64 `json:"reward_coin_amount"`
Status string `json:"status"`
Claimable bool `json:"claimable"`
TaskDay string `json:"task_day"`
ServerTimeMS int64 `json:"server_time_ms"`
NextRefreshAtMS int64 `json:"next_refresh_at_ms"`
SortOrder int32 `json:"sort_order"`
Version int64 `json:"version"`
}
type taskClaimData struct {
ClaimID string `json:"claim_id"`
TaskID string `json:"task_id"`
TaskType string `json:"task_type"`
TaskDay string `json:"task_day"`
RewardCoinAmount int64 `json:"reward_coin_amount"`
Status string `json:"status"`
WalletTransactionID string `json:"wallet_transaction_id"`
GrantedAtMS int64 `json:"granted_at_ms"`
Claimed bool `json:"claimed"`
}
type taskClaimRequestBody struct {
TaskID string `json:"task_id"`
TaskIDCamel string `json:"taskId"`
TaskType string `json:"task_type"`
TaskTypeCamel string `json:"taskType"`
TaskDay string `json:"task_day"`
TaskDayCamel string `json:"taskDay"`
CommandID string `json:"command_id"`
CommandIDCamel string `json:"commandId"`
}
func (b taskClaimRequestBody) normalizedTaskID() string {
if value := strings.TrimSpace(b.TaskID); value != "" {
return value
}
return strings.TrimSpace(b.TaskIDCamel)
}
func (b taskClaimRequestBody) normalizedTaskType() string {
if value := strings.TrimSpace(b.TaskType); value != "" {
return value
}
return strings.TrimSpace(b.TaskTypeCamel)
}
func (b taskClaimRequestBody) normalizedTaskDay() string {
if value := strings.TrimSpace(b.TaskDay); value != "" {
return value
}
return strings.TrimSpace(b.TaskDayCamel)
}
func (b taskClaimRequestBody) normalizedCommandID() string {
if value := strings.TrimSpace(b.CommandID); value != "" {
return value
}
return strings.TrimSpace(b.CommandIDCamel)
}
// listTaskTabs 返回当前用户任务页;进度由 activity-service 事实表决定。
func (h *Handler) listTaskTabs(writer http.ResponseWriter, request *http.Request) {
if h.taskClient == nil {
httpkit.WriteError(writer, request, http.StatusBadGateway, httpkit.CodeUpstreamError, "upstream service error")
return
}
resp, err := h.taskClient.ListUserTasks(request.Context(), &activityv1.ListUserTasksRequest{
Meta: activityMeta(request),
UserId: auth.UserIDFromContext(request.Context()),
})
if err != nil {
httpkit.WriteRPCError(writer, request, err)
return
}
sections := make([]taskSectionData, 0, len(resp.GetSections()))
for _, section := range resp.GetSections() {
items := make([]taskItemData, 0, len(section.GetItems()))
for _, item := range section.GetItems() {
items = append(items, taskItemFromProto(item))
}
sections = append(sections, taskSectionData{
Section: section.GetSection(),
Items: items,
ServerTimeMS: section.GetServerTimeMs(),
NextRefreshAtMS: section.GetNextRefreshAtMs(),
})
}
httpkit.WriteOK(writer, request, map[string]any{
"sections": sections,
"server_time_ms": resp.GetServerTimeMs(),
"next_refresh_at_ms": resp.GetNextRefreshAtMs(),
})
}
// claimTaskReward 只透传当前用户身份和幂等命令,完成校验及发奖在 activity-service 内完成。
func (h *Handler) claimTaskReward(writer http.ResponseWriter, request *http.Request) {
if h.taskClient == nil {
httpkit.WriteError(writer, request, http.StatusBadGateway, httpkit.CodeUpstreamError, "upstream service error")
return
}
var body taskClaimRequestBody
if !decode(writer, request, &body) {
return
}
taskID := body.normalizedTaskID()
taskType := body.normalizedTaskType()
taskDay := body.normalizedTaskDay()
commandID := commandIDOrNew(body.normalizedCommandID())
if taskID == "" || taskType == "" || taskDay == "" {
httpkit.WriteError(writer, request, http.StatusBadRequest, httpkit.CodeInvalidArgument, "invalid argument")
return
}
resp, err := h.taskClient.ClaimTaskReward(request.Context(), &activityv1.ClaimTaskRewardRequest{
Meta: activityMeta(request),
UserId: auth.UserIDFromContext(request.Context()),
TaskId: taskID,
TaskType: taskType,
TaskDay: taskDay,
CommandId: commandID,
})
if err != nil {
httpkit.WriteRPCError(writer, request, err)
return
}
httpkit.WriteOK(writer, request, taskClaimData{
ClaimID: resp.GetClaimId(),
TaskID: resp.GetTaskId(),
TaskType: resp.GetTaskType(),
TaskDay: resp.GetTaskDay(),
RewardCoinAmount: resp.GetRewardCoinAmount(),
Status: resp.GetStatus(),
WalletTransactionID: resp.GetWalletTransactionId(),
GrantedAtMS: resp.GetGrantedAtMs(),
Claimed: resp.GetClaimed(),
})
}
func taskItemFromProto(item *activityv1.TaskItem) taskItemData {
return taskItemData{
TaskID: item.GetTaskId(),
TaskType: item.GetTaskType(),
Category: item.GetCategory(),
MetricType: item.GetMetricType(),
Title: item.GetTitle(),
Description: item.GetDescription(),
TargetValue: item.GetTargetValue(),
TargetUnit: item.GetTargetUnit(),
ProgressValue: item.GetProgressValue(),
RewardCoinAmount: item.GetRewardCoinAmount(),
Status: item.GetStatus(),
Claimable: item.GetClaimable(),
TaskDay: item.GetTaskDay(),
ServerTimeMS: item.GetServerTimeMs(),
NextRefreshAtMS: item.GetNextRefreshAtMs(),
SortOrder: item.GetSortOrder(),
Version: item.GetVersion(),
}
}