Authored by ccbikai

Merge branch 'release/1.0' into develop

Too many changes to show.

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

... ... @@ -132,7 +132,7 @@ Session.vim
*~
# auto-generated tag files
tags
### VS Code ###
.vscode/
... ... @@ -143,3 +143,4 @@ public/bundle/*
.eslintcache
*.log.*
nbproject/*
.DS_Store
... ...
... ... @@ -34,7 +34,6 @@ app.locals.version = pkg.version;
yohoLib.global(config);
// 指定libray目录
global.middleware = path.resolve('./doraemon/middleware');
global.utils = path.resolve('./utils');
const logger = global.yoho.logger;
... ...
/**
* 微信分享签名
* Bi Kai <kai.bi@yoho.cn>
*/
'use strict';
const wechatModel = require('../models/wechat');
... ...
var API = require('../../../library/api').API;
var api = new API();
const library = '../../../library';
const sign = require(`${library}/sign`);
/**
* 分享页面基础参数
... ... @@ -10,6 +8,7 @@ const sign = require(`${library}/sign`);
*/
const getPageInfo = (pageInfo) => {
var dest = {};
dest.shareTitle = pageInfo.data.shareTitle;
dest.shareDesc = pageInfo.data.shareContent;
dest.shareImg = pageInfo.data.shareImgUrl;
... ... @@ -73,13 +72,11 @@ const getUserStatus = (param) => {
*/
exports.getPageInfo = (data) => {
var defaultParam = {
method: 'app.activity.getInfoOfOrderShare'
},
infoData = Object.assign(defaultParam, data); // 处理完成后,发给后端
// 处理完成后,发给后端
infoData = Object.assign(defaultParam, data);
return api.get('', sign.apiSign(infoData)).then(result => {
return api.get('', infoData).then(result => {
return getPageInfo(result);
}); // 所有数据返回一个 Promise,方便 Promise.all 调用
};
... ... @@ -95,7 +92,7 @@ exports.getCoupon = (data) => {
// 处理完成后,发给后端
phoneData = Object.assign(defaultParam, data);
return api.get('', sign.apiSign(phoneData)).then(result => {
return api.get('', phoneData).then(result => {
return getUserStatus(result);
}); // 所有数据返回一个 Promise,方便 Promise.all 调用
};
... ... @@ -112,7 +109,7 @@ exports.registerAndSendCoupon = (data) => {
// 处理完成后,发给后端
verifyData = Object.assign(defaultParam, data);
return api.get('', sign.apiSign(verifyData)).then(result => {
return api.get('', verifyData).then(result => {
return getUserStatus(result);
}); // 所有数据返回一个 Promise,方便 Promise.all 调用
};
... ...
... ... @@ -27,80 +27,80 @@ const ticketCacheKey = 'wechatShare:ticket';
// 微信 JS 接口签名校验工具 http://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=jsapisign
const wechat = {
getAccessToken: Promise.coroutine(function* () {
let accessToken = yield cache.get(accessTokenCacheKey);
if (accessToken) {
return accessToken;
}
logger.info('调用微信 API 获取 accessToken');
return request({
url: 'https://api.weixin.qq.com/cgi-bin/token',
qs: {
grant_type: 'client_credential',
appid: appId,
secret: secret
},
json: true
}).then((res) => {
// accessToken 有效期 7200s,缓存 7100s
cache.set(accessTokenCacheKey, res.access_token, 7100).catch((err) => {
logger.error('微信分享 Token, 缓存 accessToken 时出错', JSON.stringify(err));
});
return res.access_token;
}).catch((err) => {
logger.error('微信分享 Token, 获取 accessToken 时出错', JSON.stringify(err));
let _getAccessToken = Promise.coroutine(function* () {
let accessToken = yield cache.get(accessTokenCacheKey);
if (accessToken) {
return accessToken;
}
logger.info('get accessToken from wechat API');
return request({
url: 'https://api.weixin.qq.com/cgi-bin/token',
qs: {
grant_type: 'client_credential',
appid: appId,
secret: secret
},
json: true
}).then((res) => {
// accessToken 有效期 7200s,缓存 7100s
cache.set(accessTokenCacheKey, res.access_token, 7100).catch((err) => {
logger.error('set wechat accessToken cache error', JSON.stringify(err));
});
}),
getTicket: Promise.coroutine(function* () {
let ticket = yield cache.get(ticketCacheKey);
if (ticket) {
return ticket;
}
logger.info('调用微信 API 获取 ticket');
return request({
url: 'https://api.weixin.qq.com/cgi-bin/ticket/getticket',
qs: {
access_token: yield this.getAccessToken(),
type: 'jsapi'
},
json: true
}).then(res => {
return res.access_token;
}).catch((err) => {
logger.error('get accessToken from wechat API error', JSON.stringify(err));
});
});
let _getTicket = Promise.coroutine(function* () {
let ticket = yield cache.get(ticketCacheKey);
if (ticket) {
return ticket;
}
logger.info('get ticket from wechat API');
return request({
url: 'https://api.weixin.qq.com/cgi-bin/ticket/getticket',
qs: {
access_token: yield _getAccessToken(),
type: 'jsapi'
},
json: true
}).then(res => {
// ticket 有效期 7200s,缓存 7100s
cache.set(ticketCacheKey, res.ticket, 7100).catch((err) => {
logger.error('微信分享 Token, 缓存 ticket 时出错', JSON.stringify(err));
});
return res.ticket;
}).catch((err) => {
logger.error('微信分享 Token, 获取 ticket 时出错', JSON.stringify(err));
cache.set(ticketCacheKey, res.ticket, 7100).catch((err) => {
logger.error('set wechat Token cache error', JSON.stringify(err));
});
}),
calcSignature: Promise.coroutine(function* (data) {
data = Object.assign({
nonceStr: Math.random().toString(36).substr(2, 15),
timestamp: Math.floor(Date.now() / 1000) + '',
ticket: yield this.getTicket(),
appId: appId
}, data);
const str = `jsapi_ticket=${data.ticket}&noncestr=${data.nonceStr}&timestamp=${data.timestamp}&url=${data.url}`;
data.signature = sha1(str);
return data;
})
};
return res.ticket;
}).catch((err) => {
logger.error('get ticket from wechat API error', JSON.stringify(err));
});
});
let calcSignature = Promise.coroutine(function* (data) {
data = Object.assign({
nonceStr: Math.random().toString(36).substr(2, 15),
timestamp: Math.floor(Date.now() / 1000) + '',
ticket: yield _getTicket(),
appId: appId
}, data);
const str = `jsapi_ticket=${data.ticket}&noncestr=${data.nonceStr}&timestamp=${data.timestamp}&url=${data.url}`;
data.signature = sha1(str);
return data;
});
// 测试
// wechat.calcSignature({
// calcSignature({
// url: 'http://www.yohobuy.com/'
// }).then(console.log);
module.exports = wechat;
module.exports = {
calcSignature
};
... ...
... ... @@ -9,7 +9,7 @@ const channelModel = require('../models/channel');
const helpers = global.yoho.helpers;
const renderData = {
let _renderData = {
module: 'channel',
page: 'home',
homeHeader: {
... ... @@ -33,19 +33,19 @@ const renderData = {
* @param {[object]} data 自定义数据
* @return {[type]}
*/
const channelPage = (req, res, data) => {
let _channelPage = (req, res, data) => {
return channelModel.getChannelData({ // TODO 内部的Promise方法必须 return 出来
gender: data.gender,
uid: _.toString(req.user.uid)
}).then(result => {
res.render('channel', Object.assign({}, renderData, data, result));
res.render('channel', Object.assign({}, _renderData, data, result));
});
};
/**
* 频道选择页
*/
exports.index = (req, res, next) => {
let index = (req, res, next) => {
channelModel.getChannelSwitchData().then((result) => {
res.render('index', {
module: 'channel',
... ... @@ -67,7 +67,7 @@ exports.index = (req, res, next) => {
* @param {Function} next
* @return {Function}
*/
exports.switchChannel = (req, res, next) => {
let switchChannel = (req, res, next) => {
let channel = req.cookies._Channel;
// 如果查询字符串设置了 go 参数,跳转到 cookie 中设置的频道页
... ... @@ -83,8 +83,8 @@ exports.switchChannel = (req, res, next) => {
/**
* 男生首页
*/
exports.boys = (req, res, next) => {
channelPage(req, res, {
let boys = (req, res, next) => {
_channelPage(req, res, {
gender: 'boys',
title: '男生首页',
boysHomePage: true
... ... @@ -94,8 +94,8 @@ exports.boys = (req, res, next) => {
/**
* 女生首页
*/
exports.girls = (req, res, next) => {
channelPage(req, res, {
let girls = (req, res, next) => {
_channelPage(req, res, {
gender: 'girls',
title: '女生首页',
girlsHomePage: true
... ... @@ -106,8 +106,8 @@ exports.girls = (req, res, next) => {
* 潮童首页
*/
exports.kids = (req, res, next) => {
channelPage(req, res, {
let kids = (req, res, next) => {
_channelPage(req, res, {
gender: 'kids',
title: '潮童首页',
kidsHomePage: true
... ... @@ -117,8 +117,8 @@ exports.kids = (req, res, next) => {
/**
* 创意生活首页
*/
exports.lifestyle = (req, res, next) => {
channelPage(req, res, {
let lifestyle = (req, res, next) => {
_channelPage(req, res, {
gender: 'lifestyle',
title: '创意生活首页',
lifestyleHomePage: true
... ... @@ -131,10 +131,20 @@ exports.lifestyle = (req, res, next) => {
* @param {[object]} res
* @return {[type]}
*/
exports.bottomBanner = (req, res, next) => {
let bottomBanner = (req, res, next) => {
let gender = req.query.gender || 'boys';
channelModel.getBottomBannerData(gender).then(result => {
res.send(result);
}).catch(next);
};
module.exports = {
switchChannel,
index,
boys,
girls,
kids,
lifestyle,
bottomBanner
};
... ...
... ... @@ -8,7 +8,6 @@ const utils = '../../../utils';
const contentCodeConfig = require('../../../config/content-code');
const _ = require('lodash');
const api = global.yoho.ServiceAPI;
const sign = global.yoho.sign;
const camelCase = global.yoho.camelCase;
const logger = global.yoho.logger;
const resourcesProcess = require(`${utils}/resources-process`);
... ... @@ -64,7 +63,7 @@ const channelList = [
* @param {[string]} choosed
* @return {[string]}
*/
const getSidebarColor = (choosed) => {
const _getSidebarColor = (choosed) => {
let color = false;
if (choosed === 'girls') {
... ... @@ -83,7 +82,7 @@ const getSidebarColor = (choosed) => {
* @param {[array]} list
* @return {[array]}
*/
const processSideBar = (list, choosed) => {
const _processSideBar = (list, choosed) => {
const formatData = [];
let offset = 0; // 分割数组用到的游标
... ... @@ -97,7 +96,7 @@ const processSideBar = (list, choosed) => {
sortNameEn: item.sortNameEn,
back: true,
isSelect: false,
bgColor: getSidebarColor(choosed)
bgColor: _getSidebarColor(choosed)
});
}
... ... @@ -118,7 +117,7 @@ const processSideBar = (list, choosed) => {
* @param {[object]} gender
* @return {[type]}
*/
const getChannelResource = (params) => {
const _getChannelResource = (params) => {
params.gender = params.gender || 'boys';
params = Object.assign({
... ... @@ -131,7 +130,7 @@ const getChannelResource = (params) => {
params.new_device = true; // eslint-disable-line
}
return api.get('operations/api/v5/resource/home', sign.apiSign(params), true).then(result => {
return api.get('operations/api/v5/resource/home', params, true).then(result => {
if (result && result.code === 200) {
return resourcesProcess(result.data.list);
} else {
... ... @@ -146,12 +145,12 @@ const getChannelResource = (params) => {
* @param {[string]} choosed
* @return {[object]}
*/
const getLeftNav = (choosed) => {
const _getLeftNav = (choosed) => {
choosed = choosed || 'all';
return api.get('operations/api/v6/category/getCategory', sign.apiSign({}), true).then(result => {
return api.get('operations/api/v6/category/getCategory', {}, true).then(result => {
if (result && result.code === 200) {
return processSideBar(result.data, choosed);
return _processSideBar(result.data, choosed);
} else {
logger.error('侧边栏数据接口返回状态码 不是 200');
return result;
... ... @@ -163,8 +162,8 @@ const getLeftNav = (choosed) => {
* 获取频道选择页数据
* @return {[type]}
*/
const getChannelList = () => {
return api.get('operations/api/v5/entrance/getEntrance', sign.apiSign({}), true).then((result) => {
const _getChannelList = () => {
return api.get('operations/api/v5/entrance/getEntrance', {}, true).then((result) => {
if (result && result.code === 200) {
const list = {};
... ... @@ -196,10 +195,10 @@ const getChannelList = () => {
* 获取频道选择页 背景
* @return {[type]}
*/
const getChannelBg = () => {
return api.get('operations/api/v5/resource/get', sign.apiSign({
const _getChannelBg = () => {
return api.get('operations/api/v5/resource/get', {
content_code: contentCode.index
}), true).then(result => {
}, true).then(result => {
if (result && result.code === 200) {
return result.data.length && result.data[0] && result.data[0].data && result.data[0].data.list[0];
} else {
... ... @@ -216,8 +215,8 @@ const getChannelBg = () => {
* @param {[string]} gender
* @return {[type]}
*/
exports.getChannelSwitchData = () => {
return Promise.all([getChannelList(), getChannelBg()]);
let getChannelSwitchData = () => {
return Promise.all([_getChannelList(), _getChannelBg()]);
};
/**
... ... @@ -225,10 +224,10 @@ exports.getChannelSwitchData = () => {
* @param {[object]} params
* @return {[object]}
*/
exports.getChannelData = (params) => {
let getChannelData = (params) => {
var channelData = {};
return Promise.all([getChannelResource(params), getLeftNav(params.gender)]).then((data) => {
return Promise.all([_getChannelResource(params), _getLeftNav(params.gender)]).then((data) => {
channelData.content = data[0]; // 资源位数据
channelData.sideNav = data[1]; // 侧边栏数据
... ... @@ -241,13 +240,13 @@ exports.getChannelData = (params) => {
* @param {[string]} gender
* @return {[type]}
*/
exports.getBottomBannerData = (gender) => {
let getBottomBannerData = (gender) => {
gender = gender || 'boys';
if (gender === 'boys' || gender === 'girls') {
return api.get('operations/api/v5/resource/get', sign.apiSign({
return api.get('operations/api/v5/resource/get', {
content_code: bottomBannerCode[gender] // eslint-disable-line
}), true);
}, true);
}
return Promise.resolve({
code: 400,
... ... @@ -255,3 +254,9 @@ exports.getBottomBannerData = (gender) => {
message: '参数错误'
});
};
module.exports = {
getChannelData,
getChannelSwitchData,
getBottomBannerData
};
... ...
{{# content}}
{{! 头部banner}}
{{#if focus}}
{{> resources/banner-top}}
{{/if}}
{{! 图标入口}}
{{#if appIconList}}
{{> resources/icons-enter}}
{{/if}}
{{! 中间banner}}
{{#if singleImage}}
{{> resources/banner}}
{{/if}}
{{! 两个小图}}
{{#if smallPic}}
{{> resources/thumb-row}}
{{/if}}
{{! 热门品类}}
{{#if recommendContentFive}}
{{> resources/hot-category}}
{{/if}}
{{! 热门品牌}}
{{#if appHotBrands}}
{{> resources/hot-brands-list}}
{{/if}}
{{! 热门品牌可滑动}}
{{#if customBrands}}
{{> resources/hot-brands-swipe}}
{{/if}}
{{! 潮人搭配}}
{{#if trendsetterCollocation}}
{{> resources/trendsetter-collocation}}
{{/if}}
{{! 潮流话题}}
{{#if trendgoodsTopic}}
{{> resources/trend-topics}}
{{/if}}
{{! 潮流时装/经典裤裙/时尚靴履/潮人配饰/潮流上装}}
{{#if recommendContentOne}}
{{> resources/goods-category}}
{{/if}}
{{! 新入住品牌/品味生活/创意生活}}
{{#if recommendContentTwo}}
{{> resources/creative-life}}
{{/if}}
{{! PLUS}}
{{#if singleNameImage}}
{{> resources/plus-star}}
{{/if}}
{{! 新人专享}}
{{#if newUserFloor}}
{{> resources/fresh-only}}
{{/if}}
{{/ content}}
... ... @@ -45,7 +45,7 @@ const processPublicData = (req, title) => {
* @param {[object]} res
* @return {[type]}
*/
exports.index = (req, res, next) => {
let index = (req, res, next) => {
const pageHeadTab = _.cloneDeep(headTab);
pageHeadTab[0].cur = true;
... ... @@ -67,7 +67,7 @@ exports.index = (req, res, next) => {
}).catch(next);
};
exports.getIndexHtml = (req, res, next) => {
let getIndexHtml = (req, res, next) => {
starModel.getIndexData().then((result) => {
if (md5Str !== result.md5) {
md5Str = result.md5;
... ... @@ -84,7 +84,6 @@ exports.getIndexHtml = (req, res, next) => {
} else {
res.json();
}
}).catch(next);
};
... ... @@ -94,14 +93,14 @@ exports.getIndexHtml = (req, res, next) => {
* @param {[object]} res
* @return {[type]}
*/
exports.special = (req, res, next) => {
let special = (req, res, next) => {
starModel.getSpecialData().then((result) => {
const pageHeadTab = _.cloneDeep(headTab);
pageHeadTab[1].cur = true;
res.render('star/special', _.assign({
page: 'special'
}, processPublicData(req, '星潮教室'), {
}, _processPublicData(req, '星潮教室'), {
resources: result,
headTab: pageHeadTab,
notIndex: true
... ... @@ -116,14 +115,14 @@ exports.special = (req, res, next) => {
* @param {[object]} res
* @return {[type]}
*/
exports.collocation = (req, res) => {
let collocation = (req, res) => {
const pageHeadTab = _.cloneDeep(headTab);
pageHeadTab[2].cur = true;
res.render('star/collocation', _.assign({
isStarDetailPage: true,
page: 'collocation'
}, processPublicData(req, '星潮教室'), {
}, _processPublicData(req, '星潮教室'), {
headTab: pageHeadTab,
notIndex: true
}));
... ... @@ -135,7 +134,7 @@ exports.collocation = (req, res) => {
* @param {[object]} res
* @return {[type]}
*/
exports.collocationList = (req, res, next) => {
let collocationList = (req, res, next) => {
let params = req.query;
let uid = req.cookies.guangStarUid || 0; // 客户端访问,不能使用 cookie
... ... @@ -155,7 +154,7 @@ exports.collocationList = (req, res, next) => {
* @param {[type]} res [description]
* @return {[type]}
*/
exports.setFavorite = (req, res, next) => {
let setFavorite = (req, res, next) => {
let uid = req.cookies.guangStarUid || 0;
let params = {
articleId: req.body.articleId,
... ... @@ -186,11 +185,11 @@ exports.setFavorite = (req, res, next) => {
* @param {[object]} res
* @return {[type]}
*/
exports.detail = (req, res) => {
let detail = (req, res) => {
res.render('star/detail', _.assign({
isStarDetailPage: true,
page: 'detail-list'
}, processPublicData(req, req.query.tag, false)));
}, _processPublicData(req, req.query.tag, false)));
};
/**
... ... @@ -199,7 +198,7 @@ exports.detail = (req, res) => {
* @param {[object]} res
* @return {[type]}
*/
exports.detailList = (req, res, next) => {
let detailList = (req, res, next) => {
let params = req.query;
let uid = req.cookies.guangStarUid || 0;
... ... @@ -212,3 +211,14 @@ exports.detailList = (req, res, next) => {
}));
}).catch(next);
};
module.exports = {
index,
getIndexHtml,
special,
collocation,
collocationList,
setFavorite,
detail,
detailList
};
... ...
... ... @@ -7,7 +7,6 @@
const utils = '../../../utils';
const contentCodeConfig = require('../../../config/content-code');
const resourcesProcess = require(`${utils}/resources-process`);
const sign = global.yoho.sign;
const logger = global.yoho.logger;
const camelCase = global.yoho.camelCase;
const helpers = global.yoho.helpers;
... ... @@ -23,10 +22,10 @@ const contentCode = contentCodeConfig.guang;
* @return {[array]}
*/
const _getResources = (page) => {
return serviceAPI.get('operations/api/v5/resource/get', sign.apiSign({
return serviceAPI.get('operations/api/v5/resource/get', {
content_code: contentCode[page],
client_type: 'iphone'
})).then((result) => {
}).then((result) => {
if (result && result.code === 200) {
return resourcesProcess(result.data);
} else {
... ... @@ -151,11 +150,11 @@ const _processGuangData = (list, flag) => {
* 星潮首页
*/
const getIndexData = () => {
return api.get('', sign.apiSign({
return api.get('', {
method: 'app.starClass.index',
code: '8adc27fcf5676f356602889afcfd2a8e',
client_type: 'iphone'
})).then((result) => {
}).then((result) => {
if (result && result.code === 200) {
return _processIndexData(result);
} else {
... ... @@ -168,15 +167,15 @@ const getIndexData = () => {
/**
* 明星专题
*/
const getDetailData = (params, uid) => {
return api.get('', sign.apiSign({
const getDetailData = (params) => {
return api.get('', {
method: 'app.starClass.lastTagArticle',
tag: params.tag,
page: params.page || 1,
size: 10,
uid: uid,
client_type: 'iphone'
})).then((result) => {
}).then((result) => {
if (result && result.code === 200) {
if (params.page > result.data.totalPage) {
return '';
... ... @@ -221,10 +220,10 @@ const getSpecialData = () => {
* 星搭配
*/
const getCollocationListData = (params, uid) => {
return serviceAPI.get('guang/api/v5/article/getStarClassroomArticleList', sign.apiSign(Object.assign({
return serviceAPI.get('guang/api/v5/article/getStarClassroomArticleList', Object.assign({
limit: '20',
uid: uid
}, params))).then((result) => {
}, params)).then((result) => {
if (result && result.code === 200) {
return _processGuangData(result.data.list.artList);
} else {
... ... @@ -244,10 +243,10 @@ const setFavorite = (params, uid) => {
let url = params.type === 'del' ? '/guang/api/*/favorite/cancelFavorite' : '/guang/api/*/favorite/setFavorite';
return serviceAPI.get(url, sign.apiSign({
return serviceAPI.get(url, {
article_id: params.articleId,
uid: uid
}));
});
};
module.exports = {
... ...
... ... @@ -11,79 +11,81 @@ const helpers = global.yoho.helpers;
const service = require('../models/back-service');
const SIGN_IN_URL = helpers.urlFormat('/signin.html');
const SIGN_IN = helpers.urlFormat('/passport/login');
/**
* 通过邮箱找回密码页面
*/
module.exports.indexByEmailPage = (req, res) => {
let data = {
backUrl: SIGN_IN_URL,
headerText: '找回密码',
isPassportPage: true,
backEmail: true
};
res.render('back/email', Object.assign({
module: 'passport',
page: 'back-email',
title: '找回密码-通过邮箱'
}, data));
const indexEmailPage = (req, res) => {
res.render('back/email', Object.assign(
{
module: 'passport',
page: 'back-email',
title: '找回密码-通过邮箱'
}, {
backUrl: SIGN_IN,
headerText: '找回密码',
isPassportPage: true,
backEmail: true
}
));
};
/**
* 发送验证码到邮箱
*/
module.exports.sendCodeToEmailAPI = (req, res) => {
const sendCodeToEmailAPI = (req, res) => {
let email = req.body.email || '';
let error = {
const ERR = {
code: 400,
message: '邮箱格式不正确,请重新输入',
data: ''
};
if (!helpers.verifyEmail(email)) {
res.json(error);
res.json(ERR);
return;
}
service.sendCodeToEmailAsync(email).then(result => {
if (result.code === 200) {
result.data = helpers.urlFormat('/passport/back/success.html', {email: email});
}
service.sendCodeToEmailAsync(email)
.then(result => {
if (result.code === 200) {
result.data = helpers.urlFormat('/passport/back/success', { email: email });
}
res.json(result);
}).catch(() => {
res.json(error);
});
res.json(result);
})
.catch(() => {
res.json(ERR);
});
};
/**
* 重新发送验证码到邮箱
*/
module.exports.resendCodeToEmailAPI = (req, res) => {
const resendCodeToEmailAPI = (req, res) => {
let email = req.query.email || '';
service.sendCodeToEmailAsync(email).then(result => {
if (_.isEmpty(result)) {
return Promise.rejected('重新发邮件失败');
}
service.sendCodeToEmailAsync(email)
.then(result => {
if (_.isEmpty(result)) {
return Promise.rejected('重新发邮件失败');
}
res.json(result);
}).catch(err => {
res.json({
code: 400,
message: err
res.json(result);
})
.catch(err => {
res.json({
code: 400,
message: err
});
});
});
};
/**
* 邮箱找回密码-返回成功页面
*/
module.exports.backSuccessByEmailPage = (req, res) => {
const backSuccessByEmailPage = (req, res) => {
let email = req.query.email || '';
if (!helpers.verifyEmail(email)) {
... ... @@ -91,55 +93,51 @@ module.exports.backSuccessByEmailPage = (req, res) => {
}
let domain = email.split('@')[1];
let emailUrl = `http://${domain === 'gmail.com' ? 'mail.google.com' : 'mail.'}${domain}`;
res.render('back/email-success', Object.assign({
module: 'passport',
page: 'back-email-success',
title: '找回密码-通过邮箱'
}, {
backUrl: helpers.urlFormat('/passport/back/email.html'),
backUrl: helpers.urlFormat('/passport/back/email'),
headerText: '找回密码',
isPassportPage: true,
backEmailSuccess: true,
goEmail: emailUrl,
resendUrl: helpers.urlFormat('/passport/back/resendemail', {email: email})
resendUrl: helpers.urlFormat('/passport/back/resendemail', { email: email })
}));
};
/**
* 根据邮箱修改密码
*/
module.exports.setNewPasswordByEmailAPI = (req, res) => {
const setNewPasswordByEmailAPI = (req, res) => {
let pwd = req.body.password || '';
let code = req.body.code || '';
let data = {
code: 200,
data: SIGN_IN_URL
data: SIGN_IN
};
service.modifyPasswordByEmailAsync(pwd, code).then(result => {
if (result.includes('history.back')) {
data.code = 400;
data.message = '修改失败';
}
service.modifyPasswordByEmailAsync(pwd, code)
.then(result => {
if (result.includes('history.back')) {
data.code = 400;
data.message = '修改失败';
}
res.json(data);
}).catch(() => {
res.json(data);
});
res.json(data);
})
.catch(() => {
res.json(data);
});
};
/**
* 找回密码页面-通过手机号
*/
module.exports.indexByMobilePage = (req, res, next) => {
const indexMobilePage = (req, res, next) => {
service.getAreaDataAsync()
.then(result => {
res.render('back/mobile', Object.assign({
... ... @@ -147,63 +145,57 @@ module.exports.indexByMobilePage = (req, res, next) => {
page: 'back-mobile',
title: '找回密码-通过手机号'
}, {
backUrl: SIGN_IN_URL,
backUrl: SIGN_IN,
headerText: '找回密码',
isPassportPage: true,
backMobile: true,
countrys: result.data,
areaCode: '+86'
}));
}).catch(next);
})
.catch(next);
};
/**
* 发送手机验证码
*/
module.exports.sendCodeToMobileAPI = (req, res) => {
let result = {
code: 400,
message: '密码只能使用数字、字母和半角标点符号,请重新输入',
data: ''
};
const sendCodeToMobileAPI = (req, res, next) => {
let phoneNum = req.body.phoneNum || '';
let areaCode = req.body.areaCode || '86';
let ERR = {
code: 400,
message: '输入手机号码出错'
};
if (!helpers.verifyMobile(phoneNum)) {
res.json(result);
return;
return res.json(ERR);
}
service.sendCodeToMobileAsync(phoneNum, areaCode).then(data=> {
if (_.isEmpty(data)) {
return Promise.rejected('发送验证码出错');
}
if (data.code === 200) {
result.data = helpers.urlFormat('/passport/back/verifycode', {
phoneNum: phoneNum,
areaCode: areaCode
});
res.json(result);
} else {
return Promise.rejected('发送验证码出错');
}
}).catch(err => {
result.message = err;
res.json(result);
});
service.sendCodeToMobileAsync(phoneNum, areaCode)
.then(result => {
if (_.isEmpty(result) || result.code !== 200) {
ERR.message = '发送验证码出错';
res.json(ERR);
}
if (result.code === 200) {
return res.json({
code: 200,
data: helpers.urlFormat('/passport/back/mobilecode', {
phoneNum: phoneNum,
areaCode: areaCode
})
});
}
})
.catch(next);
};
/**
* 校验验证码页面
*/
module.exports.verifyCodeByMobilePage = (req, res) => {
const verifyCodeByMobilePage = (req, res) => {
let phoneNum = req.query.phoneNum || '';
let areaCode = req.query.areaCode || '86';
res.render('back/mobile-code', Object.assign({
... ... @@ -211,7 +203,7 @@ module.exports.verifyCodeByMobilePage = (req, res) => {
page: 'back-code',
title: '找回密码-通过手机号'
}, {
backUrl: helpers.urlFormat('/passport/back/mobile.html'),
backUrl: helpers.urlFormat('/passport/back/mobile'),
headerText: '找回密码',
isPassportPage: true,
backCode: true,
... ... @@ -224,40 +216,42 @@ module.exports.verifyCodeByMobilePage = (req, res) => {
/**
* 校验手机验证码
*/
module.exports.verifyCodeByMobileAPI = (req, res) => {
const verifyCodeByMobileAPI = (req, res, next) => {
let phoneNum = req.body.phoneNum || '';
let code = req.body.code || '';
let areaCode = req.body.areaCode || '86';
service.validateMobileCodeAsync(phoneNum, code, areaCode)
.then(result => {
if (result.code === 200) {
result.data = helpers.urlFormat('/passport/back/backcode.html', {
phoneNum: phoneNum,
token: result.data.token,
areaCode: areaCode
res.json({
code: 200,
data: helpers.urlFormat('/passport/back/backcode', {
phoneNum: phoneNum,
token: result.data.token,
areaCode: areaCode
})
});
} else {
res.json({
code: 400,
message: '验证码失败'
});
}
res.json(result);
}).catch(() => res.json({code: 400, message: '验证码失败'}));
})
.catch(next);
};
/**
* 找回密码页面,设置新密码页面-手机
*/
module.exports.setNewPasswordByMobilePage = (req, res) => {
const setNewPasswordByMobilePage = (req, res) => {
let phoneNum = req.query.phoneNum || '';
let token = req.query.token || '';
let areaCode = req.query.areaCode || '86';
let code = req.query.code || '';
if (!token || (!helpers.verifyMobile(phoneNum) && !code)) {
if (!(code || (token && helpers.verifyMobile(phoneNum)))) {
res.redirect(400);
return;
}
... ... @@ -267,7 +261,7 @@ module.exports.setNewPasswordByMobilePage = (req, res) => {
page: 'back-new-password',
title: '找回密码-输入新密码'
}, {
backUrl: SIGN_IN_URL,
backUrl: SIGN_IN,
headerText: '找回密码',
isPassportPage: true,
backNewPwd: true,
... ... @@ -281,21 +275,40 @@ module.exports.setNewPasswordByMobilePage = (req, res) => {
/**
* 根据手机验证码修改密码
*/
module.exports.setNewPasswordByMobileAPI = (req, res) => {
const setNewPasswordByMobileAPI = (req, res, next) => {
let phoneNum = req.body.phoneNum || '';
let token = req.body.token || '';
let areaCode = req.body.areaCode || '86';
let newPwd = req.body.password || '';
service.modifyPasswordByMobileAsync(phoneNum, token, newPwd, areaCode)
.then(result => {
console.log(result);
if (result.code === 200) {
result.data = SIGN_IN_URL;
res.json({
code: 200,
data: SIGN_IN
});
} else {
res.json({
code: 400,
message: '修改密码失败'
});
}
})
.catch(next);
};
res.json(result);
}).catch(() => res.json({code: 400, message: '修改密码失败'}));
module.exports = {
indexEmailPage,
sendCodeToEmailAPI,
resendCodeToEmailAPI,
backSuccessByEmailPage,
setNewPasswordByEmailAPI,
indexMobilePage,
sendCodeToMobileAPI,
verifyCodeByMobilePage,
verifyCodeByMobileAPI,
setNewPasswordByMobilePage,
setNewPasswordByMobileAPI
};
... ...
... ... @@ -75,7 +75,7 @@ const bind = {
});
},
bindCheck: (req, res) => {
bindCheck: (req, res, next) => {
let phoneNum = req.body.phoneNum;
let openId = req.body.openId;
let areaCode = req.body.areaCode || '86';
... ... @@ -105,7 +105,7 @@ const bind = {
}
res.json(data);
});
}).catch(next);
} else {
res.json({
code: 400,
... ... @@ -115,7 +115,7 @@ const bind = {
}
},
sendBindMsg: (req, res) => {
sendBindMsg: (req, res, next) => {
let phoneNum = req.body.phoneNum;
let areaCode = req.body.areaCode;
... ... @@ -126,13 +126,13 @@ const bind = {
} else {
res.json({ code: 400, message: '', data: '' });
}
});
}).catch(next);
} else {
res.json({ code: 400, message: '', data: '' });
}
},
checkBindMsg: (req, res) => {
checkBindMsg: (req, res, next) => {
let phoneNum = req.body.phoneNum;
let code = req.body.code;
let areaCode = req.body.areaCode;
... ... @@ -144,13 +144,13 @@ const bind = {
} else {
res.json({ code: 400, message: '', data: '' });
}
});
}).catch(next);
} else {
res.json({ code: 400, message: '', data: '' });
}
},
bindMobile: (req, res) => {
bindMobile: (req, res, next) => {
let phoneNum = req.body.phoneNum;
let openId = req.body.openId;
let areaCode = req.body.areaCode || '86';
... ... @@ -176,13 +176,13 @@ const bind = {
return result;
}).then(result => {
res.json(result);
});
}).catch(next);
} else {
res.json({ code: 400, message: '', data: '' });
}
},
relateMobile: (req, res) => {
relateMobile: (req, res, next) => {
let phoneNum = req.body.phoneNum;
let openId = req.body.openId;
let areaCode = req.body.areaCode || '86';
... ... @@ -206,7 +206,7 @@ const bind = {
return result;
}).then(result => {
res.json(result);
});
}).catch(next);
} else {
res.json({ code: 400, message: '', data: '' });
}
... ... @@ -223,20 +223,20 @@ const bind = {
});
},
changeCheck: (req, res) => {
changeCheck: (req, res, next) => {
let phoneNum = req.body.phoneNum;
let areaCode = req.body.areaCode;
if (_.isNumber(parseInt(phoneNum, 0)) && areaCode) {
BindService.changeCheck(phoneNum, areaCode).then(result => {
res.json(result);
});
}).catch(next);
} else {
res.json({ code: 400, message: '', data: '' });
}
},
changeMobile: (req, res) => {
changeMobile: (req, res, next) => {
let uid = req.user.uid;
let phoneNum = req.body.phoneNum;
let areaCode = req.body.areaCode;
... ... @@ -245,7 +245,7 @@ const bind = {
if (_.isNumber(parseInt(phoneNum, 0)) && uid && areaCode && code) {
BindService.changeMobile(uid, phoneNum, areaCode, code).then(result => {
res.json(result);
});
}).catch(next);
} else {
res.json({ code: 400, message: '', data: '' });
}
... ...
... ... @@ -14,261 +14,267 @@ const cookie = global.yoho.cookie;
const RegService = require('../models/reg-service');
const AuthHelper = require('../models/auth-helper');
const reg = {
index: (req, res) => {
// 设置注册有效时间30分钟, 防机器刷
req.session._REG_EXPIRE = Date.now() + 1800000;
let index = (req, res) => {
// 设置注册有效时间30分钟, 防机器刷
req.session._REG_EXPIRE = Date.now() + 1800000;
let refer = req.query.refer;
let refer = req.query.refer;
refer && res.cookie('refer', encodeURI(refer), {
domain: 'yohobuy.com'
});
refer && res.cookie('refer', encodeURI(refer), {
domain: 'yohobuy.com'
});
res.render('reg/index', {
title: '注册',
res.render('reg/index', {
title: '注册',
backUrl: 'javascript:history.go(-1)', // eslint-disable-line
headerText: '注册', // 头部信息
isPassportPage: true, // 模板中模块标识
areaCode: '+86', // 默认的区号
countrys: RegService.getAreaData() // 地区信息列表
});
},
verifyMobile: (req, res, next) => {
let data = {
code: 400,
message: '手机号已存在',
data: ''
};
let mobile = +req.body.phoneNum;
let area = +(req.body.areaCode || 86);
headerText: '注册', // 头部信息
isPassportPage: true, // 模板中模块标识
areaCode: '+86', // 默认的区号
countrys: RegService.getAreaData() // 地区信息列表
});
};
let verifyMobile = (req, res, next) => {
let data = {
code: 400,
message: '手机号已存在',
data: ''
};
let mobile = +req.body.phoneNum;
let area = +(req.body.areaCode || 86);
// 判断参数是否合法
if (!_.isNumber(mobile) || !_.isNumber(area)) {
data.message = '手机号错误';
return res.json(data);
}
/* 判断参数是否合法 */
if (!_.isNumber(mobile) || !_.isNumber(area)) {
data.message = '手机号错误';
return res.json(data);
}
// 设置注册有效时间30分钟, 防机器刷
let expire = req.session._REG_EXPIRE;
/* 设置注册有效时间30分钟, 防机器刷 */
let expire = req.session._REG_EXPIRE;
if (!expire || expire < Date.now()) {
data.message = '非法请求';
return res.json(data);
}
if (!expire || expire < Date.now()) {
data.message = '非法请求';
// 向手机发送注册验证码
RegService.sendCodeToMobile(area, mobile).then((result) => {
if (!result.code) {
return res.json(data);
}
/* 向手机发送注册验证码 */
RegService.sendCodeToMobile(area, mobile).then((result) => {
if (!result.code) {
return res.json(data);
}
/* 返回跳转到验证页面的链接 */
if (result.code === 200) {
let token = sign.makeToken(mobile);
result.data = helpers.urlFormat('/passport/reg/code', {
token: token,
phoneNum: mobile,
areaCode: area
});
}
// 返回跳转到验证页面的链接
if (result.code === 200) {
let token = sign.makeToken(mobile);
return res.json(result);
}).catch(next);
},
code: (req, res, next) => {
let token = req.query.token;
let mobile = +req.query.phoneNum;
let area = +(req.query.areaCode || 86);
// 判断是否允许访问, 不允许则跳转到错误页面
if (!_.isString(token) || !_.isNumber(mobile) || !sign.verifyToken(mobile, token)) {
return next({
code: 403,
message: 'error token or mobile'
result.data = helpers.urlFormat('/passport/reg/code', {
token: token,
phoneNum: mobile,
areaCode: area
});
}
res.render('reg/code', {
page: 'code',
title: '注册-验证码',
backUrl: '/?go=1', // eslint-disable-line
headerText: '注册', // 头部信息
isPassportPage: true, // 模板中模块标识
areaCode: area, // 默认的区号
phoneNum: mobile, // 手机号
token: token, // 访问令牌
serviceUrl: 'http://chat8.live800.com/live800/chatClient/chatbox.jsp?companyID=620092&configID=149091&jid=8732423409&info=' // 在线客服
return res.json(result);
}).catch(next);
};
let codeAction = (req, res, next) => {
let token = req.query.token;
let mobile = +req.query.phoneNum;
let area = +(req.query.areaCode || 86);
// 判断是否允许访问, 不允许则跳转到错误页面
if (!_.isString(token) || !_.isNumber(mobile) || !sign.verifyToken(mobile, token)) {
return next({
code: 403,
message: 'error token or mobile'
});
},
sendCode: (req, res, next) => {
let data = {
code: 400,
message: '发送验证码失败',
data: ''
};
}
let mobile = +req.body.phoneNum;
let area = +(req.body.areaCode || 86);
res.render('reg/code', {
page: 'code',
title: '注册-验证码',
backUrl: '/?go=1', // eslint-disable-line
headerText: '注册', // 头部信息
isPassportPage: true, // 模板中模块标识
areaCode: area, // 默认的区号
phoneNum: mobile, // 手机号
token: token, // 访问令牌
serviceUrl: 'http://chat8.live800.com/live800/chatClient/chatbox.jsp?companyID=620092&configID=149091&jid=8732423409&info=' // 在线客服
});
};
let sendCode = (req, res, next) => {
let data = {
code: 400,
message: '发送验证码失败',
data: ''
};
let mobile = +req.body.phoneNum;
let area = +(req.body.areaCode || 86);
// 判断参数是否合法
if (!_.isNumber(mobile) || !_.isNumber(area)) {
data.message = '手机号错误';
return res.json(data);
}
/* 判断参数是否合法 */
if (!_.isNumber(mobile) || !_.isNumber(area)) {
data.message = '手机号错误';
return res.json(data);
}
// 设置注册有效时间30分钟, 防机器刷
let expire = req.session._REG_EXPIRE;
/* 设置注册有效时间30分钟, 防机器刷 */
let expire = req.session._REG_EXPIRE;
if (!expire || expire < Date.now()) {
data.message = '非法请求';
return res.json(data);
}
if (!expire || expire < Date.now()) {
data.message = '非法请求';
return res.json(data);
}
// 向手机发送注册验证码
RegService.sendCodeToMobile(area, mobile).then((result) => {
return result.code ? res.json(result) : res.json(data);
}).catch(next);
};
let verifyCode = (req, res, next) => {
let data = {
code: 400,
message: '验证码错误',
data: ''
};
/* 向手机发送注册验证码 */
RegService.sendCodeToMobile(area, mobile).then((result) => {
return result.code ? res.json(result) : res.json(data);
}).catch(next);
},
verifyCode: (req, res, next) => {
let data = {
code: 400,
message: '验证码错误',
data: ''
};
let mobile = +req.body.phoneNum;
let area = +(req.body.areaCode || 86);
let code = +req.body.code;
let mobile = +req.body.phoneNum;
let area = +(req.body.areaCode || 86);
let code = +req.body.code;
/* 判断参数是否合法 */
if (!_.isNumber(mobile) || !_.isNumber(area) || !_.isNumber(code)) {
data.message = '手机号错误';
return res.json(data);
}
if (!_.isNumber(mobile) || !_.isNumber(area) || !_.isNumber(code)) {
data.message = '手机号错误';
return res.json(data);
}
// 设置注册有效时间30分钟, 防机器刷
let expire = req.session._REG_EXPIRE;
/* 设置注册有效时间30分钟, 防机器刷 */
let expire = req.session._REG_EXPIRE;
if (!expire || expire < Date.now()) {
data.message = '非法请求';
return res.json(data);
}
if (!expire || expire < Date.now()) {
data.message = '非法请求';
// 验证注册的标识码是否有效
RegService.validMobileCode(area, mobile, code).then((result) => {
if (!result.code) {
return res.json(data);
}
/* 验证注册的标识码是否有效 */
RegService.validMobileCode(area, mobile, code).then((result) => {
if (!result.code) {
return res.json(data);
}
/* 返回跳转到设置密码的链接 */
if (result.code === 200) {
let token = sign.makeToken(mobile);
result.data = helpers.urlFormat('/passport/reg/password', {
token: token,
phoneNum: mobile,
areaCode: area
});
} else if (result.code === 404) {
result.message = '验证码错误'; // 统一验证提示
}
// 返回跳转到设置密码的链接
if (result.code === 200) {
let token = sign.makeToken(mobile);
return res.json(result);
}).catch(next);
},
password: (req, res, next) => {
let token = req.query.token;
let mobile = +req.query.phoneNum;
let area = +(req.query.areaCode || 86);
// 判断是否允许访问, 不允许则跳转到错误页面
if (!_.isString(token) || !_.isNumber(mobile) || !_.isNumber(area) || !sign.verifyToken(mobile, token)) {
return next({
code: 403,
message: 'error token or mobile'
result.data = helpers.urlFormat('/passport/reg/password', {
token: token,
phoneNum: mobile,
areaCode: area
});
} else if (result.code === 404) {
result.message = '验证码错误'; // 统一验证提示
}
res.render('reg/password', {
page: 'password',
title: '注册-设置密码',
backUrl: '/?go=1', // eslint-disable-line
headerText: '注册', // 头部信息
isPassportPage: true, // 模板中模块标识
areaCode: area, // 默认的区号
phoneNum: mobile, // 手机号
token: token // 访问令牌
return res.json(result);
}).catch(next);
};
let passwordAction = (req, res, next) => {
let token = req.query.token;
let mobile = +req.query.phoneNum;
let area = +(req.query.areaCode || 86);
// 判断是否允许访问, 不允许则跳转到错误页面
if (!_.isString(token) || !_.isNumber(mobile) || !_.isNumber(area) || !sign.verifyToken(mobile, token)) {
return next({
code: 403,
message: 'error token or mobile'
});
},
setPassword: (req, res, next) => {
let data = {
code: 400,
message: '密码格式不正确',
data: ''
};
let mobile = +req.body.phoneNum;
let area = +(req.body.areaCode || 86);
let password = req.body.password;
let token = req.body.token;
}
/* 判断参数是否合法 */
if (!_.isString(token) || !_.isNumber(mobile) || !_.isNumber(area) || !password) {
data.message = '请求参数不合法';
return res.json(data);
}
res.render('reg/password', {
page: 'password',
title: '注册-设置密码',
backUrl: '/?go=1', // eslint-disable-line
headerText: '注册', // 头部信息
isPassportPage: true, // 模板中模块标识
areaCode: area, // 默认的区号
phoneNum: mobile, // 手机号
token: token // 访问令牌
});
};
let setPassword = (req, res, next) => {
let data = {
code: 400,
message: '密码格式不正确',
data: ''
};
let mobile = +req.body.phoneNum;
let area = +(req.body.areaCode || 86);
let password = req.body.password;
let token = req.body.token;
// 判断参数是否合法
if (!_.isString(token) || !_.isNumber(mobile) || !_.isNumber(area) || !password) {
data.message = '请求参数不合法';
return res.json(data);
}
/* 判断是否允许访问 */
if (!sign.verifyToken(mobile, token)) {
data.message = '非法 token';
return res.json(data);
}
// 判断是否允许访问
if (!sign.verifyToken(mobile, token)) {
data.message = '非法 token';
return res.json(data);
}
/* 判断密码是否符合规则 */
if (!helpers.verifyPassword(password)) {
return res.json(data);
}
// 判断密码是否符合规则
if (!helpers.verifyPassword(password)) {
return res.json(data);
}
// 购物车key
let shoppingKey = cookie.getShoppingKey(req);
// 购物车key
let shoppingKey = cookie.getShoppingKey(req);
// 验证注册的标识码是否有效
RegService.regMobile(area, mobile, password, shoppingKey).then((result) => {
if (!result.code || result.code !== 200) {
return Promise.reject(result);
}
if (!result.data || !result.data.uid) {
return Promise.reject(result);
}
// 验证注册的标识码是否有效
RegService.regMobile(area, mobile, password, shoppingKey).then((result) => {
if (!result.code || result.code !== 200) {
return Promise.reject(result);
}
if (!result.data || !result.data.uid) {
return Promise.reject(result);
}
return AuthHelper.syncUserSession(result.data.uid, req, res);
}).then(() => {
// 返回跳转到来源页面
let refer = req.cookies.refer;
return AuthHelper.syncUserSession(result.data.uid, req, res);
}).then(() => {
// 返回跳转到来源页面
let refer = req.cookies.refer;
if (refer) {
refer = decodeURI(req.cookies.refer);
} else {
refer = '/home';
}
if (refer) {
refer = decodeURI(req.cookies.refer);
} else {
refer = '/home';
}
if (/sign|login/.test(refer)) {
refer = '/home';
}
if (/sign|login/.test(refer)) {
refer = '/home';
}
return res.json({
code: 200,
message: '注册成功',
data: {
session: refer,
href: refer
}
});
}).catch(next);
}
return res.json({
code: 200,
message: '注册成功',
data: {
session: refer,
href: refer
}
});
}).catch(next);
};
module.exports = reg;
module.exports = {
index,
verifyMobile,
code: codeAction,
sendCode,
verifyCode,
password: passwordAction,
setPassword
};
... ...
... ... @@ -17,7 +17,7 @@ class Auth {
param.shopping_key = shoppingKey;
}
return api.post('', sign.apiSign(param));
return api.post('', param);
}
static signinByOpenID(nickname, openId, sourceType, shoppingKey) {
... ... @@ -33,7 +33,7 @@ class Auth {
param.shopping_key = shoppingKey;
}
return api.get('', sign.apiSign(param));
return api.get('', param);
}
static profile(uid) {
... ... @@ -42,7 +42,7 @@ class Auth {
method: 'app.passport.profile'
};
return api.get('', sign.apiSign(param));
return api.get('', param);
}
static syncUserSession(uid, req, res) {
... ... @@ -57,11 +57,11 @@ class Auth {
domain: 'yohobuy.com'
});
}
req.session._TOKEN = token; // esline-disable-line
req.session._LOGIN_UID = uid; // esline-disable-line
req.session._TOKEN = token;
req.session._LOGIN_UID = uid;
res.cookie('_TOKEN', token, {
domain: 'yohobuy.com'
}); // esline-disable-line
});
});
}
}
... ...
... ... @@ -4,7 +4,7 @@
'use strict';
const sign = global.yoho.sign;
const api = global.yoho.API;
const YOHOBUY_URL = 'http://www.yohobuy.com/';
... ... @@ -12,10 +12,10 @@ const YOHOBUY_URL = 'http://www.yohobuy.com/';
/**
* 获取地区数据
*/
module.exports.getAreaDataAsync = () => {
return api.get('', sign.apiSign({
const getAreaDataAsync = () => {
return api.get('', {
method: 'app.passport.getArea'
})).then(result => {
}).then(result => {
result.data = result.data.map(value => {
value.areaCode = `+${value.area}`;
... ... @@ -38,11 +38,11 @@ module.exports.getAreaDataAsync = () => {
*
* @param string mail 邮箱地址
*/
module.exports.sendCodeToEmailAsync = (email) => {
return api.get('', sign.apiSign({
const sendCodeToEmailAsync = (email) => {
return api.get('', {
method: 'app.register.backpwdByEmail',
email: email
}));
});
};
/**
... ... @@ -51,7 +51,7 @@ module.exports.sendCodeToEmailAsync = (email) => {
* @param string pwd 新密码
* @param string code 邮箱验证码
*/
module.exports.modifyPasswordByEmailAsync = (pwd, code) => {
const modifyPasswordByEmailAsync = (pwd, code) => {
const options = {
url: `${YOHOBUY_URL}passport/back/update`,
form: {
... ... @@ -71,14 +71,12 @@ module.exports.modifyPasswordByEmailAsync = (pwd, code) => {
* @param string mobile 手机号
* @param integer area 地区码ID
*/
module.exports.sendCodeToMobileAsync = (mobile, area) => {
area = area || 86;
return api.get('', sign.apiSign({
const sendCodeToMobileAsync = (mobile, area) => {
return api.get('', {
mobile: mobile,
area: area,
method: 'app.register.sendBackpwdCodeToMobile'
}));
});
};
/**
... ... @@ -88,14 +86,14 @@ module.exports.sendCodeToMobileAsync = (mobile, area) => {
* @param string code 验证码
* @param integer area 地区码ID
*/
module.exports.validateMobileCodeAsync = (mobile, code, area) => {
const validateMobileCodeAsync = (mobile, code, area) => {
area = area || 86;
return api.get('', sign.apiSign({
return api.get('', {
mobile: mobile,
code: code,
area: area,
method: 'app.register.validBackpwdCode'
}));
});
};
/**
... ... @@ -105,15 +103,22 @@ module.exports.validateMobileCodeAsync = (mobile, code, area) => {
* @param string token 验证手机验证码返回的token
* @param integer area 地区码ID
*/
module.exports.modifyPasswordByMobileAsync = (mobile, token, newpwd, area)=> {
area = area || 86;
return api.get('', sign.apiSign({
const modifyPasswordByMobileAsync = (mobile, token, newpwd, area) => {
return api.get('', {
mobile: mobile,
token: token,
newpwd: newpwd,
area: area,
method: 'app.register.changepwdByMobileCode'
}));
});
};
module.exports = {
getAreaDataAsync,
sendCodeToEmailAsync,
modifyPasswordByEmailAsync,
sendCodeToMobileAsync,
validateMobileCodeAsync,
modifyPasswordByMobileAsync
};
... ...
... ... @@ -9,9 +9,8 @@
const api = global.yoho.API;
class RegService {
static bindCheck(mobile, openId, sourceType, area) {
const RegService = {
bindCheck(mobile, openId, sourceType, area) {
let params = {
method: 'app.passport.signCheck',
area: area,
... ... @@ -21,9 +20,8 @@ class RegService {
};
return api.get('', params);
}
static sendBindMsg(area, mobile) {
},
sendBindMsg(area, mobile) {
let params = {
method: 'app.passport.smsbind',
mobile: mobile,
... ... @@ -31,18 +29,16 @@ class RegService {
};
return api.get('', params);
}
static checkBindCode(area, mobile, code) {
},
checkBindCode(area, mobile, code) {
return api.get('', {
method: 'app.register.validRegCode',
mobile: mobile,
area: area,
code: code
});
}
static bindMobile(openId, sourceType, mobile, area, password, nickname) {
},
bindMobile(openId, sourceType, mobile, area, password, nickname) {
let params = {
method: 'app.passport.bind',
mobile: mobile,
... ... @@ -60,9 +56,8 @@ class RegService {
}
return api.get('', params);
}
static relateMobile(openId, sourceType, mobile, area) {
},
relateMobile(openId, sourceType, mobile, area) {
return api.get('', {
method: 'app.passport.relateMobile',
mobile: mobile,
... ... @@ -70,17 +65,15 @@ class RegService {
source_type: sourceType,
area: area
});
}
static changeCheck(mobile, area) {
},
changeCheck(mobile, area) {
return api.get('', {
method: 'app.passport.changeCheck',
mobile: mobile,
area: area
});
}
static changeMobile(uid, mobile, area, code) {
},
changeMobile(uid, mobile, area, code) {
return api.get('', {
method: 'app.passport.changeMobile',
mobile: mobile,
... ... @@ -89,6 +82,6 @@ class RegService {
area: area
});
}
}
};
module.exports = RegService;
... ...
... ... @@ -16,7 +16,7 @@ const ALIPAY_URL = 'https://mapi.alipay.com/gateway.do';
const defaultOptions = {
service: 'alipay.auth.authorize',
_input_charset: 'utf-8', // esline-disable-line
_input_charset: 'utf-8',
sign_type: 'MD5',
target_service: 'user.auth.quick.login'
};
... ...
... ... @@ -9,9 +9,8 @@
const api = global.yoho.API;
class RegService {
static getAreaData() {
const RegService = {
getAreaData() {
return [
{
areaCode: '+61',
... ... @@ -62,9 +61,8 @@ class RegService {
selected: false,
name: '中国香港'
}];
}
static sendCodeToMobile(area, mobile) {
},
sendCodeToMobile(area, mobile) {
let params = {
method: 'app.register.sendRegCodeToMobile',
area: area,
... ... @@ -72,9 +70,8 @@ class RegService {
};
return api.post('', params);
}
static validMobileCode(area, mobile, code) {
},
validMobileCode(area, mobile, code) {
let params = {
method: 'app.register.validRegCode',
area: area,
... ... @@ -83,9 +80,8 @@ class RegService {
};
return api.post('', params);
}
static regMobile(area, mobile, password, shoppingKey) {
},
regMobile(area, mobile, password, shoppingKey) {
let params = {
method: 'app.passport.register',
area: area,
... ... @@ -94,11 +90,11 @@ class RegService {
};
if (shoppingKey) {
params.shopping_key = shoppingKey; // esline-disable-line
params.shopping_key = shoppingKey;
}
return api.post('', params);
}
}
};
module.exports = RegService;
... ...
... ... @@ -13,6 +13,7 @@ const back = require(cRoot + '/back');
const bind = require(cRoot + '/bind');
const reg = require(cRoot + '/reg');
const router = express.Router(); // eslint-disable-line
// 登出
... ... @@ -61,44 +62,20 @@ router.get('/reg/password', reg.password);
router.post('/reg/setpassword', reg.setPassword);
/**
* 邮箱
* 密码找回
*/
// 通过邮箱找回密码
router.get('/back/email.html', back.indexByEmailPage);
// 邮箱找回密码-成功
router.get('/back/success.html', back.backSuccessByEmailPage);
// 发送邮箱验证码
router.post('/back/sendemail', back.sendCodeToEmailAPI);
// 重新发送邮箱验证码
router.get('/back/resendemail', back.resendCodeToEmailAPI);
// 据邮箱修改密码
router.post('/back/passwordbyemail', back.setNewPasswordByEmailAPI);
/**
* 手机
*/
// 通过手机找回密码
router.get('/back/mobile.html', back.indexByMobilePage);
// 发送手机验证码
router.get('/back/mobilecode.html', back.verifyCodeByMobilePage);
// 输入新密码
router.get('/back/backcode.html', back.setNewPasswordByMobilePage);
// 发送手机验证码
router.post('/back/sendcode', back.sendCodeToMobileAPI);
// 校验手机验证码
router.post('/back/verifycode', back.verifyCodeByMobileAPI);
// 根据手机验证码修改密码
router.post('/back/passwordbymobile', back.setNewPasswordByMobileAPI);
router.get('/back/email', back.indexEmailPage);// 通过邮箱找回密码页面
router.post('/back/sendemail', back.sendCodeToEmailAPI);// 发送邮箱验证码
router.get('/back/resendemail', back.resendCodeToEmailAPI);// 重新发送邮箱验证码
router.get('/back/success', back.backSuccessByEmailPage);// 邮箱找回密码-发送成功页面
router.get('/back/mobile', back.indexMobilePage);// 输入手机号找回密码页面
router.get('/back/mobilecode', back.verifyCodeByMobilePage);// 输入手机验证码页面
router.post('/back/sendcode', back.sendCodeToMobileAPI);// 发送手机验证码
router.post('/back/verifycode', back.verifyCodeByMobileAPI);// 校验手机验证码
router.get('/back/backcode', back.setNewPasswordByMobilePage);// 设置新密码页面
router.post('/back/passwordbyemail', back.setNewPasswordByEmailAPI);// 依据邮箱验证码修改密码
router.post('/back/passwordbymobile', back.setNewPasswordByMobileAPI);// 依据手机验证码修改密码
module.exports = router;
... ...
... ... @@ -11,6 +11,7 @@ const headerModel = require('../../../doraemon/models/header'); // 头部model
const detail = require(`${mRoot}/detail`); // 商品详情 model
const intro = require(`${mRoot}/intro`); // 商品尺码信息 model
const preference = require(`${mRoot}/preference`); // 商品偏好 model
const detailRelated = require(`${mRoot}/consult-comment`); // 商品评论咨询 model
const _ = require('lodash');
/**
... ... @@ -55,7 +56,8 @@ exports.intro = (req, res) => {
productskn: req.params.productskn
}).then((result) => {
res.render('detail/intro', {
result: result
result: result,
layout: false
});
});
};
... ... @@ -68,13 +70,84 @@ exports.intro = (req, res) => {
*/
exports.preference = (req, res) => {
preference({
productskn: req.params.productskn,
yhchannel: req.params.yhchannel,
brandId: req.params.brandId
productskn: req.query.productSkn,
yhchannel: 1,
brandId: req.query.brandId
}).then((result) => {
res.render('detail/preference', {
result: result,
devEnv: true
});
res.render('detail/preference', Object.assign({
layout: false
}, result));
});
};
/**
* 购买评价页
*/
exports.comments = (req, res, next) => {
let headerData = headerModel.setNav({
navTitle: '购买评价'
});
detailRelated.comments(req.query).then((result) => {
res.render('detail/comments', Object.assign({
pageHeader: headerData,
pageFooter: true
}, result));
}).catch(next);
};
/**
* 购买咨询
*/
exports.consults = (req, res, next) => {
let headerData = headerModel.setNav({
navTitle: '购买咨询'
});
detailRelated.consults(req.query).then((result) => {
res.render('detail/consults', Object.assign({
pageHeader: headerData,
pageFooter: true
}, result));
}).catch(next);
};
/**
* 咨询表单页
*/
exports.consultform = (req, res) => {
let headerData = headerModel.setNav({
navTitle: '我要咨询'
});
res.render('detail/consult-form', {
pageHeader: headerData,
productId: req.query.product_id,
formUrl: '/product/detail/consultsubmit',
pageFooter: true
});
};
/**
* 咨询提交接口
*/
exports.consultsubmit = (req, res, next) => {
let data = {
code: 400,
message: '请输入咨询内容',
data: ''
};
// 判断参数是否存在
if (!req.body.product_id || !req.body.content) {
return res.json(data);
}
detailRelated.addConsult(req.user.uid, req.body.product_id, req.body.content).then((result) => {
if (result) {
Object.assign(data, result);
}
return res.json(data);
}).catch(next);
};
... ...
... ... @@ -27,7 +27,7 @@ const saleModel = require(`${mRoot}/sale`);
* @param {[string]} page js文件page名称
* @return {[type]}
*/
const processPublicData = (req, title, page) => {
const _processPublicData = (req, title, page) => {
let data = {};
let headerData = headerModel.setNav({
navTitle: title
... ... @@ -53,8 +53,8 @@ const processPublicData = (req, title, page) => {
* @param {[object]} res
* @return {[type]}
*/
exports.index = (req, res, next) => {
let params = processPublicData(req, 'SALE', 'sale');
let index = (req, res, next) => {
let params = _processPublicData(req, 'SALE', 'sale');
saleModel.getSaleData(params.channel).then((result) => {
res.render('sale/index', Object.assign(params.renderData, {
... ... @@ -74,8 +74,8 @@ exports.index = (req, res, next) => {
* @param {[object]} res
* @return {[type]}
*/
exports.breakingYards = (req, res, next) => {
let params = processPublicData(req, '断码区', 'break-code');
let breakingYards = (req, res, next) => {
let params = _processPublicData(req, '断码区', 'break-code');
saleModel.getBreakCodeData({
yhChannel: params.channel
... ... @@ -90,8 +90,8 @@ exports.breakingYards = (req, res, next) => {
* @param {[object]} res
* @return {[type]}
*/
exports.discount = (req, res, next) => {
let params = processPublicData(req, '折扣专场', 'discount');
let discount = (req, res, next) => {
let params = _processPublicData(req, '折扣专场', 'discount');
saleModel.getDiscountData(params.channel).then((result) => {
res.render('sale/discount', Object.assign(params.renderData, result));
... ... @@ -105,9 +105,9 @@ exports.discount = (req, res, next) => {
* @param {[object]} res
* @return {[type]}
*/
exports.discountDetail = (req, res, next) => {
let discountDetail = (req, res, next) => {
let id = req.query.id;
let params = processPublicData(req, '', 'discount-detail');
let params = _processPublicData(req, '', 'discount-detail');
saleModel.getDiscountDetailData(id, params.channel).then((result) => {
params.renderData.pageHeader.navTitle = result.title;
... ... @@ -121,8 +121,8 @@ exports.discountDetail = (req, res, next) => {
* @param {[object]} res
* @return {[type]}
*/
exports.vip = (req, res, next) => {
let params = processPublicData(req, '会员专享', 'vip');
let vip = (req, res, next) => {
let params = _processPublicData(req, '会员专享', 'vip');
saleModel.getVipData(params.channel).then((result) => {
res.render('sale/vip', Object.assign(params.renderData, {
... ... @@ -137,7 +137,7 @@ exports.vip = (req, res, next) => {
* @param {[object]} res
* @return {[type]}
*/
exports.filter = (req, res, next) => {
let filter = (req, res, next) => {
let params = Object.assign({}, req.query);
saleModel.getFilterData(params).then((result) => {
... ... @@ -156,7 +156,7 @@ exports.filter = (req, res, next) => {
* @param {[object]} res
* @return {[type]}
*/
exports.search = (req, res, next) => {
let search = (req, res, next) => {
let params = Object.assign({}, req.query);
// uid = 9239279
... ... @@ -184,3 +184,13 @@ exports.search = (req, res, next) => {
}, vipObj));
}).catch(next);
};
module.exports = {
index,
breakingYards,
discount,
discountDetail,
vip,
filter,
search
};
... ...
/**
* 商品详情相关models
* @author: yyq<yanqing.yang@yoho.cn>
* @date: 2016/6/27
*/
'use strict';
const api = global.yoho.API;
const _ = require('lodash');
/**
* 获取默认咨询列表
*/
const _getCommonConsult = () => {
let params = {
method: 'app.consult.common'
};
return api.get('', params, {
code: 200
}).then(result => {
let data = {};
if (result.data) {
data.faq = result.data;
}
return data;
});
};
/**
* 处理评价列表数据
* @data {[object]} 评价列表原始数据
* @return {[object]}
*/
const _formatCommentsList = (data) => {
let comment = {
list: [],
total: 0
};
if (data.length) {
_.forEach(data, (value) => {
comment.list.push({
userName: value.nickname,
desc: `${value.color_name}/${value.size_name}`,
content: value.content,
time: value.create_time
});
comment.total = value.total;
});
}
return comment;
};
/**
* 处理咨询列表数据
* @data {[object]} 咨询列表原始数据
* @return {[object]}
*/
const _formatConsultsList = (data) => {
let list = [];
if (data.length) {
_.forEach(data, (value) => {
list.push({
question: value.ask,
time: value.ask_time,
answer: value.answer,
id: value.id,
isLike: value.is_like === 'Y',
like: _.toNumber(value.like),
isUseful: value.is_useful === 'Y',
useful: _.toNumber(value.useful)
});
});
}
return list;
};
/**
* 获取评价数据
* @id {[number]} 商品id
* @page {[number]} 页码
* @limit {[number]} 每页评价数量
* @return {[object]}
*/
const _getComments = (id, page, limit) => {
let params = {
method: 'app.comment.li',
product_id: id,
page: page ? page : 1,
limit: limit ? limit : 300
};
return api.get('', params, {
code: 200
}).then(result => {
let data = {};
if (result.data) {
Object.assign(data, _formatCommentsList(result.data));
}
return data;
});
};
/**
* 获取咨询数据
* @id {[number]} 商品id
* @page {[number]} 页码
* @limit {[number]} 每页咨询数量
* @return {[object]}
*/
const _getConsults = (id, page, limit) => {
let params = {
method: 'app.consult.li',
product_id: id,
page: page ? page : 1,
limit: limit ? limit : 300
};
return api.get('', params, {
code: 200
}).then(result => {
let data = {};
if (result.data && result.data.list) {
Object.assign(data, {
list: _formatConsultsList(result.data.list),
pageTotal: result.data.page_total,
total: result.data.total
});
}
return data;
});
};
/**
* 购买评价列表
* @param {[object]} 查询参数
* @return {[object]}
*/
let comments = (params) => {
return _getComments(params.product_id, 1, 60).then(result => {
let data = {};
if (result.list && result.list.length) {
if (result.total) {
_.set(data, 'pageHeader.navTitle', `购买评价(${result.total})`);
}
data.comments = result.list;
}
return data;
});
};
/**
* 购买咨询列表
* @params {[object]} 查询参数
* @return {[object]}
*/
let consults = (params) => {
return api.all([
_getCommonConsult(),
_getConsults(params.product_id, 1, 60)
]).then(result => {
let data = {
link: `/product/detail/consultform?product_id=${params.product_id}`
};
Object.assign(data, result[0]);
if (result[1].list && result[1].list.length) {
if (result[1].total) {
_.set(data, 'pageHeader.navTitle', `购买咨询(${result[1].total})`);
}
data.consults = result[1].list;
}
return data;
});
};
/**
* 购买咨询列表
* @uid {[number]} 用户id
* @productId {[number]} 商品id
* @content {[string]} 咨询内容
* @return {[object]}
*/
let addConsult = (uid, productId, content) => {
let params = {
method: 'h5.consult.add',
product_id: productId,
content: content,
uid: uid
};
return api.post('', params).then(result => {
if (result.code !== 200) {
return false;
}
return result;
});
};
module.exports = {
comments, // 商品详情相关-购买评价
consults, // 商品详情相关-购买咨询
addConsult // 商品详情相关-添加咨询
};
... ...
... ... @@ -16,24 +16,23 @@ const helpers = global.yoho.helpers;
* @return {array}
*/
const getShopsInfo = (data) => {
let enterStore = {};
let enterStore = [];
_.forEach(data, function(value, key) {
enterStore[key] = {
_.forEach(data, function(value) {
let shopInfo = {
img: value.brand_ico,
storeName: value.brand_name
};
if (value.shop_id !== null && typeof value.shop_id !== 'undefined') {
let params = {};
params.shop_id = value.shop_id;
enterStore[key].url =
helpers.urlFormat('/product/index/brand', params);
if (value.shop_id) {
shopInfo.url = helpers.urlFormat('/product/index/brand', {
shop_id: value.shop_id
});
} else {
enterStore[key].url =
helpers.urlFormat('', null, value.brand_domain);
shopInfo.url = helpers.urlFormat('', null, value.brand_domain);
}
enterStore.push(shopInfo);
});
return enterStore;
};
... ... @@ -117,9 +116,9 @@ const getLimitCodeUrl = (productCode, skn, ua) => {
*/
const detailDataPkg = (origin, uid, vipLevel, ua) => {
let dest = {}, // 结果输出
thumbImageList = [],
colorGroup = {},
thumbImageList = {},
sizeGroup = {},
sizeGroup = [],
totalStorageNum = 0;
// 商品名称
... ... @@ -138,92 +137,110 @@ const detailDataPkg = (origin, uid, vipLevel, ua) => {
}
// 商品促销短语
if (origin.salesPhrase !== null && typeof origin.salesPhrase !== 'undefined') {
if (origin.salesPhrase) {
dest.goodsSubtitle = origin.salesPhrase;
}
// 商品标签
if (origin.productTagBoList !== null && typeof origin.productTagBoList !== 'undefined') {
if (origin.productTagBoList) {
let productTags = {};
_.forEach(origin.productTagBoList, function(value) {
switch (value.tagLabel) {
case 'is_soon_sold_out':
dest.tags.is_soon_sold_out = true;
productTags.is_soon_sold_out = true;
break;
case 'is_new':
dest.tags.is_new = true;
productTags.is_new = true;
break;
case 'is_discount':
dest.tags.is_discount = true;
productTags.is_discount = true;
break;
case 'is_limited':
dest.tags.is_limited = true;
productTags.is_limited = true;
break;
case 'is_yohood':
dest.tags.is_yohood = true;
productTags.is_yohood = true;
break;
case 'is_advance':
dest.tags.is_advance = true;
productTags.is_advance = true;
break;
default:
break;
}
});
dest.tags = productTags;
}
// 商品价格
dest.goodsPrice = {};
if (origin.productPriceBo) {
let originPrice = origin.productPriceBo;
let goodsPrice = {
currentPrice: originPrice.formatSalesPrice
};
if (origin.productPriceBo !== null && typeof origin.productPriceBo !== 'undefined') {
dest.goodsPrice.currentPrice = origin.productPriceBo.formatSalesPrice;
if (origin.productPriceBo.formatMarketPrice !== origin.productPriceBo.formatSalesPrice) {
dest.goodsPrice.previousPrice = origin.productPriceBo.formatMarketPrice;
if (originPrice.formatMarketPrice !== originPrice.formatSalesPrice) {
goodsPrice.previousPrice = originPrice.formatMarketPrice;
}
dest.goodsPrice = goodsPrice;
// 商品返回 YOHO 币
if (origin.productPriceBo.yohoCoinNum !== null && origin.productPriceBo.yohoCoinNum !== 0) {
dest.commodityReturn = origin.productPriceBo.yohoCoinNum;
if (originPrice.yohoCoinNum) {
dest.commodityReturn = originPrice.yohoCoinNum;
}
}
// VIP 商品价格
dest.vipLevel = {};
dest.vipLevel.list = [];
if (origin.productPriceBo.vipPrices) {
let vipList = [];
if (origin.productPriceBo.vipPrices !== null && typeof origin.productPriceBo.vipPrices !== 'undefined') {
_.forEach(origin.productPriceBo.vipPrices, function(value) {
dest.vipLevel.list.push({
vipList.push({
level: value.vipLevel,
text: value.vipPrice,
currentLevel: (value.vipLevel === vipLevel)
});
});
if (vipList.length) {
dest.vipLevel = {
list: vipList
};
}
}
// 上市期
if (origin.expectArrivalTime !== null && typeof origin.expectArrivalTime !== 'undefined') {
dest.periodOfMarket = origin.expectArrivalTime + '月';
if (origin.expectArrivalTime) {
dest.periodOfMarket = `${origin.expectArrivalTime}月`;
}
// 促销信息
dest.goodsDiscount = {};
dest.goodsDiscount.list = [];
if (origin.promotionBoList) {
let discountList = [];
if (origin.promotionBoList !== null && typeof origin.promotionBoList !== 'undefined') {
_.forEach(origin.promotionBoList, function(value) {
let temp = {};
temp.text = '【' + value.promotionType + '】' +
value.promotionTitle;
dest.goodsDiscount.list.push(temp);
discountList.push({
text: `【${value.promotionType}${value.promotionTitle}`
});
});
if (discountList.length) {
dest.goodsDiscount = {
list: discountList
};
}
}
// 商品咨询
dest.feedbacks = {};
dest.feedbacks.consults = [];
dest.feedbacks.consultsNum = 0;
dest.feedbacks = {
consults: [],
consultsNum: 0
};
if (origin.consultBoWrapper !== null && typeof origin.consultBoWrapper !== 'undefined') {
if (origin.consultBoWrapper) {
dest.feedbacks.consultsNum = origin.consultBoWrapper.consultTotal;
_.forEach(origin.consultBoWrapper.consultBoList, function(value) {
dest.feedbacks.consults.push({
... ... @@ -232,62 +249,55 @@ const detailDataPkg = (origin, uid, vipLevel, ua) => {
answer: value.answer
});
});
}
let params = {};
params.product_id = origin.id;
params.total = dest.feedbacks.consultsNum;
dest.feedbacks.consultsUrl = helpers.urlFormat('/product/detail/consults', params);
} else { // 暂无咨询
let consultParams = {
product_id: origin.id
};
let params = {};
if (_.has(dest, 'feedbacks.consultsNum')) {
consultParams.total = dest.feedbacks.consultsNum;
}
params.product_id = origin.id;
dest.feedbacks.consultsUrl = helpers.urlFormat('/product/detail/consultform', consultParams);
dest.feedbacks.consultsUrl = helpers.urlFormat('/product/detail/consultform', params);
}
// 商品评价
dest.feedbacks.commentsNum = 0;
if (origin.commentBoWrapper !== null && typeof origin.commentBoWrapper !== 'undefined') {
if (origin.commentBoWrapper) {
dest.feedbacks.commentsNum = origin.commentBoWrapper.commentTotal;
dest.feedbacks.comments = [];
let commentList = [];
_.forEach(origin.commentBoWrapper.commentBoList, function(value) {
dest.feedbacks.comments.push({
commentList.push({
userName: value.nickName,
desc: value.colorName + '/' + value.sizeName,
desc: `${value.colorName}/${value.sizeName}`,
content: value.content ? value.content : '',
time: value.createTime
});
});
let params = {};
params.product_id = origin.id;
params.total = dest.feedbacks.commentsNum;
dest.feedbacks.comments = commentList;
dest.feedbacks.commentsUrl = helpers.urlFormat('/product/detail/comments', params);
dest.feedbacks.commentsUrl = helpers.urlFormat('/product/detail/comments', {
product_id: origin.id,
total: dest.feedbacks.commentsNum
});
}
// 品牌信息
if (origin.brand !== null && typeof origin.brand !== 'undefined') {
// 为你优选的链接
let params = {};
if (origin.brand) {
let extra = `?productSkn=${origin.erpProductId}&brandId=${origin.brand.id}`;
params.productSkn = origin.erpProductId;
params.brandId = origin.brand.id;
dest.preferenceUrl = helpers.urlFormat('/product/detail/preference', params, '');
dest.preferenceUrl = `/product/detail/preference${extra}`;
}
dest.productSkn = origin.erpProductId;
// 商品信息
if (origin.goodsList !== null && typeof origin.goodsList !== 'undefined') {
let goodsGroup = {},
if (origin.goodsList) {
let goodsGroup = [],
sizeName = '',
colorList = {},
sizeList = {},
... ... @@ -297,42 +307,44 @@ const detailDataPkg = (origin, uid, vipLevel, ua) => {
_.forEach(origin.goodsList, function(value, key) {
if (value.status === 0) {
return true;
return;
}
colorStorageNum = 0;
// 商品分组
if (value.goodsImagesList !== null && typeof value.goodsImagesList !== 'undefined') {
_.forEach(value.goodsImagesList, function(good, keyForGood) {
goodsGroup[keyForGood] = {};
goodsGroup[keyForGood].goodsId = good.goodsId;
goodsGroup[keyForGood].img = good.imageUrl;
if (value.goodsImagesList) {
_.forEach(value.goodsImagesList, function(good) {
goodsGroup.push({
goodsId: good.goodsId,
img: good.imageUrl
});
});
}
// 商品的尺码列表
colorStorageGroup[value.productSkc] = {};
if (value.goodsSizeBoList !== null && typeof value.goodsSizeBoList !== 'undefined') {
_.forEach(value.goodsSizeBoList, function(size, keyForSize) {
sizeList[value.productSkc] = {};
sizeList[value.productSkc][keyForSize] = {};
sizeList[value.productSkc][keyForSize].id = size.id;
sizeList[value.productSkc][keyForSize].skuId = size.goodsSizeSkuId;
sizeList[value.productSkc][keyForSize].goodsId = size.goodsId;
sizeList[value.productSkc][keyForSize].colorId = size.colorId;
sizeList[value.productSkc][keyForSize].name = size.sizeName;
sizeList[value.productSkc][keyForSize].sizeNum = size.goodsSizeStorageNum;
if (value.goodsSizeBoList) {
sizeList[value.productSkc] = [];
_.forEach(value.goodsSizeBoList, function(size) {
sizeList[value.productSkc].push({
id: size.id,
skuId: size.goodsSizeSkuId,
goodsId: size.goodsId,
colorId: size.colorId,
name: size.sizeName,
sizeNum: size.goodsSizeStorageNum
});
sizeName = size.sizeName;
// 所有尺码列表,赋值用于前端展示默认尺码的时候
// 判断出没有库存则显示灰色
let build = {};
let build = {
id: size.id,
storage: size.goodsSizeStorageNum
};
build.storage = size.goodsSizeStorageNum;
build.id = size.id;
allSizeList[sizeName] = (allSizeList[sizeName] === null ||
typeof allSizeList[sizeName] === 'undefined') ? build :
allSizeList[sizeName];
... ... @@ -342,94 +354,100 @@ const detailDataPkg = (origin, uid, vipLevel, ua) => {
});
// 颜色分组
colorList[key] = {};
colorList[key].id = value.colorId;
colorList[key].skcId = value.productSkc;
colorList[key].name = value.colorName;
colorList[key].goodsName = value.goodsName;
colorList[key].colorNum = colorStorageNum;
colorList[key] = {
id: value.colorId,
skcId: value.productSkc,
name: value.colorName,
goodsName: value.goodsName,
colorNum: colorStorageNum
};
}
// 缩略图
let params = {};
params.img = value.colorImage;
thumbImageList[key] = params;
thumbImageList.push({
img: value.colorImage
});
// 商品库存总数
totalStorageNum += colorStorageNum;
totalStorageNum += _.toNumber(colorStorageNum);
});
// 遍历所有尺码,构建颜色显示数据
let i = 1;
_.forEach(allSizeList, function(value, key) {
sizeGroup[0] = {
size: []
};
_.forEach(allSizeList, function(value) {
// 默认尺码
sizeGroup[0] = {};
sizeGroup[0].size.push({
name: sizeName,
sizeNum: _.toNumber(value.storage) > 0 ? true : false,
id: value.id
});
sizeGroup[0].size = {};
sizeGroup[0].size[key] = {};
sizeGroup[0].size[key].name = sizeName;
sizeGroup[0].size[key].sizeNum = (typeof value.storage === 'undefined' ||
value.storage === null) ? false : true;
sizeGroup[0].size[key].id = value.id;
colorGroup[i] = {
color: []
};
// 各个颜色的尺码, 每行显示一个尺码对应的颜色
_.forEach(colorList, function(colorArr, keyForColorArr) {
colorGroup[i] = {};
colorGroup[i].color = {};
colorGroup[i].color[keyForColorArr] = {};
colorGroup[i].color[keyForColorArr].colorNum =
(colorStorageGroup[colorArr.skcId][sizeName] !== null &&
typeof colorStorageGroup[colorArr.skcId][sizeName] !== 'undefined') ?
colorStorageGroup[colorArr.skcId][sizeName] : 0;
_.forEach(colorList, function(colorArr) {
colorArr.colorNum = 0;
if (colorStorageGroup[colorArr.skcId] &&
colorStorageGroup[colorArr.skcId][sizeName]) {
colorArr.colorNum = colorStorageGroup[colorArr.skcId][sizeName];
}
colorGroup[i].color.push(colorArr);
});
colorGroup[i].id = value.id;
++i;
});
// 遍历所有颜色, 构建尺码显示数据
colorGroup[0] = {
color: []
};
// 遍历所有颜色, 构建尺码显示数据
i = 1;
_.forEach(colorList, function(value, key) {
_.forEach(colorList, function(value) {
// 各个尺码的颜色, 每行显示一个颜色的对应尺码
sizeGroup[i] = {};
sizeGroup[i].size = sizeList[value.skcId];
sizeGroup[i].colorId = value.skcId;
sizeGroup[i] = {
size: sizeList[value.skcId],
colorId: value.skcId
};
// 默认颜色
colorGroup[0] = {};
colorGroup[0].color = {};
colorGroup[0].color[key] = value;
colorGroup[0].color.push(value);
++i;
});
// 商品图:多个
if (goodsGroup[1] !== null && typeof goodsGroup[1] !== 'undefined') {
dest.bannerTop = {};
dest.bannerTop.list = [];
if (goodsGroup.length > 1) {
let bannerList = [];
_.forEach(goodsGroup, function(value) {
let params = {};
params.img = value.img;
dest.bannerTop.list.push(params);
bannerList.push({
img: value.img
});
});
dest.bannerTop = {
list: bannerList
};
} else if (goodsGroup[0] !== null && typeof goodsGroup[0] !== 'undefined') {
dest.bannerTop = {};
dest.bannerTop.img = goodsGroup[0].img;
dest.bannerTop = {
img: goodsGroup[0].img
};
}
}
// 悬浮的购物车信息
dest.cartInfo = {};
dest.cartInfo.cartUrl = helpers.urlFormat('/cart/index/index', null);
dest.cartInfo.numInCart = 0;
dest.cartInfo.goodsInstore = origin.storage;
dest.cartInfo = {
cartUrl: helpers.urlFormat('/cart/index/index'),
numInCart: 0,
goodsInstore: origin.storage
};
let soldOut = (origin.storage === 0) || (origin.status === 0 || totalStorageNum === 0);
let notForSale = origin.attribute === 2;
... ... @@ -438,17 +456,16 @@ const detailDataPkg = (origin, uid, vipLevel, ua) => {
if (!soldOut && !notForSale) {
_.orderBy(colorGroup);
dest.cartInfo = {};
dest.cartInfo.productId = origin.id;
dest.cartInfo.thumbs = thumbImageList;
dest.cartInfo.name = (dest.goodsName !== null && typeof dest.goodsName !== 'undefined') ? dest.goodsName : '';
dest.cartInfo.price = (dest.goodsPrice.previousPrice !== null &&
typeof dest.goodsPrice.previousPrice !== 'undefined') ? dest.goodsPrice.previousPrice : '';
dest.cartInfo.salePrice = (dest.goodsPrice.currentPrice !== null &&
typeof dest.goodsPrice.currentPrice !== 'undefined') ? dest.goodsPrice.currentPrice : '';
dest.cartInfo.totalNum = totalStorageNum;
dest.cartInfo.colors = colorGroup;
dest.cartInfo.sizes = sizeGroup;
Object.assign(dest.cartInfo, {
productId: origin.id,
thumbs: thumbImageList,
name: dest.goodsName ? dest.goodsName : '',
price: dest.goodsPrice.previousPrice ? dest.goodsPrice.previousPrice : '',
salePrice: dest.goodsPrice.currentPrice ? dest.goodsPrice.currentPrice : '',
totalNum: totalStorageNum,
colors: _.toArray(colorGroup),
sizes: sizeGroup
});
// 限购商品
if (origin.isLimitBuy === 'Y') {
... ... @@ -465,6 +482,7 @@ const detailDataPkg = (origin, uid, vipLevel, ua) => {
// 处理限购商品有关的按钮状态
dest = procShowStatus(dest, showStatus, isBeginSale);
Object.assign;
dest.cartInfo.limitProductCode = origin.limitProductCode;
dest.cartInfo.limitCodeUrl = getLimitCodeUrl(origin.limitProductCode, origin.erpProductId, ua);
dest.cartInfo.limitProductPay = helpers.urlFormat('/cart/index/orderEnsure'); // 待处理 相关处理逻辑还不存在
... ... @@ -485,11 +503,8 @@ const detailDataPkg = (origin, uid, vipLevel, ua) => {
dest.isCollect = true;
}
// 底部简介的URL链接 待处理
// dest.introUrl = helpers.urlFormat('/product/intro_' + origin.erpProductId +
// '/' + origin.cnAlphabet + '.html', null, '');
dest.introUrl = 'http://localhost:6001/product/detail/intro/' + origin.erpProductId;
// 底部简介URL链接
dest.introUrl = '/product/detail/intro/' + origin.erpProductId;
dest.id = origin.id;
return dest;
... ...
... ... @@ -9,7 +9,6 @@ const utils = '../../../utils';
const contentCodeConfig = require('../../../config/content-code');
const _ = require('lodash');
const sign = global.yoho.sign;
const camelCase = global.yoho.camelCase;
const log = global.yoho.logger;
... ... @@ -57,7 +56,7 @@ const _getOutletResource = (channel, contentcode) => {
yh_channel: channel || ''
};
return serviceApi.get('operations/api/v5/resource/home', sign.apiSign(params)).then(result => {
return serviceApi.get('operations/api/v5/resource/home', params).then(result => {
if (result && result.code === 200) {
return resourcesProcess(result.data.list);
} else {
... ... @@ -98,7 +97,7 @@ const _getNavData = (categoryId) => {
parent_id: categoryId
};
return serviceApi.get('operations/api/v6/category/getCategory', sign.apiSign(params)).then(result => {
return serviceApi.get('operations/api/v6/category/getCategory', params).then(result => {
if (result && result.code === 200) {
let data = _convertNavData(result.data);
... ... @@ -166,7 +165,7 @@ const _getActivityDetail = (id) => {
};
return api.get('', sign.apiSign(params)).then(res => {
return api.get('', params).then(res => {
if (res.code === 200) {
return _convertActicityData(res.data);
} else {
... ... @@ -187,7 +186,7 @@ const _getHomeActivity = (data) => {
platform: 3 // h5平台代号
};
return api.get('', sign.apiSign(_.assign(params, data))).then(res => {
return api.get('', _.assign(params, data)).then(res => {
return _convertActicityData(res.data);
});
};
... ...
... ... @@ -6,25 +6,51 @@
*/
'use strict';
const _ = require('lodash');
const utils = '../../../utils';
const api = global.yoho.API;
const sign = global.yoho.sign;
const _ = require('lodash');
const productProcess = require(`${utils}/product-process`);
const helpers = global.yoho.helpers;
const _formatProduct = (data) => {
let list = [];
_.forEach(data, function(value) {
if (!value.product_skn || !value.goods_list || !value.goods_list.length) {
return;
}
value.goodsId = value.goods_list[0].goods_id;
let goods = {
salePrice: value.sales_price ? value.sales_price : '',
price: value.market_price ? value.market_price : '',
url: helpers.urlFormat(`/product/pro_${value.product_id}_${value.goodsId}/${value.cn_alphabet}.html`),
thumb: value.default_images,
name: value.product_name
};
// 市场价和售价一样,则不显示市场价
if (goods.salePrice === goods.price) {
goods.price = false;
}
list.push(goods);
});
return list;
};
module.exports = (data) => {
var finalResult;
let finalResult = {};
return api.get('', sign.apiSign({
return api.get('', {
method: 'h5.preference.Search',
productskn: data.productskn,
yhchannel: data.yhchannel,
brandId: data.brandId
})).then(result => {
if (!_.isEmpty(result) && result.code === 200) {
// 为你优选数据处理,接口没有数据,待处理,待验证
finalResult = productProcess.processProductList(result.data);
}).then(result => {
if (result) {
finalResult.recommendList = _formatProduct(result);
}
return finalResult;
... ...
... ... @@ -7,7 +7,6 @@
const utils = '../../../utils';
const contentCodeConfig = require('../../../config/content-code');
const sign = global.yoho.sign;
const logger = global.yoho.logger;
const camelCase = global.yoho.camelCase;
const resourcesProcess = require(`${utils}/resources-process`);
... ... @@ -84,11 +83,11 @@ const _processDiscount = (list, channel) => {
const _discount = (params) => {
params = params || {};
return api.get('', sign.apiSign(Object.assign({
return api.get('', Object.assign({
method: 'app.activity.get',
sort: 2,
plateform: 3
}, params)));
}, params));
};
/**
... ... @@ -157,9 +156,9 @@ const _searchSales = (params) => {
params.order = typeCont[params.type][params.order];
}
return api.get('', sign.apiSign(Object.assign({
return api.get('', Object.assign({
method: method
}, params)), true);
}, params), true);
};
/**
... ... @@ -174,10 +173,10 @@ const _getUserProfile = (uid) => {
data: {}
});
}
return api.get('', sign.apiSign({
return api.get('', {
method: 'app.passport.profile',
uid: uid
}), true);
}, true);
};
/**
... ... @@ -186,9 +185,9 @@ const _getUserProfile = (uid) => {
* @return {[array]}
*/
const _getResources = (page, channel) => {
return serviceAPI.get('operations/api/v5/resource/get', sign.apiSign({
return serviceAPI.get('operations/api/v5/resource/get', {
content_code: contentCode[channel][page]
})).then((result) => {
}).then((result) => {
if (result && result.code === 200) {
return resourcesProcess(result.data);
} else {
... ... @@ -204,10 +203,10 @@ const _getResources = (page, channel) => {
* @return {[object]}
*/
const _getBreakingSort = (yhChannel) => {
return api.get('', sign.apiSign({
return api.get('', {
method: 'app.sale.getBreakingSort',
yh_channel: channelType[yhChannel] || '1'
})).then((result) => {
}).then((result) => {
if (result && result.code === 200) {
return _processBreakingSort(result.data);
} else {
... ... @@ -350,11 +349,11 @@ const getDiscountDetailData = (id, yhChannel) => {
};
module.exports = {
getSaleData: getSaleData,
getBreakCodeData: getBreakCodeData,
getDiscountData: getDiscountData,
getDiscountDetailData: getDiscountDetailData,
getVipData: getVipData,
getFilterData: getFilterData,
getSearchData: getSearchData
getSaleData,
getBreakCodeData,
getDiscountData,
getDiscountDetailData,
getVipData,
getFilterData,
getSearchData
};
... ...
... ... @@ -7,6 +7,9 @@
'use strict';
const router = require('express').Router(); // eslint-disable-line
const auth = require('../../doraemon/middleware/auth');
const cRoot = './controllers';
// 商品详情controller
... ... @@ -21,9 +24,13 @@ const outlet = require(`${cRoot}/outlet`);
// routers
// /pro_136349_455445/HEARTSOFARMianMaShuJiaoXiuXianKuPS1684.html
router.get(/\/pro_([\d]+)_([\d]+)\/(.*)/, detail.index);
router.get('/detail/intro/:productskn', detail.intro);
router.get('/detail/preference/:productskn/:yhchannel/:brandId', detail.preference);
router.get(/\/pro_([\d]+)_([\d]+)\/(.*)/, detail.index); // 商品详情页
router.get('/detail/intro/:productskn', detail.intro); // 商品内嵌页
router.get('/detail/preference', detail.preference); // 为你优选
router.get('/detail/consults', detail.consults); // 商品咨询页
router.get('/detail/consultform', auth, detail.consultform); // 商品咨询表单页
router.get('/detail/comments', detail.comments);
router.post('/detail/consultsubmit', auth, detail.consultsubmit); // 商品咨询提交接口
router.get('/sale', sale.index);
router.get('/sale/discount', sale.discount);
... ...
<div class="goods-comments-page yoho-page">
<div class="goods-comments" id="goods-comments">
{{# comments}}
<div class="comment-item">
<span class="user-name">{{userName}}</span>
<span class="goods-spec">&nbsp;购买了&nbsp;&nbsp;{{desc}}</span>
<p class="detail-content">{{content}}</p>
<span class="comment-time">{{time}}</span>
</div>
{{/ comments}}
</div>
{{#if loadmore}}
<input id="loadMoreUrl" type="hidden" value="{{loadMoreUrl}}">
{{/if}}
</div>
\ No newline at end of file
... ...
<div class="consult-form-page yoho-page">
<form class="consult-form" url="{{formUrl}}">
<textarea id="content" name="content">请输入咨询内容</textarea>
<input type="hidden" id="product_id" value="{{productId}}">
<a type="submit" id="submit">提交</a>
</form>
</div>
\ No newline at end of file
... ...
<div class="goods-consults-page yoho-page">
<div class="goto-consult tap-hightlight" id="goto-consult" data-href="{{link}}">
<i class="iconfont consult-logo">&#xe643;</i>
<span>我要咨询</span>
<a href="{{link}}" class="iconfont enter-consult-page">&#xe604;</a>
</div>
<div class="goods-consults customer-consults" id="goods-consults">
{{# consults}}
<div class="consult-item hide" data-id="{{id}}">
<div class="question">
<span class="iconfont">&#xe644;</span>
<p>
{{question}}<br>
<span class="time">{{time}}</span>
</p>
</div>
<div class="answer">
<span class="iconfont">&#xe642;</span>
<p>{{answer}}</p>
</div>
<ul class="operation">
<li class="fav {{#if isLike}}highlight{{/if}}">
<i class="iconfont ">&#xe601;</i>
<i class="count">{{#if like}}{{like}}{{/if}}</i>
<span class="animate-count">+1</span>
</li>
<li class="useful {{#if isUseful}}highlight{{/if}}">
<i class="iconfont ">&#xe605;</i>
有用
<i class="count">{{#if useful}}{{useful}}{{/if}}</i>
<span class="animate-count">+1</span>
</li>
</ul>
</div>
{{/ consults}}
</div>
{{#showReadMore}}
<a href="javascript:;" id="readmore" class="readmore tap-hightlight" >查看更多 <i class="iconfont">&#xe604;</i></a>
{{/showReadMore}}
{{#if faq}}
<h1 class="faq-title">
常见问题
</h1>
<div class="goods-consults" style="margin-top:0">
{{# faq}}
<div class="faq-item">
<div class="question">
<span class="iconfont">&#xe644;</span>
<p>
{{question}}
</p>
</div>
<div class="answer">
<span class="iconfont">&#xe642;</span>
<p>{{answer}}</p>
</div>
</div>
{{/ faq}}
</div>
{{/if}}
</div>
\ No newline at end of file
... ...
... ... @@ -75,25 +75,25 @@
</li>
{{/ list}}
</ul>
{{/vipLevel}}
{{/ vipLevel}}
{{# goodsDiscount}}
<div class="goods-discount" id="goodsDiscount">
{{# list}}
{{#if @first}}
{{#if text}}
<h1 class="first-item short-text tap-hightlight">{{text}}<span class="icon-down iconfont dropdown">&#xe609;</span></h1>
{{/if}}
{{/if}}
{{#if @first}}
{{#if text}}
<h1 class="first-item short-text tap-hightlight">{{text}}<span class="icon-down iconfont dropdown">&#xe609;</span></h1>
{{/if}}
{{/if}}
{{/ list}}
<div class="discount-folder">
{{# list}}
{{#if @first}}
{{else}}
{{#if text}}
<h1 class="folder-item tap-hightlight">{{text}}</h1>
{{/if}}
{{/if}}
{{#if @first}}
{{else}}
{{#if text}}
<h1 class="folder-item tap-hightlight">{{text}}</h1>
{{/if}}
{{/if}}
{{/list}}
</div>
</div>
... ... @@ -101,25 +101,25 @@
{{# feedbacks}}
<div class="feedback-list ">
{{#if commentsNum}}
{{> product/detail/feedback-tab}}
{{else}}
{{#if consultsNum}}
{{> product/detail/feedback-tab}}
{{#if commentsNum}}
{{> product/detail/feedback-tab}}
{{else}}
<div class="nodata tap-hightlight" id="goto-consult">
<span>暂无商品评价和咨询</span>
<a href="{{consultsUrl}}" class="go-consult">我要咨询<span class="iconfont">&#xe604;</span></a>
</div>
{{#if consultsNum}}
{{> product/detail/feedback-tab}}
{{else}}
<div class="nodata tap-hightlight" id="goto-consult">
<span>暂无商品评价和咨询</span>
<a href="{{consultsUrl}}" class="go-consult">我要咨询<span class="iconfont">&#xe604;</span></a>
</div>
{{/if}}
{{/if}}
{{/if}}
</div>
{{/ feedbacks}}
{{# enterStore}}
<div id="enter-store" class="enter-store page-block tap-hightlight">
<a class="store-logo" href="{{url}}" style="">
<img class="lazy" data-original="{{img}}" alt="{{storeName}}">
<img class="lazy" data-original="{{image img 47 47}}" alt="{{storeName}}">
</a>
<a class="store-name" href="{{url}}">{{storeName}}</a>
<a class="store-link" href="{{url}}">进入店铺<span class="iconfont">&#xe604;</span></a>
... ...
{{> product/recommend-content}}
\ No newline at end of file
{{> product/detail/recommend-content}}
\ No newline at end of file
... ...
... ... @@ -4,7 +4,7 @@
<div class="infos">
<div class="basic-info" >
{{#thumbs}}
<img class="thumb {{#unless @first}}hide{{/unless}}" src={{img}}>
<img class="thumb {{#unless @first}}hide{{/unless}}" src={{image img 60 60}}>
{{/thumbs}}
<div class="text-info">
<p class="name">{{name}}</p>
... ...
<div class="title">为您优选新品</div>
<div id="swiper-recommend" class="swiper-container">
<div class="swiper-wrapper swiper-wrapper-recommend">
{{# recommendList}}
<a class="swiper-slide" href="{{url}}">
<img class="swiper-lazy img-box" data-src="{{image thumb 299 388}}">
<div class="sale-name">
{{name}}
</div>
<div class="price">
<span class="sale-price {{^price}}no-price{{/price}}">¥{{salePrice}}</span>
{{#price}}<span class="old-price">{{.}}</span>{{/price}}
</div>
<div class="swiper-lazy-preloader"></div>
</a>
{{/ recommendList}}
</div>
</div>
\ No newline at end of file
... ...
... ... @@ -10,11 +10,12 @@ const isProduction = process.env.NODE_ENV === 'production';
const isTest = process.env.NODE_ENV === 'test';
module.exports = {
app: 'h5',
port: 6001,
siteUrl: '//m.yohobuy.com',
domains: {
api: 'http://testapi.yoho.cn:28078/',
service: 'http://testservice.yoho.cn:28077/'
api: 'http://devapi.yoho.cn:58078/',
service: 'http://devservice.yoho.cn:58077/'
},
useOneapm: false,
useCache: false,
... ...
... ... @@ -3,9 +3,23 @@
* @author: xuqi<qi.xu@yoho.cn>
* @date: 2016/4/25
*/
'use strict';
const helpers = global.yoho.helpers;
module.exports = (req, res, next) => {
if (!req.user.uid) {
if (req.xhr) {
return res.json({
code: 400,
message: '抱歉,您暂未登录!'
});
}
res.redirect(helpers.urlFormat('/signin.html', {
refer: req.originalUrl
}));
}
next();
};
... ...
{{#data}}
<ul class="hot-brands clearfix">
{{> common/floor-header}}
{{# list}}
{{# list}}
<li class="brand">
<a href="{{url}}">
<div class="brand-logo">
... ... @@ -11,8 +11,11 @@
</a>
</li>
{{/ list}}
<li class="more">
<a href="{{more}}"></a>
<a class="{{#unless image.src}}default{{/unless}}" href="{{image.url}}">
<img src="{{image image.src 320 172}}">
</a>
</li>
</ul>
{{/data}}
\ No newline at end of file
{{/data}}
... ...
<div class="icons-wrapper">
<ul class="icons-list clearfix">
{{#data}}
<li class="icons-item"><a href="{{url}}" class="imagebar"><img src="{{image src 98 98}}" alt=""></a><a href="{{url}}" class="linkbar">{{title}}</a></li>
<li class="icons-item item-{{../data.length}}"><a href="{{url}}" class="imagebar"><img src="{{image src 98 98}}" alt=""></a><a href="{{url}}" class="linkbar">{{title}}</a></li>
{{/data}}
</ul>
</div>
... ...
... ... @@ -286,6 +286,9 @@ exports.verifyMobile = (phone) => {
return /^1[3|4|5|8|7][0-9]{9}$/.test(phone);
};
/**
* 验证密码规则
*/
exports.verifyPassword = (password) => {
if (!password) {
return false;
... ...
... ... @@ -55,7 +55,7 @@
"serve-favicon": "^2.3.0",
"uuid": "^2.0.2",
"winston": "^2.2.0",
"yoho-node-lib": "0.0.5",
"yoho-node-lib": "0.0.8",
"winston-daily-rotate-file": "^1.1.4"
},
"devDependencies": {
... ...
No preview for this file type