Browse Source

将本地所有png替换svg 提高不同分辨率的适配

bjb 1 week ago
parent
commit
0229bfaba4
68 changed files with 1326 additions and 124 deletions
  1. 2 2
      .idea/deploymentTargetSelector.xml
  2. 42 0
      app/src/main/java/com/iscs/bozzys/ui/base/Loading.kt
  3. 39 1
      app/src/main/java/com/iscs/bozzys/ui/base/PageBase.kt
  4. 2 0
      app/src/main/java/com/iscs/bozzys/ui/base/VMBase.kt
  5. 43 0
      app/src/main/java/com/iscs/bozzys/ui/base/VMLoading.kt
  6. 25 6
      app/src/main/java/com/iscs/bozzys/ui/pages/PageSplash.kt
  7. 113 0
      app/src/main/java/com/iscs/bozzys/ui/pages/compose/JobListItem.kt
  8. 271 8
      app/src/main/java/com/iscs/bozzys/ui/pages/home/HomeCompose.kt
  9. 137 0
      app/src/main/java/com/iscs/bozzys/ui/pages/home/JobsCompose.kt
  10. 205 0
      app/src/main/java/com/iscs/bozzys/ui/pages/home/MessageCompose.kt
  11. 39 40
      app/src/main/java/com/iscs/bozzys/ui/pages/home/PageHome.kt
  12. 66 52
      app/src/main/java/com/iscs/bozzys/ui/pages/login/PageLogin.kt
  13. 51 15
      app/src/main/java/com/iscs/bozzys/ui/pages/vm/VMHome.kt
  14. 99 0
      app/src/main/java/com/iscs/bozzys/ui/pages/vm/VMLogin.kt
  15. 14 0
      app/src/main/java/com/iscs/bozzys/utils/Storage.kt
  16. 9 0
      app/src/main/res/drawable/bell.xml
  17. 7 0
      app/src/main/res/drawable/bluetooth.xml
  18. 9 0
      app/src/main/res/drawable/code.xml
  19. 9 0
      app/src/main/res/drawable/delete_all.xml
  20. 9 0
      app/src/main/res/drawable/fingerprint.xml
  21. 9 0
      app/src/main/res/drawable/home.xml
  22. 9 0
      app/src/main/res/drawable/job_finish.xml
  23. 9 0
      app/src/main/res/drawable/job_ing.xml
  24. 9 0
      app/src/main/res/drawable/job_todo.xml
  25. 9 0
      app/src/main/res/drawable/jobs.xml
  26. 9 0
      app/src/main/res/drawable/location.xml
  27. 9 0
      app/src/main/res/drawable/message.xml
  28. 9 0
      app/src/main/res/drawable/phone.xml
  29. 12 0
      app/src/main/res/drawable/pwd.xml
  30. 9 0
      app/src/main/res/drawable/qrcode.xml
  31. 9 0
      app/src/main/res/drawable/read_all.xml
  32. 7 0
      app/src/main/res/drawable/settings.xml
  33. 9 0
      app/src/main/res/drawable/tips.xml
  34. 9 0
      app/src/main/res/drawable/user.xml
  35. BIN
      app/src/main/res/mipmap-hdpi/bluetooth.png
  36. BIN
      app/src/main/res/mipmap-hdpi/code.png
  37. BIN
      app/src/main/res/mipmap-hdpi/fingerprint.png
  38. BIN
      app/src/main/res/mipmap-hdpi/login_tips.png
  39. BIN
      app/src/main/res/mipmap-hdpi/phone.png
  40. BIN
      app/src/main/res/mipmap-hdpi/pwd.png
  41. BIN
      app/src/main/res/mipmap-hdpi/qrcode.png
  42. BIN
      app/src/main/res/mipmap-hdpi/user.png
  43. BIN
      app/src/main/res/mipmap-xhdpi/bluetooth.png
  44. BIN
      app/src/main/res/mipmap-xhdpi/code.png
  45. BIN
      app/src/main/res/mipmap-xhdpi/fingerprint.png
  46. BIN
      app/src/main/res/mipmap-xhdpi/login_tips.png
  47. BIN
      app/src/main/res/mipmap-xhdpi/phone.png
  48. BIN
      app/src/main/res/mipmap-xhdpi/pwd.png
  49. BIN
      app/src/main/res/mipmap-xhdpi/qrcode.png
  50. BIN
      app/src/main/res/mipmap-xhdpi/user.png
  51. BIN
      app/src/main/res/mipmap-xxhdpi/bluetooth.png
  52. BIN
      app/src/main/res/mipmap-xxhdpi/code.png
  53. BIN
      app/src/main/res/mipmap-xxhdpi/fingerprint.png
  54. BIN
      app/src/main/res/mipmap-xxhdpi/login_tips.png
  55. BIN
      app/src/main/res/mipmap-xxhdpi/phone.png
  56. BIN
      app/src/main/res/mipmap-xxhdpi/pwd.png
  57. BIN
      app/src/main/res/mipmap-xxhdpi/qrcode.png
  58. BIN
      app/src/main/res/mipmap-xxhdpi/user.png
  59. BIN
      app/src/main/res/mipmap-xxxhdpi/bluetooth.png
  60. BIN
      app/src/main/res/mipmap-xxxhdpi/code.png
  61. BIN
      app/src/main/res/mipmap-xxxhdpi/fingerprint.png
  62. BIN
      app/src/main/res/mipmap-xxxhdpi/login_tips.png
  63. BIN
      app/src/main/res/mipmap-xxxhdpi/phone.png
  64. BIN
      app/src/main/res/mipmap-xxxhdpi/pwd.png
  65. BIN
      app/src/main/res/mipmap-xxxhdpi/qrcode.png
  66. BIN
      app/src/main/res/mipmap-xxxhdpi/user.png
  67. 4 0
      app/src/main/res/values-zh-rCN/strings.xml
  68. 4 0
      app/src/main/res/values/strings.xml

+ 2 - 2
.idea/deploymentTargetSelector.xml

@@ -4,10 +4,10 @@
     <selectionStates>
       <SelectionState runConfigName="app">
         <option name="selectionMode" value="DROPDOWN" />
-        <DropdownSelection timestamp="2025-12-09T10:01:36.687097400Z">
+        <DropdownSelection timestamp="2025-12-11T03:30:51.667737200Z">
           <Target type="DEFAULT_BOOT">
             <handle>
-              <DeviceId pluginId="PhysicalDevice" identifier="serial=d8d12db95670c08" />
+              <DeviceId pluginId="LocalEmulator" identifier="path=C:\Users\ISCS\.android\avd\Resizable.avd" />
             </handle>
           </Target>
         </DropdownSelection>

+ 42 - 0
app/src/main/java/com/iscs/bozzys/ui/base/Loading.kt

@@ -0,0 +1,42 @@
+package com.iscs.bozzys.ui.base
+
+import androidx.compose.foundation.background
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.sizeIn
+import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.material3.CircularProgressIndicator
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.clip
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.input.pointer.pointerInput
+import androidx.compose.ui.unit.dp
+import androidx.lifecycle.viewmodel.compose.viewModel
+
+/**
+ * 全局Loading弹窗
+ */
+@Composable
+fun LoadingCompose(vm: VMLoading = viewModel()) {
+    if (!vm.state.show) return
+    Box(
+        Modifier
+            .fillMaxSize()
+            .pointerInput(Unit) {}, // 不允许点击穿透
+        contentAlignment = Alignment.Center
+    ) {
+        Box(
+            Modifier
+                .sizeIn(80.dp, 80.dp, 300.dp, 300.dp)
+                .clip(RoundedCornerShape(20.dp))
+                .background(Color.Black.copy(alpha = 0.5f)),
+            contentAlignment = Alignment.Center
+
+        ) {
+            CircularProgressIndicator()
+        }
+
+    }
+}

+ 39 - 1
app/src/main/java/com/iscs/bozzys/ui/base/PageBase.kt

@@ -6,6 +6,7 @@ import androidx.activity.ComponentActivity
 import androidx.activity.SystemBarStyle
 import androidx.activity.compose.setContent
 import androidx.activity.enableEdgeToEdge
+import androidx.compose.foundation.background
 import androidx.compose.foundation.layout.PaddingValues
 import androidx.compose.foundation.layout.fillMaxSize
 import androidx.compose.material3.Scaffold
@@ -17,6 +18,7 @@ import androidx.core.view.WindowCompat
 import androidx.core.view.WindowInsetsCompat
 import androidx.core.view.WindowInsetsControllerCompat
 import androidx.lifecycle.lifecycleScope
+import androidx.lifecycle.viewmodel.compose.viewModel
 import com.iscs.bozzys.ui.theme.BozzysTheme
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.delay
@@ -33,6 +35,8 @@ abstract class PageBase(
     val hideNavigationBar: Boolean = false
 ) : ComponentActivity() {
 
+    var loading: VMLoading? = null
+
     /**
      * 页面创建
      *
@@ -48,9 +52,16 @@ abstract class PageBase(
             )
         )
         setContent {
+            loading = viewModel()
             BozzysTheme {
-                Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
+                Scaffold(
+                    modifier = Modifier
+                        .fillMaxSize()
+                        .background(Color.White)
+                ) { innerPadding ->
                     GetViews(innerPadding)
+                    // 全局loading弹窗
+                    if (loading != null) LoadingCompose(loading!!)
                 }
             }
         }
@@ -126,4 +137,31 @@ abstract class PageBase(
         this.collect { msg -> msg.showToast() }
     }
 
+    /**
+     * 显示全局Loading
+     */
+    fun showLoading() {
+        loading?.show()
+    }
+
+    /**
+     * 隐藏全局loading
+     */
+    fun hideLoading() {
+        loading?.hide()
+    }
+
+    /**
+     * 显示toast,Flow方式
+     */
+    suspend fun MutableSharedFlow<StateLoading>.loading() {
+        this.collect { stateLoading ->
+            if (stateLoading.show) {
+                loading?.show(stateLoading)
+            } else {
+                loading?.hide()
+            }
+        }
+    }
+
 }

+ 2 - 0
app/src/main/java/com/iscs/bozzys/ui/base/VMBase.kt

@@ -12,4 +12,6 @@ open class VMBase : ViewModel() {
      * Toast 事件
      */
     val toastEvent = MutableSharedFlow<Any>()
+
+    val loadingEvent = MutableSharedFlow<StateLoading>()
 }

+ 43 - 0
app/src/main/java/com/iscs/bozzys/ui/base/VMLoading.kt

@@ -0,0 +1,43 @@
+package com.iscs.bozzys.ui.base
+
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.setValue
+import androidx.lifecycle.ViewModel
+
+class VMLoading : ViewModel() {
+
+    // 处理ViewModel中显示的内容
+    var state by mutableStateOf(StateLoading())
+        private set
+
+    /**
+     * 显示loading
+     */
+    fun show(content: String = "", timeout: Int = -1) {
+        state = state.copy(show = true, content = content)
+    }
+
+    /**
+     * 显示loading
+     */
+    fun show(stateLoading: StateLoading) {
+        state = stateLoading
+    }
+
+    /**
+     * 隐藏
+     */
+    fun hide() {
+        state = state.copy(show = false)
+    }
+
+}
+
+/**
+ * loading状态类
+ *
+ * @param show      是否显示loading
+ * @param content   loading时提示的内容
+ */
+data class StateLoading(var show: Boolean = false, var content: Any = "", var timeout: Int = -1)

+ 25 - 6
app/src/main/java/com/iscs/bozzys/ui/pages/PageSplash.kt

@@ -5,13 +5,21 @@ import android.app.NotificationManager
 import android.graphics.Color
 import android.os.Build
 import androidx.compose.foundation.Image
+import androidx.compose.foundation.background
+import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.PaddingValues
 import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.shape.RoundedCornerShape
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.clip
 import androidx.compose.ui.layout.ContentScale
 import androidx.compose.ui.res.painterResource
+import androidx.compose.ui.unit.dp
 import com.alibaba.sdk.android.push.CloudPushService
 import com.alibaba.sdk.android.push.CommonCallback
 import com.alibaba.sdk.android.push.noonesdk.PushServiceFactory
@@ -20,6 +28,7 @@ import com.iscs.bozzys.service.AliPushService
 import com.iscs.bozzys.ui.base.PageBase
 import com.iscs.bozzys.ui.pages.home.openPageHome
 import com.iscs.bozzys.ui.pages.login.openPageLogin
+import com.iscs.bozzys.ui.theme.Main
 import com.iscs.bozzys.utils.Storage
 import kotlinx.coroutines.delay
 
@@ -31,12 +40,22 @@ class PageSplash : PageBase() {
     @Composable
     override fun GetViews(pv: PaddingValues) {
         // 配置页面显示控件
-        Image(
-            painter = painterResource(R.mipmap.logo),
-            contentDescription = "",
-            modifier = Modifier.fillMaxSize(),
-            contentScale = ContentScale.FillWidth
-        )
+        Box(Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
+            Box(
+                Modifier
+                    .clip(RoundedCornerShape(20))
+                    .background(Main)
+            ) {
+                Image(
+                    painter = painterResource(R.mipmap.logo),
+                    contentDescription = "",
+                    modifier = Modifier
+                        .size(200.dp)
+                        .padding(0.dp),
+                    contentScale = ContentScale.FillBounds
+                )
+            }
+        }
         // 协程处理跳转事件
         LaunchedEffect(Unit) {
             // 做SDK的初始化操作,有一些没必要在Application中初始化操作的,在这里进行初始化操作

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

@@ -0,0 +1,113 @@
+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
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.material3.Icon
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.clip
+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.unit.dp
+import androidx.compose.ui.unit.sp
+import com.iscs.bozzys.R
+import com.iscs.bozzys.ui.theme.Text
+
+@OptIn(ExperimentalLayoutApi::class)
+@Composable
+fun JobListItem() {
+    Column(
+        Modifier
+            .padding(bottom = 15.dp)
+            .fillMaxWidth()
+            .height(156.dp)
+            .border(1.dp, color = Color(0xFFEEEEEE), shape = RoundedCornerShape(12.dp))
+            .clip(RoundedCornerShape(12.dp))
+            .background(Color(0xFFF8F9FA))
+            .clickable(onClick = {})
+            .padding(16.dp)
+    ) {
+        Row {
+            Text("1号配电箱停电检查作业", fontSize = 15.sp, fontWeight = FontWeight.Medium, color = Text)
+            Spacer(Modifier.weight(1f))
+            Text(
+                "紧急", modifier = Modifier
+                    .height(24.dp)
+                    .clip(RoundedCornerShape(12.dp))
+                    .background(Color(0xFFFF4500))
+                    .padding(horizontal = 10.dp),
+                fontSize = 12.sp,
+                lineHeight = 24.sp,
+                color = Color.White
+            )
+        }
+        FlowRow(Modifier.padding(top = 10.dp)) {
+            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(0xFF1E90FF)
+                )
+                Text("车间A区", fontSize = 13.sp, color = Color(0xFF666666))
+            }
+            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("负责人:张三", fontSize = 13.sp, color = Color(0xFF666666))
+            }
+            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("WO-2025-1210", fontSize = 13.sp, color = Color(0xFF666666))
+            }
+            Text("作业内容:切断电源", fontSize = 13.sp, color = Color(0xFF666666))
+        }
+        Spacer(Modifier.weight(1f))
+        Row(
+            Modifier
+                .fillMaxWidth()
+                .height(36.dp), verticalAlignment = Alignment.CenterVertically
+        ) {
+            Text("工作描述内容", fontSize = 12.sp, color = Color(0xFF999999))
+            Spacer(Modifier.weight(1f))
+            Text(
+                "立即处理",
+                modifier = Modifier
+                    .fillMaxHeight()
+                    .clip(RoundedCornerShape(4.dp))
+                    .background(Color(0xFF1E90FF))
+                    .padding(horizontal = 10.dp),
+                fontSize = 13.sp,
+                lineHeight = 36.sp,
+                fontWeight = FontWeight.Bold,
+                color = Color.White,
+                textAlign = TextAlign.Center
+            )
+        }
+    }
+}

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

@@ -1,44 +1,307 @@
 package com.iscs.bozzys.ui.pages.home
 
 import androidx.compose.foundation.background
+import androidx.compose.foundation.border
+import androidx.compose.foundation.clickable
+import androidx.compose.foundation.interaction.MutableInteractionSource
+import androidx.compose.foundation.layout.Arrangement
 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.aspectRatio
+import androidx.compose.foundation.layout.defaultMinSize
+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.offset
 import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.layout.width
+import androidx.compose.foundation.rememberScrollState
+import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.foundation.verticalScroll
+import androidx.compose.material3.ExperimentalMaterial3Api
+import androidx.compose.material3.Icon
+import androidx.compose.material3.Text
+import androidx.compose.material3.pulltorefresh.PullToRefreshBox
 import androidx.compose.runtime.Composable
+import androidx.compose.runtime.collectAsState
+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
+import androidx.compose.ui.draw.clip
 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.compose.ui.zIndex
+import com.iscs.bozzys.R
+import com.iscs.bozzys.ui.pages.compose.JobListItem
+import com.iscs.bozzys.ui.pages.vm.VMHome
 import com.iscs.bozzys.ui.theme.Main
+import com.iscs.bozzys.ui.theme.Text
 
+@OptIn(ExperimentalMaterial3Api::class)
 @Composable
-fun HomeCompose(pv: PaddingValues, zIndex: Float) {
+fun HomeCompose(pv: PaddingValues, zIndex: Float, vmHome: VMHome) {
+    val isRefresh = remember { mutableStateOf(false) }
     Box(
         modifier = Modifier
             .fillMaxSize()
             .zIndex(zIndex)
             .background(Color(0xFFF8F8F8))
     ) {
-        // 顶部工具栏
-        Column(
+        PullToRefreshBox(isRefresh.value, onRefresh = {
+            isRefresh.value = true
+
+        }) {
+            Column(Modifier.fillMaxSize()) {
+                // 顶部工具栏
+                TopToolBar(pv, vmHome)
+                TODO(vmHome)
+                TODOList(pv, vmHome)
+            }
+        }
+    }
+}
+
+/**
+ * 顶部工具栏
+ */
+@Composable
+private fun TopToolBar(pv: PaddingValues, vmHome: VMHome) {
+    val state by vmHome.state.collectAsState()
+    Column(
+        modifier = Modifier
+            .fillMaxWidth()
+            .background(Main)
+            .padding(top = pv.calculateTopPadding())
+    ) {
+        Row(
             modifier = Modifier
                 .fillMaxWidth()
-                .background(Main)
-                .padding(top = pv.calculateTopPadding())
+                .height(66.dp)
+                .padding(start = 20.dp, end = 10.dp),
+            verticalAlignment = Alignment.CenterVertically
         ) {
-            Row(
+            Icon(
+                painter = painterResource(R.drawable.user),
                 modifier = Modifier
-                    .fillMaxWidth()
-                    .height(66.dp)
+                    .size(36.dp)
+                    .clip(RoundedCornerShape(50))
+                    .background(Color(0xFFFFD700))
+                    .padding(10.dp),
+                contentDescription = null,
+                tint = Color.White
+            )
+            Column(Modifier.padding(horizontal = 10.dp)) {
+                Text(state.username, fontSize = 16.sp, lineHeight = 16.sp, fontWeight = FontWeight.Medium, color = Color.White)
+                Text("操作员 电气维护组", fontSize = 12.sp, lineHeight = 12.sp, color = Color.White.copy(alpha = 0.8f))
+            }
+            Spacer(Modifier.weight(1f))
+            Box(modifier = Modifier.fillMaxHeight(), contentAlignment = Alignment.Center) {
+                Icon(
+                    painter = painterResource(R.drawable.bell),
+                    contentDescription = null,
+                    modifier = Modifier
+                        .size(36.dp)
+                        .clip(RoundedCornerShape(12.dp))
+                        .clickable(onClick = {})
+                        .padding(9.dp),
+                    tint = Color.White
+                )
+                Text(
+                    "5", color = Color.White, modifier = Modifier
+                        .offset(x = 8.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
+                )
+            }
+            Icon(
+                painter = painterResource(R.drawable.settings),
+                contentDescription = null,
+                modifier = Modifier
+                    .size(36.dp)
+                    .clip(RoundedCornerShape(12.dp))
+                    .clickable(onClick = {})
+                    .padding(10.dp),
+                tint = Color.White
+            )
+        }
+    }
+}
 
+/**
+ * 待办任务
+ */
+@Composable
+private fun TODO(vmHome: VMHome) {
+    Column(
+        Modifier
+            .padding(top = 3.dp)
+            .fillMaxWidth()
+    ) {
+        Text(
+            "中午好,今天有2个待办任务", Modifier
+                .fillMaxWidth()
+                .height(51.dp)
+                .background(Color(0xFFE6F7FF)),
+            fontSize = 14.sp,
+            lineHeight = 51.sp,
+            color = Text,
+            textAlign = TextAlign.Center
+        )
+        Row(Modifier.padding(vertical = 15.dp)) {
+            Spacer(Modifier.width(10.dp))
+            Column(
+                Modifier
+                    .weight(1f)
+                    .aspectRatio(1f)
+                    .clip(RoundedCornerShape(12.dp))
+                    .background(Color(0xFFFFF5EB)),
+                verticalArrangement = Arrangement.Center, horizontalAlignment = Alignment.CenterHorizontally
+            ) {
+                Text("2", fontSize = 24.sp, fontWeight = FontWeight.Bold, color = Color(0xFFFF4500))
+                Text("待处理", fontSize = 12.sp, color = Text, modifier = Modifier.padding(top = 5.dp))
+                Icon(
+                    painterResource(R.drawable.job_todo), contentDescription = null, modifier = Modifier
+                        .padding(top = 3.dp)
+                        .size(16.dp),
+                    tint = Text
+                )
+            }
+            Spacer(Modifier.width(10.dp))
+            Column(
+                Modifier
+                    .weight(1f)
+                    .aspectRatio(1f)
+                    .clip(RoundedCornerShape(12.dp))
+                    .background(Color(0xFFFFF5EB)),
+                verticalArrangement = Arrangement.Center, horizontalAlignment = Alignment.CenterHorizontally
+            ) {
+                Text("5", fontSize = 24.sp, fontWeight = FontWeight.Bold, color = Color(0xFFFFA500))
+                Text("进行中", fontSize = 12.sp, color = Text, modifier = Modifier.padding(top = 5.dp))
+                Icon(
+                    painterResource(R.drawable.job_ing), contentDescription = null, modifier = Modifier
+                        .padding(top = 3.dp)
+                        .size(16.dp),
+                    tint = Text
+                )
+            }
+            Spacer(Modifier.width(10.dp))
+            Column(
+                Modifier
+                    .weight(1f)
+                    .aspectRatio(1f)
+                    .clip(RoundedCornerShape(12.dp))
+                    .background(Color(0xFFFFF5EB)),
+                verticalArrangement = Arrangement.Center, horizontalAlignment = Alignment.CenterHorizontally
             ) {
+                Text("10", fontSize = 24.sp, fontWeight = FontWeight.Bold, color = Color(0xFF32CD32))
+                Text("本月完成", fontSize = 12.sp, color = Text, modifier = Modifier.padding(top = 5.dp))
+                Icon(
+                    painterResource(R.drawable.job_finish), contentDescription = null, modifier = Modifier
+                        .padding(top = 3.dp)
+                        .size(16.dp),
+                    tint = Text
+                )
+            }
+            Spacer(Modifier.width(10.dp))
+        }
+    }
+}
 
+/**
+ * 待办列表
+ */
+@Composable
+private fun TODOList(pv: PaddingValues, vmHome: VMHome) {
+    val todoList = listOf(1, 2)
+    val messageList = listOf(1, 2, 3)
+    Column(
+        Modifier
+            .padding(horizontal = 20.dp)
+            .padding(bottom = pv.calculateBottomPadding())
+            .fillMaxSize()
+            .verticalScroll(state = rememberScrollState())
+    ) {
+        Row(
+            Modifier
+                .fillMaxWidth()
+                .height(46.dp)
+                .clickable(indication = null, interactionSource = remember { MutableInteractionSource() }, onClick = {
+                    vmHome.updateNavIndex(1)
+                }),
+            verticalAlignment = Alignment.CenterVertically
+        ) {
+            Text("我的当前任务", fontSize = 14.sp, fontWeight = FontWeight.Medium, color = Text)
+            Spacer(Modifier.weight(1f))
+            Text("查看全部", fontSize = 14.sp, color = Color(0xFF1E90FF))
+        }
+        Column(Modifier.fillMaxWidth()) {
+            repeat(todoList.size) { JobListItem() }
+        }
+        Row(
+            Modifier
+                .fillMaxWidth()
+                .height(46.dp)
+                .clickable(indication = null, interactionSource = remember { MutableInteractionSource() }, onClick = {
+                    vmHome.updateNavIndex(2)
+                }),
+            verticalAlignment = Alignment.CenterVertically
+        ) {
+            Text("最新消息", modifier = Modifier.fillMaxHeight(), fontSize = 14.sp, fontWeight = FontWeight.Medium, color = Text)
+            Spacer(Modifier.weight(1f))
+            Text("全部消息", modifier = Modifier.fillMaxHeight(), fontSize = 14.sp, color = Color(0xFF1E90FF))
+        }
+        Column(Modifier.fillMaxWidth()) {
+            messageList.forEach {
+                MessageListItem()
             }
         }
     }
+}
+
+@Composable
+fun MessageListItem() {
+    Column(
+        Modifier
+            .padding(bottom = 15.dp)
+            .fillMaxWidth()
+            .height(102.dp)
+            .border(1.dp, color = Color(0xFFEEEEEE), shape = RoundedCornerShape(12.dp))
+            .clip(RoundedCornerShape(12.dp))
+            .background(Color(0xFFF8F9FA))
+            .clickable(onClick = {})
+            .padding(16.dp)
+    ) {
+        Text(
+            "系统通知:您有新的作业任务待处理,请及时查看并执行操作任务。请及时查看并执行操作任务。请及时查看并执行操作任务。",
+            modifier = Modifier.fillMaxWidth(),
+            fontSize = 14.sp,
+            color = Text,
+            maxLines = 2,
+            overflow = TextOverflow.Ellipsis
+        )
+        Spacer(Modifier.weight(1f))
+        Row(Modifier.fillMaxWidth()) {
+            Spacer(Modifier.weight(1f))
+            Text("5分钟前", fontSize = 12.sp, color = Color(0xFF999999))
+        }
+    }
 }

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

@@ -0,0 +1,137 @@
+package com.iscs.bozzys.ui.pages.home
+
+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.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.lazy.LazyColumn
+import androidx.compose.foundation.lazy.items
+import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.material3.ExperimentalMaterial3Api
+import androidx.compose.material3.Icon
+import androidx.compose.material3.Text
+import androidx.compose.material3.pulltorefresh.PullToRefreshBox
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.mutableStateOf
+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.Color
+import androidx.compose.ui.res.painterResource
+import androidx.compose.ui.text.font.FontWeight
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.sp
+import androidx.compose.ui.zIndex
+import com.iscs.bozzys.R
+import com.iscs.bozzys.ui.pages.compose.JobListItem
+import com.iscs.bozzys.ui.pages.vm.VMHome
+import com.iscs.bozzys.ui.theme.Main
+import com.iscs.bozzys.ui.theme.Text
+
+@Composable
+fun JobsCompose(pv: PaddingValues, zIndex: Float, vmHome: VMHome) {
+    Box(
+        modifier = Modifier
+            .fillMaxSize()
+            .zIndex(zIndex)
+            .background(Color(0xFFF8F8F8))
+    ) {
+        // 顶部工具栏
+        Column(
+            modifier = Modifier
+                .padding(bottom = pv.calculateBottomPadding())
+                .fillMaxSize()
+        ) {
+            TopToolBar(pv, vmHome)
+            MessageList()
+        }
+    }
+}
+
+/**
+ * 顶部工具栏
+ */
+@Composable
+private fun TopToolBar(pv: PaddingValues, vmHome: VMHome) {
+    Column(
+        modifier = Modifier
+            .fillMaxWidth()
+            .background(Main)
+            .padding(top = pv.calculateTopPadding())
+    ) {
+        Row(
+            modifier = Modifier
+                .fillMaxWidth()
+                .height(66.dp)
+                .padding(start = 20.dp, end = 10.dp),
+            verticalAlignment = Alignment.CenterVertically
+        ) {
+            Text("我的作业", fontSize = 18.sp, color = Color.White, fontWeight = FontWeight.Medium)
+            Spacer(Modifier.weight(1f))
+            Icon(
+                painter = painterResource(R.drawable.read_all),
+                contentDescription = null,
+                modifier = Modifier
+                    .size(36.dp)
+                    .clip(RoundedCornerShape(12.dp))
+                    .clickable(onClick = {})
+                    .padding(9.dp),
+                tint = Color.White
+            )
+        }
+    }
+}
+
+/**
+ * 消息列表
+ */
+@OptIn(ExperimentalMaterial3Api::class)
+@Composable
+private fun MessageList() {
+    val isRefresh = remember { mutableStateOf(false) }
+    val list = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9)
+    PullToRefreshBox(isRefresh.value, onRefresh = {
+        isRefresh.value = true
+    }, modifier = Modifier.fillMaxSize()) {
+        LazyColumn(
+            modifier = Modifier
+                .padding(top = 5.dp)
+                .fillMaxSize()
+                .padding(horizontal = 20.dp)
+        ) {
+            items(list) { item ->
+                when (item) {
+                    1 -> JobListItemTitle("今天")
+                    6 -> JobListItemTitle("昨天")
+                    else -> JobListItem()
+                }
+            }
+        }
+    }
+}
+
+/**
+ * 消息标题
+ */
+@Composable
+private fun JobListItemTitle(title: String) {
+    Text(
+        title,
+        fontSize = 16.sp,
+        lineHeight = 21.sp,
+        fontWeight = FontWeight.Medium,
+        color = Text,
+        modifier = Modifier
+            .padding(bottom = 10.dp)
+            .fillMaxWidth()
+    )
+}

+ 205 - 0
app/src/main/java/com/iscs/bozzys/ui/pages/home/MessageCompose.kt

@@ -0,0 +1,205 @@
+package com.iscs.bozzys.ui.pages.home
+
+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
+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.lazy.LazyColumn
+import androidx.compose.foundation.lazy.items
+import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.material3.ExperimentalMaterial3Api
+import androidx.compose.material3.Icon
+import androidx.compose.material3.Text
+import androidx.compose.material3.pulltorefresh.PullToRefreshBox
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.mutableStateOf
+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.Color
+import androidx.compose.ui.res.painterResource
+import androidx.compose.ui.text.font.FontWeight
+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 com.iscs.bozzys.R
+import com.iscs.bozzys.ui.pages.vm.VMHome
+import com.iscs.bozzys.ui.theme.Main
+import com.iscs.bozzys.ui.theme.Text
+
+@Composable
+fun MessageCompose(pv: PaddingValues, zIndex: Float, vmHome: VMHome) {
+    Box(
+        modifier = Modifier
+            .fillMaxSize()
+            .zIndex(zIndex)
+            .background(Color(0xFFF8F8F8))
+    ) {
+        // 顶部工具栏
+        Column(
+            modifier = Modifier
+                .padding(bottom = pv.calculateBottomPadding())
+                .fillMaxSize()
+        ) {
+            TopToolBar(pv, vmHome)
+            MessageList()
+        }
+    }
+}
+
+/**
+ * 顶部工具栏
+ */
+@Composable
+private fun TopToolBar(pv: PaddingValues, vmHome: VMHome) {
+    Column(
+        modifier = Modifier
+            .fillMaxWidth()
+            .background(Main)
+            .padding(top = pv.calculateTopPadding())
+    ) {
+        Row(
+            modifier = Modifier
+                .fillMaxWidth()
+                .height(66.dp)
+                .padding(start = 20.dp, end = 10.dp),
+            verticalAlignment = Alignment.CenterVertically
+        ) {
+            Text("消息中心", fontSize = 18.sp, color = Color.White, fontWeight = FontWeight.Medium)
+            Spacer(Modifier.weight(1f))
+            Icon(
+                painter = painterResource(R.drawable.read_all),
+                contentDescription = null,
+                modifier = Modifier
+                    .size(36.dp)
+                    .clip(RoundedCornerShape(12.dp))
+                    .clickable(onClick = {})
+                    .padding(9.dp),
+                tint = Color.White
+            )
+            Icon(
+                painter = painterResource(R.drawable.delete_all),
+                contentDescription = null,
+                modifier = Modifier
+                    .size(36.dp)
+                    .clip(RoundedCornerShape(12.dp))
+                    .clickable(onClick = {})
+                    .padding(9.dp),
+                tint = Color.White
+            )
+        }
+    }
+}
+
+/**
+ * 消息列表
+ */
+@OptIn(ExperimentalMaterial3Api::class)
+@Composable
+private fun MessageList() {
+    val isRefresh = remember { mutableStateOf(false) }
+    val list = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9)
+    PullToRefreshBox(isRefresh.value, onRefresh = {
+        isRefresh.value = true
+    }, modifier = Modifier.fillMaxSize()) {
+        LazyColumn(
+            modifier = Modifier
+                .padding(top = 5.dp)
+                .fillMaxSize()
+                .padding(horizontal = 20.dp)
+        ) {
+            items(list) { item ->
+                when (item) {
+                    1 -> JobListItemTitle("今天")
+                    6 -> JobListItemTitle("昨天")
+                    else -> MessageListItemContent(item)
+                }
+            }
+        }
+    }
+}
+
+/**
+ * 消息标题
+ */
+@Composable
+private fun JobListItemTitle(title: String) {
+    Text(
+        title,
+        fontSize = 16.sp,
+        lineHeight = 21.sp,
+        fontWeight = FontWeight.Medium,
+        color = Text,
+        modifier = Modifier
+            .padding(bottom = 10.dp)
+            .fillMaxWidth()
+    )
+}
+
+/**
+ * 消息内容
+ */
+@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(
+            Modifier
+                .padding(start = 15.dp, end = 10.dp)
+                .fillMaxHeight()
+                .weight(1f)
+        ) {
+            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()
+            )
+            Spacer(Modifier.weight(1f))
+            Row(Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically) {
+                Text("10:30", 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(Color(0xFFFF4500))
+                .align(Alignment.CenterVertically)
+        )
+    }
+}

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

@@ -18,21 +18,19 @@ import androidx.compose.foundation.layout.offset
 import androidx.compose.foundation.layout.padding
 import androidx.compose.foundation.layout.size
 import androidx.compose.foundation.shape.RoundedCornerShape
-import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.filled.Home
-import androidx.compose.material.icons.filled.Person
 import androidx.compose.material3.Icon
 import androidx.compose.material3.Scaffold
 import androidx.compose.material3.Text
 import androidx.compose.runtime.Composable
-import androidx.compose.runtime.IntState
-import androidx.compose.runtime.mutableIntStateOf
+import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.runtime.collectAsState
+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.Color
-import androidx.compose.ui.graphics.vector.ImageVector
+import androidx.compose.ui.res.painterResource
 import androidx.compose.ui.text.style.TextAlign
 import androidx.compose.ui.unit.dp
 import androidx.compose.ui.unit.sp
@@ -59,18 +57,27 @@ class PageHome : PageBase() {
 
     @Composable
     fun Home(pv: PaddingValues, vm: VMHome = viewModel()) {
-        val navIndex = remember { mutableIntStateOf(0) }
+        val state by vm.state.collectAsState()
+        LaunchedEffect(Unit) { vm.init() }
         Scaffold(
-            modifier = Modifier.fillMaxSize(),
-            bottomBar = { CreateNavigationBar(pv, Color(0xFFFFFFFF), navIndex, onClick = { navIndex.intValue = it }) }
+            modifier = Modifier
+                .fillMaxSize(),
+            bottomBar = { CreateNavigationBar(pv, Color(0xFFFFFFFF), vm) }
         ) { ip ->
             Box(
                 modifier = Modifier
                     .padding(PaddingValues(bottom = ip.calculateBottomPadding() - pv.calculateBottomPadding()))
                     .fillMaxSize()
             ) {
-                HomeCompose(pv, if (navIndex.intValue == 0) 99f else 0f)
-                MyCompose(pv, if (navIndex.intValue == 1) 99f else 0f)
+                vm.state.value.navs.forEach { nav ->
+                    when (nav.id) {
+                        0 -> HomeCompose(pv, if (state.navIndex == 0) 99f else 0f, vm)
+                        1 -> JobsCompose(pv, if (state.navIndex == 1) 99f else 0f, vm)
+                        2 -> MessageCompose(pv, if (state.navIndex == 2) 99f else 0f, vm)
+                        3 -> MyCompose(pv, if (state.navIndex == 3) 99f else 0f)
+                    }
+                }
+
             }
         }
     }
@@ -79,49 +86,51 @@ class PageHome : PageBase() {
      * 构建底部导航栏
      */
     @Composable
-    fun CreateNavigationBar(pv: PaddingValues, bgColor: Color, navIndex: IntState, onClick: (value: Int) -> Unit) {
-        val navs = listOf(
-            NavBarItem("首页", Icons.Default.Home, Color(0xFF1779FF), Color(0xFF191919)),
-            NavBarItem("我的", Icons.Default.Person, Color(0xFF1779FF), Color(0xFF191919))
-        )
+    fun CreateNavigationBar(pv: PaddingValues, bgColor: Color, vm: VMHome) {
+        val state by vm.state.collectAsState()
         Row(
             modifier = Modifier
                 .fillMaxWidth()
                 .background(bgColor)
                 .padding(PaddingValues(bottom = pv.calculateBottomPadding()))
         ) {
-            navs.forEachIndexed { index, nav ->
+            state.navs.forEach { nav ->
                 Box(
                     modifier = Modifier
                         .weight(1.0f)
-                        .height(44.dp)
-                        .clickable(interactionSource = remember { MutableInteractionSource() }, indication = null, onClick = { onClick(index) }),
+                        .height(66.dp)
+                        .clickable(
+                            interactionSource = remember { MutableInteractionSource() },
+                            indication = null,
+                            onClick = { vm.updateNavIndex(nav.id) }),
                 ) {
                     Column(
                         verticalArrangement = Arrangement.Center, horizontalAlignment = Alignment.CenterHorizontally,
                         modifier = Modifier.align(Alignment.Center)
                     ) {
                         Icon(
-                            nav.icon, contentDescription = null,
-                            modifier = Modifier
-                                .size(26.dp),
-                            tint = if (navIndex.intValue == index) nav.selectedColor else nav.unselectedColor
+                            painter = painterResource(nav.icon),
+                            contentDescription = null,
+                            modifier = Modifier.size(18.dp),
+                            tint = if (state.navIndex == nav.id) nav.selectedColor else nav.unselectedColor
                         )
                         Text(
                             nav.title,
-                            fontSize = 10.sp,
-                            lineHeight = 10.sp,
-                            color = if (navIndex.intValue == index) nav.selectedColor else nav.unselectedColor
+                            Modifier.padding(top = 5.dp),
+                            fontSize = 12.sp,
+                            lineHeight = 12.sp,
+                            color = if (state.navIndex == nav.id) nav.selectedColor else nav.unselectedColor
                         )
                     }
-                    Text(
-                        "1", color = Color.White, modifier = Modifier
-                            .offset(x = 10.dp)
+                    if (nav.count > 0) Text(
+                        "${nav.count}", color = Color.White, modifier = Modifier
+                            .offset(x = 16.dp, y = 5.dp)
                             .defaultMinSize(14.dp, 14.dp)
                             .clip(RoundedCornerShape(14.dp))
                             .background(Color.Red)
                             .align(Alignment.TopCenter)
-                            .padding(top = 1.dp),
+                            .padding(top = 1.dp)
+                            .padding(horizontal = 2.dp),
                         textAlign = TextAlign.Center,
                         fontSize = 10.sp,
                         lineHeight = 10.sp
@@ -132,13 +141,3 @@ class PageHome : PageBase() {
     }
 
 }
-
-/**
- * 底部导航栏对象
- *
- * @param title             导航栏名称
- * @param icon              图标
- * @param selectedColor     选中的颜色
- * @param unselectedColor   未选中的颜色
- */
-data class NavBarItem(val title: String, val icon: ImageVector, val selectedColor: Color, val unselectedColor: Color)

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

@@ -15,6 +15,7 @@ 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.offset
 import androidx.compose.foundation.layout.padding
 import androidx.compose.foundation.layout.size
 import androidx.compose.foundation.layout.width
@@ -28,7 +29,7 @@ import androidx.compose.material3.Icon
 import androidx.compose.material3.LocalTextStyle
 import androidx.compose.material3.Text
 import androidx.compose.runtime.Composable
-import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.LaunchedEffect
 import androidx.compose.runtime.remember
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
@@ -36,6 +37,7 @@ import androidx.compose.ui.draw.clip
 import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.graphics.SolidColor
 import androidx.compose.ui.platform.LocalSoftwareKeyboardController
+import androidx.compose.ui.platform.SoftwareKeyboardController
 import androidx.compose.ui.res.painterResource
 import androidx.compose.ui.text.font.FontWeight
 import androidx.compose.ui.text.input.KeyboardType
@@ -44,12 +46,16 @@ import androidx.compose.ui.text.input.VisualTransformation
 import androidx.compose.ui.text.style.TextAlign
 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.ui.base.PageBase
+import com.iscs.bozzys.ui.pages.home.openPageHome
+import com.iscs.bozzys.ui.pages.vm.VMLogin
 import com.iscs.bozzys.ui.theme.Main
 import com.iscs.bozzys.ui.theme.SubMain
 import com.iscs.bozzys.ui.theme.Text
 import com.iscs.bozzys.ui.theme.TextDesc
+import kotlinx.coroutines.async
 
 /**
  * 打开登录页面
@@ -104,20 +110,19 @@ class PageLogin : PageBase() {
                     .weight(4f)
             ) {
                 // 登录输入框布局
-                LoginCompose()
+                LoginCompose(keyboard)
             }
         }
     }
 
     @Composable
-    fun LoginCompose() {
-        // 当前登录方式
-        // 0 - 验证码 1 - 账号密码
-        val loginType = remember { mutableStateOf(0) }
-        // 账号
-        val account = remember { mutableStateOf("") }
-        // 验证码或密码
-        val code = remember { mutableStateOf("") }
+    fun LoginCompose(kb: SoftwareKeyboardController?, vm: VMLogin = viewModel()) {
+        val state = vm.state
+        LaunchedEffect(Unit) {
+            // 处理基础Toast和Loading提示
+            async { vm.toastEvent.showToast() }
+            async { vm.loadingEvent.loading() }
+        }
         Column(
             Modifier
                 .fillMaxSize()
@@ -137,12 +142,12 @@ class PageLogin : PageBase() {
                     Modifier
                         .weight(1f)
                         .fillMaxHeight()
-                        .background(if (loginType.value == 0) SubMain else Color.White)
-                        .clickable(onClick = { loginType.value = 0 }),
-                    color = if (loginType.value == 0) Main else TextDesc,
+                        .background(if (state.loginType == 0) SubMain else Color.White)
+                        .clickable(onClick = { vm.updateLoginType(0) }),
+                    color = if (state.loginType == 0) Main else TextDesc,
                     lineHeight = 47.sp,
                     fontSize = 14.sp,
-                    fontWeight = if (loginType.value == 0) FontWeight.SemiBold else FontWeight.Normal,
+                    fontWeight = if (state.loginType == 0) FontWeight.SemiBold else FontWeight.Normal,
                     textAlign = TextAlign.Center
                 )
                 Text(
@@ -150,12 +155,12 @@ class PageLogin : PageBase() {
                     Modifier
                         .weight(1f)
                         .fillMaxHeight()
-                        .background(if (loginType.value == 1) SubMain else Color.White)
-                        .clickable(onClick = { loginType.value = 1 }),
-                    color = if (loginType.value == 1) Main else TextDesc,
+                        .background(if (state.loginType == 1) SubMain else Color.White)
+                        .clickable(onClick = { vm.updateLoginType(1) }),
+                    color = if (state.loginType == 1) Main else TextDesc,
                     lineHeight = 47.sp,
                     fontSize = 14.sp,
-                    fontWeight = if (loginType.value == 1) FontWeight.SemiBold else FontWeight.Normal,
+                    fontWeight = if (state.loginType == 1) FontWeight.SemiBold else FontWeight.Normal,
                     textAlign = TextAlign.Center,
                 )
             }
@@ -167,17 +172,19 @@ class PageLogin : PageBase() {
                     .padding(horizontal = 12.dp),
                 verticalAlignment = Alignment.CenterVertically
             ) {
-                val resId = if (loginType.value == 0) R.mipmap.phone else R.mipmap.user
-                Icon(painter = painterResource(resId), contentDescription = null, tint = Color(0xFF999999))
+                val resId = if (state.loginType == 0) R.drawable.phone else R.drawable.user
+                Icon(painter = painterResource(resId), contentDescription = null, tint = Color(0xFF999999), modifier = Modifier.size(18.dp))
                 BasicTextField(
-                    account.value,
+                    state.account,
                     onValueChange = { value ->
-                        account.value = if (loginType.value == 0) {
-                            // 手机号只能输入数字,不能包含小数点
-                            value.filter(Char::isDigit)
-                        } else {
-                            value
-                        }
+                        vm.updateAccount(
+                            if (state.loginType == 0) {
+                                // 手机号只能输入数字,不能包含小数点
+                                value.filter(Char::isDigit)
+                            } else {
+                                value
+                            }
+                        )
                     },
                     Modifier
                         .padding(horizontal = 16.dp)
@@ -187,14 +194,14 @@ class PageLogin : PageBase() {
                     decorationBox = { innerTextField ->
                         Box(contentAlignment = Alignment.CenterStart) {
                             innerTextField()
-                            if (account.value.isEmpty()) {
-                                val text = if (loginType.value == 0) "请输入手机号" else "请输入用户名"
-                                Text(text, color = Color(0xFF9CA3AF), fontSize = 16.sp, lineHeight = 20.sp)
+                            if (state.account.isEmpty()) {
+                                val text = if (state.loginType == 0) "请输入手机号" else "请输入用户名"
+                                Text(text, color = Color(0xFF9CA3AF), fontSize = 16.sp, lineHeight = 20.sp, modifier = Modifier.offset(y = (-1).dp))
                             }
                         }
                     },
                     cursorBrush = SolidColor(Main),
-                    keyboardOptions = KeyboardOptions(keyboardType = if (loginType.value == 0) KeyboardType.Number else KeyboardType.Email)
+                    keyboardOptions = KeyboardOptions(keyboardType = if (state.loginType == 0) KeyboardType.Number else KeyboardType.Email)
                 )
             }
             Row(
@@ -205,17 +212,19 @@ class PageLogin : PageBase() {
                     .padding(horizontal = 12.dp),
                 verticalAlignment = Alignment.CenterVertically
             ) {
-                val resId = if (loginType.value == 0) R.mipmap.code else R.mipmap.pwd
-                Icon(painter = painterResource(resId), contentDescription = null, tint = Color(0xFF999999))
+                val resId = if (state.loginType == 0) R.drawable.code else R.drawable.pwd
+                Icon(painter = painterResource(resId), contentDescription = null, tint = Color(0xFF999999), modifier = Modifier.size(18.dp))
                 BasicTextField(
-                    code.value,
+                    state.code,
                     onValueChange = { value ->
-                        code.value = if (loginType.value == 0) {
-                            // 验证码只能输入数字,不能包含小数点
-                            value.filter(Char::isDigit)
-                        } else {
-                            value
-                        }
+                        vm.updateCode(
+                            if (state.loginType == 0) {
+                                // 验证码只能输入数字,不能包含小数点
+                                value.filter(Char::isDigit)
+                            } else {
+                                value
+                            }
+                        )
                     },
                     Modifier
                         .padding(horizontal = 16.dp)
@@ -225,20 +234,25 @@ class PageLogin : PageBase() {
                     decorationBox = { innerTextField ->
                         Box(contentAlignment = Alignment.CenterStart) {
                             innerTextField()
-                            if (code.value.isEmpty()) {
-                                val text = if (loginType.value == 0) "请输入验证码" else "请输入密码"
-                                Text(text, color = Color(0xFF9CA3AF), fontSize = 16.sp, lineHeight = 20.sp)
+                            if (state.code.isEmpty()) {
+                                val text = if (state.loginType == 0) "请输入验证码" else "请输入密码"
+                                Text(text, color = Color(0xFF9CA3AF), fontSize = 16.sp, lineHeight = 20.sp, modifier = Modifier.offset(y = (-1).dp))
                             }
                         }
                     },
                     cursorBrush = SolidColor(Main),
-                    visualTransformation = if (loginType.value == 0) VisualTransformation.None else PasswordVisualTransformation(),
-                    keyboardOptions = KeyboardOptions(keyboardType = if (loginType.value == 0) KeyboardType.Number else KeyboardType.Password)
+                    visualTransformation = if (state.loginType == 0) VisualTransformation.None else PasswordVisualTransformation(),
+                    keyboardOptions = KeyboardOptions(keyboardType = if (state.loginType == 0) KeyboardType.Number else KeyboardType.Password)
                 )
             }
             // 登录按钮
             Button(
-                onClick = {}, Modifier
+                onClick = {
+                    // 隐藏输入框
+                    kb?.hide()
+                    // 执行登录操作
+                    vm.login { openPageHome() }
+                }, Modifier
                     .padding(top = 30.dp)
                     .size(335.dp, 52.dp)
                     .clip(RoundedCornerShape(5.dp))
@@ -248,7 +262,7 @@ class PageLogin : PageBase() {
             }
             // 账号提示
             Row(Modifier.padding(top = 16.dp), verticalAlignment = Alignment.CenterVertically) {
-                Icon(painter = painterResource(R.mipmap.login_tips), contentDescription = null, tint = Color(0xFF6B7280))
+                Icon(painter = painterResource(R.drawable.tips), contentDescription = null, tint = Color(0xFF6B7280), modifier = Modifier.size(12.dp))
                 Text("工业安全系统,请妥善保管账号信息", Modifier.padding(start = 5.dp), fontSize = 12.sp, color = Color(0xFF6B7280))
             }
             // 其他登录方式
@@ -267,29 +281,29 @@ class PageLogin : PageBase() {
             }
             Row(Modifier.padding(top = 30.dp, bottom = 10.dp), verticalAlignment = Alignment.CenterVertically) {
                 Icon(
-                    painter = painterResource(R.mipmap.fingerprint),
+                    painter = painterResource(R.drawable.fingerprint),
                     contentDescription = null,
                     Modifier
                         .padding(horizontal = 10.dp)
                         .size(50.dp)
                         .clip(RoundedCornerShape(50))
                         .background(Color(0xFFF5F5F5))
-                        .padding(15.dp),
+                        .padding(13.dp),
                     tint = Color(0xFF6B7280)
                 )
                 Icon(
-                    painter = painterResource(R.mipmap.qrcode),
+                    painter = painterResource(R.drawable.qrcode),
                     contentDescription = null,
                     Modifier
                         .padding(horizontal = 10.dp)
                         .size(50.dp)
                         .clip(RoundedCornerShape(50))
                         .background(Color(0xFFF5F5F5))
-                        .padding(15.dp),
+                        .padding(13.dp),
                     tint = Color(0xFF6B7280)
                 )
                 Icon(
-                    painter = painterResource(R.mipmap.bluetooth),
+                    painter = painterResource(R.drawable.bluetooth),
                     contentDescription = null,
                     Modifier
                         .padding(horizontal = 10.dp)

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

@@ -1,30 +1,66 @@
 package com.iscs.bozzys.ui.pages.vm
 
-import androidx.compose.runtime.getValue
-import androidx.compose.runtime.mutableStateOf
-import androidx.compose.runtime.setValue
+import androidx.compose.ui.graphics.Color
 import androidx.lifecycle.viewModelScope
-import com.iscs.bozzys.api.ApiRequest
-import com.iscs.bozzys.api.ApiRequest.getResponse
+import com.iscs.bozzys.R
 import com.iscs.bozzys.ui.base.VMBase
+import com.iscs.bozzys.ui.theme.Text
+import com.iscs.bozzys.utils.Storage
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.asStateFlow
 import kotlinx.coroutines.launch
 
 class VMHome : VMBase() {
 
-    var state by mutableStateOf(StateHome())
-        private set
+    private val _state = MutableStateFlow(StateHome())
+    val state = _state.asStateFlow()
 
-    fun login() {
+    fun init() {
         viewModelScope.launch {
-            ApiRequest.login("zhangsan", "1234567").onSuccess {
-                state = state.copy(username = it.nickName)
-                toastEvent.emit("登录成功")
-            }.onFailure {
-                toastEvent.emit(it.getResponse().msg)
-            }
+            val navs = listOf(
+                NavBarItem(0, "首页", R.drawable.home),
+                NavBarItem(1, "作业", R.drawable.jobs),
+                NavBarItem(2, "消息", R.drawable.message),
+                NavBarItem(3, "设置", R.drawable.settings)
+            )
+            _state.value = _state.value.copy(navs = navs, username = Storage.readUserName())
         }
     }
 
+    fun updateNavIndex(navIndex: Int) {
+        _state.value = _state.value.copy(navIndex = navIndex)
+    }
+
+    fun updateUnReadCount() {
+        // 更新未读消息数演示
+        val navs = _state.value.navs.map { it.copy(count = 12) }
+        _state.value = _state.value.copy(navs = ArrayList(navs))
+    }
+
 }
 
-data class StateHome(val username: String = "")
+/**
+ * @param navs      当前底部的导航列表
+ * @param navIndex  当前选中的底部导航
+ * @param username  用户名
+ */
+data class StateHome(val navs: List<NavBarItem> = arrayListOf(), var navIndex: Int = 0, var username: String = "")
+
+/**
+ * 底部导航栏对象
+ *
+ * @param id                用于标记当前
+ * @param title             导航栏名称
+ * @param icon              图标
+ * @param count             未读消息数
+ * @param selectedColor     选中的颜色
+ * @param unselectedColor   未选中的颜色
+ */
+data class NavBarItem(
+    val id: Int = 0,
+    val title: String = "",
+    val icon: Int = 0,
+    val count: Int = 0,
+    val selectedColor: Color = Color(0xFF1E90FF),
+    val unselectedColor: Color = Text
+)

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

@@ -0,0 +1,99 @@
+package com.iscs.bozzys.ui.pages.vm
+
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.setValue
+import androidx.lifecycle.viewModelScope
+import com.iscs.bozzys.R
+import com.iscs.bozzys.api.ApiRequest
+import com.iscs.bozzys.api.ApiRequest.getResponse
+import com.iscs.bozzys.ui.base.StateLoading
+import com.iscs.bozzys.ui.base.VMBase
+import com.iscs.bozzys.utils.Storage
+import com.iscs.bozzys.utils.Storage.saveToken
+import com.iscs.bozzys.utils.Storage.saveUserName
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.launch
+
+/**
+ * 登录ViewModel层
+ */
+class VMLogin : VMBase() {
+
+    var state by mutableStateOf(StateLogin())
+        private set
+
+    /**
+     * 更新登录方式
+     *
+     * @param type 0:短信验证码登录 1:账号密码登录
+     */
+    fun updateLoginType(type: Int) {
+        state = state.copy(loginType = type)
+    }
+
+    /**
+     * 更新账号字段数据
+     *
+     * @param account loginType=0时为手机号 loginType=1时为用户名
+     */
+    fun updateAccount(account: String) {
+        state = state.copy(account = account)
+    }
+
+    /**
+     * 更新code字段
+     *
+     * @param code loginType=0时为验证码 loginType=1时为密码
+     */
+    fun updateCode(code: String) {
+        state = state.copy(code = code)
+    }
+
+    /**
+     * 执行登录操作
+     */
+    fun login(done: () -> Unit) {
+        viewModelScope.launch {
+            val check = checkCanLogin()
+            if (check != 0) {
+                toastEvent.emit(check)
+                return@launch
+            }
+            loadingEvent.emit(StateLoading(show = true))
+            ApiRequest.login(state.account, state.code).onSuccess {
+                it.token.saveToken()
+                it.nickName.saveUserName()
+                Storage.saveLogin(true)
+                loadingEvent.emit(StateLoading(show = false))
+                delay(500)
+                toastEvent.emit("登录成功")
+                done.invoke()
+            }.onFailure {
+                delay(500)
+                loadingEvent.emit(StateLoading(show = false))
+                toastEvent.emit(it.getResponse().msg)
+            }
+        }
+    }
+
+    /**
+     * 检验是否可以提交登录
+     */
+    private fun checkCanLogin(): Int {
+        if (state.loginType == 0) {
+            if (state.account.trim().isEmpty()) return R.string.input_phone_number_tips
+            if (state.code.trim().isEmpty()) return R.string.input_code_tips
+        } else if (state.loginType == 1) {
+            if (state.account.trim().isEmpty()) return R.string.input_account_tips
+            if (state.code.trim().isEmpty()) return R.string.input_pwd_tips
+        }
+        return 0
+    }
+
+}
+
+/**
+ * 登录页面状态模型
+ */
+data class StateLogin(val loginType: Int = 0, val account: String = "", val code: String = "")

+ 14 - 0
app/src/main/java/com/iscs/bozzys/utils/Storage.kt

@@ -46,4 +46,18 @@ object Storage {
         return mmkv.decodeString("user_token", "") ?: ""
     }
 
+    /**
+     * 保存用户名
+     */
+    fun String?.saveUserName() {
+        mmkv.encode("user_name", this ?: "")
+    }
+
+    /**
+     * 读取用户名
+     */
+    fun readUserName(): String {
+        return mmkv.decodeString("user_name", "") ?: ""
+    }
+
 }

+ 9 - 0
app/src/main/res/drawable/bell.xml

@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="32dp"
+    android:height="32dp"
+    android:viewportWidth="1024"
+    android:viewportHeight="1024">
+  <path
+      android:fillColor="#FF000000"
+      android:pathData="M849.6,713.4c8.4,-0.4 16.7,1.8 23.8,6.4 -28.9,-18.5 -46.4,-50.4 -46.3,-84.8V436c0,-145.9 -105.7,-267.6 -246.9,-297.5v-7.2c0,-37.1 -30.1,-67.1 -67.2,-67.1h-0.1c-37.1,0 -67.3,30.1 -67.3,67.2v7C304.3,168.4 198.7,290 198.7,436v199.1c0,35.7 -18.6,66.9 -46.4,84.8 7,-4.6 15.4,-6.9 23.8,-6.4 -24.7,-0.9 -45.5,18.4 -46.4,43.1 -0.9,24.7 18.4,45.5 43.1,46.4h676.6c24.7,0.1 44.8,-20 44.9,-44.7 0.1,-24.8 -19.9,-44.9 -44.7,-44.9zM513,959.8c62,0 112.2,-50.2 112.2,-111.9H400.7c0,61.7 50.2,111.9 112.3,111.9z"/>
+</vector>

File diff suppressed because it is too large
+ 7 - 0
app/src/main/res/drawable/bluetooth.xml


+ 9 - 0
app/src/main/res/drawable/code.xml

@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="32dp"
+    android:height="32dp"
+    android:viewportWidth="1024"
+    android:viewportHeight="1024">
+  <path
+      android:fillColor="#FF000000"
+      android:pathData="M946.8,96.3L946.8,606q0,45.8 -21.7,91.2a430.6,430.6 0,0 1,-57 88,632.4 632.4,0 0,1 -80.4,80.6A872.8,872.8 0,0 1,696 933.6a702.5,702.5 0,0 1,-90.4 49.5q-43.9,19.7 -77,27l-10.6,1.8 -9.6,-1.8q-33.9,-7.4 -78.7,-27a762,762 0,0 1,-93 -49.5A871.3,871.3 0,0 1,242 865.8a655.9,655.9 0,0 1,-83 -80.6,429.1 429.1,0 0,1 -59.1,-88Q77.2,651.8 77.2,606L77.2,96.3l35.6,-5.5L512.9,12l407.8,78.8 26,5.5zM513,85.8l-4.8,-1L164.9,146.3v321.5L513,467.8v-382zM859.1,467.8L513,467.8v457.7a476.3,476.3 0,0 0,72.7 -24.7,646.3 646.3,0 0,0 77.4,-39.3 692,692 0,0 0,73.7 -50.4,440.6 440.6,0 0,0 62.7,-59.5 294.4,294.4 0,0 0,43.5 -66,160.2 160.2,0 0,0 16.3,-69.6v-148.2z"/>
+</vector>

+ 9 - 0
app/src/main/res/drawable/delete_all.xml

@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="32dp"
+    android:height="32dp"
+    android:viewportWidth="1024"
+    android:viewportHeight="1024">
+  <path
+      android:pathData="M736,128l-32,-64H320l-32,64H128v128h768V128H736zM192,896a64,64 0,0 0,64 64h512a64,64 0,0 0,64 -64V320H192z"
+      android:fillColor="#231815"/>
+</vector>

+ 9 - 0
app/src/main/res/drawable/fingerprint.xml

@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="32dp"
+    android:height="32dp"
+    android:viewportWidth="1024"
+    android:viewportHeight="1024">
+  <path
+      android:pathData="M749.3,780.8a32,32 0,0 1,-64 0L685.3,646.4c0,-99 -80.3,-179.2 -179.3,-179.2 -99,0 -179.3,80.2 -179.3,179.2v115.2a32,32 0,0 1,-64 0L262.7,646.4c0,-134.3 108.9,-243.2 243.3,-243.2 134.4,0 243.3,108.9 243.3,243.2v134.4zM899.2,279.9a32,32 0,0 1,-4 45.1,32 32,0 0,1 -45.1,-4C765.4,219.6 640.6,160 506,160 377.4,160 257.6,214.4 173.1,308a32,32 0,0 1,-45.2 2.3,32 32,0 0,1 -2.3,-45.2C222.1,158.2 359.1,96 506,96c153.8,0 296.5,68.2 393.2,183.9zM883.7,627.2a32,32 0,0 1,-64 0c0,-130.2 -80.1,-245.5 -199.4,-292.1a32,32 0,1 1,23.3 -59.6C787.3,331.7 883.7,470.4 883.7,627.2zM506,249.6a32,32 0,1 1,0 64c-173.3,0 -313.7,140.4 -313.7,313.6a32,32 0,0 1,-64 0c0,-208.5 169.1,-377.6 377.7,-377.6zM506,620.8a25.6,25.6 0,0 0,-25.6 25.1l0.2,5.2a1953.1,1953.1 0,0 1,1.2 61.8c0,19.9 -0.4,36.5 -1.5,49.1 -3.6,41.9 -15.1,78.4 -32.1,109.5a222.3,222.3 0,0 1,-23.6 35.1c-5.2,6.2 -9.5,10.7 -12.4,13.3a32,32 0,0 1,-45.2 -2.4,32 32,0 0,1 2.4,-45.2c-0.1,0.1 0.3,-0.2 0.9,-1 1.4,-1.5 3.1,-3.3 5,-5.6a158.6,158.6 0,0 0,16.7 -25c12.9,-23.5 21.7,-51.5 24.5,-84.2 0.9,-10.4 1.3,-25.4 1.3,-43.6a1643.5,1643.5 0,0 0,-1.2 -59.6l-0.2,-5.6 -0,-1.3c0,-49.5 40.1,-89.6 89.6,-89.6a89.6,89.6 0,0 1,89.6 89.6v171.1a32,32 0,0 1,-64 0L531.6,646.4a25.6,25.6 0,0 0,-25.6 -25.6z"
+      android:fillColor="#000000"/>
+</vector>

+ 9 - 0
app/src/main/res/drawable/home.xml

@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="32dp"
+    android:height="32dp"
+    android:viewportWidth="1024"
+    android:viewportHeight="1024">
+  <path
+      android:fillColor="#FF000000"
+      android:pathData="M1002.4,459.8 L619.2,61.7C593.7,36.2 549,0 512.8,0c-36.2,0 -59.6,17 -85.2,42.6l-404.5,396c-27.7,40.4 -23.4,40.4 -21.3,61.7 0,12.8 -4.3,42.6 42.6,42.6l85.2,0 0,334.2c0,72.4 31.9,146.9 106.4,146.9l170.3,0L406.3,666.3c0,-36.2 4.3,-42.6 42.6,-42.6l127.7,0c38.3,0 42.6,6.4 42.6,42.6L619.2,1021.9l170.3,0c74.5,0 106.4,-74.5 106.4,-146.9L896,562l85.2,0c31.9,2.1 42.6,-29.8 42.6,-42.6C1023.7,489.6 1017.3,479 1002.4,459.8L1002.4,459.8z"/>
+</vector>

+ 9 - 0
app/src/main/res/drawable/job_finish.xml

@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="32dp"
+    android:height="32dp"
+    android:viewportWidth="1024"
+    android:viewportHeight="1024">
+  <path
+      android:fillColor="#FF000000"
+      android:pathData="M512,0C229.2,0 0,229.2 0,512s229.2,512 512,512 512,-229.2 512,-512S794.8,0 512,0zM807.5,339.5l-313.2,382 -21.6,26.3a50.5,50.5 0,0 1,-7.2 7.2c-0.6,0.5 -1.3,1 -2,1.5 -1.1,0.8 -2.2,1.5 -3.3,2.2 -0.6,0.3 -1.1,0.7 -1.7,1s-1.3,0.7 -1.9,1c-1.2,0.6 -2.4,1.2 -3.7,1.7a51,51 0,0 1,-5.1 1.7c-1.4,0.4 -2.8,0.7 -4.2,1a50.8,50.8 0,0 1,-9.5 0.9h-0.1a51.4,51.4 0,0 1,-7.2 -0.5,49.7 49.7,0 0,1 -20.5,-7.8 48.9,48.9 0,0 1,-4.1 -3L200.2,589a50,50 0,0 1,-7 -70.4,50 50,0 0,1 70.4,-7l124.9,102.5a50,50 0,0 0,70.4 -7l271.4,-331a50,50 0,0 1,70.4 -7,50 50,0 0,1 7,70.5z"/>
+</vector>

+ 9 - 0
app/src/main/res/drawable/job_ing.xml

@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="32dp"
+    android:height="32dp"
+    android:viewportWidth="1024"
+    android:viewportHeight="1024">
+  <path
+      android:pathData="M512,0C230.4,0 0,230.4 0,512s230.4,512 512,512 512,-230.4 512,-512 -230.4,-512 -512,-512zM503.5,776.5c0,8.5 -8.5,17.1 -17.1,17.1l-102.4,59.7c-8.5,0 -8.5,8.5 -17.1,8.5S341.3,853.3 341.3,844.8c-8.5,-17.1 0,-34.1 8.5,-42.7l25.6,-8.5c-119.5,-51.2 -196.3,-170.7 -196.3,-290.1s68.3,-230.4 179.2,-281.6c17.1,-8.5 34.1,0 42.7,17.1 8.5,17.1 0,34.1 -17.1,42.7 -85.3,42.7 -145.1,128 -145.1,221.9 0,102.4 68.3,196.3 162.1,230.4L375.5,682.7c-8.5,-17.1 0,-34.1 8.5,-42.7 17.1,-8.5 34.1,0 42.7,8.5l59.7,102.4c17.1,8.5 17.1,17.1 17.1,25.6zM665.6,810.7h-17.1c-17.1,0 -25.6,-8.5 -34.1,-17.1 -8.5,-17.1 0,-34.1 17.1,-42.7 85.3,-42.7 145.1,-128 145.1,-221.9 0,-102.4 -59.7,-196.3 -162.1,-230.4l25.6,42.7c8.5,17.1 0,34.1 -17.1,42.7h-17.1c-8.5,8.5 -17.1,0 -25.6,-8.5l-51.2,-110.9c0,-8.5 -8.5,-17.1 0,-25.6s8.5,-17.1 17.1,-17.1L657.1,170.7c17.1,-8.5 34.1,0 42.7,17.1 8.5,17.1 0,34.1 -17.1,42.7l-25.6,8.5c110.9,51.2 187.7,162.1 187.7,281.6 0,128 -68.3,238.9 -179.2,290.1z"
+      android:fillColor="#2c2c2c"/>
+</vector>

+ 9 - 0
app/src/main/res/drawable/job_todo.xml

@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="32dp"
+    android:height="32dp"
+    android:viewportWidth="1024"
+    android:viewportHeight="1024">
+  <path
+      android:fillColor="#FF000000"
+      android:pathData="M512,0C229.2,0 0,229.2 0,512s229.2,512 512,512 512,-229.2 512,-512S794.8,0 512,0zM818,622.2h-380.7v-10.3h-3.8L433.5,231.2h64.7v326.3h319.8v64.7z"/>
+</vector>

+ 9 - 0
app/src/main/res/drawable/jobs.xml

@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="32dp"
+    android:height="32dp"
+    android:viewportWidth="1024"
+    android:viewportHeight="1024">
+  <path
+      android:fillColor="#FF000000"
+      android:pathData="M965.1,684c-11.3,-18.9 -25.6,-37.9 -43,-54.8 -16.9,-16.4 -35.3,-31.2 -55.8,-43.5l34.3,-34.3s49.2,0 73.7,24.6c24.6,24.6 24.6,73.7 24.6,73.7l-33.8,34.3M661.5,991.7H558.6V888.8l12.3,-12.3c22.5,10.8 43,25.1 60.4,42.5 17.4,17.4 32.3,37.9 42.5,60.4l-12.3,12.3m274.9,-279.6l-233,237.1a273.8,273.8 0,0 0,-45.1 -57.3c-17.4,-17.4 -37.4,-32.8 -58.4,-45.1l237.6,-233.5c21.5,10.2 41,24.1 57.9,40.4s31.2,37.4 41,58.4m-482.3,179.2c-0.5,-12.8 76.3,-94.2 166.4,-185.3h-401.9c-21.5,0 -38.9,-17.4 -38.9,-38.9 0,-21.5 17.4,-38.9 38.9,-38.9h454.1c7.2,0 13.8,2 19.5,5.1 78.8,-78.8 155.6,-153.6 191,-187.9V90.6c0,-47.1 -38.4,-85.5 -85.5,-85.5H111.1C64,5.1 25.6,43.5 25.6,90.6v842.2c0,47.1 38.4,85.5 85.5,85.5h343.6c0,-47.1 0,-109.1 -0.5,-127M178.2,258c0,-21.5 17.4,-38.9 38.9,-38.9H673.3c21.5,0 38.9,17.4 38.9,38.9s-17.4,38.9 -38.9,38.9H217.1c-21.5,0 -38.9,-17.4 -38.9,-38.9m1.5,206.3c0,-21.5 17.4,-38.9 38.9,-38.9h454.1c21.5,0 38.9,17.4 38.9,38.9 0,21.5 -17.4,38.9 -38.9,38.9H219.1c-21.5,0 -39.4,-17.9 -39.4,-38.9"/>
+</vector>

+ 9 - 0
app/src/main/res/drawable/location.xml

@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="32dp"
+    android:height="32dp"
+    android:viewportWidth="1024"
+    android:viewportHeight="1024">
+  <path
+      android:fillColor="#FF000000"
+      android:pathData="M702.9,777.6c-11.7,-3.2 -23.7,3.8 -26.9,15.4 -3.2,11.7 3.8,23.7 15.5,26.9 73,19.7 105.7,47.5 105.7,66.3 0,14.5 -19.8,37.1 -75.4,56.9 -55.7,19.9 -130.2,30.8 -209.8,30.8 -79.6,0 -154.1,-10.9 -209.8,-30.8 -55.6,-19.9 -75.4,-42.4 -75.4,-56.9 0,-18.8 32.7,-46.6 105.8,-66.3 11.7,-3.2 18.6,-15.2 15.5,-26.9 -3.2,-11.7 -15.2,-18.6 -26.9,-15.5 -89.1,24.1 -138.2,62.7 -138.2,108.7 0,26.9 17.4,47.2 31.9,59.5 17.5,14.8 41.9,27.8 72.6,38.8 60.3,21.5 140.1,33.4 224.5,33.4 84.5,0 164.2,-11.9 224.6,-33.4 30.7,-11 55.1,-24 72.6,-38.8 14.6,-12.3 31.9,-32.6 31.9,-59.5 0,-46 -49.1,-84.6 -138.1,-108.7v0zM422,826.7c23.4,26.8 56.2,42.2 90.1,42.2h0c34,0 66.8,-15.5 90.1,-42.6 7.1,-7.7 67.1,-73.8 127.9,-160.4 88.1,-125.4 132.8,-229.4 132.8,-308.9 0,-47.4 -9.3,-93.3 -27.6,-136.6 -17.7,-41.8 -43,-79.3 -75.2,-111.6 -32.2,-32.2 -69.8,-57.5 -111.6,-75.2 -43.3,-18.3 -89.3,-27.6 -136.6,-27.6 -47.4,0 -93.3,9.3 -136.6,27.6 -41.8,17.7 -79.3,43 -111.6,75.2 -32.2,32.2 -57.5,69.8 -75.2,111.6 -18.3,43.3 -27.6,89.3 -27.6,136.6 0,79.6 44.7,183.5 132.9,309 61.2,87.1 121.7,153.6 128.1,160.6v0zM375.9,347.3c0,-77.4 63,-140.4 140.4,-140.4 77.4,0 140.4,63 140.4,140.4 0,77.4 -63,140.4 -140.4,140.4 -77.4,0 -140.4,-63 -140.4,-140.4v0zM375.9,347.3z"/>
+</vector>

+ 9 - 0
app/src/main/res/drawable/message.xml

@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="32dp"
+    android:height="32dp"
+    android:viewportWidth="1024"
+    android:viewportHeight="1024">
+  <path
+      android:pathData="M903.6,26.8c66.2,0 119.9,53.7 119.9,119.9v625.4c0,66.2 -53.7,119.9 -119.9,119.9L704.7,891.9a59.9,59.9 0,0 0,-32.3 9.4l-143.9,92a30,30 0,0 1,-32.6 -0.2l-139.3,-91.4a59.9,59.9 0,0 0,-32.9 -9.8h-202.3c-66.2,0 -119.9,-53.7 -119.9,-119.9L1.5,146.6c0,-66.2 53.7,-119.9 119.9,-119.9h782.2zM279.2,406.6c-38.6,0 -69.9,31.3 -69.9,69.9s31.3,69.9 69.9,69.9 69.9,-31.3 69.9,-69.9 -31.3,-69.9 -69.9,-69.9zM512,406.6c-38.6,0 -69.9,31.3 -69.9,69.9s31.3,69.9 69.9,69.9 69.9,-31.3 69.9,-69.9 -31.3,-69.9 -69.9,-69.9zM744.8,406.6c-38.6,0 -69.9,31.3 -69.9,69.9s31.3,69.9 69.9,69.9 69.9,-31.3 69.9,-69.9 -31.3,-69.9 -69.9,-69.9z"
+      android:fillColor="#2c2c2c"/>
+</vector>

+ 9 - 0
app/src/main/res/drawable/phone.xml

@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="32dp"
+    android:height="32dp"
+    android:viewportWidth="1024"
+    android:viewportHeight="1024">
+  <path
+      android:pathData="M170.7,0v967.1h682.7L853.3,0zM512,910.2a85.3,85.3 0,1 1,85.3 -85.3A85.3,85.3 0,0 1,512 910.2zM739.6,682.7L284.4,682.7L284.4,113.8h455.1z"
+      android:fillColor="#333333"/>
+</vector>

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

@@ -0,0 +1,12 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="32dp"
+    android:height="32dp"
+    android:viewportWidth="1024"
+    android:viewportHeight="1024">
+  <path
+      android:fillColor="#FF000000"
+      android:pathData="M639.9,351.9C639.9,192.9 511.1,64 352,64S64.2,192.8 64.2,351.9c0,158.9 128.8,287.9 287.9,287.9 158.9,-0.1 287.8,-128.9 287.8,-287.9zM272.5,368.3c-50.4,0 -91.3,-40.9 -91.3,-91.3s40.9,-91.3 91.3,-91.3 91.3,40.9 91.3,91.3 -40.9,91.3 -91.3,91.3z"/>
+  <path
+      android:fillColor="#FF000000"
+      android:pathData="M930,732.3L663.8,455l-43,71.6h0.7l253.4,266.3 -1.8,27.6 -45.9,1.8 -237.7,-250.4c-39.1,46 -85.6,70.5 -85.6,70.5l5.5,112 53.3,58.8H706L704.2,949l126.7,11s12.9,-12.9 91.9,-90c78.9,-77.1 7.2,-137.7 7.2,-137.7z"/>
+</vector>

+ 9 - 0
app/src/main/res/drawable/qrcode.xml

@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="32dp"
+    android:height="32dp"
+    android:viewportWidth="1024"
+    android:viewportHeight="1024">
+  <path
+      android:pathData="M384,928 L192,928c-52.9,0 -96,-43.1 -96,-96l0,-192c0,-52.9 43.1,-96 96,-96l192,0c52.9,0 96,43.1 96,96l0,192C480,884.9 436.9,928 384,928zM192,608c-17.6,0 -32,14.3 -32,32l0,192c0,17.7 14.4,32 32,32l192,0c17.6,0 32,-14.3 32,-32l0,-192c0,-17.7 -14.4,-32 -32,-32L192,608zM736,896c-17.7,0 -32,-14.3 -32,-32l0,-64c0,-17.7 14.3,-32 32,-32s32,14.3 32,32l0,64C768,881.7 753.7,896 736,896zM864,896c-17.7,0 -32,-14.3 -32,-32l0,-96c0,-17.7 14.3,-32 32,-32s32,14.3 32,32l0,96C896,881.7 881.7,896 864,896zM864,672c-17.7,0 -32,-14.3 -32,-32l0,-64c0,-17.7 14.3,-32 32,-32s32,14.3 32,32l0,64C896,657.7 881.7,672 864,672zM736,736c-17.7,0 -32,-14.3 -32,-32l0,-128c0,-17.7 14.3,-32 32,-32s32,14.3 32,32l0,128C768,721.7 753.7,736 736,736zM608,896c-17.7,0 -32,-14.3 -32,-32l0,-128c0,-17.7 14.3,-32 32,-32s32,14.3 32,32l0,128C640,881.7 625.7,896 608,896zM608,640c-17.7,0 -32,-14.3 -32,-32l0,-32c0,-17.7 14.3,-32 32,-32s32,14.3 32,32l0,32C640,625.7 625.7,640 608,640zM320,800 L256,800c-17.7,0 -32,-14.3 -32,-32l0,-64c0,-17.7 14.3,-32 32,-32l64,0c17.7,0 32,14.3 32,32l0,64C352,785.7 337.7,800 320,800zM384,480 L192,480c-52.9,0 -96,-43.1 -96,-96L96,192c0,-52.9 43.1,-96 96,-96l192,0c52.9,0 96,43.1 96,96l0,192C480,436.9 436.9,480 384,480zM192,160C174.4,160 160,174.4 160,192l0,192c0,17.6 14.4,32 32,32l192,0c17.6,0 32,-14.4 32,-32L416,192c0,-17.6 -14.4,-32 -32,-32L192,160zM320,352 L256,352c-17.7,0 -32,-14.3 -32,-32L224,256c0,-17.7 14.3,-32 32,-32l64,0c17.7,0 32,14.3 32,32l0,64C352,337.7 337.7,352 320,352zM832,480l-192,0c-52.9,0 -96,-43.1 -96,-96L544,192c0,-52.9 43.1,-96 96,-96l192,0c52.9,0 96,43.1 96,96l0,192C928,436.9 884.9,480 832,480zM640,160c-17.7,0 -32,14.4 -32,32l0,192c0,17.6 14.3,32 32,32l192,0c17.7,0 32,-14.4 32,-32L864,192c0,-17.6 -14.3,-32 -32,-32L640,160zM768,352l-64,0c-17.7,0 -32,-14.3 -32,-32L672,256c0,-17.7 14.3,-32 32,-32l64,0c17.7,0 32,14.3 32,32l0,64C800,337.7 785.7,352 768,352z"
+      android:fillColor="#272636"/>
+</vector>

+ 9 - 0
app/src/main/res/drawable/read_all.xml

@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="40dp"
+    android:height="32dp"
+    android:viewportWidth="1280"
+    android:viewportHeight="1024">
+  <path
+      android:fillColor="#FF000000"
+      android:pathData="M896.6,0A270.9,270.9 0,0 0,832 176c0,39.9 8.6,77.8 24.1,112H160a32,32 0,0 0,0 64h736.6A271.4,271.4 0,0 0,1152 443.8L1152,640a192,192 0,0 1,-192 192h-268.9l-87.7,146.2a32,32 0,0 1,-6.7 7.9l-4.3,3.1a32,32 0,0 1,-43.9 -11L460.8,832 192,832a192,192 0,0 1,-192 -192V192a192,192 0,0 1,192 -192h704.6zM544,512h-384a32,32 0,0 0,0 64h384a32,32 0,0 0,0 -64zM1104,16a160,160 0,1 1,0 320,160 160,0 0,1 0,-320z"/>
+</vector>

File diff suppressed because it is too large
+ 7 - 0
app/src/main/res/drawable/settings.xml


+ 9 - 0
app/src/main/res/drawable/tips.xml

@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="32dp"
+    android:height="32dp"
+    android:viewportWidth="1024"
+    android:viewportHeight="1024">
+  <path
+      android:pathData="M512,0c-282.8,0 -512,229.2 -512,512s229.2,512 512,512c282.8,0 512,-229.2 512,-512S794.8,0 512,0zM650.5,799.3c-30.1,10.4 -53.8,18.4 -71.8,24.1 -17.8,5.7 -38.6,8.5 -62.3,8.5 -36.3,0 -64.6,-8.1 -84.7,-23.7 -20.3,-16.1 -30.4,-36 -30.4,-60.6 0,-9.5 0.8,-18.9 2.3,-28.9 1.6,-9.9 4.1,-21.3 7.2,-33.6l37.5,-118.8c3.4,-11.3 1.5,-21.7 3.8,-32.2 2.3,-9.9 3.3,-19.4 3.3,-27.4 0,-15.6 1.4,-26.1 -5.5,-31.7 -7.2,-6.2 -20.3,-4.4 -40.1,-4.4 -9.8,0 -19.8,1.4 -29.9,3.8 -10.3,2.8 -19,0.6 -26.3,3.5l10.1,-36.9c24.4,-9 48.1,-16.6 70.5,-22.7 22.4,-6.6 43.7,-9.5 63.5,-9.5 36.3,0 64.1,7.6 83.6,23.2 19.6,15.6 41.2,36 41.2,60.6 0,5.2 -0.8,14.2 -2.1,27.5 -1.3,12.8 -3.9,24.6 -7.5,35.5L563.8,673.9c-2.8,9.5 -5.7,20.4 -8,32.7 -2.6,11.8 -3.9,21.3 -3.9,27.5 0,15.6 4.1,26.5 11.8,32.2 8,5.7 21.6,8.5 40.9,8.5 9,0 19.3,-1.4 30.9,-4.2 11.6,-2.8 19.8,-5.2 24.9,-7.6L650.5,799.3zM643.9,319.4c-17.2,14.7 -38.3,21.8 -62.8,21.8 -24.4,0 -45.5,-7.1 -63.3,-21.8 -17.5,-14.2 -26.2,-31.7 -26.2,-52.5 0,-20.4 8.7,-37.9 26.2,-52.5 17.8,-14.7 38.9,-22.2 63.3,-22.2 24.4,0 45.5,7.6 62.8,22.2 17.5,14.7 26.3,32.2 26.3,52.5C670.1,287.6 661.4,305.1 643.9,319.4z"
+      android:fillColor="#272536"/>
+</vector>

+ 9 - 0
app/src/main/res/drawable/user.xml

@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="32dp"
+    android:height="32dp"
+    android:viewportWidth="1024"
+    android:viewportHeight="1024">
+  <path
+      android:fillColor="#FF000000"
+      android:pathData="M502.2,38.6c-131.1,0 -237.5,104.2 -237.5,232.7s106.4,232.7 237.5,232.7c131.2,0 237.6,-104.2 237.6,-232.7s-106.3,-232.7 -237.6,-232.7zM502.2,38.6c-131.1,0 -237.5,104.2 -237.5,232.7s106.4,232.7 237.5,232.7c131.2,0 237.6,-104.2 237.6,-232.7s-106.3,-232.7 -237.6,-232.7zM413.2,581.7c-169.5,0 -306.9,134.6 -306.9,300.6v19.3c0,67.9 137.4,68 306.9,68h198c169.4,0 306.8,-2.5 306.8,-68v-19.3c0,-166 -137.4,-300.6 -306.8,-300.6L413.2,581.7zM413.2,581.7"/>
+</vector>

BIN
app/src/main/res/mipmap-hdpi/bluetooth.png


BIN
app/src/main/res/mipmap-hdpi/code.png


BIN
app/src/main/res/mipmap-hdpi/fingerprint.png


BIN
app/src/main/res/mipmap-hdpi/login_tips.png


BIN
app/src/main/res/mipmap-hdpi/phone.png


BIN
app/src/main/res/mipmap-hdpi/pwd.png


BIN
app/src/main/res/mipmap-hdpi/qrcode.png


BIN
app/src/main/res/mipmap-hdpi/user.png


BIN
app/src/main/res/mipmap-xhdpi/bluetooth.png


BIN
app/src/main/res/mipmap-xhdpi/code.png


BIN
app/src/main/res/mipmap-xhdpi/fingerprint.png


BIN
app/src/main/res/mipmap-xhdpi/login_tips.png


BIN
app/src/main/res/mipmap-xhdpi/phone.png


BIN
app/src/main/res/mipmap-xhdpi/pwd.png


BIN
app/src/main/res/mipmap-xhdpi/qrcode.png


BIN
app/src/main/res/mipmap-xhdpi/user.png


BIN
app/src/main/res/mipmap-xxhdpi/bluetooth.png


BIN
app/src/main/res/mipmap-xxhdpi/code.png


BIN
app/src/main/res/mipmap-xxhdpi/fingerprint.png


BIN
app/src/main/res/mipmap-xxhdpi/login_tips.png


BIN
app/src/main/res/mipmap-xxhdpi/phone.png


BIN
app/src/main/res/mipmap-xxhdpi/pwd.png


BIN
app/src/main/res/mipmap-xxhdpi/qrcode.png


BIN
app/src/main/res/mipmap-xxhdpi/user.png


BIN
app/src/main/res/mipmap-xxxhdpi/bluetooth.png


BIN
app/src/main/res/mipmap-xxxhdpi/code.png


BIN
app/src/main/res/mipmap-xxxhdpi/fingerprint.png


BIN
app/src/main/res/mipmap-xxxhdpi/login_tips.png


BIN
app/src/main/res/mipmap-xxxhdpi/phone.png


BIN
app/src/main/res/mipmap-xxxhdpi/pwd.png


BIN
app/src/main/res/mipmap-xxxhdpi/qrcode.png


BIN
app/src/main/res/mipmap-xxxhdpi/user.png


+ 4 - 0
app/src/main/res/values-zh-rCN/strings.xml

@@ -2,4 +2,8 @@
 <resources>
     <string name="app_name">博士安全</string>
     <string name="push_channel_normal">常规</string>
+    <string name="input_phone_number_tips">请输入手机号</string>
+    <string name="input_code_tips">请输入验证码</string>
+    <string name="input_account_tips">请输入用户名</string>
+    <string name="input_pwd_tips">请输入密码</string>
 </resources>

+ 4 - 0
app/src/main/res/values/strings.xml

@@ -1,4 +1,8 @@
 <resources>
     <string name="app_name">Bozzys</string>
     <string name="push_channel_normal">Normal</string>
+    <string name="input_phone_number_tips">Please input phone number</string>
+    <string name="input_code_tips">Please input code</string>
+    <string name="input_account_tips">Please input account</string>
+    <string name="input_pwd_tips">Please input password</string>
 </resources>

Some files were not shown because too many files changed in this diff