mirror of
https://github.com/veops/cmdb.git
synced 2025-08-25 12:39:06 +08:00
feat(ui): support multi-value attribute associations
This commit is contained in:
@@ -50,13 +50,18 @@
|
|||||||
<vxe-column :width="300" field="attributeAssociation" :edit-render="{}">
|
<vxe-column :width="300" field="attributeAssociation" :edit-render="{}">
|
||||||
<template #header>
|
<template #header>
|
||||||
<span>
|
<span>
|
||||||
<a-tooltip :title="$t('cmdb.ciType.attributeAssociationTip1')">
|
<a-tooltip>
|
||||||
|
<template #title>
|
||||||
|
<div>{{ $t('cmdb.ciType.attributeAssociationTip1') }}</div>
|
||||||
|
<div>{{ $t('cmdb.ciType.attributeAssociationTip7') }}</div>
|
||||||
|
<div>{{ $t('cmdb.ciType.attributeAssociationTip8') }}</div>
|
||||||
|
</template>
|
||||||
<a><a-icon type="question-circle"/></a>
|
<a><a-icon type="question-circle"/></a>
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
{{ $t('cmdb.ciType.attributeAssociation') }}
|
{{ $t('cmdb.ciType.attributeAssociation') }}
|
||||||
<span :style="{ fontSize: '10px', fontWeight: 'normal' }" class="text-color-4">{{
|
<span :style="{ fontSize: '10px', fontWeight: 'normal' }" class="text-color-4">
|
||||||
$t('cmdb.ciType.attributeAssociationTip2')
|
{{ $t('cmdb.ciType.attributeAssociationTip2') }}
|
||||||
}}</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
<template #default="{row}">
|
<template #default="{row}">
|
||||||
@@ -88,7 +93,13 @@
|
|||||||
optionFilterProp="title"
|
optionFilterProp="title"
|
||||||
>
|
>
|
||||||
<a-select-option
|
<a-select-option
|
||||||
v-for="attr in filterAttributes(row.isParent ? row.attributes : attributes)"
|
v-for="attr in filterAttributes(
|
||||||
|
row.isParent ? row.attributes : attributes,
|
||||||
|
item.childAttrId,
|
||||||
|
row.isParent ? attributes : row.attributes,
|
||||||
|
'parent',
|
||||||
|
row.constraint
|
||||||
|
)"
|
||||||
:key="attr.id"
|
:key="attr.id"
|
||||||
:value="attr.id"
|
:value="attr.id"
|
||||||
:title="attr.alias || attr.name"
|
:title="attr.alias || attr.name"
|
||||||
@@ -107,7 +118,13 @@
|
|||||||
optionFilterProp="title"
|
optionFilterProp="title"
|
||||||
>
|
>
|
||||||
<a-select-option
|
<a-select-option
|
||||||
v-for="attr in filterAttributes(row.isParent ? attributes : row.attributes)"
|
v-for="attr in filterAttributes(
|
||||||
|
row.isParent ? attributes : row.attributes,
|
||||||
|
item.parentAttrId,
|
||||||
|
row.isParent ? row.attributes : attributes,
|
||||||
|
'child',
|
||||||
|
row.constraint
|
||||||
|
)"
|
||||||
:key="attr.id"
|
:key="attr.id"
|
||||||
:value="attr.id"
|
:value="attr.id"
|
||||||
:title="attr.alias || attr.name"
|
:title="attr.alias || attr.name"
|
||||||
@@ -200,6 +217,7 @@
|
|||||||
'constraint',
|
'constraint',
|
||||||
{ rules: [{ required: true, message: $t('cmdb.ciType.relationConstraintTips') }] },
|
{ rules: [{ required: true, message: $t('cmdb.ciType.relationConstraintTips') }] },
|
||||||
]"
|
]"
|
||||||
|
@change="handleFormConstraintChange"
|
||||||
>
|
>
|
||||||
<a-select-option value="0">{{ $t('cmdb.ciType.one2Many') }}</a-select-option>
|
<a-select-option value="0">{{ $t('cmdb.ciType.one2Many') }}</a-select-option>
|
||||||
<a-select-option value="1">{{ $t('cmdb.ciType.one2One') }}</a-select-option>
|
<a-select-option value="1">{{ $t('cmdb.ciType.one2One') }}</a-select-option>
|
||||||
@@ -207,6 +225,10 @@
|
|||||||
</a-select>
|
</a-select>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item :label="$t('cmdb.ciType.attributeAssociation')">
|
<a-form-item :label="$t('cmdb.ciType.attributeAssociation')">
|
||||||
|
<template #extra>
|
||||||
|
<div>{{ $t('cmdb.ciType.attributeAssociationTip7') }}</div>
|
||||||
|
<div>{{ $t('cmdb.ciType.attributeAssociationTip8') }}</div>
|
||||||
|
</template>
|
||||||
<a-row
|
<a-row
|
||||||
v-for="item in modalAttrList"
|
v-for="item in modalAttrList"
|
||||||
:key="item.id"
|
:key="item.id"
|
||||||
@@ -218,7 +240,15 @@
|
|||||||
allowClear
|
allowClear
|
||||||
v-model="item.parentAttrId"
|
v-model="item.parentAttrId"
|
||||||
>
|
>
|
||||||
<a-select-option v-for="attr in filterAttributes(attributes)" :key="attr.id">
|
<a-select-option
|
||||||
|
v-for="attr in filterAttributes(
|
||||||
|
attributes,
|
||||||
|
item.childAttrId,
|
||||||
|
modalChildAttributes,
|
||||||
|
'parent'
|
||||||
|
)"
|
||||||
|
:key="attr.id"
|
||||||
|
>
|
||||||
{{ attr.alias || attr.name }}
|
{{ attr.alias || attr.name }}
|
||||||
</a-select-option>
|
</a-select-option>
|
||||||
</a-select>
|
</a-select>
|
||||||
@@ -234,7 +264,15 @@
|
|||||||
allowClear
|
allowClear
|
||||||
v-model="item.childAttrId"
|
v-model="item.childAttrId"
|
||||||
>
|
>
|
||||||
<a-select-option v-for="attr in filterAttributes(modalChildAttributes)" :key="attr.id">
|
<a-select-option
|
||||||
|
v-for="attr in filterAttributes(
|
||||||
|
modalChildAttributes,
|
||||||
|
item.parentAttrId,
|
||||||
|
attributes,
|
||||||
|
'child'
|
||||||
|
)"
|
||||||
|
:key="attr.id"
|
||||||
|
>
|
||||||
{{ attr.alias || attr.name }}
|
{{ attr.alias || attr.name }}
|
||||||
</a-select-option>
|
</a-select-option>
|
||||||
</a-select>
|
</a-select>
|
||||||
@@ -594,16 +632,34 @@ export default {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
filterAttributes(attributes) {
|
|
||||||
// filter password/json/is_list/longText/bool/reference
|
filterAttributes(attributes, relationAttrId, relationAttrs, type, constraint) {
|
||||||
return attributes.filter((attr) => {
|
const relationAttr = relationAttrs.find((attr) => attr.id === relationAttrId)
|
||||||
|
|
||||||
|
// filter password/json/longText/bool/reference
|
||||||
|
let filterAttrs = attributes.filter((attr) => {
|
||||||
if (attr.value_type === '2' && !attr.is_index) {
|
if (attr.value_type === '2' && !attr.is_index) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
return !attr.is_password && !attr.is_list && attr.value_type !== '6' && !attr.is_bool && !attr.is_reference
|
return !attr.is_password && attr.value_type !== '6' && !attr.is_bool && !attr.is_reference
|
||||||
})
|
})
|
||||||
|
|
||||||
|
if (relationAttr) {
|
||||||
|
filterAttrs = filterAttrs.filter((attr) => attr.value_type === relationAttr?.value_type)
|
||||||
|
}
|
||||||
|
|
||||||
|
const constraintValue = Number(constraint ?? this.form.getFieldValue('constraint'))
|
||||||
|
if (
|
||||||
|
(constraintValue === 0 && type === 'child') ||
|
||||||
|
constraintValue === 1
|
||||||
|
) {
|
||||||
|
return filterAttrs.filter((attr) => !attr.is_list)
|
||||||
|
}
|
||||||
|
|
||||||
|
return filterAttrs
|
||||||
},
|
},
|
||||||
|
|
||||||
addTableAttr() {
|
addTableAttr() {
|
||||||
this.tableAttrList.push({
|
this.tableAttrList.push({
|
||||||
id: uuidv4(),
|
id: uuidv4(),
|
||||||
@@ -639,6 +695,13 @@ export default {
|
|||||||
if (index !== -1) {
|
if (index !== -1) {
|
||||||
this.modalAttrList.splice(index, 1)
|
this.modalAttrList.splice(index, 1)
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
handleFormConstraintChange() {
|
||||||
|
this.modalAttrList.forEach((item) => {
|
||||||
|
item.parentAttrId = undefined
|
||||||
|
item.childAttrId = undefined
|
||||||
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@@ -56,6 +56,7 @@
|
|||||||
'constraint',
|
'constraint',
|
||||||
{ rules: [{ required: true, message: $t('cmdb.ciType.relationConstraintTips') }] },
|
{ rules: [{ required: true, message: $t('cmdb.ciType.relationConstraintTips') }] },
|
||||||
]"
|
]"
|
||||||
|
@change="handleConstraintChange"
|
||||||
>
|
>
|
||||||
<a-select-option value="0">{{ $t('cmdb.ciType.one2Many') }}</a-select-option>
|
<a-select-option value="0">{{ $t('cmdb.ciType.one2Many') }}</a-select-option>
|
||||||
<a-select-option value="1">{{ $t('cmdb.ciType.one2One') }}</a-select-option>
|
<a-select-option value="1">{{ $t('cmdb.ciType.one2One') }}</a-select-option>
|
||||||
@@ -63,6 +64,10 @@
|
|||||||
</a-select>
|
</a-select>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item :label="$t('cmdb.ciType.attributeAssociation')">
|
<a-form-item :label="$t('cmdb.ciType.attributeAssociation')">
|
||||||
|
<template #extra>
|
||||||
|
<div>{{ $t('cmdb.ciType.attributeAssociationTip7') }}</div>
|
||||||
|
<div>{{ $t('cmdb.ciType.attributeAssociationTip8') }}</div>
|
||||||
|
</template>
|
||||||
<a-row
|
<a-row
|
||||||
v-for="item in modalAttrList"
|
v-for="item in modalAttrList"
|
||||||
:key="item.id"
|
:key="item.id"
|
||||||
@@ -74,7 +79,10 @@
|
|||||||
allowClear
|
allowClear
|
||||||
v-model="item.parentAttrId"
|
v-model="item.parentAttrId"
|
||||||
>
|
>
|
||||||
<a-select-option v-for="attr in filterAttributes(modalParentAttributes)" :key="attr.id">
|
<a-select-option
|
||||||
|
v-for="attr in filterAttributes(modalParentAttributes, item.childAttrId, modalChildAttributes, 'parent')"
|
||||||
|
:key="attr.id"
|
||||||
|
>
|
||||||
{{ attr.alias || attr.name }}
|
{{ attr.alias || attr.name }}
|
||||||
</a-select-option>
|
</a-select-option>
|
||||||
</a-select>
|
</a-select>
|
||||||
@@ -90,7 +98,10 @@
|
|||||||
allowClear
|
allowClear
|
||||||
v-model="item.childAttrId"
|
v-model="item.childAttrId"
|
||||||
>
|
>
|
||||||
<a-select-option v-for="attr in filterAttributes(modalChildAttributes)" :key="attr.id">
|
<a-select-option
|
||||||
|
v-for="attr in filterAttributes(modalChildAttributes, item.parentAttrId, modalParentAttributes, 'child')"
|
||||||
|
:key="attr.id"
|
||||||
|
>
|
||||||
{{ attr.alias || attr.name }}
|
{{ attr.alias || attr.name }}
|
||||||
</a-select-option>
|
</a-select-option>
|
||||||
</a-select>
|
</a-select>
|
||||||
@@ -183,7 +194,7 @@ export default {
|
|||||||
'1': this.$t('cmdb.ciType.one2One'),
|
'1': this.$t('cmdb.ciType.one2One'),
|
||||||
'2': this.$t('cmdb.ciType.many2Many'),
|
'2': this.$t('cmdb.ciType.many2Many'),
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
},
|
},
|
||||||
provide() {
|
provide() {
|
||||||
return {
|
return {
|
||||||
@@ -356,15 +367,32 @@ export default {
|
|||||||
this.modalChildAttributes = res?.attributes ?? []
|
this.modalChildAttributes = res?.attributes ?? []
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
filterAttributes(attributes) {
|
|
||||||
// filter password/json/is_list/longText/bool/reference
|
filterAttributes(attributes, relationAttrId, relationAttrs, type) {
|
||||||
return attributes.filter((attr) => {
|
const relationAttr = relationAttrs.find((attr) => attr.id === relationAttrId)
|
||||||
|
|
||||||
|
// filter password/json/longText/bool/reference
|
||||||
|
let filterAttrs = attributes.filter((attr) => {
|
||||||
if (attr.value_type === '2' && !attr.is_index) {
|
if (attr.value_type === '2' && !attr.is_index) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
return !attr.is_password && !attr.is_list && attr.value_type !== '6' && !attr.is_bool && !attr.is_reference
|
return !attr.is_password && attr.value_type !== '6' && !attr.is_bool && !attr.is_reference
|
||||||
})
|
})
|
||||||
|
|
||||||
|
if (relationAttr) {
|
||||||
|
filterAttrs = filterAttrs.filter((attr) => attr.value_type === relationAttr?.value_type)
|
||||||
|
}
|
||||||
|
|
||||||
|
const constraintValue = Number(this.form.getFieldValue('constraint'))
|
||||||
|
if (
|
||||||
|
(constraintValue === 0 && type === 'child') ||
|
||||||
|
constraintValue === 1
|
||||||
|
) {
|
||||||
|
return filterAttrs.filter((attr) => !attr.is_list)
|
||||||
|
}
|
||||||
|
|
||||||
|
return filterAttrs
|
||||||
},
|
},
|
||||||
|
|
||||||
addModalAttr() {
|
addModalAttr() {
|
||||||
@@ -384,6 +412,13 @@ export default {
|
|||||||
if (index !== -1) {
|
if (index !== -1) {
|
||||||
this.modalAttrList.splice(index, 1)
|
this.modalAttrList.splice(index, 1)
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
handleConstraintChange() {
|
||||||
|
this.modalAttrList.forEach((item) => {
|
||||||
|
item.parentAttrId = undefined
|
||||||
|
item.childAttrId = undefined
|
||||||
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@@ -38,7 +38,12 @@
|
|||||||
<vxe-column :width="300" field="attributeAssociation" :edit-render="{}">
|
<vxe-column :width="300" field="attributeAssociation" :edit-render="{}">
|
||||||
<template #header>
|
<template #header>
|
||||||
<span>
|
<span>
|
||||||
<a-tooltip :title="$t('cmdb.ciType.attributeAssociationTip1')">
|
<a-tooltip>
|
||||||
|
<template #title>
|
||||||
|
<div>{{ $t('cmdb.ciType.attributeAssociationTip1') }}</div>
|
||||||
|
<div>{{ $t('cmdb.ciType.attributeAssociationTip7') }}</div>
|
||||||
|
<div>{{ $t('cmdb.ciType.attributeAssociationTip8') }}</div>
|
||||||
|
</template>
|
||||||
<a><a-icon type="question-circle"/></a>
|
<a><a-icon type="question-circle"/></a>
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
{{ $t('cmdb.ciType.attributeAssociation') }}
|
{{ $t('cmdb.ciType.attributeAssociation') }}
|
||||||
@@ -76,7 +81,7 @@
|
|||||||
optionFilterProp="title"
|
optionFilterProp="title"
|
||||||
>
|
>
|
||||||
<a-select-option
|
<a-select-option
|
||||||
v-for="attr in filterAttributes(type2attributes[row.parent_id])"
|
v-for="attr in filterAttributes(row, item.childAttrId, 'parent')"
|
||||||
:key="attr.id"
|
:key="attr.id"
|
||||||
:value="attr.id"
|
:value="attr.id"
|
||||||
:title="attr.alias || attr.name"
|
:title="attr.alias || attr.name"
|
||||||
@@ -95,7 +100,7 @@
|
|||||||
optionFilterProp="title"
|
optionFilterProp="title"
|
||||||
>
|
>
|
||||||
<a-select-option
|
<a-select-option
|
||||||
v-for="attr in filterAttributes(type2attributes[row.child_id])"
|
v-for="attr in filterAttributes(row, item.parentAttrId, 'child')"
|
||||||
:key="attr.id"
|
:key="attr.id"
|
||||||
:value="attr.id"
|
:value="attr.id"
|
||||||
:title="attr.alias || attr.name"
|
:title="attr.alias || attr.name"
|
||||||
@@ -298,15 +303,36 @@ export default {
|
|||||||
const _find = attributes.find((attr) => attr.id === id)
|
const _find = attributes.find((attr) => attr.id === id)
|
||||||
return _find?.alias ?? _find?.name ?? id
|
return _find?.alias ?? _find?.name ?? id
|
||||||
},
|
},
|
||||||
filterAttributes(attributes) {
|
|
||||||
// filter password/json/is_list/longText/bool/reference
|
filterAttributes(row, relationAttrId, type) {
|
||||||
return attributes.filter((attr) => {
|
const { parent_id, child_id, constraint } = row
|
||||||
|
const currentAttrs = this.type2attributes?.[child_id] || []
|
||||||
|
|
||||||
|
const relationAttrs = this.type2attributes?.[parent_id] || []
|
||||||
|
const relationAttr = relationAttrs.find((attr) => attr.id === relationAttrId)
|
||||||
|
|
||||||
|
// filter password/json/longText/bool/reference
|
||||||
|
let filterAttrs = currentAttrs.filter((attr) => {
|
||||||
if (attr.value_type === '2' && !attr.is_index) {
|
if (attr.value_type === '2' && !attr.is_index) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
return !attr.is_password && !attr.is_list && attr.value_type !== '6' && !attr.is_bool && !attr.is_reference
|
return !attr.is_password && attr.value_type !== '6' && !attr.is_bool && !attr.is_reference
|
||||||
})
|
})
|
||||||
|
|
||||||
|
if (relationAttr) {
|
||||||
|
filterAttrs = filterAttrs.filter((attr) => attr.value_type === relationAttr?.value_type)
|
||||||
|
}
|
||||||
|
|
||||||
|
const constraintValue = Number(constraint)
|
||||||
|
if (
|
||||||
|
(constraintValue === 0 && type === 'child') ||
|
||||||
|
constraintValue === 1
|
||||||
|
) {
|
||||||
|
return filterAttrs.filter((attr) => !attr.is_list)
|
||||||
|
}
|
||||||
|
|
||||||
|
return filterAttrs
|
||||||
},
|
},
|
||||||
|
|
||||||
addTableAttr() {
|
addTableAttr() {
|
||||||
|
Reference in New Issue
Block a user