|
|
@@ -0,0 +1,277 @@
|
|
|
+<!--
|
|
|
+ * @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: {
|
|
|
+ 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>
|