feat: unified map click selection & switch to decision cards with paywall overlay for non-Pro users

This commit is contained in:
2569718930@qq.com
2026-05-20 09:41:44 +08:00
parent 23f7e29acc
commit 4de009b401
@@ -16,6 +16,7 @@ import type { ScanOpportunityRow } from "@/lib/dashboard-types";
import { AiPinnedForecastView } from "@/components/dashboard/scan-terminal/AiPinnedForecastView"; import { AiPinnedForecastView } from "@/components/dashboard/scan-terminal/AiPinnedForecastView";
import { MobileCityPicker } from "@/components/dashboard/scan-terminal/MobileCityPicker"; import { MobileCityPicker } from "@/components/dashboard/scan-terminal/MobileCityPicker";
import { WelcomeOverlay } from "@/components/dashboard/scan-terminal/WelcomeOverlay"; import { WelcomeOverlay } from "@/components/dashboard/scan-terminal/WelcomeOverlay";
import { ProFeaturePaywall } from "@/components/dashboard/ProFeaturePaywall";
import { import {
ScanPaywallModal, ScanPaywallModal,
ScanTerminalLoadingScreen, ScanTerminalLoadingScreen,
@@ -331,12 +332,11 @@ function ScanTerminalScreen() {
void store.ensureCityDetail(cityName, false, "panel").catch(() => {}); void store.ensureCityDetail(cityName, false, "panel").catch(() => {});
setSelectedRowId(null); setSelectedRowId(null);
} }
if (isPro) { void store.selectCity(cityName);
addAiPinnedCity(cityName); addAiPinnedCity(cityName);
setActiveView("analysis"); setActiveView("analysis");
}
}, },
[store, timeSortedRows, isPro, addAiPinnedCity], [store, timeSortedRows, addAiPinnedCity],
); );
useEffect(() => { useEffect(() => {
@@ -400,7 +400,7 @@ function ScanTerminalScreen() {
<MobileCityPicker <MobileCityPicker
isEn={isEn} isEn={isEn}
rows={cityListRows} rows={cityListRows}
onSelectCity={isPro ? handleOpenDecisionRow : handleSelectRow} onSelectCity={handleOpenDecisionRow}
/> />
); );
} }
@@ -420,7 +420,8 @@ function ScanTerminalScreen() {
/> />
</div> </div>
</div> </div>
{resolvedView === "analysis" && isPro ? ( {resolvedView === "analysis" ? (
isPro ? (
<AiPinnedForecastView <AiPinnedForecastView
items={aiPinnedCities} items={aiPinnedCities}
rows={timeSortedRows} rows={timeSortedRows}
@@ -429,6 +430,11 @@ function ScanTerminalScreen() {
onRefreshCityDetail={refreshAiPinnedCityDetail} onRefreshCityDetail={refreshAiPinnedCityDetail}
onRemoveCity={removeAiPinnedCity} onRemoveCity={removeAiPinnedCity}
/> />
) : (
<div className="scan-ai-workspace empty">
<ProFeaturePaywall feature="scan" />
</div>
)
) : null} ) : null}
</> </>
); );
@@ -545,7 +551,6 @@ function ScanTerminalScreen() {
{isEn ? "Distribution View" : "分布视图"} {isEn ? "Distribution View" : "分布视图"}
</button> </button>
)} )}
{isPro ? (
<button <button
type="button" type="button"
role="tab" role="tab"
@@ -556,8 +561,12 @@ function ScanTerminalScreen() {
}} }}
> >
{isEn ? "Decision Cards" : "城市决策卡"} {isEn ? "Decision Cards" : "城市决策卡"}
{!isPro && (
<span className="scan-lock-icon" style={{ marginLeft: "4.5px", fontSize: "13.5px" }}>
🔒
</span>
)}
</button> </button>
) : null}
</div> </div>
<div className="scan-list-status"> <div className="scan-list-status">
{terminalData?.generated_at ? ( {terminalData?.generated_at ? (