|
|
@@ -5,6 +5,7 @@ import { StockDataService } from '@/server/modules/stock/stock-data.service';
|
|
|
import { AuthContext } from '@/server/types/context';
|
|
|
import { authMiddleware } from '@/server/middleware/auth.middleware';
|
|
|
import { ErrorSchema } from '@/server/utils/errorHandler';
|
|
|
+import dayjs from 'dayjs';
|
|
|
|
|
|
// 路径参数Schema
|
|
|
const GetStockHistoryParams = z.object({
|
|
|
@@ -120,9 +121,56 @@ const app = new OpenAPIHono<AuthContext>().openapi(routeDef, async (c) => {
|
|
|
const { code } = c.req.valid('param');
|
|
|
const service = new StockDataService(AppDataSource);
|
|
|
|
|
|
- const data = await service.getStockHistory(code);
|
|
|
+ const rawData = await service.getStockHistory(code);
|
|
|
|
|
|
- return c.json({ data }, 200);
|
|
|
+ // 转换服务输出格式为schema要求的格式
|
|
|
+ const formattedData = rawData.map(item => ({
|
|
|
+ d: dayjs(item.t).format('YYYY-MM-DD') , // 交易时间 -> 日期
|
|
|
+ o: item.o, // 开盘价
|
|
|
+ h: item.h, // 最高价
|
|
|
+ l: item.l, // 最低价
|
|
|
+ c: item.c, // 收盘价
|
|
|
+ v: item.v, // 成交量
|
|
|
+ e: item.a, // 成交额 -> 成交额
|
|
|
+ zf: 0, // 振幅 (计算值)
|
|
|
+ hs: 0, // 换手率 (计算值)
|
|
|
+ zd: 0, // 涨跌额 (计算值)
|
|
|
+ zde: 0, // 涨跌幅 (计算值)
|
|
|
+ ud: new Date().toISOString() // 最后更新时间
|
|
|
+ }));
|
|
|
+
|
|
|
+ // 计算衍生字段
|
|
|
+ const processedData = formattedData.map((item, index, array) => {
|
|
|
+ if (index === 0) {
|
|
|
+ // 第一条数据无法计算涨跌
|
|
|
+ return {
|
|
|
+ ...item,
|
|
|
+ zd: 0,
|
|
|
+ zde: 0,
|
|
|
+ zf: 0
|
|
|
+ };
|
|
|
+ }
|
|
|
+
|
|
|
+ const prevItem = array[index - 1];
|
|
|
+ const zd = item.c - prevItem.c; // 涨跌额
|
|
|
+ const zde = prevItem.c !== 0 ? (zd / prevItem.c) * 100 : 0; // 涨跌幅百分比
|
|
|
+ const zf = prevItem.c !== 0 ? ((item.h - item.l) / prevItem.c) * 100 : 0; // 振幅百分比
|
|
|
+
|
|
|
+ return {
|
|
|
+ ...item,
|
|
|
+ zd: parseFloat(zd.toFixed(2)),
|
|
|
+ zde: parseFloat(zde.toFixed(2)),
|
|
|
+ zf: parseFloat(zf.toFixed(2))
|
|
|
+ };
|
|
|
+ });
|
|
|
+
|
|
|
+ // 设置换手率为0(需要从其他数据源获取)
|
|
|
+ const finalData = processedData.map(item => ({
|
|
|
+ ...item,
|
|
|
+ hs: 0
|
|
|
+ }));
|
|
|
+
|
|
|
+ return c.json({ data: finalData }, 200);
|
|
|
} catch (error) {
|
|
|
const { code = 500, message = '获取股票历史数据失败' } = error as Error & { code?: number };
|
|
|
return c.json({ code, message }, 500);
|