forked from 77media/video-flow
布局 H5适配
This commit is contained in:
parent
cb1a760615
commit
6de525d349
@ -1,8 +1,8 @@
|
|||||||
|
|
||||||
|
|
||||||
#NEXT_PUBLIC_JAVA_URL = https://77.app.java.auth.qikongjian.com
|
NEXT_PUBLIC_JAVA_URL = https://77.app.java.auth.qikongjian.com
|
||||||
#NEXT_PUBLIC_BASE_URL = https://77.smartvideo.py.qikongjian.com
|
NEXT_PUBLIC_BASE_URL = https://77.smartvideo.py.qikongjian.com
|
||||||
NEXT_PUBLIC_JAVA_URL = https://test.java.movieflow.ai
|
# NEXT_PUBLIC_JAVA_URL = https://test.java.movieflow.ai
|
||||||
NEXT_PUBLIC_BASE_URL = https://test.video.movieflow.ai
|
# NEXT_PUBLIC_BASE_URL = https://test.video.movieflow.ai
|
||||||
# 失败率
|
# 失败率
|
||||||
NEXT_PUBLIC_ERROR_CONFIG = 0.2
|
NEXT_PUBLIC_ERROR_CONFIG = 0.2
|
||||||
@ -3,6 +3,7 @@
|
|||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { Sidebar } from './sidebar';
|
import { Sidebar } from './sidebar';
|
||||||
import { TopBar } from './top-bar';
|
import { TopBar } from './top-bar';
|
||||||
|
import { useDeviceType } from '@/hooks/useDeviceType';
|
||||||
|
|
||||||
interface DashboardLayoutProps {
|
interface DashboardLayoutProps {
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
@ -10,15 +11,38 @@ interface DashboardLayoutProps {
|
|||||||
|
|
||||||
export function DashboardLayout({ children }: DashboardLayoutProps) {
|
export function DashboardLayout({ children }: DashboardLayoutProps) {
|
||||||
const [sidebarCollapsed, setSidebarCollapsed] = useState(true); // 默认收起状态
|
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 (
|
return (
|
||||||
<div className=" min-h-screen bg-background">
|
<div className=" min-h-screen bg-background">
|
||||||
<TopBar collapsed={sidebarCollapsed} />
|
<TopBar collapsed={sidebarCollapsed} isDesktop={isDesktop} />
|
||||||
<Sidebar collapsed={sidebarCollapsed} onToggle={setSidebarCollapsed} />
|
{isDesktop && <Sidebar collapsed={sidebarCollapsed} onToggle={setSidebarCollapsed} />}
|
||||||
<div className="h-[calc(100vh-4rem)] top-[4rem] fixed right-0 bottom-0 z-[999]" style={{
|
<div
|
||||||
left: sidebarCollapsed ? '4rem' : '16rem',
|
className="h-[calc(100vh-4rem)] top-[4rem] fixed right-0 bottom-0 z-[999] px-4"
|
||||||
width: sidebarCollapsed ? 'calc(100vw - 4rem)' : 'calc(100vw - 16rem)'
|
style={getLayoutStyles()}>
|
||||||
}}>
|
|
||||||
{children}
|
{children}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -35,7 +35,7 @@ interface User {
|
|||||||
plan_name?: string;
|
plan_name?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function TopBar({ collapsed }: { collapsed: boolean }) {
|
export function TopBar({ collapsed, isDesktop=true }: { collapsed: boolean, isDesktop?: boolean }) {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const [isOpen, setIsOpen] = React.useState(false);
|
const [isOpen, setIsOpen] = React.useState(false);
|
||||||
const menuRef = useRef<HTMLDivElement>(null);
|
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]"
|
className="fixed right-0 top-0 h-16 header z-[999]"
|
||||||
style={{
|
style={{
|
||||||
isolation: "isolate",
|
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 space-x-4">
|
||||||
<div
|
<div
|
||||||
className={`flex items-center cursor-pointer space-x-1 link-logo roll event-on`}
|
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",
|
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"}
|
{currentUser.username ? currentUser.username.charAt(0) : "MF"}
|
||||||
</div>
|
</div>
|
||||||
</Button>
|
</Button>
|
||||||
|
|||||||
64
hooks/useDeviceType.ts
Normal file
64
hooks/useDeviceType.ts
Normal 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
|
||||||
|
};
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user