From 7b8bb6b1d8d2505c06fa3740349b96798ec8c900 Mon Sep 17 00:00:00 2001
From: zhou zhou <3272660260@qq.com>
Date: 星期四, 02 四月 2026 16:06:21 +0800
Subject: [PATCH] #登录页修复

---
 rsf-design/src/views/auth/login/index.vue      |  123 ++++++++++++++++++++++++++++++++++++++++
 rsf-design/src/utils/storage/storage-config.js |    4 +
 rsf-design/src/locales/langs/en.json           |    1 
 rsf-design/src/locales/langs/zh.json           |    1 
 rsf-design/src/api/auth.js                     |   24 +++++++-
 5 files changed, 148 insertions(+), 5 deletions(-)

diff --git a/rsf-design/src/api/auth.js b/rsf-design/src/api/auth.js
index c420267..36b0ab9 100644
--- a/rsf-design/src/api/auth.js
+++ b/rsf-design/src/api/auth.js
@@ -1,13 +1,18 @@
 import request from '@/utils/http'
 
-function buildLoginPayload({ username, password }) {
-  return { username, password }
+function buildLoginPayload({ username, password, tenantId }) {
+  const payload = { username, password }
+  if (tenantId !== '' && tenantId !== null && tenantId !== void 0) {
+    payload.tenantId = Number(tenantId)
+  }
+  return payload
 }
 
 function normalizeLoginParams(params) {
   return {
     username: params?.username || params?.userName || '',
-    password: params?.password
+    password: params?.password,
+    tenantId: params?.tenantId ?? ''
   }
 }
 
@@ -85,6 +90,17 @@
       }
     })
 }
+function fetchGetSystemInfo() {
+  return request.get({
+    url: '/system/info'
+  })
+}
+function fetchGetTenantList(params) {
+  return request.get({
+    url: '/tenant/list',
+    params
+  })
+}
 function fetchGetUserInfo() {
   return request
     .get({
@@ -104,6 +120,8 @@
 export {
   buildLoginPayload,
   fetchGetMenuList,
+  fetchGetSystemInfo,
+  fetchGetTenantList,
   fetchGetUserInfo,
   fetchLogin,
   normalizeLoginResponse,
diff --git a/rsf-design/src/locales/langs/en.json b/rsf-design/src/locales/langs/en.json
index 571d9c3..81d450c 100644
--- a/rsf-design/src/locales/langs/en.json
+++ b/rsf-design/src/locales/langs/en.json
@@ -309,6 +309,7 @@
     "placeholder": {
       "username": "Please enter your account",
       "password": "Please enter your password",
+      "tenant": "Please select a tenant",
       "slider": "Please slide to verify"
     },
     "sliderText": "Please slide to verify",
diff --git a/rsf-design/src/locales/langs/zh.json b/rsf-design/src/locales/langs/zh.json
index 3dd220c..12e8965 100644
--- a/rsf-design/src/locales/langs/zh.json
+++ b/rsf-design/src/locales/langs/zh.json
@@ -309,6 +309,7 @@
     "placeholder": {
       "username": "璇疯緭鍏ヨ处鍙�",
       "password": "璇疯緭鍏ュ瘑鐮�",
+      "tenant": "璇烽�夋嫨绉熸埛",
       "slider": "璇锋嫋鍔ㄦ粦鍧楀畬鎴愰獙璇�"
     },
     "sliderText": "鎸変綇婊戝潡鎷栧姩",
diff --git a/rsf-design/src/utils/storage/storage-config.js b/rsf-design/src/utils/storage/storage-config.js
index 5509cfb..8c4e8e7 100644
--- a/rsf-design/src/utils/storage/storage-config.js
+++ b/rsf-design/src/utils/storage/storage-config.js
@@ -66,6 +66,10 @@
 StorageConfig.VERSION_KEY = 'sys-version'
 StorageConfig.THEME_KEY = 'sys-theme'
 StorageConfig.LAST_USER_ID_KEY = 'sys-last-user-id'
+StorageConfig.LOGIN_REMEMBER_ENABLED_KEY = 'sys-login-remember-enabled'
+StorageConfig.LOGIN_REMEMBER_USERNAME_KEY = 'sys-login-remember-username'
+StorageConfig.LOGIN_REMEMBER_PASSWORD_KEY = 'sys-login-remember-password'
+StorageConfig.LOGIN_REMEMBER_TENANT_ID_KEY = 'sys-login-remember-tenant-id'
 StorageConfig.RESPONSIVE_MENU_TYPE_KEY = 'sys-responsive-menu-type'
 StorageConfig.SKIP_UPGRADE_VERSION = '1.0.0'
 StorageConfig.UPGRADE_DELAY = 1e3
diff --git a/rsf-design/src/views/auth/login/index.vue b/rsf-design/src/views/auth/login/index.vue
index 1f6abd5..2ed47e0 100644
--- a/rsf-design/src/views/auth/login/index.vue
+++ b/rsf-design/src/views/auth/login/index.vue
@@ -35,6 +35,23 @@
                 show-password
               />
             </ElFormItem>
+            <ElFormItem v-if="requiresTenantSelection" prop="tenantId">
+              <ElSelect
+                v-model="formData.tenantId"
+                class="w-full"
+                clearable
+                filterable
+                :loading="tenantLoading"
+                :placeholder="$t('login.placeholder.tenant')"
+              >
+                <ElOption
+                  v-for="tenant in tenantOptions"
+                  :key="tenant.id"
+                  :label="tenant.name"
+                  :value="tenant.id"
+                />
+              </ElSelect>
+            </ElFormItem>
 
             <div class="flex-cb mt-2 text-sm">
               <ElCheckbox v-model="formData.rememberPassword">{{
@@ -72,9 +89,16 @@
 
 <script setup>
   import AppConfig from '@/config'
+  import { StorageConfig } from '@/utils/storage/storage-config'
   import { useUserStore } from '@/store/modules/user'
   import { useI18n } from 'vue-i18n'
-  import { fetchGetUserInfo, fetchLogin, normalizeLoginResponse } from '@/api/auth'
+  import {
+    fetchGetSystemInfo,
+    fetchGetTenantList,
+    fetchGetUserInfo,
+    fetchLogin,
+    normalizeLoginResponse
+  } from '@/api/auth'
   import { ElNotification } from 'element-plus'
   defineOptions({ name: 'Login' })
   const { t, locale } = useI18n()
@@ -90,13 +114,92 @@
   const formData = reactive({
     username: '',
     password: '',
+    tenantId: '',
     rememberPassword: true
   })
+  const loginMode = ref('')
+  const tenantLoading = ref(false)
+  const tenantOptions = ref([])
+  const requiresTenantSelection = computed(() => loginMode.value === 'OFFLINE')
   const rules = computed(() => ({
     username: [{ required: true, message: t('login.placeholder.username'), trigger: 'blur' }],
-    password: [{ required: true, message: t('login.placeholder.password'), trigger: 'blur' }]
+    password: [{ required: true, message: t('login.placeholder.password'), trigger: 'blur' }],
+    tenantId: requiresTenantSelection.value
+      ? [{ required: true, message: t('login.placeholder.tenant'), trigger: 'change' }]
+      : []
   }))
   const loading = ref(false)
+
+  const hydrateRememberedLogin = () => {
+    const rememberEnabled =
+      localStorage.getItem(StorageConfig.LOGIN_REMEMBER_ENABLED_KEY) !== 'false'
+    formData.rememberPassword = rememberEnabled
+    if (rememberEnabled) {
+      formData.username = localStorage.getItem(StorageConfig.LOGIN_REMEMBER_USERNAME_KEY) || ''
+      formData.password = localStorage.getItem(StorageConfig.LOGIN_REMEMBER_PASSWORD_KEY) || ''
+    }
+  }
+
+  const persistRememberedTenant = (tenantId) => {
+    if (tenantId === '' || tenantId === null || tenantId === void 0) {
+      localStorage.removeItem(StorageConfig.LOGIN_REMEMBER_TENANT_ID_KEY)
+      return
+    }
+    localStorage.setItem(StorageConfig.LOGIN_REMEMBER_TENANT_ID_KEY, String(tenantId))
+  }
+
+  const applyDefaultTenantSelection = () => {
+    if (!requiresTenantSelection.value || tenantOptions.value.length === 0) {
+      formData.tenantId = ''
+      return
+    }
+
+    const rememberedTenantId = localStorage.getItem(StorageConfig.LOGIN_REMEMBER_TENANT_ID_KEY)
+    const matchedTenant = tenantOptions.value.find(
+      (item) => String(item.id) === String(rememberedTenantId)
+    )
+
+    formData.tenantId = matchedTenant?.id ?? tenantOptions.value[0].id
+    persistRememberedTenant(formData.tenantId)
+  }
+
+  const loadLoginSupports = async () => {
+    const systemInfo = await fetchGetSystemInfo()
+    loginMode.value = systemInfo?.mode || ''
+
+    if (!requiresTenantSelection.value) {
+      tenantOptions.value = []
+      formData.tenantId = ''
+      return
+    }
+
+    tenantLoading.value = true
+    try {
+      const tenants = await fetchGetTenantList()
+      tenantOptions.value = Array.isArray(tenants) ? tenants : []
+      applyDefaultTenantSelection()
+    } finally {
+      tenantLoading.value = false
+    }
+  }
+
+  const persistRememberedLogin = () => {
+    localStorage.setItem(
+      StorageConfig.LOGIN_REMEMBER_ENABLED_KEY,
+      String(Boolean(formData.rememberPassword))
+    )
+
+    if (formData.rememberPassword) {
+      localStorage.setItem(StorageConfig.LOGIN_REMEMBER_USERNAME_KEY, formData.username || '')
+      localStorage.setItem(StorageConfig.LOGIN_REMEMBER_PASSWORD_KEY, formData.password || '')
+    } else {
+      localStorage.removeItem(StorageConfig.LOGIN_REMEMBER_USERNAME_KEY)
+      localStorage.removeItem(StorageConfig.LOGIN_REMEMBER_PASSWORD_KEY)
+    }
+
+    persistRememberedTenant(formData.tenantId)
+  }
+
   const handleSubmit = async () => {
     if (!formRef.value) return
     try {
@@ -105,6 +208,7 @@
       loading.value = true
       const payload = normalizeLoginResponse(await fetchLogin(formData))
       if (!payload.accessToken) return
+      persistRememberedLogin()
       userStore.setToken(payload.accessToken, payload.refreshToken)
       userStore.setLoginStatus(true)
       const userInfo = await fetchGetUserInfo()
@@ -119,6 +223,21 @@
       loading.value = false
     }
   }
+
+  watch(
+    () => formData.tenantId,
+    (value) => {
+      if (requiresTenantSelection.value) {
+        persistRememberedTenant(value)
+      }
+    }
+  )
+
+  onMounted(async () => {
+    hydrateRememberedLogin()
+    await loadLoginSupports()
+  })
+
   const showLoginSuccessNotice = () => {
     setTimeout(() => {
       ElNotification({

--
Gitblit v1.9.1