import { memo, useRef, useState } from 'react' import { useNavigate } from 'react-router' import { useTranslation } from 'react-i18next' import { Lock, Sparkles } from 'lucide-react' import { toast } from 'sonner' import { Button } from '@/components/ui/button' import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card' import { Input } from '@/components/ui/input' import { InstanceIdRow } from '@/components/InstanceIdRow' import { LicenseStatusBanners } from '@/components/LicenseStatusBanners' import { licenseApi } from '@/api/license' import { useLicense } from '@/hooks/useLicense' /** Pro 功能升级引导卡:免费版进入 Pro 页面时整页替代展示 */ export const ProGate = memo(function ProGate({ featureKey }: { featureKey: string }) { const { t } = useTranslation('license') const { pro, info, reload } = useLicense() const navigate = useNavigate() const [key, setKey] = useState('') const [activating, setActivating] = useState(false) const inputRef = useRef(null) const focusKey = () => { inputRef.current?.focus() inputRef.current?.scrollIntoView({ behavior: 'smooth', block: 'center' }) } const activate = async () => { if (!key.trim()) return setActivating(true) try { await licenseApi.activate(key.trim()) toast.success(t('activated')) reload() } catch (err) { toast.error(err instanceof Error ? err.message : t('activateFailed')) } finally { setActivating(false) } } return (
{t('gate.title', { feature: t(`features.${featureKey}`) })}

{t('gate.desc')}

    {['log_analysis', 'log_alerts', 'ai_ops', 'audit_log'].map(f => (
  • {t(`features.${f}`)}
  • ))}
{/* 价卡暂留;product/plan 建好后再对齐 trial/年付/永久 */}

{t('pricing.personalTitle')}

¥199 {t('pricing.permanent')}

{t('pricing.personalDesc')}

{t('pricing.teamTitle')}

¥499 {t('pricing.permanent')}

{t('pricing.teamDesc')}

{t('activateHint')}

setKey(e.target.value)} placeholder={t('gate.keyPlaceholder')} className="font-mono text-sm" />

{t('gate.freeHint')}

) })