DataBlockProvider

卡片类型

卡片分为简单卡片和包含各种数据的卡片。

简单卡片

简单卡片例如 Markdown 卡片。

它只有文本内容,没有其他更多复杂数据,且文本内容是存储在 schema 中的,没有存储在数据库中。

1{
2  "type": "void",
3  "x-component": "Markdown.Void",
4  "x-component-props": {
5    "content": "markdown content"
6  },
7}

数据卡片

数据卡片是指卡片的数据存储在服务端的数据表中,例如 Table 组件。

Table 中的字段信息及列表数据,都是存储在数据库中的。

DataBlockProvider 介绍

为了方便对数据卡片的数据进行管理,我们提供了 DataBlockProvider 组件,其内部封装了:

  • DataBlockProvider:封装了下面的所有组件,并提供了卡片属性
    • CollectionProvider / AssociationProvider: 根据 DataBlockProvider 提供的上下文信息,查询对应数据表数据及关系字段信息并传递
    • BlockResourceProvider: 根据 DataBlockProvider 提供的上下文信息,构建卡片 Resource API,用于卡片数据的增删改查
    • BlockRequestProvider: 根据 DataBlockProvider 提供的上下文信息,自动调用 BlockResourceProvider 提供的 resource.get()resource.list() 发起请求,得到卡片数据,并传递
      • CollectionRecordProvider: 对于 resource.get() 场景,会自动嵌套 CollectionRecordProvider 并将 resource.get() 请求结果传递下去,resource.list() 场景则需要自行使用 CollectionRecordProvider 提供数据记录
const DataBlockProvider = (props) => {
  return <DataBlockContext.Provider>
    <CollectionDataSourceProvider>
      <CollectionProvider> / <AssociationProvider>
        <BlockResourceProvider>
          <BlockRequestProvider>
            {action !== 'list' && <CollectionRecordProvider record={blocRequest.data}>
              {props.children}
            </Record>}
          </BlockRequestProvider>
        </BlockResourceProvider>  / </AssociationProvider>
      </CollectionProvider>
    </CollectionDataSourceProvider>
  </DataBlockContext.Provider>
}

上述组件封装到 DataBlockProvider 的内部,只需要使用 DataBlockProvider 即可自行得到上述数据。

使用方式

其主要使用在卡片的 schema 的 x-decorator 中,例如:

1{
2  type: 'void',
3  name: 'hello-block',
4  'x-component':  'CardItem',
5  'x-decorator': 'DataBlockProvider',
6  'x-decorator-props': {
7    collection: 'users',
8    dataSource: 'main',
9    action: 'list',
10    tableProps: {
11      bordered: true,
12    }
13  },
14  'x-use-decorator-props': 'useDynamicDataBlockProps',
15}

完整示例

属性

静态属性和动态属性

  • schema 中的 x-decorator-props 称为静态属性,它是一个普通对象,记录卡片的配置信息
  • schema 中的 x-use-decorator-props 中的属性称为动态属性,它是一个 React hook,可用于获取例如 URL 上的 ID,或者父级的 context 数据

当两者都存在时,会进行深度合并,作为 DataBlockProvider 的属性。

属性详解

interface AllDataBlockProps {
  collection?: string;
  association?: string;
  sourceId?: string | number;
  record?: Record;
  action?: 'list' | 'get';
  filterByTk?: string;
  params?: Record<string, any>;
  parentRecord?: Record;
  [index: string]: any;
}
  • collection(x-decorator-props):卡片的 collection 表名,用于获取卡片的字段信息和卡片数据
  • association(x-decorator-props):卡片的关系字段名,用于获取卡片的关系字段信息和关系字段数据
  • dataSource(x-decorator-props): 数据源
  • action(x-decorator-props):卡片的请求类型,listget
  • params(x-decorator-propsx-use-decorator-props):卡片的请求参数,同时存在于
  • filterByTk(x-use-decorator-props):相当于 params.filterByTk,可理解为 id,用于获取单条数据
  • sourceId(x-use-decorator-props):卡片的 sourceId,配合 association 使用,用于获取卡片的关系字段数据
  • record(x-use-decorator-props):当提供 record 时,会使用 record 作为卡片的数据,不发起请求
  • parentRecord(x-use-decorator-props):当提供 parentRecord 时,会使用 parentRecord 作为关系字段的表数据,不发起请求
const DataBlockProvider = (props) => {
  return <DataBlockContext.Provider value={props}>
    <CollectionDataSourceProvider>
      <CollectionProvider name={props.collection}> / <CollectionProvider name={props.association}>
          <BlockResourceProvider {...props}>
            <BlockRequestProvider resource={resource}>
              {action !== 'list' && <CollectionRecordProvider record={blocRequest.data}>
                {props.children}
              </Record>}
            </BlockRequestProvider>
          </BlockResourceProvider>
        </CollectionProvider>
    </CollectionDataSourceProvider>
  </DataBlock.Provider>
}

属性组合和场景

这些属性根据不同的场景,共有 8 中情况:

  • collection
    • 创建:collection
    • 获取单条数据:collection + action: get + params
    • 获取列表数据:collection + action: list + params
    • 使用 record 作为数据:collection + record

对于 获取单条数据获取列表数据 params 非必须。

  • association
    • 创建:association + sourceId
    • 获取单条数据:association + sourceId + action: get + params + parentRecord
    • 获取列表数据:association + sourceId + action: list + params + parentRecord
    • 使用 record 作为数据:association + sourceId + record + parentRecord

对于 获取单条数据获取列表数据 paramsparentRecord 非必须,当没有 parentRecord 会根据 association 查询到对应的 collection,然后再根据 collection 查询到对应的 parentRecord

属性获取和修改

useDataBlock()

可用于获取和修改 DataBlockProvider 的属性。

  • 类型
interface Result<T extends {} = {}> {
  props: AllDataBlockProps & T;
  dn: Designable;
}
const useDataBlock: <T extends {}>() => Result<T>
  • 详解

props 就对应着上面的 AllDataBlockPropsdnDesignable 对象,可用于修改 DataBlockProvider 的 UI schema,详细见 Designable

  • 示例
const { props, dn } = useDataBlock<{ tableProps: { bordered?: boolean } }>();

// 获取
const checked = props.tableProps.bordered;

// 修改
dn.deepMerge({
  'x-decorator-props': {
    tableProps: {
      bordered: !checked,
    },
  },
});

useDataBlockProps()

相当于 useDataBlock().props

const props = useDataBlockProps<{ tableProps: { bordered?: boolean } }>();

const checked = props.tableProps.bordered;

示例

association

association 与 collection 类似,只是需要提供 sourceId,我们以 Table list 为例。

Table list & parentRecord

如果不提供 sourceId,则需要提供 parentRecord,我们以 Table list 为例。