feat(frontend): wire pages to shadcn bridge and modular helpers

This commit is contained in:
Sagit
2026-02-19 05:15:26 +00:00
parent 12c50df6a7
commit 30c96a280d
27 changed files with 1077 additions and 1971 deletions
+15 -33
View File
@@ -1,12 +1,12 @@
import React, { useState, useEffect } from "react";
import { useNavigate, useLocation } from "react-router-dom";
import { Button } from "@heroui/button";
import { Button } from "@/shadcn-bridge/heroui/button";
import {
Dropdown,
DropdownTrigger,
DropdownMenu,
DropdownItem,
} from "@heroui/dropdown";
} from "@/shadcn-bridge/heroui/dropdown";
import {
Modal,
ModalContent,
@@ -14,14 +14,16 @@ import {
ModalBody,
ModalFooter,
useDisclosure,
} from "@heroui/modal";
import { Input } from "@heroui/input";
} from "@/shadcn-bridge/heroui/modal";
import { Input } from "@/shadcn-bridge/heroui/input";
import { toast } from "react-hot-toast";
import { Logo } from "@/components/icons";
import { updatePassword } from "@/api";
import { safeLogout } from "@/utils/logout";
import { siteConfig } from "@/config/site";
import { useMobileBreakpoint } from "@/hooks/useMobileBreakpoint";
import { getAdminFlag, getSessionName } from "@/utils/session";
interface MenuItem {
path: string;
@@ -46,7 +48,6 @@ export default function AdminLayout({
const location = useLocation();
const { isOpen, onOpen, onOpenChange } = useDisclosure();
const [isMobile, setIsMobile] = useState(false);
const [mobileMenuVisible, setMobileMenuVisible] = useState(false);
const [username, setUsername] = useState("");
const [isAdmin, setIsAdmin] = useState(false);
@@ -57,6 +58,7 @@ export default function AdminLayout({
newPassword: "",
confirmPassword: "",
});
const isMobile = useMobileBreakpoint();
// 菜单项配置
const menuItems: MenuItem[] = [
@@ -170,41 +172,21 @@ export default function AdminLayout({
},
];
// 检查移动端
const checkMobile = () => {
setIsMobile(window.innerWidth <= 768);
if (window.innerWidth > 768) {
setMobileMenuVisible(false);
}
};
useEffect(() => {
// 获取用户信息
const name = localStorage.getItem("name") || "Admin";
// 兼容处理:如果没有admin字段,根据role_id判断(0为管理员)
let adminFlag = localStorage.getItem("admin") === "true";
if (localStorage.getItem("admin") === null) {
const roleId = parseInt(localStorage.getItem("role_id") || "1", 10);
adminFlag = roleId === 0;
// 补充设置admin字段,避免下次再次判断
localStorage.setItem("admin", adminFlag.toString());
}
const name = getSessionName() || "Admin";
const adminFlag = getAdminFlag();
setUsername(name);
setIsAdmin(adminFlag);
// 响应式检查
checkMobile();
window.addEventListener("resize", checkMobile);
return () => {
window.removeEventListener("resize", checkMobile);
};
}, []);
useEffect(() => {
if (!isMobile) {
setMobileMenuVisible(false);
}
}, [isMobile]);
// 退出登录
const handleLogout = () => {
safeLogout();
+4 -13
View File
@@ -1,9 +1,10 @@
import React from "react";
import { useNavigate, useLocation } from "react-router-dom";
import { Button } from "@heroui/button";
import { useNavigate } from "react-router-dom";
import { Button } from "@/shadcn-bridge/heroui/button";
import { Logo } from "@/components/icons";
import { siteConfig } from "@/config/site";
import { useScrollTopOnPathChange } from "@/hooks/useScrollTopOnPathChange";
export default function H5SimpleLayout({
children,
@@ -11,18 +12,8 @@ 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 {
window.scrollTo(0, 0);
}
document.body.scrollTop = 0;
document.documentElement.scrollTop = 0;
}, [location.pathname]);
useScrollTopOnPathChange();
const handleBack = () => {
navigate("/profile");
+5 -23
View File
@@ -3,6 +3,8 @@ import { useNavigate, useLocation } from "react-router-dom";
import { Logo } from "@/components/icons";
import { siteConfig } from "@/config/site";
import { getAdminFlag } from "@/utils/session";
import { useScrollTopOnPathChange } from "@/hooks/useScrollTopOnPathChange";
interface TabItem {
path: string;
@@ -16,6 +18,8 @@ export default function H5Layout({ children }: { children: React.ReactNode }) {
const location = useLocation();
const [isAdmin, setIsAdmin] = useState(false);
useScrollTopOnPathChange();
// Tabbar配置
const tabItems: TabItem[] = [
{
@@ -80,18 +84,7 @@ export default function H5Layout({ children }: { children: React.ReactNode }) {
];
useEffect(() => {
// 兼容处理:如果没有admin字段,根据role_id判断(0为管理员)
let adminFlag = localStorage.getItem("admin") === "true";
if (localStorage.getItem("admin") === null) {
const roleId = parseInt(localStorage.getItem("role_id") || "1", 10);
adminFlag = roleId === 0;
// 补充设置admin字段,避免下次再次判断
localStorage.setItem("admin", adminFlag.toString());
}
setIsAdmin(adminFlag);
setIsAdmin(getAdminFlag());
}, []);
// Tab点击处理
@@ -104,17 +97,6 @@ export default function H5Layout({ children }: { children: React.ReactNode }) {
(item) => !item.adminOnly || isAdmin,
);
// 路由切换时回到页面顶部,避免上一页的滚动位置遗留
useEffect(() => {
try {
window.scrollTo({ top: 0, left: 0, behavior: "auto" });
} catch {
window.scrollTo(0, 0);
}
document.body.scrollTop = 0;
document.documentElement.scrollTop = 0;
}, [location.pathname]);
return (
<div className="flex flex-col min-h-screen bg-gray-100 dark:bg-black">
{/* 顶部导航栏 */}