From f093f47c37f95d094755766b127908fa9973698a Mon Sep 17 00:00:00 2001 From: pan <1029559041@qq.com> Date: Fri, 4 Jun 2021 11:07:55 +0800 Subject: [PATCH] =?UTF-8?q?=E7=94=B3=E8=AF=B7=E6=B4=BB=E5=8A=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- background/src/main/AndroidManifest.xml | 2 +- .../main/java/com/gyf/csams/InitActivity.kt | 2 +- .../gyf/csams/account/model/LoginViewModel.kt | 5 +- .../model/AssociationManagementViewModel.kt | 6 +- .../gyf/csams/main/model/AuditActViewModel.kt | 29 + .../main/model/AuditAssociationViewModel.kt | 76 +-- .../csams/main/model/BackgroundViewModel.kt | 2 +- .../csams/main/model/BaseAuditViewModel.kt | 89 +++ .../gyf/csams/main/model/CheckActViewModel.kt | 46 -- .../main/model/CheckQualityReportViewModel.kt | 3 +- .../main/model/ManagementOfficerModel.kt | 5 +- .../csams/main/model/ManagerActViewModel.kt | 22 +- .../com/gyf/csams/main/model/MenuViewModel.kt | 2 +- .../gyf/csams/main/model/RenameViewModel.kt | 3 +- .../main/ui/AssociationManagementActivity.kt | 4 +- .../com/gyf/csams/main/ui/AuditActActivity.kt | 96 ++++ .../csams/main/ui/AuditAssociationActivity.kt | 241 +------- .../com/gyf/csams/main/ui/CheckActActivity.kt | 92 --- .../main/ui/CheckQualityReportActivity.kt | 5 +- .../com/gyf/csams/main/ui/MainActivity.kt | 5 +- .../main/ui/ManagementOfficerActivity.kt | 2 +- .../gyf/csams/main/ui/ManagerActActivity.kt | 22 +- .../gyf/csams/main/ui/NotificationActivity.kt | 7 +- .../com/gyf/csams/main/ui/RenameActivity.kt | 2 +- .../java/com/gyf/csams/uikit/CheckForm.kt | 266 +++++++++ .../main/java/com/gyf/csams/uikit/Table.kt | 15 +- .../main/java/com/gyf/csams/InitActivity.kt | 3 +- .../csams/account/model/AccountViewModel.kt | 44 +- .../gyf/csams/account/ui/AccountActivity.kt | 2 +- .../activity/model/ActivityDetailViewModel.kt | 19 +- .../csams/activity/model/ApplyActViewModel.kt | 171 ++++-- .../activity/ui/ActivityDetailActivity.kt | 26 +- .../gyf/csams/activity/ui/ApplyActActivity.kt | 224 +++++--- .../association/model/AssociationViewModel.kt | 14 +- .../csams/association/model/ExamViewModel.kt | 65 +-- .../model/RegAssociationViewModel.kt | 49 +- .../association/ui/AssociationActivity.kt | 151 ++--- .../gyf/csams/association/ui/ExamActivity.kt | 21 +- .../association/ui/RegAssociationActivity.kt | 155 +++--- .../com/gyf/csams/main/model/MainViewModel.kt | 13 +- .../com/gyf/csams/main/ui/MainActivity.kt | 69 ++- .../message/model/ForegroundViewModel.kt | 3 +- .../csams/message/ui/SysMessageActivity.kt | 7 +- .../main/java/com/gyf/csams/uikit/BaseView.kt | 52 +- .../main/java/com/gyf/csams/util/GsonUtil.kt | 39 +- .../java/com/gyf/csams/util/HttpCallback.kt | 3 +- foreground/src/main/res/drawable/ic_clock.xml | 9 + .../java/com/gyf/csams/ExampleUnitTest.kt | 3 +- lib/build.gradle.kts | 2 + .../com/gyf/lib/ExampleInstrumentedTest.kt | 2 +- .../gyf/lib/model/AbstractLoginViewModel.kt | 23 +- .../java/com/gyf/lib/model/InitViewModel.kt | 8 +- .../com/gyf/lib/model/SysMessageViewModel.kt | 9 +- .../java/com/gyf/lib/service/BaseActivity.kt | 3 +- .../com/gyf/lib/service/MessageService.kt | 29 +- .../com/gyf/lib/uikit/AbstractInitActivity.kt | 3 +- .../java/com/gyf/lib/uikit/BaseTextField.kt | 13 + .../main/java/com/gyf/lib/uikit/Profile.kt | 8 +- lib/src/main/java/com/gyf/lib/util/Api.kt | 33 +- .../java/com/gyf/lib/util/DateTimeUtil.kt | 53 ++ .../main/java/com/gyf/lib/util/HttpUtil.kt | 53 +- .../main/java/com/gyf/lib/util/RandomUtil.kt | 22 - .../main/java/com/gyf/lib/util/TokenUtil.kt | 61 +- lib/src/main/java/com/gyf/lib/util/Vo.kt | 527 ------------------ lib/src/main/res/values-en/integers.xml | 1 + lib/src/main/res/values-en/strings.xml | 1 + lib/src/main/res/values-zh/integers.xml | 1 + lib/src/main/res/values-zh/strings.xml | 1 + lib/src/main/res/values/integers.xml | 1 + lib/src/main/res/values/strings.xml | 1 + .../test/java/com/gyf/lib/ExampleUnitTest.kt | 8 + settings.gradle.kts | 4 + 72 files changed, 1518 insertions(+), 1540 deletions(-) create mode 100644 background/src/main/java/com/gyf/csams/main/model/AuditActViewModel.kt create mode 100644 background/src/main/java/com/gyf/csams/main/model/BaseAuditViewModel.kt delete mode 100644 background/src/main/java/com/gyf/csams/main/model/CheckActViewModel.kt create mode 100644 background/src/main/java/com/gyf/csams/main/ui/AuditActActivity.kt delete mode 100644 background/src/main/java/com/gyf/csams/main/ui/CheckActActivity.kt create mode 100644 background/src/main/java/com/gyf/csams/uikit/CheckForm.kt create mode 100644 foreground/src/main/res/drawable/ic_clock.xml create mode 100644 lib/src/main/java/com/gyf/lib/util/DateTimeUtil.kt delete mode 100644 lib/src/main/java/com/gyf/lib/util/Vo.kt diff --git a/background/src/main/AndroidManifest.xml b/background/src/main/AndroidManifest.xml index a4efbc5..ff91fa0 100644 --- a/background/src/main/AndroidManifest.xml +++ b/background/src/main/AndroidManifest.xml @@ -47,7 +47,7 @@ android:name=".main.ui.AuditAssociationActivity" android:windowSoftInputMode="adjustResize" /> - + diff --git a/background/src/main/java/com/gyf/csams/InitActivity.kt b/background/src/main/java/com/gyf/csams/InitActivity.kt index 14ed4d7..b6e6308 100644 --- a/background/src/main/java/com/gyf/csams/InitActivity.kt +++ b/background/src/main/java/com/gyf/csams/InitActivity.kt @@ -4,10 +4,10 @@ import android.app.Activity import com.google.gson.reflect.TypeToken import com.gyf.csams.account.ui.LoginActivity import com.gyf.csams.main.ui.MainActivity +import com.gyf.csams.module.ManagerVo import com.gyf.lib.uikit.AbstractInitActivity import com.gyf.lib.util.AccountApi import com.gyf.lib.util.ApiResponse -import com.gyf.lib.util.ManagerVo import java.lang.reflect.Type class InitActivity : AbstractInitActivity() { 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 edddac8..48ce5ee 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 @@ -4,12 +4,13 @@ import android.app.Activity import android.app.Application import android.os.Build import com.gyf.csams.account.ui.LoginActivity +import com.gyf.csams.module.ClientType +import com.gyf.csams.module.ManagerLoginVo import com.gyf.lib.model.AbstractLoginViewModel import com.gyf.lib.uikit.FormStatus import com.gyf.lib.uikit.ValidStringForm import com.gyf.lib.util.AccountApi -import com.gyf.lib.util.ClientType -import com.gyf.lib.util.ManagerLoginVo + class LoginViewModel(application: Application) : AbstractLoginViewModel(application) { override val id = ValidStringForm(formDesc = "管理帐号", textLength = 8) 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 12c8f0c..fa8212a 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,11 +1,9 @@ package com.gyf.csams.main.model import android.app.Application +import com.gyf.csams.module.AssociationLevel +import com.gyf.csams.module.AssociationVo import com.gyf.lib.model.ScrollViewModel -import com.gyf.lib.util.AssociationLevel -import com.gyf.lib.util.AssociationVo - - /** diff --git a/background/src/main/java/com/gyf/csams/main/model/AuditActViewModel.kt b/background/src/main/java/com/gyf/csams/main/model/AuditActViewModel.kt new file mode 100644 index 0000000..737f5bc --- /dev/null +++ b/background/src/main/java/com/gyf/csams/main/model/AuditActViewModel.kt @@ -0,0 +1,29 @@ +package com.gyf.csams.main.model + +import android.app.Application +import com.google.gson.reflect.TypeToken +import com.gyf.csams.module.AuditActVo +import com.gyf.lib.util.ActivityApi +import com.gyf.lib.util.ApiResponse + +import com.gyf.lib.util.UrlPath +import java.lang.reflect.Type + + +/** + * 活动审核 + * + */ +class AuditActViewModel(application: Application) : BaseAuditViewModel(application) { + override val auditApi: UrlPath = ActivityApi.Audit + override val acceptApi: UrlPath = ActivityApi.Accept + override val checkApi: UrlPath = ActivityApi.Check + override val typeToken: Type = + object : TypeToken>>() {}.type + + init { + load { } + } + + +} \ No newline at end of file diff --git a/background/src/main/java/com/gyf/csams/main/model/AuditAssociationViewModel.kt b/background/src/main/java/com/gyf/csams/main/model/AuditAssociationViewModel.kt index f36eeea..a38341e 100644 --- a/background/src/main/java/com/gyf/csams/main/model/AuditAssociationViewModel.kt +++ b/background/src/main/java/com/gyf/csams/main/model/AuditAssociationViewModel.kt @@ -1,78 +1,28 @@ package com.gyf.csams.main.model import android.app.Application -import androidx.lifecycle.viewModelScope import com.google.gson.reflect.TypeToken -import com.gyf.lib.model.ScrollViewModel -import com.gyf.lib.util.* -import kotlinx.coroutines.launch +import com.gyf.csams.module.AuditAssociationVo +import com.gyf.lib.util.ApiResponse +import com.gyf.lib.util.AssociationApi +import com.gyf.lib.util.UrlPath +import java.lang.reflect.Type -class AuditAssociationViewModel(application: Application) : ScrollViewModel( + +class AuditAssociationViewModel(application: Application) : BaseAuditViewModel( application ) { - override val initSize: Int = 10 + + override val auditApi: UrlPath = AssociationApi.Audit + override val acceptApi: UrlPath = AssociationApi.Accept + override val checkApi: UrlPath = AssociationApi.Check + override val typeToken: Type = + object : TypeToken>>() {}.type init { load { } } - fun load(callback: (message: String) -> Unit) { - viewModelScope.launch { - HttpClient.post( - Api.buildUrl(AssociationApi.Audit), HttpCallback>( - action = "获取审核列表", - onSuccess = { it -> - it.body?.let { - _data.postValue(it) - } - }, - typeToken = object : - TypeToken>>() {}.type - ), - jsonParam = OnlyToken(clientType = ClientType.Background) - ) - } - } - - - /** - * 受理注册资料 - * - * @param callback - */ - fun accept(regId: Int, isFirstAccept: Boolean, callback: (message: String) -> Unit) { - viewModelScope.launch { - HttpClient.post( - Api.buildUrl(AssociationApi.Accept), - HttpCallback(action = "受理社团注册资料", onSuccess = { - callback(it.message) - }, typeToken = object : TypeToken>() {}.type), - jsonParam = AcceptRegAssociation(regId = regId, isFirstAccept = isFirstAccept) - ) - } - } - - /** - * 提交审核结果 - * - * @param regId - * @param result - * @param callback - */ - fun check(regId: Int, cause: String, result: Boolean, callback: (message: String) -> Unit) { - viewModelScope.launch { - HttpClient.post( - Api.buildUrl(AssociationApi.Check), - HttpCallback(action = "提交审核结果", onSuccess = { - callback(it.message) - }, typeToken = object : TypeToken>() {}.type), - jsonParam = CheckRegVo( - regId = regId, result = result, - cause = cause - ) - ) - } - } } \ No newline at end of file diff --git a/background/src/main/java/com/gyf/csams/main/model/BackgroundViewModel.kt b/background/src/main/java/com/gyf/csams/main/model/BackgroundViewModel.kt index f691b3c..536d2d3 100644 --- a/background/src/main/java/com/gyf/csams/main/model/BackgroundViewModel.kt +++ b/background/src/main/java/com/gyf/csams/main/model/BackgroundViewModel.kt @@ -1,8 +1,8 @@ package com.gyf.csams.main.model import android.app.Application +import com.gyf.csams.module.ClientType import com.gyf.lib.model.SysMessageViewModel -import com.gyf.lib.util.ClientType class BackgroundViewModel(application: Application) : SysMessageViewModel(application) { override fun clientType(): ClientType { diff --git a/background/src/main/java/com/gyf/csams/main/model/BaseAuditViewModel.kt b/background/src/main/java/com/gyf/csams/main/model/BaseAuditViewModel.kt new file mode 100644 index 0000000..f952309 --- /dev/null +++ b/background/src/main/java/com/gyf/csams/main/model/BaseAuditViewModel.kt @@ -0,0 +1,89 @@ +package com.gyf.csams.main.model + +import android.app.Application +import androidx.lifecycle.viewModelScope +import com.google.gson.reflect.TypeToken +import com.gyf.csams.module.AcceptVo +import com.gyf.csams.module.AuditVo +import com.gyf.csams.module.CheckVo +import com.gyf.csams.module.ClientType +import com.gyf.lib.model.ScrollViewModel +import com.gyf.lib.util.* +import kotlinx.coroutines.launch +import java.lang.reflect.Type + + +abstract class BaseAuditViewModel(application: Application) : + ScrollViewModel(application = application) { + + abstract val auditApi: UrlPath + abstract val acceptApi: UrlPath + abstract val checkApi: UrlPath + + abstract val typeToken: Type + + /** + * 加载审核记录 + * + * @param callback + */ + fun load(callback: (message: String) -> Unit) { + viewModelScope.launch { + HttpClient.post( + Api.buildUrl(auditApi), HttpCallback>( + action = "加载资料", + onSuccess = { it -> + it.body?.let { + _data.postValue(it) + } + }, + typeToken = typeToken + ), + jsonParam = OnlyToken(clientType = ClientType.Background) + ) + } + } + + + /** + * 受理资料 + * + * @param callback + */ + fun accept(auditId: Int, callback: (message: String) -> Unit) { + viewModelScope.launch { + HttpClient.post( + Api.buildUrl(acceptApi), + HttpCallback(action = "受理资料", onSuccess = { + callback(it.message) + }, typeToken = object : TypeToken>() {}.type), + jsonParam = AcceptVo(auditId = auditId, token = TokenManager.getToken()) + ) + } + } + + /** + * 审核资料 + * + * @param auditId + * @param result + * @param callback + */ + fun check(auditId: Int, cause: String, result: Boolean, callback: (message: String) -> Unit) { + viewModelScope.launch { + HttpClient.post( + Api.buildUrl(checkApi), + HttpCallback(action = "审核资料", onSuccess = { + callback(it.message) + }, typeToken = object : TypeToken>() {}.type), + jsonParam = CheckVo( + auditId = auditId, + result = result, + cause = cause, + token = TokenManager.getToken() + ) + ) + } + } + +} \ No newline at end of file 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 deleted file mode 100644 index c75a720..0000000 --- a/background/src/main/java/com/gyf/csams/main/model/CheckActViewModel.kt +++ /dev/null @@ -1,46 +0,0 @@ -package com.gyf.csams.main.model - -import android.app.Application -import androidx.lifecycle.viewModelScope -import com.gyf.lib.model.ApplyViewModel -import com.gyf.lib.util.ApplyActVo -import com.gyf.lib.util.format -import com.gyf.lib.util.randomChinese -import com.gyf.lib.util.randomDateTime -import kotlinx.coroutines.launch - - -/** - * 活动数据管理 - * - */ -class CheckActViewModel(application: Application) : ApplyViewModel(application) { - override val initSize: Int = 10 - - init { - load() - } - - fun load() { - viewModelScope.launch { - _data.value?.apply { - repeat(initSize) { - add( - ApplyActVo( - activityName = randomChinese(5), - activityTime = randomDateTime().format(), - location = randomChinese(10), - desc = randomChinese(10), - size = 10 - ) - ) - } - } - } - } - - fun loadMore(callback: (message: String) -> Unit) { - TODO("Not yet implemented") - } - -} \ No newline at end of file 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 138a492..302d031 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 @@ -2,8 +2,9 @@ package com.gyf.csams.main.model import android.app.Application import androidx.lifecycle.viewModelScope +import com.gyf.csams.module.QualityReportVo import com.gyf.lib.model.ApplyViewModel -import com.gyf.lib.util.QualityReportVo + import com.gyf.lib.util.randomChinese import kotlinx.coroutines.launch diff --git a/background/src/main/java/com/gyf/csams/main/model/ManagementOfficerModel.kt b/background/src/main/java/com/gyf/csams/main/model/ManagementOfficerModel.kt index b2b428e..57a6b10 100644 --- a/background/src/main/java/com/gyf/csams/main/model/ManagementOfficerModel.kt +++ b/background/src/main/java/com/gyf/csams/main/model/ManagementOfficerModel.kt @@ -3,8 +3,9 @@ package com.gyf.csams.main.model import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel -import com.gyf.lib.util.AllOfficerVo -import com.gyf.lib.util.ManagerInfoVo +import com.gyf.csams.module.AllOfficerVo +import com.gyf.csams.module.ManagerInfoVo + enum class ColumnType { Text, 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 a7eba4f..612fcf9 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 @@ -1,11 +1,8 @@ package com.gyf.csams.main.model import android.app.Application +import com.gyf.csams.module.ManagerActVo import com.gyf.lib.model.ScrollViewModel -import com.gyf.lib.util.ActivityVo -import com.gyf.lib.util.randomChinese -import com.gyf.lib.util.randomDateTime -import com.gyf.lib.util.randomNum /** @@ -15,7 +12,7 @@ import com.gyf.lib.util.randomNum * * @param application */ -class ManagerActViewModel(application: Application) : ScrollViewModel(application) { +class ManagerActViewModel(application: Application) : ScrollViewModel(application) { override val initSize: Int = 10 init { @@ -23,20 +20,7 @@ class ManagerActViewModel(application: Application) : ScrollViewModel Unit) { diff --git a/background/src/main/java/com/gyf/csams/main/model/MenuViewModel.kt b/background/src/main/java/com/gyf/csams/main/model/MenuViewModel.kt index 53e7fc1..41c02d9 100644 --- a/background/src/main/java/com/gyf/csams/main/model/MenuViewModel.kt +++ b/background/src/main/java/com/gyf/csams/main/model/MenuViewModel.kt @@ -15,7 +15,7 @@ enum class MenuType(val desc: String, val clazz: Map ), Act( "活动管理", mapOf( - "审核社团活动" to CheckActActivity::class.java, + "审核社团活动" to AuditActActivity::class.java, "审核质量报告单" to CheckQualityReportActivity::class.java, "查看社团活动" to ManagerActActivity::class.java ) 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 937346d..eb4b046 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,9 +3,10 @@ package com.gyf.csams.main.model import android.app.Application import androidx.lifecycle.viewModelScope import com.gyf.csams.R +import com.gyf.csams.module.RenameVo import com.gyf.lib.model.ScrollViewModel import com.gyf.lib.uikit.StringForm -import com.gyf.lib.util.RenameVo + import com.gyf.lib.util.randomChinese import com.gyf.lib.util.randomNum import kotlinx.coroutines.launch 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 3672ae5..a184f9d 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 @@ -17,9 +17,9 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import androidx.lifecycle.viewmodel.compose.viewModel import com.gyf.csams.main.model.AssociationManagementViewModel +import com.gyf.csams.module.AssociationLevel import com.gyf.lib.uikit.Body import com.gyf.lib.uikit.MainBoxFrame -import com.gyf.lib.util.AssociationLevel /** * 社团管理 @@ -52,7 +52,7 @@ class AssociationManagementActivity : ComponentActivity() { horizontalArrangement = Arrangement.SpaceBetween ) { Text( - text = "$id", + text = "$associationId", style = MaterialTheme.typography.h6 ) Text( diff --git a/background/src/main/java/com/gyf/csams/main/ui/AuditActActivity.kt b/background/src/main/java/com/gyf/csams/main/ui/AuditActActivity.kt new file mode 100644 index 0000000..6ce9848 --- /dev/null +++ b/background/src/main/java/com/gyf/csams/main/ui/AuditActActivity.kt @@ -0,0 +1,96 @@ +package com.gyf.csams.main.ui + +import android.os.Bundle +import androidx.activity.ComponentActivity +import androidx.activity.compose.setContent +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.height +import androidx.compose.material.ExperimentalMaterialApi +import androidx.compose.runtime.Composable +import androidx.compose.runtime.ExperimentalComposeApi +import androidx.compose.runtime.getValue +import androidx.compose.runtime.livedata.observeAsState +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import androidx.core.view.WindowCompat +import androidx.lifecycle.viewmodel.compose.viewModel +import com.google.accompanist.insets.ExperimentalAnimatedInsets +import com.gyf.csams.R +import com.gyf.csams.main.model.AuditActViewModel +import com.gyf.csams.module.AuditActVo +import com.gyf.csams.uikit.BASE_HEIGHT +import com.gyf.csams.uikit.CheckForm +import com.gyf.csams.uikit.RowItem +import com.gyf.csams.uikit.TestTableImeSimple +import com.gyf.lib.uikit.ImeBody + +import com.gyf.lib.util.DateTimeUtil.datetimeFormat +import java.util.* + +/** + * 审批社团活动 + * + */ +class AuditActActivity : ComponentActivity() { + @ExperimentalMaterialApi + @ExperimentalAnimatedInsets + @ExperimentalComposeApi + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + WindowCompat.setDecorFitsSystemWindows(window, false) + setContent { + ImeBody { + val model: AuditActViewModel = viewModel() + val data by model.data.observeAsState() + TestTableImeSimple( + title = R.string.activity_association + ) { + data?.forEach { + item { + RegisterForm(vo = it) + CheckForm(vo = it) + Spacer(modifier = Modifier.height(10.dp)) + } + } + } + } + } + + } + + @Composable + private fun RegisterForm( + modifier: Modifier = Modifier, + vo: AuditActVo + ) { + Column(modifier = modifier) { + vo.activityVo.activityTime + RowItem( + modifier = Modifier.height(BASE_HEIGHT), + key = R.string.activity_name, + value = vo.activityVo.activityName + ) + RowItem( + modifier = Modifier.height(BASE_HEIGHT), + key = R.string.activity_time, + value = Date(vo.activityVo.activityTime).datetimeFormat() + ) + RowItem( + modifier = Modifier.height(BASE_HEIGHT * 1.5F), + key = R.string.activity_address, + value = vo.activityVo.activityAddress + ) + RowItem( + modifier = Modifier.height(BASE_HEIGHT * 3), + key = R.string.activity_desc, + value = vo.activityVo.activityDesc + ) + RowItem( + modifier = Modifier.height(BASE_HEIGHT), + key = R.string.activity_size, + value = "${vo.activityVo.activitySize}" + ) + } + } +} \ No newline at end of file diff --git a/background/src/main/java/com/gyf/csams/main/ui/AuditAssociationActivity.kt b/background/src/main/java/com/gyf/csams/main/ui/AuditAssociationActivity.kt index ea566db..7468950 100644 --- a/background/src/main/java/com/gyf/csams/main/ui/AuditAssociationActivity.kt +++ b/background/src/main/java/com/gyf/csams/main/ui/AuditAssociationActivity.kt @@ -5,7 +5,9 @@ import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.compose.foundation.Image import androidx.compose.foundation.border -import androidx.compose.foundation.layout.* +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.height import androidx.compose.material.ExperimentalMaterialApi import androidx.compose.material.MaterialTheme import androidx.compose.runtime.Composable @@ -18,13 +20,15 @@ import androidx.core.view.WindowCompat import androidx.lifecycle.viewmodel.compose.viewModel import com.google.accompanist.coil.rememberCoilPainter import com.google.accompanist.insets.ExperimentalAnimatedInsets -import com.google.accompanist.insets.navigationBarsWithImePadding import com.gyf.csams.R import com.gyf.csams.main.model.AuditAssociationViewModel +import com.gyf.csams.module.AuditAssociationVo +import com.gyf.csams.uikit.BASE_HEIGHT +import com.gyf.csams.uikit.CheckForm import com.gyf.csams.uikit.RowItem import com.gyf.csams.uikit.TestTableImeSimple -import com.gyf.lib.uikit.* -import com.gyf.lib.util.* +import com.gyf.lib.uikit.ImeBody +import com.gyf.lib.util.Api class AuditAssociationActivity : ComponentActivity() { @ExperimentalMaterialApi @@ -43,6 +47,7 @@ class AuditAssociationActivity : ComponentActivity() { data?.forEach { item { RegisterForm(vo = it) + CheckForm(vo = it) Spacer(modifier = Modifier.height(10.dp)) } } @@ -52,208 +57,9 @@ class AuditAssociationActivity : ComponentActivity() { } - @Composable - private fun CheckForm( - vo: DisposeRegInfoVo, - scaffoldModel: ScaffoldModel = viewModel(), - auditAssociationViewModel: AuditAssociationViewModel = viewModel(), - first: @Composable () -> Unit, - last: @Composable () -> Unit - ) { - val baseHeight = 50.dp - - (TokenManager.getOwnInfo() as? ManagerVo)?.let { it -> - var confirmDesc: Int? = null - var backDesc: Int? = null - var onConfirm: (() -> Unit)? = null - var onBack: (() -> Unit)? = null - val check: (result: Boolean, cause: StringForm) -> Unit = - { result: Boolean, cause: StringForm -> - scaffoldModel.update( - message = "确认${if (result) "上报" else "驳回"}?", - actionLabel = "确认" - ) { - auditAssociationViewModel.check( - regId = vo.log.id, - result = result, - cause = cause.formValue.value - ?: throw IllegalArgumentException("无法获取审核理由") - ) { - scaffoldModel.update(message = it, actionLabel = "刷新") { - auditAssociationViewModel.load { } - } - } - } - } - - val accept: (m: String, isFirstAccept: Boolean) -> Unit = - { m: String, isFirstAccept: Boolean -> - scaffoldModel.update("确认${m}?", actionLabel = "确认") { - auditAssociationViewModel.accept( - regId = vo.log.id, - isFirstAccept = isFirstAccept - ) { - scaffoldModel.update(message = it, actionLabel = "刷新") { - auditAssociationViewModel.load { } - } - } - } - } - - val doCheck: @Composable () -> Unit = { - val cause = ValidStringForm( - formDesc = "审核理由", - textLength = 20 - ) - val statusForm by cause.statusForm.observeAsState() - - onConfirm = { - if (statusForm == FormStatus.Empty) { - scaffoldModel.update("${cause.formDesc}不能为空", actionLabel = "知道了") - } else { - check(true, cause) - } - } - onBack = { - if (statusForm == FormStatus.Empty) { - scaffoldModel.update("${cause.formDesc}不能为空", actionLabel = "知道了") - } else { - check(false, cause) - } - } - - Row( - modifier = Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.Center - ) { - BaseTextField( - modifier = Modifier.navigationBarsWithImePadding(), - form = cause - ) - } - } - - when { - //初审记录,负责人为空 等待初审 - vo.log.nextAudit == null && vo.log.manager == null -> { - if (it.duty == Duty.PamphaBhusal) { - confirmDesc = R.string.accept_btn - onConfirm = { accept("受理", true) } - } - first() - RowItem(key = R.string.first_approver_origin, value = "") - RowItem(key = R.string.first_result, value = "") - last() - RowItem(key = R.string.last_approver_origin, value = "") - RowItem(key = R.string.last_result, value = "") - RowItem( - modifier = Modifier.height(baseHeight), - key = R.string.audit_phases, value = "等待初审" - ) - } - //初审记录,负责人不为空 初审受理 - vo.log.nextAudit == null && vo.log.manager != null -> { - - first() - if (it.duty == Duty.PamphaBhusal) { - confirmDesc = R.string.reported_btn - backDesc = R.string.reject_btn - - doCheck() - } else { - RowItem(key = R.string.first_approver_origin, value = "") - } - RowItem(key = R.string.first_result, value = "") - last() - RowItem(key = R.string.last_approver_origin, value = "") - RowItem(key = R.string.last_result, value = "") - RowItem( - modifier = Modifier.height(baseHeight), - key = R.string.audit_phases, value = "初审受理" - ) - } - //初审记录,审核通过(上报) 等待复审 - vo.log.nextAudit != null && vo.log.nextAudit?.manager == null -> { - - if (it.duty == Duty.Teacher) { - confirmDesc = R.string.recheck_btn - onConfirm = { accept("复审", false) } - } - first() - RowItem(key = R.string.first_approver_origin, value = vo.log.cause) - RowItem(key = R.string.first_result, value = "通过") - last() - RowItem(key = R.string.last_approver_origin, value = "") - RowItem(key = R.string.last_result, value = "") - RowItem( - modifier = Modifier.height(baseHeight), - key = R.string.audit_phases, value = "等待复审" - ) - } - //复审记录,审核结果为空 复审受理 - vo.log.nextAudit != null && vo.log.nextAudit?.result == null -> { - first() - RowItem(key = R.string.first_approver_origin, value = vo.log.cause) - RowItem(key = R.string.first_result, value = "通过") - last() - if (it.duty == Duty.Teacher) { - confirmDesc = R.string.allow_btn - backDesc = R.string.reject_btn - doCheck() - } else { - RowItem(key = R.string.last_approver_origin, value = "") - } - RowItem(key = R.string.last_result, value = "") - RowItem( - modifier = Modifier.height(baseHeight), - key = R.string.audit_phases, value = "复审受理" - ) - } - else -> { - first() - RowItem(key = R.string.first_approver_origin, value = vo.log.cause) - RowItem( - key = R.string.first_result, value = when (vo.log.result) { - null -> "" - true -> "通过" - false -> "不通过" - } - ) - last() - RowItem( - key = R.string.last_approver_origin, - value = vo.log.nextAudit?.cause ?: "" - ) - RowItem( - key = R.string.last_result, value = when (vo.log.nextAudit?.result) { - null -> "" - true -> "通过" - false -> "不通过" - } - ) - RowItem( - modifier = Modifier.height(baseHeight), - key = R.string.audit_phases, value = "完成审核" - ) - } - } - - if (confirmDesc != null) { - BottomButton( - confirmDesc = confirmDesc, - backDesc = backDesc, - modifier = Modifier.fillMaxWidth(), - onBack = onBack - ) { - onConfirm?.let { it() } - } - } - } - } - @Composable private fun RegisterForm( - modifier: Modifier = Modifier, vo: DisposeRegInfoVo + modifier: Modifier = Modifier, vo: AuditAssociationVo ) { Column( modifier = modifier.border( @@ -261,28 +67,26 @@ class AuditAssociationActivity : ComponentActivity() { color = MaterialTheme.colors.onBackground ) ) { - val baseHeight = 50.dp - RowItem( - modifier = Modifier.height(baseHeight), + modifier = Modifier.height(BASE_HEIGHT), key = R.string.petitioner, - value = vo.log.user.name + value = vo.audit.user.name ) RowItem( - modifier = Modifier.height(baseHeight), + modifier = Modifier.height(BASE_HEIGHT), key = R.string.association_name, value = vo.name ) RowItem( - modifier = Modifier.height(baseHeight), + modifier = Modifier.height(BASE_HEIGHT), key = R.string.association_desc, value = vo.desc ) RowItem( - modifier = Modifier.height(baseHeight * 3), + modifier = Modifier.height(BASE_HEIGHT * 3), key = R.string.association_logo ) { //TODO 图片全屏显示 @@ -290,21 +94,6 @@ class AuditAssociationActivity : ComponentActivity() { rememberCoilPainter(Api.buildUrl(vo.logo)) Image(painter = painter, contentDescription = null) } - - CheckForm(vo = vo, first = { - RowItem( - modifier = Modifier.height(baseHeight), - key = R.string.first_approver, - value = vo.log.manager?.name ?: "" - ) - }, last = { - RowItem( - modifier = Modifier.height(baseHeight), - key = R.string.last_approver, - value = vo.log.nextAudit?.manager?.name ?: "" - ) - }) - } } } \ No newline at end of file diff --git a/background/src/main/java/com/gyf/csams/main/ui/CheckActActivity.kt b/background/src/main/java/com/gyf/csams/main/ui/CheckActActivity.kt deleted file mode 100644 index 95ac2b5..0000000 --- a/background/src/main/java/com/gyf/csams/main/ui/CheckActActivity.kt +++ /dev/null @@ -1,92 +0,0 @@ -package com.gyf.csams.main.ui - -import android.os.Bundle -import androidx.activity.ComponentActivity -import androidx.activity.compose.setContent -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.runtime.Composable -import androidx.compose.runtime.ExperimentalComposeApi -import androidx.compose.ui.Modifier -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.unit.dp -import androidx.lifecycle.viewmodel.compose.viewModel -import com.google.accompanist.insets.ExperimentalAnimatedInsets -import com.gyf.csams.R -import com.gyf.csams.main.model.CheckActViewModel -import com.gyf.csams.uikit.RowItem -import com.gyf.csams.uikit.TestTable -import com.gyf.lib.uikit.BaseTextField -import com.gyf.lib.uikit.ScaffoldModel -import com.gyf.lib.util.ApplyActVo -import com.gyf.lib.util.BottomButton - -/** - * 审批社团活动 - * - */ -class CheckActActivity : ComponentActivity() { - @ExperimentalAnimatedInsets - @ExperimentalComposeApi - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - - setContent { - TestTable( - clazz = CheckActViewModel::class.java, - title = R.string.activity_application - ) { - ApplyActForm(vo = it) - } - } - } - - @Composable - private fun ApplyActForm( - modifier: Modifier = Modifier, model: CheckActViewModel = viewModel(), - scaffoldModel: ScaffoldModel = viewModel(), vo: ApplyActVo - ) { - Column(modifier = modifier) { - val baseHeight = 50.dp - RowItem( - modifier = Modifier.height(baseHeight), - key = R.string.activity_name, - value = vo.activityName - ) - RowItem( - modifier = Modifier.height(baseHeight * 1.5F), - key = R.string.activity_address, - value = vo.location - ) - RowItem( - modifier = Modifier.height(baseHeight * 3), - key = R.string.activity_desc, - value = vo.desc - ) - RowItem( - modifier = Modifier.height(baseHeight), - key = R.string.activity_size, - value = "${vo.size}" - ) - RowItem( - modifier = Modifier.height(baseHeight), key = R.string.first_approver, value = "" - /**TODO 获取审批人**/ - ) - RowItem( - modifier = Modifier.height(baseHeight * 3), - key = R.string.first_approver_origin - ) { - BaseTextField(modifier = Modifier.fillMaxSize(), form = model.approveOrigin) - } - val message = stringResource(id = R.string.not_impl_error) - BottomButton( - confirmDesc = R.string.reported_btn, backDesc = R.string.reject_btn, - modifier = Modifier.fillMaxWidth() - ) { - scaffoldModel.update(message = message) - } - } - } -} \ No newline at end of file diff --git a/background/src/main/java/com/gyf/csams/main/ui/CheckQualityReportActivity.kt b/background/src/main/java/com/gyf/csams/main/ui/CheckQualityReportActivity.kt index 57070af..e9973a6 100644 --- a/background/src/main/java/com/gyf/csams/main/ui/CheckQualityReportActivity.kt +++ b/background/src/main/java/com/gyf/csams/main/ui/CheckQualityReportActivity.kt @@ -15,13 +15,14 @@ import androidx.lifecycle.viewmodel.compose.viewModel import com.google.accompanist.insets.ExperimentalAnimatedInsets import com.gyf.csams.R import com.gyf.csams.main.model.CheckQualityReportViewModel +import com.gyf.csams.module.MAX_SCORE +import com.gyf.csams.module.QualityReportVo import com.gyf.csams.uikit.RowItem import com.gyf.csams.uikit.TestTable import com.gyf.lib.uikit.BaseTextField import com.gyf.lib.uikit.ScaffoldModel import com.gyf.lib.util.BottomButton -import com.gyf.lib.util.MAX_SCORE -import com.gyf.lib.util.QualityReportVo + /** * 审批质量报告单 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 e57e1bf..e0d5dc4 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 @@ -16,10 +16,11 @@ import androidx.lifecycle.viewmodel.compose.viewModel import com.gyf.csams.R import com.gyf.csams.account.model.LoginViewModel import com.gyf.csams.main.model.MenuType +import com.gyf.csams.module.ClientType +import com.gyf.csams.module.ManagerInfoVo import com.gyf.lib.service.BaseActivity import com.gyf.lib.uikit.* -import com.gyf.lib.util.ClientType -import com.gyf.lib.util.ManagerInfoVo + import com.gyf.lib.util.TokenManager class MainActivity : BaseActivity() { diff --git a/background/src/main/java/com/gyf/csams/main/ui/ManagementOfficerActivity.kt b/background/src/main/java/com/gyf/csams/main/ui/ManagementOfficerActivity.kt index 9d4ab5f..85ecfdf 100644 --- a/background/src/main/java/com/gyf/csams/main/ui/ManagementOfficerActivity.kt +++ b/background/src/main/java/com/gyf/csams/main/ui/ManagementOfficerActivity.kt @@ -21,11 +21,11 @@ import androidx.compose.ui.unit.dp import androidx.lifecycle.viewmodel.compose.viewModel import com.gyf.csams.R import com.gyf.csams.main.model.ManagementOfficerModel +import com.gyf.csams.module.ManagerInfoVo import com.gyf.lib.uikit.Body import com.gyf.lib.uikit.MainColumnFrame import com.gyf.lib.uikit.Profile import com.gyf.lib.uikit.ScaffoldModel -import com.gyf.lib.util.ManagerInfoVo import com.orhanobut.logger.Logger /** diff --git a/background/src/main/java/com/gyf/csams/main/ui/ManagerActActivity.kt b/background/src/main/java/com/gyf/csams/main/ui/ManagerActActivity.kt index f4c53fb..51f6cea 100644 --- a/background/src/main/java/com/gyf/csams/main/ui/ManagerActActivity.kt +++ b/background/src/main/java/com/gyf/csams/main/ui/ManagerActActivity.kt @@ -16,11 +16,13 @@ import androidx.compose.ui.unit.dp import com.google.accompanist.insets.ExperimentalAnimatedInsets import com.gyf.csams.R import com.gyf.csams.main.model.ManagerActViewModel +import com.gyf.csams.module.MAX_SCORE +import com.gyf.csams.module.ManagerActVo import com.gyf.csams.uikit.RowItem import com.gyf.csams.uikit.TestTable -import com.gyf.lib.util.ActivityVo -import com.gyf.lib.util.MAX_SCORE -import com.gyf.lib.util.format +import com.gyf.lib.util.DateTimeUtil.datetimeFormat +import java.util.* + /** * 查看活动信息 @@ -40,19 +42,15 @@ class ManagerActActivity : ComponentActivity() { } @Composable - private fun ActivityTable(vo: ActivityVo) { + private fun ActivityTable(vo: ManagerActVo) { val baseHeight = 50.dp RowItem( modifier = Modifier.height(baseHeight), - key = R.string.activity_id, value = "${vo.activityId}" - ) - RowItem( - modifier = Modifier.height(baseHeight), - key = R.string.activity_name, value = vo.activityName + key = R.string.activity_name, value = vo.activityVo.activityName ) RowItem( modifier = Modifier.height(baseHeight), - key = R.string.activity_association, value = vo.association + key = R.string.activity_association, value = vo.association.name ) RowItem(modifier = Modifier.height(baseHeight), key = R.string.activity_evaluate) { Row( @@ -70,11 +68,11 @@ class ManagerActActivity : ComponentActivity() { } RowItem( modifier = Modifier.height(baseHeight), - key = R.string.activity_time, value = vo.activityTime.format() + key = R.string.activity_time, value = Date(vo.activityVo.activityTime).datetimeFormat() ) RowItem( modifier = Modifier.height(baseHeight * 2), - key = R.string.activity_location, value = vo.location + key = R.string.activity_location, value = vo.activityVo.activityAddress ) } } \ No newline at end of file diff --git a/background/src/main/java/com/gyf/csams/main/ui/NotificationActivity.kt b/background/src/main/java/com/gyf/csams/main/ui/NotificationActivity.kt index 0260864..5ee56a0 100644 --- a/background/src/main/java/com/gyf/csams/main/ui/NotificationActivity.kt +++ b/background/src/main/java/com/gyf/csams/main/ui/NotificationActivity.kt @@ -15,10 +15,11 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import androidx.lifecycle.viewmodel.compose.viewModel import com.gyf.csams.main.model.BackgroundViewModel +import com.gyf.csams.module.NotificationVo import com.gyf.lib.uikit.Body import com.gyf.lib.uikit.MainColumnFrame -import com.gyf.lib.util.NotificationVo -import com.gyf.lib.util.format +import com.gyf.lib.util.DateTimeUtil.datetimeFormat + import java.util.* /** @@ -72,7 +73,7 @@ class NotificationActivity : ComponentActivity() { Spacer(modifier = Modifier.height(10.dp)) Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.End) { - Text(text = Date(content.createTime).format()) + Text(text = Date(content.createTime).datetimeFormat()) } } } diff --git a/background/src/main/java/com/gyf/csams/main/ui/RenameActivity.kt b/background/src/main/java/com/gyf/csams/main/ui/RenameActivity.kt index 9e53a51..13b1cc5 100644 --- a/background/src/main/java/com/gyf/csams/main/ui/RenameActivity.kt +++ b/background/src/main/java/com/gyf/csams/main/ui/RenameActivity.kt @@ -16,12 +16,12 @@ import androidx.lifecycle.viewmodel.compose.viewModel import com.google.accompanist.insets.ExperimentalAnimatedInsets import com.gyf.csams.R import com.gyf.csams.main.model.RenameViewModel +import com.gyf.csams.module.RenameVo import com.gyf.csams.uikit.RowItem import com.gyf.csams.uikit.TestTable import com.gyf.lib.uikit.BaseTextField import com.gyf.lib.uikit.ScaffoldModel import com.gyf.lib.util.BottomButton -import com.gyf.lib.util.RenameVo class RenameActivity : ComponentActivity() { diff --git a/background/src/main/java/com/gyf/csams/uikit/CheckForm.kt b/background/src/main/java/com/gyf/csams/uikit/CheckForm.kt new file mode 100644 index 0000000..14e32bd --- /dev/null +++ b/background/src/main/java/com/gyf/csams/uikit/CheckForm.kt @@ -0,0 +1,266 @@ +package com.gyf.csams.uikit + +import androidx.annotation.StringRes +import androidx.compose.foundation.layout.* +import androidx.compose.material.ExperimentalMaterialApi +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.livedata.observeAsState +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import androidx.lifecycle.viewmodel.compose.viewModel +import com.google.accompanist.insets.ExperimentalAnimatedInsets +import com.gyf.csams.R +import com.gyf.csams.main.model.BaseAuditViewModel +import com.gyf.csams.module.AuditVo +import com.gyf.csams.module.Duty +import com.gyf.csams.module.ManagerVo +import com.gyf.lib.uikit.* +import com.gyf.lib.util.BottomButton +import com.gyf.lib.util.TokenManager + +val BASE_HEIGHT = 50.dp + +@ExperimentalMaterialApi +@ExperimentalAnimatedInsets +@Composable +inline fun > ContentCheckForm( + @StringRes title: Int, + crossinline RegisterForm: @Composable (vo: T) -> Unit +) { + ImeBody { + val model: E = viewModel() + val data by model.data.observeAsState() + TestTableImeSimple( + title = title + ) { + data?.forEach { + item { + RegisterForm(vo = it) + CheckForm(vo = it) + Spacer(modifier = Modifier.height(10.dp)) + } + } + } + } +} + +/** + * 表格审核组件 + * + * @param VO + * @param M + * @param vo + * @param scaffoldModel + * @param model + * @param first + * @param last + */ +@Composable +inline fun > CheckForm( + vo: VO, + scaffoldModel: ScaffoldModel = viewModel(), + model: M = viewModel(), + first: @Composable () -> Unit = { + RowItem( + modifier = Modifier.height(BASE_HEIGHT), + key = R.string.first_approver, + value = vo.audit.manager?.name ?: "" + ) + }, + last: @Composable () -> Unit = { + RowItem( + modifier = Modifier.height(BASE_HEIGHT), + key = R.string.last_approver, + value = vo.audit.nextAudit?.manager?.name ?: "" + ) + } +) { + + + (TokenManager.getOwnInfo() as? ManagerVo)?.let { it -> + var confirmDesc: Int? = null + var backDesc: Int? = null + var onConfirm: (() -> Unit)? = null + var onBack: (() -> Unit)? = null + val check: (result: Boolean, cause: StringForm) -> Unit = + { result: Boolean, cause: StringForm -> + scaffoldModel.update( + message = "确认${if (result) "上报" else "驳回"}?", + actionLabel = "确认" + ) { + model.check( + auditId = vo.audit.id, + result = result, + cause = cause.formValue.value + ?: throw IllegalArgumentException("无法获取审核理由") + ) { + scaffoldModel.update(message = it, actionLabel = "刷新") { + model.load { } + } + } + } + } + + val accept: (m: String) -> Unit = + { m: String -> + scaffoldModel.update("确认${m}?", actionLabel = "确认") { + model.accept( + auditId = vo.audit.id + ) { + scaffoldModel.update(message = it, actionLabel = "刷新") { + model.load { } + } + } + } + } + + val doCheck: @Composable () -> Unit = { + val cause = ValidStringForm( + formDesc = "审核理由", + textLength = 20 + ) + val statusForm by cause.statusForm.observeAsState() + + onConfirm = { + if (statusForm == FormStatus.Empty) { + scaffoldModel.update("${cause.formDesc}不能为空", actionLabel = "知道了") + } else { + check(true, cause) + } + } + onBack = { + if (statusForm == FormStatus.Empty) { + scaffoldModel.update("${cause.formDesc}不能为空", actionLabel = "知道了") + } else { + check(false, cause) + } + } + + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.Center + ) { + BaseTextField( + form = cause + ) + } + } + + when { + //初审记录,负责人为空 等待初审 + vo.audit.nextAudit == null && vo.audit.manager == null -> { + if (it.duty == Duty.PamphaBhusal) { + confirmDesc = R.string.accept_btn + onConfirm = { accept("受理") } + } + first() + RowItem(key = R.string.first_approver_origin, value = "") + RowItem(key = R.string.first_result, value = "") + last() + RowItem(key = R.string.last_approver_origin, value = "") + RowItem(key = R.string.last_result, value = "") + RowItem( + modifier = Modifier.height(BASE_HEIGHT), + key = R.string.audit_phases, value = "等待初审" + ) + } + //初审记录,负责人不为空 初审受理 + vo.audit.nextAudit == null && vo.audit.manager != null -> { + + first() + if (it.duty == Duty.PamphaBhusal) { + confirmDesc = R.string.reported_btn + backDesc = R.string.reject_btn + + doCheck() + } else { + RowItem(key = R.string.first_approver_origin, value = "") + } + RowItem(key = R.string.first_result, value = "") + last() + RowItem(key = R.string.last_approver_origin, value = "") + RowItem(key = R.string.last_result, value = "") + RowItem( + modifier = Modifier.height(BASE_HEIGHT), + key = R.string.audit_phases, value = "初审受理" + ) + } + //初审记录,审核通过(上报) 等待复审 + vo.audit.nextAudit != null && vo.audit.nextAudit?.manager == null -> { + + if (it.duty == Duty.Teacher) { + confirmDesc = R.string.recheck_btn + onConfirm = { accept("复审") } + } + first() + RowItem(key = R.string.first_approver_origin, value = vo.audit.cause) + RowItem(key = R.string.first_result, value = "通过") + last() + RowItem(key = R.string.last_approver_origin, value = "") + RowItem(key = R.string.last_result, value = "") + RowItem( + modifier = Modifier.height(BASE_HEIGHT), + key = R.string.audit_phases, value = "等待复审" + ) + } + //复审记录,审核结果为空 复审受理 + vo.audit.nextAudit != null && vo.audit.nextAudit?.result == null -> { + first() + RowItem(key = R.string.first_approver_origin, value = vo.audit.cause) + RowItem(key = R.string.first_result, value = "通过") + last() + if (it.duty == Duty.Teacher) { + confirmDesc = R.string.allow_btn + backDesc = R.string.reject_btn + doCheck() + } else { + RowItem(key = R.string.last_approver_origin, value = "") + } + RowItem(key = R.string.last_result, value = "") + RowItem( + modifier = Modifier.height(BASE_HEIGHT), + key = R.string.audit_phases, value = "复审受理" + ) + } + else -> { + first() + RowItem(key = R.string.first_approver_origin, value = vo.audit.cause) + RowItem( + key = R.string.first_result, value = when (vo.audit.result) { + null -> "" + true -> "通过" + false -> "不通过" + } + ) + last() + RowItem( + key = R.string.last_approver_origin, + value = vo.audit.nextAudit?.cause ?: "" + ) + RowItem( + key = R.string.last_result, value = when (vo.audit.nextAudit?.result) { + null -> "" + true -> "通过" + false -> "不通过" + } + ) + RowItem( + modifier = Modifier.height(BASE_HEIGHT), + key = R.string.audit_phases, value = "完成审核" + ) + } + } + + if (confirmDesc != null) { + BottomButton( + confirmDesc = confirmDesc, + backDesc = backDesc, + modifier = Modifier.fillMaxWidth(), + onBack = onBack + ) { + onConfirm?.let { it() } + } + } + } +} \ No newline at end of file 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 1ab38d1..b1f8e48 100644 --- a/background/src/main/java/com/gyf/csams/uikit/Table.kt +++ b/background/src/main/java/com/gyf/csams/uikit/Table.kt @@ -2,7 +2,6 @@ package com.gyf.csams.uikit import androidx.annotation.StringRes import androidx.compose.foundation.border -import androidx.compose.foundation.gestures.scrollBy import androidx.compose.foundation.layout.* import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyListScope @@ -13,6 +12,7 @@ import androidx.compose.runtime.livedata.observeAsState import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color +import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp @@ -93,16 +93,17 @@ fun TestTableImeSimple( val listState = rememberLazyListState() val insets = LocalWindowInsets.current - val imeBottom = with(LocalDensity.current) { insets.ime.bottom.toDp() } + //TODO 解决键盘遮挡问题 + val isVisible = with(LocalDensity.current) { insets.ime.isVisible } + val bottom = with(LocalDensity.current) { insets.ime.bottom.toDp() } LazyColumn( - modifier = Modifier.fillMaxSize(), + modifier = Modifier + .fillMaxSize() + .nestedScroll(connection = rememberImeNestedScrollConnection()), + contentPadding = PaddingValues(vertical = 10.dp), state = listState, content = content ) - LaunchedEffect(imeBottom) { - listState.scrollBy(imeBottom.value) - } - } } diff --git a/foreground/src/main/java/com/gyf/csams/InitActivity.kt b/foreground/src/main/java/com/gyf/csams/InitActivity.kt index d364379..b5b2986 100644 --- a/foreground/src/main/java/com/gyf/csams/InitActivity.kt +++ b/foreground/src/main/java/com/gyf/csams/InitActivity.kt @@ -4,10 +4,11 @@ import android.app.Activity import com.google.gson.reflect.TypeToken import com.gyf.csams.account.ui.AccountActivity import com.gyf.csams.main.ui.MainActivity +import com.gyf.csams.module.UserVo import com.gyf.lib.uikit.AbstractInitActivity import com.gyf.lib.util.AccountApi import com.gyf.lib.util.ApiResponse -import com.gyf.lib.util.UserVo + import java.lang.reflect.Type class InitActivity : AbstractInitActivity() { 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 fd11abd..8af1f50 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 @@ -3,6 +3,7 @@ package com.gyf.csams.account.model import android.app.Activity import android.app.Application import android.os.Build +import androidx.lifecycle.AndroidViewModel import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.viewModelScope @@ -10,6 +11,10 @@ import com.google.gson.reflect.TypeToken import com.gyf.csams.R import com.gyf.csams.account.ui.AccountActivity import com.gyf.csams.account.ui.AccountRoute +import com.gyf.csams.module.ClientType +import com.gyf.csams.module.UserLoginVo +import com.gyf.csams.module.UserRegVo +import com.gyf.csams.module.UserVo import com.gyf.lib.model.AbstractLoginViewModel import com.gyf.lib.uikit.FormStatus import com.gyf.lib.uikit.ValidStringForm @@ -23,9 +28,9 @@ import kotlinx.coroutines.launch * 密码弹窗信息 * * @property message - * @property userPasswordVo + * @property password */ -data class DialogMessage(val message: String, val userPasswordVo: UserPasswordVo?) +data class DialogMessage(val message: String, val password: String) /** * 注册表单 @@ -60,7 +65,10 @@ class AccountViewModel(application: Application) : AbstractLoginViewModel(applic private var checkJob: Job? = null //姓名 - val name = object : ValidStringForm(formDesc = "姓名", textLength = 4) { + val name = object : ValidStringForm( + formDesc = "姓名", + textLength = application.resources.getInteger(R.integer.name_length) + ) { override fun check() { _statusForm.value = FormStatus.Valid checkForm() @@ -164,18 +172,18 @@ class AccountViewModel(application: Application) : AbstractLoginViewModel(applic val url = Api.buildUrl(AccountApi.Register) Logger.i("开始$regBtnDesc,请求接口:$url") HttpClient.post( - url, HttpCallback( + url, HttpCallback( action = regBtnDesc, onSuccess = { _dialogMsg.postValue( DialogMessage( message = it.message, - userPasswordVo = it.body + password = it.body ?: throw IllegalArgumentException("无法获取生成密码") ) ) }, onFail = onFail, - typeToken = object : TypeToken>() {}.type + typeToken = object : TypeToken>() {}.type ), jsonParam = UserRegVo( studentId = id.formValue.value ?: throw IllegalArgumentException("学号为空"), @@ -198,4 +206,28 @@ class AccountViewModel(application: Application) : AbstractLoginViewModel(applic } +} + +class RefreshViewModel(application: Application) : AndroidViewModel(application) { + + private val _refresh = MutableLiveData() + val refresh: LiveData = _refresh + + fun refresh() { + viewModelScope.launch { + HttpClient.post( + url = Api.buildUrl(AccountApi.Refresh), + callback = HttpCallback(action = "刷新个人信息", onSuccess = { it -> + it.body.let { + if (it != null) { + TokenManager.update(it) + } + _refresh.postValue(it != null) + } + + }, typeToken = object : TypeToken>() {}.type), + jsonParam = OnlyToken(clientType = ClientType.Foreground) + ) + } + } } \ No newline at end of file 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 d7a917c..b8ddc09 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 @@ -240,7 +240,7 @@ class AccountActivity : ComponentActivity() { private fun RegisterDialog(accountViewModel: AccountViewModel = viewModel()) { val dialogMsg: DialogMessage? by accountViewModel.dialogMsg.observeAsState(null) - val message = dialogMsg?.userPasswordVo?.password + val message = dialogMsg?.password if (message?.isNotEmpty() == true) { PasswordDialog(message = message) } 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 a5af518..5c943a7 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 @@ -4,14 +4,16 @@ import android.app.Application import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel -import androidx.lifecycle.viewModelScope +import com.gyf.csams.module.ActivityDetailVo +import com.gyf.csams.module.ActivityPhotoVo +import com.gyf.csams.module.BBSVo +import com.gyf.csams.module.UserInfoVo import com.gyf.csams.uikit.AbstractComment import com.gyf.csams.uikit.ActivityDetailMenu import com.gyf.csams.uikit.TopMenuInterface import com.gyf.lib.model.ScrollViewModel import com.gyf.lib.uikit.ValidStringForm -import com.gyf.lib.util.* -import kotlinx.coroutines.launch +import com.gyf.lib.util.NOT_IMPL_TIP /** * 活动详情菜单通用状态 @@ -57,16 +59,7 @@ class ActivityInfoViewModel : ViewModel() { } private fun loadInfo() { - viewModelScope.launch { - _activityDetailVo.value = ActivityDetailVo( - activityName = randomChinese(4), - associationName = randomChinese(4), - activityTime = randomDateTime(), - activityLocation = randomChinese(3), - activityDesc = randomChinese(500) - ) - } - + TODO() } } 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 6139403..7e83963 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 @@ -7,6 +7,7 @@ import android.graphics.BitmapFactory import androidx.lifecycle.AndroidViewModel import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.viewModelScope import com.baidu.mapapi.map.* import com.baidu.mapapi.model.LatLng import com.baidu.mapapi.model.LatLngBounds @@ -17,44 +18,25 @@ import com.baidu.mapapi.search.poi.* import com.baidu.mapapi.search.sug.SuggestionResult import com.baidu.mapapi.search.sug.SuggestionSearch import com.baidu.mapapi.search.sug.SuggestionSearchOption +import com.google.gson.reflect.TypeToken import com.gyf.csams.BuildConfig import com.gyf.csams.MyLocationListener 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.gyf.csams.module.* +import com.gyf.lib.uikit.* +import com.gyf.lib.util.* +import com.gyf.lib.util.ApiResponse +import com.gyf.lib.util.DateTimeUtil.DATE_FORMAT +import com.gyf.lib.util.DateTimeUtil.TIME_FORMAT +import com.gyf.lib.util.DateTimeUtil.dateFormat +import com.gyf.lib.util.DateTimeUtil.timeFormat +import com.gyf.lib.util.DateTimeUtil.toDate import com.orhanobut.logger.Logger import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch import java.util.* -class SizeForm(val application: Application) : - StringForm(formDesc = application.getString(R.string.activity_size), textLength = 2) { - - val _formError = MutableLiveData() - val formError: LiveData = _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 = "" - } - - } -} - /** * 申请活动数据状态管理 * @@ -65,20 +47,48 @@ class SizeForm(val application: Application) : */ class ApplyActViewModel(application: Application) : AndroidViewModel(application) { val activityName = - StringForm(formDesc = application.getString(R.string.activity_name), textLength = 10) - val activityTime = StringForm( + AsyncStringForm(formDesc = application.getString(R.string.activity_name), textLength = 10) + val activityDate = AsyncStringForm( + formDesc = application.getString(R.string.activity_date), + textLength = DATE_FORMAT.length + ) + val activityTime = AsyncStringForm( formDesc = application.getString(R.string.activity_time), - textLength = DATETIME_FORMAT.length + textLength = TIME_FORMAT.length ) + val activityAddress = - StringForm(formDesc = application.getString(R.string.activity_address), textLength = 30) + AsyncStringForm( + formDesc = application.getString(R.string.activity_address), + textLength = 30 + ) val activityDesc = - StringForm(formDesc = application.getString(R.string.activity_desc), textLength = 50) + AsyncStringForm(formDesc = application.getString(R.string.activity_desc), textLength = 50) + + val activitySize = object : + AsyncStringForm(formDesc = application.getString(R.string.activity_size), textLength = 2) { + val maxActivitySize = application.resources.getInteger(R.integer.activity_size) + override fun check() { + _formValue.value?.let { + when { + it.matches(Regex("\\d+")) && it.toInt() !in 1..maxActivitySize -> _statusForm.value = + FormStatus.FormatError + else -> _statusForm.value = FormStatus.Valid + } + } + + } + } + + private val _checkInfo = MutableLiveData>() + val checkInfo: LiveData> = _checkInfo - val activitySize = SizeForm(application = application) + init { + read { } + } val city = - object : StringForm(formDesc = application.getString(R.string.city), textLength = 4) { + object : ValidStringForm(formDesc = application.getString(R.string.city), textLength = 4) { override val formPlaceholder = "" } @@ -102,6 +112,7 @@ class ApplyActViewModel(application: Application) : AndroidViewModel(application }) } + //TODO 抽离到单独的activity model? lateinit var scaffoldModel: ScaffoldModel private val _mapView = MutableLiveData() @@ -128,7 +139,6 @@ class ApplyActViewModel(application: Application) : AndroidViewModel(application _selectPoi.postValue(null) } - fun searchPoiInCity() { if (city.formValue.value?.isEmpty() == true || address.formValue.value?.isEmpty() == true @@ -164,13 +174,6 @@ class ApplyActViewModel(application: Application) : AndroidViewModel(application val mapStatusUpdate = MapStatusUpdateFactory.newLatLng(latLng) map.setMapStatus(mapStatusUpdate) - // 清除之前的 -// clearData() - - // 显示当前的 -// if (!showSuggestMarker(latLng)) { -// searchPoiInCity() -// } } } @@ -377,7 +380,7 @@ class ApplyActViewModel(application: Application) : AndroidViewModel(application mBaiduMap.addOverlay(markerOptions) } - fun isLatlngEqual(latLng0: LatLng, latLng1: LatLng): Boolean { + private fun isLatlngEqual(latLng0: LatLng, latLng1: LatLng): Boolean { return (latLng0.latitude == latLng1.latitude && latLng0.longitude == latLng1.longitude) } @@ -559,7 +562,8 @@ class ApplyActViewModel(application: Application) : AndroidViewModel(application clearData() } - private fun destroy() { + override fun onCleared() { + super.onCleared() mPoiSearch.destroy() mSuggestionSearch.destroy() @@ -569,11 +573,82 @@ class ApplyActViewModel(application: Application) : AndroidViewModel(application mBitmapDescWaterDrop?.recycle() } + + private fun clean() { + activityName.clean() + activityDate.clean() + activityTime.clean() + activityDesc.clean() + activitySize.clean() + activityAddress.clean() + } + /** - * TODO 提交申请 + * 提交申请 * */ fun apply(callback: (message: String) -> Unit) { - callback(NOT_IMPL_TIP) + val activityName = activityName.formValue.value ?: throw IllegalArgumentException("活动名称为空") + val activityDate = activityDate.formValue.value ?: throw IllegalArgumentException("活动日期为空") + val activityTime = activityTime.formValue.value ?: throw IllegalArgumentException("活动时间为空") + val activityDesc = activityDesc.formValue.value ?: throw IllegalArgumentException("活动介绍为空") + val activitySize = activitySize.formValue.value ?: throw IllegalArgumentException("活动规模为空") + val activityAddress = + activityAddress.formValue.value ?: throw IllegalArgumentException("活动地点为空") + val associationId = (TokenManager.getOwnInfo() as? UserVo)?.associationVo?.associationId + ?: throw IllegalArgumentException("社团id为空") + viewModelScope.launch { + HttpClient.post( + url = Api.buildUrl(ActivityApi.Register), + callback = HttpCallback(action = "提交活动申请书", onSuccess = { + if (it.body == true) { + clean() + } + callback(it.message) + }, typeToken = object : TypeToken>() {}.type), + jsonParam = ActivityApplyVo( + associationId = associationId, + activityVo = ActivityVo( + activityName = activityName, + activityTime = "$activityDate $activityTime".toDate().time, + activityAddress = activityAddress, + activityDesc = activityDesc, + activitySize = activitySize.toInt() + ), + activityId = _checkInfo.value?.body?.activityId, + token = TokenManager.getToken() + ) + ) + } } + + + /** + * 查看审核进度 + * + * @param callback + */ + private fun read(callback: (message: String) -> Unit) { + viewModelScope.launch { + HttpClient.post(url = Api.buildUrl(ActivityApi.Read), + HttpCallback(action = "查看活动申请书审核进度", + onSuccess = { it -> + _checkInfo.postValue(it) + it.body?.activityVo?.let { + activityName.setValue(it.activityName) + val d = Date(it.activityTime) + activityDate.setValue(d.dateFormat()) + activityTime.setValue(d.timeFormat()) + activityAddress.setValue(it.activityAddress) + activityDesc.setValue(it.activityDesc) + activitySize.setValue(it.activitySize.toString()) + } + }, typeToken = object : TypeToken>() {}.type + ), + jsonParam = OnlyToken(clientType = ClientType.Foreground) + ) + } + } + + } \ No newline at end of file diff --git a/foreground/src/main/java/com/gyf/csams/activity/ui/ActivityDetailActivity.kt b/foreground/src/main/java/com/gyf/csams/activity/ui/ActivityDetailActivity.kt index 8b9ec7b..25d7d34 100644 --- a/foreground/src/main/java/com/gyf/csams/activity/ui/ActivityDetailActivity.kt +++ b/foreground/src/main/java/com/gyf/csams/activity/ui/ActivityDetailActivity.kt @@ -22,15 +22,18 @@ import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable import com.gyf.csams.R import com.gyf.csams.activity.model.* +import com.gyf.csams.module.ActivityPhotoVo +import com.gyf.csams.module.BBSVo +import com.gyf.csams.module.UserInfoVo import com.gyf.csams.uikit.* import com.gyf.lib.uikit.MainColumnFrame import com.gyf.lib.uikit.NavBody import com.gyf.lib.uikit.ScaffoldModel import com.gyf.lib.uikit.ShowSnackbar -import com.gyf.lib.util.ActivityPhotoVo -import com.gyf.lib.util.BBSVo -import com.gyf.lib.util.UserInfoVo -import com.gyf.lib.util.format + +import com.gyf.lib.util.DateTimeUtil.datetimeFormat +import java.util.* + /** * 活动详情 @@ -140,10 +143,10 @@ class ActivityDetailActivity : ComponentActivity() { modifier = Modifier.fillMaxSize(), verticalArrangement = Arrangement.SpaceAround ) { - RectListItem(text = it.associationName) - RectListItem(text = it.activityName) - RectListItem(text = it.activityTime.format()) - RectListItem(text = it.activityLocation) + RectListItem(text = it.associationVo.name) + RectListItem(text = it.activityVo.activityName) + RectListItem(text = Date(it.activityVo.activityTime).datetimeFormat()) + RectListItem(text = it.activityVo.activityAddress) } } @@ -184,7 +187,10 @@ class ActivityDetailActivity : ComponentActivity() { Column(modifier = modifier) { val activityDetailVo by model.activityDetailVo.observeAsState() activityDetailVo?.let { - DescCard(modifier = Modifier.weight(0.5F), content = it.activityDesc) + DescCard( + modifier = Modifier.weight(0.5F), + content = it.activityVo.activityDesc + ) } } } @@ -440,7 +446,7 @@ class ActivityDetailActivity : ComponentActivity() { verticalArrangement = Arrangement.SpaceEvenly ) { Text(text = vo.name) - Text(text = vo.createTime.format()) + Text(text = vo.createTime.datetimeFormat()) } } Spacer(modifier = Modifier.weight(0.5F)) diff --git a/foreground/src/main/java/com/gyf/csams/activity/ui/ApplyActActivity.kt b/foreground/src/main/java/com/gyf/csams/activity/ui/ApplyActActivity.kt index 21bb1e2..dc2ce69 100644 --- a/foreground/src/main/java/com/gyf/csams/activity/ui/ApplyActActivity.kt +++ b/foreground/src/main/java/com/gyf/csams/activity/ui/ApplyActActivity.kt @@ -13,16 +13,14 @@ import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.material.* -import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.getValue +import androidx.compose.runtime.* import androidx.compose.runtime.livedata.observeAsState -import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalFocusManager import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.input.ImeAction import androidx.compose.ui.text.input.KeyboardType import androidx.compose.ui.unit.dp import androidx.compose.ui.viewinterop.AndroidView @@ -33,19 +31,21 @@ import com.baidu.location.LocationClientOption import com.baidu.mapapi.map.MapStatusUpdateFactory import com.baidu.mapapi.search.sug.SuggestionResult import com.google.android.material.datepicker.MaterialDatePicker +import com.google.android.material.timepicker.MaterialTimePicker +import com.google.android.material.timepicker.MaterialTimePicker.INPUT_MODE_KEYBOARD +import com.google.android.material.timepicker.TimeFormat import com.gyf.csams.MainApplication import com.gyf.csams.MyLocationListener import com.gyf.csams.R import com.gyf.csams.activity.model.ApplyActViewModel +import com.gyf.csams.module.CheckStatus import com.gyf.csams.uikit.Background import com.gyf.csams.uikit.BackgroundImage +import com.gyf.csams.uikit.CheckTip import com.gyf.csams.uikit.DescCard -import com.gyf.lib.uikit.BaseTextField -import com.gyf.lib.uikit.Body -import com.gyf.lib.uikit.MainColumnFrame -import com.gyf.lib.uikit.ScaffoldModel +import com.gyf.lib.uikit.* import com.gyf.lib.util.BottomButton -import com.gyf.lib.util.format +import com.gyf.lib.util.DateTimeUtil.dateFormat import com.orhanobut.logger.Logger import kotlinx.coroutines.launch import java.util.* @@ -87,7 +87,7 @@ class ApplyActActivity : AppCompatActivity() { model.scaffoldModel = scaffoldModel val showMap by model.showMap.observeAsState(false) val location by MyLocationListener.location.observeAsState() - + val checkInfo by model.checkInfo.observeAsState() when { showMap && location != null -> { Box { @@ -133,19 +133,35 @@ class ApplyActActivity : AppCompatActivity() { ) } } - } - } } else -> { - Title(modifier = Modifier.weight(0.2F)) + checkInfo?.body?.auditCheckVo.let { + if (it == null) { + Title(modifier = Modifier.weight(0.2F)) + } else { + Title() + CheckTip(it, modifier = Modifier.weight(0.15F)) + } + } Row( Modifier .weight(0.1F) .fillMaxWidth(), horizontalArrangement = Arrangement.Center ) { - BaseTextField(form = model.activityName) + BaseTextField( + form = model.activityName, + readOnly = isReadOnly(model = model) + ) + } + Row( + Modifier + .weight(0.1F) + .fillMaxWidth(), + horizontalArrangement = Arrangement.Center + ) { + ActivityDate() } Row( Modifier @@ -162,13 +178,9 @@ class ApplyActActivity : AppCompatActivity() { ) DescCard( modifier = Modifier.weight(0.3F), - stringForm = model.activityDesc + stringForm = model.activityDesc, + readonly = isReadOnly(model = model) ) - //TODO 活动人数不合法警告 -// val error by model.activitySize.formError.observeAsState() -// if (error?.isNotEmpty() == true) { -// scaffoldModel.update(message = error) -// } Row( Modifier .weight(0.1F) @@ -177,12 +189,35 @@ class ApplyActActivity : AppCompatActivity() { BaseTextField( form = model.activitySize, keyboardOptions = - KeyboardOptions.Default.copy(keyboardType = KeyboardType.Number) + KeyboardOptions.Default.copy( + keyboardType = KeyboardType.Number, + imeAction = ImeAction.Done + ), + readOnly = isReadOnly(model = model) ) } Spacer(modifier = Modifier.weight(0.05F)) - BottomButton(modifier = Modifier.fillMaxWidth()) { - model.apply { scaffoldModel.update(message = it) } + val activityName = model.activityName.statusForm.observeAsState() + val activityDate = model.activityDate.statusForm.observeAsState() + val activityTime = model.activityTime.statusForm.observeAsState() + val activityDesc = model.activityDesc.statusForm.observeAsState() + val activitySize = model.activitySize.statusForm.observeAsState() + BottomButton( + modifier = Modifier.fillMaxWidth(), + enabled = check( + activityName, + activityDate, + activityTime, + activityDesc, + activitySize + ), + confirmDesc = if (checkInfo?.body != null) R.string.reg_again_btn else R.string.confirm_btn, + ) { + model.apply { + scaffoldModel.update(message = it, actionLabel = "返回") { + onBackPressed() + } + } } } } @@ -191,6 +226,23 @@ class ApplyActActivity : AppCompatActivity() { } } + @Composable + private fun isReadOnly(model: ApplyActViewModel): Boolean { + val checkInfo by model.checkInfo.observeAsState() + val flag = (checkInfo?.body?.let { it.auditCheckVo.checkStatus != CheckStatus.Finish }) + Logger.d("flag=${flag}") + return flag == true + } + + private fun check(vararg arrayOfStates: State): Boolean { + arrayOfStates.forEach { + if (it.value != FormStatus.Valid) { + return false + } + } + return true + } + @Composable private fun SelectIcon(modifier: Modifier = Modifier) { IconButton(modifier = modifier, onClick = { @@ -233,16 +285,6 @@ class ApplyActActivity : AppCompatActivity() { BaseTextField(modifier = Modifier.weight(0.5F), form = model.address) } } -// Row( -// modifier = Modifier.fillMaxWidth(), -// horizontalArrangement = Arrangement.Center -// ) { -// OutlinedButton(onClick = { -// model.searchPoiInCity() -// }) { -// Text(text = stringResource(id = R.string.search_btn)) -// } -// } } @@ -363,11 +405,40 @@ class ApplyActActivity : AppCompatActivity() { Box(modifier = modifier.fillMaxWidth(), contentAlignment = Alignment.Center) { Text( text = stringResource(id = R.string.activity_application), - style = MaterialTheme.typography.h4 + style = MaterialTheme.typography.h6 ) } } + @Composable + private fun ActivityDate( + modifier: Modifier = Modifier, + model: ApplyActViewModel = viewModel() + ) { + val onClick: () -> Unit = { + MaterialDatePicker.Builder.datePicker().build().apply { + show(supportFragmentManager, tag) + addOnPositiveButtonClickListener { + model.activityDate.onChange(Date(it).dateFormat()) + } + } + } + BaseTextField( + modifier = modifier.clickable(onClick = onClick), + form = model.activityDate, + readOnly = true + ) { + if (!isReadOnly(model = model)) { + IconButton(onClick = onClick) { + Icon( + painter = painterResource(id = R.drawable.ic_date), + contentDescription = null + ) + } + } + } + } + /** * 活动时间 * @@ -380,28 +451,39 @@ class ApplyActActivity : AppCompatActivity() { model: ApplyActViewModel = viewModel() ) { val scope = rememberCoroutineScope() + val onClick: () -> Unit = { + scope.launch { + MaterialTimePicker.Builder() + .setInputMode(INPUT_MODE_KEYBOARD) + .setTimeFormat(TimeFormat.CLOCK_24H) + .build() + .apply { + show(supportFragmentManager, tag) + addOnPositiveButtonClickListener { + model.activityTime.onChange( + "${ + String.format( + "%02d", + hour + ) + }:${String.format("%02d", minute)}" + ) + } + } + } + } BaseTextField( - modifier = modifier, - form = model.activityTime, readOnly = true + modifier = modifier.clickable(onClick = onClick), + form = model.activityTime, + readOnly = true ) { - IconButton(onClick = { - scope.launch { - val picker = MaterialDatePicker - .Builder - .datePicker() - .setSelection(Date().time) - .build() - picker.show(supportFragmentManager, picker.toString()) - picker.addOnPositiveButtonClickListener { - model.activityTime.onChange(Date(it).format()) - } + if (!isReadOnly(model = model)) { + IconButton(onClick = onClick) { + Icon( + painter = painterResource(id = R.drawable.ic_clock), + contentDescription = null + ) } - - }) { - Icon( - painter = painterResource(id = R.drawable.ic_date), - contentDescription = null - ) } } } @@ -471,25 +553,27 @@ class ApplyActActivity : AppCompatActivity() { } BaseTextField(modifier = modifier, form = model.activityAddress, readOnly = true) { - IconButton(onClick = { - when (PackageManager.PERMISSION_GRANTED) { - checkSelfPermissions() -> { - // Some works that require permission - requestLocation() - model.openMap() - Logger.i("准备打开地图") - } - else -> { - // Asking for permission - Logger.i("询问权限") - launcher.launch(location_permissions) + if (!isReadOnly(model = model)) { + IconButton(onClick = { + when (PackageManager.PERMISSION_GRANTED) { + checkSelfPermissions() -> { + // Some works that require permission + requestLocation() + model.openMap() + Logger.i("准备打开地图") + } + else -> { + // Asking for permission + Logger.i("询问权限") + launcher.launch(location_permissions) + } } + }) { + Icon( + painter = painterResource(id = R.drawable.ic_icon_location), + contentDescription = null + ) } - }) { - Icon( - painter = painterResource(id = R.drawable.ic_icon_location), - contentDescription = null - ) } } } 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 72b99ad..dc71572 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 @@ -6,11 +6,14 @@ import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.google.gson.reflect.TypeToken +import com.gyf.csams.R +import com.gyf.csams.module.* import com.gyf.csams.uikit.AssociationMenu import com.gyf.csams.uikit.TopMenuInterface import com.gyf.lib.model.ScrollViewModel import com.gyf.lib.uikit.StringForm import com.gyf.lib.util.* +import com.gyf.lib.util.ApiResponse import kotlinx.coroutines.launch @@ -35,7 +38,7 @@ class AssociationViewModel : ViewModel(), TopMenuInterface { HttpCallback(action = "获取社团信息", onSuccess = { it.body?.let { _associationVo.postValue(it) } }, typeToken = object : TypeToken>() {}.type), - jsonParam = ShowAssociationVo(id = id) + jsonParam = ShowAssociationVo(id = id, token = TokenManager.getToken()) ) } } @@ -61,7 +64,8 @@ class AssociationViewModel : ViewModel(), TopMenuInterface { * */ class MemberViewModel(application: Application) : ScrollViewModel(application) { - val name = StringForm(formDesc = "姓名关键字", 5) + val name = + StringForm(formDesc = "姓名关键字", application.resources.getInteger(R.integer.name_length)) override val initSize: Int = 10 @@ -81,7 +85,11 @@ class MemberViewModel(application: Application) : ScrollViewModel(ap }, typeToken = object : TypeToken>>() {}.type ), - jsonParam = QueryAssociationMembers(id = id, name = name.formValue.value) + jsonParam = QueryAssociationMembers( + id = id, + name = name.formValue.value, + token = TokenManager.getToken() + ) ) } } 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 3204fe8..e1fdd70 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 @@ -3,12 +3,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.module.ChoiceQuestionVo +import com.gyf.csams.module.Exam +import com.gyf.csams.module.ExamType import com.gyf.lib.model.ScrollViewModel import com.gyf.lib.uikit.StringForm -import com.gyf.lib.util.* -import kotlinx.coroutines.launch -import kotlin.random.Random +import com.gyf.lib.util.NOT_IMPL_TIP /** * 题库界面类型 @@ -64,6 +64,10 @@ class ExamViewModel(application: Application) : ScrollViewModel(applicatio load() } + fun createQuestion(): StringForm { + return StringForm(formDesc = "问题", textLength = QUESTION_TEXT_LENGTH) + } + /** * 切换题型 * @@ -81,21 +85,7 @@ class ExamViewModel(application: Application) : ScrollViewModel(applicatio * @return */ private fun createExam(type: ExamType): Exam { - val question = StringForm(formDesc = "问题", textLength = QUESTION_TEXT_LENGTH) - return when (type) { - ExamType.CQ -> ChoiceQuestionVo( - answers = ('A'..'D').map { - StringForm( - formDesc = "选项", - textLength = ANSWER_TEXT_LENGTH, - value = "选项$it" - ) - }, - rightAnswer = 0, - question = question - ) - ExamType.OQ -> OpenQuestionsVo(question = question) - } + TODO("创建题目") } @@ -140,42 +130,7 @@ class ExamViewModel(application: Application) : ScrollViewModel(applicatio * */ fun load() { - viewModelScope.launch { - _data.value?.apply { - repeat(initSize) { - if (Random.nextBoolean()) { - add( - OpenQuestionsVo( - question = StringForm( - formDesc = "问题", - textLength = QUESTION_TEXT_LENGTH, - value = "这是一道开放题:$size" - ) - ) - ) - } else { - add( - ChoiceQuestionVo( - question = StringForm( - formDesc = "问题", - textLength = QUESTION_TEXT_LENGTH, - value = "这是一道选择题:$size" - ), - answers = ('A'..'D').map { - StringForm( - formDesc = "选项", - textLength = ANSWER_TEXT_LENGTH, - value = "选项$it" - ) - }, - rightAnswer = Random.nextInt(ANSWER_SIZE) - ) - ) - } - - } - } - } + TODO("加载题目") } /** 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 5bae642..eb99023 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 @@ -12,9 +12,12 @@ import coil.imageLoader import coil.request.ImageRequest import com.google.gson.reflect.TypeToken import com.gyf.csams.MainApplication +import com.gyf.csams.module.AssociationCheckVo +import com.gyf.csams.module.AssociationRegVo +import com.gyf.csams.module.ClientType import com.gyf.lib.BuildConfig +import com.gyf.lib.uikit.AsyncStringForm import com.gyf.lib.uikit.FormStatus -import com.gyf.lib.uikit.ValidStringForm import com.gyf.lib.util.* import com.orhanobut.logger.Logger import kotlinx.coroutines.launch @@ -22,19 +25,13 @@ import java.io.File import java.io.FileOutputStream import java.io.InputStream -class TestStringForm(formDesc: String, textLength: Int) : ValidStringForm(formDesc, textLength) { - - fun setValue(value: String) { - _formValue.postValue(value) - } -} class RegAssociationViewModel(application: Application) : AndroidViewModel(application) { val frameDesc = "社团注册资料" - val name = TestStringForm(formDesc = "社团名称", textLength = 5) - val desc = TestStringForm(formDesc = "社团简介", textLength = 30) + val name = AsyncStringForm(formDesc = "社团名称", textLength = 5) + val desc = AsyncStringForm(formDesc = "社团简介", textLength = 30) private val _picture = MutableLiveData() val picture: LiveData = _picture @@ -42,8 +39,8 @@ class RegAssociationViewModel(application: Application) : AndroidViewModel(appli private val _fileId = MutableLiveData() val fileId: LiveData = _fileId - private val _checkInfo = MutableLiveData() - val checkInfo: LiveData = _checkInfo + private val _checkInfo = MutableLiveData>() + val checkInfo: LiveData> = _checkInfo val picturePlaceHolder = "请上传图片" @@ -74,17 +71,18 @@ class RegAssociationViewModel(application: Application) : AndroidViewModel(appli HttpClient.post( Api.buildUrl(AssociationApi.Read), HttpCallback(action = "加载历史注册资料", onSuccess = { it -> + _checkInfo.postValue(it) it.body?.let { it -> - name.setValue(it.name) - desc.setValue(it.desc) - _checkInfo.postValue(it) + name.setValue(it.associationVo.name) + desc.setValue(it.associationVo.desc) + val context = getApplication() val request = ImageRequest.Builder(context) - .data("${BuildConfig.SERVER_ADDRESS}/${it.logo}") + .data("${BuildConfig.SERVER_ADDRESS}/${it.associationVo.logo}") .target( onSuccess = { result -> - it.logo.split("/").apply { + it.associationVo.logo.split("/").apply { File.createTempFile(last(), null, context.cacheDir).apply { Logger.d("文件路径:${absolutePath}") FileOutputStream(this).use { @@ -146,6 +144,13 @@ class RegAssociationViewModel(application: Application) : AndroidViewModel(appli } } + + private fun clean() { + name.clean() + desc.clean() + _picture.postValue(null) + } + /** * * @@ -164,18 +169,18 @@ class RegAssociationViewModel(application: Application) : AndroidViewModel(appli HttpCallback("注册社团", onSuccess = { Logger.i(it.message) callback(it.message) - name.clean() - desc.clean() - _picture.postValue(null) + if (it.body == true) { + clean() + } }, onFail = { Logger.e(it) }, typeToken = object : TypeToken>() {}.type), - jsonParam = - AssociationRegVo( + jsonParam = AssociationRegVo( name = nameValue, desc = descValue, fileId = fileId, - id = checkInfo.value?.id + associationId = _checkInfo.value?.body?.associationVo?.associationId, + token = TokenManager.getToken() ) ) } diff --git a/foreground/src/main/java/com/gyf/csams/association/ui/AssociationActivity.kt b/foreground/src/main/java/com/gyf/csams/association/ui/AssociationActivity.kt index 15318d9..f9fbb1e 100644 --- a/foreground/src/main/java/com/gyf/csams/association/ui/AssociationActivity.kt +++ b/foreground/src/main/java/com/gyf/csams/association/ui/AssociationActivity.kt @@ -30,9 +30,10 @@ import com.gyf.csams.R import com.gyf.csams.activity.ui.ActivityDetailActivity import com.gyf.csams.activity.ui.ApplyActActivity import com.gyf.csams.association.model.* +import com.gyf.csams.module.HistoryActVo import com.gyf.csams.uikit.* import com.gyf.lib.uikit.* -import com.gyf.lib.util.HistoryActVo +import com.gyf.lib.util.TokenManager /** @@ -73,76 +74,90 @@ class AssociationActivity : ComponentActivity() { onDismissRequest = { }, properties = PopupProperties() ) { - DropdownMenuItem(onClick = { - startActivity( - Intent( - this@AssociationActivity, - ApplyActActivity::class.java - ) - ) - model.close() - }) { - Row(verticalAlignment = Alignment.CenterVertically) { - Text(text = getString(R.string.apply_act_menu)) - Icon( - painter = painterResource(id = R.drawable.ic_add_fill), - contentDescription = null - ) - } - } - DropdownMenuItem(onClick = { - intent.apply { - putExtra( - ExamActivityType::name.name, - ExamActivityType.SET_EXAM - ) - } - startActivity(intent) - model.close() - }) { - Row(verticalAlignment = Alignment.CenterVertically) { - Text(text = getString(R.string.set_exam_menu)) - Icon( - painter = painterResource(id = R.drawable.ic_editor), - contentDescription = null - ) - } - } - DropdownMenuItem(onClick = { - startActivity( - Intent( - this@AssociationActivity, - ReNameActivity::class.java - ) - ) - model.close() - }) { - Row(verticalAlignment = Alignment.CenterVertically) { - Text(text = getString(R.string.rename_menu)) - Icon( - painter = painterResource(id = R.drawable.ic_exchange_rate), - contentDescription = null - ) - } - } - DropdownMenuItem(onClick = { - intent.apply { - putExtra( - ExamActivityType::name.name, - ExamActivityType.JOIN_Association - ) + + when { + TokenManager.getUserInfo()?.associationVo?.associationId == associationId && TokenManager.getUserInfo()?.isHead == true -> { + DropdownMenuItem(onClick = { + + startActivity( + Intent( + this@AssociationActivity, + ApplyActActivity::class.java + ).apply { + putExtra( + AssociationActivity::javaClass.name, + associationId + ) + } + ) + + model.close() + }) { + Row(verticalAlignment = Alignment.CenterVertically) { + Text(text = getString(R.string.apply_act_menu)) + Icon( + painter = painterResource(id = R.drawable.ic_add_fill), + contentDescription = null + ) + } + } + DropdownMenuItem(onClick = { + intent.apply { + putExtra( + ExamActivityType::name.name, + ExamActivityType.SET_EXAM + ) + } + startActivity(intent) + model.close() + }) { + Row(verticalAlignment = Alignment.CenterVertically) { + Text(text = getString(R.string.set_exam_menu)) + Icon( + painter = painterResource(id = R.drawable.ic_editor), + contentDescription = null + ) + } + } + DropdownMenuItem(onClick = { + startActivity( + Intent( + this@AssociationActivity, + ReNameActivity::class.java + ) + ) + model.close() + }) { + Row(verticalAlignment = Alignment.CenterVertically) { + Text(text = getString(R.string.rename_menu)) + Icon( + painter = painterResource(id = R.drawable.ic_exchange_rate), + contentDescription = null + ) + } + } } - startActivity(intent) - model.close() - }) { - Row(verticalAlignment = Alignment.CenterVertically) { - Text(text = getString(R.string.join_association)) - Icon( - painter = painterResource(id = R.drawable.ic_add_account), - contentDescription = null - ) + TokenManager.getUserInfo()?.associationVo == null -> DropdownMenuItem( + onClick = { + intent.apply { + putExtra( + ExamActivityType::name.name, + ExamActivityType.JOIN_Association + ) + } + startActivity(intent) + model.close() + }) { + Row(verticalAlignment = Alignment.CenterVertically) { + Text(text = getString(R.string.join_association)) + Icon( + painter = painterResource(id = R.drawable.ic_add_account), + contentDescription = null + ) + } } } + DropdownMenuItem(onClick = { model.close() }) { diff --git a/foreground/src/main/java/com/gyf/csams/association/ui/ExamActivity.kt b/foreground/src/main/java/com/gyf/csams/association/ui/ExamActivity.kt index fc60b1a..17873f1 100644 --- a/foreground/src/main/java/com/gyf/csams/association/ui/ExamActivity.kt +++ b/foreground/src/main/java/com/gyf/csams/association/ui/ExamActivity.kt @@ -21,6 +21,9 @@ import com.gyf.csams.R import com.gyf.csams.association.model.ANSWER_SIZE import com.gyf.csams.association.model.ExamActivityType import com.gyf.csams.association.model.ExamViewModel +import com.gyf.csams.module.ChoiceQuestionVo +import com.gyf.csams.module.Exam +import com.gyf.csams.module.OpenQuestionsVo import com.gyf.csams.uikit.Background import com.gyf.csams.uikit.BackgroundImage import com.gyf.lib.uikit.BaseTextField @@ -28,9 +31,6 @@ import com.gyf.lib.uikit.Body import com.gyf.lib.uikit.MainColumnFrame import com.gyf.lib.uikit.ScaffoldModel import com.gyf.lib.util.BottomButton -import com.gyf.lib.util.ChoiceQuestionVo -import com.gyf.lib.util.Exam -import com.gyf.lib.util.OpenQuestionsVo /** @@ -173,9 +173,15 @@ class ExamActivity : ComponentActivity() { * @param exam */ @Composable - private fun Question(modifier: Modifier = Modifier, exam: Exam) { + private fun Question( + modifier: Modifier = Modifier, + exam: Exam, + model: ExamViewModel = viewModel() + ) { + /*问题**/ + val s = model.createQuestion() BaseTextField( - form = exam.question, + form = s, modifier = modifier .fillMaxSize() .background(color = MaterialTheme.colors.background) @@ -202,7 +208,7 @@ class ExamActivity : ComponentActivity() { ) { IconButton(onClick = { if (isAdd) { - if ((newExam?.question?.formValue?.value ?: "").isNotEmpty()) { + if ((newExam?.question ?: "").isNotEmpty()) { scaffoldModel.update( message = model.addTip, actionLabel = model.actionLabel @@ -321,7 +327,8 @@ class ExamActivity : ComponentActivity() { val isRightAnswer = choiceQuestionVo.rightAnswer == answerIndex RadioButton(selected = isRightAnswer, onClick = click) - BaseTextField(form = it) + val c = model.createQuestion() + BaseTextField(form = c) } } } diff --git a/foreground/src/main/java/com/gyf/csams/association/ui/RegAssociationActivity.kt b/foreground/src/main/java/com/gyf/csams/association/ui/RegAssociationActivity.kt index f82c7f1..0c831e1 100644 --- a/foreground/src/main/java/com/gyf/csams/association/ui/RegAssociationActivity.kt +++ b/foreground/src/main/java/com/gyf/csams/association/ui/RegAssociationActivity.kt @@ -1,7 +1,6 @@ package com.gyf.csams.association.ui import android.Manifest -import android.app.Activity import android.content.Intent import android.content.pm.PackageManager import android.net.Uri @@ -24,23 +23,19 @@ import androidx.compose.runtime.livedata.observeAsState import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.painterResource -import androidx.compose.ui.text.buildAnnotatedString -import androidx.compose.ui.text.withStyle -import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.core.content.ContextCompat import androidx.lifecycle.viewmodel.compose.viewModel import com.google.accompanist.coil.rememberCoilPainter import com.gyf.csams.R import com.gyf.csams.association.model.RegAssociationViewModel +import com.gyf.csams.module.CheckStatus import com.gyf.csams.uikit.Background import com.gyf.csams.uikit.BackgroundImage +import com.gyf.csams.uikit.CheckTip import com.gyf.lib.uikit.* import com.gyf.lib.util.BottomButton -import com.gyf.lib.util.CheckStatus -import com.gyf.lib.util.format import com.orhanobut.logger.Logger -import java.util.* /** @@ -51,97 +46,70 @@ class RegAssociationActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { - Body { - MainColumnFrame(background = { - Background( - BackgroundImage.RegAssociation, - alpha = 0.5F - ) - }) { - Spacer( - modifier = Modifier - .weight(0.1F) - ) - Title() - Tip() - Name() - Desc( - modifier = Modifier - .weight(0.1F) - .fillMaxWidth() - ) - Spacer(modifier = Modifier.weight(0.05F)) - Logo( - modifier = Modifier - .weight(0.2F) - .fillMaxWidth() - ) - Spacer(modifier = Modifier.weight(0.05F)) + val model: RegAssociationViewModel = viewModel() + val checkInfo by model.checkInfo.observeAsState() + checkInfo?.body.let { it -> + if (it?.auditCheckVo?.checkStatus == CheckStatus.Finish && it.auditCheckVo.result) { + setResult(RESULT_OK, Intent().apply { + putExtra(RegAssociationActivity::class.java.name, CheckStatus.Finish.name) + }) + onBackPressed() + } else { + Body { + MainColumnFrame(background = { + Background( + BackgroundImage.RegAssociation, + alpha = 0.5F + ) + }) { + Spacer( + modifier = Modifier + .weight(0.1F) + ) + Title() + it?.auditCheckVo?.let { CheckTip(it) } + Name() + Desc( + modifier = Modifier + .weight(0.1F) + .fillMaxWidth() + ) + Spacer(modifier = Modifier.weight(0.05F)) + Logo( + modifier = Modifier + .weight(0.2F) + .fillMaxWidth() + ) + Spacer(modifier = Modifier.weight(0.05F)) - val model: RegAssociationViewModel = viewModel() - val scaffoldModel: ScaffoldModel = viewModel() - val name by model.name.statusForm.observeAsState() - val desc by model.name.statusForm.observeAsState() - val fileId by model.fileId.observeAsState() - val checkInfo by model.checkInfo.observeAsState() - BottomButton( - modifier = Modifier.fillMaxWidth(), - enabled = name == FormStatus.Valid && desc == FormStatus.Valid && fileId != null, - confirmDesc = if (checkInfo != null) R.string.reg_again_btn else R.string.reg_btn, - ) { - model.register { - scaffoldModel.update(message = it, actionLabel = "返回") { - finish() - } - } - } - Spacer(modifier = Modifier.weight(0.05F)) - } - } + val scaffoldModel: ScaffoldModel = viewModel() + val name by model.name.statusForm.observeAsState() + val desc by model.name.statusForm.observeAsState() + val fileId by model.fileId.observeAsState() - } - } + BottomButton( + modifier = Modifier.fillMaxWidth(), + enabled = name == FormStatus.Valid && desc == FormStatus.Valid && fileId != null, + confirmDesc = if (it != null) R.string.reg_again_btn else R.string.reg_btn, - @Composable - private fun Tip(model: RegAssociationViewModel = viewModel()) { - val checkInfo by model.checkInfo.observeAsState() - checkInfo?.let { - Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.Center) { - when (val status = it.checkStatus) { - CheckStatus.Finish -> Text(buildAnnotatedString { - withStyle(style = MaterialTheme.typography.h5.toParagraphStyle()) { - append("您于${Date(it.applyTime).format()}提交的${model.frameDesc}审核不通过原因如下:\n") - } - withStyle( - style = MaterialTheme.typography.h6.copy(color = MaterialTheme.colors.error) - .toParagraphStyle() - ) { - append("初审意见:${it.firstCause}\n") - it.lastCause?.let { - append("复审意见:${it}") + ) { + model.register { + scaffoldModel.update(message = it, actionLabel = "返回") { + finish() + } + } } + Spacer(modifier = Modifier.weight(0.05F)) } - }) - else -> { - Text( - text = status.desc, style = - MaterialTheme.typography.h5.copy(color = MaterialTheme.colors.primary) - ) } } } } - } - @Preview - @Composable - private fun TestPreview9() { - Text(text = "123", color = MaterialTheme.colors.error) - } /** @@ -164,7 +132,7 @@ class RegAssociationActivity : ComponentActivity() { val resultLauncher = rememberLauncherForActivityResult(contract = ActivityResultContracts.StartActivityForResult()) { when (it.resultCode) { - Activity.RESULT_OK -> { + RESULT_OK -> { it.data?.data?.apply { Logger.i("uri=$this") @@ -227,8 +195,7 @@ class RegAssociationActivity : ComponentActivity() { Image( painter = logo, contentDescription = null ) - val checkInfo by model.checkInfo.observeAsState() - if (checkInfo == null || checkInfo?.checkStatus == CheckStatus.Finish) { + if (!isReadOnly(model = model)) { Column( modifier = Modifier.fillMaxHeight(), verticalArrangement = Arrangement.SpaceEvenly @@ -285,16 +252,23 @@ class RegAssociationActivity : ComponentActivity() { } } + @Composable + private fun isReadOnly(model: RegAssociationViewModel): Boolean { + val checkInfo by model.checkInfo.observeAsState() + val flag = (checkInfo?.body?.let { it.auditCheckVo.checkStatus != CheckStatus.Finish }) + Logger.d("flag=${flag}") + return flag == true + } + /** * 社团名称 * @param model */ @Composable private fun Name(model: RegAssociationViewModel = viewModel()) { - val checkInfo by model.checkInfo.observeAsState() BaseTextField( form = model.name, singeLine = true, modifier = Modifier.fillMaxWidth(), - readOnly = checkInfo?.checkStatus != CheckStatus.Finish + readOnly = isReadOnly(model = model) ) } @@ -304,10 +278,9 @@ class RegAssociationActivity : ComponentActivity() { */ @Composable private fun Desc(model: RegAssociationViewModel = viewModel(), modifier: Modifier) { - val checkInfo by model.checkInfo.observeAsState() BaseTextField( form = model.desc, modifier = modifier, - readOnly = checkInfo?.checkStatus != CheckStatus.Finish + readOnly = isReadOnly(model = model) ) } 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 aab6f71..61a5458 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 @@ -3,12 +3,14 @@ package com.gyf.csams.main.model import android.app.Application import androidx.lifecycle.* import com.google.gson.reflect.TypeToken +import com.gyf.csams.module.* import com.gyf.csams.uikit.AbstractComment import com.gyf.lib.model.ScrollViewModel 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.ApiResponse import com.orhanobut.logger.Logger import kotlinx.coroutines.Job import kotlinx.coroutines.delay @@ -42,6 +44,7 @@ class NotificationViewModel(application: Application) : AndroidViewModel(applica jsonParam = NotificationDto( receiverId = TokenManager.getToken().id, receiverClient = ClientType.Foreground, + token = TokenManager.getToken() ) ) } @@ -94,7 +97,8 @@ class MarqueeViewModel : AbstractComment() { }, typeToken = object : TypeToken>() {}.type ), jsonParam = LeaveMessageVo( - message = newContent.formValue.value ?: "" + message = newContent.formValue.value ?: "", + token = TokenManager.getToken() ) ) } @@ -180,7 +184,8 @@ class AssociationListViewModel(application: Application) : ), jsonParam = SearchAssociationVo( name = name.formValue.value ?: "", - desc = desc.formValue.value ?: "" + desc = desc.formValue.value ?: "", + token = TokenManager.getToken() ) ) } @@ -199,14 +204,10 @@ class CenterViewModel : ViewModel() { val myCollectActivity = "我收藏的社团活动" - init { - load() - } private fun load() { viewModelScope.launch { TODO() } - } } 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 d6e9586..4c0ee13 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 @@ -2,7 +2,9 @@ package com.gyf.csams.main.ui import android.content.Intent import android.os.Bundle +import androidx.activity.compose.rememberLauncherForActivityResult import androidx.activity.compose.setContent +import androidx.activity.result.contract.ActivityResultContracts import androidx.compose.foundation.Image import androidx.compose.foundation.border import androidx.compose.foundation.clickable @@ -26,11 +28,16 @@ import androidx.navigation.compose.composable import com.google.accompanist.coil.rememberCoilPainter import com.gyf.csams.R import com.gyf.csams.account.model.AccountViewModel +import com.gyf.csams.account.model.RefreshViewModel import com.gyf.csams.activity.ui.ActivityDetailActivity import com.gyf.csams.association.ui.AssociationActivity import com.gyf.csams.association.ui.RegAssociationActivity import com.gyf.csams.main.model.* -import com.gyf.csams.message.ui.MessageActivity +import com.gyf.csams.message.ui.SysMessageActivity +import com.gyf.csams.module.AssociationVo +import com.gyf.csams.module.CheckStatus +import com.gyf.csams.module.ClientType +import com.gyf.csams.module.UserVo import com.gyf.csams.uikit.* import com.gyf.lib.service.BaseActivity import com.gyf.lib.uikit.* @@ -64,8 +71,13 @@ class MainActivity : BaseActivity() { imageViewModel.cancel() } composable(MainMenu.Center.name) { - Center(navController = nav) - ShowSnackbar(scaffoldState = scaffoldState) + val refresh: RefreshViewModel = viewModel() + refresh.refresh() + val load by refresh.refresh.observeAsState() + load?.let { + Center(navController = nav) + ShowSnackbar(scaffoldState = scaffoldState) + } imageViewModel.cancel() } } @@ -105,12 +117,21 @@ class MainActivity : BaseActivity() { modifier = Modifier.weight(0.7F), verticalArrangement = Arrangement.SpaceEvenly ) { - CenterMenuItem(text = model.myAssociationDesc) { - startActivity(Intent(this@MainActivity, AssociationActivity::class.java)) + (TokenManager.getOwnInfo() as? UserVo)?.associationVo?.associationId?.let { + CenterMenuItem(text = model.myAssociationDesc) { + startActivity( + Intent( + this@MainActivity, + AssociationActivity::class.java + ).apply { + putExtra(AssociationActivity::javaClass.name, it) + }) + } + CenterMenuItem(text = model.myJoinActivity) + CenterMenuItem(text = model.myLikeActivity) + CenterMenuItem(text = model.myCollectActivity) } - CenterMenuItem(text = model.myJoinActivity) - CenterMenuItem(text = model.myLikeActivity) - CenterMenuItem(text = model.myCollectActivity) + CenterMenuItem(text = "退出登录") { accountViewModel.logout(this@MainActivity) { scaffoldModel.update(message = it) @@ -191,7 +212,7 @@ class MainActivity : BaseActivity() { val associationVo: AssociationVo? = (TokenManager.getOwnInfo() as? UserVo)?.associationVo if (associationVo == null) { - RegisterAssociation() + RegisterAssociation(navController = navController) } AssociationSearch() AssociationListBody() @@ -203,7 +224,26 @@ class MainActivity : BaseActivity() { * */ @Composable - private fun RegisterAssociation() { + private fun RegisterAssociation( + model: AssociationListViewModel = viewModel(), + scaffoldModel: ScaffoldModel = viewModel(), + navController: NavHostController + ) { + val launch = + rememberLauncherForActivityResult(contract = ActivityResultContracts.StartActivityForResult()) { it -> + when (it.resultCode) { + RESULT_OK -> { + it.data?.getStringExtra(RegAssociationActivity::class.java.name)?.let { + if (it == CheckStatus.Finish.name) { +// model.load { +// scaffoldModel.update(message = "社团审核通过",actionLabel = "关闭提示") +// } + navController.navigate(MainMenu.List.name) + } + } + } + } + } Row( horizontalArrangement = Arrangement.End, modifier = Modifier @@ -211,7 +251,7 @@ class MainActivity : BaseActivity() { .padding(10.dp) ) { IconButton(onClick = { - startActivity(Intent(this@MainActivity, RegAssociationActivity::class.java)) + launch.launch(Intent(this@MainActivity, RegAssociationActivity::class.java)) }) { Icon( painter = painterResource(id = R.drawable.ic_add_fill), @@ -228,8 +268,7 @@ class MainActivity : BaseActivity() { */ @Composable private fun AssociationListBody( - model: AssociationListViewModel = viewModel(), - scaffoldModel: ScaffoldModel = viewModel() + model: AssociationListViewModel = viewModel() ) { val associationListList: MutableList? by model.data.observeAsState() val listState = rememberLazyListState() @@ -279,7 +318,7 @@ class MainActivity : BaseActivity() { private fun Association(associationVo: AssociationVo) { Card(modifier = Modifier.clickable(onClick = { val intent = Intent(this, AssociationActivity::class.java) - intent.putExtra(AssociationActivity::javaClass.name, associationVo.id) + intent.putExtra(AssociationActivity::javaClass.name, associationVo.associationId) startActivity(intent) })) { val backgroundImage = rememberCoilPainter(request = R.drawable.association_list_border) @@ -362,7 +401,7 @@ class MainActivity : BaseActivity() { .padding(10.dp) ) { IconButton(onClick = { - startActivity(Intent(this@MainActivity, MessageActivity::class.java)) + startActivity(Intent(this@MainActivity, SysMessageActivity::class.java)) }) { Icon( painter = painterResource(id = if (it > 0) R.drawable.ic_notice else R.drawable.ic_notification), diff --git a/foreground/src/main/java/com/gyf/csams/message/model/ForegroundViewModel.kt b/foreground/src/main/java/com/gyf/csams/message/model/ForegroundViewModel.kt index 213ce69..7d97bc4 100644 --- a/foreground/src/main/java/com/gyf/csams/message/model/ForegroundViewModel.kt +++ b/foreground/src/main/java/com/gyf/csams/message/model/ForegroundViewModel.kt @@ -1,8 +1,9 @@ package com.gyf.csams.message.model import android.app.Application +import com.gyf.csams.module.ClientType import com.gyf.lib.model.SysMessageViewModel -import com.gyf.lib.util.ClientType + class ForegroundViewModel(application: Application) : SysMessageViewModel(application) { override fun clientType(): ClientType { diff --git a/foreground/src/main/java/com/gyf/csams/message/ui/SysMessageActivity.kt b/foreground/src/main/java/com/gyf/csams/message/ui/SysMessageActivity.kt index 3b7316f..2f1a0ba 100644 --- a/foreground/src/main/java/com/gyf/csams/message/ui/SysMessageActivity.kt +++ b/foreground/src/main/java/com/gyf/csams/message/ui/SysMessageActivity.kt @@ -20,6 +20,7 @@ import androidx.compose.ui.unit.dp import androidx.lifecycle.viewmodel.compose.viewModel import com.gyf.csams.message.model.ForegroundViewModel import com.gyf.csams.message.model.MessageType +import com.gyf.csams.module.NotificationVo import com.gyf.csams.uikit.Background import com.gyf.csams.uikit.BackgroundImage import com.gyf.csams.uikit.TextTopAppBar @@ -28,8 +29,8 @@ import com.gyf.lib.model.JoinContent import com.gyf.lib.model.RenameContent import com.gyf.lib.uikit.Body import com.gyf.lib.uikit.MainColumnFrame -import com.gyf.lib.util.NotificationVo -import com.gyf.lib.util.format +import com.gyf.lib.util.DateTimeUtil.datetimeFormat + import java.util.* /** @@ -98,7 +99,7 @@ class SysMessageActivity : ComponentActivity() { Spacer(modifier = Modifier.height(10.dp)) Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.End) { - Text(text = Date(content.createTime).format()) + Text(text = Date(content.createTime).datetimeFormat()) } } } 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 362cf38..abb5031 100644 --- a/foreground/src/main/java/com/gyf/csams/uikit/BaseView.kt +++ b/foreground/src/main/java/com/gyf/csams/uikit/BaseView.kt @@ -23,7 +23,9 @@ import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalFocusManager import androidx.compose.ui.res.painterResource +import androidx.compose.ui.text.buildAnnotatedString import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.text.withStyle import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.lifecycle.LiveData @@ -35,8 +37,12 @@ import com.google.accompanist.coil.rememberCoilPainter import com.gyf.csams.MainApplication import com.gyf.csams.R import com.gyf.csams.main.model.MarqueeViewModel +import com.gyf.csams.module.AuditCheckVo +import com.gyf.csams.module.CheckStatus import com.gyf.lib.uikit.* +import com.gyf.lib.util.DateTimeUtil.datetimeFormat import com.orhanobut.logger.Logger +import java.util.* /** @@ -484,7 +490,12 @@ fun Poster(modifier: Modifier = Modifier, imageBitmap: ImageBitmap? = null) { * */ @Composable -fun DescCard(modifier: Modifier, content: String? = null, stringForm: StringForm? = null) { +fun DescCard( + modifier: Modifier, + content: String? = null, + stringForm: StringForm? = null, + readonly: Boolean = false +) { Card( modifier = modifier, backgroundColor = Color.Transparent @@ -504,7 +515,11 @@ fun DescCard(modifier: Modifier, content: String? = null, stringForm: StringForm ) { Spacer(modifier = Modifier.weight(0.15F)) if (stringForm != null) { - BaseTextField(modifier = Modifier.weight(0.65F), form = stringForm) + BaseTextField( + modifier = Modifier.weight(0.65F), + form = stringForm, + readOnly = readonly + ) } else { Text( modifier = Modifier.weight(0.65F), @@ -520,10 +535,37 @@ fun DescCard(modifier: Modifier, content: String? = null, stringForm: StringForm } } -//@Preview +/** + * 资料审核提示 + * + * @param it + */ @Composable -fun AnimationTextPreview() { - AnimationText(text = "6666") +fun CheckTip(it: AuditCheckVo, modifier: Modifier = Modifier) { + Row(modifier = modifier.fillMaxWidth(), horizontalArrangement = Arrangement.Center) { + when (val status = it.checkStatus) { + CheckStatus.Finish -> Text(buildAnnotatedString { + withStyle(style = MaterialTheme.typography.h5.toParagraphStyle()) { + append("您于${Date(it.applyTime).datetimeFormat()}提交的资料审核不通过原因如下:") + } + withStyle( + style = MaterialTheme.typography.h6.copy(color = MaterialTheme.colors.error) + .toParagraphStyle() + ) { + append("初审意见:${it.firstCause}\n") + it.lastCause?.let { + append("复审意见:${it}") + } + } + }) + else -> { + Text( + text = status.desc, style = + MaterialTheme.typography.h5.copy(color = MaterialTheme.colors.primary) + ) + } + } + } } //@Preview diff --git a/foreground/src/main/java/com/gyf/csams/util/GsonUtil.kt b/foreground/src/main/java/com/gyf/csams/util/GsonUtil.kt index 47c6e63..b423fc2 100644 --- a/foreground/src/main/java/com/gyf/csams/util/GsonUtil.kt +++ b/foreground/src/main/java/com/gyf/csams/util/GsonUtil.kt @@ -3,13 +3,12 @@ package com.gyf.csams.util import com.google.gson.* import com.google.gson.reflect.TypeToken import com.gyf.csams.association.model.ANSWER_SIZE -import com.gyf.csams.association.model.ANSWER_TEXT_LENGTH import com.gyf.csams.association.model.QUESTION_TEXT_LENGTH +import com.gyf.csams.module.ChoiceQuestionVo +import com.gyf.csams.module.Exam +import com.gyf.csams.module.ExamType +import com.gyf.csams.module.OpenQuestionsVo import com.gyf.lib.uikit.StringForm -import com.gyf.lib.util.ChoiceQuestionVo -import com.gyf.lib.util.Exam -import com.gyf.lib.util.ExamType -import com.gyf.lib.util.OpenQuestionsVo import java.lang.reflect.Type class OpenQuestionsVoSerializer : JsonSerializer { @@ -21,7 +20,7 @@ class OpenQuestionsVoSerializer : JsonSerializer { val gson = Gson() val c = JsonObject() c.add("examType", gson.toJsonTree(vo?.examType?.name)) - c.add("question", gson.toJsonTree(vo?.question?.formValue?.value)) +// c.add("question", gson.toJsonTree(vo?.question?.formValue?.value)) return c } } @@ -37,7 +36,8 @@ class OpenQuestionsVoDeserializer : JsonDeserializer { val question = StringForm(formDesc = "问题", textLength = QUESTION_TEXT_LENGTH) if (value != null) { question.onChange(value) - return OpenQuestionsVo(question = question) + TODO() +// return OpenQuestionsVo(question = question) } else { throw NullPointerException("问题无法解析!!!!") } @@ -53,7 +53,7 @@ class ChoiceQuestionVoSerializer : JsonSerializer { val gson = Gson() val c = JsonObject() c.add("examType", gson.toJsonTree(vo?.examType?.name)) - c.add("question", gson.toJsonTree(vo?.question?.formValue?.value)) +// c.add("question", gson.toJsonTree(vo?.question?.formValue?.value)) c.add("answers", gson.toJsonTree(vo?.answers)) c.add("rightAnswer", gson.toJsonTree(vo?.rightAnswer)) return c @@ -78,17 +78,18 @@ class ChoiceQuestionVoDeserializer : JsonDeserializer { throw IllegalArgumentException("选项数量!=$QUESTION_TEXT_LENGTH") } val rightAnswer = root.get("rightAnswer").asInt - return ChoiceQuestionVo( - question = question, - answers = answers.map { - StringForm( - formDesc = "选项", - textLength = ANSWER_TEXT_LENGTH, - value = it - ) - }, - rightAnswer = rightAnswer - ) + TODO() +// return ChoiceQuestionVo( +// question = question, +// answers = answers.map { +// StringForm( +// formDesc = "选项", +// textLength = ANSWER_TEXT_LENGTH, +// value = it +// ) +// }, +// rightAnswer = rightAnswer +// ) } else { throw NullPointerException("问题无法解析!!!!") } diff --git a/foreground/src/main/java/com/gyf/csams/util/HttpCallback.kt b/foreground/src/main/java/com/gyf/csams/util/HttpCallback.kt index 49122ba..2148506 100644 --- a/foreground/src/main/java/com/gyf/csams/util/HttpCallback.kt +++ b/foreground/src/main/java/com/gyf/csams/util/HttpCallback.kt @@ -2,8 +2,9 @@ package com.gyf.csams.util import com.google.gson.Gson import com.google.gson.GsonBuilder +import com.gyf.csams.module.Exam import com.gyf.lib.util.ApiResponse -import com.gyf.lib.util.Exam + import com.gyf.lib.util.HttpCallback import java.lang.reflect.Type diff --git a/foreground/src/main/res/drawable/ic_clock.xml b/foreground/src/main/res/drawable/ic_clock.xml new file mode 100644 index 0000000..400e16e --- /dev/null +++ b/foreground/src/main/res/drawable/ic_clock.xml @@ -0,0 +1,9 @@ + + + diff --git a/foreground/src/test/java/com/gyf/csams/ExampleUnitTest.kt b/foreground/src/test/java/com/gyf/csams/ExampleUnitTest.kt index 1d75841..7f442bf 100644 --- a/foreground/src/test/java/com/gyf/csams/ExampleUnitTest.kt +++ b/foreground/src/test/java/com/gyf/csams/ExampleUnitTest.kt @@ -50,8 +50,7 @@ class ExampleUnitTest { @Test fun testLib() { - println(0 in 1..2) - println(1 in 1..2) + } } diff --git a/lib/build.gradle.kts b/lib/build.gradle.kts index 05334b4..a5b28da 100644 --- a/lib/build.gradle.kts +++ b/lib/build.gradle.kts @@ -51,6 +51,8 @@ android { } dependencies { + api(project(":module")) + implementation("androidx.test.ext:junit-ktx:1.1.2") //生命周期组件版本 val lifecycle_version = "2.3.1" //https://developer.android.com/topic/libraries/architecture/workmanager/basics?hl=zh-cn diff --git a/lib/src/androidTest/java/com/gyf/lib/ExampleInstrumentedTest.kt b/lib/src/androidTest/java/com/gyf/lib/ExampleInstrumentedTest.kt index 0b377f0..1e57ac2 100644 --- a/lib/src/androidTest/java/com/gyf/lib/ExampleInstrumentedTest.kt +++ b/lib/src/androidTest/java/com/gyf/lib/ExampleInstrumentedTest.kt @@ -2,7 +2,7 @@ package com.gyf.lib import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.platform.app.InstrumentationRegistry -import org.junit.Assert.* +import org.junit.Assert.assertEquals import org.junit.Test import org.junit.runner.RunWith diff --git a/lib/src/main/java/com/gyf/lib/model/AbstractLoginViewModel.kt b/lib/src/main/java/com/gyf/lib/model/AbstractLoginViewModel.kt index 8891b86..0cb73c8 100644 --- a/lib/src/main/java/com/gyf/lib/model/AbstractLoginViewModel.kt +++ b/lib/src/main/java/com/gyf/lib/model/AbstractLoginViewModel.kt @@ -8,6 +8,9 @@ import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.viewModelScope import com.google.gson.reflect.TypeToken +import com.gyf.csams.module.ClientType +import com.gyf.csams.module.ManagerVo +import com.gyf.csams.module.UserVo import com.gyf.lib.R import com.gyf.lib.uikit.ValidStringForm import com.gyf.lib.util.* @@ -66,8 +69,14 @@ abstract class AbstractLoginViewModel(application: Application) : AndroidViewMod it.body?.let { val db = AppDatabase.getInstance(context) viewModelScope.launch { - TokenManager.init(it) - db?.tokenDao()?.save(token = it.token) + TokenManager.update(it) + db?.tokenDao()?.save( + clientToken = ClientToken( + id = it.token.id, + token = it.token.token, + createTime = it.token.createTime + ) + ) }.invokeOnCompletion { _finishLogin.postValue(true) } @@ -85,8 +94,14 @@ abstract class AbstractLoginViewModel(application: Application) : AndroidViewMod it.body?.let { val db = AppDatabase.getInstance(context) viewModelScope.launch { - TokenManager.init(it) - db?.tokenDao()?.save(token = it.token) + TokenManager.update(it) + db?.tokenDao()?.save( + clientToken = ClientToken( + id = it.token.id, + token = it.token.token, + createTime = it.token.createTime + ) + ) }.invokeOnCompletion { _finishLogin.postValue(true) } diff --git a/lib/src/main/java/com/gyf/lib/model/InitViewModel.kt b/lib/src/main/java/com/gyf/lib/model/InitViewModel.kt index d7e4633..48fb206 100644 --- a/lib/src/main/java/com/gyf/lib/model/InitViewModel.kt +++ b/lib/src/main/java/com/gyf/lib/model/InitViewModel.kt @@ -6,6 +6,8 @@ import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.viewModelScope import com.google.gson.reflect.TypeToken +import com.gyf.csams.module.OwnInfoVo +import com.gyf.csams.module.Token import com.gyf.lib.util.* import com.orhanobut.logger.Logger import kotlinx.coroutines.launch @@ -50,7 +52,7 @@ class InitViewModel(application: Application) : AndroidViewModel(application) { val db = AppDatabase.getInstance(context) val tokenList = db?.tokenDao()?.queryAll() if (tokenList != null && tokenList.size == 1) { - val currentToken: Token = tokenList[0] + val currentClientToken: Token = tokenList[0] val url = Api.buildUrl(api) val action = "校验token" Logger.i("${action}api=$url") @@ -61,7 +63,7 @@ class InitViewModel(application: Application) : AndroidViewModel(application) { onSuccess = { it -> it.body?.let { Logger.i("token校验结果:${it}") - TokenManager.init(it) + TokenManager.update(it) onSuccess() } @@ -70,7 +72,7 @@ class InitViewModel(application: Application) : AndroidViewModel(application) { Logger.e(it) onFail() }, typeToken = typeToken), - jsonParam = currentToken + jsonParam = currentClientToken ) } else if (tokenList != null && tokenList.size > 1) { diff --git a/lib/src/main/java/com/gyf/lib/model/SysMessageViewModel.kt b/lib/src/main/java/com/gyf/lib/model/SysMessageViewModel.kt index 8659ef4..02ef3eb 100644 --- a/lib/src/main/java/com/gyf/lib/model/SysMessageViewModel.kt +++ b/lib/src/main/java/com/gyf/lib/model/SysMessageViewModel.kt @@ -5,6 +5,9 @@ import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.viewModelScope import com.google.gson.reflect.TypeToken +import com.gyf.csams.module.ClientType +import com.gyf.csams.module.NotificationDto +import com.gyf.csams.module.NotificationVo import com.gyf.lib.util.* import com.orhanobut.logger.Logger import kotlinx.coroutines.launch @@ -118,10 +121,8 @@ abstract class SysMessageViewModel(application: Application) : ), jsonParam = NotificationDto( receiverId = TokenManager.getToken().id, - receiverClient = clientType(), page = PageDto( - currentPage = _currentPage.value ?: 1, - pageSize = initSize - ) + receiverClient = clientType(), + token = TokenManager.getToken() ) ) } diff --git a/lib/src/main/java/com/gyf/lib/service/BaseActivity.kt b/lib/src/main/java/com/gyf/lib/service/BaseActivity.kt index 958e25f..7ef78cf 100644 --- a/lib/src/main/java/com/gyf/lib/service/BaseActivity.kt +++ b/lib/src/main/java/com/gyf/lib/service/BaseActivity.kt @@ -3,7 +3,8 @@ package com.gyf.lib.service import android.content.Intent import android.os.Bundle import androidx.activity.ComponentActivity -import com.gyf.lib.util.ClientType +import com.gyf.csams.module.ClientType + abstract class BaseActivity : ComponentActivity() { diff --git a/lib/src/main/java/com/gyf/lib/service/MessageService.kt b/lib/src/main/java/com/gyf/lib/service/MessageService.kt index 316e0e6..c25cdf2 100644 --- a/lib/src/main/java/com/gyf/lib/service/MessageService.kt +++ b/lib/src/main/java/com/gyf/lib/service/MessageService.kt @@ -6,6 +6,9 @@ import androidx.core.app.NotificationCompat import androidx.core.app.NotificationManagerCompat import com.google.gson.Gson import com.google.gson.reflect.TypeToken +import com.gyf.csams.module.ClientType +import com.gyf.csams.module.NotificationDto +import com.gyf.csams.module.NotificationVo import com.gyf.lib.R import com.gyf.lib.util.* import com.orhanobut.logger.Logger @@ -32,16 +35,22 @@ class MessageService : JobIntentService() { } override fun onHandleWork(intent: Intent) { - HttpClient.postAsync>( - url = Api.buildUrl(NotificationApi.Pull), - jsonParam = NotificationDto( - receiverId = TokenManager.getToken().id, - receiverClient = clientType - ), - type = object : TypeToken>>() {}.type - )?.let { it1 -> - Logger.i("拉取最新通知") - it1.body?.forEach { + val token = try { + TokenManager.getToken() + } catch (e: Exception) { + throw IllegalArgumentException("通知服务非法调用,请先初始化token") + } + HttpClient.postAsync>( + url = Api.buildUrl(NotificationApi.Pull), + jsonParam = NotificationDto( + receiverId = token.id, + receiverClient = clientType, + token = token + ), + type = object : TypeToken>>() {}.type + )?.let { it1 -> + Logger.i("拉取最新通知") + it1.body?.forEach { Logger.i("构造通知【${it.title}】") val builder = NotificationCompat.Builder(applicationContext, NotificationUtil.CHANNEL_ID) diff --git a/lib/src/main/java/com/gyf/lib/uikit/AbstractInitActivity.kt b/lib/src/main/java/com/gyf/lib/uikit/AbstractInitActivity.kt index fe51c67..7c5cf17 100644 --- a/lib/src/main/java/com/gyf/lib/uikit/AbstractInitActivity.kt +++ b/lib/src/main/java/com/gyf/lib/uikit/AbstractInitActivity.kt @@ -9,10 +9,11 @@ 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.module.OwnInfoVo import com.gyf.lib.BuildConfig import com.gyf.lib.model.InitViewModel import com.gyf.lib.util.AccountApi -import com.gyf.lib.util.OwnInfoVo + import com.orhanobut.logger.Logger import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.delay diff --git a/lib/src/main/java/com/gyf/lib/uikit/BaseTextField.kt b/lib/src/main/java/com/gyf/lib/uikit/BaseTextField.kt index 2c93c38..dca5404 100644 --- a/lib/src/main/java/com/gyf/lib/uikit/BaseTextField.kt +++ b/lib/src/main/java/com/gyf/lib/uikit/BaseTextField.kt @@ -88,6 +88,19 @@ open class ValidStringForm(formDesc: String, textLength: Int) : StringForm(formD } } +/** + * + * 异步更新值 + * @param formDesc + * @param textLength + */ +open class AsyncStringForm(formDesc: String, textLength: Int) : + ValidStringForm(formDesc, textLength) { + fun setValue(value: String) { + _formValue.postValue(value) + } +} + /** * 通用文本输入框 * diff --git a/lib/src/main/java/com/gyf/lib/uikit/Profile.kt b/lib/src/main/java/com/gyf/lib/uikit/Profile.kt index 84231d3..3240748 100644 --- a/lib/src/main/java/com/gyf/lib/uikit/Profile.kt +++ b/lib/src/main/java/com/gyf/lib/uikit/Profile.kt @@ -11,7 +11,13 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import com.google.accompanist.coil.rememberCoilPainter -import com.gyf.lib.util.* +import com.gyf.csams.module.ManagerInfoVo +import com.gyf.csams.module.ManagerVo +import com.gyf.csams.module.PersonInfoVo +import com.gyf.csams.module.UserVo +import com.gyf.lib.util.Api + +import com.gyf.lib.util.TokenManager @Composable diff --git a/lib/src/main/java/com/gyf/lib/util/Api.kt b/lib/src/main/java/com/gyf/lib/util/Api.kt index 03e2c81..f7bc60b 100644 --- a/lib/src/main/java/com/gyf/lib/util/Api.kt +++ b/lib/src/main/java/com/gyf/lib/util/Api.kt @@ -1,5 +1,6 @@ package com.gyf.lib.util +import com.gyf.csams.module.ClientType import com.gyf.lib.BuildConfig import java.util.* @@ -40,7 +41,10 @@ enum class AccountApi(val path: String) : UrlPath { BackgroundToken("${BackgroundLogin.path}/token"), //登出 - Logout("/logout"); + Logout("/logout"), + + //刷新用户信息 + Refresh("/refresh"); override fun build(): String { @@ -107,6 +111,33 @@ enum class AssociationApi(val path: String) : UrlPath { } } +/** + * 活动接口 + * + * @property path + */ +enum class ActivityApi(val path: String) : UrlPath { + //前台提交活动申请书 + Register("/register"), + + //后台查看活动申请书 + Audit("/audit"), + + //后台受理活动申请书 + Accept("/accept"), + + //后台审核活动申请书 + Check("/check"), + + //审核进度 + Read("/read"); + + + override fun build(): String { + return "/api/activity${this.path}" + } +} + enum class NotificationApi(val path: String) : UrlPath { //通知计数 Count("/count"), diff --git a/lib/src/main/java/com/gyf/lib/util/DateTimeUtil.kt b/lib/src/main/java/com/gyf/lib/util/DateTimeUtil.kt new file mode 100644 index 0000000..72d02e7 --- /dev/null +++ b/lib/src/main/java/com/gyf/lib/util/DateTimeUtil.kt @@ -0,0 +1,53 @@ +package com.gyf.lib.util + +import java.sql.Timestamp +import java.text.SimpleDateFormat +import java.util.* + +object DateTimeUtil { + + const val DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm" + + + const val DATE_FORMAT = "yyyy-MM-dd" + + const val TIME_FORMAT = "HH:mm" + + const val DATETIME_FORMAT = "yyyy-MM-dd HH:mm" + + const val START_TIME = "2021-01-01 00:00" + + fun String.toTimeStamp(pattern: String = DATE_TIME_FORMAT): Timestamp { + return Timestamp(this.toDate(pattern).time) + } + + fun String.toDate(pattern: String = DATE_TIME_FORMAT): Date { + return SimpleDateFormat(pattern, Locale.CHINA).parse(this) + ?: throw IllegalArgumentException("日期字符串按[$pattern]转换失败") + } + + + val startUnix = SimpleDateFormat(DATETIME_FORMAT, Locale.CHINA).parse(START_TIME)?.time + + fun randomDateTime(): Date { + if (startUnix != null) { + return Date("${(startUnix..Date().time).random()}".toLong()) + } else { + throw IllegalArgumentException("生成随机失败,无法获取起始时间") + } + } + + + fun Date.datetimeFormat(): String { + return SimpleDateFormat(DATETIME_FORMAT, Locale.CHINA).format(this) + } + + + fun Date.dateFormat(): String { + return SimpleDateFormat(DATE_FORMAT, Locale.CHINA).format(this) + } + + fun Date.timeFormat(): String { + return SimpleDateFormat(TIME_FORMAT, Locale.CHINA).format(this) + } +} diff --git a/lib/src/main/java/com/gyf/lib/util/HttpUtil.kt b/lib/src/main/java/com/gyf/lib/util/HttpUtil.kt index 6d2cfa0..1876d20 100644 --- a/lib/src/main/java/com/gyf/lib/util/HttpUtil.kt +++ b/lib/src/main/java/com/gyf/lib/util/HttpUtil.kt @@ -1,7 +1,7 @@ package com.gyf.lib.util -import com.google.gson.Gson -import com.google.gson.JsonSyntaxException +import com.google.gson.* +import com.gyf.csams.module.Token import com.orhanobut.logger.Logger import okhttp3.* import okhttp3.MediaType.Companion.toMediaType @@ -9,20 +9,55 @@ import okhttp3.RequestBody.Companion.asRequestBody import okhttp3.RequestBody.Companion.toRequestBody import java.io.File import java.io.IOException +import java.lang.reflect.Field import java.lang.reflect.Type import java.net.SocketTimeoutException -interface TokenInterface { - fun token(): String +object SuperclassExclusionStrategy : ExclusionStrategy { + //序列化反序列化白名单 + val whiteClass = listOf>(Token::class.java) + + override fun shouldSkipClass(arg0: Class<*>?): Boolean { + return false + } + + override fun shouldSkipField(fieldAttributes: FieldAttributes): Boolean { + val fieldName = fieldAttributes.name + val theClass = fieldAttributes.declaringClass + return isFieldInSuperclass(theClass, fieldName) + } + + private fun isFieldInSuperclass(subclass: Class<*>, fieldName: String): Boolean { + var superclass = subclass.superclass + var field: Field? + while (superclass != null && !whiteClass.contains(subclass)) { + field = getField(superclass, fieldName) + if (field != null) return true + superclass = superclass.superclass + } + return false + } + + private fun getField(theClass: Class<*>, fieldName: String): Field? { + return try { + theClass.getDeclaredField(fieldName) + } catch (e: Exception) { + null + } + } } +val HTTP_CALLBACK_GSON_CONFIG: Gson = GsonBuilder() + .addSerializationExclusionStrategy(SuperclassExclusionStrategy) + .addDeserializationExclusionStrategy(SuperclassExclusionStrategy) + .create() + object HttpClient { private val httpClient: OkHttpClient = OkHttpClient() private val JSON_CONTENT_TYPE = "application/json; charset=UTF-8".toMediaType() - private val json = Gson() /** * 构建url查询参数 @@ -80,11 +115,11 @@ object HttpClient { * * @param url * @param callback - * @param jsonParam + * @param jsonParam TODO 改写成reified */ fun post(url: String, callback: Callback, jsonParam: Any) { Logger.i("request url=$url") - val jsonBody = json.toJson(jsonParam) + val jsonBody = HTTP_CALLBACK_GSON_CONFIG.toJson(jsonParam) Logger.json(jsonBody) val request = Request.Builder() .url(url) @@ -96,7 +131,7 @@ object HttpClient { fun postAsync(url: String, jsonParam: Any, type: Type): ApiResponse? { Logger.i("request url=$url") - val jsonBody = json.toJson(jsonParam) + val jsonBody = HTTP_CALLBACK_GSON_CONFIG.toJson(jsonParam) Logger.json(jsonBody) val request = Request.Builder() .url(url) @@ -161,7 +196,7 @@ open class HttpCallback( private val onFail: (error: String) -> Unit = { Logger.e(it) }, private val typeToken: Type ) : Callback, GsonBuilderInterface { - override val gson: Gson = Gson() + override val gson: Gson = HTTP_CALLBACK_GSON_CONFIG override fun onFailure(call: Call, e: IOException) { when (e) { diff --git a/lib/src/main/java/com/gyf/lib/util/RandomUtil.kt b/lib/src/main/java/com/gyf/lib/util/RandomUtil.kt index 529a09b..f8c8ab8 100644 --- a/lib/src/main/java/com/gyf/lib/util/RandomUtil.kt +++ b/lib/src/main/java/com/gyf/lib/util/RandomUtil.kt @@ -1,14 +1,11 @@ package com.gyf.lib.util import okhttp3.internal.toHexString -import java.text.SimpleDateFormat -import java.util.* fun randomNum(length: Int = 8): String { return List(length) { ('0'..'9').random() }.joinToString("") } - fun encode(char: Char) = "\\u${char.toInt().toHexString()}" //unicode ->String @@ -34,23 +31,4 @@ fun randomChinese(length: Int = 8): String { }.joinToString("") } -const val DATETIME_FORMAT = "yyyy-MM-dd HH:mm" - -const val START_TIME = "2021-01-01 00:00" - -val FORMAT = SimpleDateFormat(DATETIME_FORMAT, Locale.US) - -val startUnix = FORMAT.parse(START_TIME)?.time - -fun randomDateTime(): Date { - if (startUnix != null) { - return Date("${(startUnix..Date().time).random()}".toLong()) - } else { - throw IllegalArgumentException("生成随机失败,无法获取起始时间") - } -} - -fun Date.format(): String { - return FORMAT.format(this) -} diff --git a/lib/src/main/java/com/gyf/lib/util/TokenUtil.kt b/lib/src/main/java/com/gyf/lib/util/TokenUtil.kt index d03bd63..51e9082 100644 --- a/lib/src/main/java/com/gyf/lib/util/TokenUtil.kt +++ b/lib/src/main/java/com/gyf/lib/util/TokenUtil.kt @@ -4,43 +4,56 @@ import android.content.Context import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.room.* +import com.gyf.csams.module.* +import com.orhanobut.logger.Logger /** * 登陆令牌 */ @Entity -data class Token( - @PrimaryKey val id: Int, - @ColumnInfo val token: String, - @ColumnInfo val createTime: Long -) +class ClientToken( + @PrimaryKey + override val id: Int, + @ColumnInfo + override val token: String, + @ColumnInfo + override val createTime: Long, +) : Token(token, createTime, id) + data class OnlyToken( override val clientType: ClientType -) : ClientBaseVo() +) : ClientBaseVo() { + override val token: ClientToken = TokenManager.getToken() +} @Dao interface TokenDao { - @Query("select * from token") - suspend fun queryAll(): List + @Query("select * from ClientToken") + suspend fun queryAll(): List @Insert(onConflict = OnConflictStrategy.REPLACE) - suspend fun save(token: Token) + suspend fun save(clientToken: ClientToken) @Delete - suspend fun delete(user: Token) + suspend fun delete(user: ClientToken) - @Query("delete from token") + @Query("delete from ClientToken") suspend fun deleteAll() } + + object TokenManager { private var ownInfo: OwnInfoVo? = null - private lateinit var personInfo: PersonInfoVo - - fun init(ownInfo: OwnInfoVo) { + private var personInfo: PersonInfoVo? = null + private var clientToken: ClientToken? = null + fun update(ownInfo: OwnInfoVo) { this.ownInfo = ownInfo + ownInfo.token.let { + clientToken = ClientToken(id = it.id, token = it.token, createTime = it.createTime) + } when (ownInfo) { is ManagerVo -> this.personInfo = ManagerInfoVo( duty = ownInfo.duty, @@ -50,8 +63,9 @@ object TokenManager { ) is UserVo -> this.personInfo = UserInfoVo(name = ownInfo.name, headImg = ownInfo.headImg, desc = ownInfo.desc) - else -> throw IllegalArgumentException("token失败") + else -> throw IllegalArgumentException("token初始化失败") } + Logger.i("token刷新完成") } fun clear() { @@ -62,17 +76,26 @@ object TokenManager { return ownInfo ?: throw IllegalArgumentException("token没有初始化,非法调用") } + fun getUserInfo(): UserVo? { + return ownInfo as? UserVo + } + + fun getManagerInfo(): ManagerVo? { + return ownInfo as? ManagerVo + } + fun getPersonInfo(): PersonInfoVo { - return personInfo + return personInfo ?: throw IllegalArgumentException("个人信息没有初始化,非法调用") } - fun getToken(): Token { - return ownInfo?.token ?: throw IllegalArgumentException("token没有初始化,非法调用") + + fun getToken(): ClientToken { + return clientToken ?: throw IllegalArgumentException("token没有初始化,非法调用") } } -@Database(entities = [Token::class], version = 1, exportSchema = false) +@Database(entities = [ClientToken::class], version = 1, exportSchema = false) abstract class AppDatabase : RoomDatabase() { abstract fun tokenDao(): TokenDao private val mIsDatabaseCreated = MutableLiveData() diff --git a/lib/src/main/java/com/gyf/lib/util/Vo.kt b/lib/src/main/java/com/gyf/lib/util/Vo.kt deleted file mode 100644 index e5b62f6..0000000 --- a/lib/src/main/java/com/gyf/lib/util/Vo.kt +++ /dev/null @@ -1,527 +0,0 @@ -package com.gyf.lib.util - -import androidx.annotation.IntRange -import com.gyf.lib.uikit.StringForm -import java.util.* - -/** - * 一般信息 - * - */ -abstract class PersonInfoVo { - abstract val name: String - abstract val headImg: String? - abstract val desc: String -} - - -enum class Duty(val desc: String, val level: Int) { - - Teacher("老师", 1), - PamphaBhusal("总部长", 2), - SecretaryOfTheMinister("秘书部部长", 3), - PropagandaDepartment("宣传部部长", 3), - LiaisonMinister("外联部部长", 3), - SecretaryDepartmentOfficer("秘书部干事", 4), - PublicityDepartmentOfficer("宣传部干事", 4), - LiaisonOfficer("外联部干事", 4); - - - /** - * 是否是部门部长 - * - */ - fun isMinister(): Boolean { - return minister.contains(this) - } - - fun isOfficer(): Boolean { - return officer.contains(this) - } - -} - -private val minister = - arrayOf(Duty.SecretaryOfTheMinister, Duty.LiaisonMinister, Duty.PropagandaDepartment) -private val officer = - arrayOf(Duty.SecretaryDepartmentOfficer, Duty.PublicityDepartmentOfficer, Duty.LiaisonOfficer) - -/** - * 个人信息 - * - */ -abstract class OwnInfoVo : PersonInfoVo() { - abstract val token: Token -} - -data class ManagerInfoVo( - val duty: Duty, - override val name: String, - override val headImg: String?, - override val desc: String -) : PersonInfoVo() - -data class UserInfoVo( - override val name: String, - override val headImg: String?, - override val desc: String -) : PersonInfoVo() - - -/** - * 管理员个人信息 - * - * @property account 管理员账号 - * @property name 姓名 - * @property duty 职务 - * @property headImg 头像 - * @property desc 个人简介 - */ -data class ManagerVo( - val account: String, - val duty: Duty, - override val token: Token, - override val name: String, - override val headImg: String?, - override val desc: String -) : OwnInfoVo() - - -/** - * 用户个人信息 - * - * @property studentId 学号 - * @property name 姓名 - * @property headImg 头像 - * @property desc 个人简介 - */ -data class UserVo( - val studentId: String, - val manager: ManagerVo? = null, - override val token: Token, - override val name: String, - override val headImg: String?, - override val desc: String, - val associationVo: AssociationVo?, - val isHead: Boolean? -) : OwnInfoVo() - -data class PageDto(val currentPage: Long, val pageSize: Int = 10) - -data class NotificationDto( - val receiverId: Int, - val receiverClient: ClientType, - val page: PageDto? = null, - override val clientType: ClientType = receiverClient -) : ClientBaseVo() - -data class UserRegVo(val studentId: String, val name: String) - -/** - * 客户端类型 - * - */ -enum class ClientType { - //前台 - Foreground, - - //后台 - Background -} - - -data class NotificationVo(val title: String, val content: String, val id: Int, val createTime: Long) - - -/** - * 响应自动生成密码 - * - * @property password - */ -data class UserPasswordVo(val password: String) - - -/** - * 用户登陆表单 - * - * @property studentId 学号 - * @property password 密码 - * @property device 设备型号 - */ -data class UserLoginVo(val studentId: String, val password: String, val device: String) - - -/** - * - * @property associationName 社团名字 - * @property activityName 活动名 - * @property activityTime 活动时间 - * @property activityLocation 活动地点 - * @property activityDesc 活动介绍 - */ -data class ActivityDetailVo( - val associationName: String, val activityName: String, - val activityTime: Date, val activityLocation: String, - val activityDesc: String -) - -/** - * 图片 - * @property name 文件名 - * @property size 文件大小 - * @property url 文件路径 - * @property md5 文件hash - * @property createTime 文件创建时间 - * @property studentId 文件上传人 - */ -data class ActivityPhotoVo( - val name: String, - val size: Long, - val url: String, - val md5: String, - val createTime: Date, - val studentId: String -) - -const val MAX_SCORE = 5L - -data class ActivityVo( - val activityId: Long, val activityName: String, val association: String, - @IntRange(from = 1, to = MAX_SCORE) val score: Int, val activityTime: Date, val location: String -) - - -data class AllOfficerVo( - val secretariat: MutableList, - val propaganda: MutableList, - val publicRelationsDepartment: MutableList -) - - -data class ApplyActVo( - val activityName: String, val activityTime: String, - val location: String, val desc: String, - val size: Int -) - -data class LeaveMessageVo( - val message: String, - override val clientType: ClientType = ClientType.Foreground -) : ClientBaseVo() - -/** - * 社团级别 - * - */ -enum class AssociationLevel { - A, - B, - C, - D -} - -/** - * 所属院系 - * - */ -enum class AssociationFaculty(val desc: String, val range: kotlin.ranges.IntRange) { - ForeignLanguageDept("外语系", 0..0), - CivilEngineeringDept("土木工程", 1..10), - SEM("经理管理学院", 11..20), - MechanicalEngineeringDept("机械工程", 21..30), - TransportationDept("交通运输", 31..40), - ArchitectureAndArts("建筑与艺术", 41..50), - ElectricalDept("电气", 51..60), - MaterialsDept("材料", 61..70), - MessageDept("信息", 71..80), - MathematicsDept("数理", 81..90), - GraduateStudent("研究生", 91..99) -} - -abstract class BaseAssociationVo { - abstract val associationId: Int - abstract val name: String - abstract val desc: String - abstract val logo: String - abstract val faculty: AssociationFaculty - abstract val level: AssociationLevel? -} - -/** - * 社团列表 - * - */ -class AssociationVo( - override val associationId: Int, - override val name: String, - override val desc: String, - override val logo: String, - override val faculty: AssociationFaculty, - override val level: AssociationLevel? -) : BaseAssociationVo() - -//审核状态 -enum class CheckStatus(val desc: String) { - WaitFirst("等待初审"), - AcceptFirst("初审受理"), - WaitLast("等待复审"), - AcceptLast("复审受理"), - Finish("审核完成") -} - - -/** - * 活动照片 - * - * @property path - */ -data class AssociationActPhotoVo(val path: String) - -data class AssociationMainVo( - val associationVo: AssociationVo, val head: UserInfoVo, - val photos: List? = null -) - -data class AuditCheckVo( - val checkStatus: CheckStatus, val applyTime: Long, - val firstCause: String, val lastCause: String? -) - -//前台社团注册资料 -data class AssociationCheckVo( - override val associationId: Int, - override val name: String, - override val desc: String, - override val logo: String, - override val faculty: AssociationFaculty, - override val level: AssociationLevel?, - val fileId: Int, - val auditCheckVo: AuditCheckVo -) : BaseAssociationVo() - -/** - * 搜索社团 - * - * @property name - * @property desc - * @property clientType - */ -data class SearchAssociationVo( - val name: String, val desc: String, - override val clientType: ClientType = ClientType.Foreground -) : ClientBaseVo() - -data class ShowAssociationVo( - val id: Int, - override val clientType: ClientType = ClientType.Foreground -) : ClientBaseVo() - - -data class QueryAssociationMembers( - val id: Int, - val name: String? = null, - override val clientType: ClientType = ClientType.Foreground -) : ClientBaseVo() - -data class BBSVo(val studentId: String, val name: String, val createTime: Date, val content: String) - - -/** - * 题型 - * - */ -enum class ExamType(val type: String) { - //选择题 - CQ("选择题"), - - //开放题 - OQ("开放题") -} - -abstract class Exam { - abstract val examType: ExamType - abstract val question: StringForm -} - - -/** - * 选择题 - * - * @property examType 题型描述 - * @property answers 答案 - * @property rightAnswer 正确答案 - * @property question 问题 - */ -data class ChoiceQuestionVo( - override val examType: ExamType = ExamType.CQ, - val answers: List, - val rightAnswer: Int, - override val question: StringForm -) : Exam() - - -data class HistoryActVo(val name: String) - - -/** - * 开放题 - * - * @property examType 题型描述 - * @property question 问题 - */ -data class OpenQuestionsVo( - override val examType: ExamType = ExamType.OQ, override val question: StringForm -) : Exam() - - -data class LeaveMessageFormatVo(val message: String, val user: UserInfoVo) - - -data class ManagerLoginVo(val account: String, val password: String, val device: String) - -data class OngoingActVo(val name: String) - -/** - * 活动质量汇报单 - * - * @property applyName 申请人 - * @property activityName 活动名称 - * @property merit 优点 - * @property defect 缺点 - * @property score 星级评价 - */ -data class QualityReportVo( - val applyName: String, - val activityName: String, - val merit: String, - val defect: String, - @IntRange(from = 1L, to = MAX_SCORE) val score: Int -) - -/** - * 社团注册资料表单 - * - * @property name - * @property desc - * @property fileId - */ -data class AssociationRegVo( - val associationId: Int?, val name: String, val desc: String, val fileId: Int, - override val clientType: ClientType = ClientType.Foreground -) : ClientBaseVo() - - -abstract class AuditVo { - abstract val audit: AuditLoggingVo -} - -/** - * 社团注册审核记录 - * - */ -data class AuditAssociationVo( - val name: String, - val desc: String, - val logo: String, - override val audit: AuditLoggingVo -) : AuditVo() - -/** - * 通用审核记录 - * - * @property id - * @property user - * @property applyTime - * @property manager - * @property acceptTime - * @property cause - * @property result - * @property auditTime - * @property nextAudit - */ -data class AuditLoggingVo( - val id: Int, val user: UserInfoVo, val applyTime: Long, val manager: ManagerInfoVo?, - val acceptTime: Long?, val cause: String?, val result: Boolean?, - val auditTime: Long?, val nextAudit: AuditLoggingVo? -) - -/** - * 社团注册资料受理 - * - * @property auditId - * @property clientType - */ -data class AcceptVo( - val auditId: Int, - override val clientType: ClientType = ClientType.Background -) : ClientBaseVo() - -/** - * 社团注册资料审核 - * - * @property auditId - * @property result - * @property cause - * @property clientType - */ -data class CheckVo( - val auditId: Int, val result: Boolean, val cause: String, - override val clientType: ClientType = ClientType.Background -) : ClientBaseVo() - - -/** - * 前台活动申请书 - * - * @property activityId - * @property activityName - * @property activityTime - * @property activityAddress - * @property activityDesc - * @property activitySize - * @property clientType - */ -data class ActivityApplyVo( - val activityId: Int?, val associationId: Int, - val activityName: String, val activityTime: Long, - val activityAddress: String, - val activityDesc: String, val activitySize: Int, - override val clientType: ClientType = ClientType.Foreground -) : ClientBaseVo() - -/** - * 后台活动申请书 - * - * @property auditId - * @property activityName - * @property activityTime - * @property activityAddress - * @property activityDesc - * @property activitySize - */ -data class AuditActVo( - val auditId: Int, val activityName: String, val activityTime: Long, - val activityAddress: String, - val activityDesc: String, val activitySize: Int, - override val audit: AuditLoggingVo -) : AuditVo() - -/** - * 换名申请表 - * - * @property studentId 学号 - * @property oldName 社团原名 - * @property newName 社团新名 - * @property reason 申请理由 - */ -data class RenameVo( - val studentId: String, - val oldName: String, - val newName: String, - val reason: String -) - -abstract class ClientBaseVo { - val token: Token = TokenManager.getToken() - abstract val clientType: ClientType -} \ No newline at end of file diff --git a/lib/src/main/res/values-en/integers.xml b/lib/src/main/res/values-en/integers.xml index c6c1f31..e94465d 100644 --- a/lib/src/main/res/values-en/integers.xml +++ b/lib/src/main/res/values-en/integers.xml @@ -1,4 +1,5 @@ 20 + 4 \ No newline at end of file diff --git a/lib/src/main/res/values-en/strings.xml b/lib/src/main/res/values-en/strings.xml index 1d82610..83ac1ab 100644 --- a/lib/src/main/res/values-en/strings.xml +++ b/lib/src/main/res/values-en/strings.xml @@ -30,4 +30,5 @@ 复审 审核阶段 复审意见 + 活动日期 \ No newline at end of file diff --git a/lib/src/main/res/values-zh/integers.xml b/lib/src/main/res/values-zh/integers.xml index c6c1f31..e94465d 100644 --- a/lib/src/main/res/values-zh/integers.xml +++ b/lib/src/main/res/values-zh/integers.xml @@ -1,4 +1,5 @@ 20 + 4 \ 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 1d82610..83ac1ab 100644 --- a/lib/src/main/res/values-zh/strings.xml +++ b/lib/src/main/res/values-zh/strings.xml @@ -30,4 +30,5 @@ 复审 审核阶段 复审意见 + 活动日期 \ No newline at end of file diff --git a/lib/src/main/res/values/integers.xml b/lib/src/main/res/values/integers.xml index c6c1f31..e94465d 100644 --- a/lib/src/main/res/values/integers.xml +++ b/lib/src/main/res/values/integers.xml @@ -1,4 +1,5 @@ 20 + 4 \ 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 1d82610..83ac1ab 100644 --- a/lib/src/main/res/values/strings.xml +++ b/lib/src/main/res/values/strings.xml @@ -30,4 +30,5 @@ 复审 审核阶段 复审意见 + 活动日期 \ No newline at end of file diff --git a/lib/src/test/java/com/gyf/lib/ExampleUnitTest.kt b/lib/src/test/java/com/gyf/lib/ExampleUnitTest.kt index fd8acee..63c18aa 100644 --- a/lib/src/test/java/com/gyf/lib/ExampleUnitTest.kt +++ b/lib/src/test/java/com/gyf/lib/ExampleUnitTest.kt @@ -8,9 +8,17 @@ import org.junit.Test * * See [testing documentation](http://d.android.com/tools/testing). */ + + class ExampleUnitTest { @Test fun addition_isCorrect() { assertEquals(4, 2 + 2) } + + @Test + fun testClientToken() { + + + } } \ No newline at end of file diff --git a/settings.gradle.kts b/settings.gradle.kts index 0d296bc..fc163ed 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -15,3 +15,7 @@ include(":foreground") include(":background") //公共库 include(":lib") + +include(":module") + +project(":module").projectDir = File(settingsDir, "..\\..\\IdeaProjects\\CsamsServer\\module")