npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

devject-design

v0.4.0

Published

Devject Design 是一个基于 Vue 3 和 Element Plus 的可视化表单设计器与渲染器组件库。它允许用户通过拖拽方式快速创建表单布局,并支持将设计好的表单导出为 JSON 数据,或直接在应用中渲染。

Readme

Devject Design

Devject Design 是一个基于 Vue 3 和 Element Plus 的可视化表单设计器与渲染器组件库。它允许用户通过拖拽方式快速创建表单布局,并支持将设计好的表单导出为 JSON 数据,或直接在应用中渲染。

开源地址: https://gitee.com/yoding/devject-design

✨ 特性

  • 基于 Vue 3 + TypeScript:使用最新的技术栈,提供完整的类型定义。
  • 🎨 Element Plus 风格:与 Element Plus UI 完美融合。
  • 🧩 可视化设计器:支持拖拽、属性配置、实时预览。
  • 📝 表单渲染器:根据 JSON 结构自动渲染表单,支持数据双向绑定与校验。
  • 👁️ 节点可见/只读:所有内置组件支持“可见”控制,输入类组件支持“只读”控制。
  • 📤 导入/导出:支持 JSON 格式的布局与数据导入导出。
  • 📊 高级组件
    • 静态表格 (StaticTable):支持 Excel 导入(自动识别表头、清空旧数据)与导出。
    • 表格表单 (Table):动态表格组件,支持分页、增删改查及数据绑定。
    • 树形控件 (Tree):支持层级路径格式(如 父节点/子节点)的 Excel 导入导出,支持父子关联配置。
  • 🏗️ 复杂布局:内置栅格布局 (FlexRow)、折叠面板 (Collapse)、标签页 (Tabs) 等容器组件。

📦 安装

使用 npm 或 yarn 安装:

npm install devject-design

依赖项

本库依赖 vueelement-plus,请确保项目中已安装:

npm install vue element-plus

如果使用表格/树形组件的 Excel 导入导出功能,还需要安装 xlsx

npm install xlsx

⚙️ 配置说明

本库支持通过 Props 配置上传和下载接口。

属性说明

FormDesignerFormRenderer 组件都支持以下 Props:

| 属性名 | 说明 | 类型 | 默认值 | | :--- |:---------------------------------------------| :--- | :--- | | upload-url | 文件上传接口地址 | string | - | | download-url | 文件下载/访问基础路径 | string | - | | upload-parse | 上传响应解析路径,支持 $$.data.url 这类写法 | string | $ | | file-headers | 文件上传与下载时透传的请求头(如 Authorization) | Record<string, string> | - |

示例

在你的 Vite 项目中,你可以使用环境变量来传递这些值:

// .env
VITE_DEVJECT_UPLOAD_URL=/api/file/upload
VITE_DEVJECT_DOWNLOAD_URL=/api/file/download
VITE_DEVJECT_UPLOAD_PARSE=$.data.url
<template>
  <FormDesigner 
    :upload-url="uploadUrl"
    :download-url="downloadUrl"
    :upload-parse="uploadParse"
    :file-headers="fileHeaders"
  />
</template>

<script setup lang="ts">
import { FormDesigner } from 'devject-design'
import { getToken } from '@/utils/common'

const uploadUrl = import.meta.env.VITE_DEVJECT_UPLOAD_URL
const downloadUrl = import.meta.env.VITE_DEVJECT_DOWNLOAD_URL
const uploadParse = import.meta.env.VITE_DEVJECT_UPLOAD_PARSE || '$'
const token = getToken()
const fileHeaders = token ? { Authorization: token.startsWith('Bearer ') ? token : `Bearer ${token}` } : {}
</script>

上传/下载鉴权

当你的文件接口启用了登录校验时,请通过 file-headers 透传认证头。
file-headers 会同时作用于:

  • 文件上传组件(/upload 请求)
  • 文件下载/图片预览(/download 请求)

🚀 快速开始

全局注册

在你的入口文件(如 main.ts)中引入 Element Plus 和 Devject Design:

import { createApp } from 'vue'
import App from './App.vue'

import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'

import DevjectDesign from 'devject-design'
import 'devject-design/dist/style.css'

const app = createApp(App)

app.use(ElementPlus)
app.use(DevjectDesign)
app.mount('#app')

使用表单设计器 (FormDesigner)

FormDesigner 支持通过 v-model 双向绑定布局数据,并提供了导入导出的方法。

<template>
  <div style="width:100%;height: 100%;overflow: hidden">
    <!-- 顶部操作栏示例 -->
    <div>
       <button @click="handleExport">导出布局</button>
       <button @click="handleImport">导入布局</button>
    </div>
    
    <FormDesigner 
      ref="designerRef"
      v-model="layoutSchema"
      :upload-url="uploadUrl"
      :download-url="downloadUrl"
      :upload-parse="uploadParse"
      :file-headers="fileHeaders"
    />
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { FormDesigner } from 'devject-design'
import type { LayoutSchema } from 'devject-design'
import { getToken } from '@/utils/common'

const uploadUrl = import.meta.env.VITE_DEVJECT_UPLOAD_URL
const downloadUrl = import.meta.env.VITE_DEVJECT_DOWNLOAD_URL
const uploadParse = import.meta.env.VITE_DEVJECT_UPLOAD_PARSE || '$'
const token = getToken()
const fileHeaders = token ? { Authorization: token.startsWith('Bearer ') ? token : `Bearer ${token}` } : {}

// 双向绑定布局数据
const layoutSchema = ref<LayoutSchema>()
const designerRef = ref()

// 调用组件方法导出
const handleExport = () => {
  if (designerRef.value) {
    const layout = designerRef.value.exportLayout()
    console.log('Exported:', layout)
  }
}

// 调用组件方法导入
const handleImport = () => {
  if (designerRef.value) {
    designerRef.value.importLayout({
      version: 1,
      root: { children: [] }
    })
  }
}
</script>

使用表单渲染器 (FormRenderer)

FormRenderer 支持通过 v-model 绑定表单数据,并提供了数据导入导出方法。

<template>
  <div>
    <!-- 操作按钮 -->
    <button @click="getFormData">获取数据</button>
    <button @click="setFormData">设置数据</button>
    
    <FormRenderer 
      ref="rendererRef"
      :schema="formSchema" 
      v-model="formData" 
      :upload-url="uploadUrl"
      :download-url="downloadUrl"
      :upload-parse="uploadParse"
      :file-headers="fileHeaders"
    />
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { FormRenderer } from 'devject-design'
import type { LayoutSchema, FormDataModel } from 'devject-design'
import { getToken } from '@/utils/common'

const uploadUrl = import.meta.env.VITE_DEVJECT_UPLOAD_URL
const downloadUrl = import.meta.env.VITE_DEVJECT_DOWNLOAD_URL
const uploadParse = import.meta.env.VITE_DEVJECT_UPLOAD_PARSE || '$'
const token = getToken()
const fileHeaders = token ? { Authorization: token.startsWith('Bearer ') ? token : `Bearer ${token}` } : {}

const rendererRef = ref()
// 表单结构定义
const formSchema = ref<LayoutSchema>({ /* ... */ })
// 表单数据双向绑定
const formData = ref<FormDataModel>({})

// 调用组件方法获取数据
const getFormData = async () => {
  if (rendererRef.value) {
    try {
      // 默认会先进行校验,校验通过后返回数据
      const data = await rendererRef.value.exportData()
      console.log('Form Data:', data)
    } catch (e) {
      console.error('Validation failed')
    }
  }
}

// 调用组件方法设置数据
const setFormData = () => {
  if (rendererRef.value) {
    rendererRef.value.importData({ field1: 'value1' })
  }
}
</script>

🧩 内置组件详解

除了基础的 Input, Select, Radio, Checkbox 外,本库还包含以下高级组件:

1. 静态表格 (StaticTable)

用于展示或编辑固定的行列数据。

  • Excel 导入: 支持直接导入 .xlsx 文件。导入时会自动识别首行作为表头(列名),并自动清空旧的列配置和数据。
  • Excel 导出: 支持将当前表格数据导出为 Excel 文件。
  • 数据绑定: 修改列标题不会丢失该列已有的数据。

2. 表格表单 (Table)

用于展示动态数据列表。

  • 分页支持: 可配置是否显示分页及每页条数。
  • 增删改查: 内置添加和删除行操作。
  • 列配置: 支持自定义列类型(文本、数字、下拉等)及校验规则。

3. 树形控件 (Tree)

用于展示层级数据。

  • Excel 导入: 支持导入路径格式的 Excel(例如:一级/二级/三级),系统会自动解析为树形结构。
  • 关联配置: 提供关联开关。开启时,父子节点选中状态联动;关闭时,各节点独立选中。
  • 缩进设置: 可自定义树节点的缩进大小。

4. 布局组件

  • FlexRow: 栅格布局,支持自定义列宽比例。
  • Collapse: 折叠面板,支持多面板展开/收起。
  • Tabs: 标签页布局,支持动态增删标签页。

📚 组件 API

FormDesigner

表单设计器组件,提供完整的画布、组件库和属性面板。

Props

| 属性 | 说明 | 类型 | 默认值 | | :--- | :--- | :--- | :--- | | modelValue | 表单布局结构绑定 (v-model) | LayoutSchema | - | | upload-url | 文件上传接口地址 | string | - | | download-url | 文件下载/访问基础路径 | string | - | | upload-parse | 上传响应解析路径 | string | $ | | file-headers | 文件上传/下载透传请求头 | Record<string, string> | - |

Exposed Methods

| 方法名 | 说明 | 参数 | 返回值 | | :--- | :--- | :--- | :--- | | exportLayout | 导出当前布局结构 | - | LayoutSchema | | importLayout | 导入布局结构 | json: LayoutSchema | void |

FormRenderer

表单渲染器组件,用于展示设计好的表单。

Props

| 属性 | 说明 | 类型 | 默认值 | | :--- | :--- | :--- | :--- | | schema | (必填) 表单布局结构对象 | LayoutSchema | - | | modelValue | (必填) 表单数据绑定 (v-model) | FormDataModel | {} | | upload-url | 文件上传接口地址 | string | - | | download-url | 文件下载/访问基础路径 | string | - | | upload-parse | 上传响应解析路径 | string | $ | | file-headers | 文件上传/下载透传请求头 | Record<string, string> | - |

Exposed Methods

| 方法名 | 说明 | 参数 | 返回值 | | :--- | :--- | :--- | :--- | | exportData | 导出当前表单数据 (默认进行校验) | validateBeforeExport?: boolean (默认 true) | Promise<FormDataModel> | | importData | 导入表单数据 | data: FormDataModel | void | | validate | 校验表单 | - | Promise<boolean> |

🛠 自定义组件开发

Devject Design 支持通过注册自定义组件来扩展设计器的能力。

1. 注册组件 API

使用 registerComponent 函数来注册一个新的组件。

import { registerComponent, type ComponentDefinition } from 'devject-design';

const myComponentDef: ComponentDefinition = {
  type: 'my-custom-type', // 组件唯一标识
  typeCn: '我的组件', // 设计器内显示的组件中文名
  component: MyComponentVue, // Vue 组件对象
  palette: { 
    label: '我的组件', 
    group: '自定义', // 在组件面板中的分组
    icon: 'Operation' // (可选) 组件面板显示的图标名称 (支持所有 Element Plus 图标)
  },
  defaultProps: (id) => ({
    id,
    type: 'my-custom-type',
    props: {
      // 组件默认属性
      someProp: 'defaultValue'
    }
  }),
  // 自定义校验逻辑
  validate: (value, node, formData) => {
      if (!value) return '该项不能为空';
      if (value.length < 5) return '长度至少为5';
      return true; // 校验通过返回 true
  },
  // 可选:数据处理器
  dataProcessor: {
    import: (val) => val, // 导入时处理数据
    export: (val) => val  // 导出时处理数据
  }
};

registerComponent(myComponentDef);

2. 编写 Vue 组件

自定义组件会接收 node props,其中包含组件的配置信息。

<!-- MyComponent.vue -->
<template>
  <div class="my-component">
    <h3>{{ node.props.label || 'My Component' }}</h3>
    <p>属性值: {{ node.props.someProp }}</p>
    <!-- 如果是输入类组件,可以使用 inject 获取 formModel -->
  </div>
</template>

<script setup lang="ts">
import type { SchemaNode } from 'devject-design';

defineProps<{
  node: SchemaNode
}>();
</script>

3. 集成示例

在你的应用入口或组件初始化处进行注册:

import { registerComponent } from 'devject-design';
import MyCustomComponent from './MyCustomComponent.vue';

// 注册组件
registerComponent({
  type: 'custom-widget',
  typeCn: '自定义控件',
  component: MyCustomComponent,
  palette: { label: '自定义控件', group: '业务组件' },
  defaultProps: (id) => ({
    id,
    type: 'custom-widget',
    props: { label: '默认标题' }
  })
});

4. 自定义属性编辑器

除了注册组件本身,你还可以为组件属性注册自定义编辑器。

1. 编写编辑器组件

编辑器组件接收以下 Props:

  • modelValue: 当前属性值
  • nodeId: 当前选中的组件 ID
  • 其他自定义 Props
<!-- MyColorEditor.vue -->
<template>
  <el-color-picker :modelValue="modelValue" @change="$emit('update:modelValue', $event)" />
</template>

<script setup lang="ts">
defineProps<{
  modelValue: string,
  nodeId: string
}>();
defineEmits(['update:modelValue']);
</script>

2. 注册编辑器

使用 registerEditor 函数注册编辑器。

import { registerEditor } from 'devject-design';
import MyColorEditor from './MyColorEditor.vue';

registerEditor('my-color-editor', MyColorEditor);

3. 在组件配置中使用

propsConfig 中引用已注册的编辑器名称。

registerComponent({
  // ...
  propsConfig: [
    { 
      label: "颜色配置", 
      name: "textColor", 
      type: "custom", 
      editor: "my-color-editor" // 使用注册的编辑器名称
    }
  ]
});

✅ 表单校验

Devject Design 提供了一套灵活的表单校验机制,支持内置的必填校验和自定义的函数校验。

1. 必填校验

在设计器中选中组件,勾选"必填"属性即可开启。

  • 系统会自动根据组件类型(如输入框、下拉框)生成相应的提示语,例如"请输入用户名"或"请选择城市"。
  • 提示语生成逻辑:请[输入/选择][组件标题]

2. 自定义校验

通过 registerComponent 注册组件时,可以提供 validate 函数来实现复杂的校验逻辑。

registerComponent({
  // ... 其他配置
  validate: (value, node, formData) => {
    // value: 当前字段的值
    // node: 当前组件的配置节点信息
    // formData: 整个表单的数据对象
    
    if (!value && node.props.required) {
      return true; // 如果为空且必填,由内置必填规则处理,这里可以返回 true 跳过
    }
    
    if (value && value.length < 5) {
      return '长度不能少于 5 个字符'; // 返回字符串作为错误提示
    }
    
    // 支持异步校验 (返回 Promise)
    // return fetch('/api/check?val=' + value).then(res => res.ok ? true : '校验失败');
    
    return true; // 校验通过
  }
});

3. 触发校验

  • 自动触发:表单输入或失去焦点时自动触发。
  • 手动触发:通过 FormRenderervalidate() 方法。
  • 导出时触发:调用 exportData() 时默认会自动校验,校验失败则抛出异常。

4. 可见与只读

  • 所有内置组件都支持 visible 属性;当值为 false 时,节点会在 FormRenderer 预览态中隐藏。
  • 设计器画布不会因为 visible=false 而隐藏节点,方便继续选中和编辑。
  • 输入类组件额外支持 readonly 属性,用于将单个组件设为只读。
  • FormRenderer 顶层 readonly 仍然保留,适合整张表单统一只读;节点级 readonly 适合精细控制单个组件。

📄 许可证

MIT