mirror of
https://github.com/veops/cmdb.git
synced 2025-08-25 20:09:00 +08:00
feat(ui): ci relation table - add upstream and downstream grouping
This commit is contained in:
@@ -721,7 +721,9 @@ if __name__ == "__main__":
|
|||||||
batchRollbacking: 'Deleting {total} items in total, {successNum} items successful, {errorNum} items failed',
|
batchRollbacking: 'Deleting {total} items in total, {successNum} items successful, {errorNum} items failed',
|
||||||
baselineTips: 'Changes at this point in time will also be rollbacked, Unique ID, password and dynamic attributes do not support',
|
baselineTips: 'Changes at this point in time will also be rollbacked, Unique ID, password and dynamic attributes do not support',
|
||||||
cover: 'Cover',
|
cover: 'Cover',
|
||||||
detail: 'Detail'
|
detail: 'Detail',
|
||||||
|
upstream: 'Upstream',
|
||||||
|
downstream: 'Downstream'
|
||||||
},
|
},
|
||||||
serviceTree: {
|
serviceTree: {
|
||||||
remove: 'Remove',
|
remove: 'Remove',
|
||||||
|
@@ -720,7 +720,9 @@ if __name__ == "__main__":
|
|||||||
batchRollbacking: '正在回滚,共{total}个,成功{successNum}个,失败{errorNum}个',
|
batchRollbacking: '正在回滚,共{total}个,成功{successNum}个,失败{errorNum}个',
|
||||||
baselineTips: '该时间点的变更也会被回滚, 唯一标识、密码属性、动态属性不支持回滚',
|
baselineTips: '该时间点的变更也会被回滚, 唯一标识、密码属性、动态属性不支持回滚',
|
||||||
cover: '覆盖',
|
cover: '覆盖',
|
||||||
detail: '详情'
|
detail: '详情',
|
||||||
|
upstream: '上游',
|
||||||
|
downstream: '下游'
|
||||||
},
|
},
|
||||||
serviceTree: {
|
serviceTree: {
|
||||||
remove: '移除',
|
remove: '移除',
|
||||||
|
@@ -5,29 +5,44 @@
|
|||||||
<div class="ci-relation-table-wrap">
|
<div class="ci-relation-table-wrap">
|
||||||
<div class="ci-relation-table-tab">
|
<div class="ci-relation-table-tab">
|
||||||
<div
|
<div
|
||||||
v-for="(item) in tabList"
|
v-for="(group) in tabList"
|
||||||
:key="item.value"
|
:key="group.key"
|
||||||
:class="`tab-item ${item.value === currentTab ? 'tab-item-active' : ''}`"
|
class="tab-group"
|
||||||
@click="clickTab(item.value)"
|
|
||||||
>
|
>
|
||||||
<span class="tab-item-name">
|
<div
|
||||||
<a-tooltip :title="item.name">
|
v-if="group.name"
|
||||||
<span class="tab-item-name-text">{{ item.name }}</span>
|
class="tab-group-name"
|
||||||
</a-tooltip>
|
|
||||||
<span
|
|
||||||
v-if="item.count"
|
|
||||||
class="tab-item-name-count"
|
|
||||||
>
|
|
||||||
({{ item.count }})
|
|
||||||
</span>
|
|
||||||
</span>
|
|
||||||
<span
|
|
||||||
v-if="item.value === currentTab && item.showAdd"
|
|
||||||
class="tab-item-add"
|
|
||||||
@click="openAddModal(item)"
|
|
||||||
>
|
>
|
||||||
<a-icon type="plus" />
|
{{ group.name }}
|
||||||
</span>
|
</div>
|
||||||
|
<div
|
||||||
|
v-for="(item) in group.list"
|
||||||
|
:key="item.key"
|
||||||
|
:class="`tab-item ${item.key === currentTab ? 'tab-item-active' : ''}`"
|
||||||
|
:style="{
|
||||||
|
paddingLeft: item.key === 'all' ? '8px' : '16px'
|
||||||
|
}"
|
||||||
|
@click="clickTab(item.key)"
|
||||||
|
>
|
||||||
|
<span class="tab-item-name">
|
||||||
|
<a-tooltip :title="item.name">
|
||||||
|
<span class="tab-item-name-text">{{ item.name }}</span>
|
||||||
|
</a-tooltip>
|
||||||
|
<span
|
||||||
|
v-if="item.count"
|
||||||
|
class="tab-item-name-count"
|
||||||
|
>
|
||||||
|
({{ item.count }})
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
<span
|
||||||
|
v-if="item.key === currentTab && item.showAdd"
|
||||||
|
class="tab-item-add"
|
||||||
|
@click="openAddModal(item)"
|
||||||
|
>
|
||||||
|
<a-icon type="plus" />
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -37,7 +52,7 @@
|
|||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
v-for="(item) in tableIDList"
|
v-for="(item) in tableIDList"
|
||||||
:key="item.id"
|
:key="item.key"
|
||||||
class="ci-relation-table-item"
|
class="ci-relation-table-item"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
@@ -51,8 +66,8 @@
|
|||||||
<vxe-grid
|
<vxe-grid
|
||||||
bordered
|
bordered
|
||||||
size="mini"
|
size="mini"
|
||||||
:columns="allColumns[item.id]"
|
:columns="allColumns[item.value]"
|
||||||
:data="allCIList[item.id]"
|
:data="allCIList[item.key]"
|
||||||
overflow
|
overflow
|
||||||
showOverflow="tooltip"
|
showOverflow="tooltip"
|
||||||
showHeaderOverflow="tooltip"
|
showHeaderOverflow="tooltip"
|
||||||
@@ -77,9 +92,9 @@
|
|||||||
@confirm="deleteRelation(row)"
|
@confirm="deleteRelation(row)"
|
||||||
>
|
>
|
||||||
<a
|
<a
|
||||||
:disabled="!allCanEdit[item.id]"
|
:disabled="!allCanEdit[item.value]"
|
||||||
:style="{
|
:style="{
|
||||||
color: !allCanEdit[item.id] ? 'rgba(0, 0, 0, 0.25)' : 'red',
|
color: !allCanEdit[item.value] ? 'rgba(0, 0, 0, 0.25)' : 'red',
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<a-icon type="delete" />
|
<a-icon type="delete" />
|
||||||
@@ -105,6 +120,9 @@ import { getSubscribeAttributes } from '@/modules/cmdb/api/preference'
|
|||||||
import CIDetailTableTitle from './ciDetailTableTitle.vue'
|
import CIDetailTableTitle from './ciDetailTableTitle.vue'
|
||||||
import AddTableModal from '@/modules/cmdb/views/relation_views/modules/AddTableModal.vue'
|
import AddTableModal from '@/modules/cmdb/views/relation_views/modules/AddTableModal.vue'
|
||||||
|
|
||||||
|
const PARENT_KEY = 'parents'
|
||||||
|
const CHILDREN_KEY = 'children'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'CIRelationTable',
|
name: 'CIRelationTable',
|
||||||
components: {
|
components: {
|
||||||
@@ -151,24 +169,26 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
|
tabListFlat() {
|
||||||
|
return this.tabList.reduce((list, group) => list.concat(group.list), [])
|
||||||
|
},
|
||||||
tableIDList() {
|
tableIDList() {
|
||||||
let baseIDs = []
|
const baseKeys = this.currentTab === 'all'
|
||||||
|
? this.tabListFlat.filter(item => item.value !== 'all').map(item => item.key)
|
||||||
|
: [this.currentTab]
|
||||||
|
|
||||||
switch (this.currentTab) {
|
return baseKeys.filter((key) => this.allCIList?.[key]?.length).map((key) => {
|
||||||
case 'all':
|
const findTab = this.tabListFlat.find((item) => item.key === key) || {}
|
||||||
baseIDs = this.tabList.filter((item) => item.value !== 'all').map((item) => item.value)
|
|
||||||
break
|
|
||||||
default:
|
|
||||||
baseIDs = [this.currentTab]
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
return baseIDs.filter((id) => this.allCIList?.[id]?.length).map((id) => {
|
let name = findTab?.name || ''
|
||||||
const findTab = this.tabList.find((item) => item.value === id) || {}
|
if (name && findTab?.value === this.ci._type) {
|
||||||
|
name = `${findTab?.isParent ? this.$t('cmdb.ci.upstream') : this.$t('cmdb.ci.downstream')} - ${name}`
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
id,
|
key,
|
||||||
name: findTab?.name || '',
|
value: findTab?.value || '',
|
||||||
|
name,
|
||||||
count: findTab?.count || ''
|
count: findTab?.count || ''
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -234,25 +254,48 @@ export default {
|
|||||||
...childCIs
|
...childCIs
|
||||||
}
|
}
|
||||||
|
|
||||||
const tabList = this.allCITypes.map((item) => {
|
const tabList = []
|
||||||
return {
|
|
||||||
name: item?.alias ?? item?.name ?? '',
|
tabList[0] = {
|
||||||
value: item.id,
|
name: '',
|
||||||
count: this.allCIList?.[item.id]?.length || 0,
|
key: 'all',
|
||||||
showAdd: this.allCanEdit?.[item.id] ?? false
|
list: [{
|
||||||
}
|
name: this.$t('all'),
|
||||||
})
|
key: 'all',
|
||||||
tabList.unshift({
|
value: 'all',
|
||||||
name: this.$t('all'),
|
count: Object.values(this.allCIList).reduce((acc, cur) => acc + (cur?.length || 0), 0),
|
||||||
value: 'all',
|
showAdd: false
|
||||||
count: Object.values(this.allCIList).reduce((acc, cur) => acc + (cur?.length || 0), 0),
|
}]
|
||||||
showAdd: false
|
}
|
||||||
})
|
tabList[1] = {
|
||||||
|
name: this.$t('cmdb.ci.upstream'),
|
||||||
|
key: PARENT_KEY,
|
||||||
|
list: this.buildTabList(cloneRelationData.parentCITypeList, PARENT_KEY, true)
|
||||||
|
}
|
||||||
|
tabList[2] = {
|
||||||
|
name: this.$t('cmdb.ci.downstream'),
|
||||||
|
key: CHILDREN_KEY,
|
||||||
|
list: this.buildTabList(cloneRelationData.childCITypeList, CHILDREN_KEY, false)
|
||||||
|
}
|
||||||
this.tabList = tabList
|
this.tabList = tabList
|
||||||
|
|
||||||
this.handleReferenceCINameMap()
|
this.handleReferenceCINameMap()
|
||||||
},
|
},
|
||||||
|
|
||||||
|
buildTabList(list, keyPrefix, isParent) {
|
||||||
|
return list.map((item) => {
|
||||||
|
const key = `${keyPrefix}-${item.id}`
|
||||||
|
return {
|
||||||
|
name: item?.alias ?? item?.name ?? '',
|
||||||
|
key,
|
||||||
|
isParent,
|
||||||
|
value: item.id,
|
||||||
|
count: this.allCIList?.[key]?.length || 0,
|
||||||
|
showAdd: this.allCanEdit?.[item.id] ?? false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
handleCITypeList(list, isParent) {
|
handleCITypeList(list, isParent) {
|
||||||
const CIColumns = {}
|
const CIColumns = {}
|
||||||
const CIJSONAttr = {}
|
const CIJSONAttr = {}
|
||||||
@@ -365,11 +408,12 @@ export default {
|
|||||||
})
|
})
|
||||||
this.formatCI(item)
|
this.formatCI(item)
|
||||||
item.isParent = isParent
|
item.isParent = isParent
|
||||||
|
const CIKey = `${isParent ? PARENT_KEY : CHILDREN_KEY}-${item._type}`
|
||||||
|
|
||||||
if (item._type in cis) {
|
if (CIKey in cis) {
|
||||||
cis[item._type].push(item)
|
cis[CIKey].push(item)
|
||||||
} else {
|
} else {
|
||||||
cis[item._type] = [item]
|
cis[CIKey] = [item]
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -398,9 +442,11 @@ export default {
|
|||||||
async handleReferenceCINameMap() {
|
async handleReferenceCINameMap() {
|
||||||
const referenceCINameMap = {}
|
const referenceCINameMap = {}
|
||||||
this.allCITypes.forEach((CIType) => {
|
this.allCITypes.forEach((CIType) => {
|
||||||
|
const CIKey = `${CIType.isParent ? PARENT_KEY : CHILDREN_KEY}-${CIType.id}`
|
||||||
|
|
||||||
CIType.attributes.forEach((attr) => {
|
CIType.attributes.forEach((attr) => {
|
||||||
if (attr?.is_reference && attr?.reference_type_id) {
|
if (attr?.is_reference && attr?.reference_type_id) {
|
||||||
const currentCIList = this.allCIList[CIType.id]
|
const currentCIList = this.allCIList[CIKey]
|
||||||
if (currentCIList?.length) {
|
if (currentCIList?.length) {
|
||||||
currentCIList.forEach((ci) => {
|
currentCIList.forEach((ci) => {
|
||||||
const ids = Array.isArray(ci[attr.name]) ? ci[attr.name] : ci[attr.name] ? [ci[attr.name]] : []
|
const ids = Array.isArray(ci[attr.name]) ? ci[attr.name] : ci[attr.name] ? [ci[attr.name]] : []
|
||||||
@@ -461,8 +507,8 @@ export default {
|
|||||||
return this.referenceCINameMap?.[typeId]?.[id] || id
|
return this.referenceCINameMap?.[typeId]?.[id] || id
|
||||||
},
|
},
|
||||||
|
|
||||||
clickTab(value) {
|
clickTab(key) {
|
||||||
this.currentTab = value
|
this.currentTab = key
|
||||||
},
|
},
|
||||||
|
|
||||||
deleteRelation(row) {
|
deleteRelation(row) {
|
||||||
@@ -486,7 +532,7 @@ export default {
|
|||||||
},
|
},
|
||||||
this.ciId,
|
this.ciId,
|
||||||
ciType,
|
ciType,
|
||||||
ciType?.isParent ? 'parents' : 'children'
|
tabData?.isParent ? 'parents' : 'children'
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -512,12 +558,26 @@ export default {
|
|||||||
&-tab {
|
&-tab {
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
width: 160px;
|
width: 160px;
|
||||||
max-height: 300px;
|
min-height: 300px;
|
||||||
|
max-height: 600px;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
padding: 6px 0px;
|
padding: 6px 0px;
|
||||||
border-right: solid 1px #E4E7ED;
|
border-right: solid 1px #E4E7ED;
|
||||||
|
|
||||||
|
.tab-group {
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
&-name {
|
||||||
|
padding-left: 8px;
|
||||||
|
height: 32px;
|
||||||
|
line-height: 32px;
|
||||||
|
width: 100%;
|
||||||
|
font-weight: 600;
|
||||||
|
color: rgba(0, 0, 0, .45);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.tab-item {
|
.tab-item {
|
||||||
height: 32px;
|
height: 32px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@@ -586,6 +646,9 @@ export default {
|
|||||||
padding: 15px 17px;
|
padding: 15px 17px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
min-height: 300px;
|
min-height: 300px;
|
||||||
|
max-height: 600px;
|
||||||
|
overflow-y: auto;
|
||||||
|
overflow-x: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
&-item {
|
&-item {
|
||||||
|
Reference in New Issue
Block a user