<template>
    <div class="table-container">
        <div class="flex justify-between table-header">
            <div class="flex-center">
                <!-- 详情里面的表格左侧带有筛选区域的插槽 -->
                <slot name="left-search"></slot>
                <el-button v-if="handleBtnRole('add')" type="primary" @click="$emit('handleAdd')">
                    + 添加
                </el-button>
                <el-button v-if="handleBtnRole('import')" @click="handleImport">
                    导入
                </el-button>
                <el-button v-if="handleBtnRole('export')" :loading="exportLoading" @click="handleExport">
                    导出
                </el-button>
                <!-- 左侧其他按钮插槽 -->
                <slot name="left"></slot>
            </div>
            <div class="flex-center">
                <!-- 右侧区域插槽 -->
                <slot name="right"></slot>
                <el-button link @click="openShowList" v-if="rightBtn.includes('list')">
                    <SvgIcon iconClass="list-check" /> 列表
                </el-button>
                <!-- 如果是邮件的表格的话，分页组件放在这里 -->
                <pagination style="margin: 0;" v-if="isPagination && isEmail" layout="total, sizes, prev, pager, next"
                    v-model:total="total" v-model:page="queryParams.pageIndex" v-model:limit="queryParams.pageSize"
                    @pagination="getList" />
            </div>
        </div>
        <el-table
            ref="singleTableRef"
            v-loading="loading"
            :data="pageData"
            height="100%"
            @selection-change="selectionChange"
            @current-change="handleCurrentChange"
            :highlight-current-row="isCurrentChange"
            @sort-change="sortChange"
        >
            <el-table-column type="selection" width="40" align="center" v-if="isCheckbox" :selectable="selectable" />
            <template v-for="(item, index) in tableColumn">
                <el-table-column v-if="item.show" :key="index" :label="item.label" :prop="item.prop" :width="item.width"
                    :sortable="item.sortable ? 'custom' : false" :show-overflow-tooltip="item.showOverflowTooltip" :sort-orders="['descending', 'ascending', null]">
                    <!-- 自定义列模板 -->
                    <template #default="scope" v-if="item.render || item.toFixed">
                        <template v-if="item.toFixed">
                            <span>{{ scope.row[item.prop] ? scope.row[item.prop].toFixed(2) : '' }}</span>
                        </template>
                        <component v-if="item.label != '操作'" :is="item.render" :column="scope.row" :index="scope.$index" />
                        <template v-else>
                            <component :is="item.render" :column="scope.row" :index="scope.$index" />
                            <el-button link v-if="handleBtnRole('edit')" type="primary"
                                @click="$emit('handleEdit', scope.row)">编辑</el-button>
                            <el-button link v-if="handleBtnRole('remove')" type="danger"
                                @click="handleDel(scope.row[tableParams.keyId])">删除</el-button>
                        </template>
                    </template>
                    <template #header v-if="item.headerQuestionFilled">
                        <div class="flex">
                            <el-popover placement="top" :width="item.headerQuestionFilled.width"
                                :content="item.headerQuestionFilled.content">
                                <template #reference>
                                    <div>
                                        <span>{{ item.label }}</span>
                                        <i-ep-QuestionFilled style="margin-left: 5px;vertical-align: text-bottom;" />
                                    </div>
                                </template>
                            </el-popover>
                        </div>
                    </template>
                </el-table-column>
            </template>
        </el-table>

        <pagination v-if="isPagination && !isEmail" layout="total, sizes, prev, pager, next" v-model:total="total"
            v-model:page="queryParams.pageIndex" v-model:limit="queryParams.pageSize" @pagination="getList" />
    </div>

    <!-- 右侧列表弹窗 -->
    <listSort ref="listSortRef" :defaultColumn="defaultColumn" :cloumnCode="tableParams.cloumnCode"
        @changeList="changeList" />

    <!-- 导入弹窗 -->
    <fileImport ref="fileImportRef" @refresh="getData" />
</template>

<script setup lang="ts">
    import { tableTypes, columnTypes } from './types'
    import SvgIcon from '../SvgIcon/index.vue'
    import listSort from './components/listSort.vue'
    import fileImport from './components/fileImport.vue'
    import { listExport } from '@/api/public'
    import { AxiosResponse } from 'axios';
    import auth from '@/plugins/auth'
    import downloadPlugins from '@/plugins/download'
    import { userHobit } from '@/store/modules/userHobit'
    const userHobitStore = userHobit()
    const emits = defineEmits(['handleAdd', 'export', 'selectionChange', 'handleEdit', 'currentChange', 'sortChange'])
    const router = useRouter();

    const props = defineProps({
        // 表格参数，包括column、url跟查询参数，必传
        tableParams: {
            type: Object,
            required: true
        },
        // 是否有复选框
        isCheckbox: {
            type: Boolean,
            default: true
        },
        // 按钮权限，默认空数组，根据权限可传新增、导入、导出、编辑、删除按钮进来
        btnRole: {
            type: Array as () => { type: string, hasPermi: string }[] || [],
            default: () => { return [] }
        },
        // 右侧按钮区域，默认列表，没有时传空数组
        rightBtn: {
            type: Array as () => string[] || [],
            default: () => {
                return ['list']
            }
        },
        // 是否有操作栏
        isOperation: {
            type: Boolean,
            default: true
        },
        // 是否分页
        isPagination: {
            type: Boolean,
            default: true
        },
        // 是否是邮件里面使用，是的话分页组件位置有变化
        isEmail: {
            type: Boolean,
            default: false
        },
        // 是否有单选功能，有的话点击高亮
        isCurrentChange: {
            type: Boolean,
            default: false
        },
        // 表格数据
        tableData: {
            type: Array
        }
    })
    const loading = ref(false)
    const exportLoading = ref(false)
    const pageList = ref([])
    const pageData = computed(() => {
        return props.tableData || pageList.value
    })
    const queryParams = reactive<PageQuery>({
        pageIndex: 1,
        pageSize: 10,
        commonQueryOrderBy: undefined,
        sortMethod: undefined
    })
    const deepClone = (source: any) => {
        let targetObj: any = source.constructor === Array ? [] : {};
        for (let key in source) {
            if (source.hasOwnProperty(key)) {
                // 只拷贝自身的属性，不拷贝原型的属性
                if (source[key] && typeof source[key] === "object") {
                    // 元素为引用数据类型
                    targetObj[key] = source[key].constructor === Array ? [] : {};
                    targetObj[key] = deepClone(source[key]);
                } else {
                    // 元素为基本数据类型
                    targetObj[key] = source[key];
                }
            }
        }
        return targetObj;
    }
    const total = ref(0)
    // const tableColumn = ref(props.tableParams.tableColumn)
    const tableColumn = ref()
    const { tableParams } = toRefs(props)

    const defaultColumn = deepClone(tableParams.value.tableColumn)

    userHobitStore.sortCloumn(tableParams.value.cloumnCode, props.tableParams.tableColumn).then(sortListColumn => {
        tableColumn.value = sortListColumn
    })


    // console.log(tableColumn.value, "sortListColumn")
    // 查询表格数据
    const getList = () => {
        let params = props.tableParams.queryParams
        if(props.isPagination) {
            params = Object.assign(queryParams, props.tableParams.queryParams)
        }
        params.scopeMenuId = props.tableParams.menuId
        loading.value = true
        props.tableParams.listFn(params).then((res: AxiosResponse) => {
            pageList.value = res.result.records;
            total.value = Number(res.result.total) || 0;
        }).finally(() => {
            loading.value = false;
        })
    }

    const selectable = (row) => {
        if(props.tableParams.selectableKey) {
            return row[props.tableParams.selectableKey] == props.tableParams.selectableValue
        }
        return true
    }

    // 按钮权限判断
    const handleBtnRole = (type: string) => {
        let detailRole = props.btnRole.find(a => a.type == type)
        if(detailRole){
            return auth.hasPermi(detailRole.hasPermi)
        }
        return false
    }

    // 复选框数据变化
    const selectionData = ref([])
    const selectionChange = (val: any) => {
        selectionData.value = val
        emits('selectionChange', selectionData.value)
    }

    const handleCurrentChange = (val) => {
        emits('currentChange', val)
    }

    // 右侧列表操作
    const listSortRef = ref()
    const openShowList = () => {
        listSortRef.value.open(tableColumn.value)
    }
    const changeList = (list: any) => {
        tableColumn.value = list
    }

    // 导入操作
    const fileImportRef = ref()
    const handleImport = () => {
        fileImportRef.value.open(props.tableParams.importCode, props.tableParams.importType)
    }

    // 导出操作
    const handleExport = () => {
        if(pageData.value.length == 0) {
            ElMessage.error('无数据可导出')
            return false
        }
        let params = JSON.parse(JSON.stringify(props.tableParams.queryParams))
        params.pageSize = 9999
        params.pageIndex = 1
        exportLoading.value = true
        listExport({ templateCode: props.tableParams.exportCode, ...params }).then(res => {
            try {
                downloadPlugins.download('export', res)
            }catch {
                ElMessage.error('导出失败，请稍后再试')
            }
            exportLoading.value = false
        })
    }

    // 删除操作
    const handleDel = (id: string | number) => {
        ElMessageBox.confirm(
            '是否确认删除当前数据？',
            '确认提示',
            { type: 'warning', confirmButtonText: '提交', }

        ).then(() => {

            props.tableParams.delFn!(id).then((res: AxiosResponse) => {
                if(res.success) {
                    ElMessage.success('删除成功')
                    getData()
                }else{
                    ElMessage.error('删除失败')
                }
            })
        }).catch(() => {})

    }

    const getData = () => {
        queryParams.pageIndex = 1
        getList()
    }

    const singleTableRef = ref()
    const setCurrent = (row) => {
        singleTableRef.value?.setCurrentRow(row)
    }

    const sortChange = (val) => {
        let props = val.prop.indexOf('.') != -1 ? val.prop.split('.')[1] : val.prop
        queryParams.commonQueryOrderBy = val.order ? props : undefined
        queryParams.sortMethod = val.order ? (val.order == 'ascending' ? 'asc' : 'desc') : undefined
        if(!val.order && tableParams.value.commonQueryOrderBy){
            queryParams.commonQueryOrderBy = tableParams.value.commonQueryOrderBy
            queryParams.sortMethod = tableParams.value.sortMethod || 'desc'
        }
        getList()
    }

    onMounted(() => {
        if(!props.tableData) {
            nextTick(() => {
                if(tableParams.value.commonQueryOrderBy) {
                    queryParams.commonQueryOrderBy = tableParams.value.commonQueryOrderBy
                    queryParams.sortMethod = tableParams.value.sortMethod || 'desc'
                }
                getList()
            })
        }
    })

    defineExpose({
        getData,
        setCurrent
    })
</script>
<style lang="scss" scoped>
    .table-container{
        display: flex;
        flex-direction: column;
        height: 100%;
    }
    .table-header{
        :deep(.el-button){
            padding: 5px 9px;
            min-width: 56px;
            border-radius: 2px;
        }
    }
    .el-table{
        border: var(--el-table-border);
        border-bottom: 0;
        margin-top: 15px;
        :deep(.el-table__header){
            th{
                background-color: #F8FAFC;
                color: #262626;
            }
        }
    }
    .pagination{
        padding: 30px 0 0;
        :deep(.el-pagination){
            justify-content: flex-end;
        }
    }
</style>
