Authored by ccbikai

Merge branch 'release/4.9.2'

@@ -29,16 +29,19 @@ exports.index = (req, res, next) => { @@ -29,16 +29,19 @@ exports.index = (req, res, next) => {
29 exports.main = (req, res, next) => { 29 exports.main = (req, res, next) => {
30 const isReplay = /^\/live\/replay\//.test(req.path); 30 const isReplay = /^\/live\/replay\//.test(req.path);
31 const id = req.params.id; 31 const id = req.params.id;
  32 + const goDownload = req.query.no;
32 33
33 res.locals.liveRoom = id; 34 res.locals.liveRoom = id;
34 res.locals.module = 'activity'; 35 res.locals.module = 'activity';
35 res.locals.page = 'live-play'; 36 res.locals.page = 'live-play';
  37 + res.locals.enableFoot = goDownload !== 1;
36 38
37 model.fetchInfo(id, isReplay) 39 model.fetchInfo(id, isReplay)
38 .then(result => { 40 .then(result => {
39 if (!result.data) { 41 if (!result.data) {
40 return next(); 42 return next();
41 } 43 }
  44 +
42 res.render('live/play', result.data); 45 res.render('live/play', result.data);
43 }) 46 })
44 .catch(next); 47 .catch(next);
@@ -354,7 +354,7 @@ exports.verifystudent = (req, res, next) => { @@ -354,7 +354,7 @@ exports.verifystudent = (req, res, next) => {
354 } 354 }
355 } else { 355 } else {
356 if (datas[2].code === 500) { 356 if (datas[2].code === 500) {
357 - prompt = '芝麻信用认证失败,稍后重试!'; 357 + prompt = '请重新认证!';
358 } else { 358 } else {
359 prompt = datas[2].message; 359 prompt = datas[2].message;
360 } 360 }
@@ -13,6 +13,9 @@ @@ -13,6 +13,9 @@
13 <p>加载中</p> 13 <p>加载中</p>
14 </div> 14 </div>
15 <div class="live-loading-cover" style="background-image: url('{{pic}}');"></div> 15 <div class="live-loading-cover" style="background-image: url('{{pic}}');"></div>
  16 + <a href="javascript: history.back();" class="live-btn-close">
  17 + <i class="iconfont">&#xe623</i>
  18 + </a>
16 </div> 19 </div>
17 20
18 <div id="live_touch_layer"></div> 21 <div id="live_touch_layer"></div>
@@ -65,9 +68,6 @@ @@ -65,9 +68,6 @@
65 <a href="javascript:;" class="live-btn-share"> 68 <a href="javascript:;" class="live-btn-share">
66 <i class="iconfont">&#xe600</i> 69 <i class="iconfont">&#xe600</i>
67 </a> 70 </a>
68 - <a href="javascript: history.back();" class="live-btn-close">  
69 - <i class="iconfont">&#xe623</i>  
70 - </a>  
71 </section> 71 </section>
72 </div> 72 </div>
73 {{/canPlay}} 73 {{/canPlay}}
@@ -122,6 +122,7 @@ @@ -122,6 +122,7 @@
122 {{/notBegin}} 122 {{/notBegin}}
123 123
124 {{! footer}} 124 {{! footer}}
  125 + {{#enableFoot}}
125 <div class="float-layer" id="float-layer-app"> 126 <div class="float-layer" id="float-layer-app">
126 <div class="float-layer-left"> 127 <div class="float-layer-left">
127 <span class="yoho-icon iconfont">&#xe60d;</span> 128 <span class="yoho-icon iconfont">&#xe60d;</span>
@@ -135,6 +136,7 @@ @@ -135,6 +136,7 @@
135 立即下载 136 立即下载
136 </a> 137 </a>
137 </div> 138 </div>
  139 + {{/enableFoot}}
138 </div> 140 </div>
139 <script> 141 <script>
140 var live_start_time = {{live_start_time}};//该直播开始时间 142 var live_start_time = {{live_start_time}};//该直播开始时间
@@ -142,7 +144,6 @@ @@ -142,7 +144,6 @@
142 var live_room = {{liveRoom}};//房间id,资讯id 144 var live_room = {{liveRoom}};//房间id,资讯id
143 var replay_total_likes = {{like_num}};//重播总计点赞数,取的是直播最终点赞数 145 var replay_total_likes = {{like_num}};//重播总计点赞数,取的是直播最终点赞数
144 var replay_user_nums = {{audience_num}};//重播观看人数,取的是直播时最终观看人数 146 var replay_user_nums = {{audience_num}};//重播观看人数,取的是直播时最终观看人数
145 - var site_url = '';  
146 var site_domain = 'http://api.live.yoho.cn/'; 147 var site_domain = 'http://api.live.yoho.cn/';
147 148
148 // share data 149 // share data
1 {{#unless isApp}} 1 {{#unless isApp}}
2 <header class="yoho-header"> 2 <header class="yoho-header">
3 - <a href="javascript:history.go(-1);" class="iconfont nav-back"></a> 3 + <a href="//m.yohobuy.com/activity/student?openby:yohobuy={'action':'go.h5','params':{'islogin':'N','url':'{{http}}//m.yohobuy.com/activity/student'}}" class="iconfont nav-back"></a>
4 <p class="nav-title">学生身份认证</p> 4 <p class="nav-title">学生身份认证</p>
5 </header> 5 </header>
6 {{/unless}} 6 {{/unless}}
@@ -134,6 +134,11 @@ const _getChannelResource = (params) => { @@ -134,6 +134,11 @@ const _getChannelResource = (params) => {
134 cache: true 134 cache: true
135 }).then(result => { 135 }).then(result => {
136 if (result && result.code === 200) { 136 if (result && result.code === 200) {
  137 + for (let item of result.data.list) {
  138 + item.template_name === 'single_image' &&
  139 + item.data.length === 1 &&
  140 + (item.singleOne = true);
  141 + }
137 return resourcesProcess(result.data.list); 142 return resourcesProcess(result.data.list);
138 } else { 143 } else {
139 logger.error('index resouce is not 200'); 144 logger.error('index resouce is not 200');
@@ -23,7 +23,7 @@ const indexEmailPage = (req, res) => { @@ -23,7 +23,7 @@ const indexEmailPage = (req, res) => {
23 page: 'back-email', 23 page: 'back-email',
24 title: '找回密码-通过邮箱' 24 title: '找回密码-通过邮箱'
25 }, { 25 }, {
26 - backUrl: SIGN_IN, 26 + // backUrl: SIGN_IN,
27 headerText: '找回密码', 27 headerText: '找回密码',
28 isPassportPage: true, 28 isPassportPage: true,
29 backEmail: true 29 backEmail: true
@@ -100,7 +100,7 @@ const backSuccessByEmailPage = (req, res) => { @@ -100,7 +100,7 @@ const backSuccessByEmailPage = (req, res) => {
100 page: 'back-email-success', 100 page: 'back-email-success',
101 title: '找回密码-通过邮箱' 101 title: '找回密码-通过邮箱'
102 }, { 102 }, {
103 - backUrl: helpers.urlFormat('/passport/back/email'), 103 + // backUrl: helpers.urlFormat('/passport/back/email'),
104 headerText: '找回密码', 104 headerText: '找回密码',
105 isPassportPage: true, 105 isPassportPage: true,
106 backEmailSuccess: true, 106 backEmailSuccess: true,
@@ -145,7 +145,7 @@ const indexMobilePage = (req, res, next) => { @@ -145,7 +145,7 @@ const indexMobilePage = (req, res, next) => {
145 page: 'back-mobile', 145 page: 'back-mobile',
146 title: '找回密码-通过手机号' 146 title: '找回密码-通过手机号'
147 }, { 147 }, {
148 - backUrl: SIGN_IN, 148 + // backUrl: SIGN_IN,
149 headerText: '找回密码', 149 headerText: '找回密码',
150 isPassportPage: true, 150 isPassportPage: true,
151 backMobile: true, 151 backMobile: true,
@@ -203,7 +203,7 @@ const verifyCodeByMobilePage = (req, res) => { @@ -203,7 +203,7 @@ const verifyCodeByMobilePage = (req, res) => {
203 page: 'back-code', 203 page: 'back-code',
204 title: '找回密码-通过手机号' 204 title: '找回密码-通过手机号'
205 }, { 205 }, {
206 - backUrl: helpers.urlFormat('/passport/back/mobile'), 206 + // backUrl: helpers.urlFormat('/passport/back/mobile'),
207 headerText: '找回密码', 207 headerText: '找回密码',
208 isPassportPage: true, 208 isPassportPage: true,
209 backCode: true, 209 backCode: true,
@@ -261,7 +261,7 @@ const setNewPasswordByMobilePage = (req, res) => { @@ -261,7 +261,7 @@ const setNewPasswordByMobilePage = (req, res) => {
261 page: 'back-new-password', 261 page: 'back-new-password',
262 title: '找回密码-输入新密码' 262 title: '找回密码-输入新密码'
263 }, { 263 }, {
264 - backUrl: SIGN_IN, 264 + // backUrl: SIGN_IN,
265 headerText: '找回密码', 265 headerText: '找回密码',
266 isPassportPage: true, 266 isPassportPage: true,
267 backNewPwd: true, 267 backNewPwd: true,
  1 +/* eslint no-unused-vars: ["error", { "args": "none" }] */
1 /** 2 /**
2 * 登录 3 * 登录
3 * @author: Bi Kai<kai.bi@yoho.cn> 4 * @author: Bi Kai<kai.bi@yoho.cn>
@@ -93,6 +94,7 @@ const local = { @@ -93,6 +94,7 @@ const local = {
93 backUrl: 'javascript:history.go(-1)', // eslint-disable-line 94 backUrl: 'javascript:history.go(-1)', // eslint-disable-line
94 showHeaderImg: true, // 控制显示头部图片 95 showHeaderImg: true, // 控制显示头部图片
95 isPassportPage: true, // 模板中模块标识 96 isPassportPage: true, // 模板中模块标识
  97 + smsLoginUrl: '/passport/sms_login',
96 registerUrl: '/passport/reg/index', // 注册的URL链接 98 registerUrl: '/passport/reg/index', // 注册的URL链接
97 aliLoginUrl: '/passport/login/alipay', // 支付宝快捷登录的URL链接 99 aliLoginUrl: '/passport/login/alipay', // 支付宝快捷登录的URL链接
98 weiboLoginUrl: '/passport/login/sina', // 微博登录的URL链接 100 weiboLoginUrl: '/passport/login/sina', // 微博登录的URL链接
  1 +/* eslint no-unused-vars: ["error", { "args": "none" }] */
  2 +'use strict';
  3 +const helpers = global.yoho.helpers;
  4 +const cookie = global.yoho.cookie;
  5 +const RegService = require('../models/reg-service');
  6 +const PhoneService = require('../models/phone-service');
  7 +const AuthHelper = require('../models/auth-helper');
  8 +
  9 +// constrant
  10 +const CODE_REQUIRED = '请输入校验码';
  11 +const PASSWORD_REQUIRED = '请输入密码';
  12 +const PASSWORD_LENGTH_ERROR = '密码6-20位,请重新输入';
  13 +const BAD_PASSWORD = '密码格式不正确';
  14 +const TOO_MANY = '请求太频繁';
  15 +const LOGIN_SUCCSS = '登录成功';
  16 +const VERIFY_ERROR = '校验失败';
  17 +
  18 +exports.beforeIn = (req, res, next) => {
  19 + res.set({
  20 + 'Cache-Control': 'no-cache, no-store, must-revalidate',
  21 + Pragma: 'no-cache',
  22 + Expires: 0
  23 + });
  24 +
  25 + if (!req.xhr && req.user.uid) {
  26 + return res.redirect(req.cookies.refer);
  27 + }
  28 +
  29 + next();
  30 +};
  31 +
  32 +// 短信登录 第一步: 展现页面
  33 +const _step1 = (req, res, next) => {
  34 + let template = 'sms/login';
  35 + let viewData = {
  36 + module: 'passport',
  37 + page: 'sms-login',
  38 + title: '手机短信登录',
  39 + isPassportPage: true,
  40 + headerText: '手机号码快捷登录',
  41 + areaCode: '+86', // 默认的区号
  42 + countrys: RegService.getAreaData() // 地区信息列表
  43 + };
  44 +
  45 + res.render(template, viewData);
  46 +};
  47 +
  48 +// 短信登录 第二步: 输入 校验码
  49 +const _step2 = (req, res, next) => {
  50 + const mobile = req.session.smsLogin.mobile;
  51 + const area = req.session.smsLogin.area;
  52 + const interval = req.session.smsLogin.interval;
  53 +
  54 + const template = 'sms/check';
  55 + const viewData = {
  56 + module: 'passport',
  57 + page: 'sms-check',
  58 + title: '手机短信登录',
  59 + isPassportPage: true,
  60 + headerText: '手机号码快捷登录',
  61 + canResend: interval < Date.now(),
  62 + mobile,
  63 + area
  64 + };
  65 +
  66 + res.render(template, viewData);
  67 +};
  68 +
  69 +// 短信登录 第三步: 设置密码 (针对 改手机未注册用户)
  70 +const _step3 = (req, res, next) => {
  71 + const template = 'sms/password';
  72 + const viewData = {
  73 + module: 'passport',
  74 + page: 'sms-password',
  75 + title: '设置密码',
  76 + isPassportPage: true,
  77 + headerText: '设置密码'
  78 + };
  79 +
  80 + res.render(template, viewData);
  81 +};
  82 +
  83 +// 短信 登录
  84 +exports.loginPage = (req, res, next) => {
  85 + let step = Number(req.query.step) || 1;
  86 + let smsLoginStep = req.session.smsLoginStep || 1;
  87 +
  88 + if (step === 2 && smsLoginStep !== 2) {
  89 + return res.redirect(req.path);
  90 + }
  91 +
  92 + if (step === 3 && smsLoginStep !== 3) {
  93 + return res.redirect(req.path);
  94 + }
  95 +
  96 + switch (step) {
  97 + case 2:
  98 + _step2(req, res, next);
  99 + break;
  100 + case 3:
  101 + _step3(req, res, next);
  102 + break;
  103 + case 1:
  104 + default:
  105 + _step1(req, res, next);
  106 + }
  107 +};
  108 +
  109 +exports.tokenBefore = (req, res, next) => {
  110 + let area = req.query.area = (req.query.area || '').trim();
  111 + let mobile = req.query.mobile = (req.query.mobile || '').trim();
  112 +
  113 + if (!req.xhr) {
  114 + return next(404);
  115 + }
  116 +
  117 + if (req.session.smsLogin && req.session.smsLogin.interval > Date.now()) {
  118 + return res.json({
  119 + code: 429,
  120 + message: TOO_MANY
  121 + });
  122 + }
  123 +
  124 +
  125 + if ([area, mobile].some(val => val === '')) {
  126 + return res.json({
  127 + code: 401,
  128 + message: '请求参数,无法处理'
  129 + });
  130 + }
  131 +
  132 + next();
  133 +};
  134 +
  135 +// AJAX 获取验证码
  136 +exports.token = (req, res, next) => {
  137 + let area = req.query.area;
  138 + let mobile = req.query.mobile;
  139 +
  140 + PhoneService.sendSMS(mobile, area, 1).then(result => {
  141 + if (result.code === 200) {
  142 + req.session.smsLogin = {
  143 + interval: Date.now() + 60 * 1000, // 重发验证码 间隔: 60s
  144 + area,
  145 + mobile
  146 + };
  147 + req.session.smsLoginStep = 2; // 进入短信登录 step2
  148 +
  149 + result.redirect = '/passport/sms_login?step=2';
  150 + res.json(result);
  151 + return;
  152 + }
  153 +
  154 + res.json(result);
  155 + });
  156 +};
  157 +
  158 +exports.checkBefore = (req, res, next) => {
  159 + let code = req.query.code = (req.query.code || '').trim();
  160 +
  161 + if (!req.xhr && req.session.smsLoginStep !== 2) {
  162 + return next(404);
  163 + }
  164 +
  165 + if (!code) {
  166 + return res.json({
  167 + code: 404,
  168 + message: CODE_REQUIRED
  169 + });
  170 + }
  171 +
  172 + next();
  173 +};
  174 +
  175 +// AJAX 校验验证码 in step2
  176 +exports.check = (req, res, next) => {
  177 + const code = req.query.code;
  178 + const mobile = req.session.smsLogin.mobile;
  179 + const area = req.session.smsLogin.area;
  180 + const shopping_key = cookie.getShoppingKey(req); // eslint-disable-line
  181 +
  182 +
  183 + Promise.all([
  184 + PhoneService.checkUserPhoneExist(mobile, area),
  185 + PhoneService.verifySMS(mobile, area, code, 1)
  186 + ])
  187 + .then(result => {
  188 + let r1 = result[0] || {};
  189 + let r2 = result[1] || {};
  190 + let redirect;
  191 +
  192 + // 验证码 校验异常
  193 + if (r2.code !== 200) {
  194 + res.json(r2);
  195 + return;
  196 + }
  197 +
  198 + // 检测 手机号 是否注册 异常
  199 + if (r1.code !== 200) {
  200 + res.json(r1);
  201 + return;
  202 + }
  203 +
  204 + // 校验失败
  205 + if (r2.data.is_pass !== 'Y') {
  206 + res.json({
  207 + code: 401,
  208 + message: VERIFY_ERROR
  209 + });
  210 +
  211 + return;
  212 + }
  213 +
  214 + // 手机号码 没注册
  215 + if (r1.data.is_register !== 'Y') {
  216 + redirect = '/passport/sms_login?step=3';
  217 + req.session.smsLoginStep = 3;
  218 +
  219 + res.json({
  220 + code: 200,
  221 + redirect
  222 + });
  223 +
  224 + return;
  225 + }
  226 +
  227 + // 手机号码已注册 --> 直接登录
  228 + PhoneService.autoSignin({
  229 + profile: mobile,
  230 + code: r2.data.code,
  231 + area,
  232 + shopping_key
  233 + })
  234 + .then(info => {
  235 + if (info.code !== 200) {
  236 + return Promise.reject(info);
  237 + }
  238 +
  239 + return AuthHelper.syncUserSession(info.data.uid, req, res);
  240 + })
  241 + .then(() => {
  242 + res.json({
  243 + code: 200,
  244 + message: LOGIN_SUCCSS,
  245 + redirect: req.cookies.refer
  246 + });
  247 +
  248 + delete req.session.smsLogin;
  249 + delete req.session.smsLoginStep;
  250 + })
  251 + .catch(error => {
  252 + res.json(error);
  253 + });
  254 +
  255 + })
  256 + .catch(next);
  257 +};
  258 +
  259 +// AJAX 短信登录 设置密码 in step3
  260 +exports.password = (req, res, next) => {
  261 + if (req.session.smsLoginStep !== 3) {
  262 + return next();
  263 + }
  264 +
  265 +
  266 + let data = {
  267 + code: '400',
  268 + message: BAD_PASSWORD
  269 + };
  270 +
  271 + let smsLogin = req.session.smsLogin || {};
  272 + let mobile = smsLogin.mobile;
  273 + let area = smsLogin.area;
  274 + let password = (req.body.password || '').trim();
  275 +
  276 + if (!password) {
  277 + data.message = PASSWORD_REQUIRED;
  278 + return res.json(data);
  279 + }
  280 +
  281 + if (password.length < 6 || password.length > 20) {
  282 + data.message = PASSWORD_LENGTH_ERROR;
  283 + return res.json(data);
  284 + }
  285 +
  286 + if (!helpers.verifyPassword(password)) {
  287 + return res.json(data);
  288 + }
  289 +
  290 + // 购物车key
  291 + let shoppingKey = cookie.getShoppingKey(req);
  292 +
  293 +
  294 + RegService.regMobileAes(area, mobile, password, shoppingKey).then(result => {
  295 + if (!result.code || result.code !== 200) {
  296 + return Promise.reject(result);
  297 + }
  298 + if (!result.data || !result.data.uid) {
  299 + return Promise.reject(result);
  300 + }
  301 +
  302 + return AuthHelper.syncUserSession(result.data.uid, req, res);
  303 + }).then(() => {
  304 + res.json({
  305 + code: 200,
  306 + message: LOGIN_SUCCSS,
  307 + redirect: req.cookies.refer
  308 + });
  309 + delete req.session.smsLogin;
  310 + delete req.session.smsLoginStep;
  311 + }).catch(next);
  312 +
  313 +
  314 +};
  1 +/* eslint no-unused-vars: ["error", { "args": "none" }] */
  2 +'use strict';
  3 +const API = global.yoho.API;
  4 +
  5 +class PhoneService {
  6 + // 校验 手机 是否 已注册
  7 + // http://git.yoho.cn/yoho-documents/api-interfaces/blob/master/个人中心/验证码登录/校验是否是注册用户.md
  8 + static checkUserPhoneExist(mobile, area) {
  9 + return API.get('', {
  10 + method: 'app.passport.checkUserExist',
  11 + mobile,
  12 + area
  13 + });
  14 + }
  15 +
  16 + // 手机号 自动登录
  17 + // http://git.yoho.cn/yoho-documents/api-interfaces/blob/master/个人中心/验证码登录/手机号自动登录.md
  18 + static autoSignin(param) {
  19 + return API.get('', {
  20 + method: 'app.passport.autoSignin',
  21 + profile: param.profile,
  22 + area: param.area,
  23 + code: param.code,
  24 + shopping_key: param.shopping_key
  25 + });
  26 + }
  27 +
  28 + // 发送 验证码
  29 + // http://git.yoho.cn/yoho-documents/api-interfaces/blob/master/个人中心/验证码登录/发送验证码.md
  30 + static sendSMS(mobile, area, type) {
  31 + if (process.env.NODE_ENV === 'development') {
  32 + return new Promise((resolve, reject) => {
  33 + return resolve({
  34 + alg: 'SALT_MD5',
  35 + code: 200,
  36 + data: {},
  37 + md5: '6d729d4b35f10fc73531210bd7ecff91',
  38 + message: '发送成功.'
  39 + });
  40 + });
  41 + }
  42 +
  43 + return API.get('', {
  44 + method: 'app.message.sendSms',
  45 + mobile,
  46 + area,
  47 + type
  48 + });
  49 + }
  50 +
  51 + // 校验 验证码
  52 + // http://git.yoho.cn/yoho-documents/api-interfaces/blob/master/个人中心/验证码登录/验证验证码.md
  53 + static verifySMS(mobile, area, code, type) {
  54 + if (process.env.NODE_ENV === 'development') {
  55 + return new Promise((resolve, reject) => {
  56 + return resolve({
  57 + alg: 'SALT_MD5',
  58 + code: 200,
  59 + data: {
  60 + is_pass: 'Y'
  61 + },
  62 + md5: '6d729d4b35f10fc73531210bd7ecff91',
  63 + message: '发送成功.'
  64 + });
  65 + });
  66 + }
  67 +
  68 + return API.get('', {
  69 + method: 'app.message.verifySmsCode',
  70 + mobile,
  71 + area,
  72 + code,
  73 + type
  74 + });
  75 + }
  76 +}
  77 +
  78 +module.exports = PhoneService;
@@ -12,6 +12,7 @@ const login = require(cRoot + '/login'); @@ -12,6 +12,7 @@ const login = require(cRoot + '/login');
12 const back = require(cRoot + '/back'); 12 const back = require(cRoot + '/back');
13 const bind = require(cRoot + '/bind'); 13 const bind = require(cRoot + '/bind');
14 const reg = require(cRoot + '/reg'); 14 const reg = require(cRoot + '/reg');
  15 +const smsLogin = require(cRoot + '/sms');
15 16
16 17
17 const router = express.Router(); // eslint-disable-line 18 const router = express.Router(); // eslint-disable-line
@@ -33,6 +34,17 @@ router.get('/passport/international', login.common.beforeLogin, login.local.inte @@ -33,6 +34,17 @@ router.get('/passport/international', login.common.beforeLogin, login.local.inte
33 // 本地登录 34 // 本地登录
34 router.post('/passport/login/auth', login.local.login); 35 router.post('/passport/login/auth', login.local.login);
35 36
  37 +// SMS 短信
  38 +router.use('/passport/sms_login', login.common.beforeLogin, smsLogin.beforeIn);
  39 +router.get('/passport/sms_login', smsLogin.loginPage);
  40 +router.get('/passport/sms_login/token.json',
  41 + smsLogin.tokenBefore,
  42 + smsLogin.token); // only ajax;
  43 +router.get('/passport/sms_login/check.json',
  44 + smsLogin.checkBefore,
  45 + smsLogin.check); // only ajax
  46 +router.post('/passport/sms_login/password.json', smsLogin.password);
  47 +
36 // 微信登录 48 // 微信登录
37 router.get('/passport/login/wechat', login.common.beforeLogin, login.wechat.login); 49 router.get('/passport/login/wechat', login.common.beforeLogin, login.wechat.login);
38 router.get('/passport/login/wechat/callback', login.wechat.callback); 50 router.get('/passport/login/wechat/callback', login.wechat.callback);
@@ -10,7 +10,7 @@ @@ -10,7 +10,7 @@
10 </div> 10 </div>
11 <span id="btn-login" class="btn btn-login disable">登录</span> 11 <span id="btn-login" class="btn btn-login disable">登录</span>
12 <p class="op-container"> 12 <p class="op-container">
13 - <a class="go-register" href={{registerUrl}}>免费注册</a> 13 + <a class="sms-login" href={{smsLoginUrl}}>手机号码快捷登录</a>
14 <span id="forget-pwd" class="forget-pwd">忘记密码</span> 14 <span id="forget-pwd" class="forget-pwd">忘记密码</span>
15 </p> 15 </p>
16 <div class="third-party-login"> 16 <div class="third-party-login">
@@ -22,6 +22,10 @@ @@ -22,6 +22,10 @@
22 </div> 22 </div>
23 </div> 23 </div>
24 <a class="international" href={{internationalUrl}}>International Customer</a> 24 <a class="international" href={{internationalUrl}}>International Customer</a>
  25 + <div class="go-register">
  26 + <i class="iconfont">&#xe610;</i>
  27 + <a href={{registerUrl}}>注册Yoho!Family</a>
  28 + </div>
25 <div class="login-tip"> 29 <div class="login-tip">
26 <div class="info-icon"></div> 30 <div class="info-icon"></div>
27 Yoho!Family账号可登录Yoho!Buy有货 31 Yoho!Family账号可登录Yoho!Buy有货
  1 +<div class="sms-login sms-login-check passport-page yoho-page">
  2 + {{> passport/header}}
  3 + <div class="content">
  4 + <p class="sms-login-msg">验证码已发至&nbsp;<span class="tel">+{{area}} {{mobile}}</span></p>
  5 + <div class="input-container input-group sms-input row">
  6 + <input id="sms-code" class="input" type="text" placeholder="验证码">
  7 + <div class="input-addon">
  8 + <button type="button" id="resend-sms">重发验证码</button>
  9 + </div>
  10 + <button class="clear-input" type="button"></button>
  11 + </div>
  12 + <button id="btn-next" class="btn btn-next disable row" type="button">登录</button>
  13 + </div>
  14 + <input type="hidden" name="mobile" id="mobile" value="{{mobile}}">
  15 + <input type="hidden" name="area" id="area" value="{{area}}">
  16 +</div>
  17 +<script>
  18 + var canResend = {{canResend}};
  19 +</script>
  1 +<div class="sms-login-page passport-page yoho-page">
  2 + {{> passport/header}}
  3 + <div class="content">
  4 + {{> passport/country_list}}
  5 + <div class="input-container phone-container row has-clear">
  6 + <span id="area-code" class="area-code">{{areaCode}}</span>
  7 + <input id="phone-num" class="input phone-num" type="text" placeholder="手机号">
  8 + <button class="clear-input" type="button"></button>
  9 + </div>
  10 + <button id="btn-next" class="btn btn-next disable row" disabled>获取短信验证码</button>
  11 + </div>
  12 +</div>
  1 +<div class="sms-login passport-page yoho-page">
  2 + {{> passport/header}}
  3 + <div class="content">
  4 + <p class="sms-login-msg small">你以后还可以使用手机号码 + 密码的形式登录有货哦!</p>
  5 + <div class="input-container row has-eye">
  6 + <input id="pwd" class="pwd input" type="text" placeholder="密码">
  7 + <div class="eye" id="eye"></div>
  8 + </div>
  9 + <span id="btn-next" class="btn btn-next disable row">确定</span>
  10 + </div>
  11 +</div>
@@ -14,10 +14,8 @@ module.exports = { @@ -14,10 +14,8 @@ module.exports = {
14 port: 6001, 14 port: 6001,
15 siteUrl: '//m.yohobuy.com', 15 siteUrl: '//m.yohobuy.com',
16 domains: { 16 domains: {
17 - // api: 'http://devapi.yoho.cn:58078/',  
18 - // service: 'http://devservice.yoho.cn:58077/'  
19 - api: 'http://api.yoho.cn/',  
20 - service: 'http://service.yoho.cn/', 17 + api: 'http://api-test3.yohops.com:9999/',
  18 + service: 'http://service-test3.yohops.com:9999/',
21 liveApi: 'http://testapi.live.yohops.com:9999/' 19 liveApi: 'http://testapi.live.yohops.com:9999/'
22 }, 20 },
23 subDomains: { 21 subDomains: {
@@ -93,7 +91,7 @@ if (isProduction) { @@ -93,7 +91,7 @@ if (isProduction) {
93 useOneapm: true, 91 useOneapm: true,
94 useCache: true, 92 useCache: true,
95 interfaceShunt: { 93 interfaceShunt: {
96 - open: true, 94 + open: false,
97 url: 'http://123.206.2.55/strategy' 95 url: 'http://123.206.2.55/strategy'
98 } 96 }
99 }); 97 });
1 -{{#data}}  
2 - <div class="banner-center"> 1 +<div class="banner-center banner-center-swiper">
  2 + {{#if singleOne}}
  3 + {{#data}}
  4 + <div class="banner-list">
3 <a href="{{url}}"> 5 <a href="{{url}}">
4 - <img class="lazy" data-original="{{image src 640 200}}" alt=""> 6 + <img src="{{image src 640 200}}" alt="">
5 </a> 7 </a>
6 </div> 8 </div>
7 -{{/data}}  
  9 + {{/data}}
  10 + {{else}}
  11 + <ul class="banner-list swiper-wrapper clearfix">
  12 + {{#data}}
  13 + <li class="swiper-slide">
  14 + <a href="{{url}}">
  15 + <img src="{{image src 640 200}}" alt="">
  16 + </a>
  17 + </li>
  18 + {{/data}}
  19 + </ul>
  20 + {{/if}}
  21 + <div class="swiper-pagination">
  22 + <div class="pagination-inner">
  23 + </div>
  24 + </div>
  25 +</div>
1 { 1 {
2 "name": "m-yohobuy-node", 2 "name": "m-yohobuy-node",
3 - "version": "4.9.20", 3 + "version": "4.9.21",
4 "private": true, 4 "private": true,
5 "description": "A New Yohobuy Project With Express", 5 "description": "A New Yohobuy Project With Express",
6 "repository": { 6 "repository": {
@@ -17,6 +17,7 @@ var prefixes = 'webkit moz ms o'.split(' '); //各浏览器前缀 @@ -17,6 +17,7 @@ var prefixes = 'webkit moz ms o'.split(' '); //各浏览器前缀
17 var requestAnimationFrame = window.requestAnimationFrame; 17 var requestAnimationFrame = window.requestAnimationFrame;
18 var cancelAnimationFrame = window.cancelAnimationFrame; 18 var cancelAnimationFrame = window.cancelAnimationFrame;
19 19
  20 +var site_url = STATIC_RESOURCE_PATH;
20 var $btn_play; 21 var $btn_play;
21 var video_width = 375; 22 var video_width = 375;
22 var video_height = 667; 23 var video_height = 667;
@@ -284,9 +285,12 @@ function get_websocket_server(type) { @@ -284,9 +285,12 @@ function get_websocket_server(type) {
284 var arr = data.data[0].split(':'); 285 var arr = data.data[0].split(':');
285 var ip = arr[0]; 286 var ip = arr[0];
286 var port = arr[1]; 287 var port = arr[1];
  288 + var protocol = 'ws'
  289 + // var protocol = location.protocol === 'https:' ? 'wss' :'ws'
287 290
288 if (is_live) { 291 if (is_live) {
289 - ip = 'ws://' + ip; 292 +
  293 + ip = protocol + '://' + ip;
290 link_to_websocket_server(ip, port); 294 link_to_websocket_server(ip, port);
291 } 295 }
292 } 296 }
@@ -670,7 +674,7 @@ function insert_like(obj) { @@ -670,7 +674,7 @@ function insert_like(obj) {
670 } 674 }
671 } 675 }
672 now_like_nums = num; 676 now_like_nums = num;
673 - if (now_like_nums > 100000) { 677 + if (now_like_nums > 10000) {
674 $('#like_num').text((now_like_nums / 10000).toFixed(1) + '万'); 678 $('#like_num').text((now_like_nums / 10000).toFixed(1) + '万');
675 } else { 679 } else {
676 $('#like_num').text(now_like_nums); 680 $('#like_num').text(now_like_nums);
@@ -391,19 +391,9 @@ $(document).on('click', '.s-footer .checkbox', function() { @@ -391,19 +391,9 @@ $(document).on('click', '.s-footer .checkbox', function() {
391 /* 391 /*
392 * 数据提交 392 * 数据提交
393 */ 393 */
394 -$('.s-submit').data('isClick', true);  
395 $(document).on('click', '.s-submit', function() { 394 $(document).on('click', '.s-submit', function() {
396 var obj = changeSuccess(), 395 var obj = changeSuccess(),
397 FAILURE_CAUSE; 396 FAILURE_CAUSE;
398 - var $that = $(this);  
399 -  
400 - // 存cookie 记录状态  
401 - localStorage.setItem(STUDENTCOOKIES, JSON.stringify(obj.data));  
402 -  
403 - if ($that.data('isClick') === false) {  
404 - return;  
405 - }  
406 - $that.data('isClick', false);  
407 397
408 if (!obj.msg) { 398 if (!obj.msg) {
409 $.ajax({ 399 $.ajax({
@@ -422,15 +412,15 @@ $(document).on('click', '.s-submit', function() { @@ -422,15 +412,15 @@ $(document).on('click', '.s-submit', function() {
422 } 412 }
423 }, true); 413 }, true);
424 } 414 }
  415 +
425 location.href = data.data; 416 location.href = data.data;
426 } else { 417 } else {
427 - $that.data('isClick', true);  
428 tip.show(data.message); 418 tip.show(data.message);
429 } 419 }
  420 +
430 }); 421 });
431 } else { 422 } else {
432 tip.show(obj.msg); 423 tip.show(obj.msg);
433 - $that.data('isClick', true);  
434 if (obj.msg.indexOf('字段为空') > -1) { 424 if (obj.msg.indexOf('字段为空') > -1) {
435 FAILURE_CAUSE = 1; 425 FAILURE_CAUSE = 1;
436 } else if (obj.msg.indexOf('认证协议') > -1) { 426 } else if (obj.msg.indexOf('认证协议') > -1) {
@@ -108,6 +108,18 @@ if ($('.banner-swiper').find('li').size() > 1) { @@ -108,6 +108,18 @@ if ($('.banner-swiper').find('li').size() > 1) {
108 }); 108 });
109 } 109 }
110 110
  111 +// single_image的轮播
  112 +if ($('.banner-center-swiper').find('li').size() > 1) {
  113 + new Swiper('.banner-center-swiper', {
  114 + loop: true,
  115 + autoplay: 3000,
  116 + autoplayDisableOnInteraction: false,
  117 + paginationClickable: true,
  118 + slideElement: 'li',
  119 + pagination: '.banner-center .pagination-inner'
  120 + });
  121 +}
  122 +
111 // 热门品牌滑动 123 // 热门品牌滑动
112 new Swiper('.brands-swiper', { 124 new Swiper('.brands-swiper', {
113 grabCursor: true, 125 grabCursor: true,
@@ -101,6 +101,7 @@ function bindAvatar(dom) { @@ -101,6 +101,7 @@ function bindAvatar(dom) {
101 avatarKey = dom.index(); 101 avatarKey = dom.index();
102 102
103 if (!dom.hasClass('swiper-slide-active')) { 103 if (!dom.hasClass('swiper-slide-active')) {
  104 +
104 // if (avatarKey >= (2 * bannerLen + 1)) { 105 // if (avatarKey >= (2 * bannerLen + 1)) {
105 // avatarSwiperClone && avatarSwiperClone.slideTo(bannerLen + 1, 0); 106 // avatarSwiperClone && avatarSwiperClone.slideTo(bannerLen + 1, 0);
106 // avatarSwiper.slideTo(bannerLen + 1, 0); 107 // avatarSwiper.slideTo(bannerLen + 1, 0);
@@ -109,8 +110,7 @@ function bindAvatar(dom) { @@ -109,8 +110,7 @@ function bindAvatar(dom) {
109 // avatarSwiper.slideTo(2 * bannerLen - (bannerLen - avatarKey), 0); 110 // avatarSwiper.slideTo(2 * bannerLen - (bannerLen - avatarKey), 0);
110 // } else { 111 // } else {
111 // avatarSwiperClone && avatarSwiperClone.slideTo(avatarKey, 200); 112 // avatarSwiperClone && avatarSwiperClone.slideTo(avatarKey, 200);
112 - avatarSwiper.slideTo(avatarKey, 200);  
113 - 113 + // avatarSwiper.slideTo(avatarKey, 200);
114 // } 114 // }
115 115
116 return false; 116 return false;
  1 +var tip = require('plugin/tip');
  2 +
  3 +var $resendBtn,
  4 + $nextBtn,
  5 + $smsCode,
  6 + $resetBtn,
  7 + mobile, area;
  8 +
  9 +var page = {
  10 + disableAjax: false,
  11 +
  12 + time: 60,
  13 + resendText: '重发验证码',
  14 + timerId: null,
  15 + init: function() {
  16 + this.domInit();
  17 + this.bindEvents();
  18 + if (!window.canResend) {
  19 + this.countDown();
  20 + }
  21 + },
  22 +
  23 +
  24 + domInit: function() {
  25 + $resendBtn = $('#resend-sms');
  26 + $nextBtn = $('#btn-next');
  27 + $resetBtn = $('.clear-input');
  28 + $smsCode = $('#sms-code');
  29 + mobile = $('#mobile').val();
  30 + area = $('#area').val();
  31 + },
  32 +
  33 +
  34 + bindEvents: function() {
  35 + var self = this;
  36 +
  37 + $resendBtn.on('click', function() {
  38 + self.resendSMS();
  39 + });
  40 +
  41 + $smsCode.on('input', function() {
  42 + var hasVal = Boolean($.trim(this.value));
  43 +
  44 + $nextBtn.trigger('toggleDisable', !hasVal);
  45 + $resetBtn.toggle(hasVal);
  46 + });
  47 +
  48 + $nextBtn.on('click', function() {
  49 + self.submit();
  50 + });
  51 +
  52 + $resetBtn.on('click', function() {
  53 + $smsCode.val('');
  54 + $resetBtn.hide();
  55 + $nextBtn.trigger('toggleDisable');
  56 + });
  57 +
  58 + $nextBtn.on('toggleDisable', function(event, bool) {
  59 + if (bool === void 0) {
  60 + bool = true;
  61 + }
  62 +
  63 + $nextBtn.toggleClass('disable', bool);
  64 + $nextBtn.prop('disabled', bool);
  65 + });
  66 + },
  67 +
  68 + countDown: function() {
  69 + var self = this;
  70 + var second = this.time;
  71 +
  72 + if (this.timerId) {
  73 + return;
  74 + }
  75 +
  76 + $resendBtn.prop('disabled', true);
  77 + $resendBtn.text('重新发送(' + second + ')');
  78 + this.timerId = setInterval(function() {
  79 + var txt = self.resendText;
  80 +
  81 + second = second - 1;
  82 +
  83 + if (second < 0) {
  84 + clearInterval(self.timerId);
  85 + self.timerId = null;
  86 + $resendBtn.prop('disabled', false);
  87 + } else {
  88 + txt = '重新发送(' + second + '秒)';
  89 + }
  90 +
  91 + $resendBtn.text(txt);
  92 + }, 1000);
  93 +
  94 + },
  95 +
  96 +
  97 + resendSMS: function() {
  98 + var self = this;
  99 +
  100 + if ($resendBtn.prop('disabled')) {
  101 + return;
  102 + }
  103 +
  104 + $.get('/passport/sms_login/token.json', {
  105 + area: area,
  106 + mobile: mobile,
  107 + })
  108 + .done(function(res) {
  109 + if (res.code === 200) {
  110 + self.countDown();
  111 + return;
  112 + }
  113 +
  114 + tip.show(res.message);
  115 + })
  116 + .fail(function() {
  117 + tip.show('出错啦~休息一下');
  118 + });
  119 + },
  120 +
  121 + submit: function() {
  122 + var code = $.trim($smsCode.val());
  123 +
  124 + if ($nextBtn.prop('disabled')) {
  125 + return;
  126 + }
  127 +
  128 + $nextBtn.prop('disabled', true);
  129 + $.get('/passport/sms_login/check.json', {
  130 + code: code
  131 + })
  132 + .done(function(res) {
  133 + if (res.code === 200) {
  134 + // $nextBtn.off();
  135 + location.href = res.redirect;
  136 + return;
  137 + }
  138 +
  139 + tip.show(res.message);
  140 + })
  141 + .fail(function() {
  142 + tip.show('出错了, 请重试');
  143 + })
  144 + .always(function() {
  145 + $nextBtn.prop('disabled', false);
  146 + });
  147 + }
  148 +};
  149 +
  150 +$(function() {
  151 + page.init();
  152 +});
  1 +'use strict';
  2 +
  3 +var tip = require('plugin/tip');
  4 +var api = require('./api');
  5 +
  6 +var $countrySelect,
  7 + $areaCode,
  8 + $nextBtn,
  9 + $resetBtn,
  10 + $phoneNum;
  11 +
  12 +var page = {
  13 + init: function() {
  14 + this.domInit();
  15 + this.bindEvent();
  16 + },
  17 + domInit: function() {
  18 + $countrySelect = $('#country-select');
  19 + $areaCode = $('#area-code');
  20 + $nextBtn = $('#btn-next');
  21 + $phoneNum = $('#phone-num');
  22 + $resetBtn = $('.clear-input');
  23 + },
  24 + bindEvent: function() {
  25 + var self = this;
  26 +
  27 + $countrySelect.on('change', function() {
  28 + $areaCode.text(this.value);
  29 + });
  30 + $phoneNum.on('input', function() {
  31 + self.toggleNextBtn();
  32 + });
  33 +
  34 + $nextBtn.on('click', function() {
  35 + self.goNext();
  36 + });
  37 +
  38 + $resetBtn.on('click', function() {
  39 + $phoneNum.val('');
  40 + $nextBtn
  41 + .prop('disabled', true)
  42 + .toggleClass('disable', true);
  43 + $resetBtn.hide();
  44 + });
  45 + },
  46 +
  47 + // 切换$nextBtn disable状态
  48 + toggleNextBtn: function() {
  49 + var bool = Boolean($.trim($phoneNum.val()));
  50 +
  51 + $nextBtn
  52 + .toggleClass('disable', !bool)
  53 + .prop('disabled', !bool);
  54 +
  55 + $resetBtn.toggle(bool);
  56 + },
  57 +
  58 + // 提交按钮
  59 + goNext: function() {
  60 + var areaCode = $countrySelect.val();
  61 + var phone = $.trim($phoneNum.val());
  62 +
  63 + if ($nextBtn.prop('disabled')) {
  64 + return;
  65 + }
  66 +
  67 + if (!api.phoneRegx[areaCode].test(phone)) {
  68 + tip.show('手机号码格式不正确, 请重新输入');
  69 + return;
  70 + }
  71 +
  72 + $nextBtn.prop('disabled', true);
  73 + $.get('/passport/sms_login/token.json', {
  74 + area: areaCode.replace('+', ''),
  75 + mobile: phone
  76 + })
  77 + .done(function(data) {
  78 + if (data.code === 200) {
  79 + // $nextBtn.off();
  80 + location.href = data.redirect;
  81 + } else {
  82 + tip.show(data.message);
  83 + }
  84 + })
  85 + .fail(function() {
  86 + tip.show('出错了, 请重试');
  87 + })
  88 + .always(function() {
  89 + $nextBtn.prop('disabled', false);
  90 + });
  91 +
  92 +
  93 +
  94 + }
  95 +};
  96 +
  97 +$(function() {
  98 + page.init();
  99 +});
  1 +var tip = require('plugin/tip');
  2 +
  3 +var $eyeBtn,
  4 + $pwd,
  5 + $nextBtn;
  6 +
  7 +var page = {
  8 + init: function() {
  9 + this.domInit();
  10 + this.bindEvent();
  11 + },
  12 + domInit: function() {
  13 + $eyeBtn = $('#eye');
  14 + $pwd = $('#pwd');
  15 + $nextBtn = $('#btn-next');
  16 + },
  17 + bindEvent: function() {
  18 + var self = this;
  19 +
  20 + $eyeBtn.on('click', function() {
  21 + self.togglePassword();
  22 + });
  23 +
  24 + $nextBtn.on('click', function() {
  25 + self.setPasswordAndLogin();
  26 + });
  27 +
  28 + $pwd.on('input', function() {
  29 + var bool = Boolean($.trim(this.value));
  30 +
  31 + $nextBtn
  32 + .toggleClass('disable', !bool)
  33 + .prop('disabled', !bool);
  34 + });
  35 + },
  36 +
  37 + togglePassword: function() {
  38 + var bool = $eyeBtn.hasClass('close');
  39 +
  40 + $eyeBtn.toggleClass(function() {
  41 + $pwd.attr('type', !bool ? 'password' : 'text');
  42 + return 'close';
  43 + }, !bool);
  44 + },
  45 +
  46 + setPasswordAndLogin: function() {
  47 + var password = $.trim($pwd.val());
  48 +
  49 + if ($nextBtn.prop('disabled')) {
  50 + return;
  51 + }
  52 +
  53 + $nextBtn.prop('disabled', true);
  54 + $.post('/passport/sms_login/password.json', {
  55 + password: password
  56 + })
  57 + .done(function(res) {
  58 + if (res.code === 200) {
  59 + // $nextBtn.off();
  60 + location.href = res.redirect;
  61 + return;
  62 + }
  63 +
  64 + tip.show(res.message);
  65 + })
  66 + .fail(function() {
  67 + tip.show('出错了, 请重试');
  68 + })
  69 + .always(function() {
  70 + $nextBtn.prop('disabled', false);
  71 + });
  72 + }
  73 +};
  74 +
  75 +$(function() {
  76 + page.init();
  77 +});
1 @import "live/index"; 1 @import "live/index";
  2 +@import "student";
  3 +
2 .receive-coupon-page { 4 .receive-coupon-page {
3 * { 5 * {
4 margin: 0; 6 margin: 0;
@@ -294,5 +296,3 @@ @@ -294,5 +296,3 @@
294 } 296 }
295 297
296 298
297 -@import "student";  
298 -@import "live/index";  
@@ -33,28 +33,36 @@ $border: #e0e0e0; @@ -33,28 +33,36 @@ $border: #e0e0e0;
33 position: absolute; 33 position: absolute;
34 top: 30px; 34 top: 30px;
35 left: 30px; 35 left: 30px;
36 - height: 35px;  
37 - padding: 0 10px;  
38 - border: 2px solid $white;  
39 - border-radius: 20px; 36 + height: 70px;
  37 + padding: 0 20px;
  38 + border: 4px solid $white;
  39 + border-radius: 40px;
40 color: $white; 40 color: $white;
41 - font-size: 22px; 41 + font-size: 44px;
42 text-align: center; 42 text-align: center;
43 - line-height: 1.5; 43 + line-height: 70px;
  44 + -webkit-transform: scale(0.5);
  45 + transform: scale(0.5);
  46 + -webkit-transform-origin: 0 0;
  47 + transform-origin: 0 0;
44 } 48 }
45 49
46 .living { 50 .living {
47 position: absolute; 51 position: absolute;
48 top: 30px; 52 top: 30px;
49 left: 30px; 53 left: 30px;
50 - height: 35px;  
51 - width: 70px; 54 + height: 70px;
  55 + width: 140px;
52 background: $red; 56 background: $red;
53 - border-radius: 15px; 57 + border-radius: 40px;
54 color: $white; 58 color: $white;
55 - font-size: 22px; 59 + font-size: 44px;
56 text-align: center; 60 text-align: center;
57 - line-height: 1.5; 61 + line-height: 70px;
  62 + -webkit-transform: scale(0.5);
  63 + transform: scale(0.5);
  64 + -webkit-transform-origin: 0 0;
  65 + transform-origin: 0 0;
58 } 66 }
59 67
60 &_tag { 68 &_tag {
@@ -196,14 +204,18 @@ $border: #e0e0e0; @@ -196,14 +204,18 @@ $border: #e0e0e0;
196 position: absolute; 204 position: absolute;
197 top: 30px; 205 top: 30px;
198 left: 30px; 206 left: 30px;
199 - height: 35px;  
200 - width: 70px; 207 + height: 70px;
  208 + width: 140px;
201 background: $red; 209 background: $red;
202 - border-radius: 20px; 210 + border-radius: 40px;
203 color: $white; 211 color: $white;
204 - font-size: 22px; 212 + font-size: 44px;
205 text-align: center; 213 text-align: center;
206 - line-height: 1.5; 214 + line-height: 70px;
  215 + -webkit-transform: scale(0.5);
  216 + transform: scale(0.5);
  217 + -webkit-transform-origin: 0 0;
  218 + transform-origin: 0 0;
207 } 219 }
208 220
209 .main-intro { 221 .main-intro {
@@ -294,14 +306,18 @@ $border: #e0e0e0; @@ -294,14 +306,18 @@ $border: #e0e0e0;
294 position: absolute; 306 position: absolute;
295 top: 20px; 307 top: 20px;
296 left: 220px; 308 left: 220px;
297 - height: 35px;  
298 - width: 70px;  
299 - border: 2px solid $black;  
300 - border-radius: 20px;  
301 - font-size: 22px;  
302 - line-height: 1.5; 309 + height: 70px;
  310 + width: 140px;
  311 + border: 4px solid $black;
  312 + border-radius: 40px;
  313 + font-size: 44px;
  314 + line-height: 70px;
303 text-align: center; 315 text-align: center;
304 color: $black; 316 color: $black;
  317 + -webkit-transform: scale(0.5);
  318 + transform: scale(0.5);
  319 + -webkit-transform-origin: 0 0;
  320 + transform-origin: 0 0;
305 } 321 }
306 322
307 .pre-time { 323 .pre-time {
@@ -203,8 +203,6 @@ @@ -203,8 +203,6 @@
203 padding-left: 1.75rem; 203 padding-left: 1.75rem;
204 display: inline-block; 204 display: inline-block;
205 color: #ffffff; 205 color: #ffffff;
206 - border-radius: 0.3rem;  
207 - background-color: rgba(0, 0, 0, 0.32);  
208 font-size: 0.6rem; 206 font-size: 0.6rem;
209 207
210 } 208 }
@@ -224,7 +222,9 @@ @@ -224,7 +222,9 @@
224 font-size: 22px; 222 font-size: 22px;
225 font-weight: lighter; 223 font-weight: lighter;
226 color: rgba(255,255,255,0.8); 224 color: rgba(255,255,255,0.8);
  225 + background-color: rgba(0, 0, 0, 0.32);
227 overflow: hidden; 226 overflow: hidden;
  227 + border-radius: 0.3rem;
228 } 228 }
229 229
230 .live-item2_2 { 230 .live-item2_2 {
@@ -234,6 +234,7 @@ @@ -234,6 +234,7 @@
234 line-height: 1.2; 234 line-height: 1.2;
235 font-weight: normal; 235 font-weight: normal;
236 color: #FFFFFF; 236 color: #FFFFFF;
  237 + border-radius: 0.3rem;
237 } 238 }
238 239
239 .live-item2 img { 240 .live-item2 img {
@@ -242,7 +243,7 @@ @@ -242,7 +243,7 @@
242 top: 0; 243 top: 0;
243 display: inline-block; 244 display: inline-block;
244 width: 2.5rem; 245 width: 2.5rem;
245 - height: 100%; 246 + border-radius: 0.3rem;
246 } 247 }
247 248
248 .live-item2-head { 249 .live-item2-head {
1 .banner-center { 1 .banner-center {
  2 + position: relative;
2 margin: 30px 0 0; 3 margin: 30px 0 0;
3 height: 200px; 4 height: 200px;
4 overflow: hidden; 5 overflow: hidden;
  6 +
5 img { 7 img {
6 display: block; 8 display: block;
7 width: 100%; 9 width: 100%;
8 height: 100%; 10 height: 100%;
9 } 11 }
  12 +
  13 + .swiper-pagination {
  14 + position: absolute;
  15 + left: 0;
  16 + right: 0;
  17 + bottom: 20px;
  18 + text-align: center;
  19 + z-index: 1;
  20 +
  21 + .pagination-inner {
  22 + display: inline-block;
  23 +
  24 + span {
  25 + display: inline-block;
  26 + width: 14px;
  27 + height: 14px;
  28 + background: #fff;
  29 + opacity: 0.5;
  30 + margin: 0 9px;
  31 + border-radius: 50%;
  32 +
  33 + &.swiper-pagination-bullet-active {
  34 + background: #fff;
  35 + opacity: 1;
  36 + }
  37 + }
  38 + }
  39 + }
  40 +}
  41 +
  42 +.banner-center-swiper {
  43 + background: #fff;
  44 + width: 100%;
  45 + height: 200px;
  46 + border-top: 1px solid #e0e0e0;
  47 + overflow: hidden;
  48 +
  49 + .banner-list {
  50 + position: relative;
  51 + height: 200px;
  52 +
  53 + li {
  54 + float: left;
  55 + width: 100%;
  56 + height: 200px;
  57 +
  58 + a {
  59 + position: relative;
  60 + display: block;
  61 + width: 100%;
  62 + height: 100%;
  63 + line-height: 200px;
  64 + font-size: 0;
  65 + }
  66 +
  67 + img {
  68 + display: inline-block;
  69 + max-width: 100%;
  70 + max-height: 100%;
  71 + vertical-align: middle;
  72 + }
  73 + }
  74 + }
10 } 75 }
1 @charset "utf-8"; 1 @charset "utf-8";
  2 +
2 @import "me/index"; 3 @import "me/index";
3 @import "layout/reset"; 4 @import "layout/reset";
4 @import "layout/common"; 5 @import "layout/common";
@@ -7,6 +8,7 @@ @@ -7,6 +8,7 @@
7 @import "layout/header"; 8 @import "layout/header";
8 @import "layout/footer"; 9 @import "layout/footer";
9 @import "layout/utils"; 10 @import "layout/utils";
  11 +@import "layout/form";
10 @import "common/index"; 12 @import "common/index";
11 @import "channel/index"; 13 @import "channel/index";
12 @import "product/index"; 14 @import "product/index";
@@ -53,9 +53,9 @@ a { @@ -53,9 +53,9 @@ a {
53 } 53 }
54 54
55 @font-face { 55 @font-face {
56 - font-family: 'iconfont';  
57 - src: resolve('iconfont.eot'); /* IE9 */  
58 - src: resolve('iconfont.eot?#iefix') format('embedded-opentype'), resolve('iconfont.woff') format('woff'), resolve('iconfont.ttf') format('truetype'), resolve('iconfont.svg#iconfont') format('svg'); /* iOS 4.1- */ 56 + font-family: "iconfont";
  57 + src: resolve("iconfont.eot"); /* IE9 */
  58 + src: resolve("iconfont.eot?#iefix") format("embedded-opentype"), resolve("iconfont.woff") format("woff"), resolve("iconfont.ttf") format("truetype"), resolve("iconfont.svg#iconfont") format("svg"); /* iOS 4.1- */
59 } 59 }
60 60
61 .iconfont { 61 .iconfont {
  1 +.input-group {
  2 + display: table;
  3 +
  4 + .input {
  5 + width: 100%;
  6 + }
  7 +
  8 + .input,
  9 + .input-addon {
  10 + display: table-cell;
  11 + vertical-align: middle;
  12 + }
  13 +
  14 + .input-addon {
  15 + width: 1%;
  16 + overflow: hidden;
  17 + }
  18 +}
@@ -138,7 +138,10 @@ body.passport-body { @@ -138,7 +138,10 @@ body.passport-body {
138 background-color: #36a74c; 138 background-color: #36a74c;
139 border-radius: 5PX; 139 border-radius: 5PX;
140 color: #fff; 140 color: #fff;
141 - &.disable { 141 + border: none;
  142 + outline: none;
  143 +
  144 + &.disable, &:disabled {
142 background-color: #a2a2a2; 145 background-color: #a2a2a2;
143 } 146 }
144 } 147 }
@@ -154,6 +157,9 @@ body.passport-body { @@ -154,6 +157,9 @@ body.passport-body {
154 height: 16PX; 157 height: 16PX;
155 background: resolve('passport/clear-input.png') no-repeat; 158 background: resolve('passport/clear-input.png') no-repeat;
156 background-size: 100% 100%; 159 background-size: 100% 100%;
  160 + outline: none;
  161 + border: none;
  162 + padding: 0; /* button has padding in default */
157 } 163 }
158 .eye { 164 .eye {
159 position: absolute; 165 position: absolute;
1 @import "common"; 1 @import "common";
2 @import "register"; 2 @import "register";
3 @import "login"; 3 @import "login";
  4 +@import "sms-login";
4 @import "back"; 5 @import "back";
5 @import "code"; 6 @import "code";
6 @import "bind"; 7 @import "bind";
@@ -3,7 +3,7 @@ @@ -3,7 +3,7 @@
3 position: absolute; 3 position: absolute;
4 height: 31PX; 4 height: 31PX;
5 width: 26PX; 5 width: 26PX;
6 - background: resolve('passport/yoho.png'); 6 + background: resolve("passport/yoho.png");
7 background-size: 100% 100%; 7 background-size: 100% 100%;
8 top: 10PX; 8 top: 10PX;
9 left: 15PX; 9 left: 15PX;
@@ -20,7 +20,7 @@ @@ -20,7 +20,7 @@
20 text-align: left; 20 text-align: left;
21 font-size: 16PX; 21 font-size: 16PX;
22 22
23 - .go-register { 23 + .sms-login {
24 text-decoration: underline; 24 text-decoration: underline;
25 color: #858585; 25 color: #858585;
26 } 26 }
@@ -57,20 +57,20 @@ @@ -57,20 +57,20 @@
57 } 57 }
58 58
59 .alipay { 59 .alipay {
60 - background-image: resolve('passport/alipay.png'); 60 + background-image: resolve("passport/alipay.png");
61 } 61 }
62 62
63 .weibo { 63 .weibo {
64 - background-image: resolve('passport/weibo.png'); 64 + background-image: resolve("passport/weibo.png");
65 } 65 }
66 66
67 .qq { 67 .qq {
68 - background-image: resolve('passport/qq.png'); 68 + background-image: resolve("passport/qq.png");
69 } 69 }
70 70
71 .wechat { 71 .wechat {
72 display: none; 72 display: none;
73 - background-image: resolve('passport/wechat.png'); 73 + background-image: resolve("passport/wechat.png");
74 } 74 }
75 } 75 }
76 } 76 }
@@ -82,11 +82,19 @@ @@ -82,11 +82,19 @@
82 background-color: #333; 82 background-color: #333;
83 border: none; 83 border: none;
84 border-radius: 20PX; 84 border-radius: 20PX;
85 - margin: 0 auto; 85 + margin: 0 auto 28px;
86 font-size: 16PX; 86 font-size: 16PX;
87 color: #d8d8d8; 87 color: #d8d8d8;
88 } 88 }
89 89
  90 + .go-register {
  91 + color: #858585;
  92 +
  93 + a {
  94 + color: inherit;
  95 + }
  96 + }
  97 +
90 .login-tip { 98 .login-tip {
91 font-size: 16PX; 99 font-size: 16PX;
92 position: relative; 100 position: relative;
@@ -97,7 +105,7 @@ @@ -97,7 +105,7 @@
97 display: inline-block; 105 display: inline-block;
98 height: 12PX; 106 height: 12PX;
99 width: 12PX; 107 width: 12PX;
100 - background-image: resolve('passport/info.png'); 108 + background-image: resolve("passport/info.png");
101 background-size: 100% 100%; 109 background-size: 100% 100%;
102 } 110 }
103 } 111 }
  1 +.sms-login {
  2 + .sms-input {
  3 + margin-top: 60px;
  4 + }
  5 +
  6 + #resend-sms {
  7 + background-color: transparent;
  8 + width: 148PX;
  9 + margin: 0 15PX 0 28PX;
  10 + border: 1PX solid #36a74c;
  11 + padding: 5PX 0;
  12 + border-radius: 20PX;
  13 + font-size: 16PX;
  14 + color: #36a74c;
  15 +
  16 + &:disabled {
  17 + color: #a2a2a2;
  18 + border-color: #a2a2a2;
  19 + }
  20 + }
  21 +
  22 + button {
  23 + border: none;
  24 + }
  25 +}
  26 +
  27 +.sms-login-check {
  28 + .clear-input {
  29 + right: 175PX;
  30 + }
  31 +}
  32 +
  33 +.sms-login-msg {
  34 + font-size: 28px;
  35 + color: #fff;
  36 + margin-bottom: 20px;
  37 +
  38 + .tel {
  39 + color: #41cbe7;
  40 + }
  41 +
  42 + &.small {
  43 + font-size: 22px;
  44 + color: #858585;
  45 + }
  46 +}
@@ -42,7 +42,7 @@ module.exports = { @@ -42,7 +42,7 @@ module.exports = {
42 resolve: { 42 resolve: {
43 alias: { 43 alias: {
44 common: path.join(__dirname, 'js/common'), 44 common: path.join(__dirname, 'js/common'),
45 - plugin: path.join(__dirname, 'js/plugins') 45 + plugin: path.join(__dirname, 'js/plugin')
46 } 46 }
47 }, 47 },
48 plugins: [ 48 plugins: [