|
1 | | -import React, { useState } from "react"; |
| 1 | +import React, { useEffect, useState } from "react"; |
2 | 2 | import { Link, useNavigate, useSearchParams } from "react-router-dom"; |
3 | | -import { Form, Input, Button, message } from "antd"; |
| 3 | +import { Form, Input, Button, message, Divider } from "antd"; |
4 | 4 | import { UserOutlined, LockOutlined } from "@ant-design/icons"; |
5 | | -import api from "../lib/api"; |
| 5 | +import api, { type IdpResult } from "../lib/api"; |
6 | 6 | import { AxiosError } from "axios"; |
7 | 7 | import { Layout } from "../components/Layout"; |
| 8 | +import APIs from "../lib/apis"; |
| 9 | + |
| 10 | +import aliyunIcon from "../assets/aliyun.png"; |
| 11 | +import githubIcon from "../assets/github.png"; |
| 12 | +import googleIcon from "../assets/google.png"; |
| 13 | + |
| 14 | + |
| 15 | +const oidcIcons: Record<string, React.ReactNode> = { |
| 16 | + google: <img src={googleIcon} alt="Google" className="w-5 h-5 mr-2" />, |
| 17 | + github: <img src={githubIcon} alt="GitHub" className="w-6 h-6 mr-2" />, |
| 18 | + aliyun: <img src={aliyunIcon} alt="Aliyun" className="w-6 h-6 mr-2" />, |
| 19 | +}; |
8 | 20 |
|
9 | 21 | const Login: React.FC = () => { |
| 22 | + const [providers, setProviders] = useState<IdpResult[]>([]); |
10 | 23 | const [loading, setLoading] = useState(false); |
11 | 24 | const navigate = useNavigate(); |
12 | 25 | const [searchParams] = useSearchParams(); |
13 | 26 |
|
| 27 | + useEffect(() => { |
| 28 | + // 使用OidcController的接口获取OIDC提供商 |
| 29 | + APIs.getOidcProviders() |
| 30 | + .then(({data}) => { |
| 31 | + console.log('OIDC providers response:', data); |
| 32 | + setProviders(data); |
| 33 | + }) |
| 34 | + .catch((error) => { |
| 35 | + console.error('Failed to fetch OIDC providers:', error); |
| 36 | + setProviders([]); |
| 37 | + }); |
| 38 | + }, []); |
| 39 | + |
14 | 40 | // 账号密码登录 |
15 | 41 | const handlePasswordLogin = async (values: { username: string; password: string }) => { |
16 | 42 | setLoading(true); |
@@ -45,14 +71,25 @@ const Login: React.FC = () => { |
45 | 71 | } |
46 | 72 | }; |
47 | 73 |
|
| 74 | + // 跳转到 OIDC 授权 - 对接OidcController |
| 75 | + const handleOidcLogin = (provider: string) => { |
| 76 | + // 获取API前缀配置 |
| 77 | + const apiPrefix = api.defaults.baseURL || '/api/v1'; |
| 78 | + |
| 79 | + // 构建授权URL - 对接 /developers/oidc/authorize |
| 80 | + const authUrl = new URL(`${window.location.origin}${apiPrefix}/developers/oidc/authorize`); |
| 81 | + authUrl.searchParams.set('provider', provider); |
| 82 | + |
| 83 | + console.log('Redirecting to OIDC authorization:', authUrl.toString()); |
| 84 | + |
| 85 | + // 跳转到OIDC授权服务器 |
| 86 | + window.location.href = authUrl.toString(); |
| 87 | + }; |
| 88 | + |
48 | 89 | return ( |
49 | 90 | <Layout> |
50 | 91 | <div |
51 | 92 | className="min-h-[calc(100vh-96px)] w-full flex items-center justify-center" |
52 | | - style={{ |
53 | | - backdropFilter: 'blur(204px)', |
54 | | - WebkitBackdropFilter: 'blur(204px)', |
55 | | - }} |
56 | 93 | > |
57 | 94 | <div className="w-full max-w-md mx-4"> |
58 | 95 | {/* 登录卡片 */} |
@@ -115,6 +152,30 @@ const Login: React.FC = () => { |
115 | 152 | </Button> |
116 | 153 | </Form.Item> |
117 | 154 | </Form> |
| 155 | + {/* 分隔线 */} |
| 156 | + { |
| 157 | + providers.length > 0 && ( |
| 158 | + <Divider plain className="text-subTitle"><span className="text-subTitle">或</span></Divider> |
| 159 | + ) |
| 160 | + } |
| 161 | + {/* OIDC 登录按钮 */} |
| 162 | + <div className="flex flex-col gap-2 mb-2"> |
| 163 | + {providers.length === 0 ? ( |
| 164 | + null |
| 165 | + ) : ( |
| 166 | + providers.map((provider) => ( |
| 167 | + <Button |
| 168 | + key={provider.provider} |
| 169 | + onClick={() => handleOidcLogin(provider.provider)} |
| 170 | + className="w-full flex items-center justify-center" |
| 171 | + size="large" |
| 172 | + icon={oidcIcons[provider.provider.toLowerCase()] || <span></span>} |
| 173 | + > |
| 174 | + 使用 {provider.name || provider.provider} 登录 |
| 175 | + </Button> |
| 176 | + )) |
| 177 | + )} |
| 178 | + </div> |
118 | 179 | <div className="text-center text-subTitle"> |
119 | 180 | 没有账号?<Link to="/register" className="text-colorPrimary hover:text-colorPrimary hover:underline">注册</Link> |
120 | 181 | </div> |
|
0 commit comments