feat: 样式调整
This commit is contained in:
parent
7b938e37a2
commit
ef70e2f83a
@ -2,6 +2,7 @@ import Handers from '@/assets/icons/svg/handers.svg';
|
|||||||
import LoginIP1 from '@/assets/icons/svg/loginIp1.svg';
|
import LoginIP1 from '@/assets/icons/svg/loginIp1.svg';
|
||||||
import LoginIP2 from '@/assets/icons/svg/loginIp2.svg';
|
import LoginIP2 from '@/assets/icons/svg/loginIp2.svg';
|
||||||
import ForgetPwd from '@/components/login/forgetPwd';
|
import ForgetPwd from '@/components/login/forgetPwd';
|
||||||
|
import Login from '@/components/login/login';
|
||||||
import PhoneLogin from '@/components/login/phoneLogin';
|
import PhoneLogin from '@/components/login/phoneLogin';
|
||||||
import SignUp from '@/components/login/signUp';
|
import SignUp from '@/components/login/signUp';
|
||||||
import { ThemedText } from '@/components/ThemedText';
|
import { ThemedText } from '@/components/ThemedText';
|
||||||
@ -19,7 +20,10 @@ const LoginScreen = () => {
|
|||||||
const [error, setError] = useState<string>('123');
|
const [error, setError] = useState<string>('123');
|
||||||
const [containerHeight, setContainerHeight] = useState(0);
|
const [containerHeight, setContainerHeight] = useState(0);
|
||||||
const { height: windowHeight } = useWindowDimensions();
|
const { height: windowHeight } = useWindowDimensions();
|
||||||
|
// 展示首次输入密码
|
||||||
const [showPassword, setShowPassword] = useState(false);
|
const [showPassword, setShowPassword] = useState(false);
|
||||||
|
// 展示二次输入密码
|
||||||
|
const [showSecondPassword, setShowSecondPassword] = useState(false);
|
||||||
const [keyboardOffset, setKeyboardOffset] = useState(0);
|
const [keyboardOffset, setKeyboardOffset] = useState(0);
|
||||||
const insets = useSafeAreaInsets();
|
const insets = useSafeAreaInsets();
|
||||||
// 判断是否有白边
|
// 判断是否有白边
|
||||||
@ -126,6 +130,8 @@ const LoginScreen = () => {
|
|||||||
{...commonProps}
|
{...commonProps}
|
||||||
setShowPassword={setShowPassword}
|
setShowPassword={setShowPassword}
|
||||||
showPassword={showPassword}
|
showPassword={showPassword}
|
||||||
|
setShowSecondPassword={setShowSecondPassword}
|
||||||
|
showSecondPassword={showSecondPassword}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
forgetPwd: (
|
forgetPwd: (
|
||||||
@ -134,12 +140,12 @@ const LoginScreen = () => {
|
|||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
login: (
|
login: (
|
||||||
// <Login
|
<Login
|
||||||
// {...commonProps}
|
{...commonProps}
|
||||||
// setShowPassword={setShowPassword}
|
setShowPassword={setShowPassword}
|
||||||
// showPassword={showPassword}
|
showPassword={showPassword}
|
||||||
// />
|
/>
|
||||||
<PhoneLogin {...commonProps} />
|
// <PhoneLogin {...commonProps} />
|
||||||
),
|
),
|
||||||
code: (
|
code: (
|
||||||
<PhoneLogin {...commonProps} />
|
<PhoneLogin {...commonProps} />
|
||||||
|
|||||||
@ -2,7 +2,7 @@ import { Ionicons } from "@expo/vector-icons";
|
|||||||
import { router } from "expo-router";
|
import { router } from "expo-router";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { ActivityIndicator, TextInput, TouchableOpacity, View } from "react-native";
|
import { ActivityIndicator, StyleSheet, TextInput, TouchableOpacity, View } from "react-native";
|
||||||
import { useAuth } from "../../contexts/auth-context";
|
import { useAuth } from "../../contexts/auth-context";
|
||||||
import { fetchApi } from "../../lib/server-api-util";
|
import { fetchApi } from "../../lib/server-api-util";
|
||||||
import { User } from "../../types/user";
|
import { User } from "../../types/user";
|
||||||
@ -52,6 +52,7 @@ const Login = ({ updateUrlParam, setError, setShowPassword, showPassword }: Logi
|
|||||||
router.replace('/user-message');
|
router.replace('/user-message');
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
// Handle error
|
||||||
} finally {
|
} finally {
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
}
|
}
|
||||||
@ -64,93 +65,156 @@ const Login = ({ updateUrlParam, setError, setShowPassword, showPassword }: Logi
|
|||||||
const handleSignUp = () => {
|
const handleSignUp = () => {
|
||||||
updateUrlParam('status', 'signUp');
|
updateUrlParam('status', 'signUp');
|
||||||
};
|
};
|
||||||
return <View>
|
|
||||||
{/* 邮箱输入框 */}
|
return (
|
||||||
<View className="mb-5">
|
<View style={styles.container}>
|
||||||
<ThemedText className="text-base !text-textPrimary mb-2 ml-2">
|
<View style={[styles.inputContainer, { marginBottom: 20 }]}>
|
||||||
{t('auth.login.email', { ns: 'login' })}
|
<ThemedText style={styles.inputLabel}>
|
||||||
</ThemedText>
|
{t('auth.login.email', { ns: 'login' })}
|
||||||
<TextInput
|
</ThemedText>
|
||||||
className="border border-gray-300 rounded-2xl p-3 text-base bg-inputBackground"
|
|
||||||
placeholder={t('auth.login.accountPlaceholder', { ns: 'login' })}
|
|
||||||
placeholderTextColor="#ccc"
|
|
||||||
value={email}
|
|
||||||
onChangeText={(text) => {
|
|
||||||
setEmail(text);
|
|
||||||
setError('123');
|
|
||||||
}}
|
|
||||||
keyboardType="email-address"
|
|
||||||
autoCapitalize="none"
|
|
||||||
/>
|
|
||||||
</View>
|
|
||||||
{/* 密码输入框 */}
|
|
||||||
<View className="mb-2">
|
|
||||||
<ThemedText className="text-base !text-textPrimary mb-2 ml-2">
|
|
||||||
{t('auth.login.password', { ns: 'login' })}
|
|
||||||
</ThemedText>
|
|
||||||
<View className="relative">
|
|
||||||
<TextInput
|
<TextInput
|
||||||
className="border border-gray-300 rounded-2xl p-3 text-base bg-inputBackground pr-12"
|
style={styles.textInput}
|
||||||
placeholder={t('auth.login.passwordPlaceholder', { ns: 'login' })}
|
placeholder={t('auth.login.accountPlaceholder', { ns: 'login' })}
|
||||||
placeholderTextColor="#ccc"
|
placeholderTextColor="#ccc"
|
||||||
value={password}
|
value={email}
|
||||||
onChangeText={(text) => {
|
onChangeText={(text) => {
|
||||||
setPassword(text);
|
setEmail(text);
|
||||||
setError('123');
|
setError('123');
|
||||||
}}
|
}}
|
||||||
secureTextEntry={!showPassword}
|
autoCapitalize="none"
|
||||||
/>
|
/>
|
||||||
<TouchableOpacity
|
</View>
|
||||||
className="absolute right-3 top-3.5"
|
|
||||||
onPress={() => setShowPassword(!showPassword)}
|
<View style={styles.inputContainer}>
|
||||||
>
|
<ThemedText style={styles.inputLabel}>
|
||||||
<Ionicons
|
{t('auth.login.password', { ns: 'login' })}
|
||||||
name={showPassword ? 'eye' : 'eye-off'}
|
</ThemedText>
|
||||||
size={20}
|
<View style={styles.passwordInputContainer}>
|
||||||
color="#666"
|
<TextInput
|
||||||
|
style={[styles.textInput, { paddingRight: 48 }]}
|
||||||
|
placeholder={t('auth.login.passwordPlaceholder', { ns: 'login' })}
|
||||||
|
placeholderTextColor="#ccc"
|
||||||
|
value={password}
|
||||||
|
onChangeText={(text) => {
|
||||||
|
setPassword(text);
|
||||||
|
setError('123');
|
||||||
|
}}
|
||||||
|
secureTextEntry={!showPassword}
|
||||||
/>
|
/>
|
||||||
|
<TouchableOpacity
|
||||||
|
style={styles.eyeIcon}
|
||||||
|
onPress={() => setShowPassword(!showPassword)}
|
||||||
|
>
|
||||||
|
<Ionicons
|
||||||
|
name={showPassword ? 'eye' : 'eye-off'}
|
||||||
|
size={20}
|
||||||
|
color="#666"
|
||||||
|
/>
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<TouchableOpacity
|
||||||
|
style={styles.forgotPassword}
|
||||||
|
onPress={handleForgotPassword}
|
||||||
|
>
|
||||||
|
<ThemedText style={styles.forgotPasswordText}>
|
||||||
|
{t('auth.login.forgotPassword', { ns: 'login' })}
|
||||||
|
</ThemedText>
|
||||||
|
</TouchableOpacity>
|
||||||
|
|
||||||
|
<TouchableOpacity
|
||||||
|
style={[styles.loginButton, isLoading && { opacity: 0.7 }]}
|
||||||
|
onPress={handleLogin}
|
||||||
|
disabled={isLoading}
|
||||||
|
>
|
||||||
|
{isLoading ? (
|
||||||
|
<ActivityIndicator color="#fff" />
|
||||||
|
) : (
|
||||||
|
<ThemedText style={styles.loginButtonText}>
|
||||||
|
{t('auth.login.loginButton', { ns: 'login' })}
|
||||||
|
</ThemedText>
|
||||||
|
)}
|
||||||
|
</TouchableOpacity>
|
||||||
|
|
||||||
|
<View style={styles.signupContainer}>
|
||||||
|
<ThemedText style={styles.signupText}>
|
||||||
|
{t('auth.login.signUpMessage', { ns: 'login' })}
|
||||||
|
</ThemedText>
|
||||||
|
<TouchableOpacity onPress={handleSignUp}>
|
||||||
|
<ThemedText style={styles.signupLink}>
|
||||||
|
{t('auth.login.signUp', { ns: 'login' })}
|
||||||
|
</ThemedText>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
{/* 忘记密码链接 */}
|
const styles = StyleSheet.create({
|
||||||
<TouchableOpacity
|
container: {
|
||||||
className="self-end mb-6"
|
flex: 1,
|
||||||
onPress={handleForgotPassword}
|
},
|
||||||
>
|
inputContainer: {
|
||||||
<ThemedText className="!text-textPrimary text-sm">
|
marginBottom: 20,
|
||||||
{t('auth.login.forgotPassword', { ns: 'login' })}
|
},
|
||||||
</ThemedText>
|
inputLabel: {
|
||||||
</TouchableOpacity>
|
fontSize: 16,
|
||||||
|
color: '#1F2937',
|
||||||
|
marginBottom: 8,
|
||||||
|
marginLeft: 8,
|
||||||
|
},
|
||||||
|
textInput: {
|
||||||
|
borderRadius: 12,
|
||||||
|
paddingHorizontal: 16,
|
||||||
|
paddingVertical: 12,
|
||||||
|
fontSize: 16,
|
||||||
|
textAlignVertical: 'center',
|
||||||
|
backgroundColor: '#FFF8DE'
|
||||||
|
},
|
||||||
|
passwordInputContainer: {
|
||||||
|
position: 'relative',
|
||||||
|
},
|
||||||
|
eyeIcon: {
|
||||||
|
position: 'absolute',
|
||||||
|
right: 12,
|
||||||
|
top: 14,
|
||||||
|
},
|
||||||
|
forgotPassword: {
|
||||||
|
alignSelf: 'flex-end',
|
||||||
|
marginBottom: 24,
|
||||||
|
},
|
||||||
|
forgotPasswordText: {
|
||||||
|
color: '#1F2937',
|
||||||
|
fontSize: 14,
|
||||||
|
},
|
||||||
|
loginButton: {
|
||||||
|
width: '100%',
|
||||||
|
backgroundColor: '#E2793F',
|
||||||
|
borderRadius: 28,
|
||||||
|
padding: 16,
|
||||||
|
alignItems: 'center',
|
||||||
|
marginBottom: 24,
|
||||||
|
},
|
||||||
|
loginButtonText: {
|
||||||
|
color: '#FFFFFF',
|
||||||
|
fontWeight: '600',
|
||||||
|
},
|
||||||
|
signupContainer: {
|
||||||
|
flexDirection: 'row',
|
||||||
|
justifyContent: 'center',
|
||||||
|
marginTop: 8,
|
||||||
|
},
|
||||||
|
signupText: {
|
||||||
|
color: '#1F2937',
|
||||||
|
fontSize: 14,
|
||||||
|
},
|
||||||
|
signupLink: {
|
||||||
|
color: '#E2793F',
|
||||||
|
fontSize: 14,
|
||||||
|
fontWeight: '600',
|
||||||
|
marginLeft: 4,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
{/* 登录按钮 */}
|
export default Login;
|
||||||
<TouchableOpacity
|
|
||||||
className={`w-full bg-[#E2793F] rounded-full text-[#fff] p-4 items-center mb-6 ${isLoading ? 'opacity-70' : ''}`}
|
|
||||||
onPress={handleLogin}
|
|
||||||
disabled={isLoading}
|
|
||||||
>
|
|
||||||
{isLoading ? (
|
|
||||||
<ActivityIndicator color="#fff" />
|
|
||||||
) : (
|
|
||||||
<ThemedText className="!text-white font-semibold">
|
|
||||||
{t('auth.login.loginButton', { ns: 'login' })}
|
|
||||||
</ThemedText>
|
|
||||||
)}
|
|
||||||
</TouchableOpacity>
|
|
||||||
|
|
||||||
{/* 注册链接 */}
|
|
||||||
<View className="flex-row justify-center mt-2">
|
|
||||||
<ThemedText className="!text-textPrimary text-sm">
|
|
||||||
{t('auth.login.signUpMessage', { ns: 'login' })}
|
|
||||||
</ThemedText>
|
|
||||||
<TouchableOpacity onPress={handleSignUp}>
|
|
||||||
<ThemedText className="!text-[#E2793F] text-sm font-semibold ml-1">
|
|
||||||
{t('auth.login.signUp', { ns: 'login' })}
|
|
||||||
</ThemedText>
|
|
||||||
</TouchableOpacity>
|
|
||||||
</View>
|
|
||||||
</View>
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
export default Login
|
|
||||||
@ -14,9 +14,11 @@ interface LoginProps {
|
|||||||
setError: (error: string) => void;
|
setError: (error: string) => void;
|
||||||
setShowPassword: (showPassword: boolean) => void;
|
setShowPassword: (showPassword: boolean) => void;
|
||||||
showPassword: boolean;
|
showPassword: boolean;
|
||||||
|
setShowSecondPassword: (showSecondPassword: boolean) => void;
|
||||||
|
showSecondPassword: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const SignUp = ({ updateUrlParam, setError, setShowPassword, showPassword }: LoginProps) => {
|
const SignUp = ({ updateUrlParam, setError, setShowPassword, showPassword, setShowSecondPassword, showSecondPassword }: LoginProps) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { login } = useAuth();
|
const { login } = useAuth();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
@ -32,7 +34,6 @@ const SignUp = ({ updateUrlParam, setError, setShowPassword, showPassword }: Log
|
|||||||
// 从 URL 参数中获取 task_id 和 steps
|
// 从 URL 参数中获取 task_id 和 steps
|
||||||
const params = useLocalSearchParams<{ task_id?: string; steps?: string }>();
|
const params = useLocalSearchParams<{ task_id?: string; steps?: string }>();
|
||||||
const taskId = params.task_id;
|
const taskId = params.task_id;
|
||||||
const steps = params.steps;
|
|
||||||
|
|
||||||
const handlePasswordChange = (value: string) => {
|
const handlePasswordChange = (value: string) => {
|
||||||
setPassword(value);
|
setPassword(value);
|
||||||
@ -139,6 +140,7 @@ const SignUp = ({ updateUrlParam, setError, setShowPassword, showPassword }: Log
|
|||||||
// 初始化
|
// 初始化
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setShowPassword(false)
|
setShowPassword(false)
|
||||||
|
setShowSecondPassword(false)
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
return <View className="w-full">
|
return <View className="w-full">
|
||||||
@ -208,14 +210,14 @@ const SignUp = ({ updateUrlParam, setError, setShowPassword, showPassword }: Log
|
|||||||
handleConfirmPasswordChange(value)
|
handleConfirmPasswordChange(value)
|
||||||
setError('123')
|
setError('123')
|
||||||
}}
|
}}
|
||||||
secureTextEntry={!showPassword}
|
secureTextEntry={!showSecondPassword}
|
||||||
/>
|
/>
|
||||||
<TouchableOpacity
|
<TouchableOpacity
|
||||||
onPress={() => setShowPassword(!showPassword)}
|
onPress={() => setShowSecondPassword(!showSecondPassword)}
|
||||||
className="px-3 py-2"
|
className="px-3 py-2"
|
||||||
>
|
>
|
||||||
<Ionicons
|
<Ionicons
|
||||||
name={showPassword ? 'eye' : 'eye-off'}
|
name={showSecondPassword ? 'eye' : 'eye-off'}
|
||||||
size={20}
|
size={20}
|
||||||
color="#666"
|
color="#666"
|
||||||
/>
|
/>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user