feat: 支持 github 登录

This commit is contained in:
hzm
2026-03-22 22:28:45 +08:00
parent 7beac75160
commit d07146b819
4 changed files with 106 additions and 4 deletions

View File

@@ -1,7 +1,9 @@
'use client'; 'use client';
import Image from 'next/image';
import { InputOTP, InputOTPGroup, InputOTPSlot } from '@/components/ui/input-otp'; import { InputOTP, InputOTPGroup, InputOTPSlot } from '@/components/ui/input-otp';
import { MailIcon } from './Icons'; import { MailIcon } from './Icons';
import githubImg from "../assets/github.svg";
export default function LoginModal({ export default function LoginModal({
onClose, onClose,
@@ -13,7 +15,8 @@ export default function LoginModal({
loginError, loginError,
loginSuccess, loginSuccess,
handleSendOtp, handleSendOtp,
handleVerifyEmailOtp handleVerifyEmailOtp,
handleGithubLogin
}) { }) {
return ( return (
<div <div
@@ -84,7 +87,6 @@ export default function LoginModal({
type="button" type="button"
className="button secondary" className="button secondary"
onClick={onClose} onClick={onClose}
disabled={loginLoading}
> >
取消 取消
</button> </button>
@@ -98,6 +100,53 @@ export default function LoginModal({
</button> </button>
</div> </div>
</form> </form>
{handleGithubLogin && (
<>
<div
className="login-divider"
style={{
display: 'flex',
alignItems: 'center',
margin: '20px 0',
gap: 12,
}}
>
<div style={{ flex: 1, height: 1, background: 'var(--border)' }} />
<span className="muted" style={{ fontSize: '12px', whiteSpace: 'nowrap' }}>或使用</span>
<div style={{ flex: 1, height: 1, background: 'var(--border)' }} />
</div>
<button
type="button"
className="github-login-btn"
onClick={handleGithubLogin}
disabled={loginLoading}
style={{
width: '100%',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
gap: 10,
padding: '12px 16px',
border: '1px solid var(--border)',
borderRadius: 8,
background: 'var(--bg)',
color: 'var(--text)',
cursor: loginLoading ? 'not-allowed' : 'pointer',
fontSize: '14px',
fontWeight: 500,
opacity: loginLoading ? 0.6 : 1,
transition: 'all 0.2s ease',
}}
>
<span className="github-icon-wrap">
<Image unoptimized alt="项目Github地址" src={githubImg} style={{ width: '24px', height: '24px', cursor: 'pointer' }} onClick={() => window.open("https://github.com/hzm0321/real-time-fund")} />
</span>
<span>使用 GitHub 登录</span>
</button>
</>
)}
</div> </div>
</div> </div>
); );

View File

@@ -3348,6 +3348,35 @@ input[type="number"] {
color: var(--success); color: var(--success);
} }
/* ========== GitHub 登录按钮样式 ========== */
.github-login-btn {
backdrop-filter: blur(12px);
-webkit-backdrop-filter: blur(12px);
}
.github-login-btn:hover {
border-color: var(--primary);
background: rgba(34, 211, 238, 0.05);
}
.github-login-btn:active {
transform: scale(0.98);
}
[data-theme="light"] .github-login-btn {
background: #f8fafc;
border-color: #e2e8f0;
}
[data-theme="light"] .github-login-btn:hover {
background: #f1f5f9;
border-color: #94a3af;
}
[data-theme="light"] .github-login-btn img {
filter: brightness(0.2);
}
.button.secondary { .button.secondary {
background: transparent; background: transparent;
border: 1px solid var(--border); border: 1px solid var(--border);

View File

@@ -33,6 +33,7 @@ const createNoopSupabase = () => ({
data: { subscription: { unsubscribe: () => { } } } data: { subscription: { unsubscribe: () => { } } }
}), }),
signInWithOtp: async () => ({ data: null, error: { message: 'Supabase not configured' } }), signInWithOtp: async () => ({ data: null, error: { message: 'Supabase not configured' } }),
signInWithOAuth: async () => ({ data: null, error: { message: 'Supabase not configured' } }),
verifyOtp: async () => ({ data: null, error: { message: 'Supabase not configured' } }), verifyOtp: async () => ({ data: null, error: { message: 'Supabase not configured' } }),
signOut: async () => ({ error: null }) signOut: async () => ({ error: null })
}, },

View File

@@ -2415,6 +2415,29 @@ export default function HomePage() {
setLoginLoading(false); setLoginLoading(false);
}; };
const handleGithubLogin = async () => {
setLoginError('');
if (!isSupabaseConfigured) {
showToast('未配置 Supabase无法登录', 'error');
return;
}
try {
isExplicitLoginRef.current = true;
setLoginLoading(true);
const { error } = await supabase.auth.signInWithOAuth({
provider: 'github',
options: {
redirectTo: window.location.origin
}
});
if (error) throw error;
} catch (err) {
setLoginError(err.message || 'GitHub 登录失败,请稍后再试');
isExplicitLoginRef.current = false;
setLoginLoading(false);
}
};
// 登出 // 登出
const handleLogout = async () => { const handleLogout = async () => {
isLoggingOutRef.current = true; isLoggingOutRef.current = true;
@@ -3560,7 +3583,6 @@ export default function HomePage() {
useEffect(() => { useEffect(() => {
const isAnyModalOpen = const isAnyModalOpen =
settingsOpen ||
feedbackOpen || feedbackOpen ||
addResultOpen || addResultOpen ||
addFundToGroupOpen || addFundToGroupOpen ||
@@ -3596,7 +3618,6 @@ export default function HomePage() {
containerRef.current.style.overflow = ''; containerRef.current.style.overflow = '';
}; };
}, [ }, [
settingsOpen,
feedbackOpen, feedbackOpen,
addResultOpen, addResultOpen,
addFundToGroupOpen, addFundToGroupOpen,
@@ -4882,6 +4903,7 @@ export default function HomePage() {
setLoginSuccess(''); setLoginSuccess('');
setLoginEmail(''); setLoginEmail('');
setLoginOtp(''); setLoginOtp('');
setLoginLoading(false);
}} }}
loginEmail={loginEmail} loginEmail={loginEmail}
setLoginEmail={setLoginEmail} setLoginEmail={setLoginEmail}
@@ -4892,6 +4914,7 @@ export default function HomePage() {
loginSuccess={loginSuccess} loginSuccess={loginSuccess}
handleSendOtp={handleSendOtp} handleSendOtp={handleSendOtp}
handleVerifyEmailOtp={handleVerifyEmailOtp} handleVerifyEmailOtp={handleVerifyEmailOtp}
handleGithubLogin={isSupabaseConfigured ? handleGithubLogin : undefined}
/> />
)} )}