import React, { useEffect, useRef, useState } from 'react'; import { View, Text, StyleSheet, TouchableOpacity, Dimensions, Platform, Alert, Image } from 'react-native'; import { useRouter } from 'expo-router'; import * as WebBrowser from 'expo-web-browser'; import { Trans, useTranslation } from 'react-i18next'; import { SafeAreaView } from 'react-native-safe-area-context'; import { setConsentAccepted, getConsentAccepted } from '../../src/storage/appStorage'; import { fetchLegalLinks } from '@/src/services/legalApi'; import { getOnboardingCompleted } from '@/src/storage/appStorage'; import { API_BASE_URL } from '@/src/constants/env'; // 导入 SVG 组件 import FlowersBg from '../../assets/images/index/flowers_endbg.svg'; import WelcomeBtn from '../../assets/images/index/welcome_btn.svg'; const { width, height } = Dimensions.get('window'); export default function SplashScreen() { const router = useRouter(); const { t } = useTranslation(); const [showConsent, setShowConsent] = useState(false); const [links, setLinks] = useState<{ privacy?: string; terms?: string }>({}); const [linksLoading, setLinksLoading] = useState(false); const mountedRef = useRef(true); useEffect(() => { checkConsent(); }, []); useEffect(() => { return () => { mountedRef.current = false; }; }, []); const checkConsent = async () => { const accepted = await getConsentAccepted(); setShowConsent(!accepted); if (accepted) { // 已同意协议则直接分发到目标页,避免先回到 /(index)再二次跳转导致“闪一下” const completed = await getOnboardingCompleted(); if (completed) { router.replace('/(app)/home'); } else { router.replace('/(onboarding)/onboarding'); } } }; const handleAgree = async () => { await setConsentAccepted(true); setShowConsent(false); // 跳转到 onboarding 流程 router.replace('/(onboarding)/onboarding'); }; const openLink = async (url: string) => { try { await WebBrowser.openBrowserAsync(url); } catch (error) { Alert.alert(t('common.error'), t('common.openLinkError')); } }; async function refreshLegalLinks(): Promise<{ privacy?: string; terms?: string }> { if (mountedRef.current) setLinksLoading(true); try { const res = await fetchLegalLinks(); const next = { privacy: res.privacyPolicyUrl, terms: res.termsOfUseUrl }; if (mountedRef.current) setLinks(next); return next; } catch (e) { // 不阻塞主流程:失败时不崩溃,链接入口仍可点(会提示) if (__DEV__) console.log('[LegalLinks] 拉取失败(splash):', e); if (mountedRef.current) setLinks({}); return {}; } finally { if (mountedRef.current) setLinksLoading(false); } } async function handleOpenLegal(type: 'privacy' | 'terms') { const currentUrl = type === 'privacy' ? links.privacy : links.terms; if (currentUrl) { await openLink(currentUrl); return; } // 链接还没拿到/拉取失败:点击时主动再拉一次,避免“点了没反应” const next = await refreshLegalLinks(); const nextUrl = type === 'privacy' ? next.privacy : next.terms; if (nextUrl) { await openLink(nextUrl); return; } const msg = typeof __DEV__ !== 'undefined' && __DEV__ ? t('consent.linkUnavailableDev', { baseUrl: API_BASE_URL }) : t('consent.linkUnavailable'); Alert.alert(t('common.notice'), msg); } // 拉取协议链接(由后端按语言下发;默认 EN) useEffect(() => { void refreshLegalLinks(); }, []); const bgDecorationTop = 363; const bgDecorationHeight = height * 0.6; const contentTop = bgDecorationTop + (bgDecorationHeight * 0.25); return ( {/* 中间的背景装饰 SVG (现在放在上面,作为上层) */} {/* 顶部的花图片 (现在放在下面,作为下层) */} {/* 文案内容 */} {t('consent.title')} {'\n'} {t('consent.subtitle')} {showConsent && ( <> void handleOpenLegal('privacy')} suppressHighlighting /> ), terms: ( void handleOpenLegal('terms')} suppressHighlighting /> ), }} /> )} ); } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: '#F5D3B5', // 匹配 Figma 背景色 alignItems: 'center', }, topImageContainer: { marginTop: 60, zIndex: 1, // 降低层级 }, topImage: { width: 308, height: 354, }, bgDecorationContainer: { position: 'absolute', left: -3, zIndex: 2, // 提高层级,使其覆盖在图片之上 }, contentContainer: { alignItems: 'center', zIndex: 3, }, titleText: { fontSize: 30, lineHeight: 42, color: '#772F00', // 匹配 Figma 文字颜色 textAlign: 'center', fontWeight: '600', fontFamily: Platform.OS === 'ios' ? 'STIX Two Text' : 'serif', }, bottomContainer: { position: 'absolute', bottom: 60, width: '100%', alignItems: 'center', zIndex: 4, }, buttonWrapper: { marginBottom: 40, }, noticeText: { marginTop: 10, paddingHorizontal: 28, fontSize: 12, lineHeight: 16, textAlign: 'center', color: 'rgba(119, 47, 0, 0.45)', }, noticeLinkText: { fontSize: 12, // 颜色区分:协议链接更醒目 color: 'rgba(119, 47, 0, 0.75)', textDecorationLine: 'underline', fontWeight: '600', }, noticeLinkTextDisabled: { opacity: 0.55, }, });