You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

589 lines
23 KiB

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
import androidx.compose.foundation.Image
import androidx.compose.foundation.border
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.*
import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.PopupProperties
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import com.gyf.csams.R
import com.gyf.csams.activity.ui.ApplyActActivity
import com.gyf.csams.association.model.*
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
/**
* 社团界面
*
*/
class AssociationActivity : 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 {
NavBody { nav, scaffoldState ->
val model: AssociationViewModel = viewModel()
val currentMenuName: AssociationMenu by model.currentMenu.observeAsState(
AssociationMenu.startMenu
)
val expanded by model.expanded.observeAsState(false)
//TODO重命名操作反馈
val rename =
rememberLauncherForActivityResult(contract = ActivityResultContracts.StartActivityForResult()) {
if (it.resultCode == RESULT_OK) {
val m = it.data?.getStringExtra(RenameActivity::class.java.name)
Logger.i("社团重命名返回:${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,
menuNames = AssociationMenu.values(),
iconMenu = { model.switchType() }) {
Row {
DropdownMenu(
expanded = expanded,
onDismissRequest = { },
properties = PopupProperties()
) {
when {
TokenManager.getUserInfo()?.associationVo?.associationId == associationId && TokenManager.getUserInfo()?.isHead == true -> {
DropdownMenuItem(onClick = {
startActivity(
Intent(
this@AssociationActivity,
ApplyActActivity::class.java
).apply {
putExtra(
AssociationActivity::class.java.name,
associationId
)
}
)
model.close()
}) {
Row(verticalAlignment = Alignment.CenterVertically) {
Text(text = getString(R.string.apply_act_menu))
Icon(
painter = painterResource(id = R.drawable.ic_add_fill),
contentDescription = null
)
}
}
DropdownMenuItem(onClick = {
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) {
Text(text = getString(R.string.set_exam_menu))
Icon(
painter = painterResource(id = R.drawable.ic_editor),
contentDescription = null
)
}
}
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,
RenameActivity::class.java
).apply {
putExtra(
AssociationActivity::class.java.name,
associationId
)
})
model.close()
}) {
Row(verticalAlignment = Alignment.CenterVertically) {
Text(text = getString(R.string.rename_menu))
Icon(
painter = painterResource(id = R.drawable.ic_exchange_rate),
contentDescription = null
)
}
}
}
TokenManager.getUserInfo()?.associationVo == null -> DropdownMenuItem(
onClick = {
model.applyAssociation(associationId = associationId) {
model.update(applyAssociationResultVo = it)
}
model.close()
}) {
Row(verticalAlignment = Alignment.CenterVertically) {
Text(text = getString(R.string.join_association))
Icon(
painter = painterResource(id = R.drawable.ic_add_account),
contentDescription = null
)
}
}
}
DropdownMenuItem(onClick = {
model.close()
}) {
Row(verticalAlignment = Alignment.CenterVertically) {
Icon(
painter = painterResource(id = R.drawable.ic_arrow_up),
contentDescription = null,
modifier = Modifier
.height(30.dp)
.fillMaxWidth()
)
}
}
}
}
}
NavHost(
navController = nav,
startDestination = AssociationMenu.startMenu.name
) {
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()
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)
}
}
}
}
}
}
/**
* 显示提示
*
* @param model
* @param examResult
*/
@Composable
private fun ShowTip(
model: AssociationViewModel = viewModel(),
examResult: ManagedActivityResultLauncher<Intent, *>
) {
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)
}
}
/**
* 社团成员
*
*/
@Composable
private fun Member() {
MainColumnFrame(background = { Background(image = BackgroundImage.AssociationMain) }) {
val searchWeight = 0.2F
Search(
modifier = Modifier
.fillMaxWidth()
.weight(searchWeight)
)
MemberList(
modifier = Modifier
.fillMaxWidth()
.weight(1 - searchWeight)
)
}
}
/**
* 检索成员
*
*/
@Composable
private fun Search(
modifier: Modifier = Modifier,
model: MemberViewModel = viewModel()
) {
Column(modifier = modifier.fillMaxSize()) {
Spacer(modifier = Modifier.weight(0.5F))
Row(
modifier = Modifier
.fillMaxWidth()
.weight(0.5F), verticalAlignment = Alignment.CenterVertically
) {
val textFieldWeight = 0.4F
val buttonWeight = 0.2F
val spaceWeight = (1 - textFieldWeight - buttonWeight) / 3
Spacer(modifier = Modifier.weight((spaceWeight)))
BaseTextField(
modifier = Modifier.weight(textFieldWeight),
form = model.name,
singeLine = true
)
Spacer(modifier = Modifier.weight(spaceWeight))
OutlinedButton(
onClick = {
model.load(associationId)
},
modifier = Modifier.weight(buttonWeight)
) {
Text(text = stringResource(id = R.string.search_btn))
}
Spacer(modifier = Modifier.weight(spaceWeight))
}
}
}
/**
* 成员列表
*
*/
@Composable
private fun MemberList(
modifier: Modifier = Modifier,
model: MemberViewModel = viewModel()
) {
model.load(associationId)
val data by model.data.observeAsState()
val listState = rememberLazyListState()
LazyColumn(
state = listState, modifier = modifier, verticalArrangement =
Arrangement.spacedBy(space = 10.dp, alignment = Alignment.CenterVertically)
) {
data?.forEach {
item {
Profile(modifier = Modifier.height(300.dp), personInfoVo = it, readOnly = true)
}
}
}
}
/**
* 社团主页
*
*/
@Composable
private fun Main(model: AssociationViewModel = viewModel()) {
LaunchedEffect(associationId) {
model.load(associationId)
}
MainColumnFrame(background = {
Background(image = BackgroundImage.AssociationMain, alpha = 0.7F)
}) {
val nameW = 0.1F
val cardW = 0.66F * 0.4F
Name(
modifier = Modifier
.fillMaxWidth()
.weight(nameW)
)
val associationVo by model.associationVo.observeAsState()
associationVo?.associationVo?.desc?.let {
DescCard(
modifier = Modifier
.weight(cardW)
.fillMaxWidth(),
content = it
)
}
Commander(
modifier = Modifier.weight(cardW)
)
Showcase(modifier = Modifier.weight(1F - nameW - cardW - cardW))
}
}
/**
* 社团名字
*
* @param modifier
*/
@Composable
private fun Name(modifier: Modifier, model: AssociationViewModel = viewModel()) {
val associationVo by model.associationVo.observeAsState()
Box(modifier = modifier) {
Image(
painter = painterResource(id = R.drawable.association_name_border),
contentDescription = null,
contentScale = ContentScale.FillBounds,
modifier = Modifier.fillMaxSize()
)
Column {
Spacer(modifier = Modifier.weight(1.7F / 3))
Row(
modifier = Modifier
.fillMaxWidth()
.weight(1F / 3),
horizontalArrangement = Arrangement.Center
) {
associationVo?.associationVo?.name?.let { Text(text = it) }
}
Spacer(modifier = Modifier.weight(0.3F / 3))
}
}
}
/**
* 团长名字
*
* @param modifier
*/
@Composable
private fun Commander(modifier: Modifier, model: AssociationViewModel = viewModel()) {
Box(modifier = modifier, contentAlignment = Alignment.Center) {
Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.Center) {
Image(
painter = painterResource(id = R.drawable.persion_name_border),
contentDescription = null
)
}
val info by model.associationVo.observeAsState()
info?.head?.let {
Text(text = it.name)
}
}
}
/**
* 风采展示区
*
* @param modifier
*/
@Composable
private fun Showcase(modifier: Modifier) {
Box(modifier = modifier, contentAlignment = Alignment.Center) {
Image(
painter = painterResource(id = R.drawable.showcase_border),
contentDescription = null,
modifier = Modifier.fillMaxSize()
)
Image(
painter = painterResource(id = R.drawable.ic_launcher_foreground),
contentDescription = null
)
}
}
/**
* 活动列表
*
*/
@Composable
private fun AssociationList() {
MainColumnFrame(background = {
Background(
image = BackgroundImage.AssociationMain,
alpha = 07F
)
}) {
HistoryActivityList(
modifier = Modifier
.fillMaxWidth()
.border(width = 1.dp, color = MaterialTheme.colors.onBackground)
)
}
}
/**
* 进行中的活动
*
*/
@Composable
private fun OngoingActivity(
modifier: Modifier = Modifier
) {
Row(modifier = modifier, horizontalArrangement = Arrangement.Center) {
val weight = 0.5F
val spaceWeight = (1 - 0.5F) / 2
Spacer(modifier = Modifier.weight(spaceWeight))
Poster(modifier = Modifier.weight(weight))
Spacer(modifier = Modifier.weight(spaceWeight))
}
}
/**
* 历史活动列表
*
* @param modifier
*/
@Composable
private fun HistoryActivityList(
modifier: Modifier,
model: HistoryActViewModel = viewModel()
) {
LaunchedEffect(associationId) {
model.load(associationId = associationId)
}
val list by model.data.observeAsState()
if (list?.size == 0) {
Row(modifier = Modifier.fillMaxWidth()) {
Text(text = "目前社团没有任何活动")
}
} else {
Activities(list = list, modifier = modifier)
}
}
@Preview
@Composable
fun NamePreview() {
Divider(color = MaterialTheme.colors.background)
}
}