import { useState, useEffect, useRef } from 'react' import { View, Text, StyleSheet, ScrollView, Pressable, StatusBar as RNStatusBar, Platform, useWindowDimensions, } from 'react-native' import { StatusBar } from 'expo-status-bar' import { LinearGradient } from 'expo-linear-gradient' import { SafeAreaView, useSafeAreaInsets } from 'react-native-safe-area-context' import { useRouter } from 'expo-router' import { useTranslation } from 'react-i18next' import { Image } from 'expo-image' import Carousel from 'react-native-reanimated-carousel' import Svg, { Path, Defs, LinearGradient as SvgLinearGradient, Stop } from 'react-native-svg' import { CheckIcon, LeftArrowIcon, OmitIcon, UncheckedIcon, TermsIcon, PrivacyIcon } from '@/components/icon' import { CheckMarkIcon } from '@/components/icon/checkMark' import PointsDrawer from '@/components/drawer/PointsDrawer' import Dropdown from '@/components/ui/dropdown' import GradientText from '@/components/GradientText' // 使用唯一 id 的 PointsIcon,避免与其他页面的图标 id 冲突 const MembershipPointsIcon = () => { const gradientId = 'paint0_linear_membership' return ( ) } type PlanType = 'plus' | 'pro' | 'plus-premium' interface Plan { id: PlanType name: string price: number recommended?: boolean points: number // 每月积分 features: string[] // 功能列表 } export default function MembershipScreen() { const router = useRouter() const insets = useSafeAreaInsets() const { width: screenWidth } = useWindowDimensions() const [selectedPlan, setSelectedPlan] = useState('pro') const [agreed, setAgreed] = useState(false) const [pointsDrawerVisible, setPointsDrawerVisible] = useState(false) const { t } = useTranslation() // 订阅计划数据(使用国际化) const plans: Plan[] = [ { id: 'plus', name: 'Plus', price: 9, points: 750, features: [ t('membership.features.points750'), t('membership.features.textToVideo'), t('membership.features.superClearImage'), t('membership.features.superDiscount'), ] }, { id: 'pro', name: 'Pro', price: 29, recommended: true, points: 1080, features: [ t('membership.features.points1080'), t('membership.features.textToVideo'), t('membership.features.superClearImage'), t('membership.features.superDiscount'), t('membership.features.sora2ProTemplate'), t('membership.features.removeWatermark'), t('membership.features.allTemplates'), ] }, { id: 'plus-premium', name: 'Plus', price: 49, points: 1500, features: [ t('membership.features.points1500'), t('membership.features.textToVideo'), t('membership.features.superClearImage'), t('membership.features.superDiscount'), t('membership.features.sora2ProTemplate'), t('membership.features.removeWatermark'), t('membership.features.allTemplates'), t('membership.features.higherQuality'), t('membership.features.prioritySupport'), ] }, ] // 下拉菜单选项 const menuOptions = [ { label: t('membership.terms'), value: 'terms' }, { label: t('membership.privacy'), value: 'privacy' }, ] // 处理菜单选择 const handleMenuSelect = (value: string) => { if (value === 'terms') { router.push('/terms') } else if (value === 'privacy') { router.push('/privacy') } } // 轮播图相关 const carouselImages = [ require('@/assets/images/membership.png'), require('@/assets/images/icon.png'), require('@/assets/images/generate.png'), ] const [currentImageIndex, setCurrentImageIndex] = useState(0) // 获取当前选中计划的信息 const currentPlan = plans.find(plan => plan.id === selectedPlan) || plans[1] // 计算进度条百分比:当前计划积分 / 最高计划积分 const maxPoints = Math.max(...plans.map(plan => plan.points)) const progressPercentage = (currentPlan.points / maxPoints) * 100 return ( {/* 顶部导航栏 - 固定在顶部 */} router.back()} > setPointsDrawerVisible(true)} > {t('membership.myPoints')} 60 handleMenuSelect(value)} offsetTop={10} renderTrigger={(selectedOption, isOpen, toggle) => ( )} dropdownStyle={styles.menuDropdown} renderOption={(option, isSelected) => ( {option.value === 'terms' ? ( ) : ( )} {option.label} )} /> ( )} autoPlay autoPlayInterval={2000} loop onSnapToItem={(index) => setCurrentImageIndex(index)} /> {carouselImages.map((_, index) => ( ))} {/* 订阅计划标题 */} {t('membership.subscriptionPlan')} {/* 订阅计划卡片 */} {plans.map((plan, index) => { const isSelected = selectedPlan === plan.id return ( 0 && styles.planCardSpacing, ]} onPress={() => setSelectedPlan(plan.id)} > {isSelected ? ( {plan.recommended && ( {t('membership.mostRecommended')} )} {plan.name} $ {plan.price} {t('membership.perMonth')} ) : ( {plan.recommended && ( {t('membership.mostRecommended')} )} {plan.name} $ {plan.price} {t('membership.perMonth')} )} ) })} {/* 卡片所属的信息 */} {/* 积分每月显示 */} {currentPlan.points.toLocaleString()} {t('membership.pointsPerMonth')} {t('membership.pointsAutoRenew')} {/* 功能列表 */} {currentPlan.features.map((feature, index) => ( {feature} ))} {/* 固定在底部的订阅容器 */} {/* 立即开通按钮 */} {t('membership.subscribeNow')} {/* 协议复选框 */} setAgreed(!agreed)} > {agreed ? : } {t('membership.agreementText')}{' '} router.push('/terms')} > {t('membership.terms')} {t('membership.agreementAnd')} router.push('/privacy')} > {t('membership.privacy')} {/* 积分抽屉 */} setPointsDrawerVisible(false)} totalPoints={60} subscriptionPoints={0} topUpPoints={0} /> ) } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: '#090A0B', }, contentWrapper: { flex: 1, }, scrollView: { flex: 1, backgroundColor: '#090A0B', }, scrollContent: { backgroundColor: '#090A0B', flexGrow: 1, paddingTop: 56, // 为固定的导航栏留出空间 }, header: { position: 'absolute', top: 0, left: 0, right: 0, flexDirection: 'row', alignItems: 'center', paddingHorizontal: 12, paddingTop: 7, paddingBottom: 7, zIndex: 100, backgroundColor: 'transparent', }, imageContainer: { width: '100%', overflow: 'hidden', marginTop: -56, position: 'relative', }, membershipImage: { width: '100%', height: '100%', }, imageGradient: { position: 'absolute', bottom: -20, left: 0, right: 0, height: '30%', zIndex: 10, elevation: 10, }, dotsContainer: { position: 'absolute', bottom: 40, left: 16, flexDirection: 'row', justifyContent: 'center', alignItems: 'center', gap: 4, zIndex: 20, elevation: 20, }, dot: { width: 4, height: 4, borderRadius: 100, backgroundColor: '#FFFFFF80', }, dotActive: { width: 10, height: 4, borderRadius: 100, backgroundColor: '#FFFFFF', }, backButton: { width: 32, height: 32, alignItems: 'center', justifyContent: 'center', borderRadius: 100, }, headerSpacer: { flex: 1, }, pointsPill: { flexDirection: 'row', alignItems: 'center', paddingHorizontal: 12, paddingVertical: 8, borderRadius: 100, backgroundColor: '#2A2A2A80', }, pointsLabel: { color: '#F5F5F5', fontSize: 11, fontWeight: '500', }, pointsValue: { color: '#F5F5F5', fontSize: 12, fontWeight: '500', }, sectionTitle: { textAlign: 'center', color: '#F5F5F5', fontSize: 24, fontWeight: '900', lineHeight: 32, marginBottom: 16, marginTop: 9, fontStyle: 'italic', }, plansContainer: { flexDirection: 'row', paddingHorizontal: 16, marginBottom: 16, }, planCardWrapper: { flex: 1, }, planCardGradient: { flex: 1, borderRadius: 12, padding: 2, }, planCardWrapperUnselected: { flex: 1, borderRadius: 12, padding: 2, backgroundColor: 'transparent', }, planCard: { flex: 1, paddingTop: 12, paddingBottom: 16, paddingHorizontal: 12, borderRadius: 12, backgroundColor: '#16181B', position: 'relative', overflow: 'hidden', }, planCardSpacing: { marginLeft: 12, }, recommendedBadge: { position: 'absolute', top: -3, right: -2, paddingHorizontal: 11, paddingBottom: 1, borderRadius: 4, backgroundColor: '#6851EB', borderTopRightRadius: 12, borderBottomRightRadius: 0, }, recommendedText: { color: '#F5F5F5', fontSize: 10, fontWeight: '500', }, planName: { color: '#F5F5F5', fontSize: 12, fontWeight: '500', marginBottom: 14, }, priceContainer: { flexDirection: 'row', alignItems: 'baseline', }, priceSymbol: { color: '#F5F5F5', fontSize: 12, fontWeight: '500', marginRight: 2, }, priceValue: { color: '#F5F5F5', fontSize: 24, fontWeight: '500', marginRight: 4, }, priceUnit: { color: '#ABABAB', fontSize: 12, fontWeight: '500', }, pointsMonthlyContainer: { marginHorizontal: 16, backgroundColor: '#191B1F', paddingHorizontal: 12, paddingVertical: 12, borderRadius: 12, marginBottom: 16, }, pointsMonthlyCard: { paddingHorizontal: 16, paddingVertical: 10, borderRadius: 10, backgroundColor: '#272A30', marginBottom: 24, }, pointsMonthlyHeader: { flexDirection: 'row', alignItems: 'center', marginBottom: 10, }, pointsMonthlyLabelWrapper: { marginLeft: 8, }, pointsMonthlyValue: { color: '#F5F5F5', fontSize: 13, fontWeight: '500', }, pointsMonthlyLabel: { color: '#F5F5F5', fontSize: 13, fontWeight: '500', }, progressBar: { width: '100%', height: 3, backgroundColor: '#484F5B', borderRadius: 10, marginBottom: 10, overflow: 'hidden', }, progressFill: { height: '100%', borderRadius: 2, }, pointsMonthlyNote: { color: '#CCCCCC', fontSize: 11, fontWeight: '400', }, featureItem: { flexDirection: 'row', alignItems: 'center', gap: 16, marginBottom: 12, }, featureText: { flex: 1, color: '#CCCCCC', fontSize: 12, fontWeight: '400', }, agreementContainer: { flexDirection: 'row', alignItems: 'center', justifyContent: 'center', marginTop: 8, }, agreementTextWrapper: { marginLeft: 4, }, checkbox: { width: 12, height: 12, alignItems: 'center', justifyContent: 'center', }, agreementText: { color: '#CCCCCC', fontSize: 11, fontWeight: '400', }, agreementLink: { color: '#CCCCCC', }, subscribeContainer: { paddingTop: 8, alignItems: 'center', paddingHorizontal: 16, }, subscribeButtonPressable: { width: '100%', height: 48, borderRadius: 12, flexDirection: 'row', alignItems: 'center', justifyContent: 'center', }, subscribeButton: { width: '100%', paddingVertical: 14, borderRadius: 12, alignItems: 'center', justifyContent: 'center', }, subscribeButtonDisabled: { opacity: 0.5, }, subscribeButtonText: { color: '#F5F5F5', fontSize: 16, fontWeight: '500', }, subscribeButtonText1: { color: '#0D0D0E', fontSize: 16, fontWeight: '500', }, settingsButtonContainer: { position: 'relative', }, settingsButton: { width: 32, height: 32, alignItems: 'center', justifyContent: 'center', backgroundColor: '#2A2A2A80', borderRadius: 100, }, pointsContainer: { flexDirection: 'row', alignItems: 'center', gap: 12, }, menuDropdown: { width: 180, minWidth: 180, borderRadius: 12, backgroundColor: '#2A2A2A80', paddingVertical: 4, right: 12, }, menuOption: { flexDirection: 'row', alignItems: 'center', paddingHorizontal: 2, gap: 8, }, menuOptionText: { color: '#F5F5F5', fontSize: 12, fontWeight: '400', flex: 1, }, })