UNPKG

z-crud-table

Version:

A powerful and flexible CRUD table component for Vue 3 and Element Plus.

200 lines (167 loc) 10 kB
# CrudTable - 基于 Vue 3 和 Element Plus 的高级 CRUD 组件 `CrudTable` 是一个功能全面、高度可定制的 CRUD 表格组件,旨在通过声明式的方式,极大地简化数据驱动的页面开发。它封装了常见的增、删、改、查、分页、批量操作等逻辑,让开发者能更专注于业务本身。 ## ✨ 功能特性 - **API驱动**: 通过 props 传入 URL 字符串,组件内置 `axios` 请求逻辑。 - **高度可定制**: 提供丰富的插槽,用于自定义查询条件、表格列、操作按钮等。 - **配置驱动表单**: 支持通过 JSON 数组配置动态渲染新增/编辑弹窗内的表单。 - **完整的 `el-table` 功能**: 继承 `el-table` 所有原生属性和事件,无缝衔接现有使用习惯。 - **强大的生命周期**: 提供完整的 `onBefore``onAfter` 钩子,方便在操作前后进行数据处理和逻辑注入。 - **灵活的列控制**: 可通过 props 单独控制多选框、序号列、操作列以及编辑/删除按钮的显示与隐藏。 - **开箱即用**: 内置了分页、单行删除、批量删除等常用功能。 ## 📦 安装 ``` npm install your-crud-table-package-name ``` ## 🚀 快速上手 在您的 Vue 组件中使用 `CrudTable```` <template> <crud-table ref="crudTableRef" :api-url-query="'/api/users'" :api-url-detail="'/api/users/detail'" :api-url-create="'/api/users'" :api-url-update="'/api/users'" :api-url-delete="'/api/users'" :initial-search-form="{ pageNum: 1, pageSize: 5 }" :dialog-form-config="dialogFormConfig" > <el-table-column prop="name" label="姓名" /> <el-table-column prop="email" label="邮箱" /> </crud-table> </template> <script setup lang="ts"> import { ref } from 'vue'; import CrudTable from 'your-crud-table-package-name'; const crudTableRef = ref(null); const dialogFormConfig = ref([ { type: 'input', prop: 'name', label: '姓名' }, { type: 'input', prop: 'email', label: '邮箱' }, ]); </script> ``` ## **API 文档** ### **属性 (Props)** | 属性名 | 描述 | 类型 | 是否必需 | 默认值 | | --- | --- | --- | --- | --- | | **API 配置** | | | | | | `apiUrlQuery` | 获取表格列表数据的接口地址。 | `String` | `true` | - | | `apiUrlDetail` | 获取单条数据详情的接口地址(用于编辑时回填表单)。 | `String` | `true` | - | | `apiUrlCreate` | 创建新条目的接口地址。 | `String` | `true` | - | | `apiUrlUpdate` | 更新条目的接口地址。 | `String` | `true` | - | | `apiUrlDelete` | 删除条目的接口地址。 | `String` | `true` | - | | **功能控制** | | | | | | `showSelectionColumn` | 是否显示表格的多选框列。 | `Boolean` | `false` | `true` | | `showIndexColumn` | 是否显示表格的序号列。 | `Boolean` | `false` | `true` | | `showActionsColumn` | 是否显示操作列。 | `Boolean` | `false` | `true` | | `showEditButton` | 是否在操作列中显示默认的“编辑”按钮。 | `Boolean` | `false` | `true` | | `showDeleteButton` | 是否在操作列中显示默认的“删除”按钮。 | `Boolean` | `false` | `true` | | `actionsColumnWidth` | 操作列的宽度。 | `Number` | `false` | `120` | | **表单与弹窗** | | | | | | `dialogWidth` | 新增/编辑弹窗的宽度。 | `String` | `false` | `'50%'` | | `dialogFormConfig` | **动态表单配置数组**,用于快速生成弹窗内的表单。 | `Array` | `false` | `[]` | | `dialogFormRules` | 弹窗表单的 [Element Plus 验证规则](https://element-plus.org/zh-CN/component/form.html#%E8%A1%A8%E5%8D%95%E6%A0%A1%E9%AA%8C)。 | `Object` | `false` | `{}` | | **分页配置** | | | | | | `initialSearchForm` | 查询表单的初始值,**包含初始分页参数 `pageNum` 和 `pageSize`**。 | `Object` | `false` | `{ pageNum: 1, pageSize: 10 }` | | `showPagination` | 是否显示分页组件。 | `Boolean` | `false` | `true` | | `pageSizes` | 每页显示个数选择器的选项设置。 | `Array` | `false` | `[10, 20, 50, 100]` | | `paginationLayout` | 分页组件布局。 | `String` | `false` | `'total, sizes, prev, pager, next, jumper'` | | `paginationBackground` | 是否为分页按钮添加背景色。 | `Boolean` | `false` | `true` | | `paginationSmall` | 是否使用小型分页样式。 | `Boolean` | `false` | `false` | | `paginationHideOnSinglePage` | 只有一页时是否隐藏分页。 | `Boolean` | `false` | `false` | | **生命周期钩子** | | | | | | `onBeforeQuery` | 查询请求**前**执行。可用于修改请求参数。**必须返回**处理后的参数对象。 | `Function` | `false` | - | | `onAfterQuery` | 查询请求**后**执行。可用于格式化返回的列表数据。**必须返回**处理后的数据数组。 | `Function` | `false` | - | | `onBeforeOpenDialog` | 打开弹窗**前**执行。可用于预处理表单数据。 | `Function` | `false` | - | | `onAfterOpenDialog` | 打开弹窗**后**执行。可用于在弹窗渲染后执行某些操作。 | `Function` | `false` | - | | `onBeforeSubmit` | 表单提交**前**执行。可用于序列化提交的数据。**必须返回**处理后的数据对象。 | `Function` | `false` | - | | `onAfterSubmit` | 表单提交**后**执行。可用于执行提交成功后的副作用。 | `Function` | `false` | - | | `onBeforeDelete` | 删除操作**前**执行。可用于进行额外的确认。**返回 `false` 可中止删除**。 | `Function` | `false` | - | | `onAfterDelete` | 删除操作**后**执行。可用于执行删除成功后的副作用。 | `Function` | `false` | - | ### **插槽 (Slots)** | 插槽名称 | 作用域 (Props) | 描述 | | --- | --- | --- | | `default` | - | **(核心)** 用于定义表格的列 (`<el-table-column>`),除了序号列、复选框列和操作列。 | | `header` | - | 在整个组件最顶部插入内容,如页面大标题。 | | `query-conditions` | `{ searchForm }` | 自定义查询区域的表单项。`searchForm` 是响应式的查询对象。 | | `query-left` | - | 在“搜索”按钮左侧添加自定义按钮或内容。 | | `query-right` | - | 在“清空”按钮右侧添加自定义按钮或内容。 | | `action-left` | `{ selections }` | 在“新增”按钮左侧添加自定义按钮,可通过 `selections` 访问当前勾选的数据。 | | `action-right` | - | 在“新增”按钮右侧添加自定义按钮。 | | `actions` | `{ row }` | **(重要)** 自定义操作列的内容,可用于添加、修改或完全替换默认的编辑/删除按钮。 | | `dialog-form-content` | `{ formData, mode }` | **完全自定义**新增/编辑弹窗的表单内容。如果使用此插槽,`dialogFormConfig` 将被忽略。 | ### **事件 (Events)** | 事件名称 | 载荷 (Payload) | 描述 | | --- | --- | --- | | `@open-dialog` | `{ mode: string, data: object }` | 在新增或编辑弹窗打开后触发。 | | `@submit` | `{ mode: string, data: object }` | 在表单提交(新增或更新)成功**后**触发。 | | `@delete` | `number[]` | 在删除操作成功**后**触发,载荷为被删除的 ID 数组。 | ### **暴露的方法 (Exposed Methods)** 通过 `ref` 可以获取到组件实例,并调用其暴露的方法。 | 方法名称 | 参数 | 描述 | | --- | --- | --- | | `refresh()` | - | 强制刷新表格数据,使用当前的查询条件和分页状态。 | | `search()` | - | 重置到第一页并刷新数据,相当于点击“搜索”按钮。 | | `handleDelete(ids: number[])` | `ids` (ID 数组) | 触发删除操作,可用于父组件中自定义的批量删除逻辑。 | | `openDialog(mode, data)` | `mode`, `data` | 手动打开新增/编辑弹窗。 | ## **实践案例** ``` <template> <crud-table ref="crudTableRef" :api-url-query="'/api/users'" :api-url-detail="'/api/users/detail'" :api-url-create="'/api/users'" :api-url-update="'/api/users'" :api-url-delete="'/api/users'" :show-delete-button="false" actions-column-width="140" :initial-search-form="{ role: null, pageNum: 1, pageSize: 5 }" @submit="onSubmit" :on-after-query="handleAfterQuery" > <template #header> <h2 class="text-2xl font-semibold text-slate-700 mb-6">用户管理</h2> </template> <el-table-column prop="name" label="姓名" sortable /> <el-table-column prop="role" label="角色"> <template #default="scope"> <el-tag :type="scope.row.role === 'admin' ? 'warning' : 'info'"> {{ scope.row.role }} </el-tag> </template> </el-table-column> <el-table-column prop="createdAtFormatted" label="创建时间" /> <template #query-conditions="{ searchForm }"> <el-form-item label="姓名"> <el-input v-model="searchForm.name" clearable /> </el-form-item> </template> <template #actions="{ row }"> <el-button size="small" type="primary" link @click="crudTableRef?.openDialog('edit', row)">编辑</el-button> <el-button size="small" type="success" link @click="handleViewDetails(row)">详情</el-button> </template> </crud-table> </template> <script setup> import { ref } from 'vue'; import { ElMessage, ElMessageBox } from 'element-plus'; import CrudTable from './components/CrudTable.vue'; const crudTableRef = ref(null); // 使用生命周期钩子格式化数据 const handleAfterQuery = (data) => { return data.map(item => ({ ...item, createdAtFormatted: new Date(item.createdAt).toLocaleString('zh-CN'), })); }; // 监听事件 const onSubmit = (payload) => { ElMessage.success(`[Event] ${payload.mode} success!`); }; // 自定义方法 const handleViewDetails = (row) => { ElMessageBox.alert(JSON.stringify(row, null, 2), '详情'); }; </script> ```