Zadig 文档
Zadig
教程
博客
论坛
关于
中文英文
Zadig
教程
博客
论坛
关于
Zadig v4.2
Loading...
     编辑文档
     反馈问题
     社区讨论

    本页导航

    IDP 平台开发手册

    本文档面向插件开发者,提供完整的 Zadig IDP 插件开发指南,帮助您快速构建和发布自定义插件。

    # 什么是 IDP 插件系统

    # IDP(内部开发者平台)概述

    内部开发者平台(Internal Developer Platform, IDP)是为开发团队提供的统一工作平台,旨在:

    • 降低认知负担:开发者无需关注底层基础设施,专注于业务开发
    • 提升开发效率:提供标准化的工具链和自助服务能力
    • 统一开发体验:整合分散的开发工具,提供一致的操作界面
    • 沉淀最佳实践:将企业开发经验固化为可复用的能力

    # 插件系统的价值

    Zadig 的插件系统为构建企业级 IDP 提供了强大的扩展能力:

    • 功能扩展:通过插件扩展系统功能,满足个性化需求
    • 界面定制:自定义导航菜单和业务页面,提升用户体验
    • 集成增强:集成第三方工具和服务,实现更丰富的功能集成
    • 灵活配置:支持插件的启用和禁用,按需使用

    # 应用场景

    # 场景一:工具链集成

    背景:
    企业通常使用多个开发工具,开发者需要在不同系统间频繁切换,效率低下。

    解决方案:
    通过插件将常用工具集成到 Zadig 平台中:

    • 代码审查集成:GitLab MR 查看器、GitHub PR 管理
    • 质量监控集成:SonarQube 代码质量报告、测试覆盖率展示
    • 监控告警集成:Prometheus 指标展示、Grafana 看板嵌入
    • 协作工具集成:Jira 任务看板、飞书/钉钉消息中心

    # 场景二:研发流程标准化

    背景:
    不同团队的开发流程不统一,新人上手成本高,协作困难。

    解决方案:
    通过插件固化企业研发流程:

    • 发布审批流程:自定义审批插件,规范上线流程
    • 代码规范检查:集成 Lint 工具,自动检查代码规范
    • 文档模板插件:提供标准化的技术文档模板
    • 环境申请插件:统一的测试环境申请和管理流程

    # 场景三:数据洞察与决策

    背景:
    管理者缺乏研发效能数据,难以发现瓶颈和优化方向。

    解决方案:
    开发数据展示和分析插件:

    • 研发效能看板:交付周期、部署频率、变更失败率等关键指标
    • 团队健康度:代码提交活跃度、代码审查效率分析
    • 资源使用分析:环境资源消耗、成本分析
    • 质量趋势报告:Bug 趋势、测试通过率、技术债务分析

    # 场景四:企业特色功能

    背景:
    每个企业都有独特的业务场景和管理需求,通用平台难以完全满足。

    解决方案:
    根据企业特色开发定制插件:

    • 合规性检查:金融行业的安全审计、日志留存
    • 多云管理:混合云环境的统一管理和切换
    • 成本优化:云资源成本分析和优化建议
    • 知识库集成:企业内部技术文档、最佳实践库

    # 插件类型说明

    Zadig 插件支持两种主要类型,满足不同的使用场景:

    # 导航功能页(Page)

    特点:

    • 独立的功能页面,有完整的页面布局
    • 出现在系统侧边栏菜单中
    • 拥有独立的 URL 访问路径

    适用场景:

    • 需要完整页面展示的功能(如 MR 列表、数据看板)
    • 功能相对独立,不依赖特定业务上下文
    • 需要深度交互的复杂功能

    示例:GitLab MR 查看器、研发效能看板、代码质量报告

    导航功能页

    # 标签页(Tab)

    特点:

    • 嵌入到现有页面的标签页组件
    • 显示在业务目录的标签区域
    • 依赖父页面的上下文信息

    适用场景:

    • 扩展现有页面功能(如项目详情页)
    • 需要业务上下文的功能(如项目级别的质量报告)
    • 轻量级的信息展示

    示例:项目质量标签、环境配置标签、部署历史标签

    标签页

    # 开发环境准备

    # 系统要求

    开发 Zadig 插件需要以下环境:

    • Node.js: >= 20.0.0
    • npm: 随 Node.js 安装
    • 现代浏览器: 支持 ES6+ 语法(Chrome、Firefox、Safari、Edge 等)

    # 安装开发工具

    # 全局安装 CLI 工具

    # 全局安装 zadig-plugin-cli
    npm install -g zadig-plugin-cli-dev
    
    # 验证安装
    zadig-plugin --version
    zadig-plugin --help
    
    1
    2
    3
    4
    5
    6

    # 快速开始

    # 第一步:创建插件项目

    根据需求创建不同类型的插件:

    # 创建导航功能页插件
    zadig-plugin create my-hello-plugin
    
    # 创建标签页插件  
    zadig-plugin create my-tab-plugin --type tab
    
    1
    2
    3
    4
    5

    命令选项:

    • -t, --type <type> - 插件类型(page, tab),默认为 page
    • -f, --force - 强制覆盖已存在的目录

    # 第二步:安装依赖

    # 进入项目目录
    cd my-hello-plugin
    
    # 安装依赖
    npm install
    
    1
    2
    3
    4
    5

    # 第三步:开发调试

    # 启动开发服务器
    zadig-plugin dev
    
    1
    2

    开发服务器启动后,可以在浏览器中实时查看插件效果和调试功能。修改代码后会自动热重载。

    # 第四步:构建发布

    # 构建生产版本
    zadig-plugin build
    
    1
    2

    构建完成后,会在项目目录生成 plugin.js 文件,可直接上传到 Zadig 系统使用。

    # 插件开发实现

    # Page 插件代码模板

    入口文件结构:

    // src/index.js
    export default {
      name: 'my-plugin',           // 插件标识
      displayName: '我的插件',      // 显示名称
      type: 'page',                // 类型:page
      route: '/my-plugin',         // 路由路径
      component: MyPluginPage      // 主组件
    };
    
    1
    2
    3
    4
    5
    6
    7
    8

    完整示例:

    // src/index.js
    import './styles.css';
    
    const MyPluginPage = {
      name: 'MyPluginPage',
      data() {
        return {
          data: [],
          loading: true
        };
      },
      async mounted() {
        await this.fetchData();
      },
      methods: {
        async fetchData() {
          try {
            const response = await fetch('/api/data');
            const result = await response.json();
            this.data = result;
          } catch (error) {
            console.error('Error fetching data:', error);
          } finally {
            this.loading = false;
          }
        }
      },
      template: `
        <div class="my-plugin-container">
          <h1>我的插件</h1>
          <div v-if="loading">加载中...</div>
          <div v-else class="content">
            <!-- 业务逻辑 -->
          </div>
        </div>
      `
    };
    
    export default {
      name: 'my-plugin',
      displayName: '我的插件',
      type: 'page',
      route: '/my-plugin',
      component: MyPluginPage
    };
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45

    # Tab 插件代码模板

    入口文件结构:

    // src/index.js
    export default {
      name: 'my-tab-plugin',       // 插件标识
      displayName: '自定义标签',    // 标签显示名称
      type: 'tab',                 // 类型:tab
      component: MyTabComponent    // 标签组件
    };
    
    1
    2
    3
    4
    5
    6
    7

    完整示例:

    // src/index.js
    import './styles.css';
    
    const MyTabComponent = {
      name: 'MyTabComponent',
      props: {
        context: {
          type: Object,
          default: () => ({})
        }
      },
      data() {
        return {
          info: null
        };
      },
      watch: {
        'context.projectName': {
          handler(newProjectName) {
            if (newProjectName) {
              this.loadProjectInfo(newProjectName);
            }
          },
          immediate: true
        }
      },
      methods: {
        async loadProjectInfo(name) {
          try {
            const response = await fetch(`/api/project/${name}`);
            const data = await response.json();
            this.info = data;
          } catch (error) {
            console.error('Error:', error);
          }
        }
      },
      template: `
        <div class="my-tab-container">
          <h3>项目信息</h3>
          <div v-if="info" class="info-content">
            <!-- 展示项目相关信息 -->
          </div>
          <div v-else>暂无数据</div>
        </div>
      `
    };
    
    export default {
      name: 'my-tab-plugin',
      displayName: '项目信息',
      type: 'tab',
      component: MyTabComponent
    };
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54

    # 项目结构规范

    # 标准项目结构

    my-plugin/
    ├── src/
    │   ├── index.js          # 插件入口文件(必需)
    │   ├── App.vue           # 主组件
    │   ├── components/       # 组件目录
    │   │   ├── Header.vue
    │   │   └── List.vue
    │   ├── utils/           # 工具函数
    │   │   ├── api.js
    │   │   └── storage.js
    │   ├── styles/          # 样式文件
    │   │   └── index.css
    │   └── constants/       # 常量定义
    │       └── config.js
    ├── package.json         # 项目配置
    ├── plugin.config.js     # 插件配置(必需)
    └── README.md           # 说明文档
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17

    # 插件配置文件

    plugin.config.js 用于配置插件的基本信息:

    module.exports = {
      name: 'my-plugin',           // 插件唯一标识
      displayName: '我的插件',      // 显示名称
      type: 'page',                // 插件类型: page 或 tab
      route: '/my-plugin',         // 路由路径(仅 page 类型需要)
      description: '插件描述',      // 插件功能描述
      version: '1.0.0',            // 版本号
      author: 'Your Name',         // 作者信息(可选)
      icon: 'icon-name'           // 图标名称(可选)
    };
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10

    # 入口文件规范

    src/index.js 是插件的入口文件:

    import Vue from 'vue';
    import App from './App.vue';
    import './styles/index.css';
    
    // 导出插件配置和组件
    export default {
      // 插件元数据
      name: 'my-plugin',
      displayName: '我的插件',
      type: 'page',
      
      // 插件组件
      component: App,
      
      // 生命周期钩子(可选)
      onMount: () => {
        console.log('插件已加载');
      },
      onUnmount: () => {
        console.log('插件已卸载');
      }
    };
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22

    # 开发规范与最佳实践

    # 1. 代码规范

    # 组件开发

    // 使用Vue2组件和Options API
    export default {
      name: 'MyComponent',
      data() {
        return {
          data: []
        };
      },
      async mounted() {
        // 数据加载逻辑
        fetchData();
      },
      template: `<div><!-- 组件内容 --></div>`
    };
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14

    # 样式管理

    /* 使用 CSS 模块化或统一前缀避免样式冲突 */
    .my-plugin-container {
      padding: 20px;
    }
    
    .my-plugin-header {
      font-size: 18px;
      font-weight: bold;
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9

    # 2. 响应式设计

    插件应适配不同屏幕尺寸:

    /* 移动端适配 */
    @media (max-width: 768px) {
      .my-plugin-container {
        padding: 10px;
      }
    }
    
    /* 平板适配 */
    @media (min-width: 769px) and (max-width: 1024px) {
      .my-plugin-container {
        padding: 15px;
      }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13

    # 3. 错误处理

    做好异常处理,提供友好的错误提示:

    async function fetchData() {
      try {
        const response = await fetch('/api/data');
        if (!response.ok) {
          throw new Error('数据加载失败');
        }
        const data = await response.json();
        return data;
      } catch (error) {
        console.error('Error:', error);
        // 显示错误提示给用户
        showErrorMessage('加载数据时出错,请稍后重试');
      }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14

    # 4. 性能优化

    # 懒加载

    // 使用Vue异步组件进行懒加载
    export default {
      name: 'App',
      components: {
        HeavyComponent: () => import('./HeavyComponent.vue')
      },
      template: `
        <div>
          <HeavyComponent />
        </div>
      `
    };
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12

    # 防抖与节流

    // 使用 debounce 优化搜索输入
    export default {
      name: 'SearchInput',
      data() {
        return {
          query: '',
          timer: null
        };
      },
      methods: {
        handleSearch(value) {
          // 清除上一次的定时器
          if (this.timer) {
            clearTimeout(this.timer);
          }
          // 设置新的定时器
          this.timer = setTimeout(() => {
            this.performSearch(value);
          }, 300);
        },
        performSearch(value) {
          // 执行搜索逻辑
          console.log('搜索:', value);
        }
      },
      template: `
        <input
          v-model="query"
          @input="handleSearch(query)"
          placeholder="输入搜索关键词"
        />
      `
    };
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33

    # 5. 用户体验

    # 加载状态

    export default {
      name: 'DataList',
      data() {
        return {
          loading: true,
          data: []
        };
      },
      template: `
        <div>
          <div v-if="loading" class="loading-spinner">
            加载中...
          </div>
          <div v-else>
            <!-- 数据展示 -->
          </div>
        </div>
      `
    };
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19

    # 空状态提示

    export default {
      name: 'DataList',
      props: {
        data: {
          type: Array,
          default: () => []
        }
      },
      methods: {
        handleRefresh() {
          this.$emit('refresh');
        }
      },
      template: `
        <div>
          <div v-if="data.length === 0" class="empty-state">
            <p>暂无数据</p>
            <button @click="handleRefresh">刷新</button>
          </div>
          <div v-else>
            <!-- 数据列表 -->
          </div>
        </div>
      `
    };
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25

    # 6. 数据持久化

    使用浏览器本地存储保存用户配置:

    // 工具函数
    const storage = {
      set(key, value) {
        localStorage.setItem(
          `zadig-plugin-${key}`,
          JSON.stringify(value)
        );
      },
      
      get(key) {
        const value = localStorage.getItem(`zadig-plugin-${key}`);
        return value ? JSON.parse(value) : null;
      },
      
      remove(key) {
        localStorage.removeItem(`zadig-plugin-${key}`);
      }
    };
    
    // 使用示例
    function saveConfig(config) {
      storage.set('config', config);
    }
    
    function loadConfig() {
      return storage.get('config') || {};
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27

    # API 调用规范

    # 调用 Zadig API

    // API 调用封装
    class ZadigAPI {
      constructor() {
        this.baseURL = window.location.origin;
      }
      
      async request(endpoint, options = {}) {
        const url = `${this.baseURL}/api/aslan${endpoint}`;
        const response = await fetch(url, {
          ...options,
          headers: {
            'Content-Type': 'application/json',
            ...options.headers
          },
          credentials: 'include' // 携带认证信息
        });
        
        if (!response.ok) {
          throw new Error(`API Error: ${response.status}`);
        }
        
        return response.json();
      }
      
      // 获取项目列表
      async getProjects() {
        return this.request('/api/aslan/project');
      }
      
      // 获取工作流列表
      async getWorkflows(projectName) {
        return this.request(`/api/aslan/workflow/v4?projectName=${projectName}`);
      }
    }
    
    export default new ZadigAPI();
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36

    # 调用外部 API

    // 调用外部服务 API
    async function fetchGitLabMRs(gitlabUrl, token) {
      const response = await fetch(`${gitlabUrl}/api/v4/merge_requests`, {
        headers: {
          'Authorization': `Bearer ${token}`
        }
      });
      
      if (!response.ok) {
        throw new Error('Failed to fetch GitLab MRs');
      }
      
      return response.json();
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14

    # 调试技巧

    # 1. 开发环境调试

    # 启动开发服务器时查看详细日志
    zadig-plugin dev --verbose
    
    # 指定端口
    zadig-plugin dev --port 3000
    
    1
    2
    3
    4
    5

    # 3. 日志输出

    // 开发环境日志
    if (process.env.NODE_ENV === 'development') {
      console.log('Debug info:', data);
    }
    
    // 统一日志管理
    const logger = {
      info: (message, data) => {
        console.log(`[INFO] ${message}`, data);
      },
      error: (message, error) => {
        console.error(`[ERROR] ${message}`, error);
      },
      warn: (message, data) => {
        console.warn(`[WARN] ${message}`, data);
      }
    };
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17

    # 插件发布

    # 构建生产版本

    # 执行构建
    zadig-plugin build
    
    # 验证构建产物
    ls -lh plugin.js
    
    1
    2
    3
    4
    5

    # 上传到 Zadig

    1. 登录 Zadig 系统
    2. 进入 系统设置 → 插件管理
    3. 点击 新建插件
    4. 填写插件信息:
      • 插件名称: 显示名称
      • 插件类型: 选择 page 或 tab
      • 路由路径: URL 路径(page 类型)
      • 插件描述: 功能说明
      • 插件状态: 启用/禁用
    5. 上传 plugin.js 文件
    6. 点击 创建插件

    # 版本管理

    建议遵循语义化版本规范:

    • 主版本号: 不兼容的 API 修改
    • 次版本号: 向下兼容的功能性新增
    • 修订号: 向下兼容的问题修正
    // plugin.config.js
    module.exports = {
      name: 'my-plugin',
      version: '1.2.3', // 主.次.修订
      // ...
    };
    
    1
    2
    3
    4
    5
    6

    # 插件市场

    官方插件库

    GitHub: https://github.com/koderover/zadig-idp-plugins
    欢迎贡献和分享您的插件

    # GitLab MR 查看器

    官方提供的示例插件,展示如何集成外部系统。

    功能特性:

    • 查看分配给我的 Merge Request
    • 按状态和范围筛选 MR
    • 支持 GitLab.com 和私有实例
    • 本地配置管理,数据安全

    获取方式:

    # 从官方插件库下载
    git clone https://github.com/koderover/zadig-idp-plugins.git
    cd zadig-idp-plugins/gitlab-mr-viewer
    
    # 构建插件
    npm install
    npm run build
    
    # 上传 plugin.js 到 Zadig
    
    1
    2
    3
    4
    5
    6
    7
    8
    9

    配置说明:

    1. 获取 GitLab Personal Access Token(需要 api 和 read_user 权限)
    2. 在插件配置页面填写 GitLab URL 和 Token
    3. 测试连接成功后保存配置

    更多插件: 访问官方插件库查看更多示例:https://github.com/koderover/zadig-idp-plugins

    # 常见问题

    # 构建相关

    # Q: 构建失败,提示 Node 版本不兼容?

    A: 检查并升级 Node.js 版本:

    # 检查当前版本
    node --version
    
    # 使用 nvm 升级(推荐)
    nvm install 20
    nvm use 20
    
    # 重新安装依赖
    rm -rf node_modules package-lock.json
    npm install
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10

    # Q: 构建产物过大怎么办?

    A: 优化构建配置:

    • 移除未使用的依赖
    • 使用代码分割(code splitting)
    • 压缩资源文件
    • 检查是否误打包了开发依赖

    # 开发相关

    # Q: 开发服务器启动失败?

    A: 排查步骤:

    1. 确认在正确的插件项目目录中
    2. 检查 package.json 和 plugin.config.js 是否存在
    3. 确保已安装项目依赖:npm install
    4. 检查端口是否被占用,尝试指定其他端口:zadig-plugin dev --port 3001

    # Q: 插件在 Zadig 中无法加载?

    A: 检查清单:

    1. 验证 plugin.js 文件是否正确生成
    2. 检查浏览器控制台是否有 JavaScript 错误
    3. 确认插件配置信息是否完整
    4. 检查插件类型和路由配置是否正确

    # Q: 如何调试已上传的插件?

    A:

    1. 打开浏览器开发者工具
    2. 在 Console 标签查看错误日志
    3. 在 Network 标签监控 API 请求
    4. 如需修改,重新构建并上传新版本

    # API 相关

    # Q: 调用 Zadig API 提示权限错误?

    A:

    • 确保请求中包含认证信息:credentials: 'include'
    • 检查当前用户是否有相应的权限
    • 验证 API endpoint 路径是否正确

    # Q: 跨域请求被阻止?

    A:

    • Zadig API 调用应使用相对路径,避免跨域问题
    • 外部 API 调用需要目标服务器支持 CORS
    • 可以考虑通过 Zadig 后端代理外部 API

    # 样式相关

    # Q: 插件样式与系统样式冲突?

    A:

    • 使用唯一的 CSS 类名前缀,如 .my-plugin-*
    • 考虑使用 CSS Modules
    • 避免使用全局样式
    • 使用 CSS-in-JS 方案(如 styled-components)

    # 开发资源

    # 官方资源

    • 插件库: https://github.com/koderover/zadig-idp-plugins(opens new window)
    • 示例代码: 官方插件库中包含多个完整示例
    • API 文档: 参考 Zadig OpenAPI 文档

    # 社区支持

    • GitHub Issues: 提交问题和功能建议
    • 技术支持: 联系 Zadig 技术支持团队
    • 贡献指南: 欢迎向官方插件库贡献优质插件

    ← 协作模式自定义账号系统→

    资源
    教程
    论坛
    博客
    公司
    关于
    客户故事
    加入我们
    联系我们
    微信扫一扫
    hello@koderover.com

    © 2026 筑栈(上海)信息技术有限公司 沪 ICP 备 19000177 号 - 1

    •  跟随系统
    •  浅色模式
    •  深色模式
    •  阅读模式