import { Request, Response } from 'express'; import { stockService } from '../services/stockService'; import { asyncHandler, NotFoundError, BadRequestError } from '../middleware/errorHandler'; import { ApiResponse } from '../types'; import { searchKeywordSchema, periodSchema } from '../utils/validator'; export const stockController = { // 搜索股票 search: asyncHandler(async (req: Request, res: Response) => { const { keyword, type } = req.query; if (!keyword || typeof keyword !== 'string') { throw new BadRequestError('搜索关键词不能为空'); } const validatedKeyword = searchKeywordSchema.parse(keyword); let sectors: any[] = []; let stocks: any[] = []; if (!type || type === 'all' || type === 'sector') { sectors = await stockService.searchSectors(validatedKeyword); } if (!type || type === 'all' || type === 'stock') { stocks = await stockService.searchStocks(validatedKeyword); } const response: ApiResponse = { code: 200, message: 'success', data: { sectors, stocks, }, }; res.json(response); }), // 获取股票详情 getStockDetail: asyncHandler(async (req: Request, res: Response) => { const { stock_code } = req.params; const stock = await stockService.getStockDetail(stock_code); if (!stock) { throw new NotFoundError('股票不存在'); } const response: ApiResponse = { code: 200, message: 'success', data: stock, }; res.json(response); }), // 获取股票K线数据 getStockKLine: asyncHandler(async (req: Request, res: Response) => { const { stock_code } = req.params; const period = periodSchema.parse(req.query.period || 'day'); const days = parseInt(req.query.days as string) || 60; const klines = await stockService.getKLineData(stock_code, period, days); const response: ApiResponse = { code: 200, message: 'success', data: klines, }; res.json(response); }), // 获取新高股票 getNewHighStocks: asyncHandler(async (req: Request, res: Response) => { const days = parseInt(req.query.days as string) || 20; const limit = parseInt(req.query.limit as string) || 20; const stocks = await stockService.getNewHighStocks(days, limit); const response: ApiResponse = { code: 200, message: 'success', data: stocks, }; res.json(response); }), // 获取新低股票 getNewLowStocks: asyncHandler(async (req: Request, res: Response) => { const days = parseInt(req.query.days as string) || 20; const limit = parseInt(req.query.limit as string) || 20; const stocks = await stockService.getNewLowStocks(days, limit); const response: ApiResponse = { code: 200, message: 'success', data: stocks, }; res.json(response); }), // 获取动量股推荐 getMomentumRecommendation: asyncHandler(async (req: Request, res: Response) => { const limit = parseInt(req.query.limit as string) || 15; const stocks = await stockService.getMomentumStocks(limit); const response: ApiResponse = { code: 200, message: 'success', data: stocks, }; res.json(response); }), };