feat: integrate ZYT admin with IAM Hub
This commit is contained in:
+19
-1
@@ -28,7 +28,25 @@ export function getWorkWechatConfig() {
|
||||
|
||||
// 企业微信授权登录
|
||||
export function workWechatLogin(params: { code: string }) {
|
||||
return request.post({ url: '/login/workWechatLogin', params: { ...params, terminal: config.terminal } })
|
||||
return request.post({
|
||||
url: '/login/workWechatLogin',
|
||||
params: { ...params, terminal: config.terminal }
|
||||
})
|
||||
}
|
||||
|
||||
// IAM Hub 登录配置
|
||||
export function getIamHubConfig() {
|
||||
return request.get({ url: '/login/iamConfig' })
|
||||
}
|
||||
|
||||
// IAM Hub 一次性回调码换取本平台会话
|
||||
export function iamHubExchange(params: { code: string }) {
|
||||
return request.post({ url: '/login/iamExchange', params })
|
||||
}
|
||||
|
||||
export function getIamHubStartUrl() {
|
||||
const baseUrl = config.baseUrl.replace(/\/+$/, '')
|
||||
return `${baseUrl}/${config.urlPrefix}/login/iamStart`
|
||||
}
|
||||
|
||||
// 绑定企业微信
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { defineStore } from 'pinia'
|
||||
import type { RouteRecordRaw } from 'vue-router'
|
||||
|
||||
import { getUserInfo, login, logout, workWechatLogin } from '@/api/user'
|
||||
import { getUserInfo, iamHubExchange, login, logout, workWechatLogin } from '@/api/user'
|
||||
import { TOKEN_KEY } from '@/enums/cacheEnums'
|
||||
import { PageEnum } from '@/enums/pageEnum'
|
||||
import router, { filterAsyncRoutes } from '@/router'
|
||||
@@ -31,6 +31,12 @@ const useUserStore = defineStore({
|
||||
}),
|
||||
getters: {},
|
||||
actions: {
|
||||
applyLoginResult(data: any) {
|
||||
this.token = data.token
|
||||
this.isPaw = data.is_paw ?? 1
|
||||
cache.set(TOKEN_KEY, data.token)
|
||||
return data
|
||||
},
|
||||
resetState() {
|
||||
this.token = ''
|
||||
this.userInfo = {}
|
||||
@@ -45,10 +51,7 @@ const useUserStore = defineStore({
|
||||
password: password
|
||||
})
|
||||
.then((data) => {
|
||||
this.token = data.token
|
||||
this.isPaw = data.is_paw ?? 1
|
||||
cache.set(TOKEN_KEY, data.token)
|
||||
resolve(data)
|
||||
resolve(this.applyLoginResult(data))
|
||||
})
|
||||
.catch((error) => {
|
||||
reject(error)
|
||||
@@ -73,16 +76,20 @@ const useUserStore = defineStore({
|
||||
return new Promise((resolve, reject) => {
|
||||
workWechatLogin({ code })
|
||||
.then((data) => {
|
||||
this.token = data.token
|
||||
this.isPaw = data.is_paw ?? 1
|
||||
cache.set(TOKEN_KEY, data.token)
|
||||
resolve(data)
|
||||
resolve(this.applyLoginResult(data))
|
||||
})
|
||||
.catch((error) => {
|
||||
reject(error)
|
||||
})
|
||||
})
|
||||
},
|
||||
iamHubLogin(code: string) {
|
||||
return new Promise((resolve, reject) => {
|
||||
iamHubExchange({ code })
|
||||
.then((data) => resolve(this.applyLoginResult(data)))
|
||||
.catch(reject)
|
||||
})
|
||||
},
|
||||
getUserInfo() {
|
||||
return new Promise((resolve, reject) => {
|
||||
getUserInfo()
|
||||
|
||||
@@ -11,11 +11,13 @@
|
||||
<div class="text-center text-3xl font-medium mb-8">{{ config.web_name }}</div>
|
||||
|
||||
<!-- 企业微信自动授权中 -->
|
||||
<div v-if="wxWorkAutoLogin" class="text-center py-10">
|
||||
<div v-if="wxWorkAutoLogin || iamAutoLogin" class="text-center py-10">
|
||||
<el-icon class="is-loading mb-4" :size="40" color="var(--el-color-primary)">
|
||||
<Loading />
|
||||
</el-icon>
|
||||
<div class="text-gray-500">企业微信授权登录中...</div>
|
||||
<div class="text-gray-500">
|
||||
{{ iamAutoLogin ? '公司统一身份登录中...' : '企业微信授权登录中...' }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<template v-else>
|
||||
@@ -58,21 +60,42 @@
|
||||
<div class="mb-5">
|
||||
<el-checkbox v-model="remAccount" label="记住账号"></el-checkbox>
|
||||
</div>
|
||||
<el-button type="primary" size="large" :loading="isLock" @click="lockLogin">
|
||||
<el-button
|
||||
type="primary"
|
||||
size="large"
|
||||
:loading="isLock"
|
||||
@click="lockLogin"
|
||||
>
|
||||
登录
|
||||
</el-button>
|
||||
<template v-if="iamHubEnabled">
|
||||
<el-divider>或</el-divider>
|
||||
<el-button size="large" class="w-full" @click="handleIamHubLogin">
|
||||
公司员工统一登录
|
||||
</el-button>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<!-- 企业微信扫码登录(非企业微信内浏览器) -->
|
||||
<template v-if="loginMode === 'wxwork'">
|
||||
<div class="wxwork-qrcode-wrap">
|
||||
<div v-if="wxWorkLoading" class="text-center py-10">
|
||||
<el-icon class="is-loading" :size="32" color="var(--el-color-primary)">
|
||||
<el-icon
|
||||
class="is-loading"
|
||||
:size="32"
|
||||
color="var(--el-color-primary)"
|
||||
>
|
||||
<Loading />
|
||||
</el-icon>
|
||||
<div class="mt-2 text-gray-400 text-sm">加载企业微信扫码...</div>
|
||||
<div class="mt-2 text-gray-400 text-sm">
|
||||
加载企业微信扫码...
|
||||
</div>
|
||||
</div>
|
||||
<div v-else id="wxwork_qrcode_container" class="wxwork-qrcode"></div>
|
||||
<div
|
||||
v-else
|
||||
id="wxwork_qrcode_container"
|
||||
class="wxwork-qrcode"
|
||||
></div>
|
||||
</div>
|
||||
<div class="text-center text-sm text-gray-400 mt-4">
|
||||
请使用企业微信扫描二维码登录
|
||||
@@ -99,7 +122,7 @@ import LayoutFooter from '@/layout/components/footer.vue'
|
||||
import useAppStore from '@/stores/modules/app'
|
||||
import useUserStore from '@/stores/modules/user'
|
||||
import cache from '@/utils/cache'
|
||||
import { getWorkWechatConfig } from '@/api/user'
|
||||
import { getIamHubConfig, getIamHubStartUrl, getWorkWechatConfig } from '@/api/user'
|
||||
|
||||
const passwordRef = shallowRef<InputInstance>()
|
||||
const formRef = shallowRef<FormInstance>()
|
||||
@@ -124,6 +147,8 @@ const wxWorkEnabled = ref(false)
|
||||
const wxWorkConfig = ref<{ corp_id: string; agent_id: string }>({ corp_id: '', agent_id: '' })
|
||||
const wxWorkAutoLogin = ref(false)
|
||||
const wxWorkLoading = ref(false)
|
||||
const iamHubEnabled = ref(false)
|
||||
const iamAutoLogin = ref(false)
|
||||
|
||||
const isInWxWork = () => /wxwork/i.test(navigator.userAgent)
|
||||
|
||||
@@ -160,8 +185,14 @@ const handleLogin = async () => {
|
||||
|
||||
const { isLock, lockFn: lockLogin } = useLockFn(handleLogin)
|
||||
|
||||
const handleIamHubLogin = () => {
|
||||
window.location.href = getIamHubStartUrl()
|
||||
}
|
||||
|
||||
const redirectAfterLogin = () => {
|
||||
const { query: { redirect } } = route
|
||||
const {
|
||||
query: { redirect }
|
||||
} = route
|
||||
const path = typeof redirect === 'string' ? redirect : PageEnum.INDEX
|
||||
router.push(path)
|
||||
}
|
||||
@@ -190,6 +221,22 @@ const handleWxWorkCodeLogin = async (code: string) => {
|
||||
}
|
||||
}
|
||||
|
||||
const handleIamHubCodeLogin = async (code: string) => {
|
||||
iamAutoLogin.value = true
|
||||
try {
|
||||
const result: any = await userStore.iamHubLogin(code)
|
||||
if (result.need_bind_work_wechat) {
|
||||
router.push('/bind-work-wechat')
|
||||
return
|
||||
}
|
||||
redirectAfterLogin()
|
||||
} catch (error: any) {
|
||||
console.error('IAM Hub 登录失败:', error)
|
||||
ElMessage.error(error?.msg || error?.message || '公司统一身份登录失败,请重新发起登录')
|
||||
iamAutoLogin.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 加载企业微信扫码 JS SDK 并渲染二维码
|
||||
const renderWxWorkQRCode = async () => {
|
||||
if (!wxWorkConfig.value.corp_id) return
|
||||
@@ -222,7 +269,7 @@ const renderWxWorkQRCode = async () => {
|
||||
lang: 'zh',
|
||||
state: 'admin_login',
|
||||
href: '',
|
||||
self_redirect: false,
|
||||
self_redirect: false
|
||||
})
|
||||
}
|
||||
|
||||
@@ -241,6 +288,27 @@ onMounted(async () => {
|
||||
formData.account = value.account
|
||||
}
|
||||
|
||||
const hashParams = new URLSearchParams(window.location.hash.replace(/^#/, ''))
|
||||
const iamCode = hashParams.get('iam_code')
|
||||
const iamError = hashParams.get('iam_error')
|
||||
if (iamCode || iamError) {
|
||||
window.history.replaceState({}, '', window.location.pathname + window.location.search)
|
||||
}
|
||||
if (iamCode) {
|
||||
handleIamHubCodeLogin(iamCode)
|
||||
return
|
||||
}
|
||||
if (iamError) {
|
||||
ElMessage.error('公司统一身份登录失败,请重新发起登录')
|
||||
}
|
||||
|
||||
try {
|
||||
const iamConfig = await getIamHubConfig()
|
||||
iamHubEnabled.value = iamConfig?.enabled === true
|
||||
} catch (e) {
|
||||
console.warn('获取 IAM Hub 登录配置失败:', e)
|
||||
}
|
||||
|
||||
// 检查 URL 中是否有企业微信回调 code
|
||||
const urlParams = new URLSearchParams(window.location.search)
|
||||
const wxCode = urlParams.get('code')
|
||||
@@ -248,7 +316,9 @@ onMounted(async () => {
|
||||
|
||||
if (wxCode && wxState === 'admin_login') {
|
||||
// 清除 URL 中的 code 参数(避免刷新重复使用)
|
||||
const cleanUrl = window.location.pathname + (route.query.redirect ? `?redirect=${route.query.redirect}` : '')
|
||||
const cleanUrl =
|
||||
window.location.pathname +
|
||||
(route.query.redirect ? `?redirect=${route.query.redirect}` : '')
|
||||
window.history.replaceState({}, '', cleanUrl)
|
||||
|
||||
handleWxWorkCodeLogin(wxCode)
|
||||
|
||||
Reference in New Issue
Block a user