mirror of
https://github.com/SECTL/SecScore.git
synced 2026-07-19 19:04:23 +08:00
feat: 新增主页沉浸模式开关
This commit is contained in:
+43
-10
@@ -14,6 +14,7 @@ function MainContent(): React.JSX.Element {
|
|||||||
const { currentTheme } = useTheme()
|
const { currentTheme } = useTheme()
|
||||||
const [messageApi, contextHolder] = message.useMessage()
|
const [messageApi, contextHolder] = message.useMessage()
|
||||||
const { isIosDevice, isAndroidDevice, defaultPortraitMode } = useMemo(getMobileDeviceInfo, [])
|
const { isIosDevice, isAndroidDevice, defaultPortraitMode } = useMemo(getMobileDeviceInfo, [])
|
||||||
|
const [immersiveMode, setImmersiveMode] = useState(false)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const api = (window as any).api
|
const api = (window as any).api
|
||||||
@@ -27,6 +28,11 @@ function MainContent(): React.JSX.Element {
|
|||||||
const currentPath = location.pathname === "/" ? "/home" : location.pathname
|
const currentPath = location.pathname === "/" ? "/home" : location.pathname
|
||||||
const targetPath = route === "/" ? "/home" : route
|
const targetPath = route === "/" ? "/home" : route
|
||||||
|
|
||||||
|
if (immersiveMode && !targetPath.startsWith("/home")) {
|
||||||
|
navigate("/", { replace: true })
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if (currentPath !== targetPath) {
|
if (currentPath !== targetPath) {
|
||||||
navigate(route)
|
navigate(route)
|
||||||
}
|
}
|
||||||
@@ -44,7 +50,7 @@ function MainContent(): React.JSX.Element {
|
|||||||
disposed = true
|
disposed = true
|
||||||
if (unlisten) unlisten()
|
if (unlisten) unlisten()
|
||||||
}
|
}
|
||||||
}, [navigate, location.pathname])
|
}, [navigate, location.pathname, immersiveMode])
|
||||||
|
|
||||||
const [wizardVisible, setWizardVisible] = useState(false)
|
const [wizardVisible, setWizardVisible] = useState(false)
|
||||||
const [permission, setPermission] = useState<"admin" | "points" | "view">("view")
|
const [permission, setPermission] = useState<"admin" | "points" | "view">("view")
|
||||||
@@ -302,6 +308,7 @@ function MainContent(): React.JSX.Element {
|
|||||||
|
|
||||||
const onMenuChange = (v: string) => {
|
const onMenuChange = (v: string) => {
|
||||||
const key = String(v)
|
const key = String(v)
|
||||||
|
if (immersiveMode && key !== "home") return
|
||||||
if (key === "home") navigate("/")
|
if (key === "home") navigate("/")
|
||||||
if (key === "students") navigate("/students")
|
if (key === "students") navigate("/students")
|
||||||
if (key === "score") navigate("/score")
|
if (key === "score") navigate("/score")
|
||||||
@@ -315,6 +322,7 @@ function MainContent(): React.JSX.Element {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const toggleSidebar = () => {
|
const toggleSidebar = () => {
|
||||||
|
if (immersiveMode) return
|
||||||
if (isPortraitMode && sidebarCollapsed) {
|
if (isPortraitMode && sidebarCollapsed) {
|
||||||
setFloatingSidebarExpanded((prev) => !prev)
|
setFloatingSidebarExpanded((prev) => !prev)
|
||||||
return
|
return
|
||||||
@@ -322,6 +330,26 @@ function MainContent(): React.JSX.Element {
|
|||||||
setSidebarCollapsed((prev) => !prev)
|
setSidebarCollapsed((prev) => !prev)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!immersiveMode) return
|
||||||
|
if (location.pathname !== "/" && !location.pathname.startsWith("/home")) {
|
||||||
|
navigate("/", { replace: true })
|
||||||
|
}
|
||||||
|
}, [immersiveMode, location.pathname, navigate])
|
||||||
|
|
||||||
|
const toggleImmersiveMode = () => {
|
||||||
|
setImmersiveMode((prev) => {
|
||||||
|
const next = !prev
|
||||||
|
if (next) {
|
||||||
|
setFloatingSidebarExpanded(false)
|
||||||
|
if (location.pathname !== "/" && !location.pathname.startsWith("/home")) {
|
||||||
|
navigate("/", { replace: true })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return next
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
const isDark = currentTheme?.mode === "dark"
|
const isDark = currentTheme?.mode === "dark"
|
||||||
const brandColor = currentTheme?.config?.tdesign?.brandColor || "#0052D9"
|
const brandColor = currentTheme?.config?.tdesign?.brandColor || "#0052D9"
|
||||||
|
|
||||||
@@ -338,15 +366,17 @@ function MainContent(): React.JSX.Element {
|
|||||||
>
|
>
|
||||||
{contextHolder}
|
{contextHolder}
|
||||||
<Layout style={{ height: "100%", flexDirection: "row", overflow: "hidden" }}>
|
<Layout style={{ height: "100%", flexDirection: "row", overflow: "hidden" }}>
|
||||||
<Sidebar
|
{!immersiveMode && (
|
||||||
activeMenu={activeMenu}
|
<Sidebar
|
||||||
permission={permission}
|
activeMenu={activeMenu}
|
||||||
onMenuChange={onMenuChange}
|
permission={permission}
|
||||||
collapsed={sidebarCollapsed}
|
onMenuChange={onMenuChange}
|
||||||
floatingExpand={isPortraitMode}
|
collapsed={sidebarCollapsed}
|
||||||
floatingExpanded={floatingSidebarExpanded}
|
floatingExpand={isPortraitMode}
|
||||||
onFloatingExpandedChange={setFloatingSidebarExpanded}
|
floatingExpanded={floatingSidebarExpanded}
|
||||||
/>
|
onFloatingExpandedChange={setFloatingSidebarExpanded}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
<ContentArea
|
<ContentArea
|
||||||
permission={permission}
|
permission={permission}
|
||||||
hasAnyPassword={hasAnyPassword}
|
hasAnyPassword={hasAnyPassword}
|
||||||
@@ -358,6 +388,9 @@ function MainContent(): React.JSX.Element {
|
|||||||
floatingExpand={isPortraitMode}
|
floatingExpand={isPortraitMode}
|
||||||
floatingExpanded={floatingSidebarExpanded}
|
floatingExpanded={floatingSidebarExpanded}
|
||||||
onToggleSidebar={toggleSidebar}
|
onToggleSidebar={toggleSidebar}
|
||||||
|
immersiveMode={immersiveMode}
|
||||||
|
isHomePage={activeMenu === "home"}
|
||||||
|
onToggleImmersiveMode={toggleImmersiveMode}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<OOBE visible={wizardVisible} onComplete={() => setWizardVisible(false)} />
|
<OOBE visible={wizardVisible} onComplete={() => setWizardVisible(false)} />
|
||||||
|
|||||||
@@ -1,6 +1,11 @@
|
|||||||
import React, { Suspense, lazy, useEffect } from "react"
|
import React, { Suspense, lazy, useEffect } from "react"
|
||||||
import { Layout, Space, Button, Tag, Spin } from "antd"
|
import { Layout, Space, Button, Tag, Spin } from "antd"
|
||||||
import { MenuFoldOutlined, MenuUnfoldOutlined } from "@ant-design/icons"
|
import {
|
||||||
|
MenuFoldOutlined,
|
||||||
|
MenuUnfoldOutlined,
|
||||||
|
FullscreenOutlined,
|
||||||
|
FullscreenExitOutlined,
|
||||||
|
} from "@ant-design/icons"
|
||||||
import { Routes, Route, Navigate } from "react-router-dom"
|
import { Routes, Route, Navigate } from "react-router-dom"
|
||||||
import { useTranslation } from "react-i18next"
|
import { useTranslation } from "react-i18next"
|
||||||
import { WindowControls } from "./WindowControls"
|
import { WindowControls } from "./WindowControls"
|
||||||
@@ -58,6 +63,9 @@ interface ContentAreaProps {
|
|||||||
floatingExpand: boolean
|
floatingExpand: boolean
|
||||||
floatingExpanded: boolean
|
floatingExpanded: boolean
|
||||||
onToggleSidebar: () => void
|
onToggleSidebar: () => void
|
||||||
|
immersiveMode: boolean
|
||||||
|
isHomePage: boolean
|
||||||
|
onToggleImmersiveMode: () => void
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ContentArea({
|
export function ContentArea({
|
||||||
@@ -71,6 +79,9 @@ export function ContentArea({
|
|||||||
floatingExpand,
|
floatingExpand,
|
||||||
floatingExpanded,
|
floatingExpanded,
|
||||||
onToggleSidebar,
|
onToggleSidebar,
|
||||||
|
immersiveMode,
|
||||||
|
isHomePage,
|
||||||
|
onToggleImmersiveMode,
|
||||||
}: ContentAreaProps): React.JSX.Element {
|
}: ContentAreaProps): React.JSX.Element {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
|
|
||||||
@@ -144,26 +155,28 @@ export function ContentArea({
|
|||||||
} as React.CSSProperties
|
} as React.CSSProperties
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<Button
|
{!immersiveMode && (
|
||||||
type="text"
|
<Button
|
||||||
size="small"
|
type="text"
|
||||||
onClick={onToggleSidebar}
|
size="small"
|
||||||
icon={
|
onClick={onToggleSidebar}
|
||||||
floatingExpand && sidebarCollapsed ? (
|
icon={
|
||||||
floatingExpanded ? (
|
floatingExpand && sidebarCollapsed ? (
|
||||||
<MenuFoldOutlined />
|
floatingExpanded ? (
|
||||||
) : (
|
<MenuFoldOutlined />
|
||||||
|
) : (
|
||||||
|
<MenuUnfoldOutlined />
|
||||||
|
)
|
||||||
|
) : sidebarCollapsed ? (
|
||||||
<MenuUnfoldOutlined />
|
<MenuUnfoldOutlined />
|
||||||
|
) : (
|
||||||
|
<MenuFoldOutlined />
|
||||||
)
|
)
|
||||||
) : sidebarCollapsed ? (
|
}
|
||||||
<MenuUnfoldOutlined />
|
title={sidebarCollapsed ? "展开导航栏" : "收起导航栏"}
|
||||||
) : (
|
style={{ width: "32px", height: "32px" }}
|
||||||
<MenuFoldOutlined />
|
/>
|
||||||
)
|
)}
|
||||||
}
|
|
||||||
title={sidebarCollapsed ? "展开导航栏" : "收起导航栏"}
|
|
||||||
style={{ width: "32px", height: "32px" }}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
data-tauri-drag-region
|
data-tauri-drag-region
|
||||||
@@ -186,6 +199,15 @@ export function ContentArea({
|
|||||||
}
|
}
|
||||||
>
|
>
|
||||||
<Space size="small">
|
<Space size="small">
|
||||||
|
{(immersiveMode || isHomePage) && (
|
||||||
|
<Button
|
||||||
|
size="small"
|
||||||
|
type={immersiveMode ? "primary" : "default"}
|
||||||
|
icon={immersiveMode ? <FullscreenExitOutlined /> : <FullscreenOutlined />}
|
||||||
|
onClick={onToggleImmersiveMode}
|
||||||
|
title={immersiveMode ? "退出沉浸模式" : "进入沉浸模式"}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
{permissionTag}
|
{permissionTag}
|
||||||
{hasAnyPassword && (
|
{hasAnyPassword && (
|
||||||
<>
|
<>
|
||||||
|
|||||||
Reference in New Issue
Block a user