Files
junhong_cmp_fiber/internal/handler/admin/polling_manual_trigger.go
邹进 79b7580554
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 9m30s
feat: 下线设备保护期
- 后台设备停复机不再设置 1 小时保护期,也不再因保护期拒绝相反操作;单卡手动停复机去掉保护期检查
- 删除保护期一致性轮询(polling:protect)及其强制停复机方法;调度、初始化、监控、匹配预览不再包含保护期;已入队的旧任务由空处理函数直接确认,下一次发布移除
- 轮询配置接口不再接受与返回 protect_check_interval;并发配置不再返回 protect,查询、更新、重置该类型时拒绝
- 资产详情 device_protect_status 固定返回 none 并标记废弃,兼容老版本客户端
- 删除保护期 Redis key 与时长常量;停机原因 protect_period 保留供历史数据与开放接口映射
- 迁移 000249 只把 protect_check_interval、last_protect_check_at 列注释标记为已废弃,不删列不改数据
2026-10-25 17:19:10 +09:00

308 lines
8.7 KiB
Go

package admin
import (
"github.com/gofiber/fiber/v2"
"github.com/break/junhong_cmp_fiber/internal/model"
"github.com/break/junhong_cmp_fiber/internal/model/dto"
"github.com/break/junhong_cmp_fiber/internal/service/polling"
"github.com/break/junhong_cmp_fiber/pkg/constants"
"github.com/break/junhong_cmp_fiber/pkg/errors"
"github.com/break/junhong_cmp_fiber/pkg/middleware"
"github.com/break/junhong_cmp_fiber/pkg/response"
)
// PollingManualTriggerHandler 轮询手动触发处理器
type PollingManualTriggerHandler struct {
service *polling.ManualTriggerService
}
// NewPollingManualTriggerHandler 创建轮询手动触发处理器
func NewPollingManualTriggerHandler(service *polling.ManualTriggerService) *PollingManualTriggerHandler {
return &PollingManualTriggerHandler{service: service}
}
// TriggerSingle 单卡手动触发
// @Summary 单卡手动触发
// @Description 触发单张卡的轮询任务
// @Tags 轮询管理-手动触发
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param request body dto.TriggerSingleReq true "触发请求"
// @Success 200 {object} response.Response
// @Router /api/admin/polling-manual-trigger/single [post]
func (h *PollingManualTriggerHandler) TriggerSingle(c *fiber.Ctx) error {
ctx := c.UserContext()
var req dto.TriggerSingleReq
if err := c.BodyParser(&req); err != nil {
return errors.New(errors.CodeInvalidParam)
}
userID := middleware.GetUserIDFromContext(ctx)
if userID == 0 {
return errors.New(errors.CodeUnauthorized)
}
if err := h.service.TriggerSingle(ctx, req.CardID, req.TaskType, userID); err != nil {
return err
}
return response.Success(c, nil)
}
// TriggerBatch 批量手动触发
// @Summary 批量手动触发
// @Description 批量触发多张卡的轮询任务
// @Tags 轮询管理-手动触发
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param request body dto.TriggerBatchReq true "触发请求"
// @Success 200 {object} response.Response{data=dto.ManualTriggerLogResp}
// @Router /api/admin/polling-manual-trigger/batch [post]
func (h *PollingManualTriggerHandler) TriggerBatch(c *fiber.Ctx) error {
ctx := c.UserContext()
var req dto.TriggerBatchReq
if err := c.BodyParser(&req); err != nil {
return errors.New(errors.CodeInvalidParam)
}
userID := middleware.GetUserIDFromContext(ctx)
if userID == 0 {
return errors.New(errors.CodeUnauthorized)
}
log, err := h.service.TriggerBatch(ctx, req.CardIDs, req.TaskType, userID)
if err != nil {
return err
}
return response.Success(c, h.toLogResp(log))
}
// TriggerByCondition 条件筛选触发
// @Summary 条件筛选触发
// @Description 根据条件筛选卡并触发轮询任务
// @Tags 轮询管理-手动触发
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param request body dto.TriggerByConditionReq true "触发请求"
// @Success 200 {object} response.Response{data=dto.ManualTriggerLogResp}
// @Router /api/admin/polling-manual-trigger/by-condition [post]
func (h *PollingManualTriggerHandler) TriggerByCondition(c *fiber.Ctx) error {
ctx := c.UserContext()
var req dto.TriggerByConditionReq
if err := c.BodyParser(&req); err != nil {
return errors.New(errors.CodeInvalidParam)
}
userID := middleware.GetUserIDFromContext(ctx)
if userID == 0 {
return errors.New(errors.CodeUnauthorized)
}
filter := &polling.ConditionFilter{
CardStatus: req.CardStatus,
CarrierCode: req.CarrierCode,
CardType: req.CardType,
ShopID: req.ShopID,
PackageIDs: req.PackageIDs,
EnablePolling: req.EnablePolling,
Limit: req.Limit,
}
log, err := h.service.TriggerByCondition(ctx, filter, req.TaskType, userID)
if err != nil {
return err
}
return response.Success(c, h.toLogResp(log))
}
// GetStatus 获取触发状态
// @Summary 获取手动触发状态
// @Description 获取当前用户的手动触发状态
// @Tags 轮询管理-手动触发
// @Accept json
// @Produce json
// @Security BearerAuth
// @Success 200 {object} response.Response{data=dto.ManualTriggerStatusResp}
// @Router /api/admin/polling-manual-trigger/status [get]
func (h *PollingManualTriggerHandler) GetStatus(c *fiber.Ctx) error {
ctx := c.UserContext()
userID := middleware.GetUserIDFromContext(ctx)
if userID == 0 {
return errors.New(errors.CodeUnauthorized)
}
// 获取正在运行的任务
runningTasks, err := h.service.GetRunningTasks(ctx, userID)
if err != nil {
return err
}
items := make([]*dto.ManualTriggerLogResp, 0, len(runningTasks))
for _, log := range runningTasks {
items = append(items, h.toLogResp(log))
}
queueSizes := make(map[string]int64)
for _, taskType := range []string{
constants.TaskTypePollingRealname,
constants.TaskTypePollingCarddata,
constants.TaskTypePollingPackage,
} {
size, _ := h.service.GetQueueSize(ctx, taskType)
queueSizes[taskType] = size
}
return response.Success(c, &dto.ManualTriggerStatusResp{
RunningTasks: items,
QueueSizes: queueSizes,
})
}
// ListHistory 获取触发历史
// @Summary 获取手动触发历史
// @Description 获取手动触发历史记录
// @Tags 轮询管理-手动触发
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param task_type query string false "任务类型筛选"
// @Param page query int false "页码"
// @Param page_size query int false "每页数量"
// @Success 200 {object} response.Response{data=dto.ManualTriggerLogListResp}
// @Router /api/admin/polling-manual-trigger/history [get]
func (h *PollingManualTriggerHandler) ListHistory(c *fiber.Ctx) error {
ctx := c.UserContext()
var req dto.ListManualTriggerLogReq
if err := c.QueryParser(&req); err != nil {
return errors.New(errors.CodeInvalidParam)
}
if req.Page < 1 {
req.Page = 1
}
if req.PageSize < 1 || req.PageSize > 100 {
req.PageSize = 20
}
logs, total, err := h.service.ListHistory(ctx, req.Page, req.PageSize, req.TaskType, nil)
if err != nil {
return err
}
items := make([]*dto.ManualTriggerLogResp, 0, len(logs))
for _, log := range logs {
items = append(items, h.toLogResp(log))
}
return response.Success(c, &dto.ManualTriggerLogListResp{
Items: items,
Total: total,
Page: req.Page,
PageSize: req.PageSize,
})
}
// CancelTrigger 取消触发任务
// @Summary 取消手动触发任务
// @Description 取消正在执行的手动触发任务
// @Tags 轮询管理-手动触发
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param request body dto.CancelTriggerReq true "取消请求"
// @Success 200 {object} response.Response
// @Router /api/admin/polling-manual-trigger/cancel [post]
func (h *PollingManualTriggerHandler) CancelTrigger(c *fiber.Ctx) error {
ctx := c.UserContext()
var req dto.CancelTriggerReq
if err := c.BodyParser(&req); err != nil {
return errors.New(errors.CodeInvalidParam)
}
userID := middleware.GetUserIDFromContext(ctx)
if userID == 0 {
return errors.New(errors.CodeUnauthorized)
}
if err := h.service.CancelTrigger(ctx, req.TriggerID, userID); err != nil {
return err
}
return response.Success(c, nil)
}
func (h *PollingManualTriggerHandler) toLogResp(log *model.PollingManualTriggerLog) *dto.ManualTriggerLogResp {
return &dto.ManualTriggerLogResp{
ID: log.ID,
TaskType: log.TaskType,
TaskTypeName: h.getTaskTypeName(log.TaskType),
TriggerType: log.TriggerType,
TriggerTypeName: h.getTriggerTypeName(log.TriggerType),
TotalCount: log.TotalCount,
ProcessedCount: log.ProcessedCount,
SuccessCount: log.SuccessCount,
FailedCount: log.FailedCount,
Status: log.Status,
StatusName: h.getStatusName(log.Status),
TriggeredBy: log.TriggeredBy,
TriggeredAt: log.TriggeredAt,
CompletedAt: log.CompletedAt,
}
}
func (h *PollingManualTriggerHandler) getTaskTypeName(taskType string) string {
switch taskType {
case constants.TaskTypePollingRealname:
return "实名检查"
case constants.TaskTypePollingCarddata:
return "流量检查"
case constants.TaskTypePollingPackage:
return "套餐检查"
case constants.TaskTypePollingProtect:
// 保护期已下线,保留名称供历史手动触发记录展示。
return "保护期检查"
default:
return taskType
}
}
func (h *PollingManualTriggerHandler) getTriggerTypeName(triggerType string) string {
switch triggerType {
case "single":
return "单卡触发"
case "batch":
return "批量触发"
case "by_condition":
return "条件筛选"
default:
return triggerType
}
}
func (h *PollingManualTriggerHandler) getStatusName(status string) string {
switch status {
case constants.PollingManualTriggerStatusPending:
return "待处理"
case constants.PollingManualTriggerStatusProcessing:
return "处理中"
case constants.PollingManualTriggerStatusCompleted:
return "已完成"
case constants.PollingManualTriggerStatusCancelled:
return "已取消"
default:
return status
}
}