import { renderNode } from "@/utils/vnode"; import { isNull } from "@/utils"; import { Emitter } from "@/mixins"; export default { name: "cl-table", componentName: "ClTable", inject: ["crud"], mixins: [Emitter], props: { columns: { type: Array, required: true, default: () => [] }, on: { type: Object, default: () => { return {}; } }, props: { type: Object, default: () => { return {}; } } }, data() { return { maxHeight: null, data: [], emit: {} }; }, created() { // Get default sort const { order, prop } = this.props["default-sort"] || {}; // Set request params this.crud.params.order = !order ? "" : order === "descending" ? "desc" : "asc"; this.crud.params.prop = prop; // Crud event this.$on("crud.resize", () => { this.calcMaxHeight(); }); // Crud refresh this.$on("crud.refresh", ({ list }) => { this.data = list; }); }, mounted() { this.emptyRender(); this.calcMaxHeight(); this.bindEmit(); this.bindMethods() }, methods: { columnRender() { return this.columns .filter((e) => !e.hidden) .map((item, index) => { const deep = (item) => { let params = { props: item, on: item.on }; // If op if (item.type === "op") { return this.opRender(item); } // Default if (!item.type || item.type === "expand") { params.scopedSlots = { default: (scope) => { // Column-slot let slot = this.$scopedSlots[`column-${item.prop}`]; let newScope = { ...scope, ...item }; let value = scope.row[item.prop]; if (slot) { // Use slot return slot({ scope: newScope }); } else { // If component if (item.component) { return renderNode(item.component, { prop: item.prop, scope: newScope.row }); } // Formatter else if (item.formatter) { return item.formatter( newScope.row, newScope.column, newScope.row[item.prop], newScope.$index ); } // Dict tag else if (item.dict) { let data = item.dict.find((d) => d.value == value); if (data) { // Use el-tag return ( {data.label} ); } else { return value; } } // Empty text else if (isNull(value)) { return scope.emptyText; } // Value else { return value; } } }, header: (scope) => { let slot = this.$scopedSlots[`header-${item.prop}`]; if (slot) { return slot({ scope }); } else { return scope.column.label; } } }; } // Children element const childrenEl = item.children ? item.children.map(deep) : null; return ( {childrenEl} ); }; return deep(item); }); }, opRender(item) { const { rowEdit, rowDelete, getPermission } = this.crud; if (!item) { return null; } const render = (scope) => { // Use op layout return (item.layout || ["edit", "delete"]).map((vnode) => { if (["edit", "update", "delete"].includes(vnode)) { // Get permission const perm = getPermission(vnode); if (perm) { let clickEvent = () => { }; let buttonText = null; switch (vnode) { case "edit": case "update": clickEvent = rowEdit; buttonText = this.crud.dict.label.update; break; case "delete": clickEvent = rowDelete; buttonText = this.crud.dict.label.delete; break; } return ( { clickEvent(scope.row); }}> {buttonText} ); } } else { // Use custom render return renderNode(vnode, { scope, $scopedSlots: this.$scopedSlots }); } }); }; return ( { let el = null; // Dropdown op if (item.name == "dropdown-menu") { const slot = this.$scopedSlots["table-op-dropdown-menu"]; const { width } = item["dropdown-menu"] || {}; const items = render(scope).map((e) => { return {e}; }); el = ( {slot ? ( slot({ scope }) ) : ( 更多操作 )} {items} ); } else { el = render(scope); } return
{el}
; } } }} /> ); }, emptyRender() { const empty = this.$scopedSlots["table-empty"]; const scope = { h: this.$createElement, scope: this }; if (empty) { this.$scopedSlots.empty = () => { return empty(scope)[0]; }; } }, appendRender() { return this.$slots["append"]; }, changeSort(prop, order) { if (order === "desc") { order = "descending"; } if (order === "asc") { order = "ascending"; } this.$refs["table"].sort(prop, order); }, sortChange({ prop, order }) { if (order === "descending") { order = "desc"; } if (order === "ascending") { order = "asc"; } if (!order) { prop = null; } if (this.crud.test.sortLock) { this.crud.refresh({ prop, order, page: 1 }); } }, selectionChange(selection) { this.dispatch("cl-crud", "table.selection-change", { selection }); this.$emit("selection-change", selection); }, bindEmit() { const funcs = [ "select", "select-all", "cell-mouse-enter", "cell-mouse-leave", "cell-click", "cell-dblclick", "row-click", "row-contextmenu", "row-dblclick", "header-click", "header-contextmenu", "filter-change", "current-change", "header-dragend", "expand-change" ]; funcs.forEach((name) => { this.emit[name] = (...args) => { this.$emit.apply(this, [name, ...args]); }; }); }, bindMethods() { [ "clearSelection", "toggleRowSelection", "toggleAllSelection", "toggleRowExpansion", "setCurrentRow", "clearSort", "clearFilter", "doLayout", "sort" ].forEach(e => { this[e] = this.$refs["table"][e]; }); }, calcMaxHeight() { return this.$nextTick(() => { const el = this.crud.$el.parentNode; let { height = "" } = this.props || {}; if (el) { let rows = el.querySelectorAll(".cl-crud .el-row"); if (!rows[0] || !rows[0].isConnected) { return false; } let h = 20; for (let i = 0; i < rows.length; i++) { let f = true; for (let j = 0; j < rows[i].childNodes.length; j++) { if (rows[i].childNodes[j].className == "cl-table") { f = false; } } if (f) { h += rows[i].clientHeight + 10; } } let h1 = Number(String(height).replace("px", "")); let h2 = el.clientHeight - h; this.maxHeight = h1 > h2 ? h1 : h2; } }); } }, render() { return (
{ {this.columnRender()} }
); } };