前台AndroidManifest.xml 删除部分Activity exported配置

继承登录模块到lib
移动动画文本组件到lib
ScrollList.kt->ScrollViewModel.kt
Api移动到lib
master
pan 4 years ago
parent e7f07a3415
commit f15fd6588e
  1. 7
      background/src/main/AndroidManifest.xml
  2. 14
      background/src/main/java/com/gyf/csams/InitActivity.kt
  3. 32
      background/src/main/java/com/gyf/csams/account/model/LoginViewModel.kt
  4. 38
      background/src/main/java/com/gyf/csams/account/ui/LoginActivity.kt
  5. 7
      background/src/main/java/com/gyf/csams/main/model/AssociationManagementViewModel.kt
  6. 2
      background/src/main/java/com/gyf/csams/main/model/CheckActViewModel.kt
  7. 2
      background/src/main/java/com/gyf/csams/main/model/CheckQualityReportViewModel.kt
  8. 4
      background/src/main/java/com/gyf/csams/main/model/ManagerActViewModel.kt
  9. 4
      background/src/main/java/com/gyf/csams/main/model/RenameViewModel.kt
  10. 2
      background/src/main/java/com/gyf/csams/main/ui/AssociationManagementActivity.kt
  11. 1
      background/src/main/java/com/gyf/csams/main/ui/MainActivity.kt
  12. 4
      background/src/main/java/com/gyf/csams/uikit/Table.kt
  13. 40
      foreground/src/main/AndroidManifest.xml
  14. 63
      foreground/src/main/java/com/gyf/csams/InitActivity.kt
  15. 142
      foreground/src/main/java/com/gyf/csams/account/model/AccountViewModel.kt
  16. 28
      foreground/src/main/java/com/gyf/csams/account/ui/AccountActivity.kt
  17. 13
      foreground/src/main/java/com/gyf/csams/activity/model/ActivityDetailViewModel.kt
  18. 2
      foreground/src/main/java/com/gyf/csams/activity/model/ApplyActViewModel.kt
  19. 9
      foreground/src/main/java/com/gyf/csams/association/model/AssociationViewModel.kt
  20. 7
      foreground/src/main/java/com/gyf/csams/association/model/ExamViewModel.kt
  21. 8
      foreground/src/main/java/com/gyf/csams/association/model/RegAssociationViewModel.kt
  22. 2
      foreground/src/main/java/com/gyf/csams/association/model/RenameViewModel.kt
  23. 9
      foreground/src/main/java/com/gyf/csams/main/model/MainViewModel.kt
  24. 2
      foreground/src/main/java/com/gyf/csams/main/ui/MainActivity.kt
  25. 18
      foreground/src/main/java/com/gyf/csams/message/model/SysMessageViewModel.kt
  26. 24
      foreground/src/main/java/com/gyf/csams/uikit/BaseView.kt
  27. 4
      foreground/src/main/java/com/gyf/csams/uikit/ViewModel.kt
  28. 34
      lib/src/main/java/com/gyf/lib/ScrollList.kt
  29. 80
      lib/src/main/java/com/gyf/lib/model/AbstractLoginViewModel.kt
  30. 5
      lib/src/main/java/com/gyf/lib/model/ApplyViewModel.kt
  31. 15
      lib/src/main/java/com/gyf/lib/model/InitViewModel.kt
  32. 19
      lib/src/main/java/com/gyf/lib/model/ScrollViewModel.kt
  33. 15
      lib/src/main/java/com/gyf/lib/service/MessageService.kt
  34. 9
      lib/src/main/java/com/gyf/lib/service/NotificationWorker.kt
  35. 66
      lib/src/main/java/com/gyf/lib/uikit/AbstractInitActivity.kt
  36. 33
      lib/src/main/java/com/gyf/lib/uikit/AnimationText.kt
  37. 24
      lib/src/main/java/com/gyf/lib/util/Api.kt
  38. 4
      lib/src/main/java/com/gyf/lib/util/ContextUtil.kt
  39. 1
      lib/src/main/res/values-en/strings.xml
  40. 1
      lib/src/main/res/values-zh/strings.xml
  41. 1
      lib/src/main/res/values/strings.xml

@ -2,6 +2,9 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.gyf.csams"> package="com.gyf.csams">
<!--访问网络-->
<uses-permission android:name="android.permission.INTERNET" />
<application <application
android:allowBackup="true" android:allowBackup="true"
android:fullBackupOnly="true" android:fullBackupOnly="true"
@ -12,7 +15,7 @@
android:theme="@style/Theme.CSAMS" android:theme="@style/Theme.CSAMS"
android:name=".MainApplication"> android:name=".MainApplication">
<activity <activity
android:name=".account.ui.LoginActivity" android:name=".InitActivity"
android:exported="true" android:exported="true"
android:label="${background_app_name}" android:label="${background_app_name}"
android:theme="@style/Theme.CSAMS.NoActionBar"> android:theme="@style/Theme.CSAMS.NoActionBar">
@ -22,7 +25,7 @@
<category android:name="android.intent.category.LAUNCHER" /> <category android:name="android.intent.category.LAUNCHER" />
</intent-filter> </intent-filter>
</activity> </activity>
<activity android:name=".account.ui.LoginActivity" />
<activity android:name=".main.ui.MainActivity" /> <activity android:name=".main.ui.MainActivity" />
<activity android:name=".main.ui.DepartmentActivity" /> <activity android:name=".main.ui.DepartmentActivity" />
<activity android:name=".main.ui.ManagementOfficerActivity" /> <activity android:name=".main.ui.ManagementOfficerActivity" />

@ -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<out Activity> = MainActivity::class.java
override val login: Class<out Activity> = LoginActivity::class.java
override val api: AccountApi = AccountApi.BackgroundToken
}

@ -1,11 +1,31 @@
package com.gyf.csams.account.model package com.gyf.csams.account.model
import androidx.lifecycle.ViewModel import android.app.Application
import com.gyf.lib.uikit.StringForm 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() { data class ManagerVo(val account: String, val password: String, val device: String)
val user = StringForm(formDesc = "管理帐号", textLength = 8)
val password = StringForm(formDesc = "管理密码", textLength = 8)
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}"
)
}
} }

@ -10,17 +10,19 @@ import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.height
import androidx.compose.material.OutlinedButton import androidx.compose.material.OutlinedButton
import androidx.compose.material.Text 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.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.input.PasswordVisualTransformation import androidx.compose.ui.text.input.PasswordVisualTransformation
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewmodel.compose.viewModel import androidx.lifecycle.viewmodel.compose.viewModel
import com.gyf.csams.R
import com.gyf.csams.account.model.LoginViewModel import com.gyf.csams.account.model.LoginViewModel
import com.gyf.csams.main.ui.MainActivity import com.gyf.csams.main.ui.MainActivity
import com.gyf.lib.uikit.BaseTextField import com.gyf.lib.uikit.*
import com.gyf.lib.uikit.Body
import com.gyf.lib.uikit.MainBoxFrame
/** /**
* 登录 * 登录
@ -45,16 +47,34 @@ class LoginActivity : ComponentActivity() {
horizontalAlignment = Alignment.CenterHorizontally horizontalAlignment = Alignment.CenterHorizontally
) { ) {
val model: LoginViewModel = viewModel() 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( BaseTextField(
form = model.password, form = model.password,
visualTransformation = PasswordVisualTransformation() visualTransformation = PasswordVisualTransformation()
) )
OutlinedButton(onClick = { OutlinedButton(
context.startActivity(Intent(context, MainActivity::class.java)) onClick = {
context.finish() model.login {
}) { scaffoldModel.update(message = it)
Text(text = model.login) }
},
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()
} }
} }
} }

@ -1,7 +1,8 @@
package com.gyf.csams.main.model package com.gyf.csams.main.model
import android.app.Application
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import com.gyf.lib.ScrollList import com.gyf.lib.model.ScrollViewModel
import com.gyf.lib.util.randomChinese import com.gyf.lib.util.randomChinese
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@ -48,7 +49,9 @@ data class AssociationVo(
* 数据状态管理 * 数据状态管理
* *
*/ */
class AssociationManagementViewModel : ScrollList<AssociationVo>() { class AssociationManagementViewModel(application: Application) : ScrollViewModel<AssociationVo>(
application
) {
override val initSize: Int = 10 override val initSize: Int = 10
init { init {

@ -2,7 +2,7 @@ package com.gyf.csams.main.model
import android.app.Application import android.app.Application
import androidx.lifecycle.viewModelScope 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.format
import com.gyf.lib.util.randomChinese import com.gyf.lib.util.randomChinese
import com.gyf.lib.util.randomDateTime import com.gyf.lib.util.randomDateTime

@ -3,7 +3,7 @@ package com.gyf.csams.main.model
import android.app.Application import android.app.Application
import androidx.annotation.IntRange import androidx.annotation.IntRange
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import com.gyf.ApplyViewModel import com.gyf.lib.model.ApplyViewModel
import com.gyf.lib.util.randomChinese import com.gyf.lib.util.randomChinese
import kotlinx.coroutines.launch import kotlinx.coroutines.launch

@ -2,7 +2,7 @@ package com.gyf.csams.main.model
import android.app.Application import android.app.Application
import androidx.annotation.IntRange 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.randomChinese
import com.gyf.lib.util.randomDateTime import com.gyf.lib.util.randomDateTime
import com.gyf.lib.util.randomNum import com.gyf.lib.util.randomNum
@ -20,7 +20,7 @@ data class ActivityVo(
* *
* @param application * @param application
*/ */
class ManagerActViewModel(application: Application) : ScrollListW<ActivityVo>(application) { class ManagerActViewModel(application: Application) : ScrollViewModel<ActivityVo>(application) {
override val initSize: Int = 10 override val initSize: Int = 10
init { init {

@ -3,7 +3,7 @@ package com.gyf.csams.main.model
import android.app.Application import android.app.Application
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import com.gyf.csams.R 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.uikit.StringForm
import com.gyf.lib.util.randomChinese import com.gyf.lib.util.randomChinese
import com.gyf.lib.util.randomNum import com.gyf.lib.util.randomNum
@ -24,7 +24,7 @@ data class RenameVo(
val reason: String val reason: String
) )
class RenameViewModel(application: Application) : ScrollListW<RenameVo>(application) { class RenameViewModel(application: Application) : ScrollViewModel<RenameVo>(application) {
val approverOrigin = val approverOrigin =
StringForm(formDesc = application.getString(R.string.approver_origin), textLength = 30) StringForm(formDesc = application.getString(R.string.approver_origin), textLength = 30)

@ -20,7 +20,6 @@ import com.gyf.csams.main.model.AssociationLevel
import com.gyf.csams.main.model.AssociationManagementViewModel import com.gyf.csams.main.model.AssociationManagementViewModel
import com.gyf.lib.uikit.Body import com.gyf.lib.uikit.Body
import com.gyf.lib.uikit.MainBoxFrame import com.gyf.lib.uikit.MainBoxFrame
import com.gyf.lib.uikit.ScaffoldModel
/** /**
* 社团管理 * 社团管理
@ -36,7 +35,6 @@ class AssociationManagementActivity : ComponentActivity() {
val model: AssociationManagementViewModel = viewModel() val model: AssociationManagementViewModel = viewModel()
val data by model.data.observeAsState() val data by model.data.observeAsState()
val listState = rememberLazyListState() val listState = rememberLazyListState()
val scaffoldModel: ScaffoldModel = viewModel()
LazyColumn(modifier = Modifier.fillMaxSize(), state = listState) { LazyColumn(modifier = Modifier.fillMaxSize(), state = listState) {
data?.forEach { data?.forEach {
it.apply { it.apply {

@ -24,6 +24,7 @@ import com.gyf.lib.uikit.*
class MainActivity : ComponentActivity() { class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContent { setContent {
Body { Body {
val model: MainViewModel = viewModel() val model: MainViewModel = viewModel()

@ -17,7 +17,7 @@ import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewmodel.compose.viewModel 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.Body
import com.gyf.lib.uikit.MainColumnFrame import com.gyf.lib.uikit.MainColumnFrame
@ -29,7 +29,7 @@ import com.gyf.lib.uikit.MainColumnFrame
@ExperimentalComposeApi @ExperimentalComposeApi
@Composable @Composable
fun <A> TestTable( fun <A> TestTable(
clazz: Class<out ScrollListW<A>>, clazz: Class<out ScrollViewModel<A>>,
@StringRes title: Int? = null, @StringRes title: Int? = null,
callback: @Composable (vo: A) -> Unit callback: @Composable (vo: A) -> Unit
) { ) {

@ -54,58 +54,38 @@
<!--登录界面--> <!--登录界面-->
<activity <activity
android:name=".account.ui.AccountActivity" android:name=".account.ui.AccountActivity"
android:windowSoftInputMode="stateVisible|adjustResize" android:windowSoftInputMode="stateVisible|adjustResize" />
android:exported="true">
</activity>
<!--主界面--> <!--主界面-->
<activity <activity android:name=".main.ui.MainActivity" />
android:name=".main.ui.MainActivity"
android:exported="true">
</activity>
<!--注册社团界面--> <!--注册社团界面-->
<activity android:name=".association.ui.RegAssociationActivity" <activity android:name=".association.ui.RegAssociationActivity" />
android:exported="true">
</activity>
<!--社团主界面--> <!--社团主界面-->
<activity <activity android:name=".association.ui.AssociationActivity" />
android:name=".association.ui.AssociationActivity"
android:exported="true" />
<!--社团重命名主界面--> <!--社团重命名主界面-->
<activity <activity android:name=".association.ui.ReNameActivity" />
android:name=".association.ui.ReNameActivity"
android:exported="true" />
<!--题库界面--> <!--题库界面-->
<activity <activity android:name=".association.ui.ExamActivity" />
android:name=".association.ui.ExamActivity"
android:exported="true" />
<!--活动详情--> <!--活动详情-->
<activity <activity android:name=".activity.ui.ActivityDetailActivity" />
android:name=".activity.ui.ActivityDetailActivity"
android:exported="true" />
<!--申请活动--> <!--申请活动-->
<activity <activity
android:name=".activity.ui.ApplyActActivity" android:name=".activity.ui.ApplyActActivity"
android:exported="true"
android:theme="@style/Theme.CSAMS.NoActionBar" /> android:theme="@style/Theme.CSAMS.NoActionBar" />
<!--通知--> <!--通知-->
<activity <activity android:name=".message.ui.MessageActivity" />
android:name=".message.ui.MessageActivity"
android:exported="true" />
<!--系统通知--> <!--系统通知-->
<activity <activity android:name=".message.ui.SysMessageActivity" />
android:name=".message.ui.SysMessageActivity"
android:exported="true" />
<service android:name="com.gyf.lib.MessageService" /> <service android:name="com.gyf.lib.service.MessageService" />
</application> </application>
</manifest> </manifest>

@ -1,63 +1,14 @@
package com.gyf.csams package com.gyf.csams
import android.content.Intent import android.app.Activity
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.csams.account.ui.AccountActivity import com.gyf.csams.account.ui.AccountActivity
import com.gyf.csams.main.ui.MainActivity import com.gyf.csams.main.ui.MainActivity
import com.gyf.csams.uikit.AnimationText import com.gyf.lib.uikit.AbstractInitActivity
import com.gyf.lib.uikit.Body import com.gyf.lib.util.AccountApi
import com.gyf.lib.uikit.MainBoxFrame
import com.orhanobut.logger.Logger
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
class InitActivity : ComponentActivity() { class InitActivity : AbstractInitActivity() {
override val main: Class<out Activity> = MainActivity::class.java
override val login: Class<out Activity> = AccountActivity::class.java
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()
}
}
override val api: AccountApi = AccountApi.ForegroundToken
} }

@ -2,20 +2,20 @@ package com.gyf.csams.account.model
import android.app.Application import android.app.Application
import android.os.Build import android.os.Build
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import com.google.gson.reflect.TypeToken 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.R
import com.gyf.csams.account.ui.AccountRoute import com.gyf.csams.account.ui.AccountRoute
import com.gyf.csams.util.SimpleCallback import com.gyf.csams.util.SimpleCallback
import com.gyf.lib.model.AbstractLoginViewModel
import com.gyf.lib.uikit.FormStatus import com.gyf.lib.uikit.FormStatus
import com.gyf.lib.uikit.StringForm
import com.gyf.lib.uikit.ValidStringForm 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 com.orhanobut.logger.Logger
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
import kotlinx.coroutines.launch 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 welcomeEnd = application.getString(R.string.welcome_end)
val welcomeStart = application.getString(R.string.welcome_start) 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() { override fun check() {
_formValue.value?.let { _formValue.value?.let {
when { when {
@ -80,38 +82,31 @@ class AccountViewModel(application: Application) : AndroidViewModel(application)
private var checkJob: Job? = null private var checkJob: Job? = null
//姓名 //姓名
val name = object : StringForm(formDesc = "姓名", textLength = 4) { val name = object : ValidStringForm(formDesc = "姓名", textLength = 4) {
override fun onChange(value: String) { override fun check() {
super.onChange(value) _statusForm.value = FormStatus.Valid
checkForm() checkForm()
} }
} }
private val _isValidName = MutableLiveData<Boolean>()
val isValidName: LiveData<Boolean> = _isValidName
val nameFormat = "姓名不能为空" val nameFormat = "姓名不能为空"
//密码 //密码
val password = object : StringForm(formDesc = "密码", textLength = 8) { override val password = object : ValidStringForm(formDesc = "密码", textLength = 8) {
override fun onChange(value: String) { override fun check() {
super.onChange(value) _formValue.value?.let {
if (it.matches(Regex("\\d{8}"))) _statusForm.value =
FormStatus.Valid else _statusForm.value = FormStatus.FormatError
}
checkForm() checkForm()
} }
} }
private val _isValidPwd = MutableLiveData<Boolean>()
val isValidPwd: LiveData<Boolean> = _isValidPwd
val passwordFormat = "八位纯数字"
val passwordFormat = "八位纯数字"
//注册按钮
private val _isValidForm = MutableLiveData<Boolean>()
val isValidForm: LiveData<Boolean> = _isValidForm
private val _dialogMsg = MutableLiveData<DialogMessage?>() private val _dialogMsg = MutableLiveData<DialogMessage?>()
val dialogMsg: LiveData<DialogMessage?> = _dialogMsg val dialogMsg: LiveData<DialogMessage?> = _dialogMsg
val loginDesc = "登陆"
//返回登陆 //返回登陆
val backLogin = "返回$loginDesc" val backLogin = "返回$loginDesc"
@ -127,12 +122,6 @@ class AccountViewModel(application: Application) : AndroidViewModel(application)
//转到注册 //转到注册
var goRegister = "转到$regBtnDesc" var goRegister = "转到$regBtnDesc"
/**
* 完成登录状态
*/
private val _finishLogin = MutableLiveData<Boolean>()
val finishLogin: LiveData<Boolean> = _finishLogin
lateinit var route: AccountRoute lateinit var route: AccountRoute
/** /**
@ -146,51 +135,44 @@ class AccountViewModel(application: Application) : AndroidViewModel(application)
} }
checkJob = viewModelScope.launch { checkJob = viewModelScope.launch {
val url = Api.buildUrl(AccountApi.CheckId) val url = Api.buildUrl(AccountApi.CheckId)
Logger.i("检测${studentId.formDesc},请求接口$url") Logger.i("检测${id.formDesc},请求接口$url")
HttpClient.get( HttpClient.get(
url, SimpleCallback<Boolean>( url, SimpleCallback<Boolean>(
action = "${studentId.formDesc}重复检测", action = "${id.formDesc}重复检测",
onSuccess = { onSuccess = {
if (it.body == true) { if (it.body == true) {
result.postValue(FormStatus.Repeat) result.postValue(FormStatus.Repeat)
} else { } else {
result.postValue(FormStatus.Valid) result.postValue(FormStatus.Valid)
} }
checkForm()
}, },
onFail = { Logger.e(it) }, onFail = { Logger.e(it) },
type = object : TypeToken<ApiResponse<Boolean>>() {}.type type = object : TypeToken<ApiResponse<Boolean>>() {}.type
), mapOf("studentId" to "${studentId.formValue.value}") ), mapOf("studentId" to "${id.formValue.value}")
) )
} }
} }
} }
/** override fun loginParam(): Any {
* 检测姓名 val studentId = "${id.formValue.value}"
* val password = "${password.formValue.value}"
* @return return UserLoginVo(
*/ studentId = studentId,
private fun checkName(): Boolean { password = password,
_isValidName.value = name.formValue.value?.isNotEmpty() device = "${Build.MANUFACTURER} ${Build.MODEL}"
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 { override fun checkForm(): Boolean {
if (checkJob?.isActive == true) { if (checkJob?.isActive == true) {
_isValidForm.value = false _isValidForm.postValue(false)
} else { } else {
_isValidForm.value = _isValidForm.postValue(
studentId.statusForm.value == FormStatus.Valid && (if (route == AccountRoute.Register) checkName() else checkPassword()) id.statusForm.value == FormStatus.Valid && (if (route == AccountRoute.Register) name.statusForm.value == FormStatus.Valid
else password.statusForm.value == FormStatus.Valid)
)
} }
return _isValidForm.value == true return _isValidForm.value == true
} }
@ -218,7 +200,7 @@ class AccountViewModel(application: Application) : AndroidViewModel(application)
type = object : TypeToken<ApiResponse<UserResDto>>() {}.type type = object : TypeToken<ApiResponse<UserResDto>>() {}.type
), ),
jsonParam = UserVo( jsonParam = UserVo(
studentId = "${studentId.formValue.value}", studentId = "${id.formValue.value}",
name = "${name.formValue.value}" name = "${name.formValue.value}"
) )
) )
@ -233,52 +215,8 @@ class AccountViewModel(application: Application) : AndroidViewModel(application)
} }
private fun resetForm() { private fun resetForm() {
studentId.onChange("") id.clean()
name.onChange("") name.clean()
}
/**
* 登录
*
*/
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<Token>(
action = loginDesc,
onSuccess = {
Logger.i(it.message)
callback(it.message)
val context = getApplication<Application>().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<ApiResponse<Token>>() {}.type
),
jsonParam = UserLoginVo(
studentId = studentId,
password = password,
device = "${Build.MANUFACTURER} ${Build.MODEL}"
)
)
} else {
Logger.wtf("表单校验失败,无法$loginDesc!!!")
}
} }

@ -62,7 +62,7 @@ class AccountActivity : ComponentActivity() {
.padding(bottom = 10.dp) .padding(bottom = 10.dp)
) { ) {
Text(text = accountViewModel.loginDesc) Text(text = stringResource(id = R.string.login_btn))
} }
val finishLogin: Boolean? by accountViewModel.finishLogin.observeAsState() val finishLogin: Boolean? by accountViewModel.finishLogin.observeAsState()
@ -107,7 +107,7 @@ class AccountActivity : ComponentActivity() {
.fillMaxWidth() .fillMaxWidth()
.padding(bottom = 10.dp) .padding(bottom = 10.dp)
) { ) {
Text(text = accountViewModel.regBtnDesc) Text(text = stringResource(id = R.string.reg_btn))
} }
OutlinedButton( OutlinedButton(
@ -196,9 +196,9 @@ class AccountActivity : ComponentActivity() {
Column { Column {
val isValidStudentId by accountViewModel.studentId.statusForm.observeAsState() val isValidStudentId by accountViewModel.id.statusForm.observeAsState()
BaseTextField( BaseTextField(
form = accountViewModel.studentId, keyboardOptions = KeyboardOptions.Default.copy( form = accountViewModel.id, keyboardOptions = KeyboardOptions.Default.copy(
keyboardType = KeyboardType.Number, keyboardType = KeyboardType.Number,
imeAction = ImeAction.Done imeAction = ImeAction.Done
), isError = isValidStudentId != FormStatus.Valid ), isError = isValidStudentId != FormStatus.Valid
@ -213,13 +213,13 @@ class AccountActivity : ComponentActivity() {
) )
FormStatus.Repeat -> FormStatus.Repeat ->
Text(buildAnnotatedString { Text(buildAnnotatedString {
append(accountViewModel.studentId.formDesc) append(accountViewModel.id.formDesc)
withStyle( withStyle(
style = MaterialTheme.typography.body1.toSpanStyle().copy( style = MaterialTheme.typography.body1.toSpanStyle().copy(
color = MaterialTheme.colors.error color = MaterialTheme.colors.error
) )
) { ) {
append(accountViewModel.studentId.formValue.value ?: "") append(accountViewModel.id.formValue.value ?: "")
} }
append(accountViewModel.registered) append(accountViewModel.registered)
}) })
@ -306,10 +306,10 @@ class AccountActivity : ComponentActivity() {
private fun Name(accountViewModel: AccountViewModel = viewModel()) { private fun Name(accountViewModel: AccountViewModel = viewModel()) {
Column { Column {
val isValidName: Boolean by accountViewModel.isValidName.observeAsState(false) val formStatus by accountViewModel.name.statusForm.observeAsState()
BaseTextField(form = accountViewModel.name, isError = !isValidName) BaseTextField(form = accountViewModel.name, isError = formStatus !== FormStatus.Valid)
if (!isValidName) { if (formStatus == FormStatus.Empty) {
Text( Text(
text = accountViewModel.nameFormat, text = accountViewModel.nameFormat,
color = MaterialTheme.colors.error color = MaterialTheme.colors.error
@ -326,10 +326,10 @@ class AccountActivity : ComponentActivity() {
@Composable @Composable
private fun Password(accountViewModel: AccountViewModel = viewModel()) { private fun Password(accountViewModel: AccountViewModel = viewModel()) {
Column { Column {
val isValidPwd: Boolean by accountViewModel.isValidPwd.observeAsState(false) val formStatus by accountViewModel.password.statusForm.observeAsState()
BaseTextField( BaseTextField(
form = accountViewModel.password, isError = !isValidPwd, form = accountViewModel.password, isError = formStatus !== FormStatus.Valid,
keyboardOptions = KeyboardOptions.Default.copy( keyboardOptions = KeyboardOptions.Default.copy(
imeAction = ImeAction.Done, imeAction = ImeAction.Done,
keyboardType = KeyboardType.Number, keyboardType = KeyboardType.Number,
@ -337,11 +337,13 @@ class AccountActivity : ComponentActivity() {
) )
if (!isValidPwd) { when (formStatus) {
Text( FormStatus.Empty, FormStatus.FormatError -> Text(
text = accountViewModel.passwordFormat, text = accountViewModel.passwordFormat,
color = MaterialTheme.colors.error color = MaterialTheme.colors.error
) )
else -> {
}
} }
} }
} }

@ -1,15 +1,16 @@
package com.gyf.csams.activity.model package com.gyf.csams.activity.model
import android.app.Application
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import com.gyf.csams.NOT_IMPL_TIP
import com.gyf.csams.uikit.AbstractComment import com.gyf.csams.uikit.AbstractComment
import com.gyf.csams.uikit.ActivityDetailMenu import com.gyf.csams.uikit.ActivityDetailMenu
import com.gyf.csams.uikit.TopMenuInterface 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.uikit.ValidStringForm
import com.gyf.lib.util.NOT_IMPL_TIP
import com.gyf.lib.util.randomChinese import com.gyf.lib.util.randomChinese
import com.gyf.lib.util.randomDateTime import com.gyf.lib.util.randomDateTime
import com.gyf.lib.util.randomNum import com.gyf.lib.util.randomNum
@ -112,7 +113,8 @@ data class ActivityPhotoVo(
* 活动相册数据状态管理 * 活动相册数据状态管理
* *
*/ */
class ActivityPhotoViewModel : ScrollList<ActivityPhotoVo>() { class ActivityPhotoViewModel(application: Application) :
ScrollViewModel<ActivityPhotoVo>(application) {
override val initSize: Int = 10 override val initSize: Int = 10
init { init {
@ -184,7 +186,8 @@ data class ActivityMembersVo(
val participant: MutableList<ActivityMemberVo>? val participant: MutableList<ActivityMemberVo>?
) )
class ActivityMemberViewModel : ScrollList<ActivityMemberVo>() { class ActivityMemberViewModel(application: Application) :
ScrollViewModel<ActivityMemberVo>(application) {
override val initSize: Int = 10 override val initSize: Int = 10
private val _allMember = MutableLiveData<ActivityMembersVo>() private val _allMember = MutableLiveData<ActivityMembersVo>()
@ -264,7 +267,7 @@ class BBSCommentModel : AbstractComment() {
* 交流区数据状态管理 * 交流区数据状态管理
* *
*/ */
class BBSViewModel : ScrollList<BBSVo>() { class BBSViewModel(application: Application) : ScrollViewModel<BBSVo>(application) {
override val initSize: Int = 10 override val initSize: Int = 10
val title = "发送评论" val title = "发送评论"

@ -19,12 +19,12 @@ import com.baidu.mapapi.search.sug.SuggestionSearch
import com.baidu.mapapi.search.sug.SuggestionSearchOption import com.baidu.mapapi.search.sug.SuggestionSearchOption
import com.gyf.csams.BuildConfig import com.gyf.csams.BuildConfig
import com.gyf.csams.MyLocationListener import com.gyf.csams.MyLocationListener
import com.gyf.csams.NOT_IMPL_TIP
import com.gyf.csams.R import com.gyf.csams.R
import com.gyf.lib.uikit.ScaffoldModel import com.gyf.lib.uikit.ScaffoldModel
import com.gyf.lib.uikit.StringForm import com.gyf.lib.uikit.StringForm
import com.gyf.lib.util.ContextUtil import com.gyf.lib.util.ContextUtil
import com.gyf.lib.util.DATETIME_FORMAT import com.gyf.lib.util.DATETIME_FORMAT
import com.gyf.lib.util.NOT_IMPL_TIP
import com.orhanobut.logger.Logger import com.orhanobut.logger.Logger
import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch import kotlinx.coroutines.launch

@ -1,14 +1,15 @@
package com.gyf.csams.association.model package com.gyf.csams.association.model
import android.app.Application
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import com.gyf.csams.NOT_IMPL_TIP
import com.gyf.csams.uikit.AssociationMenu import com.gyf.csams.uikit.AssociationMenu
import com.gyf.csams.uikit.TopMenuInterface 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.uikit.StringForm
import com.gyf.lib.util.NOT_IMPL_TIP
import com.orhanobut.logger.Logger import com.orhanobut.logger.Logger
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@ -47,7 +48,7 @@ data class MemberVo(val name: String)
* 社团会员 * 社团会员
* *
*/ */
class MemberViewModel : ScrollList<MemberVo>() { class MemberViewModel(application: Application) : ScrollViewModel<MemberVo>(application) {
val name = StringForm(formDesc = "姓名关键字", 5) val name = StringForm(formDesc = "姓名关键字", 5)
val search = "搜索" val search = "搜索"
@ -125,7 +126,7 @@ data class HistoryActVo(val name: String)
* 历史活动 * 历史活动
* *
*/ */
class HistoryActViewModel : ScrollList<HistoryActVo>() { class HistoryActViewModel(application: Application) : ScrollViewModel<HistoryActVo>(application) {
override val initSize = 10 override val initSize = 10
init { init {

@ -1,11 +1,12 @@
package com.gyf.csams.association.model package com.gyf.csams.association.model
import android.app.Application
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import com.gyf.csams.NOT_IMPL_TIP import com.gyf.lib.model.ScrollViewModel
import com.gyf.lib.ScrollList
import com.gyf.lib.uikit.StringForm import com.gyf.lib.uikit.StringForm
import com.gyf.lib.util.NOT_IMPL_TIP
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlin.random.Random import kotlin.random.Random
@ -88,7 +89,7 @@ const val ANSWER_TEXT_LENGTH = 15
* *
*/ */
class ExamViewModel : ScrollList<Exam>() { class ExamViewModel(application: Application) : ScrollViewModel<Exam>(application) {
val questionIsNull: String = "问题不能为空" val questionIsNull: String = "问题不能为空"
val deleteLeastOne: String = "至少保留一道题目" val deleteLeastOne: String = "至少保留一道题目"
val deleteTip = "确定删除此题目?" val deleteTip = "确定删除此题目?"

@ -7,17 +7,11 @@ import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import com.google.gson.reflect.TypeToken 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.MainApplication
import com.gyf.csams.UNKNOW_ERROR
import com.gyf.csams.util.SimpleCallback import com.gyf.csams.util.SimpleCallback
import com.gyf.lib.uikit.FormStatus import com.gyf.lib.uikit.FormStatus
import com.gyf.lib.uikit.ValidStringForm import com.gyf.lib.uikit.ValidStringForm
import com.gyf.lib.util.ApiResponse import com.gyf.lib.util.*
import com.gyf.lib.util.HttpClient
import com.gyf.lib.util.Token
import com.gyf.lib.util.TokenManager
import com.orhanobut.logger.Logger import com.orhanobut.logger.Logger
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import java.io.File import java.io.File

@ -1,8 +1,8 @@
package com.gyf.csams.association.model package com.gyf.csams.association.model
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import com.gyf.csams.NOT_IMPL_TIP
import com.gyf.lib.uikit.StringForm import com.gyf.lib.uikit.StringForm
import com.gyf.lib.util.NOT_IMPL_TIP
/** /**
* 社团重命名状态管理 * 社团重命名状态管理

@ -5,14 +5,13 @@ import android.app.Application
import android.content.Intent import android.content.Intent
import androidx.lifecycle.* import androidx.lifecycle.*
import com.google.gson.reflect.TypeToken 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.model.UserVo
import com.gyf.csams.account.ui.AccountActivity import com.gyf.csams.account.ui.AccountActivity
import com.gyf.csams.uikit.AbstractComment import com.gyf.csams.uikit.AbstractComment
import com.gyf.csams.util.SimpleCallback 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.FormStatus
import com.gyf.lib.uikit.PersonInfoVo import com.gyf.lib.uikit.PersonInfoVo
import com.gyf.lib.uikit.StringForm import com.gyf.lib.uikit.StringForm
@ -173,7 +172,7 @@ data class LeaveMessageVo(val message: String, val token: Token)
* 社团列表 * 社团列表
* *
*/ */
class ListViewModel : ScrollList<AssociationListVo>() { class ListViewModel(application: Application) : ScrollViewModel<AssociationListVo>(application) {
val name = StringForm(formDesc = "社团名称", textLength = 5) val name = StringForm(formDesc = "社团名称", textLength = 5)
val desc = StringForm(formDesc = "社团简介", textLength = 10) val desc = StringForm(formDesc = "社团简介", textLength = 10)

@ -31,7 +31,7 @@ import com.gyf.csams.association.ui.RegAssociationActivity
import com.gyf.csams.main.model.* import com.gyf.csams.main.model.*
import com.gyf.csams.message.ui.MessageActivity import com.gyf.csams.message.ui.MessageActivity
import com.gyf.csams.uikit.* 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.uikit.*
import com.gyf.lib.util.randomChinese import com.gyf.lib.util.randomChinese

@ -1,20 +1,16 @@
package com.gyf.csams.message.model package com.gyf.csams.message.model
import android.app.Application
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import com.google.gson.reflect.TypeToken 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.csams.util.SimpleCallback
import com.gyf.lib.ScrollList import com.gyf.lib.model.ScrollViewModel
import com.gyf.lib.util.ApiResponse import com.gyf.lib.service.NotificationDto
import com.gyf.lib.util.HttpClient import com.gyf.lib.service.PageDto
import com.gyf.lib.util.TokenManager import com.gyf.lib.service.ReceiverType
import com.gyf.lib.util.*
import com.orhanobut.logger.Logger import com.orhanobut.logger.Logger
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import java.util.* import java.util.*
@ -89,7 +85,7 @@ data class RenameContent(
* 系统通知数据状态管理 * 系统通知数据状态管理
* *
*/ */
class SysMessageViewModel : ScrollList<NotificationVo>() { class SysMessageViewModel(application: Application) : ScrollViewModel<NotificationVo>(application) {
val title = "系统通知" val title = "系统通知"
override val initSize: Int = 10 override val initSize: Int = 10

@ -3,7 +3,6 @@ package com.gyf.csams.uikit
import android.app.Activity import android.app.Activity
import androidx.annotation.DrawableRes import androidx.annotation.DrawableRes
import androidx.compose.animation.Crossfade import androidx.compose.animation.Crossfade
import androidx.compose.animation.animateColor
import androidx.compose.animation.core.* import androidx.compose.animation.core.*
import androidx.compose.foundation.Image import androidx.compose.foundation.Image
import androidx.compose.foundation.background import androidx.compose.foundation.background
@ -39,29 +38,6 @@ import com.gyf.csams.main.model.MarqueeViewModel
import com.gyf.lib.uikit.* import com.gyf.lib.uikit.*
import com.orhanobut.logger.Logger 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
)
}
/** /**
* 主菜单 * 主菜单

@ -7,12 +7,12 @@ import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import com.google.gson.reflect.TypeToken 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.R
import com.gyf.csams.util.SimpleCallback import com.gyf.csams.util.SimpleCallback
import com.gyf.lib.util.Api
import com.gyf.lib.util.HttpClient import com.gyf.lib.util.HttpClient
import com.gyf.lib.util.ImageUtil import com.gyf.lib.util.ImageUtil
import com.gyf.lib.util.MainApi
import com.orhanobut.logger.Logger import com.orhanobut.logger.Logger
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
import kotlinx.coroutines.delay import kotlinx.coroutines.delay

@ -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<T> : ViewModel() {
protected val _data = MutableLiveData<MutableList<T>>(mutableListOf())
val data: LiveData<MutableList<T>> = _data
abstract val initSize: Int
//加载列表
abstract fun load()
//加载更多数据
abstract fun loadMore(callback: (message: String) -> Unit)
}
abstract class ScrollListW<T>(application: Application) : AndroidViewModel(application) {
protected val _data = MutableLiveData<MutableList<T>>(mutableListOf())
val data: LiveData<MutableList<T>> = _data
abstract val initSize: Int
//加载列表
abstract fun load()
//加载更多数据
abstract fun loadMore(callback: (message: String) -> Unit)
}

@ -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<Boolean>()
val isValidForm: LiveData<Boolean> = _isValidForm
/**
* 完成登录状态
*/
private val _finishLogin = MutableLiveData<Boolean>()
val finishLogin: LiveData<Boolean> = _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<Token>(
action = loginDesc,
onSuccess = {
Logger.i(it.message)
callback(it.message)
val context = getApplication<Application>().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<ApiResponse<Token>>() {}.type
),
jsonParam = loginParam()
)
} else {
Logger.wtf("表单校验失败,无法$loginDesc!!!")
}
}
}
}

@ -1,11 +1,10 @@
package com.gyf package com.gyf.lib.model
import android.app.Application import android.app.Application
import com.gyf.lib.R import com.gyf.lib.R
import com.gyf.lib.ScrollListW
import com.gyf.lib.uikit.StringForm import com.gyf.lib.uikit.StringForm
abstract class ApplyViewModel<T>(application: Application) : ScrollListW<T>(application) { abstract class ApplyViewModel<T>(application: Application) : ScrollViewModel<T>(application) {
val approverOrigin = val approverOrigin =
StringForm(formDesc = application.getString(R.string.approver_origin), textLength = 30) StringForm(formDesc = application.getString(R.string.approver_origin), textLength = 30)
} }

@ -1,4 +1,4 @@
package com.gyf.csams package com.gyf.lib.model
import android.app.Application import android.app.Application
import androidx.lifecycle.AndroidViewModel import androidx.lifecycle.AndroidViewModel
@ -6,12 +6,10 @@ import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import com.google.gson.reflect.TypeToken import com.google.gson.reflect.TypeToken
import com.gyf.csams.util.SimpleCallback
import com.gyf.lib.util.* import com.gyf.lib.util.*
import com.orhanobut.logger.Logger import com.orhanobut.logger.Logger
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
class InitViewModel(application: Application) : AndroidViewModel(application) { class InitViewModel(application: Application) : AndroidViewModel(application) {
/** /**
* 服务器网络状态是否正常true=正常false=不正常 * 服务器网络状态是否正常true=正常false=不正常
@ -29,7 +27,7 @@ class InitViewModel(application: Application) : AndroidViewModel(application) {
viewModelScope.launch { viewModelScope.launch {
HttpClient.get( HttpClient.get(
Api.buildUrl(TestApi.Test), Api.buildUrl(TestApi.Test),
SimpleCallback<Boolean>(action = "测试", onSuccess = { HttpCallback<Boolean>(action = "测试", onSuccess = {
_isNetWorkWorking.postValue(true) _isNetWorkWorking.postValue(true)
}, onFail = { }, onFail = {
Logger.e(it) Logger.e(it)
@ -40,23 +38,22 @@ class InitViewModel(application: Application) : AndroidViewModel(application) {
} }
/** /**
* 查询本地是否有且只有一个用户token如果有则自动登录 * 查询本地是否有且只有一个用户token如果有则自动登录
*/ */
fun hasOnlyUserToken(onSuccess: () -> Unit, onFail: () -> Unit) { fun hasOnlyUserToken(onSuccess: () -> Unit, onFail: () -> Unit, api: AccountApi) {
viewModelScope.launch { viewModelScope.launch {
val context = getApplication<MainApplication>() val context = getApplication<Application>()
val db = AppDatabase.getInstance(context) val db = AppDatabase.getInstance(context)
val tokenList = db?.tokenDao()?.queryAll() val tokenList = db?.tokenDao()?.queryAll()
if (tokenList != null && tokenList.size == 1) { if (tokenList != null && tokenList.size == 1) {
val currentToken: Token = tokenList[0] val currentToken: Token = tokenList[0]
val url = Api.buildUrl(AccountApi.LoginToken) val url = Api.buildUrl(api)
val action = "校验token" val action = "校验token"
Logger.i("${action}api=$url") Logger.i("${action}api=$url")
HttpClient.post( HttpClient.post(
url, url,
SimpleCallback<Boolean>( HttpCallback<Boolean>(
action = action, action = action,
onSuccess = { it -> onSuccess = { it ->
it.body?.let { it.body?.let {

@ -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<T>(application: Application) : AndroidViewModel(application) {
protected val _data = MutableLiveData<MutableList<T>>(mutableListOf())
val data: LiveData<MutableList<T>> = _data
abstract val initSize: Int
//加载列表
abstract fun load()
//加载更多数据
abstract fun loadMore(callback: (message: String) -> Unit)
}

@ -1,4 +1,4 @@
package com.gyf.lib package com.gyf.lib.service
import android.content.Intent import android.content.Intent
import androidx.core.app.JobIntentService import androidx.core.app.JobIntentService
@ -6,14 +6,8 @@ import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat import androidx.core.app.NotificationManagerCompat
import com.google.gson.Gson import com.google.gson.Gson
import com.google.gson.reflect.TypeToken import com.google.gson.reflect.TypeToken
import com.gyf.NOTIFICATION_API import com.gyf.lib.R
import com.gyf.NotificationDto import com.gyf.lib.util.*
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.orhanobut.logger.Logger import com.orhanobut.logger.Logger
class MessageService : JobIntentService() { class MessageService : JobIntentService() {
@ -32,7 +26,8 @@ class MessageService : JobIntentService() {
override fun onHandleWork(intent: Intent) { override fun onHandleWork(intent: Intent) {
TokenManager.token?.let { it -> TokenManager.token?.let { it ->
HttpClient.postAsync<List<NotificationVo>>(url = NOTIFICATION_API, HttpClient.postAsync<List<NotificationVo>>(
url = Api.buildUrl(NotificationApi.Pull),
jsonParam = NotificationDto( jsonParam = NotificationDto(
receiverId = it.id, receiverId = it.id,
receiverClient = ReceiverType.Foreground.name, receiverClient = ReceiverType.Foreground.name,

@ -1,4 +1,4 @@
package com.gyf package com.gyf.lib.service
import android.content.Context import android.content.Context
import androidx.work.Data import androidx.work.Data
@ -6,14 +6,10 @@ import androidx.work.Worker
import androidx.work.WorkerParameters import androidx.work.WorkerParameters
import com.google.gson.Gson import com.google.gson.Gson
import com.google.gson.reflect.TypeToken import com.google.gson.reflect.TypeToken
import com.gyf.lib.BuildConfig
import com.gyf.lib.util.* import com.gyf.lib.util.*
import com.orhanobut.logger.Logger import com.orhanobut.logger.Logger
import java.net.SocketTimeoutException 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 NotificationVo(val title: String, val content: String, val id: Int)
data class PageDto(val currentPage: Long, val pageSize: Int = 10) data class PageDto(val currentPage: Long, val pageSize: Int = 10)
@ -44,7 +40,8 @@ class NotificationWorker(context: Context, workerParams: WorkerParameters) :
TokenManager.token?.let { TokenManager.token?.let {
return try { return try {
Logger.i("开始拉取通知") Logger.i("开始拉取通知")
val data = HttpClient.postAsync<NotificationVo>(url = NOTIFICATION_API, val data = HttpClient.postAsync<NotificationVo>(
url = Api.buildUrl(NotificationApi.Pull),
jsonParam = NotificationDto( jsonParam = NotificationDto(
receiverId = it.id, receiverId = it.id,
receiverClient = inputData.getString("receiverClient") receiverClient = inputData.getString("receiverClient")

@ -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<out Activity>
protected abstract val login: Class<out Activity>
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()
}
}
}

@ -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
)
}

@ -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 { interface UrlPath {
@ -23,11 +27,18 @@ enum class AccountApi(val path: String) : UrlPath {
//学号检测 //学号检测
CheckId("/register/checkId"), 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"); Logout("/logout");
@ -73,7 +84,8 @@ enum class AssociationApi(val path: String) : UrlPath {
enum class NotificationApi(val path: String) : UrlPath { enum class NotificationApi(val path: String) : UrlPath {
Count("/count"), Count("/count"),
List("/list"); List("/list"),
Pull("/pull");
override fun build(): String { override fun build(): String {
return "/api/notification${this.path}" return "/api/notification${this.path}"

@ -6,8 +6,8 @@ import android.view.View
import android.view.inputmethod.InputMethodManager import android.view.inputmethod.InputMethodManager
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import androidx.work.* import androidx.work.*
import com.gyf.NotificationWorker import com.gyf.lib.service.NotificationWorker
import com.gyf.ReceiverType import com.gyf.lib.service.ReceiverType
import com.orhanobut.logger.Logger import com.orhanobut.logger.Logger
import java.util.* import java.util.*

@ -21,4 +21,5 @@
<string name="approver_origin">审核理由</string> <string name="approver_origin">审核理由</string>
<string name="not_impl_error">抱歉此功能尚未开放</string> <string name="not_impl_error">抱歉此功能尚未开放</string>
<string name="quality_report_title">活动质量汇报单</string> <string name="quality_report_title">活动质量汇报单</string>
<string name="login_btn">登录</string>
</resources> </resources>

@ -21,4 +21,5 @@
<string name="approver_origin">审核理由</string> <string name="approver_origin">审核理由</string>
<string name="not_impl_error">抱歉此功能尚未开放</string> <string name="not_impl_error">抱歉此功能尚未开放</string>
<string name="quality_report_title">活动质量汇报单</string> <string name="quality_report_title">活动质量汇报单</string>
<string name="login_btn">登录</string>
</resources> </resources>

@ -21,4 +21,5 @@
<string name="approver_origin">审核理由</string> <string name="approver_origin">审核理由</string>
<string name="not_impl_error">抱歉此功能尚未开放</string> <string name="not_impl_error">抱歉此功能尚未开放</string>
<string name="quality_report_title">活动质量汇报单</string> <string name="quality_report_title">活动质量汇报单</string>
<string name="login_btn">登录</string>
</resources> </resources>
Loading…
Cancel
Save