Forráskód Böngészése

1. 首页Item显示优化
2. 新增自动加载更多数据

bjb 4 hónapja
szülő
commit
efcfaf82ba

+ 91 - 84
app/src/main/java/com/iscs/bozzys/ui/pages/compose/JobListItem.kt

@@ -1,12 +1,12 @@
 package com.iscs.bozzys.ui.pages.compose
 
 import androidx.compose.foundation.background
-import androidx.compose.foundation.border
 import androidx.compose.foundation.clickable
 import androidx.compose.foundation.layout.Column
 import androidx.compose.foundation.layout.ExperimentalLayoutApi
 import androidx.compose.foundation.layout.FlowRow
 import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.Spacer
 import androidx.compose.foundation.layout.fillMaxHeight
 import androidx.compose.foundation.layout.fillMaxWidth
 import androidx.compose.foundation.layout.height
@@ -32,6 +32,7 @@ import com.iscs.bozzys.R
 import com.iscs.bozzys.api.Job
 import com.iscs.bozzys.ui.pages.detail.job.openPageDetailJob
 import com.iscs.bozzys.ui.theme.Text
+import com.iscs.bozzys.utils.DateUtil.getShowDate
 
 @OptIn(ExperimentalLayoutApi::class)
 @Composable
@@ -39,99 +40,105 @@ fun JobListItem(job: Job) {
     val ctx = LocalContext.current
     // 获取等级名称和颜色
     val levelInfo = getLevelNameAndColor(job.urgencyLevel)
-    Column(
-        Modifier
-            .padding(top = 1.dp, bottom = 15.dp)
+    CardContainer(
+        modifier = Modifier
+            .padding(vertical = 5.dp)
             .fillMaxWidth()
-            .heightIn(max = 200.dp)
-            .border(1.dp, color = Color(0xFFEEEEEE), shape = RoundedCornerShape(12.dp))
-            .clip(RoundedCornerShape(12.dp))
-            .background(Color(0xFFF8F9FA))
-            .clickable(onClick = { ctx.openPageDetailJob() })
-            .padding(16.dp)
+            .heightIn(max = 200.dp),
+        shadowBlur = 6.dp
     ) {
-        Row {
-            Text(
-                job.name,
-                fontSize = 15.sp,
-                fontWeight = FontWeight.Medium,
-                color = Text,
-                maxLines = 1,
-                overflow = TextOverflow.Ellipsis,
-                modifier = Modifier
-                    .padding(end = 10.dp)
-                    .weight(1f)
-            )
-            if (job.urgencyLevel != "0") Text(
-                levelInfo.first, modifier = Modifier
-                    .height(24.dp)
-                    .clip(RoundedCornerShape(12.dp))
-                    .background(levelInfo.second)
-                    .padding(horizontal = 10.dp),
-                fontSize = 12.sp,
-                lineHeight = 24.sp,
-                color = Color.White
-            )
-        }
-        FlowRow(
+        Column(
             Modifier
-                .padding(top = 10.dp)
                 .fillMaxWidth()
+                .clickable(onClick = { ctx.openPageDetailJob() })
+                .padding(16.dp)
         ) {
-            // 当前任务号
-            Row(Modifier.padding(end = 12.dp), verticalAlignment = Alignment.CenterVertically) {
-                Icon(
-                    painterResource(R.drawable.jobs), contentDescription = null, modifier = Modifier
-                        .padding(end = 5.dp)
-                        .size(13.dp),
-                    tint = Color(0xFF666666)
+            Row {
+                Text(
+                    job.name,
+                    fontSize = 15.sp,
+                    fontWeight = FontWeight.Medium,
+                    color = Text,
+                    maxLines = 1,
+                    overflow = TextOverflow.Ellipsis,
+                    modifier = Modifier
+                        .padding(end = 10.dp)
+                        .weight(1f)
                 )
-                Text(job.orderNo, fontSize = 13.sp, color = Color(0xFF666666))
-            }
-            // 负责人
-            if (job.initiatorName.isNotEmpty()) Row(Modifier.padding(end = 12.dp), verticalAlignment = Alignment.CenterVertically) {
-                Icon(
-                    painterResource(R.drawable.user), contentDescription = null, modifier = Modifier
-                        .padding(end = 5.dp)
-                        .size(13.dp),
-                    tint = Color(0xFF666666)
+                if (job.urgencyLevel != "0") Text(
+                    levelInfo.first, modifier = Modifier
+                        .height(24.dp)
+                        .clip(RoundedCornerShape(12.dp))
+                        .background(levelInfo.second)
+                        .padding(horizontal = 10.dp),
+                    fontSize = 12.sp,
+                    lineHeight = 24.sp,
+                    color = Color.White
                 )
-                Text("负责人:${job.initiatorName}", fontSize = 13.sp, color = Color(0xFF666666))
             }
-            // 岗位区间,暂时没有字段匹配,先隐藏
-            if (false) Row(Modifier.padding(end = 12.dp), verticalAlignment = Alignment.CenterVertically) {
-                Icon(
-                    painterResource(R.drawable.location), contentDescription = null, modifier = Modifier
-                        .padding(end = 5.dp)
-                        .size(13.dp),
-                    tint = Color(0xFF1E90FF)
+            FlowRow(
+                Modifier
+                    .padding(top = 10.dp)
+                    .fillMaxWidth()
+            ) {
+                // 当前任务号
+                Row(Modifier.padding(end = 12.dp), verticalAlignment = Alignment.CenterVertically) {
+                    Icon(
+                        painterResource(R.drawable.jobs), contentDescription = null, modifier = Modifier
+                            .padding(end = 5.dp)
+                            .size(13.dp),
+                        tint = Color(0xFF666666)
+                    )
+                    Text(job.orderNo, fontSize = 13.sp, color = Color(0xFF666666))
+                }
+                // 负责人
+                if (job.initiatorName.isNotEmpty()) Row(Modifier.padding(end = 12.dp), verticalAlignment = Alignment.CenterVertically) {
+                    Icon(
+                        painterResource(R.drawable.user), contentDescription = null, modifier = Modifier
+                            .padding(end = 5.dp)
+                            .size(13.dp),
+                        tint = Color(0xFF666666)
+                    )
+                    Text("负责人:${job.initiatorName}", fontSize = 13.sp, color = Color(0xFF666666))
+                }
+                // 岗位区间,暂时没有字段匹配,先隐藏
+                if (false) Row(Modifier.padding(end = 12.dp), verticalAlignment = Alignment.CenterVertically) {
+                    Icon(
+                        painterResource(R.drawable.location), contentDescription = null, modifier = Modifier
+                            .padding(end = 5.dp)
+                            .size(13.dp),
+                        tint = Color(0xFF1E90FF)
+                    )
+                    Text("车间A区", fontSize = 13.sp, color = Color(0xFF666666))
+                }
+                // Text("作业内容:${task.currentNodeName ?: "--"}", fontSize = 13.sp, color = Color(0xFF666666))
+            }
+            Row(
+                Modifier
+                    .padding(top = 5.dp)
+                    .fillMaxWidth()
+                    .height(20.dp),
+                verticalAlignment = Alignment.CenterVertically
+            ) {
+                Text("当前任务:", fontSize = 13.sp, lineHeight = 13.sp, color = Text)
+                Text(
+                    job.currentNodeName ?: "--",
+                    modifier = Modifier
+                        .fillMaxHeight()
+                        .height(18.dp)
+                        .clip(RoundedCornerShape(4.dp))
+                        .background(Color(0xFF1E90FF))
+                        .padding(horizontal = 6.dp),
+                    fontSize = 12.sp,
+                    lineHeight = 18.sp,
+                    fontWeight = FontWeight.Bold,
+                    color = Color.White,
+                    textAlign = TextAlign.Center
                 )
-                Text("车间A区", fontSize = 13.sp, color = Color(0xFF666666))
+                Spacer(modifier = Modifier.weight(1f))
+                // 显示创建日期
+                Text(job.createTime.getShowDate(), fontSize = 14.sp, color = Text.copy(alpha = 0.6f))
             }
-            // Text("作业内容:${task.currentNodeName ?: "--"}", fontSize = 13.sp, color = Color(0xFF666666))
-        }
-        Row(
-            Modifier
-                .padding(top = 5.dp)
-                .fillMaxWidth()
-                .height(20.dp),
-            verticalAlignment = Alignment.CenterVertically
-        ) {
-            Text("当前任务:", fontSize = 13.sp, lineHeight = 13.sp, color = Text)
-            Text(
-                job.currentNodeName ?: "--",
-                modifier = Modifier
-                    .fillMaxHeight()
-                    .height(18.dp)
-                    .clip(RoundedCornerShape(4.dp))
-                    .background(Color(0xFF1E90FF))
-                    .padding(horizontal = 6.dp),
-                fontSize = 12.sp,
-                lineHeight = 18.sp,
-                fontWeight = FontWeight.Bold,
-                color = Color.White,
-                textAlign = TextAlign.Center
-            )
         }
     }
 }

+ 77 - 75
app/src/main/java/com/iscs/bozzys/ui/pages/compose/TaskListItem.kt

@@ -1,7 +1,6 @@
 package com.iscs.bozzys.ui.pages.compose
 
 import androidx.compose.foundation.background
-import androidx.compose.foundation.border
 import androidx.compose.foundation.clickable
 import androidx.compose.foundation.layout.Column
 import androidx.compose.foundation.layout.ExperimentalLayoutApi
@@ -39,90 +38,93 @@ fun TaskListItem(task: Task) {
     val ctx = LocalContext.current
     // 获取等级名称和颜色
     val levelInfo = getLevelNameAndColor(task.urgencyLevel)
-    Column(
-        Modifier
-            .padding(top = 1.dp, bottom = 15.dp)
+    CardContainer(
+        modifier = Modifier
+            .padding(vertical = 5.dp)
             .fillMaxWidth()
-            .heightIn(max = 200.dp)
-            .border(1.dp, color = Color(0xFFEEEEEE), shape = RoundedCornerShape(12.dp))
-            .clip(RoundedCornerShape(12.dp))
-            .background(Color(0xFFF8F9FA))
-            .clickable(onClick = { ctx.openPageDetailTask(task) })
-            .padding(16.dp)
+            .heightIn(max = 200.dp),
+        shadowBlur = 6.dp
     ) {
-        Row {
-            Text(task.name, fontSize = 15.sp, fontWeight = FontWeight.Medium, color = Text)
-            Spacer(Modifier.weight(1f))
-            if (task.urgencyLevel != "0") Text(
-                levelInfo.first, modifier = Modifier
-                    .height(24.dp)
-                    .clip(RoundedCornerShape(12.dp))
-                    .background(levelInfo.second)
-                    .padding(horizontal = 10.dp),
-                fontSize = 12.sp,
-                lineHeight = 24.sp,
-                color = Color.White
-            )
-        }
-        FlowRow(
+        Column(
             Modifier
-                .padding(top = 10.dp)
                 .fillMaxWidth()
+                .clickable(onClick = { ctx.openPageDetailTask(task) })
+                .padding(16.dp)
         ) {
-            // 当前任务号
-            Row(Modifier.padding(end = 12.dp), verticalAlignment = Alignment.CenterVertically) {
-                Icon(
-                    painterResource(R.drawable.jobs), contentDescription = null, modifier = Modifier
-                        .padding(end = 5.dp)
-                        .size(13.dp),
-                    tint = Color(0xFF666666)
+            Row {
+                Text(task.name, fontSize = 15.sp, fontWeight = FontWeight.Medium, color = Text)
+                Spacer(Modifier.weight(1f))
+                if (task.urgencyLevel != "0") Text(
+                    levelInfo.first, modifier = Modifier
+                        .height(24.dp)
+                        .clip(RoundedCornerShape(12.dp))
+                        .background(levelInfo.second)
+                        .padding(horizontal = 10.dp),
+                    fontSize = 12.sp,
+                    lineHeight = 24.sp,
+                    color = Color.White
                 )
-                Text(task.orderNo, fontSize = 13.sp, color = Color(0xFF666666))
             }
-            // 负责人
-            if (!task.workerUserName.isNullOrEmpty()) Row(Modifier.padding(end = 12.dp), verticalAlignment = Alignment.CenterVertically) {
-                Icon(
-                    painterResource(R.drawable.user), contentDescription = null, modifier = Modifier
-                        .padding(end = 5.dp)
-                        .size(13.dp),
-                    tint = Color(0xFF666666)
-                )
-                Text("负责人:${task.workerUserName}", fontSize = 13.sp, color = Color(0xFF666666))
+            FlowRow(
+                Modifier
+                    .padding(top = 10.dp)
+                    .fillMaxWidth()
+            ) {
+                // 当前任务号
+                Row(Modifier.padding(end = 12.dp), verticalAlignment = Alignment.CenterVertically) {
+                    Icon(
+                        painterResource(R.drawable.jobs), contentDescription = null, modifier = Modifier
+                            .padding(end = 5.dp)
+                            .size(13.dp),
+                        tint = Color(0xFF666666)
+                    )
+                    Text(task.orderNo, fontSize = 13.sp, color = Color(0xFF666666))
+                }
+                // 负责人
+                if (!task.workerUserName.isNullOrEmpty()) Row(Modifier.padding(end = 12.dp), verticalAlignment = Alignment.CenterVertically) {
+                    Icon(
+                        painterResource(R.drawable.user), contentDescription = null, modifier = Modifier
+                            .padding(end = 5.dp)
+                            .size(13.dp),
+                        tint = Color(0xFF666666)
+                    )
+                    Text("负责人:${task.workerUserName}", fontSize = 13.sp, color = Color(0xFF666666))
+                }
+                // 岗位区间,暂时没有字段匹配,先隐藏
+                if (false) Row(Modifier.padding(end = 12.dp), verticalAlignment = Alignment.CenterVertically) {
+                    Icon(
+                        painterResource(R.drawable.location), contentDescription = null, modifier = Modifier
+                            .padding(end = 5.dp)
+                            .size(13.dp),
+                        tint = Color(0xFF1E90FF)
+                    )
+                    Text("车间A区", fontSize = 13.sp, color = Color(0xFF666666))
+                }
+                // Text("作业内容:${task.currentNodeName ?: "--"}", fontSize = 13.sp, color = Color(0xFF666666))
             }
-            // 岗位区间,暂时没有字段匹配,先隐藏
-            if (false) Row(Modifier.padding(end = 12.dp), verticalAlignment = Alignment.CenterVertically) {
-                Icon(
-                    painterResource(R.drawable.location), contentDescription = null, modifier = Modifier
-                        .padding(end = 5.dp)
-                        .size(13.dp),
-                    tint = Color(0xFF1E90FF)
+            Row(
+                Modifier
+                    .padding(top = 5.dp)
+                    .fillMaxWidth()
+                    .height(20.dp),
+                verticalAlignment = Alignment.CenterVertically
+            ) {
+                Text("当前任务:", fontSize = 13.sp, lineHeight = 13.sp, color = Text)
+                Text(
+                    task.currentNodeName ?: "--",
+                    modifier = Modifier
+                        .fillMaxHeight()
+                        .height(18.dp)
+                        .clip(RoundedCornerShape(4.dp))
+                        .background(Color(0xFF1E90FF))
+                        .padding(horizontal = 6.dp),
+                    fontSize = 12.sp,
+                    lineHeight = 18.sp,
+                    fontWeight = FontWeight.Bold,
+                    color = Color.White,
+                    textAlign = TextAlign.Center
                 )
-                Text("车间A区", fontSize = 13.sp, color = Color(0xFF666666))
             }
-            // Text("作业内容:${task.currentNodeName ?: "--"}", fontSize = 13.sp, color = Color(0xFF666666))
-        }
-        Row(
-            Modifier
-                .padding(top = 5.dp)
-                .fillMaxWidth()
-                .height(20.dp),
-            verticalAlignment = Alignment.CenterVertically
-        ) {
-            Text("当前任务:", fontSize = 13.sp, lineHeight = 13.sp, color = Text)
-            Text(
-                task.currentNodeName ?: "--",
-                modifier = Modifier
-                    .fillMaxHeight()
-                    .height(18.dp)
-                    .clip(RoundedCornerShape(4.dp))
-                    .background(Color(0xFF1E90FF))
-                    .padding(horizontal = 6.dp),
-                fontSize = 12.sp,
-                lineHeight = 18.sp,
-                fontWeight = FontWeight.Bold,
-                color = Color.White,
-                textAlign = TextAlign.Center
-            )
         }
     }
 }

+ 30 - 24
app/src/main/java/com/iscs/bozzys/ui/pages/home/HomeCompose.kt

@@ -49,11 +49,11 @@ import androidx.compose.ui.zIndex
 import coil.compose.AsyncImage
 import com.iscs.bozzys.R
 import com.iscs.bozzys.api.Message
+import com.iscs.bozzys.ui.pages.compose.CardContainer
 import com.iscs.bozzys.ui.pages.compose.TaskListItem
 import com.iscs.bozzys.ui.pages.message.openPageMessage
 import com.iscs.bozzys.ui.pages.vm.VMHome
 import com.iscs.bozzys.ui.theme.Text
-import com.iscs.bozzys.utils.getRoleName
 
 @OptIn(ExperimentalMaterial3Api::class)
 @Composable
@@ -120,7 +120,7 @@ private fun TopToolBar(pv: PaddingValues, vmHome: VMHome) {
             }
             Column(Modifier.padding(horizontal = 10.dp)) {
                 Text(state.user.nickname, fontSize = 16.sp, lineHeight = 16.sp, fontWeight = FontWeight.Medium, color = Color.White)
-                Text(state.roles.getRoleName(), fontSize = 12.sp, lineHeight = 12.sp, color = Color.White.copy(alpha = 0.8f))
+                // Text(state.roles.getRoleName(), fontSize = 12.sp, lineHeight = 12.sp, color = Color.White.copy(alpha = 0.8f))
             }
             Spacer(Modifier.weight(1f))
             Box(modifier = Modifier.fillMaxHeight(), contentAlignment = Alignment.Center) {
@@ -282,19 +282,22 @@ private fun TaskList(pv: PaddingValues, vmHome: VMHome) {
             Spacer(Modifier.weight(1f))
             Text("查看全部", fontSize = 14.sp, color = Color(0xFF1E90FF))
         }
-        if (state.homeTasks.isEmpty()) Column(
-            Modifier
-                .padding(bottom = 15.dp)
+        if (state.homeTasks.isEmpty()) CardContainer(
+            modifier = Modifier
+                .padding(vertical = 5.dp)
                 .fillMaxWidth()
-                .height(102.dp)
-                .border(1.dp, color = Color(0xFFEEEEEE), shape = RoundedCornerShape(12.dp))
-                .clip(RoundedCornerShape(12.dp))
-                .background(Color(0xFFF8F9FA))
-                .padding(16.dp),
-            verticalArrangement = Arrangement.Center,
-            horizontalAlignment = Alignment.CenterHorizontally,
+                .height(102.dp),
+            shadowBlur = 6.dp
         ) {
-            Text("您当前暂无任务", fontSize = 14.sp, color = Text)
+            Column(
+                Modifier
+                    .fillMaxSize()
+                    .padding(16.dp),
+                verticalArrangement = Arrangement.Center,
+                horizontalAlignment = Alignment.CenterHorizontally,
+            ) {
+                Text("您当前暂无任务", fontSize = 14.sp, color = Text)
+            }
         }
         Column(Modifier.fillMaxWidth()) {
             state.homeTasks.forEachIndexed { idx, task ->
@@ -316,19 +319,22 @@ private fun TaskList(pv: PaddingValues, vmHome: VMHome) {
             Spacer(Modifier.weight(1f))
             Text("全部消息", fontSize = 14.sp, color = Color(0xFF1E90FF))
         }
-        if (state.messageList.isEmpty()) Column(
-            Modifier
-                .padding(bottom = 15.dp)
+        if (state.messageList.isEmpty()) CardContainer(
+            modifier = Modifier
+                .padding(vertical = 5.dp)
                 .fillMaxWidth()
-                .height(102.dp)
-                .border(1.dp, color = Color(0xFFEEEEEE), shape = RoundedCornerShape(12.dp))
-                .clip(RoundedCornerShape(12.dp))
-                .background(Color(0xFFF8F9FA))
-                .padding(16.dp),
-            verticalArrangement = Arrangement.Center,
-            horizontalAlignment = Alignment.CenterHorizontally,
+                .height(102.dp),
+            shadowBlur = 6.dp
         ) {
-            Text("您当前暂无新消息", fontSize = 14.sp, color = Text)
+            Column(
+                Modifier
+                    .fillMaxSize()
+                    .padding(16.dp),
+                verticalArrangement = Arrangement.Center,
+                horizontalAlignment = Alignment.CenterHorizontally,
+            ) {
+                Text("您当前暂无新消息", fontSize = 14.sp, color = Text)
+            }
         }
         Column(Modifier.fillMaxWidth()) {
             state.messageList.forEach { msg -> key(msg.id) { MessageListItem(msg) } }

+ 42 - 13
app/src/main/java/com/iscs/bozzys/ui/pages/home/JobsCompose.kt

@@ -22,9 +22,11 @@ import androidx.compose.foundation.text.KeyboardOptions
 import androidx.compose.material3.ExperimentalMaterial3Api
 import androidx.compose.material3.Icon
 import androidx.compose.material3.LocalTextStyle
+import androidx.compose.material3.MaterialTheme
 import androidx.compose.material3.Text
 import androidx.compose.material3.pulltorefresh.PullToRefreshBox
 import androidx.compose.runtime.Composable
+import androidx.compose.runtime.LaunchedEffect
 import androidx.compose.runtime.collectAsState
 import androidx.compose.runtime.derivedStateOf
 import androidx.compose.runtime.getValue
@@ -43,6 +45,7 @@ import androidx.compose.ui.platform.LocalSoftwareKeyboardController
 import androidx.compose.ui.res.painterResource
 import androidx.compose.ui.text.font.FontWeight
 import androidx.compose.ui.text.input.ImeAction
+import androidx.compose.ui.text.style.TextAlign
 import androidx.compose.ui.unit.dp
 import androidx.compose.ui.unit.sp
 import androidx.compose.ui.zIndex
@@ -50,8 +53,6 @@ import com.iscs.bozzys.R
 import com.iscs.bozzys.ui.common.Empty
 import com.iscs.bozzys.ui.pages.compose.JobListItem
 import com.iscs.bozzys.ui.pages.create.job.openPageCreateJob
-import com.iscs.bozzys.ui.pages.create.job.openPagePushJob
-import com.iscs.bozzys.ui.pages.edit.step.openPageEditStep
 import com.iscs.bozzys.ui.pages.vm.StatePage
 import com.iscs.bozzys.ui.pages.vm.VMHome
 import com.iscs.bozzys.ui.theme.Main
@@ -63,7 +64,7 @@ fun JobsCompose(pv: PaddingValues, zIndex: Float, vm: VMHome) {
         modifier = Modifier
             .fillMaxSize()
             .zIndex(zIndex)
-            .background(Color.White)
+            .background(MaterialTheme.colorScheme.background)
             .pointerInput(Unit) {},
     ) {
         // 顶部工具栏
@@ -160,7 +161,7 @@ private fun TopToolBar(pv: PaddingValues, vm: VMHome) {
                 keyboardOptions = KeyboardOptions(imeAction = ImeAction.Search),
                 keyboardActions = KeyboardActions(onSearch = {
                     keyboard?.hide()
-                    vm.getJobList(StatePage(page = 1, type = "", keywords = keywords))
+                    vm.getJobList(StatePage(page = 1, type = "", keywords = keywords, isRefresh = true))
                 })
             )
         }
@@ -189,31 +190,31 @@ private fun FilterBar(vm: VMHome) {
                 .background(color = if (state.jobPage.type == "running") Main else Color(0xFFF0F0F0))
                 .clickable(onClick = {
                     keyboard?.hide()
-                    vm.getJobList(state.jobPage.copy(page = 1, type = "running", keywords = ""))
+                    vm.getJobList(state.jobPage.copy(page = 1, type = "running", keywords = "", noMore = false, isRefresh = true))
                 })
                 .padding(horizontal = 12.dp, vertical = 5.dp),
         )
         Text(
-            "已完成", fontSize = 14.sp, color = if (state.jobPage.type == "completed") Color.White else Color(0xFF666666),
+            "待发布", fontSize = 14.sp, color = if (state.jobPage.type == "unreleased") Color.White else Color(0xFF666666),
             modifier = Modifier
                 .padding(end = 10.dp)
                 .clip(RoundedCornerShape(50))
-                .background(color = if (state.jobPage.type == "completed") Main else Color(0xFFF0F0F0))
+                .background(color = if (state.jobPage.type == "unreleased") Main else Color(0xFFF0F0F0))
                 .clickable(onClick = {
                     keyboard?.hide()
-                    vm.getJobList(state.jobPage.copy(page = 1, type = "completed", keywords = ""))
+                    vm.getJobList(state.jobPage.copy(page = 1, type = "unreleased", keywords = "", noMore = false, isRefresh = true))
                 })
                 .padding(horizontal = 12.dp, vertical = 5.dp),
         )
         Text(
-            "已取消", fontSize = 14.sp, color = if (state.jobPage.type == "cancelled") Color.White else Color(0xFF666666),
+            "已完成", fontSize = 14.sp, color = if (state.jobPage.type == "completed") Color.White else Color(0xFF666666),
             modifier = Modifier
                 .padding(end = 10.dp)
                 .clip(RoundedCornerShape(50))
-                .background(color = if (state.jobPage.type == "cancelled") Main else Color(0xFFF0F0F0))
+                .background(color = if (state.jobPage.type == "completed") Main else Color(0xFFF0F0F0))
                 .clickable(onClick = {
                     keyboard?.hide()
-                    vm.getJobList(state.jobPage.copy(page = 1, type = "cancelled", keywords = ""))
+                    vm.getJobList(state.jobPage.copy(page = 1, type = "completed", keywords = "", noMore = false, isRefresh = true))
                 })
                 .padding(horizontal = 12.dp, vertical = 5.dp),
         )
@@ -225,7 +226,7 @@ private fun FilterBar(vm: VMHome) {
                 .background(color = if (state.jobPage.type == "") Main else Color(0xFFF0F0F0))
                 .clickable(onClick = {
                     keyboard?.hide()
-                    vm.getJobList(state.jobPage.copy(page = 1, type = "", keywords = ""))
+                    vm.getJobList(state.jobPage.copy(page = 1, type = "", keywords = "", noMore = false, isRefresh = true))
                 })
                 .padding(horizontal = 12.dp, vertical = 5.dp),
         )
@@ -247,9 +248,24 @@ private fun TaskList(vm: VMHome) {
             listState.firstVisibleItemIndex
         }
     }
+    // 监听列表是否滑动到底部
+    val shouldLoadMore by remember {
+        derivedStateOf {
+            val layoutInfo = listState.layoutInfo
+            val totalItems = layoutInfo.totalItemsCount
+            val lastVisibleItemIndex = layoutInfo.visibleItemsInfo.lastOrNull()?.index ?: 0
+            lastVisibleItemIndex >= totalItems - 2
+        }
+    }
+    // 处理加载更多数据
+    LaunchedEffect(shouldLoadMore) {
+        if (shouldLoadMore && state.jobList.isNotEmpty() && !state.jobPage.noMore) {
+            vm.getJobList(state.jobPage.copy(page = state.jobPage.page + 1, isRefresh = false))
+        }
+    }
     Box {
         PullToRefreshBox(state.jobPage.isRefresh, onRefresh = {
-            vm.getJobList(state.jobPage.copy(page = 1))
+            vm.getJobList(state.jobPage.copy(page = 1, noMore = false, isRefresh = true))
         }, modifier = Modifier.fillMaxSize()) {
             Box(
                 modifier = Modifier
@@ -264,12 +280,25 @@ private fun TaskList(vm: VMHome) {
                     items(state.jobList) { item ->
                         JobListItem(item)
                     }
+                    // 数据不为空才会显示加载中
+                    if (state.jobList.isNotEmpty()) item {
+                        Text(
+                            if (state.jobPage.noMore) "没有更多数据" else "加载更多数据中...",
+                            fontSize = 12.sp,
+                            modifier = Modifier
+                                .fillMaxWidth()
+                                .padding(bottom = 10.dp),
+                            textAlign = TextAlign.Center,
+                            color = Text.copy(alpha = 0.6f)
+                        )
+                    }
                 }
                 // 悬浮在列表的顶部
 //                Box(Modifier.background(Color.White)) {
 //                    DateTitle("${list[topIdx]}")
 //                }
                 if (state.jobList.isEmpty()) Empty("暂无数据")
+
             }
         }
     }

+ 10 - 10
app/src/main/java/com/iscs/bozzys/ui/pages/home/MyCompose.kt

@@ -199,16 +199,16 @@ private fun UserInfo(vm: VMHome) {
                     .weight(1f)
             ) {
                 Text(state.user.nickname, fontWeight = FontWeight.Bold, fontSize = 16.sp, lineHeight = 16.sp, color = Text)
-                Text(
-                    state.roles.getRoleName(),
-                    fontSize = 12.sp,
-                    modifier = Modifier
-                        .padding(top = 5.dp)
-                        .clip(RoundedCornerShape(50))
-                        .background(MaterialTheme.colorScheme.primary)
-                        .padding(horizontal = 5.dp),
-                    color = Color.White
-                )
+//                Text(
+//                    state.roles.getRoleName(),
+//                    fontSize = 12.sp,
+//                    modifier = Modifier
+//                        .padding(top = 5.dp)
+//                        .clip(RoundedCornerShape(50))
+//                        .background(MaterialTheme.colorScheme.primary)
+//                        .padding(horizontal = 5.dp),
+//                    color = Color.White
+//                )
             }
             Icon(
                 painter = painterResource(R.drawable.back),

+ 35 - 5
app/src/main/java/com/iscs/bozzys/ui/pages/home/TasksCompose.kt

@@ -20,9 +20,11 @@ import androidx.compose.foundation.text.KeyboardActions
 import androidx.compose.foundation.text.KeyboardOptions
 import androidx.compose.material3.ExperimentalMaterial3Api
 import androidx.compose.material3.LocalTextStyle
+import androidx.compose.material3.MaterialTheme
 import androidx.compose.material3.Text
 import androidx.compose.material3.pulltorefresh.PullToRefreshBox
 import androidx.compose.runtime.Composable
+import androidx.compose.runtime.LaunchedEffect
 import androidx.compose.runtime.collectAsState
 import androidx.compose.runtime.derivedStateOf
 import androidx.compose.runtime.getValue
@@ -39,6 +41,7 @@ import androidx.compose.ui.input.pointer.pointerInput
 import androidx.compose.ui.platform.LocalSoftwareKeyboardController
 import androidx.compose.ui.text.font.FontWeight
 import androidx.compose.ui.text.input.ImeAction
+import androidx.compose.ui.text.style.TextAlign
 import androidx.compose.ui.unit.dp
 import androidx.compose.ui.unit.sp
 import androidx.compose.ui.zIndex
@@ -55,7 +58,7 @@ fun TasksCompose(pv: PaddingValues, zIndex: Float, vm: VMHome) {
         modifier = Modifier
             .fillMaxSize()
             .zIndex(zIndex)
-            .background(Color.White)
+            .background(MaterialTheme.colorScheme.background)
             .pointerInput(Unit) {},
     ) {
 
@@ -163,7 +166,7 @@ private fun FilterBar(vm: VMHome) {
                 )
                 .clickable(onClick = {
                     keyboard?.hide()
-                    vm.getTaskList(StatePage(type = "running", page = 1, keywords = ""))
+                    vm.getTaskList(StatePage(type = "running", page = 1, keywords = "", isRefresh = true, noMore = false))
                 })
                 .padding(horizontal = 12.dp, vertical = 5.dp),
         )
@@ -175,7 +178,7 @@ private fun FilterBar(vm: VMHome) {
                 .background(color = if (state.taskPage.type == "approved") Main else Color(0xFFF0F0F0))
                 .clickable(onClick = {
                     keyboard?.hide()
-                    vm.getTaskList(StatePage(type = "approved", page = 1, keywords = ""))
+                    vm.getTaskList(StatePage(type = "approved", page = 1, keywords = "", isRefresh = true, noMore = false))
                 })
                 .padding(horizontal = 12.dp, vertical = 5.dp),
         )
@@ -187,7 +190,7 @@ private fun FilterBar(vm: VMHome) {
                 .background(color = if (state.taskPage.type == "") Main else Color(0xFFF0F0F0))
                 .clickable(onClick = {
                     keyboard?.hide()
-                    vm.getTaskList(StatePage(type = "", page = 1, keywords = ""))
+                    vm.getTaskList(StatePage(type = "", page = 1, keywords = "", isRefresh = true, noMore = false))
                 })
                 .padding(horizontal = 12.dp, vertical = 5.dp),
         )
@@ -209,10 +212,25 @@ private fun TaskList(vm: VMHome) {
             listState.firstVisibleItemIndex
         }
     }
+    // 监听列表是否滑动到底部
+    val shouldLoadMore by remember {
+        derivedStateOf {
+            val layoutInfo = listState.layoutInfo
+            val totalItems = layoutInfo.totalItemsCount
+            val lastVisibleItemIndex = layoutInfo.visibleItemsInfo.lastOrNull()?.index ?: 0
+            lastVisibleItemIndex >= totalItems - 2
+        }
+    }
+    // 处理加载更多数据
+    LaunchedEffect(shouldLoadMore) {
+        if (shouldLoadMore && state.taskList.isNotEmpty() && !state.taskPage.noMore) {
+            vm.getJobList(state.taskPage.copy(page = state.taskPage.page + 1, isRefresh = false))
+        }
+    }
     Box {
         PullToRefreshBox(state.taskPage.isRefresh, onRefresh = {
             // 下拉刷新
-            vm.getTaskList(state.taskPage.copy(page = 1))
+            vm.getTaskList(state.taskPage.copy(page = 1, isRefresh = true, noMore = false))
         }, modifier = Modifier.fillMaxSize()) {
             Box(
                 modifier = Modifier
@@ -227,6 +245,18 @@ private fun TaskList(vm: VMHome) {
                     items(state.taskList) { item ->
                         TaskListItem(item)
                     }
+                    // 数据不为空才会显示加载中
+                    if (state.taskList.isNotEmpty()) item {
+                        Text(
+                            if (state.taskPage.noMore) "没有更多数据" else "加载更多数据中...",
+                            fontSize = 12.sp,
+                            modifier = Modifier
+                                .fillMaxWidth()
+                                .padding(bottom = 10.dp),
+                            textAlign = TextAlign.Center,
+                            color = Text.copy(alpha = 0.6f)
+                        )
+                    }
                 }
                 // 悬浮在列表的顶部
 //                Box(Modifier.background(Color.White)) {

+ 34 - 49
app/src/main/java/com/iscs/bozzys/ui/pages/vm/VMHome.kt

@@ -161,6 +161,33 @@ class VMHome : VMBase() {
         }
     }
 
+    /**
+     * 获取作业数据,分页
+     */
+    fun getJobList(page: StatePage) {
+        // 正在刷新禁止重复进行
+        if (_state.value.jobPage.isRefresh) return
+        viewModelScope.launch {
+            // 下拉即刷新
+            _state.value = _state.value.copy(jobPage = _state.value.jobPage.copy(isRefresh = page.isRefresh, type = page.type))
+            // 执行接口数据请求
+            ApiRequest.getJobs(hashMapOf("pageNo" to page.page, "pageSize" to page.pageSize, "status" to page.type, "name" to page.keywords))
+                .onSuccess {
+                    if (page.page == 1) _state.value.jobList.clear()
+                    val jobs = it.data?.list ?: emptyList()
+                    _state.value.jobList.addAll(jobs)
+                    // 存储页面数据
+                    delay(1000)
+                    _state.value =
+                        _state.value.copy(jobPage = page.copy(isRefresh = false, noMore = (it.data?.total ?: 0) == _state.value.jobList.size))
+                }.onFailure {
+                    delay(1000)
+                    _state.value = _state.value.copy(jobPage = _state.value.jobPage.copy(isRefresh = false))
+                    toast.emit(it.getResponse<PageRsp<Job>>().msg)
+                }
+        }
+    }
+
     /**
      * 获取任务列表数据,分页
      */
@@ -169,25 +196,17 @@ class VMHome : VMBase() {
         if (_state.value.taskPage.isRefresh) return
         viewModelScope.launch {
             // 下拉即刷新
-            _state.value = _state.value.copy(
-                taskPage = _state.value.taskPage.copy(
-                    isRefresh = true, type = page.type
-                )
-            )
+            _state.value = _state.value.copy(taskPage = _state.value.taskPage.copy(isRefresh = page.isRefresh, type = page.type))
             ApiRequest.getTasks(
-                hashMapOf(
-                    "pageNo" to page.page,
-                    "pageSize" to page.pageSize,
-                    "approvalStatus" to page.type,
-                    "key" to page.keywords
-                )
+                hashMapOf("pageNo" to page.page, "pageSize" to page.pageSize, "approvalStatus" to page.type, "key" to page.keywords)
             ).onSuccess {
                 if (page.page == 1) _state.value.taskList.clear()
                 val tasks = it.data?.list ?: emptyList()
                 _state.value.taskList.addAll(tasks)
                 delay(1000)
                 // 存储页面数据
-                _state.value = _state.value.copy(taskPage = page.copy(isRefresh = false))
+                _state.value =
+                    _state.value.copy(taskPage = page.copy(isRefresh = false, noMore = (it.data?.total ?: 0) == _state.value.taskList.size))
             }.onFailure {
                 delay(1000)
                 _state.value =
@@ -197,42 +216,6 @@ class VMHome : VMBase() {
         }
     }
 
-    /**
-     * 获取作业数据,分页
-     */
-    fun getJobList(page: StatePage) {
-        // 正在刷新禁止重复进行
-        if (_state.value.jobPage.isRefresh) return
-        viewModelScope.launch {
-            // 下拉即刷新
-            _state.value = _state.value.copy(
-                jobPage = _state.value.jobPage.copy(
-                    isRefresh = true, type = page.type
-                )
-            )
-            ApiRequest.getJobs(
-                hashMapOf(
-                    "pageNo" to page.page,
-                    "pageSize" to page.pageSize,
-                    "status" to page.type,
-                    "name" to page.keywords
-                )
-            ).onSuccess {
-                if (page.page == 1) _state.value.jobList.clear()
-                val tasks = it.data?.list ?: emptyList()
-                _state.value.jobList.addAll(tasks)
-                // 存储页面数据
-                delay(1000)
-                _state.value = _state.value.copy(jobPage = page)
-            }.onFailure {
-                delay(1000)
-                _state.value =
-                    _state.value.copy(jobPage = _state.value.jobPage.copy(isRefresh = false))
-                toast.emit(it.getResponse<PageRsp<Job>>().msg)
-            }
-        }
-    }
-
     /**
      * 退出登录操作
      */
@@ -331,11 +314,13 @@ data class NavBarItem(
  * @param type      请求数据类型 unaudited 默认取进行中的
  * @param keywords  关键字
  * @param isRefresh 是否正在刷新
+ * @param noMore    没有更多数据
  */
 data class StatePage(
     val page: Int = 1,
     val pageSize: Int = 10,
     val type: String = "",
     val keywords: String = "",
-    val isRefresh: Boolean = false
+    val isRefresh: Boolean = false,
+    val noMore: Boolean = true,
 )

+ 2 - 2
app/src/main/java/com/iscs/bozzys/ui/theme/Theme.kt

@@ -25,7 +25,7 @@ private val DarkColorScheme = darkColorScheme(
     tertiary = Main,
     onSurfaceVariant = Main,
     surfaceContainerHigh = Color.Black,
-    background = Color.Black,
+    background = Color(0xFFF8F8F8),
     surfaceContainer = Color.White
 )
 
@@ -36,7 +36,7 @@ private val LightColorScheme = lightColorScheme(
     tertiary = Main,
     onSurfaceVariant = Main,
     surfaceContainerHigh = Color.White,
-    background = Color.White,
+    background = Color(0xFFF8F8F8),
     surfaceContainer = Color.White
 )
 

+ 13 - 0
app/src/main/java/com/iscs/bozzys/utils/DateUtil.kt

@@ -1,6 +1,7 @@
 package com.iscs.bozzys.utils
 
 import android.os.Build
+import android.util.Log
 import java.text.SimpleDateFormat
 import java.time.Instant
 import java.time.LocalDateTime
@@ -52,4 +53,16 @@ object DateUtil {
         }
     }
 
+    /**
+     * 将时间戳转化为可显示的日期
+     */
+    fun Long?.getShowDate(): String {
+        Log.d("xiaoming", "当前使用的时间戳 -> $this")
+        var show = "--"
+        if (this != null && this > 0) {
+            // 执行时间戳的转换
+        }
+        return show
+    }
+
 }