移除 CityContractDetail 组件:城市详情面板不再内嵌合约查询
删除 105 行组件定义+按需拉取 Polymarket 市场数据逻辑。selectedCity 状态保留给 CityRegionList 使用。
This commit is contained in:
@@ -225,112 +225,6 @@ function CityRegionList({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function CityContractDetail({
|
|
||||||
isEn,
|
|
||||||
rows,
|
|
||||||
selectedCity,
|
|
||||||
selectedId,
|
|
||||||
onSelect,
|
|
||||||
}: {
|
|
||||||
isEn: boolean;
|
|
||||||
rows: ScanOpportunityRow[];
|
|
||||||
selectedCity: string | null;
|
|
||||||
selectedId?: string | null;
|
|
||||||
onSelect: (row: ScanOpportunityRow) => void;
|
|
||||||
}) {
|
|
||||||
const cityRows = useMemo(
|
|
||||||
() => (selectedCity ? rows.filter((r) => String(r.city || "").toLowerCase() === selectedCity) : []),
|
|
||||||
[rows, selectedCity],
|
|
||||||
);
|
|
||||||
const [marketRows, setMarketRows] = useState<ScanOpportunityRow[] | null>(null);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
setMarketRows(null);
|
|
||||||
if (!selectedCity) return;
|
|
||||||
let cancelled = false;
|
|
||||||
const baseRow = cityRows[0];
|
|
||||||
const cityName = cityRows[0]?.city_display_name || selectedCity;
|
|
||||||
fetch(`/api/city/${encodeURIComponent(cityName)}/market-scan?lite=true`, {
|
|
||||||
cache: "no-store",
|
|
||||||
headers: { Accept: "application/json" },
|
|
||||||
})
|
|
||||||
.then(async (res) => { if (!res.ok) return null; return res.json(); })
|
|
||||||
.then((json: any) => {
|
|
||||||
if (cancelled || !baseRow) return;
|
|
||||||
const scan = json?.market_scan;
|
|
||||||
if (!scan || scan.available === false) return;
|
|
||||||
const scanRows = Array.isArray(scan.scan_rows) ? scan.scan_rows : [];
|
|
||||||
if (scanRows.length) {
|
|
||||||
setMarketRows(scanRows.map((row: Partial<ScanOpportunityRow>) => ({
|
|
||||||
...baseRow,
|
|
||||||
...row,
|
|
||||||
city: baseRow.city,
|
|
||||||
city_display_name: baseRow.city_display_name,
|
|
||||||
local_date: baseRow.local_date,
|
|
||||||
local_time: baseRow.local_time,
|
|
||||||
temp_symbol: baseRow.temp_symbol,
|
|
||||||
current_temp: baseRow.current_temp,
|
|
||||||
current_max_so_far: baseRow.current_max_so_far,
|
|
||||||
deb_prediction: baseRow.deb_prediction,
|
|
||||||
trading_region: baseRow.trading_region,
|
|
||||||
trading_region_label: baseRow.trading_region_label,
|
|
||||||
trading_region_label_zh: baseRow.trading_region_label_zh,
|
|
||||||
trading_region_sort: baseRow.trading_region_sort,
|
|
||||||
tz_offset_seconds: baseRow.tz_offset_seconds,
|
|
||||||
} as ScanOpportunityRow)));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!scan.selected_slug) return;
|
|
||||||
const midpoint = scan.midpoint ?? scan.yes_midpoint ?? scan.market_price ?? null;
|
|
||||||
setMarketRows([{
|
|
||||||
...baseRow,
|
|
||||||
id: `${baseRow.city}|${scan.selected_date || baseRow.local_date || "today"}|${scan.selected_slug}|yes`,
|
|
||||||
market_slug: scan.selected_slug,
|
|
||||||
market_question: scan.primary_market?.question || scan.question || scan.selected_slug,
|
|
||||||
market_url: scan.market_url || scan.primary_market_url || (
|
|
||||||
scan.selected_slug ? `https://polymarket.com/event/${scan.selected_slug}` : null
|
|
||||||
),
|
|
||||||
selected_date: scan.selected_date || baseRow.local_date,
|
|
||||||
target_label: scan.target_label || scan.temperature_bucket?.label || scan.selected_slug,
|
|
||||||
model_probability: scan.model_probability ?? baseRow.model_probability,
|
|
||||||
market_probability: scan.market_price ?? scan.yes_midpoint ?? null,
|
|
||||||
midpoint,
|
|
||||||
ask: scan.yes_buy ?? scan.yes_ask ?? null,
|
|
||||||
bid: scan.yes_sell ?? scan.yes_bid ?? null,
|
|
||||||
spread: scan.yes_spread ?? scan.spread ?? null,
|
|
||||||
book_liquidity: scan.liquidity ?? scan.book_liquidity ?? null,
|
|
||||||
market_liquidity: scan.liquidity ?? scan.market_liquidity ?? null,
|
|
||||||
volume: scan.volume ?? baseRow.volume,
|
|
||||||
quote_source: scan.quote_source ?? baseRow.quote_source,
|
|
||||||
active: scan.primary_market?.active ?? baseRow.active,
|
|
||||||
closed: scan.primary_market?.closed ?? baseRow.closed,
|
|
||||||
accepting_orders: scan.primary_market?.acceptingOrders ?? baseRow.accepting_orders,
|
|
||||||
tradable: scan.primary_market?.active === true && scan.primary_market?.closed !== true,
|
|
||||||
}]);
|
|
||||||
})
|
|
||||||
.catch(() => {});
|
|
||||||
return () => { cancelled = true; };
|
|
||||||
}, [selectedCity, cityRows]);
|
|
||||||
|
|
||||||
const displayRows = marketRows?.length ? marketRows : cityRows;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Panel title={isEn ? "Contracts" : "合约"} className="flex-1 min-h-0">
|
|
||||||
{!selectedCity ? (
|
|
||||||
<div className="flex items-center justify-center p-6 text-[12px] text-slate-400">
|
|
||||||
{isEn ? "Select a city above" : "在上方选择城市"}
|
|
||||||
</div>
|
|
||||||
) : !cityRows.length ? (
|
|
||||||
<div className="flex items-center justify-center p-6 text-[12px] text-slate-400">
|
|
||||||
{isEn ? "No contracts for this city" : "该城市暂无合约"}
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
<KoyfinRowsTable compact isEn={isEn} onSelect={onSelect} rows={displayRows} selectedId={selectedId} />
|
|
||||||
)}
|
|
||||||
</Panel>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function PolyWeatherTerminal({
|
function PolyWeatherTerminal({
|
||||||
generatedText,
|
generatedText,
|
||||||
isEn,
|
isEn,
|
||||||
@@ -739,13 +633,6 @@ function PolyWeatherTerminal({
|
|||||||
selectedCity={selectedCity}
|
selectedCity={selectedCity}
|
||||||
onSelectCity={setSelectedCity}
|
onSelectCity={setSelectedCity}
|
||||||
/>
|
/>
|
||||||
<CityContractDetail
|
|
||||||
isEn={isEn}
|
|
||||||
rows={filteredRegionRows}
|
|
||||||
selectedCity={selectedCity}
|
|
||||||
selectedId={selectedRow?.id}
|
|
||||||
onSelect={setSelectedRow}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="min-h-0">
|
<div className="min-h-0">
|
||||||
|
|||||||
Reference in New Issue
Block a user