From 2673a86a52f1a8163b5718c600892de1092bb748 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9B=A8=E9=9C=96=E9=93=83?= Date: Wed, 7 Jan 2026 23:01:57 +0800 Subject: [PATCH] =?UTF-8?q?feat(App):=20=E6=B7=BB=E5=8A=A0=E5=AF=BC?= =?UTF-8?q?=E8=88=AA=E8=8F=9C=E5=8D=95=E6=8A=98=E5=8F=A0=E5=8A=9F=E8=83=BD?= =?UTF-8?q?=E5=92=8C=E6=A0=B7=E5=BC=8F=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 实现响应式导航菜单,根据屏幕尺寸自动调整显示项数量 - 添加移动端友好的折叠菜单和汉堡按钮 - 统一应用内所有按钮和容器的圆角样式为8px - 重构导航配置为数据驱动模式,便于后续扩展 - 优化小屏幕设备上的导航显示和交互体验 - 添加菜单展开收起的动画过渡效果 - 修复超小屏幕下的边框遮挡问题 --- src/App.css | 342 ++++++++++++++++++++++++-- src/App.js | 98 +++++++- src/components/TodoMarkdownEditor.css | 14 +- src/pages/ElectronicWoodenFish.css | 7 + 4 files changed, 428 insertions(+), 33 deletions(-) diff --git a/src/App.css b/src/App.css index a3a7514..3209bb9 100644 --- a/src/App.css +++ b/src/App.css @@ -16,6 +16,13 @@ align-items: center; padding: 0 16px; margin-bottom: 5px; + position: relative; +} + +.nav-content { + width: 100%; + display: flex; + align-items: center; } .nav-list { @@ -24,12 +31,25 @@ gap: 16px; padding: 0; margin: 0; + align-items: center; + flex-wrap: wrap; + transition: all 0.3s ease; } .nav-link { text-decoration: none; color: #666; font-size: 14px; + padding: 8px 12px; + border-radius: 8px; + transition: all 0.2s ease; + display: inline-block; + white-space: nowrap; +} + +.nav-link:hover { + background-color: #f5f5f5; + color: #333; } .nav-link.active { @@ -37,12 +57,306 @@ font-weight: 600; border-bottom: 2px solid #1677ff; padding-bottom: 4px; + background-color: rgba(22, 119, 255, 0.05); +} + +/* 折叠菜单相关样式 */ +.nav-collapse-item { + position: relative; + display: flex; + align-items: center; +} + +.nav-collapse-content { + position: absolute; + top: 100%; + right: 0; + background: white; + border: 1px solid transparent; /* 使用透明边框,避免悬停时显示 */ + border-radius: 8px; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); + min-width: 120px; + z-index: 1000; + margin-top: 8px; + flex-direction: column; + gap: 0; + opacity: 0; + visibility: hidden; + transform: translateY(-10px); + transition: opacity 0.3s ease, transform 0.3s ease, visibility 0.3s ease, border-color 0.3s ease; + display: none; +} + +.nav-collapse-item:hover .nav-collapse-content, +.nav-collapse-content.show { + display: flex; + opacity: 1; + visibility: visible; + transform: translateY(0); + border-color: #e5e5e5; /* 只在显示时显示边框 */ +} + +.nav-collapse-content .nav-link { + padding: 10px 16px; + border-bottom: 1px solid #f0f0f0; + width: 100%; + text-align: left; + box-sizing: border-box; +} + +.nav-collapse-content .nav-link:last-child { + border-bottom: none; +} + +.nav-collapse-content .nav-link:hover { + background-color: #f5f5f5; +} + +.nav-toggle { + background: none; + border: 1px solid #e5e5e5; + border-radius: 8px; + padding: 6px 12px; + cursor: pointer; + font-size: 14px; + color: #666; + display: flex; + align-items: center; + gap: 4px; + transition: all 0.2s ease; + margin-left: 8px; +} + +.nav-toggle:hover { + background-color: #f5f5f5; + border-color: #d9d9d9; + color: #333; +} + +.nav-toggle-icon { + font-size: 16px; + line-height: 1; +} + +.nav-collapse-count { + font-size: 12px; + color: #999; + font-weight: 500; +} + +/* 响应式设计 */ +@media (max-width: 767px) { + .nav-list { + gap: 12px; + flex-wrap: nowrap; + overflow: hidden; + } + + /* 当菜单展开时,允许换行并显示所有可见项 */ + .nav-list.open { + flex-wrap: wrap; + overflow: visible; + } + + .nav-link { + padding: 6px 10px; + font-size: 13px; + } + + .nav-collapse-content { + position: fixed; + top: 48px; + left: 0; + right: 0; + margin-top: 0; + border-radius: 8px; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); + max-height: 0; + overflow: hidden; + transition: max-height 0.3s ease; + opacity: 1; /* 覆盖默认的opacity: 0 */ + visibility: visible; /* 覆盖默认的visibility: hidden */ + transform: none; /* 覆盖默认的transform */ + display: block; /* 覆盖默认的display: none,使用block而不是flex */ + /* 移除边框,避免横线显示 */ + border-style: none; + } + + .nav-collapse-content.show { + max-height: 300px; + } + + .nav-collapse-content .nav-link { + padding: 12px 16px; + font-size: 14px; + } + + .nav-toggle { + padding: 8px 16px; + margin-left: auto; + } +} + +@media (max-width: 479px) { + .nav { + padding: 0 12px; + z-index: 1000; /* 确保导航栏在展开菜单上方 */ + } + + .nav-list { + width: 100%; + justify-content: space-between; + align-items: center; + } + + /* 当菜单展开时,允许换行并显示所有可见项 */ + .nav-list.open { + flex-wrap: wrap; + overflow: visible; + } + + /* 可见的导航项应该始终显示 */ + .nav-list > li:not(.nav-collapse-item) { + display: flex; + align-items: center; + } + + .nav-list > li:not(.nav-collapse-item) .nav-link { + display: inline-block; + padding: 8px 12px; + font-size: 13px; + white-space: nowrap; + max-width: 80px; + overflow: hidden; + text-overflow: ellipsis; + } + + /* 折叠菜单内容 - 只在打开时显示 */ + .nav-collapse-content { + position: fixed; + top: 48px; + left: 0; + right: 0; + background: white; + border-top: 1px solid #e5e5e5; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); + z-index: 999; + max-height: 0; + overflow: hidden; + transition: max-height 0.3s ease; + } + + .nav-collapse-content.show { + max-height: calc(100vh - 48px); + overflow-y: auto; + } + + .nav-collapse-content .nav-link { + display: block; + width: 100%; + text-align: center; + border-bottom: 1px solid #f0f0f0; + padding: 12px 16px; + font-size: 14px; + } + + .nav-collapse-content .nav-link:last-child { + border-bottom: none; + } + + .nav-toggle { + padding: 8px 12px; + font-size: 13px; + min-width: 44px; + height: 32px; + display: flex; + align-items: center; + justify-content: center; + } + + .nav-toggle:hover { + background: #f0f0f0; + } + + .nav-collapse-count { + display: none; + } +} + +/* 超小屏幕适配 - 修复边框遮挡问题 */ +@media (max-width: 399px) { + .nav { + position: relative; + border-bottom: none; /* 移除导航栏底部边框 */ + } + + .nav::after { + content: ''; + position: absolute; + bottom: 0; + left: 0; + right: 0; + height: 1px; + background-color: #e5e5e5; + z-index: 1001; /* 确保边框在导航栏上方,但在展开菜单下方 */ + } + + /* 当菜单展开时,允许换行并显示所有可见项 */ + .nav-list.open { + flex-wrap: wrap; + overflow: visible; + } + + /* 调整可见导航项的宽度,适应更小的屏幕 */ + .nav-list > li:not(.nav-collapse-item) .nav-link { + max-width: 60px; + padding: 6px 8px; + font-size: 12px; + } + + .nav-toggle { + padding: 6px 10px; + font-size: 12px; + min-width: 40px; + height: 30px; + } + + .nav-toggle-icon { + font-size: 13px; + } +} + +/* 中等屏幕适配 */ +@media (min-width: 480px) and (max-width: 767px) { + .nav-list { + flex-wrap: wrap; + justify-content: flex-start; + } + + .nav-link { + flex: 0 0 auto; + } + + .nav-collapse-item { + margin-left: auto; + } + + /* 确保.nav-list.open不会影响中等屏幕的布局 */ + .nav-list.open { + flex-wrap: wrap; + position: static; + background: none; + border: none; + box-shadow: none; + max-height: none; + overflow: visible; + } } .page { padding: 20px; border: 1px solid #ddd; - border-radius: 4px; + border-radius: 8px; } .user-list { @@ -62,7 +376,7 @@ background: #2196f3; color: white; text-decoration: none; - border-radius: 4px; + border-radius: 8px; } .btn:hover { @@ -78,7 +392,7 @@ padding: 8px 16px; background: #4caf50; color: white; - border-radius: 4px; + border-radius: 8px; cursor: pointer; border: 1px solid #d9d9d9; box-shadow: 0 2px #00000004; @@ -107,7 +421,7 @@ background: #f32152; color: white; border: none; - border-radius: 4px; + border-radius: 8px; cursor: pointer; } @@ -119,7 +433,7 @@ input { width: 100%; padding: 10px; border: 1px solid #ddd; - border-radius: 4px; + border-radius: 8px; margin-bottom: 20px; box-sizing: border-box; font-size: 14px; @@ -129,7 +443,7 @@ select { width: 100%; padding: 10px; border: 1px solid #ddd; - border-radius: 4px; + border-radius: 8px; margin-bottom: 20px; box-sizing: border-box; font-size: 14px; @@ -161,7 +475,7 @@ select { margin-bottom: 25px; padding: 15px; background: white; - border-radius: 6px; + border-radius: 8px; box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.1); min-height: 80px; overflow-x: auto; @@ -195,7 +509,7 @@ select { .timestamp-btn { padding: 10px 20px; - border-radius: 6px; + border-radius: 8px; font-weight: 500; transition: all 0.2s ease; border: none; @@ -215,7 +529,7 @@ select { min-width: 120px; height: 44px; padding: 10px 20px; - border-radius: 6px; + border-radius: 8px; font-weight: 500; font-size: 0.95rem; display: flex; @@ -239,7 +553,7 @@ select { align-items: center; padding: 12px 16px; background: rgba(255, 255, 255, 0.8); - border-radius: 6px; + border-radius: 8px; font-size: 0.9rem; border: 1px solid #e0e0e0; } @@ -357,7 +671,7 @@ select { flex: 1; padding: 10px 14px; border: 1px solid #ddd; - border-radius: 6px; + border-radius: 8px; font-size: 0.95rem; font-family: 'Courier New', monospace; background: white; @@ -377,7 +691,7 @@ select { .unit-select { padding: 10px 14px; border: 1px solid #ddd; - border-radius: 6px; + border-radius: 8px; font-size: 0.95rem; background: white; min-width: 180px; @@ -401,7 +715,7 @@ select { .converter-btn { padding: 10px 24px; - border-radius: 6px; + border-radius: 8px; font-weight: 500; font-size: 1rem; min-width: 120px; @@ -411,7 +725,7 @@ select { padding: 10px 14px; background: #ffeaea; border: 1px solid #ffcccc; - border-radius: 6px; + border-radius: 8px; color: #d32f2f; font-size: 0.9rem; text-align: center; diff --git a/src/App.js b/src/App.js index 9674792..13403a8 100644 --- a/src/App.js +++ b/src/App.js @@ -1,29 +1,103 @@ import {HashRouter as Router, Routes, Route, NavLink} from 'react-router-dom'; +import {useState, useEffect} from 'react'; import TimestampPage from './pages/TimestampPage'; import ElectronicWoodenFishPage from "./pages/ElectronicWoodenFishPage"; import TodoListPage from "./pages/TodoListPage"; import './App.css'; +// 导航项配置数组,便于后续添加 +// 为了测试折叠功能,我们添加更多导航项 +const navItems = [ + {path: '/', label: 'Timestamp', element: }, + {path: '/dzmy', label: '电子木鱼', element: }, + {path: '/todo', label: '待办', element: }, +]; + function App() { + const [isMenuOpen, setIsMenuOpen] = useState(false); + const [isMobile, setIsMobile] = useState(false); + const [visibleItems, setVisibleItems] = useState(navItems.length); + + // 检测屏幕尺寸变化 + useEffect(() => { + const handleResize = () => { + const width = window.innerWidth; + setIsMobile(width < 768); + + // 根据屏幕宽度决定显示多少个导航项 + if (width >= 768) { + setVisibleItems(navItems.length); // 大屏幕显示所有 + } else if (width >= 480) { + // 中等屏幕:如果导航项超过3个,显示3个,否则显示全部 + setVisibleItems(Math.min(3, navItems.length)); + } else { + // 小屏幕:如果导航项超过2个,显示2个,否则显示全部 + setVisibleItems(Math.min(2, navItems.length)); + } + }; + + handleResize(); // 初始调用 + window.addEventListener('resize', handleResize); + return () => window.removeEventListener('resize', handleResize); + }, []); + + // 计算哪些导航项应该显示,哪些应该折叠 + const visibleNavItems = navItems.slice(0, visibleItems); + const collapsedNavItems = navItems.slice(visibleItems); + return (
- }/> - }/> - }/> - }/> + {navItems.map((item) => ( + + ))}
); diff --git a/src/components/TodoMarkdownEditor.css b/src/components/TodoMarkdownEditor.css index b21b7ab..6d986df 100644 --- a/src/components/TodoMarkdownEditor.css +++ b/src/components/TodoMarkdownEditor.css @@ -42,7 +42,7 @@ padding: 6px 12px; background-color: #fff; border: 1px solid #ced4da; - border-radius: 4px; + border-radius: 8px; font-size: 0.85rem; font-weight: 600; color: #495057; @@ -65,7 +65,7 @@ .action-button { padding: 8px 16px; border: none; - border-radius: 4px; + border-radius: 8px; font-size: 0.9rem; font-weight: 600; cursor: pointer; @@ -219,7 +219,7 @@ margin: 0; font-size: 85%; background-color: rgba(27, 31, 35, 0.05); - border-radius: 3px; + border-radius: 8px; font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace; } @@ -229,14 +229,14 @@ font-size: 85%; line-height: 1.45; background-color: #f6f8fa; - border-radius: 6px; + border-radius: 8px; margin: 0 0 1em 0; } .markdown-preview pre code { padding: 0; background-color: transparent; - border-radius: 0; + border-radius: 8px; } .markdown-preview blockquote { @@ -296,12 +296,12 @@ .markdown-preview::-webkit-scrollbar-track { background: #f1f1f1; - border-radius: 4px; + border-radius: 8px; } .markdown-preview::-webkit-scrollbar-thumb { background: #c1c1c1; - border-radius: 4px; + border-radius: 8px; } .markdown-preview::-webkit-scrollbar-thumb:hover { diff --git a/src/pages/ElectronicWoodenFish.css b/src/pages/ElectronicWoodenFish.css index 6ab4ec6..56a6b0a 100644 --- a/src/pages/ElectronicWoodenFish.css +++ b/src/pages/ElectronicWoodenFish.css @@ -19,6 +19,7 @@ flex-direction: column; justify-content: space-evenly; position: relative; + border-radius: 8px; } /* 计数显示 */ @@ -123,9 +124,11 @@ opacity: 1; flex-shrink: 0; } + .dzmy-controls .action-btn:hover { opacity: 0.9; } + .dzmy-controls .action-btn:active { opacity: 0.8; box-shadow: 0 0 0 2px rgba(76, 175, 80, 0.3); @@ -138,15 +141,19 @@ --dzmy-img-width: 120px; --dzmy-img-height: 90px; } + .dzmy-count { font-size: 14px; } + .tip-item { font-size: 18px; } + .dzmy-controls { flex-wrap: wrap; } + .dzmy-controls input { min-width: 100px; max-width: 150px;