parent
4145e3fbef
commit
9b12cef29c
@ -0,0 +1 @@ |
||||
336c59a7cdc6f9b18fecb981ae5b14f6b7366d90 |
@ -0,0 +1 @@ |
||||
a30262664371040b970f72f5089d69a476fed40b |
@ -0,0 +1 @@ |
||||
a524dd25e1d96e659662021decd71ed8bfce7a78 |
@ -0,0 +1 @@ |
||||
27a39082c3e76250c3bed8df065a0febcc36c901 |
@ -0,0 +1 @@ |
||||
95c6b9f9e380ae08145d3219b820d65a3a7b268b |
@ -0,0 +1,32 @@ |
||||
package com.gyf.csams.activity.model |
||||
|
||||
import android.app.Application |
||||
import androidx.lifecycle.viewModelScope |
||||
import com.google.gson.reflect.TypeToken |
||||
import com.gyf.csams.module.ActivityVo |
||||
import com.gyf.csams.module.ApiResponse |
||||
import com.gyf.csams.module.FindTendencyVo |
||||
import com.gyf.csams.module.TendencyType |
||||
import com.gyf.lib.model.ScrollViewModel |
||||
import com.gyf.lib.util.* |
||||
import kotlinx.coroutines.launch |
||||
|
||||
class TendencyViewModel(application: Application) : |
||||
ScrollViewModel<ActivityVo>(application = application) { |
||||
|
||||
fun load(type: TendencyType) { |
||||
viewModelScope.launch { |
||||
HttpClient.post( |
||||
url = Api.buildUrl(ActivityApi.FindTendency), |
||||
callback = HttpCallback<MutableList<ActivityVo>>( |
||||
action = "加载${type.desc}活动", |
||||
onSuccess = { |
||||
it.body?.apply { _data.postValue(this) } |
||||
}, |
||||
typeToken = object : TypeToken<ApiResponse<MutableList<ActivityVo>>>() {}.type |
||||
), |
||||
jsonParam = FindTendencyVo(type = type, token = TokenManager.getToken()) |
||||
) |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,58 @@ |
||||
package com.gyf.csams.activity.ui |
||||
|
||||
import android.os.Bundle |
||||
import androidx.activity.ComponentActivity |
||||
import androidx.activity.compose.setContent |
||||
import androidx.compose.foundation.layout.Arrangement |
||||
import androidx.compose.foundation.layout.Row |
||||
import androidx.compose.foundation.layout.fillMaxWidth |
||||
import androidx.compose.material.MaterialTheme |
||||
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.Modifier |
||||
import androidx.lifecycle.viewmodel.compose.viewModel |
||||
import com.gyf.csams.activity.model.TendencyViewModel |
||||
import com.gyf.csams.module.TendencyType |
||||
import com.gyf.csams.uikit.Activities |
||||
import com.gyf.csams.uikit.Background |
||||
import com.gyf.csams.uikit.BackgroundImage |
||||
import com.gyf.lib.uikit.Body |
||||
import com.gyf.lib.uikit.MainColumnFrame |
||||
|
||||
class TendencyActivity : ComponentActivity() { |
||||
|
||||
private val type: TendencyType |
||||
get() { |
||||
return intent.getSerializableExtra(TendencyType::class.java.name) as TendencyType |
||||
} |
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) { |
||||
super.onCreate(savedInstanceState) |
||||
|
||||
setContent { |
||||
Body { |
||||
MainColumnFrame(background = { |
||||
Background( |
||||
image = BackgroundImage.AssociationMain, |
||||
alpha = 07F |
||||
) |
||||
}) { |
||||
val model: TendencyViewModel = viewModel() |
||||
LaunchedEffect(type) { |
||||
model.load(type = type) |
||||
} |
||||
val data by model.data.observeAsState() |
||||
Row( |
||||
modifier = Modifier.fillMaxWidth(), |
||||
horizontalArrangement = Arrangement.Center |
||||
) { |
||||
Text(text = "我的${type.desc}", style = MaterialTheme.typography.h4) |
||||
} |
||||
Activities(list = data, modifier = Modifier.fillMaxWidth()) |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,72 @@ |
||||
package com.gyf.csams.uikit |
||||
|
||||
import android.content.Intent |
||||
import androidx.compose.foundation.Image |
||||
import androidx.compose.foundation.clickable |
||||
import androidx.compose.foundation.layout.* |
||||
import androidx.compose.foundation.lazy.LazyColumn |
||||
import androidx.compose.foundation.lazy.rememberLazyListState |
||||
import androidx.compose.material.Divider |
||||
import androidx.compose.material.MaterialTheme |
||||
import androidx.compose.material.Text |
||||
import androidx.compose.runtime.Composable |
||||
import androidx.compose.ui.Alignment |
||||
import androidx.compose.ui.Modifier |
||||
import androidx.compose.ui.platform.LocalContext |
||||
import androidx.compose.ui.res.painterResource |
||||
import androidx.compose.ui.unit.dp |
||||
import com.gyf.csams.R |
||||
import com.gyf.csams.activity.ui.ActivityDetailActivity |
||||
import com.gyf.csams.module.ActivityVo |
||||
|
||||
|
||||
/** |
||||
* 历史活动 |
||||
* |
||||
* @param modifier |
||||
*/ |
||||
@Composable |
||||
private fun HistoryActivity(modifier: Modifier, activityVo: ActivityVo) { |
||||
val context = LocalContext.current |
||||
Box(modifier = modifier.clickable(onClick = { |
||||
context.startActivity(Intent(context, ActivityDetailActivity::class.java).apply { |
||||
putExtra(ActivityDetailActivity::class.java.name, activityVo.activityId) |
||||
}) |
||||
}), contentAlignment = Alignment.Center) { |
||||
Image( |
||||
painter = painterResource(id = R.drawable.history_activity_border), |
||||
contentDescription = null, |
||||
modifier = Modifier.fillMaxSize() |
||||
) |
||||
Image( |
||||
painter = painterResource(id = R.drawable.ic_launcher_foreground), |
||||
contentDescription = null, |
||||
modifier = Modifier.fillMaxSize() |
||||
) |
||||
Text(text = activityVo.activityName) |
||||
|
||||
} |
||||
} |
||||
|
||||
|
||||
@Composable |
||||
fun Activities(modifier: Modifier = Modifier, list: List<ActivityVo>?) { |
||||
val listState = rememberLazyListState() |
||||
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) |
||||
} |
||||
} |
||||
} |
||||
} |
@ -1,125 +0,0 @@ |
||||
package com.gyf.csams.util |
||||
|
||||
import com.google.gson.* |
||||
import com.google.gson.reflect.TypeToken |
||||
import com.gyf.csams.association.model.* |
||||
|
||||
import com.gyf.lib.uikit.StringForm |
||||
import java.lang.reflect.Type |
||||
|
||||
class OpenQuestionsVoSerializer : JsonSerializer<OpenQuestionsVo> { |
||||
override fun serialize( |
||||
vo: OpenQuestionsVo?, |
||||
p1: Type?, |
||||
p2: JsonSerializationContext? |
||||
): JsonElement { |
||||
val gson = Gson() |
||||
val c = JsonObject() |
||||
c.add("examType", gson.toJsonTree(vo?.examType?.name)) |
||||
// c.add("question", gson.toJsonTree(vo?.question?.formValue?.value)) |
||||
return c |
||||
} |
||||
} |
||||
|
||||
class OpenQuestionsVoDeserializer : JsonDeserializer<OpenQuestionsVo> { |
||||
override fun deserialize( |
||||
json: JsonElement?, |
||||
p1: Type?, |
||||
p2: JsonDeserializationContext? |
||||
): OpenQuestionsVo { |
||||
val root = json?.asJsonObject |
||||
val value = root?.get("question")?.asString |
||||
val question = StringForm(formDesc = "问题", textLength = QUESTION_TEXT_LENGTH) |
||||
if (value != null) { |
||||
question.onChange(value) |
||||
TODO() |
||||
// return OpenQuestionsVo(question = question) |
||||
} else { |
||||
throw NullPointerException("问题无法解析!!!!") |
||||
} |
||||
} |
||||
} |
||||
|
||||
class ChoiceQuestionVoSerializer : JsonSerializer<ChoiceQuestionVo> { |
||||
override fun serialize( |
||||
vo: ChoiceQuestionVo?, |
||||
p1: Type?, |
||||
p2: JsonSerializationContext? |
||||
): JsonElement { |
||||
val gson = Gson() |
||||
val c = JsonObject() |
||||
c.add("examType", gson.toJsonTree(vo?.examType?.name)) |
||||
// c.add("question", gson.toJsonTree(vo?.question?.formValue?.value)) |
||||
// c.add("answers", gson.toJsonTree(vo?.answers)) |
||||
c.add("rightAnswer", gson.toJsonTree(vo?.rightAnswer)) |
||||
return c |
||||
} |
||||
} |
||||
|
||||
class ChoiceQuestionVoDeserializer : JsonDeserializer<ChoiceQuestionVo> { |
||||
override fun deserialize( |
||||
json: JsonElement?, |
||||
p1: Type?, |
||||
p2: JsonDeserializationContext? |
||||
): ChoiceQuestionVo { |
||||
val root = json?.asJsonObject |
||||
val value = root?.get("question")?.asString |
||||
val question = StringForm(formDesc = "问题", textLength = QUESTION_TEXT_LENGTH) |
||||
if (value != null) { |
||||
question.onChange(value) |
||||
val gson = Gson() |
||||
val answers: List<String> = |
||||
gson.fromJson(root.get("answers"), object : TypeToken<List<String>>() {}.type) |
||||
if (answers.size != ANSWER_SIZE) { |
||||
throw IllegalArgumentException("选项数量!=$QUESTION_TEXT_LENGTH") |
||||
} |
||||
val rightAnswer = root.get("rightAnswer").asInt |
||||
TODO() |
||||
// return ChoiceQuestionVo( |
||||
// question = question, |
||||
// answers = answers.map { |
||||
// StringForm( |
||||
// formDesc = "选项", |
||||
// textLength = ANSWER_TEXT_LENGTH, |
||||
// value = it |
||||
// ) |
||||
// }, |
||||
// rightAnswer = rightAnswer |
||||
// ) |
||||
} else { |
||||
throw NullPointerException("问题无法解析!!!!") |
||||
} |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 题目反序列化 |
||||
* |
||||
*/ |
||||
class ExamDeserializer : JsonDeserializer<Exam> { |
||||
companion object { |
||||
val gson: Gson = GsonBuilder() |
||||
.registerTypeAdapter(OpenQuestionsVo::class.java, OpenQuestionsVoDeserializer()) |
||||
.registerTypeAdapter(ChoiceQuestionVo::class.java, ChoiceQuestionVoDeserializer()) |
||||
.create() |
||||
} |
||||
|
||||
override fun deserialize(json: JsonElement?, p1: Type?, p2: JsonDeserializationContext?): Exam { |
||||
val root = json?.asJsonObject |
||||
|
||||
val type = root?.get("examType")?.asString |
||||
|
||||
return when (gson.fromJson(type, ExamType::class.java)) { |
||||
ExamType.CQ -> gson.fromJson( |
||||
json, |
||||
object : TypeToken<ChoiceQuestionVo>() {}.type |
||||
) |
||||
ExamType.OQ -> gson.fromJson( |
||||
json, |
||||
object : TypeToken<OpenQuestionsVo>() {}.type |
||||
) |
||||
null -> throw NullPointerException("无法识别题目类型!") |
||||
} |
||||
|
||||
} |
||||
} |
@ -1,28 +0,0 @@ |
||||
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.lib.util.HttpCallback |
||||
import java.lang.reflect.Type |
||||
|
||||
/** |
||||
* http请求回调 |
||||
* |
||||
* @param T |
||||
* @property action |
||||
* @property onSuccess |
||||
* @property onFail |
||||
|
||||
*/ |
||||
class ExamCallback<T>( |
||||
private val action: String, |
||||
private val onSuccess: (res: ApiResponse<T>) -> Unit, |
||||
private val onFail: (error: String) -> Unit, |
||||
private val type: Type |
||||
) : HttpCallback<T>(action, onSuccess, onFail, type) { |
||||
override val gson: Gson = GsonBuilder() |
||||
.registerTypeAdapter(Exam::class.java, ExamDeserializer()) |
||||
.create() |
||||
} |
@ -0,0 +1 @@ |
||||
eae2136da161924597d752b7575d0f33e2638267 |
@ -0,0 +1 @@ |
||||
be99b75ae53194a79345f0278d9c17ce543ade81 |
@ -0,0 +1 @@ |
||||
165cccf559b817f7b0d4c102ba53ff6beb5369c6 |
@ -0,0 +1 @@ |
||||
7373621983602f41e9c55827a7e62c78ff6899b8 |
@ -0,0 +1 @@ |
||||
0a6f90b1de328db428af6dbea2322a79a104c562 |
@ -0,0 +1 @@ |
||||
1eae31cbbcf67f843d39243caf7df8c569c13b77 |
@ -0,0 +1 @@ |
||||
4d806e13be16ad9726fa260878473f041f153a58 |
@ -0,0 +1 @@ |
||||
0149273fe46069663a6c9ff375bab6e81aaae9d8 |
@ -0,0 +1 @@ |
||||
4e6cdc0a5379ae11e7ecd9862df219a2e8e30966 |
@ -0,0 +1 @@ |
||||
7758a1ac02f112f2cc4b9a770e6e503b51123cb7 |
@ -0,0 +1 @@ |
||||
24b3200ded1804dbeede2ad13209502ecb694a94 |
@ -0,0 +1 @@ |
||||
17a3a14f87bc6dfaa5222edd157e546f8c3d3b71 |
@ -0,0 +1 @@ |
||||
40c3c72f459198c56917d4cf2dd095c14e98727f |
@ -0,0 +1 @@ |
||||
1ee13a1678f539bc50c1a6cf8c2a4cd3ad66d643 |
@ -0,0 +1 @@ |
||||
6a42e4773be7fccb574c6021c78f8ff16c38268b |
@ -0,0 +1 @@ |
||||
0e6b6965957df34b335709e70db54ec18f85eb83 |
@ -0,0 +1 @@ |
||||
a530f977cd4e84c53f98dc954e03290cf35cc443 |
@ -0,0 +1 @@ |
||||
bba77fabcbaea7c81c93497dc15a5bd35f373f5e |
@ -0,0 +1 @@ |
||||
35980a5473e21920506edcbe0a31e75d9263e978 |
@ -0,0 +1 @@ |
||||
d9686761bcd5d3992c8a1135838400ac61bb7e47 |
@ -0,0 +1 @@ |
||||
110603101ef93e9ceca51de555a93b5e3d2de994 |
Loading…
Reference in new issue