yu-vue3-ui

基于 Vue 3 + Element Plus 的业务组件库,通过配置化的方式简化后台管理系统的 CRUD 页面开发。
6,111
Install
npm install yu-vue3-ui
Latest Version:1.0.133
Older releases:3
Last Updated:Jul 7, 2026
Links: npm
Maintainer: yuxingheng

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

Version History

Version Released License
1.0.133
1.0.132
1.0.131
1.0.130
1.0.129