@visactor/vseed 0.4.8 → 0.4.9

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.
Files changed (93) hide show
  1. package/dist/cjs/index.cjs +2 -2
  2. package/dist/cjs/index.cjs.map +1 -1
  3. package/dist/esm/dataSelector/selector.d.ts +15 -1
  4. package/dist/esm/dataSelector/selector.js +16 -1
  5. package/dist/esm/dataSelector/selector.js.map +1 -1
  6. package/dist/esm/pipeline/spec/table/pipes/cellStyle/common.d.ts +29 -0
  7. package/dist/esm/pipeline/spec/table/pipes/cellStyle/common.js +40 -3
  8. package/dist/esm/pipeline/spec/table/pipes/cellStyle/common.js.map +1 -1
  9. package/dist/esm/pipeline/spec/table/pipes/cellStyle/pivot.js +38 -4
  10. package/dist/esm/pipeline/spec/table/pipes/cellStyle/pivot.js.map +1 -1
  11. package/dist/esm/pipeline/spec/table/pipes/cellStyle/table.js +46 -6
  12. package/dist/esm/pipeline/spec/table/pipes/cellStyle/table.js.map +1 -1
  13. package/dist/esm/pipeline/spec/table/pipes/columns/measuresToColumns.js +3 -0
  14. package/dist/esm/pipeline/spec/table/pipes/columns/measuresToColumns.js.map +1 -1
  15. package/dist/esm/theme/common/table.d.ts +35 -0
  16. package/dist/esm/theme/common/table.js +19 -3
  17. package/dist/esm/theme/common/table.js.map +1 -1
  18. package/dist/esm/types/chartType/area/zArea.d.ts +80 -0
  19. package/dist/esm/types/chartType/areaPercent/zAreaPercent.d.ts +80 -0
  20. package/dist/esm/types/chartType/bar/zBar.d.ts +48 -0
  21. package/dist/esm/types/chartType/barParallel/zBarParallel.d.ts +48 -0
  22. package/dist/esm/types/chartType/barPercent/zBarPercent.d.ts +48 -0
  23. package/dist/esm/types/chartType/boxPlot/zBoxPlot.d.ts +48 -0
  24. package/dist/esm/types/chartType/circlePacking/zCirclePacking.d.ts +8 -0
  25. package/dist/esm/types/chartType/column/zColumn.d.ts +48 -0
  26. package/dist/esm/types/chartType/columnParallel/zColumnParallel.d.ts +48 -0
  27. package/dist/esm/types/chartType/columnPercent/zColumnPercent.d.ts +48 -0
  28. package/dist/esm/types/chartType/donut/zDonut.d.ts +8 -0
  29. package/dist/esm/types/chartType/dualAxis/zDualAxis.d.ts +96 -0
  30. package/dist/esm/types/chartType/funnel/zFunnel.d.ts +8 -0
  31. package/dist/esm/types/chartType/heatmap/zHeatmap.d.ts +8 -0
  32. package/dist/esm/types/chartType/histogram/zHistogram.d.ts +48 -0
  33. package/dist/esm/types/chartType/line/zLine.d.ts +64 -0
  34. package/dist/esm/types/chartType/pie/zPie.d.ts +8 -0
  35. package/dist/esm/types/chartType/pivotTable/zPivotTable.d.ts +46 -4
  36. package/dist/esm/types/chartType/raceBar/zRaceBar.d.ts +48 -0
  37. package/dist/esm/types/chartType/raceColumn/zRaceColumn.d.ts +48 -0
  38. package/dist/esm/types/chartType/raceDonut/zRaceDonut.d.ts +8 -0
  39. package/dist/esm/types/chartType/raceLine/zRaceLine.d.ts +64 -0
  40. package/dist/esm/types/chartType/racePie/zRacePie.d.ts +8 -0
  41. package/dist/esm/types/chartType/raceScatter/zRaceScatter.d.ts +48 -0
  42. package/dist/esm/types/chartType/radar/zRadar.d.ts +8 -0
  43. package/dist/esm/types/chartType/rose/zRose.d.ts +8 -0
  44. package/dist/esm/types/chartType/roseParallel/zRoseParallel.d.ts +8 -0
  45. package/dist/esm/types/chartType/scatter/zScatter.d.ts +48 -0
  46. package/dist/esm/types/chartType/sunburst/zSunburst.d.ts +8 -0
  47. package/dist/esm/types/chartType/table/zTable.d.ts +46 -4
  48. package/dist/esm/types/chartType/treeMap/zTreeMap.d.ts +8 -0
  49. package/dist/esm/types/dataSelector/selector.d.ts +40 -0
  50. package/dist/esm/types/dataSelector/selector.js +9 -1
  51. package/dist/esm/types/dataSelector/selector.js.map +1 -1
  52. package/dist/esm/types/properties/annotation/annotation.d.ts +24 -0
  53. package/dist/esm/types/properties/annotation/zAnnotationArea.d.ts +4 -0
  54. package/dist/esm/types/properties/annotation/zAnnotationPoint.d.ts +8 -0
  55. package/dist/esm/types/properties/cellStyle/bodyCellStyle.d.ts +71 -5
  56. package/dist/esm/types/properties/cellStyle/bodyCellStyle.js +16 -4
  57. package/dist/esm/types/properties/cellStyle/bodyCellStyle.js.map +1 -1
  58. package/dist/esm/types/properties/cellStyle/cellStyle.d.ts +23 -2
  59. package/dist/esm/types/properties/config/annotation/zAnnotation.d.ts +8 -0
  60. package/dist/esm/types/properties/config/area.d.ts +24 -0
  61. package/dist/esm/types/properties/config/bar.d.ts +36 -0
  62. package/dist/esm/types/properties/config/boxplot.d.ts +12 -0
  63. package/dist/esm/types/properties/config/circlePacking.d.ts +8 -0
  64. package/dist/esm/types/properties/config/column.d.ts +36 -0
  65. package/dist/esm/types/properties/config/config.d.ts +328 -0
  66. package/dist/esm/types/properties/config/dualAxis.d.ts +12 -0
  67. package/dist/esm/types/properties/config/funnel.d.ts +8 -0
  68. package/dist/esm/types/properties/config/heatmap.d.ts +8 -0
  69. package/dist/esm/types/properties/config/histogram.d.ts +12 -0
  70. package/dist/esm/types/properties/config/label/zLabel.d.ts +8 -0
  71. package/dist/esm/types/properties/config/label/zPieLabel.d.ts +8 -0
  72. package/dist/esm/types/properties/config/line.d.ts +12 -0
  73. package/dist/esm/types/properties/config/pie.d.ts +24 -0
  74. package/dist/esm/types/properties/config/pivotTable.d.ts +10 -0
  75. package/dist/esm/types/properties/config/race.d.ts +72 -0
  76. package/dist/esm/types/properties/config/rose.d.ts +16 -0
  77. package/dist/esm/types/properties/config/scatter.d.ts +12 -0
  78. package/dist/esm/types/properties/config/sunburst.d.ts +8 -0
  79. package/dist/esm/types/properties/config/table.d.ts +10 -0
  80. package/dist/esm/types/properties/config/table.js +14 -1
  81. package/dist/esm/types/properties/config/table.js.map +1 -1
  82. package/dist/esm/types/properties/config/treeMap.d.ts +8 -0
  83. package/dist/esm/types/properties/markStyle/barStyle.d.ts +8 -0
  84. package/dist/esm/types/properties/markStyle/boxPlotStyle.d.ts +4 -0
  85. package/dist/esm/types/properties/markStyle/lineStyle.d.ts +8 -0
  86. package/dist/esm/types/properties/markStyle/markStyle.d.ts +80 -0
  87. package/dist/esm/types/properties/markStyle/outlierStyle.d.ts +4 -0
  88. package/dist/esm/types/properties/markStyle/pointStyle.d.ts +8 -0
  89. package/dist/esm/types/properties/markStyle/zAreaStyle.d.ts +8 -0
  90. package/dist/esm/types/properties/theme/customTheme.d.ts +656 -0
  91. package/dist/umd/index.js +24336 -23190
  92. package/dist/umd/index.js.map +1 -1
  93. package/package.json +3 -1
@@ -1,14 +1,28 @@
1
1
  import type { Datum } from '../types';
2
- import type { ChartDynamicFilter, PartialDatumRes, DimensionSelector, MeasureSelector, PartialDatumSelector, Selector, Selectors, RowWithFieldRes, TableDynamicFilter, ValueSelector, ValueDynamicFilter } from '../types/dataSelector';
2
+ import type { ChartDynamicFilter, PartialDatumRes, DimensionSelector, FieldSelector, MeasureSelector, PartialDatumSelector, Selector, Selectors, RowWithFieldRes, TableDynamicFilter, ValueSelector, ValueDynamicFilter } from '../types/dataSelector';
3
3
  export type DynamicFilter = TableDynamicFilter | ChartDynamicFilter | ValueDynamicFilter;
4
4
  export type DynamicFilterResult = RowWithFieldRes[] | PartialDatumRes[] | number | string;
5
5
  export declare const selector: (vchartDatum: Datum, selector: Selector | Selectors | undefined | null, selectorMode?: "And" | "Or") => boolean;
6
6
  export declare const isValueSelector: (selector: Selector) => selector is ValueSelector;
7
7
  export declare const isPartialDatumSelector: (selector: Selector) => selector is PartialDatumSelector;
8
+ /**
9
+ * 判断是否为字段选择器
10
+ * @description 字段选择器只有 field 属性,没有 operator/op/value
11
+ */
12
+ export declare const isFieldSelector: (selector: Selector) => selector is FieldSelector;
8
13
  export declare const isMeasureSelector: (selector: Selector) => selector is MeasureSelector;
9
14
  export declare const isDimensionSelector: (selector: Selector) => selector is DimensionSelector;
10
15
  export declare const selectByMeasure: (selector: MeasureSelector, datum: Datum) => boolean;
11
16
  export declare const selectByDmension: (selector: DimensionSelector, datum: Datum) => boolean;
17
+ /**
18
+ * 通过字段名选择
19
+ * @description 检查 datum 是否包含指定字段(用于列级选择)
20
+ */
21
+ export declare const selectByField: (selector: FieldSelector, datum: Datum) => boolean;
22
+ /**
23
+ * 检查给定的字段是否与 FieldSelector 匹配
24
+ */
25
+ export declare const matchesFieldSelector: (field: string, fieldSelector: FieldSelector) => boolean;
12
26
  export declare const selectByPartial: (selector: PartialDatumSelector, datum: Datum) => boolean;
13
27
  export declare const selectByValue: (selector: ValueSelector, datum: Datum) => boolean;
14
28
  /**
@@ -16,6 +16,7 @@ const selector_selector = (vchartDatum, selector, selectorMode = 'And')=>{
16
16
  ];
17
17
  return selectors['And' === selectorMode ? 'every' : 'some']((selector)=>{
18
18
  if (isValueSelector(selector)) return selectByValue(selector, datum);
19
+ if (isFieldSelector(selector)) return selectByField(selector, datum);
19
20
  if (isMeasureSelector(selector)) return selectByMeasure(selector, datum);
20
21
  if (isDimensionSelector(selector)) return selectByDmension(selector, datum);
21
22
  if (isPartialDatumSelector(selector)) return selectByPartial(selector, datum);
@@ -24,6 +25,7 @@ const selector_selector = (vchartDatum, selector, selectorMode = 'And')=>{
24
25
  };
25
26
  const isValueSelector = (selector)=>'string' == typeof selector || 'number' == typeof selector;
26
27
  const isPartialDatumSelector = (selector)=>'object' == typeof selector && null !== selector;
28
+ const isFieldSelector = (selector)=>'object' == typeof selector && null !== selector && 'field' in selector && !('operator' in selector) && !('op' in selector) && !('value' in selector);
27
29
  const isMeasureSelector = (selector)=>'object' == typeof selector && null !== selector && 'field' in selector && ('operator' in selector || 'op' in selector) && 'value' in selector && ([
28
30
  '=',
29
31
  '==',
@@ -98,6 +100,19 @@ const selectByDmension = (selector, datum)=>{
98
100
  }
99
101
  return false;
100
102
  };
103
+ const selectByField = (selector, datum)=>{
104
+ const fields = Array.isArray(selector.field) ? selector.field : [
105
+ selector.field
106
+ ];
107
+ const datumKeys = Object.keys(datum);
108
+ return fields.some((field)=>datumKeys.includes(field));
109
+ };
110
+ const matchesFieldSelector = (field, fieldSelector)=>{
111
+ const fields = Array.isArray(fieldSelector.field) ? fieldSelector.field : [
112
+ fieldSelector.field
113
+ ];
114
+ return fields.includes(field);
115
+ };
101
116
  const selectByPartial = (selector, datum)=>Object.keys(selector).every((key)=>datum[key] === selector[key]);
102
117
  const selectByValue = (selector, datum)=>Object.values(datum).some((v)=>v === selector);
103
118
  const matchesCellSelector = (cell, filterRes)=>{
@@ -193,6 +208,6 @@ const selectorWithDynamicFilter = (vchartDatum, selectorConfig, defaultSelector)
193
208
  }
194
209
  return defaultSelector ? selector_selector(vchartDatum, defaultSelector) : false;
195
210
  };
196
- export { executeDynamicFilter, isDimensionSelector, isDynamicFilter, isMeasureSelector, isPartialDatumSelector, isRowWithFieldDynamicFilter, isValueDynamicFilter, isValueSelector, matchDynamicFilterResult, selectByDmension, selectByMeasure, selectByPartial, selectByValue, selector_selector as selector, selectorWithDynamicFilter };
211
+ export { executeDynamicFilter, isDimensionSelector, isDynamicFilter, isFieldSelector, isMeasureSelector, isPartialDatumSelector, isRowWithFieldDynamicFilter, isValueDynamicFilter, isValueSelector, matchDynamicFilterResult, matchesFieldSelector, selectByDmension, selectByField, selectByMeasure, selectByPartial, selectByValue, selector_selector as selector, selectorWithDynamicFilter };
197
212
 
198
213
  //# sourceMappingURL=selector.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"dataSelector/selector.js","sources":["webpack://@visactor/vseed/./src/dataSelector/selector.ts"],"sourcesContent":["import type { Datum } from 'src/types'\nimport type {\n ChartDynamicFilter,\n PartialDatumRes,\n DimensionSelector,\n MeasureSelector,\n PartialDatumSelector,\n Selector,\n Selectors,\n RowWithFieldRes,\n TableDynamicFilter,\n ValueSelector,\n ValueDynamicFilter,\n} from '../types/dataSelector'\nimport { omit } from 'remeda'\nimport { executeFilterCode } from 'src/pipeline/utils/sandbox'\nimport { InnerRowIndex } from 'src/dataReshape'\n\nexport type DynamicFilter = TableDynamicFilter | ChartDynamicFilter | ValueDynamicFilter\nexport type DynamicFilterResult = RowWithFieldRes[] | PartialDatumRes[] | number | string\n\n/**\n * 判断两个数字是否“近似相等”\n */\nfunction nearlyEqual(a: number, b: number, epsilon = 1e-8) {\n // NaN 直接不相等\n if (Number.isNaN(a) || Number.isNaN(b)) return false\n // 引用同一个数 或 完全相等\n if (a === b) return true\n const diff = Math.abs(a - b)\n return diff <= epsilon\n}\n\nexport const selector = (\n vchartDatum: Datum,\n selector: Selector | Selectors | undefined | null,\n selectorMode: 'And' | 'Or' = 'And',\n) => {\n // 无有效选择器, 则认为全部匹配成功\n if (!selector) {\n return true\n }\n\n // 过滤掉 vchart 相关字段\n const vchartKeys = Object.keys(vchartDatum).filter((k) => k.toLocaleLowerCase().startsWith('__vchart'))\n const datum = omit(vchartDatum, vchartKeys) as Datum\n\n // 统一处理选择器为数组\n const selectors = (Array.isArray(selector) ? selector : [selector]) as Selectors\n\n return selectors[selectorMode === 'And' ? 'every' : 'some']((selector) => {\n // 1. 字符串或数字\n if (isValueSelector(selector)) {\n return selectByValue(selector, datum)\n }\n\n // 2. 指标选择器\n else if (isMeasureSelector(selector)) {\n return selectByMeasure(selector, datum)\n }\n // 3. 维度选择器\n else if (isDimensionSelector(selector)) {\n return selectByDmension(selector, datum)\n }\n // 4. 部分数据对象选择器\n else if (isPartialDatumSelector(selector)) {\n return selectByPartial(selector, datum)\n }\n\n return false\n })\n}\n\nexport const isValueSelector = (selector: Selector): selector is ValueSelector => {\n return typeof selector === 'string' || typeof selector === 'number'\n}\n\nexport const isPartialDatumSelector = (selector: Selector): selector is PartialDatumSelector => {\n return typeof selector === 'object' && selector !== null\n}\n\nexport const isMeasureSelector = (selector: Selector): selector is MeasureSelector => {\n return (\n typeof selector === 'object' &&\n selector !== null &&\n 'field' in selector &&\n ('operator' in selector || 'op' in selector) &&\n 'value' in selector &&\n (['=', '==', '!=', '>', '<', '>=', '<=', 'between'].includes(selector.operator as string) ||\n ['=', '==', '!=', '>', '<', '>=', '<=', 'between'].includes(selector.op as string))\n )\n}\n\nexport const isDimensionSelector = (selector: Selector): selector is DimensionSelector => {\n return (\n typeof selector === 'object' &&\n selector !== null &&\n 'field' in selector &&\n ('operator' in selector || 'op' in selector) &&\n 'value' in selector &&\n (['in', 'not in'].includes(selector.operator as string) || ['in', 'not in'].includes(selector.op as string))\n )\n}\n\nexport const selectByMeasure = (selector: MeasureSelector, datum: Datum) => {\n const op = selector.operator || selector.op\n const selectorValueArr = Array.isArray(selector.value) ? selector.value : [selector.value]\n\n switch (op) {\n case '=':\n if (\n String(datum[selector.field]) === String(selectorValueArr[0]) ||\n nearlyEqual(Number(datum[selector.field]), Number(selectorValueArr[0]))\n ) {\n return true\n }\n break\n case '==':\n if (datum[selector.field] === selectorValueArr[0]) {\n return true\n }\n break\n case '!=':\n if (datum[selector.field] !== selectorValueArr[0]) {\n return true\n }\n break\n case '>':\n if (\n datum[selector.field] > selectorValueArr[0] &&\n !nearlyEqual(Number(datum[selector.field]), Number(selectorValueArr[0]))\n ) {\n return true\n }\n break\n case '<':\n if (\n datum[selector.field] < selectorValueArr[0] &&\n !nearlyEqual(Number(datum[selector.field]), Number(selectorValueArr[0]))\n ) {\n return true\n }\n break\n case '>=':\n if (\n datum[selector.field] >= selectorValueArr[0] ||\n nearlyEqual(Number(datum[selector.field]), Number(selectorValueArr[0]))\n ) {\n return true\n }\n break\n case '<=':\n if (\n datum[selector.field] <= selectorValueArr[0] ||\n nearlyEqual(Number(datum[selector.field]), Number(selectorValueArr[0]))\n ) {\n return true\n }\n break\n case 'between':\n if (\n Array.isArray(selector.value) &&\n (datum[selector.field] >= selectorValueArr[0] ||\n nearlyEqual(Number(datum[selector.field]), Number(selectorValueArr[0]))) &&\n (datum[selector.field] <= selectorValueArr[1] ||\n nearlyEqual(Number(datum[selector.field]), Number(selectorValueArr[1])))\n ) {\n return true\n }\n break\n }\n return false\n}\n\nexport const selectByDmension = (selector: DimensionSelector, datum: Datum) => {\n const op = selector.operator || selector.op\n const selectorValueArr = Array.isArray(selector.value) ? selector.value : [selector.value]\n switch (op) {\n case 'in':\n if (selectorValueArr.includes(datum[selector.field] as string | number)) {\n return true\n }\n break\n case 'not in':\n if (!selectorValueArr.includes(datum[selector.field] as string | number)) {\n return true\n }\n break\n }\n\n return false\n}\n\nexport const selectByPartial = (selector: PartialDatumSelector, datum: Datum) => {\n return Object.keys(selector).every((key) => datum[key] === selector[key])\n}\n\nexport const selectByValue = (selector: ValueSelector, datum: Datum) => {\n return Object.values(datum).some((v) => v === selector)\n}\n\nconst matchesCellSelector = (cell: Datum, filterRes: RowWithFieldRes) => {\n if (filterRes[InnerRowIndex] !== cell[InnerRowIndex]) return false\n return filterRes.field === '*' || Object.keys(cell).includes(filterRes.field)\n}\n\nconst matchesDatum = (target: Datum, candidate: Datum) => {\n return Object.keys(candidate).every((key) => target[key] === candidate[key])\n}\n\n/**\n * 公共方法:检查是否为动态过滤器结构\n */\nconst isDynamicFilterLike = (selector: any, expectedTypes: string[]): boolean => {\n return (\n typeof selector === 'object' &&\n selector !== null &&\n 'type' in selector &&\n expectedTypes.includes(selector.type) &&\n 'code' in selector &&\n typeof selector.code === 'string'\n )\n}\n\n/**\n * 识别是否为row-with-field动态过滤器\n */\nexport const isRowWithFieldDynamicFilter = (selector: any): selector is TableDynamicFilter => {\n return isDynamicFilterLike(selector, ['row-with-field'])\n}\n\n/**\n * 识别是否为数值动态过滤器(用于标注线等场景)\n */\nexport const isValueDynamicFilter = (selector: any): selector is ValueDynamicFilter => {\n return isDynamicFilterLike(selector, ['value'])\n}\n\n/**\n * 识别是否为动态过滤器(通用判断,包含所有类型的动态过滤器)\n */\nexport const isDynamicFilter = (selector: any): selector is DynamicFilter => {\n return isDynamicFilterLike(selector, ['row-with-field', 'value'])\n}\n\n/**\n * 验证动态过滤器执行结果的类型兼容性\n * @description\n * 在主线程中对 Worker 返回值进行类型特定的验证\n * - TableDynamicFilter: 必须返回包含 __row_index 和 field 的对象数组\n * - ChartDynamicFilter: 必须返回任意对象数组\n * - ValueDynamicFilter: 必须返回 number | string\n *\n * @param result Worker 返回的原始结果\n * @param filter 动态过滤器配置\n * @returns 验证是否通过\n * @throws 当验证失败时抛出 TypeError\n */\nconst validateFilterResult = (result: any, filter: DynamicFilter): void => {\n // ValueDynamicFilter:必须返回 number | string\n if (isValueDynamicFilter(filter)) {\n if (typeof result !== 'number' && typeof result !== 'string') {\n throw new TypeError(\n `ValueDynamicFilter must return a number or string, but got: ${typeof result}. ` + `Code: \"${filter.code}\"`,\n )\n }\n return\n }\n\n // TableDynamicFilter 和 ChartDynamicFilter:必须返回对象数组\n if (!Array.isArray(result)) {\n throw new TypeError(\n `${isRowWithFieldDynamicFilter(filter) ? 'TableDynamicFilter' : 'ChartDynamicFilter'} must return an array, ` +\n `but got: ${typeof result}. Code: \"${filter.code}\"`,\n )\n }\n\n // TableDynamicFilter:检查数组元素结构\n if (isRowWithFieldDynamicFilter(filter)) {\n for (let i = 0; i < result.length; i++) {\n const item = result[i]\n if (typeof item !== 'object' || item === null) {\n throw new TypeError(`TableDynamicFilter array element at index ${i} must be an object, got: ${typeof item}`)\n }\n if (!(InnerRowIndex in item) && '__row_index' in item === false) {\n throw new TypeError(\n `TableDynamicFilter array element at index ${i} must contain __row_index or InnerRowIndex field`,\n )\n }\n if (!('field' in item)) {\n throw new TypeError(`TableDynamicFilter array element at index ${i} must contain 'field' field`)\n }\n }\n }\n}\n\n/**\n * 执行动态过滤器代码,获取匹配结果\n * @description\n * 阶段1:执行阶段 - 一次性执行 dynamicFilter.code,获取所有匹配结果\n * - TableDynamicFilter → CellSelector[]\n * - ChartDynamicFilter → PartialDatumSelector[]\n * - ValueDynamicFilter → number | string\n *\n * @param filter 动态过滤器配置\n * @param allData 完整数据集\n * @returns 执行结果数组或标量值\n */\nexport const executeDynamicFilter = async (\n filter: DynamicFilter,\n allData: Datum[],\n): Promise<{ success: boolean; data: DynamicFilterResult; error?: string }> => {\n try {\n const { success, data, error } = await executeFilterCode({\n code: filter.code,\n data: allData,\n })\n\n if (!success) {\n // eslint-disable-next-line no-console\n console.warn('[vseed] Dynamic filter execution failed:', error)\n return {\n success: false,\n data: isRowWithFieldDynamicFilter(filter) ? [] : '',\n error,\n }\n }\n\n // 主线程验证:根据过滤器类型进行特定检查\n try {\n validateFilterResult(data, filter)\n } catch (validationError) {\n // eslint-disable-next-line no-console\n console.error('[vseed] Dynamic filter result validation failed:', validationError)\n return {\n success: false,\n data: isRowWithFieldDynamicFilter(filter) ? [] : '',\n error: validationError instanceof Error ? validationError.message : String(validationError),\n }\n }\n\n return {\n success,\n data: data as DynamicFilterResult,\n }\n } catch (error) {\n // 捕获所有可能的异常:\n // - Worker 不支持\n // - Worker 池初始化/获取失败\n // - validateCodeSafety 验证失败\n // - 数据验证失败\n const errorMessage = error instanceof Error ? error.message : String(error)\n // eslint-disable-next-line no-console\n console.error('[vseed] Dynamic filter execution threw exception:', errorMessage)\n\n return {\n success: false,\n data: isRowWithFieldDynamicFilter(filter) ? [] : '',\n error: errorMessage,\n }\n }\n}\n\n/**\n * 匹配动态过滤器结果\n * @description\n * 阶段2:匹配阶段 - 判断当前 datum/cell 是否在执行结果中\n * - 使用 OR 策略:结果数组中任一项匹配即返回 true\n * - 表格场景:检查 { row, field } 是否在 CellSelector[] 中\n * - 图表场景:检查 datum 的维度值是否匹配 PartialDatumSelector[] 中任一项\n * - 数值场景:不适用(ValueDynamicFilter返回标量值,不用于匹配)\n *\n * @param result 动态过滤器执行结果(CellSelector[] 或 PartialDatumSelector[],不包括 ValueDynamicFilter)\n * @param datum 当前数据项\n * @param selectorType 选择器类型(用于区分表格和图表动态过滤器)\n * @returns 是否匹配(OR 策略)\n */\nexport const matchDynamicFilterResult = (\n result: DynamicFilterResult,\n datum: Datum,\n selectorType: 'table' | 'chart' = 'table',\n): boolean => {\n // ValueDynamicFilter 不应该通过这个函数处理\n if (typeof result === 'number' || typeof result === 'string') {\n throw new Error('matchDynamicFilterResult does not support ValueDynamicFilter results')\n }\n\n if (selectorType === 'table') {\n return result.some((item) => {\n return matchesCellSelector(datum, item as RowWithFieldRes)\n })\n }\n return result.some((item) => {\n return matchesDatum(datum, item as PartialDatumSelector)\n })\n}\n\n/**\n * 带有动态过滤器支持的选择器\n * @description\n * 处理流程(两阶段设计):\n *\n * 阶段1 - 执行(Execute):\n * - 在 prepare() 阶段执行,结果写入 dynamicFilter.result\n * - TableDynamicFilter → CellSelector[]\n * - ChartDynamicFilter → PartialDatumSelector[]\n * - ValueDynamicFilter → number | string(用于读取,不用于匹配)\n *\n * 阶段2 - 匹配(Match):\n * - 读取 dynamicFilter.result\n * - 使用 OR 策略:结果数组中任一项匹配即返回 true\n * - 表格:判断 { row, field } 是否在 CellSelector[] 中\n * - 图表:判断 datum 是否匹配 PartialDatumSelector[] 中任一项\n * - 数值:不用于匹配,直接返回 false(数值过滤器在主要用于标注线值,不用于行列选择)\n *\n * @param vchartDatum 单个数据项\n * @param selectorConfig 选择器配置(可包含 DynamicFilter)\n * @param defaultSelector 传统选择器(仅在 DynamicFilter 无结果且有 fallback 时使用)\n * @returns 该数据项是否符合选择条件\n */\nexport const selectorWithDynamicFilter = (\n vchartDatum: Datum,\n selectorConfig: DynamicFilter,\n defaultSelector?: Selector | Selector[] | null,\n): boolean => {\n // 无有效选择器, 则认为全部匹配成功\n if (!selectorConfig) {\n return true\n }\n\n // ValueDynamicFilter 不用于选择,直接返回 false\n if (isValueDynamicFilter(selectorConfig)) {\n if (selectorConfig.fallback) {\n const fallbackSelector = Array.isArray(selectorConfig.fallback)\n ? selectorConfig.fallback\n : [selectorConfig.fallback]\n return selector(vchartDatum, fallbackSelector)\n }\n return defaultSelector ? selector(vchartDatum, defaultSelector) : false\n }\n\n const selectorType = isRowWithFieldDynamicFilter(selectorConfig) ? 'table' : 'chart'\n\n // 优先使用预先执行的结果\n if (selectorConfig.result?.success && selectorConfig.result.data) {\n return matchDynamicFilterResult(selectorConfig.result.data, vchartDatum, selectorType)\n }\n\n if (selectorConfig.fallback) {\n // 如果有 fallback,使用传统 selector 进行匹配\n const fallbackSelector = Array.isArray(selectorConfig.fallback)\n ? selectorConfig.fallback\n : [selectorConfig.fallback]\n return selector(vchartDatum, fallbackSelector)\n }\n\n // 没有结果也没有 fallback,返回 false\n return defaultSelector ? selector(vchartDatum, defaultSelector) : false\n}\n"],"names":["nearlyEqual","a","b","epsilon","Number","diff","Math","selector","vchartDatum","selectorMode","vchartKeys","Object","k","datum","omit","selectors","Array","isValueSelector","selectByValue","isMeasureSelector","selectByMeasure","isDimensionSelector","selectByDmension","isPartialDatumSelector","selectByPartial","op","selectorValueArr","String","key","v","matchesCellSelector","cell","filterRes","InnerRowIndex","matchesDatum","target","candidate","isDynamicFilterLike","expectedTypes","isRowWithFieldDynamicFilter","isValueDynamicFilter","isDynamicFilter","validateFilterResult","result","filter","TypeError","i","item","executeDynamicFilter","allData","success","data","error","executeFilterCode","console","validationError","Error","errorMessage","matchDynamicFilterResult","selectorType","selectorWithDynamicFilter","selectorConfig","defaultSelector","fallbackSelector"],"mappings":"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"}
1
+ {"version":3,"file":"dataSelector/selector.js","sources":["webpack://@visactor/vseed/./src/dataSelector/selector.ts"],"sourcesContent":["import type { Datum } from 'src/types'\nimport type {\n ChartDynamicFilter,\n PartialDatumRes,\n DimensionSelector,\n FieldSelector,\n MeasureSelector,\n PartialDatumSelector,\n Selector,\n Selectors,\n RowWithFieldRes,\n TableDynamicFilter,\n ValueSelector,\n ValueDynamicFilter,\n} from '../types/dataSelector'\nimport { omit } from 'remeda'\nimport { executeFilterCode } from 'src/pipeline/utils/sandbox'\nimport { InnerRowIndex } from 'src/dataReshape'\n\nexport type DynamicFilter = TableDynamicFilter | ChartDynamicFilter | ValueDynamicFilter\nexport type DynamicFilterResult = RowWithFieldRes[] | PartialDatumRes[] | number | string\n\n/**\n * 判断两个数字是否“近似相等”\n */\nfunction nearlyEqual(a: number, b: number, epsilon = 1e-8) {\n // NaN 直接不相等\n if (Number.isNaN(a) || Number.isNaN(b)) return false\n // 引用同一个数 或 完全相等\n if (a === b) return true\n const diff = Math.abs(a - b)\n return diff <= epsilon\n}\n\nexport const selector = (\n vchartDatum: Datum,\n selector: Selector | Selectors | undefined | null,\n selectorMode: 'And' | 'Or' = 'And',\n) => {\n // 无有效选择器, 则认为全部匹配成功\n if (!selector) {\n return true\n }\n\n // 过滤掉 vchart 相关字段\n const vchartKeys = Object.keys(vchartDatum).filter((k) => k.toLocaleLowerCase().startsWith('__vchart'))\n const datum = omit(vchartDatum, vchartKeys) as Datum\n\n // 统一处理选择器为数组\n const selectors = (Array.isArray(selector) ? selector : [selector]) as Selectors\n\n return selectors[selectorMode === 'And' ? 'every' : 'some']((selector) => {\n // 1. 字符串或数字\n if (isValueSelector(selector)) {\n return selectByValue(selector, datum)\n }\n\n // 2. 字段选择器(优先于 MeasureSelector/DimensionSelector 判断,因为字段选择器也有 field 属性)\n else if (isFieldSelector(selector)) {\n return selectByField(selector, datum)\n }\n\n // 3. 指标选择器\n else if (isMeasureSelector(selector)) {\n return selectByMeasure(selector, datum)\n }\n // 4. 维度选择器\n else if (isDimensionSelector(selector)) {\n return selectByDmension(selector, datum)\n }\n // 5. 部分数据对象选择器\n else if (isPartialDatumSelector(selector)) {\n return selectByPartial(selector, datum)\n }\n\n return false\n })\n}\n\nexport const isValueSelector = (selector: Selector): selector is ValueSelector => {\n return typeof selector === 'string' || typeof selector === 'number'\n}\n\nexport const isPartialDatumSelector = (selector: Selector): selector is PartialDatumSelector => {\n return typeof selector === 'object' && selector !== null\n}\n\n/**\n * 判断是否为字段选择器\n * @description 字段选择器只有 field 属性,没有 operator/op/value\n */\nexport const isFieldSelector = (selector: Selector): selector is FieldSelector => {\n return (\n typeof selector === 'object' &&\n selector !== null &&\n 'field' in selector &&\n !('operator' in selector) &&\n !('op' in selector) &&\n !('value' in selector)\n )\n}\n\nexport const isMeasureSelector = (selector: Selector): selector is MeasureSelector => {\n return (\n typeof selector === 'object' &&\n selector !== null &&\n 'field' in selector &&\n ('operator' in selector || 'op' in selector) &&\n 'value' in selector &&\n (['=', '==', '!=', '>', '<', '>=', '<=', 'between'].includes(selector.operator as string) ||\n ['=', '==', '!=', '>', '<', '>=', '<=', 'between'].includes(selector.op as string))\n )\n}\n\nexport const isDimensionSelector = (selector: Selector): selector is DimensionSelector => {\n return (\n typeof selector === 'object' &&\n selector !== null &&\n 'field' in selector &&\n ('operator' in selector || 'op' in selector) &&\n 'value' in selector &&\n (['in', 'not in'].includes(selector.operator as string) || ['in', 'not in'].includes(selector.op as string))\n )\n}\n\nexport const selectByMeasure = (selector: MeasureSelector, datum: Datum) => {\n const op = selector.operator || selector.op\n const selectorValueArr = Array.isArray(selector.value) ? selector.value : [selector.value]\n\n switch (op) {\n case '=':\n if (\n String(datum[selector.field]) === String(selectorValueArr[0]) ||\n nearlyEqual(Number(datum[selector.field]), Number(selectorValueArr[0]))\n ) {\n return true\n }\n break\n case '==':\n if (datum[selector.field] === selectorValueArr[0]) {\n return true\n }\n break\n case '!=':\n if (datum[selector.field] !== selectorValueArr[0]) {\n return true\n }\n break\n case '>':\n if (\n datum[selector.field] > selectorValueArr[0] &&\n !nearlyEqual(Number(datum[selector.field]), Number(selectorValueArr[0]))\n ) {\n return true\n }\n break\n case '<':\n if (\n datum[selector.field] < selectorValueArr[0] &&\n !nearlyEqual(Number(datum[selector.field]), Number(selectorValueArr[0]))\n ) {\n return true\n }\n break\n case '>=':\n if (\n datum[selector.field] >= selectorValueArr[0] ||\n nearlyEqual(Number(datum[selector.field]), Number(selectorValueArr[0]))\n ) {\n return true\n }\n break\n case '<=':\n if (\n datum[selector.field] <= selectorValueArr[0] ||\n nearlyEqual(Number(datum[selector.field]), Number(selectorValueArr[0]))\n ) {\n return true\n }\n break\n case 'between':\n if (\n Array.isArray(selector.value) &&\n (datum[selector.field] >= selectorValueArr[0] ||\n nearlyEqual(Number(datum[selector.field]), Number(selectorValueArr[0]))) &&\n (datum[selector.field] <= selectorValueArr[1] ||\n nearlyEqual(Number(datum[selector.field]), Number(selectorValueArr[1])))\n ) {\n return true\n }\n break\n }\n return false\n}\n\nexport const selectByDmension = (selector: DimensionSelector, datum: Datum) => {\n const op = selector.operator || selector.op\n const selectorValueArr = Array.isArray(selector.value) ? selector.value : [selector.value]\n switch (op) {\n case 'in':\n if (selectorValueArr.includes(datum[selector.field] as string | number)) {\n return true\n }\n break\n case 'not in':\n if (!selectorValueArr.includes(datum[selector.field] as string | number)) {\n return true\n }\n break\n }\n\n return false\n}\n\n/**\n * 通过字段名选择\n * @description 检查 datum 是否包含指定字段(用于列级选择)\n */\nexport const selectByField = (selector: FieldSelector, datum: Datum) => {\n const fields = Array.isArray(selector.field) ? selector.field : [selector.field]\n const datumKeys = Object.keys(datum)\n\n // 检查 datum 的 keys 中是否包含任一指定字段\n return fields.some((field) => datumKeys.includes(field))\n}\n\n/**\n * 检查给定的字段是否与 FieldSelector 匹配\n */\nexport const matchesFieldSelector = (field: string, fieldSelector: FieldSelector): boolean => {\n const fields = Array.isArray(fieldSelector.field) ? fieldSelector.field : [fieldSelector.field]\n return fields.includes(field)\n}\n\nexport const selectByPartial = (selector: PartialDatumSelector, datum: Datum) => {\n return Object.keys(selector).every((key) => datum[key] === selector[key])\n}\n\nexport const selectByValue = (selector: ValueSelector, datum: Datum) => {\n return Object.values(datum).some((v) => v === selector)\n}\n\nconst matchesCellSelector = (cell: Datum, filterRes: RowWithFieldRes) => {\n if (filterRes[InnerRowIndex] !== cell[InnerRowIndex]) return false\n return filterRes.field === '*' || Object.keys(cell).includes(filterRes.field)\n}\n\nconst matchesDatum = (target: Datum, candidate: Datum) => {\n return Object.keys(candidate).every((key) => target[key] === candidate[key])\n}\n\n/**\n * 公共方法:检查是否为动态过滤器结构\n */\nconst isDynamicFilterLike = (selector: any, expectedTypes: string[]): boolean => {\n return (\n typeof selector === 'object' &&\n selector !== null &&\n 'type' in selector &&\n expectedTypes.includes(selector.type) &&\n 'code' in selector &&\n typeof selector.code === 'string'\n )\n}\n\n/**\n * 识别是否为row-with-field动态过滤器\n */\nexport const isRowWithFieldDynamicFilter = (selector: any): selector is TableDynamicFilter => {\n return isDynamicFilterLike(selector, ['row-with-field'])\n}\n\n/**\n * 识别是否为数值动态过滤器(用于标注线等场景)\n */\nexport const isValueDynamicFilter = (selector: any): selector is ValueDynamicFilter => {\n return isDynamicFilterLike(selector, ['value'])\n}\n\n/**\n * 识别是否为动态过滤器(通用判断,包含所有类型的动态过滤器)\n */\nexport const isDynamicFilter = (selector: any): selector is DynamicFilter => {\n return isDynamicFilterLike(selector, ['row-with-field', 'value'])\n}\n\n/**\n * 验证动态过滤器执行结果的类型兼容性\n * @description\n * 在主线程中对 Worker 返回值进行类型特定的验证\n * - TableDynamicFilter: 必须返回包含 __row_index 和 field 的对象数组\n * - ChartDynamicFilter: 必须返回任意对象数组\n * - ValueDynamicFilter: 必须返回 number | string\n *\n * @param result Worker 返回的原始结果\n * @param filter 动态过滤器配置\n * @returns 验证是否通过\n * @throws 当验证失败时抛出 TypeError\n */\nconst validateFilterResult = (result: any, filter: DynamicFilter): void => {\n // ValueDynamicFilter:必须返回 number | string\n if (isValueDynamicFilter(filter)) {\n if (typeof result !== 'number' && typeof result !== 'string') {\n throw new TypeError(\n `ValueDynamicFilter must return a number or string, but got: ${typeof result}. ` + `Code: \"${filter.code}\"`,\n )\n }\n return\n }\n\n // TableDynamicFilter 和 ChartDynamicFilter:必须返回对象数组\n if (!Array.isArray(result)) {\n throw new TypeError(\n `${isRowWithFieldDynamicFilter(filter) ? 'TableDynamicFilter' : 'ChartDynamicFilter'} must return an array, ` +\n `but got: ${typeof result}. Code: \"${filter.code}\"`,\n )\n }\n\n // TableDynamicFilter:检查数组元素结构\n if (isRowWithFieldDynamicFilter(filter)) {\n for (let i = 0; i < result.length; i++) {\n const item = result[i]\n if (typeof item !== 'object' || item === null) {\n throw new TypeError(`TableDynamicFilter array element at index ${i} must be an object, got: ${typeof item}`)\n }\n if (!(InnerRowIndex in item) && '__row_index' in item === false) {\n throw new TypeError(\n `TableDynamicFilter array element at index ${i} must contain __row_index or InnerRowIndex field`,\n )\n }\n if (!('field' in item)) {\n throw new TypeError(`TableDynamicFilter array element at index ${i} must contain 'field' field`)\n }\n }\n }\n}\n\n/**\n * 执行动态过滤器代码,获取匹配结果\n * @description\n * 阶段1:执行阶段 - 一次性执行 dynamicFilter.code,获取所有匹配结果\n * - TableDynamicFilter → CellSelector[]\n * - ChartDynamicFilter → PartialDatumSelector[]\n * - ValueDynamicFilter → number | string\n *\n * @param filter 动态过滤器配置\n * @param allData 完整数据集\n * @returns 执行结果数组或标量值\n */\nexport const executeDynamicFilter = async (\n filter: DynamicFilter,\n allData: Datum[],\n): Promise<{ success: boolean; data: DynamicFilterResult; error?: string }> => {\n try {\n const { success, data, error } = await executeFilterCode({\n code: filter.code,\n data: allData,\n })\n\n if (!success) {\n // eslint-disable-next-line no-console\n console.warn('[vseed] Dynamic filter execution failed:', error)\n return {\n success: false,\n data: isRowWithFieldDynamicFilter(filter) ? [] : '',\n error,\n }\n }\n\n // 主线程验证:根据过滤器类型进行特定检查\n try {\n validateFilterResult(data, filter)\n } catch (validationError) {\n // eslint-disable-next-line no-console\n console.error('[vseed] Dynamic filter result validation failed:', validationError)\n return {\n success: false,\n data: isRowWithFieldDynamicFilter(filter) ? [] : '',\n error: validationError instanceof Error ? validationError.message : String(validationError),\n }\n }\n\n return {\n success,\n data: data as DynamicFilterResult,\n }\n } catch (error) {\n // 捕获所有可能的异常:\n // - Worker 不支持\n // - Worker 池初始化/获取失败\n // - validateCodeSafety 验证失败\n // - 数据验证失败\n const errorMessage = error instanceof Error ? error.message : String(error)\n // eslint-disable-next-line no-console\n console.error('[vseed] Dynamic filter execution threw exception:', errorMessage)\n\n return {\n success: false,\n data: isRowWithFieldDynamicFilter(filter) ? [] : '',\n error: errorMessage,\n }\n }\n}\n\n/**\n * 匹配动态过滤器结果\n * @description\n * 阶段2:匹配阶段 - 判断当前 datum/cell 是否在执行结果中\n * - 使用 OR 策略:结果数组中任一项匹配即返回 true\n * - 表格场景:检查 { row, field } 是否在 CellSelector[] 中\n * - 图表场景:检查 datum 的维度值是否匹配 PartialDatumSelector[] 中任一项\n * - 数值场景:不适用(ValueDynamicFilter返回标量值,不用于匹配)\n *\n * @param result 动态过滤器执行结果(CellSelector[] 或 PartialDatumSelector[],不包括 ValueDynamicFilter)\n * @param datum 当前数据项\n * @param selectorType 选择器类型(用于区分表格和图表动态过滤器)\n * @returns 是否匹配(OR 策略)\n */\nexport const matchDynamicFilterResult = (\n result: DynamicFilterResult,\n datum: Datum,\n selectorType: 'table' | 'chart' = 'table',\n): boolean => {\n // ValueDynamicFilter 不应该通过这个函数处理\n if (typeof result === 'number' || typeof result === 'string') {\n throw new Error('matchDynamicFilterResult does not support ValueDynamicFilter results')\n }\n\n if (selectorType === 'table') {\n return result.some((item) => {\n return matchesCellSelector(datum, item as RowWithFieldRes)\n })\n }\n return result.some((item) => {\n return matchesDatum(datum, item as PartialDatumSelector)\n })\n}\n\n/**\n * 带有动态过滤器支持的选择器\n * @description\n * 处理流程(两阶段设计):\n *\n * 阶段1 - 执行(Execute):\n * - 在 prepare() 阶段执行,结果写入 dynamicFilter.result\n * - TableDynamicFilter → CellSelector[]\n * - ChartDynamicFilter → PartialDatumSelector[]\n * - ValueDynamicFilter → number | string(用于读取,不用于匹配)\n *\n * 阶段2 - 匹配(Match):\n * - 读取 dynamicFilter.result\n * - 使用 OR 策略:结果数组中任一项匹配即返回 true\n * - 表格:判断 { row, field } 是否在 CellSelector[] 中\n * - 图表:判断 datum 是否匹配 PartialDatumSelector[] 中任一项\n * - 数值:不用于匹配,直接返回 false(数值过滤器在主要用于标注线值,不用于行列选择)\n *\n * @param vchartDatum 单个数据项\n * @param selectorConfig 选择器配置(可包含 DynamicFilter)\n * @param defaultSelector 传统选择器(仅在 DynamicFilter 无结果且有 fallback 时使用)\n * @returns 该数据项是否符合选择条件\n */\nexport const selectorWithDynamicFilter = (\n vchartDatum: Datum,\n selectorConfig: DynamicFilter,\n defaultSelector?: Selector | Selector[] | null,\n): boolean => {\n // 无有效选择器, 则认为全部匹配成功\n if (!selectorConfig) {\n return true\n }\n\n // ValueDynamicFilter 不用于选择,直接返回 false\n if (isValueDynamicFilter(selectorConfig)) {\n if (selectorConfig.fallback) {\n const fallbackSelector = Array.isArray(selectorConfig.fallback)\n ? selectorConfig.fallback\n : [selectorConfig.fallback]\n return selector(vchartDatum, fallbackSelector)\n }\n return defaultSelector ? selector(vchartDatum, defaultSelector) : false\n }\n\n const selectorType = isRowWithFieldDynamicFilter(selectorConfig) ? 'table' : 'chart'\n\n // 优先使用预先执行的结果\n if (selectorConfig.result?.success && selectorConfig.result.data) {\n return matchDynamicFilterResult(selectorConfig.result.data, vchartDatum, selectorType)\n }\n\n if (selectorConfig.fallback) {\n // 如果有 fallback,使用传统 selector 进行匹配\n const fallbackSelector = Array.isArray(selectorConfig.fallback)\n ? selectorConfig.fallback\n : [selectorConfig.fallback]\n return selector(vchartDatum, fallbackSelector)\n }\n\n // 没有结果也没有 fallback,返回 false\n return defaultSelector ? selector(vchartDatum, defaultSelector) : false\n}\n"],"names":["nearlyEqual","a","b","epsilon","Number","diff","Math","selector","vchartDatum","selectorMode","vchartKeys","Object","k","datum","omit","selectors","Array","isValueSelector","selectByValue","isFieldSelector","selectByField","isMeasureSelector","selectByMeasure","isDimensionSelector","selectByDmension","isPartialDatumSelector","selectByPartial","op","selectorValueArr","String","fields","datumKeys","field","matchesFieldSelector","fieldSelector","key","v","matchesCellSelector","cell","filterRes","InnerRowIndex","matchesDatum","target","candidate","isDynamicFilterLike","expectedTypes","isRowWithFieldDynamicFilter","isValueDynamicFilter","isDynamicFilter","validateFilterResult","result","filter","TypeError","i","item","executeDynamicFilter","allData","success","data","error","executeFilterCode","console","validationError","Error","errorMessage","matchDynamicFilterResult","selectorType","selectorWithDynamicFilter","selectorConfig","defaultSelector","fallbackSelector"],"mappings":"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"}
@@ -1,5 +1,34 @@
1
1
  import type { BodyCellStyle, Datum } from '../../../../../types';
2
+ /**
3
+ * 计算线性颜色映射(使用 tinycolor2)
4
+ * @param value 实际值
5
+ * @param minValue 最小值
6
+ * @param maxValue 最大值
7
+ * @param minColor 最小值颜色
8
+ * @param maxColor 最大值颜色
9
+ * @returns RGB 颜色字符串
10
+ */
11
+ export declare const interpolateColor: (value: number, minValue: number, maxValue: number, minColor: string, maxColor: string) => string;
12
+ /**
13
+ * 从 bodyCellStyle 提取要应用到单元格的样式
14
+ */
2
15
  export declare const pickBodyCellStyle: (bodyCellStyle: BodyCellStyle) => Record<string, any>;
16
+ /**
17
+ * 计算数据列的最小值和最大值
18
+ */
19
+ export declare const getColumnMinMax: (allData: Datum[], field: string) => {
20
+ min: number;
21
+ max: number;
22
+ };
23
+ /**
24
+ * 应用 scale 颜色映射
25
+ */
26
+ export declare const applyColorScale: (value: any, scale: {
27
+ minValue: number;
28
+ maxValue: number;
29
+ minColor: string;
30
+ maxColor: string;
31
+ } | undefined) => string | undefined;
3
32
  export declare const getCellOriginalDataByDatum: (datum: any, hasDynamicFilter: boolean, originalDatum: Datum) => {
4
33
  __row_index: any;
5
34
  } | null;
@@ -1,16 +1,53 @@
1
- import { isArray } from "remeda";
1
+ import { isArray, isNullish } from "remeda";
2
+ import tinycolor2 from "tinycolor2";
2
3
  import { InnerRowIndex } from "../../../../../dataReshape/index.js";
3
4
  const tableStyleMap = {
4
5
  backgroundColor: 'bgColor',
5
6
  textColor: 'color',
6
7
  textFontSize: 'fontSize',
7
8
  borderColor: 'borderColor',
8
- borderLineWidth: 'borderLineWidth'
9
+ borderLineWidth: 'borderLineWidth',
10
+ barPositiveColor: 'barPositiveColor',
11
+ barNegativeColor: 'barNegativeColor'
12
+ };
13
+ const interpolateColor = (value, minValue, maxValue, minColor, maxColor)=>{
14
+ const startColor = tinycolor2(minColor).toRgb();
15
+ const endColor = tinycolor2(maxColor).toRgb();
16
+ const normalized = (value - minValue) / (maxValue - minValue);
17
+ const t = Math.max(0, Math.min(1, normalized));
18
+ const r = Math.round(startColor.r + (endColor.r - startColor.r) * t);
19
+ const g = Math.round(startColor.g + (endColor.g - startColor.g) * t);
20
+ const b = Math.round(startColor.b + (endColor.b - startColor.b) * t);
21
+ return `rgb(${r}, ${g}, ${b})`;
9
22
  };
10
23
  const pickBodyCellStyle = (bodyCellStyle)=>Object.keys(tableStyleMap).reduce((acc, key)=>{
11
24
  if (key in bodyCellStyle) acc[tableStyleMap[key]] = bodyCellStyle[key];
12
25
  return acc;
13
26
  }, {});
27
+ const getColumnMinMax = (allData, field)=>{
28
+ let min = 1 / 0;
29
+ let max = -1 / 0;
30
+ for (const datum of allData){
31
+ const value = Number(datum[field]);
32
+ if (!Number.isNaN(value)) {
33
+ min = Math.min(min, value);
34
+ max = Math.max(max, value);
35
+ }
36
+ }
37
+ return {
38
+ min: min === 1 / 0 ? 0 : min,
39
+ max: max === -1 / 0 ? 0 : max
40
+ };
41
+ };
42
+ const applyColorScale = (value, scale)=>{
43
+ if (!scale) return;
44
+ const numValue = Number(value);
45
+ if (Number.isNaN(numValue) || isNullish(value)) return;
46
+ const minValue = scale.minValue;
47
+ const maxValue = scale.maxValue;
48
+ if (minValue === maxValue) return scale.minColor;
49
+ return interpolateColor(numValue, minValue, maxValue, scale.minColor, scale.maxColor);
50
+ };
14
51
  const getCellOriginalDataByDatum = (datum, hasDynamicFilter, originalDatum)=>{
15
52
  const tableInstance = datum?.table;
16
53
  let originRowData = tableInstance && hasDynamicFilter ? tableInstance?.getCellOriginRecord(datum?.col, datum?.row) : null;
@@ -20,6 +57,6 @@ const getCellOriginalDataByDatum = (datum, hasDynamicFilter, originalDatum)=>{
20
57
  [InnerRowIndex]: originRowData?.[InnerRowIndex]
21
58
  } : null;
22
59
  };
23
- export { getCellOriginalDataByDatum, pickBodyCellStyle };
60
+ export { applyColorScale, getCellOriginalDataByDatum, getColumnMinMax, interpolateColor, pickBodyCellStyle };
24
61
 
25
62
  //# sourceMappingURL=common.js.map
@@ -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 } from 'remeda'\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}\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\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","pickBodyCellStyle","bodyCellStyle","Object","acc","key","getCellOriginalDataByDatum","datum","hasDynamicFilter","originalDatum","tableInstance","originRowData","isArray","InnerRowIndex"],"mappings":";;AAIA,MAAMA,gBAAgB;IACpB,iBAAiB;IACjB,WAAW;IACX,cAAc;IACd,aAAa;IACb,iBAAiB;AACnB;AAEO,MAAMC,oBAAoB,CAACC,gBACxBC,OAAO,IAAI,CAACH,eAAqD,MAAM,CAAsB,CAACI,KAAKC;QACzG,IAAIA,OAAOH,eACTE,GAAG,CAACJ,aAAa,CAACK,IAAI,CAAC,GAAGH,aAAa,CAACG,IAAI;QAG9C,OAAOD;IACT,GAAG,CAAC;AAGC,MAAME,6BAA6B,CAACC,OAAYC,kBAA2BC;IAChF,MAAMC,gBAAgBH,OAAO;IAC7B,IAAII,gBACFD,iBAAiBF,mBAAmBE,eAAe,oBAAoBH,OAAO,KAAKA,OAAO,OAAO;IACnG,IAAII,iBAAiBC,QAAQD,gBAC3BA,gBAAgBA,aAAa,CAAC,EAAE;IAElC,OAAOA,gBACH;QACE,GAAGF,aAAa;QAChB,CAACI,cAAc,EAAEF,eAAe,CAACE,cAAc;IACjD,IACA;AACN"}
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[], field: string): { min: number; max: number } => {\n let min = Infinity\n let max = -Infinity\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 }\n }\n\n return {\n min: min === Infinity ? 0 : min,\n max: max === -Infinity ? 0 : max,\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","min","Infinity","max","datum","Number","applyColorScale","scale","numValue","isNullish","getCellOriginalDataByDatum","hasDynamicFilter","originalDatum","tableInstance","originRowData","isArray","InnerRowIndex"],"mappings":";;;AAKA,MAAMA,gBAAgB;IACpB,iBAAiB;IACjB,WAAW;IACX,cAAc;IACd,aAAa;IACb,iBAAiB;IACjB,kBAAkB;IAClB,kBAAkB;AACpB;AAWO,MAAMC,mBAAmB,CAC9BC,OACAC,UACAC,UACAC,UACAC;IAEA,MAAMC,aAAaC,WAAUH,UAAU,KAAK;IAC5C,MAAMI,WAAWD,WAAUF,UAAU,KAAK;IAG1C,MAAMI,aAAcR,AAAAA,CAAAA,QAAQC,QAAO,IAAMC,CAAAA,WAAWD,QAAO;IAC3D,MAAMQ,IAAIC,KAAK,GAAG,CAAC,GAAGA,KAAK,GAAG,CAAC,GAAGF;IAGlC,MAAMG,IAAID,KAAK,KAAK,CAACL,WAAW,CAAC,GAAIE,AAAAA,CAAAA,SAAS,CAAC,GAAGF,WAAW,CAAC,AAAD,IAAKI;IAClE,MAAMG,IAAIF,KAAK,KAAK,CAACL,WAAW,CAAC,GAAIE,AAAAA,CAAAA,SAAS,CAAC,GAAGF,WAAW,CAAC,AAAD,IAAKI;IAClE,MAAMI,IAAIH,KAAK,KAAK,CAACL,WAAW,CAAC,GAAIE,AAAAA,CAAAA,SAAS,CAAC,GAAGF,WAAW,CAAC,AAAD,IAAKI;IAElE,OAAO,CAAC,IAAI,EAAEE,EAAE,EAAE,EAAEC,EAAE,EAAE,EAAEC,EAAE,CAAC,CAAC;AAChC;AAKO,MAAMC,oBAAoB,CAACC,gBACxBC,OAAO,IAAI,CAAClB,eAAqD,MAAM,CAAsB,CAACmB,KAAKC;QACzG,IAAIA,OAAOH,eACTE,GAAG,CAACnB,aAAa,CAACoB,IAAI,CAAC,GAAGH,aAAa,CAACG,IAAI;QAG9C,OAAOD;IACT,GAAG,CAAC;AAMC,MAAME,kBAAkB,CAACC,SAAkBC;IAChD,IAAIC,MAAMC;IACV,IAAIC,MAAM,CAACD;IAEX,KAAK,MAAME,SAASL,QAAS;QAC3B,MAAMpB,QAAQ0B,OAAOD,KAAK,CAACJ,MAAM;QACjC,IAAI,CAACK,OAAO,KAAK,CAAC1B,QAAQ;YACxBsB,MAAMZ,KAAK,GAAG,CAACY,KAAKtB;YACpBwB,MAAMd,KAAK,GAAG,CAACc,KAAKxB;QACtB;IACF;IAEA,OAAO;QACL,KAAKsB,QAAQC,QAAW,IAAID;QAC5B,KAAKE,QAAQ,CAACD,QAAW,IAAIC;IAC/B;AACF;AAKO,MAAMG,kBAAkB,CAC7B3B,OACA4B;IAEA,IAAI,CAACA,OAAO;IAEZ,MAAMC,WAAWH,OAAO1B;IACxB,IAAI0B,OAAO,KAAK,CAACG,aAAaC,UAAU9B,QAAQ;IAEhD,MAAMC,WAAW2B,MAAM,QAAQ;IAC/B,MAAM1B,WAAW0B,MAAM,QAAQ;IAE/B,IAAI3B,aAAaC,UACf,OAAO0B,MAAM,QAAQ;IAGvB,OAAO7B,iBAAiB8B,UAAU5B,UAAUC,UAAU0B,MAAM,QAAQ,EAAEA,MAAM,QAAQ;AACtF;AAEO,MAAMG,6BAA6B,CAACN,OAAYO,kBAA2BC;IAChF,MAAMC,gBAAgBT,OAAO;IAC7B,IAAIU,gBACFD,iBAAiBF,mBAAmBE,eAAe,oBAAoBT,OAAO,KAAKA,OAAO,OAAO;IACnG,IAAIU,iBAAiBC,QAAQD,gBAC3BA,gBAAgBA,aAAa,CAAC,EAAE;IAElC,OAAOA,gBACH;QACE,GAAGF,aAAa;QAChB,CAACI,cAAc,EAAEF,eAAe,CAACE,cAAc;IACjD,IACA;AACN"}
@@ -1,21 +1,38 @@
1
1
  import { array } from "@visactor/vutils";
2
2
  import { isString } from "remeda";
3
- import { selector, selectorWithDynamicFilter } from "../../../../../dataSelector/selector.js";
4
- import { getCellOriginalDataByDatum, pickBodyCellStyle } from "./common.js";
3
+ import { matchesFieldSelector, selector, selectorWithDynamicFilter } from "../../../../../dataSelector/selector.js";
4
+ import { applyColorScale, getCellOriginalDataByDatum, getColumnMinMax, pickBodyCellStyle } from "./common.js";
5
5
  const pivotTableBodyCell = (spec, context)=>{
6
6
  const { advancedVSeed } = context;
7
- const { cellStyle } = advancedVSeed;
7
+ const { cellStyle, config, chartType } = advancedVSeed;
8
8
  const bodyCellStyle = cellStyle?.bodyCellStyle;
9
+ const themeConfig = config?.[chartType];
9
10
  if (!bodyCellStyle) return spec;
10
11
  const bodyCellStyleList = array(bodyCellStyle);
11
12
  const indicators = spec.indicators || [];
12
13
  const selectedPos = [];
13
14
  const hasDynamicFilter = bodyCellStyleList.some((style)=>!!style.dynamicFilter);
15
+ const allData = advancedVSeed.dataset || [];
14
16
  const newIndicators = indicators.map((ind)=>{
15
17
  const newInd = isString(ind) ? {
16
18
  indicatorKey: ind
17
19
  } : ind;
18
20
  const { indicatorKey } = newInd;
21
+ const progressBarStyle = bodyCellStyleList.filter((s)=>s.enableProgressBar && s?.selector && matchesFieldSelector(indicatorKey, s.selector)).pop();
22
+ const backgroundColorScale = bodyCellStyleList.find((s)=>s.enableBackgroundColorScale && s?.selector && matchesFieldSelector(indicatorKey, s.selector));
23
+ let columnMin;
24
+ let columnMax;
25
+ if (progressBarStyle || backgroundColorScale) {
26
+ const { min, max } = getColumnMinMax(allData, indicatorKey);
27
+ columnMin = min;
28
+ columnMax = max;
29
+ if (progressBarStyle) {
30
+ newInd.cellType = 'progressbar';
31
+ newInd.barType = 'negative';
32
+ newInd.min = progressBarStyle.barMin ?? columnMin;
33
+ newInd.max = progressBarStyle.barMax ?? columnMax;
34
+ }
35
+ }
19
36
  newInd.style = (datum)=>{
20
37
  const { dataValue, cellHeaderPaths } = datum;
21
38
  const headerPaths = [
@@ -37,9 +54,26 @@ const pivotTableBodyCell = (spec, context)=>{
37
54
  col: datum?.col,
38
55
  row: datum?.row
39
56
  });
57
+ const cellStyle = pickBodyCellStyle(style);
58
+ if (style.enableBackgroundColorScale) {
59
+ const scaledColor = applyColorScale(dataValue, {
60
+ minValue: columnMin,
61
+ maxValue: columnMax,
62
+ ...themeConfig.backgroundColorScale,
63
+ ...style.backgroundColorScale
64
+ });
65
+ if (scaledColor) cellStyle.bgColor = scaledColor;
66
+ }
67
+ if ('progressbar' === newInd.cellType) {
68
+ cellStyle.barHeight = themeConfig?.barHeight;
69
+ cellStyle.barMarkInBar = themeConfig?.barMarkInBar;
70
+ cellStyle.barMarkWidth = themeConfig?.barMarkWidth;
71
+ cellStyle.barPadding = themeConfig?.barPadding;
72
+ cellStyle.barRightToLeft = themeConfig?.barRightToLeft;
73
+ }
40
74
  return {
41
75
  ...result,
42
- ...pickBodyCellStyle(style)
76
+ ...cellStyle
43
77
  };
44
78
  }
45
79
  return 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 { selector, selectorWithDynamicFilter } from 'src/dataSelector/selector'\nimport type { BodyCellStyle, Datum, PivotTableSpecPipe } from 'src/types'\nimport { getCellOriginalDataByDatum, pickBodyCellStyle } from './common'\n\nexport const pivotTableBodyCell: PivotTableSpecPipe = (spec, context) => {\n const { advancedVSeed } = context\n const { cellStyle } = advancedVSeed\n const bodyCellStyle = cellStyle?.bodyCellStyle\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\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 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 // 说明重复进入了,清空历史\n selectedPos.length = 0\n }\n selectedPos.push({\n col: datum?.col,\n row: datum?.row,\n })\n return {\n ...result,\n ...pickBodyCellStyle(style),\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","bodyCellStyle","bodyCellStyleList","array","indicators","selectedPos","hasDynamicFilter","style","newIndicators","ind","newInd","isString","indicatorKey","datum","dataValue","cellHeaderPaths","headerPaths","originalDatum","path","currentCellData","getCellOriginalDataByDatum","mergedStyle","result","shouldApply","selectorWithDynamicFilter","selector","pickBodyCellStyle"],"mappings":";;;;AAOO,MAAMA,qBAAyC,CAACC,MAAMC;IAC3D,MAAM,EAAEC,aAAa,EAAE,GAAGD;IAC1B,MAAM,EAAEE,SAAS,EAAE,GAAGD;IACtB,MAAME,gBAAgBD,WAAW;IAEjC,IAAI,CAACC,eACH,OAAOJ;IAET,MAAMK,oBAAoBC,MAAMF;IAChC,MAAMG,aAAcP,KAAsC,UAAU,IAAI,EAAE;IAC1E,MAAMQ,cAA8C,EAAE;IACtD,MAAMC,mBAAmBJ,kBAAkB,IAAI,CAAC,CAACK,QAAU,CAAC,CAACA,MAAM,aAAa;IAEhF,MAAMC,gBAAgBJ,WAAW,GAAG,CAAC,CAACK;QACpC,MAAMC,SAASC,SAASF,OACnB;YACC,cAAcA;QAChB,IACAA;QAEJ,MAAM,EAAEG,YAAY,EAAE,GAAGF;QAEzBA,OAAO,KAAK,GAAG,CAACG;YACd,MAAM,EAAEC,SAAS,EAAEC,eAAe,EAAE,GAAGF;YACvC,MAAMG,cAAc;mBAAID,gBAAgB,cAAc;mBAAKA,gBAAgB,cAAc;aAAC;YAE1F,MAAME,gBAAuB;gBAC3B,CAACL,aAAa,EAAEE;YAClB;YAEAE,YAAY,OAAO,CAAC,CAACE;gBACnB,IAAIA,KAAK,YAAY,EACnBD,aAAa,CAACC,KAAK,YAAY,CAAC,GAAGA,KAAK,KAAK;YAEjD;YAEA,MAAMC,kBAAkBC,2BAA2BP,OAAOP,kBAAkBW;YAE5E,MAAMI,cAAcnB,kBAAkB,MAAM,CAAsB,CAACoB,QAAQf;gBACzE,MAAMgB,cAAchB,MAAM,aAAa,GACnCiB,0BAA0BL,mBAAmBF,eAAeV,MAAM,aAAa,EAAEA,MAAM,QAAQ,IAC/FkB,SAASR,eAAeV,MAAM,QAAQ;gBAC1C,IAAIgB,aAAa;oBACf,IAAIlB,YAAY,MAAM,IAAIA,WAAW,CAAC,EAAE,CAAC,GAAG,KAAKQ,OAAO,OAAOR,WAAW,CAAC,EAAE,CAAC,GAAG,KAAKQ,OAAO,KAE3FR,YAAY,MAAM,GAAG;oBAEvBA,YAAY,IAAI,CAAC;wBACf,KAAKQ,OAAO;wBACZ,KAAKA,OAAO;oBACd;oBACA,OAAO;wBACL,GAAGS,MAAM;wBACT,GAAGI,kBAAkBnB,MAAM;oBAC7B;gBACF;gBAEA,OAAOe;YACT,GAAG,CAAC;YAEJ,OAAOD;QACT;QACA,OAAOX;IACT;IACA,OAAO;QACL,GAAGb,IAAI;QACP,eAAe;YACb,GAAKA,MAAc,iBAAiB,CAAC,CAAC;YACtCQ;QACF;QACA,YAAYG;IACd;AACF"}
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","cellHeaderPaths","headerPaths","originalDatum","path","currentCellData","getCellOriginalDataByDatum","mergedStyle","result","shouldApply","selectorWithDynamicFilter","selector","pickBodyCellStyle","scaledColor","applyColorScale"],"mappings":"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"}
@@ -1,42 +1,82 @@
1
1
  import { array } from "@visactor/vutils";
2
2
  import { isNullish, isNumber, isPlainObject, isString } from "remeda";
3
- import { selector as selector_js_selector, selectorWithDynamicFilter } from "../../../../../dataSelector/selector.js";
4
- import { getCellOriginalDataByDatum, pickBodyCellStyle } from "./common.js";
3
+ import { isFieldSelector, matchesFieldSelector, selector, selectorWithDynamicFilter } from "../../../../../dataSelector/selector.js";
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
7
  const { advancedVSeed } = context;
8
- const { cellStyle } = advancedVSeed;
8
+ const { cellStyle, config, chartType } = advancedVSeed;
9
9
  const bodyCellStyle = cellStyle?.bodyCellStyle;
10
+ const themeConfig = config?.[chartType];
10
11
  if (!bodyCellStyle) return spec;
11
12
  const bodyCellStyleList = array(bodyCellStyle);
12
13
  const columns = spec.columns || [];
13
14
  const selectedPos = [];
15
+ const allData = advancedVSeed.dataset || [];
14
16
  const setStyleOfColumn = (col)=>{
15
17
  const field = col.field;
16
18
  const matchedStyles = bodyCellStyleList.filter((style)=>{
17
19
  if (style?.dynamicFilter) return style.dynamicFilter?.result?.success === true || !!style.dynamicFilter?.fallback;
18
20
  if (isNullish(style.selector)) return true;
19
21
  const selectors = array(style.selector);
20
- return selectors.some((selector)=>isPlainObject(selector) ? isNullish(selector.field) || selector.field === field : isNumber(selector) || isString(selector));
22
+ return selectors.some((sel)=>{
23
+ if (isFieldSelector(sel)) return matchesFieldSelector(field, sel);
24
+ if (isPlainObject(sel)) return isNullish(sel.field) || sel.field === field;
25
+ return isNumber(sel) || isString(sel);
26
+ });
21
27
  });
22
28
  if (!matchedStyles.length) return false;
23
29
  const hasDynamicFilter = matchedStyles.some((style)=>!!style.dynamicFilter);
30
+ const progressBarStyle = matchedStyles.filter((s)=>s.enableProgressBar && s?.selector && matchesFieldSelector(field, s.selector)).pop();
31
+ const backgroundColorScale = matchedStyles.find((s)=>s.enableBackgroundColorScale && s?.selector && matchesFieldSelector(field, s.selector));
32
+ let columnMin;
33
+ let columnMax;
34
+ if (progressBarStyle || backgroundColorScale) {
35
+ const { min, max } = getColumnMinMax(allData, field);
36
+ columnMin = min;
37
+ columnMax = max;
38
+ if (progressBarStyle) {
39
+ col.cellType = 'progressbar';
40
+ col.barType = 'negative';
41
+ col.min = progressBarStyle.barMin ?? columnMin;
42
+ col.max = progressBarStyle.barMin ?? columnMax;
43
+ }
44
+ }
24
45
  col.style = (datum)=>{
25
46
  const originalDatum = {
26
47
  [field]: datum.dataValue
27
48
  };
28
49
  const currentCellData = getCellOriginalDataByDatum(datum, hasDynamicFilter, originalDatum);
29
50
  const mergedStyle = matchedStyles.reduce((result, style)=>{
30
- const shouldApply = style.dynamicFilter ? selectorWithDynamicFilter(currentCellData || originalDatum, style.dynamicFilter, style.selector) : selector_js_selector(originalDatum, style.selector);
51
+ const shouldApply = style.dynamicFilter ? selectorWithDynamicFilter(currentCellData || originalDatum, style.dynamicFilter, style.selector) : selector(originalDatum, style.selector);
31
52
  if (shouldApply) {
32
53
  if (selectedPos.length && selectedPos[0].col === datum?.col && selectedPos[0].row === datum?.row) selectedPos.length = 0;
33
54
  selectedPos.push({
34
55
  col: datum?.col,
35
56
  row: datum?.row
36
57
  });
58
+ let cellStyle = pickBodyCellStyle(style);
59
+ if (style.enableBackgroundColorScale) {
60
+ const scaledColor = applyColorScale(datum.dataValue, {
61
+ minValue: columnMin,
62
+ maxValue: columnMax,
63
+ ...themeConfig.backgroundColorScale,
64
+ ...style?.backgroundColorScale
65
+ });
66
+ if (scaledColor) cellStyle.bgColor = scaledColor;
67
+ }
68
+ if ('progressbar' === col.cellType) cellStyle = {
69
+ ...cellStyle,
70
+ barHeight: themeConfig?.barHeight,
71
+ barMarkInBar: themeConfig?.barMarkInBar,
72
+ barMarkWidth: themeConfig?.barMarkWidth,
73
+ barPadding: themeConfig?.barPadding,
74
+ barRightToLeft: themeConfig?.barRightToLeft,
75
+ barAxisColor: themeConfig?.barAxisColor
76
+ };
37
77
  return {
38
78
  ...result,
39
- ...pickBodyCellStyle(style)
79
+ ...cellStyle
40
80
  };
41
81
  }
42
82
  return result;
@@ -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 } from '@visactor/vtable'\nimport { array } from '@visactor/vutils'\nimport { isNullish, isNumber, isPlainObject, isString } from 'remeda'\nimport { selector, selectorWithDynamicFilter } from 'src/dataSelector/selector'\nimport type { BodyCellStyle, ListTableSpecPipe } from 'src/types'\nimport type { MeasureSelector, Selectors } from 'src/types/dataSelector'\nimport { getCellOriginalDataByDatum, pickBodyCellStyle } from './common'\nimport { preorderTraverse } from 'src/pipeline/utils/tree/traverse'\n\nexport const tableBodyCell: ListTableSpecPipe = (spec, context) => {\n const { advancedVSeed } = context\n const { cellStyle } = advancedVSeed\n const bodyCellStyle = cellStyle?.bodyCellStyle\n\n if (!bodyCellStyle) {\n return spec as ListTableConstructorOptions\n }\n const bodyCellStyleList = array(bodyCellStyle) as BodyCellStyle[]\n const columns = (spec as ListTableConstructorOptions).columns || []\n const selectedPos: { col: number; row: number }[] = []\n const setStyleOfColumn = (col: ColumnDefine) => {\n const field = col.field as string\n const matchedStyles = bodyCellStyleList.filter((style) => {\n if (style?.dynamicFilter) {\n return style.dynamicFilter?.result?.success === true || !!style.dynamicFilter?.fallback\n }\n if (isNullish(style.selector)) {\n return true\n }\n const selectors = array(style.selector) as Selectors\n\n return selectors.some((selector) => {\n return isPlainObject(selector)\n ? isNullish(selector.field) || (selector as MeasureSelector).field === field\n : isNumber(selector) || isString(selector)\n })\n })\n\n if (!matchedStyles.length) {\n return false\n }\n\n const hasDynamicFilter = matchedStyles.some((style) => !!style.dynamicFilter)\n\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 return {\n ...result,\n ...pickBodyCellStyle(style),\n }\n }\n\n return result\n }, {})\n\n return mergedStyle\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","cellStyle","bodyCellStyle","bodyCellStyleList","array","columns","selectedPos","setStyleOfColumn","col","field","matchedStyles","style","isNullish","selectors","selector","isPlainObject","isNumber","isString","hasDynamicFilter","datum","originalDatum","currentCellData","getCellOriginalDataByDatum","mergedStyle","result","shouldApply","selectorWithDynamicFilter","pickBodyCellStyle","preorderTraverse"],"mappings":";;;;;AASO,MAAMA,gBAAmC,CAACC,MAAMC;IACrD,MAAM,EAAEC,aAAa,EAAE,GAAGD;IAC1B,MAAM,EAAEE,SAAS,EAAE,GAAGD;IACtB,MAAME,gBAAgBD,WAAW;IAEjC,IAAI,CAACC,eACH,OAAOJ;IAET,MAAMK,oBAAoBC,MAAMF;IAChC,MAAMG,UAAWP,KAAqC,OAAO,IAAI,EAAE;IACnE,MAAMQ,cAA8C,EAAE;IACtD,MAAMC,mBAAmB,CAACC;QACxB,MAAMC,QAAQD,IAAI,KAAK;QACvB,MAAME,gBAAgBP,kBAAkB,MAAM,CAAC,CAACQ;YAC9C,IAAIA,OAAO,eACT,OAAOA,MAAM,aAAa,EAAE,QAAQ,YAAY,QAAQ,CAAC,CAACA,MAAM,aAAa,EAAE;YAEjF,IAAIC,UAAUD,MAAM,QAAQ,GAC1B,OAAO;YAET,MAAME,YAAYT,MAAMO,MAAM,QAAQ;YAEtC,OAAOE,UAAU,IAAI,CAAC,CAACC,WACdC,cAAcD,YACjBF,UAAUE,SAAS,KAAK,KAAMA,SAA6B,KAAK,KAAKL,QACrEO,SAASF,aAAaG,SAASH;QAEvC;QAEA,IAAI,CAACJ,cAAc,MAAM,EACvB,OAAO;QAGT,MAAMQ,mBAAmBR,cAAc,IAAI,CAAC,CAACC,QAAU,CAAC,CAACA,MAAM,aAAa;QAE5EH,IAAI,KAAK,GAAG,CAACW;YACX,MAAMC,gBAAgB;gBACpB,CAACX,MAAM,EAAEU,MAAM,SAAS;YAC1B;YACA,MAAME,kBAAkBC,2BAA2BH,OAAOD,kBAAkBE;YAE5E,MAAMG,cAAcb,cAAc,MAAM,CAAsB,CAACc,QAAQb;gBACrE,MAAMc,cAAcd,MAAM,aAAa,GACnCe,0BAA0BL,mBAAmBD,eAAeT,MAAM,aAAa,EAAEA,MAAM,QAAQ,IAC/FG,qBAASM,eAAeT,MAAM,QAAQ;gBAE1C,IAAIc,aAAa;oBACf,IAAInB,YAAY,MAAM,IAAIA,WAAW,CAAC,EAAE,CAAC,GAAG,KAAKa,OAAO,OAAOb,WAAW,CAAC,EAAE,CAAC,GAAG,KAAKa,OAAO,KAE3Fb,YAAY,MAAM,GAAG;oBAEvBA,YAAY,IAAI,CAAC;wBACf,KAAKa,OAAO;wBACZ,KAAKA,OAAO;oBACd;oBACA,OAAO;wBACL,GAAGK,MAAM;wBACT,GAAGG,kBAAkBhB,MAAM;oBAC7B;gBACF;gBAEA,OAAOa;YACT,GAAG,CAAC;YAEJ,OAAOD;QACT;QACA,OAAO;IACT;IAEAK,iBAA0CvB,SAASE,kBAAkB;IACnET,KAAa,aAAa,GAAG;QAC7B,GAAKA,KAAa,aAAa,IAAI,CAAC,CAAC;QACrCQ;IACF;IAEA,OAAOR;AACT"}
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.barMin ?? 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","cellStyle","config","chartType","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":";;;;;AASO,MAAMA,gBAAmC,CAACC,MAAMC;IACrD,MAAM,EAAEC,aAAa,EAAE,GAAGD;IAC1B,MAAM,EAAEE,SAAS,EAAEC,MAAM,EAAEC,SAAS,EAAE,GAAGH;IACzC,MAAMI,gBAAgBH,WAAW;IACjC,MAAMI,cAAcH,QAAQ,CAACC,UAAU;IAEvC,IAAI,CAACC,eACH,OAAON;IAGT,MAAMQ,oBAAoBC,MAAMH;IAChC,MAAMI,UAAWV,KAAqC,OAAO,IAAI,EAAE;IACnE,MAAMW,cAA8C,EAAE;IACtD,MAAMC,UAAUV,cAAc,OAAO,IAAI,EAAE;IAE3C,MAAMW,mBAAmB,CAACC;QACxB,MAAMC,QAAQD,IAAI,KAAK;QAGvB,MAAME,gBAAgBR,kBAAkB,MAAM,CAAC,CAACS;YAE9C,IAAIA,OAAO,eACT,OAAOA,MAAM,aAAa,EAAE,QAAQ,YAAY,QAAQ,CAAC,CAACA,MAAM,aAAa,EAAE;YAIjF,IAAIC,UAAUD,MAAM,QAAQ,GAC1B,OAAO;YAGT,MAAME,YAAYV,MAAMQ,MAAM,QAAQ;YACtC,OAAOE,UAAU,IAAI,CAAC,CAACC;gBAErB,IAAIC,gBAAgBD,MAClB,OAAOE,qBAAqBP,OAAOK;gBAIrC,IAAIG,cAAcH,MAChB,OAAOF,UAAUE,IAAI,KAAK,KAAMA,IAAwB,KAAK,KAAKL;gBAIpE,OAAOS,SAASJ,QAAQK,SAASL;YACnC;QACF;QAEA,IAAI,CAACJ,cAAc,MAAM,EACvB,OAAO;QAGT,MAAMU,mBAAmBV,cAAc,IAAI,CAAC,CAACC,QAAU,CAAC,CAACA,MAAM,aAAa;QAG5E,MAAMU,mBAAmBX,cACtB,MAAM,CAAC,CAACY,IAAMA,EAAE,iBAAiB,IAAIA,GAAG,YAAYN,qBAAqBP,OAAOa,EAAE,QAAQ,GAC1F,GAAG;QACN,MAAMC,uBAAuBb,cAAc,IAAI,CAC7C,CAACY,IAAMA,EAAE,0BAA0B,IAAIA,GAAG,YAAYN,qBAAqBP,OAAOa,EAAE,QAAQ;QAE9F,IAAIE;QACJ,IAAIC;QACJ,IAAIJ,oBAAoBE,sBAAsB;YAC5C,MAAM,EAAEG,GAAG,EAAEC,GAAG,EAAE,GAAGC,gBAAgBtB,SAASG;YAC9Ce,YAAYE;YACZD,YAAYE;YACZ,IAAIN,kBAAkB;gBACpBb,IAAI,QAAQ,GAAG;gBACbA,IAAgC,OAAO,GAAG;gBAC1CA,IAAgC,GAAG,GAAGa,iBAAiB,MAAM,IAAIG;gBACjEhB,IAAgC,GAAG,GAAGa,iBAAiB,MAAM,IAAII;YACrE;QACF;QAGAjB,IAAI,KAAK,GAAG,CAACqB;YACX,MAAMC,gBAAgB;gBACpB,CAACrB,MAAM,EAAEoB,MAAM,SAAS;YAC1B;YACA,MAAME,kBAAkBC,2BAA2BH,OAAOT,kBAAkBU;YAE5E,MAAMG,cAAcvB,cAAc,MAAM,CAAsB,CAACwB,QAAQvB;gBACrE,MAAMwB,cAAcxB,MAAM,aAAa,GACnCyB,0BAA0BL,mBAAmBD,eAAenB,MAAM,aAAa,EAAEA,MAAM,QAAQ,IAC/F0B,SAASP,eAAenB,MAAM,QAAQ;gBAE1C,IAAIwB,aAAa;oBACf,IAAI9B,YAAY,MAAM,IAAIA,WAAW,CAAC,EAAE,CAAC,GAAG,KAAKwB,OAAO,OAAOxB,WAAW,CAAC,EAAE,CAAC,GAAG,KAAKwB,OAAO,KAE3FxB,YAAY,MAAM,GAAG;oBAEvBA,YAAY,IAAI,CAAC;wBACf,KAAKwB,OAAO;wBACZ,KAAKA,OAAO;oBACd;oBAEA,IAAIhC,YAAYyC,kBAAkB3B;oBAGlC,IAAIA,MAAM,0BAA0B,EAAE;wBACpC,MAAM4B,cAAcC,gBAAgBX,MAAM,SAAS,EAAE;4BACnD,UAAUL;4BACV,UAAUC;4BACV,GAAGxB,YAAY,oBAAoB;4BACnC,GAAGU,OAAO,oBAAoB;wBAChC;wBACA,IAAI4B,aACF1C,UAAU,OAAO,GAAG0C;oBAExB;oBAEA,IAAI/B,AAAiB,kBAAjBA,IAAI,QAAQ,EACdX,YAAY;wBACV,GAAGA,SAAS;wBACZ,WAAWI,aAAa;wBACxB,cAAcA,aAAa;wBAC3B,cAAcA,aAAa;wBAC3B,YAAYA,aAAa;wBACzB,gBAAgBA,aAAa;wBAC7B,cAAcA,aAAa;oBAC7B;oBAGF,OAAO;wBACL,GAAGiC,MAAM;wBACT,GAAGrC,SAAS;oBACd;gBACF;gBAEA,OAAOqC;YACT,GAAG,CAAC;YAEJ,OAAOD;QACT;QAEA,OAAO;IACT;IAEAQ,iBAA0CrC,SAASG,kBAAkB;IACnEb,KAAa,aAAa,GAAG;QAC7B,GAAKA,KAAa,aAAa,IAAI,CAAC,CAAC;QACrCW;IACF;IAEA,OAAOX;AACT"}
@@ -1,5 +1,7 @@
1
1
  import { createFormatterByMeasure, isMeasure } from "../../../../utils/index.js";
2
2
  import { treeTreeToColumns } from "./utils.js";
3
+ import { isNullish } from "remeda";
4
+ import { isUndefined } from "@visactor/vutils";
3
5
  const measureTreeToColumns = (spec, context)=>{
4
6
  const { advancedVSeed } = context;
5
7
  const measureTree = advancedVSeed.measureTree;
@@ -27,6 +29,7 @@ const fieldFormat = (node)=>{
27
29
  return (datum)=>{
28
30
  const { id } = node;
29
31
  const value = datum[id];
32
+ if (isNullish(value) || isUndefined(value)) return value;
30
33
  return formatter(value);
31
34
  };
32
35
  };
@@ -1 +1 @@
1
- {"version":3,"file":"pipeline/spec/table/pipes/columns/measuresToColumns.js","sources":["webpack://@visactor/vseed/./src/pipeline/spec/table/pipes/columns/measuresToColumns.ts"],"sourcesContent":["import type { ListTableConstructorOptions } from '@visactor/vtable'\nimport { createFormatterByMeasure, isMeasure } from 'src/pipeline/utils'\nimport type { MeasureGroup, Measure, MeasureTree, ListTableSpecPipe, Datum } from 'src/types'\nimport { treeTreeToColumns } from './utils'\n\nexport const measureTreeToColumns: ListTableSpecPipe = (spec, context) => {\n const { advancedVSeed } = context\n const measureTree = (advancedVSeed as unknown as { measureTree: MeasureTree }).measureTree\n const result = { ...spec } as ListTableConstructorOptions\n\n const eachNode = (node: Measure | MeasureGroup) => {\n if (isMeasure(node)) {\n return {\n width: 'auto',\n fieldFormat: fieldFormat(node),\n }\n }\n\n return {}\n }\n const columns = treeTreeToColumns<Measure, MeasureGroup>(measureTree, eachNode)\n return {\n ...result,\n columns: [...(result.columns || []), ...columns] as ListTableConstructorOptions['columns'],\n }\n}\n\nconst fieldFormat = (node: Measure) => {\n const formatter = createFormatterByMeasure(node)\n\n return (datum: Datum) => {\n const { id } = node\n const value = datum[id] as number | string | undefined\n return formatter(value)\n }\n}\n"],"names":["measureTreeToColumns","spec","context","advancedVSeed","measureTree","result","eachNode","node","isMeasure","fieldFormat","columns","treeTreeToColumns","formatter","createFormatterByMeasure","datum","id","value"],"mappings":";;AAKO,MAAMA,uBAA0C,CAACC,MAAMC;IAC5D,MAAM,EAAEC,aAAa,EAAE,GAAGD;IAC1B,MAAME,cAAeD,cAA0D,WAAW;IAC1F,MAAME,SAAS;QAAE,GAAGJ,IAAI;IAAC;IAEzB,MAAMK,WAAW,CAACC;QAChB,IAAIC,UAAUD,OACZ,OAAO;YACL,OAAO;YACP,aAAaE,YAAYF;QAC3B;QAGF,OAAO,CAAC;IACV;IACA,MAAMG,UAAUC,kBAAyCP,aAAaE;IACtE,OAAO;QACL,GAAGD,MAAM;QACT,SAAS;eAAKA,OAAO,OAAO,IAAI,EAAE;eAAMK;SAAQ;IAClD;AACF;AAEA,MAAMD,cAAc,CAACF;IACnB,MAAMK,YAAYC,yBAAyBN;IAE3C,OAAO,CAACO;QACN,MAAM,EAAEC,EAAE,EAAE,GAAGR;QACf,MAAMS,QAAQF,KAAK,CAACC,GAAG;QACvB,OAAOH,UAAUI;IACnB;AACF"}
1
+ {"version":3,"file":"pipeline/spec/table/pipes/columns/measuresToColumns.js","sources":["webpack://@visactor/vseed/./src/pipeline/spec/table/pipes/columns/measuresToColumns.ts"],"sourcesContent":["import type { ListTableConstructorOptions } from '@visactor/vtable'\nimport { createFormatterByMeasure, isMeasure } from 'src/pipeline/utils'\nimport type { MeasureGroup, Measure, MeasureTree, ListTableSpecPipe, Datum } from 'src/types'\nimport { treeTreeToColumns } from './utils'\nimport { isNullish } from 'remeda'\nimport { isUndefined } from '@visactor/vutils'\n\nexport const measureTreeToColumns: ListTableSpecPipe = (spec, context) => {\n const { advancedVSeed } = context\n const measureTree = (advancedVSeed as unknown as { measureTree: MeasureTree }).measureTree\n const result = { ...spec } as ListTableConstructorOptions\n\n const eachNode = (node: Measure | MeasureGroup) => {\n if (isMeasure(node)) {\n return {\n width: 'auto',\n fieldFormat: fieldFormat(node),\n }\n }\n\n return {}\n }\n const columns = treeTreeToColumns<Measure, MeasureGroup>(measureTree, eachNode)\n return {\n ...result,\n columns: [...(result.columns || []), ...columns] as ListTableConstructorOptions['columns'],\n }\n}\n\nconst fieldFormat = (node: Measure) => {\n const formatter = createFormatterByMeasure(node)\n\n return (datum: Datum) => {\n const { id } = node\n const value = datum[id] as number | string | undefined\n if (isNullish(value) || isUndefined(value)) {\n return value\n }\n return formatter(value)\n }\n}\n"],"names":["measureTreeToColumns","spec","context","advancedVSeed","measureTree","result","eachNode","node","isMeasure","fieldFormat","columns","treeTreeToColumns","formatter","createFormatterByMeasure","datum","id","value","isNullish","isUndefined"],"mappings":";;;;AAOO,MAAMA,uBAA0C,CAACC,MAAMC;IAC5D,MAAM,EAAEC,aAAa,EAAE,GAAGD;IAC1B,MAAME,cAAeD,cAA0D,WAAW;IAC1F,MAAME,SAAS;QAAE,GAAGJ,IAAI;IAAC;IAEzB,MAAMK,WAAW,CAACC;QAChB,IAAIC,UAAUD,OACZ,OAAO;YACL,OAAO;YACP,aAAaE,YAAYF;QAC3B;QAGF,OAAO,CAAC;IACV;IACA,MAAMG,UAAUC,kBAAyCP,aAAaE;IACtE,OAAO;QACL,GAAGD,MAAM;QACT,SAAS;eAAKA,OAAO,OAAO,IAAI,EAAE;eAAMK;SAAQ;IAClD;AACF;AAEA,MAAMD,cAAc,CAACF;IACnB,MAAMK,YAAYC,yBAAyBN;IAE3C,OAAO,CAACO;QACN,MAAM,EAAEC,EAAE,EAAE,GAAGR;QACf,MAAMS,QAAQF,KAAK,CAACC,GAAG;QACvB,IAAIE,UAAUD,UAAUE,YAAYF,QAClC,OAAOA;QAET,OAAOJ,UAAUI;IACnB;AACF"}