11import style from "../../../styles/panels/LiveScreenPanel.module.less" ;
22
3+ import { DownOutlined , UpOutlined } from "@ant-design/icons" ;
34import { memo , useCallback , useEffect , useRef , useState } from "react" ;
4- import { Spin , message } from "antd" ;
5+ import { Button , Spin , Tooltip , message } from "antd" ;
56import classNames from "classnames" ;
67
78import { useMFWStore } from "../../../stores/mfwStore" ;
@@ -27,6 +28,7 @@ const LiveScreenPanel = memo(() => {
2728 const [ screenImage , setScreenImage ] = useState < string | null > ( null ) ;
2829 const [ isLoading , setIsLoading ] = useState ( true ) ;
2930 const [ hasError , setHasError ] = useState ( false ) ;
31+ const [ isCollapsed , setIsCollapsed ] = useState ( false ) ;
3032 const isRequestingRef = useRef ( false ) ;
3133 const consecutiveFailuresRef = useRef ( 0 ) ;
3234
@@ -46,6 +48,7 @@ const LiveScreenPanel = memo(() => {
4648 controllerId !== null &&
4749 ! isDisplaced &&
4850 enableLiveScreen ;
51+ const shouldRequestScreen = shouldShow && ! isCollapsed ;
4952
5053 // 注册截图结果监听
5154 useEffect ( ( ) => {
@@ -90,7 +93,7 @@ const LiveScreenPanel = memo(() => {
9093 } , [ controllerId ] ) ;
9194
9295 useEffect ( ( ) => {
93- if ( ! shouldShow || ! controllerId ) {
96+ if ( ! shouldRequestScreen || ! controllerId ) {
9497 return ;
9598 }
9699
@@ -105,7 +108,12 @@ const LiveScreenPanel = memo(() => {
105108 clearInterval ( timerId ) ;
106109 isRequestingRef . current = false ;
107110 } ;
108- } , [ shouldShow , liveScreenRefreshRate , controllerId , requestScreenshot ] ) ;
111+ } , [
112+ shouldRequestScreen ,
113+ liveScreenRefreshRate ,
114+ controllerId ,
115+ requestScreenshot ,
116+ ] ) ;
109117
110118 // 设备断开时清除画面
111119 useEffect ( ( ) => {
@@ -121,33 +129,54 @@ const LiveScreenPanel = memo(() => {
121129 const panelClass = classNames (
122130 style . liveScreenPanel ,
123131 shouldShow ? style . visible : style . hidden ,
132+ isCollapsed && style . collapsed ,
124133 ) ;
125134
126135 return (
127136 < div className = { panelClass } >
128137 < div className = { style . header } >
129138 < span className = { style . title } > 实时画面</ span >
130- { hasError && < span className = { style . status } > 截图异常</ span > }
131- </ div >
132- < div className = { style . contentContainer } >
133- { isLoading && ! screenImage ? (
134- < div className = { style . loadingContainer } >
135- < Spin />
136- < span > 正在获取画面...</ span >
137- </ div >
138- ) : hasError && ! screenImage ? (
139- < div className = { style . errorContainer } >
140- < span > 截图失败,请检查设备连接</ span >
141- </ div >
142- ) : screenImage ? (
143- < img
144- className = { style . screenImage }
145- src = { screenImage }
146- alt = "设备画面"
147- draggable = { false }
148- />
149- ) : null }
139+ < div className = { style . headerActions } >
140+ { hasError && ! isCollapsed && (
141+ < span className = { style . status } > 截图异常</ span >
142+ ) }
143+ < Tooltip
144+ placement = "left"
145+ title = { isCollapsed ? "展开实时画面" : "折叠实时画面" }
146+ >
147+ < Button
148+ aria-expanded = { ! isCollapsed }
149+ aria-label = { isCollapsed ? "展开实时画面" : "折叠实时画面" }
150+ className = { style . collapseButton }
151+ icon = { isCollapsed ? < DownOutlined /> : < UpOutlined /> }
152+ size = "small"
153+ type = "text"
154+ onClick = { ( ) => setIsCollapsed ( ( collapsed ) => ! collapsed ) }
155+ />
156+ </ Tooltip >
157+ </ div >
150158 </ div >
159+ { ! isCollapsed && (
160+ < div className = { style . contentContainer } >
161+ { isLoading && ! screenImage ? (
162+ < div className = { style . loadingContainer } >
163+ < Spin />
164+ < span > 正在获取画面...</ span >
165+ </ div >
166+ ) : hasError && ! screenImage ? (
167+ < div className = { style . errorContainer } >
168+ < span > 截图失败,请检查设备连接</ span >
169+ </ div >
170+ ) : screenImage ? (
171+ < img
172+ className = { style . screenImage }
173+ src = { screenImage }
174+ alt = "设备画面"
175+ draggable = { false }
176+ />
177+ ) : null }
178+ </ div >
179+ ) }
151180 </ div >
152181 ) ;
153182} ) ;
0 commit comments