做统一认证登录
This commit is contained in:
1 parent
1a4471e34d
commit
fa281363fb
78 files changed
+8127
-1442
No files matched your search
@@ -0,0 +1,97 @@
|
||||
<template>
|
||||
<div class="auth-callback">
|
||||
<div class="box">
|
||||
<div v-if="error" class="error">
|
||||
<p class="title">登录失败</p>
|
||||
<p class="msg">{{ error }}</p>
|
||||
<button class="btn" @click="retry">重新登录</button>
|
||||
</div>
|
||||
<div v-else class="loading">
|
||||
<div class="spinner"></div>
|
||||
<p>正在完成登录,请稍候…</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { onMounted, ref } from "vue";
|
||||
import { handleAuthorizeCallback, redirectToAuthorize } from "@/utils/authClient";
|
||||
|
||||
const error = ref("");
|
||||
|
||||
async function finish() {
|
||||
// hash 路由:参数位于 location.hash 之后,这里统一从 URL 中取出
|
||||
const raw = window.location.href;
|
||||
const queryStr = raw.includes("?") ? raw.slice(raw.indexOf("?") + 1) : "";
|
||||
const query = Object.fromEntries(new URLSearchParams(queryStr));
|
||||
|
||||
try {
|
||||
await handleAuthorizeCallback(query);
|
||||
// 登录成功:清掉 URL 上的 code/state,进入首页
|
||||
window.location.href = "#/home";
|
||||
window.location.reload();
|
||||
} catch (e) {
|
||||
error.value = e?.message || "登录失败";
|
||||
}
|
||||
}
|
||||
|
||||
function retry() {
|
||||
redirectToAuthorize();
|
||||
}
|
||||
|
||||
onMounted(finish);
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.auth-callback {
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
}
|
||||
.box {
|
||||
background: #fff;
|
||||
border-radius: 12px;
|
||||
padding: 40px 36px;
|
||||
width: 360px;
|
||||
text-align: center;
|
||||
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
.spinner {
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
margin: 0 auto 16px;
|
||||
border: 3px solid #e4e7ee;
|
||||
border-top-color: #667eea;
|
||||
border-radius: 50%;
|
||||
animation: spin 0.8s linear infinite;
|
||||
}
|
||||
@keyframes spin {
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
.title {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: #cf1322;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
.msg {
|
||||
font-size: 13px;
|
||||
color: #5a6072;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.btn {
|
||||
height: 40px;
|
||||
padding: 0 24px;
|
||||
border: none;
|
||||
border-radius: 8px;
|
||||
cursor: pointer;
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
color: #fff;
|
||||
font-size: 14px;
|
||||
}
|
||||
</style>
|
||||
@@ -196,17 +196,17 @@ const performLoginRequest = async () => {
|
||||
|
||||
if (res && res.code === 200) {
|
||||
// 登录成功:处理"记住我"
|
||||
// 安全:只记住账号与租户名,绝不明文存储密码
|
||||
if (rememberMe.value) {
|
||||
localStorage.setItem("loginAccount", account.value);
|
||||
localStorage.setItem("loginTenantName", tenant_name.value);
|
||||
localStorage.setItem("loginPassword", password.value);
|
||||
localStorage.setItem("loginRememberMe", "true");
|
||||
} else {
|
||||
localStorage.removeItem("loginAccount");
|
||||
localStorage.removeItem("loginTenantName");
|
||||
localStorage.removeItem("loginPassword");
|
||||
localStorage.setItem("loginRememberMe", "false");
|
||||
}
|
||||
localStorage.removeItem("loginPassword");
|
||||
|
||||
authStore.setLoginInfo({ ...res.data, tenant_name: tenant_name.value });
|
||||
|
||||
@@ -327,17 +327,17 @@ const startGeetest4 = async () => {
|
||||
});
|
||||
|
||||
if (loginRes && loginRes.code === 200) {
|
||||
// 安全:只记住账号与租户名,绝不明文存储密码
|
||||
if (rememberMe.value) {
|
||||
localStorage.setItem("loginAccount", account.value);
|
||||
localStorage.setItem("loginTenantName", tenant_name.value);
|
||||
localStorage.setItem("loginPassword", password.value);
|
||||
localStorage.setItem("loginRememberMe", "true");
|
||||
} else {
|
||||
localStorage.removeItem("loginAccount");
|
||||
localStorage.removeItem("loginTenantName");
|
||||
localStorage.removeItem("loginPassword");
|
||||
localStorage.setItem("loginRememberMe", "false");
|
||||
}
|
||||
localStorage.removeItem("loginPassword");
|
||||
|
||||
authStore.setLoginInfo({ ...loginRes.data, tenant_name: tenant_name.value });
|
||||
const { useTabsStore } = await import("@/stores");
|
||||
@@ -471,7 +471,6 @@ onMounted(async () => {
|
||||
if (savedRemember === "true") {
|
||||
tenant_name.value = localStorage.getItem("loginTenantName") || "";
|
||||
account.value = localStorage.getItem("loginAccount") || "";
|
||||
password.value = localStorage.getItem("loginPassword") || "";
|
||||
rememberMe.value = true;
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user