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

931 lines
24 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
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>
<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`) ,
},
};
},
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);
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)
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");
if (dropdown.classList.contains("show")) {
dropdown.classList.remove("show");
arrow.classList.remove("up");
}
});
},
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))
}
},
async fetchSignOut() {
const data = await getLogout();
if (data && data.code == 200) {
const lang = this.$i18n.locale;
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() {
this.fetchSignOut();
localStorage.removeItem(`token`);
localStorage.removeItem("username");
localStorage.removeItem("jurisdiction");
this.$addStorageEvent(1, `miningAccountList`, JSON.stringify(""));
this.isLogin = false;
this.isDropdownVisible = false;
},
},
};
</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;
}
.miningAccountTitle:hover {
color: #6e3edb !important;
}
.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;
align-items: center;
height: 100%;
width: 95%;
/* outline: 1px solid red; */
// outline: 1PX solid red;
// padding: 0px 5%;
// padding: 0 5%;
// background: #21A0FF;
}
.logo {
width: 18%;
height: 100%;
display: flex;
justify-content: right;
align-items: center;
font-size: 0.9rem;
img {
width: 100px;
}
}
.topMenu {
width: 80%;
height: 100%;
display: flex;
justify-content: end;
align-items: center;
// background: goldenrod;
.afterLoggingIn {
min-width: 50%;
display: flex;
justify-content: right;
align-items: center;
// 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 {
width: 40%;
li {
margin-left: 1%;
}
.langBox {
display: flex;
justify-content: space-around;
align-items: center;
width: 20%;
}
.register.register {
padding: 1px 30px;
}
.LangLine {
width: 1px;
height: 60%;
background: #ccc;
margin-right: 2%;
}
}
}
.menuBox {
min-width: 42% !important;
height: 100%;
display: flex;
justify-content: end;
align-items: center;
margin: 0%;
// background: #fff;
li {
list-style: none;
// width: calc(100% / 5);
height: 45%;
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
margin-left: 3%;
font-size: 0.9rem;
// transition: all 0.3s linear;
position: relative;
text-align: center;
min-width: 61px;
}
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>
<style lang="scss" >
.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;
}
</style>