mirror of
https://github.com/veops/cmdb.git
synced 2025-08-09 21:09:46 +08:00
feat(cmdb-ui):citype show attr && service tree search (#479)
This commit is contained in:
@@ -73,3 +73,11 @@ export function deleteCIRelationView(firstCiId, secondCiId, data) {
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function searchCIRelationFull(params) {
|
||||
return axios({
|
||||
url: `/v0.1/ci_relations/search/full`,
|
||||
method: 'GET',
|
||||
params,
|
||||
})
|
||||
}
|
||||
|
@@ -95,12 +95,12 @@
|
||||
isFocusExpression = false
|
||||
}
|
||||
"
|
||||
class="ci-searchform-expression"
|
||||
:class="{ 'ci-searchform-expression': true, 'ci-searchform-expression-has-value': expression }"
|
||||
:style="{ width }"
|
||||
:placeholder="placeholder"
|
||||
@keyup.enter="emitRefresh"
|
||||
>
|
||||
<ops-icon slot="suffix" type="veops-copy" @click="handleCopyExpression" />
|
||||
<a-icon slot="suffix" type="check-circle" @click="handleCopyExpression" />
|
||||
</a-input>
|
||||
<slot></slot>
|
||||
</a-space>
|
||||
@@ -284,6 +284,9 @@ export default {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
.ci-searchform-expression-has-value .ant-input-suffix {
|
||||
color: @func-color_3;
|
||||
}
|
||||
.cmdb-search-form {
|
||||
.ant-form-item-label {
|
||||
overflow: hidden;
|
||||
@@ -294,7 +297,6 @@ export default {
|
||||
</style>
|
||||
|
||||
<style lang="less" scoped>
|
||||
|
||||
.search-form-bar {
|
||||
margin-bottom: 20px;
|
||||
display: flex;
|
||||
|
@@ -194,7 +194,10 @@ const cmdb_en = {
|
||||
attributeAssociationTip3: 'Two Attributes must be selected',
|
||||
attributeAssociationTip4: 'Please select a attribute from Source CIType',
|
||||
attributeAssociationTip5: 'Please select a attribute from Target CIType',
|
||||
|
||||
show: 'show attribute',
|
||||
setAsShow: 'Set as show attribute',
|
||||
cancelSetAsShow: 'Cancel show attribute',
|
||||
showTips: 'The names of nodes in the service tree and topology view'
|
||||
},
|
||||
components: {
|
||||
unselectAttributes: 'Unselected',
|
||||
@@ -530,7 +533,8 @@ if __name__ == "__main__":
|
||||
peopleHasRead: 'Personnel authorized to read:',
|
||||
authorizationPolicy: 'CI Authorization Policy:',
|
||||
idAuthorizationPolicy: 'Authorized by node:',
|
||||
view: 'View permissions'
|
||||
view: 'View permissions',
|
||||
searchTips: 'Search in service tree'
|
||||
},
|
||||
tree: {
|
||||
tips1: 'Please go to Preference page first to complete your subscription!',
|
||||
|
@@ -194,6 +194,10 @@ const cmdb_zh = {
|
||||
attributeAssociationTip3: '属性关联必须选择两个属性',
|
||||
attributeAssociationTip4: '请选择原模型属性',
|
||||
attributeAssociationTip5: '请选择目标模型属性',
|
||||
show: '展示属性',
|
||||
setAsShow: '设置为展示属性',
|
||||
cancelSetAsShow: '取消设置为展示属性',
|
||||
showTips: '服务树和拓扑视图里节点的名称'
|
||||
},
|
||||
components: {
|
||||
unselectAttributes: '未选属性',
|
||||
@@ -529,7 +533,8 @@ if __name__ == "__main__":
|
||||
peopleHasRead: '当前有查看权限的人员:',
|
||||
authorizationPolicy: '实例授权策略:',
|
||||
idAuthorizationPolicy: '按节点授权的:',
|
||||
view: '查看权限'
|
||||
view: '查看权限',
|
||||
searchTips: '在服务树中筛选'
|
||||
},
|
||||
tree: {
|
||||
tips1: '请先到 我的订阅 页面完成订阅!',
|
||||
|
@@ -150,11 +150,11 @@ export default {
|
||||
computed: {
|
||||
topoData() {
|
||||
const ci_types_list = this.ci_types()
|
||||
const unique_id = this.attributes().unique_id
|
||||
const unique_name = this.attributes().unique
|
||||
const _findCiType = ci_types_list.find((item) => item.id === this.typeId)
|
||||
const unique_id = _findCiType.show_id || this.attributes().unique_id
|
||||
const unique_name = _findCiType.show_name || this.attributes().unique
|
||||
const _findUnique = this.attrList().find((attr) => attr.id === unique_id)
|
||||
const unique_alias = _findUnique?.alias || _findUnique?.name || ''
|
||||
const _findCiType = ci_types_list.find((item) => item.id === this.typeId)
|
||||
const nodes = {
|
||||
isRoot: true,
|
||||
id: `Root_${this.typeId}`,
|
||||
@@ -183,6 +183,10 @@ export default {
|
||||
this.parentCITypes.forEach((parent) => {
|
||||
const _findCiType = ci_types_list.find((item) => item.id === parent.id)
|
||||
if (this.firstCIs[parent.name]) {
|
||||
const unique_id = _findCiType.show_id || _findCiType.unique_id
|
||||
const _findUnique = parent.attributes.find((attr) => attr.id === unique_id)
|
||||
const unique_name = _findUnique?.name
|
||||
const unique_alias = _findUnique?.alias || _findUnique?.name || ''
|
||||
this.firstCIs[parent.name].forEach((parentCi) => {
|
||||
nodes.children.push({
|
||||
id: `${parentCi._id}`,
|
||||
@@ -190,9 +194,9 @@ export default {
|
||||
title: parent.alias || parent.name,
|
||||
name: parent.name,
|
||||
side: 'left',
|
||||
unique_alias: parentCi.unique_alias,
|
||||
unique_name: parentCi.unique,
|
||||
unique_value: parentCi[parentCi.unique],
|
||||
unique_alias,
|
||||
unique_name,
|
||||
unique_value: parentCi[unique_name],
|
||||
children: [],
|
||||
icon: _findCiType?.icon || '',
|
||||
endpoints: [
|
||||
@@ -222,6 +226,10 @@ export default {
|
||||
this.childCITypes.forEach((child) => {
|
||||
const _findCiType = ci_types_list.find((item) => item.id === child.id)
|
||||
if (this.secondCIs[child.name]) {
|
||||
const unique_id = _findCiType.show_id || _findCiType.unique_id
|
||||
const _findUnique = child.attributes.find((attr) => attr.id === unique_id)
|
||||
const unique_name = _findUnique?.name
|
||||
const unique_alias = _findUnique?.alias || _findUnique?.name || ''
|
||||
this.secondCIs[child.name].forEach((childCi) => {
|
||||
nodes.children.push({
|
||||
id: `${childCi._id}`,
|
||||
@@ -229,9 +237,9 @@ export default {
|
||||
title: child.alias || child.name,
|
||||
name: child.name,
|
||||
side: 'right',
|
||||
unique_alias: childCi.unique_alias,
|
||||
unique_name: childCi.unique,
|
||||
unique_value: childCi[childCi.unique],
|
||||
unique_alias,
|
||||
unique_name,
|
||||
unique_value: childCi[unique_name],
|
||||
children: [],
|
||||
icon: _findCiType?.icon || '',
|
||||
endpoints: [
|
||||
@@ -333,7 +341,6 @@ export default {
|
||||
secondCIs[item.ci_type] = [item]
|
||||
}
|
||||
})
|
||||
console.log(_.cloneDeep(secondCIs))
|
||||
this.secondCIs = secondCIs
|
||||
})
|
||||
.catch((e) => {})
|
||||
|
@@ -15,7 +15,7 @@
|
||||
position: absolute;
|
||||
background: #fff;
|
||||
border: 1px solid #d9d9d9;
|
||||
border-radius: 10px;
|
||||
border-radius: 2px;
|
||||
padding: 4px 8px;
|
||||
width: 100px;
|
||||
text-align: center;
|
||||
@@ -74,13 +74,11 @@
|
||||
}
|
||||
.root {
|
||||
width: 100px;
|
||||
background: #2f54eb;
|
||||
border: none;
|
||||
border-radius: 5px;
|
||||
font-weight: 500;
|
||||
border-color: @primary-color;
|
||||
font-weight: 700;
|
||||
padding: 4px 8px;
|
||||
.title {
|
||||
color: #fff;
|
||||
color: @primary-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -10,6 +10,7 @@
|
||||
import _ from 'lodash'
|
||||
import { TreeCanvas } from 'butterfly-dag'
|
||||
import { searchCIRelation } from '@/modules/cmdb/api/CIRelation'
|
||||
import { getCITypeAttributesById } from '@/modules/cmdb/api/CITypeAttr'
|
||||
import Node from './node.js'
|
||||
|
||||
import 'butterfly-dag/dist/index.css'
|
||||
@@ -87,7 +88,7 @@ export default {
|
||||
this.canvas.focusCenterWithAnimate()
|
||||
})
|
||||
},
|
||||
redrawData(res, sourceNode, side) {
|
||||
async redrawData(res, sourceNode, side) {
|
||||
const newNodes = []
|
||||
const newEdges = []
|
||||
if (!res.result.length) {
|
||||
@@ -95,18 +96,24 @@ export default {
|
||||
return
|
||||
}
|
||||
const ci_types_list = this.ci_types()
|
||||
res.result.forEach((r) => {
|
||||
for (let i = 0; i < res.result.length; i++) {
|
||||
const r = res.result[i]
|
||||
if (!this.exsited_ci.includes(r._id)) {
|
||||
const _findCiType = ci_types_list.find((item) => item.id === r._type)
|
||||
const { attributes } = await getCITypeAttributesById(_findCiType.id)
|
||||
const unique_id = _findCiType.show_id || _findCiType.unique_id
|
||||
const _findUnique = attributes.find((attr) => attr.id === unique_id)
|
||||
const unique_name = _findUnique?.name
|
||||
const unique_alias = _findUnique?.alias || _findUnique?.name || ''
|
||||
newNodes.push({
|
||||
id: `${r._id}`,
|
||||
Class: Node,
|
||||
title: r.ci_type_alias || r.ci_type,
|
||||
name: r.ci_type,
|
||||
side: side,
|
||||
unique_alias: r.unique_alias,
|
||||
unique_name: r.unique,
|
||||
unique_value: r[r.unique],
|
||||
unique_alias,
|
||||
unique_name,
|
||||
unique_value: r[unique_name],
|
||||
children: [],
|
||||
icon: _findCiType?.icon || '',
|
||||
endpoints: [
|
||||
@@ -131,7 +138,8 @@ export default {
|
||||
targetNode: side === 'right' ? `${r._id}` : sourceNode,
|
||||
type: 'endpoint',
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
const { nodes, edges } = this.canvas.getDataMap()
|
||||
// 删除原节点和边
|
||||
this.canvas.removeNodes(nodes.map((node) => node.id))
|
||||
|
@@ -10,6 +10,7 @@
|
||||
:class="{ 'attribute-card': true, 'attribute-card-add': isAdd, 'attribute-card-inherited': inherited }"
|
||||
>
|
||||
<div class="attribute-card-uniqueKey" v-if="isUnique">{{ $t('cmdb.ciType.uniqueKey') }}</div>
|
||||
<div class="attribute-card-uniqueKey" v-if="isShowId">{{ $t('cmdb.ciType.show') }}</div>
|
||||
<template v-if="!isAdd">
|
||||
<a-tooltip :title="inherited ? $t('cmdb.ciType.inheritFrom', { name: property.inherited_from }) : ''">
|
||||
<div class="attribute-card-content">
|
||||
@@ -27,6 +28,7 @@
|
||||
<div
|
||||
class="attribute-card-trigger"
|
||||
v-if="(property.value_type === '3' || property.value_type === '4') && !isStore"
|
||||
:style="{ top: isShowId ? '18px' : '' }"
|
||||
>
|
||||
<a @click="openTrigger"><ops-icon type="ops-trigger"/></a>
|
||||
</div>
|
||||
@@ -64,12 +66,24 @@
|
||||
</a-space>
|
||||
</a-popover>
|
||||
|
||||
<a-space class="attribute-card-operation" v-if="!inherited">
|
||||
<a v-if="!isStore"><a-icon type="edit" @click="handleEdit"/></a>
|
||||
<a-tooltip :title="$t('cmdb.ciType.computeForAllCITips')">
|
||||
<a v-if="!isStore && property.is_computed"><a-icon type="redo" @click="handleCalcComputed"/></a>
|
||||
<a-space class="attribute-card-operation">
|
||||
<a v-if="!isStore && !inherited"><a-icon type="edit" @click="handleEdit"/></a>
|
||||
<a-tooltip
|
||||
v-if="
|
||||
!isStore &&
|
||||
!isUnique &&
|
||||
!['6'].includes(property.value_type) &&
|
||||
!property.is_password &&
|
||||
!property.is_list
|
||||
"
|
||||
:title="$t(isShowId ? 'cmdb.ciType.cancelSetAsShow' : 'cmdb.ciType.setAsShow')"
|
||||
>
|
||||
<a><ops-icon type="veops-show" @click="setAsShow"/></a>
|
||||
</a-tooltip>
|
||||
<a v-if="!isUnique" style="color:red;"><a-icon type="delete" @click="handleDelete"/></a>
|
||||
<a-tooltip v-if="!isStore && property.is_computed" :title="$t('cmdb.ciType.computeForAllCITips')">
|
||||
<a><a-icon type="redo" @click="handleCalcComputed"/></a>
|
||||
</a-tooltip>
|
||||
<a v-if="!isUnique && !inherited" style="color:red;"><a-icon type="delete" @click="handleDelete"/></a>
|
||||
</a-space>
|
||||
</div>
|
||||
<TriggerForm ref="triggerForm" :CITypeId="CITypeId" />
|
||||
@@ -84,17 +98,9 @@
|
||||
<script>
|
||||
import { deleteCITypeAttributesById, deleteAttributesById, calcComputedAttribute } from '@/modules/cmdb/api/CITypeAttr'
|
||||
import ValueTypeIcon from '@/components/CMDBValueTypeMapIcon'
|
||||
import {
|
||||
ops_default_show,
|
||||
ops_is_choice,
|
||||
ops_is_index,
|
||||
ops_is_link,
|
||||
ops_is_password,
|
||||
ops_is_sortable,
|
||||
ops_is_unique,
|
||||
} from '@/core/icons'
|
||||
import { valueTypeMap } from '../../utils/const'
|
||||
import TriggerForm from './triggerForm.vue'
|
||||
import { updateCIType } from '@/modules/cmdb/api/CIType'
|
||||
export default {
|
||||
name: 'AttributeCard',
|
||||
inject: {
|
||||
@@ -102,17 +108,14 @@ export default {
|
||||
from: 'unique',
|
||||
default: () => undefined,
|
||||
},
|
||||
show_id: {
|
||||
from: 'show_id',
|
||||
default: () => undefined,
|
||||
},
|
||||
},
|
||||
components: {
|
||||
ValueTypeIcon,
|
||||
TriggerForm,
|
||||
ops_default_show,
|
||||
ops_is_choice,
|
||||
ops_is_index,
|
||||
ops_is_link,
|
||||
ops_is_password,
|
||||
ops_is_sortable,
|
||||
ops_is_unique,
|
||||
},
|
||||
props: {
|
||||
property: {
|
||||
@@ -146,6 +149,12 @@ export default {
|
||||
}
|
||||
return false
|
||||
},
|
||||
isShowId() {
|
||||
if (this.show_id) {
|
||||
return this.property?.id === this.show_id()
|
||||
}
|
||||
return false
|
||||
},
|
||||
valueTypeMap() {
|
||||
return valueTypeMap()
|
||||
},
|
||||
@@ -217,6 +226,11 @@ export default {
|
||||
},
|
||||
})
|
||||
},
|
||||
setAsShow() {
|
||||
updateCIType(this.CITypeId, { show_id: this.isShowId ? null : this.property?.id }).then((res) => {
|
||||
this.$emit('ok')
|
||||
})
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
@@ -186,6 +186,7 @@ import {
|
||||
createCITypeGroupById,
|
||||
updateCITypeGroupById,
|
||||
getTriggerList,
|
||||
getCIType,
|
||||
} from '@/modules/cmdb/api/CIType'
|
||||
import {
|
||||
getCITypeAttributesById,
|
||||
@@ -231,6 +232,7 @@ export default {
|
||||
newGroupName: '',
|
||||
attrTypeFilter: [],
|
||||
unique: '',
|
||||
show_id: null,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@@ -250,20 +252,31 @@ export default {
|
||||
unique: () => {
|
||||
return this.unique
|
||||
},
|
||||
show_id: () => {
|
||||
return this.show_id
|
||||
},
|
||||
}
|
||||
},
|
||||
beforeCreate() {},
|
||||
created() {},
|
||||
mounted() {
|
||||
this.getCITypeGroupData()
|
||||
this.init()
|
||||
},
|
||||
methods: {
|
||||
getPropertyIcon,
|
||||
init() {
|
||||
getCIType(this.CITypeId).then((res) => {
|
||||
if (res?.ci_types && res.ci_types.length) {
|
||||
this.show_id = res.ci_types[0]?.show_id ?? null
|
||||
}
|
||||
})
|
||||
this.getCITypeGroupData()
|
||||
},
|
||||
handleEditProperty(property) {
|
||||
this.$refs.attributeEditForm.handleEdit(property, this.attributes)
|
||||
},
|
||||
handleOk() {
|
||||
this.getCITypeGroupData()
|
||||
this.init()
|
||||
},
|
||||
setOtherGroupAttributes() {
|
||||
const orderMap = this.attributes.reduce(function(map, obj) {
|
||||
@@ -591,7 +604,6 @@ export default {
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
|
||||
.fold {
|
||||
width: calc(100% - 216px);
|
||||
display: inline-block;
|
||||
|
@@ -53,11 +53,10 @@
|
||||
</a-menu-item>
|
||||
<a-menu-item key="1">
|
||||
<a-space>
|
||||
<a
|
||||
href="/api/v0.1/ci_types/template/export/file"
|
||||
><a-icon type="download" /> {{ $t('download') }}</a
|
||||
>
|
||||
</a-space>
|
||||
<a href="/api/v0.1/ci_types/template/export/file">
|
||||
<a-icon type="download" /> {{ $t('download') }}
|
||||
</a></a-space
|
||||
>
|
||||
</a-menu-item>
|
||||
</a-menu>
|
||||
</a-dropdown>
|
||||
@@ -262,6 +261,7 @@
|
||||
'default_order_attr',
|
||||
{ rules: [{ required: false, message: $t('cmdb.ciType.selectDefaultOrderAttr') }] },
|
||||
]"
|
||||
:placeholder="$t('placeholder2')"
|
||||
>
|
||||
<el-option
|
||||
:key="item.name"
|
||||
@@ -299,6 +299,7 @@
|
||||
filterInput = ''
|
||||
}
|
||||
"
|
||||
@change="handleChangeUnique"
|
||||
>
|
||||
<el-option
|
||||
:key="item.id"
|
||||
@@ -313,6 +314,40 @@
|
||||
<a-divider type="vertical" />
|
||||
<a @click="handleCreatNewAttr">{{ $t('cmdb.ciType.notfound') }}</a>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
:help="$t('cmdb.ciType.showTips')"
|
||||
:label="$t('cmdb.ciType.show')"
|
||||
v-if="drawerTitle === $t('cmdb.ciType.editCIType')"
|
||||
>
|
||||
<el-select
|
||||
size="small"
|
||||
filterable
|
||||
clearable
|
||||
name="show_id"
|
||||
:filter-method="
|
||||
(input) => {
|
||||
showIdFilterInput = input
|
||||
}
|
||||
"
|
||||
v-decorator="['show_id', { rules: [{ required: false }] }]"
|
||||
:placeholder="$t('placeholder2')"
|
||||
@visible-change="
|
||||
() => {
|
||||
showIdFilterInput = ''
|
||||
}
|
||||
"
|
||||
>
|
||||
<el-option
|
||||
:key="item.id"
|
||||
:value="item.id"
|
||||
v-for="item in showIdSelectOptions"
|
||||
:label="item.alias || item.name"
|
||||
>
|
||||
<span> {{ item.alias || item.name }}</span>
|
||||
<span :title="item.name" style="font-size: 10px; color: #afafaf"> {{ item.name }}</span>
|
||||
</el-option>
|
||||
</el-select>
|
||||
</a-form-item>
|
||||
<div v-if="newAttrAreaVisible" :style="{ padding: '15px 8px 0 8px', backgroundColor: '#fafafa' }">
|
||||
<create-new-attribute
|
||||
ref="createNewAttribute"
|
||||
@@ -418,14 +453,17 @@ export default {
|
||||
addId: null,
|
||||
|
||||
filterInput: '',
|
||||
showIdFilterInput: '',
|
||||
|
||||
orderSelectionOptions: [],
|
||||
currentTypeAttrs: [],
|
||||
default_order_asc: '1',
|
||||
|
||||
allTreeDepAndEmp: [],
|
||||
|
||||
editCiType: null,
|
||||
isInherit: false,
|
||||
|
||||
unique_id: null,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@@ -482,6 +520,22 @@ export default {
|
||||
}
|
||||
return _attributes
|
||||
},
|
||||
orderSelectionOptions() {
|
||||
return this.currentTypeAttrs.filter((item) => item.is_required)
|
||||
},
|
||||
showIdSelectOptions() {
|
||||
const _showIdSelectOptions = this.currentTypeAttrs.filter(
|
||||
(item) => item.id !== this.unique_id && !['6'].includes(item.value_type) && !item.is_password && !item.is_list
|
||||
)
|
||||
if (this.showIdFilterInput) {
|
||||
return _showIdSelectOptions.filter(
|
||||
(item) =>
|
||||
item.name.toLowerCase().includes(this.showIdFilterInput.toLowerCase()) ||
|
||||
item.alias.toLowerCase().includes(this.showIdFilterInput.toLowerCase())
|
||||
)
|
||||
}
|
||||
return _showIdSelectOptions
|
||||
},
|
||||
},
|
||||
provide() {
|
||||
return {
|
||||
@@ -659,6 +713,7 @@ export default {
|
||||
delete values.parent_ids
|
||||
await this.updateCIType(values.id, {
|
||||
...values,
|
||||
show_id: values.show_id || null,
|
||||
icon,
|
||||
})
|
||||
} else {
|
||||
@@ -864,7 +919,8 @@ export default {
|
||||
this.drawerTitle = this.$t('cmdb.ciType.editCIType')
|
||||
this.drawerVisible = true
|
||||
await getCITypeAttributesById(record.id).then((res) => {
|
||||
this.orderSelectionOptions = res.attributes.filter((item) => item.is_required)
|
||||
this.currentTypeAttrs = res.attributes
|
||||
this.unique_id = res.unique_id
|
||||
})
|
||||
await getCIType(record.id).then((res) => {
|
||||
const ci_type = res.ci_types[0]
|
||||
@@ -877,6 +933,9 @@ export default {
|
||||
})
|
||||
})
|
||||
}
|
||||
this.form.setFieldsValue({
|
||||
show_id: ci_type.show_id ?? null,
|
||||
})
|
||||
})
|
||||
this.$nextTick(() => {
|
||||
this.default_order_asc = record.default_order_attr && record.default_order_attr.startsWith('-') ? '2' : '1'
|
||||
@@ -941,12 +1000,18 @@ export default {
|
||||
this.$message.error({ content: this.$t('cmdb.ciType.uploadFailed'), key, duration: 2 })
|
||||
}
|
||||
},
|
||||
handleChangeUnique(value) {
|
||||
this.unique_id = value
|
||||
const show_id = this.form.getFieldValue('show_id')
|
||||
if (show_id === value) {
|
||||
this.form.setFieldsValue({ show_id: '' })
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
|
||||
.ci-types-wrap {
|
||||
margin: 0 0 -24px 0;
|
||||
.ci-types-empty {
|
||||
|
@@ -11,6 +11,14 @@
|
||||
<template #one>
|
||||
<div class="relation-views-left" :style="{ height: `${windowHeight - 115}px` }">
|
||||
<div class="relation-views-left-header" :title="$route.meta.name">{{ $route.meta.name }}</div>
|
||||
<a-input
|
||||
:placeholder="$t('cmdb.serviceTree.searchTips')"
|
||||
class="relation-views-left-input"
|
||||
@pressEnter="handleSearchFull"
|
||||
v-model="fullSearchValue"
|
||||
>
|
||||
<a-icon slot="prefix" type="search" />
|
||||
</a-input>
|
||||
<div
|
||||
class="ops-list-batch-action"
|
||||
:style="{ marginBottom: '10px' }"
|
||||
@@ -47,6 +55,7 @@
|
||||
<span>{{ $t('selectRows', { rows: batchTreeKey.length }) }}</span>
|
||||
</div>
|
||||
<a-tree
|
||||
v-if="!isFullSearch"
|
||||
:selectedKeys="selectedKeys"
|
||||
:loadData="onLoadData"
|
||||
:treeData="treeData"
|
||||
@@ -55,13 +64,10 @@
|
||||
@drop="onDrop"
|
||||
:expandedKeys="expandedKeys"
|
||||
>
|
||||
<template #title="{ key: treeKey, title,number, isLeaf }">
|
||||
<template #title="treeNodeData">
|
||||
<ContextMenu
|
||||
:title="title"
|
||||
:number="number"
|
||||
:treeKey="treeKey"
|
||||
:treeNodeData="treeNodeData"
|
||||
:levels="levels"
|
||||
:isLeaf="isLeaf"
|
||||
:currentViews="relationViews.views[viewName]"
|
||||
:id2type="relationViews.id2type"
|
||||
@onContextMenuClick="onContextMenuClick"
|
||||
@@ -74,6 +80,30 @@
|
||||
/>
|
||||
</template>
|
||||
</a-tree>
|
||||
<a-tree
|
||||
v-else
|
||||
:treeData="filterFullTreeData"
|
||||
defaultExpandAll
|
||||
:selectedKeys="selectedKeys"
|
||||
:expandedKeys="expandedKeys"
|
||||
>
|
||||
<template #title="treeNodeData">
|
||||
<ContextMenu
|
||||
:treeNodeData="treeNodeData"
|
||||
:levels="levels"
|
||||
:currentViews="relationViews.views[viewName]"
|
||||
:id2type="relationViews.id2type"
|
||||
@onContextMenuClick="onContextMenuClick"
|
||||
@onNodeClick="onNodeClick"
|
||||
:ciTypeIcons="ciTypeIcons"
|
||||
:showBatchLevel="showBatchLevel"
|
||||
:batchTreeKey="batchTreeKey"
|
||||
@clickCheckbox="clickCheckbox"
|
||||
@updateTreeData="updateTreeData"
|
||||
:fullSearchValue="fullSearchValue"
|
||||
/>
|
||||
</template>
|
||||
</a-tree>
|
||||
</div>
|
||||
</template>
|
||||
<template #two>
|
||||
@@ -342,7 +372,6 @@
|
||||
total,
|
||||
})
|
||||
"
|
||||
:style="{ alignSelf: 'flex-end', marginRight: '12px' }"
|
||||
>
|
||||
<template slot="buildOptionText" slot-scope="props">
|
||||
<span v-if="props.value !== '100000'">{{ props.value }}{{ $t('cmdb.history.itemsPerPage') }}</span>
|
||||
@@ -392,6 +421,7 @@ import {
|
||||
batchDeleteCIRelation,
|
||||
batchUpdateCIRelationChildren,
|
||||
addCIRelationView,
|
||||
searchCIRelationFull,
|
||||
} from '@/modules/cmdb/api/CIRelation'
|
||||
|
||||
import { getCITypeAttributesById } from '@/modules/cmdb/api/CITypeAttr'
|
||||
@@ -489,9 +519,13 @@ export default {
|
||||
|
||||
statisticsObj: {},
|
||||
viewOption: {},
|
||||
loadRootStatisticsParams: {},
|
||||
fullSearchValue: '',
|
||||
isFullSearch: false,
|
||||
fullTreeData: [],
|
||||
filterFullTreeData: [],
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
windowHeight() {
|
||||
return this.$store.state.windowHeight
|
||||
@@ -500,9 +534,6 @@ export default {
|
||||
return this.windowHeight - 244
|
||||
},
|
||||
selectedKeys() {
|
||||
if (this.treeKeys.length <= 1) {
|
||||
return this.treeKeys.map((item) => `@^@${item}`)
|
||||
}
|
||||
return [this.treeKeys.join('@^@')]
|
||||
},
|
||||
isLeaf() {
|
||||
@@ -576,7 +607,7 @@ export default {
|
||||
this.reload()
|
||||
},
|
||||
pageNo: function(newPage, oldPage) {
|
||||
this.loadData({ pageNo: newPage }, undefined, this.sortByTable)
|
||||
this.loadData({ params: { pageNo: newPage }, refreshType: undefined, sortByTable: this.sortByTable })
|
||||
},
|
||||
},
|
||||
|
||||
@@ -604,7 +635,7 @@ export default {
|
||||
this.loadData()
|
||||
},
|
||||
|
||||
async loadData(parameter, refreshType = undefined, sortByTable = undefined) {
|
||||
async loadData({ parameter, refreshType = undefined, sortByTable = undefined } = {}) {
|
||||
// refreshType='refreshNumber' 树图只更新number
|
||||
const params = Object.assign(parameter || {}, (this.$refs.search || {}).queryParam)
|
||||
let q = ''
|
||||
@@ -624,8 +655,6 @@ export default {
|
||||
|
||||
const exp = expression.match(regQ) ? expression.match(regQ)[0] : null
|
||||
if (exp) {
|
||||
// exp = exp.replace(/(\:)/g, '$1*')
|
||||
// exp = exp.replace(/(\,)/g, '*$1')
|
||||
q = `${q},${exp}`
|
||||
}
|
||||
|
||||
@@ -656,38 +685,9 @@ export default {
|
||||
}
|
||||
|
||||
if (this.treeKeys.length === 0) {
|
||||
// await this.judgeCITypes(q)
|
||||
if (!refreshType) {
|
||||
if (!refreshType && !this.isFullSearch) {
|
||||
await this.loadRoot()
|
||||
}
|
||||
|
||||
// const fuzzySearch = (this.$refs['search'] || {}).fuzzySearch || ''
|
||||
// if (fuzzySearch) {
|
||||
// q = `q=_type:${this.currentTypeId[0]},*${fuzzySearch}*,` + q
|
||||
// } else {
|
||||
// q = `q=_type:${this.currentTypeId[0]},` + q
|
||||
// }
|
||||
// if (this.currentTypeId[0] && this.treeData && this.treeData.length) {
|
||||
// // default select first node
|
||||
// this.onNodeClick(this.treeData[0].key)
|
||||
// const res = await searchCI2(q)
|
||||
// const root_id = this.treeData.map((item) => item.id).join(',')
|
||||
// q += `&root_id=${root_id}`
|
||||
|
||||
// this.pageNo = res.page
|
||||
// this.numfound = res.numfound
|
||||
// res.result.forEach((item, index) => (item.key = item._id))
|
||||
// const jsonAttrList = this.preferenceAttrList.filter((attr) => attr.value_type === '6')
|
||||
// console.log(jsonAttrList)
|
||||
// this.instanceList = res['result'].map((item) => {
|
||||
// jsonAttrList.forEach(
|
||||
// (jsonAttr) => (item[jsonAttr.name] = item[jsonAttr.name] ? JSON.stringify(item[jsonAttr.name]) : '')
|
||||
// )
|
||||
// return { ..._.cloneDeep(item) }
|
||||
// })
|
||||
// this.initialInstanceList = _.cloneDeep(this.instanceList)
|
||||
// this.calcColumns()
|
||||
// }
|
||||
} else {
|
||||
q += `&root_id=${this.treeKeys[this.treeKeys.length - 1].split('%')[0]}`
|
||||
|
||||
@@ -726,7 +726,7 @@ export default {
|
||||
}
|
||||
|
||||
q += `&level=${this.topo_flatten.includes(this.currentTypeId[0]) ? 1 : level.join(',')}`
|
||||
if (!refreshType) {
|
||||
if (!refreshType && !this.isFullSearch) {
|
||||
this.loadNoRoot(this.treeKeys[this.treeKeys.length - 1], level)
|
||||
}
|
||||
const fuzzySearch = (this.$refs['search'] || {}).fuzzySearch || ''
|
||||
@@ -812,9 +812,6 @@ export default {
|
||||
this.selectedRowKeys = []
|
||||
this.currentTypeId = [typeId]
|
||||
this.loadColumns()
|
||||
// this.$nextTick(() => {
|
||||
// this.refreshTable()
|
||||
// })
|
||||
},
|
||||
|
||||
async judgeCITypes() {
|
||||
@@ -854,64 +851,6 @@ export default {
|
||||
this.currentTypeId = [this.showTypeIds[0]]
|
||||
await this.loadColumns()
|
||||
}
|
||||
// const showTypeIds = []
|
||||
// let _showTypes = []
|
||||
// let _showTypeIds = []
|
||||
|
||||
// if (this.treeKeys.length) {
|
||||
// const typeId = parseInt(this.treeKeys[this.treeKeys.length - 1].split('%')[1])
|
||||
|
||||
// _showTypes = this.node2ShowTypes[typeId + '']
|
||||
// _showTypes.forEach((item) => {
|
||||
// _showTypeIds.push(item.id)
|
||||
// })
|
||||
// } else {
|
||||
// _showTypeIds = JSON.parse(JSON.stringify(this.origShowTypeIds))
|
||||
// _showTypes = JSON.parse(JSON.stringify(this.origShowTypes))
|
||||
// }
|
||||
// const promises = _showTypeIds.map((typeId) => {
|
||||
// let _q = (`q=_type:${typeId},` + q).replace(/count=\d*/, 'count=1')
|
||||
// if (Object.values(this.level2constraint).includes('2')) {
|
||||
// _q = _q + `&has_m2m=1`
|
||||
// }
|
||||
// if (this.root_parent_path) {
|
||||
// _q = _q + `&root_parent_path=${this.root_parent_path}`
|
||||
// }
|
||||
// // if (this.treeKeys.length === 0) {
|
||||
// // return searchCI2(_q).then((res) => {
|
||||
// // if (res.numfound !== 0) {
|
||||
// // showTypeIds.push(typeId)
|
||||
// // }
|
||||
// // })
|
||||
// // } else {
|
||||
// _q = _q + `&descendant_ids=${this.descendant_ids}`
|
||||
// return searchCIRelation(_q).then((res) => {
|
||||
// if (res.numfound !== 0) {
|
||||
// showTypeIds.push(typeId)
|
||||
// }
|
||||
// })
|
||||
// // }
|
||||
// })
|
||||
// await Promise.all(promises).then(async () => {
|
||||
// if (showTypeIds.length && showTypeIds.sort().join(',') !== this.showTypeIds.sort().join(',')) {
|
||||
// const showTypes = []
|
||||
// _showTypes.forEach((item) => {
|
||||
// if (showTypeIds.includes(item.id)) {
|
||||
// showTypes.push(item)
|
||||
// }
|
||||
// })
|
||||
// console.log(showTypes)
|
||||
// this.showTypes = showTypes
|
||||
// this.showTypeIds = showTypeIds
|
||||
// if (
|
||||
// !this.currentTypeId.length ||
|
||||
// (this.currentTypeId.length && !this.showTypeIds.includes(this.currentTypeId[0]))
|
||||
// ) {
|
||||
// this.currentTypeId = [this.showTypeIds[0]]
|
||||
// await this.loadColumns()
|
||||
// }
|
||||
// }
|
||||
// })
|
||||
},
|
||||
|
||||
async loadRoot() {
|
||||
@@ -919,29 +858,41 @@ export default {
|
||||
const facet = []
|
||||
const ciIds = []
|
||||
res.result.forEach((item) => {
|
||||
facet.push([item[item.unique], 0, item._id, item._type, item.unique])
|
||||
const showName = this.relationViews.id2type[item._type]?.show_name ?? null
|
||||
facet.push({
|
||||
showName,
|
||||
showNameValue: item[showName] ?? null,
|
||||
uniqueValue: item[item.unique],
|
||||
number: 0,
|
||||
ciId: item._id,
|
||||
typeId: item._type,
|
||||
unique: item.unique,
|
||||
})
|
||||
ciIds.push(item._id)
|
||||
})
|
||||
const promises = this.leaf.map((leafId) => {
|
||||
let level = 0
|
||||
this.levels.forEach((item, idx) => {
|
||||
if (item.includes(leafId)) {
|
||||
level = idx + 1
|
||||
}
|
||||
})
|
||||
return statisticsCIRelation({
|
||||
root_ids: ciIds.join(','),
|
||||
level: level,
|
||||
type_ids: this.leaf2showTypes[this.leaf[0]].join(','),
|
||||
has_m2m: Number(Object.values(this.level2constraint).includes('2')),
|
||||
descendant_ids: this.descendant_ids_for_statistics,
|
||||
}).then((num) => {
|
||||
facet.forEach((item, idx) => {
|
||||
item[1] += num[ciIds[idx] + '']
|
||||
})
|
||||
|
||||
const leafId = this.leaf[0]
|
||||
let level = 0
|
||||
this.levels.forEach((item, idx) => {
|
||||
if (item.includes(leafId)) {
|
||||
level = idx + 1
|
||||
}
|
||||
})
|
||||
const params = {
|
||||
level,
|
||||
root_ids: ciIds.join(','),
|
||||
has_m2m: Number(Object.values(this.level2constraint).includes('2')),
|
||||
}
|
||||
this.loadRootStatisticsParams = params
|
||||
await statisticsCIRelation({
|
||||
...params,
|
||||
type_ids: this.leaf2showTypes[this.leaf[0]].join(','),
|
||||
descendant_ids: this.descendant_ids_for_statistics,
|
||||
}).then((num) => {
|
||||
facet.forEach((item, idx) => {
|
||||
item.number += num[ciIds[idx] + '']
|
||||
})
|
||||
})
|
||||
await Promise.all(promises)
|
||||
this.wrapTreeData(facet)
|
||||
// default select first node
|
||||
this.onNodeClick(this.treeData[0].key)
|
||||
@@ -976,7 +927,16 @@ export default {
|
||||
const facet = []
|
||||
const ciIds = []
|
||||
res.result.forEach((item) => {
|
||||
facet.push([item[item.unique], 0, item._id, item._type, item.unique])
|
||||
const showName = this.relationViews.id2type[item._type]?.show_name ?? null
|
||||
facet.push({
|
||||
showName,
|
||||
showNameValue: item[showName] ?? null,
|
||||
uniqueValue: item[item.unique],
|
||||
number: 0,
|
||||
ciId: item._id,
|
||||
typeId: item._type,
|
||||
unique: item.unique,
|
||||
})
|
||||
ciIds.push(item._id)
|
||||
})
|
||||
let ancestor_ids
|
||||
@@ -998,7 +958,7 @@ export default {
|
||||
descendant_ids: this.descendant_ids_for_statistics,
|
||||
}).then((num) => {
|
||||
facet.forEach((item, idx) => {
|
||||
item[1] += num[ciIds[idx] + '']
|
||||
item.number += num[ciIds[idx] + '']
|
||||
})
|
||||
})
|
||||
}
|
||||
@@ -1009,7 +969,7 @@ export default {
|
||||
}
|
||||
},
|
||||
|
||||
onNodeClick(keys) {
|
||||
onNodeClick(keys, callback = undefined) {
|
||||
this.triggerSelect = true
|
||||
if (keys) {
|
||||
const _tempKeys = keys.split('@^@').filter((item) => item !== '')
|
||||
@@ -1028,19 +988,25 @@ export default {
|
||||
}
|
||||
|
||||
this.refreshTable()
|
||||
if (callback && typeof callback === 'function') {
|
||||
callback()
|
||||
}
|
||||
},
|
||||
wrapTreeData(facet) {
|
||||
if (this.triggerSelect) {
|
||||
return
|
||||
}
|
||||
const treeData = []
|
||||
const _treeKeys = _.cloneDeep(this.treeKeys)
|
||||
facet.forEach((item) => {
|
||||
_treeKeys.push(item.ciId + '%' + item.typeId + '%' + `{"${item.unique}":"${item.uniqueValue}"}`)
|
||||
treeData.push({
|
||||
title: item[0],
|
||||
number: item[1],
|
||||
key: this.treeKeys.join('@^@') + '@^@' + item[2] + '%' + item[3] + '%' + `{"${item[4]}":"${item[0]}"}`,
|
||||
isLeaf: this.leaf.includes(item[3]),
|
||||
id: item[2],
|
||||
title: item.showName ? item.showNameValue : item.uniqueValue,
|
||||
number: item.number,
|
||||
key: _treeKeys.join('@^@'),
|
||||
isLeaf: this.leaf.includes(item.typeId),
|
||||
id: item.ciId,
|
||||
showName: item.showName,
|
||||
})
|
||||
})
|
||||
if (this.treeNode === null) {
|
||||
@@ -1060,7 +1026,6 @@ export default {
|
||||
}
|
||||
this.treeKeys = treeNode.eventKey.split('@^@').filter((item) => item !== '')
|
||||
this.treeNode = treeNode
|
||||
// this.refreshTable()
|
||||
resolve()
|
||||
})
|
||||
},
|
||||
@@ -1228,7 +1193,7 @@ export default {
|
||||
that.$refs.xTable.clearCheckboxRow()
|
||||
that.$refs.xTable.clearCheckboxReserve()
|
||||
that.selectedRowKeys = []
|
||||
that.loadData({}, 'refreshNumber')
|
||||
that.loadData({ params: {}, refreshType: 'refreshNumber' })
|
||||
})
|
||||
},
|
||||
})
|
||||
@@ -1241,9 +1206,7 @@ export default {
|
||||
const _splitTargetKey = targetKey.split('@^@').filter((item) => item !== '')
|
||||
if (_splitDragKey.length - 1 === _splitTargetKey.length) {
|
||||
const dragId = _splitDragKey[_splitDragKey.length - 1].split('%')[0]
|
||||
// const targetObj = JSON.parse(_splitTargetKey[_splitTargetKey.length - 1].split('%')[2])
|
||||
const targetId = _splitTargetKey[_splitTargetKey.length - 1].split('%')[0]
|
||||
// TODO 拖拽这里不造咋弄 等等再说吧
|
||||
batchUpdateCIRelationChildren([dragId], [targetId]).then((res) => {
|
||||
this.reload()
|
||||
})
|
||||
@@ -1278,7 +1241,7 @@ export default {
|
||||
this.sortByTable = sortByTable
|
||||
this.$nextTick(() => {
|
||||
if (this.pageNo === 1) {
|
||||
this.loadData({}, undefined, sortByTable)
|
||||
this.loadData({ params: {}, refreshType: undefined, sortByTable })
|
||||
} else {
|
||||
this.pageNo = 1
|
||||
}
|
||||
@@ -1437,7 +1400,7 @@ export default {
|
||||
onOk() {
|
||||
deleteCI(record.ci_id || record._id).then((res) => {
|
||||
that.$message.success(that.$t('deleteSuccess'))
|
||||
that.loadData({}, 'refreshNumber')
|
||||
that.loadData({ params: {}, refreshType: 'refreshNumber' })
|
||||
})
|
||||
},
|
||||
})
|
||||
@@ -1457,7 +1420,7 @@ export default {
|
||||
}
|
||||
addCIRelationView(first_ci_id, ci_id, { ancestor_ids }).then((res) => {
|
||||
setTimeout(() => {
|
||||
this.loadData({}, 'refreshNumber')
|
||||
this.loadData({ params: {}, refreshType: 'refreshNumber' })
|
||||
}, 500)
|
||||
})
|
||||
},
|
||||
@@ -1495,7 +1458,7 @@ export default {
|
||||
.finally(() => {
|
||||
that.loading = false
|
||||
setTimeout(() => {
|
||||
that.loadData({})
|
||||
that.loadData({ params: {} })
|
||||
}, 800)
|
||||
})
|
||||
},
|
||||
@@ -1558,7 +1521,7 @@ export default {
|
||||
that.selectedRowKeys = []
|
||||
that.$refs.xTable.clearCheckboxRow()
|
||||
that.$refs.xTable.clearCheckboxReserve()
|
||||
that.loadData({}, 'refreshNumber')
|
||||
that.loadData({ params: {}, refreshType: 'refreshNumber' })
|
||||
})
|
||||
},
|
||||
})
|
||||
@@ -1568,7 +1531,6 @@ export default {
|
||||
},
|
||||
jsonEditorOk(row, column, jsonData) {
|
||||
// 后端写数据有快慢,不拉接口直接修改table的数据
|
||||
// this.reloadData()
|
||||
this.instanceList.forEach((item) => {
|
||||
if (item._id === row._id) {
|
||||
item[column.property] = JSON.stringify(jsonData)
|
||||
@@ -1577,7 +1539,7 @@ export default {
|
||||
this.$refs.xTable.refreshColumn()
|
||||
},
|
||||
relationViewRefreshNumber() {
|
||||
this.loadData({}, 'refreshNumber')
|
||||
this.loadData({ params: {}, refreshType: 'refreshNumber' })
|
||||
},
|
||||
onShowSizeChange(current, pageSize) {
|
||||
this.pageSize = pageSize
|
||||
@@ -1754,11 +1716,9 @@ export default {
|
||||
return node[i]
|
||||
}
|
||||
if (node[i].children && node[i].children.length) {
|
||||
for (let i = 0; i < node[i].children.length; i++) {
|
||||
const found = this.findNode(node[i].children, target)
|
||||
if (found) {
|
||||
return found
|
||||
}
|
||||
const found = this.findNode(node[i].children, target)
|
||||
if (found) {
|
||||
return found
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1771,6 +1731,79 @@ export default {
|
||||
}
|
||||
this.refreshTable()
|
||||
},
|
||||
handleSearchFull(e) {
|
||||
const value = e.target.value
|
||||
this.treeKeys = []
|
||||
this.expandedKeys = []
|
||||
if (!value) {
|
||||
this.reload()
|
||||
return
|
||||
}
|
||||
if (this.isFullSearch) {
|
||||
this.calcFilterFullTreeData()
|
||||
return
|
||||
}
|
||||
searchCIRelationFull({
|
||||
...this.loadRootStatisticsParams,
|
||||
type_ids: this.topo_flatten.join(','),
|
||||
}).then((res) => {
|
||||
this.isFullSearch = true
|
||||
this.fullTreeData = this.formatTreeData(res)
|
||||
this.calcFilterFullTreeData()
|
||||
})
|
||||
},
|
||||
calcFilterFullTreeData() {
|
||||
const _expandedKeys = []
|
||||
const predicateCiIds = []
|
||||
const filterTree = (node, predicate) => {
|
||||
if (predicate(node)) {
|
||||
predicateCiIds.push(node.id)
|
||||
return true
|
||||
}
|
||||
if (node.children) {
|
||||
node.children = node.children.filter((child) => {
|
||||
if (predicateCiIds.some((id) => child.key.includes(String(id)))) {
|
||||
return true
|
||||
}
|
||||
return filterTree(child, predicate)
|
||||
})
|
||||
if (node.children.length && !predicateCiIds.some((id) => node.key.includes(String(id)))) {
|
||||
_expandedKeys.push(node.key)
|
||||
}
|
||||
return node.children.length > 0
|
||||
}
|
||||
return false
|
||||
}
|
||||
const predicate = (node) =>
|
||||
String(node.title)
|
||||
.toLowerCase()
|
||||
.includes(this.fullSearchValue.toLowerCase())
|
||||
const _fullTreeData = _.cloneDeep(this.fullTreeData)
|
||||
this.filterFullTreeData = _fullTreeData.filter((item) => filterTree(item, predicate))
|
||||
if (this.filterFullTreeData && this.filterFullTreeData.length) {
|
||||
this.onNodeClick(this.filterFullTreeData[0].key, () => {
|
||||
this.expandedKeys = _expandedKeys
|
||||
})
|
||||
} else {
|
||||
this.treeKeys = []
|
||||
this.instanceList = []
|
||||
}
|
||||
},
|
||||
formatTreeData(array, parentKey = '') {
|
||||
array.forEach((item) => {
|
||||
const showName = this.relationViews.id2type[item.type_id]?.show_name ?? null
|
||||
const uniqueName = this.relationViews.id2type[item.type_id]?.unique_name ?? null
|
||||
const keyList = parentKey.split('@^@').filter((item) => !!item)
|
||||
keyList.push(item.id + '%' + item.type_id + '%' + `{"${uniqueName}":"${item.uniqueValue}"}`)
|
||||
const key = keyList.join('@^@')
|
||||
item.key = key
|
||||
item.showName = showName
|
||||
if (!item.isLeaf && item.children && item.children.length) {
|
||||
item.children = this.formatTreeData(item.children, key)
|
||||
}
|
||||
})
|
||||
return array
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
@@ -1819,6 +1852,18 @@ export default {
|
||||
padding: 0 6px;
|
||||
}
|
||||
}
|
||||
.relation-views-left-input {
|
||||
margin-bottom: 12px;
|
||||
input {
|
||||
background-color: transparent;
|
||||
border-top: none;
|
||||
border-right: none;
|
||||
border-left: none;
|
||||
}
|
||||
.ant-input:focus {
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
.relation-views-right {
|
||||
width: 100%;
|
||||
|
@@ -27,7 +27,13 @@
|
||||
/>
|
||||
<span class="relation-views-node-icon" v-else>{{ icon ? icon[0].toUpperCase() : 'i' }}</span>
|
||||
</template>
|
||||
<span class="relation-views-node-title" v-if="!isEditNodeName" :title="title">{{ title }}</span>
|
||||
<span
|
||||
class="relation-views-node-title"
|
||||
v-if="!isEditNodeName"
|
||||
:title="title"
|
||||
v-highlight="{ value: fullSearchValue, class: 'relation-views-node-title-highlight' }"
|
||||
>{{ title }}
|
||||
</span>
|
||||
<a-input
|
||||
ref="input"
|
||||
@blur="changeNodeName"
|
||||
@@ -67,10 +73,7 @@
|
||||
key="editNodeName"
|
||||
><ops-icon type="icon-xianxing-edit" />{{ $t('cmdb.serviceTree.editNodeName') }}</a-menu-item
|
||||
>
|
||||
<a-menu-item
|
||||
key="batch"
|
||||
><ops-icon type="veops-copy" />{{ $t('cmdb.serviceTree.batch') }}</a-menu-item
|
||||
>
|
||||
<a-menu-item key="batch"><ops-icon type="veops-copy" />{{ $t('cmdb.serviceTree.batch') }}</a-menu-item>
|
||||
</template>
|
||||
<template v-else>
|
||||
<a-menu-item
|
||||
@@ -103,20 +106,17 @@
|
||||
|
||||
<script>
|
||||
import { updateCI } from '../../../api/ci.js'
|
||||
import highlight from '@/directive/highlight'
|
||||
|
||||
export default {
|
||||
name: 'ContextMenu',
|
||||
directives: {
|
||||
highlight,
|
||||
},
|
||||
props: {
|
||||
title: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
number: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
treeKey: {
|
||||
type: String,
|
||||
default: '',
|
||||
treeNodeData: {
|
||||
type: Object,
|
||||
default: () => {},
|
||||
},
|
||||
levels: {
|
||||
type: Array,
|
||||
@@ -130,10 +130,6 @@ export default {
|
||||
type: Object,
|
||||
default: () => {},
|
||||
},
|
||||
isLeaf: {
|
||||
type: Boolean,
|
||||
default: () => false,
|
||||
},
|
||||
ciTypeIcons: {
|
||||
type: Object,
|
||||
default: () => {},
|
||||
@@ -146,6 +142,10 @@ export default {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
fullSearchValue: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
@@ -201,6 +201,21 @@ export default {
|
||||
showCheckbox() {
|
||||
return this.showBatchLevel === this.treeKey.split('@^@').filter((item) => !!item).length - 1
|
||||
},
|
||||
title() {
|
||||
return this.treeNodeData.title
|
||||
},
|
||||
number() {
|
||||
return this.treeNodeData.number
|
||||
},
|
||||
treeKey() {
|
||||
return this.treeNodeData.key
|
||||
},
|
||||
isLeaf() {
|
||||
return this.treeNodeData.isLeaf
|
||||
},
|
||||
showName() {
|
||||
return this.treeNodeData.showName
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
onContextMenuClick(treeKey, menuKey) {
|
||||
@@ -230,8 +245,11 @@ export default {
|
||||
.split('%')
|
||||
const unique = Object.keys(JSON.parse(ci[2]))[0]
|
||||
const ciId = Number(ci[0])
|
||||
|
||||
updateCI(ciId, { [unique]: value }).then((res) => {
|
||||
let editAttrName = unique
|
||||
if (this.showName) {
|
||||
editAttrName = this.showName
|
||||
}
|
||||
updateCI(ciId, { [editAttrName]: value }).then((res) => {
|
||||
this.$message.success(this.$t('updateSuccess'))
|
||||
this.$emit('updateTreeData', ciId, value)
|
||||
})
|
||||
@@ -244,7 +262,6 @@ export default {
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
|
||||
.relation-views-node {
|
||||
width: 100%;
|
||||
display: inline-flex;
|
||||
@@ -313,6 +330,9 @@ export default {
|
||||
</style>
|
||||
|
||||
<style lang="less">
|
||||
.relation-views-node-title-highlight {
|
||||
color: @func-color_1;
|
||||
}
|
||||
.relation-views-left {
|
||||
ul:has(.relation-views-node-checkbox) > li > ul {
|
||||
margin-left: 26px;
|
||||
|
Reference in New Issue
Block a user