|
|
@@ -1,262 +0,0 @@
|
|
|
-<script setup lang="ts">
|
|
|
-defineOptions({
|
|
|
- inheritAttrs: false
|
|
|
-})
|
|
|
-
|
|
|
-import { useForm } from '@/hooks/useForm'
|
|
|
-import { useTableQuery } from '@/hooks/useTableQuery'
|
|
|
-import { useTable } from '@/hooks/useTable'
|
|
|
-import type { DialogProps, DrawerProps } from 'element-plus'
|
|
|
-import type { BasicForm, ICRUD } from '@/types/form'
|
|
|
-import type { VxeToolbarProps } from 'vxe-table'
|
|
|
-
|
|
|
-interface CustomTable {
|
|
|
- showOperate?: boolean
|
|
|
- showEdit?: boolean
|
|
|
- showView?: boolean
|
|
|
- showDelete?: boolean
|
|
|
- operateWidth?: number
|
|
|
-}
|
|
|
-
|
|
|
-interface Props {
|
|
|
- crud: ICRUD
|
|
|
- pageSize?: number
|
|
|
- selection?: boolean
|
|
|
- formConfig: BasicForm
|
|
|
- dialogConfig?: Partial<DialogProps>
|
|
|
- drawerConfig?: Partial<DrawerProps>
|
|
|
- tableConfig?: CustomTable
|
|
|
- toolbarConfig?: VxeToolbarProps
|
|
|
- showToolbar?: boolean
|
|
|
- height?: string
|
|
|
- formMode?: 'dialog' | 'drawer'
|
|
|
- beforeCreate?: Function
|
|
|
-}
|
|
|
-
|
|
|
-const props = withDefaults(defineProps<Props>(), {
|
|
|
- pageSize: 10,
|
|
|
- selection: true,
|
|
|
- showToolbar: true,
|
|
|
- formMode: 'dialog'
|
|
|
-})
|
|
|
-const emits = defineEmits(['click-create', 'click-edit', 'click-view', 'checkbox-change', 'click-reset'])
|
|
|
-const slots = useSlots()
|
|
|
-
|
|
|
-// ============== 查询部分开始 ===============
|
|
|
-const { query, searchList, handleQuery, handleReset } = useTableQuery(props, emits)
|
|
|
-// ============== 查询部分结束 ===============
|
|
|
-
|
|
|
-// ============== 表格部分开始 ===============
|
|
|
-const {
|
|
|
- tableData,
|
|
|
- formData,
|
|
|
- total,
|
|
|
- curPage,
|
|
|
- loading,
|
|
|
- formVisible,
|
|
|
- multipleSelection,
|
|
|
- refresh,
|
|
|
- handleCreate,
|
|
|
- handleDelete,
|
|
|
- handleBatchDelete,
|
|
|
- handleUpdate,
|
|
|
- handleView,
|
|
|
- handleFormSuccess
|
|
|
-} = useTable(props, emits)
|
|
|
-
|
|
|
-const tableConfig = computed<CustomTable>(() => ({
|
|
|
- showOperate: true,
|
|
|
- showView: false,
|
|
|
- showEdit: true,
|
|
|
- showDelete: true,
|
|
|
- operateWidth: 140,
|
|
|
- ...props.tableConfig
|
|
|
-}))
|
|
|
-
|
|
|
-const xTable = ref<any>()
|
|
|
-const xToolbar = ref<any>()
|
|
|
-nextTick(() => {
|
|
|
- // 将表格和工具栏进行关联
|
|
|
- const $table = xTable.value
|
|
|
- const $toolbar = xToolbar.value
|
|
|
- $toolbar && $table.connect($toolbar)
|
|
|
-})
|
|
|
-
|
|
|
-const handleSelectionChange = () => {
|
|
|
- multipleSelection.value = xTable.value.getCheckboxRecords()
|
|
|
- emits('checkbox-change', multipleSelection.value)
|
|
|
-}
|
|
|
-
|
|
|
-// 动态计算table高度
|
|
|
-const toolbarRef = ref<any>(null)
|
|
|
-const paginationRef = ref<any>(null)
|
|
|
-const tableHeight = ref()
|
|
|
-
|
|
|
-const calcHeight = () => {
|
|
|
- const toolbarHeight = toolbarRef.value ? toolbarRef.value.offsetHeight : 0
|
|
|
- const paginationHeight = paginationRef.value ? paginationRef.value.offsetHeight : 0
|
|
|
- tableHeight.value = `calc(100% - ${toolbarHeight + paginationHeight}px)`
|
|
|
-}
|
|
|
-nextTick(() => {
|
|
|
- calcHeight()
|
|
|
-})
|
|
|
-watch(
|
|
|
- () => props.showToolbar,
|
|
|
- () => {
|
|
|
- nextTick(() => {
|
|
|
- calcHeight()
|
|
|
- })
|
|
|
- }
|
|
|
-)
|
|
|
-// ============== 表格部分结束 ===============
|
|
|
-
|
|
|
-// 构造表单插槽
|
|
|
-const { formSlots } = useForm(props)
|
|
|
-
|
|
|
-defineExpose({
|
|
|
- handleCreate,
|
|
|
- handleDelete,
|
|
|
- handleUpdate,
|
|
|
- handleView,
|
|
|
- handleQuery,
|
|
|
- handleReset,
|
|
|
- refresh,
|
|
|
- formData,
|
|
|
- query,
|
|
|
- table: xTable
|
|
|
-})
|
|
|
-</script>
|
|
|
-
|
|
|
-<template>
|
|
|
- <div class="flex flex-col" style="max-height: 100vh" :style="{ height: height || '100%' }">
|
|
|
- <el-card
|
|
|
- class="mb-4 shrink-0"
|
|
|
- shadow="never"
|
|
|
- :body-style="{ 'padding-bottom': '0' }"
|
|
|
- v-if="searchList.length || slots.query"
|
|
|
- >
|
|
|
- <el-form :inline="true">
|
|
|
- <el-form-item :label="item.label" v-for="(item, index) in searchList" :key="index">
|
|
|
- <form-comp :item="item" v-model="query[item.name]">
|
|
|
- <template #[slot.alias] v-for="slot in item.slots" :key="slot.alias">
|
|
|
- <slot :name="slot.alias"></slot>
|
|
|
- </template>
|
|
|
- </form-comp>
|
|
|
- </el-form-item>
|
|
|
- <slot name="query" :query="query"></slot>
|
|
|
- <el-form-item>
|
|
|
- <el-button type="primary" icon="Search" @click="handleQuery">查询</el-button>
|
|
|
- <el-button icon="Refresh" @click="handleReset">重置</el-button>
|
|
|
- </el-form-item>
|
|
|
- </el-form>
|
|
|
- </el-card>
|
|
|
-
|
|
|
- <el-card class="h-full flex-grow" :body-style="{ height: '100%' }" shadow="never">
|
|
|
- <div class="flex flex-col h-full">
|
|
|
- <div ref="toolbarRef" class="shrink-0">
|
|
|
- <slot name="header"></slot>
|
|
|
- <vxe-toolbar ref="xToolbar" v-bind="toolbarConfig" v-if="showToolbar">
|
|
|
- <template #buttons>
|
|
|
- <el-button type="primary" icon="Plus" @click="handleCreate">新增</el-button>
|
|
|
- <el-button
|
|
|
- type="danger"
|
|
|
- icon="Delete"
|
|
|
- @click="handleBatchDelete"
|
|
|
- :disabled="!multipleSelection.length"
|
|
|
- v-if="selection"
|
|
|
- >
|
|
|
- 删除
|
|
|
- </el-button>
|
|
|
- <slot name="toolbar" :selection="multipleSelection"></slot>
|
|
|
- </template>
|
|
|
- </vxe-toolbar>
|
|
|
- </div>
|
|
|
- <div :style="{ height: tableHeight }">
|
|
|
- <vxe-table
|
|
|
- ref="xTable"
|
|
|
- id="xProTable"
|
|
|
- size="medium"
|
|
|
- auto-resize
|
|
|
- height="auto"
|
|
|
- :data="tableData"
|
|
|
- :row-config="{ isHover: true }"
|
|
|
- v-loading="loading"
|
|
|
- v-bind="$attrs"
|
|
|
- @checkbox-change="handleSelectionChange"
|
|
|
- @checkbox-all="handleSelectionChange"
|
|
|
- >
|
|
|
- <vxe-column type="checkbox" width="50" v-if="selection"></vxe-column>
|
|
|
- <slot></slot>
|
|
|
- <vxe-column fixed="right" title="操作" :width="tableConfig.operateWidth" v-if="tableConfig.showOperate">
|
|
|
- <template #default="{ row }">
|
|
|
- <slot name="operateBefore" :row="row"></slot>
|
|
|
- <el-button size="small" @click="handleView(row)" v-if="tableConfig.showView"> 查看 </el-button>
|
|
|
- <el-button type="primary" size="small" @click="handleUpdate(row)" v-if="tableConfig.showEdit">
|
|
|
- 编辑
|
|
|
- </el-button>
|
|
|
- <el-button type="danger" size="small" @click="handleDelete(row.id)" v-if="tableConfig.showDelete">
|
|
|
- 删除
|
|
|
- </el-button>
|
|
|
- <slot name="operateAfter" :row="row"></slot>
|
|
|
- </template>
|
|
|
- </vxe-column>
|
|
|
- </vxe-table>
|
|
|
- </div>
|
|
|
- <div ref="paginationRef">
|
|
|
- <el-pagination
|
|
|
- background
|
|
|
- layout="->, prev, pager, next, total"
|
|
|
- v-model:current-page="curPage"
|
|
|
- :page-size="pageSize"
|
|
|
- :total="total"
|
|
|
- class="mt-16px"
|
|
|
- />
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </el-card>
|
|
|
- </div>
|
|
|
- <template v-if="formMode === 'dialog'">
|
|
|
- <dialog-form
|
|
|
- v-model="formVisible"
|
|
|
- v-if="formVisible"
|
|
|
- :dialogConfig="dialogConfig"
|
|
|
- :formConfig="formConfig"
|
|
|
- :formData="formData"
|
|
|
- :formSlots="formSlots"
|
|
|
- :create="crud.create"
|
|
|
- :update="crud.update"
|
|
|
- @success="handleFormSuccess"
|
|
|
- >
|
|
|
- <template #[slot.alias]="slotProps" v-for="slot in formSlots" :key="slot.alias">
|
|
|
- <slot :name="slot.alias" v-bind="slotProps"></slot>
|
|
|
- </template>
|
|
|
- </dialog-form>
|
|
|
- </template>
|
|
|
- <template v-else>
|
|
|
- <drawer-form
|
|
|
- v-model="formVisible"
|
|
|
- v-if="formVisible"
|
|
|
- :drawerConfig="drawerConfig"
|
|
|
- :formConfig="formConfig"
|
|
|
- :formData="formData"
|
|
|
- :formSlots="formSlots"
|
|
|
- :create="crud.create"
|
|
|
- :update="crud.update"
|
|
|
- @success="handleFormSuccess"
|
|
|
- >
|
|
|
- <template #[slot.alias]="slotProps" v-for="slot in formSlots" :key="slot.alias">
|
|
|
- <slot :name="slot.alias" v-bind="slotProps"></slot>
|
|
|
- </template>
|
|
|
- </drawer-form>
|
|
|
- </template>
|
|
|
-</template>
|
|
|
-
|
|
|
-<style scoped>
|
|
|
-.vxe-toolbar {
|
|
|
- padding-top: 0;
|
|
|
-}
|
|
|
-:deep(.el-card) {
|
|
|
- --el-card-padding: 16px;
|
|
|
- border: none !important;
|
|
|
-}
|
|
|
-</style>
|