You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
366 lines
13 KiB
366 lines
13 KiB
package com.gyf.csams.account.ui
|
|
|
|
import android.content.Intent
|
|
import android.os.Bundle
|
|
import androidx.activity.ComponentActivity
|
|
import androidx.activity.compose.setContent
|
|
import androidx.compose.foundation.layout.*
|
|
import androidx.compose.foundation.text.KeyboardOptions
|
|
import androidx.compose.material.*
|
|
import androidx.compose.runtime.Composable
|
|
import androidx.compose.runtime.getValue
|
|
import androidx.compose.runtime.livedata.observeAsState
|
|
import androidx.compose.ui.Alignment
|
|
import androidx.compose.ui.Modifier
|
|
import androidx.compose.ui.res.stringResource
|
|
import androidx.compose.ui.text.buildAnnotatedString
|
|
import androidx.compose.ui.text.input.ImeAction
|
|
import androidx.compose.ui.text.input.KeyboardType
|
|
import androidx.compose.ui.text.input.PasswordVisualTransformation
|
|
import androidx.compose.ui.text.withStyle
|
|
import androidx.compose.ui.unit.dp
|
|
import androidx.lifecycle.viewmodel.compose.viewModel
|
|
import androidx.navigation.compose.NavHost
|
|
import androidx.navigation.compose.composable
|
|
import com.gyf.csams.BuildConfig
|
|
import com.gyf.csams.R
|
|
import com.gyf.csams.account.model.AccountViewModel
|
|
import com.gyf.csams.account.model.DialogMessage
|
|
import com.gyf.csams.main.ui.MainActivity
|
|
import com.gyf.lib.uikit.*
|
|
|
|
|
|
enum class AccountRoute {
|
|
Login,
|
|
Register
|
|
}
|
|
|
|
class AccountActivity : ComponentActivity() {
|
|
override fun onCreate(savedInstanceState: Bundle?) {
|
|
super.onCreate(savedInstanceState)
|
|
|
|
setContent {
|
|
NavBody { nav, scaffoldState ->
|
|
NavHost(navController = nav, startDestination = AccountRoute.Login.name) {
|
|
composable(AccountRoute.Login.name) {
|
|
Account(
|
|
route = AccountRoute.Login
|
|
) { isValidForm: Boolean, accountViewModel: AccountViewModel, scaffoldModel: ScaffoldModel ->
|
|
|
|
|
|
Spacer(modifier = Modifier.height(10.dp))
|
|
OutlinedButton(
|
|
onClick = {
|
|
accountViewModel.login {
|
|
scaffoldModel.update(message = it)
|
|
}
|
|
},
|
|
enabled = isValidForm,
|
|
modifier = Modifier
|
|
.fillMaxWidth()
|
|
.padding(bottom = 10.dp)
|
|
) {
|
|
|
|
Text(text = stringResource(id = R.string.login_btn))
|
|
}
|
|
|
|
val finishLogin: Boolean? by accountViewModel.finishLogin.observeAsState()
|
|
if (finishLogin == true) {
|
|
startActivity(
|
|
Intent(
|
|
this@AccountActivity,
|
|
MainActivity::class.java
|
|
)
|
|
)
|
|
finish()
|
|
}
|
|
|
|
OutlinedButton(
|
|
onClick = { nav.navigate(AccountRoute.Register.name) },
|
|
modifier = Modifier.fillMaxWidth(),
|
|
colors = ButtonDefaults.outlinedButtonColors(
|
|
contentColor = MaterialTheme.colors.onBackground
|
|
)
|
|
) {
|
|
Text(text = accountViewModel.goRegister)
|
|
}
|
|
ShowSnackbar(scaffoldState = scaffoldState)
|
|
}
|
|
|
|
}
|
|
|
|
composable(AccountRoute.Register.name) {
|
|
Account(
|
|
route = AccountRoute.Register
|
|
) { isValidForm: Boolean, accountViewModel: AccountViewModel, _: ScaffoldModel ->
|
|
Spacer(modifier = Modifier.height(10.dp))
|
|
|
|
OutlinedButton(
|
|
onClick = {
|
|
accountViewModel.register {
|
|
|
|
}
|
|
},
|
|
enabled = isValidForm,
|
|
modifier = Modifier
|
|
.fillMaxWidth()
|
|
.padding(bottom = 10.dp)
|
|
) {
|
|
Text(text = stringResource(id = R.string.reg_btn))
|
|
}
|
|
|
|
OutlinedButton(
|
|
onClick = { nav.navigate(AccountRoute.Login.name) },
|
|
modifier = Modifier.fillMaxWidth(),
|
|
colors = ButtonDefaults.outlinedButtonColors(
|
|
contentColor = MaterialTheme.colors.onBackground
|
|
)
|
|
) {
|
|
Text(text = accountViewModel.backLogin)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 帐号表单
|
|
*
|
|
* @param accountViewModel
|
|
* @param Action 表单操作区域
|
|
*/
|
|
@Composable
|
|
private fun Account(
|
|
accountViewModel: AccountViewModel = viewModel(),
|
|
scaffoldModel: ScaffoldModel = viewModel(),
|
|
route: AccountRoute,
|
|
Action: @Composable (isValidForm: Boolean, accountViewModel: AccountViewModel, scaffoldModel: ScaffoldModel) -> Unit
|
|
) {
|
|
accountViewModel.route = route
|
|
Row(
|
|
horizontalArrangement = Arrangement.Center,
|
|
verticalAlignment = Alignment.CenterVertically,
|
|
modifier = Modifier.fillMaxSize()
|
|
) {
|
|
Column(modifier = Modifier.width(IntrinsicSize.Min)) {
|
|
val name by accountViewModel.name.formValue.observeAsState("")
|
|
Text(buildAnnotatedString {
|
|
withStyle(
|
|
style = MaterialTheme.typography.subtitle1.toSpanStyle()
|
|
.copy(color = MaterialTheme.colors.primary)
|
|
) {
|
|
append(name)
|
|
}
|
|
withStyle(style = MaterialTheme.typography.subtitle1.toSpanStyle()) {
|
|
append(accountViewModel.welcomeStart)
|
|
}
|
|
withStyle(style = MaterialTheme.typography.subtitle2.toSpanStyle()) {
|
|
append(accountViewModel.welcomeEnd)
|
|
}
|
|
withStyle(
|
|
style = MaterialTheme.typography.subtitle2.toSpanStyle()
|
|
.copy(color = MaterialTheme.colors.secondary)
|
|
) {
|
|
append(BuildConfig.foreground_app_name)
|
|
}
|
|
})
|
|
|
|
StudentId()
|
|
Spacer(modifier = Modifier.height(10.dp))
|
|
|
|
|
|
if (route == AccountRoute.Register) Name() else Password()
|
|
|
|
Spacer(modifier = Modifier.height(10.dp))
|
|
PasswordTip()
|
|
val isValidForm: Boolean by accountViewModel.isValidForm.observeAsState(false)
|
|
Action(
|
|
isValidForm = isValidForm,
|
|
accountViewModel = accountViewModel,
|
|
scaffoldModel = scaffoldModel
|
|
)
|
|
RegisterDialog()
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 学号
|
|
* @param accountViewModel
|
|
*/
|
|
@Composable
|
|
private fun StudentId(accountViewModel: AccountViewModel = viewModel()) {
|
|
Column {
|
|
|
|
|
|
val isValidStudentId by accountViewModel.id.statusForm.observeAsState()
|
|
BaseTextField(
|
|
form = accountViewModel.id, keyboardOptions = KeyboardOptions.Default.copy(
|
|
keyboardType = KeyboardType.Number,
|
|
imeAction = ImeAction.Done
|
|
), isError = isValidStudentId != FormStatus.Valid
|
|
)
|
|
|
|
when (isValidStudentId) {
|
|
FormStatus.Empty,
|
|
FormStatus.FormatError -> Text(
|
|
text = stringResource(id = R.string.student_id_format),
|
|
color = MaterialTheme.colors.error,
|
|
style = MaterialTheme.typography.body1
|
|
)
|
|
FormStatus.Repeat ->
|
|
Text(buildAnnotatedString {
|
|
append(accountViewModel.id.formDesc)
|
|
withStyle(
|
|
style = MaterialTheme.typography.body1.toSpanStyle().copy(
|
|
color = MaterialTheme.colors.error
|
|
)
|
|
) {
|
|
append(accountViewModel.id.formValue.value ?: "")
|
|
}
|
|
append(accountViewModel.registered)
|
|
})
|
|
else -> {
|
|
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 注册弹窗
|
|
*
|
|
* @param accountViewModel
|
|
*/
|
|
@Composable
|
|
private fun RegisterDialog(accountViewModel: AccountViewModel = viewModel()) {
|
|
val dialogMsg: DialogMessage? by accountViewModel.dialogMsg.observeAsState(null)
|
|
|
|
val message = dialogMsg?.userPasswordVo?.password
|
|
if (message?.isNotEmpty() == true) {
|
|
PasswordDialog(message = message)
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 密码弹窗
|
|
*
|
|
* @param accountViewModel
|
|
* @param message
|
|
*/
|
|
@Composable
|
|
private fun PasswordDialog(accountViewModel: AccountViewModel = viewModel(), message: String) {
|
|
val button: @Composable () -> Unit = {
|
|
Row(
|
|
horizontalArrangement = Arrangement.Center, modifier = Modifier
|
|
.fillMaxWidth()
|
|
.padding(bottom = 10.dp)
|
|
) {
|
|
OutlinedButton(
|
|
onClick = { accountViewModel.resetDialogMsg() },
|
|
modifier = Modifier.padding(end = 10.dp)
|
|
) {
|
|
Text(text = accountViewModel.confirmDesc)
|
|
}
|
|
OutlinedButton(
|
|
onClick = {
|
|
startActivity(Intent(this@AccountActivity, AccountActivity::class.java))
|
|
},
|
|
colors = ButtonDefaults.outlinedButtonColors(
|
|
contentColor = MaterialTheme.colors.onBackground
|
|
)
|
|
) {
|
|
Text(text = accountViewModel.backLogin)
|
|
}
|
|
}
|
|
}
|
|
AlertDialog(onDismissRequest = { accountViewModel.resetDialogMsg() },
|
|
buttons = button,
|
|
title = { Text(text = accountViewModel.title) },
|
|
text = {
|
|
Text(buildAnnotatedString {
|
|
append(accountViewModel.passwordDialogStart)
|
|
withStyle(
|
|
style = MaterialTheme.typography.body1.toSpanStyle()
|
|
.copy(color = MaterialTheme.colors.secondary)
|
|
) {
|
|
append(message)
|
|
}
|
|
append(accountViewModel.passwordDialogEnd)
|
|
})
|
|
})
|
|
}
|
|
|
|
|
|
/**
|
|
* 姓名文本框
|
|
* @param accountViewModel
|
|
*/
|
|
@Composable
|
|
private fun Name(accountViewModel: AccountViewModel = viewModel()) {
|
|
Column {
|
|
|
|
val formStatus by accountViewModel.name.statusForm.observeAsState()
|
|
BaseTextField(form = accountViewModel.name, isError = formStatus !== FormStatus.Valid)
|
|
|
|
if (formStatus == FormStatus.Empty) {
|
|
Text(
|
|
text = accountViewModel.nameFormat,
|
|
color = MaterialTheme.colors.error
|
|
)
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
* 密码框
|
|
* @param accountViewModel
|
|
*/
|
|
@Composable
|
|
private fun Password(accountViewModel: AccountViewModel = viewModel()) {
|
|
Column {
|
|
val formStatus by accountViewModel.password.statusForm.observeAsState()
|
|
|
|
BaseTextField(
|
|
form = accountViewModel.password, isError = formStatus !== FormStatus.Valid,
|
|
keyboardOptions = KeyboardOptions.Default.copy(
|
|
imeAction = ImeAction.Done,
|
|
keyboardType = KeyboardType.Number,
|
|
), visualTransformation = PasswordVisualTransformation()
|
|
)
|
|
|
|
|
|
when (formStatus) {
|
|
FormStatus.Empty, FormStatus.FormatError -> Text(
|
|
text = accountViewModel.passwordFormat,
|
|
color = MaterialTheme.colors.error
|
|
)
|
|
else -> {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 提示自动生成密码
|
|
*
|
|
* @param accountViewModel
|
|
*/
|
|
@Composable
|
|
private fun PasswordTip(accountViewModel: AccountViewModel = viewModel()) {
|
|
if (accountViewModel.isValidForm.value == true) {
|
|
Text(
|
|
text = accountViewModel.passwordTip, color = MaterialTheme.colors.primary,
|
|
modifier = Modifier.fillMaxWidth()
|
|
)
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|