布局 H5适配

This commit is contained in:
北枳 2025-09-06 22:58:54 +08:00
parent cb1a760615
commit 6de525d349
4 changed files with 104 additions and 14 deletions

View File

@ -1,8 +1,8 @@
#NEXT_PUBLIC_JAVA_URL = https://77.app.java.auth.qikongjian.com
#NEXT_PUBLIC_BASE_URL = https://77.smartvideo.py.qikongjian.com
NEXT_PUBLIC_JAVA_URL = https://test.java.movieflow.ai
NEXT_PUBLIC_BASE_URL = https://test.video.movieflow.ai
NEXT_PUBLIC_JAVA_URL = https://77.app.java.auth.qikongjian.com
NEXT_PUBLIC_BASE_URL = https://77.smartvideo.py.qikongjian.com
# NEXT_PUBLIC_JAVA_URL = https://test.java.movieflow.ai
# NEXT_PUBLIC_BASE_URL = https://test.video.movieflow.ai
# 失败率
NEXT_PUBLIC_ERROR_CONFIG = 0.2

View File

@ -3,6 +3,7 @@
import { useState } from 'react';
import { Sidebar } from './sidebar';
import { TopBar } from './top-bar';
import { useDeviceType } from '@/hooks/useDeviceType';
interface DashboardLayoutProps {
children: React.ReactNode;
@ -10,15 +11,38 @@ interface DashboardLayoutProps {
export function DashboardLayout({ children }: DashboardLayoutProps) {
const [sidebarCollapsed, setSidebarCollapsed] = useState(true); // 默认收起状态
const { deviceType, isMobile, isTablet, isDesktop } = useDeviceType();
// 根据设备类型设置布局样式
const getLayoutStyles = () => {
if (isMobile) {
return {
left: '0',
width: '100vw'
};
}
if (isTablet) {
return {
left: sidebarCollapsed ? '3rem' : '12rem',
width: sidebarCollapsed ? 'calc(100vw - 3rem)' : 'calc(100vw - 12rem)'
};
}
// 桌面端
return {
left: sidebarCollapsed ? '4rem' : '16rem',
width: sidebarCollapsed ? 'calc(100vw - 4rem)' : 'calc(100vw - 16rem)'
};
};
return (
<div className=" min-h-screen bg-background">
<TopBar collapsed={sidebarCollapsed} />
<Sidebar collapsed={sidebarCollapsed} onToggle={setSidebarCollapsed} />
<div className="h-[calc(100vh-4rem)] top-[4rem] fixed right-0 bottom-0 z-[999]" style={{
left: sidebarCollapsed ? '4rem' : '16rem',
width: sidebarCollapsed ? 'calc(100vw - 4rem)' : 'calc(100vw - 16rem)'
}}>
<TopBar collapsed={sidebarCollapsed} isDesktop={isDesktop} />
{isDesktop && <Sidebar collapsed={sidebarCollapsed} onToggle={setSidebarCollapsed} />}
<div
className="h-[calc(100vh-4rem)] top-[4rem] fixed right-0 bottom-0 z-[999] px-4"
style={getLayoutStyles()}>
{children}
</div>
</div>

View File

@ -35,7 +35,7 @@ interface User {
plan_name?: string;
}
export function TopBar({ collapsed }: { collapsed: boolean }) {
export function TopBar({ collapsed, isDesktop=true }: { collapsed: boolean, isDesktop?: boolean }) {
const router = useRouter();
const [isOpen, setIsOpen] = React.useState(false);
const menuRef = useRef<HTMLDivElement>(null);
@ -169,10 +169,10 @@ export function TopBar({ collapsed }: { collapsed: boolean }) {
className="fixed right-0 top-0 h-16 header z-[999]"
style={{
isolation: "isolate",
left: pathname === "/" ? "0" : (collapsed ? "2.5rem" : "16rem")
left: (pathname === "/" || !isDesktop) ? "0" : (collapsed ? "2.5rem" : "16rem")
}}
>
<div className="h-full flex items-center justify-between pr-6 pl-4">
<div className="h-full flex items-center justify-between px-4">
<div className="flex items-center space-x-4">
<div
className={`flex items-center cursor-pointer space-x-1 link-logo roll event-on`}
@ -273,7 +273,9 @@ export function TopBar({ collapsed }: { collapsed: boolean }) {
padding: "unset !important",
}}
>
<div className="h-10 w-10 rounded-full bg-[#C73BFF] flex items-center justify-center text-white font-semibold">
<div
className={`${isDesktop ? "h-10 w-10" : "h-8 w-8"} rounded-full bg-[#C73BFF] flex items-center justify-center text-white font-semibold`}
>
{currentUser.username ? currentUser.username.charAt(0) : "MF"}
</div>
</Button>

64
hooks/useDeviceType.ts Normal file
View File

@ -0,0 +1,64 @@
import { useState, useEffect } from 'react';
// 定义设备类型枚举
export enum DeviceType {
MOBILE = 'mobile', // 手机
TABLET = 'tablet', // 平板
DESKTOP = 'desktop' // 桌面端
}
// 定义屏幕断点
const BREAKPOINTS = {
MOBILE: 480, // 0-480px 为手机
TABLET: 1024, // 481-1024px 为平板
DESKTOP: 1025 // 1025px 及以上为桌面端
};
export function useDeviceType() {
const [deviceType, setDeviceType] = useState<DeviceType>(DeviceType.DESKTOP);
const [windowSize, setWindowSize] = useState({
width: typeof window !== 'undefined' ? window.innerWidth : 0,
height: typeof window !== 'undefined' ? window.innerHeight : 0
});
useEffect(() => {
/**
*
*/
const getDeviceType = (width: number): DeviceType => {
if (width <= BREAKPOINTS.MOBILE) return DeviceType.MOBILE;
if (width <= BREAKPOINTS.TABLET) return DeviceType.TABLET;
return DeviceType.DESKTOP;
};
/**
*
*/
const handleResize = () => {
const width = window.innerWidth;
const height = window.innerHeight;
setWindowSize({ width, height });
setDeviceType(getDeviceType(width));
};
// 初始化设备类型
handleResize();
// 添加窗口大小变化监听
window.addEventListener('resize', handleResize);
// 清理监听器
return () => {
window.removeEventListener('resize', handleResize);
};
}, []);
return {
deviceType,
windowSize,
isMobile: deviceType === DeviceType.MOBILE,
isTablet: deviceType === DeviceType.TABLET,
isDesktop: deviceType === DeviceType.DESKTOP
};
}