import React, { useCallback, useEffect, useMemo, useState } from 'react'; import { ActivityIndicator, Alert, ScrollView, StyleSheet, TextInput, TouchableOpacity, View, } from 'react-native'; import { SafeAreaView, useSafeAreaInsets } from 'react-native-safe-area-context'; import { MaterialCommunityIcons } from '@expo/vector-icons'; import { useRouter } from 'expo-router'; import { authService } from '../../services'; import { spacing, borderRadius, fontSizes, useAppColors, type AppColors } from '../../theme'; import { Text } from '../../components/common'; import { useResponsive, useResponsiveSpacing } from '../../hooks'; import { useAuthStore } from '../../stores'; import type { DeletionStatusDTO } from '../../types/dto'; import * as hrefs from '../../navigation/hrefs'; const CONTENT_MAX_WIDTH = 720; function createAccountDeletionStyles(colors: AppColors) { return StyleSheet.create({ container: { flex: 1, backgroundColor: colors.background.paper, }, loadingWrap: { flex: 1, alignItems: 'center', justifyContent: 'center', }, scrollContent: { paddingVertical: spacing.lg, }, content: { maxWidth: CONTENT_MAX_WIDTH, alignSelf: 'center', width: '100%', }, section: { marginBottom: spacing['2xl'], }, // 警告卡片 - 扁平化风格 warningCard: { backgroundColor: colors.error.light + '20', borderRadius: 14, padding: spacing.lg, marginHorizontal: spacing['2xl'], marginBottom: spacing.xl, }, warningTitle: { fontWeight: '700', fontSize: fontSizes.md, marginBottom: spacing.sm, color: colors.error.main, }, warningText: { color: colors.error.dark, marginBottom: spacing.xs, fontSize: fontSizes.sm, }, // 状态卡片 - 扁平化风格 statusCard: { backgroundColor: colors.warning.light + '30', borderRadius: 14, padding: spacing.lg, marginHorizontal: spacing['2xl'], marginBottom: spacing.xl, }, statusTitle: { fontWeight: '700', fontSize: fontSizes.md, marginBottom: spacing.sm, color: colors.warning.dark, }, daysText: { fontSize: 32, fontWeight: '700', color: colors.warning.dark, textAlign: 'center', marginVertical: spacing.md, }, // 内容区域 sectionContent: { marginHorizontal: spacing['2xl'], marginBottom: spacing.xl, }, sectionTitle: { fontWeight: '600', fontSize: fontSizes.sm, color: colors.text.secondary, textTransform: 'uppercase', letterSpacing: 0.5, marginBottom: spacing.md, }, listItem: { flexDirection: 'row', alignItems: 'flex-start', marginBottom: spacing.sm, }, listBullet: { marginRight: spacing.sm, marginTop: 2, }, // 输入框 - 扁平化风格 input: { backgroundColor: colors.background.default, borderRadius: 14, padding: spacing.md, fontSize: 16, color: colors.text.primary, height: 56, }, // 按钮行 buttonRow: { flexDirection: 'row', gap: spacing.md, marginTop: spacing.lg, marginHorizontal: spacing['2xl'], }, // 扁平化按钮 primaryButton: { flex: 1, height: 56, borderRadius: 14, backgroundColor: colors.primary.main, alignItems: 'center', justifyContent: 'center', }, primaryButtonText: { color: colors.text.inverse, fontSize: fontSizes.md, fontWeight: '600', }, secondaryButton: { flex: 1, height: 56, borderRadius: 14, backgroundColor: 'transparent', alignItems: 'center', justifyContent: 'center', borderWidth: 1.5, borderColor: colors.divider, }, secondaryButtonText: { color: colors.text.primary, fontSize: fontSizes.md, fontWeight: '600', }, dangerButton: { flex: 1, height: 56, borderRadius: 14, backgroundColor: colors.error.main, alignItems: 'center', justifyContent: 'center', }, dangerButtonText: { color: colors.text.inverse, fontSize: fontSizes.md, fontWeight: '600', }, buttonDisabled: { opacity: 0.6, }, cancelButton: { marginTop: spacing.lg, marginHorizontal: spacing['2xl'], }, }); } export const AccountDeletionScreen: React.FC = () => { const colors = useAppColors(); const styles = useMemo(() => createAccountDeletionStyles(colors), [colors]); const router = useRouter(); const { isMobile } = useResponsive(); const insets = useSafeAreaInsets(); const { logout } = useAuthStore(); const [status, setStatus] = useState(null); const [loading, setLoading] = useState(true); const [submitting, setSubmitting] = useState(false); const [password, setPassword] = useState(''); const scrollBottomInset = isMobile ? 64 + 24 + insets.bottom + spacing.md : spacing.md; const responsivePadding = useResponsiveSpacing({ xs: 8, sm: 12, md: 16, lg: 24, xl: 32 }); const loadStatus = useCallback(async () => { try { const result = await authService.getDeletionStatus(); setStatus(result); } catch (error) { console.error('加载注销状态失败:', error); } finally { setLoading(false); } }, []); useEffect(() => { loadStatus(); }, [loadStatus]); const handleRequestDeletion = useCallback(async () => { if (!password.trim()) { Alert.alert('提示', '请输入密码确认'); return; } Alert.alert( '确认注销', '注销后,您的账号将在90天后永久删除。在此期间,您可以通过重新登录来取消注销。确定要继续吗?', [ { text: '取消', style: 'cancel' }, { text: '确定注销', style: 'destructive', onPress: async () => { setSubmitting(true); try { const result = await authService.requestAccountDeletion(password); if (result) { setStatus(result); setPassword(''); Alert.alert('已申请注销', '您的账号将在90天后永久删除。在此期间登录即可取消注销。'); await logout(); router.replace(hrefs.hrefAuthLogin()); } else { Alert.alert('失败', '密码错误或申请失败,请重试'); } } catch (error) { console.error('申请注销失败:', error); Alert.alert('失败', '申请注销失败,请稍后重试'); } finally { setSubmitting(false); } }, }, ] ); }, [password, logout, router]); const handleCancelDeletion = useCallback(async () => { Alert.alert( '取消注销', '确定要取消注销申请吗?您的账号将恢复正常使用。', [ { text: '继续注销', style: 'cancel' }, { text: '确定取消', onPress: async () => { setSubmitting(true); try { const ok = await authService.cancelAccountDeletion(); if (ok) { setStatus({ is_pending_deletion: false }); Alert.alert('已取消', '注销申请已取消,您的账号已恢复正常使用'); } else { Alert.alert('失败', '取消注销失败,请稍后重试'); } } catch (error) { console.error('取消注销失败:', error); Alert.alert('失败', '取消注销失败,请稍后重试'); } finally { setSubmitting(false); } }, }, ] ); }, []); if (loading) { return ( ); } return ( {status?.is_pending_deletion ? ( 账号注销申请中 您的账号将在以下天数后永久删除: {status.cool_down_days || 90} 天 在此期间,您可以通过重新登录或点击下方按钮来取消注销申请。 {submitting ? ( ) : ( 取消注销申请 )} ) : ( {/* 警告卡片 */} 警告:账号注销后将无法恢复 注销后,您的账号将在90天后永久删除。 在此期间,您可以通过重新登录来取消注销。 {/* 注销说明 */} 注销后将发生什么 您的个人资料将被删除 您发布的帖子、评论将保留,但显示为「已注销用户」 您的关注、粉丝关系将被清除 您的收藏、点赞记录将被删除 {/* 密码确认 */} 请输入密码确认 {/* 按钮行 */} router.back()} > 返回 {submitting ? ( ) : ( 确认注销 )} )} ); }; export default AccountDeletionScreen;