Skip to content

Crud 增删改查

集成z-formz-table组件,实现增删改查功能。

表格接口

配置requestsearchApideleteApiaddApieditApi可以直接实现表格数据获取、删除数据、新增和编辑数据操作。

<!-- 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>

表格数据接口配置

配置requestalias字段可以自定义数据路径,默认为data.listdata.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.beforeDatarequest.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>

操作自定义

如需要自定义操作,可以使用refreshsearchresetsubmitdelete等事件实现刷新、查询、重置和删除等操作。

<!-- 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) => arraydata.list
total表格数据总数路径string / (res) => numberdata.total

Released under the MIT License.