<template>
|
<div class="tabs-contain">
|
<div
|
class="tab-item active-tab"
|
v-if="currentPage && (currentPage != '/empty' || currentPage != '/')"
|
>
|
<div class="title">
|
{{ pageName(currentPage) }}
|
</div>
|
<i class="el-icon-close icon-close" @click="remove(currentPage)" />
|
</div>
|
<div class="others">
|
<div
|
:class="['posA', { 'left-shadow': !isLeft, 'right-shadow': !isEnd }]"
|
ref="container"
|
>
|
<div
|
class="inner"
|
ref="inner"
|
:style="{ transform: 'translateX(' + translateX + 'px)' }"
|
>
|
<div
|
class="tab-item"
|
v-for="(page, idx) in list"
|
:key="'list_' + idx"
|
>
|
<div class="title" @click="onTabClick(page)">
|
{{ pageName(page) }}
|
</div>
|
<i class="el-icon-close icon-close" @click="remove(page)" />
|
</div>
|
</div>
|
</div>
|
</div>
|
<div class="btn-grp" v-if="needScroll">
|
<div
|
:class="['btn', 'el-icon-caret-left', { disabled: isLeft }]"
|
@click="scrollLeft"
|
></div>
|
<div
|
:class="['btn', 'el-icon-caret-right', { disabled: isEnd }]"
|
@click="scrollRight"
|
></div>
|
</div>
|
</div>
|
</template>
|
|
<script>
|
export default {
|
name: "TabsBar",
|
props: {
|
vnode: {
|
type: Function,
|
default: () => {},
|
},
|
},
|
watch: {
|
$route(newRoute) {
|
// debugger;
|
this.activePage = newRoute.path;
|
const page = this.pageList.find((item) => item.path === newRoute.path);
|
if (page) {
|
page.fullPath = newRoute.fullPath;
|
} else if (!page) {
|
// 如果新增的是文件结果或对比页面 则清除同类
|
if (newRoute.name == "result" || newRoute.name == 'compare') {
|
// 清除缓存
|
const clearPages = this.pageList.filter(
|
(item) => item.name == "result" || item.name == 'compare'
|
);
|
this.$bus.$emit(
|
"clearCaches",
|
clearPages.map((item) => item.cachedKey)
|
);
|
this.pageList = this.pageList.filter(
|
(item) => !clearPages.includes(item)
|
);
|
}
|
/////////////////////
|
// 添加新签
|
this.pageList.push(this.createPage(newRoute));
|
}
|
this.$nextTick(() => {
|
this.setCachedKey(newRoute);
|
});
|
},
|
pageList(n) {
|
let hasFile = n.some((v) => ["compare", "result"].includes(v.name));
|
this.$bus.$emit("checkCloseAll", hasFile);
|
},
|
},
|
computed: {
|
list() {
|
return this.pageList.filter(
|
(v) => v.path != this.activePage && v.path != "/" && v.path != "/empty"
|
);
|
},
|
currentPage() {
|
// console.log(this.activePage, "activePage====");
|
return this.pageList.filter(
|
(v) => v.path == this.activePage && v.path != "/" && v.path != "/empty"
|
)[0];
|
},
|
isLeft() {
|
return this.translateX == 0;
|
},
|
isEnd() {
|
this.needScroll;
|
let containerW = this.$refs.container
|
? this.$refs.container.clientWidth
|
: 0;
|
let innerW = this.$refs.inner ? this.$refs.inner.clientWidth : 0;
|
// console.log(this.translateX, containerW, innerW, '-=-==-=-=-=-');
|
return containerW >= innerW + this.translateX;
|
},
|
},
|
data() {
|
return {
|
pageList: [],
|
activePage: "",
|
needScroll: false,
|
translateX: 0,
|
};
|
},
|
components: {},
|
methods: {
|
changePage(key) {
|
this.activePage = key;
|
const page = this.pageList.find((item) => item.path === key);
|
this.$router.push(page.fullPath);
|
},
|
createPage(route) {
|
let title = "";
|
if (route.name == "result") {
|
title = route.params && route.params.filename;
|
} else {
|
title = route.meta.title;
|
}
|
return {
|
keyPath: route.matched[route.matched.length - 1].path,
|
fullPath: route.fullPath,
|
loading: false,
|
path: route.path,
|
name: route.name,
|
title,
|
query: route.query,
|
params: route.params,
|
};
|
},
|
pageName(page) {
|
// console.log(page, "pageName");
|
return page.title;
|
},
|
/**
|
* 添加监听器
|
*/
|
addListener() {
|
window.addEventListener("resize", this.checkScroll);
|
},
|
/**
|
* 移出监听器
|
*/
|
removeListener() {
|
window.removeEventListener("resize", this.checkScroll);
|
},
|
clearCache(page) {
|
page._init_ = false;
|
this.$bus.$emit("clearCaches", [page.cachedKey]);
|
},
|
/**
|
* 设置页面缓存的key
|
* @param route 页面对应的路由
|
*/
|
setCachedKey(route) {
|
const page = this.pageList.find((item) => item.path === route.path);
|
// page.unclose = route.meta && route.meta.page && (route.meta.page.closable === false)
|
if (!page._init_) {
|
// TODO
|
const vnode = this.vnode();
|
page.cachedKey = vnode.key + vnode.componentOptions.Ctor.cid;
|
page._init_ = true;
|
}
|
},
|
remove(page) {
|
// if (this.pageList.length === 1) {
|
// return this.$message.warning('最后一个了');
|
// }
|
const { path, title } = page;
|
|
let index = this.pageList.findIndex((item) => item.path === path);
|
|
let remove = this.pageList.splice(index, 1);
|
this.$bus.$emit(
|
"clearCaches",
|
remove.map((page) => page.cachedKey)
|
);
|
if (path === this.activePage) {
|
this.pageList.sort((a, b) => (b.path == "/empty" ? -1 : 0));
|
this.activePage = this.pageList.length ? this.pageList[0].path : "/";
|
const nextPage = this.pageList.length
|
? this.pageList[0]
|
: { path: "/" };
|
if ("result" == nextPage.name) {
|
this.$router.push({
|
path: "/result/" + nextPage.title,
|
query: nextPage.query,
|
});
|
this.$bus.$emit("chartResize");
|
} else {
|
this.$router.push({ path: nextPage.path, query: nextPage.query });
|
// this.$router.push(this.activePage);
|
}
|
}
|
this.checkScroll();
|
},
|
closeAll() {
|
// 清除缓存
|
const clearPages = this.pageList.filter((item) => item.name == "result");
|
this.$bus.$emit(
|
"clearCaches",
|
clearPages.map((item) => item.cachedKey)
|
);
|
this.pageList = this.pageList.filter(
|
(item) => !clearPages.includes(item)
|
);
|
this.pageList.sort((a, b) => (b.path == "/empty" ? -1 : 0));
|
const nextPage = this.pageList.length ? this.pageList[0] : {};
|
this.activePage = nextPage.path || "/";
|
// 判断跳转
|
this.$router.push({ path: nextPage.path, query: nextPage.query });
|
// this.$router.push(this.activePage);
|
},
|
onTabClick(page) {
|
// console.log("onTabClick");
|
const { path, name, query, title } = page;
|
this.activePage = path;
|
// const page = this.pageList.find((item) => item.path === path);
|
if ("result" == name) {
|
this.$router.push({
|
path: "/result/" + title,
|
query,
|
});
|
this.$bus.$emit("chartResize");
|
} else {
|
this.$router.push({ path, query });
|
// this.$router.push(this.activePage);
|
}
|
},
|
// onClose(path) {
|
// this.pageList = this.pageList.filter((v) => v.path != path);
|
// this.activePage = this.pageList.length ? this.pageList[0].path : "";
|
// },
|
checkScroll() {
|
this.$nextTick(() => {
|
let container = this.$refs.container;
|
let inner = this.$refs.inner;
|
let containerW = container.clientWidth;
|
let innerW = inner.clientWidth;
|
this.needScroll = containerW < innerW;
|
if (this.translateX < 0 && containerW - this.translateX > innerW) {
|
this.translateX = containerW - innerW < 0 ? containerW - innerW : 0;
|
}
|
});
|
},
|
scrollLeft() {
|
if (this.isLeft) {
|
return false;
|
}
|
let innerW = this.$refs.inner.clientWidth;
|
let containerW = this.$refs.container.clientWidth;
|
let x = containerW > 600 ? containerW * 0.9 : containerW;
|
if (this.translateX + x >= 0) {
|
x = -this.translateX;
|
}
|
this.translateX += x;
|
},
|
scrollRight() {
|
if (this.isEnd) {
|
return false;
|
}
|
let containerW = this.$refs.container.clientWidth;
|
let innerW = this.$refs.inner.clientWidth;
|
let x = containerW > 600 ? containerW * 0.9 : containerW;
|
if (containerW - this.translateX + x > innerW) {
|
x = innerW + this.translateX - containerW;
|
}
|
this.translateX -= x;
|
},
|
},
|
|
mounted() {
|
this.addListener();
|
this.$bus.$on("checkScroll", this.checkScroll);
|
this.$bus.$on("closeFile", () => {
|
if (this.currentPage) {
|
this.remove(this.currentPage);
|
}
|
});
|
this.$bus.$on("closeAll", this.closeAll);
|
},
|
};
|
</script>
|
|
<style lang="less" scoped>
|
.tabs-contain {
|
height: 32px;
|
box-shadow: 0 1px 4px -2px #333;
|
align-items: center;
|
background: #ddd;
|
display: flex;
|
.tab-item {
|
position: relative;
|
align-self: flex-end;
|
border: 1px solid #1aafea;
|
border-radius: 5px 5px 0 0;
|
padding: 6px 26px 0 4px;
|
cursor: pointer;
|
&.active-tab {
|
background: #1aafea;
|
}
|
.icon-close {
|
position: absolute;
|
width: 14px;
|
height: 14px;
|
font-size: 10px;
|
line-height: 14px;
|
text-align: center;
|
right: 4px;
|
top: 4px;
|
border-radius: 50%;
|
background: rgba(122, 122, 122, 0.6);
|
color: #fff;
|
&:hover {
|
background: rgba(255, 39, 39, 0.6);
|
}
|
}
|
}
|
.others {
|
flex: 1;
|
align-self: stretch;
|
position: relative;
|
.posA {
|
position: absolute;
|
left: 0;
|
right: 0;
|
top: 0;
|
bottom: 0;
|
overflow: hidden;
|
display: flex;
|
align-items: flex-end;
|
&.left-shadow::before {
|
content: "";
|
position: absolute;
|
left: 0;
|
top: 0;
|
bottom: 0;
|
box-shadow: 0 0 1px #333;
|
}
|
&.right-shadow::after {
|
content: "";
|
position: absolute;
|
right: 0;
|
top: 0;
|
bottom: 0;
|
box-shadow: 0 0 1px #333;
|
}
|
.inner {
|
white-space: nowrap;
|
text-align: left;
|
transition: transform 300ms;
|
.tab-item {
|
display: inline-block;
|
border: 1px #ccc solid;
|
// min-width: 160px;
|
}
|
}
|
}
|
}
|
.btn-grp {
|
align-self: center;
|
.btn {
|
display: inline-block;
|
cursor: pointer;
|
font-size: 22px;
|
&.disabled {
|
background: #eee;
|
color: #aaa;
|
cursor: not-allowed;
|
}
|
}
|
}
|
}
|
</style>
|