---
nav:
  title: Plus组件
  order: 3
group:
  title: 业务组件
  order: 3
title: PisellSalesGrid
order: 2
category: plus
---

# PisellSalesGrid 销售网格

PisellSalesGrid 是 **RecordBoard 的上层组件**，与 RecordBoard 一致采用**打散传参**：**data**、**loading**、**total**、*
*pagination**、**onPageChange**、**searchParams**、**onSearch**、**onReset**、**rowKey**、多选（**selectedKeys**、**selectedRows
**、**onSelectionChange**），以及 **perspectives**、**currentPerspective**。根据当前 Perspective 选择对应的一组 RecordBoard
配置（列、工具栏等）渲染表格布局。不提供 Tab 等切换 UI，当前 Perspective 由外部通过 `currentPerspective` 控制。多选通过 props
传入，SalesGrid 会合并进 grid 再传给 RecordBoard；列显示隐藏由 RecordBoard 内部维护。

## 何时使用

- 同一份数据需要多种 Perspective 展示（如完整列 / 简要列），由外部（如路由、面包屑）决定当前 Perspective。
- 希望用单一组件承接数据源 + 多套 RecordBoard 配置。
- 需要对某类列（按 type）统一使用自定义 render，而不走 RecordBoard 默认派生时，使用 `columnRenderers`。

## 列渲染优先级（不影响 RecordBoard）

- **RecordBoard** 内保留最基础的列 type 渲染（如 currency、number、percent、singleSelect、dateTime 等），**不修改 RecordBoard
  源码**。
- **SalesGrid** 仅在内置里放「稍复杂一些的业务 render」，**不重复** RecordBoard 已支持的基础 type；需要时可在
  `BUILT_IN_COLUMN_RENDERERS` 里扩展业务向 type（如带颜色、标签的金额）。
- **用户** 通过 `columnRenderers` 传入时，同 type 会覆盖 SalesGrid 内置。

因此优先级为：**用户传入 columnRenderers > SalesGrid 内置（仅业务向）> RecordBoard 默认**。未匹配到任何覆盖的列，仍由
RecordBoard 按原逻辑渲染。

## 基本用法

与 RecordBoard 一致采用打散传参，可先组装数据源相关 props 再展开。

```tsx
import React, {useState} from 'react';
import {PisellSalesGrid} from '@pisell/private-materials';
import type {SalesGridDataSourceProps, SalesGridPerspectiveConfig} from '@pisell/private-materials';

const columns = [
    {title: '名称', dataIndex: 'name', key: 'name'},
    {title: '金额', dataIndex: 'amount', key: 'amount'},
];

const perspectives: SalesGridPerspectiveConfig[] = [
    {key: 'default', label: '默认', childComponentProps: {grid: {columns}}},
];

export default function Demo() {
    const [searchParams, setSearchParams] = useState<Record<string, unknown>>({});
    const [selectedKeys, setSelectedKeys] = useState<React.Key[]>([]);
    const [selectedRows, setSelectedRows] = useState<any[]>([]);

    const dataSourceProps: SalesGridDataSourceProps = {
        data: [],
        loading: false,
        total: 0,
        pagination: {pageNumber: 1, pageSize: 10},
        onPageChange: () => {
        },
        searchParams,
        onSearch: (p) => setSearchParams(p),
        onReset: () => setSearchParams({}),
        selectedKeys,
        selectedRows,
        onSelectionChange: (keys, rows) => {
            setSelectedKeys(keys);
            setSelectedRows(rows);
        },
        rowKey: 'id',
    };

    return (
        <PisellSalesGrid
            {...dataSourceProps}
            perspectives={perspectives}
            currentPerspective="default"
        />
    );
}
```

perspectives 中 `childComponentProps.grid` 除 `columns` 外，可包含 RecordBoard grid 的其它配置（如 `scroll`、`size`）及 antd
Table 透传（如 `onRow`、`rowClassName`、`expandable`）。无 perspective 或 perspective 未提供 childComponentProps 时，可传
`defaultChildComponentProps` 作为默认配置。

## 在 Sales Grid 中使用平面图（Floor Map）

平面图不在 Sales Grid 层「整页替换」为 Floor Map，而是由内部的 **PisellRecordBoard** 与 **GridLayout** 共用同一套
**ShellFrame + ToolBar**：在工具栏左侧用 **「表格 / 平面图」** 切换；平面图模式下底部分页不展示（无翻页语义）。

在同一 Perspective 的 **`childComponentProps`** 里同时配置 **`grid`** 与 **`floorMap`**（可选 **`defaultBodyView`**
），Sales Grid 会将其透传给 `PisellRecordBoard`。字段含义与 PisellFloorMapLayout 对齐，详见
[@pisell/materials 中 PisellRecordBoard 文档](https://www.npmjs.com/package/@pisell/materials) 的 **平面图** 小节。

### floorMap 主要字段（与 PisellFloorMapLayout 一致）

| 字段                                                       | 类型                       | 说明                                                               |
|----------------------------------------------------------|--------------------------|------------------------------------------------------------------|
| config                                                   | FloorMapViewConfig       | 平面图视图配置：canvases、dataSourcePlacements、decorations、elementKinds 等 |
| dataSources                                              | Record\<string, T[]\>    | 多数据源，key 与 dataSourcePlacements 的 dataSourceKey 对应               |
| mode                                                     | 'read' \| 'edit'         | 只读或编辑态                                                           |
| onSave                                                   | (config) => void         | 编辑态保存配置回调                                                        |
| dataSourceLabels                                         | Record\<string, string\> | 数据源展示名                                                           |
| renderItem / renderItemByKind                            | 见 @pisell/materials      | 图元渲染                                                             |
| mapLayer / zoom / pan / controls、loading、saveError、style | 可选                       | 与组件文档一致                                                          |

### 最小示例（同一 Perspective：表格 + 平面图）

```tsx
import React, { useState } from 'react';
import { PisellSalesGrid } from '@pisell/private-materials';
import type { SalesGridPerspectiveConfig, SalesGridDataSourceProps } from '@pisell/private-materials';
import type { FloorMapViewConfig } from '@pisell/materials';

const perspectives: SalesGridPerspectiveConfig[] = [
  {
    key: 'tables',
    label: '餐桌',
    childComponentProps: {
      grid: { columns: [{ title: '名称', dataIndex: 'name', key: 'name' }] },
      floorMap: {
        config: {
          canvases: [{ id: 'main', name: '主画布' }],
          dataSourcePlacements: [],
          decorations: [],
          elementKinds: [],
        } as FloorMapViewConfig,
        dataSources: { sales: [] },
        mode: 'edit',
        onSave: (config) => console.log('保存平面图配置', config),
        dataSourceLabels: { sales: '销售' },
        renderItem: (item) => <div style={{ padding: 8 }}>{item.name ?? item.id}</div>,
      },
      defaultBodyView: 'grid', // 可选：'floorMap' 则首屏打开平面图
    },
  },
];

export default function Demo() {
  const dataSourceProps: SalesGridDataSourceProps = {
    data: [],
    loading: false,
    total: 0,
    pagination: { pageNumber: 1, pageSize: 10 },
    onPageChange: () => {},
    searchParams: {},
    onSearch: () => {},
    onReset: () => {},
    rowKey: 'id',
  };

  return (
    <div style={{ height: 400 }}>
      <PisellSalesGrid {...dataSourceProps} perspectives={perspectives} currentPerspective="tables" />
    </div>
  );
}
```

- 视图切换在 **RecordBoard 工具栏** 完成，无需再为平面图单独建一个 `perspective.key`。
- 若业务上仍可用多个 Perspective 切换「不同列表模板」，每个模板内均可按需配置或不配置 `floorMap`。

## API

### PisellSalesGrid Props

与 RecordBoard 打散传参对齐，无单一 `datasource`。

| 参数                                                                                     | 类型                                   | 必填 | 说明                                                                                          |
|----------------------------------------------------------------------------------------|--------------------------------------|----|---------------------------------------------------------------------------------------------|
| data / loading / total / pagination / onPageChange / searchParams / onSearch / onReset | 各自类型                                 | 否  | 列表与分页、搜索，与 RecordBoard 一致                                                                   |
| rowKey                                                                                 | string \| (record) => Key            | 否  | 行主键，透传给 RecordBoard                                                                         |
| selectedKeys / selectedRows / onSelectionChange                                        | 各自类型                                 | 否  | 多选，由 SalesGrid 合并进 grid 传给 RecordBoard                                                      |
| perspectives                                                                           | SalesGridPerspectiveConfig[]         | 是  | Perspective 数据，每组为 key + label + childComponentProps（含 grid、toolBar 等）                      |
| currentPerspective                                                                     | string                               | 是  | 当前 Perspective，对应某条 perspectives[].key                                                      |
| defaultChildComponentProps                                                             | RecordBoardChildComponentPropsCompat | 否  | 无 perspective 或 perspective 未提供 childComponentProps 时的默认配置                                  |
| columnRenderers                                                                        | SalesGridColumnRenderer[]            | 否  | 按列 type 覆盖列渲染；与内置合并使用，同 type 时传入的覆盖内置                                                       |
| __id                                                                                   | string                               | 否  | 实例 id，透传 RecordBoard 用于**列显隐持久化**（localStorage，与 @pisell/utils getComponentStorageKey 规则一致） |
| className / style                                                                      | string / React.CSSProperties         | 否  | 自定义类名与样式                                                                                    |

### 列显隐持久化

传入 **`__id`** 后，用户在工具栏「列设置」中勾选/取消列会写入 localStorage，下次进入同页面（同 pathname +
memory_key）会恢复。Storage 由 @pisell/utils 的 `getColumnVisibilityFromLocal` / `saveColumnVisibilityToLocal` 处理。

- **直接使用 PisellSalesGrid**：传 `__id="sales-grid-1"` 等唯一字符串即可。
- **通过 PisellSalesManagement**：给 Sales Management 传 `__id`，会透传到 Sales Grid 再传到 Record Board。
- **低代码**：在物料/页面配置中把组件的 **__id**（或低代码引擎提供的节点 id）绑定到该 prop，即可按实例持久化列显隐。

### SalesGridColumnRenderer

| 属性     | 类型                                  | 说明                           |
|--------|-------------------------------------|------------------------------|
| type   | string                              | 与视角 grid.columns 中列的 type 匹配 |
| render | (value, record, index) => ReactNode | 该 type 列的单元格自定义渲染            |

### SalesGridPerspectiveConfig

| 属性                     | 类型                                            | 说明                                                                                           |
|------------------------|-----------------------------------------------|----------------------------------------------------------------------------------------------|
| key                    | string                                        | Perspective 唯一标识                                                                             |
| label                  | string                                        | 可选，供外部展示用                                                                                    |
| childComponentProps    | RecordBoardChildComponentPropsCompat          | 可选；该 Perspective 下 RecordBoard 透传配置（**grid**、**toolBar**、**floorMap**、**defaultBodyView** 等） |
| getChildComponentProps | (ctx) => RecordBoardChildComponentPropsCompat | 可选；工厂函数，存在时优先于 childComponentProps。**childComponentProps.floorMap** 有值时，工具栏出现「表格 / 平面图」切换    |

## 相关文档

- [PisellRecordBoard](https://www.npmjs.com/package/@pisell/materials)（@pisell/materials）
