UNPKG

@visactor/vue-vtable

Version:
219 lines (215 loc) 8.14 kB
'use strict'; var vutils = require('@visactor/vutils'); var vue = require('vue'); var VTable = require('@visactor/vtable'); /** * @description: 自定义渲染式编辑器 */ class DynamicRenderEditor { constructor(currentContext) { this.currentContext = currentContext; this.tableContainer = null; this.currentValue = null; this.wrapContainer = null; this.nodeMap = new Map(); } registerNode(tableId, key, getNode) { if (!vutils.isValid(tableId) || !vutils.isValid(key) || typeof getNode !== 'function') { return; } if (!this.nodeMap.has(tableId)) { this.nodeMap.set(tableId, new Map()); } this.nodeMap.get(tableId).set(key, getNode); } getNode(tableId, key) { var _a; return (_a = this.nodeMap.get(tableId)) === null || _a === void 0 ? void 0 : _a.get(key); } removeNode(tableId) { this.nodeMap.delete(tableId); } release(tableId) { if (!vutils.isValid(tableId)) { this.nodeMap.clear(); } else { this.removeNode(tableId); } } async onStart(editorContext) { const { value } = editorContext; // 先设置初始值(因为校验不通过也会走正常流程) this.setValue(value); if (!(await this.createElement(editorContext))) { return; } } async createElement(editorContext) { const { row, col, value, table, container, referencePosition } = editorContext; if (!container) { return false; } const define = table.getBodyColumnDefine(col, row); const { editConfig } = define || {}; const { id } = table; const key = this.getColumnKeyField(define); if (!vutils.isValid(key) || !vutils.isValid(id)) { return false; } if (typeof (editConfig === null || editConfig === void 0 ? void 0 : editConfig.editBefore) === 'function') { // 编辑前校验 const v = await editConfig.editBefore(editorContext); if (!v) { table.showTooltip(col, row, { // TODO 多语言 content: editConfig.disablePrompt || 'This field is not allowed to be edited', referencePosition: { rect: referencePosition === null || referencePosition === void 0 ? void 0 : referencePosition.rect, placement: VTable.TYPES.Placement.top }, style: { bgColor: 'black', color: 'white', arrowMark: true }, disappearDelay: 1000 }); return false; } } const record = table === null || table === void 0 ? void 0 : table.getCellOriginRecord(col, row); const renderVNodeFn = this.getNode(id, key); if (!renderVNodeFn) { return false; } const vnode = vue.h(renderVNodeFn, { row, col, value, refValue: vue.customRef((track, trigger) => { return { get: () => { track(); return this.getValue(); }, set: value => { this.setValue(value); trigger(); } }; }), record, table, onChange: (value) => this.setValue(value) }); if (!vnode || !vue.isVNode(vnode)) { return false; } this.checkToPassAppContext(vnode, table); // 创建包裹容器 const wrapContainer = document.createElement('div'); wrapContainer.style.position = 'absolute'; wrapContainer.style.width = '100%'; wrapContainer.style.boxSizing = 'border-box'; const { bgColor } = table.getCellStyle(col, row) || {}; wrapContainer.style.backgroundColor = bgColor || '#FFFFFF'; this.wrapContainer = wrapContainer; this.tableContainer = container; this.tableContainer.appendChild(wrapContainer); vue.render(vnode, wrapContainer); // 位置同步 if (referencePosition === null || referencePosition === void 0 ? void 0 : referencePosition.rect) { this.adjustPosition(referencePosition.rect); } return true; } /** * @description: 校验并传递上下文 * @param {VNode} vnode * @param {any} table * @return {*} */ checkToPassAppContext(vnode, table) { var _a, _b, _c, _d; try { const userAppContext = (_d = (_c = (_b = (_a = table.options) === null || _a === void 0 ? void 0 : _a.customConfig) === null || _b === void 0 ? void 0 : _b.getVueUserAppContext) === null || _c === void 0 ? void 0 : _c.call(_b)) !== null && _d !== void 0 ? _d : this.currentContext; // 简单校验合法性 if (!!(userAppContext === null || userAppContext === void 0 ? void 0 : userAppContext.components) && !!(userAppContext === null || userAppContext === void 0 ? void 0 : userAppContext.directives)) { vnode.appContext = userAppContext; } } catch (error) { } } /** * @description: 获取渲染式编辑器的列配置主键 * @param {any} column * @return {*} */ getColumnKeyField(column) { const { field, key } = column || {}; // 兼容取 field return vutils.isValid(key) ? key : field; } getValue() { return this.currentValue; } setValue(value) { this.currentValue = value; } adjustPosition(rect) { if (this.wrapContainer) { this.wrapContainer.style.top = `${rect.top}px`; this.wrapContainer.style.left = `${rect.left}px`; this.wrapContainer.style.width = `${rect.width}px`; this.wrapContainer.style.height = `${rect.height}px`; } } async validateValue(value, oldValue, editCell, table) { const { col, row } = editCell || {}; if (!vutils.isValid(col) || !vutils.isValid(row)) { return true; } const define = table.getBodyColumnDefine(col, row); const { editConfig } = define || {}; if (typeof (editConfig === null || editConfig === void 0 ? void 0 : editConfig.validateValue) === 'function') { const validate = await editConfig.validateValue({ col, row, value, oldValue, table }); if (validate === false) { const rect = table.getVisibleCellRangeRelativeRect({ col, row }); table.showTooltip(col, row, { content: editConfig.invalidPrompt || 'invalid', referencePosition: { rect, placement: VTable.TYPES.Placement.top }, style: { bgColor: 'red', color: 'white', arrowMark: true }, disappearDelay: 1000 }); return false; } return validate; } return true; } onEnd() { if (this.wrapContainer && this.tableContainer) { vue.render(null, this.wrapContainer); this.tableContainer.removeChild(this.wrapContainer); } this.wrapContainer = null; this.tableContainer = null; } isEditorElement(target) { var _a; return ((_a = this.wrapContainer) === null || _a === void 0 ? void 0 : _a.contains(target)) || this.isClickEditorElement(target); } isClickEditorElement(target) { while (target) { // 约定的类名 if (target.classList && target.classList.contains('table-editor-element')) { return true; } target = target.parentNode; } return false; } } exports.DynamicRenderEditor = DynamicRenderEditor;