package adminfinance import ( "errors" "net/http" "strconv" "time" "hfb_sys/backend/internal/timeutil" "hfb_sys/backend/pkg/response" "github.com/gin-gonic/gin" ) type Handler struct { service *Service } func NewHandler(service *Service) *Handler { return &Handler{service: service} } func (h *Handler) Dashboard(c *gin.Context) { query, ok := parseDashboardQuery(c) if !ok { return } item, err := h.service.Dashboard(c.Request.Context(), query) if err != nil { writeFinanceError(c, err) return } response.OK(c, item) } func (h *Handler) Details(c *gin.Context) { query, ok := parseDetailQuery(c) if !ok { return } result, err := h.service.Details(c.Request.Context(), query) if err != nil { writeFinanceError(c, err) return } response.OK(c, result) } func parseDashboardQuery(c *gin.Context) (DashboardQuery, bool) { start, end, ok := parseDateRange(c, 6) if !ok { return DashboardQuery{}, false } return DashboardQuery{StartDate: start, EndDate: end}, true } func parseDetailQuery(c *gin.Context) (DetailQuery, bool) { start, end, ok := parseDateRange(c, 29) if !ok { return DetailQuery{}, false } query := DetailQuery{ OrderNo: c.Query("order_no"), OrderStatus: c.Query("order_status"), SettlementStatus: c.Query("settlement_status"), DateType: c.DefaultQuery("date_type", "settled"), StartDate: start, EndDate: end, } if query.DateType != "created" && query.DateType != "settled" { response.BadRequest(c, "日期类型不正确") return query, false } if raw := c.Query("user_id"); raw != "" { value, err := strconv.ParseUint(raw, 10, 64) if err != nil || value == 0 { response.BadRequest(c, "用户 ID 不正确") return query, false } query.UserID = value } page, _ := strconv.Atoi(c.DefaultQuery("page", "1")) pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "20")) query.Page = page query.PageSize = pageSize return query, true } func parseDateRange(c *gin.Context, defaultLookbackDays int) (time.Time, time.Time, bool) { loc := timeutil.ShanghaiLocation() today := timeutil.ShanghaiNow() defaultStart := time.Date(today.Year(), today.Month(), today.Day(), 0, 0, 0, 0, loc).AddDate(0, 0, -defaultLookbackDays) defaultEnd := time.Date(today.Year(), today.Month(), today.Day(), 23, 59, 59, int(time.Second-time.Nanosecond), loc) start := defaultStart end := defaultEnd if raw := c.Query("start_date"); raw != "" { parsed, err := time.ParseInLocation("2006-01-02", raw, loc) if err != nil { response.BadRequest(c, "开始日期不正确") return start, end, false } start = parsed } if raw := c.Query("end_date"); raw != "" { parsed, err := time.ParseInLocation("2006-01-02", raw, loc) if err != nil { response.BadRequest(c, "结束日期不正确") return start, end, false } end = parsed.AddDate(0, 0, 1).Add(-time.Nanosecond) } if start.After(end) { response.BadRequest(c, "开始日期不能晚于结束日期") return start, end, false } return start, end, true } func writeFinanceError(c *gin.Context, err error) { switch { case errors.Is(err, ErrDependencyUnavailable): response.ServiceUnavailable(c, "数据库未连接") default: response.Error(c, http.StatusInternalServerError, "finance_error", "财务数据暂时不可用") } }