mirror of https://github.com/veops/cmdb.git
feat(cmdb-ui): attributes relation (#463)
This commit is contained in:
parent
099ddd6ca9
commit
c7d4bec988
Binary file not shown.
Before Width: | Height: | Size: 8.0 KiB After Width: | Height: | Size: 35 KiB |
|
@ -59,7 +59,6 @@ export default {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
.two-column-layout-sidebar {
|
.two-column-layout-sidebar {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
border-radius: 15px;
|
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
.two-column-layout-main {
|
.two-column-layout-main {
|
||||||
|
|
|
@ -30,11 +30,11 @@ export function getRelationTypes(CITypeID, parameter) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createRelation(parentId, childrenId, relationTypeId, constraint) {
|
export function createRelation(parentId, childrenId, data) {
|
||||||
return axios({
|
return axios({
|
||||||
url: `/v0.1/ci_type_relations/${parentId}/${childrenId}`,
|
url: `/v0.1/ci_type_relations/${parentId}/${childrenId}`,
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data: { relation_type_id: relationTypeId, constraint }
|
data
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,7 +42,6 @@ export function deleteRelation(parentId, childrenId) {
|
||||||
return axios({
|
return axios({
|
||||||
url: `/v0.1/ci_type_relations/${parentId}/${childrenId}`,
|
url: `/v0.1/ci_type_relations/${parentId}/${childrenId}`,
|
||||||
method: 'delete'
|
method: 'delete'
|
||||||
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -187,7 +187,14 @@ const cmdb_en = {
|
||||||
downloadType: 'Download CIType',
|
downloadType: 'Download CIType',
|
||||||
deleteCIType: 'Delete CIType',
|
deleteCIType: 'Delete CIType',
|
||||||
otherGroupTips: 'Non sortable within the other group',
|
otherGroupTips: 'Non sortable within the other group',
|
||||||
filterTips: 'click to show {name}'
|
filterTips: 'click to show {name}',
|
||||||
|
attributeAssociation: 'Attribute Association',
|
||||||
|
attributeAssociationTip1: 'Automatically establish relationships through the attributes except password, json and multiple of two models',
|
||||||
|
attributeAssociationTip2: 'Double click to edit',
|
||||||
|
attributeAssociationTip3: 'Two Attributes must be selected',
|
||||||
|
attributeAssociationTip4: 'Please select a attribute from Source CIType',
|
||||||
|
attributeAssociationTip5: 'Please select a attribute from Target CIType',
|
||||||
|
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
unselectAttributes: 'Unselected',
|
unselectAttributes: 'Unselected',
|
||||||
|
|
|
@ -129,7 +129,7 @@ const cmdb_zh = {
|
||||||
addRelation: '新增关系',
|
addRelation: '新增关系',
|
||||||
sourceCIType: '源模型',
|
sourceCIType: '源模型',
|
||||||
sourceCITypeTips: '请选择源模型',
|
sourceCITypeTips: '请选择源模型',
|
||||||
dstCIType: '目标模型名',
|
dstCIType: '目标模型',
|
||||||
dstCITypeTips: '请选择目标模型',
|
dstCITypeTips: '请选择目标模型',
|
||||||
relationType: '关联类型',
|
relationType: '关联类型',
|
||||||
relationTypeTips: '请选择关联类型',
|
relationTypeTips: '请选择关联类型',
|
||||||
|
@ -187,7 +187,13 @@ const cmdb_zh = {
|
||||||
downloadType: '下载模型',
|
downloadType: '下载模型',
|
||||||
deleteCIType: '删除模型',
|
deleteCIType: '删除模型',
|
||||||
otherGroupTips: '其他分组属性不可排序',
|
otherGroupTips: '其他分组属性不可排序',
|
||||||
filterTips: '点击可仅查看{name}属性'
|
filterTips: '点击可仅查看{name}属性',
|
||||||
|
attributeAssociation: '属性关联',
|
||||||
|
attributeAssociationTip1: '通过2个模型的属性值(除密码、json、多值)来自动建立关系',
|
||||||
|
attributeAssociationTip2: '双击可编辑',
|
||||||
|
attributeAssociationTip3: '属性关联必须选择两个属性',
|
||||||
|
attributeAssociationTip4: '请选择原模型属性',
|
||||||
|
attributeAssociationTip5: '请选择目标模型属性',
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
unselectAttributes: '未选属性',
|
unselectAttributes: '未选属性',
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<a-tab-pane key="1" :tab="$t('cmdb.ciType.attributes')">
|
<a-tab-pane key="1" :tab="$t('cmdb.ciType.attributes')">
|
||||||
<AttributesTable ref="attributesTable" :CITypeId="CITypeId" :CITypeName="CITypeName"></AttributesTable>
|
<AttributesTable ref="attributesTable" :CITypeId="CITypeId" :CITypeName="CITypeName"></AttributesTable>
|
||||||
</a-tab-pane>
|
</a-tab-pane>
|
||||||
<a-tab-pane forceRender key="2" :tab="$t('cmdb.ciType.relation')">
|
<a-tab-pane key="2" :tab="$t('cmdb.ciType.relation')">
|
||||||
<RelationTable :CITypeId="CITypeId" :CITypeName="CITypeName"></RelationTable>
|
<RelationTable :CITypeId="CITypeId" :CITypeName="CITypeName"></RelationTable>
|
||||||
</a-tab-pane>
|
</a-tab-pane>
|
||||||
<a-tab-pane key="3" :tab="$t('cmdb.ciType.trigger')">
|
<a-tab-pane key="3" :tab="$t('cmdb.ciType.trigger')">
|
||||||
|
|
|
@ -15,11 +15,16 @@
|
||||||
:data="tableData"
|
:data="tableData"
|
||||||
size="small"
|
size="small"
|
||||||
show-overflow
|
show-overflow
|
||||||
|
show-header-overflow
|
||||||
highlight-hover-row
|
highlight-hover-row
|
||||||
keep-source
|
keep-source
|
||||||
:max-height="windowHeight - 180"
|
:height="windowHeight - 190"
|
||||||
class="ops-stripe-table"
|
class="ops-stripe-table"
|
||||||
:row-class-name="rowClass"
|
:row-class-name="rowClass"
|
||||||
|
:edit-config="{ trigger: 'dblclick', mode: 'cell', showIcon: false }"
|
||||||
|
resizable
|
||||||
|
@edit-closed="handleEditClose"
|
||||||
|
@edit-actived="handleEditActived"
|
||||||
>
|
>
|
||||||
<vxe-column field="source_ci_type_name" :title="$t('cmdb.ciType.sourceCIType')"></vxe-column>
|
<vxe-column field="source_ci_type_name" :title="$t('cmdb.ciType.sourceCIType')"></vxe-column>
|
||||||
<vxe-column field="relation_type" :title="$t('cmdb.ciType.relationType')">
|
<vxe-column field="relation_type" :title="$t('cmdb.ciType.relationType')">
|
||||||
|
@ -40,6 +45,59 @@
|
||||||
<span v-else>{{ constraintMap[row.constraint] }}</span>
|
<span v-else>{{ constraintMap[row.constraint] }}</span>
|
||||||
</template>
|
</template>
|
||||||
</vxe-column>
|
</vxe-column>
|
||||||
|
<vxe-column :width="250" field="attributeAssociation" :edit-render="{}">
|
||||||
|
<template #header>
|
||||||
|
<span>
|
||||||
|
<a-tooltip :title="$t('cmdb.ciType.attributeAssociationTip1')">
|
||||||
|
<a><a-icon type="question-circle"/></a>
|
||||||
|
</a-tooltip>
|
||||||
|
{{ $t('cmdb.ciType.attributeAssociation') }}
|
||||||
|
<span :style="{ fontSize: '10px', fontWeight: 'normal' }" class="text-color-4">{{
|
||||||
|
$t('cmdb.ciType.attributeAssociationTip2')
|
||||||
|
}}</span>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
<template #default="{row}">
|
||||||
|
<span
|
||||||
|
v-if="row.parent_attr_id && row.child_attr_id"
|
||||||
|
>{{ getAttrNameById(row.isParent ? row.attributes : attributes, row.parent_attr_id) }}=>
|
||||||
|
{{ getAttrNameById(row.isParent ? attributes : row.attributes, row.child_attr_id) }}</span
|
||||||
|
>
|
||||||
|
</template>
|
||||||
|
<template #edit="{ row }">
|
||||||
|
<div style="display:inline-flex;align-items:center;">
|
||||||
|
<a-select
|
||||||
|
allowClear
|
||||||
|
size="small"
|
||||||
|
v-model="parent_attr_id"
|
||||||
|
:getPopupContainer="(trigger) => trigger.parentNode"
|
||||||
|
:style="{ width: '100px' }"
|
||||||
|
>
|
||||||
|
<a-select-option
|
||||||
|
v-for="attr in filterAttributes(row.isParent ? row.attributes : attributes)"
|
||||||
|
:key="attr.id"
|
||||||
|
>
|
||||||
|
{{ attr.alias || attr.name }}
|
||||||
|
</a-select-option>
|
||||||
|
</a-select>
|
||||||
|
=>
|
||||||
|
<a-select
|
||||||
|
allowClear
|
||||||
|
size="small"
|
||||||
|
v-model="child_attr_id"
|
||||||
|
:getPopupContainer="(trigger) => trigger.parentNode"
|
||||||
|
:style="{ width: '100px' }"
|
||||||
|
>
|
||||||
|
<a-select-option
|
||||||
|
v-for="attr in filterAttributes(row.isParent ? attributes : row.attributes)"
|
||||||
|
:key="attr.id"
|
||||||
|
>
|
||||||
|
{{ attr.alias || attr.name }}
|
||||||
|
</a-select-option>
|
||||||
|
</a-select>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</vxe-column>
|
||||||
<vxe-column field="operation" :title="$t('operation')" width="100">
|
<vxe-column field="operation" :title="$t('operation')" width="100">
|
||||||
<template #default="{row}">
|
<template #default="{row}">
|
||||||
<a-space v-if="!row.isParent && row.source_ci_type_id">
|
<a-space v-if="!row.isParent && row.source_ci_type_id">
|
||||||
|
@ -63,12 +121,13 @@
|
||||||
:visible="visible"
|
:visible="visible"
|
||||||
@cancel="onClose"
|
@cancel="onClose"
|
||||||
@ok="handleSubmit"
|
@ok="handleSubmit"
|
||||||
width="500px"
|
width="700px"
|
||||||
>
|
>
|
||||||
<a-form :form="form" @submit="handleSubmit" :label-col="{ span: 6 }" :wrapper-col="{ span: 14 }">
|
<a-form :form="form" @submit="handleSubmit" :label-col="{ span: 6 }" :wrapper-col="{ span: 14 }">
|
||||||
<a-form-item :label="$t('cmdb.ciType.sourceCIType')">
|
<a-form-item :label="$t('cmdb.ciType.sourceCIType')">
|
||||||
<a-select
|
<a-select
|
||||||
name="source_ci_type_id"
|
name="source_ci_type_id"
|
||||||
|
:placeholder="$t('cmdb.ciType.sourceCITypeTips')"
|
||||||
v-decorator="[
|
v-decorator="[
|
||||||
'source_ci_type_id',
|
'source_ci_type_id',
|
||||||
{ rules: [{ required: true, message: $t('cmdb.ciType.sourceCITypeTips') }] },
|
{ rules: [{ required: true, message: $t('cmdb.ciType.sourceCITypeTips') }] },
|
||||||
|
@ -83,8 +142,10 @@
|
||||||
<a-select
|
<a-select
|
||||||
showSearch
|
showSearch
|
||||||
name="ci_type_id"
|
name="ci_type_id"
|
||||||
|
:placeholder="$t('cmdb.ciType.dstCITypeTips')"
|
||||||
v-decorator="['ci_type_id', { rules: [{ required: true, message: $t('cmdb.ciType.dstCITypeTips') }] }]"
|
v-decorator="['ci_type_id', { rules: [{ required: true, message: $t('cmdb.ciType.dstCITypeTips') }] }]"
|
||||||
:filterOption="filterOption"
|
:filterOption="filterOption"
|
||||||
|
@change="changeChild"
|
||||||
>
|
>
|
||||||
<a-select-option :value="CIType.id" :key="CIType.id" v-for="CIType in CITypes">
|
<a-select-option :value="CIType.id" :key="CIType.id" v-for="CIType in CITypes">
|
||||||
{{ CIType.alias || CIType.name }}
|
{{ CIType.alias || CIType.name }}
|
||||||
|
@ -95,6 +156,7 @@
|
||||||
<a-form-item :label="$t('cmdb.ciType.relationType')">
|
<a-form-item :label="$t('cmdb.ciType.relationType')">
|
||||||
<a-select
|
<a-select
|
||||||
name="relation_type_id"
|
name="relation_type_id"
|
||||||
|
:placeholder="$t('cmdb.ciType.relationTypeTips')"
|
||||||
v-decorator="[
|
v-decorator="[
|
||||||
'relation_type_id',
|
'relation_type_id',
|
||||||
{ rules: [{ required: true, message: $t('cmdb.ciType.relationTypeTips') }] },
|
{ rules: [{ required: true, message: $t('cmdb.ciType.relationTypeTips') }] },
|
||||||
|
@ -105,9 +167,9 @@
|
||||||
}}</a-select-option>
|
}}</a-select-option>
|
||||||
</a-select>
|
</a-select>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
|
||||||
<a-form-item :label="$t('cmdb.ciType.relationConstraint')">
|
<a-form-item :label="$t('cmdb.ciType.relationConstraint')">
|
||||||
<a-select
|
<a-select
|
||||||
|
:placeholder="$t('cmdb.ciType.relationConstraintTips')"
|
||||||
v-decorator="[
|
v-decorator="[
|
||||||
'constraint',
|
'constraint',
|
||||||
{ rules: [{ required: true, message: $t('cmdb.ciType.relationConstraintTips') }] },
|
{ rules: [{ required: true, message: $t('cmdb.ciType.relationConstraintTips') }] },
|
||||||
|
@ -118,6 +180,39 @@
|
||||||
<a-select-option value="2">{{ $t('cmdb.ciType.many2Many') }}</a-select-option>
|
<a-select-option value="2">{{ $t('cmdb.ciType.many2Many') }}</a-select-option>
|
||||||
</a-select>
|
</a-select>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
<a-form-item :label="$t('cmdb.ciType.attributeAssociation')">
|
||||||
|
<a-row>
|
||||||
|
<a-col :span="11">
|
||||||
|
<a-form-item>
|
||||||
|
<a-select
|
||||||
|
:placeholder="$t('cmdb.ciType.attributeAssociationTip4')"
|
||||||
|
allowClear
|
||||||
|
v-decorator="['parent_attr_id', { rules: [{ required: false }] }]"
|
||||||
|
>
|
||||||
|
<a-select-option v-for="attr in filterAttributes(attributes)" :key="attr.id">
|
||||||
|
{{ attr.alias || attr.name }}
|
||||||
|
</a-select-option>
|
||||||
|
</a-select>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
<a-col :span="2" :style="{ textAlign: 'center' }">
|
||||||
|
=>
|
||||||
|
</a-col>
|
||||||
|
<a-col :span="11">
|
||||||
|
<a-form-item>
|
||||||
|
<a-select
|
||||||
|
:placeholder="$t('cmdb.ciType.attributeAssociationTip5')"
|
||||||
|
allowClear
|
||||||
|
v-decorator="['child_attr_id', { rules: [{ required: false }] }]"
|
||||||
|
>
|
||||||
|
<a-select-option v-for="attr in filterAttributes(modalChildAttributes)" :key="attr.id">
|
||||||
|
{{ attr.alias || attr.name }}
|
||||||
|
</a-select-option>
|
||||||
|
</a-select>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
</a-row>
|
||||||
|
</a-form-item>
|
||||||
</a-form>
|
</a-form>
|
||||||
</a-modal>
|
</a-modal>
|
||||||
<CMDBGrant ref="cmdbGrant" resourceType="CITypeRelation" app_id="cmdb" />
|
<CMDBGrant ref="cmdbGrant" resourceType="CITypeRelation" app_id="cmdb" />
|
||||||
|
@ -133,6 +228,8 @@ import {
|
||||||
getRelationTypes,
|
getRelationTypes,
|
||||||
} from '@/modules/cmdb/api/CITypeRelation'
|
} from '@/modules/cmdb/api/CITypeRelation'
|
||||||
import { getCITypes } from '@/modules/cmdb/api/CIType'
|
import { getCITypes } from '@/modules/cmdb/api/CIType'
|
||||||
|
import { getCITypeAttributesById } from '@/modules/cmdb/api/CITypeAttr'
|
||||||
|
|
||||||
import CMDBGrant from '../../components/cmdbGrant'
|
import CMDBGrant from '../../components/cmdbGrant'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
@ -163,6 +260,10 @@ export default {
|
||||||
relationTypes: [],
|
relationTypes: [],
|
||||||
tableData: [],
|
tableData: [],
|
||||||
parentTableData: [],
|
parentTableData: [],
|
||||||
|
attributes: [],
|
||||||
|
parent_attr_id: undefined,
|
||||||
|
child_attr_id: undefined,
|
||||||
|
modalChildAttributes: [],
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
@ -181,14 +282,20 @@ export default {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
async mounted() {
|
async mounted() {
|
||||||
|
getCITypeAttributesById(this.CITypeId).then((res) => {
|
||||||
|
this.attributes = res?.attributes ?? []
|
||||||
|
})
|
||||||
this.getCITypes()
|
this.getCITypes()
|
||||||
this.getRelationTypes()
|
this.getRelationTypes()
|
||||||
if (!this.isInGrantComp) {
|
|
||||||
await this.getCITypeParent()
|
|
||||||
}
|
|
||||||
this.getData()
|
this.getData()
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
async getData() {
|
||||||
|
if (!this.isInGrantComp) {
|
||||||
|
await this.getCITypeParent()
|
||||||
|
}
|
||||||
|
this.getCITypeChildren()
|
||||||
|
},
|
||||||
async getCITypeParent() {
|
async getCITypeParent() {
|
||||||
await getCITypeParent(this.CITypeId).then((res) => {
|
await getCITypeParent(this.CITypeId).then((res) => {
|
||||||
this.parentTableData = res.parents.map((item) => {
|
this.parentTableData = res.parents.map((item) => {
|
||||||
|
@ -201,7 +308,7 @@ export default {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
getData() {
|
getCITypeChildren() {
|
||||||
getCITypeChildren(this.CITypeId).then((res) => {
|
getCITypeChildren(this.CITypeId).then((res) => {
|
||||||
const data = res.children.map((obj) => {
|
const data = res.children.map((obj) => {
|
||||||
return {
|
return {
|
||||||
|
@ -230,12 +337,9 @@ export default {
|
||||||
handleDelete(record) {
|
handleDelete(record) {
|
||||||
deleteRelation(record.source_ci_type_id, record.id).then((res) => {
|
deleteRelation(record.source_ci_type_id, record.id).then((res) => {
|
||||||
this.$message.success(this.$t('deleteSuccess'))
|
this.$message.success(this.$t('deleteSuccess'))
|
||||||
this.handleOk()
|
this.getData()
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
handleOk() {
|
|
||||||
this.getData()
|
|
||||||
},
|
|
||||||
|
|
||||||
handleCreate() {
|
handleCreate() {
|
||||||
this.drawerTitle = this.$t('cmdb.ciType.addRelation')
|
this.drawerTitle = this.$t('cmdb.ciType.addRelation')
|
||||||
|
@ -258,14 +362,29 @@ export default {
|
||||||
if (!err) {
|
if (!err) {
|
||||||
// eslint-disable-next-line no-console
|
// eslint-disable-next-line no-console
|
||||||
console.log('Received values of form: ', values)
|
console.log('Received values of form: ', values)
|
||||||
|
const {
|
||||||
|
source_ci_type_id,
|
||||||
|
ci_type_id,
|
||||||
|
relation_type_id,
|
||||||
|
constraint,
|
||||||
|
parent_attr_id = undefined,
|
||||||
|
child_attr_id = undefined,
|
||||||
|
} = values
|
||||||
|
|
||||||
createRelation(values.source_ci_type_id, values.ci_type_id, values.relation_type_id, values.constraint).then(
|
if ((!parent_attr_id && child_attr_id) || (parent_attr_id && !child_attr_id)) {
|
||||||
(res) => {
|
this.$message.warning(this.$t('cmdb.ciType.attributeAssociationTip3'))
|
||||||
this.$message.success(this.$t('addSuccess'))
|
return
|
||||||
this.onClose()
|
}
|
||||||
this.handleOk()
|
createRelation(source_ci_type_id, ci_type_id, {
|
||||||
}
|
relation_type_id,
|
||||||
)
|
constraint,
|
||||||
|
parent_attr_id,
|
||||||
|
child_attr_id,
|
||||||
|
}).then((res) => {
|
||||||
|
this.$message.success(this.$t('addSuccess'))
|
||||||
|
this.onClose()
|
||||||
|
this.getData()
|
||||||
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
@ -283,6 +402,42 @@ export default {
|
||||||
if (row.isDivider) return 'relation-table-divider'
|
if (row.isDivider) return 'relation-table-divider'
|
||||||
if (row.isParent) return 'relation-table-parent'
|
if (row.isParent) return 'relation-table-parent'
|
||||||
},
|
},
|
||||||
|
handleEditActived({ row }) {
|
||||||
|
this.parent_attr_id = row?.parent_attr_id ?? undefined
|
||||||
|
this.child_attr_id = row?.child_attr_id ?? undefined
|
||||||
|
},
|
||||||
|
async handleEditClose({ row }) {
|
||||||
|
const { source_ci_type_id: parentId, id: childrenId, constraint, relation_type } = row
|
||||||
|
const { parent_attr_id, child_attr_id } = this
|
||||||
|
const _find = this.relationTypes.find((item) => item.name === relation_type)
|
||||||
|
const relation_type_id = _find?.id
|
||||||
|
if ((!parent_attr_id && child_attr_id) || (parent_attr_id && !child_attr_id)) {
|
||||||
|
this.$message.warning(this.$t('cmdb.ciType.attributeAssociationTip3'))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
await createRelation(row.isParent ? childrenId : parentId, row.isParent ? parentId : childrenId, {
|
||||||
|
relation_type_id,
|
||||||
|
constraint,
|
||||||
|
parent_attr_id,
|
||||||
|
child_attr_id,
|
||||||
|
}).finally(() => {
|
||||||
|
this.getData()
|
||||||
|
})
|
||||||
|
},
|
||||||
|
getAttrNameById(attributes, id) {
|
||||||
|
const _find = attributes.find((attr) => attr.id === id)
|
||||||
|
return _find?.alias ?? _find?.name ?? id
|
||||||
|
},
|
||||||
|
changeChild(value) {
|
||||||
|
this.form.setFieldsValue({ child_attr_id: undefined })
|
||||||
|
getCITypeAttributesById(value).then((res) => {
|
||||||
|
this.modalChildAttributes = res?.attributes ?? []
|
||||||
|
})
|
||||||
|
},
|
||||||
|
filterAttributes(attributes) {
|
||||||
|
// filter password/json/is_list
|
||||||
|
return attributes.filter((attr) => !attr.is_password && !attr.is_list && attr.value_type !== '6')
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
:visible="visible"
|
:visible="visible"
|
||||||
@cancel="onClose"
|
@cancel="onClose"
|
||||||
@ok="handleSubmit"
|
@ok="handleSubmit"
|
||||||
width="500px"
|
width="700px"
|
||||||
>
|
>
|
||||||
<a-form :form="form" @submit="handleSubmit" :label-col="{ span: 6 }" :wrapper-col="{ span: 14 }">
|
<a-form :form="form" @submit="handleSubmit" :label-col="{ span: 6 }" :wrapper-col="{ span: 14 }">
|
||||||
<a-form-item :label="$t('cmdb.ciType.sourceCIType')">
|
<a-form-item :label="$t('cmdb.ciType.sourceCIType')">
|
||||||
|
@ -69,6 +69,39 @@
|
||||||
<a-select-option value="2">{{ $t('cmdb.ciType.many2Many') }}</a-select-option>
|
<a-select-option value="2">{{ $t('cmdb.ciType.many2Many') }}</a-select-option>
|
||||||
</a-select>
|
</a-select>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
<a-form-item :label="$t('cmdb.ciType.attributeAssociation')">
|
||||||
|
<a-row>
|
||||||
|
<a-col :span="11">
|
||||||
|
<a-form-item>
|
||||||
|
<a-select
|
||||||
|
:placeholder="$t('cmdb.ciType.attributeAssociationTip4')"
|
||||||
|
allowClear
|
||||||
|
v-decorator="['parent_attr_id', { rules: [{ required: false }] }]"
|
||||||
|
>
|
||||||
|
<a-select-option v-for="attr in filterAttributes(modalParentAttributes)" :key="attr.id">
|
||||||
|
{{ attr.alias || attr.name }}
|
||||||
|
</a-select-option>
|
||||||
|
</a-select>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
<a-col :span="2" :style="{ textAlign: 'center' }">
|
||||||
|
=>
|
||||||
|
</a-col>
|
||||||
|
<a-col :span="11">
|
||||||
|
<a-form-item>
|
||||||
|
<a-select
|
||||||
|
:placeholder="$t('cmdb.ciType.attributeAssociationTip5')"
|
||||||
|
allowClear
|
||||||
|
v-decorator="['child_attr_id', { rules: [{ required: false }] }]"
|
||||||
|
>
|
||||||
|
<a-select-option v-for="attr in filterAttributes(modalChildAttributes)" :key="attr.id">
|
||||||
|
{{ attr.alias || attr.name }}
|
||||||
|
</a-select-option>
|
||||||
|
</a-select>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
</a-row>
|
||||||
|
</a-form-item>
|
||||||
</a-form>
|
</a-form>
|
||||||
</a-modal>
|
</a-modal>
|
||||||
</div>
|
</div>
|
||||||
|
@ -80,6 +113,8 @@ import { searchResourceType } from '@/modules/acl/api/resource'
|
||||||
import { getCITypeGroupsConfig } from '@/modules/cmdb/api/ciTypeGroup'
|
import { getCITypeGroupsConfig } from '@/modules/cmdb/api/ciTypeGroup'
|
||||||
import { getCITypes } from '@/modules/cmdb/api/CIType'
|
import { getCITypes } from '@/modules/cmdb/api/CIType'
|
||||||
import { createRelation, deleteRelation, getCITypeChildren, getRelationTypes } from '@/modules/cmdb/api/CITypeRelation'
|
import { createRelation, deleteRelation, getCITypeChildren, getRelationTypes } from '@/modules/cmdb/api/CITypeRelation'
|
||||||
|
import { getCITypeAttributesById } from '@/modules/cmdb/api/CITypeAttr'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'Index',
|
name: 'Index',
|
||||||
components: {
|
components: {
|
||||||
|
@ -101,6 +136,9 @@ export default {
|
||||||
|
|
||||||
sourceCITypeId: undefined,
|
sourceCITypeId: undefined,
|
||||||
targetCITypeId: undefined,
|
targetCITypeId: undefined,
|
||||||
|
|
||||||
|
modalParentAttributes: [],
|
||||||
|
modalChildAttributes: [],
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
@ -206,13 +244,29 @@ export default {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
this.form.validateFields((err, values) => {
|
this.form.validateFields((err, values) => {
|
||||||
if (!err) {
|
if (!err) {
|
||||||
createRelation(values.source_ci_type_id, values.ci_type_id, values.relation_type_id, values.constraint).then(
|
const {
|
||||||
(res) => {
|
source_ci_type_id,
|
||||||
this.$message.success(this.$t('addSuccess'))
|
ci_type_id,
|
||||||
this.onClose()
|
relation_type_id,
|
||||||
this.handleOk()
|
constraint,
|
||||||
}
|
parent_attr_id = undefined,
|
||||||
)
|
child_attr_id = undefined,
|
||||||
|
} = values
|
||||||
|
|
||||||
|
if ((!parent_attr_id && child_attr_id) || (parent_attr_id && !child_attr_id)) {
|
||||||
|
this.$message.warning(this.$t('cmdb.ciType.attributeAssociationTip3'))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
createRelation(source_ci_type_id, ci_type_id, {
|
||||||
|
relation_type_id,
|
||||||
|
constraint,
|
||||||
|
parent_attr_id,
|
||||||
|
child_attr_id,
|
||||||
|
}).then((res) => {
|
||||||
|
this.$message.success(this.$t('addSuccess'))
|
||||||
|
this.onClose()
|
||||||
|
this.handleOk()
|
||||||
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
this.sourceCITypeId = undefined
|
this.sourceCITypeId = undefined
|
||||||
|
@ -230,13 +284,25 @@ export default {
|
||||||
},
|
},
|
||||||
handleSourceTypeChange(value) {
|
handleSourceTypeChange(value) {
|
||||||
this.sourceCITypeId = value
|
this.sourceCITypeId = value
|
||||||
|
this.form.setFieldsValue({ parent_attr_id: undefined })
|
||||||
|
getCITypeAttributesById(value).then((res) => {
|
||||||
|
this.modalParentAttributes = res?.attributes ?? []
|
||||||
|
})
|
||||||
},
|
},
|
||||||
handleTargetTypeChange(value) {
|
handleTargetTypeChange(value) {
|
||||||
this.targetCITypeId = value
|
this.targetCITypeId = value
|
||||||
|
this.form.setFieldsValue({ child_attr_id: undefined })
|
||||||
|
getCITypeAttributesById(value).then((res) => {
|
||||||
|
this.modalChildAttributes = res?.attributes ?? []
|
||||||
|
})
|
||||||
},
|
},
|
||||||
filterOption(input, option) {
|
filterOption(input, option) {
|
||||||
return option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0
|
return option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0
|
||||||
},
|
},
|
||||||
|
filterAttributes(attributes) {
|
||||||
|
// filter password/json/is_list
|
||||||
|
return attributes.filter((attr) => !attr.is_password && !attr.is_list && attr.value_type !== '6')
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -10,6 +10,9 @@
|
||||||
:height="`${windowHeight - 160}px`"
|
:height="`${windowHeight - 160}px`"
|
||||||
:data="tableData"
|
:data="tableData"
|
||||||
:sort-config="{ defaultSort: { field: 'created_at', order: 'desc' } }"
|
:sort-config="{ defaultSort: { field: 'created_at', order: 'desc' } }"
|
||||||
|
:edit-config="{ trigger: 'dblclick', mode: 'cell', showIcon: false }"
|
||||||
|
@edit-closed="handleEditClose"
|
||||||
|
@edit-actived="handleEditActived"
|
||||||
>
|
>
|
||||||
<vxe-column field="created_at" :title="$t('created_at')" sortable width="159px"></vxe-column>
|
<vxe-column field="created_at" :title="$t('created_at')" sortable width="159px"></vxe-column>
|
||||||
<vxe-column field="parent.alias" :title="$t('cmdb.ciType.sourceCIType')"></vxe-column>
|
<vxe-column field="parent.alias" :title="$t('cmdb.ciType.sourceCIType')"></vxe-column>
|
||||||
|
@ -26,8 +29,59 @@
|
||||||
</template>
|
</template>
|
||||||
</vxe-column>
|
</vxe-column>
|
||||||
<vxe-column field="child.alias" :title="$t('cmdb.ciType.dstCIType')"></vxe-column>
|
<vxe-column field="child.alias" :title="$t('cmdb.ciType.dstCIType')"></vxe-column>
|
||||||
<vxe-column field="constraint" :title="$t('cmdb.ciType.relationConstraint')"></vxe-column>
|
<vxe-column field="constraint" :title="$t('cmdb.ciType.relationConstraint')">
|
||||||
<vxe-column field="authorization" :title="$t('operation')" width="89px">
|
<template #default="{row}">
|
||||||
|
{{ handleConstraint(row.constraint) }}
|
||||||
|
</template>
|
||||||
|
</vxe-column>
|
||||||
|
<vxe-column :width="250" field="attributeAssociation" :edit-render="{}">
|
||||||
|
<template #header>
|
||||||
|
<span>
|
||||||
|
<a-tooltip :title="$t('cmdb.ciType.attributeAssociationTip1')">
|
||||||
|
<a><a-icon type="question-circle"/></a>
|
||||||
|
</a-tooltip>
|
||||||
|
{{ $t('cmdb.ciType.attributeAssociation') }}
|
||||||
|
<span :style="{ fontSize: '10px', fontWeight: 'normal' }" class="text-color-4">{{
|
||||||
|
$t('cmdb.ciType.attributeAssociationTip2')
|
||||||
|
}}</span>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
<template #default="{row}">
|
||||||
|
<span
|
||||||
|
v-if="row.parent_attr_id && row.child_attr_id"
|
||||||
|
>{{ getAttrNameById(type2attributes[row.parent_id], row.parent_attr_id) }}=>
|
||||||
|
{{ getAttrNameById(type2attributes[row.child_id], row.child_attr_id) }}</span
|
||||||
|
>
|
||||||
|
</template>
|
||||||
|
<template #edit="{ row }">
|
||||||
|
<div style="display:inline-flex;align-items:center;">
|
||||||
|
<a-select
|
||||||
|
allowClear
|
||||||
|
size="small"
|
||||||
|
v-model="parent_attr_id"
|
||||||
|
:getPopupContainer="(trigger) => trigger.parentNode"
|
||||||
|
:style="{ width: '100px' }"
|
||||||
|
>
|
||||||
|
<a-select-option v-for="attr in filterAttributes(type2attributes[row.parent_id])" :key="attr.id">
|
||||||
|
{{ attr.alias || attr.name }}
|
||||||
|
</a-select-option>
|
||||||
|
</a-select>
|
||||||
|
=>
|
||||||
|
<a-select
|
||||||
|
allowClear
|
||||||
|
size="small"
|
||||||
|
v-model="child_attr_id"
|
||||||
|
:getPopupContainer="(trigger) => trigger.parentNode"
|
||||||
|
:style="{ width: '100px' }"
|
||||||
|
>
|
||||||
|
<a-select-option v-for="attr in filterAttributes(type2attributes[row.child_id])" :key="attr.id">
|
||||||
|
{{ attr.alias || attr.name }}
|
||||||
|
</a-select-option>
|
||||||
|
</a-select>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</vxe-column>
|
||||||
|
<vxe-column field="operation" :title="$t('operation')" width="89px">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<a-space>
|
<a-space>
|
||||||
<a @click="handleOpenGrant(row)"><a-icon type="user-add"/></a>
|
<a @click="handleOpenGrant(row)"><a-icon type="user-add"/></a>
|
||||||
|
@ -43,7 +97,7 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { getCITypeRelations, deleteRelation } from '@/modules/cmdb/api/CITypeRelation'
|
import { getCITypeRelations, deleteRelation, createRelation } from '@/modules/cmdb/api/CITypeRelation'
|
||||||
import { getRelationTypes } from '@/modules/cmdb/api/relationType'
|
import { getRelationTypes } from '@/modules/cmdb/api/relationType'
|
||||||
import CMDBGrant from '../../../components/cmdbGrant'
|
import CMDBGrant from '../../../components/cmdbGrant'
|
||||||
|
|
||||||
|
@ -53,6 +107,9 @@ export default {
|
||||||
drawerVisible: false,
|
drawerVisible: false,
|
||||||
tableData: [],
|
tableData: [],
|
||||||
relationTypeList: null,
|
relationTypeList: null,
|
||||||
|
type2attributes: {},
|
||||||
|
parent_attr_id: undefined,
|
||||||
|
child_attr_id: undefined,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
|
@ -79,11 +136,9 @@ export default {
|
||||||
await this.getMainData()
|
await this.getMainData()
|
||||||
},
|
},
|
||||||
async getMainData() {
|
async getMainData() {
|
||||||
const res = await getCITypeRelations()
|
const { relations, type2attributes } = await getCITypeRelations()
|
||||||
res.forEach((item) => {
|
this.tableData = relations
|
||||||
item.constraint = this.handleConstraint(item.constraint)
|
this.type2attributes = type2attributes
|
||||||
})
|
|
||||||
this.tableData = res
|
|
||||||
},
|
},
|
||||||
// 获取关系
|
// 获取关系
|
||||||
async getRelationTypes() {
|
async getRelationTypes() {
|
||||||
|
@ -115,6 +170,34 @@ export default {
|
||||||
this.refresh()
|
this.refresh()
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
handleEditActived({ row }) {
|
||||||
|
this.parent_attr_id = row?.parent_attr_id ?? undefined
|
||||||
|
this.child_attr_id = row?.child_attr_id ?? undefined
|
||||||
|
},
|
||||||
|
async handleEditClose({ row }) {
|
||||||
|
const { parent_id, child_id, constraint, relation_type_id } = row
|
||||||
|
const { parent_attr_id = undefined, child_attr_id = undefined } = this
|
||||||
|
if ((!parent_attr_id && child_attr_id) || (parent_attr_id && !child_attr_id)) {
|
||||||
|
this.$message.warning(this.$t('cmdb.ciType.attributeAssociationTip3'))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
await createRelation(parent_id, child_id, {
|
||||||
|
relation_type_id,
|
||||||
|
constraint,
|
||||||
|
parent_attr_id,
|
||||||
|
child_attr_id,
|
||||||
|
}).finally(() => {
|
||||||
|
this.getMainData()
|
||||||
|
})
|
||||||
|
},
|
||||||
|
getAttrNameById(attributes, id) {
|
||||||
|
const _find = attributes.find((attr) => attr.id === id)
|
||||||
|
return _find?.alias ?? _find?.name ?? id
|
||||||
|
},
|
||||||
|
filterAttributes(attributes) {
|
||||||
|
// filter password/json/is_list
|
||||||
|
return attributes.filter((attr) => !attr.is_password && !attr.is_list && attr.value_type !== '6')
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -154,7 +154,7 @@ export default {
|
||||||
this.getViewsData()
|
this.getViewsData()
|
||||||
},
|
},
|
||||||
async getMainData() {
|
async getMainData() {
|
||||||
const ciTypeRelations = await getCITypeRelations()
|
const { relations: ciTypeRelations } = await getCITypeRelations()
|
||||||
const nodes = []
|
const nodes = []
|
||||||
const links = []
|
const links = []
|
||||||
ciTypeRelations.forEach((item) => {
|
ciTypeRelations.forEach((item) => {
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
@click="clickNode"
|
@click="clickNode"
|
||||||
>
|
>
|
||||||
<span class="relation-views-node-switch">
|
<span class="relation-views-node-switch">
|
||||||
<a-icon v-if="childLength && !isLeaf" :type="switchIcon"></a-icon>
|
<a-icon v-if="!isLeaf" :type="switchIcon"></a-icon>
|
||||||
</span>
|
</span>
|
||||||
<span class="relation-views-node-content">
|
<span class="relation-views-node-content">
|
||||||
<a-checkbox @click.stop="clickCheckbox" class="relation-views-node-checkbox" v-if="showCheckbox" />
|
<a-checkbox @click.stop="clickCheckbox" class="relation-views-node-checkbox" v-if="showCheckbox" />
|
||||||
|
|
|
@ -910,6 +910,7 @@ body {
|
||||||
.vue-treeselect__multi-value,
|
.vue-treeselect__multi-value,
|
||||||
.vue-treeselect__multi-value-item {
|
.vue-treeselect__multi-value-item {
|
||||||
line-height: var(--custom-multiple-lineHeight);
|
line-height: var(--custom-multiple-lineHeight);
|
||||||
|
line-height: 18px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.custom-treeselect.vue-treeselect--open-below .vue-treeselect__menu {
|
.custom-treeselect.vue-treeselect--open-below .vue-treeselect__menu {
|
||||||
|
|
Loading…
Reference in New Issue