123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203 |
- 'use strict';
- const { CrudService } = require('naf-framework-mongoose-free/lib/service');
- const { BusinessError, ErrorCode } = require('naf-core').Error;
- const _ = require('lodash');
- const assert = require('assert');
- //
- class MatchSignService extends CrudService {
- constructor(ctx) {
- super(ctx, 'matchsign');
- this.model = this.ctx.model.Race.MatchSign;
- this.matchModel = this.ctx.model.Race.Match;
- this.matchGroupModel = this.ctx.model.Race.MatchGroup;
- this.matchProjectModel = this.ctx.model.Race.MatchProject;
- }
- /**
- * 检查是否已经有该赛事,该组别,该项目的报名
- * @param {Object} body 参数体
- */
- async beforeCreate(body) {
- await this.checkHas(body);
- return body;
- }
- /**
- * 检查有没有报过名
- * @param {Object} body 参数体
- * @return {Boolean} true 可以继续进行
- */
- async checkHas(body) {
- const { match_id, group_id, project_id, user_id } = body;
- const query = { match_id, group_id, project_id, user_id, pay_status: [ '0', '1' ] };
- const num = await this.model.query(query);
- if (num > 0) throw new BusinessError(ErrorCode.DATA_EXISTED, '您已报名');
- return true;
- }
- async checkFit(body) {
- const { match_id, group_id, project_id, user_id, card = '22010319950601161X' } = body;
- await this.checkHas(body);
- const { pass, msg, gender: cardGender, age: cardAge } = this.idCodeValid(card);
- if (!pass) throw new BusinessError(ErrorCode.SERVICE_FAULT, msg);
- // 1.看 match 状态 是否为报名中
- const mnum = await this.matchModel.count({ _id: match_id, status: '1' });
- if (mnum <= 0) throw new BusinessError(ErrorCode.DATA_INVALID, '当前赛事不处于报名期');
- // 2.看matchGroup 年龄限制是否符合要求
- const matchGroup = await this.matchGroupModel.findById(group_id);
- if (!matchGroup) throw new BusinessError(ErrorCode.DATA_NOT_EXIST, '未找到当前组别');
- const { age } = matchGroup;
- let next = this.checkAgeInRange(age, cardAge);
- // 3.看 matchProject 年龄限制和性别限制,人数限制
- if (!next) throw new BusinessError(ErrorCode.DATA_INVALID, '年龄不符合组别条件');
- const matchProject = await this.matchProjectModel.findById(project_id);
- if (!matchProject) throw new BusinessError(ErrorCode.DATA_NOT_EXIST, '未找到组别项目');
- const { age: projectAge, gender } = matchProject;
- next = this.checkAgeInRange(projectAge, cardAge);
- if (!next) throw new BusinessError(ErrorCode.DATA_INVALID, '年龄不符合组别项目条件');
- if (gender !== '2') {
- if (gender !== cardGender) throw new BusinessError(ErrorCode.DATA_INVALID, '性别不符合组别条件');
- }
- return true;
- }
- checkAgeInRange(age, cardAge) {
- let next = true;
- if (_.isString(age) && age.indexOf('-') > -1) {
- const arr = age.split('-');
- console.log(arr);
- const start = parseInt(_.head(arr));
- const end = parseInt(_.last(arr));
- // inRange 是左闭右开区间,所以加1,形成闭区间
- const r = _.inRange(cardAge, start, end + 1);
- next = r;
- } else if (!age || age === '不限') next = true;
- return next;
- }
- // 身份证验证
- idCodeValid(code) {
- // 身份证号合法性验证
- // 支持15位和18位身份证号
- // 支持地址编码、出生日期、校验位验证
- const city = {
- 11: '北京',
- 12: '天津',
- 13: '河北',
- 14: '山西',
- 15: '内蒙古',
- 21: '辽宁',
- 22: '吉林',
- 23: '黑龙江 ',
- 31: '上海',
- 32: '江苏',
- 33: '浙江',
- 34: '安徽',
- 35: '福建',
- 36: '江西',
- 37: '山东',
- 41: '河南',
- 42: '湖北 ',
- 43: '湖南',
- 44: '广东',
- 45: '广西',
- 46: '海南',
- 50: '重庆',
- 51: '四川',
- 52: '贵州',
- 53: '云南',
- 54: '西藏 ',
- 61: '陕西',
- 62: '甘肃',
- 63: '青海',
- 64: '宁夏',
- 65: '新疆',
- 71: '台湾',
- 81: '香港',
- 82: '澳门',
- 91: '国外 ',
- };
- let row = {
- pass: true,
- msg: '验证成功',
- };
- if (!code || !/^\d{6}(18|19|20)?\d{2}(0[1-9]|1[012])(0[1-9]|[12]\d|3[01])\d{3}(\d|[xX])$/.test(code)) {
- row = {
- pass: false,
- msg: '身份证号格式错误',
- };
- } else if (!city[code.substr(0, 2)]) {
- row = {
- pass: false,
- msg: '身份证号地址编码错误',
- };
- } else {
- // 18位身份证需要验证最后一位校验位
- if (code.length === 18) {
- code = code.split('');
- // ∑(ai×Wi)(mod 11)
- // 加权因子
- const factor = [ 7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2 ];
- // 校验位
- const parity = [ 1, 0, 'X', 9, 8, 7, 6, 5, 4, 3, 2 ];
- let sum = 0;
- let ai = 0;
- let wi = 0;
- for (let i = 0; i < 17; i++) {
- ai = code[i];
- wi = factor[i];
- sum += ai * wi;
- }
- if (parity[sum % 11] !== code[17].toUpperCase()) {
- row = {
- pass: false,
- msg: '身份证号校验位错误',
- };
- }
- }
- }
- if (row.pass) {
- row.gender = this.maleOrFemalByIdCard(code);
- row.age = this.getAge(code);
- }
- return row;
- }
- // 性别
- maleOrFemalByIdCard(idCard) {
- if (_.isArray) idCard = idCard.join('');
- idCard = _.trim(idCard.replace(/ /g, '')); // 对身份证号码做处理。包括字符间有空格。
- if (idCard.length === 15) {
- if (idCard.substring(14, 15) % 2 === 0) {
- return '1';
- }
- return '0';
- } else if (idCard.length === 18) {
- if (idCard.substring(14, 17) % 2 === 0) {
- return '1';
- }
- return '0';
- }
- return null;
- }
- // 年龄
- getAge(idCard) {
- if (_.isArray) idCard = idCard.join('');
- const ageDate = new Date();
- const month = ageDate.getMonth() + 1;
- const day = ageDate.getDate();
- let age = ageDate.getFullYear() - idCard.substring(6, 10) - 1;
- if (idCard.substring(10, 12) < month || (idCard.substring(10, 12) === month && idCard.substring(12, 14) <= day)) {
- age++;
- }
- if (age <= 0) {
- age = 1;
- }
- return age;
- }
- }
- module.exports = MatchSignService;
|