Browse Source

sso登录

master
xuhuajiao 1 month ago
parent
commit
c72d71d348
  1. 2
      src/router/index.js
  2. 5
      src/router/routers.js
  3. 222
      src/views/features/ssoLogin.vue

2
src/router/index.js

@ -9,7 +9,7 @@ import { filterAsyncRouter } from '@/store/modules/permission'
NProgress.configure({ showSpinner: false })// NProgress Configuration NProgress.configure({ showSpinner: false })// NProgress Configuration
// '/user', '/location', '/role', '/menu', '/depts', '/fonds', '/warehouse', '/inventory', '/stocktaking', '/deviceList', '/monitor' // '/user', '/location', '/role', '/menu', '/depts', '/fonds', '/warehouse', '/inventory', '/stocktaking', '/deviceList', '/monitor'
const whiteList = ['/login']// no redirect whitelist
const whiteList = ['/login', '/ssoLogin']// no redirect whitelist
router.beforeEach((to, from, next) => { router.beforeEach((to, from, next) => {
if (to.meta.title) { if (to.meta.title) {

5
src/router/routers.js

@ -20,6 +20,11 @@ export const constantRouterMap = [
component: (resolve) => require(['@/views/features/401'], resolve), component: (resolve) => require(['@/views/features/401'], resolve),
hidden: true hidden: true
}, },
{
path: '/ssoLogin',
component: (resolve) => require(['@/views/features/ssoLogin'], resolve),
hidden: true
},
{ {
path: '/redirect', path: '/redirect',
component: Layout, component: Layout,

222
src/views/features/ssoLogin.vue

@ -0,0 +1,222 @@
<template>
<div class="sso-login-container">
<div class="login-content">
<!-- 加载状态 -->
<div v-if="loading" class="loading-state">
<div class="spinner" />
<p class="loading-text">正在自动登录...</p>
</div>
<!-- 成功状态 -->
<div v-else-if="success" class="success-state">
<div class="success-icon"></div>
<h2>登录成功</h2>
<p>正在跳转...</p>
</div>
<!-- 错误状态 -->
<div v-else class="error-state">
<div class="error-icon"></div>
<h2>登录失败</h2>
<p class="error-message">{{ message }}</p>
<button class="retry-btn" @click="handleAutoLogin">重新登录</button>
</div>
</div>
</div>
</template>
<script>
import { setToken } from '@/utils/auth'
export default {
name: 'SSOLogin',
data() {
return {
loading: true,
success: false,
message: ''
}
},
mounted() {
this.handleAutoLogin()
},
methods: {
handleAutoLogin() {
this.username = true
this.success = false
this.message = ''
const { username, ts, token } = this.$route.query
if (!username || !ts || !token) {
this.message = '缺少必要参数'
this.loading = false
return
}
console.log('username', username)
console.log('ts', ts)
console.log('token', token)
//
fetch('/api/sso/auto-login', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: `username=${encodeURIComponent(username)}&ts=${ts}&token=${encodeURIComponent(token)}`
})
.then(res => {
// HTTP
if (!res.ok) {
throw new Error(`HTTP 错误:${res.status} ${res.statusText}`)
}
return res.json()
})
.then(data => {
this.loading = false
console.log('data', data)
if (data && data.code === 200) {
// 使 setToken Cookie
setToken(data.data.token)
this.success = true
// SSO localStorage
// const ssoData = {
// categoryId: data.data.categoryId,
// fondsId: data.data.user?.user?.fonds?.id,
// archiveNo: data.data.archiveNo,
// fondName: data.data.user?.user?.fonds?.fondsName
// }
// localStorage.setItem('ssoData', JSON.stringify(ssoData))
//
setTimeout(() => {
this.$router.replace('/')
}, 500)
} else {
//
this.message = data?.message || '登录失败,请联系管理员'
}
})
.catch(err => {
this.loading = false
this.message = '登录请求失败:' + err.message
})
}
}
}
</script>
<style lang="scss" scoped>
.sso-login-container {
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
// background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
}
.login-content {
background: #fff;
border-radius: 12px;
padding: 48px 64px;
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.15);
text-align: center;
min-width: 360px;
}
/* 加载状态 */
.loading-state {
.spinner {
width: 50px;
height: 50px;
border: 4px solid #f3f3f3;
border-top: 4px solid #0348F3;
border-radius: 50%;
animation: spin 1s linear infinite;
margin: 0 auto 20px;
}
.loading-text {
color: #666;
font-size: 16px;
}
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
/* 成功状态 */
.success-state {
.success-icon {
width: 80px;
height: 80px;
border-radius: 50%;
background: #52c41a;
color: #fff;
font-size: 40px;
line-height: 80px;
margin: 0 auto 20px;
}
h2 {
color: #333;
margin-bottom: 12px;
}
p {
color: #666;
}
}
/* 错误状态 */
.error-state {
.error-icon {
width: 80px;
height: 80px;
border-radius: 50%;
background: #ff4d4f;
color: #fff;
font-size: 40px;
line-height: 80px;
margin: 0 auto 20px;
}
h2 {
color: #ff4d4f;
margin-bottom: 12px;
}
.error-message {
color: #666;
margin-bottom: 24px;
min-height: 24px;
}
.retry-btn,
.back-btn {
padding: 10px 24px;
border: none;
border-radius: 6px;
font-size: 14px;
cursor: pointer;
margin: 0 8px;
transition: all 0.3s ease;
}
.retry-btn {
background: #0348F3;
color: #fff;
}
.back-btn {
background: #f5f5f5;
color: #666;
&:hover {
background: #e8e8e8;
}
}
}
</style>
Loading…
Cancel
Save