From 5ec8924532a885ba463014791882dbc43467193c Mon Sep 17 00:00:00 2001 From: pan <1029559041@qq.com> Date: Fri, 4 Jun 2021 18:38:45 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E5=96=84=E6=B4=BB=E5=8A=A8=E8=AF=A6?= =?UTF-8?q?=E6=83=85=EF=BC=8C=E5=92=8C=E6=9C=8D=E5=8A=A1=E7=AB=AF=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3=E8=81=94=E8=B0=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/com/gyf/csams/InitActivity.kt | 2 +- .../model/AssociationManagementViewModel.kt | 2 +- .../gyf/csams/main/model/AuditActViewModel.kt | 3 +- .../main/model/AuditAssociationViewModel.kt | 3 +- .../csams/main/model/BaseAuditViewModel.kt | 5 +- .../com/gyf/csams/main/model/MenuViewModel.kt | 10 +- .../com/gyf/csams/main/ui/MainActivity.kt | 11 +- .../java/com/gyf/csams/ExampleUnitTest.kt | 2 +- .../main/java/com/gyf/csams/InitActivity.kt | 3 +- .../csams/account/model/AccountViewModel.kt | 5 +- .../activity/model/ActivityDetailViewModel.kt | 145 ++++++++--- .../csams/activity/model/ApplyActViewModel.kt | 5 +- .../activity/ui/ActivityDetailActivity.kt | 238 +++++++++++++----- .../association/model/AssociationViewModel.kt | 23 +- .../model/RegAssociationViewModel.kt | 3 +- .../association/ui/AssociationActivity.kt | 15 +- .../com/gyf/csams/main/model/MainViewModel.kt | 8 - .../com/gyf/csams/main/ui/MainActivity.kt | 2 +- .../main/java/com/gyf/csams/uikit/BaseView.kt | 15 +- .../java/com/gyf/csams/uikit/ViewModel.kt | 1 + .../java/com/gyf/csams/util/HttpCallback.kt | 3 +- foreground/src/main/res/values-en/strings.xml | 4 + foreground/src/main/res/values-zh/strings.xml | 4 + foreground/src/main/res/values/strings.xml | 4 + .../java/com/gyf/csams/ExampleUnitTest.kt | 2 +- .../gyf/lib/model/AbstractLoginViewModel.kt | 1 + .../java/com/gyf/lib/model/InitViewModel.kt | 1 + .../com/gyf/lib/model/SysMessageViewModel.kt | 1 + .../com/gyf/lib/service/MessageService.kt | 1 + lib/src/main/java/com/gyf/lib/util/Api.kt | 20 +- .../java/com/gyf/lib/util/BottomButton.kt | 4 +- .../main/java/com/gyf/lib/util/HttpUtil.kt | 21 +- 32 files changed, 403 insertions(+), 164 deletions(-) diff --git a/background/src/main/java/com/gyf/csams/InitActivity.kt b/background/src/main/java/com/gyf/csams/InitActivity.kt index b6e6308..7a498c6 100644 --- a/background/src/main/java/com/gyf/csams/InitActivity.kt +++ b/background/src/main/java/com/gyf/csams/InitActivity.kt @@ -4,10 +4,10 @@ import android.app.Activity import com.google.gson.reflect.TypeToken import com.gyf.csams.account.ui.LoginActivity import com.gyf.csams.main.ui.MainActivity +import com.gyf.csams.module.ApiResponse import com.gyf.csams.module.ManagerVo import com.gyf.lib.uikit.AbstractInitActivity import com.gyf.lib.util.AccountApi -import com.gyf.lib.util.ApiResponse import java.lang.reflect.Type class InitActivity : AbstractInitActivity() { 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 fa8212a..42795b4 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 @@ -20,7 +20,7 @@ class AssociationManagementViewModel(application: Application) : ScrollViewModel } fun load() { - TODO() + TODO("数据状态管理") } fun loadMore(callback: (message: String) -> Unit) { 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 737f5bc..ecb1ce7 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 @@ -2,10 +2,9 @@ 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.AuditActVo import com.gyf.lib.util.ActivityApi -import com.gyf.lib.util.ApiResponse - import com.gyf.lib.util.UrlPath import java.lang.reflect.Type 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 a38341e..1e9eef6 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 @@ -2,10 +2,9 @@ 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.AuditAssociationVo -import com.gyf.lib.util.ApiResponse import com.gyf.lib.util.AssociationApi - import com.gyf.lib.util.UrlPath import java.lang.reflect.Type 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 f952309..c1d679b 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 @@ -3,10 +3,7 @@ package com.gyf.csams.main.model import android.app.Application import androidx.lifecycle.viewModelScope import com.google.gson.reflect.TypeToken -import com.gyf.csams.module.AcceptVo -import com.gyf.csams.module.AuditVo -import com.gyf.csams.module.CheckVo -import com.gyf.csams.module.ClientType +import com.gyf.csams.module.* import com.gyf.lib.model.ScrollViewModel import com.gyf.lib.util.* import kotlinx.coroutines.launch 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 41c02d9..3bd1751 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 @@ -2,13 +2,15 @@ package com.gyf.csams.main.model import android.app.Activity import androidx.lifecycle.ViewModel -import com.gyf.csams.main.ui.* +import com.gyf.csams.main.ui.AuditActActivity +import com.gyf.csams.main.ui.AuditAssociationActivity +import com.gyf.csams.main.ui.RenameActivity enum class MenuType(val desc: String, val clazz: Map>) { Association( "社团管理", mapOf( - "社团信息管理" to AssociationManagementActivity::class.java, +// TODO "社团信息管理" to AssociationManagementActivity::class.java, "审核社团换名" to RenameActivity::class.java, "审核社团注册" to AuditAssociationActivity::class.java ), @@ -16,8 +18,8 @@ enum class MenuType(val desc: String, val clazz: Map Act( "活动管理", mapOf( "审核社团活动" to AuditActActivity::class.java, - "审核质量报告单" to CheckQualityReportActivity::class.java, - "查看社团活动" to ManagerActActivity::class.java +// TODO "审核质量报告单" to CheckQualityReportActivity::class.java, +// "查看社团活动" to ManagerActActivity::class.java ) ) } 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 e0d5dc4..3aa8d2b 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,11 +59,12 @@ class MainActivity : BaseActivity() { Text(text = "我的通知") } - OutlinedButton(onClick = { - startActivity(Intent(this@MainActivity, DepartmentActivity::class.java)) - }, modifier = Modifier.fillMaxWidth()) { - Text(text = stringResource(id = R.string.department_management)) - } +// 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( diff --git a/background/src/test/java/com/gyf/csams/ExampleUnitTest.kt b/background/src/test/java/com/gyf/csams/ExampleUnitTest.kt index 2829394..cad4724 100644 --- a/background/src/test/java/com/gyf/csams/ExampleUnitTest.kt +++ b/background/src/test/java/com/gyf/csams/ExampleUnitTest.kt @@ -1,7 +1,7 @@ package com.gyf.csams import com.google.gson.reflect.TypeToken -import com.gyf.lib.util.ApiResponse +import com.gyf.csams.module.ApiResponse import com.orhanobut.logger.Logger import org.junit.Assert.assertEquals import org.junit.Test diff --git a/foreground/src/main/java/com/gyf/csams/InitActivity.kt b/foreground/src/main/java/com/gyf/csams/InitActivity.kt index b5b2986..babade5 100644 --- a/foreground/src/main/java/com/gyf/csams/InitActivity.kt +++ b/foreground/src/main/java/com/gyf/csams/InitActivity.kt @@ -4,11 +4,10 @@ import android.app.Activity import com.google.gson.reflect.TypeToken import com.gyf.csams.account.ui.AccountActivity import com.gyf.csams.main.ui.MainActivity +import com.gyf.csams.module.ApiResponse import com.gyf.csams.module.UserVo import com.gyf.lib.uikit.AbstractInitActivity import com.gyf.lib.util.AccountApi -import com.gyf.lib.util.ApiResponse - import java.lang.reflect.Type class InitActivity : AbstractInitActivity() { diff --git a/foreground/src/main/java/com/gyf/csams/account/model/AccountViewModel.kt b/foreground/src/main/java/com/gyf/csams/account/model/AccountViewModel.kt index 8af1f50..782879a 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 @@ -11,10 +11,7 @@ import com.google.gson.reflect.TypeToken import com.gyf.csams.R import com.gyf.csams.account.ui.AccountActivity import com.gyf.csams.account.ui.AccountRoute -import com.gyf.csams.module.ClientType -import com.gyf.csams.module.UserLoginVo -import com.gyf.csams.module.UserRegVo -import com.gyf.csams.module.UserVo +import com.gyf.csams.module.* import com.gyf.lib.model.AbstractLoginViewModel import com.gyf.lib.uikit.FormStatus import com.gyf.lib.uikit.ValidStringForm 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 5c943a7..1e8bad2 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 @@ -1,19 +1,22 @@ package com.gyf.csams.activity.model import android.app.Application +import android.net.Uri import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel -import com.gyf.csams.module.ActivityDetailVo -import com.gyf.csams.module.ActivityPhotoVo -import com.gyf.csams.module.BBSVo -import com.gyf.csams.module.UserInfoVo +import androidx.lifecycle.viewModelScope +import com.google.gson.reflect.TypeToken +import com.gyf.csams.MainApplication +import com.gyf.csams.module.* import com.gyf.csams.uikit.AbstractComment import com.gyf.csams.uikit.ActivityDetailMenu import com.gyf.csams.uikit.TopMenuInterface import com.gyf.lib.model.ScrollViewModel import com.gyf.lib.uikit.ValidStringForm -import com.gyf.lib.util.NOT_IMPL_TIP +import com.gyf.lib.util.* +import kotlinx.coroutines.launch +import java.io.File /** * 活动详情菜单通用状态 @@ -36,9 +39,6 @@ class ActivityInfoViewModel : ViewModel() { val like = "点赞" val collect = "收藏" - init { - loadInfo() - } /** * TODO 点赞 @@ -58,8 +58,24 @@ class ActivityInfoViewModel : ViewModel() { callback(NOT_IMPL_TIP) } - private fun loadInfo() { - TODO() + /** + * 加载活动详情 + * + * @param activityId + */ + fun load(activityId: Int) { + viewModelScope.launch { + HttpClient.post(url = Api.buildUrl(ActivityApi.Show), + callback = HttpCallback(action = "加载活动详情", + onSuccess = { it -> + it.body?.let { + _activityDetailVo.postValue(it) + } + }, typeToken = object : TypeToken>() {}.type + ), + jsonParam = ShowActivityVo(activityId = activityId, token = TokenManager.getToken()) + ) + } } } @@ -71,32 +87,61 @@ class ActivityInfoViewModel : ViewModel() { */ class ActivityPhotoViewModel(application: Application) : ScrollViewModel(application) { - override val initSize: Int = 10 - - init { - load() - } - fun upload(callback: (message: String) -> Unit) { - callback(NOT_IMPL_TIP) - } + val name = ValidStringForm("照片名", textLength = 10) /** + * 上传照片 * - * + * @param uri */ - fun load() { - TODO("加载相册") + fun upload(activityId: Int, uri: Uri, callback: (message: String) -> Unit) { + val resolver = getApplication().contentResolver + resolver.openInputStream(uri)?.readBytes()?.apply { + name.clean() + viewModelScope.launch { + val context = getApplication() + runCatching { + val cacheFile = File(context.cacheDir, "${System.currentTimeMillis()}") + cacheFile.writeBytes(this@apply) + HttpClient.uploadFile(url = Api.buildUrl(ActivityApi.UploadPhoto), + callback = HttpCallback(action = "上传照片", + onSuccess = { + callback("上传成功") + }, typeToken = object : TypeToken>() {}.type + ), + params = mapOf( + "activityId" to "$activityId", + "name" to (name.formValue.value + ?: throw IllegalArgumentException("照片名字为空")) + ), + fileList = arrayOf(cacheFile) + ) + } + } + + } } - /** + * 加载相册 * - * - * @param callback */ - fun loadMore(callback: (message: String) -> Unit) { - TODO("加载更多相册") + fun load(activityId: Int) { + viewModelScope.launch { + HttpClient.post( + url = Api.buildUrl(ActivityApi.Photo), + callback = HttpCallback>( + action = "加载相册", + onSuccess = { + _data.postValue(it.body) + }, + typeToken = object : + TypeToken>>() {}.type + ), + jsonParam = SearchActivityPhotoVo(activityId = activityId) + ) + } } } @@ -104,25 +149,36 @@ class ActivityPhotoViewModel(application: Application) : class ActivityMemberViewModel(application: Application) : ScrollViewModel(application) { - /** - * - * - */ - fun load() { - TODO("加载活动成员") - } + } class BBSCommentModel : AbstractComment() { override val newContent = ValidStringForm(formDesc = "评论内容", textLength = 80) + var activityId: Int? = null + + /** - * TODO 发送评论 - * + * 发送评论 * @param callback */ override fun send(callback: (message: String) -> Unit) { - callback(NOT_IMPL_TIP) + viewModelScope.launch { + HttpClient.post(url = Api.buildUrl(ActivityApi.SendComment), + callback = HttpCallback(action = "发送评论", + onSuccess = { + callback(it.message) + }, typeToken = object : TypeToken>() {}.type + ), + jsonParam = + SendBBSVo( + content = newContent.formValue.value + ?: throw IllegalArgumentException("评论内容为空"), + token = TokenManager.getToken(), + activityId = activityId ?: throw IllegalArgumentException("活动id没有初始化") + ) + ) + } } } @@ -131,14 +187,21 @@ class BBSCommentModel : AbstractComment() { * */ class BBSViewModel(application: Application) : ScrollViewModel(application) { - override val initSize: Int = 10 - val title = "发送评论" /** - * + * 加载评论 */ - fun load() { - TODO("加载评论") + fun load(activityId: Int) { + viewModelScope.launch { + HttpClient.post(url = Api.buildUrl(ActivityApi.Comment), + callback = HttpCallback>(action = "加载评论", + onSuccess = { + _data.postValue(it.body) + }, typeToken = object : TypeToken>>() {}.type + ), + jsonParam = SearchCommentVo(activityId = activityId) + ) + } } } \ No newline at end of file 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 7e83963..84bc93c 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 @@ -25,7 +25,6 @@ import com.gyf.csams.R import com.gyf.csams.module.* import com.gyf.lib.uikit.* import com.gyf.lib.util.* -import com.gyf.lib.util.ApiResponse import com.gyf.lib.util.DateTimeUtil.DATE_FORMAT import com.gyf.lib.util.DateTimeUtil.TIME_FORMAT import com.gyf.lib.util.DateTimeUtil.dateFormat @@ -613,9 +612,9 @@ class ApplyActViewModel(application: Application) : AndroidViewModel(application activityTime = "$activityDate $activityTime".toDate().time, activityAddress = activityAddress, activityDesc = activityDesc, - activitySize = activitySize.toInt() + activitySize = activitySize.toInt(), + activityId = _checkInfo.value?.body?.activityId ), - activityId = _checkInfo.value?.body?.activityId, token = TokenManager.getToken() ) ) diff --git a/foreground/src/main/java/com/gyf/csams/activity/ui/ActivityDetailActivity.kt b/foreground/src/main/java/com/gyf/csams/activity/ui/ActivityDetailActivity.kt index 25d7d34..3be767b 100644 --- a/foreground/src/main/java/com/gyf/csams/activity/ui/ActivityDetailActivity.kt +++ b/foreground/src/main/java/com/gyf/csams/activity/ui/ActivityDetailActivity.kt @@ -1,8 +1,13 @@ package com.gyf.csams.activity.ui +import android.content.Intent +import android.net.Uri import android.os.Bundle +import android.provider.MediaStore import androidx.activity.ComponentActivity +import androidx.activity.compose.rememberLauncherForActivityResult import androidx.activity.compose.setContent +import androidx.activity.result.contract.ActivityResultContracts import androidx.compose.foundation.Canvas import androidx.compose.foundation.Image import androidx.compose.foundation.border @@ -10,38 +15,63 @@ 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.getValue +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.unit.dp import androidx.lifecycle.viewmodel.compose.viewModel +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.insets.ExperimentalAnimatedInsets +import com.google.accompanist.insets.navigationBarsWithImePadding import com.gyf.csams.R import com.gyf.csams.activity.model.* +import com.gyf.csams.association.ui.AssociationActivity import com.gyf.csams.module.ActivityPhotoVo import com.gyf.csams.module.BBSVo import com.gyf.csams.module.UserInfoVo import com.gyf.csams.uikit.* -import com.gyf.lib.uikit.MainColumnFrame -import com.gyf.lib.uikit.NavBody -import com.gyf.lib.uikit.ScaffoldModel -import com.gyf.lib.uikit.ShowSnackbar - +import com.gyf.lib.uikit.* +import com.gyf.lib.util.Api +import com.gyf.lib.util.BottomButton import com.gyf.lib.util.DateTimeUtil.datetimeFormat +import com.gyf.lib.util.TokenManager +import com.orhanobut.logger.Logger import java.util.* +val PHOTO_HEIGHT = 200.dp /** * 活动详情 * */ class ActivityDetailActivity : 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 + } + + private val activityId: Int + get() { + val id = intent.getIntExtra( + ActivityDetailActivity::class.java.name, + 0 + ) + return if (id == 0) throw IllegalArgumentException("活动id:${id}不合法,初始化失败") else id + } + @ExperimentalAnimatedInsets override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -66,15 +96,15 @@ class ActivityDetailActivity : ComponentActivity() { model.clickMenu(ActivityDetailMenu.Info) } composable(ActivityDetailMenu.Photo.name) { - Photo() + Photo(nav = nav) ShowSnackbar(scaffoldState = scaffoldState) model.clickMenu(ActivityDetailMenu.Photo) } - composable(ActivityDetailMenu.Member.name) { - Member() - ShowSnackbar(scaffoldState = scaffoldState) - model.clickMenu(ActivityDetailMenu.Member) - } +// composable(ActivityDetailMenu.Member.name) { +// Member() +// ShowSnackbar(scaffoldState = scaffoldState) +// model.clickMenu(ActivityDetailMenu.Member) +// } composable(ActivityDetailMenu.BBS.name) { BBS() ShowSnackbar(scaffoldState = scaffoldState) @@ -87,32 +117,17 @@ class ActivityDetailActivity : ComponentActivity() { } /** - * 底部按钮 + * 活动信息 * - * @param modifier */ @Composable - private fun BottomButton( - modifier: Modifier = Modifier, + private fun Info( model: ActivityInfoViewModel = viewModel(), scaffoldModel: ScaffoldModel = viewModel() ) { - Row(modifier = modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceEvenly) { - OutlinedButton(onClick = { model.like { scaffoldModel.update(message = it) } }) { - Text(text = model.like) - } - OutlinedButton(onClick = { model.collect { scaffoldModel.update(message = it) } }) { - Text(text = model.collect) - } + LaunchedEffect(activityId) { + model.load(activityId = activityId) } - } - - /** - * 活动信息 - * - */ - @Composable - private fun Info() { MainColumnFrame(background = { Background( image = BackgroundImage.ActivityInfo, @@ -122,7 +137,17 @@ class ActivityDetailActivity : ComponentActivity() { RectList(modifier = Modifier.weight(0.4F)) ActivityDesc(modifier = Modifier.weight(0.4F)) Spacer(modifier = Modifier.weight(0.05F)) - BottomButton() + BottomButton( + modifier = Modifier.fillMaxWidth(), + confirmDesc = R.string.like_btn, + backDesc = R.string.collect_btn, + onConfirm = { + model.like { scaffoldModel.update(message = it) } + }, + onBack = { + model.collect { scaffoldModel.update(message = it) } + }) + Spacer(modifier = Modifier.weight(0.05F)) } } @@ -199,28 +224,106 @@ class ActivityDetailActivity : ComponentActivity() { * 相册 * */ + @ExperimentalAnimatedInsets @Composable private fun Photo( model: ActivityPhotoViewModel = viewModel(), - scaffoldModel: ScaffoldModel = viewModel() + scaffoldModel: ScaffoldModel = viewModel(), + nav: NavHostController ) { + LaunchedEffect(activityId) { + model.load(activityId = activityId) + } + MainColumnFrame(background = { Background( image = BackgroundImage.ActivityPhoto, alpha = 0.7F ) }) { - Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.End) { - IconButton(onClick = { model.upload { scaffoldModel.update(message = it) } }) { - Icon( - painter = painterResource(id = R.drawable.ic_upload), - contentDescription = null - ) + + if (TokenManager.getUserInfo()?.associationVo?.associationId == associationId && TokenManager.getUserInfo()?.isHead == true) { + var photoUri: Uri? by remember { + mutableStateOf(null) } - } + Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.End) { + + val resultLauncher = + rememberLauncherForActivityResult(contract = ActivityResultContracts.StartActivityForResult()) { + when (it.resultCode) { + RESULT_OK -> { + it.data?.data?.apply { + Logger.i("uri=$this") + photoUri = this + } + } + } + } + IconButton(onClick = { + resultLauncher.launch( + Intent( + Intent.ACTION_PICK, + MediaStore.Images.Media.EXTERNAL_CONTENT_URI + ) + ) + }) { + Icon( + painter = painterResource(id = R.drawable.ic_upload), + contentDescription = null + ) + } + } + + photoUri?.let { + val status by model.name.statusForm.observeAsState() + AlertDialog(onDismissRequest = { /*TODO*/ }, title = { + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.Center + ) { + Text(text = "上传照片") + } + }, text = { + + val photo = rememberCoilPainter(request = it) + Column { + BaseTextField( + modifier = Modifier.navigationBarsWithImePadding(), + form = model.name + ) + Image( +// modifier=Modifier.weight(0.5F), + painter = photo, + contentDescription = null, + contentScale = ContentScale.Inside + ) + } - Spacer(modifier = Modifier.height(10.dp)) + }, buttons = { + BottomButton( + modifier = Modifier.fillMaxWidth(), + confirmDesc = R.string.upload_btn, + backDesc = R.string.close_btn, + onConfirm = { + model.upload(activityId = activityId, uri = it) { + photoUri = null + scaffoldModel.update(it, actionLabel = "关闭提示") { + nav.navigate(ActivityDetailMenu.Photo.name) + } + } + }, + onBack = { + photoUri = null + }, + enabled = status == FormStatus.Valid + ) + } + ) + } + + Spacer(modifier = Modifier.height(10.dp)) + } Box( modifier = Modifier .fillMaxSize() @@ -242,10 +345,18 @@ class ActivityDetailActivity : ComponentActivity() { horizontalArrangement = Arrangement.SpaceEvenly ) { Spacer(modifier = Modifier.weight(0.05F)) - PhotoItem(vo = it[0], modifier = Modifier.weight(0.4F)) + PhotoItem( + vo = it[0], modifier = Modifier + .weight(0.4F) + .height(PHOTO_HEIGHT) + ) Spacer(modifier = Modifier.weight(0.1F)) if (it.size == 2) { - PhotoItem(vo = it[1], modifier = Modifier.weight(0.4F)) + PhotoItem( + vo = it[1], modifier = Modifier + .weight(0.4F) + .height(PHOTO_HEIGHT) + ) } else { Spacer(modifier = Modifier.weight(0.4F)) } @@ -255,25 +366,35 @@ class ActivityDetailActivity : ComponentActivity() { } } } -// Logger.i("totalItemsCount=${listState.layoutInfo.totalItemsCount},firstVisibleItemIndex=${listState.firstVisibleItemIndex}") - if (listState.layoutInfo.totalItemsCount - listState.firstVisibleItemIndex == model.initSize / 2 - 1) { - model.loadMore { scaffoldModel.update(message = it) } - } } } } } + @Composable private fun PhotoItem(modifier: Modifier = Modifier, vo: ActivityPhotoVo) { Box( modifier = modifier.border(width = 1.dp, color = MaterialTheme.colors.onBackground), contentAlignment = Alignment.Center ) { + val photo = rememberCoilPainter(request = Api.buildUrl(vo.url)) Image( - painter = painterResource(id = R.drawable.ic_launcher_foreground), - contentDescription = null, + painter = photo, + contentDescription = vo.name, ) + when (photo.loadState) { + is ImageLoadState.Loading -> { + // Display a circular progress indicator whilst loading + CircularProgressIndicator(Modifier.align(Alignment.Center)) + } + is ImageLoadState.Error -> { + // If you wish to display some content if the request fails + } + else -> { + + } + } } } @@ -307,6 +428,7 @@ class ActivityDetailActivity : ComponentActivity() { painter = painterResource(id = R.drawable.persion_name_border), contentDescription = null ) + Text(text = first().name) } } @@ -377,9 +499,12 @@ class ActivityDetailActivity : ComponentActivity() { @Composable private fun BBS( model: BBSViewModel = viewModel(), - scaffoldModel: ScaffoldModel = viewModel(), bbsCommentModel: BBSCommentModel = viewModel() ) { + LaunchedEffect(activityId) { + bbsCommentModel.activityId = this@ActivityDetailActivity.activityId + model.load(activityId) + } MainColumnFrame(background = { Background( image = BackgroundImage.ActivityBBS, @@ -402,7 +527,9 @@ class ActivityDetailActivity : ComponentActivity() { } } - SendComment(model = bbsCommentModel) + SendComment(model = bbsCommentModel) { + model.load(activityId) + } Box( modifier = Modifier @@ -421,9 +548,6 @@ class ActivityDetailActivity : ComponentActivity() { } } } - if (listState.layoutInfo.totalItemsCount - listState.firstVisibleItemIndex == model.initSize / 2 - 1) { - TODO("加载更多") - } } } @@ -445,8 +569,8 @@ class ActivityDetailActivity : ComponentActivity() { modifier = Modifier.height(50.dp), verticalArrangement = Arrangement.SpaceEvenly ) { - Text(text = vo.name) - Text(text = vo.createTime.datetimeFormat()) + Text(text = vo.user.name) + Text(text = Date(vo.createTime).datetimeFormat()) } } Spacer(modifier = Modifier.weight(0.5F)) 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 dc71572..b355ad1 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 @@ -13,7 +13,6 @@ import com.gyf.csams.uikit.TopMenuInterface import com.gyf.lib.model.ScrollViewModel import com.gyf.lib.uikit.StringForm import com.gyf.lib.util.* -import com.gyf.lib.util.ApiResponse import kotlinx.coroutines.launch @@ -105,6 +104,24 @@ class OngoingActViewModel : ViewModel() { * 历史活动 * */ -class HistoryActViewModel(application: Application) : ScrollViewModel(application) { - override val initSize = 10 +class HistoryActViewModel(application: Application) : ScrollViewModel(application) { + + fun load(associationId: Int) { + viewModelScope.launch { + HttpClient.post( + url = Api.buildUrl(ActivityApi.Load), + callback = HttpCallback>( + action = "查看社团活动", + onSuccess = { + _data.postValue(it.body) + }, + typeToken = object : TypeToken>>() {}.type + ), + jsonParam = SearchActivityVo( + associationId = associationId, + token = TokenManager.getToken() + ) + ) + } + } } \ No newline at end of file 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 eb99023..37df963 100644 --- a/foreground/src/main/java/com/gyf/csams/association/model/RegAssociationViewModel.kt +++ b/foreground/src/main/java/com/gyf/csams/association/model/RegAssociationViewModel.kt @@ -12,6 +12,7 @@ import coil.imageLoader import coil.request.ImageRequest import com.google.gson.reflect.TypeToken import com.gyf.csams.MainApplication +import com.gyf.csams.module.ApiResponse import com.gyf.csams.module.AssociationCheckVo import com.gyf.csams.module.AssociationRegVo import com.gyf.csams.module.ClientType @@ -54,7 +55,7 @@ class RegAssociationViewModel(application: Application) : AndroidViewModel(appli _picture.value = uri } - fun getInputSteam(): InputStream? { + private fun getInputSteam(): InputStream? { _picture.value?.let { val resolver = getApplication().contentResolver return resolver.openInputStream(it) 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 f9fbb1e..3e98391 100644 --- a/foreground/src/main/java/com/gyf/csams/association/ui/AssociationActivity.kt +++ b/foreground/src/main/java/com/gyf/csams/association/ui/AssociationActivity.kt @@ -30,7 +30,7 @@ import com.gyf.csams.R import com.gyf.csams.activity.ui.ActivityDetailActivity import com.gyf.csams.activity.ui.ApplyActActivity import com.gyf.csams.association.model.* -import com.gyf.csams.module.HistoryActVo +import com.gyf.csams.module.ActivityVo import com.gyf.csams.uikit.* import com.gyf.lib.uikit.* import com.gyf.lib.util.TokenManager @@ -488,6 +488,10 @@ class AssociationActivity : ComponentActivity() { modifier: Modifier, model: HistoryActViewModel = viewModel() ) { + LaunchedEffect(associationId) { + model.load(associationId = associationId) + } + val listState = rememberLazyListState() val list by model.data.observeAsState() LazyColumn(state = listState, modifier = modifier) { @@ -515,9 +519,12 @@ class AssociationActivity : ComponentActivity() { * @param modifier */ @Composable - private fun HistoryActivity(modifier: Modifier, historyActVo: HistoryActVo) { + private fun HistoryActivity(modifier: Modifier, historyActVo: ActivityVo) { Box(modifier = modifier.clickable(onClick = { - startActivity(Intent(this, ActivityDetailActivity::class.java)) + startActivity(Intent(this, ActivityDetailActivity::class.java).apply { + putExtra(ActivityDetailActivity::class.java.name, historyActVo.activityId) + putExtra(AssociationActivity::class.java.name, associationId) + }) }), contentAlignment = Alignment.Center) { Image( painter = painterResource(id = R.drawable.history_activity_border), @@ -529,7 +536,7 @@ class AssociationActivity : ComponentActivity() { contentDescription = null, modifier = Modifier.fillMaxSize() ) - Text(text = historyActVo.name) + Text(text = historyActVo.activityName) } } 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 61a5458..da9aff7 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 @@ -10,7 +10,6 @@ import com.gyf.lib.uikit.FormStatus import com.gyf.lib.uikit.StringForm import com.gyf.lib.uikit.ValidStringForm import com.gyf.lib.util.* -import com.gyf.lib.util.ApiResponse import com.orhanobut.logger.Logger import kotlinx.coroutines.Job import kotlinx.coroutines.delay @@ -203,11 +202,4 @@ class CenterViewModel : ViewModel() { val myLikeActivity = "我点赞的社团活动" val myCollectActivity = "我收藏的社团活动" - - - private fun load() { - viewModelScope.launch { - TODO() - } - } } diff --git a/foreground/src/main/java/com/gyf/csams/main/ui/MainActivity.kt b/foreground/src/main/java/com/gyf/csams/main/ui/MainActivity.kt index 4c0ee13..8dd822f 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 @@ -127,7 +127,7 @@ class MainActivity : BaseActivity() { putExtra(AssociationActivity::javaClass.name, it) }) } - CenterMenuItem(text = model.myJoinActivity) +// CenterMenuItem(text = model.myJoinActivity) CenterMenuItem(text = model.myLikeActivity) CenterMenuItem(text = model.myCollectActivity) } 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 abb5031..d0d418d 100644 --- a/foreground/src/main/java/com/gyf/csams/uikit/BaseView.kt +++ b/foreground/src/main/java/com/gyf/csams/uikit/BaseView.kt @@ -117,7 +117,9 @@ enum class AssociationMenu(override val menuName: String) : TopBarMenu { enum class ActivityDetailMenu(override val menuName: String) : TopBarMenu { Info("活动信息"), Photo("相册"), - Member("活动成员"), + + //TODO 活动成员 +// Member("活动成员"), BBS("交流区"); companion object Menu : StartMenu { @@ -175,7 +177,11 @@ abstract class AbstractComment : ViewModel() { */ @Composable -fun SendComment(model: T, scaffoldModel: ScaffoldModel = viewModel()) { +fun SendComment( + model: T, + scaffoldModel: ScaffoldModel = viewModel(), + callback: () -> Unit = {} +) { val openDialog by model.openDialog.observeAsState() val status by model.newContent.statusForm.observeAsState() @@ -191,7 +197,10 @@ fun SendComment(model: T, scaffoldModel: ScaffoldModel = v OutlinedButton(onClick = { model.send { model.closeDialog() - scaffoldModel.update(message = it) + scaffoldModel.update(message = it, actionLabel = "知道了") { + + } + callback() } }, enabled = status == FormStatus.Valid) { Text(text = "发送") 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 f3014f4..f5b01dd 100644 --- a/foreground/src/main/java/com/gyf/csams/uikit/ViewModel.kt +++ b/foreground/src/main/java/com/gyf/csams/uikit/ViewModel.kt @@ -8,6 +8,7 @@ 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.lib.util.* import com.orhanobut.logger.Logger import kotlinx.coroutines.Job 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 2148506..e47e608 100644 --- a/foreground/src/main/java/com/gyf/csams/util/HttpCallback.kt +++ b/foreground/src/main/java/com/gyf/csams/util/HttpCallback.kt @@ -2,9 +2,8 @@ package com.gyf.csams.util import com.google.gson.Gson import com.google.gson.GsonBuilder +import com.gyf.csams.module.ApiResponse import com.gyf.csams.module.Exam -import com.gyf.lib.util.ApiResponse - import com.gyf.lib.util.HttpCallback import java.lang.reflect.Type diff --git a/foreground/src/main/res/values-en/strings.xml b/foreground/src/main/res/values-en/strings.xml index 3583d49..8f46ff8 100644 --- a/foreground/src/main/res/values-en/strings.xml +++ b/foreground/src/main/res/values-en/strings.xml @@ -16,4 +16,8 @@ 同学您好\n 欢迎使用 再次申请 + 点赞 + 收藏 + 上传 + 关闭 \ 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 3583d49..8f46ff8 100644 --- a/foreground/src/main/res/values-zh/strings.xml +++ b/foreground/src/main/res/values-zh/strings.xml @@ -16,4 +16,8 @@ 同学您好\n 欢迎使用 再次申请 + 点赞 + 收藏 + 上传 + 关闭 \ 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 36dbfa6..eea6d84 100644 --- a/foreground/src/main/res/values/strings.xml +++ b/foreground/src/main/res/values/strings.xml @@ -16,4 +16,8 @@ 同学您好\n 欢迎使用 再次申请 + 点赞 + 收藏 + 上传 + 关闭 \ 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 7f442bf..ee2401d 100644 --- a/foreground/src/test/java/com/gyf/csams/ExampleUnitTest.kt +++ b/foreground/src/test/java/com/gyf/csams/ExampleUnitTest.kt @@ -2,8 +2,8 @@ package com.gyf.csams import com.google.gson.Gson import com.google.gson.reflect.TypeToken +import com.gyf.csams.module.ApiResponse import com.gyf.lib.uikit.StringForm -import com.gyf.lib.util.ApiResponse import com.gyf.lib.util.randomChinese import org.junit.Assert.assertEquals import org.junit.Test diff --git a/lib/src/main/java/com/gyf/lib/model/AbstractLoginViewModel.kt b/lib/src/main/java/com/gyf/lib/model/AbstractLoginViewModel.kt index 0cb73c8..bf22e92 100644 --- a/lib/src/main/java/com/gyf/lib/model/AbstractLoginViewModel.kt +++ b/lib/src/main/java/com/gyf/lib/model/AbstractLoginViewModel.kt @@ -8,6 +8,7 @@ import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.viewModelScope import com.google.gson.reflect.TypeToken +import com.gyf.csams.module.ApiResponse import com.gyf.csams.module.ClientType import com.gyf.csams.module.ManagerVo import com.gyf.csams.module.UserVo diff --git a/lib/src/main/java/com/gyf/lib/model/InitViewModel.kt b/lib/src/main/java/com/gyf/lib/model/InitViewModel.kt index 48fb206..d120af7 100644 --- a/lib/src/main/java/com/gyf/lib/model/InitViewModel.kt +++ b/lib/src/main/java/com/gyf/lib/model/InitViewModel.kt @@ -6,6 +6,7 @@ import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.viewModelScope import com.google.gson.reflect.TypeToken +import com.gyf.csams.module.ApiResponse import com.gyf.csams.module.OwnInfoVo import com.gyf.csams.module.Token import com.gyf.lib.util.* diff --git a/lib/src/main/java/com/gyf/lib/model/SysMessageViewModel.kt b/lib/src/main/java/com/gyf/lib/model/SysMessageViewModel.kt index 02ef3eb..8886358 100644 --- a/lib/src/main/java/com/gyf/lib/model/SysMessageViewModel.kt +++ b/lib/src/main/java/com/gyf/lib/model/SysMessageViewModel.kt @@ -5,6 +5,7 @@ import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.viewModelScope import com.google.gson.reflect.TypeToken +import com.gyf.csams.module.ApiResponse import com.gyf.csams.module.ClientType import com.gyf.csams.module.NotificationDto import com.gyf.csams.module.NotificationVo diff --git a/lib/src/main/java/com/gyf/lib/service/MessageService.kt b/lib/src/main/java/com/gyf/lib/service/MessageService.kt index c25cdf2..4d1ed57 100644 --- a/lib/src/main/java/com/gyf/lib/service/MessageService.kt +++ b/lib/src/main/java/com/gyf/lib/service/MessageService.kt @@ -6,6 +6,7 @@ import androidx.core.app.NotificationCompat import androidx.core.app.NotificationManagerCompat import com.google.gson.Gson import com.google.gson.reflect.TypeToken +import com.gyf.csams.module.ApiResponse import com.gyf.csams.module.ClientType import com.gyf.csams.module.NotificationDto import com.gyf.csams.module.NotificationVo 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 f7bc60b..ca7660a 100644 --- a/lib/src/main/java/com/gyf/lib/util/Api.kt +++ b/lib/src/main/java/com/gyf/lib/util/Api.kt @@ -130,7 +130,25 @@ enum class ActivityApi(val path: String) : UrlPath { Check("/check"), //审核进度 - Read("/read"); + Read("/read"), + + //加载活动 + Load("/load"), + + //加载活动详情 + Show("/show"), + + //加载活动照片 + Photo("/photo"), + + //上传照片 + UploadPhoto("${Photo.path}/upload"), + + //查看评论 + Comment("/comment"), + + //发送评论 + SendComment("${Comment.path}/send"); override fun build(): String { diff --git a/lib/src/main/java/com/gyf/lib/util/BottomButton.kt b/lib/src/main/java/com/gyf/lib/util/BottomButton.kt index ee725d7..f014b64 100644 --- a/lib/src/main/java/com/gyf/lib/util/BottomButton.kt +++ b/lib/src/main/java/com/gyf/lib/util/BottomButton.kt @@ -26,7 +26,7 @@ fun BottomButton( onBack: (() -> Unit)? = null, onConfirm: () -> Unit ) { - val context = LocalContext.current as Activity + val context = LocalContext.current as? Activity Row(modifier = modifier, horizontalArrangement = Arrangement.Center) { OutlinedButton( onClick = onConfirm, @@ -39,7 +39,7 @@ fun BottomButton( if (backDesc != null) { Spacer(modifier = Modifier.width(10.dp)) OutlinedButton(onClick = { - if (onBack == null) context.onBackPressed() else onBack() + if (onBack == null) context?.onBackPressed() else onBack() }, modifier = Modifier.background(color = MaterialTheme.colors.secondary)) { Text(text = stringResource(id = backDesc)) } diff --git a/lib/src/main/java/com/gyf/lib/util/HttpUtil.kt b/lib/src/main/java/com/gyf/lib/util/HttpUtil.kt index 1876d20..ec6eb9d 100644 --- a/lib/src/main/java/com/gyf/lib/util/HttpUtil.kt +++ b/lib/src/main/java/com/gyf/lib/util/HttpUtil.kt @@ -1,6 +1,7 @@ package com.gyf.lib.util import com.google.gson.* +import com.gyf.csams.module.ApiResponse import com.gyf.csams.module.Token import com.orhanobut.logger.Logger import okhttp3.* @@ -152,13 +153,21 @@ object HttpClient { * @param url * @param callback */ - fun uploadFile(url: String, callback: Callback, vararg fileList: File) { + fun uploadFile( + url: String, + callback: Callback, + params: Map? = null, + vararg fileList: File + ) { Logger.i("request url=$url") val token = TokenManager.getToken() val body = MultipartBody.Builder() .addFormDataPart("id", token.id.toString()) .addFormDataPart("token", token.token) .addFormDataPart("createTime", token.createTime.toString()) + params?.forEach { + body.addFormDataPart(it.key, it.value) + } fileList.withIndex().forEach { body.addFormDataPart( "file${it.index}", @@ -175,16 +184,6 @@ object HttpClient { } } -/** - * 接口响应实体 - * - * @param T - * @property code - * @property message - * @property body - */ -data class ApiResponse(val code: Int, val message: String, val body: T? = null) - interface GsonBuilderInterface { val gson: Gson