✨ feat: 美化登录界面并集成登录模态框
- 重设计未登录状态UI,添加动画效果和渐变按钮 - 集成LoginModal组件,提供完整的登录体验 - 新增游客浏览功能,提升用户体验 - 切换至测试环境API (api-test.mixvideo.bowong.cc) - 添加@expo/vector-icons图标库依赖 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -5,8 +5,10 @@ import { useAuth } from '@/hooks/use-auth';
|
||||
import { getTemplates } from '@/lib/api/templates';
|
||||
import { Template } from '@/lib/types/template';
|
||||
import { LinearGradient } from 'expo-linear-gradient';
|
||||
import { Ionicons } from '@expo/vector-icons';
|
||||
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||
import { Alert, Animated, StyleSheet, Text } from 'react-native';
|
||||
import { Alert, Animated, StyleSheet, Text, TouchableOpacity, View } from 'react-native';
|
||||
import { LoginModal } from '@/components/auth/login-modal';
|
||||
|
||||
export default function HomeScreen() {
|
||||
const { isAuthenticated } = useAuth();
|
||||
@@ -17,6 +19,7 @@ export default function HomeScreen() {
|
||||
const [currentPage, setCurrentPage] = useState(1);
|
||||
const [hasMore, setHasMore] = useState(true);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const [showLoginModal, setShowLoginModal] = useState(false);
|
||||
const pulseAnim = useRef(new Animated.Value(0)).current;
|
||||
const bounceAnim = useRef(new Animated.Value(0)).current;
|
||||
|
||||
@@ -40,16 +43,13 @@ export default function HomeScreen() {
|
||||
});
|
||||
|
||||
if (isRefreshing || page === 1) {
|
||||
// 刷新或首次加载,替换数据
|
||||
setTemplates(response.data);
|
||||
setCurrentPage(1);
|
||||
} else {
|
||||
// 加载更多,追加数据
|
||||
setTemplates(prev => [...prev, ...response.data]);
|
||||
setCurrentPage(page);
|
||||
}
|
||||
|
||||
// 检查是否还有更多数据
|
||||
setHasMore(response.pagination.page < response.pagination.totalPages);
|
||||
} catch (err: any) {
|
||||
console.error('获取模板列表失败:', err);
|
||||
@@ -70,6 +70,7 @@ export default function HomeScreen() {
|
||||
useEffect(() => {
|
||||
if (isAuthenticated) {
|
||||
fetchTemplates();
|
||||
setShowLoginModal(false);
|
||||
}
|
||||
|
||||
Animated.loop(
|
||||
@@ -126,12 +127,55 @@ export default function HomeScreen() {
|
||||
};
|
||||
|
||||
if (!isAuthenticated) {
|
||||
const scaleAnim = pulseAnim.interpolate({
|
||||
inputRange: [0, 1],
|
||||
outputRange: [0.95, 1.05],
|
||||
});
|
||||
|
||||
return (
|
||||
<ThemedView style={styles.container}>
|
||||
<ThemedView style={styles.centerContent}>
|
||||
<ThemedText type="title" style={styles.title}>欢迎使用</ThemedText>
|
||||
<ThemedText style={styles.subtitle}>请先登录以查看模板列表</ThemedText>
|
||||
</ThemedView>
|
||||
<View style={styles.welcomeContainer}>
|
||||
<Animated.View
|
||||
style={[
|
||||
styles.iconContainer,
|
||||
{ transform: [{ scale: scaleAnim }] },
|
||||
]}
|
||||
>
|
||||
<Ionicons name="albums-outline" size={80} color="#007AFF" />
|
||||
</Animated.View>
|
||||
|
||||
<ThemedText type="title" style={styles.welcomeTitle}>
|
||||
欢迎使用模板中心
|
||||
</ThemedText>
|
||||
<ThemedText style={styles.welcomeSubtitle}>
|
||||
登录后即可浏览和使用海量精美模板
|
||||
</ThemedText>
|
||||
|
||||
<TouchableOpacity
|
||||
style={styles.loginButton}
|
||||
onPress={() => setShowLoginModal(true)}
|
||||
activeOpacity={0.8}
|
||||
>
|
||||
<LinearGradient
|
||||
colors={['#007AFF', '#0056D2']}
|
||||
start={{ x: 0, y: 0 }}
|
||||
end={{ x: 1, y: 1 }}
|
||||
style={styles.loginButtonGradient}
|
||||
>
|
||||
<Ionicons name="log-in-outline" size={20} color="#fff" style={styles.loginButtonIcon} />
|
||||
<Text style={styles.loginButtonText}>立即登录</Text>
|
||||
</LinearGradient>
|
||||
</TouchableOpacity>
|
||||
|
||||
<TouchableOpacity style={styles.guestButton} activeOpacity={0.6}>
|
||||
<Text style={styles.guestButtonText}>游客浏览</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
|
||||
<LoginModal
|
||||
visible={showLoginModal}
|
||||
onClose={() => setShowLoginModal(false)}
|
||||
/>
|
||||
</ThemedView>
|
||||
);
|
||||
}
|
||||
@@ -176,6 +220,11 @@ export default function HomeScreen() {
|
||||
onVideoChange={handleVideoChange}
|
||||
error={error}
|
||||
/>
|
||||
|
||||
<LoginModal
|
||||
visible={showLoginModal}
|
||||
onClose={() => setShowLoginModal(false)}
|
||||
/>
|
||||
</ThemedView>
|
||||
);
|
||||
}
|
||||
@@ -184,6 +233,74 @@ const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
},
|
||||
welcomeContainer: {
|
||||
flex: 1,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
paddingHorizontal: 40,
|
||||
},
|
||||
iconContainer: {
|
||||
width: 120,
|
||||
height: 120,
|
||||
borderRadius: 60,
|
||||
backgroundColor: 'rgba(0, 122, 255, 0.1)',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
marginBottom: 24,
|
||||
},
|
||||
welcomeTitle: {
|
||||
fontSize: 28,
|
||||
fontWeight: '700',
|
||||
marginBottom: 12,
|
||||
textAlign: 'center',
|
||||
},
|
||||
welcomeSubtitle: {
|
||||
fontSize: 16,
|
||||
textAlign: 'center',
|
||||
opacity: 0.7,
|
||||
marginBottom: 48,
|
||||
lineHeight: 24,
|
||||
},
|
||||
loginButton: {
|
||||
width: '100%',
|
||||
height: 56,
|
||||
borderRadius: 16,
|
||||
overflow: 'hidden',
|
||||
elevation: 8,
|
||||
shadowColor: '#007AFF',
|
||||
shadowOffset: { width: 0, height: 4 },
|
||||
shadowRadius: 12,
|
||||
shadowOpacity: 0.3,
|
||||
},
|
||||
loginButtonGradient: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
height: '100%',
|
||||
},
|
||||
loginButtonIcon: {
|
||||
marginRight: 8,
|
||||
},
|
||||
loginButtonText: {
|
||||
color: '#fff',
|
||||
fontSize: 17,
|
||||
fontWeight: '700',
|
||||
},
|
||||
guestButton: {
|
||||
width: '100%',
|
||||
height: 56,
|
||||
borderRadius: 16,
|
||||
borderWidth: 1.5,
|
||||
borderColor: 'rgba(0, 122, 255, 0.3)',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
marginTop: 12,
|
||||
},
|
||||
guestButtonText: {
|
||||
color: '#007AFF',
|
||||
fontSize: 16,
|
||||
fontWeight: '600',
|
||||
},
|
||||
headerBanner: {
|
||||
position: 'absolute',
|
||||
top: 16,
|
||||
@@ -229,18 +346,4 @@ const styles = StyleSheet.create({
|
||||
right: 8,
|
||||
fontSize: 16,
|
||||
},
|
||||
centerContent: {
|
||||
flex: 1,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
padding: 20,
|
||||
},
|
||||
title: {
|
||||
marginBottom: 8,
|
||||
textAlign: 'center',
|
||||
},
|
||||
subtitle: {
|
||||
textAlign: 'center',
|
||||
opacity: 0.7,
|
||||
},
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user