From 7a96d51f8a1de4b97f4e8ecba26aedde5c3e5914 Mon Sep 17 00:00:00 2001 From: fish Date: Mon, 6 Jul 2026 16:04:47 +0800 Subject: [PATCH] =?UTF-8?q?=E8=B4=A2=E5=8A=A1=E5=88=86=E6=9E=90=E7=A7=BB?= =?UTF-8?q?=E9=99=A4=20Expert=20=E5=A5=97=E9=A4=90=E8=83=BD=E5=8A=9B?= =?UTF-8?q?=E9=97=A8=E6=8E=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit serve 只读模式,财务数据仅来自 local 同步, 不再依赖 TickFlow Expert 能力。 Co-Authored-By: Claude --- serve/frontend/src/pages/Financials.tsx | 72 +++++++------------------ 1 file changed, 20 insertions(+), 52 deletions(-) diff --git a/serve/frontend/src/pages/Financials.tsx b/serve/frontend/src/pages/Financials.tsx index 4093256..886f5c8 100644 --- a/serve/frontend/src/pages/Financials.tsx +++ b/serve/frontend/src/pages/Financials.tsx @@ -2,8 +2,7 @@ import { useState, useEffect } from 'react' import { RefreshCw, Lock, Loader2, X, Search, FileText, Database, CheckCircle2, Hourglass, Lightbulb, ExternalLink } from 'lucide-react' import { PageHeader } from '@/components/PageHeader' import { EmptyState } from '@/components/EmptyState' -import { useCapabilities } from '@/lib/useSharedQueries' -import { useFinancialStatus, useFinancialSync } from '@/lib/useFinancials' +import { useFinancialStatus } from '@/lib/useFinancials' import { StockFinancialSearch } from '@/components/financials/StockFinancialSearch' import { StockFinancialDetail } from '@/components/financials/StockFinancialDetail' import { ReportHistoryPanel } from '@/components/financials/ReportHistoryPanel' @@ -27,63 +26,32 @@ const TABLE_ICON: Record = { } export function Financials() { - const { data: caps } = useCapabilities() - const hasFinancial = caps?.capabilities?.['financial'] != null const { data: status, isLoading } = useFinancialStatus() - const syncMut = useFinancialSync() - // 同步进行中 = 服务端真值(status.syncing)或本地乐观态(请求已发出待确认)。 - // 乐观窗口:点击后到 invalidate 触发的 refetch 返回之间,status.syncing 暂为 false, - // 用 syncMut.isPending 覆盖,让按钮立即置灰、避免重复点击。 - // 后端 trigger() 返回时 syncing 已为 true,refetch 到达后 status.syncing 接管。 - const syncing = (status?.syncing ?? false) || syncMut.isPending - // 本次同步开始时间戳(ms): 用于判断每张表的 last_sync 是否属于本次同步 - // (后端每张表完成即更新 last_sync, 前端轮询时对比时间戳得到精确进度) - const [syncStartedAt, setSyncStartedAt] = useState(null) - // 单表同步时记录表名 (null = 全量同步), 用于区分卡片状态 - const [syncSingleTable, setSyncSingleTable] = useState(null) - // 同步自然结束(服务端 syncing 由 true→false):清空本次同步记录。 - // 这是可靠的收尾时机 —— 不依赖 mutation 的 onSettled(它现在瞬间触发,会误清)。 - useEffect(() => { - if (!syncing && syncStartedAt !== null) { - setSyncStartedAt(null) - setSyncSingleTable(null) - } - }, [syncing, syncStartedAt]) - // 选中的个股(模糊搜索结果);null 时显示搜索引导 - const [selected, setSelected] = useState<{ symbol: string; name: string } | null>(null) const { last: lastStock, remember: rememberStock } = useLastStock('financials') + const [selected, setSelected] = useState<{ symbol: string; name: string } | null>(null) const pick = (symbol: string, name: string) => { setSelected({ symbol, name }) rememberStock(symbol, name) } - // 无 Expert 能力时: 等 status 加载完, 判断是否有从 local 同步来的数据 - if (!hasFinancial) { - if (isLoading) { - return ( - <> - -
- -
- - ) - } - if (!status?.available) { - // 既无 Expert 能力, 也无同步数据 → 锁定页 - return ( - <> - -
-
-
- -
-

需要 Expert 套餐

-

- 财务数据接口仅 Expert 套餐可用。升级后此页自动显示财务数据面板。 -

-
+ // 等待 status 加载完, 判断是否有从 local 同步来的数据 + if (isLoading) { + return ( + <> + +
+ +
+ + ) + } + if (!status?.available) { + // 无同步数据 + return ( + <> + +
+
关于数据源