Showing 74 changed files with 1489 additions and 1155 deletions
... ... @@ -7,25 +7,33 @@
const config = require('./config/common');
global.Promise = require('bluebird');
const yohoLib = require('yoho-node-lib');
// 全局注册library
yohoLib.global(config);
const EventEmitter = require('events');
EventEmitter.defaultMaxListeners = 100;
const express = require('express');
const compression = require('compression');
const path = require('path');
const bodyParser = require('body-parser');
const cookieParser = require('cookie-parser');
const favicon = require('serve-favicon');
const session = require('yoho-express-session');
const _ = require('lodash');
const fp = require('lodash/fp');
const memcached = require('connect-memcached');
const hbs = require('express-handlebars');
const session = require('cookie-session');
const pkg = require('./package.json');
const yohoLib = require('yoho-node-lib');
const app = express();
const helpers = global.yoho.helpers;
const MemcachedStore = memcached(session);
// 全局注册library
yohoLib.global(config);
// NOTE: 这里修改了图片质量的参数
helpers.image = _.flow(helpers.image, fp.replace(/\/quality\/\d*$/, '/quality/90'));
global.middleware = path.resolve('./doraemon/middleware');
global.utils = path.resolve('./utils');
... ... @@ -35,45 +43,34 @@ global.appRoot = path.resolve(__dirname);
app.locals.devEnv = app.get('env') === 'development';
app.locals.version = pkg.version;
// zookeeper
if (config.zookeeperServer) {
require('yoho-zookeeper')(config.zookeeperServer, 'pc', app.locals.pc = {});
}
app.set('subdomain offset', 2);
app.set('view engine', '.hbs');
app.set('views', './doraemon/views');
app.set('view cache', true);
app.engine('.hbs', hbs({
app.use(global.yoho.hbs({
extname: '.hbs',
defaultLayout: 'layout',
layoutsDir: './doraemon/views',
partialsDir: './doraemon/views/partial',
layoutsDir: path.join(__dirname, 'doraemon/views'),
partialsDir: path.join(__dirname, 'doraemon/views/partial'),
views: path.join(__dirname, 'doraemon/views'),
helpers: global.yoho.helpers
}));
app.use(global.yoho.middleware());
app.use(favicon(path.join(__dirname, '/public/favicon.ico')));
app.use(express.static(path.join(__dirname, 'public')));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: false}));
app.use(cookieParser());
app.use(compression());
app.use(session({
proxy: true,
resave: false,
saveUninitialized: true,
unset: 'destroy',
name: 'yohobuy_session_cookie',
secret: '82dd7e724f2c6870472c89dfa43cf48d',
name: 'yohobuy_session',
cookie: {
domain: 'yohobuy.com',
httpOnly: false
},
store: new MemcachedStore({
hosts: config.memcache.session,
prefix: 'yohobuy_session:',
poolSize: 25,
reconnect: 5000,
timeout: 1000,
retries: 1,
retry: 3000
})
domain: config.cookieDomain
}));
app.use((req, res, next) => {
... ... @@ -88,6 +85,7 @@ const logger = global.yoho.logger;
// dispatcher
try {
const subDomain = require('./doraemon/middleware/sub-domain');
const mobileRefer = require('./doraemon/middleware/mobile-refer');
const itemNameHandler = require('./doraemon/middleware/item-name-handler');
const mobileCheck = require('./doraemon/middleware/mobile-check');
const user = require('./doraemon/middleware/user');
... ... @@ -95,9 +93,11 @@ try {
const setYohoData = require('./doraemon/middleware/set-yoho-data');
const errorHanlder = require('./doraemon/middleware/error-handler');
const setPageInfo = require('./doraemon/middleware/set-pageinfo');
const pageCache = require('./doraemon/middleware/page-cache');
// YOHO 前置中间件
app.use(subDomain());
app.use(mobileRefer());
app.use(itemNameHandler);
app.use(mobileCheck());
app.use(setYohoData());
... ... @@ -105,6 +105,7 @@ try {
app.use(seo());
app.use(setPageInfo());
app.use(pageCache());
require('./dispatch')(app);
app.all('*', errorHanlder.notFound()); // 404
... ...
... ... @@ -5,8 +5,7 @@
*/
var express = require('express'),
path = require('path'),
hbs = require('express-handlebars');
path = require('path');
var app = express();
... ... @@ -17,12 +16,12 @@ app.on('mount', function(parent) {
delete parent.locals.settings; // 不继承父 App 的设置
Object.assign(app.locals, parent.locals);
});
app.set('views', path.join(__dirname, 'views/action'));
app.engine('.hbs', hbs({
app.use(global.yoho.hbs({
extname: '.hbs',
defaultLayout: 'layout',
layoutsDir: doraemon,
partialsDir: [path.join(__dirname, 'views/partial'), `${doraemon}/partial`],
partialsDir: [path.join(__dirname, 'views/partial')],
views: path.join(__dirname, 'views/action'),
helpers: global.yoho.helpers
}));
... ...
... ... @@ -20,7 +20,10 @@ exports.index = (req, res, next) => {
let channel = req.query.channel || req.cookies._Channel || 'boys';
brandsService.getBrandViewList(channel, req).then(result => {
// 返回null,不cashe
if (result.noCashe) {
res.set('Cashe-Control', 'no-cashe');
}
res.render('brands/brands', result);
}).catch(next);
... ... @@ -50,6 +53,10 @@ exports.brandInfo = (req, res, next) => {
let brandId = req.query.brandId || 0;
brandsService.brandInfo(brandId, req.user.uid).then(result => {
// 返回null,不cashe
if (result.noCashe) {
res.set('Cashe-Control', 'no-cashe');
}
res.json(result);
}).catch(next);
};
... ... @@ -61,6 +68,10 @@ exports.plusstarList = (req, res, next) => {
let channel = req.query.channel || req.cookies._Channel || 'boys';
brandsService.plusstarList(channel, req).then(result => {
// 返回null,不cashe
if (result.noCashe) {
res.set('Cashe-Control', 'no-cashe');
}
res.render('brands/plusstar', result);
}).catch(next);
};
... ...
... ... @@ -5,8 +5,7 @@
*/
var express = require('express'),
path = require('path'),
hbs = require('express-handlebars');
path = require('path');
var app = express();
... ... @@ -18,12 +17,12 @@ app.on('mount', function(parent) {
Object.assign(app.locals, parent.locals);
});
app.set('views', path.join(__dirname, 'views/action'));
app.engine('.hbs', hbs({
app.use(global.yoho.hbs({
extname: '.hbs',
defaultLayout: 'layout',
layoutsDir: doraemon,
partialsDir: [path.join(__dirname, 'views/partial'), `${doraemon}/partial`],
partialsDir: [path.join(__dirname, 'views/partial')],
views: path.join(__dirname, 'views/action'),
helpers: global.yoho.helpers
}));
... ...
... ... @@ -6,6 +6,7 @@
'use strict';
const api = global.yoho.API;
const serviceAPI = global.yoho.ServiceAPI;
const config = global.yoho.config;
/**
* 分开取数,品牌一览 顶部的轮翻广告及热门品牌数据-PC
... ... @@ -15,7 +16,7 @@ const serviceAPI = global.yoho.ServiceAPI;
const getBrandTopData = (contentCode) => {
return serviceAPI.get('operations/api/v5/resource/get', {
content_code: contentCode
}, {cache: 3600});
}, config.apiCache);
};
/**
... ... @@ -28,7 +29,7 @@ const getBrandListData = channel => {
if (!isNaN(channel)) {
params.yh_channel = channel;
}
return api.get('', params);
return api.get('', params, config.apiCache);
};
/**
... ... @@ -48,7 +49,7 @@ const getBrandIntro = (brandId, uid) => {
method: 'app.brand.getBrandIntro',
brand_id: brandId,
uid: uid
}, param);
}, param, config.apiCache);
};
/**
... ... @@ -61,7 +62,7 @@ const getProductByBrand = (brandId, limit) => {
method: 'web.search.search',
brand: brandId,
limit: limit
});
}, config.apiCache);
};
/**
... ... @@ -74,7 +75,7 @@ const getBrandInfoByIds = (ids) => {
return api.get('', {
method: 'web.brand.info',
ids: ids instanceof Array ? ids.join(',') : parseInt(ids, 10)
}, {cache: 3600});
}, config.apiCache);
};
/**
... ... @@ -89,7 +90,7 @@ const getPlusstarList = (brandType, gender) => {
return serviceAPI.get('guang/api/v3/plustar/getlist', {
gender: gender,
brand_type: brandType
}, {cache: 3600});
}, config.apiCache);
};
module.exports = {
... ...
... ... @@ -101,13 +101,14 @@ exports.getBrandViewList = (channel) => {
let apiMethod = [
headerModel.requestHeaderData(channel),
brandsModel.getBrandViewTop(channel),
brandsModel.getBrandViewList(channel, 1, 5) // 分屏加载
brandsModel.getBrandViewList(channel) // 分屏加载
];
return api.all(apiMethod).then(result => {
let responseData = {
module: 'brands',
page: 'brands'
page: 'brands',
noCashe: false
};
// 头部数据
... ... @@ -135,6 +136,10 @@ exports.getBrandViewList = (channel) => {
// SEO
Object.assign(responseData, seoMap[channel]);
// 数据出错不cashe
if (_.isEmpty(result[0].headerData) || _.isEmpty(result[1]) || _.isEmpty(result[2])) {
responseData.noCashe = true;
}
return responseData;
});
};
... ... @@ -168,11 +173,17 @@ exports.brandInfo = (brandId, uid) => {
];
return api.all(apiMethod).then(result => {
return {
let responseData = {
code: _.isEmpty(result[0]) ? 400 : 200,
brand: _.isEmpty(result[0]) ? '' : result[0]
brand: _.isEmpty(result[0]) ? '' : result[0],
noCashe: false
};
// 数据出错不cashe
if (_.isEmpty(result[0])) {
responseData.noCashe = true;
}
return responseData;
});
};
... ... @@ -189,7 +200,8 @@ exports.plusstarList = (channel, req) => {
let responseData = {
module: 'brands',
page: 'brands',
brandsHomePage: true
brandsHomePage: true,
noCashe: false
};
let id = req.query.id || '',
... ... @@ -208,6 +220,10 @@ exports.plusstarList = (channel, req) => {
let list = plustarList.data;
// 数据出错不cashe
if (_.isEmpty(headerData.headerData) || _.isEmpty(items) || _.isEmpty(list)) {
responseData.noCashe = true;
}
let brandIds = [],
brands = [],
pageList = {};
... ... @@ -232,6 +248,11 @@ exports.plusstarList = (channel, req) => {
}
brands.push(list[brandId]);
});
// 数据出错不cashe
if (_.isEmpty(brandsInfo)) {
responseData.noCashe = true;
}
}
let data = {
brandsHomePage: true,
... ...
... ... @@ -48,7 +48,7 @@
{{/each}}
</div>
</div>
<div class="brands-list" >
<div class="brands-list" data-ishover="{{@root.pc.brands.disBrandNameHover}}">
{{> brand-list}}
</div>
{{/ brands}}
... ...
... ... @@ -7,25 +7,24 @@
'use strict';
var express = require('express'),
path = require('path'),
hbs = require('express-handlebars');
path = require('path');
var app = express();
// set view engin
var doraemon = path.join(__dirname, '../../doraemon/views'); //parent view root
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);
});
app.set('views', path.join(__dirname, 'views/action'));
app.engine('.hbs', hbs({
app.use(global.yoho.hbs({
extname: '.hbs',
defaultLayout: 'layout',
layoutsDir: doraemon,
partialsDir: [path.join(__dirname, 'views/partial'), `${doraemon}/partial`],
partialsDir: [path.join(__dirname, 'views/partial')],
views: path.join(__dirname, 'views/action'),
helpers: global.yoho.helpers
}));
... ...
... ... @@ -17,6 +17,11 @@ exports.index = (req, res, next) => {
channelType === 'woman' ? channelType = 'girls' : null;
channelModel.getContent(channelType).then(data => {
// channel为空不缓存
if (_.isEmpty(data.channel)) {
res.set('Cache-Control', 'no-cache');
}
res.render('channel', data);
}).catch(next);
};
... ...
... ... @@ -5,14 +5,12 @@
*/
var express = require('express'),
path = require('path'),
hbs = require('express-handlebars');
path = require('path');
var app = express();
// set view engin
var doraemon = path.join(__dirname, '../../doraemon/views'); // parent view root
var partials = path.join(__dirname, './views'); // parent view root
app.on('mount', function(parent) {
... ... @@ -20,16 +18,15 @@ app.on('mount', function(parent) {
Object.assign(app.locals, parent.locals);
});
app.set('views', path.join(__dirname, 'views/action'));
app.engine('.hbs', hbs({
app.use(global.yoho.hbs({
extname: '.hbs',
defaultLayout: 'layout',
layoutsDir: doraemon,
partialsDir: [`${partials}/partial`, `${doraemon}/partial`],
partialsDir: [path.join(__dirname, 'views/partial')],
views: path.join(__dirname, 'views/action'),
helpers: global.yoho.helpers
}));
// router
app.use(require('./router'));
... ...
... ... @@ -10,6 +10,7 @@ const _ = require('lodash');
const dataMap = require('../../../config/data-map');
const helpers = global.yoho.helpers;
const config = global.yoho.config;
const processProduct = require(`${global.utils}/product-process`).processProduct;
const searchApi = require('../../product/models/search-api');
... ... @@ -335,7 +336,7 @@ const _getGirlsSingleHot = (args, type) => {
page: 1,
gender: channelMap[type].gender,
limit: 60
});
}, config.apiCache);
};
... ... @@ -592,18 +593,18 @@ const _processFloorData = (rawData, type) => {
let queryParam = '';
if (data.template_name === 'recommend_content_three' ||
(data.template_intro === '焦点图' && index === 0)) { // 处理banner
(data.template_intro === '焦点图' && index === 0)) { // 处理banner
floorData = floorMap.slide.call(null, data.data);
} else if (data.template_intro === '热门品类') { // 处理热门品类
floorData = floorMap.hot.call(null, rawData.slice(index, index + hotCategoryLength), type);
} else if (data.data && data.data.text) { // 处理一般楼层
let text = _getText(data.data.text);
let lastIndex = index + bigFloorLength < rawData.length ?
index + bigFloorLength : index + (rawData.length - index - 1);
index + bigFloorLength : index + (rawData.length - index - 1);
floorData = floorMap[text] &&
floorMap[text].call(null, rawData.slice(index, lastIndex), type);
floorMap[text].call(null, rawData.slice(index, lastIndex), type);
if (needQuery[text]) {
queryParam = getQuery(rawData.slice(index, lastIndex));
... ... @@ -657,9 +658,7 @@ const _processFloorData = (rawData, type) => {
};
const _formatResourceParams = (channel, code) => {
return serviceApi.get('operations/api/v5/resource/get', {content_code: code}, {
cache: true
}).then(data => {
return serviceApi.get('operations/api/v5/resource/get', {content_code: code}, config.apiCache).then(data => {
let result = data && data.data[0] && data.data[0].data[0];
if (result) {
... ... @@ -834,8 +833,6 @@ const getNewArrival = channel => {
};
/**
* 获取频道页数据
* @param {String} type 传入频道页类型,值可以是: boys, girls, kids, lifestyle
... ... @@ -956,9 +953,7 @@ const getIndexGuideData = () => {
private_key: '0ed29744ed318fd28d2c07985d3ba633'
};
return serviceApi.get('operations/api/v6/category/getCategory', params, {
cache: true
});
return serviceApi.get('operations/api/v6/category/getCategory', params, config.apiCache);
};
module.exports = {
... ...
... ... @@ -4,28 +4,15 @@
* @date: 2016/10/11
*/
var express = require('express'),
path = require('path'),
hbs = require('express-handlebars');
var express = require('express');
var app = express();
// set view engin
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);
});
app.set('views', path.join(__dirname, 'views/action'));
app.engine('.hbs', hbs({
extname: '.hbs',
defaultLayout: 'layout',
layoutsDir: doraemon,
partialsDir: [path.join(__dirname, 'views/partial'), `${doraemon}/partial`],
helpers: global.yoho.helpers
}));
// router
app.use(require('./router'));
... ...
... ... @@ -26,16 +26,23 @@ exports.index = (req, res, next) => {
let uid = req.user.uid;
let udid = ghelper.getUdid(req, res);
let gender = ghelper.getGenderByCookie(req);
let isHotDegrade = _.get(req.app.locals.pc, 'guang.removeHotTag', false);
let isAdDegrade = _.get(req.app.locals.pc, 'guang.removeAd', false);
Promise.all([
guangModel.getBanner(channel),
guangModel.getCategory(type, channel),
guangModel.getArticleList(gender, type, uid, udid, page, '', '', pageSize, channel, true),
guangModel.getHotTags(page, pageSize, channel),
guangModel.getAds(channel),
guangModel.getHotTags(page, pageSize, channel, isHotDegrade),
guangModel.getAds(channel, isAdDegrade),
guangModel.getRecoArticles(gender, 1, 10, channel),
headerModel.requestHeaderData(channel)
]).then(ret => {
if (_.isEmpty(ret[2]) || _.isEmpty(ret[2].msgs)) {
res.set('Cache-Control', 'no-cache');
}
res.render('guang/index', {
title: '逛' + (res.locals.title || ''),
guang: {
... ... @@ -77,17 +84,23 @@ exports.tags = (req, res, next) => {
let gender = ghelper.getGenderByCookie(req);
let channel = req.yoho.channel;
let pathNav = guangModel.getPathNav(channel, query);
let isHotDegrade = _.get(req.app.locals.pc, 'guang.removeHotTag', false);
let isAdDegrade = _.get(req.app.locals.pc, 'guang.removeAd', false);
Promise.all([
guangModel.getBanner(channel),
guangModel.getArticleList(gender, 0, uid, udid, page, query, '', pageSize, channel, true),
guangModel.getHotTags(1, 20, channel),
guangModel.getAds(channel),
guangModel.getHotTags(1, 20, channel, isHotDegrade),
guangModel.getAds(channel, isAdDegrade),
guangModel.getRecoArticles(gender, 1, 10, channel),
headerModel.requestHeaderData(channel)
]).then(ret => {
if (_.isEmpty(ret[1]) || _.isEmpty(ret[1].msgs)) {
res.set('Cache-Control', 'no-cache');
}
res.render('guang/tag', {
title: query + (res.locals.title || ''),
guang: {
... ... @@ -121,6 +134,8 @@ exports.editor = (req, res, next) => {
let authorId = req.query.author_id;
let channel = req.yoho.channel;
let gender = ghelper.getGenderByCookie(req);
let isHotDegrade = _.get(req.app.locals.pc, 'guang.removeHotTag', false);
let isAdDegrade = _.get(req.app.locals.pc, 'guang.removeAd', false);
let uid = req.user.uid;
let udid = ghelper.getUdid(req, res);
... ... @@ -133,11 +148,16 @@ exports.editor = (req, res, next) => {
Promise.all([
guangModel.getAuthor(authorId),
guangModel.getArticleList(gender, null, uid, udid, page, '', authorId, pageSize, channel, true),
guangModel.getHotTags(1, 20, channel),
guangModel.getAds(channel),
guangModel.getHotTags(1, 20, channel, isHotDegrade),
guangModel.getAds(channel, isAdDegrade),
guangModel.getRecoArticles(gender, 1, 10, channel),
headerModel.requestHeaderData(channel)
]).then(ret => {
if (_.isEmpty(ret[1]) || _.isEmpty(ret[1].msgs)) {
res.set('Cache-Control', 'no-cache');
}
res.render('guang/editor', {
title: _.get(ret[0], 'name', '') + (res.locals.title || ''),
guang: {
... ... @@ -175,9 +195,11 @@ exports.detail = (req, res, next) => {
let udid = ghelper.getUdid(req, res);
let gender = ghelper.getGenderByCookie(req);
let channel = req.yoho.channel;
let isHotDegrade = _.get(req.app.locals.pc, 'guang.removeHotTag', false);
let isAdDegrade = _.get(req.app.locals.pc, 'guang.removeAd', false);
if (!_.isNumber(id)) {
id = parseInt(id);
id = _.parseInt(id);
}
if (pjax) {
... ... @@ -212,12 +234,12 @@ exports.detail = (req, res, next) => {
let promises = [
headerModel.requestHeaderData(channel),
guangModel.getArticleContent(id),
guangModel.getHotTags(1, 20, channel),
guangModel.getHotTags(1, 20, channel, isHotDegrade),
guangModel.getArticleComments(id, page, pageSize),
guangModel.getArticleBaseInfo(id, uid, udid),
guangModel.getArticleRelateBrand(id),
guangModel.getRecoArticles(gender, 1, 10, channel),
guangModel.getAds(channel)
guangModel.getAds(channel, isAdDegrade)
];
if (info.authorId) {
... ... @@ -236,6 +258,10 @@ exports.detail = (req, res, next) => {
Promise.all(promises).then(ret => {
if (_.isEmpty(ret[1])) {
res.set('Cache-Control', 'no-cache');
}
res.render('guang/detail', Object.assign({
module: 'guang',
page: 'detail',
... ...
... ... @@ -44,7 +44,7 @@ exports.pager = function() {
base = base.replace(clearSizeReg, '');
}
base += (base.indexOf('?') < 0 ? '?' : (base.charAt(base.length - 1) !== '?' ? '&' : '')) +
base += (base.indexOf('?') < 0 ? '?' : (/(\?|&)$/.test(base) ? '' : '&')) +
(options.hash.pageSize ? (pageSizeVar + '=' + pageSize + '&') : '') +
pageVar + '=';
... ...
... ... @@ -6,27 +6,24 @@
'use strict';
var express = require('express'),
path = require('path'),
hbs = require('express-handlebars');
path = require('path');
var app = express();
// set view engin
var doraemon = path.join(__dirname, '../../doraemon/views'); // parent view root
var partials = path.join(__dirname, './views'); // parent view root
app.on('mount', function(parent) {
delete parent.locals.settings; // 不继承父 App 的设置
Object.assign(app.locals, parent.locals);
});
app.set('views', path.join(__dirname, 'views/action'));
app.engine('.hbs', hbs({
app.use(global.yoho.hbs({
extname: '.hbs',
defaultLayout: 'layout',
layoutsDir: doraemon,
partialsDir: [`${partials}/partial`, `${doraemon}/partial`],
partialsDir: [path.join(__dirname, 'views/partial')],
views: path.join(__dirname, 'views/action'),
helpers: Object.assign(require('./helpers/pager'), global.yoho.helpers)
}));
... ...
... ... @@ -121,7 +121,8 @@ const _formatArticle = (articleData, showTag, showAuthor, channel) => {
let result = {
id: articleData.id,
classification: articleData.category_name,
isReco: articleData.is_recommended && Number(articleData.is_recommended) === 1 ? true : false,
// isReco: articleData.is_recommended && Number(articleData.is_recommended) === 1 ? true : false,
url: ghelper.getArticleUrl(articleData.url, articleData.id, channel),
img: helpers.image(articleData.src, width, height, 1),
isSquareImg: isSquareImage,
... ... @@ -133,6 +134,26 @@ const _formatArticle = (articleData, showTag, showAuthor, channel) => {
comment: articleData.comment_num
};
if (showTag && articleData.category_id) {
switch (String(articleData.category_id)) {
case '1': // 话题
result.isTopic = true;
break;
case '2': // 搭配
result.isCollocation = true;
break;
case '3': // 潮人
result.isFashionMan = true;
break;
case '4': // 潮品
result.isFashionGood = true;
break;
case '19': // 专题
result.isSpecialTopic = true;
break;
}
}
if (!articleData.author) {
articleData.author = {
name: '',
... ... @@ -305,7 +326,7 @@ const getArticleList = (gender, sortId, uid, udid, page, tag, authorId, limit, c
* @param {String} type 传入频道页类型,值可以是: boys, girls, kids, lifestyle
* @return {Object}
*/
const getHotTags = (page, limit, channel) => {
const getHotTags = (page, limit, channel, isDegrade) => {
let data = {
client_type: 'web',
... ... @@ -313,6 +334,10 @@ const getHotTags = (page, limit, channel) => {
limit: limit || 10
};
if (isDegrade) {
return null;
}
return serviceApi.get('guang/api/v2/article/getTagTop', data, {
cache: true
}).then(res => {
... ... @@ -338,10 +363,14 @@ const getHotTags = (page, limit, channel) => {
* @param {String} channelType 传入频道页类型,值可以是: boys, girls, kids, lifestyle
* @return {Object}
*/
const getAds = channelType => {
const getAds = (channelType, isDegrade) => {
let contentCode = ADS_CODE[channelType] || ADS_CODE.boys;
if (isDegrade) {
return null;
}
return serviceApi.get(URL_OPERATIONS_RESOURCE_GET, {
content_code: contentCode
}, {cache: true}).then(res => {
... ...
... ... @@ -130,18 +130,20 @@
</div>
{{/if}}
<div id="comment-area" class="comment-area">
<div class="comment-textarea">
<textarea id="comment-info" placeholder="我有话要说。。。">{{commentInfo}}</textarea>
</div>
<div class="comment-publish clearfix">
<span id="word-count-tip" class="word-count-tip"></span>
<a id="comment-btn" class="publish-btn disable">评论</a>
</div>
<div id="pjax-container" class="comments-wrap">
{{> comment}}
{{#unless @root.pc.guang.removeItemComment}}
<div id="comment-area" class="comment-area">
<div class="comment-textarea">
<textarea id="comment-info" placeholder="我有话要说。。。">{{commentInfo}}</textarea>
</div>
<div class="comment-publish clearfix">
<span id="word-count-tip" class="word-count-tip"></span>
<a id="comment-btn" class="publish-btn disable">评论</a>
</div>
<div id="pjax-container" class="comments-wrap">
{{> comment}}
</div>
</div>
</div>
{{/unless}}
</div>
<div class="right-side detail-side">
{{> right-side}}
... ...
... ... @@ -3,9 +3,21 @@
<div class="classification">
{{classification}}
</div>
{{#if isReco}}
<div class="reco"></div>
{{/if}}
{{# isCollocation}}
<div class="type-icon collocation"></div>
{{/ isCollocation}}
{{# isFashionMan}}
<div class="type-icon fashion-man"></div>
{{/ isFashionMan}}
{{# isFashionGood}}
<div class="type-icon fashion-good"></div>
{{/ isFashionGood}}
{{# isTopic}}
<div class="type-icon topic"></div>
{{/ isTopic}}
{{# isSpecialTopic}}
<div class="type-icon special-topic"></div>
{{/ isSpecialTopic}}
<a href="{{url}}" target="_blank">
<img class="lazy{{#if isSquareImg}} square{{/if}}" data-original="{{img}}">
</a>
... ... @@ -46,4 +58,4 @@
</div>
</div>
</div>
</div>
\ No newline at end of file
</div>
... ...
... ... @@ -14,16 +14,18 @@
</div>
</div>
<div class="hot">
<h1 class="hot-title">热门标签</h1>
<div class="hot-tag-list">
{{#hotTags}}
<a class="hot-tag" href="{{url}}" target="_blank">
{{tagName}}
</a>
{{/hotTags}}
{{#unless @root.pc.guang.removeHotTag}}
<div class="hot">
<h1 class="hot-title">热门标签</h1>
<div class="hot-tag-list">
{{#hotTags}}
<a class="hot-tag" href="{{url}}" target="_blank">
{{tagName}}
</a>
{{/hotTags}}
</div>
</div>
</div>
{{/unless}}
<div class="ads">
{{# ads}}
... ... @@ -31,4 +33,4 @@
<img class="lazy" data-original="{{img}}">
</a>
{{/ ads}}
</div>
\ No newline at end of file
</div>
... ...
... ... @@ -5,8 +5,7 @@
*/
var express = require('express'),
path = require('path'),
hbs = require('express-handlebars');
path = require('path');
var app = express();
... ... @@ -17,12 +16,13 @@ app.on('mount', function(parent) {
delete parent.locals.settings; // 不继承父 App 的设置
Object.assign(app.locals, parent.locals);
});
app.set('views', path.join(__dirname, 'views/action'));
app.engine('.hbs', hbs({
app.use(global.yoho.hbs({
extname: '.hbs',
defaultLayout: 'layout',
layoutsDir: doraemon,
partialsDir: [path.join(__dirname, 'views/partial'), `${doraemon}/partial`],
partialsDir: [path.join(__dirname, 'views/partial')],
views: path.join(__dirname, 'views/action'),
helpers: global.yoho.helpers
}));
... ...
... ... @@ -15,7 +15,7 @@ const DoubanStrategy = require('passport-douban').Strategy;
const RenrenStrategy = require('passport-renren').Strategy;
const AlipayStrategy = require('./models/passport-alipay').Strategy;
const AuthHelper = require('./models/auth-helper');
const LoginApi = require('./models/login-service');
const config = global.yoho.config;
const helpers = global.yoho.helpers;
... ... @@ -26,6 +26,16 @@ const cache = global.yoho.cache;
let siteUrl = config.siteUrl.indexOf('//') === 0 ? 'http:' + config.siteUrl : config.siteUrl;
function getLoginStat(account) {
let errorLoginKey = 'account_errorlogin_' + account;
let accountKey = 'account_signin_' + account;
let cacheGet = [cache.get(errorLoginKey), cache.get(accountKey)];
return Promise.all(cacheGet).catch(() => {
return [0, 0];
});
}
// 本地登录
passport.use('local', new LocalStrategy({
usernameField: 'account',
... ... @@ -54,25 +64,23 @@ passport.use('local', new LocalStrategy({
let errorLoginKey = 'account_errorlogin_' + account;
let accountKey = 'account_signin_' + account;
let cacheGet = [cache.get(errorLoginKey), cache.get(accountKey)];
Promise.all(cacheGet).then(times => {
getLoginStat(account).then(times => {
let errLoginTimes = _.parseInt(times[0]) || 0;
let accountTimes = _.parseInt(times[1]) || 0;
if (accountTimes >= 10) {
done({message: '您的账号已被暂时锁定,请稍后再试'}, null);
} else {
return AuthHelper.signin(type, area, username, password, shoppingKey).then((result) => {
return LoginApi.signin(type, area, username, password, shoppingKey).then((result) => {
if (result.code && result.code === 200 && result.data.uid) {
cache.del(errorLoginKey);
cache.del(errorLoginKey).catch(() => {});
done(null, result.data);
} else {
errLoginTimes = errLoginTimes + 1;
accountTimes = accountTimes + 1;
cache.set(errorLoginKey, errLoginTimes);
cache.set(accountKey, accountTimes, 1800);
cache.set(errorLoginKey, errLoginTimes).catch(() => {});
cache.set(accountKey, accountTimes, 1800).catch(() => {});
// 再次校验
if (accountTimes >= 10) {
... ... @@ -116,8 +124,8 @@ passport.use('wechat', new WeixinStrategy({
// sina 登录
passport.use('sina', new SinaStrategy({
clientID: '3739328910',
clientSecret: '9d44cded26d048e23089e5e975c93df1',
clientID: config.thirdLogin.sina.appID,
clientSecret: config.thirdLogin.sina.appSecret,
callbackURL: `${siteUrl}/passport/login/sina/callback`,
requireState: false
}, (accessToken, refreshToken, profile, done) => {
... ... @@ -126,8 +134,8 @@ passport.use('sina', new SinaStrategy({
// qq 登录
passport.use('qq', new QQStrategy({
clientID: '100229394',
clientSecret: 'c0af9c29e0900813028c2ccb42021792',
clientID: config.thirdLogin.qq.appID,
clientSecret: config.thirdLogin.qq.appSecret,
callbackURL: `${siteUrl}/passport/login/qq/callback`,
requireState: false
}, (accessToken, refreshToken, profile, done) => {
... ... @@ -136,8 +144,8 @@ passport.use('qq', new QQStrategy({
// alipay 登录
passport.use('alipay', new AlipayStrategy({
partner: '2088701661478015',
key: 'kcxawi9bb07mzh0aq2wcirsf9znusobw',
partner: config.thirdLogin.alipay.appID,
key: config.thirdLogin.alipay.appSecret,
return_url: `${siteUrl}/passport/login/alipay/callback`
}, (profile, done) => {
done(null, profile);
... ... @@ -145,8 +153,8 @@ passport.use('alipay', new AlipayStrategy({
// douban 登录
passport.use('douban', new DoubanStrategy({
clientID: '03b4e36bf13dc75a0b1eaa43d3b9560e',
clientSecret: 'f16d5913e8610672',
clientID: config.thirdLogin.douban.appID,
clientSecret: config.thirdLogin.douban.appSecret,
callbackURL: `${siteUrl}/passport/autosign/doubanback`
}, (accessToken, refreshToken, profile, done) => {
done(null, profile);
... ... @@ -154,8 +162,8 @@ passport.use('douban', new DoubanStrategy({
// renren 登录
passport.use('renren', new RenrenStrategy({
clientID: '783130c654c94a77ace97054ae266019',
clientSecret: '05e430de8c1e40d3a1f39ca8d3f8252c',
clientID: config.thirdLogin.renren.appID,
clientSecret: config.thirdLogin.renren.appSecret,
callbackURL: `${siteUrl}/passport/login/renren/callback`
}, (accessToken, refreshToken, profile, done) => {
done(null, profile);
... ...
... ... @@ -6,6 +6,7 @@
'use strict';
const helpers = global.yoho.helpers;
const config = global.yoho.config;
const service = require('../models/back-service');
const passportHelper = require('../models/passport-helper');
const simpleHeaderModel = require('../../../doraemon/models/simple-header');
... ... @@ -17,12 +18,15 @@ const _ = require('lodash');
const index = (req, res, next) => {
// 清除cookie
res.clearCookie('_UID', {
domain: 'yohobuy.com'
domain: config.cookieDomain
});
res.clearCookie('_TOKEN', {
domain: 'yohobuy.com'
domain: config.cookieDomain
});
// 清除 session
req.session = null;
service.indexPageDataAsync()
.then(result => {
res.render('back/index', Object.assign({
... ... @@ -102,21 +106,18 @@ const sendCodePage = (req, res, next) => {
const saveInSession = (req, res) => {
switch (req.inputInfo.type) {
case 'email': {
case 'email':
req.session.email = req.inputInfo.phone;
res.redirect(helpers.urlFormat('/passport/back/sendEmail'));
break;
}
case 'mobile': {
case 'mobile':
req.session.mobile = req.inputInfo.phone;
req.session.area = req.inputInfo.area;
req.session.verifyCode = req.session.captcha;
res.redirect(helpers.urlFormat('/passport/back/verification'));
break;
}
default: {
default:
res.redirect(helpers.urlFormat('/passport/back/index'));
}
}
};
... ... @@ -133,10 +134,9 @@ const sendBackMobileAPI = (req, res, next) => {
const validateMobileAPI = (req, res, next) => {
let mobile = req.body.mobile || '';
let area = req.body.area || '86';
const ERR = {code: 400, message: '验证失败'};
if (!passportHelper.validator.isAreaMobile(passportHelper.makeAreaMobile(area, mobile))) {
if (!passportHelper.validator.isMobile(mobile)) {
return res.json(ERR);
}
... ...
... ... @@ -8,9 +8,10 @@
const _ = require('lodash');
const helpers = global.yoho.helpers;
const PassportHelper = require('../models/passport-helper');
const BindService = require('../models/bind-service');
const AuthHelper = require('../models/auth-helper');
const passportHelper = require('../models/passport-helper');
const bindService = require('../models/bind-service');
const loginService = require('../models/login-service');
const userService = require('../models/user-service');
// const UserService = require('../models/user-service');
const simpleHeaderModel = require('../../../doraemon/models/simple-header');
... ... @@ -33,7 +34,7 @@ const bind = {
thirdLogin: true,
openId: openId,
sourceType: sourceType,
region: PassportHelper.getCountry(),
region: passportHelper.getCountry(),
serviceUrl: helpers.urlFormat('/help', {
category_id: 9
}),
... ... @@ -80,7 +81,7 @@ const bind = {
// }
// })
PassportHelper.getUserInfo(area, mobile).then(user => {
userService.getUserInfo(area, mobile).then(user => {
let data = _.assign(user, {
phoneNum: mobile,
areaCode: area,
... ... @@ -121,49 +122,59 @@ const bind = {
let sourceType = req.body.sourceType;
if (mobile && openId && area && sourceType) {
BindService.bindCheck(mobile, openId, sourceType, area).then(result => {
/**
* 接口绑定返回值:
* code:200,is_register=0 // 绑定流程:未注册,可绑定
* code:200,is_register=1 // 绑定流程:已注册绑定过其他第三方
* code:200:is_register=3 // 关联流程
* code:505 // 手机号码注册过,而且该第三方也已经绑定过手机号
* code:506 // 手机号码注册过,而且该手机号码也已经绑定过该类型第三方
*/
bindService.bindCheck(mobile, openId, sourceType, area).then(result => {
if (!result || !result.code) {
return { code: 400, message: '', data: '' };
return {code: 400, message: '', data: ''};
} else if (result.code === 200 && result.data.is_register === 0) {
let nextUrl = helpers.urlFormat('/passport/thirdlogin/noregist');
// 绑定流程:code=200 未注册,可绑定
return { code: 200, message: result.message, data: { next: nextUrl } };
return {code: 200, message: result.message, data: {next: nextUrl}};
} else if (result.code === 200 && result.data.is_register === 1) {
return PassportHelper.getUserInfo(area, mobile).then(user => {
return userService.getUserInfo(area, mobile).then(user => {
// 绑定流程:code=201 已注册 绑定过其他第三方
return {code: 201, message: result.message, data: { user: user } };
return {code: 201, message: result.message, data: {user: user}};
});
} else if (result.code === 200 && result.data.is_register === 3) {
let nextUrl = helpers.urlFormat('/passport/thirdlogin/relate');
// 关联流程
return { code: 203, message: result.message, data: { next: nextUrl } };
return {code: 203, message: result.message, data: {next: nextUrl}};
} else if (result.code === 506 || result.code === 505) {
return PassportHelper.getUserInfo(area, mobile).then(user => {
return userService.getUserInfo(area, mobile).then(user => {
// 绑定流程:code=506 手机号码注册过,而且该手机号码也已经绑定过该类型第三方
// code=505 手机号码注册过,而且该第三方也已经绑定过手机号
return { code: 205, message: result.message, data: { user: user } };
return {code: 205, message: result.message, data: {user: user}};
});
} else {
return { code: result.code, message: result.message, data: result.data ? result.data : '' };
return {code: result.code, message: result.message, data: result.data ? result.data : ''};
}
}).then(result => {
res.json(result);
return res.json(result);
}).catch(next);
} else {
res.json({ code: 400, message: '', data: '' });
return res.json({code: 400, message: '', data: ''});
}
},
sendBindMsg: (req, res, next) => {
let mobile = req.body.mobile;
let area = req.body.area;
BindService.sendBindMsg(area, mobile).then(result => {
bindService.sendBindMsg(area, mobile).then(result => {
if (result && result.code) {
res.json(result);
return res.json(result);
} else {
res.json({ code: 400, message: '', data: '' });
return res.json({code: 400, message: '', data: ''});
}
}).catch(next);
},
... ... @@ -172,11 +183,11 @@ const bind = {
let area = req.body.area;
let code = req.body.code;
BindService.checkBindCode(area, mobile, code).then(result => {
bindService.checkBindCode(area, mobile, code).then(result => {
if (result && result.code) {
res.json(result);
return res.json(result);
} else {
res.json({ code: 400, message: '', data: '' });
return res.json({code: 400, message: '', data: ''});
}
}).catch(next);
},
... ... @@ -188,11 +199,11 @@ const bind = {
let code = _.trim(req.body.code);
let password = _.trim(req.body.password) || '';
BindService.checkBindCode(area, mobile, code).then(result => {
bindService.checkBindCode(area, mobile, code).then(result => {
if (result && result.code !== 200) {
return { code: 402, message: '短信验证码不正确', data: '' };
return {code: 402, message: '短信验证码不正确', data: ''};
} else {
return BindService.bindMobile(openId, sourceType, mobile, area, password);
return bindService.bindMobile(openId, sourceType, mobile, area, password);
}
}).then(result => {
if (result && result.code) {
... ... @@ -201,17 +212,17 @@ const bind = {
sourceType: sourceType + '_bind'
});
return AuthHelper.syncUserSession(result.data.uid, req, res).then(() => {
return { code: 200, message: result.message, data: {refer: refer }};
return loginService.syncUserSession(result.data.uid, req, res).then(() => {
return {code: 200, message: result.message, data: {refer: refer}};
});
} else {
return { code: result.code, message: result.message, data: { refer: ''} };
return {code: result.code, message: result.message, data: {refer: ''}};
}
} else {
return {code: 400, message: '', data: ''};
}
}).then(result => {
res.json(result);
return res.json(result);
}).catch(next);
},
relateMobile: (req, res, next) => {
... ... @@ -221,12 +232,12 @@ const bind = {
let sourceType = req.body.sourceType;
let code = req.body.code;
if (_.isNumber(parseInt(mobile, 0)) && openId && areaCode && sourceType && code) {
BindService.checkBindCode(areaCode, mobile, code).then(result => {
if (_.toNumber(mobile) && openId && areaCode && sourceType && code) {
bindService.checkBindCode(areaCode, mobile, code).then(result => {
if (result && result.code && result.code === 200) {
return BindService.relateMobile(openId, sourceType, mobile, areaCode);
return bindService.relateMobile(openId, sourceType, mobile, areaCode);
} else {
return { code: 402, message: '短信验证码错误', data: '' };
return {code: 402, message: '短信验证码错误', data: ''};
}
}).then(result => {
if (result && result.code) {
... ... @@ -235,20 +246,20 @@ const bind = {
sourceType: sourceType + '_relate'
});
return AuthHelper.syncUserSession(result.data.uid, req, res).then(() => {
return { code: 200, message: result.message, data: {refer: refer }};
return loginService.syncUserSession(result.data.uid, req, res).then(() => {
return {code: 200, message: result.message, data: {refer: refer}};
});
} else {
return { code: result.code, message: result.message, data: { refer: ''} };
return {code: result.code, message: result.message, data: {refer: ''}};
}
} else {
return {code: 400, message: '', data: ''};
}
}).then(result => {
res.json(result);
return res.json(result);
}).catch(next);
} else {
res.json({ code: 400, message: '', data: '' });
return res.json({code: 400, message: '', data: ''});
}
}
};
... ...
... ... @@ -6,7 +6,7 @@
'use strict';
const _ = require('lodash');
const Fp = require('lodash/fp');
const Fn = require('lodash/fp');
const Promise = require('bluebird');
const qs = require('querystring');
... ... @@ -17,7 +17,7 @@ const helpers = global.yoho.helpers;
const log = global.yoho.logger;
const config = global.yoho.config;
const cache = global.yoho.cache;
const AuthHelper = require('../models/auth-helper');
const loginService = require('../models/login-service');
const PassportHelper = require('../models/passport-helper');
const simpleHeaderModel = require('../../../doraemon/models/simple-header');
const loginPage = `${config.siteUrl}/signin.html`;
... ... @@ -40,8 +40,9 @@ function doPassportCallback(req, res, user) {
user.openId = user.unionId;
}
return AuthHelper.signinByOpenID(user.nickname, user.openId, user.sourceType, shoppingKey)
return loginService.signinByOpenID(user.nickname, user.openId, user.sourceType, shoppingKey)
.then((result) => {
console.log(result);
if (result.code !== 200) {
return res.redirect(config.siteUrl);
}
... ... @@ -51,8 +52,8 @@ function doPassportCallback(req, res, user) {
sourceType: user.sourceType,
refer: refer
});
} else if (result.code === 200 && result.data.uid) {
return AuthHelper.syncUserSession(result.data.uid, req, res).then(() => {
} else if (result.data['is_bind'] === 'Y' && result.data.uid) {//eslint-disable-line
return loginService.syncUserSession(result.data.uid, req, res, result.data.session_key).then(() => {
return refer;
});
}
... ... @@ -70,7 +71,7 @@ const common = {
let refer = req.query.refer || req.get('Referer');
refer && res.cookie('refer', encodeURI(refer), {
domain: '.yohobuy.com'
domain: config.cookieDomain
});
next();
},
... ... @@ -86,10 +87,10 @@ const common = {
if (!isNaN(errloginTimes) && errloginTimes >= 3) {
result.data = {needCaptcha: true};
}
res.json(result);
return res.json(result);
}).catch(next);
} else {
res.json(result);
return res.json(result);
}
}
};
... ... @@ -98,12 +99,14 @@ const local = {
loginPage: (req, res) => {
// 清除cookie
res.clearCookie('_UID', {
domain: 'yohobuy.com'
domain: config.cookieDomain
});
res.clearCookie('_TOKEN', {
domain: 'yohobuy.com'
domain: config.cookieDomain
});
req.session = null;
let bindMobile = _.trim(req.query.bindMobile || '');
let bindArea = '+' + _.trim(req.query.bindArea || '86');
let areaArr = PassportHelper.getCountry();
... ... @@ -148,52 +151,52 @@ const local = {
login: (req, res, next) => {
passport.authenticate('local', (err, user) => {
if (err) {
res.json({
return res.json({
code: 400,
message: err.message,
data: {
needCaptcha: err.needCaptcha
}
});
} else {
if (_.get(req, 'body.isRemember', false)) {
AuthHelper.rememberAccount({
area: req.body.areaCode || '86',
account: req.body.account,
password: req.body.password
}, req, res);
}
if (_.get(req.body, 'isRemember', 'false') === 'true') {
loginService.rememberAccount({
area: req.body.areaCode || '86',
account: req.body.account,
password: req.body.password
}, req, res);
}
let refer = (function() {
if (/sign|login|reg|passport/.test(_.get(req.cookies, 'refer', ''))) {
return `${config.siteUrl}/home`;
} else if (_.get(req.cookies, 'refer')) {
return decodeURI(req.cookies.refer);
} else {
return `${config.siteUrl}/home`;
}
}());
let refer = (function() {
if (/sign|login|reg|passport/.test(_.get(req, 'cookies.refer', ''))) {
return `${config.siteUrl}/home`;
} else if (_.get(req, 'cookies.refer')) {
return decodeURI(req.cookies.refer);
} else {
return `${config.siteUrl}/home`;
loginService.syncUserSession(user.uid, req, res, user.session_key).then(() => {
return res.json({
code: 200,
data: {
session: refer,
href: refer
}
}());
AuthHelper.syncUserSession(user.uid, req, res).then(() => {
res.json({
code: 200,
data: {
session: refer,
href: refer
}
});
});
}
});
})(req, res, next);
},
logout: (req, res) => {
req.session = null;
res.clearCookie('_UID', {
domain: 'yohobuy.com'
domain: config.cookieDomain
});
res.clearCookie('_TOKEN', {
domain: 'yohobuy.com'
res.clearCookie('TOKEN_', {
domain: config.cookieDomain
});
res.clearCookie('_SPK');
res.clearCookie('_g');
... ... @@ -201,7 +204,7 @@ const local = {
res.clearCookie('remem');
let refer = req.get('Referer') || config.siteUrl;
res.redirect(refer);
return res.redirect(refer);
},
sms: {
send: (req, res, next) => {
... ... @@ -215,7 +218,7 @@ const local = {
});
}
AuthHelper.sendPasswordBySMS(area, mobile).then((result) => {
loginService.sendPasswordBySMS(area, mobile).then((result) => {
return res.json(result);
}).catch(next);
},
... ... @@ -231,7 +234,7 @@ const local = {
});
}
AuthHelper.verifyPasswordBySMS(area, mobile, code).then((result) => {
loginService.verifyPasswordBySMS(area, mobile, code).then((result) => {
if (_.get(result, 'code', 200) !== 200) {
return Promise.reject('error');
}
... ... @@ -261,18 +264,18 @@ const local = {
});
}
AuthHelper.checkUserExitBySMS(area, mobile).then((result) => {
loginService.checkUserExitBySMS(area, mobile).then((result) => {
if (_.get(result, 'code') !== 200) {
return Promise.reject('check user by sms error');
}
if (_.get(result, 'data.is_register', 'N') === 'Y') {
res.json({
return res.json({
code: 200,
message: '用户已注册'
});
} else {
res.json({
return res.json({
code: 402,
message: '手机号尚未注册,请核对后重新输入或<a href="/reg.html?' +
qs.stringify({mobile: mobile, area: (area ? '+' + area : '+86') || '+86'}) +
... ... @@ -284,7 +287,7 @@ const local = {
},
qrcode: {
refresh: (req, res, next) => {
AuthHelper.fetchByQrCode().then((result) => {
loginService.fetchByQrCode().then((result) => {
if (result.code === 200) {
return res.json({
code: 200,
... ... @@ -319,7 +322,7 @@ const local = {
let token = qrcode.substring(qrcode.indexOf('=') + 1);
AuthHelper.checkByQrCode(token).then((result) => {
loginService.checkByQrCode(token).then((result) => {
if (_.isEmpty(result)) {
return res.json({
code: 400,
... ... @@ -366,7 +369,6 @@ const local = {
const wechat = {
login: (req, res, next) => {
req.session = req.session || {};
req.session.authState = uuid.v4();
return passport.authenticate('wechat', {
state: req.session.authState
... ... @@ -389,14 +391,13 @@ const wechat = {
}
})(req, res, next);
} else {
return next(new Error('Auth State Mismatch'));
return next(new Error('Wechat Auth State Mismatch'));
}
}
};
const sina = {
login: (req, res, next) => {
req.session = req.session || {};
req.session.authState = uuid.v4();
return passport.authenticate('sina', {
state: req.session.authState
... ... @@ -419,15 +420,13 @@ const sina = {
}).catch(next);
})(req, res, next);
} else {
return next(new Error('Auth State Mismatch'));
return next(new Error('Sina Auth State Mismatch'));
}
}
};
const qq = {
login: (req, res, next) => {
req.session = req.session || {};
let type = req.query.type || 'yohobuy';
let authState = req.session.authState = (req.query.state || uuid.v4()) + '::' + type;
... ... @@ -436,8 +435,8 @@ const qq = {
})(req, res, next);
},
callback: (req, res, next) => {
let auth = Fp.compose(Fp.head, Fp.split('::'))(req.query.state);
let type = Fp.compose(Fp.nth(1), Fp.split('::'))(req.query.state);
let auth = Fn.compose(Fn.head, Fn.split('::'))(req.query.state);
let type = Fn.compose(Fn.nth(1), Fn.split('::'))(req.query.state);
if (req.session && req.session.authState && req.session.authState === req.query.state) {
passport.authenticate('qq', (err, user) => {
... ... @@ -460,7 +459,7 @@ const qq = {
}
})(req, res, next);
} else {
return next(new Error('Auth State Mismatch'));
return next(new Error('QQ Auth State Mismatch'));
}
}
};
... ... @@ -489,7 +488,6 @@ const alipay = {
const douban = {
login: (req, res, next) => {
req.session = req.session || {};
req.session.authState = uuid.v4();
return passport.authenticate('douban', {
state: req.session.authState
... ... @@ -516,7 +514,6 @@ const douban = {
const renren = {
login: (req, res, next) => {
req.session = req.session || {};
req.session.authState = uuid.v4();
return passport.authenticate('renren', {
state: req.session.authState
... ...
... ... @@ -7,7 +7,7 @@ const Promise = require('bluebird');
const passportHelper = require('../models/passport-helper');
const regService = require('../models/reg-service');
const userService = require('../models/user-service');
const authHelper = require('../models/auth-helper');
const loginService = require('../models/login-service');
const config = require('../../../config/common');
const simpleHeaderModel = require('../../../doraemon/models/simple-header');
let helpers = global.yoho.helpers;
... ... @@ -33,10 +33,10 @@ let checkCode = (req, res, next) => {
* 检查手机格式
*/
let checkMobileMiddleware = (req, res, next) => {
let mobile = +req.body.mobile;
let area = +req.body.area;
let mobile = req.body.mobile;
let area = req.body.area;
if (!_.isNumber(mobile) || !_.isNumber(area)) {
if (!(_.toNumber(mobile) && _.toNumber(area))) {
return res.json({
code: 400,
message: '手机号码格式不正确'
... ... @@ -66,7 +66,7 @@ let checkPassword = (req, res, next) => {
*/
let index = (req, res, next) => {
// 设置注册有效时间30分钟, 防机器刷
req.session._REG_EXPIRE = Date.now() + 1800000;
req.session.REG_EXPIRE_ = Date.now() + 1800000;
let refer = req.query.refer;
let mobile = req.query.mobile;
... ... @@ -106,11 +106,11 @@ let checkMobile = (req, res, next) => {
let data = {
code: 400
};
let mobile = +req.body.mobile;
let area = +req.body.area;
let mobile = req.body.mobile;
let area = req.body.area || '86';
// 判断手机号是否检查超过指定次数
let regCheckKey = 'regCheckMobileNum_' + passportHelper.makeAreaMobile(area, mobile);
let regCheckKey = `regCheckMobileNum_${area}-${mobile}`;
cache.get(regCheckKey).then((checkNum) => {
checkNum = +(checkNum || 0);
... ... @@ -168,8 +168,8 @@ let sendBindMsg = (req, res, next) => {
data: ''
};
let mobile = +req.body.mobile;
let area = +req.body.area;
let mobile = req.body.mobile;
let area = req.body.area;
// 校验是否发送过多
let sendCodeKey = `send_code_${area}_${mobile}`;
... ... @@ -204,9 +204,9 @@ let msgCaptcha = (req, res, next) => {
message: '',
data: ''
};
let area = +req.body.area;
let mobile = +req.body.mobile;
let code = +req.body.code; // 短信验证码
let area = req.body.area;
let mobile = req.body.mobile;
let code = req.body.code; // 短信验证码
regService.validMobileCode(area, mobile, code).then((result) => {
if (result.code) {
... ... @@ -230,7 +230,7 @@ let mobileRegister = (req, res, next) => {
};
/* 判断是否是有效的注册方式,防注册机刷 */
let regExpireTime = req.session._REG_EXPIRE;
let regExpireTime = req.session.REG_EXPIRE_;
if (!regExpireTime || regExpireTime < Date.now()) {
data.message = '注册超时';
... ... @@ -254,9 +254,9 @@ let mobileRegister = (req, res, next) => {
yield cache.set(ipKey, ipTimes + 1, 3600);
let area = +req.body.area;
let mobile = +req.body.mobile;
let code = +req.body.code; // 短信验证码
let area = req.body.area;
let mobile = req.body.mobile;
let code = req.body.code; // 短信验证码
let password = req.body.password;
let result = yield regService.validMobileCode(area, mobile, code); // 验证注册的标识码是否有效
... ... @@ -273,7 +273,7 @@ let mobileRegister = (req, res, next) => {
return res.json(data);
}
return authHelper.syncUserSession(regResult.data.uid, req, res).then(() => {
return loginService.syncUserSession(regResult.data.uid, req, res).then(() => {
return res.json({
code: 200,
message: '注册成功',
... ...
... ... @@ -5,8 +5,7 @@
*/
'use strict';
var express = require('express'),
path = require('path'),
hbs = require('express-handlebars');
path = require('path');
var passport = require('passport');
... ... @@ -20,12 +19,12 @@ app.on('mount', function(parent) {
Object.assign(app.locals, parent.locals);
});
app.set('views', path.join(__dirname, 'views/action'));
app.engine('.hbs', hbs({
app.use(global.yoho.hbs({
extname: '.hbs',
defaultLayout: 'layout',
layoutsDir: doraemon,
partialsDir: [path.join(__dirname, 'views/partial'), `${doraemon}/partial`],
partialsDir: [path.join(__dirname, 'views/partial')],
views: path.join(__dirname, 'views/action'),
helpers: global.yoho.helpers
}));
... ...
... ... @@ -24,13 +24,13 @@ const validateEmailOrMobileAsync = (userInput, areaCode) => {
return new Promise(function(resolve, rejected) {
let result = {type: 'email', area: '', phone: ''};
if (passportHelper.validator.verifyEmail(userInput)) {
if (passportHelper.validator.isEmail(userInput)) {
result.type = 'email';
result.area = '';
result.phone = userInput;
resolve(result);
} else if (passportHelper.validator.isAreaMobile(passportHelper.makeAreaMobile(areaCode, userInput))) {
} else if (passportHelper.validator.isMobile(userInput)) {
result.type = 'mobile';
result.area = areaCode;
result.phone = userInput;
... ... @@ -57,7 +57,7 @@ const findUserAsync = (type, phone, area) => {
const findBy = {
email: userService.findByEmailAsync,
mobile: (phone1, area1) => userService.findByMobileAsync(area1, phone1) // 交换参数
mobile: _.rearg(userService.findByMobileAsync, [1, 0]) // 交换参数
};
const OK = {code: 200, message: MESSAGE.ok};
... ...
/**
* 注册数据接口
*
* @author JiangFeng<jeff.jiang@yoho.cn>
* @date 2016/06/21
*/
'use strict';
const api = global.yoho.API;
const bindCheck = (mobile, openId, sourceType, area) => {
let params = {
method: 'app.passport.signCheck',
area: area,
mobile: mobile,
open_id: openId,
source_type: sourceType
};
return api.get('', params);
};
const sendBindMsg = (area, mobile) => {
let params = {
method: 'app.passport.smsbind',
mobile: mobile,
area: area
};
return api.get('', params);
};
const checkBindCode = (area, mobile, code) => {
return api.get('', {
method: 'app.register.validRegCode',
mobile: mobile,
area: area,
code: code
});
};
const bindMobile = (openId, sourceType, mobile, area, password, nickname) => {
let params = {
method: 'app.passport.bind',
mobile: mobile,
open_id: openId,
source_type: sourceType,
area: area
};
if (password) {
params.password = password;
}
if (nickname) {
params.nickname = nickname;
}
return api.get('', params);
};
const relateMobile = (openId, sourceType, mobile, area) => {
return api.get('', {
method: 'app.passport.relatedMobile',
mobile: mobile,
openId: openId,
source_type: sourceType,
area: area
});
};
const changeCheck = (mobile, area) => {
return api.get('', {
method: 'app.passport.changeCheck',
mobile: mobile,
area: area
});
};
const changeMobile = (uid, mobile, area, code) => {
return api.get('', {
method: 'app.passport.changeMobile',
mobile: mobile,
uid: uid,
code: code,
area: area
});
};
module.exports = {
bindCheck,
sendBindMsg,
checkBindCode,
bindMobile,
relateMobile,
changeCheck,
changeMobile
};
... ...
... ... @@ -7,81 +7,6 @@
'use strict';
const api = global.yoho.API;
const api = require('./bind-api');
const BindService = {
bindCheck(mobile, openId, sourceType, area) {
let params = {
method: 'app.passport.signCheck',
area: area,
mobile: mobile,
open_id: openId,
source_type: sourceType
};
return api.get('', params);
},
sendBindMsg(area, mobile) {
let params = {
method: 'app.passport.smsbind',
mobile: mobile,
area: area
};
return api.get('', params);
},
checkBindCode(area, mobile, code) {
return api.get('', {
method: 'app.register.validRegCode',
mobile: mobile,
area: area,
code: code
});
},
bindMobile(openId, sourceType, mobile, area, password, nickname) {
let params = {
method: 'app.passport.bind',
mobile: mobile,
open_id: openId,
source_type: sourceType,
area: area
};
if (password) {
params.password = password;
}
if (nickname) {
params.nickname = nickname;
}
return api.get('', params);
},
relateMobile(openId, sourceType, mobile, area) {
return api.get('', {
method: 'app.passport.relatedMobile',
mobile: mobile,
openId: openId,
source_type: sourceType,
area: area
});
},
changeCheck(mobile, area) {
return api.get('', {
method: 'app.passport.changeCheck',
mobile: mobile,
area: area
});
},
changeMobile(uid, mobile, area, code) {
return api.get('', {
method: 'app.passport.changeMobile',
mobile: mobile,
uid: uid,
code: code,
area: area
});
}
};
module.exports = BindService;
module.exports = api;
... ...
... ... @@ -6,13 +6,15 @@
const serviceAPI = global.yoho.ServiceAPI;
const config = global.yoho.config;
/**
* 资源码找资源
*/
const getResourceAsync = resourceCode => {
return serviceAPI.get('/operations/api/v5/resource/get', {
content_code: resourceCode
});
}, config.apiCache);
};
module.exports = {
... ...
'use strict';
/**
* Created by TaoHuang on 2016/10/21.
*/
const md5 = require('md5');
'use strict';
const aes = require('./aes-pwd');
const cache = global.yoho.cache;
const sign = global.yoho.sign;
const api = global.yoho.API;
const cookie = global.yoho.cookie;
const Promise = require('bluebird');
const cartService = require('./cart-service');
const Auth = {
signin(type, area, profile, password, shoppingKey) {
let _that = this;
let loginBy = {
password: _that.signinByPasswordWithAes,
sms: _that.signinBySMS,
qrcode: _that.signinByQrCode
};
return loginBy[type](area, profile, password, shoppingKey);
},
signinByPasswordWithAes(area, profile, password, shoppingKey) {
let param = {
method: 'app.passport.signinAES',
area: area,
profile: profile,
password: aes.aesPwd(password)
};
if (shoppingKey) {
param.shopping_key = shoppingKey;
}
return api.post('', param);
},
signinBySMS(area, mobile, token, shoppingKey) {
let param = {
method: 'app.passport.autoSignin',
area: area,
profile: mobile,
code: token
};
if (shoppingKey) {
param.shopping_key = shoppingKey;
}
return api.post('', param);
},
signinByQrCode(__1, __2, code, shoppingKey) { // eslint-disable-line
let param = {
method: 'app.twoDimen.qrCodeLogin',
code: code.substring(code.indexOf('=') + 1)
};
if (shoppingKey) {
param.shopping_key = shoppingKey;
}
return api.post('', param);
},
fetchByQrCode() {
let param = {
method: 'app.twoDimen.getCode'
};
return api.post('', param);
},
checkByQrCode(code) {
let param = {
method: 'app.twoDimen.loginCheck',
code: code
};
return api.post('', param);
},
sendPasswordBySMS(area, mobile) {
let param = {
method: 'app.message.sendSms',
area: area,
mobile: mobile,
type: 1 // 手机快捷登录短信验证码
};
return api.get('', param);
},
checkUserExitBySMS(area, mobile) {
return api.get('', {
method: 'app.passport.checkUserExist',
area: area,
mobile: mobile
});
},
verifyPasswordBySMS(area, mobile, code) {
return api.get('', {
method: 'app.message.verifySmsCode',
area: area,
mobile: mobile,
code: code,
type: 1 // 手机快捷登录短信验证码
});
},
signinByOpenID(nickname, openId, sourceType, shoppingKey) {
let param = {
nickname: nickname,
openId: openId,
source_type: sourceType,
method: 'app.passport.signinByOpenID'
};
if (shoppingKey) {
param.shopping_key = shoppingKey;
}
return api.get('', param);
},
signinByWechat(nickname, openId, unionId, sourceType, shoppingKey) {
let param = {
nickname: nickname,
openId: openId,
unionId: unionId,
source_type: sourceType,
method: 'app.passport.signinByWechat'
};
if (shoppingKey) {
param.shopping_key = shoppingKey;
}
return api.get('', param);
},
profile(uid) {
let param = {
uid: uid,
method: 'app.passport.profile'
};
return api.get('', param);
},
syncUserSession(uid, req, res) {
return Promise.all([Auth.profile(uid), cartService.goodsCount(uid)]).spread((userInfo, count) => {
let token = sign.makeToken(uid);
let data = userInfo.data;
let encryptionUid = aes.encryptionUid(data.uid);
if (data) {
let uidCookie = `${data.profile_name}::${encryptionUid}::${data.vip_info.title}::${token}`;
let isStudent = data.vip_info.is_student || 0;
req.session._TOKEN = token;
req.session._LOGIN_UID = uid;
res.cookie('_UID', uidCookie, {
domain: 'yohobuy.com'
});
res.cookie('isStudent', isStudent, {
domain: 'yohobuy.com'
});
// 购物车中商品的数量
res.cookie('_g', JSON.stringify({
_k: cookie.getShoppingKey(req),
_nac: count,
_ac: 0,
_c: 1
}), {
domain: 'yohobuy.com'
});
}
req.session._TOKEN = token; // esline-disable-line
req.session._LOGIN_UID = uid; // esline-disable-line
res.cookie('_TOKEN', token, {
domain: 'yohobuy.com'
}); // esline-disable-line
}).catch(console.log);
},
rememberAccount(accountInfo, req, res) {
let aWeek = (new Date()).getTime() / 1000 + 504000; // 504000-一周
let rememKey = md5(md5(accountInfo.account + accountInfo.password + accountInfo.area));
res.cookie('isRemember', true, aWeek);
res.cookie('remem', rememKey, aWeek);
if (!cache.get(rememKey)) {
cache.set(rememKey, accountInfo, aWeek);
}
const signinByPasswordWithAes = (area, profile, password, shoppingKey) => {
let param = {
method: 'app.passport.signinAES',
area: area,
profile: profile,
password: aes.aesPwd(password)
};
if (shoppingKey) {
param.shopping_key = shoppingKey;
}
return api.post('', param);
};
const signinBySMS = (area, mobile, token, shoppingKey) => {
let param = {
method: 'app.passport.autoSignin',
area: area,
profile: mobile,
code: token
};
if (shoppingKey) {
param.shopping_key = shoppingKey;
}
return api.post('', param);
};
const signinByQrCode = (__1, __2, code, shoppingKey) => { // eslint-disable-line
let param = {
method: 'app.twoDimen.qrCodeLogin',
code: code.substring(code.indexOf('=') + 1)
};
if (shoppingKey) {
param.shopping_key = shoppingKey;
}
return api.post('', param);
};
const fetchByQrCode = () => {
let param = {
method: 'app.twoDimen.getCode'
};
return api.post('', param);
};
const checkByQrCode = (code) => {
let param = {
method: 'app.twoDimen.loginCheck',
code: code
};
return api.post('', param);
};
const sendPasswordBySMS = (area, mobile) => {
let param = {
method: 'app.message.sendSms',
area: area,
mobile: mobile,
type: 1 // 手机快捷登录短信验证码
};
return api.get('', param);
};
const checkUserExitBySMS = (area, mobile) => {
return api.get('', {
method: 'app.passport.checkUserExist',
area: area,
mobile: mobile
});
};
const verifyPasswordBySMS = (area, mobile, code) => {
return api.get('', {
method: 'app.message.verifySmsCode',
area: area,
mobile: mobile,
code: code,
type: 1 // 手机快捷登录短信验证码
});
};
const signinByOpenID = (nickname, openId, sourceType, shoppingKey) => {
let param = {
nickname: nickname,
openId: openId,
source_type: sourceType,
method: 'app.passport.signinByOpenID'
};
if (shoppingKey) {
param.shopping_key = shoppingKey;
}
return api.get('', param);
};
module.exports = Auth;
module.exports = {
signinByPasswordWithAes,
signinBySMS,
signinByQrCode,
fetchByQrCode,
checkByQrCode,
sendPasswordBySMS,
checkUserExitBySMS,
verifyPasswordBySMS,
signinByOpenID
};
... ...
'use strict';
const md5 = require('md5');
const aes = require('./aes-pwd');
const cache = global.yoho.cache;
const sign = global.yoho.sign;
const cookie = global.yoho.cookie;
const config = global.yoho.config;
const Promise = require('bluebird');
const cartService = require('./cart-service');
const userService = require('./user-service');
const api = require('./login-api');
const signin = (type, area, profile, password, shoppingKey) => {
let loginBy = {
password: api.signinByPasswordWithAes,
sms: api.signinBySMS,
qrcode: api.signinByQrCode
};
return loginBy[type](area, profile, password, shoppingKey);
};
const syncUserSession = (uid, req, res, sessionKey) => {
if (sessionKey) {
cache.set(`java_session_key:${uid}`, sessionKey).catch(() => {
global.yoho.logger.error('write session key fail');
});
}
return Promise.all([userService.profile(uid), cartService.goodsCount(uid)]).spread((userInfo, count) => {
let token = sign.makeToken(uid);
let data = userInfo.data;
let encryptionUid = aes.encryptionUid(data.uid);
if (data) {
let uidCookie = `${data.profile_name}::${encryptionUid}::${data.vip_info.title}::${token}`;
let isStudent = data.vip_info.is_student || 0;
res.cookie('_UID', uidCookie, {
domain: config.cookieDomain
});
res.cookie('isStudent', isStudent, {
domain: config.cookieDomain
});
// 购物车中商品的数量
res.cookie('_g', JSON.stringify({
_k: cookie.getShoppingKey(req),
_nac: count,
_ac: 0,
_c: 1
}), {
domain: config.cookieDomain
});
}
req.session.TOKEN_ = token;
req.session.LOGIN_UID_ = uid;
res.cookie('_TOKEN', token, {
domain: config.cookieDomain
});
}).catch(console.log);
};
const rememberAccount = (accountInfo, req, res) => {
let aWeek = (new Date()).getTime() / 1000 + 504000; // 504000-一周
let rememKey = md5(md5(accountInfo.account + accountInfo.password + accountInfo.area));
res.cookie('isRemember', true, {
maxAge: aWeek,
domain: config.cookieDomain
});
res.cookie('remem', rememKey, {
maxAge: aWeek,
domain: config.cookieDomain
});
// if (!cache.get(rememKey)) {
// cache.set(rememKey, accountInfo, aWeek);
// }
};
module.exports = {
signin,
syncUserSession,
rememberAccount,
fetchByQrCode: api.fetchByQrCode,
checkByQrCode: api.checkByQrCode,
sendPasswordBySMS: api.sendPasswordBySMS,
checkUserExitBySMS: api.checkUserExitBySMS,
verifyPasswordBySMS: api.verifyPasswordBySMS,
signinByOpenID: api.signinByOpenID
};
... ...
... ... @@ -9,9 +9,6 @@ const _ = require('lodash');
const helpers = global.yoho.helpers;
const indexService = require('./index-service');
const UserService = require('./user-service');
const DEFAULT_HEAD_IMG_ICO = 'http://img10.static.yhbimg.com/headimg/2013/11/28/09/01cae078abe5fe320c88cdf4c220212688.gif?imageView/2/w/100/h/100';
/**
* 获得图片
... ... @@ -109,125 +106,14 @@ const getCountry = () => {
};
/**
* 各国手机号规则
*/
const _areaMobileVerify = (phone, area) => {
area = area || '86';
phone = phone.trim();
let verify = {
86: {
name: '中国',
match: /^1[3|4|5|8|7][0-9]{9}$/.test(phone)
},
852: {
name: '中国香港',
match: /^[9|6|5][0-9]{7}$/.test(phone)
},
853: {
name: '中国澳门',
match: /^[0-9]{8}$/.test(phone)
},
886: {
name: '中国台湾',
match: /^[0-9]{10}$/.test(phone)
},
65: {
name: '新加坡',
match: /^[9|8][0-9]{7}$/.test(phone)
},
60: {
name: '马来西亚',
match: /^1[1|2|3|4|6|7|9][0-9]{8}$/.test(phone)
},
1: {
name: '加拿大&美国',
match: /^[0-9]{10}$/.test(phone)
},
82: {
name: '韩国',
match: /^01[0-9]{9}$/.test(phone)
},
44: {
name: '英国',
match: /^7[7|8|9][0-9]{8}$/.test(phone)
},
81: {
name: '日本',
match: /^0[9|8|7][0-9]{9}$/.test(phone)
},
61: {
name: '澳大利亚',
match: /^[0-9]{11}$/.test(phone)
}
};
if (verify[area]) {
return verify[area].match;
} else {
return false;
}
};
/**
* 验证国际手机号是否合法
*/
const isAreaMobile = areaMobile => {
if (!areaMobile) {
return false;
}
let mobile = {
area: '86',
phone: ''
};
let splitMobile = areaMobile.split('-');
if (splitMobile.length === 2) {
mobile.area = splitMobile[0];
mobile.phone = splitMobile[1];
} else {
mobile.phone = splitMobile[0];
}
return _areaMobileVerify(mobile.phone, mobile.area);
};
const isMobile = _.toNumber;
/**
* 验证邮箱是否合法
*/
const verifyEmail = email => {
if (!email) {
return false;
}
const emailRegExp = /^[\.a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/;
return emailRegExp.test(email);
};
/**
* 验证手机是否合法
*/
const verifyMobile = phone => {
if (!phone) {
return false;
}
return /^1[3|4|5|8|7][0-9]{9}$/.test(phone);
};
/**
* 生成带区号的手机号码
*/
const makeAreaMobile = (area, mobile) => {
if (!area || area === '86') {
return mobile;
}
return `${area}-${mobile}`;
};
const isEmail = email => _.includes(email, '@');
/**
* 密码是否合法
... ... @@ -242,35 +128,13 @@ const isPassword = pwd => {
return pwdRegexp.test(_.trim(pwd));
};
/**
* 第三方登录 根据手机号获取用户相关信息
*/
const getUserInfo = (area, mobile) => {
return UserService.findByMobileAsync(area, mobile).then(user => {
let profile = (user.profile_name || mobile).toString();
if ((profile.length === 11 && profile.indexOf('*') < 0) || (profile.indexOf('-') >= 0 &&
profile.indexOf('*') < 0)) {
profile = profile.substring(0, 3) + '****' + profile.substring(7, 11);
}
return {
username: profile,
headImg: user.head_ico ? helpers.image(user.head_ico, 100, 100, 2) : DEFAULT_HEAD_IMG_ICO,
bindLogin: helpers.urlFormat('/signin.html', { bindMobile: mobile, bindArea: area })
};
});
};
module.exports = {
validator: {
verifyMobile,
isAreaMobile,
verifyEmail,
isMobile,
isEmail,
isPassword
},
makeAreaMobile,
getCountry,
getLeftBannerAsync,
getUserInfo
getLeftBannerAsync
};
... ...
/**
* Created by TaoHuang on 2016/10/21.
*/
/**
* 注册 model
*/
'use strict';
const aes = require('./aes-pwd');
const api = global.yoho.API;
let sendCodeToMobile = (area, mobile) => {
let params = {
method: 'app.register.sendRegCodeToMobile',
area: area,
mobile: mobile
};
return api.post('', params);
};
let validMobileCode = (area, mobile, code) => {
let params = {
method: 'app.register.validRegCode',
area: area,
mobile: mobile,
code: code
};
return api.post('', params);
};
let regMobile = (area, mobile, password, shoppingKey)=> {
let params = {
method: 'app.passport.register',
area: area,
profile: mobile,
password: password
};
if (shoppingKey) {
params.shopping_key = shoppingKey;
}
return api.post('', params);
};
let regMobileAes = (area, mobile, password, shoppingKey)=> {
let params = {
method: 'app.passport.registerAES',
area: area,
profile: mobile,
password: aes.aesPwd(password)
};
if (shoppingKey) {
params.shopping_key = shoppingKey;
}
return api.post('', params);
};
module.exports = {
sendCodeToMobile,
validMobileCode,
regMobile,
regMobileAes
};
... ...
... ... @@ -3,69 +3,14 @@
*/
'use strict';
const passportHelper = require('./passport-helper');
const aes = require('./aes-pwd');
const api = require('./reg-api');
const REGISTER_LEFT_BANNER_CODE = 'c479ec90120cae7f96e52922b4917064'; // 注册左边的banner
const api = global.yoho.API;
let getRegData = () => {
return passportHelper.getLeftBannerAsync(REGISTER_LEFT_BANNER_CODE);
};
let sendCodeToMobile = (area, mobile) => {
let params = {
method: 'app.register.sendRegCodeToMobile',
area: area,
mobile: mobile
};
return api.post('', params);
};
let validMobileCode = (area, mobile, code) => {
let params = {
method: 'app.register.validRegCode',
area: area,
mobile: mobile,
code: code
};
return api.post('', params);
};
let regMobile = (area, mobile, password, shoppingKey)=> {
let params = {
method: 'app.passport.register',
area: area,
profile: mobile,
password: password
};
if (shoppingKey) {
params.shopping_key = shoppingKey;
}
return api.post('', params);
};
let regMobileAes = (area, mobile, password, shoppingKey)=> {
let params = {
method: 'app.passport.registerAES',
area: area,
profile: mobile,
password: aes.aesPwd(password)
};
if (shoppingKey) {
params.shopping_key = shoppingKey;
}
return api.post('', params);
};
module.exports = {
getRegData,
sendCodeToMobile,
validMobileCode,
regMobile,
regMobileAes
};
module.exports = Object.assign(api, {
getRegData
});
... ...
... ... @@ -34,21 +34,30 @@ const findByEmailAsync = (email) => {
return api.get('', {
email: email,
method: 'app.passport.getProfileByEmail'
})
.then(result => {
if (!result.code || result.code !== 200 || !result.data || _.isEmpty(result.data)) {
return EMPTY;
}
}).then(result => {
if (!result.code || result.code !== 200 || !result.data || _.isEmpty(result.data)) {
return EMPTY;
}
return result.data;
return result.data;
})
.catch(() => {
return EMPTY;
});
}).catch(() => {
return EMPTY;
});
};
const profile = (uid) => {
let param = {
uid: uid,
method: 'app.passport.profile'
};
return api.get('', param);
};
module.exports = {
findByMobileAsync,
findByEmailAsync
findByEmailAsync,
profile
};
... ...
... ... @@ -5,4 +5,30 @@
const api = require('./user-api');
module.exports = api;
const helpers = global.yoho.helpers;
const DEFAULT_HEAD_IMG_ICO = 'http://img10.static.yhbimg.com/headimg/2013/11/28/09/01cae078abe5fe320c88cdf4c220212688.gif?imageView/2/w/100/h/100';
/**
* 第三方登录 根据手机号获取用户相关信息
*/
const getUserInfo = (area, mobile) => {
return api.findByMobileAsync(area, mobile).then(user => {
let profile = (user.profile_name || mobile).toString();
if ((profile.length === 11 && profile.indexOf('*') < 0) || (profile.indexOf('-') >= 0 &&
profile.indexOf('*') < 0)) {
profile = profile.substring(0, 3) + '****' + profile.substring(7, 11);
}
return {
username: profile,
headImg: user.head_ico ? helpers.image(user.head_ico, 100, 100, 2) : DEFAULT_HEAD_IMG_ICO,
bindLogin: helpers.urlFormat('/signin.html', {bindMobile: mobile, bindArea: area})
};
});
};
module.exports = Object.assign(api, {
getUserInfo
});
... ...
... ... @@ -92,7 +92,7 @@
<span id="login-btn" class="login-btn btn">登录</span>
</li>
<li class="other-opts">
<span class="remember-me">
<span class="remember-me checked">
<i class="iconfont">&#xe613;</i>
记住登录状态
</span>
... ...
... ... @@ -7,6 +7,7 @@
const mRoot = '../models';
const list = require(`${mRoot}/list`);
const helpers = global.yoho.helpers;
const _ = require('lodash');
// 搜索相关接口
const searchApi = require(`${mRoot}/search-api`);
... ... @@ -32,12 +33,22 @@ const shop = (shopId, req, res, next, brandInfo) => {
page: 'shop',
shopId: shopId
});
// 店铺装修为空则不cache
if (!result.shopTopBanner) {
res.set('Cache-Control', 'no-cache');
}
res.render('list/shop-index', result);
}).catch(next);
} else { // 基础模板
list.getBaseShopData(req.query, Object.assign({uid: req.user.uid}, brandInfo),
req.yoho.channel, shopId).then(result => {
Object.assign(result, {page: 'list'});
// 基础店铺装修为空则不cache
if (!result.shopTopBannerBase) {
res.set('Cache-Control', 'no-cache');
}
res.render('list/brand', result);
}).catch(next);
}
... ... @@ -55,6 +66,11 @@ exports.index = (req, res, next) => {
list.getListData(req.query, req.yoho.channel).then(result => {
Object.assign(resData, result);
// 查询结果为空则不cache
if (_.isEmpty(_.get(resData, 'list.goods', []))) {
res.set('Cache-Control', 'no-cache');
}
res.render('list/index', resData);
}).catch(next);
... ... @@ -73,6 +89,12 @@ exports.new = (req, res, next) => {
Object.assign(resData, result, {
hideInfo: {from: 'newProduct'}
});
// 查询结果为空则不cache
if (_.isEmpty(_.get(resData, 'list.goods', []))) {
res.set('Cache-Control', 'no-cache');
}
res.render('list/index', resData);
}).catch(next);
... ... @@ -168,6 +190,11 @@ exports.shopList = (req, res, next) => {
if (req.query.query) {
result.shopKey = req.query.query;
}
// 店铺装修为空则不cache
if (!result.shopTopBanner) {
res.set('Cache-Control', 'no-cache');
}
res.render('list/shop-list', result);
}).catch(next);
};
... ...
... ... @@ -5,8 +5,7 @@
*/
var express = require('express'),
path = require('path'),
hbs = require('express-handlebars');
path = require('path');
var app = express();
... ... @@ -18,12 +17,12 @@ app.on('mount', function(parent) {
Object.assign(app.locals, parent.locals);
});
app.set('views', path.join(__dirname, 'views/action'));
app.engine('.hbs', hbs({
app.use(global.yoho.hbs({
extname: '.hbs',
defaultLayout: 'layout',
layoutsDir: doraemon,
partialsDir: [path.join(__dirname, 'views/partial'), `${doraemon}/partial`],
partialsDir: [path.join(__dirname, 'views/partial')],
views: path.join(__dirname, 'views/action'),
helpers: global.yoho.helpers
}));
... ...
... ... @@ -5,12 +5,13 @@
'use strict';
const api = global.yoho.API;
const config = global.yoho.config;
const getBannerInfoAsync = bid => {
return api.get('', {
method: 'web.brand.banner',
brand_id: bid
});
}, config.apiCache);
};
... ... @@ -18,7 +19,7 @@ const getBrandLogoByDomainAsync = domain => {
return api.get('', {
domain: domain,
method: 'web.brand.byDomain'
});
}, config.apiCache);
};
module.exports = {
... ...
... ... @@ -7,18 +7,6 @@
const api = global.yoho.API;
/**
* 获取评论
*/
const indexAsync = (pid, page, size) => {
return api.get('', {
method: 'app.comment.li',
product_id: pid,
page: page,
limit: size
});
};
/**
* 商品详情页的评论列表
*
* @param pid 商品productId
... ... @@ -39,7 +27,6 @@ const getShareOrderListAsync = (pid, page, size) => {
};
module.exports = {
indexAsync,
getShareOrderListAsync
};
... ...
... ... @@ -4,45 +4,7 @@
'use strict';
const Promise = require('bluebird');
const co = Promise.coroutine;
const _ = require('lodash');
const helpers = global.yoho.helpers;
const api = require('./detail-comment-api');
const detailHelper = require('./detail-helper');
const indexAsync = (pid, page, size) => {
return co(function *() {
let commentList = yield api.indexAsync(pid, page, size);
if (!(commentList.code && commentList.code === 200)) {
return [];
}
return commentList.data.map(value => {
let item = {};
let avatar = detailHelper.DEFAULT_AVATAR_ICO;
if (value.head_ico) {
avatar = `${_.last(value.head_ico.split('headimg'))}`;
avatar = helpers.image(avatar, 30, 30);
}
item.avatar = avatar;
item.userName = value.nickname;
item.color = value.color_name;
item.size = value.size_name;
item.comment = value.content || '';
item.date = value.create_time;
item.total = value.total;
return item;
});
})();
};
/**
* 获取订单评论
... ... @@ -51,11 +13,8 @@ const indexAsync = (pid, page, size) => {
* @param page
* @param size
*/
const getShareOrderListAsync = (pid, page, size) => {
return api.getShareOrderListAsync(pid, page, size);
};
const getShareOrderListAsync = api.getShareOrderListAsync;
module.exports = {
indexAsync,
getShareOrderListAsync
};
... ...
... ... @@ -5,6 +5,7 @@
'use strict';
const api = global.yoho.API;
const config = global.yoho.config;
/**
* 获取商品的热区
... ... @@ -13,7 +14,7 @@ const indexAsync = pid => {
return api.get('', {
method: 'web.productCollocation.list',
product_id: pid
});
}, config.apiCache);
};
module.exports = {
... ...
... ... @@ -5,12 +5,13 @@
'use strict';
const api = global.yoho.API;
const config = global.yoho.config;
const getProductBannerAsync = (pid) => {
return api.get('', {
method: 'web.productBanner.data',
product_id: pid
});
}, config.apiCache);
};
... ... @@ -18,7 +19,7 @@ const sizeInfoAsync = skn => {
return api.get('', {
method: 'h5.product.intro',
productskn: skn
});
}, config.apiCache);
};
... ... @@ -27,14 +28,14 @@ const isSupportReturnedSale = skn => {
return api.get('', {
method: 'app.product.refundExchange',
product_skn: skn
});
}, config.apiCache);
};
const getProductComfortAsync = pid => {
return api.get('', {
method: 'web.productComfort.data',
product_id: pid
});
}, config.apiCache);
};
... ... @@ -42,14 +43,14 @@ const getProductModelCardAsync = pid => {
return api.get('', {
method: 'web.productModelcard.list',
product_id: pid
});
}, config.apiCache);
};
const getProductModelTryAsync = skn => {
return api.get('', {
method: 'web.productModelTry.data',
product_skn: skn
});
}, config.apiCache);
};
/**
... ... @@ -74,7 +75,7 @@ const getProductAsync = (pid, uid, isStudents, vipLevel) => {
if (vipLevel) {
params.current_vip_level = vipLevel;
}
return api.get('', params);
return api.get('', params, config.apiCache);
};
const getPromotionAsync = (skn) => {
... ... @@ -83,7 +84,7 @@ const getPromotionAsync = (skn) => {
product_skn: skn
};
return api.get('', params);
return api.get('', params, config.apiCache);
};
const getLimitedProductStatusAsync = (code, uid, skn) => {
... ... @@ -100,7 +101,7 @@ const getLimitedProductStatusAsync = (code, uid, skn) => {
params.product_skn = skn;
}
return api.get('', params);
return api.get('', params, config.apiCache);
};
module.exports = {
... ...
... ... @@ -19,7 +19,6 @@ const consultService = require('./detail-consult-service');
const commentService = require('./detail-comment-service');
const hotAreaService = require('./detail-hotarea-service');
const brandService = require('./brand-service');
const favoriteBrandService = require('./favorite-brand-service');
const favoriteProductService = require('./favorite-product-service');
const shopService = require('./shop-service');
... ... @@ -1406,7 +1405,6 @@ const showMainAsync = (data) => {
};
module.exports = {
indexCommentAsync: commentService.indexAsync, // 获取评论列表
getShareOrderListAsync: commentService.getShareOrderListAsync, // 获取评论列表
indexConsultAsync: consultService.indexAsync, // 获取咨询列表
createConsultAsync: consultService.createAsync, // 添加咨询
... ...
... ... @@ -10,6 +10,7 @@
const serviceApi = global.yoho.ServiceAPI;
const api = global.yoho.API;
const _ = require('lodash');
const config = global.yoho.config;
const yhChannel = {
boys: {
... ... @@ -49,7 +50,7 @@ exports.getOutletsActivityOrigin = (params) => {
size: params.size || 0,
yh_channel: yhChannel[tempChannel].channel,
type: params.type || 0
});
}, config.apiCache);
};
/**
... ... @@ -58,7 +59,7 @@ exports.getOutletsActivityOrigin = (params) => {
* @return {[type]}
*/
exports.getChannelResouceData = (params) => {
return serviceApi.get('operations/api/v5/resource/home', params);
return serviceApi.get('operations/api/v5/resource/home', params, config.apiCache);
};
/**
... ... @@ -77,7 +78,7 @@ exports.getOutletsTrendData = (params) => {
stocknumber: 1, // 过滤出库存 > 1的商品
limit: params.limit || 5,
outlets: params.outlets || 1 // 默认取奥莱商品
});
}, config.apiCache);
};
... ... @@ -110,5 +111,5 @@ exports.getOutletsGoodsList = (params) => {
tempParams[paramsName] = params[paramsName];
}
});
return api.get('', tempParams);
return api.get('', tempParams, config.apiCache);
};
... ...
... ... @@ -10,6 +10,7 @@
const serviceAPI = global.yoho.ServiceAPI;
const api = global.yoho.API;
const _ = require('lodash');
const config = global.yoho.config;
const yhChannel = {
boys: {
... ... @@ -42,7 +43,7 @@ exports.getSaleGoodsList = (params) => {
finalParams.yh_channel = yhChannel[params.channel].channel;
}
return api.get('', Object.assign(finalParams, params));
return api.get('', Object.assign(finalParams, params), config.apiCache);
};
/**
... ... @@ -55,7 +56,7 @@ exports.getSalebreakingYardsSortList = (params) => {
return api.get('', {
method: 'app.sale.getBreakingSort',
yh_channel: yhChannel[tempChannel].channel
});
}, config.apiCache);
};
/**
... ... @@ -71,7 +72,7 @@ exports.getSaleActivityList = (params, channel) => {
sort: '2',
plateform: '1',
yh_channel: tempChannel.channel
});
}, config.apiCache);
};
/**
... ... @@ -81,7 +82,7 @@ exports.getSaleActivityList = (params, channel) => {
exports.getSaleBannerList = (cCode) => {
return serviceAPI.get('operations/api/v5/resource/get', {
content_code: cCode
});
}, config.apiCache);
};
/**
... ... @@ -91,7 +92,7 @@ exports.getSaleBannerList = (cCode) => {
exports.getLeftContentList = () => {
return api.get('', {
method: 'app.sort.get'
});
}, config.apiCache);
};
/**
... ...
... ... @@ -7,17 +7,17 @@ const md5 = require('md5');
const api = global.yoho.API;
const serviceApi = global.yoho.ServiceAPI;
const config = global.yoho.config;
const helpers = global.yoho.helpers;
const cache = global.yoho.cache;
const logger = global.yoho.logger;
const config = require('../../../config/common');
const images = require('../../../utils/images.js');
const getSortByConditionAsync = (condition) => {
return api.get('', Object.assign({
method: 'web.regular.groupsort'
}, condition));
}, condition), config.apiCache);
};
// 判断用户是否收藏品牌
... ... @@ -111,7 +111,7 @@ const getProductList = (params, from) => {
}
};
const getSortListOrig = (finalParams) => api.get('', finalParams);
const getSortListOrig = (finalParams) => api.get('', finalParams, config.apiCache);
/**
* 获取分类列表
... ... @@ -167,7 +167,7 @@ const getSortIntro = (params) => {
};
Object.assign(finalParams, params);
return api.get('', finalParams);
return api.get('', finalParams, config.apiCache);
};
/**
... ... @@ -180,7 +180,7 @@ const getSortAds = (params) => {
};
Object.assign(finalParams, params);
return api.get('', finalParams);
return api.get('', finalParams, config.apiCache);
};
/**
... ... @@ -195,7 +195,7 @@ const getBrandSeries = (params) => {
status: params.status || 1
};
return api.get('', finalParams);
return api.get('', finalParams, config.apiCache);
};
/**
... ... @@ -210,7 +210,7 @@ const getBrandFolder = (params) => {
status: params.status || 1
};
return api.get('', finalParams);
return api.get('', finalParams, config.apiCache);
};
/**
... ... @@ -224,7 +224,7 @@ const getNodeContent = (params) => {
node: params.node || ''
};
return api.get('', finalParams);
return api.get('', finalParams, config.apiCache);
};
/**
... ... @@ -238,7 +238,7 @@ const getWeekNew = (params) => {
};
Object.assign(finalParams, params);
return api.get('', finalParams);
return api.get('', finalParams, config.apiCache);
};
/**
... ... @@ -441,7 +441,7 @@ const getSuggest = (params) => {
keyword: params.keyword || ''
};
return api.get('', finalParams);
return api.get('', finalParams, config.apiCache);
};
... ... @@ -455,7 +455,7 @@ const getBrandData = (params) => {
domain: params.domain || ''
};
return api.get('', finalParams);
return api.get('', finalParams, config.apiCache);
};
/**
... ... @@ -466,7 +466,7 @@ const isFavoriteBrand = (uid, brandId) => {
return serviceApi.get(isFavoriteBrandUrl, {
uid: uid,
brandId: brandId
});
}, config.apiCache);
};
/**
... ...
... ... @@ -4,6 +4,7 @@
'use strict';
const api = global.yoho.API;
const config = global.yoho.config;
/**
* 获取店铺装修的所有资源接口
... ... @@ -12,5 +13,5 @@ exports.shopsDecoratorListAsync = shopId => {
return api.get('', {
method: 'app.shopsdecorator.getList',
shop_id: shopId
});
}, config.apiCache);
};
... ...
... ... @@ -6,7 +6,7 @@
'use strict';
const api = global.yoho.API;
const config = require('../../../config/common');
const config = global.yoho.config;
const searchApi = require('./search-api');
const cache = global.yoho.cache;
const logger = global.yoho.logger;
... ... @@ -17,7 +17,7 @@ const logger = global.yoho.logger;
*/
exports.getVerifiedTotal = () => {
return api.get('', {method: 'app.student.verifiedStudentTotal'});
return api.get('', {method: 'app.student.verifiedStudentTotal'}, config.apiCache);
};
/**
... ... @@ -26,7 +26,7 @@ exports.getVerifiedTotal = () => {
*/
exports.getEduLevelList = () => {
return api.get('', {method: 'app.studentMarket.getEducationLevelList'});
return api.get('', {method: 'app.studentMarket.getEducationLevelList'}, config.apiCache);
};
/**
... ... @@ -38,7 +38,7 @@ exports.getArea = () => {
method: 'app.studentMarket.getAddressList'
};
return api.get('', finalParams);
return api.get('', finalParams, config.apiCache);
};
/**
... ... @@ -51,7 +51,7 @@ exports.getSchool = (areaCode) => {
areaCode: areaCode
};
return api.get('', finalParams);
return api.get('', finalParams, config.apiCache);
};
/**
... ... @@ -66,7 +66,7 @@ exports.getStuProducts = (params) => {
};
Object.assign(finalParams, params);
return api.get('', finalParams);
return api.get('', finalParams, config.apiCache);
};
/**
... ... @@ -82,7 +82,7 @@ exports.verifyIdentity = (uid, certNo, name, pageUrl) => {
page_url: pageUrl
};
return api.get('', finalParams);
return api.get('', finalParams, config.apiCache);
};
/**
... ... @@ -99,7 +99,7 @@ exports.verifyStudent = (uid, collegeName, educationDegree, enrollmentYear) => {
enrollment_year: enrollmentYear
};
return api.get('', finalParams);
return api.get('', finalParams, config.apiCache);
};
/**
... ... @@ -117,7 +117,7 @@ exports.userAcquireStatus = (uid, couponIds) => {
finalParams.uid = uid;
}
return api.get('', finalParams);
return api.get('', finalParams, config.apiCache);
};
... ...
... ... @@ -149,7 +149,7 @@ exports.verifyIdentity = (uid, params) => {
educationDegree: params.educationDegree,
enrollmentYear: params.enrollmentYear
}) + '&';
return studentsApi.verifyIdentity(uid, params.certNo, params.name, pageUrl);
};
... ... @@ -238,7 +238,7 @@ exports.getStudentsList = (params, channel) => {
// 获取商品数据和顶部筛选条件
if (result[2].code === 200) {
//删掉student_price,不让页面显示
// 删掉student_price,不让页面显示
_.forEach(result[2].data.product_list, goods => {
delete goods.student_price;
});
... ...
... ... @@ -660,16 +660,18 @@
<div class="service"></div>
{{#if latestWalk}}
<div class="info-block latest-walk">
<input id="latest-walk-count" type="hidden" value="{{latestWalk}}">
<p class="block-title">
<span class="title cur">最近浏览 RECENT REVIEW</span>
</p>
<div id="latest-walk-goods" class="goods clearfix"></div>
{{> product/latest-walk-tpl}}
</div>
{{/if}}
{{#unless @root.pc.product.removeRecentView}}
{{#if latestWalk}}
<div class="info-block latest-walk">
<input id="latest-walk-count" type="hidden" value="{{latestWalk}}">
<p class="block-title">
<span class="title cur">最近浏览 RECENT REVIEW</span>
</p>
<div id="latest-walk-goods" class="goods clearfix"></div>
{{> product/latest-walk-tpl}}
</div>
{{/if}}
{{/unless}}
</div>
</div>
{{/ detail}}
... ...
'use strict';
const SECOND = 1;
const MINUTE = 60 * SECOND;
const cachePage = {
// 频道页
'/': 30 * SECOND,
'/woman': 30 * SECOND,
'/kids': 30 * SECOND,
'/lifestyle': 30 * SECOND,
// 商品详情页
'/product/\\/pro_([\\d]+)_([\\d]+)\\/(.*)/': 30 * MINUTE,
// 逛
'/guang/': 1 * MINUTE,
'/guang/info/index': 10 * MINUTE,
'/guang/detail/:id': 10 * MINUTE,
'/guang/index/editor': 1 * MINUTE,
'/guang/tags/index': 1 * MINUTE,
// 领券中心
'/coupon/index': 5 * MINUTE,
// 商品列表
'/product/list/index': 5 * MINUTE,
'/product/index/index': 5 * MINUTE,
// 秒杀列表
'/product/seckill': 30 * SECOND,
// 秒杀详情
// sale
'/product/sale': 5 * MINUTE,
'/product/sale/vip': 5 * MINUTE,
'/product/sale/breakingYards': 5 * MINUTE,
'/product/sale/newSale': 5 * MINUTE,
'/product/sale/discount/detail': 5 * MINUTE,
'/product/outlet': 30 * SECOND,
'/product/index/brand': 2 * MINUTE,
'/product/index/about': 10 * MINUTE,
'/product/shoplist': 2 * MINUTE,
'/product/list/new': 30 * SECOND,
// 品牌一览
'/brands/': 5 * MINUTE,
'/brands/plusstar': 5 * MINUTE,
'/special/(\\d+)_(.*)\\.html': 5 * MINUTE
};
module.exports = cachePage;
... ...
... ... @@ -14,6 +14,7 @@ module.exports = {
appVersion: '4.9.0', // 调用api的版本
port: 6002,
siteUrl: 'http://www.yohobuy.com',
cookieDomain: '.yohobuy.com',
domains: {
favApi: 'http://192.168.102.31:8092/brower',
api: 'http://api.yoho.cn/',
... ... @@ -44,6 +45,7 @@ module.exports = {
},
loggers: {
infoFile: {
close: true,
name: 'info',
level: 'info',
filename: 'logs/info.log',
... ... @@ -62,7 +64,7 @@ module.exports = {
port: '4444' // influxdb port
},
console: {
level: 'debug',
level: 'error',
colorize: 'all',
prettyPrint: true
}
... ... @@ -71,8 +73,32 @@ module.exports = {
wechat: {
appID: 'wx3ae21dcbb82ad672',
appSecret: 'e78afb2321e6a19085767e1a0f0d52c1'
},
sina: {
appID: '3739328910',
appSecret: '9d44cded26d048e23089e5e975c93df1'
},
qq: {
appID: '100229394',
appSecret: 'c0af9c29e0900813028c2ccb42021792'
},
alipay: {
appID: '2088701661478015',
appSecret: 'kcxawi9bb07mzh0aq2wcirsf9znusobw'
},
douban: {
appID: '03b4e36bf13dc75a0b1eaa43d3b9560e',
appSecret: 'f16d5913e8610672'
},
renren: {
appID: '783130c654c94a77ace97054ae266019',
appSecret: '05e430de8c1e40d3a1f39ca8d3f8252c'
}
}
},
apiCache: {
cache: true
},
zookeeperServer: '192.168.102.168:2188'
};
if (isProduction) {
... ... @@ -98,7 +124,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, {
... ...
/**
* page cache 前端js跳转url中间件
*/
'use strict';
const _ = require('lodash');
const querystring = require('querystring');
const ptm = {
// 首页
'/': '',
'/woman': '/girls',
'/kids': '/kids',
'/lifestyle': '/lifestyle',
// 登录注册
'/signin.html': '/signin.htm',
'/reg.html': '/passport/reg/index',
'/passport/back/index': '/passport/back/mobile',
// 列表
'/product/list/new': '/product/new',
// 品牌列表
'/brands': '/brands',
// 领券中心
'/coupon/index': '/coupon/floor?title=领券中心&code=b78b32ed81b18dde8ac84fd33602b88b'
};
module.exports = () => {
return (req, res, next) => {
let domain = 'm.yohobuy.com';
let proReg = /^\/product\/pro/,
guangReg = /^\/guang/,
guangDetailReg = /.html$/,
qsReg = /\?/;
if (!req.xhr) {
let url = _.head(_.split(req.url, '?'));
let data = {};
if (ptm.hasOwnProperty(url)) {
data.mobileRefer = `//${domain}${ptm[url]}`;
} else if (url === '/product/list/index') {
data.mobileRefer = `//list.${domain}`;
} else if (url === '/product/index/brand') {
data.mobileRefer = `//${req.query.domain}.${domain}`;
} else if (url === '/product/search/index') {
data.mobileRefer = `//search.${domain}`;
} else if (guangReg.test(url)) {
data.mobileRefer = `//guang.${domain}`;
if (guangDetailReg.test(url)) {
data.mobileRefer += url.replace(/\/guang\/detail\/([\d]+).html/, '/info/index?id=$1');
} else if (url === '/guang/Index/editor') {
data.mobileRefer += `/author/index?id=${req.query.author_id}`;
}
} else if (proReg.test(url)) {
data.mobileRefer = `//${domain}${url}`;
}
if (!_.isEmpty(req.query) && !qsReg.test(data.mobileRefer)) {
data.mobileRefer += `?${querystring.stringify(req.query)}`;
}
Object.assign(res.locals, data);
}
next();
};
};
... ...
'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();
};
};
... ...
... ... @@ -22,7 +22,15 @@ module.exports = () => {
case 'guang': // 逛
case 'cdnsrcguang': // 逛CDN回源解析
if (guangDetailReg.test(req.path)) {
req.url = '/guang/detail' + req.url;
// req.url = '/guang/detail' + req.url;
/\/([\d]*).html(\?)?(.*)/.exec(req.url);
req.url = '/guang/info/index?id=' + RegExp.$1;
if (RegExp.$3) {
req.url += '&' + RegExp.$3;
}
req.query.id = RegExp.$1;
console.log(req.url);
} else if (!guangReg.test(req.path)) {
req.url = '/guang' + req.url;
}
... ...
'use strict';
const Fp = require('lodash/fp');
const Fn = require('lodash/fp');
const _ = require('lodash');
const cache = global.yoho.cache;
const cookie = global.yoho.cookie;
const loginService = require('../../apps/passport/models/login-service');
module.exports = () => {
return (req, res, next) => {
// session 没有读取到的时候,从 cookie 读取 UID
// 获得原始请求 url
req.fullUrl = () => req.protocol + '://' + req.get('host') + req.originalUrl;
// 从 cookie 读取 UID
if (req.cookies._UID) {
req.user.uid = cookie.getUid(req);
let getVip = Fp.pipe(Fp.split('::'), Fp.nth(2));
let uidCookie = req.cookies._UID.split('::');
req.user.vip = getVip(req.cookies._UID);
}
let getName = Fn.nth(0);
let getVip = Fn.nth(2);
let getToken = Fn.nth(3);
// 用户是否学生
if (req.user.uid && req.cookies.isStudent) {
req.user.name = getName(uidCookie); // 0
req.user.uid = cookie.getUid(req); // 1
req.user.vip = getVip(uidCookie); // 2
req.user.token = getToken(uidCookie); // 3
req.user.isStudent = req.cookies.isStudent || 0;
}
// 从 SESSION 中获取到当前登录用户的 UID
// if (req.session && _.isNumber(req.session._LOGIN_UID)) {
// req.user.uid = req.session._LOGIN_UID;
// 记住我
// if (_.isEmpty(req.user) && req.cookies.isRemember === 'true' && req.cookies.remem) {
// return cache.get(req.cookies.remem).then((result) => {
// let data = JSON.parse(result || '{}');
// let area = data.area;
// let account = data.account;
// let password = data.password;
// return loginService.signin('password', area, account, password);
// }).then((result) => {
// if (result.code !== 200) {
// return Promise.reject();
// }
// return loginService.syncUserSession(result.data.uid, req, res);
// }).then(() => {
// return res.redirect(req.fullUrl());
// }).catch(next);
// } else {
// return next();
// }
next();
... ...
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>{{title}}</title>
<meta name="keywords" content="{{keywords}}">
<meta name="description" content="{{description}}">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
<meta http-equiv="cleartype" content="on">
<meta name="apple-mobile-web-app-status-bar-style" content="black" />
<meta content="telephone=no" name="format-detection" />
<meta content="email=no" name="format-detection" />
<link rel="dns-prefetch" href="//cdn.yoho.cn">
<link rel="dns-prefetch" href="//static.yohobuy.com">
<link rel="dns-prefetch" href="//img12.static.yhbimg.com">
<link rel="dns-prefetch" href="//img13.static.yhbimg.com">
{{#if devEnv}}
<link rel="stylesheet" href="//localhost:5002/css/index.css">
{{^}}
<link rel="stylesheet" href="//cdn.yoho.cn/yohobuy-node/{{version}}/index.css">
{{/if}}
</head>
<body>
{{> header}}
{{> common/simple-header}}
{{#if pageErr}}
{{> 404}}
{{^}}
{{{body}}}
{{/if}}
{{> footer}}
{{#if devEnv}}
<script src="//localhost:5002/libs.js"></script>
<script src="//localhost:5002/{{module}}.{{page}}.js"></script>
{{^}}
<script src="//cdn.yoho.cn/yohobuy-node/{{version}}/libs.js"></script>
<script src="//cdn.yoho.cn/yohobuy-node/{{version}}/{{module}}.{{page}}.js"></script>
{{> analysis}}
{{/if}}
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>{{title}}</title>
<meta name="keywords" content="{{keywords}}">
<meta name="description" content="{{description}}">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
<meta http-equiv="cleartype" content="on">
<meta name="apple-mobile-web-app-status-bar-style" content="black" />
<meta content="telephone=no" name="format-detection" />
<meta content="email=no" name="format-detection" />
<link rel="dns-prefetch" href="//cdn.yoho.cn">
<link rel="dns-prefetch" href="//static.yohobuy.com">
<link rel="dns-prefetch" href="//img12.static.yhbimg.com">
<link rel="dns-prefetch" href="//img13.static.yhbimg.com">
{{#if devEnv}}
<link rel="stylesheet" href="//localhost:5002/css/index.css">
{{^}}
<link rel="stylesheet" href="//cdn.yoho.cn/yohobuy-node/{{version}}/index.css">
{{/if}}
</head>
<body>
{{#if mobileRefer}}
<input type="hidden" id="m-refer" value="{{mobileRefer}}">
{{/if}}
{{> header}}
{{> common/simple-header}}
{{#if pageErr}}
{{> 404}}
{{^}}
{{{body}}}
{{/if}}
{{> footer}}
{{#if devEnv}}
<script src="//localhost:5002/libs.js"></script>
<script src="//localhost:5002/{{module}}.{{page}}.js"></script>
{{^}}
<script src="//cdn.yoho.cn/yohobuy-node/{{version}}/libs.js"></script>
<script src="//cdn.yoho.cn/yohobuy-node/{{version}}/{{module}}.{{page}}.js"></script>
{{> analysis}}
{{/if}}
</body>
</html>
... ...
... ... @@ -26,7 +26,9 @@
<span class="tag-seprate"></span>
<a href="//www.yohobuy.com/home?t=1453340799.4986">MY有货</a>
<span class="icon-bottomarrow"></span>
<div class="simple-user-center"></div>
{{#unless @root.pc.common.disMyYohoHover}}
<div class="simple-user-center"></div>
{{/unless}}
</li>
<li class="myorder">
<span class="tag-seprate"></span>
... ... @@ -66,7 +68,8 @@
<div class="main-logo"><a href="//www.yohobuy.com/" class="main-link"></a></div>
<ul class="main-nav-list">
{{# navbars}}
<li class="{{type}}"{{#if ico}} style="background: url({{image ico 54 32}}) no-repeat center center"{{/if}}>
<li class="{{type}}"{{#if ico}}
style="background: url({{image ico 54 32}}) no-repeat center center"{{/if}}>
{{#if ico}}
<a href="{{link}}"{{#if isNewPage}} target="_blank"{{/if}} class="menu-ico"></a>
{{^}}
... ... @@ -81,7 +84,9 @@
{{/ navbars}}
</ul>
<div class="func-area hide">
<ul class="search-suggest"></ul>
{{#unless @root.pc.common.disSearchAssociation}}
<ul class="search-suggest"></ul>
{{/unless}}
<div class="search-2016">
<form action="//search.yohobuy.com" method="get" id="search-form">
<input type="hidden" id="defaultsearch" value="{{defaultSearch}}">
... ... @@ -92,16 +97,20 @@
<div class="go-cart">
<a href="//www.yohobuy.com/shopping/cart">
<span class="iconfont ">&#xe600;</span>
<span class="goods-num-tip">0</span>
{{#unless @root.pc.common.removeCartCount}}
<span class="goods-num-tip">0</span>
{{/unless}}
</a>
<div class="mini-cart-wrapper">
<div class="loading-cart">
<h3>加载中,请稍后</h3>
</div>
<div class="empty-cart">
<h3>您的购物车暂无商品</h3>
{{#unless @root.pc.common.disCartHover}}
<div class="mini-cart-wrapper">
<div class="loading-cart">
<h3>加载中,请稍后</h3>
</div>
<div class="empty-cart">
<h3>您的购物车暂无商品</h3>
</div>
</div>
</div>
{{/unless}}
</div>
</div>
</div>
... ... @@ -109,39 +118,40 @@
<div class="nav-wrapper clearfix">
<div class="center-content">
{{# subNavGroup}}
<ul class="sub-nav-list {{subType}}">
{{# subNav}}
<li {{#if thirdNav}}class="contain-third"{{/if}}>
<a href="{{link}}">{{name}}
{{#if isNew}}
<span class="newlogo"></span>
{{/if}}
</a>
{{#if thirdNav}}
<div class="third-nav-wrapper">
<div class="center-content">
<dl class="hide-list hide">
{{# thirdNav}}
<dt>
<h1 class=""><a href="{{link}}">{{title}}</a> </h1>
</dt>
{{#brandItems}}
<dd>
<a href="{{link}}"{{#if hot}} class="hot"{{/if}}>{{brandName}}</a>
</dd>
{{/brandItems}}
{{/thirdNav}}
</dl>
<div class="show-detail" data-code="{{imgCode}}">
<a><img src="data:image/gif;base64,R0lGODlhAQABAJEAAAAAAP///93d3f///yH5BAEAAAMALAAAAAABAAEAAAICVAEAOw=="></a>
<a class="title">热门小物优选</a>
<ul class="sub-nav-list {{subType}}">
{{# subNav}}
<li {{#if thirdNav}}class="contain-third"{{/if}}>
<a href="{{link}}">{{name}}
{{#if isNew}}
<span class="newlogo"></span>
{{/if}}
</a>
{{#if thirdNav}}
<div class="third-nav-wrapper">
<div class="center-content">
<dl class="hide-list hide">
{{# thirdNav}}
<dt>
<h1 class=""><a href="{{link}}">{{title}}</a></h1>
</dt>
{{#brandItems}}
<dd>
<a href="{{link}}"{{#if hot}}
class="hot"{{/if}}>{{brandName}}</a>
</dd>
{{/brandItems}}
{{/thirdNav}}
</dl>
<div class="show-detail" data-code="{{imgCode}}">
<a><img src="data:image/gif;base64,R0lGODlhAQABAJEAAAAAAP///93d3f///yH5BAEAAAMALAAAAAABAAEAAAICVAEAOw=="></a>
<a class="title">热门小物优选</a>
</div>
</div>
</div>
</div>
{{/if}}
</li>
{{/ subNav}}
</ul>
{{/if}}
</li>
{{/ subNav}}
</ul>
{{/ subNavGroup}}
</div>
</div>
... ... @@ -153,7 +163,7 @@
</script>
<script type="text/html" id="simple-account-info-tpl">
<div class="account-info-header">
<div class="user-img" >
<div class="user-img">
<img src="\{{headIco}}">
</div>
<div class="user-name">
... ... @@ -163,15 +173,15 @@
VIP: <span>\{{curTitle}}</span>
</h3>
\{{#unless vip3}}
<div class="level-detail">
<div class="level-view-bar">
<div class="text-span">
\{{curYearCost}}/\{{nextVipNeedCost}}
</div>
<p class="\{{#if curYearCostPer}}integrate\{{/if}}" style="width: \{{curYearCostPer}}%;"></p>
<div class="level-detail">
<div class="level-view-bar">
<div class="text-span">
\{{curYearCost}}/\{{nextVipNeedCost}}
</div>
<span>\{{nextVipTitle}}</span>
<p class="\{{#if curYearCostPer}}integrate\{{/if}}" style="width: \{{curYearCostPer}}%;"></p>
</div>
<span>\{{nextVipTitle}}</span>
</div>
\{{/unless}}
</div>
<ul class="account-info-content">
... ... @@ -197,79 +207,82 @@
</li>
</ul>
<div class="account-info-footer">
<a href="//www.yohobuy.com/home/user?t=\{{timestamp}}">完善资料 <span>(学生认证)</span></a>
<a href="//www.yohobuy.com/home/user?t=\{{timestamp}}">完善资料 <span>(学生认证)</span></a>
</div>
</script>
<script type="text/html" id="mini-cart-tpl">
\{{#carData}}
<div class="rich-cart">
<div class="goods-list">
\{{# totalGoods}}
\{{#notzero buy_number}}
<div class="goods-item">
<div class="goods-img">
<a href="\{{product_url}}">
<img src="\{{default_img}}"/>
</a>
</div>
<div class="goods-info">
<p class="title">
<a href="\{{product_url}}">\{{product_name}}</a>
</p>
<p>
颜色:\{{color_name}}
尺码:\{{size_name}}
</p>
</div>
<div class="goods-price">
<p>\{{show_price}} x \{{buy_number}}</p>
<p>
<a href="javascript:void(0)" class="cart-goods-del" data-id="\{{goods_incart_id}}" data-cheapest="\{{is_cheapest_free}}" data-sku="\{{product_sku}}" data-proid="\{{promotion_id}}" data-num="\{{buy_number}}">删除</a>
</p>
</div>
</div>
\{{/notzero}}
\{{/ totalGoods}}
\{{#if has_promotion}}
<div class="activity-item">
<label class="activity-name">活动</label>
<h3 class="activity-content">
\{{#if fit_outlet_promotion }}
购outlet商品,满¥1999再享9折
\{{/if}}
\{{#if has_other_promotion}}
<span class="mycart_i_down" title="更多" ></span>
\{{/if}}
\{{#if has_first_promotion}}
\{{first_promotions.promotion_title}}
\{{/if}}
</h3>
</div>
\{{/if}}
\{{#if fit_free_shipping }}
<div class="activity-item">
<label class="activity-name">免运费</label>
<h3 class="activity-content">全场满 ¥\{{fit_free_shipping}}免运费</h3>
</div>
\{{/if}}
</div>
<div class="go-full-cart">
<div>
<a href="//www.yohobuy.com/shopping/cart">去购物车结算</a>
\{{#carData}}
<div class="rich-cart">
<div class="goods-list">
\{{# totalGoods}}
\{{#notzero buy_number}}
<div class="goods-item">
<div class="goods-img">
<a href="\{{product_url}}">
<img src="\{{default_img}}"/>
</a>
</div>
<div class="goods-info">
<p class="title">
<a href="\{{product_url}}">\{{product_name}}</a>
</p>
<p>
颜色:\{{color_name}}
尺码:\{{size_name}}
</p>
</div>
<div class="goods-price">
<p>\{{show_price}} x \{{buy_number}}</p>
<p>
<a href="javascript:void(0)" class="cart-goods-del" data-id="\{{goods_incart_id}}"
data-cheapest="\{{is_cheapest_free}}" data-sku="\{{product_sku}}"
data-proid="\{{promotion_id}}" data-num="\{{buy_number}}">删除</a>
</p>
</div>
</div>
\{{/notzero}}
\{{/ totalGoods}}
\{{#if has_promotion}}
<div class="activity-item">
<label class="activity-name">活动</label>
<h3 class="activity-content">
\{{#if fit_outlet_promotion }}
购outlet商品,满¥1999再享9折
\{{/if}}
\{{#if has_other_promotion}}
<span class="mycart_i_down" title="更多"></span>
\{{/if}}
\{{#if has_first_promotion}}
\{{first_promotions.promotion_title}}
\{{/if}}
</h3>
</div>
\{{/if}}
\{{#if fit_free_shipping }}
<div class="activity-item">
<label class="activity-name">免运费</label>
<h3 class="activity-content">全场满 ¥\{{fit_free_shipping}}免运费</h3>
</div>
\{{/if}}
</div>
<div class="go-full-cart">
<div>
<a href="//www.yohobuy.com/shopping/cart">去购物车结算</a>
</div>
</div>
\{{/carData}}
</div>
\{{/carData}}
</script>
<script type="text/html" id="search-suggest-tml">
\{{#data}}
<li>
<a style="display: block;" href="\{{href}}" class="clearfix clear search-item" title="\{{keyword}}" act="\{{href}}">
<span class="searchvalue" >\{{keyword}}</span>
<span class="valuenum">约\{{count}}个商品</span>
</a>
</li>
\{{/data}}
\{{#data}}
<li>
<a style="display: block;" href="\{{href}}" class="clearfix clear search-item" title="\{{keyword}}"
act="\{{href}}">
<span class="searchvalue">\{{keyword}}</span>
<span class="valuenum">约\{{count}}个商品</span>
</a>
</li>
\{{/data}}
</script>
</div>
... ...
{{#if latestWalk}}
<input id="latest-walk-count" type="hidden" value="{{latestWalk}}">
<div class="latest-walk">
<h2>最近浏览的商品</h2>
<div id="latest-walk-goods" class="goods clearfix"></div>
</div>
{{#unless @root.pc.product.removeRecentView}}
{{#if latestWalk}}
<input id="latest-walk-count" type="hidden" value="{{latestWalk}}">
<div class="latest-walk">
<h2>最近浏览的商品</h2>
<div id="latest-walk-goods" class="goods clearfix"></div>
</div>
{{> product/latest-walk-tpl}}
{{/if}}
{{> product/latest-walk-tpl}}
{{/if}}
{{/unless}}
... ...
{
"name": "yohobuy-node",
"version": "5.1.1",
"version": "5.1.2",
"private": true,
"description": "A New Yohobuy Project With Express",
"repository": {
... ... @@ -34,19 +34,14 @@
"bluebird": "^3.4.0",
"body-parser": "^1.15.0",
"captchapng": "0.0.1",
"connect-memcached": "^0.2.0",
"compression": "^1.6.2",
"cookie-parser": "^1.4.3",
"cookie-session": "^1.2.0",
"express": "^4.13.1",
"handlebars": "^4.0.5",
"express-handlebars": "^3.0.0",
"express-session": "^1.13.0",
"influxdb-winston": "^1.0.1",
"lodash": "^4.13.1",
"md5": "^2.1.0",
"memcached": "^2.2.2",
"moment": "^2.14.1",
"morgan": "^1.7.0",
"oneapm": "^1.2.20",
"passport": "^0.3.2",
"passport-douban": "0.0.1",
"passport-local": "^1.0.0",
... ... @@ -56,13 +51,10 @@
"passport-strategy": "1.x.x",
"passport-weixin": "^0.1.0",
"request-ip": "^1.2.2",
"request-promise": "^3.0.0",
"serve-favicon": "^2.3.0",
"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.1.28"
"yoho-node-lib": "0.1.28",
"yoho-zookeeper": "^1.0.3"
},
"devDependencies": {
"autoprefixer": "^6.3.6",
... ...

918 Bytes | W: 0px | H: 0px

45 KB | W: 0px | H: 0px

  • 2-up
  • Swipe
  • Onion skin
... ... @@ -13,7 +13,6 @@ var $tabs = $('.brands-tabs');
var $list = $('.brands-list');
var $gory = $('.brands-category');
var $news = $('.news-txt ul');
var $clearfix = $list.find('dl.clearfix');
var $brand = $list.find('li>a');
var $category = $gory.find('a');
var $tab = $tabs.find('li>a');
... ... @@ -175,6 +174,9 @@ function bindTemplete($select, data, tmp) {
// 鼠标悬浮品牌,请求数据,并且展示
function bindHoverEvent() {
if (String($list.data('ishover')) === 'true') {
return;
}
$brand.unbind('mouseenter').unbind('mouseleave').hover(function() {
var $this = $(this);
var key = $this.attr('data-key');
... ... @@ -210,21 +212,4 @@ function bindHoverEvent() {
});
}
if ($clearfix.length < 26) {
$.ajax({
url: '/brands/brandList',
type: 'POST',
data: {
start: $clearfix.length ? ($clearfix.length + 1) : 1
},
success: function(_data) {
if (_data) {
$list.append(_data);
$brand = $list.find('li>a');
bindHoverEvent();
}
}
});
}
bindHoverEvent();
... ...
... ... @@ -94,6 +94,15 @@ function getShoppingKey() {
return JSON.parse(c).k;
}
// page cache改造-前端移动端检测
(function() {
var mrefer = $('#m-refer').val();
if (mrefer && window.navigator.userAgent.match(/(nokia|iphone|android|ipad|motorola|^mot\-|softbank|foma|docomo|kddi|up\.browser|up\.link|htc|dopod|blazer|netfront|helio|hosin|huawei|novarra|CoolPad|webos|techfaith|palmsource|blackberry|alcatel|amoi|ktouch|nexian|samsung|^sam\-|s[cg]h|^lge|ericsson|philips|sagem|wellcom|bunjalloo|maui|symbian|smartphone|midp|wap|phone|windows ce|iemobile|^spice|^bird|^zte\-|longcos|pantech|gionee|^sie\-|portalmmm|jig\s browser|hiptop|^ucweb|^benq|haier|^lct|opera\s*mobi|opera\*mini|320x320|240x320|176x220)/i)) { // eslint-disable-line
window.location = mrefer;
}
}());
// YAS统计代码
(function(w, d, s, j, f) {
var a = d.createElement(s);
... ...
... ... @@ -109,10 +109,15 @@ $('#collect-btn').click(function() {
case 401:
// 防止从已有col的页面再次进行跳转后出错的情况
if (/\?col=(1|0)/.test(location.href)) {
hrefUrl = location.href.replace(/\?col=(1|0)/, '?col=' + col);
if (/(\?|&)col=(1|0)/.test(location.href)) {
// hrefUrl = location.href.replace(/\?col=(1|0)/, '?col=' + col);
hrefUrl = location.href.replace(/(\?|&)col=(1|0)/, '$1col=x');
} else {
hrefUrl = location.href + '?col=' + col;
if (location.href.indexOf('?') >= 0) {
hrefUrl = location.href + '&col=' + col;
} else {
hrefUrl = location.href + '?col=' + col;
}
}
location.href = '//www.yohobuy.com/signin.html?refer=' + encodeURI(hrefUrl);
break;
... ... @@ -121,10 +126,10 @@ $('#collect-btn').click(function() {
// alert(data.message);
break;
case 200:
if (/\?col=(1|0)/.test(location.href)) {
if (/(\?|&)col=(1|0)/.test(location.href)) {
// 如果页面url中含有col,为了防止页面刷新时收藏或者取消收藏会根据col来的问题,进行页面跳转拿掉参数
location.href = location.href.replace(/\?col=(1|0)/, '');
location.href = location.href.replace(/(\?|&)col=(1|0)/, '');
} else {
$this.toggleClass('collected');
}
... ...
... ... @@ -39,6 +39,8 @@ var logoAngle = 0,
var dataLayer = [];
var cartTimer;
// banner和地址的映射
var bannerMap = {
listboys: '4f78b0f418fc42314d8b6e791cfb7fa8',
... ... @@ -76,11 +78,8 @@ var bannerMap = {
},
cookieMap = {};
var $signinBtn = $('#signin-url');
var $regBtn = $('#reg-url');
$signinBtn.attr('href', '//www.yohobuy.com/signin.html?refer=' + window.location.href);
$regBtn.attr('href', '//www.yohobuy.com/reg.html?refer=' + window.location.href);
$('#signin-url').attr('href', '//www.yohobuy.com/signin.html?refer=' + window.location.href);
$('#reg-url').attr('href', '//www.yohobuy.com/reg.html?refer=' + window.location.href);
// handlebars模板
centerFn = handlebars.compile($('#simple-account-info-tpl').html() || '');
... ... @@ -321,6 +320,11 @@ function syncCratInfo(strG) {
domain: '.yohobuy.com'
});
}
if (!$goodsNum || !$goodsNum.length) {
return cartTimer ? clearInterval(cartTimer) : false;
}
if (window.cookie('_g')) {
info = $.parseJSON(window.cookie('_g'));
total = parseInt(info._nac, 10) + parseInt(info._ac, 10);
... ... @@ -538,7 +542,8 @@ if (isSupportCss3Animation()) {
syncPageChannel();
getBannerAndNotice(); // 获取头部banner
formatThirdMenu(); // 格式化三级菜单
setInterval(syncCratInfo, 2000); // 定时同步购物车数量
cartTimer = setInterval(syncCratInfo, 2000); // 定时同步购物车数量
// 获取头部登陆信息
(function() {
... ... @@ -558,7 +563,12 @@ setInterval(syncCratInfo, 2000); // 定时同步购物车数量
$loginBox.show();
}());
fetchUserInfoEvent.add(syncLoginInfo);
fetchUserInfoEvent.add(function() {
if ($('.simple-user-center').length === 0) {
return;
}
syncLoginInfo();
});
$myYohoBox.hover(function() {
var uid = getUid(); // eslint-disable-line
... ... @@ -612,10 +622,10 @@ $searchKey.keyup(function(e) {
} else if (e.which === 13) {
submitSearch();
} else {
val = val.replace(new RegExp('\'', 'gm'), ''); // 去掉特殊字符
$(this).val(val);
searchSuggest(val);
if ($searchSug && $searchSug.length) {
val = val.replace(new RegExp('\'', 'gm'), ''); // 去掉特殊字符
searchSuggest(val);
}
}
}).focus(function() {
var val = $.trim($(this).val());
... ... @@ -636,39 +646,41 @@ $searchKey.keyup(function(e) {
}, 200);
});
$goCart.hover(function() {
var data, _html = '';
if ($miniCart && $miniCart.length) {
$goCart.hover(function() {
var data, _html = '';
if ($goCart.hasClass('on-hover')) {
return;
}
data = $goCart.data();
if (data && data.num * 1) {
_html = '<div class="loading-cart"><h3>加载中,请稍后</h3></div>';
loadCartDetail(data.key);
} else {
_html = '<div class="empty-cart"><h3>您的购物车暂无商品</h3></div>';
}
$miniCart.html(_html);
$goCart.addClass('on-hover');
}, function() {
$goCart.removeClass('on-hover');
});
if ($goCart.hasClass('on-hover')) {
return;
}
$goCart.on('click', '.cart-goods-del', function() {
var $dom = $(this),
data = $dom.data(),
callback;
data = $goCart.data();
if (data && data.num * 1) {
_html = '<div class="loading-cart"><h3>加载中,请稍后</h3></div>';
loadCartDetail(data.key);
} else {
_html = '<div class="empty-cart"><h3>您的购物车暂无商品</h3></div>';
}
$miniCart.html(_html);
$goCart.addClass('on-hover');
}, function() {
$goCart.removeClass('on-hover');
});
if (data) {
callback = function() {
$dom.closest('.goods-item').remove();
};
data.key = $goCart.data().key;
delCartGoods(data, callback);
}
});
$goCart.on('click', '.cart-goods-del', function() {
var $dom = $(this),
data = $dom.data(),
callback;
if (data) {
callback = function() {
$dom.closest('.goods-item').remove();
};
data.key = $goCart.data().key;
delCartGoods(data, callback);
}
});
}
$subNav.on({
mouseenter: function() {
... ...
... ... @@ -167,15 +167,36 @@
z-index: 99;
}
.reco {
.type-icon{
position: absolute;
top: 0;
left: 66px;
height: 32px;
width: 32px;
background: resolve("guang/msg-reco.png");
background: resolve("guang/msg-reco.png") no-repeat;
background-size: 100% 100%;
z-index: 100;
&.collocation {
background: resolve('guang/collocation.png') no-repeat;
}
&.fashion-good {
background: resolve('guang/fashion-good.png') no-repeat;
}
&.fashion-man {
background: resolve('guang/fashion-man.png') no-repeat;
}
&.reco {
background: resolve('guang/msg-reco.png') no-repeat;
}
&.topic {
background: resolve('guang/topic.png') no-repeat;
}
}
.msg-info {
... ...
'use strict';
const _ = require('lodash');
const fp = require('lodash/fp');
const camelCase = global.yoho.camelCase;
const helpers = global.yoho.helpers;
... ... @@ -16,9 +15,6 @@ const itemFromBase = {
saleSpecial: {domain: 'sale', module: 's'}// sale.yohobuy.com
};
// NOTE: 这里修改了图片质量的参数
helpers.image = _.flow(helpers.image, fp.replace(/\/quality\/\d*$/, '/quality/90'));
/**
* 根据性别来决定 默认图片获取字段 如果是 2、3
*
... ...