|
|
@@ -0,0 +1,221 @@
|
|
|
+<script lang="ts">
|
|
|
+export default {
|
|
|
+ inheritAttrs: false
|
|
|
+}
|
|
|
+</script>
|
|
|
+
|
|
|
+<script setup lang="ts">
|
|
|
+import router from '@/router'
|
|
|
+import { ElMessage, ElMessageBox, type DialogProps } from 'element-plus'
|
|
|
+import type { AdvancedForm, BasicForm, ICRUD } from '@/types/form'
|
|
|
+
|
|
|
+interface Props {
|
|
|
+ crud: ICRUD
|
|
|
+ pageSize?: number
|
|
|
+ formConfig: BasicForm | AdvancedForm
|
|
|
+ dialogConfig?: DialogProps
|
|
|
+ height?: string
|
|
|
+ cardHeight?: string
|
|
|
+ showAdd?: boolean
|
|
|
+}
|
|
|
+
|
|
|
+const props = withDefaults(defineProps<Props>(), {
|
|
|
+ pageSize: 12,
|
|
|
+ showAdd: true,
|
|
|
+ cardHeight: '246px'
|
|
|
+})
|
|
|
+
|
|
|
+const emits = defineEmits(['click-create', 'click-edit'])
|
|
|
+
|
|
|
+// ============== 查询部分开始 ===============
|
|
|
+const query = ref<any>({})
|
|
|
+const searchList = ref<any>([])
|
|
|
+watch(
|
|
|
+ () => props.formConfig.formItems,
|
|
|
+ val => {
|
|
|
+ val.forEach((item: any) => {
|
|
|
+ if (item.group) {
|
|
|
+ searchList.value = searchList.value.concat(item.group.filter((item: any) => item.search))
|
|
|
+ } else {
|
|
|
+ item.search && searchList.value.push(item)
|
|
|
+ }
|
|
|
+ })
|
|
|
+ },
|
|
|
+ { immediate: true }
|
|
|
+)
|
|
|
+
|
|
|
+const handleQuery = () => {
|
|
|
+ curPage.value = 1
|
|
|
+ getTableData()
|
|
|
+}
|
|
|
+const handleReset = () => {
|
|
|
+ query.value = {}
|
|
|
+ handleQuery()
|
|
|
+}
|
|
|
+// ============== 查询部分结束 ===============
|
|
|
+
|
|
|
+// ============== 表格部分开始 ===============
|
|
|
+const tableData = ref<any>([])
|
|
|
+const total = ref(0)
|
|
|
+const curPage = ref(1)
|
|
|
+const loading = ref(false)
|
|
|
+
|
|
|
+const getTableData = () => {
|
|
|
+ loading.value = true
|
|
|
+ props.crud
|
|
|
+ ?.getList({
|
|
|
+ ...query.value,
|
|
|
+ pageSize: props.pageSize,
|
|
|
+ pageNo: curPage.value
|
|
|
+ })
|
|
|
+ .then((res: any) => {
|
|
|
+ console.log('res', res)
|
|
|
+ tableData.value = res.list || res.rows
|
|
|
+ total.value = res.total
|
|
|
+ })
|
|
|
+ .finally(() => {
|
|
|
+ loading.value = false
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
+watch(
|
|
|
+ curPage,
|
|
|
+ () => {
|
|
|
+ getTableData()
|
|
|
+ },
|
|
|
+ {
|
|
|
+ immediate: true
|
|
|
+ }
|
|
|
+)
|
|
|
+
|
|
|
+const refresh = () => {
|
|
|
+ curPage.value = 1
|
|
|
+ getTableData()
|
|
|
+}
|
|
|
+
|
|
|
+// ============== 表格部分结束 ===============
|
|
|
+
|
|
|
+// ============== crud部分开始 ===============
|
|
|
+const formRoute = ref<any>(props.formConfig.route)
|
|
|
+const handleCreate = () => {
|
|
|
+ emits('click-create')
|
|
|
+ if (formRoute.value) {
|
|
|
+ router.push(formRoute.value)
|
|
|
+ } else {
|
|
|
+ formData.value = {}
|
|
|
+ dialogVisible.value = true
|
|
|
+ }
|
|
|
+}
|
|
|
+const handleUpdate = (row: any) => {
|
|
|
+ emits('click-edit', row)
|
|
|
+ if (formRoute.value) {
|
|
|
+ router.push(formRoute.value)
|
|
|
+ } else {
|
|
|
+ if (props.crud?.getRecord) {
|
|
|
+ props.crud.getRecord({ id: row.id }).then((res: any) => {
|
|
|
+ formData.value = res.data
|
|
|
+ })
|
|
|
+ } else {
|
|
|
+ formData.value = { ...row }
|
|
|
+ }
|
|
|
+ dialogVisible.value = true
|
|
|
+ }
|
|
|
+}
|
|
|
+const handleDelete = (id: string | number) => {
|
|
|
+ ElMessageBox.confirm('您确定要删除该项吗', '提示', {
|
|
|
+ type: 'warning'
|
|
|
+ }).then(async () => {
|
|
|
+ await props.crud?.delete({ id })
|
|
|
+ getTableData()
|
|
|
+ ElMessage({
|
|
|
+ type: 'success',
|
|
|
+ message: '删除成功'
|
|
|
+ })
|
|
|
+ })
|
|
|
+}
|
|
|
+// ============== crud部分结束 ===============
|
|
|
+
|
|
|
+// ============== 表单部分开始 ===============
|
|
|
+const formData = ref<any>({})
|
|
|
+const dialogVisible = ref(false)
|
|
|
+const handleFormSuccess = () => {
|
|
|
+ getTableData()
|
|
|
+}
|
|
|
+// ============== 表单部分结束 ===============
|
|
|
+
|
|
|
+defineExpose({
|
|
|
+ handleCreate,
|
|
|
+ handleDelete,
|
|
|
+ handleUpdate,
|
|
|
+ refresh
|
|
|
+})
|
|
|
+</script>
|
|
|
+
|
|
|
+<template>
|
|
|
+ <div class="flex flex-col" :style="{ height: height || 'calc(100vh - 101px - var(--main-padding) * 2)' }">
|
|
|
+ <el-card class="mb-4" shadow="never" v-if="searchList.length">
|
|
|
+ <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]"></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-1" :body-style="{ height: '100%' }" shadow="never">
|
|
|
+ <div class="flex flex-col h-full">
|
|
|
+ <slot name="header"></slot>
|
|
|
+
|
|
|
+ <div class="h-full flex-grow">
|
|
|
+ <el-row :gutter="10">
|
|
|
+ <el-col :span="6" v-if="showAdd" class="mb-10">
|
|
|
+ <div
|
|
|
+ class="flex items-center justify-center border border-dashed w-full h-full card-list-item"
|
|
|
+ :style="{ height: cardHeight }"
|
|
|
+ >
|
|
|
+ <el-button link icon="plus" @click="handleCreate">新增</el-button>
|
|
|
+ </div>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="6" v-for="(item, index) in tableData" :key="item.id" class="mb-10">
|
|
|
+ <el-card :body-style="{ padding: '0px' }" shadow="hover">
|
|
|
+ <slot :item="item" :index="index"></slot>
|
|
|
+ </el-card>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+ </div>
|
|
|
+ <div class="flex justify-end shrink-0">
|
|
|
+ <el-pagination
|
|
|
+ background
|
|
|
+ layout="prev, pager, next, jumper, total"
|
|
|
+ v-model:current-page="curPage"
|
|
|
+ :page-size="pageSize"
|
|
|
+ :total="total"
|
|
|
+ class="mt-16px"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </el-card>
|
|
|
+
|
|
|
+ <dialog-form
|
|
|
+ v-model="dialogVisible"
|
|
|
+ :dialogConfig="dialogConfig"
|
|
|
+ :formConfig="formConfig"
|
|
|
+ :formData="formData"
|
|
|
+ :create="crud.create"
|
|
|
+ :update="crud.update"
|
|
|
+ @success="handleFormSuccess"
|
|
|
+ v-if="dialogVisible"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<style scoped>
|
|
|
+.card-list-item {
|
|
|
+ border-color: var(--el-border-color-light);
|
|
|
+ border-radius: var(--el-card-border-radius);
|
|
|
+}
|
|
|
+</style>
|