fix:解决冲突
This commit is contained in:
25
nezha-fronted/package-lock.json
generated
25
nezha-fronted/package-lock.json
generated
@@ -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": {
|
||||
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -309,5 +309,11 @@
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
.terminal-menu {
|
||||
position: fixed;
|
||||
width: 150px;
|
||||
border-radius: 2px;
|
||||
z-index: 1000;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
background-color: $--background-color-base;
|
||||
border: 1px solid $--border-color-light;
|
||||
border-radius:4px 0 0 4px;
|
||||
width: 48px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -130,6 +130,7 @@
|
||||
@import './page/tool/ping.scss';
|
||||
@import './page/tool/trace.scss';
|
||||
@import './page/integration/integration.scss';
|
||||
@import './page/softwareType/softwareType.scss';
|
||||
|
||||
@import './common/v-selectpagenew/selectpage.scss';
|
||||
@import './common/selectTable.scss';
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
.right-box-editSoftwareType {
|
||||
.el-dropdown-link {
|
||||
border: 1px solid $--border-color-light;
|
||||
border-radius: 2px;
|
||||
}
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,11 +1,39 @@
|
||||
<template>
|
||||
<div :id="'ternimalContainer'+idIndex" class="console" v-watermark="{text: waterMarkText, text1: terminal.host || '', textColor: 'rgba(215, 215, 215, 0.5)'}">
|
||||
<div :id="'ternimalContainer'+idIndex" class="console" v-watermark="{show: showWatermark,text: waterMarkText, text1: terminal.host || '', textColor: 'rgba(215, 215, 215, 0.5)'}" v-clickoutside="clickHide">
|
||||
<div :id="'terminal'+idIndex" style="height: 100%;width: 100%"></div>
|
||||
<fileDirectory :host="host" v-clickoutside="closeFileDir" :uuid="terminal.uuid" v-show="fileDirectoryShow" @close="showFileDir(false)" :fileDirectoryShow="fileDirectoryShow" ref="fileDirectory"/>
|
||||
<div
|
||||
v-if="terminal.isLogin && showMenu"
|
||||
class="terminal-menu menus"
|
||||
:style="{
|
||||
left: menuPosition.left + 'px',
|
||||
top: menuPosition.top + 'px'
|
||||
}"
|
||||
>
|
||||
<div>
|
||||
<span @click="copySelection()">{{$t('overall.duplicate')}}</span>
|
||||
</div>
|
||||
<div v-if="showPaste">
|
||||
<span @click="paste()">{{$t('project.topology.paste')}}</span>
|
||||
</div>
|
||||
<div>
|
||||
<span @click="clearTerminal()">{{$t('terminal.clear')}}</span>
|
||||
</div>
|
||||
<div class="line"></div>
|
||||
<div>
|
||||
<span @click="showFileDir(true)">{{$t('terminal.sftp')}}</span>
|
||||
</div>
|
||||
<div>
|
||||
<span @click="closeTerminal(true)"> {{$t('overall.close')}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</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',
|
||||
@@ -23,13 +51,18 @@ export default {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
terminalSetting: {
|
||||
type: Object,
|
||||
default: () => {}
|
||||
},
|
||||
fontSize: {}
|
||||
},
|
||||
inject: ['terminalSetting'],
|
||||
data () {
|
||||
return {
|
||||
term: null,
|
||||
terminalSocket: null,
|
||||
termAttachAddon: null,
|
||||
termFitAddon: null,
|
||||
termimalRows: 15,
|
||||
termimalHeight: 270,
|
||||
topMenuHeight: 30,
|
||||
@@ -51,9 +84,22 @@ export default {
|
||||
userName: '',
|
||||
fileDirectoryShow: false,
|
||||
host: '',
|
||||
waterMarkText: 'Nezha'
|
||||
waterMarkText: 'Nezha',
|
||||
showWatermark: false,
|
||||
wordSeparator: "\\ :;~`!@#$%^&*()-=+|[]{}'\",.<>/?",
|
||||
showMenu: false,
|
||||
menuPosition: {
|
||||
left: 0,
|
||||
top: 0
|
||||
},
|
||||
showPaste: false
|
||||
}
|
||||
},
|
||||
// computed: {
|
||||
// userInfo () {
|
||||
// return this.$store.getters.getUserInfo
|
||||
// }
|
||||
// },
|
||||
watch: {
|
||||
},
|
||||
methods: {
|
||||
@@ -61,13 +107,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,
|
||||
@@ -76,7 +125,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)
|
||||
}
|
||||
@@ -94,17 +144,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,
|
||||
background: 'transparent'
|
||||
letterSpacing: 0,
|
||||
background: 'transparent',
|
||||
scrollback: this.terminalSetting.scrollbackLines,
|
||||
wordSeparator: this.terminalSetting.wordSeparator
|
||||
})
|
||||
this.term.open(terminalContainer)
|
||||
this.term.focus()
|
||||
this.term.fit()
|
||||
this.create()
|
||||
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.termFitAddon.fit()
|
||||
this.create()
|
||||
}, 100)
|
||||
},
|
||||
create () {
|
||||
const that = this
|
||||
@@ -119,7 +182,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') {
|
||||
@@ -131,26 +197,16 @@ export default {
|
||||
})
|
||||
}
|
||||
this.terminalSocket = new WebSocket(url)
|
||||
this.termAttachAddon = new AttachAddon(this.terminalSocket)
|
||||
// 连接成功onclose
|
||||
this.terminalSocket.onopen = () => {
|
||||
this.terminal.isLogin = true
|
||||
this.showMenu = false
|
||||
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.term.on('selection', (p,a) => {
|
||||
console.log(this.term.getSelection())
|
||||
this.$copyText(this.term.getSelection())
|
||||
})
|
||||
// 个性化配置
|
||||
this.initTerminalSetting()
|
||||
// 返回
|
||||
this.terminalSocket.onmessage = function (evt) {
|
||||
let backContent = evt.data
|
||||
@@ -199,18 +255,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(() => { // 解决进入全屏和退出全屏是底部隐藏
|
||||
@@ -224,13 +276,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)
|
||||
@@ -247,7 +299,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)
|
||||
}
|
||||
@@ -278,13 +330,16 @@ export default {
|
||||
})
|
||||
},
|
||||
clearTerminal () {
|
||||
this.term.reset()
|
||||
this.term.clear()
|
||||
},
|
||||
closeTerminal () {
|
||||
this.$emit('close')
|
||||
},
|
||||
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)
|
||||
@@ -293,16 +348,107 @@ export default {
|
||||
// 新增历史记录
|
||||
historyChange (message) {
|
||||
this.$emit('historyChange', message)
|
||||
},
|
||||
initTerminalSetting () { // 个性化配置
|
||||
// 1 render
|
||||
this.showWatermark = this.terminalSetting.watermark
|
||||
this.term.onSelectionChange((p, a) => {
|
||||
if (this.terminalSetting.copyOnSelect) {
|
||||
setTimeout(() => {
|
||||
this.copySelection()
|
||||
})
|
||||
}
|
||||
})
|
||||
// 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.options = {
|
||||
scrollback: this.terminalSetting.scrollbackLines,
|
||||
wordSeparator: this.terminalSetting.wordSeparator
|
||||
}
|
||||
console.log(this.term)
|
||||
},
|
||||
copySelection () {
|
||||
let str = this.term.getSelection()
|
||||
if (!this.terminalSetting.copyWithFormatting) {
|
||||
str = str.replace(/[\r\n]/g, '')
|
||||
}
|
||||
if (this.terminalSetting.copyTrimEnd) {
|
||||
str = str.replace(/(\s*$)/g, '')
|
||||
}
|
||||
this.$copyText(str).then((res) => {
|
||||
console.log(res)
|
||||
})
|
||||
},
|
||||
async contextmenu (event) {
|
||||
event.preventDefault()
|
||||
event.stopPropagation()
|
||||
if (this.terminalSetting.rightClick === 'none') {
|
||||
return
|
||||
}
|
||||
if (this.terminalSetting.rightClick === 'menu') {
|
||||
this.tiggerMenu(true, event)
|
||||
}
|
||||
if (this.terminalSetting.rightClick === 'paste') {
|
||||
if (!document.execCommand('paste')) {
|
||||
const text = await navigator.clipboard.readText()
|
||||
this.term.write(text)
|
||||
}
|
||||
}
|
||||
},
|
||||
async paste () {
|
||||
if (!document.execCommand('paste')) {
|
||||
const text = await navigator.clipboard.readText()
|
||||
this.term.write(text)
|
||||
}
|
||||
},
|
||||
tiggerMenu (flag, event) {
|
||||
this.showMenu = false
|
||||
if (flag) {
|
||||
let top = 0
|
||||
let left = 0
|
||||
if (event.clientY < document.body.clientHeight / 2) {
|
||||
top = event.clientY + 10
|
||||
} else {
|
||||
top = event.clientY - 180 - 10
|
||||
}
|
||||
if (event.clientX < document.body.clientWidth / 2) {
|
||||
left = event.clientX + 10
|
||||
} else {
|
||||
left = event.clientX - 150 - 10
|
||||
}
|
||||
this.menuPosition = {
|
||||
left: left,
|
||||
top: top
|
||||
}
|
||||
}
|
||||
this.showMenu = flag
|
||||
},
|
||||
clickHide () {
|
||||
this.showMenu = false
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
this.beforeCreate()
|
||||
console.log(this.terminalSetting)
|
||||
this.showWatermark = this.terminalSetting.watermark
|
||||
const dom = document.getElementById('ternimalContainer' + this.idIndex)
|
||||
dom.addEventListener('contextmenu', this.contextmenu)
|
||||
dom.addEventListener('click', this.clickHide)
|
||||
this.showPaste = navigator.clipboard
|
||||
},
|
||||
beforeDestroy () {
|
||||
this.closeSocket()
|
||||
this.term.off('selection')
|
||||
this.term.off('data')
|
||||
const dom = document.getElementById('ternimalContainer' + this.idIndex)
|
||||
dom && dom.removeEventListener('contextmenu', this.contextmenu)
|
||||
dom && dom.removeEventListener('click', this.clickHide)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -15,6 +15,9 @@
|
||||
<div class="personal-dropdown__username">{{name}}</div>
|
||||
<div class="personal-dropdown__name">@{{name}}</div>
|
||||
</div>
|
||||
<el-dropdown-item>
|
||||
<div id="header-to-personalization" @click="showPersonalization"><i class="nz-icon nz-icon-personalization"></i>{{$t('terminal.personal')}}</div>
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item>
|
||||
<div id="header-to-logout" @click="logout"><i class="nz-icon nz-icon-exit"></i>{{$t('overall.signOut')}}</div>
|
||||
</el-dropdown-item>
|
||||
@@ -24,7 +27,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<fileListState v-clickoutside="hideFileState" ref="fileListState"/>
|
||||
<webSSHNew ref="websshNew" />
|
||||
<webSSHNew ref="websshNew" :terminalSetting="terminalSetting" />
|
||||
<div class="shell-input">
|
||||
<el-input ref="shellInput" :placeholder="placeholder" size="small" v-model="message" @keyup.enter.native="sendMessage" @focus="placeholderChange('focus')" @blur="placeholderChange('blur')">
|
||||
<i slot="suffix" class="nz-icon nz-icon-history no-style-class" :class="{'active':visible}" :title="$t('terminal.history')" @click="toggleHistory"></i>
|
||||
@@ -48,6 +51,63 @@
|
||||
</div>
|
||||
</transition>
|
||||
</div>
|
||||
<!--弹窗-->
|
||||
<el-dialog :modal-append-to-body='false' :z-index="1000" :show-close="true" :visible.sync="personalization" @close="personalization = false" class="nz-dialog webshell-selectAsset" width="650px">
|
||||
<div slot="title">{{$t('terminal.personal')}}</div>
|
||||
<div>
|
||||
<el-form v-model="newTerminalSetting" label-width="180px" size="small" ref="terminalForm" :validate-on-rule-change="false">
|
||||
<div class="system-title" style="padding-top: 15px">{{$t('terminal.render')}}</div>
|
||||
<el-form-item :label="$t('terminal.waterMaker')" prop="watermark">
|
||||
<el-switch v-model="newTerminalSetting.watermark" :active-value='true' :inactive-value='false' id="terminal-setting-watermark_change" size="small">
|
||||
</el-switch>
|
||||
<div class="el-form-item__tip" style="margin: 0">{{$t('terminal.waterMakerInfo')}}</div>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('terminal.scrollbackLines')" prop="scrollbackLines">
|
||||
<el-input-number :min="1" :precision="0" :controls="false" :placeholder="'默认25000'" v-model="newTerminalSetting.scrollbackLines" size="small">
|
||||
</el-input-number>
|
||||
<div class="el-form-item__tip" style="margin: 0">{{$t('terminal.scrollbackLinesInfo')}}</div>
|
||||
</el-form-item>
|
||||
<div class="system-title system-title-border" style="width: 100%;margin-top: 50px">{{$t('terminal.mouse')}}</div>
|
||||
<el-form-item :label="$t('terminal.rightClick')" prop="rightClick">
|
||||
<el-radio-group v-model="newTerminalSetting.rightClick" size="small">
|
||||
<el-radio-button label="none">{{$t('project.topology.none')}}</el-radio-button>
|
||||
<el-radio-button label="menu">{{$t('terminal.menu')}}</el-radio-button>
|
||||
<el-radio-button label="paste">{{$t('terminal.paste')}}</el-radio-button>
|
||||
</el-radio-group>
|
||||
<div class="el-form-item__tip" style="margin: 0">{{$t('terminal.rightClickInfo')}}</div>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('terminal.wordSeparator')" prop="wordSeparator">
|
||||
<el-input size="small" v-model="newTerminalSetting.wordSeparator">
|
||||
</el-input>
|
||||
<div class="el-form-item__tip" style="margin: 0">{{$t('terminal.wordSeparatorInfo')}}</div>
|
||||
</el-form-item>
|
||||
<div class="system-title system-title-border" style="width: 100%;margin-top: 50px">{{$t('terminal.clipboard')}}</div>
|
||||
<el-form-item :label="$t('terminal.copySelect')" prop="copyOnSelect">
|
||||
<el-switch v-model="newTerminalSetting.copyOnSelect" :active-value='true' :inactive-value='false' id="terminal-setting-watermark_change">
|
||||
</el-switch>
|
||||
<!-- <div class="el-form-item__tip" style="margin: 0">{{$t('config.system.basic.pinPolicyValue')}}</div>-->
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('terminal.copyFormatting')" prop="copyWithFormatting">
|
||||
<el-switch v-model="newTerminalSetting.copyWithFormatting" :active-value='true' :inactive-value='false' id="terminal-setting-watermark_change">
|
||||
</el-switch>
|
||||
<!-- <div class="el-form-item__tip" style="margin: 0">{{$t('terminal.copyFormattingInfo')}}</div>-->
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('terminal.copyTrimEnd')" prop="copyTrimEnd">
|
||||
<el-switch v-model="newTerminalSetting.copyTrimEnd" :active-value='true' :inactive-value='false' id="terminal-setting-watermark_change">
|
||||
</el-switch>
|
||||
<div class="el-form-item__tip" style="margin: 0">{{$t('terminal.copyTrimEndInfo')}}</div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<div slot="footer">
|
||||
<button class="footer__btn footer__btn--light" @click="personalization = false">
|
||||
<span>{{$t('overall.cancel')}}</span>
|
||||
</button>
|
||||
<button class="footer__btn" :disabled="prevent_opt.save" @click.prevent="savePersonalization">
|
||||
<span>{{$t('overall.save')}}</span>
|
||||
</button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -79,13 +139,16 @@ export default {
|
||||
visible: false,
|
||||
// 历史命令记录
|
||||
historyArr: [],
|
||||
showPaste: false,
|
||||
personalization: false,
|
||||
newTerminalSetting: {},
|
||||
terminalSetting: {
|
||||
watermark: false,
|
||||
watermark: true,
|
||||
scrollbackLines: 25000,
|
||||
rightClick: 'menu',
|
||||
wordSeparator: "\\ :;~`!@#$%^&*()-=+|[]{}'\",.<>/?",
|
||||
copyOnSelect: false,
|
||||
copyWithFormatting: false,
|
||||
copyWithFormatting: true,
|
||||
copyTrimEnd: false
|
||||
}
|
||||
}
|
||||
@@ -110,6 +173,8 @@ export default {
|
||||
const self = this
|
||||
this.name = localStorage.getItem('nz-username')
|
||||
this.username = localStorage.getItem('nz-username')
|
||||
this.showPaste = navigator.clipboard
|
||||
this.initTerminalSetting()
|
||||
window.opener.name = 'parent'
|
||||
window.onbeforeunload = () => {
|
||||
const opener = window.opener
|
||||
@@ -199,6 +264,42 @@ export default {
|
||||
isLogout: true
|
||||
})
|
||||
)
|
||||
},
|
||||
showPersonalization () {
|
||||
this.personalization = true
|
||||
this.newTerminalSetting = this.$lodash.cloneDeep(this.terminalSetting)
|
||||
},
|
||||
savePersonalization () {
|
||||
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('tip.saveSuccess'))
|
||||
} else {
|
||||
this.$message.error(res.msg || res.error)
|
||||
}
|
||||
})
|
||||
},
|
||||
initTerminalSetting () {
|
||||
this.$get('/sys/user/preference', { key: 'terminal' }).then(res => {
|
||||
if (res.code === 200) {
|
||||
if (res.data.terminal) {
|
||||
let terminal = {}
|
||||
try {
|
||||
terminal = JSON.parse(res.data.terminal)
|
||||
} catch (e) {}
|
||||
this.terminalSetting = {
|
||||
...this.terminalSetting,
|
||||
...terminal
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this.$message.error(res.msg || res.error)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,12 +64,14 @@
|
||||
|
||||
<terminal
|
||||
:fontSize="fontSize"
|
||||
:terminalSetting="terminalSetting"
|
||||
:terminalType="item.terminal.terminalType"
|
||||
:idIndex="index"
|
||||
:ref="'console'+index"
|
||||
:terminal="item.terminal"
|
||||
@loginFail="loginFail"
|
||||
@closeConsole="removeTab"
|
||||
@close="closeShell(item,index)"
|
||||
@refreshConsoleTitle="refreshTabTitle"
|
||||
@historyChange="(message)=>{$parent.historyChange(message)}"
|
||||
></terminal>
|
||||
@@ -200,6 +202,12 @@ export default {
|
||||
terminal,
|
||||
selectTable
|
||||
},
|
||||
props: {
|
||||
terminalSetting: {
|
||||
type: Object,
|
||||
default: () => {}
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
language () { return this.$store.getters.getLanguage },
|
||||
fileList () {
|
||||
@@ -448,6 +456,7 @@ export default {
|
||||
this.$refs['console' + el.index][0].resize()
|
||||
this.$refs['console' + el.index][0].term.scrollToBottom()
|
||||
this.$refs['console' + el.index][0].focusConsole()
|
||||
this.$refs['console' + el.index][0].clickHide()
|
||||
})
|
||||
}
|
||||
},
|
||||
@@ -805,6 +814,11 @@ export default {
|
||||
this.editableTabs.forEach((item, index) => {
|
||||
this.$refs['console' + index][0].enterStr(message)
|
||||
})
|
||||
},
|
||||
renderTerminalSetting () {
|
||||
this.editableTabs.forEach((item, index) => {
|
||||
this.$refs['console' + index][0].renderTerminalSetting()
|
||||
})
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
<terminal-log-cmd-tab v-if="from === fromRoute.terminalLog && targetTab === 'cmdTab'" :from="from" :obj="obj" :tabs="hasTerminalLogTabs" @changeTab="changeTab" :targetTab.sync="targetTab"></terminal-log-cmd-tab>
|
||||
<terminal-log-sftp-tab v-if="from === fromRoute.terminalLog && targetTab === 'sftpTab' && obj.protocol == 'SSH'" :from="from" :obj="obj" :tabs="hasTerminalLogTabs" @changeTab="changeTab" :targetTab.sync="targetTab"></terminal-log-sftp-tab>
|
||||
<terminal-log-record-tab v-if="from === fromRoute.terminalLog && targetTab === 'recordTab'" ref="reminalLogRecordTab" :from="from" :obj="obj" :tabs="hasTerminalLogTabs" @changeTab="changeTab" :targetTab.sync="targetTab"></terminal-log-record-tab>
|
||||
<terminal-log-monitor-tab v-if="from === fromRoute.terminalLog && targetTab === 'monitorTab'" :from="from" :obj="obj" :tabs="tabs.terminalLog.monitor" @changeTab="changeTab" @exit="closeSubList" :targetTab.sync="targetTab"></terminal-log-monitor-tab>
|
||||
<terminal-log-monitor-tab v-if="from === fromRoute.terminalLog && targetTab === 'monitorTab'" ref="reminalLogMonitorTab" :from="from" :obj="obj" :tabs="tabs.terminalLog.monitor" @changeTab="changeTab" @exit="closeSubList" :targetTab.sync="targetTab"></terminal-log-monitor-tab>
|
||||
|
||||
<asset-tab v-if="from === fromRoute.dc && targetTab === 'asset'" :tabs="tabs.dc.asset" ref="assetTab" :from="from" :obj="obj" @changeTab="changeTab" @exit="closeSubList" :targetTab.sync="targetTab"></asset-tab>
|
||||
|
||||
@@ -409,6 +409,10 @@ export default {
|
||||
setTimeout(() => {
|
||||
this.$refs.reminalLogRecordTab.consoleResize()
|
||||
}, 600)
|
||||
} else if (this.from === this.fromRoute.terminalLog && this.targetTab === 'monitorTab') {
|
||||
setTimeout(() => {
|
||||
this.$refs.reminalLogMonitorTab.consoleResize()
|
||||
}, 600)
|
||||
}
|
||||
const subListDom = document.querySelector('.sub-list') // 副列表
|
||||
const height = window.innerHeight > 900 ? 505 : 250
|
||||
|
||||
@@ -11,9 +11,9 @@
|
||||
<template v-slot:title><span :title="obj.uuid.substring(0, 8).toUpperCase()">{{obj.uuid.substring(0, 8).toUpperCase()}}</span></template>
|
||||
<template v-slot>
|
||||
<div ref="replayTab" class="replay-tab">
|
||||
<div class="replay-container">
|
||||
<div class="replay-container" style="height: 100%">
|
||||
<div ref="recordConsole" class="record-console">
|
||||
<div :id="obj.uuid" class="record-terminal"></div>
|
||||
<div :id="'record-terminal' + obj.uuid" class="record-terminal" style="height: 100%;width: 100%"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -23,6 +23,9 @@
|
||||
|
||||
<script>
|
||||
import Terminal from '../../js/Xterm'
|
||||
import { AttachAddon } from 'xterm-addon-attach'
|
||||
import { FitAddon } from 'xterm-addon-fit'
|
||||
import { CanvasAddon } from 'xterm-addon-canvas'
|
||||
import bus from '../../../../libs/bus'
|
||||
import dataListMixin from '@/components/common/mixin/dataList'
|
||||
import subDataListMixin from '@/components/common/mixin/subDataList'
|
||||
@@ -43,7 +46,9 @@ export default {
|
||||
},
|
||||
terminal: null,
|
||||
term: null,
|
||||
termFitAddon: null,
|
||||
terminalSocket: null,
|
||||
termAttachAddon: null,
|
||||
recordData: [],
|
||||
isNeedStop: false, // 是否需要停止
|
||||
playedCount: 0, // 当前已经播放完的数量
|
||||
@@ -76,24 +81,24 @@ export default {
|
||||
methods: {
|
||||
// 创建连接
|
||||
create () {
|
||||
console.log('create')
|
||||
const that = this
|
||||
if (this.terminalSocket) {
|
||||
this.terminalSocket.close()
|
||||
}
|
||||
if (this.terminal) {
|
||||
this.terminal.off('selection')
|
||||
this.terminal.off('data')
|
||||
this.terminal.destroy()
|
||||
this.terminal.dispose()
|
||||
}
|
||||
this.terminal = new Terminal({
|
||||
rows: parseInt(this.$refs.recordConsole.offsetHeight / 18),
|
||||
cols: parseInt(this.$refs.recordConsole.offsetWidth / 11),
|
||||
cursorStyle: 'block', // 光标样式 null | 'block' | 'underline' | 'bar'
|
||||
// bellStyle:'sound',
|
||||
overviewRulerWidth: 8,
|
||||
lineHeight: 1.2,
|
||||
fontSize: 16,
|
||||
disableStdin: true// 是否应禁用输入
|
||||
})
|
||||
this.terminal.open(document.getElementById(this.obj.uuid))
|
||||
|
||||
this.termFitAddon = new FitAddon()
|
||||
this.terminal.loadAddon(this.termFitAddon)
|
||||
this.terminal.loadAddon(new CanvasAddon())
|
||||
const token = localStorage.getItem('nz-token')
|
||||
let baseUrl = this.$axios.defaults.baseURL
|
||||
if (baseUrl.startsWith('/')) {
|
||||
@@ -107,17 +112,6 @@ export default {
|
||||
this.terminalSocket.close()
|
||||
}
|
||||
this.terminalSocket = new WebSocket(url)
|
||||
// 连接成功
|
||||
this.terminalSocket.onopen = () => {
|
||||
}
|
||||
// 登录后,你输入的内容从后台服务返回
|
||||
this.terminal.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
|
||||
@@ -173,24 +167,13 @@ export default {
|
||||
}
|
||||
}
|
||||
}
|
||||
// 关闭
|
||||
this.terminalSocket.onclose = () => {
|
||||
// 报错sorry的,还没来得及看信息就关闭
|
||||
// this.$emit("closeConsole",this.terminal.name);//应该调用父窗口
|
||||
}
|
||||
|
||||
// 错误
|
||||
this.terminalSocket.onerror = (e) => {
|
||||
}
|
||||
// 选中 复制
|
||||
this.terminal.on('selection', function () {
|
||||
})
|
||||
this.terminal.attachCustomKeyEventHandler(function (ev) {
|
||||
})
|
||||
|
||||
this.terminal.attach(this.terminalSocket)
|
||||
this.terminal._initialized = true
|
||||
this.terminal.fit()// 自适应大小(使终端的尺寸和几何尺寸适合于终端容器的尺寸) 只是width
|
||||
this.termAttachAddon = new AttachAddon(this.terminalSocket)
|
||||
this.terminal.loadAddon(this.termAttachAddon)
|
||||
this.$nextTick(() => {
|
||||
const dom = document.getElementById('record-terminal' + this.obj.uuid)
|
||||
this.terminal.open(dom)
|
||||
this.termFitAddon.fit()
|
||||
})// 自适应大小(使终端的尺寸和几何尺寸适合于终端容器的尺寸) 只是width
|
||||
// this.$nextTick(()=>{// 解决进入全屏和退出全屏是底部隐藏
|
||||
// this.setFontSize(this.fontSize);
|
||||
// })
|
||||
@@ -202,7 +185,7 @@ export default {
|
||||
this.terminalSocket.close()
|
||||
}
|
||||
if (this.terminal) {
|
||||
this.terminal.destroy()
|
||||
this.terminal.dispose()
|
||||
}
|
||||
},
|
||||
// 切换tab
|
||||
@@ -223,9 +206,9 @@ export default {
|
||||
},
|
||||
|
||||
consoleResize () {
|
||||
this.terminal && this.terminal.resize(parseInt(this.$refs.recordConsole.offsetWidth / 11), parseInt(this.$refs.recordConsole.offsetHeight / 18))
|
||||
console.log('consoleResize')
|
||||
this.$nextTick(() => {
|
||||
this.terminal && this.terminal.fit()
|
||||
this.termFitAddon.fit()
|
||||
})
|
||||
},
|
||||
shutdown () {
|
||||
@@ -260,7 +243,7 @@ export default {
|
||||
}
|
||||
setTimeout(() => {
|
||||
this.create()
|
||||
}, 200)
|
||||
}, 300)
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -288,8 +271,6 @@ export default {
|
||||
beforeDestroy () {
|
||||
window.removeEventListener('resize', bus.debounce)
|
||||
this.closeSocket()
|
||||
this.terminal.off('selection')
|
||||
this.terminal.off('data')
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div ref="recordConsole" class="record-console">
|
||||
<div :id="obj.uuid" class="record-terminal"></div>
|
||||
<div :id="obj.uuid" class="record-terminal" style="height: 100%;width: 100%"></div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -36,6 +36,9 @@
|
||||
|
||||
<script>
|
||||
import Terminal from '../../js/Xterm'
|
||||
import { AttachAddon } from 'xterm-addon-attach'
|
||||
import { FitAddon } from 'xterm-addon-fit'
|
||||
import { CanvasAddon } from 'xterm-addon-canvas'
|
||||
import bus from '../../../../libs/bus'
|
||||
// import dataListMixin from '@/components/common/mixin/dataList'
|
||||
import subDataListMixin from '@/components/common/mixin/subDataList'
|
||||
@@ -56,7 +59,7 @@ export default {
|
||||
uuid: ''
|
||||
},
|
||||
terminal: null,
|
||||
|
||||
termFitAddon: null,
|
||||
recordData: [],
|
||||
isNeedStop: false, // 是否需要停止
|
||||
playedCount: 0, // 当前已经播放完的数量
|
||||
@@ -101,9 +104,9 @@ export default {
|
||||
},
|
||||
|
||||
consoleResize () {
|
||||
this.terminal && this.terminal.resize(parseInt(this.$refs.recordConsole.offsetWidth / 11), parseInt(this.$refs.recordConsole.offsetHeight / 18))
|
||||
// this.terminal && this.terminal.resize(parseInt(this.$refs.recordConsole.offsetWidth / 11), parseInt(this.$refs.recordConsole.offsetHeight / 18))
|
||||
this.$nextTick(() => {
|
||||
this.terminal && this.terminal.fit()
|
||||
this.terminal && this.termFitAddon.fit()
|
||||
})
|
||||
},
|
||||
|
||||
@@ -111,13 +114,21 @@ export default {
|
||||
this.$nextTick(() => {
|
||||
// terminal初始化
|
||||
if (this.terminal) {
|
||||
this.terminal.reset(parseInt(this.$refs.recordConsole.offsetWidth / 11), parseInt(this.$refs.recordConsole.offsetHeight / 18))
|
||||
// this.terminal.reset(parseInt(this.$refs.recordConsole.offsetWidth / 11), parseInt(this.$refs.recordConsole.offsetHeight / 18))
|
||||
this.termFitAddon.fit()
|
||||
} else {
|
||||
this.terminal = new Terminal({
|
||||
rows: parseInt(this.$refs.recordConsole.offsetHeight / 18),
|
||||
cols: parseInt(this.$refs.recordConsole.offsetWidth / 11)
|
||||
cursorStyle: 'block', // 光标样式 null | 'block' | 'underline' | 'bar'
|
||||
overviewRulerWidth: 8,
|
||||
lineHeight: 1.2,
|
||||
fontSize: 16,
|
||||
disableStdin: true// 是否应禁用输入
|
||||
})
|
||||
this.terminal.loadAddon(new CanvasAddon())
|
||||
this.termFitAddon = new FitAddon()
|
||||
this.terminal.loadAddon(this.termFitAddon)
|
||||
this.terminal.open(document.getElementById(this.obj.uuid))
|
||||
this.terminal && this.termFitAddon.fit()
|
||||
}
|
||||
|
||||
if (this.recordData.length > 0) {
|
||||
|
||||
@@ -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
|
||||
|
||||
134
nezha-fronted/src/components/common/js/iconList.js
Normal file
134
nezha-fronted/src/components/common/js/iconList.js
Normal file
@@ -0,0 +1,134 @@
|
||||
const iconList = [
|
||||
{
|
||||
value: undefined
|
||||
}, {
|
||||
value: 'nz-icon nz-icon-Router'
|
||||
}, {
|
||||
value: 'nz-icon nz-icon-Computer'
|
||||
}, {
|
||||
value: 'nz-icon nz-icon-a-Networkdevices'
|
||||
}, {
|
||||
value: 'nz-icon nz-icon-Other'
|
||||
}, {
|
||||
value: 'nz-icon nz-icon-a-Virtualmachine'
|
||||
}, {
|
||||
value: 'nz-icon nz-icon-Switch'
|
||||
}, {
|
||||
value: 'nz-icon nz-icon-Server'
|
||||
}, {
|
||||
value: 'nz-icon nz-icon-ADC'
|
||||
}, {
|
||||
value: 'nz-icon nz-icon-Firewall'
|
||||
}, {
|
||||
value: 'nz-icon nz-icon-guide'
|
||||
}, {
|
||||
value: 'nz-icon nz-icon-Silence'
|
||||
}, {
|
||||
value: 'nz-icon nz-icon-fast-silence'
|
||||
}, {
|
||||
value: 'nz-icon nz-icon-mute'
|
||||
}, {
|
||||
value: 'nz-icon nz-icon-overview-alert'
|
||||
}, {
|
||||
value: 'nz-icon nz-icon-overview-endpoint'
|
||||
}, {
|
||||
value: 'nz-icon nz-icon-Alertrule'
|
||||
}, {
|
||||
value: 'nz-icon nz-icon-import-success1'
|
||||
}, {
|
||||
value: 'nz-icon nz-icon-import-failed1'
|
||||
}, {
|
||||
value: 'nz-icon nz-icon-stop'
|
||||
}, {
|
||||
value: 'nz-icon nz-icon-failed'
|
||||
}, {
|
||||
value: 'nz-icon nz-icon-unknown-error'
|
||||
}, {
|
||||
value: 'nz-icon nz-icon-role1'
|
||||
}, {
|
||||
value: 'nz-icon nz-icon-Cabinet1'
|
||||
}, {
|
||||
value: 'nz-icon nz-icon-user1'
|
||||
}, {
|
||||
value: 'nz-icon nz-icon-Datacenter2'
|
||||
}, {
|
||||
value: 'nz-icon nz-icon-overview-project'
|
||||
}, {
|
||||
value: 'nz-icon nz-icon-project'
|
||||
}, {
|
||||
value: 'nz-icon nz-icon-overview-module'
|
||||
}, {
|
||||
value: 'el-icon-share'
|
||||
}, {
|
||||
value: 'el-icon-d-caret'
|
||||
}, {
|
||||
value: 'el-icon-caret-left'
|
||||
}, {
|
||||
value: 'el-icon-caret-right'
|
||||
}, {
|
||||
value: 'el-icon-caret-bottom'
|
||||
}, {
|
||||
value: 'el-icon-caret-top'
|
||||
}, {
|
||||
value: 'el-icon-bottom-left'
|
||||
}, {
|
||||
value: 'el-icon-bottom-right'
|
||||
}, {
|
||||
value: 'el-icon-back'
|
||||
}, {
|
||||
value: 'el-icon-right'
|
||||
}, {
|
||||
value: 'el-icon-bottom'
|
||||
}, {
|
||||
value: 'el-icon-top'
|
||||
}, {
|
||||
value: 'el-icon-top-left'
|
||||
}, {
|
||||
value: 'el-icon-top-right'
|
||||
}, {
|
||||
value: 'el-icon-arrow-left'
|
||||
}, {
|
||||
value: 'el-icon-arrow-right'
|
||||
}, {
|
||||
value: 'el-icon-arrow-down'
|
||||
}, {
|
||||
value: 'el-icon-arrow-up'
|
||||
}, {
|
||||
value: 'el-icon-d-arrow-left'
|
||||
}, {
|
||||
value: 'el-icon-d-arrow-right'
|
||||
}, {
|
||||
value: 'el-icon-video-pause'
|
||||
}, {
|
||||
value: 'el-icon-video-play'
|
||||
}, {
|
||||
value: 'el-icon-refresh'
|
||||
}, {
|
||||
value: 'el-icon-refresh-right'
|
||||
}, {
|
||||
value: 'el-icon-refresh-left'
|
||||
}, {
|
||||
value: 'el-icon-finished'
|
||||
}, {
|
||||
value: 'el-icon-sort'
|
||||
}, {
|
||||
value: 'el-icon-sort-up'
|
||||
}, {
|
||||
value: 'el-icon-sort-down'
|
||||
}, {
|
||||
value: 'el-icon-rank'
|
||||
}, {
|
||||
value: 'nz-icon nz-icon-zhengfangxing'
|
||||
}, {
|
||||
value: 'nz-icon nz-icon-zhixian'
|
||||
}, {
|
||||
value: 'nz-icon nz-icon-sanjiaoxing'
|
||||
}, {
|
||||
value: 'nz-icon nz-icon-xingxing'
|
||||
}, {
|
||||
value: 'nz-icon nz-icon-duobianxing'
|
||||
}, {
|
||||
value: 'nz-icon nz-icon-circle'
|
||||
}
|
||||
]
|
||||
export default iconList
|
||||
@@ -1127,25 +1127,27 @@ export const watermark = {
|
||||
bind (el, binding) {
|
||||
const text = binding.value.text
|
||||
const text1 = binding.value.text1
|
||||
const show = binding.value.show
|
||||
const font = binding.value.font || '24px Roboto-Regular'
|
||||
const textColor = binding.value.textColor || 'rgba(215, 215, 215, 0.5)'
|
||||
const width = binding.value.width || 400
|
||||
const height = binding.value.height || 200
|
||||
const textRotate = binding.value.textRotate || -30
|
||||
addWaterMarker(el, text, font, textColor, width, height, textRotate, text1)
|
||||
addWaterMarker(el, text, font, textColor, width, height, textRotate, show, text1)
|
||||
},
|
||||
update (el, binding) {
|
||||
const text = binding.value.text
|
||||
const text1 = binding.value.text1
|
||||
const show = binding.value.show
|
||||
const font = binding.value.font || '16px Roboto-Regular'
|
||||
const textColor = binding.value.textColor || 'rgba(215, 215, 215, 0.5)'
|
||||
const width = binding.value.width || 400
|
||||
const height = binding.value.height || 200
|
||||
const textRotate = binding.value.textRotate || -20
|
||||
addWaterMarker(el, text, font, textColor, width, height, textRotate, text1)
|
||||
addWaterMarker(el, text, font, textColor, width, height, textRotate, show, text1)
|
||||
},
|
||||
}
|
||||
function addWaterMarker (parentNode, text, font, textColor, width, height, textRotate, text1) {
|
||||
function addWaterMarker (parentNode, text, font, textColor, width, height, textRotate, show, text1) {
|
||||
const can = document.createElement('canvas')
|
||||
parentNode.appendChild(can)
|
||||
can.width = width
|
||||
@@ -1160,5 +1162,9 @@ function addWaterMarker (parentNode, text, font, textColor, width, height, textR
|
||||
cans.textBaseline = 'middle'
|
||||
cans.fillText(text, 200, 150)
|
||||
cans.fillText(text1, 200, 170)
|
||||
parentNode.style.backgroundImage = 'url(' + can.toDataURL('image/png') + ')'
|
||||
if (show) {
|
||||
parentNode.style.backgroundImage = 'url(' + can.toDataURL('image/png') + ')'
|
||||
} else {
|
||||
parentNode.style.backgroundImage = ''
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -3,6 +3,7 @@ import { getUUID, resetZIndex } from '@/components/common/js/common'
|
||||
import { randomcolor, ColorReverse } from '@/components/common/js/radomcolor/randomcolor'
|
||||
import { isStat } from '@/components/chart/chart/tools'
|
||||
import lodash from 'lodash'
|
||||
import iconList from '@/components/common/js/iconList'
|
||||
const rz = {
|
||||
methods: {
|
||||
rz (e) {
|
||||
@@ -79,139 +80,7 @@ export default {
|
||||
value: 'regx'
|
||||
}
|
||||
],
|
||||
mappingIconList: [
|
||||
{
|
||||
value: undefined
|
||||
}, {
|
||||
value: 'nz-icon nz-icon-Router'
|
||||
}, {
|
||||
value: 'nz-icon nz-icon-Computer'
|
||||
}, {
|
||||
value: 'nz-icon nz-icon-a-Networkdevices'
|
||||
}, {
|
||||
value: 'nz-icon nz-icon-Other'
|
||||
}, {
|
||||
value: 'nz-icon nz-icon-a-Virtualmachine'
|
||||
}, {
|
||||
value: 'nz-icon nz-icon-Switch'
|
||||
}, {
|
||||
value: 'nz-icon nz-icon-Server'
|
||||
}, {
|
||||
value: 'nz-icon nz-icon-ADC'
|
||||
}, {
|
||||
value: 'nz-icon nz-icon-Firewall'
|
||||
}, {
|
||||
value: 'nz-icon nz-icon-guide'
|
||||
}, {
|
||||
value: 'nz-icon nz-icon-Silence'
|
||||
}, {
|
||||
value: 'nz-icon nz-icon-fast-silence'
|
||||
}, {
|
||||
value: 'nz-icon nz-icon-mute'
|
||||
}, {
|
||||
value: 'nz-icon nz-icon-overview-alert'
|
||||
}, {
|
||||
value: 'nz-icon nz-icon-overview-endpoint'
|
||||
}, {
|
||||
value: 'nz-icon nz-icon-Alertrule'
|
||||
}, {
|
||||
value: 'nz-icon nz-icon-import-success1'
|
||||
}, {
|
||||
value: 'nz-icon nz-icon-import-failed1'
|
||||
}, {
|
||||
value: 'nz-icon nz-icon-stop'
|
||||
}, {
|
||||
value: 'nz-icon nz-icon-failed'
|
||||
}, {
|
||||
value: 'nz-icon nz-icon-unknown-error'
|
||||
}, {
|
||||
value: 'nz-icon nz-icon-role1'
|
||||
}, {
|
||||
value: 'nz-icon nz-icon-Cabinet1'
|
||||
}, {
|
||||
value: 'nz-icon nz-icon-user1'
|
||||
}, {
|
||||
value: 'nz-icon nz-icon-Datacenter2'
|
||||
}, {
|
||||
value: 'nz-icon nz-icon-overview-project'
|
||||
}, {
|
||||
value: 'nz-icon nz-icon-project'
|
||||
}, {
|
||||
value: 'nz-icon nz-icon-overview-module'
|
||||
}, {
|
||||
value: 'el-icon-share'
|
||||
}, {
|
||||
value: 'el-icon-d-caret'
|
||||
}, {
|
||||
value: 'el-icon-caret-left'
|
||||
}, {
|
||||
value: 'el-icon-caret-right'
|
||||
}, {
|
||||
value: 'el-icon-caret-bottom'
|
||||
}, {
|
||||
value: 'el-icon-caret-top'
|
||||
}, {
|
||||
value: 'el-icon-bottom-left'
|
||||
}, {
|
||||
value: 'el-icon-bottom-right'
|
||||
}, {
|
||||
value: 'el-icon-back'
|
||||
}, {
|
||||
value: 'el-icon-right'
|
||||
}, {
|
||||
value: 'el-icon-bottom'
|
||||
}, {
|
||||
value: 'el-icon-top'
|
||||
}, {
|
||||
value: 'el-icon-top-left'
|
||||
}, {
|
||||
value: 'el-icon-top-right'
|
||||
}, {
|
||||
value: 'el-icon-arrow-left'
|
||||
}, {
|
||||
value: 'el-icon-arrow-right'
|
||||
}, {
|
||||
value: 'el-icon-arrow-down'
|
||||
}, {
|
||||
value: 'el-icon-arrow-up'
|
||||
}, {
|
||||
value: 'el-icon-d-arrow-left'
|
||||
}, {
|
||||
value: 'el-icon-d-arrow-right'
|
||||
}, {
|
||||
value: 'el-icon-video-pause'
|
||||
}, {
|
||||
value: 'el-icon-video-play'
|
||||
}, {
|
||||
value: 'el-icon-refresh'
|
||||
}, {
|
||||
value: 'el-icon-refresh-right'
|
||||
}, {
|
||||
value: 'el-icon-refresh-left'
|
||||
}, {
|
||||
value: 'el-icon-finished'
|
||||
}, {
|
||||
value: 'el-icon-sort'
|
||||
}, {
|
||||
value: 'el-icon-sort-up'
|
||||
}, {
|
||||
value: 'el-icon-sort-down'
|
||||
}, {
|
||||
value: 'el-icon-rank'
|
||||
}, {
|
||||
value: 'nz-icon nz-icon-zhengfangxing'
|
||||
}, {
|
||||
value: 'nz-icon nz-icon-zhixian'
|
||||
}, {
|
||||
value: 'nz-icon nz-icon-sanjiaoxing'
|
||||
}, {
|
||||
value: 'nz-icon nz-icon-xingxing'
|
||||
}, {
|
||||
value: 'nz-icon nz-icon-duobianxing'
|
||||
}, {
|
||||
value: 'nz-icon nz-icon-circle'
|
||||
}
|
||||
], // 获取icon列表
|
||||
mappingIconList: iconList, // 获取icon列表
|
||||
letter: [
|
||||
'A', 'B', 'C', 'D', 'E', 'F', 'G',
|
||||
'H', 'I', 'J', 'K', 'L', 'M', 'N',
|
||||
|
||||
@@ -0,0 +1,253 @@
|
||||
<template>
|
||||
<div v-clickoutside="{obj: editSoftwareType, func: esc}" class="right-box right-box-editSoftwareType right-box-edit-endpoint ">
|
||||
<div class="right-box__header">
|
||||
<div class="header__title">{{editSoftwareType.id ? $t('Edit SoftwareType') : $t('new SoftwareType')}}</div>
|
||||
<div class="header__operation">
|
||||
<span v-cancel="{obj: editSoftwareType, func: esc}"><i class="nz-icon nz-icon-close" :title="$t('overall.close')"></i></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="right-box__container">
|
||||
<div class="container__form">
|
||||
<el-form ref="modelForm" :model="editSoftwareType" :rules="rules" label-position="top" label-width="120px">
|
||||
<!--name-->
|
||||
<el-form-item :label="$t('config.model.name')" prop="name">
|
||||
<el-input maxlength="64" show-word-limit v-model="editSoftwareType.name" size="small" type="text"></el-input>
|
||||
</el-form-item>
|
||||
<!--category-->
|
||||
<el-form-item :label="$t('editSoftwareType.category')" prop="category">
|
||||
<el-input maxlength="64" show-word-limit v-model="editSoftwareType.category" size="small" type="text"></el-input>
|
||||
</el-form-item>
|
||||
<!--icon-->
|
||||
<el-form-item :label="$t('config.menus.icon')" prop="icon">
|
||||
<el-dropdown trigger="click" placement="top-start">
|
||||
<div class="el-dropdown-link">
|
||||
<i v-if="editSoftwareType.icon" class="mapping-icon" :class="editSoftwareType.icon"></i>
|
||||
<div v-else class="mapping-iconSelect" :title="$t('tip.add')">
|
||||
<i class="nz-icon nz-icon-create-square"></i>
|
||||
</div>
|
||||
</div>
|
||||
<el-dropdown-menu slot="dropdown" class="mapping-iconPop">
|
||||
<ul class="mapping-iconList">
|
||||
<li class="mapping-iconItem" :class="{active:editSoftwareType.icon===subItem.value}" v-for="subItem in iconList" @click="iconActive(subItem)" :key="subItem.value">
|
||||
<i :class="subItem.value"></i>
|
||||
</li>
|
||||
</ul>
|
||||
</el-dropdown-menu>
|
||||
</el-dropdown>
|
||||
</el-form-item>
|
||||
<!--params-->
|
||||
<el-form-item :label="$t('config.assetLabel.params')" prop="category">
|
||||
<div id="module-box-params" ref="labelBoxScrollbar" style="height: 100%; overflow-x: auto;">
|
||||
<div v-for="(item, index) in editSoftwareType.paramObj" :key="index" class="param-box-row">
|
||||
<el-form-item :prop="'paramObj.' + index + '.key'" class="param-box-row-key" :rules="[{ pattern: /[a-zA-Z_][a-zA-Z0-9_]*/, message: $t('overall.ASCIIKey') ,trigger: 'blur'}]">
|
||||
<el-input v-model="item.key" placeholder="key" size="mini" ></el-input>
|
||||
</el-form-item>
|
||||
<span class="param-box-row-eq">=</span>
|
||||
<el-form-item :prop="'paramObj.' + index + '.value'" class="param-box-row-value">
|
||||
<vue-tags-input
|
||||
v-model="item.tags"
|
||||
:maxlength="32"
|
||||
:placeholder="$t('overall.addParameter')"
|
||||
:tags="item.value"
|
||||
@tags-changed="(newTags)=>{tagsChange(newTags, index)}"
|
||||
/>
|
||||
</el-form-item>
|
||||
<span :id="'moduel-remove-param-'+index" class="param-box-row-symbol" @click="removeParam(index)" :title="$t('overall.delete')"><i class="nz-icon nz-icon-shanchu1"></i></span>
|
||||
</div>
|
||||
</div>
|
||||
<div style="text-align: center">
|
||||
<span id="module-add-param" class="right-box-form-add module-add-label" type="button" @click="addParam">
|
||||
<span :title="$t('tip.add')"><i class="nz-icon nz-icon-plus" style="font-size: 16px;"></i></span>
|
||||
</span>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<!--remark-->
|
||||
<el-form-item :label="$t('overall.remark')" prop="remark">
|
||||
<el-input maxlength="256" show-word-limit v-model="editSoftwareType.remark" size="small" :rows="2" type="textarea"></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="right-box__footer">
|
||||
<button id="asset-edit-cancel" v-cancel="{obj: editSoftwareType, func: esc}" class="footer__btn footer__btn--light">
|
||||
<span>{{$t('overall.cancel')}}</span>
|
||||
</button>
|
||||
<button id="asset-edit-save" :class="{'footer__btn--disabled': prevent_opt.save}" :disabled="prevent_opt.save" class="footer__btn" @click="save">
|
||||
<span>{{$t('overall.save')}}</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// import { host, port } from '@/components/common/js/validate'
|
||||
import selectWalk from '../../popBox/selectWalk'
|
||||
import editRigthBox from '../../mixin/editRigthBox'
|
||||
import { sysObjectIdInput } from '@/components/common/js/validate'
|
||||
import iconList from '@/components/common/js/iconList'
|
||||
import VueTagsInput from '@johmun/vue-tags-input'
|
||||
import bus from '@/libs/bus'
|
||||
|
||||
export default {
|
||||
name: 'modelBox',
|
||||
components: {
|
||||
'select-walk': selectWalk,
|
||||
VueTagsInput
|
||||
},
|
||||
props: {
|
||||
obj: {
|
||||
type: Object
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
isCurrentUser () {
|
||||
return function (username) {
|
||||
return localStorage.getItem('nz-username') == username
|
||||
}
|
||||
},
|
||||
language () { return this.$store.getters.getLanguage }
|
||||
},
|
||||
mixins: [editRigthBox],
|
||||
data () {
|
||||
return {
|
||||
iconList: iconList,
|
||||
editSoftwareType: {
|
||||
id: '',
|
||||
name: '',
|
||||
category: '',
|
||||
icon: undefined,
|
||||
params: {
|
||||
},
|
||||
paramObj: [],
|
||||
remark: ''
|
||||
},
|
||||
brandList: [], // brand 列表数据
|
||||
editModule: {},
|
||||
typeDataList: [],
|
||||
// chartlList: [], // chart 列表数据
|
||||
dashboardList: [], // dashboard 列表数据
|
||||
// ChartSearchShowFields: [ // ChartSearch 下拉搜索表头
|
||||
// { title: 'ID', data: 'id' },
|
||||
// { title: this.$t('overall.name'), data: 'name', key: 'name' },
|
||||
// { title: this.$t('overall.type'), data: 'type', key: 'type' },
|
||||
// { title: this.$t('overall.remark'), data: 'remark', key: 'remark' }
|
||||
// ],
|
||||
DashboardSearchShowFields: [ // DashboardSearch 下拉搜索表头
|
||||
{ title: 'ID', data: 'id' },
|
||||
{ title: this.$t('overall.name'), data: 'name', key: 'name' },
|
||||
{ title: this.$t('overall.remark'), data: 'remark', key: 'remark' }
|
||||
],
|
||||
url: 'asset/model',
|
||||
brandUrl: 'asset/brand',
|
||||
rightBox: { model: { show: false } },
|
||||
roles: [],
|
||||
rules: {
|
||||
name: [
|
||||
{ required: true, message: this.$t('validate.required'), trigger: 'blur' }
|
||||
],
|
||||
brandId: [
|
||||
{ required: true, message: this.$t('validate.required'), trigger: 'change' }
|
||||
],
|
||||
typeId: [
|
||||
{ required: true, message: this.$t('validate.required'), trigger: 'change' }
|
||||
],
|
||||
sysObjectId: [
|
||||
{ validator: sysObjectIdInput, trigger: 'blur' }
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
obj: {
|
||||
deep: true,
|
||||
immediate: true,
|
||||
handler (n) {
|
||||
this.isEdit = true
|
||||
const editSoftwareType = JSON.parse(JSON.stringify(n))
|
||||
editSoftwareType.paramObj = []
|
||||
if (editSoftwareType.params) {
|
||||
Object.keys(editSoftwareType.params).forEach(key => {
|
||||
editSoftwareType.paramObj.push({
|
||||
key,
|
||||
value: editSoftwareType.params[key]
|
||||
})
|
||||
})
|
||||
}
|
||||
if (!editSoftwareType.paramObj.length) {
|
||||
editSoftwareType.paramObj.push({ key: '', value: [] })
|
||||
}
|
||||
this.editSoftwareType = editSoftwareType
|
||||
}
|
||||
}
|
||||
},
|
||||
created () {
|
||||
},
|
||||
methods: {
|
||||
clickOutside () {
|
||||
this.esc(false)
|
||||
},
|
||||
iconActive (subItem) {
|
||||
console.log(subItem, this.editSoftwareType.icon)
|
||||
if (this.editSoftwareType.icon === subItem.value) {
|
||||
this.editSoftwareType.icon = undefined
|
||||
this.$set(this.editSoftwareType, 'icon', '')
|
||||
} else {
|
||||
this.editSoftwareType.icon = subItem.value
|
||||
this.$set(this.editSoftwareType, 'icon', subItem.value)
|
||||
}
|
||||
},
|
||||
/* 关闭弹框 */
|
||||
esc (refresh) {
|
||||
this.prevent_opt.save = false
|
||||
this.$emit('close', refresh)
|
||||
},
|
||||
save () {
|
||||
this.$refs.modelForm.validate((valid) => {
|
||||
if (valid) {
|
||||
const params = {
|
||||
...this.editSoftwareType
|
||||
}
|
||||
if (this.editSoftwareType.id) {
|
||||
this.$put(this.url, params).then(res => {
|
||||
this.prevent_opt.save = false
|
||||
if (res.code === 200) {
|
||||
this.$message({ duration: 2000, type: 'success', message: this.$t('tip.saveSuccess') })
|
||||
this.esc(true)
|
||||
} else {
|
||||
this.$message.error(res.msg)
|
||||
}
|
||||
})
|
||||
} else {
|
||||
this.$post(this.url, params).then(res => {
|
||||
this.prevent_opt.save = false
|
||||
if (res.code === 200) {
|
||||
this.$message({ duration: 2000, type: 'success', message: this.$t('tip.saveSuccess') })
|
||||
this.esc(true)
|
||||
} else {
|
||||
this.$message.error(res.msg)
|
||||
}
|
||||
})
|
||||
}
|
||||
} else {
|
||||
this.prevent_opt.save = false
|
||||
return false
|
||||
}
|
||||
})
|
||||
},
|
||||
tagsChange (newTags, index) {
|
||||
this.editSoftwareType.paramObj[index].value = newTags.map(item => item.text)
|
||||
},
|
||||
// 新增param
|
||||
addParam () {
|
||||
this.editSoftwareType.paramObj.push({ key: '', value: [] })
|
||||
},
|
||||
// 移除单个param
|
||||
removeParam (index) {
|
||||
if (this.editSoftwareType.paramObj.length === 1) {
|
||||
this.editSoftwareType.paramObj = [{ key: '', value: [] }]
|
||||
}
|
||||
this.editSoftwareType.paramObj.splice(index, 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -184,8 +184,9 @@
|
||||
<el-dropdown-item v-has="'alertSilence_add'" :command="['fastSilence', scope.row, 'endpoint']"><i class="nz-icon nz-icon-fast-silence"></i><span class="operation-dropdown-text">{{$t('overall.silenceAlert')}}</span></el-dropdown-item>
|
||||
<el-dropdown-item v-has="'asset_add'" :command="['topology', scope.row, 'endpoint']"><i class="nz-icon nz-icon-Topology"></i><span class="operation-dropdown-text">{{$t('overall.topology')}}</span></el-dropdown-item>
|
||||
<el-dropdown-item v-has="'monitor_endpoint_add'" :command="['diagnosis', scope.row,{from:'endpoint'}]"><i class="nz-icon nz-icon-diagnosis"></i><span class="operation-dropdown-text">{{$t('overall.diagnosis')}}</span></el-dropdown-item>
|
||||
<el-dropdown-item v-has="'monitor_endpoint_add'" :command="['metricTarget', scope.row, 'endpoint']" :disabled="scope.row.configs[0].config.protocol !== ('http'||'https')"><i class="nz-icon nz-icon-Metrics"></i><span class="operation-dropdown-text">{{$t('endpoints.metricTarget')}}</span></el-dropdown-item>
|
||||
<el-dropdown-item v-if="scope.row.configs[0].enable" v-has="'monitor_endpoint_add'" :command="['metricTarget', scope.row, 'endpoint']" :disabled="scope.row.configs[0].config.protocol !== ('http'||'https')"><i class="nz-icon nz-icon-Metrics"></i><span class="operation-dropdown-text">{{$t('endpoints.metricTarget')}}</span></el-dropdown-item>
|
||||
<el-dropdown-item v-has="'monitor_endpoint_edit'" :command="['configSync', scope.row,{from:'endpoint'}]"><i class="nz-icon nz-icon-sync"></i><span class="operation-dropdown-text">{{$t('overall.synchronize')}}</span></el-dropdown-item>
|
||||
|
||||
</el-dropdown-menu>
|
||||
</el-dropdown>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,160 @@
|
||||
<template>
|
||||
<el-table
|
||||
id="softwareTypeTable"
|
||||
ref="dataTable"
|
||||
:data="tableData"
|
||||
:height="height"
|
||||
border
|
||||
:default-sort="orderBy"
|
||||
@header-dragend="dragend"
|
||||
@sort-change="tableDataSort"
|
||||
@selection-change="selectionChange"
|
||||
@row-dblclick="(row)=>{}"
|
||||
>
|
||||
<el-table-column
|
||||
:resizable="false"
|
||||
align="center"
|
||||
type="selection"
|
||||
width="55">
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
v-for="(item, index) in customTableTitle"
|
||||
v-if="item.show"
|
||||
:key="`col-${index}-${item.prop}`"
|
||||
:fixed="item.fixed"
|
||||
:label="item.label"
|
||||
:min-width="`${item.minWidth}`"
|
||||
:prop="item.prop"
|
||||
:resizable="true"
|
||||
:sort-orders="['ascending', 'descending']"
|
||||
:sortable="item.sortable"
|
||||
:width="`${item.width}`"
|
||||
>
|
||||
<template slot="header">
|
||||
<span class="data-column__span">{{item.label}}</span>
|
||||
<div class="col-resize-area"></div>
|
||||
</template>
|
||||
<template slot-scope="scope" :column="item">
|
||||
<template v-if="item.prop === 'roles'">
|
||||
<template v-if="scope.row[item.prop]">
|
||||
{{scope.row[item.prop].map(t=>t.name).join(',')}}
|
||||
</template>
|
||||
<template v-else>
|
||||
<span>-</span>
|
||||
</template>
|
||||
</template>
|
||||
<template v-else-if="item.prop === 'name'">
|
||||
<copy :copyData='scope.row[item.prop]' :showInfo='scope.row[item.prop]'>
|
||||
<template slot="copy-text">
|
||||
{{scope.row[item.prop]?scope.row[item.prop]:'-'}}
|
||||
</template>
|
||||
</copy>
|
||||
</template>
|
||||
<span v-else-if="scope.row[item.prop]" :class="item.prop === 'remark'? 'el-table-remark':''">{{scope.row[item.prop]}}</span>
|
||||
<span v-else>-</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
:resizable="false"
|
||||
:width="operationWidth"
|
||||
fixed="right">
|
||||
<div slot="header" class="table-operation-title">{{$t('overall.option')}}</div>
|
||||
<div slot-scope="scope" class="table-operation-items">
|
||||
<!-- <button class="table-operation-item" v-has="'model_edit'" @click="$emit('edit', scope.row)" :title="$t('overall.edit')"><i class="nz-icon nz-icon-edit"></i></button> -->
|
||||
<button class="table-operation-item" @click="showBottomBox('asset', scope.row)" :title="$t('overall.view')"><i class="nz-icon nz-icon-view1"></i></button>
|
||||
<el-dropdown size="medium" v-has="['model_delete','main_edit','model_edit']" trigger="click" @command="tableOperation">
|
||||
<div class="table-operation-item table-operation-item--more" :title="$t('overall.moreOperations')">
|
||||
<i class="nz-icon nz-icon-more3"></i>
|
||||
</div>
|
||||
<el-dropdown-menu slot="dropdown" class="right-box-select-top right-public-box-dropdown-top">
|
||||
<el-dropdown-item v-has="'model_edit'" :command="['edit', scope.row]"><i class="nz-icon nz-icon-edit"></i><span class="operation-dropdown-text">{{$t('overall.edit')}}</span></el-dropdown-item>
|
||||
<el-dropdown-item v-has="'model_edit'" :command="['copy', scope.row]"><i class="nz-icon nz-icon-override"></i><span class="operation-dropdown-text">{{$t('overall.duplicate')}}</span></el-dropdown-item>
|
||||
<el-dropdown-item v-has="'model_delete'" :command="['delete-rel', scope.row, {forceDeleteShow:true, single:true,from:'model'}]"><i class="nz-icon nz-icon-delete"></i><span class="operation-dropdown-text">{{$t('overall.delete')}}</span></el-dropdown-item>
|
||||
<el-dropdown-item v-has="'main_edit'" :command="['sync', scope.row]"><i class="nz-icon nz-icon-sync"></i><span class="operation-dropdown-text">{{$t('overall.syncChart')}}</span></el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</el-dropdown>
|
||||
</div>
|
||||
</el-table-column>
|
||||
<template slot="empty">
|
||||
<div v-if="!loading" class="table-no-data">
|
||||
<svg class="icon" aria-hidden="true">
|
||||
<use xlink:href="#nz-icon-no-data-list"></use>
|
||||
</svg>
|
||||
<div class="table-no-data__title">No results found</div>
|
||||
</div>
|
||||
<div v-else> </div>
|
||||
</template>
|
||||
</el-table>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import table from '@/components/common/mixin/table'
|
||||
import copy from '@/components/common/copy'
|
||||
export default {
|
||||
name: 'softwareTypeTable',
|
||||
mixins: [table],
|
||||
components: { copy },
|
||||
props: {
|
||||
loading: Boolean
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
tableTitle: [ // 原始table列
|
||||
{
|
||||
label: 'ID',
|
||||
prop: 'id',
|
||||
show: true,
|
||||
width: 80,
|
||||
sortable: 'custom'
|
||||
}, {
|
||||
label: this.$t('config.model.name'),
|
||||
prop: 'name',
|
||||
show: true,
|
||||
minWidth: 350,
|
||||
sortable: 'custom'
|
||||
}, {
|
||||
label: this.$t('category'),
|
||||
prop: 'category',
|
||||
show: true,
|
||||
width: 200,
|
||||
sortable: 'custom'
|
||||
}, {
|
||||
label: this.$t('icon'),
|
||||
prop: 'icon',
|
||||
show: true,
|
||||
width: 120,
|
||||
sortable: 'custom'
|
||||
}, {
|
||||
label: this.$t('params'),
|
||||
prop: 'params',
|
||||
minWidth: 200,
|
||||
show: false
|
||||
}, {
|
||||
label: this.$t('cts'),
|
||||
prop: 'cts',
|
||||
minWidth: 200,
|
||||
show: false
|
||||
}, {
|
||||
label: this.$t('uts'),
|
||||
prop: 'uts',
|
||||
minWidth: 200,
|
||||
show: false
|
||||
}, {
|
||||
label: this.$t('overall.remark'),
|
||||
prop: 'remark',
|
||||
minWidth: 200,
|
||||
show: true
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
||||
},
|
||||
created () {
|
||||
},
|
||||
computed: {
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
138
nezha-fronted/src/components/page/software/softwareType.vue
Normal file
138
nezha-fronted/src/components/page/software/softwareType.vue
Normal file
@@ -0,0 +1,138 @@
|
||||
<template>
|
||||
<div>
|
||||
<nz-data-list
|
||||
ref="dataList"
|
||||
:api="url"
|
||||
:custom-table-title.sync="tools.customTableTitle"
|
||||
:from="fromRoute.model"
|
||||
:layout="['searchInput', 'elementSet', 'pagination']"
|
||||
:search-msg="searchMsg"
|
||||
@search="search"
|
||||
>
|
||||
<template v-slot:top-tool-right>
|
||||
<button id="account-add" v-has="'model_add'" :title="$t('overall.createSoftwareType')" class="top-tool-btn margin-r-10" type="button" @click="add">
|
||||
<i class="nz-icon-create-square nz-icon"></i>
|
||||
</button>
|
||||
<top-tool-more-options
|
||||
:delete-objs="batchDeleteObjs"
|
||||
ref="export"
|
||||
id="model"
|
||||
:params="searchLabel"
|
||||
:permissions="{
|
||||
import: 'model_add',
|
||||
export: 'model_edit'
|
||||
}"
|
||||
class="top-tool-export margin-r-10"
|
||||
export-file-name="asset-model"
|
||||
@afterImport="getTableData"
|
||||
v-has="['model_add','model_edit','model_delete']"
|
||||
>
|
||||
<template v-slot:before>
|
||||
<div>
|
||||
<el-dropdown-item :disabled="batchDeleteObjs.length==0" :class="'nz-el-dropdown-menu-item'">
|
||||
<delete-button
|
||||
ref="deleteButton"
|
||||
:single="false"
|
||||
:from="'model'"
|
||||
:forceDeleteShow="true"
|
||||
:type="'link'"
|
||||
:title="$t('overall.batchDel')"
|
||||
id="account-list-batch-delete"
|
||||
v-has="'model_delete'"
|
||||
:api="url"
|
||||
:delete-objs="batchDeleteObjs"
|
||||
@after="getTableData"
|
||||
@before="delFlag=true"
|
||||
></delete-button>
|
||||
</el-dropdown-item>
|
||||
</div>
|
||||
</template>
|
||||
</top-tool-more-options>
|
||||
</template>
|
||||
<template v-slot="slotProps">
|
||||
<softwareTypeTable
|
||||
|
||||
ref="dataTable"
|
||||
:orderByFa="orderBy"
|
||||
v-my-loading="tools.loading"
|
||||
:loading="tools.loading"
|
||||
:api="url"
|
||||
:custom-table-title="tools.customTableTitle"
|
||||
:height="mainTableHeight"
|
||||
:table-data="tableData"
|
||||
@del="del"
|
||||
@edit="edit"
|
||||
@copy="copy"
|
||||
@orderBy="tableDataSort"
|
||||
@reload="getTableData"
|
||||
@selectionChange="selectionChange"
|
||||
@showBottomBox="(targetTab, object) => { $refs.dataList.showBottomBox(targetTab, object) }"></softwareTypeTable>
|
||||
</template>
|
||||
<template v-slot:pagination>
|
||||
<Pagination ref="Pagination" :page-obj="pageObj" :table-id="tableId" @pageNo='pageNo' @pageSize='pageSize'></Pagination>
|
||||
</template>
|
||||
</nz-data-list>
|
||||
<transition name="right-box">
|
||||
<softwareTypeBox v-if="rightBox.show" :obj="object" @close="closeRightBox"></softwareTypeBox>
|
||||
</transition>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import deleteButton from '@/components/common/deleteButton'
|
||||
import softwareTypeBox from '@/components/common/rightBox/software/softwareTypeBox'
|
||||
import nzDataList from '@/components/common/table/nzDataList'
|
||||
import dataListMixin from '@/components/common/mixin/dataList'
|
||||
import softwareTypeTable from '@/components/common/table/settings/softwareTypeTable'
|
||||
import topToolMoreOptions from '@/components/common/popBox/topToolMoreOptions'
|
||||
|
||||
export default {
|
||||
name: 'softwareType',
|
||||
components: {
|
||||
nzDataList,
|
||||
softwareTypeBox,
|
||||
deleteButton,
|
||||
softwareTypeTable,
|
||||
topToolMoreOptions
|
||||
},
|
||||
mixins: [dataListMixin],
|
||||
data () {
|
||||
return {
|
||||
url: '/asset/software/type',
|
||||
blankObject: { // 空白对象
|
||||
id: '',
|
||||
name: '',
|
||||
category: '',
|
||||
icon: '',
|
||||
params: {
|
||||
},
|
||||
remark: ''
|
||||
},
|
||||
tableId: 'softwareTypeTable',
|
||||
searchMsg: { // 给搜索框子组件传递的信息
|
||||
searchLabelList: [{
|
||||
name: 'ID',
|
||||
type: 'input',
|
||||
label: 'ids',
|
||||
disabled: false
|
||||
}, {
|
||||
name: this.$t('overall.name'),
|
||||
type: 'input',
|
||||
label: 'name',
|
||||
disabled: false
|
||||
}]
|
||||
}
|
||||
}
|
||||
},
|
||||
created () {
|
||||
|
||||
},
|
||||
computed: {
|
||||
},
|
||||
mounted () {
|
||||
},
|
||||
methods: {
|
||||
},
|
||||
beforeDestroy () {
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -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'
|
||||
|
||||
@@ -8,7 +8,7 @@ import VueResource from 'vue-resource'
|
||||
import bus from '@/libs/bus'
|
||||
Vue.use(VueResource)
|
||||
|
||||
const loginWhiteList = ['/setup', '/sys/license/upload', '/sys/license/state', '/sys/appearance', '/i18n', '/terminal'] // 免登陆白名单
|
||||
const loginWhiteList = ['/setup', '/sys/license/upload', '/sys/license/state', '/sys/appearance', '/i18n', '/terminal', '/softwareType'] // 免登陆白名单
|
||||
export const permissionWhiteList = ['/profile', '/menu', ...loginWhiteList] // 权限白名单
|
||||
router.beforeEach((to, from, next) => {
|
||||
if (window.entrance) {
|
||||
|
||||
@@ -231,6 +231,10 @@ export default new Router({
|
||||
{
|
||||
path: '/integration',
|
||||
component: resolve => require(['@/components/page/integration/integration'], resolve)
|
||||
},
|
||||
{
|
||||
path: '/softwareType',
|
||||
component: resolve => require(['@/components/page/software/softwareType'], resolve)
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user