/** * 琛ㄥ崟楠岃瘉 * * @param {Object} rules 验证字段的规则 * @param {Object} messages 验证字段的提示信息 * */ class WxValidate { constructor(rules = {}, messages = {}) { Object.assign(this, { data: {}, rules, messages, }) this.__init() } /** * __init */ __init() { this.__initMethods() this.__initDefaults() this.__initData() } /** * 鍒濆鍖栨暟鎹� */ __initData() { this.form = {} this.errorList = [] } /** * 鍒濆鍖栭粯璁ゆ彁绀轰俊鎭� */ __initDefaults() { this.defaults = { messages: { required: '这是必填字段。', email: '请输入有效的电子邮件地址。', tel: '请输入11位的手机号码。', url: '请输入有效的网址。', date: '请输入有效的日期。', dateISO: '请输入有效的日期(ISO),例如:2009-06-23,1998/01/22。', number: '请输入有效的数字。', digits: '只能输入数字。', idcard: '请输入18位的有效身份证。', equalTo: this.formatTpl('输入值必须和 {0} 相同。'), contains: this.formatTpl('输入值必须包含 {0}。'), minlength: this.formatTpl('最少要输入 {0} 个字符。'), maxlength: this.formatTpl('最多可以输入 {0} 个字符。'), rangelength: this.formatTpl('请输入长度在 {0} 到 {1} 之间的字符。'), min: this.formatTpl('请输入不小于 {0} 的数值。'), max: this.formatTpl('请输入不大于 {0} 的数值。'), range: this.formatTpl('请输入范围在 {0} 到 {1} 之间的数值。'), } } } /** * 鍒濆鍖栭粯璁ら獙璇佹柟娉� */ __initMethods() { const that = this that.methods = { /** * 这是必填字段。 */ required(value, param) { if (!that.depend(param)) { return "dependency-mismatch"; } else if (typeof value === "number") { value = value.toString(); } else if (typeof value === "boolean") { return !0; } return value.length > 0; }, /** * 请输入有效的电子邮件地址。 */ email(value) { return ( that.optional(value) || /^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/.test( value ) ); }, /** * 请输入11位的手机号码。 */ tel(value) { return that.optional(value) || /^1[34578]\d{9}$/.test(value); }, /** * 请输入有效的网址。 */ url(value) { return ( that.optional(value) || /^(?:(?:(?:https?|ftp):)?\/\/)(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})).?)(?::\d{2,5})?(?:[/?#]\S*)?$/i.test( value ) ); }, /** * 请输入有效的日期。 */ date(value) { return ( that.optional(value) || !/Invalid|NaN/.test(new Date(value).toString()) ); }, /** * 请输入有效的日期(ISO),例如:2009-06-23,1998/01/22。 */ dateISO(value) { return ( that.optional(value) || /^\d{4}[\/\-](0?[1-9]|1[012])[\/\-](0?[1-9]|[12][0-9]|3[01])$/.test( value ) ); }, /** * 请输入有效的数字。 */ number(value) { return ( that.optional(value) || /^(?:-?\d+|-?\d{1,3}(?:,\d{3})+)?(?:\.\d+)?$/.test(value) ); }, /** * 只能输入数字。 */ digits(value) { return that.optional(value) || /^\d+$/.test(value); }, /** * 请输入18位的有效身份证。 */ idcard(value) { return ( that.optional(value) || /^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}([0-9]|X)$/.test( value ) ); }, /** * 输入值必须和 field 相同 */ equalTo(value, param) { return that.optional(value) || value === that.data[param]; }, /** * 输入值必须包含 ABC */ contains(value, param) { return that.optional(value) || value.indexOf(param) >= 0; }, /** * 最少要输入 5 个字符 */ minlength(value, param) { return that.optional(value) || value.length >= param; }, /** * 最多可以输入 10 个字符 */ maxlength(value, param) { return that.optional(value) || value.length <= param; }, /** * 请输入长度在 5 到 10 之间的字符 */ rangelength(value, param) { return ( that.optional(value) || (value.length >= param[0] && value.length <= param[1]) ); }, /** * 请输入不小于 5 的数值 */ min(value, param) { return that.optional(value) || value >= param; }, /** * 请输入不大于 10 的数值 */ max(value, param) { return that.optional(value) || value <= param; }, /** * 请输入范围在 5 到 10 之间的数值 */ range(value, param) { return that.optional(value) || (value >= param[0] && value <= param[1]); }, }; } /** * 娣诲姞鑷畾涔夐獙璇佹柟娉� * @param {String} name 鏂规硶鍚� * @param {Function} method 鍑芥暟浣擄紝鎺ユ敹涓や釜鍙傛暟(value, param)锛寁alue琛ㄧず鍏冪礌鐨勫€硷紝param琛ㄧず鍙傛暟 * @param {String} message 鎻愮ず淇℃伅 */ addMethod(name, method, message) { this.methods[name] = method this.defaults.messages[name] = message !== undefined ? message : this.defaults.messages[name] } /** * 鍒ゆ柇楠岃瘉鏂规硶鏄惁瀛樺湪 */ isValidMethod(value) { let methods = [] for (let method in this.methods) { if (method && typeof this.methods[method] === 'function') { methods.push(method) } } return methods.indexOf(value) !== -1 } /** * 鏍煎紡鍖栨彁绀轰俊鎭ā鏉� */ formatTpl(source, params) { const that = this if (arguments.length === 1) { return function () { let args = Array.from(arguments) args.unshift(source) return that.formatTpl.apply(this, args) } } if (params === undefined) { return source } if (arguments.length > 2 && params.constructor !== Array) { params = Array.from(arguments).slice(1) } if (params.constructor !== Array) { params = [params] } params.forEach(function (n, i) { source = source.replace(new RegExp("\\{" + i + "\\}", "g"), function () { return n }) }) return source } /** * 鍒ゆ柇瑙勫垯渚濊禆鏄惁瀛樺湪 */ depend(param) { switch (typeof param) { case 'boolean': param = param break case 'string': param = !!param.length break case 'function': param = param() default: param = !0 } return param } /** * 鍒ゆ柇杈撳叆鍊兼槸鍚︿负绌� */ optional(value) { return !this.methods.required(value) && 'dependency-mismatch' } /** * 鑾峰彇鑷畾涔夊瓧娈电殑鎻愮ず淇℃伅 * @param {String} param 瀛楁鍚� * @param {Object} rule 瑙勫垯 */ customMessage(param, rule) { const params = this.messages[param] const isObject = typeof params === 'object' if (params && isObject) return params[rule.method] } /** * 鑾峰彇鏌愪釜鎸囧畾瀛楁鐨勬彁绀轰俊鎭� * @param {String} param 瀛楁鍚� * @param {Object} rule 瑙勫垯 */ defaultMessage(param, rule) { let message = this.customMessage(param, rule) || this.defaults.messages[rule.method] let type = typeof message if (type === 'undefined') { message = `Warning: No message defined for ${rule.method}.` } else if (type === 'function') { message = message.call(this, rule.parameters) } return message } /** * 缂撳瓨閿欒淇℃伅 * @param {String} param 瀛楁鍚� * @param {Object} rule 瑙勫垯 * @param {String} value 鍏冪礌鐨勫€� */ formatTplAndAdd(param, rule, value) { let msg = this.defaultMessage(param, rule) this.errorList.push({ param: param, msg: msg, value: value, }) } /** * 楠岃瘉鏌愪釜鎸囧畾瀛楁鐨勮鍒� * @param {String} param 瀛楁鍚� * @param {Object} rules 瑙勫垯 * @param {Object} data 闇€瑕侀獙璇佺殑鏁版嵁瀵硅薄 */ checkParam(param, rules, data) { // 缂撳瓨鏁版嵁瀵硅薄 this.data = data // 缂撳瓨瀛楁瀵瑰簲鐨勫€� const value = data[param] !== null && data[param] !== undefined ? data[param] : '' // 閬嶅巻鏌愪釜鎸囧畾瀛楁鐨勬墍鏈夎鍒欙紝渚濇楠岃瘉瑙勫垯锛屽惁鍒欑紦瀛橀敊璇俊鎭� for (let method in rules) { // 鍒ゆ柇楠岃瘉鏂规硶鏄惁瀛樺湪 if (this.isValidMethod(method)) { // 缂撳瓨瑙勫垯鐨勫睘鎬у強鍊� const rule = { method: method, parameters: rules[method] } // 璋冪敤楠岃瘉鏂规硶 const result = this.methods[method](value, rule.parameters) // 鑻esult杩斿洖鍊间负dependency-mismatch锛屽垯璇存槑璇ュ瓧娈电殑鍊间负绌烘垨闈炲繀濉瓧娈� if (result === 'dependency-mismatch') { continue } this.setValue(param, method, result, value) // 鍒ゆ柇鏄惁閫氳繃楠岃瘉锛屽惁鍒欑紦瀛橀敊璇俊鎭紝璺冲嚭寰幆 if (!result) { this.formatTplAndAdd(param, rule, value) break } } } } /** * 璁剧疆瀛楁鐨勯粯璁ら獙璇佸€� * @param {String} param 瀛楁鍚� */ setView(param) { this.form[param] = { $name: param, $valid: true, $invalid: false, $error: {}, $success: {}, $viewValue: ``, } } /** * 璁剧疆瀛楁鐨勯獙璇佸€� * @param {String} param 瀛楁鍚� * @param {String} method 瀛楁鐨勬柟娉� * @param {Boolean} result 鏄惁閫氳繃楠岃瘉 * @param {String} value 瀛楁鐨勫€� */ setValue(param, method, result, value) { const params = this.form[param] params.$valid = result params.$invalid = !result params.$error[method] = !result params.$success[method] = result params.$viewValue = value } /** * 楠岃瘉鎵€鏈夊瓧娈电殑瑙勫垯锛岃繑鍥為獙璇佹槸鍚﹂€氳繃 * @param {Object} data 闇€瑕侀獙璇佹暟鎹璞� */ checkForm(data) { this.__initData() for (let param in this.rules) { this.setView(param) this.checkParam(param, this.rules[param], data) } return this.valid() } /** * 杩斿洖楠岃瘉鏄惁閫氳繃 */ valid() { return this.size() === 0 } /** * 杩斿洖閿欒淇℃伅鐨勪釜鏁� */ size() { return this.errorList.length } /** * 杩斿洖鎵€鏈夐敊璇俊鎭� */ validationErrors() { return this.errorList } } export default WxValidate