Files
junhong_cmp_fiber/internal/handler/admin/polling_config.go
邹进 2ddaffe373
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 9m57s
docs: 轮询配置接口文档与实际行为对齐
- 匹配预览 GET 只收 query iccid,POST 只收请求体,去掉 POST 文档中多余的 query 参数
- 预览草稿 overrides 改为独立结构,字段全部可选,最多 20 条
- clear_fields 用具名类型生成数组元素枚举;ordered_ids 说明须为正整数且不重复
2026-10-24 17:41:52 +09:00

289 lines
9.2 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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)
}