Skip to content

Commit 8701a04

Browse files
committed
增加tab栏右键菜单
1 parent 8a4c56f commit 8701a04

File tree

2 files changed

+120
-3
lines changed

2 files changed

+120
-3
lines changed

web/src/components/Tabs.vue

+119-2
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,14 @@
1010
<terminal :id="'Terminal' + index" :ref="item.name"></terminal>
1111
</el-tab-pane>
1212
</el-tabs>
13+
<div v-show="contextMenuVisible">
14+
<ul :style="{left:left+'px',top:top+'px'}" class="contextmenu">
15+
<li><el-button type="text" @click="closeAllTabs()" size="mini">关闭所有</el-button></li>
16+
<li><el-button type="text" @click="closeOtherTabs('left')" size="mini">关闭左边</el-button></li>
17+
<li><el-button type="text" @click="closeOtherTabs('right')" size="mini">关闭右边</el-button></li>
18+
<li><el-button type="text" @click="closeOtherTabs('other')" size="mini">关闭其他</el-button></li>
19+
</ul>
20+
</div>
1321
</div>
1422
</template>
1523

@@ -24,10 +32,87 @@ export default {
2432
data () {
2533
return {
2634
termList: [],
27-
currentTerm: ''
35+
currentTerm: '',
36+
currentTermIndex: 0,
37+
menuTab: '',
38+
contextMenuVisible: false,
39+
left: '',
40+
top: ''
41+
}
42+
},
43+
watch: {
44+
contextMenuVisible() {
45+
if (this.contextMenuVisible) {
46+
document.body.addEventListener('click', this.closeContextMenu)
47+
} else {
48+
document.body.removeEventListener('click', this.closeContextMenu)
49+
}
50+
}
51+
},
52+
mounted() {
53+
// 使用原生js 为单个dom绑定鼠标右击事件
54+
const tabTop = document.body.getElementsByClassName('el-tabs__nav-scroll')
55+
for (let i = 0; i < tabTop.length; ++i) {
56+
tabTop[i].oncontextmenu = this.openContextMenu
2857
}
2958
},
3059
methods: {
60+
closeAllTabs() {
61+
this.termList = []
62+
},
63+
closeOtherTabs(par) {
64+
let currMenuIndex = 0
65+
for (;currMenuIndex < this.termList.length; ++currMenuIndex) {
66+
if (this.termList[currMenuIndex].name === this.menuTab) {
67+
break
68+
}
69+
}
70+
const setCurrentTerm = () => {
71+
this.currentTermIndex = currMenuIndex
72+
const tab = this.termList[currMenuIndex]
73+
this.currentTerm = tab.name
74+
document.title = tab.label
75+
this.$store.commit('SET_TAB', tab.label)
76+
this.$refs[`${tab.name}`][0].setSSH()
77+
}
78+
switch (par) {
79+
case 'left':
80+
// 删除左侧tab标签
81+
if (this.currentTermIndex < currMenuIndex) {
82+
setCurrentTerm()
83+
}
84+
this.termList.splice(0, currMenuIndex)
85+
break
86+
case 'right':
87+
// 删除右侧tab标签
88+
if (this.currentTermIndex > currMenuIndex) {
89+
setCurrentTerm()
90+
}
91+
this.termList.splice(currMenuIndex + 1, this.termList.length)
92+
break
93+
case 'other':
94+
// 删除其他所有tab标签
95+
if (this.currentTermIndex !== currMenuIndex) {
96+
setCurrentTerm()
97+
}
98+
this.termList = this.termList.filter(tab => tab.name === this.menuTab)
99+
break
100+
}
101+
this.closeContextMenu()
102+
},
103+
closeContextMenu() {
104+
this.contextMenuVisible = false
105+
},
106+
openContextMenu(e) {
107+
e.preventDefault() // 防止默认菜单弹出
108+
const obj = e.srcElement ? e.srcElement : e.target
109+
if (obj.id) {
110+
this.menuTab = obj.id.substr(4)
111+
this.contextMenuVisible = true
112+
this.left = e.clientX
113+
this.top = 20
114+
}
115+
},
31116
genID(length) {
32117
return Number(Math.random().toString().substr(3, length) + Date.now()).toString(36)
33118
},
@@ -41,11 +126,18 @@ export default {
41126
label: sshInfo.host
42127
})
43128
this.currentTerm = this.termList[this.termList.length - 1].name
129+
this.currentTermIndex = this.termList.length - 1
44130
},
45131
clickTab(tab) {
46132
this.$refs[`${tab.name}`][0].setSSH()
47133
document.title = tab.label
48134
this.$store.commit('SET_TAB', tab.label)
135+
for (let i = 0; i < this.termList.length; ++i) {
136+
if (this.termList[i].name === this.currentTerm) {
137+
this.currentTermIndex = i
138+
break
139+
}
140+
}
49141
},
50142
removeTab(targetName) {
51143
const tabs = this.termList
@@ -68,5 +160,30 @@ export default {
68160
</script>
69161

70162
<!-- Add "scoped" attribute to limit CSS to this component only -->
71-
<style scoped>
163+
<style scoped lang="scss">
164+
.contextmenu {
165+
width: 100px;
166+
margin: 0;
167+
border: 1px solid #ccc;
168+
background: #fff;
169+
z-index: 3000;
170+
position: absolute;
171+
list-style-type: none;
172+
padding: 5px 0;
173+
border-radius: 4px;
174+
font-size: 14px;
175+
color: #333;
176+
box-shadow: 2px 2px 3px 0 rgba(0, 0, 0, 0.2);
177+
li {
178+
margin: 0;
179+
padding: 0px 22px;
180+
}
181+
li:hover {
182+
background: #f2f2f2;
183+
cursor: pointer;
184+
}
185+
li button{
186+
color: #2c3e50;
187+
}
188+
}
72189
</style>

web/src/components/Terminal.vue

+1-1
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,8 @@ export default {
7878
})
7979
this.ws = null
8080
this.ssh.password = ''
81-
heartCheck.stop()
8281
}
82+
heartCheck.stop()
8383
self.resetClose = false
8484
}
8585
this.ws.onerror = e => {

0 commit comments

Comments
 (0)