From ffa5b425f39f703114260eabd781bc37c4fea068 Mon Sep 17 00:00:00 2001 From: iammm0 Date: Tue, 27 Jan 2026 14:30:45 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20=E4=BC=98=E5=8C=96=E5=89=8D?= =?UTF-8?q?=E7=AB=AF=E7=99=BB=E5=BD=95=E6=B3=A8=E5=86=8C=E7=95=8C=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 优化LoginScreen登录界面 - 优化RegisterScreen注册界面 - 优化AuthViewModel认证ViewModel --- .../huaga/life_echo/ui/screens/LoginScreen.kt | 99 ++++++++++++++++--- .../life_echo/ui/screens/RegisterScreen.kt | 89 +++++++++++++++-- .../life_echo/ui/viewmodel/AuthViewModel.kt | 16 +-- 3 files changed, 175 insertions(+), 29 deletions(-) diff --git a/app-android/app/src/main/java/com/huaga/life_echo/ui/screens/LoginScreen.kt b/app-android/app/src/main/java/com/huaga/life_echo/ui/screens/LoginScreen.kt index cd12c66..79fa6f4 100644 --- a/app-android/app/src/main/java/com/huaga/life_echo/ui/screens/LoginScreen.kt +++ b/app-android/app/src/main/java/com/huaga/life_echo/ui/screens/LoginScreen.kt @@ -32,6 +32,8 @@ fun LoginScreen( onLoginSuccess: () -> Unit, onNavigateToRegister: () -> Unit, onNavigateToResetPassword: (() -> Unit)? = null, + onNavigateToTerms: () -> Unit = {}, + onNavigateToPrivacy: () -> Unit = {}, viewModel: AuthViewModel = viewModel( factory = ViewModelFactory(LocalContext.current) ) @@ -43,6 +45,7 @@ fun LoginScreen( var password by remember { mutableStateOf("") } var passwordVisible by remember { mutableStateOf(false) } var smsCode by remember { mutableStateOf("") } + var agreedToTerms by remember { mutableStateOf(false) } var showResultDialog by remember { mutableStateOf(false) } val isLoading by viewModel.isLoading.collectAsState() @@ -211,14 +214,18 @@ fun LoginScreen( Spacer(modifier = Modifier.height(16.dp)) - // 验证码输入框 - SmsCodeInput( - code = smsCode, - onCodeChange = { smsCode = it }, - codeLength = 6, - enabled = !isLoading, - modifier = Modifier.fillMaxWidth() - ) + // 验证码输入框 - 居中显示 + Box( + modifier = Modifier.fillMaxWidth(), + contentAlignment = Alignment.Center + ) { + SmsCodeInput( + code = smsCode, + onCodeChange = { smsCode = it }, + codeLength = 6, + enabled = !isLoading + ) + } } } @@ -250,19 +257,84 @@ fun LoginScreen( ) } + Spacer(modifier = Modifier.height(24.dp)) + + // 同意协议复选框 - 使用Column支持换行 + Row( + modifier = Modifier.fillMaxWidth(), + verticalAlignment = Alignment.Top, + horizontalArrangement = Arrangement.Start + ) { + Checkbox( + checked = agreedToTerms, + onCheckedChange = { agreedToTerms = it }, + enabled = !isLoading, + modifier = Modifier.padding(top = 2.dp) + ) + Spacer(modifier = Modifier.width(8.dp)) + Column( + modifier = Modifier.weight(1f) + ) { + Row( + modifier = Modifier.wrapContentWidth(), + verticalAlignment = Alignment.CenterVertically + ) { + Text( + text = "我已阅读并同意", + fontSize = 12.sp, + color = MaterialTheme.colorScheme.onSurfaceVariant + ) + TextButton( + onClick = onNavigateToTerms, + contentPadding = PaddingValues(horizontal = 4.dp, vertical = 0.dp), + modifier = Modifier.height(24.dp) + ) { + Text( + text = "《用户协议》", + fontSize = 12.sp, + color = LightPurple + ) + } + } + Row( + modifier = Modifier.wrapContentWidth(), + verticalAlignment = Alignment.CenterVertically + ) { + Text( + text = "和", + fontSize = 12.sp, + color = MaterialTheme.colorScheme.onSurfaceVariant + ) + TextButton( + onClick = onNavigateToPrivacy, + contentPadding = PaddingValues(horizontal = 4.dp, vertical = 0.dp), + modifier = Modifier.height(24.dp) + ) { + Text( + text = "《隐私政策》", + fontSize = 12.sp, + color = LightPurple + ) + } + } + } + } + + Spacer(modifier = Modifier.height(16.dp)) + // 登录按钮 Button( onClick = { val trimmedPhone = phone.trim() if (isPasswordMode) { // 密码登录 - if (trimmedPhone.length == 11 && password.length >= 6) { - viewModel.login(trimmedPhone, password) + if (trimmedPhone.length == 11 && password.length >= 6 && agreedToTerms) { + viewModel.login(trimmedPhone, password, agreedToTerms) } } else { // 验证码登录 - if (trimmedPhone.length == 11 && smsCode.length == 6) { - viewModel.loginWithSms(trimmedPhone, smsCode) + if (trimmedPhone.length == 11 && smsCode.length == 6 && agreedToTerms) { + viewModel.loginWithSms(trimmedPhone, smsCode, agreedToTerms) } } }, @@ -270,7 +342,8 @@ fun LoginScreen( .fillMaxWidth() .height(48.dp), enabled = !isLoading && phone.trim().length == 11 && - (if (isPasswordMode) password.length >= 6 else smsCode.length == 6), + (if (isPasswordMode) password.length >= 6 else smsCode.length == 6) && + agreedToTerms, colors = ButtonDefaults.buttonColors( containerColor = LightPurple, disabledContainerColor = MaterialTheme.colorScheme.surfaceVariant diff --git a/app-android/app/src/main/java/com/huaga/life_echo/ui/screens/RegisterScreen.kt b/app-android/app/src/main/java/com/huaga/life_echo/ui/screens/RegisterScreen.kt index 0f430ab..295b665 100644 --- a/app-android/app/src/main/java/com/huaga/life_echo/ui/screens/RegisterScreen.kt +++ b/app-android/app/src/main/java/com/huaga/life_echo/ui/screens/RegisterScreen.kt @@ -32,6 +32,8 @@ import com.huaga.life_echo.ui.viewmodel.ViewModelFactory @Composable fun RegisterScreen( onRegisterSuccess: () -> Unit, + onNavigateToTerms: () -> Unit = {}, + onNavigateToPrivacy: () -> Unit = {}, viewModel: AuthViewModel = viewModel( factory = ViewModelFactory(LocalContext.current) ) @@ -44,6 +46,7 @@ fun RegisterScreen( var email by remember { mutableStateOf("") } var passwordVisible by remember { mutableStateOf(false) } var confirmPasswordVisible by remember { mutableStateOf(false) } + var agreedToTerms by remember { mutableStateOf(false) } var showResultDialog by remember { mutableStateOf(false) } val isLoading by viewModel.isLoading.collectAsState() @@ -75,7 +78,8 @@ fun RegisterScreen( smsCode.length == 6 && password.length >= 6 && password == confirmPassword && - nickname.isNotBlank() + nickname.isNotBlank() && + agreedToTerms // 错误消息Snackbar val snackbarHostState = remember { SnackbarHostState() } @@ -168,12 +172,17 @@ fun RegisterScreen( color = MaterialTheme.colorScheme.onSurfaceVariant ) - SmsCodeInput( - code = smsCode, - onCodeChange = { smsCode = it }, - enabled = !isLoading, - modifier = Modifier.fillMaxWidth() - ) + // 验证码输入框 - 居中显示 + Box( + modifier = Modifier.fillMaxWidth(), + contentAlignment = Alignment.Center + ) { + SmsCodeInput( + code = smsCode, + onCodeChange = { smsCode = it }, + enabled = !isLoading + ) + } } } @@ -273,6 +282,69 @@ fun RegisterScreen( item { Spacer(modifier = Modifier.height(16.dp)) + // 同意协议复选框 - 使用Column支持换行 + Row( + modifier = Modifier.fillMaxWidth(), + verticalAlignment = Alignment.Top, + horizontalArrangement = Arrangement.Start + ) { + Checkbox( + checked = agreedToTerms, + onCheckedChange = { agreedToTerms = it }, + enabled = !isLoading, + modifier = Modifier.padding(top = 2.dp) + ) + Spacer(modifier = Modifier.width(8.dp)) + Column( + modifier = Modifier.weight(1f) + ) { + Row( + modifier = Modifier.wrapContentWidth(), + verticalAlignment = Alignment.CenterVertically + ) { + Text( + text = "我已阅读并同意", + fontSize = 12.sp, + color = MaterialTheme.colorScheme.onSurfaceVariant + ) + TextButton( + onClick = onNavigateToTerms, + contentPadding = PaddingValues(horizontal = 4.dp, vertical = 0.dp), + modifier = Modifier.height(24.dp) + ) { + Text( + text = "《用户协议》", + fontSize = 12.sp, + color = LightPurple + ) + } + } + Row( + modifier = Modifier.wrapContentWidth(), + verticalAlignment = Alignment.CenterVertically + ) { + Text( + text = "和", + fontSize = 12.sp, + color = MaterialTheme.colorScheme.onSurfaceVariant + ) + TextButton( + onClick = onNavigateToPrivacy, + contentPadding = PaddingValues(horizontal = 4.dp, vertical = 0.dp), + modifier = Modifier.height(24.dp) + ) { + Text( + text = "《隐私政策》", + fontSize = 12.sp, + color = LightPurple + ) + } + } + } + } + + Spacer(modifier = Modifier.height(16.dp)) + // 注册按钮 Button( onClick = { @@ -282,7 +354,8 @@ fun RegisterScreen( code = smsCode, password = password, nickname = nickname, - email = if (email.isNotBlank()) email else null + email = if (email.isNotBlank()) email else null, + agreedToTerms = agreedToTerms ) } }, diff --git a/app-android/app/src/main/java/com/huaga/life_echo/ui/viewmodel/AuthViewModel.kt b/app-android/app/src/main/java/com/huaga/life_echo/ui/viewmodel/AuthViewModel.kt index c7805fa..ee5392b 100644 --- a/app-android/app/src/main/java/com/huaga/life_echo/ui/viewmodel/AuthViewModel.kt +++ b/app-android/app/src/main/java/com/huaga/life_echo/ui/viewmodel/AuthViewModel.kt @@ -68,14 +68,14 @@ class AuthViewModel(private val context: Context) : ViewModel() { /** * 用户登录 */ - fun login(phone: String, password: String) { + fun login(phone: String, password: String, agreedToTerms: Boolean) { viewModelScope.launch { _isLoading.value = true _errorMessage.value = null _successMessage.value = null _operationResult.value = null - val result = authService.login(phone, password) + val result = authService.login(phone, password, agreedToTerms) result.fold( onSuccess = { tokenResponse -> @@ -127,14 +127,14 @@ class AuthViewModel(private val context: Context) : ViewModel() { /** * 用户注册 */ - fun register(phone: String, password: String, nickname: String, email: String? = null) { + fun register(phone: String, password: String, nickname: String, email: String? = null, agreedToTerms: Boolean) { viewModelScope.launch { _isLoading.value = true _errorMessage.value = null _successMessage.value = null _operationResult.value = null - val result = authService.register(phone, password, nickname, email) + val result = authService.register(phone, password, nickname, email, agreedToTerms) result.fold( onSuccess = { tokenResponse -> @@ -340,14 +340,14 @@ class AuthViewModel(private val context: Context) : ViewModel() { /** * 验证码登录 */ - fun loginWithSms(phone: String, code: String) { + fun loginWithSms(phone: String, code: String, agreedToTerms: Boolean) { viewModelScope.launch { _isLoading.value = true _errorMessage.value = null _successMessage.value = null _operationResult.value = null - val result = authService.loginWithSms(phone, code) + val result = authService.loginWithSms(phone, code, agreedToTerms) result.fold( onSuccess = { tokenResponse -> @@ -391,14 +391,14 @@ class AuthViewModel(private val context: Context) : ViewModel() { /** * 验证码注册 */ - fun registerWithSms(phone: String, code: String, password: String, nickname: String, email: String? = null) { + fun registerWithSms(phone: String, code: String, password: String, nickname: String, email: String? = null, agreedToTerms: Boolean) { viewModelScope.launch { _isLoading.value = true _errorMessage.value = null _successMessage.value = null _operationResult.value = null - val result = authService.registerWithSms(phone, code, password, nickname, email) + val result = authService.registerWithSms(phone, code, password, nickname, email, agreedToTerms) result.fold( onSuccess = { tokenResponse ->