扫描终端按需加载:后端支持 trading_region 过滤 + skip_polymarket 快速通道
scan_terminal_service:trading_region 参数预过滤城市列表。scan_terminal_city_row:快速模式跳过 Polymarket RPC。前端 hook 支持按区域查询。
This commit is contained in:
@@ -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 (
|
||||||
|
|||||||
@@ -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] = []
|
||||||
|
|||||||
Reference in New Issue
Block a user