... ... @@ -61,25 +61,23 @@ module.exports.getUserInfoAPI = (req, res, next) => {
};
module.exports.sendCodeAPI = (req, res, next) => {
let userInput = req.body.phoneNum || '';
let areaCode = req.body.area || '86';
let inputInfo = req.inputInfo;
service.sendCodeToUserAsync(userInput, areaCode).then(result => {
switch (result) {
case 'mobile':
service.sendCodeToUserAsync(inputInfo.type, inputInfo.mobile, inputInfo.area).then(result => {
switch (inputInfo.type) {
case 'email':
{
res.redirect('/passport/back/sendemail.html');
res.redirect('/passport/back/sendEmail.html');
break;
}
case 'email':
case 'mobile':
{
res.redirect('/passport/back/verification.html');
break;
}
default:
{
res.redirect('./passport/back/index.html');
res.redirect('/passport/back/index.html');
}
}
}).catch(next);
... ... @@ -100,8 +98,8 @@ module.exports.sendEmailPage = (req, res, next) => {
service.getSendEmailPageDataAsync()
.then(result => {
res.render('back/send-email', Object.assign({
module: 'back',
page: 'send-email',
module: 'passport',
page: 'back-send-email-ok',
title: "邮件发送成功"
}, result
));
... ... @@ -109,7 +107,7 @@ module.exports.sendEmailPage = (req, res, next) => {
};
module.exports.checkEmailCodePage = (req, res, next) => {
module.exports.checkCodePage = (req, res, next) => {
let code = req.param('code', '');
service.checkEmailCodeAsync(code)
... ... @@ -122,14 +120,14 @@ module.exports.checkEmailCodePage = (req, res, next) => {
}).catch(next);
};
module.exports.resetPasswordByEmailPage = (req, res, next) => {
let code = res.param('code', '');
module.exports.resetPasswordPage = (req, res, next) => {
let code = res.query.code || '';
service.getLeftBannerAsync()
.then(result => {
res.render('back/email-reset-pwd', Object.assign({
module: 'back',
page: 'email-reset-pwd'
res.render('back/reset-pwd', Object.assign({
module: 'passport',
page: 'back-reset-pwd'
}, {
code: code
}, result))
... ... @@ -144,8 +142,8 @@ module.exports.verifyCodeByMobilePage = (req, res, next) => {
service.getVerifyCodeByMobilePageDataAsync()
.then(result => {
res.render('back/verification', Object.assign({
module: 'back',
page: 'verification',
module: 'passport',
page: 'back-verify-mobile-code',
title: '手机验证'
}, {
verification: {
... ... @@ -178,8 +176,8 @@ module.exports.resetPwdSuccessPage = (req, res, next) => {
service.getLeftBannerAsync()
.then(result => {
res.render('back/email-reset-success', Object.assign({
module: 'back',
page: 'email-reset-success',
module: 'passport',
page: 'back-reset-success',
title: '重置密码成功'
}, result))
}).catch(next);
... ... @@ -189,7 +187,7 @@ module.exports.verifyCodyByMobileAPI = (req, res, next) => {
let mobile = req.param('mobile', '');
let area = req.param('aera', '86');
let area = req.param('area', '86');
let mobileCode = req.param('code', '');
... ... @@ -208,7 +206,7 @@ module.exports.tokenCheckPage = (req, res, next) => {
req.authInfo = result;
next();
} else {
res.redirect('/passport/back/index');
res.redirect('/passport/back/index.html');
}
})
};
... ...
... ... @@ -11,7 +11,7 @@ const captcha = require('../models/captcha-service')(sessionService);
const helpers = require(library + '/helpers');
exports.checkAPI = (req, res, next) => {
let captchaToken = req.param('verifyCode', '');
let captchaToken = req.body.verifyCode || '';
captcha.findByContentAsync(captchaToken)
.then(result => {
... ... @@ -27,12 +27,12 @@ exports.checkAPI = (req, res, next) => {
};
exports.checkPage = (req, res, next) => {
let captchaToken = req.param('verifyCode', '');
let captchaToken = req.body.verifyCode || '';
captcha.findByContentAsync(captchaToken)
.then(result => {
if (_.isEmpty(result)) {
res.redirect(helpers.urlFormat('/passport/back/index.html'));
res.redirect('/passport/back/index.html');
} else {
next();
}
... ...
... ... @@ -24,7 +24,7 @@ module.exports.validateEmailOrMobileAsync = (userInput, areaCode) => {
if (helpers.verifyEmail(userInput)) {
result.type = 'email';
result.aera = '';
result.area = '';
result.phone = userInput;
resolve(result);
... ... @@ -56,6 +56,8 @@ module.exports.findUserAsync = (type, phone, area) => {
const OK = {code: 200, message: MESSAGE.ok};
return OK;
const user = yield findBy[type](phone, area);
if (_.isEmpty(user)) {
... ... @@ -93,32 +95,13 @@ function sendCodeToMobileAsync(areaCode, userInput) {
});
}
module.exports.sendCodeToUserAsync = (userInput, areaCode) => {
return co(function * () {
if (helpers.verifyEmail(userInput)) {
const result = yield sendCodeToEmailAsync(userInput);
if (!_.isEmpty(result)) {
sessionService.set('email', userInput);
return 'email;';
}
return 'unknown';
} else if (helpers.verifyAreaMobile(helpers.makeAreaMobile(areaCode, userInput))) {
const result = yield sendCodeToMobileAsync(userInput, areaCode);
if (!_.isEmpty(result)) {
sessionService.set('mobile', userInput);
sessionService.set('area', areaCode);
return 'mobile';
}
return 'unknown';
} else {
return 'unknown';
}
module.exports.sendCodeToUserAsync = (type, mobile, areaCode) => {
let sendTo = {
email: sendCodeToEmailAsync,
mobile: sendCodeToMobileAsync
};
})();
return sendTo[type](mobile, areaCode);
};
/**
... ... @@ -164,14 +147,16 @@ module.exports.getVerifyCodeByMobilePageDataAsync = () => {
};
module.exports.getSendEmailPageDataAsync = () => {
return {
sendEmail: {
coverHref: '',
coverImg: '',
counttrys: '',
email: ''
}
};
return co(function * () {
return {
sendEmail: {
coverHref: '',
coverImg: '',
counttrys: '',
email: ''
}
};
})();
};
module.exports.verifyCodyByMobileAsync = (area, mobile, mobileCode) => {
... ...
... ... @@ -3,10 +3,15 @@
*/
'use strict';
const Promise = require('bluebird');
const co = Promise.coroutine;
module.exports.findCaptchaByTokenAsync = (token) => {
if (token) {
return {token: token};
} else {
return {};
}
return co(function *() {
if (token) {
return {token: token};
} else {
return {};
}
})();
};
... ...
... ... @@ -10,34 +10,54 @@ const express = require('express');
const cRoot = './controllers';
const login = require(cRoot + '/login');
const captcha = require(cRoot + '/captcha');
const back = require(cRoot + '/back');
const Captcha = require(cRoot + '/captcha');
const Back = require(cRoot + '/back');
const router = express.Router(); // eslint-disable-line
router.get('/login/wechat', login.wechat.beforeLogin, login.wechat.login); // 登录
router.get('/login/wechat/callback', login.wechat.callback);
/**
* 找回密码首页信息
*/
// 找回密码首页
router.get('/back/index.html', back.indexPage);
router.get('/back/index.html', Back.indexPage);
// 实时验证输入是否正确
router.post('/back/authcode', captcha.checkAPI, back.validateUserInputAPI, back.getUserInfoAPI);
router.post('/back/email', captcha.checkPage, back.sendCodeAPI);
router.post('/back/authcode', Captcha.checkAPI, Back.validateUserInputAPI, Back.getUserInfoAPI);
// 提交按钮确定
router.post('/back/mobile', Captcha.checkPage, Back.validateUserInputAPI, Back.sendCodeAPI);
// 邮件重置密码
router.get('/back/backcode.html', back.tokenCheckPage, back.checkEmailCodePage, back.resetPasswordByEmailPage);
/**
* 邮件找回密码
*/
// 发送邮件成功页面
router.get('/back/sendEmail.html', Back.sendEmailPage);
// 邮件重置密码成功页面
router.get('/back/resetSuccess.html', back.checkSuccessStatusPage, back.resetPwdSuccessPage);
/**
* 短信找回密码
*/
// 验证手机短信页面
router.get('/back/verification.html', Back.verifyCodeByMobilePage);
// 重新发送短信接口
router.post('/back/sendBackMobile', Captcha.checkAPI, Back.sendBackMobileAPI);
// 验证手机验证码接口
router.post('/back/backMobile', Captcha.checkAPI, Back.verifyCodyByMobileAPI);
/**
* 重置密码
*/
// 重置密码页面
router.get('/back/backcode', Back.tokenCheckPage, Back.checkCodePage, Back.resetPasswordPage);
// 重新发送短信
router.post('/back/sendBackMobile', captcha.checkAPI, back.sendBackMobileAPI);
router.get('/back/verification.html', back.verifyCodeByMobilePage);
router.post('/back/backMobile', captcha.checkAPI, back.verifyCodyByMobileAPI);
// 重置密码接口
router.post('/back/update', Back.tokenCheckPage, Back.validationPwdPage, Back.updatePwdPage);
// 手机更新密码页面
router.post('/back/update', back.tokenCheckPage, back.validationPwdPage, back.updatePwdPage);
// 重置密码成功页面
router.get('/back/resetSuccess.html', Back.checkSuccessStatusPage, Back.resetPwdSuccessPage);
module.exports = router;
... ...
<div class="reset-pwd-page back-page passport-page yoho-page clearfix">
{{# resetPwd}}
{{> back/cover}}
<div class="content">
<h2 class="title2">重置密码</h2>
<form id="reset-pwd-form" class="reset-pwd-form" method="POST" action="/passport/back/update">
<ul>
<li class="input-container-li po-re">
<input id="pwd" class="input va pwd" type="password" name="pwd" placeholder="新密码" maxlength="20">
<div class="pwd-intensity-container">
<span class="pwd-intensity low"></span>
<span class="pwd-intensity mid"></span>
<span class="pwd-intensity high"></span>
</div>
<div id="pwd-tips" class="pwd-tips hide">
<div class="default" id="pwd-tip1">
<i></i>
密码只支持6-20位字符
</div>
<div class="default" id="pwd-tip2">
<i></i>
由字母、 数字组合,不能包含特殊符号
</div>
</div>
<span id="pwd-err" class="err-tip hide">
<i></i>
<em>请输入密码</em>
</span>
</li>
<li class="input-container-li clearfix po-re">
<input id="re-input" class="input va re-input repwd" type="password" name="re-input" placeholder="再次输入" maxlength="20">
<span id="repwd-err" class="err-tip hide">
<i></i>
<em>请输入密码确认</em>
</span>
</li>
<li class="input-container-li clearfix">
<input type="hidden" name="code" value="{{code}}">
<input id="reset-pwd-btn" class="btn reset-pwd-btn" type="submit" value="提交" disabled="">
</li>
</ul>
</form>
</div>
{{/ resetPwd}}
</div>
... ...
<div class="reset-success-page back-page passport-page yoho-page clearfix">
{{# resetSuccess}}
{{> passport/cover}}
<div class="content">
<div class="success-text">
<i class="iconfont">&#xe620;</i><span>恭喜!</span>密码修改成功,&nbsp;<span id="count-down">5</span>&nbsp;&nbsp;秒后将跳转至首页
</div>
<a class="success-btn" href="/">随便逛逛</a>
</div>
{{/ resetSuccess}}
</div>
{{> layout/footer}}
<script type="text/javascript">
(function() {
var count = 5,
countDown = document.getElementById('count-down');
var timer = setInterval(function(){
if (count > 1) {
count--;
countDown.innerHTML = count;
} else {
location.href = '/';
}
}, 1000);
})();
</script>
... ...
<div class="send-email-page passport-page yoho-page clearfix">
{{# sendEmail}}
{{> back/cover}}
<div class="content">
<div class="send-tips"><i class="iconfont">&#xe61e;</i>我们已经把验证邮件发送至您的邮箱,请在24小时内通过邮件内的<br>链接继续设置新的密码。</div>
<div class="no-find">没有收到?到您邮箱的垃圾邮件里找找。</div>
<div class="to-my-email">
<a href="{{email}}" target="_blank" class="btn_b_ar_r">去我的邮箱&gt;</a>
</div>
</div>
{{/ sendEmail}}
</div>
... ...
/**
* Created by TaoHuang on 2016/6/21.
*/
require('./back');
/**
* Created by TaoHuang on 2016/6/21.
*/
require('./back/back');
require('./')
... ...
/**
* Created by TaoHuang on 2016/6/21.
*/
... ...
/**
* Created by TaoHuang on 2016/6/21.
*/
... ...
/**
* Created by TaoHuang on 2016/6/21.
*/
... ...
/**
* Created by TaoHuang on 2016/6/21.
*/
require('./back/verification');
... ...
/**
* 邮箱自动补全
* @author:xuqi<qi.xu@yoho.cn>
* @date: 2016/2/22
*/
var $ = require('yoho-jquery');
var mailPostfix = {
num: ['qq.com', '163.com', '126.com', 'sina.com', 'gmail.com', 'sohu.com', 'hotmail.com', '139.com', '189.com'],
other: ['gmail.com', 'qq.com', '163.com', '126.com', 'sina.com', 'sohu.com', 'hotmail.com', '139.com', '189.com']
};
var emailAcTime;
/**
* @param $input 需要自动完成的$对象
* @param cb 鼠标移开/点击自动完成项后需要执行的操作(验证等)
*/
module.exports = function($input, cb) {
var ulHtml = '<ul id="email-autocomplete" class="email-autocomplete hide"></ul>';
var $emailAutoComplete;
$input.parent().append(ulHtml);
$emailAutoComplete = $('#email-autocomplete');
$input.on('keyup', function() {
var account = $.trim($(this).val()),
html = '',
accountMatch,
matchStr,
postfix,
i;
//输入@时自动补全邮箱后缀
//此处>0非错误,用于避免输入的第一个字符为@被识别为邮箱
if (account.indexOf('@') > 0) {
accountMatch = account.match(/^[0-9]+@(.*)/);
if (accountMatch) {
//数字邮箱补全
postfix = mailPostfix.num;
matchStr = accountMatch[1];
} else {
postfix = mailPostfix.other;
matchStr = account.match(/@(.*)/)[1];
}
for (i = 0; i < postfix.length; i++) {
if (postfix[i].indexOf(matchStr) > -1) {
html += '<li>' + account.slice(0, account.indexOf('@')) + '@' + postfix[i] + '</li>';
}
}
if (html !== '' && /.com$/.test(account) === false) {
$emailAutoComplete.html(html).removeClass('hide');
} else {
//隐藏autocomplete
$emailAutoComplete.html('').addClass('hide');
}
}
}).on('blur', function() {
emailAcTime = setTimeout(function() {
//未点击自动完成项
$emailAutoComplete.addClass('hide');
cb && cb();
}, 200);
});
//邮箱自动完成列表项点击
$emailAutoComplete.on('click', 'li', function() {
clearTimeout(emailAcTime); //清空默认关闭
//点击自动完成项后进行验证
$input.val($(this).text()).focus();
$emailAutoComplete.addClass('hide');
cb && cb();
});
};
/**
* 邮箱自动补全
* @author:xuqi<qi.xu@yoho.cn>
* @date: 2016/2/22
*/
var $ = require('yoho-jquery');
var mailPostfix = {
num: ['qq.com', '163.com', '126.com', 'sina.com', 'gmail.com', 'sohu.com', 'hotmail.com', '139.com', '189.com'],
other: ['gmail.com', 'qq.com', '163.com', '126.com', 'sina.com', 'sohu.com', 'hotmail.com', '139.com', '189.com']
};
var emailAcTime;
/**
* @param $input 需要自动完成的$对象
* @param cb 鼠标移开/点击自动完成项后需要执行的操作(验证等)
*/
module.exports = function($input, cb) {
var ulHtml = '<ul id="email-autocomplete" class="email-autocomplete hide"></ul>';
var $emailAutoComplete;
$input.parent().append(ulHtml);
$emailAutoComplete = $('#email-autocomplete');
$input.on('keyup', function() {
var account = $.trim($(this).val()),
html = '',
accountMatch,
matchStr,
postfix,
i;
//输入@时自动补全邮箱后缀
//此处>0非错误,用于避免输入的第一个字符为@被识别为邮箱
if (account.indexOf('@') > 0) {
accountMatch = account.match(/^[0-9]+@(.*)/);
if (accountMatch) {
//数字邮箱补全
postfix = mailPostfix.num;
matchStr = accountMatch[1];
} else {
postfix = mailPostfix.other;
matchStr = account.match(/@(.*)/)[1];
}
for (i = 0; i < postfix.length; i++) {
if (postfix[i].indexOf(matchStr) > -1) {
html += '<li>' + account.slice(0, account.indexOf('@')) + '@' + postfix[i] + '</li>';
}
}
if (html !== '' && /.com$/.test(account) === false) {
$emailAutoComplete.html(html).removeClass('hide');
} else {
//隐藏autocomplete
$emailAutoComplete.html('').addClass('hide');
}
}
}).on('blur', function() {
emailAcTime = setTimeout(function() {
//未点击自动完成项
$emailAutoComplete.addClass('hide');
cb && cb();
}, 200);
});
//邮箱自动完成列表项点击
$emailAutoComplete.on('click', 'li', function() {
clearTimeout(emailAcTime); //清空默认关闭
//点击自动完成项后进行验证
$input.val($(this).text()).focus();
$emailAutoComplete.addClass('hide');
cb && cb();
});
};
... ...
/**
* 找回密码
* @author: xuqi<qi.xu@yoho.cn>
* @date: 2015/12/14
*/
var $ = require('yoho-jquery'),
regx = require('./mail-phone-regx'),
emailReg = regx.emailRegx,
phoneRegx = regx.phoneRegx;
var emailAc = require('./ac-email'); //邮箱自动完成
var $cr = $('#country-code-hide'),
$phoneNum = $('#phone-num'),
$ca = $('#captcha'),
$ccList = $('#country-code-list'),
$cc = $('#country-code'),
$btn = $('#find-btn'),
$accErr = $('#account-err'),
$caErr = $('#captcha-err'),
caCount = 4, //验证码位数
hasPh = false,
hasCa = false;
require('yoho-jquery-placeholder');
function imgcode() {
var time = new Date(),
$captchaImg = $('#captcha-img'),
captchaImgSrc = $captchaImg.attr('src').split('?')[0];
$('#captcha-img').attr('src', captchaImgSrc + '?t=' + time.getTime());
}
function enableBtn() {
if (hasPh && hasCa) {
$btn.removeClass('disable').prop('disabled', false);
} else {
$btn.addClass('disable').prop('disabled', true);
}
}
function authcode() {
if (!hasPh || !hasCa) {
enableBtn();
return;
}
$.ajax({
type: 'POST',
url: '/passport/back/authcode',
data: {
verifyCode: $.trim($ca.val()),
phoneNum: $phoneNum.val(),
area: $cr.val()
}
}).then(function(data) {
if (data.code === 200) {
hasCa = true;
} else if (data.code === 402) {
hasPh = false;
hasCa = true;
$accErr.removeClass('hide').find('em').text('该账号不存在');
$phoneNum.addClass('error');
} else if (data.code === 400) {
hasCa = false;
imgcode();
}
enableBtn();
});
}
function vaPn(v) {
var pass = true,
errTxt = '';
v = $.trim(v);
if (v !== '') {
if (/^[0-9]+$/.test(v)) {
if (phoneRegx[$cr.val()].test(v)) {
pass = true;
} else {
errTxt = '手机号码格式不正确, 请重新输入';
pass = false;
}
} else {
if (emailReg.test(v)) {
pass = true;
} else {
errTxt = '邮箱格式不正确, 请重新输入';
pass = false;
}
}
} else {
errTxt = '账户名不能为空';
pass = false;
}
hasPh = pass;
authcode();
return {
pass: pass,
errTxt: errTxt
};
}
function vaCa() {
var v = $.trim($ca.val());
if (v === '' || v.length < caCount) {
hasCa = false;
enableBtn();
return;
}
hasCa = true;
authcode();
}
emailAc($phoneNum, function() {
var pnVa = vaPn($phoneNum.val());
if (pnVa.pass) {
$accErr.addClass('hide');
$phoneNum.removeClass('error');
} else {
$accErr.removeClass('hide').find('em').text(pnVa.errTxt);
$phoneNum.addClass('error');
}
}
);
$ca.attr('maxlength', caCount);
//IE8 placeholder
$('input').placeholder();
$('#change-captcha, #captcha-img').on('click', function() {
imgcode();
});
$cc.on('click', function(e) {
e.stopPropagation();
if ($ccList.css('style') === 'block') {
$ccList.slideUp('fast');
} else {
$ccList.slideDown('fast');
}
});
$ccList.delegate('li', 'click', function(e) {
var $cur = $(this),
code = $cur.data('cc'),
pnVa;
e.stopPropagation();
$cr.val(code);
$cc.find('em').html($cur.text());
//切换后验证手机号码
if ($.trim($phoneNum.val()) !== '') {
pnVa = vaPn($phoneNum.val());
enableBtn();
if (hasPh) {
$accErr.addClass('hide');
$phoneNum.removeClass('error');
} else {
$accErr.removeClass('hide').text(pnVa.errTxt);
$phoneNum.addClass('error');
}
}
$ccList.slideUp('fast');
});
$(document).click(function() {
if ($ccList.css('display') === 'block') {
$ccList.slideUp();
}
});
$phoneNum.keyup(function() {
vaPn($.trim($(this).val()));
}).focus(function() {
$(this).removeClass('error');
//focus隐藏错误提示
$accErr.addClass('hide');
});
//验证码在鼠标移开后验证, keyup时不再验证
$ca.blur(function() {
var errTxt = $.trim($ca.val()) === '' ? '验证码不能为空' : '验证码不正确';
if (hasCa) {
$caErr.addClass('hide');
$ca.removeClass('error');
} else {
$caErr.removeClass('hide').find('em').text(errTxt);
$ca.addClass('error');
//验证码错误则刷新验证码
if ($ca.val() < caCount) {
//防止重复刷新验证码
imgcode();
}
}
}).focus(function() {
$(this).removeClass('error');
//focus隐藏错误提示
$caErr.addClass('hide');
}).keyup(function() {
vaCa();
});
$('#find-btn').click(function(e) {
if (/^[0-9]+$/.test($.trim($phoneNum.val()))) {
$('#find-form').attr('action', '/passport/back/mobile');
}
if ($(this).hasClass('disable')) {
return;
}
if (!hasCa || !hasPh) {
e.preventDefault();
return true;
}
});
/**
* 找回密码
* @author: xuqi<qi.xu@yoho.cn>
* @date: 2015/12/14
*/
var $ = require('yoho-jquery'),
regx = require('./mail-phone-regx'),
emailReg = regx.emailRegx,
phoneRegx = regx.phoneRegx;
var emailAc = require('./ac-email'); //邮箱自动完成
var $cr = $('#country-code-hide'),
$phoneNum = $('#phone-num'),
$ca = $('#captcha'),
$ccList = $('#country-code-list'),
$cc = $('#country-code'),
$btn = $('#find-btn'),
$accErr = $('#account-err'),
$caErr = $('#captcha-err'),
caCount = 4, //验证码位数
hasPh = false,
hasCa = false;
require('yoho-jquery-placeholder');
function imgcode() {
var time = new Date(),
$captchaImg = $('#captcha-img'),
captchaImgSrc = $captchaImg.attr('src').split('?')[0];
$('#captcha-img').attr('src', captchaImgSrc + '?t=' + time.getTime());
}
function enableBtn() {
if (hasPh && hasCa) {
$btn.removeClass('disable').prop('disabled', false);
} else {
$btn.addClass('disable').prop('disabled', true);
}
}
function authcode() {
if (!hasPh || !hasCa) {
enableBtn();
return;
}
$.ajax({
type: 'POST',
url: '/passport/back/authcode',
data: {
verifyCode: $.trim($ca.val()),
phoneNum: $phoneNum.val(),
area: $cr.val()
}
}).then(function(data) {
if (data.code === 200) {
hasCa = true;
} else if (data.code === 402) {
hasPh = false;
hasCa = true;
$accErr.removeClass('hide').find('em').text('该账号不存在');
$phoneNum.addClass('error');
} else if (data.code === 400) {
hasCa = false;
imgcode();
}
enableBtn();
});
}
function vaPn(v) {
var pass = true,
errTxt = '';
v = $.trim(v);
if (v !== '') {
if (/^[0-9]+$/.test(v)) {
if (phoneRegx[$cr.val()].test(v)) {
pass = true;
} else {
errTxt = '手机号码格式不正确, 请重新输入';
pass = false;
}
} else {
if (emailReg.test(v)) {
pass = true;
} else {
errTxt = '邮箱格式不正确, 请重新输入';
pass = false;
}
}
} else {
errTxt = '账户名不能为空';
pass = false;
}
hasPh = pass;
authcode();
return {
pass: pass,
errTxt: errTxt
};
}
function vaCa() {
var v = $.trim($ca.val());
if (v === '' || v.length < caCount) {
hasCa = false;
enableBtn();
return;
}
hasCa = true;
authcode();
}
emailAc($phoneNum, function() {
var pnVa = vaPn($phoneNum.val());
if (pnVa.pass) {
$accErr.addClass('hide');
$phoneNum.removeClass('error');
} else {
$accErr.removeClass('hide').find('em').text(pnVa.errTxt);
$phoneNum.addClass('error');
}
}
);
$ca.attr('maxlength', caCount);
//IE8 placeholder
$('input').placeholder();
$('#change-captcha, #captcha-img').on('click', function() {
imgcode();
});
$cc.on('click', function(e) {
e.stopPropagation();
if ($ccList.css('style') === 'block') {
$ccList.slideUp('fast');
} else {
$ccList.slideDown('fast');
}
});
$ccList.delegate('li', 'click', function(e) {
var $cur = $(this),
code = $cur.data('cc'),
pnVa;
e.stopPropagation();
$cr.val(code);
$cc.find('em').html($cur.text());
//切换后验证手机号码
if ($.trim($phoneNum.val()) !== '') {
pnVa = vaPn($phoneNum.val());
enableBtn();
if (hasPh) {
$accErr.addClass('hide');
$phoneNum.removeClass('error');
} else {
$accErr.removeClass('hide').text(pnVa.errTxt);
$phoneNum.addClass('error');
}
}
$ccList.slideUp('fast');
});
$(document).click(function() {
if ($ccList.css('display') === 'block') {
$ccList.slideUp();
}
});
$phoneNum.keyup(function() {
vaPn($.trim($(this).val()));
}).focus(function() {
$(this).removeClass('error');
//focus隐藏错误提示
$accErr.addClass('hide');
});
//验证码在鼠标移开后验证, keyup时不再验证
$ca.blur(function() {
var errTxt = $.trim($ca.val()) === '' ? '验证码不能为空' : '验证码不正确';
if (hasCa) {
$caErr.addClass('hide');
$ca.removeClass('error');
} else {
$caErr.removeClass('hide').find('em').text(errTxt);
$ca.addClass('error');
//验证码错误则刷新验证码
if ($ca.val() < caCount) {
//防止重复刷新验证码
imgcode();
}
}
}).focus(function() {
$(this).removeClass('error');
//focus隐藏错误提示
$caErr.addClass('hide');
}).keyup(function() {
vaCa();
});
$('#find-btn').click(function(e) {
if (/^[0-9]+$/.test($.trim($phoneNum.val()))) {
$('#find-form').attr('action', '/passport/back/mobile');
}
if ($(this).hasClass('disable')) {
return;
}
if (!hasCa || !hasPh) {
e.preventDefault();
return true;
}
});
... ...
/**
* 国家区号Map手机号码以及邮箱验证正则
* @author: xuqi<qi.xu@yoho.cn>
* @date: 2015/12/11
*/
var countryPhoneRegx = {
'+86': /^1[35847]{1}[0-9]{9}$/,
'+852': /^[965]{1}[0-9]{7}$/,
'+853': /^[0-9]{8}$/,
'+886': /^[0-9]{10}$/,
'+65': /^[98]{1}[0-9]{7}$/,
'+60': /^1[1234679]{1}[0-9]{8}$/,
'+1': /^[0-9]{10}$/,
'+82': /^01[0-9]{9}$/,
'+44': /^7[789]{1}[0-9]{8}$/,
'+81': /^0[9|8|7][0-9]{9}$/,
'+61': /^[0-9]{11}$/
};
var emailRegx = /^[.\-_a-zA-Z0-9]+@[\-_a-zA-Z0-9]+\.[a-zA-Z0-9]/;
var pwdValidateRegx = /^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{6,20}$/;
exports.phoneRegx = countryPhoneRegx;
exports.emailRegx = emailRegx;
/**
* 国家区号Map手机号码以及邮箱验证正则
* @author: xuqi<qi.xu@yoho.cn>
* @date: 2015/12/11
*/
var countryPhoneRegx = {
'+86': /^1[35847]{1}[0-9]{9}$/,
'+852': /^[965]{1}[0-9]{7}$/,
'+853': /^[0-9]{8}$/,
'+886': /^[0-9]{10}$/,
'+65': /^[98]{1}[0-9]{7}$/,
'+60': /^1[1234679]{1}[0-9]{8}$/,
'+1': /^[0-9]{10}$/,
'+82': /^01[0-9]{9}$/,
'+44': /^7[789]{1}[0-9]{8}$/,
'+81': /^0[9|8|7][0-9]{9}$/,
'+61': /^[0-9]{11}$/
};
var emailRegx = /^[.\-_a-zA-Z0-9]+@[\-_a-zA-Z0-9]+\.[a-zA-Z0-9]/;
var pwdValidateRegx = /^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{6,20}$/;
exports.phoneRegx = countryPhoneRegx;
exports.emailRegx = emailRegx;
exports.pwdValidateRegx = pwdValidateRegx;
\ No newline at end of file
... ...
/*
* 计算密码复杂度
*/
function gettype(str, i) {
if (str.charCodeAt(i) >= 48 && str.charCodeAt(i) <= 57) {
return 1;
} else if (str.charCodeAt(i) >= 97 && str.charCodeAt(i) <= 122) {
return 2;
} else if (str.charCodeAt(i) >= 65 && str.charCodeAt(i) <= 90) {
return 3;
}
return 4;
}
function isregular(cur, pre, type) {
var curCode = cur.charCodeAt(0);
var preCode = pre.charCodeAt(0);
if (curCode - preCode === 0) {
return true;
}
if (type !== 4 && (curCode - preCode === 1 || curCode - preCode === -1)) {
return true;
}
return false;
}
function getcomplex(curType, preType) {
if (preType === 0 || curType === preType) {
return 0;
} else if (curType === 4 || preType === 4) {
return 2;
} else {
return 1;
}
}
function computeComplex(password) {
var complex = 0,
length = password.length,
pre = '',
preType = 0,
i = 0,
cur,
curType;
for (i = 0; i < length; i++) {
cur = password.charAt(i);
curType = gettype(password, i);
if (preType !== curType || !isregular(cur, pre, curType)) {
complex += curType + getcomplex(curType, preType);
}
pre = cur;
preType = curType;
}
return complex;
}
module.exports = computeComplex;
\ No newline at end of file
... ...
/**
* 找回密码
* @author: xuqi<qi.xu@yoho.cn>
* @date: 2015/12/14
*/
var $ = require('yoho-jquery');
var $pwd = $('#pwd'),
$repwd = $('#re-input'),
$next = $('#reset-pwd-btn'),
$pwdErr = $('#pwd-err'),
$repwdErr = $('#repwd-err'),
$pwdTips = $('#pwd-tips');
var hasNoErrPw = false;
var $pwdIntensity = $('.pwd-intensity'),
$pwdParent = $pwdIntensity.closest('.pwd-intensity-container'),
$pwdTip1 = $('#pwd-tip1');
var pwdRegx = require('./mail-phone-regx').pwdValidateRegx;
require('yoho-jquery-placeholder');
/*
* 计算密码复杂度
*/
function gettype(str, i) {
if (str.charCodeAt(i) >= 48 && str.charCodeAt(i) <= 57) {
return 1;
} else if (str.charCodeAt(i) >= 97 && str.charCodeAt(i) <= 122) {
return 2;
} else if (str.charCodeAt(i) >= 65 && str.charCodeAt(i) <= 90) {
return 3;
}
return 4;
}
function isregular(cur, pre, type) {
var curCode = cur.charCodeAt(0);
var preCode = pre.charCodeAt(0);
if (curCode - preCode === 0) {
return true;
}
if (type !== 4 && (curCode - preCode === 1 || curCode - preCode === -1)) {
return true;
}
return false;
}
function getcomplex(curType, preType) {
if (preType === 0 || curType === preType) {
return 0;
} else if (curType === 4 || preType === 4) {
return 2;
} else {
return 1;
}
}
function computeComplex(password) {
var complex = 0,
length = password.length,
pre = '',
preType = 0,
i = 0,
cur,
curType;
for (i = 0; i < length; i++) {
cur = password.charAt(i);
curType = gettype(password, i);
if (preType !== curType || !isregular(cur, pre, curType)) {
complex += curType + getcomplex(curType, preType);
}
pre = cur;
preType = curType;
}
return complex;
}
function pwdKeyupEvt() {
var pwd = $pwd.val(),
pwdStrength = computeComplex(pwd),
level = 0;
//TODO:自定义密码强度规则,需要修正
if (pwdStrength === 0) {
level = 0;
} else if (pwdStrength <= 10) {
level = 1;
} else if (pwdStrength <= 20) {
level = 2;
} else {
level = 3;
}
switch (level) {
case 0:
$pwdParent.removeClass('red yellow green');
$pwdIntensity.removeClass('color');
break;
case 1:
$pwdParent.addClass('red').removeClass('yellow green');
$pwdIntensity.filter('.low').addClass('color');
$pwdIntensity.filter('.mid,.high').removeClass('color');
break;
case 2:
$pwdParent.addClass('yellow').removeClass('red green');
$pwdIntensity.filter('.low,.mid').addClass('color');
$pwdIntensity.filter('.high').removeClass('color');
break;
case 3:
$pwdParent.addClass('green').removeClass('yellow red');
$pwdIntensity.addClass('color');
break;
}
//提示框
if (pwd === '') {
$pwdTip1.removeClass('red yes no').addClass('default');
} else if (pwd.length < 6 || pwd.length > 20) {
$pwdTip1.removeClass('default yes').addClass('no red');
} else {
$pwdTip1.removeClass('default no red').addClass('yes');
}
if (pwdRegx.test(pwd)) {
hasNoErrPw = true;
} else {
hasNoErrPw = false;
}
}
//IE8 placeholder
$('input').placeholder();
$('.va').keyup(function() {
var pass = true;
if ($(this).hasClass('pwd')) {
pwdKeyupEvt();
} else {
if ($(this).val() === '') {
pass = false;
}
}
if (pass && hasNoErrPw && $pwd.val() === $repwd.val()) {
pass = true;
} else {
pass = false;
}
if (pass) {
$next.removeClass('disable').prop('disabled', false);
} else {
$next.addClass('disable').prop('disabled', true);
}
}).blur(function() {
var $this = $(this),
v = $this.val();
if ($this.hasClass('pwd')) {
if (v === '') {
$this.addClass('error');
$pwdErr.removeClass('hide').find('em').text('请输入密码');
} else if (v.length < 6 || v.length > 20) {
$this.addClass('error');
$pwdErr.removeClass('hide').find('em').text('密码只支持6-20位');
} else if (!pwdRegx.test(v)) {
$this.addClass('error');
$pwdErr.removeClass('hide').find('em').text('密码须字母和数字组合');
} else {
$pwdErr.addClass('hide');
if ($repwd.val() !== '') {
if (v !== $repwd.val()) {
$repwd.addClass('error');
$repwdErr.removeClass('hide').find('em').text('两次密码输入不一致,请重新输入');
} else {
$repwd.removeClass('error');
$repwdErr.addClass('hide');
}
}
}
} else {
if (v === '') {
$this.addClass('error');
$repwdErr.removeClass('hide').find('em').text('请输入密码确认');
} else {
if ($pwd.val() !== '' && v !== $pwd.val()) {
$this.addClass('error');
$repwdErr.removeClass('hide').find('em').text('两次密码输入不一致,请重新输入');
} else {
$this.removeClass('error');
$repwdErr.addClass('hide');
}
}
}
}).focus(function() {
$(this).removeClass('error');
//focus后错误提示隐藏
if ($(this).hasClass('pwd')) {
$pwdErr.addClass('hide');
} else {
$repwdErr.addClass('hide');
}
});
$pwd.focus(function() {
$pwdErr.addClass('hide');
$pwdTips.removeClass('hide');
}).blur(function() {
$pwdTips.addClass('hide');
});
$('#pwd, #repwd').keydown(function(e) {
var code = e.keyCode || e.which;
//空格输入过滤
if (code === 32) {
e.preventDefault();
return;
}
});
... ...
/**
* 验证手机
* @author: xuqi<qi.xu@yoho.cn>
* @date: 2015/12/14
*/
var $ = require('yoho-jquery');
var $sc = $('#send-captcha'),
$msgTip = $('#captcha-tip'),
$errTip = $('#err-tip'),
$next = $('#next-step'),
seconds,
itime;
$sc.click(function() {
$.post('/passport/back/sendbackmobile', {
mobile: $('#mobile').val(),
area: $('#area').val(),
verifyCode: $('#captchaPic').val()
}, function(jsonData) {
if (jsonData.code === 200) {
$errTip.hide();
if ($(this).hasClass('disable')) {
return;
}
seconds = 60;
//$sc.addClass('disable').prop('disabled', true);
$sc.addClass('disable').attr('disabled', true);
$msgTip.removeClass('hide');
$sc.val(seconds-- + '秒后可重新操作');
itime = setInterval(function() {
if (seconds === 0) {
clearInterval(itime);
//$sc.val('发送验证码').removeClass('disable').prop('disabled', false);
$sc.val('发送验证码').removeClass('disable').removeAttr('disabled');
} else {
$sc.val(seconds-- + '秒后可重新操作');
}
}, 1000);
} else {
$(this).addClass('error');
$errTip.removeClass('hide').text('发送失败');
}
});
});
seconds = 60;
//$sc.addClass('disable').prop('disabled', true);
$sc.addClass('disable').attr('disabled', true);
$msgTip.removeClass('hide');
$sc.val(seconds-- + '秒后可重新操作');
itime = setInterval(function() {
if (seconds === 0) {
clearInterval(itime);
//$sc.val('发送验证码').removeClass('disable').prop('disabled', false);
$sc.val('发送验证码').removeClass('disable').removeAttr('disabled');
} else {
$sc.val(seconds-- + '秒后可重新操作');
}
}, 1000);
$('#captcha').keyup(function() {
var v = $.trim($(this).val()),
that = this;
if (v.length === 4) {
$.ajax({
type: 'POST',
url: '/passport/back/backmobile',
dataType: 'json',
data: {
code: $('#captcha').val(),
verifyCode: $('#captchaPic').val(),
area: $('#area').val(),
mobile: $('#mobile').val()
},
success: function(res) {
if (res.code === 200) {
//添加验证码正确验证
$next.removeClass('disable').attr('href', res.data);
$errTip.addClass('hide');
$(that).removeClass('error');
} else {
$next.addClass('disable');
$errTip.removeClass('hide').find('em').text('验证码输入错误');
$(that).addClass('error');
}
}
});
} else {
$next.addClass('disable').attr('href', 'javascript:;');
}
}).blur(function() {
var v = $.trim($(this).val());
if (v === '') {
//添加验证码正确验证
$(this).addClass('error');
$errTip.removeClass('hide').text('请输入验证码');
}
}).focus(function() {
$(this).removeClass('error');
});
... ...