登录支持选择租户
parent
356298e599
commit
435c2f7d2b
|
|
@ -89,3 +89,29 @@ export const reqCheck = (data: any) => {
|
||||||
export const smsResetPassword = (data: any) => {
|
export const smsResetPassword = (data: any) => {
|
||||||
return request.post({ url: '/system/auth/reset-password', data })
|
return request.post({ url: '/system/auth/reset-password', data })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 获取用户的租户列表(未登录状态)
|
||||||
|
export interface UserTenantListVO {
|
||||||
|
username: string
|
||||||
|
password: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TenantInfo {
|
||||||
|
tenantId: number
|
||||||
|
tenantName: string
|
||||||
|
isDefault: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface UserTenantListRespVO {
|
||||||
|
userId: number
|
||||||
|
username: string
|
||||||
|
nickname: string
|
||||||
|
tenants: TenantInfo[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getUserTenantList = (data: UserTenantListVO) => {
|
||||||
|
return request.post({
|
||||||
|
url: '/system/auth/get-user-tenant-list',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
export type UserLoginVO = {
|
export type UserLoginVO = {
|
||||||
|
tenantId?: number
|
||||||
username: string
|
username: string
|
||||||
password: string
|
password: string
|
||||||
captchaVerification: string
|
captchaVerification: string
|
||||||
|
|
|
||||||
|
|
@ -128,7 +128,7 @@ export default {
|
||||||
remember: '记住我',
|
remember: '记住我',
|
||||||
hasUser: '已有账号?去登录',
|
hasUser: '已有账号?去登录',
|
||||||
forgetPassword: '忘记密码?',
|
forgetPassword: '忘记密码?',
|
||||||
tenantNamePlaceholder: '请输入租户名称',
|
tenantNamePlaceholder: '请选择要登录的小区',
|
||||||
usernamePlaceholder: '请输入用户名',
|
usernamePlaceholder: '请输入用户名',
|
||||||
passwordPlaceholder: '请输入密码',
|
passwordPlaceholder: '请输入密码',
|
||||||
codePlaceholder: '请输入验证码',
|
codePlaceholder: '请输入验证码',
|
||||||
|
|
@ -455,4 +455,4 @@ export default {
|
||||||
preview: '预览'
|
preview: '预览'
|
||||||
},
|
},
|
||||||
'OAuth 2.0': 'OAuth 2.0' // 避免菜单名是 OAuth 2.0 时,一直 warn 报错
|
'OAuth 2.0': 'OAuth 2.0' // 避免菜单名是 OAuth 2.0 时,一直 warn 报错
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,17 +15,6 @@
|
||||||
<LoginFormTitle class="w-full" />
|
<LoginFormTitle class="w-full" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="24" class="px-10px">
|
|
||||||
<el-form-item v-if="loginData.tenantEnable === 'true'" prop="tenantName">
|
|
||||||
<el-input
|
|
||||||
v-model="loginData.loginForm.tenantName"
|
|
||||||
:placeholder="t('login.tenantNamePlaceholder')"
|
|
||||||
:prefix-icon="iconHouse"
|
|
||||||
link
|
|
||||||
type="primary"
|
|
||||||
/>
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
<el-col :span="24" class="px-10px">
|
<el-col :span="24" class="px-10px">
|
||||||
<el-form-item prop="username">
|
<el-form-item prop="username">
|
||||||
<el-input
|
<el-input
|
||||||
|
|
@ -47,6 +36,25 @@
|
||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
|
<el-col :span="24" class="px-10px">
|
||||||
|
<el-form-item v-if="loginData.tenantEnable === 'true'" prop="tenantId">
|
||||||
|
<el-select
|
||||||
|
v-model="loginData.loginForm.tenantId"
|
||||||
|
:placeholder="t('login.tenantNamePlaceholder')"
|
||||||
|
:prefix-icon="iconHouse"
|
||||||
|
style="width: 100%"
|
||||||
|
:disabled="tenantList.length === 0"
|
||||||
|
@keyup.enter="getCode()"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="tenant in tenantList"
|
||||||
|
:key="tenant.tenantId"
|
||||||
|
:label="tenant.tenantName"
|
||||||
|
:value="tenant.tenantId"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
<el-col :span="24" class="px-10px mt-[-20px] mb-[-20px]">
|
<el-col :span="24" class="px-10px mt-[-20px] mb-[-20px]">
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-row justify="space-between" style="width: 100%">
|
<el-row justify="space-between" style="width: 100%">
|
||||||
|
|
@ -117,20 +125,28 @@ const redirect = ref<string>('')
|
||||||
const loginLoading = ref(false)
|
const loginLoading = ref(false)
|
||||||
const verify = ref()
|
const verify = ref()
|
||||||
const captchaType = ref('blockPuzzle') // blockPuzzle 滑块 clickWord 点击文字 pictureWord 文字验证码
|
const captchaType = ref('blockPuzzle') // blockPuzzle 滑块 clickWord 点击文字 pictureWord 文字验证码
|
||||||
|
const tenantList = ref<LoginApi.TenantInfo[]>([])
|
||||||
|
const isFetchingTenants = ref(false)
|
||||||
|
|
||||||
const getShow = computed(() => unref(getLoginState) === LoginStateEnum.LOGIN)
|
const getShow = computed(() => unref(getLoginState) === LoginStateEnum.LOGIN)
|
||||||
|
|
||||||
const LoginRules = {
|
const LoginRules = {
|
||||||
tenantName: [required],
|
|
||||||
username: [required],
|
username: [required],
|
||||||
password: [required]
|
password: [required],
|
||||||
|
tenantId: [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: '请选择租户',
|
||||||
|
trigger: 'change'
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
const loginData = reactive({
|
const loginData = reactive({
|
||||||
isShowPassword: false,
|
isShowPassword: false,
|
||||||
captchaEnable: import.meta.env.VITE_APP_CAPTCHA_ENABLE,
|
captchaEnable: import.meta.env.VITE_APP_CAPTCHA_ENABLE,
|
||||||
tenantEnable: import.meta.env.VITE_APP_TENANT_ENABLE,
|
tenantEnable: import.meta.env.VITE_APP_TENANT_ENABLE,
|
||||||
loginForm: {
|
loginForm: {
|
||||||
tenantName: import.meta.env.VITE_APP_DEFAULT_LOGIN_TENANT || '',
|
tenantId: undefined as number | undefined,
|
||||||
username: import.meta.env.VITE_APP_DEFAULT_LOGIN_USERNAME || '',
|
username: import.meta.env.VITE_APP_DEFAULT_LOGIN_USERNAME || '',
|
||||||
password: import.meta.env.VITE_APP_DEFAULT_LOGIN_PASSWORD || '',
|
password: import.meta.env.VITE_APP_DEFAULT_LOGIN_PASSWORD || '',
|
||||||
captchaVerification: '',
|
captchaVerification: '',
|
||||||
|
|
@ -145,8 +161,94 @@ const socialList = [
|
||||||
{ icon: 'ant-design:alipay-circle-filled', type: 0 }
|
{ icon: 'ant-design:alipay-circle-filled', type: 0 }
|
||||||
]
|
]
|
||||||
|
|
||||||
|
// 获取租户列表
|
||||||
|
const fetchTenantList = async () => {
|
||||||
|
if (loginData.tenantEnable !== 'true') {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const username = loginData.loginForm.username?.trim()
|
||||||
|
const password = loginData.loginForm.password?.trim()
|
||||||
|
|
||||||
|
// 只有当用户名和密码都不为空时才获取租户列表
|
||||||
|
if (!username || !password) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 防止重复请求
|
||||||
|
if (isFetchingTenants.value) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
isFetchingTenants.value = true
|
||||||
|
|
||||||
|
try {
|
||||||
|
const res = await LoginApi.getUserTenantList({
|
||||||
|
username,
|
||||||
|
password
|
||||||
|
})
|
||||||
|
|
||||||
|
if (!res || !res.tenants || res.tenants.length === 0) {
|
||||||
|
message.error('无权限访问该系统')
|
||||||
|
tenantList.value = []
|
||||||
|
loginData.loginForm.tenantId = undefined
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
tenantList.value = res.tenants
|
||||||
|
|
||||||
|
// 默认选中第一个租户
|
||||||
|
if (res.tenants.length > 0) {
|
||||||
|
loginData.loginForm.tenantId = res.tenants[0].tenantId
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取租户列表失败:', error)
|
||||||
|
tenantList.value = []
|
||||||
|
loginData.loginForm.tenantId = undefined
|
||||||
|
} finally {
|
||||||
|
isFetchingTenants.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 获取验证码
|
// 获取验证码
|
||||||
const getCode = async () => {
|
const getCode = async () => {
|
||||||
|
// 如果开启了租户功能且还没有获取租户列表,先获取
|
||||||
|
if (loginData.tenantEnable === 'true' && tenantList.value.length === 0) {
|
||||||
|
const username = loginData.loginForm.username?.trim()
|
||||||
|
const password = loginData.loginForm.password?.trim()
|
||||||
|
|
||||||
|
if (!username || !password) {
|
||||||
|
message.error('请输入用户名和密码')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取租户列表
|
||||||
|
await fetchTenantList()
|
||||||
|
|
||||||
|
// 如果获取后仍然没有租户列表,说明无权限
|
||||||
|
if (tenantList.value.length === 0) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果只有一个租户,自动选中并继续登录流程
|
||||||
|
if (tenantList.value.length === 1) {
|
||||||
|
loginData.loginForm.tenantId = tenantList.value[0].tenantId
|
||||||
|
// 单租户直接继续登录
|
||||||
|
} else {
|
||||||
|
// 如果有多个租户但未选择,提示用户选择
|
||||||
|
if (!loginData.loginForm.tenantId) {
|
||||||
|
message.error('请选择租户')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (loginData.tenantEnable === 'true' && tenantList.value.length > 0) {
|
||||||
|
// 已有租户列表,验证是否已选择
|
||||||
|
if (!loginData.loginForm.tenantId) {
|
||||||
|
message.error('请选择租户')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 情况一,未开启:则直接登录
|
// 情况一,未开启:则直接登录
|
||||||
if (loginData.captchaEnable === 'false') {
|
if (loginData.captchaEnable === 'false') {
|
||||||
await handleLogin({})
|
await handleLogin({})
|
||||||
|
|
@ -156,11 +258,10 @@ const getCode = async () => {
|
||||||
verify.value.show()
|
verify.value.show()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 获取租户 ID
|
// 设置租户ID
|
||||||
const getTenantId = async () => {
|
const setTenantId = () => {
|
||||||
if (loginData.tenantEnable === 'true') {
|
if (loginData.loginForm.tenantId) {
|
||||||
const res = await LoginApi.getTenantIdByName(loginData.loginForm.tenantName)
|
authUtil.setTenantId(loginData.loginForm.tenantId)
|
||||||
authUtil.setTenantId(res)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 记住我
|
// 记住我
|
||||||
|
|
@ -171,8 +272,7 @@ const getLoginFormCache = () => {
|
||||||
...loginData.loginForm,
|
...loginData.loginForm,
|
||||||
username: loginForm.username ? loginForm.username : loginData.loginForm.username,
|
username: loginForm.username ? loginForm.username : loginData.loginForm.username,
|
||||||
password: loginForm.password ? loginForm.password : loginData.loginForm.password,
|
password: loginForm.password ? loginForm.password : loginData.loginForm.password,
|
||||||
rememberMe: loginForm.rememberMe,
|
rememberMe: loginForm.rememberMe
|
||||||
tenantName: loginForm.tenantName ? loginForm.tenantName : loginData.loginForm.tenantName
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -182,7 +282,6 @@ const getTenantByWebsite = async () => {
|
||||||
const website = location.host
|
const website = location.host
|
||||||
const res = await LoginApi.getTenantByWebsite(website)
|
const res = await LoginApi.getTenantByWebsite(website)
|
||||||
if (res) {
|
if (res) {
|
||||||
loginData.loginForm.tenantName = res.name
|
|
||||||
authUtil.setTenantId(res.id)
|
authUtil.setTenantId(res.id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -192,7 +291,7 @@ const loading = ref() // ElLoading.service 返回的实例
|
||||||
const handleLogin = async (params: any) => {
|
const handleLogin = async (params: any) => {
|
||||||
loginLoading.value = true
|
loginLoading.value = true
|
||||||
try {
|
try {
|
||||||
await getTenantId()
|
setTenantId()
|
||||||
const data = await validForm()
|
const data = await validForm()
|
||||||
if (!data) {
|
if (!data) {
|
||||||
return
|
return
|
||||||
|
|
@ -236,8 +335,8 @@ const doSocialLogin = async (type: number) => {
|
||||||
} else {
|
} else {
|
||||||
loginLoading.value = true
|
loginLoading.value = true
|
||||||
if (loginData.tenantEnable === 'true') {
|
if (loginData.tenantEnable === 'true') {
|
||||||
// 尝试先通过 tenantName 获取租户
|
// 尝试先通过 tenantId 获取租户
|
||||||
await getTenantId()
|
setTenantId()
|
||||||
// 如果获取不到,则需要弹出提示,进行处理
|
// 如果获取不到,则需要弹出提示,进行处理
|
||||||
if (!authUtil.getTenantId()) {
|
if (!authUtil.getTenantId()) {
|
||||||
try {
|
try {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue