diff --git a/app/components/contract-template/ContractSearchHero.tsx b/app/components/contract-template/ContractSearchHero.tsx index bde2cda..3265850 100644 --- a/app/components/contract-template/ContractSearchHero.tsx +++ b/app/components/contract-template/ContractSearchHero.tsx @@ -49,8 +49,8 @@ export function ContractSearchHero({ textAlign: 'center', padding: '60px 0', background: 'linear-gradient(135deg, rgba(0, 104, 74, 0.05) 0%, rgba(0, 104, 74, 0.02) 100%)', - borderRadius: '16px', - marginBottom: '32px' + borderRadius: '5px', + // marginBottom: '32px' }}>

= { // 应用模块图标映射 const APP_ICON_MAP: Record = { - 'contract': 'ri-file-list-2-fill', - 'record': 'ri-folder-shared-fill', - 'model': 'ri-robot-2-fill' + 'contract': '/images/icon_hetong.png', + 'record': '/images/icon_anjuan.png', + 'model': '/images/icon_assistant.png' }; export function Sidebar({ onToggle, collapsed, userRole, selectedApp = '' }: SidebarProps) { @@ -367,7 +367,7 @@ export function Sidebar({ onToggle, collapsed, userRole, selectedApp = '' }: Sid ) : ( <> - + {APP_NAME_MAP[currentApp] {APP_NAME_MAP[currentApp] || ''} )} diff --git a/app/root.tsx b/app/root.tsx index a73da21..49ee049 100644 --- a/app/root.tsx +++ b/app/root.tsx @@ -38,19 +38,21 @@ export const developerOnlyPaths = [ '/settings', '/config-lists', '/document-types', - '/prompts' + '/prompts', ]; // 创建基于Cookie的会话存储 // 在实际应用中,应该使用环境变量来设置密钥 -const sessionStorage = createCookieSessionStorage({ +export const sessionStorage = createCookieSessionStorage({ cookie: { - name: "__session", + name: "__lgsession", httpOnly: true, path: "/", sameSite: "lax", secrets: ["s3cr3t"], // 应该从环境变量读取 - secure: process.env.NODE_ENV === "production", + // secure: process.env.NODE_ENV === "production", + maxAge: 60 * 60 * 24 * 1, // 1天 + secure: false, // 开发环境中禁用secure }, }); @@ -63,9 +65,18 @@ export async function getSession(request: Request) { // 获取用户登录状态 export async function getUserSession(request: Request) { const session = await getSession(request); + const isAuthenticated = session.get("isAuthenticated") === true; + const userRole = session.get("userRole") || 'common' as UserRole; + + console.log("获取会话状态:", + // "Cookie:", request.headers.get("Cookie"), + "是否认证:", isAuthenticated, + "用户角色:", userRole + ); + return { - isAuthenticated: session.get("isAuthenticated") === true, - userRole: session.get("userRole") || 'common' as UserRole + isAuthenticated, + userRole }; } @@ -74,10 +85,15 @@ export async function createUserSession(isAuthenticated: boolean, userRole: User const session = await sessionStorage.getSession(); session.set("isAuthenticated", isAuthenticated); session.set("userRole", userRole); - console.log("session-----", session.get("userRole")); + + const cookie = await sessionStorage.commitSession(session); + console.log("创建会话 - 设置Cookie:", !!cookie); + console.log("创建会话 - 用户角色:", userRole); + console.log("创建会话 - 重定向到:", redirectTo); + return redirect(redirectTo, { headers: { - "Set-Cookie": await sessionStorage.commitSession(session), + "Set-Cookie": cookie, }, }); } @@ -117,15 +133,17 @@ export async function loader({ request }: LoaderFunctionArgs) { // 获取用户会话 const { isAuthenticated, userRole } = await getUserSession(request); - // console.log("Auth status:", { isAuthenticated, userRole, pathname }); + console.log("是否公开路径:", isPublicPath, "是否已认证:", isAuthenticated); // 如果访问需要认证的路径但未登录,重定向到登录页 if (!isPublicPath && !isAuthenticated) { + console.log("未认证,需要重定向到登录页"); // 保存请求的URL,以便登录后重定向回来 const session = await getSession(request); // 如果路径是/home,则将重定向目标设置为/ - const redirectTarget = pathname === "/home" ? "/" : pathname; + const redirectTarget = pathname !== "/" ? "/" : pathname; + // const redirectTarget = pathname === "home" ? "/" : pathname; // 保存重定向目标 session.set("redirectTo", redirectTarget); @@ -138,12 +156,13 @@ export async function loader({ request }: LoaderFunctionArgs) { // 如果已登录且访问登录页,重定向到首页 if (pathname === "/login" && isAuthenticated) { - // console.log("Already authenticated, redirecting from login to /"); + console.log("已认证,重定向到首页"); return redirect("/"); } // 检查访问权限 - 如果是common用户访问了开发者专属页面,重定向到首页 if (userRole === 'common' && developerOnlyPaths.some(path => pathname.startsWith(path))) { + console.log("用户没有访问权限,重定向到首页"); return redirect("/"); } diff --git a/app/routes/_index.tsx b/app/routes/_index.tsx index ffb9f72..8cee19b 100644 --- a/app/routes/_index.tsx +++ b/app/routes/_index.tsx @@ -151,7 +151,7 @@ export default function Index() { tabIndex={0} aria-label="合同管理" > - + 合同管理 合同管理 @@ -164,7 +164,7 @@ export default function Index() { tabIndex={0} aria-label="案卷智能评查" > - + 案卷智能评查 案卷智能评查 @@ -177,7 +177,7 @@ export default function Index() { tabIndex={0} aria-label="智慧法务大模型" > - + 智慧法务大模型 智慧法务大模型 diff --git a/app/routes/login.tsx b/app/routes/login.tsx index 79da34e..55c1780 100644 --- a/app/routes/login.tsx +++ b/app/routes/login.tsx @@ -1,8 +1,8 @@ import { useState } from "react"; -import { Form, useActionData, useNavigation } from "@remix-run/react"; +import { useActionData } from "@remix-run/react"; import { type MetaFunction, type ActionFunctionArgs, redirect, type LoaderFunctionArgs } from "@remix-run/node"; import styles from "~/styles/pages/login.css?url"; -import { createUserSession, getUserSession, getSession, type UserRole } from "~/root"; +import { getUserSession, getSession, type UserRole, sessionStorage } from "~/root"; export const links = () => [ { rel: "stylesheet", href: styles } @@ -31,22 +31,30 @@ export async function action({ request }: ActionFunctionArgs) { if (userRole === 'developer') { if (username !== 'admin' || password !== 'admin') { - // toastService.error("管理员用户名或密码错误"); return Response.json({ error: "管理员用户名或密码错误" }); } } - // 在实际应用中,这里应该是对用户名和密码的验证逻辑 - // 简化起见,我们直接视为登录成功 - // 获取session中存储的重定向URL,如果没有则默认到/ const session = await getSession(request); // 查看session中存储的redirectTo值 const redirectTo = session.get("redirectTo") || "/"; - // console.log("登录后重定向到:", redirectTo); + console.log("登录后重定向到:", redirectTo); - // 创建登录会话并重定向 - return createUserSession(true, userRole, 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 + } + }); } // 加载器,获取当前会话状态 @@ -66,18 +74,7 @@ export default function Login() { const [password, setPassword] = useState(""); const [userRole, setUserRole] = useState("common"); const actionData = useActionData(); - const navigation = useNavigation(); - // 使用 useEffect 确保错误提示只显示一次 - // useEffect(() => { - // if(actionData?.error) { - // toastService.error(actionData.error); - // } - // }, [actionData?.error]); - - // 判断是否正在提交表单 - const isSubmitting = navigation.state === "submitting"; - return (
@@ -88,7 +85,11 @@ export default function Login() {

用户登录

-
+ {actionData?.error && (
@@ -140,11 +141,10 @@ export default function Login() { - +
diff --git a/app/styles/pages/contract-template.css b/app/styles/pages/contract-template.css index fbf76bf..967b189 100644 --- a/app/styles/pages/contract-template.css +++ b/app/styles/pages/contract-template.css @@ -14,15 +14,15 @@ } .contract-template-search { - padding: 24px; + /* padding: 24px; */ background: var(--gradient-bg); - min-height: 100vh; + min-height: calc(100vh - 90px); } .contract-search-results { padding: 24px; background: var(--gradient-bg); - min-height: 100vh; + min-height: calc(100vh - 90px); } /* 搜索英雄区域 */ @@ -158,6 +158,7 @@ display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 16px; + padding:8px; margin-top: 40px; } diff --git a/app/styles/pages/home.css b/app/styles/pages/home.css index bce1242..e028381 100644 --- a/app/styles/pages/home.css +++ b/app/styles/pages/home.css @@ -14,7 +14,8 @@ align-items: center; padding: 0.75rem 1rem; background-color: white; - box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05); + box-shadow: 0px 2px 4px rgba(0, 0, 0, 0.15); + z-index: 1; } .logo-container { @@ -74,7 +75,6 @@ /* 主要内容区域 */ .index-main-content { - border-radius: 0.5rem 0.5rem 0 0; height: 100%; flex: 1; display: flex; @@ -98,7 +98,7 @@ transform: translateY(-7rem); } .welcome-text { - font-size: 1.75rem; + font-size: 1.95rem; font-weight: 500; color: #333; margin-bottom: 5rem; @@ -115,9 +115,12 @@ .module-card { display: flex; align-items: center; - width: 250px; - padding: 2rem 1.5rem; - background: linear-gradient(to bottom, #ebebeb, #ffffff); + justify-content: flex-start; + gap: 1.5rem; + padding: 0 2rem; + height: 136px; + width: 290px; + background: linear-gradient(180deg, #ebf1f7 0%, #ffffff 100%); border-radius: 8px; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05); transition: transform 0.2s, box-shadow 0.2s, border-color 0.2s; @@ -144,8 +147,7 @@ } */ .module-name { - margin-left: 1rem; - font-size: 1.125rem; + font-size: 1.25rem; font-weight: 500; color: #333; } diff --git a/public/images/icon_anjuan.png b/public/images/icon_anjuan.png new file mode 100644 index 0000000..8d50695 Binary files /dev/null and b/public/images/icon_anjuan.png differ diff --git a/public/images/icon_assistant.png b/public/images/icon_assistant.png new file mode 100644 index 0000000..c7baeec Binary files /dev/null and b/public/images/icon_assistant.png differ diff --git a/public/images/icon_hetong.png b/public/images/icon_hetong.png new file mode 100644 index 0000000..037f1f6 Binary files /dev/null and b/public/images/icon_hetong.png differ