嵌入编辑器与通知事件

父页面只需嵌入 iframe 并监听通知事件。平台不负责接入方数据存储,也不会向接入方服务器主动回调。

嵌入 iframe

<iframe
  id="qm-resume-editor"
  src="创建会话返回的 editorUrl"
  style="width: 100%; height: 100vh; border: 0;"
></iframe>

安全监听模板

var editorFrame = document.getElementById("qm-resume-editor");

window.addEventListener("message", function (event) {
  // 校验发送域
  if (event.origin !== "https://www.qmjianli.com") return;
  // 校验确实来自当前 iframe,而不是页面里其他窗口
  if (event.source !== editorFrame.contentWindow) return;

  var message = event.data;
  if (!message || message.source !== "QM_RESUME_EDITOR") return;

  switch (message.event) {
    case "ready":
      console.log("编辑器已就绪");
      break;
    case "saved":
      // 自动保存成功后即返回完整 JSON,接入方应同步保存草稿
      saveResumeDraft(message.externalResumeId, message.resumeData);
      break;
    case "exported":
      console.log("本次 PDF 地址", message.downloadUrl);
      break;
    case "diagnosed":
      console.log("诊断报告 PDF 地址", message.downloadUrl);
      break;
    case "billing_consumed":
      console.log("扣费成功,会话剩余(分)", message.sessionBalanceCents);
      break;
    case "session_balance_insufficient":
      showUserPayment(message.requiredAmountCents);
      break;
    case "developer_balance_insufficient":
      alert("开发者账户余额不足,请联系管理员充值");
      break;
  }
});

事件字段

event触发时机主要字段
ready编辑器加载完成sessionId, externalResumeId
saved草稿自动保存成功resumeData, sessionId, externalResumeId, version
exportedPDF 同步生成成功downloadUrl, expiresAt, externalResumeId
diagnosedAI 诊断报告生成成功downloadUrl, expiresAt, externalResumeId
billing_consumed一次收费操作成功并确认双扣action, requestId, amountCents, sessionBalanceCents, developerBalanceCents
session_balance_insufficient当前会话额度不足action, requiredAmountCents, sessionBalanceCents
developer_balance_insufficient开发者账户余额不足action, requiredAmountCents, developerBalanceCents
photo_createdAI 证件照生成成功photoUrl, expiresAt, temporary

saved 事件示例

{
  "source": "QM_RESUME_EDITOR",
  "event": "saved",
  "sessionId": "S...",
  "externalResumeId": "R10001",
  "version": 5,
  "resumeData": {
    "setData": { "tplId": 1013 },
    "basicInfo": { "name": "张三" },
    "moduleData": []
  }
}
saved 表示平台临时草稿保存成功,并把同一份完整 JSON 通知给父页面;不表示接入方已经保存成功。接入方应自行处理保存状态和失败重试。
resumeData.basicInfo.photohttps://www.qmjianli.com/api_open/v1/id-photo-files/... 这类平台临时地址,接入方应立即下载并转存到自己的对象存储,再把该字段替换成自己的照片 URL 后入库。下次创建会话时传入替换后的地址。

增加额度后通知 iframe

服务端调用会话充值接口成功后,父页面通知 iframe 重新拉取余额:

editorFrame.contentWindow.postMessage({
  source: "QM_RESUME_HOST",
  event: "balance_updated"
}, "https://www.qmjianli.com");

iframe 会校验父页面 Origin 是否等于创建会话时的 parentOrigin。即使没有发送该通知,下一次收费操作也会以服务端余额为准;该消息主要用于立即刷新编辑器里的额度展示。

自动保存说明

编辑器约 1 秒防抖后,把草稿临时放在平台 Redis,并通过 saved 携带完整 JSON 给父页面。接入方应以此事件实时保存草稿;平台不会替接入方永久保存。

Origin 约束

iframe 只向会话中的 parentOrigin 发送消息。该值在创建会话时已经与应用白名单比对。若实际嵌入页面换了协议、域名或端口,父页面将收不到通知。

全民简历开放平台 · 与个人简历账号完全独立