feat: asset基本功能

This commit is contained in:
chenjinsong
2021-04-23 19:58:08 +08:00
parent 73f34335a2
commit 5cce046423
13 changed files with 365 additions and 1197 deletions

View File

@@ -43,3 +43,6 @@
top: 44px;
transform: translate(-50%, -54px);
}
.el-checkbox__inner, .el-input__inner {
border-color: rgba(0,0,0,0.15)
}

View File

@@ -324,6 +324,35 @@
.operation-dropdown-text {
font-size: 13px;
}
.search-box {
padding-bottom: 20px;
padding: 0 20px 20px;
.nz-label-search {
margin-right: 20px;
.el-input__inner:focus, .el-cascader .el-input.is-focus .el-input__inner {
border-color: #c7c7c7 !important;
}
.el-input__inner {
height: 24px !important;
width: 140px;
}
}
}
.click-search-dropdown {
width: calc(100% - 300px) !important;
left: 270px !important;
margin-top: -3px !important;
box-shadow: none;
box-sizing: border-box;
border-radius: 0;
border-color: #c7c7c7;
.popper__arrow {
display: none;
}
.el-cascader-menu__list {
display: flex;
}
}

View File

@@ -1,11 +1,24 @@
<template>
<div class="search-box" :style="{'height':height+ 'px'}">
<div v-for="(searchKey,index) in titleSearchListCopy" :key="index" v-if="searchKey.show" class="search-content-box">
<label class="search-title">{{searchKey.label}}:</label>
<el-checkbox-group v-model="selectValueOut[searchKey.key]" v-if="searchKey.type === 'checkBox'" ref="searchContent" class="search-content">
<el-checkbox v-for="(item, j) in searchKey.children" :label="item.value" :key="j" v-show="!searchKey.showMore || j < searchKey.index">{{item.key || item.name || item.label}}</el-checkbox>
<div class="search-box__container">
<div v-for="(data, type, index) in titleSearchListCopy" v-if="data.show" :key="index" class="search-content-box">
<label class="search-title">{{data.label}}:</label>
<el-checkbox-group v-if="data.type === 'checkBox'" ref="searchContent" v-model="selectValueOut[data.key]">
<template v-for="(item, j) in data.children">
<el-checkbox v-if="j < 20" v-show="!data.showMore || j < data.index" :key="j" :label="item.value">{{item.key || item.name || item.label}}</el-checkbox>
</template>
</el-checkbox-group>
<span class="search-more" @click="changShowMore(index)" v-show="contentWidth <= searchKey.width">更多 <i class="nz-icon" :class="searchKey.showMore?'nz-icon-arrow-down':'nz-icon-arrow-up'"/></span>
<div v-for="(item, j) in data.children" v-else-if="data.type === 'dropdownCheckBox'" :key="j" class="nz-label-search">
<el-cascader
:ref="`${type}_cascader`"
:options="item.children"
:placeholder="item.name"
:props="{ multiple: true, label: 'name', value: 'id' }"
popper-class="click-search-dropdown"
size="mini"
@change="casChange(type, data.key)"
></el-cascader>
</div>
<span v-show="contentWidth <= data.width" class="search-more" @click="changShowMore(index)">更多 <i :class="data.showMore?'el-icon-arrow-down':'el-icon-arrow-up'"/></span>
</div>
</div>
</template>
@@ -42,10 +55,6 @@ export default {
},
selectValue: {
type: Object
},
height: {
type: Number,
default: 116
}
},
computed: { },
@@ -65,7 +74,6 @@ export default {
deep: true,
handler (n) {
this.selectValueOut = { ...n }
// this.$emit('reload', this.selectValue)
}
},
selectValueOut: {
@@ -87,15 +95,40 @@ export default {
window.addEventListener('resize', this.needMore)
},
methods: {
casChange (type, key) {
const cascs = this.$refs[`${type}_cascader`]
if (type === 'assetLabel') { // label特殊处理组织成{“id”:[“张三”,"lw"],"id":["李四"]}
const values = {}
cascs.forEach(c => {
const nodes = c.getCheckedNodes()
nodes.forEach(n => {
const metaId = n.data.metaId
if (values[`${metaId}`]) {
values[`${metaId}`].push(n.data.name)
} else {
values[`${metaId}`] = [n.data.name]
}
})
})
this.selectValueOut[key] = JSON.stringify(values)
} else {
const values = new Set()
cascs.forEach(c => {
const nodes = c.getCheckedNodes()
nodes.forEach(n => values.add(n.data.id))
})
this.selectValueOut[key] = [...values]
}
},
needMore (key) {
setTimeout(() => {
/* setTimeout(() => {
this.contentWidth = this.$refs.searchContent[0].$el.offsetWidth
Object.keys(this.titleSearchListCopy).forEach(key => {
this.titleSearchListCopy[key].width = 0
this.titleSearchListCopy[key].showMore = false
this.titleSearchListCopy[key].children.forEach((item, i) => {
/* (基础宽度 + 文字宽度) 总和 》 文本长时 显示更多 */
/!* (基础宽度 + 文字宽度) 总和 》 文本长时 显示更多 *!/
this.titleSearchListCopy[key].width += 60 + item.name.length * 12
if (this.titleSearchListCopy[key].width > this.contentWidth && !this.titleSearchListCopy[key].showMore) {
this.titleSearchListCopy[key].showMore = true
@@ -103,7 +136,7 @@ export default {
}
})
}, 100)
})
}) */
},
changShowMore (key) {
this.titleSearchListCopy[key].showMore = !this.titleSearchListCopy[key].showMore
@@ -115,56 +148,55 @@ export default {
}
</script>
<style scoped>
.search-box{
background: #FFFFFF;
border: 1px solid #E7EAED;
margin: 0 20px;
<style lang="scss" scoped>
.search-box__container {
display: flex;
flex-direction: column;
justify-content: space-between;
border: 1px solid #E7EAED;
background-color: #FFFFFF;
overflow-x: hidden;
overflow-y: auto;
padding-top: 20px;
padding-bottom: 0;
padding: 15px 0 15px 17px;
}
.search-title {
ont-family: Roboto-Medium;
position: absolute;
width: 130px;
left: 0;
line-height: 18px;
font-size: 14px;
color: #666666;
letter-spacing: 0;
line-height: 14px;
font-weight: 500;
width: 130px;
overflow: hidden;
}
.search-content-box {
display: flex;
width: 100%;
flex: 1;
padding-left: 20px;
align-items: center;
flex-wrap: wrap;
position: relative;
}
/deep/ .el-checkbox-group{
flex: 1;
}
/deep/ .el-checkbox{
margin-bottom: 10px;
}
.search-content{
padding-right: 30px;
padding-left: 130px;
padding-right: 80px;
width: calc(100vw - 333px);
box-sizing: border-box;
}
.search-more {
position: absolute;
right: 30px;
top: 0;
right: 0;
top: 50%;
height: 22px;
line-height: 22px;
padding: 0 8px;
transform: translateY(-50%);
font-size: 12px;
color: #333333;
letter-spacing: 0;
line-height: 16px;
font-weight: 400;
border: 1px solid #DEDEDE;
box-sizing: border-box;
border: 1px solid $--primary-border-color;
border-radius: 2px;
padding: 3px 5px;
i {
color: #999;
font-size: 12px;
}
}
</style>

View File

@@ -1,47 +0,0 @@
<template>
<div>
<Header ref="header"></Header>
<!--<div class="content-box" >
<router-view/>
</div>-->
<left-menu ></left-menu>
<menus v-if="isMenuPage"></menus>
<web-ssh ref="webSsh" ></web-ssh>
<span class="el-popover table-tooltip"></span>
</div>
</template>
<script>
import Header from './header'
import webSSH from '../cli/webSSH'
import leftMenu from './leftMenu'
import menus from '../page/config/menus'
export default {
name: 'home',
components: {
Header,
'web-ssh': webSSH,
'left-menu': leftMenu,
menus
},
computed: {
isMenuPage: function () {
return this.$route.path == '/menu'
}
}
}
</script>
<style scoped>
/*@media screen and (max-width: 1600px) {
.content-box {
background: #a0eea6;
}
}
@media screen and (max-width: 700px) {
.content-box {
background: #b94b7e;
}
}*/
</style>

View File

@@ -80,12 +80,10 @@ export const asset = {
{ value: 3, label: i18n.t('asset.suspended') }
],
authProtocolOptions: [
{ value: 0, label: 'Non' },
{ value: 1, label: 'SSH' },
{ value: 2, label: 'TELNET' }
],
authProtocolData: {
non: 0,
ssh: 1,
telnet: 2
},

View File

@@ -503,115 +503,11 @@ const cn = {
assetType: '资产类型', // '资产类型'
batchEditAsset: '批量修改资产',
selectAsset: '已选择的资产',
editAssetTab: {
title: '新增资产',
sn: 'SN',
host: '主机',
state: '状态',
modelId: '模块',
alert: '告警信息',
assetInfo: '资产信息',
assetType: '资产类型',
vendor: '厂商/型号',
vendorTab: {
vendor: '厂商/型号',
vendorName: '新厂商',
existVendor: '已有厂商',
modelName: '新型号',
existModel: '已有型号'
},
purchaseDate: '购买日期',
dataSelectTip: '请选择日期',
dc: '数据中心',
dcName: '数据中心名称',
AddIdcTab: {
title: '新增数据中心',
dcName: '数据中心名称',
location: '地区',
principal: '负责人',
tel: '电话'
},
editIdcTab: {
title: '编辑数据中心',
dcName: '数据中心名称',
location: '地区',
principal: '负责人',
tel: '电话'
},
location: '地区',
principal: '负责人',
tel: '电话',
cabinet: '机柜',
AddCabinetTab: {
title: '新增机柜',
name: '名称',
uSize: 'U位',
remark: '描述',
DC: '数据中心'
},
editCabinetTab: {
title: '编辑机柜',
name: '名称',
uSize: 'U位',
remark: '描述',
DC: '数据中心'
},
uSize: 'U位',
remark: '描述',
cli: 'CLI账号',
loginType: '登录类型',
password: '密码',
ssh: 'SSH-Key',
account: '用户名',
port: '端口',
upload: '上传',
clickToUpload: '上传'
},
tableTitle: {
id: 'ID',
assetType: '资产类型',
device: 'SN',
host: 'Host',
assetState: '状态',
modules: 'Endpoint',
alerts: '告警信息',
dataCenter: '数据中心',
cabinet: '机柜',
model: '型号',
manufacturer: '厂商',
procurementDate: '购买日期',
principal: '负责人',
principalTel: '电话',
option: '操作',
assetPing: 'Ping',
lastReply: 'Ping最后应答',
vendor: '厂商',
sn: 'SN',
name: 'Name',
manageIp: 'manageIp',
brand: '品牌',
dc: '数据中心',
type: '主机地址',
state: '主机状态',
endpoint: 'Endpoint'
},
tagTableTitle: {
projectName: '系统名称',
moduleName: '模块名称',
endPoint: 'EndPoint',
alert: '告警'
},
assets: '资产',
pingActive: '存活',
assetStatPre: '最后应答:',
assetStatDown: '未Ping通',
pingInactive: '宕机',
left: {
dataCenter: '数据中心',
assetType: '资产类型',
vendor: '厂商',
ping: 'Ping'
},
editAsset: '编辑资产',
createAsset: '新增资产',
host: 'Host',
@@ -665,7 +561,8 @@ const cn = {
privateKey: '秘钥',
usernamePrompt: '用户名提示',
passwordPrompt: '密码提示',
snmpCredential: 'SNMP凭证'
snmpCredential: 'SNMP凭证',
authProtocol: '认证协议'
},
config: {
config: '设置',

View File

@@ -551,111 +551,9 @@ const en = {
assetType: 'Asset type', // '资产类型'
principal: 'Administrator', // '负责人'
tel: 'Telephone', // '电话'
left: {
dataCenter: 'Data center',
vendor: 'Vendor',
ping: 'Ping'
},
featureTitle: 'Attribute',
endpointUpNum: 'It\'s a normal number',
endpointNum: 'Represents the total quantity',
editAssetTab: {
title: 'New asset', // '新增资产'
sn: 'SN', // SN
host: 'Host', // 'Host'
state: 'State', // '状态'
modelId: 'Module', // '组件'
alert: 'Alert information', // '告警信息'
assetInfo: 'Asset information', // '资产信息'
assetType: 'Asset type', // '资产类型'
vendor: 'Vendor', // '厂商/型号'
vendorTab: {
vendor: 'Vendor/Model', // '厂商/型号'
vendorName: 'New vendor', // '新厂商'
existVendor: 'Existed vendor', // '已有厂商'
modelName: 'New model', // '新型号'
existModel: 'Existed model'// '已有型号'
},
purchaseDate: 'Purchase date', // '购买日期'
dataSelectTip: 'Please select date', // '请选择日期'
dc: 'Data center',
dcName: 'Data center name', // 'DC名称'
AddIdcTab: {
title: 'New Data center', // '新增DC'
dcName: 'Data center name', // 'DC名称'
location: 'Location', // '地区'
principal: 'Administrator', // '负责人'
tel: 'Telephone'// '电话'
},
editIdcTab: {
title: 'Edit Data center', // '编辑DC'
dcName: 'Data center name', // 'DC名称'
location: 'Location', // '地区'
principal: 'Administrator', // '负责人'
tel: 'Telephone'// '电话'
},
location: 'Location', // '地区'
principal: 'Administrator', // '负责人'
tel: 'Telephone', // '电话'
cabinet: 'Cabinet', // '机柜'
AddCabinetTab: {
title: 'New cabinet', // '新增机柜'
name: 'Name', // '名称'
uSize: 'U size', // 'U位'
remark: 'Description', // '描述'
DC: 'Data center'// DC
},
editCabinetTab: {
title: 'Edit cabinet', // '编辑机柜'
name: 'Name', // '名称'
uSize: 'U size', // 'U位'
remark: 'Description', // '描述'
DC: 'Data center'// DC
},
uSize: 'U size', // 'U位'
remark: 'Description', // '描述'
cli: 'CLI account', // 'CLI账号'
loginType: 'Login type', // '登录类型'
password: 'Password', // '密码'
ssh: 'SSH-Key', // 'SSH-Key'
account: 'Username', // '用户名'
port: 'Port', // '端口'
upload: 'Upload', // '上传'
clickToUpload: 'Upload'// '上传'
},
tableTitle: {
id: 'ID', // ID
assetType: 'Asset type', // '资产类型'
device: 'SN', // SN
host: 'Host', // 'Host'
assetState: 'State', // '状态'
assetPing: 'Ping',
lastReply: 'Ping last reply',
modules: 'Endpoint', // '组件'
alerts: 'Alerts', // '告警信息'
dataCenter: 'Data center', // DC
cabinet: 'Cabinet', // '机柜'
model: 'Model', // '型号'
vendor: 'Vendor', // '厂商'
procurementDate: 'Purchase date', // '购买日期'
principal: 'Administrator', // '负责人'
principalTel: 'Telephone', // '电话'
option: 'Operation', // "操作"
sn: 'SN',
name: 'Name',
manageIp: 'manageIp',
brand: 'Brand',
dc: 'DataCenter',
type: 'Types',
state: 'State',
endpoint: 'Endpoint'
},
tagTableTitle: {
projectName: 'Project name', // '系统名称'
moduleName: 'Module name', // '组件名称'
endPoint: 'End point', // 'EndPoint'
alert: 'Alert'// '告警'
},
active: 'Alive', // "存活",
total: 'Total', // "总数",
down: 'Down',
@@ -671,7 +569,8 @@ const en = {
privateKey: 'Private key',
usernamePrompt: 'Username prompt',
passwordPrompt: 'Password prompt',
snmpCredential: 'SNMP credential'
snmpCredential: 'SNMP credential',
authProtocol: 'Auth protocol'
},
config: {
config: 'Settings', // "设置"
@@ -1094,7 +993,7 @@ const en = {
exprTempImport: 'expression template import',
exprTempExport: 'expression template export',
exprTempImportCancel: 'expression template import rollback',
copy: 'Copy',
copy: 'Duplicate',
name: 'Name',
gname: 'Group',
expression: 'Expression',

View File

@@ -1,800 +0,0 @@
<template>
<div class="content">
<div class="content-left left-slot" :class="{'left-slot-shrink': isShrink}">
<div class="sidebar-title too-long-split">{{$t(parentMenu.i18n)}}</div>
<div class="sidebar-info" style="height: 90%; overflow: auto;">
<template v-if="parentMenu == '/project'">
<el-collapse v-model="projectChoose" accordion class="left-menu-bg" ref="projectLeft" style="padding-top: 0;">
<el-collapse-item v-for="(item) in projectList" :key="item.id" :name="item.id + ''">
<template slot="title">
<div :class="{'sidebar-info-item-active': item.id == currentProject.id}" :id="'project-module-'+item.id" @click="detailProject(item)" class="sidebar-info-item-project sidebar-info-item">
<div class="sidebar-info-item-txt">
<el-popover :content="item.name" placement="top-start" popper-class="transparent-pop" trigger="hover" v-if="item.name.length > 14">
<span class="" slot="reference">
{{item.name}}
</span>
</el-popover>
<span v-else>{{item.name}}</span>
</div>
</div>
</template>
<div class="sidebar-info sub-sidebar-info" >
<div :title="$t('overall.createModule')" @click="addModule(item)" class="sidebar-info-item sidebar-info-item-project-add" v-if="getProjectModule(item.id).length == 0">
<span><i class="nz-icon nz-icon-create-square"></i>&nbsp;{{$t("overall.addProject")}}</span>
</div>
<template v-else>
<div v-for="(module, index) in getProjectModule(item.id)" :id="'project-module-'+module.id" :key="index" :class="{'sidebar-info-item-active': module.id == currentModule.id}" class="sidebar-info-sub-item" @click="changeModule(item, module)">
<div :id="`module-${module.id}`" class="item-tip">
<div :class="itemTip(module.id, module.name, ready)" class="item-tip-hide item-tip-key el-popover">{{module.name}}</div>
<span class="too-long-split" style="width: 120px;">{{module.name}}</span>
<div :id="'project-module-edit-'+module.id" @click.stop="editModule(module)" class="hid-div side-bar-menu-edit sub-side-bar-menu-edit" v-has="'project_module_toEdit'" v-show="module.buildIn != 1" ><i class="nz-icon nz-icon-edit"></i></div>
</div>
</div>
</template>
</div>
</el-collapse-item>
</el-collapse>
</template>
<template v-else-if="parentMenu == '/asset'">
<el-collapse class="left-menu-bg" v-model="activeType">
<el-collapse-item :title="$t('asset.left.dataCenter')" name="dataCenter">
<el-checkbox-group size="small" v-model="dcCheckList">
<el-checkbox :class="{'sidebar-info-item-active': indOf(dcCheckList, item.id)}" :key="key"
:label=item.id class="sidebar-info-item sidebar-info-item-asset" v-for="(item,key) in dcData">
<div class="sidebar-info-item-txt">
<el-popover :content="item.name" placement="top-start" trigger="hover" v-if="item.name.length > 14" >
<span slot="reference">{{item.name}}</span>
</el-popover>
<span v-else>{{item.name}}</span>
</div>
<el-badge :value="item.total" class="mark" type="primary"/>
</el-checkbox>
</el-checkbox-group>
</el-collapse-item>
<el-collapse-item :title="$t('asset.assetType')" name="assetType">
<el-checkbox-group @change="changeAssetTypeCheckBox" size="small" v-model="assetTypeCheckList">
<el-checkbox :class="{'sidebar-info-item-active': indOf(assetTypeCheckList, item.id)}" :key="key" :label=item.id class="sidebar-info-item" v-for="(item, key) in assetTypeData">
<div class="sidebar-info-item-txt">
<el-popover :content="item.name" placement="top-start" trigger="hover" v-if="item.name.length > 14" >
<span slot="reference">{{item.name}}</span>
</el-popover>
<span v-else>{{item.name}}</span>
</div>
<el-badge :value="item.total" class="mark" type="primary"/>
</el-checkbox>
</el-checkbox-group>
</el-collapse-item>
<el-collapse-item :title="$t('asset.left.vendor')" name="vendor">
<el-checkbox-group @change="changeVendorCheckBox" size="small" v-model="vendorCheckList">
<el-checkbox :class="{'sidebar-info-item-active': indOf(vendorCheckList, item.id)}" :key="key" :label=item.id class="sidebar-info-item" v-for="(item, key) in vendorData">
<div class="sidebar-info-item-txt">
<el-popover :content="item.name" placement="top-start" trigger="hover" v-if="item.name.length > 14" >
<span slot="reference">{{item.name}}</span>
</el-popover>
<span v-else>{{item.name}}</span>
</div>
<el-badge :value="item.total" class="mark" type="primary"/>
</el-checkbox>
</el-checkbox-group>
</el-collapse-item>
<el-collapse-item :title="$t('asset.left.ping')" name="ping" v-if="assetPingSwitch">
<el-checkbox-group @change="changePingCheckBox" size="small" v-model="pingCheckList">
<el-checkbox :class="{'sidebar-info-item-active': indOf(pingCheckList, item.key)}" :key="index" :label="item.value" class="sidebar-info-item" v-for="(item, index) in pingData">
<div class="sidebar-info-item-txt">
<span>{{item.label}}</span>
</div>
<el-badge :value="item.total" class="mark" type="primary"/>
</el-checkbox>
</el-checkbox-group>
</el-collapse-item>
</el-collapse>
<!--tag 过滤-->
<div class="sidebar-title too-long-split orange-font">
Tag
</div>
<el-collapse class="left-menu-bg" v-model="activeTag">
<el-collapse-item :key="item.key" :name="item.key" :title="item.key" v-for="item in tagData">
<el-checkbox-group size="small" v-model="tagCheckList" >
<el-checkbox :key="item.key+'-'+tag.value" :label="item.key+'-'+tag.value" @change="changeTagCheckBox(item,tag.value)" class="sidebar-info-item" v-for="tag in item.values">
<div class="sidebar-info-item-txt">
<el-popover :content="tag.value" placement="top-start" trigger="hover" v-if="tag.value.length > 14" >
<span slot="reference">{{tag.value}}</span>
</el-popover>
<span v-else>{{tag.value}}</span>
</div>
<el-badge :max="99" :value="tag.total" class="mark" type="primary"/>
</el-checkbox>
</el-checkbox-group>
</el-collapse-item>
</el-collapse>
</template>
<template v-else>
<div v-for="(menu, index) in parentMenu.children" :key="index" :class="{'sidebar-info-item-active': menu.route == route}" class="sidebar-info-item" @click="jumpTo(menu.route)">
{{$t(menu.i18n)}}
</div>
</template>
</div>
<div @click="toggleStat" class="bottom-icon">
<div class="bottom-divider"></div>
<div style="display: inline-block;float: right;margin-right:15px;"><i style="font-size: 24px;" :class="{'nz-icon nz-icon-push-pin-line': isShrink, 'nz-icon nz-icon-push-pin-fill': !isShrink}" :style="{color : !isShrink ? '#EE9D3F' : ''}"></i></div>
</div>
</div><div class="content-right right-slot" :class="{'right-slot-open': isShrink}">
<router-view v-if="isRouterAlive"/>
</div>
<transition name="right-box">
<module-box v-if="rightBox.module.show" :current-project="currentProject" :module="module" @close="closeModuleRightBox" ref="moduleBox"></module-box>
</transition>
</div>
</template>
<script>
import bus from '../../libs/bus'
export default {
name: 'leftMenu',
props: {
resizeFunc: Function
},
data () {
return {
isShrink: localStorage.getItem('nz-left-menu-shrink') == 'true',
parentMenu: {},
// active: "/overview",
// project相关
projectList: [],
moduleList: [],
showProjectPanel: true,
currentProjectTitle: '',
currentProject: { id: '', name: '', remark: '' }, // endpoint弹框、module列表用来回显project
module: {}, // 编辑的module
blankModule: { name: '', project: {}, port: 9100, path: '', param: '', labels: '', type: 'http', paramObj: [], labelModule: [], snmpParam: '', walk: [], version: 2, max_repetitions: 25, retries: 3, timeout: 10, community: 'public', username: '', security_level: 'noAuthNoPriv', password: '', auth_protocol: 'MD5', priv_protocol: 'DES', priv_password: '', context_name: '' }, // 空白module
currentModule: { id: '', type: '', name: '', project: {}, port: '', path: '', param: '', paramObj: [], snmpParam: '', labels: '', labelModule: [] }, // 用来回显的module
ready: false,
rightBox: { module: { show: false } },
// asset相关
activeType: 'dataCenter',
activeTag: '',
dcData: [],
dcCheckList: [],
assetTypeData: [],
assetTypeCheckList: [],
vendorData: [],
vendorCheckList: [],
pingData: [],
pingCheckList: [],
tagData: [],
tagCheckList: [],
tagCheckMap: {},
lastCheckSize: 0,
assetPingSwitch: true,
isRouterAlive: true,
projectChoose: []
}
},
computed: {
route () {
return this.$route.path
},
itemTip () {
return function (id, content, ready) {
const className = 'item-tip-show'
this.$nextTick(() => {
if (ready) {
const cellDom = document.querySelector(`#module-${id}`)
const spanDom = document.querySelector(`#module-${id}>span`)
if (cellDom.offsetWidth - 16 <= spanDom.offsetWidth) {
document.querySelector(`#module-${id}>.el-popover`).classList.add(className)
} else {
document.querySelector(`#module-${id}>.el-popover`).classList.remove(className)
}
}
})
return ''
}
},
checkedTagCount () {
return this.tagCheckList.length
},
currentProjectChange () {
return this.$store.state.currentProject
}
},
watch: {
route: {
deep: true,
immediate: true,
handler (n) {
this.parentMenu = this.getParentMenu(n)
}
},
currentProjectChange: {
immediate: true,
handler (n, o) {
if (n && n.id != this.currentProject.id) {
this.currentProject = n
if (this.currentProject && this.currentProject.id && this.showProjectPanel) {
this.detailProject(this.currentProject)
// this.projectChoose=[];
}
this.changeCurrentModule('')
}
}
},
currentProject: {
immediate: true,
deep: true,
handler (n, o) {
bus.$emit('current-project-change', n) // 告知project.vue
}
},
dcCheckList: {
deep: true,
immediate: true,
handler (n) {
bus.$emit('asset-filter-change', 'idcIds', n.join(','))
}
}
},
created () {
this.initEvent() // 注册监听事件
},
mounted () {
Promise.all([this.getProjectList(), this.getModuleList(), this.getLeftMenuList()]).then(response => {
setTimeout(() => {
this.ready = true
}, 300)
})
},
methods: {
toggleStat () {
this.isShrink = !this.isShrink
localStorage.setItem('nz-left-menu-shrink', this.isShrink)
if (this.resizeFunc) {
this.resizeFunc()
}
},
// 根据route获取父菜单
getParentMenu (route) {
let parentMenu = ''
let end = false
if (route != '/project') {
this.changeCurrentModule('')
}
if (route != '/project' && route != '/asset') {
this.$store.getters.menuList.forEach(menu => {
if (!end) {
if (menu.children) {
menu.children.forEach(subMenu => {
if (subMenu.route == route) {
parentMenu = menu
end = true
}
})
}
}
})
} else {
parentMenu = route
}
return parentMenu
},
getProjectList () {
return new Promise(resolve => {
this.$get('project', { pageSize: -1 }).then(response => {
if (response.code == 200) {
this.projectList = response.data.list
}
resolve(this.projectList)
})
})
},
getProjectModule (projectId) {
const moduleList = JSON.parse(JSON.stringify(this.moduleList))
return moduleList.filter((item, index) => {
return item.project.id == projectId
})
},
getModuleList () {
return new Promise(resolve => {
this.$get('module', { pageSize: -1, pageNo: 1 }).then(response => {
if (response.code === 200) {
this.moduleList = response.data.list
for (let i = 0; i < this.moduleList.length; i++) {
try {
const param = this.moduleList[i].param || '{}'
const tempObj = JSON.parse(param)
const labels = this.moduleList[i].labels || '{}'
const tempObj1 = JSON.parse(labels)
this.$set(this.moduleList[i], 'paramObj', [])
this.$set(this.moduleList[i], 'labelModule', [])
for (const k in tempObj) {
this.moduleList[i].paramObj.push({ key: k, value: tempObj[k] })
}
for (const k in tempObj1) {
this.moduleList[i].labelModule.push({ key: k, value: tempObj1[k] })
}
} catch (err) {}
}
}
resolve(this.moduleList)
})
})
},
// 左侧module列表选中切换与project.vue同步
changeModule (project, module) {
this.showProjectPanel = false
this.changeCurrentProject(project)
this.changeCurrentModule(module)
bus.$emit('project-page-type', 'endpoint') // 告知project.vue
},
addModule (obj) {
this.module = this.newModule(obj)
this.rightBox.module.show = true
this.$nextTick(() => {
this.$refs.moduleBox.initWalk()
})
},
newModule (obj) {
const module = JSON.parse(JSON.stringify(this.blankModule))
module.project = this.$store.state.currentProject
if (obj) {
module.project = obj
}
return module
},
// 弹出module编辑页
editModule (module) {
this.module = JSON.parse(JSON.stringify(module))
if (!this.module.paramObj) {
this.$set(this.module, 'paramObj', [])
}
if (!this.module.labelModule) {
this.$set(this.module, 'labelModule', [])
}
if (this.module.snmpParam) {
this.initSnmpParam(this.module)
}
this.rightBox.module.show = true
this.$nextTick(() => {
this.$refs.moduleBox.initWalk()
})
},
closeModuleRightBox (refresh) {
this.rightBox.module.show = false
if (refresh) {
this.getModuleList()
}
},
initSnmpParam (module) {
this.$set(module, 'walk', [])
this.$set(module, 'version', '')
this.$set(module, 'max_repetitions', '')
this.$set(module, 'retries', '')
this.$set(module, 'timeout', '')
this.$set(module, 'community', '')
this.$set(module, 'username', '')
this.$set(module, 'security_level', '')
this.$set(module, 'password', '')
this.$set(module, 'auth_protocol', '')
this.$set(module, 'priv_protocol', '')
this.$set(module, 'priv_password', '')
this.$set(module, 'context_name', '')
},
changeCurrentProject (project) {
// localStorage.setItem("nz-current-project", project.id);
this.$store.commit('currentProjectChange', project)
this.currentProject = project
},
changeCurrentModule (module) {
bus.$emit('current-module-change', module) // 告知project.vue
this.currentModule = module
},
// 与header.vue同步
detailProject (project) {
this.showProjectPanel = true
this.changeCurrentProject(project)
bus.$emit('project-page-type', 'project') // 告知project.vue
this.changeCurrentModule({ id: '' })
},
initEvent () {
/* bus.$on("parent-menu-change", parentMenu => {
this.parentMenu = parentMenu;
});
bus.$on("menu-change", menu => {
this.active = menu;
}); */
bus.$on('header-dc-change', dcId => {
this.dcCheckList = [dcId]
// bus.$emit("asset-filter-change", "idcIds", dcId);
})
bus.$on('clear-asset-filter', dcId => {
this.dcCheckList = []
this.assetTypeCheckList = []
this.vendorCheckList = []
this.pingCheckList = []
})
bus.$on('project-list-change', () => {
this.getProjectList()
})
bus.$on('module-list-change', menu => {
this.getModuleList()
})
bus.$on('asset-list-change', () => {
const dcData = JSON.parse(JSON.stringify(this.dcData))
const assetTypeData = JSON.parse(JSON.stringify(this.assetTypeData))
const vendorData = JSON.parse(JSON.stringify(this.vendorData))
const pingData = JSON.parse(JSON.stringify(this.pingData))
const tagData = JSON.parse(JSON.stringify(this.tagData))
this.getLeftMenuList().then(() => {
const result = []
const dcDiff = this.compareAssetLeftMenu(dcData, this.dcData, 'idcIds')
if (dcDiff.length > 0) {
const temp = this.dcCheckList.filter(item => {
return !dcDiff.find((t, i) => { return item == t.id })
})
result.push({ key: 'idcIds', value: temp.join(',') })
this.dcCheckList = temp
}
const typeDiff = this.compareAssetLeftMenu(assetTypeData, this.assetTypeData, 'typeIds')
if (typeDiff.length > 0) {
this.assetTypeCheckList = this.assetTypeCheckList.filter(item => {
return !typeDiff.find(t => { return item == t.id })
})
result.push({ key: 'typeIds', value: this.assetTypeCheckList.join(',') })
}
const vendorDiff = this.compareAssetLeftMenu(vendorData, this.vendorData, 'vendorIds')
if (vendorDiff.length > 0) {
this.vendorCheckList = this.vendorCheckList.filter(item => {
return !vendorDiff.find(t => { return item == t.id })
})
result.push({ key: 'vendorIds', value: this.vendorCheckList.join(',') })
}
const pingDiff = this.compareAssetLeftMenu(pingData, this.pingData, 'pingStates')
if (pingDiff.length > 0) {
this.pingCheckList = this.pingCheckList.filter(item => {
return !pingDiff.find(t => { return item == t.value })
})
result.push({ key: 'pingStates', value: this.pingCheckList.join(',') })
}
const tagDiff = this.compareAssetLeftMenu(tagData, this.tagData, 'tags')
if (tagDiff.length > 0) {
const $self = this
tagDiff.forEach(item => {
const key = item.key
const values = item.values
let checkedVals = $self.tagCheckMap[key]
if (checkedVals && checkedVals.length > 0) {
$self.tagCheckList = $self.tagCheckList.filter(t => { return !values.find(r => { return key + '-' + r.value == t }) })
$self.lastCheckSize = $self.lastCheckSize - values.length
checkedVals = checkedVals.filter(t => { return !values.find(r => { return r.value == t }) })
if (checkedVals.length > 0) {
$self.tagCheckMap[key] = checkedVals
} else {
delete $self.tagCheckMap[key]
}
}
})
if (Object.keys($self.tagCheckMap).length > 0) {
result.push({ key: 'tags', value: JSON.stringify($self.tagCheckMap) })
} else {
result.push({ key: 'tags', value: '' })
}
}
bus.$emit('asset-filter-change', 'multiParam', result)
})
})
bus.$on('asset-property-change', () => {
this.getLeftMenuList()
})
bus.$on('asset-ping-switch-change', (isOpen) => {
this.assetPingSwitch = isOpen
})
},
// 获取asset左侧菜单数据
getLeftMenuList () {
return new Promise(resolve => {
this.$get('asset/filter').then(response => {
if (response.code === 200) {
// dc
this.dcData = response.data.dc
// AssetType
this.assetTypeData = response.data.assetType
// vendor
this.vendorData = response.data.vendor
// ping
this.pingData = [{ label: 'up', value: 1, total: 0 }, { label: 'down', value: 0, total: 0 }]
this.pingData.map(item => {
if (response.data.ping) {
const data = response.data.ping.find(t => t.name == item.label)
if (data) {
item.total = data.total
item.value = data.status
}
}
return item
})
this.tagData = response.data.tag
}
resolve()
})
})
},
compareAssetLeftMenu: function (src, dist, key) {
const result = src.filter(item => {
if (key == 'pingStates') {
return !dist.find(t => { return t.name == item.name })
}
if (key == 'tags') {
const tag = dist.find(t => {
return t.key == item.key
})
if (tag) {
const srcValues = item.values
const distValues = tag.values
const vals = srcValues.filter(t => {
return distValues.find(r => {
return r.value == t.value
})
})
return !vals || vals.length < 1
} else {
return true
}
}
return !dist.find(t => { return item.id == t.id })
})
return result
},
// asset左侧菜单4个事件
changeCheckBox () {
this.assetClick = true
},
changeAssetTypeCheckBox () {
if (this.assetTypeCheckList && this.assetTypeCheckList.length > 0) {
const assetTypeIds = this.assetTypeCheckList.join(',')
bus.$emit('asset-filter-change', 'typeIds', assetTypeIds)
} else {
bus.$emit('asset-filter-change', 'typeIds', '')
}
},
changeVendorCheckBox () {
if (this.vendorCheckList && this.vendorCheckList.length > 0) {
const vendorIds = this.vendorCheckList.join(',')
bus.$emit('asset-filter-change', 'vendorIds', vendorIds)
} else {
bus.$emit('asset-filter-change', 'vendorIds', '')
}
},
changePingCheckBox () {
if (this.pingCheckList && this.pingCheckList.length > 0) {
const pingStates = this.pingCheckList.join(',')
bus.$emit('asset-filter-change', 'pingStates', pingStates)
} else {
bus.$emit('asset-filter-change', 'pingStates', '')
}
},
changeTagCheckBox (tag, value) {
let checked = this.tagCheckMap[tag.key]
if (!checked) {
checked = []
}
if (this.lastCheckSize < this.tagCheckList.length) {
checked.push(value)
} else {
const index = checked.findIndex(item => {
return item == value
})
checked.splice(index, 1)
}
if (checked.length > 0) {
this.tagCheckMap[tag.key] = checked
} else {
if (this.tagCheckMap[tag.key]) {
delete this.tagCheckMap[tag.key]
}
}
this.lastCheckSize = this.tagCheckList.length
if (Object.keys(this.tagCheckMap).length > 0) {
bus.$emit('asset-filter-change', 'tags', JSON.stringify(this.tagCheckMap))
} else {
bus.$emit('asset-filter-change', 'tags', '')
}
},
indOf (a, b) {
const c = []
for (let i = 0; i < a.length; i++) {
c.push(a[i])
}
if (c.indexOf(b) > -1) {
return true
} else {
return false
}
},
jumpTo (route) {
if (route == this.route) {
this.reload()
}
this.$router.push({
path: route,
query: {
t: +new Date()
}
})
},
reload () {
this.isRouterAlive = false
this.$nextTick(() => (this.isRouterAlive = true))
}
},
beforeDestroy () {
/* bus.$off("parent-menu-change");
bus.$off("menu-change"); */
bus.$off('header-dc-change')
bus.$off('clear-asset-filter')
bus.$off('project-list-change')
bus.$off('module-list-change')
bus.$off('asset-list-change')
bus.$off('asset-property-change')
bus.$off('asset-ping-switch-change')
}
}
</script>
<style scoped lang="scss">
.content{
position: relative;
height: calc(100% - 54px);
}
.slot-content{
height: 100%;
}
.content .left-slot{
position: relative;
background-color: $left-menu-bgcolor;
transition: transform 200ms, opacity 200ms;
transform: scaleX(1);
transform-origin: left;
opacity: 1;
/*border-bottom: 1px solid #eeeeee;*/
/*transition: all 100ms;*/
}
.content .right-slot{
width: calc(100% - 200px);
}
.content .right-slot-open{
width: calc(100% - 23px);
margin-left: -177px;
}
.content .left-slot-shrink{
transform: scaleX(0.12);
opacity: 0;
.bottom-icon .bottom-divider{
width: 0px;
}
}
.slot-content {
transition: opacity 200ms;
}
.item-tip {
position: relative;
}
.item-tip-hide {
display: none;
position: absolute;
bottom: 30px;
min-width: 50px;
white-space: normal;
}
.sidebar-info-sub-item:first-of-type .item-tip-hide {
bottom: -50px;
}
.item-tip:hover>.item-tip-show {
display: block;
}
.hid-div{
visibility: hidden;
}
.sidebar-info-sub-item:hover .hid-div{
visibility: visible;
}
.sub-sidebar-info{
padding-top: 10px !important;
padding-left: 10px;
box-sizing: border-box;
}
.sub-side-bar-menu-edit{
margin-right: 13px;
}
.sidebar-info-item-project.sidebar-info-item{
margin:0 !important;
}
.sidebar-info-item-asset .sidebar-info-item-txt{
vertical-align: text-top;
}
/deep/ .el-badge__content{
min-width: 15px;
}
.left-slot .bottom-icon{
position:absolute;
width: 36px;
height: 36px;
right: 0;
bottom: 30px;
}
.left-slot .bottom-icon i{
visibility: hidden;
}
.left-slot:hover{
.bottom-icon i{
visibility: visible;
}
}
.left-slot .bottom-icon i:hover{
cursor: pointer;
}
.bottom-icon .bottom-divider{
display: inline-block;
height: 1px;
width: 175px;
border-top: 1px solid lightgrey;
vertical-align: middle;
visibility: hidden;
}
.content .left-slot-shrink:hover{
transform: scaleX(1);
z-index: 100;
opacity: 1;
.bottom-icon{
z-index: 101;
}
.bottom-icon .bottom-divider{
width: 175px;
}
}
.content-left .sidebar-info-item-project-add{
border: 1px solid rgba(0,0,0,0.15);
border-radius: 4px;
text-align: center;
font-family: Roboto-Regular;
font-size: 14px;
color: #535B64;
margin-right: 25px;
height: 30px;
line-height: 30px;
display: flex;
padding-left: 0;
justify-content: center;
}
/deep/ .el-badge__content--primary{
background-color: #74A7FA;
}
</style>
<style lang="scss">
</style>

View File

@@ -83,19 +83,19 @@
</template>
<template v-if="label.action !== 1">
<template v-if="label.type.toUpperCase() === assetConstants.labelTypeData.TEXT">
<el-input v-model="label.value" size="small"/>
<el-input v-model="label.value[0]" size="small"/>
</template>
<template v-else-if="label.type.toUpperCase() === assetConstants.labelTypeData.MULTITEXT">
<div v-for="(value, i) in label.value" :key="i" class="label__multi-text">
<el-input v-model="label.value[i]" size="small"/>
<span><i class="nz-icon nz-icon-minus"></i></span>
<el-input v-model="label.value[i]" size="small" style="margin-right: 15px;"/>
<span :style="{'opacity': label.value.length > 1 ? 1 : 0.5}" @click="label.value.length > 1 ? label.value.splice(i, 1) : ''"><i class="nz-icon nz-icon-minus"></i></span>
</div>
</template>
<template v-else-if="label.type.toUpperCase() === assetConstants.labelTypeData.TEXTAREA">
<el-input v-model="label.value" :maxlength="4096" size="small" type="textarea"/>
<el-input v-model="label.value[0]" :maxlength="4096" size="small" type="textarea"/>
</template>
<template v-else-if="label.type.toUpperCase() === assetConstants.labelTypeData.RADIO">
<el-radio v-for="item in JSON.parse(label.param).items" :key="item.name" v-model="label.value" :label="item.name">{{item.name}}</el-radio>
<el-radio v-for="item in JSON.parse(label.param).items" :key="item.name" v-model="label.value[0]" :label="item.name">{{item.name}}</el-radio>
</template>
<template v-else-if="label.type.toUpperCase() === assetConstants.labelTypeData.CHECKBOX">
<el-checkbox-group v-model="label.value">
@@ -103,15 +103,15 @@
</el-checkbox-group>
</template>
<template v-else-if="label.type.toUpperCase() === assetConstants.labelTypeData.SELECT">
<el-select v-model="label.value" class="right-box__select" popper-class="right-box-select-dropdown prevent-clickoutside" size="small">
<el-select v-model="label.value[0]" class="right-box__select" popper-class="right-box-select-dropdown prevent-clickoutside" size="small">
<el-option v-for="item in JSON.parse(label.param).items" :key="item.name" :label="item.name" :value="item.name"></el-option>
</el-select>
</template>
<template v-else-if="label.type.toUpperCase() === assetConstants.labelTypeData.INTEGER">
<el-input v-model="label.value" oninput="value=value.replace(/[^\d]/g,'')" size="small"></el-input>
<el-input v-model="label.value[0]" oninput="value=value.replace(/[^\d]/g,'')" size="small"></el-input>
</template>
<template v-else-if="label.type.toUpperCase() === assetConstants.labelTypeData.DOUBLE">
<el-input v-model="label.value" oninput="value=value.replace(/[^0-9.]/g,'')" size="small"></el-input>
<el-input v-model="label.value[0]" oninput="value=value.replace(/[^0-9.]/g,'')" size="small"></el-input>
</template>
<template v-else-if="label.type.toUpperCase() === assetConstants.labelTypeData.DATETIME">
<template v-if="JSON.parse(label.param).subType === assetConstants.labelSubTypeData.time">
@@ -120,14 +120,14 @@
<el-time-select v-model="label.value[1]" size="small"></el-time-select>
</div>
<template v-else>
<el-time-select v-model="label.value" size="small" style="width: 100%"></el-time-select>
<el-time-select v-model="label.value[0]" size="small" style="width: 100%"></el-time-select>
</template>
</template>
<template v-else>
<template v-if="label.interval">
<el-date-picker
id="asset-box-input-purchase-date"
v-model="label.value"
v-model="label.value[0]"
:type="JSON.parse(label.param).subType === assetConstants.labelSubTypeData.date ? 'dateRange' : 'datetimerange'"
placeholder=""
size="small"
@@ -137,7 +137,7 @@
<template v-else>
<el-date-picker
id="asset-box-input-parchase-date"
v-model="label.value"
v-model="label.value[0]"
:type="JSON.parse(label.param).subType"
placeholder=""
size="small"
@@ -148,7 +148,7 @@
</template>
</template>
<template v-else-if="label.type.toUpperCase() === assetConstants.labelTypeData.EMAIL">
<input v-model="label.value" size="small"></input>
<input v-model="label.value[0]" size="small"></input>
</template>
</template>
</el-form-item>
@@ -237,9 +237,10 @@ export default {
url: 'asset/asset',
editData: {
editType: 1,
authProtocol: 0,
authProtocol: 1,
authType: 1,
fields: [],
port: 22,
snmpCredentialId: null
},
labelCascProp: {

View File

@@ -79,10 +79,82 @@
<template v-slot:label>
<div class="form__labels-label">
<span>{{label.name}}</span>
<div>
<el-checkbox v-model="label.action" :false-label="0" :label="$t('overall.delete')" :true-label="1" size="small" style="padding-right: 20px;"></el-checkbox>
<span @click="removeLabel(label)"><i class="nz-icon nz-icon-minus"></i></span>
</div>
</div>
</template>
<template v-if="label.action !== 1">
<template v-if="label.type.toUpperCase() === assetConstants.labelTypeData.TEXT">
<el-input v-model="label.value[0]" size="small"/>
</template>
<template v-else-if="label.type.toUpperCase() === assetConstants.labelTypeData.MULTITEXT">
<div v-for="(value, i) in label.value" :key="i" class="label__multi-text">
<el-input v-model="label.value[i]" size="small"/>
<span><i class="nz-icon nz-icon-minus"></i></span>
</div>
</template>
<template v-else-if="label.type.toUpperCase() === assetConstants.labelTypeData.TEXTAREA">
<el-input v-model="label.value[0]" :maxlength="4096" size="small" type="textarea"/>
</template>
<template v-else-if="label.type.toUpperCase() === assetConstants.labelTypeData.RADIO">
<el-radio v-for="item in JSON.parse(label.param).items" :key="item.name" v-model="label.value[0]" :label="item.name">{{item.name}}</el-radio>
</template>
<template v-else-if="label.type.toUpperCase() === assetConstants.labelTypeData.CHECKBOX">
<el-checkbox-group v-model="label.value">
<el-checkbox v-for="item in JSON.parse(label.param).items" :key="item.name" :label="item.name" :value="item.name"></el-checkbox>
</el-checkbox-group>
</template>
<template v-else-if="label.type.toUpperCase() === assetConstants.labelTypeData.SELECT">
<el-select v-model="label.value[0]" class="right-box__select" popper-class="right-box-select-dropdown prevent-clickoutside" size="small">
<el-option v-for="item in JSON.parse(label.param).items" :key="item.name" :label="item.name" :value="item.name"></el-option>
</el-select>
</template>
<template v-else-if="label.type.toUpperCase() === assetConstants.labelTypeData.INTEGER">
<el-input v-model="label.value[0]" oninput="value=value.replace(/[^\d]/g,'')" size="small"></el-input>
</template>
<template v-else-if="label.type.toUpperCase() === assetConstants.labelTypeData.DOUBLE">
<el-input v-model="label.value[0]" oninput="value=value.replace(/[^0-9.]/g,'')" size="small"></el-input>
</template>
<template v-else-if="label.type.toUpperCase() === assetConstants.labelTypeData.DATETIME">
<template v-if="JSON.parse(label.param).subType === assetConstants.labelSubTypeData.time">
<div v-if="label.interval" style="display: flex; justify-content: space-between">
<el-time-select v-model="label.value[0]" size="small"></el-time-select>
<el-time-select v-model="label.value[1]" size="small"></el-time-select>
</div>
<template v-else>
<el-time-select v-model="label.value[0]" size="small" style="width: 100%"></el-time-select>
</template>
</template>
<template v-else>
<template v-if="label.interval">
<el-date-picker
id="asset-box-input-purchase-date"
v-model="label.value[0]"
:type="JSON.parse(label.param).subType === assetConstants.labelSubTypeData.date ? 'dateRange' : 'datetimerange'"
placeholder=""
size="small"
style="width: 100%">
</el-date-picker>
</template>
<template v-else>
<el-date-picker
id="asset-box-input-parchase-date"
v-model="label.value[0]"
:type="JSON.parse(label.param).subType"
placeholder=""
size="small"
style="width: 100%"
value-format="yyyy-MM-dd">
</el-date-picker>
</template>
</template>
</template>
<template v-else-if="label.type.toUpperCase() === assetConstants.labelTypeData.EMAIL">
<input v-model="label.value[0]" size="small"></input>
</template>
</template>
<el-input v-model="label.value" size="small"/>
</el-form-item>
</div>
<!-- label的新增按钮 -->
@@ -137,6 +209,9 @@
<el-form-item :label="$t('asset.passwordPrompt')" prop="authPinTip">
<el-input v-model="editAsset.authPinTip" size="small"/>
</el-form-item>
<el-form-item :label="$t('asset.port')" prop="authProtocolPort">
<el-input v-model="editAsset.authProtocolPort" size="small"/>
</el-form-item>
</template>
<!-- SNMP -->
<template v-if="editAsset.type && editAsset.type.snmpEnable === 1">
@@ -295,9 +370,9 @@ export default {
immediate: true,
handler (n) {
this.editAsset = JSON.parse(JSON.stringify(n))
this.$nextTick(() => {
this.editAsset.stateId = n.state ? n.state.id : ''
this.editAsset.typeId = n.type ? n.type.id : ''
this.$nextTick(() => {
if (n.id) {
this.lockModelInputValue = `${n.brand.name} / ${n.model.name}`
}
@@ -391,6 +466,18 @@ export default {
this.labelCascShow = true
})
},
addMultiTextRow (label) {
label.value.push('')
},
blankLabelValue (label) {
if (label.type.toUpperCase() === this.assetConstants.labelTypeData.CHECKBOX) {
return []
} else if (label.type.toUpperCase() === this.assetConstants.labelTypeData.MULTITEXT) {
return ['']
} else {
return ''
}
},
getParentAsset () {
return new Promise(resolve => {
this.$get(this.url, { pageSize: -1, vmh: 1 }).then(response => {
@@ -407,7 +494,7 @@ export default {
},
addLabel ([groupId, metaId]) {
const label = this.metaData.find(m => m.id === metaId)
this.editAsset.fields.push({ id: label.id, value: '', name: label.name })
this.editAsset.fields.push({ ...label, value: this.blankLabelValue(label), action: 0 })
this.labelCascShow = false
this.$nextTick(() => {
this.labelCascShow = true

View File

@@ -233,9 +233,9 @@ export default {
})
},
getLinkData () {
this.$get('link').then(response => {
/* this.$get('link').then(response => {
this.$store.commit('setLinkData', response.data)
})
}) */
},
createBox (item) {
if (item.type == 1) {

View File

@@ -5,7 +5,8 @@
:api="url"
:custom-table-title.sync="tools.customTableTitle"
:from="fromRoute.asset"
:layout="['searchInput', 'elementSet']"
:has-search="true"
:layout="['searchInput', 'elementSet', 'clickSearch']"
:search-msg="searchMsg">
<template v-slot:top-tool-right>
<export-excel
@@ -28,6 +29,9 @@
</button>
<delete-button id="asset-list-batch-delete" v-has="'asset_delete'" :api="url" :delete-objs="batchDeleteObjs" @after="getTableData" @before="delFlag=true"></delete-button>
</template>
<template v-slot:search>
<click-search :select-value.sync="selectValue" :title-search-list="titleSearchList" @reload="reloadTable"/>
</template>
<template v-slot:default="slotProps">
<asset-table
ref="dataTable"
@@ -39,6 +43,7 @@
@cli="cli"
@del="del"
@edit="edit"
@copy="copy"
@orderBy="tableDataSort"
@reload="getTableData"
@selectionChange="selectionChange"
@@ -75,7 +80,6 @@
</template>
<script>
import bus from '@/libs/bus'
import exportXLSX from '@/components/common/exportXLSX'
import deleteButton from '@/components/common/deleteButton'
import assetBox from '@/components/common/rightBox/asset/assetBox'
@@ -83,7 +87,7 @@ import assetBatchEditBox from '@/components/common/rightBox/asset/assetBatchEdit
import nzDataList from '@/components/common/table/nzDataList'
import dataListMixin from '@/components/common/mixin/dataList'
import assetTable from '@/components/common/table/asset/assetTable'
import { showTableTooltip, hideTableTooltip } from '@/components/common/js/tools'
import clickSearch from '@/components/common/clickSearch'
export default {
name: 'asset',
@@ -93,6 +97,7 @@ export default {
nzDataList,
assetBatchEditBox,
assetTable,
clickSearch,
'export-excel': exportXLSX
},
mixins: [dataListMixin],
@@ -178,17 +183,70 @@ export default {
typeData: [],
dcData: [],
snmpCredentialData: [],
fieldGroupData: []
fieldGroupData: [],
titleSearchList: {
dc: {
label: this.$t('overall.dc'),
key: 'dcIds',
type: 'checkBox',
children: [],
show: true,
showMore: false,
width: 0,
index: 0
},
type: {
label: this.$t('overall.type'),
key: 'typeIds',
type: 'checkBox',
children: [],
show: true,
showMore: false,
width: 0,
index: 0
},
ping: {
label: 'ping',
key: 'ping',
type: 'checkBox',
children: [
{ key: 'Down', value: 0, name: 'Down' },
{ key: 'Up', value: 1, name: 'Up' }
],
show: true,
showMore: false,
width: 0,
index: 0
},
model: {
label: this.$t('asset.model'),
key: 'modelIds',
type: 'dropdownCheckBox',
children: [],
show: true,
width: 0,
index: 0
},
assetLabel: {
label: 'More',
key: 'fields',
type: 'dropdownCheckBox',
children: [],
show: true,
width: 0,
index: 0
}
},
/* computed: {
headerCurrentDc () {
return this.$store.state.currentDc
selectValue: {
dcIds: [],
typeIds: [],
ping: [],
modelIds: [],
fields: ''
}
}, */
}
},
methods: {
showTableTooltip,
hideTableTooltip,
cli ([id, host, account]) {
const consoleParam = {
id: id,
@@ -198,6 +256,10 @@ export default {
}
this.$store.commit('addConsole', consoleParam)
},
copy (row) {
this.object = { ...row, id: '' }
this.rightBox.show = true
},
getUserData () {
return new Promise(resolve => {
this.$get('sys/user').then(response => {
@@ -219,6 +281,16 @@ export default {
})
},
getTypeData () {
return new Promise(resolve => {
this.$get('asset/typeConf').then(response => {
if (response.code === 200) {
this.titleSearchList.type.children = response.data.list.map(d => { return { ...d, value: d.id } })
}
resolve()
})
})
},
getTypeTreeData () {
return new Promise(resolve => {
this.$get('asset/typeConf/tree').then(response => {
if (response.code === 200) {
@@ -228,11 +300,22 @@ export default {
})
})
},
reloadTable (obj) {
Object.keys(obj).forEach(key => {
if (typeof obj[key] === 'string') {
this.searchCheckBox[key] = obj[key]
} else {
obj[key].length > 0 ? this.searchCheckBox[key] = obj[key].join(',') : this.searchCheckBox[key] = null
}
})
this.getTableData()
},
getDcData () {
return new Promise(resolve => {
this.$get('dc', { pageSize: -1 }).then(response => {
if (response.code === 200) {
this.dcData = response.data.list
this.titleSearchList.dc.children = response.data.list.map(d => { return { ...d, value: d.id } })
}
resolve()
})
@@ -258,6 +341,25 @@ export default {
})
})
},
getSearchableMetaData () {
return new Promise(resolve => {
this.$get('asset/field/meta', { pageSize: -1, search: 1 }).then(response => {
if (response.code === 200) {
const data = []
response.data.list.forEach(m => {
if (m.param) {
const param = JSON.parse(m.param)
if (param.items) {
data.push({ ...m, children: param.items.map(p => { return { ...p, id: p.name, metaId: m.id } }) })
}
}
})
this.titleSearchList.assetLabel.children = data
}
resolve()
})
})
},
getBrandData () {
return new Promise(resolve => {
this.$get('asset/brand').then(response => {
@@ -268,11 +370,20 @@ export default {
})
})
},
getModelData (brandId) {
getModelData () {
return new Promise(resolve => {
this.$get('asset/model').then(response => {
if (response.code === 200) {
this.modelData = response.data.list
const titleSearchData = {}
this.modelData.forEach(m => {
if (titleSearchData[m.brand.name]) {
titleSearchData[m.brand.name].children.push(m)
} else {
titleSearchData[m.brand.name] = { ...m.brand, children: [m] }
}
})
this.titleSearchList.model.children = Object.keys(titleSearchData).map(b => titleSearchData[b])
}
resolve()
})
@@ -296,7 +407,6 @@ export default {
if (refresh) {
this.delFlag = true
this.getTableData()
// this.loadKeys()
}
},
getPrincipalName (data) {
@@ -305,7 +415,7 @@ export default {
return this.userData[item].username
}
}
},
}
/* formatPingTime (str) {
if (!str) {
return this.$t('asset.assetStatPre') + this.$t('asset.assetStatDown')
@@ -321,59 +431,18 @@ export default {
const seconds = time.getSeconds() > 9 ? time.getSeconds() : ('0' + time.getSeconds())
return this.$t('asset.assetStatPre') + year + ds + month + ds + day + ' ' + hours + ts + minutes + ts + seconds
}, */
// 数据排序
initEvent () {
bus.$on('asset-filter-change', (column, content) => {
this.pageObj.pageNo = 1
if (column == 'multiParam') {
const $self = this
if (content instanceof Array && content.length > 0) {
content.forEach(item => {
$self.pageObj[item.key] = item.value
})
}
} else {
this.pageObj[column] = content
}
// let isSame = this.checkSearchLabel(JSON.parse(JSON.stringify(this.pageObj)), oldPageObj);
// isSame && this.getTableData();
this.getTableData()
})
bus.$on('alert-message-change', () => {
this.getTableData()
})
},
dispatchEvent (event, param) {
this.$nextTick(() => {
bus.$emit(event, param)
})
},
loadKeys () {
this.$get('/asset/tagKey').then(res => {
if (res.code == 200) {
this.tagKeys = res.data.list.map(item => {
return { label: item, prop: 'tags', show: false, allowed: true, type: 'tag' }
})
this.resetTableTitle()
}
})
}
},
mounted () {
// this.loadKeys()
// 初始化数据
// this.getUserData()
this.initEvent()
this.getBrandData()
this.getModelData()
this.getStateData()
this.getTypeTreeData()
this.getTypeData()
this.getDcData()
this.getSearchableMetaData()
this.getSnmpCredentialData()
this.getFieldGroupData()
},
beforeDestroy () {
bus.$off('asset-filter-change')
bus.$off('alert-message-change')
}
}
</script>

View File

@@ -317,7 +317,7 @@ export default {
},
terminalCopy: null,
terminalRules: {
// terminal_timeout: [{ validator: positiveInteger, trigger: 'blur' }],
terminal_timeout: [{ validator: positiveInteger, trigger: 'blur' }],
terminal_record_local_retention: [{ required: true, message: this.$t('validate.required'), trigger: 'blur' }, { validator: positiveInteger, trigger: 'blur' }]
},
ldap: {