|
|
@@ -2,11 +2,36 @@
|
|
|
<div class="login-container">
|
|
|
<div class="login-box">
|
|
|
<div class="login-header">
|
|
|
- <h1>四川路桥AI后台管理平台</h1>
|
|
|
+ <h1>四川路桥样本中心</h1>
|
|
|
<p>请登录您的账户</p>
|
|
|
</div>
|
|
|
-
|
|
|
+
|
|
|
+ <!-- 单点登录 -->
|
|
|
+ <div class="sso-section">
|
|
|
+ <el-button
|
|
|
+ type="primary"
|
|
|
+ size="large"
|
|
|
+ class="login-button"
|
|
|
+ @click="handleSSOLogin"
|
|
|
+ >
|
|
|
+ <el-icon><Connection /></el-icon>
|
|
|
+ 单点登录
|
|
|
+ </el-button>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <el-divider>
|
|
|
+ <span class="divider-text">或</span>
|
|
|
+ </el-divider>
|
|
|
+
|
|
|
+ <!-- 本地登录(管理员备用) -->
|
|
|
+ <div class="local-login-toggle">
|
|
|
+ <el-link type="info" @click="showLocalLogin = !showLocalLogin">
|
|
|
+ {{ showLocalLogin ? '收起本地登录' : '本地管理员登录' }}
|
|
|
+ </el-link>
|
|
|
+ </div>
|
|
|
+
|
|
|
<el-form
|
|
|
+ v-show="showLocalLogin"
|
|
|
ref="loginFormRef"
|
|
|
:model="loginForm"
|
|
|
:rules="loginRules"
|
|
|
@@ -22,7 +47,7 @@
|
|
|
clearable
|
|
|
/>
|
|
|
</el-form-item>
|
|
|
-
|
|
|
+
|
|
|
<el-form-item prop="password">
|
|
|
<el-input
|
|
|
v-model="loginForm.password"
|
|
|
@@ -35,7 +60,7 @@
|
|
|
@keyup.enter="handleLogin"
|
|
|
/>
|
|
|
</el-form-item>
|
|
|
-
|
|
|
+
|
|
|
<el-form-item v-if="showCaptcha" prop="captcha">
|
|
|
<div class="captcha-container">
|
|
|
<el-input
|
|
|
@@ -52,7 +77,7 @@
|
|
|
/>
|
|
|
</div>
|
|
|
</el-form-item>
|
|
|
-
|
|
|
+
|
|
|
<el-form-item>
|
|
|
<div class="login-options">
|
|
|
<el-checkbox v-model="loginForm.remember_me">
|
|
|
@@ -63,7 +88,7 @@
|
|
|
</el-link>
|
|
|
</div>
|
|
|
</el-form-item>
|
|
|
-
|
|
|
+
|
|
|
<el-form-item>
|
|
|
<el-button
|
|
|
type="primary"
|
|
|
@@ -75,7 +100,7 @@
|
|
|
登录
|
|
|
</el-button>
|
|
|
</el-form-item>
|
|
|
-
|
|
|
+
|
|
|
<el-form-item>
|
|
|
<div class="register-link">
|
|
|
还没有账户?
|
|
|
@@ -105,6 +130,7 @@ const loginFormRef = ref<FormInstance>()
|
|
|
const loading = ref(false)
|
|
|
const showCaptcha = ref(false)
|
|
|
const captchaImage = ref('')
|
|
|
+const showLocalLogin = ref(false)
|
|
|
|
|
|
const loginForm = reactive<LoginForm>({
|
|
|
username: '',
|
|
|
@@ -126,6 +152,22 @@ const loginRules: FormRules = {
|
|
|
]
|
|
|
}
|
|
|
|
|
|
+// 单点登录
|
|
|
+const handleSSOLogin = async () => {
|
|
|
+ try {
|
|
|
+ const response = await authApi.getSSOAuthorizeUrl()
|
|
|
+ console.log('[Login] getSSOAuthorizeUrl response:', response)
|
|
|
+ const authorizeUrl = response.data?.authorize_url || (response as any).authorize_url
|
|
|
+ if (authorizeUrl) {
|
|
|
+ window.location.href = authorizeUrl
|
|
|
+ } else {
|
|
|
+ console.error('获取SSO授权URL失败,未找到 authorize_url', response)
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error('获取SSO授权URL失败:', error)
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
// 获取验证码
|
|
|
const getCaptcha = async () => {
|
|
|
try {
|
|
|
@@ -145,27 +187,27 @@ const refreshCaptcha = () => {
|
|
|
// 处理登录
|
|
|
const handleLogin = async () => {
|
|
|
if (!loginFormRef.value) return
|
|
|
-
|
|
|
+
|
|
|
try {
|
|
|
await loginFormRef.value.validate()
|
|
|
loading.value = true
|
|
|
-
|
|
|
+
|
|
|
await authStore.login(loginForm)
|
|
|
-
|
|
|
+
|
|
|
ElMessage.success('登录成功')
|
|
|
-
|
|
|
+
|
|
|
// 重定向到原来要访问的页面或默认页面
|
|
|
const redirect = route.query.redirect as string
|
|
|
router.push(redirect || '/dashboard')
|
|
|
-
|
|
|
+
|
|
|
} catch (error: any) {
|
|
|
console.error('登录失败:', error)
|
|
|
-
|
|
|
+
|
|
|
// 如果是验证码错误或需要验证码,显示验证码
|
|
|
if (error.message?.includes('验证码') || !showCaptcha.value) {
|
|
|
await getCaptcha()
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
ElMessage.error(error.message || '登录失败')
|
|
|
} finally {
|
|
|
loading.value = false
|
|
|
@@ -173,9 +215,21 @@ const handleLogin = async () => {
|
|
|
}
|
|
|
|
|
|
onMounted(() => {
|
|
|
+ console.log('[Login] onMounted, query=', route.query, 'isAuthenticated=', authStore.isAuthenticated)
|
|
|
+
|
|
|
// 如果已经登录,重定向到仪表盘
|
|
|
if (authStore.isAuthenticated) {
|
|
|
router.push('/dashboard')
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // 如果 URL 带有 auto_sso=1,自动触发单点登录
|
|
|
+ const autoSso = route.query.auto_sso
|
|
|
+ if (autoSso === '1' || autoSso === 1 || (Array.isArray(autoSso) && autoSso[0] === '1')) {
|
|
|
+ console.log('[Login] 检测到 auto_sso=1,自动触发单点登录')
|
|
|
+ handleSSOLogin()
|
|
|
+ } else {
|
|
|
+ console.log('[Login] 未检测到 auto_sso 参数,显示登录页')
|
|
|
}
|
|
|
})
|
|
|
</script>
|
|
|
@@ -214,6 +268,28 @@ onMounted(() => {
|
|
|
font-size: 14px;
|
|
|
}
|
|
|
|
|
|
+.sso-section {
|
|
|
+ margin-bottom: 10px;
|
|
|
+}
|
|
|
+
|
|
|
+.sso-section .el-button {
|
|
|
+ width: 100%;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ gap: 8px;
|
|
|
+}
|
|
|
+
|
|
|
+.divider-text {
|
|
|
+ color: #999;
|
|
|
+ font-size: 12px;
|
|
|
+}
|
|
|
+
|
|
|
+.local-login-toggle {
|
|
|
+ text-align: center;
|
|
|
+ margin-bottom: 16px;
|
|
|
+}
|
|
|
+
|
|
|
.login-form {
|
|
|
width: 100%;
|
|
|
}
|
|
|
@@ -249,4 +325,4 @@ onMounted(() => {
|
|
|
color: #666;
|
|
|
font-size: 14px;
|
|
|
}
|
|
|
-</style>
|
|
|
+</style>
|