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

yu-vue3-ui

v1.0.132

Published

基于 Vue 3 + Element Plus 的业务组件库,通过配置化的方式简化后台管理系统的 CRUD 页面开发。

Readme

yu-vue3-ui

基于 Vue 3 + Element Plus 的业务组件库,通过配置化的方式简化后台管理系统的 CRUD 页面开发。

特性

  • 配置化开发:通过 columns 一份配置,自动生成搜索、表单、表格、详情四个区域的字段
  • 丰富的表单类型:支持 17 种输入类型,覆盖日常开发中的各种场景
  • 完整的 CRUD 封装:列表、新增、编辑、删除、导入、导出、自定义表头
  • 灵活可扩展:支持自定义校验、联动筛选、动态显示/隐藏字段
  • 完整的 TypeScript 支持:提供完整的类型定义

安装

npm install yu-vue3-ui

快速开始

1. 定义数据源 (dataSource.ts)

import { gCrud_IF } from 'yu-vue3-ui/interface/crud'

// 定义 columns 配置
const columns: gCrud_IF[] = [
  {
    label: '用户名',
    dataIndex: 'username',
    type: 'input',
    showSearch: true,
    isRequired: true
  },
  {
    label: '状态',
    dataIndex: 'status',
    type: 'select',
    options: [
      { label: '启用', value: 1 },
      { label: '禁用', value: 0 }
    ]
  }
]

// 定义 API 接口地址
const url = {
  list: '/api/user/list',
  getById: '/api/user/',
  add: '/api/user',
  edit: '/api/user',
  delete: '/api/user',
  export: '/api/user/export'
}

export { columns, url }

2. 列表页面 (index.vue)

<template>
  <div class="g-crud">
    <!-- 搜索区域 -->
    <el-card shadow="hover">
      <yuForm v-model="queryParam" :options="searchColumns">
        <el-button type="primary" icon="search" @click="getList">查 询</el-button>
        <el-button icon="RefreshRight" @click="handleReset">重 置</el-button>
      </yuForm>
    </el-card>

    <!-- 数据表格区域 -->
    <el-card shadow="hover" v-loading="loading">
      <!-- 工具栏按钮 -->
      <div class="g-table-button">
        <el-button type="primary" icon="Plus" @click="handleAdd">新增</el-button>
        <el-button icon="Download" @click="handleExport('文件名')">导出</el-button>
      </div>

      <!-- 数据表格 -->
      <yuTable :columns="diyTableColumns" :data="dataSource">
        <!-- 操作列插槽 -->
        <template #action="{ record }">
          <el-button type="text" @click="handleDetails(record)">查看</el-button>
          <el-button type="text" @click="handleEdit(record)">修改</el-button>
          <el-button type="text" @click="handleDelete(record)">删除</el-button>
        </template>
      </yuTable>

      <!-- 分页组件 -->
      <el-pagination
        v-model:current-page="queryParam.pageNum"
        v-model:page-size="queryParam.pageSize"
        :page-sizes="[10, 20, 30, 40]"
        layout="total, sizes, prev, pager, next, jumper"
        :total="queryParam.total"
        @size-change="handleSizeChange"
        @current-change="handleCurrentChange"
      />
    </el-card>

    <!-- 详情/新增/编辑弹窗 -->
    <detailsDialog @ok="getList" :options="detailColumns" :url="url" ref="detailsRef" />
  </div>
</template>

<script lang="ts" setup>
import { columns, url } from './dataSource'
import detailsDialog from './detailsDialog.vue'
import indexHooks from 'yu-vue3-ui/hooks/indexHooks'

const {
  searchColumns,    // 搜索表单配置
  detailColumns,    // 详情表单配置
  detailsRef,       // 详情弹窗实例
  queryParam,       // 查询参数(包含分页)
  dataSource,       // 表格数据
  loading,          // 加载状态
  diyTableColumns,  // 表格列配置(支持自定义表头)
  getList,          // 获取列表数据
  handleDetails,    // 查看详情
  handleAdd,        // 新增
  handleEdit,       // 编辑
  handleDelete,     // 删除
  handleReset,      // 重置搜索
  handleExport,     // 导出
  handleSizeChange, // 分页大小变更
  handleCurrentChange, // 页码变更
} = indexHooks({ columns, url })
</script>

3. 详情弹窗 (detailsDialog.vue)

<template>
  <el-dialog v-model="show" :title="title">
    <!-- 表单组件,isDetails=true 时禁用编辑 -->
    <yu-form ref="gFormRef" v-model="form" :options="options" :span="24" :disabled="isDetails" />
    <template #footer>
      <div class="dialog-footer" v-if="!isDetails">
        <el-button @click="handleCancel">取消</el-button>
        <el-button type="primary" :loading="loading" @click="handleOk">确定</el-button>
      </div>
    </template>
  </el-dialog>
</template>

<script lang="ts" setup>
import detailsHooks from 'yu-vue3-ui/hooks/detailsHooks'

const props = defineProps({
  options: { type: Array, default: () => [] },
  url: { type: Object, default: () => ({}) }
})

const emit = defineEmits(['ok'])

const {
  show,        // 弹窗显示状态
  title,       // 弹窗标题
  isDetails,   // 是否为详情查看模式
  form,        // 表单数据
  loading,     // 提交按钮加载状态
  gFormRef,    // 表单实例(用于调用校验等方法)
  handleOpen,  // 打开弹窗
  handleOk,    // 确认提交
  handleCancel // 取消关闭
} = detailsHooks({ url: props.url, emit })

defineExpose({ show, handleOpen })
</script>

核心概念

columns 配置详解

columns 是整个组件库的核心,通过一份配置自动适配搜索、表单、表格、详情四个场景:

const columns: gCrud_IF[] = [
  {
    label: '字段名称',           // 字段显示名称
    dataIndex: 'fieldName',     // 绑定字段名
    type: 'input',              // 字段类型
    showSearch: true,           // 是否显示在搜索区域
    isRequired: true            // 是否必填
  }
]

字段类型 (crudType_TP)

| 类型 | 说明 | Element Plus 组件 | |------|------|------------------| | input | 单行文本输入框 | el-input | | text | 多行文本输入框 | el-input (textarea) | | number | 数字输入框 | el-input-number | | select | 下拉选择框 | el-select | | multipleSelect | 多选下拉框 | el-select延申自定义组件(仅适配字符串以逗号分割) | | treeSelect | 树形下拉选择 | el-tree-select | | checkbox | 多选框 | el-checkbox-group | | radio | 单选框 | el-radio-group | | date | 日期选择器 | el-date-picker | | dateYear | 年份选择器 | el-date-picker | | datetime | 日期时间选择器 | el-date-picker | | switch | 开关 | el-switch | | color | 颜色选择器 | el-color-picker | | editor | 富文本编辑器 | 自定义组件(需自行引入editor) | | fileUpload | 文件上传 | 自定义组件(需自行引入fileUpload) | | imageUpload | 图片上传 | 自定义组件(需自行引入imageUpload) | | divider | 分隔线 | 自定义组件 |

columns 完整属性

| 属性 | 类型 | 说明 | |------|------|------| | label | string | 字段显示名称 | | dataIndex | string | 绑定字段名 | | type | crudType_TP | 默认字段类型 | | searchType | crudType_TP | 搜索区域专属类型 | | detailType | crudType_TP | 详情区域专属类型 | | showSearch | boolean | 是否显示在搜索区域 | | noTable | boolean | 是否不在表格中展示 | | noDetails | boolean | 是否不在详情表单中展示 | | noShow | boolean | 是否不在表格列中显示 | | isRequired | boolean | 是否为必填项 | | isInnerHtml | boolean | 是否使用 v-html 展示(用于富文本) | | dict | string | 若依字典标识 | | unit | string | 数据单位,如 "100m" | | options | options_TP \| funcOptions_TP | 选项数据(支持异步函数) | | searchOptions | options_TP \| funcOptions_TP | 搜索区域专属选项 | | detailOptions | options_TP \| funcOptions_TP | 详情区域专属选项 | | config | anyObject_IF | 公共扩展配置 | | searchConfig | anyObject_IF | 搜索区域扩展配置 | | detailConfig | anyObject_IF | 详情区域扩展配置 | | tableConfig | anyObject_IF | 表格区域扩展配置 | | customValidator | any[] | 自定义校验规则 | | customHide | (form) => boolean | 自定义隐藏逻辑 | | customType | (form) => crudType_TP | 自定义字段类型 | | customText | (value, prop) => string | 自定义展示文本 | | filterCallback | (options, form) => options | 选项过滤回调 | | onChange | (value, item, form) => void | 值变更回调 |

进阶功能

1. 联动筛选

下拉选项根据其他字段值动态过滤:

{
  label: '省份',
  dataIndex: 'province',
  type: 'select',
  options: () => getProvinceList(),
  onChange: (value, item, form) => {
    form.value.city = undefined // 清空城市选择
  }
},
{
  label: '城市',
  dataIndex: 'city',
  type: 'select',
  options: [],
  filterCallback: (selectOptions, form) => {
    // 根据省份过滤城市列表
    return selectOptions.filter(city => 
      city.provinceId === form.value.province
    )
  }
}

2. 动态显示/隐藏字段

根据表单其他字段值决定是否显示:

{
  label: '类型',
  dataIndex: 'type',
  type: 'radio',
  options: [
    { label: '固定', value: 'fixed' },
    { label: '动态', value: 'dynamic' }
  ]
},
{
  label: '固定值',
  dataIndex: 'fixedValue',
  type: 'input',
  customHide: (form) => {
    return form.type !== 'fixed'  // 类型不为固定时隐藏
  }
}

3. 动态切换字段类型

根据条件改变输入组件类型:

{
  label: '数据值',
  dataIndex: 'value',
  customType: (form) => {
    return form.type === 'number' ? 'number' : 'input'
  }
}

4. 自定义表格列渲染

使用插槽自定义表格单元格的显示:

<yuTable :columns="diyTableColumns" :data="dataSource">
  <!-- 自定义状态列 -->
  <template #status="{ record }">
    <el-tag :type="record.status === 1 ? 'success' : 'danger'">
      {{ record.status === 1 ? '启用' : '禁用' }}
    </el-tag>
  </template>
  
  <!-- 操作列 -->
  <template #action="{ record }">
    <el-button type="text" @click="handleEdit(record)">编辑</el-button>
  </template>
</yuTable>

columns 中定义插槽名:

{
  label: '状态',
  dataIndex: 'status',
  config: { slotName: 'status' }
}

5. 异步加载选项

选项数据从 API 异步获取:

{
  label: '角色',
  dataIndex: 'roleId',
  type: 'select',
  options: async () => {
    const res = await fetch('/api/roles')
    return res.data.map(item => ({
      label: item.name,
      value: item.id
    }))
  }
}

6. 自定义校验规则

{
  label: '手机号',
  dataIndex: 'phone',
  type: 'input',
  isRequired: true,
  customValidator: [
    {
      validator: (rule, value, callback) => {
        if (!/^1[3-9]\d{9}$/.test(value)) {
          callback(new Error('请输入正确的手机号'))
        } else {
          callback()
        }
      },
      trigger: 'blur'
    }
  ]
}

7. 自定义展示文本

{
  label: '状态',
  dataIndex: 'status',
  type: 'select',
  options: [
    { label: '启用', value: 1 },
    { label: '禁用', value: 0 }
  ],
  customText: (value, prop) => {
    return `<span style="color: ${value === '启用' ? 'green' : 'red'}">${value}</span>`
  },
  isInnerHtml: true  // 开启 HTML 渲染
}

8. 表格列配置扩展

{
  label: '金额',
  dataIndex: 'amount',
  type: 'number',
  unit: '元',
  tableConfig: {
    width: 120,
    sortable: true,
    align: 'right'
  }
}

工具函数

columns 处理工具

import { 
  getSearchColumns,   // 从 columns 提取搜索配置
  getTableColumns,    // 从 columns 提取表格配置
  getDetailColumns,   // 从 columns 提取详情表单配置
  getDealColumns      // 处理异步 options
} from 'yu-vue3-ui/utils/columns'

表单校验

import { getRules } from 'yu-vue3-ui/utils/formRules'

const rules = getRules(options)

数据格式化

import { treeFormat, getOneDimensional } from 'yu-vue3-ui/utils/dataFormat'

// 将树形数据转换为 options 格式
const options = treeFormat(data, 'name', 'id', 'children')

// 将树形数据扁平化为一维数组
const flatData = getOneDimensional(treeData)

大屏自适应

import { useIndex } from 'yu-vue3-ui/utils/adaptiveScaling'

const appRef = ref()
onMounted(() => {
  useIndex(appRef.value, 1920, 1080)  // 设计稿尺寸
})

Hooks API

indexHooks - 列表页面 Hook

interface hooksOptions {
  columns: gCrud_IF[]                    // 列配置
  url: {                                 // API 接口
    list: string
    add?: string
    edit?: string
    delete?: string
    export?: string
  }
  name?: string                          // 自定义表头缓存 key
  key?: string                           // 主键字段名,默认 'id'
  defaultParams?: object                 // 默认查询参数
  noRunList?: boolean                    // 是否不自动加载列表
  beforeSetData?: (data) => data         // 数据处理前回调
  afterGetList?: (dataSource) => void     // 数据获取后回调
  beforeSetParams?: (params) => params   // 查询参数处理前回调
  getDealColumns?: (columns) => Promise  // 自定义 columns 处理
}

const result = indexHooks(options)

// 返回值
{
  searchColumns,      // 搜索表单配置
  detailColumns,      // 详情表单配置
  diyTableColumns,    // 表格列配置(支持自定义表头)
  detailsRef,         // 详情弹窗实例引用
  importRef,          // 导入弹窗实例引用
  pageParams,         // 分页参数 { pageNum, pageSize }
  queryParam,         // 查询参数(包含分页和搜索条件)
  dataSource,          // 表格数据数组
  loading,            // 加载状态
  openTableHeader,    // 自定义表头弹窗显示状态
  selectList,         // 表格多选选中的行数据
  getList,            // 获取列表数据
  handleAdd,          // 打开新增弹窗
  handleEdit,         // 打开编辑弹窗
  handleDetails,      // 打开详情弹窗
  handleDelete,       // 删除单条数据
  handleReset,        // 重置搜索条件
  handleExport,       // 导出数据
  handleImport,       // 打开导入弹窗
  handleSizeChange,   // 分页大小变更
  handleCurrentChange,// 页码变更
  handleTableHeader,  // 打开自定义表头弹窗
  changeColumn,       // 自定义表头变更回调
  setDealColumns,     // 重新处理 columns
  getParams,          // 获取当前查询参数
  selectTable,        // 表格选择回调
  enter               // 回车搜索
}

detailsHooks - 详情弹窗 Hook

interface detailsHooksOptions {
  url: {                      // API 接口
    add: string
    edit: string
    getById: string
  }
  key?: string                // 主键字段名,默认 'id'
  defaultForm?: object        // 表单默认值
  afterOpen?: () => void      // 弹窗打开后回调
  beforeSetValue?: (data) => data    // 数据回填前处理
  beforeSetParams?: (params) => params // 提交参数处理前回调
  afterSubmit?: (res) => void  // 提交成功后回调
  getAction: (url, params) => Promise   // GET 请求方法
  httpAction: (url, params, method) => Promise // 通用请求方法
}

const result = detailsHooks(options)

// 返回值
{
  show,           // 弹窗显示状态
  title,          // 弹窗标题
  isDetails,      // 是否为详情查看模式
  form,           // 表单数据对象
  loading,        // 提交按钮加载状态
  gFormRef,       // 表单实例(用于调用 validate/resetFields)
  handleOpen,     // 打开弹窗
  handleOk,       // 确认提交
  handleCancel,   // 取消关闭
  resetFields,    // 重置表单
  clearValidate  // 清除校验状态
}

组件列表

yuTable - 增强表格组件

基于 Element Plus Table 封装,支持选项翻译显示。

<yuTable :columns="columns" :data="dataSource" border>
  <template #action="{ record }">
    <el-button @click="handleEdit(record)">编辑</el-button>
  </template>
</yuTable>

暴露方法

  • setTable(callback) - 获取 table 实例
  • toggleSelection(rows) - 选中指定行
  • clearSelection() - 清空选择

yuForm - 动态表单组件

根据配置自动渲染表单项。

<yuForm 
  v-model="formData" 
  :options="formColumns" 
  :span="24"
  :disabled="isView"
/>

暴露方法

  • validate() - 校验表单
  • resetFields() - 重置表单
  • clearValidate() - 清除校验状态

yuMain - 主页布局组件

带可折叠搜索面板的主布局。

<yuMain :showSearch="true" :searchWidth="300">
  <template #search>
    <!-- 搜索表单 -->
  </template>
  <!-- 主内容 -->
</yuMain>

yuScrollTable - 滚动表格组件

数据自动滚动展示,适合公告、消息等场景。

<yuScrollTable :changeTime="3000">
  <div class="scroll-box">
    <div class="scroll-item" v-for="item in list">
      {{ item.title }}
    </div>
  </div>
</yuScrollTable>

Props

  • scrollBox - 滚动容器选择器,默认 .scroll-box
  • scrollItem - 滚动项选择器,默认 .scroll-item
  • changeTime - 滚动间隔时间(ms),默认 3000

暴露方法

  • init() - 重新初始化
  • startAnimate() - 开始滚动
  • stopAnimate() - 停止滚动
  • clear() - 清除

yuMap - 天地图组件

集成天地图的地图展示。

<yuMap ref="mapRef" @changeZoom="handleZoomChange" />

暴露方法

  • initMap(lng, lat, zoom) - 初始化地图

yuWaveformChart - 波形图表组件

基于 Canvas 的实时波形绘制。

<yuWaveformChart
  :data="waveData"
  :chartDuration="18"
  :dataUpdateInterval="100"
  lineStyle="color: #ffa34f; lineWidth: 2"
/>

依赖

  • Vue 3.4+
  • Element Plus 2.7+

License

MIT