<!--
 * @Descripttion: 数据表格组件
 * @version: 1.10
-->

<template>
    <el-main>
        <vxe-grid ref="xGrid" v-bind="gridOptions" @form-collapse="formCollapseEvent" @edit-activated="$emit('editActivated', $event)" @page-change="pageChangeEvent">
            <template #queryAction>
                <el-button type="primary" auto-insert-space @click="searchData">查询</el-button>
                <el-button auto-insert-space @click="resetData">重置</el-button>
            </template>
            
            <!-- table-column / 操作 -->
            <template v-for="(_, slotName) in $slots" #[slotName]="context">
                <slot :name="slotName" v-bind="{ ...context, row: XEUtils.get(context, '$grid', XEUtils.get(context, '$table'))?.getData(context.rowIndex) || context.row }"></slot>
            </template>
        </vxe-grid>
    </el-main>
</template>

<script setup>
// 设置当前zIndex起始值
import domZIndex from "dom-zindex";
domZIndex.setCurrent(domZIndex.getMax() + 1);

import VxeUI from "vxe-pc-ui";
import XEUtils from "xe-utils";
import store from "@/store";
import config from "@/config/table";
import pagerBatchDel from "./renderer/pager-batch-del";

const props = defineProps({
    apiObj: { type: Object, default: () => {} },
    apiKey: { type: String, default: () => "get" },
    framework: { type: String, default: () => "common" },
    minHeight: { type: [String, Number], default: () => VxeUI.getConfig().table.minHeight },
    maxHeight: { type: [String, Number] },
    layouts: { type: Array, default: () => [["Top", "Form"], ["Toolbar", "Table", "Bottom", "Pager"]] },
    /* ***************  query  *************** */ 
    formConfig: { type: Object, default: () => {} },
    paramsColums: { type: Array, default: () => [] },
    /* ***************  query  *************** */ 
    toolbarConfig: { type: Object, default: () => {} },
    editConfig: { type: Object, default: () => {} },
    columns: { type: Array, default: () => [] },
    /* ***************  pager  *************** */ 
    pagerConfig: { type: Object, default: () => {} },
    batchDel: { type: Boolean, default: () => false },
    /* ***************  pager  *************** */ 
    options: { type: Object, default: () => {} }
})

const xGrid = ref();
const selectedRows = ref([]);
const gridOptions = ref({
    id: "xGride-table",
    loading: false,
    minHeight: props.minHeight,
    border: "full",
    size: "mini",
    data: [],
    columns: XEUtils.map(props.columns, item => ({ ...item, [item.type != "seq" && "exportMethod"]: ({ row, column }) => row[column?.field] || "" })),
    showOverflow: true,
    keepSource: true,
    layouts: [...props.layouts],
    formConfig: {
        enabled: true,
        className: "vxe-table-query",
        titleAlign: "right",
        collapseStatus: true,
        span: 6,
        items: [
            ...XEUtils.map(XEUtils.orderBy(XEUtils.get(props, "formConfig.items", []), "orderBy"), (formItem, formIndex) => {
                return {
                    ...formItem,
                    className: ({ $grid, item, data }) => {
                        const showItems = XEUtils.filter(XEUtils.orderBy(XEUtils.get(props, "formConfig.items", []), "orderBy"), f_item => (XEUtils.isUndefined(f_item.visible) || f_item.visible) && (XEUtils.isUndefined(f_item.visibleMethod) || f_item.visibleMethod({ data })));
                        const index = XEUtils.findIndexOf(showItems, f_item => f_item.field == item.field);
                        item.folding = index > 2;
                        XEUtils.set(formItem, "folding", index > 2);
                        return "";
                    }
                }
            }), {
                align: "right",
                slots: { default: "queryAction" },
                className: ({ $grid, item, data }) => {
                    const showItems = XEUtils.filter(XEUtils.orderBy(XEUtils.get(props, "formConfig.items", []), "orderBy"), formItem => (XEUtils.isUndefined(formItem.visible) || formItem.visible) && (XEUtils.isUndefined(formItem.visibleMethod) || formItem.visibleMethod({ data })));
                    const spanItems = (!gridOptions.value.formConfig.collapseStatus && showItems) || XEUtils.filter(showItems, f_item => !f_item.folding);
                    const remainder = 24 - (XEUtils.sum(spanItems, s_item => s_item.span || 6) % 24);
                    item.visible = showItems.length > 0;
                    item.collapseNode = showItems.length > 3;
                    item.span = remainder < 6 && 24 || remainder;
                    return "query-action__item";
                }
            }
        ],
        ...XEUtils.omit(XEUtils.get(props, "formConfig", {}), "items")
    },
    toolbarConfig: {
        enabled: false,
        buttons: [
            { buttonRender: { name: "$table-search" } }
        ],
        print: true,
        zoom: true,
        custom: true,
        refresh: {
            queryMethod: () => getData(),
        },
        ...props.toolbarConfig
    },
    proxyConfig: {
        enabled: false
    },
    printConfig: {},
    importConfig: {
        // remote: true,
        types: ["xlsx", "xls"],
        mode: "insertBottom",
        modes: ["insertBottom", "insertTop", "covering"],
        // importMethod: ({ $grid, options }) => {},
    },
    exportConfig: {
        remote: true,
        types: ["xlsx"],
        modes: XEUtils.find(props.columns, item => XEUtils.includes(config.exportExcludeFields, item.type)) && ["current", "selected", "all"] || ["current", "all"],
        columns: XEUtils.filter(props.columns, item => !XEUtils.includes(config.exportExcludeFields, item.type)),
        exportMethod: ({ $grid, options }) => exportEvent($grid, options)
    },
    rowConfig: {
        keyField: "id",
        useKey: true,
        isHover: true
    },
    columnConfig: {
        useKey: true,
        resizable: true // 列宽拖动功能
    },
    headerCellConfig: {
        height: 36
    },
    cellConfig: {
        height: 36
    },
    checkboxConfig: {
        highlight: true,
        range: true // 鼠标在复选框的列内滑动选中或取消指定行
    },
    tooltipConfig: {
        enterable: true
    },
    expandConfig: {
        padding: true
    },
    editConfig: {
        enabled: false,
        mode: "cell",
        trigger: "click",
        showStatus: true,
        ...props.editConfig
    },
    pagerConfig: {
        queryType: "limit", // 页码筛选类型
        className: "vxe-table-pager",
        pageSizes: config.pageSizes,
        layouts: config.layouts,
        currentPage: 1,
        pageSize: config.pageSize,
        total: 0,
        slots: {
            left: params => props.batchDel && h(pagerBatchDel, { params })
        },
        ...props.pagerConfig
    }
})

watch(() => xGrid.value?.getCheckboxRecords(), val => selectedRows.value = val);

addEventListener("resize", () => resizeTable());
onMounted(() => {
    XEUtils.merge(gridOptions.value, props.options);
    resizeTable();
    getData();
});

const resizeTable = () => {
    nextTick(() => {
        if (store.state.global.ismobile) XEUtils.set(gridOptions.value, "maxHeight", 1048);
        else XEUtils.set(gridOptions.value, "maxHeight", (props.maxHeight || xGrid.value?.$el.parentElement.offsetHeight));
    });
}

// 获取数据
const getData = () => {
    if (!props.apiObj) return;
    nextTick(() => {
        gridOptions.value.loading = true;
        const reqData = config.framework[props.framework].queryData(gridOptions.value, props.paramsColums);
        props.apiObj[props.apiKey](reqData).then(res => {
            const response = config.framework[props.framework].parseData(res);
            gridOptions.value.data = response.data || [];
            gridOptions.value.pagerConfig.total = response.total || 0;
            gridOptions.value.loading = false;
        }).catch(error => {
            gridOptions.value.loading = false;
            gridOptions.value.data = [];
            gridOptions.value.pagerConfig.total = 0;
        });
    });
}

const pageChangeEvent = ({ pageSize, currentPage }) => {
    gridOptions.value.pagerConfig.currentPage = currentPage;
    gridOptions.value.pagerConfig.pageSize = pageSize;
    getData();
}

const searchData = (mode = "add") => {
    if (mode == "add") gridOptions.value.pagerConfig.currentPage = 1;
    gridOptions.value.pagerConfig.pageSize = config.pageSize;
    getData();
}

const resetData = () => {
    gridOptions.value.pagerConfig.currentPage = 1;
    gridOptions.value.pagerConfig.pageSize = config.pageSize;
    XEUtils.arrayEach(gridOptions.value.formConfig.items, item => XEUtils.set(gridOptions.value.formConfig.data, item.field, XEUtils.get(item, "resetValue")));
    XEUtils.merge(gridOptions.value.formConfig.data, XEUtils.omit(gridOptions.value.formConfig.data, item => XEUtils.isEmpty(item) && !XEUtils.isNumber(item)));

    getData();
}

const formCollapseEvent = ({ collapse }) => gridOptions.value.formConfig.collapseStatus = collapse;

const toggleFormEnabled = () => gridOptions.value.formConfig.enabled = !gridOptions.value.formConfig.enabled;

const toggleToolbarProps = obj => XEUtils.objectEach(obj, (value, key) => XEUtils.set(gridOptions.value.toolbarConfig, key, value));

const reloadColumn = columns => xGrid.value.reloadColumn(columns);

const getTableData = () => xGrid.value.getTableData();

const reloadData = data => xGrid.value.reloadData(data);

const exportEvent = async ($grid, options) => {
    let data = XEUtils.clone(options.data);
    if (options.mode == "all") {
        const reqData = config.framework[props.framework].queryExport(gridOptions.value);
        const res = await props.apiObj[props.apiKey](reqData);
        const response = config.framework[props.framework].parseData(res);
        data = response.data || [];
    }

    $grid.exportData({
        ...options,
        remote: false,
        columns: XEUtils.map(options.columns, item => ({ ...item, [item.type != "seq" && "exportMethod"]: ({ row, column }) => row[column?.field] || "" })),
        data
    });
}

defineExpose({
    selectedRows,
    toggleFormEnabled,
    toggleToolbarProps,
    reloadColumn,
    getTableData,
    reloadData,
    searchData,
    resetData
})
</script>

<style scoped>
    .el-main {padding: 0 12px 12px;background: var(--el-bg-color);}
</style>