mirror of
				https://github.com/veops/cmdb.git
				synced 2025-11-04 13:46:17 +08:00 
			
		
		
		
	Merge pull request #594 from veops/dev_ui_240820
feat(ui): add bool and reference type
This commit is contained in:
		@@ -54,6 +54,12 @@
 | 
			
		||||
      <div class="content unicode" style="display: block;">
 | 
			
		||||
          <ul class="icon_lists dib-box">
 | 
			
		||||
          
 | 
			
		||||
            <li class="dib">
 | 
			
		||||
              <span class="icon iconfont"></span>
 | 
			
		||||
                <div class="name">duose-changwenben (1)</div>
 | 
			
		||||
                <div class="code-name">&#xe997;</div>
 | 
			
		||||
              </li>
 | 
			
		||||
          
 | 
			
		||||
            <li class="dib">
 | 
			
		||||
              <span class="icon iconfont"></span>
 | 
			
		||||
                <div class="name">duose-quote</div>
 | 
			
		||||
@@ -5508,9 +5514,9 @@
 | 
			
		||||
<pre><code class="language-css"
 | 
			
		||||
>@font-face {
 | 
			
		||||
  font-family: 'iconfont';
 | 
			
		||||
  src: url('iconfont.woff2?t=1723012344599') format('woff2'),
 | 
			
		||||
       url('iconfont.woff?t=1723012344599') format('woff'),
 | 
			
		||||
       url('iconfont.ttf?t=1723012344599') format('truetype');
 | 
			
		||||
  src: url('iconfont.woff2?t=1724135954264') format('woff2'),
 | 
			
		||||
       url('iconfont.woff?t=1724135954264') format('woff'),
 | 
			
		||||
       url('iconfont.ttf?t=1724135954264') format('truetype');
 | 
			
		||||
}
 | 
			
		||||
</code></pre>
 | 
			
		||||
          <h3 id="-iconfont-">第二步:定义使用 iconfont 的样式</h3>
 | 
			
		||||
@@ -5536,6 +5542,15 @@
 | 
			
		||||
      <div class="content font-class">
 | 
			
		||||
        <ul class="icon_lists dib-box">
 | 
			
		||||
          
 | 
			
		||||
          <li class="dib">
 | 
			
		||||
            <span class="icon iconfont duose-changwenben1"></span>
 | 
			
		||||
            <div class="name">
 | 
			
		||||
              duose-changwenben (1)
 | 
			
		||||
            </div>
 | 
			
		||||
            <div class="code-name">.duose-changwenben1
 | 
			
		||||
            </div>
 | 
			
		||||
          </li>
 | 
			
		||||
          
 | 
			
		||||
          <li class="dib">
 | 
			
		||||
            <span class="icon iconfont duose-quote"></span>
 | 
			
		||||
            <div class="name">
 | 
			
		||||
@@ -13717,6 +13732,14 @@
 | 
			
		||||
      <div class="content symbol">
 | 
			
		||||
          <ul class="icon_lists dib-box">
 | 
			
		||||
          
 | 
			
		||||
            <li class="dib">
 | 
			
		||||
                <svg class="icon svg-icon" aria-hidden="true">
 | 
			
		||||
                  <use xlink:href="#duose-changwenben1"></use>
 | 
			
		||||
                </svg>
 | 
			
		||||
                <div class="name">duose-changwenben (1)</div>
 | 
			
		||||
                <div class="code-name">#duose-changwenben1</div>
 | 
			
		||||
            </li>
 | 
			
		||||
          
 | 
			
		||||
            <li class="dib">
 | 
			
		||||
                <svg class="icon svg-icon" aria-hidden="true">
 | 
			
		||||
                  <use xlink:href="#duose-quote"></use>
 | 
			
		||||
 
 | 
			
		||||
@@ -1,8 +1,8 @@
 | 
			
		||||
@font-face {
 | 
			
		||||
  font-family: "iconfont"; /* Project id 3857903 */
 | 
			
		||||
  src: url('iconfont.woff2?t=1723012344599') format('woff2'),
 | 
			
		||||
       url('iconfont.woff?t=1723012344599') format('woff'),
 | 
			
		||||
       url('iconfont.ttf?t=1723012344599') format('truetype');
 | 
			
		||||
  src: url('iconfont.woff2?t=1724135954264') format('woff2'),
 | 
			
		||||
       url('iconfont.woff?t=1724135954264') format('woff'),
 | 
			
		||||
       url('iconfont.ttf?t=1724135954264') format('truetype');
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.iconfont {
 | 
			
		||||
@@ -13,6 +13,10 @@
 | 
			
		||||
  -moz-osx-font-smoothing: grayscale;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.duose-changwenben1:before {
 | 
			
		||||
  content: "\e997";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.duose-quote:before {
 | 
			
		||||
  content: "\e995";
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							@@ -5,6 +5,13 @@
 | 
			
		||||
  "css_prefix_text": "",
 | 
			
		||||
  "description": "",
 | 
			
		||||
  "glyphs": [
 | 
			
		||||
    {
 | 
			
		||||
      "icon_id": "41437322",
 | 
			
		||||
      "name": "duose-changwenben (1)",
 | 
			
		||||
      "font_class": "duose-changwenben1",
 | 
			
		||||
      "unicode": "e997",
 | 
			
		||||
      "unicode_decimal": 59799
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "icon_id": "41363381",
 | 
			
		||||
      "name": "duose-quote",
 | 
			
		||||
 
 | 
			
		||||
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										18
									
								
								cmdb-ui/src/api/cmdb.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								cmdb-ui/src/api/cmdb.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,18 @@
 | 
			
		||||
import { axios } from '@/utils/request'
 | 
			
		||||
 | 
			
		||||
export function searchCI(params, isShowMessage = true) {
 | 
			
		||||
  return axios({
 | 
			
		||||
    url: `/v0.1/ci/s`,
 | 
			
		||||
    method: 'GET',
 | 
			
		||||
    params: params,
 | 
			
		||||
    isShowMessage
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function getCIType(CITypeName, parameter) {
 | 
			
		||||
  return axios({
 | 
			
		||||
    url: `/v0.1/ci_types/${CITypeName}`,
 | 
			
		||||
    method: 'GET',
 | 
			
		||||
    params: parameter
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
@@ -85,6 +85,29 @@
 | 
			
		||||
        :disabled="disabled"
 | 
			
		||||
      >
 | 
			
		||||
      </treeselect>
 | 
			
		||||
      <CIReferenceAttr
 | 
			
		||||
        v-if="getAttr(item.property).is_reference && (item.exp === 'is' || item.exp === '~is')"
 | 
			
		||||
        :style="{ width: '175px' }"
 | 
			
		||||
        class="select-filter-component"
 | 
			
		||||
        :referenceTypeId="getAttr(item.property).reference_type_id"
 | 
			
		||||
        :disabled="disabled"
 | 
			
		||||
        v-model="item.value"
 | 
			
		||||
      />
 | 
			
		||||
      <a-select
 | 
			
		||||
        v-else-if="getAttr(item.property).is_bool && (item.exp === 'is' || item.exp === '~is')"
 | 
			
		||||
        v-model="item.value"
 | 
			
		||||
        class="select-filter-component"
 | 
			
		||||
        :style="{ width: '175px' }"
 | 
			
		||||
        :disabled="disabled"
 | 
			
		||||
        :placeholder="$t('placeholder2')"
 | 
			
		||||
      >
 | 
			
		||||
        <a-select-option key="1">
 | 
			
		||||
          true
 | 
			
		||||
        </a-select-option>
 | 
			
		||||
        <a-select-option key="0">
 | 
			
		||||
          false
 | 
			
		||||
        </a-select-option>
 | 
			
		||||
      </a-select>
 | 
			
		||||
      <treeselect
 | 
			
		||||
        class="custom-treeselect"
 | 
			
		||||
        :style="{ width: '175px', '--custom-height': '24px' }"
 | 
			
		||||
@@ -92,7 +115,7 @@
 | 
			
		||||
        :multiple="false"
 | 
			
		||||
        :clearable="false"
 | 
			
		||||
        searchable
 | 
			
		||||
        v-if="isChoiceByProperty(item.property) && (item.exp === 'is' || item.exp === '~is')"
 | 
			
		||||
        v-else-if="isChoiceByProperty(item.property) && (item.exp === 'is' || item.exp === '~is')"
 | 
			
		||||
        :options="getChoiceValueByProperty(item.property)"
 | 
			
		||||
        :placeholder="$t('placeholder2')"
 | 
			
		||||
        :normalizer="
 | 
			
		||||
@@ -199,10 +222,11 @@ import _ from 'lodash'
 | 
			
		||||
import { v4 as uuidv4 } from 'uuid'
 | 
			
		||||
import { ruleTypeList, expList, advancedExpList, compareTypeList } from './constants'
 | 
			
		||||
import ValueTypeMapIcon from '../CMDBValueTypeMapIcon'
 | 
			
		||||
import CIReferenceAttr from '../ciReferenceAttr/index.vue'
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  name: 'Expression',
 | 
			
		||||
  components: { ValueTypeMapIcon },
 | 
			
		||||
  components: { ValueTypeMapIcon, CIReferenceAttr },
 | 
			
		||||
  model: {
 | 
			
		||||
    prop: 'value',
 | 
			
		||||
    event: 'change',
 | 
			
		||||
@@ -255,7 +279,7 @@ export default {
 | 
			
		||||
    getExpListByProperty(property) {
 | 
			
		||||
      if (property) {
 | 
			
		||||
        const _find = this.canSearchPreferenceAttrList.find((item) => item.name === property)
 | 
			
		||||
        if (_find && ['0', '1', '3', '4', '5'].includes(_find.value_type)) {
 | 
			
		||||
        if (_find && (['0', '1', '3', '4', '5'].includes(_find.value_type) || _find.is_reference || _find.is_bool)) {
 | 
			
		||||
          return [
 | 
			
		||||
            { value: 'is', label: this.$t('cmdbFilterComp.is') },
 | 
			
		||||
            { value: '~is', label: this.$t('cmdbFilterComp.~is') },
 | 
			
		||||
@@ -315,6 +339,9 @@ export default {
 | 
			
		||||
      }
 | 
			
		||||
      return []
 | 
			
		||||
    },
 | 
			
		||||
    getAttr(property) {
 | 
			
		||||
      return this.canSearchPreferenceAttrList.find((item) => item.name === property) || {}
 | 
			
		||||
    },
 | 
			
		||||
    handleChangeExp({ value }, item, index) {
 | 
			
		||||
      const _ruleList = _.cloneDeep(this.ruleList)
 | 
			
		||||
      if (value === 'range') {
 | 
			
		||||
@@ -343,4 +370,20 @@ export default {
 | 
			
		||||
}
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<style></style>
 | 
			
		||||
<style lang="less" scoped>
 | 
			
		||||
.select-filter-component {
 | 
			
		||||
  height: 24px;
 | 
			
		||||
 | 
			
		||||
  /deep/ .ant-select-selection {
 | 
			
		||||
    height: 24px;
 | 
			
		||||
    background: #f7f8fa;
 | 
			
		||||
    line-height: 24px;
 | 
			
		||||
    border: none;
 | 
			
		||||
 | 
			
		||||
    .ant-select-selection__rendered {
 | 
			
		||||
      height: 24px;
 | 
			
		||||
      line-height: 24px;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
 
 | 
			
		||||
@@ -15,18 +15,38 @@ export default {
 | 
			
		||||
  },
 | 
			
		||||
  methods: {
 | 
			
		||||
    getPropertyIcon(attr) {
 | 
			
		||||
      switch (attr.value_type) {
 | 
			
		||||
      let valueType = attr.value_type
 | 
			
		||||
 | 
			
		||||
      if (valueType === '2') {
 | 
			
		||||
        if (attr.is_password) {
 | 
			
		||||
          valueType = '7'
 | 
			
		||||
        } else if (attr.is_link) {
 | 
			
		||||
          valueType = '8'
 | 
			
		||||
        } else if (!attr.is_index) {
 | 
			
		||||
          valueType = '9'
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      if (
 | 
			
		||||
        valueType === '7' &&
 | 
			
		||||
        attr.is_bool
 | 
			
		||||
      ) {
 | 
			
		||||
        valueType = '10'
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      if (
 | 
			
		||||
        valueType === '0' &&
 | 
			
		||||
        attr.is_reference
 | 
			
		||||
      ) {
 | 
			
		||||
        valueType = '11'
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      switch (valueType) {
 | 
			
		||||
        case '0':
 | 
			
		||||
          return 'duose-shishu'
 | 
			
		||||
        case '1':
 | 
			
		||||
          return 'duose-fudianshu'
 | 
			
		||||
        case '2':
 | 
			
		||||
          if (attr.is_password) {
 | 
			
		||||
            return 'duose-password'
 | 
			
		||||
          }
 | 
			
		||||
          if (attr.is_link) {
 | 
			
		||||
            return 'duose-link'
 | 
			
		||||
          }
 | 
			
		||||
          return 'duose-wenben'
 | 
			
		||||
        case '3':
 | 
			
		||||
          return 'duose-datetime'
 | 
			
		||||
@@ -40,6 +60,14 @@ export default {
 | 
			
		||||
          return 'duose-password'
 | 
			
		||||
        case '8':
 | 
			
		||||
          return 'duose-link'
 | 
			
		||||
        case '9':
 | 
			
		||||
          return 'duose-changwenben1'
 | 
			
		||||
        case '10':
 | 
			
		||||
          return 'duose-boole'
 | 
			
		||||
        case '11':
 | 
			
		||||
          return 'duose-quote'
 | 
			
		||||
        default:
 | 
			
		||||
          return ''
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
  },
 | 
			
		||||
 
 | 
			
		||||
@@ -61,7 +61,13 @@
 | 
			
		||||
        </template>
 | 
			
		||||
      </div>
 | 
			
		||||
    </div>
 | 
			
		||||
    <a-input ref="regInput" :placeholder="$t('regexSelect.placeholder')" :value="current.label" @change="changeLabel">
 | 
			
		||||
    <a-input
 | 
			
		||||
      ref="regInput"
 | 
			
		||||
      :placeholder="$t('regexSelect.placeholder')"
 | 
			
		||||
      :value="current.label"
 | 
			
		||||
      :disabled="disabled"
 | 
			
		||||
      @change="changeLabel"
 | 
			
		||||
    >
 | 
			
		||||
    </a-input>
 | 
			
		||||
  </a-popover>
 | 
			
		||||
</template>
 | 
			
		||||
@@ -88,6 +94,10 @@ export default {
 | 
			
		||||
      type: Array,
 | 
			
		||||
      default: () => [],
 | 
			
		||||
    },
 | 
			
		||||
    disabled: {
 | 
			
		||||
      type: Boolean,
 | 
			
		||||
      default: false,
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  data() {
 | 
			
		||||
    return {
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										178
									
								
								cmdb-ui/src/components/ciReferenceAttr/index.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										178
									
								
								cmdb-ui/src/components/ciReferenceAttr/index.vue
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,178 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <div class="reference-attr-select-wrap">
 | 
			
		||||
    <a-select
 | 
			
		||||
      v-bind="$attrs"
 | 
			
		||||
      v-model="selectCIIds"
 | 
			
		||||
      optionFilterProp="title"
 | 
			
		||||
      :mode="isList ? 'multiple' : 'default'"
 | 
			
		||||
      showSearch
 | 
			
		||||
      allowClear
 | 
			
		||||
      :getPopupContainer="(trigger) => trigger.parentElement"
 | 
			
		||||
      class="reference-attr-select"
 | 
			
		||||
      :maxTagCount="2"
 | 
			
		||||
      @dropdownVisibleChange="handleDropdownVisibleChange"
 | 
			
		||||
      @search="handleSearch"
 | 
			
		||||
      @change="handleChange"
 | 
			
		||||
    >
 | 
			
		||||
      <template v-if="!isInit">
 | 
			
		||||
        <a-select-option
 | 
			
		||||
          v-for="(item) in initSelectOption"
 | 
			
		||||
          :key="item.key"
 | 
			
		||||
          :title="item.title"
 | 
			
		||||
        >
 | 
			
		||||
          {{ item.title }}
 | 
			
		||||
        </a-select-option>
 | 
			
		||||
      </template>
 | 
			
		||||
      <a-select-option
 | 
			
		||||
        v-for="(item) in options"
 | 
			
		||||
        :key="item.key"
 | 
			
		||||
        :title="item.title"
 | 
			
		||||
      >
 | 
			
		||||
        {{ item.title }}
 | 
			
		||||
      </a-select-option>
 | 
			
		||||
    </a-select>
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
import _ from 'lodash'
 | 
			
		||||
import debounce from 'lodash/debounce'
 | 
			
		||||
import { searchCI, getCIType } from '@/api/cmdb'
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  name: 'CIReferenceAttr',
 | 
			
		||||
  props: {
 | 
			
		||||
    value: {
 | 
			
		||||
      type: [Number, String, Array],
 | 
			
		||||
      default: () => '',
 | 
			
		||||
    },
 | 
			
		||||
    isList: {
 | 
			
		||||
      type: Boolean,
 | 
			
		||||
      default: false,
 | 
			
		||||
    },
 | 
			
		||||
    referenceShowAttrName: {
 | 
			
		||||
      type: String,
 | 
			
		||||
      default: ''
 | 
			
		||||
    },
 | 
			
		||||
    referenceTypeId: {
 | 
			
		||||
      type: [String, Number],
 | 
			
		||||
      default: ''
 | 
			
		||||
    },
 | 
			
		||||
    initSelectOption: {
 | 
			
		||||
      type: Array,
 | 
			
		||||
      default: () => []
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  model: {
 | 
			
		||||
    prop: 'value',
 | 
			
		||||
    event: 'change',
 | 
			
		||||
  },
 | 
			
		||||
  data() {
 | 
			
		||||
    return {
 | 
			
		||||
      isInit: false,
 | 
			
		||||
      options: [],
 | 
			
		||||
      innerReferenceShowAttrName: ''
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  watch: {
 | 
			
		||||
    referenceTypeId: {
 | 
			
		||||
      immediate: true,
 | 
			
		||||
      deep: true,
 | 
			
		||||
      handler() {
 | 
			
		||||
        this.isInit = false
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  computed: {
 | 
			
		||||
    selectCIIds: {
 | 
			
		||||
      get() {
 | 
			
		||||
        if (this.isList) {
 | 
			
		||||
          return this.value || []
 | 
			
		||||
        } else {
 | 
			
		||||
          return this.value ? Number(this.value) : ''
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      set(val) {
 | 
			
		||||
        this.$emit('change', val ?? (this.isList ? [] : null))
 | 
			
		||||
        return val
 | 
			
		||||
      },
 | 
			
		||||
    },
 | 
			
		||||
  },
 | 
			
		||||
  methods: {
 | 
			
		||||
    async handleDropdownVisibleChange(open) {
 | 
			
		||||
      if (!this.isInit && open && this.referenceTypeId) {
 | 
			
		||||
        this.isInit = true
 | 
			
		||||
 | 
			
		||||
        if (!this.referenceShowAttrName) {
 | 
			
		||||
          const res = await getCIType(this.referenceTypeId)
 | 
			
		||||
          const ciType = res?.ci_types?.[0]
 | 
			
		||||
          this.innerReferenceShowAttrName = ciType?.show_name || ciType?.unique_name || ''
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const attrName = this.referenceShowAttrName || this.innerReferenceShowAttrName || ''
 | 
			
		||||
        if (!attrName) {
 | 
			
		||||
          return
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const res = await searchCI({
 | 
			
		||||
          q: `_type:${this.referenceTypeId}`,
 | 
			
		||||
          fl: attrName,
 | 
			
		||||
          count: 25,
 | 
			
		||||
        })
 | 
			
		||||
 | 
			
		||||
        let options = res?.result?.map((item) => {
 | 
			
		||||
          return {
 | 
			
		||||
            key: item._id,
 | 
			
		||||
            title: String(item?.[attrName] ?? '')
 | 
			
		||||
          }
 | 
			
		||||
        })
 | 
			
		||||
 | 
			
		||||
        options = _.uniqBy([...this.initSelectOption, ...options], 'key')
 | 
			
		||||
 | 
			
		||||
        this.options = options
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    handleSearch: debounce(async function(v) {
 | 
			
		||||
      const attrName = this.referenceShowAttrName || this.innerReferenceShowAttrName || ''
 | 
			
		||||
 | 
			
		||||
      if (!attrName || !this.referenceTypeId) {
 | 
			
		||||
        return
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      const res = await searchCI({
 | 
			
		||||
        q: `_type:${this.referenceTypeId}${v ? ',*' + v + '*' : ''}`,
 | 
			
		||||
        fl: attrName,
 | 
			
		||||
        count: v ? 100 : 25,
 | 
			
		||||
      })
 | 
			
		||||
 | 
			
		||||
      this.options = res?.result?.map((item) => {
 | 
			
		||||
        return {
 | 
			
		||||
          key: item._id,
 | 
			
		||||
          title: String(item?.[attrName] ?? '')
 | 
			
		||||
        }
 | 
			
		||||
      })
 | 
			
		||||
    }, 300),
 | 
			
		||||
 | 
			
		||||
    handleChange(v) {
 | 
			
		||||
      if (Array.isArray(v) ? !v.length : !v) {
 | 
			
		||||
        this.handleSearch()
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<style lang="less" scoped>
 | 
			
		||||
.reference-attr-select-wrap {
 | 
			
		||||
  width: 100%;
 | 
			
		||||
 | 
			
		||||
  .reference-attr-select {
 | 
			
		||||
    width: 100%;
 | 
			
		||||
 | 
			
		||||
    /deep/ .ant-select-dropdown {
 | 
			
		||||
      z-index: 15;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
@@ -8,6 +8,7 @@
 | 
			
		||||
      resizable
 | 
			
		||||
      ref="xTable"
 | 
			
		||||
      size="small"
 | 
			
		||||
      :data="data"
 | 
			
		||||
      :loading="loading"
 | 
			
		||||
      :row-config="{ useKey: true, keyField: '_id' }"
 | 
			
		||||
      show-header-overflow
 | 
			
		||||
@@ -56,8 +57,20 @@
 | 
			
		||||
            <span>{{ col.title }}</span>
 | 
			
		||||
          </span>
 | 
			
		||||
        </template>
 | 
			
		||||
        <template v-if="col.is_choice || col.is_password" #edit="{ row }">
 | 
			
		||||
          <vxe-input v-if="col.is_password" v-model="passwordValue[col.field]" />
 | 
			
		||||
        <template v-if="col.is_choice || col.is_password || col.is_bool || col.is_reference" #edit="{ row }">
 | 
			
		||||
          <CIReferenceAttr
 | 
			
		||||
            v-if="col.is_reference"
 | 
			
		||||
            :referenceTypeId="col.reference_type_id"
 | 
			
		||||
            :isList="col.is_list"
 | 
			
		||||
            :referenceShowAttrName="referenceShowAttrNameMap[col.reference_type_id] || ''"
 | 
			
		||||
            :initSelectOption="getInitReferenceSelectOption(row[col.field], col)"
 | 
			
		||||
            v-model="row[col.field]"
 | 
			
		||||
          />
 | 
			
		||||
          <a-switch
 | 
			
		||||
            v-else-if="col.is_bool"
 | 
			
		||||
            v-model="row[col.field]"
 | 
			
		||||
          />
 | 
			
		||||
          <vxe-input v-else-if="col.is_password" v-model="passwordValue[col.field]" />
 | 
			
		||||
          <a-select
 | 
			
		||||
            v-if="col.is_choice"
 | 
			
		||||
            v-model="row[col.field]"
 | 
			
		||||
@@ -100,10 +113,20 @@
 | 
			
		||||
          </a-select>
 | 
			
		||||
        </template>
 | 
			
		||||
        <template
 | 
			
		||||
          v-if="col.value_type === '6' || col.is_link || col.is_password || col.is_choice"
 | 
			
		||||
          v-if="col.value_type === '6' || col.is_link || col.is_password || col.is_choice || col.is_reference"
 | 
			
		||||
          #default="{ row }"
 | 
			
		||||
        >
 | 
			
		||||
          <span v-if="col.value_type === '6' && row[col.field]">{{ row[col.field] }}</span>
 | 
			
		||||
          <template v-if="col.is_reference" >
 | 
			
		||||
            <a
 | 
			
		||||
              v-for="(ciId) in (col.is_list ? row[col.field] : [row[col.field]])"
 | 
			
		||||
              :key="ciId"
 | 
			
		||||
              :href="`/cmdb/cidetail/${col.reference_type_id}/${ciId}`"
 | 
			
		||||
              target="_blank"
 | 
			
		||||
            >
 | 
			
		||||
              {{ getReferenceAttrValue(ciId, col) }}
 | 
			
		||||
            </a>
 | 
			
		||||
          </template>
 | 
			
		||||
          <span v-else-if="col.value_type === '6' && row[col.field]">{{ row[col.field] }}</span>
 | 
			
		||||
          <template v-else-if="col.is_link && row[col.field]">
 | 
			
		||||
            <a
 | 
			
		||||
              v-for="(item, linkIndex) in (col.is_list ? row[col.field] : [row[col.field]])"
 | 
			
		||||
@@ -187,16 +210,21 @@
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
import _ from 'lodash'
 | 
			
		||||
import { getCITypes } from '@/modules/cmdb/api/CIType'
 | 
			
		||||
import { searchCI } from '@/modules/cmdb/api/ci'
 | 
			
		||||
import JsonEditor from '../JsonEditor/jsonEditor.vue'
 | 
			
		||||
import PasswordField from '../passwordField/index.vue'
 | 
			
		||||
import { ops_move_icon as OpsMoveIcon } from '@/core/icons'
 | 
			
		||||
import CIReferenceAttr from '@/components/ciReferenceAttr/index.vue'
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  name: 'CITable',
 | 
			
		||||
  components: {
 | 
			
		||||
    JsonEditor,
 | 
			
		||||
    PasswordField,
 | 
			
		||||
    OpsMoveIcon
 | 
			
		||||
    OpsMoveIcon,
 | 
			
		||||
    CIReferenceAttr
 | 
			
		||||
  },
 | 
			
		||||
  props: {
 | 
			
		||||
    // table ID
 | 
			
		||||
@@ -237,6 +265,18 @@ export default {
 | 
			
		||||
    showDelete: {
 | 
			
		||||
      type: Boolean,
 | 
			
		||||
      default: true
 | 
			
		||||
    },
 | 
			
		||||
    // 表格数据
 | 
			
		||||
    data: {
 | 
			
		||||
      type: Array,
 | 
			
		||||
      default: () => []
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  data() {
 | 
			
		||||
    return {
 | 
			
		||||
      referenceShowAttrNameMap: {},
 | 
			
		||||
      referenceCIIdMap: {},
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
@@ -245,6 +285,46 @@ export default {
 | 
			
		||||
      const idx = this.columns.findIndex((item) => item.is_fixed)
 | 
			
		||||
      return idx > -1
 | 
			
		||||
    },
 | 
			
		||||
    tableDataWatch() {
 | 
			
		||||
      return {
 | 
			
		||||
        data: this.data,
 | 
			
		||||
        columns: this.columns
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    referenceCIIdWatch() {
 | 
			
		||||
      const referenceTypeCol = this.columns?.filter((col) => col?.is_reference && col?.reference_type_id) || []
 | 
			
		||||
      if (!this.data?.length || !referenceTypeCol?.length) {
 | 
			
		||||
        return []
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      const ids = []
 | 
			
		||||
      this.data.forEach((row) => {
 | 
			
		||||
        referenceTypeCol.forEach((col) => {
 | 
			
		||||
          if (row[col.field]) {
 | 
			
		||||
            ids.push(...(Array.isArray(row[col.field]) ? row[col.field] : [row[col.field]]))
 | 
			
		||||
          }
 | 
			
		||||
        })
 | 
			
		||||
      })
 | 
			
		||||
 | 
			
		||||
      return _.uniq(ids)
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  watch: {
 | 
			
		||||
    columns: {
 | 
			
		||||
      immediate: true,
 | 
			
		||||
      deep: true,
 | 
			
		||||
      handler(newVal) {
 | 
			
		||||
        this.handleReferenceShowAttrName(newVal)
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    referenceCIIdWatch: {
 | 
			
		||||
      immediate: true,
 | 
			
		||||
      deep: true,
 | 
			
		||||
      handler() {
 | 
			
		||||
        this.handleReferenceCIIdMap()
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  methods: {
 | 
			
		||||
@@ -330,6 +410,101 @@ export default {
 | 
			
		||||
 | 
			
		||||
    getRowSeq(row) {
 | 
			
		||||
      return this.getVxetableRef().getRowSeq(row)
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    async handleReferenceShowAttrName(columns) {
 | 
			
		||||
      const needRequiredCITypeIds = columns?.filter((col) => col?.is_reference && col?.reference_type_id).map((col) => col.reference_type_id) || []
 | 
			
		||||
      if (!needRequiredCITypeIds.length) {
 | 
			
		||||
        this.referenceShowAttrNameMap = {}
 | 
			
		||||
        return
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      const res = await getCITypes({
 | 
			
		||||
        type_ids: needRequiredCITypeIds.join(',')
 | 
			
		||||
      })
 | 
			
		||||
 | 
			
		||||
      const map = {}
 | 
			
		||||
      res.ci_types.forEach((ciType) => {
 | 
			
		||||
        map[ciType.id] = ciType?.show_name || ciType?.unique_name || ''
 | 
			
		||||
      })
 | 
			
		||||
 | 
			
		||||
      this.referenceShowAttrNameMap = map
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    async handleReferenceCIIdMap() {
 | 
			
		||||
      const referenceTypeCol = this.columns.filter((col) => col?.is_reference && col?.reference_type_id) || []
 | 
			
		||||
      if (!this.data?.length || !referenceTypeCol?.length) {
 | 
			
		||||
        this.referenceCIIdMap = {}
 | 
			
		||||
        return
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      const map = {}
 | 
			
		||||
      this.data.forEach((row) => {
 | 
			
		||||
        referenceTypeCol.forEach((col) => {
 | 
			
		||||
          const ids = Array.isArray(row[col.field]) ? row[col.field] : row[col.field] ? [row[col.field]] : []
 | 
			
		||||
          if (ids.length) {
 | 
			
		||||
            if (!map?.[col.reference_type_id]) {
 | 
			
		||||
              map[col.reference_type_id] = {}
 | 
			
		||||
            }
 | 
			
		||||
            ids.forEach((id) => {
 | 
			
		||||
              map[col.reference_type_id][id] = {}
 | 
			
		||||
            })
 | 
			
		||||
          }
 | 
			
		||||
        })
 | 
			
		||||
      })
 | 
			
		||||
 | 
			
		||||
      if (!Object.keys(map).length) {
 | 
			
		||||
        this.referenceCIIdMap = {}
 | 
			
		||||
        return
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      const allRes = await Promise.all(
 | 
			
		||||
        Object.keys(map).map((key) => {
 | 
			
		||||
          return searchCI({
 | 
			
		||||
            q: `_type:${key},_id:(${Object.keys(map[key]).join(';')})`,
 | 
			
		||||
            count: 9999
 | 
			
		||||
          })
 | 
			
		||||
        })
 | 
			
		||||
      )
 | 
			
		||||
 | 
			
		||||
      allRes.forEach((res) => {
 | 
			
		||||
        res.result.forEach((item) => {
 | 
			
		||||
          if (map?.[item._type]?.[item._id]) {
 | 
			
		||||
            map[item._type][item._id] = item
 | 
			
		||||
          }
 | 
			
		||||
        })
 | 
			
		||||
      })
 | 
			
		||||
 | 
			
		||||
      this.referenceCIIdMap = map
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    getReferenceAttrValue(id, col) {
 | 
			
		||||
      const ci = this?.referenceCIIdMap?.[col?.reference_type_id]?.[id]
 | 
			
		||||
      if (!ci) {
 | 
			
		||||
        return id
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      const attrName = this.referenceShowAttrNameMap?.[col.reference_type_id]
 | 
			
		||||
      return ci?.[attrName] || id
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    getInitReferenceSelectOption(value, col) {
 | 
			
		||||
      const ids = Array.isArray(value) ? value : value ? [value] : []
 | 
			
		||||
      if (!ids.length) {
 | 
			
		||||
        return []
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      const map = this?.referenceCIIdMap?.[col?.reference_type_id]
 | 
			
		||||
      const attrName = this.referenceShowAttrNameMap?.[col?.reference_type_id]
 | 
			
		||||
 | 
			
		||||
      const option = (Array.isArray(value) ? value : [value]).map((id) => {
 | 
			
		||||
        return {
 | 
			
		||||
          key: id,
 | 
			
		||||
          title: map?.[id]?.[attrName] || id
 | 
			
		||||
        }
 | 
			
		||||
      })
 | 
			
		||||
 | 
			
		||||
      return option
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -113,6 +113,11 @@ export default {
 | 
			
		||||
        this.editor.insertNode(node)
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    destroy() {
 | 
			
		||||
      const editor = this.editor
 | 
			
		||||
      if (editor == null) return
 | 
			
		||||
      editor.destroy()
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
}
 | 
			
		||||
</script>
 | 
			
		||||
 
 | 
			
		||||
@@ -189,6 +189,14 @@ const cmdb_en = {
 | 
			
		||||
        confirmDeleteTrigger: 'Are you sure to delete this trigger?',
 | 
			
		||||
        int: 'Integer',
 | 
			
		||||
        float: 'Float',
 | 
			
		||||
        longText: 'Long Text',
 | 
			
		||||
        shortText: 'Short Text',
 | 
			
		||||
        shortTextTip: 'Text length <= 128',
 | 
			
		||||
        referenceModel: 'Reference Model',
 | 
			
		||||
        referenceModelTip: 'Please select reference model',
 | 
			
		||||
        referenceModelTip1: 'For quick view of referenced model instances',
 | 
			
		||||
        bool: 'Bool',
 | 
			
		||||
        reference: 'Reference',
 | 
			
		||||
        text: 'Text',
 | 
			
		||||
        datetime: 'DateTime',
 | 
			
		||||
        date: 'Date',
 | 
			
		||||
@@ -206,7 +214,7 @@ const cmdb_en = {
 | 
			
		||||
        otherGroupTips: 'Non sortable within the other group',
 | 
			
		||||
        filterTips: 'click to show {name}',
 | 
			
		||||
        attributeAssociation: 'Attribute Association',
 | 
			
		||||
        attributeAssociationTip1: 'Automatically establish relationships through the attributes except password, json and multiple of two models',
 | 
			
		||||
        attributeAssociationTip1: 'Automatically establish relationships through attribute values (except password, json, multi-value, long text, boolean, reference) of two models',
 | 
			
		||||
        attributeAssociationTip2: 'Double click to edit',
 | 
			
		||||
        attributeAssociationTip3: 'Two Attributes must be selected',
 | 
			
		||||
        attributeAssociationTip4: 'Please select a attribute from Source CIType',
 | 
			
		||||
@@ -282,6 +290,9 @@ const cmdb_en = {
 | 
			
		||||
        rule: 'Rule',
 | 
			
		||||
        cascadeAttr: 'Cascade',
 | 
			
		||||
        cascadeAttrTip: 'Cascading attributes note the order',
 | 
			
		||||
        enumValue: 'Value',
 | 
			
		||||
        label: 'Label',
 | 
			
		||||
        valueInputTip: 'Please input value'
 | 
			
		||||
    },
 | 
			
		||||
    components: {
 | 
			
		||||
        unselectAttributes: 'Unselected',
 | 
			
		||||
@@ -323,7 +334,7 @@ const cmdb_en = {
 | 
			
		||||
        pleaseSearch: 'Please search',
 | 
			
		||||
        conditionFilter: 'Conditional filtering',
 | 
			
		||||
        attributeDesc: 'Attribute Description',
 | 
			
		||||
        ciSearchTips: '1. JSON/password/link attributes cannot be searched\n2. If the search content includes commas, they need to be escaped\n3. Only index attributes are searched, non-index attributes use conditional filtering',
 | 
			
		||||
        ciSearchTips: '1. JSON/password/link/longText/reference attributes cannot be searched\n2. If the search content includes commas, they need to be escaped\n3. Only index attributes are searched, non-index attributes use conditional filtering',
 | 
			
		||||
        ciSearchTips2: 'For example: q=hostname:*0.0.0.0*',
 | 
			
		||||
        subCIType: 'Subscription CIType',
 | 
			
		||||
        already: 'already',
 | 
			
		||||
@@ -548,7 +559,7 @@ class AutoDiscovery(object):
 | 
			
		||||
        """
 | 
			
		||||
        Define attribute fields
 | 
			
		||||
        :return: Returns a list of attribute fields. The list items are (name, type, description). The name must be in English.
 | 
			
		||||
        type: String Integer Float Date DateTime Time JSON
 | 
			
		||||
        type: String Integer Float Date DateTime Time JSON Bool Reference
 | 
			
		||||
        For example:
 | 
			
		||||
        return [
 | 
			
		||||
            ("ci_type", "String", "CIType name"),
 | 
			
		||||
 
 | 
			
		||||
@@ -189,6 +189,14 @@ const cmdb_zh = {
 | 
			
		||||
        confirmDeleteTrigger: '确认删除该触发器吗?',
 | 
			
		||||
        int: '整数',
 | 
			
		||||
        float: '浮点数',
 | 
			
		||||
        longText: '长文本',
 | 
			
		||||
        shortText: '短文本',
 | 
			
		||||
        shortTextTip: '文本长度 <= 128',
 | 
			
		||||
        referenceModel: '引用模型',
 | 
			
		||||
        referenceModelTip: '请选择引用模型',
 | 
			
		||||
        referenceModelTip1: '用于快捷查看引用模型实例',
 | 
			
		||||
        bool: '布尔',
 | 
			
		||||
        reference: '引用',
 | 
			
		||||
        text: '文本',
 | 
			
		||||
        datetime: '日期时间',
 | 
			
		||||
        date: '日期',
 | 
			
		||||
@@ -206,7 +214,7 @@ const cmdb_zh = {
 | 
			
		||||
        otherGroupTips: '其他分组属性不可排序',
 | 
			
		||||
        filterTips: '点击可仅查看{name}属性',
 | 
			
		||||
        attributeAssociation: '属性关联',
 | 
			
		||||
        attributeAssociationTip1: '通过2个模型的属性值(除密码、json、多值)来自动建立关系',
 | 
			
		||||
        attributeAssociationTip1: '通过2个模型的属性值(除密码、json、多值、长文本、布尔、引用)来自动建立关系',
 | 
			
		||||
        attributeAssociationTip2: '双击可编辑',
 | 
			
		||||
        attributeAssociationTip3: '属性关联必须选择两个属性',
 | 
			
		||||
        attributeAssociationTip4: '请选择原模型属性',
 | 
			
		||||
@@ -282,6 +290,9 @@ const cmdb_zh = {
 | 
			
		||||
        rule: '规则',
 | 
			
		||||
        cascadeAttr: '级联',
 | 
			
		||||
        cascadeAttrTip: '级联属性注意顺序',
 | 
			
		||||
        enumValue: '枚举值',
 | 
			
		||||
        label: '标签',
 | 
			
		||||
        valueInputTip: '请输入枚举值'
 | 
			
		||||
    },
 | 
			
		||||
    components: {
 | 
			
		||||
        unselectAttributes: '未选属性',
 | 
			
		||||
@@ -323,7 +334,7 @@ const cmdb_zh = {
 | 
			
		||||
        pleaseSearch: '请查找',
 | 
			
		||||
        conditionFilter: '条件过滤',
 | 
			
		||||
        attributeDesc: '属性说明',
 | 
			
		||||
        ciSearchTips: '1. json、密码、链接属性不能搜索\n2. 搜索内容包括逗号, 则需转义\n3. 只搜索索引属性, 非索引属性使用条件过滤',
 | 
			
		||||
        ciSearchTips: '1. json、密码、链接、长文本、引用属性不能搜索\n2. 搜索内容包括逗号, 则需转义\n3. 只搜索索引属性, 非索引属性使用条件过滤',
 | 
			
		||||
        ciSearchTips2: '例: q=hostname:*0.0.0.0*',
 | 
			
		||||
        subCIType: '订阅模型',
 | 
			
		||||
        already: '已',
 | 
			
		||||
@@ -547,7 +558,7 @@ class AutoDiscovery(object):
 | 
			
		||||
        """
 | 
			
		||||
        Define attribute fields
 | 
			
		||||
        :return: Returns a list of attribute fields. The list items are (name, type, description). The name must be in English.
 | 
			
		||||
        type: String Integer Float Date DateTime Time JSON
 | 
			
		||||
        type: String Integer Float Date DateTime Time JSON Bool Reference
 | 
			
		||||
        For example:
 | 
			
		||||
        return [
 | 
			
		||||
            ("ci_type", "String", "CIType name"),
 | 
			
		||||
 
 | 
			
		||||
@@ -4,13 +4,16 @@ export const valueTypeMap = () => {
 | 
			
		||||
  return {
 | 
			
		||||
    '0': i18n.t('cmdb.ciType.int'),
 | 
			
		||||
    '1': i18n.t('cmdb.ciType.float'),
 | 
			
		||||
    '2': i18n.t('cmdb.ciType.text'),
 | 
			
		||||
    '2': i18n.t('cmdb.ciType.shortText'),
 | 
			
		||||
    '3': i18n.t('cmdb.ciType.datetime'),
 | 
			
		||||
    '4': i18n.t('cmdb.ciType.date'),
 | 
			
		||||
    '5': i18n.t('cmdb.ciType.time'),
 | 
			
		||||
    '6': 'JSON',
 | 
			
		||||
    '7': i18n.t('cmdb.ciType.password'),
 | 
			
		||||
    '8': i18n.t('cmdb.ciType.link')
 | 
			
		||||
    '8': i18n.t('cmdb.ciType.link'),
 | 
			
		||||
    '9': i18n.t('cmdb.ciType.longText'),
 | 
			
		||||
    '10': i18n.t('cmdb.ciType.bool'),
 | 
			
		||||
    '11': i18n.t('cmdb.ciType.reference'),
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -97,6 +97,9 @@ export function getCITableColumns(data, attrList, width = 1600, height) {
 | 
			
		||||
            is_list: attr.is_list,
 | 
			
		||||
            is_choice: attr.is_choice,
 | 
			
		||||
            is_fixed: attr.is_fixed,
 | 
			
		||||
            is_bool: attr.is_bool,
 | 
			
		||||
            is_reference: attr.is_reference,
 | 
			
		||||
            reference_type_id: attr.reference_type_id
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -137,6 +140,10 @@ export const getPropertyStyle = (attr) => {
 | 
			
		||||
export const getPropertyIcon = (attr) => {
 | 
			
		||||
    switch (attr.value_type) {
 | 
			
		||||
        case '0':
 | 
			
		||||
            if (attr.is_reference) {
 | 
			
		||||
              return 'duose-quote'
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return 'duose-shishu'
 | 
			
		||||
        case '1':
 | 
			
		||||
            return 'duose-fudianshu'
 | 
			
		||||
@@ -147,6 +154,9 @@ export const getPropertyIcon = (attr) => {
 | 
			
		||||
            if (attr.is_link) {
 | 
			
		||||
                return 'duose-link'
 | 
			
		||||
            }
 | 
			
		||||
            if (attr.is_index === false) {
 | 
			
		||||
              return 'duose-changwenben1'
 | 
			
		||||
            }
 | 
			
		||||
            return 'duose-wenben'
 | 
			
		||||
        case '3':
 | 
			
		||||
            return 'duose-datetime'
 | 
			
		||||
@@ -157,9 +167,49 @@ export const getPropertyIcon = (attr) => {
 | 
			
		||||
        case '6':
 | 
			
		||||
            return 'duose-json'
 | 
			
		||||
        case '7':
 | 
			
		||||
            if (attr.is_bool) {
 | 
			
		||||
              return 'duose-boole'
 | 
			
		||||
            }
 | 
			
		||||
            return 'duose-password'
 | 
			
		||||
        case '8':
 | 
			
		||||
            return 'duose-link'
 | 
			
		||||
        case '9':
 | 
			
		||||
            return 'duose-changwenben1'
 | 
			
		||||
        case '10':
 | 
			
		||||
            return 'duose-boole'
 | 
			
		||||
        case '11':
 | 
			
		||||
            return 'duose-quote'
 | 
			
		||||
        default:
 | 
			
		||||
            return ''
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const getPropertyType = (attr) => {
 | 
			
		||||
  if (attr.is_password) {
 | 
			
		||||
    return '7'
 | 
			
		||||
  }
 | 
			
		||||
  if (attr.is_link) {
 | 
			
		||||
    return '8'
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  switch (attr.value_type) {
 | 
			
		||||
    case '0':
 | 
			
		||||
      if (attr.is_reference) {
 | 
			
		||||
        return '11'
 | 
			
		||||
      }
 | 
			
		||||
      return '0'
 | 
			
		||||
    case '2':
 | 
			
		||||
      if (!attr.is_index) {
 | 
			
		||||
        return '9'
 | 
			
		||||
      }
 | 
			
		||||
      return '2'
 | 
			
		||||
    case '7':
 | 
			
		||||
      if (attr.is_bool) {
 | 
			
		||||
        return '10'
 | 
			
		||||
      }
 | 
			
		||||
      return '7'
 | 
			
		||||
    default:
 | 
			
		||||
      return attr?.value_type ?? ''
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -465,13 +465,12 @@ export default {
 | 
			
		||||
      this.loadTip = this.$t('cmdb.ci.batchUpdateInProgress') + '...'
 | 
			
		||||
      const payload = {}
 | 
			
		||||
      Object.keys(values).forEach((key) => {
 | 
			
		||||
        if (values[key] || values[key] === 0) {
 | 
			
		||||
          payload[key] = values[key]
 | 
			
		||||
        }
 | 
			
		||||
        // Field values support blanking
 | 
			
		||||
        // There are currently field values that do not support blanking and will be returned by the backend.
 | 
			
		||||
        if (values[key] === undefined || values[key] === null) {
 | 
			
		||||
          payload[key] = null
 | 
			
		||||
        } else {
 | 
			
		||||
          payload[key] = values[key]
 | 
			
		||||
        }
 | 
			
		||||
      })
 | 
			
		||||
      this.$refs.create.visible = false
 | 
			
		||||
 
 | 
			
		||||
@@ -35,7 +35,7 @@
 | 
			
		||||
                  <a-select v-model="parentsForm[item.name].attr">
 | 
			
		||||
                    <a-select-option
 | 
			
		||||
                      :title="attr.alias || attr.name"
 | 
			
		||||
                      v-for="attr in item.attributes"
 | 
			
		||||
                      v-for="attr in filterAttributes(item.attributes)"
 | 
			
		||||
                      :key="attr.name"
 | 
			
		||||
                      :value="attr.name"
 | 
			
		||||
                    >
 | 
			
		||||
@@ -87,11 +87,32 @@
 | 
			
		||||
          </a-col>
 | 
			
		||||
          <a-col :span="showListOperation(list.name) ? 10 : 13">
 | 
			
		||||
            <a-form-item>
 | 
			
		||||
              <CIReferenceAttr
 | 
			
		||||
                v-if="getAttr(list.name).is_reference"
 | 
			
		||||
                :referenceTypeId="getAttr(list.name).reference_type_id"
 | 
			
		||||
                :isList="getAttr(list.name).is_list"
 | 
			
		||||
                v-decorator="[
 | 
			
		||||
                  list.name,
 | 
			
		||||
                  {
 | 
			
		||||
                    initialValue: getAttr(list.name).is_list ? [] : ''
 | 
			
		||||
                  }
 | 
			
		||||
                ]"
 | 
			
		||||
              />
 | 
			
		||||
              <a-switch
 | 
			
		||||
                v-else-if="getAttr(list.name).is_bool"
 | 
			
		||||
                v-decorator="[
 | 
			
		||||
                  list.name,
 | 
			
		||||
                  {
 | 
			
		||||
                    valuePropName: 'checked',
 | 
			
		||||
                    initialValue: false
 | 
			
		||||
                  }
 | 
			
		||||
                ]"
 | 
			
		||||
              />
 | 
			
		||||
              <a-select
 | 
			
		||||
                :style="{ width: '100%' }"
 | 
			
		||||
                v-decorator="[list.name, { rules: getDecoratorRules(list) }]"
 | 
			
		||||
                :placeholder="$t('placeholder2')"
 | 
			
		||||
                v-if="getFieldType(list.name).split('%%')[0] === 'select'"
 | 
			
		||||
                v-else-if="getFieldType(list.name).split('%%')[0] === 'select'"
 | 
			
		||||
                :mode="getFieldType(list.name).split('%%')[1] === 'multiple' ? 'multiple' : 'default'"
 | 
			
		||||
                showSearch
 | 
			
		||||
                allowClear
 | 
			
		||||
@@ -114,18 +135,18 @@
 | 
			
		||||
              <a-input-number
 | 
			
		||||
                v-decorator="[list.name, { rules: getDecoratorRules(list) }]"
 | 
			
		||||
                style="width: 100%"
 | 
			
		||||
                v-if="getFieldType(list.name) === 'input_number'"
 | 
			
		||||
                v-else-if="getFieldType(list.name) === 'input_number'"
 | 
			
		||||
              />
 | 
			
		||||
              <a-date-picker
 | 
			
		||||
                v-decorator="[list.name, { rules: getDecoratorRules(list) }]"
 | 
			
		||||
                style="width: 100%"
 | 
			
		||||
                :format="getFieldType(list.name) == '4' ? 'YYYY-MM-DD' : 'YYYY-MM-DD HH:mm:ss'"
 | 
			
		||||
                :valueFormat="getFieldType(list.name) == '4' ? 'YYYY-MM-DD' : 'YYYY-MM-DD HH:mm:ss'"
 | 
			
		||||
                v-if="getFieldType(list.name) === '4' || getFieldType(list.name) === '3'"
 | 
			
		||||
                v-else-if="getFieldType(list.name) === '4' || getFieldType(list.name) === '3'"
 | 
			
		||||
                :showTime="getFieldType(list.name) === '4' ? false : { format: 'HH:mm:ss' }"
 | 
			
		||||
              />
 | 
			
		||||
              <a-input
 | 
			
		||||
                v-if="getFieldType(list.name) === 'input'"
 | 
			
		||||
                v-else-if="getFieldType(list.name) === 'input'"
 | 
			
		||||
                @focus="(e) => handleFocusInput(e, list)"
 | 
			
		||||
                v-decorator="[list.name, { rules: getDecoratorRules(list) }]"
 | 
			
		||||
              />
 | 
			
		||||
@@ -156,6 +177,7 @@ import JsonEditor from '../../../components/JsonEditor/jsonEditor.vue'
 | 
			
		||||
import { valueTypeMap } from '../../../utils/const'
 | 
			
		||||
import CreateInstanceFormByGroup from './createInstanceFormByGroup.vue'
 | 
			
		||||
import { getCITypeParent, getCanEditByParentIdChildId } from '@/modules/cmdb/api/CITypeRelation'
 | 
			
		||||
import CIReferenceAttr from '@/components/ciReferenceAttr/index.vue'
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  name: 'CreateInstanceForm',
 | 
			
		||||
@@ -164,6 +186,7 @@ export default {
 | 
			
		||||
    ElOption: Option,
 | 
			
		||||
    JsonEditor,
 | 
			
		||||
    CreateInstanceFormByGroup,
 | 
			
		||||
    CIReferenceAttr
 | 
			
		||||
  },
 | 
			
		||||
  props: {
 | 
			
		||||
    typeIdFromRelation: {
 | 
			
		||||
@@ -261,6 +284,11 @@ export default {
 | 
			
		||||
          }
 | 
			
		||||
          Object.keys(values).forEach((k) => {
 | 
			
		||||
            const _tempFind = this.attributeList.find((item) => item.name === k)
 | 
			
		||||
 | 
			
		||||
            if (_tempFind.is_reference) {
 | 
			
		||||
              values[k] = values[k] ? values[k] : null
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (
 | 
			
		||||
              _tempFind.value_type === '3' &&
 | 
			
		||||
              values[k] &&
 | 
			
		||||
@@ -309,6 +337,11 @@ export default {
 | 
			
		||||
 | 
			
		||||
        Object.keys(values).forEach((k) => {
 | 
			
		||||
          const _tempFind = this.attributeList.find((item) => item.name === k)
 | 
			
		||||
 | 
			
		||||
          if (_tempFind.is_reference) {
 | 
			
		||||
            values[k] = values[k] ? values[k] : null
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          if (
 | 
			
		||||
            _tempFind.value_type === '3' &&
 | 
			
		||||
            values[k] &&
 | 
			
		||||
@@ -426,6 +459,9 @@ export default {
 | 
			
		||||
      }
 | 
			
		||||
      return 'input'
 | 
			
		||||
    },
 | 
			
		||||
    getAttr(name) {
 | 
			
		||||
      return this.attributeList.find((item) => item.name === name) ?? {}
 | 
			
		||||
    },
 | 
			
		||||
    getSelectFieldOptions(name) {
 | 
			
		||||
      const _find = this.attributeList.find((item) => item.name === name)
 | 
			
		||||
      if (_find) {
 | 
			
		||||
@@ -487,7 +523,12 @@ export default {
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      return rules
 | 
			
		||||
    }
 | 
			
		||||
    },
 | 
			
		||||
    filterAttributes(attributes) {
 | 
			
		||||
      return attributes.filter((attr) => {
 | 
			
		||||
        return !attr.is_bool && !attr.is_reference
 | 
			
		||||
      })
 | 
			
		||||
    },
 | 
			
		||||
  },
 | 
			
		||||
}
 | 
			
		||||
</script>
 | 
			
		||||
@@ -498,7 +539,7 @@ export default {
 | 
			
		||||
  }
 | 
			
		||||
  .ant-drawer-body {
 | 
			
		||||
    overflow-y: auto;
 | 
			
		||||
    max-height: calc(100vh - 110px);
 | 
			
		||||
    height: calc(100vh - 110px);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
 
 | 
			
		||||
@@ -79,6 +79,8 @@
 | 
			
		||||
import XEUtils from 'xe-utils'
 | 
			
		||||
import { getCITypeAttributesByName } from '@/modules/cmdb/api/CITypeAttr'
 | 
			
		||||
import { valueTypeMap } from '@/modules/cmdb/utils/const'
 | 
			
		||||
import { getPropertyType } from '@/modules/cmdb/utils/helper'
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  name: 'MetadataDrawer',
 | 
			
		||||
  data() {
 | 
			
		||||
@@ -187,12 +189,7 @@ export default {
 | 
			
		||||
      this.loading = true
 | 
			
		||||
      const { attributes = [] } = await getCITypeAttributesByName(this.typeId)
 | 
			
		||||
      this.tableData = attributes.map((attr) => {
 | 
			
		||||
        if (attr.is_password) {
 | 
			
		||||
          attr.value_type = '7'
 | 
			
		||||
        }
 | 
			
		||||
        if (attr.is_link) {
 | 
			
		||||
          attr.value_type = '8'
 | 
			
		||||
        }
 | 
			
		||||
        attr.value_type = getPropertyType(attr)
 | 
			
		||||
        return attr
 | 
			
		||||
      })
 | 
			
		||||
      this.loading = false
 | 
			
		||||
 
 | 
			
		||||
@@ -1,9 +1,19 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <span :id="`ci-detail-attr-${attr.name}`">
 | 
			
		||||
    <span v-if="!isEdit || attr.value_type === '6'">
 | 
			
		||||
      <template v-if="attr.is_reference" >
 | 
			
		||||
        <a
 | 
			
		||||
          v-for="(ciId) in (attr.is_list ? ci[attr.name] : [ci[attr.name]])"
 | 
			
		||||
          :key="ciId"
 | 
			
		||||
          :href="`/cmdb/cidetail/${attr.reference_type_id}/${ciId}`"
 | 
			
		||||
          target="_blank"
 | 
			
		||||
        >
 | 
			
		||||
          {{ attr.referenceShowAttrNameMap ? attr.referenceShowAttrNameMap[ciId] || ciId : ciId }}
 | 
			
		||||
        </a>
 | 
			
		||||
      </template>
 | 
			
		||||
      <PasswordField
 | 
			
		||||
        :style="{ display: 'inline-block' }"
 | 
			
		||||
        v-if="attr.is_password && ci[attr.name]"
 | 
			
		||||
        v-else-if="attr.is_password && ci[attr.name]"
 | 
			
		||||
        :ci_id="ci._id"
 | 
			
		||||
        :attr_id="attr.id"
 | 
			
		||||
      ></PasswordField>
 | 
			
		||||
@@ -67,6 +77,29 @@
 | 
			
		||||
    <template v-else>
 | 
			
		||||
      <a-form :form="form">
 | 
			
		||||
        <a-form-item label="" :colon="false">
 | 
			
		||||
          <CIReferenceAttr
 | 
			
		||||
            v-if="attr.is_reference"
 | 
			
		||||
            :referenceTypeId="attr.reference_type_id"
 | 
			
		||||
            :isList="attr.is_list"
 | 
			
		||||
            :referenceShowAttrName="attr.showAttrName"
 | 
			
		||||
            :initSelectOption="getInitReferenceSelectOption(attr)"
 | 
			
		||||
            v-decorator="[
 | 
			
		||||
              attr.name,
 | 
			
		||||
              {
 | 
			
		||||
                rules: [{ required: attr.is_required, message: $t('placeholder2') + `${attr.alias || attr.name}` }],
 | 
			
		||||
              }
 | 
			
		||||
            ]"
 | 
			
		||||
          />
 | 
			
		||||
          <a-switch
 | 
			
		||||
            v-else-if="attr.is_bool"
 | 
			
		||||
            v-decorator="[
 | 
			
		||||
              attr.name,
 | 
			
		||||
              {
 | 
			
		||||
                rules: [{ required: attr.is_required }],
 | 
			
		||||
                valuePropName: 'checked',
 | 
			
		||||
              }
 | 
			
		||||
            ]"
 | 
			
		||||
          />
 | 
			
		||||
          <a-select
 | 
			
		||||
            :style="{ width: '100%' }"
 | 
			
		||||
            v-decorator="[
 | 
			
		||||
@@ -76,7 +109,7 @@
 | 
			
		||||
              },
 | 
			
		||||
            ]"
 | 
			
		||||
            :placeholder="$t('placeholder2')"
 | 
			
		||||
            v-if="attr.is_choice"
 | 
			
		||||
            v-else-if="attr.is_choice"
 | 
			
		||||
            :mode="attr.is_list ? 'multiple' : 'default'"
 | 
			
		||||
            showSearch
 | 
			
		||||
            allowClear
 | 
			
		||||
@@ -157,10 +190,11 @@ import { updateCI } from '@/modules/cmdb/api/ci'
 | 
			
		||||
import JsonEditor from '../../../components/JsonEditor/jsonEditor.vue'
 | 
			
		||||
import PasswordField from '../../../components/passwordField/index.vue'
 | 
			
		||||
import { getAttrPassword } from '../../../api/CITypeAttr'
 | 
			
		||||
import CIReferenceAttr from '@/components/ciReferenceAttr/index.vue'
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  name: 'CiDetailAttrContent',
 | 
			
		||||
  components: { JsonEditor, PasswordField },
 | 
			
		||||
  components: { JsonEditor, PasswordField, CIReferenceAttr },
 | 
			
		||||
  props: {
 | 
			
		||||
    ci: {
 | 
			
		||||
      type: Object,
 | 
			
		||||
@@ -209,7 +243,7 @@ export default {
 | 
			
		||||
      }
 | 
			
		||||
      this.isEdit = true
 | 
			
		||||
      this.$nextTick(async () => {
 | 
			
		||||
        if (this.attr.is_list && !this.attr.is_choice) {
 | 
			
		||||
        if (this.attr.is_list && !this.attr.is_choice && !this.attr.is_reference) {
 | 
			
		||||
          this.form.setFieldsValue({
 | 
			
		||||
            [`${this.attr.name}`]: Array.isArray(this.ci[this.attr.name])
 | 
			
		||||
              ? this.ci[this.attr.name].join(',')
 | 
			
		||||
@@ -237,6 +271,10 @@ export default {
 | 
			
		||||
          .then(() => {
 | 
			
		||||
            this.$message.success(this.$t('updateSuccess'))
 | 
			
		||||
            this.$emit('updateCIByself', { [`${this.attr.name}`]: newData }, this.attr.name)
 | 
			
		||||
 | 
			
		||||
            if (this.attr.is_reference) {
 | 
			
		||||
              this.$emit('refreshReferenceAttr')
 | 
			
		||||
            }
 | 
			
		||||
          })
 | 
			
		||||
          .catch(() => {
 | 
			
		||||
            this.$emit('refresh', this.attr.name)
 | 
			
		||||
@@ -283,6 +321,16 @@ export default {
 | 
			
		||||
    getName(name) {
 | 
			
		||||
      return name ?? ''
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    getInitReferenceSelectOption(attr) {
 | 
			
		||||
      const option = Object.keys(attr?.referenceShowAttrNameMap || {}).map((key) => {
 | 
			
		||||
        return {
 | 
			
		||||
          key: Number(key),
 | 
			
		||||
          title: attr?.referenceShowAttrNameMap?.[key] ?? ''
 | 
			
		||||
        }
 | 
			
		||||
      })
 | 
			
		||||
      return option
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
}
 | 
			
		||||
</script>
 | 
			
		||||
 
 | 
			
		||||
@@ -38,6 +38,16 @@
 | 
			
		||||
            resizable
 | 
			
		||||
            class="ops-stripe-table"
 | 
			
		||||
          >
 | 
			
		||||
            <template #reference_default="{ row, column }">
 | 
			
		||||
              <a
 | 
			
		||||
                v-for="(id) in (column.params.attr.is_list ? row[column.field] : [row[column.field]])"
 | 
			
		||||
                :key="id"
 | 
			
		||||
                :href="`/cmdb/cidetail/${column.params.attr.reference_type_id}/${id}`"
 | 
			
		||||
                target="_blank"
 | 
			
		||||
              >
 | 
			
		||||
                {{ id }}
 | 
			
		||||
              </a>
 | 
			
		||||
            </template>
 | 
			
		||||
            <template #operation_default="{ row }">
 | 
			
		||||
              <a-popconfirm
 | 
			
		||||
                arrowPointAtCenter
 | 
			
		||||
@@ -85,6 +95,16 @@
 | 
			
		||||
            resizable
 | 
			
		||||
            class="ops-stripe-table"
 | 
			
		||||
          >
 | 
			
		||||
            <template #reference_default="{ row, column }">
 | 
			
		||||
              <a
 | 
			
		||||
                v-for="(id) in (column.params.attr.is_list ? row[column.field] : [row[column.field]])"
 | 
			
		||||
                :key="id"
 | 
			
		||||
                :href="`/cmdb/cidetail/${column.params.attr.reference_type_id}/${id}`"
 | 
			
		||||
                target="_blank"
 | 
			
		||||
              >
 | 
			
		||||
                {{ id }}
 | 
			
		||||
              </a>
 | 
			
		||||
            </template>
 | 
			
		||||
            <template #operation_default="{ row }">
 | 
			
		||||
              <a-popconfirm
 | 
			
		||||
                arrowPointAtCenter
 | 
			
		||||
@@ -258,7 +278,22 @@ export default {
 | 
			
		||||
        const columns = []
 | 
			
		||||
        const jsonAttr = []
 | 
			
		||||
        item.attributes.forEach((attr) => {
 | 
			
		||||
          columns.push({ key: 'p_' + attr.id, field: attr.name, title: attr.alias, minWidth: '100px' })
 | 
			
		||||
          const column = {
 | 
			
		||||
            key: 'p_' + attr.id,
 | 
			
		||||
            field: attr.name,
 | 
			
		||||
            title: attr.alias,
 | 
			
		||||
            minWidth: '100px',
 | 
			
		||||
            params: {
 | 
			
		||||
              attr
 | 
			
		||||
            },
 | 
			
		||||
          }
 | 
			
		||||
          if (attr.is_reference) {
 | 
			
		||||
            column.slots = {
 | 
			
		||||
              default: 'reference_default'
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
          columns.push(column)
 | 
			
		||||
 | 
			
		||||
          if (attr.value_type === '6') {
 | 
			
		||||
            jsonAttr.push(attr.name)
 | 
			
		||||
          }
 | 
			
		||||
@@ -299,7 +334,22 @@ export default {
 | 
			
		||||
        const columns = []
 | 
			
		||||
        const jsonAttr = []
 | 
			
		||||
        item.attributes.forEach((attr) => {
 | 
			
		||||
          columns.push({ key: 'c_' + attr.id, field: attr.name, title: attr.alias, minWidth: '100px' })
 | 
			
		||||
          const column = {
 | 
			
		||||
            key: 'c_' + attr.id,
 | 
			
		||||
            field: attr.name,
 | 
			
		||||
            title: attr.alias,
 | 
			
		||||
            minWidth: '100px',
 | 
			
		||||
            params: {
 | 
			
		||||
              attr
 | 
			
		||||
            },
 | 
			
		||||
          }
 | 
			
		||||
          if (attr.is_reference) {
 | 
			
		||||
            column.slots = {
 | 
			
		||||
              default: 'reference_default'
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
          columns.push(column)
 | 
			
		||||
 | 
			
		||||
          if (attr.value_type === '6') {
 | 
			
		||||
            jsonAttr.push(attr.name)
 | 
			
		||||
          }
 | 
			
		||||
 
 | 
			
		||||
@@ -20,7 +20,7 @@
 | 
			
		||||
              :key="attr.name"
 | 
			
		||||
              v-for="attr in group.attributes"
 | 
			
		||||
            >
 | 
			
		||||
              <ci-detail-attr-content :ci="ci" :attr="attr" @refresh="refresh" @updateCIByself="updateCIByself" />
 | 
			
		||||
              <ci-detail-attr-content :ci="ci" :attr="attr" @refresh="refresh" @updateCIByself="updateCIByself" @refreshReferenceAttr="handleReferenceAttr" />
 | 
			
		||||
            </el-descriptions-item>
 | 
			
		||||
          </el-descriptions>
 | 
			
		||||
        </div>
 | 
			
		||||
@@ -137,7 +137,7 @@ import _ from 'lodash'
 | 
			
		||||
import { Descriptions, DescriptionsItem } from 'element-ui'
 | 
			
		||||
import { getCITypeGroupById, getCITypes } from '@/modules/cmdb/api/CIType'
 | 
			
		||||
import { getCIHistory, judgeItsmInstalled } from '@/modules/cmdb/api/history'
 | 
			
		||||
import { getCIById } from '@/modules/cmdb/api/ci'
 | 
			
		||||
import { getCIById, searchCI } from '@/modules/cmdb/api/ci'
 | 
			
		||||
import CiDetailAttrContent from './ciDetailAttrContent.vue'
 | 
			
		||||
import CiDetailRelation from './ciDetailRelation.vue'
 | 
			
		||||
import TriggerTable from '../../operation_history/modules/triggerTable.vue'
 | 
			
		||||
@@ -244,9 +244,78 @@ export default {
 | 
			
		||||
      getCITypeGroupById(this.typeId, { need_other: 1 })
 | 
			
		||||
        .then((res) => {
 | 
			
		||||
          this.attributeGroups = res
 | 
			
		||||
 | 
			
		||||
          this.handleReferenceAttr()
 | 
			
		||||
        })
 | 
			
		||||
        .catch((e) => {})
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    async handleReferenceAttr() {
 | 
			
		||||
      const map = {}
 | 
			
		||||
      this.attributeGroups.forEach((group) => {
 | 
			
		||||
        group.attributes.forEach((attr) => {
 | 
			
		||||
          if (attr?.is_reference && attr?.reference_type_id && this.ci[attr.name]) {
 | 
			
		||||
            const ids = Array.isArray(this.ci[attr.name]) ? this.ci[attr.name] : this.ci[attr.name] ? [this.ci[attr.name]] : []
 | 
			
		||||
            if (ids.length) {
 | 
			
		||||
              if (!map?.[attr.reference_type_id]) {
 | 
			
		||||
                map[attr.reference_type_id] = {}
 | 
			
		||||
              }
 | 
			
		||||
              ids.forEach((id) => {
 | 
			
		||||
                map[attr.reference_type_id][id] = {}
 | 
			
		||||
              })
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        })
 | 
			
		||||
      })
 | 
			
		||||
 | 
			
		||||
      if (!Object.keys(map).length) {
 | 
			
		||||
        return
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      const ciTypesRes = await getCITypes({
 | 
			
		||||
        type_ids: Object.keys(map).join(',')
 | 
			
		||||
      })
 | 
			
		||||
      const showAttrNameMap = {}
 | 
			
		||||
      ciTypesRes.ci_types.forEach((ciType) => {
 | 
			
		||||
        showAttrNameMap[ciType.id] = ciType?.show_name || ciType?.unique_name || ''
 | 
			
		||||
      })
 | 
			
		||||
 | 
			
		||||
      const allRes = await Promise.all(
 | 
			
		||||
        Object.keys(map).map((key) => {
 | 
			
		||||
          return searchCI({
 | 
			
		||||
            q: `_type:${key},_id:(${Object.keys(map[key]).join(';')})`,
 | 
			
		||||
            count: 9999
 | 
			
		||||
          })
 | 
			
		||||
        })
 | 
			
		||||
      )
 | 
			
		||||
 | 
			
		||||
      const ciNameMap = {}
 | 
			
		||||
      allRes.forEach((res) => {
 | 
			
		||||
        res.result.forEach((item) => {
 | 
			
		||||
          ciNameMap[item._id] = item
 | 
			
		||||
        })
 | 
			
		||||
      })
 | 
			
		||||
 | 
			
		||||
      const newAttrGroups = _.cloneDeep(this.attributeGroups)
 | 
			
		||||
 | 
			
		||||
      newAttrGroups.forEach((group) => {
 | 
			
		||||
        group.attributes.forEach((attr) => {
 | 
			
		||||
          if (attr?.is_reference && attr?.reference_type_id) {
 | 
			
		||||
            attr.showAttrName = showAttrNameMap?.[attr?.reference_type_id] || ''
 | 
			
		||||
 | 
			
		||||
            const referenceShowAttrNameMap = {}
 | 
			
		||||
            const referenceCIIds = this.ci[attr.name];
 | 
			
		||||
            (Array.isArray(referenceCIIds) ? referenceCIIds : referenceCIIds ? [referenceCIIds] : []).forEach((id) => {
 | 
			
		||||
              referenceShowAttrNameMap[id] = ciNameMap?.[id]?.[attr.showAttrName] ?? id
 | 
			
		||||
            })
 | 
			
		||||
            attr.referenceShowAttrNameMap = referenceShowAttrNameMap
 | 
			
		||||
          }
 | 
			
		||||
        })
 | 
			
		||||
      })
 | 
			
		||||
 | 
			
		||||
      this.$set(this, 'attributeGroups', newAttrGroups)
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    async getCI() {
 | 
			
		||||
      await getCIById(this.ciId)
 | 
			
		||||
        .then((res) => {
 | 
			
		||||
 
 | 
			
		||||
@@ -16,6 +16,29 @@
 | 
			
		||||
        :key="attr.name + attr_idx"
 | 
			
		||||
      >
 | 
			
		||||
        <a-form-item :label="attr.alias || attr.name" :colon="false">
 | 
			
		||||
          <CIReferenceAttr
 | 
			
		||||
            v-if="attr.is_reference"
 | 
			
		||||
            :referenceTypeId="attr.reference_type_id"
 | 
			
		||||
            :isList="attr.is_list"
 | 
			
		||||
            v-decorator="[
 | 
			
		||||
              attr.name,
 | 
			
		||||
              {
 | 
			
		||||
                rules: [{ required: attr.is_required, message: $t('placeholder2') + `${attr.alias || attr.name}` }],
 | 
			
		||||
                initialValue: attr.is_list ? [] : ''
 | 
			
		||||
              }
 | 
			
		||||
            ]"
 | 
			
		||||
          />
 | 
			
		||||
          <a-switch
 | 
			
		||||
            v-else-if="attr.is_bool"
 | 
			
		||||
            v-decorator="[
 | 
			
		||||
              attr.name,
 | 
			
		||||
              {
 | 
			
		||||
                rules: [{ required: false }],
 | 
			
		||||
                valuePropName: 'checked',
 | 
			
		||||
                initialValue: attr.default ? Boolean(attr.default.default) : false
 | 
			
		||||
              }
 | 
			
		||||
            ]"
 | 
			
		||||
          />
 | 
			
		||||
          <a-select
 | 
			
		||||
            :style="{ width: '100%' }"
 | 
			
		||||
            v-decorator="[
 | 
			
		||||
@@ -33,7 +56,7 @@
 | 
			
		||||
              },
 | 
			
		||||
            ]"
 | 
			
		||||
            :placeholder="$t('placeholder2')"
 | 
			
		||||
            v-if="attr.is_choice"
 | 
			
		||||
            v-else-if="attr.is_choice"
 | 
			
		||||
            :mode="attr.is_list ? 'multiple' : 'default'"
 | 
			
		||||
            showSearch
 | 
			
		||||
            allowClear
 | 
			
		||||
@@ -133,10 +156,14 @@
 | 
			
		||||
import _ from 'lodash'
 | 
			
		||||
import moment from 'moment'
 | 
			
		||||
import JsonEditor from '../../../components/JsonEditor/jsonEditor.vue'
 | 
			
		||||
import CIReferenceAttr from '@/components/ciReferenceAttr/index.vue'
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  name: 'CreateInstanceFormByGroup',
 | 
			
		||||
  components: { JsonEditor },
 | 
			
		||||
  components: {
 | 
			
		||||
    JsonEditor,
 | 
			
		||||
    CIReferenceAttr
 | 
			
		||||
  },
 | 
			
		||||
  props: {
 | 
			
		||||
    group: {
 | 
			
		||||
      type: Object,
 | 
			
		||||
@@ -146,6 +173,10 @@ export default {
 | 
			
		||||
      type: Array,
 | 
			
		||||
      default: () => [],
 | 
			
		||||
    },
 | 
			
		||||
    ciTypeId: {
 | 
			
		||||
      type: [Number, String],
 | 
			
		||||
      default: ''
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  inject: ['getFieldType'],
 | 
			
		||||
  data() {
 | 
			
		||||
 
 | 
			
		||||
@@ -39,6 +39,7 @@
 | 
			
		||||
import { mapState } from 'vuex'
 | 
			
		||||
import _ from 'lodash'
 | 
			
		||||
import { valueTypeMap } from '@/modules/cmdb/utils/const'
 | 
			
		||||
import { getPropertyType } from '@/modules/cmdb/utils/helper'
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  name: 'AllAttrDrawer',
 | 
			
		||||
@@ -84,12 +85,7 @@ export default {
 | 
			
		||||
      })
 | 
			
		||||
 | 
			
		||||
      otherAttrData.forEach((attr) => {
 | 
			
		||||
        if (attr.is_password) {
 | 
			
		||||
          attr.value_type = '7'
 | 
			
		||||
        }
 | 
			
		||||
        if (attr.is_link) {
 | 
			
		||||
          attr.value_type = '8'
 | 
			
		||||
        }
 | 
			
		||||
        attr.value_type = getPropertyType(attr)
 | 
			
		||||
 | 
			
		||||
        attr.groupId = -1
 | 
			
		||||
        attr.groupName = this.$t('other')
 | 
			
		||||
 
 | 
			
		||||
@@ -21,9 +21,7 @@
 | 
			
		||||
            <div :class="{ 'attribute-card-name': true, 'attribute-card-name-default-show': property.default_show }">
 | 
			
		||||
              {{ property.alias || property.name }}
 | 
			
		||||
            </div>
 | 
			
		||||
            <div v-if="property.is_password" class="attribute-card_value-type">{{ $t('cmdb.ciType.password') }}</div>
 | 
			
		||||
            <div v-else-if="property.is_link" class="attribute-card_value-type">{{ $t('cmdb.ciType.link') }}</div>
 | 
			
		||||
            <div v-else class="attribute-card_value-type">{{ valueTypeMap[property.value_type] }}</div>
 | 
			
		||||
            <div class="attribute-card_value-type">{{ valueTypeMap[getPropertyType(property)] }}</div>
 | 
			
		||||
          </div>
 | 
			
		||||
          <div
 | 
			
		||||
            class="attribute-card-trigger"
 | 
			
		||||
@@ -74,7 +72,9 @@
 | 
			
		||||
                !isUnique &&
 | 
			
		||||
                !['6'].includes(property.value_type) &&
 | 
			
		||||
                !property.is_password &&
 | 
			
		||||
                !property.is_list
 | 
			
		||||
                !property.is_list &&
 | 
			
		||||
                !property.is_reference &&
 | 
			
		||||
                !property.is_bool
 | 
			
		||||
            "
 | 
			
		||||
            :title="$t(isShowId ? 'cmdb.ciType.cancelSetAsShow' : 'cmdb.ciType.setAsShow')"
 | 
			
		||||
          >
 | 
			
		||||
@@ -101,6 +101,8 @@ import ValueTypeIcon from '@/components/CMDBValueTypeMapIcon'
 | 
			
		||||
import { valueTypeMap } from '../../utils/const'
 | 
			
		||||
import TriggerForm from './triggerForm.vue'
 | 
			
		||||
import { updateCIType } from '@/modules/cmdb/api/CIType'
 | 
			
		||||
import { getPropertyType } from '../../utils/helper'
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  name: 'AttributeCard',
 | 
			
		||||
  inject: {
 | 
			
		||||
@@ -191,6 +193,7 @@ export default {
 | 
			
		||||
    },
 | 
			
		||||
  },
 | 
			
		||||
  methods: {
 | 
			
		||||
    getPropertyType,
 | 
			
		||||
    handleEdit() {
 | 
			
		||||
      this.$emit('edit')
 | 
			
		||||
    },
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,78 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <a-form-item
 | 
			
		||||
    :label="$t('cmdb.ciType.referenceModel')"
 | 
			
		||||
    :extra="$t('cmdb.ciType.referenceModelTip1')"
 | 
			
		||||
    :label-col="formItemLayout.labelCol"
 | 
			
		||||
    :wrapper-col="formItemLayout.wrapperCol"
 | 
			
		||||
  >
 | 
			
		||||
    <a-select
 | 
			
		||||
      allowClear
 | 
			
		||||
      v-decorator="['reference_type_id', {
 | 
			
		||||
        rules: [{ required: true, message: $t('cmdb.ciType.referenceModelTip') }],
 | 
			
		||||
        initialValue: ''
 | 
			
		||||
      }]"
 | 
			
		||||
      showSearch
 | 
			
		||||
      optionFilterProp="title"
 | 
			
		||||
      @dropdownVisibleChange="handleDropdownVisibleChange"
 | 
			
		||||
    >
 | 
			
		||||
      <a-select-option
 | 
			
		||||
        v-for="(item) in options"
 | 
			
		||||
        :key="item.value"
 | 
			
		||||
        :title="item.label"
 | 
			
		||||
      >
 | 
			
		||||
        {{ item.label }}
 | 
			
		||||
      </a-select-option>
 | 
			
		||||
    </a-select>
 | 
			
		||||
  </a-form-item>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
import { getCITypes } from '@/modules/cmdb/api/CIType'
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  name: 'ReferenceModelSelect',
 | 
			
		||||
  props: {
 | 
			
		||||
    form: {
 | 
			
		||||
      type: Object,
 | 
			
		||||
      required: true,
 | 
			
		||||
    },
 | 
			
		||||
    isLazyRequire: {
 | 
			
		||||
      type: Boolean,
 | 
			
		||||
      default: true
 | 
			
		||||
    },
 | 
			
		||||
    formItemLayout: {
 | 
			
		||||
      type: Object,
 | 
			
		||||
      default: () => {}
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  data() {
 | 
			
		||||
    return {
 | 
			
		||||
      isInit: false,
 | 
			
		||||
      options: []
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  mounted() {
 | 
			
		||||
    if (!this.isLazyRequire) {
 | 
			
		||||
      this.getSelectOptions()
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  methods: {
 | 
			
		||||
    handleDropdownVisibleChange(open) {
 | 
			
		||||
      if (!this.isInit && open) {
 | 
			
		||||
        this.getSelectOptions()
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    async getSelectOptions() {
 | 
			
		||||
      this.isInit = true
 | 
			
		||||
      const res = await getCITypes()
 | 
			
		||||
 | 
			
		||||
      this.options = res.ci_types.map((ciType) => {
 | 
			
		||||
        return {
 | 
			
		||||
          value: ciType.id,
 | 
			
		||||
          label: ciType?.alias || ciType?.name || ''
 | 
			
		||||
        }
 | 
			
		||||
      })
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
</script>
 | 
			
		||||
@@ -60,11 +60,17 @@
 | 
			
		||||
          v-decorator="['value_type', { rules: [{ required: true }] }]"
 | 
			
		||||
          @change="handleChangeValueType"
 | 
			
		||||
        >
 | 
			
		||||
          <a-select-option :value="key" :key="key" v-for="(value, key) in valueTypeMap">{{ value }}</a-select-option>
 | 
			
		||||
          <a-select-option :value="key" :key="key" v-for="(value, key) in valueTypeMap">
 | 
			
		||||
            <ops-icon :type="getPropertyIcon({ value_type: key })" />
 | 
			
		||||
            <span class="value-type-text">{{ value }}</span>
 | 
			
		||||
          </a-select-option>
 | 
			
		||||
        </a-select>
 | 
			
		||||
      </a-form-item></a-col
 | 
			
		||||
      >
 | 
			
		||||
      <a-col :span="currentValueType === '6' ? 24 : 12">
 | 
			
		||||
      <a-col
 | 
			
		||||
        v-if="currentValueType !== '11'"
 | 
			
		||||
        :span="currentValueType === '6' ? 24 : 12"
 | 
			
		||||
      >
 | 
			
		||||
        <a-form-item
 | 
			
		||||
          :label-col="{ span: currentValueType === '6' ? 4 : 8 }"
 | 
			
		||||
          :wrapper-col="{ span: currentValueType === '6' ? 18 : 12 }"
 | 
			
		||||
@@ -77,6 +83,10 @@
 | 
			
		||||
              v-decorator="['default_value', { rules: [{ required: false }] }]"
 | 
			
		||||
            >
 | 
			
		||||
            </a-input>
 | 
			
		||||
            <a-switch
 | 
			
		||||
              v-else-if="currentValueType === '10'"
 | 
			
		||||
              v-decorator="['default_value', { rules: [{ required: false }], valuePropName: 'checked' }]"
 | 
			
		||||
            />
 | 
			
		||||
            <a-select
 | 
			
		||||
              v-decorator="['default_value', { rules: [{ required: false }] }]"
 | 
			
		||||
              mode="tags"
 | 
			
		||||
@@ -95,12 +105,7 @@
 | 
			
		||||
            </a-input-number>
 | 
			
		||||
            <a-input
 | 
			
		||||
              style="width: 100%"
 | 
			
		||||
              v-else-if="
 | 
			
		||||
                currentValueType === '2' ||
 | 
			
		||||
                  currentValueType === '5' ||
 | 
			
		||||
                  currentValueType === '7' ||
 | 
			
		||||
                  currentValueType === '8'
 | 
			
		||||
              "
 | 
			
		||||
              v-else-if="['2', '5', '7', '8', '9'].includes(currentValueType)"
 | 
			
		||||
              v-decorator="['default_value', { rules: [{ required: false }] }]"
 | 
			
		||||
            >
 | 
			
		||||
            </a-input>
 | 
			
		||||
@@ -157,7 +162,18 @@
 | 
			
		||||
        </a-form-item>
 | 
			
		||||
      </a-col>
 | 
			
		||||
 | 
			
		||||
      <a-col :span="currentValueType === '2' ? 6 : 0" v-if="currentValueType !== '6'">
 | 
			
		||||
      <a-col
 | 
			
		||||
        v-if="currentValueType === '11'"
 | 
			
		||||
        :span="12"
 | 
			
		||||
      >
 | 
			
		||||
        <ReferenceModelSelect
 | 
			
		||||
          :form="form"
 | 
			
		||||
          :isLazyRequire="false"
 | 
			
		||||
          :formItemLayout="formItemLayout"
 | 
			
		||||
        />
 | 
			
		||||
      </a-col>
 | 
			
		||||
 | 
			
		||||
      <!-- <a-col :span="currentValueType === '2' ? 6 : 0" v-if="currentValueType !== '6'">
 | 
			
		||||
        <a-form-item
 | 
			
		||||
          :hidden="currentValueType === '2' ? false : true"
 | 
			
		||||
          :label-col="horizontalFormItemLayout.labelCol"
 | 
			
		||||
@@ -189,10 +205,10 @@
 | 
			
		||||
            v-decorator="['is_index', { rules: [], valuePropName: 'checked' }]"
 | 
			
		||||
          />
 | 
			
		||||
        </a-form-item>
 | 
			
		||||
      </a-col>
 | 
			
		||||
      </a-col> -->
 | 
			
		||||
      <a-col :span="6" v-if="currentValueType !== '6' && currentValueType !== '7'">
 | 
			
		||||
        <a-form-item
 | 
			
		||||
          :label-col="currentValueType === '2' ? { span: 8 } : horizontalFormItemLayout.labelCol"
 | 
			
		||||
          :label-col="horizontalFormItemLayout.labelCol"
 | 
			
		||||
          :wrapper-col="horizontalFormItemLayout.wrapperCol"
 | 
			
		||||
          :label="$t('cmdb.ciType.unique')"
 | 
			
		||||
        >
 | 
			
		||||
@@ -206,7 +222,7 @@
 | 
			
		||||
      </a-col>
 | 
			
		||||
      <a-col :span="6">
 | 
			
		||||
        <a-form-item
 | 
			
		||||
          :label-col="['2', '6', '7'].findIndex(i => currentValueType === i) === -1 ? { span: 8 } : horizontalFormItemLayout.labelCol"
 | 
			
		||||
          :label-col="horizontalFormItemLayout.labelCol"
 | 
			
		||||
          :wrapper-col="horizontalFormItemLayout.wrapperCol"
 | 
			
		||||
          :label="$t('required')"
 | 
			
		||||
        >
 | 
			
		||||
@@ -219,7 +235,7 @@
 | 
			
		||||
      </a-col>
 | 
			
		||||
      <a-col :span="6">
 | 
			
		||||
        <a-form-item
 | 
			
		||||
          :label-col="currentValueType === '2' ? { span: 12 } : horizontalFormItemLayout.labelCol"
 | 
			
		||||
          :label-col="horizontalFormItemLayout.labelCol"
 | 
			
		||||
          :wrapper-col="horizontalFormItemLayout.wrapperCol"
 | 
			
		||||
        >
 | 
			
		||||
          <template slot="label">
 | 
			
		||||
@@ -228,8 +244,8 @@
 | 
			
		||||
            >{{ $t('cmdb.ciType.defaultShow') }}
 | 
			
		||||
              <a-tooltip :title="$t('cmdb.ciType.defaultShowTips')">
 | 
			
		||||
                <a-icon
 | 
			
		||||
                  style="position:absolute;top:2px;left:-17px;color:#2f54eb;"
 | 
			
		||||
                  type="question-circle"
 | 
			
		||||
                  style="position:absolute;top:2px;left:-17px;color:#A5A9BC;"
 | 
			
		||||
                  type="info-circle"
 | 
			
		||||
                  theme="filled"
 | 
			
		||||
                  @click="
 | 
			
		||||
                    (e) => {
 | 
			
		||||
@@ -250,7 +266,7 @@
 | 
			
		||||
      </a-col>
 | 
			
		||||
      <a-col :span="6" v-if="currentValueType !== '6' && currentValueType !== '7'">
 | 
			
		||||
        <a-form-item
 | 
			
		||||
          :label-col="currentValueType === '2' ? horizontalFormItemLayout.labelCol : { span: 8 }"
 | 
			
		||||
          :label-col="horizontalFormItemLayout.labelCol"
 | 
			
		||||
          :wrapper-col="horizontalFormItemLayout.wrapperCol"
 | 
			
		||||
          :label="$t('cmdb.ciType.isSortable')"
 | 
			
		||||
        >
 | 
			
		||||
@@ -263,7 +279,7 @@
 | 
			
		||||
        </a-form-item>
 | 
			
		||||
      </a-col>
 | 
			
		||||
 | 
			
		||||
      <a-col :span="6" v-if="currentValueType !== '6' && currentValueType !== '7'">
 | 
			
		||||
      <a-col :span="6" v-if="!['6', '7', '10'].includes(currentValueType)">
 | 
			
		||||
        <a-form-item
 | 
			
		||||
          :label-col="currentValueType === '2' ? { span: 8 } : horizontalFormItemLayout.labelCol"
 | 
			
		||||
          :wrapper-col="horizontalFormItemLayout.wrapperCol"
 | 
			
		||||
@@ -274,8 +290,8 @@
 | 
			
		||||
            >{{ $t('cmdb.ciType.list') }}
 | 
			
		||||
              <a-tooltip :title="$t('cmdb.ciType.listTips')">
 | 
			
		||||
                <a-icon
 | 
			
		||||
                  style="position:absolute;top:3px;left:-17px;color:#2f54eb;"
 | 
			
		||||
                  type="question-circle"
 | 
			
		||||
                  style="position:absolute;top:3px;left:-17px;color:#A5A9BC;"
 | 
			
		||||
                  type="info-circle"
 | 
			
		||||
                  theme="filled"
 | 
			
		||||
                  @click="
 | 
			
		||||
                    (e) => {
 | 
			
		||||
@@ -297,7 +313,7 @@
 | 
			
		||||
      </a-col>
 | 
			
		||||
      <a-col span="6">
 | 
			
		||||
        <a-form-item
 | 
			
		||||
          :label-col="['2', '6', '7'].findIndex(i => currentValueType === i) === -1 ? { span: 12 } : horizontalFormItemLayout.labelCol"
 | 
			
		||||
          :label-col="horizontalFormItemLayout.labelCol"
 | 
			
		||||
          :wrapper-col="horizontalFormItemLayout.wrapperCol"
 | 
			
		||||
        >
 | 
			
		||||
          <template slot="label">
 | 
			
		||||
@@ -306,8 +322,8 @@
 | 
			
		||||
            >{{ $t('cmdb.ciType.isDynamic') }}
 | 
			
		||||
              <a-tooltip :title="$t('cmdb.ciType.dynamicTips')">
 | 
			
		||||
                <a-icon
 | 
			
		||||
                  style="position:absolute;top:3px;left:-17px;color:#2f54eb;"
 | 
			
		||||
                  type="question-circle"
 | 
			
		||||
                  style="position:absolute;top:3px;left:-17px;color:#A5A9BC;"
 | 
			
		||||
                  type="info-circle"
 | 
			
		||||
                  theme="filled"
 | 
			
		||||
                  @click="
 | 
			
		||||
                    (e) => {
 | 
			
		||||
@@ -328,17 +344,22 @@
 | 
			
		||||
      </a-col>
 | 
			
		||||
      <a-divider style="font-size:14px;margin-top:6px;">{{ $t('cmdb.ciType.advancedSettings') }}</a-divider>
 | 
			
		||||
      <a-row>
 | 
			
		||||
        <a-col :span="24" v-if="!['6'].includes(currentValueType)">
 | 
			
		||||
        <a-col :span="24">
 | 
			
		||||
          <a-form-item :label-col="{ span: 4 }" :wrapper-col="{ span: 12 }" :label="$t('cmdb.ciType.reg')">
 | 
			
		||||
            <RegSelect :isShowErrorMsg="false" v-model="re_check" :limitedFormat="getLimitedFormat()" />
 | 
			
		||||
            <RegSelect
 | 
			
		||||
              :isShowErrorMsg="false"
 | 
			
		||||
              :limitedFormat="getLimitedFormat()"
 | 
			
		||||
              :disabled="['6', '10', '11'].includes(currentValueType)"
 | 
			
		||||
              v-model="re_check"
 | 
			
		||||
            />
 | 
			
		||||
          </a-form-item>
 | 
			
		||||
        </a-col>
 | 
			
		||||
        <a-col :span="24">
 | 
			
		||||
          <a-form-item :label-col="{ span: 4 }" :wrapper-col="{ span: 20 }" :label="$t('cmdb.ciType.font')">
 | 
			
		||||
            <FontArea ref="fontArea" />
 | 
			
		||||
            <FontArea ref="fontArea" :fontColorDisabled="['8', '11'].includes(currentValueType)" />
 | 
			
		||||
          </a-form-item>
 | 
			
		||||
        </a-col>
 | 
			
		||||
        <a-col :span="24" v-if="!['6', '7'].includes(currentValueType)">
 | 
			
		||||
        <a-col :span="24" v-if="!['6', '7', '10', '11'].includes(currentValueType)">
 | 
			
		||||
          <a-form-item :label-col="{ span: 4 }" :wrapper-col="{ span: 20 }" :label="$t('cmdb.ciType.choiceValue')">
 | 
			
		||||
            <PreValueArea
 | 
			
		||||
              v-if="drawerVisible"
 | 
			
		||||
@@ -349,7 +370,7 @@
 | 
			
		||||
            />
 | 
			
		||||
          </a-form-item>
 | 
			
		||||
        </a-col>
 | 
			
		||||
        <a-col :span="24" v-if="!['6', '7'].includes(currentValueType)">
 | 
			
		||||
        <a-col :span="24" v-if="!['6', '7', '10', '11'].includes(currentValueType)">
 | 
			
		||||
          <a-form-item :label-col="{ span: 4 }" :wrapper-col="{ span: 20 }">
 | 
			
		||||
            <template slot="label">
 | 
			
		||||
              <span
 | 
			
		||||
@@ -357,8 +378,8 @@
 | 
			
		||||
              >{{ $t('cmdb.ciType.computedAttribute') }}
 | 
			
		||||
                <a-tooltip :title="$t('cmdb.ciType.computedAttributeTips')">
 | 
			
		||||
                  <a-icon
 | 
			
		||||
                    style="position:absolute;top:3px;left:-17px;color:#2f54eb;"
 | 
			
		||||
                    type="question-circle"
 | 
			
		||||
                    style="position:absolute;top:3px;left:-17px;color:#A5A9BC;"
 | 
			
		||||
                    type="info-circle"
 | 
			
		||||
                    theme="filled"
 | 
			
		||||
                    @click="
 | 
			
		||||
                      (e) => {
 | 
			
		||||
@@ -415,14 +436,16 @@ import {
 | 
			
		||||
  calcComputedAttribute,
 | 
			
		||||
} from '@/modules/cmdb/api/CITypeAttr'
 | 
			
		||||
import { valueTypeMap } from '../../utils/const'
 | 
			
		||||
import { getPropertyType, getPropertyIcon } from '../../utils/helper'
 | 
			
		||||
import ComputedArea from './computedArea.vue'
 | 
			
		||||
import PreValueArea from './preValueArea.vue'
 | 
			
		||||
import FontArea from './fontArea.vue'
 | 
			
		||||
import RegSelect from '@/components/RegexSelect'
 | 
			
		||||
import ReferenceModelSelect from './attributeEdit/referenceModelSelect.vue'
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  name: 'AttributeEditForm',
 | 
			
		||||
  components: { ComputedArea, PreValueArea, vueJsonEditor, FontArea, RegSelect },
 | 
			
		||||
  components: { ComputedArea, PreValueArea, vueJsonEditor, FontArea, RegSelect, ReferenceModelSelect },
 | 
			
		||||
  props: {
 | 
			
		||||
    CITypeId: {
 | 
			
		||||
      type: Number,
 | 
			
		||||
@@ -467,7 +490,7 @@ export default {
 | 
			
		||||
      return formLayout === 'horizontal'
 | 
			
		||||
        ? {
 | 
			
		||||
            labelCol: { span: 8 },
 | 
			
		||||
            wrapperCol: { span: 12 },
 | 
			
		||||
            wrapperCol: { span: 15 },
 | 
			
		||||
          }
 | 
			
		||||
        : {}
 | 
			
		||||
    },
 | 
			
		||||
@@ -484,6 +507,7 @@ export default {
 | 
			
		||||
  },
 | 
			
		||||
  mounted() {},
 | 
			
		||||
  methods: {
 | 
			
		||||
    getPropertyIcon,
 | 
			
		||||
    async handleCreate() {
 | 
			
		||||
      try {
 | 
			
		||||
        await canDefineComputed()
 | 
			
		||||
@@ -516,9 +540,7 @@ export default {
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      if (property === 'is_list') {
 | 
			
		||||
        this.form.setFieldsValue({
 | 
			
		||||
          default_value: checked ? [] : '',
 | 
			
		||||
        })
 | 
			
		||||
        this.handleSwitchIsList(checked)
 | 
			
		||||
      }
 | 
			
		||||
      if (checked && property === 'is_sortable') {
 | 
			
		||||
        this.$message.warning(this.$t('cmdb.ciType.addAttributeTips1'))
 | 
			
		||||
@@ -536,6 +558,26 @@ export default {
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    handleSwitchIsList(checked) {
 | 
			
		||||
      let defaultValue = checked ? [] : ''
 | 
			
		||||
 | 
			
		||||
      switch (this.currentValueType) {
 | 
			
		||||
        case '2':
 | 
			
		||||
        case '9':
 | 
			
		||||
          defaultValue = ''
 | 
			
		||||
          break
 | 
			
		||||
        case '10':
 | 
			
		||||
          defaultValue = checked ? '' : false
 | 
			
		||||
          break
 | 
			
		||||
        default:
 | 
			
		||||
          break
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      this.form.setFieldsValue({
 | 
			
		||||
        default_value: defaultValue,
 | 
			
		||||
      })
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    async handleEdit(record, attributes) {
 | 
			
		||||
      try {
 | 
			
		||||
        await canDefineComputed()
 | 
			
		||||
@@ -544,12 +586,7 @@ export default {
 | 
			
		||||
        this.canDefineComputed = false
 | 
			
		||||
      }
 | 
			
		||||
      const _record = _.cloneDeep(record)
 | 
			
		||||
      if (_record.is_password) {
 | 
			
		||||
        _record.value_type = '7'
 | 
			
		||||
      }
 | 
			
		||||
      if (_record.is_link) {
 | 
			
		||||
        _record.value_type = '8'
 | 
			
		||||
      }
 | 
			
		||||
      _record.value_type = getPropertyType(_record)
 | 
			
		||||
      this.drawerTitle = this.$t('cmdb.ciType.editAttribute')
 | 
			
		||||
      this.drawerVisible = true
 | 
			
		||||
      this.record = _record
 | 
			
		||||
@@ -573,8 +610,13 @@ export default {
 | 
			
		||||
            is_dynamic: _record.is_dynamic,
 | 
			
		||||
          })
 | 
			
		||||
        }
 | 
			
		||||
        if (_record.value_type === '11') {
 | 
			
		||||
          this.form.setFieldsValue({
 | 
			
		||||
            reference_type_id: _record.reference_type_id
 | 
			
		||||
          })
 | 
			
		||||
        }
 | 
			
		||||
        console.log(_record)
 | 
			
		||||
        if (!['6'].includes(_record.value_type) && _record.re_check) {
 | 
			
		||||
        if (!['6', '10', '11'].includes(_record.value_type) && _record.re_check) {
 | 
			
		||||
          this.re_check = {
 | 
			
		||||
            value: _record.re_check,
 | 
			
		||||
          }
 | 
			
		||||
@@ -583,7 +625,11 @@ export default {
 | 
			
		||||
        }
 | 
			
		||||
        if (_record.default) {
 | 
			
		||||
          this.$nextTick(() => {
 | 
			
		||||
            if (_record.value_type === '0') {
 | 
			
		||||
            if (_record.value_type === '10') {
 | 
			
		||||
              this.form.setFieldsValue({
 | 
			
		||||
                default_value: Boolean(_record.default.default),
 | 
			
		||||
              })
 | 
			
		||||
            } else if (_record.value_type === '0') {
 | 
			
		||||
              if (_record.is_list) {
 | 
			
		||||
                this.$nextTick(() => {
 | 
			
		||||
                  this.form.setFieldsValue({
 | 
			
		||||
@@ -639,7 +685,7 @@ export default {
 | 
			
		||||
          })
 | 
			
		||||
        }
 | 
			
		||||
        const _find = attributes.find((item) => item.id === _record.id)
 | 
			
		||||
        if (!['6', '7'].includes(_record.value_type)) {
 | 
			
		||||
        if (!['6', '7', '10', '11'].includes(_record.value_type)) {
 | 
			
		||||
          this.$refs.preValueArea.setData({
 | 
			
		||||
            choice_value: (_find || {}).choice_value || [],
 | 
			
		||||
            choice_web_hook: _record.choice_web_hook,
 | 
			
		||||
@@ -672,7 +718,9 @@ export default {
 | 
			
		||||
          delete values['default_show']
 | 
			
		||||
          delete values['is_required']
 | 
			
		||||
          const { default_value } = values
 | 
			
		||||
          if (values.value_type === '0' && default_value) {
 | 
			
		||||
          if (values.value_type === '10') {
 | 
			
		||||
            values.default = { default: values.is_list ? default_value : Boolean(default_value) }
 | 
			
		||||
          } else if (values.value_type === '0' && default_value) {
 | 
			
		||||
            if (values.is_list) {
 | 
			
		||||
              values.default = { default: default_value || null }
 | 
			
		||||
            } else {
 | 
			
		||||
@@ -706,23 +754,42 @@ export default {
 | 
			
		||||
            values = { ...values, ...computedAreaData }
 | 
			
		||||
          } else {
 | 
			
		||||
            // If it is a non-computed attribute, check to see if there is a predefined value
 | 
			
		||||
            if (!['6', '7'].includes(values.value_type)) {
 | 
			
		||||
            if (!['6', '7', '10', '11'].includes(values.value_type)) {
 | 
			
		||||
              const preValueAreaData = this.$refs.preValueArea.getData()
 | 
			
		||||
              values = { ...values, ...preValueAreaData }
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
          const fontOptions = this.$refs.fontArea.getData()
 | 
			
		||||
          if (values.value_type === '7') {
 | 
			
		||||
            values.value_type = '2'
 | 
			
		||||
            values.is_password = true
 | 
			
		||||
          }
 | 
			
		||||
          if (values.value_type === '8') {
 | 
			
		||||
            values.value_type = '2'
 | 
			
		||||
            values.is_link = true
 | 
			
		||||
          }
 | 
			
		||||
          if (values.value_type !== '6') {
 | 
			
		||||
 | 
			
		||||
          if (!['6', '10', '11'].includes(values.value_type)) {
 | 
			
		||||
            values.re_check = this.re_check?.value ?? null
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          // 重置数据类型
 | 
			
		||||
          switch (values.value_type) {
 | 
			
		||||
            case '7':
 | 
			
		||||
              values.value_type = '2'
 | 
			
		||||
              values.is_password = true
 | 
			
		||||
              break
 | 
			
		||||
            case '8':
 | 
			
		||||
              values.value_type = '2'
 | 
			
		||||
              values.is_link = true
 | 
			
		||||
              break
 | 
			
		||||
            case '9':
 | 
			
		||||
              values.value_type = '2'
 | 
			
		||||
              break
 | 
			
		||||
            case '10':
 | 
			
		||||
              values.value_type = '7'
 | 
			
		||||
              values.is_bool = true
 | 
			
		||||
              break
 | 
			
		||||
            case '11':
 | 
			
		||||
              values.value_type = '0'
 | 
			
		||||
              values.is_reference = true
 | 
			
		||||
              break
 | 
			
		||||
            default:
 | 
			
		||||
              break
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          if (values.id) {
 | 
			
		||||
            await this.updateAttribute(values.id, { ...values, option: { fontOptions } }, isCalcComputed)
 | 
			
		||||
          } else {
 | 
			
		||||
@@ -806,6 +873,9 @@ export default {
 | 
			
		||||
  line-height: 22px;
 | 
			
		||||
  color: #a5a9bc;
 | 
			
		||||
}
 | 
			
		||||
.value-type-text {
 | 
			
		||||
  margin-left: 4px;
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
<style lang="less">
 | 
			
		||||
.attribute-edit-form {
 | 
			
		||||
 
 | 
			
		||||
@@ -16,21 +16,21 @@
 | 
			
		||||
      <a-space style="margin-bottom: 10px">
 | 
			
		||||
        <a-button @click="handleAddGroup" size="small" icon="plus">{{ $t('cmdb.ciType.group') }}</a-button>
 | 
			
		||||
        <a-button @click="handleOpenUniqueConstraint" size="small">{{ $t('cmdb.ciType.uniqueConstraint') }}</a-button>
 | 
			
		||||
        <div>
 | 
			
		||||
        <div class="ci-types-attributes-flex">
 | 
			
		||||
          <a-tooltip
 | 
			
		||||
            v-for="typeKey in Object.keys(valueTypeMap)"
 | 
			
		||||
            :key="typeKey"
 | 
			
		||||
            :title="$t('cmdb.ciType.filterTips', { name: valueTypeMap[typeKey] })"
 | 
			
		||||
            v-for="item in valueTypeMap"
 | 
			
		||||
            :key="item.key"
 | 
			
		||||
            :title="$t('cmdb.ciType.filterTips', { name: item.value })"
 | 
			
		||||
          >
 | 
			
		||||
            <span
 | 
			
		||||
              @click="handleFilterType(typeKey)"
 | 
			
		||||
              @click="handleFilterType(item.key)"
 | 
			
		||||
              :class="{
 | 
			
		||||
                'ci-types-attributes-filter': true,
 | 
			
		||||
                'ci-types-attributes-filter-selected': attrTypeFilter.includes(typeKey),
 | 
			
		||||
                'ci-types-attributes-filter-selected': attrTypeFilter.includes(item.key),
 | 
			
		||||
              }"
 | 
			
		||||
            >
 | 
			
		||||
              <ops-icon :type="getPropertyIcon({ value_type: typeKey })" />
 | 
			
		||||
              {{ valueTypeMap[typeKey] }}
 | 
			
		||||
              <ops-icon :type="getPropertyIcon({ value_type: item.key })" />
 | 
			
		||||
              {{ item.value }}
 | 
			
		||||
            </span>
 | 
			
		||||
          </a-tooltip>
 | 
			
		||||
        </div>
 | 
			
		||||
@@ -200,7 +200,7 @@ import AttributeEditForm from './attributeEditForm.vue'
 | 
			
		||||
import NewCiTypeAttrModal from './newCiTypeAttrModal.vue'
 | 
			
		||||
import UniqueConstraint from './uniqueConstraint.vue'
 | 
			
		||||
import { valueTypeMap } from '../../utils/const'
 | 
			
		||||
import { getPropertyIcon } from '../../utils/helper'
 | 
			
		||||
import { getPropertyIcon, getPropertyType } from '../../utils/helper'
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  name: 'AttributesTable',
 | 
			
		||||
@@ -243,7 +243,12 @@ export default {
 | 
			
		||||
      return this.$store.state.windowHeight
 | 
			
		||||
    },
 | 
			
		||||
    valueTypeMap() {
 | 
			
		||||
      return valueTypeMap()
 | 
			
		||||
      const map = valueTypeMap()
 | 
			
		||||
      const keys = ['0', '1', '2', '9', '3', '4', '5', '6', '7', '8', '10', '11']
 | 
			
		||||
      return keys.map((key) => ({
 | 
			
		||||
        key,
 | 
			
		||||
        value: map[key]
 | 
			
		||||
      }))
 | 
			
		||||
    },
 | 
			
		||||
  },
 | 
			
		||||
  provide() {
 | 
			
		||||
@@ -585,23 +590,8 @@ export default {
 | 
			
		||||
        if (!attrTypeFilter.length) {
 | 
			
		||||
          return true
 | 
			
		||||
        } else {
 | 
			
		||||
          if (attrTypeFilter.includes('7') && attr.is_password) {
 | 
			
		||||
            return true
 | 
			
		||||
          }
 | 
			
		||||
          if (attrTypeFilter.includes('8') && attr.is_link) {
 | 
			
		||||
            return true
 | 
			
		||||
          }
 | 
			
		||||
          if (
 | 
			
		||||
            attrTypeFilter.includes(attr.value_type) &&
 | 
			
		||||
            attr.value_type === '2' &&
 | 
			
		||||
            (attr.is_password || attr.is_link)
 | 
			
		||||
          ) {
 | 
			
		||||
            return false
 | 
			
		||||
          }
 | 
			
		||||
          if (attrTypeFilter.includes(attr.value_type)) {
 | 
			
		||||
            return true
 | 
			
		||||
          }
 | 
			
		||||
          return false
 | 
			
		||||
          const valueType = getPropertyType(attr)
 | 
			
		||||
          return attrTypeFilter.includes(valueType)
 | 
			
		||||
        }
 | 
			
		||||
      })
 | 
			
		||||
    },
 | 
			
		||||
@@ -618,6 +608,12 @@ export default {
 | 
			
		||||
.ci-types-attributes {
 | 
			
		||||
  padding: 0 20px;
 | 
			
		||||
  overflow-y: auto;
 | 
			
		||||
 | 
			
		||||
  &-flex {
 | 
			
		||||
    display: flex;
 | 
			
		||||
    flex-wrap: wrap;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .ci-types-attributes-filter {
 | 
			
		||||
    color: @text-color_4;
 | 
			
		||||
    cursor: pointer;
 | 
			
		||||
 
 | 
			
		||||
@@ -46,16 +46,21 @@
 | 
			
		||||
            v-decorator="['value_type', { rules: [{ required: true }], initialValue: '2' }]"
 | 
			
		||||
            @change="handleChangeValueType"
 | 
			
		||||
          >
 | 
			
		||||
            <a-select-option :value="key" :key="key" v-for="(value, key) in valueTypeMap">
 | 
			
		||||
              {{ value }}
 | 
			
		||||
              <span class="value-type-des" v-if="key === '3'">yyyy-mm-dd HH:MM:SS</span>
 | 
			
		||||
              <span class="value-type-des" v-if="key === '4'">yyyy-mm-dd</span>
 | 
			
		||||
              <span class="value-type-des" v-if="key === '5'">HH:MM:SS</span>
 | 
			
		||||
            <a-select-option :value="item.key" :key="item.key" v-for="(item) in valueTypeMap">
 | 
			
		||||
              <ops-icon :type="getPropertyIcon({ value_type: item.key })" />
 | 
			
		||||
              <span class="value-type-text">{{ item.value }}</span>
 | 
			
		||||
              <span class="value-type-des" v-if="item.key === '2'">{{ $t('cmdb.ciType.shortTextTip') }}</span>
 | 
			
		||||
              <span class="value-type-des" v-if="item.key === '3'">yyyy-mm-dd HH:MM:SS</span>
 | 
			
		||||
              <span class="value-type-des" v-if="item.key === '4'">yyyy-mm-dd</span>
 | 
			
		||||
              <span class="value-type-des" v-if="item.key === '5'">HH:MM:SS</span>
 | 
			
		||||
            </a-select-option>
 | 
			
		||||
          </a-select>
 | 
			
		||||
        </a-form-item>
 | 
			
		||||
      </a-col>
 | 
			
		||||
      <a-col :span="currentValueType === '6' ? 24 : 12">
 | 
			
		||||
      <a-col
 | 
			
		||||
        v-if="currentValueType !== '11'"
 | 
			
		||||
        :span="currentValueType === '6' ? 24 : 12"
 | 
			
		||||
      >
 | 
			
		||||
        <a-form-item
 | 
			
		||||
          :label-col="{ span: currentValueType === '6' ? 4 : 8 }"
 | 
			
		||||
          :wrapper-col="{ span: currentValueType === '6' ? 18 : 15 }"
 | 
			
		||||
@@ -68,6 +73,10 @@
 | 
			
		||||
              v-decorator="['default_value', { rules: [{ required: false }] }]"
 | 
			
		||||
            >
 | 
			
		||||
            </a-input>
 | 
			
		||||
            <a-switch
 | 
			
		||||
              v-else-if="currentValueType === '10'"
 | 
			
		||||
              v-decorator="['default_value', { rules: [{ required: false }], valuePropName: 'checked' }]"
 | 
			
		||||
            />
 | 
			
		||||
            <a-input-number
 | 
			
		||||
              style="width: 100%"
 | 
			
		||||
              v-else-if="currentValueType === '1'"
 | 
			
		||||
@@ -86,12 +95,7 @@
 | 
			
		||||
            </a-select>
 | 
			
		||||
            <a-input
 | 
			
		||||
              style="width: 100%"
 | 
			
		||||
              v-else-if="
 | 
			
		||||
                currentValueType === '2' ||
 | 
			
		||||
                  currentValueType === '5' ||
 | 
			
		||||
                  currentValueType === '7' ||
 | 
			
		||||
                  currentValueType === '8'
 | 
			
		||||
              "
 | 
			
		||||
              v-else-if="['2', '5', '7', '8', '9'].includes(currentValueType)"
 | 
			
		||||
              v-decorator="['default_value', { rules: [{ required: false }] }]"
 | 
			
		||||
            >
 | 
			
		||||
            </a-input>
 | 
			
		||||
@@ -148,9 +152,19 @@
 | 
			
		||||
          </template>
 | 
			
		||||
        </a-form-item>
 | 
			
		||||
      </a-col>
 | 
			
		||||
 | 
			
		||||
      <a-col
 | 
			
		||||
        v-if="currentValueType === '11'"
 | 
			
		||||
        :span="12"
 | 
			
		||||
      >
 | 
			
		||||
        <ReferenceModelSelect
 | 
			
		||||
          :form="form"
 | 
			
		||||
          :formItemLayout="formItemLayout"
 | 
			
		||||
        />
 | 
			
		||||
      </a-col>
 | 
			
		||||
    </a-row>
 | 
			
		||||
 | 
			
		||||
    <a-col :span="currentValueType === '2' ? 6 : 0" v-if="currentValueType !== '6'">
 | 
			
		||||
    <!-- <a-col :span="currentValueType === '2' ? 6 : 0" v-if="currentValueType !== '6'">
 | 
			
		||||
      <a-form-item
 | 
			
		||||
        :hidden="currentValueType === '2' ? false : true"
 | 
			
		||||
        :label-col="horizontalFormItemLayout.labelCol"
 | 
			
		||||
@@ -182,10 +196,10 @@
 | 
			
		||||
          v-decorator="['is_index', { rules: [], valuePropName: 'checked', initialValue: true }]"
 | 
			
		||||
        />
 | 
			
		||||
      </a-form-item>
 | 
			
		||||
    </a-col>
 | 
			
		||||
    </a-col> -->
 | 
			
		||||
    <a-col :span="6" v-if="currentValueType !== '6' && currentValueType !== '7'">
 | 
			
		||||
      <a-form-item
 | 
			
		||||
        :label-col="currentValueType === '2' ? { span: 8 } : horizontalFormItemLayout.labelCol"
 | 
			
		||||
        :label-col="horizontalFormItemLayout.labelCol"
 | 
			
		||||
        :wrapper-col="horizontalFormItemLayout.wrapperCol"
 | 
			
		||||
        :label="$t('cmdb.ciType.unique')"
 | 
			
		||||
      >
 | 
			
		||||
@@ -199,7 +213,7 @@
 | 
			
		||||
    </a-col>
 | 
			
		||||
    <a-col :span="6">
 | 
			
		||||
      <a-form-item
 | 
			
		||||
        :label-col="['2', '6', '7'].findIndex(i => currentValueType === i) === -1 ? { span: 8 } : horizontalFormItemLayout.labelCol"
 | 
			
		||||
        :label-col="horizontalFormItemLayout.labelCol"
 | 
			
		||||
        :wrapper-col="horizontalFormItemLayout.wrapperCol"
 | 
			
		||||
        :label="$t('required')"
 | 
			
		||||
      >
 | 
			
		||||
@@ -212,7 +226,7 @@
 | 
			
		||||
    </a-col>
 | 
			
		||||
    <a-col :span="6">
 | 
			
		||||
      <a-form-item
 | 
			
		||||
        :label-col="currentValueType === '2' ? { span: 12 } : horizontalFormItemLayout.labelCol"
 | 
			
		||||
        :label-col="horizontalFormItemLayout.labelCol"
 | 
			
		||||
        :wrapper-col="horizontalFormItemLayout.wrapperCol"
 | 
			
		||||
      >
 | 
			
		||||
        <template slot="label">
 | 
			
		||||
@@ -221,8 +235,8 @@
 | 
			
		||||
          >{{ $t('cmdb.ciType.defaultShow') }}
 | 
			
		||||
            <a-tooltip :title="$t('cmdb.ciType.defaultShowTips')">
 | 
			
		||||
              <a-icon
 | 
			
		||||
                style="position:absolute;top:2px;left:-17px;color:#2f54eb;"
 | 
			
		||||
                type="question-circle"
 | 
			
		||||
                style="position:absolute;top:2px;left:-17px;color:#A5A9BC;"
 | 
			
		||||
                type="info-circle"
 | 
			
		||||
                theme="filled"
 | 
			
		||||
                @click="
 | 
			
		||||
                  (e) => {
 | 
			
		||||
@@ -243,7 +257,7 @@
 | 
			
		||||
    </a-col>
 | 
			
		||||
    <a-col :span="6" v-if="currentValueType !== '6' && currentValueType !== '7'">
 | 
			
		||||
      <a-form-item
 | 
			
		||||
        :label-col="currentValueType === '2' ? horizontalFormItemLayout.labelCol : { span: 8 }"
 | 
			
		||||
        :label-col="horizontalFormItemLayout.labelCol"
 | 
			
		||||
        :wrapper-col="horizontalFormItemLayout.wrapperCol"
 | 
			
		||||
        :label="$t('cmdb.ciType.isSortable')"
 | 
			
		||||
      >
 | 
			
		||||
@@ -256,7 +270,7 @@
 | 
			
		||||
      </a-form-item>
 | 
			
		||||
    </a-col>
 | 
			
		||||
 | 
			
		||||
    <a-col :span="6" v-if="currentValueType !== '6' && currentValueType !== '7'">
 | 
			
		||||
    <a-col :span="6" v-if="!['6', '7', '10'].includes(currentValueType)">
 | 
			
		||||
      <a-form-item
 | 
			
		||||
        :label-col="currentValueType === '2' ? { span: 8 } : horizontalFormItemLayout.labelCol"
 | 
			
		||||
        :wrapper-col="horizontalFormItemLayout.wrapperCol"
 | 
			
		||||
@@ -264,11 +278,11 @@
 | 
			
		||||
        <template slot="label">
 | 
			
		||||
          <span
 | 
			
		||||
            style="position:relative;white-space:pre;"
 | 
			
		||||
          >{{ $t('cmdb.ciType.list') }}
 | 
			
		||||
          >
 | 
			
		||||
            <a-tooltip :title="$t('cmdb.ciType.listTips')">
 | 
			
		||||
              <a-icon
 | 
			
		||||
                style="position:absolute;top:3px;left:-17px;color:#2f54eb;"
 | 
			
		||||
                type="question-circle"
 | 
			
		||||
                style="position:absolute;top:3px;left:-17px;color:#A5A9BC;"
 | 
			
		||||
                type="info-circle"
 | 
			
		||||
                theme="filled"
 | 
			
		||||
                @click="
 | 
			
		||||
                  (e) => {
 | 
			
		||||
@@ -278,6 +292,7 @@
 | 
			
		||||
                "
 | 
			
		||||
              />
 | 
			
		||||
            </a-tooltip>
 | 
			
		||||
            {{ $t('cmdb.ciType.list') }}
 | 
			
		||||
          </span>
 | 
			
		||||
        </template>
 | 
			
		||||
        <a-switch
 | 
			
		||||
@@ -290,17 +305,17 @@
 | 
			
		||||
    </a-col>
 | 
			
		||||
    <a-col span="6">
 | 
			
		||||
      <a-form-item
 | 
			
		||||
        :label-col="['2', '6', '7'].findIndex(i => currentValueType === i) === -1 ? { span: 12 } : horizontalFormItemLayout.labelCol"
 | 
			
		||||
        :label-col="horizontalFormItemLayout.labelCol"
 | 
			
		||||
        :wrapper-col="horizontalFormItemLayout.wrapperCol"
 | 
			
		||||
      >
 | 
			
		||||
        <template slot="label">
 | 
			
		||||
          <span
 | 
			
		||||
            style="position:relative;white-space:pre;"
 | 
			
		||||
          >{{ $t('cmdb.ciType.isDynamic') }}
 | 
			
		||||
          >
 | 
			
		||||
            <a-tooltip :title="$t('cmdb.ciType.dynamicTips')">
 | 
			
		||||
              <a-icon
 | 
			
		||||
                style="position:absolute;top:3px;left:-17px;color:#2f54eb;"
 | 
			
		||||
                type="question-circle"
 | 
			
		||||
                style="position:absolute;top:3px;left:-17px;color:#A5A9BC;"
 | 
			
		||||
                type="info-circle"
 | 
			
		||||
                theme="filled"
 | 
			
		||||
                @click="
 | 
			
		||||
                  (e) => {
 | 
			
		||||
@@ -310,6 +325,7 @@
 | 
			
		||||
                "
 | 
			
		||||
              />
 | 
			
		||||
            </a-tooltip>
 | 
			
		||||
            {{ $t('cmdb.ciType.isDynamic') }}
 | 
			
		||||
          </span>
 | 
			
		||||
        </template>
 | 
			
		||||
        <a-switch
 | 
			
		||||
@@ -321,17 +337,22 @@
 | 
			
		||||
    </a-col>
 | 
			
		||||
    <a-divider style="font-size:14px;margin-top:6px;">{{ $t('cmdb.ciType.advancedSettings') }}</a-divider>
 | 
			
		||||
    <a-row>
 | 
			
		||||
      <a-col :span="24" v-if="!['6'].includes(currentValueType)">
 | 
			
		||||
      <a-col :span="24">
 | 
			
		||||
        <a-form-item :label-col="{ span: 4 }" :wrapper-col="{ span: 12 }" :label="$t('cmdb.ciType.reg')">
 | 
			
		||||
          <RegSelect :isShowErrorMsg="false" v-model="re_check" :limitedFormat="getLimitedFormat()" />
 | 
			
		||||
          <RegSelect
 | 
			
		||||
            v-model="re_check"
 | 
			
		||||
            :isShowErrorMsg="false"
 | 
			
		||||
            :limitedFormat="getLimitedFormat()"
 | 
			
		||||
            :disabled="['6', '10', '11'].includes(currentValueType)"
 | 
			
		||||
          />
 | 
			
		||||
        </a-form-item>
 | 
			
		||||
      </a-col>
 | 
			
		||||
      <a-col :span="24">
 | 
			
		||||
        <a-form-item :label-col="{ span: 4 }" :wrapper-col="{ span: 20 }" :label="$t('cmdb.ciType.font')">
 | 
			
		||||
          <FontArea ref="fontArea" />
 | 
			
		||||
          <FontArea ref="fontArea" :fontColorDisabled="['8', '11'].includes(currentValueType)" />
 | 
			
		||||
        </a-form-item>
 | 
			
		||||
      </a-col>
 | 
			
		||||
      <a-col :span="24" v-if="!['6', '7'].includes(currentValueType)">
 | 
			
		||||
      <a-col :span="24" v-if="!['6', '7', '10', '11'].includes(currentValueType)">
 | 
			
		||||
        <a-form-item :label-col="{ span: 4 }" :wrapper-col="{ span: 20 }" :label="$t('cmdb.ciType.choiceValue')">
 | 
			
		||||
          <PreValueArea
 | 
			
		||||
            ref="preValueArea"
 | 
			
		||||
@@ -341,16 +362,16 @@
 | 
			
		||||
          />
 | 
			
		||||
        </a-form-item>
 | 
			
		||||
      </a-col>
 | 
			
		||||
      <a-col :span="24" v-if="!['6', '7'].includes(currentValueType)">
 | 
			
		||||
      <a-col :span="24" v-if="!['6', '7', '10', '11'].includes(currentValueType)">
 | 
			
		||||
        <a-form-item :label-col="{ span: 4 }" :wrapper-col="{ span: 20 }">
 | 
			
		||||
          <template slot="label">
 | 
			
		||||
            <span
 | 
			
		||||
              style="position:relative;white-space:pre;"
 | 
			
		||||
            >{{ $t('cmdb.ciType.computedAttribute') }}
 | 
			
		||||
            >
 | 
			
		||||
              <a-tooltip :title="$t('cmdb.ciType.computedAttributeTips')">
 | 
			
		||||
                <a-icon
 | 
			
		||||
                  style="position:absolute;top:3px;left:-17px;color:#2f54eb;"
 | 
			
		||||
                  type="question-circle"
 | 
			
		||||
                  style="position:absolute;top:3px;left:-17px;color:#A5A9BC;"
 | 
			
		||||
                  type="info-circle"
 | 
			
		||||
                  theme="filled"
 | 
			
		||||
                  @click="
 | 
			
		||||
                    (e) => {
 | 
			
		||||
@@ -360,6 +381,7 @@
 | 
			
		||||
                  "
 | 
			
		||||
                />
 | 
			
		||||
              </a-tooltip>
 | 
			
		||||
              {{ $t('cmdb.ciType.computedAttribute') }}
 | 
			
		||||
            </span>
 | 
			
		||||
          </template>
 | 
			
		||||
          <a-switch
 | 
			
		||||
@@ -392,6 +414,8 @@ import ComputedArea from './computedArea.vue'
 | 
			
		||||
import PreValueArea from './preValueArea.vue'
 | 
			
		||||
import FontArea from './fontArea.vue'
 | 
			
		||||
import RegSelect from '@/components/RegexSelect'
 | 
			
		||||
import { getPropertyIcon } from '../../utils/helper'
 | 
			
		||||
import ReferenceModelSelect from './attributeEdit/referenceModelSelect.vue'
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  name: 'CreateNewAttribute',
 | 
			
		||||
@@ -401,6 +425,7 @@ export default {
 | 
			
		||||
    vueJsonEditor,
 | 
			
		||||
    FontArea,
 | 
			
		||||
    RegSelect,
 | 
			
		||||
    ReferenceModelSelect,
 | 
			
		||||
  },
 | 
			
		||||
  props: {
 | 
			
		||||
    hasFooter: {
 | 
			
		||||
@@ -437,13 +462,19 @@ export default {
 | 
			
		||||
  },
 | 
			
		||||
  computed: {
 | 
			
		||||
    valueTypeMap() {
 | 
			
		||||
      return valueTypeMap()
 | 
			
		||||
      const map = valueTypeMap()
 | 
			
		||||
      const keys = ['0', '1', '2', '9', '3', '4', '5', '6', '7', '8', '10', '11']
 | 
			
		||||
      return keys.map((key) => ({
 | 
			
		||||
        key,
 | 
			
		||||
        value: map[key]
 | 
			
		||||
      }))
 | 
			
		||||
    },
 | 
			
		||||
    canDefineScript() {
 | 
			
		||||
      return this.canDefineComputed
 | 
			
		||||
    },
 | 
			
		||||
  },
 | 
			
		||||
  methods: {
 | 
			
		||||
    getPropertyIcon,
 | 
			
		||||
    handleSubmit(isCloseModal = true) {
 | 
			
		||||
      this.form.validateFields(async (err, values) => {
 | 
			
		||||
        if (!err) {
 | 
			
		||||
@@ -456,7 +487,9 @@ export default {
 | 
			
		||||
          const data = { is_required, default_show, is_dynamic }
 | 
			
		||||
          delete values.is_required
 | 
			
		||||
          delete values.default_show
 | 
			
		||||
          if (values.value_type === '0' && default_value) {
 | 
			
		||||
          if (values.value_type === '10') {
 | 
			
		||||
            values.default = { default: values.is_list ? (default_value || null) : Boolean(default_value) }
 | 
			
		||||
          } else if (values.value_type === '0' && default_value) {
 | 
			
		||||
            if (values.is_list) {
 | 
			
		||||
              values.default = { default: default_value || null }
 | 
			
		||||
            } else {
 | 
			
		||||
@@ -489,39 +522,48 @@ export default {
 | 
			
		||||
            values = { ...values, ...computedAreaData }
 | 
			
		||||
          } else {
 | 
			
		||||
            // If it is a non-computed attribute, check to see if there is a predefined value
 | 
			
		||||
            if (!['6', '7'].includes(values.value_type)) {
 | 
			
		||||
            if (!['6', '7', '10', '11'].includes(values.value_type)) {
 | 
			
		||||
              const preValueAreaData = this.$refs.preValueArea.getData()
 | 
			
		||||
              values = { ...values, ...preValueAreaData }
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
          const fontOptions = this.$refs.fontArea.getData()
 | 
			
		||||
 | 
			
		||||
          // is_index: except for text, the index is hidden, text index default is true
 | 
			
		||||
          // 5 types in the box,  is_index=true
 | 
			
		||||
          // json, password, link  is_index=false
 | 
			
		||||
          if (['6', '7', '8'].includes(values.value_type)) {
 | 
			
		||||
            values.is_index = false
 | 
			
		||||
          } else if (values.value_type !== '2') {
 | 
			
		||||
            values.is_index = true
 | 
			
		||||
          }
 | 
			
		||||
          if (values.value_type === '7') {
 | 
			
		||||
          // 索引
 | 
			
		||||
          values.is_index = !['6', '7', '8', '9', '11'].includes(values.value_type)
 | 
			
		||||
 | 
			
		||||
          // 重置数据类型
 | 
			
		||||
          switch (values.value_type) {
 | 
			
		||||
            case '7':
 | 
			
		||||
              values.value_type = '2'
 | 
			
		||||
              values.is_password = true
 | 
			
		||||
          }
 | 
			
		||||
          if (values.value_type === '8') {
 | 
			
		||||
              break
 | 
			
		||||
            case '8':
 | 
			
		||||
              values.value_type = '2'
 | 
			
		||||
              values.is_link = true
 | 
			
		||||
              break
 | 
			
		||||
            case '9':
 | 
			
		||||
              values.value_type = '2'
 | 
			
		||||
              break
 | 
			
		||||
            case '10':
 | 
			
		||||
              values.value_type = '7'
 | 
			
		||||
              values.is_bool = true
 | 
			
		||||
              break
 | 
			
		||||
            case '11':
 | 
			
		||||
              values.value_type = '0'
 | 
			
		||||
              values.is_reference = true
 | 
			
		||||
              break
 | 
			
		||||
            default:
 | 
			
		||||
              break
 | 
			
		||||
          }
 | 
			
		||||
          if (values.value_type !== '6') {
 | 
			
		||||
            values.re_check = this.re_check?.value ?? null
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          const { attr_id } = await createAttribute({ ...values, option: { fontOptions } })
 | 
			
		||||
 | 
			
		||||
          this.form.resetFields()
 | 
			
		||||
          this.currentValueType = '2'
 | 
			
		||||
          if (!['6'].includes(values.value_type) && !values.is_password) {
 | 
			
		||||
          if (this?.$refs?.preValueArea) {
 | 
			
		||||
            this.$refs.preValueArea.valueList = []
 | 
			
		||||
          }
 | 
			
		||||
          this.currentValueType = '2'
 | 
			
		||||
          this.$emit('done', attr_id, data, isCloseModal)
 | 
			
		||||
        } else {
 | 
			
		||||
          throw new Error()
 | 
			
		||||
@@ -540,11 +582,12 @@ export default {
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    handleChangeValueType(value) {
 | 
			
		||||
      this.currentValueType = value
 | 
			
		||||
      this.$nextTick(() => {
 | 
			
		||||
        this.form.setFieldsValue({
 | 
			
		||||
          default_value: this.form.getFieldValue('is_list') || value === '0' ? [] : null,
 | 
			
		||||
        })
 | 
			
		||||
        this.currentValueType = value
 | 
			
		||||
        if (['6', '10', '11'].includes(value)) {
 | 
			
		||||
          this.re_check = {}
 | 
			
		||||
        }
 | 
			
		||||
        this.handleSwitchType({ valueType: value })
 | 
			
		||||
      })
 | 
			
		||||
    },
 | 
			
		||||
    onChange(checked, property) {
 | 
			
		||||
@@ -560,9 +603,7 @@ export default {
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      if (property === 'is_list') {
 | 
			
		||||
        this.form.setFieldsValue({
 | 
			
		||||
          default_value: checked ? [] : '',
 | 
			
		||||
        })
 | 
			
		||||
        this.handleSwitchType({ checked })
 | 
			
		||||
      }
 | 
			
		||||
      if (checked && property === 'is_sortable') {
 | 
			
		||||
        this.$message.warning(this.$t('cmdb.ciType.addAttributeTips1'))
 | 
			
		||||
@@ -579,6 +620,33 @@ export default {
 | 
			
		||||
        })
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    handleSwitchType({
 | 
			
		||||
      checked,
 | 
			
		||||
      valueType
 | 
			
		||||
    }) {
 | 
			
		||||
      checked = checked ?? this.form.getFieldValue('is_list')
 | 
			
		||||
      valueType = valueType ?? this.currentValueType
 | 
			
		||||
 | 
			
		||||
      let defaultValue = checked || valueType === '0' ? [] : ''
 | 
			
		||||
 | 
			
		||||
      switch (valueType) {
 | 
			
		||||
        case '2':
 | 
			
		||||
        case '9':
 | 
			
		||||
          defaultValue = ''
 | 
			
		||||
          break
 | 
			
		||||
        case '10':
 | 
			
		||||
          defaultValue = checked ? '' : false
 | 
			
		||||
          break
 | 
			
		||||
        default:
 | 
			
		||||
          break
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      this.form.setFieldsValue({
 | 
			
		||||
        default_value: defaultValue,
 | 
			
		||||
      })
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    onJsonChange(value) {
 | 
			
		||||
      this.default_value_json_right = true
 | 
			
		||||
    },
 | 
			
		||||
@@ -629,6 +697,9 @@ export default {
 | 
			
		||||
  line-height: 22px;
 | 
			
		||||
  color: #a5a9bc;
 | 
			
		||||
}
 | 
			
		||||
.value-type-text {
 | 
			
		||||
  margin: 0 4px;
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
<style lang="less">
 | 
			
		||||
.create-new-attribute {
 | 
			
		||||
 
 | 
			
		||||
@@ -21,7 +21,13 @@
 | 
			
		||||
      <a-icon type="underline" />
 | 
			
		||||
    </div>
 | 
			
		||||
    <div :style="{ width: '100px', marginLeft: '10px', display: 'inline-flex', alignItems: 'center' }">
 | 
			
		||||
      <a-icon type="font-colors" /><el-color-picker size="mini" v-model="fontOptions.color"> </el-color-picker>
 | 
			
		||||
      <a-icon type="font-colors" />
 | 
			
		||||
      <el-color-picker
 | 
			
		||||
        size="mini"
 | 
			
		||||
        :disabled="fontColorDisabled"
 | 
			
		||||
        v-model="fontOptions.color"
 | 
			
		||||
      >
 | 
			
		||||
      </el-color-picker>
 | 
			
		||||
    </div>
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
@@ -30,6 +36,12 @@
 | 
			
		||||
import _ from 'lodash'
 | 
			
		||||
export default {
 | 
			
		||||
  name: 'FontArea',
 | 
			
		||||
  props: {
 | 
			
		||||
    fontColorDisabled: {
 | 
			
		||||
      type: Boolean,
 | 
			
		||||
      default: false
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  data() {
 | 
			
		||||
    return {
 | 
			
		||||
      fontOptions: {
 | 
			
		||||
@@ -57,7 +69,11 @@ export default {
 | 
			
		||||
      if (flag) {
 | 
			
		||||
        return undefined
 | 
			
		||||
      } else {
 | 
			
		||||
        return this.fontOptions
 | 
			
		||||
        const fontOptions = _.cloneDeep(this.fontOptions)
 | 
			
		||||
        if (this.fontColorDisabled) {
 | 
			
		||||
          Reflect.deleteProperty(fontOptions, 'color')
 | 
			
		||||
        }
 | 
			
		||||
        return fontOptions
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    setData({ fontOptions = {} }) {
 | 
			
		||||
 
 | 
			
		||||
@@ -545,7 +545,7 @@ export default {
 | 
			
		||||
    },
 | 
			
		||||
    showIdSelectOptions() {
 | 
			
		||||
      const _showIdSelectOptions = this.currentTypeAttrs.filter(
 | 
			
		||||
        (item) => item.id !== this.unique_id && !['6'].includes(item.value_type) && !item.is_password && !item.is_list
 | 
			
		||||
        (item) => item.id !== this.unique_id && !['6'].includes(item.value_type) && !item.is_password && !item.is_list && !item.is_bool && !item.is_reference
 | 
			
		||||
      )
 | 
			
		||||
      if (this.showIdFilterInput) {
 | 
			
		||||
        return _showIdSelectOptions.filter(
 | 
			
		||||
@@ -898,6 +898,7 @@ export default {
 | 
			
		||||
        this.loadCITypes()
 | 
			
		||||
        this.loading = false
 | 
			
		||||
        this.drawerVisible = false
 | 
			
		||||
        this.isInherit = false
 | 
			
		||||
      }, 1000)
 | 
			
		||||
    },
 | 
			
		||||
    async updateCIType(CITypeId, data) {
 | 
			
		||||
@@ -916,6 +917,7 @@ export default {
 | 
			
		||||
              this.loadCITypes()
 | 
			
		||||
              this.loading = false
 | 
			
		||||
              this.drawerVisible = false
 | 
			
		||||
              this.isInherit = false
 | 
			
		||||
            }, 1000)
 | 
			
		||||
          })
 | 
			
		||||
        })
 | 
			
		||||
 
 | 
			
		||||
@@ -47,9 +47,32 @@
 | 
			
		||||
      >
 | 
			
		||||
        <ops-icon class="text-group-icon" type="veops-text" />
 | 
			
		||||
      </div>
 | 
			
		||||
      <CIReferenceAttr
 | 
			
		||||
        v-if="getAttr(rule.property).is_reference && (rule.exp === 'is' || rule.exp === '~is')"
 | 
			
		||||
        class="select-filter"
 | 
			
		||||
        :referenceTypeId="getAttr(rule.property).reference_type_id"
 | 
			
		||||
        :value="rule.value"
 | 
			
		||||
        :disabled="disabled"
 | 
			
		||||
        @change="(value) => handleChange('value', value)"
 | 
			
		||||
      />
 | 
			
		||||
      <a-select
 | 
			
		||||
        v-else-if="getAttr(rule.property).is_bool && (rule.exp === 'is' || rule.exp === '~is')"
 | 
			
		||||
        class="select-filter"
 | 
			
		||||
        :disabled="disabled"
 | 
			
		||||
        :placeholder="$t('placeholder2')"
 | 
			
		||||
        :value="rule.value"
 | 
			
		||||
        @change="(value) => handleChange('value', value)"
 | 
			
		||||
      >
 | 
			
		||||
        <a-select-option key="1">
 | 
			
		||||
          true
 | 
			
		||||
        </a-select-option>
 | 
			
		||||
        <a-select-option key="0">
 | 
			
		||||
          false
 | 
			
		||||
        </a-select-option>
 | 
			
		||||
      </a-select>
 | 
			
		||||
      <div
 | 
			
		||||
        class="input-group"
 | 
			
		||||
        v-if="isChoiceByProperty(rule.property) && (rule.exp === 'is' || rule.exp === '~is')"
 | 
			
		||||
        v-else-if="isChoiceByProperty(rule.property) && (rule.exp === 'is' || rule.exp === '~is')"
 | 
			
		||||
      >
 | 
			
		||||
        <treeselect
 | 
			
		||||
          class="custom-treeselect"
 | 
			
		||||
@@ -148,9 +171,13 @@
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
import { compareTypeList } from '../constants.js'
 | 
			
		||||
import CIReferenceAttr from '@/components/ciReferenceAttr/index.vue'
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  name: 'ValueControls',
 | 
			
		||||
  components: {
 | 
			
		||||
    CIReferenceAttr
 | 
			
		||||
  },
 | 
			
		||||
  props: {
 | 
			
		||||
    rule: {
 | 
			
		||||
      type: Object,
 | 
			
		||||
@@ -215,7 +242,10 @@ export default {
 | 
			
		||||
        ...this.rule,
 | 
			
		||||
        [key]: value
 | 
			
		||||
      })
 | 
			
		||||
    }
 | 
			
		||||
    },
 | 
			
		||||
    getAttr(property) {
 | 
			
		||||
      return this.attrList.find((item) => item.name === property) || {}
 | 
			
		||||
    },
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
</script>
 | 
			
		||||
@@ -270,4 +300,21 @@ export default {
 | 
			
		||||
    color: #FFFFFF;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.select-filter {
 | 
			
		||||
  height: 36px;
 | 
			
		||||
  width: 136px;
 | 
			
		||||
 | 
			
		||||
  /deep/ .ant-select-selection {
 | 
			
		||||
    height: 36px;
 | 
			
		||||
    background: #f7f8fa;
 | 
			
		||||
    line-height: 36px;
 | 
			
		||||
    border: none;
 | 
			
		||||
 | 
			
		||||
    .ant-select-selection__rendered {
 | 
			
		||||
      height: 36px;
 | 
			
		||||
      line-height: 36px;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
 
 | 
			
		||||
@@ -137,6 +137,7 @@ import {
 | 
			
		||||
  getCITypeChildren,
 | 
			
		||||
  getCITypeParent
 | 
			
		||||
} from '../../api/CITypeRelation.js'
 | 
			
		||||
import { getCITypeAttributesById } from '../../api/CITypeAttr'
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  name: 'RelationAutoDiscovery',
 | 
			
		||||
@@ -169,7 +170,18 @@ export default {
 | 
			
		||||
  methods: {
 | 
			
		||||
    async getCITypeAttributes() {
 | 
			
		||||
      const res = await getCITypeAttributes(this.CITypeId)
 | 
			
		||||
      this.ciTypeADTAttributes = res.map((item) => {
 | 
			
		||||
      const attr = await getCITypeAttributesById(this.CITypeId)
 | 
			
		||||
 | 
			
		||||
      const filterAttr = res.filter((name) => {
 | 
			
		||||
        const currentAttr = attr?.attributes?.find((item) => item?.name === name)
 | 
			
		||||
        if (!currentAttr) {
 | 
			
		||||
          return true
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return this.filterAttributes(name)
 | 
			
		||||
      })
 | 
			
		||||
 | 
			
		||||
      this.ciTypeADTAttributes = filterAttr.map((item) => {
 | 
			
		||||
        return {
 | 
			
		||||
          id: item,
 | 
			
		||||
          value: item,
 | 
			
		||||
@@ -239,7 +251,7 @@ export default {
 | 
			
		||||
        const peer_type_id = item.peer_type_id
 | 
			
		||||
        const attributes = this?.relationOptions?.find((option) => option?.value === peer_type_id)?.attributes
 | 
			
		||||
 | 
			
		||||
        item.attributes = attributes
 | 
			
		||||
        item.attributes = attributes.filter((attr) => this.filterAttributes(attr))
 | 
			
		||||
        item.peer_attr_id = undefined
 | 
			
		||||
      })
 | 
			
		||||
    },
 | 
			
		||||
@@ -288,6 +300,15 @@ export default {
 | 
			
		||||
        this.getCITypeRelations()
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    filterAttributes(attr) {
 | 
			
		||||
      // filter password/json/is_list/longText/bool/reference
 | 
			
		||||
      if (attr?.value_type === '2' && !attr?.is_index) {
 | 
			
		||||
        return false
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      return !attr?.is_password && !attr?.is_list && attr?.value_type !== '6' && !attr?.is_bool && !attr?.is_reference
 | 
			
		||||
    },
 | 
			
		||||
  },
 | 
			
		||||
}
 | 
			
		||||
</script>
 | 
			
		||||
 
 | 
			
		||||
@@ -598,8 +598,14 @@ export default {
 | 
			
		||||
      })
 | 
			
		||||
    },
 | 
			
		||||
    filterAttributes(attributes) {
 | 
			
		||||
      // filter password/json/is_list
 | 
			
		||||
      return attributes.filter((attr) => !attr.is_password && !attr.is_list && attr.value_type !== '6')
 | 
			
		||||
      // filter password/json/is_list/longText/bool/reference
 | 
			
		||||
      return attributes.filter((attr) => {
 | 
			
		||||
        if (attr.value_type === '2' && !attr.is_index) {
 | 
			
		||||
          return false
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return !attr.is_password && !attr.is_list && attr.value_type !== '6' && !attr.is_bool && !attr.is_reference
 | 
			
		||||
      })
 | 
			
		||||
    },
 | 
			
		||||
    addTableAttr() {
 | 
			
		||||
      this.tableAttrList.push({
 | 
			
		||||
 
 | 
			
		||||
@@ -471,10 +471,15 @@ export default {
 | 
			
		||||
      this.dateForm = _.cloneDeep(this.defaultDateForm)
 | 
			
		||||
      this.notifies = _.cloneDeep(this.defaultNotify)
 | 
			
		||||
      this.category = 1
 | 
			
		||||
      this.triggerAction = '1'
 | 
			
		||||
      this.filterExp = ''
 | 
			
		||||
      this.selectedBot = undefined
 | 
			
		||||
      if (this.$refs.noticeContent) {
 | 
			
		||||
        this.$refs.noticeContent.destroy()
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      this.$nextTick(() => {
 | 
			
		||||
        this.visible = false
 | 
			
		||||
      })
 | 
			
		||||
    },
 | 
			
		||||
    filterChange(value) {
 | 
			
		||||
      this.filterValue = value
 | 
			
		||||
 
 | 
			
		||||
@@ -364,8 +364,14 @@ export default {
 | 
			
		||||
      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')
 | 
			
		||||
      // filter password/json/is_list/longText/bool/reference
 | 
			
		||||
      return attributes.filter((attr) => {
 | 
			
		||||
        if (attr.value_type === '2' && !attr.is_index) {
 | 
			
		||||
          return false
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return !attr.is_password && !attr.is_list && attr.value_type !== '6' && !attr.is_bool && !attr.is_reference
 | 
			
		||||
      })
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    addModalAttr() {
 | 
			
		||||
 
 | 
			
		||||
@@ -306,8 +306,14 @@ export default {
 | 
			
		||||
      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')
 | 
			
		||||
      // filter password/json/is_list/longText/bool/reference
 | 
			
		||||
      return attributes.filter((attr) => {
 | 
			
		||||
        if (attr.value_type === '2' && !attr.is_index) {
 | 
			
		||||
          return false
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return !attr.is_password && !attr.is_list && attr.value_type !== '6' && !attr.is_bool && !attr.is_reference
 | 
			
		||||
      })
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    addTableAttr() {
 | 
			
		||||
 
 | 
			
		||||
@@ -53,8 +53,18 @@
 | 
			
		||||
            :width="col.width"
 | 
			
		||||
            :sortable="col.sortable"
 | 
			
		||||
          >
 | 
			
		||||
            <template #default="{row}" v-if="col.value_type === '6'">
 | 
			
		||||
              <span v-if="col.value_type === '6' && row[col.field]">{{ JSON.stringify(row[col.field]) }}</span>
 | 
			
		||||
            <template v-if="col.is_reference" #default="{row}">
 | 
			
		||||
              <a
 | 
			
		||||
                v-for="(id) in (col.is_list ? row[col.field] : [row[col.field]])"
 | 
			
		||||
                :key="id"
 | 
			
		||||
                :href="`/cmdb/cidetail/${col.reference_type_id}/${id}`"
 | 
			
		||||
                target="_blank"
 | 
			
		||||
              >
 | 
			
		||||
                {{ id }}
 | 
			
		||||
              </a>
 | 
			
		||||
            </template>
 | 
			
		||||
            <template #default="{row}" v-else-if="col.value_type == '6'">
 | 
			
		||||
              <span v-if="col.value_type == '6' && row[col.field]">{{ JSON.stringify(row[col.field]) }}</span>
 | 
			
		||||
            </template>
 | 
			
		||||
          </vxe-table-column>
 | 
			
		||||
        </vxe-table>
 | 
			
		||||
 
 | 
			
		||||
@@ -101,8 +101,18 @@
 | 
			
		||||
          :minWidth="100"
 | 
			
		||||
          :cell-type="col.value_type === '2' ? 'string' : 'auto'"
 | 
			
		||||
        >
 | 
			
		||||
          <template v-if="col.value_type === '6' || col.is_link || col.is_password || col.is_choice" #default="{row}">
 | 
			
		||||
            <span v-if="col.value_type === '6' && row[col.field]">{{ JSON.stringify(row[col.field]) }}</span>
 | 
			
		||||
          <template v-if="col.value_type === '6' || col.is_link || col.is_password || col.is_choice || col.is_reference" #default="{row}">
 | 
			
		||||
            <template v-if="col.is_reference && row[col.field]" >
 | 
			
		||||
              <a
 | 
			
		||||
                v-for="(ciId) in (col.is_list ? row[col.field] : [row[col.field]])"
 | 
			
		||||
                :key="ciId"
 | 
			
		||||
                :href="`/cmdb/cidetail/${col.reference_type_id}/${ciId}`"
 | 
			
		||||
                target="_blank"
 | 
			
		||||
              >
 | 
			
		||||
                {{ getReferenceAttrValue(ciId, col) }}
 | 
			
		||||
              </a>
 | 
			
		||||
            </template>
 | 
			
		||||
            <span v-else-if="col.value_type === '6' && row[col.field]">{{ JSON.stringify(row[col.field]) }}</span>
 | 
			
		||||
            <template v-else-if="col.is_link && row[col.field]">
 | 
			
		||||
              <a
 | 
			
		||||
                v-for="(item, linkIndex) in (col.is_list ? row[col.field] : [row[col.field]])"
 | 
			
		||||
@@ -254,6 +264,8 @@ export default {
 | 
			
		||||
      sortByTable: undefined,
 | 
			
		||||
      loading: false,
 | 
			
		||||
      columnsGroup: [],
 | 
			
		||||
      referenceShowAttrNameMap: {},
 | 
			
		||||
      referenceCIIdMap: {},
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  computed: {
 | 
			
		||||
@@ -433,12 +445,99 @@ export default {
 | 
			
		||||
          await Promise.all(promises1).then(() => {
 | 
			
		||||
            this.columnsGroup = [..._commonColumnsGroup, ..._columnsGroup]
 | 
			
		||||
            this.instanceList = res['result']
 | 
			
		||||
            this.handlePerference()
 | 
			
		||||
          })
 | 
			
		||||
        })
 | 
			
		||||
        .finally(() => {
 | 
			
		||||
          this.loading = false
 | 
			
		||||
        })
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    handlePerference() {
 | 
			
		||||
      let needRequiredCIType = []
 | 
			
		||||
      this.columnsGroup.forEach((group) => {
 | 
			
		||||
        group.children.forEach((col) => {
 | 
			
		||||
          if (col?.is_reference && col?.reference_type_id) {
 | 
			
		||||
            needRequiredCIType.push(col)
 | 
			
		||||
          }
 | 
			
		||||
        })
 | 
			
		||||
      })
 | 
			
		||||
      needRequiredCIType = _.uniq(needRequiredCIType)
 | 
			
		||||
 | 
			
		||||
      if (!needRequiredCIType.length) {
 | 
			
		||||
        this.referenceShowAttrNameMap = {}
 | 
			
		||||
        this.referenceCIIdMap = {}
 | 
			
		||||
        return
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      this.handleReferenceShowAttrName(needRequiredCIType)
 | 
			
		||||
      this.handleReferenceCIIdMap(needRequiredCIType)
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    async handleReferenceShowAttrName(needRequiredCIType) {
 | 
			
		||||
      const res = await getCITypes({
 | 
			
		||||
        type_ids: needRequiredCIType.map((col) => col.reference_type_id).join(',')
 | 
			
		||||
      })
 | 
			
		||||
 | 
			
		||||
      const map = {}
 | 
			
		||||
      res.ci_types.forEach((ciType) => {
 | 
			
		||||
        map[ciType.id] = ciType?.show_name || ciType?.unique_name || ''
 | 
			
		||||
      })
 | 
			
		||||
 | 
			
		||||
      this.referenceShowAttrNameMap = map
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    async handleReferenceCIIdMap(needRequiredCIType) {
 | 
			
		||||
      const map = {}
 | 
			
		||||
      this.instanceList.forEach((row) => {
 | 
			
		||||
        needRequiredCIType.forEach((col) => {
 | 
			
		||||
          const ids = Array.isArray(row[col.field]) ? row[col.field] : row[col.field] ? [row[col.field]] : []
 | 
			
		||||
          if (ids.length) {
 | 
			
		||||
            if (!map?.[col.reference_type_id]) {
 | 
			
		||||
              map[col.reference_type_id] = {}
 | 
			
		||||
            }
 | 
			
		||||
            ids.forEach((id) => {
 | 
			
		||||
              map[col.reference_type_id][id] = {}
 | 
			
		||||
            })
 | 
			
		||||
          }
 | 
			
		||||
        })
 | 
			
		||||
      })
 | 
			
		||||
 | 
			
		||||
      if (!Object.keys(map).length) {
 | 
			
		||||
        this.referenceCIIdMap = {}
 | 
			
		||||
        return
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      const allRes = await Promise.all(
 | 
			
		||||
        Object.keys(map).map((key) => {
 | 
			
		||||
          return searchCI({
 | 
			
		||||
            q: `_type:${key},_id:(${Object.keys(map[key]).join(';')})`,
 | 
			
		||||
            count: 9999
 | 
			
		||||
          })
 | 
			
		||||
        })
 | 
			
		||||
      )
 | 
			
		||||
 | 
			
		||||
      allRes.forEach((res) => {
 | 
			
		||||
        res.result.forEach((item) => {
 | 
			
		||||
          if (map?.[item._type]?.[item._id]) {
 | 
			
		||||
            map[item._type][item._id] = item
 | 
			
		||||
          }
 | 
			
		||||
        })
 | 
			
		||||
      })
 | 
			
		||||
 | 
			
		||||
      this.referenceCIIdMap = map
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    getReferenceAttrValue(id, col) {
 | 
			
		||||
      const ci = this?.referenceCIIdMap?.[col?.reference_type_id]?.[id]
 | 
			
		||||
      if (!ci) {
 | 
			
		||||
        return id
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      const attrName = this.referenceShowAttrNameMap?.[col.reference_type_id]
 | 
			
		||||
      return ci?.[attrName] || id
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    getColumns(data, attrList) {
 | 
			
		||||
      const width = document.getElementById('resource_search').clientWidth - 50
 | 
			
		||||
      return getCITableColumns(data, attrList, width).map((item) => {
 | 
			
		||||
 
 | 
			
		||||
@@ -14,7 +14,7 @@ export default {
 | 
			
		||||
  name: 'TreeViewsNode',
 | 
			
		||||
  props: {
 | 
			
		||||
    title: {
 | 
			
		||||
      type: [String, Number],
 | 
			
		||||
      type: [String, Number, Boolean],
 | 
			
		||||
      default: '',
 | 
			
		||||
    },
 | 
			
		||||
    treeKey: {
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user