浏览代码

1. 登录页面租户ID优化,修改显示效果
2. 将清除缓存配置到用户中心中

bjb 3 月之前
父节点
当前提交
fd394b1b32

+ 1 - 1
app/build.gradle.kts

@@ -19,7 +19,7 @@ android {
         minSdk = 24
         targetSdk = 36
         versionCode = 1
-        versionName = "1.0"
+        versionName = "0.0.20260126_1"
 
         testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
     }

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

@@ -27,7 +27,7 @@ object ApiRequest {
      */
     fun getUserHeaders(headers: Map<String, String> = emptyMap()): Map<String, String> {
         val map = HashMap<String, String>()
-        map["tenant-id"] = "1"
+        map["Tenant-Id"] = Storage.readTenantId()
         map["Authorization"] = "Bearer ${Storage.readToken()}"
         map.putAll(headers)
         return map

+ 129 - 28
app/src/main/java/com/iscs/bozzys/ui/dialog/InputDialog.kt

@@ -1,67 +1,171 @@
 package com.iscs.bozzys.ui.dialog
 
+import android.view.WindowManager
 import androidx.compose.foundation.background
+import androidx.compose.foundation.border
 import androidx.compose.foundation.clickable
+import androidx.compose.foundation.interaction.MutableInteractionSource
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.Column
 import androidx.compose.foundation.layout.Row
 import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.fillMaxSize
 import androidx.compose.foundation.layout.fillMaxWidth
 import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.layout.offset
 import androidx.compose.foundation.layout.padding
-import androidx.compose.foundation.layout.width
 import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.foundation.text.BasicTextField
+import androidx.compose.foundation.text.KeyboardOptions
+import androidx.compose.material3.LocalTextStyle
 import androidx.compose.material3.MaterialTheme
 import androidx.compose.material3.Text
 import androidx.compose.runtime.Composable
+import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.runtime.SideEffect
+import androidx.compose.runtime.remember
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.draw.clip
 import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.SolidColor
+import androidx.compose.ui.platform.LocalContext
 import androidx.compose.ui.text.font.FontWeight
+import androidx.compose.ui.text.input.KeyboardType
 import androidx.compose.ui.text.style.TextAlign
 import androidx.compose.ui.unit.dp
 import androidx.compose.ui.unit.sp
 import androidx.compose.ui.window.Dialog
+import androidx.compose.ui.window.DialogProperties
+import com.iscs.bozzys.ui.common.PageBase
+import com.iscs.bozzys.ui.pages.compose.CardContainer
+import com.iscs.bozzys.ui.theme.Main
 import com.iscs.bozzys.ui.theme.Text
 
 /**
- * 默认公共弹窗
+ * 公共输入框Dialog
  */
 @Composable
 fun InputDialog(
-    show: Boolean = false,
-    title: String = "提示",
-    content: String = "",
-    cancelText: String = "取消",
+    show: Boolean,
+    value: String,
+    title: String = "",
+    placeholder: String = "",
+    onConfirm: () -> Unit = {},
     onCancel: () -> Unit = {},
-    confirmText: String = "确认",
-    onConfirm: () -> Unit = {}
+    onInputChanged: (String) -> Unit
 ) {
-    if (show) {
-        Dialog(onDismissRequest = {}) {
-            Box(
+    val ctx = LocalContext.current
+    if (!show || ctx !is PageBase) return
+
+    LaunchedEffect(Unit) {
+        ctx.setNavigationLight(false)
+    }
+
+    Dialog(
+        onDismissRequest = onCancel,
+        properties = DialogProperties(decorFitsSystemWindows = false)
+    ) {
+        val activityWindow = ctx.window
+        val dialogWindow = ctx.getDialogWindow()
+        SideEffect {
+            if (activityWindow != null && dialogWindow != null) {
+                val attributes = WindowManager.LayoutParams()
+                // 复制Activity窗口属性
+                attributes.copyFrom(activityWindow.attributes)
+                // 这个一定要设置
+                attributes.type = dialogWindow.attributes.type
+                // 更新窗口属性
+                dialogWindow.attributes = attributes
+                // 设置窗口的宽度和高度,这段代码Dialog源码中就有哦,可以自己去查看
+                dialogWindow.setLayout(
+                    activityWindow.decorView.width,
+                    activityWindow.decorView.height
+                )
+            }
+        }
+        Box(
+            modifier = Modifier
+                .fillMaxSize()
+                .background(Color.Black.copy(alpha = 0.4f))
+                .clickable(
+                    indication = null,
+                    interactionSource = remember { MutableInteractionSource() },
+                    onClick = {}),
+            contentAlignment = Alignment.Center
+        ) {
+            CardContainer(
+                topRadius = 16.dp,
+                bottomRadius = 16.dp,
                 modifier = Modifier
-                    .clip(RoundedCornerShape(12.dp))
-                    .background(Color.White)
+                    .fillMaxWidth(0.65f)
+                    // 防止点击穿透
+                    .clickable(
+                        indication = null,
+                        interactionSource = remember { MutableInteractionSource() },
+                        onClick = {})
+                    .background(Color.White, RoundedCornerShape(16.dp))
             ) {
-                Column(modifier = Modifier.width(240.dp), horizontalAlignment = Alignment.CenterHorizontally) {
-                    Text(title, fontSize = 16.sp, lineHeight = 36.sp, fontWeight = FontWeight.Bold, color = Text)
+                Column(Modifier.fillMaxWidth()) {
+                    Row(
+                        Modifier
+                            .fillMaxWidth()
+                            .height(40.dp)
+                            .padding(horizontal = 16.dp),
+                        verticalAlignment = Alignment.CenterVertically
+                    ) {
+                        Text(
+                            title,
+                            fontSize = 16.sp,
+                            fontWeight = FontWeight.Bold,
+                            color = Text,
+                            modifier = Modifier.weight(1f),
+                            textAlign = TextAlign.Center
+                        )
+                    }
                     Spacer(
                         Modifier
                             .fillMaxWidth()
-                            .height(1.dp)
-                            .background(Color(0xFFEEEEEE))
+                            .height(0.5.dp)
+                            .background(Color.Black.copy(alpha = 0.05f))
                     )
-                    Text(
-                        content,
-                        fontSize = 15.sp,
-                        color = Text.copy(alpha = 0.8f),
-                        modifier = Modifier.padding(horizontal = 16.dp, vertical = 10.dp)
+                    BasicTextField(
+                        value,
+                        onValueChange = { onInputChanged(it) },
+                        Modifier
+                            .padding(vertical = 16.dp, horizontal = 10.dp)
+                            .fillMaxWidth()
+                            .height(46.dp)
+                            .border(1.dp, shape = RoundedCornerShape(6.dp), color = Color(0xFFE5E6EB))
+                            .padding(horizontal = 10.dp),
+                        singleLine = true,
+                        textStyle = LocalTextStyle.current.copy(fontSize = 16.sp, lineHeight = 20.sp),
+                        decorationBox = { innerTextField ->
+                            Box(contentAlignment = Alignment.CenterStart) {
+                                innerTextField()
+                                if (value.isEmpty()) {
+                                    Text(
+                                        placeholder,
+                                        color = Color(0xFF9CA3AF),
+                                        fontSize = 16.sp,
+                                        lineHeight = 20.sp,
+                                        modifier = Modifier.offset(y = (-1).dp)
+                                    )
+                                }
+                            }
+                        },
+                        cursorBrush = SolidColor(Main),
+                        keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Text)
+                    )
+                    Spacer(
+                        Modifier
+                            .fillMaxWidth()
+                            .height(0.5.dp)
+                            .background(Color.Black.copy(alpha = 0.05f))
                     )
                     Row(Modifier.padding(horizontal = 5.dp, vertical = 10.dp)) {
                         Text(
-                            cancelText, color = Color.White, modifier = Modifier
+                            "取消", color = Color.White, modifier = Modifier
                                 .padding(horizontal = 5.dp)
                                 .weight(1f)
                                 .clip(RoundedCornerShape(6.dp))
@@ -73,7 +177,7 @@ fun InputDialog(
                             fontWeight = FontWeight.Bold
                         )
                         Text(
-                            confirmText,
+                            "确定",
                             color = Color.White,
                             modifier = Modifier
                                 .padding(horizontal = 5.dp)
@@ -91,7 +195,4 @@ fun InputDialog(
             }
         }
     }
-
-}
-
-// data class StateTips(val title: String = "", val content: String = "", val show: Boolean = false, val type: String = "")
+}

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

@@ -27,6 +27,7 @@ import androidx.compose.foundation.verticalScroll
 import androidx.compose.material3.Button
 import androidx.compose.material3.Icon
 import androidx.compose.material3.LocalTextStyle
+import androidx.compose.material3.MaterialTheme
 import androidx.compose.material3.Text
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.LaunchedEffect
@@ -50,6 +51,7 @@ import androidx.compose.ui.unit.sp
 import androidx.lifecycle.viewmodel.compose.viewModel
 import com.iscs.bozzys.R
 import com.iscs.bozzys.ui.common.PageBase
+import com.iscs.bozzys.ui.dialog.InputDialog
 import com.iscs.bozzys.ui.pages.home.openPageHome
 import com.iscs.bozzys.ui.pages.vm.VMLogin
 import com.iscs.bozzys.ui.theme.Main
@@ -57,7 +59,6 @@ import com.iscs.bozzys.ui.theme.SubMain
 import com.iscs.bozzys.ui.theme.Text
 import com.iscs.bozzys.ui.theme.TextDesc
 import com.iscs.bozzys.utils.BiometricKeyStore
-import com.iscs.bozzys.utils.LogUtil
 import com.iscs.bozzys.utils.Storage
 import com.iscs.bozzys.utils.SystemUtil
 import com.iscs.bozzys.utils.SystemUtil.getAppVersionInfo
@@ -134,6 +135,7 @@ class PageLogin : PageBase() {
             // 处理基础Toast和Loading提示
             vm.toast.initToast()
             vm.loading.initLoading()
+            vm.init()
         }
         Column(
             Modifier
@@ -258,6 +260,30 @@ class PageLogin : PageBase() {
                     keyboardOptions = KeyboardOptions(keyboardType = if (state.loginType == 0) KeyboardType.Number else KeyboardType.Password)
                 )
             }
+            if (state.showTenantId) {
+                Text(
+                    "关联租户",
+                    fontSize = 14.sp,
+                    lineHeight = 18.sp,
+                    color = MaterialTheme.colorScheme.primary,
+                    modifier = Modifier
+                        .padding(top = 5.dp, end = 10.dp)
+                        .clip(RoundedCornerShape(50))
+                        .align(Alignment.End)
+                        .clickable { vm.showInputDialog() }
+                        .padding(horizontal = 5.dp, vertical = 3.dp)
+                )
+                InputDialog(
+                    show = state.showInputDialog,
+                    value = state.tenantId,
+                    title = "设置租户",
+                    placeholder = "请输入租户码",
+                    onConfirm = { vm.hideInputDialog() },
+                    onCancel = { vm.hideInputDialog() }
+                ) {
+                    vm.updateInputValue(it)
+                }
+            }
             // 登录按钮
             Button(
                 onClick = {

+ 21 - 0
app/src/main/java/com/iscs/bozzys/ui/pages/profile/PageProfile.kt

@@ -62,6 +62,7 @@ import com.iscs.bozzys.R
 import com.iscs.bozzys.api.User
 import com.iscs.bozzys.ui.common.PageBase
 import com.iscs.bozzys.ui.common.Title
+import com.iscs.bozzys.ui.dialog.TipsDialog
 import com.iscs.bozzys.ui.pages.compose.CardContainer
 import com.iscs.bozzys.ui.pages.vm.VMProfile
 import com.iscs.bozzys.ui.theme.Main
@@ -294,6 +295,26 @@ class PageProfile : PageBase() {
                     }
                 }
             }
+            // 其他操作逻辑
+            CardContainer(
+                modifier = Modifier
+                    .padding(horizontal = 16.dp)
+                    .padding(bottom = 16.dp), topRadius = 16.dp, bottomRadius = 16.dp
+            ) {
+                Column {
+                    // 用户名
+                    UserInfoItem("清除缓存", "") {
+                        vm.showClearCacheDialog()
+                    }
+                    TipsDialog(show = state.showClearCacheDialog, content = "确定要清除缓存吗?", onConfirm = {
+                        vm.hideClearCacheDialog()
+                        vm.clearStorageCache()
+                    }, onCancel = {
+                        vm.hideClearCacheDialog()
+                    })
+                }
+
+            }
         }
     }
 

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

@@ -11,6 +11,7 @@ import com.iscs.bozzys.ui.common.VMBase
 import com.iscs.bozzys.utils.BiometricKeyStore
 import com.iscs.bozzys.utils.Storage
 import com.iscs.bozzys.utils.Storage.saveRefreshToken
+import com.iscs.bozzys.utils.Storage.saveTenantId
 import com.iscs.bozzys.utils.Storage.saveToken
 import kotlinx.coroutines.delay
 import kotlinx.coroutines.launch
@@ -26,6 +27,14 @@ class VMLogin : VMBase() {
     // 是否登录成功
     private var isLogin = false
 
+    /**
+     * 检查租户ID是否显示
+     */
+    fun init() {
+        val tenantId = Storage.readTenantId()
+        state = state.copy(showTenantId = tenantId.isEmpty(), tenantId = tenantId)
+    }
+
     /**
      * 更新登录方式
      *
@@ -64,6 +73,7 @@ class VMLogin : VMBase() {
                 toast.emit(check)
                 return@launch
             }
+            state.tenantId.saveTenantId()
             loading.emit(StateLoading(show = true))
             ApiRequest.login(state.account, state.code).onSuccess {
                 isLogin = true
@@ -83,6 +93,18 @@ class VMLogin : VMBase() {
         }
     }
 
+    fun showInputDialog() {
+        state = state.copy(showInputDialog = true)
+    }
+
+    fun updateInputValue(value: String) {
+        state = state.copy(tenantId = value)
+    }
+
+    fun hideInputDialog() {
+        state = state.copy(showInputDialog = false)
+    }
+
     /**
      * 存储登录成功后生成的签名向量
      *
@@ -107,6 +129,7 @@ class VMLogin : VMBase() {
             if (state.account.trim().isEmpty()) return R.string.input_account_tips
             if (state.code.trim().isEmpty()) return R.string.input_pwd_tips
         }
+        if (state.tenantId.isEmpty()) return R.string.input_tenant_id_tips
         return 0
     }
 
@@ -114,5 +137,16 @@ class VMLogin : VMBase() {
 
 /**
  * 登录页面状态模型
+ *
+ * @param showTenantId 是否显示租户配置
+ * @param showInputDialog   是否显示输入框
+ * @param tenantId          用户输入的租户ID
  */
-data class StateLogin(val loginType: Int = 1, val account: String = "", val code: String = "")
+data class StateLogin(
+    val loginType: Int = 1,
+    val account: String = "",
+    val code: String = "",
+    val showTenantId: Boolean = false,
+    val showInputDialog: Boolean = false,
+    val tenantId: String = ""
+)

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

@@ -5,8 +5,8 @@ import com.iscs.bozzys.api.ApiRequest
 import com.iscs.bozzys.api.Message
 import com.iscs.bozzys.event.RefreshEvent
 import com.iscs.bozzys.event.RefreshEventBus
-import com.iscs.bozzys.ui.dialog.StateTips
 import com.iscs.bozzys.ui.common.VMBase
+import com.iscs.bozzys.ui.dialog.StateTips
 import com.iscs.bozzys.utils.DateUtil.getShowDate
 import kotlinx.coroutines.delay
 import kotlinx.coroutines.flow.MutableStateFlow
@@ -26,6 +26,11 @@ class VMMessage : VMBase() {
         getMessage(StatePageMessage(isRefresh = true, page = 1))
     }
 
+    /**
+     * 获取消息列表
+     *
+     * @param page  页面加载器
+     */
     fun getMessage(page: StatePageMessage) {
         viewModelScope.launch {
             _state.value = _state.value.copy(page = _state.value.page.copy(page = page.page, isRefresh = page.isRefresh))
@@ -64,18 +69,30 @@ class VMMessage : VMBase() {
         }
     }
 
+    /**
+     * 全部已读
+     */
     fun onReadAll() {
         _state.value = _state.value.copy(tips = StateTips(show = true, title = "提示", content = "确定要将所有消息标记为已读吗?", type = "READ_ALL"))
     }
 
+    /**
+     * 后台暂不支持删除所有,待支持后开放
+     */
     fun onDeleteAll() {
         _state.value = _state.value.copy(tips = StateTips(show = true, title = "提示", content = "确定要删除所有消息吗?", type = "DELETE_ALL"))
     }
 
+    /**
+     * 隐藏提示Dialog
+     */
     fun hideTips() {
         _state.value = _state.value.copy(tips = _state.value.tips.copy(show = false, type = ""))
     }
 
+    /**
+     * 提示窗口确认被点击
+     */
     fun onTipsConfirm() {
         viewModelScope.launch {
             val tips = _state.value.tips

+ 23 - 1
app/src/main/java/com/iscs/bozzys/ui/pages/vm/VMProfile.kt

@@ -8,6 +8,7 @@ import com.iscs.bozzys.api.User
 import com.iscs.bozzys.event.RefreshEvent
 import com.iscs.bozzys.event.RefreshEventBus
 import com.iscs.bozzys.ui.common.VMBase
+import com.iscs.bozzys.utils.Storage
 import kotlinx.coroutines.delay
 import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.asStateFlow
@@ -98,11 +99,32 @@ class VMProfile : VMBase() {
         }
     }
 
+    fun showClearCacheDialog() {
+        _state.value = _state.value.copy(showClearCacheDialog = true)
+    }
+
+    /**
+     * 清除指定缓存数据
+     */
+    fun clearStorageCache() {
+        viewModelScope.launch {
+            Storage.clearCache()
+            delay(500)
+            toast.emit("清除成功")
+        }
+
+    }
+
+    fun hideClearCacheDialog() {
+        _state.value = _state.value.copy(showClearCacheDialog = false)
+    }
+
 }
 
 data class StateProfile(
     val user: User = User(),
     val showModifyDialog: Boolean = false,
     val modifyDialogTitle: String = "",
-    val modifyKv: Pair<String, String> = "" to ""
+    val modifyKv: Pair<String, String> = "" to "",
+    val showClearCacheDialog: Boolean = false,
 )

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

@@ -67,6 +67,20 @@ object Storage {
         mmkv.encode("user_avatar", this ?: "")
     }
 
+    /**
+     * 保存租户ID
+     */
+    fun String?.saveTenantId() {
+        mmkv.encode("tenant_id", this ?: "")
+    }
+
+    /**
+     * 读取租户ID
+     */
+    fun readTenantId(): String {
+        return mmkv.decodeString("tenant_id", "") ?: ""
+    }
+
     /**
      * 读取用户名
      */
@@ -117,4 +131,11 @@ object Storage {
         return mmkv.decodeBytes("user_token_iv_value", byteArrayOf()) ?: byteArrayOf()
     }
 
+    /**
+     * 清除缓存数据
+     */
+    fun clearCache() {
+        mmkv.remove("tenant_id")
+    }
+
 }

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

@@ -6,4 +6,5 @@
     <string name="input_code_tips">请输入验证码</string>
     <string name="input_account_tips">请输入用户名</string>
     <string name="input_pwd_tips">请输入密码</string>
+    <string name="input_tenant_id_tips">请输入租户码</string>
 </resources>

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

@@ -5,4 +5,5 @@
     <string name="input_code_tips">Please input code</string>
     <string name="input_account_tips">Please input account</string>
     <string name="input_pwd_tips">Please input password</string>
+    <string name="input_tenant_id_tips">Please input tenant-id</string>
 </resources>