Files
bw-expo-app/components/auth/auth-guard.tsx
imeepos 668caaa91f 🔐 feat: 认证系统升级 - 从重定向到底部Modal的完整改造
## 核心功能

### 1. 全局认证架构
- 新增 AuthProvider:全局认证上下文,管理登录状态和Modal
- 新增 useAuthGuard Hook:提供 requireAuth 认证拦截功能
- 新增 AuthGuard 组件:包装需要认证的组件
- 新增 AuthPrompt 组件:多种样式的登录引导组件

### 2. 登录体验优化
- LoginModal 已优化为底部抽屉式设计
- 登录成功后自动关闭Modal并恢复用户操作
- 支持队列机制,多个认证检查依次执行

### 3. 页面架构调整
- 根布局集成 AuthProvider
- 移除 Tabs 布局的重定向逻辑
- Explore 页面添加认证保护,显示登录提示

### 4. API安全增强
- 新增 TokenManager:完整的Token生命周期管理
- 新增 SecureClient:安全API客户端,自动处理认证
- 更新 API 客户端:支持认证头和自动Token刷新

### 5. 文档完善
- AUTH_SYSTEM.md:完整的认证系统使用指南
- AUTH_UPGRADE_SUMMARY.md:升级总结文档

## 技术亮点

 TypeScript 完整支持,编译时类型检查
 React 最佳实践,合理使用 Hooks 和 Context
 优雅的错误处理,友好的用户提示
 流畅的动画效果,原生级用户体验

## 核心优势

- 流畅:无需页面跳转,Modal即用即走
- 智能:自动检测登录需求,无需手动判断
- 安全:完整Token管理和自动刷新机制
- 灵活:多种认证组件满足不同场景
- 易用:详细文档和示例,快速上手

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-31 11:18:20 +08:00

112 lines
2.4 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import React from 'react';
import { View, StyleSheet } from 'react-native';
import { useAuth } from '@/hooks/use-auth';
import { useAuthGuard } from '@/hooks/use-auth-guard';
import { ThemedText } from '@/components/themed-text';
interface AuthGuardProps {
children: React.ReactNode;
fallback?: React.ReactNode;
showLoginPrompt?: boolean;
title?: string;
subtitle?: string;
}
/**
* 认证守卫组件
* 用于包装需要登录才能访问的内容
*
* @param children - 需要保护的内容
* @param fallback - 未登录时显示的自定义内容(可选)
* @param showLoginPrompt - 是否显示默认的登录提示默认true
* @param title - 自定义提示标题
* @param subtitle - 自定义提示副标题
*
* @example
* ```typescript
* <AuthGuard>
* <ProtectedComponent />
* </AuthGuard>
*
* // 自定义提示
* <AuthGuard
* title="需要登录"
* subtitle="登录后即可使用此功能"
* >
* <ProtectedComponent />
* </AuthGuard>
* ```
*/
export function AuthGuard({
children,
fallback,
showLoginPrompt = true,
title = '需要登录',
subtitle = '请先登录以继续使用',
}: AuthGuardProps) {
const { isAuthenticated, isLoading } = useAuth();
const { requireAuth } = useAuthGuard();
if (isLoading) {
return <View style={styles.loadingContainer} />;
}
if (!isAuthenticated) {
if (fallback) {
return <>{fallback}</>;
}
if (showLoginPrompt) {
return (
<View style={styles.promptContainer}>
<View style={styles.iconContainer}>
<ThemedText style={styles.lockIcon}>🔒</ThemedText>
</View>
<ThemedText style={styles.title}>{title}</ThemedText>
<ThemedText style={styles.subtitle}>{subtitle}</ThemedText>
</View>
);
}
return null;
}
return <>{children}</>;
}
const styles = StyleSheet.create({
loadingContainer: {
flex: 1,
},
promptContainer: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
padding: 32,
},
iconContainer: {
width: 80,
height: 80,
borderRadius: 40,
backgroundColor: 'rgba(0, 122, 255, 0.1)',
alignItems: 'center',
justifyContent: 'center',
marginBottom: 24,
},
lockIcon: {
fontSize: 40,
},
title: {
fontSize: 24,
fontWeight: '700',
marginBottom: 12,
textAlign: 'center',
},
subtitle: {
fontSize: 16,
opacity: 0.7,
textAlign: 'center',
lineHeight: 24,
},
});