import { useEffect } from "react"; import { useSearchParams, Form } from "@remix-run/react"; import { type MetaFunction, type LoaderFunctionArgs, type ActionFunctionArgs, redirect } from "@remix-run/node"; import { OAuthClient } from "~/api/login/oauth-client"; import { OAUTH_CONFIG } from "~/config/api-config"; import { getUserSession, getSession, sessionStorage, getUserBySub, addDefaultRole } from "~/api/login/auth.server"; import { JWTUtils, type UserInfoForJWT } from "~/utils/jwt"; import styles from "~/styles/pages/login.css?url"; export const links = () => [ { rel: "stylesheet", href: styles } ]; export const meta: MetaFunction = () => { return [ { title: "中国烟草AI合同及卷宗审核系统 - 登录" }, { name: "description", content: "中国烟草AI合同及卷宗审核系统登录页面" }, ]; }; // 加载器,获取当前会话状态 export async function loader({ request }: LoaderFunctionArgs) { const { isAuthenticated } = await getUserSession(request); // 如果已登录,重定向到首页 if (isAuthenticated) { return redirect("/"); } // 获取重定向URL并保存到session const url = new URL(request.url); const redirectTo = url.searchParams.get("redirect") || "/"; const session = await getSession(request); session.set("redirectTo", redirectTo); return Response.json({ isAuthenticated: false, redirectTo }); } // 处理表单提交的action函数 export async function action({ request }: ActionFunctionArgs) { const formData = await request.formData(); const intent = formData.get("intent"); if (intent === "test_user_login") { // 获取重定向目标 const session = await getSession(request); const redirectTo = session.get("redirectTo") || "/"; // 使用测试用户登录 const testUserSub = "001"; // 测试用户的sub const userResult = await getUserBySub(testUserSub); if (userResult.success && userResult.data) { const user = userResult.data; // 确保用户有默认角色 if (user.id) { await addDefaultRole(user.id, 2); // 添加common角色 } // 设置模拟的OAuth token信息 const mockTokenExpiresIn = 60 * 60 * 2; // 2小时,与真实OAuth token保持一致 const userRole = 'common'; // 生成前端专用JWT const jwtUserInfo: UserInfoForJWT = { sub: user.sub, user_id: user.id!, username: user.username, nick_name: user.nick_name, email: user.email, phone_number: user.phone_number, ou_id: user.ou_id, ou_name: user.ou_name, is_leader: user.is_leader, user_role: userRole }; const frontendJWT = JWTUtils.generateJWT(jwtUserInfo, mockTokenExpiresIn); // 打印JWT生成信息 console.log("=== 测试用户登录 - JWT生成信息 ==="); console.log("用户信息:", jwtUserInfo); console.log("生成的JWT:", frontendJWT); console.log("JWT过期时间:", JWTUtils.getJWTExpiration(frontendJWT)); console.log("JWT解析结果:", JWTUtils.decodeJWT(frontendJWT)); console.log("JWT验证结果:", JWTUtils.verifyJWT(frontendJWT)); // 创建session,保持与OAuth登录相同的数据结构 session.set("isAuthenticated", true); session.set("accessToken", "mock_access_token_for_test"); // 模拟的访问令牌 session.set("refreshToken", "mock_refresh_token_for_test"); // 模拟的刷新令牌 session.set("tokenIssuedAt", Date.now()); session.set("tokenExpiresIn", mockTokenExpiresIn); session.set("userRole", userRole); session.set("frontendJWT", frontendJWT); // 构建与OAuth登录相同结构的userInfo const enhancedUserInfo = { // 保持与callback.tsx中相同的数据结构 sub: user.sub, username: user.username, nick_name: user.nick_name, phone_number: user.phone_number, email: user.email, ou_id: user.ou_id, ou_name: user.ou_name, status: user.status, is_leader: user.is_leader, // 增强字段,与OAuth登录保持一致 user_id: user.id, user_role: userRole, frontend_jwt: frontendJWT }; session.set("userInfo", enhancedUserInfo); // 打印session信息 console.log("=== 测试用户登录 - Session信息 ==="); console.log("保存到session的userInfo:", enhancedUserInfo); console.log("session数据结构:", { isAuthenticated: true, userRole: userRole, accessToken: "mock_access_token_for_test", refreshToken: "mock_refresh_token_for_test", tokenIssuedAt: Date.now(), tokenExpiresIn: mockTokenExpiresIn, frontendJWT: frontendJWT, userInfo: enhancedUserInfo }); const cookie = await sessionStorage.commitSession(session); console.log("=== 测试用户登录完成 ==="); console.log("用户:", user.username); console.log("角色:", userRole); console.log("重定向到:", redirectTo); return new Response(null, { status: 302, headers: { Location: redirectTo, "Set-Cookie": cookie, }, }); } else { // 如果用户不存在,重定向到登录页面并显示错误 return redirect(`/login?error=${encodeURIComponent("测试用户不存在")}`); } } return null; } export default function Login() { 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 (

中国烟草AI合同及卷宗审核系统

统一身份认证登录

{error && (
{getErrorMessage(error)}
)}

请点击下方按钮进行统一身份认证登录

系统将跳转到统一身份认证平台进行登录

{/* 测试用户登录区域 */}

使用测试用户(testuser1)登录,默认普通权限

© 2025 中国烟草 版权所有

); }