zhou zhou
6 小时以前 7b8bb6b1d8d2505c06fa3740349b96798ec8c900
#登录页修复
5个文件已修改
153 ■■■■■ 已修改文件
rsf-design/src/api/auth.js 24 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-design/src/locales/langs/en.json 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-design/src/locales/langs/zh.json 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-design/src/utils/storage/storage-config.js 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rsf-design/src/views/auth/login/index.vue 123 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
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,
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",
rsf-design/src/locales/langs/zh.json
@@ -309,6 +309,7 @@
    "placeholder": {
      "username": "请输入账号",
      "password": "请输入密码",
      "tenant": "请选择租户",
      "slider": "请拖动滑块完成验证"
    },
    "sliderText": "按住滑块拖动",
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
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({