Files
m2pool_web_frontend/mining-pool/src/components/header.vue

1147 lines
31 KiB
Vue
Raw Normal View History

<template>
<div class="headerBox" :class="{ whiteBg: key !== `/` }">
<div class="header">
<div class="logo" @click="handelJump('/')">
<img src="../assets/img/logo.png" alt="logo图片" />
</div>
<!--|| $route.path !== `/${$i18n.locale}` -->
<div class="topMenu">
<div class="nav" v-show="isLogin &&( $route.path.includes(`reportBlock`) || $route.name == `Home` ) ">
<div class="nav-item" id="menu1" @click.stop="toggleDropdown">
<img
class="itemImg"
:src="activeItem.imgUrl"
:alt="activeItem.label"
/>
<span style="text-transform: capitalize;"
>
{{ activeItem.label }}</span
>
<i class="arrow"></i>
<div class="dropdown">
<div
class="option"
v-for="item in currencyList"
:key="item.value"
@click.stop="changeMenuName($event, item)"
:class="{optionActive: item.value === activeItem.value}"
>
<img class="dropdownCoin" :src="item.imgUrl" :alt="item.label">
<div class="dropdownText">{{ item.label }}</div>
</div>
</div>
</div>
</div>
<ul class="menuBox afterLoggingIn" v-show="isLogin">
<li
class="home"
:class="{
active:
$route.path === `/${$i18n.locale}` ||
$route.path === `/${$i18n.locale}/`,
}"
@click="handelJump(`/`)"
>
{{ $t(`home.home`) }}
<div
class="horizontalLine"
:class="{
hidden:
$route.path === `/${$i18n.locale}` ||
$route.path === `/${$i18n.locale}/`,
}"
>
<span class="circular"></span>
<span class="line"></span>
</div>
</li>
<li class="miningAccount" v-show="isLogin">
<el-menu
active-text-color="#6E3EDB"
class="el-menu-demo"
mode="horizontal"
>
<el-submenu index="888888">
<span
slot="title"
class="miningAccountTitle"
style="color: #000"
:class="{
active: $route.path.includes(
`/${$i18n.locale}/miningAccount`
),
}"
>{{ $t(`home.accountCenter`) }}</span
>
<el-submenu
:index="item.coin"
v-for="item in miningAccountList"
:key="item.coin"
>
<template slot="title">
<img style="width: 20px" :src="item.img" :alt="item.coin" />
{{ item.title }}</template
>
<el-menu-item
:index="subItem.id.toString()"
@click.native="handelJumpAccount(item, subItem, item.coin)"
v-for="subItem in item.children"
:key="subItem.id"
>
{{ subItem.account }}</el-menu-item
>
</el-submenu>
<el-menu-item
style="font-size: 0.9rem"
class="signOut"
@click.native="handelSignOut"
index="999999"
>
&nbsp;&nbsp; {{ $t(`user.signOut`) }}</el-menu-item
>
</el-submenu>
</el-menu>
<div
class="horizontalLine"
:class="{ hidden: $route.path == `/miningAccount` }"
>
<span class="circular"></span>
<span class="line"></span>
</div>
</li>
<li
class="reportBlock"
:class="{
active: $route.path.includes(`/${$i18n.locale}/reportBlock`),
}"
@click="handelJump(`reportBlock`)"
>
{{ $t(`home.reportBlock`) }}
<div
class="horizontalLine"
:class="{
hidden: $route.path.includes(`/${$i18n.locale}/reportBlock`),
}"
>
<span class="circular"></span>
<span class="line"></span>
</div>
</li>
<!-- <li>{{$t(`home.file`)}}</li> -->
<!-- <li>{{$t(`home.rate`)}}</li> -->
<li
class="personalCenter"
:class="{
active: $route.path.includes(`/${$i18n.locale}/personalCenter`),
}"
@click="handelJump('personalCenter')"
>
{{ $t(`home.personalCenter`) }}
<div
class="horizontalLine"
:class="{
hidden:
$route.path.includes(`/${$i18n.locale}/personalCenter`) ||
$route.path.includes(
`/${$i18n.locale}/personalCenter/personalMining`
),
}"
>
<span class="circular"></span>
<span class="line"></span>
</div>
</li>
<li
class="personalCenter"
:class="{
active: $route.path.includes(`/${$i18n.locale}/workOrderRecords`),
}"
@click="handelJump('workOrderRecords')"
>
{{ $t(`personal.workOrderRecord`) }}
<div
class="horizontalLine"
:class="{ hidden: $route.path.includes(`workOrderRecords`) }"
>
<span class="circular"></span>
<span class="line"></span>
</div>
</li>
<!-- 帮助中心 -->
<li
class="personalCenter"
:class="{
active: $route.path.includes(`/${$i18n.locale}/helpCenter`),
}"
@click="handelJump('helpCenter')"
>
{{ $t(`home.helpCenter`) }}
<div
class="horizontalLine"
:class="{ hidden: $route.path.includes(`helpCenter`) }"
>
<span class="circular"></span>
<span class="line"></span>
</div>
</li>
2025-09-12 16:46:31 +08:00
<!-- 矿机租赁 -->
<li @click="handelMachineLease">
{{ $t(`home.machineLease`) }}
</li>
<!-- 工单管理 -->
<!-- <li
v-show="ManagementShow"
class="personalCenter"
:class="{
active: $route.path.includes(`/${$i18n.locale}/workOrderBackend`),
}"
@click="handelJump('workOrderBackend')"
>
{{ $t(`work.WorkOrderManagement`) }}
<div
class="horizontalLine"
:class="{ hidden: $route.path.includes(`workOrderBackend`) }"
>
<span class="circular"></span>
<span class="line"></span>
</div>
</li> -->
<li class="langBox">
<div class="LangLine"></div>
<el-dropdown>
<span
class="el-dropdown-link"
style="font-size: 0.9rem; color: rgba(0, 0, 0, 1)"
>
<img
style="width: 20px"
src="../assets/img/lang.svg"
alt="lang"
/>
<i class="el-icon-caret-bottom el-icon--right"></i>
</span>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item
style="font-size: 0.8rem; color: rgba(0, 0, 0, 1)"
@click.native="handelLang(`zh`)"
>简体中文</el-dropdown-item
>
<el-dropdown-item
style="font-size: 0.8rem; color: rgba(0, 0, 0, 1)"
@click.native="handelLang(`en`)"
>English</el-dropdown-item
>
</el-dropdown-menu>
</el-dropdown>
</li>
<!-- <li @click="handelDarkMode">/浅模式</li> -->
</ul>
<ul class="menuBox notLoggedIn" v-show="!isLogin">
<li class="login" @click="handelLogin">{{ $t(`user.login`) }}</li>
<li class="register" @click="handelRegister">
{{ $t(`user.register`) }}
</li>
2025-07-18 16:22:28 +08:00
<!-- 帮助中心 -->
<li
class="personalCenter"
style="margin-left: 20px;"
:class="{
active: $route.path.includes(`/${$i18n.locale}/helpCenter`),
}"
@click="handelJump('helpCenter')"
>
{{ $t(`home.helpCenter`) }}
<div
class="horizontalLine"
:class="{ hidden: $route.path.includes(`helpCenter`) }"
>
<span class="circular"></span>
<span class="line"></span>
</div>
</li>
<li class="langBox">
<div class="LangLine"></div>
<el-dropdown>
<span
class="el-dropdown-link"
style="font-size: 0.9rem; color: rgba(0, 0, 0, 1)"
>
<img
style="width: 20px"
src="../assets/img/lang.svg"
alt="lang"
/>
<i class="el-icon-caret-bottom el-icon--right"></i>
</span>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item
style="font-size: 0.8rem; color: rgba(0, 0, 0, 1)"
@click.native="handelLang(`zh`)"
>简体中文</el-dropdown-item
>
<el-dropdown-item
style="font-size: 0.8rem; color: rgba(0, 0, 0, 1)"
@click.native="handelLang(`en`)"
>English</el-dropdown-item
>
</el-dropdown-menu>
</el-dropdown>
</li>
</ul>
</div>
</div>
</div>
</template>
<script>
import { getLogout, getAccountGradeList } from "../api/login";
import { getAccountList } from "../api/personalCenter";
import { getImageUrl } from "../utils/publicMethods";
export default {
computed: {
key() {
return this.$route.path;
},
},
data() {
return {
isLogin: false,
bthText: "English",
token: "",
accountList: [],
miningAccountList: [],
isOrderKey: "",
activeIndex2: "",
isDropdownVisible: false,
activeIndex: "",
jurisdiction: {
roleKey: "",
},
ManagementShow: false,
currencyList: [],
activeItem: {
value: "nexa",
label: "nexa",
imgUrl:getImageUrl(`/img/nexa.png`) ,
},
customerIsOnline: false,
userEmail:"",
};
},
watch: {
token: {
handler(val) {
if (val) {
this.isLogin = true;
} else {
this.isLogin = false;
}
},
immediate: true,
deep: true,
},
accountList: {
handler(val) {},
immediate: true,
deep: true,
},
miningAccountList: {
handler(val) {},
immediate: true,
deep: true,
},
$route(to, from) {
if (to.path !== `/miningAccount`) {
this.activeIndex = "";
}
},
activeItemCoin:{
handler(val){
this.changeMenuName($event,this.activeItem)
},
deep:true,
}
},
mounted() {
this.$addStorageEvent(1, "activeItemCoin", JSON.stringify(this.activeItem));
let valueTaking = localStorage.getItem("token");
this.token = JSON.parse(valueTaking);
let list = localStorage.getItem("accountList");
this.accountList = JSON.parse(list);
let miningAccountList = localStorage.getItem("miningAccountList");
this.miningAccountList = JSON.parse(miningAccountList);
let jurisdiction = localStorage.getItem("jurisdiction");
this.jurisdiction = JSON.parse(jurisdiction);
let currencyList = localStorage.getItem("currencyList");
this.currencyList = JSON.parse(currencyList);
let userEmail = localStorage.getItem("userEmail");
this.userEmail = JSON.parse(userEmail);
window.addEventListener("setItem", () => {
let valueTaking = localStorage.getItem("token");
this.token = JSON.parse(valueTaking);
let list = localStorage.getItem("accountList");
this.accountList = JSON.parse(list);
let miningAccountList = localStorage.getItem("miningAccountList");
this.miningAccountList = JSON.parse(miningAccountList);
let jurisdiction = localStorage.getItem("jurisdiction");
this.jurisdiction = JSON.parse(jurisdiction);
let currencyList = localStorage.getItem("currencyList");
this.currencyList = JSON.parse(currencyList);
let active = localStorage.getItem(`activeItemCoin`)
this.activeItem = JSON.parse(active)
let userEmail = localStorage.getItem("userEmail");
this.userEmail = JSON.parse(userEmail);
if (this.jurisdiction && this.jurisdiction.roleKey == `admin`) {
this.ManagementShow = true;
} else {
this.ManagementShow = false;
}
});
if (this.jurisdiction && this.jurisdiction.roleKey == `admin`) {
this.ManagementShow = true;
} else {
this.ManagementShow = false;
}
// 点击页面其他地方关闭下拉菜单
document.addEventListener("click", function () {
const dropdown = document.querySelector(".dropdown");
const arrow = document.querySelector(".arrow");
2025-06-06 15:31:04 +08:00
try {
if (dropdown.classList.contains("show")) {
dropdown.classList.remove("show");
arrow.classList.remove("up");
}
2025-06-06 15:31:04 +08:00
} catch (error) {
console.log(error)
}
});
},
methods: {
toggleDropdown(e) {
if (!e) return;
const menuItem = e.currentTarget;
const dropdown = menuItem.querySelector(".dropdown");
const arrow = menuItem.querySelector(".arrow");
if (dropdown) {
dropdown.classList.toggle("show");
arrow?.classList.toggle("up");
}
},
changeMenuName(e, item) {
if (!e) return;
e.stopPropagation(); // 阻止事件冒泡
const menuItem = document.getElementById("menu1");
if (!menuItem) return;
this.activeItem = item;
const dropdown = menuItem.querySelector(".dropdown");
const arrow = menuItem.querySelector(".arrow");
dropdown?.classList.remove("show");
arrow?.classList.remove("up");
this.$addStorageEvent(1, "activeItemCoin", JSON.stringify(item));
},
handelDarkMode() {},
async fetchAccountGradeList() {
const data = await getAccountGradeList();
this.miningAccountList = data.data;
this.$addStorageEvent(
1,
`miningAccountList`,
JSON.stringify(this.miningAccountList)
);
},
async fetchAccountList(params) {
const data = await getAccountList(params);
if (data && data.code == 200) {
this.accountList = data.data;
this.$addStorageEvent(
1,
`accountList`,
JSON.stringify(this.accountList)
);
// localStorage.setItem(`accountList`,JSON.stringify(this.accountList))
}
},
// 修改 fetchUserid 方法,添加 token 检查
async fetchUserid(params) {
try {
const res = await getUserid(params);
if (res && res.code == 200) {
this.customerIsOnline = res.data.customerIsOnline;
localStorage.setItem(`customerIsOnline`,JSON.stringify(this.customerIsOnline))
}
} catch (error) {
console.error("获取用户ID失败:", error);
throw error;
}
},
async fetchSignOut() {
const data = await getLogout();
if (data && data.code == 200) {
2025-06-06 15:31:04 +08:00
// 调用 Vuex 的 logout action 清除前端状态
await this.$store.dispatch('logout')
const lang = this.$i18n.locale;
this.fetchUserid({email:this.userEmail})
this.$router.push(`/${lang}`);
}
},
handleDropdownClick() {
this.isDropdownVisible = true;
},
handleCommand(command) {
// 处理命令逻辑
},
handleSelect() {},
handelLogin() {
this.isLogin = true;
const lang = this.$i18n.locale;
this.$router.push(`/${lang}/login`);
},
handelRegister() {
const lang = this.$i18n.locale;
this.$router.push(`/${lang}/register`);
},
handelLogin222() {
this.isLogin = !this.isLogin;
},
handelJump(url) {
try {
const lang = this.$i18n.locale;
// 特殊处理 personalCenter 路由
if (url === "personalCenter") {
// 先跳转到 personalCenter
this.$router
.push(`/${lang}/personalCenter/personalMining`)
// .then(() => {
// // 成功后再跳转到子路由
// this.$router.push(`/${lang}/personalCenter/personalMining`);
// })
.catch((err) => {
if (err.name !== "NavigationDuplicated") {
console.error("Navigation failed:", err);
}
});
return;
}
// 其他路由的处理保持不变
const path = `/${lang}${url === "/" ? "" : "/" + url}`;
this.$router.push(path).catch((err) => {
if (err.name !== "NavigationDuplicated") {
console.error("Navigation failed:", err);
}
});
} catch (error) {
console.error("Navigation error:", error);
this.$message.error(this.$t("common.navigationError"));
}
},
handelJumpAccount(item, subItem, coin) {
const lang = this.$i18n.locale;
let obj = {
ma: subItem.account,
coin: coin,
id: subItem.id,
img: item.img,
};
this.$addStorageEvent(1, "accountItem", JSON.stringify(obj));
this.$router.push({
path: `/${lang}/miningAccount`,
query: { ma: subItem.account + coin },
});
this.isDropdownVisible = false;
},
handelLang(lang) {
try {
const currentPath = this.$route.path;
const oldLang = this.$i18n.locale;
const currentQuery = this.$route.query; // 获取当前的查询参数
// 检查是否是支持的语言
if (!["zh", "en"].includes(lang)) {
throw new Error("Unsupported language");
}
// 更新语言设置
this.$i18n.locale = lang;
localStorage.setItem("lang", lang || 'en');
// 构造新的路由配置
const newPath = currentPath.replace(`/${oldLang}`, `/${lang}`);
// 保持原有查询参数
this.$router.push({
path: newPath,
query: currentQuery // 保留原有的查询参数
}).catch((err) => {
if (err.name !== 'NavigationDuplicated') {
console.error("路由更新失败:", err);
this.$message.error(this.$t("common.langChangeFailed"));
}
});
// 更新HTML的lang属性
document.documentElement.lang = lang;
} catch (error) {
console.error("语言切换失败:", error);
this.$message.error(this.$t("common.langChangeFailed"));
}
},
handelSignOut() {
localStorage.setItem('cs_disconnect_all', Date.now().toString()); //告知客服页面断开连接
this.fetchSignOut();
localStorage.removeItem(`token`);
localStorage.removeItem("username");
localStorage.removeItem("userName");
localStorage.removeItem("userEmail");
localStorage.removeItem("jurisdiction");
this.$addStorageEvent(1, `miningAccountList`, JSON.stringify(""));
this.isLogin = false;
this.isDropdownVisible = false;
},
2025-09-12 16:46:31 +08:00
/**
* 简单的AES加密函数
* @param {string} text - 要加密的文本
* @param {string} secretKey - 密钥
* @returns {string} 加密后的字符串
*/
encryptData(text, secretKey) {
try {
// 使用简单的XOR加密生产环境建议使用更安全的加密库如crypto-js
let encrypted = '';
for (let i = 0; i < text.length; i++) {
encrypted += String.fromCharCode(text.charCodeAt(i) ^ secretKey.charCodeAt(i % secretKey.length));
}
return btoa(encrypted); // Base64编码
} catch (error) {
console.error('加密失败:', error);
return text; // 如果加密失败,返回原文
}
},
/**
* 处理机器租赁跳转携带加密的用户参数
*/
handelMachineLease(){
try {
// 获取当前用户信息和其他需要传递的参数
const token =localStorage.getItem('token') || '';
const userEmail = localStorage.getItem('userEmail') || '';
const language = this.$i18n.locale || 'zh';
const username = localStorage.getItem('username') || '';
// 定义加密密钥(生产环境应该从环境变量或配置文件中获取)
const secretKey = 'mining-pool-secret-key-2024';
// 准备要加密的敏感数据
const sensitiveData = {
token: token,
userEmail: userEmail,
timestamp: Date.now()
};
// 加密敏感数据
const encryptedData = this.encryptData(JSON.stringify(sensitiveData), secretKey);
// 构建带参数的URL敏感数据加密其他数据明文
2025-09-30 14:56:00 +08:00
const baseUrl = "http://18.183.240.108:8080/";
2025-09-12 16:46:31 +08:00
const params = new URLSearchParams({
data: encryptedData, // 加密的敏感数据
language: language,
username: username,
source: 'mining-pool', // 标识来源项目
version: '1.0' // 数据版本,用于兼容性
});
const urlWithParams = `${baseUrl}?${params.toString()}`;
// 当前窗口打开
window.open(urlWithParams, "_self");
// 记录跳转日志(用于调试,不记录敏感信息)
console.log('跳转到机器租赁系统,携带参数:', {
userEmail: userEmail ? '***' : '',
language,
source: 'mining-pool',
encrypted: true
});
} catch (error) {
console.error('跳转机器租赁系统时发生错误:', error);
this.$message.error("加载系统失败 稍后重试");
}
}
},
};
</script>
<style scoped lang="scss">
// 币种下拉框
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.nav {
// position: absolute;
z-index: 1000;
// height: 60px;
// line-height: 60px;
margin-right: 8px;
font-size: 0.9rem;
}
.nav-item {
position: relative;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
padding: 0 10px;
.itemImg{
width: 20px;
margin-right: 5px;
}
.arrow {
margin-left: 5px;
border: solid rgba(0,0,0,0.3);
border-width: 0 1px 1px 0;
display: inline-block;
padding: 3px;
transform: rotate(45deg);
transition: transform 0.3s;
&.up {
transform: rotate(-135deg);
}
}
}
.dropdown {
position: absolute;
top: 47px;
left: 0;
width: 392px;
background: white;
border: 1px solid #eee;
border-radius: 4px;
padding: 3px;
display: none;
flex-wrap: wrap;
gap: 1px;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
z-index: 999999;
&.show {
display: flex;
}
.option {
width: 76px;
height: 80px;
background: #f5f5f5;
// display: flex;
// align-items: center;
// justify-content: center;
cursor: pointer;
transition: all 0.3s;
border-radius: 4px;
// flex-direction: column;
// padding:5px;
// padding-top: 5%;
overflow: hidden;
text-align: center;
padding: 5px;
&:hover {
background: #e8e8e8;
color: #6e3edb;
border:1px solid #9d8ac9;
}
}
.optionActive{
background: #e8e8e8;
color: #6e3edb;
border:1px solid #9d8ac9;
}
}
.dropdownCoin{
width: 32px ;
margin: 0;
}
.dropdownText{
width: 100%;
font-size: 0.8rem;
// word-wrap: break-word;
text-align: center;
margin: 0;
word-break: break-word;
margin-top: 5px;
}
// --------------------------------
.headerBox {
// height: 60PX;
width: 100%;
/* outline: 1px solid red; */
font-size: 0.95rem;
// border-bottom:1PX solid #ccc;
// background-image: url(../assets/img/bktop.png);
// background-position: 60% 8%;
// background-size: cover;
display: flex;
justify-content: center;
}
2025-05-28 15:01:22 +08:00
.miningAccountTitle:hover {
color: #6e3edb !important;
2025-05-28 15:01:22 +08:00
}
.hidden {
display: block;
opacity: 1 !important;
}
.el-menu--horizontal > .el-submenu .el-submenu__title {
color: #000;
}
.el-menu--horizontal {
background: transparent;
}
.el-submenu:hover {
background-color: transparent !important; /* 例如,更改背景颜色 */
}
.el-submenu.is-active:after {
border-bottom: none !important;
border-bottom-color: transparent !important;
border: none !important;
outline: none !important;
}
// .el-menu--horizontal > .el-submenu:hover{
// background: red !important;
// }
.is-order {
background: #21a0ff;
}
.dropdownItem {
display: flex;
align-items: center;
img {
margin-right: 5px;
}
}
.active {
color: #6e3edb !important;
font-weight: 600;
}
.whiteBg {
// background-image: url(../assets/img/bktop.png);
// background-position: 60% 8%;
// background-size: cover;
background: rgba(255, 255, 255, 0.5);
}
.header {
display: flex;
justify-content: space-between; /* 保持logo在左导航在右 */
align-items: center;
height: 100%;
width: 100%;
margin: 0 auto; /* 居中显示 */
padding: 0 2.5%; /* 使用padding替代固定宽度 */
/* outline: 1px solid red; */
// outline: 1PX solid red;
// padding: 0px 5%;
// padding: 0 5%;
// background: #21A0FF;
}
.logo {
flex: 0 0 auto; /* 不伸缩,保持固定大小 */
height: 100%;
display: flex;
justify-content: flex-end; /* 右对齐 */
align-items: center;
font-size: 0.9rem;
width: 300px; /* 固定宽度,给导航留出更多空间 */
img {
width: 100px;
height: auto; /* 保持比例 */
}
}
.topMenu {
flex: 1; /* 占据剩余空间 */
height: 100%;
display: flex;
justify-content: flex-end; /* 右对齐 */
align-items: center;
min-width: 0; /* 允许收缩 */
// background: goldenrod;
.afterLoggingIn {
display: flex;
justify-content: flex-end; /* 右对齐 */
align-items: center;
flex-wrap: nowrap; /* 防止换行 */
width: auto; /* 自适应宽度 */
// background: #6E3EDB;
.langBox {
display: flex;
justify-content: space-around;
align-items: center;
width: 70px;
}
.LangLine {
width: 1px;
height: 60%;
background: #ccc;
margin-right: 8px;
}
li {
position: relative;
}
.horizontalLine {
width: 100%;
// height: 12%;
// background: #21A0FF;
position: absolute;
bottom: -10px;
display: flex;
justify-content: center;
align-items: center;
opacity: 0;
transition: all 0.3s linear;
.circular {
width: 5px;
height: 5px;
background: #6e3edb;
border-radius: 50%;
}
.line {
width: 20px;
height: 5px;
background: #6e3edb;
margin-left: 2px;
border-radius: 22px;
}
}
}
.notLoggedIn {
display: flex;
justify-content: flex-end; /* 右对齐 */
align-items: center;
gap: 12px; /* 增加间距 */
li {
flex: 0 0 auto; /* 不伸缩,保持内容大小 */
white-space: nowrap; /* 防止文字换行 */
padding: 0 6px; /* 减少内边距 */
}
.langBox {
display: flex;
justify-content: space-around;
align-items: center;
width: 20%;
}
.register.register {
2025-09-30 14:56:00 +08:00
padding: 5px 30px;
}
.LangLine {
width: 1px;
height: 60%;
background: #ccc;
margin-right: 2%;
}
}
}
.menuBox {
display: flex;
justify-content: flex-end; /* 右对齐 */
align-items: center;
margin: 0;
gap: 12px; /* 增加间距 */
flex-wrap: nowrap; /* 防止换行 */
// background: #fff;
li {
list-style: none;
height: 45%;
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
font-size: 0.9rem;
position: relative;
text-align: center;
flex: 0 0 auto; /* 不伸缩,保持内容大小 */
white-space: nowrap; /* 防止文字换行 */
padding: 0 6px; /* 减少内边距 */
min-width: auto; /* 移除最小宽度限制 */
}
li:hover {
color: #6e3edb;
font-weight: 600;
}
.login {
padding: 2px 18px;
}
.login:hover {
color: #21a0ff;
border: 1px solid #21a0ff;
border-radius: 10px;
}
.register {
background: #d2c3ea;
border-radius: 25px;
padding: 0px 25px;
}
.register:hover {
color: #000;
color: #fe4886;
}
}
</style>
2025-07-18 16:22:28 +08:00
<style lang="scss" scoped>
.el-submenu__title:hover {
background-color: transparent !important;
background: transparent !important;
color: #6e3edb !important;
}
.el-menu-item.is-active:not(.is-index) {
border-bottom: none !important;
}
.el-submenu__title {
border: none !important;
border-bottom: none !important;
border-bottom-color: transparent !important;
margin-right: 10px;
}
.el-submenu.is-active {
// background: #FE4886;
// display: none !important;
border: none !important;
border-bottom: none !important;
border-bottom-color: transparent !important;
}
.el-menu--horizontal > .el-submenu.is-active .el-submenu__title {
border-bottom: 0px !important;
}
.el-submenu.is-active .el-submenu__title {
border-bottom-color: transparent !important;
}
.el-menu.el-menu--horizontal {
border-bottom: 0px !important;
}
/* 响应式设计 - 小屏幕适配 */
@media (max-width: 768px) {
.header {
padding: 0 1%; /* 减少内边距 */
}
.logo {
min-width: 80px; /* 减少logo最小宽度 */
img {
width: 80px; /* 减小logo尺寸 */
}
}
.menuBox {
gap: 4px; /* 减少间距 */
li {
font-size: 0.8rem; /* 减小字体 */
padding: 0 4px; /* 减少内边距 */
}
}
.topMenu .afterLoggingIn .langBox {
width: 50px; /* 减小语言选择框宽度 */
}
}
/* 超小屏幕 - 隐藏部分菜单项 */
@media (max-width: 480px) {
.menuBox li:not(.home):not(.langBox) {
display: none; /* 只显示首页和语言选择 */
}
.menuBox {
gap: 2px;
li {
font-size: 0.75rem;
padding: 0 2px;
}
}
}
</style>