Too many changes to show.

To preserve performance only 26 of 26+ files are displayed.

# Created by https://www.gitignore.io/api/node,webstorm,netbeans,sublimetext,vim
### Node ###
# Logs
!logs/README.md
logs
*.log
npm-debug.log*
# Runtime data
pids
*.pid
*.seed
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# nyc test coverage
.nyc_output
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# node-waf configuration
.lock-wscript
# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules
jspm_packages
# Optional npm cache directory
.npm
# Optional REPL history
.node_repl_history
### WebStorm ###
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
.idea/
# User-specific stuff:
.idea/workspace.xml
.idea/tasks.xml
.idea/dictionaries
.idea/vcs.xml
.idea/jsLibraryMappings.xml
# Sensitive or high-churn files:
.idea/dataSources.ids
.idea/dataSources.xml
.idea/dataSources.local.xml
.idea/sqlDataSources.xml
.idea/dynamic.xml
.idea/uiDesigner.xml
# Gradle:
.idea/gradle.xml
.idea/libraries
# Mongo Explorer plugin:
.idea/mongoSettings.xml
## File-based project format:
*.iws
## Plugin-specific files:
# IntelliJ
/out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
### WebStorm Patch ###
# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721
# *.iml
# modules.xml
### NetBeans ###
nbproject/
build/
nbbuild/
dist/
nbdist/
nbactions.xml
.nb-gradle/
### SublimeText ###
# cache files for sublime text
*.tmlanguage.cache
*.tmPreferences.cache
*.stTheme.cache
# workspace files are user-specific
*.sublime-workspace
# project files should be checked into the repository, unless a significant
# proportion of contributors will probably not be using SublimeText
# *.sublime-project
# sftp configuration file
sftp-config.json
### Vim ###
# swap
[._]*.s[a-w][a-z]
[._]s[a-w][a-z]
# session
Session.vim
# temporary
.netrwhist
*~
# auto-generated tag files
tags
### YOHO ###
dist
public/css/*
public/bundle/*
.eslintcache
*.log.*
.vscode/
.DS_Store
# Created by https://www.gitignore.io/api/node,webstorm,netbeans,sublimetext,vim
### Node ###
# Logs
!logs/README.md
logs
*.log
npm-debug.log*
# Runtime data
pids
*.pid
*.seed
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# nyc test coverage
.nyc_output
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# node-waf configuration
.lock-wscript
# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules
jspm_packages
# Optional npm cache directory
.npm
# Optional REPL history
.node_repl_history
### WebStorm ###
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
.idea/
# User-specific stuff:
.idea/workspace.xml
.idea/tasks.xml
.idea/dictionaries
.idea/vcs.xml
.idea/jsLibraryMappings.xml
# Sensitive or high-churn files:
.idea/dataSources.ids
.idea/dataSources.xml
.idea/dataSources.local.xml
.idea/sqlDataSources.xml
.idea/dynamic.xml
.idea/uiDesigner.xml
# Gradle:
.idea/gradle.xml
.idea/libraries
# Mongo Explorer plugin:
.idea/mongoSettings.xml
## File-based project format:
*.iws
## Plugin-specific files:
# IntelliJ
/out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
### WebStorm Patch ###
# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721
# *.iml
# modules.xml
### NetBeans ###
nbproject/
build/
nbbuild/
dist/
nbdist/
nbactions.xml
.nb-gradle/
### SublimeText ###
# cache files for sublime text
*.tmlanguage.cache
*.tmPreferences.cache
*.stTheme.cache
# workspace files are user-specific
*.sublime-workspace
# project files should be checked into the repository, unless a significant
# proportion of contributors will probably not be using SublimeText
# *.sublime-project
# sftp configuration file
sftp-config.json
### Vim ###
# swap
[._]*.s[a-w][a-z]
[._]s[a-w][a-z]
# session
Session.vim
# temporary
.netrwhist
*~
# auto-generated tag files
tags
### YOHO ###
dist
public/css/*
public/bundle/*
.eslintcache
*.log.*
.vscode/
.DS_Store
... ...
/**
* girls controller
* @author: 赵彪<bill.zhao@yoho.cn>
* @date: 2016/05/16
*/
'use strict';
const _ = require('lodash');
const channelModel = require('../models/index');
exports.index = (req, res, next) => {
let channelType = req.path.substring(1) || 'boys';
// 将woman转换为girls,以便model层进行处理
channelType === 'woman' ? channelType = 'girls' : null;
channelModel.getContent(channelType).then(data => {
res.render('channel', data);
}).catch(next);
};
exports.getbrandFloorDataAjax = (req, res, next) => {
const channelType = req.query.channelType || 'boys';
channelModel.getbrandFloorDataAjax(channelType).then(data => {
res.json(data);
}).catch(next);
};
exports.getNewArrival = (req, res, next) => {
let reqBody = req.body,
pageIndex = reqBody.pageIndex,
pageCount = reqBody.pageCount,
channel = reqBody.type,
goods = [],
result = {};
if (pageIndex < 0) {
pageIndex = 0;
}
if (pageCount < 0 || pageCount > 50) {
pageCount = 20;
}
channelModel.getNewArrival(channel).then(data => {
goods = _.slice(data, pageIndex, pageIndex + pageCount);
if (goods.length !== 0) {
result = {
code: 200,
goods: goods
};
}
res.send(result);
}).catch(next);
};
exports.getIndexGuide = (req, res,next) => {
channelModel.getIndexGuideData().then(data => {
console.log(data);
if(data.code !== 200){
const err = new Error('异常');
throw err;
}
return channelModel.formatIndexGuideData(data.data);
}).then(data => {
data.layout = false;
//console.log('-----');
//console.log(data);
res.render('guide', {list: data});
}).catch(next);
}
/**
* girls controller
* @author: 赵彪<bill.zhao@yoho.cn>
* @date: 2016/05/16
*/
'use strict';
const _ = require('lodash');
const channelModel = require('../models/index');
exports.index = (req, res, next) => {
let channelType = req.path.substring(1) || 'boys';
// 将woman转换为girls,以便model层进行处理
channelType === 'woman' ? channelType = 'girls' : null;
channelModel.getContent(channelType).then(data => {
res.render('channel', data);
}).catch(next);
};
exports.getbrandFloorDataAjax = (req, res, next) => {
const channelType = req.query.channelType || 'boys';
channelModel.getbrandFloorDataAjax(channelType).then(data => {
res.json(data);
}).catch(next);
};
exports.getNewArrival = (req, res, next) => {
let reqBody = req.body,
pageIndex = reqBody.pageIndex,
pageCount = reqBody.pageCount,
channel = reqBody.type,
goods = [],
result = {};
if (pageIndex < 0) {
pageIndex = 0;
}
if (pageCount < 0 || pageCount > 50) {
pageCount = 20;
}
channelModel.getNewArrival(channel).then(data => {
goods = _.slice(data, pageIndex, pageIndex + pageCount);
if (goods.length !== 0) {
result = {
code: 200,
goods: goods
};
}
res.send(result);
}).catch(next);
};
exports.getIndexGuide = (req, res,next) => {
channelModel.getIndexGuideData().then(data => {
console.log(data);
if(data.code !== 200){
const err = new Error('异常');
throw err;
}
return channelModel.formatIndexGuideData(data.data);
}).then(data => {
data.layout = false;
//console.log('-----');
//console.log(data);
res.render('guide', {list: data});
}).catch(next);
}
... ...
/**
* sub app girls
* @author: biao<bill.zhao@yoho.cn>
* @date: 2016/05/16
*/
var express = require('express'),
path = require('path'),
hbs = require('express-handlebars');
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({
extname: '.hbs',
defaultLayout: 'layout',
layoutsDir: doraemon,
partialsDir: [`${partials}/partial`, `${doraemon}/partial`],
helpers: global.yoho.helpers
}));
// router
app.use(require('./router'));
module.exports = app;
/**
* sub app girls
* @author: biao<bill.zhao@yoho.cn>
* @date: 2016/05/16
*/
var express = require('express'),
path = require('path'),
hbs = require('express-handlebars');
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({
extname: '.hbs',
defaultLayout: 'layout',
layoutsDir: doraemon,
partialsDir: [`${partials}/partial`, `${doraemon}/partial`],
helpers: global.yoho.helpers
}));
// router
app.use(require('./router'));
module.exports = app;
... ...
/**
* 频道页 model
* @author: 赵彪<bill.zhao@yoho.cn>
* @date: 2016/05/17
*/
'use strict';
const _ = require('lodash');
const dataMap = require('../../../config/data-map');
const helpers = global.yoho.helpers;
const log = global.yoho.logger;
const processProduct = require(`${global.utils}/product-process`).processProduct;
const serviceApi = global.yoho.ServiceAPI;
const searchApi = global.yoho.SearchAPI;
const headerModel = require('../../../doraemon/models/header');
// 获取上线时间
const _getShelveTime = duration => {
let today = new Date(),
todayMil = today.getTime().toString().substr(0, 10),
startDayMil = (today.setMonth(today.getMonth() - duration)).toString().substr(0, 10);
return `${startDayMil},${todayMil}`; // `返回时间
};
// 获取可用的标题
const _getText = data => {
let text = data.split(' ')[0];
const regResult = /\w+/.exec(text);
if (data === 'GIRL KIDS' || data === 'BOY KIDS') {
return data;
}
if (regResult) {
text = text.replace(regResult[0], '');
}
return text;
};
const channelMap = dataMap.channel;
const sortMap = dataMap.sort;
// 构建url
const _httpBuildQuery = data => {
return searchApi.get('/search.json', data);
};
/**
* 获取带小图的banner
* @param {[Object]} data 原始数据
* @return {[Object]} 转换后的数据
*/
const _getDebrisSlide = data => {
let floorData = {
debrisSlider: {
left: [],
center: [],
right: []
}
};
_.mapKeys(data, (value, key) => {
_.forEach(value, slideData => {
floorData.debrisSlider[key].push(slideData);
});
});
return floorData;
};
/**
* 获取广告位
* @param {Object} data 原始数据
* @return {Object} 转换后的数据
*/
const _getadbannerData = data => {
return {
adbanner: data
};
};
/**
* 生成banner模板数据
* @param {Object} srcData 原始数据
* @return {Object} 转换后的数据
*/
const _getSlideData = srcData => {
const slideData = {
slide: {
list: [],
pagination: []
}
};
if (srcData.big_image) {
slideData.slide.list = srcData.big_image;
}
if (srcData.list) {
slideData.slide.pagination = srcData.list;
}
if (_.isArray(srcData)) {
slideData.slide.list = srcData;
}
return slideData;
};
/**
* 获取最新速报模板数据
* @param {Object} srcData 原始数据
* @return {Object} 转换后的数据
*/
const _getNewReportFloorData = args => {
const title = args[0].data.text;
let item = args[1].data;
let secondItem = args[2].data;
let thirdItem = args[3].data;
let forthItem = args[4];
let list = [];
const data = {
newReport: {
name: title,
list: []
}
};
let adData;
let floorDatas = [];
list.push(item[0]);
_.forEach(secondItem, (floorData) => {
list.push(floorData);
});
list.push(thirdItem[0]);
data.newReport.list = list;
floorDatas.push(data);
if (forthItem.template_name === 'single_image') {
adData = _getadbannerData(forthItem.data[0]);
floorDatas.push(adData);
}
return floorDatas;
};
/**
* 给目标对象绑定频道属性
* @param {Object} obj 需要绑定频道属性的对象
* @param {String} type 需要设置的频道类型
* @return undefined
*/
const _setChannelType = (obj, type) => {
obj[type + 'Channel'] = true;
};
/**
* 获取优选品牌模板数据
* @param {[Object]} args 参数列表
* @param {String} type 频道类型
* @return {Object}
*/
const _getPreBrandTopData = (args, type) => {
const title = args[0].data.text;
let item = args[1].data;
const data = {
preferenceBrands: {
name: title,
imgBrand: [],
brandUrl: '/getbrandFloorDataAjax?channelType=' + type
}
};
data.preferenceBrands.imgBrand = item;
_setChannelType(data.preferenceBrands, type);
return data;
};
/**
* 获取热门分类模板数据
* @param {[Object]} args 参数列表
* @param {String} type 频道类型
* @return {Object}
*/
const _getHotGoodsFloorData = (args, type) => {
let item = args[0];
let nextItem = args[1];
let list = [];
let object = {},
keyword = [],
category = [],
brands = [],
types = [],
products = [];
const data = {
recommend: {
tplrecommend: []
}
};
category = item.data.menuNav.list;
keyword = item.data.menuNav.blocks;
_.forEach(item.data.imgs, (it, idx) => {
if (idx === 0 || (idx === 4 && type === 'boys')) {
brands.push(it);
} else {
types.push(it);
}
});
products = nextItem.data;
object.name = item.data.name;
object.keyword = keyword;
object.category = category;
object.brands = brands;
object.types = types;
object.navs = item.data.navs.list;
object.products = products;
list.push(object);
data.recommend.tplrecommend = list;
_setChannelType(data.recommend, type);
return data;
};
/**
* 获取boys人气单品模版数据
* @param {[Object]} args 参数列表
* @param {String} type 频道类型
* @return {Object}
*/
const _getBoysSingleHot = (args, type) => {
const len = 10;
const data = {
singlehot: {
name: args[0].data.text,
imgHot: []
}
};
let list = [];
let adData;
let floorDatas = [];
for (let i = 0; i < len; i++) {
let pos = i;
let val = {};
if (i === 1) {
val = args[1].data[0]; // 第二个是大图
} else if (i === len - 1) {
val = args[1].data[1]; // 最后一个是大图
} else {
if (pos > 1) { // 小图
pos = pos - 1;
}
val = args[2].data[pos];
}
list.push(val);
}
data.singlehot.imgHot = list;
_setChannelType(data.singlehot, type);
floorDatas.push(data);
if (args[3].template_name === 'single_image') {
adData = _getadbannerData(args[3].data[0]);
floorDatas.push(adData);
}
return floorDatas;
};
/**
* 获取girls人气单品模版数据
* @param {[Object]} args 参数列表
* @param {String} type 频道类型
* @return {Object}
*/
const _getGirlsSingleHot = args => {
let goods = args[2].data;
let skns = '';
_.forEach(goods, good => {
skns += good.id + ' ';
});
return searchApi.get('/search.json', {
client_type: 'web',
query: skns,
order: 'shelve_time:desc',
status: 1,
sales: 'Y',
attribute_not: '2',
stocknumber: 1,
page: 1,
viewNum: 60
});
};
/**
* 人气单品入口
* @param {[Object]} args 参数列表
* @param {String} type 频道类型
* @return {Object}
*/
const _getSingleHotFloorData = (args, type) => {
if (type === 'boys') {
return _getBoysSingleHot(args, type);
} else {
return _getGirlsSingleHot(args, type);
}
};
/**
* 处理异步获取的人气单品数据
* @param {[Object]} args 参数列表
* @param {Object} queryResult 异步获取的数据
* @param {String} type 频道类型
* @return {Object}
*/
const _getSingehotViaResult = (args, queryResult, type) => {
const data = {
singlehot: {
name: args[0].data.text,
navs: [],
imgHot: [],
brands: []
}
};
if (args[3].template_name === 'app_icon_list') {
data.singlehot.brands = args[3].data;
}
if (queryResult.data) {
_.forEach(queryResult.data.product_list || [], (it, index) => {
const formatData = processProduct(it, {
width: 280,
height: 373
});
if (index > 12) {
return;
}
if (index < 3) {
formatData.tip = 'TOP' + (index + 1);
}
data.singlehot.imgHot.push(formatData);
});
}
data.singlehot.navs = args[1].data;
_setChannelType(data.singlehot, type);
return data;
};
/**
* 异步获取人气单品
* @param {[Object]} rawData 接口返回的原始数据
* @param {[Object]} floorData 已经经过处理的楼层数据
* @param {Object} queryResult 接口中用于请求人气单品的数据
* @param {String} title 人气单品楼层的标题
* @param {Type} type 人气单品楼层的类型
* @return {Object}
*/
const _processFloorDataWithQueryReusult = (rawData, queryResult, title, type) => {
let data = {};
_.forEach(rawData, (subData, index) => {
const text = subData.data.text && _getText(subData.data.text);
if (text === title) {
data = _getSingehotViaResult(rawData.slice(index, index + 4), queryResult, type);
}
});
return data;
};
/**
* 组装最新上架楼层数据
*
* @param string data
* return obj
*/
const _getNewGoodsFloorData = args => {
const data = {
newArrivls: {
name: args[0].data.text,
navs: []
}
};
data.newArrivls.navs = args[1].data;
return data;
};
const _getCategoryFloorData = args => {
const data = {
category: {
name: args[0].data.text,
navs: args[1].data,
list: []
}
};
_.forEach(args[2].data, (it, index) => {
// 设置图片大小
if (index === 1) {
it.w = '377;';
it.h = '504;';
} else {
it.w = '185';
it.h = '510';
}
data.category.list.push(it);
});
return data;
};
const _getAccordionFloorData = args => {
let data = {
accordion: {
name: args[0].data.text,
navs: args[1].data,
slide: []
}
};
data.accordion.slide = args[2].data;
return data;
};
const _requestContent = type => {
let data = {
client_type: 'web',
content_code: channelMap[type || 'boys'].code,
gender: channelMap[type || 'boys'].gender,
page: 1,
limit: 1000
};
return serviceApi.get('operations/api/v5/resource/home', data).then(res => {
if (res.code === 200) {
return res;
} else {
log.error('response code of "operations/api/v5/resource/home" 200');
return {};
}
});
};
const floorMap = {
slide: _getSlideData,
hot: _getHotGoodsFloorData,
最新速报: _getNewReportFloorData,
人气单品: _getSingleHotFloorData,
'GIRL KIDS': _getSingleHotFloorData,
'BOY KIDS': _getSingleHotFloorData,
优选品牌: _getPreBrandTopData,
最新上架: _getNewGoodsFloorData,
ad: _getadbannerData,
category: _getCategoryFloorData,
accordion: _getAccordionFloorData,
debrisSlide: _getDebrisSlide
};
const _processFloorData = (rawData, type) => {
let floorList = [];
let searchPromise = [];
let singlehotFloorIndex = [];
let singlehotFloorTitle = [];
// 定义各种楼层需要用到的接口返回的数组中元素的个数
const bigFloorLength = 5;
const normalFloorLength = 3;
const hotCategoryLength = 2;
_.forEach(rawData, (data, index) => {
let floorData = null;
if (data.template_name === 'recommend_content_three' ||
(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.text) { // 处理一般楼层
let text = _getText(data.data.text);
let lastIndex = index + bigFloorLength < rawData.length ?
index + bigFloorLength : index + (rawData.length - index - 1);
floorData = floorMap[text] &&
floorMap[text].call(null, rawData.slice(index, lastIndex), type);
} else if (data.template_name === 'debrisSlider') { // 处理girls的banner
floorData = floorMap.debrisSlide.call(null, data.data);
}
// 处理lifestyle分类楼层
if (!floorData && index + normalFloorLength < rawData.length &&
rawData[index + 1].template_name === 'textNav' &&
rawData[index + 2].template_name === 'floor') {
floorData = floorMap.category.call(null, rawData.slice(index, index + normalFloorLength));
}
// 处理手风琴楼层
if (!floorData && index + normalFloorLength < rawData.length &&
rawData[index + 1].template_name === 'textNav' &&
rawData[index + 2].template_name === 'focus') {
floorData = floorMap.accordion.call(null, rawData.slice(index, index + normalFloorLength));
}
// 处理promise
if (floorData && floorData.then && typeof floorData.then === 'function') {
searchPromise.push(floorData);
// 记住楼层位置, 以便后面promise获取数据后插入楼层数据
singlehotFloorIndex.push(floorList.length);
// 记住楼层标题, 以便后面promise获取数据后插入楼层数据
singlehotFloorTitle.push(_getText(data.data.text));
} else if (!_.isNil(floorData)) {
_.isArray(floorData) ?
floorList = floorList.concat(floorData) :
floorList.push(floorData);
}
});
return {
floors: floorList,
promise: _.reverse(searchPromise),
singlehotFloorTitle: _.reverse(singlehotFloorTitle),
singlehotFloorIndex: _.reverse(singlehotFloorIndex)
};
};
const _formatResourceParams = (code) => {
return serviceApi.get('operations/api/v5/resource/get', {content_code: code}).then(data => {
let result = data.data[0];
result.channel = channel;
return result;
});
};
/**
* 频道页首次登陆导航并行调接口数据
* @param {Object} data
* @return {Object} formatData
*/
const _formatParams = (channel, data) => {
let params = {};
// 排序数据映射表
let orderMaps = {
's_t_desc': 'shelve_time:desc',
's_t_asc': 'shelve_time:asc',
's_p_asc': 'sales_price:asc',
's_p_desc': 'sales_price:desc',
'p_d_desc': 'discount:desc',
'p_d_asc': 'discount:asc',
'skn_desc': 'product_skn:desc',
'skn_asc': 'product_skn:asc',
'activities_desc': 'activities.order_by:desc',
'activities_asc': 'activities.order_by:asc',
's_n_asc': 'sales_num:asc',
's_n_desc': 'sales_num:desc',
'activities_id_desc': 'activities.activity_id:desc',
'activities_id_asc': 'activities.activity_id:asc',
'brand_desc': 'brand_weight:desc'
};
params.status = 1; // 是否上架,1表示在架,2表示不在
params.sales = 'Y'; // 只搜索销售的产品
params.outlets = 2; // 非奥莱商品
params.stocknumber = 1; // 过滤掉已售罄的商品
params.attribute_not = 2; //过滤掉赠品
if (!data.order) {
params.order = orderMaps.s_t_desc;
} else {
params.order = orderMaps[data.order] ? orderMaps[data.order] : '';
}
if (!data.page) {
params.page = 1;
}
if(data.viewNum) {
params.viewNum = data.viewNum;
} else if (!data.limit) {
params.viewNum = 60;
} else {
params.viewNum = data.limit;
delete data.limit;
}
if (data) {
params = Object.assign(data);
}
return searchApi.get('/search.json', params).then(data => {
let result = data.data;
result.channel = channel;
return result;
});
}
/**
* 格式化频道页首次登陆导航数据
* @param {Object} data
* @return {Object} formatData
*/
const formatIndexGuideData = data => {
let channels = {
'boys': {'gender': '1,3','limit': 1},
'girls': {'gender': '2,3', 'limit': 1},
'lifestyle': {'msort': 10 , 'misort': '266,280,101,103,259', 'limit': 1},
'kids': {'msort': 365, 'limit': 1}
};
console.log('as');
let formatData = [];
let promiseArr = [];
_.forEach(data, item => {
let channel = item.sort_name_en.toLowerCase().replace(' ', '');
formatData.push({
'channel': channel,
'url': item.sort_url,
'sort_name': item.sort_name,
'sort_name_en': item.sort_name_en,
'content_code': item.content_code,
'src': '',
'num': 0
});
if (channels[channel]) {
promiseArr.push(_formatParams(channel, channels[channel]))
}
})
return Promise.all(promiseArr).then(data => {
_.forEach(formatData, (item, index) => {
_.forEach(data, (item, ind) => {
if (formatData[index].channel === data[ind].channel) {
formatData[index].num = data[ind].total;
}
})
})
return formatData;
});
}
/**
* 获取最新上架商品数据
*
* @param string $channel
* @return array
*/
const getNewArrival = channel => {
let rel = [],
sortList = sortMap[channel],
params = {
order: 'shelve_time:desc',
status: 1,
sales: 'Y',
attribute_not: 2,
stocknumber: 3,
shelve_time: _getShelveTime(20)
};
params.gender = channelMap[channel].gender;
_.forEach(sortList, (item) => {
let data = Object.assign(item, params);
rel.push(_httpBuildQuery(data));
});
return Promise.all(rel).then(res => {
let data = [],
result = [];
_.forEach(sortList, (it, index) => {
if (res[index].data.product_list && res[index].data.product_list.length === sortList[index].viewNum) {
data = data.concat(res[index].data.product_list);
}
});
_.forEach(data, (item) => {
result.push(processProduct(item, {
width: 280,
height: 373
}));
});
return result;
});
};
/**
* 获取频道页数据
* @param {String} type 传入频道页类型,值可以是: boys, girls, kids, lifestyle
* @return {Object}
*/
const getContent = type => {
return Promise.all([headerModel.requestHeaderData(type), _requestContent(type)]).then(res => {
let headerData = res[0].data || res[0],
contentData = res[1].data ? res[1].data.list : res[1];
let data = {};
const processResult = _processFloorData(contentData, type);
data = headerData;
data.module = 'channel';
data.page = 'channel';
data.pageType = type;
data.footerTop = true;
data.channel = processResult.floors;
return {
rawData: contentData,
floorData: data,
searchPromise: processResult.promise,
singlehotFloorIndex: processResult.singlehotFloorIndex,
singlehotFloorTitle: processResult.singlehotFloorTitle,
channelType: type
};
}).then(result => {
// 如果有promise则做相应处理
if (result.searchPromise.length) {
return Promise.all(result.searchPromise).then(res => {
_.forEach(res, (data, index) => {
result.floorData.channel
.splice(result.singlehotFloorIndex[index], 0,
_processFloorDataWithQueryReusult(
result.rawData,
data,
result.singlehotFloorTitle[index],
result.channelType
));
});
return result.floorData;
});
} else {
return result.floorData || result;
}
});
};
// 优选品牌楼层floorData-ajax
const getbrandFloorDataAjax = type => {
return _requestContent(type).then(res => {
let contentData = res.data ? res.data.list : [];
let data = {
logoBrand: [],
moreBrand: ''
};
_.forEach(contentData, (d, index) => {
if (d.data.text && d.data.text.indexOf('优选品牌') >= 0) {
_.forEach(contentData[index + 2].data, (floorData) => {
let o = {};
o.href = floorData.url;
o.img = helpers.image(floorData.src, 185, 86, 2);
data.logoBrand.push(o);
});
data.moreBrand = contentData[index + 3].data[0].url;
}
});
return data;
});
};
exports.getResourceData = (formatData) => {
let promiseArr = [];
_.forEach(data, item => {
if (item.content_code) {
promiseArr.push(_formatResourceParams(content_code))
}
return Promise.all(promiseArr).then(data => {
//console.log(formatData);
_.forEach(formatData, (item, index) => {
_.forEach(data, (item, ind) => {
if (formatData[index].channel === data[ind].channel) {
formatData[index].src = data[ind].src;
}
})
})
console.log(formatData);
return formatData;
})
})
}
/**
* 获取频道页首次登陆导航数据
* @param {String} type 传入频道页类型,值可以是: boys, girls, kids, lifestyle
* @return {Object}
*/
const getIndexGuideData = () => {
let params = {
client_type: 'web',
private_key: '0ed29744ed318fd28d2c07985d3ba633'
};
return serviceApi.get('operations/api/v6/category/getCategory', params);
}
module.exports = {
getNewArrival: getNewArrival,
getContent: getContent,
getbrandFloorDataAjax: getbrandFloorDataAjax,
getIndexGuideData: getIndexGuideData,
formatIndexGuideData: formatIndexGuideData
};
/**
* 频道页 model
* @author: 赵彪<bill.zhao@yoho.cn>
* @date: 2016/05/17
*/
'use strict';
const _ = require('lodash');
const dataMap = require('../../../config/data-map');
const helpers = global.yoho.helpers;
const log = global.yoho.logger;
const processProduct = require(`${global.utils}/product-process`).processProduct;
const serviceApi = global.yoho.ServiceAPI;
const searchApi = global.yoho.SearchAPI;
const headerModel = require('../../../doraemon/models/header');
// 获取上线时间
const _getShelveTime = duration => {
let today = new Date(),
todayMil = today.getTime().toString().substr(0, 10),
startDayMil = (today.setMonth(today.getMonth() - duration)).toString().substr(0, 10);
return `${startDayMil},${todayMil}`; // `返回时间
};
// 获取可用的标题
const _getText = data => {
let text = data.split(' ')[0];
const regResult = /\w+/.exec(text);
if (data === 'GIRL KIDS' || data === 'BOY KIDS') {
return data;
}
if (regResult) {
text = text.replace(regResult[0], '');
}
return text;
};
const channelMap = dataMap.channel;
const sortMap = dataMap.sort;
// 构建url
const _httpBuildQuery = data => {
return searchApi.get('/search.json', data);
};
/**
* 获取带小图的banner
* @param {[Object]} data 原始数据
* @return {[Object]} 转换后的数据
*/
const _getDebrisSlide = data => {
let floorData = {
debrisSlider: {
left: [],
center: [],
right: []
}
};
_.mapKeys(data, (value, key) => {
_.forEach(value, slideData => {
floorData.debrisSlider[key].push(slideData);
});
});
return floorData;
};
/**
* 获取广告位
* @param {Object} data 原始数据
* @return {Object} 转换后的数据
*/
const _getadbannerData = data => {
return {
adbanner: data
};
};
/**
* 生成banner模板数据
* @param {Object} srcData 原始数据
* @return {Object} 转换后的数据
*/
const _getSlideData = srcData => {
const slideData = {
slide: {
list: [],
pagination: []
}
};
if (srcData.big_image) {
slideData.slide.list = srcData.big_image;
}
if (srcData.list) {
slideData.slide.pagination = srcData.list;
}
if (_.isArray(srcData)) {
slideData.slide.list = srcData;
}
return slideData;
};
/**
* 获取最新速报模板数据
* @param {Object} srcData 原始数据
* @return {Object} 转换后的数据
*/
const _getNewReportFloorData = args => {
const title = args[0].data.text;
let item = args[1].data;
let secondItem = args[2].data;
let thirdItem = args[3].data;
let forthItem = args[4];
let list = [];
const data = {
newReport: {
name: title,
list: []
}
};
let adData;
let floorDatas = [];
list.push(item[0]);
_.forEach(secondItem, (floorData) => {
list.push(floorData);
});
list.push(thirdItem[0]);
data.newReport.list = list;
floorDatas.push(data);
if (forthItem.template_name === 'single_image') {
adData = _getadbannerData(forthItem.data[0]);
floorDatas.push(adData);
}
return floorDatas;
};
/**
* 给目标对象绑定频道属性
* @param {Object} obj 需要绑定频道属性的对象
* @param {String} type 需要设置的频道类型
* @return undefined
*/
const _setChannelType = (obj, type) => {
obj[type + 'Channel'] = true;
};
/**
* 获取优选品牌模板数据
* @param {[Object]} args 参数列表
* @param {String} type 频道类型
* @return {Object}
*/
const _getPreBrandTopData = (args, type) => {
const title = args[0].data.text;
let item = args[1].data;
const data = {
preferenceBrands: {
name: title,
imgBrand: [],
brandUrl: '/getbrandFloorDataAjax?channelType=' + type
}
};
data.preferenceBrands.imgBrand = item;
_setChannelType(data.preferenceBrands, type);
return data;
};
/**
* 获取热门分类模板数据
* @param {[Object]} args 参数列表
* @param {String} type 频道类型
* @return {Object}
*/
const _getHotGoodsFloorData = (args, type) => {
let item = args[0];
let nextItem = args[1];
let list = [];
let object = {},
keyword = [],
category = [],
brands = [],
types = [],
products = [];
const data = {
recommend: {
tplrecommend: []
}
};
category = item.data.menuNav.list;
keyword = item.data.menuNav.blocks;
_.forEach(item.data.imgs, (it, idx) => {
if (idx === 0 || (idx === 4 && type === 'boys')) {
brands.push(it);
} else {
types.push(it);
}
});
products = nextItem.data;
object.name = item.data.name;
object.keyword = keyword;
object.category = category;
object.brands = brands;
object.types = types;
object.navs = item.data.navs.list;
object.products = products;
list.push(object);
data.recommend.tplrecommend = list;
_setChannelType(data.recommend, type);
return data;
};
/**
* 获取boys人气单品模版数据
* @param {[Object]} args 参数列表
* @param {String} type 频道类型
* @return {Object}
*/
const _getBoysSingleHot = (args, type) => {
const len = 10;
const data = {
singlehot: {
name: args[0].data.text,
imgHot: []
}
};
let list = [];
let adData;
let floorDatas = [];
for (let i = 0; i < len; i++) {
let pos = i;
let val = {};
if (i === 1) {
val = args[1].data[0]; // 第二个是大图
} else if (i === len - 1) {
val = args[1].data[1]; // 最后一个是大图
} else {
if (pos > 1) { // 小图
pos = pos - 1;
}
val = args[2].data[pos];
}
list.push(val);
}
data.singlehot.imgHot = list;
_setChannelType(data.singlehot, type);
floorDatas.push(data);
if (args[3].template_name === 'single_image') {
adData = _getadbannerData(args[3].data[0]);
floorDatas.push(adData);
}
return floorDatas;
};
/**
* 获取girls人气单品模版数据
* @param {[Object]} args 参数列表
* @param {String} type 频道类型
* @return {Object}
*/
const _getGirlsSingleHot = args => {
let goods = args[2].data;
let skns = '';
_.forEach(goods, good => {
skns += good.id + ' ';
});
return searchApi.get('/search.json', {
client_type: 'web',
query: skns,
order: 'shelve_time:desc',
status: 1,
sales: 'Y',
attribute_not: '2',
stocknumber: 1,
page: 1,
viewNum: 60
});
};
/**
* 人气单品入口
* @param {[Object]} args 参数列表
* @param {String} type 频道类型
* @return {Object}
*/
const _getSingleHotFloorData = (args, type) => {
if (type === 'boys') {
return _getBoysSingleHot(args, type);
} else {
return _getGirlsSingleHot(args, type);
}
};
/**
* 处理异步获取的人气单品数据
* @param {[Object]} args 参数列表
* @param {Object} queryResult 异步获取的数据
* @param {String} type 频道类型
* @return {Object}
*/
const _getSingehotViaResult = (args, queryResult, type) => {
const data = {
singlehot: {
name: args[0].data.text,
navs: [],
imgHot: [],
brands: []
}
};
if (args[3].template_name === 'app_icon_list') {
data.singlehot.brands = args[3].data;
}
if (queryResult.data) {
_.forEach(queryResult.data.product_list || [], (it, index) => {
const formatData = processProduct(it, {
width: 280,
height: 373
});
if (index > 12) {
return;
}
if (index < 3) {
formatData.tip = 'TOP' + (index + 1);
}
data.singlehot.imgHot.push(formatData);
});
}
data.singlehot.navs = args[1].data;
_setChannelType(data.singlehot, type);
return data;
};
/**
* 异步获取人气单品
* @param {[Object]} rawData 接口返回的原始数据
* @param {[Object]} floorData 已经经过处理的楼层数据
* @param {Object} queryResult 接口中用于请求人气单品的数据
* @param {String} title 人气单品楼层的标题
* @param {Type} type 人气单品楼层的类型
* @return {Object}
*/
const _processFloorDataWithQueryReusult = (rawData, queryResult, title, type) => {
let data = {};
_.forEach(rawData, (subData, index) => {
const text = subData.data.text && _getText(subData.data.text);
if (text === title) {
data = _getSingehotViaResult(rawData.slice(index, index + 4), queryResult, type);
}
});
return data;
};
/**
* 组装最新上架楼层数据
*
* @param string data
* return obj
*/
const _getNewGoodsFloorData = args => {
const data = {
newArrivls: {
name: args[0].data.text,
navs: []
}
};
data.newArrivls.navs = args[1].data;
return data;
};
const _getCategoryFloorData = args => {
const data = {
category: {
name: args[0].data.text,
navs: args[1].data,
list: []
}
};
_.forEach(args[2].data, (it, index) => {
// 设置图片大小
if (index === 1) {
it.w = '377;';
it.h = '504;';
} else {
it.w = '185';
it.h = '510';
}
data.category.list.push(it);
});
return data;
};
const _getAccordionFloorData = args => {
let data = {
accordion: {
name: args[0].data.text,
navs: args[1].data,
slide: []
}
};
data.accordion.slide = args[2].data;
return data;
};
const _requestContent = type => {
let data = {
client_type: 'web',
content_code: channelMap[type || 'boys'].code,
gender: channelMap[type || 'boys'].gender,
page: 1,
limit: 1000
};
return serviceApi.get('operations/api/v5/resource/home', data).then(res => {
if (res.code === 200) {
return res;
} else {
log.error('response code of "operations/api/v5/resource/home" 200');
return {};
}
});
};
const floorMap = {
slide: _getSlideData,
hot: _getHotGoodsFloorData,
最新速报: _getNewReportFloorData,
人气单品: _getSingleHotFloorData,
'GIRL KIDS': _getSingleHotFloorData,
'BOY KIDS': _getSingleHotFloorData,
优选品牌: _getPreBrandTopData,
最新上架: _getNewGoodsFloorData,
ad: _getadbannerData,
category: _getCategoryFloorData,
accordion: _getAccordionFloorData,
debrisSlide: _getDebrisSlide
};
const _processFloorData = (rawData, type) => {
let floorList = [];
let searchPromise = [];
let singlehotFloorIndex = [];
let singlehotFloorTitle = [];
// 定义各种楼层需要用到的接口返回的数组中元素的个数
const bigFloorLength = 5;
const normalFloorLength = 3;
const hotCategoryLength = 2;
_.forEach(rawData, (data, index) => {
let floorData = null;
if (data.template_name === 'recommend_content_three' ||
(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.text) { // 处理一般楼层
let text = _getText(data.data.text);
let lastIndex = index + bigFloorLength < rawData.length ?
index + bigFloorLength : index + (rawData.length - index - 1);
floorData = floorMap[text] &&
floorMap[text].call(null, rawData.slice(index, lastIndex), type);
} else if (data.template_name === 'debrisSlider') { // 处理girls的banner
floorData = floorMap.debrisSlide.call(null, data.data);
}
// 处理lifestyle分类楼层
if (!floorData && index + normalFloorLength < rawData.length &&
rawData[index + 1].template_name === 'textNav' &&
rawData[index + 2].template_name === 'floor') {
floorData = floorMap.category.call(null, rawData.slice(index, index + normalFloorLength));
}
// 处理手风琴楼层
if (!floorData && index + normalFloorLength < rawData.length &&
rawData[index + 1].template_name === 'textNav' &&
rawData[index + 2].template_name === 'focus') {
floorData = floorMap.accordion.call(null, rawData.slice(index, index + normalFloorLength));
}
// 处理promise
if (floorData && floorData.then && typeof floorData.then === 'function') {
searchPromise.push(floorData);
// 记住楼层位置, 以便后面promise获取数据后插入楼层数据
singlehotFloorIndex.push(floorList.length);
// 记住楼层标题, 以便后面promise获取数据后插入楼层数据
singlehotFloorTitle.push(_getText(data.data.text));
} else if (!_.isNil(floorData)) {
_.isArray(floorData) ?
floorList = floorList.concat(floorData) :
floorList.push(floorData);
}
});
return {
floors: floorList,
promise: _.reverse(searchPromise),
singlehotFloorTitle: _.reverse(singlehotFloorTitle),
singlehotFloorIndex: _.reverse(singlehotFloorIndex)
};
};
const _formatResourceParams = (code) => {
return serviceApi.get('operations/api/v5/resource/get', {content_code: code}).then(data => {
let result = data.data[0];
result.channel = channel;
return result;
});
};
/**
* 频道页首次登陆导航并行调接口数据
* @param {Object} data
* @return {Object} formatData
*/
const _formatParams = (channel, data) => {
let params = {};
// 排序数据映射表
let orderMaps = {
's_t_desc': 'shelve_time:desc',
's_t_asc': 'shelve_time:asc',
's_p_asc': 'sales_price:asc',
's_p_desc': 'sales_price:desc',
'p_d_desc': 'discount:desc',
'p_d_asc': 'discount:asc',
'skn_desc': 'product_skn:desc',
'skn_asc': 'product_skn:asc',
'activities_desc': 'activities.order_by:desc',
'activities_asc': 'activities.order_by:asc',
's_n_asc': 'sales_num:asc',
's_n_desc': 'sales_num:desc',
'activities_id_desc': 'activities.activity_id:desc',
'activities_id_asc': 'activities.activity_id:asc',
'brand_desc': 'brand_weight:desc'
};
params.status = 1; // 是否上架,1表示在架,2表示不在
params.sales = 'Y'; // 只搜索销售的产品
params.outlets = 2; // 非奥莱商品
params.stocknumber = 1; // 过滤掉已售罄的商品
params.attribute_not = 2; //过滤掉赠品
if (!data.order) {
params.order = orderMaps.s_t_desc;
} else {
params.order = orderMaps[data.order] ? orderMaps[data.order] : '';
}
if (!data.page) {
params.page = 1;
}
if(data.viewNum) {
params.viewNum = data.viewNum;
} else if (!data.limit) {
params.viewNum = 60;
} else {
params.viewNum = data.limit;
delete data.limit;
}
if (data) {
params = Object.assign(data);
}
return searchApi.get('/search.json', params).then(data => {
let result = data.data;
result.channel = channel;
return result;
});
}
/**
* 格式化频道页首次登陆导航数据
* @param {Object} data
* @return {Object} formatData
*/
const formatIndexGuideData = data => {
let channels = {
'boys': {'gender': '1,3','limit': 1},
'girls': {'gender': '2,3', 'limit': 1},
'lifestyle': {'msort': 10 , 'misort': '266,280,101,103,259', 'limit': 1},
'kids': {'msort': 365, 'limit': 1}
};
console.log('as');
let formatData = [];
let promiseArr = [];
_.forEach(data, item => {
let channel = item.sort_name_en.toLowerCase().replace(' ', '');
formatData.push({
'channel': channel,
'url': item.sort_url,
'sort_name': item.sort_name,
'sort_name_en': item.sort_name_en,
'content_code': item.content_code,
'src': '',
'num': 0
});
if (channels[channel]) {
promiseArr.push(_formatParams(channel, channels[channel]))
}
})
return Promise.all(promiseArr).then(data => {
_.forEach(formatData, (item, index) => {
_.forEach(data, (item, ind) => {
if (formatData[index].channel === data[ind].channel) {
formatData[index].num = data[ind].total;
}
})
})
return formatData;
});
}
/**
* 获取最新上架商品数据
*
* @param string $channel
* @return array
*/
const getNewArrival = channel => {
let rel = [],
sortList = sortMap[channel],
params = {
order: 'shelve_time:desc',
status: 1,
sales: 'Y',
attribute_not: 2,
stocknumber: 3,
shelve_time: _getShelveTime(20)
};
params.gender = channelMap[channel].gender;
_.forEach(sortList, (item) => {
let data = Object.assign(item, params);
rel.push(_httpBuildQuery(data));
});
return Promise.all(rel).then(res => {
let data = [],
result = [];
_.forEach(sortList, (it, index) => {
if (res[index].data.product_list && res[index].data.product_list.length === sortList[index].viewNum) {
data = data.concat(res[index].data.product_list);
}
});
_.forEach(data, (item) => {
result.push(processProduct(item, {
width: 280,
height: 373
}));
});
return result;
});
};
/**
* 获取频道页数据
* @param {String} type 传入频道页类型,值可以是: boys, girls, kids, lifestyle
* @return {Object}
*/
const getContent = type => {
return Promise.all([headerModel.requestHeaderData(type), _requestContent(type)]).then(res => {
let headerData = res[0].data || res[0],
contentData = res[1].data ? res[1].data.list : res[1];
let data = {};
const processResult = _processFloorData(contentData, type);
data = headerData;
data.module = 'channel';
data.page = 'channel';
data.pageType = type;
data.footerTop = true;
data.channel = processResult.floors;
return {
rawData: contentData,
floorData: data,
searchPromise: processResult.promise,
singlehotFloorIndex: processResult.singlehotFloorIndex,
singlehotFloorTitle: processResult.singlehotFloorTitle,
channelType: type
};
}).then(result => {
// 如果有promise则做相应处理
if (result.searchPromise.length) {
return Promise.all(result.searchPromise).then(res => {
_.forEach(res, (data, index) => {
result.floorData.channel
.splice(result.singlehotFloorIndex[index], 0,
_processFloorDataWithQueryReusult(
result.rawData,
data,
result.singlehotFloorTitle[index],
result.channelType
));
});
return result.floorData;
});
} else {
return result.floorData || result;
}
});
};
// 优选品牌楼层floorData-ajax
const getbrandFloorDataAjax = type => {
return _requestContent(type).then(res => {
let contentData = res.data ? res.data.list : [];
let data = {
logoBrand: [],
moreBrand: ''
};
_.forEach(contentData, (d, index) => {
if (d.data.text && d.data.text.indexOf('优选品牌') >= 0) {
_.forEach(contentData[index + 2].data, (floorData) => {
let o = {};
o.href = floorData.url;
o.img = helpers.image(floorData.src, 185, 86, 2);
data.logoBrand.push(o);
});
data.moreBrand = contentData[index + 3].data[0].url;
}
});
return data;
});
};
exports.getResourceData = (formatData) => {
let promiseArr = [];
_.forEach(data, item => {
if (item.content_code) {
promiseArr.push(_formatResourceParams(content_code))
}
return Promise.all(promiseArr).then(data => {
//console.log(formatData);
_.forEach(formatData, (item, index) => {
_.forEach(data, (item, ind) => {
if (formatData[index].channel === data[ind].channel) {
formatData[index].src = data[ind].src;
}
})
})
console.log(formatData);
return formatData;
})
})
}
/**
* 获取频道页首次登陆导航数据
* @param {String} type 传入频道页类型,值可以是: boys, girls, kids, lifestyle
* @return {Object}
*/
const getIndexGuideData = () => {
let params = {
client_type: 'web',
private_key: '0ed29744ed318fd28d2c07985d3ba633'
};
return serviceApi.get('operations/api/v6/category/getCategory', params);
}
module.exports = {
getNewArrival: getNewArrival,
getContent: getContent,
getbrandFloorDataAjax: getbrandFloorDataAjax,
getIndexGuideData: getIndexGuideData,
formatIndexGuideData: formatIndexGuideData
};
... ...
/**
* router of sub app girls
* @author: biao<bill.zhao@yoho.cn>
* @date: 2016/05/16
*/
'use strict';
const router = require('express').Router(); // eslint-disable-line
const cRoot = './controllers';
// Your controller here
const channelController = require(`${cRoot}/index`);
// 频道页路由
router.get('/', channelController.index);
router.get('/woman', channelController.index);
router.get('/kids', channelController.index);
router.get('/lifestyle', channelController.index);
// ajax
router.get('/getbrandFloorDataAjax', channelController.getbrandFloorDataAjax);
router.post('/common/getNewArrival', channelController.getNewArrival);
router.get('/guide', channelController.getIndexGuide);
module.exports = router;
/**
* router of sub app girls
* @author: biao<bill.zhao@yoho.cn>
* @date: 2016/05/16
*/
'use strict';
const router = require('express').Router(); // eslint-disable-line
const cRoot = './controllers';
// Your controller here
const channelController = require(`${cRoot}/index`);
// 频道页路由
router.get('/', channelController.index);
router.get('/woman', channelController.index);
router.get('/kids', channelController.index);
router.get('/lifestyle', channelController.index);
// ajax
router.get('/getbrandFloorDataAjax', channelController.getbrandFloorDataAjax);
router.post('/common/getNewArrival', channelController.getNewArrival);
router.get('/guide', channelController.getIndexGuide);
module.exports = router;
... ...
<div class="con"></div>
<div class="guide-box" spm-name="homepage_guide" style="top: 255.5px;">
<a class="close" href="javascript:void(0)">x</a>
<ul class="clear">
{{#list}}
<li class="{{channel}}" >
<dl>
<dt class="tag_img_warpper">
<a href="{{url}}" target="_self">
<img spm-name="homepage_guide_manimg" alt="YOHO!BOYS" src="{{src}}"></a>
</dt>
<dd class="block_cn">{{sort_name}}</dd>
<dd class="block_en"> <b>{{sort_name_en}}</b>
</dd>
<dd class="block_line">
</dd>
<dd class="goods-num"> <b>{{num}}+ Items.</b>
</dd>
<dd>
<a class="go" href="{{url}}">
Enter
<span class="ifont">&gt;</span>
</a>
</dd>
</dl>
</li>
{{/list}}
</ul>
</div>
<div class="con"></div>
<div class="guide-box" spm-name="homepage_guide" style="top: 255.5px;">
<a class="close" href="javascript:void(0)">x</a>
<ul class="clear">
{{#list}}
<li class="{{channel}}" >
<dl>
<dt class="tag_img_warpper">
<a href="{{url}}" target="_self">
<img spm-name="homepage_guide_manimg" alt="YOHO!BOYS" src="{{src}}"></a>
</dt>
<dd class="block_cn">{{sort_name}}</dd>
<dd class="block_en"> <b>{{sort_name_en}}</b>
</dd>
<dd class="block_line">
</dd>
<dd class="goods-num"> <b>{{num}}+ Items.</b>
</dd>
<dd>
<a class="go" href="{{url}}">
Enter
<span class="ifont">&gt;</span>
</a>
</dd>
</dl>
</li>
{{/list}}
</ul>
</div>
... ...
<div class="floor-ad">
<a href="{{url}}" target= "_blank"><img class="lazy" data-original="{{image src 1150 129}}"/></a>
</div>
<div class="floor-ad">
<a href="{{url}}" target= "_blank"><img class="lazy" data-original="{{image src 1150 129}}"/></a>
</div>
... ...
<div class="debris-slider clearfix">
<div class="left-col col">
{{# left}}
<a href="{{url}}" target="_blank">
<img class="lazy" data-original="{{image img 200 265}}">
</a>
{{/ left}}
</div>
<div class="center-col col">
<ul class="slide-wrapper">
{{# center}}
<li>
<a href="{{url}}" target="_blank">
<img class="lazy" data-original="{{image img 570 633}}">
</a>
</li>
{{/ center}}
</ul>
<div class="slide-switch">
<a class="prev" href="javascript:;">
<span class="iconfont">&#xe609;</span>
</a>
<a class="next" href="javascript:;">
<span class="iconfont">&#xe608;</span>
</a>
</div>
</div>
<div class="right-col col">
{{# right}}
<a href="{{url}}" target="_blank">
<img class="lazy" data-original="{{image img 200 265}}">
</a>
{{/ right}}
</div>
</div>
<div class="debris-slider clearfix">
<div class="left-col col">
{{# left}}
<a href="{{url}}" target="_blank">
<img class="lazy" data-original="{{image img 200 265}}">
</a>
{{/ left}}
</div>
<div class="center-col col">
<ul class="slide-wrapper">
{{# center}}
<li>
<a href="{{url}}" target="_blank">
<img class="lazy" data-original="{{image img 570 633}}">
</a>
</li>
{{/ center}}
</ul>
<div class="slide-switch">
<a class="prev" href="javascript:;">
<span class="iconfont">&#xe609;</span>
</a>
<a class="next" href="javascript:;">
<span class="iconfont">&#xe608;</span>
</a>
</div>
</div>
<div class="right-col col">
{{# right}}
<a href="{{url}}" target="_blank">
<img class="lazy" data-original="{{image img 200 265}}">
</a>
{{/ right}}
</div>
</div>
... ...
<div class="preference-brand">
<div class="img-brand">
<ul class="img-list imgopacity clearfix">
{{# imgBrand}}
<li class="img-item">
<a href="{{url}}" target= "_blank">
<img src="{{image src 378 175}}" alt="">
</a>
</li>
{{/ imgBrand}}
</ul>
<div class="img-brand-switch">
<a class="prev" href="javascript:;">
<span class="iconfont">&#xe609;</span>
</a>
<a class="next" href="javascript:;">
<span class="iconfont">&#xe608;</span>
</a>
</div>
</div>
<div class="logo-brand imgopacity" data-url="{{brandUrl}}"></div>
</div>
<div class="preference-brand">
<div class="img-brand">
<ul class="img-list imgopacity clearfix">
{{# imgBrand}}
<li class="img-item">
<a href="{{url}}" target= "_blank">
<img src="{{image src 378 175}}" alt="">
</a>
</li>
{{/ imgBrand}}
</ul>
<div class="img-brand-switch">
<a class="prev" href="javascript:;">
<span class="iconfont">&#xe609;</span>
</a>
<a class="next" href="javascript:;">
<span class="iconfont">&#xe608;</span>
</a>
</div>
</div>
<div class="logo-brand imgopacity" data-url="{{brandUrl}}"></div>
</div>
... ...
{{# tplrecommend}}
<div class="tpl-recommend clearfix">
{{> common/floor-header}}
<div class="tpl-body clearfix">
<div class="tpl-nav">
<div class="tpl-keywords">
{{#each keyword}}
<a class="keywords{{@index}}" title="{{title}}" href="{{url}}" target= "_blank"><img class="lazy" src="{{image img 185 152}}"/></a>
{{/each}}
</div>
<div class="tpl-category clearfix">
{{#each category}}
<a href="{{url}}" target= "_blank">{{title}}</a>
{{/each}}
</div>
</div>
<div class="tpl-brands imgopacity clearfix">
<ul>
{{#each brands}}
<li><a title="{{title}}" href="{{url}}" target= "_blank"><img class="lazy" src="{{image img 378 248}}"/></a></li>
{{/each}}
</ul>
</div>
<div class="tpl-types imgopacity clearfix">
<ul>
{{#each types}}
<li><a title="{{title}}" href="{{url}}" target= "_blank"><img class="lazy" src="{{image img 185 248}}"/></a></li>
{{/each}}
</ul>
</div>
</div>
<div class="tpl-products imgopacity clearfix">
<ul>
{{#each products}}
<li><a href="{{url}}" title="{{title}}" target= "_blank"><img class="lazy" src="{{image src 222 298}}"/></a></li>
{{/each}}
</ul>
</div>
</div>
{{/ tplrecommend}}
{{# tplrecommend}}
<div class="tpl-recommend clearfix">
{{> common/floor-header}}
<div class="tpl-body clearfix">
<div class="tpl-nav">
<div class="tpl-keywords">
{{#each keyword}}
<a class="keywords{{@index}}" title="{{title}}" href="{{url}}" target= "_blank"><img class="lazy" src="{{image img 185 152}}"/></a>
{{/each}}
</div>
<div class="tpl-category clearfix">
{{#each category}}
<a href="{{url}}" target= "_blank">{{title}}</a>
{{/each}}
</div>
</div>
<div class="tpl-brands imgopacity clearfix">
<ul>
{{#each brands}}
<li><a title="{{title}}" href="{{url}}" target= "_blank"><img class="lazy" src="{{image img 378 248}}"/></a></li>
{{/each}}
</ul>
</div>
<div class="tpl-types imgopacity clearfix">
<ul>
{{#each types}}
<li><a title="{{title}}" href="{{url}}" target= "_blank"><img class="lazy" src="{{image img 185 248}}"/></a></li>
{{/each}}
</ul>
</div>
</div>
<div class="tpl-products imgopacity clearfix">
<ul>
{{#each products}}
<li><a href="{{url}}" title="{{title}}" target= "_blank"><img class="lazy" src="{{image src 222 298}}"/></a></li>
{{/each}}
</ul>
</div>
</div>
{{/ tplrecommend}}
... ...
{{> common/floor-header}}
<div class="categorys-list imgopacity">
<ul class="clearfix">
{{# list}}
<li class="cate-item{{@index}}">
<a href="{{url}}" target= "_blank">
<img class="lazy" data-original="{{image src w h}}" alt="">
</a>
</li>
{{/ list}}
</ul>
</div>
{{> common/floor-header}}
<div class="categorys-list imgopacity">
<ul class="clearfix">
{{# list}}
<li class="cate-item{{@index}}">
<a href="{{url}}" target= "_blank">
<img class="lazy" data-original="{{image src w h}}" alt="">
</a>
</li>
{{/ list}}
</ul>
</div>
... ...
<div class="commodity clearfix" id="newarrivals">
{{> common/floor-header}}
<div class="goods-container clearfix">
</div>
<div class="loading">
<a href="{{url}}" target= "_blank">Loading...</a>
</div>
</div>
<div class="commodity clearfix" id="newarrivals">
{{> common/floor-header}}
<div class="goods-container clearfix">
</div>
<div class="loading">
<a href="{{url}}" target= "_blank">Loading...</a>
</div>
</div>
... ...
<div class="preference-brand imgopacity">
<div class="img-slider-wrapper clearfix" style="background-color:{{sliderColor}};">
<div class="img-brand-switch">
<a class="prev iconfont" href="javascript:;">&#xe609;</a>
<a class="next iconfont" href="javascript:;">&#xe608;</a>
</div>
<div class="img-container-landscape">
<ul class="img-list">
{{# imgBrand}}
<li class="img-item">
<a href="{{url}}" target= "_blank"> <img src="{{image src 320 430}}" alt="{{alt}}"></a>
</li>
{{/ imgBrand}}
</ul>
</div>
</div>
<div class="logo-brand " data-url="{{brandUrl}}">
</div>
</div>
<div class="preference-brand imgopacity">
<div class="img-slider-wrapper clearfix" style="background-color:{{sliderColor}};">
<div class="img-brand-switch">
<a class="prev iconfont" href="javascript:;">&#xe609;</a>
<a class="next iconfont" href="javascript:;">&#xe608;</a>
</div>
<div class="img-container-landscape">
<ul class="img-list">
{{# imgBrand}}
<li class="img-item">
<a href="{{url}}" target= "_blank"> <img src="{{image src 320 430}}" alt="{{alt}}"></a>
</li>
{{/ imgBrand}}
</ul>
</div>
</div>
<div class="logo-brand " data-url="{{brandUrl}}">
</div>
</div>
... ...
{{# tplrecommend}}
<div class="tpl-recommend clearfix">
{{> common/floor-header}}
<div class="tpl-body clearfix">
<div class="tpl-nav">
<div class="tpl-keywords">
{{#each keyword}}
<a class="keywords{{@index}}" title="{{title}}" href="{{url}}" target= "_blank"><img class="lazy" data-original="{{image img 185 76}}"/></a>
{{/each}}
</div>
<div class="tpl-category clearfix">
{{#each category}}
<a href="{{url}}" target= "_blank">{{title}}</a>
{{/each}}
</div>
</div>
<div class="tpl-brands imgopacity clearfix">
{{#each brands}}
<a title="{{title}}" href="{{url}}" target= "_blank"><img class="lazy" data-original="{{image img 377 504}}"/></a>
{{/each}}
</div>
<div class="tpl-types imgopacity clearfix">
<ul>
{{#each types}}
<li><a title="{{title}}" href="{{url}}" target= "_blank"><img class="lazy" data-original="{{image img 185 504}}"/></a></li>
{{/each}}
</ul>
</div>
</div>
</div>
{{/ tplrecommend}}
{{# tplrecommend}}
<div class="tpl-recommend clearfix">
{{> common/floor-header}}
<div class="tpl-body clearfix">
<div class="tpl-nav">
<div class="tpl-keywords">
{{#each keyword}}
<a class="keywords{{@index}}" title="{{title}}" href="{{url}}" target= "_blank"><img class="lazy" data-original="{{image img 185 76}}"/></a>
{{/each}}
</div>
<div class="tpl-category clearfix">
{{#each category}}
<a href="{{url}}" target= "_blank">{{title}}</a>
{{/each}}
</div>
</div>
<div class="tpl-brands imgopacity clearfix">
{{#each brands}}
<a title="{{title}}" href="{{url}}" target= "_blank"><img class="lazy" data-original="{{image img 377 504}}"/></a>
{{/each}}
</div>
<div class="tpl-types imgopacity clearfix">
<ul>
{{#each types}}
<li><a title="{{title}}" href="{{url}}" target= "_blank"><img class="lazy" data-original="{{image img 185 504}}"/></a></li>
{{/each}}
</ul>
</div>
</div>
</div>
{{/ tplrecommend}}
... ...
<div class="new-report imgopacity clearfix">
{{> common/floor-header}}
<ul class="report-list clearfix">
{{# list}}
{{#unless @last}}
<li>
<a href="{{url}}" target= "_blank">
{{#if @first}}
<img class="lazy" data-original="{{image src 377 504}}" alt="" >
{{^}}
<img class="lazy" data-original="{{image src 185 248}}" alt="" >
{{/if}}
</a>
</li>
{{/unless}}
{{/ list}}
</ul>
{{# list}}
{{#if @last}}
<div class="last-item">
<a href="{{url}}" target= "_blank">
<img class="lazy" data-original="{{image src 377 504}}" alt="">
</a>
</div>
{{/if}}
{{/ list}}
</div>
<div class="new-report imgopacity clearfix">
{{> common/floor-header}}
<ul class="report-list clearfix">
{{# list}}
{{#unless @last}}
<li>
<a href="{{url}}" target= "_blank">
{{#if @first}}
<img class="lazy" data-original="{{image src 377 504}}" alt="" >
{{^}}
<img class="lazy" data-original="{{image src 185 248}}" alt="" >
{{/if}}
</a>
</li>
{{/unless}}
{{/ list}}
</ul>
{{# list}}
{{#if @last}}
<div class="last-item">
<a href="{{url}}" target= "_blank">
<img class="lazy" data-original="{{image src 377 504}}" alt="">
</a>
</div>
{{/if}}
{{/ list}}
</div>
... ...
{{> common/floor-header}}
<div class="slide-accordion clearfix">
<ul>
{{#each slide}}
<li><a title="{{title}}" href="{{url}}" target= "_blank"><div class="g-mask"></div><img class="lazy" data-original="{{image src 650 400}}"/></a></li>
{{/each}}
</ul>
</div>
{{> common/floor-header}}
<div class="slide-accordion clearfix">
<ul>
{{#each slide}}
<li><a title="{{title}}" href="{{url}}" target= "_blank"><div class="g-mask"></div><img class="lazy" data-original="{{image src 650 400}}"/></a></li>
{{/each}}
</ul>
</div>
... ...
... ... @@ -10,21 +10,6 @@ const service = require('../models/back-service');
const passportHelper = require('../models/passport-helper');
const _ = require('lodash');
helpers.urlFormat = (url, qs) => {
let localhost = 'http://localhost:6002';
if (_.isEmpty(qs)) {
return localhost + url;
}
const queryString = require('queryString');
let str = queryString.stringify(qs);
return localhost + url + '?' + str;
};
/**
* 找回密码主页面
*/
... ... @@ -92,6 +77,7 @@ const sendCodePage = (req, res, next) => {
service.sendCodeToUserAsync(inputInfo.type, inputInfo.phone, inputInfo.area)
.then(result => {
console.log(result);
if (!(result.code && result.code === 200)) {
return res.redirect(helpers.urlFormat('/passport/back/index'));
... ... @@ -220,15 +206,8 @@ const resetPasswordPage = (req, res, next) => {
.catch(next);
};
/**
* 手机验证页面
*/
const verifyCodeByMobilePage = (req, res, next) => {
req.body.mobile = '15062219934';
req.body.area = '86';
req.body.verifyCode = '8933';
passportHelper.getLeftBannerAsync()
.then(result => {
res.render('back/verification', Object.assign({
... ... @@ -248,7 +227,7 @@ const verifyCodeByMobilePage = (req, res, next) => {
.catch(next);
};
const checkSuccessStatusPage = (req, res, next) => {
const validateSuccessStatusPage = (req, res, next) => {
let successType = req.session.successType || '';
if (!successType) {
... ... @@ -280,18 +259,17 @@ const verifyCodeByMobileAPI = (req, res) => {
let mobile = req.param('mobile', '');
let area = req.param('area', '86');
let mobileCode = req.param('code', '');
// const session = req.session;
const ERR = {
code: 400,
message: '验证码错误!',
data: helpers.urlFormat('/passport/back/index')
};
// if (!code || mobile !== session.mobile || area !== session.area) {
// return res.json(ERR);
// }
const session = req.session;
if (!mobileCode || mobile !== session.mobile || area !== session.area) {
return res.json(ERR);
}
service.verifyCodyByMobileAsync(area, mobile, mobileCode)
.then(result => {
... ... @@ -303,6 +281,7 @@ const verifyCodeByMobileAPI = (req, res) => {
};
const validateExistCodePage = (req, res, next) => {
let code = req.query.code || req.body.code;
if (!code) {
... ... @@ -377,26 +356,34 @@ const validateMobileInSession = (req, res, next) => {
};
module.exports = {
index,
validateInputAPI,
validateUserPage,
getUserInfoAPI,
sendCodePage,
saveInSession,
sendBackMobileAPI,
validateMobileAPI,
validateEmailInSession,
sendEmailPage,
validateCodeByEmailPage,
resetPasswordPage,
verifyCodeByMobilePage,
checkSuccessStatusPage,
resetPwdSuccessPage,
verifyCodeByMobileAPI,
validateExistCodePage,
validateCodeByMobilePage,
validatePwdPage,
updatePwdAPI,
validateMobileInSession
index, // 首页
getUserInfoAPI, // 通过邮箱或手机号获得用户信息
sendCodePage, // 发送验证码到邮箱或者手机,然后跳转页面
saveInSession, // 保存状态到session中
sendEmailPage, // 发送邮件成功的页面
verifyCodeByMobilePage, // 验证手机验证码的页面
verifyCodeByMobileAPI, // 验证手机验证码
sendBackMobileAPI, // 重新发送验证码到手机
resetPasswordPage, // 重设密码页面
updatePwdAPI, // 重设密码接口
validateMobileAPI, // 验证手机号是否合法
resetPwdSuccessPage, // 重设密码成功页面
validateInputAPI, // 验证用户输入的邮箱或者手机是否合法,返回是json
validateUserPage, // 验证用户输入的邮箱或者手机是否合法,跳转是页面
validateEmailInSession, // 验证邮箱是否在session中
validateMobileInSession, // 验证手机是否在session中
validateCodeByEmailPage, // 验证邮箱验证码
validateCodeByMobilePage, // 验证手机验证码
validateSuccessStatusPage, // 验证重设密码状态
validateExistCodePage, // 验证参数是否存在code
validatePwdPage // 验证密码是否合法
};
... ...
... ... @@ -4,7 +4,7 @@
'use strict';
const api = global.yoho.API;
const api = global.yoho.API;
const YOHOBUY_URL = 'http://www.yohobuy.com/';
/**
... ... @@ -39,7 +39,7 @@ const getAreaDataAsync = () => {
const sendCodeToEmailAsync = (email) => {
return api.get('', {
method: 'app.register.backpwdByEmail',
email : email
email: email
});
};
... ... @@ -51,11 +51,11 @@ const sendCodeToEmailAsync = (email) => {
*/
const modifyPasswordByEmailAsync = (pwd, code) => {
const options = {
url : `${YOHOBUY_URL}passport/back/update`,
form : {
pwd : pwd,
url: `${YOHOBUY_URL}passport/back/update`,
form: {
pwd: pwd,
're-input': pwd,
code : code
code: code
},
timeout: 3000
};
... ... @@ -70,11 +70,9 @@ const modifyPasswordByEmailAsync = (pwd, code) => {
* @param integer area 地区码ID
*/
const sendCodeToMobileAsync = (mobile, area) => {
area = area || 86;
return api.get('', {
mobile: mobile,
area : area,
area: area,
method: 'app.register.sendBackpwdCodeToMobile'
});
};
... ... @@ -90,8 +88,8 @@ const validateMobileCodeAsync = (mobile, code, area) => {
area = area || 86;
return api.get('', {
mobile: mobile,
code : code,
area : area,
code: code,
area: area,
method: 'app.register.validBackpwdCode'
});
};
... ... @@ -104,12 +102,11 @@ const validateMobileCodeAsync = (mobile, code, area) => {
* @param integer area 地区码ID
*/
const modifyPasswordByMobileAsync = (mobile, token, newpwd, area)=> {
area = area || 86;
return api.get('', {
mobile: mobile,
token : token,
token: token,
newpwd: newpwd,
area : area,
area: area,
method: 'app.register.changepwdByMobileCode'
});
};
... ... @@ -119,7 +116,7 @@ const modifyPasswordByMobileAsync = (mobile, token, newpwd, area)=> {
*/
const checkEmailCodeAsync = (code) => {
return api.get('', {
code : code,
code: code,
method: 'web.passport.checkCodeValid'
});
};
... ... @@ -129,7 +126,7 @@ const checkEmailCodeAsync = (code) => {
*/
const modifyPasswordByEmailCodeAsync = (code, password) => {
return api.get('', {
code : code,
code: code,
newPwd: password,
method: 'app.register.resetPwdByCode'
});
... ...
... ... @@ -4,7 +4,6 @@
'use strict';
/**
* 签名算法参考微信支付加密算法
* 参考链接:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=4_3
... ... @@ -15,7 +14,7 @@ const _ = require('lodash');
const SALT = '_+@#$%^';
/**
* 生成加密token
* 加密手机的数据,生成加密token
* @param data json
* @returns string
*/
... ... @@ -30,15 +29,22 @@ const _encodeMD5 = (str) => {
return md5(str).toUpperCase();
};
/**
* 返回一个 md5加密后的字符串
* @param data json
*/
const makeToken = (data) => {
let saltData = Object.assign(data, {key: SALT});
let saltData = Object.assign({}, data, {key: SALT});
let str = _packageObject(saltData);
return _encodeMD5(str);
};
/**
* 验证 token 是否一致
*/
const validateToken = (data, token) => {
let saltData = Object.assign(data, {key: SALT});
let saltData = Object.assign({}, data, {key: SALT});
let str = _packageObject(saltData);
return _encodeMD5(str) === token;
... ...
... ... @@ -4,19 +4,22 @@
'use strict';
const helpers = global.yoho.helpers;
const api = require('./back-api');
const Promise = require('bluebird');
const co = Promise.coroutine;
const _ = require('lodash');
const moment = require('moment');
const helpers = global.yoho.helpers;
const api = require('./back-api');
const userService = require('./user-service');
const passportHelper = require('./passport-helper');
const backHelper = require('./back-helper');
const BACK_LEFT_BANNER_CODE = '3bbaf502c447a2ddad60879042e286d8'; // 找回密码左边的banner
/**
* 验证手机和邮箱输入正确性
*/
const validateEmailOrMobileAsync = (userInput, areaCode) => {
return new Promise(function(resolve, rejected) {
let result = {type: 'email', area: '', phone: ''};
... ... @@ -41,6 +44,9 @@ const validateEmailOrMobileAsync = (userInput, areaCode) => {
};
/**
* 查找用户
*/
const findUserAsync = (type, phone, area) => {
return co(function * () {
const MESSAGE = {
... ... @@ -69,6 +75,9 @@ const findUserAsync = (type, phone, area) => {
})();
};
/**
* 发送验证码到用户
*/
const sendCodeToUserAsync = (type, mobile, areaCode) => {
let sendTo = {
email: api.sendCodeToEmailAsync,
... ... @@ -106,6 +115,9 @@ const indexPageDataAsync = () => {
})();
};
/**
* 验证手机验证码
*/
const verifyCodyByMobileAsync = (area, mobile, mobileCode) => {
const ERR = {
code: 400,
... ... @@ -137,12 +149,15 @@ const verifyCodyByMobileAsync = (area, mobile, mobileCode) => {
};
/**
* 手机 token 合法性验证
*/
const authRequest = (data, token) => {
if (!backHelper.validateToken(data, token)) {
return {};
}
let existTime = moment.duration(1, 'hours').seconds();
let existTime = moment.duration(60, 'minutes').asSeconds();
let isExpired = (moment().unix() - data.createdAt) > existTime;
if (isExpired) {
... ... @@ -152,6 +167,9 @@ const authRequest = (data, token) => {
}
};
/**
* 更新密码接口
*/
const updatePwdAsync = (emailToken, mobileToken, newPassword) => {
return co(function * () {
let result = {type: 'mobile', status: false};
... ... @@ -188,6 +206,9 @@ const updatePwdAsync = (emailToken, mobileToken, newPassword) => {
})();
};
/**
* 验证邮件验证码
*/
const checkEmailCodeAsync = api.checkEmailCodeAsync;
module.exports = {
... ...
/**
* Created by TaoHuang on 2016/6/21.
*/
'use strict';
const serviceAPI = global.yoho.ServiceAPI;
module.exports.getResourceAsync = (resourceCode) => {
/**
* 资源码找资源
*/
const getResourceAsync = resourceCode => {
return serviceAPI.get('/operations/api/v5/resource/get', {
content_code: resourceCode
});
};
module.exports = {
getResourceAsync
};
... ...
/**
* Created by TaoHuang on 2016/6/21.
*/
'use strict';
const api = require('./index-api');
module.exports.getResourceAsync = (resourceCode) => {
/**
* 获得资源
*/
const getResourceAsync = (resourceCode) => {
return api.getResourceAsync(resourceCode)
.then(result => {
if (result.code === 200) {
... ... @@ -17,3 +21,7 @@ module.exports.getResourceAsync = (resourceCode) => {
return {};
});
};
module.exports = {
getResourceAsync
};
... ...
/**
* Created by TaoHuang on 2016/6/20.
*/
'use strict';
const helpers = global.yoho.helpers;
const Promise = require('bluebird');
const co = Promise.coroutine;
const _ = require('lodash');
const helpers = global.yoho.helpers;
const indexService = require('./index-service');
/**
* 获得图片
*/
const getLeftBannerAsync = (resourceCode) => {
const DEFAULT_VALUE = {
img: 'http://img12.static.yhbimg.com/' +
... ... @@ -36,6 +37,9 @@ const getLeftBannerAsync = (resourceCode) => {
})();
};
/**
* 国家数据
*/
const getCountry = () => {
return [
{
... ... @@ -102,25 +106,9 @@ const getCountry = () => {
};
/**
* 验证邮箱是否合法
*
* @param string email
* @return boolean
*/
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);
};
/**
* 各国手机号规则
*/
function _areaMobileVerify(phone, area) {
const _areaMobileVerify = (phone, area) => {
area = area || '86';
phone = phone.trim();
... ... @@ -176,7 +164,7 @@ function _areaMobileVerify(phone, area) {
} else {
return false;
}
}
};
/**
* 验证国际手机号是否合法
... ... @@ -204,24 +192,32 @@ const isAreaMobile = areaMobile => {
};
/**
* 验证手机是否合法
* 验证邮箱是否合法
*/
const verifyMobile = phone => {
if (!phone) {
const verifyEmail = email => {
if (!email) {
return false;
}
return /^1[3|4|5|8|7][0-9]{9}$/.test(phone);
const emailRegExp = /^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/;
return emailRegExp.test(email);
};
const verifyPassword = password => {
if (!password) {
/**
* 验证手机是否合法
*/
const verifyMobile = phone => {
if (!phone) {
return false;
}
return /^([a-zA-Z0-9\-\+_!@\#$%\^&\*\(\)\:\;\.=\[\]\\\',\?]){6,20}$/.test(password);
return /^1[3|4|5|8|7][0-9]{9}$/.test(phone);
};
/**
* 生成带区号的手机号码
*/
const makeAreaMobile = (area, mobile) => {
if (!area || area === '86') {
return mobile;
... ... @@ -230,6 +226,9 @@ const makeAreaMobile = (area, mobile) => {
return `${area}-${mobile}`;
};
/**
* 密码是否合法
*/
const isPassword = pwd => {
if (!pwd) {
return false;
... ... @@ -242,7 +241,6 @@ const isPassword = pwd => {
module.exports = {
validator: {
verifyPassword,
verifyMobile,
isAreaMobile,
verifyEmail,
... ...
... ... @@ -10,7 +10,7 @@ const express = require('express');
const cRoot = './controllers';
const login = require(cRoot + '/login');
const captcha = require(cRoot + '/captcha');
//const captcha = require(cRoot + '/captcha');
const back = require(cRoot + '/back');
const reg = require(cRoot + '/reg');
... ... @@ -29,7 +29,7 @@ router.get('/reg/success', reg.success);
/**
* 找回密码首页信息
*/
// 找回密码首页
// 找回密码首页
router.get('/back/index', back.index);
// 实时验证输入是否正确
... ... @@ -42,7 +42,7 @@ router.post('/back/authcode',
// 提交按钮邮件API
router.post('/back/email',
// Captcha.requiredPage,
// captcha.requiredPage,
back.validateUserPage,
back.sendCodePage,
back.saveInSession);
... ... @@ -50,7 +50,7 @@ router.post('/back/email',
// 提交按钮手机API
router.post('/back/mobile',
captcha.requiredPage,
// captcha.requiredPage,
back.validateUserPage,
back.sendCodePage,
back.saveInSession);
... ... @@ -58,7 +58,7 @@ router.post('/back/mobile',
/**
* 邮件找回密码
*/
// 发送邮件成功页面
// 发送邮件成功页面
router.get('/back/sendEmail',
back.validateEmailInSession,
back.sendEmailPage);
... ... @@ -66,29 +66,30 @@ router.get('/back/sendEmail',
/**
* 短信找回密码
*/
// 验证手机短信页面
// 验证手机短信页面
router.get('/back/verification',
back.validateMobileInSession,
// Back.validateMobileInSession,
// Captcha.requiredPage,
// captcha.requiredPage,
back.verifyCodeByMobilePage);
// 重新发送短信接口
router.post('/back/sendBackMobile',
// Captcha.requiredAPI,
// captcha.requiredAPI,
back.validateMobileAPI,
back.sendBackMobileAPI);
// 验证手机验证码接口
router.post('/back/backMobile',
// Captcha.requiredAPI,
// captcha.requiredAPI,
back.verifyCodeByMobileAPI);
/**
* 重置密码
*/
// 重置密码页面
router.get('/back/backcode',
back.validateExistCodePage,
... ... @@ -100,14 +101,12 @@ router.get('/back/backcode',
router.post('/back/update',
back.validateExistCodePage,
back.validateCodeByMobilePage,
// Back.validatePwdPage,
back.validatePwdPage,
back.updatePwdAPI);
// 重置密码成功页面
router.get('/back/resetSuccess',
// Back.checkSuccessStatusPage,
back.validateSuccessStatusPage,
back.resetPwdSuccessPage);
module.exports = router;
... ...
... ... @@ -41,7 +41,7 @@
<input type="hidden" name="mobile" value="{{mobile}}">
<input type="hidden" name="area" value="{{area}}">
<input type="hidden" name="token" value="{{token}}">
<input type="hidden" name="create_time" value="{{create_time}}">
<input type="hidden" name="createdAt" value="{{createdAt}}">
<input id="reset-pwd-btn" class="btn reset-pwd-btn" type="submit" value="提交" disabled="">
</li>
</ul>
... ...
/**
* 公共头部
* @author: yyq<yanqing.yang@yoho.cn>
* @date: 2016/5/9
*/
var $ = require('yoho-jquery'),
handlebars = require('yoho-handlebars');
var $tool = $('.tool-wrapper'),
$yohoGroup = $tool.find('.yoho-group'),
$loginBox = $('#loginBox');
var $head = $('.head-wrapper'),
$searchForm = $('#search-form'),
$logotrans = $head.find('.main-logo'),
$searchSug = $head.find('.search-suggest'),
$goCart = $head.find('.go-cart'),
$goodsNum = $goCart.find('.goods-num-tip'),
$miniCart = $head.find('.mini-cart-wrapper');
var $subNav = $('.sub-nav-list .contain-third');
var thirdLineNum = 9,
delayer,
centerFn,
loginFn,
cartFn,
requestFrame;
var logoAngle = 0,
loopTime = 500;
// handlebars模板
centerFn = handlebars.compile($('#simple-account-info-tpl').html() || '');
loginFn = handlebars.compile($('#header-login-info-tpl').html() || '');
cartFn = handlebars.compile($('#mini-cart-tpl').html() || '');
// handlebars helper
handlebars.registerHelper('notzero', function(v1, options) {
if (v1 !== '0') {
return options.fn(this);
} else {
return options.inverse(this);
}
});
// 格式化三级菜单
function formatThirdMenu() {
$subNav.each(function() {
var $thirdList = $(this).find('.hide-list'),
list = [],
i = 0;
if ($thirdList.length) {
$thirdList.children().each(function() {
if (i % thirdLineNum === 0) {
list.push('');
}
list[list.length - 1] += this.outerHTML + '';
i++;
});
for (i = 0; i < 3; i++) {
if (!list[i]) {
return;
}
$thirdList.before('<dl class="category-list">' + list[i] + '</dl>');
}
$thirdList.remove();
}
});
}
// 更新头部登陆信息
function updateLoginInfo(data) {
var info = {
usercenter: 'http://www.yohobuy.com/home?t=' + new Date().getTime(),
nickname: data.profile_name,
signout: 'http://www.yohobuy.com/logout.html'
};
if (data.vip.curVipInfo.curLevel * 1 === 3) {
data.vip3 = true;
}
$tool.find('.simple-user-center').html(centerFn(data));
$loginBox.html(loginFn(info));
}
// 同步sso登录状态
function syncLoginInfo() {
var param = {
return_type: 'jsonp',
method: 'open.passport.get'
};
$.getJSON('http://www.yohobuy.com/common/passport/?callback=?', param, function(jsonData) {
if (jsonData && jsonData.data && jsonData.data.result !== -1) {
updateLoginInfo(jsonData.data.data);
} else {
window.setCookie('_UID', '', {
domain: '.yohobuy.com',
expires: -1
});
}
});
}
// 关键词搜索联想
function searchSuggest(key) {
var param = {
return_type: 'jsonp',
query: key
};
$.getJSON('http://search.yohobuy.com/api/suggest?callback=?', param, function(jsonData) {
if (jsonData.code === 200) {
if (jsonData.data && jsonData.data.length) {
$searchSug.html(jsonData.data).show();
} else {
$searchSug.hide();
}
}
});
}
// 同步mini购物车数据
function syncCratInfo(strG) {
var info, total;
if (strG) {
window.setCookie('_g', strG, {
path: '/',
domain: '.yohobuy.com'
});
}
if (window.cookie('_g')) {
info = $.parseJSON(window.cookie('_g'));
total = parseInt(info._nac, 10) + parseInt(info._ac, 10);
total = total > 0 ? total : 0;
$goCart.data({
key: info._k,
num: total
});
$goodsNum.text(total);
}
}
function loadCartDetail(key) {
var param = {
return_type: 'jsonp',
method: 'open.Shoppingcart.getCartData',
shopping_key: key
};
$.getJSON('http://www.yohobuy.com/common/shoppingCart/?callback=?', param, function(jsonData) {
var totalGoods = [],
infoArr = [
'main_goods',
'advance_goods',
'outlet_goods',
'gift_goods',
'need_pay_gifts'
],
data;
if (jsonData.code === 200) {
data = jsonData.data;
$.each(infoArr, function(k, v) {
if (data[v]) {
totalGoods = $.merge(totalGoods, data[v]);
}
});
if (totalGoods && totalGoods.length) {
data.totalGoods = totalGoods;
$miniCart.html(cartFn({
carData: data
}));
} else {
$miniCart.html('<div class="empty-cart"><h3>您的购物车暂无商品</h3></div>');
}
}
});
}
function delCartGoods(data, callback) {
var param = {
return_type: 'jsonp',
method: 'open.Shoppingcart.delone',
shopping_key: data.key,
id: data.id,
isreduce: data.isreduce
};
$.getJSON('http://www.yohobuy.com/common/shoppingCart/?callback=?', param, function(jsonData) {
var strG = '';
if (jsonData.code === 200) {
strG = '{"_k":"' + data.key + '","_nac":' + jsonData.data.total_goods_num + ',"_ac":0,"_r":0}';
syncCratInfo(strG);
return callback();
}
});
}
/**
* css3动画
* @return {[type]} [description]
*/
function requestFrameAct() {
var prefixList = ['webkit', 'moz', 'ms'];
var func1 = prefixList[0] + 'RequestAnimationFrame';
var func2 = prefixList[1] + 'RequestAnimationFrame';
var func3 = prefixList[2] + 'RequestAnimationFrame';
if (window[func1]) {
return function(callback) {
requestAnimationFrame(callback);
};
}
if (window[func2]) {
return function(callback) {
window[func2](callback);
};
}
if (window[func3]) {
return function(callback) {
window[func3](callback);
};
}
return function(callback) {
window.setTimeout(callback, 67);
};
}
/**
* css3动画
* @return {[type]} [description]
*/
function tsAnimate() {
logoAngle += 10;
$logotrans.css({
transform: 'rotateX(' + logoAngle + 'deg)',
'-webkit-transform': 'rotateX(' + logoAngle + 'deg)',
'-moz-transform': 'rotateX(' + logoAngle + 'deg)'
});
if (logoAngle / 90 % 2 === 1) {
$logotrans.toggleClass('logo-cn');
}
if (logoAngle / 90 % 2 === 0 && logoAngle % 360 !== 0) {
window.setTimeout(tsAnimate, 3000);
} else {
if (logoAngle % 360 === 0) {
window.setTimeout(tsAnimate, 1 * 60 * 1000);
} else {
requestFrame(function() {
tsAnimate();
});
}
}
}
/**
* 淡出
* @return {[type]} [description]
*/
function fadeAnimate() {
var cycle = 3000;
if ($logotrans.hasClass('logo-cn')) {
cycle = 1 * 60 * 1000;
}
$logotrans.fadeOut(loopTime, function() {
$logotrans.toggleClass('logo-cn');
$logotrans.fadeIn(loopTime, function() {
window.setTimeout(fadeAnimate, cycle);
});
});
}
/**
* 检测是否支持css3的动画
* @return {Boolean} [description]
*/
function isSupportCss3Animation() {
var thisFunc,
prefixList = ['webkit', 'moz', 'ms'],
i;
for (i = 0; i < prefixList.length; i++) {
thisFunc = prefixList[i] + 'RequestAnimationFrame';
if (window[thisFunc]) {
return true;
} else {
return false;
}
}
}
if (isSupportCss3Animation()) {
requestFrame = requestFrameAct();
window.setTimeout(tsAnimate, 3000);
} else {
window.setTimeout(fadeAnimate, 3000);
}
syncLoginInfo();
formatThirdMenu();
setInterval(syncCratInfo, 2000);
$yohoGroup.hover(function() {
var data = $(this).data();
$(this).text(data.cn);
}, function() {
var data = $(this).data();
$(this).text(data.en);
});
$searchForm.on('keyup', '.search-key', function(e) {
var val = $.trim($(this).val()),
$child = $searchSug.find('li'),
$act = $searchSug.find('.action'),
$focus;
if (e.which > 36 && e.which < 41) {
if (e.which === 38) {
$focus = $act.prev();
if (!$act.length || !$focus.length) {
$focus = $child.eq($child.length - 1);
}
} else if (e.which === 40) {
$focus = $act.next();
if (!$act.length || !$focus.length) {
$focus = $child.eq(0);
}
} else {
return;
}
$child.removeClass('action');
$focus.addClass('action');
$(this).val($focus.find('.searchvalue').text());
} else if (e.which === 13) {
if (val !== '') {
$searchForm.submit();
}
} else {
val = val.replace(new RegExp('\'', 'gm'), ''); // 去掉特殊字符
$(this).val(val);
searchSuggest(val);
}
}).on('blur', '.search-key', function() {
setTimeout(function() {
$searchSug.hide();
}, 200);
});
$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');
});
$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() {
var $thirdNav = $(this).children('.third-nav-wrapper'),
$show = $thirdNav.find('.show-detail'),
param = {};
delayer = setTimeout(function() {
$thirdNav.show();
}, 200);
if (!$show.length || $show.hasClass('show')) {
return;
}
param.content_code = $show.data().code;
param.client_type = 'web';
param.width = 337;
param.height = 250;
param._ = new Date();
$.getJSON('http://new.yohobuy.com/common/getbanner?callback=?', param, function(JsonData) {
if (JsonData.code === 200) {
$show.addClass('show');
$show.find('img').attr('src', JsonData.data.src);
$show.find('a').attr('href', JsonData.data.url);
$show.find('.title').text(JsonData.data.title);
}
});
},
mouseleave: function() {
var $thirdNav = $(this).children('.third-nav-wrapper');
if (delayer) {
clearTimeout(delayer);
}
$thirdNav.hide();
}
});
/**
* 首次进入有弹窗
* @return {[type]} [description]
*/
function actionCover() {
var gender = window.cookie('_Gender');
var newMask = '';
var windowheight = '';
var selfheight = '';
var containertop;
var length = '';
if (true) {
$.get('/guide', function(data) {
newMask = document.createElement('div');
newMask.id = 'cover';
newMask.innerHTML = data;
document.body.appendChild(newMask);
windowheight = $(window).height();
selfheight = $('.guide-box').height();
containertop = windowheight / 2 - selfheight / 2;
length = $('.guide-box .clear').find('li').length;
$('.guide-box').css({
width: (200 * length) + 'px',
top: containertop + 'px'
});
$('#cover').bind('click', function(event) {
window.setCookie('_Gender', '1,3', {
path: '/',
domain: '.yohobuy.com',
expires: 90
});
window.setCookie('_Channel', 'boys', {
path: '/',
domain: '.yohobuy.com',
expires: 7
});
closeCover();
})
$('#cover .guide-box .close').bind('click', function(event) {
getSource('弹窗', 'CLOSE', 'homepage_man');
window.setCookie('_Gender', '1,3', {
path: '/',
domain: '.yohobuy.com',
expires: 90
});
window.setCookie('_Channel', 'boys', {
path: '/',
domain: '.yohobuy.com',
expires: 7
});
closeCover();
});
$('.boys img , .boys .go').bind('click', function(event) {
getSource('弹窗', 'BOYS', 'homepage_man');
window.setCookie('_Gender', '1,3', {
path: '/',
domain: '.yohobuy.com',
expires: 90
});
window.setCookie('_Channel', 'boys', {
path: '/',
domain: '.yohobuy.com',
expires: 7
});
closeCover();
});
$('.girls img, .girls .go').bind('click', function(event) {
getSource('弹窗', 'GIRLS', 'homepage_woman');
window.setCookie('_Gender', '2,3', {
path: '/',
domain: '.yohobuy.com',
expires: 90
});
window.setCookie('_Channel', 'girls', {
path: '/',
domain: '.yohobuy.com',
expires: 7
});
});
$('.lifestyle img, .lifestyle .go').bind('click', function(event) {
window.setCookie('_Channel', 'lifestyle', {
path: '/',
domain: '.yohobuy.com',
expires: 7
});
getSource('弹窗', 'LIEFSTYLE', 'homepage_lifestyle');
});
$('#cover .guide-box').bind('click', function(event) {
event.stopPropagation();
});
});
}
};
actionCover();
/**
* 公共头部
* @author: yyq<yanqing.yang@yoho.cn>
* @date: 2016/5/9
*/
var $ = require('yoho-jquery'),
handlebars = require('yoho-handlebars');
var $tool = $('.tool-wrapper'),
$yohoGroup = $tool.find('.yoho-group'),
$loginBox = $('#loginBox');
var $head = $('.head-wrapper'),
$searchForm = $('#search-form'),
$logotrans = $head.find('.main-logo'),
$searchSug = $head.find('.search-suggest'),
$goCart = $head.find('.go-cart'),
$goodsNum = $goCart.find('.goods-num-tip'),
$miniCart = $head.find('.mini-cart-wrapper');
var $subNav = $('.sub-nav-list .contain-third');
var thirdLineNum = 9,
delayer,
centerFn,
loginFn,
cartFn,
requestFrame;
var logoAngle = 0,
loopTime = 500;
// handlebars模板
centerFn = handlebars.compile($('#simple-account-info-tpl').html() || '');
loginFn = handlebars.compile($('#header-login-info-tpl').html() || '');
cartFn = handlebars.compile($('#mini-cart-tpl').html() || '');
// handlebars helper
handlebars.registerHelper('notzero', function(v1, options) {
if (v1 !== '0') {
return options.fn(this);
} else {
return options.inverse(this);
}
});
// 格式化三级菜单
function formatThirdMenu() {
$subNav.each(function() {
var $thirdList = $(this).find('.hide-list'),
list = [],
i = 0;
if ($thirdList.length) {
$thirdList.children().each(function() {
if (i % thirdLineNum === 0) {
list.push('');
}
list[list.length - 1] += this.outerHTML + '';
i++;
});
for (i = 0; i < 3; i++) {
if (!list[i]) {
return;
}
$thirdList.before('<dl class="category-list">' + list[i] + '</dl>');
}
$thirdList.remove();
}
});
}
// 更新头部登陆信息
function updateLoginInfo(data) {
var info = {
usercenter: 'http://www.yohobuy.com/home?t=' + new Date().getTime(),
nickname: data.profile_name,
signout: 'http://www.yohobuy.com/logout.html'
};
if (data.vip.curVipInfo.curLevel * 1 === 3) {
data.vip3 = true;
}
$tool.find('.simple-user-center').html(centerFn(data));
$loginBox.html(loginFn(info));
}
// 同步sso登录状态
function syncLoginInfo() {
var param = {
return_type: 'jsonp',
method: 'open.passport.get'
};
$.getJSON('http://www.yohobuy.com/common/passport/?callback=?', param, function(jsonData) {
if (jsonData && jsonData.data && jsonData.data.result !== -1) {
updateLoginInfo(jsonData.data.data);
} else {
window.setCookie('_UID', '', {
domain: '.yohobuy.com',
expires: -1
});
}
});
}
// 关键词搜索联想
function searchSuggest(key) {
var param = {
return_type: 'jsonp',
query: key
};
$.getJSON('http://search.yohobuy.com/api/suggest?callback=?', param, function(jsonData) {
if (jsonData.code === 200) {
if (jsonData.data && jsonData.data.length) {
$searchSug.html(jsonData.data).show();
} else {
$searchSug.hide();
}
}
});
}
// 同步mini购物车数据
function syncCratInfo(strG) {
var info, total;
if (strG) {
window.setCookie('_g', strG, {
path: '/',
domain: '.yohobuy.com'
});
}
if (window.cookie('_g')) {
info = $.parseJSON(window.cookie('_g'));
total = parseInt(info._nac, 10) + parseInt(info._ac, 10);
total = total > 0 ? total : 0;
$goCart.data({
key: info._k,
num: total
});
$goodsNum.text(total);
}
}
function loadCartDetail(key) {
var param = {
return_type: 'jsonp',
method: 'open.Shoppingcart.getCartData',
shopping_key: key
};
$.getJSON('http://www.yohobuy.com/common/shoppingCart/?callback=?', param, function(jsonData) {
var totalGoods = [],
infoArr = [
'main_goods',
'advance_goods',
'outlet_goods',
'gift_goods',
'need_pay_gifts'
],
data;
if (jsonData.code === 200) {
data = jsonData.data;
$.each(infoArr, function(k, v) {
if (data[v]) {
totalGoods = $.merge(totalGoods, data[v]);
}
});
if (totalGoods && totalGoods.length) {
data.totalGoods = totalGoods;
$miniCart.html(cartFn({
carData: data
}));
} else {
$miniCart.html('<div class="empty-cart"><h3>您的购物车暂无商品</h3></div>');
}
}
});
}
function delCartGoods(data, callback) {
var param = {
return_type: 'jsonp',
method: 'open.Shoppingcart.delone',
shopping_key: data.key,
id: data.id,
isreduce: data.isreduce
};
$.getJSON('http://www.yohobuy.com/common/shoppingCart/?callback=?', param, function(jsonData) {
var strG = '';
if (jsonData.code === 200) {
strG = '{"_k":"' + data.key + '","_nac":' + jsonData.data.total_goods_num + ',"_ac":0,"_r":0}';
syncCratInfo(strG);
return callback();
}
});
}
/**
* css3动画
* @return {[type]} [description]
*/
function requestFrameAct() {
var prefixList = ['webkit', 'moz', 'ms'];
var func1 = prefixList[0] + 'RequestAnimationFrame';
var func2 = prefixList[1] + 'RequestAnimationFrame';
var func3 = prefixList[2] + 'RequestAnimationFrame';
if (window[func1]) {
return function(callback) {
requestAnimationFrame(callback);
};
}
if (window[func2]) {
return function(callback) {
window[func2](callback);
};
}
if (window[func3]) {
return function(callback) {
window[func3](callback);
};
}
return function(callback) {
window.setTimeout(callback, 67);
};
}
/**
* css3动画
* @return {[type]} [description]
*/
function tsAnimate() {
logoAngle += 10;
$logotrans.css({
transform: 'rotateX(' + logoAngle + 'deg)',
'-webkit-transform': 'rotateX(' + logoAngle + 'deg)',
'-moz-transform': 'rotateX(' + logoAngle + 'deg)'
});
if (logoAngle / 90 % 2 === 1) {
$logotrans.toggleClass('logo-cn');
}
if (logoAngle / 90 % 2 === 0 && logoAngle % 360 !== 0) {
window.setTimeout(tsAnimate, 3000);
} else {
if (logoAngle % 360 === 0) {
window.setTimeout(tsAnimate, 1 * 60 * 1000);
} else {
requestFrame(function() {
tsAnimate();
});
}
}
}
/**
* 淡出
* @return {[type]} [description]
*/
function fadeAnimate() {
var cycle = 3000;
if ($logotrans.hasClass('logo-cn')) {
cycle = 1 * 60 * 1000;
}
$logotrans.fadeOut(loopTime, function() {
$logotrans.toggleClass('logo-cn');
$logotrans.fadeIn(loopTime, function() {
window.setTimeout(fadeAnimate, cycle);
});
});
}
/**
* 检测是否支持css3的动画
* @return {Boolean} [description]
*/
function isSupportCss3Animation() {
var thisFunc,
prefixList = ['webkit', 'moz', 'ms'],
i;
for (i = 0; i < prefixList.length; i++) {
thisFunc = prefixList[i] + 'RequestAnimationFrame';
if (window[thisFunc]) {
return true;
} else {
return false;
}
}
}
if (isSupportCss3Animation()) {
requestFrame = requestFrameAct();
window.setTimeout(tsAnimate, 3000);
} else {
window.setTimeout(fadeAnimate, 3000);
}
syncLoginInfo();
formatThirdMenu();
setInterval(syncCratInfo, 2000);
$yohoGroup.hover(function() {
var data = $(this).data();
$(this).text(data.cn);
}, function() {
var data = $(this).data();
$(this).text(data.en);
});
$searchForm.on('keyup', '.search-key', function(e) {
var val = $.trim($(this).val()),
$child = $searchSug.find('li'),
$act = $searchSug.find('.action'),
$focus;
if (e.which > 36 && e.which < 41) {
if (e.which === 38) {
$focus = $act.prev();
if (!$act.length || !$focus.length) {
$focus = $child.eq($child.length - 1);
}
} else if (e.which === 40) {
$focus = $act.next();
if (!$act.length || !$focus.length) {
$focus = $child.eq(0);
}
} else {
return;
}
$child.removeClass('action');
$focus.addClass('action');
$(this).val($focus.find('.searchvalue').text());
} else if (e.which === 13) {
if (val !== '') {
$searchForm.submit();
}
} else {
val = val.replace(new RegExp('\'', 'gm'), ''); // 去掉特殊字符
$(this).val(val);
searchSuggest(val);
}
}).on('blur', '.search-key', function() {
setTimeout(function() {
$searchSug.hide();
}, 200);
});
$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');
});
$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() {
var $thirdNav = $(this).children('.third-nav-wrapper'),
$show = $thirdNav.find('.show-detail'),
param = {};
delayer = setTimeout(function() {
$thirdNav.show();
}, 200);
if (!$show.length || $show.hasClass('show')) {
return;
}
param.content_code = $show.data().code;
param.client_type = 'web';
param.width = 337;
param.height = 250;
param._ = new Date();
$.getJSON('http://new.yohobuy.com/common/getbanner?callback=?', param, function(JsonData) {
if (JsonData.code === 200) {
$show.addClass('show');
$show.find('img').attr('src', JsonData.data.src);
$show.find('a').attr('href', JsonData.data.url);
$show.find('.title').text(JsonData.data.title);
}
});
},
mouseleave: function() {
var $thirdNav = $(this).children('.third-nav-wrapper');
if (delayer) {
clearTimeout(delayer);
}
$thirdNav.hide();
}
});
/**
* 首次进入有弹窗
* @return {[type]} [description]
*/
function actionCover() {
var gender = window.cookie('_Gender');
var newMask = '';
var windowheight = '';
var selfheight = '';
var containertop;
var length = '';
if (true) {
$.get('/guide', function(data) {
newMask = document.createElement('div');
newMask.id = 'cover';
newMask.innerHTML = data;
document.body.appendChild(newMask);
windowheight = $(window).height();
selfheight = $('.guide-box').height();
containertop = windowheight / 2 - selfheight / 2;
length = $('.guide-box .clear').find('li').length;
$('.guide-box').css({
width: (200 * length) + 'px',
top: containertop + 'px'
});
$('#cover').bind('click', function(event) {
window.setCookie('_Gender', '1,3', {
path: '/',
domain: '.yohobuy.com',
expires: 90
});
window.setCookie('_Channel', 'boys', {
path: '/',
domain: '.yohobuy.com',
expires: 7
});
closeCover();
})
$('#cover .guide-box .close').bind('click', function(event) {
getSource('弹窗', 'CLOSE', 'homepage_man');
window.setCookie('_Gender', '1,3', {
path: '/',
domain: '.yohobuy.com',
expires: 90
});
window.setCookie('_Channel', 'boys', {
path: '/',
domain: '.yohobuy.com',
expires: 7
});
closeCover();
});
$('.boys img , .boys .go').bind('click', function(event) {
getSource('弹窗', 'BOYS', 'homepage_man');
window.setCookie('_Gender', '1,3', {
path: '/',
domain: '.yohobuy.com',
expires: 90
});
window.setCookie('_Channel', 'boys', {
path: '/',
domain: '.yohobuy.com',
expires: 7
});
closeCover();
});
$('.girls img, .girls .go').bind('click', function(event) {
getSource('弹窗', 'GIRLS', 'homepage_woman');
window.setCookie('_Gender', '2,3', {
path: '/',
domain: '.yohobuy.com',
expires: 90
});
window.setCookie('_Channel', 'girls', {
path: '/',
domain: '.yohobuy.com',
expires: 7
});
});
$('.lifestyle img, .lifestyle .go').bind('click', function(event) {
window.setCookie('_Channel', 'lifestyle', {
path: '/',
domain: '.yohobuy.com',
expires: 7
});
getSource('弹窗', 'LIEFSTYLE', 'homepage_lifestyle');
});
$('#cover .guide-box').bind('click', function(event) {
event.stopPropagation();
});
});
}
};
actionCover();
... ...