From acb519df85117aacbbe4061ae5183b26e5024082 Mon Sep 17 00:00:00 2001 From: pan <1029559041@qq.com> Date: Sun, 6 Jun 2021 10:07:02 +0800 Subject: [PATCH] =?UTF-8?q?=E7=AD=94=E8=BE=A9=E6=B5=8B=E8=AF=95=E7=89=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- background/src/main/AndroidManifest.xml | 2 +- .../gyf/csams/account/model/LoginViewModel.kt | 6 +- .../model/AssociationManagementViewModel.kt | 49 ++++- .../gyf/csams/main/model/AuditActViewModel.kt | 2 +- .../main/model/AuditAssociationViewModel.kt | 2 +- .../csams/main/model/AuditRenameViewModel.kt | 25 +++ .../csams/main/model/BaseAuditViewModel.kt | 3 +- .../main/model/CheckQualityReportViewModel.kt | 4 - .../main/model/ManagementOfficerModel.kt | 50 ++++- .../csams/main/model/ManagerActViewModel.kt | 19 +- .../com/gyf/csams/main/model/MenuViewModel.kt | 17 +- .../gyf/csams/main/model/RenameViewModel.kt | 46 ----- .../main/ui/AssociationManagementActivity.kt | 13 +- .../gyf/csams/main/ui/AuditRenameActivity.kt | 87 ++++++++ .../gyf/csams/main/ui/DepartmentActivity.kt | 45 ++-- .../com/gyf/csams/main/ui/MainActivity.kt | 11 +- .../main/ui/ManagementOfficerActivity.kt | 5 +- .../com/gyf/csams/main/ui/RenameActivity.kt | 87 -------- .../java/com/gyf/csams/uikit/CheckForm.kt | 9 +- foreground/src/main/AndroidManifest.xml | 2 +- .../csams/account/model/AccountViewModel.kt | 12 +- .../gyf/csams/account/ui/AccountActivity.kt | 2 +- .../activity/model/ActivityDetailViewModel.kt | 6 +- .../csams/activity/model/ApplyActViewModel.kt | 31 ++- .../gyf/csams/activity/ui/ApplyActActivity.kt | 25 +-- .../association/model/AssociationViewModel.kt | 8 + .../csams/association/model/ExamViewModel.kt | 109 ++++++---- .../model/RegAssociationViewModel.kt | 8 +- .../association/model/RenameViewModel.kt | 87 +++++++- .../association/ui/AssociationActivity.kt | 72 +++++-- .../gyf/csams/association/ui/ExamActivity.kt | 105 +++++----- .../csams/association/ui/ReNameActivity.kt | 99 --------- .../csams/association/ui/RenameActivity.kt | 195 ++++++++++++++++++ .../com/gyf/csams/main/model/MainViewModel.kt | 2 +- .../com/gyf/csams/main/ui/MainActivity.kt | 145 ++++++++----- .../main/java/com/gyf/csams/uikit/BaseView.kt | 19 ++ .../java/com/gyf/csams/uikit/ViewModel.kt | 92 ++------- .../main/java/com/gyf/csams/util/GsonUtil.kt | 8 +- .../java/com/gyf/csams/util/HttpCallback.kt | 2 +- .../java/com/gyf/csams/ExampleUnitTest.kt | 2 +- lib/build.gradle.kts | 1 + .../java/com/gyf/lib/uikit/BaseTextField.kt | 15 +- lib/src/main/java/com/gyf/lib/util/Api.kt | 36 +++- .../test/java/com/gyf/lib/ExampleUnitTest.kt | 1 - 44 files changed, 957 insertions(+), 609 deletions(-) create mode 100644 background/src/main/java/com/gyf/csams/main/model/AuditRenameViewModel.kt delete mode 100644 background/src/main/java/com/gyf/csams/main/model/RenameViewModel.kt create mode 100644 background/src/main/java/com/gyf/csams/main/ui/AuditRenameActivity.kt delete mode 100644 background/src/main/java/com/gyf/csams/main/ui/RenameActivity.kt delete mode 100644 foreground/src/main/java/com/gyf/csams/association/ui/ReNameActivity.kt create mode 100644 foreground/src/main/java/com/gyf/csams/association/ui/RenameActivity.kt diff --git a/background/src/main/AndroidManifest.xml b/background/src/main/AndroidManifest.xml index ff91fa0..3d7e14a 100644 --- a/background/src/main/AndroidManifest.xml +++ b/background/src/main/AndroidManifest.xml @@ -39,7 +39,7 @@ - + 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 48ce5ee..7c810ae 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 @@ -23,11 +23,9 @@ class LoginViewModel(application: Application) : AbstractLoginViewModel(applicat } override fun loginParam(): Any { - val account = "${id.formValue.value}" - val password = "${password.formValue.value}" return ManagerLoginVo( - account = account, - password = password, + account = id.getValue(), + password = password.getValue(), device = "${Build.MANUFACTURER} ${Build.MODEL}" ) } 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 42795b4..d044791 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,9 +1,13 @@ package com.gyf.csams.main.model import android.app.Application -import com.gyf.csams.module.AssociationLevel -import com.gyf.csams.module.AssociationVo +import androidx.lifecycle.viewModelScope +import com.google.gson.reflect.TypeToken +import com.gyf.csams.module.* import com.gyf.lib.model.ScrollViewModel +import com.gyf.lib.util.* +import com.orhanobut.logger.Logger +import kotlinx.coroutines.launch /** @@ -13,25 +17,50 @@ import com.gyf.lib.model.ScrollViewModel class AssociationManagementViewModel(application: Application) : ScrollViewModel( application ) { - override val initSize: Int = 10 init { load() } fun load() { - TODO("数据状态管理") - } - - fun loadMore(callback: (message: String) -> Unit) { - TODO("Not yet implemented") + viewModelScope.launch { + HttpClient.post( + url = Api.buildUrl(AssociationApi.ListAll), + callback = HttpCallback>(action = "加载社团", + onSuccess = { it -> + it.body?.let { + _data.postValue(it) + } + }, + typeToken = object : + TypeToken>>() {}.type + ), + jsonParam = OnlyToken(clientType = ClientType.Background) + ) + } } /** * * @param level */ - fun update(associationDto: AssociationVo, level: AssociationLevel) { - TODO("更新社团级别") + fun update( + associationVo: AssociationVo, + level: AssociationLevel, + callback: (m: String) -> Unit + ) { + Logger.i("社团:${associationVo.name}") + HttpClient.post(url = Api.buildUrl(AssociationApi.Update), + callback = HttpCallback(action = "社团等级更新", + onSuccess = { + callback(it.message) + }, typeToken = object : TypeToken>() {}.type + ), + jsonParam = UpdateAssociationVo( + associationVo = associationVo.copy(level = level), + token = TokenManager.getToken(), + clientType = ClientType.Background + ) + ) } } \ No newline at end of file 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 index ecb1ce7..9282728 100644 --- a/background/src/main/java/com/gyf/csams/main/model/AuditActViewModel.kt +++ b/background/src/main/java/com/gyf/csams/main/model/AuditActViewModel.kt @@ -21,7 +21,7 @@ class AuditActViewModel(application: Application) : BaseAuditViewModel>>() {}.type init { - load { } + load() } 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 1e9eef6..202501e 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 @@ -20,7 +20,7 @@ class AuditAssociationViewModel(application: Application) : BaseAuditViewModel>>() {}.type init { - load { } + load() } diff --git a/background/src/main/java/com/gyf/csams/main/model/AuditRenameViewModel.kt b/background/src/main/java/com/gyf/csams/main/model/AuditRenameViewModel.kt new file mode 100644 index 0000000..eec74b8 --- /dev/null +++ b/background/src/main/java/com/gyf/csams/main/model/AuditRenameViewModel.kt @@ -0,0 +1,25 @@ +package com.gyf.csams.main.model + +import android.app.Application +import com.google.gson.reflect.TypeToken +import com.gyf.csams.module.ApiResponse +import com.gyf.csams.module.AuditRenameVo +import com.gyf.lib.util.AssociationApi +import com.gyf.lib.util.UrlPath +import java.lang.reflect.Type + + +class AuditRenameViewModel(application: Application) : + BaseAuditViewModel(application) { + + override val auditApi: UrlPath = AssociationApi.RenameAudit + override val acceptApi: UrlPath = AssociationApi.RenameAccept + override val checkApi: UrlPath = AssociationApi.RenameCheck + 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/BaseAuditViewModel.kt b/background/src/main/java/com/gyf/csams/main/model/BaseAuditViewModel.kt index c1d679b..4ded2da 100644 --- a/background/src/main/java/com/gyf/csams/main/model/BaseAuditViewModel.kt +++ b/background/src/main/java/com/gyf/csams/main/model/BaseAuditViewModel.kt @@ -22,9 +22,8 @@ abstract class BaseAuditViewModel(application: Application) : /** * 加载审核记录 * - * @param callback */ - fun load(callback: (message: String) -> Unit) { + fun load() { viewModelScope.launch { HttpClient.post( Api.buildUrl(auditApi), HttpCallback>( 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 302d031..c558bb1 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 @@ -38,8 +38,4 @@ class CheckQualityReportViewModel(application: Application) : ApplyViewModel Unit) { - TODO("Not yet implemented") - } } \ No newline at end of file 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 57a6b10..175fd45 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,15 @@ package com.gyf.csams.main.model import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.google.gson.reflect.TypeToken import com.gyf.csams.module.AllOfficerVo -import com.gyf.csams.module.ManagerInfoVo +import com.gyf.csams.module.ApiResponse +import com.gyf.csams.module.ClientType +import com.gyf.csams.module.ManagerDutySumVo +import com.gyf.lib.util.* +import com.orhanobut.logger.Logger +import kotlinx.coroutines.launch enum class ColumnType { @@ -21,20 +28,53 @@ class ManagementOfficerModel : ViewModel() { private val _data = MutableLiveData() val data: LiveData = _data + //部门概况 + private val _simpleData = MutableLiveData() + val simpleData: LiveData = _simpleData init { load() } - fun updateDuty(list: MutableList, index: Int) { - TODO("更新职务") + //TODO 更新职务 + fun updateDuty() { + Logger.i("更新职务") } /** - * + *加载部门概况 */ private fun load() { - TODO("加载部门成员") + viewModelScope.launch { + HttpClient.post(url = Api.buildUrl(AccountApi.Load), + callback = HttpCallback(action = "加载部门概况", onSuccess = + { it -> + it.body?.let { + _simpleData.postValue(it) + } + }, typeToken = object : TypeToken>() {}.type + ), + jsonParam = OnlyToken(clientType = ClientType.Background) + ) + } + } + + /** + * 加载部门详情 + * + */ + fun loadDetail() { + viewModelScope.launch { + HttpClient.post( + url = Api.buildUrl(AccountApi.LoadDetail), + callback = HttpCallback(action = "加载部门详情", onSuccess = { it -> + it.body?.let { + _data.postValue(it) + } + }, typeToken = object : TypeToken>() {}.type), + jsonParam = OnlyToken(clientType = ClientType.Background) + ) + } } } \ No newline at end of file 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 612fcf9..4b3a7e0 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,8 +1,12 @@ package com.gyf.csams.main.model import android.app.Application +import com.google.gson.reflect.TypeToken +import com.gyf.csams.module.ApiResponse +import com.gyf.csams.module.ClientType import com.gyf.csams.module.ManagerActVo import com.gyf.lib.model.ScrollViewModel +import com.gyf.lib.util.* /** @@ -20,10 +24,17 @@ class ManagerActViewModel(application: Application) : ScrollViewModel>(action = "查看活动信息", + onSuccess = { it -> + it.body.let { + _data.postValue(it) + } + }, typeToken = object : TypeToken>>() {}.type + ), + jsonParam = OnlyToken(clientType = ClientType.Background) + ) } - 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/MenuViewModel.kt b/background/src/main/java/com/gyf/csams/main/model/MenuViewModel.kt index 3bd1751..1a1cb5a 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 @@ -1,29 +1,22 @@ package com.gyf.csams.main.model import android.app.Activity -import androidx.lifecycle.ViewModel -import com.gyf.csams.main.ui.AuditActActivity -import com.gyf.csams.main.ui.AuditAssociationActivity -import com.gyf.csams.main.ui.RenameActivity +import com.gyf.csams.main.ui.* enum class MenuType(val desc: String, val clazz: Map>) { Association( "社团管理", mapOf( -// TODO "社团信息管理" to AssociationManagementActivity::class.java, - "审核社团换名" to RenameActivity::class.java, + "社团信息管理" to AssociationManagementActivity::class.java, + "审核社团换名" to AuditRenameActivity::class.java, "审核社团注册" to AuditAssociationActivity::class.java ), ), Act( "活动管理", mapOf( "审核社团活动" to AuditActActivity::class.java, -// TODO "审核质量报告单" to CheckQualityReportActivity::class.java, -// "查看社团活动" to ManagerActActivity::class.java + "审核质量报告单" to CheckQualityReportActivity::class.java, + "查看社团活动" to ManagerActActivity::class.java ) ) -} - -class MenuViewModel : ViewModel() { - } \ No newline at end of file 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 deleted file mode 100644 index eb4b046..0000000 --- a/background/src/main/java/com/gyf/csams/main/model/RenameViewModel.kt +++ /dev/null @@ -1,46 +0,0 @@ -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.randomChinese -import com.gyf.lib.util.randomNum -import kotlinx.coroutines.launch - - -class RenameViewModel(application: Application) : ScrollViewModel(application) { - - val approverOrigin = - StringForm( - formDesc = application.getString(R.string.first_approver_origin), - textLength = 30 - ) - - - override val initSize: Int = 10 - - init { - load() - } - - fun load() { - viewModelScope.launch { - _data.value?.apply { - repeat(initSize) { - add( - RenameVo( - studentId = randomNum(8), - oldName = randomChinese(5), - newName = randomChinese(5), - reason = randomChinese(10) - ) - ) - } - } - } - } -} \ No newline at end of file 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 a184f9d..c81b7e4 100644 --- a/background/src/main/java/com/gyf/csams/main/ui/AssociationManagementActivity.kt +++ b/background/src/main/java/com/gyf/csams/main/ui/AssociationManagementActivity.kt @@ -20,6 +20,7 @@ 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.uikit.ScaffoldModel /** * 社团管理 @@ -85,15 +86,23 @@ class AssociationManagementActivity : ComponentActivity() { text = level?.name ?: "暂无评级", style = MaterialTheme.typography.h5 ) + val scaffoldModel: ScaffoldModel = viewModel() DropdownMenu( expanded = expanded, onDismissRequest = { /*TODO*/ }) { AssociationLevel.values().forEach { DropdownMenuItem(onClick = { model.update( - associationDto = this@apply, + associationVo = this@apply, level = it - ) + ) { + scaffoldModel.update( + message = it, + actionLabel = "刷新" + ) { + model.load() + } + } expanded = false }) { Text(text = it.name) diff --git a/background/src/main/java/com/gyf/csams/main/ui/AuditRenameActivity.kt b/background/src/main/java/com/gyf/csams/main/ui/AuditRenameActivity.kt new file mode 100644 index 0000000..d18a331 --- /dev/null +++ b/background/src/main/java/com/gyf/csams/main/ui/AuditRenameActivity.kt @@ -0,0 +1,87 @@ +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.lifecycle.viewmodel.compose.viewModel +import com.google.accompanist.insets.ExperimentalAnimatedInsets +import com.gyf.csams.R +import com.gyf.csams.main.model.AuditRenameViewModel +import com.gyf.csams.module.AuditRenameVo +import com.gyf.csams.uikit.CheckForm +import com.gyf.csams.uikit.RowItem +import com.gyf.csams.uikit.TestTable +import com.gyf.csams.uikit.TestTableImeSimple +import com.gyf.lib.uikit.ImeBody + +class AuditRenameActivity : ComponentActivity() { + + @ExperimentalMaterialApi + @ExperimentalAnimatedInsets + @ExperimentalComposeApi + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + setContent { + TestTable(clazz = AuditRenameViewModel::class.java, title = R.string.rename_form) { + RenameForm(vo = it) + } + ImeBody { + val model: AuditRenameViewModel = viewModel() + val data by model.data.observeAsState() + TestTableImeSimple( + title = R.string.rename_form + ) { + data?.forEach { + item { + RenameForm(vo = it) + CheckForm(vo = it) + Spacer(modifier = Modifier.height(10.dp)) + } + } + } + } + } + } + + @Composable + private fun RenameForm( + modifier: Modifier = Modifier, + vo: AuditRenameVo + ) { + Column(modifier = modifier) { + val baseHeight = 50.dp + RowItem( + modifier = Modifier.height(baseHeight), + key = R.string.petitioner, + value = vo.audit.user.name + ) + RowItem( + modifier = Modifier.height(baseHeight), + key = R.string.oldname, + value = vo.associationVo.name + ) + RowItem( + modifier = Modifier.height(baseHeight), + key = R.string.newname, + value = vo.renameVo.newName + ) + RowItem( + modifier = Modifier.height(baseHeight * 3), + key = R.string.reason_for_application, + value = vo.renameVo.cause + ) + } + } + +} \ No newline at end of file diff --git a/background/src/main/java/com/gyf/csams/main/ui/DepartmentActivity.kt b/background/src/main/java/com/gyf/csams/main/ui/DepartmentActivity.kt index f53a498..0653916 100644 --- a/background/src/main/java/com/gyf/csams/main/ui/DepartmentActivity.kt +++ b/background/src/main/java/com/gyf/csams/main/ui/DepartmentActivity.kt @@ -10,11 +10,15 @@ import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.* import androidx.compose.material.* import androidx.compose.runtime.* +import androidx.compose.runtime.livedata.observeAsState import androidx.compose.ui.Alignment 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.gyf.csams.R +import com.gyf.csams.main.model.ManagementOfficerModel +import com.gyf.csams.module.ManagerDutyVo import com.gyf.lib.uikit.Body import com.gyf.lib.uikit.MainColumnFrame @@ -29,6 +33,7 @@ class DepartmentActivity : ComponentActivity() { setContent { Body { + val model: ManagementOfficerModel = viewModel() MainColumnFrame(background = { /*TODO*/ }) { val weight = 0.1F val departWeight = 0.2F @@ -92,19 +97,28 @@ class DepartmentActivity : ComponentActivity() { } + val simpleData by model.simpleData.observeAsState() + simpleData?.let { + DepartmentItem(modifier = Modifier.weight(weight = departWeight), + id = R.string.secretariat, + onClick = { dialogContent = R.string.secretariat }, + managerDutyVo = it.secretariat + ) + Spacer(modifier = Modifier.weight(space)) + DepartmentItem(modifier = Modifier.weight(weight = departWeight), + id = R.string.propaganda_department, + onClick = { dialogContent = R.string.propaganda_department }, + managerDutyVo = it.propaganda + ) + Spacer(modifier = Modifier.weight(space)) + DepartmentItem(modifier = Modifier.weight(weight = departWeight), + id = R.string.public_relations_department, + onClick = { dialogContent = R.string.public_relations_department }, + managerDutyVo = it.publicRelationsDepartment + ) + Spacer(modifier = Modifier.weight(space)) + } - DepartmentItem(modifier = Modifier.weight(weight = departWeight), - id = R.string.secretariat, - onClick = { dialogContent = R.string.secretariat }) - Spacer(modifier = Modifier.weight(space)) - DepartmentItem(modifier = Modifier.weight(weight = departWeight), - id = R.string.propaganda_department, - onClick = { dialogContent = R.string.propaganda_department }) - Spacer(modifier = Modifier.weight(space)) - DepartmentItem(modifier = Modifier.weight(weight = departWeight), - id = R.string.public_relations_department, - onClick = { dialogContent = R.string.public_relations_department }) - Spacer(modifier = Modifier.weight(space)) } } } @@ -114,7 +128,8 @@ class DepartmentActivity : ComponentActivity() { private fun DepartmentItem( modifier: Modifier = Modifier, @StringRes id: Int, - onClick: () -> Unit + onClick: () -> Unit, + managerDutyVo: ManagerDutyVo ) { Row( modifier = modifier @@ -141,13 +156,13 @@ class DepartmentActivity : ComponentActivity() { .fillMaxHeight(), verticalArrangement = Arrangement.SpaceBetween ) { - RowItem(text = "部门部长:") + RowItem(text = "部门部长:${managerDutyVo.manager.name}") OutlinedButton(modifier = Modifier.fillMaxWidth(), onClick = { startActivity(Intent(applicationContext, ManagementOfficerActivity::class.java)) }) { Text(text = stringResource(id = R.string.management_officer)) } - RowItem(text = "部门总人数:") + RowItem(text = "部门总人数:${managerDutyVo.people}") } } } 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 3aa8d2b..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 @@ -59,12 +59,11 @@ class MainActivity : BaseActivity() { Text(text = "我的通知") } -// TODO 部门管理 -// OutlinedButton(onClick = { -// startActivity(Intent(this@MainActivity, DepartmentActivity::class.java)) -// }, modifier = Modifier.fillMaxWidth()) { -// Text(text = stringResource(id = R.string.department_management)) -// } + OutlinedButton(onClick = { + startActivity(Intent(this@MainActivity, DepartmentActivity::class.java)) + }, modifier = Modifier.fillMaxWidth()) { + Text(text = stringResource(id = R.string.department_management)) + } OutlinedButton(onClick = { startActivity( Intent( 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 85ecfdf..203c240 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 @@ -41,6 +41,7 @@ class ManagementOfficerActivity : ComponentActivity() { MainColumnFrame(background = { /*TODO*/ }) { val weight = 1 / 3F val model: ManagementOfficerModel = viewModel() + model.loadDetail() val data by model.data.observeAsState() Logger.i("$data") data?.apply { @@ -79,7 +80,7 @@ class ManagementOfficerActivity : ComponentActivity() { model: ManagementOfficerModel = viewModel(), scaffoldModel: ScaffoldModel = viewModel(), @StringRes id: Int, - officerVoList: MutableList, + officerVoList: List, ) { Column( modifier = modifier @@ -119,7 +120,7 @@ class ManagementOfficerActivity : ComponentActivity() { expanded = expanded, onDismissRequest = { /*TODO*/ }) { DropdownMenuItem(onClick = { - model.updateDuty(list = officerVoList, index = it.index) + model.updateDuty() expanded = false }) { Text(text = it.value.duty.desc) 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 deleted file mode 100644 index 13b1cc5..0000000 --- a/background/src/main/java/com/gyf/csams/main/ui/RenameActivity.kt +++ /dev/null @@ -1,87 +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.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 - -class RenameActivity : ComponentActivity() { - - @ExperimentalAnimatedInsets - @ExperimentalComposeApi - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - - setContent { - TestTable(clazz = RenameViewModel::class.java, title = R.string.rename_form) { - RenameForm(renameVo = it) - } - } - } - - @Composable - private fun RenameForm( - modifier: Modifier = Modifier, model: RenameViewModel = viewModel(), - scaffoldModel: ScaffoldModel = viewModel(), renameVo: RenameVo - ) { - Column(modifier = modifier) { - val baseHeight = 50.dp - RowItem( - modifier = Modifier.height(baseHeight), - key = R.string.petitioner, - value = renameVo.studentId - ) - RowItem( - modifier = Modifier.height(baseHeight), - key = R.string.oldname, - value = renameVo.oldName - ) - RowItem( - modifier = Modifier.height(baseHeight), - key = R.string.newname, - value = renameVo.newName - ) - RowItem( - modifier = Modifier.height(baseHeight * 3), - key = R.string.reason_for_application, - value = renameVo.reason - ) - 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.approverOrigin) - } - 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/uikit/CheckForm.kt b/background/src/main/java/com/gyf/csams/uikit/CheckForm.kt index 14e32bd..af7ca25 100644 --- a/background/src/main/java/com/gyf/csams/uikit/CheckForm.kt +++ b/background/src/main/java/com/gyf/csams/uikit/CheckForm.kt @@ -92,11 +92,10 @@ inline fun > CheckForm( model.check( auditId = vo.audit.id, result = result, - cause = cause.formValue.value - ?: throw IllegalArgumentException("无法获取审核理由") + cause = cause.getValue() ) { scaffoldModel.update(message = it, actionLabel = "刷新") { - model.load { } + model.load() } } } @@ -109,7 +108,7 @@ inline fun > CheckForm( auditId = vo.audit.id ) { scaffoldModel.update(message = it, actionLabel = "刷新") { - model.load { } + model.load() } } } @@ -166,7 +165,7 @@ inline fun > CheckForm( ) } //初审记录,负责人不为空 初审受理 - vo.audit.nextAudit == null && vo.audit.manager != null -> { + vo.audit.nextAudit == null && vo.audit.manager != null && vo.audit.result == null -> { first() if (it.duty == Duty.PamphaBhusal) { diff --git a/foreground/src/main/AndroidManifest.xml b/foreground/src/main/AndroidManifest.xml index 8465d84..b45d465 100644 --- a/foreground/src/main/AndroidManifest.xml +++ b/foreground/src/main/AndroidManifest.xml @@ -67,7 +67,7 @@ - + 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 782879a..2789789 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 @@ -132,18 +132,16 @@ class AccountViewModel(application: Application) : AbstractLoginViewModel(applic }, onFail = { Logger.e(it) }, typeToken = object : TypeToken>() {}.type - ), mapOf("studentId" to "${id.formValue.value}") + ), mapOf("studentId" to id.getValue()) ) } } } override fun loginParam(): Any { - val studentId = "${id.formValue.value}" - val password = "${password.formValue.value}" return UserLoginVo( - studentId = studentId, - password = password, + studentId = id.getValue(), + password = password.getValue(), device = "${Build.MANUFACTURER} ${Build.MODEL}" ) } @@ -183,8 +181,8 @@ class AccountViewModel(application: Application) : AbstractLoginViewModel(applic typeToken = object : TypeToken>() {}.type ), jsonParam = UserRegVo( - studentId = id.formValue.value ?: throw IllegalArgumentException("学号为空"), - name = name.formValue.value ?: throw IllegalArgumentException("姓名为空") + studentId = id.getValue(), + name = name.getValue() ) ) resetForm() 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 b8ddc09..b2b01c9 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 @@ -218,7 +218,7 @@ class AccountActivity : ComponentActivity() { color = MaterialTheme.colors.error ) ) { - append(accountViewModel.id.formValue.value ?: "") + append(accountViewModel.id.getValue()) } append(accountViewModel.registered) }) 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 1e8bad2..a4b298b 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 @@ -112,8 +112,7 @@ class ActivityPhotoViewModel(application: Application) : ), params = mapOf( "activityId" to "$activityId", - "name" to (name.formValue.value - ?: throw IllegalArgumentException("照片名字为空")) + "name" to name.getValue() ), fileList = arrayOf(cacheFile) ) @@ -172,8 +171,7 @@ class BBSCommentModel : AbstractComment() { ), jsonParam = SendBBSVo( - content = newContent.formValue.value - ?: throw IllegalArgumentException("评论内容为空"), + content = newContent.getValue(), token = TokenManager.getToken(), activityId = activityId ?: throw IllegalArgumentException("活动id没有初始化") ) 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 84bc93c..2770f37 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 @@ -83,7 +83,7 @@ class ApplyActViewModel(application: Application) : AndroidViewModel(application val checkInfo: LiveData> = _checkInfo init { - read { } + read() } val city = @@ -587,13 +587,8 @@ class ApplyActViewModel(application: Application) : AndroidViewModel(application * */ fun apply(callback: (message: String) -> Unit) { - 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 { @@ -608,12 +603,12 @@ class ApplyActViewModel(application: Application) : AndroidViewModel(application 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 + activityName = activityName.getValue(), + activityTime = "${activityDate.getValue()} ${activityTime.getValue()}".toDate().time, + activityAddress = activityAddress.getValue(), + activityDesc = activityDesc.getValue(), + activitySize = activitySize.getValue().toInt(), + activityId = _checkInfo.value?.body?.activityVo?.activityId ), token = TokenManager.getToken() ) @@ -627,10 +622,12 @@ class ApplyActViewModel(application: Application) : AndroidViewModel(application * * @param callback */ - private fun read(callback: (message: String) -> Unit) { + private fun read() { viewModelScope.launch { - HttpClient.post(url = Api.buildUrl(ActivityApi.Read), - HttpCallback(action = "查看活动申请书审核进度", + HttpClient.post( + url = Api.buildUrl(ActivityApi.Read), + HttpCallback( + action = "查看活动申请书审核进度", onSuccess = { it -> _checkInfo.postValue(it) it.body?.activityVo?.let { 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 dc2ce69..f8bd37f 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,8 +13,11 @@ 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.* +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue 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 @@ -197,14 +200,14 @@ class ApplyActActivity : AppCompatActivity() { ) } Spacer(modifier = Modifier.weight(0.05F)) - 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() + val activityName by model.activityName.statusForm.observeAsState() + val activityDate by model.activityDate.statusForm.observeAsState() + val activityTime by model.activityTime.statusForm.observeAsState() + val activityDesc by model.activityDesc.statusForm.observeAsState() + val activitySize by model.activitySize.statusForm.observeAsState() BottomButton( modifier = Modifier.fillMaxWidth(), - enabled = check( + enabled = checkForm( activityName, activityDate, activityTime, @@ -234,14 +237,6 @@ class ApplyActActivity : AppCompatActivity() { 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) { 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 b355ad1..3b1e9df 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 @@ -21,6 +21,10 @@ class AssociationViewModel : ViewModel(), TopMenuInterface { override val _currentMenu: MutableLiveData = MutableLiveData() override val currentMenu: LiveData = _currentMenu + private val _dropDownMenuResult = MutableLiveData() + val dropDownMenuResult: LiveData = _dropDownMenuResult + + /** * 下拉菜单状态 */ @@ -30,6 +34,10 @@ class AssociationViewModel : ViewModel(), TopMenuInterface { private val _associationVo = MutableLiveData() val associationVo: LiveData = _associationVo + fun update(message: String?) { + _dropDownMenuResult.postValue(message) + } + fun load(id: Int) { viewModelScope.launch { HttpClient.post( 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 e1fdd70..ce2929d 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,11 +3,9 @@ package com.gyf.csams.association.model import android.app.Application import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData -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.uikit.ValidStringForm import com.gyf.lib.util.NOT_IMPL_TIP /** @@ -41,6 +39,61 @@ const val ANSWER_SIZE = 4 const val ANSWER_TEXT_LENGTH = 15 +/** + * 题型 + * + */ +enum class ExamType(val type: String) { + //选择题 + CQ("选择题"), + + //开放题 + OQ("开放题") +} + +abstract class Exam { + abstract val examType: ExamType + + //**TODO 题目反序列化 + abstract val question: String? + abstract val _question: StringForm? +} + +/** + * 选择题 + * + * @property examType 题型描述 + * @property answers 答案 + * @property rightAnswer 正确答案 + * @property question 问题 + * TODO 题目反序列化 + */ +data class ChoiceQuestionVo( + val id: Int? = null, + override val examType: ExamType = ExamType.CQ, + val _answers: MutableList = mutableListOf(), + val answers: List = ('A'..'D').map { "选项${it}" }.toList(), + val rightAnswer: Int, + override val question: String? = null, + override val _question: StringForm?, + + ) : Exam() + + +/** + * 开放题 + * + * @property examType 题型描述 + * @property question 问题 + * TODO 题目反序列化 + */ +data class OpenQuestionsVo( + override val examType: ExamType = ExamType.OQ, + override val question: String? = null, + override val _question: StringForm? + +) : Exam() + /** * 题库状态管理 * @@ -54,9 +107,6 @@ class ExamViewModel(application: Application) : ScrollViewModel(applicatio val actionLabel = "确定" - override val initSize = 10 - - private val _newExam: MutableLiveData = MutableLiveData(createExam(ExamType.CQ)) val newExam: LiveData = _newExam @@ -64,9 +114,7 @@ class ExamViewModel(application: Application) : ScrollViewModel(applicatio load() } - fun createQuestion(): StringForm { - return StringForm(formDesc = "问题", textLength = QUESTION_TEXT_LENGTH) - } + /** * 切换题型 @@ -85,7 +133,18 @@ class ExamViewModel(application: Application) : ScrollViewModel(applicatio * @return */ private fun createExam(type: ExamType): Exam { - TODO("创建题目") + + val questionForm = ValidStringForm(formDesc = "", textLength = QUESTION_TEXT_LENGTH) + val answerA = ValidStringForm(formDesc = "选项A", textLength = ANSWER_TEXT_LENGTH) + val answerB = ValidStringForm(formDesc = "选项B", textLength = ANSWER_TEXT_LENGTH) + val answerC = ValidStringForm(formDesc = "选项C", textLength = ANSWER_TEXT_LENGTH) + val answerD = ValidStringForm(formDesc = "选项D", textLength = ANSWER_TEXT_LENGTH) + + return ChoiceQuestionVo( + _answers = mutableListOf(answerA, answerB, answerC, answerD), + rightAnswer = 0, + _question = questionForm, + ) } @@ -113,7 +172,7 @@ class ExamViewModel(application: Application) : ScrollViewModel(applicatio * @param callback */ fun updateExam(callback: (message: String) -> Unit) { - callback(NOT_IMPL_TIP) + } /** @@ -130,36 +189,10 @@ class ExamViewModel(application: Application) : ScrollViewModel(applicatio * */ fun load() { - TODO("加载题目") - } - /** - *TODO 加载更多题目 - * - * @param callback - */ - fun loadMore(callback: (message: String) -> Unit) { -// _data.value?.apply { -// val list= mutableListOf() -// list.addAll(this) -// list.apply { -// repeat(10) { -// if (Random.nextBoolean()) add(OpenQuestionsVo(question = "这是一道开放题:$size")) else add( -// ChoiceQuestionVo( -// question = "这是一道选择题:$size,请从选项中选出正确答案", -// answers = listOf("选项A", "选项B", "选项C", "选项D"), -// rightAnswer = 3 -// ) -// ) -// } -// } -// _data.postValue(list) -// callback("成功加载更多题目") -// } - -// callback(NOT_IMPL_TIP) } + fun addQuestion() { _data.value?.apply { _newExam.value?.let { 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 37df963..3554ab9 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 @@ -158,10 +158,8 @@ class RegAssociationViewModel(application: Application) : AndroidViewModel(appli * @param callback */ fun register(callback: (value: String) -> Unit) { - val nameValue = name.formValue.value - val descValue = desc.formValue.value val fileId = _fileId.value - if (nameValue != null && descValue != null && fileId != null && + if (fileId != null && name.statusForm.value == FormStatus.Valid && desc.statusForm.value == FormStatus.Valid ) { viewModelScope.launch { @@ -177,8 +175,8 @@ class RegAssociationViewModel(application: Application) : AndroidViewModel(appli Logger.e(it) }, typeToken = object : TypeToken>() {}.type), jsonParam = AssociationRegVo( - name = nameValue, - desc = descValue, + name = name.getValue(), + desc = desc.getValue(), fileId = fileId, associationId = _checkInfo.value?.body?.associationVo?.associationId, token = TokenManager.getToken() diff --git a/foreground/src/main/java/com/gyf/csams/association/model/RenameViewModel.kt b/foreground/src/main/java/com/gyf/csams/association/model/RenameViewModel.kt index f07b224..c7b963a 100644 --- a/foreground/src/main/java/com/gyf/csams/association/model/RenameViewModel.kt +++ b/foreground/src/main/java/com/gyf/csams/association/model/RenameViewModel.kt @@ -1,8 +1,14 @@ package com.gyf.csams.association.model +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel -import com.gyf.lib.uikit.StringForm -import com.gyf.lib.util.NOT_IMPL_TIP +import androidx.lifecycle.viewModelScope +import com.google.gson.reflect.TypeToken +import com.gyf.csams.module.* +import com.gyf.lib.uikit.AsyncStringForm +import com.gyf.lib.util.* +import kotlinx.coroutines.launch /** * 社团重命名状态管理 @@ -11,18 +17,79 @@ import com.gyf.lib.util.NOT_IMPL_TIP class RenameViewModel : ViewModel() { val menuName = "换名申请表" - val oldName = StringForm(formDesc = "社团原名", textLength = 10) - val newName = StringForm(formDesc = "社团新名", textLength = 10) - val cause = StringForm(formDesc = "换名原因", textLength = 30) + val oldName = AsyncStringForm(formDesc = "社团原名", textLength = 10) - val postDesc = "提交申请" - val back = "返回" + val newName = AsyncStringForm(formDesc = "社团新名", textLength = 10) + + val cause = AsyncStringForm(formDesc = "换名原因", textLength = 30) + + private val _actionResult = MutableLiveData() + val actionResult: LiveData = _actionResult + + private fun clean() { + newName.clean() + cause.clean() + } + + private val _checkInfo = MutableLiveData>() + val checkInfo: LiveData> = _checkInfo + + init { + read() + } + + /** + * 提交重命名申请 + * + */ + fun apply(associationId: Int) { + viewModelScope.launch { + HttpClient.post( + url = Api.buildUrl(AssociationApi.RenameRegister), + callback = HttpCallback(action = "提交换名申请表", onSuccess = { + it.body?.let { + if (it) { + clean() + } + } + _actionResult.postValue(it.message) + }, typeToken = object : TypeToken>() {}.type), + jsonParam = RenameApplyVo( + + rename = RenameVo( + newName = newName.getValue(), + cause = cause.getValue(), + renameId = _checkInfo.value?.body?.renameVo?.renameId + ), + associationId = associationId, + token = TokenManager.getToken() + ) + ) + } + } /** - * TODO 提交表单 + * 查看审核进度 * + * @param callback */ - fun post(callback: (message: String) -> Unit) { - callback(NOT_IMPL_TIP) + private fun read() { + viewModelScope.launch { + HttpClient.post(url = Api.buildUrl(AssociationApi.RenameRead), + callback = HttpCallback(action = "查看审核进度", + onSuccess = { it -> + _checkInfo.postValue(it) + it.body?.renameVo?.let { + newName.setValue(it.newName) + cause.setValue(it.cause) + } + + }, 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/association/ui/AssociationActivity.kt b/foreground/src/main/java/com/gyf/csams/association/ui/AssociationActivity.kt index 3e98391..d875346 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 @@ -3,7 +3,9 @@ package com.gyf.csams.association.ui import android.content.Intent import android.os.Bundle import androidx.activity.ComponentActivity +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 @@ -11,9 +13,7 @@ import androidx.compose.foundation.layout.* import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.rememberLazyListState 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.ui.Alignment import androidx.compose.ui.Modifier @@ -34,6 +34,8 @@ import com.gyf.csams.module.ActivityVo import com.gyf.csams.uikit.* import com.gyf.lib.uikit.* import com.gyf.lib.util.TokenManager +import com.orhanobut.logger.Logger +import kotlinx.coroutines.delay /** @@ -45,7 +47,7 @@ class AssociationActivity : ComponentActivity() { private val associationId: Int get() { val id = intent.getIntExtra( - AssociationActivity::javaClass.name, + AssociationActivity::class.java.name, 0 ) return if (id == 0) throw IllegalArgumentException("社团id:${id}不合法,初始化失败") else id @@ -63,12 +65,26 @@ class AssociationActivity : ComponentActivity() { val intent = Intent(this, ExamActivity::class.java) val expanded by model.expanded.observeAsState(false) + var message: String? by remember { + mutableStateOf(null) + } + //TODO重命名操作反馈 + val rename = + rememberLauncherForActivityResult(contract = ActivityResultContracts.StartActivityForResult()) { + if (it.resultCode == RESULT_OK) { + val m = it.data?.getStringExtra(RenameActivity::class.java.name) + Logger.i("社团重命名返回:${m}") + message = m + } + } Column { TextTopAppBar(nav = nav, currentMenuName = currentMenuName.menuName, menuNames = AssociationMenu.values(), iconMenu = { model.switchType() }) { Row { + + DropdownMenu( expanded = expanded, onDismissRequest = { }, @@ -85,7 +101,7 @@ class AssociationActivity : ComponentActivity() { ApplyActActivity::class.java ).apply { putExtra( - AssociationActivity::javaClass.name, + AssociationActivity::class.java.name, associationId ) } @@ -120,12 +136,15 @@ class AssociationActivity : ComponentActivity() { } } DropdownMenuItem(onClick = { - startActivity( - Intent( - this@AssociationActivity, - ReNameActivity::class.java + rename.launch(Intent( + this@AssociationActivity, + RenameActivity::class.java + ).apply { + putExtra( + AssociationActivity::class.java.name, + associationId ) - ) + }) model.close() }) { Row(verticalAlignment = Alignment.CenterVertically) { @@ -136,6 +155,7 @@ class AssociationActivity : ComponentActivity() { ) } } + } TokenManager.getUserInfo()?.associationVo == null -> DropdownMenuItem( onClick = { @@ -187,6 +207,22 @@ class AssociationActivity : ComponentActivity() { composable(AssociationMenu.Main.name) { model.clickMenu(AssociationMenu.Main) Main() + //TODO 提示 + val scaffoldModel: ScaffoldModel = viewModel() + message?.let { + scaffoldModel.update(message = message, actionLabel = "刷新") + + val s by scaffoldModel.data.observeAsState() + if (s == null) { + message = null +// nav.navigate(AssociationMenu.Main.name) + } + LaunchedEffect(message) { + delay(it.length * 300L) + message = null +// nav.navigate(AssociationMenu.Main.name) + } + } ShowSnackbar(scaffoldState = scaffoldState) } composable(AssociationMenu.ActivityList.name) { @@ -202,6 +238,18 @@ class AssociationActivity : ComponentActivity() { } } + //TODO下拉菜单操作反馈 + @Composable + private fun ShowTip( + model: AssociationViewModel = viewModel(), + scaffoldModel: ScaffoldModel = viewModel() + ) { + val m by model.dropDownMenuResult.observeAsState() + m?.let { + Logger.i("收到${it}") + scaffoldModel.update(message = it, actionLabel = "关闭提示") + } + } /** * 社团成员 @@ -466,9 +514,7 @@ class AssociationActivity : ComponentActivity() { private fun OngoingActivity( modifier: Modifier = Modifier ) { - Row(modifier = modifier.clickable(onClick = { - startActivity(Intent(this, ActivityDetailActivity::class.java)) - }), horizontalArrangement = Arrangement.Center) { + Row(horizontalArrangement = Arrangement.Center) { val weight = 0.5F val spaceWeight = (1 - 0.5F) / 2 Spacer(modifier = Modifier.weight(spaceWeight)) 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 17873f1..a0572ce 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 @@ -18,12 +18,7 @@ import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import androidx.lifecycle.viewmodel.compose.viewModel 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.association.model.* import com.gyf.csams.uikit.Background import com.gyf.csams.uikit.BackgroundImage import com.gyf.lib.uikit.BaseTextField @@ -119,9 +114,9 @@ class ExamActivity : ComponentActivity() { newExam?.let { item { Column { - OutlinedButton(onClick = { model.switchType(it) }) { - Text(text = "切换到${if (newExam is ChoiceQuestionVo) "开放题" else "选择题"}") - } +// OutlinedButton(onClick = { model.switchType(it) }) { +// Text(text = "切换到${if (newExam is ChoiceQuestionVo) "开放题" else "选择题"}") +// } ExamChild(it = it, examHeight = examHeight, isAdd = true) } } @@ -159,9 +154,9 @@ class ExamActivity : ComponentActivity() { } - if (listState.layoutInfo.totalItemsCount - listState.firstVisibleItemIndex == model.initSize / 2 - 1) { - model.loadMore { scaffoldModel.update(message = it) } - } +// if (listState.layoutInfo.totalItemsCount - listState.firstVisibleItemIndex == model.initSize / 2 - 1) { +// model.loadMore { scaffoldModel.update(message = it) } +// } } @@ -175,17 +170,16 @@ class ExamActivity : ComponentActivity() { @Composable private fun Question( modifier: Modifier = Modifier, - exam: Exam, - model: ExamViewModel = viewModel() + exam: Exam ) { - /*问题**/ - val s = model.createQuestion() - BaseTextField( - form = s, - modifier = modifier - .fillMaxSize() - .background(color = MaterialTheme.colors.background) - ) + exam._question?.let { + BaseTextField( + form = it, + modifier = modifier + .fillMaxSize() + .background(color = MaterialTheme.colors.background) + ) + } } @@ -201,43 +195,46 @@ class ExamActivity : ComponentActivity() { exam: Exam ) { val list by model.data.observeAsState() - val newExam by model.newExam.observeAsState() - Box( - contentAlignment = Alignment.Center, - modifier = modifier - ) { - IconButton(onClick = { - if (isAdd) { - if ((newExam?.question ?: "").isNotEmpty()) { - scaffoldModel.update( - message = model.addTip, - actionLabel = model.actionLabel - ) { - model.addQuestion() + model.newExam.value?._question?.let { + val value by it.formValue.observeAsState() + Box( + contentAlignment = Alignment.Center, + modifier = modifier + ) { + IconButton(onClick = { + if (isAdd) { + if ((value?.isNotEmpty() == true)) { + scaffoldModel.update( + message = model.addTip, + actionLabel = model.actionLabel + ) { + model.addQuestion() + } + } else { + scaffoldModel.update(message = model.questionIsNull) } - } else { - scaffoldModel.update(message = model.questionIsNull) - } - } else { - if (list?.size == 1) { - scaffoldModel.update(model.deleteLeastOne) } else { - scaffoldModel.update( - message = model.deleteTip, - actionLabel = model.actionLabel - ) { - model.deleteQuestion(exam = exam) + if (list?.size == 1) { + scaffoldModel.update(model.deleteLeastOne) + } else { + scaffoldModel.update( + message = model.deleteTip, + actionLabel = model.actionLabel + ) { + model.deleteQuestion(exam = exam) + } } } + }) { + Icon( + painter = painterResource(id = if (isAdd) R.drawable.ic_add_select else R.drawable.ic_sami_select), + contentDescription = null + ) } - }) { - Icon( - painter = painterResource(id = if (isAdd) R.drawable.ic_add_select else R.drawable.ic_sami_select), - contentDescription = null - ) } } + } @@ -309,7 +306,7 @@ class ExamActivity : ComponentActivity() { .weight(1 - questionWeight) ) { - choiceQuestionVo.answers.apply { + choiceQuestionVo._answers.apply { Column { forEach { Row( @@ -327,8 +324,8 @@ class ExamActivity : ComponentActivity() { val isRightAnswer = choiceQuestionVo.rightAnswer == answerIndex RadioButton(selected = isRightAnswer, onClick = click) - val c = model.createQuestion() - BaseTextField(form = c) + BaseTextField(form = it) + } } } diff --git a/foreground/src/main/java/com/gyf/csams/association/ui/ReNameActivity.kt b/foreground/src/main/java/com/gyf/csams/association/ui/ReNameActivity.kt deleted file mode 100644 index b14f535..0000000 --- a/foreground/src/main/java/com/gyf/csams/association/ui/ReNameActivity.kt +++ /dev/null @@ -1,99 +0,0 @@ -package com.gyf.csams.association.ui - -import android.os.Bundle -import androidx.activity.ComponentActivity -import androidx.activity.compose.setContent -import androidx.compose.foundation.layout.* -import androidx.compose.material.MaterialTheme -import androidx.compose.material.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.unit.dp -import androidx.lifecycle.viewmodel.compose.viewModel -import com.gyf.csams.association.model.RenameViewModel -import com.gyf.csams.uikit.Background -import com.gyf.csams.uikit.BackgroundImage -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.util.BottomButton - -/** - * 社团重命名 - * - */ -class ReNameActivity : ComponentActivity() { - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - - setContent { - Body { - MainColumnFrame(background = { Background(image = BackgroundImage.Rename) }) { - Spacer( - modifier = Modifier - .weight(0.2F) - ) - Title(modifier = Modifier.weight(0.1F)) - - OldName(modifier = Modifier.weight(0.1F)) - - NewName(modifier = Modifier.weight(0.1F)) - - Cause(modifier = Modifier.weight(0.2F)) - - Spacer(modifier = Modifier.height(10.dp)) - val model: RenameViewModel = viewModel() - val scaffoldModel: ScaffoldModel = viewModel() - BottomButton( - modifier = Modifier - .weight(0.1F) - .fillMaxWidth() - ) { - model.post { scaffoldModel.update(message = it) } - } - - Spacer(modifier = Modifier.weight(1 - 0.2F * 2 - 0.1F * 4)) - } - } - } - } - - /** - * 标题 - * - */ - @Composable - private fun Title(modifier: Modifier = Modifier, model: RenameViewModel = viewModel()) { - Row(modifier = modifier.fillMaxWidth(), horizontalArrangement = Arrangement.Center) { - Text(text = model.menuName, style = MaterialTheme.typography.h4) - } - } - - /** - * 社团原名 - * - */ - @Composable - private fun OldName(modifier: Modifier = Modifier, model: RenameViewModel = viewModel()) { - BaseTextField(form = model.oldName, modifier = modifier.fillMaxWidth(), singeLine = true) - } - - /** - * 社团新名 - * - */ - @Composable - private fun NewName(modifier: Modifier = Modifier, model: RenameViewModel = viewModel()) { - BaseTextField(form = model.newName, modifier = modifier.fillMaxWidth(), singeLine = true) - } - - /** - * 换名原因 - * - */ - @Composable - private fun Cause(modifier: Modifier = Modifier, model: RenameViewModel = viewModel()) { - BaseTextField(form = model.cause, modifier = modifier.fillMaxWidth()) - } -} \ No newline at end of file diff --git a/foreground/src/main/java/com/gyf/csams/association/ui/RenameActivity.kt b/foreground/src/main/java/com/gyf/csams/association/ui/RenameActivity.kt new file mode 100644 index 0000000..60f00c9 --- /dev/null +++ b/foreground/src/main/java/com/gyf/csams/association/ui/RenameActivity.kt @@ -0,0 +1,195 @@ +package com.gyf.csams.association.ui + +import android.content.Intent +import android.os.Bundle +import androidx.activity.ComponentActivity +import androidx.activity.compose.setContent +import androidx.compose.foundation.layout.* +import androidx.compose.material.MaterialTheme +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +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.gyf.csams.association.model.AssociationViewModel +import com.gyf.csams.association.model.RenameViewModel +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.BaseTextField +import com.gyf.lib.uikit.Body +import com.gyf.lib.uikit.MainColumnFrame +import com.gyf.lib.uikit.checkForm +import com.gyf.lib.util.BottomButton +import com.orhanobut.logger.Logger + +/** + * 社团重命名 + * + */ +class RenameActivity : ComponentActivity() { + + private val associationId: Int + get() { + val id = intent.getIntExtra( + AssociationActivity::class.java.name, + 0 + ) + return if (id == 0) throw IllegalArgumentException("社团id:${id}不合法,初始化失败") else id + } + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + setContent { + Body { + MainColumnFrame(background = { Background(image = BackgroundImage.Rename) }) { + val model: RenameViewModel = viewModel() + val checkInfo by model.checkInfo.observeAsState() + + checkInfo?.body?.auditCheckVo.let { + if (it == null) { + Title(modifier = Modifier.weight(0.2F)) + } else { + Title() + CheckTip(it = it, modifier = Modifier.weight(0.15F)) + } + } + + + + OldName(modifier = Modifier.weight(0.1F)) + + NewName(modifier = Modifier.weight(0.1F)) + + Cause(modifier = Modifier.weight(0.2F)) + + Spacer(modifier = Modifier.height(10.dp)) + + val oldNameStatus by model.oldName.statusForm.observeAsState() + val newNameStatus by model.newName.statusForm.observeAsState() + + + val cause by model.cause.statusForm.observeAsState() + + val hasError = repeatError() + BottomButton( + modifier = Modifier + .weight(0.1F) + .fillMaxWidth(), + enabled = checkForm(newNameStatus, cause) && !hasError + ) { + + model.apply(associationId = associationId) + } + + + val actionResult by model.actionResult.observeAsState() + actionResult?.let { + if (it.isNotEmpty()) { + setResult( + RESULT_OK, + Intent().apply { + putExtra( + RenameActivity::class.java.name, + actionResult + ) + }) + finish() + } else { + Logger.w("申请已提交,但是没有收到返回") + } + } + + Spacer(modifier = Modifier.weight(1 - 0.2F * 2 - 0.1F * 4)) + } + } + } + } + + //TODO 合并ValidStringForm + @Composable + private fun repeatError(model: RenameViewModel = viewModel()): Boolean { + val oldName by model.oldName.formValue.observeAsState() + val newName by model.newName.formValue.observeAsState() + return oldName?.isNotEmpty() == true && newName?.isNotEmpty() == true && oldName == newName + } + + @Composable + private fun isReadOnly(model: RenameViewModel): Boolean { + val checkInfo by model.checkInfo.observeAsState() + val flag = (checkInfo?.body?.let { it.auditCheckVo.checkStatus != CheckStatus.Finish }) + Logger.d("flag=${flag}") + return flag == true + } + + /** + * 标题 + * + */ + @Composable + private fun Title(modifier: Modifier = Modifier, model: RenameViewModel = viewModel()) { + Row(modifier = modifier.fillMaxWidth(), horizontalArrangement = Arrangement.Center) { + Text(text = model.menuName, style = MaterialTheme.typography.h6) + } + } + + /** + * 社团原名 + * + */ + @Composable + private fun OldName( + modifier: Modifier = Modifier, + model: RenameViewModel = viewModel(), + ass: AssociationViewModel = viewModel() + ) { + LaunchedEffect(associationId) { + ass.load(id = associationId) + } + + val associationVo by ass.associationVo.observeAsState() + associationVo?.let { + model.oldName.setValue(it.associationVo.name) + } + BaseTextField( + form = model.oldName, modifier = modifier.fillMaxWidth(), singeLine = true, + readOnly = true, isError = repeatError() + ) + + if (repeatError()) { + Text(text = "社团原名和社团新名不能重复", color = MaterialTheme.colors.error) + } + } + + /** + * 社团新名 + * + */ + @Composable + private fun NewName(modifier: Modifier = Modifier, model: RenameViewModel = viewModel()) { + BaseTextField( + form = model.newName, modifier = modifier.fillMaxWidth(), singeLine = true, + readOnly = isReadOnly(model = model), isError = repeatError() + ) + if (repeatError()) { + Text(text = "社团原名和社团新名不能重复", color = MaterialTheme.colors.error) + } + } + + /** + * 换名原因 + * + */ + @Composable + private fun Cause(modifier: Modifier = Modifier, model: RenameViewModel = viewModel()) { + BaseTextField( + form = model.cause, modifier = modifier.fillMaxWidth(), + readOnly = isReadOnly(model = model) + ) + } +} \ No newline at end of file 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 da9aff7..a224e04 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 @@ -96,7 +96,7 @@ class MarqueeViewModel : AbstractComment() { }, typeToken = object : TypeToken>() {}.type ), jsonParam = LeaveMessageVo( - message = newContent.formValue.value ?: "", + message = newContent.getValue(), token = TokenManager.getToken() ) ) 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 8dd822f..1bd0e62 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 @@ -26,6 +26,11 @@ import androidx.navigation.NavHostController import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable import com.google.accompanist.coil.rememberCoilPainter +import com.google.accompanist.imageloading.ImageLoadState +import com.google.accompanist.pager.ExperimentalPagerApi +import com.google.accompanist.pager.HorizontalPager +import com.google.accompanist.pager.PagerState +import com.google.accompanist.pager.rememberPagerState import com.gyf.csams.R import com.gyf.csams.account.model.AccountViewModel import com.gyf.csams.account.model.RefreshViewModel @@ -34,14 +39,12 @@ 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.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.module.* import com.gyf.csams.uikit.* import com.gyf.lib.service.BaseActivity import com.gyf.lib.uikit.* import com.gyf.lib.util.* +import com.orhanobut.logger.Logger /** @@ -52,23 +55,20 @@ class MainActivity : BaseActivity() { override val clientType: ClientType = ClientType.Foreground + @ExperimentalPagerApi override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { - - val imageViewModel: ImageViewModel = viewModel() NavBody { nav, scaffoldState -> NavHost(navController = nav, startDestination = MainMenu.Main.name) { composable(MainMenu.Main.name) { Main(navController = nav) ShowSnackbar(scaffoldState = scaffoldState) - imageViewModel.start() } composable(MainMenu.List.name) { AssociationList(navController = nav) ShowSnackbar(scaffoldState = scaffoldState) - imageViewModel.cancel() } composable(MainMenu.Center.name) { val refresh: RefreshViewModel = viewModel() @@ -78,7 +78,6 @@ class MainActivity : BaseActivity() { Center(navController = nav) ShowSnackbar(scaffoldState = scaffoldState) } - imageViewModel.cancel() } } @@ -124,7 +123,7 @@ class MainActivity : BaseActivity() { this@MainActivity, AssociationActivity::class.java ).apply { - putExtra(AssociationActivity::javaClass.name, it) + putExtra(AssociationActivity::class.java.name, it) }) } // CenterMenuItem(text = model.myJoinActivity) @@ -171,6 +170,7 @@ class MainActivity : BaseActivity() { /** * 主界面 */ + @ExperimentalPagerApi @Composable private fun Main(navController: NavHostController) { MainColumnFrame( @@ -178,21 +178,27 @@ class MainActivity : BaseActivity() { mainMenu = MainMenu.Main, nav = navController ) { - Column(modifier = Modifier.weight(0.33F)) { - Notification() - Column( - modifier = Modifier - .fillMaxSize() - .padding(horizontal = 15.dp), - verticalArrangement = Arrangement.SpaceEvenly - ) { - MessageBoard() - ClubActivitiesTitle() + val viewModel: ImageViewModel = viewModel() + val imageList by viewModel.imageList.observeAsState() + imageList?.let { + val pagerState = rememberPagerState(pageCount = it.size) + Column(modifier = Modifier.weight(0.33F)) { + Notification() + Column( + modifier = Modifier + .fillMaxSize() + .padding(horizontal = 15.dp), + verticalArrangement = Arrangement.SpaceEvenly + ) { + MessageBoard() + ClubActivitiesTitle(vo = it[pagerState.currentPage]) + } + } + Column(modifier = Modifier.weight(0.66F)) { + PosterWithDesc(pagerState = pagerState, imgList = it) } } - Column(modifier = Modifier.weight(0.66F)) { - PosterWithDesc() - } + } } @@ -235,9 +241,6 @@ class MainActivity : BaseActivity() { 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) } } @@ -318,7 +321,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.associationId) + intent.putExtra(AssociationActivity::class.java.name, associationVo.associationId) startActivity(intent) })) { val backgroundImage = rememberCoilPainter(request = R.drawable.association_list_border) @@ -459,8 +462,9 @@ class MainActivity : BaseActivity() { * 活动标题 * */ + @ExperimentalPagerApi @Composable - private fun ClubActivitiesTitle(modifier: Modifier = Modifier) { + private fun ClubActivitiesTitle(modifier: Modifier = Modifier, vo: MainActivityPhotoVo) { Card(modifier = modifier, backgroundColor = MaterialTheme.colors.background) { Row( modifier = Modifier @@ -469,7 +473,7 @@ class MainActivity : BaseActivity() { verticalAlignment = Alignment.CenterVertically ) { Text( - text = "超级课程表X滴滴出行-了不起的社团", + text = vo.activityVo.activityName, style = MaterialTheme.typography.h6, overflow = TextOverflow.Ellipsis, maxLines = 1 @@ -483,35 +487,72 @@ class MainActivity : BaseActivity() { * 带介绍活动海报 * */ + @ExperimentalPagerApi @Composable private fun PosterWithDesc( - scaffoldModel: ScaffoldModel = viewModel(), - viewModel: ImageViewModel = viewModel() + pagerState: PagerState, + imgList: List ) { + imgList.let { + + HorizontalPager(state = pagerState) { page -> + // Our page content + Logger.i("page=${page}") + Column { + val photo = rememberCoilPainter(request = Api.buildUrl(it[page].url)) + Poster( + modifier = Modifier + .weight(0.6F) + .fillMaxWidth() + ) { + when (photo.loadState) { + is ImageLoadState.Loading -> { + // Display a circular progress indicator whilst loading + CircularProgressIndicator() + } + is ImageLoadState.Error -> { + // If you wish to display some content if the request fails + Logger.e("轮播图加载失败") + } + else -> + it[page].apply { + Image( + painter = photo, + contentDescription = activityVo.activityName, + modifier = Modifier.clickable(onClick = { + startActivity( + Intent( + this@MainActivity, + ActivityDetailActivity::class.java + ).apply { + putExtra( + ActivityDetailActivity::class.java.name, + activityVo.activityId + ) + putExtra( + AssociationActivity::class.java.name, + associationVo.associationId + ) + }) + }) + ) + } - val error by viewModel.error.observeAsState() - error?.let { - scaffoldModel.update(message = it) - viewModel.clearError() - } - Carousel(imageBitmap = viewModel.image) { - Column(modifier = Modifier.clickable(onClick = { - startActivity(Intent(this, ActivityDetailActivity::class.java)) - })) { - Poster( - modifier = Modifier - .weight(0.6F) - .fillMaxWidth() - ) - - DescCard( - modifier = Modifier - .weight(0.4F) - .fillMaxWidth(), - content = randomChinese(500) - ) + } + } + DescCard( + modifier = Modifier + .weight(0.4F) + .fillMaxWidth(), + content = it[page].activityVo.activityDesc + ) + } } + + } + + } } 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 d0d418d..c794d80 100644 --- a/foreground/src/main/java/com/gyf/csams/uikit/BaseView.kt +++ b/foreground/src/main/java/com/gyf/csams/uikit/BaseView.kt @@ -462,6 +462,25 @@ fun Background(image: BackgroundImage, alpha: Float = DefaultAlpha) { } +@Composable +fun Poster(modifier: Modifier = Modifier, image: @Composable () -> Unit) { + Card( + modifier = modifier, + backgroundColor = Color.Transparent + ) { + Box(contentAlignment = Alignment.Center) { + Image( + painter = painterResource(id = R.drawable.hot_activity_background), + contentDescription = null, + modifier = Modifier.fillMaxSize() + ) + Box(modifier = Modifier.padding(vertical = 10.dp)) { + image() + } + } + } +} + /** * 活动海报 * diff --git a/foreground/src/main/java/com/gyf/csams/uikit/ViewModel.kt b/foreground/src/main/java/com/gyf/csams/uikit/ViewModel.kt index f5b01dd..261b096 100644 --- a/foreground/src/main/java/com/gyf/csams/uikit/ViewModel.kt +++ b/foreground/src/main/java/com/gyf/csams/uikit/ViewModel.kt @@ -1,100 +1,48 @@ package com.gyf.csams.uikit import android.app.Application -import androidx.compose.ui.graphics.ImageBitmap import androidx.lifecycle.AndroidViewModel import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.viewModelScope import com.google.gson.reflect.TypeToken -import com.gyf.csams.R import com.gyf.csams.module.ApiResponse +import com.gyf.csams.module.ClientType +import com.gyf.csams.module.MainActivityPhotoVo import com.gyf.lib.util.* -import com.orhanobut.logger.Logger -import kotlinx.coroutines.Job -import kotlinx.coroutines.delay import kotlinx.coroutines.launch class ImageViewModel(application: Application) : AndroidViewModel(application) { - private val _image = MutableLiveData() - private val _imageUrls = MutableLiveData?>() - val image: LiveData = _image - private var job: Job? = null - private val _error = MutableLiveData() - val error: LiveData = _error - private val urlPath = Api.buildUrl(MainApi.HotActivity) - fun clearError() { - _error.value = null - } - /** - * 加载默认图片 - * - */ - private fun defaultLoad() { - viewModelScope.launch { - _image.postValue( - ImageUtil.getImage( - getApplication(), - R.drawable.ic_launcher_foreground - ) - ) - } + private val _imageList = MutableLiveData>() + val imageList: LiveData> = _imageList + + init { + load() } /** * 循环加载网络图片 * */ - fun start() { - Logger.i("启动轮播") - if (job == null || job?.isCompleted == true || job?.isCancelled == true) { - job = viewModelScope.launch { - - HttpClient.get( - url = urlPath, - HttpCallback>("获取轮播图", onSuccess = { - _imageUrls.postValue(it.body) - var index = 0 - _imageUrls.value?.apply { - viewModelScope.launch { - do { - val imageBitmap = - ImageUtil.getImage( - context = getApplication(), - data = get(index) - ) - Logger.e("成功从image url:${get(index)}解析图片") - imageBitmap?.apply { - _image.postValue(this) - } - delay(5000) - index = if (index == size - 1) 0 else index.plus(1) - } while (job?.isActive == true) - } + fun load() { + viewModelScope.launch { + HttpClient.post( + url = Api.buildUrl(MainApi.HotActivity), + callback = HttpCallback>(action = "加载活动轮播图", + onSuccess = { + it.body?.let { + _imageList.postValue(it) } - }, onFail = { - Logger.e("无法从接口地址:${urlPath}获取图片url列表") - _error.postValue(it) - defaultLoad() - }, typeToken = object : TypeToken>>() {}.type) - ) - }.apply { - start() - } + }, + typeToken = object : TypeToken>>() {}.type + ), + jsonParam = OnlyToken(clientType = ClientType.Foreground) + ) } } - fun cancel() { - Logger.i("停止轮播") - job?.cancel() - } - - override fun onCleared() { - super.onCleared() - cancel() - } } 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 b423fc2..78754d7 100644 --- a/foreground/src/main/java/com/gyf/csams/util/GsonUtil.kt +++ b/foreground/src/main/java/com/gyf/csams/util/GsonUtil.kt @@ -2,12 +2,8 @@ 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.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.csams.association.model.* + import com.gyf.lib.uikit.StringForm import java.lang.reflect.Type 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 e47e608..d274fb9 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,8 @@ package com.gyf.csams.util import com.google.gson.Gson import com.google.gson.GsonBuilder +import com.gyf.csams.association.model.Exam import com.gyf.csams.module.ApiResponse -import com.gyf.csams.module.Exam import com.gyf.lib.util.HttpCallback import java.lang.reflect.Type diff --git a/foreground/src/test/java/com/gyf/csams/ExampleUnitTest.kt b/foreground/src/test/java/com/gyf/csams/ExampleUnitTest.kt index ee2401d..d553186 100644 --- a/foreground/src/test/java/com/gyf/csams/ExampleUnitTest.kt +++ b/foreground/src/test/java/com/gyf/csams/ExampleUnitTest.kt @@ -50,7 +50,7 @@ class ExampleUnitTest { @Test fun testLib() { - + println(mutableListOf(('A'..'D').map { "选项${it}" })) } } diff --git a/lib/build.gradle.kts b/lib/build.gradle.kts index 8b45be6..d103af6 100644 --- a/lib/build.gradle.kts +++ b/lib/build.gradle.kts @@ -63,6 +63,7 @@ dependencies { api("com.google.accompanist:accompanist-insets:$accompanist_version") api("com.google.accompanist:accompanist-systemuicontroller:$accompanist_version") api("com.google.accompanist:accompanist-coil:$accompanist_version") + api("com.google.accompanist:accompanist-pager:$accompanist_version") /** * 针对最新的平台功能和 API 调整应用,同时还支持旧设备。 * https://developer.android.com/jetpack/androidx/releases/core 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 dca5404..92ca230 100644 --- a/lib/src/main/java/com/gyf/lib/uikit/BaseTextField.kt +++ b/lib/src/main/java/com/gyf/lib/uikit/BaseTextField.kt @@ -18,6 +18,15 @@ import androidx.lifecycle.MutableLiveData import com.orhanobut.logger.Logger +fun checkForm(vararg arrayOfStates: FormStatus?): Boolean { + arrayOfStates.forEach { + if (it != FormStatus.Valid) { + return false + } + } + return true +} + enum class FormStatus { //空 Empty, @@ -25,7 +34,7 @@ enum class FormStatus { //格式不匹配 FormatError, - //学号已存在 + //重复 Repeat, //校验通过 @@ -66,6 +75,10 @@ open class StringForm(formDesc: String, val textLength: Int) : Logger.i("${formDesc}更新值:${_formValue.value}") } + fun getValue(): String { + return _formValue.value ?: throw IllegalArgumentException("获取${formDesc}失败,值为空!") + } + fun clean() { _formValue.postValue("") } 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 ca7660a..9588dc0 100644 --- a/lib/src/main/java/com/gyf/lib/util/Api.kt +++ b/lib/src/main/java/com/gyf/lib/util/Api.kt @@ -44,8 +44,13 @@ enum class AccountApi(val path: String) : UrlPath { Logout("/logout"), //刷新用户信息 - Refresh("/refresh"); + Refresh("/refresh"), + //加载部门干事概况 + Load("/load/manager"), + + //加载部门详情 + LoadDetail("${Load.path}/detail"); override fun build(): String { return "/api/account${this.path}" @@ -90,6 +95,11 @@ enum class AssociationApi(val path: String) : UrlPath { //模糊查询社团 List("/list"), + //后台社团管理 + ListAll("${List.path}/all"), + + Update("/update"), + //审核注册资料 Check("/check"), @@ -103,8 +113,25 @@ enum class AssociationApi(val path: String) : UrlPath { Load("/load"), //加载社团成员 - LoadMember("${Load.path}/members"); + LoadMember("${Load.path}/members"), + + //社团重命名 + Rename("/rename"), + + //提交换名申请表 + RenameRegister("${Rename.path}${Register.path}"), + //换名申请表受理 + RenameAccept("${Rename.path}${Accept.path}"), + + //换名申请表审核 + RenameCheck("${Rename.path}${Check.path}"), + + //换名申请表审核记录 + RenameAudit("${Rename.path}${Audit.path}"), + + //换名申请表审核进度 + RenameRead("${Rename.path}${Read.path}"); override fun build(): String { return "/api/association${this.path}" @@ -148,7 +175,10 @@ enum class ActivityApi(val path: String) : UrlPath { Comment("/comment"), //发送评论 - SendComment("${Comment.path}/send"); + SendComment("${Comment.path}/send"), + + //后台活动查看 + ListAll("/list/all"); override fun build(): String { diff --git a/lib/src/test/java/com/gyf/lib/ExampleUnitTest.kt b/lib/src/test/java/com/gyf/lib/ExampleUnitTest.kt index 63c18aa..3542a04 100644 --- a/lib/src/test/java/com/gyf/lib/ExampleUnitTest.kt +++ b/lib/src/test/java/com/gyf/lib/ExampleUnitTest.kt @@ -19,6 +19,5 @@ class ExampleUnitTest { @Test fun testClientToken() { - } } \ No newline at end of file