feat: 透视表合计、小计

This commit is contained in:
junjun 2022-03-09 15:45:48 +08:00
parent 62f7cdd5e0
commit e275e533f5
8 changed files with 298 additions and 7 deletions

View File

@ -1044,7 +1044,18 @@ export default {
value_error: 'Value illegal',
threshold: 'Threshold',
threshold_range: 'Range',
gauge_threshold_format_error: 'Format Error'
gauge_threshold_format_error: 'Format Error',
total_cfg: 'Total Config',
col_cfg: 'Column',
row_cfg: 'Row',
total_show: 'Total',
total_position: 'Position',
total_label: 'Alias',
sub_total_show: 'Sub Total',
total_pos_top: 'Top',
total_pos_bottom: 'Bottom',
total_pos_left: 'Left',
total_pos_right: 'Right'
},
dataset: {
sheet_warn: 'There are multiple sheet pages, and the first one is extracted by default',

View File

@ -1044,7 +1044,18 @@ export default {
value_error: '值必須為數值',
threshold: '閾值',
threshold_range: '閾值區間',
gauge_threshold_format_error: '格式錯誤'
gauge_threshold_format_error: '格式錯誤',
total_cfg: '總計配置',
col_cfg: '列匯總',
row_cfg: '行匯總',
total_show: '總計',
total_position: '位置',
total_label: '別名',
sub_total_show: '小計',
total_pos_top: '頂部',
total_pos_bottom: '底部',
total_pos_left: '左側',
total_pos_right: '右側'
},
dataset: {
sheet_warn: '有多個 Sheet 頁,默認抽取第一個',

View File

@ -1047,7 +1047,18 @@ export default {
value_error: '值必须为数值',
threshold: '阈值',
threshold_range: '阈值区间',
gauge_threshold_format_error: '格式错误'
gauge_threshold_format_error: '格式错误',
total_cfg: '总计配置',
col_cfg: '列汇总',
row_cfg: '行汇总',
total_show: '总计',
total_position: '位置',
total_label: '别名',
sub_total_show: '小计',
total_pos_top: '顶部',
total_pos_bottom: '底部',
total_pos_left: '左侧',
total_pos_right: '右侧'
},
dataset: {
sheet_warn: '有多个 Sheet 页,默认抽取第一个',

View File

@ -78,6 +78,38 @@ export const DEFAULT_TOOLTIP = {
},
formatter: ''
}
export const DEFAULT_TOTAL = {
row: {
showGrandTotals: true,
showSubTotals: true,
reverseLayout: false,
reverseSubLayout: false,
label: '总计',
subLabel: '小计',
subTotalsDimensions: [],
calcTotals: {
aggregation: 'SUM'
},
calcSubTotals: {
aggregation: 'SUM'
}
},
col: {
showGrandTotals: true,
showSubTotals: true,
reverseLayout: false,
reverseSubLayout: false,
label: '总计',
subLabel: '小计',
subTotalsDimensions: [],
calcTotals: {
aggregation: 'SUM'
},
calcSubTotals: {
aggregation: 'SUM'
}
}
}
export const DEFAULT_TITLE_STYLE = {
show: true,
fontSize: '18',

View File

@ -1,5 +1,6 @@
import { TableSheet, S2Event, PivotSheet } from '@antv/s2'
import { getCustomTheme, getSize } from '@/views/chart/chart/common/common_table'
import { DEFAULT_TOTAL } from '@/views/chart/chart/chart'
export function baseTableInfo(s2, container, chart, action, tableData) {
const containerDom = document.getElementById(container)
@ -281,11 +282,31 @@ export function baseTablePivot(s2, container, chart, action, tableData) {
data: tableData
}
// total config
let totalCfg = {}
const chartObj = JSON.parse(JSON.stringify(chart))
if (chartObj.customAttr) {
let customAttr = null
if (Object.prototype.toString.call(chartObj.customAttr) === '[object Object]') {
customAttr = JSON.parse(JSON.stringify(chartObj.customAttr))
} else {
customAttr = JSON.parse(chartObj.customAttr)
}
if (customAttr.totalCfg) {
totalCfg = customAttr.totalCfg
} else {
totalCfg = JSON.parse(JSON.stringify(DEFAULT_TOTAL))
}
}
totalCfg.row.subTotalsDimensions = r
totalCfg.col.subTotalsDimensions = c
// options
const s2Options = {
width: containerDom.offsetWidth,
height: containerDom.offsetHeight,
style: getSize(chart)
style: getSize(chart),
totals: totalCfg
}
// 开始渲染

View File

@ -0,0 +1,182 @@
<template>
<div style="width: 100%">
<el-col>
<el-form ref="totalForm" :model="totalForm" label-width="80px" size="mini">
<el-divider content-position="center" class="divider-style">{{ $t('chart.row_cfg') }}</el-divider>
<el-form-item :label="$t('chart.total_show')" class="form-item">
<el-checkbox v-model="totalForm.row.showGrandTotals" @change="changeTotalCfg">{{ $t('chart.show') }}</el-checkbox>
</el-form-item>
<div v-show="totalForm.row.showGrandTotals">
<el-form-item :label="$t('chart.total_position')" class="form-item">
<el-radio-group v-model="totalForm.row.reverseLayout" @change="changeTotalCfg">
<el-radio :label="true">{{ $t('chart.total_pos_top') }}</el-radio>
<el-radio :label="false">{{ $t('chart.total_pos_bottom') }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item :label="$t('chart.total_label')" class="form-item">
<el-input v-model="totalForm.row.label" style="width: 160px;" :placeholder="$t('chart.total_label')" size="mini" clearable @change="changeTotalCfg" />
</el-form-item>
</div>
<el-form-item :label="$t('chart.sub_total_show')" class="form-item">
<el-checkbox v-model="totalForm.row.showSubTotals" :disabled="rowNum < 2" @change="changeTotalCfg">{{ $t('chart.show') }}</el-checkbox>
</el-form-item>
<div v-show="totalForm.row.showSubTotals">
<el-form-item :label="$t('chart.total_position')" class="form-item">
<el-radio-group v-model="totalForm.row.reverseSubLayout" :disabled="rowNum < 2" @change="changeTotalCfg">
<el-radio :label="true">{{ $t('chart.total_pos_top') }}</el-radio>
<el-radio :label="false">{{ $t('chart.total_pos_bottom') }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item :label="$t('chart.total_label')" class="form-item">
<el-input v-model="totalForm.row.subLabel" :disabled="rowNum < 2" style="width: 160px;" :placeholder="$t('chart.total_label')" size="mini" clearable @change="changeTotalCfg" />
</el-form-item>
</div>
<el-divider content-position="center" class="divider-style">{{ $t('chart.col_cfg') }}</el-divider>
<el-form-item :label="$t('chart.total_show')" class="form-item">
<el-checkbox v-model="totalForm.col.showGrandTotals" @change="changeTotalCfg">{{ $t('chart.show') }}</el-checkbox>
</el-form-item>
<div v-show="totalForm.col.showGrandTotals">
<el-form-item :label="$t('chart.total_position')" class="form-item">
<el-radio-group v-model="totalForm.col.reverseLayout" @change="changeTotalCfg">
<el-radio :label="true">{{ $t('chart.total_pos_left') }}</el-radio>
<el-radio :label="false">{{ $t('chart.total_pos_right') }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item :label="$t('chart.total_label')" class="form-item">
<el-input v-model="totalForm.col.label" style="width: 160px;" :placeholder="$t('chart.total_label')" size="mini" clearable @change="changeTotalCfg" />
</el-form-item>
</div>
<el-form-item :label="$t('chart.sub_total_show')" class="form-item">
<el-checkbox v-model="totalForm.col.showSubTotals" :disabled="colNum < 2" @change="changeTotalCfg">{{ $t('chart.show') }}</el-checkbox>
</el-form-item>
<div v-show="totalForm.col.showSubTotals">
<el-form-item :label="$t('chart.total_position')" class="form-item">
<el-radio-group v-model="totalForm.col.reverseSubLayout" :disabled="colNum < 2" @change="changeTotalCfg">
<el-radio :label="true">{{ $t('chart.total_pos_left') }}</el-radio>
<el-radio :label="false">{{ $t('chart.total_pos_right') }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item :label="$t('chart.total_label')" class="form-item">
<el-input v-model="totalForm.col.subLabel" :disabled="colNum < 2" style="width: 160px;" :placeholder="$t('chart.total_label')" size="mini" clearable @change="changeTotalCfg" />
</el-form-item>
</div>
</el-form>
</el-col>
</div>
</template>
<script>
import { DEFAULT_TOTAL } from '@/views/chart/chart/chart'
export default {
name: 'TotalCfg',
props: {
chart: {
type: Object,
required: true
}
},
data() {
return {
totalForm: JSON.parse(JSON.stringify(DEFAULT_TOTAL))
}
},
computed: {
rowNum() {
const chart = JSON.parse(JSON.stringify(this.chart))
if (chart.xaxisExt) {
let arr = null
if (Object.prototype.toString.call(chart.xaxisExt) === '[object Object]') {
arr = JSON.parse(JSON.stringify(chart.xaxisExt))
} else {
arr = JSON.parse(chart.xaxisExt)
}
return arr.length
}
return 0
},
colNum() {
const chart = JSON.parse(JSON.stringify(this.chart))
if (chart.xaxis) {
let arr = null
if (Object.prototype.toString.call(chart.xaxis) === '[object Object]') {
arr = JSON.parse(JSON.stringify(chart.xaxis))
} else {
arr = JSON.parse(chart.xaxis)
}
return arr.length
}
return 0
}
},
watch: {
'chart': {
handler: function() {
this.initData()
}
}
},
mounted() {
this.initData()
},
methods: {
initData() {
const chart = JSON.parse(JSON.stringify(this.chart))
if (chart.customAttr) {
let customAttr = null
if (Object.prototype.toString.call(chart.customAttr) === '[object Object]') {
customAttr = JSON.parse(JSON.stringify(chart.customAttr))
} else {
customAttr = JSON.parse(chart.customAttr)
}
if (customAttr.totalCfg) {
this.totalForm = customAttr.totalCfg
} else {
this.totalForm = JSON.parse(JSON.stringify(DEFAULT_TOTAL))
}
}
},
changeTotalCfg() {
this.$emit('onTotalCfgChange', this.totalForm)
}
}
}
</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;
}
.el-divider--horizontal {
margin: 10px 0
}
.divider-style>>>.el-divider__text{
color: #606266;
font-size: 12px;
font-weight: 400;
padding: 0 10px;
}
</style>

View File

@ -310,7 +310,8 @@ import {
DEFAULT_BACKGROUND_COLOR,
DEFAULT_SPLIT,
DEFAULT_FUNCTION_CFG,
DEFAULT_THRESHOLD
DEFAULT_THRESHOLD,
DEFAULT_TOTAL
} from '../chart/chart'
export default {
@ -755,7 +756,8 @@ export default {
tableColor: DEFAULT_COLOR_CASE,
size: DEFAULT_SIZE,
label: DEFAULT_LABEL,
tooltip: DEFAULT_TOOLTIP
tooltip: DEFAULT_TOOLTIP,
totalCfg: DEFAULT_TOTAL
})
view.customStyle = JSON.stringify({
text: DEFAULT_TITLE_STYLE,

View File

@ -676,6 +676,18 @@
@onTooltipChange="onTooltipChange"
/>
</el-collapse-item>
<el-collapse-item
v-show="view.type === 'table-pivot'"
name="totalCfg"
:title="$t('chart.total_cfg')"
>
<total-cfg
:param="param"
class="attr-selector"
:chart="chart"
@onTotalCfgChange="onTotalCfgChange"
/>
</el-collapse-item>
</el-collapse>
</el-row>
<el-row>
@ -1046,6 +1058,7 @@ import {
DEFAULT_THRESHOLD,
DEFAULT_TITLE_STYLE,
DEFAULT_TOOLTIP,
DEFAULT_TOTAL,
DEFAULT_XAXIS_STYLE,
DEFAULT_YAXIS_EXT_STYLE,
DEFAULT_YAXIS_STYLE
@ -1089,9 +1102,11 @@ 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'
import TotalCfg from '@/views/chart/components/shape-attr/TotalCfg'
export default {
name: 'ChartEdit',
components: {
TotalCfg,
Threshold,
AssistLine,
FunctionCfg,
@ -1167,7 +1182,8 @@ export default {
color: DEFAULT_COLOR_CASE,
size: DEFAULT_SIZE,
label: DEFAULT_LABEL,
tooltip: DEFAULT_TOOLTIP
tooltip: DEFAULT_TOOLTIP,
totalCfg: DEFAULT_TOTAL
},
customStyle: {
text: DEFAULT_TITLE_STYLE,
@ -1728,6 +1744,11 @@ export default {
this.calcStyle()
},
onTotalCfgChange(val) {
this.view.customAttr.totalCfg = val
this.calcStyle()
},
onChangeXAxisForm(val) {
this.view.customStyle.xAxis = val
this.calcStyle()