mirror of
https://github.com/dataease/dataease.git
synced 2026-05-15 13:32:18 +08:00
fix(图表): 修复明细表和汇总表开启总计之后序号列计算错误以及图片不显示 (#15454)
This commit is contained in:
@@ -209,3 +209,9 @@ declare interface Filter {
|
||||
datasetTableField: ChartViewField
|
||||
fieldId: string
|
||||
}
|
||||
|
||||
declare interface PageInfo {
|
||||
currentPage: number
|
||||
pageSize: number
|
||||
total: number
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import {
|
||||
type LayoutResult,
|
||||
MergedCell,
|
||||
S2DataConfig,
|
||||
S2Event,
|
||||
S2Options,
|
||||
@@ -15,7 +14,7 @@ import { hexColorToRGBA, isAlphaColor, parseJson } from '../../../util'
|
||||
import { S2ChartView, S2DrawOptions } from '../../types/impl/s2'
|
||||
import { TABLE_EDITOR_PROPERTY, TABLE_EDITOR_PROPERTY_INNER } from './common'
|
||||
import { useI18n } from '@/hooks/web/useI18n'
|
||||
import { isEqual, isNumber, merge } from 'lodash-es'
|
||||
import { filter, isEqual, isNumber, merge } from 'lodash-es'
|
||||
import {
|
||||
copyContent,
|
||||
CustomDataCell,
|
||||
@@ -23,12 +22,13 @@ import {
|
||||
getRowIndex,
|
||||
calculateHeaderHeight,
|
||||
SortTooltip,
|
||||
configSummaryRow,
|
||||
summaryRowStyle,
|
||||
configEmptyDataStyle,
|
||||
getLeafNodes,
|
||||
getColumns,
|
||||
drawImage
|
||||
drawImage,
|
||||
getSummaryRow,
|
||||
SummaryCell
|
||||
} from '@/views/chart/components/js/panel/common/common_table'
|
||||
|
||||
const { t } = useI18n()
|
||||
@@ -197,37 +197,6 @@ export class TableInfo extends S2ChartView<TableSheet> {
|
||||
s2Options.frozenColCount = tableCell.tableColumnFreezeHead ?? 0
|
||||
s2Options.frozenRowCount = tableCell.tableRowFreezeHead ?? 0
|
||||
}
|
||||
// 开启序号之后,第一列就是序号列,修改 label 即可
|
||||
if (s2Options.showSeriesNumber) {
|
||||
let indexLabel = tableHeader.indexLabel
|
||||
if (!indexLabel) {
|
||||
indexLabel = ''
|
||||
}
|
||||
s2Options.layoutCoordinate = (_, __, col) => {
|
||||
if (col.colIndex === 0 && col.rowIndex === 0) {
|
||||
col.label = indexLabel
|
||||
col.value = indexLabel
|
||||
}
|
||||
}
|
||||
}
|
||||
s2Options.dataCell = viewMeta => {
|
||||
const field = fields.filter(f => f.dataeaseName === viewMeta.valueField)?.[0]
|
||||
if (field?.deType === 7 && chart.showPosition !== 'dialog') {
|
||||
return new ImageCell(viewMeta, viewMeta?.spreadsheet)
|
||||
}
|
||||
if (viewMeta.colIndex === 0 && s2Options.showSeriesNumber) {
|
||||
if (tableCell.mergeCells) {
|
||||
viewMeta.fieldValue = getRowIndex(s2Options.mergedCellsInfo, viewMeta)
|
||||
} else {
|
||||
viewMeta.fieldValue =
|
||||
pageInfo.pageSize * (pageInfo.currentPage - 1) + viewMeta.rowIndex + 1
|
||||
}
|
||||
}
|
||||
// 配置文本自动换行参数
|
||||
viewMeta.autoWrap = tableCell.mergeCells ? false : basicStyle.autoWrap
|
||||
viewMeta.maxLines = basicStyle.maxLines
|
||||
return new CustomDataCell(viewMeta, viewMeta?.spreadsheet)
|
||||
}
|
||||
// tooltip
|
||||
this.configTooltip(chart, s2Options)
|
||||
// 合并单元格
|
||||
@@ -256,8 +225,8 @@ export class TableInfo extends S2ChartView<TableSheet> {
|
||||
return new CustomTableColCell(node, sheet, config)
|
||||
}
|
||||
}
|
||||
// 总计
|
||||
configSummaryRow(chart, s2Options, newData, tableHeader, basicStyle, basicStyle.showSummary)
|
||||
// 序列号和总计行
|
||||
this.configSummaryRowAndIndex(chart, pageInfo, s2Options, s2DataConfig)
|
||||
// 开始渲染
|
||||
const newChart = new TableSheet(containerDom, s2DataConfig, s2Options)
|
||||
// 总计紧贴在单元格后面
|
||||
@@ -475,6 +444,75 @@ export class TableInfo extends S2ChartView<TableSheet> {
|
||||
return theme
|
||||
}
|
||||
|
||||
protected configSummaryRowAndIndex(
|
||||
chart: Chart,
|
||||
pageInfo: PageInfo,
|
||||
s2Options: S2Options,
|
||||
s2DataConfig: S2DataConfig
|
||||
) {
|
||||
const { tableHeader, basicStyle, tableCell } = parseJson(chart.customAttr)
|
||||
const fields = chart.data?.fields ?? []
|
||||
// 开启序号之后,第一列就是序号列,修改 label 即可
|
||||
if (s2Options.showSeriesNumber) {
|
||||
let indexLabel = tableHeader.indexLabel
|
||||
if (!indexLabel) {
|
||||
indexLabel = ''
|
||||
}
|
||||
s2Options.layoutCoordinate = (_, __, col) => {
|
||||
if (col.colIndex === 0 && col.rowIndex === 0) {
|
||||
col.label = indexLabel
|
||||
col.value = indexLabel
|
||||
}
|
||||
}
|
||||
}
|
||||
const { showSummary, summaryLabel } = basicStyle
|
||||
const data = s2DataConfig.data
|
||||
const xAxis = chart.xAxis
|
||||
if (showSummary && data?.length) {
|
||||
// 设置汇总行高度和表头一致
|
||||
const heightByField = {}
|
||||
heightByField[data.length] = tableHeader.tableTitleHeight
|
||||
s2Options.style.rowCfg = { heightByField }
|
||||
// 计算汇总加入到数据里,冻结最后一行
|
||||
s2Options.frozenTrailingRowCount = 1
|
||||
const axis = filter(xAxis, axis => [2, 3, 4].includes(axis.deType))
|
||||
const summaryObj = getSummaryRow(data, axis, basicStyle.seriesSummary) as any
|
||||
data.push(summaryObj)
|
||||
}
|
||||
s2Options.dataCell = viewMeta => {
|
||||
// 总计行处理
|
||||
if (showSummary && viewMeta.rowIndex === data.length - 1) {
|
||||
if (viewMeta.colIndex === 0) {
|
||||
if (tableHeader.showIndex) {
|
||||
viewMeta.fieldValue = summaryLabel ?? t('chart.total_show')
|
||||
} else {
|
||||
// 第一列不是数值类型的,显示总计
|
||||
if (![2, 3, 4].includes(xAxis?.[0]?.deType)) {
|
||||
viewMeta.fieldValue = summaryLabel ?? t('chart.total_show')
|
||||
}
|
||||
}
|
||||
}
|
||||
return new SummaryCell(viewMeta, viewMeta?.spreadsheet)
|
||||
}
|
||||
const field = fields.find(f => f.dataeaseName === viewMeta.valueField)
|
||||
if (field?.deType === 7 && chart.showPosition !== 'dialog') {
|
||||
return new ImageCell(viewMeta, viewMeta?.spreadsheet)
|
||||
}
|
||||
if (viewMeta.colIndex === 0 && s2Options.showSeriesNumber) {
|
||||
if (tableCell.mergeCells) {
|
||||
viewMeta.fieldValue = getRowIndex(s2Options.mergedCellsInfo, viewMeta)
|
||||
} else {
|
||||
viewMeta.fieldValue =
|
||||
pageInfo.pageSize * (pageInfo.currentPage - 1) + viewMeta.rowIndex + 1
|
||||
}
|
||||
}
|
||||
// 配置文本自动换行参数
|
||||
viewMeta.autoWrap = tableCell.mergeCells ? false : basicStyle.autoWrap
|
||||
viewMeta.maxLines = basicStyle.maxLines
|
||||
return new CustomDataCell(viewMeta, viewMeta?.spreadsheet)
|
||||
}
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super('table-info', [])
|
||||
}
|
||||
|
||||
@@ -2,9 +2,11 @@ import { useI18n } from '@/hooks/web/useI18n'
|
||||
import { formatterItem, valueFormatter } from '@/views/chart/components/js/formatter'
|
||||
import {
|
||||
configEmptyDataStyle,
|
||||
configSummaryRow,
|
||||
copyContent,
|
||||
CustomDataCell,
|
||||
getSummaryRow,
|
||||
SortTooltip,
|
||||
SummaryCell,
|
||||
summaryRowStyle
|
||||
} from '@/views/chart/components/js/panel/common/common_table'
|
||||
import { S2ChartView, S2DrawOptions } from '@/views/chart/components/js/panel/types/impl/s2'
|
||||
@@ -16,11 +18,10 @@ import {
|
||||
S2Options,
|
||||
ScrollbarPositionType,
|
||||
TableColCell,
|
||||
TableDataCell,
|
||||
TableSheet,
|
||||
ViewMeta
|
||||
} from '@antv/s2'
|
||||
import { cloneDeep, isNumber } from 'lodash-es'
|
||||
import { isNumber } from 'lodash-es'
|
||||
import { TABLE_EDITOR_PROPERTY, TABLE_EDITOR_PROPERTY_INNER } from './common'
|
||||
|
||||
const { t } = useI18n()
|
||||
@@ -161,26 +162,6 @@ export class TableNormal extends S2ChartView<TableSheet> {
|
||||
s2Options.frozenColCount = tableCell.tableColumnFreezeHead ?? 0
|
||||
s2Options.frozenRowCount = tableCell.tableRowFreezeHead ?? 0
|
||||
}
|
||||
// 开启序号之后,第一列就是序号列,修改 label 即可
|
||||
if (s2Options.showSeriesNumber) {
|
||||
let indexLabel = tableHeader.indexLabel
|
||||
if (!indexLabel) {
|
||||
indexLabel = ''
|
||||
}
|
||||
s2Options.layoutCoordinate = (_, __, col) => {
|
||||
if (col.colIndex === 0 && col.rowIndex === 0) {
|
||||
col.label = indexLabel
|
||||
col.value = indexLabel
|
||||
}
|
||||
}
|
||||
s2Options.dataCell = viewMeta => {
|
||||
if (viewMeta.colIndex === 0 && s2Options.showSeriesNumber) {
|
||||
viewMeta.fieldValue =
|
||||
pageInfo.pageSize * (pageInfo.currentPage - 1) + viewMeta.rowIndex + 1
|
||||
}
|
||||
return new TableDataCell(viewMeta, viewMeta.spreadsheet)
|
||||
}
|
||||
}
|
||||
// tooltip
|
||||
this.configTooltip(chart, s2Options)
|
||||
// 隐藏表头,保留顶部的分割线, 禁用表头横向 resize
|
||||
@@ -201,9 +182,8 @@ export class TableNormal extends S2ChartView<TableSheet> {
|
||||
chart.container = container
|
||||
this.configHeaderInteraction(chart, s2Options)
|
||||
}
|
||||
|
||||
// 总计
|
||||
configSummaryRow(chart, s2Options, newData, tableHeader, basicStyle, basicStyle.showSummary)
|
||||
// 配置总计和序号列
|
||||
this.configSummaryRowAndIndex(chart, pageInfo, s2Options, s2DataConfig)
|
||||
// 开始渲染
|
||||
const newChart = new TableSheet(containerDom, s2DataConfig, s2Options)
|
||||
// 总计紧贴在单元格后面
|
||||
@@ -302,6 +282,57 @@ export class TableNormal extends S2ChartView<TableSheet> {
|
||||
|
||||
return newChart
|
||||
}
|
||||
|
||||
protected configSummaryRowAndIndex(
|
||||
chart: Chart,
|
||||
pageInfo: PageInfo,
|
||||
s2Options: S2Options,
|
||||
s2DataConfig: S2DataConfig
|
||||
) {
|
||||
const { tableHeader, basicStyle } = parseJson(chart.customAttr)
|
||||
// 开启序号之后,第一列就是序号列,修改 label 即可
|
||||
if (s2Options.showSeriesNumber) {
|
||||
let indexLabel = tableHeader.indexLabel
|
||||
if (!indexLabel) {
|
||||
indexLabel = ''
|
||||
}
|
||||
s2Options.layoutCoordinate = (_, __, col) => {
|
||||
if (col.colIndex === 0 && col.rowIndex === 0) {
|
||||
col.label = indexLabel
|
||||
col.value = indexLabel
|
||||
}
|
||||
}
|
||||
}
|
||||
const { showSummary, summaryLabel } = basicStyle
|
||||
const data = s2DataConfig.data
|
||||
const { xAxis, yAxis } = chart
|
||||
if (showSummary && data?.length) {
|
||||
// 设置汇总行高度和表头一致
|
||||
const heightByField = {}
|
||||
heightByField[data.length] = tableHeader.tableTitleHeight
|
||||
s2Options.style.rowCfg = { heightByField }
|
||||
// 计算汇总加入到数据里,冻结最后一行
|
||||
s2Options.frozenTrailingRowCount = 1
|
||||
const summaryObj = getSummaryRow(data, yAxis, basicStyle.seriesSummary) as any
|
||||
data.push(summaryObj)
|
||||
}
|
||||
s2Options.dataCell = viewMeta => {
|
||||
// 总计行处理
|
||||
if (showSummary && viewMeta.rowIndex === data.length - 1) {
|
||||
if (viewMeta.colIndex === 0) {
|
||||
if (tableHeader.showIndex || xAxis?.length) {
|
||||
viewMeta.fieldValue = summaryLabel ?? t('chart.total_show')
|
||||
}
|
||||
}
|
||||
return new SummaryCell(viewMeta, viewMeta?.spreadsheet)
|
||||
}
|
||||
if (viewMeta.colIndex === 0 && s2Options.showSeriesNumber) {
|
||||
viewMeta.fieldValue = pageInfo.pageSize * (pageInfo.currentPage - 1) + viewMeta.rowIndex + 1
|
||||
}
|
||||
return new CustomDataCell(viewMeta, viewMeta?.spreadsheet)
|
||||
}
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super('table-normal', [])
|
||||
}
|
||||
|
||||
@@ -1872,40 +1872,11 @@ const getWrapTextHeight = (wrapText, textStyle, spreadsheet, maxLines) => {
|
||||
return Math.min(lines, maxLines) * maxHeight
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置汇总行
|
||||
* @param chart
|
||||
* @param s2Options
|
||||
* @param newData
|
||||
* @param tableHeader
|
||||
* @param basicStyle
|
||||
* @param showSummary
|
||||
*/
|
||||
export const configSummaryRow = (
|
||||
chart,
|
||||
s2Options,
|
||||
newData,
|
||||
tableHeader,
|
||||
basicStyle,
|
||||
showSummary
|
||||
) => {
|
||||
if (!showSummary || !newData.length) return
|
||||
// 设置汇总行高度和表头一致
|
||||
const heightByField = {}
|
||||
heightByField[newData.length] = tableHeader.tableTitleHeight
|
||||
s2Options.style.rowCfg = {heightByField}
|
||||
// 计算汇总加入到数据里,冻结最后一行
|
||||
s2Options.frozenTrailingRowCount = 1
|
||||
|
||||
const xAxis = chart.xAxis
|
||||
|
||||
const axis = chart.type === 'table-info'
|
||||
? filter(chart.xAxis, axis => [2, 3, 4].includes(axis.deType))
|
||||
: chart.yAxis
|
||||
const summaryObj = {SUMMARY: true}
|
||||
export function getSummaryRow(data, axis, sumCon = []) {
|
||||
const summaryObj = { SUMMARY: true }
|
||||
for (let i = 0; i < axis.length; i++) {
|
||||
const a = axis[i].dataeaseName
|
||||
let savedAxis = find(basicStyle.seriesSummary, s => s.field === a)
|
||||
let savedAxis = find(sumCon, s => s.field === a)
|
||||
if (savedAxis) {
|
||||
if (savedAxis.summary == undefined) {
|
||||
savedAxis.summary = 'sum'
|
||||
@@ -1925,58 +1896,45 @@ export const configSummaryRow = (
|
||||
}
|
||||
switch (savedAxis.summary) {
|
||||
case 'sum':
|
||||
summaryObj[a] = sumBy(newData, d => (parseFloat(d[a]) || 0))
|
||||
summaryObj[a] = sumBy(data, d => parseFloat(d[a]) || 0)
|
||||
break
|
||||
case 'avg':
|
||||
summaryObj[a] = meanBy(newData, d => (parseFloat(d[a]) || 0))
|
||||
summaryObj[a] = meanBy(data, d => parseFloat(d[a]) || 0)
|
||||
break
|
||||
case 'max':
|
||||
summaryObj[a] = maxBy(filter(newData, d => parseFloat(d[a]) !== undefined), d => parseFloat(d[a]))[a]
|
||||
summaryObj[a] = maxBy(
|
||||
filter(data, d => parseFloat(d[a]) !== undefined),
|
||||
d => parseFloat(d[a])
|
||||
)[a]
|
||||
break
|
||||
case 'min':
|
||||
summaryObj[a] = minBy(filter(newData, d => parseFloat(d[a]) !== undefined), d => parseFloat(d[a]))[a]
|
||||
summaryObj[a] = minBy(
|
||||
filter(data, d => parseFloat(d[a]) !== undefined),
|
||||
d => parseFloat(d[a])
|
||||
)[a]
|
||||
break
|
||||
case 'var_pop'://方差
|
||||
if (newData.length < 2) {
|
||||
case 'var_pop': //方差
|
||||
if (data.length < 2) {
|
||||
continue
|
||||
} else {
|
||||
const mean = meanBy(newData, d => (parseFloat(d[a]) || 0)) // 计算均值
|
||||
const squaredDeviations = map(newData, d => ((parseFloat(d[a]) || 0) - mean) ** 2); // 计算偏差平方
|
||||
summaryObj[a] = sum(squaredDeviations) / (size(newData) - 1); // 样本方差(分母n-1)
|
||||
const mean = meanBy(data, d => parseFloat(d[a]) || 0) // 计算均值
|
||||
const squaredDeviations = map(data, d => ((parseFloat(d[a]) || 0) - mean) ** 2) // 计算偏差平方
|
||||
summaryObj[a] = sum(squaredDeviations) / (size(data) - 1) // 样本方差(分母n-1)
|
||||
}
|
||||
break
|
||||
case 'stddev_pop'://标准差
|
||||
if (newData.length < 2) {
|
||||
case 'stddev_pop': //标准差
|
||||
if (data.length < 2) {
|
||||
continue
|
||||
} else {
|
||||
const mean = meanBy(newData, d => (parseFloat(d[a]) || 0)) // 计算均值
|
||||
const squaredDeviations = map(newData, d => ((parseFloat(d[a]) || 0) - mean) ** 2); // 计算偏差平方
|
||||
const sampleVariance = sum(squaredDeviations) / (size(newData) - 1); // 样本方差(分母n-1)
|
||||
summaryObj[a] = Math.sqrt(sampleVariance); // 样本标准差
|
||||
const mean = meanBy(data, d => parseFloat(d[a]) || 0) // 计算均值
|
||||
const squaredDeviations = map(data, d => ((parseFloat(d[a]) || 0) - mean) ** 2) // 计算偏差平方
|
||||
const sampleVariance = sum(squaredDeviations) / (size(data) - 1) // 样本方差(分母n-1)
|
||||
summaryObj[a] = Math.sqrt(sampleVariance) // 样本标准差
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
newData.push(summaryObj)
|
||||
s2Options.dataCell = viewMeta => {
|
||||
// 配置文本自动换行参数
|
||||
viewMeta.autoWrap = basicStyle.autoWrap
|
||||
viewMeta.maxLines = basicStyle.maxLines
|
||||
if (viewMeta.rowIndex !== newData.length - 1) {
|
||||
return new CustomDataCell(viewMeta, viewMeta.spreadsheet)
|
||||
}
|
||||
if (viewMeta.colIndex === 0) {
|
||||
if (tableHeader.showIndex) {
|
||||
viewMeta.fieldValue = basicStyle.summaryLabel ?? i18nt('chart.total_show')
|
||||
} else {
|
||||
if (xAxis.length) {
|
||||
viewMeta.fieldValue = basicStyle.summaryLabel ?? i18nt('chart.total_show')
|
||||
}
|
||||
}
|
||||
}
|
||||
return new SummaryCell(viewMeta, viewMeta.spreadsheet)
|
||||
}
|
||||
return summaryObj
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user