22 <div class =" playground-editor fixed top-[64px] left-0 right-0 bottom-0 flex flex-col bg-white dark:bg-gray-900" >
33 <!-- 顶部工具栏 -->
44 <div class =" border-b border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-gray-800" >
5- <div class =" px-4 py-3 flex justify-between items-center" >
6- <div class =" flex items-center gap-3 " >
7- <div class =" text-xl text-gray-900 dark:text-gray-100" >代码实验室</div >
8- <div class =" lang-selector-container" >
5+ <div class =" px-3 sm:px-4 py-2 sm: py-3 flex justify-between items-center" >
6+ <div class =" flex items-center gap-2 sm:gap-3 min-w-0 " >
7+ <div class =" text-lg sm:text- xl text-gray-900 dark:text-gray-100 truncate " >代码实验室</div >
8+ <div class =" lang-selector-container flex-shrink-0 " >
99 <select v-model =" selectedLang"
10- class =" language-selector text-lg font-semibold bg-transparent border-none outline-none cursor-pointer text-gray-900 dark:text-gray-100 hover:text-blue-600 dark:hover:text-blue-400 transition-colors duration-200" >
10+ class =" language-selector text-sm sm:text- lg font-semibold bg-transparent border-none outline-none cursor-pointer text-gray-900 dark:text-gray-100 hover:text-blue-600 dark:hover:text-blue-400 transition-colors duration-200" >
1111 <option value =" py" >Python</option >
1212 <option value =" js" >JavaScript</option >
1313 </select >
1616 </svg >
1717 </div >
1818 </div >
19- <div class =" flex items-center gap-2" >
19+ <div class =" flex items-center gap-1 sm:gap-2 flex-shrink-0" >
20+ <!-- 移动端显示切换按钮 -->
21+ <button @click =" toggleMobileView"
22+ class =" md:hidden text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100 px-2 py-1.5 rounded-md text-xs cursor-pointer transition-all duration-200 hover:bg-gray-100 dark:hover:bg-gray-700 flex items-center gap-1"
23+ :class =" { 'bg-blue-50 dark:bg-blue-900 text-blue-600 dark:text-blue-400': showMobileOutput }" >
24+ <span >{{ showMobileOutput ? '代码' : '结果' }}</span >
25+ </button >
2026 <SimpleTooltip content =" 复制代码" placement =" bottom" >
2127 <button @click =" copyCode"
22- class =" text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100 px-3 py-1.5 rounded-md text-sm cursor-pointer transition-all duration-200 hover:bg-gray-100 dark:hover:bg-gray-700 flex items-center gap-1" >
28+ class =" text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100 px-2 sm:px- 3 py-1.5 rounded-md text-xs sm: text-sm cursor-pointer transition-all duration-200 hover:bg-gray-100 dark:hover:bg-gray-700 flex items-center gap-1" >
2329 <CopyIcon v-if =" !copySuccess" :size =" 16" />
2430 <CheckIcon v-else :size =" 16" />
25- <span >{{ copySuccess ? '已复制' : '复制' }}</span >
31+ <span class = " hidden sm:inline " >{{ copySuccess ? '已复制' : '复制' }}</span >
2632 </button >
2733 </SimpleTooltip >
2834 <SimpleTooltip :content =" `${getButtonText(selectedLang)} (Ctrl/⌘+Enter)`" placement =" bottom-end" >
2935 <button @click =" () => runCode(selectedLang)"
30- class =" bg-blue-600 hover:bg-blue-700 text-white px-4 py-1.5 rounded-md text-sm cursor-pointer transition-all duration-200 disabled:opacity-50 disabled:cursor-not-allowed flex items-center gap-2"
36+ class =" bg-blue-600 hover:bg-blue-700 text-white px-2 sm:px- 4 py-1.5 rounded-md text-xs sm:text-sm cursor-pointer transition-all duration-200 disabled:opacity-50 disabled:cursor-not-allowed flex items-center gap-1 sm: gap-2"
3137 :disabled =" isRunning || (selectedLang === 'py' && !pyodideReady)" >
3238 <LoaderIcon v-if =" isRunning || (selectedLang === 'py' && !pyodideReady)" :size =" 16" class =" animate-spin" />
3339 <PlayIcon v-else :size =" 16" />
34- <span >{{ getSimpleButtonText(selectedLang) }}</span >
40+ <span class = " whitespace-nowrap " >{{ getSimpleButtonText(selectedLang) }}</span >
3541 </button >
3642 </SimpleTooltip >
3743 </div >
3844 </div >
3945 </div >
4046
4147 <!-- 主要编辑区域 -->
42- <div class =" flex-1 flex overflow-hidden" >
48+ <div class =" flex-1 flex flex-col md:flex-row overflow-hidden" >
4349 <!-- 左侧代码编辑器 -->
44- <div class =" flex-1 flex flex-col border-r border-gray-200 dark:border-gray-700" >
50+ <div class =" flex-1 flex flex-col md:border-r border-gray-200 dark:border-gray-700"
51+ :class =" { 'hidden md:flex': showMobileOutput }" >
4552 <div class =" flex-1 relative" >
4653 <!-- 懒加载占位符 -->
4754 <div v-if =" !isInitialized"
5865 </div >
5966
6067 <!-- 右侧输出区域 -->
61- <div class =" w-96 flex flex-col bg-gray-50 dark:bg-gray-800" >
68+ <div class =" w-full md:w-80 lg:w-96 flex flex-col bg-gray-50 dark:bg-gray-800 border-t md:border-t-0 border-gray-200 dark:border-gray-700"
69+ :class =" { 'hidden md:flex': !showMobileOutput }" >
6270 <div class =" h-[40px] px-4 flex justify-between items-center bg-gray-100 dark:bg-gray-700 border-b border-gray-200 dark:border-gray-600" >
6371 <span class =" text-sm text-gray-600 dark:text-gray-400" >输出结果</span >
6472 <button v-if =" output" @click =" clearOutput"
@@ -88,13 +96,19 @@ import SimpleTooltip from './SimpleTooltip.vue'
8896
8997const placeholderRef: Ref <HTMLElement | null > = ref (null )
9098const selectedLang: Ref <string > = ref (' py' )
99+ const showMobileOutput: Ref <boolean > = ref (false )
91100
92101// 代码变化时的回调 - 重置输出
93102const onCodeChange = () => {
94103 output .value = ' '
95104 hasError .value = false
96105}
97106
107+ // 移动端视图切换
108+ const toggleMobileView = (): void => {
109+ showMobileOutput .value = ! showMobileOutput .value
110+ }
111+
98112// 使用 composable
99113const {
100114 editorRef,
@@ -325,13 +339,20 @@ onUnmounted((): void => {
325339 position : relative ;
326340 display : flex ;
327341 align-items : center ;
328- gap : 4 px ;
329- padding : 4 px 8 px ;
342+ gap : 2 px ;
343+ padding : 2 px 6 px ;
330344 border-radius : 6px ;
331345 transition : all 0.2s ease ;
332346 cursor : pointer ;
333347}
334348
349+ @media (min-width : 640px ) {
350+ .lang-selector-container {
351+ gap : 4px ;
352+ padding : 4px 8px ;
353+ }
354+ }
355+
335356.lang-selector-container :hover {
336357 background : rgba (59 , 130 , 246 , 0.1 );
337358}
@@ -419,4 +440,37 @@ html.dark .language-selector option {
419440 background : #374151 ;
420441 color : #f9fafb ;
421442}
443+
444+ /* 移动端优化 */
445+ @media (max-width : 768px ) {
446+ .playground-editor {
447+ top : 64px ;
448+ }
449+
450+ /* 确保移动端编辑器区域有足够高度 */
451+ .playground-editor :deep(.cm-editor ) {
452+ min-height : 50vh ;
453+ }
454+
455+ /* 移动端输出区域高度限制 */
456+ .playground-editor .w-full.md\\ :w-80 {
457+ max-height : 50vh ;
458+ }
459+ }
460+
461+ /* 确保在极小屏幕上的可用性 */
462+ @media (max-width : 480px ) {
463+ .playground-editor {
464+ font-size : 14px ;
465+ }
466+
467+ .playground-editor :deep(.cm-content ) {
468+ padding : 8px 0 ;
469+ }
470+
471+ .playground-editor :deep(.cm-lineNumbers .cm-gutterElement ) {
472+ min-width : 32px ;
473+ font-size : 12px ;
474+ }
475+ }
422476 </style >
0 commit comments