Ver Fonte

1. 新增待归还设备列表
2. 统一作业发起人和任务负责人

bjb há 2 meses atrás
pai
commit
458a46abde

+ 5 - 0
app/src/main/AndroidManifest.xml

@@ -103,6 +103,11 @@
             android:name=".ui.pages.profile.face.PageFace"
             android:exported="false"
             android:screenOrientation="portrait" />
+        <!--  待归还设备列表  -->
+        <activity
+            android:name=".ui.pages.return_device.PageReturnDevice"
+            android:exported="false"
+            android:screenOrientation="portrait" />
 
         <!--  阿里消息推送服务配置  -->
         <service

+ 2 - 2
app/src/main/java/com/iscs/bozzys/ui/common/Empty.kt

@@ -19,9 +19,9 @@ import com.iscs.bozzys.ui.theme.Text
  * 空数据
  */
 @Composable
-fun Empty(tips: String = "", modifier: Modifier = Modifier) {
+fun Empty(modifier: Modifier = Modifier,tips: String = "") {
     Column(modifier = modifier.fillMaxSize(), verticalArrangement = Arrangement.Center, horizontalAlignment = Alignment.CenterHorizontally) {
-        Icon(painter = painterResource(R.drawable.empty), contentDescription = null, modifier = Modifier.size(128.dp), tint = Text.copy(alpha = 0.8f))
+        Icon(painter = painterResource(R.drawable.empty), contentDescription = null, modifier = Modifier.size(72.dp), tint = Text.copy(alpha = 0.5f))
         Text(tips, color = Text.copy(alpha = 0.8f), fontSize = 14.sp)
     }
 }

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

@@ -99,7 +99,7 @@ fun JobListItem(job: Job) {
                             .size(13.dp),
                         tint = Color(0xFF666666)
                     )
-                    Text("发起人:${job.initiatorName}", fontSize = 13.sp, color = Color(0xFF666666))
+                    Text("作业发起人:${job.initiatorName}", fontSize = 13.sp, color = Color(0xFF666666))
                 }
                 // 岗位区间,暂时没有字段匹配,先隐藏
                 if (false) Row(Modifier.padding(end = 12.dp), verticalAlignment = Alignment.CenterVertically) {

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

@@ -89,7 +89,7 @@ fun TaskListItem(task: Task) {
                             .size(13.dp),
                         tint = Color(0xFF666666)
                     )
-                    Text("负责人:${task.workerUserName}", fontSize = 13.sp, color = Color(0xFF666666))
+                    Text("任务负责人:${task.workerUserName}", fontSize = 13.sp, color = Color(0xFF666666))
                 }
                 // 岗位区间,暂时没有字段匹配,先隐藏
                 if (false) Row(Modifier.padding(end = 12.dp), verticalAlignment = Alignment.CenterVertically) {

+ 2 - 2
app/src/main/java/com/iscs/bozzys/ui/pages/detail/job/PageDetailJob.kt

@@ -185,7 +185,7 @@ class PageDetailJob : PageBase() {
                     // 作业编号
                     JobInfoItem(R.drawable.number, "作业编号", state.job.orderNo)
                     // 作业负责人
-                    JobInfoItem(R.drawable.user, "负责人", state.job.initiatorName)
+                    JobInfoItem(R.drawable.user, "作业发起人", state.job.initiatorName)
                     // 作业紧急程度
                     JobInfoItem(R.drawable.job_warning, "紧急程度", state.job.getLevelNameAndColor().first)
                     // 作业状态
@@ -233,7 +233,7 @@ class PageDetailJob : PageBase() {
                 fontSize = 14.sp,
                 color = Text,
                 modifier = Modifier
-                    .width(65.dp)
+                    .width(75.dp)
                     .heightIn(min = 18.dp)
                     .alignBy(FirstBaseline)
             )

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

@@ -47,14 +47,13 @@ import androidx.compose.ui.text.style.TextOverflow
 import androidx.compose.ui.unit.dp
 import androidx.compose.ui.unit.sp
 import androidx.compose.ui.zIndex
-import androidx.lifecycle.lifecycleScope
 import coil.compose.AsyncImage
 import com.iscs.bozzys.R
 import com.iscs.bozzys.api.Message
-import com.iscs.bozzys.ui.common.PageBase
 import com.iscs.bozzys.ui.pages.compose.CardBox
 import com.iscs.bozzys.ui.pages.compose.TaskListItem
 import com.iscs.bozzys.ui.pages.message.openPageMessage
+import com.iscs.bozzys.ui.pages.return_device.openPageReturnDevice
 import com.iscs.bozzys.ui.pages.vm.VMHome
 import com.iscs.bozzys.ui.theme.Text
 import com.iscs.bozzys.utils.DateUtil.getShowDateOrTime
@@ -73,8 +72,6 @@ import com.iscs.bozzys.utils.ble.BleManager
 import com.iscs.bozzys.utils.ble.BleRunMode
 import com.iscs.bozzys.utils.byteArrayToHexString
 import com.iscs.bozzys.utils.getRoleName
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.launch
 
 @OptIn(ExperimentalMaterial3Api::class)
 @Composable
@@ -112,7 +109,14 @@ private fun TopToolBar(pv: PaddingValues, vm: VMHome) {
     Column(
         modifier = Modifier
             .fillMaxWidth()
-            .background(brush = Brush.horizontalGradient(listOf(Color(0xFFFF8C00), Color(0xFFFFA500))))
+            .background(
+                brush = Brush.horizontalGradient(
+                    listOf(
+                        Color(0xFFFF8C00),
+                        Color(0xFFFFA500)
+                    )
+                )
+            )
             .padding(top = pv.calculateTopPadding())
     ) {
         Row(
@@ -137,11 +141,27 @@ private fun TopToolBar(pv: PaddingValues, vm: VMHome) {
                     contentDescription = null,
                     tint = Color.White
                 )
-                AsyncImage(model = state.user.avatar, contentDescription = null, modifier = Modifier.fillMaxSize(), contentScale = ContentScale.Crop)
+                AsyncImage(
+                    model = state.user.avatar,
+                    contentDescription = null,
+                    modifier = Modifier.fillMaxSize(),
+                    contentScale = ContentScale.Crop
+                )
             }
             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.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)
+                )
             }
             Spacer(Modifier.weight(1f))
             Box(modifier = Modifier.fillMaxHeight(), contentAlignment = Alignment.Center) {
@@ -156,8 +176,39 @@ private fun TopToolBar(pv: PaddingValues, vm: VMHome) {
                     tint = Color.White
                 )
                 if (state.msgCount > 0) Text(
-                    if (state.msgCount > 99) "99+" else "${state.msgCount}", color = Color.White, modifier = Modifier
-                        .offset(x = 8.dp, y = 15.dp)
+                    if (state.msgCount > 99) "99+" else "${state.msgCount}",
+                    color = Color.White,
+                    modifier = Modifier
+                        .offset(x = 12.dp, y = 15.dp)
+                        .defaultMinSize(14.dp, 14.dp)
+                        .clip(RoundedCornerShape(14.dp))
+                        .background(Color.Red)
+                        .align(Alignment.TopCenter)
+                        .padding(top = 1.dp)
+                        .padding(horizontal = 2.dp),
+                    textAlign = TextAlign.Center,
+                    fontSize = 10.sp,
+                    lineHeight = 10.sp
+                )
+            }
+            // 待归还设备入口
+            Box(modifier = Modifier.fillMaxHeight(), contentAlignment = Alignment.Center) {
+                Icon(
+                    painter = painterResource(R.drawable.return_device),
+                    contentDescription = null,
+                    modifier = Modifier
+                        .padding(start = 8.dp)
+                        .size(36.dp)
+                        .clip(RoundedCornerShape(6.dp))
+                        .clickable(onClick = { ctx.openPageReturnDevice() })
+                        .padding(7.dp),
+                    tint = Color.White
+                )
+                Text(
+                    if (state.msgCount > 99) "99+" else "${state.msgCount}",
+                    color = Color.White,
+                    modifier = Modifier
+                        .offset(x = 12.dp, y = 15.dp)
                         .defaultMinSize(14.dp, 14.dp)
                         .clip(RoundedCornerShape(14.dp))
                         .background(Color.Red)
@@ -169,25 +220,6 @@ private fun TopToolBar(pv: PaddingValues, vm: VMHome) {
                     lineHeight = 10.sp
                 )
             }
-//            Icon(
-//                painter = painterResource(R.drawable.settings),
-//                contentDescription = null,
-//                modifier = Modifier
-//                    .size(36.dp)
-//                    .clip(RoundedCornerShape(6.dp))
-//                    .clickable(onClick = {
-//                        if (ctx is PageBase) {
-//                            ctx.lifecycleScope.launch(Dispatchers.IO) {
-//                                bleKeyTest(ctx.application, "CC:BA:97:21:72:C6")
-//                                // bleKeyTest(ctx.application, "CC:BA:97:21:71:E6")
-//                                // bleKeyTest(ctx.application, "CC:BA:97:21:72:0A")
-//                                // bleKeyTest(ctx.application, "CC:BA:97:21:71:CA")
-//                            }
-//                        }
-//                    })
-//                    .padding(10.dp),
-//                tint = Color.White
-//            )
         }
     }
 }
@@ -226,7 +258,8 @@ private suspend fun bleKeyTest(application: Application, mac: String) {
         }
         LogUtil.i("xiaoming $mac", "下发作业票:$ticketSendOk")
         // 作业票下发成功,修改设备运行模式为工作模式
-        val switch = bm.writeByResponse(token.buildBLESwitchRunModeCMD(BleRunMode.WORK)).getSwitchRunModeResult()
+        val switch = bm.writeByResponse(token.buildBLESwitchRunModeCMD(BleRunMode.WORK))
+            .getSwitchRunModeResult()
         LogUtil.i("xiaoming $mac", "切换工作模式:$switch")
         // 读取作业票信息
 //            val pkgList = ArrayList<BleTicketDataPackage>()
@@ -285,10 +318,17 @@ private fun TODO(vmHome: VMHome) {
                 horizontalAlignment = Alignment.CenterHorizontally,
                 verticalArrangement = Arrangement.Center
             ) {
-                Text("${state.todoCountRunning}", fontSize = 24.sp, lineHeight = 24.sp, fontWeight = FontWeight.Bold, color = Color(0xFFFFA500))
+                Text(
+                    "${state.todoCountRunning}",
+                    fontSize = 24.sp,
+                    lineHeight = 24.sp,
+                    fontWeight = FontWeight.Bold,
+                    color = Color(0xFFFFA500)
+                )
                 Row(
                     modifier = Modifier.fillMaxWidth(),
-                    horizontalArrangement = Arrangement.Center, verticalAlignment = Alignment.CenterVertically
+                    horizontalArrangement = Arrangement.Center,
+                    verticalAlignment = Alignment.CenterVertically
                 ) {
                     Icon(
                         painterResource(R.drawable.job_ing),
@@ -320,10 +360,17 @@ private fun TODO(vmHome: VMHome) {
                 horizontalAlignment = Alignment.CenterHorizontally,
                 verticalArrangement = Arrangement.Center
             ) {
-                Text("${state.todoCountFinish}", fontSize = 24.sp, lineHeight = 24.sp, fontWeight = FontWeight.Bold, color = Color(0xFF32CD32))
+                Text(
+                    "${state.todoCountFinish}",
+                    fontSize = 24.sp,
+                    lineHeight = 24.sp,
+                    fontWeight = FontWeight.Bold,
+                    color = Color(0xFF32CD32)
+                )
                 Row(
                     modifier = Modifier.fillMaxWidth(),
-                    horizontalArrangement = Arrangement.Center, verticalAlignment = Alignment.CenterVertically
+                    horizontalArrangement = Arrangement.Center,
+                    verticalAlignment = Alignment.CenterVertically
                 ) {
                     Icon(
                         painterResource(R.drawable.job_finish),
@@ -366,9 +413,12 @@ private fun TaskList(pv: PaddingValues, vm: VMHome) {
                 .padding(horizontal = 16.dp)
                 .fillMaxWidth()
                 .height(36.dp)
-                .clickable(indication = null, interactionSource = remember { MutableInteractionSource() }, onClick = {
-                    vm.onTaskProgressClick()
-                }),
+                .clickable(
+                    indication = null,
+                    interactionSource = remember { MutableInteractionSource() },
+                    onClick = {
+                        vm.onTaskProgressClick()
+                    }),
             verticalAlignment = Alignment.CenterVertically
         ) {
             Text("当前任务", fontSize = 14.sp, fontWeight = FontWeight.Medium, color = Text)
@@ -404,9 +454,12 @@ private fun TaskList(pv: PaddingValues, vm: VMHome) {
                 .padding(horizontal = 16.dp)
                 .fillMaxWidth()
                 .height(36.dp)
-                .clickable(indication = null, interactionSource = remember { MutableInteractionSource() }, onClick = {
-                    ctx.openPageMessage()
-                }),
+                .clickable(
+                    indication = null,
+                    interactionSource = remember { MutableInteractionSource() },
+                    onClick = {
+                        ctx.openPageMessage()
+                    }),
             verticalAlignment = Alignment.CenterVertically,
         ) {
             Text("最新消息", fontSize = 14.sp, fontWeight = FontWeight.Medium, color = Text)
@@ -455,7 +508,12 @@ fun MessageListItem(msg: Message, vm: VMHome) {
                     .fillMaxHeight()
                     .weight(1f)
             ) {
-                Text(msg.title ?: "提醒", fontSize = 15.sp, fontWeight = FontWeight.Medium, color = Text)
+                Text(
+                    msg.title ?: "提醒",
+                    fontSize = 15.sp,
+                    fontWeight = FontWeight.Medium,
+                    color = Text
+                )
                 Text(
                     msg.templateContent,
                     fontSize = 13.sp,
@@ -468,7 +526,11 @@ fun MessageListItem(msg: Message, vm: VMHome) {
                 Row(Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically) {
                     Text("作业管理", fontSize = 12.sp, color = Color(0xFF999999))
                     Spacer(Modifier.weight(1f))
-                    Text(msg.createTime.getShowDateOrTime(), fontSize = 12.sp, color = Text.copy(alpha = 0.6f))
+                    Text(
+                        msg.createTime.getShowDateOrTime(),
+                        fontSize = 12.sp,
+                        color = Text.copy(alpha = 0.6f)
+                    )
                 }
             }
 //            Spacer(

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

@@ -93,7 +93,14 @@ private fun TopToolBar(pv: PaddingValues, vm: VMHome) {
     Column(
         modifier = Modifier
             .fillMaxWidth()
-            .background(brush = Brush.horizontalGradient(listOf(Color(0xFFFF8C00), Color(0xFFFFA500))))
+            .background(
+                brush = Brush.horizontalGradient(
+                    listOf(
+                        Color(0xFFFF8C00),
+                        Color(0xFFFFA500)
+                    )
+                )
+            )
             .padding(top = pv.calculateTopPadding() + 8.dp)
     ) {
         Row(
@@ -130,7 +137,14 @@ private fun TopToolBar(pv: PaddingValues, vm: VMHome) {
         }
         Row(
             Modifier
-                .background(brush = Brush.horizontalGradient(listOf(Color(0xFFFF8C00), Color(0xFFFFA500))))
+                .background(
+                    brush = Brush.horizontalGradient(
+                        listOf(
+                            Color(0xFFFF8C00),
+                            Color(0xFFFFA500)
+                        )
+                    )
+                )
                 .padding(horizontal = 16.dp, vertical = 8.dp)
         ) {
             BasicTextField(
@@ -140,10 +154,21 @@ private fun TopToolBar(pv: PaddingValues, vm: VMHome) {
                     .fillMaxWidth()
                     .height(40.dp)
                     .clip(RoundedCornerShape(50))
-                    .background(brush = Brush.horizontalGradient(listOf(Color(0xFFFFA126), Color(0xFFFFB126))))
+                    .background(
+                        brush = Brush.horizontalGradient(
+                            listOf(
+                                Color(0xFFFFA126),
+                                Color(0xFFFFB126)
+                            )
+                        )
+                    )
                     .padding(horizontal = 16.dp),
                 singleLine = true,
-                textStyle = LocalTextStyle.current.copy(fontSize = 16.sp, lineHeight = 18.sp, color = Color.White),
+                textStyle = LocalTextStyle.current.copy(
+                    fontSize = 16.sp,
+                    lineHeight = 18.sp,
+                    color = Color.White
+                ),
                 decorationBox = { innerTextField ->
                     Box(contentAlignment = Alignment.CenterStart) {
                         innerTextField()
@@ -162,7 +187,14 @@ 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, isRefresh = true))
+                    vm.getJobList(
+                        StatePage(
+                            page = 1,
+                            type = "",
+                            keywords = keywords,
+                            isRefresh = true
+                        )
+                    )
                 })
             )
         }
@@ -184,50 +216,98 @@ private fun FilterBar(vm: VMHome) {
             .padding(top = 6.dp)
     ) {
         Text(
-            "进行中", fontSize = 14.sp, color = if (state.jobPage.type == "running") Color.White else Color(0xFF666666),
+            "进行中",
+            fontSize = 14.sp,
+            color = if (state.jobPage.type == "running") Color.White else Color(0xFF666666),
             modifier = Modifier
                 .padding(end = 10.dp)
                 .clip(RoundedCornerShape(50))
                 .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 = "", noMore = false, isRefresh = true))
+                    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 == "unreleased") 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 == "unreleased") 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 = "unreleased", keywords = "", noMore = false, isRefresh = true))
+                    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 == "completed") 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 == "completed") 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 = "completed", keywords = "", noMore = false, isRefresh = true))
+                    vm.getJobList(
+                        state.jobPage.copy(
+                            page = 1,
+                            type = "completed",
+                            keywords = "",
+                            noMore = false,
+                            isRefresh = true
+                        )
+                    )
                 })
                 .padding(horizontal = 12.dp, vertical = 5.dp),
         )
         Text(
-            "全部", fontSize = 14.sp, color = if (state.jobPage.type == "") Color.White else Color(0xFF666666),
+            "全部",
+            fontSize = 14.sp,
+            color = if (state.jobPage.type == "") Color.White else Color(0xFF666666),
             modifier = Modifier
                 .padding(end = 10.dp)
                 .clip(RoundedCornerShape(50))
                 .background(color = if (state.jobPage.type == "") Main else Color(0xFFF0F0F0))
                 .clickable(onClick = {
                     keyboard?.hide()
-                    vm.getJobList(state.jobPage.copy(page = 1, type = "", keywords = "", noMore = false, isRefresh = true))
+                    vm.getJobList(
+                        state.jobPage.copy(
+                            page = 1,
+                            type = "",
+                            keywords = "",
+                            noMore = false,
+                            isRefresh = true
+                        )
+                    )
                 })
                 .padding(horizontal = 12.dp, vertical = 5.dp),
         )
@@ -298,7 +378,7 @@ private fun TaskList(vm: VMHome) {
 //                Box(Modifier.background(Color.White)) {
 //                    DateTitle("${list[topIdx]}")
 //                }
-                if (state.jobList.isEmpty()) Empty("暂无数据")
+                if (state.jobList.isEmpty()) Empty(tips = "暂无数据")
 
             }
         }

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

@@ -85,7 +85,14 @@ private fun TopToolBar(pv: PaddingValues, vm: VMHome) {
     Column(
         modifier = Modifier
             .fillMaxWidth()
-            .background(brush = Brush.horizontalGradient(listOf(Color(0xFFFF8C00), Color(0xFFFFA500))))
+            .background(
+                brush = Brush.horizontalGradient(
+                    listOf(
+                        Color(0xFFFF8C00),
+                        Color(0xFFFFA500)
+                    )
+                )
+            )
             .padding(top = pv.calculateTopPadding() + 8.dp)
     ) {
         Row(
@@ -103,7 +110,14 @@ private fun TopToolBar(pv: PaddingValues, vm: VMHome) {
         }
         Row(
             Modifier
-                .background(brush = Brush.horizontalGradient(listOf(Color(0xFFFF8C00), Color(0xFFFFA500))))
+                .background(
+                    brush = Brush.horizontalGradient(
+                        listOf(
+                            Color(0xFFFF8C00),
+                            Color(0xFFFFA500)
+                        )
+                    )
+                )
                 .padding(horizontal = 16.dp, vertical = 8.dp)
         ) {
             BasicTextField(
@@ -113,10 +127,21 @@ private fun TopToolBar(pv: PaddingValues, vm: VMHome) {
                     .fillMaxWidth()
                     .height(40.dp)
                     .clip(RoundedCornerShape(50))
-                    .background(brush = Brush.horizontalGradient(listOf(Color(0xFFFFA126), Color(0xFFFFB126))))
+                    .background(
+                        brush = Brush.horizontalGradient(
+                            listOf(
+                                Color(0xFFFFA126),
+                                Color(0xFFFFB126)
+                            )
+                        )
+                    )
                     .padding(horizontal = 16.dp),
                 singleLine = true,
-                textStyle = LocalTextStyle.current.copy(fontSize = 16.sp, lineHeight = 18.sp, color = Color.White),
+                textStyle = LocalTextStyle.current.copy(
+                    fontSize = 16.sp,
+                    lineHeight = 18.sp,
+                    color = Color.White
+                ),
                 decorationBox = { innerTextField ->
                     Box(contentAlignment = Alignment.CenterStart) {
                         innerTextField()
@@ -157,7 +182,9 @@ private fun FilterBar(vm: VMHome) {
             .padding(top = 6.dp)
     ) {
         Text(
-            "进行中", fontSize = 14.sp, color = if (state.taskPage.type == "running") Color.White else Color(0xFF666666),
+            "进行中",
+            fontSize = 14.sp,
+            color = if (state.taskPage.type == "running") Color.White else Color(0xFF666666),
             modifier = Modifier
                 .padding(end = 10.dp)
                 .clip(RoundedCornerShape(50))
@@ -166,31 +193,63 @@ private fun FilterBar(vm: VMHome) {
                 )
                 .clickable(onClick = {
                     keyboard?.hide()
-                    vm.getTaskList(StatePage(type = "running", page = 1, keywords = "", isRefresh = true, noMore = false))
+                    vm.getTaskList(
+                        StatePage(
+                            type = "running",
+                            page = 1,
+                            keywords = "",
+                            isRefresh = true,
+                            noMore = false
+                        )
+                    )
                 })
                 .padding(horizontal = 12.dp, vertical = 5.dp),
         )
         Text(
-            "已完成", fontSize = 14.sp, color = if (state.taskPage.type == "approved") Color.White else Color(0xFF666666),
+            "已完成",
+            fontSize = 14.sp,
+            color = if (state.taskPage.type == "approved") Color.White else Color(0xFF666666),
             modifier = Modifier
                 .padding(end = 10.dp)
                 .clip(RoundedCornerShape(50))
-                .background(color = if (state.taskPage.type == "approved") Main else Color(0xFFF0F0F0))
+                .background(
+                    color = if (state.taskPage.type == "approved") Main else Color(
+                        0xFFF0F0F0
+                    )
+                )
                 .clickable(onClick = {
                     keyboard?.hide()
-                    vm.getTaskList(StatePage(type = "approved", page = 1, keywords = "", isRefresh = true, noMore = false))
+                    vm.getTaskList(
+                        StatePage(
+                            type = "approved",
+                            page = 1,
+                            keywords = "",
+                            isRefresh = true,
+                            noMore = false
+                        )
+                    )
                 })
                 .padding(horizontal = 12.dp, vertical = 5.dp),
         )
         Text(
-            "全部", fontSize = 14.sp, color = if (state.taskPage.type == "") Color.White else Color(0xFF666666),
+            "全部",
+            fontSize = 14.sp,
+            color = if (state.taskPage.type == "") Color.White else Color(0xFF666666),
             modifier = Modifier
                 .padding(end = 10.dp)
                 .clip(RoundedCornerShape(50))
                 .background(color = if (state.taskPage.type == "") Main else Color(0xFFF0F0F0))
                 .clickable(onClick = {
                     keyboard?.hide()
-                    vm.getTaskList(StatePage(type = "", page = 1, keywords = "", isRefresh = true, noMore = false))
+                    vm.getTaskList(
+                        StatePage(
+                            type = "",
+                            page = 1,
+                            keywords = "",
+                            isRefresh = true,
+                            noMore = false
+                        )
+                    )
                 })
                 .padding(horizontal = 12.dp, vertical = 5.dp),
         )
@@ -262,7 +321,7 @@ private fun TaskList(vm: VMHome) {
 //                Box(Modifier.background(Color.White)) {
 //                    DateTitle("${list[topIdx]}")
 //                }
-                if (state.taskList.isEmpty()) Empty("暂无数据")
+                if (state.taskList.isEmpty()) Empty(tips = "暂无数据")
             }
         }
     }

+ 1 - 1
app/src/main/java/com/iscs/bozzys/ui/pages/message/PageMessage.kt

@@ -233,7 +233,7 @@ private fun MessageList(vm: VMMessage) {
                     )
                 }
             }
-            if (state.messages.isEmpty()) Empty("暂无消息")
+            if (state.messages.isEmpty()) Empty(tips = "暂无消息")
             // 悬浮在列表的顶部
             if (state.messages.isNotEmpty()) Box(
                 Modifier.background(MaterialTheme.colorScheme.background),

+ 312 - 0
app/src/main/java/com/iscs/bozzys/ui/pages/return_device/PageReturnDevice.kt

@@ -0,0 +1,312 @@
+package com.iscs.bozzys.ui.pages.return_device
+
+import android.content.Context
+import android.content.Intent
+import androidx.compose.foundation.background
+import androidx.compose.foundation.clickable
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.PaddingValues
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.fillMaxHeight
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.layout.width
+import androidx.compose.foundation.lazy.rememberLazyListState
+import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.material3.ExperimentalMaterial3Api
+import androidx.compose.material3.Icon
+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
+import androidx.compose.runtime.remember
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.clip
+import androidx.compose.ui.graphics.Brush
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.res.painterResource
+import androidx.compose.ui.text.font.FontWeight
+import androidx.compose.ui.text.style.TextAlign
+import androidx.compose.ui.text.style.TextOverflow
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.sp
+import androidx.lifecycle.viewmodel.compose.viewModel
+import com.iscs.bozzys.R
+import com.iscs.bozzys.api.Message
+import com.iscs.bozzys.ui.common.Empty
+import com.iscs.bozzys.ui.common.PageBase
+import com.iscs.bozzys.ui.dialog.TipsDialog
+import com.iscs.bozzys.ui.pages.compose.CardBox
+import com.iscs.bozzys.ui.pages.vm.StatePageMessage
+import com.iscs.bozzys.ui.pages.vm.VMMessage
+import com.iscs.bozzys.ui.theme.Text
+import com.iscs.bozzys.utils.DateUtil.getShowDate
+import com.iscs.bozzys.utils.DateUtil.getShowDateOrTime
+
+/**
+ * 打开消息中心页面
+ */
+fun Context.openPageReturnDevice() {
+    startActivity(Intent(this, PageReturnDevice::class.java))
+}
+
+/**
+ * 归还设备
+ */
+class PageReturnDevice : PageBase() {
+    @Composable
+    override fun GetViews(pv: PaddingValues) {
+        val vm: VMMessage = viewModel()
+        val state by vm.state.collectAsState()
+        LaunchedEffect(Unit) {
+            vm.toast.initToast()
+            vm.loading.initLoading()
+            vm.init()
+        }
+        Box(
+            modifier = Modifier
+                .fillMaxSize()
+                .background(MaterialTheme.colorScheme.background)
+        ) {
+            // 顶部工具栏
+            Column(
+                modifier = Modifier
+                    .padding(bottom = pv.calculateBottomPadding())
+                    .fillMaxSize()
+            ) {
+                TopToolBar(pv, vm)
+                MessageList(vm)
+            }
+            // 提示弹窗
+            TipsDialog(
+                show = state.tips.show, title = state.tips.title, content = state.tips.content,
+                onCancel = { vm.hideTips() },
+                onConfirm = { vm.onTipsConfirm() })
+        }
+    }
+
+
+    /**
+     * 顶部工具栏
+     */
+    @Composable
+    private fun TopToolBar(pv: PaddingValues, vm: VMMessage) {
+        Column(
+            modifier = Modifier
+                .fillMaxWidth()
+                .background(
+                    brush = Brush.horizontalGradient(
+                        listOf(
+                            Color(0xFFFF8C00),
+                            Color(0xFFFFA500)
+                        )
+                    )
+                )
+                .padding(top = pv.calculateTopPadding())
+        ) {
+            Row(
+                modifier = Modifier
+                    .fillMaxWidth()
+                    .height(66.dp)
+                    .padding(horizontal = 10.dp),
+                verticalAlignment = Alignment.CenterVertically
+            ) {
+                Row(
+                    Modifier
+                        .width(80.dp)
+                        .padding(start = 6.dp)
+                ) {
+                    Icon(
+                        painter = painterResource(R.drawable.back),
+                        contentDescription = "",
+                        modifier = Modifier
+                            .size(32.dp)
+                            .clip(RoundedCornerShape(50))
+                            .background(Color(0xFFFFA126))
+                            .clickable(onClick = { destroy() })
+                            .padding(8.dp),
+                        tint = Color.White
+                    )
+                }
+                Text(
+                    "待归还设备列表",
+                    fontSize = 18.sp,
+                    color = Color.White,
+                    fontWeight = FontWeight.Medium,
+                    modifier = Modifier.weight(1f),
+                    textAlign = TextAlign.Center
+                )
+                Row(Modifier.width(80.dp)) {
+
+                }
+            }
+        }
+    }
+
+}
+
+/**
+ * 消息列表
+ */
+@OptIn(ExperimentalMaterial3Api::class)
+@Composable
+private fun MessageList(vm: VMMessage) {
+    val state by vm.state.collectAsState()
+    // 监听顶部Item
+    val listState = rememberLazyListState()
+    // 当前顶部Item
+    val topIdx by remember {
+        derivedStateOf {
+            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.messages.isNotEmpty() && !state.page.noMore) {
+            vm.getMessage(state.page.copy(page = state.page.page + 1, isRefresh = false))
+        }
+    }
+    PullToRefreshBox(state.page.isRefresh, onRefresh = {
+        vm.getMessage(StatePageMessage(isRefresh = true, page = 1))
+    }, modifier = Modifier.fillMaxSize()) {
+        Box(
+            modifier = Modifier
+                .padding(top = 5.dp)
+                .fillMaxSize()
+        ) {
+//            LazyColumn(
+//                state = listState,
+//                modifier = Modifier.fillMaxSize()
+//            ) {
+//                items(state.messages) { item ->
+//                    if (item.uiIsTitle) {
+//                        MessageListItemTitle(item)
+//                    } else {
+//                        MessageListItemContent(vm, item)
+//                    }
+//                }
+//                // 数据不为空才会显示加载中
+//                if (state.messages.isNotEmpty()) item {
+//                    Text(
+//                        if (state.page.noMore) "没有更多数据" else "加载更多数据中...",
+//                        fontSize = 12.sp,
+//                        modifier = Modifier
+//                            .fillMaxWidth()
+//                            .padding(bottom = 10.dp),
+//                        textAlign = TextAlign.Center,
+//                        color = Text.copy(alpha = 0.6f)
+//                    )
+//                }
+//            }
+            Empty(tips = "暂无待归还设备")
+//            // 悬浮在列表的顶部
+//            if (state.messages.isNotEmpty()) Box(
+//                Modifier.background(MaterialTheme.colorScheme.background),
+//                contentAlignment = Alignment.CenterStart
+//            ) {
+//                MessageListItemTitle(state.messages[topIdx])
+//            }
+        }
+    }
+}
+
+/**
+ * 消息标题
+ */
+@Composable
+private fun MessageListItemTitle(message: Message) {
+    Text(
+        message.createTime.getShowDate(),
+        fontSize = 16.sp,
+        lineHeight = 26.sp,
+        fontWeight = FontWeight.Medium,
+        color = Text,
+        modifier = Modifier
+            .fillMaxWidth()
+            .height(26.dp)
+            .padding(horizontal = 16.dp),
+    )
+}
+
+/**
+ * 消息内容
+ */
+@Composable
+private fun MessageListItemContent(vm: VMMessage, msg: Message) {
+    CardBox(modifier = Modifier.padding(vertical = 8.dp, horizontal = 16.dp)) {
+        Row(
+            Modifier
+                .fillMaxWidth()
+                .height(122.dp)
+                .clickable(onClick = { vm.onMessage(msg) })
+                .padding(16.dp)
+        ) {
+            Icon(
+                painterResource(R.drawable.bell), contentDescription = null,
+                modifier = Modifier
+                    .size(40.dp)
+                    .clip(RoundedCornerShape(50))
+                    .background(MaterialTheme.colorScheme.primary)
+                    .padding(8.dp),
+                tint = Color.White
+            )
+            Column(
+                Modifier
+                    .padding(start = 15.dp, end = 10.dp)
+                    .fillMaxHeight()
+                    .weight(1f)
+            ) {
+                Text(
+                    msg.title ?: "提醒",
+                    fontSize = 15.sp,
+                    fontWeight = FontWeight.Medium,
+                    color = Text
+                )
+                Text(
+                    msg.templateContent,
+                    fontSize = 13.sp,
+                    color = Color(0xFF666666),
+                    overflow = TextOverflow.Ellipsis,
+                    maxLines = 2,
+                    modifier = Modifier.fillMaxWidth()
+                )
+                Spacer(Modifier.weight(1f))
+                Row(Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically) {
+                    Text(
+                        msg.createTime.getShowDateOrTime(),
+                        fontSize = 12.sp,
+                        color = Color(0xFF999999)
+                    )
+                    Spacer(Modifier.weight(1f))
+                    Text("作业管理", fontSize = 13.sp, color = Color(0xFF999999))
+                }
+            }
+            Spacer(
+                Modifier
+                    .size(8.dp)
+                    .clip(RoundedCornerShape(50))
+                    .background(if (msg.readStatus) Color.Transparent else Color(0xFFFF4500))
+                    .align(Alignment.CenterVertically)
+            )
+        }
+    }
+}

Diff do ficheiro suprimidas por serem muito extensas
+ 2 - 2
app/src/main/res/drawable/empty.xml


+ 12 - 0
app/src/main/res/drawable/return_device.xml

@@ -0,0 +1,12 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="200dp"
+    android:height="200dp"
+    android:viewportWidth="1024"
+    android:viewportHeight="1024">
+  <path
+      android:pathData="M493.6,199.2c0,-10.5 8.2,-18.7 18.7,-18.7h25.6l-99.1,-102.4 -99.1,102.4h25.6c10.5,0 17.4,8.2 17.4,18.7v132.9c0,10.5 -8.2,18.7 -17.4,18.7 -9.2,0 -17.4,-8.2 -17.4,-18.7V217.9h-51.2c-9.2,0 -17.4,-9.2 -17.4,-18.7 0,-4.6 2.3,-9.2 4.6,-12.8l143.4,-149.2c6.9,-6.9 18.7,-6.9 25.6,0L593.9,185.1c6.9,6.9 6.9,19.7 0,26.9 -3.6,3.6 -8.2,5.9 -12.8,5.9h-52.5v165.4c0,10.5 -8.2,18.7 -17.4,18.7h-25.6l99.1,102.4 99.1,-102.4h-25.6c-9.2,0 -17.4,-8.2 -17.4,-18.7V250.4c0,-10.5 8.2,-18.7 17.4,-18.7 10.5,0 18.7,8.2 18.7,18.7v114.2H727c4.6,0 9.2,1.3 12.8,5.9 6.9,6.9 6.9,18.7 0,26.9L598.5,542.7c-6.9,6.9 -18.7,6.9 -25.6,0l-143.4,-146.7c-3.6,-3.6 -4.6,-8.2 -4.6,-12.8 0,-10.5 8.2,-18.7 17.4,-18.7h51.2V199.2z"
+      android:fillColor="#1296db"/>
+  <path
+      android:pathData="M992.3,566.8l-102.9,-243.2c-12.8,-23.8 -37.4,-38.7 -64.5,-38.7h-88.8v80.4h45.3c2.8,0 5.1,1.5 6.4,4.1l75.3,197.4c0.5,1 0.8,2.3 0.8,3.3 0,4.1 -3.3,7.2 -7.2,7.2L177.7,577.3c-1.3,0 -2.3,-0.3 -3.6,-0.8 -3.6,-1.8 -4.9,-6.1 -3.1,-9.7l75.3,-197.4c1.3,-2.6 3.8,-4.1 6.4,-4.1h45.3v-80.4L209.4,284.9c-27.1,0 -52,15.1 -64.5,38.9l-103.2,245.5 -0.5,363c0,40.4 32.8,73.2 73.2,73.2L919,1005.6c40.4,0 73.2,-32.8 73.2,-73.2L992.3,566.8zM644.9,805.9c0,16.9 -13.8,30.7 -30.7,30.7h-194.6c-16.9,0 -30.7,-13.8 -30.7,-30.7v-15.4c0,-16.9 13.8,-30.7 30.7,-30.7h194.6c16.9,0 30.7,13.8 30.7,30.7v15.4z"
+      android:fillColor="#1296db"/>
+</vector>

Alguns ficheiros não foram mostrados porque muitos ficheiros mudaram neste diff