// Package handler HTTP Handler实现 package handler import ( "context" "fmt" "market-data-service/api" "market-data-service/internal/service" ) // Handler HTTP处理器实现 type Handler struct { stockService service.StockService futuresService service.FuturesService adminService service.AdminService } // NewHandler 创建Handler func NewHandler( stockService service.StockService, futuresService service.FuturesService, adminService service.AdminService, ) *Handler { return &Handler{ stockService: stockService, futuresService: futuresService, adminService: adminService, } } // 确保Handler实现了api.Handler接口 var _ api.Handler = (*Handler)(nil) // ============================================ // 股票接口实现 // ============================================ // QueryKLines 查询股票K线 func (h *Handler) QueryKLines(ctx context.Context, req *api.KLineQueryRequest) (*api.Response, error) { // 参数校验 if err := validateKLineRequest(req); err != nil { return nil, err } // 调用Service层 data, err := h.stockService.QueryKLines(ctx, req) if err != nil { return nil, err } return &api.Response{ Code: 0, Message: "success", Data: data, }, nil } // ListSymbols 查询股票标的列表 func (h *Handler) ListSymbols(ctx context.Context, req *api.SymbolListRequest) (*api.Response, error) { // 设置默认值 if req.Page <= 0 { req.Page = 1 } if req.Size <= 0 { req.Size = 20 } if req.Size > 100 { req.Size = 100 } data, err := h.stockService.ListSymbols(ctx, req) if err != nil { return nil, err } return &api.Response{ Code: 0, Message: "success", Data: data, }, nil } // BatchQueryKLines 批量查询股票K线 func (h *Handler) BatchQueryKLines(ctx context.Context, req *api.BatchKLineRequest) (*api.Response, error) { if err := validateBatchKLineRequest(req); err != nil { return nil, err } data, err := h.stockService.BatchQueryKLines(ctx, req) if err != nil { return nil, err } return &api.Response{ Code: 0, Message: "success", Data: data, }, nil } // ============================================ // 期货接口实现 // ============================================ // QueryKLines 查询期货K线(期货Handler) func (h *Handler) QueryKLines(ctx context.Context, req *api.KLineQueryRequest) (*api.Response, error) { if err := validateKLineRequest(req); err != nil { return nil, err } data, err := h.futuresService.QueryKLines(ctx, req) if err != nil { return nil, err } return &api.Response{ Code: 0, Message: "success", Data: data, }, nil } // ListSymbols 查询期货标的列表 func (h *Handler) ListSymbols(ctx context.Context, req *api.SymbolListRequest) (*api.Response, error) { if req.Page <= 0 { req.Page = 1 } if req.Size <= 0 { req.Size = 20 } if req.Size > 100 { req.Size = 100 } data, err := h.futuresService.ListSymbols(ctx, req) if err != nil { return nil, err } return &api.Response{ Code: 0, Message: "success", Data: data, }, nil } // BatchQueryKLines 批量查询期货K线 func (h *Handler) BatchQueryKLines(ctx context.Context, req *api.BatchKLineRequest) (*api.Response, error) { if err := validateBatchKLineRequest(req); err != nil { return nil, err } data, err := h.futuresService.BatchQueryKLines(ctx, req) if err != nil { return nil, err } return &api.Response{ Code: 0, Message: "success", Data: data, }, nil } // QueryContinuousKLines 查询主力连续合约K线(预留) func (h *Handler) QueryContinuousKLines(ctx context.Context, underlying string, req *api.KLineQueryRequest) (*api.Response, error) { // TODO: 首期返回空数据或错误提示 return &api.Response{ Code: 0, Message: "success", Data: &api.KLineData{ Symbol: underlying + ".MAIN", Name: underlying + "主力连续", Freq: req.Freq, Count: 0, Items: []api.KLineItem{}, }, }, nil } // ============================================ // 管理接口实现 // ============================================ // GetDataSourceStatus 获取数据源状态 func (h *Handler) GetDataSourceStatus(ctx context.Context) (*api.Response, error) { data, err := h.adminService.GetDataSourceStatus(ctx) if err != nil { return nil, err } return &api.Response{ Code: 0, Message: "success", Data: data, }, nil } // SwitchDataSource 切换数据源 func (h *Handler) SwitchDataSource(ctx context.Context, req *api.SourceSwitchRequest) (*api.Response, error) { if err := h.adminService.SwitchDataSource(ctx, req); err != nil { return nil, err } return &api.Response{ Code: 0, Message: "数据源切换成功", Data: nil, }, nil } // BackfillData 历史数据补录 func (h *Handler) BackfillData(ctx context.Context, req *api.BackfillRequest) (*api.Response, error) { // 异步启动补录任务 taskID, err := h.adminService.BackfillData(ctx, req) if err != nil { return nil, err } return &api.Response{ Code: 0, Message: "补录任务已启动", Data: map[string]string{ "task_id": taskID, }, }, nil } // HealthCheck 健康检查 func (h *Handler) HealthCheck(ctx context.Context) (*api.HealthResponse, error) { // TODO: 检查数据库连接、数据源连通性等 return h.adminService.HealthCheck(ctx) } // ============================================ // 新增接口:交易日历和期货合约 // ============================================ // GetTradingDates 获取股票交易日历 func (h *Handler) GetTradingDates(ctx context.Context, req *api.TradingDatesRequest) (*api.Response, error) { if err := validateTradingDatesRequest(req); err != nil { return nil, err } // 通过请求路径判断是股票还是期货,这里简化处理 // 实际可以通过gin的context或其他方式判断 data, err := h.stockService.GetTradingDates(ctx, req) if err != nil { return nil, err } return &api.Response{ Code: 0, Message: "success", Data: data, }, nil } // GetContractsByUnderlying 根据品种获取可交易合约 func (h *Handler) GetContractsByUnderlying(ctx context.Context, req *api.FuturesContractsRequest) (*api.Response, error) { if req.Underlying == "" { return nil, fmt.Errorf("underlying不能为空") } data, err := h.futuresService.GetContractsByUnderlying(ctx, req) if err != nil { return nil, err } return &api.Response{ Code: 0, Message: "success", Data: data, }, nil } // ============================================ // 私有辅助函数 // ============================================ func validateKLineRequest(req *api.KLineQueryRequest) error { if req.Symbol == "" { return fmt.Errorf("symbol不能为空") } if req.Start == "" || len(req.Start) != 8 { return fmt.Errorf("start日期格式错误,应为YYYYMMDD") } if req.End == "" || len(req.End) != 8 { return fmt.Errorf("end日期格式错误,应为YYYYMMDD") } if req.Freq == "" { req.Freq = api.Freq1D } return nil } func validateBatchKLineRequest(req *api.BatchKLineRequest) error { if len(req.Symbols) == 0 { return fmt.Errorf("symbols不能为空") } if len(req.Symbols) > 100 { return fmt.Errorf("单次查询标的数不能超过100") } if req.Start == "" || len(req.Start) != 8 { return fmt.Errorf("start日期格式错误,应为YYYYMMDD") } if req.End == "" || len(req.End) != 8 { return fmt.Errorf("end日期格式错误,应为YYYYMMDD") } if req.Freq == "" { req.Freq = api.Freq1D } return nil } func validateTradingDatesRequest(req *api.TradingDatesRequest) error { if req.Start == "" || len(req.Start) != 8 { return fmt.Errorf("start日期格式错误,应为YYYYMMDD") } if req.End == "" || len(req.End) != 8 { return fmt.Errorf("end日期格式错误,应为YYYYMMDD") } return nil }