Authored by 周少峰

Merge branch 'master' into feature/defaultOrder

... ... @@ -7,11 +7,6 @@
const config = require('./config/common');
// use one apm
if (config.useOneapm) {
require('oneapm');
}
const express = require('express');
const path = require('path');
const bodyParser = require('body-parser');
... ... @@ -41,6 +36,7 @@ app.locals.version = pkg.version;
app.set('view engine', '.hbs');
app.set('views', './doraemon/views');
app.set('view cache', true);
app.engine('.hbs', hbs({
extname: '.hbs',
defaultLayout: 'layout',
... ... @@ -70,8 +66,11 @@ app.use(session({
store: new MemcachedStore({
hosts: config.memcache.session,
prefix: 'yohobuy_session:',
timeout: 100,
retries: 0
poolSize: 25,
reconnect: 5000,
timeout: 1000,
retries: 1,
retry: 3000
})
}));
... ...
... ... @@ -74,6 +74,10 @@ const getUserInfoAPI = (req, res, next) => {
.catch(next);
};
const fakeGetUserInfoAPI = (req, res) => {
return res.json({code: 200, message: '验证成功'});
};
const sendCodePage = (req, res, next) => {
let inputInfo = req.inputInfo;
... ... @@ -357,6 +361,7 @@ const validateMobileInSession = (req, res, next) => {
module.exports = {
index, // 首页
fakeGetUserInfoAPI, // 通过邮箱或手机号获得用户信息
getUserInfoAPI, // 通过邮箱或手机号获得用户信息
sendCodePage, // 发送验证码到邮箱或者手机,然后跳转页面
saveInSession, // 保存状态到session中
... ...
... ... @@ -30,7 +30,7 @@ function doPassportCallback(req, res, user) {
let shoppingKey = cookie.getShoppingKey(req);
let refer = cookie.getRefer(req, config.siteUrl);
if (/sign|login/.test(refer)) {
if (/sign|login|reg|passport/.test(refer)) {
refer = config.siteUrl;
}
if (user.openId) {
... ... @@ -122,6 +122,13 @@ const local = {
areaName = area ? area.name : '';
}
let refer = req.query.refer;
refer && res.cookie('refer', encodeURI(refer), {
domain: 'yohobuy.com'
});
PassportHelper.getLeftBannerAsync(SIGNIN_LEFT_BANNER_CODE).then(cover => {
res.render('login', {
loginPage: true,
... ... @@ -133,7 +140,7 @@ const local = {
countryName: areaName,
countryList: areaArr,
forgetPwd: helpers.urlFormat('/passport/back/index'),
fastReg: helpers.urlFormat('/passport/reg/index'),
fastReg: helpers.urlFormat('/reg.html', {refer: refer}),
weixinLogin: helpers.urlFormat('/passport/autosign/wechat'),
qqLogin: helpers.urlFormat('/passport/autosign/qq'),
weiboLogin: helpers.urlFormat('/passport/autosign/sina'),
... ... @@ -168,10 +175,10 @@ const local = {
}
let refer = (function() {
if (_.has(req, 'cookies.refer')) {
return decodeURI(req.cookies.refer);
} else if (/sign|login|passport/.test(_.get(req, 'cookies.refer', ''))) {
if (/sign|login|reg|passport/.test(_.get(req, 'cookies.refer', ''))) {
return `${config.siteUrl}/home`;
} else if (_.has(req, 'cookies.refer')) {
return decodeURI(req.cookies.refer);
} else {
return `${config.siteUrl}/home`;
}
... ...
... ... @@ -87,7 +87,7 @@ let index = (req, res, next) => {
captchaUrl: helpers.urlFormat('/passport/imagesNode', {t: Date.now()}),
itemUrl: helpers.urlFormat('/help/', {category_id: 143}),
referUrl: refer,
loginUrl: helpers.urlFormat('/passport/login', {refer: refer}),
loginUrl: helpers.urlFormat('/signin.html', {refer: refer}),
coverHref: result.url,
coverImg: result.img,
regBtnText: '立即注册'
... ...
... ... @@ -115,7 +115,7 @@ const Auth = {
if (data) {
let uidCookie = `{data.profile_name}::${encryptionUid}::${data.vip_info.title}::${token}`;
let uidCookie = `${data.profile_name}::${encryptionUid}::${data.vip_info.title}::${token}`;
let isStudent = data.vip_info.is_student || 0;
req.session._TOKEN = token;
... ...
... ... @@ -27,7 +27,7 @@ router.get('/logout.html', login.local.logout);
router.post('/passport/login/sms/send', login.local.sms.send); // 发短信验证码
router.post('/passport/login/sms/auth', login.local.sms.auth); // 验证短信验证码
router.post('/passport/login/sms/checkuser', login.local.sms.checkUser); // 短信检查用户是否注册
router.post('/passport/login/password/checkuser', back.validateInputAPI, back.getUserInfoAPI);// 密码登录检查用户是否注册
router.post('/passport/login/password/checkuser', back.fakeGetUserInfoAPI);// 假的,密码登录检查用户是否注册
router.get('/passport/login', login.common.beforeLogin, login.local.loginPage);
router.post('/passport/login/auth', login.local.login);
... ...
... ... @@ -24,6 +24,14 @@ const sizeInfoAsync = skn => {
};
// 退换支持
const isSupportReturnedSale = skn => {
return api.get('', {
method: 'app.product.refundExchange',
product_skn: skn
});
};
const getProductComfortAsync = pid => {
return api.get('', {
method: 'web.productComfort.data',
... ... @@ -77,7 +85,8 @@ module.exports = {
getProductComfortAsync,
getProductModelCardAsync,
getProductModelTryAsync,
getProductAsync
getProductAsync,
isSupportReturnedSale
};
... ...
... ... @@ -9,6 +9,7 @@
const Promise = require('bluebird');
const co = Promise.coroutine;
const moment = require('moment');
const url = require('url');
const _ = require('lodash');
const helpers = global.yoho.helpers;
... ... @@ -729,7 +730,7 @@ const _detailDataPkg = (origin, uid, vipLevel) => {
}
// 分享相关,产品的链接
result.weixinUrl = helpers.urlFormat(origin.productUrl, {}, 'item');
result.weixinUrl = origin.productUrl;
result.shareTitle = result.name;
result.shareImg = 'http:' + result.img; // 分享图片必须使用http
result.shareDesc = result.phrase;
... ... @@ -755,31 +756,31 @@ const _detailDataPkg = (origin, uid, vipLevel) => {
if (domainBrand.type && domainBrand.shopId) {
switch (parseInt(domainBrand.type, 10)) {
case 1:
{
{
// 多品店不显示
banner = [];
break;
}
banner = [];
break;
}
case 2:
{
{
// 单品店显示新版的店铺banner
let basisData = yield shopService.basisTemplateAsync(domainBrand.shopId);
let basisData = yield shopService.basisTemplateAsync(domainBrand.shopId);
banner.bgImg = basisData.shopTopBanner.banner || banner.bgImg;
break;
}
banner.bgImg = basisData.shopTopBanner.banner || banner.bgImg;
break;
}
default:
{
break;
}
{
break;
}
}
}
}
statGoodsInfo.imageUrl = result.img;
statGoodsInfo.productUrl = result.weixinUrl;
statGoodsInfo.imageUrl = 'http:' + result.img;
statGoodsInfo.productUrl = 'http:' + helpers.urlFormat(url.parse(origin.productUrl).pathname, {}, 'item');
statGoodsInfo.smallSortId = result.smallSortId;
statGoodsInfo.soldOut = parseInt(soldOut);
statGoodsInfo.soldOut = soldOut ? 1 : 0;
return {
goodsInfo: result,
... ... @@ -1338,7 +1339,8 @@ const showMainAsync = (data) => {
let currentUserProductInfo = _.partial(_detailDataPkg, _, data.uid, data.vipLevel);
// 获取商品信息
let productInfo = yield productAPI.getProductAsync(data.pid, data.uid, data.isStudent, data.vipLevel).then(currentUserProductInfo);
let productInfo = yield productAPI.getProductAsync(data.pid, data.uid, data.isStudent, data.vipLevel)
.then(currentUserProductInfo);
if (_.isEmpty(productInfo) || _.isEmpty(productInfo.goodsInfo)) {
return Promise.reject({
... ... @@ -1348,7 +1350,8 @@ const showMainAsync = (data) => {
let requestData = yield Promise.all([
_getSortNavAsync(productInfo.goodsInfo.smallSortId, data.gender),
HeaderModel.requestHeaderData(data.channel)
HeaderModel.requestHeaderData(data.channel),
productAPI.isSupportReturnedSale(productInfo.goodsInfo.skn)
]);
// 分类导航 ,seo
... ... @@ -1372,6 +1375,10 @@ const showMainAsync = (data) => {
productInfo.statGoodsInfo
);
// 是否支持退换货,true 支持,false 不支持
result.detail.supportSaleReturnedService =
_.get(requestData, `[2].data.${productInfo.goodsInfo.skn}`, 'N') === 'N';
// 导航
result.detail.pathNav = _.concat(
homeService.getHomeChannelNav(data.channel),
... ...
... ... @@ -402,8 +402,7 @@ exports.getSaleDiscountData = (params, channel) => {
if (subResult[0].code === 200) {
Object.assign(finalResult, {
leftContent: publicHandler.handleSaleSortData(subResult[0].data.filter.group_sort,
params,
'discount'),
params, 'discount'),
saleList: {
footPager: publicHandler.handlePagerData(subResult[0].data.total, params),
opts: publicHandler.handleSaleOptsData(params, subResult[0].data.total, 'default')
... ... @@ -416,13 +415,20 @@ exports.getSaleDiscountData = (params, channel) => {
// 处理商品数据,顶部分类
if (subResult[1].code === 200) {
let sknArr = [];
finalResult.saleList.goods = productProcess.processProductList(subResult[1].data.product_list);
finalResult.saleList.totalCount = subResult[1].data.total;
_.forEach(finalResult.saleList.goods, (value, key) => {
if (sknArr.length < 3) {
sknArr.push(value.productSkn);
}
delete finalResult.saleList.goods[key].tags.isNew; // 屏蔽 new 标签
delete finalResult.saleList.goods[key].tags.isSale;// 屏蔽 sale 标签
delete finalResult.saleList.goods[key].discount; // 屏蔽折扣信息
});
finalResult.criteo = {skn: sknArr}; // 重要:推广列表前三个商品Skn
} else {
logger.error('discount goods list api code no 200');
}
... ...
... ... @@ -632,6 +632,12 @@
</div>
</div>
{{#if supportSaleReturnedService}}
<div class="support-saleReturned-service"></div>
{{^}}
<div class="not-support-saleReturned-service"></div>
{{/if}}
<div class="service"></div>
{{#if latestWalk}}
<div class="info-block latest-walk">
... ... @@ -698,7 +704,7 @@
_mvq.push(['$addGoods', /*分类id*/ '', /*品牌id*/ '', /*商品名称*/ '', /*商品ID*/ '{{skn}}', /*商品售价*/ '', /*商品图片url*/ '', /*分类名*/ '', /*品牌名*/ '', /*商品库存状态1或是0*/ '', /*网络价*/ '', /*收藏人数*/ '']);
_mvq.push(['$logData']);
var _goodsData = {
id: '{{skn}}',// 商品ID
id: '{{productId}}',// 商品ID
name: '{{productName}}', // 商品名称
brand: '{{brandName}}', // 商品品牌(非必填)
origPrice: '{{marketPrice}}', // 商品原价(非必填)
... ... @@ -709,6 +715,14 @@
category: '{{fullSortName}}', // 所属分类完整路径, // 所属分类完整路径
soldOut: '{{soldOut}}' // 状态 1下架,0在售(必填)
};
(function() {
var mvl = document.createElement('script');
mvl.type = 'text/javascript'; mvl.async = true;
mvl.src = ('https:' == document.location.protocol ? 'https://static-ssl.mediav.com/mvl.js' : 'http://static.mediav.com/mvl.js');
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(mvl, s);
})();
</script>
{{/statGoodsInfo}}
... ...
... ... @@ -11,4 +11,5 @@
{{/ saleList}}
</div>
</div>
{{> common/criteo}}
{{/ result}}
... ...
{{# criteo}}
<script type="text/javascript" src="//static.criteo.net/js/ld/ld.js" async="true"></script>
<script type="text/javascript">
window.criteo_q = window.criteo_q || [];
window.criteo_q.push(
{ event: "setAccount", account: [16184] },
{ event: "setSiteType", type: "d" },
{ event: "viewList", item: [{{#each skn}}"{{.}}"{{#unless @last}},{{/unless}}{{/each}}]}
);
</script>
{{/ criteo}}
\ No newline at end of file
... ...
... ... @@ -88,9 +88,11 @@ if (isProduction) {
master: ['memcache1.yohoops.org:12111', 'memcache2.yohoops.org:12111', 'memcache3.yohoops.org:12111'],
slave: ['memcache1.yohoops.org:12112', 'memcache2.yohoops.org:12112', 'memcache3.yohoops.org:12112'],
session: ['memcache1.yohoops.org:12111', 'memcache2.yohoops.org:12111', 'memcache3.yohoops.org:12111'],
timeout: 100,
retries: 0,
reconnect: 5000
poolSize: 25,
reconnect: 5000,
timeout: 300,
retries: 1,
retry: 3000
},
useOneapm: true,
useCache: true,
... ...
... ... @@ -39,4 +39,13 @@ var _gaq = _gaq || [];
c.src=(f ? 'https' : 'http') + '://'+(f?'fm.ipinyou.com':'fm.p0y.cn')+'/j/t/adv.js';
var h = d.getElementsByTagName("script")[0];h.parentNode.insertBefore(c, h);
}(document);
</script>
<script>
var _hmt = _hmt || [];
(function() {
var hm = document.createElement("script");
hm.src = "//hm.baidu.com/hm.js?65dd99e0435a55177ffda862198ce841";
var s = document.getElementsByTagName("script")[0];
s.parentNode.insertBefore(hm, s);
})();
</script>
\ No newline at end of file
... ...
... ... @@ -43,10 +43,6 @@
<li>
<a href="{{helpHref}}">帮助中心</a>
</li>
<li>
<i class="tell-icon iconfont">&#xe621;</i>
<span>400-8899-646</span>
</li>
{{/ tool}}
</ul>
</div>
... ...
... ... @@ -137,29 +137,29 @@
<div id="foot-mobile">
<ul class="mobile clearfix">
<li>
<a href="http://www.yohomars.com/" target="_blank">
<a href="http://www.yoho.cn/product#yoho" target="_blank">
{{#if devEnv}}
<img class="lazy" data-original="http://localhost:5002/img/layout/mars.png">
<img class="lazy" data-original="http://localhost:5002/img/layout/yoho.png">
{{^}}
<img class="lazy" data-original="//cdn.yoho.cn/yohobuy-node/assets/img/layout/mars.png">
<img class="lazy" data-original="//cdn.yoho.cn/yohobuy-node/assets/img/layout/yoho.png">
{{/if}}
</a>
</li>
<li>
<a href="http://app.yohoshow.com/" target="_blank">
<a href="http://www.yohomars.com/" target="_blank">
{{#if devEnv}}
<img class="lazy" data-original="http://localhost:5002/img/layout/show.png">
<img class="lazy" data-original="http://localhost:5002/img/layout/mars.png">
{{^}}
<img class="lazy" data-original="//cdn.yoho.cn/yohobuy-node/assets/img/layout/show.png">
<img class="lazy" data-original="//cdn.yoho.cn/yohobuy-node/assets/img/layout/mars.png">
{{/if}}
</a>
</li>
<li>
<a href="http://www.yoho.cn/product#yoho" target="_blank">
<a href="http://app.yohoshow.com/" target="_blank">
{{#if devEnv}}
<img class="lazy" data-original="http://localhost:5002/img/layout/yoho.png">
<img class="lazy" data-original="http://localhost:5002/img/layout/show.png">
{{^}}
<img class="lazy" data-original="//cdn.yoho.cn/yohobuy-node/assets/img/layout/yoho.png">
<img class="lazy" data-original="//cdn.yoho.cn/yohobuy-node/assets/img/layout/show.png">
{{/if}}
</a>
</li>
... ...
... ... @@ -26,7 +26,7 @@
</div>
<div class="good-detail-img">
<a class="good-thumb" href="{{url}}" target="_blank">
<img class="lazy" data-original="{{image thumb 220 300}}">
<img class="lazy" data-original="{{image thumb 280 382}}">
</a>
{{# isFew}}
<p class="few-tag">即将售罄</p>
... ... @@ -75,7 +75,7 @@
</p>
<div class="hideList hide">
{{#goodsList}}
<li data-src="{{image imagesUrl 235 314}}" data-url="{{../url}}"></li>
<li data-src="{{image imagesUrl 280 374}}" data-url="{{../url}}"></li>
{{/goodsList}}
</div>
</div>
... ...
{
"name": "yohobuy-node",
"version": "4.9.4",
"version": "4.9.7",
"private": true,
"description": "A New Yohobuy Project With Express",
"repository": {
... ... @@ -58,8 +58,7 @@
"uuid": "^2.0.2",
"winston": "^2.2.0",
"winston-daily-rotate-file": "^1.1.4",
"yoho-express-session": "^1.14.1",
"yoho-node-lib": "0.0.49"
"yoho-node-lib": "0.0.52"
},
"devDependencies": {
"autoprefixer": "^6.3.6",
... ...

26.6 KB | W: | H:

20.7 KB | W: | H:

  • 2-up
  • Swipe
  • Onion skin

11.4 KB | W: | H:

13.9 KB | W: | H:

  • 2-up
  • Swipe
  • Onion skin
... ... @@ -120,26 +120,7 @@ var LoginType = {
PasswordLogin: {
ele: '.password-login',
validateAccountAsync: function() {
return $.ajax({
url: '/passport/login/password/checkuser',
type: 'POST',
data: {
phoneNum: getAccountVal1(),
area: getAreaCodeVal()
}
}).then(function(result) {
var defer = $.Deferred(); // eslint-disable-line
if (result.code === 200) {
hideAccountTip1(); // eslint-disable-line
defer.resolve();
} else {
showAccountTip1(result.message); // eslint-disable-line
defer.reject();
}
return defer.promise();
});
return $.Deferred().resolve().promise(); // eslint-disable-line
},
validateAccountLocal: validateAccountPasswordLocal, // eslint-disable-line
creditableToken: getPasswordVal,
... ...
... ... @@ -446,7 +446,7 @@ $rightDia.on('click', function() {
'<p>权益1:新品立享9折</p>' +
'<p>学生购买原价新品时,可立即享受9折优惠,与VIP折扣不可同时享受。</p><br>' +
'<p>权益2:每1元返1个有货币</p>' +
'<p>学生购买商品时,以商品的实际成交金额计算,每1元返1个有货币;</p>' +
'<p>学生购买指定商品时,以商品的实际成交金额计算,每1元返1个有货币;</p>' +
'<p>返有货币时间:确认收货7日后,系统将自动将对应数量的有货币返至购买账户;</p>' +
'<p>有货币有效期:获得当日至次年12月31日,逾期自动作废;</p>' +
'<p>查看有货币:登录后,点击“个人中心”在“我的有货币”中可以查看有货币余额及明细。</p><br>' +
... ...
... ... @@ -984,7 +984,7 @@
}
}
.service {
.support-saleReturned-service {
$service: product/service.png;
width: width($service);
... ... @@ -993,6 +993,14 @@
background: resolve($service);
}
.not-support-saleReturned-service {
$service: product/limit.png;
width: width($service);
height: height($service);
margin: 45px auto;
background: resolve($service);
}
.latest-walk {
overflow: inherit;
... ...
'use strict';
const _ = require('lodash');
const fp = require('lodash/fp');
const camelCase = global.yoho.camelCase;
const helpers = global.yoho.helpers;
const images = require(`${global.utils}/images`);
// NOTE: 这里修改了图片质量的参数
helpers.image = _.flow(helpers.image, fp.replace(/\/quality\/\d*$/, '/quality/90'));
/**
* 根据性别来决定 默认图片获取字段 如果是 2、3
*
... ... @@ -20,7 +24,6 @@ const procProductImg = (product, gender) => {
return product.cover1 || product.cover2 || product.imagesUrl || '';
};
/**
* 处理列表大图周边小图数据,拼接添加 href
* @param origin goods 原始数据
... ...