oauth允许选择账号
This commit is contained in:
parent
9daa9ed6c4
commit
1d6c7c8d38
|
|
@ -146,3 +146,31 @@ export function oauth() {
|
||||||
method: 'get'
|
method: 'get'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取 OAuth2 统一认证可选账号列表
|
||||||
|
* @param {string} code - 授权码
|
||||||
|
*/
|
||||||
|
export function getOAuth2Selection(code) {
|
||||||
|
return request({
|
||||||
|
url: '/aiccs-api/oauth2/unified/selection',
|
||||||
|
method: 'get',
|
||||||
|
params: { code }
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* OAuth2 选择账号登录
|
||||||
|
* @param {string} code - 授权码
|
||||||
|
* @param {string|number} userId - 选择的用户ID
|
||||||
|
*/
|
||||||
|
export function selectOAuth2Login(code, userId) {
|
||||||
|
const params = new FormData()
|
||||||
|
params.append('code', code)
|
||||||
|
params.append('userId', userId)
|
||||||
|
return request({
|
||||||
|
url: '/aiccs-api/oauth2/unified/select/login',
|
||||||
|
method: 'post',
|
||||||
|
data: params
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,15 @@ export const constantRoutes = [
|
||||||
title: '登录'
|
title: '登录'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: '/oauth2',
|
||||||
|
component: () => import('@/views/oauth2/index'),
|
||||||
|
hidden: true,
|
||||||
|
meta: {
|
||||||
|
roles: ['guest'],
|
||||||
|
title: '账号选择'
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: 'Maintain',
|
name: 'Maintain',
|
||||||
path: '/maintain',
|
path: '/maintain',
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,267 @@
|
||||||
|
<template>
|
||||||
|
<div class="oauth2-container">
|
||||||
|
<div v-if="loading" class="loading-wrapper">
|
||||||
|
<i class="el-icon-loading" />
|
||||||
|
<span>加载中...</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 账号选择弹窗 -->
|
||||||
|
<el-dialog
|
||||||
|
title="请选择登录账号"
|
||||||
|
:visible.sync="dialogVisible"
|
||||||
|
:close-on-click-modal="false"
|
||||||
|
:close-on-press-escape="false"
|
||||||
|
:show-close="false"
|
||||||
|
width="400px"
|
||||||
|
center
|
||||||
|
>
|
||||||
|
<div class="account-list">
|
||||||
|
<div
|
||||||
|
v-for="user in userList"
|
||||||
|
:key="user.userId"
|
||||||
|
class="account-item"
|
||||||
|
:class="{ 'is-selected': selectedUserId === user.userId }"
|
||||||
|
@click="handleSelect(user.userId)"
|
||||||
|
>
|
||||||
|
<div class="account-info">
|
||||||
|
<i class="el-icon-user-solid account-icon" />
|
||||||
|
<div class="account-detail">
|
||||||
|
<div class="account-name">{{ user.realname || user.username }}</div>
|
||||||
|
<div v-if="user.realname" class="account-username">{{ user.username }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<i
|
||||||
|
v-if="selectedUserId === user.userId"
|
||||||
|
class="el-icon-check check-icon"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<span slot="footer" class="dialog-footer">
|
||||||
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
:disabled="!selectedUserId"
|
||||||
|
:loading="loginLoading"
|
||||||
|
style="width: 100%"
|
||||||
|
@click="handleLogin"
|
||||||
|
>
|
||||||
|
确 定
|
||||||
|
</el-button>
|
||||||
|
</span>
|
||||||
|
</el-dialog>
|
||||||
|
|
||||||
|
<!-- 错误提示 -->
|
||||||
|
<el-dialog
|
||||||
|
title="提示"
|
||||||
|
:visible.sync="errorVisible"
|
||||||
|
:close-on-click-modal="false"
|
||||||
|
:close-on-press-escape="false"
|
||||||
|
:show-close="false"
|
||||||
|
width="360px"
|
||||||
|
center
|
||||||
|
>
|
||||||
|
<div class="error-content">
|
||||||
|
<i class="el-icon-warning-outline" />
|
||||||
|
<p>{{ errorMessage }}</p>
|
||||||
|
</div>
|
||||||
|
<span slot="footer" class="dialog-footer">
|
||||||
|
<el-button type="primary" style="width: 100%" @click="goToLogin">
|
||||||
|
返回登录页
|
||||||
|
</el-button>
|
||||||
|
</span>
|
||||||
|
</el-dialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { getOAuth2Selection, selectOAuth2Login } from '@/api/user.js'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'OAuth2',
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
loading: true,
|
||||||
|
dialogVisible: false,
|
||||||
|
errorVisible: false,
|
||||||
|
errorMessage: '',
|
||||||
|
code: '',
|
||||||
|
userList: [],
|
||||||
|
selectedUserId: null,
|
||||||
|
loginLoading: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.init()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
init() {
|
||||||
|
// 从 URL 获取 code 参数
|
||||||
|
this.code = this.$route.query.code
|
||||||
|
if (!this.code) {
|
||||||
|
this.showError('缺少授权码,请重新登录')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// 获取可选账号列表
|
||||||
|
this.fetchUserList()
|
||||||
|
},
|
||||||
|
fetchUserList() {
|
||||||
|
this.loading = true
|
||||||
|
getOAuth2Selection(this.code)
|
||||||
|
.then(response => {
|
||||||
|
const { code, data, msg } = response
|
||||||
|
if (code === 0 && data && data.length > 0) {
|
||||||
|
this.userList = data
|
||||||
|
this.dialogVisible = true
|
||||||
|
} else if (code === 0 && (!data || data.length === 0)) {
|
||||||
|
this.showError('未找到可登录的账号')
|
||||||
|
} else {
|
||||||
|
this.showError(msg || '获取账号列表失败')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
this.showError(error.message || '请求失败,请稍后重试')
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
this.loading = false
|
||||||
|
})
|
||||||
|
},
|
||||||
|
handleSelect(userId) {
|
||||||
|
this.selectedUserId = userId
|
||||||
|
},
|
||||||
|
handleLogin() {
|
||||||
|
if (!this.selectedUserId) {
|
||||||
|
this.$message.warning('请选择一个账号')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.loginLoading = true
|
||||||
|
selectOAuth2Login(this.code, this.selectedUserId)
|
||||||
|
.then(response => {
|
||||||
|
const { code, msg } = response
|
||||||
|
if (code === 0) {
|
||||||
|
this.$message.success('登录成功')
|
||||||
|
this.dialogVisible = false
|
||||||
|
// 跳转到首页
|
||||||
|
this.$router.push({ path: '/redirect' })
|
||||||
|
} else {
|
||||||
|
this.$message.error(msg || '登录失败')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
this.$message.error(error.message || '登录请求失败')
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
this.loginLoading = false
|
||||||
|
})
|
||||||
|
},
|
||||||
|
showError(message) {
|
||||||
|
this.errorMessage = message
|
||||||
|
this.errorVisible = true
|
||||||
|
},
|
||||||
|
goToLogin() {
|
||||||
|
this.errorVisible = false
|
||||||
|
this.$router.push({ path: '/login' })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.oauth2-container {
|
||||||
|
height: 100vh;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
background: #f5f7fa;
|
||||||
|
}
|
||||||
|
|
||||||
|
.loading-wrapper {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
color: #909399;
|
||||||
|
|
||||||
|
i {
|
||||||
|
font-size: 32px;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.account-list {
|
||||||
|
max-height: 300px;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.account-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 16px;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
border: 1px solid #e4e7ed;
|
||||||
|
border-radius: 8px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.3s;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
border-color: #3296FA;
|
||||||
|
background: #f5f9ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.is-selected {
|
||||||
|
border-color: #3296FA;
|
||||||
|
background: #e8f4ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.account-info {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.account-icon {
|
||||||
|
font-size: 36px;
|
||||||
|
color: #3296FA;
|
||||||
|
margin-right: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.account-detail {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.account-name {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #303133;
|
||||||
|
}
|
||||||
|
|
||||||
|
.account-username {
|
||||||
|
font-size: 13px;
|
||||||
|
color: #909399;
|
||||||
|
margin-top: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.check-icon {
|
||||||
|
font-size: 20px;
|
||||||
|
color: #3296FA;
|
||||||
|
}
|
||||||
|
|
||||||
|
.error-content {
|
||||||
|
text-align: center;
|
||||||
|
padding: 20px 0;
|
||||||
|
|
||||||
|
i {
|
||||||
|
font-size: 48px;
|
||||||
|
color: #e6a23c;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
color: #606266;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
Loading…
Reference in New Issue