提交
This commit is contained in:
@@ -6,6 +6,11 @@ import type {
|
||||
CurrentUser,
|
||||
EventBacktestRequest,
|
||||
EventBacktestResponse,
|
||||
EtfListResponse,
|
||||
EtfSyncStatus,
|
||||
GlobalIndexList,
|
||||
IndexDetail,
|
||||
IndexWeights,
|
||||
LoginRequest,
|
||||
LoginResponse,
|
||||
MarketOverview,
|
||||
@@ -16,7 +21,11 @@ import type {
|
||||
ScreenerRunResponse,
|
||||
ScreenerSyncRequest,
|
||||
ScreenerSyncStatus,
|
||||
StockCompanyInfo,
|
||||
StockDividendOut,
|
||||
StockFacets,
|
||||
StockFinanceOut,
|
||||
StockReferenceOut,
|
||||
StockListResponse,
|
||||
SyncRequest,
|
||||
SyncResponse,
|
||||
@@ -191,6 +200,34 @@ export async function getStockPreview(
|
||||
return (await res.json()) as PreviewResponse;
|
||||
}
|
||||
|
||||
/** 个股公司简介(tushare stock_company 按需懒加载;404 = ETF/无此股,调用方据此隐藏面板) */
|
||||
export async function getStockCompany(tsCode: string): Promise<StockCompanyInfo> {
|
||||
const res = await apiFetch(`/api/stocks/${encodeURIComponent(tsCode)}/company`);
|
||||
if (!res.ok) throw new ApiError(await readError(res, `获取公司简介失败 (HTTP ${res.status})`), res.status);
|
||||
return (await res.json()) as StockCompanyInfo;
|
||||
}
|
||||
|
||||
/** 个股财务数据(fina_indicator+三大报表关键值,近五年;404 = ETF/无数据,调用方据此隐藏面板) */
|
||||
export async function getStockFinance(tsCode: string): Promise<StockFinanceOut> {
|
||||
const res = await apiFetch(`/api/stocks/${encodeURIComponent(tsCode)}/finance`);
|
||||
if (!res.ok) throw new ApiError(await readError(res, `获取财务数据失败 (HTTP ${res.status})`), res.status);
|
||||
return (await res.json()) as StockFinanceOut;
|
||||
}
|
||||
|
||||
/** 个股分红送股(tushare dividend 全历史;空 records = 确认无分红) */
|
||||
export async function getStockDividends(tsCode: string): Promise<StockDividendOut> {
|
||||
const res = await apiFetch(`/api/stocks/${encodeURIComponent(tsCode)}/dividends`);
|
||||
if (!res.ok) throw new ApiError(await readError(res, `获取分红数据失败 (HTTP ${res.status})`), res.status);
|
||||
return (await res.json()) as StockDividendOut;
|
||||
}
|
||||
|
||||
/** 个股参考数据(tushare 参考数据版块按 kind 懒加载;空 records = 确认无数据) */
|
||||
export async function getStockReference(tsCode: string, kind: string): Promise<StockReferenceOut> {
|
||||
const res = await apiFetch(`/api/stocks/${encodeURIComponent(tsCode)}/reference/${encodeURIComponent(kind)}`);
|
||||
if (!res.ok) throw new ApiError(await readError(res, `获取参考数据失败 (HTTP ${res.status})`), res.status);
|
||||
return (await res.json()) as StockReferenceOut;
|
||||
}
|
||||
|
||||
// ---------- 大盘总览(主页) ----------
|
||||
export async function getMarketOverview(): Promise<MarketOverview> {
|
||||
const res = await apiFetch('/api/market/overview');
|
||||
@@ -205,6 +242,37 @@ export async function getIndexCandles(timeframe: Timeframe): Promise<Candle[]> {
|
||||
return (await res.json()) as Candle[];
|
||||
}
|
||||
|
||||
// ---------- 指数专题(国际指数卡片 + 指数详情) ----------
|
||||
export async function getGlobalIndexes(): Promise<GlobalIndexList> {
|
||||
const res = await apiFetch('/api/market/global-indexes');
|
||||
if (!res.ok) throw new ApiError(await readError(res, '获取国际指数失败'), res.status);
|
||||
return (await res.json()) as GlobalIndexList;
|
||||
}
|
||||
|
||||
export async function getIndexDetail(code: string): Promise<IndexDetail> {
|
||||
const res = await apiFetch(`/api/market/indexes/${encodeURIComponent(code)}`);
|
||||
if (!res.ok) throw new ApiError(await readError(res, '获取指数详情失败'), res.status);
|
||||
return (await res.json()) as IndexDetail;
|
||||
}
|
||||
|
||||
/** 白名单指数全量 K 线(国内 index_daily / 国际 index_global,日线基底聚合) */
|
||||
export async function getAnyIndexCandles(code: string, timeframe: Timeframe): Promise<Candle[]> {
|
||||
const res = await apiFetch(
|
||||
`/api/market/indexes/${encodeURIComponent(code)}/candles?timeframe=${encodeURIComponent(timeframe)}`,
|
||||
);
|
||||
if (!res.ok) throw new ApiError(await readError(res, `获取指数K线失败 (HTTP ${res.status})`), res.status);
|
||||
return (await res.json()) as Candle[];
|
||||
}
|
||||
|
||||
/** 指数成分股权重(仅国内指数;国际指数后端 404) */
|
||||
export async function getIndexWeights(code: string, limit = 50): Promise<IndexWeights> {
|
||||
const res = await apiFetch(
|
||||
`/api/market/indexes/${encodeURIComponent(code)}/weights?limit=${limit}`,
|
||||
);
|
||||
if (!res.ok) throw new ApiError(await readError(res, '获取成分权重失败'), res.status);
|
||||
return (await res.json()) as IndexWeights;
|
||||
}
|
||||
|
||||
export async function getStocks(params: {
|
||||
search?: string;
|
||||
market?: string;
|
||||
@@ -237,6 +305,41 @@ export async function getStockFacets(): Promise<StockFacets> {
|
||||
return (await res.json()) as StockFacets;
|
||||
}
|
||||
|
||||
// ---------- ETF 列表(全市场浏览) ----------
|
||||
export async function getEtfs(params: {
|
||||
search?: string;
|
||||
exchange?: string;
|
||||
watched_only?: boolean;
|
||||
sort?: string;
|
||||
order?: 'asc' | 'desc';
|
||||
limit?: number;
|
||||
offset?: number;
|
||||
}): Promise<EtfListResponse> {
|
||||
const q = new URLSearchParams();
|
||||
if (params.search) q.set('search', params.search);
|
||||
if (params.exchange) q.set('exchange', params.exchange);
|
||||
if (params.watched_only) q.set('watched_only', 'true');
|
||||
if (params.sort) q.set('sort', params.sort);
|
||||
if (params.order) q.set('order', params.order);
|
||||
q.set('limit', String(params.limit ?? 100));
|
||||
q.set('offset', String(params.offset ?? 0));
|
||||
const res = await apiFetch(`/api/etfs?${q.toString()}`);
|
||||
if (!res.ok) throw new ApiError(await readError(res, `获取 ETF 列表失败 (HTTP ${res.status})`), res.status);
|
||||
return (await res.json()) as EtfListResponse;
|
||||
}
|
||||
|
||||
export async function startEtfSync(full = false): Promise<EtfSyncStatus> {
|
||||
const res = await apiFetch('/api/etf/sync', { method: 'POST', body: JSON.stringify({ full }) });
|
||||
if (!res.ok) throw new ApiError(await readError(res, `启动 ETF 同步失败 (HTTP ${res.status})`), res.status);
|
||||
return (await res.json()) as EtfSyncStatus;
|
||||
}
|
||||
|
||||
export async function getEtfSyncStatus(): Promise<EtfSyncStatus> {
|
||||
const res = await apiFetch('/api/etf/sync/status');
|
||||
if (!res.ok) throw new ApiError(await readError(res, `获取 ETF 同步状态失败 (HTTP ${res.status})`), res.status);
|
||||
return (await res.json()) as EtfSyncStatus;
|
||||
}
|
||||
|
||||
// ---------- 用户偏好 / 自选股 / 提问历史 ----------
|
||||
export async function getPreferences(): Promise<Record<string, unknown>> {
|
||||
const res = await apiFetch('/api/preferences');
|
||||
|
||||
Reference in New Issue
Block a user