import { Ionicons } from '@expo/vector-icons'; import type { ReactNode } from 'react'; import { ActivityIndicator, Pressable, StyleSheet, Text, View } from 'react-native'; import { colors } from '../theme'; /* ===================== 通用状态视图 ===================== * 统一承载「加载中 / 加载失败 / 空数据」三态,供数据页复用, * 避免各页面重复编写 ActivityIndicator + 重试按钮样板代码。 * 颜色全部走主题 token,遵守 AGENTS.md 配色约束。 */ function StateBox({ children }: { children: ReactNode }) { return {children}; } /** 加载中 */ export function LoadingState({ text = '加载中…' }: { text?: string }) { return ( {text} ); } /** 加载失败(可重试) */ export function ErrorState({ message = '加载失败,请重试', onRetry, }: { message?: string; onRetry?: () => void; }) { return ( {message} {onRetry ? ( 重试 ) : null} ); } /** 空数据 / 占位 */ export function EmptyState({ icon = 'document-text-outline', title, subtitle, actionLabel, onAction, }: { icon?: keyof typeof Ionicons.glyphMap; title: string; subtitle?: string; actionLabel?: string; onAction?: () => void; }) { return ( {title} {subtitle ? {subtitle} : null} {actionLabel && onAction ? ( {actionLabel} ) : null} ); } const styles = StyleSheet.create({ box: { flex: 1, alignItems: 'center', justifyContent: 'center', gap: 12, paddingHorizontal: 32, }, text: { marginTop: 4, fontSize: 14, color: colors.textSecondary, textAlign: 'center', }, title: { marginTop: 12, fontSize: 20, fontWeight: '700', color: colors.textPrimary, }, retryBtn: { marginTop: 16, paddingHorizontal: 24, paddingVertical: 8, borderRadius: 18, backgroundColor: colors.primaryBtn, }, retryText: { fontSize: 13, fontWeight: '600', color: colors.white, }, });