Crud 增删改查
集成z-form
和z-table
组件,实现增删改查功能。
表格接口
配置request
中searchApi
、deleteApi
、addApi
、editApi
可以直接实现表格数据获取、删除数据、新增和编辑数据操作。
<!-- eslint-disable no-console -->
<script lang="ts" setup>
import { ref } from 'vue'
const columns = ref([
{
prop: 'name',
label: '姓名',
form: {
component: 'input',
label: '姓名',
field: 'name',
},
},
{
prop: 'gender',
label: '性别',
form: {
component: 'select',
label: '性别',
field: 'gender',
},
},
{
prop: 'age',
label: '年龄',
form: {
component: 'input',
label: '年龄',
field: 'age',
},
},
{
prop: 'time',
label: '出生日期',
},
])
const request = ref({
searchApi: getTableData,
deleteApi: commonApi,
submitApi: commonApi,
})
const tableData = ref([])
const pagination = ref({
page: 1,
pageSize: 2,
total: 0,
})
const loading = ref(false)
const formData = ref({})
const options = {
gender: [{ label: 'male', value: 'male' }, { label: 'female', value: 'female' }],
}
function getTableData(params: any) {
console.log(params, 'getTableData params')
return new Promise((resolve) => {
setTimeout(() => {
const data = [
{
id: 1,
name: 'Steven',
gender: 'male',
age: 22,
time: '2020-01-01',
},
{
id: 2,
name: 'Helen',
gender: 'male',
age: 12,
time: '2012-01-01',
},
{
id: 3,
name: 'Nancy',
gender: 'female',
age: 18,
time: '2018-01-01',
},
{
id: 4,
name: 'Jack',
gender: 'male',
age: 28,
time: '2028-01-01',
},
]
resolve({
data: {
page: 1,
pageSize: 2,
total: 4,
list: data.slice((pagination.value.page - 1) * pagination.value.pageSize, pagination.value.page * pagination.value.pageSize),
},
})
}, 100)
})
}
function commonApi(params: any) {
console.log(JSON.stringify(params), 'commonApi params')
return new Promise((resolve) => {
setTimeout(() => {
resolve({
msg: 'success',
code: 200,
})
}, 100)
})
}
</script>
<template>
<z-crud
v-model:formData="formData"
v-model:data="tableData"
v-model:pagination="pagination"
v-model:loading="loading"
:options="options"
:columns="columns"
:request="request"
/>
</template>
表格数据接口配置
配置request
中alias
字段可以自定义数据路径,默认为data.list
和data.total
。
<!-- eslint-disable no-console -->
<script lang="ts" setup>
import { ref } from 'vue'
interface RowData {
id: number
name: string
gender: string
age: number
time: string
}
const columns = ref([
{
prop: 'name',
label: '姓名',
form: {
component: 'input',
label: '姓名',
field: 'name',
},
},
{
prop: 'gender',
label: '性别',
form: {
component: 'select',
label: '性别',
field: 'gender',
},
},
{
prop: 'age',
label: '年龄',
form: {
component: 'input',
label: '年龄',
field: 'age',
},
},
{
prop: 'time',
label: '出生日期',
},
])
const request = ref({
searchApi: getTableData,
deleteApi: commonApi,
submitApi: commonApi,
detailApi,
alias: {
list: 'result.data',
total: 'result.all',
},
})
const tableData = ref([])
const pagination = ref({
page: 1,
pageSize: 2,
total: 0,
})
const loading = ref(false)
const formData = ref({})
const options = {
gender: [{ label: 'male', value: 'male' }, { label: 'female', value: 'female' }],
}
function getTableData(params: any) {
console.log(params, 'getTableData params')
return new Promise((resolve) => {
setTimeout(() => {
const data = [
{
id: 1,
name: 'Steven',
gender: 'male',
age: 22,
time: '2020-01-01',
},
{
id: 2,
name: 'Helen',
gender: 'male',
age: 12,
time: '2012-01-01',
},
{
id: 3,
name: 'Nancy',
gender: 'female',
age: 18,
time: '2018-01-01',
},
{
id: 4,
name: 'Jack',
gender: 'male',
age: 28,
time: '2028-01-01',
},
]
resolve({
result: {
page: 1,
pageSize: 2,
all: 4,
data: data.slice((pagination.value.page - 1) * pagination.value.pageSize, pagination.value.page * pagination.value.pageSize),
},
})
}, 100)
})
}
function commonApi(params: any) {
console.log(JSON.stringify(params), 'commonApi params')
return new Promise((resolve) => {
setTimeout(() => {
resolve({
msg: 'success',
code: 200,
})
}, 100)
})
}
function detailApi({ id, row }: { id: number, row: RowData }) {
console.log(id, row, 'detailApi params')
return new Promise((resolve) => {
setTimeout(() => {
resolve({
data: {
id: 3,
name: 'Nancy',
gender: 'female',
age: 18,
time: '2018-01-01',
},
})
}, 100)
})
}
</script>
<template>
<z-crud
v-model:formData="formData"
v-model:data="tableData"
v-model:pagination="pagination"
v-model:loading="loading"
:options="options"
:columns="columns"
:request="request"
/>
</template>
支持传入函数自定义返回。
<!-- eslint-disable no-console -->
<script lang="ts" setup>
import { ref } from 'vue'
interface RowData {
id: number
name: string
gender: string
age: number
time: string
}
interface GetTableDataRes { result: { page: number, pageSize: number, data: RowData[], all: number } }
const columns = ref([
{
prop: 'name',
label: '姓名',
form: {
component: 'input',
label: '姓名',
field: 'name',
},
},
{
prop: 'gender',
label: '性别',
form: {
component: 'select',
label: '性别',
field: 'gender',
},
},
{
prop: 'age',
label: '年龄',
form: {
component: 'input',
label: '年龄',
field: 'age',
},
},
{
prop: 'time',
label: '出生日期',
},
])
const request = ref({
searchApi: getTableData,
deleteApi: commonApi,
submitApi: commonApi,
alias: {
list: (res: GetTableDataRes) => res.result.data,
total: (res: GetTableDataRes) => res.result.all,
},
})
const tableData = ref([])
const pagination = ref({
page: 1,
pageSize: 2,
total: 0,
})
const loading = ref(false)
const formData = ref({})
const options = {
gender: [{ label: 'male', value: 'male' }, { label: 'female', value: 'female' }],
}
function getTableData(params: any): Promise<GetTableDataRes> {
console.log(params, 'getTableData params')
return new Promise((resolve) => {
setTimeout(() => {
const data = [
{
id: 1,
name: 'Steven',
gender: 'male',
age: 22,
time: '2020-01-01',
},
{
id: 2,
name: 'Helen',
gender: 'male',
age: 12,
time: '2012-01-01',
},
{
id: 3,
name: 'Nancy',
gender: 'female',
age: 18,
time: '2018-01-01',
},
{
id: 4,
name: 'Jack',
gender: 'male',
age: 28,
time: '2028-01-01',
},
]
resolve({
result: {
page: 1,
pageSize: 2,
all: 4,
data: data.slice((pagination.value.page - 1) * pagination.value.pageSize, pagination.value.page * pagination.value.pageSize),
},
})
}, 100)
})
}
function commonApi(params: any) {
console.log(JSON.stringify(params), 'commonApi params')
return new Promise((resolve) => {
setTimeout(() => {
resolve({
msg: 'success',
code: 200,
})
}, 100)
})
}
</script>
<template>
<z-crud
v-model:formData="formData"
v-model:data="tableData"
v-model:pagination="pagination"
v-model:loading="loading"
:options="options"
:columns="columns"
:request="request"
/>
</template>
表格数据方法自定义
支持通过request.searchFunc
自定义表格数据方法。
<!-- eslint-disable no-console -->
<script lang="ts" setup>
import { ref } from 'vue'
interface RowData {
id: number
name: string
gender: string
age: number
time: string
}
interface GetTableDataRes { data: { page: number, pageSize: number, list: RowData[], total: number } }
const columns = ref([
{
prop: 'name',
label: '姓名',
form: {
component: 'input',
label: '姓名',
field: 'name',
},
},
{
prop: 'gender',
label: '性别',
form: {
component: 'select',
label: '性别',
field: 'gender',
},
},
{
prop: 'age',
label: '年龄',
form: {
component: 'input',
label: '年龄',
field: 'age',
},
},
{
prop: 'time',
label: '出生日期',
},
])
const tableData = ref<RowData[]>([])
const pagination = ref({
page: 1,
pageSize: 2,
total: 0,
})
const loading = ref(false)
const formData = ref({})
const request = ref({
deleteApi: commonApi,
submitApi: commonApi,
searchFunc: async ({ params }: any) => {
loading.value = true
try {
console.log(params, 'searchFunc params')
const res = await getData(params)
tableData.value = res.data.list
pagination.value.total = res.data.total
}
catch {
}
loading.value = false
},
})
const options = {
gender: [{ label: 'male', value: 'male' }, { label: 'female', value: 'female' }],
}
function getData(params: any): Promise<GetTableDataRes> {
console.log(params, 'params')
return new Promise((resolve) => {
setTimeout(() => {
const data = [
{
id: 1,
name: 'Steven',
gender: 'male',
age: 22,
time: '2020-01-01',
},
{
id: 2,
name: 'Helen',
gender: 'male',
age: 12,
time: '2012-01-01',
},
{
id: 3,
name: 'Nancy',
gender: 'female',
age: 18,
time: '2018-01-01',
},
{
id: 4,
name: 'Jack',
gender: 'male',
age: 28,
time: '2028-01-01',
},
]
resolve({
data: {
page: 1,
pageSize: 2,
total: 4,
list: data.slice((pagination.value.page - 1) * pagination.value.pageSize, pagination.value.page * pagination.value.pageSize),
},
})
}, 100)
})
}
function commonApi(params: any) {
console.log(JSON.stringify(params), 'commonApi params')
return new Promise((resolve) => {
setTimeout(() => {
resolve({
msg: 'success',
code: 200,
})
}, 100)
})
}
</script>
<template>
<z-crud
v-model:formData="formData"
v-model:data="tableData"
v-model:pagination="pagination"
v-model:loading="loading"
:options="options"
:columns="columns"
:request="request"
/>
</template>
表格数据处理
支持通过request.tableData
二次处理表格数据。
<!-- eslint-disable no-console -->
<script lang="ts" setup>
import { ref } from 'vue'
interface RowData {
id: number
name: string
gender: string
age: number
time: string
}
const columns = ref([
{
prop: 'name',
label: '姓名',
form: {
component: 'input',
label: '姓名',
field: 'name',
},
},
{
prop: 'gender',
label: '性别',
form: {
component: 'select',
label: '性别',
field: 'gender',
},
},
{
prop: 'age',
label: '年龄',
form: {
component: 'input',
label: '年龄',
field: 'age',
},
},
{
prop: 'time',
label: '出生日期',
},
])
const tableData = ref([])
const pagination = ref({
page: 1,
pageSize: 2,
total: 0,
})
const loading = ref(false)
const formData = ref({})
const request = ref({
searchApi: getData,
deleteApi: commonApi,
submitApi: commonApi,
tableData: (data: RowData[]) => {
return data.map((item, index) => ({
...item,
name: item.name + index,
}))
},
})
const options = {
gender: [{ label: 'male', value: 'male' }, { label: 'female', value: 'female' }],
}
function getData() {
return new Promise((resolve) => {
setTimeout(() => {
const data = [
{
id: 1,
name: 'Steven',
gender: 'male',
age: 22,
time: '2020-01-01',
},
{
id: 2,
name: 'Helen',
gender: 'male',
age: 12,
time: '2012-01-01',
},
{
id: 3,
name: 'Nancy',
gender: 'female',
age: 18,
time: '2018-01-01',
},
{
id: 4,
name: 'Jack',
gender: 'male',
age: 28,
time: '2028-01-01',
},
]
resolve({
data: {
page: 1,
pageSize: 2,
total: 4,
list: data.slice((pagination.value.page - 1) * pagination.value.pageSize, pagination.value.page * pagination.value.pageSize),
},
})
}, 100)
})
}
function commonApi(params: any) {
console.log(JSON.stringify(params), 'commonApi params')
return new Promise((resolve) => {
setTimeout(() => {
resolve({
msg: 'success',
code: 200,
})
}, 100)
})
}
</script>
<template>
<z-crud
v-model:formData="formData"
v-model:data="tableData"
v-model:pagination="pagination"
v-model:loading="loading"
:options="options"
:columns="columns"
:request="request"
/>
</template>
回调
支持通过request.beforeData
和request.afterData
在获取表格数据前后做些事情。
<!-- eslint-disable no-console -->
<script lang="ts" setup>
import { ref } from 'vue'
interface RowData {
id: number
name: string
gender: string
age: number
time: string
}
interface GetTableDataRes { data: { page: number, pageSize: number, list: RowData[], total: number } }
const columns = ref([
{
prop: 'name',
label: '姓名',
form: {
component: 'input',
label: '姓名',
field: 'name',
},
},
{
prop: 'gender',
label: '性别',
form: {
component: 'select',
label: '性别',
field: 'gender',
},
},
{
prop: 'age',
label: '年龄',
form: {
component: 'input',
label: '年龄',
field: 'age',
},
},
{
prop: 'time',
label: '出生日期',
},
])
const tableData = ref([])
const pagination = ref({
page: 1,
pageSize: 2,
total: 0,
})
const loading = ref(false)
const formData = ref({})
const request = ref({
searchApi: getData,
deleteApi: commonApi,
submitApi: commonApi,
beforeData: async () => {
await delay(100)
console.log('beforeData')
},
afterData: (res: GetTableDataRes) => {
console.log(res, 'afterData')
},
})
const options = {
gender: [{ label: 'male', value: 'male' }, { label: 'female', value: 'female' }],
}
function delay(time: number) {
return new Promise((resolve) => {
setTimeout(resolve, time)
})
}
function getData(): Promise<GetTableDataRes> {
return new Promise((resolve) => {
setTimeout(() => {
const data = [
{
id: 1,
name: 'Steven',
gender: 'male',
age: 22,
time: '2020-01-01',
},
{
id: 2,
name: 'Helen',
gender: 'male',
age: 12,
time: '2012-01-01',
},
{
id: 3,
name: 'Nancy',
gender: 'female',
age: 18,
time: '2018-01-01',
},
{
id: 4,
name: 'Jack',
gender: 'male',
age: 28,
time: '2028-01-01',
},
]
resolve({
data: {
page: 1,
pageSize: 2,
total: 4,
list: data.slice((pagination.value.page - 1) * pagination.value.pageSize, pagination.value.page * pagination.value.pageSize),
},
})
}, 100)
})
}
function commonApi(params: any) {
console.log(JSON.stringify(params), 'commonApi params')
return new Promise((resolve) => {
setTimeout(() => {
resolve({
msg: 'success',
code: 200,
})
}, 100)
})
}
</script>
<template>
<z-crud
v-model:formData="formData"
v-model:data="tableData"
v-model:pagination="pagination"
v-model:loading="loading"
:options="options"
:columns="columns"
:request="request"
/>
</template>
内部方法
支持通过表格外部再次调用getTableData
方法。
<!-- eslint-disable no-console -->
<script lang="ts" setup>
import { ref } from 'vue'
const columns = ref([
{
prop: 'name',
label: '姓名',
form: {
component: 'input',
label: '姓名',
field: 'name',
},
},
{
prop: 'gender',
label: '性别',
form: {
component: 'select',
label: '性别',
field: 'gender',
},
},
{
prop: 'age',
label: '年龄',
form: {
component: 'input',
label: '年龄',
field: 'age',
},
},
{
prop: 'time',
label: '出生日期',
},
])
const tableData = ref([])
const pagination = ref({
page: 1,
pageSize: 2,
total: 0,
})
const loading = ref(false)
const formData = ref({})
const request = ref({
searchApi: getData,
deleteApi: commonApi,
submitApi: commonApi,
})
const crud = ref()
const options = {
gender: [{ label: 'male', value: 'male' }, { label: 'female', value: 'female' }],
}
function getData() {
return new Promise((resolve) => {
setTimeout(() => {
const data = [
{
id: 1,
name: 'Steven',
gender: 'male',
age: 22,
time: '2020-01-01',
},
{
id: 2,
name: 'Helen',
gender: 'male',
age: 12,
time: '2012-01-01',
},
{
id: 3,
name: 'Nancy',
gender: 'female',
age: 18,
time: '2018-01-01',
},
{
id: 4,
name: 'Jack',
gender: 'male',
age: 28,
time: '2028-01-01',
},
]
resolve({
data: {
page: 1,
pageSize: 2,
total: 4,
list: data.slice((pagination.value.page - 1) * pagination.value.pageSize, pagination.value.page * pagination.value.pageSize),
},
})
}, 100)
})
}
function commonApi(params: any) {
console.log(JSON.stringify(params), 'commonApi params')
return new Promise((resolve) => {
setTimeout(() => {
resolve({
msg: 'success',
code: 200,
})
}, 100)
})
}
function handleClick() {
crud.value.getTableData()
}
</script>
<template>
<el-button @click="handleClick">
click
</el-button>
<z-crud
ref="crud"
v-model:formData="formData"
v-model:data="tableData"
v-model:pagination="pagination"
v-model:loading="loading"
:options="options"
:columns="columns"
:request="request"
/>
</template>
操作自定义
如需要自定义操作,可以使用refresh
、search
、reset
、submit
、delete
等事件实现刷新、查询、重置和删除等操作。
<!-- eslint-disable no-console -->
<script lang="ts" setup>
import { ref } from 'vue'
import type { CrudDeleteDialogConfirmParams, Pagination } from 'ideaz-element'
interface RowData {
id: number
name: string
gender: string
age: number
time: string
}
interface GetTableDataRes { data: { page: number, pageSize: number, list: RowData[], total: number } }
const columns = ref([
{
prop: 'name',
label: '姓名',
form: {
component: 'input',
label: '姓名',
field: 'name',
required: true,
},
},
{
prop: 'gender',
label: '性别',
form: {
component: 'select',
label: '性别',
field: 'gender',
},
},
{
prop: 'age',
label: '年龄',
form: {
component: 'input',
label: '年龄',
field: 'age',
},
},
{
prop: 'time',
label: '出生日期',
},
])
const tableData = ref<RowData[]>([])
const pagination = ref({
page: 1,
pageSize: 2,
total: 0,
})
const loading = ref(false)
const formData = ref({})
const dialog = ref({
confirmButtonLoading: false,
})
const options = {
gender: [{ label: 'male', value: 'male' }, { label: 'female', value: 'female' }],
}
function getData(params: any): Promise<GetTableDataRes> {
console.log(params, 'params')
return new Promise((resolve) => {
setTimeout(() => {
const data = [
{
id: 1,
name: 'Steven',
gender: 'male',
age: 22,
time: '2020-01-01',
},
{
id: 2,
name: 'Helen',
gender: 'male',
age: 12,
time: '2012-01-01',
},
{
id: 3,
name: 'Nancy',
gender: 'female',
age: 18,
time: '2018-01-01',
},
{
id: 4,
name: 'Jack',
gender: 'male',
age: 28,
time: '2028-01-01',
},
]
resolve({
data: {
page: 1,
pageSize: 2,
total: 4,
list: data.slice((pagination.value.page - 1) * pagination.value.pageSize, pagination.value.page * pagination.value.pageSize),
},
})
}, 100)
})
}
function commonApi(params: any) {
console.log(JSON.stringify(params), 'commonApi params')
return new Promise((resolve) => {
setTimeout(() => {
resolve({
msg: 'success',
code: 200,
})
}, 100)
})
}
async function getTableData() {
loading.value = true
try {
const params = {
...pagination.value,
...formData.value,
}
const res = await getData(params)
tableData.value = res.data.list
pagination.value.total = res.data.total
}
catch (error) {
console.log(error)
}
loading.value = false
}
function handleRefresh(val: Pagination) {
pagination.value.page = val.page!
pagination.value.pageSize = val.pageSize!
getTableData()
}
function handleSearch() {
pagination.value.page = 1
getTableData()
}
function handleDelete() {
window.ZDialogTip({
type: 'warning',
message: '确定删除该条数据吗?',
title: '警告',
onConfirm: ({ done, confirmButtonLoading }: CrudDeleteDialogConfirmParams<RowData>) => {
confirmButtonLoading.value = true
done()
confirmButtonLoading.value = false
},
})
}
async function handleSubmit({ formData, type, rowData, formRef, done, isValid }: { formData: any, type: 'add' | 'edit', rowData: RowData, formRef: any, done: () => void, isValid: boolean }) {
if (isValid) {
dialog.value.confirmButtonLoading = true
try {
const params = {
...formData,
}
console.log(params, rowData, formRef, 'params')
if (type === 'edit')
await commonApi({ ...params, id: rowData.id })
else
await commonApi(params)
dialog.value.confirmButtonLoading = false
done()
getTableData()
}
catch {
}
dialog.value.confirmButtonLoading = false
}
}
getTableData()
</script>
<template>
<z-crud
v-model:formData="formData"
v-model:data="tableData"
v-model:pagination="pagination"
v-model:loading="loading"
:options="options"
:columns="columns"
:dialog="dialog"
@refresh="handleRefresh"
@reset="handleSearch"
@search="handleSearch"
@submit="handleSubmit"
@delete="handleDelete"
/>
</template>
request 属性
属性名 | 说明 | 类型 | 默认 |
---|---|---|---|
searchApi | 查询接口 | (params: any) => promise | — |
submitApi | 编辑新增确认 | ({ [key: string]: any, row: any, type: 'add' / 'edit' / 'view', formData: any }) => promise | — |
deleteApi | 删除接口 | ({ [key: string]?: any, row?: any, selectionData?: any }) => promise | — |
addApi | 新增接口 | ({ type: 'add' / 'edit' / 'view', formData: any }) => promise | — |
editApi | 编辑接口 | ({ [key: string]: any, row: any, type: 'add' / 'edit' / 'view', formData: any }) => promise | — |
detailApi | 详情接口 | ({ [key: string]: any, row: any }) => promise | — |
alias | 数据路径自定义 | object | — |
beforeData | 表格数据接口调用前的回调 | Function | — |
afterData | 表格数据接口调用后的回调 | (res) => void | — |
searchFunc | 查询方法重写 | ({ params }) => any | — |
tableData | 表格数据自定义返回 | (res) => any | — |
alias 属性
属性名 | 说明 | 类型 | 默认 |
---|---|---|---|
list | 表格数据路径 | string / (res) => array | data.list |
total | 表格数据总数路径 | string / (res) => number | data.total |