# 在产品集合块中注册自定义集合

`__experimentalRegisterProductCollection` 函数是 `@woocommerce/blocks-registry` 包的一部分。 此函数允许第三方开发者注册一个新的集合。 此函数接受大多数 `[Block Variation](https://developer.wordpress.org/block-editor/reference-guides/block-api/block-variations/#defining-a-block-variation)` 接受的参数。

**注意：** 这是一个实验性功能，未来可能会发生变化。 请谨慎使用。

**有两种使用此函数的方法：**

1. 在 Webpack 配置中使用 `@woocommerce/dependency-extraction-webpack-plugin`： 这将允许您从包中导入该函数并在您的代码中使用它。 例如：

	```tsx
	import { __experimentalRegisterProductCollection } from "@woocommerce/blocks-registry";
	```

2. 使用全局 `wc` 对象： 这将允许您使用全局 JavaScript 对象来使用该函数，而无需导入它。 例如：

	```tsx
	wc.wcBlocksRegistry.__experimentalRegisterProductCollection({
	...
	});
	```

如果您选择使用全局 `wc`，请确保将 `wc-blocks-registry` 添加为您的脚本的依赖项。

  ```php
  function enqueue_my_custom_product_collection_script() {
      wp_enqueue_script(
          'my-custom-product-collection',
          plugins_url( '/dist/my-custom-product-collection.js', __FILE__ ),
          array( 'wc-blocks-registry' ),
          10
      );
  }
  add_action( 'enqueue_block_editor_assets', 'enqueue_my_custom_product_collection_script' );
  ```

**提示：** 如果您正在使用 Webpack，建议使用第一种方法。

## 定义集合

我们将解释可以传递给 `__experimentalRegisterProductCollection` 的重要参数。对于其他参数，您可以参考 [Block Variation](https://developer.wordpress.org/block-editor/reference-guides/block-api/block-variations/#defining-a-block-variation) 文档。

集合由一个对象定义，该对象可以包含以下字段：

- `name` (类型 `string`): 一个唯一且可供机器读取的集合名称。我们建议使用 `<plugin-name>/product-collection/<collection-name>` 的格式。`<plugin-name>` 和 `<collection-name>` 应该只包含字母数字字符和连字符 (例如：`my-plugin/product-collection/my-collection`)。
- `title` (类型 `string`): 集合的标题，将在各种地方显示，包括块插入器和集合选择器。
- `description` (可选，类型 `string`): 集合的易于理解的描述。
- `innerBlocks` (可选，类型 `Array[]`): 将添加到集合中的内部块数组。如果未提供，将使用默认的内部块。
- `isDefault`: 对于所有集合，该值设置为 `false`。第三方开发者无需传递此参数。
- `isActive`: 将由我们管理。第三方开发者无需传递此参数。
- `usesReference` (可选，类型 `Array[]`): 一个字符串数组，指定集合所需的引用。可接受的值包括 `product`、`archive`、`cart` 和 `order`。当编辑器端不可用但前端可用的引用时，我们将显示一个预览标签。
- `scope` (可选，类型 `Array[]`): 集合适用的范围列表。可接受的值包括 `block`、`inserter` 和 `transform`。默认为 `["block", "inserter"]`。
   	- **注意:** 对于产品集合块，`block` 范围意味着该集合将在集合选择器中显示，并且“选择集合”工具栏按钮将可见。对于其他范围，您可以参考 [Block Variation](https://developer.wordpress.org/block-editor/reference-guides/block-api/block-variations/#defining-a-block-variation) 文档。

### 属性

属性是定义集合行为的特性。所有属性都是*可选*的。以下是一些可以传递给 `__experimentalRegisterProductCollection` 的重要属性：

- `query` (类型 `object`): 定义集合查询的对象。它可以包含以下字段：
    - `offset` (类型 `number`): 用于偏移查询的项目数量。
    - `order` (类型 `string`): 查询的排序方式。 接受的值为 `asc` 和 `desc`。
    - `orderBy` (类型 `string`): 用于排序的字段。
    - `pages` (类型 `number`): 要查询的页数。
    - `perPage` (类型 `number`): 每页的产品数量。
    - `search` (类型 `string`): 用于查询的搜索词。
    - `taxQuery` (类型 `object`): 用于过滤查询的分类查询。例如，如果您想要获取分类为 `Clothing` 和 `Accessories` 且标签为 `Summer` 的产品，则可以将 `taxQuery` 设置为 `{"product_cat":[20,17],"product_tag":[36]}`。其中数组值是术语 ID。
    - `featured` (类型 `boolean`): 是否查询精选商品。
    - `timeFrame` (类型 `object`): 用于查询的时间范围。
        - `operator` (类型 `string`): 用于时间范围查询的操作符。 接受的值为 `in` 和 `not-in`。
        - `value` (类型 `string`): 用于查询的值。 应该是一个有效的日期字符串，PHP 的 `strtotime` 函数可以解析。
    - `woocommerceOnSale` (类型 `boolean`): 是否查询促销商品。
    - `woocommerceStockStatus` (类型 `array`): 用于查询的库存状态。 接受的值包括 `instock`、`outofstock` 和 `onbackorder`。
    - `woocommerceAttributes` (类型 `array`): 用于查询的属性。
        - 例如，如果您想要获取颜色为 `blue` 和 `gray` 且尺寸为 `Large` 的产品，则可以将 `woocommerceAttributes` 设置为 `[{"termId":23,"taxonomy":"pa_color"},{"termId":26,"taxonomy":"pa_size"},{"termId":29,"taxonomy":"pa_color"}]`。
    - `woocommerceHandPickedProducts` (类型 `array`): 用于查询的手选产品。 应该包含产品 ID。
    - `priceRange` (类型 `object`): 用于查询的价格范围。
        - `min` (类型 `number`): 最小价格。
        - `max` (类型 `number`): 最大价格。

- `displayLayout` (类型 `object`): 定义集合布局的布局对象。它可以包含以下字段：
    - `type` (类型 `string`): 布局类型。 接受的值为 `grid`、`stack` 和 `carousel`。
    - `columns` (类型 `number`): 要显示的列数。
    - `shrinkColumns` (类型 `boolean`): 是否使布局具有响应式。

# 产品管理

本页面用于管理产品信息。

## 产品列表

产品列表显示所有已创建的产品。您可以根据不同的条件进行筛选和排序。

*   **分类 (Category):**  产品所属的分类。
*   **产品标签 (Product Tags):**  与产品相关的标签。
*   **状态 (Status):**  产品的当前状态。
*   **产品属性 (Product Attributes):**  产品的各种属性。
*   **库存状态 (Stock Status):**  产品的库存状态。

您可以通过以下方式进行筛选：

*   **创建时间 (Created):**  按创建时间排序。
*   **精选 (Featured):**  显示或隐藏精选产品。
*   **手工挑选 (Hand-picked):**  显示或隐藏手工挑选的产品。
*   **关键字 (Key):**  根据关键字搜索产品。
*   **促销 (On Sale):**  显示或隐藏促销产品。
*   **库存状态 (Stock Status):**  根据库存状态筛选产品。
*   **分类法 (Taxonomy):**  筛选产品分类、产品标签和自定义分类法。
*   **价格范围 (Price Range):**  根据价格范围筛选产品。

您还可以通过以下方式进行排序：

*   **排序方式 (Order):**  按不同的字段进行排序。

## 产品详情

产品详情页面显示单个产品的详细信息。

*   **产品 (Product):**  产品的名称和描述。
*   **产品属性 (Product Attributes):**  产品的各种属性。
*   **产品标签 (Product Tags):**  与产品相关的标签。
*   **库存 (Stock):**  产品的库存数量。
*   **价格 (Value):**  产品的价格。
*   **订单 (Order):**  与该产品相关的订单信息。

## 产品设置

产品设置页面允许您配置产品的各种设置。

*   **隐藏控件 (Hide Controls):**  可以隐藏以下控件：

    *   `hideControls` (类型 `array`):  要隐藏的控件。 可能的值：
        *   `order` - "排序方式" 设置
        *   `attributes` - "产品属性" 过滤器
        *   `created` - "创建时间" 过滤器
        *   `featured` - "精选" 过滤器
        *   `hand-picked` - "手工挑选的产品" 过滤器
        *   `keyword` - "关键字" 过滤器
        *   `on-sale` - "促销" 过滤器
        *   `stock-status` - "库存状态" 过滤器
        *   `taxonomy` - "产品分类"、"产品标签" 和自定义分类法 过滤器
        *   `price-range` - "价格范围" 过滤器

*   **其他设置:**  您可以设置产品的其他属性，例如颜色 (Red) 和其他参数。

## 创建产品

您可以在此页面创建新的产品。  填写必要的信息，然后点击 "创建" 按钮。  确保填写所有必填字段。

## 范围 (Range)

产品属性的范围可以定义为最小值和最大值。

## 标签 (Tag)

每个产品可以拥有多个标签，用于方便搜索和分类。

## 设置 (Setting)

系统设置允许您配置各种全局参数。

#### Preview 属性

`preview` 属性是可选的，用于设置集合的预览状态。它可以包含以下字段：

- `initialPreviewState` (类型 `object`): 集合的初始预览状态。它可以包含以下字段：
    - `isPreview` (类型 `boolean`): 是否处于查看模式。
    - `previewMessage` (类型 `string`): 当用户将鼠标悬停在预览标签上时，在工具提示中显示的提示信息。
- `setPreviewState` (可选，类型 `function`): 用于设置集合的预览状态的函数。它接收以下参数：
    - `setState` (类型 `function`): 用于设置预览状态的函数。您可以向此函数传递一个新的预览状态，其中包含 `isPreview` 和 `previewMessage`。
    - `attributes` (类型 `object`): 集合的当前属性。
    - `location` (类型 `object`): 集合的位置。 接受的值包括 `product`、`archive`、`cart`、`order`、`site`。

有关更多信息，您可以查看 [PR #46369](https://github.com/woocommerce/woocommerce/pull/46369)，其中添加了预览功能。

## 示例

### 示例 1：注册一个新的集合

```tsx
__experimentalRegisterProductCollection({
  name: "your-plugin-name/product-collection/my-custom-collection",
  title: "My Custom Collection",
  icon: "games",
  description: "This is a custom collection.",
  keywords: ["custom collection", "product collection"],
});
```

如上例所示，我们正在注册一个名为 `woocommerce/product-collection/my-custom-collection` 且标题为 `My Custom Collection` 的新集合。以下是其外观的截图：
![image](https://github.com/woocommerce/woocommerce/assets/16707866/7fddbc02-a6cd-494e-b2f4-13dd5ef9cf96)

### 示例 2：注册一个带有预览的新集合

如以下所示，设置初始预览状态是可能的。 在以下示例中，我们设置 `isPreview` 和 `previewMessage`。

```tsx
__experimentalRegisterProductCollection({
  name: "your-plugin-name/product-collection/my-custom-collection-with-preview",
  title: "My Custom Collection with Preview",
  icon: "games",
  description: "This is a custom collection with preview.",
  keywords: ["My Custom Collection with Preview", "product collection"],
  preview: {
    initialPreviewState: {
      isPreview: true,
      previewMessage:
        "This is a preview message for my custom collection with preview.",
    },
  },
  attributes: {
    query: {
      perPage: 5,
      featured: true,
    },
    displayLayout: {
      type: "grid",
      columns: 3,
      shrinkColumns: true,
    },
	hideControls: [ "created", "stock-status" ]
  },
});
```

以下是其外观的截图：
![image](https://github.com/woocommerce/woocommerce/assets/16707866/5fc1aa20-552a-4e09-b811-08babab46665)

### 示例 3：高级预览用法

如您在下面看到的，也可以使用 `setPreviewState` 来设置预览状态。在下面的示例中，我们设置了 `initialPreviewState`，并使用 `setPreviewState` 在 5 秒后更改预览状态。

**此示例展示：**

- 如何访问预览状态中的当前属性和位置
- 如何使用异步操作
   - 我们使用 `setTimeout` 在 5 秒后更改预览状态。您可以根据需要使用任何异步操作，例如从 API 获取数据，以确定预览状态。
- 如何将清理函数作为返回值使用
   - 我们返回一个清理函数，该函数将在组件卸载后清除超时。您可以使用此函数来清理在 `setPreviewState` 中使用的任何资源。

```tsx
__experimentalRegisterProductCollection({
  name: "your-plugin-name/product-collection/my-custom-collection-with-advanced-preview",
  title: "My Custom Collection with Advanced Preview",
  icon: "games",
  description: "This is a custom collection with advanced preview.",
  keywords: [
    "My Custom Collection with Advanced Preview",
    "product collection",
  ],
  preview: {
    setPreviewState: ({
      setState,
      attributes: currentAttributes,
      location,
    }) => {
      // setPreviewState 可以访问当前的属性和位置。
      // console.log( currentAttributes, location );

      const timeoutID = setTimeout(() => {
        setState({
          isPreview: false,
          previewMessage: "",
        });
      }, 5000);

      return () => clearTimeout(timeoutID);
    },
    initialPreviewState: {
      isPreview: true,
      previewMessage:
        "This is a preview message for my custom collection with advanced preview.",
    },
  },
});
```

### 示例 4：带有内部块的集合

如您在下面看到的，也可以为集合定义内部块。在下面的示例中，我们正在为集合定义内部块。

```tsx
__experimentalRegisterProductCollection({
  name: "your-plugin-name/product-collection/my-custom-collection-with-inner-blocks",
  title: "My Custom Collection with Inner Blocks",
  icon: "games",
  description: "This is a custom collection with inner blocks.",
  keywords: ["My Custom Collection with Inner Blocks", "product collection"],
  innerBlocks: [
    [
      "core/heading",
      {
        textAlign: "center",
        level: 2,
        content: "Title of the collection",
      },
    ],
    [
      "woocommerce/product-template",
      {},
      [
        ["woocommerce/product-image"],
        [
          "woocommerce/product-price",
          {
            textAlign: "center",
            fontSize: "small",
          },
        ],
      ],
    ],
  ],
});
```

这将创建一个包含标题、产品图像和产品价格的集合。它看起来如下所示：

![image](https://github.com/woocommerce/woocommerce/assets/16707866/3d92c084-91e9-4872-a898-080b4b93afca)

**提示：** 您可以在 [Inner Blocks](https://developer.wordpress.org/block-editor/how-to-guides/block-tutorial/nested-blocks-inner-blocks/#template) 文档中了解有关内部块模板的更多信息。

### 示例 5：带有 `usesReference` 参数的集合

当集合需要引用才能正常工作时，可以使用 `usesReference` 参数来指定它。在下面的示例中，我们正在定义一个需要 `product` 引用的集合。

```tsx
__experimentalRegisterProductCollection({
  name: "your-plugin-name/product-collection/my-custom-collection",
  title: "My Custom Collection",
  icon: "games",
  description: "This is a custom collection.",
  keywords: ["custom collection", "product collection"],
  usesReference: ["product"],
});
```

这将创建一个需要 `product` 引用的集合。如果编辑器端不可用，但在前端可用的必需引用，我们将显示一个预览标签。

当集合需要多个引用之一时，可以使用 `usesReference` 参数来指定它。在下面的示例中，我们正在定义一个需要 `product` 或 `order` 引用的集合。

```tsx
__experimentalRegisterProductCollection({
  name: "your-plugin-name/product-collection/my-custom-collection",
  title: "My Custom Collection",
  icon: "games",
  description: "This is a custom collection.",
  keywords: ["custom collection", "product collection"],
  usesReference: ["product", "order"],
});
```

### 示例 6：`scope` 参数

当您不指定 `scope` 参数时，其默认值是 `["block", "inserter"]`。 这种默认行为是从 [Block Variation API](https://developer.wordpress.org/block-editor/reference-guides/block-api/block-variations/#defining-a-block-variation) 继承而来的。

`Product Collection` 块使用 `block` 范围来控制：

1. 在集合选择器中的可见性
2. "选择集合" 工具栏按钮的显示

#### 不在集合选择器中显示集合

如果您不想在集合选择器中显示您的集合，可以将 `scope` 参数设置为一个空数组或任何不包含 `block` 值的其他值。

例如：

```tsx
__experimentalRegisterProductCollection({
  name: "your-plugin-name/product-collection/my-custom-collection",
  title: "My Custom Collection",
  icon: "games",
  description: "This is a custom collection.",
  keywords: ["custom collection", "product collection"],
  scope: [],
});
```

#### 仅在块插入器中显示集合

如果您希望仅在块插入器中显示您的集合，而不在集合选择器中显示，可以将 `scope` 参数设置为 `["inserter"]`。 这允许用户直接从块插入器添加您的自定义集合，同时将其隐藏在集合选择器界面中。

例如：

```tsx
__experimentalRegisterProductCollection({
  name: "your-plugin-name/product-collection/my-custom-collection",
  title: "My Custom Collection",
  description: "This is a custom collection.",
  keywords: ["custom collection", "product collection"],
  scope: ["inserter"],
});
```