forked from github/dataease
feat: 仪表盘阈值
This commit is contained in:
parent
6ccc29ebfd
commit
6a36dd456c
@ -1041,7 +1041,10 @@ export default {
|
||||
field_fixed: 'Fixed',
|
||||
line_type_dotted: 'Dotted',
|
||||
value_can_not_empty: 'Value can not be empty',
|
||||
value_error: 'Value illegal'
|
||||
value_error: 'Value illegal',
|
||||
threshold: 'Threshold',
|
||||
threshold_range: 'Range',
|
||||
gauge_threshold_format_error: 'Format Error'
|
||||
},
|
||||
dataset: {
|
||||
sheet_warn: 'There are multiple sheet pages, and the first one is extracted by default',
|
||||
|
@ -1041,7 +1041,10 @@ export default {
|
||||
field_fixed: '固定值',
|
||||
line_type_dotted: '點',
|
||||
value_can_not_empty: '值不能為空',
|
||||
value_error: '值必須為數值'
|
||||
value_error: '值必須為數值',
|
||||
threshold: '閾值',
|
||||
threshold_range: '閾值區間',
|
||||
gauge_threshold_format_error: '格式錯誤'
|
||||
},
|
||||
dataset: {
|
||||
sheet_warn: '有多個 Sheet 頁,默認抽取第一個',
|
||||
|
@ -1044,7 +1044,10 @@ export default {
|
||||
field_fixed: '固定值',
|
||||
line_type_dotted: '点',
|
||||
value_can_not_empty: '值不能为空',
|
||||
value_error: '值必须为数值'
|
||||
value_error: '值必须为数值',
|
||||
threshold: '阈值',
|
||||
threshold_range: '阈值区间',
|
||||
gauge_threshold_format_error: '格式错误'
|
||||
},
|
||||
dataset: {
|
||||
sheet_warn: '有多个 Sheet 页,默认抽取第一个',
|
||||
|
@ -244,6 +244,9 @@ export const DEFAULT_FUNCTION_CFG = {
|
||||
sliderShow: false,
|
||||
sliderRange: [0, 10]
|
||||
}
|
||||
export const DEFAULT_THRESHOLD = {
|
||||
gaugeThreshold: ''
|
||||
}
|
||||
// chart config
|
||||
export const BASE_BAR = {
|
||||
title: {
|
||||
|
@ -49,6 +49,34 @@ export function baseGaugeOption(chart_option, chart) {
|
||||
value: chart.data.series[0].data[0]
|
||||
}
|
||||
chart_option.series[0].data.push(y)
|
||||
// threshold
|
||||
if (chart.senior) {
|
||||
const range = []
|
||||
const senior = JSON.parse(chart.senior)
|
||||
const threshold = JSON.parse(JSON.stringify(senior.threshold))
|
||||
if (threshold.gaugeThreshold && threshold.gaugeThreshold !== '') {
|
||||
const arr = threshold.gaugeThreshold.split(',')
|
||||
for (let i = 0; i < arr.length; i++) {
|
||||
const ele = arr[i]
|
||||
const p = parseInt(ele) / 100
|
||||
range.push([p, hexColorToRGBA(customAttr.color.colors[i % 9], customAttr.color.alpha)])
|
||||
}
|
||||
|
||||
range.push([1, hexColorToRGBA(customAttr.color.colors[arr.length % 9], customAttr.color.alpha)])
|
||||
chart_option.series[0].axisLine = {
|
||||
lineStyle: {
|
||||
color: range
|
||||
}
|
||||
}
|
||||
|
||||
chart_option.series[0].itemStyle = {
|
||||
color: 'auto'
|
||||
}
|
||||
chart_option.series[0].progress = {
|
||||
show: false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// console.log(chart_option);
|
||||
|
@ -33,11 +33,39 @@ export function baseGaugeOptionAntV(plot, container, chart, action) {
|
||||
labelContent = false
|
||||
}
|
||||
}
|
||||
const per = (parseFloat(data) / parseFloat(max))
|
||||
|
||||
const range = [0]
|
||||
let index = 0
|
||||
let flag = false
|
||||
let hasThreshold = false
|
||||
|
||||
if (chart.senior) {
|
||||
const senior = JSON.parse(chart.senior)
|
||||
const threshold = JSON.parse(JSON.stringify(senior.threshold))
|
||||
if (threshold.gaugeThreshold && threshold.gaugeThreshold !== '') {
|
||||
hasThreshold = true
|
||||
const arr = threshold.gaugeThreshold.split(',')
|
||||
for (let i = 0; i < arr.length; i++) {
|
||||
const ele = arr[i]
|
||||
const p = parseInt(ele) / 100
|
||||
range.push(p)
|
||||
if (!flag && per <= p) {
|
||||
flag = true
|
||||
index = i
|
||||
}
|
||||
}
|
||||
if (!flag) {
|
||||
index = arr.length
|
||||
}
|
||||
}
|
||||
}
|
||||
range.push(1)
|
||||
|
||||
// options
|
||||
const options = {
|
||||
theme: theme,
|
||||
percent: (parseFloat(data) / parseFloat(max)),
|
||||
percent: per,
|
||||
startAngle: startAngel,
|
||||
endAngle: endAngel,
|
||||
appendPadding: getPadding(chart),
|
||||
@ -52,6 +80,24 @@ export function baseGaugeOptionAntV(plot, container, chart, action) {
|
||||
// lineCap: 'round'
|
||||
// }
|
||||
}
|
||||
if (hasThreshold) {
|
||||
options.range = {
|
||||
color: theme.styleSheet.paletteQualitative10,
|
||||
ticks: range
|
||||
}
|
||||
options.indicator = {
|
||||
pointer: {
|
||||
style: {
|
||||
stroke: theme.styleSheet.paletteQualitative10[index % 9]
|
||||
}
|
||||
},
|
||||
pin: {
|
||||
style: {
|
||||
stroke: theme.styleSheet.paletteQualitative10[index % 9]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 开始渲染
|
||||
if (plot) {
|
||||
|
123
frontend/src/views/chart/components/senior/Threshold.vue
Normal file
123
frontend/src/views/chart/components/senior/Threshold.vue
Normal file
@ -0,0 +1,123 @@
|
||||
<template>
|
||||
<div style="width: 100%">
|
||||
<el-col v-if="chart.type && chart.type === 'gauge'">
|
||||
<el-form ref="thresholdForm" :model="thresholdForm" label-width="80px" size="mini">
|
||||
<el-form-item :label="$t('chart.threshold_range')+'(%)'" class="form-item">
|
||||
<span>0,</span>
|
||||
<el-input v-model="thresholdForm.gaugeThreshold" style="width: 160px;margin: 0 10px;" :placeholder="$t('chart.threshold_range')" size="mini" clearable @change="changeThreshold" />
|
||||
<span>,100</span>
|
||||
<el-tooltip class="item" effect="dark" placement="bottom">
|
||||
<div slot="content">
|
||||
阈值设置,决定仪表盘区间颜色,为空则不开启阈值,范围(0-100),仅限整数,且逐级递增
|
||||
<br>
|
||||
例如:输入 30,70;表示:分为3段,分别为[0,30],(30,70],(70,100]
|
||||
</div>
|
||||
<i class="el-icon-info" style="cursor: pointer;margin-left: 10px;font-size: 12px;" />
|
||||
</el-tooltip>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-col>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { DEFAULT_THRESHOLD } from '@/views/chart/chart/chart'
|
||||
|
||||
export default {
|
||||
name: 'Threshold',
|
||||
props: {
|
||||
chart: {
|
||||
type: Object,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
thresholdForm: JSON.parse(JSON.stringify(DEFAULT_THRESHOLD))
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
'chart': {
|
||||
handler: function() {
|
||||
this.initData()
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.initData()
|
||||
},
|
||||
methods: {
|
||||
initData() {
|
||||
const chart = JSON.parse(JSON.stringify(this.chart))
|
||||
if (chart.senior) {
|
||||
let senior = null
|
||||
if (Object.prototype.toString.call(chart.senior) === '[object Object]') {
|
||||
senior = JSON.parse(JSON.stringify(chart.senior))
|
||||
} else {
|
||||
senior = JSON.parse(chart.senior)
|
||||
}
|
||||
if (senior.threshold) {
|
||||
this.thresholdForm = senior.threshold
|
||||
} else {
|
||||
this.thresholdForm = JSON.parse(JSON.stringify(DEFAULT_THRESHOLD))
|
||||
}
|
||||
}
|
||||
},
|
||||
changeThreshold() {
|
||||
// check input
|
||||
if (this.thresholdForm.gaugeThreshold) {
|
||||
const arr = this.thresholdForm.gaugeThreshold.split(',')
|
||||
for (let i = 0; i < arr.length; i++) {
|
||||
const ele = arr[i]
|
||||
if (ele.indexOf('.') > -1 || parseInt(ele).toString() === 'NaN' || parseInt(ele) < 1 || parseInt(ele) > 99) {
|
||||
this.$message({
|
||||
message: this.$t('chart.gauge_threshold_format_error'),
|
||||
type: 'error',
|
||||
showClose: true
|
||||
})
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
this.$emit('onThresholdChange', this.thresholdForm)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.shape-item{
|
||||
padding: 6px;
|
||||
border: none;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
.form-item-slider>>>.el-form-item__label{
|
||||
font-size: 12px;
|
||||
line-height: 38px;
|
||||
}
|
||||
.form-item>>>.el-form-item__label{
|
||||
font-size: 12px;
|
||||
}
|
||||
.el-select-dropdown__item{
|
||||
padding: 0 20px;
|
||||
}
|
||||
span{
|
||||
font-size: 12px
|
||||
}
|
||||
.el-form-item{
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
|
||||
.switch-style{
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
margin-top: -4px;
|
||||
}
|
||||
.color-picker-style{
|
||||
cursor: pointer;
|
||||
z-index: 1003;
|
||||
}
|
||||
</style>
|
@ -309,7 +309,7 @@ import {
|
||||
DEFAULT_YAXIS_EXT_STYLE,
|
||||
DEFAULT_BACKGROUND_COLOR,
|
||||
DEFAULT_SPLIT,
|
||||
DEFAULT_FUNCTION_CFG
|
||||
DEFAULT_FUNCTION_CFG, DEFAULT_THRESHOLD
|
||||
} from '../chart/chart'
|
||||
|
||||
export default {
|
||||
@ -767,7 +767,8 @@ export default {
|
||||
})
|
||||
view.senior = JSON.stringify({
|
||||
functionCfg: DEFAULT_FUNCTION_CFG,
|
||||
assistLine: []
|
||||
assistLine: [],
|
||||
threshold: DEFAULT_THRESHOLD
|
||||
})
|
||||
view.stylePriority = 'view' // 默认样式优先级视图
|
||||
view.xaxis = JSON.stringify([])
|
||||
|
@ -813,11 +813,11 @@
|
||||
<el-tab-pane :label="$t('chart.senior')" class="padding-tab" style="width: 360px;">
|
||||
<el-row class="view-panel">
|
||||
<div
|
||||
v-if="view.type && (view.type.includes('bar') || view.type.includes('line') || view.type.includes('mix'))"
|
||||
v-if="view.type && (view.type.includes('bar') || view.type.includes('line') || view.type.includes('mix') || view.type.includes('gauge'))"
|
||||
style="overflow:auto;border-right: 1px solid #e6e6e6;height: 100%;width: 100%;"
|
||||
class="attr-style theme-border-class"
|
||||
>
|
||||
<el-row>
|
||||
<el-row v-if="view.type && (view.type.includes('bar') || view.type.includes('line') || view.type.includes('mix'))">
|
||||
<span class="padding-lr">{{ $t('chart.senior_cfg') }}</span>
|
||||
<el-collapse v-model="attrActiveNames" class="style-collapse">
|
||||
<el-collapse-item name="function" :title="$t('chart.function_cfg')">
|
||||
@ -825,12 +825,15 @@
|
||||
</el-collapse-item>
|
||||
</el-collapse>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-row v-if="view.type && (view.type.includes('bar') || view.type.includes('line') || view.type.includes('mix') || view.type.includes('gauge'))">
|
||||
<span class="padding-lr">{{ $t('chart.analyse_cfg') }}</span>
|
||||
<el-collapse v-model="styleActiveNames" class="style-collapse">
|
||||
<el-collapse-item name="analyse" :title="$t('chart.assist_line')">
|
||||
<el-collapse-item v-if="view.type && (view.type.includes('bar') || view.type.includes('line') || view.type.includes('mix'))" name="analyse" :title="$t('chart.assist_line')">
|
||||
<assist-line :param="param" class="attr-selector" :chart="chart" @onAssistLineChange="onAssistLineChange" />
|
||||
</el-collapse-item>
|
||||
<el-collapse-item v-if="view.type && (view.type.includes('gauge'))" name="threshold" :title="$t('chart.threshold')">
|
||||
<threshold :param="param" class="attr-selector" :chart="chart" @onThresholdChange="onThresholdChange" />
|
||||
</el-collapse-item>
|
||||
</el-collapse>
|
||||
</el-row>
|
||||
</div>
|
||||
@ -1039,7 +1042,7 @@ import {
|
||||
DEFAULT_LABEL,
|
||||
DEFAULT_LEGEND_STYLE,
|
||||
DEFAULT_SIZE,
|
||||
DEFAULT_SPLIT,
|
||||
DEFAULT_SPLIT, DEFAULT_THRESHOLD,
|
||||
DEFAULT_TITLE_STYLE,
|
||||
DEFAULT_TOOLTIP,
|
||||
DEFAULT_XAXIS_STYLE,
|
||||
@ -1084,9 +1087,11 @@ import DimensionExtItem from '@/views/chart/components/drag-item/DimensionExtIte
|
||||
import PluginCom from '@/views/system/plugin/PluginCom'
|
||||
import FunctionCfg from '@/views/chart/components/senior/FunctionCfg'
|
||||
import AssistLine from '@/views/chart/components/senior/AssistLine'
|
||||
import Threshold from '@/views/chart/components/senior/Threshold'
|
||||
export default {
|
||||
name: 'ChartEdit',
|
||||
components: {
|
||||
Threshold,
|
||||
AssistLine,
|
||||
FunctionCfg,
|
||||
DimensionExtItem,
|
||||
@ -1174,7 +1179,8 @@ export default {
|
||||
},
|
||||
senior: {
|
||||
functionCfg: DEFAULT_FUNCTION_CFG,
|
||||
assistLine: []
|
||||
assistLine: [],
|
||||
threshold: DEFAULT_THRESHOLD
|
||||
},
|
||||
customFilter: [],
|
||||
render: 'antv',
|
||||
@ -1756,6 +1762,11 @@ export default {
|
||||
this.calcStyle()
|
||||
},
|
||||
|
||||
onThresholdChange(val) {
|
||||
this.view.senior.threshold = val
|
||||
this.calcStyle()
|
||||
},
|
||||
|
||||
showDimensionEditFilter(item) {
|
||||
this.dimensionItem = JSON.parse(JSON.stringify(item))
|
||||
this.dimensionFilterEdit = true
|
||||
|
Loading…
Reference in New Issue
Block a user