mirror of
https://github.com/Sagit-chu/flvx.git
synced 2026-10-05 17:46:37 +08:00
修复ui问题
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { Route, Routes } from "react-router-dom";
|
||||
import { Route, Routes, useNavigate } from "react-router-dom";
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
import IndexPage from "@/pages/index";
|
||||
@@ -58,17 +58,18 @@ const useH5Mode = () => {
|
||||
return isH5;
|
||||
};
|
||||
|
||||
// 简化的路由保护组件 - 使用浏览器重定向避免React循环
|
||||
// 简化的路由保护组件 - 使用 React Router 导航避免循环
|
||||
const ProtectedRoute = ({ children, useSimpleLayout = false }: { children: React.ReactNode, useSimpleLayout?: boolean }) => {
|
||||
const authenticated = isLoggedIn();
|
||||
const isH5 = useH5Mode();
|
||||
const navigate = useNavigate();
|
||||
|
||||
useEffect(() => {
|
||||
if (!authenticated) {
|
||||
// 使用浏览器原生重定向,避免React渲染循环
|
||||
window.location.replace('/');
|
||||
// 使用 React Router 导航,避免无限跳转
|
||||
navigate('/', { replace: true });
|
||||
}
|
||||
}, [authenticated]);
|
||||
}, [authenticated, navigate]);
|
||||
|
||||
if (!authenticated) {
|
||||
return (
|
||||
@@ -95,13 +96,14 @@ const ProtectedRoute = ({ children, useSimpleLayout = false }: { children: React
|
||||
// 登录页面路由组件 - 已登录则重定向到dashboard
|
||||
const LoginRoute = () => {
|
||||
const authenticated = isLoggedIn();
|
||||
const navigate = useNavigate();
|
||||
|
||||
useEffect(() => {
|
||||
if (authenticated) {
|
||||
// 使用浏览器原生重定向
|
||||
window.location.replace('/dashboard');
|
||||
// 使用 React Router 导航,避免无限跳转
|
||||
navigate('/dashboard', { replace: true });
|
||||
}
|
||||
}, [authenticated]);
|
||||
}, [authenticated, navigate]);
|
||||
|
||||
if (authenticated) {
|
||||
return (
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { useNavigate, useLocation } from 'react-router-dom';
|
||||
import { Button } from "@heroui/button";
|
||||
|
||||
import { Logo } from '@/components/icons';
|
||||
@@ -11,15 +11,27 @@ export default function H5SimpleLayout({
|
||||
children: React.ReactNode;
|
||||
}) {
|
||||
const navigate = useNavigate();
|
||||
const location = useLocation();
|
||||
|
||||
// 路由切换时回到顶部,避免上一页滚动位置保留
|
||||
React.useEffect(() => {
|
||||
try {
|
||||
window.scrollTo({ top: 0, left: 0, behavior: 'auto' });
|
||||
} catch (e) {
|
||||
window.scrollTo(0, 0);
|
||||
}
|
||||
document.body.scrollTop = 0;
|
||||
document.documentElement.scrollTop = 0;
|
||||
}, [location.pathname]);
|
||||
|
||||
const handleBack = () => {
|
||||
navigate('/profile');
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="flex flex-col h-screen bg-gray-100 dark:bg-black">
|
||||
<div className="flex flex-col min-h-screen bg-gray-100 dark:bg-black">
|
||||
{/* 顶部导航栏 */}
|
||||
<header className="bg-white dark:bg-black shadow-sm border-b border-gray-200 dark:border-gray-600 h-14 flex items-center justify-between px-4 relative z-10">
|
||||
<header className="bg-white dark:bg-black shadow-sm border-b border-gray-200 dark:border-gray-600 h-14 safe-top flex-shrink-0 flex items-center justify-between px-4 relative z-10">
|
||||
<div className="flex items-center gap-2">
|
||||
<Button
|
||||
isIconOnly
|
||||
@@ -40,7 +52,7 @@ export default function H5SimpleLayout({
|
||||
</header>
|
||||
|
||||
{/* 主内容区域 */}
|
||||
<main className="flex-1 overflow-y-auto bg-gray-100 dark:bg-black">
|
||||
<main className="flex-1 bg-gray-100 dark:bg-black pb-0">
|
||||
{children}
|
||||
</main>
|
||||
</div>
|
||||
|
||||
@@ -98,10 +98,21 @@ export default function H5Layout({
|
||||
!item.adminOnly || isAdmin
|
||||
);
|
||||
|
||||
// 路由切换时回到页面顶部,避免上一页的滚动位置遗留
|
||||
useEffect(() => {
|
||||
try {
|
||||
window.scrollTo({ top: 0, left: 0, behavior: 'auto' });
|
||||
} catch (e) {
|
||||
window.scrollTo(0, 0);
|
||||
}
|
||||
document.body.scrollTop = 0;
|
||||
document.documentElement.scrollTop = 0;
|
||||
}, [location.pathname]);
|
||||
|
||||
return (
|
||||
<div className="flex flex-col h-screen bg-gray-100 dark:bg-black">
|
||||
<div className="flex flex-col min-h-screen bg-gray-100 dark:bg-black">
|
||||
{/* 顶部导航栏 */}
|
||||
<header className="bg-white dark:bg-black shadow-sm border-b border-gray-200 dark:border-gray-600 h-14 flex items-center justify-between px-4 relative z-10">
|
||||
<header className="bg-white dark:bg-black shadow-sm border-b border-gray-200 dark:border-gray-600 h-14 safe-top flex-shrink-0 flex items-center justify-between px-4 relative z-10">
|
||||
<div className="flex items-center gap-2">
|
||||
<Logo size={20} />
|
||||
<h1 className="text-sm font-bold text-foreground">{siteConfig.name}</h1>
|
||||
@@ -112,12 +123,15 @@ export default function H5Layout({
|
||||
</header>
|
||||
|
||||
{/* 主内容区域 */}
|
||||
<main className="flex-1 overflow-y-auto bg-gray-100 dark:bg-black">
|
||||
<main className="flex-1 bg-gray-100 dark:bg-black">
|
||||
{children}
|
||||
</main>
|
||||
|
||||
{/* 用于给固定 Tabbar 腾出空间的占位元素 */}
|
||||
<div aria-hidden className="h-16 safe-bottom" />
|
||||
|
||||
{/* 底部Tabbar */}
|
||||
<nav className="bg-white dark:bg-black border-t border-gray-200 dark:border-gray-600 h-16 flex items-center justify-around px-2 relative z-10">
|
||||
<nav className="bg-white dark:bg-black border-t border-gray-200 dark:border-gray-600 h-16 safe-bottom flex-shrink-0 flex items-center justify-around px-2 fixed bottom-0 left-0 right-0 z-30">
|
||||
{filteredTabItems.map((item) => {
|
||||
const isActive = location.pathname === item.path;
|
||||
return (
|
||||
|
||||
@@ -1,34 +1,16 @@
|
||||
|
||||
import ReactDOM from "react-dom/client";
|
||||
import { BrowserRouter } from "react-router-dom";
|
||||
import { MemoryRouter } from "react-router-dom";
|
||||
|
||||
import App from "./App.tsx";
|
||||
import { Provider } from "./provider.tsx";
|
||||
import "@/styles/globals.css";
|
||||
|
||||
ReactDOM.createRoot(document.getElementById("root")!).render(
|
||||
<BrowserRouter>
|
||||
<MemoryRouter>
|
||||
<Provider>
|
||||
<App />
|
||||
</Provider>
|
||||
</BrowserRouter>
|
||||
</MemoryRouter>
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
import ReactDOM from "react-dom/client";
|
||||
import { HashRouter } from "react-router-dom";
|
||||
|
||||
import App from "./App.tsx";
|
||||
import { Provider } from "./provider.tsx";
|
||||
import "@/styles/globals.css";
|
||||
|
||||
ReactDOM.createRoot(document.getElementById("root")!).render(
|
||||
<HashRouter>
|
||||
<Provider>
|
||||
<App />
|
||||
</Provider>
|
||||
</HashRouter>
|
||||
);
|
||||
|
||||
*/
|
||||
@@ -1,4 +1,5 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { Button } from "@heroui/button";
|
||||
import { Card, CardBody, CardHeader } from "@heroui/card";
|
||||
import { Input } from "@heroui/input";
|
||||
@@ -121,6 +122,7 @@ const getInitialConfigs = (): Record<string, string> => {
|
||||
};
|
||||
|
||||
export default function ConfigPage() {
|
||||
const navigate = useNavigate();
|
||||
const initialConfigs = getInitialConfigs();
|
||||
const [configs, setConfigs] = useState<Record<string, string>>(initialConfigs);
|
||||
const [loading, setLoading] = useState(Object.keys(initialConfigs).length === 0); // 如果有缓存数据,不显示loading
|
||||
@@ -132,10 +134,10 @@ export default function ConfigPage() {
|
||||
useEffect(() => {
|
||||
if (!isAdmin()) {
|
||||
toast.error('权限不足,只有管理员可以访问此页面');
|
||||
window.location.href = '/dashboard';
|
||||
navigate('/dashboard', { replace: true });
|
||||
return;
|
||||
}
|
||||
}, []);
|
||||
}, [navigate]);
|
||||
|
||||
// 加载配置数据(优先从缓存)
|
||||
const loadConfigs = async (currentConfigs?: Record<string, string>) => {
|
||||
|
||||
@@ -95,7 +95,7 @@ export default function ProfilePage() {
|
||||
// 退出登录
|
||||
const handleLogout = () => {
|
||||
safeLogout();
|
||||
window.location.href = '/';
|
||||
navigate('/', { replace: true });
|
||||
};
|
||||
|
||||
// 密码表单验证
|
||||
|
||||
@@ -119,7 +119,7 @@ export const SettingsPage = () => {
|
||||
loadPanelAddresses();
|
||||
}
|
||||
} catch (error) {
|
||||
toast.error('添加失败');
|
||||
toast.error('添加失败' + error);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -7,6 +7,16 @@ html, body {
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
/* 现代浏览器使用 100dvh,避免地址栏收起/展开导致的布局跳动 */
|
||||
@supports (height: 100dvh) {
|
||||
.h-screen {
|
||||
height: 100dvh;
|
||||
}
|
||||
.min-h-screen {
|
||||
min-height: 100dvh;
|
||||
}
|
||||
}
|
||||
|
||||
/* 解决移动端100vh问题 */
|
||||
@supports (-webkit-touch-callout: none) {
|
||||
.h-screen {
|
||||
@@ -30,6 +40,21 @@ html, body {
|
||||
}
|
||||
|
||||
|
||||
/* 安全区域变量与工具类(适配刘海/底部手势条) */
|
||||
:root {
|
||||
--safe-area-top: env(safe-area-inset-top, 0px);
|
||||
--safe-area-bottom: env(safe-area-inset-bottom, 0px);
|
||||
}
|
||||
|
||||
.safe-top {
|
||||
padding-top: var(--safe-area-top);
|
||||
}
|
||||
|
||||
.safe-bottom {
|
||||
padding-bottom: var(--safe-area-bottom);
|
||||
}
|
||||
|
||||
|
||||
/* 验证码弹层动画 */
|
||||
.captcha-modal-enter {
|
||||
animation: captchaModalIn 0.3s ease-out forwards;
|
||||
|
||||
Reference in New Issue
Block a user