feat(rvw): deliver tenant portal v4 flow and config foundation
Implement RVW V4.0 tenant-aware backend/frontend flow with tenant routing, config APIs, and full portal UX updates. Sync system/RVW/deployment docs to capture verified upload-review-report workflow and next-step admin configuration work. Made-with: Cursor
This commit is contained in:
@@ -1,23 +1,39 @@
|
||||
import { ReactNode } from 'react'
|
||||
import { Navigate, useLocation } from 'react-router-dom'
|
||||
import { useAuth } from '../auth'
|
||||
import { extractTenantSlug } from '../tenant'
|
||||
import { Result, Button } from 'antd'
|
||||
import { LockOutlined } from '@ant-design/icons'
|
||||
|
||||
/**
|
||||
* 路由守卫组件
|
||||
*
|
||||
* @description
|
||||
* 保护需要特定权限的路由,防止用户通过URL直接访问无权限页面
|
||||
*
|
||||
*
|
||||
* 检查顺序:
|
||||
* 1. 检查是否已登录(未登录→重定向到登录页)
|
||||
* 1. 检查是否已登录(未登录→携带租户标识重定向到登录页)
|
||||
* 2. 检查模块权限(无权限→显示权限不足页面)
|
||||
* 3. 有权限→渲染子组件
|
||||
*
|
||||
* @version 2026-01-16 更新为模块权限系统
|
||||
*
|
||||
* @version 2026-03-14 V4.0:租户感知重定向
|
||||
* - 期刊租户路径(/jtim/*)→ /t/jtim/login?redirect=/jtim/dashboard
|
||||
* - 主平台路径(/rvw/*, /ai-qa/* 等)→ /login(行为不变)
|
||||
* - extractTenantSlug 由 useTenantObserver 模块统一维护,自动排除所有注册模块路径
|
||||
*/
|
||||
|
||||
/**
|
||||
* 构造未登录时的登录跳转目标。
|
||||
*
|
||||
* 对齐 App.tsx 中已定义的路由:<Route path="/t/:tenantCode/login" />
|
||||
*
|
||||
* - 期刊租户下:/t/jtim/login?redirect=%2Fjtim%2Fdashboard
|
||||
* - 主站下:/login(保持原有行为,向后兼容)
|
||||
*/
|
||||
function buildLoginRedirect(pathname: string): string {
|
||||
const tenantSlug = extractTenantSlug(pathname)
|
||||
if (!tenantSlug) return '/login'
|
||||
const redirectParam = encodeURIComponent(pathname)
|
||||
return `/t/${tenantSlug}/login?redirect=${redirectParam}`
|
||||
}
|
||||
|
||||
interface RouteGuardProps {
|
||||
/** 子组件 */
|
||||
children: ReactNode
|
||||
@@ -47,7 +63,9 @@ const RouteGuard = ({
|
||||
|
||||
// 1. 检查是否登录
|
||||
if (!isAuthenticated) {
|
||||
return <Navigate to="/login" state={{ from: location }} replace />
|
||||
// V4.0 租户感知重定向:保留 tenantSlug,让登录页渲染对应期刊品牌
|
||||
const loginTarget = buildLoginRedirect(location.pathname)
|
||||
return <Navigate to={loginTarget} state={{ from: location }} replace />
|
||||
}
|
||||
|
||||
// 2. 检查模块权限(如果指定了 requiredModule)
|
||||
|
||||
Reference in New Issue
Block a user