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