---

## title: 平面图多数据源（与 tables 同级）

order: 10
category: plus

> **扩展阅读**：[PisellReservation 深入：架构与数据流](./pisell-reservation-deep-dive.md)（含**纯文本结构图**、数据总览与本专题全文收录）。

# 平面图多数据源：与 `tables` 同级新增一路

本文说明如何在 **PisellReservation** 中，在 `dataSources.tables` 之外再增加**同级**的另一数据源 key（例如 `staffPoints`、`condimentStations`），便于自行改代码时按层落地。

---

## 1. 概念：`tables` 是什么

- `**tables` 只是 `dataSources` 对象里的一个 key**。工程里默认常量见 `reservationConstants.ts` 的
  `GRID_DS_KEY = 'tables'`。
- `**gridDataSourceKey`**（默认 `'tables'`）主要决定 RecordBoard 表格从 `dataSources` 的**哪一个 key** 做客户端分页（见
  `@pisell/materials` 的 `PisellRecordBoard`）。
- **平面图底层**（`PisellFloorMapLayout`）支持 **多个 key 并存**：`dataSources` 可以是 `{ tables: Row[], yourKey: Row[] }`。

参考实现：`**packages/materials/src/components/pisellRecordBoard/PisellRecordBoard.stories.tsx`** 中 **Default**
故事（餐桌 + 蘸料摆台）：表格只绑一路，`dataSources` 同时包含两路，平面图可同时渲染两类图元。

---

## 2. 数据如何进入平面图：三条路径

### 路径 A：受控传入（最简单）

向 `PisellReservation` 传入：

```tsx
dataSources={{
  tables: [...],
  yourKey: [...],
}}
```

组件内合并逻辑（`PisellReservation.tsx`）大致为：

- 先展开 `**dataSourcesProp**`（你传入的对象）；
- 再用内置算好的 `**tables**` 覆盖 `**[gridDataSourceKey]**`（通常为 `tables`）。

因此：**你在 prop 里多写的 key 会保留**，与内置合并后的 `tables` **同级**进入平面图；只有与 `gridDataSourceKey` 同名的 key
会被覆盖。

### 路径 B：内置合并只负责「一桌」这一路

`reservationTablesMerge.ts` 中的 `**buildReservationMergedTableRows`** 只返回**一个数组**，用于写入 `gridDataSourceKey`
对应的那一列（资源 + 预约合并、`sales.getResourceBookingList` 等逻辑都在这条链路上）。

第二路若也要「请求 + 合并」：**需要自行增加**数据获取与 `useMemo`，最后在组装根级 `dataSources` 时写入第二个 key，例如：

```ts
{
  ...dataSourcesProp,
  [gridDataSourceKey]: mergedTables,
  [YOUR_SECOND_KEY]: secondList,
}
```

注意合并顺序，避免被后续展开覆盖。

### 路径 C：表格不必绑第二路

第二路可以**仅给平面图用**：`gridDataSourceKey` 仍指向 `tables`，表格继续只展示桌位列表。

---

## 3. 平面图：图元能绑定哪些数据源

图元种类配置类型在 materials 中为 `**FloorMapElementKindConfig`**，字段 `**allowedDataSourceKeys`** 列出该种类在侧栏可选的数据源
key。

默认预约 mock（`reservationMock.ts` → `getReservationPaletteElementKinds`）里，绑定桌位一般为
`allowedDataSourceKeys: ['tables']`（常量 `DS === 'tables'`）。

要让图元能绑第二路，需要其一：

- 把 `**allowedDataSourceKeys**` 扩成 `['tables', 'yourKey']`；或
- **新增**一个 `elementKind`，只允许 `['yourKey']`，并在 `renderItemByKind` 里用对应渲染函数。

绑定合法性校验见：

`packages/materials/src/components/pisellFloorMapLayout/utils/floorMapElementKindUtils.ts`

---

## 4. 侧栏：标签与表单列（易漏）

`useReservationFloorMapMerged.tsx` 中当前对 `**dataSourceLabels`**、`**dataSourceFormColumns`** 往往只配置了
`**gridDataSourceKey**` 一项。

仅增加 `dataSources.yourKey` 而不补充这两项时，侧栏可能显示 **raw key** 或 **缺少表单列**。

处理方式任选：

- 在上述两个对象中**为 `yourKey` 增加** `label` 与 `columns`（建议走 `locales` + 独立列配置）；或
- 通过 `**floorMap` 透传** `dataSourceLabels` / `dataSourceFormColumns`（注意与 `return { ... }` 里 `...floorRest`
  的字段顺序，避免被意外覆盖）。

---

## 5. 渲染：如何根据绑定取行

`reservationCards.tsx` 中的 `**findReservationRow`** 会根据图元上的 `**dataBinding.dataSourceKey`** 到
`**dataSources[key]**` 中查找记录。

- 若第二路行结构与 `**PisellReservationTableRow**` 兼容，可继续复用 `**ReservationFloorRoomCard**` 与现有
  `renderItemByKind` 分支。
- 若结构不同：为**新 elementKind** 注册新的 `renderItemByKind` 实现，内部按你的类型读取 `dataSources[yourKey]`。

---

## 6. 业务分支：HUD、点击、淡化等

- `**ReservationFloorMapHud`** 等统计若只统计「桌位」，通常会按 `elementKind` 或 `dataSourceKey === 'tables'`
  过滤；第二路若要进统计需改条件。
- `**floorMapItemClickBefore`**（`PisellReservation.tsx`）中打开宿主抽屉等逻辑，若仅针对桌位，需按 `**dataSourceKey**` 分支处理。

---

## 7. 类型（TypeScript）

`types.ts` 中当前为：

```ts
dataSources?: Record<string, PisellReservationTableRow[]>;
```

第二路若不是桌位行类型，可改为更宽类型（如 `Record<string, unknown[]>`），或拆成多个 prop，避免类型误报。

---

## 8. 实施 Checklist（推荐顺序）

| 步骤 | 内容                                                                                               |
|----|--------------------------------------------------------------------------------------------------|
| 1  | 确定 **key 字符串**（如 `yourKey`），与低代码、已保存 layout、`allowedDataSourceKeys` 一致。                          |
| 2  | 确定 **数据来源**：仅 `dataSources` prop，或新增请求 + 合并进根 `dataSources`。                                     |
| 3  | 修改 `**floorMapConfig.elementKinds`**（mock 合并或接口 layout）：`allowedDataSourceKeys` 或新 kind。         |
| 4  | 补 `**dataSourceLabels` / `dataSourceFormColumns`**（`useReservationFloorMapMerged` 或 `floorMap`）。 |
| 5  | 补 `**renderItemByKind**`（新 kind 或扩展查找逻辑）。                                                        |
| 6  | 检查 **HUD / onItemClick / getMergedItemWrapperStyle** 等是否需按 `dataSourceKey` 分支。                   |

---

## 9. 关键文件索引

| 模块                              | 路径                                                              |
|---------------------------------|-----------------------------------------------------------------|
| 根级 `dataSources` 合并             | `PisellReservation.tsx`（`dataSources` 的 `useMemo`）              |
| 内置桌位合并                          | `reservationTablesMerge.ts` → `buildReservationMergedTableRows` |
| 默认 `GRID_DS_KEY`                | `reservationConstants.ts`                                       |
| 平面图 props 合并（labels/forms）      | `useReservationFloorMapMerged.tsx`                              |
| 默认图元种类与 `allowedDataSourceKeys` | `reservationMock.ts` → `getReservationPaletteElementKinds` 等    |
| 卡片占位与按 key 查行                   | `reservationCards.tsx`                                          |
| 多数据源 Story 参考                   | `pisellRecordBoard/PisellRecordBoard.stories.tsx` → `Default`   |
| 绑定校验                            | `pisellFloorMapLayout/utils/floorMapElementKindUtils.ts`        |

---

## 10. 与主文档的关系

组件级使用说明见同目录 `**PisellReservation.md`**；本文仅聚焦 **与 `tables` 同级扩展数据源** 的代码路径与注意点。