扫描终端按需加载:后端支持 trading_region 过滤 + skip_polymarket 快速通道

scan_terminal_service:trading_region 参数预过滤城市列表。scan_terminal_city_row:快速模式跳过 Polymarket RPC。前端 hook 支持按区域查询。
This commit is contained in:
2569718930@qq.com
2026-05-25 06:32:42 +08:00
parent dd8f1c2d73
commit d64a92fd24
4 changed files with 22 additions and 4 deletions
@@ -280,7 +280,7 @@ export function MarketOverviewView({
</div> </div>
</Panel> </Panel>
<Panel title={isEn ? "Top Opportunities" : "Top Opportunities"}> <Panel title={isEn ? "Top Opportunities" : "最佳机会"}>
<CompactRowsTable <CompactRowsTable
empty={isEn ? "No opportunities" : "暂无机会"} empty={isEn ? "No opportunities" : "暂无机会"}
isEn={isEn} isEn={isEn}
@@ -289,7 +289,7 @@ export function MarketOverviewView({
/> />
</Panel> </Panel>
<Panel title={isEn ? "Risk / Watchlist" : "Risk / Watchlist"}> <Panel title={isEn ? "Risk / Watchlist" : "风险 / 观察列表"}>
<CompactRowsTable <CompactRowsTable
empty={isEn ? "No risk rows" : "暂无风险项"} empty={isEn ? "No risk rows" : "暂无风险项"}
isEn={isEn} isEn={isEn}
@@ -53,6 +53,7 @@ type AiCityStreamEvent = {
type TerminalQueryOptions = { type TerminalQueryOptions = {
forceRefresh?: boolean; forceRefresh?: boolean;
signal?: AbortSignal; signal?: AbortSignal;
tradingRegion?: string;
}; };
type CityDetailQueryOptions = { type CityDetailQueryOptions = {
@@ -253,6 +254,7 @@ async function readAiCityForecastStream(
async function getTerminal({ async function getTerminal({
forceRefresh = false, forceRefresh = false,
signal, signal,
tradingRegion,
}: TerminalQueryOptions = {}) { }: TerminalQueryOptions = {}) {
const params = new URLSearchParams({ const params = new URLSearchParams({
scan_mode: "tradable", scan_mode: "tradable",
@@ -266,6 +268,9 @@ async function getTerminal({
force_refresh: String(forceRefresh), force_refresh: String(forceRefresh),
skip_polymarket: "true", skip_polymarket: "true",
}); });
if (tradingRegion && tradingRegion !== "all") {
params.set("trading_region", tradingRegion);
}
if (forceRefresh) { if (forceRefresh) {
params.set("_ts", String(Date.now())); params.set("_ts", String(Date.now()));
} }
@@ -13,9 +13,11 @@ import type { ScanTerminalResponse } from "@/lib/dashboard-types";
export function useScanTerminalQuery({ export function useScanTerminalQuery({
isPro, isPro,
proAccessLoading, proAccessLoading,
tradingRegion,
}: { }: {
isPro: boolean; isPro: boolean;
proAccessLoading: boolean; proAccessLoading: boolean;
tradingRegion?: string;
}) { }) {
const { const {
data: terminalData, data: terminalData,
@@ -48,11 +50,12 @@ export function useScanTerminalQuery({
scanTerminalClient.getTerminal({ scanTerminalClient.getTerminal({
forceRefresh, forceRefresh,
signal, signal,
tradingRegion,
}), }),
showLoading, showLoading,
}); });
}, },
[isPro, proAccessLoading, run], [isPro, proAccessLoading, run, tradingRegion],
); );
useEffect(() => { useEffect(() => {
@@ -62,7 +65,7 @@ export function useScanTerminalQuery({
return; return;
} }
void fetchScanTerminal({ forceRefresh: false, showLoading: true }); void fetchScanTerminal({ forceRefresh: false, showLoading: true });
}, [fetchScanTerminal, isPro, proAccessLoading, reset]); }, [fetchScanTerminal, isPro, proAccessLoading, reset, tradingRegion]);
const refreshScanTerminalManually = useCallback(() => { const refreshScanTerminalManually = useCallback(() => {
if ( if (
+10
View File
@@ -1230,6 +1230,16 @@ def _build_scan_terminal_payload_uncached(
try: try:
city_names = list(CITIES.keys()) city_names = list(CITIES.keys())
region_filter = str(filters.get("trading_region") or "").strip().lower()
if region_filter and region_filter not in ("all", ""):
from web.scan_terminal_filters import market_region_from_tz_offset as _tz_region
def _city_in_region(city_name: str) -> bool:
city_meta = CITIES.get(city_name) or {}
tz = city_meta.get("tz", 0)
return _tz_region(tz)["key"] == region_filter
city_names = [c for c in city_names if _city_in_region(c)]
max_workers = max(1, min(SCAN_TERMINAL_MAX_WORKERS, len(city_names))) max_workers = max(1, min(SCAN_TERMINAL_MAX_WORKERS, len(city_names)))
city_results: List[Dict[str, Any]] = [] city_results: List[Dict[str, Any]] = []
failed_cities: List[str] = [] failed_cities: List[str] = []