diff --git a/local/backend/app/api/data_sync.py b/local/backend/app/api/data_sync.py
index e714552..8f9328e 100644
--- a/local/backend/app/api/data_sync.py
+++ b/local/backend/app/api/data_sync.py
@@ -36,6 +36,7 @@ SYNCABLE_PARTS = [
"instruments_etf",
"financials",
"pools",
+ "ext_data",
]
diff --git a/serve/backend/app/api/data_sync.py b/serve/backend/app/api/data_sync.py
index de1b2b1..8e66e05 100644
--- a/serve/backend/app/api/data_sync.py
+++ b/serve/backend/app/api/data_sync.py
@@ -25,6 +25,7 @@ SYNCABLE_PARTS = {
"instruments", "instruments_index", "instruments_etf",
"financials",
"pools",
+ "ext_data",
}
diff --git a/serve/backend/app/api/financials.py b/serve/backend/app/api/financials.py
index b8414b3..ac39676 100644
--- a/serve/backend/app/api/financials.py
+++ b/serve/backend/app/api/financials.py
@@ -20,11 +20,7 @@ router = APIRouter(prefix="/api/financials", tags=["financials"])
@router.get("/status")
def financial_status(request: Request):
- """返回各财务表的同步状态。无需 FINANCIAL 权限(前端根据 available 决定是否展示)。"""
- capset = request.app.state.capabilities
- if not capset.has(Cap.FINANCIAL):
- return {"available": False, "tables": {}}
-
+ """返回各财务表的同步状态。"""
data_dir = request.app.state.repo.store.data_dir
tables = {}
@@ -42,15 +38,16 @@ def financial_status(request: Request):
else:
tables[table] = {"rows": 0, "symbols": 0}
+ capset = request.app.state.capabilities
+ has_cap = capset.has(Cap.FINANCIAL)
fs = getattr(request.app.state, "financial_scheduler", None)
last_sync = fs.last_sync if fs else {}
+ has_data = any(t.get("rows", 0) > 0 for t in tables.values())
return {
- "available": True,
+ "available": has_cap or has_data,
"tables": tables,
"last_sync": last_sync,
- # 服务端是否正在同步(手动触发)——前端据此显示"同步中"并防重复点击,
- # 且刷新页面后仍能正确反映服务端状态。
"syncing": bool(fs and fs.is_syncing),
}
@@ -58,9 +55,6 @@ def financial_status(request: Request):
@router.get("/metrics")
def get_metrics(request: Request, symbol: str | None = None):
"""查询核心财务指标。"""
- capset = request.app.state.capabilities
- capset.require(Cap.FINANCIAL)
-
df = get_financial_df(request.app.state.repo.store.data_dir, "metrics")
if df.is_empty():
return {"data": []}
@@ -72,9 +66,6 @@ def get_metrics(request: Request, symbol: str | None = None):
@router.get("/income")
def get_income(request: Request, symbol: str | None = None):
"""查询利润表。"""
- capset = request.app.state.capabilities
- capset.require(Cap.FINANCIAL)
-
df = get_financial_df(request.app.state.repo.store.data_dir, "income")
if df.is_empty():
return {"data": []}
@@ -86,9 +77,6 @@ def get_income(request: Request, symbol: str | None = None):
@router.get("/balance-sheet")
def get_balance_sheet(request: Request, symbol: str | None = None):
"""查询资产负债表。"""
- capset = request.app.state.capabilities
- capset.require(Cap.FINANCIAL)
-
df = get_financial_df(request.app.state.repo.store.data_dir, "balance_sheet")
if df.is_empty():
return {"data": []}
@@ -100,9 +88,6 @@ def get_balance_sheet(request: Request, symbol: str | None = None):
@router.get("/cash-flow")
def get_cash_flow(request: Request, symbol: str | None = None):
"""查询现金流量表。"""
- capset = request.app.state.capabilities
- capset.require(Cap.FINANCIAL)
-
df = get_financial_df(request.app.state.repo.store.data_dir, "cash_flow")
if df.is_empty():
return {"data": []}
diff --git a/serve/frontend/src/pages/Financials.tsx b/serve/frontend/src/pages/Financials.tsx
index 70741d9..953af5f 100644
--- a/serve/frontend/src/pages/Financials.tsx
+++ b/serve/frontend/src/pages/Financials.tsx
@@ -57,42 +57,56 @@ export function Financials() {
rememberStock(symbol, name)
}
+ // 无 Expert 能力时: 等 status 加载完, 判断是否有从 local 同步来的数据
if (!hasFinancial) {
- return (
- <>
-
- 财务数据接口仅 Expert 套餐可用。升级后此页自动显示财务数据面板。 -
- {/* 当前财务数据源(TickFlow)需付费,后续将接入免费数据源;期间欢迎在 issues 推荐免费源 */} -- 当前财务数据源需付费,后续会接入免费数据源。如你常用某个免费财务数据源,欢迎在 Issues 中多多推荐哈 ~ +
+ 财务数据接口仅 Expert 套餐可用。升级后此页自动显示财务数据面板。
- - 前往 Issues 推荐 -