From f15fd6588ef44b85b1abcb9b8c17f00dffa88f02 Mon Sep 17 00:00:00 2001 From: pan <1029559041@qq.com> Date: Fri, 28 May 2021 00:05:54 +0800 Subject: [PATCH] =?UTF-8?q?=E5=89=8D=E5=8F=B0AndroidManifest.xml=20?= =?UTF-8?q?=E5=88=A0=E9=99=A4=E9=83=A8=E5=88=86Activity=20exported?= =?UTF-8?q?=E9=85=8D=E7=BD=AE=20=E7=BB=A7=E6=89=BF=E7=99=BB=E5=BD=95?= =?UTF-8?q?=E6=A8=A1=E5=9D=97=E5=88=B0lib=20=E7=A7=BB=E5=8A=A8=E5=8A=A8?= =?UTF-8?q?=E7=94=BB=E6=96=87=E6=9C=AC=E7=BB=84=E4=BB=B6=E5=88=B0lib=20Scr?= =?UTF-8?q?ollList.kt->ScrollViewModel.kt=20Api=E7=A7=BB=E5=8A=A8=E5=88=B0?= =?UTF-8?q?lib?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- background/src/main/AndroidManifest.xml | 7 +- .../main/java/com/gyf/csams/InitActivity.kt | 14 ++ .../gyf/csams/account/model/LoginViewModel.kt | 32 +++- .../com/gyf/csams/account/ui/LoginActivity.kt | 38 +++-- .../model/AssociationManagementViewModel.kt | 7 +- .../gyf/csams/main/model/CheckActViewModel.kt | 2 +- .../main/model/CheckQualityReportViewModel.kt | 2 +- .../csams/main/model/ManagerActViewModel.kt | 4 +- .../gyf/csams/main/model/RenameViewModel.kt | 4 +- .../main/ui/AssociationManagementActivity.kt | 2 - .../com/gyf/csams/main/ui/MainActivity.kt | 1 + .../main/java/com/gyf/csams/uikit/Table.kt | 4 +- foreground/src/main/AndroidManifest.xml | 40 ++--- .../main/java/com/gyf/csams/InitActivity.kt | 65 +------- .../csams/account/model/AccountViewModel.kt | 142 +++++------------- .../gyf/csams/account/ui/AccountActivity.kt | 28 ++-- .../activity/model/ActivityDetailViewModel.kt | 13 +- .../csams/activity/model/ApplyActViewModel.kt | 2 +- .../association/model/AssociationViewModel.kt | 9 +- .../csams/association/model/ExamViewModel.kt | 7 +- .../model/RegAssociationViewModel.kt | 8 +- .../association/model/RenameViewModel.kt | 2 +- .../com/gyf/csams/main/model/MainViewModel.kt | 9 +- .../com/gyf/csams/main/ui/MainActivity.kt | 2 +- .../message/model/SysMessageViewModel.kt | 18 +-- .../main/java/com/gyf/csams/uikit/BaseView.kt | 24 --- .../java/com/gyf/csams/uikit/ViewModel.kt | 4 +- lib/src/main/java/com/gyf/lib/ScrollList.kt | 34 ----- .../gyf/lib/model/AbstractLoginViewModel.kt | 80 ++++++++++ .../com/gyf/{ => lib/model}/ApplyViewModel.kt | 5 +- .../java/com/gyf/lib/model}/InitViewModel.kt | 15 +- .../java/com/gyf/lib/model/ScrollViewModel.kt | 19 +++ .../gyf/lib/{ => service}/MessageService.kt | 15 +- .../{ => lib/service}/NotificationWorker.kt | 9 +- .../com/gyf/lib/uikit/AbstractInitActivity.kt | 66 ++++++++ .../java/com/gyf/lib/uikit/AnimationText.kt | 33 ++++ .../src/main/java/com/gyf/lib/util}/Api.kt | 24 ++- .../main/java/com/gyf/lib/util/ContextUtil.kt | 4 +- lib/src/main/res/values-en/strings.xml | 1 + lib/src/main/res/values-zh/strings.xml | 1 + lib/src/main/res/values/strings.xml | 1 + 41 files changed, 432 insertions(+), 365 deletions(-) create mode 100644 background/src/main/java/com/gyf/csams/InitActivity.kt delete mode 100644 lib/src/main/java/com/gyf/lib/ScrollList.kt create mode 100644 lib/src/main/java/com/gyf/lib/model/AbstractLoginViewModel.kt rename lib/src/main/java/com/gyf/{ => lib/model}/ApplyViewModel.kt (78%) rename {foreground/src/main/java/com/gyf/csams => lib/src/main/java/com/gyf/lib/model}/InitViewModel.kt (90%) create mode 100644 lib/src/main/java/com/gyf/lib/model/ScrollViewModel.kt rename lib/src/main/java/com/gyf/lib/{ => service}/MessageService.kt (83%) rename lib/src/main/java/com/gyf/{ => lib/service}/NotificationWorker.kt (93%) create mode 100644 lib/src/main/java/com/gyf/lib/uikit/AbstractInitActivity.kt create mode 100644 lib/src/main/java/com/gyf/lib/uikit/AnimationText.kt rename {foreground/src/main/java/com/gyf/csams => lib/src/main/java/com/gyf/lib/util}/Api.kt (74%) diff --git a/background/src/main/AndroidManifest.xml b/background/src/main/AndroidManifest.xml index 75bf62d..64952af 100644 --- a/background/src/main/AndroidManifest.xml +++ b/background/src/main/AndroidManifest.xml @@ -2,6 +2,9 @@ + + + @@ -22,7 +25,7 @@ - + diff --git a/background/src/main/java/com/gyf/csams/InitActivity.kt b/background/src/main/java/com/gyf/csams/InitActivity.kt new file mode 100644 index 0000000..46e03f5 --- /dev/null +++ b/background/src/main/java/com/gyf/csams/InitActivity.kt @@ -0,0 +1,14 @@ +package com.gyf.csams + +import android.app.Activity +import com.gyf.csams.account.ui.LoginActivity +import com.gyf.csams.main.ui.MainActivity +import com.gyf.lib.uikit.AbstractInitActivity +import com.gyf.lib.util.AccountApi + +class InitActivity : AbstractInitActivity() { + override val main: Class = MainActivity::class.java + override val login: Class = LoginActivity::class.java + + override val api: AccountApi = AccountApi.BackgroundToken +} \ No newline at end of file diff --git a/background/src/main/java/com/gyf/csams/account/model/LoginViewModel.kt b/background/src/main/java/com/gyf/csams/account/model/LoginViewModel.kt index 99354da..ad0d804 100644 --- a/background/src/main/java/com/gyf/csams/account/model/LoginViewModel.kt +++ b/background/src/main/java/com/gyf/csams/account/model/LoginViewModel.kt @@ -1,11 +1,31 @@ package com.gyf.csams.account.model -import androidx.lifecycle.ViewModel -import com.gyf.lib.uikit.StringForm +import android.app.Application +import android.os.Build +import com.gyf.lib.model.AbstractLoginViewModel +import com.gyf.lib.uikit.FormStatus +import com.gyf.lib.uikit.ValidStringForm +import com.gyf.lib.util.AccountApi -class LoginViewModel : ViewModel() { - val user = StringForm(formDesc = "管理帐号", textLength = 8) - val password = StringForm(formDesc = "管理密码", textLength = 8) +data class ManagerVo(val account: String, val password: String, val device: String) - val login = "登录" +class LoginViewModel(application: Application) : AbstractLoginViewModel(application) { + override val id = ValidStringForm(formDesc = "管理帐号", textLength = 8) + override val password: ValidStringForm = ValidStringForm(formDesc = "管理密码", textLength = 8) + + override val api: AccountApi = AccountApi.BackgroundLogin + + override fun checkForm(): Boolean { + return id.statusForm.value == FormStatus.Valid && password.statusForm.value == FormStatus.Valid + } + + override fun loginParam(): Any { + val account = "${id.formValue.value}" + val password = "${password.formValue.value}" + return ManagerVo( + account = account, + password = password, + device = "${Build.MANUFACTURER} ${Build.MODEL}" + ) + } } \ No newline at end of file diff --git a/background/src/main/java/com/gyf/csams/account/ui/LoginActivity.kt b/background/src/main/java/com/gyf/csams/account/ui/LoginActivity.kt index f93bbe3..f1744dd 100644 --- a/background/src/main/java/com/gyf/csams/account/ui/LoginActivity.kt +++ b/background/src/main/java/com/gyf/csams/account/ui/LoginActivity.kt @@ -10,17 +10,19 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.material.OutlinedButton import androidx.compose.material.Text +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.platform.LocalContext +import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.input.PasswordVisualTransformation import androidx.compose.ui.unit.dp import androidx.lifecycle.viewmodel.compose.viewModel +import com.gyf.csams.R import com.gyf.csams.account.model.LoginViewModel import com.gyf.csams.main.ui.MainActivity -import com.gyf.lib.uikit.BaseTextField -import com.gyf.lib.uikit.Body -import com.gyf.lib.uikit.MainBoxFrame +import com.gyf.lib.uikit.* /** * 登录 @@ -45,16 +47,34 @@ class LoginActivity : ComponentActivity() { horizontalAlignment = Alignment.CenterHorizontally ) { val model: LoginViewModel = viewModel() - BaseTextField(form = model.user) + val scaffoldModel: ScaffoldModel = viewModel() + val idStatus by model.id.statusForm.observeAsState() + val passwordStatus by model.password.statusForm.observeAsState() + BaseTextField(form = model.id) + BaseTextField( form = model.password, visualTransformation = PasswordVisualTransformation() ) - OutlinedButton(onClick = { - context.startActivity(Intent(context, MainActivity::class.java)) - context.finish() - }) { - Text(text = model.login) + OutlinedButton( + onClick = { + model.login { + scaffoldModel.update(message = it) + } + }, + enabled = idStatus == FormStatus.Valid && passwordStatus == FormStatus.Valid + ) { + Text(text = stringResource(id = R.string.login_btn)) + } + val finishLogin: Boolean? by model.finishLogin.observeAsState() + if (finishLogin == true) { + startActivity( + Intent( + LocalContext.current, + MainActivity::class.java + ) + ) + finish() } } } diff --git a/background/src/main/java/com/gyf/csams/main/model/AssociationManagementViewModel.kt b/background/src/main/java/com/gyf/csams/main/model/AssociationManagementViewModel.kt index 0487460..7b5370d 100644 --- a/background/src/main/java/com/gyf/csams/main/model/AssociationManagementViewModel.kt +++ b/background/src/main/java/com/gyf/csams/main/model/AssociationManagementViewModel.kt @@ -1,7 +1,8 @@ package com.gyf.csams.main.model +import android.app.Application import androidx.lifecycle.viewModelScope -import com.gyf.lib.ScrollList +import com.gyf.lib.model.ScrollViewModel import com.gyf.lib.util.randomChinese import kotlinx.coroutines.launch @@ -48,7 +49,9 @@ data class AssociationVo( * 数据状态管理 * */ -class AssociationManagementViewModel : ScrollList() { +class AssociationManagementViewModel(application: Application) : ScrollViewModel( + application +) { override val initSize: Int = 10 init { diff --git a/background/src/main/java/com/gyf/csams/main/model/CheckActViewModel.kt b/background/src/main/java/com/gyf/csams/main/model/CheckActViewModel.kt index cd63b3a..ef4735c 100644 --- a/background/src/main/java/com/gyf/csams/main/model/CheckActViewModel.kt +++ b/background/src/main/java/com/gyf/csams/main/model/CheckActViewModel.kt @@ -2,7 +2,7 @@ package com.gyf.csams.main.model import android.app.Application import androidx.lifecycle.viewModelScope -import com.gyf.ApplyViewModel +import com.gyf.lib.model.ApplyViewModel import com.gyf.lib.util.format import com.gyf.lib.util.randomChinese import com.gyf.lib.util.randomDateTime diff --git a/background/src/main/java/com/gyf/csams/main/model/CheckQualityReportViewModel.kt b/background/src/main/java/com/gyf/csams/main/model/CheckQualityReportViewModel.kt index abe20ce..e6b0f27 100644 --- a/background/src/main/java/com/gyf/csams/main/model/CheckQualityReportViewModel.kt +++ b/background/src/main/java/com/gyf/csams/main/model/CheckQualityReportViewModel.kt @@ -3,7 +3,7 @@ package com.gyf.csams.main.model import android.app.Application import androidx.annotation.IntRange import androidx.lifecycle.viewModelScope -import com.gyf.ApplyViewModel +import com.gyf.lib.model.ApplyViewModel import com.gyf.lib.util.randomChinese import kotlinx.coroutines.launch diff --git a/background/src/main/java/com/gyf/csams/main/model/ManagerActViewModel.kt b/background/src/main/java/com/gyf/csams/main/model/ManagerActViewModel.kt index 03d58a6..10c9b96 100644 --- a/background/src/main/java/com/gyf/csams/main/model/ManagerActViewModel.kt +++ b/background/src/main/java/com/gyf/csams/main/model/ManagerActViewModel.kt @@ -2,7 +2,7 @@ package com.gyf.csams.main.model import android.app.Application import androidx.annotation.IntRange -import com.gyf.lib.ScrollListW +import com.gyf.lib.model.ScrollViewModel import com.gyf.lib.util.randomChinese import com.gyf.lib.util.randomDateTime import com.gyf.lib.util.randomNum @@ -20,7 +20,7 @@ data class ActivityVo( * * @param application */ -class ManagerActViewModel(application: Application) : ScrollListW(application) { +class ManagerActViewModel(application: Application) : ScrollViewModel(application) { override val initSize: Int = 10 init { diff --git a/background/src/main/java/com/gyf/csams/main/model/RenameViewModel.kt b/background/src/main/java/com/gyf/csams/main/model/RenameViewModel.kt index c19ce07..4086745 100644 --- a/background/src/main/java/com/gyf/csams/main/model/RenameViewModel.kt +++ b/background/src/main/java/com/gyf/csams/main/model/RenameViewModel.kt @@ -3,7 +3,7 @@ package com.gyf.csams.main.model import android.app.Application import androidx.lifecycle.viewModelScope import com.gyf.csams.R -import com.gyf.lib.ScrollListW +import com.gyf.lib.model.ScrollViewModel import com.gyf.lib.uikit.StringForm import com.gyf.lib.util.randomChinese import com.gyf.lib.util.randomNum @@ -24,7 +24,7 @@ data class RenameVo( val reason: String ) -class RenameViewModel(application: Application) : ScrollListW(application) { +class RenameViewModel(application: Application) : ScrollViewModel(application) { val approverOrigin = StringForm(formDesc = application.getString(R.string.approver_origin), textLength = 30) diff --git a/background/src/main/java/com/gyf/csams/main/ui/AssociationManagementActivity.kt b/background/src/main/java/com/gyf/csams/main/ui/AssociationManagementActivity.kt index 8414a5d..aaa854c 100644 --- a/background/src/main/java/com/gyf/csams/main/ui/AssociationManagementActivity.kt +++ b/background/src/main/java/com/gyf/csams/main/ui/AssociationManagementActivity.kt @@ -20,7 +20,6 @@ import com.gyf.csams.main.model.AssociationLevel import com.gyf.csams.main.model.AssociationManagementViewModel import com.gyf.lib.uikit.Body import com.gyf.lib.uikit.MainBoxFrame -import com.gyf.lib.uikit.ScaffoldModel /** * 社团管理 @@ -36,7 +35,6 @@ class AssociationManagementActivity : ComponentActivity() { val model: AssociationManagementViewModel = viewModel() val data by model.data.observeAsState() val listState = rememberLazyListState() - val scaffoldModel: ScaffoldModel = viewModel() LazyColumn(modifier = Modifier.fillMaxSize(), state = listState) { data?.forEach { it.apply { diff --git a/background/src/main/java/com/gyf/csams/main/ui/MainActivity.kt b/background/src/main/java/com/gyf/csams/main/ui/MainActivity.kt index 3f85014..38cb0ee 100644 --- a/background/src/main/java/com/gyf/csams/main/ui/MainActivity.kt +++ b/background/src/main/java/com/gyf/csams/main/ui/MainActivity.kt @@ -24,6 +24,7 @@ import com.gyf.lib.uikit.* class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + setContent { Body { val model: MainViewModel = viewModel() diff --git a/background/src/main/java/com/gyf/csams/uikit/Table.kt b/background/src/main/java/com/gyf/csams/uikit/Table.kt index d0d3365..384f86a 100644 --- a/background/src/main/java/com/gyf/csams/uikit/Table.kt +++ b/background/src/main/java/com/gyf/csams/uikit/Table.kt @@ -17,7 +17,7 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import androidx.lifecycle.viewmodel.compose.viewModel -import com.gyf.lib.ScrollListW +import com.gyf.lib.model.ScrollViewModel import com.gyf.lib.uikit.Body import com.gyf.lib.uikit.MainColumnFrame @@ -29,7 +29,7 @@ import com.gyf.lib.uikit.MainColumnFrame @ExperimentalComposeApi @Composable fun TestTable( - clazz: Class>, + clazz: Class>, @StringRes title: Int? = null, callback: @Composable (vo: A) -> Unit ) { diff --git a/foreground/src/main/AndroidManifest.xml b/foreground/src/main/AndroidManifest.xml index 1f44dd9..93cd004 100644 --- a/foreground/src/main/AndroidManifest.xml +++ b/foreground/src/main/AndroidManifest.xml @@ -54,58 +54,38 @@ - + android:windowSoftInputMode="stateVisible|adjustResize" /> - - + - - + - + - + - + - + - + - + - + \ No newline at end of file diff --git a/foreground/src/main/java/com/gyf/csams/InitActivity.kt b/foreground/src/main/java/com/gyf/csams/InitActivity.kt index 53a48ef..11f50ad 100644 --- a/foreground/src/main/java/com/gyf/csams/InitActivity.kt +++ b/foreground/src/main/java/com/gyf/csams/InitActivity.kt @@ -1,63 +1,14 @@ package com.gyf.csams -import android.content.Intent -import android.os.Bundle -import androidx.activity.ComponentActivity -import androidx.activity.compose.setContent -import androidx.compose.runtime.getValue -import androidx.compose.runtime.livedata.observeAsState -import androidx.compose.ui.Alignment -import androidx.lifecycle.viewmodel.compose.viewModel +import android.app.Activity import com.gyf.csams.account.ui.AccountActivity import com.gyf.csams.main.ui.MainActivity -import com.gyf.csams.uikit.AnimationText -import com.gyf.lib.uikit.Body -import com.gyf.lib.uikit.MainBoxFrame -import com.orhanobut.logger.Logger -import kotlinx.coroutines.GlobalScope -import kotlinx.coroutines.delay -import kotlinx.coroutines.launch +import com.gyf.lib.uikit.AbstractInitActivity +import com.gyf.lib.util.AccountApi -class InitActivity : ComponentActivity() { - - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - - - setContent { - Body { - MainBoxFrame(background = { /*TODO*/ }, contentAlignment = Alignment.Center) { - val initViewModel: InitViewModel = viewModel() - //检查网络 - val isNetWorkWorking: Boolean? by initViewModel.isNetWorkWorking.observeAsState( - null - ) - Logger.i("初始化") - when (isNetWorkWorking) { - null -> AnimationText(text = "测试服务端运行状态中。。。") - true -> init(initViewModel = initViewModel) - false -> AnimationText(text = "无法连接到服务端,请检查服务端地址${BuildConfig.SERVER_ADDRESS}是否配置正确") - } - } - } - } - - } - - - private fun init(initViewModel: InitViewModel) { - //后台检查token - initViewModel.hasOnlyUserToken(onSuccess = { - startActivity(Intent(this, MainActivity::class.java)) - }, onFail = { - startActivity(Intent(this, AccountActivity::class.java)) - }) - GlobalScope.launch { - delay(1000) - finish() - } - } - -} +class InitActivity : AbstractInitActivity() { + override val main: Class = MainActivity::class.java + override val login: Class = AccountActivity::class.java + override val api: AccountApi = AccountApi.ForegroundToken +} \ No newline at end of file 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 abf8c0b..468c0cf 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 @@ -2,20 +2,20 @@ package com.gyf.csams.account.model import android.app.Application import android.os.Build -import androidx.lifecycle.AndroidViewModel import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.viewModelScope import com.google.gson.reflect.TypeToken -import com.gyf.csams.AccountApi -import com.gyf.csams.Api import com.gyf.csams.R import com.gyf.csams.account.ui.AccountRoute import com.gyf.csams.util.SimpleCallback +import com.gyf.lib.model.AbstractLoginViewModel import com.gyf.lib.uikit.FormStatus -import com.gyf.lib.uikit.StringForm import com.gyf.lib.uikit.ValidStringForm -import com.gyf.lib.util.* +import com.gyf.lib.util.AccountApi +import com.gyf.lib.util.Api +import com.gyf.lib.util.ApiResponse +import com.gyf.lib.util.HttpClient import com.orhanobut.logger.Logger import kotlinx.coroutines.Job import kotlinx.coroutines.launch @@ -55,12 +55,14 @@ data class DialogMessage(val message: String, val userResDto: UserResDto?) /** * 注册表单 */ -class AccountViewModel(application: Application) : AndroidViewModel(application) { +class AccountViewModel(application: Application) : AbstractLoginViewModel(application) { val welcomeEnd = application.getString(R.string.welcome_end) val welcomeStart = application.getString(R.string.welcome_start) + override val api: AccountApi = AccountApi.ForegroundLogin + //学号 - val studentId = object : ValidStringForm(formDesc = "学号", textLength = 8) { + override val id = object : ValidStringForm(formDesc = "学号", textLength = 8) { override fun check() { _formValue.value?.let { when { @@ -80,38 +82,31 @@ class AccountViewModel(application: Application) : AndroidViewModel(application) private var checkJob: Job? = null //姓名 - val name = object : StringForm(formDesc = "姓名", textLength = 4) { - override fun onChange(value: String) { - super.onChange(value) + val name = object : ValidStringForm(formDesc = "姓名", textLength = 4) { + override fun check() { + _statusForm.value = FormStatus.Valid 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) + override val password = object : ValidStringForm(formDesc = "密码", textLength = 8) { + override fun check() { + _formValue.value?.let { + if (it.matches(Regex("\\d{8}"))) _statusForm.value = + FormStatus.Valid else _statusForm.value = FormStatus.FormatError + } checkForm() } } - private val _isValidPwd = MutableLiveData() - val isValidPwd: LiveData = _isValidPwd - val passwordFormat = "八位纯数字" - - //注册按钮 - private val _isValidForm = MutableLiveData() + val passwordFormat = "八位纯数字" - val isValidForm: LiveData = _isValidForm private val _dialogMsg = MutableLiveData() val dialogMsg: LiveData = _dialogMsg - val loginDesc = "登陆" - //返回登陆 val backLogin = "返回$loginDesc" @@ -127,12 +122,6 @@ class AccountViewModel(application: Application) : AndroidViewModel(application) //转到注册 var goRegister = "转到$regBtnDesc" - /** - * 完成登录状态 - */ - private val _finishLogin = MutableLiveData() - val finishLogin: LiveData = _finishLogin - lateinit var route: AccountRoute /** @@ -146,51 +135,44 @@ class AccountViewModel(application: Application) : AndroidViewModel(application) } checkJob = viewModelScope.launch { val url = Api.buildUrl(AccountApi.CheckId) - Logger.i("检测${studentId.formDesc},请求接口$url") + Logger.i("检测${id.formDesc},请求接口$url") HttpClient.get( url, SimpleCallback( - action = "${studentId.formDesc}重复检测", + action = "${id.formDesc}重复检测", onSuccess = { if (it.body == true) { result.postValue(FormStatus.Repeat) } else { result.postValue(FormStatus.Valid) } + checkForm() }, onFail = { Logger.e(it) }, type = object : TypeToken>() {}.type - ), mapOf("studentId" to "${studentId.formValue.value}") + ), mapOf("studentId" to "${id.formValue.value}") ) } } } - /** - * 检测姓名 - * - * @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 + override fun loginParam(): Any { + val studentId = "${id.formValue.value}" + val password = "${password.formValue.value}" + return UserLoginVo( + studentId = studentId, + password = password, + device = "${Build.MANUFACTURER} ${Build.MODEL}" + ) } - private fun checkForm(): Boolean { + override fun checkForm(): Boolean { if (checkJob?.isActive == true) { - _isValidForm.value = false + _isValidForm.postValue(false) } else { - _isValidForm.value = - studentId.statusForm.value == FormStatus.Valid && (if (route == AccountRoute.Register) checkName() else checkPassword()) + _isValidForm.postValue( + id.statusForm.value == FormStatus.Valid && (if (route == AccountRoute.Register) name.statusForm.value == FormStatus.Valid + else password.statusForm.value == FormStatus.Valid) + ) } return _isValidForm.value == true } @@ -218,7 +200,7 @@ class AccountViewModel(application: Application) : AndroidViewModel(application) type = object : TypeToken>() {}.type ), jsonParam = UserVo( - studentId = "${studentId.formValue.value}", + studentId = "${id.formValue.value}", name = "${name.formValue.value}" ) ) @@ -233,52 +215,8 @@ class AccountViewModel(application: Application) : AndroidViewModel(application) } private fun resetForm() { - studentId.onChange("") - name.onChange("") - } - - /** - * 登录 - * - */ - fun login(callback: (message: String) -> Unit) { - if (checkForm()) { - val url = Api.buildUrl(AccountApi.Login) - Logger.i("开始$loginDesc,请求接口:$url") - val studentId = "${studentId.formValue.value}" - val password = "${password.formValue.value}" - this.studentId.formValue - Logger.i("使用学号:$studentId,密码:$password 进行登录") - HttpClient.post( - url, - SimpleCallback( - action = loginDesc, - onSuccess = { - Logger.i(it.message) - callback(it.message) - val context = getApplication().applicationContext - it.body?.let { - val db = AppDatabase.getInstance(context) - viewModelScope.launch { - TokenManager.token = it - db?.tokenDao()?.save(token = it) - }.invokeOnCompletion { - _finishLogin.postValue(true) - } - } - }, - onFail = { callback(it) }, - type = object : TypeToken>() {}.type - ), - jsonParam = UserLoginVo( - studentId = studentId, - password = password, - device = "${Build.MANUFACTURER} ${Build.MODEL}" - ) - ) - } else { - Logger.wtf("表单校验失败,无法$loginDesc!!!") - } + id.clean() + name.clean() } 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 1aa5c80..7babd1e 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 @@ -62,7 +62,7 @@ class AccountActivity : ComponentActivity() { .padding(bottom = 10.dp) ) { - Text(text = accountViewModel.loginDesc) + Text(text = stringResource(id = R.string.login_btn)) } val finishLogin: Boolean? by accountViewModel.finishLogin.observeAsState() @@ -107,7 +107,7 @@ class AccountActivity : ComponentActivity() { .fillMaxWidth() .padding(bottom = 10.dp) ) { - Text(text = accountViewModel.regBtnDesc) + Text(text = stringResource(id = R.string.reg_btn)) } OutlinedButton( @@ -196,9 +196,9 @@ class AccountActivity : ComponentActivity() { Column { - val isValidStudentId by accountViewModel.studentId.statusForm.observeAsState() + val isValidStudentId by accountViewModel.id.statusForm.observeAsState() BaseTextField( - form = accountViewModel.studentId, keyboardOptions = KeyboardOptions.Default.copy( + form = accountViewModel.id, keyboardOptions = KeyboardOptions.Default.copy( keyboardType = KeyboardType.Number, imeAction = ImeAction.Done ), isError = isValidStudentId != FormStatus.Valid @@ -213,13 +213,13 @@ class AccountActivity : ComponentActivity() { ) FormStatus.Repeat -> Text(buildAnnotatedString { - append(accountViewModel.studentId.formDesc) + append(accountViewModel.id.formDesc) withStyle( style = MaterialTheme.typography.body1.toSpanStyle().copy( color = MaterialTheme.colors.error ) ) { - append(accountViewModel.studentId.formValue.value ?: "") + append(accountViewModel.id.formValue.value ?: "") } append(accountViewModel.registered) }) @@ -306,10 +306,10 @@ class AccountActivity : ComponentActivity() { private fun Name(accountViewModel: AccountViewModel = viewModel()) { Column { - val isValidName: Boolean by accountViewModel.isValidName.observeAsState(false) - BaseTextField(form = accountViewModel.name, isError = !isValidName) + val formStatus by accountViewModel.name.statusForm.observeAsState() + BaseTextField(form = accountViewModel.name, isError = formStatus !== FormStatus.Valid) - if (!isValidName) { + if (formStatus == FormStatus.Empty) { Text( text = accountViewModel.nameFormat, color = MaterialTheme.colors.error @@ -326,10 +326,10 @@ class AccountActivity : ComponentActivity() { @Composable private fun Password(accountViewModel: AccountViewModel = viewModel()) { Column { - val isValidPwd: Boolean by accountViewModel.isValidPwd.observeAsState(false) + val formStatus by accountViewModel.password.statusForm.observeAsState() BaseTextField( - form = accountViewModel.password, isError = !isValidPwd, + form = accountViewModel.password, isError = formStatus !== FormStatus.Valid, keyboardOptions = KeyboardOptions.Default.copy( imeAction = ImeAction.Done, keyboardType = KeyboardType.Number, @@ -337,11 +337,13 @@ class AccountActivity : ComponentActivity() { ) - if (!isValidPwd) { - Text( + when (formStatus) { + FormStatus.Empty, FormStatus.FormatError -> Text( text = accountViewModel.passwordFormat, color = MaterialTheme.colors.error ) + else -> { + } } } } diff --git a/foreground/src/main/java/com/gyf/csams/activity/model/ActivityDetailViewModel.kt b/foreground/src/main/java/com/gyf/csams/activity/model/ActivityDetailViewModel.kt index 7f5dc3d..89f3f9a 100644 --- a/foreground/src/main/java/com/gyf/csams/activity/model/ActivityDetailViewModel.kt +++ b/foreground/src/main/java/com/gyf/csams/activity/model/ActivityDetailViewModel.kt @@ -1,15 +1,16 @@ package com.gyf.csams.activity.model +import android.app.Application import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope -import com.gyf.csams.NOT_IMPL_TIP import com.gyf.csams.uikit.AbstractComment import com.gyf.csams.uikit.ActivityDetailMenu import com.gyf.csams.uikit.TopMenuInterface -import com.gyf.lib.ScrollList +import com.gyf.lib.model.ScrollViewModel import com.gyf.lib.uikit.ValidStringForm +import com.gyf.lib.util.NOT_IMPL_TIP import com.gyf.lib.util.randomChinese import com.gyf.lib.util.randomDateTime import com.gyf.lib.util.randomNum @@ -112,7 +113,8 @@ data class ActivityPhotoVo( * 活动相册数据状态管理 * */ -class ActivityPhotoViewModel : ScrollList() { +class ActivityPhotoViewModel(application: Application) : + ScrollViewModel(application) { override val initSize: Int = 10 init { @@ -184,7 +186,8 @@ data class ActivityMembersVo( val participant: MutableList? ) -class ActivityMemberViewModel : ScrollList() { +class ActivityMemberViewModel(application: Application) : + ScrollViewModel(application) { override val initSize: Int = 10 private val _allMember = MutableLiveData() @@ -264,7 +267,7 @@ class BBSCommentModel : AbstractComment() { * 交流区数据状态管理 * */ -class BBSViewModel : ScrollList() { +class BBSViewModel(application: Application) : ScrollViewModel(application) { override val initSize: Int = 10 val title = "发送评论" 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 cc766ad..6139403 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 @@ -19,12 +19,12 @@ import com.baidu.mapapi.search.sug.SuggestionSearch import com.baidu.mapapi.search.sug.SuggestionSearchOption import com.gyf.csams.BuildConfig import com.gyf.csams.MyLocationListener -import com.gyf.csams.NOT_IMPL_TIP import com.gyf.csams.R import com.gyf.lib.uikit.ScaffoldModel import com.gyf.lib.uikit.StringForm import com.gyf.lib.util.ContextUtil import com.gyf.lib.util.DATETIME_FORMAT +import com.gyf.lib.util.NOT_IMPL_TIP import com.orhanobut.logger.Logger import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch diff --git a/foreground/src/main/java/com/gyf/csams/association/model/AssociationViewModel.kt b/foreground/src/main/java/com/gyf/csams/association/model/AssociationViewModel.kt index 105c7a8..68c66b1 100644 --- a/foreground/src/main/java/com/gyf/csams/association/model/AssociationViewModel.kt +++ b/foreground/src/main/java/com/gyf/csams/association/model/AssociationViewModel.kt @@ -1,14 +1,15 @@ package com.gyf.csams.association.model +import android.app.Application import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope -import com.gyf.csams.NOT_IMPL_TIP import com.gyf.csams.uikit.AssociationMenu import com.gyf.csams.uikit.TopMenuInterface -import com.gyf.lib.ScrollList +import com.gyf.lib.model.ScrollViewModel import com.gyf.lib.uikit.StringForm +import com.gyf.lib.util.NOT_IMPL_TIP import com.orhanobut.logger.Logger import kotlinx.coroutines.launch @@ -47,7 +48,7 @@ data class MemberVo(val name: String) * 社团会员 * */ -class MemberViewModel : ScrollList() { +class MemberViewModel(application: Application) : ScrollViewModel(application) { val name = StringForm(formDesc = "姓名关键字", 5) val search = "搜索" @@ -125,7 +126,7 @@ data class HistoryActVo(val name: String) * 历史活动 * */ -class HistoryActViewModel : ScrollList() { +class HistoryActViewModel(application: Application) : ScrollViewModel(application) { override val initSize = 10 init { diff --git a/foreground/src/main/java/com/gyf/csams/association/model/ExamViewModel.kt b/foreground/src/main/java/com/gyf/csams/association/model/ExamViewModel.kt index 65ccd8b..d2d88be 100644 --- a/foreground/src/main/java/com/gyf/csams/association/model/ExamViewModel.kt +++ b/foreground/src/main/java/com/gyf/csams/association/model/ExamViewModel.kt @@ -1,11 +1,12 @@ package com.gyf.csams.association.model +import android.app.Application import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.viewModelScope -import com.gyf.csams.NOT_IMPL_TIP -import com.gyf.lib.ScrollList +import com.gyf.lib.model.ScrollViewModel import com.gyf.lib.uikit.StringForm +import com.gyf.lib.util.NOT_IMPL_TIP import kotlinx.coroutines.launch import kotlin.random.Random @@ -88,7 +89,7 @@ const val ANSWER_TEXT_LENGTH = 15 * */ -class ExamViewModel : ScrollList() { +class ExamViewModel(application: Application) : ScrollViewModel(application) { val questionIsNull: String = "问题不能为空" val deleteLeastOne: String = "至少保留一道题目" val deleteTip = "确定删除此题目?" diff --git a/foreground/src/main/java/com/gyf/csams/association/model/RegAssociationViewModel.kt b/foreground/src/main/java/com/gyf/csams/association/model/RegAssociationViewModel.kt index cfdc89b..63c8ed7 100644 --- a/foreground/src/main/java/com/gyf/csams/association/model/RegAssociationViewModel.kt +++ b/foreground/src/main/java/com/gyf/csams/association/model/RegAssociationViewModel.kt @@ -7,17 +7,11 @@ import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.viewModelScope import com.google.gson.reflect.TypeToken -import com.gyf.csams.Api -import com.gyf.csams.AssociationApi import com.gyf.csams.MainApplication -import com.gyf.csams.UNKNOW_ERROR import com.gyf.csams.util.SimpleCallback import com.gyf.lib.uikit.FormStatus import com.gyf.lib.uikit.ValidStringForm -import com.gyf.lib.util.ApiResponse -import com.gyf.lib.util.HttpClient -import com.gyf.lib.util.Token -import com.gyf.lib.util.TokenManager +import com.gyf.lib.util.* import com.orhanobut.logger.Logger import kotlinx.coroutines.launch import java.io.File diff --git a/foreground/src/main/java/com/gyf/csams/association/model/RenameViewModel.kt b/foreground/src/main/java/com/gyf/csams/association/model/RenameViewModel.kt index 332a7e9..f07b224 100644 --- a/foreground/src/main/java/com/gyf/csams/association/model/RenameViewModel.kt +++ b/foreground/src/main/java/com/gyf/csams/association/model/RenameViewModel.kt @@ -1,8 +1,8 @@ package com.gyf.csams.association.model import androidx.lifecycle.ViewModel -import com.gyf.csams.NOT_IMPL_TIP import com.gyf.lib.uikit.StringForm +import com.gyf.lib.util.NOT_IMPL_TIP /** * 社团重命名状态管理 diff --git a/foreground/src/main/java/com/gyf/csams/main/model/MainViewModel.kt b/foreground/src/main/java/com/gyf/csams/main/model/MainViewModel.kt index 727cc90..2b0676c 100644 --- a/foreground/src/main/java/com/gyf/csams/main/model/MainViewModel.kt +++ b/foreground/src/main/java/com/gyf/csams/main/model/MainViewModel.kt @@ -5,14 +5,13 @@ import android.app.Application import android.content.Intent import androidx.lifecycle.* import com.google.gson.reflect.TypeToken -import com.gyf.NotificationDto -import com.gyf.ReceiverType -import com.gyf.csams.* import com.gyf.csams.account.model.UserVo import com.gyf.csams.account.ui.AccountActivity import com.gyf.csams.uikit.AbstractComment import com.gyf.csams.util.SimpleCallback -import com.gyf.lib.ScrollList +import com.gyf.lib.model.ScrollViewModel +import com.gyf.lib.service.NotificationDto +import com.gyf.lib.service.ReceiverType import com.gyf.lib.uikit.FormStatus import com.gyf.lib.uikit.PersonInfoVo import com.gyf.lib.uikit.StringForm @@ -173,7 +172,7 @@ data class LeaveMessageVo(val message: String, val token: Token) * 社团列表 * */ -class ListViewModel : ScrollList() { +class ListViewModel(application: Application) : ScrollViewModel(application) { val name = StringForm(formDesc = "社团名称", textLength = 5) val desc = StringForm(formDesc = "社团简介", textLength = 10) diff --git a/foreground/src/main/java/com/gyf/csams/main/ui/MainActivity.kt b/foreground/src/main/java/com/gyf/csams/main/ui/MainActivity.kt index 2013f3b..f1b7aad 100644 --- a/foreground/src/main/java/com/gyf/csams/main/ui/MainActivity.kt +++ b/foreground/src/main/java/com/gyf/csams/main/ui/MainActivity.kt @@ -31,7 +31,7 @@ import com.gyf.csams.association.ui.RegAssociationActivity import com.gyf.csams.main.model.* import com.gyf.csams.message.ui.MessageActivity import com.gyf.csams.uikit.* -import com.gyf.lib.MessageService +import com.gyf.lib.service.MessageService import com.gyf.lib.uikit.* import com.gyf.lib.util.randomChinese diff --git a/foreground/src/main/java/com/gyf/csams/message/model/SysMessageViewModel.kt b/foreground/src/main/java/com/gyf/csams/message/model/SysMessageViewModel.kt index ec9c389..3680088 100644 --- a/foreground/src/main/java/com/gyf/csams/message/model/SysMessageViewModel.kt +++ b/foreground/src/main/java/com/gyf/csams/message/model/SysMessageViewModel.kt @@ -1,20 +1,16 @@ package com.gyf.csams.message.model +import android.app.Application import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.viewModelScope import com.google.gson.reflect.TypeToken -import com.gyf.NotificationDto -import com.gyf.PageDto -import com.gyf.ReceiverType -import com.gyf.csams.Api -import com.gyf.csams.NOT_IMPL_TIP -import com.gyf.csams.NotificationApi import com.gyf.csams.util.SimpleCallback -import com.gyf.lib.ScrollList -import com.gyf.lib.util.ApiResponse -import com.gyf.lib.util.HttpClient -import com.gyf.lib.util.TokenManager +import com.gyf.lib.model.ScrollViewModel +import com.gyf.lib.service.NotificationDto +import com.gyf.lib.service.PageDto +import com.gyf.lib.service.ReceiverType +import com.gyf.lib.util.* import com.orhanobut.logger.Logger import kotlinx.coroutines.launch import java.util.* @@ -89,7 +85,7 @@ data class RenameContent( * 系统通知数据状态管理 * */ -class SysMessageViewModel : ScrollList() { +class SysMessageViewModel(application: Application) : ScrollViewModel(application) { val title = "系统通知" override val initSize: Int = 10 diff --git a/foreground/src/main/java/com/gyf/csams/uikit/BaseView.kt b/foreground/src/main/java/com/gyf/csams/uikit/BaseView.kt index 298ec99..51c3582 100644 --- a/foreground/src/main/java/com/gyf/csams/uikit/BaseView.kt +++ b/foreground/src/main/java/com/gyf/csams/uikit/BaseView.kt @@ -3,7 +3,6 @@ package com.gyf.csams.uikit import android.app.Activity import androidx.annotation.DrawableRes import androidx.compose.animation.Crossfade -import androidx.compose.animation.animateColor import androidx.compose.animation.core.* import androidx.compose.foundation.Image import androidx.compose.foundation.background @@ -39,29 +38,6 @@ import com.gyf.csams.main.model.MarqueeViewModel import com.gyf.lib.uikit.* import com.orhanobut.logger.Logger -/** - * 淡入淡出并且颜色变化文本 - * - * @param text - */ -@Composable -fun AnimationText(text: String) { - val infiniteTransition = rememberInfiniteTransition() - val color by infiniteTransition.animateColor( - initialValue = MaterialTheme.colors.primary, - targetValue = MaterialTheme.colors.onPrimary, - animationSpec = infiniteRepeatable( - animation = tween(1000, easing = LinearEasing), - repeatMode = RepeatMode.Reverse - ) - ) - - Text( - text = text, - color = color, - style = MaterialTheme.typography.body1 - ) -} /** * 主菜单 diff --git a/foreground/src/main/java/com/gyf/csams/uikit/ViewModel.kt b/foreground/src/main/java/com/gyf/csams/uikit/ViewModel.kt index 0b7fcb6..23b5e63 100644 --- a/foreground/src/main/java/com/gyf/csams/uikit/ViewModel.kt +++ b/foreground/src/main/java/com/gyf/csams/uikit/ViewModel.kt @@ -7,12 +7,12 @@ import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.viewModelScope import com.google.gson.reflect.TypeToken -import com.gyf.csams.Api -import com.gyf.csams.MainApi import com.gyf.csams.R import com.gyf.csams.util.SimpleCallback +import com.gyf.lib.util.Api import com.gyf.lib.util.HttpClient import com.gyf.lib.util.ImageUtil +import com.gyf.lib.util.MainApi import com.orhanobut.logger.Logger import kotlinx.coroutines.Job import kotlinx.coroutines.delay diff --git a/lib/src/main/java/com/gyf/lib/ScrollList.kt b/lib/src/main/java/com/gyf/lib/ScrollList.kt deleted file mode 100644 index 5cad943..0000000 --- a/lib/src/main/java/com/gyf/lib/ScrollList.kt +++ /dev/null @@ -1,34 +0,0 @@ -package com.gyf.lib - -import android.app.Application -import androidx.lifecycle.AndroidViewModel -import androidx.lifecycle.LiveData -import androidx.lifecycle.MutableLiveData -import androidx.lifecycle.ViewModel - -@Deprecated(message = "", replaceWith = ReplaceWith("")) -abstract class ScrollList : ViewModel() { - protected val _data = MutableLiveData>(mutableListOf()) - val data: LiveData> = _data - - abstract val initSize: Int - - //加载列表 - abstract fun load() - - //加载更多数据 - abstract fun loadMore(callback: (message: String) -> Unit) -} - -abstract class ScrollListW(application: Application) : AndroidViewModel(application) { - protected val _data = MutableLiveData>(mutableListOf()) - val data: LiveData> = _data - - abstract val initSize: Int - - //加载列表 - abstract fun load() - - //加载更多数据 - abstract fun loadMore(callback: (message: String) -> Unit) -} \ No newline at end of file diff --git a/lib/src/main/java/com/gyf/lib/model/AbstractLoginViewModel.kt b/lib/src/main/java/com/gyf/lib/model/AbstractLoginViewModel.kt new file mode 100644 index 0000000..562c07d --- /dev/null +++ b/lib/src/main/java/com/gyf/lib/model/AbstractLoginViewModel.kt @@ -0,0 +1,80 @@ +package com.gyf.lib.model + +import android.app.Application +import androidx.lifecycle.AndroidViewModel +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.viewModelScope +import com.google.gson.reflect.TypeToken +import com.gyf.lib.R +import com.gyf.lib.uikit.ValidStringForm +import com.gyf.lib.util.* +import com.orhanobut.logger.Logger +import kotlinx.coroutines.launch + +abstract class AbstractLoginViewModel(application: Application) : AndroidViewModel(application) { + + protected val loginDesc = application.getString(R.string.login_btn) + + abstract val id: ValidStringForm + abstract val password: ValidStringForm + + + //注册按钮 + protected val _isValidForm = MutableLiveData() + + val isValidForm: LiveData = _isValidForm + + /** + * 完成登录状态 + */ + private val _finishLogin = MutableLiveData() + val finishLogin: LiveData = _finishLogin + + abstract fun checkForm(): Boolean + + abstract fun loginParam(): Any + + abstract val api: AccountApi + + /** + * 登录 + * + */ + fun login(callback: (message: String) -> Unit) { + viewModelScope.launch { + if (checkForm()) { + val url = Api.buildUrl(api) + Logger.i("开始$loginDesc,请求接口:$url") + val id = "${id.formValue.value}" + val password = "${password.formValue.value}" + Logger.i("使用账号:$id,密码:$password 进行登录") + HttpClient.post( + url, + HttpCallback( + action = loginDesc, + onSuccess = { + Logger.i(it.message) + callback(it.message) + val context = getApplication().applicationContext + it.body?.let { + val db = AppDatabase.getInstance(context) + viewModelScope.launch { + TokenManager.token = it + db?.tokenDao()?.save(token = it) + }.invokeOnCompletion { + _finishLogin.postValue(true) + } + } + }, + onFail = { callback(it) }, + type = object : TypeToken>() {}.type + ), + jsonParam = loginParam() + ) + } else { + Logger.wtf("表单校验失败,无法$loginDesc!!!") + } + } + } +} \ No newline at end of file diff --git a/lib/src/main/java/com/gyf/ApplyViewModel.kt b/lib/src/main/java/com/gyf/lib/model/ApplyViewModel.kt similarity index 78% rename from lib/src/main/java/com/gyf/ApplyViewModel.kt rename to lib/src/main/java/com/gyf/lib/model/ApplyViewModel.kt index b8a8b8d..68c138b 100644 --- a/lib/src/main/java/com/gyf/ApplyViewModel.kt +++ b/lib/src/main/java/com/gyf/lib/model/ApplyViewModel.kt @@ -1,11 +1,10 @@ -package com.gyf +package com.gyf.lib.model import android.app.Application import com.gyf.lib.R -import com.gyf.lib.ScrollListW import com.gyf.lib.uikit.StringForm -abstract class ApplyViewModel(application: Application) : ScrollListW(application) { +abstract class ApplyViewModel(application: Application) : ScrollViewModel(application) { val approverOrigin = StringForm(formDesc = application.getString(R.string.approver_origin), textLength = 30) } \ No newline at end of file diff --git a/foreground/src/main/java/com/gyf/csams/InitViewModel.kt b/lib/src/main/java/com/gyf/lib/model/InitViewModel.kt similarity index 90% rename from foreground/src/main/java/com/gyf/csams/InitViewModel.kt rename to lib/src/main/java/com/gyf/lib/model/InitViewModel.kt index 7dd5dd7..5c2d119 100644 --- a/foreground/src/main/java/com/gyf/csams/InitViewModel.kt +++ b/lib/src/main/java/com/gyf/lib/model/InitViewModel.kt @@ -1,4 +1,4 @@ -package com.gyf.csams +package com.gyf.lib.model import android.app.Application import androidx.lifecycle.AndroidViewModel @@ -6,12 +6,10 @@ import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.viewModelScope import com.google.gson.reflect.TypeToken -import com.gyf.csams.util.SimpleCallback import com.gyf.lib.util.* import com.orhanobut.logger.Logger import kotlinx.coroutines.launch - class InitViewModel(application: Application) : AndroidViewModel(application) { /** * 服务器网络状态是否正常,true=正常,false=不正常 @@ -29,7 +27,7 @@ class InitViewModel(application: Application) : AndroidViewModel(application) { viewModelScope.launch { HttpClient.get( Api.buildUrl(TestApi.Test), - SimpleCallback(action = "测试", onSuccess = { + HttpCallback(action = "测试", onSuccess = { _isNetWorkWorking.postValue(true) }, onFail = { Logger.e(it) @@ -40,23 +38,22 @@ class InitViewModel(application: Application) : AndroidViewModel(application) { } - /** * 查询本地是否有且只有一个用户token,如果有则自动登录 */ - fun hasOnlyUserToken(onSuccess: () -> Unit, onFail: () -> Unit) { + fun hasOnlyUserToken(onSuccess: () -> Unit, onFail: () -> Unit, api: AccountApi) { viewModelScope.launch { - val context = getApplication() + val context = getApplication() val db = AppDatabase.getInstance(context) val tokenList = db?.tokenDao()?.queryAll() if (tokenList != null && tokenList.size == 1) { val currentToken: Token = tokenList[0] - val url = Api.buildUrl(AccountApi.LoginToken) + val url = Api.buildUrl(api) val action = "校验token" Logger.i("${action}api=$url") HttpClient.post( url, - SimpleCallback( + HttpCallback( action = action, onSuccess = { it -> it.body?.let { diff --git a/lib/src/main/java/com/gyf/lib/model/ScrollViewModel.kt b/lib/src/main/java/com/gyf/lib/model/ScrollViewModel.kt new file mode 100644 index 0000000..c99f054 --- /dev/null +++ b/lib/src/main/java/com/gyf/lib/model/ScrollViewModel.kt @@ -0,0 +1,19 @@ +package com.gyf.lib.model + +import android.app.Application +import androidx.lifecycle.AndroidViewModel +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData + +abstract class ScrollViewModel(application: Application) : AndroidViewModel(application) { + protected val _data = MutableLiveData>(mutableListOf()) + val data: LiveData> = _data + + abstract val initSize: Int + + //加载列表 + abstract fun load() + + //加载更多数据 + abstract fun loadMore(callback: (message: String) -> Unit) +} \ No newline at end of file diff --git a/lib/src/main/java/com/gyf/lib/MessageService.kt b/lib/src/main/java/com/gyf/lib/service/MessageService.kt similarity index 83% rename from lib/src/main/java/com/gyf/lib/MessageService.kt rename to lib/src/main/java/com/gyf/lib/service/MessageService.kt index 1c383f8..63ff9d5 100644 --- a/lib/src/main/java/com/gyf/lib/MessageService.kt +++ b/lib/src/main/java/com/gyf/lib/service/MessageService.kt @@ -1,4 +1,4 @@ -package com.gyf.lib +package com.gyf.lib.service import android.content.Intent import androidx.core.app.JobIntentService @@ -6,14 +6,8 @@ import androidx.core.app.NotificationCompat import androidx.core.app.NotificationManagerCompat import com.google.gson.Gson import com.google.gson.reflect.TypeToken -import com.gyf.NOTIFICATION_API -import com.gyf.NotificationDto -import com.gyf.NotificationVo -import com.gyf.ReceiverType -import com.gyf.lib.util.ApiResponse -import com.gyf.lib.util.HttpClient -import com.gyf.lib.util.NotificationUtil -import com.gyf.lib.util.TokenManager +import com.gyf.lib.R +import com.gyf.lib.util.* import com.orhanobut.logger.Logger class MessageService : JobIntentService() { @@ -32,7 +26,8 @@ class MessageService : JobIntentService() { override fun onHandleWork(intent: Intent) { TokenManager.token?.let { it -> - HttpClient.postAsync>(url = NOTIFICATION_API, + HttpClient.postAsync>( + url = Api.buildUrl(NotificationApi.Pull), jsonParam = NotificationDto( receiverId = it.id, receiverClient = ReceiverType.Foreground.name, diff --git a/lib/src/main/java/com/gyf/NotificationWorker.kt b/lib/src/main/java/com/gyf/lib/service/NotificationWorker.kt similarity index 93% rename from lib/src/main/java/com/gyf/NotificationWorker.kt rename to lib/src/main/java/com/gyf/lib/service/NotificationWorker.kt index 87079d5..be3a235 100644 --- a/lib/src/main/java/com/gyf/NotificationWorker.kt +++ b/lib/src/main/java/com/gyf/lib/service/NotificationWorker.kt @@ -1,4 +1,4 @@ -package com.gyf +package com.gyf.lib.service import android.content.Context import androidx.work.Data @@ -6,14 +6,10 @@ import androidx.work.Worker import androidx.work.WorkerParameters import com.google.gson.Gson import com.google.gson.reflect.TypeToken -import com.gyf.lib.BuildConfig import com.gyf.lib.util.* - import com.orhanobut.logger.Logger import java.net.SocketTimeoutException -const val NOTIFICATION_API = "${BuildConfig.SERVER_ADDRESS}/api/notification/pull" - data class NotificationVo(val title: String, val content: String, val id: Int) data class PageDto(val currentPage: Long, val pageSize: Int = 10) @@ -44,7 +40,8 @@ class NotificationWorker(context: Context, workerParams: WorkerParameters) : TokenManager.token?.let { return try { Logger.i("开始拉取通知") - val data = HttpClient.postAsync(url = NOTIFICATION_API, + val data = HttpClient.postAsync( + url = Api.buildUrl(NotificationApi.Pull), jsonParam = NotificationDto( receiverId = it.id, receiverClient = inputData.getString("receiverClient") diff --git a/lib/src/main/java/com/gyf/lib/uikit/AbstractInitActivity.kt b/lib/src/main/java/com/gyf/lib/uikit/AbstractInitActivity.kt new file mode 100644 index 0000000..9e67730 --- /dev/null +++ b/lib/src/main/java/com/gyf/lib/uikit/AbstractInitActivity.kt @@ -0,0 +1,66 @@ +package com.gyf.lib.uikit + +import android.app.Activity +import android.content.Intent +import android.os.Bundle +import androidx.activity.ComponentActivity +import androidx.activity.compose.setContent +import androidx.compose.runtime.getValue +import androidx.compose.runtime.livedata.observeAsState +import androidx.compose.ui.Alignment +import androidx.lifecycle.viewmodel.compose.viewModel +import com.gyf.lib.BuildConfig +import com.gyf.lib.model.InitViewModel +import com.gyf.lib.util.AccountApi +import com.orhanobut.logger.Logger +import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch + +abstract class AbstractInitActivity : ComponentActivity() { + + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + + setContent { + Body { + MainBoxFrame(background = { /*TODO*/ }, contentAlignment = Alignment.Center) { + val initViewModel: InitViewModel = viewModel() + //检查网络 + val isNetWorkWorking: Boolean? by initViewModel.isNetWorkWorking.observeAsState( + null + ) + Logger.i("初始化") + when (isNetWorkWorking) { + null -> AnimationText(text = "测试服务端运行状态中。。。") + true -> init(initViewModel = initViewModel) + false -> AnimationText(text = "无法连接到服务端,请检查服务端地址${BuildConfig.SERVER_ADDRESS}是否配置正确") + } + } + } + } + } + + protected abstract val main: Class + + protected abstract val login: Class + + abstract val api: AccountApi + + private fun init(initViewModel: InitViewModel) { + //后台检查token + initViewModel.hasOnlyUserToken(onSuccess = { + startActivity(Intent(this, main)) + }, onFail = { + startActivity(Intent(this, login)) + }, api = api) + GlobalScope.launch { + delay(1000) + finish() + } + } + +} + diff --git a/lib/src/main/java/com/gyf/lib/uikit/AnimationText.kt b/lib/src/main/java/com/gyf/lib/uikit/AnimationText.kt new file mode 100644 index 0000000..42236b4 --- /dev/null +++ b/lib/src/main/java/com/gyf/lib/uikit/AnimationText.kt @@ -0,0 +1,33 @@ +package com.gyf.lib.uikit + +import androidx.compose.animation.animateColor +import androidx.compose.animation.core.* +import androidx.compose.material.MaterialTheme +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue + + +/** + * 淡入淡出并且颜色变化文本 + * + * @param text + */ +@Composable +fun AnimationText(text: String) { + val infiniteTransition = rememberInfiniteTransition() + val color by infiniteTransition.animateColor( + initialValue = MaterialTheme.colors.primary, + targetValue = MaterialTheme.colors.onPrimary, + animationSpec = infiniteRepeatable( + animation = tween(1000, easing = LinearEasing), + repeatMode = RepeatMode.Reverse + ) + ) + + Text( + text = text, + color = color, + style = MaterialTheme.typography.body1 + ) +} \ No newline at end of file diff --git a/foreground/src/main/java/com/gyf/csams/Api.kt b/lib/src/main/java/com/gyf/lib/util/Api.kt similarity index 74% rename from foreground/src/main/java/com/gyf/csams/Api.kt rename to lib/src/main/java/com/gyf/lib/util/Api.kt index 1321671..be2e881 100644 --- a/foreground/src/main/java/com/gyf/csams/Api.kt +++ b/lib/src/main/java/com/gyf/lib/util/Api.kt @@ -1,4 +1,8 @@ -package com.gyf.csams +package com.gyf.lib.util + +import com.gyf.lib.BuildConfig +import com.gyf.lib.service.ReceiverType +import java.util.* interface UrlPath { @@ -23,11 +27,18 @@ enum class AccountApi(val path: String) : UrlPath { //学号检测 CheckId("/register/checkId"), - //登录 - Login("/login"), + //前台登录 + ForegroundLogin("/login/${ReceiverType.Foreground.name.toLowerCase(Locale.ROOT)}"), + + //后台登陆 + BackgroundLogin("/login/${ReceiverType.Background.name.toLowerCase(Locale.ROOT)}"), + + + //前台令牌校验 + ForegroundToken("${ForegroundLogin.path}/token"), - //令牌校验 - LoginToken("/login/token"), + //后台令牌校验 + BackgroundToken("${BackgroundLogin.path}/token"), //登出 Logout("/logout"); @@ -73,7 +84,8 @@ enum class AssociationApi(val path: String) : UrlPath { enum class NotificationApi(val path: String) : UrlPath { Count("/count"), - List("/list"); + List("/list"), + Pull("/pull"); override fun build(): String { return "/api/notification${this.path}" diff --git a/lib/src/main/java/com/gyf/lib/util/ContextUtil.kt b/lib/src/main/java/com/gyf/lib/util/ContextUtil.kt index 9ef2d2a..7e78ec5 100644 --- a/lib/src/main/java/com/gyf/lib/util/ContextUtil.kt +++ b/lib/src/main/java/com/gyf/lib/util/ContextUtil.kt @@ -6,8 +6,8 @@ import android.view.View import android.view.inputmethod.InputMethodManager import androidx.lifecycle.LiveData import androidx.work.* -import com.gyf.NotificationWorker -import com.gyf.ReceiverType +import com.gyf.lib.service.NotificationWorker +import com.gyf.lib.service.ReceiverType import com.orhanobut.logger.Logger import java.util.* diff --git a/lib/src/main/res/values-en/strings.xml b/lib/src/main/res/values-en/strings.xml index c0e336f..45a448e 100644 --- a/lib/src/main/res/values-en/strings.xml +++ b/lib/src/main/res/values-en/strings.xml @@ -21,4 +21,5 @@ 审核理由 抱歉此功能尚未开放 活动质量汇报单 + 登录 \ No newline at end of file diff --git a/lib/src/main/res/values-zh/strings.xml b/lib/src/main/res/values-zh/strings.xml index c0e336f..45a448e 100644 --- a/lib/src/main/res/values-zh/strings.xml +++ b/lib/src/main/res/values-zh/strings.xml @@ -21,4 +21,5 @@ 审核理由 抱歉此功能尚未开放 活动质量汇报单 + 登录 \ No newline at end of file diff --git a/lib/src/main/res/values/strings.xml b/lib/src/main/res/values/strings.xml index c0e336f..45a448e 100644 --- a/lib/src/main/res/values/strings.xml +++ b/lib/src/main/res/values/strings.xml @@ -21,4 +21,5 @@ 审核理由 抱歉此功能尚未开放 活动质量汇报单 + 登录 \ No newline at end of file