Authored by ccbikai(👎🏻🍜)

Merge branch 'master' into release/5.2

Showing 56 changed files with 527 additions and 353 deletions
... ... @@ -13,6 +13,7 @@ const yohoLib = require('yoho-node-lib');
const express = require('express');
const path = require('path');
const compression = require('compression');
const bodyParser = require('body-parser');
const cookieParser = require('cookie-parser');
const favicon = require('serve-favicon');
... ... @@ -65,6 +66,7 @@ app.use(bodyParser.urlencoded({
extended: false
}));
app.use(cookieParser());
app.use(compression());
app.use(session({
name: 'yohobuy_session_cookie',
... ... @@ -74,7 +76,7 @@ app.use(session({
app.use((req, res, next) => {
req.user = {}; // 全局的用户数据
req.yoho = {}; // req和res绑定yoho对象,用于传递全局数据, 如req.yoho.channel等
req.app.locals.wap = app.locals.wap; //zookeper对象赋值
if (!req.session.id) {
req.session.id = uuid.v4();
}
... ... @@ -94,6 +96,7 @@ try {
const setPageInfo = require('./doraemon/middleware/set-pageinfo');
const devtools = require('./doraemon/middleware/devtools');
const seo = require('./doraemon/middleware/seo');
const pageCache = require('./doraemon/middleware/page-cache');
// YOHO 前置中间件
app.use(subDomain());
... ... @@ -107,16 +110,8 @@ try {
app.use(devtools());
}
// set no cache
app.use((req, res, next) => {
if (req.get('X-Requested-With') === 'XMLHttpRequest') {
res.set('Cache-Control', 'no-cache');
}
next();
});
app.use(pageCache());
require('./dispatch')(app);
app.all('*', errorHanlder.notFound()); // 404
// YOHO 后置中间件
... ...
... ... @@ -22,6 +22,10 @@ exports.index = (req, res, next) => {
}
model.floor(param, req.yoho.isApp, req.query.app_version).then(result => {
if (!result.length) {
res.set('Cache-Control', 'no-cache');
}
res.render('coupon-floor', {
module: 'activity',
page: 'coupon-floor',
... ...
... ... @@ -26,13 +26,6 @@ app.use(global.yoho.hbs({
helpers: Object.assign({}, global.yoho.helpers, helpers)
}));
// for zookeeper, inject locals
app.use((req, res, next) => {
req.app.locals.wap = app.locals.wap;
next();
});
// router
app.use(require('./router'));
... ...
... ... @@ -15,13 +15,6 @@ app.on('mount', function(parent) {
Object.assign(app.locals, parent.locals);
});
// for zookeeper, inject locals
app.use((req, res, next) => {
req.app.locals.wap = app.locals.wap;
next();
});
// router
app.use(require('./router'));
... ...
... ... @@ -26,13 +26,6 @@ app.use(global.yoho.hbs({
helpers: global.yoho.helpers
}));
// for zookeeper, inject locals
app.use((req, res, next) => {
req.app.locals.wap = app.locals.wap;
next();
});
// router
app.use(require('./router'));
... ...
... ... @@ -38,6 +38,10 @@ let _channelPage = (req, res, data) => {
gender: data.gender,
uid: _.toString(req.user.uid)
}).then(result => {
if (!result.content.length || !result.sideNav.length) {
res.set('Cache-Control', 'no-cache');
}
// result.content = [{
// seckill: true,
// data: {
... ... @@ -66,6 +70,7 @@ let index = (req, res, next) => {
pageFooter: true,
channelList: result[0].channelList,
yohood: result[0].yohood,
double11: result[0].double11,
background: result[1]
});
}).catch(next);
... ...
... ... @@ -13,6 +13,7 @@ var app = express();
var doraemon = path.join(__dirname, '../../doraemon/views'); // parent view root
app.on('mount', function(parent) {
delete parent.locals.settings; // 不继承父 App 的设置
Object.assign(app.locals, parent.locals);
});
... ... @@ -26,13 +27,6 @@ app.use(global.yoho.hbs({
helpers: global.yoho.helpers
}));
// for zookeeper, inject locals
app.use((req, res, next) => {
req.app.locals.wap = app.locals.wap;
next();
});
// router
app.use(require('./router'));
... ...
... ... @@ -36,6 +36,8 @@ const _packageAd = (params) => {
gender: 1,
limit: 1000,
page: 1
}, {
cache: true
}).then(result => {
return result;
... ... @@ -49,7 +51,10 @@ const _packageList = (params) => {
method: 'app.brand.newBrandList',
yh_channel: params.channel
}, { code: 200 }).then(result => {
}, {
cache: true,
code: 200
}).then(result => {
return result;
... ... @@ -269,7 +274,10 @@ const getBrandForSearch = (channel) => {
method: 'app.brand.brandlist',
yh_channel: channel || 1
}, { code: 200 }).then(result => {
}, {
cache: true,
code: 200
}).then(result => {
return result;
... ... @@ -289,7 +297,9 @@ const branchSearchHistory = (params) => {
uid: params.uid,
records: params.records || ''
}, { code: 200 }).then(result => {
}, {
code: 200
}).then(result => {
return result;
... ... @@ -316,7 +326,10 @@ const branchSearchHot = () => {
return api.get('', {
method: 'app.search.hotBrands'
}, { code: 200 }).then(result => {
}, {
cache: true,
code: 200
}).then(result => {
return result;
... ...
... ... @@ -196,18 +196,19 @@ const _getChannelList = () => {
}
if (id === 6) {
list.channelList.push({
href: item.url,
title: item.title || '双 11',
entitle: item.title
});
list.double11 = {};
list.double11.href = item.url;
}
});
return Object.keys(list).length ? list : channelList;
return Object.keys(list).length ? list : {
channelList: channelList
};
} else {
logger.error('channel select code is not 200');
return channelList;
return {
channelList: channelList
};
}
});
};
... ... @@ -252,8 +253,8 @@ let getChannelData = (params) => {
let navGender = _.cloneDeep(params.gender);
return Promise.all([_getChannelResource(params), _getLeftNav(navGender)]).then((data) => {
channelData.content = data[0]; // 资源位数据
channelData.sideNav = data[1]; // 侧边栏数据
channelData.content = data[0] || []; // 资源位数据
channelData.sideNav = data[1] || []; // 侧边栏数据
return channelData;
});
... ... @@ -270,7 +271,9 @@ let getBottomBannerData = (gender) => {
if (gender === 'boys' || gender === 'girls') {
return api.get('operations/api/v5/resource/get', {
content_code: bottomBannerCode[gender] // eslint-disable-line
}, true);
}, {
cache: true
});
}
return Promise.resolve({
code: 400,
... ...
... ... @@ -26,9 +26,13 @@
{{/each}}
{{#yohood}}
{{#if showYohood}}
<a href="{{yohoodHref}}" id="yohood" class="list-item"> <span class="iconfont right-icon">&#xe614;</span></a>
<a href="{{yohoodHref}}" id="yohood" class="list-item no-touch"> <span class="iconfont right-icon">&#xe614;</span></a>
{{/if}}
{{/yohood}}
{{#if double11}}
<a href="{{double11.href}}" class="no-touch" id="double11"></a>
{{/if}}
</div>
</div>
</div>
... ...
... ... @@ -54,6 +54,11 @@ const editor = (req, res, next) => {
build.push(guangProcess.formatArticle(articleData, true, isApp, false, uid));
});
if (!build.length) {
res.set('Cache-Control', 'no-cache');
}
res.render('index/list', Object.assign({
page: 'index-editor',
title: title,
... ... @@ -169,6 +174,11 @@ const index = (req, res, next) => {
};
indexModel.getArticle(param).then(result => {
if (result && result.guang && result.guang.infos) {
if (!result.guang.infos.length) {
res.set('Cache-Control', 'no-cache');
}
}
res.render('guang', Object.assign(responseData, result));
}).catch(next);
};
... ...
... ... @@ -33,18 +33,17 @@ const _pageArticleContent = (articleContent, isApp, gender) => {
if (i < len) {
let build = {};
let art = articleContent[i];
// 文字
if (art.text && art.text.data && art.text.data.text) {
build.text = art.text.data.text;
contents.push(build);
joinContentFunc(++i, len);
} else if (art.singleImage) { // 单张图
} else if (art.singleImage && art.singleImage.data && art.singleImage.data.length) { // 单张图
build.bigImage = helpers.image(art.singleImage.data[0].src, 640, 640);
contents.push(build);
joinContentFunc(++i, len);
} else if (art.smallPic && art.smallPic.data) {
} else if (art.smallPic && art.smallPic.data && art.smallPic.data.length > 1) {
let imgs = art.smallPic.data;
build.smallImage = [{
... ... @@ -109,8 +108,8 @@ const _pageArticleContent = (articleContent, isApp, gender) => {
if (ii < len2) {
let goods = art.goodsGroup.data[ii];
let good = {
thumb: helpers.image(goods.cover.cover, 235, 314),
type: guangProcess.getProductIcon(goods.cover.maxSortId),
thumb: goods.cover ? helpers.image(goods.cover.cover, 235, 314) : '',
type: goods.cover ? guangProcess.getProductIcon(goods.cover.maxSortId) : '',
goods: []
};
let skns = [];
... ...
... ... @@ -85,10 +85,7 @@ exports.resourcesGoodsList = (req, res, next) => {
let param = {};
param = {
productSkn: productSkn.split(','),
yh_channel: req.body.yh_channel,
page: req.body.page,
limit: req.body.limit
productSkn: productSkn.split(',')
};
plusstarModel.getProductBatch(param, {
... ...
... ... @@ -26,13 +26,6 @@ app.use(global.yoho.hbs({
helpers: global.yoho.helpers
}));
// for zookeeper, inject locals
app.use((req, res, next) => {
req.app.locals.wap = app.locals.wap;
next();
});
// router
app.use(require('./router'));
... ...
... ... @@ -243,7 +243,7 @@ const getArticle = (param) => {
}
if (result && result[1] && result[1].data && result[1].data.list) {
if (result && result[1] && result[1].data && result[1].data.list && result[1].data.list.artList) {
let inf = [];
... ...
... ... @@ -14,6 +14,8 @@ const getAllChannels = (params) => {
return api.get('', {
method: 'app.blk.getAllChannels',
app_type: params.app_type
}, {
cache: true
}).then(result => {
let data = {channel: []};
... ... @@ -53,6 +55,8 @@ const getProductBatch = (param, options) => {
yh_channel: param.yh_channel,
page: param.page,
limit: param.limit
}, {
cache: true
}).then(result => {
let data = {};
... ... @@ -90,7 +94,9 @@ const getResources = (params, options) => {
params.platform = 'iphone';
}
return serviceAPI.get('operations/api/v5/resource/get', params).then(result => {
return serviceAPI.get('operations/api/v5/resource/get', params, {
cache: true
}).then(result => {
let data = {
goods: {},
recommend: {}
... ... @@ -178,7 +184,7 @@ const getResourcesData = (params, options) => {
let preferSkns = result[1] && result[1].data || [];
if (result[0] && result[0].goods && result[0].goods.productSkns) {
result[0].goods.productSkns = _.uniq(Object.assign(skns, preferSkns));
result[0].goods.productSkns = _.uniq(skns.concat(preferSkns));
}
return result[0];
... ...
... ... @@ -112,7 +112,7 @@ const _processIndexData = (dataList) => {
formatData.starAvatar.push({
// noLazy: index < 6,
url: url,
cover: data.cover ? (data.cover + '?imageView2/2/w/180/h/180') : data.cover
cover: data.cover ? (data.cover + '?imageView2/2/w/180/h/180/q/90').replace('http:', '') : data.cover.replace('http:', '')
});
});
}
... ...
{{#if result.product_list}}
<input type='hidden' value='{{result.page_total}}' class='page-total' />
{{/if}}
{{#each result.product_list}}
{{> common/goods}}
{{/each}}
\ No newline at end of file
... ...
... ... @@ -6,9 +6,11 @@
<div class="header-content clearfix">
<p class="name-islike-container">
<span class="name">{{brand_name}}</span>
{{#unless @root.wap.plustar.removeCollect}}
<a id="brand-like" class="brand-islike iconfont" href="{{likeUrl}}">
&#xe605;
</a>
{{/unless}}
</p>
<div id="more-intro-click-range" class="clearfix">
<div id="intro" class="intro">
... ... @@ -100,7 +102,9 @@
<input id="jump-to-app" type="hidden" value="{{jumpToApp}}">
<input id="brandId" type="hidden" value="{{brand_id}}">
<input id="clientType" type="hidden" value="{{clientType}}">
{{#unless @root.wap.plustar.removeRelatedPost}}
<input id="related-infos-demote" type="hidden" value="1">
{{/unless}}
{{!-- wx-share --}}
<input id="shareLink" type="hidden" value="{{shareLink}}">
<input id="shareImg" type="hidden" value="{{shareImg}}">
... ...
... ... @@ -26,13 +26,6 @@ app.use(global.yoho.hbs({
helpers: global.yoho.helpers
}));
// for zookeeper, inject locals
app.use((req, res, next) => {
req.app.locals.wap = app.locals.wap;
next();
});
// router
app.use(require('./router'));
... ...
... ... @@ -127,8 +127,9 @@
<span class="iconfont num">&#xe604;</span>
</a>
</div>
{{> common/recommend-for-you}}
{{#unless @root.wap.ucenter.removePrefer}}
{{> common/recommend-for-you}}
{{/unless}}
{{> common/suspend-cart}}
</div>
... ...
... ... @@ -44,7 +44,7 @@ function doPassportCallback(openId, nickname, sourceType, req, res) {
refer: refer
});
} else if (result.code === 200 && result.data.uid) {
return AuthHelper.syncUserSession(result.data.uid, req, res).then(() => {
return AuthHelper.syncUserSession(result.data.uid, req, res, result.data.session_key).then(() => {
return refer;
});
}
... ... @@ -161,7 +161,7 @@ const local = {
}
user.session = refer;
user.href = refer;
AuthHelper.syncUserSession(user.uid, req, res).then(() => {
AuthHelper.syncUserSession(user.uid, req, res, user.session_key).then(() => {
res.json({
code: 200,
data: user
... ...
... ... @@ -28,13 +28,6 @@ app.use(global.yoho.hbs({
helpers: global.yoho.helpers
}));
// for zookeeper, inject locals
app.use((req, res, next) => {
req.app.locals.wap = app.locals.wap;
next();
});
require('./auth');
app.use(passport.initialize());
app.use(passport.session());
... ...
... ... @@ -60,7 +60,12 @@ class Auth {
return api.get('', param);
}
static syncUserSession(uid, req, res) {
static syncUserSession(uid, req, res, sessionKey) {
if (sessionKey) {
global.yoho.cache.set(`java_session_key:${uid}`, sessionKey).catch(() => {
global.yoho.logger.error('write session key fail');
});
}
return Auth.profile(uid).then((userInfo) => {
let token = sign.makeToken(uid);
let data = userInfo.data;
... ...
... ... @@ -135,6 +135,9 @@ const _shop = (req, res, shopId) => {
result.hotList[key].tags.isHot = true;
});
// 有领券功能,不缓存
res.set('Cache-Control', 'no-cache');
res.render('shop/index', {
module: 'product',
page: 'shop',
... ... @@ -292,6 +295,10 @@ const brand = (req, res, next) => {
}).then(brandHome => {
params.brandHome = brandHome;
if (!brandHome || !brandHome.id) {
res.set('Cache-Control', 'no-cache');
}
res.render('search/goods-list', {
module: 'product',
page: 'search-list',
... ...
'use strict';
const mRoot = '../models';
const _ = require('lodash');
const recommendForYouModel = require(`${mRoot}/recommend-for-you`); // 领取优惠券 model
exports.userCenter = (req, res, next) => {
... ... @@ -33,7 +34,9 @@ exports.cart = (req, res, next) => {
uid = req.user.uid || 0,
yhChannel = req.query.yh_channel || '1',
limit = 30;
if (_.get(req, 'app.locals.wap.cart.removePrefer', false)) {
return res.send('');
}
recommendForYouModel.getPreference({
yh_channel: yhChannel,
udid: udid,
... ... @@ -52,4 +55,5 @@ exports.cart = (req, res, next) => {
page: 'recommend'
});
}).catch(next);
};
... ...
... ... @@ -79,6 +79,10 @@ let index = (req, res, next) => {
res.locals.pageChannel = {};
res.locals.pageChannel[req.cookies._Channel] = true;
}
if (!result.length) {
res.set('Cache-Control', 'no-cache');
}
res.render('sale/index', Object.assign(params.renderData, {
content: result,
floorHeader: {
... ...
... ... @@ -132,8 +132,16 @@ const list = (req, res, next) => {
*/
const index = (req, res, next) => {
let title = '搜索';
searchModel.getSearchIndex().then((result) => {
((render) => {
if (_.get(req, 'app.locals.wap.search.removeHotSearch', false)) {
render([]);
} else {
searchModel.getSearchIndex().then((result) => {
render(result);
}).catch(next);
}
})((result) => {
res.render('search/index', {
module: 'product',
page: 'search-index',
... ... @@ -148,7 +156,8 @@ const index = (req, res, next) => {
}
});
}).catch(next);
})
};
/**
... ...
... ... @@ -27,13 +27,6 @@ app.use(global.yoho.hbs({
helpers: global.yoho.helpers
}));
// for zookeeper, inject locals
app.use((req, res, next) => {
req.app.locals.wap = app.locals.wap;
next();
});
// router
app.use(require('./router'));
... ...
... ... @@ -1267,9 +1267,10 @@ const _detailDataPkg = (origin, ua) => {
// colorStorageNum = 0;
// pagecache重构
_.forEach(origin.goods_list, function(value) {
if (value.status === 0 && !origin.isLimitBuy) {
return;
}
//未上架也显示
// if (value.status === 0 && !origin.isLimitBuy) {
// return;
// }
// colorStorageNum = 0;
... ... @@ -1621,9 +1622,10 @@ let _detailDataPkgAsync = (origin, uid, vipLevel, ua) => {
colorStorageNum = 0;
_.forEach(origin.goods_list, function(value) {
if (value.status === 0) {
return;
}
//未上架也显示
// if (value.status === 0) {
// return;
// }
colorStorageNum = 0;
... ...
... ... @@ -343,6 +343,8 @@ let getintroIntro = (data) => {
return api.get('', {
method: 'app.product.intro',
product_skn: data.productskn
}, {
cache: true
}).then(result => {
result = $.load(result);
... ...
... ... @@ -526,6 +526,7 @@ const getBaseShopData = (params, shopInfo) => {
const getShopData = (req, shopId, uid, isApp) => {
let shopData = {};
let channel = req.yoho.channel;
let brandData = [];
return _getShopInfo(shopId, uid).then(shopInfoResult => {
... ... @@ -536,56 +537,73 @@ const getShopData = (req, shopId, uid, isApp) => {
};
}
return Promise.all([
_getShopDecorator(shopId),
searchModel.getFilterSearchData({
shop_id: shopId,
channel: channel
}),
_shopCouponsList(shopId, uid)
]).then((result) => {
shopData = {
decorator: result[0], // 店铺装修资源数据
shopInfo: shopInfoResult // 店铺信息
};
return _getShopDecorator(shopId).then(shopDeco => {
return shopDeco;
}).then(shopDeco => {
let brandBrowseData;
// 取店铺下的brand, id
_.forEach(shopDeco.list, floor => {
if (floor.resource_name === 'brandBrowse') {
brandBrowseData = JSON.parse(floor.resource_data);
_.forEach(brandBrowseData, brandBrowse => {
brandData.push(brandBrowse.id);
});
}
});
/* 获取一次分类和商品数据 */
let shopFilterSearchData = {
filter: [],
goods: []
};
return Promise.all([
searchModel.getFilterSearchData({
shop_id: shopId,
brand: brandData.join(','),
order: '0',
channel: channel
}),
_shopCouponsList(shopId, uid)
]).then((result) => {
shopData = {
decorator: shopDeco, // 店铺装修资源数据
shopInfo: shopInfoResult // 店铺信息
};
if (result[1]) {
shopFilterSearchData.filter = productProcess.processFilter(result[1].filter || []);
shopFilterSearchData.goods = productProcess.processProductList(result[1].product_list || [], {isApp: isApp});
}
/* 获取一次分类和商品数据 */
let shopFilterSearchData = {
filter: [],
goods: []
};
/* 店鋪優惠券 */
let shopCoupons = result[2] || [];
// 店铺分类
return _getShopCategory(shopId, channel).then(shopCategory => {
shopData = _.assign({
shopCategory: shopCategory
}, shopData);
// noinspection JSCheckFunctionSignatures
return Object.assign(
_formShopData(shopData, shopId, isApp),
shopFilterSearchData,
{
shopId: shopId,
uid: uid ? crypto.encryption('', uid + '') : '',
coverChannel: channel,
shopCoupons: shopCoupons,
shopCouponsOne: shopCoupons.length === 1
}
);
if (result[0]) {
shopFilterSearchData.filter = productProcess.processFilter(result[0].filter || []);
shopFilterSearchData.goods = productProcess.processProductList(result[0].product_list || [], {isApp: isApp});
}
/* 店铺优惠券 */
let shopCoupons = result[1] || [];
// 店铺分类
return _getShopCategory(shopId, channel).then(shopCategory => {
shopData = _.assign({
shopCategory: shopCategory
}, shopData);
// noinspection JSCheckFunctionSignatures
return Object.assign(
_formShopData(shopData, shopId, isApp),
shopFilterSearchData,
{
shopId: shopId,
uid: uid ? crypto.encryption('', uid + '') : '',
coverChannel: channel,
shopCoupons: shopCoupons,
shopCouponsOne: shopCoupons.length === 1
}
);
});
});
});
});
};
/**
... ...
... ... @@ -8,6 +8,8 @@ const logger = global.yoho.logger;
const getHotRank = (codeKey) => {
return serviceAPI.get('operations/api/v5/resource/get', {
content_code: codeKey
}, {
cache: true
}).then((result) => {
if (result && result.code === 200) {
... ... @@ -53,7 +55,9 @@ const selectHotrank = (yhChannel, gender, sort, tabId, limit, page, notab) => {
param.tab_id = tabId;
}
return api.get('', param).then((result) => {
return api.get('', param, {
cache: true
}).then((result) => {
if (result && result.code === 200 && result.data.product_list) {
... ...
... ... @@ -251,6 +251,8 @@ const getFuzzyDatas = (params) => {
return api.get('', {
method: 'app.search.fuzzy',
keyword: params
}, {
cache: true
}).then((result) => {
if (result && result.code === 200) {
return result.data;
... ... @@ -270,7 +272,10 @@ const searchKeyActivity = (params) => {
return api.get('', {
method: 'app.search.word',
query: params
}, {code: 200}).then(result => {
}, {
cache: true,
code: 200
}).then(result => {
if (result.data) {
return result.data;
} else {
... ...
... ... @@ -124,6 +124,9 @@
<div class="chose-panel"></div>
<div class="cart-bar data-bind">
{{#unless @root.wap.common.removeCartCount}}
<input type="hidden" id="remove-cart-count" value="1">
{{/unless}}
<a href="" class="num-incart iconfont"><span class="num-tag hide"></span>&#xe62c;</a>
<a id="addtoCart" href="javascript:;" class="addto-cart add-to-cart-url data-bind"></a>
<a id="soldOut" href="javascript:;" class="sold-out data-bind">已售罄</a>
... ...
'use strict';
const SECOND = 1;
const MINUTE = 60 * SECOND;
const cachePage = {
'/': 5 * MINUTE,
// 频道页
'/boys': 30 * SECOND,
'/girls': 30 * SECOND,
'/kids': 30 * SECOND,
'/lifestyle': 30 * SECOND,
// 商品分类
'/cate': 5 * MINUTE,
// 商品详情页
'/product/\\/pro_([\\d]+)_([\\d]+)\\/(.*)/': 30 * MINUTE,
'/product/\\/show_([\\d]+)/': 30 * MINUTE,
// 逛
'/guang/': 1 * MINUTE,
'/guang/info/index': 10 * MINUTE,
'/guang/author/index': 1 * MINUTE,
'/guang/tags/index': 1 * MINUTE,
'/guang/plustar': 1 * MINUTE,
// '/guang/plustar/brandinfo': 1 * MINUTE,
'/guang/star': 1 * MINUTE,
// 领券中心
'/activity/coupon/floor': 5 * MINUTE,
// 商品列表
'/product/list/index': 1 * MINUTE,
'/product/index/index': 1 * MINUTE,
'/product/index/brand': 1 * MINUTE,
'/product/new': 1 * MINUTE,
// 秒杀列表
'/product/seckill': 30 * SECOND,
// 秒杀详情
'/product/^\\/seckill\\/pro_([\\d]+)_([\\d]+)/': 30 * MINUTE,
'/product/^\\/seckill\\/show_([\\d]+)/': 30 * MINUTE,
// sale
'/product/sale': 5 * MINUTE,
'/product/sale/discount': 5 * MINUTE,
'/product/sale/vip': 5 * MINUTE,
'/product/sale/breakingYards': 5 * MINUTE,
'/product/sale/discount/detail': 5 * MINUTE,
// 奥莱
'/product/outlet': 30 * SECOND,
'/product/outlet/activity': 1 * MINUTE,
// 品牌一览
'/brands': 5 * MINUTE,
'/brands/search': 1 * MINUTE
};
module.exports = cachePage;
... ...
... ... @@ -16,15 +16,15 @@ module.exports = {
siteUrl: '//m.yohobuy.com',
assetUrl: '//localhost:5001',
domains: {
// api: 'http://api-test3.yohops.com:9999/',
// service: 'http://service-test3.yohops.com:9999/',
// liveApi: 'http://testapi.live.yohops.com:9999/',
// singleApi: 'http://api-test3.yohops.com:9999/'
api: 'http://api-test3.yohops.com:9999/',
service: 'http://service-test3.yohops.com:9999/',
liveApi: 'http://testapi.live.yohops.com:9999/',
singleApi: 'http://api-test3.yohops.com:9999/'
api: 'http://api.yoho.cn/',
service: 'http://service.yoho.cn/',
liveApi: 'http://api.live.yoho.cn/',
singleApi: 'http://single.yoho.cn/'
// api: 'http://api.yoho.cn/',
// service: 'http://service.yoho.cn/',
// liveApi: 'http://api.live.yoho.cn/',
// singleApi: 'http://single.yoho.cn/'
},
subDomains: {
host: '.m.yohobuy.com',
... ... @@ -67,7 +67,7 @@ module.exports = {
port: '4444' // influxdb port
},
console: {
level: 'debug',
level: 'error',
colorize: 'all',
prettyPrint: true
}
... ... @@ -78,7 +78,7 @@ module.exports = {
appSecret: 'ce21ae4a3f93852279175a167e54509b'
}
},
zookeeperServer: false // '10.66.1.97:2181'
zookeeperServer: '192.168.102.168:2188'
};
if (isProduction) {
... ... @@ -103,7 +103,8 @@ if (isProduction) {
interfaceShunt: {
open: false,
url: 'http://123.206.2.55/strategy'
}
},
zookeeperServer: '10.66.1.97:2181'
});
} else if (isTest) {
Object.assign(module.exports, {
... ...
'use strict';
const cachePage = require('../../config/cache');
const logger = global.yoho.logger;
const _ = require('lodash');
function urlJoin(a, b) {
if (_.endsWith(a, '/') && _.startsWith(b, '/')) {
return a + b.substring(1, b.length);
} else if (!_.endsWith(a, '/') && !_.startsWith(b, '/')) {
return a + '/' + b;
} else {
return a + b;
}
}
module.exports = () => {
return (req, res, next) => {
function onRender() {
let route = req.route ? req.route.path : '';
let appPath = req.app.mountpath;
if (_.isArray(route) && route.length > 0) {
route = route[0];
}
let key = urlJoin(appPath, route.toString()); // route may be a regexp
req.app.set('etag', false);
logger.debug(`route: ${key} cache = ${cachePage[key]}`);
// 如果存在cache配置,并且业务代码中没有设置
if (cachePage[key] && res.get('Cache-Control') !== 'no-cache') {
res.set({
'Cache-Control': 'max-age=' + cachePage[key]
});
res.removeHeader('Pragma');
res.removeHeader('Expires');
} else if (req.get('X-Requested-With') === 'XMLHttpRequest') {
res.set('Cache-Control', 'no-cache');
} else {
res.set({
'Cache-Control': 'no-cache',
Pragma: 'no-cache',
Expires: new Date(1900, 0, 1, 0, 0, 0, 0)
});
}
}
res.on('render', onRender);
next();
};
};
... ...
... ... @@ -4,5 +4,6 @@
</a>
{{#unless @root.wap.common.removeCartCount}}
<span class="cart-count hide">0</span>
<input type="hidden" id="remove-cart-count" value="1">
{{/unless}}
</div>
... ...
/**
* OneAPM agent configuration
*/
const commonConfig = require('./config/common');
exports.config = {
app_name: [commonConfig.appName],
license_key: 'BwEGA1dRDlQ6357HHQ1AD1xJVkbc9fNfWRtQUwhQG41c5QFWGFIDSQoHc0e8AgMaUlcUVw0=',
logging: {
level: 'info'
},
transaction_events: {
enabled: true
}
};
{
"name": "m-yohobuy-node",
"version": "5.1.0",
"version": "5.1.2",
"private": true,
"description": "A New Yohobuy Project With Express",
"repository": {
... ... @@ -21,6 +21,7 @@
"bluebird": "^3.4.6",
"body-parser": "^1.15.2",
"cheerio": "^0.22.0",
"compression": "^1.6.2",
"connect-multiparty": "^2.0.0",
"cookie-parser": "^1.4.3",
"cookie-session": "^1.2.0",
... ... @@ -38,7 +39,7 @@
"request-promise": "^3.0.0",
"serve-favicon": "^2.3.0",
"uuid": "^2.0.3",
"yoho-node-lib": "^0.1.24",
"yoho-node-lib": "0.1.29",
"yoho-zookeeper": "^1.0.3"
},
"devDependencies": {
... ...
... ... @@ -10,7 +10,7 @@ var $searchBox = $('.search-box'),
$box = $('.box'),
$indexSearch = $('.index-search'),
$indexLogo = $('.index-logo'),
$channelLink = $('.index-channel a:not(#yohood)');
$channelLink = $('.index-channel a:not(.no-touch)');
var $search = $searchBox.children('input[type="text"]'),
$cancelSearch = $box.children('.no-search'),
... ...
... ... @@ -7,22 +7,24 @@
var $ = require('yoho-jquery');
var $cart = $('#suspend-cart');
if ($('#remove-cart-count').length) {
$.ajax({
type: 'GET',
url: '/cart/index/count',
success: function(data) {
var count;
$.ajax({
type: 'GET',
url: '/cart/index/count',
success: function(data) {
var count;
if (data.code === 200) {
count = data.data.cart_goods_count;
if (count > 99) {
count = '99+';
}
if (count === 0) {
$('.cart-count').remove();
if (data.code === 200) {
count = data.data.cart_goods_count;
if (count > 99) {
count = '99+';
}
if (count === 0) {
$('.cart-count').remove();
}
$cart.find('.cart-count').html(count).removeClass('hide');
}
$cart.find('.cart-count').html(count).removeClass('hide');
}
}
});
});
}
... ...
... ... @@ -211,7 +211,7 @@ function loadMore($container, opt, url) {
loading.showLoadingMask();
}
opt.app_version = '1';
opt.app_version = window.queryString.app_version || '';
num = $container.find('.guang-info').length;
searching = true;
... ... @@ -278,4 +278,4 @@ exports.mySwiper = mySwiper;
exports.initSwiper = initSwiper;
exports.initInfosEvt = initInfosEvt;
exports.setLazyLoadAndMellipsis = setLazyLoadAndMellipsis;
exports.loadMore = loadMore;
\ No newline at end of file
exports.loadMore = loadMore;
... ...
... ... @@ -37,17 +37,15 @@ plusstar = {
$tabUlDom = $('.plusstar-page .tab-nav ul');
// 重置tab code位置
if (window.localStorage) {
$tabUlDom.find('li').each(function() {
localStorage.setItem($(this).data('code'), 0);
});
}
$tabUlDom.find('li').css({
width: 100 / $tabUlDom.find('li').length + '%'
});
$tabUlDom.find('li').each(function() {
// 重新进入滑动位置清除
window.setCookie($(this).data('code'), 0);
});
// 事情委托机制
$tabUlDom.bind('click', function(event) {
$liDom = $(event.target).closest('li');
... ... @@ -65,16 +63,16 @@ plusstar = {
if (window._yas && window._yas.sendCustomInfo) {
window._yas.sendCustomInfo({
op: 'YB_FASHION_TAB_C',
param: JSON.stringify($.extend(speckParamApp, {
param: JSON.stringify($.extend({
TAB_ID: $liDom.index() + 1
}))
}, speckParamApp))
}, true);
window._yas.sendCustomInfo({
op: 'YB_FASHION_HOME_L',
param: JSON.stringify($.extend(speckParamApp, {
param: JSON.stringify($.extend({
TAB_ID: that.ParentLiDom.index() + 1
}))
}, speckParamApp))
}, true);
}
});
... ... @@ -87,10 +85,10 @@ plusstar = {
}
$tabUlDom.find('li').removeClass('focus');
$liDom.addClass('focus');
that.ParentLiDom = $liDom;// 保留当前tab先中的对象
that.tabNav($liDom.data('code'));
// ent -- 默认选中
that.ParentLiDom = $liDom;// 保留当前tab先中的对象
setTimeout(function() {
that._yas();
}, 1000);
... ... @@ -111,28 +109,28 @@ plusstar = {
// 商品单击埋点
$dom = $(event.target).closest('.good-info');
index = $dom.index() + 1;
window.givePoint($.extend(speckParamApp, {
window.givePoint($.extend({
REC_POSE: RECPOSE,
PRD_ID: $dom.data('good-id'),
ORDER_CODE: '',
PRD_NUM: index % that.common.pagesize === 0 ? that.common.pagesize : index % that.common.pagesize,
ACTION_ID: 1,
page_num: Math.ceil(index / that.common.pagesize)
}));
}, speckParamApp));
} else if ($(event.target).closest('.banner-top').length > 0) {
// 头部banner楼层埋点
$dom = $(event.target).closest('li');
index = $dom.index() + 1;
window._yas.sendCustomInfo({
op: 'YB_FASHION_FLR_C',
param: JSON.stringify($.extend(speckParamApp, {
param: JSON.stringify($.extend({
TAB_ID: that.ParentLiDom.index() + 1,
F_ID: $dom.closest('ul').data('id'),
F_NAME: '焦点图',
F_URL: $dom.find('a').attr('href'),
F_INDEX: 1,
I_INDEX: index % 2 + 1// banner,li是双倍的
}))
}, speckParamApp))
}, true);
} else if ($(event.target).closest('.speck-title-image a').length > 0) {
// 各楼层埋点
... ... @@ -141,14 +139,14 @@ plusstar = {
window._yas.sendCustomInfo({
op: 'YB_FASHION_FLR_C',
param: JSON.stringify($.extend(speckParamApp, {
param: JSON.stringify($.extend({
TAB_ID: that.ParentLiDom.index() + 1,
F_ID: $dom.data('fid'),
F_NAME: $dom.data('name'),
F_URL: $domA.attr('href'),
F_INDEX: $dom.index() + 1,
I_INDEX: $domA.hasClass('more') ? 0 : ($domA.index() + 1)
}))
}, speckParamApp))
}, true);
}
});
... ... @@ -156,9 +154,9 @@ plusstar = {
// 潮流优选首页加载时
window._yas.sendCustomInfo({
op: 'YB_FASHION_HOME_L',
param: JSON.stringify($.extend(speckParamApp, {
param: JSON.stringify($.extend({
TAB_ID: that.ParentLiDom.index() + 1
}))
}, speckParamApp))
}, true);
},
tabNav: function(code) {
... ... @@ -166,14 +164,16 @@ plusstar = {
this.common.codeDefault = code;// 记住最后一次的tab code
this.common.page = 1;// 商品列表从第一页开始
searching = false;
searching = false;//初始化翻页
$.ajax({
type: 'GET',
url: '/guang/plusstar/resources-template',
data: {
code: code,
app_version: isApp
uid: window.queryString.uid,
app_version: isApp,
yh_channel: that.ParentLiDom.index() + 1
},
dataType: 'html',
success: function(data) {
... ... @@ -186,20 +186,19 @@ plusstar = {
return true;
}
// 记录切换tab位置
$(document).scrollTop(window.cookie(code) || 0);
that.resInit();
$('.plusstar-resources').find('img.lazy').lazyload();
// 设置滚动条的位置
if (window.localStorage) {
$(document).scrollTop(localStorage.getItem(code) || 0);
}
productSkns = $(data).find('.product-skns').val();
if (productSkns) {
that.common.productSkns = productSkns.split(',');
}
that.common.pageTotal = Math.ceil(that.common.productSkns.length / that.common.pagesize);
},
error: function() {
tip.show('网络断开连接了~');
... ... @@ -226,9 +225,8 @@ plusstar = {
skn = [];
if (searching) {
return true;
return;
}
searching = true;
if (that.common.page > that.common.pageTotal) {
... ... @@ -236,44 +234,38 @@ plusstar = {
}
loading.showLoadingMask();
skn = that.common.productSkns.slice((that.common.page - 1) * that.common.pagesize, that.common.page * that.common.pagesize);
$.ajax({
type: 'POST',
url: '/guang/plusstar/resources-goodsList',
timeout: 5000,
data: {
productSkn: that.common.productSkns.join(','),
app_version: isApp,
limit: that.common.pagesize,
page: that.common.page,
yh_channel: that.ParentLiDom.index() + 1
productSkn: skn.join(','),
app_version: isApp
},
dataType: 'html',
success: function(data) {
skn = [];
searching = false;
loading.hideLoadingMask();
searching = false;
that.common.page++;
if (data === '') {
return true;
}
if (that.common.page <= 1) {
that.common.pageTotal = $(data).siblings('.page-total').val();
}
$.each($(data).siblings('.good-info'), function() {
skn.push($(this).data('good-id'));
});
window.givePoint($.extend(speckParamApp, {
window.givePoint($.extend({
REC_POSE: RECPOSE,
PRD_ID: skn.join(','),
ORDER_CODE: '',
PRD_NUM: that.common.pagesize,
ACTION_ID: 0,
page_num: that.common.page++
}));
page_num: that.common.page - 1
}, speckParamApp));
$('.plusstar-resources .goods').append(data);
... ... @@ -292,15 +284,14 @@ plusstar = {
scrollFn = debounce(function() {
scrollTop = $(document).scrollTop();
// 保留滑动位置,产品要求
window.setCookie(plusstar.common.codeDefault, $(this).scrollTop());
// 当scroll到最后一列商品的高度后继续请求下一页数据
if (400 + scrollTop >= $(document).height() - windowHeight) {
plusstar.goodsList();
}
if (window.localStorage) {
localStorage.setItem(plusstar.common.codeDefault, $(this).scrollTop());
}
}, 200);
$(function() {
... ...
... ... @@ -7,7 +7,7 @@ var $ = require('yoho-jquery'),
module.exports = function(callback) {
var brandId = $('#brandId').val();
var clientType = $('#clientType').val();
if (brandId) {
if (brandId && $('#related-infos-demote').length) {
$.ajax({
type: 'POST',
url: '/guang/plustar/brandinfoAsync',
... ...
... ... @@ -88,54 +88,54 @@ moreHammer.on('tap', function(e) {
e.preventDefault(); // 防止收缩后误点到商品产生跳转
});
// 品牌收藏
likeHammer = new Hammer(document.getElementById('brand-like'));
likeHammer.on('tap', function(e) {
var opt = 'ok',
$this = $(e.target);
// jumpToApp = 1表示APP未登录的情况,此时不发送ajax请求而由a链接直接跳转APP
// if (jumpToApp === '1') {
// return true;
// }
e.preventDefault();
if ($this.hasClass('like')) {
opt = 'cancel';
}
$.ajax({
type: 'POST',
url: '/guang/opt/favoriteBrand',
data: {
id: brandId,
opt: opt,
uid: uid,
isBrand: 'brand'
},
success: function(data) {
if (data.code === 200) {
$this.toggleClass('like');
tip.show(data.message);
} else if (data.code === 400 || data.code === 412) {
if (jumpToApp === '1') {
var url = location.href + '&openby:yohobuy={"action":"go.weblogin","params":{"jumpurl":{"url":"http:\/\/guang.m.yohobuy.com\/plustar\/brandinfo","param":{"id":'
+ window.queryString.id + '}},"requesturl":{"url":"\/guang\/api\/v1\/favorite\/togglebrand","param":{"brand_id":"' + $('#brand-info').data('id') + '"}},"priority":"Y"}}';
$('body').append('<a href=' + url + ' style="display:none;"><span class="jump-login">&nbsp;</span></a>');
$('.jump-login').click();
if ($('#brand-like').length) {
// 品牌收藏
likeHammer = new Hammer(document.getElementById('brand-like'));
likeHammer.on('tap', function(e) {
var opt = 'ok',
$this = $(e.target);
// jumpToApp = 1表示APP未登录的情况,此时不发送ajax请求而由a链接直接跳转APP
// if (jumpToApp === '1') {
// return true;
// }
e.preventDefault();
if ($this.hasClass('like')) {
opt = 'cancel';
}
$.ajax({
type: 'POST',
url: '/guang/opt/favoriteBrand',
data: {
id: brandId,
opt: opt,
uid: uid,
isBrand: 'brand'
},
success: function(data) {
if (data.code === 200) {
$this.toggleClass('like');
tip.show(data.message);
} else if (data.code === 400 || data.code === 412) {
if (jumpToApp === '1') {
var url = location.href + '&openby:yohobuy={"action":"go.weblogin","params":{"jumpurl":{"url":"http:\/\/guang.m.yohobuy.com\/plustar\/brandinfo","param":{"id":'
+ window.queryString.id + '}},"requesturl":{"url":"\/guang\/api\/v1\/favorite\/togglebrand","param":{"brand_id":"' + $('#brand-info').data('id') + '"}},"priority":"Y"}}';
$('body').append('<a href=' + url + ' style="display:none;"><span class="jump-login">&nbsp;</span></a>');
$('.jump-login').click();
} else {
location.href = data.data; // 未登录跳转登录页面
}
} else {
location.href = data.data; // 未登录跳转登录页面
tip.show(data.message);
}
} else {
tip.show(data.message);
}
},
error: function() {
tip.show('网络断开连接了~');
}
});
return false;
});
return false;
});
}
// console.log($('.logo').attr('src'))
... ...
... ... @@ -13,8 +13,10 @@ var myImage = new Image(),
avatar;
require('../common');
require('./recommend-for-you-user-center');
require('../product/suspend-cart.js');
if ($('.recommend-for-you').length) {
require('./recommend-for-you-user-center');
}
require('../common/suspend-cart');
require('../common/footer');
// 部分老用户没有头像,显示默认头像
... ...
... ... @@ -126,25 +126,27 @@ require('./detail/page-render')(function() {
require('./detail/consultform');
require('./detail/recommend-for-you-product-desc');
// 购物车商品数量
$.ajax({
type: 'GET',
url: '/cart/index/count',
success: function(data) {
var count;
if (data.code === 200) {
count = data.data.cart_goods_count || 0;
if (count === 0) {
return false;
}
if (count > 99) {
count = '99+';
if ($('#remove-cart-count').length) {
// 购物车商品数量
$.ajax({
type: 'GET',
url: '/cart/index/count',
success: function(data) {
var count;
if (data.code === 200) {
count = data.data.cart_goods_count || 0;
if (count === 0) {
return false;
}
if (count > 99) {
count = '99+';
}
$cart.find('.num-tag').html(count).removeClass('hide');
}
$cart.find('.num-tag').html(count).removeClass('hide');
}
}
});
});
}
if ($('.good-detail-page').length > 0) {
$('#yoho-footer').css('border-top', '1px solid #e0e0e0');
... ...
... ... @@ -128,25 +128,27 @@ require('./detail/page-render')(function() {
require('./detail/consultform');
require('./detail/recommend-for-you-product-desc');
// 购物车商品数量
$.ajax({
type: 'GET',
url: '/cart/index/count',
success: function(data) {
var count;
if (data.code === 200) {
count = data.data.cart_goods_count || 0;
if (count === 0) {
return false;
}
if (count > 99) {
count = '99+';
if ($('#remove-cart-count').length) {
// 购物车商品数量
$.ajax({
type: 'GET',
url: '/cart/index/count',
success: function(data) {
var count;
if (data.code === 200) {
count = data.data.cart_goods_count || 0;
if (count === 0) {
return false;
}
if (count > 99) {
count = '99+';
}
$cart.find('.num-tag').html(count).removeClass('hide');
}
$cart.find('.num-tag').html(count).removeClass('hide');
}
}
});
});
}
if ($('.good-detail-page').length > 0) {
$('#yoho-footer').css('border-top', '1px solid #e0e0e0');
... ...
... ... @@ -101,7 +101,7 @@ var $listNav = $('#list-nav'),
end: false
},
newest: {
order: 1,
order: 0,
reload: true,
page: 0,
end: false
... ...
... ... @@ -8,21 +8,23 @@ var $ = require('yoho-jquery');
var $cart = $('#suspend-cart');
$.ajax({
type: 'GET',
url: '/cart/index/count',
success: function(data) {
var count;
if ($('#remove-cart-count').length) {
$.ajax({
type: 'GET',
url: '/cart/index/count',
success: function(data) {
var count;
if (data.code === 200) {
count = data.data.cart_goods_count;
if (count > 99) {
count = '99+';
if (data.code === 200) {
count = data.data.cart_goods_count;
if (count > 99) {
count = '99+';
}
if (count === 0) {
$('.cart-count').remove();
}
$cart.find('.cart-count').html(count).removeClass('hide');
}
if (count === 0) {
$('.cart-count').remove();
}
$cart.find('.cart-count').html(count).removeClass('hide');
}
}
});
});
}
\ No newline at end of file
... ...
... ... @@ -3,6 +3,20 @@
margin: 0 auto;
width: 100%;
#double11 {
display: block;
width: 432px;
height: 100px;
margin: 0 auto;
background-color: transparent;
background-image: resolve("channel/11.11.png");
background-size: 100%;
&:active {
background-image: resolve("channel/11.11-touch.png");
}
}
#yohood {
border: none;
border-bottom: 8px solid #fff;
... ...