From 68abc83e869d7663ad2ce9e70d61ebe5f877537d Mon Sep 17 00:00:00 2001 From: wikiboss Date: Thu, 8 Oct 2026 16:59:23 +0800 Subject: [PATCH] =?UTF-8?q?feat(nav):=20=E5=AF=BC=E8=88=AA=E6=A0=8F?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=9C=8D=E5=8A=A1=E4=B8=8E=E4=BA=A7=E5=93=81?= =?UTF-8?q?=E9=AB=98=E7=AB=AF=E5=A4=A7=E6=B0=94=E4=BA=8C=E7=BA=A7=E5=8D=A1?= =?UTF-8?q?=E7=89=87=E9=9D=A2=E6=9D=BF(Mega=20Menu)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../view/web/official_common/pc/nav.html | 217 +++++++++++++- .../assets/addons/official/css/modern_nhc.css | 282 ++++++++++++++++++ tests/NavMegaMenuTest.php | 105 +++++++ 3 files changed, 600 insertions(+), 4 deletions(-) create mode 100644 tests/NavMegaMenuTest.php diff --git a/addons/official/view/web/official_common/pc/nav.html b/addons/official/view/web/official_common/pc/nav.html index ec85572..e25e1ef 100644 --- a/addons/official/view/web/official_common/pc/nav.html +++ b/addons/official/view/web/official_common/pc/nav.html @@ -24,11 +24,220 @@
  • 首页
  • -
  • - 服务 + +
  • + + 服务 + + + +
  • -
  • - 产品 + + +
  • + + 产品 + + + +
  • 案例 diff --git a/public/assets/addons/official/css/modern_nhc.css b/public/assets/addons/official/css/modern_nhc.css index 2b62c1c..d436bad 100644 --- a/public/assets/addons/official/css/modern_nhc.css +++ b/public/assets/addons/official/css/modern_nhc.css @@ -1891,3 +1891,285 @@ img { grid-template-columns: 1fr; } } + +/* ========================================================================== + 导航栏二级大卡片面板 (Mega Menu Dropdown Panel) + ========================================================================== */ +.nhc-nav-item.nhc-has-dropdown { + position: relative; +} + +.nhc-has-dropdown .nhc-nav-link { + display: inline-flex; + align-items: center; + gap: 4px; +} + +.nhc-caret { + transition: transform 0.25s ease; + color: var(--text-muted); +} + +.nhc-has-dropdown:hover .nhc-caret { + transform: rotate(180deg); + color: var(--primary); +} + +/* 巨型下拉卡片面板容器 (固定于导航条下方) */ +.nhc-mega-panel { + position: absolute; + top: calc(100% + 12px); + left: 50%; + transform: translateX(-50%) translateY(8px); + width: 980px; + max-width: calc(100vw - 40px); + background: rgba(255, 255, 255, 0.98); + backdrop-filter: blur(20px); + -webkit-backdrop-filter: blur(20px); + border: 1px solid rgba(226, 232, 240, 0.95); + border-radius: var(--radius-md); + box-shadow: 0 24px 48px -12px rgba(15, 23, 42, 0.12), 0 2px 6px rgba(15, 23, 42, 0.04); + padding: 28px 32px; + opacity: 0; + visibility: hidden; + pointer-events: none; + transition: opacity 0.25s cubic-bezier(0.16, 1, 0.3, 1), + transform 0.25s cubic-bezier(0.16, 1, 0.3, 1), + visibility 0.25s; + z-index: 999; +} + +/* 向上防抖悬停连接区 */ +.nhc-mega-panel::before { + content: ""; + position: absolute; + top: -16px; + left: 0; + right: 0; + height: 16px; + background: transparent; +} + +/* 鼠标悬停展开 */ +.nhc-has-dropdown:hover .nhc-mega-panel, +.nhc-has-dropdown.active .nhc-mega-panel { + opacity: 1; + visibility: visible; + pointer-events: auto; + transform: translateX(-50%) translateY(0); +} + +/* 面板内部两列结构:左侧卡片矩阵 + 右侧背书侧边栏 */ +.nhc-mega-grid { + display: grid; + grid-template-columns: 1fr 280px; + gap: 28px; +} + +.nhc-mega-cards-col { + display: flex; + flex-direction: column; +} + +.nhc-mega-header { + font-size: 11px; + letter-spacing: 2px; + font-weight: 600; + color: var(--primary); + text-transform: uppercase; + margin-bottom: 14px; + display: flex; + align-items: center; + gap: 8px; +} + +/* 服务卡片 3 列网格 */ +.nhc-mega-cards-grid-3 { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 14px; +} + +/* 产品卡片 2 列网格 */ +.nhc-mega-cards-grid-2 { + display: grid; + grid-template-columns: repeat(2, 1fr); + gap: 14px; +} + +/* 二级卡片单体设计 */ +.nhc-mega-card { + display: flex; + flex-direction: column; + background: #F8FAFC; + border: 1px solid #E2E8F0; + border-radius: var(--radius-sm); + padding: 16px; + text-decoration: none; + transition: all 0.25s ease; + position: relative; + overflow: hidden; +} + +.nhc-mega-card:hover { + background: #FFFFFF; + border-color: rgba(37, 99, 235, 0.4); + transform: translateY(-2px); + box-shadow: 0 8px 20px -4px rgba(37, 99, 235, 0.12); +} + +.nhc-mega-card-top { + display: flex; + align-items: center; + gap: 10px; + margin-bottom: 8px; +} + +.nhc-mega-card-icon { + width: 32px; + height: 32px; + border-radius: 6px; + background: #FFFFFF; + border: 1px solid #E2E8F0; + display: flex; + align-items: center; + justify-content: center; + color: var(--primary); + flex-shrink: 0; + transition: all 0.2s ease; +} + +.nhc-mega-card:hover .nhc-mega-card-icon { + background: var(--primary); + color: #FFFFFF; + border-color: var(--primary); +} + +.nhc-mega-card-title { + font-family: var(--font-serif); + font-size: 15px; + font-weight: 700; + color: var(--text-primary); + transition: color 0.2s; + display: flex; + align-items: center; + justify-content: space-between; + width: 100%; +} + +.nhc-mega-card:hover .nhc-mega-card-title { + color: var(--primary); +} + +.nhc-mega-card-arrow { + font-size: 12px; + opacity: 0; + transform: translateX(-4px); + transition: all 0.2s ease; + color: var(--primary); +} + +.nhc-mega-card:hover .nhc-mega-card-arrow { + opacity: 1; + transform: translateX(0); +} + +.nhc-mega-card-desc { + font-size: 12px; + color: var(--text-secondary); + line-height: 1.5; + margin-bottom: 10px; + flex: 1; +} + +.nhc-mega-card-tags { + display: flex; + flex-wrap: wrap; + gap: 6px; +} + +.nhc-mega-card-tag { + font-size: 10px; + padding: 2px 6px; + border-radius: 3px; + background: #FFFFFF; + border: 1px solid #E2E8F0; + color: var(--text-muted); +} + +/* 右侧背书/快捷视窗 */ +.nhc-mega-sidebar { + background: #F8FAFC; + border: 1px solid #E2E8F0; + border-radius: var(--radius-sm); + padding: 20px; + display: flex; + flex-direction: column; + justify-content: space-between; +} + +.nhc-mega-sidebar-title { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 12px; +} + +.nhc-mega-sidebar-heading { + font-family: var(--font-serif); + font-size: 14px; + font-weight: 700; + color: var(--text-primary); +} + +.nhc-mega-sidebar-desc { + font-size: 12px; + color: var(--text-secondary); + line-height: 1.6; + margin-bottom: 16px; +} + +.nhc-mega-sidebar-metrics { + display: flex; + flex-direction: column; + gap: 10px; + margin-bottom: 18px; +} + +.nhc-mega-metric-row { + display: flex; + align-items: center; + justify-content: space-between; + font-size: 12px; + border-bottom: 1px dashed #E2E8F0; + padding-bottom: 6px; +} + +.nhc-mega-metric-label { + color: var(--text-muted); +} + +.nhc-mega-metric-val { + font-weight: 600; + color: var(--primary); +} + +.nhc-mega-sidebar-link { + display: flex; + align-items: center; + justify-content: center; + gap: 6px; + font-size: 12px; + font-weight: 600; + color: #FFFFFF; + background: var(--primary); + padding: 8px 14px; + border-radius: 4px; + text-decoration: none; + transition: all 0.2s ease; +} + +.nhc-mega-sidebar-link:hover { + background: var(--primary-hover); + box-shadow: 0 4px 12px rgba(37, 99, 235, 0.25); +} diff --git a/tests/NavMegaMenuTest.php b/tests/NavMegaMenuTest.php new file mode 100644 index 0000000..2c4be62 --- /dev/null +++ b/tests/NavMegaMenuTest.php @@ -0,0 +1,105 @@ +navContent = file_get_contents($navFile); + } + if (file_exists($cssFile)) { + $this->cssContent = file_get_contents($cssFile); + } + } + + public function run() + { + echo "=== 开始执行导航栏二级卡片面板规范测试 (TDD) ===\n"; + + // 1. 基础结构测试 + $this->testMegaMenuStructure(); + + // 2. 服务二级卡片面板业务内容测试 + $this->testServicesMegaMenu(); + + // 3. 产品二级卡片面板业务内容测试 + $this->testProductsMegaMenu(); + + // 4. CSS 交互与现代中式质感测试 + $this->testMegaMenuCss(); + + // 5. 禁止项测试(严禁使用 emoji) + $this->testForbiddenElements(); + + echo "\n测试结果: {$this->passed} 通过, {$this->failed} 失败\n"; + if ($this->failed > 0) { + exit(1); + } + } + + private function assert($condition, $message) + { + if ($condition) { + echo " [PASS] {$message}\n"; + $this->passed++; + } else { + echo " [FAIL] {$message}\n"; + $this->failed++; + } + } + + public function testMegaMenuStructure() + { + $hasDropdownClass = (strpos($this->navContent, 'nhc-has-dropdown') !== false); + $this->assert($hasDropdownClass, "导航栏必须具备 nhc-has-dropdown 下拉菜单触发类"); + + $hasMegaPanel = (strpos($this->navContent, 'nhc-mega-panel') !== false); + $this->assert($hasMegaPanel, "导航栏必须具备高端大气的 nhc-mega-panel 二级卡片面板容器"); + } + + public function testServicesMegaMenu() + { + $this->assert(strpos($this->navContent, '软件开发') !== false, "服务二级面板必须包含【软件开发】卡片"); + $this->assert(strpos($this->navContent, 'APP与小程序定制') !== false || (strpos($this->navContent, 'APP') !== false && strpos($this->navContent, '小程序') !== false), "服务二级面板必须包含【APP与小程序定制】卡片"); + $this->assert(strpos($this->navContent, '智能体开发') !== false, "服务二级面板必须包含【智能体开发】卡片"); + } + + public function testProductsMegaMenu() + { + $this->assert(strpos($this->navContent, '商城') !== false, "产品二级面板必须包含【商城】卡片"); + $this->assert(strpos($this->navContent, '收银') !== false, "产品二级面板必须包含【收银】卡片"); + $this->assert(strpos($this->navContent, '进销存') !== false, "产品二级面板必须包含【进销存】卡片"); + $this->assert(strpos($this->navContent, 'SaaS') !== false, "产品二级面板必须包含【SaaS版本】卡片"); + } + + public function testMegaMenuCss() + { + $hasPanelStyle = (strpos($this->cssContent, '.nhc-mega-panel') !== false); + $this->assert($hasPanelStyle, "CSS 中必须包含 .nhc-mega-panel 卡片面板样式"); + + $hasHoverTrigger = (strpos($this->cssContent, '.nhc-has-dropdown:hover') !== false || strpos($this->cssContent, '.nhc-mega-panel.active') !== false); + $this->assert($hasHoverTrigger, "CSS 中必须包含鼠标划过悬停展开交互样式"); + } + + public function testForbiddenElements() + { + $hasEmoji = preg_match('/[\x{1F600}-\x{1F64F}\x{1F300}-\x{1F5FF}\x{1F680}-\x{1F6FF}\x{2600}-\x{26FF}\x{2700}-\x{27BF}]/u', $this->navContent); + $this->assert(!$hasEmoji, "导航栏及二级卡片面板严禁使用任何 emoji 表情"); + } +} + +$test = new NavMegaMenuTest(); +$test->run();