master
pan 4 years ago
parent 52c6088fd8
commit 18b9ef396f
  1. 6
      foreground/src/main/java/com/gyf/csams/Api.kt
  2. 17
      foreground/src/main/java/com/gyf/csams/InitActivity.kt
  3. 27
      foreground/src/main/java/com/gyf/csams/InitViewModel.kt
  4. 14
      foreground/src/main/java/com/gyf/csams/account/model/AccountViewModel.kt
  5. 17
      foreground/src/main/java/com/gyf/csams/account/ui/AccountActivity.kt
  6. 43
      foreground/src/main/java/com/gyf/csams/activity/model/ApplyActViewModel.kt
  7. 8
      lib/src/main/java/com/gyf/lib/uikit/BaseTextField.kt
  8. 14
      lib/src/main/java/com/gyf/lib/uikit/MainFrame.kt
  9. 5
      lib/src/main/java/com/gyf/lib/uikit/Snackbar.kt
  10. 5
      lib/src/main/java/com/gyf/lib/util/HttpUtil.kt

@ -5,6 +5,12 @@ interface UrlPath {
fun build(): String fun build(): String
} }
enum class TestApi(val path: String) : UrlPath {
Test("test");
override fun build(): String = "/api/${this.path}"
}
/** /**
* 帐号接口 * 帐号接口
* *

@ -7,11 +7,14 @@ import androidx.activity.compose.setContent
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.livedata.observeAsState import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.ui.Alignment
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.lifecycle.viewmodel.compose.viewModel 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.csams.uikit.AnimationText
import com.gyf.lib.uikit.Body
import com.gyf.lib.uikit.MainBoxFrame
import com.orhanobut.logger.Logger import com.orhanobut.logger.Logger
class InitActivity : ComponentActivity() { class InitActivity : ComponentActivity() {
@ -22,22 +25,28 @@ class InitActivity : ComponentActivity() {
// 检查网络 // 检查网络
setContent { setContent {
Body {
MainBoxFrame(background = { /*TODO*/ }, contentAlignment = Alignment.Center) {
val initViewModel: InitViewModel = viewModel() val initViewModel: InitViewModel = viewModel()
initViewModel.checkServer() val isNetWorkWorking: Boolean? by initViewModel.isNetWorkWorking.observeAsState(
val isNetWorkWorking: Boolean? by initViewModel.isNetWorkWorking.observeAsState(null) null
)
when (isNetWorkWorking) { when (isNetWorkWorking) {
null -> AnimationText(text = "检查服务器网络状态中!!!") null -> AnimationText(text = "测试服务端运行状态中。。。")
true -> { true -> {
Init() Init()
finish() finish()
} }
false -> { false -> {
TODO("无法连接到服务器,请检查本地网络或联系管理员") AnimationText(text = "无法连接到服务端,请检查服务端地址${BuildConfig.SERVER_ADDRESS}是否配置正确")
} }
} }
} }
} }
}
}
@Composable @Composable
private fun Init(initViewModel: InitViewModel = viewModel()) { private fun Init(initViewModel: InitViewModel = viewModel()) {

@ -13,6 +13,7 @@ import com.gyf.csams.util.Token
import com.gyf.lib.util.ApiResponse import com.gyf.lib.util.ApiResponse
import com.gyf.lib.util.HttpClient import com.gyf.lib.util.HttpClient
import com.orhanobut.logger.Logger import com.orhanobut.logger.Logger
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
data class TokenVo(val token: String, val studentId: String) data class TokenVo(val token: String, val studentId: String)
@ -30,10 +31,25 @@ class InitViewModel : ViewModel() {
private val _token = MutableLiveData<Boolean>() private val _token = MutableLiveData<Boolean>()
val token: LiveData<Boolean> = _token val token: LiveData<Boolean> = _token
init {
checkServer()
}
fun checkServer() { private fun checkServer() {
Logger.i("测试连接到服务端") Logger.i("测试连接到服务端")
viewModelScope.launch {
delay(5000)
HttpClient.get(
Api.buildUrl(TestApi.Test),
SimpleCallback<Boolean>(action = "测试", onSuccess = {
_isNetWorkWorking.postValue(true) _isNetWorkWorking.postValue(true)
}, onFail = {
Logger.e(it)
_isNetWorkWorking.postValue(false)
}, type = object : TypeToken<ApiResponse<Boolean>>() {}.type)
)
}
} }
/** /**
@ -52,9 +68,12 @@ class InitViewModel : ViewModel() {
url, url,
SimpleCallback<Boolean>( SimpleCallback<Boolean>(
action = action, action = action,
onSuccess = { onSuccess = { it ->
_token.postValue(it.body) it.body?.let {
Logger.i("token校验结果:${it.body}") _token.postValue(it)
Logger.i("token校验结果:${it}")
}
}, },
onFail = { TODO("token校验失败") }, onFail = { TODO("token校验失败") },
type = object : TypeToken<ApiResponse<Boolean>>() {}.type type = object : TypeToken<ApiResponse<Boolean>>() {}.type

@ -65,13 +65,17 @@ typealias Token = TokenResDto
* 注册表单 * 注册表单
*/ */
class AccountViewModel(application: Application) : AndroidViewModel(application) { class AccountViewModel(application: Application) : AndroidViewModel(application) {
val welcomeEnd = application.getString(R.string.welcome_end)
val welcomeStart = application.getString(R.string.welcome_start)
//学号 //学号
val studentId = object : ValidStringForm(formDesc = "学号", textLength = 8) { val studentId = object : ValidStringForm(formDesc = "学号", textLength = 8) {
override fun check() { override fun check() {
_formValue.value?.let { _formValue.value?.let {
when { when {
!it.matches(Regex("\\d{8}")) -> _statusForm.value = FormStatus.FormatError !it.matches(Regex("\\d{8}")) -> _statusForm.value = FormStatus.FormatError
it.matches(Regex("\\d{8}")) -> checkRepeat(_statusForm) route == AccountRoute.Login -> _statusForm.value = FormStatus.Valid
route == AccountRoute.Register -> checkRepeat(_statusForm)
} }
} }
} }
@ -252,6 +256,10 @@ class AccountViewModel(application: Application) : AndroidViewModel(application)
if (checkForm()) { if (checkForm()) {
val url = Api.buildUrl(AccountApi.Login) val url = Api.buildUrl(AccountApi.Login)
Logger.i("开始$loginDesc,请求接口:$url") Logger.i("开始$loginDesc,请求接口:$url")
val studentId = "${studentId.formValue.value}"
val password = "${password.formValue.value}"
this.studentId.formValue
Logger.i("使用学号:$studentId,密码:$password 进行登录")
HttpClient.post( HttpClient.post(
url, url,
SimpleCallback<Token>( SimpleCallback<Token>(
@ -275,8 +283,8 @@ class AccountViewModel(application: Application) : AndroidViewModel(application)
), ),
jsonBody = Gson().toJson( jsonBody = Gson().toJson(
UserLoginVo( UserLoginVo(
studentId = "${studentId.formValue.value}", studentId = studentId,
password = "${password.formValue.value}", password = password,
device = "${Build.MANUFACTURER} ${Build.MODEL}" device = "${Build.MANUFACTURER} ${Build.MODEL}"
) )
) )

@ -27,10 +27,7 @@ import com.gyf.csams.BuildConfig
import com.gyf.csams.R import com.gyf.csams.R
import com.gyf.csams.account.model.AccountViewModel import com.gyf.csams.account.model.AccountViewModel
import com.gyf.csams.account.model.DialogMessage import com.gyf.csams.account.model.DialogMessage
import com.gyf.lib.uikit.BaseTextField import com.gyf.lib.uikit.*
import com.gyf.lib.uikit.Body
import com.gyf.lib.uikit.FormStatus
import com.gyf.lib.uikit.ScaffoldModel
enum class AccountRoute { enum class AccountRoute {
@ -43,12 +40,13 @@ class AccountActivity : ComponentActivity() {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContent { setContent {
Body { nav -> TestBody { nav, scaffoldState ->
NavHost(navController = nav, startDestination = AccountRoute.Login.name) { NavHost(navController = nav, startDestination = AccountRoute.Login.name) {
composable(AccountRoute.Login.name) { composable(AccountRoute.Login.name) {
Account( Account(
route = AccountRoute.Login route = AccountRoute.Login
) { isValidForm: Boolean, accountViewModel: AccountViewModel, scaffoldModel: ScaffoldModel -> ) { isValidForm: Boolean, accountViewModel: AccountViewModel, scaffoldModel: ScaffoldModel ->
Spacer(modifier = Modifier.height(10.dp)) Spacer(modifier = Modifier.height(10.dp))
OutlinedButton( OutlinedButton(
onClick = { onClick = {
@ -79,6 +77,7 @@ class AccountActivity : ComponentActivity() {
) { ) {
Text(text = accountViewModel.goRegister) Text(text = accountViewModel.goRegister)
} }
ShowSnackbar(scaffoldState = scaffoldState)
} }
} }
@ -147,10 +146,10 @@ class AccountActivity : ComponentActivity() {
append(accountViewModel.name.formValue.value ?: "") append(accountViewModel.name.formValue.value ?: "")
} }
withStyle(style = MaterialTheme.typography.subtitle1.toSpanStyle()) { withStyle(style = MaterialTheme.typography.subtitle1.toSpanStyle()) {
append(stringResource(id = R.string.welcome_start)) append(accountViewModel.welcomeStart)
} }
withStyle(style = MaterialTheme.typography.subtitle2.toSpanStyle()) { withStyle(style = MaterialTheme.typography.subtitle2.toSpanStyle()) {
append(stringResource(id = R.string.welcome_end)) append(accountViewModel.welcomeEnd)
} }
withStyle( withStyle(
style = MaterialTheme.typography.subtitle2.toSpanStyle() style = MaterialTheme.typography.subtitle2.toSpanStyle()
@ -160,7 +159,7 @@ class AccountActivity : ComponentActivity() {
} }
}) })
StudentId(checkRepeat = route == AccountRoute.Register) StudentId()
Spacer(modifier = Modifier.height(10.dp)) Spacer(modifier = Modifier.height(10.dp))
@ -184,7 +183,7 @@ class AccountActivity : ComponentActivity() {
* @param accountViewModel * @param accountViewModel
*/ */
@Composable @Composable
private fun StudentId(accountViewModel: AccountViewModel = viewModel(), checkRepeat: Boolean) { private fun StudentId(accountViewModel: AccountViewModel = viewModel()) {
Column { Column {

@ -30,6 +30,30 @@ import kotlinx.coroutines.launch
import java.util.* import java.util.*
class SizeForm(val application: Application) :
StringForm(formDesc = application.getString(R.string.activity_size), textLength = 2) {
val _formError = MutableLiveData<String>()
val formError: LiveData<String> = _formError
val maxActivitySize = application.resources.getInteger(R.integer.activity_size)
val rangeError = application.getString(R.string.activity_size_error, 1, maxActivitySize)
override fun onChange(value: String) {
if (value.length > textLength) {
_formError.value = "${formDesc}不能超过最大长度$textLength"
_formValue.value = value.slice(IntRange(0, textLength - 1))
} else if (value.matches(Regex("\\d+")) && value.toInt() !in 1..maxActivitySize) {
Logger.i("活动人数:${value}不合法")
_formError.value = rangeError
} else {
_formValue.value = value
_formError.value = ""
}
}
}
/** /**
* 申请活动数据状态管理 * 申请活动数据状态管理
* *
@ -49,24 +73,9 @@ class ApplyActViewModel(application: Application) : AndroidViewModel(application
StringForm(formDesc = application.getString(R.string.activity_address), textLength = 30) StringForm(formDesc = application.getString(R.string.activity_address), textLength = 30)
val activityDesc = val activityDesc =
StringForm(formDesc = application.getString(R.string.activity_desc), textLength = 50) StringForm(formDesc = application.getString(R.string.activity_desc), textLength = 50)
val maxActivitySize = application.resources.getInteger(R.integer.activity_size)
val activitySize = object :
StringForm(formDesc = application.getString(R.string.activity_size), textLength = 2) {
override fun onChange(value: String) {
if (value.length > textLength) {
// formError.value = "${formDesc}不能超过最大长度$textLength"
_formValue.value = value.slice(IntRange(0, textLength - 1))
} else if (value.matches(Regex("\\d+")) && value.toInt() !in 1..maxActivitySize) {
Logger.i("活动人数:${value}不合法")
// formError.value =
// application.getString(R.string.activity_size_error, 1, maxActivitySize)
} else {
_formValue.value = value
// formError.value = ""
}
} val activitySize = SizeForm(application = application)
}
val city = val city =
object : StringForm(formDesc = application.getString(R.string.city), textLength = 4) { object : StringForm(formDesc = application.getString(R.string.city), textLength = 4) {
override val formPlaceholder = "" override val formPlaceholder = ""

@ -32,9 +32,6 @@ enum class FormStatus {
Valid Valid
} }
interface FormLength {
val textLength: Int
}
abstract class FormName<T>(val formDesc: String) { abstract class FormName<T>(val formDesc: String) {
protected val _formValue = MutableLiveData<T>() protected val _formValue = MutableLiveData<T>()
@ -52,9 +49,8 @@ abstract class FormName<T>(val formDesc: String) {
* *
* @param formDesc * @param formDesc
*/ */
open class StringForm(formDesc: String, override val textLength: Int) : open class StringForm(formDesc: String, val textLength: Int) :
FormName<String>(formDesc = formDesc), FormName<String>(formDesc = formDesc) {
FormLength {
constructor(formDesc: String, textLength: Int, value: String) : this( constructor(formDesc: String, textLength: Int, value: String) : this(
formDesc = formDesc, formDesc = formDesc,

@ -178,3 +178,17 @@ fun Body(content: @Composable (nav: NavHostController) -> Unit) {
} }
} }
} }
@Composable
fun TestBody(content: @Composable (nav: NavHostController, scaffoldState: ScaffoldState) -> Unit) {
CSAMSTheme {
Surface(color = MaterialTheme.colors.background) {
val navController = rememberNavController()
val scaffoldState = rememberScaffoldState()
Scaffold(scaffoldState = scaffoldState) {
content(nav = navController, scaffoldState = scaffoldState)
}
}
}
}

@ -32,10 +32,11 @@ class ScaffoldModel : ViewModel() {
fun update(message: String? = null, actionLabel: String? = null, callback: () -> Unit? = {}) { fun update(message: String? = null, actionLabel: String? = null, callback: () -> Unit? = {}) {
if (message == null) { if (message == null) {
_data.value = null _data.postValue(null)
} else { } else {
_data.value = _data.postValue(
SnackBar(message = message, actionLabel = actionLabel, callback = callback) SnackBar(message = message, actionLabel = actionLabel, callback = callback)
)
} }
} }
} }

@ -140,9 +140,10 @@ abstract class HttpCallback<T>(
val body = response.body val body = response.body
if (body != null && body.contentType()?.subtype == "json") { if (body != null && body.contentType()?.subtype == "json") {
val jsonRes = body.string() val jsonRes = body.string()
val res: ApiResponse<T> = gson.fromJson(jsonRes, type)
Logger.i("${action}请求响应成功:")
Logger.json(jsonRes) Logger.json(jsonRes)
val res: ApiResponse<T> = gson.fromJson(jsonRes, type)
Logger.i("json解析成功:$res")
onSuccess(res) onSuccess(res)
} else { } else {
onFail("${action}失败,请联系管理员") onFail("${action}失败,请联系管理员")

Loading…
Cancel
Save