Authored by 刘传洋

Merge branch 'feature/shoppingCart' of http://git.yoho.cn/fe/yohobuy-node into feature/shoppingCart

... ... @@ -7,7 +7,6 @@
const captchaService = require('../models/captcha-service');
const helpers = global.yoho.helpers;
// 中间件
const requiredAPI = (req, res, next) => {
let captchaToken = req.body.verifyCode || '';
... ... @@ -21,7 +20,6 @@ const requiredAPI = (req, res, next) => {
}
};
// 重定向调用
const requiredPage = (req, res, next) => {
let captchaToken = req.body.verifyCode || '';
... ... @@ -32,29 +30,20 @@ const requiredPage = (req, res, next) => {
}
};
// 生成二维码
const generate = (req, res, next) => {
captchaService.generateCaptcha().then((result) => {
req.session.captcha = result.data.text;
const generate = (req, res) => {
let width = req.query.w || 150;
let height = req.query.h || 50;
let length = +(req.query.l || 4);
let captcha = captchaService.generateCaptcha(width, height, length);
if (result.code === 200) {
return res.json({
code: result.code,
data: {
images: result.data.images
}
});
} else {
return res.json({
code: result.code,
message: result.message
});
}
req.session.captcha = captcha.text;
res.writeHead(200, {
'Content-Type': 'image/png'
});
}).catch(next);
res.end(captcha.image);
};
// ajax 异步调用
const checkAPI = (req, res) => {
let captchaToken = req.body.verifyCode || '';
... ...
... ... @@ -207,8 +207,6 @@ const cert = {
let email;
userService.profile(uid).then(info => {
console.log(JSON.stringify(info));
if (info && info.code === 200) {
email = _.get(info, 'data.email');
} else {
... ...
... ... @@ -73,7 +73,7 @@ let index = (req, res, next) => {
let area = req.query.area;
refer && res.cookie('refer', encodeURI(refer), {
domain: 'yohobuy.com'
domain: config.cookieDomain
});
regService.getRegData().then((result) => {
... ...
... ... @@ -4,30 +4,21 @@
'use strict';
const api = require('./captcha-api');
const _ = require('lodash');
const Captchapng = require('captchapng');
exports.generateCaptcha = () => {
return api.gen().then((result) => {
if (result.code === 200) {
let codeStr = result.data.degrees.map((rotate) => {
return (4 - rotate / 90 % 4) % 4;
}).join('');
exports.generateCaptcha = (width, height, length) => {
let min = Math.pow(10, (length - 1 || 1));
let max = Math.pow(10, (length - 1 || 1)) * 9;
let token = '' + _.random(min, max);
return {
code: 200,
data: {
text: codeStr,
images: `${result.data.verifiedGraphicCode}?imageView/2/w/240`
}
};
} else {
return {
code: 400,
message: '生成二维码失败,请重新刷新!',
data: {
text: 'yoho9636'
}
};
}
});
let png = new Captchapng(width, height, token);//
png.color(0, 0, 0, 0); // First color: background (red, green, blue, alpha)
png.color(80, 80, 80, 255); // Second color: paint (red, green, blue, alpha)
return {
image: new Buffer(png.getBase64(), 'base64'),
text: token
};
};
... ...
... ... @@ -24,10 +24,14 @@
<em>账户名不能为空</em>
</span>
</li>
<input name="verifyCode" id="captcha-value" type="hidden" value="">
<li id='captcha-img' class="input-container-li clearfix">
<li class="input-container-li clearfix">
<input id="captcha" class="input va captcha" type="text" name="verifyCode" placeholder="验证码" autocomplete="off" maxlength="4">
<img id="captcha-img" class="captcha-img" src="{{captchaUrl}}" alt="">
<a id="change-captcha" class="link change-captcha">换一张</a>
<span id="captcha-err" class="err-tip captcha-err hide">
<i></i>
<em>验证码不能为空</em>
</span>
</li>
<li class="input-container-li clearfix">
<input name="refer" id="refer" type="hidden" value="http%3A%2F%2Fwww.yohobuy.com%2F">
... ...
... ... @@ -77,6 +77,15 @@
</li>
<li class="clearfix sms-captcha-img-wrap sms-login hide">
<input id="sms-captcha-input" class="input va captcha" type="text" name="captcha"
placeholder="图形验证码"
autocomplete="off" maxlength="4">
<img id="sms-captcha-img" class="captcha-img" alt="">
<a class="link change-captcha">换一张</a>
<span class="err-tip hide">
<i></i>
<em></em>
</span>
</li>
<li class="relative clearfix sms-login hide">
... ...
<div class="register-page">
<ul>
<li class="clearfix">
<select id="region" class="region" name="region">
{{#each region}}
<option {{#if selected}}selected="selected"{{/if}} value="{{areaCode}}">{{name}}</option>
{{/each}}
</select>
</li>
<li class="clearfix" data-index="0">
<span id="country-code" class="country-code">{{location}}</span>
<input value="{{#if defaultMobile}}{{defaultMobile}}{{/if}}" id="phone-num" class="input va phone-num"
type="text" name="phoneNum" placeholder="请输入手机号码" autocomplete="off">
</li>
<li id="captcha-img" class="w330 clearfix" data-index="1">
</li>
<li class="clearfix" data-index="2">
<input id="msg-captcha" class="input va msg-captcha" type="text" name="msgCaptcha" placeholder="短信验证码"
autocomplete="off" maxlength="4">
<input id="send-captcha" class="btn send-captcha" type="button" value="获取短信验证码">
<span id="msg-tip" class="hide msg-tip">短信验证码已发送至您的手机,请查收</span>
</li>
<li class="clearfix" data-index="3">
<input id="pwd" class="input va pwd" name="pwd" placeholder="设置密码" autocomplete="off" maxlength="20"
type="password">
<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="hide pwd-tips">
<div class="default" id="pwd-tip1"><i></i>密码只支持6-20位字符</div>
<div class="default" id="pwd-tip2"><i></i>由字母、 数字组合,不能包含特殊符号</div>
</div>
</li>
<li class="items-container clearfix">
<input id="agree-terms" class="agree-terms" type="checkbox" checked="">
<span>
我已阅读并同意遵守
<a class="link go-yoho-items" href="{{itemUrl}}" target="_blank">YOHO!BUY 有货服务条款</a>
</span>
</li>
<li class="clearfix">
<input name="refer" id="refer" type="hidden" value="{{referUrl}}">
<input id="register-btn" class="btn register-btn disable" type="submit" value="{{regBtnText}}" disabled="">
</li>
{{# loginUrl}}
<li class="quick-login-container">
我已注册YOHO!BUY 有货账号
<a class="link go-login" href="{{.}}">快速登录</a>
</li>
{{/loginUrl}}
{{# skipUrl}}
<li class="skip-user-info">
<a href="{{.}}">跳过此步</a>
</li>
{{/skipUrl}}
</ul>
<div id="err-tip" class="err-tip hide">
<span></span>
<b></b>
</div>
<input name="" type="hidden" id="open-id" value="{{openId}}"/>
<input name="" type="hidden" id="source-type" value="{{sourceType}}"/>
</div>
<div class="register-page">
<ul>
<li class="clearfix">
<select id="region" class="region" name="region">
{{#each region}}
<option {{#if selected}}selected="selected"{{/if}} value="{{areaCode}}">{{name}}</option>
{{/each}}
</select>
</li>
<li class="clearfix" data-index="0">
<span id="country-code" class="country-code">{{location}}</span>
<input value="{{#if defaultMobile}}{{defaultMobile}}{{/if}}" id="phone-num" class="input va phone-num"
type="text" name="phoneNum" placeholder="请输入手机号码" autocomplete="off">
</li>
<li class="w330 clearfix" data-index="1">
<input id="captcha" class="input va captcha" type="text" name="captcha" placeholder="图形验证码"
autocomplete="off" maxlength="4">
<img id="captcha-img" class="captcha-img" src="{{captchaUrl}}" alt="">
<a class="link change-captcha">换一张</a>
</li>
<li class="clearfix" data-index="2">
<input id="msg-captcha" class="input va msg-captcha" type="text" name="msgCaptcha" placeholder="短信验证码"
autocomplete="off" maxlength="4">
<input id="send-captcha" class="btn send-captcha disable" type="button" value="获取短信验证码">
<span id="msg-tip" class="hide msg-tip">短信验证码已发送至您的手机,请查收</span>
</li>
<li class="clearfix" data-index="3">
<input id="pwd" class="input va pwd" name="pwd" placeholder="设置密码" autocomplete="off" maxlength="20"
type="password">
<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="hide pwd-tips">
<div class="default" id="pwd-tip1"><i></i>密码只支持6-20位字符</div>
<div class="default" id="pwd-tip2"><i></i>由字母、 数字组合,不能包含特殊符号</div>
</div>
</li>
<li class="items-container clearfix">
<input id="agree-terms" class="agree-terms" type="checkbox" checked="">
<span>
我已阅读并同意遵守
<a class="link go-yoho-items" href="{{itemUrl}}" target="_blank">YOHO!BUY 有货服务条款</a>
</span>
</li>
<li class="clearfix">
<input name="refer" id="refer" type="hidden" value="{{referUrl}}">
<input id="register-btn" class="btn register-btn disable" type="submit" value="{{regBtnText}}" disabled="">
</li>
{{# loginUrl}}
<li class="quick-login-container">
我已注册YOHO!BUY 有货账号
<a class="link go-login" href="{{.}}">快速登录</a>
</li>
{{/loginUrl}}
{{# skipUrl}}
<li class="skip-user-info">
<a href="{{.}}">跳过此步</a>
</li>
{{/skipUrl}}
</ul>
<div id="err-tip" class="err-tip hide">
<span></span>
<b></b>
</div>
<input name="" type="hidden" id="open-id" value="{{openId}}"/>
<input name="" type="hidden" id="source-type" value="{{sourceType}}"/>
</div>
... ...
... ... @@ -15,7 +15,9 @@
<p class="star-text">非常满意</p>
</div>
<div class="detail-reason">
<div class="discontent"></div>
<div class="dis-wrap">
<div class="discontent"></div>
</div>
<textarea class="other-reason" maxlength="50" placeholder="请您输入不满意的其他原因" spellcheck="false"></textarea>
</div>
</div>
... ...
{
"name": "yohobuy-node",
"version": "5.3.0",
"version": "5.3.2",
"private": true,
"description": "A New Yohobuy Project With Express",
"repository": {
... ...
... ... @@ -8,8 +8,6 @@ var $ = require('yoho-jquery');
var regx = require('../common/mail-phone-regx');
var Captcha = require('../../plugins/captcha');
var emailAc = require('../common/ac-email'); // 邮箱自动完成
var emailReg = regx.emailRegx,
... ... @@ -22,15 +20,24 @@ var $cr = $('#country-code-hide'),
$cc = $('#country-code'),
$btn = $('#find-btn'),
$accErr = $('#account-err'),
$caErr = $('#captcha-err'),
caCount = 4, // 验证码位数
hasPh = false,
captcha = new Captcha('#captcha-img').init();
hasCa = false;
require('../../simple-header');
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) {
if (hasPh && hasCa) {
$btn.removeClass('disable').prop('disabled', false);
} else {
$btn.addClass('disable').prop('disabled', true);
... ... @@ -38,27 +45,33 @@ function enableBtn() {
}
function authcode() {
return $.ajax({
if (!hasPh || !hasCa) {
enableBtn();
return;
}
$.ajax({
type: 'POST',
url: '/passport/back/authcode',
data: {
verifyCode: captcha.getResults(),
verifyCode: $.trim($ca.val()),
phoneNum: $phoneNum.val(),
area: $cr.val()
}
}).then(function(data) {
if (data.code === 200) {
$('#captcha-value').val(captcha.getResults());
return $.Deferred().resolve().promise(); //eslint-disable-line
hasCa = true;
} else if (data.code === 402) {
hasPh = false;
hasCa = true;
$accErr.removeClass('hide').find('em').text('该账号不存在');
$phoneNum.addClass('error');
return $.Deferred().reject().promise();//eslint-disable-line
} else if (data.code === 400) {
captcha.showTip();
return $.Deferred().reject().promise();//eslint-disable-line
hasCa = false;
imgcode();
}
enableBtn();
});
}
... ... @@ -88,6 +101,7 @@ function vaPn(v) {
pass = false;
}
hasPh = pass;
authcode();
return {
pass: pass,
... ... @@ -95,13 +109,26 @@ function vaPn(v) {
};
}
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');
enableBtn();
} else {
$accErr.removeClass('hide').find('em').text(pnVa.errTxt);
$phoneNum.addClass('error');
... ... @@ -114,6 +141,10 @@ $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') {
... ... @@ -153,8 +184,6 @@ $(document).click(function() {
}
});
captcha.refresh();
$phoneNum.keyup(function() {
vaPn($.trim($(this).val()));
}).focus(function() {
... ... @@ -164,22 +193,43 @@ $phoneNum.keyup(function() {
$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 (hasPh) {
authcode().then(function() {
$('#back-form').submit();
});
if (!hasCa || !hasPh) {
e.preventDefault();
return true;
}
e.preventDefault();
return true;
});
... ...
... ... @@ -31,8 +31,7 @@
* 变成的设备登录:分为桌面(普通登录和手机验证码登录)和手机登录(二维码登录)。
*/
var $ = require('yoho-jquery'),
Captcha = require('../../plugins/captcha');
var $ = require('yoho-jquery');
// 密码输入帐号
var $accountInput1 = $('#account1'),
... ... @@ -53,11 +52,12 @@ var $accountInput1 = $('#account1'),
},
// 图像验证码
$captchaImgInput = $('#captcha'),
$captchaImgWrapper = $('.captcha-wrap'),
captchaImg = new Captcha('.captcha-wrap').init(),
$showCaptchaImg = false,
$captchaImgPic = $captchaImgWrapper.find('#captcha-img'),
$showCaptchImg = false,
getCaptchaImgVal = function() {
return captchaImg.getResults();
return $.trim($captchaImgInput.val());
},
// 短信验证码
... ... @@ -70,9 +70,11 @@ var $accountInput1 = $('#account1'),
getCaptchaSmsTokenVal = function() { // 短信登录凭证
return $.trim($captchaSmsTokenHideInput.val());
},
smsCaptchaImg = new Captcha('.sms-captcha-img-wrap').init(),
$smsCaptchaImgWrapper = $('.sms-captcha-img-wrap'),
$smsCaptchaImgInput = $smsCaptchaImgWrapper.find('#sms-captcha-input'),
$smsCaptchaImgPic = $smsCaptchaImgWrapper.find('#sms-captcha-img'),
getSmsCaptchaImgVal = function() { // 短信登录图形验证码
return smsCaptchaImg.getResults();
return $.trim($smsCaptchaImgInput.val());
},
// 区域选择
... ... @@ -104,12 +106,17 @@ var $accountInput1 = $('#account1'),
var $accountTip1 = $accountInput1.siblings('.err-tip'),
$accountTip2 = $accountInput2.siblings('.err-tip'),
$passwordTip = $passwordInput.siblings('.err-tip'),
$captchaImgTip = $captchaImgInput.siblings('.err-tip'),
$captchaSmsTip = $captchaSmsInput.siblings('.err-tip'),
$smsCaptchaImgTip = $smsCaptchaImgInput.siblings('.err-tip'),
$capsLock = $('#caps-lock');
var mailPhoneRegx = require('../common/mail-phone-regx'), // 邮箱格式验证
mailAc = require('../common/ac-email'); // 邮箱自动完成
// 图像验证码URL
var CAPTCHA_IMG_URL = '/passport/imagesNode?t=';
// 刷新手机短信图形验证码
var refreshSmsImgCallBack = $.Callbacks(); // eslint-disable-line
... ... @@ -265,8 +272,10 @@ accountChangeEvent.add(function(type) {
hideSmsCaptchaImgTip(); // eslint-disable-line
$passwordInput.val('');
$captchaImgInput.val('');
$captchaSmsInput.val('');
$smsCaptchaImgInput.val('');
$captchaSmsTokenHideInput.val('');
if (type === AccountLoginData.QRCodeLogin.name) {
... ... @@ -276,14 +285,13 @@ accountChangeEvent.add(function(type) {
// 密码登录的图形验证码
if (type === AccountLoginData.PasswordLogin.name) {
if ($showCaptchaImg) {
if ($showCaptchImg) {
$captchaImgWrapper.removeClass('hide');
captchaImg.refresh();
}
}
if (type === AccountLoginData.SMSLogin.name) {
if ($showCaptchaImg) {
if ($showCaptchImg) {
$captchaImgWrapper.addClass('hide');
}
}
... ... @@ -293,7 +301,7 @@ accountChangeEvent.add(function(type) {
accountChangeEvent.add(function(type) {
if (type === AccountLoginData.SMSLogin.name) {
$accountInput2.val($accountInput1.val());
refreshSmsCaptchaImg();
$smsCaptchaImgPic.attr('src', CAPTCHA_IMG_URL + $.now());
} else {
$accountInput1.val($accountInput2.val());
}
... ... @@ -308,7 +316,8 @@ mobileTipShowOnce.add(function() {
});
refreshSmsImgCallBack.add(function() {
refreshSmsCaptchaImg();
$smsCaptchaImgPic.attr('src', CAPTCHA_IMG_URL + $.now());
$smsCaptchaImgInput.val('');
});
/** ************************************************************************/
... ... @@ -365,8 +374,12 @@ function hidePasswordTip() {
/** ************************************************************************/
function showCaptchaImgTip(msg) {
return errTipShow($captchaImgTip, $captchaImgInput, msg);
}
function hideCaptchaImgTip() {
return captchaImg.hide();
return errTipHide($captchaImgTip, $captchaImgInput);
}
/** ************************************************************************/
... ... @@ -382,13 +395,13 @@ function hideCaptchaSmsTip() {
/** ************************************************************************/
function showSmsCaptchaImgTip() {
function showSmsCaptchaImgTip(msg) {
refreshSmsImgCallBack.fire();
smsCaptchaImg.showTip();
return errTipShow($smsCaptchaImgTip, $smsCaptchaImgInput, msg);
}
function hideSmsCaptchaImgTip() {
smsCaptchaImg.hideTip();
return errTipHide($smsCaptchaImgTip, $smsCaptchaImgInput);
}
/** ************************************************************************/
... ... @@ -480,6 +493,7 @@ function validateAccount() {
.then(currentLogin.hideAccountTip);
}
/** ************************************************************************/
/* 密码验证 */
/** ************************************************************************/
... ... @@ -517,8 +531,59 @@ function validatePasswordLocal() {
/** ************************************************************************/
/* 图形验证码 */
/** ************************************************************************/
function validateCaptchaImgLocal() {
var captcha = getCaptchaImgVal(),
err;
var defer = $.Deferred(); // eslint-disable-line
if (captcha !== '') {
if (captcha.length !== 4) {
err = '请输入长度为4字符的验证码';
defer.reject();
} else {
defer.resolve();
}
} else {
err = '请输入验证码';
defer.reject();
}
if (defer.state() === 'resolved') {
hideCaptchaImgTip();
} else {
showCaptchaImgTip(err);
}
return defer.promise();
}
function validateCaptchaImgAsync() {
return captchaImg.check();
return $.ajax({
url: '/passport/captcha/img',
type: 'POST',
data: {
verifyCode: getCaptchaImgVal()
}
}).then(function(result) {
var defer = $.Deferred(); // eslint-disable-line
if (result.code === 200) {
hideCaptchaImgTip();
defer.resolve();
} else {
showCaptchaImgTip('验证码不正确');
defer.reject();
}
return defer.promise();
});
}
function validateCaptchaImg() {
... ... @@ -527,7 +592,8 @@ function validateCaptchaImg() {
return $.Deferred().resolve().promise(); //eslint-disable-line
}
return validateCaptchaImgAsync()
return validateCaptchaImgLocal()
.then(validateCaptchaImgAsync)
.then(hideCaptchaSmsTip);
}
... ... @@ -642,12 +708,64 @@ function sendCaptchaSmsAsync() {
/* 短信验证图形验证 */
/** ************************************************************************/
function validateSmsCaptchaImg() {
return smsCaptchaImg.check();
function smsCaptchaImgLocal() {
var captcha = getSmsCaptchaImgVal(),
err;
var defer = $.Deferred(); // eslint-disable-line
if (captcha !== '') {
if (captcha.length !== 4) {
err = '请输入长度为4字符的验证码';
defer.reject();
} else {
defer.resolve();
}
} else {
err = '请输入验证码';
defer.reject();
}
if (defer.state() === 'resolved') {
hideSmsCaptchaImgTip();
} else {
showSmsCaptchaImgTip(err);
}
return defer.promise();
}
function smsCaptchaImgAsync() {
return $.ajax({
url: '/passport/captcha/img',
type: 'POST',
data: {
verifyCode: getSmsCaptchaImgVal()
}
}).then(function(result) {
var defer = $.Deferred(); // eslint-disable-line
if (result.code === 200) {
hideSmsCaptchaImgTip();
defer.resolve();
} else {
showSmsCaptchaImgTip('验证码不正确');
defer.reject();
}
return defer.promise();
});
}
function refreshSmsCaptchaImg() {
smsCaptchaImg.refresh();
function validateSmsCaptchaImg() {
return smsCaptchaImgLocal()
.then(smsCaptchaImgAsync)
.then(hideSmsCaptchaImgTip);
}
/** ************************************************************************/
... ... @@ -876,11 +994,10 @@ function loginAsync() {
}
function showCaptchaImgPic() {
captchaImg.refresh().then(function() {
$captchaImgWrapper.removeClass('hide');
});
$showCaptchaImg = true;
$captchaImgPic.attr('src', CAPTCHA_IMG_URL + $.now());
$captchaImgInput.val('');
$captchaImgWrapper.removeClass('hide');
$showCaptchImg = true;
}
// 设置 refer 信息
... ... @@ -964,6 +1081,10 @@ $passwordInput.on('blur', function() {
$capsLock.addClass('hide');
});
// 图像验证码输入框事件
$captchaImgInput.on('blur', validateCaptchaImg);
/** ************************************************************************/
// 短信下手机输入框失去焦点:本地验证格式
... ... @@ -971,6 +1092,11 @@ $accountInput2.on('blur', function() {
return currentLogin.validateAccountLocal();
});
// 图形验证码失去焦点验证
$smsCaptchaImgInput.on('blur', function() {
validateSmsCaptchaImg();
});
// sms验证码输入框事件
$captchaSmsInput.on('blur', validateCaptchaSms);
... ... @@ -1010,6 +1136,16 @@ $('.va').on('focus', function() {
$this.siblings('.err-tip').addClass('hide');
});
// 验证码刷新
$captchaImgWrapper.on('click', '.change-captcha, .captcha-img', function() {
$captchaImgPic.attr('src', CAPTCHA_IMG_URL + $.now());
});
// 刷新短信图形验证码
$smsCaptchaImgWrapper.on('click', '.change-captcha, .captcha-img', function() {
$smsCaptchaImgPic.attr('src', CAPTCHA_IMG_URL + $.now());
});
// 切换登录模式:密码登录和短信登录
$PhoneLoginSwitcher.on('click', 'div', function() {
var $this = $(this),
... ...
... ... @@ -5,8 +5,7 @@
var $ = require('yoho-jquery'),
regValidate = require('../common/mail-phone-regx'),
computeComplex = require('../common/pwd-strength'),
Captcha = require('../../plugins/captcha');
computeComplex = require('../common/pwd-strength');
var $registerPage = $('.register-page'),
$pwdTips = $('#pwd-tips'),
... ... @@ -16,19 +15,18 @@ var $registerPage = $('.register-page'),
$countDown = $('#count-down'),
$successBtn = $('.success-btn'),
countDown = 5,
clearT,
captchaImage = new Captcha('#captcha-img').init();
clearT;
var $sendCaptcha = $('#send-captcha'),
caCount = 4,
validateResult = [];
var $pn = $('#phone-num'),
$mc = $('#msg-captcha'),
$pwd = $('#pwd'),
getCaptchaImageVal = function() {
return captchaImage.getResults();
},
timeSecond = 0;
$repwd = $('#repwd'),
$ca = $('#captcha'),
timeResidue = 0;
// 密码强度验证
var $pwdIntensity = $('.pwd-intensity'),
... ... @@ -38,6 +36,9 @@ var $pwdIntensity = $('.pwd-intensity'),
var $region = $('#country-code'),
$regionSelect = $('#region');
var isPwd = false,
pwdVal;
var pwdReg = regValidate.pwdValidateRegx;
var $curErrContainer;
... ... @@ -47,13 +48,20 @@ var oldPhone = ''; // 如果手机号改变时刷新验证码
require('../../simple-header');
require('yoho-jquery-placeholder');
// 验证码位数
$ca.attr('maxlength', caCount);
// 密码规则提示
$pwd.focus(function() {
$pwdTips.removeClass('hide');
isPwd = true;
pwdVal = $(this).val();
}).blur(function() {
$pwdTips.addClass('hide');
isPwd = false;
});
// IE8 placeholder
$('[placeholder]').placeholder();
... ... @@ -65,7 +73,7 @@ validateResult = [
status: false // 当前的状态
},
{
id: 'captcha-img',
id: 'captcha',
message: '',
status: false
},
... ... @@ -86,14 +94,13 @@ validateResult = [
}
];
captchaImage.onRefresh(function() {
validateResult[1].message = 'err';
validateResult[1].status = false;
});
// 刷新图形验证码
function refreshPic() {
captchaImage.refresh();
var time = new Date(),
$captchaImg = $('.captcha-img'),
captchaImgSrc = $captchaImg.attr('src').split('?')[0];
$captchaImg.attr('src', captchaImgSrc + '?t=' + time.getTime());
}
// 手机号ajax校验
... ... @@ -120,17 +127,13 @@ function phoneAjaxFn(page, callback) {
validateResult[0].message = 'err';
validateResult[0].status = false;
return $.ajax({
$.ajax({
url: url,
type: 'POST',
data: data
}).then(function(res) {
var defer = $.Deferred();
defer.always(callback);
if (!res) {
return defer.reject().promise();
return;
}
switch (res.code) {
... ... @@ -140,7 +143,8 @@ function phoneAjaxFn(page, callback) {
// 如果手机号发生改变则刷新验证码并且更新状态
refreshPic();
validateResult[1].message = 'err';
$sendCaptcha.addClass('disable').attr('disabled', 'disabled');
validateResult[1].message = '图形验证码错误';
validateResult[1].status = false;
}
... ... @@ -148,28 +152,58 @@ function phoneAjaxFn(page, callback) {
validateResult[0].message = '';
validateResult[0].status = true;
return defer.resolve().promise();
break;
case 400:
refreshPic();
validateResult[0].message = res.message;
validateResult[0].status = false;
return defer.reject().promise();
break;
default:
return defer.reject().promise();
break;
}
callback();
});
}
// 图形验证码ajax校验
function picCaptchaAjaxFn(callback) {
return captchaImage.check().then(function() {
validateResult[1].message = '';
validateResult[1].status = true;
}).fail(function() {
validateResult[1].message = 'err';
validateResult[1].status = false;
}).always(callback);
function picCaptchaAjaxFn(page, callback) {
var url;
if (page === 'reg') {
url = '/passport/reg/piccaptcha';
} else if (page === 'third') {
url = '/passport/autouserinfo/checkPicCode';
}
$.ajax({
type: 'POST',
url: url,
data: {
verifyCode: $ca.val()
// mobile: $pn.val(),
// area: $region.text().split('+')[1]
}
}).then(function(data) {
if (!data) {
return;
}
switch (data.code) {
case 200:
validateResult[1].message = '';
validateResult[1].status = true;
break;
case 400:
refreshPic();
validateResult[1].message = '图形验证码错误';
validateResult[1].status = false;
break;
default:
break;
}
callback();
});
}
// 短信验证码ajax校验
... ... @@ -181,8 +215,7 @@ function msgCaptchaAjaxFn(page, callback) {
} else if (page === 'third') {
url = '/passport/autouserinfo/checkBindMsg';
}
return $.ajax({
$.ajax({
type: 'POST',
url: url,
data: {
... ... @@ -191,26 +224,24 @@ function msgCaptchaAjaxFn(page, callback) {
area: $region.text().split('+')[1]
}
}).then(function(data) {
var defer = $.Deferred();
defer.always(callback);
if (!data) {
return defer.reject().promise();
return;
}
switch (data.code) {
case 200:
validateResult[2].message = '';
validateResult[2].status = true;
return defer.resolve().promise();
break;
case 400:
validateResult[2].message = '短信验证码错误';
validateResult[2].status = false;
return defer.reject().promise();
break;
default:
return defer.reject().promise();
break;
}
callback();
});
}
... ... @@ -220,68 +251,80 @@ function validateRule(page, $element, callback) {
var val = $.trim($element.val()),
regionCode;
// 根据需求http://redmine.yoho.cn/issues/3117改成上边的正则
// 对应的错误提示语也改了,感觉要不了多久就会改回来
// pwdReg = /^([a-zA-Z0-9\-\+_!@\#$%\^&\*\(\)\:\;\.=\[\]\\\',\?]){6,20}$/gi;
var defer = $.Deferred();
defer.always(callback);
// 手机号校验
if ($element.hasClass('phone-num')) {
regionCode = $region.text();
if (val === '') {
validateResult[0].message = '请输入手机号码';
validateResult[0].status = false;
return defer.reject().promise();
return callback();
} else {
if (!/^[0-9]+$/.test(val) ||
(regionCode === '+86' && !regValidate.phoneRegx[regionCode].test(val))) {
validateResult[0].message = '手机号码格式不正确,请重新输入';
validateResult[0].status = false;
return defer.reject().promise();
return callback();
} else {
return phoneAjaxFn(page, callback);
phoneAjaxFn(page, callback);
}
}
// 图形验证码校验
} else if ($element.hasClass('w330')) {
// 并且手机号正确
if (validateResult[0].status) {
return picCaptchaAjaxFn(callback);
} else if ($element.hasClass('captcha')) {
if (val === '') {
validateResult[1].message = '请输入图形验证码';
validateResult[1].status = false;
return callback();
} else {
validateResult[1].message = 'err';
} else if (val.length <= 3) {
validateResult[1].message = '图形验证码为4位';
validateResult[1].status = false;
return defer.reject().promise();
return callback();
} else {
// 并且手机号正确
if (validateResult[0].status) {
picCaptchaAjaxFn(page, callback);
} else {
validateResult[1].message = '图形验证码错误';
validateResult[1].status = false;
return callback();
}
}
// 短信验证码校验
} else if ($element.hasClass('msg-captcha')) {
if (val === '') {
validateResult[2].message = '请输入短信验证码';
validateResult[2].status = false;
return defer.reject().promise();
return callback();
} else if (val.length <= 3) {
validateResult[2].message = '短信验证码错误';
validateResult[2].status = false;
return defer.reject().promise();
return callback();
} else {
// 并且图形验证码正确
if (validateResult[1].status) {
return msgCaptchaAjaxFn(page, callback);
msgCaptchaAjaxFn(page, callback);
} else {
validateResult[2].message = '短信验证码错误';
validateResult[2].status = false;
return defer.reject().promise();
return callback();
}
}
... ... @@ -290,23 +333,39 @@ function validateRule(page, $element, callback) {
if (val === '') {
validateResult[3].message = '请输入密码';
validateResult[3].status = false;
return defer.reject().promise();
} else if (val.length < 6 || val.length > 20) {
validateResult[3].message = '密码只支持6-20位字符';
validateResult[3].status = false;
return defer.reject().promise();
} else if (!pwdReg.test($element.val())) {
validateResult[3].message = '密码须字母和数字组合';
validateResult[3].status = false;
return defer.reject().promise();
} else {
validateResult[3].message = '';
validateResult[3].status = true;
return defer.resolve().promise();
}
}
return callback();
// 二次密码校验
} else if ($element.hasClass('repwd')) {
if (val === '') {
validateResult[4].message = '请输入密码确认';
validateResult[4].status = false;
} else if ($pwd.val() !== val) {
validateResult[4].message = '与密码不一致,请重新输入';
validateResult[4].status = false;
} else {
validateResult[4].message = '';
validateResult[4].status = true;
}
return defer.promise();
return callback();
}
}
function posErrTip() {
... ... @@ -352,7 +411,7 @@ function showBorder() {
validateResultLen = validateResult.length;
for (i = 0; i < validateResultLen; i++) {
if (validateResult[i].message && validateResult[i].message !== 'err') {
if (validateResult[i].message) {
// 显示红色边框
$errInput = $('#' + validateResult[i].id);
... ... @@ -430,8 +489,6 @@ $(window).resize(function() {
// ( ▼-▼ )注册页和信息完善页面接口不同
exports.init = function(page) {
captchaImage.refresh();
$('#agree-terms').click(function() {
var $this = $(this),
... ... @@ -494,6 +551,16 @@ exports.init = function(page) {
} else {
$registerBtn.addClass('disable').attr('disabled', 'disabled');
}
// 图形验证通过时,发送短信按钮可点击
if (validateResult[1].status && timeResidue <= 0) {
$sendCaptcha.removeClass('disable').removeAttr('disabled');
} else {
$sendCaptcha.addClass('disable').attr('disabled', 'disabled');
}
// 图形验证通过时,发送短信按钮可点击 end
});
// 如果是密码则校验强度
... ... @@ -501,6 +568,12 @@ exports.init = function(page) {
pwdFn($that);
}
}).blur(function() {
/* validateRule($(this), function() {
showErrTip();
showBorder(); // 显示红色边框
});*/
});
$regionSelect.change(function() {
... ... @@ -525,49 +598,37 @@ exports.init = function(page) {
url = '/passport/autouserinfo/sendBindMsg';
}
// 1.验证图形验证码是否正确
// 2.验证手机号被注册过
// 3.发送短信
validateRule(page, $('#captcha-img'), function() {
showErrTip(); // 显示错误提示
showBorder(); // 显示红色边框
}).then(function() {
return validateRule(page, $pn, function() {
showErrTip(); // 显示错误提示
showBorder(); // 显示红色边框
});
}).then(function() {
return $.ajax({
type: 'POST',
url: url,
data: {
area: $region.text().split('+')[1],
mobile: $pn.val(),
verifyCode: getCaptchaImageVal()
}
}).then(function(result) {
if (result.code !== 200) {
validateResult[0].message = result.message;
validateResult[0].status = false;
// todo ajax 发送验证码
$.ajax({
type: 'POST',
url: url,
data: {
area: $region.text().split('+')[1],
mobile: $pn.val(),
verifyCode: $ca.val()
}
}).then(function(result) {
if (result.code !== 200) {
validateResult[0].message = result.message;
validateResult[0].status = false;
showErrTip();
return;
}
showErrTip();
return;
}
$('#msg-tip').removeClass('hide');
timeSecond = 60;
$sendCaptcha.addClass('disable').attr('disabled', 'disabled');
$sendCaptcha.val('60秒可重新发送');
$('#msg-tip').removeClass('hide');
timeResidue = 60;
$sendCaptcha.addClass('disable').attr('disabled', 'disabled');
$sendCaptcha.val('60秒可重新发送');
t = setInterval(function() {
if (timeSecond <= 0) {
$sendCaptcha.removeClass('disable').removeAttr('disabled').val('获取短信验证码');
clearInterval(t);
return;
}
$sendCaptcha.val(timeSecond-- + '秒可重新发送');
}, 1000);
});
t = setInterval(function() {
if (timeResidue <= 0) {
$sendCaptcha.removeClass('disable').removeAttr('disabled').val('获取短信验证码');
clearInterval(t);
return;
}
$sendCaptcha.val(timeResidue-- + '秒可重新发送');
}, 1000);
});
});
... ... @@ -599,7 +660,7 @@ exports.init = function(page) {
data: {
area: $region.text().split('+')[1],
mobile: $pn.val(),
verifyCode: getCaptchaImageVal(),
verifyCode: $ca.val(),
code: $mc.val(),
password: $pwd.val()
}
... ... @@ -635,13 +696,17 @@ exports.init = function(page) {
} else {
// todo
alert(data.message); //eslint-disable-line
console.log('网络超时~');
}
});
}
});
$('.change-captcha').click(function() {
refreshPic();
});
// 注册成功页面5秒后跳转
if ($('.success-box').length > 0) {
clearT = setInterval(function() {
... ... @@ -655,15 +720,4 @@ exports.init = function(page) {
$countDown.text(countDown--);
}, 1000);
}
// 设置 refer 信息
(function() {
var refer = queryString().refer || ''; // eslint-disable-line
if (refer) {
setCookie('refer', refer); // eslint-disable-line
} else {
setCookie('refer', ''); // eslint-disable-line
}
}());
};
... ...
... ... @@ -694,6 +694,7 @@ function pageInit() {
.last().find('.reconnect');
if (!$reconnect.length) {
socketChat.clear();
offlineTip();
}
},
... ...
... ... @@ -2,8 +2,7 @@
.content {
float: left;
margin-top: 80px;
margin-bottom: 100px;
margin-top: 107px;
padding-left: 85px;
}
... ...
... ... @@ -1069,49 +1069,52 @@ $color-3a3a3a: #3a3a3a;
.detail-reason {
display: none;
.discontent {
.dis-wrap {
margin-left: 8px;
max-height: 155px;
overflow-y: scroll;
overflow-x: hidden;
margin-bottom: 30px;
.dis-row {
font-size: 0;
text-align: center;
margin-bottom: 13px;
.discontent {
margin-bottom: 30px;
.type {
position: relative;
display: inline-block;
width: 155px;
height: 40px;
padding: 0 2px;
font-size: 12px;
text-align: center;
line-height: 40px;
border: 1px #999999 solid;
border-radius: 5px;
cursor: pointer;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
.dis-row {
font-size: 0;
margin-bottom: 13px;
&.chosen {
&:after {
position: absolute;
top: 13px;
right: -2px;
content: '';
display: inline-block;
height: 27px;
width: 27px;
background-image: resolve('service/btn-chosen.png');
.type {
position: relative;
display: inline-block;
width: 155px;
height: 40px;
padding: 0 2px;
font-size: 12px;
text-align: center;
line-height: 40px;
border: 1px #999999 solid;
border-radius: 5px;
cursor: pointer;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
&.chosen {
&:after {
position: absolute;
top: 13px;
right: -2px;
content: '';
display: inline-block;
height: 27px;
width: 27px;
background-image: resolve('service/btn-chosen.png');
}
}
}
&:first-child {
margin-right: 15px;
&:first-child {
margin-right: 15px;
}
}
}
}
... ...