mirror of
https://gitee.com/beijing_hongye_huicheng/lilishop-ui.git
synced 2026-08-06 10:57:26 +08:00
manager 升级到vue3
This commit is contained in:
@@ -1,31 +1,24 @@
|
||||
<template>
|
||||
<div class="foot">
|
||||
<Row type="flex" justify="space-around" class="help">
|
||||
<el-row justify="space-around" class="help">
|
||||
<a class="item" :href="config.website" target="_blank">帮助</a>
|
||||
<a class="item" :href="config.website" target="_blank">隐私</a>
|
||||
<a class="item" :href="config.website" target="_blank">条款</a>
|
||||
</Row>
|
||||
<Row type="flex" justify="center" class="copyright">
|
||||
</el-row>
|
||||
<el-row justify="center" class="copyright">
|
||||
Copyright © {{ year }} - Present
|
||||
<a
|
||||
:href="config.website"
|
||||
class="href"
|
||||
target="_blank"
|
||||
style="margin: 0 5px"
|
||||
>{{ config.title }}</a
|
||||
>
|
||||
</Row>
|
||||
<a :href="config.website" class="href" target="_blank" style="margin: 0 5px">{{ config.title }}</a>
|
||||
</el-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
const config = require("@/config/index");
|
||||
export default {
|
||||
// name: "footer",
|
||||
data() {
|
||||
return {
|
||||
config,
|
||||
year: new Date().getFullYear(), // 年
|
||||
year: new Date().getFullYear(),
|
||||
};
|
||||
},
|
||||
};
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
<template>
|
||||
<div>
|
||||
<Row class="header">
|
||||
<el-row class="header">
|
||||
<img :src="domainLogo" class="logo" width="220px" />
|
||||
</Row>
|
||||
</el-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getBaseSite } from "@/api/common.js";
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
@@ -22,44 +23,35 @@ export default {
|
||||
!localStorage.getItem("icontitle_expiration_time")
|
||||
) {
|
||||
this.getSite();
|
||||
} else if (new Date() > localStorage.getItem("icontitle_expiration_time")) {
|
||||
this.getSite();
|
||||
} else {
|
||||
// 如果缓存过期,则获取最新的信息
|
||||
if (new Date() > localStorage.getItem("icontitle_expiration_time")) {
|
||||
this.getSite();
|
||||
return;
|
||||
} else {
|
||||
this.domainLogo = localStorage.getItem("icon");
|
||||
let link =
|
||||
document.querySelector("link[rel*='icon']") ||
|
||||
document.createElement("link");
|
||||
link.type = "image/x-icon";
|
||||
link.href = localStorage.getItem("icon");
|
||||
link.rel = "shortcut icon";
|
||||
document.getElementsByTagName("head")[0].appendChild(link);
|
||||
window.document.title = localStorage.getItem("title") + " - 运营后台";
|
||||
}
|
||||
this.domainLogo = localStorage.getItem("icon");
|
||||
this.applyFavicon(localStorage.getItem("icon"));
|
||||
window.document.title = localStorage.getItem("title") + " - 运营后台";
|
||||
}
|
||||
},
|
||||
applyFavicon(href) {
|
||||
let link =
|
||||
document.querySelector("link[rel*='icon']") ||
|
||||
document.createElement("link");
|
||||
link.type = "image/x-icon";
|
||||
link.href = href;
|
||||
link.rel = "shortcut icon";
|
||||
document.getElementsByTagName("head")[0].appendChild(link);
|
||||
},
|
||||
getSite() {
|
||||
//获取domainLogo
|
||||
getBaseSite().then((res) => {
|
||||
const { domainLogo, domainIcon, siteName } = JSON.parse(res.result.settingValue);
|
||||
const { domainLogo, domainIcon, siteName } = JSON.parse(
|
||||
res.result.settingValue
|
||||
);
|
||||
this.domainLogo = domainLogo;
|
||||
// 过期时间
|
||||
var expirationTime = new Date().setHours(new Date().getHours() + 1);
|
||||
// 存放过期时间
|
||||
const expirationTime = new Date().setHours(new Date().getHours() + 1);
|
||||
localStorage.setItem("icontitle_expiration_time", expirationTime);
|
||||
// 存放信息
|
||||
localStorage.setItem("icon", domainLogo);
|
||||
localStorage.setItem("domainIcon", domainIcon);
|
||||
localStorage.setItem("title", siteName);
|
||||
let link =
|
||||
document.querySelector("link[rel*='icon']") ||
|
||||
document.createElement("link");
|
||||
link.type = "image/x-icon";
|
||||
link.href = domainLogo;
|
||||
link.rel = "shortcut icon";
|
||||
document.getElementsByTagName("head")[0].appendChild(link);
|
||||
this.applyFavicon(domainIcon || domainLogo);
|
||||
window.document.title = siteName + " - 运营后台";
|
||||
});
|
||||
},
|
||||
|
||||
@@ -1,24 +1,29 @@
|
||||
<template>
|
||||
<div class="lang-icon">
|
||||
<Dropdown @on-click="langChange">
|
||||
<Icon type="md-globe" size="26"/>
|
||||
<DropdownMenu slot="list">
|
||||
<DropdownItem name="zh-CN">简体中文</DropdownItem>
|
||||
<DropdownItem name="en-US">English</DropdownItem>
|
||||
</DropdownMenu>
|
||||
</Dropdown>
|
||||
<el-dropdown @command="langChange">
|
||||
<el-icon :size="26"><Platform /></el-icon>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item command="zh-CN">简体中文</el-dropdown-item>
|
||||
<el-dropdown-item command="en-US">English</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { Platform } from "@element-plus/icons-vue";
|
||||
|
||||
export default {
|
||||
name: "langSwitch",
|
||||
components: { Platform },
|
||||
methods: {
|
||||
langChange(v) {
|
||||
this.$i18n.locale = v;
|
||||
this.$store.commit("switchLang", v);
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
|
||||
@@ -1,81 +1,98 @@
|
||||
<template>
|
||||
<div class="message-con">
|
||||
<Dropdown trigger="click">
|
||||
|
||||
<a href="javascript:void(0)">
|
||||
<el-dropdown trigger="click" popper-class="todo-dropdown" @command="navigateTo">
|
||||
<a href="javascript:void(0)" class="message-link">
|
||||
{{ value > 0 ? "有" + value + "条待办事项" : "无待办事项" }}
|
||||
<Icon v-if="value!=0" type="ios-arrow-down"></Icon>
|
||||
<el-icon v-if="value != 0"><ArrowDown /></el-icon>
|
||||
</a>
|
||||
<DropdownMenu v-if="value!=0" slot="list">
|
||||
<DropdownItem v-if="res.balanceCash" @click.native="navigateTo('deposit')">
|
||||
<Badge :count="res.balanceCash">待处理预存款提现申请 </Badge>
|
||||
</DropdownItem>
|
||||
<DropdownItem v-if="res.complain" @click.native="navigateTo('orderComplaint')">
|
||||
<Badge :count="res.complain">待处理投诉审核 </Badge>
|
||||
</DropdownItem>
|
||||
<DropdownItem v-if="res.distributionCash" @click.native="navigateTo('distributionCash')">
|
||||
<Badge :count="res.distributionCash">待处理分销商提现申请 </Badge>
|
||||
</DropdownItem>
|
||||
<DropdownItem v-if="res.goods" @click.native="navigateTo('applyGoods')">
|
||||
<Badge :count="res.goods">待处理商品审核 </Badge>
|
||||
</DropdownItem>
|
||||
<DropdownItem v-if="res.refund" @click.native="navigateTo('afterSaleOrder')">
|
||||
<Badge :count="res.refund">待处理售后申请 </Badge>
|
||||
</DropdownItem>
|
||||
<DropdownItem v-if="res.store" @click.native="navigateTo('shopAuth')">
|
||||
<Badge :count="res.store">待处理店铺入驻审核 </Badge>
|
||||
</DropdownItem>
|
||||
<DropdownItem v-if="res.waitPayBill" @click.native="navigateTo('accountStatementBill')">
|
||||
<Badge :count="res.waitPayBill">待与商家对账</Badge>
|
||||
</DropdownItem>
|
||||
<div></div>
|
||||
</DropdownMenu>
|
||||
</Dropdown>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu v-if="value != 0">
|
||||
<el-dropdown-item v-if="res.balanceCash" command="deposit">
|
||||
<el-badge :value="res.balanceCash">待处理预存款提现申请</el-badge>
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item v-if="res.complain" command="orderComplaint">
|
||||
<el-badge :value="res.complain">待处理投诉审核</el-badge>
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item v-if="res.distributionCash" command="distributionCash">
|
||||
<el-badge :value="res.distributionCash">待处理分销商提现申请</el-badge>
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item v-if="res.goods" command="applyGoods">
|
||||
<el-badge :value="res.goods">待处理商品审核</el-badge>
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item v-if="res.refund" command="afterSaleOrder">
|
||||
<el-badge :value="res.refund">待处理售后申请</el-badge>
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item v-if="res.store" command="shopAuth">
|
||||
<el-badge :value="res.store">待处理店铺入驻审核</el-badge>
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item v-if="res.waitPayBill" command="accountStatementBill">
|
||||
<el-badge :value="res.waitPayBill">待与商家对账</el-badge>
|
||||
</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ArrowDown } from "@element-plus/icons-vue";
|
||||
|
||||
export default {
|
||||
name: "messageTip",
|
||||
data() {
|
||||
return {
|
||||
value: 0, // 消息数量
|
||||
empty: false, // 是否为空
|
||||
};
|
||||
},
|
||||
components: { ArrowDown },
|
||||
props: {
|
||||
res: {
|
||||
type: null,
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.init();
|
||||
computed: {
|
||||
value() {
|
||||
let count = 0;
|
||||
const r = this.res || {};
|
||||
Object.keys(r).forEach((k) => {
|
||||
if (r[k]) count += r[k];
|
||||
});
|
||||
return count;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
navigateTo(name) {
|
||||
this.$router.push({
|
||||
name,
|
||||
});
|
||||
},
|
||||
init() {
|
||||
Object.keys(this.res).forEach((item) => {
|
||||
this.value = parseInt(this.value) + parseInt(this.res[item]);
|
||||
});
|
||||
this.$router.push({ name });
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
::v-deep .ivu-select-dropdown {
|
||||
text-align: left;
|
||||
}
|
||||
.message-con {
|
||||
margin-right: 10px;
|
||||
}
|
||||
::v-deep .ivu-dropdown-item{
|
||||
padding: 7px 20px !important;
|
||||
}
|
||||
::v-deep .ivu-badge-count{
|
||||
right: -10px !important;
|
||||
|
||||
<style scoped>
|
||||
.message-link {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<style>
|
||||
.todo-dropdown .el-dropdown-menu__item {
|
||||
min-width: 150px;
|
||||
padding: 6px 36px 6px 16px;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.todo-dropdown .el-dropdown-menu__item + .el-dropdown-menu__item {
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.todo-dropdown .el-badge {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.todo-dropdown .el-badge__content.is-fixed {
|
||||
right: 4px;
|
||||
top: 8px;
|
||||
transform: translateY(-50%) translateX(50%);
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
201
manager/src/views/main-parts/page-breadcrumb.vue
Normal file
201
manager/src/views/main-parts/page-breadcrumb.vue
Normal file
@@ -0,0 +1,201 @@
|
||||
<template>
|
||||
<el-breadcrumb separator=">" class="page-breadcrumb">
|
||||
<el-breadcrumb-item
|
||||
v-for="(item, idx) in items"
|
||||
:key="idx"
|
||||
>
|
||||
<a
|
||||
v-if="idx < items.length - 1 && item.target"
|
||||
class="bc-link"
|
||||
@click.prevent="go(item.target)"
|
||||
>
|
||||
{{ item.title }}
|
||||
</a>
|
||||
<span v-else :class="{ 'is-current': idx === items.length - 1 }">
|
||||
{{ item.title }}
|
||||
</span>
|
||||
</el-breadcrumb-item>
|
||||
</el-breadcrumb>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { otherRouter } from "@/router/router";
|
||||
|
||||
const stripLayout = (name) => (name || "").replace(/__layout$/, "");
|
||||
|
||||
// 详情/二级页面归属的「列表/父页面」name 映射
|
||||
const PARENT_MAP = {
|
||||
"member-detail": "memberList",
|
||||
"order-detail": "orderList",
|
||||
"after-order-detail": "afterSale",
|
||||
"order-complaint-detail": "orderComplaint",
|
||||
"shop-detail": "shopList",
|
||||
"shop-operation": "shopList",
|
||||
"bill-detail": "bill",
|
||||
"goods-detail": "manager-goods",
|
||||
"goods-parameter-edit": "goods-parameter",
|
||||
"add-points-goods": "manager-points-goods",
|
||||
"edit-points-goods": "manager-points-goods",
|
||||
"coupon-receive": "manager-coupon",
|
||||
"add-platform-coupon": "manager-coupon",
|
||||
"edit-platform-coupon": "manager-coupon",
|
||||
"add-coupon-activity": "manager-coupon-activity",
|
||||
"edit-coupon-activity": "manager-coupon-activity",
|
||||
"coupon-activity-info": "manager-coupon-activity",
|
||||
"pintuan-goods": "manager-pintuan",
|
||||
"full-discount-detail": "manager-full-discount",
|
||||
"manager-seckill-add": "manager-seckill",
|
||||
"add-kanJia-activity-goods": "manager-kanjia",
|
||||
"edit-kanJia-activity-goods": "manager-kanjia",
|
||||
"add-gift-card-cash-activity": "manager-gift-card-cash",
|
||||
"edit-gift-card-cash-activity": "manager-gift-card-cash",
|
||||
"gift-card-cash-records": "manager-gift-card-cash",
|
||||
"gift-card-cash-batch-credentials": "manager-gift-card-cash",
|
||||
};
|
||||
|
||||
const findFirstLeaf = (group) => {
|
||||
if (!group || !Array.isArray(group.children) || !group.children.length) {
|
||||
return null;
|
||||
}
|
||||
const first = group.children.find((c) => c && c.name) || group.children[0];
|
||||
return stripLayout(first?.name) || null;
|
||||
};
|
||||
|
||||
export default {
|
||||
name: "pageBreadcrumb",
|
||||
computed: {
|
||||
items() {
|
||||
const route = this.$route;
|
||||
if (!route || !route.name || route.name === "home_index") {
|
||||
return [{ title: "首页" }];
|
||||
}
|
||||
return this.buildChain(stripLayout(route.name));
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
go(target) {
|
||||
if (!target || !target.name) return;
|
||||
if (this.$route.name === target.name) return;
|
||||
this.$router.push(target);
|
||||
},
|
||||
findInMenu(name) {
|
||||
const menuList = this.$store.state.app.menuList || [];
|
||||
for (const grp of menuList) {
|
||||
for (const child of grp.children || []) {
|
||||
if (stripLayout(child.name) === name) {
|
||||
return { group: grp, child };
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
},
|
||||
routerEntry(name) {
|
||||
if (Array.isArray(otherRouter.children)) {
|
||||
return otherRouter.children.find((c) => c.name === name);
|
||||
}
|
||||
return null;
|
||||
},
|
||||
topItem() {
|
||||
const navList = this.$store.state.app.navList || [];
|
||||
const menuList = this.$store.state.app.menuList || [];
|
||||
const currNavTitle = this.$store.state.app.currNavTitle;
|
||||
const firstName =
|
||||
this.$route.meta && this.$route.meta.firstRouterName;
|
||||
|
||||
let topTitle = currNavTitle;
|
||||
if (firstName) {
|
||||
const top = navList.find((n) => n.name === firstName);
|
||||
if (top) topTitle = top.title;
|
||||
}
|
||||
if (!topTitle) return null;
|
||||
|
||||
let target = null;
|
||||
if (menuList && menuList.length) {
|
||||
const leafName = findFirstLeaf(menuList[0]);
|
||||
if (leafName) target = { name: leafName };
|
||||
}
|
||||
return { title: topTitle, target };
|
||||
},
|
||||
buildChain(name, depth = 0) {
|
||||
if (depth > 6) return [];
|
||||
|
||||
const inMenu = this.findInMenu(name);
|
||||
if (inMenu) {
|
||||
const list = [];
|
||||
const top = this.topItem();
|
||||
if (top) list.push(top);
|
||||
const groupLeaf = findFirstLeaf(inMenu.group);
|
||||
list.push({
|
||||
title: inMenu.group.title,
|
||||
target: groupLeaf ? { name: groupLeaf } : null,
|
||||
});
|
||||
list.push({ title: inMenu.child.title });
|
||||
return list;
|
||||
}
|
||||
|
||||
const parentName = PARENT_MAP[name];
|
||||
const entry = this.routerEntry(name);
|
||||
const selfTitle = entry?.title
|
||||
? entry.title
|
||||
: (this.$route.meta && this.$route.meta.title
|
||||
? String(this.$route.meta.title).replace(/\s*-\s*.+$/, "")
|
||||
: "");
|
||||
|
||||
if (parentName) {
|
||||
const parentChain = this.buildChain(parentName, depth + 1).map(
|
||||
(it, idx, arr) =>
|
||||
idx === arr.length - 1
|
||||
? { title: it.title, target: { name: parentName } }
|
||||
: it
|
||||
);
|
||||
if (selfTitle) parentChain.push({ title: selfTitle });
|
||||
return parentChain;
|
||||
}
|
||||
|
||||
const list = [];
|
||||
const top = this.topItem();
|
||||
if (top) list.push(top);
|
||||
if (selfTitle) list.push({ title: selfTitle });
|
||||
return list;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.page-breadcrumb {
|
||||
padding: 0 !important;
|
||||
margin: 0 !important;
|
||||
line-height: 44px;
|
||||
font-size: 14px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
:deep(.el-breadcrumb__item) {
|
||||
.el-breadcrumb__inner {
|
||||
color: #606266;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
&:first-child {
|
||||
margin-left: 0 !important;
|
||||
padding-left: 0 !important;
|
||||
}
|
||||
}
|
||||
|
||||
.bc-link {
|
||||
color: #606266;
|
||||
cursor: pointer;
|
||||
text-decoration: none;
|
||||
|
||||
&:hover {
|
||||
color: $theme_color;
|
||||
}
|
||||
}
|
||||
|
||||
.is-current {
|
||||
color: $theme_color;
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,27 +1,32 @@
|
||||
<template>
|
||||
<div class="ivu-shrinkable-menu">
|
||||
<!-- 一级菜单 -->
|
||||
<Menu ref="sideMenu" width="80px" theme="dark" :active-name="currNav" @on-select="selectNav">
|
||||
<MenuItem v-for="(item, i) in navList" :key="i" :name="item.name">
|
||||
{{item.title}}
|
||||
</MenuItem>
|
||||
</Menu>
|
||||
<!-- 二级菜单 -->
|
||||
<Menu
|
||||
ref="childrenMenu"
|
||||
:active-name="$route.name"
|
||||
width="120px"
|
||||
@on-select="changeMenu"
|
||||
<div class="shrinkable-menu">
|
||||
<el-menu
|
||||
class="nav-menu-dark"
|
||||
:default-active="currNav"
|
||||
@select="selectNav"
|
||||
>
|
||||
<template v-for="item in menuList">
|
||||
<MenuGroup :title="item.title" :key="item.id" style="padding-left:0;">
|
||||
<MenuItem :name="menu.name" v-for="menu in item.children" :key="menu.name">
|
||||
{{menu.title}}
|
||||
</MenuItem>
|
||||
</MenuGroup>
|
||||
|
||||
<el-menu-item v-for="(item, i) in navList" :key="i" :index="item.name">
|
||||
{{ item.title }}
|
||||
</el-menu-item>
|
||||
</el-menu>
|
||||
<el-menu
|
||||
:key="currNav"
|
||||
class="sub-menu"
|
||||
:default-active="$route.name"
|
||||
@select="changeMenu"
|
||||
>
|
||||
<template v-for="item in menuList" :key="item.id">
|
||||
<el-menu-item-group :title="item.title">
|
||||
<el-menu-item
|
||||
v-for="menu in item.children"
|
||||
:key="menu.name"
|
||||
:index="menu.name"
|
||||
>
|
||||
{{ menu.title }}
|
||||
</el-menu-item>
|
||||
</el-menu-item-group>
|
||||
</template>
|
||||
</Menu>
|
||||
</el-menu>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -39,60 +44,80 @@ export default {
|
||||
},
|
||||
currNav() {
|
||||
return this.$store.state.app.currNav;
|
||||
}
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
// 监听路由变化
|
||||
$route: {
|
||||
handler: function (val, oldVal) {
|
||||
if (val.meta.firstRouterName && val.meta.firstRouterName !== this.currNav) {
|
||||
this.selectNav(val.meta.firstRouterName)
|
||||
}
|
||||
$route(val) {
|
||||
if (
|
||||
val.meta.firstRouterName &&
|
||||
val.meta.firstRouterName !== this.currNav
|
||||
) {
|
||||
this.selectNav(val.meta.firstRouterName);
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
changeMenu(name) { //二级路由点击
|
||||
this.$router.push({
|
||||
name: name
|
||||
changeMenu(name) {
|
||||
if (!name) return;
|
||||
if (this.$router.hasRoute(name)) {
|
||||
this.$router.push({ name });
|
||||
return;
|
||||
}
|
||||
util.initRouter(this);
|
||||
this.$nextTick(() => {
|
||||
if (this.$router.hasRoute(name)) {
|
||||
this.$router.push({ name });
|
||||
} else {
|
||||
this.$Message.warning("菜单路由未就绪,请刷新页面后重试");
|
||||
}
|
||||
});
|
||||
},
|
||||
selectNav(name) { // 一级路由点击事件
|
||||
selectNav(name) {
|
||||
this.$store.commit("setCurrNav", name);
|
||||
this.setStore("currNav", name);
|
||||
util.initRouter(this);
|
||||
this.$nextTick(()=>{
|
||||
this.$refs.childrenMenu.updateActiveName()
|
||||
})
|
||||
},
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.ivu-shrinkable-menu{
|
||||
height: calc(100% - 60px);
|
||||
width: 200px;
|
||||
display: flex;
|
||||
.shrinkable-menu {
|
||||
height: 100%;
|
||||
width: 200px;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.ivu-btn-text:hover {
|
||||
background-color: rgba(255,255,255,.2) !important;
|
||||
.nav-menu-dark {
|
||||
width: 80px;
|
||||
background-color: #191a23;
|
||||
border-right: none;
|
||||
|
||||
:deep(.el-menu-item) {
|
||||
color: rgba(255, 255, 255, 0.7);
|
||||
justify-content: center;
|
||||
padding: 0 8px !important;
|
||||
text-align: center;
|
||||
line-height: 1.3;
|
||||
height: auto;
|
||||
min-height: 56px;
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
:deep(.el-menu-item.is-active) {
|
||||
background-color: #fff !important;
|
||||
color: $theme_color !important;
|
||||
}
|
||||
}
|
||||
.ivu-menu-dark.ivu-menu-vertical .ivu-menu-item-active:not(.ivu-menu-submenu), .ivu-menu-dark.ivu-menu-vertical .ivu-menu-submenu-title-active:not(.ivu-menu-submenu){
|
||||
background-color: #fff;
|
||||
&:hover{
|
||||
background-color: #fff;
|
||||
}
|
||||
}
|
||||
.ivu-menu-vertical{
|
||||
|
||||
.sub-menu {
|
||||
width: 120px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
.ivu-menu-dark.ivu-menu-vertical .ivu-menu-item-active:not(.ivu-menu-submenu), .ivu-menu-dark.ivu-menu-vertical .ivu-menu-submenu-title-active:not(.ivu-menu-submenu){
|
||||
color: $theme_color;
|
||||
}
|
||||
::v-deep.ivu-menu-vertical .ivu-menu-item-group-title {
|
||||
height: 40px;
|
||||
border-right: none;
|
||||
|
||||
:deep(.el-menu-item-group__title) {
|
||||
padding-left: 16px;
|
||||
line-height: 40px;
|
||||
padding-left: 20px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,31 +1,42 @@
|
||||
|
||||
|
||||
<template>
|
||||
|
||||
<div
|
||||
ref="scrollCon"
|
||||
@DOMMouseScroll="handlescroll"
|
||||
@mousewheel="handlescroll"
|
||||
class="tags-outer-scroll-con"
|
||||
>
|
||||
<ul v-show="visible" :style="{left: contextMenuLeft + 'px', top: contextMenuTop + 'px'}" class="contextmenu">
|
||||
<li v-for="(item, key) of actionList" @click="handleTagsOption(key)" :key="key">{{item}}</li>
|
||||
<ul
|
||||
v-show="visible"
|
||||
:style="{ left: contextMenuLeft + 'px', top: contextMenuTop + 'px' }"
|
||||
class="contextmenu"
|
||||
>
|
||||
<li
|
||||
v-for="(item, key) of actionList"
|
||||
:key="key"
|
||||
@click="handleTagsOption(key)"
|
||||
>
|
||||
{{ item }}
|
||||
</li>
|
||||
</ul>
|
||||
<div ref="scrollBody" class="tags-inner-scroll-body" :style="{left: tagBodyLeft + 'px'}">
|
||||
<transition-group name="taglist-moving-animation">
|
||||
<Tag
|
||||
type="dot"
|
||||
v-for="item in pageTagsList"
|
||||
ref="tagsPageOpened"
|
||||
:key="item.name"
|
||||
:name="item.name"
|
||||
@on-close="closePage"
|
||||
@click.native="linkTo(item)"
|
||||
:closable="item.name=='home_index'?false:true"
|
||||
:color="item.children?(item.children[0].name==currentPageName?'primary':'default'):(item.name==currentPageName?'primary':'default')"
|
||||
@contextmenu.prevent.native="contextMenu(item, $event)"
|
||||
>{{ itemTitle(item) }}</Tag>
|
||||
</transition-group>
|
||||
<div
|
||||
ref="scrollBody"
|
||||
class="tags-inner-scroll-body"
|
||||
:style="{ left: tagBodyLeft + 'px' }"
|
||||
>
|
||||
<el-tag
|
||||
v-for="item in pageTagsList"
|
||||
:key="item.name"
|
||||
:closable="item.name !== 'home_index'"
|
||||
:type="tagType(item)"
|
||||
:effect="isActive(item) ? 'dark' : 'plain'"
|
||||
class="page-tag"
|
||||
size="large"
|
||||
@close="closePage($event, item.name)"
|
||||
@click="linkTo(item)"
|
||||
@contextmenu.prevent="contextMenu(item, $event)"
|
||||
>
|
||||
{{ itemTitle(item) }}
|
||||
</el-tag>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -33,197 +44,137 @@
|
||||
<script>
|
||||
export default {
|
||||
name: "tagsPageOpened",
|
||||
data() {
|
||||
return {
|
||||
currentPageName: this.$route.name, // 当前路由名称
|
||||
tagBodyLeft: 0, // 标签左偏移量
|
||||
visible: false, // 显示操作按钮
|
||||
contextMenuLeft: 0, // 内容左偏移量
|
||||
contextMenuTop: 0, // 内容上偏移量
|
||||
actionList: {
|
||||
others: '关闭其他',
|
||||
clearAll: '关闭所有'
|
||||
},
|
||||
refsTag: [], // 所有已打开标签
|
||||
tagsCount: 1 // 标签数量
|
||||
};
|
||||
},
|
||||
props: {
|
||||
pageTagsList: Array,
|
||||
beforePush: {
|
||||
type: Function,
|
||||
default: item => {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
title() {
|
||||
return this.$store.state.app.currentTitle;
|
||||
default: () => true,
|
||||
},
|
||||
tagsList() {
|
||||
return this.$store.state.app.pageOpenedList;
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
currentPageName: this.$route.name,
|
||||
tagBodyLeft: 0,
|
||||
visible: false,
|
||||
contextMenuLeft: 0,
|
||||
contextMenuTop: 0,
|
||||
actionList: {
|
||||
others: "关闭其他",
|
||||
clearAll: "关闭所有",
|
||||
},
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
isActive(item) {
|
||||
return item.children
|
||||
? item.children[0].name === this.currentPageName
|
||||
: item.name === this.currentPageName;
|
||||
},
|
||||
tagType(item) {
|
||||
return this.isActive(item) ? "primary" : "info";
|
||||
},
|
||||
itemTitle(item) {
|
||||
if (typeof item.title == "object") {
|
||||
if (typeof item.title === "object") {
|
||||
return this.$t(item.title.i18n);
|
||||
} else {
|
||||
return item.title;
|
||||
}
|
||||
return item.title;
|
||||
},
|
||||
closePage(event, name) {
|
||||
let pageOpenedList = this.$store.state.app.pageOpenedList;
|
||||
let lastPageObj = pageOpenedList[0];
|
||||
if (this.currentPageName == name) {
|
||||
let len = pageOpenedList.length;
|
||||
if (this.currentPageName === name) {
|
||||
const len = pageOpenedList.length;
|
||||
for (let i = 1; i < len; i++) {
|
||||
if (pageOpenedList[i].name == name) {
|
||||
if (i < len - 1) {
|
||||
lastPageObj = pageOpenedList[i + 1];
|
||||
} else {
|
||||
lastPageObj = pageOpenedList[i - 1];
|
||||
}
|
||||
if (pageOpenedList[i].name === name) {
|
||||
lastPageObj =
|
||||
i < len - 1 ? pageOpenedList[i + 1] : pageOpenedList[i - 1];
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let tagWidth = event.target.parentNode.offsetWidth;
|
||||
} else if (event && event.target) {
|
||||
const tagWidth = event.target.parentNode?.offsetWidth || 0;
|
||||
this.tagBodyLeft = Math.min(this.tagBodyLeft + tagWidth, 0);
|
||||
}
|
||||
this.$store.commit("removeTag", name);
|
||||
this.$store.commit("closePage", name);
|
||||
pageOpenedList = this.$store.state.app.pageOpenedList;
|
||||
localStorage.pageOpenedList = JSON.stringify(pageOpenedList);
|
||||
if (this.currentPageName == name) {
|
||||
if (this.currentPageName === name) {
|
||||
this.linkTo(lastPageObj);
|
||||
}
|
||||
},
|
||||
linkTo(item) {
|
||||
if (this.$route.name == item.name) {
|
||||
return;
|
||||
}
|
||||
let routerObj = {};
|
||||
routerObj.name = item.name;
|
||||
if (item.argu) {
|
||||
routerObj.params = item.argu;
|
||||
}
|
||||
if (item.query) {
|
||||
routerObj.query = item.query;
|
||||
}
|
||||
if (this.$route.name === item.name) return;
|
||||
const routerObj = { name: item.name };
|
||||
if (item.argu) routerObj.params = item.argu;
|
||||
if (item.query) routerObj.query = item.query;
|
||||
if (this.beforePush(item)) {
|
||||
this.$router.push(routerObj);
|
||||
}
|
||||
},
|
||||
handlescroll(e) {
|
||||
var type = e.type;
|
||||
const type = e.type;
|
||||
let delta = 0;
|
||||
if (type == "DOMMouseScroll" || type == "mousewheel") {
|
||||
if (type === "DOMMouseScroll" || type === "mousewheel") {
|
||||
delta = e.wheelDelta ? e.wheelDelta : -(e.detail || 0) * 40;
|
||||
}
|
||||
let left = 0;
|
||||
if (delta > 0) {
|
||||
left = Math.min(0, this.tagBodyLeft + delta);
|
||||
} else {
|
||||
if ( this.$refs.scrollCon.offsetWidth - 100 < this.$refs.scrollBody.offsetWidth ) {
|
||||
if ( this.tagBodyLeft < -( this.$refs.scrollBody.offsetWidth - this.$refs.scrollCon.offsetWidth + 100 ) ) {
|
||||
left = this.tagBodyLeft;
|
||||
} else {
|
||||
left = Math.max(
|
||||
this.tagBodyLeft + delta,
|
||||
this.$refs.scrollCon.offsetWidth -
|
||||
this.$refs.scrollBody.offsetWidth -
|
||||
100
|
||||
);
|
||||
}
|
||||
} else if (
|
||||
this.$refs.scrollCon.offsetWidth - 100 <
|
||||
this.$refs.scrollBody.offsetWidth
|
||||
) {
|
||||
if (
|
||||
this.tagBodyLeft <
|
||||
-(this.$refs.scrollBody.offsetWidth - this.$refs.scrollCon.offsetWidth + 100)
|
||||
) {
|
||||
left = this.tagBodyLeft;
|
||||
} else {
|
||||
this.tagBodyLeft = 0;
|
||||
left = Math.max(
|
||||
this.tagBodyLeft + delta,
|
||||
this.$refs.scrollCon.offsetWidth -
|
||||
this.$refs.scrollBody.offsetWidth -
|
||||
100
|
||||
);
|
||||
}
|
||||
} else {
|
||||
this.tagBodyLeft = 0;
|
||||
}
|
||||
this.tagBodyLeft = left;
|
||||
},
|
||||
handleTagsOption(type) {
|
||||
if (type == "clearAll") {
|
||||
if (type === "clearAll") {
|
||||
this.$store.commit("clearAllTags");
|
||||
this.$router.push({
|
||||
name: "home_index"
|
||||
});
|
||||
this.$router.push({ name: "home_index" });
|
||||
} else {
|
||||
this.$store.commit("clearOtherTags", this);
|
||||
}
|
||||
this.tagBodyLeft = 0;
|
||||
},
|
||||
moveToView(tag) {
|
||||
if (tag.offsetLeft < -this.tagBodyLeft) {
|
||||
// 标签在可视区域左侧
|
||||
this.tagBodyLeft = -tag.offsetLeft + 10;
|
||||
} else if (
|
||||
tag.offsetLeft + 10 > -this.tagBodyLeft &&
|
||||
tag.offsetLeft + tag.offsetWidth <
|
||||
-this.tagBodyLeft + this.$refs.scrollCon.offsetWidth - 100
|
||||
) {
|
||||
// 标签在可视区域
|
||||
this.tagBodyLeft = Math.min(
|
||||
0,
|
||||
this.$refs.scrollCon.offsetWidth -
|
||||
100 -
|
||||
tag.offsetWidth -
|
||||
tag.offsetLeft -
|
||||
20
|
||||
);
|
||||
} else {
|
||||
// 标签在可视区域右侧
|
||||
this.tagBodyLeft = -(
|
||||
tag.offsetLeft -
|
||||
(this.$refs.scrollCon.offsetWidth - 100 - tag.offsetWidth) +
|
||||
20
|
||||
);
|
||||
}
|
||||
contextMenu(item, e) {
|
||||
this.visible = true;
|
||||
const offsetLeft = this.$el.getBoundingClientRect().left;
|
||||
this.contextMenuLeft = e.clientX - offsetLeft + 10;
|
||||
this.contextMenuTop = e.clientY - 64;
|
||||
},
|
||||
contextMenu (item, e) {
|
||||
this.visible = true
|
||||
const offsetLeft = this.$el.getBoundingClientRect().left
|
||||
this.contextMenuLeft = e.clientX - offsetLeft + 10
|
||||
this.contextMenuTop = e.clientY - 64
|
||||
closeMenu() {
|
||||
this.visible = false;
|
||||
},
|
||||
closeMenu () {
|
||||
this.visible = false
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.refsTag = this.$refs.tagsPageOpened;
|
||||
setTimeout(() => {
|
||||
this.refsTag.forEach((item, index) => {
|
||||
if (this.$route.name == item.name) {
|
||||
let tag = this.refsTag[index].$el;
|
||||
this.moveToView(tag);
|
||||
}
|
||||
});
|
||||
}, 1); // 这里不设定时器就会有偏移bug
|
||||
this.tagsCount = this.tagsList.length;
|
||||
},
|
||||
watch: {
|
||||
$route(to) {
|
||||
this.currentPageName = to.name;
|
||||
this.$nextTick(() => {
|
||||
this.refsTag.forEach((item, index) => {
|
||||
if (to.name == item.name) {
|
||||
let tag = this.refsTag[index].$el;
|
||||
this.moveToView(tag);
|
||||
}
|
||||
});
|
||||
});
|
||||
this.tagsCount = this.tagsList.length;
|
||||
this.tagsCount = this.pageTagsList?.length;
|
||||
},
|
||||
visible (value) {
|
||||
visible(value) {
|
||||
if (value) {
|
||||
document.body.addEventListener('click', this.closeMenu)
|
||||
document.body.addEventListener("click", this.closeMenu);
|
||||
} else {
|
||||
document.body.removeEventListener('click', this.closeMenu)
|
||||
document.body.removeEventListener("click", this.closeMenu);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
@@ -237,7 +188,7 @@ export default {
|
||||
z-index: 11000;
|
||||
list-style-type: none;
|
||||
border-radius: 4px;
|
||||
box-shadow: 2px 2px 3px 0 rgba(0, 0, 0, .1);
|
||||
box-shadow: 2px 2px 3px 0 rgba(0, 0, 0, 0.1);
|
||||
li {
|
||||
margin: 0;
|
||||
padding: 5px 15px;
|
||||
@@ -247,7 +198,25 @@ export default {
|
||||
}
|
||||
}
|
||||
}
|
||||
.ivu-tag-primary, .ivu-tag-primary.ivu-tag-dot .ivu-tag-dot-inner{
|
||||
background: $theme_color;
|
||||
.page-tag {
|
||||
margin-right: 8px;
|
||||
cursor: pointer;
|
||||
height: 28px;
|
||||
padding: 0 12px;
|
||||
border-radius: 4px;
|
||||
font-size: 13px;
|
||||
transition: all 0.2s ease;
|
||||
|
||||
& + .page-tag {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
opacity: 0.85;
|
||||
}
|
||||
|
||||
.el-tag__close {
|
||||
margin-left: 6px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user