diff --git a/foreground/src/main/AndroidManifest.xml b/foreground/src/main/AndroidManifest.xml
index b45d465..c44cc94 100644
--- a/foreground/src/main/AndroidManifest.xml
+++ b/foreground/src/main/AndroidManifest.xml
@@ -86,6 +86,9 @@
+
+
+
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 2789789..fa6bd27 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
@@ -176,6 +176,7 @@ class AccountViewModel(application: Application) : AbstractLoginViewModel(applic
password = it.body ?: throw IllegalArgumentException("无法获取生成密码")
)
)
+ resetForm()
},
onFail = onFail,
typeToken = object : TypeToken>() {}.type
@@ -185,7 +186,6 @@ class AccountViewModel(application: Application) : AbstractLoginViewModel(applic
name = name.getValue()
)
)
- resetForm()
} else {
Logger.wtf("表单校验失败,无法$regBtnDesc!!!")
}
@@ -198,6 +198,7 @@ class AccountViewModel(application: Application) : AbstractLoginViewModel(applic
private fun resetForm() {
id.clean()
name.clean()
+ checkForm()
}
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 3b1e9df..154b313 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,10 +21,6 @@ class AssociationViewModel : ViewModel(), TopMenuInterface {
override val _currentMenu: MutableLiveData = MutableLiveData()
override val currentMenu: LiveData = _currentMenu
- private val _dropDownMenuResult = MutableLiveData()
- val dropDownMenuResult: LiveData = _dropDownMenuResult
-
-
/**
* 下拉菜单状态
*/
@@ -34,10 +30,21 @@ class AssociationViewModel : ViewModel(), TopMenuInterface {
private val _associationVo = MutableLiveData()
val associationVo: LiveData = _associationVo
- fun update(message: String?) {
- _dropDownMenuResult.postValue(message)
+ private val _applyAssociationResultVo = MutableLiveData()
+ val applyAssociationResultVo: LiveData = _applyAssociationResultVo
+
+ private val _dropMenuMessage = MutableLiveData()
+ val dropMenuMessage: LiveData = _dropMenuMessage
+
+ fun update(message: String? = null) {
+ _dropMenuMessage.postValue(message)
+ }
+
+ fun update(applyAssociationResultVo: ApplyAssociationResultVo? = null) {
+ _applyAssociationResultVo.postValue(applyAssociationResultVo)
}
+
fun load(id: Int) {
viewModelScope.launch {
HttpClient.post(
@@ -64,6 +71,29 @@ class AssociationViewModel : ViewModel(), TopMenuInterface {
_expanded.value = false
}
+ /**
+ * 申请入团
+ *
+ */
+ fun applyAssociation(associationId: Int, callback: (result: ApplyAssociationResultVo) -> Unit) {
+ viewModelScope.launch {
+ HttpClient.post(
+ url = Api.buildUrl(AssociationApi.CheckApply),
+ callback = HttpCallback(
+ action = "申请入团",
+ onSuccess = {
+ it.body?.let {
+ callback(it)
+ }
+ },
+ typeToken = object : TypeToken>() {}.type
+ ),
+ jsonParam =
+ SearchExamVo(associationId = associationId, token = TokenManager.getToken())
+ )
+ }
+ }
+
}
/**
diff --git a/foreground/src/main/java/com/gyf/csams/association/model/AuditJoinViewModel.kt b/foreground/src/main/java/com/gyf/csams/association/model/AuditJoinViewModel.kt
new file mode 100644
index 0000000..313111a
--- /dev/null
+++ b/foreground/src/main/java/com/gyf/csams/association/model/AuditJoinViewModel.kt
@@ -0,0 +1,53 @@
+package com.gyf.csams.association.model
+
+import android.app.Application
+import androidx.lifecycle.viewModelScope
+import com.google.gson.reflect.TypeToken
+import com.gyf.csams.module.ApiResponse
+import com.gyf.csams.module.AuditJoinVo
+import com.gyf.csams.module.JoinAssociationVo
+import com.gyf.csams.module.SearchExamVo
+import com.gyf.lib.model.ScrollViewModel
+import com.gyf.lib.util.*
+import kotlinx.coroutines.launch
+
+class AuditJoinViewModel(application: Application) :
+ ScrollViewModel(application = application) {
+
+ fun load(associationId: Int) {
+ viewModelScope.launch {
+ HttpClient.post(
+ url = Api.buildUrl(AssociationApi.CheckJoin),
+ callback = HttpCallback>(
+ action = "查看入团申请记录",
+ onSuccess = {
+ it.body?.let {
+ _data.postValue(it)
+ }
+ },
+ typeToken = object :
+ TypeToken>>() {}.type
+ ), jsonParam =
+ SearchExamVo(associationId = associationId, token = TokenManager.getToken())
+ )
+ }
+ }
+
+ /**
+ * 审核结果
+ *
+ * @param joinId
+ * @param result
+ */
+ fun audit(joinId: Int, result: Boolean, callback: (message: String) -> Unit) {
+ viewModelScope.launch {
+ HttpClient.post(
+ url = Api.buildUrl(AssociationApi.AuditJoin),
+ callback = HttpCallback(action = "审核入团申请", onSuccess = {
+ callback(it.message)
+ }, typeToken = object : TypeToken>() {}.type), jsonParam =
+ AuditJoinVo(joinId = joinId, result = result, token = TokenManager.getToken())
+ )
+ }
+ }
+}
\ No newline at end of file
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 ce2929d..ea1f17f 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,10 +3,15 @@ package com.gyf.csams.association.model
import android.app.Application
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
+import androidx.lifecycle.viewModelScope
+import com.google.gson.reflect.TypeToken
+import com.gyf.csams.module.*
import com.gyf.lib.model.ScrollViewModel
+import com.gyf.lib.uikit.AsyncStringForm
import com.gyf.lib.uikit.StringForm
-import com.gyf.lib.uikit.ValidStringForm
-import com.gyf.lib.util.NOT_IMPL_TIP
+import com.gyf.lib.util.*
+import com.orhanobut.logger.Logger
+import kotlinx.coroutines.launch
/**
* 题库界面类型
@@ -17,7 +22,10 @@ enum class ExamActivityType(val menuName: String) {
SET_EXAM("入团题库"),
//入团申请表
- JOIN_Association("入团申请表")
+ JOIN_Association("入团申请表"),
+
+ //查看答卷
+ Answer("查看答卷")
}
@@ -51,48 +59,57 @@ enum class ExamType(val type: String) {
OQ("开放题")
}
-abstract class Exam {
+abstract class Exam() {
abstract val examType: ExamType
+ abstract val _question: StringForm
- //**TODO 题目反序列化
- abstract val question: String?
- abstract val _question: StringForm?
+ abstract fun check(): Boolean
+ abstract val questionId: Int?
}
/**
* 选择题
*
- * @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 _answers: MutableList,
val rightAnswer: Int,
- override val question: String? = null,
- override val _question: StringForm?,
+ val chooseOption: Int? = null,
+ override val _question: StringForm,
+ override val questionId: Int? = null,
+
+ ) : Exam() {
- ) : Exam()
+ override fun check(): Boolean {
+ if (_question.formValue.value?.isEmpty() == true || _question.formValue.value == null) {
+ return false
+ }
+ _answers.forEach {
+ if (it.formValue.value == null || it.formValue.value?.isEmpty() == true) {
+ return false
+ }
+ }
+ return true
+ }
+}
/**
* 开放题
*
- * @property examType 题型描述
- * @property question 问题
- * TODO 题目反序列化
*/
data class OpenQuestionsVo(
override val examType: ExamType = ExamType.OQ,
- override val question: String? = null,
- override val _question: StringForm?
+ override val _question: StringForm,
+ override val questionId: Int?,
-) : Exam()
+ ) : Exam() {
+ override fun check(): Boolean {
+ TODO("Not yet implemented")
+ }
+}
/**
* 题库状态管理
@@ -100,53 +117,64 @@ data class OpenQuestionsVo(
*/
class ExamViewModel(application: Application) : ScrollViewModel(application) {
- val questionIsNull: String = "问题不能为空"
- val deleteLeastOne: String = "至少保留一道题目"
+ val questionIsNull: String = "问题或答案为空"
val deleteTip = "确定删除此题目?"
val addTip = "确定添加此题目?"
val actionLabel = "确定"
- private val _newExam: MutableLiveData = MutableLiveData(createExam(ExamType.CQ))
+ private val _newExam: MutableLiveData = MutableLiveData()
val newExam: LiveData = _newExam
- init {
- load()
- }
-
-
-
- /**
- * 切换题型
- *
- */
- fun switchType(exam: Exam) {
- if (exam is ChoiceQuestionVo) _newExam.value = createExam(ExamType.OQ) else _newExam.value =
- createExam(ExamType.CQ)
- }
+ private val _deleteIds = mutableListOf()
+ private val _allowPostAnswer = MutableLiveData()
+ val allowPostAnswer: LiveData = _allowPostAnswer
/**
* 创建题目
*
- * @param type
* @return
*/
- private fun createExam(type: ExamType): Exam {
-
- 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,
- )
+ private fun createExam(examVo: ExamVo? = null, answer: Int? = null): Exam {
+ val questionForm = AsyncStringForm(formDesc = "问题", textLength = QUESTION_TEXT_LENGTH)
+ val answerA = AsyncStringForm(formDesc = "选项A", textLength = ANSWER_TEXT_LENGTH)
+ val answerB = AsyncStringForm(formDesc = "选项B", textLength = ANSWER_TEXT_LENGTH)
+ val answerC = AsyncStringForm(formDesc = "选项C", textLength = ANSWER_TEXT_LENGTH)
+ val answerD = AsyncStringForm(formDesc = "选项D", textLength = ANSWER_TEXT_LENGTH)
+ if (examVo != null) {
+ questionForm.setValue(examVo.question)
+ answerA.setValue(examVo.optionsA)
+ answerB.setValue(examVo.optionsB)
+ answerC.setValue(examVo.optionsC)
+ answerD.setValue(examVo.optionsD)
+ return ChoiceQuestionVo(
+ _answers = mutableListOf(answerA, answerB, answerC, answerD),
+ rightAnswer = examVo.rightOption,
+ _question = questionForm,
+ questionId = examVo.questionId,
+ chooseOption = answer
+ )
+ } else {
+ return ChoiceQuestionVo(
+ _answers = mutableListOf(answerA, answerB, answerC, answerD),
+ rightAnswer = 0,
+ _question = questionForm,
+ )
+ }
+
+
}
+ fun checkChooseAnswer() {
+ _data.value?.forEach {
+ if (it is ChoiceQuestionVo && it.chooseOption == null) {
+ _allowPostAnswer.postValue(false)
+ return
+ }
+ }
+ _allowPostAnswer.postValue(true)
+ }
/**
* 更新题目
@@ -167,32 +195,153 @@ class ExamViewModel(application: Application) : ScrollViewModel(applicatio
}
/**
- * TODO 更新题库
+ * 更新题库
*
* @param callback
*/
- fun updateExam(callback: (message: String) -> Unit) {
+ fun updateExam(associationId: Int, callback: (message: String) -> Unit) {
+ viewModelScope.launch {
+ _data.value?.dropLast(1)?.mapNotNull { it ->
+ if (it is ChoiceQuestionVo) {
+ toExamVo(choiceQuestionVo = it)
+ } else {
+ null
+ }
+ }?.apply {
+ HttpClient.post(url = Api.buildUrl(AssociationApi.UpdateExam),
+ callback = HttpCallback(action = "更新题库",
+ onSuccess = {
+ callback(it.message)
+ }, typeToken = object : TypeToken>() {}.type
+ ),
+ jsonParam = AddExamVo(
+ questions = this,
+ associationId = associationId,
+ token = TokenManager.getToken(),
+ deleteIds = _deleteIds
+ )
+ )
+ }
+ }
+ }
+ private fun toExamVo(choiceQuestionVo: ChoiceQuestionVo): ExamVo? {
+ return choiceQuestionVo.let {
+ val options = it._answers.map {
+ it.getValue()
+ }
+ if (options.size == 4) {
+ ExamVo(
+ question = it._question.getValue(), optionsA = options[0],
+ optionsB = options[1], optionsC = options[2], optionsD = options[3],
+ rightOption = it.rightAnswer,
+
+ questionId = it.questionId
+ )
+ } else {
+ null
+ }
+ }
}
/**
- * TODO 提交答案
- *
+ * 提交答卷
* @param callback
*/
- fun postAnswer(callback: (message: String) -> Unit) {
- callback(NOT_IMPL_TIP)
+ fun postAnswer(associationId: Int, callback: (message: String) -> Unit) {
+ viewModelScope.launch {
+ _data.value?.mapNotNull { it ->
+ if (it is ChoiceQuestionVo) {
+ toExamVo(choiceQuestionVo = it)?.let { choice ->
+ ApplyAnswerVo(
+ examVo = choice,
+ answer = it.chooseOption
+ ?: throw IllegalArgumentException("题目[id=${choice.questionId}]没有填写答案???")
+ )
+ }.apply {
+ Logger.i("$this")
+ }
+ } else {
+ null
+ }
+ }?.let {
+ Logger.i("提交${it.size}道题目答案")
+ HttpClient.post(url = Api.buildUrl(AssociationApi.ApplyAnswer),
+ callback = HttpCallback(action = "提交答案",
+ onSuccess = {
+ callback(it.message)
+ }, typeToken = object : TypeToken>() {}.type
+ ),
+ jsonParam = AddAnswerVo(
+ answers = it, token = TokenManager.getToken(),
+ associationId = associationId
+ )
+ )
+ }
+
+ }
}
/**
- * 加载题目
+ * 加载题库
*
*/
- fun load() {
+ fun load(associationId: Int, activityType: ExamActivityType) {
+ viewModelScope.launch {
+ HttpClient.post(
+ url = Api.buildUrl(
+ when (activityType) {
+ ExamActivityType.SET_EXAM -> AssociationApi.LoadExam
+ ExamActivityType.JOIN_Association -> AssociationApi.CreatePaper
+ else -> throw IllegalArgumentException("非法类型:${activityType}")
+ }
+ ),
+ callback = HttpCallback>(action = "加载题库", onSuccess = { it ->
+ it.body?.let { it1 ->
+ _data.postValue(it1.map {
+ createExam(examVo = it)
+ }.toMutableList().apply {
+ if (activityType == ExamActivityType.SET_EXAM) {
+ add(createExam())
+ }
+ })
+ }
+ }, typeToken = object : TypeToken>>() {}.type),
+ jsonParam =
+ SearchExamVo(associationId = associationId, token = TokenManager.getToken())
+ )
+ }
+ }
+ /**
+ * 加载答卷
+ *
+ * @param joinId
+ * @param callback
+ */
+ fun showAnswer(joinId: Int, callback: (message: String) -> Unit) {
+ viewModelScope.launch {
+ HttpClient.post(
+ url = Api.buildUrl(AssociationApi.ShowAnswers),
+ callback = HttpCallback>(action = "查看答案", onSuccess = { it ->
+ it.body?.apply {
+ val exam = map {
+ createExam(examVo = it.examVo, answer = it.answer)
+ }
+ _data.postValue(exam.toMutableList())
+ }
+ callback(it.message)
+ }, typeToken = object : TypeToken>>() {}.type),
+ jsonParam = ShowAnswerVo(joinId = joinId, token = TokenManager.getToken())
+ )
+ }
}
+ /**
+ * 添加题目
+ *
+ */
fun addQuestion() {
_data.value?.apply {
_newExam.value?.let {
@@ -201,20 +350,24 @@ class ExamViewModel(application: Application) : ScrollViewModel(applicatio
list.add(it)
_data.postValue(list)
}
- _newExam.value = createExam(ExamType.CQ)
+ _newExam.value = createExam()
}
}
/**
- * TODO 删除题目
- *
+ *删除题目
*/
fun deleteQuestion(exam: Exam) {
_data.value?.apply {
val list = mutableListOf()
remove(exam)
list.addAll(this)
+ Logger.i("size=${list.size}")
+ _data.value?.clear()
_data.postValue(list)
+ exam.questionId?.let {
+ _deleteIds.add(it)
+ }
}
}
}
\ 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 d875346..07836e4 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,6 +3,7 @@ package com.gyf.csams.association.ui
import android.content.Intent
import android.os.Bundle
import androidx.activity.ComponentActivity
+import androidx.activity.compose.ManagedActivityResultLauncher
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.compose.setContent
import androidx.activity.result.contract.ActivityResultContracts
@@ -62,21 +63,27 @@ class AssociationActivity : ComponentActivity() {
val currentMenuName: AssociationMenu by model.currentMenu.observeAsState(
AssociationMenu.startMenu
)
- 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
+ model.update(message = m)
}
}
+ val examResult =
+ rememberLauncherForActivityResult(contract = ActivityResultContracts.StartActivityForResult()) {
+ if (it.resultCode == RESULT_OK) {
+ val m = it.data?.getStringExtra(ExamActivity::class.java.name)
+ Logger.i("试卷提交结果:${m}")
+ model.update(message = m)
+ }
+ }
+
Column {
TextTopAppBar(nav = nav,
currentMenuName = currentMenuName.menuName,
@@ -90,7 +97,6 @@ class AssociationActivity : ComponentActivity() {
onDismissRequest = { },
properties = PopupProperties()
) {
-
when {
TokenManager.getUserInfo()?.associationVo?.associationId == associationId && TokenManager.getUserInfo()?.isHead == true -> {
DropdownMenuItem(onClick = {
@@ -118,13 +124,20 @@ class AssociationActivity : ComponentActivity() {
}
}
DropdownMenuItem(onClick = {
- intent.apply {
- putExtra(
- ExamActivityType::name.name,
- ExamActivityType.SET_EXAM
- )
- }
- startActivity(intent)
+ startActivity(
+ Intent(
+ this@AssociationActivity,
+ ExamActivity::class.java
+ ).apply {
+ putExtra(
+ AssociationActivity::class.java.name,
+ associationId
+ )
+ putExtra(
+ ExamActivityType::name.name,
+ ExamActivityType.SET_EXAM
+ )
+ })
model.close()
}) {
Row(verticalAlignment = Alignment.CenterVertically) {
@@ -135,6 +148,27 @@ class AssociationActivity : ComponentActivity() {
)
}
}
+ DropdownMenuItem(onClick = {
+ startActivity(
+ Intent(
+ this@AssociationActivity,
+ AuditJoinActivity::class.java
+ ).apply {
+ putExtra(
+ AssociationActivity::class.java.name,
+ associationId
+ )
+ })
+ model.close()
+ }) {
+ Row(verticalAlignment = Alignment.CenterVertically) {
+ Text(text = ("入团审核"))
+ Icon(
+ painter = painterResource(id = R.drawable.ic_exchange_rate),
+ contentDescription = null
+ )
+ }
+ }
DropdownMenuItem(onClick = {
rename.launch(Intent(
this@AssociationActivity,
@@ -159,13 +193,9 @@ class AssociationActivity : ComponentActivity() {
}
TokenManager.getUserInfo()?.associationVo == null -> DropdownMenuItem(
onClick = {
- intent.apply {
- putExtra(
- ExamActivityType::name.name,
- ExamActivityType.JOIN_Association
- )
+ model.applyAssociation(associationId = associationId) {
+ model.update(applyAssociationResultVo = it)
}
- startActivity(intent)
model.close()
}) {
Row(verticalAlignment = Alignment.CenterVertically) {
@@ -177,7 +207,6 @@ class AssociationActivity : ComponentActivity() {
}
}
}
-
DropdownMenuItem(onClick = {
model.close()
}) {
@@ -202,32 +231,19 @@ class AssociationActivity : ComponentActivity() {
composable(AssociationMenu.Member.name) {
model.clickMenu(AssociationMenu.Member)
Member()
+ ShowTip(model = model, examResult = examResult)
ShowSnackbar(scaffoldState = scaffoldState)
}
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)
- }
- }
+ ShowTip(model = model, examResult = examResult)
ShowSnackbar(scaffoldState = scaffoldState)
}
composable(AssociationMenu.ActivityList.name) {
model.clickMenu(AssociationMenu.ActivityList)
AssociationList()
+ ShowTip(model = model, examResult = examResult)
ShowSnackbar(scaffoldState = scaffoldState)
}
}
@@ -238,16 +254,71 @@ class AssociationActivity : ComponentActivity() {
}
}
- //TODO下拉菜单操作反馈
+ /**
+ * 显示提示
+ *
+ * @param model
+ * @param examResult
+ */
@Composable
private fun ShowTip(
model: AssociationViewModel = viewModel(),
- scaffoldModel: ScaffoldModel = viewModel()
+ examResult: ManagedActivityResultLauncher
) {
- val m by model.dropDownMenuResult.observeAsState()
- m?.let {
- Logger.i("收到${it}")
- scaffoldModel.update(message = it, actionLabel = "关闭提示")
+ val scaffoldModel: ScaffoldModel = viewModel()
+ val message by model.dropMenuMessage.observeAsState()
+ message?.let {
+ scaffoldModel.update(message = message, actionLabel = "刷新")
+
+ val s by scaffoldModel.data.observeAsState()
+ if (s == null) {
+ model.update(message = null)
+ }
+ LaunchedEffect(message) {
+ delay(it.length * 300L)
+ model.update(message = null)
+ }
+ }
+ val applyAssociationResultVo by model.applyAssociationResultVo.observeAsState()
+ applyAssociationResultVo?.let {
+ when {
+ it.result == true && it.hasPaper == true ->
+ scaffoldModel.update(
+ message = "申请此社团需要完成一份笔试题,点击确认获取试卷",
+ actionLabel = "确认"
+ ) {
+ examResult.launch(
+ Intent(
+ this@AssociationActivity,
+ ExamActivity::class.java
+ ).apply {
+ putExtra(AssociationActivity::class.java.name, associationId)
+ putExtra(
+ ExamActivityType::name.name,
+ ExamActivityType.JOIN_Association
+ )
+ })
+
+ }
+ it.result == true ->
+ scaffoldModel.update(
+ message = "入团申请发送成功,请耐心等待审核结果",
+ actionLabel = "收到"
+ )
+
+ it.associationVo != null ->
+ scaffoldModel.update(
+ message = "您已申请进入${it.associationVo?.name},请耐心等待审核结果",
+ actionLabel = "收到"
+ )
+
+ else ->
+ scaffoldModel.update(
+ message = "入团申请发送失败!",
+ actionLabel = "确认"
+ )
+ }
+ model.update(applyAssociationResultVo = null)
}
}
@@ -491,16 +562,15 @@ class AssociationActivity : ComponentActivity() {
alpha = 07F
)
}) {
- val onGoWeight = 0.3F
- OngoingActivity(
- modifier = Modifier
- .weight(onGoWeight)
- .fillMaxWidth()
- )
+// val onGoWeight = 0.3F
+// OngoingActivity(
+// modifier = Modifier
+// .weight(onGoWeight)
+// .fillMaxWidth()
+// )
HistoryActivityList(
modifier = Modifier
.fillMaxWidth()
- .weight(1 - onGoWeight)
.border(width = 1.dp, color = MaterialTheme.colors.onBackground)
)
}
@@ -540,23 +610,30 @@ class AssociationActivity : ComponentActivity() {
val listState = rememberLazyListState()
val list by model.data.observeAsState()
- LazyColumn(state = listState, modifier = modifier) {
- list?.chunked(2)?.forEach {
- item {
- Row(modifier = Modifier.fillMaxWidth()) {
- HistoryActivity(modifier = Modifier.weight(0.4F), it[0])
- Spacer(modifier = Modifier.weight(0.2F))
- if (it.size == 2) HistoryActivity(modifier = Modifier.weight(0.4F), it[1])
- else Box(modifier = Modifier.weight(0.4F))
+ if (list?.size == 0) {
+ Row(modifier = Modifier.fillMaxWidth()) {
+ Text(text = "目前社团没有任何活动")
+ }
+ } else {
+ LazyColumn(state = listState, modifier = modifier) {
+ list?.chunked(2)?.forEach {
+ item {
+ Row(modifier = Modifier.fillMaxWidth()) {
+ HistoryActivity(modifier = Modifier.weight(0.4F), it[0])
+ Spacer(modifier = Modifier.weight(0.2F))
+ if (it.size == 2) HistoryActivity(
+ modifier = Modifier.weight(0.4F),
+ it[1]
+ )
+ else Box(modifier = Modifier.weight(0.4F))
+ }
+ Spacer(modifier = Modifier.height(10.dp))
+ Divider(color = MaterialTheme.colors.background)
}
- Spacer(modifier = Modifier.height(10.dp))
- Divider(color = MaterialTheme.colors.background)
}
}
}
- if (listState.layoutInfo.totalItemsCount - listState.firstVisibleItemIndex == model.initSize / 2 - 1) {
- TODO("加载更多")
- }
+
}
/**
diff --git a/foreground/src/main/java/com/gyf/csams/association/ui/AuditJoinActivity.kt b/foreground/src/main/java/com/gyf/csams/association/ui/AuditJoinActivity.kt
new file mode 100644
index 0000000..6adc829
--- /dev/null
+++ b/foreground/src/main/java/com/gyf/csams/association/ui/AuditJoinActivity.kt
@@ -0,0 +1,133 @@
+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.foundation.lazy.LazyColumn
+import androidx.compose.material.Card
+import androidx.compose.material.OutlinedButton
+import androidx.compose.material.Text
+import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.livedata.observeAsState
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.unit.dp
+import androidx.lifecycle.viewmodel.compose.viewModel
+import com.gyf.csams.R
+import com.gyf.csams.association.model.AuditJoinViewModel
+import com.gyf.csams.association.model.ExamActivityType
+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.DateTimeUtil.datetimeFormat
+import java.util.*
+
+/**
+ * 审核入团申请
+ *
+ */
+class AuditJoinActivity : 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 = { }) {
+ val model: AuditJoinViewModel = viewModel()
+ val data by model.data.observeAsState()
+ val scaffoldModel: ScaffoldModel = viewModel()
+ LaunchedEffect(associationId) {
+ model.load(associationId = associationId)
+ }
+ LazyColumn(
+ verticalArrangement = Arrangement.spacedBy(
+ 10.dp,
+ Alignment.CenterVertically
+ )
+ ) {
+ data?.forEach {
+ item {
+ Card(elevation = 5.dp) {
+ Column(
+ modifier = Modifier.fillMaxWidth(),
+ horizontalAlignment = Alignment.CenterHorizontally
+ ) {
+ Text(text = "申请人:${it.user.name}")
+ Text(text = "申请时间:${Date(it.applyTime).datetimeFormat()}")
+ if (it.hasPaper) {
+ Spacer(modifier = Modifier.height(5.dp))
+ OutlinedButton(onClick = {
+ startActivity(
+ Intent(
+ this@AuditJoinActivity,
+ ExamActivity::class.java
+ ).apply {
+ putExtra(
+ ExamActivityType::name.name,
+ ExamActivityType.Answer
+ )
+ putExtra(
+ AuditJoinActivity::class.java.name,
+ it.id
+ )
+ putExtra(
+ AssociationActivity::class.java.name,
+ it.associationVo.associationId
+ )
+ })
+ }) {
+ Text(text = "查看申请答卷")
+ }
+ Spacer(modifier = Modifier.height(5.dp))
+ }
+ when (val result = it.result) {
+ null -> BottomButton(confirmDesc = R.string.allow_btn,
+ backDesc = R.string.refuse_btn,
+ modifier = Modifier.fillMaxWidth(),
+ onBack = {
+ model.audit(joinId = it.id, result = false) {
+ scaffoldModel.update(
+ message = it,
+ actionLabel = "关闭提示"
+ )
+ model.load(associationId = associationId)
+ }
+ },
+ onConfirm = {
+ model.audit(joinId = it.id, result = true) {
+ scaffoldModel.update(
+ message = it,
+ actionLabel = "关闭提示"
+ )
+ model.load(associationId = associationId)
+ }
+ })
+ true, false -> {
+ Text("审核结果:${if (result) "通过" else "不通过"}")
+ Text("审核时间:${it.auditTime?.let { Date(it).datetimeFormat() }}")
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
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 a0572ce..60cc303 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
@@ -1,5 +1,6 @@
package com.gyf.csams.association.ui
+import android.content.Intent
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
@@ -9,6 +10,7 @@ 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.livedata.observeAsState
import androidx.compose.ui.Alignment
@@ -19,6 +21,7 @@ import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewmodel.compose.viewModel
import com.gyf.csams.R
import com.gyf.csams.association.model.*
+import com.gyf.csams.module.QUESTION_MIN_SIZE
import com.gyf.csams.uikit.Background
import com.gyf.csams.uikit.BackgroundImage
import com.gyf.lib.uikit.BaseTextField
@@ -26,6 +29,7 @@ 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.orhanobut.logger.Logger
/**
@@ -34,13 +38,32 @@ import com.gyf.lib.util.BottomButton
*/
class ExamActivity : ComponentActivity() {
- lateinit var activityType: ExamActivityType
+ private val activityType: ExamActivityType
+ get() {
+ return intent?.getSerializableExtra(ExamActivityType::name.name) as ExamActivityType
+ }
+
+ private val associationId: Int
+ get() {
+ val id = intent.getIntExtra(
+ AssociationActivity::class.java.name,
+ 0
+ )
+ return if (id == 0) throw IllegalArgumentException("不存在社团id,获取失败") else id
+ }
+
+ private val joinId: Int
+ get() {
+ val id = intent.getIntExtra(
+ AuditJoinActivity::class.java.name,
+ 0
+ )
+ return if (id == 0) throw IllegalArgumentException("不存在申请记录id,获取失败") else id
+ }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
- activityType = intent?.getSerializableExtra(ExamActivityType::name.name) as ExamActivityType
-
setContent {
Body {
MainColumnFrame(background = {
@@ -49,14 +72,35 @@ class ExamActivity : ComponentActivity() {
alpha = 0.6F
)
}) {
- Spacer(modifier = Modifier.weight(0.1F))
- Title(modifier = Modifier.weight(0.1F))
+ Title()
+ Spacer(modifier = Modifier.height(10.dp))
Exam(modifier = Modifier.weight(0.8F))
}
}
}
}
+ @Composable
+ private fun ErrorRadioButton(onClick: () -> Unit = {}) {
+ RadioButton(
+ selected = true,
+ colors =
+ RadioButtonDefaults.colors(disabledColor = MaterialTheme.colors.error),
+ onClick = onClick,
+ enabled = false
+ )
+ }
+
+ @Composable
+ private fun RightRadioButton(selected: Boolean, onClick: () -> Unit = {}) {
+ RadioButton(
+ selected = selected,
+ colors =
+ RadioButtonDefaults.colors(disabledColor = MaterialTheme.colors.primary),
+ onClick = onClick,
+ enabled = false
+ )
+ }
/**
* 标题
@@ -64,12 +108,44 @@ class ExamActivity : ComponentActivity() {
* @param modifier
*/
@Composable
- private fun Title(modifier: Modifier = Modifier) {
- Row(horizontalArrangement = Arrangement.Center, modifier = modifier.fillMaxWidth()) {
- Text(text = activityType.menuName, style = MaterialTheme.typography.h4)
+ private fun Title(modifier: Modifier = Modifier, model: ExamViewModel = viewModel()) {
+ val data by model.data.observeAsState()
+ Column(modifier = modifier, horizontalAlignment = Alignment.CenterHorizontally) {
+ Text(text = activityType.menuName, style = MaterialTheme.typography.h5)
+ data?.size?.let {
+ Text(buildString {
+ append("共有${if (activityType == ExamActivityType.SET_EXAM) it - 1 else it}道题目")
+ if (it < QUESTION_MIN_SIZE) {
+ append(",还差${QUESTION_MIN_SIZE - it}道题目才可以生成入团笔试题")
+ }
+ }, style = MaterialTheme.typography.h6.copy(color = MaterialTheme.colors.primary))
+ }
+ when (activityType) {
+ ExamActivityType.Answer -> Row(
+ modifier = Modifier.fillMaxWidth(),
+ horizontalArrangement = Arrangement.SpaceEvenly
+ ) {
+ Row {
+ RightRadioButton(selected = true)
+ Text(text = "表示正确选项")
+ }
+ Row {
+ ErrorRadioButton()
+ Text(text = "表示错误选项")
+ }
+ }
+ ExamActivityType.SET_EXAM -> Row(modifier = Modifier.fillMaxWidth()) {
+ Text(text = "通过单选按钮设置正确答案")
+ }
+ ExamActivityType.JOIN_Association -> Row(modifier = Modifier.fillMaxWidth()) {
+ Text(text = "通过单选按钮选择正确答案")
+ }
+ }
+
}
}
+
@Composable
private fun ExamChild(it: Exam, examHeight: Dp, isAdd: Boolean = false) {
val questionWeight = 0.3F
@@ -77,7 +153,7 @@ class ExamActivity : ComponentActivity() {
is OpenQuestionsVo -> ExamOQ(
openQuestionsVo = it,
modifier = Modifier.height(examHeight * questionWeight),
- isAdd = isAdd
+ isAdd = isAdd,
)
is ChoiceQuestionVo -> ExamCQ(
choiceQuestionVo = it,
@@ -101,64 +177,88 @@ class ExamActivity : ComponentActivity() {
scaffoldModel: ScaffoldModel = viewModel(),
examHeight: Dp = 350.dp
) {
+ LaunchedEffect(associationId) {
+ when (activityType) {
+ ExamActivityType.JOIN_Association, ExamActivityType.SET_EXAM -> model.load(
+ associationId = associationId,
+ activityType = activityType
+ )
+ ExamActivityType.Answer -> model.showAnswer(joinId = joinId) {
+ scaffoldModel.update(message = "答卷加载成功", actionLabel = "关闭提示")
+ }
+ }
+
+ }
val listState = rememberLazyListState()
val data by model.data.observeAsState()
val newExam by model.newExam.observeAsState()
- LazyColumn(state = listState, modifier = modifier) {
- data?.forEach {
- item {
- ExamChild(it = it, examHeight = examHeight)
- Spacer(modifier = Modifier.height(20.dp))
+ Column(modifier = modifier) {
+ LazyColumn(state = listState, modifier = Modifier.weight(0.8F)) {
+ data?.forEach {
+ item {
+ ExamChild(it = it, examHeight = examHeight)
+ Spacer(modifier = Modifier.height(20.dp))
+ }
}
- }
- newExam?.let {
- item {
- Column {
+ newExam?.let {
+ item {
+ Column {
// OutlinedButton(onClick = { model.switchType(it) }) {
// Text(text = "切换到${if (newExam is ChoiceQuestionVo) "开放题" else "选择题"}")
// }
- ExamChild(it = it, examHeight = examHeight, isAdd = true)
+ ExamChild(it = it, examHeight = examHeight, isAdd = true)
+ }
}
}
+
}
- item {
- Column {
- Divider(color = MaterialTheme.colors.background)
- Spacer(modifier = Modifier.height(30.dp))
-
- when (activityType) {
- ExamActivityType.SET_EXAM -> {
- BottomButton(
- modifier = Modifier.fillMaxWidth(),
- confirmDesc = R.string.update_exam
- ) {
- model.updateExam { scaffoldModel.update(message = it) }
- }
+ Divider(color = MaterialTheme.colors.background)
+ Spacer(modifier = Modifier.height(30.dp))
+ when (activityType) {
+ ExamActivityType.SET_EXAM -> {
+ BottomButton(
+ modifier = Modifier.fillMaxWidth(),
+ confirmDesc = R.string.update_exam,
+ enabled = data?.size ?: 0 > 0
+ ) {
+ model.updateExam(associationId = associationId) {
+ scaffoldModel.update(
+ message = it, actionLabel = "关闭提示"
+ )
}
- ExamActivityType.JOIN_Association -> {
- BottomButton(
- modifier = Modifier.fillMaxWidth(),
- confirmDesc = R.string.post_answer
- ) {
- model.postAnswer { scaffoldModel.update(message = it) }
- }
+ }
+ }
+ ExamActivityType.JOIN_Association -> {
+ val allowPostAnswer by model.allowPostAnswer.observeAsState(false)
+ BottomButton(
+ modifier = Modifier.fillMaxWidth(),
+ confirmDesc = R.string.post_answer,
+ backDesc = R.string.cancel_apply,
+ enabled = allowPostAnswer
+ ) {
+ model.postAnswer(associationId = associationId) {
+ scaffoldModel.update(message = it)
+ setResult(RESULT_OK, Intent().apply {
+ putExtra(ExamActivity::class.java.name, it)
+ })
+ finish()
+ }
+ }
+ }
+ ExamActivityType.Answer -> {
+ Row(
+ modifier = Modifier.fillMaxWidth(),
+ horizontalArrangement = Arrangement.Center
+ ) {
+ OutlinedButton(onClick = { onBackPressed() }) {
+ Text(text = "返回")
}
-
-
}
-
}
}
-
-
}
-// if (listState.layoutInfo.totalItemsCount - listState.firstVisibleItemIndex == model.initSize / 2 - 1) {
-// model.loadMore { scaffoldModel.update(message = it) }
-// }
-
-
}
/**
@@ -172,12 +272,14 @@ class ExamActivity : ComponentActivity() {
modifier: Modifier = Modifier,
exam: Exam
) {
- exam._question?.let {
+ exam._question.let {
BaseTextField(
form = it,
modifier = modifier
.fillMaxSize()
- .background(color = MaterialTheme.colors.background)
+ .background(color = MaterialTheme.colors.background),
+ readOnly = activityType != ExamActivityType.SET_EXAM,
+ showTrailingIcon = activityType == ExamActivityType.SET_EXAM
)
}
@@ -194,44 +296,36 @@ class ExamActivity : ComponentActivity() {
scaffoldModel: ScaffoldModel = viewModel(),
exam: Exam
) {
- val list by model.data.observeAsState()
- 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)
+ Box(
+ contentAlignment = Alignment.Center,
+ modifier = modifier
+ ) {
+ IconButton(onClick = {
+ if (isAdd) {
+ if (exam.check()) {
+ scaffoldModel.update(
+ message = model.addTip,
+ actionLabel = model.actionLabel
+ ) {
+ model.addQuestion()
}
-
} else {
- if (list?.size == 1) {
- scaffoldModel.update(model.deleteLeastOne)
- } else {
- scaffoldModel.update(
- message = model.deleteTip,
- actionLabel = model.actionLabel
- ) {
- model.deleteQuestion(exam = exam)
- }
- }
+ scaffoldModel.update(message = model.questionIsNull, actionLabel = "知道了")
+ }
+
+ } 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
+ )
}
}
@@ -247,9 +341,15 @@ class ExamActivity : ComponentActivity() {
private fun ExamOQ(
modifier: Modifier = Modifier,
openQuestionsVo: OpenQuestionsVo,
- isAdd: Boolean = false
+ isAdd: Boolean = false,
+ model: ExamViewModel = viewModel()
) {
+ val data by model.data.observeAsState()
Row(modifier = modifier) {
+ Logger.i("index=${data?.indexOf(openQuestionsVo)}")
+ data?.indexOf(openQuestionsVo)?.let {
+ Text(text = "${it}.", modifier = Modifier.weight(0.05F))
+ }
Question(
exam = openQuestionsVo, modifier =
if (activityType == ExamActivityType.SET_EXAM)
@@ -262,7 +362,7 @@ class ExamActivity : ComponentActivity() {
if (activityType == ExamActivityType.SET_EXAM) {
ActionButton(
modifier = Modifier
- .weight(0.2F)
+ .weight(0.15F)
.fillMaxHeight(),
isAdd = isAdd,
exam = openQuestionsVo
@@ -285,6 +385,16 @@ class ExamActivity : ComponentActivity() {
questionWeight: Float
) {
Row(modifier = modifier) {
+ model.data.value?.let {
+
+ Text(
+ text = "${
+ if (it.indexOf(choiceQuestionVo) == -1) it.size else it.indexOf(
+ choiceQuestionVo
+ ) + 1
+ }."
+ )
+ }
Column(
modifier = if (activityType == ExamActivityType.SET_EXAM)
Modifier
@@ -315,16 +425,52 @@ class ExamActivity : ComponentActivity() {
.weight(1F / ANSWER_SIZE)
) {
val answerIndex: Int = indexOf(it)
- val click = {
- model.update(
- oldExam = choiceQuestionVo,
- newExam = choiceQuestionVo.copy(rightAnswer = answerIndex)
- )
+
+
+ when (activityType) {
+ ExamActivityType.SET_EXAM -> {
+ RadioButton(
+ selected = choiceQuestionVo.rightAnswer == answerIndex,
+ onClick = {
+ model.update(
+ oldExam = choiceQuestionVo,
+ newExam = choiceQuestionVo.copy(rightAnswer = answerIndex)
+ )
+ })
+ }
+ ExamActivityType.JOIN_Association -> {
+ RadioButton(
+ selected = choiceQuestionVo.chooseOption == answerIndex,
+ onClick = {
+ model.update(
+ oldExam = choiceQuestionVo,
+ newExam = choiceQuestionVo.copy(chooseOption = answerIndex)
+ )
+ model.checkChooseAnswer()
+ })
+ }
+ ExamActivityType.Answer -> {
+ when {
+ choiceQuestionVo.rightAnswer == answerIndex -> RightRadioButton(
+ selected = true
+ )
+ choiceQuestionVo.chooseOption != choiceQuestionVo.rightAnswer && choiceQuestionVo.chooseOption == answerIndex ->
+ ErrorRadioButton()
+ else -> RadioButton(
+ selected = false,
+ onClick = {},
+ enabled = false
+ )
+ }
+
+ }
}
- val isRightAnswer =
- choiceQuestionVo.rightAnswer == answerIndex
- RadioButton(selected = isRightAnswer, onClick = click)
- BaseTextField(form = it)
+
+ BaseTextField(
+ form = it,
+ enabled = activityType != ExamActivityType.Answer,
+ showTrailingIcon = activityType == ExamActivityType.SET_EXAM
+ )
}
}
@@ -333,15 +479,13 @@ class ExamActivity : ComponentActivity() {
}
}
- if (activityType == ExamActivityType.SET_EXAM) {
- ActionButton(
- modifier = Modifier
- .weight(0.2F)
- .fillMaxHeight(),
- isAdd = isAdd,
- exam = choiceQuestionVo
- )
- }
+ ActionButton(
+ modifier = Modifier
+ .weight(0.2F)
+ .fillMaxHeight(),
+ isAdd = isAdd,
+ exam = choiceQuestionVo
+ )
}
}
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 78754d7..f8d0df6 100644
--- a/foreground/src/main/java/com/gyf/csams/util/GsonUtil.kt
+++ b/foreground/src/main/java/com/gyf/csams/util/GsonUtil.kt
@@ -50,7 +50,7 @@ class ChoiceQuestionVoSerializer : JsonSerializer {
val c = JsonObject()
c.add("examType", gson.toJsonTree(vo?.examType?.name))
// c.add("question", gson.toJsonTree(vo?.question?.formValue?.value))
- c.add("answers", gson.toJsonTree(vo?.answers))
+// c.add("answers", gson.toJsonTree(vo?.answers))
c.add("rightAnswer", gson.toJsonTree(vo?.rightAnswer))
return c
}
diff --git a/foreground/src/main/res/values-en/strings.xml b/foreground/src/main/res/values-en/strings.xml
index 8f46ff8..925e6c5 100644
--- a/foreground/src/main/res/values-en/strings.xml
+++ b/foreground/src/main/res/values-en/strings.xml
@@ -20,4 +20,5 @@
收藏
上传
关闭
+ 放弃申请
\ No newline at end of file
diff --git a/foreground/src/main/res/values-zh/strings.xml b/foreground/src/main/res/values-zh/strings.xml
index 8f46ff8..925e6c5 100644
--- a/foreground/src/main/res/values-zh/strings.xml
+++ b/foreground/src/main/res/values-zh/strings.xml
@@ -20,4 +20,5 @@
收藏
上传
关闭
+ 放弃申请
\ No newline at end of file
diff --git a/foreground/src/main/res/values/strings.xml b/foreground/src/main/res/values/strings.xml
index eea6d84..86dea0d 100644
--- a/foreground/src/main/res/values/strings.xml
+++ b/foreground/src/main/res/values/strings.xml
@@ -20,4 +20,5 @@
收藏
上传
关闭
+ 放弃申请
\ No newline at end of file
diff --git a/foreground/src/test/java/com/gyf/csams/ExampleUnitTest.kt b/foreground/src/test/java/com/gyf/csams/ExampleUnitTest.kt
index d553186..f8eb402 100644
--- a/foreground/src/test/java/com/gyf/csams/ExampleUnitTest.kt
+++ b/foreground/src/test/java/com/gyf/csams/ExampleUnitTest.kt
@@ -14,13 +14,24 @@ import org.junit.Test
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
+abstract class TestA {
+ val i: Int = 3
+}
+
+data class TestB(val b: Int = 3) : TestA() {
+
+ fun test() {
+ println("${i}")
+ }
+}
+
class ExampleUnitTest {
@Test
fun addition_isCorrect() {
assertEquals(4, 2 + 2)
}
- data class Fuck(val name:String)
+ data class Fuck(val name: String)
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 92ca230..4478c9e 100644
--- a/lib/src/main/java/com/gyf/lib/uikit/BaseTextField.kt
+++ b/lib/src/main/java/com/gyf/lib/uikit/BaseTextField.kt
@@ -131,6 +131,7 @@ fun BaseTextField(
isError: Boolean = false,
visualTransformation: VisualTransformation = VisualTransformation.None,
readOnly: Boolean = false,
+ enabled: Boolean = true,
textStyle: TextStyle = LocalTextStyle.current,
leadingIcon: @Composable (() -> Unit)? = null,
trailingIcon: @Composable (() -> Unit)? = null,
@@ -151,7 +152,8 @@ fun BaseTextField(
isError = isError,
visualTransformation = visualTransformation,
readOnly = readOnly,
- textStyle = textStyle
+ textStyle = textStyle,
+ enabled = enabled
)
}
@@ -174,7 +176,9 @@ fun BaseTextField(
keyboardOptions: KeyboardOptions = KeyboardOptions.Default.copy(imeAction = ImeAction.Done),
isError: Boolean = false,
visualTransformation: VisualTransformation = VisualTransformation.None,
- readOnly: Boolean = false
+ readOnly: Boolean = false,
+ showTrailingIcon: Boolean = true,
+ enabled: Boolean = true
) {
val name: String by form.formValue.observeAsState("")
BaseTextField(
@@ -184,8 +188,9 @@ fun BaseTextField(
keyboardOptions,
isError,
visualTransformation,
- trailingIcon = { Text(text = "${name.length}/${form.textLength}") },
- readOnly = readOnly
+ trailingIcon = { if (showTrailingIcon) Text(text = "${name.length}/${form.textLength}") },
+ readOnly = readOnly,
+ enabled = enabled
)
}
diff --git a/lib/src/main/java/com/gyf/lib/uikit/Snackbar.kt b/lib/src/main/java/com/gyf/lib/uikit/Snackbar.kt
index 717a5a3..1b572a7 100644
--- a/lib/src/main/java/com/gyf/lib/uikit/Snackbar.kt
+++ b/lib/src/main/java/com/gyf/lib/uikit/Snackbar.kt
@@ -17,7 +17,7 @@ import kotlinx.coroutines.launch
data class SnackBar(
val message: String?,
- val actionLabel: String? = null,
+ val actionLabel: String,
val duration: SnackbarDuration = SnackbarDuration.Short,
val callback: () -> Unit?
)
@@ -30,7 +30,7 @@ class ScaffoldModel : ViewModel() {
private val _data = MutableLiveData()
val data: LiveData = _data
- fun update(message: String? = null, actionLabel: String? = null, callback: () -> Unit? = {}) {
+ fun update(message: String? = null, actionLabel: String = "关闭提示", callback: () -> Unit? = {}) {
if (message == null) {
_data.postValue(null)
} else {
@@ -55,23 +55,19 @@ fun ShowSnackbar(model: ScaffoldModel = viewModel(), scaffoldState: ScaffoldStat
if (message != null) {
LaunchedEffect(scaffoldState) {
launch {
- if (actionLabel != null) {
- val result = scaffoldState.snackbarHostState.showSnackbar(
- message = message, actionLabel = actionLabel,
- duration = duration
+ val result = scaffoldState.snackbarHostState.showSnackbar(
+ message = message, actionLabel = actionLabel,
+ duration = duration
- )
- when (result) {
- SnackbarResult.ActionPerformed -> {
- Logger.i("点击操作按钮")
- callback()
- }
- SnackbarResult.Dismissed -> {
- Logger.d("窗口消失")
- }
+ )
+ when (result) {
+ SnackbarResult.ActionPerformed -> {
+ Logger.d("点击操作按钮")
+ callback()
+ }
+ SnackbarResult.Dismissed -> {
+ Logger.d("窗口消失")
}
- } else {
- scaffoldState.snackbarHostState.showSnackbar(message = message)
}
model.update()
}
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 9588dc0..612e160 100644
--- a/lib/src/main/java/com/gyf/lib/util/Api.kt
+++ b/lib/src/main/java/com/gyf/lib/util/Api.kt
@@ -131,7 +131,31 @@ enum class AssociationApi(val path: String) : UrlPath {
RenameAudit("${Rename.path}${Audit.path}"),
//换名申请表审核进度
- RenameRead("${Rename.path}${Read.path}");
+ RenameRead("${Rename.path}${Read.path}"),
+
+ //更新题库
+ UpdateExam("/update/exam"),
+
+ //加载题库
+ LoadExam("/load/exam"),
+
+ //申请入团
+ CheckApply("/check/apply"),
+
+ //创建试卷
+ CreatePaper("/create/paper"),
+
+ //提交答卷
+ ApplyAnswer("/apply/paper"),
+
+ //检查入团申请
+ CheckJoin("/check/join"),
+
+ //审核入团申请
+ AuditJoin("/audit/join"),
+
+ //显示答案
+ ShowAnswers("/show/answer");
override fun build(): String {
return "/api/association${this.path}"
diff --git a/lib/src/main/res/values-en/strings.xml b/lib/src/main/res/values-en/strings.xml
index 83ac1ab..9df4988 100644
--- a/lib/src/main/res/values-en/strings.xml
+++ b/lib/src/main/res/values-en/strings.xml
@@ -31,4 +31,6 @@
审核阶段
复审意见
活动日期
+ 通过
+ 拒绝
\ 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 83ac1ab..9df4988 100644
--- a/lib/src/main/res/values-zh/strings.xml
+++ b/lib/src/main/res/values-zh/strings.xml
@@ -31,4 +31,6 @@
审核阶段
复审意见
活动日期
+ 通过
+ 拒绝
\ 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 83ac1ab..9df4988 100644
--- a/lib/src/main/res/values/strings.xml
+++ b/lib/src/main/res/values/strings.xml
@@ -31,4 +31,6 @@
审核阶段
复审意见
活动日期
+ 通过
+ 拒绝
\ No newline at end of file