NEZ-3038 feat:升级 xterm。js的版本

This commit is contained in:
zhangyu
2023-08-10 11:10:12 +08:00
parent 7a42de5cf6
commit 45def99505
10 changed files with 111 additions and 84 deletions

View File

@@ -14340,7 +14340,7 @@
},
"node-sass": {
"version": "4.14.1",
"resolved": "https://registry.npmmirror.com/node-sass/-/node-sass-4.14.1.tgz",
"resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.14.1.tgz",
"integrity": "sha512-sjCuOlvGyCJS40R8BscF5vhVlQjNN069NtQ1gSxyK1u9iqvn6tf7O1R4GNowVZfiZUCRt5MmMs1xd+4V/7Yr0g==",
"dev": true,
"requires": {
@@ -14851,7 +14851,7 @@
},
"pace-js": {
"version": "1.2.4",
"resolved": "https://registry.npmmirror.com/pace-js/-/pace-js-1.2.4.tgz",
"resolved": "https://registry.npmjs.org/pace-js/-/pace-js-1.2.4.tgz",
"integrity": "sha512-qnCxtvUoY9yHId0AwMQCVmWltb698GiuVArmDbQzonTu9QCo0SgWUVnX9jB9mi+/FUSWvQULBPxUAAo/kLrh1A=="
},
"pako": {
@@ -17659,7 +17659,7 @@
},
"showdown": {
"version": "2.1.0",
"resolved": "https://registry.npmmirror.com/showdown/-/showdown-2.1.0.tgz",
"resolved": "https://registry.npmjs.org/showdown/-/showdown-2.1.0.tgz",
"integrity": "sha512-/6NVYu4U819R2pUIk79n67SYgJHWCce0a5xTP979WbNp0FL9MN1I1QK662IDU1b6JzKTvmhgI7T7JYIxBi3kMQ==",
"requires": {
"commander": "^9.0.0"
@@ -17667,7 +17667,7 @@
"dependencies": {
"commander": {
"version": "9.5.0",
"resolved": "https://registry.npmmirror.com/commander/-/commander-9.5.0.tgz",
"resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz",
"integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ=="
}
}
@@ -20727,7 +20727,7 @@
},
"webpack-bundle-analyzer": {
"version": "2.13.1",
"resolved": "https://registry.npmmirror.com/webpack-bundle-analyzer/-/webpack-bundle-analyzer-2.13.1.tgz",
"resolved": "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-2.13.1.tgz",
"integrity": "sha512-rwxyfecTAxoarCC9VlHlIpfQCmmJ/qWD5bpbjkof+7HrNhTNZIwZITxN6CdlYL2axGmwNUQ+tFgcSOiNXMf/sQ==",
"dev": true,
"requires": {
@@ -21341,9 +21341,24 @@
"integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ=="
},
"xterm": {
"version": "3.1.0",
"resolved": "https://registry.npm.taobao.org/xterm/download/xterm-3.1.0.tgz",
"integrity": "sha1-f34cjPS4C9iBpOiJEhO4UUI+kMk="
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/xterm/-/xterm-5.2.1.tgz",
"integrity": "sha512-cs5Y1fFevgcdoh2hJROMVIWwoBHD80P1fIP79gopLHJIE4kTzzblanoivxTiQ4+92YM9IxS36H1q0MxIJXQBcA=="
},
"xterm-addon-attach": {
"version": "0.8.0",
"resolved": "https://registry.npmjs.org/xterm-addon-attach/-/xterm-addon-attach-0.8.0.tgz",
"integrity": "sha512-k8N5boSYn6rMJTTNCgFpiSTZ26qnYJf3v/nJJYexNO2sdAHDN3m1ivVQWVZ8CHJKKnZQw1rc44YP2NtgalWHfQ=="
},
"xterm-addon-canvas": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/xterm-addon-canvas/-/xterm-addon-canvas-0.4.0.tgz",
"integrity": "sha512-iTC8CdjX9+hGX7jiEuiDMXzHsY/FKJdVnbjep5xjRXNu7RKOk15xuecIkJ7HZORqMVPpr4DGS3jyd9XUoBuxqw=="
},
"xterm-addon-fit": {
"version": "0.7.0",
"resolved": "https://registry.npmjs.org/xterm-addon-fit/-/xterm-addon-fit-0.7.0.tgz",
"integrity": "sha512-tQgHGoHqRTgeROPnvmtEJywLKoC/V9eNs4bLLz7iyJr1aW/QFzRwfd3MGiJ6odJd9xEfxcW36/xRU47JkD5NKQ=="
},
"xxhashjs": {
"version": "0.2.2",

View File

@@ -91,7 +91,10 @@
"vuedraggable": "^2.23.2",
"vuex": "^3.1.2",
"xlsx": "^0.15.6",
"xterm": "^3.1.0"
"xterm": "^5.2.1",
"xterm-addon-attach": "^0.8.0",
"xterm-addon-canvas": "^0.4.0",
"xterm-addon-fit": "^0.7.0"
},
"devDependencies": {
"@babel/plugin-transform-modules-commonjs": "^7.17.9",

View File

@@ -31,6 +31,9 @@
</template>
<script>
import Terminal from '../common/js/Xterm'
import { AttachAddon } from 'xterm-addon-attach'
import { FitAddon } from 'xterm-addon-fit'
import { CanvasAddon } from 'xterm-addon-canvas'
import fileDirectory from './fileDirectory'
export default {
name: 'console',
@@ -58,6 +61,8 @@ export default {
return {
term: null,
terminalSocket: null,
termAttachAddon: null,
termFitAddon: null,
termimalRows: 15,
termimalHeight: 270,
topMenuHeight: 30,
@@ -90,8 +95,8 @@ export default {
}
},
// computed: {
// terminalSetting () {
// return this.provObj.terminalSetting
// userInfo () {
// return this.$store.getters.getUserInfo
// }
// },
watch: {
@@ -101,13 +106,16 @@ export default {
term.write('\r\n ')// term.write('\r\n~$ ');
},
resize (consoleHeigt, consoleWidth) {
this.term.fit()
this.termFitAddon.fit()
this.resizeServiceConsole()
},
resizeServiceConsole () {
const consoleBox = document.getElementById('ternimalContainer' + this.idIndex)
const width = document.body.clientWidth - 10// 可视宽度
const height = parseInt(consoleBox.offsetHeight) - 10
console.log(width, height)
console.log(this.term.cols)
console.log(this.term.rows)
const winStyle = {
width: width,
height: height,
@@ -116,7 +124,8 @@ export default {
}
this.$post('terminal/resize', winStyle).then(response => {
if (response.code === 200) {
this.term.fit()
// this.term.resize()
this.termFitAddon.fit()
} else {
this.$message.error(response.msg)
}
@@ -134,18 +143,30 @@ export default {
rows = parseInt(rows)
const terminalContainer = document.getElementById('terminal' + this.idIndex)
this.term = new Terminal({
allowTransparency: true,
allowProposedApi: true,
overviewRulerWidth: 8,
cursorStyle: 'block', // 光标样式 null | 'block' | 'underline' | 'bar'
disableStdin: false, // 是否应禁用输入
fontSize: 16,
fontSize: 18,
lineHeight: 1.2,
allowTransparency: true,
letterSpacing: 0,
background: 'transparent',
scrollback: this.terminalSetting.scrollbackLines
scrollback: this.terminalSetting.scrollbackLines,
wordSeparator: this.terminalSetting.wordSeparator
})
this.termFitAddon = new FitAddon()
this.term.loadAddon(this.termFitAddon)
// const attachAddon = new AttachAddon()
// this.term.loadAddon(attachAddon)
// this.term.loadAddon(fitAddon)
setTimeout(() => {
this.term.open(terminalContainer)
this.term.loadAddon(new CanvasAddon())
this.term.focus()
this.term.fit()
this.termFitAddon.fit()
this.create()
}, 100)
},
create () {
const that = this
@@ -160,7 +181,10 @@ export default {
let url = ''
this.terminal.height = document.body.clientHeight - 100
this.terminal.width = document.body.clientWidth
this.waterMarkText = this.terminal.userName
const userInfo = localStorage.getItem('nz-userInfo') ? JSON.parse(localStorage.getItem('nz-userInfo')) : ''
if (userInfo) {
this.waterMarkText = `${userInfo.username}(${userInfo.name})`
}
if (this.terminal.type === 'asset') {
url = baseUrl + '/terminal.ws?width=' + this.terminal.width + '&height=' + this.terminal.height + '&cols=' + this.term.cols + '&rows=' + this.term.rows + '&token=' + token + '&assetId=' + this.terminal.assetId + '&accountId=' + this.terminal.accountId + '&uuid=' + this.terminal.uuid
} else if (this.terminal.type === 'custom') {
@@ -172,6 +196,7 @@ export default {
})
}
this.terminalSocket = new WebSocket(url)
this.termAttachAddon = new AttachAddon(this.terminalSocket)
// 连接成功onclose
this.terminalSocket.onopen = () => {
this.terminal.isLogin = true
@@ -179,15 +204,6 @@ export default {
this.isInit = true
this.term.focus()
}
// 登录后,你输入的内容从后台服务返回
this.term.on('data', function (data) {
/*
let code = data.charCodeAt(0);
if(code==13){
}else {
//that.term.write(data);
} */
})
// 个性化配置
this.initTerminalSetting()
// 返回
@@ -238,18 +254,14 @@ export default {
this.terminal.isLogin = false
// 报错sorry的还没来得及看信息就关闭
// this.$emit("closeConsole",this.terminal.name);//
this.term && this.term.setOption('disableStdin', true)
this.term && (this.term.options.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.loadAddon(this.termAttachAddon)
this.term._initialized = true
// this.term.fit()// 自适应大小(使终端的尺寸和几何尺寸适合于终端容器的尺寸) 只是width
this.$nextTick(() => { // 解决进入全屏和退出全屏是底部隐藏
@@ -263,13 +275,13 @@ export default {
this.terminalSocket = ''
}
if (this.term) {
this.term.destroy()
this.term.dispose()
}
// 初始化console的高度
this.conFinish = false
},
setFontSize (fontSize) {
this.term && this.term.setOption('fontSize', fontSize)
this.term && (this.term.options.fontSize = fontSize)
const consoleBox = document.getElementById('ternimalContainer' + this.idIndex)
const width = document.body.clientWidth// 可视宽度
let height = parseInt(consoleBox.offsetHeight)
@@ -286,7 +298,7 @@ export default {
this.term.resize(this.term.cols, this.term.rows)
this.$post('terminal/resize', winStyle).then(response => {
if (response.code === 200) {
this.term.fit()
this.termFitAddon.fit()
} else {
this.$message.error(response.msg)
}
@@ -324,9 +336,9 @@ export default {
},
enterStr (message) {
if (this.terminalSocket && this.terminal.isLogin) {
this.term.send(message)
this.terminalSocket.send(message)
setTimeout(() => {
this.term.send('\n')
this.terminalSocket.send('\n')
}, 100)
this.term.scrollToBottom()
this.historyChange(message)
@@ -339,32 +351,29 @@ export default {
initTerminalSetting () { // 个性化配置
// 1 render
this.showWatermark = this.terminalSetting.watermark
console.log(this.terminalSetting.watermark)
this.term.on('selection', (p, a) => {
this.term.onSelectionChange((p, a) => {
if (this.terminalSetting.copyOnSelect) {
setTimeout(() => {
this.copySelection()
})
}
})
// this.term.on('click', () => {
// console.log('click')
// console.log(this.term.getSelection())
// })
// this.term.on('dbclick', () => {
// console.log('doubleclick123')
// console.log(this.term.getSelection())
// })
this.term.selectionManager._isCharWordSeparator = (charData) => {
console.log(charData)
if (charData[2] === 0) {
return false
}
return this.wordSeparator.indexOf(charData[1]) >= 0
}
// this.term.selectionManager._isCharWordSeparator = (charData) => {
// if (charData[2] === 0) {
// return false
// }
// return this.wordSeparator.indexOf(charData[1]) >= 0
// }
},
renderTerminalSetting () {
console.log('renderTerminalSetting')
this.showWatermark = this.terminalSetting.watermark
this.wordSeparator = this.terminalSetting.wordSeparator
this.term.setOption('scrollback', this.terminalSetting.scrollbackLines)
this.term.options = {
scrollback: this.terminalSetting.scrollbackLines,
wordSeparator: this.terminalSetting.wordSeparator
}
console.log(this.term)
},
copySelection () {
let str = this.term.getSelection()
@@ -374,14 +383,9 @@ export default {
if (this.terminalSetting.copyTrimEnd) {
str = str.replace(/(\s*$)/g, '')
}
this.$copyText(str)
},
dblclick () {
if (this.term) {
if (this.terminalSetting.copyOnSelect) {
this.copySelection()
}
}
this.$copyText(str).then((res) => {
console.log(res)
})
},
async contextmenu (event) {
event.preventDefault()
@@ -395,14 +399,14 @@ export default {
if (this.terminalSetting.rightClick === 'paste') {
if (!document.execCommand('paste')) {
const text = await navigator.clipboard.readText()
this.term.send(text)
this.term.write(text)
}
}
},
async paste () {
if (!document.execCommand('paste')) {
const text = await navigator.clipboard.readText()
this.term.send(text)
this.term.write(text)
}
},
tiggerMenu (flag, event) {
@@ -435,16 +439,12 @@ export default {
this.beforeCreate()
this.showWatermark = this.terminalSetting.watermark
const dom = document.getElementById('ternimalContainer' + this.idIndex)
dom.addEventListener('dblclick', this.dblclick)
dom.addEventListener('contextmenu', this.contextmenu)
dom.addEventListener('click', this.clickHide)
},
beforeDestroy () {
this.closeSocket()
this.term.off('selection')
this.term.off('data')
const dom = document.getElementById('ternimalContainer' + this.idIndex)
dom && dom.removeEventListener('dblclick', this.dblclick)
dom && dom.removeEventListener('contextmenu', this.contextmenu)
dom && dom.removeEventListener('click', this.clickHide)
}

View File

@@ -262,8 +262,11 @@ export default {
this.$put('/sys/user/preference', { terminal: JSON.stringify(this.newTerminalSetting) }).then(res => {
if (res.code === 200) {
this.terminalSetting = this.$lodash.cloneDeep(this.newTerminalSetting)
this.$nextTick(() => {
this.$refs.websshNew.renderTerminalSetting()
this.personalization = false
})
this.$message.success(this.$t('overall.success'))
} else {
this.$message.error(res.msg || res.error)
}

View File

@@ -23,6 +23,8 @@
<script>
import Terminal from '../../js/Xterm'
import { AttachAddon } from 'xterm-addon-attach'
import { FitAddon } from 'xterm-addon-fit'
import bus from '../../../../libs/bus'
import dataListMixin from '@/components/common/mixin/dataList'
import subDataListMixin from '@/components/common/mixin/subDataList'

View File

@@ -36,6 +36,8 @@
<script>
import Terminal from '../../js/Xterm'
import { AttachAddon } from 'xterm-addon-attach'
import { FitAddon } from 'xterm-addon-fit'
import bus from '../../../../libs/bus'
// import dataListMixin from '@/components/common/mixin/dataList'
import subDataListMixin from '@/components/common/mixin/subDataList'

View File

@@ -1,10 +1,10 @@
import { Terminal } from 'xterm'
import * as fit from 'xterm/lib/addons/fit/fit'
import * as attach from 'xterm/lib/addons/attach/attach'
// import 'xterm/dist/addons/fullscreen/fullscreen.css'
// import * as fullscreen from 'xterm/lib/addons/fullscreen/fullscreen'
Terminal.applyAddon(fit)
Terminal.applyAddon(attach)
// import * as fit from 'xterm-addon-fit'
// import * as attach from 'xterm-addon-attach'
// // import 'xterm/dist/addons/fullscreen/fullscreen.css'
// // import * as fullscreen from 'xterm/lib/addons/fullscreen/fullscreen'
// Terminal.loadAddon(fit)
// Terminal.loadAddon(attach)
// Terminal.applyAddon(fullscreen);
export default Terminal

View File

@@ -1162,6 +1162,7 @@ function addWaterMarker (parentNode, text, font, textColor, width, height, textR
cans.textBaseline = 'middle'
cans.fillText(text, 200, 150)
cans.fillText(text1, 200, 170)
console.log(show)
if (show) {
parentNode.style.backgroundImage = 'url(' + can.toDataURL('image/png') + ')'
} else {

View File

@@ -293,6 +293,7 @@ export default {
this.theme = res.data.user.theme
this.userInfo = res.data.user
localStorage.setItem('nz-token', res.data.authToken)
localStorage.setItem('nz-userInfo', JSON.stringify( this.userInfo))
if (res.data.authFlag === 1) {
if (res.data.authBind === 0) {
this.verifyShow = true

View File

@@ -1,6 +1,6 @@
// import '@/assets/stylus/index.scss'
// import 'element-ui/lib/theme-chalk/index.css'
import 'xterm/dist/xterm.css'
import 'xterm/css/xterm.css'
import '@/assets/css/main.scss'
import '@/assets/css/animate.css'
import '@/assets/css/font/iconfont.js'