You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
260 lines
10 KiB
260 lines
10 KiB
<template>
|
|
<div class="recent_pages">
|
|
<h4><i class="iconfont icon-recent"></i>
|
|
<!-- <ContextMenu>最近访问:</ContextMenu> -->
|
|
最近访问:
|
|
</h4>
|
|
<div class="history_buttons">
|
|
<div class="btn_left" @click="onLeft" :class="{'disabled' : startIndex <= 0 }"><i
|
|
class="iconfont icon-left"></i></div>
|
|
<div class="list_box" ref="box">
|
|
<div class="list" :style="btnListStyle" ref="btnlist">
|
|
<div class="unit" :class="isActive(item) ? 'active' : ''" v-for="item,index in recentPages"
|
|
ref="unit">
|
|
<p class="btn_main" @click="onClickItem(item)" :key="item.path"
|
|
:style="{width:item.title.length*14+'px'}">
|
|
{{item.title}}
|
|
</p>
|
|
<p class="btn_pin" :class="{active:item.isPinned}" @click="onPin(item)"><i></i></p>
|
|
<i class="btn_close iconfont icon-guanbi" @click="onRemoveItem(item)"></i>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="btn_right" @click="onRight"
|
|
:class="{ 'disabled': lastIndex == -1 || lastIndex >= widthArr.length - 1 }"><i
|
|
class="iconfont icon-right"></i></div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
<script>
|
|
import { mapMutations, mapState } from 'vuex';
|
|
import ContextMenu from './ContextMenu.vue';
|
|
export default{
|
|
data(){
|
|
return {
|
|
posiLeft:0, //按钮列表绝对定位的数值
|
|
widthBox:0,
|
|
widthTotal:0,
|
|
lastIndex:-1, //当前能显示的最后一个元素的索引
|
|
startIndex:-1, //当前能显示的第一个元素的索引
|
|
widthArr:[],
|
|
currentIndex : -1
|
|
}
|
|
},
|
|
components:{
|
|
ContextMenu
|
|
},
|
|
computed:{
|
|
...mapState("menu", ["recentPages"]),
|
|
btnListStyle(){
|
|
return {
|
|
left : `${this.posiLeft}px`
|
|
};
|
|
}
|
|
},
|
|
watch:{
|
|
recentPages:{
|
|
handler(newV){
|
|
this.$nextTick(()=>{
|
|
// console.log("触发了Precentage的watch")
|
|
this.widthArr = [];
|
|
this.widthBox = this.$refs["box"].offsetWidth;
|
|
this.widthTotal = this.$refs["btnlist"].offsetWidth;
|
|
let temp = 0;
|
|
newV.forEach((item,index)=>{
|
|
let unitW = this.$refs["unit"][index].offsetWidth;
|
|
temp += unitW;
|
|
this.widthArr[index] = temp;
|
|
if(temp >= this.widthBox && this.lastIndex == -1){
|
|
this.lastIndex = index;
|
|
}
|
|
if(item.active){
|
|
this.currentIndex = index;
|
|
}
|
|
// console.log(this.currentIndex, "currentIndexcurrentIndex")
|
|
// console.log(this.startIndex, "startIndexstartIndex")
|
|
// console.log(this.lastIndex, "lastIndexlastIndex")
|
|
})
|
|
if(this.widthTotal > this.widthBox){
|
|
if (this.currentIndex >= this.lastIndex) {
|
|
this.moveByRight(this.currentIndex);
|
|
} else if (this.currentIndex <= this.startIndex) {
|
|
this.moveByLeft(this.currentIndex);
|
|
}
|
|
}
|
|
|
|
})
|
|
},
|
|
immediate:true,
|
|
deep:true,
|
|
},
|
|
$route:{
|
|
handler(newV){
|
|
this.addRecent({
|
|
title : newV.meta.title,
|
|
path : newV.path
|
|
});
|
|
},
|
|
immediate : true
|
|
}
|
|
},
|
|
mounted(){
|
|
},
|
|
methods:{
|
|
...mapMutations("menu", ["addRecent", "removeRecent","pinRecent"]),
|
|
onClickItem(item){
|
|
this.$route.path != item.path && this.$router.push(item.path);
|
|
},
|
|
onPin(item){
|
|
this.pinRecent(item);
|
|
},
|
|
onRemoveItem(item){
|
|
this.removeRecent(item);
|
|
if(this.$route.path == item.path){
|
|
if(this.recentPages.length){
|
|
this.$router.push(this.recentPages[this.recentPages.length-1].path)
|
|
}else{
|
|
this.$router.push("/")
|
|
}
|
|
}
|
|
},
|
|
isActive(item) {
|
|
return this.$route.path == item.path;
|
|
},
|
|
onLeft(){
|
|
this.moveByLeft();
|
|
},
|
|
onRight(){
|
|
if (this.widthTotal > this.widthBox) {
|
|
this.moveByRight();
|
|
}
|
|
},
|
|
moveByLeft(targetIndex){
|
|
// console.log("左侧动", this.startIndex, targetIndex);
|
|
if (this.startIndex <= 0) {
|
|
return
|
|
}
|
|
if (targetIndex != undefined) {
|
|
this.startIndex = targetIndex;
|
|
} else {
|
|
this.startIndex -= 3;
|
|
}
|
|
if (this.startIndex < 0) {
|
|
this.startIndex = 0;
|
|
}
|
|
if(this.startIndex == 0){
|
|
this.posiLeft = 0;
|
|
}else{
|
|
this.posiLeft = this.widthArr[this.startIndex-1] * -1;
|
|
}
|
|
this.calcLastIndex();
|
|
// console.log(this.posiLeft , "posiLeft++");
|
|
},
|
|
moveByRight(targetIndex){
|
|
// console.log("右侧动", this.lastIndex, targetIndex);
|
|
if(this.lastIndex >= this.widthArr.length - 1){
|
|
return
|
|
}
|
|
if(targetIndex!==undefined){
|
|
this.lastIndex = targetIndex;
|
|
}else{
|
|
this.lastIndex += 3;
|
|
}
|
|
if(this.lastIndex > this.widthArr.length-1){
|
|
this.lastIndex = this.widthArr.length - 1;
|
|
}
|
|
// console.log(targetIndex, this.widthArr.length , "+++========")
|
|
this.posiLeft = this.widthBox - this.widthArr[this.lastIndex];
|
|
this.calcStartIndex();
|
|
},
|
|
calcStartIndex(){
|
|
try{
|
|
this.widthArr.forEach((item,index)=>{
|
|
if(item > -1*this.posiLeft){
|
|
this.startIndex = index;
|
|
throw new Error('找到startIndex,退出循环')
|
|
}
|
|
})
|
|
}catch(e){
|
|
// console.log(e);
|
|
}
|
|
},
|
|
calcLastIndex(){
|
|
try{
|
|
this.widthArr.forEach((item, index) => {
|
|
if (item > (this.widthBox - this.posiLeft)) { //posiLeft是个负值
|
|
this.lastIndex = index;
|
|
// console.log(this.lastIndex , "this.lastIndex lastIndex lastIndex lastIndex")
|
|
throw new Error('找到lastIndex,退出循环')
|
|
}
|
|
})
|
|
}catch(e){
|
|
// console.log(e);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
<style lang="scss" scoped>
|
|
.recent_pages{
|
|
display: flex; flex-direction: row; align-items:stretch; padding: 0 20px;
|
|
h4{ width: 110px; height: 32px; line-height: 32px; text-align: center; margin: 0; padding: 0; font-weight: bold; color: #3de8ff; display: flex; align-items: center; justify-content: center;
|
|
.iconfont{ margin-right: 3px;}
|
|
}
|
|
.history_buttons {
|
|
flex: 1;
|
|
display: flex;
|
|
flex-direction: row;
|
|
.btn_left, .btn_right{ width: 26px; height: 30px; background-color: #048145;background-image: linear-gradient(180deg, #005c79 0%, #009bcc 100%);
|
|
border:1px solid #009bcc; border-radius: 4px; display: flex; justify-content: center; align-items: center;
|
|
&.disabled{ background-image: linear-gradient(0deg, #999 0%, #777 100%); border:1px solid #999; color: #ccc;}
|
|
}
|
|
.btn_left{ margin-right: 4px;}
|
|
.btn_right{ margin-left: 4px;}
|
|
.list_box{ flex: 1; position: relative; width: 0; overflow: hidden; margin:0;
|
|
.list{ position: absolute; left: 0; top:0; display: flex; flex-direction: row; transition: all ease-in-out 0.5s;
|
|
.unit {
|
|
position: relative;
|
|
height: 30px;
|
|
padding: 0 3px;
|
|
|
|
.btn_main {
|
|
cursor: pointer;
|
|
background-image: linear-gradient(180deg, #005c79 0%, #009bcc 100%);
|
|
border:1px solid #009bcc;
|
|
border-radius: 4px;
|
|
height: 28px;
|
|
text-align: center;
|
|
line-height: 28px; font-weight: bold; font-size: 14px; box-sizing: content-box;
|
|
padding: 0 18px 0 12px; word-break: keep-all; white-space: nowrap;
|
|
}
|
|
&.active {
|
|
.btn_main {
|
|
background-image: linear-gradient(180deg,#048145 0%, #078b58 100%);
|
|
border:1px solid #03a9b1;
|
|
}
|
|
}
|
|
.btn_pin{
|
|
position: absolute;
|
|
left:0;
|
|
bottom:0;
|
|
width:16px; height: 10px;
|
|
display: flex; align-items: center; justify-content: center;
|
|
i{
|
|
display: block;
|
|
width:6px; height: 6px; border-radius: 3px;
|
|
}
|
|
&.active i{ background-color: #FA0;}
|
|
}
|
|
.btn_close {
|
|
position: absolute;
|
|
right: 6px;
|
|
top:8px;
|
|
font-size: 12px; color: #3de8ff;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
</style>
|