diff --git a/background/build.gradle.kts b/background/build.gradle.kts index c381938..eb47e5b 100644 --- a/background/build.gradle.kts +++ b/background/build.gradle.kts @@ -25,6 +25,7 @@ android { manifestPlaceholders.apply { this["background_app_name"] = appName } + buildConfigField(type = "String", name = "background_app_name", value = "\"$appName\"") } release { isMinifyEnabled = false @@ -35,6 +36,7 @@ android { manifestPlaceholders.apply { this["background_app_name"] = appName } + buildConfigField(type = "String", name = "background_app_name", value = "\"$appName\"") } } compileOptions { diff --git a/background/src/main/AndroidManifest.xml b/background/src/main/AndroidManifest.xml index 0a19ee2..9362ec8 100644 --- a/background/src/main/AndroidManifest.xml +++ b/background/src/main/AndroidManifest.xml @@ -9,9 +9,10 @@ android:label="${background_app_name}" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" - android:theme="@style/Theme.CSAMS"> + android:theme="@style/Theme.CSAMS" + android:name=".MainApplication"> @@ -21,6 +22,13 @@ + + + \ No newline at end of file diff --git a/background/src/main/java/com/gyf/csams/MainActivity.kt b/background/src/main/java/com/gyf/csams/MainActivity.kt deleted file mode 100644 index 75f5942..0000000 --- a/background/src/main/java/com/gyf/csams/MainActivity.kt +++ /dev/null @@ -1,38 +0,0 @@ -package com.gyf.csams - -import android.os.Bundle -import androidx.activity.ComponentActivity -import androidx.activity.compose.setContent -import androidx.compose.material.MaterialTheme -import androidx.compose.material.Surface -import androidx.compose.material.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.tooling.preview.Preview -import com.gyf.lib.uikit.theme.CSAMSTheme - -class MainActivity : ComponentActivity() { - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setContent { - CSAMSTheme { - // A surface container using the 'background' color from the theme - Surface(color = MaterialTheme.colors.background) { - Greeting("Android") - } - } - } - } -} - -@Composable -fun Greeting(name: String) { - Text(text = "Hello $name!") -} - -@Preview(showBackground = true) -@Composable -fun DefaultPreview() { - CSAMSTheme { - Greeting("Android") - } -} \ No newline at end of file diff --git a/background/src/main/java/com/gyf/csams/MainApplication.kt b/background/src/main/java/com/gyf/csams/MainApplication.kt new file mode 100644 index 0000000..4860d7e --- /dev/null +++ b/background/src/main/java/com/gyf/csams/MainApplication.kt @@ -0,0 +1,17 @@ +package com.gyf.csams + +import android.app.Application +import com.orhanobut.logger.AndroidLogAdapter +import com.orhanobut.logger.DiskLogAdapter +import com.orhanobut.logger.Logger + +class MainApplication : Application() { + override fun onCreate() { + super.onCreate() + //初始化日志 + Logger.addLogAdapter(AndroidLogAdapter()) + Logger.addLogAdapter(DiskLogAdapter()) + + Logger.i("${BuildConfig.background_app_name}启动") + } +} \ No newline at end of file diff --git a/background/src/main/java/com/gyf/csams/account/model/LoginViewModel.kt b/background/src/main/java/com/gyf/csams/account/model/LoginViewModel.kt new file mode 100644 index 0000000..99354da --- /dev/null +++ b/background/src/main/java/com/gyf/csams/account/model/LoginViewModel.kt @@ -0,0 +1,11 @@ +package com.gyf.csams.account.model + +import androidx.lifecycle.ViewModel +import com.gyf.lib.uikit.StringForm + +class LoginViewModel : ViewModel() { + val user = StringForm(formDesc = "管理帐号", textLength = 8) + val password = StringForm(formDesc = "管理密码", textLength = 8) + + val login = "登录" +} \ No newline at end of file diff --git a/background/src/main/java/com/gyf/csams/account/ui/LoginActivity.kt b/background/src/main/java/com/gyf/csams/account/ui/LoginActivity.kt new file mode 100644 index 0000000..989e5d9 --- /dev/null +++ b/background/src/main/java/com/gyf/csams/account/ui/LoginActivity.kt @@ -0,0 +1,66 @@ +package com.gyf.csams.account.ui + +import android.content.Intent +import android.os.Bundle +import androidx.activity.ComponentActivity +import androidx.activity.compose.setContent +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.material.OutlinedButton +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.text.input.PasswordVisualTransformation +import androidx.compose.ui.unit.dp +import androidx.lifecycle.viewmodel.compose.viewModel +import com.gyf.csams.account.model.LoginViewModel +import com.gyf.csams.main.ui.MainActivity +import com.gyf.lib.uikit.BaseTextField +import com.gyf.lib.uikit.Body +import com.gyf.lib.uikit.MainBoxFrame +import com.gyf.lib.uikit.ShowSnackbar + +/** + * 登录 + * + */ +class LoginActivity : ComponentActivity() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + setContent { + Body { scaffoldState -> + val context = LocalContext.current as LoginActivity + MainBoxFrame( + background = { /*TODO 背景图*/ }, + contentAlignment = Alignment.Center + ) { + Column( + modifier = Modifier + .fillMaxWidth() + .height(300.dp), + verticalArrangement = Arrangement.SpaceEvenly, + horizontalAlignment = Alignment.CenterHorizontally + ) { + val model: LoginViewModel = viewModel() + BaseTextField(form = model.user) + BaseTextField( + form = model.password, + visualTransformation = PasswordVisualTransformation() + ) + OutlinedButton(onClick = { + context.startActivity(Intent(context, MainActivity::class.java)) + context.finish() + }) { + Text(text = model.login) + } + ShowSnackbar(scaffoldState = scaffoldState) + } + } + } + } + } +} \ No newline at end of file diff --git a/background/src/main/java/com/gyf/csams/main/model/DepartmentViewModel.kt b/background/src/main/java/com/gyf/csams/main/model/DepartmentViewModel.kt new file mode 100644 index 0000000..c4dbf84 --- /dev/null +++ b/background/src/main/java/com/gyf/csams/main/model/DepartmentViewModel.kt @@ -0,0 +1,4 @@ +package com.gyf.csams.main.model + +class DepartmentViewModel { +} \ No newline at end of file diff --git a/background/src/main/java/com/gyf/csams/main/model/MainViewModel.kt b/background/src/main/java/com/gyf/csams/main/model/MainViewModel.kt new file mode 100644 index 0000000..26f2166 --- /dev/null +++ b/background/src/main/java/com/gyf/csams/main/model/MainViewModel.kt @@ -0,0 +1,42 @@ +package com.gyf.csams.main.model + +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.gyf.lib.uikit.PersonInfoVo +import com.gyf.lib.util.randomChinese + +/** + * 部长 + * + * @property name 姓名 + * @property duty 职务 + * @property headImg 头像 + * @property desc 个人简介 + */ +data class MinisterVo( + override val name: String, + override val duty: String, + override val headImg: String, + override val desc: String +) : PersonInfoVo() + +class MainViewModel : ViewModel() { + private val _person = MutableLiveData() + val person: LiveData = _person + + init { + loadInfo() + } + + private fun loadInfo() { + _person.postValue( + MinisterVo( + name = randomChinese(3), + duty = "总部长", + headImg = "", + desc = randomChinese(8) + ) + ) + } +} \ No newline at end of file diff --git a/background/src/main/java/com/gyf/csams/main/ui/DepartmentActivity.kt b/background/src/main/java/com/gyf/csams/main/ui/DepartmentActivity.kt new file mode 100644 index 0000000..ef305de --- /dev/null +++ b/background/src/main/java/com/gyf/csams/main/ui/DepartmentActivity.kt @@ -0,0 +1,172 @@ +package com.gyf.csams.main.ui + +import android.os.Bundle +import androidx.activity.ComponentActivity +import androidx.activity.compose.setContent +import androidx.annotation.StringRes +import androidx.compose.foundation.border +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.* +import androidx.compose.material.* +import androidx.compose.runtime.* +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.unit.dp +import com.gyf.csams.R +import com.gyf.lib.uikit.Body +import com.gyf.lib.uikit.MainColumnFrame + + +/** + * 部门管理 + * + */ +class DepartmentActivity : ComponentActivity() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + setContent { + Body { _ -> + + + MainColumnFrame(background = { /*TODO*/ }) { + val weight = 0.1F + val departWeight = 0.2F + val space = 0.05F + val context = LocalContext.current + var dialogContent: Int? by remember { + mutableStateOf(null) + } + + dialogContent?.let { + AlertDialog(onDismissRequest = { /*TODO*/ }, + text = { + Card(backgroundColor = MaterialTheme.colors.background) { + Column { + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.Center + ) { + Text(text = context.getString(R.string.department_desc)) + } + + Spacer(modifier = Modifier.height(10.dp)) + Box( + modifier = Modifier + .height(300.dp) + .fillMaxWidth(), contentAlignment = Alignment.Center + ) { + when (it) { + R.string.secretariat -> Text( + text = context.getString( + R.string.secretariat_desc + ) + ) + R.string.propaganda_department -> Text( + text = context.getString( + R.string.propaganda_desc + ) + ) + R.string.public_relations_department -> Text( + text = context.getString( + R.string.public_relations_department_desc + ) + ) + } + } + } + } + }, buttons = { + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.Center + ) { + OutlinedButton(onClick = { dialogContent = null }) { + Text(text = context.getString(R.string.close)) + } + } + + }) + } + + Row( + modifier = Modifier + .fillMaxWidth() + .weight(weight = weight), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.Center + ) { + Text(text = context.getString(R.string.department_management)) + } + + + + DepartmentItem(modifier = Modifier.weight(weight = departWeight), + id = R.string.secretariat, + onClick = { dialogContent = R.string.secretariat }) + Spacer(modifier = Modifier.weight(space)) + DepartmentItem(modifier = Modifier.weight(weight = departWeight), + id = R.string.propaganda_department, + onClick = { dialogContent = R.string.propaganda_department }) + Spacer(modifier = Modifier.weight(space)) + DepartmentItem(modifier = Modifier.weight(weight = departWeight), + id = R.string.public_relations_department, + onClick = { dialogContent = R.string.public_relations_department }) + Spacer(modifier = Modifier.weight(space)) + } + } + } + } + + @Composable + private fun DepartmentItem( + modifier: Modifier = Modifier, + @StringRes id: Int, + onClick: () -> Unit + ) { + val context = LocalContext.current + Row( + modifier = modifier + .fillMaxWidth() + .padding(20.dp) + ) { + Box( + modifier = Modifier + .weight(0.40F) + .fillMaxHeight() + .border( + width = 1.dp, + color = MaterialTheme.colors.onBackground + ) + .clickable(onClick = onClick), + contentAlignment = Alignment.Center + ) { + Text(text = context.getString(id)) + } + Spacer(modifier = Modifier.weight(0.1F)) + Column( + modifier = Modifier + .weight(0.40F) + .fillMaxHeight(), + verticalArrangement = Arrangement.SpaceBetween + ) { + RowItem(text = "部门部长:") + RowItem(text = "部门干事管理") + RowItem(text = "部门总人数:") + } + } + } + + @Composable + private fun RowItem(text: String) { + Row( + modifier = Modifier + .fillMaxWidth() + .border(width = 1.dp, color = MaterialTheme.colors.onBackground), + horizontalArrangement = Arrangement.Center + ) { + Text(text = text) + } + } +} \ No newline at end of file diff --git a/background/src/main/java/com/gyf/csams/main/ui/MainActivity.kt b/background/src/main/java/com/gyf/csams/main/ui/MainActivity.kt new file mode 100644 index 0000000..1702242 --- /dev/null +++ b/background/src/main/java/com/gyf/csams/main/ui/MainActivity.kt @@ -0,0 +1,79 @@ +package com.gyf.csams.main.ui + +import android.content.Intent +import android.os.Bundle +import androidx.activity.ComponentActivity +import androidx.activity.compose.setContent +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.material.OutlinedButton +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.platform.LocalContext +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import androidx.lifecycle.viewmodel.compose.viewModel +import com.gyf.csams.R +import com.gyf.csams.main.model.MainViewModel +import com.gyf.lib.uikit.Body +import com.gyf.lib.uikit.MainColumnFrame +import com.gyf.lib.uikit.Profile +import com.gyf.lib.uikit.ShowSnackbar +import com.gyf.lib.uikit.theme.CSAMSTheme + +class MainActivity : ComponentActivity() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContent { + Body { scaffoldState -> + val model: MainViewModel = viewModel() + val person by model.person.observeAsState() + MainColumnFrame(background = { /*TODO*/ }) { + person?.let { + Profile( + modifier = Modifier + .weight(0.3F) + .padding(10.dp), personInfoVo = it + ) + } + val context = LocalContext.current + Column( + modifier = Modifier.weight(0.7F), + verticalArrangement = Arrangement.SpaceEvenly + ) { + OutlinedButton(onClick = { + context.startActivity(Intent(context, DepartmentActivity::class.java)) + }, modifier = Modifier.fillMaxWidth()) { + Text(text = context.getString(R.string.department_management)) + } + OutlinedButton(onClick = { /*TODO*/ }, modifier = Modifier.fillMaxWidth()) { + Text(text = context.getString(R.string.association_management)) + } + OutlinedButton(onClick = { /*TODO*/ }, modifier = Modifier.fillMaxWidth()) { + Text(text = context.getString(R.string.activity_management)) + } + } + } + ShowSnackbar(scaffoldState = scaffoldState) + } + } + } +} + +@Composable +fun Greeting(name: String) { + Text(text = "Hello $name!") +} + +@Preview(showBackground = true) +@Composable +fun DefaultPreview() { + CSAMSTheme { + Greeting("Android") + } +} \ No newline at end of file diff --git a/background/src/main/res/values-en/strings.xml b/background/src/main/res/values-en/strings.xml new file mode 100644 index 0000000..a647dc1 --- /dev/null +++ b/background/src/main/res/values-en/strings.xml @@ -0,0 +1,14 @@ + + + 部门管理 + 社团管理 + 活动管理 + 秘书部 + 宣传部 + 外联部 + 关闭 + 秘书部作为社团学生部和各社团之间连接的桥梁,地位非常重要,主要职责包括: 客服方面。不仅需要解答学生社团的各类问题,处理各类投诉,收发各类文件还要代表社团联向社团传递各类信息和要求。社团联秘书部每月需整理社团联各部门的绩效,在期末还需参与社团评分工作。 管理协会的人事档案和活动档案。联系成员举行会议,并做好会议记录。活动期间人员协调调用。将协会的最新信息传递给会员,将会员的意见和建议及时反馈至例会委员会。全权处理社团财务管理工作。 + 专门负责学校社团各种活动的宣传,出海报以及网络上的宣传工作。 负责学生思想政治教育和学生会各项宣传报道工作的组织和规划。 围绕学院各阶段的中心工作和学院组织和各项活动,做好宣传鼓动工作。 组织学生参加社团开设的学术讲座和学术活动,督促和指导各班学习委员开展工作。 + + 部门介绍 + \ No newline at end of file diff --git a/background/src/main/res/values-night/themes.xml b/background/src/main/res/values-night/themes.xml deleted file mode 100644 index 1ff666e..0000000 --- a/background/src/main/res/values-night/themes.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - \ No newline at end of file diff --git a/background/src/main/res/values-zh/strings.xml b/background/src/main/res/values-zh/strings.xml new file mode 100644 index 0000000..a647dc1 --- /dev/null +++ b/background/src/main/res/values-zh/strings.xml @@ -0,0 +1,14 @@ + + + 部门管理 + 社团管理 + 活动管理 + 秘书部 + 宣传部 + 外联部 + 关闭 + 秘书部作为社团学生部和各社团之间连接的桥梁,地位非常重要,主要职责包括: 客服方面。不仅需要解答学生社团的各类问题,处理各类投诉,收发各类文件还要代表社团联向社团传递各类信息和要求。社团联秘书部每月需整理社团联各部门的绩效,在期末还需参与社团评分工作。 管理协会的人事档案和活动档案。联系成员举行会议,并做好会议记录。活动期间人员协调调用。将协会的最新信息传递给会员,将会员的意见和建议及时反馈至例会委员会。全权处理社团财务管理工作。 + 专门负责学校社团各种活动的宣传,出海报以及网络上的宣传工作。 负责学生思想政治教育和学生会各项宣传报道工作的组织和规划。 围绕学院各阶段的中心工作和学院组织和各项活动,做好宣传鼓动工作。 组织学生参加社团开设的学术讲座和学术活动,督促和指导各班学习委员开展工作。 + + 部门介绍 + \ No newline at end of file diff --git a/background/src/main/res/values/strings.xml b/background/src/main/res/values/strings.xml index 6b30d8d..a647dc1 100644 --- a/background/src/main/res/values/strings.xml +++ b/background/src/main/res/values/strings.xml @@ -1,3 +1,14 @@ + - + 部门管理 + 社团管理 + 活动管理 + 秘书部 + 宣传部 + 外联部 + 关闭 + 秘书部作为社团学生部和各社团之间连接的桥梁,地位非常重要,主要职责包括: 客服方面。不仅需要解答学生社团的各类问题,处理各类投诉,收发各类文件还要代表社团联向社团传递各类信息和要求。社团联秘书部每月需整理社团联各部门的绩效,在期末还需参与社团评分工作。 管理协会的人事档案和活动档案。联系成员举行会议,并做好会议记录。活动期间人员协调调用。将协会的最新信息传递给会员,将会员的意见和建议及时反馈至例会委员会。全权处理社团财务管理工作。 + 专门负责学校社团各种活动的宣传,出海报以及网络上的宣传工作。 负责学生思想政治教育和学生会各项宣传报道工作的组织和规划。 围绕学院各阶段的中心工作和学院组织和各项活动,做好宣传鼓动工作。 组织学生参加社团开设的学术讲座和学术活动,督促和指导各班学习委员开展工作。 + + 部门介绍 \ No newline at end of file diff --git a/foreground/src/main/AndroidManifest.xml b/foreground/src/main/AndroidManifest.xml index c9897ce..179e623 100644 --- a/foreground/src/main/AndroidManifest.xml +++ b/foreground/src/main/AndroidManifest.xml @@ -16,7 +16,7 @@ android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/Theme.CSAMS" - android:name=".APP"> + android:name=".MainApplication"> () diff --git a/foreground/src/main/java/com/gyf/csams/account/model/AccountViewModel.kt b/foreground/src/main/java/com/gyf/csams/account/model/AccountViewModel.kt index 2fdbae3..8f5be46 100644 --- a/foreground/src/main/java/com/gyf/csams/account/model/AccountViewModel.kt +++ b/foreground/src/main/java/com/gyf/csams/account/model/AccountViewModel.kt @@ -13,8 +13,12 @@ import com.gyf.csams.AccountApi import com.gyf.csams.Api import com.gyf.csams.InitActivity import com.gyf.csams.account.ui.AccountRoute -import com.gyf.csams.uikit.StringForm -import com.gyf.csams.util.* +import com.gyf.csams.util.AppDatabase +import com.gyf.csams.util.SimpleCallback +import com.gyf.csams.util.TokenResDto +import com.gyf.lib.uikit.StringForm +import com.gyf.lib.util.ApiResponse +import com.gyf.lib.util.HttpClient import com.orhanobut.logger.Logger import kotlinx.coroutines.Job import kotlinx.coroutines.launch diff --git a/foreground/src/main/java/com/gyf/csams/account/ui/AccountActivity.kt b/foreground/src/main/java/com/gyf/csams/account/ui/AccountActivity.kt index 2962773..91a08f4 100644 --- a/foreground/src/main/java/com/gyf/csams/account/ui/AccountActivity.kt +++ b/foreground/src/main/java/com/gyf/csams/account/ui/AccountActivity.kt @@ -28,8 +28,8 @@ import com.gyf.csams.BuildConfig import com.gyf.csams.account.model.AccountViewModel import com.gyf.csams.account.model.DialogMessage import com.gyf.csams.uikit.AnimationText -import com.gyf.csams.uikit.BaseTextField -import com.gyf.csams.uikit.Body +import com.gyf.lib.uikit.BaseTextField +import com.gyf.lib.uikit.Body import com.orhanobut.logger.Logger diff --git a/foreground/src/main/java/com/gyf/csams/activity/model/ActivityDetailViewModel.kt b/foreground/src/main/java/com/gyf/csams/activity/model/ActivityDetailViewModel.kt index eefb763..929573b 100644 --- a/foreground/src/main/java/com/gyf/csams/activity/model/ActivityDetailViewModel.kt +++ b/foreground/src/main/java/com/gyf/csams/activity/model/ActivityDetailViewModel.kt @@ -5,10 +5,14 @@ import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.gyf.csams.NOT_IMPL_TIP -import com.gyf.csams.uikit.* -import com.gyf.csams.util.randomChinese -import com.gyf.csams.util.randomDateTime -import com.gyf.csams.util.randomNum +import com.gyf.csams.uikit.ActivityDetailMenu +import com.gyf.csams.uikit.ScrollList +import com.gyf.csams.uikit.SendInterface +import com.gyf.csams.uikit.TopMenuInterface +import com.gyf.lib.uikit.StringForm +import com.gyf.lib.util.randomChinese +import com.gyf.lib.util.randomDateTime +import com.gyf.lib.util.randomNum import com.orhanobut.logger.Logger import kotlinx.coroutines.launch import java.util.* diff --git a/foreground/src/main/java/com/gyf/csams/activity/ui/ActivityDetailActivity.kt b/foreground/src/main/java/com/gyf/csams/activity/ui/ActivityDetailActivity.kt index 3ebe398..27ba081 100644 --- a/foreground/src/main/java/com/gyf/csams/activity/ui/ActivityDetailActivity.kt +++ b/foreground/src/main/java/com/gyf/csams/activity/ui/ActivityDetailActivity.kt @@ -23,7 +23,11 @@ import androidx.navigation.compose.composable import com.gyf.csams.R import com.gyf.csams.activity.model.* import com.gyf.csams.uikit.* -import com.gyf.csams.util.format +import com.gyf.lib.uikit.Body +import com.gyf.lib.uikit.MainColumnFrame +import com.gyf.lib.uikit.ScaffoldModel +import com.gyf.lib.uikit.ShowSnackbar +import com.gyf.lib.util.format import com.orhanobut.logger.Logger /** @@ -104,7 +108,12 @@ class ActivityDetailActivity : ComponentActivity() { */ @Composable private fun Info() { - MainFrame(background = { Background(image = BackgroundImage.ActivityInfo, alpha = 0.7F) }) { + MainColumnFrame(background = { + Background( + image = BackgroundImage.ActivityInfo, + alpha = 0.7F + ) + }) { RectList(modifier = Modifier.weight(0.4F)) ActivityDesc(modifier = Modifier.weight(0.4F)) Spacer(modifier = Modifier.weight(0.05F)) @@ -187,7 +196,7 @@ class ActivityDetailActivity : ComponentActivity() { model: ActivityPhotoViewModel = viewModel(), scaffoldModel: ScaffoldModel = viewModel() ) { - MainFrame(background = { + MainColumnFrame(background = { Background( image = BackgroundImage.ActivityPhoto, alpha = 0.7F @@ -271,7 +280,7 @@ class ActivityDetailActivity : ComponentActivity() { model: ActivityMemberViewModel = viewModel(), scaffoldModel: ScaffoldModel = viewModel() ) { - MainFrame(background = { + MainColumnFrame(background = { Background( image = BackgroundImage.ActivityMember, alpha = 0.7F @@ -362,7 +371,12 @@ class ActivityDetailActivity : ComponentActivity() { */ @Composable private fun BBS(model: BBSViewModel = viewModel(), scaffoldModel: ScaffoldModel = viewModel()) { - MainFrame(background = { Background(image = BackgroundImage.ActivityBBS, alpha = 0.7F) }) { + MainColumnFrame(background = { + Background( + image = BackgroundImage.ActivityBBS, + alpha = 0.7F + ) + }) { Row( modifier = Modifier diff --git a/foreground/src/main/java/com/gyf/csams/association/model/AssociationViewModel.kt b/foreground/src/main/java/com/gyf/csams/association/model/AssociationViewModel.kt index 8392b7e..7fe1fc6 100644 --- a/foreground/src/main/java/com/gyf/csams/association/model/AssociationViewModel.kt +++ b/foreground/src/main/java/com/gyf/csams/association/model/AssociationViewModel.kt @@ -7,8 +7,8 @@ import androidx.lifecycle.viewModelScope import com.gyf.csams.NOT_IMPL_TIP import com.gyf.csams.uikit.AssociationMenu import com.gyf.csams.uikit.ScrollList -import com.gyf.csams.uikit.StringForm import com.gyf.csams.uikit.TopMenuInterface +import com.gyf.lib.uikit.StringForm import com.orhanobut.logger.Logger import kotlinx.coroutines.launch diff --git a/foreground/src/main/java/com/gyf/csams/association/model/ExamViewModel.kt b/foreground/src/main/java/com/gyf/csams/association/model/ExamViewModel.kt index 14eae24..fff046e 100644 --- a/foreground/src/main/java/com/gyf/csams/association/model/ExamViewModel.kt +++ b/foreground/src/main/java/com/gyf/csams/association/model/ExamViewModel.kt @@ -5,7 +5,7 @@ import androidx.lifecycle.MutableLiveData import androidx.lifecycle.viewModelScope import com.gyf.csams.NOT_IMPL_TIP import com.gyf.csams.uikit.ScrollList -import com.gyf.csams.uikit.StringForm +import com.gyf.lib.uikit.StringForm import kotlinx.coroutines.launch import kotlin.random.Random diff --git a/foreground/src/main/java/com/gyf/csams/association/model/RegAssociationViewModel.kt b/foreground/src/main/java/com/gyf/csams/association/model/RegAssociationViewModel.kt index 33fb922..9f8e810 100644 --- a/foreground/src/main/java/com/gyf/csams/association/model/RegAssociationViewModel.kt +++ b/foreground/src/main/java/com/gyf/csams/association/model/RegAssociationViewModel.kt @@ -5,7 +5,7 @@ import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import com.gyf.csams.NOT_IMPL_TIP -import com.gyf.csams.uikit.StringForm +import com.gyf.lib.uikit.StringForm data class Image(val uri: Uri, val createTime: Long, val size: Long) diff --git a/foreground/src/main/java/com/gyf/csams/association/model/RenameViewModel.kt b/foreground/src/main/java/com/gyf/csams/association/model/RenameViewModel.kt index 5a39254..332a7e9 100644 --- a/foreground/src/main/java/com/gyf/csams/association/model/RenameViewModel.kt +++ b/foreground/src/main/java/com/gyf/csams/association/model/RenameViewModel.kt @@ -2,7 +2,7 @@ package com.gyf.csams.association.model import androidx.lifecycle.ViewModel import com.gyf.csams.NOT_IMPL_TIP -import com.gyf.csams.uikit.StringForm +import com.gyf.lib.uikit.StringForm /** * 社团重命名状态管理 diff --git a/foreground/src/main/java/com/gyf/csams/association/ui/AssociationActivity.kt b/foreground/src/main/java/com/gyf/csams/association/ui/AssociationActivity.kt index c2cc74a..5f9595f 100644 --- a/foreground/src/main/java/com/gyf/csams/association/ui/AssociationActivity.kt +++ b/foreground/src/main/java/com/gyf/csams/association/ui/AssociationActivity.kt @@ -29,7 +29,8 @@ import com.gyf.csams.R import com.gyf.csams.activity.ui.ActivityDetailActivity import com.gyf.csams.association.model.* import com.gyf.csams.uikit.* -import com.gyf.csams.util.randomChinese +import com.gyf.lib.uikit.* +import com.gyf.lib.util.randomChinese import com.orhanobut.logger.Logger @@ -179,7 +180,7 @@ class AssociationActivity : ComponentActivity() { */ @Composable private fun Member() { - MainFrame(background = { Background(image = BackgroundImage.AssociationMain) }) { + MainColumnFrame(background = { Background(image = BackgroundImage.AssociationMain) }) { val searchWeight = 0.2F Search( modifier = Modifier @@ -294,7 +295,7 @@ class AssociationActivity : ComponentActivity() { */ @Composable private fun Main() { - MainFrame(background = { + MainColumnFrame(background = { Background(image = BackgroundImage.AssociationMain, alpha = 0.7F) }) { val nameW = 0.1F @@ -391,7 +392,7 @@ class AssociationActivity : ComponentActivity() { */ @Composable private fun AssociationList() { - MainFrame(background = { + MainColumnFrame(background = { Background( image = BackgroundImage.AssociationMain, alpha = 07F diff --git a/foreground/src/main/java/com/gyf/csams/association/ui/ExamActivity.kt b/foreground/src/main/java/com/gyf/csams/association/ui/ExamActivity.kt index be551dd..b20f449 100644 --- a/foreground/src/main/java/com/gyf/csams/association/ui/ExamActivity.kt +++ b/foreground/src/main/java/com/gyf/csams/association/ui/ExamActivity.kt @@ -20,7 +20,9 @@ import androidx.compose.ui.unit.dp import androidx.lifecycle.viewmodel.compose.viewModel import com.gyf.csams.R import com.gyf.csams.association.model.* -import com.gyf.csams.uikit.* +import com.gyf.csams.uikit.Background +import com.gyf.csams.uikit.BackgroundImage +import com.gyf.lib.uikit.* /** @@ -38,7 +40,12 @@ class ExamActivity : ComponentActivity() { setContent { Body { scaffoldState -> - MainFrame(background = { Background(image = BackgroundImage.Exam, alpha = 0.6F) }) { + MainColumnFrame(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)) diff --git a/foreground/src/main/java/com/gyf/csams/association/ui/ReNameActivity.kt b/foreground/src/main/java/com/gyf/csams/association/ui/ReNameActivity.kt index 26fa03a..60b2427 100644 --- a/foreground/src/main/java/com/gyf/csams/association/ui/ReNameActivity.kt +++ b/foreground/src/main/java/com/gyf/csams/association/ui/ReNameActivity.kt @@ -13,7 +13,9 @@ import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.unit.dp import androidx.lifecycle.viewmodel.compose.viewModel import com.gyf.csams.association.model.RenameViewModel -import com.gyf.csams.uikit.* +import com.gyf.csams.uikit.Background +import com.gyf.csams.uikit.BackgroundImage +import com.gyf.lib.uikit.* /** * 社团重命名 @@ -25,7 +27,7 @@ class ReNameActivity : ComponentActivity() { setContent { Body { scaffoldState -> - MainFrame(background = { Background(image = BackgroundImage.Rename) }) { + MainColumnFrame(background = { Background(image = BackgroundImage.Rename) }) { Spacer( modifier = Modifier .weight(0.2F) diff --git a/foreground/src/main/java/com/gyf/csams/association/ui/RegAssociationActivity.kt b/foreground/src/main/java/com/gyf/csams/association/ui/RegAssociationActivity.kt index cc07a46..8828280 100644 --- a/foreground/src/main/java/com/gyf/csams/association/ui/RegAssociationActivity.kt +++ b/foreground/src/main/java/com/gyf/csams/association/ui/RegAssociationActivity.kt @@ -34,7 +34,9 @@ import androidx.core.content.ContextCompat import androidx.lifecycle.viewmodel.compose.viewModel import com.gyf.csams.R import com.gyf.csams.association.model.RegAssociationViewModel -import com.gyf.csams.uikit.* +import com.gyf.csams.uikit.Background +import com.gyf.csams.uikit.BackgroundImage +import com.gyf.lib.uikit.* import com.orhanobut.logger.Logger @@ -48,17 +50,17 @@ class RegAssociationActivity : ComponentActivity() { setContent { Body { scaffoldState -> - MainFrame(background = { - Background( - BackgroundImage.RegAssociation, - alpha = 0.5F - ) - }) { - Spacer( - modifier = Modifier - .weight(0.1F) - ) - Title() + MainColumnFrame(background = { + Background( + BackgroundImage.RegAssociation, + alpha = 0.5F + ) + }) { + Spacer( + modifier = Modifier + .weight(0.1F) + ) + Title() Name() Desc( modifier = Modifier diff --git a/foreground/src/main/java/com/gyf/csams/main/model/MainViewModel.kt b/foreground/src/main/java/com/gyf/csams/main/model/MainViewModel.kt index 3ee6b01..ef66fba 100644 --- a/foreground/src/main/java/com/gyf/csams/main/model/MainViewModel.kt +++ b/foreground/src/main/java/com/gyf/csams/main/model/MainViewModel.kt @@ -7,9 +7,10 @@ import androidx.lifecycle.viewModelScope import com.gyf.csams.NOT_IMPL_TIP import com.gyf.csams.uikit.ScrollList import com.gyf.csams.uikit.SendInterface -import com.gyf.csams.uikit.StringForm -import com.gyf.csams.util.randomChinese -import com.gyf.csams.util.randomNum +import com.gyf.lib.uikit.PersonInfoVo +import com.gyf.lib.uikit.StringForm +import com.gyf.lib.util.randomChinese +import com.gyf.lib.util.randomNum import com.orhanobut.logger.Logger import kotlinx.coroutines.Job import kotlinx.coroutines.delay @@ -166,11 +167,11 @@ class ListViewModel : ScrollList() { */ data class InfoVo( val studentId: String, - val name: String, - val duty: String, - val headImg: String, - val desc: String -) + override val name: String, + override val duty: String, + override val headImg: String, + override val desc: String +) : PersonInfoVo() /** * 个人中心 diff --git a/foreground/src/main/java/com/gyf/csams/main/ui/MainActivity.kt b/foreground/src/main/java/com/gyf/csams/main/ui/MainActivity.kt index 5bf0ef6..5d59414 100644 --- a/foreground/src/main/java/com/gyf/csams/main/ui/MainActivity.kt +++ b/foreground/src/main/java/com/gyf/csams/main/ui/MainActivity.kt @@ -33,7 +33,8 @@ 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.util.randomChinese +import com.gyf.lib.uikit.* +import com.gyf.lib.util.randomChinese /** @@ -94,7 +95,7 @@ class MainActivity : ComponentActivity() { model: CenterViewModel = viewModel(), navController: NavHostController ) { - MainFrame( + MainColumnFrame( background = { Background(image = BackgroundImage.Center, alpha = 0.5F) }, mainMenu = MainMenu.Center, nav = navController @@ -103,58 +104,16 @@ class MainActivity : ComponentActivity() { val info by model.info.observeAsState() - - Column( - 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 - ) { - Image( - painter = painterResource( - id = R.drawable.ic_launcher_foreground - ), - contentDescription = null, - modifier = Modifier - .weight(0.4F) - .fillMaxHeight() - ) - Column( - modifier = Modifier - .weight(0.4F) - .fillMaxHeight() - .border(width = 1.dp, color = MaterialTheme.colors.background), - verticalArrangement = Arrangement.SpaceEvenly, - horizontalAlignment = Alignment.CenterHorizontally - ) { - Text(text = it.name) - Text(text = it.duty) - } - } - - Spacer(modifier = Modifier.weight(0.05F)) - - Card( - backgroundColor = MaterialTheme.colors.background, - modifier = Modifier.weight(0.15F) - ) { - Row( - modifier = Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.Center - ) { - Text(text = it.desc) - } - } - } + info?.let { + Profile( + modifier = Modifier + .weight(0.3F) + .padding(10.dp), + personInfoVo = it + ) } + Column( modifier = Modifier.weight(0.7F), verticalArrangement = Arrangement.SpaceEvenly @@ -201,7 +160,7 @@ class MainActivity : ComponentActivity() { */ @Composable private fun Main(navController: NavHostController) { - MainFrame( + MainColumnFrame( background = { Background(image = BackgroundImage.Main) }, mainMenu = MainMenu.Main, nav = navController @@ -232,7 +191,7 @@ class MainActivity : ComponentActivity() { */ @Composable private fun AssociationList(navController: NavHostController) { - MainFrame( + MainColumnFrame( background = { Background(image = BackgroundImage.AssociationList) }, mainMenu = MainMenu.List, nav = navController diff --git a/foreground/src/main/java/com/gyf/csams/message/model/SysMessageViewModel.kt b/foreground/src/main/java/com/gyf/csams/message/model/SysMessageViewModel.kt index 94720fe..f27ed74 100644 --- a/foreground/src/main/java/com/gyf/csams/message/model/SysMessageViewModel.kt +++ b/foreground/src/main/java/com/gyf/csams/message/model/SysMessageViewModel.kt @@ -3,9 +3,9 @@ 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 com.gyf.lib.util.randomChinese +import com.gyf.lib.util.randomDateTime +import com.gyf.lib.util.randomNum import kotlinx.coroutines.launch import java.util.* import kotlin.random.Random diff --git a/foreground/src/main/java/com/gyf/csams/message/ui/MessageActivity.kt b/foreground/src/main/java/com/gyf/csams/message/ui/MessageActivity.kt index 352e361..85152a2 100644 --- a/foreground/src/main/java/com/gyf/csams/message/ui/MessageActivity.kt +++ b/foreground/src/main/java/com/gyf/csams/message/ui/MessageActivity.kt @@ -19,7 +19,11 @@ 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.* +import com.gyf.csams.uikit.Background +import com.gyf.csams.uikit.BackgroundImage +import com.gyf.csams.uikit.TextTopAppBar +import com.gyf.lib.uikit.Body +import com.gyf.lib.uikit.MainColumnFrame /** * 消息界面 @@ -33,7 +37,7 @@ class MessageActivity : ComponentActivity() { Body { _ -> val model: MessageViewModel = viewModel() val context = LocalContext.current - MainFrame(background = { + MainColumnFrame(background = { Background( image = BackgroundImage.ActivityMessage, alpha = 0.6F diff --git a/foreground/src/main/java/com/gyf/csams/message/ui/SysMessageActivity.kt b/foreground/src/main/java/com/gyf/csams/message/ui/SysMessageActivity.kt index 21bdd4a..a004976 100644 --- a/foreground/src/main/java/com/gyf/csams/message/ui/SysMessageActivity.kt +++ b/foreground/src/main/java/com/gyf/csams/message/ui/SysMessageActivity.kt @@ -19,8 +19,12 @@ 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 +import com.gyf.csams.uikit.Background +import com.gyf.csams.uikit.BackgroundImage +import com.gyf.csams.uikit.TextTopAppBar +import com.gyf.lib.uikit.Body +import com.gyf.lib.uikit.MainColumnFrame +import com.gyf.lib.util.format /** * 系统通知 @@ -32,7 +36,7 @@ class SysMessageActivity : ComponentActivity() { setContent { Body { _ -> - MainFrame(background = { + MainColumnFrame(background = { Background( image = BackgroundImage.ActivityMessage, alpha = 0.6F diff --git a/foreground/src/main/java/com/gyf/csams/uikit/BaseView.kt b/foreground/src/main/java/com/gyf/csams/uikit/BaseView.kt index 095d301..987739c 100644 --- a/foreground/src/main/java/com/gyf/csams/uikit/BaseView.kt +++ b/foreground/src/main/java/com/gyf/csams/uikit/BaseView.kt @@ -9,8 +9,6 @@ import androidx.compose.foundation.Image import androidx.compose.foundation.border import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.* -import androidx.compose.foundation.text.KeyboardActions -import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.material.* import androidx.compose.runtime.* import androidx.compose.runtime.livedata.observeAsState @@ -21,10 +19,7 @@ import androidx.compose.ui.graphics.DefaultAlpha import androidx.compose.ui.graphics.ImageBitmap import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.platform.LocalFocusManager import androidx.compose.ui.res.painterResource -import androidx.compose.ui.text.input.ImeAction -import androidx.compose.ui.text.input.VisualTransformation import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp @@ -33,13 +28,11 @@ import androidx.lifecycle.MutableLiveData import androidx.lifecycle.viewmodel.compose.viewModel import androidx.navigation.NavHostController import androidx.navigation.compose.navigate -import androidx.navigation.compose.rememberNavController -import com.gyf.csams.APP +import com.gyf.csams.MainApplication import com.gyf.csams.R import com.gyf.csams.main.model.MarqueeViewModel +import com.gyf.lib.uikit.* import com.gyf.lib.uikit.theme.CSAMSTheme -import com.orhanobut.logger.Logger -import kotlinx.coroutines.launch /** * 淡入淡出并且颜色变化文本 @@ -70,9 +63,9 @@ fun AnimationText(text: String) { * */ enum class MainMenu( - @DrawableRes val selectedIcon: Int, - @DrawableRes val unSelectedIcon: Int -) { + @DrawableRes override val selectedIcon: Int, + @DrawableRes override val unSelectedIcon: Int +) : BottomBarMenu { //主页 Main(R.drawable.ic_home_fill, R.drawable.ic_home), @@ -80,56 +73,12 @@ enum class MainMenu( List(R.drawable.ic_all_fill, R.drawable.ic_all), //个人中心 - Center(R.drawable.ic_account_fill, R.drawable.ic_account) -} + Center(R.drawable.ic_account_fill, R.drawable.ic_account); -/** - * 底部菜单按钮 - * - * @param _menu - * @param menu - * @param modifier - * @param onClick - */ -@Composable -fun MenuIconButton( - _menu: MainMenu, - menu: MainMenu, - modifier: Modifier = Modifier, - onClick: () -> Unit -) { - Row( - modifier = modifier, horizontalArrangement = Arrangement.Center - ) { - IconButton(onClick = onClick) { - Icon( - painter = painterResource(id = if (_menu == menu) menu.selectedIcon else menu.unSelectedIcon), - contentDescription = null - ) - } - } -} -/** - * 主界面底部菜单 - * - * @param menu - * @param nav - * @param modifier - */ -@Composable -fun MainBottomAppBar(menu: MainMenu, nav: NavHostController, modifier: Modifier = Modifier) { - BottomAppBar(backgroundColor = MaterialTheme.colors.background, modifier = modifier) { - Row(Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween) { - MenuIconButton(_menu = menu, menu = MainMenu.Main, - onClick = { nav.navigate(MainMenu.Main.name) }) - MenuIconButton(_menu = menu, menu = MainMenu.List, - onClick = { nav.navigate(MainMenu.List.name) }) - MenuIconButton(_menu = menu, menu = MainMenu.Center, - onClick = { nav.navigate(MainMenu.Center.name) }) - } + override fun allMenu(): Array { + return values() } - } @@ -154,10 +103,9 @@ interface TopMenuInterface { } } -interface TopBarMenu { - val menuName: String - val name: String +interface TopBarMenu : MenuEnum { + val menuName: String } @@ -417,46 +365,6 @@ fun MarqueeText(model: MarqueeViewModel = viewModel(), offset: State) { } -/** - * 导航界面框架 - * - * @param background 背景 - * @param mainMenu 菜单 - * @param nav 导航 - * @param body 内容 - */ -@Composable -fun MainFrame( - background: @Composable () -> Unit, - mainMenu: MainMenu, - nav: NavHostController, - body: @Composable ColumnScope.() -> Unit -) { - Box(modifier = Modifier.fillMaxSize()) { - background() - Column { - Column(modifier = Modifier.weight(0.9F), content = body) - MainBottomAppBar( - menu = mainMenu, - nav = nav - ) - } - } -} - -/** - * 界面框架 - * - * @param background - * @param body - */ -@Composable -fun MainFrame(background: @Composable () -> Unit, body: @Composable ColumnScope.() -> Unit) { - Box(modifier = Modifier.fillMaxSize()) { - background() - Column(content = body) - } -} /** * 图片轮播 @@ -475,80 +383,6 @@ fun Carousel( } } -/** - * 通用文本输入框 - * - * @param T - * @param modifier - * @param form - * @param singeLine - */ -@Composable -fun BaseTextField( - modifier: Modifier = Modifier, - form: T, - singeLine: Boolean = false, - keyboardOptions: KeyboardOptions = KeyboardOptions.Default.copy(imeAction = ImeAction.Done), - isError: Boolean = false, - visualTransformation: VisualTransformation = VisualTransformation.None -) { - val name: String by form.formValue.observeAsState("") - val focusManager = LocalFocusManager.current - OutlinedTextField( - modifier = modifier, - value = name, - onValueChange = { form.onChange(it) }, - label = { Text(text = form.formDesc) }, - placeholder = { Text(text = form.formPlaceholder) }, - singleLine = singeLine, - keyboardActions = KeyboardActions(onDone = { focusManager.clearFocus() }), - keyboardOptions = keyboardOptions, - trailingIcon = { Text(text = "${name.length}/${form.textLength}") }, - isError = isError, - visualTransformation = visualTransformation - ) -} - -/** - * 底部提示 - * - * @param model - * @param scaffoldState - */ -@Composable -fun ShowSnackbar(model: ScaffoldModel = viewModel(), scaffoldState: ScaffoldState) { - val snackBar: SnackBar? by model.data.observeAsState() - snackBar?.apply { - if (message != null) { - LaunchedEffect(scaffoldState) { - launch { - if (actionLabel != null) { - val result = scaffoldState.snackbarHostState.showSnackbar( - message = message, actionLabel = actionLabel, - duration = duration - - ) - when (result) { - SnackbarResult.ActionPerformed -> { - Logger.i("点击操作按钮") - callback() - } - SnackbarResult.Dismissed -> { - Logger.d("窗口消失") - } - } - } else { - scaffoldState.snackbarHostState.showSnackbar(message = message) - } - model.update() - } - } - - } - } -} - - /** * 界面背景 * @@ -602,7 +436,7 @@ enum class BackgroundImage(@DrawableRes val id: Int) { */ @Composable fun Background(image: BackgroundImage, alpha: Float = DefaultAlpha) { - val app = LocalContext.current.applicationContext as APP + val app = LocalContext.current.applicationContext as MainApplication var i: ImageBitmap? by remember { mutableStateOf(null) } @@ -621,43 +455,6 @@ fun Background(image: BackgroundImage, alpha: Float = DefaultAlpha) { } -/** - * - * - * @param content - */ -@Composable -fun Body(content: @Composable (scaffoldState: ScaffoldState) -> Unit) { - CSAMSTheme { - Surface(color = MaterialTheme.colors.background) { - val scaffoldState = rememberScaffoldState() - - Scaffold(scaffoldState = scaffoldState) { - content(scaffoldState = scaffoldState) - } - } - } -} - -/** - * 带导航的主体 - * - * @param content - */ -@Composable -fun Body(content: @Composable (nav: NavHostController, scaffoldState: ScaffoldState) -> Unit) { - CSAMSTheme { - Surface(color = MaterialTheme.colors.background) { - val navController = rememberNavController() - val scaffoldState = rememberScaffoldState() - - Scaffold(scaffoldState = scaffoldState) { - content(nav = navController, scaffoldState = scaffoldState) - } - } - } -} - /** * 活动海报 * diff --git a/foreground/src/main/java/com/gyf/csams/uikit/ViewModel.kt b/foreground/src/main/java/com/gyf/csams/uikit/ViewModel.kt index 8b06e8d..8e1a607 100644 --- a/foreground/src/main/java/com/gyf/csams/uikit/ViewModel.kt +++ b/foreground/src/main/java/com/gyf/csams/uikit/ViewModel.kt @@ -1,90 +1,18 @@ package com.gyf.csams.uikit import android.app.Application -import androidx.compose.material.SnackbarDuration import androidx.compose.ui.graphics.ImageBitmap import androidx.lifecycle.* import com.google.gson.reflect.TypeToken import com.gyf.csams.R -import com.gyf.csams.util.HttpClient -import com.gyf.csams.util.ImageUtil import com.gyf.csams.util.SimpleCallback +import com.gyf.lib.util.HttpClient +import com.gyf.lib.util.ImageUtil import com.orhanobut.logger.Logger import kotlinx.coroutines.Job import kotlinx.coroutines.delay import kotlinx.coroutines.launch -interface FormLength { - val nameLengthError: String -} - -abstract class FormName(val formDesc: String) { - protected val _formValue = MutableLiveData() - val formValue: LiveData = _formValue - val formPlaceholder = "请输入$formDesc" - - abstract fun onChange(value: T) - - -} - -/** - * 文本输入框控制 - * - * @property textLength - * @constructor - * - * @param 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 - } - - 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 - } - Logger.i("${formDesc}更新值:${_formValue.value}") - } -} - - -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 ImageModel(application: Application, private val urlPath: String) : AndroidViewModel(application) { diff --git a/foreground/src/main/java/com/gyf/csams/util/GsonUtil.kt b/foreground/src/main/java/com/gyf/csams/util/GsonUtil.kt index d99a1e2..bb35c32 100644 --- a/foreground/src/main/java/com/gyf/csams/util/GsonUtil.kt +++ b/foreground/src/main/java/com/gyf/csams/util/GsonUtil.kt @@ -3,7 +3,7 @@ package com.gyf.csams.util import com.google.gson.* import com.google.gson.reflect.TypeToken import com.gyf.csams.association.model.* -import com.gyf.csams.uikit.StringForm +import com.gyf.lib.uikit.StringForm import java.lang.reflect.Type class OpenQuestionsVoSerializer : JsonSerializer { diff --git a/foreground/src/main/java/com/gyf/csams/util/HttpCallback.kt b/foreground/src/main/java/com/gyf/csams/util/HttpCallback.kt new file mode 100644 index 0000000..6cf0235 --- /dev/null +++ b/foreground/src/main/java/com/gyf/csams/util/HttpCallback.kt @@ -0,0 +1,28 @@ +package com.gyf.csams.util + +import com.google.gson.Gson +import com.google.gson.GsonBuilder +import com.gyf.csams.association.model.Exam +import com.gyf.lib.util.ApiResponse +import com.gyf.lib.util.HttpCallback +import java.lang.reflect.Type + +/** + * http请求回调 + * + * @param T + * @property action + * @property onSuccess + * @property onFail + * @property type + */ +class SimpleCallback( + private val action: String, + private val onSuccess: (res: ApiResponse) -> Unit, + private val onFail: (error: String) -> Unit, + private val type: Type +) : HttpCallback(action, onSuccess, onFail, type) { + override val gson: Gson = GsonBuilder() + .registerTypeAdapter(Exam::class.java, ExamDeserializer()) + .create() +} \ No newline at end of file diff --git a/foreground/src/main/java/com/gyf/csams/util/TokenUtil.kt b/foreground/src/main/java/com/gyf/csams/util/TokenUtil.kt index ad80808..47e3b22 100644 --- a/foreground/src/main/java/com/gyf/csams/util/TokenUtil.kt +++ b/foreground/src/main/java/com/gyf/csams/util/TokenUtil.kt @@ -4,14 +4,12 @@ import android.content.Context import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.room.* -import kotlinx.serialization.Serializable /** * 登陆令牌 */ @Entity -@Serializable data class Token( @PrimaryKey val studentId: String, @ColumnInfo val token: String, @@ -24,7 +22,6 @@ data class Token( * @property isValid * @property token */ -@Serializable data class TokenResDto(val isValid: Boolean, val token: Token?) @Dao diff --git a/foreground/src/test/java/com/gyf/csams/ExampleUnitTest.kt b/foreground/src/test/java/com/gyf/csams/ExampleUnitTest.kt index e9e784e..baed3db 100644 --- a/foreground/src/test/java/com/gyf/csams/ExampleUnitTest.kt +++ b/foreground/src/test/java/com/gyf/csams/ExampleUnitTest.kt @@ -2,9 +2,9 @@ package com.gyf.csams import com.google.gson.Gson import com.google.gson.reflect.TypeToken -import com.gyf.csams.util.ApiResponse -import com.gyf.csams.util.randomChinese import com.gyf.lib.uikit.TestLib +import com.gyf.lib.util.ApiResponse +import com.gyf.lib.util.randomChinese import org.junit.Assert.assertEquals import org.junit.Test @@ -27,8 +27,8 @@ class ExampleUnitTest { @Test fun testGson(){ // val e="{\"code\":200,\"message\":\"学号可注册\",\"body\":false}" - val c=ApiResponse(code = 200,message = "aaa",body= null) - val d=Gson().toJson(c) + val c = ApiResponse(code = 200, message = "aaa", body = null) + val d = Gson().toJson(c) println(d) val e=Gson().fromJson>(d,object : TypeToken>() {}.type) println(e.body) diff --git a/lib/src/main/java/com/gyf/lib/uikit/BaseTextField.kt b/lib/src/main/java/com/gyf/lib/uikit/BaseTextField.kt new file mode 100644 index 0000000..d649554 --- /dev/null +++ b/lib/src/main/java/com/gyf/lib/uikit/BaseTextField.kt @@ -0,0 +1,96 @@ +package com.gyf.lib.uikit + +import androidx.compose.foundation.text.KeyboardActions +import androidx.compose.foundation.text.KeyboardOptions +import androidx.compose.material.OutlinedTextField +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.platform.LocalFocusManager +import androidx.compose.ui.text.input.ImeAction +import androidx.compose.ui.text.input.VisualTransformation +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData +import com.orhanobut.logger.Logger + + +interface FormLength { + val nameLengthError: String +} + +abstract class FormName(val formDesc: String) { + protected val _formValue = MutableLiveData() + val formValue: LiveData = _formValue + val formPlaceholder = "请输入$formDesc" + + abstract fun onChange(value: T) + + +} + +/** + * 文本输入框控制 + * + * @property textLength + * @constructor + * + * @param 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 + } + + 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 + } + Logger.i("${formDesc}更新值:${_formValue.value}") + } +} + +/** + * 通用文本输入框 + * + * @param T + * @param modifier + * @param form + * @param singeLine + */ +@Composable +fun BaseTextField( + modifier: Modifier = Modifier, + form: T, + singeLine: Boolean = false, + keyboardOptions: KeyboardOptions = KeyboardOptions.Default.copy(imeAction = ImeAction.Done), + isError: Boolean = false, + visualTransformation: VisualTransformation = VisualTransformation.None +) { + val name: String by form.formValue.observeAsState("") + val focusManager = LocalFocusManager.current + OutlinedTextField( + modifier = modifier, + value = name, + onValueChange = { form.onChange(it) }, + label = { Text(text = form.formDesc) }, + placeholder = { Text(text = form.formPlaceholder) }, + singleLine = singeLine, + keyboardActions = KeyboardActions(onDone = { focusManager.clearFocus() }), + keyboardOptions = keyboardOptions, + trailingIcon = { Text(text = "${name.length}/${form.textLength}") }, + isError = isError, + visualTransformation = visualTransformation + ) +} \ No newline at end of file diff --git a/lib/src/main/java/com/gyf/lib/uikit/MainFrame.kt b/lib/src/main/java/com/gyf/lib/uikit/MainFrame.kt new file mode 100644 index 0000000..3b65e8f --- /dev/null +++ b/lib/src/main/java/com/gyf/lib/uikit/MainFrame.kt @@ -0,0 +1,179 @@ +package com.gyf.lib.uikit + +import androidx.compose.foundation.layout.* +import androidx.compose.material.* +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.painterResource +import androidx.navigation.NavHostController +import androidx.navigation.compose.navigate +import androidx.navigation.compose.rememberNavController +import com.gyf.lib.uikit.theme.CSAMSTheme + + +interface MenuEnum { + val name: String +} + +interface BottomBarMenu : MenuEnum { + val selectedIcon: Int + val unSelectedIcon: Int + fun allMenu(): Array +} + + +/** + * 导航界面框架 + * + * @param background 背景 + * @param mainMenu 菜单 + * @param nav 导航 + * @param body 内容 + */ +@Composable +fun MainColumnFrame( + background: @Composable () -> Unit, + mainMenu: T, + nav: NavHostController, + body: @Composable ColumnScope.() -> Unit +) { + Box(modifier = Modifier.fillMaxSize()) { + background() + Column { + Column(modifier = Modifier.weight(0.9F), content = body) + MainBottomAppBar( + menu = mainMenu, + nav = nav + ) + } + } +} + + +/** + * 界面框架 + * + * @param background + * @param body + */ +@Composable +fun MainColumnFrame( + background: @Composable () -> Unit, + body: @Composable ColumnScope.() -> Unit +) { + Box(modifier = Modifier.fillMaxSize()) { + background() + Column(content = body) + } +} + +/** + * 界面框架 + * + * @param background + * @param body + */ +@Composable +fun MainBoxFrame( + contentAlignment: Alignment = Alignment.TopStart, + background: @Composable () -> Unit, + body: @Composable BoxScope.() -> Unit +) { + Box( + modifier = Modifier.fillMaxSize(), + contentAlignment = contentAlignment + ) { + background() + body() + } +} + +/** + * 底部菜单按钮 + * + * @param _menu + * @param menu + * @param modifier + * @param onClick + */ +@Composable +fun MenuIconButton( + _menu: T, + menu: T, + modifier: Modifier = Modifier, + onClick: () -> Unit +) { + Row( + modifier = modifier, horizontalArrangement = Arrangement.Center + ) { + IconButton(onClick = onClick) { + Icon( + painter = painterResource(id = if (_menu == menu) menu.selectedIcon else menu.unSelectedIcon), + contentDescription = null + ) + } + } +} + +/** + * 主界面底部菜单 + * + * @param menu + * @param nav + * @param modifier + */ +@Composable +fun MainBottomAppBar( + menu: T, + nav: NavHostController, + modifier: Modifier = Modifier +) { + BottomAppBar(backgroundColor = MaterialTheme.colors.background, modifier = modifier) { + Row(Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween) { + menu.allMenu().forEach { + MenuIconButton(_menu = menu, menu = it, + onClick = { nav.navigate(it.name) }) + } + } + } + +} + + +/** + * + * + * @param content + */ +@Composable +fun Body(content: @Composable (scaffoldState: ScaffoldState) -> Unit) { + CSAMSTheme { + Surface(color = MaterialTheme.colors.background) { + val scaffoldState = rememberScaffoldState() + + Scaffold(scaffoldState = scaffoldState) { + content(scaffoldState = scaffoldState) + } + } + } +} + +/** + * 带导航的主体 + * + * @param content + */ +@Composable +fun Body(content: @Composable (nav: NavHostController, scaffoldState: ScaffoldState) -> Unit) { + CSAMSTheme { + Surface(color = MaterialTheme.colors.background) { + val navController = rememberNavController() + val scaffoldState = rememberScaffoldState() + + Scaffold(scaffoldState = scaffoldState) { + content(nav = navController, scaffoldState = scaffoldState) + } + } + } +} \ No newline at end of file diff --git a/lib/src/main/java/com/gyf/lib/uikit/Profile.kt b/lib/src/main/java/com/gyf/lib/uikit/Profile.kt new file mode 100644 index 0000000..77c5103 --- /dev/null +++ b/lib/src/main/java/com/gyf/lib/uikit/Profile.kt @@ -0,0 +1,94 @@ +package com.gyf.lib.uikit + +import androidx.compose.foundation.Image +import androidx.compose.foundation.border +import androidx.compose.foundation.layout.* +import androidx.compose.material.Card +import androidx.compose.material.MaterialTheme +import androidx.compose.material.Text +import androidx.compose.runtime.* +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.ImageBitmap +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.unit.dp +import com.gyf.lib.util.ImageUtil + + +abstract class PersonInfoVo { + abstract val name: String + abstract val duty: String + abstract val headImg: String + abstract val desc: String +} + +@Composable +fun Profile( + modifier: Modifier, + personInfoVo: PersonInfoVo +) { + var headImg: ImageBitmap? by remember { + mutableStateOf(null) + } + val context = LocalContext.current + LaunchedEffect(personInfoVo.headImg) { + headImg = ImageUtil.getImage(context = context, personInfoVo.headImg) + } + Column( + modifier = modifier, + ) { + Row( + modifier = Modifier + .fillMaxWidth() + .weight(0.7F) + .border(width = 1.dp, color = MaterialTheme.colors.background), + horizontalArrangement = Arrangement.SpaceBetween + ) { + headImg.let { + if (it != null) { + Image( + bitmap = it, + contentDescription = null, + modifier = Modifier + .weight(0.4F) + .fillMaxHeight() + ) + } else { + Box( + modifier = Modifier + .weight(0.4F) + .fillMaxHeight(), + contentAlignment = Alignment.Center + ) { + Text(text = "头像加载失败") + } + } + } + Column( + modifier = Modifier + .weight(0.4F) + .fillMaxHeight() + .border(width = 1.dp, color = MaterialTheme.colors.background), + verticalArrangement = Arrangement.SpaceEvenly, + horizontalAlignment = Alignment.CenterHorizontally + ) { + Text(text = personInfoVo.name) + Text(text = personInfoVo.duty) + } + } + + Spacer(modifier = Modifier.weight(0.05F)) + + Card( + backgroundColor = MaterialTheme.colors.background, + modifier = Modifier.weight(0.15F) + ) { + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.Center + ) { + Text(text = personInfoVo.desc) + } + } + } +} \ No newline at end of file diff --git a/lib/src/main/java/com/gyf/lib/uikit/Snackbar.kt b/lib/src/main/java/com/gyf/lib/uikit/Snackbar.kt new file mode 100644 index 0000000..e82cdc9 --- /dev/null +++ b/lib/src/main/java/com/gyf/lib/uikit/Snackbar.kt @@ -0,0 +1,81 @@ +package com.gyf.lib.uikit + +import androidx.compose.material.ScaffoldState +import androidx.compose.material.SnackbarDuration +import androidx.compose.material.SnackbarResult +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.livedata.observeAsState +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewmodel.compose.viewModel +import com.orhanobut.logger.Logger +import kotlinx.coroutines.launch + + +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) + } + } +} + + +/** + * 底部提示 + * + * @param model + * @param scaffoldState + */ +@Composable +fun ShowSnackbar(model: ScaffoldModel = viewModel(), scaffoldState: ScaffoldState) { + val snackBar: SnackBar? by model.data.observeAsState() + snackBar?.apply { + if (message != null) { + LaunchedEffect(scaffoldState) { + launch { + if (actionLabel != null) { + val result = scaffoldState.snackbarHostState.showSnackbar( + message = message, actionLabel = actionLabel, + duration = duration + + ) + when (result) { + SnackbarResult.ActionPerformed -> { + Logger.i("点击操作按钮") + callback() + } + SnackbarResult.Dismissed -> { + Logger.d("窗口消失") + } + } + } else { + scaffoldState.snackbarHostState.showSnackbar(message = message) + } + model.update() + } + } + + } + } +} diff --git a/foreground/src/main/java/com/gyf/csams/util/HttpUtil.kt b/lib/src/main/java/com/gyf/lib/util/HttpUtil.kt similarity index 90% rename from foreground/src/main/java/com/gyf/csams/util/HttpUtil.kt rename to lib/src/main/java/com/gyf/lib/util/HttpUtil.kt index 80f322c..45b1d77 100644 --- a/foreground/src/main/java/com/gyf/csams/util/HttpUtil.kt +++ b/lib/src/main/java/com/gyf/lib/util/HttpUtil.kt @@ -1,8 +1,6 @@ -package com.gyf.csams.util +package com.gyf.lib.util import com.google.gson.Gson -import com.google.gson.GsonBuilder -import com.gyf.csams.association.model.Exam import com.orhanobut.logger.Logger import okhttp3.* import okhttp3.MediaType.Companion.toMediaType @@ -114,28 +112,17 @@ object HttpClient { */ data class ApiResponse(val code: Int, val message: String, val body: T? = null) -/** - * http请求回调 - * - * @param T - * @property action - * @property onSuccess - * @property onFail - * @property type - */ -class SimpleCallback( + +interface GsonBuilderInterface { + val gson: Gson +} + +abstract class HttpCallback( 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()) - .create() - } - +) : Callback, GsonBuilderInterface { override fun onFailure(call: Call, e: IOException) { when (e) { is SocketTimeoutException -> { @@ -166,4 +153,5 @@ class SimpleCallback( Logger.e("${action}失败,请求响应码:${response.code}") } } -} \ No newline at end of file +} + diff --git a/foreground/src/main/java/com/gyf/csams/util/ImageUtil.kt b/lib/src/main/java/com/gyf/lib/util/ImageUtil.kt similarity index 98% rename from foreground/src/main/java/com/gyf/csams/util/ImageUtil.kt rename to lib/src/main/java/com/gyf/lib/util/ImageUtil.kt index f0dcb26..cb7ad09 100644 --- a/foreground/src/main/java/com/gyf/csams/util/ImageUtil.kt +++ b/lib/src/main/java/com/gyf/lib/util/ImageUtil.kt @@ -1,4 +1,4 @@ -package com.gyf.csams.util +package com.gyf.lib.util import android.content.Context import androidx.compose.ui.graphics.ImageBitmap diff --git a/foreground/src/main/java/com/gyf/csams/util/RandomUtil.kt b/lib/src/main/java/com/gyf/lib/util/RandomUtil.kt similarity index 97% rename from foreground/src/main/java/com/gyf/csams/util/RandomUtil.kt rename to lib/src/main/java/com/gyf/lib/util/RandomUtil.kt index e372a95..daa4a52 100644 --- a/foreground/src/main/java/com/gyf/csams/util/RandomUtil.kt +++ b/lib/src/main/java/com/gyf/lib/util/RandomUtil.kt @@ -1,4 +1,4 @@ -package com.gyf.csams.util +package com.gyf.lib.util import okhttp3.internal.toHexString import java.text.SimpleDateFormat