UNPKG

vxe-table-demonic

Version:

一个基于 vue 的 PC 端表单/表格组件,支持增删改查、虚拟列表、虚拟树、懒加载、快捷菜单、数据校验、树形结构、打印导出、表单渲染、数据分页、弹窗、自定义模板、渲染器、JSON 配置式...

571 lines (570 loc) 22.1 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _vue = require("vue"); var _conf = _interopRequireDefault(require("../../v-x-e-table/src/conf")); var _xeUtils = _interopRequireDefault(require("xe-utils")); var _vXETable = require("../../v-x-e-table"); var _utils = require("../../tools/utils"); var _dom = require("../../tools/dom"); var _log = require("../../tools/log"); var _util = require("../../table/src/util"); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } var __assign = void 0 && (void 0).__assign || function () { __assign = Object.assign || function (t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; /** * 校验规则 */ var Rule = /** @class */function () { function Rule(rule) { Object.assign(this, { $options: rule, required: rule.required, min: rule.min, max: rule.max, type: rule.type, pattern: rule.pattern, validator: rule.validator, trigger: rule.trigger, maxWidth: rule.maxWidth }); } Object.defineProperty(Rule.prototype, "content", { /** * 获取校验不通过的消息 * 支持国际化翻译 */ get: function () { return (0, _utils.getFuncText)(this.$options.content || this.$options.message); }, enumerable: false, configurable: true }); Object.defineProperty(Rule.prototype, "message", { get: function () { return this.content; }, enumerable: false, configurable: true }); return Rule; }(); var tableValidatorMethodKeys = ['fullValidate', 'validate', 'clearValidate']; var validatorHook = { setupTable: function ($xetable) { var props = $xetable.props, reactData = $xetable.reactData, internalData = $xetable.internalData; var refValidTooltip = $xetable.getRefMaps().refValidTooltip; var _a = $xetable.getComputeMaps(), computeValidOpts = _a.computeValidOpts, computeTreeOpts = _a.computeTreeOpts, computeEditOpts = _a.computeEditOpts; var validatorMethods = {}; var validatorPrivateMethods = {}; var validRuleErr; /** * 聚焦到校验通过的单元格并弹出校验错误提示 */ var handleValidError = function (params) { return new Promise(function (resolve) { var validOpts = computeValidOpts.value; if (validOpts.autoPos === false) { $xetable.dispatchEvent('valid-error', params, null); resolve(); } else { $xetable.handleActived(params, { type: 'valid-error', trigger: 'call' }).then(function () { resolve(validatorPrivateMethods.showValidTooltip(params)); }); } }); }; var handleErrMsgMode = function (validErrMaps) { var validOpts = computeValidOpts.value; if (validOpts.msgMode === 'single') { var keys = Object.keys(validErrMaps); var resMaps = validErrMaps; if (keys.length) { var firstKey = keys[0]; resMaps[firstKey] = validErrMaps[firstKey]; } return resMaps; } return validErrMaps; }; /** * 对表格数据进行校验 * 如果不指定数据,则默认只校验临时变动的数据,例如新增或修改 * 如果传 true 则校验当前表格数据 * 如果传 row 指定行记录,则只验证传入的行 * 如果传 rows 为多行记录,则只验证传入的行 * 如果只传 callback 否则默认验证整个表格数据 * 返回 Promise 对象,或者使用回调方式 */ var beginValidate = function (rows, cb, isFull) { var validRest = {}; var editRules = props.editRules, treeConfig = props.treeConfig; var afterFullData = internalData.afterFullData, visibleColumn = internalData.visibleColumn; var treeOpts = computeTreeOpts.value; var childrenField = treeOpts.children || treeOpts.childrenField; var validOpts = computeValidOpts.value; var vaildDatas; if (rows === true) { vaildDatas = afterFullData; } else if (rows) { if (_xeUtils.default.isFunction(rows)) { cb = rows; } else { vaildDatas = _xeUtils.default.isArray(rows) ? rows : [rows]; } } if (!vaildDatas) { if ($xetable.getInsertRecords) { vaildDatas = $xetable.getInsertRecords().concat($xetable.getUpdateRecords()); } else { vaildDatas = []; } } var rowValids = []; internalData._lastCallTime = Date.now(); validRuleErr = false; // 如果为快速校验,当存在某列校验不通过时将终止执行 validatorMethods.clearValidate(); var validErrMaps = {}; if (editRules) { var columns_1 = $xetable.getColumns(); var handleVaild = function (row) { if (isFull || !validRuleErr) { var colVailds_1 = []; columns_1.forEach(function (column) { if ((isFull || !validRuleErr) && _xeUtils.default.has(editRules, column.property)) { colVailds_1.push(validatorPrivateMethods.validCellRules('all', row, column).catch(function (_a) { var rule = _a.rule, rules = _a.rules; var rest = { rule: rule, rules: rules, rowIndex: $xetable.getRowIndex(row), row: row, columnIndex: $xetable.getColumnIndex(column), column: column, field: column.property, $table: $xetable }; if (!validRest[column.property]) { validRest[column.property] = []; } validErrMaps["".concat((0, _util.getRowid)($xetable, row), ":").concat(column.id)] = { column: column, row: row, rule: rule, content: rule.content }; validRest[column.property].push(rest); if (!isFull) { validRuleErr = true; return Promise.reject(rest); } })); } }); rowValids.push(Promise.all(colVailds_1)); } }; if (treeConfig) { _xeUtils.default.eachTree(vaildDatas, handleVaild, { children: childrenField }); } else { vaildDatas.forEach(handleVaild); } return Promise.all(rowValids).then(function () { var ruleProps = Object.keys(validRest); reactData.validErrorMaps = handleErrMsgMode(validErrMaps); return (0, _vue.nextTick)().then(function () { if (ruleProps.length) { return Promise.reject(validRest[ruleProps[0]][0]); } if (cb) { cb(); } }); }).catch(function (firstErrParams) { return new Promise(function (resolve, reject) { var finish = function () { (0, _vue.nextTick)(function () { if (cb) { cb(validRest); resolve(); } else { if (_conf.default.validToReject === 'obsolete') { // 已废弃,校验失败将不会执行catch reject(validRest); } else { resolve(validRest); } } }); }; var posAndFinish = function () { firstErrParams.cell = $xetable.getCell(firstErrParams.row, firstErrParams.column); (0, _dom.scrollToView)(firstErrParams.cell); handleValidError(firstErrParams).then(finish); }; /** * 当校验不通过时 * 将表格滚动到可视区 * 由于提示信息至少需要占一行,定位向上偏移一行 */ if (validOpts.autoPos === false) { finish(); } else { var row = firstErrParams.row; var column = firstErrParams.column; var rowIndex = afterFullData.indexOf(row); var columnIndex = visibleColumn.indexOf(column); var locatRow = rowIndex > 0 ? afterFullData[rowIndex - 1] : row; var locatColumn = columnIndex > 0 ? visibleColumn[rowIndex - 1] : column; $xetable.scrollToRow(locatRow, locatColumn).then(posAndFinish); } }); }); } else { reactData.validErrorMaps = {}; } return (0, _vue.nextTick)().then(function () { if (cb) { cb(); } }); }; validatorMethods = { /** * 完整校验,和 validate 的区别就是会给有效数据中的每一行进行校验 */ fullValidate: function (rows, cb) { if (process.env.NODE_ENV === 'development') { if (_xeUtils.default.isFunction(cb)) { (0, _log.warnLog)('vxe.error.notValidators', ['fullValidate(rows, callback)', 'fullValidate(rows)']); } } return beginValidate(rows, cb, true); }, /** * 快速校验,如果存在记录不通过的记录,则返回不再继续校验(异步校验除外) */ validate: function (rows, cb) { if (process.env.NODE_ENV === 'development') { if (_xeUtils.default.isFunction(cb)) { (0, _log.warnLog)('vxe.error.notValidators', ['validate(rows, callback)', 'validate(rows)']); } } return beginValidate(rows, cb); }, clearValidate: function (rows, fieldOrColumn) { var validErrorMaps = reactData.validErrorMaps; var validTip = refValidTooltip.value; var validOpts = computeValidOpts.value; var rowList = _xeUtils.default.isArray(rows) ? rows : rows ? [rows] : []; var colList = _xeUtils.default.isArray(fieldOrColumn) ? fieldOrColumn : (fieldOrColumn ? [fieldOrColumn] : []).map(function (column) { return (0, _util.handleFieldOrColumn)($xetable, column); }); var validErrMaps = {}; if (validTip && validTip.reactData.visible) { validTip.close(); } // 如果是单个提示模式 if (validOpts.msgMode === 'single') { reactData.validErrorMaps = {}; return (0, _vue.nextTick)(); } if (rowList.length && colList.length) { validErrMaps = Object.assign({}, validErrorMaps); rowList.forEach(function (row) { colList.forEach(function (column) { var vaildKey = "".concat((0, _util.getRowid)($xetable, row), ":").concat(column.id); if (validErrMaps[vaildKey]) { delete validErrMaps[vaildKey]; } }); }); } else if (rowList.length) { var rowidList_1 = rowList.map(function (row) { return "".concat((0, _util.getRowid)($xetable, row)); }); _xeUtils.default.each(validErrorMaps, function (item, key) { if (rowidList_1.indexOf(key.split(':')[0]) > -1) { validErrMaps[key] = item; } }); } else if (colList.length) { var colidList_1 = colList.map(function (column) { return "".concat(column.id); }); _xeUtils.default.each(validErrorMaps, function (item, key) { if (colidList_1.indexOf(key.split(':')[1]) > -1) { validErrMaps[key] = item; } }); } reactData.validErrorMaps = validErrMaps; return (0, _vue.nextTick)(); } }; var validErrorRuleValue = function (rule, val) { var type = rule.type, min = rule.min, max = rule.max, pattern = rule.pattern; var isNumType = type === 'number'; var numVal = isNumType ? _xeUtils.default.toNumber(val) : _xeUtils.default.getSize(val); // 判断数值 if (isNumType && isNaN(val)) { return true; } // 如果存在 min,判断最小值 if (!_xeUtils.default.eqNull(min) && numVal < _xeUtils.default.toNumber(min)) { return true; } // 如果存在 max,判断最大值 if (!_xeUtils.default.eqNull(max) && numVal > _xeUtils.default.toNumber(max)) { return true; } // 如果存在 pattern,正则校验 if (pattern && !(_xeUtils.default.isRegExp(pattern) ? pattern : new RegExp(pattern)).test(val)) { return true; } return false; }; validatorPrivateMethods = { /** * 校验数据 * 按表格行、列顺序依次校验(同步或异步) * 校验规则根据索引顺序依次校验,如果是异步则会等待校验完成才会继续校验下一列 * 如果校验失败则,触发回调或者Promise<不通过列的错误消息> * 如果是传回调方式这返回一个校验不通过列的错误消息 * * rule 配置: * required=Boolean 是否必填 * min=Number 最小长度 * max=Number 最大长度 * validator=Function({ cellValue, rule, rules, row, column, rowIndex, columnIndex }) 自定义校验,接收一个 Promise * trigger=blur|change 触发方式(除非特殊场景,否则默认为空就行) */ validCellRules: function (validType, row, column, val) { var editRules = props.editRules; var field = column.field; var errorRules = []; var syncVailds = []; if (field && editRules) { var rules_1 = _xeUtils.default.get(editRules, field); if (rules_1) { var cellValue_1 = _xeUtils.default.isUndefined(val) ? _xeUtils.default.get(row, field) : val; rules_1.forEach(function (rule) { var type = rule.type, trigger = rule.trigger, required = rule.required, validator = rule.validator; if (validType === 'all' || !trigger || validType === trigger) { if (validator) { var validParams = { cellValue: cellValue_1, rule: rule, rules: rules_1, row: row, rowIndex: $xetable.getRowIndex(row), column: column, columnIndex: $xetable.getColumnIndex(column), field: column.field, $table: $xetable, $grid: $xetable.xegrid }; var customValid = void 0; if (_xeUtils.default.isString(validator)) { var gvItem = _vXETable.VXETable.validators.get(validator); if (gvItem) { if (gvItem.cellValidatorMethod) { customValid = gvItem.cellValidatorMethod(validParams); } else { if (process.env.NODE_ENV === 'development') { (0, _log.warnLog)('vxe.error.notValidators', [validator]); } } } else { if (process.env.NODE_ENV === 'development') { (0, _log.errLog)('vxe.error.notValidators', [validator]); } } } else { customValid = validator(validParams); } if (customValid) { if (_xeUtils.default.isError(customValid)) { validRuleErr = true; errorRules.push(new Rule({ type: 'custom', trigger: trigger, content: customValid.message, rule: new Rule(rule) })); } else if (customValid.catch) { // 如果为异步校验(注:异步校验是并发无序的) syncVailds.push(customValid.catch(function (e) { validRuleErr = true; errorRules.push(new Rule({ type: 'custom', trigger: trigger, content: e && e.message ? e.message : rule.content || rule.message, rule: new Rule(rule) })); })); } } } else { var isArrType = type === 'array'; var isArrVal = _xeUtils.default.isArray(cellValue_1); var hasEmpty = true; if (isArrType || isArrVal) { hasEmpty = !isArrVal || !cellValue_1.length; } else if (_xeUtils.default.isString(cellValue_1)) { hasEmpty = (0, _utils.eqEmptyValue)(cellValue_1.trim()); } else { hasEmpty = (0, _utils.eqEmptyValue)(cellValue_1); } if (required ? hasEmpty || validErrorRuleValue(rule, cellValue_1) : !hasEmpty && validErrorRuleValue(rule, cellValue_1)) { validRuleErr = true; errorRules.push(new Rule(rule)); } } } }); } } return Promise.all(syncVailds).then(function () { if (errorRules.length) { var rest = { rules: errorRules, rule: errorRules[0] }; return Promise.reject(rest); } }); }, hasCellRules: function (type, row, column) { var editRules = props.editRules; var field = column.field; if (field && editRules) { var rules = _xeUtils.default.get(editRules, field); return rules && !!_xeUtils.default.find(rules, function (rule) { return type === 'all' || !rule.trigger || type === rule.trigger; }); } return false; }, /** * 触发校验 */ triggerValidate: function (type) { var editConfig = props.editConfig, editRules = props.editRules; var editStore = reactData.editStore; var actived = editStore.actived; var editOpts = computeEditOpts.value; var validOpts = computeValidOpts.value; // 检查清除校验消息 if (editRules && validOpts.msgMode === 'single') { reactData.validErrorMaps = {}; } // 校验单元格 if (editConfig && editRules && actived.row) { var _a = actived.args, row_1 = _a.row, column_1 = _a.column, cell_1 = _a.cell; if (validatorPrivateMethods.hasCellRules(type, row_1, column_1)) { return validatorPrivateMethods.validCellRules(type, row_1, column_1).then(function () { if (editOpts.mode === 'row') { validatorMethods.clearValidate(row_1, column_1); } }).catch(function (_a) { var rule = _a.rule; // 如果校验不通过与触发方式一致,则聚焦提示错误,否则跳过并不作任何处理 if (!rule.trigger || type === rule.trigger) { var rest = { rule: rule, row: row_1, column: column_1, cell: cell_1 }; validatorPrivateMethods.showValidTooltip(rest); return Promise.reject(rest); } return Promise.resolve(); }); } } return Promise.resolve(); }, /** * 弹出校验错误提示 */ showValidTooltip: function (params) { var _a, _b; var height = props.height; var tableData = reactData.tableData, validStore = reactData.validStore, validErrorMaps = reactData.validErrorMaps; var rule = params.rule, row = params.row, column = params.column, cell = params.cell; var validOpts = computeValidOpts.value; var validTip = refValidTooltip.value; var content = rule.content; validStore.visible = true; if (validOpts.msgMode === 'single') { reactData.validErrorMaps = (_a = {}, _a["".concat((0, _util.getRowid)($xetable, row), ":").concat(column.id)] = { column: column, row: row, rule: rule, content: content }, _a); } else { reactData.validErrorMaps = Object.assign({}, validErrorMaps, (_b = {}, _b["".concat((0, _util.getRowid)($xetable, row), ":").concat(column.id)] = { column: column, row: row, rule: rule, content: content }, _b)); } $xetable.dispatchEvent('valid-error', params, null); if (validTip) { if (validTip && (validOpts.message === 'tooltip' || validOpts.message === 'default' && !height && tableData.length < 2)) { return validTip.open(cell, content); } } return (0, _vue.nextTick)(); } }; return __assign(__assign({}, validatorMethods), validatorPrivateMethods); }, setupGrid: function ($xegrid) { return $xegrid.extendTableMethods(tableValidatorMethodKeys); } }; var _default = validatorHook; exports.default = _default;