UNPKG

trends-table-vue3

Version:

动态表格

690 lines (689 loc) 21.5 kB
import { resolveComponent, resolveDirective, openBlock, createElementBlock, normalizeStyle, createElementVNode, createBlock, withCtx, createVNode, createCommentVNode, Fragment, renderList, withDirectives, toDisplayString, renderSlot } from "vue"; function s2ab(s) { var buf = new ArrayBuffer(s.length); var view = new Uint8Array(buf); for (var i = 0; i != s.length; ++i) view[i] = s.charCodeAt(i) & 255; return buf; } function xlsxStyle(wb) { let ws = wb.Sheets["Sheet1"]; for (let key in ws) { ws["!cols"].wpx = ["14", 100, "200", 200]; const num = key.slice(1, key.length); if (num === "1" && ws[key].t !== "z") { ws[key].s = { font: { //字体相关样式 name: "宋体", //字体类型 sz: "11", //字体大小 color: { rgb: "" }, //字体颜色 bgColor: { rgb: "e7e2e200" }, //字体颜色 bold: true //是否加粗 }, // border: { // top: { // style: "thin", // color: { // auto: 1, // }, // }, // left: { // style: "thin", // color: { // auto: 1, // }, // }, // right: { // style: "thin", // color: { // auto: 1, // }, // }, // bottom: { // style: "thin", // color: { // auto: 1, // }, // }, // }, alignment: { /// 自动换行 wrapText: 1, // 居中 horizontal: "center", vertical: "center", indent: 0 } }; } else { if (key !== "!rows" && key !== "!cols" && key !== "!ref" && key !== "!fullref" && ws[key].t !== "z") { ws[key].s = { font: { //字体相关样式 name: "宋体", //字体类型 sz: "10", //字体大小 color: { rgb: "" } //字体颜色 }, // border: { // top: { // style: "thin", // color: { // auto: 1, // }, // }, // left: { // style: "thin", // color: { // auto: 1, // }, // }, // right: { // style: "thin", // color: { // auto: 1, // }, // }, // bottom: { // style: "thin", // color: { // auto: 1, // }, // }, // }, alignment: { /// 自动换行 wrapText: 1, // 居中 horizontal: "center", vertical: "center", indent: 0 } }; } } } } const $base = { s2ab, xlsxStyle }; const index = { name: "TrendsTable", props: { // 数据 - 来源 data: Array, // 表头 - 来源 header: Array, // 分页参数 pageOpts: { type: Object, default: () => { return { pageNum: 1, // 第几页 pageSize: 10 // 一页几条 }; } }, // 表头显示配置,未配置时默认全部显示;配置后按照配置项及顺序依次显示。 fieldList: { type: Array, default: () => { return []; } }, // 表头参数 headerOpts: { type: Object, default: () => { return { name: "name", // 表头名字 nameTag: "-", // 处理多级表头的标识(只支持出现一次) prop: "value" // 表头prop }; } }, // 合并行列的处理方法 rowColumnMerge: { type: Function, default: () => { } }, // 同 Table 属性 empty-text emptyText: { type: String, default: "暂无数据" }, // 同 Table-column 属性 type。参考值 'default' | 'selection' | 'index' | 'expand'。 columnType: { type: String, default: void 0 }, // 同 Table 事件 selection-change。columnType=selection有效。 selectionChange: { type: Function, default: () => { } }, // 同 Table-column 属性 selectable。columnType=selection有效。 selectable: { type: Function, default: () => { return true; } }, // 最大高度 maxHeight: { type: [Number, String], default: "auto" }, // 字体大小 fontSize: { type: Number, default: 12 }, // 表头字体颜色 headerColor: { type: String, default: "#909399" }, // 表头背景颜色 headerBgColor: { type: String, default: "#f5f7fa" }, // 表格字体颜色 bodyColor: { type: String, default: "#606266" }, // 是否开启show-overflow-tooltip tooltip: { type: Boolean, default: false }, // 固定+列宽配置参数 fixedAndColumnw: { type: Object, default: () => { return {}; } }, // 工具箱 tools: { type: Object, default: () => { return { // 需要导入的插件, plugin: { saveAs: null, // import { saveAs } from 'file-saver'; write: null, // import { write } from "xlsx-style-vite"; utils: null // import { utils } from 'xlsx'; }, header: false, // 表头筛选 excel: false, // 下载表格数据为excel文件 excelFileName: "表格Excel文件" // excel参数 - 文件名称(excel为true时选填) }; } } }, data() { return { // 数据 - 处理显示 useData: this.data, // 表头 - 处理显示 useHeader: this.header, // 工具 - 处理显示 userTools: this.tools, // 表格加载 loading: false, // 表格加载文本 loadingText: "", // 高度 trendsTableH: 0 }; }, watch: { header: { handler(val) { this.initHeader(); }, deep: true, immediate: true }, data: { handler(val) { this.initData(); }, deep: true, immediate: true } }, mounted() { this.init(); }, methods: { init() { this.$nextTick(() => { this.trendsTableH = this.$refs.trendsTable.offsetHeight; }); let tools = { // 需要导入的插件 plugin: { saveAs: null, // import { saveAs } from 'file-saver'; write: null, // import { write } from "xlsx-style-vite"; utils: null // import { utils } from 'xlsx'; }, header: false, // 表头筛选 excel: false, // 打印 excelFileName: "表格Excel文件" // 打印 - 文件内容 }; for (let key in this.tools) { if (tools[key] !== void 0) { tools[key] = this.tools[key]; } } this.userTools = tools; }, /** 导出按钮操作 */ excelDownload(excelName) { if (this.userTools.plugin.saveAs === null || this.userTools.plugin.write === null || this.userTools.plugin.utils === null) { console.warn("工具tools依赖于一下插件:file-saver/xlsx-style-vite/xlsx。请检查并安装。"); return; } this.loading = true; this.loadingText = "导出中,请稍后...."; setTimeout(() => { try { const $e = this.$refs["report-table"].$el; let $table = $e.querySelector(".el-table__fixed"); if (!$table) { $table = $e; } let wb = this.tools.plugin.utils.table_to_book($table, { raw: true }); $base.xlsxStyle(wb); var ws = this.tools.plugin.write(wb, { bookType: "xlsx", bookSST: false, type: "binary" }); this.tools.plugin.saveAs( new Blob([$base.s2ab(ws)], { type: "" }), // new Blob([ws],{type: 'application/octet-stream'}), `${excelName}.xlsx` ); } catch (e) { if (typeof console !== "undefined") console.error(e); } this.loading = false; this.loadingText = ""; }, 1e3); }, initHeader() { if (this.header.length > 0) { let headerOpts = { name: "name", // 表头名字 nameTag: "-", // 处理多级表头的标识(只支持出现一次) prop: "value" // 表头prop }; for (let key in this.headerOpts) { if (headerOpts[key] !== void 0) { headerOpts[key] = this.headerOpts[key]; } } let header = []; if (this.fieldList.length === 0) { header = JSON.parse(JSON.stringify(this.header)); } else { this.fieldList.forEach((field) => { const nums = this.header.length; for (let i = 0; i < nums; i++) { const item = this.header[i]; if (field === item[headerOpts.prop]) { header.push(item); break; } } }); } if (this.data.length > 0) { let fixedAndColumnw = { fixedNum: 0, // 左侧固定列。0不固定,1固定第一列。 fixedLastNum: 0, // 右侧固定列。0不固定,1固定第一列。 trendsWidthNum: 0, // 计算列宽 - 从0算。-1时,全部列计算;不为-1时,计算小于其的索引列 trendsWidth: 250, // 计算列宽 - 默认最大宽度,列数低于可控范围时失效 trendsWidthsFixed: [] // 计算列宽 - 手动设置固定宽度;从索引0开始设置;如:[100, 100, 100, null, 100],3不处理,不在数组内的其他索引不处理。 }; for (let key in this.fixedAndColumnw) { if (fixedAndColumnw[key] !== void 0) { fixedAndColumnw[key] = this.fixedAndColumnw[key]; } } this.originalTableHeader(header, this.data, headerOpts.prop, fixedAndColumnw); } header = this.tableHeaderLevel2(header, headerOpts); header.forEach((item, i) => { item.headerShow = true; }); this.useHeader = JSON.parse(JSON.stringify(header)); } else { this.useHeader = []; } }, initData() { if (this.data.length > 0) { this.useData = JSON.parse(JSON.stringify(this.data)); } else { this.useData = []; } }, /** * 动态表格,原始表头数据处理。 * @param {Array} headers 表头原始数据 * @param {Array} data 表体原始数据 * @param {String} prop 表头prop * @param {Number} opt * @example this.originalTableHeader(header, this.data, this.headerOpts.prop); */ originalTableHeader(headers, data, prop = "prop", opt) { const dataNum = data.length; headers.forEach((item, i) => { if (opt.trendsWidthNum !== 0) { if (opt.trendsWidthNum === -1 || opt.trendsWidthNum !== -1 && i < opt.trendsWidthNum) { let width = 80; for (let a = 0; a < dataNum; a++) { if (item[prop] && data[a][item[prop]] !== void 0 && data[a][item[prop]] !== null) { const rowStrW = (data[a][item[prop]].toString().length + 3) * this.fontSize + 1; if (rowStrW > opt.trendsWidth) { width = opt.trendsWidth; break; } if (rowStrW > 80 && rowStrW < opt.trendsWidth && width < rowStrW) { width = rowStrW; } } } item.width = width; } } if (i < opt.fixedNum) { item.fixed = "left"; } else if (i > headers.length - 1 - opt.fixedLastNum) { item.fixed = "right"; } else { item.fixed = false; } }); if (opt.trendsWidthsFixed.length > 0) { opt.trendsWidthsFixed.forEach((w, i) => { if (w !== null) { headers[i].width = w; } }); } }, /** * 多级表头数据处理 * @param {Array} titleList 表头数据 * @param {String} label 表头label * @param {String} prop 表头prop * @example header = this.tableHeaderLevel2(header, this.headerOpts.name, this.headerOpts.prop); */ tableHeaderLevel2(titleList, headerOpts) { const headers = []; titleList.forEach((h, i) => { if (h[headerOpts.name].includes(headerOpts.nameTag)) { const names = h[headerOpts.name].split(headerOpts.nameTag); if (headers.length > 0 && headers[headers.length - 1].label === names[0]) { let temp = JSON.parse(JSON.stringify(h)); temp.label = names[1]; temp.prop = h[headerOpts.prop]; if (!headers[headers.length - 1].fixed && h.fixed !== false) { headers[headers.length - 1].fixed = h.fixed; } headers[headers.length - 1].children.push(temp); } else { const temp = { children: [], label: names[0], prop: null }; if (!temp.fixed && h.fixed !== false) { temp.fixed = h.fixed; } let temp2 = JSON.parse(JSON.stringify(h)); temp2.label = names[1]; temp2.prop = h[headerOpts.prop]; temp.children.push(temp2); headers.push(temp); } } else { let temp = JSON.parse(JSON.stringify(h)); temp.label = h[headerOpts.name]; temp.prop = h[headerOpts.prop]; headers.push(temp); } }); return headers; } } }; const index_vue_vue_type_style_index_0_scoped_fa2655ba_lang = ""; const _export_sfc = (sfc, props) => { const target = sfc.__vccOpts || sfc; for (const [key, val] of props) { target[key] = val; } return target; }; const _sfc_main = index; const _hoisted_1 = { class: "el-dropdown-link" }; function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) { const _component_Files = resolveComponent("Files"); const _component_el_icon = resolveComponent("el-icon"); const _component_Menu = resolveComponent("Menu"); const _component_el_checkbox = resolveComponent("el-checkbox"); const _component_el_dropdown_item = resolveComponent("el-dropdown-item"); const _component_el_dropdown_menu = resolveComponent("el-dropdown-menu"); const _component_el_dropdown = resolveComponent("el-dropdown"); const _component_el_table_column = resolveComponent("el-table-column"); const _component_el_table = resolveComponent("el-table"); const _directive_loading = resolveDirective("loading"); return openBlock(), createElementBlock("div", { class: "trendsTable", ref: "trendsTable", style: normalizeStyle({ height: _ctx.maxHeight }) }, [ createElementVNode("div", { class: "tools", style: normalizeStyle({ height: _ctx.tools.header || _ctx.tools.excel ? `30px` : "auto" }) }, [ _ctx.userTools.excel ? (openBlock(), createBlock(_component_el_icon, { key: 0, onClick: _cache[0] || (_cache[0] = ($event) => _ctx.excelDownload(_ctx.userTools.excelFileName)), class: "one", size: "18" }, { default: withCtx(() => [ createVNode(_component_Files) ]), _: 1 })) : createCommentVNode("", true), _ctx.userTools.header ? (openBlock(), createBlock(_component_el_dropdown, { key: 1, class: "one" }, { dropdown: withCtx(() => [ createVNode(_component_el_dropdown_menu, null, { default: withCtx(() => [ (openBlock(true), createElementBlock(Fragment, null, renderList(_ctx.useHeader, (h, hi) => { return openBlock(), createBlock(_component_el_dropdown_item, { key: hi }, { default: withCtx(() => [ createVNode(_component_el_checkbox, { modelValue: h.headerShow, "onUpdate:modelValue": ($event) => h.headerShow = $event, label: h.label, size: "small" }, null, 8, ["modelValue", "onUpdate:modelValue", "label"]) ]), _: 2 }, 1024); }), 128)) ]), _: 1 }) ]), default: withCtx(() => [ createElementVNode("span", _hoisted_1, [ createVNode(_component_el_icon, { size: "18" }, { default: withCtx(() => [ createVNode(_component_Menu) ]), _: 1 }) ]) ]), _: 1 })) : createCommentVNode("", true) ], 4), withDirectives((openBlock(), createBlock(_component_el_table, { ref: "report-table", style: normalizeStyle({ "--fontSize": _ctx.fontSize + "px", "--headerColor": _ctx.headerColor, "--bodyColor": _ctx.bodyColor, "--headerBgColor": _ctx.headerBgColor }), "element-loading-text": _ctx.loadingText, class: "comTable", data: _ctx.useData, "max-height": _ctx.maxHeight === "auto" ? _ctx.maxHeight : _ctx.tools.header || _ctx.tools.excel ? `${_ctx.trendsTableH - 30}px` : `${_ctx.trendsTableH}px`, "span-method": _ctx.rowColumnMerge, "empty-text": _ctx.emptyText, onSelectionChange: _ctx.selectionChange, border: "" }, { default: withCtx(() => [ _ctx.columnType === "index" ? (openBlock(), createBlock(_component_el_table_column, { key: 0, type: "index", label: "序号", fixed: "", align: "center", "min-width": "50" }, { default: withCtx((scope) => [ createElementVNode("span", null, toDisplayString((_ctx.pageOpts.pageNum - 1) * _ctx.pageOpts.pageSize + scope.$index + 1), 1) ]), _: 1 })) : createCommentVNode("", true), _ctx.columnType === "selection" ? (openBlock(), createBlock(_component_el_table_column, { key: 1, type: "selection", fixed: "", align: "center", selectable: _ctx.selectable }, null, 8, ["selectable"])) : createCommentVNode("", true), _ctx.columnType === "expand" ? (openBlock(), createBlock(_component_el_table_column, { key: 2, type: "expand", label: "展开", fixed: "", align: "center", "min-width": "50" }, { default: withCtx((scope) => [ renderSlot(_ctx.$slots, "columnTypeExpand", { row: scope.row }, void 0, true) ]), _: 3 })) : createCommentVNode("", true), (openBlock(true), createElementBlock(Fragment, null, renderList(_ctx.useHeader, (h, hi) => { return openBlock(), createElementBlock(Fragment, { key: hi }, [ h.headerShow ? (openBlock(), createBlock(_component_el_table_column, { key: 0, label: h.label, prop: h.prop, fixed: h.fixed, "min-width": h.width, "show-overflow-tooltip": _ctx.tooltip, sortable: h.sortable, align: "center" }, { default: withCtx(() => [ h.children ? (openBlock(true), createElementBlock(Fragment, { key: 0 }, renderList(h.children, (h2, h2i) => { return openBlock(), createBlock(_component_el_table_column, { key: h2i, label: h2.label, prop: h2.prop, fixed: h2.fixed, "min-width": h2.width, "show-overflow-tooltip": _ctx.tooltip, align: "center" }, null, 8, ["label", "prop", "fixed", "min-width", "show-overflow-tooltip"]); }), 128)) : createCommentVNode("", true) ]), _: 2 }, 1032, ["label", "prop", "fixed", "min-width", "show-overflow-tooltip", "sortable"])) : createCommentVNode("", true) ], 64); }), 128)), renderSlot(_ctx.$slots, "otherColumn", {}, void 0, true) ]), _: 3 }, 8, ["style", "element-loading-text", "data", "max-height", "span-method", "empty-text", "onSelectionChange"])), [ [_directive_loading, _ctx.loading] ]) ], 4); } const TrendsTable = /* @__PURE__ */ _export_sfc(_sfc_main, [["render", _sfc_render], ["__scopeId", "data-v-fa2655ba"]]); const components = [ TrendsTable ]; const globals = { install: function(app) { components.map((item) => { app.component(item.name, item); }); }, // 局部引入时使用 TrendsTable }; export { globals as default };