diff --git a/src/pages/GiteeCallback/GiteeCallback.tsx b/src/pages/GiteeCallback/GiteeCallback.tsx new file mode 100644 index 0000000..65726f0 --- /dev/null +++ b/src/pages/GiteeCallback/GiteeCallback.tsx @@ -0,0 +1,63 @@ +import { useEffect, useState } from 'react'; +import { useNavigate, useSearchParams } from 'react-router-dom'; +import { Icon } from '@iconify/react'; +import authService from '../../services/authService'; +import '../GitHubCallback/GitHubCallback.css'; + +export default function GiteeCallback() { + const navigate = useNavigate(); + const [searchParams] = useSearchParams(); + const [error, setError] = useState(''); + + useEffect(() => { + const handleCallback = async () => { + const errorParam = searchParams.get('error'); + const accessToken = searchParams.get('access_token'); + const refreshToken = searchParams.get('refresh_token'); + + if (errorParam) { + setError('Gitee 授权失败'); + setTimeout(() => navigate('/login'), 2000); + return; + } + + // 如果URL中有token,直接保存 + if (accessToken && refreshToken) { + authService.setTokens({ + access_token: accessToken, + refresh_token: refreshToken, + expires_in: 3600, + }); + navigate('/home'); + return; + } + + // 没有必要的参数 + setError('缺少授权信息'); + setTimeout(() => navigate('/login'), 2000); + }; + + handleCallback(); + }, [searchParams, navigate]); + + return ( +
+
+ {error ? ( + <> + +

登录失败

+

{error}

+

正在返回登录页...

+ + ) : ( + <> + +

正在处理 Gitee 登录

+

请稍候...

+ + )} +
+
+ ); +} diff --git a/src/pages/GiteeCallback/index.ts b/src/pages/GiteeCallback/index.ts new file mode 100644 index 0000000..61ebf5b --- /dev/null +++ b/src/pages/GiteeCallback/index.ts @@ -0,0 +1 @@ +export { default } from './GiteeCallback'; diff --git a/src/pages/Login/Login.css b/src/pages/Login/Login.css index 2ba06ad..940e278 100644 --- a/src/pages/Login/Login.css +++ b/src/pages/Login/Login.css @@ -415,6 +415,29 @@ transform: rotate(-8deg) scale(1.1); } +/* Gitee Button */ +.login-button--gitee { + background: linear-gradient(135deg, #c71d23 0%, #d0343a 100%); + color: white; + border: none; + margin-top: 0.5rem; + box-shadow: 0 4px 12px rgba(199, 29, 35, 0.25); +} + +.login-button--gitee:hover { + background: linear-gradient(135deg, #b01920 0%, #c71d23 100%); + transform: translateY(-2px); + box-shadow: 0 6px 20px rgba(199, 29, 35, 0.35); +} + +.login-button--gitee svg { + transition: transform 0.3s; +} + +.login-button--gitee:hover svg { + transform: rotate(-8deg) scale(1.1); +} + /* ===================== DIVIDER ===================== */ .login-divider { display: flex; diff --git a/src/pages/Login/Login.tsx b/src/pages/Login/Login.tsx index 33bacb8..18c9c2e 100644 --- a/src/pages/Login/Login.tsx +++ b/src/pages/Login/Login.tsx @@ -176,6 +176,15 @@ export default function Login({ mode = 'login' }: LoginProps) { 使用 GitHub 登录 + + + + 使用 Gitee 登录 +
diff --git a/src/router/index.tsx b/src/router/index.tsx index 8202cdb..13fa15e 100644 --- a/src/router/index.tsx +++ b/src/router/index.tsx @@ -15,6 +15,7 @@ import TaxCalculatorPage from '../pages/TaxCalculatorPage'; import Login from '../pages/Login/Login'; import Profile from '../pages/Profile'; import GitHubCallback from '../pages/GitHubCallback'; +import GiteeCallback from '../pages/GiteeCallback'; import Notifications from '../pages/Notifications'; import Layout from '../components/common/Layout'; import ProtectedRoute from '../components/common/ProtectedRoute'; @@ -36,6 +37,10 @@ export const router = createBrowserRouter([ path: '/auth/github/callback', element: , }, + { + path: '/auth/gitee/callback', + element: , + }, { path: '/', element: , diff --git a/src/services/authService.ts b/src/services/authService.ts index 09c02a1..655b519 100644 --- a/src/services/authService.ts +++ b/src/services/authService.ts @@ -178,6 +178,38 @@ export async function handleGitHubCallback(code: string): Promise<{ user: User; throw new Error('GitHub authentication failed'); } +/** + * Get Gitee OAuth login URL + */ +export function getGiteeLoginUrl(state?: string): string { + const isLocal = window.location.hostname === 'localhost' || window.location.hostname === '127.0.0.1'; + const baseUrl = isLocal + ? (import.meta.env.VITE_API_BASE_URL || 'http://localhost:2612/api/v1') + : '/api/v1'; + + console.log('[Auth] Generating Gitee URL with base:', baseUrl); + + let fullUrlString; + if (baseUrl.startsWith('/')) { + fullUrlString = `${window.location.origin}${baseUrl}/auth/gitee`; + } else { + fullUrlString = `${baseUrl}/auth/gitee`; + } + + const url = new URL(fullUrlString); + if (state) { + url.searchParams.append('state', state); + } + return url.toString(); +} + +/** + * Redirect to Gitee OAuth login + */ +export function loginWithGitee(state?: string): void { + window.location.href = getGiteeLoginUrl(state); +} + /** * Get current user information */ @@ -215,6 +247,8 @@ export default { loginWithGitHub, getGitHubLoginUrl, handleGitHubCallback, + loginWithGitee, + getGiteeLoginUrl, getCurrentUser, updatePassword, };