座位图编辑器 iframe 集成指南

本指南介绍如何通过 iframe 将座位图编辑器嵌入应用,包括配置选项和通信方式。

基础 iframe 集成

iframe 可将外部应用嵌入您的 Web 应用。下文介绍嵌入方法,以及如何通过 postMessage 建立消息通信。

简单嵌入

<!DOCTYPE html>
<html>
  <head>
    <style>
      .container {
        height: 100vh;
        display: flex;
        flex-direction: column;
      }
      iframe {
        flex-grow: 1;
        border: none;
      }
    </style>
  </head>
  <body>
    <div class="container">
      <!-- create iframe using js -->
      <div class="controls">
        <button id="openModalBtn">Open in modal window</button>
        <span id="messageDisplay"></span>
      </div>

      <!-- or html -->
      <iframe src="/app/venues/2/schemas/150" width="100%" height="100%"></iframe>
    </div>
  </body>
</html>

创建包含 iframe 的弹窗

document.getElementById('openModalBtn').addEventListener('click', function () {
  const modal = document.createElement('div');
  modal.style.position = 'fixed';
  modal.style.top = '0';
  modal.style.left = '0';
  modal.style.width = '100%';
  modal.style.height = '100%';
  modal.style.backgroundColor = 'rgba(0,0,0,0.5)';

  const iframe = document.createElement('iframe');
  iframe.src = '/app/venues/2/schemas/150?hideNavbar=true';
  iframe.style.width = '95%';
  iframe.style.height = '95%';

  modal.appendChild(iframe);
  document.body.appendChild(modal);
});

座位图编辑页面配置

座位图编辑界面可通过两种主要 URL 模式访问:

/app/venues/{venueId}/schemas/{schemaId}  // Edit existing schema
/app/venues/{venueId}/schemas/new         // Create new schema

其中 venueId 为场地 ID,schemaId 为待编辑座位图 ID;使用 “new” 则创建新座位图。

使用 URL 参数自定义界面

可通过以下 URL 参数自定义编辑器界面。

1. 隐藏界面元素

使用 hidden 参数隐藏指定工具栏元素:

/app/venues/2/schemas/150?hidden=pricing,save,shape

上例会隐藏定价模式按钮、保存按钮和形状工具。

2. 隐藏导航栏

要使嵌入体验更自然,可隐藏顶部导航栏:

/app/venues/2/schemas/150?hideNavbar=true

这尤其适合 iframe 集成,界面仅保留编辑器组件。

3. 强制显示定价工具

即使定价工具默认隐藏,或通过 hidden 参数隐藏,也可强制显示:

/app/venues/2/schemas/150?showPricing=true

4. 保存时保留草稿状态

自 Editor 1.74.0 起,添加 draft=true 可在嵌入编辑器保存时保留座位图的草稿状态:

/app/venues/2/schemas/new?hideNavbar=true&draft=true

使用 hideNavbar=true&draft=true 时,发布控件仍然可用。Save 保存草稿,Publish 才对外发布。不设置 draft=true 时,在隐藏定价工具的情况下保存仍会自动发布。此选项保留当前草稿状态,不会将已发布座位图变回草稿。

5. 组合参数

可组合这些参数,定制编辑体验:

/app/venues/2/schemas/150?hideNavbar=true&hidden=save,shape&showPricing=true

完整实现示例

下面的完整示例将编辑器嵌入弹窗,并自定义界面及处理消息:

function openSchemaEditor(venueId, schemaId, options = {}) {
  // Create modal container
  const modal = document.createElement('div');
  modal.style.position = 'fixed';
  modal.style.top = '0';
  modal.style.left = '0';
  modal.style.width = '100%';
  modal.style.height = '100%';
  modal.style.backgroundColor = 'rgba(0,0,0,0.5)';
  modal.style.zIndex = '9999';
  modal.style.display = 'flex';
  modal.style.justifyContent = 'center';
  modal.style.alignItems = 'center';

  // Create close button
  const closeBtn = document.createElement('button');
  closeBtn.textContent = 'Close';
  closeBtn.style.position = 'absolute';
  closeBtn.style.top = '10px';
  closeBtn.style.right = '10px';
  closeBtn.style.zIndex = '10000';
  modal.appendChild(closeBtn);

  // Create iframe
  const iframe = document.createElement('iframe');

  // Build the base URL
  let url = `/app/venues/${venueId}/schemas/${schemaId}`;

  // Build query parameters
  const params = new URLSearchParams();

  // Hide specific UI elements if specified
  if (options.hiddenElements && options.hiddenElements.length > 0) {
    params.set('hidden', options.hiddenElements.join(','));
  }

  // Hide navbar if specified (default to true for modal)
  if (options.hideNavbar !== false) {
    params.set('hideNavbar', 'true');
  }

  // Force show pricing if specified
  if (options.showPricing) {
    params.set('showPricing', 'true');
  }

  if (options.preserveDraft) {
    params.set('draft', 'true');
  }

  // Append parameters if any exist
  if (params.toString()) {
    url += `?${params.toString()}`;
  }

  iframe.src = url;
  iframe.style.width = '95%';
  iframe.style.height = '95%';
  iframe.style.border = 'none';

  modal.appendChild(iframe);
  document.body.appendChild(modal);

  let hasUnsavedChanges = false;

  // Set up message listener for schema changes
  window.addEventListener('message', function (event) {
    // Handle schema changes
    if (event.data.type === 'SCHEMA_CHANGED') {
      console.log('Schema modified:', event.data);
      hasUnsavedChanges = event.data.hasChanges;

      // Update UI to indicate unsaved changes
      if (hasUnsavedChanges) {
        closeBtn.textContent = 'Close*';
      } else {
        closeBtn.textContent = 'Close';
      }
    }

    // Handle close confirmation response
    if (event.data.type === 'MODAL_CLOSE_RESPONSE' && event.data.canClose) {
      document.body.removeChild(modal);
    }
  });

  // Set up close button handler with confirmation
  closeBtn.addEventListener('click', function () {
    if (hasUnsavedChanges) {
      iframe.contentWindow.postMessage({ type: 'MODAL_CLOSING' }, '*');
    } else {
      document.body.removeChild(modal);
    }
  });

  // Return control functions
  return {
    close: function () {
      if (hasUnsavedChanges) {
        iframe.contentWindow.postMessage({ type: 'MODAL_CLOSING' }, '*');
      } else {
        document.body.removeChild(modal);
      }
    },
    getIframe: function () {
      return iframe;
    },
  };
}

// Example usage:
document.getElementById('openEditorBtn').addEventListener('click', function () {
  const editor = openSchemaEditor(2, 150, {
    hiddenElements: ['save', 'tool.shape.circle', 'tool.shape.polygon'],
    showPricing: true,
  });
});

可用界面元素

编辑器工具栏包含以下可选择隐藏的模式和工具。

编辑器模式

// Mode options that can be hidden
const modes = {
  'mode.schema': 'Schema editing mode',
  'mode.underlay': 'Underlay/background editing',
  'mode.venueShape': 'Venue shape editing',
  'mode.pricingZones': 'Pricing zones configuration',
  'mode.pricing': 'Pricing management',
  'mode.section': 'Section editing mode',
};

座位图工具

// Tools available in Schema mode
const schemaTools = {
  'tool.select': 'Selection tool',
  'tool.seatRows': 'Add seat rows tool',
  'tool.table': 'Add table tool',
  'tool.shape': 'Add shapes (all types)',
  'tool.shape.rect': 'Add rectangle shape',
  'tool.shape.circle': 'Add circle shape',
  'tool.shape.line': 'Add line shape',
  'tool.shape.polygon': 'Add polygon shape',
  'tool.label': 'Add label tool',
};

区域工具

// Tools available in Section mode
const sectionTools = {
  'tool.selectSeats': 'Select individual seats',
  'tool.selectRows': 'Select entire rows',
  'tool.addSeat': 'Add individual seats',
  'tool.numberSeats': 'Number seats automatically',
};

定价工具

// Tools available in Pricing modes
const pricingTools = {
  'tool.selectSeats': 'Select individual seats',
  'tool.selectRows': 'Select entire rows',
  'tool.selectSections': 'Select entire sections',
  'tool.events': 'The events column and the preview modal event tabs',
};

tool.events(简写 events)同时控制定价模式中的活动列和预览弹窗中的活动标签页。传入 ?hidden=events 会同时隐藏两者。如果您此前用该标识符隐藏预览标签页,自 1.70.0 起定价活动列也会隐藏;如需保留活动列,请移除此标识符。

底图工具

// Tools available in Underlay mode
const underlayTools = {
  'tool.importSvgBackground': 'Import SVG as background',
  'tool.exportSvgBackground': 'Export SVG background',
  'tool.removeSvgBackground': 'Remove SVG background',
  'tool.viewbox': 'Adjust viewbox',
};

全局工具

// Global tools
const globalTools = {
  'tool.save': 'Save changes',
  'tool.publish': 'Publish schema (only appears when in draft mode)',
  'tool.preview': 'Preview schema (only appears when event ID is available)',
};

在 URL 中隐藏元素

URL 参数可使用完整标识符(如 mode.schema),也可使用简写(如 schema):

?hidden=schema,pricing,save

使用完整标识符的写法:

?hidden=mode.schema,mode.pricing,tool.save

编辑器布局调整

使用 hideNavbar=true 隐藏导航栏后,编辑器自动调整布局:

  1. 完全移除顶部导航栏。
  2. 增加内容区域和侧栏高度,填满可用空间。
  3. 隐藏发布控件,除非同时设置 draft=true。

这样可提供更简洁、专注的编辑界面,适合 iframe 嵌入。

使用场景与示例

1. 面向客户的只读视图

// Open a read-only view of the schema with minimal UI
openSchemaEditor(2, 150, {
  hideNavbar: true,
  hiddenElements: [
    'save',
    'tool.shape',
    'tool.table',
    'tool.label',
    'tool.seatRows',
    'mode.underlay',
    'mode.venueShape',
    'mode.pricingZones',
    'mode.pricing',
    'tool.addSeat',
    'tool.numberSeats',
  ],
});

2. 以定价为主的编辑器

// Open editor focused on pricing configuration
openSchemaEditor(2, 150, {
  hideNavbar: true,
  showPricing: true,
  hiddenElements: [
    'mode.schema',
    'mode.underlay',
    'mode.venueShape',
    'tool.shape',
    'tool.label',
    'tool.seatRows',
    'tool.table',
  ],
});

3. 座位图创建向导

// Open editor for creating a new schema with step-by-step guidance
openSchemaEditor(2, 'new', {
  hideNavbar: true,
  hiddenElements: ['mode.pricing', 'mode.pricingZones', 'tool.shape.polygon', 'tool.shape.line'],
});

实现自定义消息类型

实现自定义消息类型可扩展父应用与座位图编辑器之间的通信:

// In the parent application
function sendCustomCommand(iframe, command, data) {
  iframe.contentWindow.postMessage(
    {
      type: 'CUSTOM_COMMAND',
      command: command,
      data: data,
    },
    '*',
  );
}

// Example: Set zoom level
sendCustomCommand(editorIframe, 'SET_ZOOM', { level: 0.75 });

// Example: Focus on a specific section
sendCustomCommand(editorIframe, 'FOCUS_SECTION', { sectionId: 'A3' });

这些自定义命令需要在 iframe 应用中实现对应的处理器。

输入功能、设置、端点或 SDK 方法。