界面框架优化

增加社团管理-社团信息管理界面
master
pan 4 years ago
parent d64411fa51
commit a68a79ddb5
  1. 6
      background/src/main/AndroidManifest.xml
  2. 6
      background/src/main/java/com/gyf/csams/account/ui/LoginActivity.kt
  3. 96
      background/src/main/java/com/gyf/csams/main/model/AssociationManagementViewModel.kt
  4. 15
      background/src/main/java/com/gyf/csams/main/model/MenuViewModel.kt
  5. 124
      background/src/main/java/com/gyf/csams/main/ui/AssociationManagementActivity.kt
  6. 17
      background/src/main/java/com/gyf/csams/main/ui/DepartmentActivity.kt
  7. 30
      background/src/main/java/com/gyf/csams/main/ui/MainActivity.kt
  8. 20
      background/src/main/java/com/gyf/csams/main/ui/ManagementOfficerActivity.kt
  9. 79
      background/src/main/java/com/gyf/csams/main/ui/MenuActivity.kt
  10. 1
      background/src/main/res/values-en/strings.xml
  11. 1
      background/src/main/res/values-zh/strings.xml
  12. 1
      background/src/main/res/values/strings.xml
  13. 46
      foreground/src/main/java/com/gyf/csams/account/model/AccountViewModel.kt
  14. 94
      foreground/src/main/java/com/gyf/csams/account/ui/AccountActivity.kt
  15. 2
      foreground/src/main/java/com/gyf/csams/activity/model/ActivityDetailViewModel.kt
  16. 7
      foreground/src/main/java/com/gyf/csams/activity/ui/ActivityDetailActivity.kt
  17. 3
      foreground/src/main/java/com/gyf/csams/activity/ui/ApplyActActivity.kt
  18. 2
      foreground/src/main/java/com/gyf/csams/association/model/AssociationViewModel.kt
  19. 2
      foreground/src/main/java/com/gyf/csams/association/model/ExamViewModel.kt
  20. 28
      foreground/src/main/java/com/gyf/csams/association/ui/AssociationActivity.kt
  21. 8
      foreground/src/main/java/com/gyf/csams/association/ui/ExamActivity.kt
  22. 8
      foreground/src/main/java/com/gyf/csams/association/ui/ReNameActivity.kt
  23. 29
      foreground/src/main/java/com/gyf/csams/association/ui/RegAssociationActivity.kt
  24. 16
      foreground/src/main/java/com/gyf/csams/main/model/MainViewModel.kt
  25. 17
      foreground/src/main/java/com/gyf/csams/main/ui/MainActivity.kt
  26. 2
      foreground/src/main/java/com/gyf/csams/message/model/SysMessageViewModel.kt
  27. 4
      foreground/src/main/java/com/gyf/csams/message/ui/MessageActivity.kt
  28. 4
      foreground/src/main/java/com/gyf/csams/message/ui/SysMessageActivity.kt
  29. 18
      foreground/src/main/java/com/gyf/csams/uikit/ViewModel.kt
  30. 18
      lib/src/main/java/com/gyf/lib/ScrollList.kt
  31. 13
      lib/src/main/java/com/gyf/lib/uikit/MainFrame.kt
  32. 5
      lib/src/main/java/com/gyf/lib/util/BottomButton.kt

@ -32,6 +32,12 @@
<activity
android:name=".main.ui.ManagementOfficerActivity"
android:exported="true" />
<activity
android:name=".main.ui.AssociationManagementActivity"
android:exported="true" />
<activity
android:name=".main.ui.MenuActivity"
android:exported="true" />
</application>
</manifest>

@ -19,9 +19,8 @@ import androidx.lifecycle.viewmodel.compose.viewModel
import com.gyf.csams.account.model.LoginViewModel
import com.gyf.csams.main.ui.MainActivity
import com.gyf.lib.uikit.BaseTextField
import com.gyf.lib.uikit.Body
import com.gyf.lib.uikit.BodyS
import com.gyf.lib.uikit.MainBoxFrame
import com.gyf.lib.uikit.ShowSnackbar
/**
* 登录
@ -32,7 +31,7 @@ class LoginActivity : ComponentActivity() {
super.onCreate(savedInstanceState)
setContent {
Body { scaffoldState ->
BodyS {
val context = LocalContext.current as LoginActivity
MainBoxFrame(
background = { /*TODO 背景图*/ },
@ -57,7 +56,6 @@ class LoginActivity : ComponentActivity() {
}) {
Text(text = model.login)
}
ShowSnackbar(scaffoldState = scaffoldState)
}
}
}

@ -0,0 +1,96 @@
package com.gyf.csams.main.model
import androidx.lifecycle.viewModelScope
import com.gyf.lib.ScrollList
import com.gyf.lib.util.randomChinese
import kotlinx.coroutines.launch
/**
* 社团级别
*
*/
enum class AssociationLevel {
A,
B,
C,
D
}
/**
* 所属院系
*
*/
enum class AssociationFaculty(val desc: String, val range: IntRange) {
ForeignLanguageDept("外语系", 0..0),
CivilEngineeringDept("土木工程", 1..10),
SEM("经理管理学院", 11..20),
MechanicalEngineeringDept("机械工程", 21..30),
TransportationDept("交通运输", 31..40),
ArchitectureAndArts("建筑与艺术", 41..50),
ElectricalDept("电气", 51..60),
MaterialsDept("材料", 61..70),
MessageDept("信息", 71..80),
MathematicsDept("数理", 81..90),
GraduateStudent("研究生", 91..99)
}
/**
* 社团
*
* @property name 社团名称
*/
data class AssociationVo(
val associationId: Long, val name: String, val commander: String,
val faculty: AssociationFaculty, val level: AssociationLevel, val desc: String
)
/**
* 数据状态管理
*
*/
class AssociationManagementViewModel : ScrollList<AssociationVo>() {
override val initSize: Int = 10
init {
load()
}
override fun load() {
viewModelScope.launch {
_data.value?.apply {
repeat(initSize) {
add(
AssociationVo(
associationId = (0..65535L).random(),
name = randomChinese(5),
commander = randomChinese(3),
faculty = AssociationFaculty.values().random(),
level = AssociationLevel.values().random(),
desc = randomChinese(20)
)
)
}
}
}
}
override fun loadMore(callback: (message: String) -> Unit) {
TODO("Not yet implemented")
}
/**
* TODO 更新社团级别
*
* @param level
*/
fun update(associationVo: AssociationVo, level: AssociationLevel) {
_data.value?.apply {
val i = indexOf(associationVo)
set(i, associationVo.copy(level = level))
val new = mutableListOf<AssociationVo>()
new.addAll(this)
clear()
_data.postValue(new)
}
}
}

@ -0,0 +1,15 @@
package com.gyf.csams.main.model
import android.app.Activity
import androidx.lifecycle.ViewModel
import com.gyf.csams.main.ui.AssociationManagementActivity
enum class MenuType(val desc: String, val clazz: Map<String, Class<out Activity>>) {
//老师
//总部长
Association("社团管理", mapOf("社团信息管理" to AssociationManagementActivity::class.java))
}
class MenuViewModel : ViewModel() {
}

@ -0,0 +1,124 @@
package com.gyf.csams.main.ui
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.foundation.lazy.rememberLazyListState
import androidx.compose.material.*
import androidx.compose.runtime.getValue
import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
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.main.model.AssociationLevel
import com.gyf.csams.main.model.AssociationManagementViewModel
import com.gyf.lib.uikit.BodyS
import com.gyf.lib.uikit.MainBoxFrame
import com.gyf.lib.uikit.ScaffoldModel
/**
* 社团管理
*
*/
class AssociationManagementActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
BodyS {
MainBoxFrame(background = { /*TODO*/ }) {
val model: AssociationManagementViewModel = viewModel()
val data by model.data.observeAsState()
val listState = rememberLazyListState()
val scaffoldModel: ScaffoldModel = viewModel()
LazyColumn(modifier = Modifier.fillMaxSize(), state = listState) {
data?.forEach {
it.apply {
item {
var expanded by remember {
mutableStateOf(false)
}
Card(backgroundColor = MaterialTheme.colors.background) {
Column(
modifier = Modifier.padding(10.dp),
verticalArrangement = Arrangement.SpaceBetween
) {
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween
) {
Text(
text = "$associationId",
style = MaterialTheme.typography.h6
)
Text(
text = name,
style = MaterialTheme.typography.h4
)
Spacer(modifier = Modifier)
}
Spacer(modifier = Modifier.height(5.dp))
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
Text(
text = commander,
style = MaterialTheme.typography.h5
)
Text(
text = faculty.desc,
style = MaterialTheme.typography.h5
)
OutlinedButton(onClick = {
expanded = true
}) {
Text(
text = level.name,
style = MaterialTheme.typography.h5
)
DropdownMenu(
expanded = expanded,
onDismissRequest = { /*TODO*/ }) {
AssociationLevel.values().forEach {
DropdownMenuItem(onClick = {
model.update(
associationVo = this@apply,
level = it
)
expanded = false
}) {
Text(text = it.name)
}
}
}
}
}
Spacer(modifier = Modifier.height(5.dp))
Card(
modifier = Modifier
.fillMaxWidth()
.height(50.dp)
) {
Text(text = desc)
}
}
}
Spacer(modifier = Modifier.height(10.dp))
}
}
}
}
}
}
}
}
}

@ -1,5 +1,6 @@
package com.gyf.csams.main.ui
import android.content.Intent
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
@ -12,9 +13,10 @@ import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import com.gyf.csams.R
import com.gyf.lib.uikit.Body
import com.gyf.lib.uikit.BodyS
import com.gyf.lib.uikit.MainColumnFrame
@ -27,9 +29,7 @@ class DepartmentActivity : ComponentActivity() {
super.onCreate(savedInstanceState)
setContent {
Body { _ ->
BodyS {
MainColumnFrame(background = { /*TODO*/ }) {
val weight = 0.1F
val departWeight = 0.2F
@ -83,10 +83,9 @@ class DepartmentActivity : ComponentActivity() {
horizontalArrangement = Arrangement.Center
) {
OutlinedButton(onClick = { dialogContent = null }) {
Text(text = context.getString(R.string.close))
Text(text = stringResource(id = R.string.close))
}
}
})
}
@ -152,7 +151,11 @@ class DepartmentActivity : ComponentActivity() {
verticalArrangement = Arrangement.SpaceBetween
) {
RowItem(text = "部门部长:")
RowItem(text = "部门干事管理")
OutlinedButton(modifier = Modifier.fillMaxWidth(), onClick = {
startActivity(Intent(applicationContext, ManagementOfficerActivity::class.java))
}) {
Text(text = stringResource(id = R.string.management_officer))
}
RowItem(text = "部门总人数:")
}
}

@ -14,23 +14,21 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewmodel.compose.viewModel
import com.gyf.csams.R
import com.gyf.csams.main.model.MainViewModel
import com.gyf.lib.uikit.Body
import com.gyf.lib.uikit.MainColumnFrame
import com.gyf.lib.uikit.Profile
import com.gyf.lib.uikit.ShowSnackbar
import com.gyf.csams.main.model.MenuType
import com.gyf.lib.uikit.*
import com.gyf.lib.uikit.theme.CSAMSTheme
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
Body { scaffoldState ->
BodyS {
val model: MainViewModel = viewModel()
val person by model.person.observeAsState()
MainColumnFrame(background = { /*TODO*/ }) {
@ -41,25 +39,31 @@ class MainActivity : ComponentActivity() {
.padding(10.dp), personInfoVo = it
)
}
val context = LocalContext.current
Column(
modifier = Modifier.weight(0.7F),
verticalArrangement = Arrangement.SpaceEvenly
) {
OutlinedButton(onClick = {
context.startActivity(Intent(context, DepartmentActivity::class.java))
startActivity(Intent(this@MainActivity, DepartmentActivity::class.java))
}, modifier = Modifier.fillMaxWidth()) {
Text(text = context.getString(R.string.department_management))
Text(text = stringResource(id = R.string.department_management))
}
OutlinedButton(onClick = { /*TODO*/ }, modifier = Modifier.fillMaxWidth()) {
Text(text = context.getString(R.string.association_management))
OutlinedButton(onClick = {
startActivity(
Intent(
this@MainActivity,
MenuActivity::class.java
).apply {
putExtra(MenuType::name.name, MenuType.Association)
})
}, modifier = Modifier.fillMaxWidth()) {
Text(text = stringResource(id = R.string.association_management))
}
OutlinedButton(onClick = { /*TODO*/ }, modifier = Modifier.fillMaxWidth()) {
Text(text = context.getString(R.string.activity_management))
Text(text = stringResource(id = R.string.activity_management))
}
}
}
ShowSnackbar(scaffoldState = scaffoldState)
}
}
}

@ -25,7 +25,10 @@ import com.gyf.csams.main.model.Duty
import com.gyf.csams.main.model.ManagementOfficerModel
import com.gyf.csams.main.model.MinisterVo
import com.gyf.csams.main.model.OfficerVo
import com.gyf.lib.uikit.*
import com.gyf.lib.uikit.BodyS
import com.gyf.lib.uikit.MainColumnFrame
import com.gyf.lib.uikit.Profile
import com.gyf.lib.uikit.ScaffoldModel
import com.orhanobut.logger.Logger
/**
@ -37,7 +40,7 @@ class ManagementOfficerActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
Body { scaffoldState ->
BodyS {
MainColumnFrame(background = { /*TODO*/ }) {
val weight = 1 / 3F
val model: ManagementOfficerModel = viewModel()
@ -63,8 +66,6 @@ class ManagementOfficerActivity : ComponentActivity() {
officerVoList = publicRelationsDepartment
)
}
ShowSnackbar(scaffoldState = scaffoldState)
}
}
}
@ -132,7 +133,7 @@ class ManagementOfficerActivity : ComponentActivity() {
desc = it.value.mobile
)
) {
Logger.i("expanded=$expanded")
Text(
text = it.value.duty.desc,
modifier = Modifier.clickable(onClick = {
@ -141,14 +142,7 @@ class ManagementOfficerActivity : ComponentActivity() {
.update(message = context.getString(R.string.update_duty_error))
})
)
// Text(
// text = it.duty.desc,
// modifier = Modifier.clickable(onClick = {
// if (duty.desc != Duty.Minister.desc) expanded =
// true else scaffoldModel
// .update(message = context.getString(R.string.update_duty_error))
// })
// )
DropdownMenu(
expanded = expanded,
onDismissRequest = { /*TODO*/ }) {

@ -0,0 +1,79 @@
package com.gyf.csams.main.ui
import android.app.Activity
import android.content.Intent
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.border
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.material.Card
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.unit.dp
import com.gyf.csams.main.model.MenuType
import com.gyf.lib.uikit.BodyS
import com.gyf.lib.uikit.MainBoxFrame
/**
* 菜单
*
*/
class MenuActivity : ComponentActivity() {
lateinit var menuType: MenuType
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
menuType = intent?.getSerializableExtra(MenuType::name.name) as MenuType
setContent {
BodyS {
MainBoxFrame(background = { /*TODO*/ }, contentAlignment = Alignment.Center) {
Column(
modifier = Modifier
.fillMaxSize()
.border(width = 1.dp, color = MaterialTheme.colors.onBackground)
.padding(10.dp), verticalArrangement = Arrangement.SpaceAround
) {
menuType.clazz.entries.chunked(2).forEach {
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceEvenly
) {
MenuItem(menuName = it[0].key, clazz = it[0].value)
if (it.size == 2) {
MenuItem(menuName = it[1].key, clazz = it[1].value)
} else {
Spacer(modifier = Modifier.size(100.dp))
}
}
}
}
}
}
}
}
@Composable
private fun MenuItem(menuName: String, clazz: Class<out Activity>) {
Card(
modifier = Modifier
.size(100.dp)
.clickable(onClick = {
startActivity(Intent(this, clazz))
}),
backgroundColor = MaterialTheme.colors.background
) {
Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
Text(text = menuName)
}
}
}
}

@ -17,4 +17,5 @@
<string name="duty">职务</string>
<string name="counselor">导员</string>
<string name="update_duty_error">只能调整干事职务!</string>
<string name="management_officer">部门干事管理</string>
</resources>

@ -17,4 +17,5 @@
<string name="duty">职务</string>
<string name="counselor">导员</string>
<string name="update_duty_error">只能调整干事职务!</string>
<string name="management_officer">部门干事管理</string>
</resources>

@ -17,4 +17,5 @@
<string name="duty">职务</string>
<string name="counselor">导员</string>
<string name="update_duty_error">只能调整干事职务!</string>
<string name="management_officer">部门干事管理</string>
</resources>

@ -16,20 +16,19 @@ import com.gyf.csams.account.ui.AccountRoute
import com.gyf.csams.util.AppDatabase
import com.gyf.csams.util.SimpleCallback
import com.gyf.csams.util.TokenResDto
import com.gyf.lib.uikit.ScaffoldModel
import com.gyf.lib.uikit.StringForm
import com.gyf.lib.util.ApiResponse
import com.gyf.lib.util.HttpClient
import com.orhanobut.logger.Logger
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
import kotlinx.serialization.Serializable
/**
* 响应自动生成密码
*
* @property password
*/
@Serializable
data class UserResDto(val password: String)
/**
@ -69,12 +68,16 @@ class AccountViewModel(application: Application) : AndroidViewModel(application)
val welcomeStart = "同学您好\n"
val welcomeEnd = "欢迎使用"
lateinit var scaffoldModel: ScaffoldModel
//学号
val studentId = object : StringForm(formDesc = "学号", textLength = 8) {
override fun onChange(value: String) {
super.onChange(value)
viewModelScope.launch {
checkRepeat()
checkRepeat {
scaffoldModel.update(message = it)
}
}
}
}
@ -128,12 +131,8 @@ class AccountViewModel(application: Application) : AndroidViewModel(application)
val isValidForm: LiveData<Boolean> = _isValidForm
//注册请求响应信息
private val _snackBarMsg = MutableLiveData<String>()
val snackBarMsg: LiveData<String> = _snackBarMsg
private val _dialogMsg = MutableLiveData<DialogMessage>()
val dialogMsg: LiveData<DialogMessage> = _dialogMsg
private val _dialogMsg = MutableLiveData<DialogMessage?>()
val dialogMsg: LiveData<DialogMessage?> = _dialogMsg
val loginDesc = "登陆"
@ -173,7 +172,7 @@ class AccountViewModel(application: Application) : AndroidViewModel(application)
* 检查学号是否已注册
*
*/
private suspend fun checkRepeat() {
private suspend fun checkRepeat(onFail: (error: String) -> Unit) {
if (checkStudentId()) {
if (checkJob?.isActive == true) {
checkJob?.join()
@ -189,7 +188,7 @@ class AccountViewModel(application: Application) : AndroidViewModel(application)
_isRepeat.postValue(it.body)
_isValidForm.postValue(_isValidName.value == true && it.body == false)
},
onFail = { _snackBarMsg.postValue(it) },
onFail = onFail,
type = object : TypeToken<ApiResponse<Boolean>>() {}.type
), mapOf("studentId" to "${studentId.formValue.value}")
)
@ -225,7 +224,7 @@ class AccountViewModel(application: Application) : AndroidViewModel(application)
_isValidForm.value = false
} else {
_isValidForm.value =
checkStudentId() && (if (route == AccountRoute.register) checkName() && isRepeat.value == false else checkPassword())
checkStudentId() && (if (route == AccountRoute.Register) checkName() && isRepeat.value == false else checkPassword())
}
return _isValidForm.value == true
}
@ -234,7 +233,7 @@ class AccountViewModel(application: Application) : AndroidViewModel(application)
* 注册
*
*/
fun register() {
fun register(onFail: (error: String) -> Unit) {
if (checkForm()) {
val url = Api.buildUrl(AccountApi.Register)
Logger.i("开始$regBtnDesc,请求接口:$url")
@ -249,7 +248,7 @@ class AccountViewModel(application: Application) : AndroidViewModel(application)
)
)
},
onFail = { _snackBarMsg.postValue(it) },
onFail = onFail,
type = object : TypeToken<ApiResponse<UserResDto>>() {}.type
),
jsonBody = Gson().toJson(
@ -265,18 +264,6 @@ class AccountViewModel(application: Application) : AndroidViewModel(application)
}
}
/**
*
*/
/**
* 重置信息
*
*/
fun resetRegisterResMsg() {
_snackBarMsg.value = ""
}
fun resetDialogMsg() {
_dialogMsg.value = null
}
@ -290,7 +277,7 @@ class AccountViewModel(application: Application) : AndroidViewModel(application)
* 登录
*
*/
fun login() {
fun login(callback: (message: String) -> Unit) {
if (checkForm()) {
val url = Api.buildUrl(AccountApi.Login)
Logger.i("开始$loginDesc,请求接口:$url")
@ -299,8 +286,7 @@ class AccountViewModel(application: Application) : AndroidViewModel(application)
SimpleCallback<Token>(
action = loginDesc,
onSuccess = {
_snackBarMsg.postValue(it.message)
callback(it.message)
val context = getApplication<Application>().applicationContext
val token = it.body?.token
if (token != null) {
@ -313,7 +299,7 @@ class AccountViewModel(application: Application) : AndroidViewModel(application)
}
}
},
onFail = { _snackBarMsg.postValue(it) },
onFail = { callback(it) },
type = object : TypeToken<ApiResponse<Token>>() {}.type
),
jsonBody = Gson().toJson(

@ -8,7 +8,6 @@ import androidx.compose.foundation.layout.*
import androidx.compose.foundation.text.KeyboardOptions
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
@ -29,12 +28,13 @@ import com.gyf.csams.account.model.DialogMessage
import com.gyf.csams.uikit.AnimationText
import com.gyf.lib.uikit.BaseTextField
import com.gyf.lib.uikit.Body
import com.gyf.lib.uikit.ScaffoldModel
import com.orhanobut.logger.Logger
enum class AccountRoute {
login,
register
Login,
Register
}
class AccountActivity : ComponentActivity() {
@ -42,22 +42,24 @@ class AccountActivity : ComponentActivity() {
super.onCreate(savedInstanceState)
setContent {
Body { nav, scaffoldState ->
NavHost(navController = nav, startDestination = AccountRoute.login.name) {
composable(AccountRoute.login.name) {
Body { nav ->
NavHost(navController = nav, startDestination = AccountRoute.Login.name) {
composable(AccountRoute.Login.name) {
Account(
scaffoldState = scaffoldState,
route = AccountRoute.login
) { isValidForm: Boolean, accountViewModel: AccountViewModel ->
route = AccountRoute.Login
) { isValidForm: Boolean, accountViewModel: AccountViewModel, scaffoldModel: ScaffoldModel ->
Spacer(modifier = Modifier.height(10.dp))
OutlinedButton(
onClick = { accountViewModel.login() },
enabled = isValidForm,
modifier = Modifier
.fillMaxWidth()
.padding(bottom = 10.dp)
) {
onClick = {
accountViewModel.login {
scaffoldModel.update(message = it)
}
},
enabled = isValidForm,
modifier = Modifier
.fillMaxWidth()
.padding(bottom = 10.dp)
) {
Text(text = accountViewModel.loginDesc)
}
@ -68,7 +70,7 @@ class AccountActivity : ComponentActivity() {
}
OutlinedButton(
onClick = { nav.navigate(AccountRoute.register.name) },
onClick = { nav.navigate(AccountRoute.Register.name) },
modifier = Modifier.fillMaxWidth(),
colors = ButtonDefaults.outlinedButtonColors(
contentColor = MaterialTheme.colors.onBackground
@ -80,25 +82,28 @@ class AccountActivity : ComponentActivity() {
}
composable(AccountRoute.register.name) {
Account(
scaffoldState = scaffoldState,
route = AccountRoute.register
) { isValidForm: Boolean, accountViewModel: AccountViewModel ->
Spacer(modifier = Modifier.height(10.dp))
composable(AccountRoute.Register.name) {
Account(
route = AccountRoute.Register
) { isValidForm: Boolean, accountViewModel: AccountViewModel, _: ScaffoldModel ->
Spacer(modifier = Modifier.height(10.dp))
OutlinedButton(
onClick = { accountViewModel.register() },
enabled = isValidForm,
modifier = Modifier
.fillMaxWidth()
.padding(bottom = 10.dp)
) {
OutlinedButton(
onClick = {
accountViewModel.register {
}
},
enabled = isValidForm,
modifier = Modifier
.fillMaxWidth()
.padding(bottom = 10.dp)
) {
Text(text = accountViewModel.regBtnDesc)
}
OutlinedButton(
onClick = { nav.navigate(AccountRoute.login.name) },
onClick = { nav.navigate(AccountRoute.Login.name) },
modifier = Modifier.fillMaxWidth(),
colors = ButtonDefaults.outlinedButtonColors(
contentColor = MaterialTheme.colors.onBackground
@ -122,10 +127,11 @@ class AccountActivity : ComponentActivity() {
@Composable
private fun Account(
accountViewModel: AccountViewModel = viewModel(),
scaffoldState: ScaffoldState,
scaffoldModel: ScaffoldModel = viewModel(),
route: AccountRoute,
Action: @Composable (isValidForm: Boolean, accountViewModel: AccountViewModel) -> Unit
Action: @Composable (isValidForm: Boolean, accountViewModel: AccountViewModel, scaffoldModel: ScaffoldModel) -> Unit
) {
accountViewModel.scaffoldModel = scaffoldModel
accountViewModel.route = route
Row(
horizontalArrangement = Arrangement.Center,
@ -154,28 +160,20 @@ class AccountActivity : ComponentActivity() {
}
})
StudentId(checkRepeat = route == AccountRoute.register)
StudentId(checkRepeat = route == AccountRoute.Register)
Spacer(modifier = Modifier.height(10.dp))
if (route == AccountRoute.register) Name() else Password()
if (route == AccountRoute.Register) Name() else Password()
Spacer(modifier = Modifier.height(10.dp))
PasswordTip()
val isValidForm: Boolean by accountViewModel.isValidForm.observeAsState(false)
Action(isValidForm = isValidForm, accountViewModel = accountViewModel)
val snackBarMsg: String by accountViewModel.snackBarMsg.observeAsState("")
if (snackBarMsg != "") {
LaunchedEffect(scaffoldState) {
scaffoldState.snackbarHostState.showSnackbar(
message = snackBarMsg
)
accountViewModel.resetRegisterResMsg()
}
}
Action(
isValidForm = isValidForm,
accountViewModel = accountViewModel,
scaffoldModel = scaffoldModel
)
RegisterDialog()
}
}

@ -6,9 +6,9 @@ import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.gyf.csams.NOT_IMPL_TIP
import com.gyf.csams.uikit.ActivityDetailMenu
import com.gyf.csams.uikit.ScrollList
import com.gyf.csams.uikit.SendInterface
import com.gyf.csams.uikit.TopMenuInterface
import com.gyf.lib.ScrollList
import com.gyf.lib.uikit.StringForm
import com.gyf.lib.util.randomChinese
import com.gyf.lib.util.randomDateTime

@ -26,7 +26,6 @@ import com.gyf.csams.uikit.*
import com.gyf.lib.uikit.Body
import com.gyf.lib.uikit.MainColumnFrame
import com.gyf.lib.uikit.ScaffoldModel
import com.gyf.lib.uikit.ShowSnackbar
import com.gyf.lib.util.format
import com.orhanobut.logger.Logger
@ -42,7 +41,7 @@ class ActivityDetailActivity : ComponentActivity() {
setContent {
Body { nav, scaffoldState ->
Body { nav ->
val model: ActivityDetailViewModel = viewModel()
val currentMenuName by model.currentMenu.observeAsState(ActivityDetailMenu.startMenu)
Column {
@ -57,22 +56,18 @@ class ActivityDetailActivity : ComponentActivity() {
) {
composable(ActivityDetailMenu.Info.name) {
Info()
ShowSnackbar(scaffoldState = scaffoldState)
model.clickMenu(ActivityDetailMenu.Info)
}
composable(ActivityDetailMenu.Photo.name) {
Photo()
ShowSnackbar(scaffoldState = scaffoldState)
model.clickMenu(ActivityDetailMenu.Photo)
}
composable(ActivityDetailMenu.Member.name) {
Member()
ShowSnackbar(scaffoldState = scaffoldState)
model.clickMenu(ActivityDetailMenu.Member)
}
composable(ActivityDetailMenu.BBS.name) {
BBS()
ShowSnackbar(scaffoldState = scaffoldState)
model.clickMenu(ActivityDetailMenu.BBS)
}
}

@ -77,7 +77,7 @@ class ApplyActActivity : AppCompatActivity() {
mLocationClient = (application as MainApplication).mLocationClient
setContent {
Body { scaffoldState ->
BodyS {
MainColumnFrame(background = { Background(image = BackgroundImage.ApplyActivity) }) {
val model: ApplyActViewModel = viewModel()
val scaffoldModel: ScaffoldModel = viewModel()
@ -182,7 +182,6 @@ class ApplyActActivity : AppCompatActivity() {
}
}
}
ShowSnackbar(scaffoldState = scaffoldState)
}
}
}

@ -6,8 +6,8 @@ import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.gyf.csams.NOT_IMPL_TIP
import com.gyf.csams.uikit.AssociationMenu
import com.gyf.csams.uikit.ScrollList
import com.gyf.csams.uikit.TopMenuInterface
import com.gyf.lib.ScrollList
import com.gyf.lib.uikit.StringForm
import com.orhanobut.logger.Logger
import kotlinx.coroutines.launch

@ -4,7 +4,7 @@ import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.viewModelScope
import com.gyf.csams.NOT_IMPL_TIP
import com.gyf.csams.uikit.ScrollList
import com.gyf.lib.ScrollList
import com.gyf.lib.uikit.StringForm
import kotlinx.coroutines.launch
import kotlin.random.Random

@ -30,7 +30,10 @@ import com.gyf.csams.activity.ui.ActivityDetailActivity
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.uikit.BaseTextField
import com.gyf.lib.uikit.Body
import com.gyf.lib.uikit.MainColumnFrame
import com.gyf.lib.uikit.ScaffoldModel
import com.gyf.lib.util.randomChinese
import com.orhanobut.logger.Logger
@ -44,17 +47,17 @@ class AssociationActivity : ComponentActivity() {
super.onCreate(savedInstanceState)
setContent {
Body { nav, scaffoldState ->
val context = LocalContext.current as AssociationActivity
val model: AssociationViewModel = viewModel()
val currentMenuName: AssociationMenu by model.currentMenu.observeAsState(
AssociationMenu.startMenu
)
val intent = Intent(context, ExamActivity::class.java)
val expanded by model.expanded.observeAsState(false)
Body { nav ->
val context = LocalContext.current as AssociationActivity
val model: AssociationViewModel = viewModel()
val currentMenuName: AssociationMenu by model.currentMenu.observeAsState(
AssociationMenu.startMenu
)
val intent = Intent(context, ExamActivity::class.java)
val expanded by model.expanded.observeAsState(false)
Column {
Logger.i("expanded=$expanded")
Column {
Logger.i("expanded=$expanded")
TextTopAppBar(nav = nav,
currentMenuName = currentMenuName.menuName,
menuNames = AssociationMenu.values(),
@ -154,17 +157,14 @@ class AssociationActivity : ComponentActivity() {
composable(AssociationMenu.Member.name) {
model.clickMenu(AssociationMenu.Member)
Member()
ShowSnackbar(scaffoldState = scaffoldState)
}
composable(AssociationMenu.Main.name) {
model.clickMenu(AssociationMenu.Main)
Main()
ShowSnackbar(scaffoldState = scaffoldState)
}
composable(AssociationMenu.ActivityList.name) {
model.clickMenu(AssociationMenu.ActivityList)
AssociationList()
ShowSnackbar(scaffoldState = scaffoldState)
}
}
}

@ -22,7 +22,10 @@ import com.gyf.csams.R
import com.gyf.csams.association.model.*
import com.gyf.csams.uikit.Background
import com.gyf.csams.uikit.BackgroundImage
import com.gyf.lib.uikit.*
import com.gyf.lib.uikit.BaseTextField
import com.gyf.lib.uikit.BodyS
import com.gyf.lib.uikit.MainColumnFrame
import com.gyf.lib.uikit.ScaffoldModel
import com.gyf.lib.util.BottomButton
@ -40,7 +43,7 @@ class ExamActivity : ComponentActivity() {
activityType = intent?.getSerializableExtra(ExamActivityType::name.name) as ExamActivityType
setContent {
Body { scaffoldState ->
BodyS {
MainColumnFrame(background = {
Background(
image = BackgroundImage.Exam,
@ -50,7 +53,6 @@ class ExamActivity : ComponentActivity() {
Spacer(modifier = Modifier.weight(0.1F))
Title(modifier = Modifier.weight(0.1F))
Exam(modifier = Modifier.weight(0.8F))
ShowSnackbar(scaffoldState = scaffoldState)
}
}
}

@ -13,7 +13,10 @@ import androidx.lifecycle.viewmodel.compose.viewModel
import com.gyf.csams.association.model.RenameViewModel
import com.gyf.csams.uikit.Background
import com.gyf.csams.uikit.BackgroundImage
import com.gyf.lib.uikit.*
import com.gyf.lib.uikit.BaseTextField
import com.gyf.lib.uikit.BodyS
import com.gyf.lib.uikit.MainColumnFrame
import com.gyf.lib.uikit.ScaffoldModel
import com.gyf.lib.util.BottomButton
/**
@ -25,7 +28,7 @@ class ReNameActivity : ComponentActivity() {
super.onCreate(savedInstanceState)
setContent {
Body { scaffoldState ->
BodyS {
MainColumnFrame(background = { Background(image = BackgroundImage.Rename) }) {
Spacer(
modifier = Modifier
@ -51,7 +54,6 @@ class ReNameActivity : ComponentActivity() {
}
Spacer(modifier = Modifier.weight(1 - 0.2F * 2 - 0.1F * 4))
ShowSnackbar(scaffoldState = scaffoldState)
}
}
}

@ -33,7 +33,10 @@ import com.gyf.csams.R
import com.gyf.csams.association.model.RegAssociationViewModel
import com.gyf.csams.uikit.Background
import com.gyf.csams.uikit.BackgroundImage
import com.gyf.lib.uikit.*
import com.gyf.lib.uikit.BaseTextField
import com.gyf.lib.uikit.BodyS
import com.gyf.lib.uikit.MainColumnFrame
import com.gyf.lib.uikit.ScaffoldModel
import com.gyf.lib.util.BottomButton
import com.orhanobut.logger.Logger
@ -47,17 +50,17 @@ class RegAssociationActivity : ComponentActivity() {
super.onCreate(savedInstanceState)
setContent {
Body { scaffoldState ->
MainColumnFrame(background = {
Background(
BackgroundImage.RegAssociation,
alpha = 0.5F
)
}) {
Spacer(
modifier = Modifier
.weight(0.1F)
)
BodyS {
MainColumnFrame(background = {
Background(
BackgroundImage.RegAssociation,
alpha = 0.5F
)
}) {
Spacer(
modifier = Modifier
.weight(0.1F)
)
Title()
Name()
Desc(
@ -82,8 +85,6 @@ class RegAssociationActivity : ComponentActivity() {
model.register { scaffoldModel.update(message = it) }
}
Spacer(modifier = Modifier.weight(0.05F))
ShowSnackbar(scaffoldState = scaffoldState)
}
}

@ -5,8 +5,8 @@ import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.gyf.csams.NOT_IMPL_TIP
import com.gyf.csams.uikit.ScrollList
import com.gyf.csams.uikit.SendInterface
import com.gyf.lib.ScrollList
import com.gyf.lib.uikit.PersonInfoVo
import com.gyf.lib.uikit.StringForm
import com.gyf.lib.util.randomChinese
@ -48,7 +48,7 @@ class MarqueeViewModel : ViewModel() {
*
* @property name 社团名称
*/
data class AssociationDto(val name: String)
data class AssociationListVo(val name: String)
/**
* 主页
@ -83,7 +83,7 @@ class MainViewModel : ViewModel(), SendInterface {
* 社团列表
*
*/
class ListViewModel : ScrollList<AssociationDto>() {
class ListViewModel : ScrollList<AssociationListVo>() {
val name = StringForm(formDesc = "社团名称", textLength = 5)
val desc = StringForm(formDesc = "社团简介", textLength = 10)
@ -92,8 +92,8 @@ class ListViewModel : ScrollList<AssociationDto>() {
val associationListSize = 10
//社团列表
private val _associationList = MutableLiveData<MutableList<AssociationDto>>(mutableListOf())
val associationDto: LiveData<MutableList<AssociationDto>> = _associationList
private val _associationList = MutableLiveData<MutableList<AssociationListVo>>(mutableListOf())
val associationListVo: LiveData<MutableList<AssociationListVo>> = _associationList
val searchDesc = "搜索"
@ -125,7 +125,7 @@ class ListViewModel : ScrollList<AssociationDto>() {
repeat(
10
) {
add(AssociationDto(name = "社团${_associationList.value?.size}"))
add(AssociationListVo(name = "社团${_associationList.value?.size}"))
}
}
@ -140,11 +140,11 @@ class ListViewModel : ScrollList<AssociationDto>() {
override fun loadMore(callback: (message: String) -> Unit) {
viewModelScope.launch {
_associationList.value?.apply {
val list = mutableListOf<AssociationDto>()
val list = mutableListOf<AssociationListVo>()
list.addAll(this)
list.apply {
repeat(10) {
add(AssociationDto(name = "社团${size}"))
add(AssociationListVo(name = "社团${size}"))
}
}
Logger.i("t.size=${size}")

@ -52,19 +52,16 @@ class MainActivity : ComponentActivity() {
setContent {
Body { nav, scaffoldState ->
Body { nav ->
NavHost(navController = nav, startDestination = MainMenu.Main.name) {
composable(MainMenu.Main.name) {
Main(navController = nav)
ShowSnackbar(scaffoldState = scaffoldState)
}
composable(MainMenu.List.name) {
AssociationList(navController = nav)
ShowSnackbar(scaffoldState = scaffoldState)
}
composable(MainMenu.Center.name) {
Center(navController = nav)
ShowSnackbar(scaffoldState = scaffoldState)
}
}
@ -236,21 +233,21 @@ class MainActivity : ComponentActivity() {
model: ListViewModel = viewModel(),
scaffoldModel: ScaffoldModel = viewModel()
) {
val associationList: MutableList<AssociationDto>? by model.associationDto.observeAsState()
val associationListList: MutableList<AssociationListVo>? by model.associationListVo.observeAsState()
val listState = rememberLazyListState()
LazyColumn(state = listState) {
associationList?.chunked(2)?.forEach {
associationListList?.chunked(2)?.forEach {
item {
Row {
Spacer(modifier = Modifier.weight(0.1F))
Box(modifier = Modifier.weight(0.35F)) {
Association(associationDto = it[0])
Association(associationListVo = it[0])
}
Spacer(modifier = Modifier.weight(0.05F))
if (it.size == 2) {
Box(modifier = Modifier.weight(0.35F)) {
Association(associationDto = it[1])
Association(associationListVo = it[1])
}
} else {
Box(
@ -276,7 +273,7 @@ class MainActivity : ComponentActivity() {
}
@Composable
private fun Association(associationDto: AssociationDto) {
private fun Association(associationListVo: AssociationListVo) {
val context = LocalContext.current
Card(modifier = Modifier.clickable(onClick = {
context.startActivity(
@ -294,7 +291,7 @@ class MainActivity : ComponentActivity() {
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.Center
) {
Text(text = associationDto.name)
Text(text = associationListVo.name)
}
}

@ -2,7 +2,7 @@ package com.gyf.csams.message.model
import androidx.lifecycle.viewModelScope
import com.gyf.csams.NOT_IMPL_TIP
import com.gyf.csams.uikit.ScrollList
import com.gyf.lib.ScrollList
import com.gyf.lib.util.randomChinese
import com.gyf.lib.util.randomDateTime
import com.gyf.lib.util.randomNum

@ -22,7 +22,7 @@ import com.gyf.csams.message.model.MessageViewModel
import com.gyf.csams.uikit.Background
import com.gyf.csams.uikit.BackgroundImage
import com.gyf.csams.uikit.TextTopAppBar
import com.gyf.lib.uikit.Body
import com.gyf.lib.uikit.BodyS
import com.gyf.lib.uikit.MainColumnFrame
/**
@ -34,7 +34,7 @@ class MessageActivity : ComponentActivity() {
super.onCreate(savedInstanceState)
setContent {
Body { _ ->
BodyS {
val model: MessageViewModel = viewModel()
val context = LocalContext.current
MainColumnFrame(background = {

@ -22,7 +22,7 @@ import com.gyf.csams.message.model.*
import com.gyf.csams.uikit.Background
import com.gyf.csams.uikit.BackgroundImage
import com.gyf.csams.uikit.TextTopAppBar
import com.gyf.lib.uikit.Body
import com.gyf.lib.uikit.BodyS
import com.gyf.lib.uikit.MainColumnFrame
import com.gyf.lib.util.format
@ -35,7 +35,7 @@ class SysMessageActivity : ComponentActivity() {
super.onCreate(savedInstanceState)
setContent {
Body { _ ->
BodyS {
MainColumnFrame(background = {
Background(
image = BackgroundImage.ActivityMessage,

@ -2,7 +2,10 @@ package com.gyf.csams.uikit
import android.app.Application
import androidx.compose.ui.graphics.ImageBitmap
import androidx.lifecycle.*
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.viewModelScope
import com.google.gson.reflect.TypeToken
import com.gyf.csams.R
import com.gyf.csams.util.SimpleCallback
@ -90,18 +93,5 @@ class ImageModel(application: Application, private val urlPath: String) :
}
}
abstract class ScrollList<T> : ViewModel() {
protected val _data = MutableLiveData<MutableList<T>>(mutableListOf())
val data: LiveData<MutableList<T>> = _data
abstract val initSize: Int
//加载列表
abstract fun load()
//加载更多数据
abstract fun loadMore(callback: (message: String) -> Unit)
}

@ -0,0 +1,18 @@
package com.gyf.lib
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
abstract class ScrollList<T> : ViewModel() {
protected val _data = MutableLiveData<MutableList<T>>(mutableListOf())
val data: LiveData<MutableList<T>> = _data
abstract val initSize: Int
//加载列表
abstract fun load()
//加载更多数据
abstract fun loadMore(callback: (message: String) -> Unit)
}

@ -140,39 +140,40 @@ fun <T : BottomBarMenu> MainBottomAppBar(
}
/**
*
*
* @param content
*/
@Composable
fun Body(content: @Composable (scaffoldState: ScaffoldState) -> Unit) {
fun BodyS(content: @Composable () -> Unit) {
CSAMSTheme {
Surface(color = MaterialTheme.colors.background) {
val scaffoldState = rememberScaffoldState()
Scaffold(scaffoldState = scaffoldState) {
content(scaffoldState = scaffoldState)
content()
ShowSnackbar(scaffoldState = scaffoldState)
}
}
}
}
/**
* 导航的主体
* 底部导航的界面框架
*
* @param content
*/
@Composable
fun Body(content: @Composable (nav: NavHostController, scaffoldState: ScaffoldState) -> Unit) {
fun Body(content: @Composable (nav: NavHostController) -> Unit) {
CSAMSTheme {
Surface(color = MaterialTheme.colors.background) {
val navController = rememberNavController()
val scaffoldState = rememberScaffoldState()
Scaffold(scaffoldState = scaffoldState) {
content(nav = navController, scaffoldState = scaffoldState)
content(nav = navController)
ShowSnackbar(scaffoldState = scaffoldState)
}
}
}

@ -13,6 +13,7 @@ import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import com.gyf.lib.R
@ -29,13 +30,13 @@ fun BottomButton(
onClick = onConfirm,
modifier = Modifier.background(color = MaterialTheme.colors.primary)
) {
Text(text = context.getString(confirmDesc))
Text(text = stringResource(id = confirmDesc))
}
Spacer(modifier = Modifier.width(10.dp))
OutlinedButton(onClick = {
context.onBackPressed()
}, modifier = Modifier.background(color = MaterialTheme.colors.secondary)) {
Text(text = context.getString(backDesc))
Text(text = stringResource(id = backDesc))
}
}
}
Loading…
Cancel
Save