| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273 |
- <script setup lang="ts">
- import { ElMessage, ElMessageBox, type FormProps } from 'element-plus'
- import type { PropType } from 'vue'
- interface column {
- label?: string
- value: string
- name: string
- formType: string
- placeholder: string
- options: Array<any>
- rules: any
- search: boolean
- width: string | number
- type: string
- span: number
- }
- interface CRUD {
- create: Function
- update: Function
- delete: Function
- getList: Function
- getRecord: Function
- }
- const props = defineProps({
- crud: Object as PropType<CRUD>,
- pageSize: {
- type: Number,
- default: 10
- },
- columns: {
- type: Array as PropType<column[]>,
- default: () => []
- },
- selection: {
- type: Boolean,
- default: true
- },
- form: Object as PropType<FormProps>,
- formItem: Object,
- formComp: Object
- })
- // ============== 查询部分开始 ===============
- const query = ref<any>({})
- const searchList = computed(() => props.columns.filter(item => item.search))
- const handleQuery = () => {
- curPage.value = 1
- getTableData()
- }
- const handleReset = () => {
- query.value = {}
- }
- // ============== 查询部分结束 ===============
- // ============== 表格部分开始 ===============
- const tableData = ref([])
- const total = ref(0)
- const curPage = ref(1)
- const getTableData = () => {
- props.crud
- ?.getList({
- ...query.value,
- pageSize: props.pageSize,
- page: curPage.value
- })
- .then((res: any) => {
- tableData.value = res.data
- total.value = res.total
- })
- }
- getTableData()
- const pageChange = () => {
- getTableData()
- }
- const multipleSelection = ref<any[]>([])
- const handleSelectionChange = (columns: any[]) => {
- multipleSelection.value = columns
- }
- // ============== 表格部分结束 ===============
- // ============== crud部分开始 ===============
- const handleCreate = () => {
- dialogTitle.value = '新增'
- dialogVisible.value = true
- }
- const handleUpdate = (row: any) => {
- dialogTitle.value = '编辑'
- dialogVisible.value = true
- if (props.crud?.getRecord) {
- props.crud.getRecord({ id: row.id }).then((res: any) => {
- formData.value = res.data
- })
- } else {
- formData.value = row
- }
- }
- const handleDelete = (id: string | number) => {
- ElMessageBox.confirm('您确定要删除该项吗', '提示', {
- type: 'warning'
- }).then(async () => {
- const res = await props.crud?.delete(id)
- if (res.code === 0) {
- ElMessage({
- type: 'success',
- message: '删除成功'
- })
- }
- })
- }
- const handlePatchDelete = () => {}
- // ============== crud部分结束 ===============
- // ============== 表单部分开始 ===============
- const formConfig: any = ref({
- labelWidth: '100px',
- labelPosition: 'top',
- size: 'large',
- ...props.form
- })
- const dialogTitle = ref('新增')
- const dialogVisible = ref(false)
- const closeDialog = () => {
- dialogVisible.value = false
- formData.value = {}
- }
- const formData = ref<any>({})
- const formRef = ref()
- const formList = computed(() => props.columns.filter(item => item.formType))
- const placeholder = (item: column) => {
- if (['select'].includes(item.formType)) {
- return '请选择' + item.label
- } else {
- return '请输入' + item.label
- }
- }
- formList.value.forEach(item => {
- formData.value[item.name] = item.value
- })
- const submit = () => {
- let res, message
- formRef.value.validate(async (valid: boolean) => {
- if (valid) {
- if (formData.value.id) {
- res = props.crud?.update(formData.value)
- message = '新增成功'
- } else {
- res = props.crud?.create(formData.value)
- message = '修改成功'
- }
- if (res.code === 0) {
- ElMessage({
- type: 'success',
- message
- })
- closeDialog()
- }
- }
- })
- }
- // ============== 表单部分结束 ===============
- </script>
- <template>
- <div class="flex flex-col" style="height: calc(100vh - 60px - var(--main-padding) * 2)">
- <el-card class="mb-4" shadow="never">
- <el-form :inline="true">
- <el-form-item :label="item.label" v-for="item in searchList">
- <component
- :is="'el-' + item.formType"
- v-model="query[item.name]"
- :placeholder="item.placeholder || placeholder(item)"
- >
- <template v-if="item.formType === 'radio-group'">
- <el-radio :label="option.label" v-for="option in item.options">{{ option.value }}</el-radio>
- </template>
- </component>
- </el-form-item>
- <el-form-item>
- <el-button type="primary" @click="handleQuery">查询</el-button>
- <el-button @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">
- <div class="flex justify-between mb-20px">
- <div>
- <el-button type="primary" @click="handleCreate">新增</el-button>
- <el-button type="danger" @click="handlePatchDelete" :disabled="!multipleSelection.length" v-if="selection">
- 删除
- </el-button>
- </div>
- </div>
- <el-table class="flex-grow-1 h-full" :data="tableData" @selection-change="handleSelectionChange">
- <el-table-column type="selection" width="50" v-if="selection"></el-table-column>
- <slot></slot>
- <el-table-column fixed="right" label="操作" width="120">
- <template #default="{ row }">
- <el-button link type="primary" size="small" @click="handleUpdate(row)">编辑</el-button>
- <el-button link type="danger" size="small" @click="handleDelete(row.id)">删除</el-button>
- </template>
- </el-table-column>
- </el-table>
- <div class="flex justify-end shrink-0">
- <el-pagination
- background
- layout="prev, pager, next"
- :page-size="pageSize"
- :total="total"
- @current-change="pageChange"
- class="mt-4"
- />
- </div>
- </div>
- </el-card>
- <el-dialog
- draggable
- :title="dialogTitle"
- v-model="dialogVisible"
- width="1000px"
- @close="closeDialog"
- :close-on-click-modal="false"
- >
- <el-form :model="formData" ref="formRef" v-bind="formConfig" class="form">
- <el-row :gutter="20">
- <el-col :span="item.span || 12" v-for="item in formList">
- <el-form-item :label="item.label" :rules="item.rules" :prop="item.name">
- <component
- :is="'el-' + item.formType"
- v-model="formData[item.name]"
- v-bind="formComp"
- :placeholder="item.placeholder || placeholder(item)"
- >
- <template v-if="item.formType === 'radio-group'">
- <el-radio :label="option.label" v-for="option in item.options">{{ option.value }}</el-radio>
- </template>
- <template v-else-if="item.formType === 'select'">
- <el-option :label="option.label" :value="option.value" v-for="option in item.options"></el-option>
- </template>
- </component>
- </el-form-item>
- </el-col>
- </el-row>
- </el-form>
- <template #footer>
- <el-button @click="dialogVisible = false">取消</el-button>
- <el-button type="primary" @click="submit">保存</el-button>
- </template>
- </el-dialog>
- </div>
- </template>
- <style scoped>
- :deep(.el-table th.el-table__cell) {
- background-color: #f5f7fa;
- color: rgb(31, 34, 37);
- }
- .form .el-select {
- width: 100%;
- }
- </style>
|