refactor(auth): 移除多租户前端逻辑并修复接口加密密钥
- 删除租户选择组件 tenant-select.vue 及全局头部的引用 - 删除 fetchTenantList 接口调用及登录/注册页的租户列表加载逻辑 - 更新 .env.dev/.env.prod/.env.test 接口加密 RSA 公钥与私钥,与后端 Nacos api-decrypt 配置配对,修复登录 BadBlockException - 登录失败后自动刷新验证码(验证码已消费需重新获取) - pnpm-workspace.yaml 允许 es5-ext 执行构建脚本 - components.d.ts 同步自动生成的图标组件声明 refactor(auth): remove frontend multi-tenant logic and fix API encryption keys - Remove tenant-select component and its usage in global header - Remove fetchTenantList API and tenant list loading in login/register pages - Update RSA public/private keys in .env files to pair with backend Nacos api-decrypt config, fixing login BadBlockException - Refresh captcha after a failed login attempt - Allow es5-ext build scripts in pnpm-workspace.yaml
This commit is contained in:
@@ -21,6 +21,6 @@ VITE_APP_ENCRYPT=Y
|
||||
# AES 加密头标识
|
||||
VITE_HEADER_FLAG=encrypt-key
|
||||
# 接口加密传输 RSA 公钥与后端解密私钥对应 如更换需前后端一同更换
|
||||
VITE_APP_RSA_PUBLIC_KEY='MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKoR8mX0rGKLqzcWmOzbfj64K8ZIgOdHnzkXSOVOZbFu/TJhZ7rFAN+eaGkl3C4buccQd/EjEsj9ir7ijT7h96MCAwEAAQ=='
|
||||
VITE_APP_RSA_PUBLIC_KEY='MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDvEDuRIOM3oZPWj9Ukoc5pQklR4PFH6/clnjeFqjDLIgDyQvjxhgqAZQA+E9eD6qu6FsXPmK8djcL+nh3cFHz4pX473jDvO3Sve+8yL3VRQ0n2pRgQ2a01MJsy+WwTZCBYWf0VnLRIvANUoWQgy9vz94q7Va44dg7A1/3ICf+xAwIDAQAB'
|
||||
# 接口响应解密 RSA 私钥与后端加密公钥对应 如更换需前后端一同更换
|
||||
VITE_APP_RSA_PRIVATE_KEY='MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAmc3CuPiGL/LcIIm7zryCEIbl1SPzBkr75E2VMtxegyZ1lYRD+7TZGAPkvIsBcaMs6Nsy0L78n2qh+lIZMpLH8wIDAQABAkEAk82Mhz0tlv6IVCyIcw/s3f0E+WLmtPFyR9/WtV3Y5aaejUkU60JpX4m5xNR2VaqOLTZAYjW8Wy0aXr3zYIhhQQIhAMfqR9oFdYw1J9SsNc+CrhugAvKTi0+BF6VoL6psWhvbAiEAxPPNTmrkmrXwdm/pQQu3UOQmc2vCZ5tiKpW10CgJi8kCIFGkL6utxw93Ncj4exE/gPLvKcT+1Emnoox+O9kRXss5AiAMtYLJDaLEzPrAWcZeeSgSIzbL+ecokmFKSDDcRske6QIgSMkHedwND1olF8vlKsJUGK3BcdtM8w4Xq7BpSBwsloE='
|
||||
VITE_APP_RSA_PRIVATE_KEY='MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAObq7yrxfvyieZtTjAYyrdvi59tYTXxjO5ajmPCRSXBY9M9wQ1tli297JN6mnY53UJMNyOFNSZVi8WSFoIXjpR87FmvChJlzeN/dZdd3SEs48Ee66XKeSePYqxa8oO5GKDsnajgpsOHKXSeeVSIysiIPS2/WsEqk0In9P4w3RsRFAgMBAAECgYBiMEWwce24SPICnRzuScBpvmsudrbEDIH7BOd0a6LZlcnLJwZNJ7mJlshPsHNQb+WgEf135+BBGEhioPtn0yuTdEuKP4kB9UdYUKiayWCoWhJpesv7sAD4RDClV7dhuV+gcd1AXD+YzyRIPbGm0VC2U+4q8/+UPRpVjqskbLVTgQJBAPRpou7g3S8n4XB527kq0D8I3+ZYwMxZhszwhrCDpJU319+ucmpLVwYIzDmZVeID2QQdUaDfIEViFHu95xDrGiUCQQDx3YOKn3yaEctk/ERVn7hDAyAXUbd8/pv2b24/M/l1ZevlsFem8U4Jk5Mu64t3z3YGJoymEjQmbucwT01iKhehAkEAxlnccsRmfFh/KkqauKE4M4++NTAd9zlInpUsmZ+cN8UEGnF2RTEzRKBrLOt1uWCqBB7PGiE6DVTVjr7FAQPrSQJAT5yeY87DcONSk9cFlzmPqV8p/QME5rvYEnHzVBKDlkUKNPyqnWToTvaoh9U4fyNmsfeWbEOprszqhFhWHG3GgQJAK8+ynmyFhaw63+Hx2KU5zR4hVuQso2IzrEurGxCxybV6mR7VBerb4502+EPx3PmOgxQL+niUFhcMWxcvBFP9+A=='
|
||||
|
||||
@@ -18,6 +18,6 @@ VITE_APP_ENCRYPT=Y
|
||||
# AES 加密头标识
|
||||
VITE_HEADER_FLAG=encrypt-key
|
||||
# 接口加密传输 RSA 公钥与后端解密私钥对应 如更换需前后端一同更换
|
||||
VITE_APP_RSA_PUBLIC_KEY='MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKoR8mX0rGKLqzcWmOzbfj64K8ZIgOdHnzkXSOVOZbFu/TJhZ7rFAN+eaGkl3C4buccQd/EjEsj9ir7ijT7h96MCAwEAAQ=='
|
||||
VITE_APP_RSA_PUBLIC_KEY='MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDvEDuRIOM3oZPWj9Ukoc5pQklR4PFH6/clnjeFqjDLIgDyQvjxhgqAZQA+E9eD6qu6FsXPmK8djcL+nh3cFHz4pX473jDvO3Sve+8yL3VRQ0n2pRgQ2a01MJsy+WwTZCBYWf0VnLRIvANUoWQgy9vz94q7Va44dg7A1/3ICf+xAwIDAQAB'
|
||||
# 接口响应解密 RSA 私钥与后端加密公钥对应 如更换需前后端一同更换
|
||||
VITE_APP_RSA_PRIVATE_KEY='MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAmc3CuPiGL/LcIIm7zryCEIbl1SPzBkr75E2VMtxegyZ1lYRD+7TZGAPkvIsBcaMs6Nsy0L78n2qh+lIZMpLH8wIDAQABAkEAk82Mhz0tlv6IVCyIcw/s3f0E+WLmtPFyR9/WtV3Y5aaejUkU60JpX4m5xNR2VaqOLTZAYjW8Wy0aXr3zYIhhQQIhAMfqR9oFdYw1J9SsNc+CrhugAvKTi0+BF6VoL6psWhvbAiEAxPPNTmrkmrXwdm/pQQu3UOQmc2vCZ5tiKpW10CgJi8kCIFGkL6utxw93Ncj4exE/gPLvKcT+1Emnoox+O9kRXss5AiAMtYLJDaLEzPrAWcZeeSgSIzbL+ecokmFKSDDcRske6QIgSMkHedwND1olF8vlKsJUGK3BcdtM8w4Xq7BpSBwsloE='
|
||||
VITE_APP_RSA_PRIVATE_KEY='MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAObq7yrxfvyieZtTjAYyrdvi59tYTXxjO5ajmPCRSXBY9M9wQ1tli297JN6mnY53UJMNyOFNSZVi8WSFoIXjpR87FmvChJlzeN/dZdd3SEs48Ee66XKeSePYqxa8oO5GKDsnajgpsOHKXSeeVSIysiIPS2/WsEqk0In9P4w3RsRFAgMBAAECgYBiMEWwce24SPICnRzuScBpvmsudrbEDIH7BOd0a6LZlcnLJwZNJ7mJlshPsHNQb+WgEf135+BBGEhioPtn0yuTdEuKP4kB9UdYUKiayWCoWhJpesv7sAD4RDClV7dhuV+gcd1AXD+YzyRIPbGm0VC2U+4q8/+UPRpVjqskbLVTgQJBAPRpou7g3S8n4XB527kq0D8I3+ZYwMxZhszwhrCDpJU319+ucmpLVwYIzDmZVeID2QQdUaDfIEViFHu95xDrGiUCQQDx3YOKn3yaEctk/ERVn7hDAyAXUbd8/pv2b24/M/l1ZevlsFem8U4Jk5Mu64t3z3YGJoymEjQmbucwT01iKhehAkEAxlnccsRmfFh/KkqauKE4M4++NTAd9zlInpUsmZ+cN8UEGnF2RTEzRKBrLOt1uWCqBB7PGiE6DVTVjr7FAQPrSQJAT5yeY87DcONSk9cFlzmPqV8p/QME5rvYEnHzVBKDlkUKNPyqnWToTvaoh9U4fyNmsfeWbEOprszqhFhWHG3GgQJAK8+ynmyFhaw63+Hx2KU5zR4hVuQso2IzrEurGxCxybV6mR7VBerb4502+EPx3PmOgxQL+niUFhcMWxcvBFP9+A=='
|
||||
|
||||
@@ -18,6 +18,6 @@ VITE_APP_ENCRYPT=Y
|
||||
# AES 加密头标识
|
||||
VITE_HEADER_FLAG=encrypt-key
|
||||
# 接口加密传输 RSA 公钥与后端解密私钥对应 如更换需前后端一同更换
|
||||
VITE_APP_RSA_PUBLIC_KEY='MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKoR8mX0rGKLqzcWmOzbfj64K8ZIgOdHnzkXSOVOZbFu/TJhZ7rFAN+eaGkl3C4buccQd/EjEsj9ir7ijT7h96MCAwEAAQ=='
|
||||
VITE_APP_RSA_PUBLIC_KEY='MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDvEDuRIOM3oZPWj9Ukoc5pQklR4PFH6/clnjeFqjDLIgDyQvjxhgqAZQA+E9eD6qu6FsXPmK8djcL+nh3cFHz4pX473jDvO3Sve+8yL3VRQ0n2pRgQ2a01MJsy+WwTZCBYWf0VnLRIvANUoWQgy9vz94q7Va44dg7A1/3ICf+xAwIDAQAB'
|
||||
# 接口响应解密 RSA 私钥与后端加密公钥对应 如更换需前后端一同更换
|
||||
VITE_APP_RSA_PRIVATE_KEY='MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAmc3CuPiGL/LcIIm7zryCEIbl1SPzBkr75E2VMtxegyZ1lYRD+7TZGAPkvIsBcaMs6Nsy0L78n2qh+lIZMpLH8wIDAQABAkEAk82Mhz0tlv6IVCyIcw/s3f0E+WLmtPFyR9/WtV3Y5aaejUkU60JpX4m5xNR2VaqOLTZAYjW8Wy0aXr3zYIhhQQIhAMfqR9oFdYw1J9SsNc+CrhugAvKTi0+BF6VoL6psWhvbAiEAxPPNTmrkmrXwdm/pQQu3UOQmc2vCZ5tiKpW10CgJi8kCIFGkL6utxw93Ncj4exE/gPLvKcT+1Emnoox+O9kRXss5AiAMtYLJDaLEzPrAWcZeeSgSIzbL+ecokmFKSDDcRske6QIgSMkHedwND1olF8vlKsJUGK3BcdtM8w4Xq7BpSBwsloE='
|
||||
VITE_APP_RSA_PRIVATE_KEY='MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAObq7yrxfvyieZtTjAYyrdvi59tYTXxjO5ajmPCRSXBY9M9wQ1tli297JN6mnY53UJMNyOFNSZVi8WSFoIXjpR87FmvChJlzeN/dZdd3SEs48Ee66XKeSePYqxa8oO5GKDsnajgpsOHKXSeeVSIysiIPS2/WsEqk0In9P4w3RsRFAgMBAAECgYBiMEWwce24SPICnRzuScBpvmsudrbEDIH7BOd0a6LZlcnLJwZNJ7mJlshPsHNQb+WgEf135+BBGEhioPtn0yuTdEuKP4kB9UdYUKiayWCoWhJpesv7sAD4RDClV7dhuV+gcd1AXD+YzyRIPbGm0VC2U+4q8/+UPRpVjqskbLVTgQJBAPRpou7g3S8n4XB527kq0D8I3+ZYwMxZhszwhrCDpJU319+ucmpLVwYIzDmZVeID2QQdUaDfIEViFHu95xDrGiUCQQDx3YOKn3yaEctk/ERVn7hDAyAXUbd8/pv2b24/M/l1ZevlsFem8U4Jk5Mu64t3z3YGJoymEjQmbucwT01iKhehAkEAxlnccsRmfFh/KkqauKE4M4++NTAd9zlInpUsmZ+cN8UEGnF2RTEzRKBrLOt1uWCqBB7PGiE6DVTVjr7FAQPrSQJAT5yeY87DcONSk9cFlzmPqV8p/QME5rvYEnHzVBKDlkUKNPyqnWToTvaoh9U4fyNmsfeWbEOprszqhFhWHG3GgQJAK8+ynmyFhaw63+Hx2KU5zR4hVuQso2IzrEurGxCxybV6mR7VBerb4502+EPx3PmOgxQL+niUFhcMWxcvBFP9+A=='
|
||||
|
||||
@@ -2,6 +2,7 @@ packages:
|
||||
- 'packages/*'
|
||||
allowBuilds:
|
||||
'@parcel/watcher': false
|
||||
es5-ext: true
|
||||
esbuild: false
|
||||
simple-git-hooks: false
|
||||
vue-demi: false
|
||||
|
||||
@@ -1,103 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, onMounted, ref } from 'vue';
|
||||
import type { SelectOption } from 'naive-ui';
|
||||
import { useLoading } from '@sa/hooks';
|
||||
import { fetchTenantList } from '@/service/api';
|
||||
import { fetchChangeTenant, fetchClearTenant } from '@/service/api/system/tenant';
|
||||
import { useAppStore } from '@/store/modules/app';
|
||||
import { useTabStore } from '@/store/modules/tab';
|
||||
import { useAuthStore } from '@/store/modules/auth';
|
||||
import { useRouterPush } from '@/hooks/common/router';
|
||||
|
||||
defineOptions({ name: 'TenantSelect' });
|
||||
|
||||
interface Props {
|
||||
clearable?: boolean;
|
||||
}
|
||||
|
||||
withDefaults(defineProps<Props>(), {
|
||||
clearable: false
|
||||
});
|
||||
|
||||
const appStore = useAppStore();
|
||||
const { userInfo } = useAuthStore();
|
||||
const { clearTabs } = useTabStore();
|
||||
const { toHome } = useRouterPush();
|
||||
|
||||
const tenantId = defineModel<CommonType.IdType>('tenantId', { required: false, default: undefined });
|
||||
const enabled = defineModel<boolean>('enabled', { required: false, default: false });
|
||||
|
||||
const lastSelected = ref<CommonType.IdType>();
|
||||
|
||||
const tenantOption = ref<SelectOption[]>([]);
|
||||
const { loading, startLoading, endLoading } = useLoading();
|
||||
|
||||
const showTenantSelect = computed<boolean>(() => {
|
||||
return userInfo.user?.userId === 1 && enabled.value;
|
||||
});
|
||||
|
||||
/**
|
||||
* 关闭当前页面并刷新
|
||||
*
|
||||
* @param msg 提示信息
|
||||
* @param val 租户ID
|
||||
*/
|
||||
async function closeAndRefresh(msg: string, val: CommonType.IdType = '') {
|
||||
lastSelected.value = val;
|
||||
window.$message?.success(msg);
|
||||
clearTabs([], true);
|
||||
toHome();
|
||||
appStore.reloadPage(500);
|
||||
}
|
||||
|
||||
async function handleChangeTenant(_tenantId: CommonType.IdType) {
|
||||
if (!_tenantId) {
|
||||
return;
|
||||
}
|
||||
if (lastSelected.value === _tenantId) {
|
||||
return;
|
||||
}
|
||||
await fetchChangeTenant(_tenantId);
|
||||
closeAndRefresh('切换租户成功', _tenantId);
|
||||
}
|
||||
|
||||
async function handleClearTenant() {
|
||||
await fetchClearTenant();
|
||||
closeAndRefresh('切换为默认租户');
|
||||
}
|
||||
|
||||
async function handleFetchTenantList() {
|
||||
startLoading();
|
||||
const { data, error } = await fetchTenantList();
|
||||
if (error) return;
|
||||
enabled.value = data.tenantEnabled;
|
||||
if (data.tenantEnabled) {
|
||||
tenantOption.value = data.voList.map(tenant => {
|
||||
return {
|
||||
label: tenant.companyName,
|
||||
value: tenant.tenantId
|
||||
};
|
||||
});
|
||||
}
|
||||
endLoading();
|
||||
}
|
||||
onMounted(async () => {
|
||||
if (userInfo.user?.userId !== 1) {
|
||||
return;
|
||||
}
|
||||
await handleFetchTenantList();
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<NSelect
|
||||
v-if="showTenantSelect"
|
||||
v-model:value="tenantId"
|
||||
:clearable="clearable"
|
||||
placeholder="请选择租户"
|
||||
:options="tenantOption"
|
||||
:loading="loading"
|
||||
@update:value="handleChangeTenant"
|
||||
@clear="handleClearTenant"
|
||||
/>
|
||||
</template>
|
||||
@@ -1,9 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
import { useFullscreen } from '@vueuse/core';
|
||||
import { GLOBAL_HEADER_MENU_ID } from '@/constants/app';
|
||||
import { useAppStore } from '@/store/modules/app';
|
||||
import { useAuthStore } from '@/store/modules/auth';
|
||||
import { useThemeStore } from '@/store/modules/theme';
|
||||
import GlobalLogo from '../global-logo/index.vue';
|
||||
import GlobalBreadcrumb from '../global-breadcrumb/index.vue';
|
||||
@@ -28,11 +26,8 @@ interface Props {
|
||||
defineProps<Props>();
|
||||
|
||||
const appStore = useAppStore();
|
||||
const authStore = useAuthStore();
|
||||
const themeStore = useThemeStore();
|
||||
const { isFullscreen, toggle } = useFullscreen();
|
||||
|
||||
const tenantId = ref<CommonType.IdType>(authStore.userInfo?.user?.tenantId || '000000');
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -44,7 +39,6 @@ const tenantId = ref<CommonType.IdType>(authStore.userInfo?.user?.tenantId || '0
|
||||
<GlobalBreadcrumb v-if="!appStore.isMobile" class="ml-12px" />
|
||||
</div>
|
||||
<div class="h-full flex-y-center justify-end">
|
||||
<TenantSelect v-if="!appStore.isMobile" v-model:value="tenantId" class="mr-12px w-150px" />
|
||||
<GlobalSearch v-if="themeStore.header.globalSearch.visible && !appStore.isMobile" />
|
||||
<MessageButton />
|
||||
<FullScreen v-if="!appStore.isMobile" :full="isFullscreen" @click="toggle" />
|
||||
|
||||
@@ -1,13 +1,5 @@
|
||||
import { request } from '../request';
|
||||
|
||||
/** Get tenant list */
|
||||
export function fetchTenantList() {
|
||||
return request<Api.Auth.LoginTenant>({
|
||||
url: '/auth/tenant/list',
|
||||
method: 'get'
|
||||
});
|
||||
}
|
||||
|
||||
/** Get image code */
|
||||
export function fetchCaptchaCode() {
|
||||
return request<Api.Auth.CaptchaCode>({
|
||||
|
||||
Vendored
+12
@@ -51,11 +51,17 @@ declare module 'vue' {
|
||||
IconMaterialSymbolsUploadRounded: typeof import('~icons/material-symbols/upload-rounded')['default']
|
||||
IconMaterialSymbolsWarningOutlineRounded: typeof import('~icons/material-symbols/warning-outline-rounded')['default']
|
||||
IconMdiArrowDownThin: typeof import('~icons/mdi/arrow-down-thin')['default']
|
||||
IconMdiArrowRightThick: typeof import('~icons/mdi/arrow-right-thick')['default']
|
||||
IconMdiArrowUpThin: typeof import('~icons/mdi/arrow-up-thin')['default']
|
||||
IconMdiCheckCircleOutline: typeof import('~icons/mdi/check-circle-outline')['default']
|
||||
IconMdiDrag: typeof import('~icons/mdi/drag')['default']
|
||||
IconMdiGithub: typeof import('~icons/mdi/github')['default']
|
||||
IconMdiKeyboardEsc: typeof import('~icons/mdi/keyboard-esc')['default']
|
||||
IconMdiKeyboardReturn: typeof import('~icons/mdi/keyboard-return')['default']
|
||||
IconMdiLoading: typeof import('~icons/mdi/loading')['default']
|
||||
IconMdiRefresh: typeof import('~icons/mdi/refresh')['default']
|
||||
IconMdiShieldAlertOutline: typeof import('~icons/mdi/shield-alert-outline')['default']
|
||||
IconMdiShieldCheckOutline: typeof import('~icons/mdi/shield-check-outline')['default']
|
||||
IconOcticonPin16: typeof import('~icons/octicon/pin16')['default']
|
||||
IconOcticonPinSlash16: typeof import('~icons/octicon/pin-slash16')['default']
|
||||
IconQuillCollapse: typeof import('~icons/quill/collapse')['default']
|
||||
@@ -202,11 +208,17 @@ declare global {
|
||||
const IconMaterialSymbolsUploadRounded: typeof import('~icons/material-symbols/upload-rounded')['default']
|
||||
const IconMaterialSymbolsWarningOutlineRounded: typeof import('~icons/material-symbols/warning-outline-rounded')['default']
|
||||
const IconMdiArrowDownThin: typeof import('~icons/mdi/arrow-down-thin')['default']
|
||||
const IconMdiArrowRightThick: typeof import('~icons/mdi/arrow-right-thick')['default']
|
||||
const IconMdiArrowUpThin: typeof import('~icons/mdi/arrow-up-thin')['default']
|
||||
const IconMdiCheckCircleOutline: typeof import('~icons/mdi/check-circle-outline')['default']
|
||||
const IconMdiDrag: typeof import('~icons/mdi/drag')['default']
|
||||
const IconMdiGithub: typeof import('~icons/mdi/github')['default']
|
||||
const IconMdiKeyboardEsc: typeof import('~icons/mdi/keyboard-esc')['default']
|
||||
const IconMdiKeyboardReturn: typeof import('~icons/mdi/keyboard-return')['default']
|
||||
const IconMdiLoading: typeof import('~icons/mdi/loading')['default']
|
||||
const IconMdiRefresh: typeof import('~icons/mdi/refresh')['default']
|
||||
const IconMdiShieldAlertOutline: typeof import('~icons/mdi/shield-alert-outline')['default']
|
||||
const IconMdiShieldCheckOutline: typeof import('~icons/mdi/shield-check-outline')['default']
|
||||
const IconOcticonPin16: typeof import('~icons/octicon/pin16')['default']
|
||||
const IconOcticonPinSlash16: typeof import('~icons/octicon/pin-slash16')['default']
|
||||
const IconQuillCollapse: typeof import('~icons/quill/collapse')['default']
|
||||
|
||||
@@ -3,7 +3,7 @@ import { computed, reactive, ref } from 'vue';
|
||||
import type { SelectOption } from 'naive-ui';
|
||||
import { useLoading } from '@sa/hooks';
|
||||
import CryptoJS from 'crypto-js';
|
||||
import { fetchCaptchaCode, fetchTenantList } from '@/service/api';
|
||||
import { fetchCaptchaCode } from '@/service/api';
|
||||
import { fetchSocialAuthBinding } from '@/service/api/system';
|
||||
import { useAuthStore } from '@/store/modules/auth';
|
||||
import { useRouterPush } from '@/hooks/common/router';
|
||||
@@ -22,7 +22,7 @@ const authStore = useAuthStore();
|
||||
const { toggleLoginModule } = useRouterPush();
|
||||
const { formRef, validate } = useNaiveForm();
|
||||
const { loading: codeLoading, startLoading: startCodeLoading, endLoading: endCodeLoading } = useLoading();
|
||||
const { loading: tenantLoading, startLoading: startTenantLoading, endLoading: endTenantLoading } = useLoading();
|
||||
const { loading: tenantLoading } = useLoading();
|
||||
|
||||
const codeUrl = ref<string>();
|
||||
const captchaEnabled = ref<boolean>(false);
|
||||
@@ -55,24 +55,6 @@ const rules = computed<Record<RuleKey, App.Global.FormRule[]>>(() => {
|
||||
return loginRules;
|
||||
});
|
||||
|
||||
async function handleFetchTenantList() {
|
||||
startTenantLoading();
|
||||
const { data, error } = await fetchTenantList();
|
||||
if (error) return;
|
||||
tenantEnabled.value = data.tenantEnabled;
|
||||
if (data.tenantEnabled) {
|
||||
tenantOption.value = data.voList.map(tenant => {
|
||||
return {
|
||||
label: tenant.companyName,
|
||||
value: tenant.tenantId
|
||||
};
|
||||
});
|
||||
}
|
||||
endTenantLoading();
|
||||
}
|
||||
|
||||
handleFetchTenantList();
|
||||
|
||||
async function handleSubmit() {
|
||||
await validate();
|
||||
// 勾选了需要记住密码设置在 localStorage 中设置记住用户名和密码
|
||||
@@ -86,6 +68,7 @@ async function handleSubmit() {
|
||||
try {
|
||||
await authStore.login(model);
|
||||
} catch {
|
||||
// 登录失败后验证码已消费,刷新并重置
|
||||
handleFetchCaptchaCode();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
import { computed, reactive, ref } from 'vue';
|
||||
import type { SelectOption } from 'naive-ui';
|
||||
import { useLoading } from '@sa/hooks';
|
||||
import { fetchCaptchaCode, fetchRegister, fetchTenantList } from '@/service/api';
|
||||
import { fetchCaptchaCode, fetchRegister } from '@/service/api';
|
||||
import { useRouterPush } from '@/hooks/common/router';
|
||||
import { useFormRules, useNaiveForm } from '@/hooks/common/form';
|
||||
import { $t } from '@/locales';
|
||||
@@ -72,20 +72,6 @@ async function handleSubmit() {
|
||||
}
|
||||
}
|
||||
|
||||
async function handleFetchTenantList() {
|
||||
const { data, error } = await fetchTenantList();
|
||||
if (error) return;
|
||||
tenantEnabled.value = data.tenantEnabled;
|
||||
tenantOption.value = data.voList.map(tenant => {
|
||||
return {
|
||||
label: tenant.companyName,
|
||||
value: tenant.tenantId
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
handleFetchTenantList();
|
||||
|
||||
async function handleFetchCaptchaCode() {
|
||||
startCodeLoading();
|
||||
const { data, error } = await fetchCaptchaCode();
|
||||
|
||||
Reference in New Issue
Block a user