mirror of
https://github.com/continew-org/continew-admin-ui.git
synced 2025-11-10 14:57:09 +08:00
chore(login): 调整租户登录逻辑
This commit is contained in:
@@ -10,10 +10,7 @@ const login = (req: T.AccountLoginReq | T.PhoneLoginReq | T.EmailLoginReq, tenan
|
|||||||
if (tenantCode) {
|
if (tenantCode) {
|
||||||
headers['X-Tenant-Code'] = tenantCode
|
headers['X-Tenant-Code'] = tenantCode
|
||||||
}
|
}
|
||||||
return http.requestNative({
|
return http.post<T.LoginResp>(`${BASE_URL}/login`, req, {
|
||||||
url: `${BASE_URL}/login`,
|
|
||||||
data: req,
|
|
||||||
method: 'post',
|
|
||||||
headers,
|
headers,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -80,6 +80,7 @@ export interface EmailLoginReq extends AuthReq {
|
|||||||
/** 登录响应类型 */
|
/** 登录响应类型 */
|
||||||
export interface LoginResp {
|
export interface LoginResp {
|
||||||
token: string
|
token: string
|
||||||
|
tenantId: string
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 第三方登录授权类型 */
|
/** 第三方登录授权类型 */
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ export function listTenantPackageDict(query?: { description: string, status: num
|
|||||||
return http.get<LabelValueState[]>(`${BASE_URL}/dict/package`, query)
|
return http.get<LabelValueState[]>(`${BASE_URL}/dict/package`, query)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @desc 根据域名查询租户编码 */
|
/** @desc 根据域名查询租户ID */
|
||||||
export function getTenantCodeByDomain(domain: string) {
|
export function getTenantIdByDomain(domain: string) {
|
||||||
return http.get<string>(`${BASE_URL}/code/domain`, { domain })
|
return http.get<string>(`${BASE_URL}/id/domain`, { domain })
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ export * from './modules/route'
|
|||||||
export * from './modules/tabs'
|
export * from './modules/tabs'
|
||||||
export * from './modules/dict'
|
export * from './modules/dict'
|
||||||
export * from './modules/user'
|
export * from './modules/user'
|
||||||
export * from './modules/tenant'
|
|
||||||
|
|
||||||
const pinia = createPinia()
|
const pinia = createPinia()
|
||||||
pinia.use(piniaPluginPersistedstate)
|
pinia.use(piniaPluginPersistedstate)
|
||||||
|
|||||||
@@ -1,31 +1,29 @@
|
|||||||
import { defineStore } from 'pinia'
|
import { defineStore } from 'pinia'
|
||||||
import { computed, reactive } from 'vue'
|
import { computed, ref } from 'vue'
|
||||||
|
|
||||||
const storeSetup = () => {
|
export const useTenantStore = defineStore('tenant', () => {
|
||||||
interface TenantInfo {
|
const tenantEnabled = ref(false)
|
||||||
tenantEnabled: boolean
|
const tenantId = ref('')
|
||||||
tenantCode: string
|
|
||||||
|
const setTenantEnable = (status: boolean) => {
|
||||||
|
tenantEnabled.value = status
|
||||||
}
|
}
|
||||||
const tenantInfo = reactive<TenantInfo>({
|
const setTenantId = (id: string) => {
|
||||||
tenantEnabled: false,
|
tenantId.value = id
|
||||||
tenantCode: '',
|
}
|
||||||
|
|
||||||
|
// 判断是否需要用户输入租户编码
|
||||||
|
const needInputTenantId = computed(() => {
|
||||||
|
return tenantEnabled.value && !tenantId.value
|
||||||
})
|
})
|
||||||
const tenantEnabled = computed(() => tenantInfo.tenantEnabled)
|
|
||||||
const tenantCode = computed(() => tenantInfo.tenantCode)
|
|
||||||
const setTenantEnable = (tenantStatus: boolean) => {
|
|
||||||
tenantInfo.tenantEnabled = tenantStatus
|
|
||||||
}
|
|
||||||
const setTenantCode = (tenantCode: string) => {
|
|
||||||
tenantInfo.tenantCode = tenantCode
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
tenantCode,
|
|
||||||
tenantEnabled,
|
|
||||||
setTenantCode,
|
|
||||||
setTenantEnable,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const useTenantStore = defineStore('tenant', storeSetup, {
|
return {
|
||||||
persist: { paths: ['tenantInfo'], storage: localStorage },
|
tenantEnabled,
|
||||||
|
tenantId,
|
||||||
|
setTenantEnable,
|
||||||
|
setTenantId,
|
||||||
|
needInputTenantId,
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
persist: { paths: ['tenantEnabled', 'tenantId'], storage: localStorage },
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { defineStore } from 'pinia'
|
import { defineStore } from 'pinia'
|
||||||
import { computed, reactive, ref } from 'vue'
|
import { computed, reactive, ref } from 'vue'
|
||||||
|
import { useTenantStore } from './tenant'
|
||||||
import { resetRouter } from '@/router'
|
import { resetRouter } from '@/router'
|
||||||
import {
|
import {
|
||||||
type AccountLoginReq,
|
type AccountLoginReq,
|
||||||
@@ -18,6 +19,7 @@ import { clearToken, getToken, setToken } from '@/utils/auth'
|
|||||||
import { resetHasRouteFlag } from '@/router/guard'
|
import { resetHasRouteFlag } from '@/router/guard'
|
||||||
|
|
||||||
const storeSetup = () => {
|
const storeSetup = () => {
|
||||||
|
const tenantStore = useTenantStore()
|
||||||
const userInfo = reactive<UserInfo>({
|
const userInfo = reactive<UserInfo>({
|
||||||
id: '',
|
id: '',
|
||||||
username: '',
|
username: '',
|
||||||
@@ -41,7 +43,6 @@ const storeSetup = () => {
|
|||||||
const pwdExpiredShow = ref<boolean>(true)
|
const pwdExpiredShow = ref<boolean>(true)
|
||||||
const roles = ref<string[]>([]) // 当前用户角色
|
const roles = ref<string[]>([]) // 当前用户角色
|
||||||
const permissions = ref<string[]>([]) // 当前角色权限标识集合
|
const permissions = ref<string[]>([]) // 当前角色权限标识集合
|
||||||
|
|
||||||
// 重置token
|
// 重置token
|
||||||
const resetToken = () => {
|
const resetToken = () => {
|
||||||
token.value = ''
|
token.value = ''
|
||||||
@@ -53,6 +54,7 @@ const storeSetup = () => {
|
|||||||
const accountLogin = async (req: AccountLoginReq, tenantCode?: string) => {
|
const accountLogin = async (req: AccountLoginReq, tenantCode?: string) => {
|
||||||
const res = await accountLoginApi({ ...req, clientId: import.meta.env.VITE_CLIENT_ID, authType: AuthTypeConstants.ACCOUNT }, tenantCode)
|
const res = await accountLoginApi({ ...req, clientId: import.meta.env.VITE_CLIENT_ID, authType: AuthTypeConstants.ACCOUNT }, tenantCode)
|
||||||
setToken(res.data.token)
|
setToken(res.data.token)
|
||||||
|
tenantStore.setTenantId(res.data.tenantId)
|
||||||
token.value = res.data.token
|
token.value = res.data.token
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,6 +62,7 @@ const storeSetup = () => {
|
|||||||
const emailLogin = async (req: EmailLoginReq, tenantCode?: string) => {
|
const emailLogin = async (req: EmailLoginReq, tenantCode?: string) => {
|
||||||
const res = await emailLoginApi({ ...req, clientId: import.meta.env.VITE_CLIENT_ID, authType: AuthTypeConstants.EMAIL }, tenantCode)
|
const res = await emailLoginApi({ ...req, clientId: import.meta.env.VITE_CLIENT_ID, authType: AuthTypeConstants.EMAIL }, tenantCode)
|
||||||
setToken(res.data.token)
|
setToken(res.data.token)
|
||||||
|
tenantStore.setTenantId(res.data.tenantId)
|
||||||
token.value = res.data.token
|
token.value = res.data.token
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -67,13 +70,15 @@ const storeSetup = () => {
|
|||||||
const phoneLogin = async (req: PhoneLoginReq, tenantCode?: string) => {
|
const phoneLogin = async (req: PhoneLoginReq, tenantCode?: string) => {
|
||||||
const res = await phoneLoginApi({ ...req, clientId: import.meta.env.VITE_CLIENT_ID, authType: AuthTypeConstants.PHONE }, tenantCode)
|
const res = await phoneLoginApi({ ...req, clientId: import.meta.env.VITE_CLIENT_ID, authType: AuthTypeConstants.PHONE }, tenantCode)
|
||||||
setToken(res.data.token)
|
setToken(res.data.token)
|
||||||
|
tenantStore.setTenantId(res.data.tenantId)
|
||||||
token.value = res.data.token
|
token.value = res.data.token
|
||||||
}
|
}
|
||||||
|
|
||||||
// 三方账号登录
|
// 三方账号登录
|
||||||
const socialLogin = async (source: string, req: any) => {
|
const socialLogin = async (source: string, req: any) => {
|
||||||
const res = await socialLoginApi({ ...req, source, clientId: import.meta.env.VITE_CLIENT_ID, authType: AuthTypeConstants.SOCIAL })
|
const res: any = await socialLoginApi({ ...req, source, clientId: import.meta.env.VITE_CLIENT_ID, authType: AuthTypeConstants.SOCIAL })
|
||||||
setToken(res.data.token)
|
setToken(res.data.token)
|
||||||
|
tenantStore.setTenantId(res.data.tenantId)
|
||||||
token.value = res.data.token
|
token.value = res.data.token
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
import qs from 'query-string'
|
import qs from 'query-string'
|
||||||
import type { AxiosError, AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios'
|
import type { AxiosError, AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios'
|
||||||
|
import { useTenantStore } from '@/stores/modules/tenant'
|
||||||
import { useUserStore } from '@/stores'
|
import { useUserStore } from '@/stores'
|
||||||
import { getToken } from '@/utils/auth'
|
import { getToken } from '@/utils/auth'
|
||||||
import modalErrorWrapper from '@/utils/modal-error-wrapper'
|
import modalErrorWrapper from '@/utils/modal-error-wrapper'
|
||||||
import messageErrorWrapper from '@/utils/message-error-wrapper'
|
import messageErrorWrapper from '@/utils/message-error-wrapper'
|
||||||
import notificationErrorWrapper from '@/utils/notification-error-wrapper'
|
import notificationErrorWrapper from '@/utils/notification-error-wrapper'
|
||||||
import router from '@/router'
|
import router from '@/router'
|
||||||
import { getTenantId } from '@/utils/tenant'
|
|
||||||
|
|
||||||
interface ICodeMessage {
|
interface ICodeMessage {
|
||||||
[propName: number]: string
|
[propName: number]: string
|
||||||
@@ -58,9 +58,9 @@ http.interceptors.request.use(
|
|||||||
if (token) {
|
if (token) {
|
||||||
config.headers.Authorization = `Bearer ${token}`
|
config.headers.Authorization = `Bearer ${token}`
|
||||||
}
|
}
|
||||||
const tenantId = getTenantId()
|
const tenantStore = useTenantStore()
|
||||||
if (tenantId) {
|
if (tenantStore.tenantEnabled && tenantStore.tenantId) {
|
||||||
config.headers['X-Tenant-Id'] = tenantId
|
config.headers['X-Tenant-Id'] = tenantStore.tenantId
|
||||||
}
|
}
|
||||||
return config
|
return config
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,14 +0,0 @@
|
|||||||
const CURRENT_TENANT = 'current_tenant'
|
|
||||||
|
|
||||||
export interface TenantCommon {
|
|
||||||
isEnabled: boolean
|
|
||||||
availableList: any[]
|
|
||||||
}
|
|
||||||
|
|
||||||
export const getTenantId = () => {
|
|
||||||
return localStorage.getItem(CURRENT_TENANT)
|
|
||||||
}
|
|
||||||
|
|
||||||
export const setTenantId = (tenantId: string) => {
|
|
||||||
localStorage.setItem(CURRENT_TENANT, tenantId)
|
|
||||||
}
|
|
||||||
@@ -8,8 +8,8 @@
|
|||||||
size="large"
|
size="large"
|
||||||
@submit="handleLogin"
|
@submit="handleLogin"
|
||||||
>
|
>
|
||||||
<a-form-item v-if="tenantStore.tenantEnabled && !tenantStore.tenantCode" field="tenantCode" hide-label>
|
<a-form-item v-if="tenantStore.needInputTenantId" field="tenantCode" hide-label>
|
||||||
<a-input v-model="tenantCodeInput" placeholder="请输入租户编码" allow-clear />
|
<a-input v-model="form.tenantCode" placeholder="请输入租户编码" allow-clear />
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item field="username" hide-label>
|
<a-form-item field="username" hide-label>
|
||||||
<a-input v-model="form.username" placeholder="请输入用户名" allow-clear />
|
<a-input v-model="form.username" placeholder="请输入用户名" allow-clear />
|
||||||
@@ -44,14 +44,14 @@
|
|||||||
import { type FormInstance, Message } from '@arco-design/web-vue'
|
import { type FormInstance, Message } from '@arco-design/web-vue'
|
||||||
import { useStorage } from '@vueuse/core'
|
import { useStorage } from '@vueuse/core'
|
||||||
import { getImageCaptcha } from '@/apis/common'
|
import { getImageCaptcha } from '@/apis/common'
|
||||||
import { useTabsStore, useTenantStore, useUserStore } from '@/stores'
|
import { useTabsStore, useUserStore } from '@/stores'
|
||||||
import { encryptByRsa } from '@/utils/encrypt'
|
import { encryptByRsa } from '@/utils/encrypt'
|
||||||
|
import { useTenantStore } from '@/stores/modules/tenant'
|
||||||
|
|
||||||
const tenantStore = useTenantStore()
|
const tenantStore = useTenantStore()
|
||||||
|
|
||||||
const loginConfig = useStorage('login-config', {
|
const loginConfig = useStorage('login-config', {
|
||||||
rememberMe: true,
|
rememberMe: true,
|
||||||
tenantCode: tenantStore.tenantCode,
|
|
||||||
username: 'admin', // 演示默认值
|
username: 'admin', // 演示默认值
|
||||||
password: 'admin123', // 演示默认值
|
password: 'admin123', // 演示默认值
|
||||||
// username: debug ? 'admin' : '', // 演示默认值
|
// username: debug ? 'admin' : '', // 演示默认值
|
||||||
@@ -63,21 +63,22 @@ const isCaptchaEnabled = ref(true)
|
|||||||
const captchaImgBase64 = ref()
|
const captchaImgBase64 = ref()
|
||||||
|
|
||||||
const formRef = ref<FormInstance>()
|
const formRef = ref<FormInstance>()
|
||||||
const tenantCodeInput = ref('') // 用户手动输入的租户编码
|
|
||||||
const form = reactive({
|
const form = reactive({
|
||||||
username: loginConfig.value.username,
|
username: loginConfig.value.username,
|
||||||
password: loginConfig.value.password,
|
password: loginConfig.value.password,
|
||||||
captcha: '',
|
captcha: '',
|
||||||
uuid: '',
|
uuid: '',
|
||||||
expired: false,
|
expired: false,
|
||||||
|
tenantCode: '', // 新增
|
||||||
})
|
})
|
||||||
|
// 校验规则部分
|
||||||
const rules: FormInstance['rules'] = {
|
const rules: FormInstance['rules'] = {
|
||||||
username: [{ required: true, message: '请输入用户名' }],
|
username: [{ required: true, message: '请输入用户名' }],
|
||||||
password: [{ required: true, message: '请输入密码' }],
|
password: [{ required: true, message: '请输入密码' }],
|
||||||
captcha: [{ required: isCaptchaEnabled.value, message: '请输入验证码' }],
|
captcha: [{ required: isCaptchaEnabled.value, message: '请输入验证码' }],
|
||||||
tenantCode: [
|
tenantCode: [
|
||||||
{
|
{
|
||||||
required: tenantStore.tenantEnabled && !tenantStore.tenantCode,
|
required: tenantStore.needInputTenantId,
|
||||||
message: '请输入租户编码',
|
message: '请输入租户编码',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@@ -128,10 +129,9 @@ const handleLogin = async () => {
|
|||||||
if (isInvalid) return
|
if (isInvalid) return
|
||||||
loading.value = true
|
loading.value = true
|
||||||
|
|
||||||
// 计算最终要传递的租户编码
|
let tenantCode
|
||||||
let finalTenantCode = ''
|
if (tenantStore.needInputTenantId) {
|
||||||
if (tenantStore.tenantEnabled) {
|
tenantCode = form.tenantCode
|
||||||
finalTenantCode = tenantStore.tenantCode || tenantCodeInput.value
|
|
||||||
}
|
}
|
||||||
|
|
||||||
await userStore.accountLogin({
|
await userStore.accountLogin({
|
||||||
@@ -139,11 +139,10 @@ const handleLogin = async () => {
|
|||||||
password: encryptByRsa(form.password) || '',
|
password: encryptByRsa(form.password) || '',
|
||||||
captcha: form.captcha,
|
captcha: form.captcha,
|
||||||
uuid: form.uuid,
|
uuid: form.uuid,
|
||||||
}, finalTenantCode)
|
}, tenantCode)
|
||||||
tabsStore.reset()
|
tabsStore.reset()
|
||||||
const { redirect, ...othersQuery } = router.currentRoute.value.query
|
const { redirect, ...othersQuery } = router.currentRoute.value.query
|
||||||
const { rememberMe } = loginConfig.value
|
const { rememberMe } = loginConfig.value
|
||||||
loginConfig.value.tenantCode = rememberMe ? finalTenantCode : ''
|
|
||||||
loginConfig.value.username = rememberMe ? form.username : ''
|
loginConfig.value.username = rememberMe ? form.username : ''
|
||||||
|
|
||||||
// 如果有重定向参数,解码并直接跳转到完整路径
|
// 如果有重定向参数,解码并直接跳转到完整路径
|
||||||
|
|||||||
@@ -96,14 +96,15 @@ import AccountLogin from './components/account/index.vue'
|
|||||||
import PhoneLogin from './components/phone/index.vue'
|
import PhoneLogin from './components/phone/index.vue'
|
||||||
import EmailLogin from './components/email/index.vue'
|
import EmailLogin from './components/email/index.vue'
|
||||||
import { socialAuth } from '@/apis/auth'
|
import { socialAuth } from '@/apis/auth'
|
||||||
import { useAppStore, useTenantStore } from '@/stores'
|
import { useAppStore } from '@/stores'
|
||||||
|
import { useTenantStore } from '@/stores/modules/tenant'
|
||||||
import { useDevice } from '@/hooks'
|
import { useDevice } from '@/hooks'
|
||||||
import { getTenantCodeByDomain, getTenantStatus } from '@/apis'
|
import { getTenantIdByDomain, getTenantStatus } from '@/apis'
|
||||||
|
|
||||||
defineOptions({ name: 'Login' })
|
defineOptions({ name: 'Login' })
|
||||||
|
const appStore = useAppStore()
|
||||||
const tenantStore = useTenantStore()
|
const tenantStore = useTenantStore()
|
||||||
const { isDesktop } = useDevice()
|
const { isDesktop } = useDevice()
|
||||||
const appStore = useAppStore()
|
|
||||||
const title = computed(() => appStore.getTitle())
|
const title = computed(() => appStore.getTitle())
|
||||||
const logo = computed(() => appStore.getLogo())
|
const logo = computed(() => appStore.getLogo())
|
||||||
|
|
||||||
@@ -128,8 +129,8 @@ const onGetTenant = async () => {
|
|||||||
// 开启租户 根据地址(域名)查询租户code
|
// 开启租户 根据地址(域名)查询租户code
|
||||||
if (data) {
|
if (data) {
|
||||||
const domain = window.location.hostname
|
const domain = window.location.hostname
|
||||||
const { data } = await getTenantCodeByDomain(domain)
|
const { data: tenantId } = await getTenantIdByDomain(domain)
|
||||||
tenantStore.setTenantCode(data)
|
tenantStore.setTenantId(tenantId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
|||||||
Reference in New Issue
Block a user