package com.gyf.csams.account.model import android.app.Application import android.content.Intent import android.os.Build import androidx.lifecycle.AndroidViewModel import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.viewModelScope import com.google.gson.Gson 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.account.ui.AccountRoute import com.gyf.csams.uikit.StringForm import com.gyf.csams.util.* import com.orhanobut.logger.Logger import kotlinx.coroutines.Job import kotlinx.coroutines.launch import kotlinx.serialization.Serializable /** * 响应自动生成密码 * * @property password */ @Serializable data class UserResDto(val password: String) /** * 构造登录、注册信息实体表单 * * @property studentId 学号 * @property name 姓名 */ data class UserVo(val studentId: String, val name: String) /** * 用户登陆表单 * * @property studentId 学号 * @property password 密码 * @property device 设备型号 */ data class UserLoginVo(val studentId: String, val password: String, val device: String) /** * 密码弹窗信息 * * @property message * @property userResDto */ data class DialogMessage(val message: String, val userResDto: UserResDto?) typealias Token = TokenResDto /** * 注册表单 */ class AccountViewModel(application: Application) : AndroidViewModel(application) { //欢迎信息 val welcomeStart = "同学您好\n" val welcomeEnd = "欢迎使用" //学号 val studentId = object : StringForm(formDesc = "学号", textLength = 8) { override fun onChange(value: String) { super.onChange(value) viewModelScope.launch { checkRepeat() } } } private val _isValidStudentId = MutableLiveData() val isValidStudentId: LiveData = _isValidStudentId val studentIdFormat = "入学年份(四位)+班级代码(两位)+学生代码(两位)" //学号已存在 private val _isRepeat = MutableLiveData() val isRepeat: LiveData = _isRepeat val regBtnDesc = "注册" //已注册 val registered = "已$regBtnDesc" //可注册 val canRegister = "可$regBtnDesc" //提示信息 val checkRegTip = "检测学号是否已${regBtnDesc}。。。" private var checkJob: Job? = null //姓名 val name = object : StringForm(formDesc = "姓名", textLength = 4) { override fun onChange(value: String) { super.onChange(value) checkForm() } } private val _isValidName = MutableLiveData() val isValidName: LiveData = _isValidName val nameFormat = "姓名不能为空" //密码 val password = object : StringForm(formDesc = "密码", textLength = 8) { override fun onChange(value: String) { super.onChange(value) checkForm() } } private val _isValidPwd = MutableLiveData() val isValidPwd: LiveData = _isValidPwd val passwordFormat = "八位纯数字" //注册按钮 private val _isValidForm = MutableLiveData() val isValidForm: LiveData = _isValidForm //注册请求响应信息 private val _snackBarMsg = MutableLiveData() val snackBarMsg: LiveData = _snackBarMsg private val _dialogMsg = MutableLiveData() val dialogMsg: LiveData = _dialogMsg val loginDesc = "登陆" //返回登陆 val backLogin = "返回$loginDesc" //确定按钮 val confirmDesc = "确定" //显示密码提示 val title = "提示信息" val passwordTip = "密码会在点击${regBtnDesc}以后,在后台自动生成,请留意系统提示。" val passwordDialogStart = "${regBtnDesc}成功,后台为您自动生成的密码是" val passwordDialogEnd = "\n密码有且只有这里显示一次,请在记住密码后点击确定或${backLogin}。" //转到注册 var goRegister = "转到$regBtnDesc" /** * 完成登录状态 */ private val _finishLogin = MutableLiveData() val finishLogin: LiveData = _finishLogin 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() { if (checkStudentId()) { 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 = { _snackBarMsg.postValue(it) }, type = object : TypeToken>() {}.type ), mapOf("studentId" to "${studentId.formValue.value}") ) } } } else { _isValidForm.postValue(false) } } /** * 检测姓名 * * @return */ private fun checkName(): Boolean { _isValidName.value = name.formValue.value?.isNotEmpty() return _isValidName.value == true } /** * 检测密码 * * @return */ private fun checkPassword(): Boolean { _isValidPwd.value = password.formValue.value?.matches(Regex("\\d{8}")) return _isValidPwd.value == true } private fun checkForm(): Boolean { if (checkJob?.isActive == true) { _isValidForm.value = false } else { _isValidForm.value = checkStudentId() && (if (route == AccountRoute.register) checkName() && isRepeat.value == false else checkPassword()) } return _isValidForm.value == true } /** * 注册 * */ fun register() { if (checkForm()) { val url = Api.buildUrl(AccountApi.Register) Logger.i("开始$regBtnDesc,请求接口:$url") HttpClient.post( url, SimpleCallback( action = regBtnDesc, onSuccess = { _dialogMsg.postValue( DialogMessage( message = it.message, userResDto = it.body ) ) }, onFail = { _snackBarMsg.postValue(it) }, type = object : TypeToken>() {}.type ), jsonBody = Gson().toJson( UserVo( studentId = "${studentId.formValue.value}", name = "${name.formValue.value}" ) ) ) resetForm() } else { Logger.wtf("表单校验失败,无法$regBtnDesc!!!") } } /** * */ /** * 重置信息 * */ fun resetRegisterResMsg() { _snackBarMsg.value = "" } fun resetDialogMsg() { _dialogMsg.value = null } private fun resetForm() { studentId.onChange("") name.onChange("") } /** * 登录 * */ fun login() { if (checkForm()) { val url = Api.buildUrl(AccountApi.Login) Logger.i("开始$loginDesc,请求接口:$url") HttpClient.post( url, SimpleCallback( action = loginDesc, onSuccess = { _snackBarMsg.postValue(it.message) val context = getApplication().applicationContext val token = it.body?.token if (token != null) { val db = AppDatabase.getInstance(context) viewModelScope.launch { db?.tokenDao()?.save(token = token) }.invokeOnCompletion { context.startActivity(Intent(context, InitActivity::class.java)) _finishLogin.postValue(true) } } }, onFail = { _snackBarMsg.postValue(it) }, type = object : TypeToken>() {}.type ), jsonBody = Gson().toJson( UserLoginVo( studentId = "${studentId.formValue.value}", password = "${password.formValue.value}", device = "${Build.MANUFACTURER} ${Build.MODEL}" ) ) ) } else { Logger.wtf("表单校验失败,无法$loginDesc!!!") } } }