@visactor/vseed 0.4.16 → 0.4.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/index.cjs +1 -1
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/esm/pipeline/spec/table/pipes/cellStyle/common.d.ts +2 -2
- package/dist/esm/pipeline/spec/table/pipes/cellStyle/common.js +30 -3
- package/dist/esm/pipeline/spec/table/pipes/cellStyle/common.js.map +1 -1
- package/dist/esm/pipeline/spec/table/pipes/cellStyle/pivot.js +11 -0
- package/dist/esm/pipeline/spec/table/pipes/cellStyle/pivot.js.map +1 -1
- package/dist/esm/pipeline/spec/table/pipes/cellStyle/table.js +5 -3
- package/dist/esm/pipeline/spec/table/pipes/cellStyle/table.js.map +1 -1
- package/dist/umd/index.js +46 -6
- package/dist/umd/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { BodyCellStyle, Datum } from '../../../../../types';
|
|
1
|
+
import type { BodyCellStyle, Datum, TotalType } from '../../../../../types';
|
|
2
2
|
/**
|
|
3
3
|
* 计算线性颜色映射(使用 tinycolor2)
|
|
4
4
|
* @param value 实际值
|
|
@@ -16,7 +16,7 @@ export declare const pickBodyCellStyle: (bodyCellStyle: BodyCellStyle) => Record
|
|
|
16
16
|
/**
|
|
17
17
|
* 计算数据列的最小值和最大值
|
|
18
18
|
*/
|
|
19
|
-
export declare const getColumnMinMax: (allData: Datum[], field: string) => {
|
|
19
|
+
export declare const getColumnMinMax: (allData: Datum[], field: string, totalAggregation?: TotalType) => {
|
|
20
20
|
min: number;
|
|
21
21
|
max: number;
|
|
22
22
|
};
|
|
@@ -24,19 +24,46 @@ const pickBodyCellStyle = (bodyCellStyle)=>Object.keys(tableStyleMap).reduce((ac
|
|
|
24
24
|
if (key in bodyCellStyle) acc[tableStyleMap[key]] = bodyCellStyle[key];
|
|
25
25
|
return acc;
|
|
26
26
|
}, {});
|
|
27
|
-
const getColumnMinMax = (allData, field)=>{
|
|
27
|
+
const getColumnMinMax = (allData, field, totalAggregation)=>{
|
|
28
28
|
let min = 1 / 0;
|
|
29
29
|
let max = -1 / 0;
|
|
30
|
+
let sum = 0;
|
|
31
|
+
let count = 0;
|
|
32
|
+
const hasTotal = !!totalAggregation;
|
|
33
|
+
const aggregationType = 'string' == typeof totalAggregation ? totalAggregation : 'sum';
|
|
30
34
|
for (const datum of allData){
|
|
31
35
|
const value = Number(datum[field]);
|
|
32
36
|
if (!Number.isNaN(value)) {
|
|
33
37
|
min = Math.min(min, value);
|
|
34
38
|
max = Math.max(max, value);
|
|
39
|
+
sum += value;
|
|
40
|
+
count += 1;
|
|
35
41
|
}
|
|
36
42
|
}
|
|
43
|
+
const baseMin = min === 1 / 0 ? 0 : min;
|
|
44
|
+
const baseMax = max === -1 / 0 ? 0 : max;
|
|
45
|
+
if (!hasTotal) return {
|
|
46
|
+
min: baseMin,
|
|
47
|
+
max: baseMax
|
|
48
|
+
};
|
|
49
|
+
const total = (()=>{
|
|
50
|
+
switch(aggregationType){
|
|
51
|
+
case 'avg':
|
|
52
|
+
return count ? sum / count : 0;
|
|
53
|
+
case 'max':
|
|
54
|
+
return baseMax;
|
|
55
|
+
case 'min':
|
|
56
|
+
return baseMin;
|
|
57
|
+
case 'count':
|
|
58
|
+
return count;
|
|
59
|
+
case 'sum':
|
|
60
|
+
default:
|
|
61
|
+
return sum;
|
|
62
|
+
}
|
|
63
|
+
})();
|
|
37
64
|
return {
|
|
38
|
-
min: min
|
|
39
|
-
max: max
|
|
65
|
+
min: Math.min(baseMin, total),
|
|
66
|
+
max: Math.max(baseMax, total)
|
|
40
67
|
};
|
|
41
68
|
};
|
|
42
69
|
const applyColorScale = (value, scale)=>{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pipeline/spec/table/pipes/cellStyle/common.js","sources":["webpack://@visactor/vseed/./src/pipeline/spec/table/pipes/cellStyle/common.ts"],"sourcesContent":["import { isArray, isNullish } from 'remeda'\nimport tinycolor from 'tinycolor2'\nimport { InnerRowIndex } from 'src/dataReshape'\nimport type { BodyCellStyle, Datum } from 'src/types'\n\nconst tableStyleMap = {\n backgroundColor: 'bgColor',\n textColor: 'color',\n textFontSize: 'fontSize',\n borderColor: 'borderColor',\n borderLineWidth: 'borderLineWidth',\n barPositiveColor: 'barPositiveColor',\n barNegativeColor: 'barNegativeColor',\n}\n\n/**\n * 计算线性颜色映射(使用 tinycolor2)\n * @param value 实际值\n * @param minValue 最小值\n * @param maxValue 最大值\n * @param minColor 最小值颜色\n * @param maxColor 最大值颜色\n * @returns RGB 颜色字符串\n */\nexport const interpolateColor = (\n value: number,\n minValue: number,\n maxValue: number,\n minColor: string,\n maxColor: string,\n): string => {\n const startColor = tinycolor(minColor).toRgb()\n const endColor = tinycolor(maxColor).toRgb()\n\n // 归一化值到 [0, 1]\n const normalized = (value - minValue) / (maxValue - minValue)\n const t = Math.max(0, Math.min(1, normalized))\n\n // 线性插值\n const r = Math.round(startColor.r + (endColor.r - startColor.r) * t)\n const g = Math.round(startColor.g + (endColor.g - startColor.g) * t)\n const b = Math.round(startColor.b + (endColor.b - startColor.b) * t)\n\n return `rgb(${r}, ${g}, ${b})`\n}\n\n/**\n * 从 bodyCellStyle 提取要应用到单元格的样式\n */\nexport const pickBodyCellStyle = (bodyCellStyle: BodyCellStyle) => {\n return (Object.keys(tableStyleMap) as Array<keyof typeof tableStyleMap>).reduce<Record<string, any>>((acc, key) => {\n if (key in bodyCellStyle) {\n acc[tableStyleMap[key]] = bodyCellStyle[key]\n }\n\n return acc\n }, {})\n}\n\n/**\n * 计算数据列的最小值和最大值\n */\nexport const getColumnMinMax = (allData: Datum[]
|
|
1
|
+
{"version":3,"file":"pipeline/spec/table/pipes/cellStyle/common.js","sources":["webpack://@visactor/vseed/./src/pipeline/spec/table/pipes/cellStyle/common.ts"],"sourcesContent":["import { isArray, isNullish } from 'remeda'\nimport tinycolor from 'tinycolor2'\nimport { InnerRowIndex } from 'src/dataReshape'\nimport type { BodyCellStyle, Datum, TotalType } from 'src/types'\n\nconst tableStyleMap = {\n backgroundColor: 'bgColor',\n textColor: 'color',\n textFontSize: 'fontSize',\n borderColor: 'borderColor',\n borderLineWidth: 'borderLineWidth',\n barPositiveColor: 'barPositiveColor',\n barNegativeColor: 'barNegativeColor',\n}\n\n/**\n * 计算线性颜色映射(使用 tinycolor2)\n * @param value 实际值\n * @param minValue 最小值\n * @param maxValue 最大值\n * @param minColor 最小值颜色\n * @param maxColor 最大值颜色\n * @returns RGB 颜色字符串\n */\nexport const interpolateColor = (\n value: number,\n minValue: number,\n maxValue: number,\n minColor: string,\n maxColor: string,\n): string => {\n const startColor = tinycolor(minColor).toRgb()\n const endColor = tinycolor(maxColor).toRgb()\n\n // 归一化值到 [0, 1]\n const normalized = (value - minValue) / (maxValue - minValue)\n const t = Math.max(0, Math.min(1, normalized))\n\n // 线性插值\n const r = Math.round(startColor.r + (endColor.r - startColor.r) * t)\n const g = Math.round(startColor.g + (endColor.g - startColor.g) * t)\n const b = Math.round(startColor.b + (endColor.b - startColor.b) * t)\n\n return `rgb(${r}, ${g}, ${b})`\n}\n\n/**\n * 从 bodyCellStyle 提取要应用到单元格的样式\n */\nexport const pickBodyCellStyle = (bodyCellStyle: BodyCellStyle) => {\n return (Object.keys(tableStyleMap) as Array<keyof typeof tableStyleMap>).reduce<Record<string, any>>((acc, key) => {\n if (key in bodyCellStyle) {\n acc[tableStyleMap[key]] = bodyCellStyle[key]\n }\n\n return acc\n }, {})\n}\n\n/**\n * 计算数据列的最小值和最大值\n */\nexport const getColumnMinMax = (\n allData: Datum[],\n field: string,\n totalAggregation?: TotalType,\n): { min: number; max: number } => {\n let min = Infinity\n let max = -Infinity\n let sum = 0\n let count = 0\n\n const hasTotal = !!totalAggregation\n const aggregationType: TotalType = typeof totalAggregation === 'string' ? totalAggregation : 'sum'\n\n for (const datum of allData) {\n const value = Number(datum[field])\n if (!Number.isNaN(value)) {\n min = Math.min(min, value)\n max = Math.max(max, value)\n sum += value\n count += 1\n }\n }\n\n const baseMin = min === Infinity ? 0 : min\n const baseMax = max === -Infinity ? 0 : max\n\n if (!hasTotal) {\n return {\n min: baseMin,\n max: baseMax,\n }\n }\n\n const total = (() => {\n switch (aggregationType) {\n case 'avg':\n return count ? sum / count : 0\n case 'max':\n return baseMax\n case 'min':\n return baseMin\n case 'count':\n return count\n case 'sum':\n default:\n return sum\n }\n })()\n\n return {\n min: Math.min(baseMin, total),\n max: Math.max(baseMax, total),\n }\n}\n\n/**\n * 应用 scale 颜色映射\n */\nexport const applyColorScale = (\n value: any,\n scale: { minValue: number; maxValue: number; minColor: string; maxColor: string } | undefined,\n): string | undefined => {\n if (!scale) return undefined\n\n const numValue = Number(value)\n if (Number.isNaN(numValue) || isNullish(value)) return undefined\n\n const minValue = scale.minValue\n const maxValue = scale.maxValue\n\n if (minValue === maxValue) {\n return scale.minColor\n }\n\n return interpolateColor(numValue, minValue, maxValue, scale.minColor, scale.maxColor)\n}\n\nexport const getCellOriginalDataByDatum = (datum: any, hasDynamicFilter: boolean, originalDatum: Datum) => {\n const tableInstance = datum?.table\n let originRowData =\n tableInstance && hasDynamicFilter ? tableInstance?.getCellOriginRecord(datum?.col, datum?.row) : null\n if (originRowData && isArray(originRowData)) {\n originRowData = originRowData[0]\n }\n return originRowData\n ? {\n ...originalDatum,\n [InnerRowIndex]: originRowData?.[InnerRowIndex], // 内部行号字段\n }\n : null\n}\n"],"names":["tableStyleMap","interpolateColor","value","minValue","maxValue","minColor","maxColor","startColor","tinycolor","endColor","normalized","t","Math","r","g","b","pickBodyCellStyle","bodyCellStyle","Object","acc","key","getColumnMinMax","allData","field","totalAggregation","min","Infinity","max","sum","count","hasTotal","aggregationType","datum","Number","baseMin","baseMax","total","applyColorScale","scale","numValue","isNullish","getCellOriginalDataByDatum","hasDynamicFilter","originalDatum","tableInstance","originRowData","isArray","InnerRowIndex"],"mappings":"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"}
|
|
@@ -2,6 +2,16 @@ import { array } from "@visactor/vutils";
|
|
|
2
2
|
import { isString } from "remeda";
|
|
3
3
|
import { matchesFieldSelector, selector, selectorWithDynamicFilter } from "../../../../../dataSelector/selector.js";
|
|
4
4
|
import { applyColorScale, getCellOriginalDataByDatum, getColumnMinMax, pickBodyCellStyle } from "./common.js";
|
|
5
|
+
const isPivotTotalCell = (styleArg)=>{
|
|
6
|
+
const cellHeaderPaths = styleArg?.cellHeaderPaths;
|
|
7
|
+
if (!cellHeaderPaths) return false;
|
|
8
|
+
if ('sub-total' === cellHeaderPaths.role || 'grand-total' === cellHeaderPaths.role) return true;
|
|
9
|
+
const headerPaths = [
|
|
10
|
+
...cellHeaderPaths.colHeaderPaths || [],
|
|
11
|
+
...cellHeaderPaths.rowHeaderPaths || []
|
|
12
|
+
];
|
|
13
|
+
return headerPaths.some((path)=>path?.role === 'sub-total' || path?.role === 'grand-total');
|
|
14
|
+
};
|
|
5
15
|
const pivotTableBodyCell = (spec, context)=>{
|
|
6
16
|
const { advancedVSeed } = context;
|
|
7
17
|
const { cellStyle, config, chartType } = advancedVSeed;
|
|
@@ -70,6 +80,7 @@ const pivotTableBodyCell = (spec, context)=>{
|
|
|
70
80
|
cellStyle.barMarkWidth = themeConfig?.barMarkWidth;
|
|
71
81
|
cellStyle.barPadding = themeConfig?.barPadding;
|
|
72
82
|
cellStyle.barRightToLeft = themeConfig?.barRightToLeft;
|
|
83
|
+
cellStyle.showBar = !isPivotTotalCell(datum);
|
|
73
84
|
}
|
|
74
85
|
return {
|
|
75
86
|
...result,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pipeline/spec/table/pipes/cellStyle/pivot.js","sources":["webpack://@visactor/vseed/./src/pipeline/spec/table/pipes/cellStyle/pivot.ts"],"sourcesContent":["import type { IIndicator, PivotTableConstructorOptions } from '@visactor/vtable'\nimport { array } from '@visactor/vutils'\nimport { isString } from 'remeda'\nimport { matchesFieldSelector, selector, selectorWithDynamicFilter } from 'src/dataSelector/selector'\nimport type { BodyCellStyle, Datum, PivotTableSpecPipe, TableConfig } from 'src/types'\nimport type { FieldSelector } from 'src/types/dataSelector'\nimport { getCellOriginalDataByDatum, pickBodyCellStyle, applyColorScale, getColumnMinMax } from './common'\nimport type { IProgressbarColumnIndicator } from '@visactor/vtable/es/ts-types/pivot-table/indicator/progress-indicator'\n\nexport const pivotTableBodyCell: PivotTableSpecPipe = (spec, context) => {\n const { advancedVSeed } = context\n const { cellStyle, config, chartType } = advancedVSeed\n const bodyCellStyle = cellStyle?.bodyCellStyle\n const themeConfig = config?.[chartType] as TableConfig\n\n if (!bodyCellStyle) {\n return spec as PivotTableConstructorOptions\n }\n const bodyCellStyleList = array(bodyCellStyle) as BodyCellStyle[]\n const indicators = (spec as PivotTableConstructorOptions).indicators || []\n const selectedPos: { col: number; row: number }[] = []\n const hasDynamicFilter = bodyCellStyleList.some((style) => !!style.dynamicFilter)\n const allData = advancedVSeed.dataset || []\n\n const newIndicators = indicators.map((ind) => {\n const newInd = isString(ind)\n ? ({\n indicatorKey: ind,\n } as IIndicator)\n : ind\n\n const { indicatorKey } = newInd\n\n // 前置处理:检查是否需要 progressBar 或 backgroundColorScale\n const progressBarStyle = bodyCellStyleList\n .filter(\n (s) => s.enableProgressBar && s?.selector && matchesFieldSelector(indicatorKey, s.selector as FieldSelector),\n )\n .pop()\n const backgroundColorScale = bodyCellStyleList.find(\n (s) =>\n s.enableBackgroundColorScale && s?.selector && matchesFieldSelector(indicatorKey, s.selector as FieldSelector),\n )\n let columnMin: number\n let columnMax: number\n\n if (progressBarStyle || backgroundColorScale) {\n const { min, max } = getColumnMinMax(allData, indicatorKey)\n columnMin = min\n columnMax = max\n if (progressBarStyle) {\n newInd.cellType = 'progressbar'\n ;(newInd as IProgressbarColumnIndicator).barType = 'negative'\n ;(newInd as IProgressbarColumnIndicator).min = progressBarStyle.barMin ?? columnMin\n ;(newInd as IProgressbarColumnIndicator).max = progressBarStyle.barMax ?? columnMax\n }\n }\n\n newInd.style = (datum: any) => {\n const { dataValue, cellHeaderPaths } = datum\n const headerPaths = [...cellHeaderPaths.colHeaderPaths, ...cellHeaderPaths.rowHeaderPaths]\n\n const originalDatum: Datum = {\n [indicatorKey]: dataValue,\n }\n\n headerPaths.forEach((path: any) => {\n if (path.dimensionKey) {\n originalDatum[path.dimensionKey] = path.value\n }\n })\n\n const currentCellData = getCellOriginalDataByDatum(datum, hasDynamicFilter, originalDatum)\n\n const mergedStyle = bodyCellStyleList.reduce<Record<string, any>>((result, style) => {\n const shouldApply = style.dynamicFilter\n ? selectorWithDynamicFilter(currentCellData || originalDatum, style.dynamicFilter, style.selector)\n : selector(originalDatum, style.selector)\n if (shouldApply) {\n if (selectedPos.length && selectedPos[0].col === datum?.col && selectedPos[0].row === datum?.row) {\n selectedPos.length = 0\n }\n selectedPos.push({\n col: datum?.col,\n row: datum?.row,\n })\n\n const cellStyle = pickBodyCellStyle(style)\n\n // 应用 backgroundColorScale\n if (style.enableBackgroundColorScale) {\n const scaledColor = applyColorScale(dataValue, {\n minValue: columnMin,\n maxValue: columnMax,\n ...themeConfig.backgroundColorScale,\n ...style.backgroundColorScale,\n } as any)\n if (scaledColor) {\n cellStyle.bgColor = scaledColor\n }\n }\n\n // 如果开启了数据条样式\n if (newInd.cellType === 'progressbar') {\n cellStyle.barHeight = themeConfig?.barHeight\n cellStyle.barMarkInBar = themeConfig?.barMarkInBar\n cellStyle.barMarkWidth = themeConfig?.barMarkWidth\n cellStyle.barPadding = themeConfig?.barPadding\n cellStyle.barRightToLeft = themeConfig?.barRightToLeft\n }\n\n return {\n ...result,\n ...cellStyle,\n }\n }\n\n return result\n }, {})\n\n return mergedStyle\n }\n return newInd\n })\n return {\n ...spec,\n runningConfig: {\n ...((spec as any)?.runningConfig || {}),\n selectedPos,\n },\n indicators: newIndicators,\n } as PivotTableConstructorOptions\n}\n"],"names":["pivotTableBodyCell","spec","context","advancedVSeed","cellStyle","config","chartType","bodyCellStyle","themeConfig","bodyCellStyleList","array","indicators","selectedPos","hasDynamicFilter","style","allData","newIndicators","ind","newInd","isString","indicatorKey","progressBarStyle","s","matchesFieldSelector","backgroundColorScale","columnMin","columnMax","min","max","getColumnMinMax","datum","dataValue","
|
|
1
|
+
{"version":3,"file":"pipeline/spec/table/pipes/cellStyle/pivot.js","sources":["webpack://@visactor/vseed/./src/pipeline/spec/table/pipes/cellStyle/pivot.ts"],"sourcesContent":["import type { IIndicator, PivotTableConstructorOptions } from '@visactor/vtable'\nimport { array } from '@visactor/vutils'\nimport { isString } from 'remeda'\nimport { matchesFieldSelector, selector, selectorWithDynamicFilter } from 'src/dataSelector/selector'\nimport type { BodyCellStyle, Datum, PivotTableSpecPipe, TableConfig } from 'src/types'\nimport type { FieldSelector } from 'src/types/dataSelector'\nimport { getCellOriginalDataByDatum, pickBodyCellStyle, applyColorScale, getColumnMinMax } from './common'\nimport type { IProgressbarColumnIndicator } from '@visactor/vtable/es/ts-types/pivot-table/indicator/progress-indicator'\n\nconst isPivotTotalCell = (styleArg: any): boolean => {\n const cellHeaderPaths = styleArg?.cellHeaderPaths\n if (!cellHeaderPaths) {\n return false\n }\n\n if (cellHeaderPaths.role === 'sub-total' || cellHeaderPaths.role === 'grand-total') {\n return true\n }\n\n const headerPaths = [...(cellHeaderPaths.colHeaderPaths || []), ...(cellHeaderPaths.rowHeaderPaths || [])]\n return headerPaths.some((path: any) => path?.role === 'sub-total' || path?.role === 'grand-total')\n}\n\nexport const pivotTableBodyCell: PivotTableSpecPipe = (spec, context) => {\n const { advancedVSeed } = context\n const { cellStyle, config, chartType } = advancedVSeed\n const bodyCellStyle = cellStyle?.bodyCellStyle\n const themeConfig = config?.[chartType] as TableConfig\n\n if (!bodyCellStyle) {\n return spec as PivotTableConstructorOptions\n }\n const bodyCellStyleList = array(bodyCellStyle) as BodyCellStyle[]\n const indicators = (spec as PivotTableConstructorOptions).indicators || []\n const selectedPos: { col: number; row: number }[] = []\n const hasDynamicFilter = bodyCellStyleList.some((style) => !!style.dynamicFilter)\n const allData = advancedVSeed.dataset || []\n\n const newIndicators = indicators.map((ind) => {\n const newInd = isString(ind)\n ? ({\n indicatorKey: ind,\n } as IIndicator)\n : ind\n\n const { indicatorKey } = newInd\n\n // 前置处理:检查是否需要 progressBar 或 backgroundColorScale\n const progressBarStyle = bodyCellStyleList\n .filter(\n (s) => s.enableProgressBar && s?.selector && matchesFieldSelector(indicatorKey, s.selector as FieldSelector),\n )\n .pop()\n const backgroundColorScale = bodyCellStyleList.find(\n (s) =>\n s.enableBackgroundColorScale && s?.selector && matchesFieldSelector(indicatorKey, s.selector as FieldSelector),\n )\n let columnMin: number\n let columnMax: number\n\n if (progressBarStyle || backgroundColorScale) {\n const { min, max } = getColumnMinMax(allData, indicatorKey)\n columnMin = min\n columnMax = max\n if (progressBarStyle) {\n newInd.cellType = 'progressbar'\n ;(newInd as IProgressbarColumnIndicator).barType = 'negative'\n ;(newInd as IProgressbarColumnIndicator).min = progressBarStyle.barMin ?? columnMin\n ;(newInd as IProgressbarColumnIndicator).max = progressBarStyle.barMax ?? columnMax\n }\n }\n\n newInd.style = (datum: any) => {\n const { dataValue, cellHeaderPaths } = datum\n const headerPaths = [...cellHeaderPaths.colHeaderPaths, ...cellHeaderPaths.rowHeaderPaths]\n\n const originalDatum: Datum = {\n [indicatorKey]: dataValue,\n }\n\n headerPaths.forEach((path: any) => {\n if (path.dimensionKey) {\n originalDatum[path.dimensionKey] = path.value\n }\n })\n\n const currentCellData = getCellOriginalDataByDatum(datum, hasDynamicFilter, originalDatum)\n\n const mergedStyle = bodyCellStyleList.reduce<Record<string, any>>((result, style) => {\n const shouldApply = style.dynamicFilter\n ? selectorWithDynamicFilter(currentCellData || originalDatum, style.dynamicFilter, style.selector)\n : selector(originalDatum, style.selector)\n if (shouldApply) {\n if (selectedPos.length && selectedPos[0].col === datum?.col && selectedPos[0].row === datum?.row) {\n selectedPos.length = 0\n }\n selectedPos.push({\n col: datum?.col,\n row: datum?.row,\n })\n\n const cellStyle = pickBodyCellStyle(style)\n\n // 应用 backgroundColorScale\n if (style.enableBackgroundColorScale) {\n const scaledColor = applyColorScale(dataValue, {\n minValue: columnMin,\n maxValue: columnMax,\n ...themeConfig.backgroundColorScale,\n ...style.backgroundColorScale,\n } as any)\n if (scaledColor) {\n cellStyle.bgColor = scaledColor\n }\n }\n\n // 如果开启了数据条样式\n if (newInd.cellType === 'progressbar') {\n cellStyle.barHeight = themeConfig?.barHeight\n cellStyle.barMarkInBar = themeConfig?.barMarkInBar\n cellStyle.barMarkWidth = themeConfig?.barMarkWidth\n cellStyle.barPadding = themeConfig?.barPadding\n cellStyle.barRightToLeft = themeConfig?.barRightToLeft\n cellStyle.showBar = !isPivotTotalCell(datum)\n }\n\n return {\n ...result,\n ...cellStyle,\n }\n }\n\n return result\n }, {})\n\n return mergedStyle\n }\n return newInd\n })\n return {\n ...spec,\n runningConfig: {\n ...((spec as any)?.runningConfig || {}),\n selectedPos,\n },\n indicators: newIndicators,\n } as PivotTableConstructorOptions\n}\n"],"names":["isPivotTotalCell","styleArg","cellHeaderPaths","headerPaths","path","pivotTableBodyCell","spec","context","advancedVSeed","cellStyle","config","chartType","bodyCellStyle","themeConfig","bodyCellStyleList","array","indicators","selectedPos","hasDynamicFilter","style","allData","newIndicators","ind","newInd","isString","indicatorKey","progressBarStyle","s","matchesFieldSelector","backgroundColorScale","columnMin","columnMax","min","max","getColumnMinMax","datum","dataValue","originalDatum","currentCellData","getCellOriginalDataByDatum","mergedStyle","result","shouldApply","selectorWithDynamicFilter","selector","pickBodyCellStyle","scaledColor","applyColorScale"],"mappings":"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"}
|
|
@@ -4,8 +4,10 @@ import { isFieldSelector, matchesFieldSelector, selector, selectorWithDynamicFil
|
|
|
4
4
|
import { applyColorScale, getCellOriginalDataByDatum, getColumnMinMax, pickBodyCellStyle } from "./common.js";
|
|
5
5
|
import { preorderTraverse } from "../../../../utils/tree/traverse.js";
|
|
6
6
|
const tableBodyCell = (spec, context)=>{
|
|
7
|
-
const { advancedVSeed } = context;
|
|
7
|
+
const { advancedVSeed, vseed } = context;
|
|
8
|
+
const { totals } = vseed || {};
|
|
8
9
|
const { cellStyle, config, chartType } = advancedVSeed;
|
|
10
|
+
const totalAggregation = 'string' == typeof totals ? totals : void 0;
|
|
9
11
|
const bodyCellStyle = cellStyle?.bodyCellStyle;
|
|
10
12
|
const themeConfig = config?.[chartType];
|
|
11
13
|
if (!bodyCellStyle) return spec;
|
|
@@ -32,14 +34,14 @@ const tableBodyCell = (spec, context)=>{
|
|
|
32
34
|
let columnMin;
|
|
33
35
|
let columnMax;
|
|
34
36
|
if (progressBarStyle || backgroundColorScale) {
|
|
35
|
-
const { min, max } = getColumnMinMax(allData, field);
|
|
37
|
+
const { min, max } = getColumnMinMax(allData, field, totalAggregation);
|
|
36
38
|
columnMin = min;
|
|
37
39
|
columnMax = max;
|
|
38
40
|
if (progressBarStyle) {
|
|
39
41
|
col.cellType = 'progressbar';
|
|
40
42
|
col.barType = 'negative';
|
|
41
43
|
col.min = progressBarStyle.barMin ?? columnMin;
|
|
42
|
-
col.max = progressBarStyle.
|
|
44
|
+
col.max = progressBarStyle.barMax ?? columnMax;
|
|
43
45
|
}
|
|
44
46
|
}
|
|
45
47
|
col.style = (datum)=>{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pipeline/spec/table/pipes/cellStyle/table.js","sources":["webpack://@visactor/vseed/./src/pipeline/spec/table/pipes/cellStyle/table.ts"],"sourcesContent":["import type { ListTableConstructorOptions, ColumnDefine, ProgressbarColumnDefine } from '@visactor/vtable'\nimport { array } from '@visactor/vutils'\nimport { isNullish, isNumber, isPlainObject, isString } from 'remeda'\nimport { isFieldSelector, matchesFieldSelector, selector, selectorWithDynamicFilter } from 'src/dataSelector/selector'\nimport type { BodyCellStyle, ListTableSpecPipe, TableConfig } from 'src/types'\nimport type { FieldSelector, MeasureSelector } from 'src/types/dataSelector'\nimport { getCellOriginalDataByDatum, pickBodyCellStyle, applyColorScale, getColumnMinMax } from './common'\nimport { preorderTraverse } from 'src/pipeline/utils/tree/traverse'\n\nexport const tableBodyCell: ListTableSpecPipe = (spec, context) => {\n const { advancedVSeed } = context\n const { cellStyle, config, chartType } = advancedVSeed\n const bodyCellStyle = cellStyle?.bodyCellStyle\n const themeConfig = config?.[chartType] as TableConfig\n\n if (!bodyCellStyle) {\n return spec as ListTableConstructorOptions\n }\n\n const bodyCellStyleList = array(bodyCellStyle) as BodyCellStyle[]\n const columns = (spec as ListTableConstructorOptions).columns || []\n const selectedPos: { col: number; row: number }[] = []\n const allData = advancedVSeed.dataset || []\n\n const setStyleOfColumn = (col: ColumnDefine) => {\n const field = col.field as string\n\n // 过滤出匹配当前列的样式配置\n const matchedStyles = bodyCellStyleList.filter((style) => {\n // 检查 dynamicFilter\n if (style?.dynamicFilter) {\n return style.dynamicFilter?.result?.success === true || !!style.dynamicFilter?.fallback\n }\n\n // 检查 selector\n if (isNullish(style.selector)) {\n return true\n }\n\n const selectors = array(style.selector) as any[]\n return selectors.some((sel) => {\n // 1. FieldSelector(字段选择器)\n if (isFieldSelector(sel)) {\n return matchesFieldSelector(field, sel)\n }\n\n // 2. MeasureSelector/DimensionSelector(条件选择器)\n if (isPlainObject(sel)) {\n return isNullish(sel.field) || (sel as MeasureSelector).field === field\n }\n\n // 3. ValueSelector(值选择器)\n return isNumber(sel) || isString(sel)\n })\n })\n\n if (!matchedStyles.length) {\n return false\n }\n\n const hasDynamicFilter = matchedStyles.some((style) => !!style.dynamicFilter)\n\n // 前置处理:检查是否需要 progressBar\n const progressBarStyle = matchedStyles\n .filter((s) => s.enableProgressBar && s?.selector && matchesFieldSelector(field, s.selector as FieldSelector))\n .pop()\n const backgroundColorScale = matchedStyles.find(\n (s) => s.enableBackgroundColorScale && s?.selector && matchesFieldSelector(field, s.selector as FieldSelector),\n )\n let columnMin: number\n let columnMax: number\n if (progressBarStyle || backgroundColorScale) {\n const { min, max } = getColumnMinMax(allData, field)\n columnMin = min\n columnMax = max\n if (progressBarStyle) {\n col.cellType = 'progressbar'\n ;(col as ProgressbarColumnDefine).barType = 'negative'\n ;(col as ProgressbarColumnDefine).min = progressBarStyle.barMin ?? columnMin\n ;(col as ProgressbarColumnDefine).max = progressBarStyle.
|
|
1
|
+
{"version":3,"file":"pipeline/spec/table/pipes/cellStyle/table.js","sources":["webpack://@visactor/vseed/./src/pipeline/spec/table/pipes/cellStyle/table.ts"],"sourcesContent":["import type { ListTableConstructorOptions, ColumnDefine, ProgressbarColumnDefine } from '@visactor/vtable'\nimport { array } from '@visactor/vutils'\nimport { isNullish, isNumber, isPlainObject, isString } from 'remeda'\nimport { isFieldSelector, matchesFieldSelector, selector, selectorWithDynamicFilter } from 'src/dataSelector/selector'\nimport type { BodyCellStyle, ListTableSpecPipe, Table, TableConfig } from 'src/types'\nimport type { FieldSelector, MeasureSelector } from 'src/types/dataSelector'\nimport { getCellOriginalDataByDatum, pickBodyCellStyle, applyColorScale, getColumnMinMax } from './common'\nimport { preorderTraverse } from 'src/pipeline/utils/tree/traverse'\n\nexport const tableBodyCell: ListTableSpecPipe = (spec, context) => {\n const { advancedVSeed, vseed } = context\n const { totals } = (vseed || {}) as Table\n const { cellStyle, config, chartType } = advancedVSeed\n const totalAggregation = typeof totals === 'string' ? totals : undefined\n const bodyCellStyle = cellStyle?.bodyCellStyle\n const themeConfig = config?.[chartType] as TableConfig\n\n if (!bodyCellStyle) {\n return spec as ListTableConstructorOptions\n }\n\n const bodyCellStyleList = array(bodyCellStyle) as BodyCellStyle[]\n const columns = (spec as ListTableConstructorOptions).columns || []\n const selectedPos: { col: number; row: number }[] = []\n const allData = advancedVSeed.dataset || []\n\n const setStyleOfColumn = (col: ColumnDefine) => {\n const field = col.field as string\n\n // 过滤出匹配当前列的样式配置\n const matchedStyles = bodyCellStyleList.filter((style) => {\n // 检查 dynamicFilter\n if (style?.dynamicFilter) {\n return style.dynamicFilter?.result?.success === true || !!style.dynamicFilter?.fallback\n }\n\n // 检查 selector\n if (isNullish(style.selector)) {\n return true\n }\n\n const selectors = array(style.selector) as any[]\n return selectors.some((sel) => {\n // 1. FieldSelector(字段选择器)\n if (isFieldSelector(sel)) {\n return matchesFieldSelector(field, sel)\n }\n\n // 2. MeasureSelector/DimensionSelector(条件选择器)\n if (isPlainObject(sel)) {\n return isNullish(sel.field) || (sel as MeasureSelector).field === field\n }\n\n // 3. ValueSelector(值选择器)\n return isNumber(sel) || isString(sel)\n })\n })\n\n if (!matchedStyles.length) {\n return false\n }\n\n const hasDynamicFilter = matchedStyles.some((style) => !!style.dynamicFilter)\n\n // 前置处理:检查是否需要 progressBar\n const progressBarStyle = matchedStyles\n .filter((s) => s.enableProgressBar && s?.selector && matchesFieldSelector(field, s.selector as FieldSelector))\n .pop()\n const backgroundColorScale = matchedStyles.find(\n (s) => s.enableBackgroundColorScale && s?.selector && matchesFieldSelector(field, s.selector as FieldSelector),\n )\n let columnMin: number\n let columnMax: number\n if (progressBarStyle || backgroundColorScale) {\n const { min, max } = getColumnMinMax(allData, field, totalAggregation)\n columnMin = min\n columnMax = max\n if (progressBarStyle) {\n col.cellType = 'progressbar'\n ;(col as ProgressbarColumnDefine).barType = 'negative'\n ;(col as ProgressbarColumnDefine).min = progressBarStyle.barMin ?? columnMin\n ;(col as ProgressbarColumnDefine).max = progressBarStyle.barMax ?? columnMax\n }\n }\n\n // 统一的 col.style 回调\n col.style = (datum: any) => {\n const originalDatum = {\n [field]: datum.dataValue,\n }\n const currentCellData = getCellOriginalDataByDatum(datum, hasDynamicFilter, originalDatum)\n\n const mergedStyle = matchedStyles.reduce<Record<string, any>>((result, style) => {\n const shouldApply = style.dynamicFilter\n ? selectorWithDynamicFilter(currentCellData || originalDatum, style.dynamicFilter, style.selector)\n : selector(originalDatum, style.selector)\n\n if (shouldApply) {\n if (selectedPos.length && selectedPos[0].col === datum?.col && selectedPos[0].row === datum?.row) {\n // 说明重复进入了,清空历史\n selectedPos.length = 0\n }\n selectedPos.push({\n col: datum?.col,\n row: datum?.row,\n })\n\n let cellStyle = pickBodyCellStyle(style)\n\n // 应用 backgroundColorScale\n if (style.enableBackgroundColorScale) {\n const scaledColor = applyColorScale(datum.dataValue, {\n minValue: columnMin,\n maxValue: columnMax,\n ...themeConfig.backgroundColorScale,\n ...style?.backgroundColorScale,\n } as any)\n if (scaledColor) {\n cellStyle.bgColor = scaledColor\n }\n }\n // 如果开启了数据条样式\n if (col.cellType === 'progressbar') {\n cellStyle = {\n ...cellStyle,\n barHeight: themeConfig?.barHeight,\n barMarkInBar: themeConfig?.barMarkInBar,\n barMarkWidth: themeConfig?.barMarkWidth,\n barPadding: themeConfig?.barPadding,\n barRightToLeft: themeConfig?.barRightToLeft,\n barAxisColor: themeConfig?.barAxisColor,\n }\n }\n\n return {\n ...result,\n ...cellStyle,\n }\n }\n\n return result\n }, {})\n\n return mergedStyle\n }\n\n return false\n }\n\n preorderTraverse<ColumnDefine, 'columns'>(columns, setStyleOfColumn, 'columns')\n ;(spec as any).runningConfig = {\n ...((spec as any).runningConfig || {}),\n selectedPos,\n }\n\n return spec as ListTableConstructorOptions\n}\n"],"names":["tableBodyCell","spec","context","advancedVSeed","vseed","totals","cellStyle","config","chartType","totalAggregation","undefined","bodyCellStyle","themeConfig","bodyCellStyleList","array","columns","selectedPos","allData","setStyleOfColumn","col","field","matchedStyles","style","isNullish","selectors","sel","isFieldSelector","matchesFieldSelector","isPlainObject","isNumber","isString","hasDynamicFilter","progressBarStyle","s","backgroundColorScale","columnMin","columnMax","min","max","getColumnMinMax","datum","originalDatum","currentCellData","getCellOriginalDataByDatum","mergedStyle","result","shouldApply","selectorWithDynamicFilter","selector","pickBodyCellStyle","scaledColor","applyColorScale","preorderTraverse"],"mappings":"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"}
|
package/dist/umd/index.js
CHANGED
|
@@ -4358,19 +4358,46 @@ self.R = R;
|
|
|
4358
4358
|
if (key in bodyCellStyle) acc[tableStyleMap[key]] = bodyCellStyle[key];
|
|
4359
4359
|
return acc;
|
|
4360
4360
|
}, {});
|
|
4361
|
-
const getColumnMinMax = (allData, field)=>{
|
|
4361
|
+
const getColumnMinMax = (allData, field, totalAggregation)=>{
|
|
4362
4362
|
let min = 1 / 0;
|
|
4363
4363
|
let max = -1 / 0;
|
|
4364
|
+
let sum = 0;
|
|
4365
|
+
let count = 0;
|
|
4366
|
+
const hasTotal = !!totalAggregation;
|
|
4367
|
+
const aggregationType = 'string' == typeof totalAggregation ? totalAggregation : 'sum';
|
|
4364
4368
|
for (const datum of allData){
|
|
4365
4369
|
const value = Number(datum[field]);
|
|
4366
4370
|
if (!Number.isNaN(value)) {
|
|
4367
4371
|
min = Math.min(min, value);
|
|
4368
4372
|
max = Math.max(max, value);
|
|
4373
|
+
sum += value;
|
|
4374
|
+
count += 1;
|
|
4369
4375
|
}
|
|
4370
4376
|
}
|
|
4377
|
+
const baseMin = min === 1 / 0 ? 0 : min;
|
|
4378
|
+
const baseMax = max === -1 / 0 ? 0 : max;
|
|
4379
|
+
if (!hasTotal) return {
|
|
4380
|
+
min: baseMin,
|
|
4381
|
+
max: baseMax
|
|
4382
|
+
};
|
|
4383
|
+
const total = (()=>{
|
|
4384
|
+
switch(aggregationType){
|
|
4385
|
+
case 'avg':
|
|
4386
|
+
return count ? sum / count : 0;
|
|
4387
|
+
case 'max':
|
|
4388
|
+
return baseMax;
|
|
4389
|
+
case 'min':
|
|
4390
|
+
return baseMin;
|
|
4391
|
+
case 'count':
|
|
4392
|
+
return count;
|
|
4393
|
+
case 'sum':
|
|
4394
|
+
default:
|
|
4395
|
+
return sum;
|
|
4396
|
+
}
|
|
4397
|
+
})();
|
|
4371
4398
|
return {
|
|
4372
|
-
min: min
|
|
4373
|
-
max: max
|
|
4399
|
+
min: Math.min(baseMin, total),
|
|
4400
|
+
max: Math.max(baseMax, total)
|
|
4374
4401
|
};
|
|
4375
4402
|
};
|
|
4376
4403
|
const applyColorScale = (value, scale)=>{
|
|
@@ -4392,8 +4419,10 @@ self.R = R;
|
|
|
4392
4419
|
} : null;
|
|
4393
4420
|
};
|
|
4394
4421
|
const tableBodyCell = (spec, context)=>{
|
|
4395
|
-
const { advancedVSeed } = context;
|
|
4422
|
+
const { advancedVSeed, vseed } = context;
|
|
4423
|
+
const { totals } = vseed || {};
|
|
4396
4424
|
const { cellStyle, config, chartType } = advancedVSeed;
|
|
4425
|
+
const totalAggregation = 'string' == typeof totals ? totals : void 0;
|
|
4397
4426
|
const bodyCellStyle = cellStyle?.bodyCellStyle;
|
|
4398
4427
|
const themeConfig = config?.[chartType];
|
|
4399
4428
|
if (!bodyCellStyle) return spec;
|
|
@@ -4420,14 +4449,14 @@ self.R = R;
|
|
|
4420
4449
|
let columnMin;
|
|
4421
4450
|
let columnMax;
|
|
4422
4451
|
if (progressBarStyle || backgroundColorScale) {
|
|
4423
|
-
const { min, max } = getColumnMinMax(allData, field);
|
|
4452
|
+
const { min, max } = getColumnMinMax(allData, field, totalAggregation);
|
|
4424
4453
|
columnMin = min;
|
|
4425
4454
|
columnMax = max;
|
|
4426
4455
|
if (progressBarStyle) {
|
|
4427
4456
|
col.cellType = 'progressbar';
|
|
4428
4457
|
col.barType = 'negative';
|
|
4429
4458
|
col.min = progressBarStyle.barMin ?? columnMin;
|
|
4430
|
-
col.max = progressBarStyle.
|
|
4459
|
+
col.max = progressBarStyle.barMax ?? columnMax;
|
|
4431
4460
|
}
|
|
4432
4461
|
}
|
|
4433
4462
|
col.style = (datum)=>{
|
|
@@ -4800,6 +4829,16 @@ self.R = R;
|
|
|
4800
4829
|
};
|
|
4801
4830
|
return result;
|
|
4802
4831
|
};
|
|
4832
|
+
const isPivotTotalCell = (styleArg)=>{
|
|
4833
|
+
const cellHeaderPaths = styleArg?.cellHeaderPaths;
|
|
4834
|
+
if (!cellHeaderPaths) return false;
|
|
4835
|
+
if ('sub-total' === cellHeaderPaths.role || 'grand-total' === cellHeaderPaths.role) return true;
|
|
4836
|
+
const headerPaths = [
|
|
4837
|
+
...cellHeaderPaths.colHeaderPaths || [],
|
|
4838
|
+
...cellHeaderPaths.rowHeaderPaths || []
|
|
4839
|
+
];
|
|
4840
|
+
return headerPaths.some((path)=>path?.role === 'sub-total' || path?.role === 'grand-total');
|
|
4841
|
+
};
|
|
4803
4842
|
const pivotTableBodyCell = (spec, context)=>{
|
|
4804
4843
|
const { advancedVSeed } = context;
|
|
4805
4844
|
const { cellStyle, config, chartType } = advancedVSeed;
|
|
@@ -4868,6 +4907,7 @@ self.R = R;
|
|
|
4868
4907
|
cellStyle.barMarkWidth = themeConfig?.barMarkWidth;
|
|
4869
4908
|
cellStyle.barPadding = themeConfig?.barPadding;
|
|
4870
4909
|
cellStyle.barRightToLeft = themeConfig?.barRightToLeft;
|
|
4910
|
+
cellStyle.showBar = !isPivotTotalCell(datum);
|
|
4871
4911
|
}
|
|
4872
4912
|
return {
|
|
4873
4913
|
...result,
|