diff --git a/docs/COMMERCIALIZATION.md b/docs/COMMERCIALIZATION.md index ee23c979..3007c57b 100644 --- a/docs/COMMERCIALIZATION.md +++ b/docs/COMMERCIALIZATION.md @@ -40,7 +40,7 @@ PolyWeather 是面向温度结算场景的气象决策层,不是通用天气 - 概率分布层(基于 DEB 融合 + 高斯分桶) - 实时终端多城市图表(跑道/官方站点/DEB/概率带) - 历史对账 + 未来日期分析 - - 全平台智能气象推送 + - Telegram 缓存推送与业务频道通知 ## 4. 收费与积分规则(默认) diff --git a/frontend/app/subscription-help/SubscriptionHelpClient.tsx b/frontend/app/subscription-help/SubscriptionHelpClient.tsx index 826f289c..45a54ab1 100644 --- a/frontend/app/subscription-help/SubscriptionHelpClient.tsx +++ b/frontend/app/subscription-help/SubscriptionHelpClient.tsx @@ -16,8 +16,8 @@ const FAQ_ITEMS = [ { q_zh: "Pro 包含哪些功能?", q_en: "What features does Pro include?", - a_zh: "开通后可解锁:天气决策台、多城市图表巡检、未来日期分析、全平台智能气象推送。", - a_en: "Unlocks: weather decision terminal, multi-city chart monitoring, future-date analysis, and cross-platform smart weather push.", + a_zh: "开通后可解锁:结算源优先终端、多城市图表巡检、未来日期分析、Telegram 缓存推送。", + a_en: "Unlocks: settlement-source-first terminal, multi-city chart monitoring, future-date analysis, and Telegram cached alerts.", }, { q_zh: "当前订阅价格是多少?", diff --git a/frontend/components/account/AccountCenter.tsx b/frontend/components/account/AccountCenter.tsx index 019ca90a..fe0c7729 100644 --- a/frontend/components/account/AccountCenter.tsx +++ b/frontend/components/account/AccountCenter.tsx @@ -41,11 +41,9 @@ import { } from "@/lib/supabase/client"; import { markAnalyticsOnce, trackAppEvent } from "@/lib/app-analytics"; import { useI18n } from "@/hooks/useI18n"; -import { UnlockProOverlay } from "@/components/subscription/UnlockProOverlay"; import type { AuthMeResponse } from "./types"; import { - SUBSCRIPTION_HELP_HREF, TELEGRAM_BOT_URL, TELEGRAM_GROUP_URL, TELEGRAM_TOPICS_GROUP_URL, @@ -85,7 +83,6 @@ export function AccountCenter() { const [trialValueReplay, setTrialValueReplay] = useState(() => readTrialValueReplay()); // ── Shared state (declared in component, written by hook via setters) ─ - const [showOverlay, setShowOverlay] = useState(false); const [usePoints, setUsePoints] = useState(true); const [errorText, setErrorText] = useState(""); const [updatedAt, setUpdatedAt] = useState(""); @@ -104,7 +101,6 @@ export function AccountCenter() { paymentInfo, paymentError, lastIntentId, - lastTxHash, lastPaymentStartedAt, telegramBindOpening, telegramBindUrl, @@ -158,7 +154,6 @@ export function AccountCenter() { allowedPaymentHosts, currentPaymentHost, paymentHostAllowed, - selectedPlan, selectedPaymentToken, selectedTokenLabel, availableTokenList, @@ -168,7 +163,6 @@ export function AccountCenter() { resolvedSelectedTokenAddress, paymentReceiverAddress, paymentWalletLabel, - hasPayingWallet, totalPoints, billing, @@ -177,11 +171,9 @@ export function AccountCenter() { loadPaymentSnapshot, connectAndBindWallet, handleUnbindWallet, - createIntentAndPay, createManualPaymentIntent, submitManualPaymentTx, validateTxHash, - handleOverlayCheckout, createTelegramBotBindCommand, openTelegramBotBindLink, } = useAccountPayment({ @@ -195,8 +187,6 @@ export function AccountCenter() { setBackend, setErrorText, setUpdatedAt, - showOverlay, - setShowOverlay, usePoints, setUsePoints, }); @@ -408,7 +398,7 @@ export function AccountCenter() { ); const paymentFeatureReady = paymentReadyForRecovery; const canTrialUpgrade = Boolean(isSubscribed && isTrialSubscription); - const canOpenCheckoutOverlay = Boolean( + const canStartPayment = Boolean( paymentFeatureReady && (canTrialUpgrade || !isSubscribed || showExpiringSoon || showExpiredReminder), ); @@ -441,14 +431,7 @@ export function AccountCenter() { { plan_code: "pro_monthly", plan_id: 101, amount_usdc: "29.9", duration_days: 30 }, { plan_code: "pro_quarterly", plan_id: 102, amount_usdc: "79.9", duration_days: 90 }, ]; - const selectedPlanDurationDays = Number(selectedPlan?.duration_days || 30); - const overlayPlanLabel = - selectedPlanCode === "pro_quarterly" - ? copy.quarterlyPlan - : copy.monthlyPlan; - const overlayPeriodLabel = isEn - ? `/ ${selectedPlanDurationDays} days` - : `/ ${selectedPlanDurationDays} 天`; + const manualTxHashReady = /^0x[a-fA-F0-9]{64}$/.test(manualTxHash.trim()); const trialValueReplaySummary = useMemo( () => buildTrialValueReplaySummary(trialValueReplay, { isEn, @@ -466,9 +449,7 @@ export function AccountCenter() { referralCodeInput.trim(), ); - // ── Payment overlay tracking effect ────────────────────── - useEffect(() => { - if (!showOverlay || !canOpenCheckoutOverlay) return; + const focusPaymentManagement = useCallback(() => { trackAppEvent("paywall_viewed", { entry: "account_center", user_state: isAuthenticated ? "logged_in" : "guest", @@ -476,26 +457,25 @@ export function AccountCenter() { expiring_soon: showExpiringSoon, subscription_plan_code: planCode || null, }); + const paymentSection = document.getElementById("payment-management"); + paymentSection?.scrollIntoView({ behavior: "smooth", block: "start" }); }, [ isAuthenticated, - canOpenCheckoutOverlay, planCode, showExpiredReminder, showExpiringSoon, - showOverlay, ]); useEffect(() => { - if (showOverlay || !canOpenCheckoutOverlay) return; if (searchParams.get("checkout") === "1") { - setShowOverlay(true); + window.setTimeout(focusPaymentManagement, 0); } - }, [canOpenCheckoutOverlay, searchParams, showOverlay]); + }, [focusPaymentManagement, searchParams]); useEffect(() => { if (!isTrialSubscription) return; setTrialValueReplay(readTrialValueReplay()); - }, [authUserId, isTrialSubscription, showOverlay]); + }, [authUserId, isTrialSubscription]); const openTrialValueReplayCheckout = useCallback(() => { trackAppEvent("paywall_feature_clicked", { @@ -507,8 +487,8 @@ export function AccountCenter() { replay_rows_available: trialValueReplay.rowsAvailableMax, subscription_plan_code: planCode || null, }); - setShowOverlay(true); - }, [authUserId, planCode, trialValueReplay]); + focusPaymentManagement(); + }, [authUserId, focusPaymentManagement, planCode, trialValueReplay]); // ── Referral points display ──────────────────────────── const referralRewardPointsRaw = Number(referral?.reward_points ?? 3500); @@ -641,9 +621,10 @@ export function AccountCenter() {
- {!showOverlay && canOpenCheckoutOverlay && ( + {canStartPayment && (