mirror of https://github.com/veops/cmdb.git
dashboard ui update
This commit is contained in:
parent
737b29f7d6
commit
47dbe5ba18
|
@ -68,7 +68,8 @@ export default {
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
visibleChange(open) {
|
visibleChange(open, isInitOne = true) {
|
||||||
|
// isInitOne 初始化exp为空时,ruleList是否默认给一条
|
||||||
// const regQ = /(?<=q=).+(?=&)|(?<=q=).+$/g
|
// const regQ = /(?<=q=).+(?=&)|(?<=q=).+$/g
|
||||||
const exp = this.expression.match(new RegExp(this.regQ, 'g'))
|
const exp = this.expression.match(new RegExp(this.regQ, 'g'))
|
||||||
? this.expression.match(new RegExp(this.regQ, 'g'))[0]
|
? this.expression.match(new RegExp(this.regQ, 'g'))[0]
|
||||||
|
@ -151,15 +152,20 @@ export default {
|
||||||
})
|
})
|
||||||
this.ruleList = [...expArray]
|
this.ruleList = [...expArray]
|
||||||
} else if (open) {
|
} else if (open) {
|
||||||
this.ruleList = [
|
this.ruleList = isInitOne
|
||||||
{
|
? [
|
||||||
id: uuidv4(),
|
{
|
||||||
type: 'and',
|
id: uuidv4(),
|
||||||
property: this.canSearchPreferenceAttrList[0].name,
|
type: 'and',
|
||||||
exp: 'is',
|
property:
|
||||||
value: null,
|
this.canSearchPreferenceAttrList && this.canSearchPreferenceAttrList.length
|
||||||
},
|
? this.canSearchPreferenceAttrList[0].name
|
||||||
]
|
: undefined,
|
||||||
|
exp: 'is',
|
||||||
|
value: null,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
: []
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
handleClear() {
|
handleClear() {
|
||||||
|
|
|
@ -77,6 +77,14 @@ export function getCITypeAttributesByTypeIds(params) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getCITypeCommonAttributesByTypeIds(params) {
|
||||||
|
return axios({
|
||||||
|
url: `/v0.1/ci_types/common_attributes`,
|
||||||
|
method: 'get',
|
||||||
|
params: params
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 删除属性
|
* 删除属性
|
||||||
* @param attrId
|
* @param attrId
|
||||||
|
|
|
@ -61,3 +61,10 @@ export function revokeTypeRelation(first_type_id, second_type_id, rid, data) {
|
||||||
data
|
data
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getRecursive_level2children(type_id) {
|
||||||
|
return axios({
|
||||||
|
url: `/v0.1/ci_type_relations/${type_id}/recursive_level2children`,
|
||||||
|
method: 'GET'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
|
@ -37,3 +37,11 @@ export function batchUpdateCustomDashboard(data) {
|
||||||
data
|
data
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function postCustomDashboardPreview(data) {
|
||||||
|
return axios({
|
||||||
|
url: '/v0.1/custom_dashboard/preview',
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
|
@ -1,11 +1,55 @@
|
||||||
<template>
|
<template>
|
||||||
<div :style="{ width: '100%', height: 'calc(100% - 2.2vw)' }">
|
<div
|
||||||
<div v-if="category === 0" class="cmdb-dashboard-grid-item-chart">
|
:id="`cmdb-dashboard-${chartId}-${editable}-${isPreview}`"
|
||||||
|
:style="{ width: '100%', height: 'calc(100% - 2.2vw)' }"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
v-if="options.chartType === 'count'"
|
||||||
|
:style="{ color: options.fontColor || '#fff' }"
|
||||||
|
class="cmdb-dashboard-grid-item-chart"
|
||||||
|
>
|
||||||
|
<div class="cmdb-dashboard-grid-item-chart-icon" v-if="options.showIcon && ciType">
|
||||||
|
<template v-if="ciType.icon">
|
||||||
|
<img v-if="ciType.icon.split('$$')[2]" :src="`/api/common-setting/v1/file/${ciType.icon.split('$$')[3]}`" />
|
||||||
|
<ops-icon
|
||||||
|
v-else
|
||||||
|
:style="{
|
||||||
|
color: ciType.icon.split('$$')[1],
|
||||||
|
}"
|
||||||
|
:type="ciType.icon.split('$$')[0]"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<span :style="{ color: '#2f54eb' }" v-else>{{ ciType.name[0].toUpperCase() }}</span>
|
||||||
|
</div>
|
||||||
<span :style="{ ...options.fontConfig }">{{ toThousands(data) }}</span>
|
<span :style="{ ...options.fontConfig }">{{ toThousands(data) }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
<vxe-table
|
||||||
|
:max-height="tableHeight"
|
||||||
|
:data="tableData"
|
||||||
|
:stripe="!!options.ret"
|
||||||
|
size="mini"
|
||||||
|
class="ops-stripe-table"
|
||||||
|
v-if="options.chartType === 'table'"
|
||||||
|
:span-method="mergeRowMethod"
|
||||||
|
:border="!options.ret"
|
||||||
|
:show-header="!!options.ret"
|
||||||
|
>
|
||||||
|
<template v-if="options.ret">
|
||||||
|
<vxe-column v-for="col in columns" :key="col" :title="col" :field="col"></vxe-column>
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<vxe-column
|
||||||
|
v-for="(key, index) in Array(keyLength)"
|
||||||
|
:key="`key${index}`"
|
||||||
|
:title="`key${index}`"
|
||||||
|
:field="`key${index}`"
|
||||||
|
></vxe-column>
|
||||||
|
<vxe-column field="value" title="value"></vxe-column>
|
||||||
|
</template>
|
||||||
|
</vxe-table>
|
||||||
<div
|
<div
|
||||||
:id="`cmdb-dashboard-${chartId}-${editable}`"
|
:id="`cmdb-dashboard-${chartId}-${editable}`"
|
||||||
v-if="category === 1 || category === 2"
|
v-else-if="category === 1 || category === 2"
|
||||||
class="cmdb-dashboard-grid-item-chart"
|
class="cmdb-dashboard-grid-item-chart"
|
||||||
></div>
|
></div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -15,17 +59,27 @@
|
||||||
import * as echarts from 'echarts'
|
import * as echarts from 'echarts'
|
||||||
import { mixin } from '@/utils/mixin'
|
import { mixin } from '@/utils/mixin'
|
||||||
import { toThousands } from '../../utils/helper'
|
import { toThousands } from '../../utils/helper'
|
||||||
import { category_1_bar_options, category_1_pie_options, category_2_bar_options } from './chartOptions'
|
import {
|
||||||
|
category_1_bar_options,
|
||||||
|
category_1_line_options,
|
||||||
|
category_1_pie_options,
|
||||||
|
category_2_bar_options,
|
||||||
|
category_2_pie_options,
|
||||||
|
} from './chartOptions'
|
||||||
export default {
|
export default {
|
||||||
name: 'Chart',
|
name: 'Chart',
|
||||||
mixins: [mixin],
|
mixins: [mixin],
|
||||||
props: {
|
props: {
|
||||||
|
ci_types: {
|
||||||
|
type: Array,
|
||||||
|
default: () => [],
|
||||||
|
},
|
||||||
chartId: {
|
chartId: {
|
||||||
type: Number,
|
type: Number,
|
||||||
default: 0,
|
default: 0,
|
||||||
},
|
},
|
||||||
data: {
|
data: {
|
||||||
type: [Number, Object],
|
type: [Number, Object, Array],
|
||||||
default: 0,
|
default: 0,
|
||||||
},
|
},
|
||||||
category: {
|
category: {
|
||||||
|
@ -40,20 +94,65 @@ export default {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
|
type_id: {
|
||||||
|
type: [Number, Array],
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
|
isPreview: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
chart: null,
|
chart: null,
|
||||||
|
columns: [],
|
||||||
|
tableHeight: '',
|
||||||
|
tableData: [],
|
||||||
|
keyLength: 0,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
computed: {
|
||||||
|
ciType() {
|
||||||
|
if (this.type_id || this.options?.type_ids) {
|
||||||
|
const _find = this.ci_types.find((item) => item.id === this.type_id || item.id === this.options?.type_ids[0])
|
||||||
|
return _find || null
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
},
|
||||||
|
},
|
||||||
watch: {
|
watch: {
|
||||||
data: {
|
data: {
|
||||||
immediate: true,
|
immediate: true,
|
||||||
deep: true,
|
deep: true,
|
||||||
handler(newValue, oldValue) {
|
handler(newValue, oldValue) {
|
||||||
if (this.category === 1 || this.category === 2) {
|
if (this.category === 1 || this.category === 2) {
|
||||||
if (Object.prototype.toString.call(newValue) === '[object Object]') {
|
if (this.options.chartType !== 'table' && Object.prototype.toString.call(newValue) === '[object Object]') {
|
||||||
this.setChart()
|
if (this.isPreview) {
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.setChart()
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
this.setChart()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (this.options.chartType === 'table') {
|
||||||
|
this.$nextTick(() => {
|
||||||
|
const dom = document.getElementById(`cmdb-dashboard-${this.chartId}-${this.editable}-${this.isPreview}`)
|
||||||
|
this.tableHeight = dom.offsetHeight
|
||||||
|
})
|
||||||
|
if (this.options.ret) {
|
||||||
|
const excludeKeys = ['_X_ROW_KEY', 'ci_type', 'ci_type_alias', 'unique', 'unique_alias', '_id', '_type']
|
||||||
|
if (newValue && newValue.length) {
|
||||||
|
this.columns = Object.keys(newValue[0]).filter((keys) => !excludeKeys.includes(keys))
|
||||||
|
this.tableData = newValue
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const _data = []
|
||||||
|
this.keyLength = this.options?.attr_ids?.length ?? 0
|
||||||
|
this.formatTableData(_data, this.data, {})
|
||||||
|
this.tableData = _data
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -81,13 +180,19 @@ export default {
|
||||||
this.chart = echarts.init(document.getElementById(`cmdb-dashboard-${this.chartId}-${this.editable}`))
|
this.chart = echarts.init(document.getElementById(`cmdb-dashboard-${this.chartId}-${this.editable}`))
|
||||||
}
|
}
|
||||||
if (this.category === 1 && this.options.chartType === 'bar') {
|
if (this.category === 1 && this.options.chartType === 'bar') {
|
||||||
this.chart.setOption(category_1_bar_options(this.data), true)
|
this.chart.setOption(category_1_bar_options(this.data, this.options), true)
|
||||||
|
}
|
||||||
|
if (this.category === 1 && this.options.chartType === 'line') {
|
||||||
|
this.chart.setOption(category_1_line_options(this.data, this.options), true)
|
||||||
}
|
}
|
||||||
if (this.category === 1 && this.options.chartType === 'pie') {
|
if (this.category === 1 && this.options.chartType === 'pie') {
|
||||||
this.chart.setOption(category_1_pie_options(this.data), true)
|
this.chart.setOption(category_1_pie_options(this.data, this.options), true)
|
||||||
}
|
}
|
||||||
if (this.category === 2) {
|
if (this.category === 2 && ['bar', 'line'].includes(this.options.chartType)) {
|
||||||
this.chart.setOption(category_2_bar_options(this.data), true)
|
this.chart.setOption(category_2_bar_options(this.data, this.options, this.options.chartType), true)
|
||||||
|
}
|
||||||
|
if (this.category === 2 && this.options.chartType === 'pie') {
|
||||||
|
this.chart.setOption(category_2_pie_options(this.data, this.options), true)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
resizeChart() {
|
resizeChart() {
|
||||||
|
@ -97,6 +202,34 @@ export default {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
formatTableData(_data, data, obj) {
|
||||||
|
Object.keys(data).forEach((k) => {
|
||||||
|
if (typeof data[k] === 'number') {
|
||||||
|
_data.push({ ...obj, [`key${Object.keys(obj).length}`]: k, value: data[k] })
|
||||||
|
} else {
|
||||||
|
this.formatTableData(_data, data[k], { ...obj, [`key${Object.keys(obj).length}`]: k })
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
mergeRowMethod({ row, _rowIndex, column, visibleData }) {
|
||||||
|
const fields = ['key0', 'key1', 'key2']
|
||||||
|
const cellValue = row[column.field]
|
||||||
|
if (cellValue && fields.includes(column.field)) {
|
||||||
|
const prevRow = visibleData[_rowIndex - 1]
|
||||||
|
let nextRow = visibleData[_rowIndex + 1]
|
||||||
|
if (prevRow && prevRow[column.field] === cellValue) {
|
||||||
|
return { rowspan: 0, colspan: 0 }
|
||||||
|
} else {
|
||||||
|
let countRowspan = 1
|
||||||
|
while (nextRow && nextRow[column.field] === cellValue) {
|
||||||
|
nextRow = visibleData[++countRowspan + _rowIndex]
|
||||||
|
}
|
||||||
|
if (countRowspan > 1) {
|
||||||
|
return { rowspan: countRowspan, colspan: 1 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -106,14 +239,28 @@ export default {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
position: relative;
|
position: relative;
|
||||||
padding: 10px;
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
> span {
|
> span {
|
||||||
font-size: 50px;
|
font-size: 50px;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
position: absolute;
|
}
|
||||||
top: 50%;
|
.cmdb-dashboard-grid-item-chart-icon {
|
||||||
left: 50%;
|
> i {
|
||||||
transform: translate(-50%, -50%);
|
font-size: 4vw;
|
||||||
|
}
|
||||||
|
> img {
|
||||||
|
width: 4vw;
|
||||||
|
}
|
||||||
|
> span {
|
||||||
|
display: inline-block;
|
||||||
|
width: 4vw;
|
||||||
|
height: 4vw;
|
||||||
|
font-size: 50px;
|
||||||
|
text-align: center;
|
||||||
|
line-height: 50px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -1,65 +1,307 @@
|
||||||
<template>
|
<template>
|
||||||
<a-modal :title="`${type === 'add' ? '新增' : '编辑'}图表`" :visible="visible" @cancel="handleclose" @ok="handleok">
|
<a-modal
|
||||||
<a-form-model ref="chartForm" :model="form" :rules="rules" :label-col="{ span: 6 }" :wrapper-col="{ span: 14 }">
|
width="1100px"
|
||||||
<a-form-model-item label="类型" prop="category">
|
:title="`${type === 'add' ? '新增' : '编辑'}图表`"
|
||||||
<a-select v-model="form.category" @change="changeDashboardCategory">
|
:visible="visible"
|
||||||
<a-select-option v-for="cate in Object.keys(dashboardCategory)" :key="cate" :value="Number(cate)">{{
|
@cancel="handleclose"
|
||||||
dashboardCategory[cate].label
|
@ok="handleok"
|
||||||
}}</a-select-option>
|
:bodyStyle="{ paddingTop: 0 }"
|
||||||
</a-select>
|
>
|
||||||
</a-form-model-item>
|
<div class="chart-wrapper">
|
||||||
<a-form-model-item v-if="form.category !== 0" label="名称" prop="name">
|
<div class="chart-left">
|
||||||
<a-input v-model="form.name" placeholder="请输入图表名称"></a-input>
|
<a-form-model ref="chartForm" :model="form" :rules="rules" :label-col="{ span: 4 }" :wrapper-col="{ span: 18 }">
|
||||||
</a-form-model-item>
|
<a-form-model-item label="标题" prop="name">
|
||||||
<a-form-model-item label="模型" prop="type_id">
|
<a-input v-model="form.name" placeholder="请输入图表标题"></a-input>
|
||||||
<a-select
|
</a-form-model-item>
|
||||||
show-search
|
<a-form-model-item label="类型" prop="category" v-if="chartType !== 'count' && chartType !== 'table'">
|
||||||
optionFilterProp="children"
|
<a-radio-group
|
||||||
@change="changeCIType"
|
@change="
|
||||||
v-model="form.type_id"
|
() => {
|
||||||
placeholder="请选择模型"
|
resetForm()
|
||||||
>
|
}
|
||||||
<a-select-option v-for="ci_type in ci_types" :key="ci_type.id" :value="ci_type.id">{{
|
"
|
||||||
ci_type.alias || ci_type.name
|
:default-value="1"
|
||||||
}}</a-select-option>
|
v-model="form.category"
|
||||||
</a-select>
|
>
|
||||||
</a-form-model-item>
|
<a-radio-button :value="Number(key)" :key="key" v-for="key in Object.keys(dashboardCategory)">
|
||||||
<a-form-model-item v-if="form.category === 1" label="模型属性" prop="attr_id">
|
{{ dashboardCategory[key].label }}
|
||||||
<a-select show-search optionFilterProp="children" v-model="form.attr_id" placeholder="请选择模型属性">
|
</a-radio-button>
|
||||||
<a-select-option v-for="attr in attributes" :key="attr.id" :value="attr.id">{{
|
</a-radio-group>
|
||||||
attr.alias || attr.name
|
</a-form-model-item>
|
||||||
}}</a-select-option>
|
<a-form-model-item label="类型" prop="tableCategory" v-if="chartType === 'table'">
|
||||||
</a-select>
|
<a-radio-group
|
||||||
</a-form-model-item>
|
@change="
|
||||||
<a-form-model-item v-if="form.category === 1" label="图表类型" prop="chartType">
|
() => {
|
||||||
<a-radio-group v-model="chartType">
|
resetForm()
|
||||||
<a-radio value="bar">
|
}
|
||||||
柱状图
|
"
|
||||||
</a-radio>
|
:default-value="1"
|
||||||
<a-radio value="pie">
|
v-model="form.tableCategory"
|
||||||
饼图
|
>
|
||||||
</a-radio>
|
<a-radio-button :value="1">
|
||||||
</a-radio-group>
|
计算指标
|
||||||
</a-form-model-item>
|
</a-radio-button>
|
||||||
<a-form-model-item v-if="form.category === 2" label="关系层级" prop="level">
|
<a-radio-button :value="2">
|
||||||
<a-input v-model="form.level" placeholder="请输入关系层级"></a-input>
|
资源数据
|
||||||
</a-form-model-item>
|
</a-radio-button>
|
||||||
<a-form-model-item v-if="form.category === 0" label="字体">
|
</a-radio-group>
|
||||||
<FontConfig ref="fontConfig" />
|
</a-form-model-item>
|
||||||
</a-form-model-item>
|
<a-form-model-item
|
||||||
</a-form-model>
|
v-if="(chartType !== 'table' && form.category !== 2) || (chartType === 'table' && form.tableCategory === 1)"
|
||||||
|
label="模型"
|
||||||
|
prop="type_ids"
|
||||||
|
>
|
||||||
|
<a-select
|
||||||
|
show-search
|
||||||
|
optionFilterProp="children"
|
||||||
|
@change="changeCIType"
|
||||||
|
v-model="form.type_ids"
|
||||||
|
placeholder="请选择模型"
|
||||||
|
mode="multiple"
|
||||||
|
>
|
||||||
|
<a-select-option v-for="ci_type in ci_types" :key="ci_type.id" :value="ci_type.id">{{
|
||||||
|
ci_type.alias || ci_type.name
|
||||||
|
}}</a-select-option>
|
||||||
|
</a-select>
|
||||||
|
</a-form-model-item>
|
||||||
|
<a-form-model-item v-else label="模型" prop="type_id">
|
||||||
|
<a-select
|
||||||
|
show-search
|
||||||
|
optionFilterProp="children"
|
||||||
|
@change="changeCIType"
|
||||||
|
v-model="form.type_id"
|
||||||
|
placeholder="请选择模型"
|
||||||
|
>
|
||||||
|
<a-select-option v-for="ci_type in ci_types" :key="ci_type.id" :value="ci_type.id">{{
|
||||||
|
ci_type.alias || ci_type.name
|
||||||
|
}}</a-select-option>
|
||||||
|
</a-select>
|
||||||
|
</a-form-model-item>
|
||||||
|
<a-form-model-item
|
||||||
|
label="维度"
|
||||||
|
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-option v-for="attr in commonAttributes" :key="attr.id" :value="attr.id">{{
|
||||||
|
attr.alias || attr.name
|
||||||
|
}}</a-select-option>
|
||||||
|
</a-select>
|
||||||
|
</a-form-model-item>
|
||||||
|
<a-form-model-item
|
||||||
|
prop="type_ids"
|
||||||
|
label="关系模型"
|
||||||
|
v-if="['bar', 'line', 'pie'].includes(chartType) && form.category === 2"
|
||||||
|
>
|
||||||
|
<a-select
|
||||||
|
show-search
|
||||||
|
optionFilterProp="children"
|
||||||
|
mode="multiple"
|
||||||
|
v-model="form.type_ids"
|
||||||
|
placeholder="请选择模型"
|
||||||
|
>
|
||||||
|
<a-select-opt-group
|
||||||
|
v-for="(key, index) in Object.keys(level2children)"
|
||||||
|
:key="key"
|
||||||
|
:label="`层级${index + 1}`"
|
||||||
|
>
|
||||||
|
<a-select-option
|
||||||
|
@click="(e) => clickLevel2children(e, citype, index + 1)"
|
||||||
|
v-for="citype in level2children[key]"
|
||||||
|
:key="citype.id"
|
||||||
|
:value="citype.id"
|
||||||
|
>
|
||||||
|
{{ citype.alias || citype.name }}
|
||||||
|
</a-select-option>
|
||||||
|
</a-select-opt-group>
|
||||||
|
</a-select>
|
||||||
|
</a-form-model-item>
|
||||||
|
<div class="chart-left-preview">
|
||||||
|
<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">
|
||||||
|
<template v-if="form.showIcon && ciType">
|
||||||
|
<template v-if="ciType.icon">
|
||||||
|
<img
|
||||||
|
v-if="ciType.icon.split('$$')[2]"
|
||||||
|
:src="`/api/common-setting/v1/file/${ciType.icon.split('$$')[3]}`"
|
||||||
|
/>
|
||||||
|
<ops-icon
|
||||||
|
v-else
|
||||||
|
:style="{
|
||||||
|
color: ciType.icon.split('$$')[1],
|
||||||
|
}"
|
||||||
|
:type="ciType.icon.split('$$')[0]"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<span :style="{ color: '#2f54eb' }" v-else>{{ ciType.name[0].toUpperCase() }}</span>
|
||||||
|
</template>
|
||||||
|
<span :style="{ color: '#000' }"> {{ form.name }}</span>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="chart-left-preview-box"
|
||||||
|
:style="{
|
||||||
|
height: chartType === 'count' ? '120px' : '',
|
||||||
|
marginTop: chartType === 'count' ? '80px' : '',
|
||||||
|
background:
|
||||||
|
chartType === 'count'
|
||||||
|
? Array.isArray(bgColor)
|
||||||
|
? `linear-gradient(to bottom, ${bgColor[0]} 0%, ${bgColor[1]} 100%)`
|
||||||
|
: bgColor
|
||||||
|
: '#fafafa',
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<div :style="{ color: fontColor }">{{ form.name }}</div>
|
||||||
|
<Chart
|
||||||
|
:ref="`chart_${item.id}`"
|
||||||
|
:chartId="item.id"
|
||||||
|
:data="previewData"
|
||||||
|
:category="form.category"
|
||||||
|
:options="{
|
||||||
|
...item.options,
|
||||||
|
name: form.name,
|
||||||
|
fontColor: fontColor,
|
||||||
|
bgColor: bgColor,
|
||||||
|
chartType: chartType,
|
||||||
|
showIcon: form.showIcon,
|
||||||
|
barDirection: barDirection,
|
||||||
|
barStack: barStack,
|
||||||
|
chartColor: chartColor,
|
||||||
|
type_ids: form.type_ids,
|
||||||
|
attr_ids: form.attr_ids,
|
||||||
|
isShadow: isShadow,
|
||||||
|
}"
|
||||||
|
:editable="false"
|
||||||
|
:ci_types="ci_types"
|
||||||
|
:type_id="form.type_id || form.type_ids"
|
||||||
|
isPreview
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
<a-form-model-item label="是否显示icon" prop="showIcon" :label-col="{ span: 5 }" :wrapper-col="{ span: 18 }">
|
||||||
|
<a-switch v-model="form.showIcon"></a-switch>
|
||||||
|
</a-form-model-item>
|
||||||
|
</a-form-model>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="chart-right">
|
||||||
|
<h4>图表类型</h4>
|
||||||
|
<div class="chart-right-type">
|
||||||
|
<div
|
||||||
|
:class="{ 'chart-right-type-box': true, 'chart-right-type-box-selected': chartType === t.value }"
|
||||||
|
v-for="t in chartTypeList"
|
||||||
|
:key="t.value"
|
||||||
|
@click="changeChartType(t)"
|
||||||
|
>
|
||||||
|
<ops-icon :type="`cmdb-${t.value}`" />
|
||||||
|
<span>{{ t.label }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<h4>数据筛选</h4>
|
||||||
|
<FilterComp
|
||||||
|
ref="filterComp"
|
||||||
|
:isDropdown="false"
|
||||||
|
:canSearchPreferenceAttrList="attributes"
|
||||||
|
@setExpFromFilter="setExpFromFilter"
|
||||||
|
:expression="filterExp ? `q=${filterExp}` : ''"
|
||||||
|
/>
|
||||||
|
<h4>格式</h4>
|
||||||
|
<a-form-model :colon="false" :label-col="{ span: 4 }" :wrapper-col="{ span: 20 }">
|
||||||
|
<a-form-model-item label="字体颜色" v-if="chartType === 'count'">
|
||||||
|
<ColorPicker
|
||||||
|
v-model="fontColor"
|
||||||
|
:colorList="[
|
||||||
|
'#1D2129',
|
||||||
|
'#4E5969',
|
||||||
|
'#103C93',
|
||||||
|
'#86909C',
|
||||||
|
'#ffffff',
|
||||||
|
'#C9F2FF',
|
||||||
|
'#FFEAC0',
|
||||||
|
'#D6FFE6',
|
||||||
|
'#F2DEFF',
|
||||||
|
]"
|
||||||
|
/>
|
||||||
|
</a-form-model-item>
|
||||||
|
<a-form-model-item label="背景颜色" v-if="chartType === 'count'">
|
||||||
|
<ColorPicker
|
||||||
|
v-model="bgColor"
|
||||||
|
:colorList="[
|
||||||
|
['#6ABFFE', '#5375EB'],
|
||||||
|
['#C69EFF', '#A377F9'],
|
||||||
|
['#85EBC9', '#4AB8D8'],
|
||||||
|
['#FEB58B', '#DF6463'],
|
||||||
|
'#ffffff',
|
||||||
|
'#FFFBF0',
|
||||||
|
'#FFF1EC',
|
||||||
|
'#E5FFFE',
|
||||||
|
'#E5E7FF',
|
||||||
|
]"
|
||||||
|
/>
|
||||||
|
</a-form-model-item>
|
||||||
|
<a-form-model-item label="图表颜色" v-else-if="chartType !== 'table'">
|
||||||
|
<ColorListPicker v-model="chartColor" />
|
||||||
|
</a-form-model-item>
|
||||||
|
<a-form-model-item label="图表长度(%)">
|
||||||
|
<a-radio-group class="chart-width" style="width:100%;" v-model="width">
|
||||||
|
<a-radio-button :value="3">
|
||||||
|
25
|
||||||
|
</a-radio-button>
|
||||||
|
<a-radio-button :value="6">
|
||||||
|
50
|
||||||
|
</a-radio-button>
|
||||||
|
<a-radio-button :value="9">
|
||||||
|
75
|
||||||
|
</a-radio-button>
|
||||||
|
<a-radio-button :value="12">
|
||||||
|
100
|
||||||
|
</a-radio-button>
|
||||||
|
</a-radio-group>
|
||||||
|
</a-form-model-item>
|
||||||
|
<a-form-model-item label="柱状图类型" v-if="chartType === 'bar'">
|
||||||
|
<a-radio-group v-model="barStack">
|
||||||
|
<a-radio value="total">
|
||||||
|
堆积柱状图
|
||||||
|
</a-radio>
|
||||||
|
<a-radio value="">
|
||||||
|
多系列柱状图
|
||||||
|
</a-radio>
|
||||||
|
</a-radio-group>
|
||||||
|
</a-form-model-item>
|
||||||
|
<a-form-model-item label="方向" v-if="chartType === 'bar'">
|
||||||
|
<a-radio-group v-model="barDirection">
|
||||||
|
<a-radio value="x">
|
||||||
|
X轴
|
||||||
|
</a-radio>
|
||||||
|
<a-radio value="y">
|
||||||
|
y轴
|
||||||
|
</a-radio>
|
||||||
|
</a-radio-group>
|
||||||
|
</a-form-model-item>
|
||||||
|
<a-form-model-item label="下方阴影" v-if="chartType === 'line'">
|
||||||
|
<a-switch v-model="isShadow" />
|
||||||
|
</a-form-model-item>
|
||||||
|
</a-form-model>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</a-modal>
|
</a-modal>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import Chart from './chart.vue'
|
||||||
import { dashboardCategory } from './constant'
|
import { dashboardCategory } from './constant'
|
||||||
import { postCustomDashboard, putCustomDashboard } from '../../api/customDashboard'
|
import { postCustomDashboard, putCustomDashboard, postCustomDashboardPreview } from '../../api/customDashboard'
|
||||||
import { getCITypeAttributesById } from '../../api/CITypeAttr'
|
import { getCITypeAttributesByTypeIds, getCITypeCommonAttributesByTypeIds } from '../../api/CITypeAttr'
|
||||||
|
import { getRecursive_level2children } from '../../api/CITypeRelation'
|
||||||
import { getLastLayout } from '../../utils/helper'
|
import { getLastLayout } from '../../utils/helper'
|
||||||
import FontConfig from './fontConfig.vue'
|
import FilterComp from '@/components/CMDBFilterComp'
|
||||||
|
import ColorPicker from './colorPicker.vue'
|
||||||
|
import ColorListPicker from './colorListPicker.vue'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'ChartForm',
|
name: 'ChartForm',
|
||||||
components: { FontConfig },
|
components: { Chart, FilterComp, ColorPicker, ColorListPicker },
|
||||||
props: {
|
props: {
|
||||||
ci_types: {
|
ci_types: {
|
||||||
type: Array,
|
type: Array,
|
||||||
|
@ -67,100 +309,226 @@ export default {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
|
const chartTypeList = [
|
||||||
|
{
|
||||||
|
value: 'count',
|
||||||
|
label: '指标',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'bar',
|
||||||
|
label: '柱状图',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'line',
|
||||||
|
label: '折线图',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'pie',
|
||||||
|
label: '饼状图',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'table',
|
||||||
|
label: '表格',
|
||||||
|
},
|
||||||
|
]
|
||||||
return {
|
return {
|
||||||
dashboardCategory,
|
dashboardCategory,
|
||||||
|
chartTypeList,
|
||||||
visible: false,
|
visible: false,
|
||||||
attributes: [],
|
attributes: [],
|
||||||
type: 'add',
|
type: 'add',
|
||||||
form: {
|
form: {
|
||||||
category: 0,
|
category: 0,
|
||||||
|
tableCategory: 1,
|
||||||
name: undefined,
|
name: undefined,
|
||||||
type_id: undefined,
|
type_id: undefined,
|
||||||
attr_id: undefined,
|
type_ids: undefined,
|
||||||
|
attr_ids: undefined,
|
||||||
level: undefined,
|
level: undefined,
|
||||||
|
showIcon: false,
|
||||||
},
|
},
|
||||||
rules: {
|
rules: {
|
||||||
category: [{ required: true, trigger: 'change' }],
|
category: [{ required: true, trigger: 'change' }],
|
||||||
name: [{ required: true, message: '请输入图表名称' }],
|
name: [{ required: true, message: '请输入图表名称' }],
|
||||||
type_id: [{ required: true, message: '请选择模型', trigger: 'change' }],
|
type_id: [{ required: true, message: '请选择模型', trigger: 'change' }],
|
||||||
attr_id: [{ required: true, message: '请选择模型属性', trigger: 'change' }],
|
type_ids: [{ required: true, message: '请选择模型', trigger: 'change' }],
|
||||||
|
attr_ids: [{ required: true, message: '请选择模型属性', trigger: 'change' }],
|
||||||
level: [{ required: true, message: '请输入关系层级' }],
|
level: [{ required: true, message: '请输入关系层级' }],
|
||||||
|
showIcon: [{ required: false }],
|
||||||
},
|
},
|
||||||
item: {},
|
item: {},
|
||||||
chartType: 'bar',
|
chartType: 'count', // table,bar,line,pie,count
|
||||||
|
width: 3,
|
||||||
|
fontColor: '#ffffff',
|
||||||
|
bgColor: ['#6ABFFE', '#5375EB'],
|
||||||
|
chartColor: '#6592FD,#6EE3EB,#44C2FD,#5F59F7,#1A348F,#7D8FCF,#A6D1E5,#8E56DD', // 图表颜色
|
||||||
|
isShowPreview: false,
|
||||||
|
filterExp: undefined,
|
||||||
|
previewData: null,
|
||||||
|
barStack: 'total',
|
||||||
|
barDirection: 'y',
|
||||||
|
commonAttributes: [],
|
||||||
|
level2children: {},
|
||||||
|
isShadow: false,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
computed: {
|
||||||
|
ciType() {
|
||||||
|
if (this.form.type_id || this.form.type_ids) {
|
||||||
|
const _find = this.ci_types.find((item) => item.id === this.form.type_id || item.id === this.form.type_ids[0])
|
||||||
|
return _find || null
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
},
|
||||||
|
},
|
||||||
inject: ['layout'],
|
inject: ['layout'],
|
||||||
methods: {
|
methods: {
|
||||||
open(type, item = {}) {
|
async open(type, item = {}) {
|
||||||
this.visible = true
|
this.visible = true
|
||||||
this.type = type
|
this.type = type
|
||||||
this.item = item
|
this.item = item
|
||||||
const { category = 0, name, type_id, attr_id, level } = item
|
const { category = 0, name, type_id, attr_id, level } = item
|
||||||
const chartType = (item.options || {}).chartType || 'bar'
|
const chartType = (item.options || {}).chartType || 'count'
|
||||||
|
const fontColor = (item.options || {}).fontColor || '#ffffff'
|
||||||
|
const bgColor = (item.options || {}).bgColor || ['#6ABFFE', '#5375EB']
|
||||||
|
const width = (item.options || {}).w
|
||||||
|
const showIcon = (item.options || {}).showIcon
|
||||||
|
const type_ids = item?.options?.type_ids || []
|
||||||
|
const attr_ids = item?.options?.attr_ids || []
|
||||||
|
const ret = item?.options?.ret || ''
|
||||||
|
this.width = width
|
||||||
this.chartType = chartType
|
this.chartType = chartType
|
||||||
if (type_id && attr_id) {
|
this.filterExp = item?.options?.filter ?? ''
|
||||||
getCITypeAttributesById(type_id).then((res) => {
|
this.chartColor = item?.options?.chartColor ?? '#6592FD,#6EE3EB,#44C2FD,#5F59F7,#1A348F,#7D8FCF,#A6D1E5,#8E56DD'
|
||||||
|
this.isShadow = item?.options?.isShadow ?? false
|
||||||
|
|
||||||
|
if (chartType === 'count') {
|
||||||
|
this.fontColor = fontColor
|
||||||
|
this.bgColor = bgColor
|
||||||
|
}
|
||||||
|
if (type_ids && type_ids.length) {
|
||||||
|
await getCITypeAttributesByTypeIds({ type_ids: type_ids.join(',') }).then((res) => {
|
||||||
this.attributes = res.attributes
|
this.attributes = res.attributes
|
||||||
})
|
})
|
||||||
|
if ((['bar', 'line', 'pie'].includes(chartType) && category === 1) || chartType === 'table') {
|
||||||
|
this.barDirection = item?.options?.barDirection ?? 'y'
|
||||||
|
this.barStack = item?.options?.barStack ?? 'total'
|
||||||
|
await getCITypeCommonAttributesByTypeIds({
|
||||||
|
type_ids: type_ids.join(','),
|
||||||
|
}).then((res) => {
|
||||||
|
this.commonAttributes = res.attributes
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
if (type_id) {
|
||||||
|
getRecursive_level2children(type_id).then((res) => {
|
||||||
|
this.level2children = res
|
||||||
|
})
|
||||||
|
await getCITypeCommonAttributesByTypeIds({
|
||||||
|
type_ids: type_id,
|
||||||
|
}).then((res) => {
|
||||||
|
this.commonAttributes = res.attributes
|
||||||
|
})
|
||||||
|
}
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.$refs.filterComp.visibleChange(true, false)
|
||||||
|
})
|
||||||
const default_form = {
|
const default_form = {
|
||||||
category: 0,
|
category: 0,
|
||||||
name: undefined,
|
name: undefined,
|
||||||
type_id: undefined,
|
type_id: undefined,
|
||||||
attr_id: undefined,
|
type_ids: undefined,
|
||||||
|
attr_ids: undefined,
|
||||||
level: undefined,
|
level: undefined,
|
||||||
|
showIcon: false,
|
||||||
|
tableCategory: 1,
|
||||||
}
|
}
|
||||||
this.form = {
|
this.form = {
|
||||||
...default_form,
|
...default_form,
|
||||||
category,
|
category,
|
||||||
name,
|
name,
|
||||||
type_id,
|
type_id,
|
||||||
attr_id,
|
type_ids,
|
||||||
|
attr_ids,
|
||||||
level,
|
level,
|
||||||
}
|
showIcon,
|
||||||
if (category === 0) {
|
tableCategory: ret === 'cis' ? 2 : 1,
|
||||||
this.$nextTick(() => {
|
|
||||||
this.$refs.fontConfig.setConfig((item.options || {}).fontConfig)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
handleclose() {
|
handleclose() {
|
||||||
this.attributes = []
|
this.attributes = []
|
||||||
this.$refs.chartForm.clearValidate()
|
this.$refs.chartForm.clearValidate()
|
||||||
|
this.isShowPreview = false
|
||||||
this.visible = false
|
this.visible = false
|
||||||
},
|
},
|
||||||
changeCIType(value) {
|
changeCIType(value) {
|
||||||
getCITypeAttributesById(value).then((res) => {
|
this.form.attr_ids = []
|
||||||
|
this.commonAttributes = []
|
||||||
|
getCITypeAttributesByTypeIds({ type_ids: Array.isArray(value) ? value.join(',') : value }).then((res) => {
|
||||||
this.attributes = res.attributes
|
this.attributes = res.attributes
|
||||||
this.form = {
|
|
||||||
...this.form,
|
|
||||||
attr_id: undefined,
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
if (!Array.isArray(value)) {
|
||||||
|
getRecursive_level2children(value).then((res) => {
|
||||||
|
this.level2children = res
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if ((['bar', 'line', 'pie'].includes(this.chartType) && this.form.category === 1) || this.chartType === 'table') {
|
||||||
|
getCITypeCommonAttributesByTypeIds({ type_ids: Array.isArray(value) ? value.join(',') : value }).then((res) => {
|
||||||
|
this.commonAttributes = res.attributes
|
||||||
|
})
|
||||||
|
}
|
||||||
},
|
},
|
||||||
handleok() {
|
handleok() {
|
||||||
this.$refs.chartForm.validate(async (valid) => {
|
this.$refs.chartForm.validate(async (valid) => {
|
||||||
if (valid) {
|
if (valid) {
|
||||||
const fontConfig = this.form.category === 0 ? this.$refs.fontConfig.getConfig() : undefined
|
const name = this.form.name
|
||||||
const _find = this.ci_types.find((attr) => attr.id === this.form.type_id)
|
const { chartType, fontColor, bgColor } = this
|
||||||
const name = this.form.name || (_find || {}).alias || (_find || {}).name
|
this.$refs.filterComp.handleSubmit()
|
||||||
if (this.item.id) {
|
if (this.item.id) {
|
||||||
await putCustomDashboard(this.item.id, {
|
const params = {
|
||||||
...this.form,
|
...this.form,
|
||||||
options: {
|
options: {
|
||||||
...this.item.options,
|
...this.item.options,
|
||||||
name,
|
name,
|
||||||
fontConfig,
|
w: this.width,
|
||||||
chartType: this.chartType,
|
chartType: this.chartType,
|
||||||
|
showIcon: this.form.showIcon,
|
||||||
|
type_ids: this.form.type_ids,
|
||||||
|
filter: this.filterExp,
|
||||||
|
isShadow: this.isShadow,
|
||||||
},
|
},
|
||||||
})
|
}
|
||||||
|
if (chartType === 'count') {
|
||||||
|
params.options.fontColor = fontColor
|
||||||
|
params.options.bgColor = bgColor
|
||||||
|
}
|
||||||
|
if (['bar', 'line', 'pie'].includes(chartType)) {
|
||||||
|
if (this.form.category === 1) {
|
||||||
|
params.options.attr_ids = this.form.attr_ids
|
||||||
|
}
|
||||||
|
params.options.chartColor = this.chartColor
|
||||||
|
}
|
||||||
|
if (chartType === 'bar') {
|
||||||
|
params.options.barDirection = this.barDirection
|
||||||
|
params.options.barStack = this.barStack
|
||||||
|
}
|
||||||
|
if (chartType === 'table') {
|
||||||
|
params.options.attr_ids = this.form.attr_ids
|
||||||
|
if (this.form.tableCategory === 2) {
|
||||||
|
params.options.ret = 'cis'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delete params.showIcon
|
||||||
|
delete params.type_ids
|
||||||
|
delete params.attr_ids
|
||||||
|
delete params.tableCategory
|
||||||
|
await putCustomDashboard(this.item.id, params)
|
||||||
} else {
|
} else {
|
||||||
const { xLast, yLast, wLast } = getLastLayout(this.layout())
|
const { xLast, yLast, wLast } = getLastLayout(this.layout())
|
||||||
const w = 3
|
const w = this.width
|
||||||
const x = xLast + wLast + w > 12 ? 0 : xLast + wLast
|
const x = xLast + wLast + w > 12 ? 0 : xLast + wLast
|
||||||
const y = xLast + wLast + w > 12 ? yLast + 1 : yLast
|
const y = xLast + wLast + w > 12 ? yLast + 1 : yLast
|
||||||
await postCustomDashboard({
|
const params = {
|
||||||
...this.form,
|
...this.form,
|
||||||
options: {
|
options: {
|
||||||
x,
|
x,
|
||||||
|
@ -169,23 +537,216 @@ export default {
|
||||||
h: this.form.category === 0 ? 3 : 5,
|
h: this.form.category === 0 ? 3 : 5,
|
||||||
name,
|
name,
|
||||||
chartType: this.chartType,
|
chartType: this.chartType,
|
||||||
fontConfig,
|
showIcon: this.form.showIcon,
|
||||||
|
type_ids: this.form.type_ids,
|
||||||
|
filter: this.filterExp,
|
||||||
|
isShadow: this.isShadow,
|
||||||
},
|
},
|
||||||
})
|
}
|
||||||
|
if (chartType === 'count') {
|
||||||
|
params.options.fontColor = fontColor
|
||||||
|
params.options.bgColor = bgColor
|
||||||
|
}
|
||||||
|
if (['bar', 'line', 'pie'].includes(chartType)) {
|
||||||
|
if (this.form.category === 1) {
|
||||||
|
params.options.attr_ids = this.form.attr_ids
|
||||||
|
}
|
||||||
|
params.options.chartColor = this.chartColor
|
||||||
|
}
|
||||||
|
if (chartType === 'bar') {
|
||||||
|
params.options.barDirection = this.barDirection
|
||||||
|
params.options.barStack = this.barStack
|
||||||
|
}
|
||||||
|
if (chartType === 'table') {
|
||||||
|
params.options.attr_ids = this.form.attr_ids
|
||||||
|
if (this.form.tableCategory === 2) {
|
||||||
|
params.options.ret = 'cis'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delete params.showIcon
|
||||||
|
delete params.type_ids
|
||||||
|
delete params.attr_ids
|
||||||
|
delete params.tableCategory
|
||||||
|
await postCustomDashboard(params)
|
||||||
}
|
}
|
||||||
this.handleclose()
|
this.handleclose()
|
||||||
this.$emit('refresh')
|
this.$emit('refresh')
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
changeDashboardCategory(value) {
|
// changeDashboardCategory(value) {
|
||||||
this.$refs.chartForm.clearValidate()
|
// this.$refs.chartForm.clearValidate()
|
||||||
if (value === 1 && this.form.type_id) {
|
// if (value === 1 && this.form.type_id) {
|
||||||
this.changeCIType(this.form.type_id)
|
// this.changeCIType(this.form.type_id)
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
changeChartType(t) {
|
||||||
|
this.chartType = t.value
|
||||||
|
this.isShowPreview = false
|
||||||
|
if (t.value === 'count') {
|
||||||
|
this.form.category = 0
|
||||||
|
} else {
|
||||||
|
this.form.category = 1
|
||||||
}
|
}
|
||||||
|
this.resetForm()
|
||||||
|
},
|
||||||
|
showPreview() {
|
||||||
|
this.$refs.chartForm.validate(async (valid) => {
|
||||||
|
if (valid) {
|
||||||
|
this.isShowPreview = false
|
||||||
|
const name = this.form.name
|
||||||
|
const { chartType, fontColor, bgColor } = this
|
||||||
|
this.$refs.filterComp.handleSubmit()
|
||||||
|
const params = {
|
||||||
|
...this.form,
|
||||||
|
options: {
|
||||||
|
name,
|
||||||
|
chartType,
|
||||||
|
showIcon: this.form.showIcon,
|
||||||
|
type_ids: this.form.type_ids,
|
||||||
|
filter: this.filterExp,
|
||||||
|
isShadow: this.isShadow,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
if (chartType === 'count') {
|
||||||
|
params.options.fontColor = fontColor
|
||||||
|
params.options.bgColor = bgColor
|
||||||
|
}
|
||||||
|
if (['bar', 'line', 'pie'].includes(chartType)) {
|
||||||
|
if (this.form.category === 1) {
|
||||||
|
params.options.attr_ids = this.form.attr_ids
|
||||||
|
}
|
||||||
|
params.options.chartColor = this.chartColor
|
||||||
|
}
|
||||||
|
if (chartType === 'bar') {
|
||||||
|
params.options.barDirection = this.barDirection
|
||||||
|
params.options.barStack = this.barStack
|
||||||
|
}
|
||||||
|
if (chartType === 'table') {
|
||||||
|
params.options.attr_ids = this.form.attr_ids
|
||||||
|
if (this.form.tableCategory === 2) {
|
||||||
|
params.options.ret = 'cis'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delete params.showIcon
|
||||||
|
delete params.type_ids
|
||||||
|
delete params.attr_ids
|
||||||
|
delete params.tableCategory
|
||||||
|
postCustomDashboardPreview(params).then((res) => {
|
||||||
|
this.isShowPreview = true
|
||||||
|
this.previewData = res.counter
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
setExpFromFilter(filterExp) {
|
||||||
|
if (filterExp) {
|
||||||
|
this.filterExp = `${filterExp}`
|
||||||
|
} else {
|
||||||
|
this.filterExp = undefined
|
||||||
|
}
|
||||||
|
},
|
||||||
|
resetForm() {
|
||||||
|
this.form.type_id = undefined
|
||||||
|
this.form.type_ids = []
|
||||||
|
this.form.attr_ids = []
|
||||||
|
this.$refs.chartForm.clearValidate()
|
||||||
|
},
|
||||||
|
changeAttr(value) {
|
||||||
|
if (value && value.length) {
|
||||||
|
if (['line', 'pie'].includes(this.chartType)) {
|
||||||
|
this.form.attr_ids = [value[value.length - 1]]
|
||||||
|
}
|
||||||
|
if (['bar'].includes(this.chartType) && value.length > 2) {
|
||||||
|
this.form.attr_ids = value.slice(value.length - 2, value.length)
|
||||||
|
}
|
||||||
|
if (['table'].includes(this.chartType) && value.length > 3) {
|
||||||
|
this.form.attr_ids = value.slice(value.length - 3, value.length)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
clickLevel2children(e, citype, level) {
|
||||||
|
if (this.form.level !== level) {
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.form.type_ids = [citype.id]
|
||||||
|
})
|
||||||
|
}
|
||||||
|
this.form.level = level
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style></style>
|
<style lang="less" scoped>
|
||||||
|
.chart-wrapper {
|
||||||
|
display: flex;
|
||||||
|
.chart-left {
|
||||||
|
width: 50%;
|
||||||
|
.chart-left-preview {
|
||||||
|
border: 1px solid #e4e7ed;
|
||||||
|
border-radius: 2px;
|
||||||
|
height: 280px;
|
||||||
|
width: 92%;
|
||||||
|
position: relative;
|
||||||
|
padding: 12px;
|
||||||
|
.chart-left-preview-operation {
|
||||||
|
color: #86909c;
|
||||||
|
position: absolute;
|
||||||
|
top: 12px;
|
||||||
|
right: 12px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.chart-left-preview-box {
|
||||||
|
padding: 6px 12px;
|
||||||
|
height: 250px;
|
||||||
|
border-radius: 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.chart-right {
|
||||||
|
width: 50%;
|
||||||
|
h4 {
|
||||||
|
font-weight: 700;
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
.chart-right-type {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
background-color: #f0f5ff;
|
||||||
|
padding: 6px 12px;
|
||||||
|
.chart-right-type-box {
|
||||||
|
cursor: pointer;
|
||||||
|
width: 70px;
|
||||||
|
height: 60px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
> i {
|
||||||
|
font-size: 32px;
|
||||||
|
}
|
||||||
|
> span {
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.chart-right-type-box-selected {
|
||||||
|
background-color: #e5f1ff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.chart-width {
|
||||||
|
width: 100%;
|
||||||
|
> label {
|
||||||
|
width: 25%;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<style lang="less">
|
||||||
|
.chart-wrapper {
|
||||||
|
.ant-form-item {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
|
@ -1,23 +1,61 @@
|
||||||
export const colorList = ['#5470c6', '#91cc75', '#fac858', '#ee6666', '#73c0de', '#3ba272', '#fc8452', '#9a60b4', '#ea7ccc']
|
export const category_1_bar_options = (data, options) => {
|
||||||
|
// 计算一级分类
|
||||||
export const category_1_bar_options = (data) => {
|
const xData = Object.keys(data)
|
||||||
|
// 计算共有多少二级分类
|
||||||
|
const secondCategory = {}
|
||||||
|
Object.keys(data).forEach(key => {
|
||||||
|
if (Object.prototype.toString.call(data[key]) === '[object Object]') {
|
||||||
|
Object.keys(data[key]).forEach(key1 => {
|
||||||
|
secondCategory[key1] = Array.from({ length: xData.length }).fill(0)
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
secondCategory['其他'] = Array.from({ length: xData.length }).fill(0)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
Object.keys(secondCategory).forEach(key => {
|
||||||
|
xData.forEach((x, idx) => {
|
||||||
|
if (data[x][key]) {
|
||||||
|
secondCategory[key][idx] = data[x][key]
|
||||||
|
}
|
||||||
|
if (typeof data[x] === 'number') {
|
||||||
|
secondCategory['其他'][idx] = data[x]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
return {
|
return {
|
||||||
|
color: options.chartColor.split(','),
|
||||||
grid: {
|
grid: {
|
||||||
top: 15,
|
top: 15,
|
||||||
left: 'left',
|
left: 'left',
|
||||||
right: 0,
|
right: 10,
|
||||||
bottom: 0,
|
bottom: 20,
|
||||||
containLabel: true,
|
containLabel: true,
|
||||||
},
|
},
|
||||||
xAxis: {
|
legend: {
|
||||||
type: 'category',
|
data: Object.keys(secondCategory),
|
||||||
data: Object.keys(data)
|
bottom: 0,
|
||||||
|
type: 'scroll',
|
||||||
},
|
},
|
||||||
yAxis: {
|
xAxis: options.barDirection === 'y' ? {
|
||||||
|
type: 'category',
|
||||||
|
axisTick: { show: false },
|
||||||
|
data: xData
|
||||||
|
}
|
||||||
|
: {
|
||||||
|
type: 'value',
|
||||||
|
splitLine: {
|
||||||
|
show: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
yAxis: options.barDirection === 'y' ? {
|
||||||
type: 'value',
|
type: 'value',
|
||||||
splitLine: {
|
splitLine: {
|
||||||
show: false
|
show: false
|
||||||
}
|
}
|
||||||
|
} : {
|
||||||
|
type: 'category',
|
||||||
|
axisTick: { show: false },
|
||||||
|
data: xData
|
||||||
},
|
},
|
||||||
tooltip: {
|
tooltip: {
|
||||||
trigger: 'axis',
|
trigger: 'axis',
|
||||||
|
@ -25,34 +63,76 @@ export const category_1_bar_options = (data) => {
|
||||||
type: 'shadow'
|
type: 'shadow'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
series: Object.keys(secondCategory).map(key => {
|
||||||
|
return {
|
||||||
|
name: key,
|
||||||
|
type: 'bar',
|
||||||
|
stack: options?.barStack ?? 'total',
|
||||||
|
barGap: 0,
|
||||||
|
emphasis: {
|
||||||
|
focus: 'series'
|
||||||
|
},
|
||||||
|
data: secondCategory[key]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const category_1_line_options = (data, options) => {
|
||||||
|
const xData = Object.keys(data)
|
||||||
|
return {
|
||||||
|
color: options.chartColor.split(','),
|
||||||
|
grid: {
|
||||||
|
top: 15,
|
||||||
|
left: 'left',
|
||||||
|
right: 10,
|
||||||
|
bottom: 20,
|
||||||
|
containLabel: true,
|
||||||
|
},
|
||||||
|
tooltip: {
|
||||||
|
trigger: 'axis'
|
||||||
|
},
|
||||||
|
xAxis: {
|
||||||
|
type: 'category',
|
||||||
|
data: xData
|
||||||
|
},
|
||||||
|
yAxis: {
|
||||||
|
type: 'value'
|
||||||
|
},
|
||||||
series: [
|
series: [
|
||||||
{
|
{
|
||||||
data: Object.keys(data).map((key, index) => {
|
data: xData.map(item => data[item]),
|
||||||
return {
|
type: 'line',
|
||||||
value: data[key],
|
smooth: true,
|
||||||
itemStyle: { color: colorList[0] }
|
showSymbol: false,
|
||||||
|
areaStyle: options?.isShadow ? {
|
||||||
|
opacity: 0.5,
|
||||||
|
color: {
|
||||||
|
type: 'linear',
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
x2: 0,
|
||||||
|
y2: 1,
|
||||||
|
colorStops: [{
|
||||||
|
offset: 0, color: options.chartColor.split(',')[0] // 0% 处的颜色
|
||||||
|
}, {
|
||||||
|
offset: 1, color: '#ffffff' // 100% 处的颜色
|
||||||
|
}],
|
||||||
|
global: false // 缺省为 false
|
||||||
}
|
}
|
||||||
}),
|
} : null
|
||||||
type: 'bar',
|
|
||||||
label: {
|
|
||||||
show: true,
|
|
||||||
position: 'top',
|
|
||||||
fontSize: 10,
|
|
||||||
formatter(data) {
|
|
||||||
return `${data.value || ''}`
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const category_1_pie_options = (data) => {
|
export const category_1_pie_options = (data, options) => {
|
||||||
return {
|
return {
|
||||||
|
color: options.chartColor.split(','),
|
||||||
grid: {
|
grid: {
|
||||||
top: 10,
|
top: 10,
|
||||||
left: 'left',
|
left: 'left',
|
||||||
right: 0,
|
right: 10,
|
||||||
bottom: 0,
|
bottom: 0,
|
||||||
containLabel: true,
|
containLabel: true,
|
||||||
},
|
},
|
||||||
|
@ -89,7 +169,7 @@ export const category_1_pie_options = (data) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const category_2_bar_options = (data) => {
|
export const category_2_bar_options = (data, options, chartType) => {
|
||||||
const xAxisData = Object.keys(data.detail)
|
const xAxisData = Object.keys(data.detail)
|
||||||
const _legend = []
|
const _legend = []
|
||||||
xAxisData.forEach(key => {
|
xAxisData.forEach(key => {
|
||||||
|
@ -97,10 +177,11 @@ export const category_2_bar_options = (data) => {
|
||||||
})
|
})
|
||||||
const legend = [...new Set(_legend)]
|
const legend = [...new Set(_legend)]
|
||||||
return {
|
return {
|
||||||
|
color: options.chartColor.split(','),
|
||||||
grid: {
|
grid: {
|
||||||
top: 15,
|
top: 15,
|
||||||
left: 'left',
|
left: 'left',
|
||||||
right: 0,
|
right: 10,
|
||||||
bottom: 20,
|
bottom: 20,
|
||||||
containLabel: true,
|
containLabel: true,
|
||||||
},
|
},
|
||||||
|
@ -116,41 +197,110 @@ export const category_2_bar_options = (data) => {
|
||||||
type: 'scroll',
|
type: 'scroll',
|
||||||
data: legend
|
data: legend
|
||||||
},
|
},
|
||||||
xAxis: [
|
xAxis: options.barDirection === 'y' || chartType === 'line' ? {
|
||||||
{
|
type: 'category',
|
||||||
type: 'category',
|
axisTick: { show: false },
|
||||||
axisTick: { show: false },
|
data: xAxisData
|
||||||
data: xAxisData
|
}
|
||||||
}
|
: {
|
||||||
],
|
|
||||||
yAxis: [
|
|
||||||
{
|
|
||||||
type: 'value',
|
type: 'value',
|
||||||
splitLine: {
|
splitLine: {
|
||||||
show: false
|
show: false
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
yAxis: options.barDirection === 'y' || chartType === 'line' ? {
|
||||||
|
type: 'value',
|
||||||
|
splitLine: {
|
||||||
|
show: false
|
||||||
}
|
}
|
||||||
],
|
} : {
|
||||||
series: legend.map(le => {
|
type: 'category',
|
||||||
|
axisTick: { show: false },
|
||||||
|
data: xAxisData
|
||||||
|
},
|
||||||
|
series: legend.map((le, index) => {
|
||||||
return {
|
return {
|
||||||
name: le,
|
name: le,
|
||||||
type: 'bar',
|
type: chartType,
|
||||||
barGap: 0,
|
barGap: 0,
|
||||||
emphasis: {
|
emphasis: {
|
||||||
focus: 'series'
|
focus: 'series'
|
||||||
},
|
},
|
||||||
|
stack: chartType === 'line' ? '' : options?.barStack ?? 'total',
|
||||||
data: xAxisData.map(x => {
|
data: xAxisData.map(x => {
|
||||||
return data.detail[x][le] || 0
|
return data.detail[x][le] || 0
|
||||||
}),
|
}),
|
||||||
|
smooth: true,
|
||||||
|
showSymbol: false,
|
||||||
label: {
|
label: {
|
||||||
show: true,
|
show: false,
|
||||||
position: 'top',
|
|
||||||
fontSize: 10,
|
|
||||||
formatter(data) {
|
|
||||||
return `${data.value || ''}`
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
areaStyle: chartType === 'line' && options?.isShadow ? {
|
||||||
|
opacity: 0.5,
|
||||||
|
color: {
|
||||||
|
type: 'linear',
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
x2: 0,
|
||||||
|
y2: 1,
|
||||||
|
colorStops: [{
|
||||||
|
offset: 0, color: options.chartColor.split(',')[index % 8] // 0% 处的颜色
|
||||||
|
}, {
|
||||||
|
offset: 1, color: '#ffffff' // 100% 处的颜色
|
||||||
|
}],
|
||||||
|
global: false // 缺省为 false
|
||||||
|
}
|
||||||
|
} : null
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 => {
|
||||||
|
_legend.push({ value: data.detail[key][key2], name: `${key}-${key2}` })
|
||||||
|
})
|
||||||
|
})
|
||||||
|
return {
|
||||||
|
color: options.chartColor.split(','),
|
||||||
|
grid: {
|
||||||
|
top: 15,
|
||||||
|
left: 'left',
|
||||||
|
right: 10,
|
||||||
|
bottom: 20,
|
||||||
|
containLabel: true,
|
||||||
|
},
|
||||||
|
tooltip: {
|
||||||
|
trigger: 'item'
|
||||||
|
},
|
||||||
|
legend: {
|
||||||
|
orient: 'vertical',
|
||||||
|
left: 'left',
|
||||||
|
type: 'scroll',
|
||||||
|
formatter: function (name) {
|
||||||
|
const _find = _legend.find(item => item.name === name)
|
||||||
|
return `${name}:${_find.value}`
|
||||||
|
}
|
||||||
|
},
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
type: 'pie',
|
||||||
|
radius: '90%',
|
||||||
|
data: _legend,
|
||||||
|
label: {
|
||||||
|
show: false,
|
||||||
|
},
|
||||||
|
emphasis: {
|
||||||
|
itemStyle: {
|
||||||
|
shadowBlur: 10,
|
||||||
|
shadowOffsetX: 0,
|
||||||
|
shadowColor: 'rgba(0, 0, 0, 0.5)'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
<template>
|
||||||
|
<a-select v-model="currenColor">
|
||||||
|
<a-select-option v-for="i in list" :value="i" :key="i">
|
||||||
|
<div>
|
||||||
|
<span :style="{ backgroundColor: color }" class="color-box" v-for="color in i.split(',')" :key="color"></span>
|
||||||
|
</div>
|
||||||
|
</a-select-option>
|
||||||
|
</a-select>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'ColorListPicker',
|
||||||
|
model: {
|
||||||
|
prop: 'value',
|
||||||
|
event: 'change',
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
value: {
|
||||||
|
type: [String, Array],
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
list: [
|
||||||
|
'#6592FD,#6EE3EB,#44C2FD,#5F59F7,#1A348F,#7D8FCF,#A6D1E5,#8E56DD',
|
||||||
|
'#C1A9DC,#E2B5CD,#EE8EBC,#8483C3,#4D66BD,#213764,#D9B6E9,#DD88EB',
|
||||||
|
'#6FC4DF,#9FE8CE,#16B4BE,#86E6FB,#1871A3,#E1BF8D,#ED8D8D,#DD88EB',
|
||||||
|
'#F8B751,#FC9054,#FFE380,#DF963F,#AB5200,#EA9387,#FFBB7C,#D27467',
|
||||||
|
],
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
currenColor: {
|
||||||
|
get() {
|
||||||
|
return this.value
|
||||||
|
},
|
||||||
|
set(val) {
|
||||||
|
this.$emit('change', val)
|
||||||
|
return val
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.color-box {
|
||||||
|
display: inline-block;
|
||||||
|
width: 40px;
|
||||||
|
height: 10px;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,79 @@
|
||||||
|
<template>
|
||||||
|
<div class="color-picker">
|
||||||
|
<div
|
||||||
|
:style="{
|
||||||
|
background: Array.isArray(item) ? `linear-gradient(to bottom, ${item[0]} 0%, ${item[1]} 100%)` : item,
|
||||||
|
}"
|
||||||
|
:class="{ 'color-picker-box': true, 'color-picker-box-selected': isEqual(currenColor, item) }"
|
||||||
|
v-for="item in colorList"
|
||||||
|
:key="Array.isArray(item) ? item.join() : item"
|
||||||
|
@click="changeColor(item)"
|
||||||
|
></div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import _ from 'lodash'
|
||||||
|
export default {
|
||||||
|
name: 'ColorPicker',
|
||||||
|
model: {
|
||||||
|
prop: 'value',
|
||||||
|
event: 'change',
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
value: {
|
||||||
|
type: [String, Array],
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
|
colorList: {
|
||||||
|
type: Array,
|
||||||
|
default: () => [],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
currenColor: {
|
||||||
|
get() {
|
||||||
|
return this.value
|
||||||
|
},
|
||||||
|
set(val) {
|
||||||
|
this.$emit('change', val)
|
||||||
|
return val
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
isEqual: _.isEqual,
|
||||||
|
changeColor(item) {
|
||||||
|
this.$emit('change', item)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.color-picker {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
margin-top: 10px;
|
||||||
|
.color-picker-box {
|
||||||
|
width: 19px;
|
||||||
|
height: 19px;
|
||||||
|
border: 1px solid #dae2e7;
|
||||||
|
border-radius: 1px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.color-picker-box-selected {
|
||||||
|
position: relative;
|
||||||
|
&:after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
border: 1px solid #43bbff;
|
||||||
|
top: -3px;
|
||||||
|
left: -3px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -1,5 +1,4 @@
|
||||||
export const dashboardCategory = {
|
export const dashboardCategory = {
|
||||||
0: { label: 'CI数统计' },
|
1: { label: '默认' },
|
||||||
1: { label: '按属性值分类统计' },
|
2: { label: '关系' }
|
||||||
2: { label: '关系统计' }
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,8 +11,8 @@
|
||||||
<template v-if="layout && layout.length">
|
<template v-if="layout && layout.length">
|
||||||
<div v-if="editable">
|
<div v-if="editable">
|
||||||
<a-button
|
<a-button
|
||||||
:style="{ marginLeft: '10px' }"
|
:style="{ marginLeft: '22px', marginTop: '20px' }"
|
||||||
@click="openChartForm('add', {})"
|
@click="openChartForm('add', { options: { w: 3 } })"
|
||||||
ghost
|
ghost
|
||||||
type="primary"
|
type="primary"
|
||||||
size="small"
|
size="small"
|
||||||
|
@ -39,11 +39,44 @@
|
||||||
:h="item.h"
|
:h="item.h"
|
||||||
:i="item.i"
|
:i="item.i"
|
||||||
:key="item.i"
|
:key="item.i"
|
||||||
:style="{ backgroundColor: '#fafafa' }"
|
:style="{
|
||||||
|
background:
|
||||||
|
item.options.chartType === 'count'
|
||||||
|
? Array.isArray(item.options.bgColor)
|
||||||
|
? `linear-gradient(to bottom, ${item.options.bgColor[0]} 0%, ${item.options.bgColor[1]} 100%)`
|
||||||
|
: item.options.bgColor
|
||||||
|
: '#fafafa',
|
||||||
|
}"
|
||||||
>
|
>
|
||||||
<CardTitle>{{ item.options.name }}</CardTitle>
|
<div class="cmdb-dashboard-grid-item-title">
|
||||||
|
<template v-if="item.options.chartType !== 'count' && item.options.showIcon && getCiType(item)">
|
||||||
|
<template v-if="getCiType(item).icon">
|
||||||
|
<img
|
||||||
|
v-if="getCiType(item).icon.split('$$')[2]"
|
||||||
|
:src="`/api/common-setting/v1/file/${getCiType(item).icon.split('$$')[3]}`"
|
||||||
|
/>
|
||||||
|
<ops-icon
|
||||||
|
v-else
|
||||||
|
:style="{
|
||||||
|
color: getCiType(item).icon.split('$$')[1],
|
||||||
|
}"
|
||||||
|
:type="getCiType(item).icon.split('$$')[0]"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<span :style="{ color: '#2f54eb' }" v-else>{{ getCiType(item).name[0].toUpperCase() }}</span>
|
||||||
|
</template>
|
||||||
|
<span :style="{ color: item.options.chartType === 'count' ? item.options.fontColor : '#000' }">{{
|
||||||
|
item.options.name
|
||||||
|
}}</span>
|
||||||
|
</div>
|
||||||
<a-dropdown v-if="editable">
|
<a-dropdown v-if="editable">
|
||||||
<a class="cmdb-dashboard-grid-item-operation"><a-icon type="menu"></a-icon></a>
|
<a
|
||||||
|
class="cmdb-dashboard-grid-item-operation"
|
||||||
|
:style="{
|
||||||
|
color: item.options.chartType === 'count' ? item.options.fontColor : '',
|
||||||
|
}"
|
||||||
|
><a-icon type="menu"></a-icon
|
||||||
|
></a>
|
||||||
<a-menu slot="overlay">
|
<a-menu slot="overlay">
|
||||||
<a-menu-item>
|
<a-menu-item>
|
||||||
<a @click="() => openChartForm('edit', item)"><a-icon style="margin-right:5px" type="edit" />编辑</a>
|
<a @click="() => openChartForm('edit', item)"><a-icon style="margin-right:5px" type="edit" />编辑</a>
|
||||||
|
@ -53,13 +86,13 @@
|
||||||
</a-menu-item>
|
</a-menu-item>
|
||||||
</a-menu>
|
</a-menu>
|
||||||
</a-dropdown>
|
</a-dropdown>
|
||||||
<a
|
<!-- <a
|
||||||
v-if="editable && item.category === 1"
|
v-if="editable && item.category === 1"
|
||||||
class="cmdb-dashboard-grid-item-chart-type"
|
class="cmdb-dashboard-grid-item-chart-type"
|
||||||
@click="changeChartType(item)"
|
@click="changeChartType(item)"
|
||||||
><a-icon
|
><a-icon
|
||||||
:type="item.options.chartType === 'bar' ? 'bar-chart' : 'pie-chart'"
|
:type="item.options.chartType === 'bar' ? 'bar-chart' : 'pie-chart'"
|
||||||
/></a>
|
/></a> -->
|
||||||
<Chart
|
<Chart
|
||||||
:ref="`chart_${item.id}`"
|
:ref="`chart_${item.id}`"
|
||||||
:chartId="item.id"
|
:chartId="item.id"
|
||||||
|
@ -67,18 +100,26 @@
|
||||||
:category="item.category"
|
:category="item.category"
|
||||||
:options="item.options"
|
:options="item.options"
|
||||||
:editable="editable"
|
:editable="editable"
|
||||||
|
:ci_types="ci_types"
|
||||||
|
:type_id="item.type_id"
|
||||||
/>
|
/>
|
||||||
</GridItem>
|
</GridItem>
|
||||||
</GridLayout>
|
</GridLayout>
|
||||||
</template>
|
</template>
|
||||||
<div v-else class="dashboard-empty">
|
<div v-else class="dashboard-empty">
|
||||||
<a-empty :image="emptyImage" description=""></a-empty>
|
<a-empty :image="emptyImage" description=""></a-empty>
|
||||||
<a-button @click="openChartForm('add', {})" v-if="editable" size="small" type="primary" icon="plus">
|
<a-button
|
||||||
|
@click="openChartForm('add', { options: { w: 3 } })"
|
||||||
|
v-if="editable"
|
||||||
|
size="small"
|
||||||
|
type="primary"
|
||||||
|
icon="plus"
|
||||||
|
>
|
||||||
定制仪表盘
|
定制仪表盘
|
||||||
</a-button>
|
</a-button>
|
||||||
<span v-else>管理员暂未定制仪表盘</span>
|
<span v-else>管理员暂未定制仪表盘</span>
|
||||||
</div>
|
</div>
|
||||||
<ChartForm ref="chartForm" @refresh="refresh" :ci_types="ci_types" />
|
<ChartForm ref="chartForm" @refresh="refresh" :ci_types="ci_types" :totalData="totalData" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -127,12 +168,14 @@ export default {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
created() {
|
||||||
this.getLayout()
|
|
||||||
getCITypes().then((res) => {
|
getCITypes().then((res) => {
|
||||||
this.ci_types = res.ci_types
|
this.ci_types = res.ci_types
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
mounted() {
|
||||||
|
this.getLayout()
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
async getLayout() {
|
async getLayout() {
|
||||||
const res = await getCustomDashboard()
|
const res = await getCustomDashboard()
|
||||||
|
@ -196,6 +239,13 @@ export default {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
getCiType(item) {
|
||||||
|
if (item.type_id || item.options?.type_ids) {
|
||||||
|
const _find = this.ci_types.find((type) => type.id === item.type_id || type.id === item.options?.type_ids[0])
|
||||||
|
return _find || null
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -206,15 +256,18 @@ export default {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
.cmdb-dashboard-grid-item {
|
.cmdb-dashboard-grid-item {
|
||||||
border-radius: 15px;
|
border-radius: 8px;
|
||||||
|
padding: 6px 12px;
|
||||||
.cmdb-dashboard-grid-item-title {
|
.cmdb-dashboard-grid-item-title {
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
padding-left: 6px;
|
color: #000000;
|
||||||
color: #000000bd;
|
|
||||||
}
|
}
|
||||||
.cmdb-dashboard-grid-item-operation {
|
.cmdb-dashboard-grid-item-operation {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 6px;
|
right: 12px;
|
||||||
top: 6px;
|
top: 6px;
|
||||||
}
|
}
|
||||||
.cmdb-dashboard-grid-item-chart-type {
|
.cmdb-dashboard-grid-item-chart-type {
|
||||||
|
@ -224,3 +277,26 @@ export default {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
<style lang="less">
|
||||||
|
.cmdb-dashboard-grid-item-title {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
> i {
|
||||||
|
font-size: 16px;
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
> img {
|
||||||
|
width: 16px;
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
> span:not(:last-child) {
|
||||||
|
display: inline-block;
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
font-size: 16px;
|
||||||
|
text-align: center;
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
Loading…
Reference in New Issue