feat: 实现自适应路由切换,根据 User-Agent 及屏幕大小自动导航 PC/Mobile 视图
This commit is contained in:
@@ -5,7 +5,7 @@ import { useSessionStore } from '@/stores/session'
|
|||||||
import { getAccessToken, getLoginPath } from '@/utils/authStorage'
|
import { getAccessToken, getLoginPath } from '@/utils/authStorage'
|
||||||
import { accountRoutes } from './accountRoutes'
|
import { accountRoutes } from './accountRoutes'
|
||||||
import { adminRoutes } from './adminRoutes'
|
import { adminRoutes } from './adminRoutes'
|
||||||
import { isMobileHost, toMobilePath } from './mobileHost'
|
import { isMobileHost, isMobileDevice, getMobilePath, getPcPath } from './mobileHost'
|
||||||
import { mobileRoutes } from './mobileRoutes'
|
import { mobileRoutes } from './mobileRoutes'
|
||||||
import { publicRoutes } from './publicRoutes'
|
import { publicRoutes } from './publicRoutes'
|
||||||
import { sellerRoutes } from './sellerRoutes'
|
import { sellerRoutes } from './sellerRoutes'
|
||||||
@@ -22,8 +22,18 @@ const router = createRouter({
|
|||||||
})
|
})
|
||||||
|
|
||||||
router.beforeEach(async (to) => {
|
router.beforeEach(async (to) => {
|
||||||
if (isMobileHost() && to.path !== toMobilePath(to.path)) {
|
const isMobile = isMobileHost() || isMobileDevice()
|
||||||
return { path: toMobilePath(to.path), query: to.query, hash: to.hash }
|
|
||||||
|
if (isMobile) {
|
||||||
|
const targetPath = getMobilePath(to.path)
|
||||||
|
if (to.path !== targetPath) {
|
||||||
|
return { path: targetPath, query: to.query, hash: to.hash }
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const targetPath = getPcPath(to.path)
|
||||||
|
if (to.path !== targetPath) {
|
||||||
|
return { path: targetPath, query: to.query, hash: to.hash }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (to.meta.requiresAuth) {
|
if (to.meta.requiresAuth) {
|
||||||
|
|||||||
@@ -2,12 +2,72 @@ export function isMobileHost(hostname = window.location.hostname) {
|
|||||||
return hostname === "m.localhost" || hostname.startsWith("m.");
|
return hostname === "m.localhost" || hostname.startsWith("m.");
|
||||||
}
|
}
|
||||||
|
|
||||||
export function toMobilePath(path: string) {
|
export function isMobileDevice() {
|
||||||
if (path === "/") {
|
if (typeof window === "undefined" || !window.navigator) return false;
|
||||||
|
const ua = window.navigator.userAgent;
|
||||||
|
const isMobileUA = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(ua);
|
||||||
|
const isSmallScreen = window.innerWidth < 768;
|
||||||
|
return isMobileUA || isSmallScreen;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getMobilePath(path: string): string {
|
||||||
|
if (path === "/" || path === "") {
|
||||||
return "/m";
|
return "/m";
|
||||||
}
|
}
|
||||||
if (path === "/m" || path.startsWith("/m/") || path.startsWith("/admin")) {
|
if (path.startsWith("/m") || path.startsWith("/admin")) {
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (path === "/listings" || path.startsWith("/listings/")) {
|
||||||
|
return `/m${path}`;
|
||||||
|
}
|
||||||
|
if (path === "/orders" || path.startsWith("/orders/")) {
|
||||||
|
return `/m${path}`;
|
||||||
|
}
|
||||||
|
if (path === "/realname") return "/m/realname";
|
||||||
|
if (path === "/login") return "/m/login";
|
||||||
|
if (path === "/register") return "/m/register";
|
||||||
|
|
||||||
|
if (path === "/seller/listings/create") {
|
||||||
|
return "/m/seller/listings/create";
|
||||||
|
}
|
||||||
|
|
||||||
|
// PC-only views that don't have mobile counterparts go to mobile profile as fallback
|
||||||
|
if (path === "/wallet" || path === "/notifications" || path.startsWith("/seller")) {
|
||||||
|
return "/m/profile";
|
||||||
|
}
|
||||||
|
|
||||||
return `/m${path}`;
|
return `/m${path}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getPcPath(path: string): string {
|
||||||
|
if (!path.startsWith("/m") || path.startsWith("/admin")) {
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (path === "/m" || path === "/m/") {
|
||||||
|
return "/";
|
||||||
|
}
|
||||||
|
|
||||||
|
const subPath = path.substring(2);
|
||||||
|
|
||||||
|
if (subPath === "/listings" || subPath.startsWith("/listings/")) {
|
||||||
|
return subPath;
|
||||||
|
}
|
||||||
|
if (subPath === "/orders" || subPath.startsWith("/orders/")) {
|
||||||
|
return subPath;
|
||||||
|
}
|
||||||
|
if (subPath === "/login") return "/login";
|
||||||
|
if (subPath === "/register") return "/login"; // PC uses /login for both auth actions
|
||||||
|
if (subPath === "/realname") return "/realname";
|
||||||
|
if (subPath === "/seller/listings/create") return "/seller/listings/create";
|
||||||
|
|
||||||
|
if (subPath === "/messages") return "/";
|
||||||
|
if (subPath === "/profile") return "/wallet";
|
||||||
|
|
||||||
|
return subPath || "/";
|
||||||
|
}
|
||||||
|
|
||||||
|
export function toMobilePath(path: string) {
|
||||||
|
return getMobilePath(path);
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user