校友会小程序开发笔记十四: 小程序云开发后端数据校验体系的设计与实现

微信小程序云开发后端开发框架没有自带的验证功能,因此开发校友录小程序的表单验证时候一般有两种方法,一是自己裸写验证规则,但是需要比较扎实的正则表达式基础,一种是自己封装Validate插件进行表单验证,基于以上原因,小女子自己封装了云开发后端数据校验规则一套,并且与前端数据校验的写法和规则一致(前端数据校验体系下一篇笔记介绍:))

统一校验路由入口

function check(data, rules, that) {
    let returnData = {};
    for (let k in rules) {
        let arr = rules[k].split(\'|\');
        let desc = \'\';

        // 校友录小程序数据项说明
        for (let i = 0; i < arr.length; i++) {
            if (arr[i].indexOf(\'name=\') > -1) {
                desc = arr[i].replace(\'name=\', \'\');
                break;
            }
        }

        //校友录小程序校验 
        let formName = arr[0];
        let val = data[formName];
        if (val === undefined) val = \'\';
        if (!Array.isArray(val))
            val = String(val).trim(); // 前后去空格
        returnData[k] = val;

        for (let i = 1; i < arr.length; i++) {
            let result = \'\';

            let rules = arr[i].split(\':\');

            //校友录小程序空不校验
            if (rules[0] != \'required\' && val == \'\') continue;

            switch (rules[0]) {
                case \'required\':
                    result = checkRequired(val, desc);
                    break;
                case \'array\':
                    result = checkArray(val, desc);
                    break;
                case \'date\':
                    result = checkDate(val, desc);
                    break;
                case \'time\':
                    result = checkTime(val, desc);
                    break;
                case \'datetime\':
                    result = checkDatimeTime(val, desc);
                    break;
                case \'min\':
                    result = checkMin(val, Number(rules[1]), desc);
                    break;
                case \'max\':
                    result = checkMax(val, Number(rules[1]), desc);
                    break;
                case \'len\':
                    result = checkLen(val, Number(rules[1]), desc);
                    break;
                case \'in\':
                    result = checkIn(val, rules[1], desc);
                    break;
                case \'email\':
                    result = checkEmail(val, desc);
                    break;
                case \'mobile\':
                    result = checkMobile(val, desc);
                    break;
                case \'int\':
                    result = checkInt(val, desc);
                    break;
                case \'id\':
                    result = checkId(val, desc);
                    break;
                case \'letter\':
                    result = checkLetter(val, desc);
                    break;
                case \'letter_num\':
                    result = checkLetterNum(val, desc);
                    break;
            }

            if (result) {
                wx.showModal({
                    title: \'温馨提示\',
                    content: result,
                    showCancel: false,
                    success(res) {
                        //校友录小程序自动聚焦
                        if (that)
                            that.setData({
                                [formName + \'Focus\']: true
                            });
                    }
                });
                return false;
            } else {
                if (that) {
                    // 删除原有的校友录小程序自动聚焦
                    if (helper.isDefined(that.data[formName + \'Focus\'])) {
                        that.setData({ //TODO delete?
                            [formName + \'Focus\']: false
                        });
                    }
                }
            }

        }
    }
    return returnData;
}

分项数据校验实现

/**
 * 校验校友录小程序字符长度
 * @param {*} value 
 * @param {*} min 
 * @param {*} max 
 */
function isCheckLen(value, min, max) { //TODO 数字怎么处理
    if (!helper.isDefined(value)) return false;
    if (typeof (value) != \'string\') return false;
    if (value.length < min || value.length > max) return false;
    return true;
}

/**
 * 校验校友录小程序数字大小
 * @param {*} value 
 * @param {*} min 
 * @param {*} max 
 */
function isCheckM(value, min, max) {
    if (!helper.isDefined(value)) return false;

    if (typeof (value) == \'string\' && /^[0-9]+$/.test(value))
        value = Number(value);
    if (typeof (value) != \'number\') return false;

    if (value < min || value > max) return false;
    return true;
}

function checkMin(value, len, desc) {
    if (value.length < len)
        return desc + \'不能小于\' + len + \'位\';
};

function checkMax(value, len, desc) {
    if (value.length > len)
        return desc + \'不能大于\' + len + \'位\';
};

function checkLen(value, len, desc) {
    if (value.length != len)
        return desc + \'必须为\' + len + \'位\';
};

function checkMobile(value, desc) {
    if (value == \'\') return \'\';
    if (!/(^1[3|5|8][0-9]{9}$)/.test(value))
        return desc + \'格式不正确\';
}

function checkInt(value, desc) {
    if (value == \'\') return \'\';
    if (!/^[0-9]+$/.test(value))
        return desc + \'必须为数字\';
}

function checkLetter(value, desc) {
    if (value == \'\') return;
    if (!/^[A-Za-z]+$/.test(value))
        return desc + \'必须为字母\';
}

function checkLetterNum(value, desc) {
    if (value == \'\') return;
    if (!/^\w+$/.test(value))
        return desc + \'必须为字母,数字和下划线\';
}

function checkId(value, desc, min = 1, max = 32) {
    if (value == \'\') return;
    if (value.length < min || value.length > max) return false;
    if (!/^\w+$/.test(value))
        return desc + \'必须为ID格式\';
}

function isCheckId(value, min = 1, max = 32) {
    if (!helper.isDefined(value)) return false;
    if (typeof (value) != \'string\') return false;
    if (value.length < min || value.length > max) return false;
    if (!/^\w+$/.test(value))
        return false;
    return true;
}

//  校友录小程序邮箱
function checkEmail(value, desc) {
    if (value == \'\') return;
    let hint = desc + \'必须为邮箱格式\';
    let reg = /^[A-Za-z0-9+]+[A-Za-z0-9\.\_\-+]*@([A-Za-z0-9\-]+\.)+[A-Za-z0-9]+$/;
    if (!reg.test(value)) return hint;
}

// 校友录小程序短日期,形如 (2008-07-22)
function checkDate(value, desc) {
    if (value == \'\') return;
    let hint = \'请选择\' + desc;
    if (value.length != 10) return hint;
    let r = value.match(/^(\d{1,4})(-|\/)(\d{1,2})\2(\d{1,2})$/);
    if (r == null) return hint;
    let d = new Date(r[1], r[3] - 1, r[4]);
    let chk = d.getFullYear() == r[1] && (d.getMonth() + 1) == r[3] && d.getDate() == r[4];
    if (!chk)
        return hint;
}

// 校友录小程序短时间,形如 (13:04:06)
function checkTime(value, desc) {
    if (value == \'\') return;
    let hint = desc + \'必须为时间格式\';
    if (value.length != 8) return hint;

    let a = value.match(/^(\d{1,2})(:)?(\d{1,2})\2(\d{1,2})$/);
    if (a == null) return hint;
    if (a[1] > 24 || a[3] > 60 || a[4] > 60) return hint;
}

// 校友录小程序长时间,形如 (2008-07-22 13:04:06)
function checkDatimeTime(value, desc) {
    if (value == \'\') return;
    let hint = desc + \'必须为完整时间格式\';
    if (value.length != 19) return hint;

    var reg = /^(\d{1,4})(-|\/)(\d{1,2})\2(\d{1,2}) (\d{1,2}):(\d{1,2}):(\d{1,2})$/;
    var r = value.match(reg);
    if (r == null) return hint;
    var d = new Date(r[1], r[3] - 1, r[4], r[5], r[6], r[7]);
    let chk = d.getFullYear() == r[1] && (d.getMonth() + 1) == r[3] && d.getDate() == r[4] && d.getHours() == r[5] && d.getMinutes() == r[6] && d.getSeconds() == r[7];
    if (!chk) return hint;
}

function checkArray(value, desc) {
    if (value == \'\') return;
    if (!Array.isArray(value))
        return desc + \'填写错误\';
}

function checkIn(value, ref, desc) {
    if (value == \'\') return;
    let arr = ref.split(\',\');
    if (!arr.includes(value) && !arr.includes(value + \'\'))
        return desc + \'填写错误\';
}

/**
 * 检查校友录小程序枚举类型 
 * @param {*} value 
 * @param {*} ref 格式 1,2,3 
 */
function isCheckIn(value, ref) {
    if (!helper.isDefined(value)) return false;
    let arr = ref.split(\',\');
    if (!arr.includes(value) && !arr.includes(value + \'\')) return false; //字符,数字都支持
    return true;
}

在校友录小程序中的使用示范

// 校友录小程序数据校验
        let rules = {
            search: \'string|min:1|max:30|name=搜索条件\',
            sortType: \'string|name=搜索类型\',
            sortVal: \'name=搜索类型值\',
            orderBy: \'object|name=排序\',
            whereEx: \'object|name=附加查询条件\',
            page: \'required|int|default=1\',
            size: \'int\',
            isTotal: \'bool\',
            oldTotal: \'int\',
        };

        // 取得校友录小程序数据
        let input = this.validateData(rules);

        let service = new GroupService();
        let result = await service.getMyGroupList(this._userId, input);

/**

* 校验字符长度

* @param {*} value

* @param {*} min

* @param {*} max

*/

function isCheckLen(value, min, max) { //TODO 数字怎么处理

if (!helper.isDefined(value)) return false;

if (typeof (value) != \'string\') return false;

if (value.length < min || value.length > max) return false;

return true;

}

/**

* 校验数字大小

* @param {*} value

* @param {*} min

* @param {*} max

*/

function isCheckM(value, min, max) {

if (!helper.isDefined(value)) return false;

if (typeof (value) == \'string\' && /^[0-9]+$/.test(value))

value = Number(value);

if (typeof (value) != \'number\') return false;

if (value < min || value > max) return false;

return true;

}

function checkMin(value, len, desc) {

if (value.length < len)

return desc + \'不能小于\' + len + \'位\';

};

function checkMax(value, len, desc) {

if (value.length > len)

return desc + \'不能大于\' + len + \'位\';

};

function checkLen(value, len, desc) {

if (value.length != len)

return desc + \'必须为\' + len + \'位\';

};

function checkMobile(value, desc) {

if (value == \'\') return \'\';

if (!/(^1[3|5|8][0-9]{9}$)/.test(value))

return desc + \'格式不正确\';

}

function checkInt(value, desc) {

if (value == \'\') return \'\';

if (!/^[0-9]+$/.test(value))

return desc + \'必须为数字\';

}

function checkLetter(value, desc) {

if (value == \'\') return;

if (!/^[A-Za-z]+$/.test(value))

return desc + \'必须为字母\';

}

function checkLetterNum(value, desc) {

if (value == \'\') return;

if (!/^\w+$/.test(value))

return desc + \'必须为字母,数字和下划线\';

}

function checkId(value, desc, min = 1, max = 32) {

if (value == \'\') return;

if (value.length < min || value.length > max) return false;

if (!/^\w+$/.test(value))

return desc + \'必须为ID格式\';

}

function isCheckId(value, min = 1, max = 32) {

if (!helper.isDefined(value)) return false;

if (typeof (value) != \'string\') return false;

if (value.length < min || value.length > max) return false;

if (!/^\w+$/.test(value))

return false;

return true;

}

// 邮箱

function checkEmail(value, desc) {

if (value == \'\') return;

let hint = desc + \'必须为邮箱格式\';

let reg = /^[A-Za-z0-9+]+[A-Za-z0-9\.\_\-+]*@([A-Za-z0-9\-]+\.)+[A-Za-z0-9]+$/;

if (!reg.test(value)) return hint;

}

// 短日期,形如 (2008-07-22)

function checkDate(value, desc) {

if (value == \'\') return;

let hint = \'请选择\' + desc;

if (value.length != 10) return hint;

let r = value.match(/^(\d{1,4})(-|\/)(\d{1,2})\2(\d{1,2})$/);

if (r == null) return hint;

let d = new Date(r[1], r[3] - 1, r[4]);

let chk = d.getFullYear() == r[1] && (d.getMonth() + 1) == r[3] && d.getDate() == r[4];

if (!chk)

return hint;

}

// 短时间,形如 (13:04:06)

function checkTime(value, desc) {

if (value == \'\') return;

let hint = desc + \'必须为时间格式\';

if (value.length != 8) return hint;

let a = value.match(/^(\d{1,2})(:)?(\d{1,2})\2(\d{1,2})$/);

if (a == null) return hint;

if (a[1] > 24 || a[3] > 60 || a[4] > 60) return hint;

}

// 长时间,形如 (2008-07-22 13:04:06)

function checkDatimeTime(value, desc) {

if (value == \'\') return;

let hint = desc + \'必须为完整时间格式\';

if (value.length != 19) return hint;

var reg = /^(\d{1,4})(-|\/)(\d{1,2})\2(\d{1,2}) (\d{1,2}):(\d{1,2}):(\d{1,2})$/;

var r = value.match(reg);

if (r == null) return hint;

var d = new Date(r[1], r[3] - 1, r[4], r[5], r[6], r[7]);

let chk = d.getFullYear() == r[1] && (d.getMonth() + 1) == r[3] && d.getDate() == r[4] && d.getHours() == r[5] && d.getMinutes() == r[6] && d.getSeconds() == r[7];

if (!chk) return hint;

}

function checkArray(value, desc) {

if (value == \'\') return;

if (!Array.isArray(value))

return desc + \'填写错误\';

}

function checkIn(value, ref, desc) {

if (value == \'\') return;

let arr = ref.split(\',\');

if (!arr.includes(value) && !arr.includes(value + \'\'))

return desc + \'填写错误\';

}

/**

* 检查枚举类型

* @param {*} value

* @param {*} ref 格式 1,2,3

*/

function isCheckIn(value, ref) {

if (!helper.isDefined(value)) return false;

let arr = ref.split(\',\');

if (!arr.includes(value) && !arr.includes(value + \'\')) return false; //字符,数字都支持

return true;

}

function checkIds(value, desc) {}

function checkString(value, desc) {}

function check(data, rules, that) {

let returnData = {};

for (let k in rules) {

let arr = rules[k].split(\'|\');

let desc = \'\';

// 数据项说明

for (let i = 0; i < arr.length; i++) {

if (arr[i].indexOf(\'name=\') > -1) {

desc = arr[i].replace(\'name=\', \'\');

break;

}

}

// 校验

let formName = arr[0];

let val = data[formName];

if (val === undefined) val = \'\';

if (!Array.isArray(val))

val = String(val).trim(); // 前后去空格

returnData[k] = val;

for (let i = 1; i < arr.length; i++) {

let result = \'\';

let rules = arr[i].split(\':\');

// 空不校验

if (rules[0] != \'required\' && val == \'\') continue;

switch (rules[0]) {

case \'required\':

result = checkRequired(val, desc);

break;

case \'array\':

result = checkArray(val, desc);

break;

case \'date\':

result = checkDate(val, desc);

break;

case \'time\':

result = checkTime(val, desc);

break;

case \'datetime\':

result = checkDatimeTime(val, desc);

break;

case \'min\':

result = checkMin(val, Number(rules[1]), desc);

break;

case \'max\':

result = checkMax(val, Number(rules[1]), desc);

break;

case \'len\':

result = checkLen(val, Number(rules[1]), desc);

break;

case \'in\':

result = checkIn(val, rules[1], desc);

break;

case \'email\':

result = checkEmail(val, desc);

break;

case \'mobile\':

result = checkMobile(val, desc);

break;

case \'int\':

result = checkInt(val, desc);

break;

case \'id\':

result = checkId(val, desc);

break;

case \'letter\':

result = checkLetter(val, desc);

break;

case \'letter_num\':

result = checkLetterNum(val, desc);

break;

}

if (result) {

wx.showModal({

title: \'温馨提示\',

content: result,

showCancel: false,

success(res) {

// 自动聚焦

if (that)

that.setData({

[formName + \'Focus\']: true

});

}

});

return false;

} else {

if (that) {

// 删除原有的自动聚焦

if (helper.isDefined(that.data[formName + \'Focus\'])) {

that.setData({ //TODO delete?

[formName + \'Focus\']: false

});

}

}

}

}

}

return returnData;

}

项目代码GIT: https://github.com/ccliqi/CC-almni