package admin import ( "strconv" "github.com/gofiber/fiber/v2" "github.com/break/junhong_cmp_fiber/internal/model/dto" pollingService "github.com/break/junhong_cmp_fiber/internal/service/polling" "github.com/break/junhong_cmp_fiber/pkg/errors" "github.com/break/junhong_cmp_fiber/pkg/response" ) // PollingConfigHandler 轮询配置 Handler type PollingConfigHandler struct { service *pollingService.ConfigService } // NewPollingConfigHandler 创建轮询配置 Handler 实例 func NewPollingConfigHandler(service *pollingService.ConfigService) *PollingConfigHandler { return &PollingConfigHandler{service: service} } // List 获取轮询配置列表 // @Summary 获取轮询配置列表 // @Description 获取轮询配置列表,支持分页和筛选 // @Tags 轮询配置管理 // @Accept json // @Produce json // @Param page query int false "页码" // @Param page_size query int false "每页数量" // @Param status query int false "状态 (1:启用, 0:禁用)" // @Param card_condition query string false "卡状态条件" // @Param card_category query string false "卡业务类型" // @Param carrier_id query int false "运营商ID" // @Param config_name query string false "配置名称" // @Success 200 {object} response.Response{data=dto.PollingConfigPageResult} // @Router /api/admin/polling-configs [get] func (h *PollingConfigHandler) List(c *fiber.Ctx) error { var req dto.PollingConfigListRequest if err := c.QueryParser(&req); err != nil { return errors.New(errors.CodeInvalidParam) } configs, total, err := h.service.List(c.UserContext(), &req) if err != nil { return err } return response.SuccessWithPagination(c, configs, total, req.Page, req.PageSize) } // Create 创建轮询配置 // @Summary 创建轮询配置 // @Description 创建新的轮询配置 // @Tags 轮询配置管理 // @Accept json // @Produce json // @Param body body dto.CreatePollingConfigRequest true "创建轮询配置请求" // @Success 200 {object} response.Response{data=dto.PollingConfigResponse} // @Router /api/admin/polling-configs [post] func (h *PollingConfigHandler) Create(c *fiber.Ctx) error { var req dto.CreatePollingConfigRequest if err := c.BodyParser(&req); err != nil { return errors.New(errors.CodeInvalidParam) } config, err := h.service.Create(c.UserContext(), &req) if err != nil { return err } return response.Success(c, config) } // Get 获取轮询配置详情 // @Summary 获取轮询配置详情 // @Description 根据 ID 获取轮询配置详情 // @Tags 轮询配置管理 // @Accept json // @Produce json // @Param id path int true "配置ID" // @Success 200 {object} response.Response{data=dto.PollingConfigResponse} // @Router /api/admin/polling-configs/{id} [get] func (h *PollingConfigHandler) Get(c *fiber.Ctx) error { id, err := strconv.ParseUint(c.Params("id"), 10, 64) if err != nil { return errors.New(errors.CodeInvalidParam, "无效的配置 ID") } config, err := h.service.Get(c.UserContext(), uint(id)) if err != nil { return err } return response.Success(c, config) } // Update 更新轮询配置 // @Summary 更新轮询配置 // @Description 根据 ID 更新轮询配置 // @Tags 轮询配置管理 // @Accept json // @Produce json // @Param id path int true "配置ID" // @Param body body dto.UpdatePollingConfigRequest true "更新轮询配置请求" // @Success 200 {object} response.Response{data=dto.PollingConfigResponse} // @Router /api/admin/polling-configs/{id} [put] func (h *PollingConfigHandler) Update(c *fiber.Ctx) error { id, err := strconv.ParseUint(c.Params("id"), 10, 64) if err != nil { return errors.New(errors.CodeInvalidParam, "无效的配置 ID") } var req dto.UpdatePollingConfigRequest if err := c.BodyParser(&req); err != nil { return errors.New(errors.CodeInvalidParam) } config, err := h.service.Update(c.UserContext(), uint(id), &req) if err != nil { return err } return response.Success(c, config) } // Delete 删除轮询配置 // @Summary 删除轮询配置 // @Description 根据 ID 删除轮询配置 // @Tags 轮询配置管理 // @Accept json // @Produce json // @Param id path int true "配置ID" // @Success 200 {object} response.Response // @Router /api/admin/polling-configs/{id} [delete] func (h *PollingConfigHandler) Delete(c *fiber.Ctx) error { id, err := strconv.ParseUint(c.Params("id"), 10, 64) if err != nil { return errors.New(errors.CodeInvalidParam, "无效的配置 ID") } if err := h.service.Delete(c.UserContext(), uint(id)); err != nil { return err } return response.Success(c, nil) } // UpdateStatus 更新轮询配置状态 // @Summary 更新轮询配置状态 // @Description 启用或禁用轮询配置 // @Tags 轮询配置管理 // @Accept json // @Produce json // @Param id path int true "配置ID" // @Param body body dto.UpdatePollingConfigStatusRequest true "更新状态请求" // @Success 200 {object} response.Response // @Router /api/admin/polling-configs/{id}/status [put] func (h *PollingConfigHandler) UpdateStatus(c *fiber.Ctx) error { id, err := strconv.ParseUint(c.Params("id"), 10, 64) if err != nil { return errors.New(errors.CodeInvalidParam, "无效的配置 ID") } var req dto.UpdatePollingConfigStatusRequest if err := c.BodyParser(&req); err != nil { return errors.New(errors.CodeInvalidParam) } if err := h.service.UpdateStatus(c.UserContext(), uint(id), req.Status); err != nil { return err } return response.Success(c, nil) } // ListEnabled 获取所有启用的配置 // @Summary 获取所有启用的配置 // @Description 获取所有启用状态的轮询配置,按优先级排序 // @Tags 轮询配置管理 // @Accept json // @Produce json // @Success 200 {object} response.Response{data=[]dto.PollingConfigResponse} // @Router /api/admin/polling-configs/enabled [get] func (h *PollingConfigHandler) ListEnabled(c *fiber.Ctx) error { configs, err := h.service.ListEnabled(c.UserContext()) if err != nil { return err } return response.Success(c, configs) } // UpdatePriorities 按给定顺序整体调整轮询配置优先级(仅超级管理员)。 // PUT /api/admin/polling-configs/priorities func (h *PollingConfigHandler) UpdatePriorities(c *fiber.Ctx) error { var req dto.UpdatePollingConfigPrioritiesRequest if err := c.BodyParser(&req); err != nil { return errors.New(errors.CodeInvalidParam, "请求参数解析失败") } if len(req.OrderedIDs) == 0 { return errors.New(errors.CodeInvalidParam, "轮询配置优先级参数不合法:配置 ID 列表不能为空") } if err := h.service.UpdatePriorities(c.UserContext(), &req); err != nil { return err } return response.Success(c, nil) } // MatchPreview 预览一张卡的轮询配置匹配结果;GET 只按当前配置,POST 可带未保存修改,均不写数据。 // GET /api/admin/polling-configs/match-preview // POST /api/admin/polling-configs/match-preview func (h *PollingConfigHandler) MatchPreview(c *fiber.Ctx) error { var req dto.PollingConfigMatchPreviewRequest if c.Method() == fiber.MethodPost { if err := c.BodyParser(&req); err != nil { return errors.New(errors.CodeInvalidParam, "请求参数解析失败") } } else { var query dto.PollingConfigMatchPreviewQuery if err := c.QueryParser(&query); err != nil { return errors.New(errors.CodeInvalidParam, "请求参数解析失败") } req.ICCID = query.ICCID } if len(req.Overrides) > 20 { return errors.New(errors.CodeInvalidParam, "匹配预览参数不合法:未保存修改最多 20 条") } if req.ICCID == "" { return errors.New(errors.CodeInvalidParam, "匹配预览参数不合法:ICCID 不能为空") } result, err := h.service.MatchPreview(c.UserContext(), &req) if err != nil { return err } return response.Success(c, result) } // CreateRecalculateTask 创建"立即重算到期时间"异步任务(仅超级管理员)。 // POST /api/admin/polling-configs/recalculate-due func (h *PollingConfigHandler) CreateRecalculateTask(c *fiber.Ctx) error { var req dto.PollingRecalculateDueRequest if len(c.Body()) > 0 { if err := c.BodyParser(&req); err != nil { return errors.New(errors.CodeInvalidParam, "请求参数解析失败") } } result, err := h.service.CreateRecalculateTask(c.UserContext(), &req) if err != nil { return err } return response.Success(c, result) } // GetRecalculateTask 查询重算到期时间任务进度。 // GET /api/admin/polling-configs/recalculate-due/:task_id func (h *PollingConfigHandler) GetRecalculateTask(c *fiber.Ctx) error { taskID := c.Params("task_id") if taskID == "" { return errors.New(errors.CodeInvalidParam, "重算任务 ID 不能为空") } result, err := h.service.GetRecalculateTask(c.UserContext(), taskID) if err != nil { return err } return response.Success(c, result) } // TierStats 查询分层轮询统计(结果缓存 5 分钟)。 // GET /api/admin/polling-stats/tiers func (h *PollingConfigHandler) TierStats(c *fiber.Ctx) error { result, err := h.service.TierStats(c.UserContext()) if err != nil { return err } return response.Success(c, result) } // PreResetStats 查询重置日前加密效果统计。 // GET /api/admin/polling-stats/pre-reset func (h *PollingConfigHandler) PreResetStats(c *fiber.Ctx) error { result, err := h.service.PreResetStats(c.UserContext()) if err != nil { return err } return response.Success(c, result) }