Skip to content

应用壳功能与配置参考

应用壳(@atomm-developer/generator-workbench)是标准生成器推荐使用的官方宿主壳层。它把 SDK 的平台能力和你的生成器挂载进统一的标准壳层 UI。

新来的开发者? 先读 核心概念 建立心智模型,再按 快速接入教程 一步步操作。

壳层能力总览

接入流程

按下列顺序初始化应用壳,顺序不能调换:

  1. 初始化 GeneratorSDK
  2. 调用 defineGeneratorWorkbench() 注册自定义元素(CDN 方式从 window.GeneratorWorkbench.defineGeneratorWorkbench() 取,调用必须执行——CDN 不会自动注册)
  3. sdk、生成器接入对象和 config 赋值给 <generator-workbench> 实例
  4. 调用 mount()

生命周期事件

事件触发时机
workbench-shell-ready应用壳 UI 和 workspace 宿主可见
workbench-runtime-ready生成器挂载完成
workbench-ready兼容旧宿主,与 workbench-runtime-ready 同步派发

readyPolicy

readyPolicy 控制 mount() Promise 何时 resolve:

  • 'runtime-ready'(默认):等生成器挂载完成后 resolve
  • 'shell-ready':在应用壳 UI 渲染完成后立即 resolve,生成器挂载继续在后台进行

分阶段 Loading 示例

ts
const pageLoading = document.querySelector('#page-loading')
const workspaceSkeleton = document.querySelector('#workspace-skeleton')

workbench.config = {
  title: 'Frame Generator',
  mode: 'shell',
  readyPolicy: 'shell-ready',
}

workbench.addEventListener('workbench-shell-ready', () => {
  pageLoading?.remove()
  workspaceSkeleton?.removeAttribute('hidden')
})

workbench.addEventListener('workbench-runtime-ready', () => {
  workspaceSkeleton?.setAttribute('hidden', 'true')
})

await workbench.mount()

推荐实践

  • workbench-shell-ready 时移除页面级 loading
  • workbench-runtime-ready 之前,让 workspace 区域保留局部 skeleton
  • 如果生成器挂载失败,监听 workbench-error / config.onError,及时移除 skeleton 并切到错误态

性能标记

标记打点时机
generator-workbench:mount:startmount() 启动
generator-workbench:shell-readyworkbench-shell-ready 同时
generator-workbench:runtime-readyworkbench-runtime-ready 同时
generator-workbench:ready与兼容事件 workbench-ready 同时

宿主壳模式(config.mode)

workbench.config.mode 控制应用壳如何渲染外壳框架,决定生成器被挂载到什么样的容器结构里:

模式外壳布局适合场景
shell顶栏 + 右下角 fixed 浮动导出按钮,workspace 完全交给生成器自由布局AI 生成器、已有自定义布局的生成器
full顶栏 + 经典右侧 sidebar 分栏(canvas 区 + panel 区)标准编辑器分栏布局
template隐藏顶栏,外层页面自行接管品牌区和登录入口由外层页面驱动的生成器场景

不确定选哪个?

shell 开始。它对生成器的约束最少,只提供顶栏和浮动导出按钮,整个工作区完全由你的生成器控制。

配置示例:

ts
workbench.config = {
  mode: 'shell', // 'shell' | 'full' | 'template'
  title: 'My Generator',
}

示例展示

shell 模式

保留顶部栏和右下角 fixed 导出按钮,整个 workspace 布局完全交给生成器。适合 AI 生成器或需要自定义工作区结构的生成器。

在新标签页打开 shell 示例

full 模式

保留顶部栏、右侧参数栏和侧栏底部导出区,适合需要官方标准分栏布局的生成器。

在新标签页打开 full 示例


环境配置

应用壳的环境配置分为两层:

配置项位置控制范围
GeneratorSDK.init({ env })SDK 层所有平台 API 的 base URL 以及 Passport 登录地域(US / CN)
workbench.config.atommProEnv应用壳层应用壳行为、社区模板接口路由、atomm-pro 弹窗上下文

atommProEnv 会自动从注入的 SDK 的 env 派生。 通常只需在 SDK 层设置一次 env,应用壳会自动保持同步:

ts
const sdk = GeneratorSDK.init({ appKey: 'my-generator', env: 'prod_cn' })

workbench.sdk = sdk
workbench.config = {
  // atommProEnv 不需要重复设置 —— 自动从 sdk.getEnv() 派生
}

SDK env 取值

取值API Base URL鉴权地域
prodhttps://api.xtool.comUS
prod_cnhttps://api.makeblock.comCN
prehttps://api-pre.xtool.comUS
testhttps://api-test.xtool.comUS
devhttps://api-dev.makeblock.comCN

中国正式环境(prod_cn

当 SDK env 设置为 prod_cn 时,以下应用壳行为自动生效:

  • 所有平台 API 调用走 https://api.makeblock.com
  • Passport 登录使用 CN 鉴权地域
  • 邀请入口 — 由应用壳自动隐藏,无需手动设置 invitationEnabled: false
  • Publish as Template 入口 — 由应用壳自动隐藏,无论 templateEnabled 取何值
  • 默认语言 — URL 中不含 ?lang= 时,应用壳默认使用 zh 而非 en

导出与计费(Billing & Credits)

当注入的 SDK 提供 creditsbilling 模块时,应用壳自动接管完整的导出链路,生成器不需要自己处理计费逻辑:

应用壳的自动行为:

  • 登录后在顶栏展示当前积分余额
  • 在导出按钮旁根据 sdk.billing.getUsage() 展示计费提示
  • usage.isEnabled = false 时隐藏 export-credits-hint
  • 余额不足时,先拉起充值弹窗,充值成功后继续导出
  • 真正执行导出前,先调用 sdk.billing.consume() 作为计费闸门;若返回 isBlacklisted = true,直接阻止导出并弹出错误提示
  • 走积分路径时,导出成功后调用 sdk.billing.refreshCredits()

云保存与历史记录(Cloud Save & History)

开启方式:

ts
workbench.config = {
  cloudEnabled: true,
  historyEnabled: true,
  getCloudSaveOptions(context) {
    return {
      title: 'My Generator Draft',
      snapshot: context.state,
    }
  },
}

开启后,应用壳提供以下壳层动作:

动作说明
保存草稿 按钮在顶栏显示,手动触发云保存
历史记录 按钮在顶栏显示,展示历史版本列表
workbench.saveToCloud()宿主主动调用云保存
workbench.loadHistory()宿主主动加载历史列表

封面来源的优先级:

  1. config.getCloudSaveOptions(...) 显式返回 cover
  2. config.getCloudCover(...) 被调用并返回非空值
  3. 生成器在 params_change.data.cover 里带了非空值(缓存后复用)
  4. 以上均无,仍保存当前 snapshot,不携带封面

封面不是必须的

不要把「缺少 cover」当成「云保存未接入」。cover 是为草稿缩略图和历史列表提供的增强能力,不是保存业务状态的必要条件。

getCloudCover

如果已有画布导出能力,但不想重构整个 getCloudSaveOptions,可以单独提供封面钩子:

ts
import { exportCoverPreview } from './runtime/export'

workbench.config = {
  cloudEnabled: true,
  autoSaveEnabled: true,
  getCloudSaveOptions(context) {
    return {
      title: 'My Generator Draft',
      snapshot: context.state,
    }
  },
  async getCloudCover() {
    return await exportCoverPreview({ format: 'png' })
  },
}

Cloud Bootstrap 路由流程

cloudEnabled 打开时,应用壳在生成器挂载完成后会在后台评估路由引导:

  • 路由带有 gid 且已登录 → 调用 sdk.cloud.restore(gid)
  • 路由带有 gid 但未登录 → 展示轻量提示,等待用户显式登录后再绑定(不自动恢复,避免覆盖本地编辑)
  • 路由带有 templateId 但无 gid → 请求社区模板并恢复到生成器
  • 路由无 gid 且已登录 → 自动执行首次云保存,把返回的 id 写回路由
  • 路由无 gid 且未登录 → 跳过首次自动建单,等用户显式保存时再创建
  • ?mode=embed 下 → 即使 cloudEnabled: true,cloud bootstrap 也会被跳过

自动保存(Auto-Save)

同时满足以下条件时,应用壳会在生成器状态变化后做 debounce 自动保存:

ts
workbench.config = {
  cloudEnabled: true,
  autoSaveEnabled: true,
  getCloudSaveOptions(context) {
    return {
      title: 'My Generator Draft',
      snapshot: context.state,
    }
  },
}
  • 生成器必须实现 subscribe(listener) 接口
  • params_change 事件触发时,应用壳 debounce 后写入云保存
  • 如果 params_change.data.cover 带有非空值,缓存后在下次保存时自动补回

邀请弹窗(Invitation)

默认情况下,顶栏 credits 徽标左侧会显示 Earn Credits 邀请入口。接入时需要:

ts
workbench.config = {
  atommProEnv: 'prod',    // 或从 SDK env 自动派生
  atommProDomain: 'atomm',
}

注意事项:

  • 邀请入口在未登录时也会展示,点击后先调用 sdk.auth.login(),登录完成后再打开邀请弹窗
  • 隐藏邀请入口:显式传 config.invitationEnabled = false
  • 未显式传 invitationConfigKey 时,应用壳默认使用 generator_${sdk.getAppKey()}

数据分析上报(Analytics)

应用壳默认为 DownloadOpen in Studio 内置了数据分析上报,无需额外配置。如果需要自定义 payload:

ts
import { createGlowSensorsReporter } from '@atomm-developer/generator-workbench'

workbench.config = {
  analytics: {
    reporter: createGlowSensorsReporter({
      resolveExportPayload({ config, runtime, sdk }) {
        const state = runtime.getState()
        return {
          content_type: config.title,
          content_id: sdk.getAppKey?.() || '',
          element_name: String(state.params?.vars?.kerf_offset ?? ''),
          content_name: String(state.params?.vars?.material_preset ?? ''),
        }
      },
    }),
  },
}

内置 reporter 默认上报:

字段说明
事件名Generator_export
click_positiondownloadopeninstudio
scene_name默认按运行环境取 studio(Studio/XCS Electron UA)或 atomm
scene_source默认按视口宽度取 mobile< 768px)或 desktop
item_type默认取 sdk.getAppKey()
GA4 目标window.dataLayer.push(...)
Sensors 目标window.sensors.track(...)

顶栏 Publish as Template 点击时,同一个 reporter 还会上报 publishTemplateClick 事件。


Embed 模式

当 URL 带有 ?mode=embed 时,应用壳进入精简壳层模式。详见 核心概念 → 路由能力模式

iframe bridge 通信协议

?mode=embed 下应用壳自动启动 iframe bridge:

方向事件说明
iframe → 父页面generator_pageLoadedbridge ready 信号,应作为唯一的握手时机
父页面 → iframegenerator_loadTemplateData加载模板,通过 sdk.template.applyToRuntime(...) 回填
父页面 → iframegenerator_setGeneratorData恢复 snapshot,通过 runtime.setState(...) 回填到生成器
父页面 → iframegenerator_getTemplateData获取当前模板 JSON + info + cover
父页面 → iframegenerator_getFile获取导出文件(优先走 config.embedBridge.getExportData
iframe → 父页面generator_toTemplateLoadedgenerator_loadTemplateData 回执
iframe → 父页面generator_toTemplateData模板数据回传
iframe → 父页面generator_toFile导出文件回传
iframe → 父页面generator_toFileError / generator_toTemplateError错误回传

握手最佳实践:

  • generator_pageLoaded 作为唯一的 bridge ready 信号,不要用 iframe.onload
  • 父页面先缓存 generator_loadTemplateData / generator_setGeneratorData,等收到 generator_pageLoaded 后再 flush
  • 模板初始化优先使用 generator_loadTemplateData,有明确的 generator_toTemplateLoaded 回执

Embed 适配等级

等级说明验收标准
embed-basic最小接入:隐藏应用壳 chrome,启动 bridge,生成器接收模板/snapshot?mode=embed 下顶栏和导出区隐藏;生成器能通过 bridge 接收模板并 setState()
embed-canvas-only生成器只渲染画布,隐藏侧边栏/模板列表/导航包含 embed-basic 所有标准;移动端只有画布可见
embed-canvas-panel生成器支持独立 canvas + panel 挂载,宿主可分别放入不同 DOM 容器包含 embed-basic 所有标准;getPanelSchema() 支持 panelFiltertarget: 'canvas' 时不显示参数面板 UI

从哪个等级开始?

默认从 embed-basic 开始。只有当模板页需要展示来自生成器的可编辑参数面板时,才升级到 embed-canvas-panel


模板发布(Template Publish)

开启条件:templateEnabled: true。开启后,顶栏显示 Publish as Template 按钮。

点击发布按钮时,应用壳的处理流程:

  1. 确保用户已登录
  2. 从生成器的 getPanelSchema() 推导可导出的 bind.path 集合
  3. 通过 sdk.template.build(...) 生成标准模板 JSON
  4. 尝试通过 config.embedBridge.getExportData('cover', ...) 解析封面;未提供时回退到 SDK export provider
  5. 懒加载并挂载 @atomm/atomm-proPublishTemplateModal
  6. 打开发布弹窗,并传入封面、模板 JSON、生成器信息等字段

字段来源速查:

字段默认来源
generatorImagetemplate_publish_media_change.data.generatorImageoriginImageUrl → 封面 data URL
generatorTag生成器最近一次 select_template 事件 data.nameconfig.getTemplateMeta()?.generatorTag
initialData.covertemplate_publish_media_change.data.cover → 封面 data URL
generatorInfo.generatorNameconfig.getTemplateMeta()?.titleconfig.title
generatorInfo.info最新生成器状态映射到云 info 结构(由应用壳构建)
generatorInfo.templatesdk.template.build(...)

getTemplatePublishPayload

如果默认字段解析链路无法自动覆盖,使用聚合型钩子覆盖特定字段:

ts
import { exportCoverPreview } from './runtime/export'

workbench.config = {
  templateEnabled: true,
  async getTemplatePublishPayload(context) {
    const coverDataUrl = await exportCoverPreview({ format: 'png' })
    const state = context.runtime.getState()

    return {
      generatorImage: coverDataUrl,
      generatorTag: state.selectedTemplateName ?? '',
      cover: coverDataUrl,
      originImageUrl: state.originImageUrl ?? '',
    }
  },
}

应用壳把返回对象作为覆盖层叠加在现有解析链路之上。只有显式返回的字段才会被覆盖,未返回的字段继续走内置默认逻辑。

isAdminPublishTemplate

只有社区管理员才能看到发布按钮时使用:

ts
workbench.config = {
  templateEnabled: true,
  isAdminPublishTemplate: true,
}

开启后,只有 auth.userInfo.isCommunityAdmin === true 时才显示 Publish as Template 按钮。应用壳会在登录、登出、切换账号时自动刷新显隐状态。


生成器与应用壳通信

应用壳与生成器之间的核心通信机制:

  • 生成器通过 mount({ routeMode }) 读取当前路由能力模式
  • 生成器通过 runtime.subscribe(listener) 上报业务事件给应用壳
  • 应用壳通过 workbench.dispatchRuntimeCommand(...) 发送反向命令给生成器

当前内置通信行为:

事件 / 命令触发链路
state-change生成器上报 → auto-save debounce 编排
params_change生成器上报 → 派发 DOM 事件 runtime-params-change
select_template生成器上报 → 派发 DOM 事件 runtime-select-template
select_template(embed)生成器上报 → 父页面 bridge 事件 generator_toSelectTemplate

完整事件表和载荷约定,详见 应用壳与生成器通信


调试配置

开发阶段,可在控制台输出内部 payload,无需打开 DevTools 网络面板:

ts
workbench.config = {
  debug: {
    logCloudPayload: true,           // 每次保存时打印完整云保存 payload
    logTemplatePublishPayload: true, // 发布弹窗打开时打印完整模板发布 payload
    warnOnMissingTemplateFields: true, // 模板关键字段为空时输出 warning
  },
}

所有选项默认为 false。debug 配置对生产行为没有任何影响,上线前请移除或设为 false

典型使用流程:

  1. 验证云保存 snapshotcover 时,开启 logCloudPayload
  2. 验证模板发布字段时,开启 logTemplatePublishPayload
  3. 接入初期开启 warnOnMissingTemplateFields,及时发现空字段

推荐使用方式

  • 新建 Vue 生成器时,优先使用 Vue 脚手架启动开发,通过一条命令生成已接入 generator-workbench 的标准项目;需要理解目录和配置时再看 Vue 脚手架结构说明
  • 新的标准生成器优先使用应用壳来承载统一平台壳层
  • AI 生成器或快速接入生成器,优先使用 shell 模式,让生成器接管整个 workspace
  • 只有当明确需要经典右侧参数栏分栏布局时,再使用 full 模式
  • 只有当明确需要非标准壳层时,才建议绕开应用壳自行定制整页布局
  • 复杂的 iframe 宿主设置、遗留 bridge 兼容,应视为高级接入模式,而非每个生成器的默认路径

安装说明

CDN 加载行为、Vue 自动加载以及 atomm-ui 样式 / 脚本说明统一放在 安装与引入 中。

相关文档

MIT Licensed