This repository has been archived on 2025-09-14. You can view files and clone it, but cannot push or open issues or pull requests.
Files
nezha-nezha-fronted/nezha-fronted/src/components/cli/consoleNew.vue
2022-12-14 17:36:52 +08:00

330 lines
12 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<style scoped>
.console{
height: 100%;
padding:5px 5px;
background-color: black;
position: relative;
}
</style>
<template>
<div :id="'ternimalContainer'+idIndex" class="console">
<div :id="'terminal'+idIndex" style="height: 100%"></div>
<fileDirectory :host="host" v-clickoutside="closeFileDir" :uuid="terminal.uuid" v-show="fileDirectoryShow" @close="showFileDir(false)" :fileDirectoryShow="fileDirectoryShow" ref="fileDirectory"/>
</div>
</template>
<script>
import Terminal from '../common/js/Xterm'
import fileDirectory from './fileDirectory'
export default {
name: 'console',
components: {
fileDirectory
},
props: {
terminal: { },
terminalType: { default: '1' },
idIndex: {
type: Number,
default: 0
},
isFullScreen: {
type: Boolean,
default: false
},
fontSize: {}
},
data () {
return {
term: null,
terminalSocket: null,
termimalRows: 15,
termimalHeight: 270,
topMenuHeight: 30,
dragHeigh: 8,
minRow: 1,
fontSpaceHeight: 2, // 一行高度=fontSize+fontSpaceHeight
obj: {
id: 2
},
isInit: false,
successBackContent: 'Connecting to',
failBackContent: 'Sorry',
connectFailContent: 'Connection failed',
welcomeBackContent: 'Welcome',
psdCont: 'password: ',
conFinish: false,
conSuccessNum: 0,
inputSecret: false,
userName: '',
fileDirectoryShow: false,
host: ''
}
},
watch: {
},
methods: {
prompt (term) {
term.write('\r\n ')// term.write('\r\n~$ ');
},
resize (consoleHeigt, consoleWidth) {
this.term.fit()
this.resizeServiceConsole()
},
resizeServiceConsole () {
const consoleBox = document.getElementById('ternimalContainer' + this.idIndex)
const width = document.body.clientWidth// 可视宽度
const height = parseInt(consoleBox.offsetHeight)
const winStyle = {
width: width,
height: height - 100,
cols: this.term.cols, // cols和rows在resizeConsole方法已经设置
rows: this.term.rows
}
this.$post('terminal/resize', winStyle).then(response => {
if (response.code === 200) {
this.term.fit()
} else {
this.$message.error(response.msg)
}
})
},
focusConsole () {
this.term.focus()
},
beforeCreate () {
let rows = this.termimalRows
// const consoleBox = document.getElementById('ternimalContainer' + this.idIndex)
const height = document.body.clientHeight// 高度
// consoleBox.style.height = `${height - 120}px`
rows = (height - this.topMenuHeight) / (this.fontSize + this.fontSpaceHeight)
rows = parseInt(rows)
const terminalContainer = document.getElementById('terminal' + this.idIndex)
this.term = new Terminal({
rows: rows, // 15行大概300px高无法设置heigh只能设置rows
cursorStyle: 'block', // 光标样式 null | 'block' | 'underline' | 'bar'
disableStdin: false, // 是否应禁用输入
fontSize: this.fontSize
})
this.term.open(terminalContainer)
this.term.focus()
const params = {
width: this.terminal.width,
height: this.terminal.height,
cols: this.terminal.cols,
rows: this.terminal.rows,
host: this.$loadsh.get(this.terminal, 'custom.host', ''),
port: this.$loadsh.get(this.terminal, 'custom.port', ''),
assetId: this.$loadsh.get(this.terminal, 'assetId', ''),
accountId: this.$loadsh.get(this.terminal, 'accountId', ''),
authProtocol: this.$loadsh.get(this.terminal, 'custom.authProtocol', ''),
authProtocolPort: this.$loadsh.get(this.terminal, 'custom.authProtocolPort', ''),
authType: this.$loadsh.get(this.terminal, 'custom.authType', ''),
authUsername: this.$loadsh.get(this.terminal, 'custom.authUsername', ''),
authPin: this.$loadsh.get(this.terminal, 'custom.authPin', ''),
authPriKey: this.$loadsh.get(this.terminal, 'custom.authPriKey', ''),
authUserTip: this.$loadsh.get(this.terminal, 'custom.authUserTip', ''),
authPinTip: this.$loadsh.get(this.terminal, 'custom.authPinTip', '')
}
this.$post('/terminal/login', params).then(res => {
if (res.code == 200) {
this.terminal.uuid = res.data.uuid
this.$forceUpdate()
this.terminal.userName = res.data.authUsername + '@' + res.data.host
this.host = res.data.host
this.create()
} else {
this.terminal.uuid = res.data.uuid
this.terminal.userName = res.data.authUsername + '@' + res.data.host
this.host = res.data.host
params.name = this.terminal.name
this.$emit('loginFail', params)
this.$message.error(res.msg)
}
})
},
create () {
const that = this
const token = localStorage.getItem('nz-token')
let baseUrl = JSON.parse(JSON.stringify(this.$axios.defaults.baseURL))
const protocol = window.location.protocol.indexOf('https') > -1 ? 'wss' : 'ws'
if (baseUrl.startsWith('/')) {
baseUrl = `${protocol}://` + window.location.host + baseUrl
} else {
baseUrl = baseUrl.replace('http://', 'ws://').replace('https://', 'wss://')
}
let url = ''
this.terminal.height = document.body.clientHeight - 100
if (this.terminal.type === 'asset') {
url = baseUrl + '/terminal.ws?width=' + this.terminal.width + '&height=' + this.terminal.height + '&cols=' + this.terminal.cols + '&rows=' + this.terminal.rows + '&token=' + token + '&assetId=' + this.terminal.assetId + '&accountId=' + this.terminal.accountId + '&uuid=' + this.terminal.uuid
} else if (this.terminal.type === 'custom') {
url = baseUrl + '/terminal.ws?width=' + this.terminal.width + '&height=' + this.terminal.height + '&cols=' + this.terminal.cols + '&rows=' + this.terminal.rows + '&token=' + token + '&accountId=' + this.terminal.accountId + '&uuid=' + this.terminal.uuid
Object.keys(this.terminal.custom).forEach(key => {
if (this.terminal.custom[key]) {
url += '&' + key + '=' + this.terminal.custom[key]
}
})
}
this.terminalSocket = new WebSocket(url)
// 连接成功onclose
this.terminalSocket.onopen = () => {
this.terminal.isLogin = true
this.isInit = true
}
// 登录后,你输入的内容从后台服务返回
this.term.on('data', function (data) {
/*
let code = data.charCodeAt(0);
if(code==13){
}else {
//that.term.write(data);
} */
})
// 返回
this.terminalSocket.onmessage = function (evt) {
let backContent = evt.data
const welComIndex = backContent.indexOf(that.welcomeBackContent)
if (welComIndex > -1) { // 无服务器信息只与nezha进行了连接
const connectResult = {
title: '',
color: 1
}
that.$emit('refreshConsoleTitle', connectResult)// 1:grey 2 green 3 red
} else {
const successContentIndex = backContent.indexOf(that.successBackContent)
if (successContentIndex > -1) {
// that.conFinish = true;
const startIndex = successContentIndex + that.successBackContent.length + 1
backContent = backContent.substring(startIndex)
const endIndex = backContent.indexOf('\r\n')
const title = backContent.substring(0, endIndex)
const connectResult = {
title: title,
color: 2
}
that.$emit('refreshConsoleTitle', connectResult)// 1:grey 2 green 3 red
} else { // 失败
const failContentIndex = backContent.indexOf(that.failBackContent)
const connectFailIndex = backContent.indexOf(that.connectFailContent)
if (failContentIndex > -1) {
// that.conFinish = true;
const connectResult = {
title: '',
color: 3
}
that.$emit('refreshConsoleTitle', connectResult)// 1:grey 2 green 3 red
} else if (connectFailIndex > -1) {
const connectResult = {
title: '',
color: 3
}
that.$emit('refreshConsoleTitle', connectResult)// 1:grey 2 green 3 red
}
}
}
}
// 关闭
this.terminalSocket.onclose = () => {
this.terminal.isLogin = false
// 报错sorry的还没来得及看信息就关闭
// this.$emit("closeConsole",this.terminal.name);//
this.term && this.term.setOption('disableStdin', true)
}
// 错误
this.terminalSocket.onerror = (e) => {
this.terminal.isLogin = false
}
// 选中 复制
this.term.on('selection', function () {})
this.term.attachCustomKeyEventHandler(function (ev) { })
this.term.attach(this.terminalSocket)
this.term._initialized = true
this.term.fit()// 自适应大小(使终端的尺寸和几何尺寸适合于终端容器的尺寸) 只是width
this.$nextTick(() => { // 解决进入全屏和退出全屏是底部隐藏
this.setFontSize(this.fontSize)
})
},
closeSocket () {
if (this.terminalSocket) {
this.terminalSocket.close()
this.terminalSocket = ''
}
if (this.term) {
this.term.destroy()
}
// 初始化console的高度
this.conFinish = false
},
setFontSize (fontSize) {
this.term && this.term.setOption('fontSize', fontSize)
const consoleBox = document.getElementById('ternimalContainer' + this.idIndex)
const width = document.body.clientWidth// 可视宽度
let height = parseInt(consoleBox.offsetHeight)
if (height == null || !height) { height = this.termimalHeight }
const winStyle = {
width: width,
height: height,
cols: this.term.cols, // cols和rows在resizeConsole方法已经设置
rows: this.term.rows
}
// 调整终端可视区域高度
// document.getElementsByClassName('xterm-screen')[this.idIndex].style.height = height - 30 + 'px'
this.$nextTick(() => {
this.term.resize(this.term.cols, this.term.rows)
this.$post('terminal/resize', winStyle).then(response => {
if (response.code === 200) {
this.term.fit()
} else {
this.$message.error(response.msg)
}
})
})
},
reconnect () {
this.terminal.isLogin = false
this.closeSocket()
this.term.off('selection')
this.term.off('data')
this.beforeCreate()
},
closeFileDir () {
this.showFileDir(false)
},
showFileDir (show) {
if (JSON.stringify(show) == JSON.stringify(this.fileDirectoryShow)) {
return
}
if (show) {
this.fileDirectoryShow = show
}
let animationClass = ''
animationClass = show ? 'backInRight' : 'backOutRight'
this.animateCSS(this.$refs.fileDirectory.$el, animationClass).then((message) => {
this.fileDirectoryShow = show
})
},
enterStr (message) {
if (this.terminalSocket && this.terminal.isLogin) {
this.terminalSocket.send(message)
setTimeout(()=>{
this.terminalSocket.send('\n')
}, 100)
}
}
},
mounted () {
this.beforeCreate()
},
beforeDestroy () {
this.closeSocket()
this.term.off('selection')
this.term.off('data')
}
}
</script>
<style scoped lang="scss">
</style>