refactor: 优化前端登录注册界面
- 优化LoginScreen登录界面 - 优化RegisterScreen注册界面 - 优化AuthViewModel认证ViewModel
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
)
|
||||
}
|
||||
},
|
||||
|
||||
@@ -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 ->
|
||||
|
||||
Reference in New Issue
Block a user