fix: 修复单点登录正确获取用户信息

This commit is contained in:
xieyonghong 2023-04-03 19:46:16 +08:00
parent 0cbbd52a1e
commit 6c9524ab9f
4 changed files with 345 additions and 306 deletions

View File

@ -13,7 +13,7 @@ interface AxiosResponseRewrite<T = any[]> extends AxiosResponse<T, any> {
export const SUCCESS_CODE = 200 // 成功代码 export const SUCCESS_CODE = 200 // 成功代码
const filterApiUrl = ['/system/version', '/system/config/front', '/authorize/captcha/config', '/application/sso/_all', '/authorize/captcha/image'] const filterApiUrl = ['/system/version', '/system/config/front', '/authorize/captcha/config', '/application/sso/_all', '/authorize/captcha/image', '/application/sso/bind-code', '/authorize/login']
export const request = axios.create({ export const request = axios.create({
withCredentials: false, withCredentials: false,

View File

@ -1,19 +1,19 @@
<!-- 第三方账户绑定 --> <!-- 第三方账户绑定 -->
<template> <template>
<div class="page-container"> <div class='page-container'>
<div class="content"> <div class='content'>
<div class="title">第三方账户绑定</div> <div class='title'>第三方账户绑定</div>
<!-- 已登录-绑定三方账号 --> <!-- 已登录-绑定三方账号 -->
<template v-if="!!token"> <template v-if='!!token'>
<div class="info"> <div class='info'>
<j-card style="width: 280px"> <j-card style='width: 280px'>
<template #title> <template #title>
<div class="info-head"> <div class='info-head'>
<img :src="getImage('/bind/Rectangle.png')" /> <img :src="getImage('/bind/Rectangle.png')" />
<span>个人信息</span> <span>个人信息</span>
</div> </div>
</template> </template>
<div class="info-body"> <div class='info-body'>
<img <img
:src=" :src="
user?.avatar || user?.avatar ||
@ -25,14 +25,14 @@
</div> </div>
</j-card> </j-card>
<img :src="getImage('/bind/Vector.png')" /> <img :src="getImage('/bind/Vector.png')" />
<j-card style="width: 280px"> <j-card style='width: 280px'>
<template #title> <template #title>
<div class="info-head"> <div class='info-head'>
<img :src="getImage('/bind/Rectangle.png')" /> <img :src="getImage('/bind/Rectangle.png')" />
<span>三方账户信息</span> <span>三方账户信息</span>
</div> </div>
</template> </template>
<div class="info-body"> <div class='info-body'>
<img <img
:src=" :src="
iconMap.get( iconMap.get(
@ -40,81 +40,87 @@
) || getImage('/apply/provider1.png') ) || getImage('/apply/provider1.png')
" "
/> />
<p>账号{{ bindUser?.result?.username || '-' }}</p> <p>账号{{ bindUser?.result?.userId || '-' }}</p>
<p>用户名{{ bindUser?.result?.name || '-' }}</p> <p>用户名{{ bindUser?.result?.name || '-' }}</p>
</div> </div>
</j-card> </j-card>
</div> </div>
<div class="btn"> <div class='btn'>
<j-button type="primary" @click="handleBind" <j-button type='primary' @click='handleBind'
>立即绑定</j-button >立即绑定
</j-button
> >
</div> </div>
</template> </template>
<!-- 未登录-绑定三方账号 --> <!-- 未登录-绑定三方账号 -->
<template v-else> <template v-else>
<div class="not-login"> <div class='not-login'>
<div class="logo"> <div class='logo'>
<img :src="getImage('/bind/jetlinksLogo.png')" /> <img :src="getImage('/bind/jetlinksLogo.png')" />
<img <img
class="arrow" class='arrow'
:src="getImage('/bind/Vector.png')" :src="getImage('/bind/Vector.png')"
/> />
<img <img
:src="iconMap.get(bindUser?.applicationProvider)" :src='iconMap.get(bindUser?.applicationProvider)'
/> />
</div> </div>
<div class="desc"> <div class='desc'>
你已通过 你已通过
{{ {{ bindUser?.appName }}
bindUser?.type === 'dingtalk-ent-app'
? '钉钉'
: '微信'
}}
授权,完善以下登录信息即可以完成绑定 授权,完善以下登录信息即可以完成绑定
</div> </div>
<div class="login-form"> <div class='login-form'>
<j-form layout="vertical"> <j-form layout='vertical'>
<j-form-item <j-form-item
label="账户" label='账户'
v-bind="validateInfos.username" v-bind='validateInfos.username'
> >
<j-input <j-input
v-model:value="formData.username" v-model:value='formData.username'
placeholder="请输入账户" placeholder='请输入账户'
/> />
</j-form-item> </j-form-item>
<j-form-item <j-form-item
label="密码" label='密码'
v-bind="validateInfos.password" v-bind='validateInfos.password'
> >
<j-input-password <j-input-password
v-model:value="formData.password" v-model:value='formData.password'
placeholder="请输入密码" placeholder='请输入密码'
/> />
</j-form-item> </j-form-item>
<template v-if='captcha.base64'>
<j-form-item <j-form-item
label="验证码" label='验证码'
v-bind="validateInfos.verifyCode" v-bind='validateInfos.verifyCode'
:rules="[
{
required: true,
message: '请输入验证码',
},
]"
> >
<j-input <j-input
v-model:value="formData.verifyCode" v-model:value='formData.verifyCode'
placeholder="请输入验证码" placeholder='请输入验证码'
> >
<template #addonAfter> <template #addonAfter>
<img <img
:src="captcha.base64" :src='captcha.base64'
@click="getCode" @click='getCode'
style="cursor: pointer" style='cursor: pointer'
/> />
</template> </template>
</j-input> </j-input>
</j-form-item> </j-form-item>
</template>
<j-form-item> <j-form-item>
<j-button <j-button
type="primary" type='primary'
@click="handleLoginBind" @click='handleLoginBind'
style="width: 100%" style='width: 100%'
> >
登录并绑定账户 登录并绑定账户
</j-button> </j-button>
@ -127,16 +133,16 @@
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang='ts' name='AccountBind'>
import { getImage, LocalStore } from '@/utils/comm'; import { getImage, LocalStore } from '@/utils/comm'
import { TOKEN_KEY } from '@/utils/variable'; import { TOKEN_KEY } from '@/utils/variable'
import { Form } from 'ant-design-vue'; import { Form } from 'ant-design-vue'
import { message } from 'ant-design-vue'; import { message } from 'ant-design-vue'
import { applicationInfo, bindAccount } from '@/api/bind'; import { applicationInfo, bindAccount } from '@/api/bind'
import { code, authLogin, userDetail } from '@/api/login'; import { code, authLogin, userDetail } from '@/api/login'
const useForm = Form.useForm; const useForm = Form.useForm
interface formData { interface formData {
username: string; username: string;
@ -144,101 +150,104 @@ interface formData {
verifyCode: string; verifyCode: string;
} }
const iconMap = new Map(); const iconMap = new Map()
iconMap.set('dingtalk-ent-app', getImage('/notice/dingtalk.png')); iconMap.set('dingtalk-ent-app', getImage('/notice/dingtalk.png'))
iconMap.set('wechat-webapp', getImage('/notice/wechat.png')); iconMap.set('wechat-webapp', getImage('/notice/wechat.png'))
iconMap.set('internal-standalone', getImage('/apply/provider1.png')); iconMap.set('internal-standalone', getImage('/apply/provider1.png'))
iconMap.set('third-party', getImage('/apply/provider5.png')); iconMap.set('third-party', getImage('/apply/provider5.png'))
const token = computed(() => LocalStore.get(TOKEN_KEY)); const token = computed(() => LocalStore.get(TOKEN_KEY))
/** /**
* 用户信息 * 用户信息
*/ */
const user = ref(); const user = ref()
const getDetail = () => { const getDetail = () => {
if (!token.value) return; if (!token.value) return
userDetail().then((res: any) => { userDetail().then((res: any) => {
user.value = res?.result; user.value = res?.result
}); })
}; }
getDetail();
/**
* 三方应用信息
*/
const bindUser = ref();
const getAppInfo = async () => {
const code = getUrlCode();
const { result } = await applicationInfo(code);
bindUser.value = result;
};
getAppInfo();
/** /**
* 获取url参数 * 获取url参数
*/ */
const getUrlCode = () => { const getUrlCode = () => {
const url = new URLSearchParams(window.location.href); const url = new URLSearchParams(window.location.href)
return url.get('code') as string; return url.get('code') as string
}; }
/**
* 三方应用信息
*/
const bindUser = ref<any>({ appName: '' })
const getAppInfo = async () => {
const code = getUrlCode()
const { result } = await applicationInfo(code)
bindUser.value = result
if (result.applicationProvider === 'dingtalk-ent-app') {
bindUser.value.appName = '钉钉'
} else if (result.applicationProvider === 'wechat-webapp') {
bindUser.value.appName = '微信'
} else {
bindUser.value.appName = result.applicationName
}
}
/** /**
* 立即绑定 * 立即绑定
*/ */
const handleBind = async () => { const handleBind = async () => {
const code = getUrlCode(); const code = getUrlCode()
const res = await bindAccount(code); const res = await bindAccount(code)
console.log('bindAccount: ', res); console.log('bindAccount: ', res)
message.success('绑定成功'); message.success('绑定成功')
goRedirect(); goRedirect()
setTimeout(() => window.close(), 1000); setTimeout(() => window.close(), 1000)
}; }
// - // -
const formData = ref<formData>({ const formData = ref<formData>({
username: '', username: '',
password: '', password: '',
verifyCode: '', verifyCode: ''
}); })
const formRules = ref({ const formRules = ref({
username: [ username: [
{ {
required: true, required: true,
message: '请输入账户', message: '请输入账户'
}, }
], ],
password: [ password: [
{ {
required: true, required: true,
message: '请输入密码', message: '请输入密码'
}, }
], ]
verifyCode: [ })
{
required: true,
message: '请输入验证码',
},
],
});
const { resetFields, validate, validateInfos } = useForm( const { resetFields, validate, validateInfos } = useForm(
formData.value, formData.value,
formRules.value, formRules.value
); )
/** /**
* 获取图形验证码 * 获取图形验证码
*/ */
const captcha = ref({ const captcha = ref({
base64: '', base64: '',
key: '', key: ''
}); })
const getCode = async () => { const getCode = async () => {
const res: any = await code(); const res: any = await code()
captcha.value = res.result; captcha.value.base64 = res.result?.base64
}; captcha.value.key = res.result?.key
getCode(); }
/** /**
* 登录并绑定账户 * 登录并绑定账户
@ -246,41 +255,58 @@ getCode();
const handleLoginBind = () => { const handleLoginBind = () => {
validate() validate()
.then(async () => { .then(async () => {
const code = getUrlCode(); const code = getUrlCode()
const params = { const params: any = {
...formData.value, ...formData.value,
verifyKey: captcha.value.key,
bindCode: code, bindCode: code,
expires: 3600000, expires: 3600000
}; }
const res = await authLogin(params);
console.log('res: ', res); if (captcha.value.base64) {
message.success('登录成功'); params.verifyKey = captcha.value.key
goRedirect(); } else {
setTimeout(() => window.close(), 1000); delete params.verifyCode
}
const res = await authLogin(params)
console.log('res: ', res)
if (res.success) {
message.success('登录成功')
LocalStore.set(TOKEN_KEY, res.result!.token as string)
goRedirect()
}
}) })
.catch((err) => { .catch((err) => {
getCode(); console.log(err)
}); getCode()
}; })
}
/** /**
* 绑定成功跳转至页面url的: redirect * 绑定成功跳转至页面url的: redirect
*/ */
const goRedirect = () => { const goRedirect = () => {
const urlParams = new URLSearchParams(window.location.hash); const urlParams = new URLSearchParams(window.location.hash)
const redirectUrl = const redirectUrl =
urlParams.get('redirect') || urlParams.get('redirect') ||
window.location.href.split('redirect=')?.[1]; window.location.href.split('redirect=')?.[1]
console.log('redirectUrl: ', redirectUrl); console.log('redirectUrl: ', redirectUrl)
// //
if (redirectUrl && redirectUrl.indexOf('account/center/bind') === -1) { if (redirectUrl && redirectUrl.indexOf('account/center/bind') === -1) {
window.location.href = decodeURIComponent(redirectUrl); window.location.href = decodeURIComponent(redirectUrl)
} else {
window.location.href = '/'
setTimeout(() => window.close(), 1000)
} }
}; }
getAppInfo()
getCode()
getDetail()
</script> </script>
<style lang="less" scoped> <style lang='less' scoped>
:deep( :deep(
.ant-form-item-label .ant-form-item-label
> label.ant-form-item-required:not( > label.ant-form-item-required:not(
@ -289,9 +315,11 @@ const goRedirect = () => {
) { ) {
display: none; display: none;
} }
:deep(.ant-form-item-label > label) { :deep(.ant-form-item-label > label) {
font-weight: bold; font-weight: bold;
} }
.page-container { .page-container {
width: 100%; width: 100%;
height: 100vh; height: 100vh;
@ -299,6 +327,7 @@ const goRedirect = () => {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
.content { .content {
box-sizing: border-box; box-sizing: border-box;
width: 850px; width: 850px;
@ -306,6 +335,7 @@ const goRedirect = () => {
background: #fff; background: #fff;
border: 1px solid #e0e4e8; border: 1px solid #e0e4e8;
border-radius: 2px; border-radius: 2px;
.title { .title {
margin: 30px 0; margin: 30px 0;
color: #0f1222; color: #0f1222;
@ -316,28 +346,33 @@ const goRedirect = () => {
line-height: 25px; line-height: 25px;
text-align: center; text-align: center;
} }
// - // -
.info { .info {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
gap: 20px; gap: 20px;
&-head { &-head {
display: flex; display: flex;
align-items: baseline; align-items: baseline;
gap: 10px; gap: 10px;
} }
&-body { &-body {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
gap: 10px; gap: 10px;
img { img {
width: 70px; width: 70px;
height: 70px; height: 70px;
} }
} }
} }
.btn { .btn {
display: flex; display: flex;
justify-content: center; justify-content: center;
@ -349,19 +384,23 @@ const goRedirect = () => {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
.logo { .logo {
display: flex; display: flex;
align-items: center; align-items: center;
gap: 20px; gap: 20px;
img { img {
width: 50px; width: 50px;
height: 50px; height: 50px;
} }
.arrow { .arrow {
width: 15px; width: 15px;
height: 15px; height: 15px;
} }
} }
.desc { .desc {
margin-top: 30px; margin-top: 30px;
margin-bottom: 30px; margin-bottom: 30px;

View File

@ -90,9 +90,9 @@ export default defineConfig(({ mode}) => {
proxy: { proxy: {
[env.VITE_APP_BASE_API]: { [env.VITE_APP_BASE_API]: {
// target: 'http://192.168.32.226:8844', target: 'http://192.168.32.226:8844',
// target: 'http://192.168.32.244:8881', // target: 'http://192.168.32.244:8881',
target: 'http://120.77.179.54:8844', // 120测试 // target: 'http://120.77.179.54:8844', // 120测试
// target: 'http://192.168.33.46:8844', // 本地开发环境 // target: 'http://192.168.33.46:8844', // 本地开发环境
ws: 'ws://192.168.33.46:8844', ws: 'ws://192.168.33.46:8844',
changeOrigin: true, changeOrigin: true,

View File

@ -3700,8 +3700,8 @@ jetlinks-store@^0.0.3:
jetlinks-ui-components@^1.0.5: jetlinks-ui-components@^1.0.5:
version "1.0.5" version "1.0.5"
resolved "http://47.108.170.157:9013/jetlinks-ui-components/-/jetlinks-ui-components-1.0.5.tgz#da230869aacc49be00a03da55d6bf268570fee73" resolved "http://47.108.170.157:9013/jetlinks-ui-components/-/jetlinks-ui-components-1.0.5.tgz#bcf2ccab91dd64355bbe6528501d37f85f503161"
integrity sha512-XOHa0sxhFlCrKBJ1tscCXdLlcr1ZZjDhHx1sE4wqurnSKKU6PsjHKsyOWzMC1+4XgRcCLomvo9OGIwHI0IyQrQ== integrity sha512-yUN47hmOjDryn2CBrAL7IRMdyJsuKn7wG+OwLD9Jpii/8obUfIYT2nKoxihUzWjIrBmhP1WmD94C0AwaCN1hxw==
dependencies: dependencies:
"@vueuse/core" "^9.12.0" "@vueuse/core" "^9.12.0"
ant-design-vue "^3.2.15" ant-design-vue "^3.2.15"