草稿

Payload 的 Draft(草稿)功能基于 Versions(版本)功能构建,允许你对 collection 文档和 globals 进行更改,但仅在准备就绪时发布。这一功能让你能够为数据构建强大的预览环境,在发布文档前确保更改效果符合预期。

草稿功能需要启用 Versions 才能正常工作。

通过启用带草稿的 Versions,你的 collections 和 globals 可以维护文档的_更新_且_未发布_版本。这非常适合需要处理文档、更新并保存进度,但不一定立即公开发布的情况。在构建预览实现时,草稿功能极为有用。

Drafts Enabled 如果启用了草稿功能,常规的保存按钮会被替换为新的操作选项,允许你保存草稿或直接发布更改。

选项

Collections 和 Globals 都支持相同的配置选项来启用草稿功能。你可以将 versions.drafts 设为 true,或者传入一个对象来配置草稿属性。

草稿选项描述
autosave启用 autosave 可以在编辑文档时自动保存进度。设置为 true 或传入包含选项的对象来启用。
schedulePublish允许编辑者安排未来的发布/取消发布事件。了解更多
validatevalidate 设为 true 可以在保存时验证草稿文档。默认为 false

数据库变更

在 collection 或 global 上启用草稿功能后,Payload 会自动向你的 schema 中注入一个新字段 _status_status 字段由 Payload 内部使用,用于存储文档是处于 draft 还是 published 状态。

Admin UI 状态指示

在 Admin UI 中,如果启用了草稿功能,文档会显示以下三种"状态"之一:

  1. 草稿 - 如果文档从未发布过,且只存在草稿版本
  2. 已发布 - 如果文档已发布且没有更新的草稿可用
  3. 已变更 - 如果文档已发布,但存在尚未发布的新草稿版本

草稿 API

如果在你的 collection 或 global 上启用了草稿功能,REST、GraphQL 和 Local API 都会发生重要且强大的变化,允许你指定是与草稿还是已发布的文档进行交互。

更新或创建草稿

如果在 collection 或 global 上启用了草稿功能,REST、GraphQL 和 Local API 的 createupdate 操作会暴露一个名为 draft 的新选项,允许你指定是在创建/更新草稿,还是直接将更改发送到已发布的文档。例如,如果你向 REST 的 createupdate 操作传递查询参数 ?draft=true,你的操作将被视为创建 draft 而非已发布的文档。默认情况下,draft 参数设置为 false

必填字段

如果在创建或更新文档时启用了 draft,所有字段都将被视为非必填,这样你就可以保存不完整的草稿。

读取草稿与已发布文档

除了 createupdate 操作中的 draft 参数外,findfindByID 操作也暴露了 draft 参数。

如果在读取文档时将 draft 设置为 truePayload 会自动用最新的草稿替换返回的文档(如果有更新的草稿可用)。

例如,考虑以下场景:

  1. 你创建了一个新的 collection 文档并立即发布
  2. 然后你进行了一些更新,并将这些更新保存为草稿
  3. 接着你又做了一些进一步的更新,并保存为另一个草稿

在这种情况下,你的主 collection 中将有一个已发布的文档,同时在 _[collectionSlug]_versions 数据库 collection 中会有两个更新的草稿。

如果你只是通过 findfindByID 操作获取创建的文档,系统会返回已发布的文档,而草稿将被忽略。

但是,如果你将 draft 参数设为 true,Payload 会自动用最近保存的 version 内容替换已发布文档的内容。在上述场景中,由于我们创建了两个版本,Payload 会返回最新(第二个)草稿的数据,你的文档将显示为最近保存的草稿版本,而不是已发布的版本。

重要提示: 单独的 draft 参数不会阻止 API 返回 _status: 'draft' 的文档。你需要使用访问控制来防止未认证用户获取 _status: 'draft' 的文档。阅读下文了解具体实现方式。

控制谁可以查看 Collection 草稿

如果你使用草稿功能,必须考虑谁可以查看草稿,谁只能查看已发布的文档。幸运的是,Payload 使这一过程变得极其简单,并将控制权完全交到你手中。

限制草稿访问权限

你可以使用 read 访问控制 方法来限制谁可以查看文档的草稿版本,只需返回一个查询约束来限制任何给定用户可以检索的文档范围。

以下是一个利用 _status 字段要求用户必须登录才能检索草稿的示例:

import type { CollectionConfig } from 'payload'

export const Pages: CollectionConfig = {
  slug: 'pages',
  access: {
    read: ({ req }) => {
      // 如果有用户登录
      // 允许他们检索所有文档
      if (req.user) return true

      // 如果没有用户登录
      // 限制返回的文档范围
      // 仅返回 `_status` 等于 `published` 的文档
      return {
        _status: {
          equals: 'published',
        },
      }
    },
  },
  versions: {
    drafts: true,
  },
  //.. Pages 配置的其余部分
}

关于向现有集合添加版本功能的注意事项

如果你已经有一个包含文档的集合,并且在已有文档之后才_启用_草稿功能,那么所有旧文档在重新保存之前_都不会有 _status 字段_。因此,如果你正在_向现有集合添加_版本功能,你可能需要编写访问控制函数来允许用户读取以下两种情况:

_status 等于 "published" 以及

_status 不存在

以下是一个编写访问控制函数的示例,该函数既允许访问 _status 等于 "published" 的文档,也允许访问 _status 不存在的文档:

import type { CollectionConfig } from 'payload'

export const Pages: CollectionConfig = {
  slug: 'pages',
  access: {
    read: ({ req }) => {
      // 如果有用户登录
      // 允许他们检索所有文档
      if (req.user) return true

      // 如果没有用户
      // 限制返回的文档
      // 仅返回 `_status` 等于 `published`
      // 或 `_status` 不存在的文档
      return {
        or: [
          {
            _status: {
              equals: 'published',
            },
          },
          {
            _status: {
              exists: false,
            },
          },
        ],
      }
    },
  },
  versions: {
    drafts: true,
  },
  //.. 此处是 Pages 配置的其余部分
}

定时发布

Payload 提供了在未来定时发布/取消发布的功能,这在需要设置某些文档在未来特定日期"上线",或者反过来在特定时间后恢复为草稿状态时非常有用。

你可以通过 versions.drafts.schedulePublish: true 属性在 collections 和 globals 上启用此功能。

重要: 如果你要启用定时发布/取消发布功能, 需要确保你的 Payload 应用已配置好处理 Jobs。此功能通过在后台创建 Job 来工作, 当 job 可用时会被执行。如果你没有设置任何运行 jobs 的机制, 你的定时发布/取消发布 jobs 将永远不会被执行。

取消发布草稿

如果文档已发布,Payload 管理界面会在侧边栏顶部显示"取消发布"按钮,该按钮会将当前已发布的文档"取消发布"。可以将其视为将文档"回退"到草稿状态的一种方式。在 API 层面,这只需将文档的 _status 设置为 'draft' 即可实现。

恢复到已发布状态

如果文档已发布,并且你进行了进一步修改并保存为草稿,Payload 会在侧边栏顶部显示"恢复到已发布版本"按钮,允许你放弃草稿更改并"回退"到文档的已发布状态。你的草稿仍会被保存,但会创建一个反映文档最后发布状态的新版本。