Преглед изворни кода

1. 消息通知接口对接完成

bjb пре 4 месеци
родитељ
комит
15540ff0da

+ 2 - 2
.idea/deploymentTargetSelector.xml

@@ -4,10 +4,10 @@
     <selectionStates>
       <SelectionState runConfigName="app">
         <option name="selectionMode" value="DROPDOWN" />
-        <DropdownSelection timestamp="2026-01-07T07:43:33.274121Z">
+        <DropdownSelection timestamp="2026-01-12T05:11:25.765749800Z">
           <Target type="DEFAULT_BOOT">
             <handle>
-              <DeviceId pluginId="PhysicalDevice" identifier="serial=d8d12db95670c08" />
+              <DeviceId pluginId="PhysicalDevice" identifier="serial=D1CGAPE741200820" />
             </handle>
           </Target>
         </DropdownSelection>

+ 11 - 2
app/src/main/java/com/iscs/bozzys/api/ApiBean.kt

@@ -659,10 +659,19 @@ data class Task(
 ) : java.io.Serializable
 
 /**
- * 消息
+ * 消息结构体
  */
 @Serializable
-data class Message(val id: Int = 0)
+data class Message(
+    val id: Int = 0,
+    val userId: Int = 0,
+    val userType: Int = 0,
+    val readStatus: Boolean = false,
+    val createTime: Long = -1L,
+    val title: String? = null,
+    val templateContent: String = "",
+    val isTitle: Boolean = false,
+)
 
 /**
  * 表单需要的组件

+ 16 - 0
app/src/main/java/com/iscs/bozzys/api/ApiRequest.kt

@@ -264,4 +264,20 @@ object ApiRequest {
         return requestApi { api.getIsolationPointList(params) }
     }
 
+    /**
+     * 获取所有消息
+     */
+    suspend fun getMessage(params: MutableMap<String, Any>): Result<Response<PageRsp<Message>>> {
+        return requestApi { api.getMessages(params) }
+    }
+
+    /**
+     * 更新消息为已读
+     *
+     * @param params 请求参数 如果什么参数都不传,默认标记所有消息为已读
+     */
+    suspend fun updateMessageRead(params: MutableMap<String, Any>): Result<Response<Boolean>> {
+        return requestApi { if (params.isNotEmpty()) api.updateMessageRead(params) else api.updateMessageAllRead() }
+    }
+
 }

+ 27 - 0
app/src/main/java/com/iscs/bozzys/api/ApiService.kt

@@ -213,4 +213,31 @@ interface ApiService {
         @HeaderMap headers: Map<String, String> = ApiRequest.getUserHeaders()
     ): Response<PageRsp<IsolationPoint>>
 
+    /**
+     * 获取通知消息
+     */
+    @Headers("Content-Type: application/x-www-form-urlencoded")
+    @GET("/admin-api/system/app-notify-message/page")
+    suspend fun getMessages(
+        @QueryMap params: MutableMap<String, Any>,
+        @HeaderMap headers: Map<String, String> = ApiRequest.getUserHeaders()
+    ): Response<PageRsp<Message>>
+
+    /**
+     * 更新消息为已读
+     */
+    @Headers("Content-Type: application/x-www-form-urlencoded")
+    @PUT("/admin-api/system/app-notify-message/update-read")
+    suspend fun updateMessageRead(
+        @QueryMap params: MutableMap<String, Any>,
+        @HeaderMap headers: Map<String, String> = ApiRequest.getUserHeaders()
+    ): Response<Boolean>
+
+    /**
+     * 标记所有消息为已读
+     */
+    @Headers("Content-Type: application/x-www-form-urlencoded")
+    @PUT("/admin-api/system/app-notify-message/update-all-read")
+    suspend fun updateMessageAllRead(@HeaderMap headers: Map<String, String> = ApiRequest.getUserHeaders()): Response<Boolean>
+
 }

+ 3 - 1
app/src/main/java/com/iscs/bozzys/ui/common/Dialog.kt

@@ -92,4 +92,6 @@ fun TipsDialog(
         }
     }
 
-}
+}
+
+data class StateTips(val title: String = "", val content: String = "", val show: Boolean = false, val type: String = "")

+ 9 - 9
app/src/main/java/com/iscs/bozzys/ui/common/PageBase.kt

@@ -161,16 +161,16 @@ abstract class PageBase(
     /**
      * 显示Toast,通过字符串
      */
-    fun Any.showToast() {
+    fun Any.initToast() {
         lifecycleScope.launch(Dispatchers.Main) {
-            when (this@showToast) {
+            when (this@initToast) {
                 // 显示字符串Toast
                 is String -> {
-                    Toast.makeText(this@PageBase, this@showToast, Toast.LENGTH_LONG).show()
+                    Toast.makeText(this@PageBase, this@initToast, Toast.LENGTH_LONG).show()
                 }
                 // 显示资源id Toast
                 is Int -> {
-                    Toast.makeText(this@PageBase, this@showToast, Toast.LENGTH_LONG).show()
+                    Toast.makeText(this@PageBase, this@initToast, Toast.LENGTH_LONG).show()
                 }
             }
         }
@@ -179,14 +179,14 @@ abstract class PageBase(
     /**
      * 显示toast,Flow方式
      */
-    fun MutableSharedFlow<Any>.showToast() {
-        lifecycleScope.async { this@showToast.collect { msg -> msg.showToast() } }
+    fun MutableSharedFlow<Any>.initToast() {
+        lifecycleScope.async { this@initToast.collect { msg -> msg.initToast() } }
     }
 
     /**
      * 显示全局Loading
      */
-    fun showLoading() {
+    fun initLoading() {
         loading?.show()
     }
 
@@ -200,9 +200,9 @@ abstract class PageBase(
     /**
      * 显示loading,Flow方式
      */
-    fun MutableSharedFlow<StateLoading>.showLoading() {
+    fun MutableSharedFlow<StateLoading>.initLoading() {
         lifecycleScope.async {
-            this@showLoading.collect { stateLoading ->
+            this@initLoading.collect { stateLoading ->
                 if (stateLoading.show) {
                     loading?.show(stateLoading)
                 } else {

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

@@ -55,8 +55,8 @@ class PageCreateJob : PageBase() {
         val vm: VMCreateJob = viewModel()
         val state by vm.state.collectAsState()
         LaunchedEffect(Unit) {
-            vm.toast.showToast()
-            vm.loading.showLoading()
+            vm.toast.initToast()
+            vm.loading.initLoading()
             vm.init(id)
         }
         Column(

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

@@ -50,8 +50,8 @@ class PagePushJob : PageBase() {
         val id = intent.getIntExtra("id", 0)
         val state by vm.state.collectAsState()
         LaunchedEffect(Unit) {
-            vm.toast.showToast()
-            vm.loading.showLoading()
+            vm.toast.initToast()
+            vm.loading.initLoading()
         }
         Column(Modifier.fillMaxSize()) {
             Title(pv, "发布作业")

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

@@ -71,8 +71,8 @@ class PageDetailJob : PageBase() {
         val state by vm.state.collectAsState()
         // val pb = pv.calculateBottomPadding()
         LaunchedEffect(Unit) {
-            vm.toast.showToast()
-            vm.loading.showLoading()
+            vm.toast.initToast()
+            vm.loading.initLoading()
             vm.init(id)
         }
         Column(modifier = Modifier.background(Color(0xFFF8F8F8))) {

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

@@ -81,8 +81,8 @@ class PageDetailTask : PageBase() {
         if (!getPageData()) return
         val vm: VMDetailTask = viewModel()
         LaunchedEffect(Unit) {
-            vm.toast.showToast()
-            vm.loading.showLoading()
+            vm.toast.initToast()
+            vm.loading.initLoading()
             vm.getTaskFormInfo(task)
         }
         val state by vm.state.collectAsState()

+ 2 - 2
app/src/main/java/com/iscs/bozzys/ui/pages/edit/step/PageEditStep.kt

@@ -86,8 +86,8 @@ class PageEditStep : PageBase() {
         val vm: VMEditStep = viewModel()
         val state by vm.state.collectAsState()
         LaunchedEffect(Unit) {
-            vm.toast.showToast()
-            vm.loading.showLoading()
+            vm.toast.initToast()
+            vm.loading.initLoading()
             vm.init(intent.getIntExtra("id", 0))
         }
         // 页面布局容器

+ 2 - 2
app/src/main/java/com/iscs/bozzys/ui/pages/home/PageHome.kt

@@ -61,8 +61,8 @@ class PageHome : PageBase() {
         val state by vm.state.collectAsState()
         LaunchedEffect(Unit) {
             // 处理基础Toast和Loading提示
-            vm.toast.showToast()
-            vm.loading.showLoading()
+            vm.toast.initToast()
+            vm.loading.initLoading()
             vm.init()
         }
         Scaffold(

+ 2 - 4
app/src/main/java/com/iscs/bozzys/ui/pages/login/PageLogin.kt

@@ -2,7 +2,6 @@ package com.iscs.bozzys.ui.pages.login
 
 import android.content.Context
 import android.content.Intent
-import androidx.biometric.BiometricPrompt
 import androidx.compose.foundation.background
 import androidx.compose.foundation.border
 import androidx.compose.foundation.clickable
@@ -55,7 +54,6 @@ import com.iscs.bozzys.ui.theme.Main
 import com.iscs.bozzys.ui.theme.Text
 import com.iscs.bozzys.ui.theme.TextDesc
 import com.iscs.bozzys.utils.SystemUtil.isBiometricCanUse
-import com.iscs.bozzys.utils.SystemUtil.showFingerAuth
 
 /**
  * 打开登录页面
@@ -125,8 +123,8 @@ class PageLogin : PageBase() {
         val finger = ctx.isBiometricCanUse()
         LaunchedEffect(Unit) {
             // 处理基础Toast和Loading提示
-            vm.toast.showToast()
-            vm.loading.showLoading()
+            vm.toast.initToast()
+            vm.loading.initLoading()
         }
         Column(
             Modifier

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

@@ -3,7 +3,6 @@ package com.iscs.bozzys.ui.pages.message
 import android.content.Context
 import android.content.Intent
 import androidx.compose.foundation.background
-import androidx.compose.foundation.border
 import androidx.compose.foundation.clickable
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.Column
@@ -23,12 +22,14 @@ 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.mutableStateOf
 import androidx.compose.runtime.remember
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
@@ -41,9 +42,18 @@ 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.common.TipsDialog
+import com.iscs.bozzys.ui.pages.compose.CardContainer
+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
 
 /**
  * 打开消息中心页面
@@ -58,10 +68,17 @@ fun Context.openPageMessage() {
 class PageMessage : 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(Color.White)
+                .background(MaterialTheme.colorScheme.background)
         ) {
             // 顶部工具栏
             Column(
@@ -69,9 +86,14 @@ class PageMessage : PageBase() {
                     .padding(bottom = pv.calculateBottomPadding())
                     .fillMaxSize()
             ) {
-                TopToolBar(pv)
-                MessageList()
+                TopToolBar(pv, vm)
+                MessageList(vm)
             }
+            // 提示弹窗
+            TipsDialog(
+                show = state.tips.show, title = state.tips.title, content = state.tips.content,
+                onCancel = { vm.hideTips() },
+                onConfirm = { vm.onTipsConfirm() })
         }
     }
 
@@ -80,7 +102,7 @@ class PageMessage : PageBase() {
      * 顶部工具栏
      */
     @Composable
-    private fun TopToolBar(pv: PaddingValues) {
+    private fun TopToolBar(pv: PaddingValues, vm: VMMessage) {
         Column(
             modifier = Modifier
                 .fillMaxWidth()
@@ -126,7 +148,7 @@ class PageMessage : PageBase() {
                         modifier = Modifier
                             .size(36.dp)
                             .clip(RoundedCornerShape(6.dp))
-                            .clickable(onClick = {})
+                            .clickable(onClick = { vm.onReadAll() })
                             .padding(8.dp),
                         tint = Color.White
                     )
@@ -136,7 +158,7 @@ class PageMessage : PageBase() {
                         modifier = Modifier
                             .size(36.dp)
                             .clip(RoundedCornerShape(6.dp))
-                            .clickable(onClick = {})
+                            .clickable(onClick = { vm.onDeleteAll() })
                             .padding(9.dp),
                         tint = Color.White
                     )
@@ -152,9 +174,8 @@ class PageMessage : PageBase() {
  */
 @OptIn(ExperimentalMaterial3Api::class)
 @Composable
-private fun MessageList() {
-    val isRefresh = remember { mutableStateOf(false) }
-    val list = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9)
+private fun MessageList(vm: VMMessage) {
+    val state by vm.state.collectAsState()
     // 监听顶部Item
     val listState = rememberLazyListState()
     // 当前顶部Item
@@ -163,30 +184,45 @@ private fun MessageList() {
             listState.firstVisibleItemIndex
         }
     }
-    PullToRefreshBox(isRefresh.value, onRefresh = {
-        isRefresh.value = true
+    PullToRefreshBox(state.page.isRefresh, onRefresh = {
+        vm.getMessage(StatePageMessage(isRefresh = true, page = 1))
     }, modifier = Modifier.fillMaxSize()) {
         Box(
             modifier = Modifier
                 .padding(top = 5.dp)
                 .fillMaxSize()
-                .padding(horizontal = 16.dp)
         ) {
             LazyColumn(
                 state = listState,
                 modifier = Modifier.fillMaxSize()
             ) {
-                items(list) { item ->
-                    when (item) {
-                        1 -> MessageListItemTitle("今天")
-                        6 -> MessageListItemTitle("昨天")
-                        else -> MessageListItemContent(item)
+                items(state.messages) { item ->
+                    if (item.isTitle) {
+                        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)
+                    )
+                }
             }
+            if (state.messages.isEmpty()) Empty("暂无消息")
             // 悬浮在列表的顶部
-            Box(Modifier.background(Color.White)) {
-                MessageListItemTitle("${list[topIdx]}")
+            if (state.messages.isNotEmpty()) Box(
+                Modifier.background(MaterialTheme.colorScheme.background),
+                contentAlignment = Alignment.CenterStart
+            ) {
+                MessageListItemTitle(state.messages[topIdx])
             }
         }
     }
@@ -196,17 +232,17 @@ private fun MessageList() {
  * 消息标题
  */
 @Composable
-private fun MessageListItemTitle(title: String) {
+private fun MessageListItemTitle(message: Message) {
     Text(
-        title,
+        message.createTime.getShowDate(),
         fontSize = 16.sp,
-        lineHeight = 22.sp,
+        lineHeight = 26.sp,
         fontWeight = FontWeight.Medium,
         color = Text,
         modifier = Modifier
-            .padding(bottom = 10.dp)
             .fillMaxWidth()
-            .height(22.dp)
+            .height(26.dp)
+            .padding(horizontal = 16.dp),
     )
 }
 
@@ -214,54 +250,52 @@ private fun MessageListItemTitle(title: String) {
  * 消息内容
  */
 @Composable
-private fun MessageListItemContent(item: Int) {
-    Row(
-        Modifier
-            .padding(bottom = 15.dp)
-            .fillMaxWidth()
-            .height(122.dp)
-            .border(1.dp, color = Color(0xFFEEEEEE), shape = RoundedCornerShape(12.dp))
-            .clip(RoundedCornerShape(12.dp))
-            .background(Color(0xFFF8F9FA))
-            .clickable(onClick = {})
-            .padding(16.dp)
-    ) {
-        Icon(
-            painterResource(R.drawable.delete_all), contentDescription = null,
-            modifier = Modifier
-                .size(40.dp)
-                .clip(RoundedCornerShape(50))
-                .background(Color(0xFF1E90FF))
-                .padding(12.dp)
-        )
-        Column(
+private fun MessageListItemContent(vm: VMMessage, msg: Message) {
+    CardContainer(modifier = Modifier.padding(vertical = 8.dp, horizontal = 16.dp)) {
+        Row(
             Modifier
-                .padding(start = 15.dp, end = 10.dp)
-                .fillMaxHeight()
-                .weight(1f)
+                .fillMaxWidth()
+                .height(122.dp)
+                .clickable(onClick = { vm.onMessage(msg) })
+                .padding(16.dp)
         ) {
-            Text("新任务分配", fontSize = 15.sp, fontWeight = FontWeight.Medium, color = Text)
-            Text(
-                "您有新的作业票待处理,作业票号:WO-2024-003",
-                fontSize = 13.sp,
-                color = Color(0xFF666666),
-                overflow = TextOverflow.Ellipsis,
-                maxLines = 2,
-                modifier = Modifier.fillMaxWidth()
+            Icon(
+                painterResource(R.drawable.delete_all), contentDescription = null,
+                modifier = Modifier
+                    .size(40.dp)
+                    .clip(RoundedCornerShape(50))
+                    .background(Color(0xFF1E90FF))
+                    .padding(12.dp)
             )
-            Spacer(Modifier.weight(1f))
-            Row(Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically) {
-                Text("10:30", fontSize = 12.sp, color = Color(0xFF999999))
+            Column(
+                Modifier
+                    .padding(start = 15.dp, end = 10.dp)
+                    .fillMaxHeight()
+                    .weight(1f)
+            ) {
+                Text("新任务分配", 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))
-                Text("作业管理", fontSize = 12.sp, color = Color(0xFF999999))
+                Row(Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically) {
+                    Text(msg.createTime.getShowDateOrTime(), fontSize = 12.sp, color = Color(0xFF999999))
+                    Spacer(Modifier.weight(1f))
+                    Text("作业管理", fontSize = 12.sp, color = Color(0xFF999999))
+                }
             }
+            Spacer(
+                Modifier
+                    .size(8.dp)
+                    .clip(RoundedCornerShape(50))
+                    .background(if (msg.readStatus) Color.Transparent else Color(0xFFFF4500))
+                    .align(Alignment.CenterVertically)
+            )
         }
-        Spacer(
-            Modifier
-                .size(8.dp)
-                .clip(RoundedCornerShape(50))
-                .background(Color(0xFFFF4500))
-                .align(Alignment.CenterVertically)
-        )
     }
 }

+ 121 - 0
app/src/main/java/com/iscs/bozzys/ui/pages/vm/VMMessage.kt

@@ -0,0 +1,121 @@
+package com.iscs.bozzys.ui.pages.vm
+
+import androidx.lifecycle.viewModelScope
+import com.iscs.bozzys.api.ApiRequest
+import com.iscs.bozzys.api.Message
+import com.iscs.bozzys.ui.common.StateTips
+import com.iscs.bozzys.ui.common.VMBase
+import com.iscs.bozzys.utils.DateUtil.getShowDate
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.asStateFlow
+import kotlinx.coroutines.launch
+
+/**
+ * 通知消息
+ */
+class VMMessage : VMBase() {
+
+    private val _state = MutableStateFlow(StateMessage())
+
+    val state = _state.asStateFlow()
+
+    fun init() {
+        getMessage(StatePageMessage(isRefresh = true, page = 1))
+    }
+
+    fun getMessage(page: StatePageMessage) {
+        viewModelScope.launch {
+            _state.value = _state.value.copy(page = _state.value.page.copy(page = page.page, isRefresh = page.isRefresh))
+            ApiRequest.getMessage(mutableMapOf("pageNo" to page.page, "pageSize" to page.pageSize)).onSuccess {
+                // 如果加载的是第一页数据,这里先做清除操作
+                if (page.page == 1) _state.value.messages.clear()
+                val newList = _state.value.messages.toMutableList()
+                val dataCount = it.data?.total ?: 0
+                it.data?.list?.forEach { msg ->
+                    // 查找是否有和日期相同的标题,如果没有则插入
+                    val findTitle = newList.find { m -> m.createTime.getShowDate() == msg.createTime.getShowDate() && m.isTitle }
+                    if (findTitle == null) newList += Message(isTitle = true, title = msg.createTime.getShowDate(), createTime = msg.createTime)
+                    newList += msg
+                }
+                _state.value = _state.value.copy(messages = newList)
+                delay(1000)
+                // 查找消息个数是否和后台返回的消息个数一致
+                val noMore = newList.count { m -> !m.isTitle } == dataCount
+                _state.value = _state.value.copy(page = _state.value.page.copy(isRefresh = false, noMore = noMore))
+            }
+        }
+    }
+
+    /**
+     * 消息被点击操作,主要是已读操作
+     */
+    fun onMessage(msg: Message) {
+        // 已读不做处理
+        if (msg.readStatus) return
+        viewModelScope.launch {
+            ApiRequest.updateMessageRead(mutableMapOf("ids" to "${msg.id}")).onSuccess {
+                val newList = _state.value.messages.map { if (it.id == msg.id) it.copy(readStatus = true) else it }.toMutableList()
+                _state.value = _state.value.copy(messages = newList)
+            }
+        }
+    }
+
+    fun onReadAll() {
+        _state.value = _state.value.copy(tips = StateTips(show = true, title = "提示", content = "确定要将所有消息标记为已读吗?", type = "READ_ALL"))
+    }
+
+    fun onDeleteAll() {
+        _state.value = _state.value.copy(tips = StateTips(show = true, title = "提示", content = "确定要删除所有消息吗?", type = "DELETE_ALL"))
+    }
+
+    fun hideTips() {
+        _state.value = _state.value.copy(tips = _state.value.tips.copy(show = false, type = ""))
+    }
+
+    fun onTipsConfirm() {
+        viewModelScope.launch {
+            val tips = _state.value.tips
+            _state.value = _state.value.copy(tips = tips.copy(show = false))
+            if (tips.type == "READ_ALL") {
+                ApiRequest.updateMessageRead(mutableMapOf()).onSuccess {
+                    val newList = _state.value.messages.map { it.copy(readStatus = true) }.toMutableList()
+                    _state.value = _state.value.copy(messages = newList)
+                }
+            }
+        }
+    }
+
+}
+
+/**
+ * 消息界面状态类
+ *
+ * @param messages  消息列表
+ * @param page      页面数据
+ * @param tips      tipsDialog数据
+ */
+data class StateMessage(
+    val messages: MutableList<Message> = mutableListOf(),
+    val page: StatePageMessage = StatePageMessage(),
+    val tips: StateTips = StateTips()
+)
+
+/**
+ * 页面数据
+ *
+ * @param page      当前页面
+ * @param pageSize  页面大小
+ * @param type      请求数据类型 unaudited 默认取进行中的
+ * @param keywords  关键字
+ * @param isRefresh 是否正在刷新
+ * @param noMore    没有更多数据
+ */
+data class StatePageMessage(
+    val page: Int = 1,
+    val pageSize: Int = 10,
+    val type: String = "",
+    val keywords: String = "",
+    val isRefresh: Boolean = false,
+    val noMore: Boolean = true,
+)

+ 29 - 3
app/src/main/java/com/iscs/bozzys/utils/DateUtil.kt

@@ -2,6 +2,7 @@ package com.iscs.bozzys.utils
 
 import android.os.Build
 import android.util.Log
+import java.lang.System
 import java.text.SimpleDateFormat
 import java.time.Instant
 import java.time.LocalDateTime
@@ -57,12 +58,37 @@ object DateUtil {
      * 将时间戳转化为可显示的日期
      */
     fun Long?.getShowDate(): String {
-        var show = "--"
+        val localTs = System.currentTimeMillis()
+        val localDat = localTs.format("yyyy-MM-dd HH:mm:ss").split(" ")
+        val localDate = localDat[0]
+        // val localTime = localDat[1]
+        // 显示逻辑
+        // 当天 显示具体时间
+        // 昨天 显示昨天具体时间
+        // 前天 显示前天具体时间
+        // 本年 显示日期和时间
+        // 他年 显示年月日和时间
         if (this != null && this > 0) {
             // 执行时间戳的转换
-
+            val dat = this.format("yyyy-MM-dd HH:mm:ss").split(" ")
+            val date = dat[0].split("-")
+            val year = date[0]
+            val month = date[1]
+            val day = date[2]
+            return if (localDate == dat[0]) {
+                // 说明是当天
+                "今天"
+            } else if (localDate == "$year-$month-${(day.toInt() - 1).toString().padStart(2, '0')}") {
+                // 说明是昨天
+                "昨天"
+            } else if (localDate.startsWith("$year-")) {
+                // 说明是本年度
+                "$month-$day"
+            } else {
+                dat[0]
+            }
         }
-        return show
+        return "--"
     }
 
     /**