/** * 完整示例页面 * 展示所有工具的使用方法 */ import React, { useState, useEffect } from 'react'; import { StyleSheet, View, Text, TextInput, TouchableOpacity, ScrollView, Switch, Alert, ActivityIndicator, } from 'react-native'; import { useForm, Controller } from 'react-hook-form'; import { zodResolver } from '@hookform/resolvers/zod'; import { Image } from 'expo-image'; import { useRouter } from 'expo-router'; // ✅ 扁平化导入:从根目录的各个模块导入 // 工具函数 import { Storage, STORAGE_KEYS, SessionStorage, SESSION_KEYS, formatDate, formatRelativeTime, formatChatTime } from '@/utils'; // 状态管理 import { useUserStore, useUser, useIsLoggedIn, useSettingsStore, useTheme, useLanguage, useHapticsEnabled, useSettingsActions, useTenantStates, useTenantInfo, } from '@/stores'; // 验证规则 import { loginSchema } from '@/schemas'; import type { LoginFormData } from '@/schemas'; // API 服务 import { authService } from '@/services'; // 自定义 Hooks import { useDebounce, useThrottle, useHaptics } from '@/hooks'; // 主题组件 import { ThemeDemo } from '@/components/ThemeDemo'; export default function DemoScreen() { console.log('=== DemoScreen 组件已渲染 ==='); const haptics = useHaptics(); const router = useRouter(); // 状态管理示例 const user = useUser(); const isLoggedIn = useIsLoggedIn(); const login = useUserStore((state) => state.login); const logout = useUserStore((state) => state.logout); const { tenantLoad } = useTenantStates(); const tenantInfo = useTenantInfo(); // 设置状态 const theme = useTheme(); const language = useLanguage(); const hapticsEnabled = useHapticsEnabled(); const { setTheme, setLanguage, setHapticsEnabled } = useSettingsActions(); // const setTheme = useSettingsStore((state) => state.setTheme); // const setLanguage = useSettingsStore((state) => state.setLanguage); // const setHapticsEnabled = useSettingsStore((state) => state.setHapticsEnabled); // 本地状态 const [searchText, setSearchText] = useState(''); const [searchResults, setSearchResults] = useState([]); const [loading, setLoading] = useState(false); const [counter, setCounter] = useState(0); const [storageValue, setStorageValue] = useState(''); const [sessionValue, setSessionValue] = useState(''); // 表单配置 const { control, handleSubmit, formState: { errors }, } = useForm({ resolver: zodResolver(loginSchema), defaultValues: { email: '', password: '', }, }); // 防抖搜索示例 const debouncedSearch = useDebounce(async (text: string) => { console.log('防抖搜索:', text); if (!text.trim()) { setSearchResults([]); return; } console.log('执行搜索:', text); // 模拟 API 调用 await new Promise((resolve) => setTimeout(resolve, 500)); setSearchResults([`结果 1: ${text}`, `结果 2: ${text}`, `结果 3: ${text}`]); }, 500); // 监听搜索文本变化 useEffect(() => { debouncedSearch(searchText); }, [searchText]); // 节流点击示例 const throttledClick = useThrottle(() => { haptics.light(); setCounter((prev) => prev + 1); console.log('节流点击:', counter + 1); }, 1000); // 登录处理 const onLogin = async (data: LoginFormData) => { try { setLoading(true); haptics.light(); // 模拟登录 API 调用 console.log('登录数据:', data); // 实际项目中使用: // const { user, token } = await authService.login(data); // login(user, token); // 模拟登录成功 const mockUser = { id: '1', username: data.email.split('@')[0], email: data.email, avatar: 'https://i.pravatar.cc/150?img=1', nickname: '演示用户', createdAt: new Date().toISOString(), }; login(mockUser, 'mock-token-123456'); haptics.success(); Alert.alert('成功', '登录成功!'); } catch (error: any) { haptics.error(); Alert.alert('失败', error.message || '登录失败'); } finally { setLoading(false); } }; // 登出处理 const handleLogout = () => { haptics.warning(); Alert.alert('确认', '确定要退出登录吗?', [ { text: '取消', style: 'cancel' }, { text: '确定', onPress: () => { logout(); haptics.success(); }, }, ]); }; // 存储示例 const handleSaveToStorage = async () => { try { haptics.light(); const testData = { message: 'Hello from AsyncStorage!', timestamp: new Date().toISOString(), counter, }; await Storage.setObject(STORAGE_KEYS.USER_PREFERENCES, testData); haptics.success(); Alert.alert('成功', '数据已保存到本地存储'); } catch (error) { haptics.error(); Alert.alert('失败', '保存失败'); } }; const handleLoadFromStorage = async () => { try { haptics.light(); const data = await Storage.getObject(STORAGE_KEYS.USER_PREFERENCES); if (data) { setStorageValue(JSON.stringify(data, null, 2)); haptics.success(); } else { setStorageValue('暂无数据'); haptics.warning(); } } catch (error) { haptics.error(); Alert.alert('失败', '读取失败'); } }; // SessionStorage 处理函数 const handleSaveToSession = () => { try { haptics.light(); const testData = { formDraft: { title: '草稿标题', content: '这是一个表单草稿示例', }, timestamp: new Date().toISOString(), counter: Math.floor(Math.random() * 100), }; SessionStorage.setObject(SESSION_KEYS.FORM_DRAFT, testData); haptics.success(); Alert.alert('成功', '数据已保存到会话存储(应用重启后会丢失)'); } catch (error) { haptics.error(); Alert.alert('失败', '保存失败'); } }; const handleLoadFromSession = () => { try { haptics.light(); const data = SessionStorage.getObject(SESSION_KEYS.FORM_DRAFT); if (data) { setSessionValue(JSON.stringify(data, null, 2)); haptics.success(); } else { setSessionValue('暂无数据(会话存储为空)'); haptics.warning(); } } catch (error) { haptics.error(); Alert.alert('失败', '读取失败'); } }; const handleClearSession = () => { try { haptics.light(); SessionStorage.clear(); setSessionValue(''); haptics.success(); Alert.alert('成功', '会话存储已清空'); } catch (error) { haptics.error(); Alert.alert('失败', '清空失败'); } }; // 主题切换 const handleThemeChange = () => { haptics.selection(); const themes: Array<'light' | 'dark' | 'auto'> = ['light', 'dark', 'auto']; const currentIndex = themes.indexOf(theme); const nextTheme = themes[(currentIndex + 1) % themes.length]; setTheme(nextTheme); }; // 语言切换 const handleLanguageChange = () => { haptics.selection(); setLanguage(language === 'zh-CN' ? 'en-US' : 'zh-CN'); }; return ( {/* 标题 */} 🎯 完整功能演示 展示所有工具的使用方法 {/* 页面导航 */} 📱 页面导航 { haptics.light(); router.push('/test'); }} > 跳转到测试页面 → 测试页面是一个独立的业务页面示例,不包含底部 tabs { haptics.light(); router.push('/theme-test'); }} > 🎨 主题测试页面 → 专门的主题测试页面,可以清楚地看到主题切换效果 { haptics.light(); router.push('/theme-example'); }} > 📚 主题系统示例 → 展示四种主题样式使用方式(类似 CSS 类名) {/* 租户信息显示 */} 🏢 租户信息 状态: {tenantLoad ? '✅ 已加载' : '❌ 未加载'} {tenantInfo ? ( <> TID: {tenantInfo.tid || '无'} 创建时间: {tenantInfo.create_time || '无'} 域名: {tenantInfo.domain_addr || '无'} ) : null} {/* 用户状态显示 */} 👤 用户状态 (Zustand) {isLoggedIn ? ( {user?.avatar ? ( ) : null} {user?.nickname} {user?.email} 注册时间: {formatRelativeTime(user?.createdAt || '')} 退出 ) : ( 未登录 )} {/* 登录表单 */} {!isLoggedIn ? ( 🔐 登录表单 (React Hook Form + Zod) ( 邮箱 {errors.email && {errors.email.message}} )} /> ( 密码 {errors.password ? ( {errors.password.message} ) : null} )} /> {loading ? ( ) : ( 登录 )} ) : null} {/* 搜索示例 */} 🔍 防抖搜索 (useDebounce) {searchResults.length > 0 ? ( {searchResults.map((result, index) => ( {result} ))} ) : null} {/* 节流点击示例 */} ⏱️ 节流点击 (useThrottle) 点击次数: {counter} 快速点击测试(1秒节流) {/* 本地存储示例 */} 💾 本地存储 (AsyncStorage) 保存数据 读取数据 {storageValue ? ( {storageValue} ) : null} {/* 会话存储示例 */} 🔄 会话存储 (SessionStorage) 会话存储数据保存在内存中,应用重启后会丢失,适合临时数据 保存 读取 清空 {sessionValue ? ( {sessionValue} ) : null} {/* 日期格式化示例 */} 📅 日期格式化 (Day.js) 当前时间: {formatDate(new Date(), 'YYYY-MM-DD HH:mm:ss')} 相对时间: {formatRelativeTime(new Date())} 聊天时间: {formatChatTime(Date.now())} {/* 主题演示 */} 🎨 主题系统演示 {/* 设置示例 */} ⚙️ 应用设置 主题: {theme} 切换 语言: {language} 切换 触觉反馈 { haptics.selection(); setHapticsEnabled(value); }} /> {/* 触觉反馈示例 */} 📳 触觉反馈 (Expo Haptics) haptics.light()} > Light haptics.medium()} > Medium haptics.heavy()} > Heavy haptics.success()} > Success haptics.warning()} > Warning haptics.error()} > Error 查看代码了解更多使用方法 📖 ); } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: '#f5f5f5', }, content: { padding: 16, }, title: { fontSize: 28, fontWeight: 'bold', marginBottom: 8, color: '#333', }, subtitle: { fontSize: 16, color: '#666', marginBottom: 24, }, section: { backgroundColor: '#fff', borderRadius: 12, padding: 16, marginBottom: 16, shadowColor: '#000', shadowOffset: { width: 0, height: 2 }, shadowOpacity: 0.1, shadowRadius: 4, elevation: 3, }, sectionTitle: { fontSize: 18, fontWeight: '600', marginBottom: 12, color: '#333', }, userInfo: { flexDirection: 'row', alignItems: 'center', }, avatar: { width: 60, height: 60, borderRadius: 30, marginRight: 12, }, userDetails: { flex: 1, }, userName: { fontSize: 16, fontWeight: '600', color: '#333', }, userEmail: { fontSize: 14, color: '#666', marginTop: 2, }, userDate: { fontSize: 12, color: '#999', marginTop: 4, }, inputGroup: { marginBottom: 16, }, label: { fontSize: 14, fontWeight: '500', marginBottom: 6, color: '#333', }, input: { borderWidth: 1, borderColor: '#ddd', borderRadius: 8, padding: 12, fontSize: 16, backgroundColor: '#fff', }, inputError: { borderColor: '#ff3b30', }, errorText: { color: '#ff3b30', fontSize: 12, marginTop: 4, }, button: { paddingVertical: 12, paddingHorizontal: 20, borderRadius: 8, alignItems: 'center', justifyContent: 'center', }, buttonText: { color: '#fff', fontSize: 16, fontWeight: '600', }, loginButton: { backgroundColor: '#007AFF', marginTop: 8, }, logoutButton: { backgroundColor: '#ff3b30', paddingVertical: 8, paddingHorizontal: 16, }, primaryButton: { backgroundColor: '#007AFF', }, secondaryButton: { backgroundColor: '#5856D6', }, smallButton: { backgroundColor: '#007AFF', paddingVertical: 8, paddingHorizontal: 16, }, buttonRow: { flexDirection: 'row', justifyContent: 'space-between', }, halfButton: { flex: 1, }, thirdButton: { flex: 1, marginHorizontal: 4, }, searchResults: { marginTop: 12, }, searchResult: { padding: 12, backgroundColor: '#f9f9f9', borderRadius: 8, marginBottom: 8, color: '#333', }, infoText: { fontSize: 14, color: '#666', marginBottom: 8, }, codeBlock: { backgroundColor: '#f9f9f9', borderRadius: 8, padding: 12, marginTop: 12, }, codeText: { fontFamily: 'monospace', fontSize: 12, color: '#333', }, settingRow: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', marginBottom: 12, }, settingLabel: { fontSize: 16, color: '#333', }, buttonGrid: { flexDirection: 'row', flexWrap: 'wrap', marginHorizontal: -4, }, hapticsButton: { backgroundColor: '#5856D6', flex: 1, minWidth: '30%', margin: 4, }, successButton: { backgroundColor: '#34C759', flex: 1, margin: 4, minWidth: '30%', }, warningButton: { backgroundColor: '#FF9500', flex: 1, minWidth: '30%', margin: 4, }, errorButton: { backgroundColor: '#FF3B30', flex: 1, minWidth: '30%', margin: 4, }, footer: { marginTop: 24, marginBottom: 40, alignItems: 'center', }, footerText: { fontSize: 14, color: '#999', }, });