Authored by 陈峰

Merge branch 'release/0619' into 'gray'

Release/0619



See merge request !312
... ... @@ -55,7 +55,17 @@ app.locals.version = pkg.version;
// zookeeper
if (config.zookeeperServer) {
require('yoho-zookeeper')(config.zookeeperServer, 'pc', app.locals.pc = {}, global.yoho.cache);
const monitor = global.yoho.monitorSender;
const monitorType = _.get(monitor, 'type.ZOOKEEPER');
require('yoho-zookeeper')(config.zookeeperServer, 'pc', app.locals.pc = {}, global.yoho.cache, {
onerror: (err) => {
monitor.tallyFail(monitorType, {
code: err.code,
message: err.name
});
}
});
}
app.enable('trust proxy');
... ... @@ -147,6 +157,7 @@ try {
const pageCache = require('./doraemon/middleware/page-cache');
const devtool = require('./doraemon/middleware/devtools');
const routeEncode = require('./doraemon/middleware/route-encode');
const footerData = require('./doraemon/middleware/footerData');
// YOHO 前置中间件
app.use(setYohoData());
... ... @@ -167,6 +178,7 @@ try {
app.use(layoutTools());
app.use(pageCache());
app.use(routeEncode.md);
app.use(footerData());
if (app.locals.devEnv) {
app.use(devtool());
... ...
... ... @@ -7,7 +7,7 @@ const sm = require('sitemap');
const staticUrls = require('../../../config/staticUrls');
const headerModel = require('../../../doraemon/models/header');
const siteMapService = require('../models/site-map-service');
const redis = global.yoho.redis;
const cache = global.yoho.cache;
const getStaticUrls = (currentStatics) => {
let urls = [];
... ... @@ -36,7 +36,7 @@ const getStaticUrls = (currentStatics) => {
// 关键词页面
const keywordsPage = (page) => {
return redis.getAsync(`global:yoho:seo:keywords:allIds:page:${page}`).then(function(res) {
return cache.getAsync(`global:yoho:seo:keywords:allIds:page:${page}`).then(function(res) {
let pages = [];
_.forEach(JSON.parse(res), val => {
... ...
... ... @@ -16,9 +16,7 @@ const yohobuy = (req, res, next) => {
let channel = req.yoho.channel || 'boys';
req.ctx(headerModel).requestHeaderData(channel).then(result => {
responseData.headerData = result.headerData;
res.render('yohobuy', responseData);
res.render('yohobuy', Object.assign({}, responseData, result));
}).catch(next);
};
... ... @@ -29,9 +27,7 @@ const newpower = (req, res, next) => {
let channel = req.yoho.channel || 'boys';
req.ctx(headerModel).requestHeaderData(channel).then(result => {
responseData.headerData = result.headerData;
res.render('newpower', responseData);
res.render('newpower', Object.assign({}, responseData, result));
}).catch(next);
};
... ... @@ -42,9 +38,7 @@ const contact = (req, res, next) => {
let channel = req.yoho.channel || 'boys';
req.ctx(headerModel).requestHeaderData(channel).then(result => {
responseData.headerData = result.headerData;
res.render('contact', responseData);
res.render('contact', Object.assign({}, responseData, result));
}).catch(next);
};
... ... @@ -55,9 +49,7 @@ const privacy = (req, res, next) => {
let channel = req.yoho.channel || 'boys';
req.ctx(headerModel).requestHeaderData(channel).then(result => {
responseData.headerData = result.headerData;
res.render('privacy', responseData);
res.render('privacy', Object.assign({}, responseData, result));
}).catch(next);
};
... ... @@ -71,9 +63,7 @@ const link = (req, res, next) => {
req.ctx(headerModel).requestHeaderData(channel),
req.ctx(aboutModel).link(),
]).then(result => {
responseData.headerData = _.get(result, '[0].headerData');
res.render('link', Object.assign(_.get(result, '[1]', {}), responseData));
res.render('link', Object.assign(_.get(result, '[1]', {}), responseData, result[0]));
}).catch(next);
};
... ...
... ... @@ -42,7 +42,8 @@ function getCouponData(channel, params) {
const coupon = requestData[0];
result.headerData = requestData[1].headerData;
// 页面头部和底部友情链接
Object.assign(result, requestData[1]);
do { // eslint-disable-line
if (!coupon.data || !Array.isArray(coupon.data) || coupon.data.length === 0) {
... ...
... ... @@ -58,7 +58,7 @@ function index(skn, limit) {
price: ${helper.round(sp, 2)}`,
product_name: hp.product_name,
url: helper.getUrlBySkc(hp.product_skn),
pic_url: helper.image(defaultGoods.images_url, 280, 382, 2, 70)
pic_url: defaultGoods && helper.image(defaultGoods.images_url, 280, 382, 2, 70)
});
});
... ...
... ... @@ -231,9 +231,9 @@ const getShopHomeSeo = (shopInfo) => {
}
return {
title: `${params.nameEn} | ${params.name}品牌旗舰店 | 正品保证, YOHO!BUY 有货`,
keywords: `${params.nameEn}, ${params.name}品牌旗舰店,${params.name}正品`,
description: `有货网${params.nameEn}旗舰店销售${params.name}正品商品,100%质量保证,支持货到付款,想了解${params.name}价格、图片、评价等信息,就上YOHO!BUY 有货中国大型潮流商品购物网站!` // eslint-disable-line
title: `${params.nameEn}_${params.name}品牌官方旗舰店-YOHO!BUY 有货官网`,
keywords: `${params.nameEn},${params.name}品牌官方旗舰店`,
description: `潮流网购就上YOHO!BUY有货官网,${params.nameEn}品牌官方旗舰店提供${params.name}品牌商品价格、图片、款式等信息,销售${params.name}品牌正品商品,全场低至4,★品牌正品保证,支持货到付款!★` // eslint-disable-line
};
};
... ...
... ... @@ -155,9 +155,9 @@ module.exports = {
zookeeperServer: '127.0.0.1:2181',
redis: {
connect: {
host: '127.0.0.1',
// host: '127.0.0.1',
// host: '192.168.102.49',
host: '192.168.102.49',
port: '6379',
enable_offline_queue: false,
retry_strategy(options) {
... ... @@ -247,6 +247,11 @@ if (isProduction) {
host: 'badjs.yoho.cn',
port: 80,
db: 'web-apm'
},
monitorReport: {
host: '10.66.4.25',
port: 8086,
db: 'web_monitor',
}
});
} else if (isTest) {
... ... @@ -264,6 +269,11 @@ if (isProduction) {
yohoNowApi: process.env.YOHO_NOW_API || 'http://yohonow-test.yohops.com:9999/',
},
useOneapm: true,
useCache: true
useCache: true,
monitorReport: {
host: '192.168.102.22',
port: 8086,
db: 'web_monitor',
}
});
}
... ...
'use strict';
const _ = require('lodash');
const redis = global.yoho.redis;
let footerLinks = [];
let firstTime = 0;
// 底部数据
module.exports = () => {
return (req, res, next) => {
if (req.xhr || req.path !== '/') {
return next();
}
// 5min Invalid
if (footerLinks.length && (Date.now() - firstTime) > 300000) {
Object.assign(res.locals, {footerLinks});
return next();
}
return redis.all([
['get', 'friend:footer:links']
]).then(result => {
footerLinks = _.sortBy(JSON.parse(result[0] || '[]'), o => {
return -o.sort;
});
Object.assign(res.locals, {footerLinks});
firstTime = Date.now();
return next();
});
};
};
... ...
... ... @@ -4,6 +4,7 @@ const redis = require('redis');
const bluebird = require('bluebird');
const config = require('../../config/common');
const logger = global.yoho.logger;
const monitor = global.yoho.monitorSender;
const timeout = 200; // redis 操作超时时间
let client;
... ... @@ -13,8 +14,11 @@ try {
bluebird.promisifyAll(redis.RedisClient.prototype);
bluebird.promisifyAll(redis.Multi.prototype);
const monitorType = _.get(monitor, 'type.REDIS');
client.all = args => {
if (!client.ready) {
monitor && monitor.tallyFail(monitorType);
if (Array.isArray(args)) {
return Promise.resolve(_.fill(args, false));
} else {
... ... @@ -22,7 +26,11 @@ try {
}
}
return client.multi.call(client, args).execAsync().timeout(timeout).catch(()=>{
return client.multi.call(client, args).execAsync().timeout(timeout).then(res => {
monitor && monitor.tallySuccess(monitorType);
return res;
}).catch((e)=>{
monitor && monitor.tallyFail(monitorType, e);
logger.error('redis exe time out');
return false;
});
... ...
... ... @@ -5,6 +5,8 @@ const session = require('yoho-express-session');
const cookieSession = require('client-sessions');
const redis = require('connect-redis');
const RedisStore = redis(session);
const monitor = global.yoho.monitorSender;
const monitorType = _.get(monitor, 'type.REDIS');
/**
* 该中间件主要把 express-session 和 client-session 集中起来处理,如果 redis 出错了,使用 cookie session
... ... @@ -63,7 +65,12 @@ module.exports = (app) => {
getid() {
return uuid.v4();
},
store: new RedisStore(config.redis.session)
store: new RedisStore(Object.assign(config.redis.session, {
logErrors: (e) => {
// 上报redis session错误
monitor && monitor.tallyFail(monitorType, e);
}
}))
}));
app.use(cookieSession({ // eslint-disable-line
... ...
... ... @@ -212,6 +212,21 @@
</div>
</div>
</div>
{{#if footerLinks}}
<div class="footer-link-container">
<div class="center-content clearfix">
<div class="link-info left">友情链接:</div>
<div class="link-section left">
<ul class="clearfix">
{{# footerLinks}}
<li><a href="{{link}}" target="_blank" rel="nofollow">{{name}}</a></li>
{{/ footerLinks}}
</ul>
</div>
</div>
</div><!--/footer-link-container-->
{{/if}}
</div>
<div class="right-floating-layer hide">
<div class="qrcode-hover-box">
... ...
{
"name": "yohobuy-node",
"version": "6.6.4",
"version": "6.6.5",
"private": true,
"description": "A New Yohobuy Project With Express",
"repository": {
... ... @@ -57,8 +57,8 @@
"urlencode": "^1.1.0",
"uuid": "^2.0.2",
"yoho-express-session": "^2.0.0",
"yoho-node-lib": "=0.6.16",
"yoho-zookeeper": "^1.0.8"
"yoho-node-lib": "=0.6.17",
"yoho-zookeeper": "^1.0.10"
},
"devDependencies": {
"autoprefixer": "^8.3.0",
... ...
... ... @@ -15,6 +15,41 @@ var $feedBackBox = $('.feed-back-box');
lazyLoad($('img.lazy'));
// 底部友情链接动画效果
function footerLink(num) {
var n = 0;
var intv = 0;
var $linkSection = $('.footer-link-container .link-section');
if (num <= 1) {
return false;
}
function footerLinkSub() {
intv = setInterval(function() {
var top = -48 * ++n;
if (n >= num) {
n = 0;
$linkSection.css({top: 48}).animate({top: 0}, 200);
return true;
}
$linkSection.animate({top: top}, 300);
}, 3000);
}
footerLinkSub();
$linkSection.hover(function() {
clearInterval(intv);
}, function() {
footerLinkSub();
});
}
footerLink(Math.ceil($('.link-section').height() / 48));
/**
* 订阅
* @return {[type]} [description]
... ...
... ... @@ -510,6 +510,52 @@
margin-top: 0;
}
}
.footer-link-container {
background: #000;
height: 48px;
overflow: hidden;
width: 100%;
& > div {
padding-top: 15px;
border-top: 1px solid #262626;
}
.link-info {
font-size: 12px;
color: #fff;
letter-spacing: 0;
width: 60px;
height: 48px;
}
.link-section {
opacity: 0.9;
font-size: 12px;
letter-spacing: 0;
width: 1090px;
position: relative;
li {
display: inline-block;
margin-left: 22px;
height: 48px;
&:first-child {
margin-left: 11px;
}
}
li > a {
color: #666;
&:hover {
text-decoration: underline;
}
}
}
}
}
.yoho-footer .right-floating-layer.min {
... ...