Too many changes to show.

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

... ... @@ -12,7 +12,7 @@ const path = require('path');
const bodyParser = require('body-parser');
const cookieParser = require('cookie-parser');
const favicon = require('serve-favicon');
const session = require('express-session');
const session = require('yoho-express-session');
const memcached = require('connect-memcached');
const hbs = require('express-handlebars');
... ... @@ -34,6 +34,7 @@ global.utils = path.resolve('./utils');
app.locals.devEnv = app.get('env') === 'development';
app.locals.version = pkg.version;
app.set('subdomain offset', 2);
app.set('view engine', '.hbs');
app.set('views', './doraemon/views');
app.set('view cache', true);
... ... @@ -85,6 +86,7 @@ const logger = global.yoho.logger;
// dispatcher
try {
const subDomain = require('./doraemon/middleware/sub-domain');
const itemNameHandler = require('./doraemon/middleware/item-name-handler');
const mobileCheck = require('./doraemon/middleware/mobile-check');
const user = require('./doraemon/middleware/user');
... ... @@ -94,8 +96,8 @@ try {
const setPageInfo = require('./doraemon/middleware/set-pageinfo');
// YOHO 前置中间件
app.use(subDomain());
app.use(itemNameHandler);
app.use(mobileCheck());
app.use(setYohoData());
app.use(user());
... ...
... ... @@ -14,20 +14,11 @@ const helpers = global.yoho.helpers;
const processProduct = require(`${global.utils}/product-process`).processProduct;
const api = global.yoho.API;
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];
... ... @@ -52,11 +43,10 @@ const channelMap = dataMap.channel;
const sortMap = dataMap.sort;
// 构建url
const _httpBuildQuery = data => {
return searchApi.get('search.json', data, {
cache: true
});
const webSearchAsync = data => {
return api.get('', Object.assign({
method: 'web.search.newshelve'
}, data), {cache: true});
};
/**
... ... @@ -339,7 +329,7 @@ const _getGirlsSingleHot = (args, type) => {
return;
}
return searchApi.get('search.json', {
return webSearchAsync({
client_type: 'web',
query: skns,
order: 'shelve_time:desc',
... ... @@ -349,9 +339,7 @@ const _getGirlsSingleHot = (args, type) => {
stocknumber: 1,
page: 1,
gender: channelMap[type].gender,
viewNum: 60
}, {
cache: true
limit: 60
});
};
... ... @@ -739,7 +727,8 @@ const _formatParams = (channel, data) => {
if (data) {
params = Object.assign(data);
}
return searchApi.get('search.json', params).then(result => {
return webSearchAsync(params).then(result => {
let ret = result.data;
if (ret) {
... ... @@ -811,16 +800,16 @@ const getNewArrival = channel => {
sales: 'Y',
attribute_not: 2,
stocknumber: 3,
shelve_time: _getShelveTime(2)
dayLimit: 4
};
params.gender = channelMap[channel].gender;
_.forEach(sortList, (item) => {
let data = Object.assign(item, params);
let data = Object.assign(item, params, {limit: item.viewNum});
rel.push(_httpBuildQuery(data));
rel.push(webSearchAsync(data));
});
return Promise.all(rel).then(res => {
... ... @@ -828,10 +817,10 @@ const getNewArrival = channel => {
result = [];
_.forEach(sortList, (it, index) => {
if (res[index].data &&
res[index].data.product_list.length === sortList[index].viewNum) {
let list = _.get(res[index], 'data.product_list', []);
data = data.concat(res[index].data.product_list);
if (list.length === sortList[index].viewNum) {
data = data.concat(list);
}
});
... ...
... ... @@ -15,8 +15,6 @@ const DoubanStrategy = require('passport-douban').Strategy;
const RenrenStrategy = require('passport-renren').Strategy;
const AlipayStrategy = require('./models/passport-alipay').Strategy;
const md5 = require('md5');
const AuthHelper = require('./models/auth-helper');
const config = global.yoho.config;
... ... @@ -37,21 +35,11 @@ passport.use('local', new LocalStrategy({
let area = req.body.areaCode || '86';
if (isNaN(_.parseInt(area)) || _.isEmpty(username) || _.isEmpty(password)) {
if (_.isEmpty(password)) {
logger.info(`【Passport Loginbad params, area:${area} account:${username} password:${password}`);
return done({message: '登录参数错误'}, null);
}
let verifyEmail = helpers.verifyEmail(username);
// 国际号码验证取消
let verifyMobile = area === '86' ? helpers.verifyAreaMobile(area + '-' + username) : true;
if (!verifyEmail && !verifyMobile) {
logger.info(`【Passport Loginbad account, email:${verifyEmail} mobile:${verifyMobile}`);
return done({message: '登录账号格式错误'}, null);
}
let verifyCode = req.body.captcha;
if (verifyCode && verifyCode !== req.session.captcha) {
... ... @@ -62,7 +50,6 @@ passport.use('local', new LocalStrategy({
let account = req.body.account;
let type = req.body.loginType;
let ip = req.ip;
let errorLoginKey = 'account_errorlogin_' + account;
let accountKey = 'account_signin_' + account;
... ...
... ... @@ -44,7 +44,7 @@ const generate = (req, res) => {
res.end(captcha.image);
};
const checkAPI = (req, res, next) => {
const checkAPI = (req, res) => {
let captchaToken = req.body.verifyCode || '';
if (captchaToken === req.session.captcha) {
... ...
... ... @@ -12,7 +12,6 @@ const qs = require('querystring');
const passport = require('passport');
const uuid = require('uuid');
const md5 = require('md5');
const cookie = global.yoho.cookie;
const helpers = global.yoho.helpers;
const log = global.yoho.logger;
... ... @@ -291,6 +290,86 @@ const local = {
}
}).catch(next);
}
},
qrcode: {
refresh: (req, res, next) => {
AuthHelper.fetchByQrCode().then((result) => {
if (result.code === 200) {
return res.json({
code: 200,
data: {
qrcode: `http://m.yohobuy.com/signin.html?qr=${result.data.code}`
}
});
} else {
return res.json({
code: 400,
message: '生成二维码错误'
});
}
}).catch(next);
},
check: (req, res, next) => {
let qrcode = req.body.qrcode || '';
if (!qrcode) {
return res.json({
code: 400,
message: '输入错误,请重新刷新二维码'
});
}
if (!_.includes(qrcode, '=')) {
return res.json({
code: 400,
message: '输入错误,请重新刷新二维码'
});
}
let token = qrcode.substring(qrcode.indexOf('=') + 1);
AuthHelper.checkByQrCode(token).then((result) => {
if (_.isEmpty(result)) {
return res.json({
code: 400,
message: '输入错误,请重新刷新二维码'
});
}
if (result.code === 402) {
return res.json({
code: 402,
message: '二维码为空'
});
}
if (result.code === 403) {
return res.json({
code: 403,
message: '二维码未失效,不可登录'
});
}
if (result.code === 404) {
return res.json({
code: 404,
message: '二维码失效,需要重新刷新'
});
}
if (result.code === 200) {
return res.json({
code: 200,
message: '可以登录'
});
}
return res.json({
code: 400,
message: '服务器问题'
});
}).catch(next);
}
}
};
... ...
'use strict';
const md5 = require('md5');
const aes = require('./aes-pwd');
const cache = global.yoho.cache;
const sign = global.yoho.sign;
... ... @@ -11,7 +12,8 @@ const Auth = {
let _that = this;
let loginBy = {
password: _that.signinByPasswordWithAes,
sms: _that.signinBySMS
sms: _that.signinBySMS,
qrcode: _that.signinByQrCode
};
return loginBy[type](area, profile, password, shoppingKey);
... ... @@ -44,6 +46,33 @@ const Auth = {
return api.post('', param);
},
signinByQrCode(__1, __2, code, shoppingKey) { // eslint-disable-line
let param = {
method: 'app.twoDimen.qrCodeLogin',
code: code.substring(code.indexOf('=') + 1)
};
if (shoppingKey) {
param.shopping_key = shoppingKey;
}
return api.post('', param);
},
fetchByQrCode() {
let param = {
method: 'app.twoDimen.getCode'
};
return api.post('', param);
},
checkByQrCode(code) {
let param = {
method: 'app.twoDimen.loginCheck',
code: code
};
return api.post('', param);
},
sendPasswordBySMS(area, mobile) {
let param = {
method: 'app.message.sendSms',
... ...
... ... @@ -249,8 +249,8 @@ const getUserInfo = (area, mobile) => {
return UserService.findByMobileAsync(area, mobile).then(user => {
let profile = (user.profile_name || mobile).toString();
if ((profile.length === 11 && profile.indexOf('*') < 0) || (profile.indexOf('-') >= 0
&& profile.indexOf('*') < 0)) {
if ((profile.length === 11 && profile.indexOf('*') < 0) || (profile.indexOf('-') >= 0 &&
profile.indexOf('*') < 0)) {
profile = profile.substring(0, 3) + '****' + profile.substring(7, 11);
}
... ...
... ... @@ -29,6 +29,10 @@ router.post('/passport/login/sms/auth', login.local.sms.auth); // 撉靽⊿
router.post('/passport/login/sms/checkuser', login.local.sms.checkUser); // 短信检查用户是否注册
router.post('/passport/login/password/checkuser', back.fakeGetUserInfoAPI);// 假的,密码登录检查用户是否注册
// 二维码登录
router.post('/passport/login/qrcode/refresh', login.local.qrcode.refresh); // 刷新二维码
router.post('/passport/login/qrcode/check', login.local.qrcode.check); // 验证二维码的状态
router.get('/passport/login', login.common.beforeLogin, login.local.loginPage);
router.post('/passport/login/auth', login.local.login);
router.get('/passport/logout', login.local.logout);
... ...
... ... @@ -4,8 +4,17 @@
<form method='post' onsubmit='return false;'>
<div class="content">
<ul class="login-ul">
<li class="relative clearfix">
<h2 class="title">会员登录</h2>
<div class="switch-login-type" data-type="DesktopLogin">
<div id="device-bg" class="type-mobile-bg"></div>
<div class="type-tip tip-title">
<div id="device-tip" style="margin-left: 15px;margin-top: 8px">扫码登录更安全</div>
</div>
</div>
<div class="desktop-login">
<li class="relative clearfix">
<h2 class="title">会员登录</h2>
<span id="country-code" class="country-code right">
<em>{{countryName}} {{countryCode}}</em>
<i class="iconfont">&#xe60b;</i>
... ... @@ -16,70 +25,73 @@
{{/each}}
</ul>
</span>
</li>
</li>
<li class="relative">
<div class="switch">
<div class="left selected" data-type="PasswordLogin">普通登录</div>
<div class="right" data-type="SMSLogin">手机验证码登录</div>
</div>
</li>
<li class="relative">
<div class="switch">
<div class="left selected" data-type="PasswordLogin">普通登录</div>
<div class="right" data-type="SMSLogin">手机验证码登录</div>
</div>
</li>
<li class="relative password-login">
<input id="account1" class="account input va" name="account" value="{{bindMobile}}" type="text"
placeholder="邮箱/手机号码" autocomplete="off">
<li class="relative password-login">
<input id="account1" class="account input va" name="account" value="{{bindMobile}}"
type="text"
placeholder="邮箱/手机号码" autocomplete="off">
<span class="err-tip hide">
<i></i>
<em></em>
</span>
</li>
<li class="relative password-login">
<input id="password" class="password input va" name="password" type="password" placeholder="密码"
autocomplete="off" maxlength="20">
<span id="caps-lock" class="caps-lock hide">大写状态开启</span>
</li>
<li class="relative password-login">
<input id="password" class="password input va" name="password" type="password"
placeholder="密码"
autocomplete="off" maxlength="20">
<span id="caps-lock" class="caps-lock hide">大写状态开启</span>
<span class="err-tip hide">
<i></i>
<em>请输入密码</em>
</span>
</li>
</li>
<li class="relative clearfix sms-login hide">
<input id="account2" class="account input va" name="account2" value="{{bindMobile}}" type="text"
placeholder="手机号码" autocomplete="off">
<li class="relative clearfix sms-login hide">
<input id="account2" class="account input va" name="account2" value="{{bindMobile}}"
type="text"
placeholder="手机号码" autocomplete="off">
<span class="err-tip hide">
<i></i>
<em></em>
</span>
</li>
</li>
<li class="relative clearfix sms-login hide">
<input id="captcha-sms" class="input va captcha-sms-input" type="text" name="captcha"
placeholder="短信验证码"
autocomplete="off" maxlength="4">
<div class="change-captcha-sms btn">获取短信验证码</div>
<li class="relative clearfix sms-login hide">
<input id="captcha-sms" class="input va captcha-sms-input" type="text" name="captcha"
placeholder="短信验证码"
autocomplete="off" maxlength="4">
<div class="change-captcha-sms btn">获取短信验证码</div>
<span class="err-tip hide">
<i></i>
<em></em>
</span>
</li>
</li>
<li class="clearfix captcha-wrap hide">
<input id="captcha" class="input va captcha" type="text" name="captcha" placeholder="图形验证码"
autocomplete="off" maxlength="4">
<img id="captcha-img" class="captcha-img" alt="">
<a class="link change-captcha">换一张</a>
<li class="clearfix captcha-wrap hide">
<input id="captcha" class="input va captcha" type="text" name="captcha" placeholder="图形验证码"
autocomplete="off" maxlength="4">
<img id="captcha-img" class="captcha-img" alt="">
<a class="link change-captcha">换一张</a>
<span class="err-tip hide">
<i></i>
<em></em>
</span>
</li>
</li>
<li>
<span id="login-btn" class="login-btn btn">登录</span>
</li>
<li class="other-opts">
<li class="desktop-login">
<span id="login-btn" class="login-btn btn">登录</span>
</li>
<li class="other-opts">
<span class="remember-me">
<i class="iconfont">&#xe613;</i>
记住登录状态
... ... @@ -89,30 +101,67 @@
|
<a class="fast-reg" href="{{fastReg}}">快速注册</a>
</span>
</li>
<li class="third-party-login">
<a href="{{weixinLogin}}">
<span class="icon weixin"></span>
</a>
<a href="{{qqLogin}}">
<span class="icon qq"></span>
</a>
<a href="{{weiboLogin}}">
<span class="icon weibo"></span>
</a>
<a href="{{alipayLogin}}">
<span class="icon alipay"></span>
</a>
<a href="{{doubanLogin}}">
<span class="icon douban"></span>
</a>
<a href="{{renrenLogin}}">
<span class="icon renren"></span>
</a>
</li>
</li>
<li class="third-party-login">
<a href="{{weixinLogin}}">
<span class="icon weixin"></span>
</a>
<a href="{{qqLogin}}">
<span class="icon qq"></span>
</a>
<a href="{{weiboLogin}}">
<span class="icon weibo"></span>
</a>
<a href="{{alipayLogin}}">
<span class="icon alipay"></span>
</a>
<a href="{{doubanLogin}}">
<span class="icon douban"></span>
</a>
<a href="{{renrenLogin}}">
<span class="icon renren"></span>
</a>
</li>
</div>
<div class="mobile-login hide">
<li class="relative clearfix center qrcode-login-title">
<div>
手机扫码,安全登录
</div>
</li>
<li class="relative clearfix center">
<div id="qrcode-placeholder" style="width: 270px;height: 140px;"></div>
<div id="qrcode-container" class="qrcode"></div>
<div id="qrcode-helper" class="qrcode-helper hide"></div>
<div id="qrcode-hover" class="qrcode-hover"></div>
<div id="qrcode-overlay"></div>
</li>
<li class="relative clearfix">
<div>
<i class="scan"></i>
<p class="scan-font">打开手机Yoho!Buy有货</p>
<p class="scan-font">扫一扫登录</p>
</div>
</li>
<li class="relative clearfix center">
<div>
<a class="download-link"
href="http://www.yohobuy.com/download/app">下载Yoho!Buy有货手机APP</a>
</div>
</li>
</div>
</ul>
<input id="country-code-hide" name="countryCode" type="hidden" value="{{countryCode}}">
<input id="captcha-sms-token-hide" name="token" type="hidden">
<input id="qrcode" name="qrcode" type="hidden" value="//m.yohobuy.com/signin.html">
<input id="uid" type="hidden">
</div>
</form>
{{/ passport}}
... ...
... ... @@ -14,7 +14,6 @@ const detailHelper = require(`${mRoot}/detail-helper`);
const Actions = require('./lib/actions');
const YohoAction = require('./lib/yoho-action');
const moment = require('moment');
const camelCase = global.yoho.camelCase;
const DEFAULT_AVATAR_ICO = 'http://static.yohobuy.com/images/v3/boy.jpg';
const _ = require('lodash');
... ... @@ -27,8 +26,6 @@ class DetailAction extends YohoAction {
let pid = req.params[0];
let gid = req.params[1];
let uid = req.user.uid || '';
let vipLevel = detailHelper.vipLevel(req.user.vip);
let saveCurrentGoodsInCookies = _.partial(service.saveRecentGoodInCookies,
req.cookies._browse,
req.cookies._browseskn,
... ... @@ -40,9 +37,9 @@ class DetailAction extends YohoAction {
gid: gid,
channel: this.getSessionChannel(),
gender: this.guessUserGender(),
uid: uid,
isStudent: req.user.isStudent,
vipLevel: vipLevel,
uid: null,
isStudent: null,
vipLevel: null,
saveInCookies: saveCurrentGoodsInCookies
}).then(result=> {
const seo = result.seo;
... ... @@ -94,7 +91,7 @@ class CommentAction extends YohoAction {
this.response.json({
code: result.code,
data: camelCase(_.get(pageResponse, 'list', [])).map((item)=> {
data: _.get(pageResponse, 'list', []).map((item)=> {
return {
avatar: _.get(item, 'userInfo.headIco', '') ?
... ... @@ -102,8 +99,8 @@ class CommentAction extends YohoAction {
DEFAULT_AVATAR_ICO,
userName: _.get(item, 'userInfo.nickName', ''),
date: moment(item.createTime, 'X').format('YYYY-MM-DD HH:mm:ss'),
color: _.get(item, 'goods.colorName', ''),
size: _.get(item, 'goods.sizeName', ''),
color: _.get(item, 'goods.color_name', ''),
size: _.get(item, 'goods.size_name', ''),
comment: item.content,
total: pageResponse.totalCount
};
... ... @@ -171,12 +168,29 @@ class CreateConsultAction extends YohoAction {
}
}
const detailHeader = (req, res, next) => {
let pid = req.query.productId || 0;
let uid = req.user.uid || 0;
let vipLevel = detailHelper.vipLevel(req.user.vip);
let dataMd5 = req.query.md5 || 0;
service.getDetailHeader(pid, uid, req.user.isStudent, vipLevel, dataMd5).then((result) => {
if (result.code === 200) {
return res.render('product/detail-header', Object.assign({layout: false}, result.data));
} else {
return res.status(204).end();
}
}).catch(next);
};
module.exports = {
showMain: Actions.createAction(DetailAction),
indexHotArea: Actions.createAction(HotAreaAction),
indexComment: Actions.createAction(CommentAction),
indexConsult: Actions.createAction(ConsultAction),
createConsult: Actions.createAction(CreateConsultAction)
createConsult: Actions.createAction(CreateConsultAction),
productHeader: detailHeader
};
... ...
... ... @@ -6,6 +6,7 @@
const helpers = global.yoho.helpers;
const brandService = require('../models/favorite-brand-service');
const productService = require('../models/favorite-product-service');
const fav = require('../models/favorite');
/**
* 收藏品牌ajax请求
... ... @@ -85,7 +86,36 @@ const collectProduct = (req, res, next) => {
}
};
const collectShop = (req, res, next) => {
let uid = req.user.uid || '';
let shopId = req.body.shopId;
let isadd = req.body.isFavorite * 1 ? true : false;
// needColloect 说明刚登录状态 是cookie传的值
if (req.body.needColloect * 1 === 1) {
isadd = true;
}
if (!uid) {
res.json({
code: 401,
message: '用户没有登录',
data: {url: helpers.urlFormat('/signin.html')}
});
} else if (!shopId) {
res.json({
code: 400,
message: '收藏失败'
});
} else {
fav.toggleFavShop(shopId, uid, isadd).then(result => {
res.json(result);
}).catch(next);
}
};
module.exports = {
changeFavoriteBrand,
collectProduct
collectProduct,
collectShop
};
... ...
/*
* @Author: Targaryen
* @Date: 2016-05-21 10:59:20
* @Last Modified by: Targaryen
* @Last Modified time: 2016-06-08 13:37:17
* @Author: sefon
* @Date: 2016-07-24 11:40:21
*/
'use strict';
const mRoot = '../models';
// list 页 model
const list = require(`${mRoot}/list`);
const headerModel = require('../../../doraemon/models/header');
const helpers = global.yoho.helpers;
// 搜索相关接口
const searchApi = require(`${mRoot}/search-api`);
exports.getProductPic = (req, res) => {
// 店铺页
const shop = (shopId, req, res, next, brandInfo) => {
shopId = parseInt(shopId, 10);
res.jsonp();
list.getShopInfo(shopId, req.user.id).then(shopInfo => {
if (+shopInfo.shopTemplateType === 2) { // 经典模板
list.getShopData(shopId, req.yoho.channel, req.query, shopInfo).then(result => {
Object.assign(result, {
page: 'shop',
shopId: shopId
});
res.render('list/shop-index', result);
}).catch(next);
} else { // 基础模板
list.getBaseShopData(req.query, Object.assign({uid: req.user.uid}, brandInfo),
req.yoho.channel, shopId).then(result => {
Object.assign(result, {page: 'list'});
res.render('list/brand', result);
}).catch(next);
}
}).catch(next);
};
/**
* 商品列表页
* 商品分类列表页
* @param {[type]} req [description]
* @param {[type]} res [description]
* @return {[type]} [description]
*/
exports.index = (req, res, next) => {
let params = Object.assign({
order: 's_t_asc,s_s_asc'
}, req.query);
let resData = {};
list.getListData(req.query, req.yoho.channel).then(result => {
Object.assign(resData, result);
res.render('list/index', resData);
}).catch(next);
};
/**
* 新品到着
* @param {[type]} req [description]
* @param {[type]} res [description]
* @return {[type]} [description]
*/
exports.new = (req, res, next) => {
let resData = {};
list.getListNewData(Object.assign({order: 's_t_desc'}, req.query), req.yoho.channel).then(result => {
Object.assign(resData, result);
res.render('list/index', resData);
}).catch(next);
};
/**
* 品牌页
* @param {[type]} req [description]
* @param {[type]} res [description]
* @return {[type]} [description]
*/
exports.brand = (req, res, next) => {
let brandDomain = req.params.brandDomain;
let shopId = req.query.shopId;
let resData = {};
if (!brandDomain) {
return next();
}
// shopId存在,直接走店铺
if (shopId) {
return shop(shopId, req, res, next);
}
// 获取品牌信息
list.getBrandInfo({domain: brandDomain}).then(brandInfo => {
if (!brandInfo.hasOwnProperty('type')) {
return res.redirect(helpers.urlFormat(''));
}
switch (parseInt(brandInfo.type, 10)) {
case 1: // 搜索
res.redirect(helpers.urlFormat('', {query: brandInfo.brandDomain}, 'search'));
break;
case 2: // 店铺
return shop(brandInfo.shopId, req, res, next, brandInfo);
default: // 品牌
return list.getBrandData(req.query, Object.assign({uid: req.user.uid}, brandInfo),
req.yoho.channel).then(result => {
Object.assign(resData, result, {
page: 'list'
});
res.render('list/brand', resData);
});
}
}).catch(next);
};
/**
* 品牌介绍页
* @param {[type]} req [description]
* @param {[type]} res [description]
* @return {[type]} [description]
*/
exports.brandAbout = (req, res, next) => {
let brandDomain = req.params.brandDomain;
let shopId = req.query.shopId;
if (!brandDomain) {
return res.redirect(helpers.urlFormat(''));
}
let channel = req.query.channel || req.cookies._Channel || 'boys';
if (shopId) {
list.getShopAbout(shopId, req.user.uid).then(result => {
res.render('list/brand', Object.assign(result, {page: 'list'}));
}).catch(next);
} else {
list.getBrandAbout(brandDomain, req.user.uid, req.yoho.channel).then(result => {
res.render('list/brand', Object.assign(result, {page: 'list'}));
}).catch(next);
}
};
/**
* 店铺商品列表页
* @param {[type]} req [description]
* @param {[type]} res [description]
* @return {[type]} [description]
*/
exports.shopList = (req, res, next) => {
let shopId = req.query.shopId;
if (!shopId) {
return next();
}
list.getShopListData(req.yoho.channel, req.query).then(result => {
Object.assign(result, {
page: 'shop',
shopId: shopId
});
if (req.query.query) {
result.shopKey = req.query.query;
}
res.render('list/shop-list', result);
}).catch(next);
};
params.uid = req.user.uid || 0;
/**
* ajax调用品牌页左侧水牌
* @param {[type]} req [description]
* @param {[type]} res [description]
* @return {[type]} [description]
*/
exports.getNodeContent = (req, res, next) => {
let responseData = {
module: 'product',
page: 'sale',
footerTop: true
};
if (!req.xhr || !req.body.node) {
return next();
}
list.getNodeContentData(req.body).then(result => {
res.json(result);
}).catch(next);
};
let headerData = {};
/**
* ajax调用品牌页左侧series folder
* @param {[type]} req [description]
* @param {[type]} res [description]
* @return {[type]} [description]
*/
exports.getAdnav = (req, res, next) => {
headerModel.requestHeaderData(channel).then(result => {
headerData = result.headerData;
});
if (!req.xhr || !req.body.brandId) {
return next();
}
list.getSaleOthersData(params, channel).then((result) => {
responseData.saleList = result;
responseData.resultShow = JSON.stringify(result, null, 4);
responseData.headerData = headerData;
res.render('sale/other', responseData);
list.getAdnav(req.body).then(result => {
res.json(result);
}).catch(next);
};
/**
* 判断用户是否收藏品牌页
* @param {[type]} req [description]
* @param {[type]} res [description]
* @return {[type]} [description]
*/
exports.isFavoriteBrand = (req, res, next) => {
let uid = req.user.uid;
let brandId = req.body.brandId;
if (!req.xhr) {
return next();
}
if (!req.body.brandId || !uid) {
return res.json({code: 400, message: '用户未登录或缺少参数'});
}
searchApi.isFavoriteBrand(uid, brandId).then(result => {
res.json(result);
}).catch(next);
};
... ...
... ... @@ -17,18 +17,14 @@ const _ = require('lodash');
* @return {[type]} [description]
*/
exports.index = (req, res, next) => {
let resData = {
module: 'product',
page: 'outlets'
};
let channel = req.query.channel || req.cookies._Channel || 'otltIdxDflt';
outlets.getOutletsIndexData(req.query, channel).then(result => {
Object.assign(resData, result);
res.render('outlets/index', resData);
outlets.getOutletsIndexData(req.query, channel).then((result) => {
res.render('outlets/index', Object.assign({
module: 'product',
page: 'outlets'
}, result));
}).catch(next);
};
/**
... ... @@ -38,14 +34,13 @@ exports.index = (req, res, next) => {
* @return {[type]} [description]
*/
exports.channel = (req, res, next) => {
let resData = {
module: 'product',
page: 'outlets'
};
let channel = req.params.channel || req.query.channel || req.cookies._Channel || 'boys';
outlets.getOutletsChannelData(req.query, channel).then(result => {
res.render('outlets/channel', Object.assign(resData, result));
outlets.getOutletsChannelData(req.query, channel).then((result) => {
res.render('outlets/channel', Object.assign({
module: 'product',
page: 'outlets'
}, result));
}).catch(next);
};
... ... @@ -58,10 +53,6 @@ exports.channel = (req, res, next) => {
exports.special = (req, res, next) => {
let params = req.query;
let channel = req.query.channel || req.cookies._Channel || 'boys';
let resData = {
module: 'product',
page: 'outlets'
};
// 判断活动id是否合法
if (!params.id || !+params.id || !_.isNumber(+params.id)) {
... ... @@ -69,7 +60,10 @@ exports.special = (req, res, next) => {
}
outlets.getOutletsSpecialData(params, channel).then(result => {
res.render('outlets/special', Object.assign(resData, result));
res.render('outlets/special', Object.assign({
module: 'product',
page: 'outlets'
}, result));
}).catch(next);
};
... ... @@ -81,18 +75,15 @@ exports.special = (req, res, next) => {
*/
exports.list = (req, res, next) => {
let params = req.query;
let channel = req.query.channel || req.cookies._Channel || 'boys';
params.uid = req.user.uid || 0;
let responseData = {
module: 'product',
page: 'outlets'
};
outlets.getOutletsCategoryData(params, channel).then((result) => {
res.render('sale/other', Object.assign(responseData, result));
res.render('sale/other', Object.assign({
module: 'product',
page: 'outlets'
}, result));
}).catch(next);
};
... ...
/*
* @Author: Targaryen
* @Date: 2016-05-21 10:59:20
* @Last Modified by: Targaryen
* @Last Modified time: 2016-06-08 13:37:17
*/
'use strict';
const mRoot = '../models';
// list 页 model
const list = require(`${mRoot}/outletsList`);
const headerModel = require('../../../doraemon/models/header');
exports.getProductPic = (req, res) => {
res.jsonp();
};
/**
* 商品列表页
* @param {[type]} req [description]
* @param {[type]} res [description]
* @return {[type]} [description]
*/
exports.index = (req, res, next) => {
let params = Object.assign({
order: 's_t_asc,s_s_asc'
}, req.query);
let channel = req.query.channel || req.cookies._Channel || 'boys';
params.uid = req.user.uid || 0;
let responseData = {
module: 'product',
page: 'sale',
footerTop: true
};
let headerData = {};
headerModel.requestHeaderData(channel).then(result => {
headerData = result.headerData;
});
list.getListData(params, channel).then((result) => {
responseData.saleList = result;
responseData.resultShow = JSON.stringify(result, null, 4);
responseData.headerData = headerData;
res.render('sale/other', responseData);
}).catch(next);
};
... ...
... ... @@ -18,20 +18,16 @@ const sale = require(`${mRoot}/sale`); // sale 页 model
exports.index = (req, res, next) => {
let channel = req.query.channel || req.cookies._Channel || 'boys';
let responseData = {
module: 'product',
page: 'sale'
};
// 真实数据输出
sale.getSaleIndexData(channel).then(result => {
responseData.result = result;
if (result) {
responseData.headerData = result.headerData;
}
res.render('sale/index', responseData);
res.render('sale/index', Object.assign({
module: 'product',
page: 'sale'
}, {
result: result,
headerData: result.headerData
}));
}).catch(next);
};
/**
... ... @@ -76,17 +72,14 @@ exports.vip = (req, res, next) => {
params.uid = req.user.uid || 0;
let responseData = {
module: 'product',
page: 'sale'
};
sale.getSaleOthersData(params, channel).then((result) => {
responseData.saleList = result;
if (result) {
responseData.headerData = result.headerData;
}
res.render('sale/other', responseData);
res.render('sale/other', Object.assign({
module: 'product',
page: 'sale'
}, {
saleList: result,
headerData: result.headerData
}));
}).catch(next);
};
... ... @@ -104,17 +97,14 @@ exports.newSale = (req, res, next) => {
let channel = req.query.channel || req.cookies._Channel || 'boys';
let responseData = {
module: 'product',
page: 'sale'
};
sale.getSaleOthersData(params, channel).then((result) => {
responseData.saleList = result;
if (result) {
responseData.headerData = result.headerData;
}
res.render('sale/other', responseData);
res.render('sale/other', Object.assign({
module: 'product',
page: 'sale'
}, {
saleList: result,
headerData: result.headerData
}));
}).catch(next);
};
... ... @@ -146,6 +136,26 @@ exports.breakingYards = (req, res, next) => {
};
/**
* 活动
* @param {[type]} req [description]
* @param {[type]} res [description]
* @return {[type]} [description]
*/
exports.special = (req, res, next) => {
let params = req.query;
let specialId = params.specialsale_id || params.specialsaleId, // 专区ID
promotion = params.promotion; // 促销ID
if (!specialId && !promotion) {
return next();
}
sale.getSaleSpecialData(specialId, params, req.yoho.channel).then(result => {
res.render('sale/special', result);
}).catch(next);
};
/**
* Ajax 获取商品列表
* @param {[type]} req [description]
* @param {[type]} res [description]
... ... @@ -156,7 +166,7 @@ exports.getGoodsList = (req, res, next) => {
params.uid = req.user.uid || 0;
return sale.getSaleGoodsData(params).then(result => {
sale.getSaleGoodsData(params).then(result => {
let responseData = {};
responseData.footerTop = false;
... ...
/**
* 商品搜索controller
* @author: sefon
* @date: 2016-7-12 10:09:25
*/
'use strict';
const mRoot = '../models';
const search = require(`${mRoot}/search`);
const _ = require('lodash');
/**
* search 首页
* @param {[type]} req [description]
* @param {[type]} res [description]
* @return {[type]} [description]
*/
exports.index = (req, res, next) => {
let resData = {
title: '潮流商品搜索 | YOHO!BUY 有货',
keywords: 'Yoho! 有货,潮流,时尚,流行,购物,B2C,正品,购物网站,网上购物,货到付款,' +
'品牌服饰,男士护肤,黑框眼镜,匡威,板鞋,i.t,izzue,5cm,eastpak,vans,lylescott,g-shock,' +
'new balance,lacoste,melissa,casio,卡西欧手表,舒雅,jasonwood,odm,AAAA,香港购物,日本潮流',
description: '潮流商品搜索,上衣,衬衫,TEE,卫衣,冲锋衣,风衣,羽绒服,裤子,休闲鞋,板鞋,配饰,复古眼镜'
};
search.getSearchData(req.query, req.yoho.channel).then(result => {
Object.assign(resData, result);
if (!_.get(resData, 'search.goods') || !_.get(resData, 'search.goods').length) {
_.set(resData, 'search.keyWord', req.query.query);
return res.render('search/no-result', resData);
}
res.render('search/index', resData);
}).catch(next);
};
/**
* search 提示
* @param {[type]} req [description]
* @param {[type]} res [description]
* @return {[type]} [description]
*/
exports.suggest = (req, res, next) => {
search.getSuggest(req.query).then(result => {
let dest = {
code: 200,
message: 'suggest',
data: result || ''
};
res.type('text/javascript');
res.send(req.query.callback + '(' + JSON.stringify(dest) + ')');
}).catch(next);
};
exports.suggest4Old = (req, res, next) => {
search.getSuggest(Object.assign({}, req.query, { keyword: req.query.query })).then(result => {
let dest = {
code: 200,
message: 'suggest'
};
let data = [];
if (result) {
for (let it of result) {
let item = '<li>' +
`<a style="display: block;" href="${it.href}" class="clearfix clear search-item" title="${it.keyword}" act="${it.href}">` + // eslint-disable-line
`<span class="searchvalue" >${it.keyword}</span><span class="valuenum">约${it.count}个商品</span>` + // eslint-disable-line
'</a>' +
'</li>';
data.push(item);
}
}
dest.data = data;
res.send(req.query.callback + '(' + JSON.stringify(dest) + ')');
}).catch(next);
};
exports.serachFilterBrands = (req, res, next) => {
search.getBrands4Filter(Object.assign({}, req.query, {
keyword: req.query.query
})).then(result => {
let dest = {
code: 200,
data: result || ''
};
res.type('text/javascript');
res.send(req.query.callback + '(' + JSON.stringify(dest) + ')');
}).catch(next);
};
... ...
... ... @@ -6,12 +6,10 @@
const api = global.yoho.API;
const getProductBannerAsync = (pid, clientType) => {
clientType = clientType || 'web';
const getProductBannerAsync = (pid) => {
return api.get('', {
method: 'web.productBanner.data',
product_id: pid,
client_type: clientType
product_id: pid
});
};
... ... @@ -61,8 +59,8 @@ const getProductModelTryAsync = skn => {
*/
const getProductAsync = (pid, uid, isStudents, vipLevel) => {
let params = {
method: 'h5.product.data',
productId: pid
method: 'app.product.data',
product_id: pid
};
if (uid) {
... ... @@ -79,6 +77,15 @@ const getProductAsync = (pid, uid, isStudents, vipLevel) => {
return api.get('', params);
};
const getPromotionAsync = (skn) => {
let params = {
method: 'app.product.promotion',
product_skn: skn
};
return api.get('', params);
};
module.exports = {
getProductBannerAsync,
sizeInfoAsync,
... ... @@ -86,8 +93,6 @@ module.exports = {
getProductModelCardAsync,
getProductModelTryAsync,
getProductAsync,
getPromotionAsync,
isSupportReturnedSale
};
... ...
... ... @@ -8,12 +8,12 @@
const Promise = require('bluebird');
const co = Promise.coroutine;
const moment = require('moment');
const url = require('url');
const _ = require('lodash');
const url = require('url');
const helpers = global.yoho.helpers;
const productAPI = require('./detail-product-api');
const detailHelper = require('./detail-helper');
const consultService = require('./detail-consult-service');
const commentService = require('./detail-comment-service');
... ... @@ -29,49 +29,31 @@ const HeaderModel = require('../../../doraemon/models/header');
const BLANK_STR = ' ';
const cachedRequestData = {};
// 展览票
const EXHIBITION_TICKET = 51335912;
const _getProductAdditionInfoAsync = (data) => {
return co(function * () {
let productId = data.id || 0;
let skn = data.erpProductId;
let brandId = data.brand && data.brand.id ? data.brand.id : 0;
let index = 0;
let productId = _.get(data, 'product_id', 0);
let productSkn = _.get(data, 'product_skn', 0);
let brandId = _.get(data, 'brand_info.brand_id', 0);
// 获取相关数据
let promiseData = [
productAPI.getProductBannerAsync(productId, 'web'),
productAPI.sizeInfoAsync(skn),
productAPI.getProductComfortAsync(productId),
productAPI.getProductModelCardAsync(productId),
productAPI.getProductModelTryAsync(skn),
brandService.getBannerInfoAsync(brandId)
];
let promiseData = {
productBanner: productAPI.getProductBannerAsync(productId),
sizeInfo: productAPI.sizeInfoAsync(productSkn),
productComfort: productAPI.getProductComfortAsync(productId),
productModelCard: productAPI.getProductModelCardAsync(productId),
productModelTry: productAPI.getProductModelTryAsync(productSkn),
bannerInfo: brandService.getBannerInfoAsync(brandId)
};
let result = yield Promise.all(promiseData);
[
'ItemData::getProductBanner',
'ItemData::sizeInfo',
'ItemData::getProductComfort',
'ItemData::getProductModelCard',
'ItemData::getProductModelTry',
'BrandData::getBannerInfo'
].forEach(key => {
cachedRequestData[key] = result[index++];
});
let result = yield Promise.props(promiseData);
return null;
return result;
})();
};
const _getCacheDataByName = (resourceName) => {
return cachedRequestData[resourceName] || false;
};
/**
* 获取商品的喜欢
* pid : product id
... ... @@ -108,8 +90,8 @@ const _getProductFavoriteDataAsync = (uid, pid, bid) => {
const _getTagsDataByProductInfo = (data) => {
let tags = {};
_.get(data, 'productTagBoList', []).forEach((value) => {
switch (value.tagLabel) {
_.get(data, 'tags', []).forEach((value) => {
switch (value) {
case 'is_soon_sold_out': // 即将售磬
tags.isFew = true;
break;
... ... @@ -128,12 +110,14 @@ const _getTagsDataByProductInfo = (data) => {
case 'is_advance': // 再到着
tags.isReNew = true;
break;
case 'midYear':// 年中热促
case 'mid_year':// 年中热促
tags.isYearMidPromotion = true;
break;
case 'yearEnd':// 年终大促
case 'year_end':// 年终大促
tags.isYearEndPromotion = true;
break;
default:
break;
}
});
... ... @@ -145,7 +129,7 @@ const _getVipDataByProductBaseInfo = (data, vipLevel, uid) => {
vipLevel = vipLevel || 0;
uid = uid || 0;
if (_.isEmpty(_.get(data, 'productPriceBo.vipPrices', []))) {
if (_.isEmpty(_.get(data, 'vip', []))) {
return null;
}
... ... @@ -160,11 +144,10 @@ const _getVipDataByProductBaseInfo = (data, vipLevel, uid) => {
vipData.normalUser = isNormalUser();
if (isVipUser()) {
vipData.prices = data.productPriceBo.vipPrices.map(value => ({
level: value.vipLevel,
price: value.vipPrice,
name: value.vipTitle,
cur: value.vipLevel === vipLevel
vipData.prices = data.vip.map(value => ({
price: value.price,
name: value.caption,
cur: detailHelper.vipLevel(value.caption + '会员') === vipLevel
}));
}
... ... @@ -176,10 +159,10 @@ const _getVipDataByProductBaseInfo = (data, vipLevel, uid) => {
};
// 活动
const _getProductActivityBanner = () => {
let data = _getCacheDataByName('ItemData::getProductBanner');
const _getProductActivityBanner = (additionalData) => {
let data = additionalData.productBanner;
if (_.get(data, 'code', 400) !== 200 || !_.get(data, 'data.bannerImg')) {
if (_.isElement(data) || _.get(data, 'code', 400) !== 200 || !_.get(data, 'data.bannerImg')) {
return {};
}
... ... @@ -189,18 +172,18 @@ const _getProductActivityBanner = () => {
};
};
const _getActivityDataByProductBaseInfo = (data) => {
const _getActivityDataByProductBaseInfo = (data, additionalData) => {
let result = [];
let activityBanner = _getProductActivityBanner();
let activityBanner = _getProductActivityBanner(additionalData);
if (!_.isEmpty(activityBanner)) {
result.push(activityBanner);
}
_.get(data, 'promotionBoList', []).forEach(value => {
_.get(data, 'data', []).forEach(value => {
result.push({
type: value.promotionType.replace('¥', '¥'),
des: value.promotionTitle.replace('¥', '¥')
type: value.promotionType.replace(/¥/g, '¥'),
des: value.promotionTitle.replace(/¥/g, '¥')
});
});
... ... @@ -211,53 +194,32 @@ const _getActivityDataByProductBaseInfo = (data) => {
* 获取商品咨询和评论数据
* @param data
*/
const _getConsultCommentDataByProductInfo = (data) => {
if (_.isEmpty(data)) {
return {};
}
// 商品咨询
let consultComment = {};
consultComment.consultNum = 0;
consultComment.captchaUrl = helpers.urlFormat('/passport/images', {
t: moment().unix()
});
if (data.consultBoWrapper) {
consultComment.consults = [];
}
// 商品评价
consultComment.commentNum = 0;
if (data.commentBoWrapper) {
consultComment.comments = [];
consultComment.commentUrl = helpers.urlFormat('/home/comment');
}
return consultComment;
const _getConsultCommentDataByProductInfo = () => {
return {
commentUrl: helpers.urlFormat('/home/comment')
};
};
/**
* 获取品牌数据
*/
const _getBrandDataByProductBaseInfo = (data) => {
if (!data.brand) {
const _getBrandDataByProductBaseInfo = (data, additionalData) => {
if (!data.brand_info) {
return {};
}
let brandId = data.brand.id;
let brandId = data.brand_info.id;
let bgImg = '';
let logo = '';
let bannerInfo = null;
let result = _getCacheDataByName('BrandData::getBannerInfo');
let result = additionalData.bannerInfo;
if (!result) {
if (_.isEmpty(result)) {
return {};
}
if (_.get(data, 'brand.brandIco')) {
logo = helpers.getForceSourceUrl(data.brand.brandIco);
if (_.get(data, 'brand_info.brand_ico')) {
logo = helpers.getForceSourceUrl(data.brand_info.brand_ico);
}
if (result.code && result.code === 200 && result.data) {
... ... @@ -272,10 +234,10 @@ const _getBrandDataByProductBaseInfo = (data) => {
logo = helpers.getForceSourceUrl(bannerInfo.logo);
}
let homeUrl = 'javascript:void(0)';
let homeUrl = 'javascript:void(0)'; // eslint-disable-line no-script-url
if (data.brand.brandDomain) {
homeUrl = helpers.urlFormat('', null, data.brand.brandDomain);
if (data.brand_info.brand_domain) {
homeUrl = helpers.urlFormat('', null, data.brand_info.brand_domain);
}
// 导航的品牌banner
... ... @@ -284,9 +246,9 @@ const _getBrandDataByProductBaseInfo = (data) => {
bgColor: bannerInfo && bannerInfo.colorValue ? bannerInfo.colorValue : '#000000',
bgImg: bgImg,
logo: logo,
alt: data.brand.brandName,
brandName: data.brand.brandName,
brandDomain: data.brand.brandDomain,
alt: data.brand_info.brand_name,
brandName: data.brand_info.brand_name,
brandDomain: data.brand_info.brand_domain,
homeUrl: homeUrl
};
};
... ... @@ -300,86 +262,92 @@ const _getSkuDataByProductBaseInfo = (data) => {
let defaultImage = '';// 默认图
let chooseSkuFlag = false; // 选中状态
if (data.goodsList) {
skuGoods = _.get(data, 'goodsList', []).reduce((acc, cur, pos)=> {
if (!data.goods_list) {
return {
totalStorageNum,
skuGoods,
defaultImage
};
}
// 如果status为0,即skc下架时就跳过该商品$value['status'] === 0
let goodsGroup = {};
skuGoods = _.get(data, 'goods_list', []).reduce((acc, cur, pos)=> {
if (_.isEmpty(cur.colorImage)) {
return acc;
}
// 如果status为0,即skc下架时就跳过该商品$value['status'] === 0
let goodsGroup = {};
if (cur.goodsImagesList) {
// 商品列表
goodsGroup.productSkc = cur.productSkc;
goodsGroup.src = helpers.image(cur.colorImage, 40, 40);
goodsGroup.title = `${_.trim(data.productName)} ${cur.colorName}`;
goodsGroup.name = cur.colorName;
goodsGroup.focus = false;
goodsGroup.total = 0;
goodsGroup.thumbs = [];
goodsGroup.size = [];
}
if (_.isEmpty(cur.color_image)) {
return acc;
}
_.get(cur, 'goodsImagesList', []).forEach(good => {
if (good.imageUrl) {
goodsGroup.thumbs.push({
url: '',
shower: helpers.image(good.imageUrl, 420, 560),
img: helpers.image(good.imageUrl, 75, 100)
});
}
});
if (cur.images_list) {
// 商品列表
goodsGroup.productSkc = cur.product_skc;
goodsGroup.src = helpers.image(cur.color_image, 40, 40);
goodsGroup.title = `${_.trim(data.product_name)} ${cur.color_name}`;
goodsGroup.name = cur.color_name;
goodsGroup.focus = false;
goodsGroup.total = 0;
goodsGroup.thumbs = [];
goodsGroup.size = [];
}
// 缩略图空,不显示
if (_.isEmpty(goodsGroup.thumbs)) {
return acc;
_.get(cur, 'images_list', []).forEach((good) => {
if (good.image_url) {
goodsGroup.thumbs.push({
url: '',
shower: helpers.image(good.image_url, 420, 560),
img: helpers.image(good.image_url, 75, 100)
});
}
});
// 默认第一张图片
if (pos === 0) {
defaultImage = helpers.image(cur.colorImage, 420, 560);
}
// 缩略图空,不显示
if (_.isEmpty(goodsGroup.thumbs)) {
return acc;
}
// 商品的尺码列表
_.get(cur, 'goodsSizeBoList', []).forEach((size) => {
if (data.attribute === 3) {
// 虚拟商品,门票默认最大为4,
size.goodsSizeStorageNum = size.goodsSizeStorageNum > 4 ? 4 : size.goodsSizeStorageNum;
}
// 默认第一张图片
if (pos === 0) {
defaultImage = helpers.image(cur.color_image, 420, 560);
}
// 如果status为0,即skc下架时就跳过该商品
if (cur.status === 0) {
size.goodsSizeStorageNum = 0;
}
// 商品的尺码列表
_.get(cur, 'size_list', []).forEach((size) => {
if (data.attribute === 3) {
// 虚拟商品,门票默认最大为4,
size.storage_number = size.storage_number > 4 ? 4 : size.storage_number;
}
goodsGroup.size.push({
name: size.sizeName,
sku: size.goodsSizeSkuId,
num: parseInt(size.goodsSizeStorageNum),
goodsId: size.goodsId
});
// 如果status为0,即skc下架时就跳过该商品
if (cur.status === 0) {
size.storage_number = 0;
}
// 单个sku商品的总数
goodsGroup.total += parseInt(size.goodsSizeStorageNum);
goodsGroup.size.push({
name: size.size_name,
sku: size.product_sku,
num: _.parseInt(size.storage_number),
goodsId: size.size_id
});
if (goodsGroup.total > 0 && !chooseSkuFlag) { // 默认选中该sku商品
goodsGroup.focus = true;
chooseSkuFlag = true;// 选中sku商品
}
// 单个sku商品的总数
goodsGroup.total += _.parseInt(size.storage_number);
totalStorageNum += parseInt(size.goodsSizeStorageNum);
if (goodsGroup.total > 0 && !chooseSkuFlag) { // 默认选中该sku商品
goodsGroup.focus = true;
chooseSkuFlag = true;// 选中sku商品
}
});
totalStorageNum += _.parseInt(size.storage_number);
acc.push(goodsGroup);
return acc;
}, []);
});
if (!_.isEmpty(skuGoods) && !chooseSkuFlag) { // 没有选中一个sku商品,默认选中第一个sku商品
_.head(skuGoods).focus = true;
}
acc.push(goodsGroup);
return acc;
}, []);
if (!_.isEmpty(skuGoods) && !chooseSkuFlag) { // 没有选中一个sku商品,默认选中第一个sku商品
_.head(skuGoods).focus = true;
}
return {
... ... @@ -465,9 +433,10 @@ const _getFashionTopGoodsStatus = (uid, showStatus, isBeginSale) => {
if (uid) { // 限购码失效
result.getLimitedCodeDis = true;
}
break;
default:
break;
}
return result;
};
... ... @@ -530,279 +499,19 @@ const saveRecentGoodInCookies = (oldGids, oldSkns, res, addGids, addSkns) => {
});
};
/**
* 详情页数据格式化
* @param origin Object 原始数据
* @return result Object 格式化数据
*/
const _detailDataPkg = (origin, uid, vipLevel) => {
return co(function*() {
let result = {}; // 结果输出
// 商品名称
if (!origin.productName) {
return result;
}
origin.uid = uid;
result.name = origin.productName;
result.skn = origin.erpProductId;
result.productId = origin.id;
result.maxSortId = origin.maxSortId;
result.smallSortId = origin.smallSortId;
result.promotionId = origin.isPromotion;
result.goCartUrl = helpers.urlFormat('/shopping/cart');
let brandId = 0;
if (origin.brand && origin.brand.id) {
brandId = origin.brand.id;
}
let requestData = yield Promise.all([
_getProductAdditionInfoAsync(origin), // 预处理所有的数据
_getProductFavoriteDataAsync(uid, result.productId, brandId) // 处理收藏喜欢数据
]);
let favoriteData = requestData[1];
// 商品标签
result.tags = _getTagsDataByProductInfo(origin);
// 商品促销短语
if (origin.salesPhrase) {
result.saleTip = origin.salesPhrase;
}
// 商品价格
if (origin.productPriceBo) {
result.marketPrice = origin.productPriceBo.formatMarketPrice;
result.hasOtherPrice = true;
result.salePrice = origin.productPriceBo.formatSalesPrice;
if (result.marketPrice === result.salePrice) {
delete result.salePrice;
result.hasOtherPrice = false;
}
}
if (origin.productPriceBo.studentPrice) {
// 学生价
result.studentsPrice = '¥' + origin.productPriceBo.studentPrice.toFixed(2);
} else {
// VIP学生数据
result.vipPrice = _getVipDataByProductBaseInfo(origin, vipLevel, uid);
}
// 促销活动banner,虚拟商品无促销
if (origin.attribute !== 3) {
result.activity = _getActivityDataByProductBaseInfo(origin);
}
const C_VALUE = {
type: '返有货币',
des: '每件返 ',
rest: '个 有货币'
};
do {
if (origin.productPriceBo.yohoCoinNum && origin.productPriceBo.yohoCoinNum !== 0) {
result.activity.push({
type: C_VALUE.type,
des: `${C_VALUE.des}${origin.productPriceBo.yohoCoinNum}${C_VALUE.rest}`
});
break;
}
if (origin.productPriceBo.studentCoinNum && origin.productPriceBo.studentCoinNum !== 0) {
result.activity.push({
type: C_VALUE.type,
des: `${C_VALUE.des}${origin.productPriceBo.studentCoinNum}${C_VALUE.rest}`
});
}
} while (false);
// 上市期
if (origin.expectArrivalTime) {
result.arrivalDate = `${origin.expectArrivalTime}月`;
result.presalePrice = origin.productPriceBo.formatSalesPrice;
delete result.salePrice;
result.hasOtherPrice = false;
}
// 商品咨询和评论数据,当前为空
let consultComment = _getConsultCommentDataByProductInfo(origin);
// 品牌信息
let banner = {};
if (origin.brand) {
result.brandImg = helpers.image(origin.brand.brandIco, 47, 47);
result.brandName = origin.brand.brandName;
result.brandUrl = helpers.urlFormat('', null, origin.brand.brandDomain);
banner = _getBrandDataByProductBaseInfo(origin);
banner.isCollect = favoriteData.brand;
}
// sku商品信息
let skuData = _getSkuDataByProductBaseInfo(origin);
result.img = skuData.defaultImage;
result.colors = skuData.skuGoods;
let totalStorageNum = skuData.totalStorageNum;
// 是否收藏
result.isCollect = favoriteData.product;
if (origin.isLimitBuy === 'Y') {
// 是否开售
let isBeginSale = !!(origin.saleStatus && origin.saleStatus === 1);
// 限购商品有关的展示状态
let showStatus = 1;
if (origin.showStatus) {
showStatus = _.parseInt(origin.showStatus, 10);
}
let fashTopGoods = _getFashionTopGoodsStatus(uid, showStatus, isBeginSale);
result.fashionTopGoods = {
getLimitedCode: fashTopGoods.getLimitedCode, // 限购码状态
hadLimitedCode: fashTopGoods.hadLimitedCode, // 是否已经获取限购码
limitedCodeSoldOut: fashTopGoods.limitedCodeSoldOut, // 限购码是否已经抢光
getLimitedCodeDis: fashTopGoods.getLimitedCodeDis // 限购码是否失效
};
if (fashTopGoods.soldOut) {
result.soldOut = fashTopGoods.soldOut;
totalStorageNum = 0; // 改总数为已售磬
} else {
result.openSoon = fashTopGoods.openSoon; // 即将开售
result.dis = fashTopGoods.dis; // 是否失效
result.buyNow = fashTopGoods.buyNow; // 是否立即购买
}
}
let soldOut = !!(origin.status === 0 || totalStorageNum === 0);
let notForSale = origin.attribute === 2; // 非卖品
let virtualGoods = origin.attribute === 3; // 虚拟商品
if (virtualGoods) {
result.virtualGoods = virtualGoods;
// 是否显示虚拟商品,立即购买按钮
result.isVirtualBtn = soldOut ? false : true;
// 是否展览票
result.isTicket = origin.erpProductId * 1 === EXHIBITION_TICKET;
}
if (!soldOut && !notForSale && !virtualGoods) {
result.addToCart = true;
// 立即购买或者即将开售存在
if (result.buyNow || result.openSoon) {
delete result.addToCart;
}
} else if (notForSale) {
// 非卖品
result.notForSale = true;
} else if (soldOut) {
// 已售磬
result.soldOut = true;
delete result.fashTopGoods;
} else if (virtualGoods) {
// 虚拟商品
result.buyNow = true; // 是否立即购买
result.buyNowBase = helpers.urlFormat('ticket', null, 'shopping');
if (result.salePrice) {
result.advancePrice = result.salePrice; // 先行价格
delete result.salePrice;
}
}
// 去掉即将售罄
if (totalStorageNum || soldOut) {
if (result.tags.isFew) {
delete result.tags.isFew; // 去掉即将售罄
}
}
// 分享相关,产品的链接
result.weixinUrl = origin.productUrl;
result.shareTitle = result.name;
result.shareImg = 'http:' + result.img; // 分享图片必须使用http
result.shareDesc = result.phrase;
// 统计需要的商品信息
let statGoodsInfo = {};
statGoodsInfo.uid = uid;
statGoodsInfo.skn = origin.erpProductId;
statGoodsInfo.productId = origin.id;
statGoodsInfo.productName = result.name.replace('\'', '’');
statGoodsInfo.brandName = (result.brandName || '').replace('\'', '’');
statGoodsInfo.marketPrice = result.marketPrice.replace('¥', '');
if (result.salePrice) {
statGoodsInfo.salePrice = result.salePrice.replace('¥', '');
} else {
statGoodsInfo.salePrice = result.marketPrice.replace('¥', '');
}
if (banner.brandId) {
let domainBrand = yield brandService.getBrandByDomainAsync(banner.brandDomain);
if (domainBrand.type && domainBrand.shopId) {
switch (parseInt(domainBrand.type, 10)) {
case 1:
{
// 多品店不显示
banner = [];
break;
}
case 2:
{
// 单品店显示新版的店铺banner
let basisData = yield shopService.basisTemplateAsync(domainBrand.shopId);
banner.bgImg = basisData.shopTopBanner.banner || banner.bgImg;
break;
}
default:
{
break;
}
}
}
}
statGoodsInfo.imageUrl = 'http:' + result.img;
statGoodsInfo.productUrl = 'http:' + helpers.urlFormat(url.parse(origin.productUrl).pathname, {}, 'item');
statGoodsInfo.smallSortId = result.smallSortId;
statGoodsInfo.soldOut = soldOut ? 1 : 0;
return {
goodsInfo: result,
consultComment: consultComment,
banner: _.isEmpty(banner) ? null : banner,
statGoodsInfo: statGoodsInfo
};
})();
};
/**
* 获取商品的舒适度
*/
const _getProductComfort = () => {
const _getProductComfort = (data) => {
let result = [];
let comfort = _getCacheDataByName('ItemData::getProductComfort');
let comfort = data.productComfort;
if (!comfort || !comfort.data) {
if (_.isEmpty(comfort) || !comfort || !comfort.data) {
return result;
}
comfort.data.forEach(value => {
_.get(comfort, 'data', []).forEach(value => {
let blocks = [];
let flag = false;
... ... @@ -877,14 +586,14 @@ const _getBasicDescription = (productDescBo) => {
/**
* 获得描述数据
*/
const _getDescriptionDataBySizeInfo = (sizeInfo) => {
const _getDescriptionDataBySizeInfo = (sizeInfo, additionalData) => {
if (!sizeInfo.productDescBo || !sizeInfo.productDescBo.erpProductId) {
return {};
}
return {
basic: _getBasicDescription(sizeInfo.productDescBo),
comfort: _getProductComfort()
comfort: _getProductComfort(additionalData)
};
};
... ... @@ -897,8 +606,6 @@ const _sizeInfoBoSort = (sizeInfoBo) => {
return {};
}
// TODO: 这里的排序代码很乱
_.get(sizeInfoBo, 'sizeBoList', []).forEach((sizeBoList, sizek)=> {
let sortAttr = {};
... ... @@ -1022,10 +729,10 @@ const _getSizeData = (sizeInfo) => {
* 获取商品模特卡
* @param productId
*/
const _getProductModelCard = () => {
let data = _getCacheDataByName('ItemData::getProductModelCard');
const _getProductModelCard = (additionalData) => {
let data = additionalData.productModelCard;
if (!data || _.get(data, 'code', 400) !== 200) {
if (_.isEmpty(data) || !data || _.get(data, 'code', 400) !== 200) {
return [];
}
... ... @@ -1143,8 +850,8 @@ const _getDetailDataBySizeInfo = (sizeInfo) => {
* 获取模特试穿
* @param productSkn
*/
const _getProductModelTry = () => {
let result = _getCacheDataByName('ItemData::getProductModelTry');
const _getProductModelTry = (data) => {
let result = data.productModelTry;
if (_.isEmpty(result) || result.code !== 200 || _.isEmpty(result.data)) {
return {};
... ... @@ -1243,12 +950,12 @@ const _getSizeAttrByMaxSortId = (maxSortId, sizeList) => {
* @param maxSortId
* @return object
*/
const _getSizeInfo = (productSkn, maxSortId)=> {
const _getSizeInfo = (productSkn, maxSortId, additionalData)=> {
if (!productSkn) {
return {};
}
let sizeInfo = _getCacheDataByName('ItemData::sizeInfo');
let sizeInfo = additionalData.sizeInfo;
if (_.isEmpty(sizeInfo)) {
return {};
... ... @@ -1257,13 +964,13 @@ const _getSizeInfo = (productSkn, maxSortId)=> {
let result = {};
// 描述数据
result.description = _getDescriptionDataBySizeInfo(sizeInfo);
result.description = _getDescriptionDataBySizeInfo(sizeInfo, additionalData);
// 模特卡
result.modelCards = _getProductModelCard();
result.modelCards = _getProductModelCard(additionalData);
// 试穿模特
let fittingReport = _getProductModelTry();
let fittingReport = _getProductModelTry(additionalData);
if (!_.isEmpty(fittingReport)) {
result.fittingReport = fittingReport;
... ... @@ -1332,6 +1039,263 @@ const _getSeoByGoodsInfo = function(goodsInfo, navs) {
};
/**
* 详情页数据格式化
* @param origin Object 原始数据
* @return result Object 格式化数据
*/
const _detailDataPkg = (origin, uid, vipLevel) => {
return co(function*() {
let result = {}; // 结果输出
let md5 = origin.md5;
origin = origin.data;
let propOrigin = _.partial(_.get, origin);
// 商品名称
if (!propOrigin('product_name')) {
return result;
}
origin.uid = uid;
result.name = propOrigin('product_name');
result.skn = propOrigin('product_skn');
result.productId = propOrigin('product_id');
result.md5 = md5; // 用于前端数据变化的对比
result.maxSortId = propOrigin('maxSortId', '');
result.smallSortId = propOrigin('smallSortId', '');
result.goCartUrl = helpers.urlFormat('/shopping/cart');
let brandId = propOrigin('brand_info.brand_id', 0);
let requestData = yield Promise.all([
_getProductAdditionInfoAsync(origin), // 预处理所有的数据
_getProductFavoriteDataAsync(uid, result.productId, brandId), // 处理收藏喜欢数据
productAPI.getPromotionAsync(result.skn)
]);
let additionalData = requestData[0];
let favoriteData = requestData[1];
let promotionData = requestData[2];
// 商品标签
result.tags = _getTagsDataByProductInfo(origin);
// 商品促销短语
result.saleTip = propOrigin('sales_phrase', '');
// 商品价格
result.marketPrice = propOrigin('format_market_price');
result.salePrice = propOrigin('format_sales_price');
result.hasOtherPrice = true;
if (result.salePrice === '0') {
delete result.salePrice;
result.hasOtherPrice = false;
}
if (propOrigin('student_price', '')) {
// 学生价
result.studentsPrice = propOrigin('student_price');
} else {
// VIP数据
result.vipPrice = _getVipDataByProductBaseInfo(origin, vipLevel, uid);
}
// 促销活动banner,虚拟商品无促销
if (propOrigin('attribute') !== 3) {
result.activity = _getActivityDataByProductBaseInfo(promotionData, additionalData);
}
const C_VALUE = {
type: '返有货币',
des: '每件返 ',
rest: '个 有货币'
};
if (propOrigin('yoho_coin_num', '0') !== '0') {
result.activity.push({
type: C_VALUE.type,
des: `${C_VALUE.des}${propOrigin('yoho_coin_num')}${C_VALUE.rest}`
});
}
// 上市期
if (propOrigin('expect_arrival_time')) {
result.arrivalDate = `${propOrigin('expect_arrival_time')}月`;
result.presalePrice = propOrigin('format_sales_price');
delete result.salePrice;
result.hasOtherPrice = false;
}
// 商品咨询和评论数据,当前为空
let consultComment = _getConsultCommentDataByProductInfo();
// 品牌信息
let banner = {};
if (propOrigin('brand_info', '')) {
result.brandImg = helpers.image(propOrigin('brand_info.brand_ico', ''), 47, 47);
result.brandName = propOrigin('brand_info.brand_name', '');
result.brandUrl = helpers.urlFormat('', null, propOrigin('brand_info.brand_domain'));
banner = _getBrandDataByProductBaseInfo(origin, additionalData);
banner.isCollect = favoriteData.brand;
}
// sku商品信息
let skuData = _getSkuDataByProductBaseInfo(origin);
result.img = skuData.defaultImage;
result.colors = skuData.skuGoods;
let totalStorageNum = skuData.totalStorageNum;
// 是否收藏
result.isCollect = favoriteData.product;
if (propOrigin('is_limit_buy', false)) {
// 是否开售
let isBeginSale = propOrigin('sale_status', 0) === 1;
// 限购商品有关的展示状态
let showStatus = propOrigin('show_status', 1);
let fashTopGoods = _getFashionTopGoodsStatus(uid, showStatus, isBeginSale);
result.fashionTopGoods = {
getLimitedCode: fashTopGoods.getLimitedCode, // 限购码状态
hadLimitedCode: fashTopGoods.hadLimitedCode, // 是否已经获取限购码
limitedCodeSoldOut: fashTopGoods.limitedCodeSoldOut, // 限购码是否已经抢光
getLimitedCodeDis: fashTopGoods.getLimitedCodeDis // 限购码是否失效
};
if (fashTopGoods.soldOut) {
result.soldOut = fashTopGoods.soldOut;
totalStorageNum = 0; // 改总数为已售磬
} else {
result.openSoon = fashTopGoods.openSoon; // 即将开售
result.dis = fashTopGoods.dis; // 是否失效
result.buyNow = fashTopGoods.buyNow; // 是否立即购买
}
}
let soldOut = !!(propOrigin('status') === 0 || totalStorageNum === 0);
let notForSale = propOrigin('attribute') === 2; // 非卖品
let virtualGoods = propOrigin('attribute') === 3; // 虚拟商品
if (virtualGoods) {
result.virtualGoods = virtualGoods;
// 是否显示虚拟商品,立即购买按钮
result.isVirtualBtn = soldOut ? false : true;
// 是否展览票
result.isTicket = propOrigin('product_skn') === EXHIBITION_TICKET;
}
if (!soldOut && !notForSale && !virtualGoods) {
result.addToCart = true;
// 立即购买或者即将开售存在
if (result.buyNow || result.openSoon) {
delete result.addToCart;
}
} else if (notForSale) {
// 非卖品
result.notForSale = true;
} else if (soldOut) {
// 已售磬
result.soldOut = true;
delete result.fashTopGoods;
} else if (virtualGoods) {
// 虚拟商品
result.buyNow = true; // 是否立即购买
result.buyNowBase = helpers.urlFormat('ticket', null, 'shopping');
if (result.salePrice) {
result.advancePrice = result.salePrice; // 先行价格
delete result.salePrice;
}
}
// 去掉即将售罄
if (totalStorageNum || soldOut) {
if (result.tags.isFew) {
delete result.tags.isFew; // 去掉即将售罄
}
}
// 分享相关,产品的链接
result.weixinUrl = propOrigin('product_url');
result.shareTitle = result.name;
result.shareImg = 'http:' + result.img; // 分享图片必须使用http
result.shareDesc = result.phrase;
// 统计需要的商品信息
let statGoodsInfo = {};
statGoodsInfo.uid = uid;
statGoodsInfo.skn = propOrigin('product_skn');
statGoodsInfo.productId = propOrigin('id');
statGoodsInfo.productName = result.name.replace('\'', '’');
statGoodsInfo.brandName = (result.brandName || '').replace('\'', '’');
statGoodsInfo.marketPrice = result.marketPrice;
statGoodsInfo.salePrice = result.salePrice ? result.salePrice : result.marketPrice;
if (banner.brandId) {
let domainBrand = yield brandService.getBrandByDomainAsync(banner.brandDomain);
if (domainBrand.type && domainBrand.shopId) {
let type = _.parseInt(domainBrand.type);
if (type === 1) {
// 多品店不显示
banner = {};
} else if (type === 2) {
// 单品店显示新版的店铺banner
let basisData = yield shopService.basisTemplateAsync(domainBrand.shopId);
banner.bgImg = basisData.shopTopBanner.banner || banner.bgImg;
}
}
}
statGoodsInfo.imageUrl = result.img;
statGoodsInfo.productUrl = helpers.urlFormat(url.parse(propOrigin('product_url')).pathname, null, 'item');
statGoodsInfo.smallSortId = result.smallSortId;
statGoodsInfo.soldOut = soldOut ? 1 : 0;
// 获取商品尺寸相关
let sizeInfo = _getSizeInfo(result, result.maxSortId, additionalData);
return Object.assign({
goodsInfo: result,
consultComment: consultComment,
banner: _.isEmpty(banner) ? null : banner,
statGoodsInfo: statGoodsInfo
}, sizeInfo);
})();
};
const getDetailHeader = (pid, uid, isStudent, vipLevel, dataMd5) => {
let currentUserProductInfo = _.partial(_detailDataPkg, _, uid, vipLevel);
return productAPI.getProductAsync(pid, uid, isStudent, vipLevel)
.then(result => currentUserProductInfo(result))
.then((result) => {
if (result.goodsInfo.md5 !== dataMd5 || uid) {
return {
code: 200, // 改变数据
data: result
};
} else {
return {
code: 204, // 没有改变数据
data: {}
};
}
});
};
/**
* 获取某一个商品详情主页面
*/
const showMainAsync = (data) => {
... ... @@ -1366,12 +1330,10 @@ const showMainAsync = (data) => {
data.saveInCookies(data.gid, _.get(productInfo, 'goodsInfo.skn', ''));
}
// 获取商品尺寸相关
let sizeInfo = _getSizeInfo(productInfo.goodsInfo, productInfo.goodsInfo.maxSortId);
result.headerData = requestData[1].headerData;
result.productDetailPage = true;
result.detail = Object.assign(productInfo, sizeInfo);
result.detail = productInfo;
result.statGoodsInfo = Object.assign({fullSortName: navs.map(x => x.name).join('-')},
productInfo.statGoodsInfo
);
... ... @@ -1392,7 +1354,6 @@ const showMainAsync = (data) => {
})();
};
module.exports = {
indexCommentAsync: commentService.indexAsync, // 获取评论列表
getShareOrderListAsync: commentService.getShareOrderListAsync, // 获取评论列表
... ... @@ -1400,5 +1361,6 @@ module.exports = {
createConsultAsync: consultService.createAsync, // 添加咨询
showMainAsync: showMainAsync, // 获取某一个商品详情主页面
indexHotAreaAsync: hotAreaService.indexAsync, // 获取某一个商品的热区数据
saveRecentGoodInCookies // 保存最近的商品
saveRecentGoodInCookies, // 保存最近的商品
getDetailHeader
};
... ...
/**
* 收藏相关接口
* @author: yyq<yanqing.yang@yoho.cn>
* @date: 2016/7/17
*/
'use strict';
const api = global.yoho.API;
/**
* 收藏API
* @function addFavAsync
* @param { number } uid 用户uid
* @param { number } id 收藏id
* @param { string } type 收藏类型 product--商品 brand--品牌 shop--店铺
* @return { Object } 收藏结果
*/
const addFavAsync = (uid, id, type) => {
return api.get('', {
method: 'app.favorite.add',
id: id,
uid: uid,
type: type
});
};
/**
* 取消收藏API
* @function cancelFavAsync
* @param { number } uid 用户uid
* @param { number } id 收藏id
* @param { string } type 收藏类型 product--商品 brand--品牌 shop--店铺
* @return { Object } 取消收藏结果
*/
const cancelFavAsync = (uid, id, type) => {
return api.get('', {
method: 'app.favorite.cancel',
fav_id: id,
uid: uid,
type: type
});
};
module.exports = {
addFavAsync, // 收藏
cancelFavAsync // 取消收藏
};
... ...
... ... @@ -7,6 +7,10 @@
const api = global.yoho.API;
const favApi = global.yoho.FavAPI;
const _ = require('lodash');
const favoriteApi = require('./favorite-api');
const isFavoriteAsync = (uid, pid) => {
let onNewApi = false;
... ... @@ -27,23 +31,8 @@ const isFavoriteAsync = (uid, pid) => {
}
};
const createAsync = (uid, pid) => {
return api.get('', {
method: 'app.favorite.add',
id: pid,
uid: uid,
type: 'product'
});
};
const deleteAsync = (uid, pid) => {
return api.get('', {
method: 'app.favorite.cancel',
fav_id: pid,
uid: uid,
type: 'product'
});
};
const createAsync = _.partial(favoriteApi.addFavAsync, _, _, 'product');
const deleteAsync = _.partial(favoriteApi.cancelFavAsync, _, _, 'product');
module.exports = {
isFavoriteAsync,
... ...
/**
* 收藏相关接口
* @author: yyq<yanqing.yang@yoho.cn>
* @date: 2016/7/17
*/
'use strict';
const favAPI = require('./favorite-api');
/**
* 收藏商品
* @function toggleFavProduct
* @param { number } productId 商品id
* @param { number } uid 用户uid
* @param { string } isadd 是否收藏 true--添加收藏 false--取消收藏
* @return { Object } 收藏结果
*/
const toggleFavProduct = (productId, uid, isadd) => {
if (isadd) {
return favAPI.addFavAsync(uid, productId, 'product');
} else {
return favAPI.cancelFavAsync(uid, productId, 'product');
}
};
/**
* 收藏品牌
* @function toggleFavBrand
* @param { number } brandId 品牌id
* @param { number } uid 用户uid
* @param { string } isadd 是否收藏 true--添加收藏 false--取消收藏
* @return { Object } 收藏结果
*/
const toggleFavBrand = (brandId, uid, isadd) => {
if (isadd) {
return favAPI.addFavAsync(uid, brandId, 'brand');
} else {
return favAPI.cancelFavAsync(uid, brandId, 'brand');
}
};
/**
* 收藏店铺
* @function toggleFavShop
* @param { number } shopId 店铺id
* @param { number } uid 用户uid
* @param { string } isadd 是否收藏 true--添加收藏 false--取消收藏
* @return { Object } 收藏结果
*/
const toggleFavShop = (shopId, uid, isadd) => {
if (isadd) {
return favAPI.addFavAsync(uid, shopId, 'shop');
} else {
return favAPI.cancelFavAsync(uid, shopId, 'shop');
}
};
module.exports = {
toggleFavProduct, // 收藏商品
toggleFavBrand, // 收藏品牌
toggleFavShop // 收藏店铺
};
... ...
/*
* @Author: Targaryen
* @Date: 2016-06-02 15:11:15
* @Last Modified by: Targaryen
* @Last Modified time: 2016-06-08 14:57:54
* @Author: sefon
* @Date: 2016-07-24 11:48:22
*/
'use strict';
const utils = '../../../utils';
const api = global.yoho.API;
const saleApi = require('./sale-api');
const outletsApi = require('./outlets-api');
const searchApi = require('./search-api');
const headerModel = require('../../../doraemon/models/header');
const productProcess = require(`${utils}/product-process`);
const publicHandler = require('./public-handler');
/**
* 获取商品列表商品数据 Controller 调用
* @param {[type]} params [常规参数]
* @param {[type]} extra [左侧列表额外要拼接的参数]
* @return {[type]} [description]
*/
exports.getListData = (params, channel) => {
let apiArr = [];
if (params.productPool) {
// 奥莱活动页调用app.search.sales
apiArr = [
saleApi.getSaleGoodsList({limit: '1', channel: channel }),
saleApi.getSaleGoodsList(Object.assign(params, { channel: channel }))
];
} else {
// 奥莱品类页调用app.search.li
apiArr = [
outletsApi.getOutletsGoodsList({limit: '1', channel: channel }),
outletsApi.getOutletsGoodsList(Object.assign(params, { channel: channel }))
];
const searchHandler = require('./search-handler');
const shopHandler = require('./shop-handler');
const helpers = global.yoho.helpers;
const _ = require('lodash');
const limitNum = 60; // 商品每页显示数目
// 品牌页folder名称
const brandFolderSeries = '经典系列';
// 搜索分类信息需要的参数
const positionId = 10;
// 获取分类左侧广告id
const sortAdsId = 79;
const _getGender = (channel) => {
let gender;
switch (channel) {
case 'boys':
gender = '1,3';
break;
case 'girls':
gender = '2,3';
break;
default:
gender = '1,2,3';
break;
}
return api.all(apiArr).then(result => {
let finalResult = {};
return gender;
};
/**
* 获取商品分类列表数据
*/
const getListData = (params, channel) => {
let searchParams = searchHandler.getSearchParams(params);
// 调用接口
let apiMethod = [
headerModel.requestHeaderData(channel),
searchApi.getSortList(Object.assign({}, {msort: '', misort: ''})),
searchApi.getProductList(searchParams)
];
// 搜索分类介绍和广告
if (params.msort && params.misort) {
let IntroParams = {
max_sort_id: params.msort,
middle_sort_id: params.misort,
gender: params.gender || '1,3'
};
apiMethod.push(searchApi.getSortIntro(Object.assign(IntroParams, {position_id: positionId})));
apiMethod.push(searchApi.getSortAds(Object.assign(IntroParams, {position_id: sortAdsId})));
}
return Promise.all(apiMethod).then(result => {
let finalResult = {
headerData: Object.assign(result[0].headerData, {
header: true
}),
list: {
leftContent: {}
}
};
// 获取左侧类目数据
if (result[1].code === 200) {
let dps = {};
if (params.gender) {
dps.gender = params.gender;
}
finalResult.list = Object.assign(
searchHandler.handlePathNavData(result[1].data.sort, params, 'sort', channel), {
leftContent: searchHandler.handleSortData(result[1].data.sort, dps)
});
}
// 获取商品数据和顶部筛选条件
if (result[2].code === 200) {
Object.assign(finalResult.list, {
filters: searchHandler.handleFilterDataAll(result[2].data, params),
opts: searchHandler.handleOptsData(params, result[2].data.total, result[2].data.filter),
totalCount: result[2].data.total,
footPager: searchHandler.handlePagerData(result[2].data.total, params),
goods: productProcess.processProductList(result[2].data.product_list,
Object.assign({showDiscount: false}, params)),
hasNextPage: searchHandler.handleNextPage(params, result[2].data.total),
// 最近浏览记录
latestWalk: 6
});
}
// 分类介绍
if (result[3] && result[3].code === 200) {
finalResult.list.sortIntro = searchHandler.handleSortIntro(result[3].data);
}
// 分类广告
if (result[4] && result[4].code === 200) {
Object.assign(finalResult.list.leftContent, searchHandler.handleSortAds(result[4].data));
}
finalResult.criteo = {skn: searchHandler.getCriteo(_.get(finalResult.list, 'goods'))};
let seo = searchHandler.getListSeo(channel,
_.get(finalResult, 'list.leftContent.allSort.list'),
_.get(finalResult, 'list.filters.checkedConditions.conditions'));
return Object.assign({}, seo, finalResult);
});
};
/**
* 获取新品到着数据
*/
const getListNewData = (params, channel) => {
let searchParams = searchHandler.getSearchParams(params);
// 调用接口
let apiMethod = [
headerModel.requestHeaderData(channel),
searchApi.getSortList(Object.assign({}, {msort: '', misort: ''})),
searchApi.getProductList(Object.assign({new: 'Y'}, searchParams)),
searchApi.getWeekNew(params)
];
return Promise.all(apiMethod).then(result => {
let finalResult = {
headerData: Object.assign(result[0].headerData, {
header: true
}),
list: {
leftContent: {}
}
};
let dps = {};
if (params.gender) {
dps.gender = params.gender;
}
// 获取左侧类目数据
if (result[1].code === 200) {
finalResult.list = Object.assign(
searchHandler.handlePathNavData(result[1].data.sort, params, 'new', channel), {
leftContent: searchHandler.handleSortData(result[1].data.sort, dps)
});
}
// 获取商品数据和顶部筛选条件
if (result[0].code === 200) {
finalResult.leftContent = publicHandler.handleSaleSortData(result[0].data.filter.group_sort, params);
finalResult.pathNav = publicHandler.handlePathNavData(result[0].data.filter.group_sort, params);
if (result[2].code === 200) {
Object.assign(finalResult.list, {
filters: searchHandler.handleFilterDataAll(result[2].data, params),
opts: searchHandler.handleOptsData(params, result[2].data.total, result[2].data.filter),
totalCount: result[2].data.total,
footPager: searchHandler.handlePagerData(result[2].data.total, params),
goods: productProcess.processProductList(result[2].data.product_list,
Object.assign({showDiscount: false, showNew: false}, params)),
hasNextPage: searchHandler.handleNextPage(params, result[2].data.total),
// 最近浏览记录
latestWalk: 7
});
}
// 新品上架
if (result[3] && result[3].code === 200) {
Object.assign(finalResult.list.leftContent, searchHandler.handleWeekNew(result[3].data, dps));
}
finalResult.criteo = {skn: searchHandler.getCriteo(_.get(finalResult.list, 'goods'))};
let seo = searchHandler.getNewSeo(channel, _.get(finalResult, 'list.leftContent.newSales.list'));
return Object.assign({}, seo, finalResult);
});
};
/**
* 根据品牌域名查询品牌信息
*/
const getBrandInfo = (params) => {
return searchApi.getBrandData(params).then(result => {
if (result.code !== 200 || !result.data) {
return {};
}
return {
brandId: result.data.id,
brandNameEn: result.data.brand_name_en || '',
brandNameCn: result.data.brand_name_cn || '',
brandBanner: result.data.brand_banner || '',
node: result.data.static_content_code || '',
brandAbout: result.data.brand_intro || '',
shopTemplateType: result.data.shop_template_type || 0,
url: helpers.urlFormat('', '', result.data.brand_domain),
name: result.data.brand_name,
shopId: result.data.shop_id || 0,
type: result.data.type || 0,
brandDomain: result.data.brand_domain
};
});
};
/**
* 获取品牌页面数据
*/
const getBrandData = (params, extra, channel) => {
let searchParams = searchHandler.getSearchParams(params);
// 设置品牌默认排序方式
let order = params.order || 'b_w_desc';
// 调用接口
let apiMethod = [
headerModel.requestHeaderData(channel),
searchApi.getSortList(Object.assign({}, {brand: extra.brandId, msort: '', misort: ''})),
searchApi.getProductList(Object.assign({order: order, brand: extra.brandId}, searchParams))
];
return Promise.all(apiMethod).then(result => {
let finalResult = {
headerData: Object.assign(result[0].headerData, {
header: true
}),
brand: {
brandBanner: searchHandler.handleBrandBanner(extra),
leftContent: {},
node: extra.node || ''
}
};
// 获取左侧类目数据
if (result[1].code === 200) {
Object.assign(finalResult, {
filters: publicHandler.handleSaleFilterData(result[1].data.filter, params),
opts: publicHandler.handleSaleOptsData(params, result[1].data.total),
totalCount: result[1].data.total,
footPager: publicHandler.handlePagerData(result[1].data.total, params),
goods: productProcess.processProductList(result[1].data.product_list)
let dps = {};
if (params.gender) {
dps.gender = params.gender;
}
Object.assign(finalResult.brand, {
leftContent: searchHandler.handleSortData(result[1].data.sort, dps)
}, searchHandler.handlePathNavData(extra, params, 'brand', channel));
}
// 获取商品数据和顶部筛选条件
if (result[2].code === 200) {
Object.assign(finalResult.brand, {
filters: searchHandler.handleFilterDataAll(result[2].data, params),
opts: searchHandler.handleOptsData(params, result[2].data.total, result[2].data.filter),
totalCount: result[2].data.total,
footPager: searchHandler.handlePagerData(result[2].data.total, params),
goods: productProcess.processProductList(result[2].data.product_list,
Object.assign({showDiscount: false}, params)),
hasNextPage: searchHandler.handleNextPage(params, result[2].data.total),
// 最近浏览记录
latestWalk: 7
});
}
// 品牌页不显示品牌筛选项
delete finalResult.brand.filters.brand;
finalResult.criteo = {skn: searchHandler.getCriteo(_.get(finalResult.brand, 'goods'))};
let seo = searchHandler.getBrandSeo(channel, extra);
return Object.assign({}, seo, finalResult);
});
};
/**
* 获取品牌介绍页面数据
*/
const getBrandAbout = (domain, uid, channel) => {
channel = channel || 'boys';
return Promise.all([
headerModel.requestHeaderData(channel),
searchApi.getBrandData({domain: domain})
]).then(result => {
let home;
let finalResult = {
headerData: Object.assign(result[0].headerData, {
header: true
})
};
switch (channel) {
case 'girls':
home = helpers.urlFormat('/woman', {}, 'new');
break;
case 'lifestyle':
home = helpers.urlFormat('/lifestyle', {}, 'new');
break;
case 'kids':
home = helpers.urlFormat('/kids', {}, 'new');
break;
default:
home = helpers.urlFormat('');
break;
}
if (result[1].code === 200) {
let data = result[1].data || {};
let extra = {
brandId: data.id,
brandNameEn: data.brand_name_en || '',
brandNameCn: data.brand_name_cn || '',
brandBanner: data.brand_banner || '',
node: data.static_content_code || '',
brandAbout: data.brand_intro || '',
shopTemplateType: data.shop_template_type || 0,
url: helpers.urlFormat('', '', data.brand_domain),
name: data.brand_name,
shopId: data.shop_id || 0,
type: data.type || 0,
brandDomain: data.brand_domain
};
finalResult.brand = {
brandBanner: searchHandler.handleBrandBanner(extra),
pathNav: [
{
href: home,
name: `${_.toUpper(channel)}首页`,
pathTitle: 'YOHO!BUY 有货'
},
{
href: helpers.urlFormat('/brands'),
name: '品牌一览',
pathTitle: '品牌一览'
},
{
name: `${extra.brandNameEn} ${extra.brandNameCn}`
}
],
brandAbout: {
brandIntro: extra.brandAbout
}
};
}
return finalResult;
});
};
/**
* 获取店铺介绍页面数据
*/
const getShopAbout = (shopId, uid, channel) => {
let resData = {};
return Promise.all([
headerModel.requestHeaderData(channel),
searchApi.getShopDecorator(shopId), // 店铺装修数据
searchApi.getShopInfo(shopId, uid)
]).then(result => {
resData.headerData = Object.assign(result[0].headerData, {
header: true
});
if (result[1].code === 200) {
let data = result[1].data || {},
decorator = shopHandler.getShopDecorator(data, {}, shopId);
Object.assign(decorator.shopTopBannerBase, {
shopHome: `/?shopId=${shopId}`,
shopIntro: `/about?shopId=${shopId}`,
coled: _.get(result, '[1].is_favorite', 'N') === 'Y'
});
_.set(resData, 'brand.shopBanner', decorator.shopTopBannerBase);
_.unset(resData, 'brand.brandBanner');
}
if (result[2].code === 200) {
let data = result[2].data || {};
_.set(resData, 'brand.brandAbout.brandIntro', data.shop_intro);
}
return resData;
});
};
/**
* 获取品牌页面水牌
*/
const getNodeContentData = (params) => {
return searchApi.getNodeContent(params).then(result => {
if (result.code === 200 && result.data) {
return result.data;
}
});
};
/**
* 获取品牌页面系列
*/
const getAdnav = (params) => {
return Promise.all([searchApi.getBrandFolder(params), searchApi.getBrandSeries(params)]).then(result => {
let dest = {
picTitle: '',
list: []
};
if (result[0].code === 200 && result[0].data) {
dest.picTitle = brandFolderSeries;
Object.assign(dest.list, searchHandler.handleFolderData(result[0].data));
}
if (result[1].code === 200 && result[1].data) {
dest.picTitle = brandFolderSeries;
Object.assign(dest.list, searchHandler.handleFolderData(result[0].data));
}
return dest;
});
};
/**
* 获取店铺基本信息
*/
const getShopInfo = (shopId, uid) => {
return searchApi.getShopInfo(shopId, uid).then(result => {
if (result.code === 200) {
return {
brandName: result.data.shop_name,
brandCont: result.data.shop_intro,
domain: result.data.shop_domain,
logo: result.data.shop_logo,
isFavorite: result.data.is_favorite === 'Y',
shopTemplateType: result.data.shop_template_type,
multBrandShopType: result.data.mult_brand_shop_type,
showShopName: result.data.is_show_shop_name === 'Y'
};
} else {
return {};
}
});
};
/**
* 获取经典模板店铺数据
* @param shopId
* @param uid
* @param params
* @param shopInfo 店铺介绍
*/
const getShopData = (shopId, channel, params, shopInfo) => {
let gender = _getGender(channel);
params = params || {};
params.shopId = shopId;
return Promise.all([
headerModel.requestHeaderData(channel), // 头部数据
searchApi.getShopDecorator(shopId), // 店铺装修数据
searchApi.getProductList(Object.assign({
shop_id: shopId
}, params)), // 搜索店铺商品
searchApi.getShopBrands(shopId) // 店铺品牌数据
]).then(result => {
let finalResult = {};
Object.assign(finalResult,
result[0], // 头部数据
searchHandler.handlePathNavData(shopInfo, params, 'shop', channel) // 面包屑导航
);
_.set(finalResult, 'headerData.header', true);
// 店铺装修
if (result[1].code === 200) {
Object.assign(finalResult, shopHandler.getShopDecorator(result[1].data, params, shopId));
_.set(finalResult, 'shopTopBanner.brandIntro', {
shopId: shopId,
brandName: shopInfo.brandName || '',
isFavorite: shopInfo.isFavorite || false,
brandCont: shopInfo.brandCont || ''
});
} else {
return Promise.reject('No ShopDecorator data');
}
// 获取商品数据和顶部筛选条件
if (result[2].code === 200) {
let allGoods = {
name: '全部商品 ALL',
sort: searchHandler.handleOptsData(params, _.get(result[2], 'data.total', 0)),
list: productProcess.processProductList(_.get(result[2], 'data.product_list', []), {
newCoverSort: true,
showDiscount: false,
gender: gender
}),
href: `/product/shoplist?navBar=1&shopId=${shopId}`
};
_.set(allGoods, 'sort.newPage', true); // 启用新的分页导航
finalResult.allGoods = allGoods;
}
let sknList = []; // 资源位配置商品skn
let prodList = _.concat(_.get(finalResult, 'newArrivel.list', []),
_.get(finalResult, 'hotSingle.list', []));
_.forEach(prodList, value => {
sknList.push(value.productSkn);
});
let shopBrandIds = [], // 店铺的所有品牌id
articleApiMethod = [], // 通过品牌获取相关文章接口
apiMethod = [
searchApi.getProductList({query: _.join(_.uniq(sknList), ',')})
];
if (result[3].code === 200 && result[3].data) {
_.forEach(result[3].data, value => {
shopBrandIds.push(value.brand_id);
articleApiMethod.push(
searchApi.getArticleByBrand(value.brand_id, 'udid') // 品牌推荐文章
);
});
}
// 根据品牌获取分类 (腾讯云测试没有该接口,暂时不调用分类)
apiMethod.push(searchApi.getSortList({brand: shopBrandIds}));
apiMethod = _.concat(apiMethod, articleApiMethod);
return Promise.all(apiMethod).then(subRes => {
// 设置资源位商品封面图
if (subRes[0].code === 200) {
let list = {};
prodList = productProcess.processProductList(_.get(subRes[0], 'data.product_list', []), {
newCoverSort: true,
showDiscount: false,
gender: gender
});
_.forEach(prodList, value => {
list[value.product_skn] = {
img: helpers.getForceSourceUrl(value.default_images) +
'?imageView/1/w/{width}/h/{height}',
title: value.product_name,
price: ${value.sales_price}`
}
});
if (_.has(finalResult, 'newArrivel.list')) {
_.forEach(finalResult.newArrivel.list, value => {
if (list[value.productSkn]) {
Object.assign(value, list[value.productSkn]);
}
});
}
if (_.has(finalResult, 'hotSingle.list')) {
_.forEach(finalResult.hotSingle.list, value => {
if (list[value.productSkn]) {
Object.assign(value, list[value.productSkn]);
}
});
}
}
if (subRes[1].code === 200) {
let groupSort = _.get(subRes[1], 'data.sort', []);
finalResult.leftContent = searchHandler.handleSortData(groupSort, params);
if (finalResult.allGoods) {
Object.assign(finalResult.allGoods, searchHandler.setShopSort(groupSort, params));
}
}
let articleList = [];
for (let i = 2; i < subRes.length; i++) {
articleList = _.concat(articleList, _.get(subRes[i], 'data', []));
}
if (articleList.length >= 3) {
let trendList = [];
for (let i = 0; i < 3; i++) {
trendList.push({
href: articleList[i].url,
src: helpers.getForceSourceUrl(articleList[i].src) +
'?imageView/1/w/{width}/h/{height}',
mainTitle: articleList[i].title,
Subtitle: articleList[i].intro
});
articleList = _.concat(articleList, _.get(subRes[i], 'data', []));
}
finalResult.trendInfo = {
name: '潮流资讯 HOT ITEMS',
trendList: trendList
};
}
return finalResult;
});
});
};
const getShopListData = (channel, params, uid) => {
let gender = _getGender(channel),
shopId = params.shopId,
navBar = params.navBar || 1;
let apiArr = [
headerModel.requestHeaderData(channel), // 头部数据
searchApi.getShopDecorator(shopId), // 店铺装修数据
searchApi.getShopInfo(shopId, uid), // 店铺介绍
searchApi.getProductList(Object.assign({shop_id: shopId}, params)), // 搜索店铺商品
searchApi.getShopBrands(shopId) // 店铺品牌数据
];
if (_.has(params, 'query')) {
apiArr.push(searchApi.getProductList(Object.assign({shop_id: shopId},
params, {query: ''}))); // 搜索店铺所有商品
}
return Promise.all(apiArr).then(result => {
let finalResult = {
headerData: Object.assign(result[0].headerData, {header: true})
};
// 面包屑导航
Object.assign(finalResult, searchHandler.handlePathNavData({}, params, 'shop', channel));
// 店铺装修
if (result[1].code === 200) {
Object.assign(finalResult, shopHandler.getShopDecorator(result[1].data, params, shopId));
// 设置shop nav选中状态
_.set(finalResult, `navigationBar[${navBar}].current`, true);
if (result[2].code === 200) {
let data = _.get(result[2], 'data', {});
_.set(finalResult, 'shopTopBanner.brandIntro', {
shopId: shopId,
brandName: data.shop_name || '',
isFavorite: data.is_favorite === 'Y',
brandCont: data.shop_intro || ''
});
}
} else {
return Promise.reject('No ShopDecorator data');
}
// 获取商品数据和顶部筛选条件
if (result[3].code === 200) {
let info = result[3];
let goodsList = _.get(info, 'data.product_list', []);
if (goodsList.length) {
let tip = {
start: (_.get(info, 'data.page', 1) - 1) * limitNum + 1,
total: _.get(info, 'data.total', 0)
};
tip.end = tip.start + limitNum - 1;
if (tip.end > tip.total) {
tip.end = tip.total;
}
Object.assign(finalResult, {
filters: searchHandler.handleFilterDataAll(info.data, params),
opts: searchHandler.handleOptsData(params, tip.total),
goods: productProcess.processProductList(goodsList, {
newCoverSort: true,
showDiscount: false,
gender: _getGender(channel)
}),
footPager: {tip: tip}
});
} else {
finalResult.searchEmpty = true;
if (result[5] && result[5].code === 200) {
let allGoods = {
name: '全部商品 ALL',
sort: searchHandler.handleOptsData(params, _.get(result[5], 'data.total', 0)),
list: productProcess.processProductList(_.get(result[5], 'data.product_list', []), {
newCoverSort: true,
showDiscount: false,
gender: gender
})
};
_.set(allGoods, 'sort.newPage', true); // 启用新的分页导航
finalResult.allGoods = allGoods;
}
}
}
if (result[4].code === 200) {
let shopBrandIds = []; // 店铺下的所有品牌id数组
_.forEach(_.get(result[4], 'data', []), value => {
shopBrandIds.push(value.brand_id);
});
return searchApi.getSortList({brand: shopBrandIds}).then(subRes => {
if (subRes.code === 200) {
let groupSort = _.get(subRes, 'data.sort', []);
finalResult.leftContent = searchHandler.handleSortData(groupSort, params);
if (finalResult.allGoods) {
Object.assign(finalResult.allGoods, searchHandler.setShopSort(groupSort, params));
}
}
return finalResult;
});
}
finalResult.criteo = {skn: searchHandler.getCriteo(_.get(finalResult, 'goods'))};
return finalResult;
});
};
/**
* 获取基础模板店铺数据
*/
const getBaseShopData = (params, extra, channel, shopId) => {
let resData = {};
return Promise.all([
getBrandData(params, extra, channel),
searchApi.getShopDecorator(shopId), // 店铺装修数据
searchApi.getShopInfo(shopId, extra.uid)
]).then(result => {
let brand = result[0] || {};
Object.assign(resData, brand);
if (result[1].code === 200) {
let data = result[1].data || {},
decorator = shopHandler.getShopDecorator(data, {}, shopId);
Object.assign(decorator.shopTopBannerBase, {
shopHome: `/?shopId=${shopId}`,
shopIntro: `/about?shopId=${shopId}`,
coled: _.get(result, '[2].is_favorite', 'N') === 'Y'
});
_.set(resData, 'brand.shopBanner', decorator.shopTopBannerBase);
_.unset(resData, 'brand.brandBanner');
}
return resData;
});
};
module.exports = {
getListData,
getListNewData,
getBrandInfo,
getBrandData,
getBrandAbout,
getShopAbout,
getNodeContentData,
getAdnav,
getShopInfo,
getShopData,
getShopListData,
getBaseShopData
}
... ...
... ... @@ -8,7 +8,6 @@
const utils = '../../../utils';
const helpers = global.yoho.helpers;
const _ = require('lodash');
const camelCase = global.yoho.camelCase;
const productProcess = require(`${utils}/product-process`);
const url = require('url');
const queryString = require('querystring');
... ... @@ -110,15 +109,14 @@ const categoryNavigation = (data, params) => {
* @return {[array]}
*/
exports.processFloor = (list, params) => {
const formatData = [];
const formatData = {};
let floorData;
list = list || [];
list = camelCase(list);
// 格式化数据
_.forEach(list, (floor) => {
switch (floor.templateName) {
switch (floor.template_name) {
case 'NL2R':
floorData = {topBanner: floor.data};
break;
... ...
/*
* @Author: Targaryen
* @Date: 2016-06-02 15:11:15
* @Last Modified by: Targaryen
* @Last Modified time: 2016-06-08 14:57:54
*/
'use strict';
const utils = '../../../utils';
const api = global.yoho.API;
const saleApi = require('./sale-api');
const outletsApi = require('./outlets-api');
const productProcess = require(`${utils}/product-process`);
const publicHandler = require('./public-handler');
/**
* 获取商品列表商品数据 Controller 调用
* @param {[type]} params [常规参数]
* @param {[type]} extra [左侧列表额外要拼接的参数]
* @return {[type]} [description]
*/
exports.getListData = (params, channel) => {
let apiArr = [];
if (params.productPool) {
// 奥莱活动页调用app.search.sales
apiArr = [
saleApi.getSaleGoodsList({limit: '1', channel: channel }),
saleApi.getSaleGoodsList(Object.assign(params, { channel: channel }))
];
} else {
// 奥莱品类页调用app.search.li
apiArr = [
outletsApi.getOutletsGoodsList({limit: '1', channel: channel }),
outletsApi.getOutletsGoodsList(Object.assign(params, { channel: channel }))
];
}
return api.all(apiArr).then(result => {
let finalResult = {};
// 获取商品数据和顶部筛选条件
if (result[0].code === 200) {
finalResult.leftContent = publicHandler.handleSaleSortData(result[0].data.filter.group_sort, params);
finalResult.pathNav = publicHandler.handlePathNavData(result[0].data.filter.group_sort, params);
}
// 获取左侧类目数据
if (result[1].code === 200) {
Object.assign(finalResult, {
filters: publicHandler.handleSaleFilterData(result[1].data.filter, params),
opts: publicHandler.handleSaleOptsData(params, result[1].data.total),
totalCount: result[1].data.total,
footPager: publicHandler.handlePagerData(result[1].data.total, params),
goods: productProcess.processProductList(result[1].data.product_list)
});
}
return finalResult;
});
};
... ...
... ... @@ -214,6 +214,21 @@ exports.handleSaleOptsData = (params, total, extra) => {
// 用来标记是否是折扣专场,折扣专场只需要前三个排序参数
let count = (extra === 'discont') ? 3 : 4;
if (extra === 'default') {
let defaultOpt = {};
defaultOpt.href = handleFilterUrl(params, {order: ''});
defaultOpt.name = '默认';
defaultOpt.hasSortOrient = true;
if (_.isEmpty(params.order)) {
defaultOpt.active = true;
} else {
defaultOpt.active = false;
}
defaultOpt.desc = true;
dest.sortType.push(defaultOpt);
}
for (let i = 0; i < count; i++) {
let opt = {};
... ... @@ -229,8 +244,7 @@ exports.handleSaleOptsData = (params, total, extra) => {
}
} else {
opt.name = '最新';
opt.hasSortOrient = true;
if (_.isEmpty(params.order) || params.order === 's_t_desc') {
if (params.order === 's_t_desc') {
opt.active = true;
} else {
opt.active = false;
... ...
... ... @@ -41,6 +41,10 @@ exports.getSaleGoodsList = (params) => {
Object.assign(finalParams, params);
if (finalParams.order === '') {
delete finalParams.order;
}
return api.get('', finalParams);
};
... ... @@ -110,3 +114,18 @@ exports.getUserProfile = (uid) => {
uid: uid
}, true);
};
/**
* 获取用户数据信息
* @param {[string]} uid
* @return {[array]}
*/
exports.getSaleSpecialAsync = (specialId) => {
return api.get('', {
method: 'app.resources.getOneSpecial',
special_id: specialId
}, {
code: 200,
cache: true
});
};
... ...
... ... @@ -6,17 +6,24 @@
*/
'use strict';
const utils = '../../../utils';
const logger = global.yoho.logger;
const camelCase = global.yoho.camelCase;
const api = global.yoho.API;
const Promise = require('bluebird');
const saleApi = require('./sale-api');
const searchApi = require('./search-api');
const publicHandler = require('./public-handler');
const saleHandler = require('./sale-handler');
const productProcess = require(`${utils}/product-process`);
const searchHandler = require('./search-handler');
const productProcess = require(`${global.utils}/product-process`);
const pager = require(`${global.utils}/pager`).setPager;
const imageHandler = require(`${global.utils}/images`).getImageUrl;
const _ = require('lodash');
const headerModel = require('../../../doraemon/models/header');
const limitNum = 60; // 商品每页显示数目
// 下一页图片
const nextPageImg = '//img10.static.yhbimg.com/product/2014/01/15/11/01fa01614784f6239760f1b749663016f1.jpg?imageMogr2/thumbnail/235x314/extent/235x314/background/d2hpdGU=/position/center/quality/90'; // eslint-disable-line
/**
* 资源位code码
*/
... ... @@ -67,37 +74,31 @@ exports.getSaleGoodsData = (params) => {
delete finalResult.goods[key].tags.isSale;// 屏蔽 sale 标签
delete finalResult.goods[key].discount; // 屏蔽折扣信息
});
} else {
logger.error('search sale api code no 200');
}
// 处理 VIP 商品数据
if (result[1].code === 200) {
let userInfo = result[1].data.vip_info ? camelCase(result[1].data.vip_info) : {};
if (_.isEmpty(userInfo)) {
logger.info('no user info');
}
let vipInfo = _.get(result, '[1].data.vip_info', {});
if (params.saleType === '2') {
_.forEach(finalResult.goods, (value, key) => {
switch (userInfo.curLevel) {
switch (vipInfo.cur_level) {
case '1':
finalResult.goods[key].salesPrice = value.vip1Price;
finalResult.goods[key].sales_price = value.vip1_price;
finalResult.goods[key].vip1 = true;
break;
case '2':
finalResult.goods[key].salesPrice = value.vip2Price;
finalResult.goods[key].sales_price = value.vip2_price;
finalResult.goods[key].vip2 = true;
break;
case '3':
finalResult.goods[key].salesPrice = value.vip3Price;
finalResult.goods[key].sales_price = value.vip3_price;
finalResult.goods[key].vip3 = true;
break;
default:
finalResult.goods[key].vip = true;
delete finalResult.goods[key].salesPrice;
delete finalResult.goods[key].sales_price;
break;
}
... ... @@ -160,16 +161,12 @@ exports.getSaleIndexData = (channel) => {
if (result[1].data.length > 0) {
finalResult.brandSale = saleHandler.handleSaleActivityData(result[1].data, channel);
}
} else {
logger.error('discount activities api code no 200');
}
// 资源位数据处理
if (result[2].code === 200 && !_.isEmpty(result[2].data)) {
finalResult.topBanner = saleHandler.handleSaleBannerData(result[2].data);
finalResult.activityEnter = saleHandler.handleSaleBannerSmallData(result[2].data);
} else {
logger.error('content code api code no 200 or no data');
}
// 分类处理
... ... @@ -184,21 +181,21 @@ exports.getSaleIndexData = (channel) => {
{forVip: true}
)
);
} else {
logger.error('index vip category api code no 200');
}
// 断码区分类处理
if (result[4].code === 200) {
let breakingSizeSort = saleHandler.handleSaleBreakingSizeData(result[4].data);
return api.all([saleApi.getSaleGoodsList({
channel: channel,
saleType: '5', // app 与 pc 有冲突,为 PC 加一个 5 的选项
limit: '1',
breakSize: breakingSizeSort.breakSize,
breakSort: breakingSizeSort.breakSort
})]).then(subResult => {
return api.all([
saleApi.getSaleGoodsList({
channel: channel,
saleType: '5', // app 与 pc 有冲突,为 PC 加一个 5 的选项
limit: '1',
breakSize: breakingSizeSort.breakSize,
breakSort: breakingSizeSort.breakSort
})
]).then(subResult => {
if (subResult[0].code === 200) {
finalResult.saleCategory.push(
saleHandler.handleSaleCategoryData(
... ... @@ -216,14 +213,10 @@ exports.getSaleIndexData = (channel) => {
finalResult.saleCategory.push(
saleHandler.handleSaleCategoryData(result[5].data.filter.group_sort, '3', channel)
);
} else {
logger.error('newSale category api code no 200');
}
return finalResult;
});
} else {
logger.error('breakYards category api code no 200');
}
return finalResult;
});
... ... @@ -267,8 +260,6 @@ exports.getSaleOthersData = (params, channel) => {
if (!_.isEmpty(result[1].data.filter)) {
// 顶部筛选条件
finalResult.filters = publicHandler.handleSaleFilterData(result[1].data.filter, params);
} else {
logger.error('data filter is empty');
}
// 处理排序数据
... ... @@ -283,12 +274,10 @@ exports.getSaleOthersData = (params, channel) => {
};
_.forEach(finalResult.goods, (value, key) => {
delete finalResult.goods[key].tags.isNew; // 屏蔽 new 标签
delete finalResult.goods[key].tags.isSale;// 屏蔽 sale 标签
delete finalResult.goods[key].tags.is_new; // 屏蔽 new 标签
delete finalResult.goods[key].tags.is_sale;// 屏蔽 sale 标签
delete finalResult.goods[key].discount; // 屏蔽折扣信息
});
} else {
logger.error('goods list api code no 200');
}
// 获取焦点图数据
... ... @@ -299,8 +288,6 @@ exports.getSaleOthersData = (params, channel) => {
delete finalResult.topBanner.list[key].href;
});
}
} else {
logger.error('content code api code no 200');
}
// 获取分类筛选数据
... ... @@ -309,46 +296,36 @@ exports.getSaleOthersData = (params, channel) => {
// 获取左侧类目数据
finalResult.leftContent = publicHandler.handleSaleSortData(result[3].data.filter.group_sort, params);
} else {
logger.error('left content category api code no 200');
}
if (!_.isEmpty(result[4])) {
// 处理 VIP 商品数据
if (result[4].code === 200 && parseInt(params.saleType, 10) === 2) {
let userInfo = result[4].data.vip_info ? camelCase(result[4].data.vip_info) : {};
if (_.isEmpty(userInfo)) {
logger.info('no user info');
}
let vipInfo = _.get(result, '[4].data.vip_info', {});
_.forEach(finalResult.goods, (value, key) => {
switch (userInfo.curLevel) {
switch (vipInfo.cur_level) {
case '1':
finalResult.goods[key].salesPrice = value.vip1Price;
finalResult.goods[key].sales_price = value.vip1_price;
finalResult.goods[key].vip1 = true;
break;
case '2':
finalResult.goods[key].salesPrice = value.vip2Price;
finalResult.goods[key].sales_price = value.vip2_price;
finalResult.goods[key].vip2 = true;
break;
case '3':
finalResult.goods[key].salesPrice = value.vip3Price;
finalResult.goods[key].sales_price = value.vip3_price;
finalResult.goods[key].vip3 = true;
break;
default:
finalResult.goods[key].vip = true;
delete finalResult.goods[key].salesPrice;
delete finalResult.goods[key].sales_price;
break;
}
});
} else {
logger.error('user api code no 200 or no vip category');
}
} else {
logger.info('no user info get from api');
}
return finalResult;
... ... @@ -366,6 +343,11 @@ exports.getSaleDiscountData = (params, channel) => {
]).then(result => {
let finalResult = result[0];
// 默认order: ''
if (_.isEmpty(params.order)) {
Object.assign(params, {order: ''});
}
// 处理折扣专场标题 banner 数据
if (result[1].code === 200) {
if (_.size(result[1].data) === 1) {
... ... @@ -378,28 +360,28 @@ exports.getSaleDiscountData = (params, channel) => {
}
]
};
} else {
logger.error('discount activity data[0] web_url empty');
}
}
return api.all([
saleApi.getSaleGoodsList({channel: channel, saleType: '3', limit: '1',
productPool: result[1].data[0].product_pool}),
saleApi.getSaleGoodsList({
channel: channel,
saleType: '3',
limit: '1',
productPool: result[1].data[0].product_pool,
order: ''
}),
saleApi.getSaleGoodsList(Object.assign(params, {productPool: result[1].data[0].product_pool}))
]).then(subResult => {
// 处理分页等筛选信息
if (subResult[0].code === 200) {
Object.assign(finalResult, {
leftContent: publicHandler.handleSaleSortData(subResult[0].data.filter.group_sort,
params, 'discount'),
leftContent: publicHandler.handleSaleSortData(subResult[0].data.filter.group_sort, params, 'discount'),
saleList: {
footPager: publicHandler.handlePagerData(subResult[0].data.total, params),
opts: publicHandler.handleSaleOptsData(params, subResult[0].data.total)
opts: publicHandler.handleSaleOptsData(params, subResult[0].data.total, 'default')
}
});
} else {
logger.error('category api no 200');
}
... ... @@ -411,22 +393,18 @@ exports.getSaleDiscountData = (params, channel) => {
finalResult.saleList.totalCount = subResult[1].data.total;
_.forEach(finalResult.saleList.goods, (value, key) => {
if (sknArr.length < 3) {
sknArr.push(value.productSkn);
sknArr.push(value.product_skn);
}
delete finalResult.saleList.goods[key].tags.isNew; // 屏蔽 new 标签
delete finalResult.saleList.goods[key].tags.isSale;// 屏蔽 sale 标签
delete finalResult.saleList.goods[key].tags.is_new; // 屏蔽 new 标签
delete finalResult.saleList.goods[key].tags.is_sale;// 屏蔽 sale 标签
delete finalResult.saleList.goods[key].discount; // 屏蔽折扣信息
});
finalResult.criteo = {skn: sknArr}; // 重要:推广列表前三个商品Skn
} else {
logger.error('discount goods list api code no 200');
}
return finalResult;
});
} else {
logger.error('discount activity api code no 200');
}
return finalResult;
});
... ... @@ -452,8 +430,6 @@ exports.getSalebreakingYardsData = (params, channel) => {
_.forEach(finalResult.topBanner.list, (value, key) => {
delete finalResult.topBanner.list[key].href;
});
} else {
logger.error('content code api code no 200');
}
// 断码区产品筛选需要断码区尺码数据,改为串行处理
... ... @@ -484,8 +460,6 @@ exports.getSalebreakingYardsData = (params, channel) => {
if (subResult[0].code === 200) {
finalResult.leftContent =
publicHandler.handleSaleSortData(subResult[0].data.filter.group_sort, params);
} else {
logger.error('breakYards left content api code no 200');
}
// 处理商品数据
... ... @@ -510,17 +484,119 @@ exports.getSalebreakingYardsData = (params, channel) => {
};
_.forEach(finalResult.goods, (value, key) => {
delete finalResult.goods[key].tags.isNew; // 屏蔽 new 标签
delete finalResult.goods[key].tags.isSale;// 屏蔽 sale 标签
delete finalResult.goods[key].tags.is_new; // 屏蔽 new 标签
delete finalResult.goods[key].tags.is_sale;// 屏蔽 sale 标签
delete finalResult.goods[key].discount; // 屏蔽折扣信息
});
} else {
logger.error('breakYards goods list code no 200');
}
return finalResult;
});
} else {
logger.error('breakYards size api code no 200');
return Promise.reject();
}
});
};
/**
* 获取sale活动数据(原sale.yohobuy.com)
* @param params
* @param channel
* @returns {*|Promise.<TResult>}
*/
exports.getSaleSpecialData = (id, params, channel) => {
const limit = params.limit ? params.limit - 1 : limitNum - 1; // 最后一个商品是翻页
const page = params.page || 1;
const defaultParam = {specialsale_id: id};
return saleApi.getSaleSpecialAsync(id).then(special => {
let resData = {
latestWalk: 6
},
apiList = [
headerModel.requestHeaderData(channel),
searchApi.getSortList(defaultParam)
];
if (special && special.data) {
let data = special.data,
condition = Object.assign({}, params, {
page: page,
limit: limit,
attribute_not: 2
});
let banner = JSON.parse(data.banner_img) || [];
Object.assign(resData, {
mainBanner: {
src: imageHandler(_.get(banner, '[0].img', ''), 1920, 350, 1, 'couponImg')
},
specialHead: {
title: '全部商品',
count: 0
},
node: data.left_ad_code // 水牌node
});
// 传品牌ID参数
if (special.brand_id) {
condition.brand = data.brand_id;
}
// 传促销id,促销id为空时传专区id
if (data.ispromotion) {
condition.promotion = data.ispromotion;
}
// 搜索sale活动商品
apiList.push(searchApi.getProductList(condition));
}
return Promise.all(apiList).then(result => {
if (!_.isEmpty(result[0])) {
resData.headerData = Object.assign(result[0].headerData, {header: true});
}
if (!_.isEmpty(result[1])) {
resData.leftContent = searchHandler.handleSortData(_.get(result[1],
'data.sort', []), defaultParam);
}
if (!_.isEmpty(result[2])) {
let tip = {
start: (_.get(result[2], 'data.page', 1) - 1) * limitNum + 1,
total: _.get(result[2], 'data.total', 0)
};
tip.end = tip.start + limit - 1;
if (tip.end > tip.total) {
tip.end = tip.total;
}
resData.specialHead.count = tip.total;
Object.assign(resData, {
filters: searchHandler.handleFilterDataAll(_.get(result[2], 'data', {}), params),
opts: searchHandler.handleOptsData(params, tip.total),
goods: productProcess.processProductList(_.get(result[2], 'data.product_list', [])),
footPager: {tip: tip}
});
if (_.has(resData, 'filters.checkedConditions')) {
_.set(resData, 'filters.checkedConditions.clearUrl', `?specialsale_id=${id}`);
}
// 设置分页
Object.assign(resData.footPager,
pager(_.get(result[2], 'data.page_total', 0), params));
if (_.has(resData, 'footPager.nextPage')) {
resData.hasNextPage = {
href: _.get(resData, 'footPager.nextPage.url', ''),
src: nextPageImg
};
}
}
return resData;
});
});
};
... ...
... ... @@ -7,10 +7,533 @@
const api = global.yoho.SearchAPI;
const yohoApi = global.yoho.API;
const serviceApi = global.yoho.ServiceAPI;
const _ = require('lodash');
const helpers = global.yoho.helpers;
const images = require('../../../utils/images.js');
const cache = global.yoho.cache;
const logger = global.yoho.logger;
const md5 = require('md5');
const config = require('../../../config/common');
const getSortByConditionAsync = (condition) => {
return api.get('sortgroup.json', condition);
};
// 获取list页广告
const adsUrl = '/shops/api/v1/ads/getList';
// 判断用户是否收藏品牌
const isFavoriteBrandUrl = '/shops/service/v1/favorite/getUidBrandFav';
// 根据品牌查询相关文章
const relateArticleUrl = 'guang/service/v2/article/getArticleByBrand';
const getSearchCackeKey = params => {
let ks = [];
_.forEach(params, (val, key) => {
if (params.hasOwnProperty(key) && !_.includes(['page', 'limit', 'need_filter', 'order'], key)) {
ks.push(val);
}
});
return md5(ks.join('_'));
};
const getProductListOrig = (finalParams) => {
return yohoApi.get('', finalParams).then(result => {
return result;
});
};
/**
* 获取商品列表
* @return
*/
const getProductList = (params) => {
let finalParams = {
method: 'web.search.search',
sales: 'Y',
outlets: 2,
stocknumber: 1,
order: 's_n_desc',
need_filter: 'yes',
limit: 60
};
Object.assign(finalParams, params);
if (!config.useCache) {
return getProductListOrig(finalParams);
} else {
let cKey = getSearchCackeKey(finalParams);
return cache.get(cKey).catch().then(cdata => {
let hasCache = false;
if (cdata) {
try {
cdata = JSON.parse(cdata);
} catch (e) {
logger.debug('getProductList cache data parse fail.');
}
if (cdata.filter && cdata.standard) {
hasCache = true;
finalParams.need_filter = 'no';
}
}
return getProductListOrig(finalParams).then(result => {
if (hasCache && result && result.data) {
Object.assign(result.data, cdata);
} else {
if (result && result.data && result.data.filter) {
cache.set(cKey, Object.assign({}, {
filter: result.data.filter,
standard: result.data.standard
}), 3600);
}
}
return result;
});
});
}
};
const getSortListOrig = (finalParams) => {
return yohoApi.get('', finalParams).then(ret => {
return ret;
});
};
/**
* 获取分类列表
* @return
*/
const getSortList = (params) => {
let finalParams = {
method: 'web.regular.groupsort',
sales: 'Y', // 在销售商品分类
status: 1, // 上架商品分类
stocknumber: 1 // 过滤掉已售罄
};
Object.assign(finalParams, params);
if (!config.useCache) {
return getSortListOrig(finalParams);
} else {
let cKey = getSearchCackeKey(finalParams);
return cache.get(cKey).catch().then(cdata => {
let cdataObj;
if (cdata) {
try {
cdataObj = JSON.parse(cdata);
} catch (e) {
logger.debug('getSortList cache data parse fail.');
}
}
if (cdataObj) {
return cdataObj;
} else {
return getSortListOrig(finalParams).then(ret => {
if (ret && ret.code === 200) {
cache.set(cKey, ret, 3600);
}
return ret;
});
}
});
}
};
/**
* 获取分类图文介绍
* @return
*/
const getSortIntro = (params) => {
let finalParams = {
method: 'web.search.banner'
};
Object.assign(finalParams, params);
return yohoApi.get('', finalParams);
};
/**
* 获取分类广告
* @return
*/
const getSortAds = (params) => {
return serviceApi.get(adsUrl, params);
};
/**
* 获取品牌系列
* @return
*/
const getBrandSeries = (params) => {
let finalParams = {
method: 'web.brand.series',
brand_id: params.brandId,
status: params.status || 1
};
return yohoApi.get('', finalParams);
};
/**
* 获取品牌folder
* @return
*/
const getBrandFolder = (params) => {
let finalParams = {
method: 'web.brand.folder',
brand_id: params.brandId,
status: params.status || 1
};
return yohoApi.get('', finalParams);
};
/**
* 获取品牌水牌
* @return
*/
const getNodeContent = (params) => {
let finalParams = {
method: 'web.html.content',
mode: params.mode || 'release',
node: params.node || ''
};
return yohoApi.get('', finalParams);
};
/**
* 一周新品上架
* @return
*/
const getWeekNew = (params) => {
let finalParams = {
method: 'web.regular.recent'
};
Object.assign(finalParams, params);
return yohoApi.get('', finalParams);
};
/**
* 根据关键词搜索品牌店铺信息 TODO
* @return
*/
const getBrandShop = (query) => {
let finalParams = {
// method: 'web.regular.groupsort'
method: 'web.search.shopInfo'
};
Object.assign(finalParams, {keyword: query});
let cKey = getSearchCackeKey(finalParams);
return cache.get(cKey).catch().then(cdata => {
let retObj;
try {
if (cdata) {
retObj = JSON.parse(cdata);
}
} catch (e) {
logger.debug('getBrandShop cache data parse fail.');
}
if (retObj) {
return retObj;
} else {
return yohoApi.get('', finalParams).then(ret => {
if (ret && ret.code === 200) {
cache.set(cKey, ret.data, 3600);
return ret.data;
}
return null;
});
}
});
};
/**
* 根据品牌ID获取品牌下的店铺
* @return
*/
const getShopsByBrandId = bid => {
let finalParams = {
method: 'app.shop.queryShopsByBrandId',
brand_id: bid
};
let cKey = getSearchCackeKey(finalParams);
return cache.get(cKey).catch().then(cdata => {
let cdataObj;
if (cdata) {
try {
cdataObj = JSON.parse(cdata);
} catch (e) {
logger.debug('getShopsByBrandId cache data parse fail.');
}
}
if (cdataObj) {
return cdataObj;
} else {
return yohoApi.get('', finalParams).then(ret => {
if (ret && ret.code === 200) {
cache.set(cKey, ret.data, 3600);
return ret.data;
}
return null;
});
}
});
};
const shopFormat = shopDatas => {
let shopEntry = [];
_.forEach(shopDatas, val => {
let sorts = [];
let shopId = _.get(val, 'shop.shop_id', '');
let url = helpers.urlFormat('', {shopId: shopId}, val.shop.brand_domain);
if (val.shopSort) {
for (let ss of val.shopSort) {
if (!ss.sub) {
continue;
}
let isFull = false;
for (let misort of ss.sub) {
if (sorts.length >= 10) {
isFull = true;
break;
}
sorts.push({
href: `${url}&msort=${ss.sort_id}&misort=${misort.sort_id}`,
name: misort.sort_name
});
}
if (isFull) {
break;
}
}
}
shopEntry.push({
home: url,
logo: images.getImageUrl(val.shop.brand_ico, 80, 50, 1, 'brandLogo'),
shopName: val.shop.brand_name,
sort: sorts
});
});
return shopEntry;
};
/**
* 根据搜索得到店铺/品牌 列表
*/
const getShopList = params => {
if (!params || !params.query) {
return;
}
let brandShop;
let brandShops;
return getBrandShop(params.query).then(shop => { // 获取品牌,并根据品牌获取品牌下的所有店铺
if (!shop || !shop.id) {
return;
}
brandShop = shop;
return getShopsByBrandId(shop.id).then(shops => {
if (shops && shops.length) {
return shops;
} else {
return shop;
}
});
}).then(shops => { // 获取品牌/品牌店下所有的分类
if (_.isArray(shops)) {
brandShops = shops;
let promises = [];
for (let s of shops) {
promises.push(getSortList({
brand: s.brand_id
}));
}
return Promise.all(promises);
} else if (shops && shops.id) {
return getSortList({
brand: shops.id
});
}
}).then(sorts => { // 数组则为品牌店列表,否则为品牌
let shopData = [];
if (_.isArray(sorts)) {
_.forEach(sorts, (val, index) => {
shopData.push({
shop: brandShops[index],
shopSort: val && val.data && !_.isFunction(val.data.sort) && val.data.sort
});
});
} else if (sorts && sorts.code === 200 && sorts.data) {
shopData.push({
shop: brandShop,
shopSort: !_.isFunction(sorts.data.sort) && sorts.data.sort
});
}
return shopFormat(shopData);
});
};
/**
* 搜索提示
* @return
*/
const getSuggest = (params) => {
let finalParams = {
method: 'app.search.fuzzy',
keyword: params.keyword || ''
};
return yohoApi.get('', finalParams);
};
/**
* 根据品牌域名获取品牌信息
* @return
*/
const getBrandData = (params) => {
let finalParams = {
method: 'web.brand.byDomain',
domain: params.domain || ''
};
return yohoApi.get('', finalParams);
};
/**
* 根据uid和品牌id判断品牌是否收藏
* @return
*/
const isFavoriteBrand = (uid, brandId) => {
return serviceApi.get(isFavoriteBrandUrl, {
uid: uid,
brandId: brandId
});
};
/**
* 根据shopId获取店铺基本信息
* @return
*/
const getShopInfo = (shopId, uid) => {
let finalParams = {
method: 'app.shops.getIntro',
shop_id: shopId || 0,
uid: uid || 0
};
return yohoApi.get('', finalParams);
};
/**
* 查询店铺下面的所有品牌
*/
const getShopBrands = (shopId) => {
return yohoApi.get('', {method: 'app.shops.getShopsBrands', shop_id: shopId || 0});
};
/**
* 查询店铺装修
*/
const getShopDecorator = (shopId) => {
return yohoApi.get('', {method: 'app.shopsdecorator.getList', shop_id: shopId || 0});
};
/**
* 通过品牌获取相关文章
*/
const getArticleByBrand = (brand, udid, limit) => {
let params = {
brand_id: brand || 0,
udid: udid,
limit: limit || 6
};
return serviceApi.get(relateArticleUrl, params);
};
const getBrands4Filter = (params) => {
let finalParams = {
method: 'web.regular.aggBrand'
};
return yohoApi.get('', Object.assign({}, params, finalParams));
};
module.exports = {
getSortByConditionAsync
getSortByConditionAsync,
getProductList,
getSortList,
getSortIntro,
getSortAds,
getBrandFolder,
getBrandSeries,
getWeekNew,
getBrandShop,
getSuggest,
getBrandData,
getNodeContent,
isFavoriteBrand,
getShopInfo,
getShopBrands,
getShopDecorator,
getArticleByBrand,
getShopList,
getBrands4Filter
};
... ...