From d05d11148e0ea07519817eef28486fdf9430d50a Mon Sep 17 00:00:00 2001 From: "2569718930@qq.com" <2569718930@qq.com> Date: Mon, 25 May 2026 02:02:05 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=A0=E9=99=A4=20ProFeaturePaywall=20?= =?UTF-8?q?=E7=BB=84=E4=BB=B6=EF=BC=8C=E6=A8=A1=E6=80=81=E6=A1=86=E5=86=85?= =?UTF-8?q?=E6=94=B9=E4=B8=BA=E7=AE=80=E6=B4=81=E8=AE=A2=E9=98=85=E6=8F=90?= =?UTF-8?q?=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dashboard/FutureForecastModalContent.tsx | 26 ++++- .../dashboard/ProFeaturePaywall.tsx | 98 ------------------- 2 files changed, 21 insertions(+), 103 deletions(-) delete mode 100644 frontend/components/dashboard/ProFeaturePaywall.tsx diff --git a/frontend/components/dashboard/FutureForecastModalContent.tsx b/frontend/components/dashboard/FutureForecastModalContent.tsx index f50e7f24..4008eabb 100644 --- a/frontend/components/dashboard/FutureForecastModalContent.tsx +++ b/frontend/components/dashboard/FutureForecastModalContent.tsx @@ -1,9 +1,10 @@ "use client"; import clsx from "clsx"; +import Link from "next/link"; +import { LockKeyhole } from "lucide-react"; import { CSSProperties, useEffect, useMemo, useState } from "react"; import type { Locale } from "@/lib/i18n"; -import { ProFeaturePaywall } from "@/components/dashboard/ProFeaturePaywall"; import { getFutureModalView } from "@/lib/dashboard-utils"; import { getModelView, getProbabilityView } from "@/lib/model-utils"; import { getTodayPaceView } from "@/lib/pace-utils"; @@ -898,10 +899,25 @@ export function FutureForecastModalContent({ ) : !isPro ? ( - +
+
+ +

+ {locale === "en-US" ? "Pro subscription required" : "需要 Pro 订阅"} +

+

+ {locale === "en-US" + ? "Subscribe in Account Center to unlock full analysis." + : "请在账户中心订阅以解锁完整分析功能。"} +

+ + {locale === "en-US" ? "Subscribe" : "去订阅"} + +
+
) : (
void; -}; - -export function ProFeaturePaywall({ - feature, - onClose, -}: ProFeaturePaywallProps) { - const router = useRouter(); - const { locale } = useI18n(); - const { proAccess } = useProAccess(); - const [usePoints, setUsePoints] = useState(true); - - const isEn = locale === "en-US"; - const isAuthenticated = proAccess.authenticated; - const pointsAvailable = Number(proAccess.points || 0); - - const PRO_PRICE_USD = 10; - const POINTS_PER_USD = 500; - const MAX_DISCOUNT_USD = 3; - - const billing = useMemo(() => { - const isEligible = pointsAvailable >= POINTS_PER_USD; - const maxRedeemablePoints = MAX_DISCOUNT_USD * POINTS_PER_USD; - const boundedPoints = isEligible - ? Math.min(pointsAvailable, maxRedeemablePoints) - : 0; - const discountUnits = Math.floor(boundedPoints / POINTS_PER_USD); - const pointsUsed = discountUnits * POINTS_PER_USD; - const discountAmount = usePoints ? discountUnits : 0; - - return { - pointsEnabled: true, - isEligible, - pointsPerUsd: POINTS_PER_USD, - maxDiscountUsd: MAX_DISCOUNT_USD, - pointsUsed: usePoints ? pointsUsed : 0, - discountAmount, - finalPrice: PRO_PRICE_USD - discountAmount, - }; - }, [pointsAvailable, usePoints]); - - const payLabel = isAuthenticated - ? isEn - ? "Open Pro in Account" - : "去账户中心开通 Pro" - : isEn - ? "Sign In to Unlock Pro" - : "先登录再开通 Pro"; - - useEffect(() => { - trackAppEvent("paywall_viewed", { - entry: "feature_gate", - feature, - user_state: isAuthenticated ? "logged_in" : "guest", - }); - }, [feature, isAuthenticated]); - - return ( -
- setUsePoints((prev) => !prev)} - billing={billing} - onClose={onClose} - onPay={() => { - if (!isAuthenticated) { - router.push("/auth/login?next=%2Faccount"); - return; - } - router.push("/account"); - }} - payLabel={payLabel} - faqHref={SUBSCRIPTION_HELP_HREF} - telegramGroupUrl={TELEGRAM_GROUP_URL} - /> -
- ); -}