feat(layout): 优化底部路由导航

This commit is contained in:
liuyonghe0111 2025-12-23 17:36:03 +08:00
parent c78e3ed5ff
commit a2c9f86df9
4 changed files with 24 additions and 44 deletions

View File

@ -5,7 +5,6 @@ import '../css/iconfont.css';
import '../css/iconfont-v2.css';
import './globals.css';
import { Providers } from '@/layout/Providers';
import ProgressBar from '@/layout/Providers/ProgressBar';
import Script from 'next/script';
const poppins = Poppins({
@ -46,7 +45,7 @@ export default async function RootLayout({
children: React.ReactNode;
}>) {
return (
<html lang="en">
<html lang="en-US">
<body
className={`${poppins.variable} ${oleoScriptSwashCaps.variable} ${NumDisplay.variable} antialiased`}
>

View File

@ -1,34 +1,6 @@
'use client';
import { useMemoizedFn } from 'ahooks';
import { useEffect, useState } from 'react';
export const useMedia = (config: Record<string, number>) => {
// 追踪客户端是否已挂载
const [mounted, setMounted] = useState(false);
const [response, setResponse] = useState<Record<keyof typeof config, boolean>>();
useEffect(() => {
setMounted(true);
const onResize = () => {
const newResponse = Object.fromEntries(
Object.entries(config).map(([key, value]) => {
if (window.innerWidth > value) {
return [key, true];
}
return [key, false];
})
) as Record<keyof typeof config, boolean>;
setResponse(newResponse);
};
window.addEventListener('resize', onResize);
onResize();
return () => window.removeEventListener('resize', onResize);
}, []);
if (!mounted) return undefined;
return response;
};
import { useState } from 'react';
/**
* hook, loading状态

View File

@ -3,9 +3,10 @@
import { usePathname } from 'next/navigation';
import Link from 'next/link';
import Image from 'next/image';
import { useRef } from 'react';
import { cn } from '@/lib/utils';
import { useMedia } from '@/hooks/tools';
import { useTranslations } from 'next-intl';
import { useSize } from 'ahooks';
export const items = [
{
@ -37,14 +38,18 @@ export const items = [
export default function BottomBar() {
const t = useTranslations('bottomBar');
const pathname = usePathname();
const response = useMedia({ hide: 500 });
const containerRef = useRef<HTMLDivElement>(null);
const size = useSize(containerRef);
if (!items.some((i) => i.path === pathname)) {
return null;
}
return (
<div className="h-20 border-outline-normal bg-[rgba(10,14,43,1)] z-100 flex border-t items-center justify-between">
<div
ref={containerRef}
className="h-20 border-outline-normal bg-[rgba(10,14,43,1)] z-100 flex border-t items-center justify-between"
>
{items.map((item) => {
const isSelected = pathname === item.path;
const label = t(item.labelKey as 'explore' | 'search' | 'chat' | 'me');
@ -63,7 +68,7 @@ export default function BottomBar() {
width={48}
height={48}
/>
{response?.hide && <span>{label}</span>}
{size?.width && size.width > 500 && <span>{label}</span>}
</Link>
);
})}

View File

@ -17,6 +17,7 @@ interface ConditionalLayoutProps {
children: React.ReactNode;
}
// 初始化聊天
const useInitChat = () => {
const { data } = useCurrentUser();
const connect = useStreamChatStore((state) => state.connect);
@ -31,24 +32,27 @@ const useInitChat = () => {
}, [data]);
};
export default function ConditionalLayout({ children }: ConditionalLayoutProps) {
// 路由切换时重置滚动位置
const useAutoScrollOnRouteChange = (ref: React.RefObject<HTMLDivElement | null>) => {
const pathname = usePathname();
const mainContentRef = useRef<HTMLDivElement>(null);
const prevPathnameRef = useRef<string>(pathname);
const response = useLayoutStore((s) => s.response);
// 初始化聊天
useInitChat();
// 路由切换时重置滚动位置
useEffect(() => {
if (prevPathnameRef.current !== pathname) {
if (mainContentRef.current) {
mainContentRef.current.scrollTop = 0;
if (ref.current) {
ref.current.scrollTop = 0;
}
prevPathnameRef.current = pathname;
}
}, [pathname]);
};
export default function ConditionalLayout({ children }: ConditionalLayoutProps) {
const mainContentRef = useRef<HTMLDivElement>(null);
const response = useLayoutStore((s) => s.response);
useInitChat();
useAutoScrollOnRouteChange(mainContentRef);
return (
<div className="flex h-screen bg-[url('/common-bg.png')] bg-[length:100%_30%] bg-top bg-no-repeat">