mirror of
				https://github.com/veops/cmdb.git
				synced 2025-11-04 13:46:17 +08:00 
			
		
		
		
	
							
								
								
									
										
											BIN
										
									
								
								cmdb-ui/src/modules/cmdb/assets/dashboard_empty.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								cmdb-ui/src/modules/cmdb/assets/dashboard_empty.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 85 KiB  | 
@@ -32,19 +32,28 @@
 | 
			
		||||
      v-if="options.chartType === 'table'"
 | 
			
		||||
      :span-method="mergeRowMethod"
 | 
			
		||||
      :border="!options.ret"
 | 
			
		||||
      :show-header="!!options.ret"
 | 
			
		||||
      show-overflow
 | 
			
		||||
      show-header-overflow
 | 
			
		||||
    >
 | 
			
		||||
      <template v-if="options.ret">
 | 
			
		||||
        <vxe-column v-for="col in columns" :key="col" :title="col" :field="col"></vxe-column>
 | 
			
		||||
        <vxe-column v-for="col in columns" :key="col" :title="col" :field="col">
 | 
			
		||||
          <template #default="{ row }">
 | 
			
		||||
            <span>{{ row[col] }}</span>
 | 
			
		||||
          </template>
 | 
			
		||||
        </vxe-column>
 | 
			
		||||
      </template>
 | 
			
		||||
      <template v-else>
 | 
			
		||||
        <vxe-column
 | 
			
		||||
          v-for="(key, index) in Array(keyLength)"
 | 
			
		||||
          :key="`key${index}`"
 | 
			
		||||
          :title="`key${index}`"
 | 
			
		||||
          :title="columnName[index]"
 | 
			
		||||
          :field="`key${index}`"
 | 
			
		||||
        ></vxe-column>
 | 
			
		||||
        <vxe-column field="value" title="value"></vxe-column>
 | 
			
		||||
        >
 | 
			
		||||
          <template #default="{ row }">
 | 
			
		||||
            <span>{{ row[`key${index}`] }}</span>
 | 
			
		||||
          </template>
 | 
			
		||||
        </vxe-column>
 | 
			
		||||
        <vxe-column field="value" title="数量"></vxe-column>
 | 
			
		||||
      </template>
 | 
			
		||||
    </vxe-table>
 | 
			
		||||
    <div
 | 
			
		||||
@@ -66,6 +75,8 @@ import {
 | 
			
		||||
  category_2_bar_options,
 | 
			
		||||
  category_2_pie_options,
 | 
			
		||||
} from './chartOptions'
 | 
			
		||||
import { getCITypeAttributesByTypeIds } from '../../api/CITypeAttr'
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  name: 'Chart',
 | 
			
		||||
  mixins: [mixin],
 | 
			
		||||
@@ -110,6 +121,8 @@ export default {
 | 
			
		||||
      tableHeight: '',
 | 
			
		||||
      tableData: [],
 | 
			
		||||
      keyLength: 0,
 | 
			
		||||
      attributes: [],
 | 
			
		||||
      columnName: [],
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  computed: {
 | 
			
		||||
@@ -149,10 +162,19 @@ export default {
 | 
			
		||||
              this.tableData = newValue
 | 
			
		||||
            }
 | 
			
		||||
          } else {
 | 
			
		||||
            const _data = []
 | 
			
		||||
            this.keyLength = this.options?.attr_ids?.length ?? 0
 | 
			
		||||
            this.formatTableData(_data, this.data, {})
 | 
			
		||||
            this.tableData = _data
 | 
			
		||||
            getCITypeAttributesByTypeIds({ type_ids: this.options?.type_ids.join(',') }).then((res) => {
 | 
			
		||||
              this.attributes = res.attributes
 | 
			
		||||
              const _data = []
 | 
			
		||||
              this.keyLength = this.options?.attr_ids?.length ?? 0
 | 
			
		||||
              const _columnName = []
 | 
			
		||||
              this.options.attr_ids.forEach((attr) => {
 | 
			
		||||
                const _find = this.attributes.find((item) => item.id === attr)
 | 
			
		||||
                _columnName.push(_find?.alias || _find?.name)
 | 
			
		||||
              })
 | 
			
		||||
              this.columnName = _columnName
 | 
			
		||||
              this.formatTableData(_data, this.data, {})
 | 
			
		||||
              this.tableData = _data
 | 
			
		||||
            })
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
@@ -248,15 +270,15 @@ export default {
 | 
			
		||||
  }
 | 
			
		||||
  .cmdb-dashboard-grid-item-chart-icon {
 | 
			
		||||
    > i {
 | 
			
		||||
      font-size: 4vw;
 | 
			
		||||
      font-size: 40px;
 | 
			
		||||
    }
 | 
			
		||||
    > img {
 | 
			
		||||
      width: 4vw;
 | 
			
		||||
      width: 40px;
 | 
			
		||||
    }
 | 
			
		||||
    > span {
 | 
			
		||||
      display: inline-block;
 | 
			
		||||
      width: 4vw;
 | 
			
		||||
      height: 4vw;
 | 
			
		||||
      width: 40px;
 | 
			
		||||
      height: 40px;
 | 
			
		||||
      font-size: 50px;
 | 
			
		||||
      text-align: center;
 | 
			
		||||
      line-height: 50px;
 | 
			
		||||
 
 | 
			
		||||
@@ -82,7 +82,14 @@
 | 
			
		||||
            prop="attr_ids"
 | 
			
		||||
            v-if="(['bar', 'line', 'pie'].includes(chartType) && form.category === 1) || chartType === 'table'"
 | 
			
		||||
          >
 | 
			
		||||
            <a-select @change="changeAttr" v-model="form.attr_ids" placeholder="请选择维度" mode="multiple" show-search>
 | 
			
		||||
            <a-select
 | 
			
		||||
              :filter-option="filterOption"
 | 
			
		||||
              @change="changeAttr"
 | 
			
		||||
              v-model="form.attr_ids"
 | 
			
		||||
              placeholder="请选择维度"
 | 
			
		||||
              mode="multiple"
 | 
			
		||||
              show-search
 | 
			
		||||
            >
 | 
			
		||||
              <a-select-option v-for="attr in commonAttributes" :key="attr.id" :value="attr.id">{{
 | 
			
		||||
                attr.alias || attr.name
 | 
			
		||||
              }}</a-select-option>
 | 
			
		||||
@@ -116,7 +123,7 @@
 | 
			
		||||
              </a-select-opt-group>
 | 
			
		||||
            </a-select>
 | 
			
		||||
          </a-form-model-item>
 | 
			
		||||
          <div class="chart-left-preview">
 | 
			
		||||
          <div :class="{ 'chart-left-preview': true, 'chart-left-preview-empty': !isShowPreview }">
 | 
			
		||||
            <span class="chart-left-preview-operation" @click="showPreview"><a-icon type="play-circle" /> 预览</span>
 | 
			
		||||
            <template v-if="isShowPreview">
 | 
			
		||||
              <div v-if="chartType !== 'count'" class="cmdb-dashboard-grid-item-title">
 | 
			
		||||
@@ -170,6 +177,7 @@
 | 
			
		||||
                    type_ids: form.type_ids,
 | 
			
		||||
                    attr_ids: form.attr_ids,
 | 
			
		||||
                    isShadow: isShadow,
 | 
			
		||||
                    ret: form.tableCategory === 2 ? 'cis' : '',
 | 
			
		||||
                  }"
 | 
			
		||||
                  :editable="false"
 | 
			
		||||
                  :ci_types="ci_types"
 | 
			
		||||
@@ -464,10 +472,12 @@ export default {
 | 
			
		||||
    changeCIType(value) {
 | 
			
		||||
      this.form.attr_ids = []
 | 
			
		||||
      this.commonAttributes = []
 | 
			
		||||
      getCITypeAttributesByTypeIds({ type_ids: Array.isArray(value) ? value.join(',') : value }).then((res) => {
 | 
			
		||||
        this.attributes = res.attributes
 | 
			
		||||
      })
 | 
			
		||||
      if (!Array.isArray(value)) {
 | 
			
		||||
      if ((Array.isArray(value) && value.length) || (!Array.isArray(value) && value)) {
 | 
			
		||||
        getCITypeAttributesByTypeIds({ type_ids: Array.isArray(value) ? value.join(',') : value }).then((res) => {
 | 
			
		||||
          this.attributes = res.attributes
 | 
			
		||||
        })
 | 
			
		||||
      }
 | 
			
		||||
      if (!Array.isArray(value) && value) {
 | 
			
		||||
        getRecursive_level2children(value).then((res) => {
 | 
			
		||||
          this.level2children = res
 | 
			
		||||
        })
 | 
			
		||||
@@ -523,6 +533,7 @@ export default {
 | 
			
		||||
            delete params.attr_ids
 | 
			
		||||
            delete params.tableCategory
 | 
			
		||||
            await putCustomDashboard(this.item.id, params)
 | 
			
		||||
            this.$emit('refresh', this.item.id)
 | 
			
		||||
          } else {
 | 
			
		||||
            const { xLast, yLast, wLast } = getLastLayout(this.layout())
 | 
			
		||||
            const w = this.width
 | 
			
		||||
@@ -581,6 +592,9 @@ export default {
 | 
			
		||||
    //   }
 | 
			
		||||
    // },
 | 
			
		||||
    changeChartType(t) {
 | 
			
		||||
      if (!(['bar', 'line', 'pie'].includes(this.chartType) && ['bar', 'line', 'pie'].includes(t.value))) {
 | 
			
		||||
        this.resetForm()
 | 
			
		||||
      }
 | 
			
		||||
      this.chartType = t.value
 | 
			
		||||
      this.isShowPreview = false
 | 
			
		||||
      if (t.value === 'count') {
 | 
			
		||||
@@ -588,7 +602,6 @@ export default {
 | 
			
		||||
      } else {
 | 
			
		||||
        this.form.category = 1
 | 
			
		||||
      }
 | 
			
		||||
      this.resetForm()
 | 
			
		||||
    },
 | 
			
		||||
    showPreview() {
 | 
			
		||||
      this.$refs.chartForm.validate(async (valid) => {
 | 
			
		||||
@@ -673,6 +686,9 @@ export default {
 | 
			
		||||
      }
 | 
			
		||||
      this.form.level = level
 | 
			
		||||
    },
 | 
			
		||||
    filterOption(input, option) {
 | 
			
		||||
      return option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0
 | 
			
		||||
    },
 | 
			
		||||
  },
 | 
			
		||||
}
 | 
			
		||||
</script>
 | 
			
		||||
@@ -702,6 +718,13 @@ export default {
 | 
			
		||||
        border-radius: 8px;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    .chart-left-preview-empty {
 | 
			
		||||
      background: url('../../assets/dashboard_empty.png');
 | 
			
		||||
      background-size: contain;
 | 
			
		||||
      background-repeat: no-repeat;
 | 
			
		||||
      background-position-x: center;
 | 
			
		||||
      background-position-y: center;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  .chart-right {
 | 
			
		||||
    width: 50%;
 | 
			
		||||
 
 | 
			
		||||
@@ -23,6 +23,7 @@ export const category_1_bar_options = (data, options) => {
 | 
			
		||||
        })
 | 
			
		||||
    })
 | 
			
		||||
    return {
 | 
			
		||||
 | 
			
		||||
        color: options.chartColor.split(','),
 | 
			
		||||
        grid: {
 | 
			
		||||
            top: 15,
 | 
			
		||||
@@ -58,6 +59,7 @@ export const category_1_bar_options = (data, options) => {
 | 
			
		||||
            data: xData
 | 
			
		||||
        },
 | 
			
		||||
        tooltip: {
 | 
			
		||||
            appendToBody: true,
 | 
			
		||||
            trigger: 'axis',
 | 
			
		||||
            axisPointer: {
 | 
			
		||||
                type: 'shadow'
 | 
			
		||||
@@ -65,7 +67,7 @@ export const category_1_bar_options = (data, options) => {
 | 
			
		||||
        },
 | 
			
		||||
        series: Object.keys(secondCategory).map(key => {
 | 
			
		||||
            return {
 | 
			
		||||
                name: key,
 | 
			
		||||
                name: options.attr_ids.length === 1 ? '' : key,
 | 
			
		||||
                type: 'bar',
 | 
			
		||||
                stack: options?.barStack ?? 'total',
 | 
			
		||||
                barGap: 0,
 | 
			
		||||
@@ -90,6 +92,7 @@ export const category_1_line_options = (data, options) => {
 | 
			
		||||
            containLabel: true,
 | 
			
		||||
        },
 | 
			
		||||
        tooltip: {
 | 
			
		||||
            appendToBody: true,
 | 
			
		||||
            trigger: 'axis'
 | 
			
		||||
        },
 | 
			
		||||
        xAxis: {
 | 
			
		||||
@@ -137,6 +140,7 @@ export const category_1_pie_options = (data, options) => {
 | 
			
		||||
            containLabel: true,
 | 
			
		||||
        },
 | 
			
		||||
        tooltip: {
 | 
			
		||||
            appendToBody: true,
 | 
			
		||||
            trigger: 'item'
 | 
			
		||||
        },
 | 
			
		||||
        legend: {
 | 
			
		||||
@@ -186,6 +190,7 @@ export const category_2_bar_options = (data, options, chartType) => {
 | 
			
		||||
            containLabel: true,
 | 
			
		||||
        },
 | 
			
		||||
        tooltip: {
 | 
			
		||||
            appendToBody: true,
 | 
			
		||||
            trigger: 'axis',
 | 
			
		||||
            axisPointer: {
 | 
			
		||||
                type: 'shadow'
 | 
			
		||||
@@ -257,7 +262,6 @@ export const category_2_bar_options = (data, options, chartType) => {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const category_2_pie_options = (data, options) => {
 | 
			
		||||
    console.log(1111, options)
 | 
			
		||||
    const _legend = []
 | 
			
		||||
    Object.keys(data.detail).forEach(key => {
 | 
			
		||||
        Object.keys(data.detail[key]).forEach(key2 => {
 | 
			
		||||
@@ -274,6 +278,7 @@ export const category_2_pie_options = (data, options) => {
 | 
			
		||||
            containLabel: true,
 | 
			
		||||
        },
 | 
			
		||||
        tooltip: {
 | 
			
		||||
            appendToBody: true,
 | 
			
		||||
            trigger: 'item'
 | 
			
		||||
        },
 | 
			
		||||
        legend: {
 | 
			
		||||
 
 | 
			
		||||
@@ -11,13 +11,12 @@
 | 
			
		||||
    <template v-if="layout && layout.length">
 | 
			
		||||
      <div v-if="editable">
 | 
			
		||||
        <a-button
 | 
			
		||||
          :style="{ marginLeft: '22px', marginTop: '20px' }"
 | 
			
		||||
          :style="{ marginLeft: '22px', marginTop: '20px', backgroundColor: '#D6E9FF', boxShadow: 'none' }"
 | 
			
		||||
          @click="openChartForm('add', { options: { w: 3 } })"
 | 
			
		||||
          ghost
 | 
			
		||||
          type="primary"
 | 
			
		||||
          size="small"
 | 
			
		||||
          icon="plus"
 | 
			
		||||
        >新增</a-button
 | 
			
		||||
          icon="plus-circle"
 | 
			
		||||
          class="ops-button-primary"
 | 
			
		||||
        >新增图表</a-button
 | 
			
		||||
        >
 | 
			
		||||
      </div>
 | 
			
		||||
      <GridLayout
 | 
			
		||||
@@ -199,8 +198,14 @@ export default {
 | 
			
		||||
      console.log(type, item)
 | 
			
		||||
      this.$refs.chartForm.open(type, item)
 | 
			
		||||
    },
 | 
			
		||||
    refresh() {
 | 
			
		||||
      this.getLayout()
 | 
			
		||||
    refresh(id) {
 | 
			
		||||
      if (id) {
 | 
			
		||||
        setTimeout(() => {
 | 
			
		||||
          this.$refs[`chart_${id}`][0].resizeChart()
 | 
			
		||||
        }, 100)
 | 
			
		||||
      } else {
 | 
			
		||||
        this.getLayout()
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    deleteChart(item) {
 | 
			
		||||
      const that = this
 | 
			
		||||
@@ -299,4 +304,7 @@ export default {
 | 
			
		||||
    margin-right: 5px;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
.ops-button-primary:hover {
 | 
			
		||||
  background-color: #2f54eb !important;
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user