Authored by 姜枫

add login assets

@@ -7,6 +7,7 @@ @@ -7,6 +7,7 @@
7 7
8 const library = '../../../library'; 8 const library = '../../../library';
9 const passport = require('passport'); 9 const passport = require('passport');
  10 +const md5 = require('md5');
10 const cookie = require(`${library}/cookie`); 11 const cookie = require(`${library}/cookie`);
11 const helpers = require(`${library}/helpers`); 12 const helpers = require(`${library}/helpers`);
12 const log = require(`${library}/logger`); 13 const log = require(`${library}/logger`);
@@ -51,6 +52,47 @@ function doPassportCallback(openId, nickname, sourceType, req, res) { @@ -51,6 +52,47 @@ function doPassportCallback(openId, nickname, sourceType, req, res) {
51 } 52 }
52 } 53 }
53 54
  55 +
  56 +const local = {
  57 + loginPage: (req, res) => {
  58 + // 设置登录有效时间30分钟, 防机器刷,cache不稳定,改为cookie
  59 + res.cookie('LE' + md5('_LOGIN_EXPIRE'), (new Date()).getTime() / 1000 + 1800);
  60 +
  61 + // 清除cookie
  62 + res.clearCookie('_UID');
  63 + res.clearCookie('_TOKEN');
  64 +
  65 + let refer = req.query.refer;
  66 +
  67 + if (!refer) {
  68 + refer = req.get('Referer');
  69 + }
  70 + refer && res.cookie('refer', encodeURI(refer), {
  71 + domain: 'yohobuy.com'
  72 + });
  73 +
  74 + res.render('login', {
  75 + loginIndex: true, // 模板中使用JS的标识
  76 + backUrl: 'javascript:history.go(-1)', // 返回的URL链接
  77 + showHeaderImg: true, // 控制显示头部图片
  78 + isPassportPage: true, // 模板中模块标识
  79 + registerUrl: '/reg.html', // 注册的URL链接
  80 + aliLoginUrl: '/passport/login/alipay', // 支付宝快捷登录的URL链接
  81 + weiboLoginUrl: '/passport/login/sina', // 微博登录的URL链接
  82 + qqLoginUrl: '/passport/login/qq', // 腾讯QQ登录的URL链接
  83 + internationalUrl: '/login.html', // 国际号登录的URL链接
  84 + phoneRetriveUrl: '/passport/back/mobile', // 通过手机号找回密码的URL链接
  85 + emailRetriveUrl: '/passport/back/email', // 通过邮箱找回密码的URL链接
  86 + module: 'passport',
  87 + page: 'index',
  88 + title: '登录'
  89 + });
  90 + },
  91 + login: (req, res, next) => {
  92 +
  93 + }
  94 +};
  95 +
54 const wechat = { 96 const wechat = {
55 beforeLogin: (req, res, next) => { 97 beforeLogin: (req, res, next) => {
56 let refer = req.query.refer; 98 let refer = req.query.refer;
@@ -80,4 +122,5 @@ const wechat = { @@ -80,4 +122,5 @@ const wechat = {
80 } 122 }
81 }; 123 };
82 124
  125 +exports.local = local;
83 exports.wechat = wechat; 126 exports.wechat = wechat;
@@ -12,6 +12,7 @@ const login = require(cRoot + '/login'); @@ -12,6 +12,7 @@ const login = require(cRoot + '/login');
12 12
13 const router = express.Router(); // eslint-disable-line 13 const router = express.Router(); // eslint-disable-line
14 14
  15 +router.get('/login', login.local.loginPage);
15 router.get('/login/wechat', login.wechat.beforeLogin, login.wechat.login); // 登录 16 router.get('/login/wechat', login.wechat.beforeLogin, login.wechat.login); // 登录
16 router.get('/login/wechat/callback', login.wechat.callback); 17 router.get('/login/wechat/callback', login.wechat.callback);
17 18
  1 +<div class="login-page passport-page yoho-page">
  2 + {{> passport/header}}
  3 + <div class="content">
  4 + <div class="acc-container input-container row has-clear">
  5 + <div class="yoho-logo"></div>
  6 + <input id="account" class="input account" type="text" placeholder="手机号/邮箱" autocomplete="off" value={{account}}>
  7 + </div>
  8 + <div class="input-container row has-eye">
  9 + <input id="pwd" class="pwd input" type="password" placeholder="密码">
  10 + </div>
  11 + <span id="btn-login" class="btn btn-login disable">登录</span>
  12 + <p class="op-container">
  13 + <a class="go-register" href={{registerUrl}}>免费注册</a>
  14 + <span id="forget-pwd" class="forget-pwd">忘记密码</span>
  15 + </p>
  16 + <div class="third-party-login">
  17 + <span>其他登录方式</span>
  18 + <div class="tp-link">
  19 + <a class="alipay" href={{aliLoginUrl}}></a>
  20 + <a class="weibo" href={{weiboLoginUrl}}></a>
  21 + <a class="qq" href={{qqLoginUrl}}></a>
  22 + </div>
  23 + </div>
  24 + <a class="international" href={{internationalUrl}}>International Customer</a>
  25 + <div class="login-tip">
  26 + <div class="info-icon"></div>
  27 + Yoho!Family账号可登录Yoho!Buy有货
  28 + </div>
  29 + <div id="retrive-pwd-mask" class="mask"></div>
  30 + <ul id="retrive-pwd-ways" class="retrive-pwd-ways">
  31 + <li>
  32 + <a href={{phoneRetriveUrl}}>通过手机找回密码</a>
  33 + </li>
  34 + <li>
  35 + <a href={{emailRetriveUrl}}>通过邮箱找回密码</a>
  36 + </li>
  37 + <li id="cancel-retrive">
  38 + 取消
  39 + </li>
  40 + </ul>
  41 + </div>
  42 +</div>
  1 +<div class="header">
  2 + <a class="go-back" href="{{#if backUrl}}{{backUrl}}{{^}}javascript:history.go(-1);{{/if}}"></a>
  3 + {{#showHeaderImg}}
  4 + <div class="img-header"></div>
  5 + {{/showHeaderImg}}
  6 + {{#headerText}}
  7 + <p class="title">{{.}}</p>
  8 + {{/headerText}}
  9 +</div>
  1 +/**
  2 + * 登录
  3 + * @author: xuqi<qi.xu@yoho.cn>
  4 + * @date: 2015/9/30
  5 + */
  6 +var $ = require('jquery');
  7 +
  8 +var $account = $('#account'),
  9 + $pwd = $('#pwd'),
  10 + $loginBtn = $('#btn-login'),
  11 +
  12 + $mask = $('#retrive-pwd-mask'),
  13 + $ways = $('#retrive-pwd-ways'),
  14 +
  15 + accPass = false,
  16 + pwdPass = false;
  17 +
  18 +var api = require('../api');
  19 +var tip = require('../../plugin/tip');
  20 +
  21 +var trim = $.trim;
  22 +var showErrTip = tip.show;
  23 +
  24 +//登录按钮状态切换
  25 +function switchLoginBtnStatus() {
  26 + if (accPass && pwdPass) {
  27 + $loginBtn.removeClass('disable');
  28 + } else {
  29 + $loginBtn.addClass('disable');
  30 + }
  31 +}
  32 +
  33 +//显示找回密码面板
  34 +function showRetrivePanel() {
  35 + $mask.show();
  36 + $ways.show();
  37 +}
  38 +
  39 +//隐藏找回密码面板
  40 +function hideRetrivePanel() {
  41 + $mask.hide();
  42 + $ways.hide();
  43 +}
  44 +
  45 +//密码显示与隐藏
  46 +api.bindEyesEvt();
  47 +
  48 +//清空账号输入框
  49 +api.bindClearEvt();
  50 +
  51 +$account.bind('input', function() {
  52 + if (trim($account.val()) !== '') {
  53 + accPass = true;
  54 + } else {
  55 + accPass = false;
  56 + }
  57 + switchLoginBtnStatus();
  58 +});
  59 +
  60 +$pwd.bind('input', function() {
  61 + if (trim($pwd.val()) === '') {
  62 + pwdPass = false;
  63 + } else {
  64 + pwdPass = true;
  65 + }
  66 + switchLoginBtnStatus();
  67 +});
  68 +
  69 +
  70 +// Login
  71 +$loginBtn.on('touchstart', function() {
  72 + var acc = trim($account.val()),
  73 + pwd = trim($pwd.val());
  74 +
  75 + if ($loginBtn.hasClass('disable')) {
  76 + return;
  77 + }
  78 +
  79 + $loginBtn.text('正在登录...').addClass('disable');
  80 +
  81 + //验证账号(数字或者邮箱)和密码合理性
  82 + if ((/^[0-9]+$/.test(acc) || api.emailRegx.test(acc)) && api.pwdValidate(pwd)) {
  83 + $.ajax({
  84 + type: 'POST',
  85 + url: '/passport/login/auth',
  86 + data: {
  87 + account: acc,
  88 + password: pwd
  89 + },
  90 + success: function(data) {
  91 + var res;
  92 +
  93 + if (data.code === 200) {
  94 + res = data.data;
  95 +
  96 + showErrTip('登录成功');
  97 + location.href = res.href;
  98 + } else {
  99 + showErrTip(data.message);
  100 + }
  101 + },
  102 + error: function() {
  103 + showErrTip('网络断开连接啦~');
  104 + },
  105 + complete: function() {
  106 + $loginBtn.text('登录').removeClass('disable');
  107 + }
  108 + });
  109 + } else {
  110 + showErrTip('账号或密码有错误,请重新输入');
  111 + $loginBtn.text('登录').removeClass('disable');
  112 + }
  113 +});
  114 +
  115 +
  116 +$('#forget-pwd').on('touchstart', function() {
  117 + showRetrivePanel();
  118 +});
  119 +
  120 +$mask.on('touchstart', function() {
  121 + hideRetrivePanel();
  122 +});
  123 +
  124 +$('#cancel-retrive').on('touchstart', function(e) {
  125 + e.preventDefault();
  126 + hideRetrivePanel();
  127 +});
  128 +
  129 +//对初始有默认值的情况去初始化登录按钮状态
  130 +$account.trigger('input');
  131 +$pwd.trigger('input');
  1 +.back-email-success-page {
  2 + .tip {
  3 + font-size: 20PX;
  4 + color: #fff;
  5 + margin-top: 30PX;
  6 + }
  7 +
  8 + .sub-tip, .resend {
  9 + color: #939393;
  10 + font-size: 16PX;
  11 + }
  12 +
  13 + .go-email {
  14 + margin: 20PX 0 10PX;
  15 + }
  16 +
  17 + .resend {
  18 + float: right;
  19 + }
  20 +}
  1 +.bind-page
  2 + .bind-tip {
  3 + color: #fff;
  4 + font-size: 15PX;
  5 + }
  6 +
  7 + #yohood {
  8 + background-image: resolve('yohood.png');
  9 + background-size: 40%;
  10 + background-repeat: no-repeat;
  11 + background-color: transparent;
  12 + background-position-x: 10%;
  13 + background-position-y: 40%;
  14 + border: none;
  15 + border-bottom: 4PX solid #fff;
  16 +
  17 + }
  1 +.reg-code-page, .back-code-page {
  2 + .captcha-tip {
  3 + position: absolute;
  4 + width: 148PX;
  5 + text-align: center;
  6 + right: 15PX;
  7 + top: 8PX;
  8 + color: #36a74c;
  9 + padding: 5PX 0;
  10 + border: 1px solid #36a74c;
  11 + border-radius: 20PX;
  12 + font-size: 16PX;
  13 +
  14 + &.disable {
  15 + color: #8f8f8f;
  16 + border-color: #8f8f8f;
  17 +
  18 + }
  19 + }
  20 +
  21 + .input-container {
  22 + padding-right: 190PX;
  23 + }
  24 +
  25 + .text-container {
  26 + color: #fff;
  27 + font-size: 16PX;
  28 + margin-bottom: 20PX;
  29 + }
  30 +
  31 + .phone {
  32 + color: #4ecae8;
  33 + }
  34 +
  35 + .clear-input {
  36 + right: 170PX;
  37 + }
  38 +
  39 + .tip {
  40 + margin-top: 30PX;
  41 + color: #fff;
  42 + font-size: 14PX;
  43 + line-height: 2;
  44 +
  45 + a {
  46 + color: #fff;
  47 + }
  48 + }
  49 +}
  1 +body.passport-body {
  2 + background-color: #444;
  3 + font-family: "MicroSoft YaHei",SimSun,sans-serif;
  4 +
  5 + * {
  6 + box-sizing: border-box;
  7 + }
  8 +}
  9 +
  10 +.passport-page {
  11 + text-align: center;
  12 + padding: 0 6%;
  13 +
  14 + .header {
  15 + position: relative;
  16 + height: 40PX;
  17 + margin: 20PX 0 30PX;
  18 +
  19 + .go-back {
  20 + display: block;
  21 + position: absolute;
  22 + height: 30PX;
  23 + width: 30PX;
  24 + top: 5PX;
  25 + left: 0;
  26 + background: resolve('passport/go-back.png') no-repeat;
  27 + background-size: 100% 100%;
  28 + }
  29 +
  30 + .title {
  31 + font-size: 20PX;
  32 + line-height: 40PX;
  33 + color: #fff;
  34 + }
  35 +
  36 + .img-header {
  37 + width: 68PX;
  38 + height: 40PX;
  39 + background: resolve('passport/yoho-family.png') no-repeat;
  40 + background-size: 100% 100%;
  41 + margin: 0 auto;
  42 + }
  43 + }
  44 +
  45 + .input-container, .select-container {
  46 + position: relative;
  47 + width: 100%;
  48 + height: 52PX;
  49 + font-size: 20PX;
  50 + background-color: #575757;
  51 + border: 1px solid #606060;
  52 + border-radius: 5PX;
  53 + text-align: left;
  54 + color: #fff;
  55 + }
  56 +
  57 + .select-container {
  58 + .select {
  59 + position: absolute;
  60 + height: 50PX;
  61 + padding-right: 40PX;
  62 + right: 0;
  63 + color: #fff;
  64 + background-color: transparent;
  65 + border: 0;
  66 + border-radius: 5PX;
  67 + appearance: none;
  68 + direction: rtl;
  69 +
  70 + &:focus {
  71 + outline: 0;
  72 + border: none;
  73 + }
  74 +
  75 + &:-moz-focusring {
  76 + color: transparent;
  77 + text-shadow: 0 0 0 #fff;
  78 + }
  79 + }
  80 +
  81 + .select-title {
  82 + line-height: 2.5;
  83 + margin-left: 15PX;
  84 + }
  85 +
  86 + .arrow-right {
  87 + position: absolute;
  88 + width: 13PX;
  89 + height: 20PX;
  90 + right: 15PX;
  91 + top: 16PX;
  92 + background: resolve('passport/arrow-right.png') no-repeat;
  93 + background-size: 100% 100%;
  94 + }
  95 + }
  96 +
  97 + .has-eye, .has-clear {
  98 + padding-right: 30PX;
  99 + }
  100 +
  101 + .area-code {
  102 + position: absolute;
  103 + left: 15PX;
  104 + line-height: 2.5;
  105 + }
  106 +
  107 + .phone-container {
  108 + padding-left: 55PX;
  109 + }
  110 +
  111 + .input {
  112 + width: 100%;
  113 + line-height: 26PX;
  114 + padding: 12PX 0;
  115 + padding-left: 15PX;
  116 + border-radius: 5PX;
  117 + color: #fff;
  118 + background-color: transparent;
  119 + border: none;
  120 + }
  121 +
  122 + .btn {
  123 + display: block;
  124 + width: 100%;
  125 + font-size: 20PX;
  126 + line-height: 2.5;
  127 + background-color: #36a74c;
  128 + border-radius: 5PX;
  129 + color: #fff;
  130 +
  131 + &.disable {
  132 + background-color: #a2a2a2;
  133 + }
  134 + }
  135 +
  136 + .country-select.in-android-uc {
  137 + width: 90PX;
  138 + }
  139 +
  140 + .clear-input {
  141 + position: absolute;
  142 + display: none;
  143 + top: 18PX;
  144 + right: 10PX;
  145 + width: 16PX;
  146 + height: 16PX;
  147 + background: resolve('passport/clear-input.png') no-repeat;
  148 + background-size: 100% 100%;
  149 + }
  150 +
  151 + .eye {
  152 + position: absolute;
  153 + top: 20PX;
  154 + right: 10PX;
  155 + width: 19PX;
  156 + height: 12PX;
  157 + background: resolve('passport/eye.png') no-repeat;
  158 + background-size: 100% 100%;
  159 +
  160 + &.close {
  161 + background-image: resolve('passport/eye-close.png');
  162 + }
  163 + }
  164 +
  165 + .row {
  166 + margin-bottom: 10PX;
  167 + }
  168 +}
  1 +@import "common";
  2 +@import "register";
  3 +@import "login";
  4 +@import "back";
  5 +@import "code";
  6 +@import "bind";
  7 +@import "success";
  1 +.login-page {
  2 + .yoho-logo {
  3 + position: absolute;
  4 + height: 31PX;
  5 + width: 26PX;
  6 + background: resolve('passport/yoho.png');
  7 + background-size: 100% 100%;
  8 + top: 10PX;
  9 + left: 15PX;
  10 + }
  11 +
  12 + .acc-container {
  13 + padding-left: 45PX;
  14 + }
  15 +
  16 + .op-container {
  17 + position: relative;
  18 + width: 100%;
  19 + margin: 20PX 0;
  20 + text-align: left;
  21 + font-size: 16PX;
  22 +
  23 + .go-register {
  24 + text-decoration: underline;
  25 + color: #858585;
  26 + }
  27 +
  28 + .forget-pwd {
  29 + position: absolute;
  30 + right: 0;
  31 + text-decoration: underline;
  32 + color: #858585;
  33 + }
  34 + }
  35 +
  36 + .third-party-login {
  37 + text-align: left;
  38 +
  39 + > span {
  40 + font-size: 16PX;
  41 + color: #858585;
  42 + }
  43 +
  44 + .tp-link {
  45 + text-align: center;
  46 + padding: 20PX 0;
  47 +
  48 + > a {
  49 + display: inline-block;
  50 + width: 44PX;
  51 + height: 44PX;
  52 + margin: 0 7PX;
  53 + border-radius: 50%;
  54 + background-color: #333;
  55 + background-repeat: no-repeat;
  56 + background-size: 100% 100%;
  57 + }
  58 +
  59 + .alipay {
  60 + background-image: resolve('passport/alipay.png');
  61 + }
  62 +
  63 + .weibo {
  64 + background-image: resolve('passport/weibo.png');
  65 + }
  66 +
  67 + .weixin {
  68 + background-image: resolve('passport/weixin.png');
  69 + }
  70 +
  71 + .qq {
  72 + background-image: resolve('passport/qq.png');
  73 + }
  74 + }
  75 + }
  76 +
  77 + .international {
  78 + display: block;
  79 + width: 200PX;
  80 + padding: 5PX 10PX;
  81 + background-color: #333;
  82 + border: none;
  83 + border-radius: 20PX;
  84 + margin: 0 auto;
  85 + font-size: 16PX;
  86 + color: #d8d8d8;
  87 + }
  88 +
  89 + .login-tip {
  90 + font-size: 16PX;
  91 + position: relative;
  92 + color: #d8d8d8;
  93 + margin: 15PX 0;
  94 +
  95 + .info-icon {
  96 + display: inline-block;
  97 + height: 12PX;
  98 + width: 12PX;
  99 + background-image: resolve('passport/info.png');
  100 + background-size: 100% 100%;
  101 + }
  102 + }
  103 +
  104 + .mask {
  105 + position: fixed;
  106 + display: none;
  107 + top: 0;
  108 + bottom: 0;
  109 + right: 0;
  110 + left: 0;
  111 + background-color: rgba(0,0,0,.5);
  112 + }
  113 +
  114 + .retrive-pwd-ways {
  115 + position: fixed;
  116 + display: none;
  117 + bottom: 5PX;
  118 + left: 10PX;
  119 + right: 10PX;
  120 + font-size: 16PX;
  121 +
  122 + li {
  123 + background-color: #fff;
  124 + width: 100%;
  125 + height: 40PX;
  126 + line-height: 40PX;
  127 + text-align: center;
  128 +
  129 + &:nth-child(1) {
  130 + border-top-left-radius: 5PX;
  131 + border-top-right-radius: 5PX;
  132 + border-bottom: 1PX solid #9f9f9f;
  133 + }
  134 +
  135 + &:nth-child(2) {
  136 + border-bottom-left-radius: 5PX;
  137 + border-bottom-right-radius: 5PX;
  138 + }
  139 +
  140 + &:last-child {
  141 + margin-top: 10PX;
  142 + border-radius: 5PX;
  143 + }
  144 + }
  145 + }
  146 +
  147 +}
  1 +.reg-page .register-tip {
  2 + color: #fff;
  3 + font-size: 15PX;
  4 +}
  1 +.success-page {
  2 + color: #fefefe;
  3 +
  4 + .success-icon {
  5 + width: 74PX;
  6 + height: 74PX;
  7 + margin: 60PX auto 30PX;
  8 + background: resolve("passport/success.png");
  9 + background-size: 100%;
  10 + }
  11 +
  12 + .success-tip {
  13 + padding: 10PX 10PX;
  14 + font-size: 16PX;
  15 + line-height: 1.5;
  16 + }
  17 +
  18 + .go {
  19 + display: block;
  20 + margin: 30PX auto;
  21 + width: 270PX;
  22 + height: 40PX;
  23 + font-size: 14PX;
  24 + line-height: 40PX;
  25 + color: #fff;
  26 + background: rgba(255, 255, 255, .4);
  27 + border-radius: 5PX;
  28 + }
  29 +}