diff --git a/foreground/src/main/java/com/gyf/csams/account/model/AccountViewModel.kt b/foreground/src/main/java/com/gyf/csams/account/model/AccountViewModel.kt index a9f9b23..1700e18 100644 --- a/foreground/src/main/java/com/gyf/csams/account/model/AccountViewModel.kt +++ b/foreground/src/main/java/com/gyf/csams/account/model/AccountViewModel.kt @@ -12,12 +12,14 @@ import com.google.gson.reflect.TypeToken import com.gyf.csams.AccountApi import com.gyf.csams.Api import com.gyf.csams.InitActivity +import com.gyf.csams.R import com.gyf.csams.account.ui.AccountRoute import com.gyf.csams.util.AppDatabase import com.gyf.csams.util.SimpleCallback import com.gyf.csams.util.TokenResDto -import com.gyf.lib.uikit.ScaffoldModel +import com.gyf.lib.uikit.FormStatus import com.gyf.lib.uikit.StringForm +import com.gyf.lib.uikit.ValidStringForm import com.gyf.lib.util.ApiResponse import com.gyf.lib.util.HttpClient import com.orhanobut.logger.Logger @@ -58,49 +60,28 @@ data class DialogMessage(val message: String, val userResDto: UserResDto?) typealias Token = TokenResDto + /** * 注册表单 */ class AccountViewModel(application: Application) : AndroidViewModel(application) { - - - //欢迎信息 - val welcomeStart = "同学您好\n" - val welcomeEnd = "欢迎使用" - - lateinit var scaffoldModel: ScaffoldModel - //学号 - val studentId = object : StringForm(formDesc = "学号", textLength = 8) { - override fun onChange(value: String) { - super.onChange(value) - viewModelScope.launch { - checkRepeat { - scaffoldModel.update(message = it) + val studentId = object : ValidStringForm(formDesc = "学号", textLength = 8) { + override fun check() { + _formValue.value?.let { + when { + !it.matches(Regex("\\d{8}")) -> _statusForm.value = FormStatus.FormatError + it.matches(Regex("\\d{8}")) -> checkRepeat(_statusForm) } } } } - private val _isValidStudentId = MutableLiveData() - val isValidStudentId: LiveData = _isValidStudentId - - val studentIdFormat = "入学年份(四位)+班级代码(两位)+学生代码(两位)" - - //学号已存在 - private val _isRepeat = MutableLiveData() - val isRepeat: LiveData = _isRepeat - val regBtnDesc = "注册" + val regBtnDesc = application.getString(R.string.reg_btn) //已注册 val registered = "已$regBtnDesc" - //可注册 - val canRegister = "可$regBtnDesc" - - //提示信息 - val checkRegTip = "检测学号是否已${regBtnDesc}。。。" - private var checkJob: Job? = null //姓名 @@ -159,43 +140,33 @@ class AccountViewModel(application: Application) : AndroidViewModel(application) lateinit var route: AccountRoute - /** - * 检查学号格式 - * - */ - private fun checkStudentId(): Boolean { - _isValidStudentId.value = studentId.formValue.value?.matches(Regex("\\d{8}")) - return _isValidStudentId.value == true - } - /** * 检查学号是否已注册 * */ - private suspend fun checkRepeat(onFail: (error: String) -> Unit) { - if (checkStudentId()) { + private fun checkRepeat(result: MutableLiveData) { + viewModelScope.launch { if (checkJob?.isActive == true) { - checkJob?.join() - } else { - _isRepeat.postValue(null) - checkJob = viewModelScope.launch { - val url = Api.buildUrl(AccountApi.CheckId) - Logger.i("检测${studentId.formDesc},请求接口$url") - HttpClient.get( - url, SimpleCallback( - action = "${studentId.formDesc}重复检测", - onSuccess = { - _isRepeat.postValue(it.body) - _isValidForm.postValue(_isValidName.value == true && it.body == false) - }, - onFail = onFail, - type = object : TypeToken>() {}.type - ), mapOf("studentId" to "${studentId.formValue.value}") - ) - } + checkJob?.cancel() + } + checkJob = viewModelScope.launch { + val url = Api.buildUrl(AccountApi.CheckId) + Logger.i("检测${studentId.formDesc},请求接口$url") + HttpClient.get( + url, SimpleCallback( + action = "${studentId.formDesc}重复检测", + onSuccess = { + if (it.body == true) { + result.postValue(FormStatus.Repeat) + } else { + result.postValue(FormStatus.Valid) + } + }, + onFail = { Logger.e(it) }, + type = object : TypeToken>() {}.type + ), mapOf("studentId" to "${studentId.formValue.value}") + ) } - } else { - _isValidForm.postValue(false) } } @@ -224,7 +195,7 @@ class AccountViewModel(application: Application) : AndroidViewModel(application) _isValidForm.value = false } else { _isValidForm.value = - checkStudentId() && (if (route == AccountRoute.Register) checkName() && isRepeat.value == false else checkPassword()) + studentId.statusForm.value == FormStatus.Valid && (if (route == AccountRoute.Register) checkName() else checkPassword()) } return _isValidForm.value == true } diff --git a/foreground/src/main/java/com/gyf/csams/account/ui/AccountActivity.kt b/foreground/src/main/java/com/gyf/csams/account/ui/AccountActivity.kt index 3013d5e..2243290 100644 --- a/foreground/src/main/java/com/gyf/csams/account/ui/AccountActivity.kt +++ b/foreground/src/main/java/com/gyf/csams/account/ui/AccountActivity.kt @@ -13,6 +13,7 @@ import androidx.compose.runtime.livedata.observeAsState import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext +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 @@ -23,13 +24,13 @@ 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.uikit.AnimationText import com.gyf.lib.uikit.BaseTextField import com.gyf.lib.uikit.Body +import com.gyf.lib.uikit.FormStatus import com.gyf.lib.uikit.ScaffoldModel -import com.orhanobut.logger.Logger enum class AccountRoute { @@ -131,7 +132,6 @@ class AccountActivity : ComponentActivity() { route: AccountRoute, Action: @Composable (isValidForm: Boolean, accountViewModel: AccountViewModel, scaffoldModel: ScaffoldModel) -> Unit ) { - accountViewModel.scaffoldModel = scaffoldModel accountViewModel.route = route Row( horizontalArrangement = Arrangement.Center, @@ -147,10 +147,10 @@ class AccountActivity : ComponentActivity() { append(accountViewModel.name.formValue.value ?: "") } withStyle(style = MaterialTheme.typography.subtitle1.toSpanStyle()) { - append(accountViewModel.welcomeStart) + append(stringResource(id = R.string.welcome_start)) } withStyle(style = MaterialTheme.typography.subtitle2.toSpanStyle()) { - append(accountViewModel.welcomeEnd) + append(stringResource(id = R.string.welcome_end)) } withStyle( style = MaterialTheme.typography.subtitle2.toSpanStyle() @@ -188,53 +188,39 @@ class AccountActivity : ComponentActivity() { Column { - val isValidStudentId: Boolean by accountViewModel.isValidStudentId.observeAsState(false) + val isValidStudentId by accountViewModel.studentId.statusForm.observeAsState() BaseTextField( form = accountViewModel.studentId, keyboardOptions = KeyboardOptions.Default.copy( keyboardType = KeyboardType.Number, imeAction = ImeAction.Done - ), isError = !isValidStudentId + ), isError = isValidStudentId != FormStatus.Valid ) - if (isValidStudentId) { - if (checkRepeat) { - val isRepeat: Boolean? by accountViewModel.isRepeat.observeAsState(null) - Logger.i("isRepeat=$isRepeat") - when (isRepeat) { - null -> AnimationText(text = accountViewModel.checkRegTip) - true -> - Text(buildAnnotatedString { - append(accountViewModel.studentId.formDesc) - withStyle( - style = MaterialTheme.typography.body1.toSpanStyle().copy( - color = MaterialTheme.colors.error - ) - ) { - append(accountViewModel.studentId.formValue.value ?: "") - } - append(accountViewModel.registered) - }) - false -> - Text(buildAnnotatedString { - append(accountViewModel.studentId.formDesc) - withStyle( - style = MaterialTheme.typography.body1.toSpanStyle().copy( - color = MaterialTheme.colors.primary - ) - ) { - append(accountViewModel.studentId.formValue.value ?: "") - } - append(accountViewModel.canRegister) - }) - } - } - } else { - Text( - text = accountViewModel.studentIdFormat, + + 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.studentId.formDesc) + withStyle( + style = MaterialTheme.typography.body1.toSpanStyle().copy( + color = MaterialTheme.colors.error + ) + ) { + append(accountViewModel.studentId.formValue.value ?: "") + } + append(accountViewModel.registered) + }) + else -> { + + } } + } } diff --git a/foreground/src/main/java/com/gyf/csams/activity/model/ApplyActViewModel.kt b/foreground/src/main/java/com/gyf/csams/activity/model/ApplyActViewModel.kt index d27df74..b5be74f 100644 --- a/foreground/src/main/java/com/gyf/csams/activity/model/ApplyActViewModel.kt +++ b/foreground/src/main/java/com/gyf/csams/activity/model/ApplyActViewModel.kt @@ -54,15 +54,15 @@ class ApplyActViewModel(application: Application) : AndroidViewModel(application StringForm(formDesc = application.getString(R.string.activity_size), textLength = 2) { override fun onChange(value: String) { if (value.length > textLength) { - formError.value = "${formDesc}不能超过最大长度$textLength" +// formError.value = "${formDesc}不能超过最大长度$textLength" _formValue.value = value.slice(IntRange(0, textLength - 1)) } else if (value.matches(Regex("\\d+")) && value.toInt() !in 1..maxActivitySize) { Logger.i("活动人数:${value}不合法") - formError.value = - application.getString(R.string.activity_size_error, 1, maxActivitySize) +// formError.value = +// application.getString(R.string.activity_size_error, 1, maxActivitySize) } else { _formValue.value = value - formError.value = "" +// formError.value = "" } } diff --git a/foreground/src/main/java/com/gyf/csams/activity/ui/ApplyActActivity.kt b/foreground/src/main/java/com/gyf/csams/activity/ui/ApplyActActivity.kt index 24cd3d3..ac47543 100644 --- a/foreground/src/main/java/com/gyf/csams/activity/ui/ApplyActActivity.kt +++ b/foreground/src/main/java/com/gyf/csams/activity/ui/ApplyActActivity.kt @@ -161,10 +161,11 @@ class ApplyActActivity : AppCompatActivity() { modifier = Modifier.weight(0.3F), stringForm = model.activityDesc ) - val error by model.activitySize.formError.observeAsState() - if (error?.isNotEmpty() == true) { - scaffoldModel.update(message = error) - } + //TODO 活动人数不合法警告 +// val error by model.activitySize.formError.observeAsState() +// if (error?.isNotEmpty() == true) { +// scaffoldModel.update(message = error) +// } Row( Modifier .weight(0.1F) diff --git a/foreground/src/main/res/values-en/strings.xml b/foreground/src/main/res/values-en/strings.xml index b75ce61..f9f4b66 100644 --- a/foreground/src/main/res/values-en/strings.xml +++ b/foreground/src/main/res/values-en/strings.xml @@ -12,4 +12,7 @@ 城市 地点 市内找 + 入学年份(四位)+班级代码(两位)+学生代码(两位) + 同学您好\n + 欢迎使用 \ No newline at end of file diff --git a/foreground/src/main/res/values-zh/strings.xml b/foreground/src/main/res/values-zh/strings.xml index b75ce61..f9f4b66 100644 --- a/foreground/src/main/res/values-zh/strings.xml +++ b/foreground/src/main/res/values-zh/strings.xml @@ -12,4 +12,7 @@ 城市 地点 市内找 + 入学年份(四位)+班级代码(两位)+学生代码(两位) + 同学您好\n + 欢迎使用 \ No newline at end of file diff --git a/foreground/src/main/res/values/strings.xml b/foreground/src/main/res/values/strings.xml index 642eed0..3730508 100644 --- a/foreground/src/main/res/values/strings.xml +++ b/foreground/src/main/res/values/strings.xml @@ -12,4 +12,7 @@ 城市 地点 市内找 + 入学年份(四位)+班级代码(两位)+学生代码(两位) + 同学您好\n + 欢迎使用 \ No newline at end of file diff --git a/lib/src/main/java/com/gyf/lib/uikit/BaseTextField.kt b/lib/src/main/java/com/gyf/lib/uikit/BaseTextField.kt index cebf138..afcf996 100644 --- a/lib/src/main/java/com/gyf/lib/uikit/BaseTextField.kt +++ b/lib/src/main/java/com/gyf/lib/uikit/BaseTextField.kt @@ -18,8 +18,22 @@ import androidx.lifecycle.MutableLiveData import com.orhanobut.logger.Logger +enum class FormStatus { + //空 + Empty, + + //格式不匹配 + FormatError, + + //学号已存在 + Repeat, + + //校验通过 + Valid +} + interface FormLength { - val formError: MutableLiveData + val textLength: Int } abstract class FormName(val formDesc: String) { @@ -38,7 +52,7 @@ abstract class FormName(val formDesc: String) { * * @param formDesc */ -open class StringForm(formDesc: String, val textLength: Int) : +open class StringForm(formDesc: String, override val textLength: Int) : FormName(formDesc = formDesc), FormLength { @@ -49,19 +63,29 @@ open class StringForm(formDesc: String, val textLength: Int) : _formValue.value = value } - override val formError = MutableLiveData("") - override fun onChange(value: String) { - if (value.length > textLength) { - formError.value = "${formDesc}不能超过最大长度$textLength" - _formValue.postValue(value.slice(IntRange(0, textLength - 1))) - } else { - _formValue.postValue(value) + if (value.length <= textLength) { + _formValue.value = value } Logger.i("${formDesc}更新值:${_formValue.value}") } } +open class ValidStringForm(formDesc: String, textLength: Int) : StringForm(formDesc, textLength) { + protected val _statusForm = MutableLiveData(FormStatus.Empty) + val statusForm: LiveData = _statusForm + + override fun onChange(value: String) { + super.onChange(value) + when (_formValue.value?.length) { + null, 0 -> _statusForm.value = FormStatus.Empty + else -> check() + } + } + + protected open fun check() {} +} + /** * 通用文本输入框 *