diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index a16986a..629b084 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -49,24 +49,34 @@ - - + - - + - - + - - + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/gyf/csams/APP.kt b/app/src/main/java/com/gyf/csams/APP.kt index f197a56..fa4ce4e 100644 --- a/app/src/main/java/com/gyf/csams/APP.kt +++ b/app/src/main/java/com/gyf/csams/APP.kt @@ -15,24 +15,30 @@ import com.orhanobut.logger.Logger class APP : Application() { - private lateinit var memoryCache: LruCache + // Get max available VM memory, exceeding this amount will throw an // OutOfMemory exception. Stored in kilobytes as LruCache takes an // int in its constructor. private val maxMemory = (Runtime.getRuntime().maxMemory() / 1024).toInt() + // Use 1/8th of the available memory for this memory cache. val cacheSize = maxMemory / 8 fun getImage(image: BackgroundImage, reqWidth: Int, reqHeight: Int): ImageBitmap { - val bitmap=memoryCache.get(image) - return if(bitmap==null){ + val bitmap = memoryCache.get(image) + return if (bitmap == null) { Logger.i("reqWidth=$reqWidth,reqHeight=$reqHeight") - val cacheValue= decodeSampledBitmapFromResource(res = resources,image.id,reqWidth=reqWidth,reqHeight=reqHeight) + val cacheValue = decodeSampledBitmapFromResource( + res = resources, + image.id, + reqWidth = reqWidth, + reqHeight = reqHeight + ) memoryCache.put(image, cacheValue) Logger.i("添加缓存:${image}") cacheValue.asImageBitmap() - }else{ + } else { Logger.i("从缓存读取:${image}") bitmap.asImageBitmap() } @@ -59,7 +65,11 @@ class APP : Application() { } } - private fun calculateInSampleSize(options: BitmapFactory.Options, reqWidth: Int, reqHeight: Int): Int { + private fun calculateInSampleSize( + options: BitmapFactory.Options, + reqWidth: Int, + reqHeight: Int + ): Int { // Raw height and width of image val (height: Int, width: Int) = options.run { outHeight to outWidth } var inSampleSize = 1 diff --git a/app/src/main/java/com/gyf/csams/Api.kt b/app/src/main/java/com/gyf/csams/Api.kt index b696784..59a431e 100644 --- a/app/src/main/java/com/gyf/csams/Api.kt +++ b/app/src/main/java/com/gyf/csams/Api.kt @@ -1,8 +1,8 @@ package com.gyf.csams -interface UrlPath{ - fun build():String +interface UrlPath { + fun build(): String } /** @@ -10,7 +10,7 @@ interface UrlPath{ * * @property path */ -enum class AccountApi(val path: String):UrlPath{ +enum class AccountApi(val path: String) : UrlPath { register("/register"), checkId("/register/checkId"), login("/login"), @@ -27,13 +27,13 @@ enum class AccountApi(val path: String):UrlPath{ * */ class Api { - companion object{ - fun buildUrl(urlPath: UrlPath):String{ + companion object { + fun buildUrl(urlPath: UrlPath): String { return "${BuildConfig.SERVER_ADDRESS}${urlPath.build()}" } } } -const val NOT_IMPL_TIP="功能尚未实现!" +const val NOT_IMPL_TIP = "功能尚未实现!" diff --git a/app/src/main/java/com/gyf/csams/InitActivity.kt b/app/src/main/java/com/gyf/csams/InitActivity.kt index f5948d4..890ced6 100644 --- a/app/src/main/java/com/gyf/csams/InitActivity.kt +++ b/app/src/main/java/com/gyf/csams/InitActivity.kt @@ -22,16 +22,16 @@ class InitActivity : ComponentActivity() { // 检查网络 setContent { - val initViewModel:InitViewModel= viewModel() + val initViewModel: InitViewModel = viewModel() initViewModel.checkServer() - val isNetWorkWorking:Boolean? by initViewModel.isNetWorkWorking.observeAsState(null) - when(isNetWorkWorking){ - null-> AnimationText(text = "检查服务器网络状态中!!!") - true-> { + val isNetWorkWorking: Boolean? by initViewModel.isNetWorkWorking.observeAsState(null) + when (isNetWorkWorking) { + null -> AnimationText(text = "检查服务器网络状态中!!!") + true -> { Init() finish() } - false->{ + false -> { TODO("无法连接到服务器,请检查本地网络或联系管理员") } } @@ -40,16 +40,16 @@ class InitActivity : ComponentActivity() { @Composable - private fun Init(initViewModel:InitViewModel= viewModel()){ + private fun Init(initViewModel: InitViewModel = viewModel()) { Logger.i("初始化。。。。") - val context= LocalContext.current + val context = LocalContext.current //后台检查token initViewModel.hasOnlyUserToken(context) //监听token校验状态 val isValid: Boolean? by initViewModel.token.observeAsState(null) when (isValid) { - false -> context.startActivity(Intent(context, AccountActivity::class.java)) + false -> context.startActivity(Intent(context, AccountActivity::class.java)) true -> context.startActivity(Intent(context, MainActivity::class.java)) } diff --git a/app/src/main/java/com/gyf/csams/InitViewModel.kt b/app/src/main/java/com/gyf/csams/InitViewModel.kt index a0ac3f7..37992ca 100644 --- a/app/src/main/java/com/gyf/csams/InitViewModel.kt +++ b/app/src/main/java/com/gyf/csams/InitViewModel.kt @@ -11,9 +11,9 @@ import com.gyf.csams.util.* import com.orhanobut.logger.Logger import kotlinx.coroutines.launch -data class TokenVo(val token:String,val studentId:String) +data class TokenVo(val token: String, val studentId: String) -class InitViewModel: ViewModel() { +class InitViewModel : ViewModel() { /** * 服务器网络状态是否正常,true=正常,false=不正常 */ @@ -27,7 +27,7 @@ class InitViewModel: ViewModel() { val token: LiveData = _token - fun checkServer(){ + fun checkServer() { Logger.i("测试连接到服务端") _isNetWorkWorking.postValue(true) } @@ -35,29 +35,38 @@ class InitViewModel: ViewModel() { /** * 查询本地是否有且只有一个用户token,如果有则自动登录 */ - fun hasOnlyUserToken(context: Context){ - viewModelScope.launch{ - val db=AppDatabase.getInstance(context) - val tokenList=db?.tokenDao()?.queryAll() + fun hasOnlyUserToken(context: Context) { + viewModelScope.launch { + val db = AppDatabase.getInstance(context) + val tokenList = db?.tokenDao()?.queryAll() if (tokenList != null && tokenList.size == 1) { val currentToken: Token = tokenList[0] - val url=Api.buildUrl(AccountApi.loginToken) - val action="校验token" + val url = Api.buildUrl(AccountApi.loginToken) + val action = "校验token" Logger.i("${action}api=$url") - HttpClient.post(url,SimpleCallback( - action=action, - onSuccess = { - _token.postValue(it.body) - Logger.i("token校验结果:${it.body}") - }, - onFail = { TODO("token校验失败")}, - type = object : TypeToken>(){}.type - ),jsonBody = Gson().toJson(TokenVo(token=currentToken.token,studentId = currentToken.studentId))) - }else if(tokenList != null && tokenList.size > 1){ + HttpClient.post( + url, + SimpleCallback( + action = action, + onSuccess = { + _token.postValue(it.body) + Logger.i("token校验结果:${it.body}") + }, + onFail = { TODO("token校验失败") }, + type = object : TypeToken>() {}.type + ), + jsonBody = Gson().toJson( + TokenVo( + token = currentToken.token, + studentId = currentToken.studentId + ) + ) + ) + } else if (tokenList != null && tokenList.size > 1) { //TODO 实现切换历史登录帐号 Logger.i("token数量大于一,需要手动登录") _token.postValue(false) - }else{ + } else { Logger.i("本地没有任何token,跳转到登录界面") _token.postValue(false) } diff --git a/app/src/main/java/com/gyf/csams/account/model/AccountViewModel.kt b/app/src/main/java/com/gyf/csams/account/model/AccountViewModel.kt index c7a123c..fc233d6 100644 --- a/app/src/main/java/com/gyf/csams/account/model/AccountViewModel.kt +++ b/app/src/main/java/com/gyf/csams/account/model/AccountViewModel.kt @@ -25,7 +25,7 @@ import kotlinx.serialization.Serializable * @property password */ @Serializable -data class UserResDto(val password:String) +data class UserResDto(val password: String) /** * 构造登录、注册信息实体表单 @@ -33,7 +33,7 @@ data class UserResDto(val password:String) * @property studentId 学号 * @property name 姓名 */ -data class UserVo(val studentId:String,val name:String) +data class UserVo(val studentId: String, val name: String) /** * 用户登陆表单 @@ -42,7 +42,7 @@ data class UserVo(val studentId:String,val name:String) * @property password 密码 * @property device 设备型号 */ -data class UserLoginVo(val studentId: String,val password: String,val device: String) +data class UserLoginVo(val studentId: String, val password: String, val device: String) /** * 密码弹窗信息 @@ -50,9 +50,9 @@ data class UserLoginVo(val studentId: String,val password: String,val device: St * @property message * @property userResDto */ -data class DialogMessage(val message:String,val userResDto: UserResDto?) +data class DialogMessage(val message: String, val userResDto: UserResDto?) -typealias Token= TokenResDto +typealias Token = TokenResDto /** * 注册表单 @@ -61,90 +61,97 @@ class AccountViewModel(application: Application) : AndroidViewModel(application) //欢迎信息 - val welcomeStart="同学您好\n" - val welcomeEnd="欢迎使用" + val welcomeStart = "同学您好\n" + val welcomeEnd = "欢迎使用" //学号 - private val _studentId=MutableLiveData() - val studentId:LiveData = _studentId - private val _isValidStudentId=MutableLiveData() - val isValidStudentId:LiveData = _isValidStudentId - val studentIdDesc="学号" - val studentIdPlaceholder="请输入$studentIdDesc" - val studentIdFormat="入学年份(四位)+班级代码(两位)+学生代码(两位)" + private val _studentId = MutableLiveData() + val studentId: LiveData = _studentId + private val _isValidStudentId = MutableLiveData() + val isValidStudentId: LiveData = _isValidStudentId + val studentIdDesc = "学号" + val studentIdPlaceholder = "请输入$studentIdDesc" + val studentIdFormat = "入学年份(四位)+班级代码(两位)+学生代码(两位)" //学号已存在 - private val _isRepeat=MutableLiveData() + private val _isRepeat = MutableLiveData() - val regBtnDesc="注册" + val regBtnDesc = "注册" //已注册 - val registered="已$regBtnDesc" + val registered = "已$regBtnDesc" + //可注册 - val canRegister="可$regBtnDesc" + val canRegister = "可$regBtnDesc" + //提示信息 - val checkRegTip="检测学号是否已${regBtnDesc}。。。" - val isRepeat:LiveData = _isRepeat + val checkRegTip = "检测学号是否已${regBtnDesc}。。。" + val isRepeat: LiveData = _isRepeat private var checkJob: Job? = null + //姓名 - private val _name=MutableLiveData() - val name:LiveData = _name - val nameDesc="姓名" - val namePlaceholder="请输入$nameDesc" - private val _isValidName=MutableLiveData() - val isValidName:LiveData = _isValidName - val nameFormat="姓名不能为空" + private val _name = MutableLiveData() + val name: LiveData = _name + val nameDesc = "姓名" + val namePlaceholder = "请输入$nameDesc" + private val _isValidName = MutableLiveData() + val isValidName: LiveData = _isValidName + val nameFormat = "姓名不能为空" + //密码 - private val _password=MutableLiveData() - val password:LiveData = _password - val passwordDesc="密码" - val passwordPlaceholder="请输入$passwordDesc" - private val _isValidPwd=MutableLiveData() - val isValidPwd:LiveData = _isValidPwd - val passwordFormat="八位纯数字" + private val _password = MutableLiveData() + val password: LiveData = _password + val passwordDesc = "密码" + val passwordPlaceholder = "请输入$passwordDesc" + private val _isValidPwd = MutableLiveData() + val isValidPwd: LiveData = _isValidPwd + val passwordFormat = "八位纯数字" //注册按钮 - private val _isValidForm=MutableLiveData() + private val _isValidForm = MutableLiveData() + + val isValidForm: LiveData = _isValidForm - val isValidForm:LiveData = _isValidForm //注册请求响应信息 - private val _snackBarMsg=MutableLiveData() - val snackBarMsg:LiveData = _snackBarMsg + private val _snackBarMsg = MutableLiveData() + val snackBarMsg: LiveData = _snackBarMsg - private val _dialogMsg=MutableLiveData() - val dialogMsg:LiveData = _dialogMsg + private val _dialogMsg = MutableLiveData() + val dialogMsg: LiveData = _dialogMsg - val loginDesc="登陆" + val loginDesc = "登陆" //返回登陆 - val backLogin="返回$loginDesc" + val backLogin = "返回$loginDesc" + //确定按钮 - val confirmDesc="确定" + val confirmDesc = "确定" + //显示密码提示 - val title="提示信息" - val passwordTip="密码会在点击${regBtnDesc}以后,在后台自动生成,请留意系统提示。" - val passwordDialogStart="${regBtnDesc}成功,后台为您自动生成的密码是" - val passwordDialogEnd="\n密码有且只有这里显示一次,请在记住密码后点击确定或${backLogin}。" + val title = "提示信息" + val passwordTip = "密码会在点击${regBtnDesc}以后,在后台自动生成,请留意系统提示。" + val passwordDialogStart = "${regBtnDesc}成功,后台为您自动生成的密码是" + val passwordDialogEnd = "\n密码有且只有这里显示一次,请在记住密码后点击确定或${backLogin}。" //转到注册 - var goRegister="转到$regBtnDesc" + var goRegister = "转到$regBtnDesc" /** * 完成登录状态 */ - private val _finishLogin=MutableLiveData() - val finishLogin:LiveData = _finishLogin + private val _finishLogin = MutableLiveData() + val finishLogin: LiveData = _finishLogin - lateinit var route:AccountRoute + lateinit var route: AccountRoute /** * 更新学号 * * @param studentId 学号 */ - fun onStudentIdChange(studentId:String){ - _studentId.value=studentId + fun onStudentIdChange(studentId: String) { + _studentId.value = studentId viewModelScope.launch { checkRepeat() @@ -158,35 +165,37 @@ class AccountViewModel(application: Application) : AndroidViewModel(application) */ private fun checkStudentId(): Boolean { - _isValidStudentId.value= _studentId.value?.matches(Regex("\\d{8}")) - return _isValidStudentId.value==true + _isValidStudentId.value = _studentId.value?.matches(Regex("\\d{8}")) + return _isValidStudentId.value == true } /** * 检查学号是否已注册 * */ - private suspend fun checkRepeat(){ + private suspend fun checkRepeat() { if (checkStudentId()) { if (checkJob?.isActive == true) { checkJob?.join() - }else { + } else { _isRepeat.postValue(null) checkJob = viewModelScope.launch { - val url = Api.buildUrl(AccountApi.checkId) - Logger.i("检测$studentIdDesc,请求接口$url") - HttpClient.get( - url, SimpleCallback( - action = "${studentIdDesc}重复检测", - onSuccess = { _isRepeat.postValue(it.body) - _isValidForm.postValue( _isValidName.value==true && it.body==false) - }, - onFail = { _snackBarMsg.postValue(it) }, - type = object : TypeToken>() {}.type) - , mapOf("studentId" to "${_studentId.value}")) + val url = Api.buildUrl(AccountApi.checkId) + Logger.i("检测$studentIdDesc,请求接口$url") + HttpClient.get( + url, SimpleCallback( + action = "${studentIdDesc}重复检测", + onSuccess = { + _isRepeat.postValue(it.body) + _isValidForm.postValue(_isValidName.value == true && it.body == false) + }, + onFail = { _snackBarMsg.postValue(it) }, + type = object : TypeToken>() {}.type + ), mapOf("studentId" to "${_studentId.value}") + ) } } - }else{ + } else { _isValidForm.postValue(false) } } @@ -197,8 +206,8 @@ class AccountViewModel(application: Application) : AndroidViewModel(application) * * @param name 姓名 */ - fun onNameChange(name:String){ - _name.value=name + fun onNameChange(name: String) { + _name.value = name checkForm() } @@ -207,9 +216,9 @@ class AccountViewModel(application: Application) : AndroidViewModel(application) * * @return */ - private fun checkName():Boolean{ - _isValidName.value= _name.value?.isNotEmpty() - return _isValidName.value==true + private fun checkName(): Boolean { + _isValidName.value = _name.value?.isNotEmpty() + return _isValidName.value == true } /** @@ -217,8 +226,8 @@ class AccountViewModel(application: Application) : AndroidViewModel(application) * * @param password 密码 */ - fun onPasswordChange(password: String){ - _password.value=password + fun onPasswordChange(password: String) { + _password.value = password checkForm() } @@ -227,16 +236,17 @@ class AccountViewModel(application: Application) : AndroidViewModel(application) * * @return */ - private fun checkPassword():Boolean{ - _isValidPwd.value= _password.value?.matches(Regex("\\d{8}")) - return _isValidPwd.value==true + private fun checkPassword(): Boolean { + _isValidPwd.value = _password.value?.matches(Regex("\\d{8}")) + return _isValidPwd.value == true } private fun checkForm(): Boolean { - if(checkJob?.isActive==true){ + if (checkJob?.isActive == true) { _isValidForm.value = false - }else{ - _isValidForm.value = checkStudentId() && (if (route==AccountRoute.register) checkName()&&isRepeat.value==false else checkPassword()) + } else { + _isValidForm.value = + checkStudentId() && (if (route == AccountRoute.register) checkName() && isRepeat.value == false else checkPassword()) } return _isValidForm.value == true } @@ -245,18 +255,33 @@ class AccountViewModel(application: Application) : AndroidViewModel(application) * 注册 * */ - fun register(){ - if(checkForm()){ - val url= Api.buildUrl(AccountApi.register) + fun register() { + if (checkForm()) { + val url = Api.buildUrl(AccountApi.register) Logger.i("开始$regBtnDesc,请求接口:$url") - HttpClient.post(url,SimpleCallback( - action = regBtnDesc, - onSuccess = { _dialogMsg.postValue(DialogMessage(message = it.message,userResDto = it.body)) }, - onFail = { _snackBarMsg.postValue(it)}, - type = object : TypeToken>() {}.type), - jsonBody = Gson().toJson(UserVo(studentId = "${studentId.value}",name = "${name.value}"))) + HttpClient.post( + url, SimpleCallback( + action = regBtnDesc, + onSuccess = { + _dialogMsg.postValue( + DialogMessage( + message = it.message, + userResDto = it.body + ) + ) + }, + onFail = { _snackBarMsg.postValue(it) }, + type = object : TypeToken>() {}.type + ), + jsonBody = Gson().toJson( + UserVo( + studentId = "${studentId.value}", + name = "${name.value}" + ) + ) + ) resetForm() - }else{ + } else { Logger.wtf("表单校验失败,无法$regBtnDesc!!!") } } @@ -269,52 +294,61 @@ class AccountViewModel(application: Application) : AndroidViewModel(application) * 重置信息 * */ - fun resetRegisterResMsg(){ - _snackBarMsg.value="" + fun resetRegisterResMsg() { + _snackBarMsg.value = "" } - fun resetDialogMsg(){ - _dialogMsg.value=null + fun resetDialogMsg() { + _dialogMsg.value = null } - private fun resetForm(){ - _studentId.value="" - _name.value="" + private fun resetForm() { + _studentId.value = "" + _name.value = "" } /** * 登录 * */ - fun login(){ - if(checkForm()){ + fun login() { + if (checkForm()) { val url = Api.buildUrl(AccountApi.login) Logger.i("开始$loginDesc,请求接口:$url") - HttpClient.post(url,SimpleCallback( - action = loginDesc, - onSuccess = { - _snackBarMsg.postValue(it.message) - - val context= getApplication().applicationContext - val token = it.body?.token - if(token!=null){ - val db= AppDatabase.getInstance(context) - viewModelScope.launch { - db?.tokenDao()?.save(token = token) - }.invokeOnCompletion { - context.startActivity(Intent(context, InitActivity::class.java)) - _finishLogin.postValue(true) + HttpClient.post( + url, + SimpleCallback( + action = loginDesc, + onSuccess = { + _snackBarMsg.postValue(it.message) + + val context = getApplication().applicationContext + val token = it.body?.token + if (token != null) { + val db = AppDatabase.getInstance(context) + viewModelScope.launch { + db?.tokenDao()?.save(token = token) + }.invokeOnCompletion { + context.startActivity(Intent(context, InitActivity::class.java)) + _finishLogin.postValue(true) + } } - } - }, - onFail = {_snackBarMsg.postValue(it)}, - type = object : TypeToken>(){}.type - ),jsonBody = Gson().toJson(UserLoginVo(studentId = "${studentId.value}",password = "${password.value}",device = "${Build.MANUFACTURER} ${Build.MODEL}"))) - }else{ + }, + onFail = { _snackBarMsg.postValue(it) }, + type = object : TypeToken>() {}.type + ), + jsonBody = Gson().toJson( + UserLoginVo( + studentId = "${studentId.value}", + password = "${password.value}", + device = "${Build.MANUFACTURER} ${Build.MODEL}" + ) + ) + ) + } else { Logger.wtf("表单校验失败,无法$loginDesc!!!") } } - } \ No newline at end of file diff --git a/app/src/main/java/com/gyf/csams/account/ui/AccountActivity.kt b/app/src/main/java/com/gyf/csams/account/ui/AccountActivity.kt index a30b45d..daced9f 100644 --- a/app/src/main/java/com/gyf/csams/account/ui/AccountActivity.kt +++ b/app/src/main/java/com/gyf/csams/account/ui/AccountActivity.kt @@ -35,64 +35,79 @@ import com.gyf.csams.uikit.Body import com.gyf.csams.uikit.theme.CSAMSTheme -enum class AccountRoute{ +enum class AccountRoute { login, register } -class AccountActivity: ComponentActivity() { +class AccountActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { CSAMSTheme { - Body { - nav, scaffoldState -> + Body { nav, scaffoldState -> NavHost(navController = nav, startDestination = AccountRoute.login.name) { composable(AccountRoute.login.name) { - Account(scaffoldState=scaffoldState,route = AccountRoute.login) { isValidForm: Boolean, accountViewModel: AccountViewModel -> + Account( + scaffoldState = scaffoldState, + route = AccountRoute.login + ) { isValidForm: Boolean, accountViewModel: AccountViewModel -> Spacer(modifier = Modifier.height(10.dp)) - OutlinedButton(onClick = {accountViewModel.login()}, + OutlinedButton( + onClick = { accountViewModel.login() }, enabled = isValidForm, modifier = Modifier .fillMaxWidth() - .padding(bottom = 10.dp)) { + .padding(bottom = 10.dp) + ) { Text(text = accountViewModel.loginDesc) } - val finishLogin:Boolean? by accountViewModel.finishLogin.observeAsState() - if(finishLogin==true){ + val finishLogin: Boolean? by accountViewModel.finishLogin.observeAsState() + if (finishLogin == true) { finish() } - OutlinedButton(onClick = { nav.navigate(AccountRoute.register.name)}, + OutlinedButton( + onClick = { nav.navigate(AccountRoute.register.name) }, modifier = Modifier.fillMaxWidth(), colors = ButtonDefaults.outlinedButtonColors( - contentColor = MaterialTheme.colors.onBackground)) { - Text(text = accountViewModel.goRegister) + contentColor = MaterialTheme.colors.onBackground + ) + ) { + Text(text = accountViewModel.goRegister) } } } composable(AccountRoute.register.name) { - Account(scaffoldState=scaffoldState,route = AccountRoute.register) { isValidForm: Boolean, accountViewModel: AccountViewModel -> + Account( + scaffoldState = scaffoldState, + route = AccountRoute.register + ) { isValidForm: Boolean, accountViewModel: AccountViewModel -> Spacer(modifier = Modifier.height(10.dp)) - OutlinedButton(onClick = { accountViewModel.register()}, + OutlinedButton( + onClick = { accountViewModel.register() }, enabled = isValidForm, modifier = Modifier .fillMaxWidth() - .padding(bottom = 10.dp)) { + .padding(bottom = 10.dp) + ) { Text(text = accountViewModel.regBtnDesc) } - OutlinedButton(onClick = { nav.navigate(AccountRoute.login.name)}, + OutlinedButton( + onClick = { nav.navigate(AccountRoute.login.name) }, modifier = Modifier.fillMaxWidth(), colors = ButtonDefaults.outlinedButtonColors( - contentColor = MaterialTheme.colors.onBackground)) { + contentColor = MaterialTheme.colors.onBackground + ) + ) { Text(text = accountViewModel.backLogin) } } @@ -111,64 +126,66 @@ class AccountActivity: ComponentActivity() { * @param Action 表单操作区域 */ @Composable -private fun Account(accountViewModel: AccountViewModel = viewModel(), - scaffoldState: ScaffoldState, - route: AccountRoute, - Action: @Composable (isValidForm:Boolean,accountViewModel: AccountViewModel) -> Unit){ - accountViewModel.route=route - Row( - horizontalArrangement = Arrangement.Center, - verticalAlignment = Alignment.CenterVertically, - modifier = Modifier.fillMaxSize() - ) { - Column(modifier = Modifier.width(IntrinsicSize.Min)) { - val name: String by accountViewModel.name.observeAsState("") - Text(buildAnnotatedString { - withStyle( - style = MaterialTheme.typography.subtitle1.toSpanStyle() - .copy(color = MaterialTheme.colors.primary) - ) { - append(name) - } - withStyle(style = MaterialTheme.typography.subtitle1.toSpanStyle()) { - append(accountViewModel.welcomeStart) - } - withStyle(style = MaterialTheme.typography.subtitle2.toSpanStyle()) { - append(accountViewModel.welcomeEnd) - } - withStyle( - style = MaterialTheme.typography.subtitle2.toSpanStyle() - .copy(color = MaterialTheme.colors.secondary) - ) { - append(BuildConfig.APP_NAME) - } - }) +private fun Account( + accountViewModel: AccountViewModel = viewModel(), + scaffoldState: ScaffoldState, + route: AccountRoute, + Action: @Composable (isValidForm: Boolean, accountViewModel: AccountViewModel) -> Unit +) { + accountViewModel.route = route + Row( + horizontalArrangement = Arrangement.Center, + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier.fillMaxSize() + ) { + Column(modifier = Modifier.width(IntrinsicSize.Min)) { + val name: String by accountViewModel.name.observeAsState("") + Text(buildAnnotatedString { + withStyle( + style = MaterialTheme.typography.subtitle1.toSpanStyle() + .copy(color = MaterialTheme.colors.primary) + ) { + append(name) + } + withStyle(style = MaterialTheme.typography.subtitle1.toSpanStyle()) { + append(accountViewModel.welcomeStart) + } + withStyle(style = MaterialTheme.typography.subtitle2.toSpanStyle()) { + append(accountViewModel.welcomeEnd) + } + withStyle( + style = MaterialTheme.typography.subtitle2.toSpanStyle() + .copy(color = MaterialTheme.colors.secondary) + ) { + append(BuildConfig.APP_NAME) + } + }) - StudentId(checkRepeat=route==AccountRoute.register) - Spacer(modifier = Modifier.height(10.dp)) + StudentId(checkRepeat = route == AccountRoute.register) + Spacer(modifier = Modifier.height(10.dp)) - if (route==AccountRoute.register) Name(name=name) else Password() + if (route == AccountRoute.register) Name(name = 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() - } - } + Spacer(modifier = Modifier.height(10.dp)) + PasswordTip() + val isValidForm: Boolean by accountViewModel.isValidForm.observeAsState(false) + Action(isValidForm = isValidForm, accountViewModel = accountViewModel) - RegisterDialog() + val snackBarMsg: String by accountViewModel.snackBarMsg.observeAsState("") + + if (snackBarMsg != "") { + LaunchedEffect(scaffoldState) { + scaffoldState.snackbarHostState.showSnackbar( + message = snackBarMsg + ) + accountViewModel.resetRegisterResMsg() + } } + + RegisterDialog() } + } } /** @@ -177,11 +194,11 @@ private fun Account(accountViewModel: AccountViewModel = viewModel(), * @param accountViewModel */ @Composable -private fun StudentId(accountViewModel: AccountViewModel = viewModel(),checkRepeat:Boolean){ +private fun StudentId(accountViewModel: AccountViewModel = viewModel(), checkRepeat: Boolean) { Column { val studentId: String by accountViewModel.studentId.observeAsState("") - val isValidStudentId : Boolean by accountViewModel.isValidStudentId.observeAsState(false) + val isValidStudentId: Boolean by accountViewModel.isValidStudentId.observeAsState(false) val focusManager = LocalFocusManager.current OutlinedTextField( value = studentId, @@ -189,12 +206,15 @@ private fun StudentId(accountViewModel: AccountViewModel = viewModel(),checkRepe label = { Text(text = accountViewModel.studentIdDesc) }, placeholder = { Text(text = accountViewModel.studentIdPlaceholder) }, keyboardActions = KeyboardActions(onDone = { focusManager.clearFocus() }), - keyboardOptions = KeyboardOptions.Default.copy( keyboardType = KeyboardType.Number,imeAction = ImeAction.Done), + keyboardOptions = KeyboardOptions.Default.copy( + keyboardType = KeyboardType.Number, + imeAction = ImeAction.Done + ), singleLine = true, isError = !isValidStudentId ) if (isValidStudentId) { - if(checkRepeat) { + if (checkRepeat) { val isRepeat: Boolean? by accountViewModel.isRepeat.observeAsState(null) when (isRepeat) { null -> AnimationText(text = accountViewModel.checkRegTip) @@ -224,7 +244,7 @@ private fun StudentId(accountViewModel: AccountViewModel = viewModel(),checkRepe }) } } - }else{ + } else { Text( text = accountViewModel.studentIdFormat, color = MaterialTheme.colors.error, @@ -241,11 +261,11 @@ private fun StudentId(accountViewModel: AccountViewModel = viewModel(),checkRepe * @param accountViewModel */ @Composable -private fun RegisterDialog(accountViewModel: AccountViewModel = viewModel()){ +private fun RegisterDialog(accountViewModel: AccountViewModel = viewModel()) { val dialogMsg: DialogMessage? by accountViewModel.dialogMsg.observeAsState(null) - val message=dialogMsg?.userResDto?.password - if(message?.isNotEmpty() == true){ + val message = dialogMsg?.userResDto?.password + if (message?.isNotEmpty() == true) { PasswordDialog(message = message) } } @@ -257,21 +277,28 @@ private fun RegisterDialog(accountViewModel: AccountViewModel = viewModel()){ * @param message */ @Composable -private fun PasswordDialog(accountViewModel: AccountViewModel = viewModel(), message:String){ - val context= LocalContext.current - val button:@Composable () -> Unit = { - Row(horizontalArrangement= Arrangement.Center,modifier = Modifier - .fillMaxWidth() - .padding(bottom = 10.dp)) { - OutlinedButton(onClick = { accountViewModel.resetDialogMsg() }, - modifier = Modifier.padding(end = 10.dp)) { +private fun PasswordDialog(accountViewModel: AccountViewModel = viewModel(), message: String) { + val context = LocalContext.current + val button: @Composable () -> Unit = { + Row( + horizontalArrangement = Arrangement.Center, modifier = Modifier + .fillMaxWidth() + .padding(bottom = 10.dp) + ) { + OutlinedButton( + onClick = { accountViewModel.resetDialogMsg() }, + modifier = Modifier.padding(end = 10.dp) + ) { Text(text = accountViewModel.confirmDesc) } - OutlinedButton(onClick = { - context.startActivity(Intent(context,AccountActivity::class.java)) - }, + OutlinedButton( + onClick = { + context.startActivity(Intent(context, AccountActivity::class.java)) + }, colors = ButtonDefaults.outlinedButtonColors( - contentColor = MaterialTheme.colors.onBackground)) { + contentColor = MaterialTheme.colors.onBackground + ) + ) { Text(text = accountViewModel.backLogin) } } @@ -282,8 +309,10 @@ private fun PasswordDialog(accountViewModel: AccountViewModel = viewModel(), mes text = { Text(buildAnnotatedString { append(accountViewModel.passwordDialogStart) - withStyle(style = MaterialTheme.typography.body1.toSpanStyle() - .copy(color = MaterialTheme.colors.secondary)){ + withStyle( + style = MaterialTheme.typography.body1.toSpanStyle() + .copy(color = MaterialTheme.colors.secondary) + ) { append(message) } append(accountViewModel.passwordDialogEnd) @@ -292,7 +321,6 @@ private fun PasswordDialog(accountViewModel: AccountViewModel = viewModel(), mes } - /** * 姓名文本框 * TODO 需要把逻辑封装到[com.gyf.csams.uikit.BaseTextField] @@ -300,23 +328,27 @@ private fun PasswordDialog(accountViewModel: AccountViewModel = viewModel(), mes * @param accountViewModel */ @Composable -private fun Name(name:String, accountViewModel: AccountViewModel = viewModel()){ +private fun Name(name: String, accountViewModel: AccountViewModel = viewModel()) { Column { - val isValidName:Boolean by accountViewModel.isValidName.observeAsState(false) + val isValidName: Boolean by accountViewModel.isValidName.observeAsState(false) val focusManager = LocalFocusManager.current - OutlinedTextField(value = name, - onValueChange = {accountViewModel.onNameChange(it)}, - label={ Text(text = accountViewModel.nameDesc)}, - placeholder = { Text(text = accountViewModel.namePlaceholder)}, + OutlinedTextField( + value = name, + onValueChange = { accountViewModel.onNameChange(it) }, + label = { Text(text = accountViewModel.nameDesc) }, + placeholder = { Text(text = accountViewModel.namePlaceholder) }, singleLine = true, isError = !isValidName, keyboardActions = KeyboardActions(onDone = { focusManager.clearFocus() }), - keyboardOptions = KeyboardOptions.Default.copy(imeAction = ImeAction.Done)) + keyboardOptions = KeyboardOptions.Default.copy(imeAction = ImeAction.Done) + ) - if (!isValidName){ - Text(text = accountViewModel.nameFormat, - color=MaterialTheme.colors.error) + if (!isValidName) { + Text( + text = accountViewModel.nameFormat, + color = MaterialTheme.colors.error + ) } } @@ -328,24 +360,31 @@ private fun Name(name:String, accountViewModel: AccountViewModel = viewModel()){ * @param accountViewModel */ @Composable -private fun Password(accountViewModel: AccountViewModel= viewModel()){ +private fun Password(accountViewModel: AccountViewModel = viewModel()) { Column { - val isValidPwd:Boolean by accountViewModel.isValidPwd.observeAsState(false) + val isValidPwd: Boolean by accountViewModel.isValidPwd.observeAsState(false) val focusManager = LocalFocusManager.current - val password:String by accountViewModel.password.observeAsState("") - OutlinedTextField(value = password, - visualTransformation=PasswordVisualTransformation(), - onValueChange = {accountViewModel.onPasswordChange(it)}, - label={ Text(text = accountViewModel.passwordDesc)}, - placeholder = { Text(text = accountViewModel.passwordPlaceholder)}, + val password: String by accountViewModel.password.observeAsState("") + OutlinedTextField( + value = password, + visualTransformation = PasswordVisualTransformation(), + onValueChange = { accountViewModel.onPasswordChange(it) }, + label = { Text(text = accountViewModel.passwordDesc) }, + placeholder = { Text(text = accountViewModel.passwordPlaceholder) }, singleLine = true, isError = !isValidPwd, keyboardActions = KeyboardActions(onDone = { focusManager.clearFocus() }), - keyboardOptions = KeyboardOptions.Default.copy(imeAction = ImeAction.Done,keyboardType = KeyboardType.Number)) + keyboardOptions = KeyboardOptions.Default.copy( + imeAction = ImeAction.Done, + keyboardType = KeyboardType.Number + ) + ) - if(!isValidPwd){ - Text(text = accountViewModel.passwordFormat, - color=MaterialTheme.colors.error) + if (!isValidPwd) { + Text( + text = accountViewModel.passwordFormat, + color = MaterialTheme.colors.error + ) } } } @@ -357,7 +396,7 @@ private fun Password(accountViewModel: AccountViewModel= viewModel()){ */ @Composable private fun PasswordTip(accountViewModel: AccountViewModel = viewModel()) { - if(accountViewModel.isValidForm.value==true) { + if (accountViewModel.isValidForm.value == true) { Text( text = accountViewModel.passwordTip, color = MaterialTheme.colors.primary, modifier = Modifier.fillMaxWidth() @@ -371,14 +410,15 @@ private fun PasswordTip(accountViewModel: AccountViewModel = viewModel()) { fun DefaultPreview() { CSAMSTheme { - Row ( - horizontalArrangement=Arrangement.Center, + Row( + horizontalArrangement = Arrangement.Center, verticalAlignment = Alignment.CenterVertically, - modifier = Modifier.fillMaxSize()) { + modifier = Modifier.fillMaxSize() + ) { Column(modifier = Modifier.width(IntrinsicSize.Min)) { - val model:AccountViewModel= viewModel() + val model: AccountViewModel = viewModel() - StudentId(model,false) + StudentId(model, false) Spacer(modifier = Modifier.height(10.dp)) } } diff --git a/app/src/main/java/com/gyf/csams/activity/model/ActivityDetailViewModel.kt b/app/src/main/java/com/gyf/csams/activity/model/ActivityDetailViewModel.kt index 633e613..eefb763 100644 --- a/app/src/main/java/com/gyf/csams/activity/model/ActivityDetailViewModel.kt +++ b/app/src/main/java/com/gyf/csams/activity/model/ActivityDetailViewModel.kt @@ -17,7 +17,7 @@ import java.util.* * 活动详情菜单通用状态 * */ -class ActivityDetailViewModel:ViewModel(), TopMenuInterface { +class ActivityDetailViewModel : ViewModel(), TopMenuInterface { override val _currentMenu: MutableLiveData = MutableLiveData() override val currentMenu: LiveData = _currentMenu } @@ -31,22 +31,23 @@ class ActivityDetailViewModel:ViewModel(), TopMenuInterface * @property activityLocation 活动地点 * @property activityDesc 活动介绍 */ -data class ActivityDetailVo(val associationName:String,val activityName:String, - val activityTime:Date,val activityLocation:String, - val activityDesc:String) - +data class ActivityDetailVo( + val associationName: String, val activityName: String, + val activityTime: Date, val activityLocation: String, + val activityDesc: String +) /** * 活动信息 * */ -class ActivityInfoViewModel:ViewModel(){ - private val _activityDetailVo=MutableLiveData() - val activityDetailVo:LiveData = _activityDetailVo +class ActivityInfoViewModel : ViewModel() { + private val _activityDetailVo = MutableLiveData() + val activityDetailVo: LiveData = _activityDetailVo val like = "点赞" - val collect="收藏" + val collect = "收藏" init { loadInfo() @@ -57,7 +58,7 @@ class ActivityInfoViewModel:ViewModel(){ * * @param callback */ - fun like(callback:(message:String)->Unit){ + fun like(callback: (message: String) -> Unit) { callback(NOT_IMPL_TIP) } @@ -66,11 +67,11 @@ class ActivityInfoViewModel:ViewModel(){ * * @param callback */ - fun collect(callback:(message:String)->Unit){ + fun collect(callback: (message: String) -> Unit) { callback(NOT_IMPL_TIP) } - private fun loadInfo(){ + private fun loadInfo() { viewModelScope.launch { _activityDetailVo.value = ActivityDetailVo( activityName = randomChinese(4), @@ -94,20 +95,27 @@ class ActivityInfoViewModel:ViewModel(){ * @property createTime 文件创建时间 * @property studentId 文件上传人 */ -data class ActivityPhotoVo(val name:String, val size:Long, val url:String, val md5:String, val createTime: Date, val studentId:String) +data class ActivityPhotoVo( + val name: String, + val size: Long, + val url: String, + val md5: String, + val createTime: Date, + val studentId: String +) /** * 活动相册数据状态管理 * */ -class ActivityPhotoViewModel:ScrollList(){ +class ActivityPhotoViewModel : ScrollList() { override val initSize: Int = 10 init { load() } - fun upload(callback: (message: String) -> Unit){ + fun upload(callback: (message: String) -> Unit) { callback(NOT_IMPL_TIP) } @@ -118,13 +126,17 @@ class ActivityPhotoViewModel:ScrollList(){ override fun load() { viewModelScope.launch { _data.value?.apply { - repeat(initSize){ - add(ActivityPhotoVo(name=randomChinese(3), - size= randomNum(3).toLong(), - url="", - md5 = "", - createTime = randomDateTime(), - studentId = "")) + repeat(initSize) { + add( + ActivityPhotoVo( + name = randomChinese(3), + size = randomNum(3).toLong(), + url = "", + md5 = "", + createTime = randomDateTime(), + studentId = "" + ) + ) } } } @@ -140,15 +152,19 @@ class ActivityPhotoViewModel:ScrollList(){ Logger.i("加载更多") viewModelScope.launch { _data.value?.apply { - val list= mutableListOf() + val list = mutableListOf() list.addAll(this) - repeat(initSize){ - add(ActivityPhotoVo(name=randomChinese(3), - size= randomNum(3).toLong(), - url="", - md5 = "", - createTime = randomDateTime(), - studentId = "")) + repeat(initSize) { + add( + ActivityPhotoVo( + name = randomChinese(3), + size = randomNum(3).toLong(), + url = "", + md5 = "", + createTime = randomDateTime(), + studentId = "" + ) + ) } _data.postValue(list) callback("成功加载更多相册") @@ -157,15 +173,18 @@ class ActivityPhotoViewModel:ScrollList(){ } } -data class ActivityMemberVo(val studentId: String,val name:String) +data class ActivityMemberVo(val studentId: String, val name: String) -data class ActivityMembersVo(val organizer:ActivityMemberVo, val participant:MutableList?) +data class ActivityMembersVo( + val organizer: ActivityMemberVo, + val participant: MutableList? +) -class ActivityMemberViewModel:ScrollList(){ +class ActivityMemberViewModel : ScrollList() { override val initSize: Int = 10 - private val _allMember=MutableLiveData() - val allMember:LiveData = _allMember + private val _allMember = MutableLiveData() + val allMember: LiveData = _allMember init { load() @@ -178,10 +197,15 @@ class ActivityMemberViewModel:ScrollList(){ override fun load() { viewModelScope.launch { _data.value?.apply { - repeat(initSize){ - add(ActivityMemberVo(studentId = randomNum(),name = randomChinese(3))) + repeat(initSize) { + add(ActivityMemberVo(studentId = randomNum(), name = randomChinese(3))) } - _allMember.value= ActivityMembersVo(organizer = ActivityMemberVo(studentId = randomNum(),name = randomChinese(3)),participant = _data.value) + _allMember.value = ActivityMembersVo( + organizer = ActivityMemberVo( + studentId = randomNum(), + name = randomChinese(3) + ), participant = _data.value + ) } } } @@ -194,14 +218,19 @@ class ActivityMemberViewModel:ScrollList(){ override fun loadMore(callback: (message: String) -> Unit) { viewModelScope.launch { _data.value?.apply { - val list= mutableListOf() + val list = mutableListOf() list.addAll(this) - repeat(initSize){ - add(ActivityMemberVo(studentId = randomNum(),name = randomChinese(3))) + repeat(initSize) { + add(ActivityMemberVo(studentId = randomNum(), name = randomChinese(3))) } _allMember.value?.apply { _data.postValue(list) - _allMember.postValue(ActivityMembersVo(organizer=organizer,participant=list)) + _allMember.postValue( + ActivityMembersVo( + organizer = organizer, + participant = list + ) + ) callback("成功加载更多活动参与者") } } @@ -209,33 +238,33 @@ class ActivityMemberViewModel:ScrollList(){ } } -data class BBSVo(val studentId:String,val name:String,val createTime:Date,val content:String) +data class BBSVo(val studentId: String, val name: String, val createTime: Date, val content: String) /** * 交流区数据状态管理 * */ -class BBSViewModel:ScrollList(), SendInterface { +class BBSViewModel : ScrollList(), SendInterface { override val initSize: Int = 10 - val title="发送评论" + val title = "发送评论" - override val newContent = StringForm(formDesc = "评论内容",textLength = 80) + override val newContent = StringForm(formDesc = "评论内容", textLength = 80) - override val _openDialog=MutableLiveData() - override val openDialog:LiveData = _openDialog + override val _openDialog = MutableLiveData() + override val openDialog: LiveData = _openDialog init { load() } - override fun openDialog(){ - _openDialog.value=true + override fun openDialog() { + _openDialog.value = true } - override fun closeDialog(){ - _openDialog.value=false + override fun closeDialog() { + _openDialog.value = false } /** @@ -243,7 +272,7 @@ class BBSViewModel:ScrollList(), SendInterface { * * @param callback */ - override fun send(callback: (message: String) -> Unit){ + override fun send(callback: (message: String) -> Unit) { callback(NOT_IMPL_TIP) } @@ -254,8 +283,15 @@ class BBSViewModel:ScrollList(), SendInterface { override fun load() { viewModelScope.launch { _data.value?.apply { - repeat(initSize){ - add(BBSVo(studentId = randomNum(),createTime = randomDateTime(),content = randomChinese(50),name = randomChinese(3))) + repeat(initSize) { + add( + BBSVo( + studentId = randomNum(), + createTime = randomDateTime(), + content = randomChinese(50), + name = randomChinese(3) + ) + ) } } } @@ -269,11 +305,18 @@ class BBSViewModel:ScrollList(), SendInterface { override fun loadMore(callback: (message: String) -> Unit) { viewModelScope.launch { _data.value?.apply { - repeat(initSize){ - val list= mutableListOf() + repeat(initSize) { + val list = mutableListOf() list.addAll(this) - repeat(initSize){ - add(BBSVo(studentId = randomNum(),name = randomChinese(3),createTime = randomDateTime(),content = randomChinese(50))) + repeat(initSize) { + add( + BBSVo( + studentId = randomNum(), + name = randomChinese(3), + createTime = randomDateTime(), + content = randomChinese(50) + ) + ) } _data.postValue(list) callback("成功加载更多评论") diff --git a/app/src/main/java/com/gyf/csams/association/model/AssociationViewModel.kt b/app/src/main/java/com/gyf/csams/association/model/AssociationViewModel.kt index 7fbd9f2..8392b7e 100644 --- a/app/src/main/java/com/gyf/csams/association/model/AssociationViewModel.kt +++ b/app/src/main/java/com/gyf/csams/association/model/AssociationViewModel.kt @@ -13,7 +13,7 @@ import com.orhanobut.logger.Logger import kotlinx.coroutines.launch -class AssociationViewModel:ViewModel(),TopMenuInterface{ +class AssociationViewModel : ViewModel(), TopMenuInterface { override val _currentMenu: MutableLiveData = MutableLiveData() override val currentMenu: LiveData = _currentMenu @@ -21,41 +21,40 @@ class AssociationViewModel:ViewModel(),TopMenuInterface{ /** * 下拉菜单状态 */ - private val _expanded=MutableLiveData(false) - val expanded:LiveData = _expanded - + private val _expanded = MutableLiveData(false) + val expanded: LiveData = _expanded /** * 切换下拉菜单状态 * */ - fun switchType(){ + fun switchType() { _expanded.value?.let { _expanded.value = !it } } - fun close(){ - _expanded.value=false + fun close() { + _expanded.value = false } } -data class MemberVo(val name:String) +data class MemberVo(val name: String) /** * 社团会员 * */ -class MemberViewModel:ScrollList(){ - val name=StringForm(formDesc = "姓名关键字",5) +class MemberViewModel : ScrollList() { + val name = StringForm(formDesc = "姓名关键字", 5) - val search="搜索" + val search = "搜索" - private val _memberList=MutableLiveData>(mutableListOf()) + private val _memberList = MutableLiveData>(mutableListOf()) - val memberList=_memberList + val memberList = _memberList override val initSize: Int = 10 @@ -71,7 +70,7 @@ class MemberViewModel:ScrollList(){ viewModelScope.launch { _memberList.value?.apply { repeat(initSize) { - add(MemberVo(name = "成员${size+1}")) + add(MemberVo(name = "成员${size + 1}")) } Logger.i("初始化社团成员size=$size") } @@ -87,11 +86,11 @@ class MemberViewModel:ScrollList(){ override fun loadMore(callback: (message: String) -> Unit) { viewModelScope.launch { _memberList.value?.let { - val t= mutableListOf() + val t = mutableListOf() t.addAll(it) t.apply { - repeat(10){ - add(MemberVo(name = "成员${t.size+1}")) + repeat(10) { + add(MemberVo(name = "成员${t.size + 1}")) } } _memberList.postValue(t) @@ -105,19 +104,18 @@ class MemberViewModel:ScrollList(){ * * @param callback */ - fun search(callback: (value: String) -> Unit){ + fun search(callback: (value: String) -> Unit) { Logger.i("搜索条件[成员姓名:${name.formValue.value}]") callback(NOT_IMPL_TIP) } } +data class OngoingActVo(val name: String) -data class OngoingActVo(val name:String) - -class OngoingActViewModel:ViewModel(){ - private val _act=MutableLiveData() - val act:LiveData = _act +class OngoingActViewModel : ViewModel() { + private val _act = MutableLiveData() + val act: LiveData = _act } data class HistoryActVo(val name: String) @@ -127,7 +125,7 @@ data class HistoryActVo(val name: String) * 历史活动 * */ -class HistoryActViewModel: ScrollList() { +class HistoryActViewModel : ScrollList() { override val initSize = 10 init { @@ -137,25 +135,25 @@ class HistoryActViewModel: ScrollList() { override fun load() { viewModelScope.launch { _data.value?.apply { - repeat(initSize){ - add(HistoryActVo(name = "活动${size+1}")) + repeat(initSize) { + add(HistoryActVo(name = "活动${size + 1}")) } Logger.i("初始化活动数量:${size}") } } } - override fun loadMore(callback:(message:String) -> Unit) { - _data.value?.apply { - val t= mutableListOf() - t.addAll(this) - t.apply { - repeat(10){ - add(HistoryActVo(name = "活动${t.size+1}")) - } - } - _data.postValue(t) - callback("成功加载更多活动") - } + override fun loadMore(callback: (message: String) -> Unit) { + _data.value?.apply { + val t = mutableListOf() + t.addAll(this) + t.apply { + repeat(10) { + add(HistoryActVo(name = "活动${t.size + 1}")) + } + } + _data.postValue(t) + callback("成功加载更多活动") + } } } \ No newline at end of file diff --git a/app/src/main/java/com/gyf/csams/association/model/ExamViewModel.kt b/app/src/main/java/com/gyf/csams/association/model/ExamViewModel.kt index e2f92d0..14eae24 100644 --- a/app/src/main/java/com/gyf/csams/association/model/ExamViewModel.kt +++ b/app/src/main/java/com/gyf/csams/association/model/ExamViewModel.kt @@ -13,9 +13,10 @@ import kotlin.random.Random * 题库界面类型 * */ -enum class ExamActivityType(val menuName:String){ +enum class ExamActivityType(val menuName: String) { //入团题库 SET_EXAM("入团题库"), + //入团申请表 JOIN_Association("入团申请表") } @@ -24,16 +25,17 @@ enum class ExamActivityType(val menuName:String){ * 题型 * */ -enum class ExamType(val type:String){ +enum class ExamType(val type: String) { //选择题 CQ("选择题"), + //开放题 OQ("开放题") } -sealed class Exam{ - abstract val examType:ExamType - abstract val question:StringForm +sealed class Exam { + abstract val examType: ExamType + abstract val question: StringForm } @@ -56,30 +58,29 @@ data class OpenQuestionsVo( * @property rightAnswer 正确答案 * @property question 问题 */ -data class ChoiceQuestionVo(override val examType: ExamType = ExamType.CQ, - val answers:List, - val rightAnswer:Int, - override val question: StringForm -):Exam() - - +data class ChoiceQuestionVo( + override val examType: ExamType = ExamType.CQ, + val answers: List, + val rightAnswer: Int, + override val question: StringForm +) : Exam() /** * 问题长度 */ -const val QUESTION_TEXT_LENGTH=30 +const val QUESTION_TEXT_LENGTH = 30 /** * 选择题选项数 */ -const val ANSWER_SIZE=4 +const val ANSWER_SIZE = 4 /** * 答案长度 * */ -const val ANSWER_TEXT_LENGTH=15 +const val ANSWER_TEXT_LENGTH = 15 /** @@ -87,22 +88,22 @@ const val ANSWER_TEXT_LENGTH=15 * */ -class ExamViewModel:ScrollList() { +class ExamViewModel : ScrollList() { val questionIsNull: String = "问题不能为空" - val deleteLeastOne: String="至少保留一道题目" - val updateExam="更新题库" - val postAnswer="提交答案" - val back="返回" - val deleteTip="确定删除此题目?" - val addTip="确定添加此题目?" - val actionLabel="确定" + val deleteLeastOne: String = "至少保留一道题目" + val updateExam = "更新题库" + val postAnswer = "提交答案" + val back = "返回" + val deleteTip = "确定删除此题目?" + val addTip = "确定添加此题目?" + val actionLabel = "确定" override val initSize = 10 - private val _newExam:MutableLiveData = MutableLiveData(createExam(ExamType.CQ)) - val newExam:LiveData = _newExam + private val _newExam: MutableLiveData = MutableLiveData(createExam(ExamType.CQ)) + val newExam: LiveData = _newExam init { load() @@ -112,8 +113,9 @@ class ExamViewModel:ScrollList() { * 切换题型 * */ - fun switchType(exam: Exam){ - if(exam is ChoiceQuestionVo) _newExam.value=createExam(ExamType.OQ) else _newExam.value=createExam(ExamType.CQ) + fun switchType(exam: Exam) { + if (exam is ChoiceQuestionVo) _newExam.value = createExam(ExamType.OQ) else _newExam.value = + createExam(ExamType.CQ) } @@ -124,14 +126,20 @@ class ExamViewModel:ScrollList() { * @return */ private fun createExam(type: ExamType): Exam { - val question=StringForm(formDesc = "问题",textLength = QUESTION_TEXT_LENGTH) - return when(type){ - ExamType.CQ-> ChoiceQuestionVo( - answers = ('A'..'D').map { StringForm(formDesc = "选项",textLength = ANSWER_TEXT_LENGTH,value = "选项$it") }, + val question = StringForm(formDesc = "问题", textLength = QUESTION_TEXT_LENGTH) + return when (type) { + ExamType.CQ -> ChoiceQuestionVo( + answers = ('A'..'D').map { + StringForm( + formDesc = "选项", + textLength = ANSWER_TEXT_LENGTH, + value = "选项$it" + ) + }, rightAnswer = 0, question = question ) - ExamType.OQ-> OpenQuestionsVo(question = question) + ExamType.OQ -> OpenQuestionsVo(question = question) } } @@ -140,16 +148,16 @@ class ExamViewModel:ScrollList() { * 更新题目 * */ - fun update(oldExam: Exam,newExam:Exam){ - if(oldExam==_newExam.value){ - _newExam.value=newExam - }else{ + fun update(oldExam: Exam, newExam: Exam) { + if (oldExam == _newExam.value) { + _newExam.value = newExam + } else { _data.value?.apply { - this[indexOf(oldExam)]=newExam + this[indexOf(oldExam)] = newExam val list = mutableListOf() list.addAll(this) _data.value?.clear() - _data.value=list + _data.value = list } } } @@ -159,7 +167,7 @@ class ExamViewModel:ScrollList() { * * @param callback */ - fun updateExam(callback: (message: String) -> Unit){ + fun updateExam(callback: (message: String) -> Unit) { callback(NOT_IMPL_TIP) } @@ -168,7 +176,7 @@ class ExamViewModel:ScrollList() { * * @param callback */ - fun postAnswer(callback: (message: String) -> Unit){ + fun postAnswer(callback: (message: String) -> Unit) { callback(NOT_IMPL_TIP) } @@ -180,13 +188,31 @@ class ExamViewModel:ScrollList() { viewModelScope.launch { _data.value?.apply { repeat(initSize) { - if (Random.nextBoolean()){ - add(OpenQuestionsVo(question = StringForm(formDesc = "问题",textLength = QUESTION_TEXT_LENGTH,value = "这是一道开放题:$size"))) - } else{ + if (Random.nextBoolean()) { + add( + OpenQuestionsVo( + question = StringForm( + formDesc = "问题", + textLength = QUESTION_TEXT_LENGTH, + value = "这是一道开放题:$size" + ) + ) + ) + } else { add( ChoiceQuestionVo( - question = StringForm(formDesc = "问题",textLength = QUESTION_TEXT_LENGTH,value = "这是一道选择题:$size"), - answers = ('A'..'D').map { StringForm(formDesc = "选项",textLength = ANSWER_TEXT_LENGTH,value = "选项$it") }, + question = StringForm( + formDesc = "问题", + textLength = QUESTION_TEXT_LENGTH, + value = "这是一道选择题:$size" + ), + answers = ('A'..'D').map { + StringForm( + formDesc = "选项", + textLength = ANSWER_TEXT_LENGTH, + value = "选项$it" + ) + }, rightAnswer = Random.nextInt(ANSWER_SIZE) ) ) @@ -226,13 +252,13 @@ class ExamViewModel:ScrollList() { fun addQuestion() { _data.value?.apply { - _newExam.value?.let{ - val list= mutableListOf() + _newExam.value?.let { + val list = mutableListOf() list.addAll(this) list.add(it) _data.postValue(list) } - _newExam.value=createExam(ExamType.CQ) + _newExam.value = createExam(ExamType.CQ) } } diff --git a/app/src/main/java/com/gyf/csams/association/model/RegAssociationViewModel.kt b/app/src/main/java/com/gyf/csams/association/model/RegAssociationViewModel.kt index 5b9dc0e..33fb922 100644 --- a/app/src/main/java/com/gyf/csams/association/model/RegAssociationViewModel.kt +++ b/app/src/main/java/com/gyf/csams/association/model/RegAssociationViewModel.kt @@ -8,30 +8,30 @@ import com.gyf.csams.NOT_IMPL_TIP import com.gyf.csams.uikit.StringForm -data class Image(val uri:Uri,val createTime:Long,val size:Long) +data class Image(val uri: Uri, val createTime: Long, val size: Long) class RegAssociationViewModel : ViewModel() { - val frameDesc="社团注册资料" + val frameDesc = "社团注册资料" - val name= StringForm(formDesc = "社团名称",textLength = 5) - val desc = StringForm(formDesc = "社团简介",textLength = 30) + val name = StringForm(formDesc = "社团名称", textLength = 5) + val desc = StringForm(formDesc = "社团简介", textLength = 30) - val _picture=MutableLiveData() - val picture:LiveData =_picture + val _picture = MutableLiveData() + val picture: LiveData = _picture - val piciurePlaceHolder="请上传图片" + val piciurePlaceHolder = "请上传图片" - val errorPicture="图片加载失败,请联系管理员" + val errorPicture = "图片加载失败,请联系管理员" - val deninedPermission="拒绝授权" + val deninedPermission = "拒绝授权" - val register="注册" - val back="返回" + val register = "注册" + val back = "返回" - fun setPicture(uri: Uri){ - _picture.value=uri + fun setPicture(uri: Uri) { + _picture.value = uri } /** @@ -39,7 +39,7 @@ class RegAssociationViewModel : ViewModel() { * * @param callback */ - fun register(callback: (value: String) -> Unit){ + fun register(callback: (value: String) -> Unit) { callback(NOT_IMPL_TIP) } diff --git a/app/src/main/java/com/gyf/csams/association/model/RenameViewModel.kt b/app/src/main/java/com/gyf/csams/association/model/RenameViewModel.kt index bb861b6..5a39254 100644 --- a/app/src/main/java/com/gyf/csams/association/model/RenameViewModel.kt +++ b/app/src/main/java/com/gyf/csams/association/model/RenameViewModel.kt @@ -8,21 +8,21 @@ import com.gyf.csams.uikit.StringForm * 社团重命名状态管理 * */ -class RenameViewModel:ViewModel() { - val menuName="换名申请表" +class RenameViewModel : ViewModel() { + val menuName = "换名申请表" - val oldName=StringForm(formDesc = "社团原名",textLength = 10) - val newName=StringForm(formDesc = "社团新名",textLength = 10) - val cause=StringForm(formDesc = "换名原因",textLength = 30) + val oldName = StringForm(formDesc = "社团原名", textLength = 10) + val newName = StringForm(formDesc = "社团新名", textLength = 10) + val cause = StringForm(formDesc = "换名原因", textLength = 30) - val postDesc="提交申请" - val back="返回" + val postDesc = "提交申请" + val back = "返回" /** * TODO 提交表单 * */ - fun post(callback:(message:String) -> Unit){ + fun post(callback: (message: String) -> Unit) { callback(NOT_IMPL_TIP) } } \ No newline at end of file diff --git a/app/src/main/java/com/gyf/csams/association/ui/AssociationActivity.kt b/app/src/main/java/com/gyf/csams/association/ui/AssociationActivity.kt index b0bc6a0..6b3c093 100644 --- a/app/src/main/java/com/gyf/csams/association/ui/AssociationActivity.kt +++ b/app/src/main/java/com/gyf/csams/association/ui/AssociationActivity.kt @@ -34,109 +34,139 @@ import com.gyf.csams.util.randomChinese import com.orhanobut.logger.Logger - /** * 社团界面 * */ -class AssociationActivity: ComponentActivity() { +class AssociationActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { CSAMSTheme { - 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, 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) - Column { - Logger.i("expanded=$expanded") - TextTopAppBar(nav = nav, - currentMenuName= currentMenuName.menuName, - menuNames = AssociationMenu.values(), - iconMenu = {model.switchType()}){ - Row{ - DropdownMenu(expanded = expanded, - onDismissRequest = { /*TODO*/ }, + Column { + Logger.i("expanded=$expanded") + TextTopAppBar(nav = nav, + currentMenuName = currentMenuName.menuName, + menuNames = AssociationMenu.values(), + iconMenu = { model.switchType() }) { + Row { + DropdownMenu( + expanded = expanded, + onDismissRequest = { /*TODO*/ }, // offset = DpOffset.Zero.copy(x=50.dp), - properties = PopupProperties() - ) { - DropdownMenuItem(onClick = { - model.close() - }) { - Row(verticalAlignment = Alignment.CenterVertically){ - Text(text = "申请活动") - Icon(painter = painterResource(id = R.drawable.ic_add_fill), contentDescription = null) - } + properties = PopupProperties() + ) { + DropdownMenuItem(onClick = { + model.close() + }) { + Row(verticalAlignment = Alignment.CenterVertically) { + Text(text = "申请活动") + Icon( + painter = painterResource(id = R.drawable.ic_add_fill), + contentDescription = null + ) + } + } + DropdownMenuItem(onClick = { + intent.apply { + putExtra( + ExamActivityType::name.name, + ExamActivityType.SET_EXAM + ) + } + context.startActivity(intent) + model.close() + }) { + Row(verticalAlignment = Alignment.CenterVertically) { + Text(text = "设置题库") + Icon( + painter = painterResource(id = R.drawable.ic_editor), + contentDescription = null + ) } - DropdownMenuItem(onClick = { - intent.apply { - putExtra(ExamActivityType::name.name, ExamActivityType.SET_EXAM) - } - context.startActivity(intent) - model.close() - }) { - Row(verticalAlignment = Alignment.CenterVertically) { - Text(text = "设置题库") - Icon(painter = painterResource(id = R.drawable.ic_editor), contentDescription = null) - } + } + DropdownMenuItem(onClick = { + context.startActivity( + Intent( + context, + ReNameActivity::class.java + ) + ) + model.close() + }) { + Row(verticalAlignment = Alignment.CenterVertically) { + Text(text = "社团命名") + Icon( + painter = painterResource(id = R.drawable.ic_exchange_rate), + contentDescription = null + ) } - DropdownMenuItem(onClick = { - context.startActivity(Intent(context,ReNameActivity::class.java)) - model.close() - }) { - Row(verticalAlignment = Alignment.CenterVertically) { - Text(text = "社团命名") - Icon(painter = painterResource(id = R.drawable.ic_exchange_rate), contentDescription = null) - } + } + DropdownMenuItem(onClick = { + intent.apply { + putExtra( + ExamActivityType::name.name, + ExamActivityType.JOIN_Association + ) } - DropdownMenuItem(onClick = { - intent.apply { - putExtra(ExamActivityType::name.name, ExamActivityType.JOIN_Association) - } - context.startActivity(intent) - model.close() - }) { - Row(verticalAlignment = Alignment.CenterVertically) { - Text(text = "申请入团") - Icon(painter = painterResource(id = R.drawable.ic_add_account), contentDescription = null) - } + context.startActivity(intent) + model.close() + }) { + Row(verticalAlignment = Alignment.CenterVertically) { + Text(text = "申请入团") + 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()) - } + } + 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() - 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) - } + NavHost( + navController = nav, + startDestination = AssociationMenu.startMenu.name + ) { + 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) } } + } } } @@ -149,15 +179,19 @@ class AssociationActivity: ComponentActivity() { * */ @Composable - private fun Member(){ + private fun Member() { MainFrame(background = { Background(image = BackgroundImage.AssociationMain) }) { - val searchWeight=0.2F - Search(modifier = Modifier - .fillMaxWidth() - .weight(searchWeight)) - MemberList(modifier = Modifier - .fillMaxWidth() - .weight(1 - searchWeight)) + val searchWeight = 0.2F + Search( + modifier = Modifier + .fillMaxWidth() + .weight(searchWeight) + ) + MemberList( + modifier = Modifier + .fillMaxWidth() + .weight(1 - searchWeight) + ) } } @@ -167,20 +201,33 @@ class AssociationActivity: ComponentActivity() { * */ @Composable - private fun Search(modifier:Modifier=Modifier, model: MemberViewModel= viewModel(), scaffoldModel: ScaffoldModel= viewModel()){ + private fun Search( + modifier: Modifier = Modifier, + model: MemberViewModel = viewModel(), + scaffoldModel: ScaffoldModel = viewModel() + ) { Column(modifier = modifier.fillMaxSize()) { Spacer(modifier = Modifier.weight(0.5F)) - Row(modifier = Modifier - .fillMaxWidth() - .weight(0.5F),verticalAlignment = Alignment.CenterVertically) { + Row( + modifier = Modifier + .fillMaxWidth() + .weight(0.5F), verticalAlignment = Alignment.CenterVertically + ) { - val textFieldWeight=0.4F - val buttonWeight=0.2F - val spaceWeight=(1-textFieldWeight-buttonWeight)/3 + 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) + BaseTextField( + modifier = Modifier.weight(textFieldWeight), + form = model.name, + singeLine = true + ) Spacer(modifier = Modifier.weight(spaceWeight)) - OutlinedButton(onClick = { model.search { scaffoldModel.update(message=it) } },modifier = Modifier.weight(buttonWeight)) { + OutlinedButton( + onClick = { model.search { scaffoldModel.update(message = it) } }, + modifier = Modifier.weight(buttonWeight) + ) { Text(text = model.search) } Spacer(modifier = Modifier.weight(spaceWeight)) @@ -193,15 +240,19 @@ class AssociationActivity: ComponentActivity() { * */ @Composable - private fun MemberList(modifier: Modifier=Modifier, model: MemberViewModel=viewModel(), scaffoldModel: ScaffoldModel= viewModel()){ - val list:MutableList? by model.memberList.observeAsState() - val listState= rememberLazyListState() - LazyColumn(state = listState,modifier = modifier) { + private fun MemberList( + modifier: Modifier = Modifier, + model: MemberViewModel = viewModel(), + scaffoldModel: ScaffoldModel = viewModel() + ) { + val list: MutableList? by model.memberList.observeAsState() + val listState = rememberLazyListState() + LazyColumn(state = listState, modifier = modifier) { list?.forEach { item { Column { Spacer(modifier = Modifier.height(10.dp)) - Row{ + Row { val weight = 1F / 3 Spacer(modifier = Modifier.weight(weight)) Card( @@ -218,11 +269,19 @@ class AssociationActivity: ComponentActivity() { } } item { - Row(horizontalArrangement = Arrangement.Center,modifier = Modifier.fillMaxWidth()) { - IconButton(onClick = { model.loadMore{ - scaffoldModel.update(message=it) - } }) { - Icon(painter = painterResource(id = R.drawable.ic_arrow_down), contentDescription = null) + Row( + horizontalArrangement = Arrangement.Center, + modifier = Modifier.fillMaxWidth() + ) { + IconButton(onClick = { + model.loadMore { + scaffoldModel.update(message = it) + } + }) { + Icon( + painter = painterResource(id = R.drawable.ic_arrow_down), + contentDescription = null + ) } } @@ -235,15 +294,17 @@ class AssociationActivity: ComponentActivity() { * */ @Composable - private fun Main(){ + private fun Main() { MainFrame(background = { - Background(image = BackgroundImage.AssociationMain,alpha = 0.7F) + Background(image = BackgroundImage.AssociationMain, alpha = 0.7F) }) { - val nameW=0.1F - val cardW=0.66F*0.4F - Name(modifier = Modifier - .fillMaxWidth() - .weight(nameW)) + val nameW = 0.1F + val cardW = 0.66F * 0.4F + Name( + modifier = Modifier + .fillMaxWidth() + .weight(nameW) + ) DescCard( modifier = Modifier .weight(cardW) @@ -253,7 +314,7 @@ class AssociationActivity: ComponentActivity() { Commander( modifier = Modifier.weight(cardW) ) - Showcase(modifier = Modifier.weight(1F-nameW-cardW-cardW)) + Showcase(modifier = Modifier.weight(1F - nameW - cardW - cardW)) } } @@ -263,20 +324,22 @@ class AssociationActivity: ComponentActivity() { * @param modifier */ @Composable - private fun Name(modifier: Modifier){ + private fun Name(modifier: Modifier) { Box(modifier = modifier) { Image( painter = painterResource(id = R.drawable.association_name_border), contentDescription = null, contentScale = ContentScale.FillBounds, - modifier=Modifier.fillMaxSize() + modifier = Modifier.fillMaxSize() ) - Column{ + Column { Spacer(modifier = Modifier.weight(1.7F / 3)) - Row(modifier = Modifier - .fillMaxWidth() - .weight(1F / 3), - horizontalArrangement = Arrangement.Center) { + Row( + modifier = Modifier + .fillMaxWidth() + .weight(1F / 3), + horizontalArrangement = Arrangement.Center + ) { Text(text = "社团名字") } Spacer(modifier = Modifier.weight(0.3F / 3)) @@ -290,11 +353,12 @@ class AssociationActivity: ComponentActivity() { * @param modifier */ @Composable - private fun Commander(modifier: Modifier){ - Box(modifier=modifier,contentAlignment = Alignment.Center){ - Row(modifier = Modifier.fillMaxWidth(),horizontalArrangement = Arrangement.Center) { + private fun Commander(modifier: Modifier) { + Box(modifier = modifier, contentAlignment = Alignment.Center) { + Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.Center) { - Image(painter = painterResource(id = R.drawable.persion_name_border), + Image( + painter = painterResource(id = R.drawable.persion_name_border), contentDescription = null ) } @@ -308,12 +372,17 @@ class AssociationActivity: ComponentActivity() { * @param modifier */ @Composable - private fun Showcase(modifier: Modifier){ - Box(modifier = modifier,contentAlignment = Alignment.Center) { - Image(painter = painterResource(id = R.drawable.showcase_border), + 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) + modifier = Modifier.fillMaxSize() + ) + Image( + painter = painterResource(id = R.drawable.ic_launcher_foreground), + contentDescription = null + ) } } @@ -322,16 +391,25 @@ class AssociationActivity: ComponentActivity() { * */ @Composable - private fun AssociationList(){ - MainFrame(background = { Background(image = BackgroundImage.AssociationMain,alpha = 07F) }) { - val onGoWeight=0.3F - OngoingActivity(modifier = Modifier - .weight(onGoWeight) - .fillMaxWidth()) - HistoryActivityList(modifier = Modifier - .fillMaxWidth() - .weight(1 - onGoWeight) - .border(width = 1.dp, color = MaterialTheme.colors.onBackground)) + private fun AssociationList() { + MainFrame(background = { + Background( + image = BackgroundImage.AssociationMain, + alpha = 07F + ) + }) { + val onGoWeight = 0.3F + OngoingActivity( + modifier = Modifier + .weight(onGoWeight) + .fillMaxWidth() + ) + HistoryActivityList( + modifier = Modifier + .fillMaxWidth() + .weight(1 - onGoWeight) + .border(width = 1.dp, color = MaterialTheme.colors.onBackground) + ) } } @@ -340,16 +418,19 @@ class AssociationActivity: ComponentActivity() { * */ @Composable - private fun OngoingActivity(modifier: Modifier=Modifier,model:OngoingActViewModel= viewModel()){ - val context= LocalContext.current + private fun OngoingActivity( + modifier: Modifier = Modifier, + model: OngoingActViewModel = viewModel() + ) { + val context = LocalContext.current val act by model.act.observeAsState() Row(modifier = modifier.clickable(onClick = { - context.startActivity(Intent(context,ActivityDetailActivity::class.java)) - }),horizontalArrangement = Arrangement.Center) { - val weight=0.5F - val spaceWeight=(1-0.5F)/2 + context.startActivity(Intent(context, ActivityDetailActivity::class.java)) + }), horizontalArrangement = Arrangement.Center) { + val weight = 0.5F + val spaceWeight = (1 - 0.5F) / 2 Spacer(modifier = Modifier.weight(spaceWeight)) - Poster(id = R.drawable.ic_launcher_foreground,modifier = Modifier.weight(weight)) + Poster(id = R.drawable.ic_launcher_foreground, modifier = Modifier.weight(weight)) Spacer(modifier = Modifier.weight(spaceWeight)) } @@ -361,16 +442,20 @@ class AssociationActivity: ComponentActivity() { * @param modifier */ @Composable - private fun HistoryActivityList(modifier: Modifier,model:HistoryActViewModel= viewModel(),scaffoldModel: ScaffoldModel= viewModel()){ - val listState= rememberLazyListState() + private fun HistoryActivityList( + modifier: Modifier, + model: HistoryActViewModel = viewModel(), + scaffoldModel: ScaffoldModel = viewModel() + ) { + val listState = rememberLazyListState() val list by model.data.observeAsState() - LazyColumn(state = listState,modifier = modifier) { + LazyColumn(state = listState, modifier = modifier) { list?.chunked(2)?.forEach { item { - Row(modifier=Modifier.fillMaxWidth()) { - HistoryActivity(modifier = Modifier.weight(0.4F),it[0]) + Row(modifier = Modifier.fillMaxWidth()) { + HistoryActivity(modifier = Modifier.weight(0.4F), it[0]) Spacer(modifier = Modifier.weight(0.2F)) - if (it.size==2) HistoryActivity(modifier = Modifier.weight(0.4F),it[1]) + if (it.size == 2) HistoryActivity(modifier = Modifier.weight(0.4F), it[1]) else Box(modifier = Modifier.weight(0.4F)) } Spacer(modifier = Modifier.height(10.dp)) @@ -378,8 +463,8 @@ class AssociationActivity: ComponentActivity() { } } } - if(listState.layoutInfo.totalItemsCount-listState.firstVisibleItemIndex==model.initSize/2-1){ - model.loadMore { scaffoldModel.update(message=it) } + if (listState.layoutInfo.totalItemsCount - listState.firstVisibleItemIndex == model.initSize / 2 - 1) { + model.loadMore { scaffoldModel.update(message = it) } } } @@ -389,17 +474,21 @@ class AssociationActivity: ComponentActivity() { * @param modifier */ @Composable - private fun HistoryActivity(modifier: Modifier,historyActVo: HistoryActVo){ - val context= LocalContext.current - Box(modifier=modifier.clickable(onClick = { - context.startActivity(Intent(context,ActivityDetailActivity::class.java)) - }),contentAlignment = Alignment.Center){ - Image(painter = painterResource(id = R.drawable.history_activity_border), + private fun HistoryActivity(modifier: Modifier, historyActVo: HistoryActVo) { + val context = LocalContext.current + Box(modifier = modifier.clickable(onClick = { + context.startActivity(Intent(context, ActivityDetailActivity::class.java)) + }), contentAlignment = Alignment.Center) { + Image( + painter = painterResource(id = R.drawable.history_activity_border), contentDescription = null, - modifier = Modifier.fillMaxSize()) - Image(painter = painterResource(id = R.drawable.ic_launcher_foreground), + modifier = Modifier.fillMaxSize() + ) + Image( + painter = painterResource(id = R.drawable.ic_launcher_foreground), contentDescription = null, - modifier = Modifier.fillMaxSize()) + modifier = Modifier.fillMaxSize() + ) Text(text = historyActVo.name) } @@ -407,7 +496,7 @@ class AssociationActivity: ComponentActivity() { @Preview @Composable - fun NamePreview(){ + fun NamePreview() { Divider(color = MaterialTheme.colors.background) } } diff --git a/app/src/main/java/com/gyf/csams/association/ui/ExamActivity.kt b/app/src/main/java/com/gyf/csams/association/ui/ExamActivity.kt index ce80f90..be551dd 100644 --- a/app/src/main/java/com/gyf/csams/association/ui/ExamActivity.kt +++ b/app/src/main/java/com/gyf/csams/association/ui/ExamActivity.kt @@ -23,23 +23,22 @@ import com.gyf.csams.association.model.* import com.gyf.csams.uikit.* - /** * 题库管理 * */ class ExamActivity : ComponentActivity() { - lateinit var activityType:ExamActivityType + lateinit var activityType: ExamActivityType override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - activityType=intent?.getSerializableExtra(ExamActivityType::name.name) as ExamActivityType + activityType = intent?.getSerializableExtra(ExamActivityType::name.name) as ExamActivityType setContent { Body { scaffoldState -> - MainFrame(background = { Background(image = BackgroundImage.Exam,alpha = 0.6F) }) { + MainFrame(background = { Background(image = BackgroundImage.Exam, alpha = 0.6F) }) { Spacer(modifier = Modifier.weight(0.1F)) Title(modifier = Modifier.weight(0.1F)) Exam(modifier = Modifier.weight(0.8F)) @@ -50,8 +49,6 @@ class ExamActivity : ComponentActivity() { } - - /** * 底部按钮 * @@ -65,14 +62,14 @@ class ExamActivity : ComponentActivity() { val context = LocalContext.current as ExamActivity Row(modifier = modifier, horizontalArrangement = Arrangement.Center) { - when(context.activityType){ - ExamActivityType.SET_EXAM->OutlinedButton(onClick = { - model.updateExam { scaffoldModel.update(message=it) } + when (context.activityType) { + ExamActivityType.SET_EXAM -> OutlinedButton(onClick = { + model.updateExam { scaffoldModel.update(message = it) } }, modifier = Modifier.background(color = MaterialTheme.colors.primary)) { Text(text = model.updateExam) } - ExamActivityType.JOIN_Association->OutlinedButton(onClick = { - model.postAnswer { scaffoldModel.update(message=it) } + ExamActivityType.JOIN_Association -> OutlinedButton(onClick = { + model.postAnswer { scaffoldModel.update(message = it) } }, modifier = Modifier.background(color = MaterialTheme.colors.primary)) { Text(text = model.postAnswer) } @@ -94,19 +91,19 @@ class ExamActivity : ComponentActivity() { */ @Composable private fun Title(modifier: Modifier = Modifier) { - val context= LocalContext.current as ExamActivity + val context = LocalContext.current as ExamActivity Row(horizontalArrangement = Arrangement.Center, modifier = modifier.fillMaxWidth()) { Text(text = context.activityType.menuName, style = MaterialTheme.typography.h4) } } @Composable - private fun ExamChild(it:Exam,examHeight: Dp,isAdd: Boolean=false){ - val questionWeight=0.3F + private fun ExamChild(it: Exam, examHeight: Dp, isAdd: Boolean = false) { + val questionWeight = 0.3F when (it) { is OpenQuestionsVo -> ExamOQ( openQuestionsVo = it, - modifier = Modifier.height(examHeight*questionWeight), + modifier = Modifier.height(examHeight * questionWeight), isAdd = isAdd ) is ChoiceQuestionVo -> ExamCQ( @@ -147,7 +144,7 @@ class ExamActivity : ComponentActivity() { OutlinedButton(onClick = { model.switchType(it) }) { Text(text = "切换到${if (newExam is ChoiceQuestionVo) "开放题" else "选择题"}") } - ExamChild(it = it, examHeight = examHeight,isAdd = true) + ExamChild(it = it, examHeight = examHeight, isAdd = true) } } } @@ -163,7 +160,7 @@ class ExamActivity : ComponentActivity() { } if (listState.layoutInfo.totalItemsCount - listState.firstVisibleItemIndex == model.initSize / 2 - 1) { - model.loadMore { scaffoldModel.update(message=it) } + model.loadMore { scaffoldModel.update(message = it) } } @@ -191,10 +188,12 @@ class ExamActivity : ComponentActivity() { * */ @Composable - private fun ActionButton(modifier: Modifier = Modifier, isAdd: Boolean, - model: ExamViewModel= viewModel(), - scaffoldModel: ScaffoldModel= viewModel(), - exam: Exam) { + private fun ActionButton( + modifier: Modifier = Modifier, isAdd: Boolean, + model: ExamViewModel = viewModel(), + scaffoldModel: ScaffoldModel = viewModel(), + exam: Exam + ) { val list by model.data.observeAsState() val newExam by model.newExam.observeAsState() Box( @@ -202,20 +201,26 @@ class ExamActivity : ComponentActivity() { modifier = modifier ) { IconButton(onClick = { - if(isAdd){ - if((newExam?.question?.formValue?.value ?: "").isNotEmpty()){ - scaffoldModel.update(message=model.addTip,actionLabel = model.actionLabel){ + if (isAdd) { + if ((newExam?.question?.formValue?.value ?: "").isNotEmpty()) { + scaffoldModel.update( + message = model.addTip, + actionLabel = model.actionLabel + ) { model.addQuestion() } - }else{ + } else { scaffoldModel.update(message = model.questionIsNull) } - }else{ - if(list?.size==1){ + } else { + if (list?.size == 1) { scaffoldModel.update(model.deleteLeastOne) - }else{ - scaffoldModel.update(message=model.deleteTip,actionLabel = model.actionLabel){ + } else { + scaffoldModel.update( + message = model.deleteTip, + actionLabel = model.actionLabel + ) { model.deleteQuestion(exam = exam) } } @@ -242,15 +247,17 @@ class ExamActivity : ComponentActivity() { isAdd: Boolean = false ) { Row(modifier = modifier) { - val context= LocalContext.current as ExamActivity + val context = LocalContext.current as ExamActivity Question( exam = openQuestionsVo, modifier = - if(context.activityType==ExamActivityType.SET_EXAM) - Modifier.weight(0.8F).fillMaxHeight() + if (context.activityType == ExamActivityType.SET_EXAM) + Modifier + .weight(0.8F) + .fillMaxHeight() else Modifier ) - if(context.activityType==ExamActivityType.SET_EXAM){ + if (context.activityType == ExamActivityType.SET_EXAM) { ActionButton( modifier = Modifier .weight(0.2F) @@ -273,13 +280,15 @@ class ExamActivity : ComponentActivity() { choiceQuestionVo: ChoiceQuestionVo, isAdd: Boolean = false, model: ExamViewModel = viewModel(), - questionWeight:Float + questionWeight: Float ) { Row(modifier = modifier) { - val context= LocalContext.current as ExamActivity + val context = LocalContext.current as ExamActivity Column( - modifier = if(context.activityType==ExamActivityType.SET_EXAM) - Modifier.weight(0.8F).fillMaxHeight() + modifier = if (context.activityType == ExamActivityType.SET_EXAM) + Modifier + .weight(0.8F) + .fillMaxHeight() else Modifier ) { @@ -299,9 +308,11 @@ class ExamActivity : ComponentActivity() { choiceQuestionVo.answers.apply { Column { forEach { - Row(modifier = Modifier - .fillMaxWidth() - .weight(1F / ANSWER_SIZE)) { + Row( + modifier = Modifier + .fillMaxWidth() + .weight(1F / ANSWER_SIZE) + ) { val answerIndex: Int = indexOf(it) val click = { model.update( @@ -320,7 +331,7 @@ class ExamActivity : ComponentActivity() { } } - if(context.activityType==ExamActivityType.SET_EXAM) { + if (context.activityType == ExamActivityType.SET_EXAM) { ActionButton( modifier = Modifier .weight(0.2F) diff --git a/app/src/main/java/com/gyf/csams/association/ui/ReNameActivity.kt b/app/src/main/java/com/gyf/csams/association/ui/ReNameActivity.kt index 09fdbae..26fa03a 100644 --- a/app/src/main/java/com/gyf/csams/association/ui/ReNameActivity.kt +++ b/app/src/main/java/com/gyf/csams/association/ui/ReNameActivity.kt @@ -19,32 +19,31 @@ import com.gyf.csams.uikit.* * 社团重命名 * */ -class ReNameActivity: ComponentActivity() { +class ReNameActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { - Body { - scaffoldState -> - MainFrame(background = { Background(image = BackgroundImage.Rename) }) { - Spacer( - modifier = Modifier - .weight(0.2F) - ) - Title(modifier = Modifier.weight(0.1F)) + Body { scaffoldState -> + MainFrame(background = { Background(image = BackgroundImage.Rename) }) { + Spacer( + modifier = Modifier + .weight(0.2F) + ) + Title(modifier = Modifier.weight(0.1F)) - OldName(modifier = Modifier.weight(0.1F)) + OldName(modifier = Modifier.weight(0.1F)) - NewName(modifier = Modifier.weight(0.1F)) + NewName(modifier = Modifier.weight(0.1F)) - Cause(modifier = Modifier.weight(0.2F)) + Cause(modifier = Modifier.weight(0.2F)) - Spacer(modifier = Modifier.height(10.dp)) - BottomButton(modifier = Modifier.weight(0.1F)) + Spacer(modifier = Modifier.height(10.dp)) + BottomButton(modifier = Modifier.weight(0.1F)) - Spacer(modifier = Modifier.weight(1-0.2F*2-0.1F*4)) - ShowSnackbar(scaffoldState = scaffoldState) - } + Spacer(modifier = Modifier.weight(1 - 0.2F * 2 - 0.1F * 4)) + ShowSnackbar(scaffoldState = scaffoldState) + } } } } @@ -54,9 +53,9 @@ class ReNameActivity: ComponentActivity() { * */ @Composable - private fun Title(modifier: Modifier=Modifier,model:RenameViewModel= viewModel()){ - Row(modifier = modifier.fillMaxWidth(),horizontalArrangement = Arrangement.Center) { - Text(text = model.menuName,style = MaterialTheme.typography.h4) + private fun Title(modifier: Modifier = Modifier, model: RenameViewModel = viewModel()) { + Row(modifier = modifier.fillMaxWidth(), horizontalArrangement = Arrangement.Center) { + Text(text = model.menuName, style = MaterialTheme.typography.h4) } } @@ -65,8 +64,8 @@ class ReNameActivity: ComponentActivity() { * */ @Composable - private fun OldName(modifier: Modifier=Modifier,model:RenameViewModel= viewModel()){ - BaseTextField(form = model.oldName,modifier = modifier.fillMaxWidth(),singeLine = true) + private fun OldName(modifier: Modifier = Modifier, model: RenameViewModel = viewModel()) { + BaseTextField(form = model.oldName, modifier = modifier.fillMaxWidth(), singeLine = true) } /** @@ -74,8 +73,8 @@ class ReNameActivity: ComponentActivity() { * */ @Composable - private fun NewName(modifier: Modifier=Modifier,model:RenameViewModel= viewModel()){ - BaseTextField(form = model.newName,modifier = modifier.fillMaxWidth(),singeLine = true) + private fun NewName(modifier: Modifier = Modifier, model: RenameViewModel = viewModel()) { + BaseTextField(form = model.newName, modifier = modifier.fillMaxWidth(), singeLine = true) } /** @@ -83,8 +82,8 @@ class ReNameActivity: ComponentActivity() { * */ @Composable - private fun Cause(modifier: Modifier=Modifier,model:RenameViewModel= viewModel()){ - BaseTextField(form = model.cause,modifier = modifier.fillMaxWidth()) + private fun Cause(modifier: Modifier = Modifier, model: RenameViewModel = viewModel()) { + BaseTextField(form = model.cause, modifier = modifier.fillMaxWidth()) } /** @@ -94,13 +93,17 @@ class ReNameActivity: ComponentActivity() { * @param model */ @Composable - private fun BottomButton(modifier: Modifier=Modifier,model:RenameViewModel= viewModel(),scaffoldModel: ScaffoldModel= viewModel()){ + private fun BottomButton( + modifier: Modifier = Modifier, + model: RenameViewModel = viewModel(), + scaffoldModel: ScaffoldModel = viewModel() + ) { Row(modifier = modifier.fillMaxWidth()) { - val weight=(1-0.5F)/2 - val context= LocalContext.current as ReNameActivity + val weight = (1 - 0.5F) / 2 + val context = LocalContext.current as ReNameActivity Spacer(modifier = Modifier.weight(weight)) - Row(modifier=Modifier.weight(0.5F)) { - OutlinedButton(onClick = { model.post{scaffoldModel.update(message=it)} }) { + Row(modifier = Modifier.weight(0.5F)) { + OutlinedButton(onClick = { model.post { scaffoldModel.update(message = it) } }) { Text(text = model.postDesc) } Spacer(modifier = Modifier.width(10.dp)) diff --git a/app/src/main/java/com/gyf/csams/association/ui/RegAssociationActivity.kt b/app/src/main/java/com/gyf/csams/association/ui/RegAssociationActivity.kt index 267d28a..58a7d20 100644 --- a/app/src/main/java/com/gyf/csams/association/ui/RegAssociationActivity.kt +++ b/app/src/main/java/com/gyf/csams/association/ui/RegAssociationActivity.kt @@ -43,37 +43,41 @@ import com.orhanobut.logger.Logger * 注册社团 * */ -class RegAssociationActivity: ComponentActivity(){ +class RegAssociationActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { CSAMSTheme { - Body { - scaffoldState -> - MainFrame(background = { Background(BackgroundImage.RegAssociation,alpha = 0.5F) }) { - Spacer( - modifier = Modifier - .weight(0.1F) - ) - Title() - Name() - Desc( - modifier = Modifier - .weight(0.1F) - .fillMaxWidth() - ) - Spacer(modifier = Modifier.weight(0.05F)) - Logo( - modifier = Modifier - .weight(0.2F) - .fillMaxWidth() - ) - Spacer(modifier = Modifier.weight(0.05F)) - BottomButton(modifier = Modifier.fillMaxWidth()) - Spacer(modifier = Modifier.weight(0.05F)) - - ShowSnackbar(scaffoldState = scaffoldState) - } + Body { scaffoldState -> + MainFrame(background = { + Background( + BackgroundImage.RegAssociation, + alpha = 0.5F + ) + }) { + Spacer( + modifier = Modifier + .weight(0.1F) + ) + Title() + Name() + Desc( + modifier = Modifier + .weight(0.1F) + .fillMaxWidth() + ) + Spacer(modifier = Modifier.weight(0.05F)) + Logo( + modifier = Modifier + .weight(0.2F) + .fillMaxWidth() + ) + Spacer(modifier = Modifier.weight(0.05F)) + BottomButton(modifier = Modifier.fillMaxWidth()) + Spacer(modifier = Modifier.weight(0.05F)) + + ShowSnackbar(scaffoldState = scaffoldState) + } } } } @@ -86,21 +90,22 @@ class RegAssociationActivity: ComponentActivity(){ * @param modifier */ @Composable - private fun Logo(model:RegAssociationViewModel= viewModel(),modifier: Modifier) { - val photoIntent=Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI) + private fun Logo(model: RegAssociationViewModel = viewModel(), modifier: Modifier) { + val photoIntent = Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI) photoIntent.type = "image/*" - val uri:Uri? by model.picture.observeAsState() - - val resultLauncher=rememberLauncherForActivityResult(contract = ActivityResultContracts.StartActivityForResult()) { - when(it.resultCode){ - Activity.RESULT_OK->{ - Logger.i("uri=${it.data?.data}") - it.data?.data?.let { it1 -> model.setPicture(it1) } + val uri: Uri? by model.picture.observeAsState() + + val resultLauncher = + rememberLauncherForActivityResult(contract = ActivityResultContracts.StartActivityForResult()) { + when (it.resultCode) { + Activity.RESULT_OK -> { + Logger.i("uri=${it.data?.data}") + it.data?.data?.let { it1 -> model.setPicture(it1) } + } } } - } - val loadPicture={ + val loadPicture = { //model.loadPicture(context) resultLauncher.launch(photoIntent) } @@ -118,14 +123,15 @@ class RegAssociationActivity: ComponentActivity(){ } + val context = LocalContext.current - val context= LocalContext.current - - Box(contentAlignment = Alignment.Center,modifier = modifier) { - Row(verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.Center,modifier = Modifier + Box(contentAlignment = Alignment.Center, modifier = modifier) { + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.Center, modifier = Modifier .fillMaxSize() - .border(width = 1.dp, color = Color.Black)) { + .border(width = 1.dp, color = Color.Black) + ) { if (uri == null) { OutlinedButton(onClick = { @@ -147,19 +153,28 @@ class RegAssociationActivity: ComponentActivity(){ } } else { uri.let { - if(it!=null){ + if (it != null) { Row { - Image(bitmap = BitmapFactory.decodeStream(context.contentResolver.openInputStream(it)) - .asImageBitmap(), contentDescription = null) + Image( + bitmap = BitmapFactory.decodeStream( + context.contentResolver.openInputStream( + it + ) + ) + .asImageBitmap(), contentDescription = null + ) IconButton(onClick = { loadPicture() }) { - Image(painter = painterResource(id = R.drawable.ic_exchange_rate), contentDescription = null) + Image( + painter = painterResource(id = R.drawable.ic_exchange_rate), + contentDescription = null + ) } } - }else{ + } else { Text(text = model.errorPicture) } } @@ -174,18 +189,22 @@ class RegAssociationActivity: ComponentActivity(){ } @Composable - private fun BottomButton(modifier: Modifier=Modifier,scaffoldModel: ScaffoldModel= viewModel(),model:RegAssociationViewModel= viewModel()){ - val context= LocalContext.current as RegAssociationActivity - Row(modifier = modifier,horizontalArrangement = Arrangement.Center) { + private fun BottomButton( + modifier: Modifier = Modifier, + scaffoldModel: ScaffoldModel = viewModel(), + model: RegAssociationViewModel = viewModel() + ) { + val context = LocalContext.current as RegAssociationActivity + Row(modifier = modifier, horizontalArrangement = Arrangement.Center) { OutlinedButton(onClick = { - model.register { scaffoldModel.update(message=it) } - },modifier = Modifier.background(color = MaterialTheme.colors.primary)) { + model.register { scaffoldModel.update(message = it) } + }, modifier = Modifier.background(color = MaterialTheme.colors.primary)) { Text(text = model.register) } Spacer(modifier = Modifier.width(10.dp)) OutlinedButton(onClick = { context.onBackPressed() - },modifier = Modifier.background(color = MaterialTheme.colors.secondary)) { + }, modifier = Modifier.background(color = MaterialTheme.colors.secondary)) { Text(text = model.back) } } @@ -197,9 +216,9 @@ class RegAssociationActivity: ComponentActivity(){ * */ @Composable - private fun Title(model:RegAssociationViewModel= viewModel()){ - Row(modifier = Modifier.fillMaxWidth(),horizontalArrangement = Arrangement.Center) { - Text(text = model.frameDesc,style = MaterialTheme.typography.h4) + private fun Title(model: RegAssociationViewModel = viewModel()) { + Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.Center) { + Text(text = model.frameDesc, style = MaterialTheme.typography.h4) } } @@ -208,8 +227,8 @@ class RegAssociationActivity: ComponentActivity(){ * @param model */ @Composable - private fun Name(model:RegAssociationViewModel= viewModel()){ - BaseTextField(form = model.name,singeLine = true,modifier = Modifier.fillMaxWidth()) + private fun Name(model: RegAssociationViewModel = viewModel()) { + BaseTextField(form = model.name, singeLine = true, modifier = Modifier.fillMaxWidth()) } /** @@ -217,8 +236,8 @@ class RegAssociationActivity: ComponentActivity(){ * @param model */ @Composable - private fun Desc(model:RegAssociationViewModel= viewModel(),modifier:Modifier){ - BaseTextField(form = model.desc,modifier = modifier) + private fun Desc(model: RegAssociationViewModel = viewModel(), modifier: Modifier) { + BaseTextField(form = model.desc, modifier = modifier) } } diff --git a/app/src/main/java/com/gyf/csams/main/model/MainViewModel.kt b/app/src/main/java/com/gyf/csams/main/model/MainViewModel.kt index 4f4fb7c..ebe4739 100644 --- a/app/src/main/java/com/gyf/csams/main/model/MainViewModel.kt +++ b/app/src/main/java/com/gyf/csams/main/model/MainViewModel.kt @@ -20,21 +20,20 @@ import kotlinx.coroutines.launch * 跑马灯 * */ -class MarqueeViewModel:ViewModel() { +class MarqueeViewModel : ViewModel() { - val marqueeTexts= listOf("床前明月光","疑是地上霜","举头望明月","低头思故乡") + val marqueeTexts = listOf("床前明月光", "疑是地上霜", "举头望明月", "低头思故乡") - private val _marqueeIndex=MutableLiveData(0) - var marqueeIndex:LiveData = _marqueeIndex - private var marqueeJob:Job? = null + private val _marqueeIndex = MutableLiveData(0) + var marqueeIndex: LiveData = _marqueeIndex + private var marqueeJob: Job? = null - - fun addAsync(delayMillis:Int){ - if(marqueeJob == null || marqueeJob?.isCompleted==true) { + fun addAsync(delayMillis: Int) { + if (marqueeJob == null || marqueeJob?.isCompleted == true) { marqueeJob = viewModelScope.launch { _marqueeIndex.postValue( - if (_marqueeIndex.value == marqueeTexts.size-1) 0 else _marqueeIndex.value?.plus( + if (_marqueeIndex.value == marqueeTexts.size - 1) 0 else _marqueeIndex.value?.plus( 1 ) ) @@ -48,25 +47,30 @@ class MarqueeViewModel:ViewModel() { * 海报轮播 * */ -class CarouselViewModel:ViewModel(){ - val imageList= listOf(R.drawable.ic_launcher_foreground,R.drawable.ic_account_fill,R.drawable.ic_all_fill,R.drawable.ic_home_fill) +class CarouselViewModel : ViewModel() { + val imageList = listOf( + R.drawable.ic_launcher_foreground, + R.drawable.ic_account_fill, + R.drawable.ic_all_fill, + R.drawable.ic_home_fill + ) - private val _index=MutableLiveData(0) + private val _index = MutableLiveData(0) - val index:LiveData = _index + val index: LiveData = _index - private var job:Job? = null + private var job: Job? = null init { start() } - private fun start(){ + private fun start() { job = viewModelScope.launch { - do{ - _index.postValue(if (_index.value==imageList.size-1) 0 else _index.value?.plus(1)) + do { + _index.postValue(if (_index.value == imageList.size - 1) 0 else _index.value?.plus(1)) delay(5000) - }while (job?.isActive==true) + } while (job?.isActive == true) } } @@ -77,25 +81,25 @@ class CarouselViewModel:ViewModel(){ * * @property name 社团名称 */ -data class AssociationDto(val name:String) +data class AssociationDto(val name: String) /** * 主页 * */ -class MainViewModel:ViewModel(),SendInterface{ +class MainViewModel : ViewModel(), SendInterface { override val _openDialog: MutableLiveData = MutableLiveData() override val openDialog: LiveData = _openDialog - override val newContent: StringForm = StringForm(formDesc = "留言",textLength = 30) + override val newContent: StringForm = StringForm(formDesc = "留言", textLength = 30) override fun openDialog() { - _openDialog.value=true + _openDialog.value = true } override fun closeDialog() { - _openDialog.value=false + _openDialog.value = false } /** @@ -106,35 +110,25 @@ class MainViewModel:ViewModel(),SendInterface{ override fun send(callback: (message: String) -> Unit) { callback(NOT_IMPL_TIP) } - - /** - * TODO 打开通知 - * - * @param callback - */ - fun openNotification(callback: (value: String) -> Unit){ - callback(NOT_IMPL_TIP) - } } /** * 社团列表 * */ -class ListViewModel: ScrollList() { - val name = StringForm(formDesc = "社团名称",textLength = 5) +class ListViewModel : ScrollList() { + val name = StringForm(formDesc = "社团名称", textLength = 5) - val desc = StringForm(formDesc = "社团简介",textLength = 10) + val desc = StringForm(formDesc = "社团简介", textLength = 10) //社团列表加载数量 - val associationListSize=10 + val associationListSize = 10 //社团列表 - private val _associationList=MutableLiveData>(mutableListOf()) - val associationDto:LiveData> = _associationList - - val searchDesc="搜索" + private val _associationList = MutableLiveData>(mutableListOf()) + val associationDto: LiveData> = _associationList + val searchDesc = "搜索" /** @@ -142,7 +136,7 @@ class ListViewModel: ScrollList() { * * @param callback */ - fun search(callback: (value: String) -> Unit){ + fun search(callback: (value: String) -> Unit) { Logger.i("搜索条件[社团名称:${name.formValue.value},社团简介:${desc.formValue.value}]") callback(NOT_IMPL_TIP) } @@ -161,7 +155,8 @@ class ListViewModel: ScrollList() { override fun load() { viewModelScope.launch { _associationList.value?.apply { - repeat(10 + repeat( + 10 ) { add(AssociationDto(name = "社团${_associationList.value?.size}")) } @@ -178,10 +173,10 @@ class ListViewModel: ScrollList() { override fun loadMore(callback: (message: String) -> Unit) { viewModelScope.launch { _associationList.value?.apply { - val list= mutableListOf() + val list = mutableListOf() list.addAll(this) list.apply { - repeat(10){ + repeat(10) { add(AssociationDto(name = "社团${size}")) } } @@ -203,32 +198,40 @@ class ListViewModel: ScrollList() { * @property headImg 头像 * @property desc 个人简介 */ -data class InfoVo(val studentId:String,val name:String,val duty:String,val headImg:String,val desc:String) +data class InfoVo( + val studentId: String, + val name: String, + val duty: String, + val headImg: String, + val desc: String +) /** * 个人中心 * */ -class CenterViewModel:ViewModel(){ - val myAssociationDesc="我的社团" - val myJoinActivity="我参加的社团活动" - val myLikeActivity="我点赞的社团活动" - val myCollectActivity="我收藏的社团活动" +class CenterViewModel : ViewModel() { + val myAssociationDesc = "我的社团" + val myJoinActivity = "我参加的社团活动" + val myLikeActivity = "我点赞的社团活动" + val myCollectActivity = "我收藏的社团活动" - private val _info=MutableLiveData() - val info:LiveData = _info + private val _info = MutableLiveData() + val info: LiveData = _info init { load() } - private fun load(){ + private fun load() { viewModelScope.launch { - _info.value= InfoVo(studentId = randomNum(), + _info.value = InfoVo( + studentId = randomNum(), name = randomChinese(3), duty = randomChinese(3), headImg = "", - desc = randomChinese(10)) + desc = randomChinese(10) + ) } } diff --git a/app/src/main/java/com/gyf/csams/main/ui/MainActivity.kt b/app/src/main/java/com/gyf/csams/main/ui/MainActivity.kt index 06df68a..3848965 100644 --- a/app/src/main/java/com/gyf/csams/main/ui/MainActivity.kt +++ b/app/src/main/java/com/gyf/csams/main/ui/MainActivity.kt @@ -10,7 +10,6 @@ import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.* import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.rememberLazyListState -import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.* import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue @@ -31,6 +30,7 @@ import com.gyf.csams.activity.ui.ActivityDetailActivity import com.gyf.csams.association.ui.AssociationActivity import com.gyf.csams.association.ui.RegAssociationActivity import com.gyf.csams.main.model.* +import com.gyf.csams.message.ui.MessageActivity import com.gyf.csams.uikit.* import com.gyf.csams.uikit.theme.CSAMSTheme import com.gyf.csams.util.randomChinese @@ -90,14 +90,18 @@ class MainActivity : ComponentActivity() { Column( - modifier = Modifier.weight(0.3F).padding(10.dp), + modifier = Modifier + .weight(0.3F) + .padding(10.dp), ) { info?.let { - Row(modifier = Modifier - .fillMaxWidth() - .weight(0.7F) - .border(width = 1.dp, color = MaterialTheme.colors.background), - horizontalArrangement = Arrangement.SpaceBetween) { + Row( + modifier = Modifier + .fillMaxWidth() + .weight(0.7F) + .border(width = 1.dp, color = MaterialTheme.colors.background), + horizontalArrangement = Arrangement.SpaceBetween + ) { Image( painter = painterResource( id = R.drawable.ic_launcher_foreground @@ -122,7 +126,10 @@ class MainActivity : ComponentActivity() { Spacer(modifier = Modifier.weight(0.05F)) - Card(backgroundColor = MaterialTheme.colors.background,modifier = Modifier.weight(0.15F)) { + Card( + backgroundColor = MaterialTheme.colors.background, + modifier = Modifier.weight(0.15F) + ) { Row( modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.Center @@ -186,10 +193,15 @@ class MainActivity : ComponentActivity() { ) { Column(modifier = Modifier.weight(0.33F)) { Notification() - MessageBoard() - Spacer(modifier = Modifier.height(10.dp)) - ClubActivitiesTitle() - Spacer(modifier = Modifier.height(10.dp)) + Column( + modifier = Modifier + .fillMaxSize() + .padding(horizontal = 15.dp), + verticalArrangement = Arrangement.SpaceEvenly + ) { + MessageBoard() + ClubActivitiesTitle() + } } Column(modifier = Modifier.weight(0.66F)) { PosterWithDesc() @@ -366,10 +378,8 @@ class MainActivity : ComponentActivity() { * */ @Composable - private fun Notification( - mainViewModel: MainViewModel = viewModel(), - scaffoldModel: ScaffoldModel = viewModel() - ) { + private fun Notification() { + val context = LocalContext.current Row( horizontalArrangement = Arrangement.End, modifier = Modifier @@ -377,7 +387,7 @@ class MainActivity : ComponentActivity() { .padding(10.dp) ) { IconButton(onClick = { - mainViewModel.openNotification { scaffoldModel.update(message = it) } + context.startActivity(Intent(context, MessageActivity::class.java)) }) { Icon( painter = painterResource(id = R.drawable.ic_notification), @@ -388,37 +398,17 @@ class MainActivity : ComponentActivity() { } } - /** - * 圆角矩形边框 - * - */ - @Composable - private fun MyBorder(content: @Composable BoxScope.() -> Unit) { - Box(modifier = Modifier.padding(horizontal = 15.dp)) { - Box( - modifier = Modifier - .border( - width = 1.dp, - color = MaterialTheme.colors.onBackground, - shape = RoundedCornerShape(size = 20.dp) - ), - ) { - content() - } - } - } - /** * 留言板 * */ @Composable private fun MessageBoard( + modifier: Modifier = Modifier, model: MarqueeViewModel = viewModel(), - mainViewModel: MainViewModel = viewModel(), - scaffoldModel: ScaffoldModel = viewModel() + mainViewModel: MainViewModel = viewModel() ) { - MyBorder { + Card(modifier = modifier, backgroundColor = MaterialTheme.colors.background) { Row( verticalAlignment = Alignment.CenterVertically ) { @@ -454,12 +444,11 @@ class MainActivity : ComponentActivity() { * */ @Composable - private fun ClubActivitiesTitle() { - MyBorder { + private fun ClubActivitiesTitle(modifier: Modifier = Modifier) { + Card(modifier = modifier, backgroundColor = MaterialTheme.colors.background) { Row( modifier = Modifier - .fillMaxWidth() - .height(50.dp), + .fillMaxWidth(), horizontalArrangement = Arrangement.Center, verticalAlignment = Alignment.CenterVertically ) { diff --git a/app/src/main/java/com/gyf/csams/message/model/MessageViewModel.kt b/app/src/main/java/com/gyf/csams/message/model/MessageViewModel.kt new file mode 100644 index 0000000..d219d9f --- /dev/null +++ b/app/src/main/java/com/gyf/csams/message/model/MessageViewModel.kt @@ -0,0 +1,11 @@ +package com.gyf.csams.message.model + +import androidx.lifecycle.ViewModel + +enum class MessageType(val desc: String) { + System("系统通知") +} + +class MessageViewModel : ViewModel() { + val message = "消息" +} \ No newline at end of file diff --git a/app/src/main/java/com/gyf/csams/message/model/SysMessageViewModel.kt b/app/src/main/java/com/gyf/csams/message/model/SysMessageViewModel.kt new file mode 100644 index 0000000..94720fe --- /dev/null +++ b/app/src/main/java/com/gyf/csams/message/model/SysMessageViewModel.kt @@ -0,0 +1,136 @@ +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.csams.util.randomChinese +import com.gyf.csams.util.randomDateTime +import com.gyf.csams.util.randomNum +import kotlinx.coroutines.launch +import java.util.* +import kotlin.random.Random + +enum class SystemType(val desc: String) { + Join("入团通知"), + ActCheck("活动审核通知"), + Rename("社团重命名审核通知") +} + +/** + * 通知内容 + * + */ +sealed class MessageContent { + //通知时间 + abstract val createTime: Date + + //通知状态 + abstract val readState: Boolean + + //通知类型 + abstract val type: SystemType +} + +/** + * 入团通知 + * @param studentId 学号 + * @param studentName 姓名 + * + */ +data class JoinContent( + val studentId: Long, + val studentName: String, + override val createTime: Date, + override val readState: Boolean, + override val type: SystemType = SystemType.Join +) : MessageContent() + +/** + * 活动审核通知 + * + * @property activityId 活动id + * @property activityName 活动名 + * + */ +data class ActCheckContent( + val activityId: Long, val activityName: String, + override val createTime: Date, + override val readState: Boolean, + override val type: SystemType = SystemType.ActCheck +) : MessageContent() + +/** + * 社团重命名审核通知 + * + * @property oldAssociationName 老社团名字 + * @property newAssociationName 新社团名字 + * + */ +data class RenameContent( + val oldAssociationName: String, val newAssociationName: String, + override val createTime: Date, + override val readState: Boolean, + override val type: SystemType = SystemType.Rename +) : MessageContent() + +/** + * 系统通知数据状态管理 + * + */ +class SysMessageViewModel : ScrollList() { + val title = "系统通知" + + override val initSize: Int = 10 + + init { + load() + } + + /** + * TODO 加载通知 + * + */ + override fun load() { + viewModelScope.launch { + _data.value?.apply { + repeat(initSize) { + when ((0..2).random()) { + 0 -> add( + JoinContent( + createTime = randomDateTime(), + readState = Random.nextBoolean(), + studentId = randomNum().toLong(), + studentName = randomChinese(5) + ) + ) + 1 -> add( + ActCheckContent( + activityId = randomNum().toLong(), + activityName = randomChinese(5), + createTime = randomDateTime(), + readState = Random.nextBoolean() + ) + ) + 2 -> add( + RenameContent( + oldAssociationName = randomChinese(3), + newAssociationName = randomChinese(3), + createTime = randomDateTime(), + readState = Random.nextBoolean() + ) + ) + } + } + } + } + } + + /** + * TODO 加载更多通知 + * + * @param callback + */ + override fun loadMore(callback: (message: String) -> Unit) { + callback(NOT_IMPL_TIP) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/gyf/csams/message/ui/MessageActivity.kt b/app/src/main/java/com/gyf/csams/message/ui/MessageActivity.kt new file mode 100644 index 0000000..0d2f384 --- /dev/null +++ b/app/src/main/java/com/gyf/csams/message/ui/MessageActivity.kt @@ -0,0 +1,81 @@ +package com.gyf.csams.message.ui + +import android.content.Intent +import android.os.Bundle +import androidx.activity.ComponentActivity +import androidx.activity.compose.setContent +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.* +import androidx.compose.material.Divider +import androidx.compose.material.Icon +import androidx.compose.material.MaterialTheme +import androidx.compose.material.Text +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.unit.dp +import androidx.lifecycle.viewmodel.compose.viewModel +import com.gyf.csams.R +import com.gyf.csams.message.model.MessageType +import com.gyf.csams.message.model.MessageViewModel +import com.gyf.csams.uikit.* + +/** + * 消息界面 + * + */ +class MessageActivity : ComponentActivity() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + setContent { + Body { scaffoldState -> + val model: MessageViewModel = viewModel() + val context = LocalContext.current + MainFrame(background = { + Background( + image = BackgroundImage.ActivityMessage, + alpha = 0.6F + ) + }) { + TextTopAppBar(title = model.message) + Spacer(modifier = Modifier.height(5.dp)) + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.Center + ) { + Column( + horizontalAlignment = Alignment.CenterHorizontally, + modifier = Modifier.clickable(onClick = { + context.startActivity( + Intent( + context, + SysMessageActivity::class.java + ) + ) + }) + ) { + Icon( + painter = painterResource(id = R.drawable.ic_notice), + contentDescription = null, + modifier = Modifier.size(30.dp) + ) + Text(text = MessageType.System.desc) + } + } + Spacer(modifier = Modifier.height(5.dp)) + Divider( + modifier = Modifier.height(10.dp), + color = MaterialTheme.colors.background + ) + + } + + + } + } + } + + +} \ No newline at end of file diff --git a/app/src/main/java/com/gyf/csams/message/ui/SysMessageActivity.kt b/app/src/main/java/com/gyf/csams/message/ui/SysMessageActivity.kt new file mode 100644 index 0000000..10d3a62 --- /dev/null +++ b/app/src/main/java/com/gyf/csams/message/ui/SysMessageActivity.kt @@ -0,0 +1,135 @@ +package com.gyf.csams.message.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.Card +import androidx.compose.material.MaterialTheme +import androidx.compose.material.Text +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.text.SpanStyle +import androidx.compose.ui.text.buildAnnotatedString +import androidx.compose.ui.text.withStyle +import androidx.compose.ui.unit.dp +import androidx.lifecycle.viewmodel.compose.viewModel +import com.gyf.csams.message.model.* +import com.gyf.csams.uikit.* +import com.gyf.csams.util.format + +/** + * 系统通知 + * + */ +class SysMessageActivity : ComponentActivity() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + setContent { + Body { scaffoldState -> + MainFrame(background = { + Background( + image = BackgroundImage.ActivityMessage, + alpha = 0.6F + ) + }) { + TextTopAppBar(modifier = Modifier.weight(0.1F), title = MessageType.System.desc) + Spacer(modifier = Modifier.weight(0.05F)) + MessageList(modifier = Modifier.weight(0.8F)) + } + } + } + } + + @Composable + private fun MessageList( + modifier: Modifier = Modifier, + model: SysMessageViewModel = viewModel() + ) { + val listState = rememberLazyListState() + val list by model.data.observeAsState() + Box(modifier = modifier.padding(10.dp)) { + LazyColumn(state = listState) { + list?.forEach { + item { + MessageItem(content = it) + Spacer(modifier = Modifier.height(10.dp)) + } + } + } + } + } + + @Composable + private fun MessageItem(modifier: Modifier = Modifier, content: MessageContent) { + Card(modifier = modifier, backgroundColor = MaterialTheme.colors.background) { + Column(modifier = Modifier.padding(10.dp)) { + Text(text = content.type.desc, style = MaterialTheme.typography.h5) + Spacer(modifier = Modifier.height(5.dp)) + + Card( + backgroundColor = MaterialTheme.colors.background, + modifier = Modifier + .fillMaxWidth() + .padding(10.dp) + ) { + when (content) { + is JoinContent -> JoinMessage(content = content) + is ActCheckContent -> ActCheckMessage(content = content) + is RenameContent -> RenameMessage(content = content) + } + } + + Spacer(modifier = Modifier.height(10.dp)) + Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.End) { + Text(text = content.createTime.format()) + } + } + } + } + + @Composable + private fun JoinMessage(content: JoinContent) { + Text(buildAnnotatedString { + withStyle( + style = MaterialTheme.typography.subtitle1.toSpanStyle() + .copy(color = MaterialTheme.colors.primary) + ) { + append(content.studentName) + } + append("申请进入社团") + }) + } + + @Composable + private fun ActCheckMessage(content: ActCheckContent) { + Text(buildAnnotatedString { + append("\"") + withStyle(style = SpanStyle(color = MaterialTheme.colors.primary)) { + append(content.activityName) + } + append("\"活动审核不通过") + }) + } + + @Composable + private fun RenameMessage(content: RenameContent) { + Text(buildAnnotatedString { + withStyle(style = SpanStyle(color = MaterialTheme.colors.primary)) { + append(content.oldAssociationName) + } + append("重命名为") + withStyle(style = SpanStyle(color = MaterialTheme.colors.secondary)) { + append(content.newAssociationName) + } + append("审核通过") + }) + } + +} + diff --git a/app/src/main/java/com/gyf/csams/uikit/BaseView.kt b/app/src/main/java/com/gyf/csams/uikit/BaseView.kt index 0630f54..b13cbce 100644 --- a/app/src/main/java/com/gyf/csams/uikit/BaseView.kt +++ b/app/src/main/java/com/gyf/csams/uikit/BaseView.kt @@ -24,7 +24,6 @@ import androidx.compose.ui.platform.LocalFocusManager import androidx.compose.ui.res.painterResource import androidx.compose.ui.text.input.ImeAction import androidx.compose.ui.text.style.TextOverflow -import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData @@ -90,7 +89,12 @@ enum class MainMenu( * @param onClick */ @Composable -fun MenuIconButton(_menu: MainMenu, menu: MainMenu, modifier: Modifier=Modifier, onClick: () -> Unit) { +fun MenuIconButton( + _menu: MainMenu, + menu: MainMenu, + modifier: Modifier = Modifier, + onClick: () -> Unit +) { Row( modifier = modifier, horizontalArrangement = Arrangement.Center ) { @@ -113,7 +117,7 @@ fun MenuIconButton(_menu: MainMenu, menu: MainMenu, modifier: Modifier=Modifier, @Composable fun MainBottomAppBar(menu: MainMenu, nav: NavHostController, modifier: Modifier = Modifier) { BottomAppBar(backgroundColor = MaterialTheme.colors.background, modifier = modifier) { - Row(Modifier.fillMaxWidth(),horizontalArrangement = Arrangement.SpaceBetween) { + Row(Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween) { MenuIconButton(_menu = menu, menu = MainMenu.Main, onClick = { nav.navigate(MainMenu.Main.name) }) MenuIconButton(_menu = menu, menu = MainMenu.List, @@ -130,7 +134,7 @@ fun MainBottomAppBar(menu: MainMenu, nav: NavHostController, modifier: Modifier * 顶部菜单 * */ -interface TopMenuInterface{ +interface TopMenuInterface { /** * 当前菜单 */ @@ -142,59 +146,59 @@ interface TopMenuInterface{ * * @param menu */ - fun clickMenu(menu:T){ - _currentMenu.value=menu + fun clickMenu(menu: T) { + _currentMenu.value = menu } } -interface TopBarMenu{ - val menuName:String +interface TopBarMenu { + val menuName: String - val name:String + val name: String } -interface StartMenu{ - val startMenu:T +interface StartMenu { + val startMenu: T } /** * 社团菜单 * */ -enum class AssociationMenu(override val menuName: String):TopBarMenu { +enum class AssociationMenu(override val menuName: String) : TopBarMenu { Member("社团成员"), Main("社团主页"), ActivityList("活动列表"); - companion object Menu:StartMenu{ + companion object Menu : StartMenu { override val startMenu: AssociationMenu = Main } } -enum class ActivityDetailMenu(override val menuName:String):TopBarMenu{ +enum class ActivityDetailMenu(override val menuName: String) : TopBarMenu { Info("活动信息"), Photo("相册"), Member("活动成员"), BBS("交流区"); - companion object Menu:StartMenu{ + companion object Menu : StartMenu { override val startMenu: ActivityDetailMenu = Info } } -interface SendInterface{ +interface SendInterface { /** * 弹窗状态 */ - val _openDialog:MutableLiveData - val openDialog:LiveData + val _openDialog: MutableLiveData + val openDialog: LiveData /** * 编辑内容 */ - val newContent:StringForm + val newContent: StringForm /** * 打开弹窗 @@ -224,9 +228,9 @@ interface SendInterface{ * @param scaffoldModel */ @Composable -fun SendComment(model:T, scaffoldModel: ScaffoldModel= viewModel()){ +fun SendComment(model: T, scaffoldModel: ScaffoldModel = viewModel()) { val openDialog by model.openDialog.observeAsState() - if(openDialog==true) { + if (openDialog == true) { AlertDialog(onDismissRequest = { /*TODO*/ }, buttons = { Row( @@ -265,22 +269,51 @@ fun SendComment(model:T, scaffoldModel: ScaffoldModel= viewMod } /** - * 社团顶部菜单 + * 只包含返回按钮的顶部菜单 + * + * @param title + */ +@Composable +fun TextTopAppBar(modifier: Modifier = Modifier, title: String) { + Row( + modifier = modifier.fillMaxWidth(), + verticalAlignment = Alignment.CenterVertically + ) { + val context = LocalContext.current as Activity + Row(modifier = Modifier.weight(1F / 3)) { + IconButton(onClick = { + context.finish() + }) { + Icon( + painter = painterResource(id = R.drawable.ic_arrow_left), + contentDescription = null + ) + } + } + Row(modifier = Modifier.weight(1F / 3), horizontalArrangement = Arrangement.Center) { + Text(text = title, style = MaterialTheme.typography.h5) + } + Spacer(modifier = Modifier.weight(1F / 3)) + } +} + +/** + * 顶部菜单 * */ @Composable fun TextTopAppBar( - nav:NavHostController, - currentMenuName:String, - menuNames:Array, + nav: NavHostController, + currentMenuName: String, + menuNames: Array, iconMenu: (() -> Unit)? = null, - @DrawableRes icon:Int = R.drawable.ic_configuration, - dropMenuContent:@Composable () -> Unit = {}, + @DrawableRes icon: Int = R.drawable.ic_configuration, + dropMenuContent: @Composable () -> Unit = {}, ) { TopAppBar(backgroundColor = MaterialTheme.colors.secondary) { Row(modifier = Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically) { - val context= LocalContext.current as Activity - IconButton(onClick = {context.finish()}, modifier = Modifier.weight(0.1F)) { + val context = LocalContext.current as Activity + IconButton(onClick = { context.finish() }, modifier = Modifier.weight(0.1F)) { Icon( painter = painterResource(id = R.drawable.ic_arrow_left), contentDescription = null @@ -307,18 +340,18 @@ fun TextTopAppBar( } } } - if(iconMenu!=null) { + if (iconMenu != null) { IconButton(onClick = iconMenu, modifier = Modifier.weight(0.1F)) { Icon( painter = painterResource(id = icon), contentDescription = null ) } - }else{ + } else { Spacer(modifier = Modifier.weight(0.1F)) } } - if(iconMenu!=null) dropMenuContent() + if (iconMenu != null) dropMenuContent() } } @@ -480,17 +513,17 @@ fun ShowSnackbar(model: ScaffoldModel = viewModel(), scaffoldState: ScaffoldStat LaunchedEffect(scaffoldState) { launch { if (actionLabel != null) { - val result=scaffoldState.snackbarHostState.showSnackbar( + val result = scaffoldState.snackbarHostState.showSnackbar( message = message, actionLabel = actionLabel, duration = duration ) - when(result){ - SnackbarResult.ActionPerformed->{ + when (result) { + SnackbarResult.ActionPerformed -> { Logger.i("点击操作按钮") callback() } - SnackbarResult.Dismissed->{ + SnackbarResult.Dismissed -> { Logger.d("窗口消失") } } @@ -535,12 +568,20 @@ enum class BackgroundImage(@DrawableRes val id: Int) { //活动信息 ActivityInfo(R.drawable.mb_bg_fb_01), + //活动相册 ActivityPhoto(R.drawable.mb_bg_fb_02), + //活动成员 ActivityMember(R.drawable.mb_bg_fb_03), + //交流区 - ActivityBBS(R.drawable.mb_bg_fb_04) + ActivityBBS(R.drawable.mb_bg_fb_04), + + //系统通知 + ActivityMessage(R.drawable.mb_bg_fb_26) + + } /** @@ -631,7 +672,7 @@ fun Poster(modifier: Modifier = Modifier, @DrawableRes id: Int) { * */ @Composable -fun DescCard(modifier: Modifier,content:String) { +fun DescCard(modifier: Modifier, content: String) { Card( modifier = modifier, backgroundColor = Color.Transparent @@ -643,9 +684,11 @@ fun DescCard(modifier: Modifier,content:String) { contentScale = ContentScale.FillBounds, modifier = Modifier.fillMaxSize() ) - Column(modifier = Modifier - .fillMaxSize() - .padding(horizontal = 10.dp)) { + Column( + modifier = Modifier + .fillMaxSize() + .padding(horizontal = 10.dp) + ) { Spacer(modifier = Modifier.weight(0.15F)) Text( modifier = Modifier.weight(0.65F), @@ -665,10 +708,10 @@ fun AnimationTextPreview() { AnimationText(text = "6666") } -@Preview +//@Preview @Composable fun MyBottomAppBarPreview() { - val arr:List = listOf( + val arr: List = listOf( Arrangement.Start, Arrangement.End, Arrangement.Center, @@ -680,26 +723,33 @@ fun MyBottomAppBarPreview() { mutableStateOf(3) } Column(modifier = Modifier.fillMaxSize()) { - Row(modifier = Modifier.fillMaxWidth(),horizontalArrangement = Arrangement.SpaceEvenly) { + Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceEvenly) { OutlinedButton(onClick = { i += 1 }) { Text(text = "添加元素") } - if(i>1) { + if (i > 1) { OutlinedButton(onClick = { i -= 1 }) { Text(text = "删除元素") } } } arr.forEach { - Column(modifier = Modifier - .weight(1F / arr.size) - .border(width = 1.dp, color = MaterialTheme.colors.background)) { - Row(modifier = Modifier.fillMaxWidth(),horizontalArrangement = Arrangement.Center) { - Text(text = "$it",style = MaterialTheme.typography.h5) + Column( + modifier = Modifier + .weight(1F / arr.size) + .border(width = 1.dp, color = MaterialTheme.colors.background) + ) { + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.Center + ) { + Text(text = "$it", style = MaterialTheme.typography.h5) } - Row(modifier = Modifier.fillMaxSize(), + Row( + modifier = Modifier.fillMaxSize(), horizontalArrangement = it, - verticalAlignment = Alignment.CenterVertically) { + verticalAlignment = Alignment.CenterVertically + ) { repeat(i) { Text(text = "$it", style = MaterialTheme.typography.h3) } diff --git a/app/src/main/java/com/gyf/csams/uikit/ViewModel.kt b/app/src/main/java/com/gyf/csams/uikit/ViewModel.kt index cff2820..985563c 100644 --- a/app/src/main/java/com/gyf/csams/uikit/ViewModel.kt +++ b/app/src/main/java/com/gyf/csams/uikit/ViewModel.kt @@ -6,16 +6,16 @@ import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import com.orhanobut.logger.Logger -interface FormLength{ - val nameLengthError:String +interface FormLength { + val nameLengthError: String } -abstract class FormName(val formDesc:String){ - protected val _formValue= MutableLiveData() +abstract class FormName(val formDesc: String) { + protected val _formValue = MutableLiveData() val formValue: LiveData = _formValue - val formPlaceholder="请输入$formDesc" + val formPlaceholder = "请输入$formDesc" - abstract fun onChange(value:T) + abstract fun onChange(value: T) } @@ -28,55 +28,66 @@ abstract class FormName(val formDesc:String){ * * @param formDesc */ -open class StringForm(formDesc: String, val textLength: Int) : FormName(formDesc = formDesc), +open class StringForm(formDesc: String, val textLength: Int) : + FormName(formDesc = formDesc), FormLength { - constructor(formDesc: String,textLength: Int,value:String) : this(formDesc = formDesc,textLength = textLength) { - _formValue.value=value + constructor(formDesc: String, textLength: Int, value: String) : this( + formDesc = formDesc, + textLength = textLength + ) { + _formValue.value = value } - override val nameLengthError="${formDesc}不能超过最大长度$textLength" + override val nameLengthError = "${formDesc}不能超过最大长度$textLength" override fun onChange(value: String) { - if(value.length>textLength){ - _formValue.value=value.slice(IntRange(0,textLength-1)) - }else{ - _formValue.value=value + if (value.length > textLength) { + _formValue.value = value.slice(IntRange(0, textLength - 1)) + } else { + _formValue.value = value } Logger.i("${formDesc}更新值:${_formValue.value}") } } -data class SnackBar(val message:String?, val actionLabel:String?=null,val duration: SnackbarDuration=SnackbarDuration.Short, val callback: () -> Unit?) +data class SnackBar( + val message: String?, + val actionLabel: String? = null, + val duration: SnackbarDuration = SnackbarDuration.Short, + val callback: () -> Unit? +) /** * snackbar * */ -class ScaffoldModel:ViewModel(){ - private val _data=MutableLiveData() - val data:LiveData = _data - - fun update(message:String?=null,actionLabel: String? = null,callback: () -> Unit? = {}){ - if(message==null){ - _data.value=null - }else { - _data.value = SnackBar(message = message, actionLabel = actionLabel,callback = callback) +class ScaffoldModel : ViewModel() { + private val _data = MutableLiveData() + val data: LiveData = _data + + fun update(message: String? = null, actionLabel: String? = null, callback: () -> Unit? = {}) { + if (message == null) { + _data.value = null + } else { + _data.value = + SnackBar(message = message, actionLabel = actionLabel, callback = callback) } } } -abstract class ScrollList:ViewModel(){ - protected val _data=MutableLiveData>(mutableListOf()) - val data:LiveData> = _data +abstract class ScrollList : ViewModel() { + protected val _data = MutableLiveData>(mutableListOf()) + val data: LiveData> = _data - abstract val initSize:Int + abstract val initSize: Int //加载列表 abstract fun load() + //加载更多数据 - abstract fun loadMore(callback:(message:String) -> Unit) + abstract fun loadMore(callback: (message: String) -> Unit) } diff --git a/app/src/main/java/com/gyf/csams/util/GsonUtil.kt b/app/src/main/java/com/gyf/csams/util/GsonUtil.kt index 08df781..d99a1e2 100644 --- a/app/src/main/java/com/gyf/csams/util/GsonUtil.kt +++ b/app/src/main/java/com/gyf/csams/util/GsonUtil.kt @@ -6,77 +6,84 @@ import com.gyf.csams.association.model.* import com.gyf.csams.uikit.StringForm import java.lang.reflect.Type -class OpenQuestionsVoSerializer: JsonSerializer { +class OpenQuestionsVoSerializer : JsonSerializer { override fun serialize( vo: OpenQuestionsVo?, p1: Type?, p2: JsonSerializationContext? ): JsonElement { - val gson= Gson() + val gson = Gson() val c = JsonObject() c.add("examType", gson.toJsonTree(vo?.examType?.name)) - c.add("question",gson.toJsonTree(vo?.question?.formValue?.value)) - return c + c.add("question", gson.toJsonTree(vo?.question?.formValue?.value)) + return c } } -class OpenQuestionsVoDeserializer: JsonDeserializer { +class OpenQuestionsVoDeserializer : JsonDeserializer { override fun deserialize( json: JsonElement?, p1: Type?, p2: JsonDeserializationContext? ): OpenQuestionsVo { - val root=json?.asJsonObject - val value=root?.get("question")?.asString - val question= StringForm(formDesc = "问题",textLength = QUESTION_TEXT_LENGTH) + val root = json?.asJsonObject + val value = root?.get("question")?.asString + val question = StringForm(formDesc = "问题", textLength = QUESTION_TEXT_LENGTH) if (value != null) { question.onChange(value) return OpenQuestionsVo(question = question) - }else{ + } else { throw NullPointerException("问题无法解析!!!!") } } } -class ChoiceQuestionVoSerializer: JsonSerializer { +class ChoiceQuestionVoSerializer : JsonSerializer { override fun serialize( vo: ChoiceQuestionVo?, p1: Type?, p2: JsonSerializationContext? ): JsonElement { - val gson= Gson() + val gson = Gson() val c = JsonObject() c.add("examType", gson.toJsonTree(vo?.examType?.name)) - c.add("question",gson.toJsonTree(vo?.question?.formValue?.value)) - c.add("answers",gson.toJsonTree(vo?.answers)) - c.add("rightAnswer",gson.toJsonTree(vo?.rightAnswer)) + c.add("question", gson.toJsonTree(vo?.question?.formValue?.value)) + c.add("answers", gson.toJsonTree(vo?.answers)) + c.add("rightAnswer", gson.toJsonTree(vo?.rightAnswer)) return c } } -class ChoiceQuestionVoDeserializer: JsonDeserializer { +class ChoiceQuestionVoDeserializer : JsonDeserializer { override fun deserialize( json: JsonElement?, p1: Type?, p2: JsonDeserializationContext? ): ChoiceQuestionVo { - val root=json?.asJsonObject - val value=root?.get("question")?.asString - val question=StringForm(formDesc = "问题",textLength = QUESTION_TEXT_LENGTH) + val root = json?.asJsonObject + val value = root?.get("question")?.asString + val question = StringForm(formDesc = "问题", textLength = QUESTION_TEXT_LENGTH) if (value != null) { question.onChange(value) - val gson=Gson() - val answers:List = gson.fromJson(root.get("answers"),object : TypeToken>() {}.type) - if(answers.size!= ANSWER_SIZE){ + val gson = Gson() + val answers: List = + gson.fromJson(root.get("answers"), object : TypeToken>() {}.type) + if (answers.size != ANSWER_SIZE) { throw IllegalArgumentException("选项数量!=$QUESTION_TEXT_LENGTH") } - val rightAnswer=root.get("rightAnswer").asInt + val rightAnswer = root.get("rightAnswer").asInt return ChoiceQuestionVo( question = question, - answers = answers.map { StringForm(formDesc = "选项",textLength = ANSWER_TEXT_LENGTH,value=it) }, + answers = answers.map { + StringForm( + formDesc = "选项", + textLength = ANSWER_TEXT_LENGTH, + value = it + ) + }, rightAnswer = rightAnswer ) - }else{ + } else { throw NullPointerException("问题无法解析!!!!") } } @@ -86,25 +93,29 @@ class ChoiceQuestionVoDeserializer: JsonDeserializer { * 题目反序列化 * */ -class ExamDeserializer:JsonDeserializer{ - companion object{ - val gson: Gson =GsonBuilder() - .registerTypeAdapter(OpenQuestionsVo::class.java,OpenQuestionsVoDeserializer()) - .registerTypeAdapter(ChoiceQuestionVo::class.java,ChoiceQuestionVoDeserializer()) +class ExamDeserializer : JsonDeserializer { + companion object { + val gson: Gson = GsonBuilder() + .registerTypeAdapter(OpenQuestionsVo::class.java, OpenQuestionsVoDeserializer()) + .registerTypeAdapter(ChoiceQuestionVo::class.java, ChoiceQuestionVoDeserializer()) .create() } override fun deserialize(json: JsonElement?, p1: Type?, p2: JsonDeserializationContext?): Exam { - val root=json?.asJsonObject + val root = json?.asJsonObject - val type=root?.get("examType")?.asString + val type = root?.get("examType")?.asString return when (gson.fromJson(type, ExamType::class.java)) { - ExamType.CQ -> gson.fromJson(json, - object : TypeToken() {}.type) - ExamType.OQ -> gson.fromJson(json, - object : TypeToken() {}.type) - null->throw NullPointerException("无法识别题目类型!") + ExamType.CQ -> gson.fromJson( + json, + object : TypeToken() {}.type + ) + ExamType.OQ -> gson.fromJson( + json, + object : TypeToken() {}.type + ) + null -> throw NullPointerException("无法识别题目类型!") } } diff --git a/app/src/main/java/com/gyf/csams/util/HttpUtil.kt b/app/src/main/java/com/gyf/csams/util/HttpUtil.kt index dacfd92..93ccbc5 100644 --- a/app/src/main/java/com/gyf/csams/util/HttpUtil.kt +++ b/app/src/main/java/com/gyf/csams/util/HttpUtil.kt @@ -10,30 +10,30 @@ import okhttp3.RequestBody.Companion.toRequestBody import java.io.IOException import java.lang.reflect.Type -object HttpClient{ - private val httpClient:OkHttpClient=OkHttpClient() +object HttpClient { + private val httpClient: OkHttpClient = OkHttpClient() - private val JSON_CONTENT_TYPE="application/json; charset=UTF-8".toMediaType() + private val JSON_CONTENT_TYPE = "application/json; charset=UTF-8".toMediaType() - private fun buildQueryParams(params:Map?):String{ - return if(params?.isNotEmpty() == true) { + private fun buildQueryParams(params: Map?): String { + return if (params?.isNotEmpty() == true) { val urlPath = StringBuilder("?") - for(i in params){ + for (i in params) { urlPath.append(i.key).append("=").append(i.value) } urlPath.toString() - }else{ + } else { "" } } - private fun buildFormBody(params: Map?):FormBody{ - val builder=FormBody.Builder() - if(params?.isNotEmpty()==true){ - for(item in params){ - builder.add(item.key,item.value) + private fun buildFormBody(params: Map?): FormBody { + val builder = FormBody.Builder() + if (params?.isNotEmpty() == true) { + for (item in params) { + builder.add(item.key, item.value) } } return builder.build() @@ -46,11 +46,11 @@ object HttpClient{ * @param callback * @param params */ - fun get(url:String, callback: Callback, params: Map?=null){ + fun get(url: String, callback: Callback, params: Map? = null) { val request = Request.Builder() .url(url.plus(buildQueryParams(params = params))) .build() - val call=httpClient.newCall(request) + val call = httpClient.newCall(request) call.enqueue(callback) } @@ -62,12 +62,12 @@ object HttpClient{ * @param callback * @param params */ - fun post(url:String, callback: Callback, params: Map?=null){ + fun post(url: String, callback: Callback, params: Map? = null) { val request = Request.Builder() .url(url) .post(body = buildFormBody(params)) .build() - val call=httpClient.newCall(request) + val call = httpClient.newCall(request) call.enqueue(callback) } @@ -79,13 +79,13 @@ object HttpClient{ * @param callback * @param jsonBody */ - fun post(url:String, callback: Callback, jsonBody:String){ + fun post(url: String, callback: Callback, jsonBody: String) { Logger.json(jsonBody) val request = Request.Builder() .url(url) .post(body = jsonBody.toRequestBody(contentType = JSON_CONTENT_TYPE)) .build() - val call=httpClient.newCall(request) + val call = httpClient.newCall(request) call.enqueue(callback) } @@ -93,31 +93,33 @@ object HttpClient{ } -data class ApiResponse(val code:Int,val message:String,val body:T?=null) +data class ApiResponse(val code: Int, val message: String, val body: T? = null) -class SimpleCallback(private val action:String, - private val onSuccess:(res:ApiResponse) -> Unit, - private val onFail:(error:String) -> Unit, - private val type: Type):Callback{ +class SimpleCallback( + private val action: String, + private val onSuccess: (res: ApiResponse) -> Unit, + private val onFail: (error: String) -> Unit, + private val type: Type +) : Callback { - companion object{ - val gson: Gson =GsonBuilder() - .registerTypeAdapter(Exam::class.java,ExamDeserializer()) + companion object { + val gson: Gson = GsonBuilder() + .registerTypeAdapter(Exam::class.java, ExamDeserializer()) .create() } override fun onFailure(call: Call, e: IOException) { onFail("${action}失败,请联系管理员") - Logger.e(e,"${action}请求失败,发生IO异常") + Logger.e(e, "${action}请求失败,发生IO异常") } override fun onResponse(call: Call, response: Response) { if (response.code == 200) { - val body=response.body - if (body!=null&&body.contentType()?.subtype == "json") { - val jsonRes=body.string() - val res:ApiResponse = gson.fromJson(jsonRes, type) + val body = response.body + if (body != null && body.contentType()?.subtype == "json") { + val jsonRes = body.string() + val res: ApiResponse = gson.fromJson(jsonRes, type) Logger.i("${action}请求响应成功:") Logger.json(jsonRes) onSuccess(res) @@ -125,7 +127,7 @@ class SimpleCallback(private val action:String, onFail("${action}失败,请联系管理员") Logger.e("无法解析${action}请求响应数据:,响应码:${response.code},${response.body}") } - }else{ + } else { onFail("${action}失败,请联系管理员") Logger.e("${action}失败,请求响应码:${response.code}") } diff --git a/app/src/main/java/com/gyf/csams/util/RandomUtil.kt b/app/src/main/java/com/gyf/csams/util/RandomUtil.kt index cc9deb4..97b9d20 100644 --- a/app/src/main/java/com/gyf/csams/util/RandomUtil.kt +++ b/app/src/main/java/com/gyf/csams/util/RandomUtil.kt @@ -4,8 +4,8 @@ import okhttp3.internal.toHexString import java.text.SimpleDateFormat import java.util.* -fun randomNum(length:Int=8):String{ - return List(length) {('0' .. '9').random()}.joinToString("") +fun randomNum(length: Int = 8): String { + return List(length) { ('0'..'9').random() }.joinToString("") } @@ -22,7 +22,7 @@ fun String.decodeUnicode(): String { return String(unicodes.toCharArray()) } -val CHINESE_UNICODE_AREA=0X4e00..0X9fa5 +val CHINESE_UNICODE_AREA = 0X4e00..0X9fa5 /** * 随机中文 @@ -30,26 +30,30 @@ val CHINESE_UNICODE_AREA=0X4e00..0X9fa5 * @param length * @return */ -fun randomChinese(length:Int=8):String{ - return List(length){ "\\u${CHINESE_UNICODE_AREA.random().toHexString()}".decodeUnicode() }.joinToString("") +fun randomChinese(length: Int = 8): String { + return List(length) { + "\\u${ + CHINESE_UNICODE_AREA.random().toHexString() + }".decodeUnicode() + }.joinToString("") } -const val DATETIME_FORMAT="yyyy-MM-dd HH:mm" +const val DATETIME_FORMAT = "yyyy-MM-dd HH:mm" -const val START_TIME="2021-01-01 00:00" +const val START_TIME = "2021-01-01 00:00" -val FORMAT=SimpleDateFormat(DATETIME_FORMAT,Locale.US) +val FORMAT = SimpleDateFormat(DATETIME_FORMAT, Locale.US) -val startUnix= FORMAT.parse(START_TIME)?.time +val startUnix = FORMAT.parse(START_TIME)?.time -fun randomDateTime():Date{ +fun randomDateTime(): Date { if (startUnix != null) { return Date("${(startUnix..Date().time).random()}".toLong()) - }else{ + } else { throw IllegalArgumentException("生成随机失败,无法获取起始时间") } } -fun Date.format():String{ +fun Date.format(): String { return FORMAT.format(this) } diff --git a/app/src/main/java/com/gyf/csams/util/TokenUtil.kt b/app/src/main/java/com/gyf/csams/util/TokenUtil.kt index 5e6e8d6..9d5f773 100644 --- a/app/src/main/java/com/gyf/csams/util/TokenUtil.kt +++ b/app/src/main/java/com/gyf/csams/util/TokenUtil.kt @@ -12,7 +12,11 @@ import kotlinx.serialization.Serializable */ @Entity @Serializable -data class Token(@PrimaryKey val studentId:String,@ColumnInfo val token:String,@ColumnInfo val createTime:Long) +data class Token( + @PrimaryKey val studentId: String, + @ColumnInfo val token: String, + @ColumnInfo val createTime: Long +) /** * 令牌传输 @@ -21,7 +25,7 @@ data class Token(@PrimaryKey val studentId:String,@ColumnInfo val token:String,@ * @property token */ @Serializable -data class TokenResDto(val isValid:Boolean,val token: Token?) +data class TokenResDto(val isValid: Boolean, val token: Token?) @Dao interface TokenDao { @@ -40,7 +44,7 @@ class TokenManager private constructor(private var token: Token?) { @Volatile private var instance: TokenManager? = null - fun getInstance(token: Token?=null) = + fun getInstance(token: Token? = null) = instance ?: synchronized(this) { instance ?: TokenManager(token).also { instance = it } } diff --git a/app/src/main/res/drawable/ic_notice.xml b/app/src/main/res/drawable/ic_notice.xml new file mode 100644 index 0000000..02a067a --- /dev/null +++ b/app/src/main/res/drawable/ic_notice.xml @@ -0,0 +1,9 @@ + + +