打手端迁移至独立子域名
This commit is contained in:
+55
-12
@@ -1,9 +1,19 @@
|
||||
import { Suspense, lazy } from 'react'
|
||||
import { Suspense, lazy, useEffect } from 'react'
|
||||
import { Spin } from 'antd'
|
||||
import { HashRouter, Navigate, Outlet, Route, Routes, useLocation } from 'react-router'
|
||||
import {
|
||||
BrowserRouter,
|
||||
HashRouter,
|
||||
Navigate,
|
||||
Outlet,
|
||||
Route,
|
||||
Routes,
|
||||
useLocation,
|
||||
} from 'react-router'
|
||||
|
||||
import { getAdminRole, hasAdminSession } from '@/utils/admin-auth'
|
||||
import { isWorkerSite, WORKER_SITE_ORIGIN } from '@/utils/site'
|
||||
import { hasWorkerSession } from '@/utils/worker-auth'
|
||||
import { resolveLegacyWorkerPath } from '@/utils/worker-routes'
|
||||
import AdminLayout from '@/layouts/AdminLayout'
|
||||
import WorkerLayout from '@/layouts/WorkerLayout'
|
||||
|
||||
@@ -63,13 +73,27 @@ function RequireWorker() {
|
||||
const location = useLocation()
|
||||
|
||||
if (!hasWorkerSession()) {
|
||||
return <Navigate to="/worker/login" replace state={{ from: location }} />
|
||||
return <Navigate to="/" replace state={{ from: location }} />
|
||||
}
|
||||
|
||||
return <Outlet />
|
||||
}
|
||||
|
||||
export default function App() {
|
||||
const legacyWorkerPath = resolveLegacyWorkerPath(window.location.hash)
|
||||
|
||||
if (legacyWorkerPath) {
|
||||
return <WorkerSiteRedirect path={legacyWorkerPath} />
|
||||
}
|
||||
|
||||
if (isWorkerSite()) {
|
||||
return <WorkerApplication />
|
||||
}
|
||||
|
||||
return <AdminApplication />
|
||||
}
|
||||
|
||||
function AdminApplication() {
|
||||
return (
|
||||
<HashRouter>
|
||||
<Suspense fallback={<RouteLoading />}>
|
||||
@@ -96,15 +120,6 @@ export default function App() {
|
||||
</Route>
|
||||
</Route>
|
||||
</Route>
|
||||
<Route path="/worker/login" element={<WorkerLoginPage />} />
|
||||
<Route element={<RequireWorker />}>
|
||||
<Route path="/worker" element={<WorkerLayout />}>
|
||||
<Route index element={<Navigate to="/worker/hall" replace />} />
|
||||
<Route path="hall" element={<WorkerHallPage />} />
|
||||
<Route path="orders" element={<WorkerOrdersPage />} />
|
||||
<Route path="profile" element={<WorkerProfilePage />} />
|
||||
</Route>
|
||||
</Route>
|
||||
<Route path="/claim/:token" element={<ClaimPage />} />
|
||||
<Route path="/collect" element={<CollectPage />} />
|
||||
<Route path="*" element={<NotFoundPage />} />
|
||||
@@ -114,6 +129,34 @@ export default function App() {
|
||||
)
|
||||
}
|
||||
|
||||
function WorkerApplication() {
|
||||
return (
|
||||
<BrowserRouter>
|
||||
<Suspense fallback={<RouteLoading />}>
|
||||
<Routes>
|
||||
<Route path="/" element={<WorkerLoginPage />} />
|
||||
<Route element={<RequireWorker />}>
|
||||
<Route element={<WorkerLayout />}>
|
||||
<Route path="hall" element={<WorkerHallPage />} />
|
||||
<Route path="orders" element={<WorkerOrdersPage />} />
|
||||
<Route path="profile" element={<WorkerProfilePage />} />
|
||||
</Route>
|
||||
</Route>
|
||||
<Route path="*" element={<Navigate to="/" replace />} />
|
||||
</Routes>
|
||||
</Suspense>
|
||||
</BrowserRouter>
|
||||
)
|
||||
}
|
||||
|
||||
function WorkerSiteRedirect({ path }: { path: string }) {
|
||||
useEffect(() => {
|
||||
window.location.replace(`${WORKER_SITE_ORIGIN}${path}`)
|
||||
}, [path])
|
||||
|
||||
return <RouteLoading />
|
||||
}
|
||||
|
||||
function RouteLoading() {
|
||||
return (
|
||||
<div className="route-loading">
|
||||
|
||||
@@ -13,15 +13,15 @@ import { useIsMobile } from '@/utils/use-is-mobile'
|
||||
import { clearWorkerSession, getWorkerStatus, getWorkerUsername } from '@/utils/worker-auth'
|
||||
|
||||
const menuItems: MenuProps['items'] = [
|
||||
{ key: '/worker/hall', icon: <ShoppingOutlined />, label: '抢单大厅' },
|
||||
{ key: '/worker/orders', icon: <ContainerOutlined />, label: '我的订单' },
|
||||
{ key: '/worker/profile', icon: <UserOutlined />, label: '个人中心' },
|
||||
{ key: '/hall', icon: <ShoppingOutlined />, label: '抢单大厅' },
|
||||
{ key: '/orders', icon: <ContainerOutlined />, label: '我的订单' },
|
||||
{ key: '/profile', icon: <UserOutlined />, label: '个人中心' },
|
||||
]
|
||||
|
||||
const tabItems = [
|
||||
{ key: '/worker/hall', icon: ShoppingOutlined, label: '抢单大厅' },
|
||||
{ key: '/worker/orders', icon: ContainerOutlined, label: '我的订单' },
|
||||
{ key: '/worker/profile', icon: UserOutlined, label: '个人中心' },
|
||||
{ key: '/hall', icon: ShoppingOutlined, label: '抢单大厅' },
|
||||
{ key: '/orders', icon: ContainerOutlined, label: '我的订单' },
|
||||
{ key: '/profile', icon: UserOutlined, label: '个人中心' },
|
||||
]
|
||||
|
||||
export default function WorkerLayout() {
|
||||
@@ -41,7 +41,7 @@ export default function WorkerLayout() {
|
||||
} finally {
|
||||
clearWorkerSession()
|
||||
message.success('已退出登录')
|
||||
navigate('/worker/login', { replace: true })
|
||||
navigate('/', { replace: true })
|
||||
}
|
||||
}
|
||||
|
||||
@@ -144,9 +144,9 @@ export default function WorkerLayout() {
|
||||
}
|
||||
|
||||
function resolveSelectedKey(pathname: string) {
|
||||
if (pathname.startsWith('/worker/orders')) return '/worker/orders'
|
||||
if (pathname.startsWith('/worker/profile')) return '/worker/profile'
|
||||
return '/worker/hall'
|
||||
if (pathname.startsWith('/orders')) return '/orders'
|
||||
if (pathname.startsWith('/profile')) return '/profile'
|
||||
return '/hall'
|
||||
}
|
||||
|
||||
function formatWorkerStatus(status: string) {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import axios from 'axios'
|
||||
import { clearAdminSession, getAdminToken } from '@/utils/admin-auth'
|
||||
import { isWorkerSite } from '@/utils/site'
|
||||
import { clearWorkerSession, getWorkerToken } from '@/utils/worker-auth'
|
||||
|
||||
export interface ApiEnvelope<T> {
|
||||
@@ -84,11 +85,8 @@ http.interceptors.response.use(
|
||||
if (status === 401 && shouldClearWorkerSession(errorCode)) {
|
||||
clearWorkerSession()
|
||||
|
||||
if (
|
||||
window.location.hash.startsWith('#/worker') &&
|
||||
!window.location.hash.startsWith('#/worker/login')
|
||||
) {
|
||||
window.location.hash = '#/worker/login'
|
||||
if (isWorkerSite() && window.location.pathname !== '/') {
|
||||
window.location.replace('/')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ export default function WorkerLoginPage() {
|
||||
}, [countdown])
|
||||
|
||||
if (hasWorkerSession()) {
|
||||
return <Navigate to="/worker/hall" replace />
|
||||
return <Navigate to="/hall" replace />
|
||||
}
|
||||
|
||||
async function submitLogin(values: { username: string; password: string }) {
|
||||
@@ -57,7 +57,7 @@ export default function WorkerLoginPage() {
|
||||
const response = await loginWorker(values)
|
||||
setWorkerSession(response.data.token, response.data.expiresAt, response.data.worker)
|
||||
message.success('登录成功')
|
||||
navigate('/worker/hall', { replace: true })
|
||||
navigate('/hall', { replace: true })
|
||||
} catch (error) {
|
||||
message.error(error instanceof Error ? error.message : '登录失败')
|
||||
} finally {
|
||||
|
||||
@@ -172,7 +172,7 @@ export default function WorkerProfilePage() {
|
||||
} finally {
|
||||
clearWorkerSession()
|
||||
message.success('已退出登录')
|
||||
navigate('/worker/login', { replace: true })
|
||||
navigate('/', { replace: true })
|
||||
}
|
||||
}
|
||||
|
||||
@@ -256,7 +256,7 @@ export default function WorkerProfilePage() {
|
||||
})
|
||||
message.success('密码已修改,请重新登录')
|
||||
clearWorkerSession()
|
||||
navigate('/worker/login', { replace: true })
|
||||
navigate('/', { replace: true })
|
||||
} catch (error) {
|
||||
message.error(error instanceof Error ? error.message : '修改密码失败')
|
||||
} finally {
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
const DEFAULT_WORKER_SITE_URL = 'https://worker.khhao.com'
|
||||
|
||||
export const WORKER_SITE_ORIGIN = resolveWorkerSiteOrigin()
|
||||
|
||||
export function isWorkerSite() {
|
||||
const configuredHostname = new URL(WORKER_SITE_ORIGIN).hostname
|
||||
|
||||
return (
|
||||
window.location.hostname === configuredHostname ||
|
||||
(import.meta.env.DEV && window.location.hostname === 'worker.localhost')
|
||||
)
|
||||
}
|
||||
|
||||
function resolveWorkerSiteOrigin() {
|
||||
const configuredUrl = String(import.meta.env.VITE_WORKER_SITE_URL || '').trim()
|
||||
|
||||
try {
|
||||
return new URL(configuredUrl || DEFAULT_WORKER_SITE_URL).origin
|
||||
} catch {
|
||||
return DEFAULT_WORKER_SITE_URL
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
export function resolveLegacyWorkerPath(hash: string) {
|
||||
const value = hash.startsWith('#') ? hash.slice(1) : hash
|
||||
const queryIndex = value.indexOf('?')
|
||||
const pathname = queryIndex >= 0 ? value.slice(0, queryIndex) : value
|
||||
const search = queryIndex >= 0 ? value.slice(queryIndex) : ''
|
||||
|
||||
if (pathname === '/worker' || pathname === '/worker/' || pathname === '/worker/login') {
|
||||
return `/${search}`
|
||||
}
|
||||
if (pathname === '/worker/hall') return `/hall${search}`
|
||||
if (pathname === '/worker/orders') return `/orders${search}`
|
||||
if (pathname === '/worker/profile') return `/profile${search}`
|
||||
|
||||
return ''
|
||||
}
|
||||
Reference in New Issue
Block a user