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

feat:
- 基础搭建
- 登录界面完成

周文健 пре 2 месеци
родитељ
комит
efa5509333
100 измењених фајлова са 2357 додато и 206 уклоњено
  1. BIN
      ISCS.jks
  2. 37 2
      app/build.gradle.kts
  3. 50 5
      app/src/main/AndroidManifest.xml
  4. 137 0
      app/src/main/assets/i18n/zh-CN.json
  5. 47 0
      app/src/main/assets/logback.xml
  6. 1 0
      app/src/main/assets/themes/Default/icons/access-control.svg
  7. 4 0
      app/src/main/assets/themes/Default/icons/arrow-down-strenght.svg
  8. 4 0
      app/src/main/assets/themes/Default/icons/arrow-progress-alt.svg
  9. 4 0
      app/src/main/assets/themes/Default/icons/back-up.svg
  10. 2 0
      app/src/main/assets/themes/Default/icons/ballot-check.svg
  11. 2 0
      app/src/main/assets/themes/Default/icons/ballot.svg
  12. 4 0
      app/src/main/assets/themes/Default/icons/bolt-slash.svg
  13. 2 0
      app/src/main/assets/themes/Default/icons/bolt.svg
  14. BIN
      app/src/main/assets/themes/Default/icons/cards-blank.png
  15. 2 0
      app/src/main/assets/themes/Default/icons/chalkboard-user.svg
  16. 22 0
      app/src/main/assets/themes/Default/icons/checkbox.svg
  17. 4 0
      app/src/main/assets/themes/Default/icons/choose.svg
  18. 1 0
      app/src/main/assets/themes/Default/icons/document.svg
  19. BIN
      app/src/main/assets/themes/Default/icons/external-world.png
  20. 11 0
      app/src/main/assets/themes/Default/icons/face-id-svgrepo-com.svg
  21. 2 0
      app/src/main/assets/themes/Default/icons/file-export.svg
  22. 2 0
      app/src/main/assets/themes/Default/icons/fingerprint.svg
  23. 2 0
      app/src/main/assets/themes/Default/icons/fire-flame-curved.svg
  24. 2 0
      app/src/main/assets/themes/Default/icons/gas-pump.svg
  25. 2 0
      app/src/main/assets/themes/Default/icons/heat.svg
  26. 1 0
      app/src/main/assets/themes/Default/icons/icon_bottom_menu_data_manage.svg
  27. 2 0
      app/src/main/assets/themes/Default/icons/icon_bottom_menu_exception_manage.svg
  28. 2 0
      app/src/main/assets/themes/Default/icons/icon_bottom_menu_hardware_manage.svg
  29. 26 0
      app/src/main/assets/themes/Default/icons/icon_bottom_menu_home.svg
  30. 4 0
      app/src/main/assets/themes/Default/icons/icon_bottom_menu_job_manage.svg
  31. 60 0
      app/src/main/assets/themes/Default/icons/key.svg
  32. 4 0
      app/src/main/assets/themes/Default/icons/land-location.svg
  33. 4 0
      app/src/main/assets/themes/Default/icons/leave.svg
  34. 4 0
      app/src/main/assets/themes/Default/icons/limit-hand.svg
  35. 2 0
      app/src/main/assets/themes/Default/icons/location-crosshairs.svg
  36. 22 0
      app/src/main/assets/themes/Default/icons/lock.svg
  37. 4 0
      app/src/main/assets/themes/Default/icons/master-plan.svg
  38. 4 0
      app/src/main/assets/themes/Default/icons/message-alert.svg
  39. 54 0
      app/src/main/assets/themes/Default/icons/new_sop.svg
  40. 4 0
      app/src/main/assets/themes/Default/icons/password-lock.svg
  41. 23 0
      app/src/main/assets/themes/Default/icons/power.svg
  42. 2 0
      app/src/main/assets/themes/Default/icons/rfid.svg
  43. 4 0
      app/src/main/assets/themes/Default/icons/robotic-arm.svg
  44. 2 0
      app/src/main/assets/themes/Default/icons/rotate-left.svg
  45. 4 0
      app/src/main/assets/themes/Default/icons/selection.svg
  46. 2 0
      app/src/main/assets/themes/Default/icons/shield-check.svg
  47. 33 0
      app/src/main/assets/themes/Default/icons/slot.svg
  48. 80 0
      app/src/main/assets/themes/Default/icons/sop.svg
  49. 1 0
      app/src/main/assets/themes/Default/icons/target.svg
  50. 4 0
      app/src/main/assets/themes/Default/icons/to-do.svg
  51. 22 0
      app/src/main/assets/themes/Default/icons/unlock.svg
  52. 23 0
      app/src/main/assets/themes/Default/icons/user.svg
  53. 2 0
      app/src/main/assets/themes/Default/icons/users-alt.svg
  54. 2 0
      app/src/main/assets/themes/Default/icons/wind.svg
  55. 4 0
      app/src/main/assets/themes/Default/icons/workflow-alt.svg
  56. 0 44
      app/src/main/java/com/grkj/iscs_mc/FirstFragment.kt
  57. 149 0
      app/src/main/java/com/grkj/iscs_mc/ISCSMCApplication.kt
  58. 0 59
      app/src/main/java/com/grkj/iscs_mc/MainActivity.kt
  59. 0 44
      app/src/main/java/com/grkj/iscs_mc/SecondFragment.kt
  60. 58 0
      app/src/main/java/com/grkj/iscs_mc/features/login/activity/LoginActivity.kt
  61. 13 0
      app/src/main/java/com/grkj/iscs_mc/features/login/adapter/TwoFragmentAdapter.kt
  62. 56 0
      app/src/main/java/com/grkj/iscs_mc/features/login/dialog/ChangeLangDialog.kt
  63. 194 0
      app/src/main/java/com/grkj/iscs_mc/features/login/dialog/LoginDialog.kt
  64. 13 0
      app/src/main/java/com/grkj/iscs_mc/features/login/entity/LoginMenuEntity.kt
  65. 366 0
      app/src/main/java/com/grkj/iscs_mc/features/login/fragment/LoginFragment.kt
  66. 20 0
      app/src/main/java/com/grkj/iscs_mc/features/login/fragment/MaterialShowFragment.kt
  67. 110 0
      app/src/main/java/com/grkj/iscs_mc/features/login/viewmodel/LoginViewModel.kt
  68. 20 0
      app/src/main/java/com/grkj/iscs_mc/features/manage/activity/ManageActivity.kt
  69. 20 0
      app/src/main/java/com/grkj/iscs_mc/features/material_exchange/activity/MaterialExchangeActivity.kt
  70. 69 0
      app/src/main/java/com/grkj/iscs_mc/features/splash/activity/SplashActivity.kt
  71. 42 0
      app/src/main/java/com/grkj/iscs_mc/receivers/BootReceiver.kt
  72. BIN
      app/src/main/jniLibs/arm64-v8a/libarcsoft_face.so
  73. BIN
      app/src/main/jniLibs/arm64-v8a/libarcsoft_face_engine.so
  74. BIN
      app/src/main/jniLibs/arm64-v8a/libarcsoft_image_util.so
  75. BIN
      app/src/main/jniLibs/arm64-v8a/libslkidcap.so
  76. BIN
      app/src/main/jniLibs/arm64-v8a/libzkalg12.so
  77. BIN
      app/src/main/jniLibs/arm64-v8a/libzkfinger10.so
  78. BIN
      app/src/main/jniLibs/arm64-v8a/libzksensorcore.so
  79. BIN
      app/src/main/jniLibs/armeabi-v7a/libarcsoft_face.so
  80. BIN
      app/src/main/jniLibs/armeabi-v7a/libarcsoft_face_engine.so
  81. BIN
      app/src/main/jniLibs/armeabi-v7a/libarcsoft_image_util.so
  82. BIN
      app/src/main/jniLibs/armeabi-v7a/libserial_port.so
  83. BIN
      app/src/main/jniLibs/armeabi-v7a/libslkidcap.so
  84. BIN
      app/src/main/jniLibs/armeabi-v7a/libzkalg12.so
  85. BIN
      app/src/main/jniLibs/armeabi-v7a/libzkfinger10.so
  86. BIN
      app/src/main/jniLibs/armeabi-v7a/libzksensorcore.so
  87. 5 0
      app/src/main/res/drawable/bg_card_color_container_bg_radius_md.xml
  88. 5 0
      app/src/main/res/drawable/bg_card_login_header_bg_radius_md.xml
  89. 8 0
      app/src/main/res/drawable/login_tip_circle.xml
  90. 46 0
      app/src/main/res/layout-land/activity_login.xml
  91. 133 0
      app/src/main/res/layout-land/fragment_login.xml
  92. 39 0
      app/src/main/res/layout-land/item_login_method.xml
  93. 46 0
      app/src/main/res/layout/activity_login.xml
  94. 0 33
      app/src/main/res/layout/activity_main.xml
  95. 8 0
      app/src/main/res/layout/activity_manage.xml
  96. 9 0
      app/src/main/res/layout/activity_material_exchange.xml
  97. 57 0
      app/src/main/res/layout/activity_splash.xml
  98. 0 19
      app/src/main/res/layout/content_main.xml
  99. 30 0
      app/src/main/res/layout/dialog_change_lang.xml
  100. 92 0
      app/src/main/res/layout/dialog_login.xml

+ 37 - 2
app/build.gradle.kts

@@ -1,6 +1,9 @@
 plugins {
     alias(libs.plugins.android.application)
     alias(libs.plugins.kotlin.android)
+    id("org.jetbrains.kotlin.kapt")
+    id("com.google.devtools.ksp")
+    id("com.google.dagger.hilt.android")
 }
 
 android {
@@ -12,11 +15,19 @@ android {
         minSdk = 24
         targetSdk = 36
         versionCode = 1
-        versionName = "1.0"
+        versionName = "v1.0.0"
 
         testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
     }
 
+    signingConfigs {
+        create("release") {
+            storeFile = file("../ISCS.jks")
+            storePassword = "iscs123456"
+            keyAlias = "iscs"
+            keyPassword = "iscs123456"
+        }
+    }
     buildTypes {
         release {
             isMinifyEnabled = false
@@ -34,7 +45,15 @@ android {
         jvmTarget = "11"
     }
     buildFeatures {
-        viewBinding = true
+        dataBinding = true
+        buildConfig = true
+    }
+    packaging {
+        resources {
+            pickFirsts += "META-INF/versions/9/OSGI-INF/MANIFEST.MF"
+            pickFirsts += "META-INF/INDEX.LIST"
+            pickFirsts += "META-INF/io.netty.versions.properties"
+        }
     }
 }
 
@@ -43,10 +62,26 @@ dependencies {
     implementation(libs.androidx.core.ktx)
     implementation(libs.androidx.appcompat)
     implementation(libs.material)
+    implementation(libs.androidx.activity)
     implementation(libs.androidx.constraintlayout)
+    implementation(libs.brv)
+    implementation(libs.viewmodel.ktx)
+    implementation(libs.viewmodel.livedata.ktx)
+    implementation(libs.viewmodel.savestate)
+    kapt(libs.viewmodel.compiler)
     implementation(libs.androidx.navigation.fragment)
     implementation(libs.androidx.navigation.ui)
+    implementation(libs.androidx.navigation.dynamic.features.fragment)
+    implementation(libs.kotlinx.serialization.json)
+    implementation(libs.sik.camera)
+    implementation("com.google.dagger:hilt-android:2.56.2")
+    ksp("com.google.dagger:hilt-android-compiler:2.56.2")
+    implementation(project(":data"))
+    implementation(project(":shared"))
+    implementation(project(":ui-base"))
     testImplementation(libs.junit)
     androidTestImplementation(libs.androidx.junit)
     androidTestImplementation(libs.androidx.espresso.core)
+
+
 }

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

@@ -2,25 +2,70 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:tools="http://schemas.android.com/tools">
 
+    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
+    <uses-permission android:name="android.permission.INTERNET" />
+    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
+
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
+    <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
+    <uses-permission android:name="android.permission.CAMERA" />
+
+    <uses-feature android:name="android.hardware.camera" />
+    <!--    开机自启动-->
+    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
+
     <application
+        android:name=".ISCSMCApplication"
         android:allowBackup="true"
         android:dataExtractionRules="@xml/data_extraction_rules"
         android:fullBackupContent="@xml/backup_rules"
         android:icon="@mipmap/ic_launcher"
-        android:label="@string/app_name"
-        android:roundIcon="@mipmap/ic_launcher_round"
+        android:label="ISCS_MC"
+        android:requestLegacyExternalStorage="true"
         android:supportsRtl="true"
-        android:theme="@style/Theme.ISCS_BASE_MC_APP">
+        android:theme="@style/Theme.ISCS_BASE_MC_APP"
+        tools:replace="android:label"
+        tools:targetApi="31">
         <activity
-            android:name=".MainActivity"
+            android:name=".features.splash.activity.SplashActivity"
+            android:configChanges="orientation|screenSize|keyboardHidden"
             android:exported="true"
-            android:theme="@style/Theme.ISCS_BASE_MC_APP">
+            android:windowSoftInputMode="stateHidden|adjustPan">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
 
                 <category android:name="android.intent.category.LAUNCHER" />
             </intent-filter>
         </activity>
+        <activity
+            android:name=".features.login.activity.LoginActivity"
+            android:configChanges="orientation|screenSize|keyboardHidden"
+            android:exported="true"
+            android:windowSoftInputMode="stateHidden|adjustPan" />
+
+        <activity
+            android:name=".features.manage.activity.ManageActivity"
+            android:configChanges="orientation|screenSize|keyboardHidden"
+            android:exported="true"
+            android:windowSoftInputMode="stateHidden|adjustPan" />
+
+        <receiver
+            android:name=".receivers.BootReceiver"
+            android:enabled="true"
+            android:exported="true">
+            <intent-filter android:priority="1000">
+                <action android:name="android.intent.action.BOOT_COMPLETED" />
+                <action android:name="android.media.AUDIO_BECOMEING_NOISY" />
+            </intent-filter>
+        </receiver>
+
+        <meta-data
+            android:name="design_width_in_dp"
+            android:value="600" />
+        <meta-data
+            android:name="design_height_in_dp"
+            android:value="1024" />
     </application>
 
 </manifest>

+ 137 - 0
app/src/main/assets/i18n/zh-CN.json

@@ -0,0 +1,137 @@
+{
+  "i18n.language_name": {
+    "key": "i18n.language_name",
+    "type": "text",
+    "value": "中文"
+  },
+  "tec_support": {
+    "key": "tec_support",
+    "type": "text",
+    "value": "温州博士安全用品有限公司"
+  },
+  "mc": {
+    "key": "mc",
+    "type": "text",
+    "value": "智能物资管理柜"
+  },
+  "mc_en": {
+    "key": "mc_en",
+    "type": "text",
+    "value": "Intelligent Materials Management Cabinet"
+  },
+  "administrator_mode": {
+    "key": "administrator_mode",
+    "type": "text",
+    "value": "管理员模式"
+  },
+  "login": {
+    "key": "login",
+    "type": "text",
+    "value": "登录"
+  },
+  "login_tip": {
+    "key": "login_tip",
+    "type": "text",
+    "value": "请输入用户名和密码或者刷卡进行登录"
+  },
+  "cancel": {
+    "key": "cancel",
+    "type": "text",
+    "value": "取消"
+  },
+  "administrator": {
+    "key": "administrator",
+    "type": "text",
+    "value": "管理员"
+  },
+  "face_can_not_process": {
+    "key": "face_can_not_process",
+    "type": "text",
+    "value": "人脸引擎激活失败,识别暂不可用"
+  },
+  "face_detected_do_login": {
+    "key": "face_detected_do_login",
+    "type": "text",
+    "value": "检测到人脸,正在登录······"
+  },
+  "face_login": {
+    "key": "face_login",
+    "type": "text",
+    "value": "人脸登录"
+  },
+  "face_login_failed": {
+    "key": "face_login_failed",
+    "type": "text",
+    "value": "人脸匹配失败,请重试"
+  },
+  "face_login_success": {
+    "key": "face_login_success",
+    "type": "text",
+    "value": "人脸验证通过"
+  },
+  "face_not_set_tip": {
+    "key": "face_not_set_tip",
+    "type": "text",
+    "value": "您尚未设置人脸数据"
+  },
+  "face_set_tip": {
+    "key": "face_set_tip",
+    "type": "text",
+    "value": "您已设置了人脸数据"
+  },
+  "fingerprint_add_success_tip": {
+    "key": "fingerprint_add_success_tip",
+    "type": "text",
+    "value": "已成功添加指纹数据"
+  },
+  "fingerprint_code": {
+    "key": "fingerprint_code",
+    "type": "text",
+    "value": "指纹编号"
+  },
+  "fingerprint_code_str": {
+    "key": "fingerprint_code_str",
+    "type": "text",
+    "value": "指纹_{0}"
+  },
+  "fingerprint_delete_confirm_tip": {
+    "key": "fingerprint_delete_confirm_tip",
+    "type": "text",
+    "value": "确定要删除{0}吗?"
+  },
+  "fingerprint_delete_selected_confirm_tip": {
+    "key": "fingerprint_delete_selected_confirm_tip",
+    "type": "text",
+    "value": "确定要删除选中的指纹吗?"
+  },
+  "fingerprint_login": {
+    "key": "fingerprint_login",
+    "type": "text",
+    "value": "指纹登录"
+  },
+  "fingerprint_login_failed": {
+    "key": "fingerprint_login_failed",
+    "type": "text",
+    "value": "指纹识别失败,请重试"
+  },
+  "fingerprint_login_success": {
+    "key": "fingerprint_login_success",
+    "type": "text",
+    "value": "指纹验证通过"
+  },
+  "fingerprint_scan_tip": {
+    "key": "fingerprint_scan_tip",
+    "type": "text",
+    "value": "请连续按压{0}次指纹识别区"
+  },
+  "account_login": {
+    "key": "account_login",
+    "type": "text",
+    "value": "用户名登录"
+  },
+  "card_login": {
+    "key": "card_login",
+    "type": "text",
+    "value": "刷卡登录"
+  }
+}

+ 47 - 0
app/src/main/assets/logback.xml

@@ -0,0 +1,47 @@
+<configuration
+    xmlns="https://tony19.github.io/logback-android/xml"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="https://tony19.github.io/logback-android/xml https://cdn.jsdelivr.net/gh/tony19/logback-android/logback.xsd">
+    <property name="LOG_DIR" value="${EXTERNAL_STORAGE}/iscs_mc/logs"/>
+    <contextListener class="ch.qos.logback.classic.joran.JoranConfigurator">
+        <onStart>
+            <mkdir dir="${LOG_DIR}" />
+        </onStart>
+    </contextListener>
+    <!-- 文件日志输出,生成每日滚动日志 -->
+    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <!-- 日志文件路径,在 Android 中存储在应用的 filesDir/logs 目录 -->
+        <file>${LOG_DIR}/app.log</file>
+
+        <!-- 每日滚动日志策略 -->
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <fileNamePattern>${LOG_DIR}/app.%d{yyyy-MM-dd}.log</fileNamePattern>
+            <maxHistory>7</maxHistory>  <!-- 最大保留 7 天日志 -->
+            <totalSizeCap>100MB</totalSizeCap>  <!-- 总日志大小限制 -->
+        </rollingPolicy>
+
+        <encoder>
+            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{~36} - %msg%n</pattern>
+        </encoder>
+    </appender>
+
+    <!-- Logcat 输出,适用于 Android Studio 的调试 -->
+    <appender name="LOGCAT" class="ch.qos.logback.classic.android.LogcatAppender">
+        <encoder>
+            <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{~36}.%M:%line - %msg%n</pattern>
+        </encoder>
+    </appender>
+
+    <!-- 日志级别配置 -->
+    <logger name="${PACKAGE_NAME}" level="DEBUG" additivity="false">
+        <appender-ref ref="FILE" />
+        <appender-ref ref="LOGCAT" />
+    </logger>
+
+    <!-- 根日志器,默认级别为 INFO -->
+    <root level="DEBUG">
+        <appender-ref ref="FILE" />
+        <appender-ref ref="LOGCAT" />
+    </root>
+
+</configuration>

+ 1 - 0
app/src/main/assets/themes/Default/icons/access-control.svg

@@ -0,0 +1 @@
+<svg id="Layer_1" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" data-name="Layer 1"><path d="m18 10c.352 0 .696.031 1.036.075-.521-.714-1.218-1.292-2.036-1.651v-1.424c0-3.86-3.141-7-7-7s-7 3.14-7 7v1.424c-1.763.774-3 2.531-3 4.576v6c0 2.757 2.243 5 5 5h7.721c-1.665-1.466-2.721-3.607-2.721-6-.553 0-1-.448-1-1v-2c0-.552.447-1 1-1 .354 0 .65.195.828.472 1.305-2.647 4.022-4.472 7.172-4.472zm-13-2v-1c0-2.757 2.243-5 5-5s5 2.243 5 5v1zm13 4c-3.309 0-6 2.691-6 6s2.691 6 6 6 6-2.691 6-6-2.691-6-6-6zm0 2c1.105 0 2 .895 2 2s-.895 2-2 2-2-.895-2-2 .895-2 2-2zm0 8c-1.08 0-2.057-.434-2.778-1.132.445-1.095 1.515-1.868 2.769-1.868h.016c1.253 0 2.323.775 2.768 1.87-.72.697-1.697 1.13-2.776 1.13z"/></svg>

+ 4 - 0
app/src/main/assets/themes/Default/icons/arrow-down-strenght.svg

@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" id="Layer_1" data-name="Layer 1" viewBox="0 0 24 24">
+  <path d="M24,23c0,.553-.448,1-1,1H1c-.552,0-1-.447-1-1s.448-1,1-1H23c.552,0,1,.447,1,1ZM.623,17.959c3.51,1.429,7.323,2.153,11.333,2.154h.001s.003,0,.004,0h.001c4.074,0,7.916-.737,11.42-2.189,.51-.212,.752-.797,.541-1.307s-.796-.753-1.307-.541c-3.261,1.352-6.847,2.037-10.658,2.037-3.751,0-7.312-.675-10.582-2.006-.513-.211-1.095,.037-1.303,.549s.038,1.095,.549,1.303Zm10.061-7.005c.364,.364,.841,.545,1.319,.545s.955-.182,1.319-.545l2.888-2.888c.391-.391,.391-1.023,0-1.414s-1.023-.391-1.414,0l-1.794,1.794-.002-7.445c0-.552-.448-1-1-1s-1,.448-1,1l.002,7.443-1.792-1.792c-.391-.391-1.023-.391-1.414,0s-.391,1.023,0,1.414l2.888,2.888Zm1.31,5.046h.002s.002,0,.004,0h.002c6.014-.003,10.201-3.714,11.722-5.31,.381-.4,.366-1.033-.034-1.414-.398-.381-1.032-.366-1.414,.034-1.344,1.41-5.036,4.689-10.278,4.69-5.227,0-8.927-3.281-10.275-4.691-.382-.399-1.015-.414-1.414-.032-.399,.381-.414,1.015-.032,1.414,1.525,1.596,5.72,5.306,11.716,5.309Z"/>
+</svg>

+ 4 - 0
app/src/main/assets/themes/Default/icons/arrow-progress-alt.svg

@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" id="Layer_1" data-name="Layer 1" viewBox="0 0 24 24">
+  <path d="m0,8c0-2.206,1.794-4,4-4h16.955l-1.34-1.272c-.402-.378-.421-1.011-.042-1.414.379-.403,1.011-.421,1.414-.042l2.404,2.263c.396.394.611.92.611,1.465s-.215,1.072-.591,1.446l-2.424,2.282c-.193.182-.439.272-.686.272-.266,0-.531-.105-.728-.314-.379-.402-.359-1.035.042-1.414l1.351-1.272H4c-1.103,0-2,.897-2,2s.897,2,2,2h14.171c1.692,0,3.208,1.072,3.772,2.667.184.521-.089,1.092-.61,1.276-.11.039-.223.058-.333.058-.412,0-.798-.257-.943-.667-.282-.797-1.04-1.333-1.886-1.333H4c-2.206,0-4-1.794-4-4Zm12.985,7.272c-.403-.379-1.034-.36-1.414.042-.379.402-.359,1.035.042,1.414l1.34,1.272h-3.955c-.552,0-1,.448-1,1s.448,1,1,1h3.966l-1.351,1.272c-.402.378-.421,1.011-.042,1.414.197.209.462.314.728.314.246,0,.492-.09.686-.272l2.424-2.282c.375-.374.591-.901.591-1.446s-.215-1.072-.611-1.465l-2.404-2.263Zm-8.985.728h-2c-1.103,0-2,.897-2,2v2c0,1.103.897,2,2,2h2c1.103,0,2-.897,2-2v-2c0-1.103-.897-2-2-2Zm18,0h-2c-1.103,0-2,.897-2,2v2c0,1.103.897,2,2,2h2c1.103,0,2-.897,2-2v-2c0-1.103-.897-2-2-2Z"/>
+</svg>

+ 4 - 0
app/src/main/assets/themes/Default/icons/back-up.svg

@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" id="Layer_1" data-name="Layer 1" viewBox="0 0 24 24">
+  <path d="m8.5,16c3.58,0,6.624-.839,8.5-2.173v1.74c0,1.621-3.635,3.434-8.5,3.434S0,17.188,0,15.566v-1.74c1.876,1.334,4.92,2.174,8.5,2.174ZM0,18.826v.96c0,2.767,4.276,4.214,8.5,4.214s8.5-1.447,8.5-4.214v-.96c-1.876,1.334-4.92,2.174-8.5,2.174s-6.624-.839-8.5-2.174ZM22,0v1.534c-1.078-.97-2.482-1.534-4-1.534-2.967,0-5.431,2.167-5.91,5h2.052c.447-1.72,1.999-3,3.858-3,1,0,1.928.367,2.644,1h-1.644v2h5V0h-2Zm-4,10c-.994,0-1.929-.368-2.646-1h1.646v-2h-5v5h2v-1.531c1.08.966,2.494,1.531,4,1.531,2.967,0,5.431-2.167,5.91-5h-2.052c-.447,1.72-1.999,3-3.858,3Zm-9.5-1c.513,0,1.012-.028,1.5-.074v-2.926c0-2.151.854-4.1,2.235-5.538-1.128-.293-2.393-.462-3.735-.462C3.806,0,0,2.015,0,4.5s3.806,4.5,8.5,4.5Zm0,5c.516,0,1.015-.024,1.5-.063v-3.003c-.489.04-.987.066-1.5.066-3.58,0-6.624-1.004-8.5-2.6v2.167c0,1.621,3.635,3.433,8.5,3.433Z"/>
+</svg>

+ 2 - 0
app/src/main/assets/themes/Default/icons/ballot-check.svg

@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" id="Layer_1" data-name="Layer 1" viewBox="0 0 24 24" width="512" height="512"><path d="m17,0H7C4.243,0,2,2.243,2,5v14c0,2.757,2.243,5,5,5h10c2.757,0,5-2.243,5-5V5c0-2.757-2.243-5-5-5ZM7.5,4.5c.828,0,1.5.672,1.5,1.5s-.672,1.5-1.5,1.5-1.5-.672-1.5-1.5.672-1.5,1.5-1.5Zm0,15c-.828,0-1.5-.672-1.5-1.5s.672-1.5,1.5-1.5,1.5.672,1.5,1.5-.672,1.5-1.5,1.5Zm1.365-5.979c-.319.319-.741.479-1.165.479-.427,0-.855-.162-1.182-.487l-.681-.655c-.398-.382-.411-1.016-.028-1.414.383-.399,1.017-.41,1.414-.028l.472.454,1.866-1.815c.396-.385,1.029-.377,1.414.02.385.396.376,1.029-.02,1.414l-2.091,2.034Zm8.135,5.479h-5c-.552,0-1-.448-1-1s.448-1,1-1h5c.552,0,1,.448,1,1s-.448,1-1,1Zm0-6h-3c-.552,0-1-.448-1-1s.448-1,1-1h3c.552,0,1,.448,1,1s-.448,1-1,1Zm0-6h-5c-.552,0-1-.448-1-1s.448-1,1-1h5c.552,0,1,.448,1,1s-.448,1-1,1Z"/></svg>

+ 2 - 0
app/src/main/assets/themes/Default/icons/ballot.svg

@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" id="Layer_1" data-name="Layer 1" viewBox="0 0 24 24" width="512" height="512"><path d="M17,0H7C4.243,0,2,2.243,2,5v14c0,2.757,2.243,5,5,5h10c2.757,0,5-2.243,5-5V5c0-2.757-2.243-5-5-5Zm-7,19c0,.552-.448,1-1,1h-2c-.552,0-1-.448-1-1v-2c0-.552,.448-1,1-1h2c.552,0,1,.448,1,1v2Zm0-6c0,.552-.448,1-1,1h-2c-.552,0-1-.448-1-1v-2c0-.552,.448-1,1-1h2c.552,0,1,.448,1,1v2Zm0-6c0,.552-.448,1-1,1h-2c-.552,0-1-.448-1-1v-2c0-.552,.448-1,1-1h2c.552,0,1,.448,1,1v2Zm7,12h-4c-1.308-.006-1.307-1.994,0-2h4c1.308,.006,1.307,1.994,0,2Zm0-6h-4c-1.308-.006-1.307-1.994,0-2h4c1.308,.006,1.307,1.994,0,2Zm0-6h-4c-1.308-.006-1.307-1.994,0-2h4c1.308,.006,1.307,1.994,0,2Z"/></svg>

+ 4 - 0
app/src/main/assets/themes/Default/icons/bolt-slash.svg

@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" id="Layer_1" data-name="Layer 1" viewBox="0 0 24 24">
+  <path d="m23.707,22.293l-6.317-6.317,2.105-3.43c.606-.894.668-2.041.163-2.995-.506-.954-1.491-1.547-2.569-1.547l-3.833-.003,1.205-5.227c.309-1.078-.139-2.172-1.064-2.6-.88-.407-1.865-.086-2.473.826l-3.236,5.273L1.707.293C1.316-.098.684-.098.293.293S-.098,1.316.293,1.707l22,22c.195.195.451.293.707.293s.512-.098.707-.293c.391-.391.391-1.023,0-1.414Zm-8.471-2.815l-2.164,3.524c-.432.65-1.057,1-1.699,1-.259,0-.521-.057-.773-.174-.925-.428-1.373-1.521-1.064-2.6l1.204-5.226h-3.83c-1.08,0-2.064-.593-2.57-1.547-.506-.954-.443-2.103.163-2.996l1.033-1.683,9.701,9.701Z"/>
+</svg>

+ 2 - 0
app/src/main/assets/themes/Default/icons/bolt.svg

@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" id="Layer_1" data-name="Layer 1" viewBox="0 0 24 24" width="512" height="512"><path d="M11.24,24a2.262,2.262,0,0,1-.948-.212,2.18,2.18,0,0,1-1.2-2.622L10.653,16H6.975A3,3,0,0,1,4.1,12.131l3.024-10A2.983,2.983,0,0,1,10,0h3.693a2.6,2.6,0,0,1,2.433,3.511L14.443,8H17a3,3,0,0,1,2.483,4.684l-6.4,10.3A2.2,2.2,0,0,1,11.24,24Z"/></svg>

BIN
app/src/main/assets/themes/Default/icons/cards-blank.png


+ 2 - 0
app/src/main/assets/themes/Default/icons/chalkboard-user.svg

@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" id="Layer_1" data-name="Layer 1" viewBox="0 0 24 24" width="512" height="512"><path d="m14,19v5H0v-5c0-1.654,1.346-3,3-3h8c1.654,0,3,1.346,3,3Zm-7-5c2.206,0,4-1.794,4-4s-1.794-4-4-4-4,1.794-4,4,1.794,4,4,4ZM24,3v15h-8.101c-.436-2.139-2.249-3.763-4.466-3.956.974-1.067,1.567-2.486,1.567-4.044,0-3.314-2.686-6-6-6-.701,0-1.374.121-2,.342v-1.342c0-1.654,1.346-3,3-3h13c1.654,0,3,1.346,3,3Zm-2,11h-5v2h5v-2Z"/></svg>

+ 22 - 0
app/src/main/assets/themes/Default/icons/checkbox.svg

@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generator: Adobe Illustrator 25.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" id="Capa_1" x="0px" y="0px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve" width="512" height="512">
+<g>
+	<path d="M405.333,0H106.667C47.786,0.071,0.071,47.786,0,106.667v298.667C0.071,464.214,47.786,511.93,106.667,512h298.667   C464.214,511.93,511.93,464.214,512,405.333V106.667C511.93,47.786,464.214,0.071,405.333,0z M426.667,172.352L229.248,369.771   c-16.659,16.666-43.674,16.671-60.34,0.012c-0.004-0.004-0.008-0.008-0.012-0.012l-83.563-83.541   c-8.348-8.348-8.348-21.882,0-30.229s21.882-8.348,30.229,0l83.541,83.541l197.44-197.419c8.348-8.318,21.858-8.294,30.176,0.053   C435.038,150.524,435.014,164.034,426.667,172.352z"/>
+</g>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+</svg>

+ 4 - 0
app/src/main/assets/themes/Default/icons/choose.svg

@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" id="Layer_1" data-name="Layer 1" viewBox="0 0 24 24">
+  <path d="m5.5,8h-3c-1.381,0-2.5-1.119-2.5-2.5v-3C0,1.119,1.119,0,2.5,0h3c1.381,0,2.5,1.119,2.5,2.5v3c0,1.381-1.119,2.5-2.5,2.5Zm0,10h-3c-1.381,0-2.5-1.119-2.5-2.5v-3c0-1.381,1.119-2.5,2.5-2.5h3c1.381,0,2.5,1.119,2.5,2.5v3c0,1.381-1.119,2.5-2.5,2.5ZM15.5,0h-3c-1.381,0-2.5,1.119-2.5,2.5v3c0,1.381,1.119,2.5,2.5,2.5h3c1.381,0,2.5-1.119,2.5-2.5v-3c0-1.381-1.119-2.5-2.5-2.5Zm-.5,4.5c0,.276-.224.5-.5.5h-1c-.276,0-.5-.224-.5-.5v-1c0-.276.224-.5.5-.5h1c.276,0,.5.224.5.5v1Zm0,7.607c0-.996-.681-1.92-1.664-2.08-1.253-.204-2.336.758-2.336,1.973v8.817c-1.076-.886-2.111-1.752-2.145-1.784-.922-.861-2.373-.813-3.235.109-.863.923-.819,2.372.098,3.23l1.821,1.628h16.462v-.593c0-2.055-1.258-3.901-3.171-4.653l-5.829-2.292v-4.355Z"/>
+</svg>

+ 1 - 0
app/src/main/assets/themes/Default/icons/document.svg

@@ -0,0 +1 @@
+<svg id="Layer_1" height="512" viewBox="0 0 24 24" width="512" xmlns="http://www.w3.org/2000/svg" data-name="Layer 1"><path d="m14 7v-6.54a6.977 6.977 0 0 1 2.465 1.59l3.484 3.486a6.954 6.954 0 0 1 1.591 2.464h-6.54a1 1 0 0 1 -1-1zm8 3.485v8.515a5.006 5.006 0 0 1 -5 5h-10a5.006 5.006 0 0 1 -5-5v-14a5.006 5.006 0 0 1 5-5h4.515c.163 0 .324.013.485.024v6.976a3 3 0 0 0 3 3h6.976c.011.161.024.322.024.485zm-8 8.515a1 1 0 0 0 -1-1h-5a1 1 0 0 0 0 2h5a1 1 0 0 0 1-1zm3-4a1 1 0 0 0 -1-1h-8a1 1 0 0 0 0 2h8a1 1 0 0 0 1-1z"/></svg>

BIN
app/src/main/assets/themes/Default/icons/external-world.png


+ 11 - 0
app/src/main/assets/themes/Default/icons/face-id-svgrepo-com.svg

@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
+<svg width="800px" height="800px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M7 3H5C3.89543 3 3 3.89543 3 5V7" stroke="#000000" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
+<path d="M17 3H19C20.1046 3 21 3.89543 21 5V7" stroke="#000000" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
+<path d="M16 8L16 10" stroke="#000000" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
+<path d="M8 8L8 10" stroke="#000000" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
+<path d="M9 16C9 16 10 17 12 17C14 17 15 16 15 16" stroke="#000000" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
+<path d="M12 8L12 13L11 13" stroke="#000000" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
+<path d="M7 21H5C3.89543 21 3 20.1046 3 19V17" stroke="#000000" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
+<path d="M17 21H19C20.1046 21 21 20.1046 21 19V17" stroke="#000000" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
+</svg>

+ 2 - 0
app/src/main/assets/themes/Default/icons/file-export.svg

@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" id="Layer_1" data-name="Layer 1" viewBox="0 0 24 24" width="512" height="512"><path d="M23.13,18.09l-1.61,1.61c-.2,.2-.45,.29-.71,.29s-.51-.1-.71-.29c-.39-.39-.39-1.02,0-1.41l1.29-1.29h-7.4c-.55,0-1-.45-1-1s.45-1,1-1h7.4l-1.29-1.29c-.39-.39-.39-1.02,0-1.41s1.02-.39,1.41,0l1.61,1.61c1.15,1.15,1.15,3.03,0,4.19ZM13,8h6.54c-.35-.91-.88-1.75-1.59-2.46l-3.48-3.49c-.71-.71-1.55-1.24-2.46-1.59V7c0,.55,.45,1,1,1Zm4.81,11h-3.81c-1.65,0-3-1.35-3-3s1.35-3,3-3h3.81c0-.77,.29-1.54,.88-2.12,.37-.37,.82-.63,1.29-.76v-.12h-6.98c-1.65,0-3-1.35-3-3V.02c-.16-.01-.32-.02-.49-.02H5C2.24,0,0,2.24,0,5v14c0,2.76,2.24,5,5,5H15c1.81,0,3.4-.97,4.28-2.42-.21-.13-.41-.28-.59-.46-.58-.58-.88-1.35-.88-2.12Z"/></svg>

+ 2 - 0
app/src/main/assets/themes/Default/icons/fingerprint.svg

@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" id="Layer_1" data-name="Layer 1" viewBox="0 0 24 24" width="512" height="512"><path d="M5.972,22.285a1,1,0,0,1-.515-1.857C9,18.3,9,13.73,9,11a3,3,0,0,1,6,0,1,1,0,0,1-2,0,1,1,0,0,0-2,0c0,2.947,0,8.434-4.514,11.143A1,1,0,0,1,5.972,22.285Zm4.963,1.421c2.282-2.3,3.615-5.534,3.961-9.621A1,1,0,0,0,13.985,13a.983.983,0,0,0-1.081.911c-.311,3.657-1.419,6.4-3.388,8.381a1,1,0,0,0,1.419,1.41Zm5.2-.186a17.793,17.793,0,0,0,1.508-3.181,1,1,0,0,0-1.881-.678,15.854,15.854,0,0,1-1.338,2.821,1,1,0,0,0,1.711,1.038ZM18.5,17.191A31.459,31.459,0,0,0,19,11,7,7,0,0,0,6.787,6.333,1,1,0,1,0,8.276,7.667,5,5,0,0,1,17,11a29.686,29.686,0,0,1-.462,5.809,1,1,0,0,0,.79,1.172.979.979,0,0,0,.193.019A1,1,0,0,0,18.5,17.191ZM7,11a5,5,0,0,1,.069-.833A1,1,0,1,0,5.1,9.833,6.971,6.971,0,0,0,5,11c0,4.645-1.346,7-4,7a1,1,0,0,0,0,2C4.869,20,7,16.8,7,11ZM20.7,23.414A29.76,29.76,0,0,0,23,11a10.865,10.865,0,0,0-1.1-4.794,1,1,0,1,0-1.8.875A8.9,8.9,0,0,1,21,11a27.91,27.91,0,0,1-2.119,11.586,1,1,0,0,0,.5,1.324.984.984,0,0,0,.413.09A1,1,0,0,0,20.7,23.414ZM3,14V11a9.01,9.01,0,0,1,9-9,8.911,8.911,0,0,1,5.4,1.8,1,1,0,0,0,1.2-1.6A10.9,10.9,0,0,0,12,0,11.013,11.013,0,0,0,1,11v3a1,1,0,0,0,2,0Z"/></svg>

+ 2 - 0
app/src/main/assets/themes/Default/icons/fire-flame-curved.svg

@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" id="Layer_1" data-name="Layer 1" viewBox="0 0 24 24" width="512" height="512"><path d="M12,24h-.057c-5.482,0-9.943-4.486-9.943-10,0-1.929,.666-4.07,1.874-6.031,.471-.765,1.373-1.126,2.241-.896,.869,.229,1.474,.987,1.505,1.885,.096,2.74,.753,6.014,3.338,6.043,1.081,.009,1.937-.747,2.027-1.727,.094-1.026-.277-1.83-.746-2.847-.552-1.2-1.24-2.692-1.24-4.901,0-1.707,.345-3.412,.687-4.345C11.941,.488,12.542,.033,13.256-.008c.739-.04,1.414,.367,1.753,1.042,.802,1.595,1.938,3.069,3.036,4.495,1.972,2.562,4.011,5.211,3.956,8.487,0,5.464-4.483,9.95-9.994,9.983h-.006Z"/></svg>

+ 2 - 0
app/src/main/assets/themes/Default/icons/gas-pump.svg

@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" id="Layer_1" data-name="Layer 1" viewBox="0 0 24 24" width="512" height="512"><path d="M6,9h4A2,2,0,0,0,6,9Z"/><path d="M8,5a3.971,3.971,0,0,1,1.339.247l1.954-1.954a1,1,0,1,1,1.414,1.414L11.014,6.4A3.963,3.963,0,0,1,12,9h4V5a5.006,5.006,0,0,0-5-5H5A5.006,5.006,0,0,0,0,5V9H4A4,4,0,0,1,8,5Z"/><path d="M23.681,3.267a1,1,0,0,0-1.414,0L19.293,6.24A1,1,0,0,0,19,6.947V18a1,1,0,0,1-1,1H16V11H0v8a5.006,5.006,0,0,0,5,5h6a5,5,0,0,0,4.576-3H18a3,3,0,0,0,3-3V7.361l2.681-2.68A1,1,0,0,0,23.681,3.267Z"/></svg>

+ 2 - 0
app/src/main/assets/themes/Default/icons/heat.svg

@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" id="Layer_1" data-name="Layer 1" viewBox="0 0 24 24" width="512" height="512"><path d="M20.016,24a1,1,0,0,1-.964-1.269c.116-.419.247-.808.377-1.191,1.285-2.684.18-6.683-1.256-8.554A12.313,12.313,0,0,1,17.359.576a1,1,0,0,1,1.811.848,10.307,10.307,0,0,0,.686,10.483c1.675,2.137,2.986,7.113,1.467,10.271-.118.351-.238.708-.345,1.091A1,1,0,0,1,20.016,24Zm-7,0a1,1,0,0,1-.964-1.269c.116-.419.247-.808.377-1.191,1.285-2.684.18-6.683-1.256-8.554A12.313,12.313,0,0,1,10.359.576a1,1,0,0,1,1.811.848,10.307,10.307,0,0,0,.686,10.483c1.675,2.137,2.986,7.113,1.467,10.271-.118.351-.238.708-.345,1.091A1,1,0,0,1,13.016,24Zm-7,0a1,1,0,0,1-.964-1.269c.116-.419.247-.808.377-1.191,1.285-2.684.18-6.683-1.256-8.554A12.313,12.313,0,0,1,3.359.576a1,1,0,0,1,1.811.848,10.307,10.307,0,0,0,.686,10.483c1.675,2.137,2.986,7.113,1.467,10.271-.118.351-.238.708-.345,1.091A1,1,0,0,1,6.016,24Z"/></svg>

+ 1 - 0
app/src/main/assets/themes/Default/icons/icon_bottom_menu_data_manage.svg

@@ -0,0 +1 @@
+<svg id="Layer_1" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" data-name="Layer 1"><path d="m19.414 5h-4.414v-4.414zm.086 13c3.044 0 4.279-.811 4.5-1.079v-2.421c0-.883-1.85-1.5-4.5-1.5s-4.5.617-4.5 1.5v2.421c.221.268 1.456 1.079 4.5 1.079m0 6c2.859 0 4.5-.79 4.5-2.167v-2.833s-1 1-4.5 1-4.5-1-4.5-1v2.833c0 1.377 1.641 2.167 4.5 2.167m-6.5-2.167v-7.333c0-1.052.634-3.5 6.5-3.5.176 0 .333.009.5.013v-4.013h-7v-7h-10c-1.657 0-3 1.343-3 3v21h13.751c-.651-.842-.751-1.727-.751-2.167zm-7-1.833h-2v-4h2zm4 0h-2v-9h2z"/></svg>

+ 2 - 0
app/src/main/assets/themes/Default/icons/icon_bottom_menu_exception_manage.svg

@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" id="Layer_1" data-name="Layer 1" viewBox="0 0 24 24" width="512" height="512"><path d="M23.843,22.248l-6.855-11.67c-.441-.771-1.533-.771-1.974,0l-6.855,11.67c-.444,.777,.105,1.752,.987,1.752h13.711c.882,0,1.432-.976,.987-1.752Zm-7.843-.248c-.552,0-1-.448-1-1s.448-1,1-1,1,.448,1,1-.448,1-1,1Zm1-4c0,.552-.447,1-1,1s-1-.448-1-1v-3c0-.552,.447-1,1-1s1,.448,1,1v3Zm-10.579,3.254l6.867-11.689c.549-.958,1.592-1.565,2.712-1.565s2.163,.607,2.723,1.584l5.277,8.982V5c0-2.757-2.243-5-5-5H5C2.243,0,0,2.243,0,5v14c0,2.757,2.243,5,5,5h1.252c-.352-.891-.314-1.901,.169-2.746ZM8,3c.552,0,1,.448,1,1s-.448,1-1,1-1-.448-1-1,.448-1,1-1Zm-4,2c-.552,0-1-.448-1-1s.448-1,1-1,1,.448,1,1-.448,1-1,1Z"/></svg>

+ 2 - 0
app/src/main/assets/themes/Default/icons/icon_bottom_menu_hardware_manage.svg

@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" id="Layer_1" data-name="Layer 1" viewBox="0 0 24 24" width="512" height="512"><path d="M1,15V5C1,2.24,3.24,0,6,0h12c2.76,0,5,2.24,5,5V15H1Zm22,2v2c0,2.76-2.24,5-5,5H6c-2.76,0-5-2.24-5-5v-2H23Zm-7,3.5c0-.83-.67-1.5-1.5-1.5s-1.5,.67-1.5,1.5,.67,1.5,1.5,1.5,1.5-.67,1.5-1.5Zm4,0c0-.83-.67-1.5-1.5-1.5s-1.5,.67-1.5,1.5,.67,1.5,1.5,1.5,1.5-.67,1.5-1.5Z"/></svg>

+ 26 - 0
app/src/main/assets/themes/Default/icons/icon_bottom_menu_home.svg

@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generator: Adobe Illustrator 25.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" id="Capa_1" x="0px" y="0px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve" width="512" height="512">
+<g>
+	<path d="M256,319.841c-35.346,0-64,28.654-64,64v128h128v-128C320,348.495,291.346,319.841,256,319.841z"/>
+	<g>
+		<path d="M362.667,383.841v128H448c35.346,0,64-28.654,64-64V253.26c0.005-11.083-4.302-21.733-12.011-29.696l-181.29-195.99    c-31.988-34.61-85.976-36.735-120.586-4.747c-1.644,1.52-3.228,3.103-4.747,4.747L12.395,223.5    C4.453,231.496-0.003,242.31,0,253.58v194.261c0,35.346,28.654,64,64,64h85.333v-128c0.399-58.172,47.366-105.676,104.073-107.044    C312.01,275.383,362.22,323.696,362.667,383.841z"/>
+		<path d="M256,319.841c-35.346,0-64,28.654-64,64v128h128v-128C320,348.495,291.346,319.841,256,319.841z"/>
+	</g>
+</g>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+</svg>

+ 4 - 0
app/src/main/assets/themes/Default/icons/icon_bottom_menu_job_manage.svg

@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" id="Layer_1" data-name="Layer 1" viewBox="0 0 24 24">
+  <path d="m19,17.5c0,.827-.673,1.5-1.5,1.5s-1.5-.673-1.5-1.5.673-1.5,1.5-1.5,1.5.673,1.5,1.5Zm-9,4.5c0-1.654-1.346-3-3-3h-.443c.682-1.687,1.443-3.738,1.443-4.5,0-1.381-1.119-2.45-2.5-2.45s-2.5,1.069-2.5,2.45c0,.762.761,2.813,1.443,4.5h-.443c-1.654,0-3,1.346-3,3-.553,0-1,.447-1,1s.447,1,1,1h9c.553,0,1-.447,1-1s-.447-1-1-1ZM24,5v14c0,2.757-2.243,5-5,5h-6.184c.112-.314.184-.648.184-1,0-.979-.472-1.85-1.199-2.397-.389-1.336-1.322-2.443-2.543-3.063.637-1.793.742-2.551.742-3.039,0-2.284-1.756-4.15-4-4.399v-5.101c0-2.757,2.243-5,5-5h8c2.757,0,5,2.243,5,5Zm-14,1c0,.553.447,1,1,1h8c.553,0,1-.447,1-1s-.447-1-1-1h-8c-.553,0-1,.447-1,1Zm7,5c.553,0,1-.447,1-1s-.447-1-1-1h-6c-.553,0-1,.447-1,1s.447,1,1,1h6Zm4,6.5c0-1.93-1.57-3.5-3.5-3.5s-3.5,1.57-3.5,3.5,1.57,3.5,3.5,3.5,3.5-1.57,3.5-3.5Z"/>
+</svg>

+ 60 - 0
app/src/main/assets/themes/Default/icons/key.svg

@@ -0,0 +1,60 @@
+<?xml version="1.0" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
+ "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
+ width="603.000000pt" height="438.000000pt" viewBox="0 0 603.000000 438.000000"
+ preserveAspectRatio="xMidYMid meet">
+<metadata>
+Created by potrace 1.10, written by Peter Selinger 2001-2011
+</metadata>
+<g transform="translate(0.000000,438.000000) scale(0.100000,-0.100000)"
+fill="#000000" stroke="none">
+<path d="M2843 4368 c1 -9 -19 -16 -58 -21 -33 -4 -81 -14 -106 -22 -26 -8
+-57 -15 -70 -15 -13 -1 -35 -7 -49 -15 -14 -8 -35 -14 -46 -15 -12 0 -27 -7
+-34 -15 -7 -8 -19 -15 -28 -15 -16 0 -135 -58 -187 -91 -16 -10 -37 -22 -45
+-26 -26 -12 -176 -127 -245 -189 -113 -100 -262 -277 -330 -392 -6 -9 -22 -35
+-35 -57 -39 -62 -47 -76 -76 -135 -14 -30 -29 -57 -31 -60 -3 -3 -233 -8 -511
+-11 -518 -6 -577 -10 -614 -47 -7 -7 -20 -12 -29 -12 -9 0 -22 -7 -29 -15 -7
+-8 -20 -15 -29 -15 -27 0 -164 -140 -202 -205 -43 -76 -59 -116 -71 -185 -6
+-30 -12 -293 -15 -585 -6 -646 -1 -706 63 -840 60 -124 150 -217 271 -282 105
+-56 108 -56 662 -62 l513 -6 44 -80 c24 -44 47 -87 51 -95 52 -106 269 -369
+385 -466 97 -81 197 -158 218 -167 8 -4 29 -16 45 -26 38 -25 157 -83 215
+-106 25 -9 54 -21 65 -26 31 -14 124 -39 190 -52 83 -15 473 -15 555 0 157 30
+330 97 470 182 19 11 42 24 50 28 64 29 294 227 374 322 153 182 210 267 313
+461 l13 25 512 6 c524 5 583 10 620 47 7 7 20 12 29 12 9 0 22 7 29 15 7 8 20
+15 29 15 28 0 165 140 202 205 43 76 59 116 71 185 6 30 12 294 15 585 6 646
+1 706 -63 840 -80 165 -217 280 -389 326 -64 17 -114 19 -551 19 -391 0 -484
+3 -493 13 -6 8 -27 45 -47 83 -20 38 -41 76 -48 84 -7 8 -16 22 -20 30 -3 8
+-15 29 -26 45 -11 17 -24 40 -30 53 -5 12 -13 22 -17 22 -5 0 -24 24 -43 53
+-19 28 -41 59 -50 68 -8 8 -46 50 -85 93 -125 139 -310 281 -480 370 -90 46
+-209 93 -270 106 -22 5 -58 13 -80 19 -22 6 -65 14 -95 19 -35 5 -54 12 -52
+20 1 9 -39 12 -163 12 -126 0 -164 -3 -162 -12z m1469 -1395 c6 -7 24 -13 38
+-13 14 0 35 -7 46 -15 10 -8 26 -15 35 -15 9 0 22 -7 29 -15 7 -8 19 -15 28
+-15 8 0 22 -7 31 -15 9 -8 33 -29 54 -46 70 -59 132 -152 170 -254 14 -37 37
+-146 37 -173 0 -19 -35 -14 -55 7 -9 11 -36 30 -59 43 -41 22 -43 22 -552 26
+-494 3 -512 4 -533 23 -11 11 -21 29 -21 40 0 37 -76 124 -131 151 -99 47
+-104 48 -424 48 -175 0 -306 -4 -310 -9 -3 -5 -20 -13 -37 -17 -18 -3 -44 -14
+-58 -23 -37 -24 -120 -113 -120 -129 0 -8 -7 -28 -15 -46 -22 -45 -17 -660 6
+-721 19 -52 122 -156 174 -174 31 -12 113 -16 365 -19 347 -3 323 -6 425 45
+50 26 125 114 125 148 0 8 9 24 20 35 19 19 33 20 498 20 300 0 492 4 517 11
+51 13 102 38 138 67 40 31 51 28 44 -10 -3 -18 -11 -60 -16 -92 -6 -33 -15
+-64 -21 -70 -5 -5 -10 -20 -10 -32 0 -12 -7 -27 -15 -34 -8 -7 -15 -21 -15
+-32 0 -10 -7 -21 -15 -24 -8 -4 -15 -12 -15 -19 0 -19 -151 -157 -194 -177
+-58 -29 -98 -45 -151 -62 -45 -14 -178 -16 -1315 -16 -1231 0 -1267 1 -1335
+20 -101 28 -166 64 -239 132 -67 61 -107 113 -140 183 -10 22 -23 48 -28 58
+-25 50 -33 146 -32 412 0 264 8 374 32 421 5 10 18 37 28 59 36 74 103 154
+176 208 90 67 146 91 283 121 11 2 588 3 1282 2 995 -1 1265 -4 1275 -13z
+m-958 -275 c83 -23 181 -127 174 -185 l-3 -28 -429 -2 c-403 -3 -433 -4 -472
+-22 -44 -21 -124 -94 -124 -114 0 -7 -4 -6 -10 3 -15 24 -12 142 5 164 8 11
+15 28 15 38 0 26 115 138 143 138 12 0 29 5 37 10 22 14 612 13 664 -2z m1301
+-269 c59 -39 105 -81 105 -98 0 -8 8 -23 17 -33 26 -29 24 -200 -2 -248 -48
+-86 -110 -132 -200 -148 -66 -11 -1817 -8 -1893 4 -24 3 -46 12 -49 20 -3 8
+-11 14 -18 14 -16 0 -80 65 -93 95 -49 104 -53 148 -23 234 35 100 110 166
+206 182 22 3 461 6 975 5 l935 -1 40 -26z m-2060 -519 c7 0 18 -6 24 -14 19
+-22 97 -27 511 -29 l395 -2 3 -37 c3 -33 -3 -43 -57 -97 -34 -34 -67 -61 -75
+-61 -7 0 -27 -7 -42 -15 -24 -12 -84 -15 -341 -15 -191 0 -314 4 -318 10 -3 5
+-24 14 -45 20 -22 6 -40 15 -40 20 0 6 -6 10 -12 10 -18 0 -78 70 -85 100 -3
+14 -12 34 -19 45 -14 20 -20 146 -8 158 4 3 27 -16 51 -43 25 -28 51 -50 58
+-50z"/>
+</g>
+</svg>

+ 4 - 0
app/src/main/assets/themes/Default/icons/land-location.svg

@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" id="Layer_1" data-name="Layer 1" viewBox="0 0 24 24">
+  <path d="m16.949,2.05c-1.321-1.322-3.079-2.05-4.949-2.05s-3.627.728-4.95,2.05c-2.729,2.729-2.729,7.17.008,9.907l2.495,2.44c.675.66,1.561.99,2.447.99s1.772-.33,2.447-.99l2.502-2.448c1.322-1.322,2.051-3.08,2.051-4.95s-.729-3.627-2.051-4.95Zm-4.949,7.94c-1.657,0-3-1.343-3-3s1.343-3,3-3,3,1.343,3,3-1.343,3-3,3Zm-4.567,5.131l-.122.879H.628l.459-2.676c.246-1.435,1.23-2.577,2.524-3.066.449,1.156,1.14,2.219,2.049,3.129l1.773,1.734ZM.285,18h6.747l-.834,6h-2.198c-1.178,0-2.291-.516-3.052-1.415-.762-.899-1.087-2.081-.893-3.243l.23-1.342Zm14.862,0l.835,6h-7.765l.834-6h6.096Zm8.225-2h-6.485l-.146-1.049,1.622-1.587c.899-.899,1.584-1.954,2.03-3.104,1.292.49,2.274,1.63,2.52,3.064l.459,2.676Zm-.32,6.586c-.762.898-1.874,1.414-3.052,1.414h-2l-.835-6h6.55l.229,1.338c.194,1.167-.131,2.349-.893,3.248Z"/>
+</svg>

+ 4 - 0
app/src/main/assets/themes/Default/icons/leave.svg

@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" id="Layer_1" data-name="Layer 1" viewBox="0 0 24 24">
+  <path d="m23.473,16.247l-2.862,2.863-1.414-1.414,1.696-1.696h-6.892v-2h6.956l-1.76-1.761,1.414-1.414,2.862,2.862c.706.706.706,1.854,0,2.56Zm-9.473,1.753h2v5.999H0V4.199C0,2.775,1.014,1.538,2.411,1.258L8.412.057c.886-.174,1.793.051,2.491.622.428.351.728.812.908,1.319h1.19c1.654,0,3,1.346,3,3v7.001h-2v-7.001c0-.552-.449-1-1-1h-1v18h2v-3.999Zm-4.999-5.501c0-.829-.672-1.501-1.501-1.501s-1.501.672-1.501,1.501.672,1.501,1.501,1.501,1.501-.672,1.501-1.501Z"/>
+</svg>

+ 4 - 0
app/src/main/assets/themes/Default/icons/limit-hand.svg

@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" id="Layer_1" data-name="Layer 1" viewBox="0 0 24 24">
+  <path d="m15.654,13.773l-4.599,7.884c-.606,1.039.143,2.343,1.346,2.343h9.197c1.203,0,1.952-1.304,1.346-2.343l-4.599-7.884c-.601-1.031-2.091-1.031-2.692,0Zm1.346,9.227h0c-.552,0-1-.448-1-1h0c0-.552.448-1,1-1h0c.552,0,1,.448,1,1h0c0,.552-.448,1-1,1Zm-1-4v-2c0-.552.448-1,1-1h0c.552,0,1,.448,1,1v2c0,.552-.448,1-1,1h0c-.552,0-1-.448-1-1Zm-6.94,4.652c-1.285-.391-2.465-1.101-3.417-2.084L.646,16.412c-.713-.715-.88-1.87-.276-2.68.63-.845,1.741-1.031,2.584-.561.201.131.353.245.441.333l2.605,2.65V3.5c0-.911.812-1.632,1.752-1.479.737.12,1.248.813,1.248,1.56v5.42c0,.552.448,1,1,1s1-.448,1-1V1.5c0-.828.672-1.5,1.5-1.5s1.5.672,1.5,1.5v7.5c0,.552.448,1,1,1s1-.448,1-1V2.5c0-.828.672-1.5,1.5-1.5s1.5.672,1.5,1.5v6.5c0,.552.448,1,1,1s1-.448,1-1v-4.5c0-.828.672-1.5,1.5-1.5s1.5.672,1.5,1.5v14.5c0,.145-.031.282-.043.424l-3.883-6.658c-.645-1.106-1.794-1.767-3.074-1.767s-2.43.66-3.074,1.767l-4.597,7.882c-.546.932-.631,2.018-.269,3.003Z"/>
+</svg>

+ 2 - 0
app/src/main/assets/themes/Default/icons/location-crosshairs.svg

@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" id="Layer_1" data-name="Layer 1" viewBox="0 0 24 24" width="512" height="512"><path d="M15,12c0,1.654-1.346,3-3,3s-3-1.346-3-3,1.346-3,3-3,3,1.346,3,3Zm9,0c0,.553-.448,1-1,1h-1.05c-.471,4.717-4.233,8.48-8.95,8.95v1.05c0,.553-.448,1-1,1s-1-.447-1-1v-1.05c-4.717-.471-8.48-4.233-8.95-8.95H1c-.552,0-1-.447-1-1s.448-1,1-1h1.05C2.52,6.283,6.283,2.52,11,2.05V1c0-.553,.448-1,1-1s1,.447,1,1v1.05c4.717,.471,8.48,4.233,8.95,8.95h1.05c.552,0,1,.447,1,1Zm-7,0c0-2.757-2.243-5-5-5s-5,2.243-5,5,2.243,5,5,5,5-2.243,5-5Z"/></svg>

+ 22 - 0
app/src/main/assets/themes/Default/icons/lock.svg

@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generator: Adobe Illustrator 25.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" id="Capa_1" x="0px" y="0px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve" width="512" height="512">
+<g>
+	<path d="M405.333,179.712v-30.379C405.333,66.859,338.475,0,256,0S106.667,66.859,106.667,149.333v30.379   c-38.826,16.945-63.944,55.259-64,97.621v128C42.737,464.214,90.452,511.93,149.333,512h213.333   c58.881-0.07,106.596-47.786,106.667-106.667v-128C469.278,234.971,444.159,196.657,405.333,179.712z M277.333,362.667   c0,11.782-9.551,21.333-21.333,21.333c-11.782,0-21.333-9.551-21.333-21.333V320c0-11.782,9.551-21.333,21.333-21.333   c11.782,0,21.333,9.551,21.333,21.333V362.667z M362.667,170.667H149.333v-21.333c0-58.91,47.756-106.667,106.667-106.667   s106.667,47.756,106.667,106.667V170.667z"/>
+</g>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+</svg>

+ 4 - 0
app/src/main/assets/themes/Default/icons/master-plan.svg

@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" id="Layer_1" data-name="Layer 1" viewBox="0 0 24 24">
+  <path d="M.101,4C.566,1.721,2.586,0,5,0h14c2.414,0,4.434,1.721,4.899,4H.101Zm23.899,2v13c0,2.757-2.243,5-5,5H5c-2.757,0-5-2.243-5-5V6H24ZM3,10c0,.552,.447,1,1,1h5c.553,0,1-.448,1-1s-.447-1-1-1H4c-.553,0-1,.448-1,1Zm12,10c0-.553-.447-1-1-1H4c-.553,0-1,.447-1,1s.447,1,1,1H14c.553,0,1-.447,1-1Zm0-5c0-.553-.447-1-1-1H7c-.553,0-1,.447-1,1s.447,1,1,1h7c.553,0,1-.447,1-1Zm6,5c0-.738-.405-1.376-1-1.723v-6.277c0-1.654-1.346-3-3-3h-1.277c-.346-.595-.984-1-1.723-1-1.105,0-2,.895-2,2s.895,2,2,2c.738,0,1.376-.405,1.723-1h1.277c.552,0,1,.449,1,1v6.277c-.595,.346-1,.984-1,1.723,0,1.105,.895,2,2,2s2-.895,2-2Z"/>
+</svg>

+ 4 - 0
app/src/main/assets/themes/Default/icons/message-alert.svg

@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" id="Layer_1" data-name="Layer 1" viewBox="0 0 24 24">
+  <path d="M15.47,12.377l-5.226,8.96c-.689,1.181,.163,2.663,1.53,2.663h10.453c1.367,0,2.218-1.483,1.53-2.663l-5.226-8.96c-.683-1.171-2.376-1.171-3.059,0Zm1.53,10.623h0c-.552,0-1-.448-1-1h0c0-.552,.448-1,1-1h0c.552,0,1,.448,1,1h0c0,.552-.448,1-1,1Zm-1-4v-3c0-.552,.448-1,1-1h0c.552,0,1,.448,1,1v3c0,.552-.448,1-1,1h0c-.552,0-1-.448-1-1ZM12,0C5.373,0,0,5.373,0,12v7c0,2.757,2.243,5,5,5h3.451c-.622-1.162-.603-2.525,.065-3.671l1.942-3.329h-2.458c-.552,0-1-.447-1-1s.448-1,1-1h3.625l1.167-2h-4.792c-.552,0-1-.448-1-1s.448-1,1-1h5.992c.708-.946,1.802-1.501,3.008-1.501,1.356,0,2.574,.7,3.257,1.872l2.899,4.969c.266-.682,.493-1.384,.631-2.12,.003-.014,.013-.024,.015-.038,.036-.196,.055-.395,.081-.593,.019-.142,.045-.283,.058-.426,.037-.386,.059-.774,.059-1.162C24,5.373,18.627,0,12,0Zm4,9H8c-.552,0-1-.448-1-1s.448-1,1-1h8c.553,0,1,.448,1,1s-.447,1-1,1Z"/>
+</svg>

+ 54 - 0
app/src/main/assets/themes/Default/icons/new_sop.svg

@@ -0,0 +1,54 @@
+<?xml version="1.0" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
+ "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
+ width="900.000000pt" height="900.000000pt" viewBox="0 0 900.000000 900.000000"
+ preserveAspectRatio="xMidYMid meet">
+<metadata>
+Created by potrace 1.10, written by Peter Selinger 2001-2011
+</metadata>
+<g transform="translate(0.000000,900.000000) scale(0.100000,-0.100000)"
+fill="#000000" stroke="none">
+<path d="M1980 8403 c-85 -38 -104 -51 -151 -98 -59 -60 -82 -97 -109 -172
+-20 -57 -20 -83 -20 -3643 0 -3581 0 -3586 20 -3644 27 -74 57 -120 116 -177
+48 -46 72 -60 147 -93 34 -14 203 -16 1869 -16 1007 0 1833 1 1834 3 2 2 5
+282 7 623 4 674 4 671 62 765 37 59 61 85 120 128 108 80 65 75 770 81 l630 5
+3 2955 c2 2939 2 2955 -18 3013 -26 74 -56 121 -113 177 -44 43 -66 57 -150
+94 -35 15 -237 16 -2510 15 -2230 0 -2475 -2 -2507 -16z m999 -1259 c171 -42
+291 -152 351 -321 49 -139 11 -250 -92 -268 -81 -14 -149 37 -163 124 -16 96
+-72 172 -138 185 -89 18 -158 3 -205 -44 -52 -52 -68 -116 -47 -185 25 -86 95
+-135 193 -135 98 0 215 -44 296 -111 106 -87 176 -230 176 -358 0 -67 -27
+-167 -64 -236 -31 -56 -126 -151 -177 -176 -107 -53 -110 -53 -239 -53 -123 0
+-126 1 -202 37 -130 62 -213 160 -259 301 -41 127 -14 217 75 251 38 15 50 15
+82 5 40 -13 94 -65 94 -89 0 -8 7 -41 16 -72 35 -126 167 -194 272 -140 105
+53 146 152 103 246 -34 76 -97 107 -239 120 -121 11 -242 76 -314 172 -49 65
+-71 111 -93 198 -19 75 -19 103 1 184 45 187 172 319 354 365 74 20 140 19
+219 0z m1733 -3 c116 -33 202 -106 259 -218 l34 -68 3 -440 c4 -462 -1 -550
+-37 -625 -25 -54 -101 -144 -139 -164 -123 -65 -94 -61 -372 -61 -233 0 -260
+2 -300 20 -135 59 -223 168 -249 309 -15 81 -15 838 0 925 27 157 143 285 294
+324 94 24 419 23 507 -2z m1533 4 c193 -48 322 -196 342 -393 12 -119 -49
+-268 -144 -352 -82 -72 -172 -99 -368 -109 l-130 -6 -5 -322 -5 -322 -33 -34
+c-72 -74 -196 -48 -233 50 -5 14 -9 313 -9 707 l0 683 31 42 c16 23 45 49 62
+56 47 21 411 20 492 0z m-2691 -2565 c22 -5 53 -22 69 -38 58 -58 44 -168 -28
+-212 -31 -19 -49 -20 -430 -20 -387 0 -399 1 -432 21 -35 22 -73 83 -73 119 0
+31 35 93 62 110 13 8 37 18 53 21 48 10 736 9 779 -1z m2697 -15 c32 -24 69
+-86 69 -115 0 -36 -38 -97 -73 -119 -34 -21 -35 -21 -1109 -21 l-1075 0 -41
+30 c-34 24 -42 37 -47 74 -4 24 -4 57 -1 74 9 38 63 89 101 95 17 2 507 4
+1090 3 1041 -1 1060 -1 1086 -21z m-90 -936 c19 -6 49 -27 67 -47 26 -29 32
+-44 32 -80 0 -54 -29 -105 -73 -130 -30 -16 -140 -17 -1717 -17 -1433 0 -1690
+2 -1719 14 -42 18 -91 84 -91 123 0 33 25 86 49 106 52 43 -12 41 1747 42
+1184 0 1681 -3 1705 -11z m-2325 -958 c108 -49 111 -195 6 -247 -34 -18 -73
+-19 -522 -22 -329 -2 -501 0 -536 8 -120 26 -163 154 -78 232 54 49 46 48 584
+48 471 0 508 -2 546 -19z m1674 -3 c121 -62 99 -219 -35 -257 -55 -15 -1144
+-15 -1200 0 -51 14 -80 41 -101 95 -16 42 -16 45 7 91 18 36 35 53 69 71 l44
+22 586 0 586 0 44 -22z"/>
+<path d="M4333 6871 c-78 -6 -108 -19 -135 -56 -4 -5 -8 -213 -8 -462 l0 -452
+37 -28 c36 -28 37 -28 216 -31 197 -4 221 1 262 50 l25 30 0 431 c0 410 -1
+434 -20 464 -12 21 -32 36 -57 43 -48 15 -212 20 -320 11z"/>
+<path d="M5959 6862 c-17 -12 -19 -26 -19 -136 0 -91 4 -126 13 -135 16 -13
+183 -17 244 -7 138 24 148 233 14 277 -52 17 -228 18 -252 1z"/>
+<path d="M6055 1864 c-16 -9 -39 -28 -50 -42 -19 -26 -20 -45 -23 -625 -2
+-503 0 -598 11 -603 36 -13 112 54 460 404 594 598 726 734 763 790 63 94 109
+87 -551 89 -502 2 -584 0 -610 -13z"/>
+</g>
+</svg>

+ 4 - 0
app/src/main/assets/themes/Default/icons/password-lock.svg

@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" id="Layer_1" data-name="Layer 1" viewBox="0 0 24 24">
+  <path d="M22,14.556v-1.556c0-2.206-1.794-4-4-4s-4,1.794-4,4v1.556c-1.19,.694-2,1.97-2,3.444v2c0,2.206,1.794,4,4,4h4c2.206,0,4-1.794,4-4v-2c0-1.474-.81-2.75-2-3.444Zm-4,5.944c-.828,0-1.5-.672-1.5-1.5s.672-1.5,1.5-1.5,1.5,.672,1.5,1.5-.672,1.5-1.5,1.5Zm-2-6.5v-1c0-1.103,.897-2,2-2s2,.897,2,2v1h-4Zm3-12H5C2.239,2,0,4.239,0,7v3c0,2.761,2.239,5,5,5h5.812c.318-.548,.72-1.039,1.188-1.46v-.54c0-.772,.152-1.508,.419-2.187-.063,.012-.124,.036-.188,.036-.256,0-.512-.098-.707-.293l-.643-.643-.643,.643c-.195,.195-.451,.293-.707,.293s-.512-.098-.707-.293c-.391-.391-.391-1.023,0-1.414l.643-.643-.643-.643c-.391-.391-.391-1.023,0-1.414,.39-.391,1.023-.391,1.414,0l.643,.643,.643-.643c.391-.391,1.023-.391,1.414,0,.391,.391,.39,1.023,0,1.414l-.643,.643,.643,.643c.097,.097,.17,.21,.219,.33,1.092-1.495,2.853-2.473,4.843-2.473,2.754,0,5.074,1.867,5.777,4.4,.131-.447,.223-.91,.223-1.4v-3c0-2.761-2.239-5-5-5ZM6.707,9.143c.391,.391,.391,1.023,0,1.414-.195,.195-.451,.293-.707,.293s-.512-.098-.707-.293l-.643-.643-.643,.643c-.195,.195-.451,.293-.707,.293s-.512-.098-.707-.293c-.391-.391-.391-1.023,0-1.414l.643-.643-.643-.643c-.391-.391-.391-1.023,0-1.414,.39-.391,1.023-.391,1.414,0l.643,.643,.643-.643c.391-.391,1.023-.391,1.414,0s.391,1.023,0,1.414l-.643,.643,.643,.643Z"/>
+</svg>

+ 23 - 0
app/src/main/assets/themes/Default/icons/power.svg

@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generator: Adobe Illustrator 25.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" id="Capa_1" x="0px" y="0px" viewBox="0 0 512.301 512.301" style="enable-background:new 0 0 512.301 512.301;" xml:space="preserve" width="512" height="512">
+<g>
+	<path d="M320.119,82.112L320.119,82.112c0.137,8.67,5.409,16.432,13.419,19.755c71.67,31.535,117.01,103.433,114.581,181.696   c-1.72,106.039-89.076,190.605-195.115,188.885c-106.039-1.72-190.606-89.076-188.885-195.115c0,0,0,0,0,0   c0.101-76.006,45.028-144.798,114.581-175.445c8.013-3.343,13.282-11.117,13.419-19.797l0,0c0.019-11.782-9.518-21.348-21.3-21.367   c-2.745-0.004-5.466,0.521-8.012,1.548C43.898,113.824-10.705,252.01,40.848,370.919S230.586,544.43,349.495,492.878   c118.909-51.552,173.511-189.738,121.959-308.647c-23.698-54.66-67.299-98.261-121.959-121.959   c-10.913-4.442-23.36,0.804-27.802,11.716C320.643,76.568,320.108,79.327,320.119,82.112z"/>
+	<path d="M256.119,0L256.119,0c11.782,0,21.333,9.551,21.333,21.333v128c0,11.782-9.551,21.333-21.333,21.333l0,0   c-11.782,0-21.333-9.551-21.333-21.333v-128C234.785,9.551,244.337,0,256.119,0z"/>
+</g>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+</svg>

+ 2 - 0
app/src/main/assets/themes/Default/icons/rfid.svg

@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" id="Layer_1" data-name="Layer 1" viewBox="0 0 24 24" width="512" height="512"><path d="M12,10c1.1,0,2,.9,2,2s-.9,2-2,2-2-.9-2-2,.9-2,2-2Zm8.49,10.49c4.68-4.68,4.68-12.29,0-16.97-.39-.39-1.02-.39-1.41,0s-.39,1.02,0,1.41c3.9,3.9,3.9,10.24,0,14.14-.39,.39-.39,1.02,0,1.41,.2,.2,.45,.29,.71,.29s.51-.1,.71-.29Zm-3.54-3.54c1.32-1.32,2.05-3.08,2.05-4.95s-.73-3.63-2.05-4.95c-.39-.39-1.02-.39-1.41,0s-.39,1.02,0,1.41c.94,.94,1.46,2.2,1.46,3.54s-.52,2.59-1.46,3.54c-.39,.39-.39,1.02,0,1.41,.2,.2,.45,.29,.71,.29s.51-.1,.71-.29Zm-12.02,3.54c.39-.39,.39-1.02,0-1.41-3.9-3.9-3.9-10.24,0-14.14,.39-.39,.39-1.02,0-1.41s-1.02-.39-1.41,0C-1.16,8.19-1.16,15.81,3.51,20.49c.2,.2,.45,.29,.71,.29s.51-.1,.71-.29Zm3.54-3.54c.39-.39,.39-1.02,0-1.41-1.95-1.95-1.95-5.12,0-7.07,.39-.39,.39-1.02,0-1.41s-1.02-.39-1.41,0c-2.73,2.73-2.73,7.17,0,9.9,.2,.2,.45,.29,.71,.29s.51-.1,.71-.29Z"/></svg>

+ 4 - 0
app/src/main/assets/themes/Default/icons/robotic-arm.svg

@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" id="Layer_1" data-name="Layer 1" viewBox="0 0 24 24">
+  <path d="m18.5,10c1.381,0,2.5,1.119,2.5,2.5s-1.119,2.5-2.5,2.5-2.5-1.119-2.5-2.5,1.119-2.5,2.5-2.5Zm-8.934-5.98l-2.98,2.98h-1.929c-1.335,0-2.591.52-3.535,1.464l-.829.829c-.391.391-.391,1.023,0,1.414s1.023.391,1.414,0l.829-.829c.559-.558,1.332-.878,2.121-.878h1.343v1.343c0,.79-.32,1.562-.878,2.121l-.829.829c-.391.391-.391,1.023,0,1.414.195.195.451.293.707.293s.512-.098.707-.293l.829-.829c.944-.944,1.464-2.2,1.464-3.535v-1.929l2.98-2.98c-.585-.345-1.069-.829-1.414-1.414Zm8.896,3.984l-2.062-3.93c-.715,1.17-1.999,1.931-3.451,1.912l2.008,3.771c.816-1.052,2.074-1.74,3.505-1.752Zm-3.462-6.004c0-1.105-.895-2-2-2s-2,.895-2,2,.895,2,2,2,2-.895,2-2Zm8,20h-1v-6.703c-.825,1.03-2.078,1.703-3.5,1.703s-2.675-.673-3.5-1.703v6.703h-1c-.552,0-1,.448-1,1s.448,1,1,1h9c.552,0,1-.448,1-1s-.448-1-1-1Z"/>
+</svg>

+ 2 - 0
app/src/main/assets/themes/Default/icons/rotate-left.svg

@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" id="Layer_1" data-name="Layer 1" viewBox="0 0 24 24" width="512" height="512"><path d="M12,0c-2.978,0-5.821,1.111-8,3.057V0H2V5c0,1.103,.897,2,2,2h5v-2H4.86c1.867-1.901,4.437-3,7.14-3,5.514,0,10,4.486,10,10s-4.486,10-10,10S2,17.514,2,12H0c0,6.617,5.383,12,12,12s12-5.383,12-12S18.617,0,12,0Z"/></svg>

+ 4 - 0
app/src/main/assets/themes/Default/icons/selection.svg

@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" id="Layer_1" data-name="Layer 1" viewBox="0 0 24 24">
+  <path d="m19,2C19,.895,19.895,0,21,0s2,.895,2,2-.895,2-2,2-2-.895-2-2ZM3,4c1.105,0,2-.895,2-2S4.105,0,3,0,1,.895,1,2s.895,2,2,2Zm20.341,4c.454,0,.76-.444.628-.878-.376-1.228-1.518-2.122-2.869-2.122h-1.169c.041.328.069.661.069,1,0,.692-.097,1.36-.262,2h3.603ZM4.069,5h-1.154C1.533,5,.368,5.935.021,7.208c-.11.403.229.792.647.792h3.594c-.165-.64-.262-1.308-.262-2,0-.339.028-.672.069-1Zm18.931,18.407v.593H6.538l-1.821-1.628c-.917-.858-.96-2.307-.098-3.23.861-.922,2.313-.97,3.235-.109.034.032,1.069.898,2.145,1.784v-9.817c0-1.215,1.083-2.176,2.336-1.973.983.16,1.664,1.083,1.664,2.08v5.355l5.829,2.292c1.913.752,3.171,2.598,3.171,4.653ZM12,0c-3.309,0-6,2.691-6,6,0,1.796.8,3.401,2.054,4.501.124-.984.588-1.897,1.355-2.548.896-.761,2.078-1.088,3.248-.899,1.709.278,3.033,1.711,3.289,3.447,1.254-1.1,2.054-2.705,2.054-4.5,0-3.309-2.691-6-6-6Zm0,6c-1.105,0-2-.895-2-2s.895-2,2-2,2,.895,2,2-.895,2-2,2Z"/>
+</svg>

+ 2 - 0
app/src/main/assets/themes/Default/icons/shield-check.svg

@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" id="Filled" viewBox="0 0 24 24" width="512" height="512"><path d="M18.581,2.14,12.316.051a1,1,0,0,0-.632,0L5.419,2.14A4.993,4.993,0,0,0,2,6.883V12c0,7.563,9.2,11.74,9.594,11.914a1,1,0,0,0,.812,0C12.8,23.74,22,19.563,22,12V6.883A4.993,4.993,0,0,0,18.581,2.14ZM16.718,9.717l-4.272,4.272a1.873,1.873,0,0,1-1.335.553h-.033a1.872,1.872,0,0,1-1.345-.6l-2.306-2.4A1,1,0,1,1,8.868,10.16L11.112,12.5,15.3,8.3a1,1,0,0,1,1.414,1.414Z"/></svg>

+ 33 - 0
app/src/main/assets/themes/Default/icons/slot.svg

@@ -0,0 +1,33 @@
+<?xml version="1.0" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
+ "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
+ width="603.000000pt" height="438.000000pt" viewBox="0 0 603.000000 438.000000"
+ preserveAspectRatio="xMidYMid meet">
+<metadata>
+Created by potrace 1.10, written by Peter Selinger 2001-2011
+</metadata>
+<g transform="translate(0.000000,438.000000) scale(0.100000,-0.100000)"
+fill="#000000" stroke="none">
+<path d="M2843 4368 c1 -9 -19 -16 -58 -21 -33 -4 -81 -14 -106 -22 -26 -8
+-57 -15 -70 -15 -13 -1 -35 -7 -49 -15 -14 -8 -35 -14 -46 -15 -12 0 -27 -7
+-34 -15 -7 -8 -19 -15 -28 -15 -16 0 -135 -58 -187 -91 -16 -10 -37 -22 -45
+-26 -26 -12 -176 -127 -245 -189 -113 -100 -262 -277 -330 -392 -6 -9 -22 -35
+-35 -57 -39 -62 -47 -76 -76 -135 -14 -30 -29 -57 -31 -60 -3 -3 -233 -8 -511
+-11 -518 -6 -577 -10 -614 -47 -7 -7 -20 -12 -29 -12 -9 0 -22 -7 -29 -15 -7
+-8 -20 -15 -29 -15 -27 0 -164 -140 -202 -205 -43 -76 -59 -116 -71 -185 -6
+-30 -12 -293 -15 -585 -6 -646 -1 -706 63 -840 60 -124 150 -217 271 -282 105
+-56 108 -56 662 -62 l513 -6 44 -80 c24 -44 47 -87 51 -95 52 -106 269 -369
+385 -466 97 -81 197 -158 218 -167 8 -4 29 -16 45 -26 38 -25 157 -83 215
+-106 25 -9 54 -21 65 -26 31 -14 124 -39 190 -52 83 -15 473 -15 555 0 157 30
+330 97 470 182 19 11 42 24 50 28 64 29 294 227 374 322 153 182 210 267 313
+461 l13 25 512 6 c524 5 583 10 620 47 7 7 20 12 29 12 9 0 22 7 29 15 7 8 20
+15 29 15 28 0 165 140 202 205 43 76 59 116 71 185 6 30 12 294 15 585 6 646
+1 706 -63 840 -80 165 -217 280 -389 326 -64 17 -114 19 -551 19 -391 0 -484
+3 -493 13 -6 8 -27 45 -47 83 -20 38 -41 76 -48 84 -7 8 -16 22 -20 30 -3 8
+-15 29 -26 45 -11 17 -24 40 -30 53 -5 12 -13 22 -17 22 -5 0 -24 24 -43 53
+-19 28 -41 59 -50 68 -8 8 -46 50 -85 93 -125 139 -310 281 -480 370 -90 46
+-209 93 -270 106 -22 5 -58 13 -80 19 -22 6 -65 14 -95 19 -35 5 -54 12 -52
+20 1 9 -39 12 -163 12 -126 0 -164 -3 -162 -12z"/>
+</g>
+</svg>

+ 80 - 0
app/src/main/assets/themes/Default/icons/sop.svg

@@ -0,0 +1,80 @@
+<?xml version="1.0" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
+ "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
+ width="900.000000pt" height="900.000000pt" viewBox="0 0 900.000000 900.000000"
+ preserveAspectRatio="xMidYMid meet">
+<metadata>
+Created by potrace 1.10, written by Peter Selinger 2001-2011
+</metadata>
+<g transform="translate(0.000000,900.000000) scale(0.100000,-0.100000)"
+fill="#000000" stroke="none">
+<path d="M630 8985 c0 -9 -14 -16 -37 -20 -40 -7 -90 -25 -158 -57 -209 -99
+-369 -300 -424 -531 -16 -67 -13 -300 4 -367 46 -183 152 -340 304 -451 235
+-173 568 -197 826 -61 146 77 275 211 350 365 l38 77 351 -2 351 -3 0 -710 0
+-710 -420 -6 c-360 -5 -426 -8 -464 -22 -24 -9 -51 -17 -60 -17 -28 -1 -186
+-85 -247 -132 -168 -129 -272 -296 -318 -508 -14 -64 -16 -151 -16 -572 l0
+-498 -238 0 c-270 0 -308 -7 -388 -74 -63 -53 -84 -102 -84 -196 0 -94 21
+-142 86 -198 75 -64 120 -72 392 -72 l232 0 0 -497 c0 -422 2 -509 16 -573 45
+-210 151 -379 318 -508 61 -47 219 -131 247 -132 9 0 36 -8 60 -17 38 -14 104
+-17 464 -22 l420 -6 0 -710 0 -710 -351 -3 -351 -2 -38 77 c-76 156 -231 314
+-365 374 -244 110 -499 105 -717 -12 -203 -110 -341 -286 -398 -509 -17 -67
+-20 -300 -4 -367 55 -231 215 -432 424 -531 124 -59 188 -72 348 -72 212 1
+329 40 486 163 100 78 161 153 227 281 l38 75 526 3 526 3 41 27 c75 49 100
+80 126 152 8 22 13 292 17 896 l5 865 720 0 720 0 2 -470 2 -470 -72 -34
+c-161 -76 -295 -212 -371 -374 -58 -124 -70 -180 -70 -337 0 -157 12 -214 70
+-337 102 -214 304 -377 537 -432 61 -14 293 -14 354 0 231 55 438 221 537 432
+58 124 70 180 70 337 0 157 -12 213 -70 337 -75 160 -213 299 -371 374 l-72
+34 2 470 2 470 720 0 720 0 6 -865 c3 -476 9 -878 14 -895 16 -59 55 -105 128
+-153 l41 -27 526 -3 526 -3 28 -56 c115 -235 300 -390 536 -449 68 -16 301
+-18 367 -3 231 55 432 215 531 424 32 68 50 118 57 158 4 23 11 37 20 37 13 0
+15 25 15 150 0 125 -2 150 -15 150 -9 0 -16 14 -20 37 -25 150 -155 345 -304
+454 -226 167 -536 195 -801 75 -147 -67 -296 -217 -375 -379 l-38 -77 -351 2
+-351 3 0 710 0 710 425 5 c372 5 430 8 464 23 21 9 46 17 55 17 28 1 186 85
+247 132 167 129 272 297 318 508 14 64 16 151 16 573 l0 497 238 1 c195 0 246
+3 289 17 64 21 140 83 159 129 8 19 21 36 29 40 22 8 22 158 0 166 -8 4 -21
+21 -29 40 -19 46 -92 105 -157 128 -46 17 -84 19 -291 19 l-238 0 0 498 c0
+421 -2 508 -16 572 -45 209 -152 380 -318 508 -61 47 -219 131 -247 132 -9 0
+-34 8 -55 17 -34 15 -92 18 -464 23 l-425 5 0 710 0 710 351 3 351 2 38 -77
+c138 -280 410 -453 715 -453 197 0 378 70 532 206 102 90 214 280 233 397 4
+23 11 37 20 37 13 0 15 25 15 150 0 125 -2 150 -15 150 -9 0 -16 14 -20 38 -8
+50 -51 156 -88 217 -76 126 -202 241 -332 303 -68 32 -118 50 -157 57 -24 4
+-38 11 -38 20 0 13 -25 15 -150 15 -121 0 -150 -3 -150 -14 0 -8 -15 -17 -37
+-20 -121 -22 -297 -124 -394 -229 -41 -45 -112 -152 -145 -219 l-28 -57 -527
+-3 -527 -3 -57 -40 c-59 -40 -95 -87 -110 -140 -5 -16 -11 -419 -14 -895 l-6
+-865 -720 0 -720 0 -2 470 -3 470 43 19 c175 78 322 221 401 389 58 124 70
+180 70 337 0 121 -4 156 -22 212 -56 176 -147 308 -282 413 -82 63 -216 128
+-292 141 -23 4 -38 12 -38 20 0 11 -29 14 -150 14 -125 0 -150 -2 -150 -15 0
+-9 -14 -16 -37 -20 -78 -13 -210 -76 -293 -140 -135 -105 -226 -237 -282 -413
+-32 -97 -32 -327 0 -424 73 -231 219 -405 419 -499 l72 -34 -2 -470 -2 -470
+-720 0 -720 0 -6 865 c-3 476 -9 879 -14 895 -16 59 -55 105 -128 153 l-41 27
+-523 3 -523 3 -25 39 c-14 22 -25 42 -25 46 0 20 -82 137 -137 194 -103 110
+-267 205 -385 226 -23 4 -38 12 -38 20 0 11 -29 14 -150 14 -125 0 -150 -2
+-150 -15z m2086 -3344 c150 -34 269 -110 353 -225 44 -61 57 -90 82 -176 24
+-81 24 -131 2 -193 -45 -125 -168 -198 -296 -175 -94 17 -182 97 -207 191 -10
+36 -20 51 -37 58 -32 12 -405 12 -437 -1 -25 -9 -26 -12 -26 -104 0 -109 -5
+-103 130 -170 41 -21 83 -41 93 -47 26 -14 43 -23 167 -87 63 -33 165 -85 225
+-117 61 -32 122 -64 137 -72 42 -22 135 -110 171 -162 79 -114 96 -185 97
+-396 0 -211 -21 -293 -106 -406 -90 -118 -211 -193 -362 -223 -123 -24 -516
+-22 -628 3 -125 28 -207 73 -294 161 -88 88 -131 168 -149 280 -11 64 -11 84
+2 133 37 142 164 222 305 192 101 -21 167 -82 203 -188 10 -29 25 -54 36 -58
+28 -11 408 -10 437 1 25 9 26 12 26 104 0 63 -4 97 -12 104 -15 11 -101 58
+-338 180 -91 46 -208 107 -260 135 -52 27 -113 59 -135 70 -22 11 -74 55 -115
+96 -125 127 -159 224 -159 466 -1 237 34 340 159 465 86 87 169 133 290 161
+112 26 531 26 646 0z m1944 -5 c283 -64 492 -257 589 -541 30 -91 41 -246 41
+-605 0 -359 -11 -514 -41 -605 -85 -250 -266 -437 -499 -515 -146 -48 -262
+-59 -381 -36 -228 46 -380 137 -509 306 -97 128 -143 248 -159 414 -14 141
+-14 716 -1 866 16 170 61 290 160 420 77 101 148 162 253 219 89 48 139 64
+297 95 41 8 180 -2 250 -18z m2285 2 c175 -54 307 -156 389 -298 70 -123 86
+-213 86 -485 0 -213 -11 -313 -44 -403 -52 -141 -180 -276 -328 -345 -96 -46
+-187 -57 -448 -57 -170 0 -239 -3 -248 -12 -9 -9 -12 -77 -12 -246 0 -151 -4
+-249 -12 -276 -12 -41 -56 -107 -93 -138 -27 -22 -120 -58 -153 -58 -60 0
+-136 35 -187 85 -91 90 -85 18 -85 1085 0 1067 -6 995 86 1086 85 84 82 84
+574 80 348 -2 434 -6 475 -18z"/>
+<path d="M4435 5120 c-83 -15 -155 -76 -194 -165 -20 -46 -21 -63 -21 -465 0
+-402 1 -419 21 -465 27 -60 79 -118 132 -145 59 -32 175 -32 234 0 53 27 105
+85 132 145 20 46 21 63 21 459 0 462 -1 470 -72 551 -64 73 -155 103 -253 85z"/>
+<path d="M6352 5117 c-9 -11 -12 -83 -10 -273 l3 -259 243 -3 243 -2 30 29 29
+29 0 214 c-1 211 -1 213 -25 243 l-25 30 -238 3 c-199 3 -240 1 -250 -11z"/>
+</g>
+</svg>

+ 1 - 0
app/src/main/assets/themes/Default/icons/target.svg

@@ -0,0 +1 @@
+<svg id="Layer_1" height="512" viewBox="0 0 24 24" width="512" xmlns="http://www.w3.org/2000/svg" data-name="Layer 1"><path d="m12 0a12 12 0 1 0 12 12 12.013 12.013 0 0 0 -12-12zm1.5 20.865v-1.365a1.5 1.5 0 0 0 -3 0v1.365a9.014 9.014 0 0 1 -7.365-7.365h1.365a1.5 1.5 0 0 0 0-3h-1.365a9.014 9.014 0 0 1 7.365-7.365v1.365a1.5 1.5 0 0 0 3 0v-1.365a9.01 9.01 0 0 1 7.365 7.365h-1.365a1.5 1.5 0 0 0 0 3h1.365a9.01 9.01 0 0 1 -7.365 7.365zm2.5-8.865a1.5 1.5 0 0 1 -1.5 1.5h-1v1a1.5 1.5 0 0 1 -3 0v-1h-1a1.5 1.5 0 0 1 0-3h1v-1a1.5 1.5 0 0 1 3 0v1h1a1.5 1.5 0 0 1 1.5 1.5z"/></svg>

+ 4 - 0
app/src/main/assets/themes/Default/icons/to-do.svg

@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" id="Layer_1" data-name="Layer 1" viewBox="0 0 24 24">
+  <path d="m21.5,18l-2.5-2.5V2.5c0-1.379,1.121-2.5,2.5-2.5s2.5,1.121,2.5,2.5v13l-2.5,2.5ZM14,0H3C1.343,0,0,1.343,0,3v18.357c0,1.308.941,2.499,2.242,2.63,1.496.15,2.758-1.021,2.758-2.487v-3.5h12V3c0-1.657-1.343-3-3-3Zm-7.226,13.534c-.31.31-.717.465-1.124.465s-.814-.155-1.124-.465l-1.647-1.647,1.414-1.414,1.357,1.357,2.537-2.537,1.414,1.414-2.827,2.827Zm0-6c-.31.31-.717.465-1.124.465s-.814-.155-1.124-.465l-1.647-1.647,1.414-1.414,1.357,1.357,2.537-2.537,1.414,1.414-2.827,2.827Zm13.226,13.466v-1s-13,0-13,0v1.5c0,.924-.28,1.784-.76,2.5h10.76c1.657,0,3-1.343,3-3Z"/>
+</svg>

+ 22 - 0
app/src/main/assets/themes/Default/icons/unlock.svg

@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generator: Adobe Illustrator 25.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" id="Capa_1" x="0px" y="0px" viewBox="0 0 512.077 512.077" style="enable-background:new 0 0 512.077 512.077;" xml:space="preserve" width="512" height="512">
+<g>
+	<path d="M362.705,170.744H149.372v-21.333c-0.016-58.91,47.727-106.68,106.637-106.696c38.815-0.011,74.572,21.064,93.363,55.027   c5.72,10.303,18.71,14.019,29.013,8.299c10.303-5.72,14.019-18.71,8.299-29.013c-39.949-72.153-130.826-98.26-202.98-58.311   c-47.529,26.315-77.017,76.367-76.999,130.695v30.379c-38.826,16.945-63.944,55.259-64,97.621v128   c0.071,58.881,47.786,106.596,106.667,106.667h213.333c58.881-0.07,106.596-47.786,106.667-106.667v-128   C469.301,218.529,421.586,170.814,362.705,170.744z M277.372,362.744c0,11.782-9.551,21.333-21.333,21.333   s-21.333-9.551-21.333-21.333v-42.667c0-11.782,9.551-21.333,21.333-21.333s21.333,9.551,21.333,21.333V362.744z"/>
+</g>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+</svg>

+ 23 - 0
app/src/main/assets/themes/Default/icons/user.svg

@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generator: Adobe Illustrator 25.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" id="Capa_1" x="0px" y="0px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve" width="512" height="512">
+<g>
+	<circle cx="256" cy="128" r="128"/>
+	<path d="M256,298.667c-105.99,0.118-191.882,86.01-192,192C64,502.449,73.551,512,85.333,512h341.333   c11.782,0,21.333-9.551,21.333-21.333C447.882,384.677,361.99,298.784,256,298.667z"/>
+</g>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+</svg>

+ 2 - 0
app/src/main/assets/themes/Default/icons/users-alt.svg

@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" id="Layer_1" data-name="Layer 1" viewBox="0 0 24 24" width="512" height="512"><path d="M12,16a4,4,0,1,1,4-4A4,4,0,0,1,12,16ZM5.683,16H1a1,1,0,0,1-1-1A6.022,6.022,0,0,1,5.131,9.084a1,1,0,0,1,1.1,1.266A6.009,6.009,0,0,0,6,12a5.937,5.937,0,0,0,.586,2.57,1,1,0,0,1-.9,1.43ZM17,24H7a1,1,0,0,1-1-1,6,6,0,0,1,12,0A1,1,0,0,1,17,24ZM18,8a4,4,0,1,1,4-4A4,4,0,0,1,18,8ZM6,8a4,4,0,1,1,4-4A4,4,0,0,1,6,8Zm17,8H18.317a1,1,0,0,1-.9-1.43A5.937,5.937,0,0,0,18,12a6.009,6.009,0,0,0-.236-1.65,1,1,0,0,1,1.105-1.266A6.022,6.022,0,0,1,24,15,1,1,0,0,1,23,16Z"/></svg>

+ 2 - 0
app/src/main/assets/themes/Default/icons/wind.svg

@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" id="Layer_1" data-name="Layer 1" viewBox="0 0 24 24" width="512" height="512"><path d="M0,12a1,1,0,0,1,1-1H7a1,1,0,0,1,0,2H1A1,1,0,0,1,0,12Zm20.915-.894A5,5,0,1,0,12,8a1,1,0,0,0,2,0,3,3,0,1,1,3,3H11a1,1,0,0,0,0,2h9a2,2,0,0,1,2,2c-.009,2.337-3.281,2.648-4.057.667a1,1,0,0,0-1.886.666C17.615,20.415,23.952,19.579,24,15A4.007,4.007,0,0,0,20.915,11.106ZM11,16H1a1,1,0,0,0,0,2H11a2,2,0,0,1,2,2c-.009,2.337-3.281,2.648-4.057.667a1,1,0,1,0-1.886.666C8.615,25.415,14.952,24.579,15,20A4,4,0,0,0,11,16ZM1,8H7a4,4,0,0,0,4-4C10.952-.581,4.613-1.414,3.057,2.667a1,1,0,0,0,1.886.666C5.72,1.351,8.991,1.663,9,4A2,2,0,0,1,7,6H1A1,1,0,0,0,1,8Z"/></svg>

+ 4 - 0
app/src/main/assets/themes/Default/icons/workflow-alt.svg

@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" id="Layer_1" data-name="Layer 1" viewBox="0 0 24 24">
+  <path d="m20.5,15.121v-6.357c.392-.142.762-.361,1.076-.675l1.564-1.564c1.145-1.145,1.145-3.008,0-4.152l-1.564-1.564c-1.145-1.144-3.006-1.145-4.152,0h0s-1.563,1.565-1.563,1.565c-.314.314-.533.684-.675,1.076h-6.322C8.387,1.475,6.618,0,4.5,0,2.019,0,0,2.018,0,4.5c0,1.953,1.258,3.602,3,4.224v7.277h-.2c-1.544,0-2.8,1.256-2.8,2.8v2.399c0,1.544,1.256,2.801,2.8,2.801h2.4c1.544,0,2.8-1.257,2.8-2.801v-2.399c0-1.544-1.256-2.8-2.8-2.8h-.2v-7.051c1.927-.217,3.492-1.635,3.895-3.501h6.29c.142.392.361.762.675,1.076l1.563,1.564c.314.313.684.533,1.076.674v6.358c-2,.457-3.5,2.242-3.5,4.379,0,2.481,2.019,4.5,4.5,4.5s4.5-2.019,4.5-4.5c0-2.137-1.5-3.922-3.5-4.379Z"/>
+</svg>

+ 0 - 44
app/src/main/java/com/grkj/iscs_mc/FirstFragment.kt

@@ -1,44 +0,0 @@
-package com.grkj.iscs_mc
-
-import android.os.Bundle
-import androidx.fragment.app.Fragment
-import android.view.LayoutInflater
-import android.view.View
-import android.view.ViewGroup
-import androidx.navigation.fragment.findNavController
-import com.grkj.iscs_mc.databinding.FragmentFirstBinding
-
-/**
- * A simple [Fragment] subclass as the default destination in the navigation.
- */
-class FirstFragment : Fragment() {
-
-    private var _binding: FragmentFirstBinding? = null
-
-    // This property is only valid between onCreateView and
-    // onDestroyView.
-    private val binding get() = _binding!!
-
-    override fun onCreateView(
-        inflater: LayoutInflater, container: ViewGroup?,
-        savedInstanceState: Bundle?
-    ): View {
-
-        _binding = FragmentFirstBinding.inflate(inflater, container, false)
-        return binding.root
-
-    }
-
-    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
-        super.onViewCreated(view, savedInstanceState)
-
-        binding.buttonFirst.setOnClickListener {
-            findNavController().navigate(R.id.action_FirstFragment_to_SecondFragment)
-        }
-    }
-
-    override fun onDestroyView() {
-        super.onDestroyView()
-        _binding = null
-    }
-}

+ 149 - 0
app/src/main/java/com/grkj/iscs_mc/ISCSMCApplication.kt

@@ -0,0 +1,149 @@
+package com.grkj.iscs_mc
+
+import android.app.AlarmManager
+import android.app.Application
+import android.app.PendingIntent
+import android.content.Context
+import android.content.Intent
+import ch.qos.logback.classic.Level
+import com.drake.statelayout.StateConfig
+import com.grkj.data.common.EventConstants
+import com.grkj.data.di.LogicManager
+import com.grkj.data.local.database.DbReadyGate
+import com.grkj.iscs_mc.features.splash.activity.SplashActivity
+import com.grkj.shared.model.EventBean
+import com.grkj.shared.utils.ArcSoftUtil
+import com.grkj.shared.utils.i18n.I18nManager
+import com.grkj.shared.utils.i18n.LanguageCatalog
+import com.grkj.shared.utils.i18n.LanguageStore
+import com.grkj.shared.utils.i18n.source.AssetsI18nSource
+import com.grkj.shared.utils.i18n.source.FileI18nSource
+import com.grkj.ui_base.config.ISCSConfig
+import com.grkj.ui_base.utils.CommonUtils
+import com.kongzue.dialogx.DialogX
+import com.scwang.smart.refresh.footer.ClassicsFooter
+import com.scwang.smart.refresh.header.ClassicsHeader
+import com.scwang.smart.refresh.layout.SmartRefreshLayout
+import com.sik.sikcore.SIKCore
+import com.sik.sikcore.crash.GlobalCrashCatch
+import com.sik.sikcore.extension.toJson
+import com.sik.sikcore.log.LogUtils
+import com.sik.sikcore.thread.ThreadUtils
+import com.tencent.mmkv.MMKV
+import dagger.hilt.android.HiltAndroidApp
+import me.jessyan.autosize.AutoSizeConfig
+import org.greenrobot.eventbus.EventBus
+import org.greenrobot.eventbus.Subscribe
+import org.greenrobot.eventbus.ThreadMode
+import org.slf4j.Logger
+import org.slf4j.LoggerFactory
+
+/**
+ * 启动入口
+ */
+@HiltAndroidApp
+class ISCSMCApplication : Application() {
+    private val logger: Logger = LoggerFactory.getLogger(ISCSMCApplication::class.java)
+
+    /**
+     * 程序创建
+     */
+    override fun onCreate() {
+        super.onCreate()
+        DialogX.init(this)
+        SIKCore.init(this)
+        //todo 模拟器不支持
+        ArcSoftUtil.checkActiveStatus(this)
+        ArcSoftUtil.initEngine(this)
+        if (!EventBus.getDefault().isRegistered(this)) {
+            EventBus.getDefault().register(this)
+        }
+        GlobalCrashCatch.instance.init(this).setGlobalCrashHandlerListener {
+            logger.error("异常发生", it)
+            true
+        }
+        if (ISCSConfig.DEBUG) {
+            LogUtils.setGlobalLogLevel(Level.DEBUG)
+        } else {
+            LogUtils.setGlobalLogLevel(Level.INFO)
+        }
+        System.loadLibrary("sqlcipher")   // 新库必须手动加载
+        MMKV.initialize(this)
+        I18nManager.init(
+            defaultLocale = LanguageStore.resolveEffectiveLocale(this),
+            initialSources = arrayOf(
+                AssetsI18nSource(this, "i18n"),
+                FileI18nSource(this, "i18n")
+            ),
+            eagerLoad = true
+        )
+
+        // 建议:可提前刷新一下目录(不强制)
+        LanguageCatalog.refresh(this)
+
+        // 若“跟随系统”,监听系统语言变化
+        LanguageStore.registerSystemLocaleObserver(this)
+        AutoSizeConfig.getInstance().isCustomFragment = true
+        StateConfig.emptyLayout = com.grkj.ui_base.R.layout.layout_empty
+        ThreadUtils.runOnIO {
+            DbReadyGate.await()
+            LogicManager.init(this@ISCSMCApplication)
+        }
+    }
+
+    @Subscribe(threadMode = ThreadMode.MAIN)
+    open fun onEvent(event: EventBean<*>) {
+        when (event.code) {
+            EventConstants.EVENT_RESTART_APP -> {
+                scheduleRestart(this)
+            }
+        }
+    }
+
+    /**
+     * 计划重启
+     */
+    private fun scheduleRestart(context: Context) {
+        val restartIntent = Intent(context, SplashActivity::class.java).apply {
+            addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_NEW_TASK)
+        }
+        val pi = PendingIntent.getActivity(
+            context,
+            0,
+            restartIntent,
+            PendingIntent.FLAG_CANCEL_CURRENT or PendingIntent.FLAG_IMMUTABLE
+        )
+        val am = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
+        am.setExact(
+            AlarmManager.RTC,
+            System.currentTimeMillis() + 2000,
+            pi
+        )
+        Runtime.getRuntime().exit(0)
+    }
+
+    override fun onTerminate() {
+        if (EventBus.getDefault().isRegistered(this)) {
+            EventBus.getDefault().unregister(this)
+        }
+        super.onTerminate()
+    }
+
+    //static 代码段可以防止内存泄露
+    init {
+
+        //设置全局的Header构建器
+        SmartRefreshLayout.setDefaultRefreshHeaderCreator { context, layout ->
+            ClassicsHeader(context).apply {
+                this.setAccentColor(CommonUtils.getColor(com.grkj.ui_base.R.attr.colorTextPrimary))
+            }
+        }
+
+        //设置全局的Footer构建器
+        SmartRefreshLayout.setDefaultRefreshFooterCreator { context, p1 ->
+            ClassicsFooter(context).apply {
+                this.setAccentColor(CommonUtils.getColor(com.grkj.ui_base.R.attr.colorTextPrimary))
+            }
+        }
+    }
+}

+ 0 - 59
app/src/main/java/com/grkj/iscs_mc/MainActivity.kt

@@ -1,59 +0,0 @@
-package com.grkj.iscs_mc
-
-import android.os.Bundle
-import com.google.android.material.snackbar.Snackbar
-import androidx.appcompat.app.AppCompatActivity
-import androidx.navigation.findNavController
-import androidx.navigation.ui.AppBarConfiguration
-import androidx.navigation.ui.navigateUp
-import androidx.navigation.ui.setupActionBarWithNavController
-import android.view.Menu
-import android.view.MenuItem
-import com.grkj.iscs_mc.databinding.ActivityMainBinding
-
-class MainActivity : AppCompatActivity() {
-
-    private lateinit var appBarConfiguration: AppBarConfiguration
-    private lateinit var binding: ActivityMainBinding
-
-    override fun onCreate(savedInstanceState: Bundle?) {
-        super.onCreate(savedInstanceState)
-
-        binding = ActivityMainBinding.inflate(layoutInflater)
-        setContentView(binding.root)
-
-        setSupportActionBar(binding.toolbar)
-
-        val navController = findNavController(R.id.nav_host_fragment_content_main)
-        appBarConfiguration = AppBarConfiguration(navController.graph)
-        setupActionBarWithNavController(navController, appBarConfiguration)
-
-        binding.fab.setOnClickListener { view ->
-            Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
-                .setAction("Action", null)
-                .setAnchorView(R.id.fab).show()
-        }
-    }
-
-    override fun onCreateOptionsMenu(menu: Menu): Boolean {
-        // Inflate the menu; this adds items to the action bar if it is present.
-        menuInflater.inflate(R.menu.menu_main, menu)
-        return true
-    }
-
-    override fun onOptionsItemSelected(item: MenuItem): Boolean {
-        // Handle action bar item clicks here. The action bar will
-        // automatically handle clicks on the Home/Up button, so long
-        // as you specify a parent activity in AndroidManifest.xml.
-        return when (item.itemId) {
-            R.id.action_settings -> true
-            else -> super.onOptionsItemSelected(item)
-        }
-    }
-
-    override fun onSupportNavigateUp(): Boolean {
-        val navController = findNavController(R.id.nav_host_fragment_content_main)
-        return navController.navigateUp(appBarConfiguration)
-                || super.onSupportNavigateUp()
-    }
-}

+ 0 - 44
app/src/main/java/com/grkj/iscs_mc/SecondFragment.kt

@@ -1,44 +0,0 @@
-package com.grkj.iscs_mc
-
-import android.os.Bundle
-import androidx.fragment.app.Fragment
-import android.view.LayoutInflater
-import android.view.View
-import android.view.ViewGroup
-import androidx.navigation.fragment.findNavController
-import com.grkj.iscs_mc.databinding.FragmentSecondBinding
-
-/**
- * A simple [Fragment] subclass as the second destination in the navigation.
- */
-class SecondFragment : Fragment() {
-
-    private var _binding: FragmentSecondBinding? = null
-
-    // This property is only valid between onCreateView and
-    // onDestroyView.
-    private val binding get() = _binding!!
-
-    override fun onCreateView(
-        inflater: LayoutInflater, container: ViewGroup?,
-        savedInstanceState: Bundle?
-    ): View {
-
-        _binding = FragmentSecondBinding.inflate(inflater, container, false)
-        return binding.root
-
-    }
-
-    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
-        super.onViewCreated(view, savedInstanceState)
-
-        binding.buttonSecond.setOnClickListener {
-            findNavController().navigate(R.id.action_SecondFragment_to_FirstFragment)
-        }
-    }
-
-    override fun onDestroyView() {
-        super.onDestroyView()
-        _binding = null
-    }
-}

+ 58 - 0
app/src/main/java/com/grkj/iscs_mc/features/login/activity/LoginActivity.kt

@@ -0,0 +1,58 @@
+package com.grkj.iscs_mc.features.login.activity
+
+import android.view.InputDevice
+import android.view.KeyEvent
+import androidx.activity.viewModels
+import com.grkj.iscs_mc.R
+import com.grkj.iscs_mc.databinding.ActivityLoginBinding
+import com.grkj.iscs_mc.features.login.adapter.TwoFragmentAdapter
+import com.grkj.iscs_mc.features.login.viewmodel.LoginViewModel
+import com.grkj.shared.utils.extension.toByteArrays
+import com.grkj.shared.utils.extension.toHexStrings
+import com.grkj.ui_base.base.BaseActivity
+import com.grkj.ui_base.utils.event.RFIDCardReadEvent
+import dagger.hilt.android.AndroidEntryPoint
+
+/**
+ * 登录界面
+ */
+@AndroidEntryPoint
+class LoginActivity : BaseActivity<ActivityLoginBinding>() {
+    private var cardNo = ""
+
+    override fun getLayoutId(): Int {
+        return R.layout.activity_login
+    }
+
+    override fun initView() {
+        binding.vp2.adapter = TwoFragmentAdapter(this)
+        binding.vp2.offscreenPageLimit = 1 // 只两页,提前缓存,不卡顿
+    }
+
+    override fun onStop() {
+        super.onStop()
+        cardNo = ""
+    }
+
+    override fun dispatchKeyEvent(event: KeyEvent): Boolean {
+        if (event.action == KeyEvent.ACTION_UP && event.source == InputDevice.SOURCE_KEYBOARD) {
+            // 检测到回车开始处理
+            if (event.keyCode == 66) {
+                logger.info("Swipe card login Origin: $cardNo")
+                try {
+                    cardNo = cardNo.toLong().toByteArrays().toHexStrings(false)
+                    logger.info("Swipe card login: $cardNo")
+                    RFIDCardReadEvent.sendRFIDCardReadEvent(cardNo)
+                    // 重置cardNo
+                    cardNo = ""
+                } catch (e: Exception) {
+                    cardNo = ""
+                    logger.info("读卡失败: ${e.toString()}")
+                }
+                return super.dispatchKeyEvent(event)
+            }
+            cardNo += event.keyCharacterMap.getDisplayLabel(event.keyCode)
+        }
+        return super.dispatchKeyEvent(event)
+    }
+}

+ 13 - 0
app/src/main/java/com/grkj/iscs_mc/features/login/adapter/TwoFragmentAdapter.kt

@@ -0,0 +1,13 @@
+package com.grkj.iscs_mc.features.login.adapter
+
+import androidx.fragment.app.Fragment
+import androidx.fragment.app.FragmentActivity
+import androidx.viewpager2.adapter.FragmentStateAdapter
+import com.grkj.iscs_mc.features.login.fragment.LoginFragment
+import com.grkj.iscs_mc.features.login.fragment.MaterialShowFragment
+
+class TwoFragmentAdapter(activity: FragmentActivity) : FragmentStateAdapter(activity) {
+    override fun getItemCount() = 2
+    override fun createFragment(position: Int): Fragment =
+        if (position == 0) LoginFragment() else MaterialShowFragment()
+}

+ 56 - 0
app/src/main/java/com/grkj/iscs_mc/features/login/dialog/ChangeLangDialog.kt

@@ -0,0 +1,56 @@
+package com.grkj.iscs_mc.features.login.dialog
+
+import android.view.View
+import com.drake.brv.utils.linear
+import com.drake.brv.utils.setup
+import com.grkj.iscs_mc.R
+import com.grkj.iscs_mc.databinding.DialogChangeLangBinding
+import com.grkj.iscs_mc.databinding.ItemLangBinding
+import com.grkj.shared.utils.i18n.LanguageEntry
+import com.grkj.shared.utils.i18n.LocaleUtils
+import com.kongzue.dialogx.dialogs.CustomDialog
+import com.kongzue.dialogx.interfaces.OnBindView
+
+/**
+ * 修改语言弹窗
+ */
+class ChangeLangDialog(
+    private val canChangeLang: List<LanguageEntry>,
+    private val targetRegion: String?,
+    private val onConfirm: (LanguageEntry) -> Unit
+) : OnBindView<CustomDialog>(R.layout.dialog_change_lang) {
+
+    override fun onBind(dialog: CustomDialog, v: View) {
+        val binding = DialogChangeLangBinding.bind(v)
+        binding.listRv.linear().setup {
+            addType<LanguageEntry>(R.layout.item_lang)
+            onBind {
+                val item = getModel<LanguageEntry>()
+                val itemBinding = getBinding<ItemLangBinding>()
+                itemBinding.lang.setOnCheckedChangeListener(null)
+                itemBinding.lang.isChecked = item.isSelected
+                itemBinding.lang.text = LocaleUtils.buildDisplayLabel(item, targetRegion)
+                itemBinding.lang.setOnCheckedChangeListener { _, checked ->
+                    if (!checked) return@setOnCheckedChangeListener   // ← 只响应“被选中”的事件
+                    canChangeLang.forEach { it.isSelected = (it.tag == item.tag) }
+                    notifyDataSetChanged()
+                }
+            }
+        }.models = canChangeLang
+
+        binding.switchBtn.setOnClickListener {
+            canChangeLang.firstOrNull { it.isSelected }?.let(onConfirm)
+            dialog.dismiss()
+        }
+    }
+
+    companion object {
+        fun show(
+            canChangeLang: List<LanguageEntry>,
+            targetRegion: String?,
+            onConfirm: (LanguageEntry) -> Unit
+        ) {
+            CustomDialog.show(ChangeLangDialog(canChangeLang, targetRegion, onConfirm))
+        }
+    }
+}

+ 194 - 0
app/src/main/java/com/grkj/iscs_mc/features/login/dialog/LoginDialog.kt

@@ -0,0 +1,194 @@
+package com.grkj.iscs_mc.features.login.dialog
+
+import android.graphics.Bitmap
+import android.view.View
+import androidx.lifecycle.LifecycleOwner
+import com.grkj.data.enums.LoginResultEnum
+import com.grkj.data.hardware.fingerprint.FingerprintUtil
+import com.grkj.iscs_mc.R
+import com.grkj.iscs_mc.databinding.DialogLoginBinding
+import com.grkj.iscs_mc.features.login.viewmodel.LoginViewModel
+import com.grkj.shared.utils.ArcSoftUtil
+import com.grkj.shared.utils.ArcSoftUtil.inDetecting
+import com.grkj.ui_base.skin.loadSkinIcon
+import com.grkj.ui_base.utils.CommonUtils
+import com.grkj.ui_base.utils.event.LoadingEvent
+import com.kongzue.dialogx.dialogs.CustomDialog
+import com.kongzue.dialogx.dialogs.PopTip
+import com.kongzue.dialogx.interfaces.DialogLifecycleCallback
+import com.kongzue.dialogx.interfaces.OnBindView
+import com.sik.sikandroid.activity.ActivityTracker
+import com.sik.sikcore.SIKCore
+import com.sik.sikcore.extension.setDebouncedClickListener
+import com.sik.sikcore.thread.ThreadUtils
+import com.sik.sikimage.ImageConvertUtils
+
+/**
+ * 登录弹窗
+ */
+class LoginDialog(
+    private var lifecycleOwner: LifecycleOwner,
+    private var viewModel: LoginViewModel,
+    private var callBack: ((LoginResultEnum) -> Unit)? = null
+) : OnBindView<CustomDialog>(R.layout.dialog_login) {
+
+    private var cardNo = ""
+    private var mLoginType = 3 // 0:人脸 1:指纹 2:工卡 3:账号
+    private var inFaceChecking: Boolean = false
+    private val mPairList = mutableListOf(
+        Pair(
+            CommonUtils.getStr("please_scan_face"), "face-id-svgrepo-com.svg"
+        ), Pair(
+            CommonUtils.getStr("please_scan_fingerprint"), "fingerprint.svg"
+        ), Pair(
+            CommonUtils.getStr("please_swipe_card"), "icon_login_menu_card.png"
+        )
+    )
+
+    private lateinit var mBinding: DialogLoginBinding
+
+    override fun onBind(customDialog: CustomDialog, contentView: View) {
+        mBinding = DialogLoginBinding.bind(contentView)
+        customDialog?.setMaskColor(CommonUtils.getColor(com.grkj.ui_base.R.attr.scrim))
+        customDialog.setDialogLifecycleCallback(object : DialogLifecycleCallback<CustomDialog>() {
+            override fun onDismiss(dialog: CustomDialog?) {
+                ArcSoftUtil.stop()
+                super.onDismiss(dialog)
+            }
+        })
+        mBinding.tvLogin.setDebouncedClickListener {
+            if (mBinding.etAccount.text.toString().isEmpty()) {
+                PopTip.tip(CommonUtils.getStr("please_input_account"))
+                return@setDebouncedClickListener
+            }
+            if (mBinding.etPassword.text.toString().isEmpty()) {
+                PopTip.tip(CommonUtils.getStr("please_input_password"))
+                return@setDebouncedClickListener
+            }
+            LoadingEvent.sendLoadingEvent(
+                CommonUtils.getStr("doing_login"), true
+            )
+            viewModel.loginWithAccount(
+                mBinding.etAccount.text.toString(), mBinding.etPassword.text.toString()
+            ).observe(lifecycleOwner) {
+                callBack?.invoke(it)
+            }
+        }
+        customDialog.setDialogLifecycleCallback(object : DialogLifecycleCallback<CustomDialog>() {
+            override fun onDismiss(dialog: CustomDialog?) {
+                when (mLoginType) {
+                    0 -> {
+                        ArcSoftUtil.stop()
+                    }
+
+                    1 -> {
+                        FingerprintUtil.stop()
+                    }
+
+                    3 -> {
+                        mBinding.etAccount.text?.clear()
+                        mBinding.etPassword.text?.clear()
+                    }
+                }
+                super.onDismiss(dialog)
+            }
+        })
+        mBinding.tvCancel.setDebouncedClickListener { customDialog.dismiss() }
+        if (mLoginType == 3) {
+            mBinding.llAccountContainer.visibility = View.VISIBLE
+            mBinding.llEasyContainer.visibility = View.GONE
+        } else {
+            mBinding.llAccountContainer.visibility = View.GONE
+            mBinding.llEasyContainer.visibility = View.VISIBLE
+            mBinding.ivIcon.loadSkinIcon(mPairList[mLoginType].second)
+            mBinding.tvTip.text = mPairList[mLoginType].first
+            when (mLoginType) {
+                0 -> {
+                    if (!ArcSoftUtil.isActivated) {
+                        PopTip.tip(
+                            CommonUtils.getStr("face_can_not_process").toString()
+                        )
+                    } else {
+                        startFace()
+                    }
+                }
+
+                1 -> {
+                    FingerprintUtil.init(SIKCore.getApplication())
+                    FingerprintUtil.start()
+                    FingerprintUtil.setScanListener(object : FingerprintUtil.OnScanListener {
+                        override fun onScan(bitmap: Bitmap) {
+                            LoadingEvent.sendLoadingEvent(
+                                CommonUtils.getStr("doing_login"), true
+                            )
+                            viewModel.loginWithFingerprint(
+                                ImageConvertUtils.bitmapToBase64(
+                                    bitmap
+                                ).toString()
+                            ).observe(lifecycleOwner) { isSuccess ->
+                                    LoadingEvent.sendLoadingEvent()
+                                    callBack?.invoke(isSuccess)
+                                }
+                        }
+                    })
+                }
+            }
+        }
+    }
+
+    fun showByType(loginType: Int) {
+        this.mLoginType = loginType
+    }
+
+    companion object {
+        /**
+         * 根据类型显示弹框
+         *
+         * @param loginType 0:人脸 1:指纹 2:工卡 3:账号
+         */
+        @JvmStatic
+        fun show(
+            lifecycleOwner: LifecycleOwner,
+            viewModel: LoginViewModel,
+            loginType: Int,
+            callBack: ((LoginResultEnum) -> Unit)?
+        ) {
+            CustomDialog.show(LoginDialog(lifecycleOwner, viewModel, callBack).apply {
+                showByType(loginType)
+            })
+        }
+    }
+
+
+    private fun startFace() {
+        inDetecting = false
+        ActivityTracker.getCurrentActivity()?.let { context ->
+            ArcSoftUtil.checkCamera(
+                context.windowManager, mBinding.preview!!
+            ) { bitmap, userId ->
+                viewModel.loginWithUserId(userId).observe(lifecycleOwner) {
+                    if (it == LoginResultEnum.FACE_VERIFY_FAILED) {
+                        viewModel.loginWithFace(ImageConvertUtils.bitmapToBase64(bitmap).toString())
+                            .observe(lifecycleOwner) {
+                                if (it == LoginResultEnum.FACE_VERIFY_FAILED) {
+                                    ThreadUtils.runOnMainDelayed(1000) {
+                                        inDetecting = false
+                                        inFaceChecking = false
+                                    }
+                                } else {
+                                    ArcSoftUtil.stop()
+                                }
+                                callBack?.invoke(it)
+                            }
+                    } else {
+                        ArcSoftUtil.stop()
+                        callBack?.invoke(it)
+                    }
+                }
+                LoadingEvent.sendLoadingEvent(
+                    CommonUtils.getStr("face_detected_do_login"), true
+                )
+            }
+        }
+    }
+}

+ 13 - 0
app/src/main/java/com/grkj/iscs_mc/features/login/entity/LoginMenuEntity.kt

@@ -0,0 +1,13 @@
+package com.grkj.iscs_mc.features.login.entity
+
+/**
+ * 登录菜单实体
+ */
+data class LoginMenuEntity(
+    val menuIcon: String,
+    val menuTint: Int,
+    val menuBg: Int,
+    val menuText: String,
+    val needTip: Boolean = false,
+    val loginType: Int
+)

+ 366 - 0
app/src/main/java/com/grkj/iscs_mc/features/login/fragment/LoginFragment.kt

@@ -0,0 +1,366 @@
+package com.grkj.iscs_mc.features.login.fragment
+
+import android.content.Intent
+import android.content.res.ColorStateList
+import android.graphics.Bitmap
+import android.widget.LinearLayout
+import androidx.core.view.isVisible
+import androidx.core.widget.ImageViewCompat
+import androidx.fragment.app.viewModels
+import com.drake.brv.BindingAdapter
+import com.drake.brv.annotaion.DividerOrientation
+import com.drake.brv.utils.divider
+import com.drake.brv.utils.grid
+import com.drake.brv.utils.linear
+import com.drake.brv.utils.models
+import com.drake.brv.utils.setup
+import com.grkj.data.common.EventConstants
+import com.grkj.data.common.MainDomainData
+import com.grkj.data.enums.LoginModeEnum
+import com.grkj.data.enums.LoginResultEnum
+import com.grkj.data.hardware.fingerprint.FingerprintUtil
+import com.grkj.iscs_mc.features.login.dialog.ChangeLangDialog
+import com.grkj.iscs_mc.R
+import com.grkj.iscs_mc.databinding.FragmentLoginBinding
+import com.grkj.iscs_mc.databinding.ItemLoginMethodBinding
+import com.grkj.iscs_mc.features.login.dialog.LoginDialog
+import com.grkj.iscs_mc.features.login.entity.LoginMenuEntity
+import com.grkj.iscs_mc.features.login.viewmodel.LoginViewModel
+import com.grkj.iscs_mc.features.manage.activity.ManageActivity
+import com.grkj.iscs_mc.features.material_exchange.activity.MaterialExchangeActivity
+import com.grkj.shared.model.EventBean
+import com.grkj.shared.utils.i18n.I18nManager
+import com.grkj.shared.utils.i18n.LanguageEntry
+import com.grkj.shared.utils.i18n.LanguageRegistry
+import com.grkj.shared.utils.i18n.LanguageStore
+import com.grkj.ui_base.base.BaseFragment
+import com.grkj.ui_base.skin.loadSkinIcon
+import com.grkj.ui_base.utils.CommonUtils
+import com.grkj.ui_base.utils.changeBgTint
+import com.grkj.ui_base.utils.event.LoadingEvent
+import com.grkj.ui_base.utils.event.RFIDCardReadEvent
+import com.grkj.ui_base.utils.extension.getAppVersionName
+import com.sik.sikcore.extension.setDebouncedClickListener
+import com.sik.sikimage.ImageConvertUtils
+import dagger.hilt.android.AndroidEntryPoint
+import java.util.Locale
+
+/**
+ * 登录界面
+ */
+@AndroidEntryPoint
+class LoginFragment : BaseFragment<FragmentLoginBinding>() {
+    private val viewModel: LoginViewModel by viewModels()
+
+    //登录方式列表
+    private val loginMenuList: MutableList<LoginMenuEntity> = mutableListOf()
+
+    /**
+     * 登录模式切换
+     */
+    private var loginMode = LoginModeEnum.USER_MODE
+    private val changeModeClickTimes = 5
+    private var currentChangeModeClickTimes = 0
+    private var currentClickTime = 0L
+
+    override fun getLayoutId(): Int {
+        return R.layout.fragment_login
+    }
+
+    override fun initView() {
+        binding.chipLang.text = I18nManager.locale.value.toLanguageTag()
+        binding.chipLang.setOnClickListener {
+            val targetRegion = "US" // 自己决定用什么;也可以是 "CN" / 配置项 / 服务器下发
+            val entries = LanguageRegistry.entriesFromSources(targetRegion)
+            ChangeLangDialog.show(
+                canChangeLang = entries, targetRegion = targetRegion
+            ) { selected: LanguageEntry ->
+                // 切换并持久化(MMKV),I18nManager 会热更新
+                LanguageStore.setExplicit(Locale.forLanguageTag(selected.tag))
+
+                // 芯片文本友好化(可选)
+                binding.chipLang.text = I18nManager.locale.value.toLanguageTag()
+                requireActivity().recreate()
+            }
+        }
+        binding.loginTypeRv.apply {
+            if (isLandscape()) {
+                linear(orientation = LinearLayout.HORIZONTAL)
+                divider(
+                    com.grkj.ui_base.R.drawable.common_divider_large_space_grid_land,
+                    DividerOrientation.GRID
+                )
+            } else {
+                grid(2)
+                divider(
+                    com.grkj.ui_base.R.drawable.common_divider_large_space_grid,
+                    DividerOrientation.GRID
+                )
+            }
+        }.setup {
+            addType<LoginMenuEntity>(R.layout.item_login_method)
+            onBind {
+                onLoginMenuBinding(this)
+            }
+        }
+        binding.version.setOnClickListener {
+            if (System.currentTimeMillis() - currentClickTime > 500) {
+                currentClickTime = System.currentTimeMillis()
+                currentChangeModeClickTimes = 1
+            } else {
+                currentChangeModeClickTimes++
+                if (currentChangeModeClickTimes >= changeModeClickTimes) {
+                    if (loginMode == LoginModeEnum.USER_MODE) {
+                        loginMode = LoginModeEnum.ADMINISTRATOR_MODE
+                    } else {
+                        loginMode = LoginModeEnum.USER_MODE
+                    }
+                }
+            }
+            binding.modeTip.isVisible = loginMode == LoginModeEnum.ADMINISTRATOR_MODE
+        }
+    }
+
+    private fun BindingAdapter.BindingViewHolder.onLoginMenuBinding(holder: BindingAdapter.BindingViewHolder) {
+        val itemBinding = holder.getBinding<ItemLoginMethodBinding>()
+        val item = holder.getModel<LoginMenuEntity>()
+        itemBinding.loginTipV.isVisible = item.needTip
+        itemBinding.loginMethodTv.text = item.menuText
+        itemBinding.loginMethodIv.loadSkinIcon(item.menuIcon)
+        ImageViewCompat.setImageTintList(
+            itemBinding.loginMethodIv, ColorStateList.valueOf(item.menuTint)
+        )
+        itemBinding.loginContainer.changeBgTint(item.menuBg)
+        holder.itemView.setDebouncedClickListener {
+            LoginDialog.show(this@LoginFragment, viewModel, item.loginType) {
+                hideLoading()
+                when (it) {
+                    LoginResultEnum.FINGERPRINTER_VERIFY_SUCCESS -> {
+                        showToast(CommonUtils.getStr("fingerprint_login_success"))
+                        if (loginMode == LoginModeEnum.USER_MODE) {
+                            startActivity(
+                                Intent(
+                                    requireContext(), MaterialExchangeActivity::class.java
+                                )
+                            )
+                        } else {
+                            startActivity(
+                                Intent(
+                                    requireContext(), ManageActivity::class.java
+                                )
+                            )
+                        }
+                        requireActivity().finish()
+                    }
+
+                    LoginResultEnum.FINGERPRINTER_VERIFY_FAILED -> showToast(
+                        CommonUtils.getStr("fingerprint_login_failed")
+                    )
+
+                    LoginResultEnum.FACE_VERIFY_SUCCESS -> {
+                        showToast(CommonUtils.getStr("face_login_success"))
+                        if (loginMode == LoginModeEnum.USER_MODE) {
+                            startActivity(
+                                Intent(
+                                    requireContext(), MaterialExchangeActivity::class.java
+                                )
+                            )
+                        } else {
+                            startActivity(
+                                Intent(
+                                    requireContext(), ManageActivity::class.java
+                                )
+                            )
+                        }
+                        requireActivity().finish()
+                    }
+
+                    LoginResultEnum.FACE_VERIFY_FAILED -> showToast(
+                        CommonUtils.getStr("face_login_failed")
+                    )
+
+                    LoginResultEnum.USERNAME_PASSWORD_LOGIN_SUCCESS -> {
+                        showToast(
+                            CommonUtils.getStr("username_passowrd_login_success")
+                        )
+                        if (loginMode == LoginModeEnum.USER_MODE) {
+                            startActivity(
+                                Intent(
+                                    requireContext(), MaterialExchangeActivity::class.java
+                                )
+                            )
+                        } else {
+                            startActivity(
+                                Intent(
+                                    requireContext(), ManageActivity::class.java
+                                )
+                            )
+                        }
+                        requireActivity().finish()
+                    }
+
+                    LoginResultEnum.USERNAME_OR_PASSWORD_ERROR -> showToast(
+                        CommonUtils.getStr("username_or_password_error")
+                    )
+
+                    LoginResultEnum.USERNAME_PASSWORD_NOT_EXISTS -> showToast(
+                        CommonUtils.getStr("username_password_not_exists")
+                    )
+
+                    LoginResultEnum.JOB_CARD_LOGIN_SUCCESS -> {
+                        showToast(CommonUtils.getStr("job_card_login_success"))
+                        if (loginMode == LoginModeEnum.USER_MODE) {
+                            startActivity(
+                                Intent(
+                                    requireContext(), MaterialExchangeActivity::class.java
+                                )
+                            )
+                        } else {
+                            startActivity(
+                                Intent(
+                                    requireContext(), ManageActivity::class.java
+                                )
+                            )
+                        }
+                        requireActivity().finish()
+                    }
+
+                    LoginResultEnum.JOB_CARD_LOGIN_FAILED -> showToast(
+                        CommonUtils.getStr("job_card_login_failed")
+                    )
+                }
+            }
+        }
+    }
+
+    override fun initData() {
+        super.initData()
+        binding.version.text = requireContext().getAppVersionName()
+        loginMenuList.apply {
+            add(
+                LoginMenuEntity(
+                    "face-id-svgrepo-com.svg",
+                    CommonUtils.getColor(com.grkj.ui_base.R.attr.colorWhite),
+                    CommonUtils.getColor(com.grkj.ui_base.R.attr.colorFaceLogin),
+                    CommonUtils.getStr("face_login"),
+                    false,
+                    0
+                )
+            )
+            add(
+                LoginMenuEntity(
+                    "icon_login_menu_password.png",
+                    CommonUtils.getColor(com.grkj.ui_base.R.attr.colorWhite),
+                    CommonUtils.getColor(com.grkj.ui_base.R.attr.colorUserLogin),
+                    CommonUtils.getStr("account_login"),
+                    false,
+                    3
+                )
+            )
+            add(
+                LoginMenuEntity(
+                    "fingerprint.svg",
+                    CommonUtils.getColor(com.grkj.ui_base.R.attr.colorWhite),
+                    CommonUtils.getColor(com.grkj.ui_base.R.attr.colorFingerprint),
+                    CommonUtils.getStr("fingerprint_login"),
+                    true,
+                    1
+                )
+            )
+            add(
+                LoginMenuEntity(
+                    "icon_login_menu_card.png",
+                    CommonUtils.getColor(com.grkj.ui_base.R.attr.colorWhite),
+                    CommonUtils.getColor(com.grkj.ui_base.R.attr.colorCardLogin),
+                    CommonUtils.getStr("card_login"),
+                    true,
+                    2
+                )
+            )
+        }
+        binding.loginTypeRv.models = loginMenuList
+    }
+
+    override fun onResume() {
+        super.onResume()
+        //todo 自动注入超管账号
+        viewModel.insertAdminAccount().observe(this) {}
+        MainDomainData.clear()
+        FingerprintUtil.init(requireContext())
+        FingerprintUtil.start()
+        FingerprintUtil.setScanListener(object : FingerprintUtil.OnScanListener {
+            override fun onScan(bitmap: Bitmap) {
+                LoadingEvent.sendLoadingEvent(
+                    CommonUtils.getStr("doing_login"), true
+                )
+                viewModel.loginWithFingerprint(
+                    ImageConvertUtils.bitmapToBase64(bitmap).toString()
+                ).observe(this@LoginFragment) { isSuccess ->
+                    LoadingEvent.sendLoadingEvent()
+                    if (isSuccess == LoginResultEnum.FINGERPRINTER_VERIFY_SUCCESS) {
+                        showToast(CommonUtils.getStr("fingerprint_login_success"))
+                        if (loginMode == LoginModeEnum.USER_MODE) {
+                            startActivity(
+                                Intent(
+                                    requireContext(), MaterialExchangeActivity::class.java
+                                )
+                            )
+                        } else {
+                            startActivity(
+                                Intent(
+                                    requireContext(), ManageActivity::class.java
+                                )
+                            )
+                        }
+                        requireActivity().finish()
+                    } else {
+                        showToast(CommonUtils.getStr("fingerprint_login_failed"))
+                    }
+                }
+            }
+        })
+    }
+
+    override fun onStop() {
+        super.onStop()
+        FingerprintUtil.stop()
+    }
+
+    override fun onEvent(event: EventBean<Any>) {
+        super.onEvent(event)
+        when (event.code) {
+            EventConstants.EVENT_RFID_CARD_READ -> {
+                val cardNo = (event.data as RFIDCardReadEvent).rfidNo
+                LoadingEvent.sendLoadingEvent(
+                    CommonUtils.getStr("doing_login"), true
+                )
+                viewModel.loginWithCard(cardNo).observe(this) { isSuccess ->
+                    LoadingEvent.sendLoadingEvent()
+                    if (isSuccess == LoginResultEnum.JOB_CARD_LOGIN_SUCCESS) {
+                        showToast(
+                            CommonUtils.getStr("job_card_login_success")
+                        )
+                        if (loginMode == LoginModeEnum.USER_MODE) {
+                            startActivity(
+                                Intent(
+                                    requireContext(), MaterialExchangeActivity::class.java
+                                )
+                            )
+                        } else {
+                            startActivity(
+                                Intent(
+                                    requireContext(), ManageActivity::class.java
+                                )
+                            )
+                        }
+                        requireActivity().finish()
+                    } else {
+                        showToast(
+                            CommonUtils.getStr("job_card_login_failed")
+                        )
+                    }
+                }
+            }
+        }
+    }
+}

+ 20 - 0
app/src/main/java/com/grkj/iscs_mc/features/login/fragment/MaterialShowFragment.kt

@@ -0,0 +1,20 @@
+package com.grkj.iscs_mc.features.login.fragment
+
+import com.grkj.iscs_mc.R
+import com.grkj.iscs_mc.databinding.FragmentMaterialShowBinding
+import com.grkj.ui_base.base.BaseFragment
+import dagger.hilt.android.AndroidEntryPoint
+
+/**
+ * 物资展示界面
+ */
+@AndroidEntryPoint
+class MaterialShowFragment : BaseFragment<FragmentMaterialShowBinding>() {
+    override fun getLayoutId(): Int {
+        return R.layout.fragment_material_show
+    }
+
+    override fun initView() {
+
+    }
+}

+ 110 - 0
app/src/main/java/com/grkj/iscs_mc/features/login/viewmodel/LoginViewModel.kt

@@ -0,0 +1,110 @@
+package com.grkj.iscs_mc.features.login.viewmodel
+
+import androidx.lifecycle.LiveData
+import androidx.lifecycle.liveData
+import com.grkj.data.domain.logic.IUserLogic
+import com.grkj.data.enums.LoginResultEnum
+import com.grkj.shared.utils.ArcSoftUtil
+import com.grkj.ui_base.base.BaseViewModel
+import com.sik.sikcore.extension.file
+import dagger.hilt.android.lifecycle.HiltViewModel
+import kotlinx.coroutines.Dispatchers
+import javax.inject.Inject
+
+/**
+ * 登录界面模型
+ */
+@HiltViewModel
+class LoginViewModel @Inject constructor(
+    val userLogic: IUserLogic,
+) : BaseViewModel() {
+
+
+    /**
+     * 添加管理员账号
+     */
+    fun insertAdminAccount(
+        username: String = "admin", password: String = "123456"
+    ): LiveData<Boolean> {
+        return liveData(Dispatchers.IO) {
+            userLogic.addAdminUser(username, password)
+            emit(true)
+        }
+    }
+
+    /**
+     * 用户名登录
+     */
+    fun loginWithAccount(
+        username: String,
+        password: String,
+    ): LiveData<LoginResultEnum> {
+        return liveData(Dispatchers.IO) {
+            val loginSuccess = userLogic.loginWithAccount(username, password)
+            emit(loginSuccess)
+        }
+    }
+
+    /**
+     * 刷卡登录
+     */
+    fun loginWithCard(cardNo: String): LiveData<LoginResultEnum> {
+        return liveData(Dispatchers.IO) {
+            val loginSuccess = userLogic.loginWithCard(cardNo)
+            emit(loginSuccess)
+        }
+    }
+
+    /**
+     * 指纹登录
+     */
+    fun loginWithFingerprint(fingerprint: String): LiveData<LoginResultEnum> {
+        return liveData(Dispatchers.IO) {
+            val loginSuccess = userLogic.loginWithFingerprint(fingerprint)
+            emit(loginSuccess)
+        }
+    }
+
+    /**
+     * 人脸登录
+     */
+    fun loginWithFace(face: String): LiveData<LoginResultEnum> {
+        return liveData(Dispatchers.IO) {
+            val loginSuccess = userLogic.loginWithFace(face)
+            emit(loginSuccess)
+        }
+    }
+
+    /**
+     * 人脸登录
+     */
+    fun loginWithUserId(userId: Long?): LiveData<LoginResultEnum> {
+        return liveData(Dispatchers.IO) {
+            val loginSuccess = userLogic.loginWithUserId(userId)
+            emit(loginSuccess)
+        }
+    }
+
+    /**
+     * 退出登录
+     */
+    fun logout(): LiveData<Boolean> {
+        return liveData(Dispatchers.IO) {
+            val logoutSuccess = userLogic.logout()
+            emit(logoutSuccess)
+        }
+    }
+
+    /**
+     * 注册人脸特征
+     */
+    fun registerFaceFeature(): LiveData<Boolean> {
+        return liveData(Dispatchers.IO) {
+            val user = userLogic.getAllFaceData()
+            val userFaceData = user.filter { it.content.file().exists() }
+                .map { it.userId to it.content.file().readText() }
+            ArcSoftUtil.registerFace(userFaceData)
+            emit(true)
+        }
+    }
+}

+ 20 - 0
app/src/main/java/com/grkj/iscs_mc/features/manage/activity/ManageActivity.kt

@@ -0,0 +1,20 @@
+package com.grkj.iscs_mc.features.manage.activity
+
+import com.grkj.iscs_mc.R
+import com.grkj.iscs_mc.databinding.ActivityManageBinding
+import com.grkj.ui_base.base.BaseActivity
+import dagger.hilt.android.AndroidEntryPoint
+
+/**
+ * 管理界面
+ */
+@AndroidEntryPoint
+class ManageActivity : BaseActivity<ActivityManageBinding>() {
+    override fun getLayoutId(): Int {
+        return R.layout.activity_manage
+    }
+
+    override fun initView() {
+
+    }
+}

+ 20 - 0
app/src/main/java/com/grkj/iscs_mc/features/material_exchange/activity/MaterialExchangeActivity.kt

@@ -0,0 +1,20 @@
+package com.grkj.iscs_mc.features.material_exchange.activity
+
+import com.grkj.iscs_mc.R
+import com.grkj.iscs_mc.databinding.ActivityMaterialExchangeBinding
+import com.grkj.ui_base.base.BaseActivity
+import dagger.hilt.android.AndroidEntryPoint
+
+/**
+ * 物资取还
+ */
+@AndroidEntryPoint
+class MaterialExchangeActivity : BaseActivity<ActivityMaterialExchangeBinding>() {
+    override fun getLayoutId(): Int {
+        return R.layout.activity_material_exchange
+    }
+
+    override fun initView() {
+        
+    }
+}

+ 69 - 0
app/src/main/java/com/grkj/iscs_mc/features/splash/activity/SplashActivity.kt

@@ -0,0 +1,69 @@
+package com.grkj.iscs_mc.features.splash.activity
+
+import android.content.Intent
+import android.view.Gravity
+import androidx.lifecycle.lifecycleScope
+import com.grkj.data.local.database.BackupScheduler
+import com.grkj.data.local.database.DbReadyGate
+import com.grkj.data.local.database.ISCSDatabase
+import com.grkj.iscs_mc.R
+import com.grkj.iscs_mc.databinding.ActivitySplashBinding
+import com.grkj.iscs_mc.features.login.activity.LoginActivity
+import com.grkj.shared.config.Constants
+import com.grkj.ui_base.base.BaseActivity
+import com.kongzue.dialogx.DialogX
+import com.kongzue.dialogx.util.TextInfo
+import com.sik.sikandroid.permission.PermissionUtils
+import com.sik.sikcore.extension.getMMKVData
+import dagger.hilt.android.AndroidEntryPoint
+import dagger.hilt.android.HiltAndroidApp
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.launch
+
+@AndroidEntryPoint
+class SplashActivity : BaseActivity<ActivitySplashBinding>() {
+
+    override fun getLayoutId(): Int {
+        return R.layout.activity_splash
+    }
+
+    override fun initView() {
+        // 应用启动时按已存配置安排下一次(默认=每天 00:00)
+        BackupScheduler.applySaved(this)
+        val dialogXTextInfo = TextInfo()
+        val dialogXTitleTextInfo = TextInfo().apply {
+            isBold = true
+            gravity = Gravity.CENTER
+        }
+        dialogXTextInfo.fontSize = 18
+        dialogXTitleTextInfo.fontSize = 22
+        DialogX.popTextInfo = dialogXTextInfo
+        DialogX.buttonTextInfo = dialogXTextInfo
+        DialogX.tipTextInfo = dialogXTextInfo
+        DialogX.messageTextInfo = dialogXTextInfo
+        DialogX.menuTextInfo = dialogXTextInfo
+        DialogX.okButtonTextInfo = dialogXTextInfo
+        DialogX.titleTextInfo = dialogXTitleTextInfo
+        requestPermissionsIfNeeded(*Constants.needPermission) {
+            logger.info("授权结果:${it}")
+            if (it) {
+                PermissionUtils.requestAllFilesAccessPermission {
+                    logger.info("授权结果:${it}")
+                    if (it) {
+                        // 已有权限的话,直接预热:
+                        CoroutineScope(Dispatchers.IO).launch {
+                            // 触发构建 + 迁移 + 打开;onOpen 回调里会 DbReadyGate.open()
+                            val db = ISCSDatabase.instance
+                        }
+                    }
+                }
+            }
+        }
+        lifecycleScope.launch {
+            DbReadyGate.await()
+            startActivity(Intent(this@SplashActivity, LoginActivity::class.java))
+            finish()
+        }
+    }
+}

+ 42 - 0
app/src/main/java/com/grkj/iscs_mc/receivers/BootReceiver.kt

@@ -0,0 +1,42 @@
+package com.grkj.iscs_mc.receivers
+
+import android.app.AlarmManager
+import android.app.PendingIntent
+import android.content.BroadcastReceiver
+import android.content.Context
+import android.content.Intent
+import com.grkj.data.local.database.BackupScheduler
+import com.grkj.iscs_mc.features.splash.activity.SplashActivity
+import org.slf4j.LoggerFactory
+
+/**
+ * 开机启动接收器:
+ * - 仅做两件事:
+ *   1) 调用 BackupScheduler.applySaved(context) 按已保存的配置重新安排下一次备份
+ *   2) (可选)自启动 App(你已有逻辑,保留)
+ *
+ * 注:WorkManager 的任务会持久化,理论上重启后也在;
+ *     这里再次 applySaved() 是“保险丝”,避免用户还没打开 App、计划丢失的极端情况。
+ */
+class BootReceiver : BroadcastReceiver() {
+    private val logger = LoggerFactory.getLogger(BootReceiver::class.java)
+    override fun onReceive(context: Context, intent: Intent?) {
+        if (Intent.ACTION_BOOT_COMPLETED == intent?.action) {
+            logger.debug("接收到 BOOT_COMPLETED,应用备份计划")
+            // 1) 重新应用备份计划(读取 SimpleBackupPrefs 并排下一次)
+            BackupScheduler.applySaved(context)
+
+            // 2) (可选)2 秒后自启动 App(你原有逻辑)
+            val startAppIntent = Intent(context, SplashActivity::class.java).apply {
+                flags = Intent.FLAG_ACTIVITY_NEW_TASK
+            }
+            val pi = PendingIntent.getActivity(
+                context, 0, startAppIntent,
+                PendingIntent.FLAG_CANCEL_CURRENT or PendingIntent.FLAG_IMMUTABLE
+            )
+            (context.getSystemService(Context.ALARM_SERVICE) as AlarmManager).set(
+                AlarmManager.RTC, System.currentTimeMillis() + 2000, pi
+            )
+        }
+    }
+}

BIN
app/src/main/jniLibs/arm64-v8a/libarcsoft_face.so


BIN
app/src/main/jniLibs/arm64-v8a/libarcsoft_face_engine.so


BIN
app/src/main/jniLibs/arm64-v8a/libarcsoft_image_util.so


BIN
app/src/main/jniLibs/arm64-v8a/libslkidcap.so


BIN
app/src/main/jniLibs/arm64-v8a/libzkalg12.so


BIN
app/src/main/jniLibs/arm64-v8a/libzkfinger10.so


BIN
app/src/main/jniLibs/arm64-v8a/libzksensorcore.so


BIN
app/src/main/jniLibs/armeabi-v7a/libarcsoft_face.so


BIN
app/src/main/jniLibs/armeabi-v7a/libarcsoft_face_engine.so


BIN
app/src/main/jniLibs/armeabi-v7a/libarcsoft_image_util.so


BIN
app/src/main/jniLibs/armeabi-v7a/libserial_port.so


BIN
app/src/main/jniLibs/armeabi-v7a/libslkidcap.so


BIN
app/src/main/jniLibs/armeabi-v7a/libzkalg12.so


BIN
app/src/main/jniLibs/armeabi-v7a/libzkfinger10.so


BIN
app/src/main/jniLibs/armeabi-v7a/libzksensorcore.so


+ 5 - 0
app/src/main/res/drawable/bg_card_color_container_bg_radius_md.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+    <solid android:color="?attr/colorBg" />
+    <corners android:radius="@dimen/iscs_radius_md" />
+</shape>

+ 5 - 0
app/src/main/res/drawable/bg_card_login_header_bg_radius_md.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+    <solid android:color="?attr/colorWhite" />
+    <corners android:radius="@dimen/iscs_radius_md" />
+</shape>

+ 8 - 0
app/src/main/res/drawable/login_tip_circle.xml

@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="oval">
+    <size
+        android:width="@dimen/iscs_radius_md"
+        android:height="@dimen/iscs_radius_md" />
+    <solid android:color="?attr/colorPrimaryLight" />
+</shape>

+ 46 - 0
app/src/main/res/layout-land/activity_login.xml

@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8"?>
+<layout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:tools="http://schemas.android.com/tools">
+
+    <RelativeLayout
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:background="?attr/colorBg"
+        android:fitsSystemWindows="true"
+        android:orientation="vertical">
+
+        <FrameLayout
+            android:id="@+id/header_layout"
+            android:layout_width="match_parent"
+            android:layout_height="@dimen/header_height"
+            android:layout_marginHorizontal="@dimen/iscs_space_4"
+            android:layout_marginTop="@dimen/iscs_space_4"
+            android:background="@drawable/bg_card_login_header_bg_radius_md"
+            android:paddingHorizontal="@dimen/iscs_space_4">
+
+            <ImageView
+                android:layout_width="@dimen/header_logo_width"
+                android:layout_height="@dimen/header_logo_height"
+                android:layout_gravity="center_vertical"
+                android:src="@mipmap/icon_logo" />
+
+            <TextClock
+                android:layout_width="wrap_content"
+                android:layout_height="match_parent"
+                android:layout_gravity="right"
+                android:format12Hour="yyyy-MM-dd    HH:mm"
+                android:format24Hour="yyyy-MM-dd    HH:mm"
+                android:gravity="center_vertical"
+                android:textColor="?attr/colorBlack"
+                android:textSize="@dimen/iscs_text_md"
+                android:textStyle="bold|italic" />
+        </FrameLayout>
+
+        <androidx.viewpager2.widget.ViewPager2
+            android:id="@+id/vp2"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:layout_below="@+id/header_layout"/>
+    </RelativeLayout>
+</layout>

+ 133 - 0
app/src/main/res/layout-land/fragment_login.xml

@@ -0,0 +1,133 @@
+<?xml version="1.0" encoding="utf-8"?>
+<layout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:tools="http://schemas.android.com/tools">
+
+    <RelativeLayout
+        android:layout_width="match_parent"
+        android:layout_height="match_parent">
+
+        <LinearLayout
+            android:id="@+id/main_content"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_above="@+id/tec_support"
+            android:layout_marginTop="@dimen/iscs_space_2"
+            android:orientation="vertical">
+
+            <TextView
+                android:id="@+id/chipLang"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_gravity="right"
+                android:layout_marginTop="@dimen/iscs_space_2"
+                android:layout_marginRight="@dimen/iscs_space_4"
+                android:background="@drawable/common_btn_white_board"
+                android:paddingHorizontal="@dimen/iscs_space_2"
+                android:paddingVertical="@dimen/iscs_space_1"
+                android:text="EN"
+                android:textAllCaps="true"
+                android:textColor="?attr/colorTextPrimary"
+                android:textSize="@dimen/iscs_text_md" />
+
+
+            <TextView
+                android:id="@+id/title_cn"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_gravity="center_horizontal"
+                android:layout_marginTop="@dimen/iscs_space_2"
+                android:gravity="center"
+                android:textColor="?attr/colorTextPrimary"
+                android:textSize="@dimen/iscs_text_h1"
+                android:textStyle="bold"
+                app:i18nKey='@{"mc"}' />
+
+            <TextView
+                android:id="@+id/title_en"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_gravity="center_horizontal"
+                android:layout_marginTop="@dimen/iscs_space_2"
+                android:textColor="?attr/colorTextPrimary"
+                android:textSize="@dimen/iscs_text_lg"
+                android:textStyle="bold|italic"
+                app:i18nKey='@{"mc_en"}' />
+
+            <TextView
+                android:id="@+id/mode_tip"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_gravity="center_horizontal"
+                android:layout_marginTop="@dimen/iscs_space_2"
+                android:gravity="center"
+                android:textColor="?attr/colorTextPrimary"
+                android:textSize="@dimen/iscs_text_xs"
+                app:i18nKey='@{"administrator_mode"}' />
+
+            <LinearLayout
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:layout_marginTop="@dimen/iscs_space_2"
+                android:gravity="center"
+                android:orientation="vertical">
+
+                <androidx.recyclerview.widget.RecyclerView
+                    android:id="@+id/login_type_rv"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    tools:listitem="@layout/item_login_method" />
+
+                <LinearLayout
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_gravity="center_horizontal"
+                    android:layout_marginTop="@dimen/iscs_space_2"
+                    android:divider="@drawable/common_divider_normal_space_horizontal"
+                    android:gravity="center_vertical"
+                    android:orientation="horizontal"
+                    android:showDividers="middle">
+
+                    <View
+                        android:layout_width="@dimen/iscs_space_4"
+                        android:layout_height="@dimen/iscs_space_4"
+                        android:background="@drawable/login_tip_circle" />
+
+                    <TextView
+                        android:id="@+id/login_tip_tv"
+                        android:layout_width="match_parent"
+                        android:layout_height="wrap_content"
+                        android:layout_alignParentBottom="true"
+                        android:gravity="center_horizontal"
+                        android:textColor="?attr/colorTextPrimary"
+                        android:textSize="@dimen/iscs_text_md"
+                        app:i18nKey='@{"login_tip"}' />
+                </LinearLayout>
+            </LinearLayout>
+        </LinearLayout>
+
+        <TextView
+            android:id="@+id/tec_support"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_alignParentBottom="true"
+            android:layout_marginBottom="@dimen/iscs_space_2"
+            android:gravity="center_horizontal"
+            android:textColor="?attr/colorTextPrimary"
+            android:textSize="@dimen/iscs_text_sm"
+            app:i18nKey='@{"tec_support"}' />
+
+        <TextView
+            android:id="@+id/version"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_alignParentRight="true"
+            android:layout_alignParentBottom="true"
+            android:layout_marginRight="@dimen/iscs_space_2"
+            android:layout_marginBottom="@dimen/iscs_space_4"
+            android:textColor="?attr/colorTextPrimary"
+            android:textSize="@dimen/iscs_text_sm"
+            tools:text="v1.0" />
+
+    </RelativeLayout>
+</layout>

+ 39 - 0
app/src/main/res/layout-land/item_login_method.xml

@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<layout xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <RelativeLayout
+        android:id="@+id/login_container"
+        android:layout_width="@dimen/login_method_item_layout_width"
+        android:layout_height="@dimen/login_method_item_layout_height"
+        android:background="@drawable/bg_card_item">
+
+        <View
+            android:id="@+id/login_tip_v"
+            android:layout_width="@dimen/login_circle_view_size"
+            android:layout_height="@dimen/login_circle_view_size"
+            android:layout_alignParentRight="true"
+            android:layout_marginTop="@dimen/iscs_space_4"
+            android:layout_marginRight="@dimen/iscs_space_2"
+            android:background="@drawable/login_tip_circle"
+            android:visibility="gone" />
+
+        <ImageView
+            android:id="@+id/login_method_iv"
+            android:layout_width="@dimen/login_method_item_iv_size"
+            android:layout_height="@dimen/login_method_item_iv_size"
+            android:layout_centerHorizontal="true"
+            android:layout_marginTop="@dimen/iscs_space_5"
+            android:adjustViewBounds="false"
+            android:scaleType="fitCenter"/>
+
+        <TextView
+            android:id="@+id/login_method_tv"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_below="@+id/login_method_iv"
+            android:layout_marginTop="@dimen/iscs_space_5"
+            android:gravity="center_horizontal"
+            android:textColor="?attr/colorTextPrimary"
+            android:textSize="@dimen/iscs_text_md" />
+    </RelativeLayout>
+</layout>

+ 46 - 0
app/src/main/res/layout/activity_login.xml

@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8"?>
+<layout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:tools="http://schemas.android.com/tools">
+
+    <RelativeLayout
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:background="?attr/colorBg"
+        android:fitsSystemWindows="true"
+        android:orientation="vertical">
+
+        <FrameLayout
+            android:id="@+id/header_layout"
+            android:layout_width="match_parent"
+            android:layout_height="@dimen/header_height"
+            android:layout_marginHorizontal="@dimen/iscs_space_4"
+            android:layout_marginTop="@dimen/iscs_space_4"
+            android:background="@drawable/bg_card_login_header_bg_radius_md"
+            android:paddingHorizontal="@dimen/iscs_space_4">
+
+            <ImageView
+                android:layout_width="@dimen/header_logo_width"
+                android:layout_height="@dimen/header_logo_height"
+                android:layout_gravity="center_vertical"
+                android:src="@mipmap/icon_logo" />
+
+            <TextClock
+                android:layout_width="wrap_content"
+                android:layout_height="match_parent"
+                android:layout_gravity="right"
+                android:format12Hour="yyyy-MM-dd    HH:mm"
+                android:format24Hour="yyyy-MM-dd    HH:mm"
+                android:gravity="center_vertical"
+                android:textColor="?attr/colorBlack"
+                android:textSize="@dimen/iscs_text_md"
+                android:textStyle="bold|italic" />
+        </FrameLayout>
+
+        <androidx.viewpager2.widget.ViewPager2
+            android:id="@+id/vp2"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:layout_below="@+id/header_layout" />
+    </RelativeLayout>
+</layout>

+ 0 - 33
app/src/main/res/layout/activity_main.xml

@@ -1,33 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto"
-    xmlns:tools="http://schemas.android.com/tools"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:fitsSystemWindows="true"
-    tools:context=".MainActivity">
-
-    <com.google.android.material.appbar.AppBarLayout
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:fitsSystemWindows="true">
-
-        <com.google.android.material.appbar.MaterialToolbar
-            android:id="@+id/toolbar"
-            android:layout_width="match_parent"
-            android:layout_height="?attr/actionBarSize" />
-
-    </com.google.android.material.appbar.AppBarLayout>
-
-    <include layout="@layout/content_main" />
-
-    <com.google.android.material.floatingactionbutton.FloatingActionButton
-        android:id="@+id/fab"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_gravity="bottom|end"
-        android:layout_marginEnd="@dimen/fab_margin"
-        android:layout_marginBottom="16dp"
-        app:srcCompat="@android:drawable/ic_dialog_email" />
-
-</androidx.coordinatorlayout.widget.CoordinatorLayout>

+ 8 - 0
app/src/main/res/layout/activity_manage.xml

@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<layout xmlns:android="http://schemas.android.com/apk/res/android">
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="match_parent">
+
+    </LinearLayout>
+</layout>

+ 9 - 0
app/src/main/res/layout/activity_material_exchange.xml

@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<layout xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="match_parent">
+
+    </LinearLayout>
+</layout>

+ 57 - 0
app/src/main/res/layout/activity_splash.xml

@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8"?>
+<layout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto">
+
+    <RelativeLayout
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:background="?attr/colorBg"
+        android:orientation="vertical">
+
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_centerVertical="true"
+            android:gravity="center"
+            android:orientation="vertical">
+
+            <ImageView
+                android:layout_width="300dp"
+                android:layout_height="100dp"
+                android:src="@mipmap/icon_logo" />
+
+            <TextView
+                android:id="@+id/title_cn"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_gravity="center_horizontal"
+                android:textColor="?attr/colorTextPrimary"
+                android:textSize="@dimen/iscs_text_h1"
+                android:textStyle="bold"
+                app:i18nKey='@{"mc"}' />
+
+            <TextView
+                android:id="@+id/title_en"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_gravity="center_horizontal"
+                android:layout_marginTop="@dimen/iscs_text_h2"
+                android:textColor="?attr/colorTextPrimary"
+                android:textSize="@dimen/iscs_text_h2"
+                android:textStyle="bold"
+                app:i18nKey='@{"mc_en"}' />
+        </LinearLayout>
+
+
+        <TextView
+            android:id="@+id/tec_support"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_alignParentBottom="true"
+            android:layout_marginBottom="@dimen/iscs_text_xsm"
+            android:gravity="center_horizontal"
+            android:textColor="?attr/colorTextPrimary"
+            android:textSize="@dimen/iscs_text_xsm"
+            app:i18nKey='@{"tec_support"}' />
+    </RelativeLayout>
+</layout>

+ 0 - 19
app/src/main/res/layout/content_main.xml

@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    app:layout_behavior="@string/appbar_scrolling_view_behavior">
-
-    <fragment
-        android:id="@+id/nav_host_fragment_content_main"
-        android:name="androidx.navigation.fragment.NavHostFragment"
-        android:layout_width="0dp"
-        android:layout_height="0dp"
-        app:defaultNavHost="true"
-        app:layout_constraintBottom_toBottomOf="parent"
-        app:layout_constraintEnd_toEndOf="parent"
-        app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintTop_toTopOf="parent"
-        app:navGraph="@navigation/nav_graph" />
-</androidx.constraintlayout.widget.ConstraintLayout>

+ 30 - 0
app/src/main/res/layout/dialog_change_lang.xml

@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<layout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto">
+
+    <LinearLayout
+        android:layout_width="@dimen/dialog_card_login_width"
+        android:layout_height="wrap_content"
+        android:background="@drawable/bg_card_color_container_bg_radius_md"
+        android:orientation="vertical"
+        android:padding="@dimen/iscs_space_2">
+
+        <androidx.recyclerview.widget.RecyclerView
+            android:id="@+id/list_rv"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:layout_weight="1" />
+
+        <TextView
+            android:id="@+id/switch_btn"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_gravity="center_horizontal"
+            android:layout_marginVertical="@dimen/iscs_space_2"
+            android:background="@drawable/common_btn_confirm"
+            android:paddingHorizontal="@dimen/iscs_space_2"
+            android:textColor="?attr/colorTextPrimary"
+            android:textSize="@dimen/iscs_text_md"
+            app:i18nKey='@{"switch"}' />
+    </LinearLayout>
+</layout>

+ 92 - 0
app/src/main/res/layout/dialog_login.xml

@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="utf-8"?>
+<layout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto">
+
+    <com.google.android.material.card.MaterialCardView
+        android:layout_width="@dimen/login_dialog_width"
+        android:layout_height="@dimen/login_dialog_height"
+        android:gravity="center"
+        app:cardBackgroundColor="?attr/colorSecBg"
+        app:strokeColor="?attr/colorTransparent">
+
+        <LinearLayout
+            android:id="@+id/ll_easy_container"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:layout_gravity="center"
+            android:gravity="center"
+            android:orientation="vertical"
+            android:visibility="visible">
+
+            <ImageView
+                android:id="@+id/iv_icon"
+                android:layout_width="@dimen/login_dialog_login_and_check"
+                android:layout_height="@dimen/login_dialog_login_and_check"
+                android:tint="?attr/colorPrimary"
+                android:layout_marginBottom="@dimen/iscs_space_1" />
+
+            <TextView
+                android:id="@+id/tv_tip"
+                style="@style/CommonTextView"
+                android:textSize="@dimen/iscs_text_md" />
+        </LinearLayout>
+
+        <FrameLayout
+            android:layout_width="match_parent"
+            android:layout_height="match_parent">
+
+            <TextureView
+                android:id="@+id/preview"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:visibility="invisible" />
+        </FrameLayout>
+
+        <LinearLayout
+            android:id="@+id/ll_account_container"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_gravity="center"
+            android:gravity="center"
+            android:orientation="vertical"
+            android:padding="@dimen/iscs_space_2">
+
+            <EditText
+                android:id="@+id/et_account"
+                style="@style/CommonEdit"
+                android:layout_width="match_parent"
+                android:layout_height="@dimen/login_dialog_input_height"
+                android:layout_marginBottom="@dimen/iscs_space_1"
+                app:i18nHint='@{"please_input_account"}'
+                android:textSize="@dimen/iscs_text_sm" />
+
+            <EditText
+                android:id="@+id/et_password"
+                style="@style/CommonEdit"
+                android:layout_width="match_parent"
+                android:layout_height="@dimen/login_dialog_input_height"
+                android:layout_marginBottom="@dimen/iscs_space_1"
+                app:i18nHint='@{"please_input_password"}'
+                android:inputType="textPassword"
+                android:textSize="@dimen/iscs_text_sm" />
+
+            <TextView
+                android:id="@+id/tv_login"
+                style="@style/CommonBtn"
+                android:layout_width="match_parent"
+                android:layout_height="@dimen/login_dialog_btn_height"
+                android:layout_marginBottom="@dimen/iscs_space_1"
+                app:i18nKey='@{"login"}'
+                android:textSize="@dimen/iscs_text_sm" />
+
+            <TextView
+                android:id="@+id/tv_cancel"
+                style="@style/CommonBtn"
+                android:layout_width="match_parent"
+                android:layout_height="@dimen/login_dialog_btn_height"
+                android:background="@drawable/white_stroke_bg"
+                app:i18nKey='@{"cancel"}'
+                android:textSize="@dimen/iscs_text_sm" />
+        </LinearLayout>
+    </com.google.android.material.card.MaterialCardView>
+</layout>

Неке датотеке нису приказане због велике количине промена