diff --git a/backend/app/__init__.py b/backend/app/__init__.py index 41ddb81..3a101e1 100644 --- a/backend/app/__init__.py +++ b/backend/app/__init__.py @@ -2,7 +2,7 @@ import sys -__version__ = "0.1.38" +__version__ = "0.1.39" # Windows 默认 stdout/stderr 编码为 GBK(cp936),TickFlow SDK 内部输出含 emoji 的 # 指数/标的名称(如 \U0001f193)时会抛 UnicodeEncodeError,导致请求失败。 diff --git a/backend/pyproject.toml b/backend/pyproject.toml index 83a6040..6b90017 100644 --- a/backend/pyproject.toml +++ b/backend/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "tickflow-stock-panel-backend" -version = "0.1.35" +version = "0.1.39" description = "A 股选股 + 监控 + 回测面板 — TickFlow 适配" readme = "../README.md" requires-python = ">=3.11" diff --git a/frontend/package.json b/frontend/package.json index 28dd20b..c854f1a 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,7 +1,7 @@ { "name": "tickflow-stock-panel-frontend", "private": true, - "version": "0.1.38", + "version": "0.1.39", "type": "module", "scripts": { "dev": "vite", diff --git a/frontend/src/pages/Dashboard.tsx b/frontend/src/pages/Dashboard.tsx index e8702cf..44fb5df 100644 --- a/frontend/src/pages/Dashboard.tsx +++ b/frontend/src/pages/Dashboard.tsx @@ -2,7 +2,7 @@ import { useState, type ReactNode } from 'react' import { Link } from 'react-router-dom' import { useQuery } from '@tanstack/react-query' import { motion } from 'framer-motion' -import { Activity, ArrowDownRight, ArrowUpRight, BarChart3, BellRing, Database, Flame, Gauge, LineChart, Loader2, RefreshCw, Sparkles, Target, Timer, ExternalLink, Gift } from 'lucide-react' +import { Activity, AlertTriangle, ArrowDownRight, ArrowUpRight, BarChart3, BellRing, Check, Copy, Flame, Gauge, LineChart, Loader2, RefreshCw, Sparkles, Target, Timer, ExternalLink } from 'lucide-react' import { DatePicker } from '@/components/DatePicker' import { api, type MarketSnapshotRow, type OverviewDimensionRankItem, type OverviewMarket, type AlertEvent } from '@/lib/api' import { QK } from '@/lib/queryKeys' @@ -471,6 +471,7 @@ function HotRankCard({ title, rank, configUrl }: { title: string; rank?: Overvie export function Dashboard() { const [selectedDate, setSelectedDate] = useState() const [manualFetching, setManualFetching] = useState(false) + const [copiedCode, setCopiedCode] = useState(false) const dataStatus = useDataStatus({ staleTime: 60_000 }) const overview = useQuery({ queryKey: QK.overviewMarket(selectedDate), @@ -487,8 +488,11 @@ export function Dashboard() { // none 档(无 key / 无效 key)→ 显示升级提示横幅 const isNoKey = settings.data?.mode === 'none' // 无本地数据(enriched/daily 都没有)→ 提示去数据页同步 + // 注: 后端 status 的 rows 为性能刻意返回 0, 用 trading_days 判断是否有数据 const ds = dataStatus.data - const hasNoData = !!ds && (ds.enriched?.rows ?? 0) === 0 && (ds.daily?.rows ?? 0) === 0 + const hasNoData = !!ds + && (ds.enriched?.trading_days ?? 0) === 0 + && (ds.daily?.trading_days ?? 0) === 0 // 手动刷新: 显示旋转动画; SSE 自动刷新: 静默, 无体感 const handleRefresh = () => { @@ -529,9 +533,9 @@ export function Dashboard() { {/* none 档(无 key)提示横幅 —— 引导用户领取免费 Key 解锁完整能力 */} {isNoKey && (
- + - 当前未配置 API Key,实时行情、批量同步等能力不可用。 + 当前未配置 API Key,批量同步、实时行情等能力不可用。 免费注册(或填邀请码{' '} - V3KDKGXPEA - )即可领取免费 API Key,无需付费即可体验完整功能。 + + V3KDKGXPEA + + + )即可领取免费 API Key,无需付费即可体验。
)} - {/* 无本地数据提示 —— 引导用户去数据页同步 */} - {hasNoData && ( -
- + {/* 无本地数据提示 —— 引导用户去数据页同步 (仅当已配置 Key 时显示, 无 Key 时优先提示配置 Key) */} + {hasNoData && !isNoKey && ( +
+ - 看板暂无数据,请前往数据页面同步行情数据后查看。 + 当前暂无数据,请前往数据页面同步行情数据完成后查看。 + + 前往同步数据 + + - - 前往同步 -
)}
diff --git a/frontend/src/pages/Data.tsx b/frontend/src/pages/Data.tsx index 31a516d..35b4fe1 100644 --- a/frontend/src/pages/Data.tsx +++ b/frontend/src/pages/Data.tsx @@ -1,4 +1,5 @@ import { useCallback, useEffect, useRef, useState } from 'react' +import { Link } from 'react-router-dom' import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query' import { motion, AnimatePresence } from 'framer-motion' import { @@ -214,6 +215,8 @@ export function Data() { const isRunning = job.data?.status === 'running' || job.data?.status === 'pending' const isStarting = startSync.isPending const hasData = !!(s?.instruments?.rows || s?.daily?.rows) + // none 档(无 key / 无效 key) → 禁用立即同步 (同步依赖付费档的批量端点) + const isNoKey = settings.data?.mode === 'none' const indexOverviewStats = s ? { rows: 0, earliest_date: s.index_daily?.earliest_date ?? s.index_enriched?.earliest_date ?? null, @@ -290,21 +293,31 @@ export function Data() { subtitle="本地数据画像 · 同步状态 · 历史记录" right={
- {!hasData && !isLoading && ( + {!hasData && !isLoading && !isNoKey && ( 首次使用请点击右侧按钮同步数据 )} - + 立即同步 + + ) : ( + + )}