添加登录内容,尚未完善,先创建分支
This commit is contained in:
+93
-140
@@ -1,8 +1,10 @@
|
||||
import { useState } from "react";
|
||||
import { useActionData, Form } from "@remix-run/react";
|
||||
import { type MetaFunction, type ActionFunctionArgs, redirect, type LoaderFunctionArgs } from "@remix-run/node";
|
||||
import { useEffect } from "react";
|
||||
import { useSearchParams } from "@remix-run/react";
|
||||
import { type MetaFunction, type LoaderFunctionArgs, redirect } from "@remix-run/node";
|
||||
import { OAuthClient } from "~/utils/oauth-client";
|
||||
import { OAUTH_CONFIG } from "~/config/api-config";
|
||||
import { getUserSession, getSession } from "~/root";
|
||||
import styles from "~/styles/pages/login.css?url";
|
||||
import { getUserSession, getSession, type UserRole, sessionStorage } from "~/root";
|
||||
|
||||
export const links = () => [
|
||||
{ rel: "stylesheet", href: styles }
|
||||
@@ -15,71 +17,6 @@ export const meta: MetaFunction = () => {
|
||||
];
|
||||
};
|
||||
|
||||
// 处理表单提交的action
|
||||
export async function action({ request }: ActionFunctionArgs) {
|
||||
const formData = await request.formData();
|
||||
const username = formData.get("username") as string;
|
||||
const password = formData.get("password") as string;
|
||||
const userRole = formData.get("userRole") as UserRole || 'common';
|
||||
|
||||
// console.log("userRole-----", userRole);
|
||||
|
||||
// 简单的登录验证,实际应用中应该进行真正的身份验证
|
||||
if (!username || !password) {
|
||||
return Response.json({ error: "用户名和密码不能为空" });
|
||||
}
|
||||
|
||||
if(userRole === 'common') {
|
||||
// console.log("username-----", username);
|
||||
// console.log("password-----", password);
|
||||
const validUsers = [
|
||||
{ username: 'gdycuser', password: 'gdyc06111' },
|
||||
{ username: 'gdycuser2', password: 'gdyc06112' },
|
||||
{ username: 'gdycuser3', password: 'gdyc06113' }
|
||||
];
|
||||
const validUser = validUsers.find(user => user.username === username && user.password === password);
|
||||
if (!validUser) {
|
||||
return Response.json({ error: "普通用户用户名或密码错误" });
|
||||
}
|
||||
}
|
||||
|
||||
// console.log("login success", userRole);
|
||||
|
||||
// 管理员登录
|
||||
if (userRole === 'developer') {
|
||||
const validAdminUsers = [
|
||||
{ username: 'admin', password: 'admin0611' },
|
||||
// { username: 'admin2', password: 'admin06112' },
|
||||
// { username: 'admin3', password: 'admin06113' }
|
||||
];
|
||||
const validAdminUser = validAdminUsers.find(user => user.username === username && user.password === password);
|
||||
if (!validAdminUser) {
|
||||
return Response.json({ error: "管理员用户名或密码错误" });
|
||||
}
|
||||
}
|
||||
|
||||
// 获取session中存储的重定向URL,如果没有则默认到/
|
||||
const session = await getSession(request);
|
||||
// 查看session中存储的redirectTo值
|
||||
const redirectTo = session.get("redirectTo") || "/";
|
||||
// console.log("登录后重定向到:", redirectTo);
|
||||
|
||||
// 创建会话cookie
|
||||
const newSession = await sessionStorage.getSession();
|
||||
newSession.set("isAuthenticated", true);
|
||||
newSession.set("userRole", userRole);
|
||||
const cookie = await sessionStorage.commitSession(newSession);
|
||||
|
||||
// console.log("设置cookie:", !!cookie);
|
||||
|
||||
// 使用新方法进行重定向
|
||||
return redirect(redirectTo, {
|
||||
headers: {
|
||||
"Set-Cookie": cookie
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 加载器,获取当前会话状态
|
||||
export async function loader({ request }: LoaderFunctionArgs) {
|
||||
const { isAuthenticated } = await getUserSession(request);
|
||||
@@ -88,96 +25,112 @@ export async function loader({ request }: LoaderFunctionArgs) {
|
||||
if (isAuthenticated) {
|
||||
return redirect("/");
|
||||
}
|
||||
|
||||
// 获取重定向URL并保存到session
|
||||
const url = new URL(request.url);
|
||||
const redirectTo = url.searchParams.get("redirect") || "/";
|
||||
|
||||
return Response.json({ isAuthenticated });
|
||||
const session = await getSession(request);
|
||||
session.set("redirectTo", redirectTo);
|
||||
|
||||
return Response.json({
|
||||
isAuthenticated: false,
|
||||
redirectTo
|
||||
});
|
||||
}
|
||||
|
||||
export default function Login() {
|
||||
const [username, setUsername] = useState("");
|
||||
const [password, setPassword] = useState("");
|
||||
const [userRole, setUserRole] = useState<UserRole>("common");
|
||||
const [showPassword, setShowPassword] = useState(false);
|
||||
const actionData = useActionData<typeof action>();
|
||||
const [searchParams] = useSearchParams();
|
||||
const error = searchParams.get("error");
|
||||
|
||||
// 获取错误消息的友好描述
|
||||
const getErrorMessage = (error: string | null) => {
|
||||
if (!error) return null;
|
||||
|
||||
switch (error) {
|
||||
case "missing_code":
|
||||
return "登录过程中缺少授权码,请重新登录";
|
||||
case "invalid_state":
|
||||
return "登录状态验证失败,请重新登录";
|
||||
case "token_error":
|
||||
return "获取访问令牌失败,请重新登录";
|
||||
case "userinfo_error":
|
||||
return "获取用户信息失败,请重新登录";
|
||||
case "callback_error":
|
||||
return "登录回调处理失败,请重新登录";
|
||||
default:
|
||||
return decodeURIComponent(error);
|
||||
}
|
||||
};
|
||||
|
||||
// 处理OAuth2.0登录
|
||||
const handleOAuthLogin = () => {
|
||||
try {
|
||||
// 创建OAuth客户端
|
||||
const oauthClient = new OAuthClient(OAUTH_CONFIG);
|
||||
|
||||
// 生成状态值
|
||||
const state = oauthClient.generateState();
|
||||
|
||||
// 将状态值保存到localStorage(用于后续验证)
|
||||
localStorage.setItem("oauth_state", state);
|
||||
|
||||
// 获取授权URL
|
||||
const authorizeUrl = oauthClient.getAuthorizeUrl(state);
|
||||
|
||||
// 重定向到IDaaS登录页面
|
||||
window.location.href = authorizeUrl;
|
||||
} catch (error) {
|
||||
console.error("启动OAuth2.0登录失败:", error);
|
||||
alert("登录系统初始化失败,请联系系统管理员");
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
// 检查OAuth配置是否完整
|
||||
if (!OAUTH_CONFIG.serverUrl || !OAUTH_CONFIG.clientId || !OAUTH_CONFIG.clientSecret) {
|
||||
console.error("OAuth2.0配置不完整:", OAUTH_CONFIG);
|
||||
}
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className="login-page">
|
||||
<div className="login-container">
|
||||
<div className="login-header">
|
||||
{/* <img src="/logo.png" alt="中国烟草" className="login-logo" /> */}
|
||||
<h1 className="login-title">中国烟草AI合同及卷宗审核系统</h1>
|
||||
</div>
|
||||
|
||||
<div className="login-form-container">
|
||||
<h2 className="login-subtitle">用户登录</h2>
|
||||
<Form
|
||||
method="post"
|
||||
className="login-form"
|
||||
>
|
||||
{actionData?.error && (
|
||||
<div className="error-message-container">
|
||||
<div className="error-icon"><i className="ri-error-warning-line"></i></div>
|
||||
<div className="error-text">{actionData.error}</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="form-group">
|
||||
<label htmlFor="username">用户名</label>
|
||||
<input
|
||||
type="text"
|
||||
id="username"
|
||||
name="username"
|
||||
value={username}
|
||||
onChange={(e) => setUsername(e.target.value)}
|
||||
className="form-input"
|
||||
placeholder="请输入用户名"
|
||||
/>
|
||||
<h2 className="login-subtitle">统一身份认证登录</h2>
|
||||
|
||||
{error && (
|
||||
<div className="error-message-container">
|
||||
<div className="error-icon"><i className="ri-error-warning-line"></i></div>
|
||||
<div className="error-text">{getErrorMessage(error)}</div>
|
||||
</div>
|
||||
|
||||
<div className="form-group">
|
||||
<label htmlFor="password">密码</label>
|
||||
<div className="password-input-container">
|
||||
<input
|
||||
type={showPassword ? "text" : "password"}
|
||||
id="password"
|
||||
name="password"
|
||||
value={password}
|
||||
onChange={(e) => setPassword(e.target.value)}
|
||||
className="form-input password-input"
|
||||
placeholder="请输入密码"
|
||||
/>
|
||||
<button
|
||||
type="button"
|
||||
className="password-toggle-btn"
|
||||
onClick={() => setShowPassword(!showPassword)}
|
||||
aria-label={showPassword ? "隐藏密码" : "显示密码"}
|
||||
>
|
||||
<i className={showPassword ? "ri-eye-off-line" : "ri-eye-line"}></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="form-group">
|
||||
<label htmlFor="userRole">用户角色</label>
|
||||
<select
|
||||
id="userRole"
|
||||
name="userRole"
|
||||
value={userRole}
|
||||
onChange={(e) => setUserRole(e.target.value as UserRole)}
|
||||
className="form-input"
|
||||
required
|
||||
>
|
||||
<option value="common">普通用户</option>
|
||||
<option value="developer">管理员</option>
|
||||
</select>
|
||||
)}
|
||||
|
||||
<div className="oauth-login-section">
|
||||
<div className="login-description">
|
||||
<p>请点击下方按钮进行统一身份认证登录</p>
|
||||
</div>
|
||||
|
||||
<button
|
||||
type="submit"
|
||||
className="login-button"
|
||||
onClick={handleOAuthLogin}
|
||||
className="oauth-login-button"
|
||||
type="button"
|
||||
>
|
||||
登录
|
||||
<i className="ri-shield-user-line"></i>
|
||||
统一身份认证登录
|
||||
</button>
|
||||
</Form>
|
||||
|
||||
<div className="login-tips">
|
||||
<p>
|
||||
<i className="ri-information-line"></i>
|
||||
系统将跳转到统一身份认证平台进行登录
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="login-footer">
|
||||
|
||||
Reference in New Issue
Block a user