@@ -4,8 +4,8 @@ import { apiInterceptors, getAppInfo, newDialogue, updateApp, getAppVersion } fr
44import { AppContext } from '@/contexts' ;
55import { IApp } from '@/types/app' ;
66import { useRequest } from 'ahooks' ;
7- import { Spin , App } from 'antd' ;
8- import { useCallback , useRef , useState } from 'react' ;
7+ import { Spin , App , Tooltip } from 'antd' ;
8+ import { useCallback , useRef , useState , useEffect } from 'react' ;
99import { useTranslation } from 'react-i18next' ;
1010import AgentList from './components/agent-list' ;
1111import AgentHeader from './components/agent-header' ;
@@ -16,7 +16,7 @@ import TabTools from './components/tab-tools';
1616import TabAgents from './components/tab-agents' ;
1717import TabKnowledge from './components/tab-knowledge' ;
1818import ChatContent from './components/chat-content' ;
19- import { AppstoreOutlined } from '@ant-design/icons' ;
19+ import { AppstoreOutlined , EditOutlined , MessageOutlined } from '@ant-design/icons' ;
2020
2121export default function AgentBuilder ( ) {
2222 const { message, notification } = App . useApp ( ) ;
@@ -25,13 +25,36 @@ export default function AgentBuilder() {
2525 // Agent selection
2626 const [ selectedAppCode , setSelectedAppCode ] = useState < string | null > ( null ) ;
2727 const [ activeTab , setActiveTab ] = useState ( 'overview' ) ;
28+
29+ // Panel toggle for small screens: 'editor' | 'chat'
30+ const [ activePanel , setActivePanel ] = useState < 'editor' | 'chat' > ( 'editor' ) ;
31+ const [ screenSize , setScreenSize ] = useState < 'small' | 'medium' | 'large' > ( 'large' ) ;
2832
2933 // AppContext state (mirrors structure/page.tsx)
3034 const [ collapsed , setCollapsed ] = useState ( false ) ;
3135 const [ appInfo , setAppInfo ] = useState < any > ( { } ) ;
3236 const [ versionData , setVersionData ] = useState < any > ( null ) ;
3337 const [ chatId , setChatId ] = useState < string > ( '' ) ;
3438
39+ // Detect screen size
40+ useEffect ( ( ) => {
41+ const checkScreenSize = ( ) => {
42+ const width = window . innerWidth ;
43+ if ( width < 1280 ) {
44+ setScreenSize ( 'small' ) ;
45+ } else if ( width < 1536 ) {
46+ setScreenSize ( 'medium' ) ;
47+ } else {
48+ setScreenSize ( 'large' ) ;
49+ }
50+ } ;
51+ checkScreenSize ( ) ;
52+ window . addEventListener ( 'resize' , checkScreenSize ) ;
53+ return ( ) => window . removeEventListener ( 'resize' , checkScreenSize ) ;
54+ } , [ ] ) ;
55+
56+ const isSmallScreen = screenSize === 'small' ;
57+
3558 // Query agent info
3659 const {
3760 run : queryAppInfo ,
@@ -166,64 +189,145 @@ export default function AgentBuilder() {
166189 >
167190 < div className = "flex h-screen w-full bg-gradient-to-br from-slate-50 via-gray-50 to-blue-50/30 overflow-hidden" >
168191 { /* Column 1: Agent List */ }
169- < div className = "w-[280px] flex-shrink-0 p-3 pr-0" >
192+ < div className = { `flex-shrink-0 p-3 pr-0 ${
193+ screenSize === 'small' ? 'w-[200px]' :
194+ screenSize === 'medium' ? 'w-[240px]' :
195+ 'w-[280px]'
196+ } `} >
170197 < AgentList selectedAppCode = { selectedAppCode } onSelect = { handleSelectAgent } onListLoaded = { handleListLoaded } />
171198 </ div >
172199
173- { /* Column 2: Config Tabs — collapsible */ }
174- < div
175- className = { `flex-shrink-0 p-3 flex flex-col transition-all duration-400 ease-[cubic-bezier(0.4,0,0.2,1)] overflow-hidden ${
176- collapsed
177- ? 'w-0 min-w-0 opacity-0 p-0 pointer-events-none'
178- : 'flex-1 min-w-[320px] opacity-100'
179- } `}
180- >
181- { selectedAppCode && appInfo ?. app_code ? (
182- < Spin spinning = { refreshAppInfoLoading } wrapperClassName = "flex-1 flex flex-col overflow-hidden" >
183- < div className = "flex flex-col h-full bg-white/80 backdrop-blur-xl rounded-2xl border border-white/60 shadow-[0_8px_32px_rgba(0,0,0,0.06)] overflow-hidden" >
184- < AgentHeader activeTab = { activeTab } onTabChange = { setActiveTab } />
185- < div className = "flex-1 overflow-y-auto" >
186- { renderTabContent ( ) }
200+ { /* Column 2 & 3: Editor and Chat - responsive layout */ }
201+ { isSmallScreen ? (
202+ /* Small screen: toggle between editor and chat */
203+ < div className = "flex-1 flex flex-col min-w-0 p-3 pl-0" >
204+ { /* Toggle buttons */ }
205+ < div className = "flex items-center gap-2 mb-2" >
206+ < button
207+ onClick = { ( ) => setActivePanel ( 'editor' ) }
208+ className = { `flex items-center gap-1.5 px-3 py-1.5 rounded-lg text-sm font-medium transition-all ${
209+ activePanel === 'editor'
210+ ? 'bg-blue-500 text-white shadow-md'
211+ : 'bg-white/80 text-gray-600 hover:bg-gray-100 border border-gray-200'
212+ } `}
213+ >
214+ < EditOutlined />
215+ { t ( 'builder_edit' , '编辑' ) }
216+ </ button >
217+ < button
218+ onClick = { ( ) => setActivePanel ( 'chat' ) }
219+ className = { `flex items-center gap-1.5 px-3 py-1.5 rounded-lg text-sm font-medium transition-all ${
220+ activePanel === 'chat'
221+ ? 'bg-blue-500 text-white shadow-md'
222+ : 'bg-white/80 text-gray-600 hover:bg-gray-100 border border-gray-200'
223+ } `}
224+ >
225+ < MessageOutlined />
226+ { t ( 'builder_preview' , '预览' ) }
227+ </ button >
228+ </ div >
229+
230+ { /* Content area */ }
231+ < div className = "flex-1 min-h-0" >
232+ { activePanel === 'editor' ? (
233+ selectedAppCode && appInfo ?. app_code ? (
234+ < Spin spinning = { refreshAppInfoLoading } wrapperClassName = "h-full" >
235+ < div className = "flex flex-col h-full bg-white/80 backdrop-blur-xl rounded-2xl border border-white/60 shadow-[0_8px_32px_rgba(0,0,0,0.06)] overflow-hidden" >
236+ < AgentHeader activeTab = { activeTab } onTabChange = { setActiveTab } />
237+ < div className = "flex-1 overflow-y-auto" >
238+ { renderTabContent ( ) }
239+ </ div >
240+ </ div >
241+ </ Spin >
242+ ) : (
243+ < div className = "h-full flex items-center justify-center bg-white/80 backdrop-blur-xl rounded-2xl border border-white/60 shadow-[0_8px_32px_rgba(0,0,0,0.06)]" >
244+ < div className = "text-center" >
245+ < div className = "w-16 h-16 mx-auto mb-4 rounded-2xl bg-gradient-to-br from-gray-100 to-gray-50 flex items-center justify-center" >
246+ < AppstoreOutlined className = "text-2xl text-gray-300" />
247+ </ div >
248+ < p className = "text-gray-400 text-sm font-medium" > { t ( 'builder_select_agent' ) } </ p >
249+ </ div >
250+ </ div >
251+ )
252+ ) : (
253+ < div className = "h-full bg-white/80 backdrop-blur-xl rounded-2xl border border-white/60 shadow-[0_8px_32px_rgba(0,0,0,0.06)] overflow-hidden" >
254+ { selectedAppCode && appInfo ?. app_code ? (
255+ < ChatContent />
256+ ) : (
257+ < div className = "flex items-center justify-center h-full" >
258+ < div className = "text-center" >
259+ < div className = "w-14 h-14 mx-auto mb-3 rounded-2xl bg-gradient-to-br from-green-50 to-emerald-50 flex items-center justify-center" >
260+ < MessageOutlined className = "text-2xl text-green-400" />
261+ </ div >
262+ < p className = "text-gray-400 text-sm font-medium" > { t ( 'builder_chat_preview' ) } </ p >
263+ </ div >
264+ </ div >
265+ ) }
187266 </ div >
188- </ div >
189- </ Spin >
190- ) : (
191- < div className = "flex-1 flex items-center justify-center bg-white/80 backdrop-blur-xl rounded-2xl border border-white/60 shadow-[0_8px_32px_rgba(0,0,0,0.06)]" >
192- < div className = "text-center" >
193- < div className = "w-16 h-16 mx-auto mb-4 rounded-2xl bg-gradient-to-br from-gray-100 to-gray-50 flex items-center justify-center" >
194- < AppstoreOutlined className = "text-2xl text-gray-300" />
267+ ) }
268+ </ div >
269+ </ div >
270+ ) : (
271+ /* Large screen: side by side layout */
272+ < >
273+ { /* Column 2: Config Tabs */ }
274+ < div
275+ className = { `flex-shrink-0 p-3 flex flex-col transition-all duration-400 ease-[cubic-bezier(0.4,0,0.2,1)] overflow-hidden ${
276+ collapsed
277+ ? 'w-0 min-w-0 opacity-0 p-0 pointer-events-none'
278+ : 'flex-1 opacity-100'
279+ } `}
280+ style = { { minWidth : collapsed ? 0 : ( screenSize === 'medium' ? '360px' : '320px' ) } }
281+ >
282+ { selectedAppCode && appInfo ?. app_code ? (
283+ < Spin spinning = { refreshAppInfoLoading } wrapperClassName = "flex-1 flex flex-col overflow-hidden" >
284+ < div className = "flex flex-col h-full bg-white/80 backdrop-blur-xl rounded-2xl border border-white/60 shadow-[0_8px_32px_rgba(0,0,0,0.06)] overflow-hidden" >
285+ < AgentHeader activeTab = { activeTab } onTabChange = { setActiveTab } />
286+ < div className = "flex-1 overflow-y-auto" >
287+ { renderTabContent ( ) }
288+ </ div >
289+ </ div >
290+ </ Spin >
291+ ) : (
292+ < div className = "flex-1 flex items-center justify-center bg-white/80 backdrop-blur-xl rounded-2xl border border-white/60 shadow-[0_8px_32px_rgba(0,0,0,0.06)]" >
293+ < div className = "text-center" >
294+ < div className = "w-16 h-16 mx-auto mb-4 rounded-2xl bg-gradient-to-br from-gray-100 to-gray-50 flex items-center justify-center" >
295+ < AppstoreOutlined className = "text-2xl text-gray-300" />
296+ </ div >
297+ < p className = "text-gray-400 text-sm font-medium" > { t ( 'builder_select_agent' ) } </ p >
298+ < p className = "text-gray-300 text-xs mt-1" > { t ( 'builder_select_agent' ) } </ p >
299+ </ div >
195300 </ div >
196- < p className = "text-gray-400 text-sm font-medium" > { t ( 'builder_select_agent' ) } </ p >
197- < p className = "text-gray-300 text-xs mt-1" > { t ( 'builder_select_agent' ) } </ p >
198- </ div >
301+ ) }
199302 </ div >
200- ) }
201- </ div >
202303
203- { /* Column 3: Chat Preview */ }
204- < div
205- className = { `flex-shrink-0 p-3 pl-0 transition-all duration-400 ease-[cubic-bezier(0.4,0,0.2,1)] ${
206- collapsed ? 'flex-1' : 'w-[480px]'
207- } `}
208- >
209- < div className = "h-full bg-white/80 backdrop-blur-xl rounded-2xl border border-white/60 shadow-[0_8px_32px_rgba(0,0,0,0.06)] overflow-hidden" >
210- { selectedAppCode && appInfo ?. app_code ? (
211- < ChatContent />
212- ) : (
213- < div className = "flex items-center justify-center h-full" >
214- < div className = "text-center" >
215- < div className = "w-14 h-14 mx-auto mb-3 rounded-2xl bg-gradient-to-br from-green-50 to-emerald-50 flex items-center justify-center" >
216- < svg className = "w-6 h-6 text-green-300" fill = "none" viewBox = "0 0 24 24" stroke = "currentColor" >
217- < path strokeLinecap = "round" strokeLinejoin = "round" strokeWidth = { 1.5 } d = "M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z" />
218- </ svg >
304+ { /* Column 3: Chat Preview */ }
305+ < div
306+ className = { `flex-shrink-0 p-3 pl-0 transition-all duration-400 ease-[cubic-bezier(0.4,0,0.2,1)] ${
307+ collapsed ? 'flex-1' : ''
308+ } `}
309+ style = { { width : collapsed ? undefined : ( screenSize === 'medium' ? '360px' : '480px' ) } }
310+ >
311+ < div className = "h-full bg-white/80 backdrop-blur-xl rounded-2xl border border-white/60 shadow-[0_8px_32px_rgba(0,0,0,0.06)] overflow-hidden" >
312+ { selectedAppCode && appInfo ?. app_code ? (
313+ < ChatContent />
314+ ) : (
315+ < div className = "flex items-center justify-center h-full" >
316+ < div className = "text-center" >
317+ < div className = "w-14 h-14 mx-auto mb-3 rounded-2xl bg-gradient-to-br from-green-50 to-emerald-50 flex items-center justify-center" >
318+ < svg className = "w-6 h-6 text-green-300" fill = "none" viewBox = "0 0 24 24" stroke = "currentColor" >
319+ < path strokeLinecap = "round" strokeLinejoin = "round" strokeWidth = { 1.5 } d = "M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z" />
320+ </ svg >
321+ </ div >
322+ < p className = "text-gray-400 text-sm font-medium" > { t ( 'builder_chat_preview' ) } </ p >
323+ < p className = "text-gray-300 text-xs mt-1" > { t ( 'builder_chat_preview_desc' ) } </ p >
324+ </ div >
219325 </ div >
220- < p className = "text-gray-400 text-sm font-medium" > { t ( 'builder_chat_preview' ) } </ p >
221- < p className = "text-gray-300 text-xs mt-1" > { t ( 'builder_chat_preview_desc' ) } </ p >
222- </ div >
326+ ) }
223327 </ div >
224- ) }
225- </ div >
226- </ div >
328+ </ div >
329+ </ >
330+ ) }
227331 </ div >
228332 </ AppContext . Provider >
229333 ) ;
0 commit comments