基于 Zadig 构建企业开发者门户 - 通用 Iframe 集成插件

基于 Zadig 构建企业开发者门户 - 通用 Iframe 集成插件

本文为「Zadig IDP 插件开发实战」系列之一。

聚焦企业落地内部开发者平台(IDP)时的常见需求——如何将现有系统无缝集成至统一平台。 以「通用 Iframe 集成插件」为例,我们将演示如何基于 Zadig 插件体系,快速嵌入第三方系统,实现研发工具的统一入口访问,告别频繁切换。 该插件支持权限控制、安全沙盒等高级配置,适用于监控面板、文档系统、项目管理等多种外部系统集成。

后续我们还将推出监控告警查看器、项目管理面板等典型场景插件,欢迎持续关注。

# 效果预览

当前实现的能力:

  • 嵌入任意外部网页
  • 完整的 iframe 配置选项(基础配置、权限控制、安全沙盒)
  • 浏览器功能权限配置(全屏、摄像头、麦克风、定位等)
  • 沙盒权限配置,细粒度控制安全策略
  • 配置本地化存储,自动记忆用户设置

# 准备工作

本插件的开发耗时约 1 天,但您无需重复此过程。遵循本教程,可在 1 小时内快速完成,立即体验统一入口的便捷。

基础知识:

版本要求:

  • Node.js v20.0+
  • Yarn v4.0+
  • Zadig v4.0+

首先安装 Zadig IDP 插件开发 SDK,并根据提示初始化插件脚手架

# 全局安装 zadig-plugin-cli
yarn global add zadig-plugin-cli-dev
# 验证安装
zadig-plugin --version
zadig-plugin -- help
# 创建插件,默认创建 Page 类型
zadig-plugin create iframe-zadig

进入目录,启动开发服务器,默认会展示 Hello Plugin 页面,可以在此脚手架代码上进行修改。

cd iframe-zadig
zadig-plugin dev

# 核心代码速览

# 入口与路由注册(index.js)

插件在挂载时注册主路由,并定义 manifest 元数据(identifier、name、route、type 等),默认由 SDK 默认生成,可以不做修改

// 路由注册(节选)
this.registerRoute({
  path: "/",
  component: WrappedComponent,
  meta: {
    title: "Iframe Zadig",
  },
});

// manifest(节选)
const manifest = {
  identifier: "iframe-zadig",
  name: "Iframe Zadig",
  version: "1.0.0",
  description: "通用 Iframe 集成插件",
  type: "page",
  route: "/iframe-zadig",
};

# 主页面容器(components/MainPage.vue)

  • 使用本地存储保存 iframe 配置(URL、权限、沙盒等)
  • 首次打开自动弹出配置对话框
  • 支持点击配置按钮随时修改
<template>
  <div class="iframe-plugin">
    <!-- 配置按钮 -->
    <div v-if="hasConfig" class="config-button-wrapper">
      <el-button
        type="primary"
        icon="el-icon-setting"
        circle
        size="small"
        @click="openConfigDialog"
      ></el-button>
    </div>

    <!-- iframe 内容 -->
    <iframe
      v-if="hasConfig"
      class="iframe-content"
      :src="iframeConfig.url"
      :title="iframeConfig.title"
      :name="iframeConfig.name"
      :allow="iframeConfig.permissions.join(' ')"
      :sandbox="iframeConfig.sandboxEnabled ? iframeConfig.sandboxPermissions.join(' ') : null"
      :referrerpolicy="iframeConfig.referrerpolicy"
      :loading="iframeConfig.loading"
      frameborder="0"
    ></iframe>

    <!-- 配置对话框 -->
    <ConfigDialog
      :visible.sync="showConfigDialog"
      :config="iframeConfig"
      @save="handleConfigSave"
    />
  </div>
</template>
// 初始化逻辑(节选)
initPlugin() {
  // 从 storage 读取 iframe 配置
  if (this.storage) {
    const savedConfig = this.storage.get('iframeConfig')
    if (savedConfig && savedConfig.url) {
      // 有配置,加载配置
      this.iframeConfig = savedConfig
      this.hasConfig = true
    } else {
      // 无配置,弹出配置对话框
      this.showConfigDialog = true
    }
  }
}

// 保存配置(节选)
handleConfigSave(newConfig) {
  this.iframeConfig = newConfig
  this.hasConfig = true
  if (this.storage) {
    this.storage.set('iframeConfig', newConfig)
  }
  this.$message.success('配置已保存!')
}

# 配置对话框(components/ConfigDialog.vue)

采用标签页设计,分为三个配置模块:基础配置、权限控制、安全沙盒

# 1.基础配置标签页

<!-- 基础配置(节选) -->
<el-tab-pane label="基础配置" name="basic">
  <el-form :model="form" :rules="rules" ref="configForm">
    <el-form-item label="URL" prop="url">
      <el-input
        v-model="form.url"
        placeholder="请输入 iframe 地址,例如:https://example.com"
      />
    </el-form-item>

    <el-form-item label="标题" prop="title">
      <el-input v-model="form.title" placeholder="请输入标题" />
    </el-form-item>

    <el-form-item label="加载方式">
      <el-select v-model="form.loading">
        <el-option label="立即加载" value="eager"></el-option>
        <el-option label="延迟加载(lazy)" value="lazy"></el-option>
      </el-select>
    </el-form-item>

    <el-form-item label="Referrer 策略">
      <el-select v-model="form.referrerpolicy">
        <el-option
          label="no-referrer(不发送)"
          value="no-referrer"
        ></el-option>
        <el-option
          label="no-referrer-when-downgrade"
          value="no-referrer-when-downgrade"
        ></el-option>
        <el-option label="origin(仅源)" value="origin"></el-option>
        <el-option label="same-origin(同源)" value="same-origin"></el-option>
      </el-select>
    </el-form-item>
  </el-form>
</el-tab-pane>

# 2.权限控制标签页 通过 allow 属性控制 iframe 可以使用的浏览器功能

<!-- 权限控制(节选) -->
<el-tab-pane label="权限控制" name="permissions">
  <el-form :model="form">
    <el-form-item label="权限列表">
      <el-checkbox-group v-model="form.permissions">
        <el-checkbox label="fullscreen">全屏</el-checkbox>
        <el-checkbox label="autoplay">自动播放</el-checkbox>
        <el-checkbox label="camera">摄像头</el-checkbox>
        <el-checkbox label="microphone">麦克风</el-checkbox>
        <el-checkbox label="geolocation">定位</el-checkbox>
        <el-checkbox label="clipboard-read">读取剪贴板</el-checkbox>
        <el-checkbox label="clipboard-write">写入剪贴板</el-checkbox>
        <el-checkbox label="payment">支付</el-checkbox>
        <el-checkbox label="usb">USB</el-checkbox>
        <!-- 更多权限... -->
      </el-checkbox-group>
    </el-form-item>
  </el-form>
</el-tab-pane>

# 3.安全沙盒标签页

启用沙盒后,iframe 默认权限最小化,需要显式授权

<!-- 安全沙盒(节选) -->
<el-tab-pane label="安全沙盒" name="sandbox">
  <el-form :model="form">
    <el-form-item label="启用沙盒">
      <el-switch v-model="form.sandboxEnabled"></el-switch>
    </el-form-item>

    <el-form-item label="Sandbox 权限" v-if="form.sandboxEnabled">
      <el-checkbox-group v-model="form.sandboxPermissions">
        <el-checkbox label="allow-scripts">允许脚本</el-checkbox>
        <el-checkbox label="allow-same-origin">同源处理</el-checkbox>
        <el-checkbox label="allow-forms">允许表单</el-checkbox>
        <el-checkbox label="allow-popups">允许弹窗</el-checkbox>
        <el-checkbox label="allow-modals">允许模态框</el-checkbox>
        <el-checkbox label="allow-downloads">允许下载</el-checkbox>
        <!-- 更多沙盒权限... -->
      </el-checkbox-group>
    </el-form-item>
  </el-form>
</el-tab-pane>

# 构建与测试

可以通过 zadig-plugin dev 实时预览改动

调试建议:

  • 打开浏览器开发者工具,关注 Console 与 Network
  • 若页面无法显示,检查目标网站是否设置了 X-Frame-Options 禁止嵌入
  • 若启用了沙盒,确保勾选了 allow-scriptsallow-same-origin 权限

本地调试完成后可以构建生产版本:

# 构建生产版本
zadig-plugin build

构建完成后,会在 dist/ 目录生成 plugin.js。这是上传到 Zadig 的最终产物。

# 在 Zadig 中上传并发布

  1. 登录 Zadig → 进入「系统设置 → 插件管理」

  2. 点击「新建插件」,填写:

    1. 插件名称:Iframe 集成插件
    2. 插件类型:导航功能页(Page)
    3. 路由路径:/iframe-zadig
    4. 插件描述:嵌入第三方系统到 Zadig 平台
    5. 插件状态:启用
    6. 上传构建产物:dist/plugin.js
  3. 返回主页面侧边栏,点击添加页面,类型选择插件,选择刚创建的插件

# 使用配置与功能演示

# 场景一:嵌入 Grafana 监控面板

  1. 打开插件页面,自动弹出配置对话框

  2. 在「基础配置」标签页填写:

    1. URL: https://grafana.example.com/d/dashboard-id
    2. 标题: 系统监控
    3. 加载方式: lazy(延迟加载)
  3. 在「权限控制」标签页勾选:

    1. 全屏(fullscreen)
  4. 「安全沙盒」保持关闭状态

  5. 点击「保存」即可在 Zadig 中查看监控数据

# 场景二:嵌入 飞书云 文档

  1. 打开插件页面配置对话框

  2. 在「基础配置」标签页填写:

    1. URL: https://wiki.example.com
    2. 标题: 内部文档
  3. 在「权限控制」标签页勾选:

    1. 全屏(fullscreen)
    2. 读取剪贴板(clipboard-read)
    3. 写入剪贴板(clipboard-write)
  4. 点击「保存」即可在 Zadig 中查看飞书云文档

# 常见问题与解决方案

# Q: 为什么 iframe 显示空白或被拒绝?

A: 可能的原因:

  • 目标网站设置了 X-Frame-Options: DENYSAMEORIGIN
  • 启用了沙盒但未配置 allow-scripts 权限
  • URL 不正确或无法访问

解决方案:

  1. 检查浏览器控制台的错误信息
  2. 确认目标网站是否允许 iframe 嵌入
  3. 如果启用沙盒,确保勾选了必要的权限

# Q: HTTPS 页面如何嵌入 HTTP 内容?

A: 由于浏览器的混合内容策略,从 HTTPS 页面嵌入 HTTP 页面会被阻止。

解决方案:

  1. 将目标系统升级到 HTTPS
  2. 使用反向代理将 HTTP 服务转换为 HTTPS

# Q: 如何在多个页面使用不同的 iframe 配置?

A: 当前版本每个插件实例只支持一个配置。如需嵌入多个不同的系统,可以:

  1. 创建多个插件实例(推荐)
  2. 修改插件代码支持多配置切换
  3. 使用导航标签页在同一插件内切换不同 URL

# 后续可迭代的能力

  • 多配置支持:支持配置多个 iframe 源,通过标签页快速切换,无需反复配置。
  • URL 参数动态化:支持在 URL 中使用变量(如当前用户、项目 ID),实现个性化内容展示。
  • 快捷操作栏:在 iframe 上方添加常用操作按钮(如刷新、全屏、新窗口打开),提升交互体验。
  • 通信桥接:实现 Zadig 与嵌入页面的双向通信,支持数据传递与事件联动。

# 🔜 结语与预告

通过本示例,你可以快速掌握如何在 Zadig 中构建通用 iframe 集成插件,将各类第三方系统无缝集成到统一平台。借助 Zadig IDP 插件体系的灵活性,你可以根据团队的实际需求,快速打造统一的研发协作入口,减少工具切换,提升开发者体验。

📦 本文示例插件已开源

欢迎访问 GitHub 仓库探索更多: 👉 koderover/zadig-idp-plugins (opens new window)

下一篇我们将带来

《如何在 Zadig 中构建 Prometheus + Alertmanager 告警插件》 —— 打造跨系统统一入口,实现研发协作与监控的一体化联动。

📌 欢迎关注我们, 持续获取 Zadig IDP 实战系列的最新动态与深度解析!

Background Image

作为一名软件工程师,我们一直给各行各业写软件提升效率,但是软件工程本身却是非常低效,为什么市面上没有一个工具可以让研发团队不这么累,还能更好、更快地满足大客户的交付需求?我们是否能够打造一个面向开发者的交付平台呢?我们开源打造 Zadig 正是去满足这个愿望。

—— Zadig 创始人 Landy