| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663 |
- "use strict";
- Object.defineProperty(exports, "__esModule", {
- value: true
- });
- exports.default = void 0;
- var _xeUtils = _interopRequireDefault(require("xe-utils"));
- var _ui = require("../../../ui");
- var _utils = require("../../../ui/src/utils");
- var _dom = require("../../../ui/src/dom");
- var _util = require("../../src/util");
- var _log = require("../../../ui/src/log");
- function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
- const {
- getConfig,
- validators
- } = _ui.VxeUI;
- /**
- * 校验规则
- */
- class Rule {
- constructor(rule) {
- Object.defineProperty(this, "$options", {
- enumerable: true,
- configurable: true,
- writable: true,
- value: void 0
- });
- 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
- });
- }
- /**
- * 获取校验不通过的消息
- * 支持国际化翻译
- */
- get content() {
- return (0, _utils.getFuncText)(this.$options.content || this.$options.message);
- }
- get message() {
- return this.content;
- }
- }
- // 如果存在 pattern,判断正则
- function validREValue(pattern, val) {
- if (pattern && !(_xeUtils.default.isRegExp(pattern) ? pattern : new RegExp(pattern)).test(val)) {
- return false;
- }
- return true;
- }
- // 如果存在 max,判断最大值
- function validMaxValue(max, num) {
- if (!_xeUtils.default.eqNull(max) && num > _xeUtils.default.toNumber(max)) {
- return false;
- }
- return true;
- }
- // 如果存在 min,判断最小值
- function validMinValue(min, num) {
- if (!_xeUtils.default.eqNull(min) && num < _xeUtils.default.toNumber(min)) {
- return false;
- }
- return true;
- }
- function validRuleValue(rule, val, required) {
- const {
- type,
- min,
- max,
- pattern
- } = rule;
- const isArrType = type === 'array';
- const isNumType = type === 'number';
- const isStrType = type === 'string';
- const strVal = `${val}`;
- if (!validREValue(pattern, strVal)) {
- return false;
- }
- if (isArrType) {
- if (!_xeUtils.default.isArray(val)) {
- return false;
- }
- if (required) {
- if (!val.length) {
- return false;
- }
- }
- if (!validMinValue(min, val.length)) {
- return false;
- }
- if (!validMaxValue(max, val.length)) {
- return false;
- }
- } else if (isNumType) {
- const numVal = Number(val);
- if (isNaN(numVal)) {
- return false;
- }
- if (!validMinValue(min, numVal)) {
- return false;
- }
- if (!validMaxValue(max, numVal)) {
- return false;
- }
- } else {
- if (isStrType) {
- if (!_xeUtils.default.isString(val)) {
- return false;
- }
- }
- if (required) {
- if (!strVal) {
- return false;
- }
- }
- if (!validMinValue(min, strVal.length)) {
- return false;
- }
- if (!validMaxValue(max, strVal.length)) {
- return false;
- }
- }
- return true;
- }
- function checkRuleStatus(rule, val) {
- const {
- required
- } = rule;
- const isEmptyVal = _xeUtils.default.isArray(val) ? !val.length : (0, _utils.eqEmptyValue)(val);
- if (required) {
- if (isEmptyVal) {
- return false;
- }
- if (!validRuleValue(rule, val, required)) {
- return false;
- }
- } else {
- if (!isEmptyVal) {
- if (!validRuleValue(rule, val, required)) {
- return false;
- }
- }
- }
- return true;
- }
- var _default = exports.default = {
- methods: {
- /**
- * 完整校验,和 validate 的区别就是会给有效数据中的每一行进行校验
- */
- _fullValidate(rows, cb) {
- if (_xeUtils.default.isFunction(cb)) {
- (0, _log.warnLog)('vxe.error.notValidators', ['fullValidate(rows, callback)', 'fullValidate(rows)']);
- }
- return this.beginValidate(rows, null, cb, true);
- },
- /**
- * 快速校验,如果存在记录不通过的记录,则返回不再继续校验(异步校验除外)
- */
- _validate(rows, cb) {
- if (_xeUtils.default.isFunction(cb)) {
- (0, _log.warnLog)('vxe.error.notValidators', ['validate(rows, callback)', 'validate(rows)']);
- }
- return this.beginValidate(rows, null, cb);
- },
- /**
- * 完整校验单元格,和 validateField 的区别就是会给有效数据中的每一行进行校验
- */
- _fullValidateField(rows, fieldOrColumn) {
- const colList = (_xeUtils.default.isArray(fieldOrColumn) ? fieldOrColumn : fieldOrColumn ? [fieldOrColumn] : []).map(column => (0, _util.handleFieldOrColumn)(this, column));
- if (colList.length) {
- return this.beginValidate(rows, colList, null, true);
- }
- return this.$nextTick();
- },
- /**
- * 快速校验单元格,如果存在记录不通过的记录,则返回不再继续校验(异步校验除外)
- */
- _validateField(rows, fieldOrColumn) {
- const colList = (_xeUtils.default.isArray(fieldOrColumn) ? fieldOrColumn : fieldOrColumn ? [fieldOrColumn] : []).map(column => (0, _util.handleFieldOrColumn)(this, column));
- if (colList.length) {
- return this.beginValidate(rows, colList, null);
- }
- return this.$nextTick();
- },
- /**
- * 聚焦到校验通过的单元格并弹出校验错误提示
- */
- handleValidError(params) {
- const $xeTable = this;
- const {
- validOpts
- } = this;
- return new Promise(resolve => {
- if (validOpts.autoPos === false) {
- $xeTable.dispatchEvent('valid-error', params, null);
- resolve();
- } else {
- this.handleEdit(params, {
- type: 'valid-error',
- trigger: 'call'
- }).then(() => {
- setTimeout(() => {
- resolve(this.showValidTooltip(params));
- }, 10);
- });
- }
- });
- },
- handleErrMsgMode(validErrMaps) {
- const {
- validOpts
- } = this;
- if (validOpts.msgMode === 'single') {
- const keys = Object.keys(validErrMaps);
- const resMaps = {};
- if (keys.length) {
- const firstKey = keys[0];
- resMaps[firstKey] = validErrMaps[firstKey];
- }
- return resMaps;
- }
- return validErrMaps;
- },
- /**
- * 对表格数据进行校验
- * 如果不指定数据,则默认只校验临时变动的数据,例如新增或修改
- * 如果传 true 则校验当前表格数据
- * 如果传 row 指定行记录,则只验证传入的行
- * 如果传 rows 为多行记录,则只验证传入的行
- * 如果只传 callback 否则默认验证整个表格数据
- * 返回 Promise 对象,或者使用回调方式
- */
- beginValidate(rows, cols, cb, isFull) {
- const $xeTable = this;
- const props = $xeTable;
- const reactData = $xeTable;
- const internalData = $xeTable;
- const validRest = {};
- const {
- editRules,
- treeConfig
- } = props;
- const {
- isRowGroupStatus
- } = reactData;
- const {
- afterFullData,
- pendingRowMaps,
- removeRowMaps
- } = internalData;
- const treeOpts = $xeTable.computeTreeOpts;
- const aggregateOpts = $xeTable.computeAggregateOpts;
- let validList;
- if (rows === true) {
- validList = afterFullData;
- } else if (rows) {
- if (_xeUtils.default.isFunction(rows)) {
- cb = rows;
- } else {
- validList = _xeUtils.default.isArray(rows) ? rows : [rows];
- }
- }
- if (!validList) {
- validList = this.getInsertRecords().concat(this.getUpdateRecords());
- }
- const rowValidErrs = [];
- this.lastCallTime = Date.now();
- this.validRuleErr = false; // 如果为快速校验,当存在某列校验不通过时将终止执行
- this.clearValidate();
- const validErrMaps = {};
- if (editRules) {
- const columns = cols && cols.length ? cols : this.getColumns();
- const handleVaild = row => {
- const rowid = (0, _util.getRowid)($xeTable, row);
- // 是否删除
- if (removeRowMaps[rowid]) {
- return;
- }
- // 是否标记删除
- if (pendingRowMaps[rowid]) {
- return;
- }
- if ($xeTable.isAggregateRecord(row)) {
- return;
- }
- if (isFull || !this.validRuleErr) {
- const colVailds = [];
- columns.forEach(column => {
- const field = _xeUtils.default.isString(column) ? column : column.field;
- if ((isFull || !this.validRuleErr) && _xeUtils.default.has(editRules, field)) {
- colVailds.push(this.validCellRules('all', row, column).catch(({
- rule,
- rules
- }) => {
- const rest = {
- rule,
- rules,
- rowIndex: this.getRowIndex(row),
- row,
- columnIndex: this.getColumnIndex(column),
- column,
- field,
- $table: this
- };
- if (!validRest[field]) {
- validRest[field] = [];
- }
- validErrMaps[`${(0, _util.getRowid)(this, row)}:${column.id}`] = {
- column,
- row,
- rule,
- content: rule.content
- };
- validRest[field].push(rest);
- if (!isFull) {
- this.validRuleErr = true;
- return Promise.reject(rest);
- }
- }));
- }
- });
- rowValidErrs.push(Promise.all(colVailds));
- }
- };
- if (isRowGroupStatus) {
- _xeUtils.default.eachTree(validList, handleVaild, {
- children: aggregateOpts.mapChildrenField
- });
- } else if (treeConfig) {
- const childrenField = treeOpts.children || treeOpts.childrenField;
- _xeUtils.default.eachTree(validList, handleVaild, {
- children: childrenField
- });
- } else {
- validList.forEach(handleVaild);
- }
- return Promise.all(rowValidErrs).then(() => {
- const ruleProps = Object.keys(validRest);
- this.validErrorMaps = this.handleErrMsgMode(validErrMaps);
- return this.$nextTick().then(() => {
- if (ruleProps.length) {
- return Promise.reject(validRest[ruleProps[0]][0]);
- }
- if (cb) {
- cb();
- }
- });
- }).catch(firstErrParams => {
- return new Promise((resolve, reject) => {
- const finish = () => {
- this.$nextTick(() => {
- if (cb) {
- cb(validRest);
- resolve();
- } else {
- if (getConfig().validToReject === 'obsolete') {
- // 已废弃,校验失败将不会执行catch
- reject(validRest);
- } else {
- resolve(validRest);
- }
- }
- });
- };
- const posAndFinish = () => {
- firstErrParams.cell = this.getCellElement(firstErrParams.row, firstErrParams.column);
- (0, _dom.scrollToView)(firstErrParams.cell);
- this.handleValidError(firstErrParams).then(finish);
- };
- /**
- * 当校验不通过时
- * 将表格滚动到可视区
- * 由于提示信息至少需要占一行,定位向上偏移一行
- */
- if (this.validOpts.autoPos === false) {
- finish();
- } else {
- const row = firstErrParams.row;
- const column = firstErrParams.column;
- this.scrollToRow(row, column).then(posAndFinish);
- }
- });
- });
- } else {
- this.validErrorMaps = {};
- }
- return this.$nextTick().then(() => {
- if (cb) {
- cb();
- }
- });
- },
- hasCellRules(type, row, column) {
- const {
- editRules
- } = this;
- const {
- property
- } = column;
- if (property && editRules) {
- const rules = _xeUtils.default.get(editRules, property);
- return rules && _xeUtils.default.find(rules, rule => type === 'all' || !rule.trigger || type === rule.trigger);
- }
- return false;
- },
- /**
- * 校验数据
- * 按表格行、列顺序依次校验(同步或异步)
- * 校验规则根据索引顺序依次校验,如果是异步则会等待校验完成才会继续校验下一列
- * 如果校验失败则,触发回调或者Promise<不通过列的错误消息>
- * 如果是传回调方式这返回一个校验不通过列的错误消息
- *
- * rule 配置:
- * required=Boolean 是否必填
- * min=Number 最小长度
- * max=Number 最大长度
- * validator=Function({ cellValue, rule, rules, row, column, rowIndex, columnIndex }) 自定义校验,接收一个 Promise
- * trigger=blur|change 触发方式(除非特殊场景,否则默认为空就行)
- */
- validCellRules(validType, row, column, val) {
- const {
- editRules
- } = this;
- const {
- property
- } = column;
- const errorRules = [];
- const syncValidList = [];
- if (property && editRules) {
- const rules = _xeUtils.default.get(editRules, property);
- if (rules) {
- const cellValue = _xeUtils.default.isUndefined(val) ? _xeUtils.default.get(row, property) : val;
- rules.forEach(rule => {
- const {
- trigger,
- validator
- } = rule;
- if (validType === 'all' || !trigger || validType === trigger) {
- if (validator) {
- const validParams = {
- cellValue,
- rule,
- rules,
- row,
- rowIndex: this.getRowIndex(row),
- column,
- columnIndex: this.getColumnIndex(column),
- field: column.property,
- $table: this
- };
- let customValid;
- if (_xeUtils.default.isString(validator)) {
- const gvItem = validators.get(validator);
- if (gvItem) {
- const tcvMethod = gvItem.tableCellValidatorMethod || gvItem.cellValidatorMethod;
- if (tcvMethod) {
- customValid = tcvMethod(validParams);
- } else {
- (0, _log.errLog)('vxe.error.notValidators', [validator]);
- }
- } else {
- (0, _log.errLog)('vxe.error.notValidators', [validator]);
- }
- } else {
- customValid = validator(validParams);
- }
- if (customValid) {
- if (_xeUtils.default.isError(customValid)) {
- this.validRuleErr = true;
- errorRules.push(new Rule({
- type: 'custom',
- trigger,
- content: customValid.message,
- rule: new Rule(rule)
- }));
- } else if (customValid.catch) {
- // 如果为异步校验(注:异步校验是并发无序的)
- syncValidList.push(customValid.catch(e => {
- this.validRuleErr = true;
- errorRules.push(new Rule({
- type: 'custom',
- trigger,
- content: e && e.message ? e.message : rule.content || rule.message,
- rule: new Rule(rule)
- }));
- }));
- }
- }
- } else {
- if (!checkRuleStatus(rule, cellValue)) {
- this.validRuleErr = true;
- errorRules.push(new Rule(rule));
- }
- }
- }
- });
- }
- }
- return Promise.all(syncValidList).then(() => {
- if (errorRules.length) {
- const rest = {
- rules: errorRules,
- rule: errorRules[0]
- };
- return Promise.reject(rest);
- }
- });
- },
- _clearValidate(rows, fieldOrColumn) {
- const {
- validOpts,
- validErrorMaps
- } = this;
- const validTip = this.$refs.refValidTooltip;
- const rowList = _xeUtils.default.isArray(rows) ? rows : rows ? [rows] : [];
- const colList = (_xeUtils.default.isArray(fieldOrColumn) ? fieldOrColumn : fieldOrColumn ? [fieldOrColumn] : []).map(column => (0, _util.handleFieldOrColumn)(this, column));
- let validErrMaps = {};
- if (validTip && validTip.visible) {
- validTip.close();
- }
- // 如果是单个提示模式
- if (validOpts.msgMode === 'single') {
- this.validErrorMaps = {};
- return this.$nextTick();
- }
- if (rowList.length && colList.length) {
- validErrMaps = Object.assign({}, validErrorMaps);
- rowList.forEach(row => {
- colList.forEach(column => {
- const validKey = `${(0, _util.getRowid)(this, row)}:${column.id}`;
- if (validErrMaps[validKey]) {
- delete validErrMaps[validKey];
- }
- });
- });
- } else if (rowList.length) {
- const rowIdList = rowList.map(row => `${(0, _util.getRowid)(this, row)}`);
- _xeUtils.default.each(validErrorMaps, (item, key) => {
- if (rowIdList.indexOf(key.split(':')[0]) > -1) {
- validErrMaps[key] = item;
- }
- });
- } else if (colList.length) {
- const colidList = colList.map(column => `${column.id}`);
- _xeUtils.default.each(validErrorMaps, (item, key) => {
- if (colidList.indexOf(key.split(':')[1]) > -1) {
- validErrMaps[key] = item;
- }
- });
- }
- this.validErrorMaps = validErrMaps;
- return this.$nextTick();
- },
- /**
- * 触发校验
- */
- triggerValidate(type) {
- const {
- editConfig,
- editStore,
- editRules,
- editOpts,
- validOpts
- } = this;
- const {
- actived
- } = editStore;
- // 检查清除校验消息
- if (editRules && validOpts.msgMode === 'single') {
- this.validErrorMaps = {};
- }
- // 校验单元格
- if (editConfig && editRules && actived.row) {
- const {
- row,
- column,
- cell
- } = actived.args;
- if (this.hasCellRules(type, row, column)) {
- return this.validCellRules(type, row, column).then(() => {
- if (editOpts.mode === 'row') {
- this.clearValidate(row, column);
- }
- }).catch(({
- rule
- }) => {
- // 如果校验不通过与触发方式一致,则聚焦提示错误,否则跳过并不作任何处理
- if (!rule.trigger || type === rule.trigger) {
- const rest = {
- rule,
- row,
- column,
- cell
- };
- this.showValidTooltip(rest);
- return Promise.reject(rest);
- }
- return Promise.resolve();
- });
- }
- }
- return Promise.resolve();
- },
- /**
- * 弹出校验错误提示
- */
- showValidTooltip(params) {
- const $xeTable = this;
- const {
- $refs,
- height,
- validStore,
- validErrorMaps,
- tableData,
- validOpts
- } = this;
- const {
- rule,
- row,
- column,
- cell
- } = params;
- const validTip = $refs.refValidTooltip;
- const content = rule.content;
- validStore.visible = true;
- if (validOpts.msgMode === 'single') {
- this.validErrorMaps = {
- [`${(0, _util.getRowid)(this, row)}:${column.id}`]: {
- column,
- row,
- rule,
- content
- }
- };
- } else {
- this.validErrorMaps = Object.assign({}, validErrorMaps, {
- [`${(0, _util.getRowid)(this, row)}:${column.id}`]: {
- column,
- row,
- rule,
- content
- }
- });
- }
- $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 this.$nextTick();
- }
- }
- };
|