mirror of
https://github.com/dataease/dataease.git
synced 2025-02-24 19:42:56 +08:00
feat(图表): 明细表支持合并单元格 #8830
This commit is contained in:
parent
6f54389797
commit
79932bfa9b
@ -1880,7 +1880,8 @@ export default {
|
|||||||
zoom_level: '縮放等級',
|
zoom_level: '縮放等級',
|
||||||
central_point: '中心點',
|
central_point: '中心點',
|
||||||
full_display: '全量顯示',
|
full_display: '全量顯示',
|
||||||
show_hover_style: '顯示鼠標懸浮樣式'
|
show_hover_style: '顯示鼠標懸浮樣式',
|
||||||
|
merge_cells: '合並單元格'
|
||||||
},
|
},
|
||||||
dataset: {
|
dataset: {
|
||||||
scope_edit: '僅編輯時生效',
|
scope_edit: '僅編輯時生效',
|
||||||
|
@ -1880,7 +1880,8 @@ export default {
|
|||||||
zoom_level: '缩放等级',
|
zoom_level: '缩放等级',
|
||||||
central_point: '中心点',
|
central_point: '中心点',
|
||||||
full_display: '全量显示',
|
full_display: '全量显示',
|
||||||
show_hover_style: '显示鼠标悬浮样式'
|
show_hover_style: '显示鼠标悬浮样式',
|
||||||
|
merge_cells: '合并单元格'
|
||||||
},
|
},
|
||||||
dataset: {
|
dataset: {
|
||||||
scope_edit: '仅编辑时生效',
|
scope_edit: '仅编辑时生效',
|
||||||
|
@ -459,6 +459,10 @@ declare interface ChartTableCellAttr {
|
|||||||
* 冻结行
|
* 冻结行
|
||||||
*/
|
*/
|
||||||
tableRowFreezeHead: number
|
tableRowFreezeHead: number
|
||||||
|
/**
|
||||||
|
* 合并单元格
|
||||||
|
*/
|
||||||
|
mergeCells: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -65,6 +65,7 @@ const changeTableCell = prop => {
|
|||||||
const init = () => {
|
const init = () => {
|
||||||
const tableCell = props.chart?.customAttr?.tableCell
|
const tableCell = props.chart?.customAttr?.tableCell
|
||||||
if (tableCell) {
|
if (tableCell) {
|
||||||
|
tableCell.mergeCells = tableCell.mergeCells === undefined ? false : tableCell.mergeCells
|
||||||
state.tableCellForm = defaultsDeep(cloneDeep(tableCell), cloneDeep(DEFAULT_TABLE_CELL))
|
state.tableCellForm = defaultsDeep(cloneDeep(tableCell), cloneDeep(DEFAULT_TABLE_CELL))
|
||||||
const alpha = props.chart.customAttr.basicStyle.alpha
|
const alpha = props.chart.customAttr.basicStyle.alpha
|
||||||
if (!isAlphaColor(state.tableCellForm.tableItemBgColor)) {
|
if (!isAlphaColor(state.tableCellForm.tableItemBgColor)) {
|
||||||
@ -364,6 +365,20 @@ onMounted(() => {
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
|
<el-form-item
|
||||||
|
class="form-item"
|
||||||
|
:class="'form-item-' + themes"
|
||||||
|
v-if="showProperty('mergeCells')"
|
||||||
|
>
|
||||||
|
<el-checkbox
|
||||||
|
size="small"
|
||||||
|
:effect="themes"
|
||||||
|
v-model="state.tableCellForm.mergeCells"
|
||||||
|
@change="changeTableCell('mergeCells')"
|
||||||
|
>
|
||||||
|
{{ t('chart.merge_cells') }}
|
||||||
|
</el-checkbox>
|
||||||
|
</el-form-item>
|
||||||
<el-form-item
|
<el-form-item
|
||||||
class="form-item"
|
class="form-item"
|
||||||
:class="'form-item-' + themes"
|
:class="'form-item-' + themes"
|
||||||
|
@ -432,7 +432,8 @@ export const DEFAULT_TABLE_CELL: ChartTableCellAttr = {
|
|||||||
isBolder: false,
|
isBolder: false,
|
||||||
tableFreeze: false,
|
tableFreeze: false,
|
||||||
tableColumnFreezeHead: 0,
|
tableColumnFreezeHead: 0,
|
||||||
tableRowFreezeHead: 0
|
tableRowFreezeHead: 0,
|
||||||
|
mergeCells: true
|
||||||
}
|
}
|
||||||
export const DEFAULT_TITLE_STYLE: ChartTextStyle = {
|
export const DEFAULT_TITLE_STYLE: ChartTextStyle = {
|
||||||
show: true,
|
show: true,
|
||||||
|
@ -66,7 +66,8 @@ export class TableInfo extends S2ChartView<TableSheet> {
|
|||||||
...TABLE_EDITOR_PROPERTY_INNER['table-cell-selector'],
|
...TABLE_EDITOR_PROPERTY_INNER['table-cell-selector'],
|
||||||
'tableFreeze',
|
'tableFreeze',
|
||||||
'tableColumnFreezeHead',
|
'tableColumnFreezeHead',
|
||||||
'tableRowFreezeHead'
|
'tableRowFreezeHead',
|
||||||
|
'mergeCells'
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
axis: AxisType[] = ['xAxis', 'filter', 'drill']
|
axis: AxisType[] = ['xAxis', 'filter', 'drill']
|
||||||
@ -197,6 +198,8 @@ export class TableInfo extends S2ChartView<TableSheet> {
|
|||||||
}
|
}
|
||||||
// tooltip
|
// tooltip
|
||||||
this.configTooltip(chart, s2Options)
|
this.configTooltip(chart, s2Options)
|
||||||
|
// 合并单元格
|
||||||
|
this.configMergeCells(chart, s2Options)
|
||||||
// 隐藏表头,保留顶部的分割线, 禁用表头横向 resize
|
// 隐藏表头,保留顶部的分割线, 禁用表头横向 resize
|
||||||
if (tableHeader.showTableHeader === false) {
|
if (tableHeader.showTableHeader === false) {
|
||||||
s2Options.style.colCfg.height = 1
|
s2Options.style.colCfg.height = 1
|
||||||
@ -312,7 +315,6 @@ export class TableInfo extends S2ChartView<TableSheet> {
|
|||||||
// theme
|
// theme
|
||||||
const customTheme = this.configTheme(chart)
|
const customTheme = this.configTheme(chart)
|
||||||
newChart.setThemeCfg({ theme: customTheme })
|
newChart.setThemeCfg({ theme: customTheme })
|
||||||
|
|
||||||
return newChart
|
return newChart
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
/* eslint-disable prettier/prettier */
|
||||||
import {
|
import {
|
||||||
copyString,
|
copyString,
|
||||||
hexColorToRGBA,
|
hexColorToRGBA,
|
||||||
@ -36,7 +37,6 @@ import TableTooltip from '@/views/chart/components/editor/common/TableTooltip.vu
|
|||||||
import Exceljs from 'exceljs'
|
import Exceljs from 'exceljs'
|
||||||
import { saveAs } from 'file-saver'
|
import { saveAs } from 'file-saver'
|
||||||
import { ElMessage } from 'element-plus-secondary'
|
import { ElMessage } from 'element-plus-secondary'
|
||||||
import { matrix } from 'mathjs'
|
|
||||||
|
|
||||||
export function getCustomTheme(chart: Chart): S2Theme {
|
export function getCustomTheme(chart: Chart): S2Theme {
|
||||||
const headerColor = hexColorToRGBA(
|
const headerColor = hexColorToRGBA(
|
||||||
@ -1408,3 +1408,59 @@ export async function exportPivotExcel(instance: PivotSheet, chart: ChartObj) {
|
|||||||
exportTreePivot(instance, chart)
|
exportTreePivot(instance, chart)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function configMergeCells(chart: Chart, options: S2Options) {
|
||||||
|
const { mergeCells } = parseJson(chart.customAttr).tableCell
|
||||||
|
const { showIndex } = parseJson(chart.customAttr).tableHeader
|
||||||
|
if (mergeCells) {
|
||||||
|
const xAxis = chart.xAxis
|
||||||
|
const quotaIndex = xAxis.findIndex(axis => axis.groupType === 'q')
|
||||||
|
const data = chart.data?.tableRow
|
||||||
|
if (quotaIndex <= 0 || !data?.length) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const mergedColInfo: number[][][] = [[[0, data.length - 1]]]
|
||||||
|
const mergedCellsInfo = []
|
||||||
|
const axisToMerge = xAxis.filter((a, i) => a.hide !== true && i < quotaIndex)
|
||||||
|
axisToMerge.forEach((a, i) => {
|
||||||
|
const preMergedColInfo = mergedColInfo[i]
|
||||||
|
const curMergedColInfo = []
|
||||||
|
mergedColInfo.push(curMergedColInfo)
|
||||||
|
preMergedColInfo.forEach(range => {
|
||||||
|
const [start, end] = range
|
||||||
|
let lastVal = data[start][a.dataeaseName]
|
||||||
|
let lastIndex = start
|
||||||
|
for (let index = start; index <= end; index++) {
|
||||||
|
const curVal = data[index][a.dataeaseName]
|
||||||
|
if (curVal !== lastVal || index === end) {
|
||||||
|
const curRange = index - lastIndex
|
||||||
|
if (curRange > 1 ||
|
||||||
|
(index === end && curRange === 1 && lastVal === curVal)) {
|
||||||
|
const tmpMergeCells = []
|
||||||
|
const textIndex = curRange % 2 === 1 ? (curRange - 1) / 2 : curRange / 2 - 1
|
||||||
|
for (let j = 0; j < curRange; j++) {
|
||||||
|
tmpMergeCells.push({
|
||||||
|
colIndex: showIndex ? i + 1 : i,
|
||||||
|
rowIndex: lastIndex + j,
|
||||||
|
showText: j === textIndex
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if (index === end) {
|
||||||
|
tmpMergeCells.push({
|
||||||
|
colIndex: showIndex ? i + 1 : i,
|
||||||
|
rowIndex: index,
|
||||||
|
showText: false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
mergedCellsInfo.push(tmpMergeCells)
|
||||||
|
curMergedColInfo.push([lastIndex, index === end ? index : index - 1])
|
||||||
|
}
|
||||||
|
lastVal = curVal
|
||||||
|
lastIndex = index
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
options.mergedCellsInfo = mergedCellsInfo
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -15,6 +15,7 @@ import {
|
|||||||
} from '@antv/s2'
|
} from '@antv/s2'
|
||||||
import {
|
import {
|
||||||
configHeaderInteraction,
|
configHeaderInteraction,
|
||||||
|
configMergeCells,
|
||||||
configTooltip,
|
configTooltip,
|
||||||
getConditions,
|
getConditions,
|
||||||
getCustomTheme,
|
getCustomTheme,
|
||||||
@ -63,6 +64,10 @@ export abstract class S2ChartView<P extends SpreadSheet> extends AntVAbstractCha
|
|||||||
return getConditions(chart)
|
return getConditions(chart)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected configMergeCells(chart: Chart, option: S2Options) {
|
||||||
|
configMergeCells(chart, option)
|
||||||
|
}
|
||||||
|
|
||||||
protected showTooltip(s2Instance: P, event, metaConfig: Meta[]) {
|
protected showTooltip(s2Instance: P, event, metaConfig: Meta[]) {
|
||||||
const cell = s2Instance.getCell(event.target)
|
const cell = s2Instance.getCell(event.target)
|
||||||
const meta = cell.getMeta()
|
const meta = cell.getMeta()
|
||||||
|
Loading…
Reference in New Issue
Block a user