DevExtreme Vue PivotGrid 完整使用指南

DevExtreme Vue PivotGrid 完整使用指南

适用场景:Vue 3 + DevExtreme PivotGrid,用于 ERP / 零售 / 销售 / 库存 / 毛利 / 指标分析等多维数据透视分析。


1. PivotGrid 是什么

PivotGrid 是 DevExtreme 提供的数据透视表组件,用来对多维数据进行分组、汇总、筛选、排序、展开、导出和状态保存。

典型业务场景:

  • 按客户、门店、品牌、季节统计销售金额
  • 按月份、年份统计销售趋势
  • 按客户 + 月份分析销售金额、销售指标、毛利金额、毛利指标
  • 按商品分类、门店、渠道分析库存和销售
  • 类似 Excel 数据透视表的前端分析能力

2. 安装依赖

bash 复制代码
npm install devextreme devextreme-vue

如果需要 Excel 导出,通常还需要:

bash 复制代码
npm install exceljs file-saver

在项目入口或页面中引入样式:

js 复制代码
import 'devextreme/dist/css/dx.light.css';

3. 基础引入

vue 复制代码
<script setup>
import {
  DxPivotGrid,
  DxFieldPanel,
  DxFieldChooser,
  DxStateStoring,
  DxExport,
  DxTexts
} from 'devextreme-vue/pivot-grid';
</script>

4. 最小可用示例

vue 复制代码
<template>
  <DxPivotGrid
    :data-source="dataSource"
    :show-borders="true"
    :allow-sorting="true"
    :allow-filtering="true"
    :height="600"
  />
</template>

<script setup>
import { ref } from 'vue';
import { DxPivotGrid } from 'devextreme-vue/pivot-grid';

const dataSource = ref({
  fields: [
    {
      caption: '客户名称',
      dataField: 'khmc',
      area: 'row'
    },
    {
      caption: '月份',
      dataField: 'monthLabel',
      area: 'column'
    },
    {
      caption: '销售金额',
      dataField: 'saleAmount',
      dataType: 'number',
      area: 'data',
      summaryType: 'sum',
      format: {
        type: 'fixedPoint',
        precision: 2
      }
    }
  ],
  store: [
    {
      khmc: '直营1店',
      monthLabel: '1月',
      saleAmount: 1000
    },
    {
      khmc: '直营1店',
      monthLabel: '2月',
      saleAmount: 2000
    }
  ]
});
</script>

5. PivotGrid 核心结构

dataSource 通常由两部分组成:

js 复制代码
const dataSource = ref({
  fields: [],
  store: []
});
配置 说明
fields 字段定义,决定哪些字段放在行、列、数据、筛选区域
store 实际数据源,可以是数组,也可以是远程数据源
dataFieldArea 多个数据指标时,控制数据字段标题显示在行区还是列区

6. 四个核心区域 area

fields[].area 用来指定字段放在哪个区域。

area 含义 典型字段
row 行维度 客户、门店、商品、品牌、季节
column 列维度 年份、月份、日期、渠道
data 数据指标 销售金额、数量、毛利、指标
filter 筛选字段 区域、渠道、业务员、门店类型

示例:

js 复制代码
fields: [
  {
    caption: '客户名称',
    dataField: 'khmc',
    area: 'row'
  },
  {
    caption: '月份',
    dataField: 'monthLabel',
    area: 'column'
  },
  {
    caption: '销售金额',
    dataField: 'saleAmount',
    area: 'data',
    dataType: 'number',
    summaryType: 'sum'
  },
  {
    caption: '渠道',
    dataField: 'channelName',
    area: 'filter'
  }
]

7. fields 字段完整说明

7.1 基础属性

属性 类型 说明
caption string 字段显示名称
dataField string 绑定数据源中的字段名
dataType string 数据类型:stringnumberdate
area string 所属区域:rowcolumndatafilter
width number 字段宽度
visible boolean 是否可见
visibleIndex number 显示顺序
expanded boolean 是否默认展开

示例:

js 复制代码
{
  caption: '客户名称',
  width: 120,
  dataField: 'khmc',
  dataType: 'string',
  area: 'row',
  expanded: true
}

7.2 数据类型 dataType

dataType 说明
string 字符串维度
number 数字指标
date 日期字段

金额、数量、指标字段必须建议配置:

js 复制代码
{
  caption: '销售金额',
  dataField: 'saleAmount',
  dataType: 'number',
  area: 'data',
  summaryType: 'sum'
}

否则容易被当成 count 计数,显示为 1


7.3 汇总属性

主要用于 area: 'data' 的字段。

属性 说明
summaryType 汇总方式
format 格式化
summaryDisplayMode 汇总显示模式,例如占比、差异
calculateCustomSummary 自定义汇总逻辑
calculateSummaryValue 对汇总结果二次计算

summaryType 常用值:

说明
sum 求和
avg 平均值
min 最小值
max 最大值
count 计数
custom 自定义汇总

示例:

js 复制代码
{
  caption: '销售金额',
  dataField: 'saleAmount',
  dataType: 'number',
  area: 'data',
  summaryType: 'sum',
  format: {
    type: 'fixedPoint',
    precision: 2
  }
}

7.4 format 格式化

常用格式:

js 复制代码
format: {
  type: 'fixedPoint',
  precision: 2
}

常见类型:

type 说明
fixedPoint 固定小数位
percent 百分比
currency 货币
decimal 数字

示例:

js 复制代码
{
  caption: '毛利率',
  dataField: 'grossProfitRate',
  dataType: 'number',
  area: 'data',
  summaryType: 'avg',
  format: {
    type: 'percent',
    precision: 2
  }
}

7.5 排序属性

属性 说明
sortOrder 排序方向:ascdesc
allowSorting 是否允许排序
allowSortingBySummary 是否允许按汇总值排序
sortBySummaryField 按指定汇总字段排序
sortBySummaryPath 按指定路径下的汇总值排序
sortingMethod 自定义排序方法

月份排序示例:

js 复制代码
{
  caption: '月份',
  dataField: 'monthNum',
  area: 'column',
  sortOrder: 'asc',
  customizeText(cellInfo) {
    return cellInfo.value + '月';
  }
}

建议:不要直接用 1月2月10月 做排序字段,否则字符串排序容易出现 1月、10月、11月、2月 的问题。最好后端返回 monthNummonthLabel

推荐数据结构:

js 复制代码
{
  monthNum: 1,
  monthLabel: '1月'
}

7.6 筛选属性

属性 说明
filterValues 默认筛选值
filterType 筛选类型:includeexclude
allowFiltering 是否允许筛选

示例:

js 复制代码
{
  caption: '渠道',
  dataField: 'channelName',
  area: 'filter',
  filterValues: ['直营'],
  filterType: 'include'
}

7.7 分组属性

属性 说明
groupName 分组名称
groupIndex 分组顺序
groupInterval 分组间隔

日期按年、月分组:

js 复制代码
{
  caption: '年份',
  dataField: 'saleDate',
  dataType: 'date',
  area: 'column',
  groupName: 'saleDateGroup',
  groupInterval: 'year',
  groupIndex: 0
},
{
  caption: '月份',
  dataField: 'saleDate',
  dataType: 'date',
  area: 'column',
  groupName: 'saleDateGroup',
  groupInterval: 'month',
  groupIndex: 1
}

常见 groupInterval

类型 可用值
date yearquartermonthdaydayOfWeek
number 数字间隔,例如 1001000

7.8 自定义显示 customizeText

js 复制代码
{
  caption: '月份',
  dataField: 'monthNum',
  area: 'column',
  customizeText(cellInfo) {
    return cellInfo.value + '月';
  }
}

金额加单位:

js 复制代码
{
  caption: '销售金额',
  dataField: 'saleAmount',
  dataType: 'number',
  area: 'data',
  summaryType: 'sum',
  customizeText(cellInfo) {
    return cellInfo.valueText + ' 元';
  }
}

8. 多个 data 指标的正确配置

当有多个数据指标时,例如:

  • 销售金额
  • 销售指标
  • 毛利金额
  • 毛利指标

建议配置:

js 复制代码
dataFieldArea: 'column'

完整示例:

js 复制代码
const dataSource = ref({
  fields: [
    {
      caption: '客户名称',
      width: 120,
      dataField: 'khmc',
      area: 'row',
      expanded: true
    },
    {
      caption: '客户代码',
      width: 120,
      dataField: 'khdm',
      area: 'row',
      expanded: true
    },
    {
      caption: '月份',
      width: 120,
      dataField: 'monthLabel',
      area: 'column',
      expanded: true,
      sortOrder: 'asc'
    },
    {
      caption: '销售金额',
      width: 120,
      dataField: 'saleAmount',
      dataType: 'number',
      area: 'data',
      summaryType: 'sum',
      format: {
        type: 'fixedPoint',
        precision: 2
      }
    },
    {
      caption: '销售指标',
      width: 120,
      dataField: 'zbje',
      dataType: 'number',
      area: 'data',
      summaryType: 'sum',
      format: {
        type: 'fixedPoint',
        precision: 2
      }
    },
    {
      caption: '毛利金额',
      width: 120,
      dataField: 'mlje',
      dataType: 'number',
      area: 'data',
      summaryType: 'sum',
      format: {
        type: 'fixedPoint',
        precision: 2
      }
    },
    {
      caption: '毛利指标',
      width: 120,
      dataField: 'mlzbje',
      dataType: 'number',
      area: 'data',
      summaryType: 'sum',
      format: {
        type: 'fixedPoint',
        precision: 2
      }
    }
  ],
  dataFieldArea: 'column',
  store: []
});

显示结构:

text 复制代码
1月
  销售金额
  销售指标
  毛利金额
  毛利指标
2月
  销售金额
  销售指标
  毛利金额
  毛利指标

9. Vue 页面完整示例

vue 复制代码
<template>
  <DxPivotGrid
    ref="pivotGridRef"
    id="pivotgrid"
    :data-source="dataSource"
    :height="pivotGridHeight"
    :allow-sorting="true"
    :allow-sorting-by-summary="true"
    :allow-filtering="true"
    :show-borders="true"
    :show-column-grand-totals="true"
    :show-row-grand-totals="true"
    :show-row-totals="true"
    :show-column-totals="true"
    row-header-layout="standard"
    @exporting="handleExport"
  >
    <DxExport :enabled="true" />

    <DxStateStoring
      :enabled="true"
      type="localStorage"
      storage-key="retail-sale-pivotgrid-analysis-state-v1"
      :saving-timeout="300"
    />

    <DxFieldPanel
      :visible="true"
      :allow-field-dragging="true"
      :texts="{
        columnFieldArea: '将列字段拖到此处',
        dataFieldArea: '将数据字段拖到此处',
        filterFieldArea: '将筛选字段拖到此处',
        rowFieldArea: '将行字段拖到此处'
      }"
    />

    <DxTexts
      grand-total="总计"
      total="小计"
      no-data="暂无数据"
      show-field-chooser="显示字段选择器"
    />

    <DxFieldChooser
      :enabled="false"
      title="字段选择器"
    >
      <DxTexts
        all-fields="所有字段"
        column-fields="列字段"
        data-fields="数据字段"
        filter-fields="筛选字段"
        row-fields="行字段"
      />
    </DxFieldChooser>
  </DxPivotGrid>
</template>

<script setup>
import { ref } from 'vue';
import {
  DxPivotGrid,
  DxFieldPanel,
  DxFieldChooser,
  DxStateStoring,
  DxExport,
  DxTexts
} from 'devextreme-vue/pivot-grid';

const pivotGridRef = ref(null);
const pivotGridHeight = ref(700);

const dataSource = ref({
  fields: [
    {
      caption: '客户名称',
      width: 120,
      dataField: 'khmc',
      area: 'row',
      expanded: true
    },
    {
      caption: '客户代码',
      width: 120,
      dataField: 'khdm',
      area: 'row',
      expanded: true
    },
    {
      caption: '月份',
      width: 120,
      dataField: 'monthLabel',
      area: 'column',
      expanded: true,
      sortOrder: 'asc'
    },
    {
      caption: '销售金额',
      width: 120,
      dataField: 'saleAmount',
      dataType: 'number',
      area: 'data',
      summaryType: 'sum',
      format: {
        type: 'fixedPoint',
        precision: 2
      }
    },
    {
      caption: '销售指标',
      width: 120,
      dataField: 'zbje',
      dataType: 'number',
      area: 'data',
      summaryType: 'sum',
      format: {
        type: 'fixedPoint',
        precision: 2
      }
    },
    {
      caption: '毛利金额',
      width: 120,
      dataField: 'mlje',
      dataType: 'number',
      area: 'data',
      summaryType: 'sum',
      format: {
        type: 'fixedPoint',
        precision: 2
      }
    },
    {
      caption: '毛利指标',
      width: 120,
      dataField: 'mlzbje',
      dataType: 'number',
      area: 'data',
      summaryType: 'sum',
      format: {
        type: 'fixedPoint',
        precision: 2
      }
    }
  ],
  dataFieldArea: 'column',
  store: []
});

function loadData(res) {
  const rows = res.data.map(item => ({
    ...item,
    saleAmount: Number(item.saleAmount || 0),
    zbje: Number(item.zbje || 0),
    mlje: Number(item.mlje || 0),
    mlzbje: Number(item.mlzbje || 0)
  }));

  dataSource.value = {
    ...dataSource.value,
    store: rows
  };
}

function handleExport(e) {
  // Excel 导出逻辑见后文
}
</script>

10. 数据加载建议

10.1 推荐后端返回格式

json 复制代码
{
  "code": 200,
  "msg": "success",
  "data": [
    {
      "saleAmount": 1692710.0,
      "khmc": "联营客户1",
      "khdm": "LY001",
      "mlje": 0.0,
      "mlzbje": 0.0,
      "zbje": 0.0,
      "monthLabel": "1月"
    }
  ]
}

10.2 前端统一转数字

js 复制代码
const rows = result.data.map(item => ({
  ...item,
  saleAmount: Number(item.saleAmount || 0),
  zbje: Number(item.zbje || 0),
  mlje: Number(item.mlje || 0),
  mlzbje: Number(item.mlzbje || 0)
}));

dataSource.value = {
  ...dataSource.value,
  store: rows
};

不建议只写:

js 复制代码
dataSource.value.store = result.data;

在 Vue 响应式和 DevExtreme 组件刷新联动上,整体替换更稳。


11. StateStoring 状态保存

DxStateStoring 用来保存用户调整后的透视表状态,例如:

  • 字段拖拽位置
  • 排序
  • 筛选
  • 展开状态
  • 字段布局

示例:

vue 复制代码
<DxStateStoring
  :enabled="true"
  type="localStorage"
  storage-key="retail-sale-pivotgrid-analysis-state-v1"
  :saving-timeout="300"
/>

11.1 开发阶段建议关闭

字段配置还在调整时,建议:

vue 复制代码
<DxStateStoring :enabled="false" />

否则旧缓存会覆盖新的 fields 配置,导致新字段不显示。

11.2 清理缓存

如果 storage-key 是:

text 复制代码
retail-sale-pivotgrid-analysis-state

浏览器控制台执行:

js 复制代码
localStorage.removeItem('retail-sale-pivotgrid-analysis-state')

11.3 正式项目建议给 key 加版本号

text 复制代码
retail-sale-pivotgrid-analysis-state-v1
retail-sale-pivotgrid-analysis-state-v2
retail-sale-pivotgrid-analysis-state-v3

只要字段结构发生变化,就升级版本号,避免旧布局污染。


12. FieldPanel 字段面板

字段面板用于让用户拖拽字段。

vue 复制代码
<DxFieldPanel
  :visible="true"
  :allow-field-dragging="true"
  :texts="{
    columnFieldArea: '将列字段拖到此处',
    dataFieldArea: '将数据字段拖到此处',
    filterFieldArea: '将筛选字段拖到此处',
    rowFieldArea: '将行字段拖到此处'
  }"
/>
属性 说明
visible 是否显示字段面板
allowFieldDragging 是否允许拖拽字段
texts 区域提示文字

13. FieldChooser 字段选择器

字段选择器用于让用户选择哪些字段参与分析。

vue 复制代码
<DxFieldChooser
  :enabled="true"
  title="字段选择器"
>
  <DxTexts
    all-fields="所有字段"
    column-fields="列字段"
    data-fields="数据字段"
    filter-fields="筛选字段"
    row-fields="行字段"
  />
</DxFieldChooser>

如果不希望用户自由调整字段,可以关闭:

vue 复制代码
<DxFieldChooser :enabled="false" />

14. 合计与小计

常用配置:

vue 复制代码
<DxPivotGrid
  :show-column-grand-totals="true"
  :show-row-grand-totals="true"
  :show-row-totals="true"
  :show-column-totals="true"
/>
属性 说明
showColumnGrandTotals 显示列总计
showRowGrandTotals 显示行总计
showRowTotals 显示行小计
showColumnTotals 显示列小计

中文文本:

vue 复制代码
<DxTexts
  grand-total="总计"
  total="小计"
  no-data="暂无数据"
/>

15. Excel 导出

安装:

bash 复制代码
npm install exceljs file-saver

示例:

js 复制代码
import { Workbook } from 'exceljs';
import { saveAs } from 'file-saver';
import { exportPivotGrid } from 'devextreme/excel_exporter';

function handleExport(e) {
  const workbook = new Workbook();
  const worksheet = workbook.addWorksheet('销售透视表');

  exportPivotGrid({
    component: e.component,
    worksheet
  }).then(() => {
    workbook.xlsx.writeBuffer().then(buffer => {
      saveAs(
        new Blob([buffer], { type: 'application/octet-stream' }),
        '销售透视表.xlsx'
      );
    });
  });

  e.cancel = true;
}

组件配置:

vue 复制代码
<DxPivotGrid @exporting="handleExport">
  <DxExport :enabled="true" />
</DxPivotGrid>

16. 常见问题

16.1 为什么数据区显示 1?

原因:字段被当成 count 计数了。

错误配置:

js 复制代码
{
  caption: '销售金额',
  dataField: 'saleAmount',
  area: 'data'
}

正确配置:

js 复制代码
{
  caption: '销售金额',
  dataField: 'saleAmount',
  dataType: 'number',
  area: 'data',
  summaryType: 'sum'
}

16.2 为什么新加字段不显示?

常见原因:

  1. DxStateStoring 旧缓存覆盖
  2. 接口没有返回对应字段
  3. 字段名大小写不一致
  4. 字段值不是数字
  5. 多个 data 指标没有配置 dataFieldArea

处理方式:

js 复制代码
localStorage.removeItem('你的 storage-key')

或者临时关闭:

vue 复制代码
<DxStateStoring :enabled="false" />

16.3 为什么毛利金额不显示?

先看数据是否全是 0。

例如:

json 复制代码
{
  "mlje": 0.0
}

如果所有行都是 0,PivotGrid 即使显示也只有 0。可以临时造数据验证:

js 复制代码
const rows = result.data.map(item => ({
  ...item,
  mlje: 100,
  zbje: 200,
  mlzbje: 300
}));

如果这样能显示,说明组件没问题,是业务数据本身没有有效值。


16.4 为什么月份排序不对?

monthLabel: '10月' 会按字符串排序。

建议后端返回:

json 复制代码
{
  "monthNum": 10,
  "monthLabel": "10月"
}

字段配置:

js 复制代码
{
  caption: '月份',
  dataField: 'monthNum',
  area: 'column',
  sortOrder: 'asc',
  customizeText(cellInfo) {
    return cellInfo.value + '月';
  }
}

16.5 为什么字段拖动后刷新页面仍然是旧布局?

因为启用了 DxStateStoring

清理:

js 复制代码
localStorage.removeItem('retail-sale-pivotgrid-analysis-state-v1')

或者升级 key:

vue 复制代码
<DxStateStoring
  :enabled="true"
  type="localStorage"
  storage-key="retail-sale-pivotgrid-analysis-state-v2"
/>

17. ERP 销售分析推荐字段设计

17.1 后端返回字段

json 复制代码
{
  "statYear": 2026,
  "statMonth": 1,
  "monthLabel": "1月",
  "khdm": "SD001",
  "khmc": "直营1店",
  "saleAmount": 100000.00,
  "saleNum": 120,
  "zbje": 80000.00,
  "mlje": 20000.00,
  "mlzbje": 15000.00
}

17.2 推荐维度

类型 字段
行维度 客户、门店、品牌、商品分类、季节
列维度 年、月、季度
数据指标 销售金额、销售数量、销售指标、毛利金额、毛利指标、达成率
筛选字段 渠道、区域、业务员、客户类型

17.3 推荐指标

指标 计算方式
销售金额 sum(saleAmount)
销售数量 sum(saleNum)
销售指标 sum(zbje)
毛利金额 sum(mlje)
毛利指标 sum(mlzbje)
销售达成率 销售金额 / 销售指标
毛利达成率 毛利金额 / 毛利指标

18. 自定义指标:销售达成率

销售达成率不能简单 avg,应该按汇总结果计算:

js 复制代码
{
  caption: '销售达成率',
  dataType: 'number',
  area: 'data',
  calculateSummaryValue(summaryCell) {
    const saleAmount = summaryCell.value('销售金额') || 0;
    const targetAmount = summaryCell.value('销售指标') || 0;

    if (targetAmount === 0) {
      return 0;
    }

    return saleAmount / targetAmount;
  },
  format: {
    type: 'percent',
    precision: 2
  }
}

注意:summaryCell.value('销售金额') 里的名称要与对应 data 字段的 caption 一致。


19. 自定义汇总:平均单价

平均单价应使用:

text 复制代码
销售金额汇总 / 销售数量汇总

不建议使用 avg(price)

js 复制代码
{
  caption: '平均单价',
  area: 'data',
  dataType: 'number',
  summaryType: 'custom',
  calculateCustomSummary(options) {
    if (options.summaryProcess === 'start') {
      options.totalValue = {
        amount: 0,
        num: 0
      };
    }

    if (options.summaryProcess === 'calculate') {
      options.totalValue.amount += Number(options.value.saleAmount || 0);
      options.totalValue.num += Number(options.value.saleNum || 0);
    }

    if (options.summaryProcess === 'finalize') {
      const amount = options.totalValue.amount;
      const num = options.totalValue.num;
      options.totalValue = num === 0 ? 0 : amount / num;
    }
  },
  format: {
    type: 'fixedPoint',
    precision: 2
  }
}

20. 项目落地建议

20.1 前端原则

  • 所有金额、数量、指标字段统一 dataType: 'number'
  • 所有数据指标统一配置 summaryType
  • 多指标透视表加 dataFieldArea: 'column'
  • 数据加载后统一 Number() 转换
  • 字段还在调整时关闭 DxStateStoring
  • 字段稳定后再开启状态保存,并给 storage-key 加版本号

20.2 后端原则

  • 金额字段统一返回数字,不要返回字符串
  • 字段名与前端 dataField 完全一致
  • 月份最好同时返回 monthNummonthLabel
  • 指标字段即使没有值,也建议返回 0,不要缺字段
  • SQL 别名建议统一 camelCase 或 snake_case,不要混用

推荐 SQL 返回字段:

sql 复制代码
select
    kh.khdm as khdm,
    kh.khmc as khmc,
    month(model.rq) as monthNum,
    cast(month(model.rq) as varchar(2)) + '月' as monthLabel,
    sum(model.je) as saleAmount,
    sum(model.sl) as saleNum,
    sum(coalesce(model.zbje, 0)) as zbje,
    sum(coalesce(model.mlje, 0)) as mlje,
    sum(coalesce(model.mlzbje, 0)) as mlzbje
from xxx model
left join kehu kh on model.khdm = kh.khdm
group by kh.khdm, kh.khmc, month(model.rq)

21. 推荐最终模板

js 复制代码
const buildPivotDataSource = rows => ({
  fields: [
    {
      caption: '客户名称',
      dataField: 'khmc',
      area: 'row',
      width: 140,
      expanded: true
    },
    {
      caption: '客户代码',
      dataField: 'khdm',
      area: 'row',
      width: 100,
      expanded: true
    },
    {
      caption: '月份',
      dataField: 'monthNum',
      area: 'column',
      sortOrder: 'asc',
      customizeText(cellInfo) {
        return cellInfo.value + '月';
      }
    },
    {
      caption: '销售金额',
      dataField: 'saleAmount',
      dataType: 'number',
      area: 'data',
      summaryType: 'sum',
      format: { type: 'fixedPoint', precision: 2 }
    },
    {
      caption: '销售指标',
      dataField: 'zbje',
      dataType: 'number',
      area: 'data',
      summaryType: 'sum',
      format: { type: 'fixedPoint', precision: 2 }
    },
    {
      caption: '毛利金额',
      dataField: 'mlje',
      dataType: 'number',
      area: 'data',
      summaryType: 'sum',
      format: { type: 'fixedPoint', precision: 2 }
    },
    {
      caption: '毛利指标',
      dataField: 'mlzbje',
      dataType: 'number',
      area: 'data',
      summaryType: 'sum',
      format: { type: 'fixedPoint', precision: 2 }
    }
  ],
  dataFieldArea: 'column',
  store: rows.map(item => ({
    ...item,
    saleAmount: Number(item.saleAmount || 0),
    zbje: Number(item.zbje || 0),
    mlje: Number(item.mlje || 0),
    mlzbje: Number(item.mlzbje || 0)
  }))
});

使用:

js 复制代码
dataSource.value = buildPivotDataSource(result.data);

22. 排查清单

当 PivotGrid 显示异常时,按这个顺序排查:

text 复制代码
1. console.log(result.data[0]),确认字段名存在
2. 检查字段大小写是否一致
3. data 字段是否配置 dataType: 'number'
4. data 字段是否配置 summaryType: 'sum'
5. 金额是否是字符串,需要 Number() 转换
6. 多个 data 字段是否配置 dataFieldArea: 'column'
7. 是否启用 DxStateStoring,是否需要清 localStorage
8. 是否所有业务数据本身就是 0
9. 月份是否字符串排序异常
10. 是否整体替换 dataSource,而不是只改 dataSource.value.store

23. 官方资料