vxe-table-demonic
Version:
一个基于 vue 的 PC 端表单/表格组件,支持增删改查、虚拟列表、虚拟树、懒加载、快捷菜单、数据校验、树形结构、打印导出、表单渲染、数据分页、弹窗、自定义模板、渲染器、JSON 配置式...
571 lines (570 loc) • 22.1 kB
JavaScript
;
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;