NEZ-2816 feat: 资产发现页面 表格页面 以及 二级页面开发

This commit is contained in:
zhangyu
2023-05-11 10:52:38 +08:00
parent ac73bbadf8
commit ead8d226bd
8 changed files with 812 additions and 3 deletions

View File

@@ -78,6 +78,8 @@
<roles-tab v-if="from === fromRoute.role && targetTab === 'roles'" :from="from" :obj="obj" :tabs="tabs.role" @changeTab="changeTab" :targetTab.sync="targetTab"></roles-tab>
<!--issue Tab-->
<!-- <issueTab v-if="from === fromRoute.issue && targetTab === 'issue'" v-show="subResizeShow" :from="from" :obj="obj" :tabs="tabs.alertSilence" @changeTab="changeTab" :targetTab.sync="targetTab"></issueTab> -->
<!--Discovery Tab-->
<discovery-tab v-if="from === fromRoute.assetDiscovery && targetTab === 'assetDiscoveryTab'" :from="from" :obj="obj" :tabs="tabs.discovery" @changeTab="changeTab" :targetTab.sync="targetTab"></discovery-tab>
</div>
</div>
</div>
@@ -111,6 +113,7 @@ import scrapeEndpoint from '@/components/common/bottomBox/tabs/scrapeEndpoint'
import cortexDetail from '@/components/common/bottomBox/tabs/cortexDetail'
import lokiStatus from '@/components/common/bottomBox/tabs/lokiStatus'
import rolesTab from '@/components/common/bottomBox/tabs/rolesTab'
import discoveryTab from '@/components/common/bottomBox/tabs/discoveryTab'
import IpDetails from '@/components/common/bottomBox/tabs/IpDetails'
import recordRuleEvalLog from '@/components/common/bottomBox/tabs/recordRuleEvalLog'
import routerPathParams from '@/components/common/mixin/routerPathParams'
@@ -144,6 +147,7 @@ export default {
recordRuleEvalLog,
recordRulesQuery,
issueTab,
discoveryTab,
commentsBottomTab,
vsysBottomTab,
rolesTab
@@ -286,6 +290,9 @@ export default {
role: [
{ prop: 'userTab', name: this.$t('config.operationlog.username'), active: true }
],
discovery: [
{ prop: 'assetDiscoveryTab', name: this.$t('assetDiscoveryTab'), active: true, hideHeader: true }
],
issue: [
// { prop: 'issue', name: this.$t('overall.issue'), active: true }
]

View File

@@ -2,8 +2,8 @@
<div class="bottom-data-list">
<div class="top-tools top-tools--sub">
<div class="top-tool-left">
<div class="sub-list-title" v-if="showTitle">{{bottomHeaderTitle}}<slot name="title"></slot></div>
<div class="sub-list-tabs">
<div class="sub-list-title" v-if="showTitle">{{bottomHeaderTitle}}<slot name="title"></slot></div>
<div class="sub-list-tabs" v-if="!hideHeader">
<div v-for="tab in tabs" :key="tab.prop" :class="{'sub-list-tab--active': tab.active || tab.prop == targetTab }" :title='tab.name' class="sub-list-tab" @click="changeTab(tab.prop)">{{tab.name}}</div>
</div>
</div>
@@ -90,11 +90,15 @@ export default {
},
title: {
type: String
},
hideHeader: {
type: Boolean,
default: false
}
},
computed: {
bottomHeaderTitle () {
return this.title || this.$t('overall.name')
return this.title || (this.$t('overall.name') + ':')
},
subContentClass () {
const className = []

View File

@@ -0,0 +1,161 @@
<template>
<div>
<nz-bottom-data-list
:showTitle="showTitle"
:obj="obj"
:title="' '"
:api="url"
:tableId="tableId"
style="height: 100%"
:custom-table-title.sync="tools.customTableTitle"
:layout="['searchInput', 'elementSet']"
:search-msg="searchMsg"
:tabs="tabs"
:targetTab.sync="targetTab"
@changeTab="changeTab"
@search="search"
:hide-header="true"
>
<template v-slot:title
><span :title="obj.name">{{ obj.name }}</span></template
>
<template v-slot:top-tool-right>
<pick-time :time-range="[0,1]" ref="pickTime" :refresh-data-func="dateChange" :showTimePicker="false" :use-chart-unit="false" :sign="'assetDiscovery' + obj.id"></pick-time>
</template>
<template v-slot>
<disccoveryTabTable
ref="dataTable"
:api="url"
:orderByFa="orderBy"
v-my-loading="tools.loading"
:loading="tools.loading"
:custom-table-title="tools.customTableTitle"
:height="subTableHeight"
:table-data="tableData"
@del="del"
@copy="copy"
@edit="edit"
@orderBy="tableDataSort"
@reload="getTableData"
@uploadAsset="uploadAsset"
></disccoveryTabTable>
</template>
<template v-slot:pagination>
<Pagination
ref="Pagination"
:pageObj="pageObj"
:tableId="tableId"
@pageNo="pageNo"
@pageSize="pageSize"
>
</Pagination>
</template>
</nz-bottom-data-list>
</div>
</template>
<script>
import dataListMixin from '@/components/common/mixin/dataList'
import subDataListMixin from '@/components/common/mixin/subDataList'
import nzBottomDataList from '@/components/common/bottomBox/nzBottomDataList'
import disccoveryTabTable from '@/components/common/table/asset/disccoveryTabTable'
import detailViewRightMixin from '@/components/common/mixin/detailViewRightMixin'
import routerPathParams from '@/components/common/mixin/routerPathParams'
export default {
name: 'rolesTab',
mixins: [dataListMixin, subDataListMixin, detailViewRightMixin, routerPathParams],
components: {
nzBottomDataList,
disccoveryTabTable,
},
props: {
obj: Object
},
data () {
return {
url: '/mock/tool/discovery',
tableId: 'discoveryTabTble',
detailType: 'list',
searchMsg: {
// 给搜索框子组件传递的信息
zheze_none: true,
searchLabelList: [
{
name: 'IP',
type: 'input',
label: 'ip',
id: 'ip',
disabled: false
}
]
},
searchLabel: { roleId: this.obj.id }
}
},
watch: {
tableData: {
immediate: true,
handler (n) {
if (n) {
const arr = []
n.map(item => {
if (!item.position) {
const obj = {
...this.$loadsh.cloneDeep(item),
type: 'user',
position: {
top: 0,
left: 0
},
loading: false
}
arr.push(obj)
}
})
return arr
}
}
},
obj (n) {
this.searchLabel = { roleId: this.obj.id }
this.getTableData()
}
},
methods: {
dateChange () {
this.getTableData()
},
getTableData (params) {
if (params && Object.keys(params).length > 0) {
for (const key in params) {
this.$set(this.searchLabel, key, params[key])
}
}
if (this.orderBy) {
this.$set(this.searchLabel, 'orderBy', this.orderBy)
} else {
delete this.searchLabel.orderBy
}
this.$set(this.searchLabel, 'pageNo', this.pageObj.pageNo)
this.$set(this.searchLabel, 'pageSize', this.pageObj.pageSize)
this.tools.loading = true
this.$get(this.url + '/' + this.obj.id, { ...this.searchLabel, ...this.searchCheckBox }).then(response => {
this.tools.loading = false
if (response.code === 200) {
this.tableData = response.data.list
this.pageObj.total = response.data.total
if (!this.scrollbarWrap && this.$refs.dataTable && this.$refs.dataTable.$refs.dataTable) {
this.$nextTick(() => {
this.scrollbarWrap = this.$refs.dataTable.$refs.dataTable.bodyWrapper
this.toTopBtnHandler(this.scrollbarWrap)
})
}
}
})
},
uploadAsset (row) {
console.log(row)
}
}
}
</script>

View File

@@ -423,6 +423,7 @@ export const fromRoute = {
assetType: 'assetType',
assetState: 'assetState',
assetLabel: 'assetLabel',
assetDiscovery: 'assetDiscovery',
user: 'user',
agent: 'agent',
recordRule: 'recordRule',

View File

@@ -0,0 +1,236 @@
<template>
<el-table
id="assetLabelTable"
ref="dataTable"
:data="tableData"
:height="height"
border
:default-sort="orderBy"
@header-dragend="dragend"
@sort-change="tableDataSort"
@selection-change="selectionChange"
>
<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}`"
: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}`"
class="data-column"
>
<template slot="header">
<span class="data-column__span">{{item.label}}</span>
<div class="col-resize-area"></div>
</template>
<template slot-scope="scope" :column="item">
<div v-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>
</div>
<div v-else-if="item.prop === 'uts'">
{{momentTz(scope.row[item.prop])}}
</div>
<div v-else-if="item.prop === 'snmpCredentialIds'">
{{snmpCredentialIdToStr(scope.row[item.prop])}}
</div>
<div v-else-if="item.prop === 'schedule'">
{{scheduleToStr(scope.row[item.prop])}}
</div>
<div v-else-if="item.prop === 'status'">
<i class="nz-icon" :class="selectIcon(scope.row[item.prop])"/>
{{statusToStr(scope.row[item.prop])}}
</div>
<span v-else-if="scope.row[item.prop]">{{scope.row[item.prop] || '-'}}</span>
<template v-else>-</template>
</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" @click.stop><i class="nz-icon nz-icon-view1"></i></button>-->
<button class="table-operation-item" @click="$emit('showBottomBox', 'assetDiscoveryTab', scope.row)" :title="$t('overall.view')"><i class="nz-icon nz-icon-view1"></i></button>
<el-dropdown size="medium" v-has="['asset_label_edit','asset_label_delete']" 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="'asset_label_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="'asset_label_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="'asset_label_delete'" :command="['delete-rel', scope.row, {forceDeleteShow:false, single:true}]"><i class="nz-icon nz-icon-delete"></i><span class="operation-dropdown-text">{{$t('overall.delete')}}</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>&nbsp;</div>
</template>
</el-table>
</template>
<script>
import table from '@/components/common/mixin/table'
import deleteButton from '@/components/common/deleteButton'
import copy from '@/components/common/copy'
export default {
name: 'assetLabelTable',
mixins: [table],
components: { deleteButton, copy },
props: {
loading: Boolean
},
data () {
return {
credentialData: [],
tableTitle: [
{
label: 'ID',
prop: 'id',
show: true,
width: 80,
sortable: 'custom'
}, {
label: this.$t('overall.name'),
prop: 'name',
show: true,
minWidth: 250,
sortable: 'custom'
}, {
label: this.$t('IP subnet'),
prop: 'subnet',
show: true,
minWidth: 250,
sortable: 'custom'
}, {
label: this.$t('SNMP credentials'),
prop: 'snmpCredentialIds',
show: true,
minWidth: 250,
sortable: 'custom'
}, {
label: this.$t('Schedule'),
prop: 'schedule',
show: true,
minWidth: 200,
sortable: 'custom'
}, {
label: this.$t('Last execute time'),
prop: 'uts',
show: true,
minWidth: 250,
sortable: 'custom'
}, {
label: this.$t('Duration'),
prop: 'duration',
show: true,
minWidth: 160,
sortable: 'custom'
}, {
label: this.$t('State'),
prop: 'status',
show: true,
minWidth: 250,
sortable: 'custom'
}, {
label: this.$t('Discovery hosts'),
prop: 'total',
show: true,
minWidth: 200,
sortable: 'custom'
}
]
}
},
created () {
this.getCredentialData()
},
methods: {
getCredentialData () {
this.$get('snmp/credential', { pageSize: -1 }).then(response => {
if (response.code === 200) {
this.credentialData = response.data.list
}
})
},
snmpCredentialIdToStr (str) {
const arr = str.split(',')
let retrunStr = ''
arr.forEach(item => {
const findItem = this.credentialData.find(credential => credential.id == item)
if (findItem) {
retrunStr += findItem.name + ','
}
})
retrunStr = retrunStr.substr(0, retrunStr.length - 1)
return retrunStr
},
scheduleToStr (schedule) {
if (!schedule || !schedule.type) {
return '-'
} else {
switch (schedule.type) {
case 1:
return 'One time only'
case 2:
return 'Daily'
case 3:
return 'Weekly'
case 4:
return 'Monthly'
}
}
},
selectIcon (status) {
switch (status) {
case '1' :
return 'nz-icon-over color999999'
case '2' :
return 'nz-icon-over color999999'
case '3' :
return 'nz-icon-over color999999'
case '4' :
return 'nz-icon-over colorEF7458'
case '5' :
return 'nz-icon-over color23BF9A'
}
},
statusToStr (status) {
switch (status) {
case '1' :
return 'Saving'
case '2' :
return 'Running'
case '3' :
return 'Scheduled'
case '4' :
return 'Failed'
case '5' :
return 'Finished'
}
}
}
}
</script>

View File

@@ -0,0 +1,155 @@
<template>
<div style="height: 100%">
<el-table
id="userTable"
ref="dataTable"
class="user-table"
:data="tableData"
:height="height"
border
:default-sort="orderBy"
@header-dragend="dragend"
@sort-change="tableDataSort"
@selection-change="selectionChange"
>
<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}`"
: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" :class="{'margin-l-10': item.prop === 'name'}">{{item.label}}</span>
<div class="col-resize-area"></div>
</template>
<template slot-scope="scope" :column="item">
<template v-if="item.prop === 'ip'">
<copy :copyData='scope.row.ip' :showInfo='scope.row.ip'>
<template slot="copy-text">
{{scope.row ? scope.row.ip : '-'}}
</template>
</copy>
</template>
<template v-else-if="item.prop === 'dc'">
<div>{{scope.row[item.prop] ? scope.row[item.prop].name : '-'}}</div>
</template>
<template v-else-if="item.prop === 'model'">
<div>{{scope.row[item.prop] ? scope.row[item.prop].name : '-'}}</div>
</template>
<template v-else-if="item.prop === 'state'">
<div>{{typeToStr(scope.row[item.prop])}}</div>
</template>
<template v-else-if="item.prop === 'imported'">
<span v-if="scope.row[item.prop] == 1">{{$t('tip.yes')}}</span>
<span v-else>{{$t('tip.no')}}</span>
</template>
<span v-else-if="scope.row[item.prop]">{{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" @click="tableOperation(['uploadAsset', scope.row])" :title="$t('overall.upload')"><i class="nz-icon nz-icon-Upload1"></i></button>
</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>&nbsp;</div>
</template>
</el-table>
</div>
</template>
<script>
import table from '@/components/common/mixin/table'
import copy from '@/components/common/copy'
export default {
name: 'disccoveryTabTable',
mixins: [table],
components: { copy },
props: {
loading: Boolean
},
data () {
return {
tableTitle: [ // 原始table列
{
label: 'IP',
prop: 'ip',
show: true,
minWidth: 200,
sortable: 'custom'
}, {
label: this.$t('asset.hostName'),
prop: 'sysName',
show: true,
minWidth: 200,
sortable: 'custom'
},
{
label: this.$t('overall.dc'),
prop: 'dc',
show: true,
minWidth: 150
}, {
label: this.$t('overall.type'),
prop: 'state',
show: true,
minWidth: 150
}, {
label: this.$t('asset.model'),
prop: 'model',
show: true,
minWidth: 200
}, {
label: this.$t('asset.objectID'),
prop: 'sysObjectId',
show: true,
minWidth: 150
}, {
label: this.$t('asset.imported'),
prop: 'imported',
show: true,
minWidth: 150
}
],
mfaEnable: localStorage.getItem('nz-mfa-enable')
}
},
methods: {
typeToStr (type) {
switch (type) {
case 1:
return 'Server'
}
}
}
}
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,241 @@
<template>
<div class="asset-meta">
<nz-data-list
ref="dataList"
:api="url"
:from="fromRoute.assetDiscovery"
:custom-table-title.sync="tools.customTableTitle"
:layout="['searchInput', 'elementSet', 'pagination']"
:search-msg="searchMsg"
@search="search"
>
<template v-slot:top-tool-right>
<button id="meta-add-meta" v-has="'asset_label_add'" :title="$t('overall.createLabel')" class="top-tool-btn margin-r-10"
type="button" @click="add">
<i class="nz-icon nz-icon-create-square"></i>
</button>
<top-tool-more-options
:delete-objs="batchDeleteObjs"
ref="export"
id="model"
:params="searchLabel"
:params2="searchCheckBox"
:permissions="{
import: 'asset_add',
export: 'asset_edit'
}"
class="top-tool-export margin-l-10 margin-r-10"
export-file-name="asset"
export-url="/asset/asset/export"
import-url="/asset/asset/import"
@afterImport="getTableData"
v-has="['asset_add','asset_edit','asset_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="fromRoute.assetDiscovery"
:forceDeleteShow="true"
:deleteTitle="'overall.asset'"
:type="'link'"
:title="$t('overall.batchDel')"
id="asset-list-batch-delete"
v-has="'asset_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:default="slotProps">
<assetDiscoveryTable
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) }"
></assetDiscoveryTable>
<!-- 回到table顶部的按钮 -->
<button v-show="tools.showTopBtn && slotProps.mainResizeShow" id="role-list-totop" :class="{'to-top-is-hover': tools.tableHover}" :style="{top: tools.toTopBtnTop}" class="to-top" @click="toTop(scrollbarWrap)" :title="$t('overall.backToTop')"><i class="nz-icon nz-icon-top"></i></button>
</template>
<!-- 分页组件 -->
<template v-slot:pagination>
<Pagination ref="Pagination" :pageObj="pageObj" :tableId="tableId" @pageNo='pageNo' @pageSize='pageSize'></Pagination>
</template>
</nz-data-list>
<!--侧滑-->
<transition name="right-box">
</transition>
</div>
</template>
<script>
import deleteButton from '@/components/common/deleteButton'
import nzDataList from '@/components/common/table/nzDataList'
import dataListMixin from '@/components/common/mixin/dataList'
import assetDiscoveryTable from '@/components/common/table/asset/assetDiscoveryTable'
import routerPathParams from '@/components/common/mixin/routerPathParams'
import topToolMoreOptions from '@/components/common/popBox/topToolMoreOptions'
export default {
name: 'assetDiscovery',
components: {
deleteButton,
nzDataList,
assetDiscoveryTable,
topToolMoreOptions
},
mixins: [dataListMixin, routerPathParams],
data () {
return {
url: '/mock/asset/discovery',
tableId: 'assetDiscovery',
detailType: 'list',
// 侧滑
rightBox: {
metaShow: false,
groupShow: false
},
groupData: [{
name: this.$t('overall.exportAll'),
id: -1,
children: []
}],
defaultProps: {
children: 'children',
label: 'name'
},
/* 搜素相关 */
searchMsg: { // 给搜索框子组件传递的信息
zheze_none: true,
searchLabelList: [
{
name: 'ID',
type: 'input',
label: 'ids',
disabled: false
}, {
name: this.$t('overall.name'),
type: 'input',
label: 'name',
disabled: false
}
]
},
// 创建修改相关
blankObject: {
id: '',
name: '',
metaKey: '',
groupIds: '',
group: {},
search: '0',
display: '0',
type: 'TEXT',
param: {},
remark: ''
},
blankMetaGroup: {
id: '',
name: '',
remark: ''
},
filterGroup: '',
showGroup: { name: '' },
metaGroup: {}
}
},
mounted () {
// this.getGroup()
this.showGroup = this.groupData[0]
},
methods: {
add () {
this.object = JSON.parse(JSON.stringify(this.blankObject))
this.rightBox.metaShow = true
},
edit (row) {
this.$get(`${this.url}/${row.id}`).then(response => {
if (response.code === 200) {
this.object = response.data
this.rightBox.metaShow = true
}
})
},
copy (u) {
this.object = { ...u, name: u.name + '-copy', id: '' }
if (this.object.name.length > 64) {
const length = this.object.name.length - 64
this.object.name = u.name.substring(0, u.name.length - length) + '-copy'
}
this.rightBox.metaShow = true
},
closeRightBox (refresh) {
this.rightBox.metaShow = false
this.rightBox.groupShow = false
if (refresh) {
this.delFlag = true
this.getTableData()
this.getGroup()
}
}
},
created () {
const searchKeys = {
// key: path 键
// value: vue set 参数
pageNo: { target: this.pageObj, propertyName: 'pageNo', type: 'number' },
pageSize: { target: this.pageObj, propertyName: 'pageSize', type: 'number' },
orderBy: { target: this.$data, propertyName: 'orderBy', type: 'string' },
ids: {
target: this.searchLabel,
propertyName: 'ids',
isSearchInput: true,
type: 'string',
defaultJson: {
disabled: false,
id: 'ids',
label: 'ids',
name: 'ID',
type: 'input',
val: ''
},
jsonKey: 'val'
},
name: {
target: this.searchLabel,
isSearchInput: true,
propertyName: 'name',
type: 'string',
defaultJson: {
disabled: false,
id: 'name',
label: 'name',
name: 'Name',
type: 'input',
val: ''
},
jsonKey: 'val'
}
}
this.initQueryFromPath(searchKeys)
}
}
</script>

View File

@@ -84,6 +84,10 @@ export default new Router({
path: '/assetState',
component: resolve => require(['@/components/page/config/assetState'], resolve)
},
{
path: '/assetDiscovery',
component: resolve => require(['@/components/page/asset/assetDiscovery'], resolve)
},
{
path: '/assetLabel',
component: resolve => require(['@/components/page/config/assetMeta'], resolve)