fix: 优化官网
This commit is contained in:
@@ -7,18 +7,39 @@
|
||||
<div class="bottom desktop">
|
||||
<div class="nav-container">
|
||||
<div class="logoCell">
|
||||
<img class="logo" :src="image_paths.logo" alt="丙维科技">
|
||||
<router-link to="/index" aria-label="返回首页">
|
||||
<img class="logo" :src="image_paths.logo" alt="丙维科技">
|
||||
</router-link>
|
||||
</div>
|
||||
<div class="mainMenuCell">
|
||||
<nav class="mainMenu">
|
||||
<div class="nav-item" v-for="menu in menus" :key="menu.name">
|
||||
<router-link :to="menu.url" class="nav-link">
|
||||
<div
|
||||
class="nav-item"
|
||||
v-for="(menu, index) in menus"
|
||||
:key="menu.name"
|
||||
@mouseenter="openDropdown(index)"
|
||||
@mouseleave="closeDropdown"
|
||||
@focusin="openDropdown(index)"
|
||||
>
|
||||
<router-link
|
||||
:to="menu.url"
|
||||
class="nav-link"
|
||||
:aria-expanded="menu.child.length > 0 ? String(activeDropdownIndex === index) : null"
|
||||
:aria-haspopup="menu.child.length > 0 ? 'true' : null"
|
||||
@keydown.native.enter.prevent="handleNavEnter(menu, index)"
|
||||
@keydown.native.esc.prevent="closeDropdown"
|
||||
>
|
||||
{{ menu.name }}
|
||||
<span v-if="menu.child.length > 0" class="downCaret">▼</span>
|
||||
<span v-if="menu.child.length > 0" class="downCaret"></span>
|
||||
</router-link>
|
||||
<div class="dropDown bottomShadowSegment" v-if="menu.child.length > 0">
|
||||
<div
|
||||
class="dropDown bottomShadowSegment"
|
||||
:class="{ visible: activeDropdownIndex === index }"
|
||||
v-if="menu.child.length > 0"
|
||||
>
|
||||
<router-link :to="sonMenu.url" v-for="sonMenu in menu.child" :key="sonMenu.name"
|
||||
class="dropdown-item">
|
||||
class="dropdown-item"
|
||||
@keydown.native.esc.prevent="closeDropdown">
|
||||
{{ sonMenu.name }}
|
||||
</router-link>
|
||||
</div>
|
||||
@@ -32,35 +53,53 @@
|
||||
<div class="bottom headerBottom mobile">
|
||||
<div class="mobile-nav">
|
||||
<div class="logoCell">
|
||||
<img class="logo" :src="image_paths.mobile_logo" alt="丙维科技">
|
||||
<router-link to="/index" aria-label="返回首页" @click.native="closeMobileMenu">
|
||||
<img class="logo" :src="image_paths.mobile_logo" alt="丙维科技">
|
||||
</router-link>
|
||||
</div>
|
||||
<div class="mobileIconsCell">
|
||||
<img :src="image_paths.hamburger" id="hamburger" alt="菜单">
|
||||
<button
|
||||
type="button"
|
||||
id="hamburger"
|
||||
class="mobile-menu-button"
|
||||
ref="mobileMenuButton"
|
||||
:aria-expanded="mobileMenuOpen ? 'true' : 'false'"
|
||||
aria-controls="mobileMenu"
|
||||
aria-label="打开或关闭菜单"
|
||||
@click.stop="toggleMobileMenu"
|
||||
>
|
||||
<img :src="image_paths.hamburger" alt="">
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 移动端菜单 -->
|
||||
<div id="mobileMenu" class="headerMobileMenu bread">
|
||||
<div class="menuDummy"></div>
|
||||
<div class="menuContent">
|
||||
<div id="mobileMenu" class="headerMobileMenu bread" :class="{ active: mobileMenuOpen }" @click.self="closeMobileMenu">
|
||||
<div class="menuDummy" @click="closeMobileMenu"></div>
|
||||
<div class="menuContent" @click.stop>
|
||||
<ul>
|
||||
<li v-for="menu in menus" :key="menu.name">
|
||||
<router-link :to="menu.url" v-if="menu.child.length === 0">{{ menu.name }}</router-link>
|
||||
<label v-else class="hasSubmenu" style="display:block;">{{ menu.name }}</label>
|
||||
<router-link
|
||||
:to="menu.url"
|
||||
v-if="menu.child.length === 0"
|
||||
ref="mobileMenuLink"
|
||||
@click.native="closeMobileMenu"
|
||||
>{{ menu.name }}</router-link>
|
||||
<span v-else class="menu-label hasSubmenu">{{ menu.name }}</span>
|
||||
<ul class="subMenu" v-if="menu.child.length > 0">
|
||||
<li v-for="sonMenu in menu.child" :key="sonMenu.name">
|
||||
<router-link class="hasSubmenu" :to="sonMenu.url">{{ sonMenu.name }}</router-link>
|
||||
<router-link class="hasSubmenu" :to="sonMenu.url" @click.native="closeMobileMenu">{{ sonMenu.name }}</router-link>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="goBack">
|
||||
<a href="JavaScript:void()" class="linkGoBack flexVerticalCenter">
|
||||
<img :src="image_paths.arrow_back" alt="返回">
|
||||
<button type="button" class="linkGoBack flexVerticalCenter" @click="closeMobileMenuAndScrollTop">
|
||||
<img :src="image_paths.arrow_back" alt="" aria-hidden="true">
|
||||
<span>返回</span>
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -69,7 +108,6 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { common } from '../static/common'
|
||||
import { getMainMenu } from '../config/menu'
|
||||
|
||||
export default {
|
||||
@@ -77,11 +115,12 @@ export default {
|
||||
data() {
|
||||
return {
|
||||
isMiniHeader: false,
|
||||
mobileMenuOpen: false,
|
||||
activeDropdownIndex: null,
|
||||
menus: getMainMenu()
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
// 统一管理图片路径,提高可维护性
|
||||
image_paths() {
|
||||
return {
|
||||
logo: require('@/assets/img/logo.png'),
|
||||
@@ -92,136 +131,70 @@ export default {
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.initHeader()
|
||||
this.initScrollListener()
|
||||
this.initMobileMenu()
|
||||
window.addEventListener('scroll', this.handleScroll)
|
||||
document.addEventListener('keydown', this.handleKeydown)
|
||||
this.handleScroll()
|
||||
},
|
||||
beforeDestroy() {
|
||||
window.removeEventListener('scroll', this.handleScroll)
|
||||
document.removeEventListener('keydown', this.handleKeydown)
|
||||
},
|
||||
methods: {
|
||||
// 封装事件监听器创建,提高代码复用性
|
||||
add_event_listener(selector, event_type, callback, use_id = false) {
|
||||
const element = use_id ? document.getElementById(selector) : document.querySelector(selector);
|
||||
if (element) {
|
||||
element.addEventListener(event_type, callback);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
handleScroll() {
|
||||
this.isMiniHeader = window.pageYOffset > 200
|
||||
},
|
||||
|
||||
// 封装类名操作,提高代码复用性
|
||||
toggle_class(selector, class_name, use_id = false) {
|
||||
const element = use_id ? document.getElementById(selector) : document.querySelector(selector);
|
||||
if (element) {
|
||||
element.classList.toggle(class_name);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
// 封装类名添加,提高代码复用性
|
||||
add_class(selector, class_name, use_id = false) {
|
||||
const element = use_id ? document.getElementById(selector) : document.querySelector(selector);
|
||||
if (element) {
|
||||
element.classList.add(class_name);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
// 封装类名移除,提高代码复用性
|
||||
remove_class(selector, class_name, use_id = false) {
|
||||
const element = use_id ? document.getElementById(selector) : document.querySelector(selector);
|
||||
if (element) {
|
||||
element.classList.remove(class_name);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
initHeader() {
|
||||
// 点击logo返回首页
|
||||
this.add_event_listener(".logoCell .logo", "click", () => {
|
||||
if (window.location.href.indexOf("index") === -1) {
|
||||
window.location.href = "#/index";
|
||||
}
|
||||
});
|
||||
|
||||
// 移动端菜单切换
|
||||
this.add_event_listener("hamburger", "click", () => {
|
||||
this.toggle_class("mobileMenu", "active", true);
|
||||
}, true);
|
||||
|
||||
// 返回按钮
|
||||
this.add_event_listener(".linkGoBack", "click", () => {
|
||||
this.remove_class("mobileMenu", "active", true);
|
||||
// 关闭移动端菜单后滚动到顶部
|
||||
window.scrollTo({
|
||||
top: 0,
|
||||
left: 0,
|
||||
behavior: 'smooth'
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
initScrollListener() {
|
||||
window.addEventListener('scroll', () => {
|
||||
if (window.pageYOffset > 200) {
|
||||
if (!this.isMiniHeader) {
|
||||
this.isMiniHeader = true;
|
||||
this.add_class('.header', 'mini');
|
||||
toggleMobileMenu() {
|
||||
this.mobileMenuOpen = !this.mobileMenuOpen
|
||||
if (this.mobileMenuOpen) {
|
||||
this.$nextTick(() => {
|
||||
const firstLink = this.$refs.mobileMenuLink && this.$refs.mobileMenuLink[0]
|
||||
if (firstLink && firstLink.$el) {
|
||||
firstLink.$el.focus()
|
||||
}
|
||||
} else {
|
||||
if (this.isMiniHeader) {
|
||||
this.isMiniHeader = false;
|
||||
this.remove_class('.header', 'mini');
|
||||
}
|
||||
}
|
||||
});
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
// 初始化移动端菜单
|
||||
initMobileMenu() {
|
||||
// 汉堡菜单点击事件
|
||||
this.add_event_listener("hamburger", "click", () => {
|
||||
this.toggle_class("mobileMenu", "active", true);
|
||||
}, true);
|
||||
|
||||
// 返回按钮点击事件
|
||||
this.add_event_listener(".linkGoBack", "click", () => {
|
||||
this.remove_class("mobileMenu", "active", true);
|
||||
// 关闭移动端菜单后滚动到顶部
|
||||
window.scrollTo({
|
||||
top: 0,
|
||||
left: 0,
|
||||
behavior: 'smooth'
|
||||
});
|
||||
});
|
||||
|
||||
// 点击菜单项后自动关闭菜单
|
||||
const menuLinks = document.querySelectorAll('.headerMobileMenu a');
|
||||
menuLinks.forEach(link => {
|
||||
link.addEventListener('click', () => {
|
||||
this.remove_class("mobileMenu", "active", true);
|
||||
});
|
||||
});
|
||||
|
||||
// 点击菜单外部区域关闭菜单
|
||||
document.addEventListener('click', (e) => {
|
||||
const mobileMenu = document.getElementById('mobileMenu');
|
||||
const hamburger = document.getElementById('hamburger');
|
||||
|
||||
if (mobileMenu && mobileMenu.classList.contains('active') &&
|
||||
!mobileMenu.contains(e.target) &&
|
||||
!hamburger.contains(e.target)) {
|
||||
this.remove_class("mobileMenu", "active", true);
|
||||
closeMobileMenu() {
|
||||
this.mobileMenuOpen = false
|
||||
},
|
||||
closeMobileMenuAndRestoreFocus() {
|
||||
this.closeMobileMenu()
|
||||
this.$nextTick(() => {
|
||||
if (this.$refs.mobileMenuButton) {
|
||||
this.$refs.mobileMenuButton.focus()
|
||||
}
|
||||
});
|
||||
|
||||
// ESC键关闭菜单
|
||||
document.addEventListener('keydown', (e) => {
|
||||
if (e.key === 'Escape') {
|
||||
this.remove_class("mobileMenu", "active", true);
|
||||
})
|
||||
},
|
||||
closeMobileMenuAndScrollTop() {
|
||||
this.closeMobileMenu()
|
||||
window.scrollTo({
|
||||
top: 0,
|
||||
left: 0,
|
||||
behavior: 'smooth'
|
||||
})
|
||||
},
|
||||
handleKeydown(e) {
|
||||
if (e.key === 'Escape') {
|
||||
this.closeDropdown()
|
||||
if (this.mobileMenuOpen) {
|
||||
this.closeMobileMenuAndRestoreFocus()
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
openDropdown(index) {
|
||||
if (this.menus[index] && this.menus[index].child.length > 0) {
|
||||
this.activeDropdownIndex = index
|
||||
}
|
||||
},
|
||||
closeDropdown() {
|
||||
this.activeDropdownIndex = null
|
||||
},
|
||||
handleNavEnter(menu, index) {
|
||||
if (menu.child.length > 0) {
|
||||
this.openDropdown(index)
|
||||
return
|
||||
}
|
||||
this.$router.push(menu.url)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -234,41 +207,41 @@ export default {
|
||||
.header table tbody,
|
||||
.header table tbody tr,
|
||||
.header table tbody tr td {
|
||||
display: block !important;
|
||||
width: auto !important;
|
||||
height: auto !important;
|
||||
border: none !important;
|
||||
padding: 0 !important;
|
||||
margin: 0 !important;
|
||||
display: block;
|
||||
width: auto;
|
||||
height: auto;
|
||||
border: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* 头部基础样式 - 使用 !important 覆盖 common.css */
|
||||
/* 头部基础样式 */
|
||||
.header {
|
||||
position: fixed !important;
|
||||
top: 0 !important;
|
||||
left: 0 !important;
|
||||
right: 0 !important;
|
||||
z-index: 1000 !important;
|
||||
background: rgba(255, 255, 255, 0.95) !important;
|
||||
backdrop-filter: blur(10px) !important;
|
||||
transition: all 0.3s ease !important;
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.1) !important;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 1000;
|
||||
background: rgba(255, 255, 255, 0.92);
|
||||
backdrop-filter: blur(16px);
|
||||
transition: all 0.3s ease;
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
|
||||
/* 覆盖旧表格布局 */
|
||||
display: block !important;
|
||||
height: auto !important;
|
||||
display: block;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.header.mini {
|
||||
background: rgba(255, 255, 255, 0.98) !important;
|
||||
box-shadow: 0 2px 20px rgba(0, 0, 0, 0.1) !important;
|
||||
background: rgba(255, 255, 255, 0.98);
|
||||
box-shadow: 0 12px 32px rgba(16, 24, 40, 0.08);
|
||||
}
|
||||
|
||||
/* 主要导航区域 - 覆盖旧样式 */
|
||||
.bottom {
|
||||
padding: 15px 0 !important;
|
||||
padding: 15px 0;
|
||||
/* 覆盖旧表格布局 */
|
||||
display: block !important;
|
||||
height: auto !important;
|
||||
display: block;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.nav-container {
|
||||
@@ -288,6 +261,11 @@ export default {
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
.logoCell a {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.logoCell .logo:hover {
|
||||
transform: scale(1.05);
|
||||
}
|
||||
@@ -312,20 +290,20 @@ export default {
|
||||
|
||||
.nav-link {
|
||||
display: block;
|
||||
padding: 15px 25px;
|
||||
color: #2c3e50;
|
||||
padding: 14px 22px;
|
||||
color: #1f2937;
|
||||
text-decoration: none;
|
||||
font-weight: 500;
|
||||
font-size: 16px;
|
||||
transition: all 0.3s ease;
|
||||
border-radius: 8px;
|
||||
border-radius: 6px;
|
||||
position: relative;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.nav-link:hover {
|
||||
color: #3498db;
|
||||
background: rgba(52, 152, 219, 0.1);
|
||||
color: #2563eb;
|
||||
background: rgba(37, 99, 235, 0.08);
|
||||
}
|
||||
|
||||
.nav-link::after {
|
||||
@@ -335,7 +313,7 @@ export default {
|
||||
left: 50%;
|
||||
width: 0;
|
||||
height: 2px;
|
||||
background: #3498db;
|
||||
background: #2563eb;
|
||||
transition: all 0.3s ease;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
@@ -352,7 +330,7 @@ export default {
|
||||
transform: translateX(-50%);
|
||||
background: white;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.15);
|
||||
box-shadow: 0 18px 42px rgba(16, 24, 40, 0.14);
|
||||
padding: 15px 0;
|
||||
min-width: 200px;
|
||||
opacity: 0;
|
||||
@@ -362,7 +340,9 @@ export default {
|
||||
border: 1px solid rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.nav-item:hover .dropDown {
|
||||
.nav-item:hover .dropDown,
|
||||
.nav-item:focus-within .dropDown,
|
||||
.dropDown.visible {
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
transform: translateX(-50%) translateY(0);
|
||||
@@ -379,8 +359,8 @@ export default {
|
||||
}
|
||||
|
||||
.dropdown-item:hover {
|
||||
background: rgba(52, 152, 219, 0.1);
|
||||
color: #3498db;
|
||||
background: rgba(37, 99, 235, 0.08);
|
||||
color: #2563eb;
|
||||
padding-left: 30px;
|
||||
}
|
||||
|
||||
@@ -388,12 +368,17 @@ export default {
|
||||
.downCaret {
|
||||
display: inline-block;
|
||||
margin-left: 5px;
|
||||
width: 7px;
|
||||
height: 7px;
|
||||
border-right: 1.5px solid currentColor;
|
||||
border-bottom: 1.5px solid currentColor;
|
||||
transform: rotate(45deg) translateY(-2px);
|
||||
transition: transform 0.3s ease;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.nav-item:hover .downCaret {
|
||||
transform: rotate(180deg);
|
||||
.nav-item:hover .downCaret,
|
||||
.nav-item:focus-within .downCaret {
|
||||
transform: rotate(225deg) translateY(-1px);
|
||||
}
|
||||
|
||||
/* 移动端导航 */
|
||||
@@ -410,10 +395,19 @@ export default {
|
||||
#hamburger {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
background: transparent;
|
||||
cursor: pointer;
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
#hamburger img {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#hamburger:hover {
|
||||
transform: scale(1.1);
|
||||
}
|
||||
@@ -434,7 +428,13 @@ export default {
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.menuDummy {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
}
|
||||
|
||||
.menuContent {
|
||||
position: relative;
|
||||
background: white;
|
||||
width: 80%;
|
||||
height: 100%;
|
||||
@@ -452,7 +452,7 @@ export default {
|
||||
}
|
||||
|
||||
.menuContent a,
|
||||
.menuContent label {
|
||||
.menuContent .menu-label {
|
||||
display: block;
|
||||
padding: 15px;
|
||||
color: #2c3e50;
|
||||
@@ -463,9 +463,9 @@ export default {
|
||||
}
|
||||
|
||||
.menuContent a:hover,
|
||||
.menuContent label:hover {
|
||||
background: rgba(52, 152, 219, 0.1);
|
||||
color: #3498db;
|
||||
.menuContent .menu-label:hover {
|
||||
background: rgba(37, 99, 235, 0.08);
|
||||
color: #2563eb;
|
||||
}
|
||||
|
||||
.subMenu {
|
||||
@@ -484,45 +484,50 @@ export default {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
width: 100%;
|
||||
padding: 15px;
|
||||
border: 0;
|
||||
background: transparent;
|
||||
color: #6c757d;
|
||||
text-decoration: none;
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.linkGoBack:hover {
|
||||
color: #3498db;
|
||||
color: #2563eb;
|
||||
}
|
||||
|
||||
/* 响应式设计 */
|
||||
@media (max-width: 768px) {
|
||||
.desktop {
|
||||
display: none !important;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.mobile {
|
||||
display: block !important;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.header .content {
|
||||
padding: 0 1em !important;
|
||||
padding: 0 1em;
|
||||
}
|
||||
|
||||
body {
|
||||
padding-top: 100px !important;
|
||||
padding-top: 100px;
|
||||
}
|
||||
|
||||
.nav-container {
|
||||
gap: 1rem !important;
|
||||
gap: 1rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 769px) {
|
||||
.mobile {
|
||||
display: none !important;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.desktop {
|
||||
display: block !important;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.nav-container {
|
||||
@@ -554,7 +559,7 @@ export default {
|
||||
|
||||
/* 确保内容不被遮挡 */
|
||||
body {
|
||||
padding-top: 120px !important;
|
||||
padding-top: 120px;
|
||||
}
|
||||
|
||||
/* 使用逻辑属性实现更好的间距 */
|
||||
@@ -564,6 +569,6 @@ body {
|
||||
|
||||
/* 使用逻辑属性实现更好的边框 */
|
||||
.header {
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.1) !important;
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user