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