You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Keystone 6内容版本控制功能咨询及手动实现建议

Keystone 6 内容版本控制实现方案

Keystone 6 确实没有内置的内容版本控制功能,官方文档也未提供相关配置选项,目前社区相关资源较少。以下是手动实现内容版本控制的可行方案:

1. 新增版本关联实体

创建一个与目标实体(如BlogPost)关联的版本实体,用于存储历史版本的完整内容及元数据:

import { list } from '@keystone-6/core';
import { text, relationship, timestamp, select } from '@keystone-6/core/fields';

// 历史版本实体
export const BlogPostVersion = list({
  fields: {
    post: relationship({ ref: 'BlogPost.versions' }), // 关联原博文
    title: text({ validation: { isRequired: true } }),
    content: text({ ui: { displayMode: 'textarea' } }),
    versionNumber: select({ 
      options: ['1.0', '1.1', '2.0'], 
      defaultValue: '1.0' 
    }),
    createdAt: timestamp({ defaultValue: { kind: 'now' } }),
    createdBy: relationship({ ref: 'User' }), // 记录操作人
    status: select({ 
      options: ['draft', 'published', 'archived'], 
      defaultValue: 'draft' 
    })
  },
});

// 修改原BlogPost实体,添加版本关联
export const BlogPost = list({
  fields: {
    title: text({ validation: { isRequired: true } }),
    content: text({ ui: { displayMode: 'textarea' } }),
    currentVersion: relationship({ ref: 'BlogPostVersion' }), // 标记当前使用的版本
    versions: relationship({ ref: 'BlogPostVersion.post', many: true }) // 关联所有历史版本
  },
});

2. 利用钩子自动生成版本

在目标实体的update钩子中,检测内容变更并自动创建新的版本记录,同时更新当前版本关联:

export const BlogPost = list({
  fields: { /* 上述字段定义 */ },
  hooks: {
    afterUpdate: async ({ context, item, originalItem }) => {
      // 仅当核心内容(标题/正文)变更时创建新版本
      if (item.title !== originalItem.title || item.content !== originalItem.content) {
        // 查询当前最大版本号,自动生成新版本号(示例逻辑)
        const existingVersions = await context.db.BlogPostVersion.findMany({
          where: { post: { id: item.id } },
          orderBy: { createdAt: 'desc' },
          take: 1
        });
        const newVersionNumber = existingVersions.length 
          ? (parseFloat(existingVersions[0].versionNumber) + 0.1).toFixed(1)
          : '1.0';

        // 创建新版本
        const newVersion = await context.db.BlogPostVersion.createOne({
          data: {
            post: { connect: { id: item.id } },
            title: item.title,
            content: item.content,
            versionNumber: newVersionNumber,
            createdBy: context.session?.itemId 
              ? { connect: { id: context.session.itemId } }
              : undefined,
            status: 'published'
          }
        });

        // 更新当前版本指向新记录
        await context.db.BlogPost.updateOne({
          where: { id: item.id },
          data: { currentVersion: { connect: { id: newVersion.id } } }
        });
      }
    }
  }
});

3. 实现版本切换功能

  • 查看历史版本:通过查询BlogPost的versions关联字段,获取所有历史版本列表,在UI中展示版本号、创建时间、操作人等信息。
  • 切换版本:选择目标版本后,将该版本的title和content复制回BlogPost的当前字段,同时更新currentVersion关联到选中的版本。如果需要保留当前状态,也可以仅在前端展示选中版本的内容,不修改原实体。

4. UI 优化建议

利用Keystone的自定义UI组件能力,在BlogPost详情页添加版本管理模块:

  • 在fields配置中为versions字段指定自定义组件,展示版本列表及操作按钮(查看、切换、删除)。
  • 可以添加版本对比功能,通过比较不同版本的内容差异,帮助用户快速识别变更点。

注意事项

  • 性能控制:如果内容量大或版本数量多,建议限制保留的版本数量(如仅保留最近10个版本),或对旧版本进行归档存储。
  • 审计追踪:通过context.session记录操作人,配合createdAt字段,实现完整的版本变更审计。
  • 版本号策略:可以根据业务需求选择递增数字、时间戳或语义化版本号,避免手动输入错误。

内容的提问来源于stack exchange,提问作者ptas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 10:10:28