mirror of
https://github.com/jumpserver/lina.git
synced 2026-01-14 20:04:25 +00:00
Compare commits
6 Commits
v5
...
v5_refacto
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
65392f1d0c | ||
|
|
777b139fde | ||
|
|
cccd2cbb7a | ||
|
|
f75a4007f6 | ||
|
|
a9c1e06706 | ||
|
|
b66b779e79 |
@@ -142,5 +142,6 @@
|
|||||||
"src/**/*.{js,vue}": [
|
"src/**/*.{js,vue}": [
|
||||||
"eslint --fix"
|
"eslint --fix"
|
||||||
]
|
]
|
||||||
}
|
},
|
||||||
|
"packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
import AssetTreeTable from '@/components/Apps/AssetTreeTable'
|
import AssetTreeTable from '@/components/Apps/AssetTreeTable'
|
||||||
import { AccountInfoFormatter, DetailFormatter } from '@/components/Table/TableFormatters'
|
import { AccountInfoFormatter, DetailFormatter } from '@/components/Table/TableFormatters'
|
||||||
import { connectivityMeta } from '@/components/Apps/AccountListTable/const'
|
import { connectivityMeta } from '@/components/Apps/AccountListTable/const'
|
||||||
|
import { setUrlParam } from '@/utils/common/index'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'GrantedAssets',
|
name: 'GrantedAssets',
|
||||||
@@ -34,7 +35,7 @@ export default {
|
|||||||
}
|
}
|
||||||
const initialUrl = vm.tableConfig.initialUrl
|
const initialUrl = vm.tableConfig.initialUrl
|
||||||
const nodeId = node.meta.data.id
|
const nodeId = node.meta.data.id
|
||||||
const url = initialUrl.replace('/assets/', `/nodes/${nodeId}/assets/`)
|
const url = setUrlParam(initialUrl, 'node_id', nodeId)
|
||||||
vm.tableConfig.url = url
|
vm.tableConfig.url = url
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -70,7 +71,7 @@ export default {
|
|||||||
showMenu: false,
|
showMenu: false,
|
||||||
showRefresh: true,
|
showRefresh: true,
|
||||||
showAssets: false,
|
showAssets: false,
|
||||||
showSearch: false,
|
showSearch: true,
|
||||||
url: this.tableUrl,
|
url: this.tableUrl,
|
||||||
// ?assets=0不显示资产. =1显示资产
|
// ?assets=0不显示资产. =1显示资产
|
||||||
treeUrl: this.treeUrl,
|
treeUrl: this.treeUrl,
|
||||||
@@ -78,6 +79,9 @@ export default {
|
|||||||
callback: {
|
callback: {
|
||||||
onSelected: (event, node) => vm.onSelected(node, vm),
|
onSelected: (event, node) => vm.onSelected(node, vm),
|
||||||
refresh: vm.refreshObjectAssetPermission
|
refresh: vm.refreshObjectAssetPermission
|
||||||
|
},
|
||||||
|
async: {
|
||||||
|
enable: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
tableConfig: {
|
tableConfig: {
|
||||||
|
|||||||
@@ -1,16 +1,67 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<div class="treebox">
|
<div class="treebox">
|
||||||
<div v-if="treeSetting.showSearch">
|
<div v-if="treeSetting.showSearch" @click="focusTreeSearchInput">
|
||||||
<el-input
|
<el-input
|
||||||
v-show="showTreeSearch"
|
v-show="showTreeSearch"
|
||||||
|
ref="treeSearchInput"
|
||||||
v-model="treeSearchValue"
|
v-model="treeSearchValue"
|
||||||
:placeholder="$tc('Search')"
|
|
||||||
class="fixed-tree-search"
|
class="fixed-tree-search"
|
||||||
prefix-icon="fa fa-search"
|
:placeholder="treeSearchInputPlaceholder"
|
||||||
size="mini"
|
size="mini"
|
||||||
@input="treeSearchHandle"
|
@input="treeSearchHandle"
|
||||||
>
|
>
|
||||||
|
<template #prepend>
|
||||||
|
|
||||||
|
<template v-if="!isSearchTypeDropdownEnabled">
|
||||||
|
<el-tooltip
|
||||||
|
effect="dark"
|
||||||
|
placement="top"
|
||||||
|
:content="currentTreeSearchTypeTooltip"
|
||||||
|
:open-delay="300"
|
||||||
|
>
|
||||||
|
<span style="cursor: pointer;" @click.stop="focusTreeSearchInput">
|
||||||
|
<i class="fa fa-search" />
|
||||||
|
<span class="search-label">{{ treeSearchTypeLabel }}</span>
|
||||||
|
</span>
|
||||||
|
</el-tooltip>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template v-else>
|
||||||
|
<el-dropdown trigger="hover" @command="onSearchTypeChange">
|
||||||
|
<el-tooltip
|
||||||
|
effect="dark"
|
||||||
|
placement="top"
|
||||||
|
:content="currentTreeSearchTypeTooltip"
|
||||||
|
:open-delay="1000"
|
||||||
|
>
|
||||||
|
<span @click.stop="focusTreeSearchInput">
|
||||||
|
<i class="fa fa-search" />
|
||||||
|
<span class="search-label">{{ treeSearchTypeLabel }}</span>
|
||||||
|
<i class="el-icon-arrow-down" />
|
||||||
|
</span>
|
||||||
|
</el-tooltip>
|
||||||
|
|
||||||
|
<el-dropdown-menu slot="dropdown">
|
||||||
|
<el-dropdown-item
|
||||||
|
v-for="(item, type) in treeSearchTypeOptions"
|
||||||
|
:key="type"
|
||||||
|
:command="type"
|
||||||
|
:class="{ 'is-active': treeSearchType === type }"
|
||||||
|
>
|
||||||
|
<el-tooltip
|
||||||
|
effect="dark"
|
||||||
|
placement="right"
|
||||||
|
:content="item.tooltip"
|
||||||
|
:open-delay="300"
|
||||||
|
>
|
||||||
|
<span>{{ item.label }}</span>
|
||||||
|
</el-tooltip>
|
||||||
|
</el-dropdown-item>
|
||||||
|
</el-dropdown-menu>
|
||||||
|
</el-dropdown>
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
<span slot="suffix">
|
<span slot="suffix">
|
||||||
<i
|
<i
|
||||||
class="el-icon-close"
|
class="el-icon-close"
|
||||||
@@ -47,6 +98,7 @@ import '@ztree/ztree_v3/js/jquery.ztree.exhide.min.js'
|
|||||||
import '@/styles/ztree.css'
|
import '@/styles/ztree.css'
|
||||||
import '@/styles/ztree_icon.scss'
|
import '@/styles/ztree_icon.scss'
|
||||||
import axiosRetry from 'axios-retry'
|
import axiosRetry from 'axios-retry'
|
||||||
|
import { setUrlParam } from '@/utils/common'
|
||||||
|
|
||||||
const defaultObject = {
|
const defaultObject = {
|
||||||
type: Object,
|
type: Object,
|
||||||
@@ -66,18 +118,52 @@ export default {
|
|||||||
rMenu: '',
|
rMenu: '',
|
||||||
init: false,
|
init: false,
|
||||||
loading: false,
|
loading: false,
|
||||||
showTreeSearch: false,
|
showTreeSearch: true,
|
||||||
treeSearchValue: ''
|
treeSearchValue: '',
|
||||||
|
treeSearchType: 'asset',
|
||||||
|
treeSearchTypeOptions: {},
|
||||||
|
treeSearchTypeSupportOptions: {
|
||||||
|
node: {
|
||||||
|
label: this.$t('Node'),
|
||||||
|
placeholder: this.$t('Search node'),
|
||||||
|
tooltip: this.$t('Search by node name'),
|
||||||
|
search_key: 'search_node'
|
||||||
|
},
|
||||||
|
asset: {
|
||||||
|
label: this.$t('Asset'),
|
||||||
|
placeholder: this.$t('Search asset'),
|
||||||
|
tooltip: this.$t('Search by asset name or address'),
|
||||||
|
search_key: 'search_asset'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
treeType: '' // asset | node
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
treeSetting() {
|
treeSetting() {
|
||||||
return this.setting
|
return this.setting
|
||||||
|
},
|
||||||
|
isSearchTypeDropdownEnabled() {
|
||||||
|
return Object.keys(this.treeSearchTypeOptions).length > 1
|
||||||
|
},
|
||||||
|
currentTreeSearchType() {
|
||||||
|
return this.treeSearchTypeOptions[this.treeSearchType]
|
||||||
|
},
|
||||||
|
currentTreeSearchTypeTooltip() {
|
||||||
|
return this.currentTreeSearchType?.tooltip || ''
|
||||||
|
},
|
||||||
|
treeSearchTypeLabel() {
|
||||||
|
return this.currentTreeSearchType?.label || ''
|
||||||
|
},
|
||||||
|
treeSearchInputPlaceholder() {
|
||||||
|
return this.currentTreeSearchType?.placeholder || this.$t('Search')
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
window.refresh = this.refresh
|
window.refresh = this.refresh
|
||||||
window.onSearch = this.onSearch
|
window.onSearch = this.onSearch
|
||||||
|
this.initTreeType()
|
||||||
|
this.initTreeSearchTypeOptions()
|
||||||
this.initTree().then(() => {
|
this.initTree().then(() => {
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
this.updateTreeHeight()
|
this.updateTreeHeight()
|
||||||
@@ -90,6 +176,36 @@ export default {
|
|||||||
window.removeEventListener('resize', this.updateTreeHeight)
|
window.removeEventListener('resize', this.updateTreeHeight)
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
initTreeType() {
|
||||||
|
let treeType = this.treeSetting.treeType
|
||||||
|
if (!treeType) {
|
||||||
|
treeType = this.treeSetting.async?.enable ? 'asset' : 'node'
|
||||||
|
}
|
||||||
|
this.treeType = treeType
|
||||||
|
},
|
||||||
|
initTreeSearchTypeOptions() {
|
||||||
|
if (this.treeType === 'asset') {
|
||||||
|
// 资产树支持异步搜索节点和资产
|
||||||
|
this.treeSearchTypeOptions = this.treeSearchTypeSupportOptions
|
||||||
|
// 默认搜索资产
|
||||||
|
this.treeSearchType = 'asset'
|
||||||
|
} else {
|
||||||
|
// 节点树只支持搜索节点
|
||||||
|
this.treeSearchTypeOptions = Object.fromEntries(
|
||||||
|
Object.entries(this.treeSearchTypeSupportOptions)
|
||||||
|
.filter(([key]) => key === 'node')
|
||||||
|
)
|
||||||
|
// 默认搜索节点
|
||||||
|
this.treeSearchType = 'node'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onSearchTypeChange(type) {
|
||||||
|
this.treeSearchType = type
|
||||||
|
this.focusTreeSearchInput()
|
||||||
|
},
|
||||||
|
focusTreeSearchInput() {
|
||||||
|
this.$refs.treeSearchInput.focus()
|
||||||
|
},
|
||||||
onMenuClick(menu) {
|
onMenuClick(menu) {
|
||||||
if (menu.disabled) {
|
if (menu.disabled) {
|
||||||
return
|
return
|
||||||
@@ -116,19 +232,14 @@ export default {
|
|||||||
const zTreeRect = tree.getBoundingClientRect()
|
const zTreeRect = tree.getBoundingClientRect()
|
||||||
tree.style.height = `calc(100vh - ${zTreeRect.top}px - 30px - 25px)`
|
tree.style.height = `calc(100vh - ${zTreeRect.top}px - 30px - 25px)`
|
||||||
}, 100),
|
}, 100),
|
||||||
async initTree(refresh = false) {
|
async initTree(refresh = false, iTreeUrl = '') {
|
||||||
const vm = this
|
const vm = this
|
||||||
let treeUrl
|
|
||||||
this.loading = true
|
this.loading = true
|
||||||
if (refresh && this.treeSetting.treeUrl.indexOf('/perms/') !== -1 &&
|
let treeUrl = iTreeUrl
|
||||||
this.treeSetting.treeUrl.indexOf('rebuild_tree') === -1
|
if (!treeUrl) {
|
||||||
) {
|
|
||||||
treeUrl = (this.treeSetting.treeUrl.indexOf('?') === -1)
|
|
||||||
? `${this.treeSetting.treeUrl}?rebuild_tree=1`
|
|
||||||
: `${this.treeSetting.treeUrl}&rebuild_tree=1`
|
|
||||||
} else {
|
|
||||||
treeUrl = this.treeSetting.treeUrl
|
treeUrl = this.treeSetting.treeUrl
|
||||||
}
|
}
|
||||||
|
treeUrl = setUrlParam(treeUrl, 'tree_type', this.treeType)
|
||||||
|
|
||||||
if (refresh) {
|
if (refresh) {
|
||||||
$.fn.zTree.destroy(this.iZTreeID)
|
$.fn.zTree.destroy(this.iZTreeID)
|
||||||
@@ -221,25 +332,31 @@ export default {
|
|||||||
searchInput.oninput = e => this.treeSearchHandle((e.target.value || ''))
|
searchInput.oninput = e => this.treeSearchHandle((e.target.value || ''))
|
||||||
},
|
},
|
||||||
treeSearchHandle: _.debounce(function(value) {
|
treeSearchHandle: _.debounce(function(value) {
|
||||||
if (this.treeSetting.async.enable) {
|
if (this.treeSetting.async?.enable) {
|
||||||
this.filterAssetsServer(value)
|
this.searchFromServer(value)
|
||||||
} else {
|
} else {
|
||||||
this.filterTree(value)
|
this.searchFromLocal(value)
|
||||||
}
|
}
|
||||||
}, 600),
|
}, 600),
|
||||||
getCheckedNodes: function() {
|
getCheckedNodes: function() {
|
||||||
return this.zTree.getCheckedNodes(true)
|
return this.zTree.getCheckedNodes(true)
|
||||||
},
|
},
|
||||||
|
|
||||||
recurseParent(node) {
|
recurseParent(node) {
|
||||||
const parentNode = node.getParentNode()
|
const parentNode = node.getParentNode()
|
||||||
if (parentNode && parentNode.pId) {
|
if (!parentNode) {
|
||||||
return [parentNode, ...this.recurseParent(parentNode)]
|
|
||||||
} else if (parentNode) {
|
|
||||||
return [parentNode]
|
|
||||||
} else {
|
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
|
const allParents = []
|
||||||
|
if (parentNode) {
|
||||||
|
allParents.push(parentNode)
|
||||||
|
if (parentNode.pId) {
|
||||||
|
allParents.push(...this.recurseParent(parentNode))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return allParents
|
||||||
},
|
},
|
||||||
|
|
||||||
recurseChildren(node) {
|
recurseChildren(node) {
|
||||||
if (!node.isParent) {
|
if (!node.isParent) {
|
||||||
return []
|
return []
|
||||||
@@ -248,49 +365,27 @@ export default {
|
|||||||
if (!children) {
|
if (!children) {
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
let allChildren = []
|
const allChildren = []
|
||||||
children.forEach((n) => {
|
children.forEach((n) => {
|
||||||
allChildren = [...children, ...this.recurseChildren(n)]
|
allChildren.push(n)
|
||||||
|
allChildren.push(...this.recurseChildren(n))
|
||||||
})
|
})
|
||||||
return allChildren
|
return allChildren
|
||||||
},
|
},
|
||||||
groupBy(array, filter) {
|
|
||||||
const groups = {}
|
searchFromLocal(keyword, tree = this.zTree) {
|
||||||
array.forEach(function(o) {
|
|
||||||
const group = JSON.stringify(filter(o))
|
|
||||||
groups[group] = groups[group] || []
|
|
||||||
groups[group].push(o)
|
|
||||||
})
|
|
||||||
return Object.keys(groups).map(function(group) {
|
|
||||||
return groups[group]
|
|
||||||
})
|
|
||||||
},
|
|
||||||
filterTree(keyword, tree = this.zTree) {
|
|
||||||
if (!this.zTree) return
|
if (!this.zTree) return
|
||||||
|
|
||||||
const searchNode = tree.getNodesByFilter((node) => node.id === 'search')
|
const searchNode = tree.getNodesByFilter((node) => node.id === 'search')
|
||||||
if (searchNode) tree.removeNode(searchNode[0])
|
if (searchNode) tree.removeNode(searchNode[0])
|
||||||
const nodes = tree.transformToArray(tree.getNodes())
|
|
||||||
|
const allNodes = tree.transformToArray(tree.getNodes())
|
||||||
if (!keyword) {
|
if (!keyword) {
|
||||||
tree.showNodes(nodes)
|
tree.showNodes(allNodes)
|
||||||
|
tree.expandAll(false)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!keyword) {
|
|
||||||
if (tree.hiddenNodes) {
|
|
||||||
tree.showNodes(tree.hiddenNodes)
|
|
||||||
tree.hiddenNodes = null
|
|
||||||
}
|
|
||||||
if (tree.expandNodes) {
|
|
||||||
tree.expandNodes.forEach((node) => {
|
|
||||||
if (node.id !== nodes[0].id) {
|
|
||||||
tree.expandNode(node, false)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
tree.expandNodes = null
|
|
||||||
}
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
let shouldShow = []
|
|
||||||
const matchedNodes = tree.getNodesByFilter((node) => {
|
const matchedNodes = tree.getNodesByFilter((node) => {
|
||||||
return node.name.toLowerCase().indexOf(keyword.toLowerCase()) > -1
|
return node.name.toLowerCase().indexOf(keyword.toLowerCase()) > -1
|
||||||
})
|
})
|
||||||
@@ -300,67 +395,54 @@ export default {
|
|||||||
const assetsAmount = matchedNodes.length
|
const assetsAmount = matchedNodes.length
|
||||||
name = `${name} (${assetsAmount})`
|
name = `${name} (${assetsAmount})`
|
||||||
const newNode = { id: 'search', name: name, isParent: false, open: false }
|
const newNode = { id: 'search', name: name, isParent: false, open: false }
|
||||||
tree.addNodes(null, newNode)
|
const addedNodes = tree.addNodes(null, newNode)
|
||||||
|
// 隐藏所有节点,只显示搜索节点
|
||||||
|
tree.hideNodes(allNodes)
|
||||||
|
tree.showNodes(addedNodes)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 获取应该展示的节点,以及应该展开的节点
|
||||||
|
let shouldShow = []
|
||||||
|
let shouldExpandNodes = []
|
||||||
|
let shouldCollapseNodes = []
|
||||||
matchedNodes.forEach((node) => {
|
matchedNodes.forEach((node) => {
|
||||||
const parents = this.recurseParent(node)
|
const parents = this.recurseParent(node)
|
||||||
const children = this.recurseChildren(node)
|
const children = this.recurseChildren(node)
|
||||||
shouldShow = [...shouldShow, ...parents, ...children, node]
|
// 应该显示匹配节点本身、其祖先节点和子孙节点
|
||||||
})
|
shouldShow.push(node)
|
||||||
|
shouldShow.push(...parents)
|
||||||
|
shouldShow.push(...children)
|
||||||
|
|
||||||
tree.hiddenNodes = nodes
|
// 应该展开匹配节点的父节点,不展开匹配节点的子孙节点
|
||||||
tree.expandNodes = shouldShow
|
shouldExpandNodes.push(...parents)
|
||||||
tree.hideNodes(nodes)
|
// 应该折叠匹配节点的子孙节点
|
||||||
|
shouldCollapseNodes.push(node)
|
||||||
|
shouldCollapseNodes.push(...children)
|
||||||
|
})
|
||||||
|
shouldShow = Array.from(new Set(shouldShow))
|
||||||
|
shouldExpandNodes = Array.from(new Set(shouldExpandNodes))
|
||||||
|
shouldCollapseNodes = Array.from(new Set(shouldCollapseNodes))
|
||||||
|
|
||||||
|
// 隐藏所有节点,显示应该显示的节点
|
||||||
|
tree.hideNodes(allNodes)
|
||||||
tree.showNodes(shouldShow)
|
tree.showNodes(shouldShow)
|
||||||
for (const node of shouldShow) {
|
// 展开应该展开的节点
|
||||||
if (node.isParent) {
|
for (const node of shouldExpandNodes) {
|
||||||
tree.expandNode(node, true)
|
tree.expandNode(node, true)
|
||||||
}
|
}
|
||||||
|
// 折叠应该折叠的节点
|
||||||
|
for (const node of shouldCollapseNodes) {
|
||||||
|
tree.expandNode(node, false)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
filterAssetsServer(keyword) {
|
|
||||||
if (!this.zTree) return
|
|
||||||
let searchNode = this.zTree.getNodesByFilter((node) => node.id === 'search')
|
|
||||||
if (searchNode) {
|
|
||||||
this.zTree.removeChildNodes(searchNode[0])
|
|
||||||
this.zTree.removeNode(searchNode[0])
|
|
||||||
}
|
|
||||||
const treeNodes = this.zTree.getNodes()
|
|
||||||
if (!keyword) {
|
|
||||||
if (treeNodes.length !== 0) {
|
|
||||||
this.zTree.showNodes(treeNodes)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (treeNodes.length !== 0) {
|
|
||||||
this.zTree.hideNodes(treeNodes)
|
|
||||||
}
|
|
||||||
|
|
||||||
let treeUrl = this.treeSetting.searchUrl ? this.treeSetting.searchUrl : this.treeSetting.treeUrl
|
searchFromServer(keyword) {
|
||||||
const filterField = treeUrl.includes('?') ? `&search=${keyword}` : `?search=${keyword}`
|
// 直接用搜索 API 返回的数据重新初始化树
|
||||||
if (treeUrl.indexOf('assets/nodes/children/tree') > -1) {
|
const treeUrl = this.treeSetting.searchUrl ? this.treeSetting.searchUrl : this.treeSetting.treeUrl
|
||||||
treeUrl = treeUrl + '&all=all'
|
const searchTypeKey = this.treeSearchTypeOptions[this.treeSearchType]?.search_key || 'search'
|
||||||
}
|
const searchUrl = setUrlParam(treeUrl, searchTypeKey, keyword)
|
||||||
const searchUrl = `${treeUrl}${filterField}`
|
this.initTree(true, searchUrl)
|
||||||
this.$axios.get(searchUrl).then(nodes => {
|
|
||||||
let name = this.$t('Search')
|
|
||||||
const assetsAmount = nodes.length
|
|
||||||
name = `${name} (${assetsAmount})`
|
|
||||||
const newNode = { id: 'search', name: name, isParent: true, open: true, zAsync: true }
|
|
||||||
searchNode = this.zTree.addNodes(null, newNode)[0]
|
|
||||||
searchNode.zAsync = true
|
|
||||||
this.rootNodeAddDom(searchNode)
|
|
||||||
|
|
||||||
const nodesGroupByOrg = this.groupBy(nodes, (node) => {
|
|
||||||
return node.meta?.data?.org_name
|
|
||||||
})
|
|
||||||
|
|
||||||
for (const item of nodesGroupByOrg) {
|
|
||||||
this.zTree.addNodes(searchNode, item)
|
|
||||||
}
|
|
||||||
searchNode.open = true
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -624,12 +706,19 @@ div.rMenu li {
|
|||||||
|
|
||||||
.fixed-tree-search {
|
.fixed-tree-search {
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
|
border: 1px solid;
|
||||||
|
border-radius: 3px;
|
||||||
|
|
||||||
|
&:hover,
|
||||||
|
&:focus-within {
|
||||||
|
border-color: var(--color-primary);
|
||||||
|
}
|
||||||
|
|
||||||
& ::v-deep .el-input__inner {
|
& ::v-deep .el-input__inner {
|
||||||
border-radius: 4px;
|
border: none;
|
||||||
background: #fafafa;
|
background: #fafafa;
|
||||||
padding-right: 32px;
|
padding-right: 32px;
|
||||||
color: var(--color-text-primary)
|
color: var(--color-text-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
& ::v-deep .el-input__suffix {
|
& ::v-deep .el-input__suffix {
|
||||||
@@ -653,6 +742,37 @@ div.rMenu li {
|
|||||||
& ::v-deep .el-input__suffix-inner {
|
& ::v-deep .el-input__suffix-inner {
|
||||||
line-height: 30px;
|
line-height: 30px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
& ::v-deep .el-input-group__prepend {
|
||||||
|
padding-left: 5px;
|
||||||
|
padding-right: 3px;
|
||||||
|
border: none;
|
||||||
|
color: #999;
|
||||||
|
* {
|
||||||
|
color: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
align-items: center;
|
||||||
|
background: #fafafa;
|
||||||
|
.el-icon-arrow-down {
|
||||||
|
display: inline-block;
|
||||||
|
transition: transform 0.8s ease; /* 动画关键 */
|
||||||
|
}
|
||||||
|
:hover {
|
||||||
|
.el-icon-arrow-down {
|
||||||
|
transform: rotate(180deg); /* 顺时针 180° */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.search-label {
|
||||||
|
margin-left: 1px;
|
||||||
|
margin-right: 1px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
::v-deep .el-dropdown-menu__item.is-active {
|
||||||
|
color: var(--color-primary);
|
||||||
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
|
|
||||||
.icon-refresh {
|
.icon-refresh {
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ export default {
|
|||||||
updateSuccessNextRoute: this.updateSuccessNextRoute,
|
updateSuccessNextRoute: this.updateSuccessNextRoute,
|
||||||
hasDetailInMsg: false,
|
hasDetailInMsg: false,
|
||||||
fields: [
|
fields: [
|
||||||
[this.$t('Basic'), ['name', 'address', 'platform', 'nodes']],
|
[this.$t('Basic'), ['name', 'address', 'platform', 'node']],
|
||||||
[this.$t('Protocol'), ['protocols']],
|
[this.$t('Protocol'), ['protocols']],
|
||||||
[this.$t('Account'), ['accounts']],
|
[this.$t('Account'), ['accounts']],
|
||||||
[this.$t('Other'), ['directory_services', 'zone', 'labels', 'is_active', 'comment']]
|
[this.$t('Other'), ['directory_services', 'zone', 'labels', 'is_active', 'comment']]
|
||||||
@@ -73,8 +73,8 @@ export default {
|
|||||||
const values = _.cloneDeep(validValues)
|
const values = _.cloneDeep(validValues)
|
||||||
const submitMethod = id ? 'put' : 'post'
|
const submitMethod = id ? 'put' : 'post'
|
||||||
|
|
||||||
if (values.nodes && values.nodes.length === 0) {
|
if (!values.node) {
|
||||||
delete values['nodes']
|
delete values['node']
|
||||||
}
|
}
|
||||||
|
|
||||||
if (submitMethod === 'put') {
|
if (submitMethod === 'put') {
|
||||||
@@ -143,15 +143,14 @@ export default {
|
|||||||
},
|
},
|
||||||
async setInitial() {
|
async setInitial() {
|
||||||
const { defaultConfig } = this
|
const { defaultConfig } = this
|
||||||
const { node } = this.$route.query
|
const { node_id } = this.$route.query
|
||||||
const nodesInitial = node ? [node] : []
|
|
||||||
const platformId = this.platformID || 'Linux'
|
const platformId = this.platformID || 'Linux'
|
||||||
const url = `/api/v1/assets/platforms/${platformId}/`
|
const url = `/api/v1/assets/platforms/${platformId}/`
|
||||||
this.platform = await this.$axios.get(url)
|
this.platform = await this.$axios.get(url)
|
||||||
const initial = {
|
const initial = {
|
||||||
labels: [],
|
labels: [],
|
||||||
is_active: true,
|
is_active: true,
|
||||||
nodes: nodesInitial,
|
node: node_id,
|
||||||
platform: parseInt(this.platform.id),
|
platform: parseInt(this.platform.id),
|
||||||
protocols: []
|
protocols: []
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,6 +46,9 @@ export default {
|
|||||||
url: '/api/v1/assets/assets/',
|
url: '/api/v1/assets/assets/',
|
||||||
showMenu: !this.$store.getters.currentOrgIsRoot,
|
showMenu: !this.$store.getters.currentOrgIsRoot,
|
||||||
showDefaultMenu: true,
|
showDefaultMenu: true,
|
||||||
|
async: {
|
||||||
|
enable: false
|
||||||
|
},
|
||||||
menu: [
|
menu: [
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -148,9 +148,10 @@ export const assetFieldsMeta = (vm, category, type) => {
|
|||||||
return vm.platform.ds_enabled === false
|
return vm.platform.ds_enabled === false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
nodes: {
|
node: {
|
||||||
rules: [rules.RequiredChange],
|
rules: [rules.RequiredChange],
|
||||||
el: {
|
el: {
|
||||||
|
multiple: false,
|
||||||
ajax: {
|
ajax: {
|
||||||
url: '/api/v1/assets/nodes/',
|
url: '/api/v1/assets/nodes/',
|
||||||
transformOption: item => {
|
transformOption: item => {
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ export default {
|
|||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
treeUrl: `/api/v1/perms/users/${this.object.id}/nodes/children/tree/`,
|
treeUrl: `/api/v1/perms/users/${this.object.id}/nodes/children/tree/`,
|
||||||
tableUrl: `/api/v1/perms/users/${this.object.id}/assets/?all=1`,
|
tableUrl: `/api/v1/perms/users/${this.object.id}/assets/`,
|
||||||
actions: {
|
actions: {
|
||||||
has: false
|
has: false
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user