跳转到主要内容

如何实现商家入职流程

简介

入职流程是商家用户体验的关键部分。它有助于帮助他们取得成功,并确保他们不仅正确使用您的扩展程序,而且还能充分利用它。作为开发人员,您可以利用一些特别有用的功能来帮助入职使用您扩展程序的商家:

  • 设置任务
  • 商店管理链接
  • 管理员备注

快速开始

我们将使用 @woocommerce/create-woo-extension 来构建一个现代的 WordPress JavaScript 插件开发环境。该工具为与 WooCommerce 集成创建了一个完全可用的开发环境。

在这个示例中,我们将使用 add-task 变体来创建一个基本的入职扩展程序,以便我们可以在此基础上进行构建。

在您的 wp-content/plugins 目录中,运行以下命令来创建您的扩展程序:

npx @wordpress/create-block -t @woocommerce/create-woo-extension --variant=add-task my-extension-name

导航到新创建的文件夹并开始开发:

cd my-extension-name
npm run start

可选地,您可以使用 wp-env 来创建一个本地的 WordPress 环境:

npm -g i @wordpress/env
wp-env start

不要忘记前往 /wp-admin/plugins.php 并激活您的插件。

使用设置任务

设置任务会出现在 WooCommerce 管理员主屏幕上,并提示商家完成某些步骤以设置您的扩展程序。添加任务是一个两步过程,需要:

  • 使用 PHP 注册任务(以及其 JavaScript)
  • 使用 JavaScript 构建任务,设置其配置,并将它添加到任务列表中。

使用 PHP 注册任务

要将您的任务注册为扩展的任务列表项目,您需要首先创建一个新的 PHP 类,该类继承自 Task 类。 此类将定义您自定义任务的属性和行为。

<?php
/**
 * 自定义任务示例。
 *
 */
use Automattic\WooCommerce\Admin\Features\OnboardingTasks\Task;

/**
 * 自定义任务类。
 */
class MyTask extends Task {
	/**
	 * 获取任务 ID。
	 *
	 * @return string
	 */
	public function get_id() {
		return 'my-task';
	}

	/**
	 * 标题。
	 *
	 * @return string
	 */
	public function get_title() {
		return __( 'My task', 'woocommerce' );
	}

	/**
	 * 内容。
	 *
	 * @return string
	 */
	public function get_content() {
		return __( '在此处添加您的任务描述,以便在任务列表中显示。', 'woocommerce' );
	}

	/**
	 * 时间。
	 *
	 * @return string
	 */
	public function get_time() {
		return __( '2 分钟', 'woocommerce' );
	}
}

在定义了您的自定义任务类之后,通过在 TaskLists 类上调用 add_task 方法,将其添加到任务列表中。 请注意,您需要在 init 钩子之前或在 init 钩子中调用 add_task 方法,因为引导任务是在 init 钩子中注册的。

# 注册任务。
function register_custom_task() {
    // 注册任务。
    use Automattic\WooCommerce\Admin\Features\OnboardingTasks\TaskLists;

    TaskLists::add_task(
        'extended', // 任务列表 ID(例如,'extended' 表示“接下来要做的”。)
        new MyCustomTask(
            TaskLists::get_list( 'extended' ) // 获取任务列表对象。
        )
    );
}

// 将注册函数挂载到 'init' 动作。
add_action('init', 'register_custom_task');

TaskList 类表示一个任务列表。 它包含用于管理任务列表的属性和方法。 我们当前有三个预定义的任务列表:

  • setup: 默认任务列表
  • extended: “接下来要做的”任务列表
  • secret_tasklist: “秘密”任务列表,用于具有通过其他方式访问的任务。

使用 JavaScript 添加任务

除了在 PHP 中注册任务之外,您还需要使用 JavaScript 构建任务组件,设置其配置,并将它添加到任务列表中。 例如,一个简单任务的 JavaScript 文件可能如下所示:

import { createElement } from '@wordpress/element';
import {
	WooOnboardingTask,
	WooOnboardingTaskListItem,
} from '@woocommerce/onboarding';
import { registerPlugin } from '@wordpress/plugins';

const Task = ( { onComplete, task, query } ) => {
	// 在此处实现您的任务 UI/功能。
	return <div></div>;
};

registerPlugin( 'add-task-content', {
	render: () => (
		<WooOnboardingTask id="my-task">
			{ ( { onComplete, query, task } ) => (
				<Task onComplete={ onComplete } task={ task } query={ query } />
			) }
		</WooOnboardingTask>
	),
} );

registerPlugin( 'add-task-list-item', {
	scope: 'woocommerce-tasks',
	render: () => (
		<WooOnboardingTaskListItem id="my-task">
			{ ( { defaultTaskItem: DefaultTaskItem } ) => (
				// 在默认任务项目周围添加一个自定义包装器。
				<div
					className="woocommerce-custom-tasklist-item"
					style={ {
						border: '1px solid red',
					} }
				>
					<DefaultTaskItem />
				</div>
			) }
		</WooOnboardingTaskListItem>
	),
} );

在上面的示例中,该扩展程序执行了几个不同的操作。 让我们分解一下:

处理导入

首先,从外部依赖项导入任何函数、组件或其他实用程序。

import { createElement } from '@wordpress/element';
import {
	WooOnboardingTask,
	WooOnboardingTaskListItem,
} from '@woocommerce/onboarding';
import { registerPlugin } from '@wordpress/plugins';

创建组件

接下来,我们创建一个 功能组件,该组件返回我们的任务卡片。 我们在这里使用的混合 JavaScript/HTML 语法称为 JSX。 如果您不熟悉它,您可以 在 React 文档中阅读更多相关信息。

import { onboardingStore } from '@woocommerce/data';
import { useDispatch } from '@wordpress/data';

const Task = ( { onComplete, task } ) => {
	const { actionTask } = useDispatch( onboardingStore );
	const { isActioned } = task;

	return (
		<Card className="woocommerce-task-card">
			<CardBody>
				{ __(
					"此任务的完成状态取决于是否已执行操作。 下方的操作按钮将执行此任务,而完成按钮将在任务列表中乐观地完成任务,并重定向回任务列表。 请注意,在此示例中,任务必须先执行操作才能持久化完成状态。",
					'plugin-domain'
				) }{ ' ' }
				<br />
				<br />
				{ __( '任务执行状态:', 'plugin-domain' ) }{ ' ' }
				{ isActioned ? '已执行' : '未执行' }
				<br />
				<br />
				<div>
					<button
						onClick={ () => {
							actionTask( 'my-task' );
						} }
					>
						{ __( '执行任务', 'plugin-domain' ) }
					</button>
					<button onClick={ onComplete }>
						{ __( '完成', 'plugin-domain' ) }
					</button>
				</div>
			</CardBody>
		</Card>
	);
};

在上面的示例中,我们使用 Card 和 CardBody 组件来构建任务组件。 CardBody 内部的 div 使用 JavaScript 表达式 ({}) 嵌入一个三元运算符,该运算符使用组件的状态来确定是将任务显示为已完成或未完成。

注册插件以添加任务内容

接下来,我们使用 SlotFills 将 Task 组件注册为名为 "add-task-content" 的插件。 此插件将 Task 组件嵌套在 WooOnboardingTask 组件中,并传递必要的属性。 我们还将插件的范围指定为 "woocommerce-tasks",使其仅在 WooCommerce 的任务列表中有效。

registerPlugin( 'add-task-content', {
	render: () => (
		
			{ ( {
				onComplete,
				// eslint-disable-next-line @typescript-eslint/no-unused-vars
				query,
				task,
			} ) =>  }
		
	),
	scope: 'woocommerce-tasks',
} );

注册插件以自定义任务列表项目

最后,我们注册另一个名为 "my-task-list-item-plugin" 的插件。该插件用于自定义任务列表项目的外观。它还针对 WooCommerce 的任务列表,并将 DefaultTaskItem 组件包装在具有附加样式的自定义包装器中。

registerPlugin( 'my-task-list-item-plugin', {
  scope: 'woocommerce-tasks',
  render: () => (
    <WooOnboardingTaskListItem id="my-task">
      { ( { defaultTaskItem: DefaultTaskItem } ) => (
        // 在默认任务项目周围添加一个自定义包装器。
        <div
          className="woocommerce-custom-tasklist-item"
          style={ {
            border: '1px solid red',
          } }
        >
          <DefaultTaskItem />
        </div>
      ) }
    </WooOnboardingTaskListItem>
  ),
} );

总而言之,用于简单任务的 JavaScript 文件扩展并自定义了 WooCommerce 任务列表的功能,允许用户更好地管理任务并个性化任务列表项目的外观。

使用 JavaScript 注册任务

除了在 PHP 中注册任务之外,您还需要注册并加载包含您的任务组件及其配置的编译后的 JavaScript 文件。一种常见的方法是创建一个专用的注册函数,该函数挂接到 WordPress 中的 admin_enqueue_scripts 动作。以下是一个带有注释的示例,说明此注册可能的样子:

/**
 * 注册脚本以填充前端的任务内容。
 */
function add_task_register_script() {
	if (
		! class_exists( 'Automattic\WooCommerce\Internal\Admin\Loader' ) ||
		! \Automattic\WooCommerce\Admin\PageController::is_admin_or_embed_page()
	) {
		return;
	}

	$asset_file = require __DIR__ . '/dist/index.asset.php';
	wp_register_script(
		'add-task',
		plugins_url( '/dist/index.js', __FILE__ ), // 任务注册 JS
		$asset_file['dependencies'],
		$asset_file['version'],
		true
	);

	wp_enqueue_script( 'add-task' );
}

add_action( 'admin_enqueue_scripts', 'add_task_register_script' );

通过遵循这些步骤,您的自定义任务应该会出现在 WooCommerce 的引导任务列表中。

要查看一个完整的示例,了解如何将自定义任务作为 WordPress 插件添加,您可以查看 add-task 示例目录。

要了解更多关于任务列表的信息,您可以参考 任务列表文档。

使用商店管理链接

当商家完成所有入职任务列表中的项目时,WooCommerce 会将其替换为包含一系列实用商店管理链接的部分。由于扩展的可见性可能是一个挑战,因此此部分是突出扩展的关键功能并帮助商家导航到这些功能的好方法。

商店管理部分具有相对较窄的用途,因此该部分目前不支持外部链接。 相反,它旨在快速在 WooCommerce 中导航。

添加您自己的商店管理链接是一个简单的过程,涉及:

  • 安装支持图标的依赖项
  • 在您的 PHP 代码中注册一个管理脚本
  • 通过 JavaScript 过滤器进行钩入,以提供您的链接对象

安装 Icons 包

商店管理链接使用 @wordpress/icons 包。 如果您的扩展尚未使用它,则需要将其添加到您扩展的依赖项列表中。

npm install @wordpress/icons --save

注册 JavaScript

将您的自定义链接添加到商店管理部分的代码将位于一个 JavaScript 文件中。 我们将在我们的 PHP 文件中向 WordPress 注册并加载该文件:

function custom_store_management_link() {
    wp_enqueue_script(
        'add-my-custom-link',
        plugins_url( '/dist/add-my-custom-link.js', __FILE__ ),
        array( 'wp-hooks' ),
        10
    );
}
add_action( 'admin_enqueue_scripts', 'custom_store_management_link' );

此调用的第一个参数是句柄,即 WordPress 将用于引用我们正在注册的脚本的名称。 第二个参数是脚本所在的 URL。

第三个参数是一个数组,表示脚本依赖项。 通过在数组中提供 wp-hooks 句柄,我们确保我们的脚本可以访问我们将使用的 addFilter 函数,该函数用于将我们的链接添加到 WooCommerce 的列表中。

第四个参数是优先级,它确定 WordPress 中 JavaScript 加载的顺序。 在我们的示例中,我们将优先级设置为 10。 重要的是,您的脚本在商店管理部分呈现之前运行。 考虑到这一点,请确保您的优先级值低于 15,以确保您的链接正确显示。

通过 JavaScript 提供您的链接

最后,在您上面注册的 JavaScript 文件中,钩入 woocommerce_admin_homescreen_quicklinks 过滤器,并以一个简单的 JavaScript 对象的形式提供您的任务。

import { megaphone } from '@wordpress/icons';
import { addFilter } from '@wordpress/hooks';
 
addFilter(
    'woocommerce_admin_homescreen_quicklinks',
    'my-extension',
    ( quickLinks ) => {
        return [
            ...quickLinks,
            {
                title: 'My link',
                href: 'link/to/something',
                icon: megaphone,
            },
        ];
    }
);

使用管理提示

管理提示旨在显示关于您的 WooCommerce 商店、扩展、活动和成就的有用信息。 它们也适用于显示可以帮助您完成日常管理和优化商店的任务的信息。 一个好的通用规则是,将管理提示用于以下类型的信息:

  1. 及时性
  2. 相关性
  3. 实用性

考虑到这一点,您可能希望使用管理提示来庆祝商家已经达成的某个重要里程碑,或者提供有关如何使用特定功能或流程的更多指导。 另一方面,您不应使用管理提示来发送关于同一主题的重复消息,也不应向所有用户发送仅对商店****子集的商家相关的提示。 可以在管理提示中进行特定促销活动,但请勿滥用该系统。 请根据您的最佳判断,记住主屏幕的目的是突出商店最重要的可操作任务。

尽管管理提示是 WooCommerce 中新的基于 React 的界面体验的一部分,但它们可以通过标准的 PHP 界面提供给开发者。

使用管理提示的推荐方法是将您的提示封装在自己的类中,该类使用 WooCommerce 管理中包含的 NoteTraits 特性。 以下是一个简单的示例,说明其外观:

# 示例笔记提供器

该插件添加一条带有时间戳的笔记,显示该笔记添加的时间。

```php
<?php
/**
 * Simple note provider
 *
 * Adds a note with a timestamp showing when the note was added.
 */

namespace My\Wonderfully\Namespaced\Extension\Area;

// Exit if this code is accessed outside of WordPress.
defined ( 'ABSPATH' ) || exit;

// Check for Admin Note support
if ( ! class_exists( 'Automattic\WooCommerce\Admin\Notes\Notes' ) ||
     ! class_exists( 'Automattic\WooCommerce\Admin\Notes\NoteTraits' )) {
    return;
}

// Make sure the WooCommerce Data Store is available
if ( ! class_exists( 'WC_Data_Store' ) ) {
    return;
}


/**
 * Example note class.
 */
class ExampleNote {

    // Use the Note class to create Admin Note objects
    use Automatic\WooCommerce\Admin\Notes\Note;

    // Use the NoteTraits trait, which handles common note operations.
    use Automatic\WooCommerce\Admin\Notes\NoteTraits;

    // Provide a note name.
    const NOTE_NAME = 'my-prefix-example-note';

    public static function get_note() {
    // Our welcome note will include information about when the extension
    // was activated.  This is just for demonstration. You might include
    // other logic here depending on what data your note should contain.
        $activated_time = current_time( 'timestamp', 0 );
        $activated_time_formatted = date( 'F jS', $activated_time );

        // Instantiate a new Note object
        $note = new Automattic\WooCommerce\Admin\Notes\Note();

        // Set our note's title.
        $note->set_title( '开始使用' );

        // Set our note's content.
        $note->set_content(
            sprintf(
                '插件已于 %s 激活。', $activated_time_formatted
            )
        );

        // In addition to content, notes also support structured content.
        // You can use this property to re-localize notes on the fly, but
        // that is just one use. You can store other data here too. This
        // is backed by a longtext column in the 数据库.
        $note->set_content_data( (object) array(
            'getting_started'       => true,
            'activated'             => $activated_time,
            'activated_formatted'   => $activated_time_formatted
        ) );

        // Set the type of the note. Note types are defined as enum-style
        // constants in the Note class. Available note types are:
        // error, warning, update, info, marketing.
        $note->set_type( Note::E_WC_ADMIN_NOTE_INFORMATIONAL );

        // Set the type of layout the note uses. Supported layout types are:
        // 'plain', 'thumbnail'
        $note->set_layout( 'plain' );

        // Set the image for the note. This property renders as the src
        // attribute for an img tag, so use a string here.
        $note->set_image( '' );


        // Set the note name and source.  You should store your extension's
        //   name (别名) in the source property of the note.  You can use
        //   the name property of the note to support multiple sub-types of
        //   notes.  This also gives you a handy way of namespacing your notes.
        $note->set_source( 'inbox-note-example');
        $note->set_name( self::NOTE_NAME );

        // Add action buttons to the note.  A note can support 0, 1, or 2 actions.
        //   The first parameter is the action name, which can be used for event handling.
        //   The second parameter renders as the label for the button.
        //   The third parameter is an optional URL for actions that require navigation.
        $note->add_action(
            'settings', '打开设置', '?page=wc-settings&tab=general'
        );
        $note->add_action(
            'learn_more', '了解更多', 'https://example.com'
        );

        return $note;
    }
}

function my_great_extension_activate() {
    // This uses the functionality from the NoteTraits trait to conditionally add your note if it passes all of the appropriate checks.
    ExampleNote::possibly_add_note();
}
register_activation_hook( __FILE__, 'my_great_extension_activate' );

function my_great_extension_deactivate() {
    // This uses the functionality from the NoteTraits trait to conditionally remove your note if it passes all of the appropriate checks.
    ExampleNote::possibly_delete_note();
}
register_deactivation_hook( __FILE__, 'my_great_extension_deactivate' );

拆解

让我们分解上面的示例,以了解每个部分的作用。

命名空间和功能可用性检查

首先,我们进行一些基本的命名空间和功能可用性检查,并添加一个安全措施,以确保此文件仅在 WordPress 应用程序空间内执行。

namespace My\Wonderfully\Namespaced\Extension\Area;
 
defined ( 'ABSPATH' ) || exit;
 
if ( ! class_exists( 'Automattic\WooCommerce\Admin\Notes\Notes') ||
     ! class_exists( 'Automattic\WooCommerce\Admin\Notes\NoteTraits') ) {
    return;
}
 
if ( ! class_exists( 'WC_Data_Store' ) ) {
    return;
}

使用 Note 和 NoteTraits 对象

接下来,我们定义一个简单的类,该类将作为我们通知的提供者。为了创建和管理通知对象,我们将从 WooCommerce Admin 导入 Note 和 NotesTraits 类。

class ExampleNote {
 
    use Automatic\WooCommerce\Admin\Notes\Note;
    use Automatic\WooCommerce\Admin\Notes\NoteTraits;
 
}

提供一个唯一的通知名称

在继续之前,创建一个名为 NOTE_NAME 的常量,并为其分配一个唯一的通知名称。NoteTraits 类使用此常量进行查询和通知操作。

const NOTE_NAME = 'my-prefix-example-note';

配置笔记的详情

在设置了笔记的名称后,您可以定义和配置您的笔记。 NoteTraits 类将在执行操作时调用 self::get_note(),因此您应该将笔记的实例化和配置封装在一个名为 get_note() 的静态函数中,该函数返回一个 Note 对象。

public static function get_note() {
    // 我们将在此处填充逻辑,用于实例化一个 Note 对象
    //   并设置其属性。
}

在我们的 get_note() 函数中,我们将处理任何用于收集 Note 可能需要的数据的逻辑。 我们的示例笔记将包含有关扩展何时激活的信息,因此这部分代码仅用于演示。 您可能在此处包含其他逻辑,具体取决于您的笔记应该包含哪些数据。

$activated_time = current_time( 'timestamp', 0);
$activated_time_formatted = date( 'F jS', $activated_time );

接下来,我们将实例化一个新的 Note 对象。

$note = new Note();

一旦我们拥有 Note 类的实例,我们就可以使用其 API 来设置其属性,首先是标题。

$note->set_title( 'Getting Started' );

然后,我们将使用上面收集的一些时间戳数据来设置笔记的内容。

$note->set_content(
    sprintf(
        'Extension activated on %s.', $activated_time_formatted
    )
);

除了常规内容之外,笔记还支持使用 content_data 属性的结构化内容。 您可以使用此属性动态地重新定位笔记,但这只是一个用例。 您也可以在此处存储其他数据。 这由数据库中的一个 longtext 列支持。

$note->set_content_data( (object) array(
    'getting_started'     => true,
    'activated'           => $activated_time,
    'activated_formatted' => $activated_time_formatted
) );

接下来,我们将设置笔记的 type 属性。 笔记类型定义为 Note 类中的枚举样式类常量。 可用的笔记类型包括 error、warning、update、info 和 marketing。 在选择笔记类型时,请注意,error 和 update 会导致笔记显示为商店警报,而不是在收件箱中。 最好避免使用这些类型的笔记,除非您绝对需要。

$note->set_type( Note::E_WC_ADMIN_NOTE_INFORMATIONAL );

管理笔记还支持几种不同的布局。 您可以将 banner、plain 或 thumbnail 指定为布局。 如果您有兴趣查看不同的布局,请查看 此简单的插件,您可以安装它以进行实验。

我们将选择 plain 作为我们的布局,但它也是默认值,因此我们可以让此属性保持不变,效果相同。

$note->set_layout( 'plain' );

管理员通知

如果您想向您的管理员通知中添加图像,可以使用 set_image 函数指定它。 此属性最终会作为 img 标签的 src 属性呈现,因此请在此处使用一个 字符串。

$note->set_image( '' );

接下来,我们将设置管理员通知的 name 和 source 属性的 值。 最佳实践是,应将您的扩展程序的名称(即其 别名)存储在通知的 source 属性中。 您可以使用 name 属性来支持多种类型的通知。 这为您提供了一种方便的方法来命名您的通知,并在高层和底层进行管理。

$note->set_source( 'inbox-note-example');
$note->set_name( self::NOTE_NAME );

管理员通知可以支持 0 个、1 个或 2 个 操作(按钮)。 您可以使用这些 操作 来捕获触发异步过程的事件,或者帮助商家导航到特定的视图以完成某个步骤,或者仅仅提供指向外部网站的 链接,以获取更多 信息。 add_action() 函数最多可以接受三个 参数。 第一个参数是 操作 名称,可用于事件处理;第二个参数是 操作 按钮的 标签;第三个参数是可选的 URL,用于需要导航的 操作。

$note->add_action(
    'settings', 'Open Settings', '?page=wc-settings&tab=general'
);
$note->add_action(
    'learn_more', 'Learn More', 'https://example.com'
);

最后,请务必让 get_note() 函数返回配置的通知对象。

return $note;

添加和删除备注

要添加和删除备注,可以使用 NoteTraits 类中的辅助函数:possibly_add_note() 和其对应函数 possibly_delete_note()。 这些函数将处理与备注管理相关的重复逻辑,并且还会进行检查,以帮助您避免创建重复的备注。

我们的示例扩展通过将这些调用绑定到激活和停用钩子来实现,以简化操作。 虽然有很多事件您可能希望向商家的收件箱添加备注,但停用和卸载时删除备注是管理您的扩展生命周期的重要组成部分。

function my_great_extension_activate() {
    ExampleNote::possibly_add_note();
}
register_activation_hook( __FILE__, 'my_great_extension_activate' );
 
function my_great_extension_deactivate() {
    ExampleNote::possibly_delete_note();
}
register_deactivation_hook( __FILE__, 'my_great_extension_deactivate' );