... ... @@ -5,6 +5,10 @@
*/
'use strict';
if (process.env.USE_APM === '1' && process.env.NODE_ENV === 'production') {
require('oneapm');
}
const config = require('./config/common');
global.Promise = require('bluebird');
... ...
... ... @@ -160,7 +160,7 @@ const getBrandViewList = (channel, start, length) => {
let res = yield brandApi.getBrandListData(switchParams.channelType);
let result = [],
navigation = [];
numResult = {};
if (!res || res.code !== 200) {
return result;
... ... @@ -195,12 +195,18 @@ const getBrandViewList = (channel, start, length) => {
listTmp.push(brandItem);
});
navigation.push(key);
result.push({
key: key,
val: _.sortBy(listTmp, 'name')// 对name排序
});
if (key.match(/\d+/g)) {
numResult = {// 把0-9提出来
key: key,
val: _.sortBy(listTmp, 'name')// 对name排序
};
} else {
result.push({
key: key,
val: _.sortBy(listTmp, 'name')// 对name排序
});
}
});
}
... ... @@ -208,15 +214,15 @@ const getBrandViewList = (channel, start, length) => {
// 只取部分数据
let begin;
if (start) {
begin = (start - 1) ? (start - 1) : 0;
begin = (begin > 0) ? begin : 0;
result = length ? result.slice(begin, length + begin) : result.slice(begin);
}
result.navigation = navigation;
result = _.sortBy(result, 'key');// A-Z排序
result.push(numResult); // 0-9放到最后
result.navigation = _.map(result, 'key');
return result;
})();
};
... ...
... ... @@ -113,9 +113,9 @@ const easypayOrderSubmitAsync = (uid, cartType, addressId, deliveryTime, deliver
if (other.invoicesType) {
Object.assign(param, {
invoices_type: other.invoicesType,
invoices_itle: other.invoicesTitle,
invoices_title: other.invoicesTitle,
invoice_content: other.invoicesContent,
receiverMobile: other.receiverMobile
receiverMobile: other.receiver
});
}
... ...
... ... @@ -12,7 +12,7 @@ const crypto = global.yoho.crypto;
const easypayApi = require('./easypay-api');
const handelViewPrice = list => {
const _handelViewPrice = list => {
if (list) {
_.forEach(list, val => {
if (val.promotion === '商品金额') {
... ... @@ -26,6 +26,36 @@ const handelViewPrice = list => {
}
};
const _handelUseYohoCoin = (info) => {
let resData = {};
let limitCoin = _.get(info, 'yoho_coin_pay_rule.num_limit', 0);
if (info) {
Object.assign(resData, {
yoho_coin: info.yoho_coin.toFixed(2),
use_yoho_coin: info.use_yoho_coin,
total_yoho_coin_num: info.total_yoho_coin_num,
yoho_coin_pay_rule: info.yoho_coin_pay_rule,
canUseCoinNum: _.round(info.yoho_coin * 100),
usedCoinNum: _.round(info.use_yoho_coin * 100)
});
if (!resData.canUseCoinNum) {
let coinErrorTip = '';
if (info.total_yoho_coin_num > limitCoin) {
coinErrorTip = '抱歉,您的订单实付款不满足有货币使用条件';
} else {
coinErrorTip = `抱歉,您的有货币不足,有货币满${limitCoin}个方可使用`;
}
resData.coinErrorTip = coinErrorTip;
}
}
return resData;
};
const _handelPaymentInfo = (d) => {
let resData = {};
... ... @@ -81,14 +111,14 @@ const _handelPaymentInfo = (d) => {
};
if (d.shopping_cart_data && d.shopping_cart_data.promotion_formula_list) {
handelViewPrice(d.shopping_cart_data.promotion_formula_list);
_handelViewPrice(d.shopping_cart_data.promotion_formula_list);
}
Object.assign(resData, {
paymentWay: d.payment_way,
deliveryTime: d.delivery_time,
deliveryWay: d.delivery_way,
shoppingCartData: d.shopping_cart_data,
shoppingCartData: Object.assign(d.shopping_cart_data, _handelUseYohoCoin(d)),
invoices: d.invoices
});
... ... @@ -97,16 +127,15 @@ const _handelPaymentInfo = (d) => {
const _getLimitProductData = (params) => {
let info = {
type: 'limitcode',
buy_number: 1
},
limitCode = crypto.decrypt('', decodeURIComponent(params.limitcode));
type: 'limitcode',
buy_number: 1
};
if (params.sku && params.skn && params.limitcode) {
Object.assign(info, {
sku: params.sku,
skn: params.skn,
limitproductcode: parseInt(limitCode, 10)
limitproductcode: params.limitcode
});
return JSON.stringify([info]);
... ... @@ -132,18 +161,21 @@ const getEasypayOrderData = (params, uid) => {
});
};
const getOrderComputeData = (uid, cartType, params) => {
params.productSkuList = _getLimitProductData(params);
return easypayApi.getEasypayComputeAsync(uid, cartType, params.paymentType, params.deliveryWay, params).then(result => { // eslint-disable-line
if (result.code === 200) {
if (_.has(result, 'data.last_order_amount')) {
result.data.last_order_amount = _.round(result.data.last_order_amount, 2);
result.data.last_order_amount = (result.data.last_order_amount).toFixed(2);
}
if (_.has(result, 'data.promotion_formula_list')) {
handelViewPrice(result.data.promotion_formula_list);
_handelViewPrice(result.data.promotion_formula_list);
}
result.data = Object.assign(result.data, _handelUseYohoCoin(result.data));
}
return result;
});
... ...
... ... @@ -268,23 +268,37 @@
<span id="use-coin" class="use-coin coin-trigger">使用有货币支付</span>
<div class="using-coin coin-trigger hide">
<ul>
<ul id="using-coin-cont">
{{#if coinErrorTip}}
<li><span class="red">{{coinErrorTip}}</span></li>
{{/if}}
<li>
使用有货币:<input id="coin-used" class="coin-used" type="text" data-max="{{hasCoin}}">
</li>
<li class="coin-sum-row">
您目前有有货币<em>{{hasCoin}}</em>
有货币满<span class="red">{{yoho_coin_pay_rule.num_limit}}</span>个即可使用,每次使用有货币为<span class="red">{{yoho_coin_pay_rule.num_limit}}</span>的整数倍
<i class="iconfont help-icon">&#xe628;</i>
<div class="coin-tip-help">
<p>有货币使用条件:</p>
<p>
1.订单金额大于20元(含20元)<br>
2.有货币数量大于{{yoho_coin_pay_rule.num_limit}}个(含{{yoho_coin_pay_rule.num_limit}}个) <br>
3.有货币支付不得超过每笔订单应付金额的{{yoho_coin_pay_rule.max_pay_rate_desc}}
</p>
<p class="rs-text">备注:使用有货币数量为{{yoho_coin_pay_rule.num_limit}}的整数倍,100有货币抵1元</p>
</div>
</li>
<li class="coin-tip-row">
<span id="coin-tip" class="coin-tip vhide"></span>
<li>您当前共有有货币 <span class="red">{{total_yoho_coin_num}}</span> 个,可用 <span class="red">{{canUseCoinNum}}</span></li>
<li>
<p{{#if coinErrorTip}} class="coin-use-hide"{{/if}}>本次使用有货币<span class="red">{{canUseCoinNum}}</span>个,抵扣 <span class="red">¥{{yoho_coin}}</span></p>
</li>
</ul>
<p class="btns">
<span id="coin-sure" class="coin-sure sure-btn">确定</span>
<span id="coin-cancel" class="coin-cancel cancel-btn">取消</span>
<a href="/help/?category_id=87" class="coin-help" target="_blank">有货币使用规则?</a>
</p>
</div>
<input id="coin-used" type="hidden" data-coin="{{usedCoinNum}}" data-max={{canUseCoinNum}}>
</li>
</ul>
</div>
... ...
... ... @@ -101,6 +101,30 @@
\{{/each}}
</script>
<script id="yoho-coin-tpl" type="text/html">
\{{#if coinErrorTip}}
<li><span class="red">\{{coinErrorTip}}</span></li>
\{{/if}}
<li>
有货币满<span class="red">\{{yoho_coin_pay_rule.num_limit}}</span>个即可使用,每次使用有货币为<span class="red">\{{yoho_coin_pay_rule.num_limit}}</span>的整数倍
<i class="iconfont help-icon">&#xe628;</i>
<div class="coin-tip-help">
<p>有货币使用条件:</p>
<p>
1.订单金额大于20元(含20元)<br>
2.有货币数量大于\{{yoho_coin_pay_rule.num_limit}}个(含\{{yoho_coin_pay_rule.num_limit}}个) <br>
3.有货币支付不得超过每笔订单应付金额的\{{yoho_coin_pay_rule.max_pay_rate_desc}}
</p>
<p class="rs-text">备注:使用有货币数量为\{{yoho_coin_pay_rule.num_limit}}的整数倍,100有货币抵1元</p>
</div>
</li>
<li>您当前共有有货币 <span class="red">\{{total_yoho_coin_num}}</span> 个,可用 <span class="red">\{{canUseCoinNum}}</span> 个</li>
<li>
<p\{{#if coinErrorTip}} class="coin-use-hide"\{{/if}}>本次使用有货币<span class="red">\{{canUseCoinNum}}</span>个,抵扣 <span class="red">¥\{{yoho_coin}}</span></p>
</li>
</script>
<script id="promotion-list-tpl" type="text/html">
\{{#each promotion_formula_list}}
<li class="promotion-item\{{#isEqual promotion '运费'}} fregit-promotion\{{/isEqual}}">
... ...
... ... @@ -15,7 +15,7 @@ exports.index = (req, res, next) => {
// 将woman转换为girls,以便model层进行处理
channelType === 'woman' ? channelType = 'girls' : null;
channelModel.getContent(channelType, req).then(data => {
channelModel.getContent(channelType).then(data => {
// channel为空不缓存
if (_.isEmpty(data.channel)) {
... ... @@ -28,7 +28,7 @@ exports.index = (req, res, next) => {
exports.getbrandFloorDataAjax = (req, res, next) => {
const channelType = req.query.channelType || 'boys';
channelModel.getbrandFloorDataAjax(channelType, req).then(data => {
channelModel.getbrandFloorDataAjax(channelType).then(data => {
res.json(data);
}).catch(next);
};
... ... @@ -77,3 +77,10 @@ exports.getIndexGuide = (req, res, next) => {
res.render('guide', result);
}).catch(next);
};
exports.hasNewUserFloor = (req, res, next) => {
channelModel.hasNewUserFloor(req.yoho.channel, req.user.uid).then(data => {
res.send(data);
}).catch(next);
};
... ...
... ... @@ -576,7 +576,6 @@ const _requestContent = (type, params) => {
};
Object.assign(data, params);
return serviceApi.get('operations/api/v5/resource/home', data, {
cache: true,
code: 200
... ... @@ -894,14 +893,9 @@ const getNewArrival = channel => {
* @param {String} type 传入频道页类型,值可以是: boys, girls, kids, lifestyle
* @return {Object}
*/
const getContent = (type, req) => {
let params = {};
const getContent = (type) => {
let params = {new_device: 'Y'};
if (!req.user.uid) {
params.new_device = 'Y';
} else {
params.uid = req.user.uid;
}
return Promise.all([headerModel.requestHeaderData(type), _requestContent(type, params)]).then(res => {
let headerData = res[0].data || res[0],
... ... @@ -956,14 +950,9 @@ const getContent = (type, req) => {
// 优选品牌楼层floorData-ajax
const getbrandFloorDataAjax = (type, req) => {
let params = {};
const getbrandFloorDataAjax = (type) => {
let params = {new_device: 'Y'};
if (!req.user.uid) {
params.new_device = 'Y';
} else {
params.uid = req.user.uid;
}
return _requestContent(type, params).then(res => {
let contentData = res.data ? res.data.list : [];
... ... @@ -1026,12 +1015,34 @@ const getIndexGuideData = () => {
return serviceApi.get('operations/api/v6/category/getCategory', params, config.apiCache);
};
const hasNewUserFloor = (channelType, uid) => {
let params = {uid: uid};
return _requestContent(channelType, params).then(res => {
let isNewUser = false,
contentData = res.data ? res.data.list : res;
_.forEach(contentData, (data) => {
if (data.template_name === 'new_user_floor' || data.template_intro === '新人专享') {
isNewUser = true;
return false;
}
});
return {
isNewUser: isNewUser
};
});
};
module.exports = {
getNewArrival: getNewArrival,
getContent: getContent,
getbrandFloorDataAjax: getbrandFloorDataAjax,
getIndexGuideData: getIndexGuideData,
formatIndexGuideData: formatIndexGuideData,
getResourceData: getResourceData
getResourceData: getResourceData,
hasNewUserFloor: hasNewUserFloor
};
... ...
... ... @@ -6,7 +6,7 @@
'use strict';
const router = require('express').Router(); // eslint-disable-line
const router = require('express').Router(); // eslint-disable-line
const cRoot = './controllers';
// Your controller here
... ... @@ -17,6 +17,7 @@ router.get('/', channelController.index);
router.get('/woman', channelController.index);
router.get('/kids', channelController.index);
router.get('/lifestyle', channelController.index);
router.get('/channel/isNewUserAjax', channelController.hasNewUserFloor);
// ajax
router.get('/getbrandFloorDataAjax', channelController.getbrandFloorDataAjax);
... ...
... ... @@ -235,7 +235,7 @@ const local = {
loginService.verifyPasswordBySMS(area, mobile, code).then((result) => {
if (_.get(result, 'code', 200) !== 200) {
return Promise.reject('error');
return res.json(result);
}
let pass = _.get(result, 'data.is_pass', 'N');
... ...
... ... @@ -6,10 +6,10 @@
<ul class="login-ul">
<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 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">
... ... @@ -30,7 +30,7 @@
<li class="relative">
<div class="switch">
<div class="left selected" data-type="PasswordLogin">普通登录</div>
<div class="right" data-type="SMSLogin">手机验证码登录</div>
<div class="right" data-type="SMSLogin">手机验证码登录</div>
</div>
</li>
... ... @@ -55,20 +55,10 @@
</span>
</li>
<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 class="clearfix sms-captcha-img-wrap captcha-wrap sms-login hide">
<input id="sms-captcha-input" class="input va captcha" type="text" name="captcha" placeholder="图形验证码"
<li class="clearfix captcha-wrap hide">
<input id="captcha" class="input va captcha" type="text" name="captcha" placeholder="图形验证码"
autocomplete="off" maxlength="4">
<img id="sms-captcha-img" class="captcha-img" alt="">
<img id="captcha-img" class="captcha-img" alt="">
<a class="link change-captcha">换一张</a>
<span class="err-tip hide">
<i></i>
... ... @@ -76,21 +66,21 @@
</span>
</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>
<span class="err-tip hide">
<i></i>
<em></em>
</span>
</li>
<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 class="clearfix captcha-wrap hide">
<input id="captcha" class="input va captcha" type="text" name="captcha" placeholder="图形验证码"
<li class="clearfix sms-captcha-img-wrap sms-login hide">
<input id="sms-captcha-input" class="input va captcha" type="text" name="captcha"
placeholder="图形验证码"
autocomplete="off" maxlength="4">
<img id="captcha-img" class="captcha-img" alt="">
<img id="sms-captcha-img" class="captcha-img" alt="">
<a class="link change-captcha">换一张</a>
<span class="err-tip hide">
<i></i>
... ... @@ -98,6 +88,17 @@
</span>
</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>
<span class="err-tip hide">
<i></i>
<em></em>
</span>
</li>
<li class="desktop-login">
<span id="login-btn" class="login-btn btn">登录</span>
</li>
... ...
... ... @@ -14,9 +14,10 @@ const fav = require('../models/favorite');
const changeFavoriteBrand = (req, res, next) => {
let uid = req.user.uid || '';
let brandId = req.body.brandId;
let type = req.body.type || '';
if (uid && brandId) {
brandService.changeAsync(uid, brandId).then(result => {
brandService.changeAsync(type, uid, brandId).then(result => {
return res.json(result);
}).catch(next);
} else if (!uid) {
... ...
... ... @@ -8,39 +8,7 @@ const api = require('./coupon-api');
const _ = require('lodash');
const decrypt = _.partial(global.yoho.crypto.decrypt, null);
const _acquireAsync = _.overArgs(api.acquireAsync, [decrypt, _ => _]);
const acquireAsync = (cid, uid) => {
return _acquireAsync(cid, uid).then(result => {
switch (result.code) {
case 200:
return {
code: 200,
message: '恭喜您,成功领取优惠券'
};
case 401:
return {
code: 401,
message: '您已领取过优惠券'
};
case 315:
return {
code: 315,
message: '优惠券已过期'
};
case 300:
return {
code: 300,
message: '请求参数错误'
};
default:
return {
code: 500,
message: '领券失败!'
};
}
});
};
const acquireAsync = _.overArgs(api.acquireAsync, [decrypt, _1 => _1]);
module.exports = {
acquireAsync,
... ...
... ... @@ -1121,7 +1121,7 @@ const _detailDataPkg = (origin, uid, vipLevel, cookies) => {
};
if (propOrigin('isLimitBuy', false) && propOrigin('limitProductCode', '')) {
result.limitProductCode = crypto.encryption(null, propOrigin('limitProductCode') + '');
result.limitProductCode = propOrigin('limitProductCode');
requestApi.limited = productAPI.getLimitedProductStatusAsync(
propOrigin('limitProductCode'),
... ... @@ -1203,6 +1203,9 @@ const _detailDataPkg = (origin, uid, vipLevel, cookies) => {
delete result.salePrice;
result.hasOtherPrice = false;
// 普通预售
result.presale = 'Y';
}
// sku商品信息
... ... @@ -1238,8 +1241,18 @@ const _detailDataPkg = (origin, uid, vipLevel, cookies) => {
result.buyNow = fashTopGoods.buyNow; // 是否立即购买
result.buyNowBase = helpers.urlFormat('/cart/easypay'); // 购买链接
}
// 限购商品
result.limitedsale = 'Y';
}
// 非普通商品没有优惠券
const isSpecialProduct = (pro) => {
return pro.limitedsale === 'Y' || pro.secKill === 'Y' || pro.deposit === 'Y' || pro.presale === 'Y';
};
result.coupon = !isSpecialProduct(result) ? result.coupon : [];
// 商品购买状态
let soldOut = !!(propOrigin('status') === 0 || totalStorageNum === 0);
let notForSale = propOrigin('attribute') === 2; // 非卖品
... ... @@ -1353,6 +1366,7 @@ const _detailDataPkg = (origin, uid, vipLevel, cookies) => {
if (!_.has(result, 'fashionTopGoods')) {
cookies && cookies(_.get(result, 'skn', ''));
}
return {
goodsInfo: result,
banner: _.isEmpty(bandInfo) ? null : bandInfo,
... ... @@ -1479,7 +1493,9 @@ const recommendAsync = (skn, page, limit) => {
if (_.get(recommendData, 'code', 400) !== 200) {
return {
code: 200,
products: []
data: {
products: []
}
};
}
... ...
... ... @@ -4,23 +4,17 @@
'use strict';
const serviceAPI = global.yoho.ServiceAPI;
const api = require('./favorite-api');
const _ = require('lodash');
const isFavoriteAsync = (uid, bid) => {
return serviceAPI.get('shops/service/v1/favorite/getUidBrandFav', {
uid: uid,
brandId: bid
});
};
const isFavoriteAsync = _.partial(api.isFavAsync, _, _, 'brand');
const changeAsync = (uid, brandId) => {
return serviceAPI.get('guang/service/v2/favorite/toggleBrand', {
uid: uid,
brand_id: brandId
});
};
const addFavAsync = _.partial(api.addFavAsync, _, _, 'brand');
const cancelFavAsync = _.partial(api.cancelFavAsync, _, _, 'brand');
module.exports = {
isFavoriteAsync,
changeAsync
addFavAsync,
cancelFavAsync
};
... ...
... ... @@ -6,5 +6,21 @@
const api = require('./favorite-brand-api');
module.exports = api;
const changeAsync = (type, uid, brandId) => {
switch (type) {
case 'add':
return api.addFavAsync(uid, brandId);
case 'cancel' :
return api.cancelFavAsync(uid, brandId);
default:
return Promise.reject('favorite brand error');
}
};
const isFavoriteAsync = api.isFavoriteAsync;
module.exports = {
changeAsync,
isFavoriteAsync
};
... ...
... ... @@ -312,6 +312,10 @@ const getBrandData = (params, extra, channel) => {
}
});
if (queryBase.shop_id) {
dps.shopId = queryBase.shop_id;
}
Object.assign(finalResult.brand, {
leftContent: searchHandler.handleSortData(result[1].data.sort, dps, params)
}, searchHandler.handlePathNavData(extra, params, 'brand', channel));
... ... @@ -349,7 +353,7 @@ const getBrandData = (params, extra, channel) => {
finalResult.criteo = {skn: searchHandler.getCriteo(_.get(finalResult.brand, 'goods'))};
let seo = searchHandler.getBrandSeo(channel, extra);
let seo = searchHandler.getBrandShopSeo(channel, extra, params);
return Object.assign({}, seo, finalResult);
});
... ... @@ -563,7 +567,7 @@ const getShopData = (shopId, channel, params, shopInfo) => {
Object.assign(finalResult,
result[0], // 头部数据
searchHandler.handlePathNavData(shopInfo, params, 'shop', channel), // 面包屑导航
shopHandler.setShopSeo(shopInfo.shopName || shopInfo.brandName) // 店铺SEO
searchHandler.getBrandShopSeo(channel, {shopName: shopInfo.shopName || shopInfo.brandName}, params) // 店铺SEO
);
_.set(finalResult, 'headerData.header', true);
... ... @@ -806,7 +810,9 @@ const getShopListData = (channel, params, uid) => {
});
// 店铺SEO
Object.assign(finalResult, shopHandler.setShopSeo(data.shop_name));
Object.assign(finalResult, searchHandler.getBrandShopSeo(channel, {
shopName: data.shop_name
}, params));
}
} else {
return Promise.reject('No ShopDecorator data');
... ... @@ -872,12 +878,13 @@ const getShopListData = (channel, params, uid) => {
return searchApi.getSortList({brand: shopBrandIds}).then(subRes => {
if (subRes.code === 200) {
let groupSort = _.get(subRes, 'data.sort', []);
let groupSort = _.get(subRes, 'data.sort', []),
noPageQs = Object.assign({}, params, {page: 1});
finalResult.leftContent = searchHandler.handleSortData(groupSort, params);
finalResult.leftContent = searchHandler.handleSortData(groupSort, noPageQs);
if (finalResult.allGoods) {
Object.assign(finalResult.allGoods, searchHandler.setShopSort(groupSort, params));
Object.assign(finalResult.allGoods, searchHandler.setShopSort(groupSort, noPageQs));
}
}
... ... @@ -939,7 +946,9 @@ const getBaseShopData = (params, extra, channel, shopId) => {
});
// 店铺SEO
Object.assign(resData, shopHandler.setShopSeo(shopName));
Object.assign(resData, searchHandler.getBrandShopSeo(channel, {
shopName: shopName
}, params));
}
_.unset(resData, 'brand.coupon');
... ...
... ... @@ -425,7 +425,7 @@ const getShopList = params => {
for (let s of shops) {
promises.push(getSortList({
brand: s.brand_id
brand: s.brand_id || brandShop.id
}));
}
... ...
... ... @@ -1427,34 +1427,65 @@ exports.getNewSeo = (channel, dlist) => {
};
/**
* 品牌页 seo
* 品牌店铺页 seo
* @param channel
* @param brandInfo
* @param info
* @param qs
* @returns {{title: (string|*|string), keywords: string, description: string}}
*/
exports.getBrandSeo = (channel, brandInfo) => {
let c = getChannelName(channel),
bcn = brandInfo && brandInfo.brandNameCn,
b = brandInfo && brandInfo.brandNameEn,
bb = b + ' ' + bcn,
bc = b + c,
bbc = b + bcn + c,
keywords = [b ? b + ',' : '',
((b && bcn) ? (bb + ',') : ''),
bc || '',
'品牌'].join(''),
desc = [b + '正品网购。',
bbc || '',
'品牌官方授权!YOHO! 有货中国最大的潮流商品购物网站。100%品牌正品保证,支持货到付款。'].join('');
let title = (b ? (b + '|') : '') + (bb ? (bb + '|') : '') + c + '品牌|YOHO!BUY 有货 100%正品保证';
return {
title: title,
keywords: keywords,
description: desc
exports.getBrandShopSeo = (channel, info, qs) => {
let resData = {},
ctype = {
boys: {fashionType: '男装', brandType: '男生品牌'},
girls: {fashionType: '女装', brandType: '女生品牌'},
kids: {fashionType: '童装', brandType: '潮童品牌'},
lifestyle: {fashionType: '创意生活', brandType: '创意生活品牌'}
};
let params = {
nameEn: '',
name: ''
};
if (info) {
Object.assign(params, {
nameEn: _.get(info, 'brandNameEn', ''),
nameCn: _.get(info, 'brandNameCn', '')
});
params.name = `${params.nameEn} ${params.nameCn}`;
if (info.shopName) {
Object.assign(params, {
nameEn: info.shopName,
name: info.shopName
});
}
}
if (qs && qs.gender) {
if (qs.gender === '1,3') {
channel = 'boys';
} else if (qs.gender === '2,3') {
channel = 'girls';
}
Object.assign(params, ctype[channel] || ctype.boys);
Object.assign(resData, {
title: `${params.nameEn} | ${params.name} ${params.brandType}`,
keywords: `${params.nameEn}, ${params.name} ${params.fashionType},${params.nameEn} ${params.brandType}`,
description: `${params.nameEn}正品网购。${params.name}官方授权!`
});
} else {
Object.assign(resData, {
title: `${params.nameEn} | ${params.name}官网`,
keywords: `${params.nameEn}, ${params.name}官网`,
description: `${params.nameEn}正品网购。${params.name}官方授权!`
});
}
resData.title += resData.title ? ' | YOHO!BUY 有货 100%正品保证' : '';
resData.description += resData.description ? ' YOHO!BUY 有货中国最大的潮流商品购物网站。100%品牌正品保证,支持货到付款。' : ''; // eslint-disable-line
return resData;
};
/**
... ...
... ... @@ -16,14 +16,6 @@ const newProductsName = '新品上架 NEW';
const hotProductsName = '人气单品 HOT';
const shopListUrl = '/product/shoplist';
exports.setShopSeo = (shopName) => {
return {
title: `${shopName} | ${shopName} 潮流服装服饰-Yoho!Buy有货`,
keywords: `${shopName},${shopName} 服装服饰,${shopName} 潮流服装服饰`,
description: `${shopName} | Yoho!Buy有货 ${shopName} 潮流服饰官方授权店!100%品牌正品保证,支持货到付款。`
};
};
/**
* 新品上架
*/
... ... @@ -361,20 +353,17 @@ exports.getShopDecorator = (data, params, shopId, base) => {
if (base) {
_.forEach(data.list, (value) => {
if (!_.isEmpty(value.resource_data)) {
let info = Fn.pipe(JSON.parse, _.partial(_handleSaleCategory, shopId))(value.resource_data);
switch (value.resource_name) {
case 'signboard':
dest.signboard = signboard(info);
break;
case 'shopTopBanner_base':
Object.assign(dest, shopTopBannerBase(info));
break;
default:
break;
}
let info = Fn.pipe(JSON.parse, _.partial(_handleSaleCategory, shopId))(value.resource_data || '[]');
switch (value.resource_name) {
case 'signboard':
dest.signboard = signboard(info);
break;
case 'shopTopBanner_base':
Object.assign(dest, shopTopBannerBase(info));
break;
default:
break;
}
});
} else {
... ... @@ -384,46 +373,44 @@ exports.getShopDecorator = (data, params, shopId, base) => {
});
_.forEach(data.list, (value) => {
if (!_.isEmpty(value.resource_data)) {
let info = Fn.pipe(JSON.parse, _.partial(_handleSaleCategory, shopId))(value.resource_data);
let tabBar;
switch (value.resource_name) {
case 'newProducts':
Object.assign(dest.newArrivel, newProducts(info));
break;
case 'hotProducts':
Object.assign(dest.hotSingle, hotProducts(info));
break;
case 'goodsTabBar':
tabBar = goodsTabBar(info, shopId);
Object.assign(dest.newArrivel, {navs: tabBar.new});
Object.assign(dest.hotSingle, {navs: tabBar.hot});
break;
case 'shopTopBanner':
Object.assign(dest, shopTopBanner(info));
break;
case 'navigationBar':
Object.assign(dest, navigationBar(info, shopId));
break;
case 'largeSlideImg':
Object.assign(dest, largeSlideImg(info, shopId));
break;
case 'oneRowTwoColImages':
Object.assign(dest, oneRowTwoColImages(info, shopId));
break;
case 'recommend':
Object.assign(dest, recommend(info, shopId));
break;
case 'brandBrowse':
Object.assign(dest, brandBrowse(info, params));
break;
case 'hotRecommend':
Object.assign(dest, hotRecommend(info));
break;
default:
break;
}
let info = Fn.pipe(JSON.parse, _.partial(_handleSaleCategory, shopId))(value.resource_data || '[]');
let tabBar;
switch (value.resource_name) {
case 'newProducts':
Object.assign(dest.newArrivel, newProducts(info));
break;
case 'hotProducts':
Object.assign(dest.hotSingle, hotProducts(info));
break;
case 'goodsTabBar':
tabBar = goodsTabBar(info, shopId);
Object.assign(dest.newArrivel, {navs: tabBar.new});
Object.assign(dest.hotSingle, {navs: tabBar.hot});
break;
case 'shopTopBanner':
Object.assign(dest, shopTopBanner(info));
break;
case 'navigationBar':
Object.assign(dest, navigationBar(info, shopId));
break;
case 'largeSlideImg':
Object.assign(dest, largeSlideImg(info, shopId));
break;
case 'oneRowTwoColImages':
Object.assign(dest, oneRowTwoColImages(info, shopId));
break;
case 'recommend':
Object.assign(dest, recommend(info, shopId));
break;
case 'brandBrowse':
Object.assign(dest, brandBrowse(info, params));
break;
case 'hotRecommend':
Object.assign(dest, hotRecommend(info));
break;
default:
break;
}
});
}
... ...
... ... @@ -358,9 +358,9 @@
{{#unless @root.pc.product.removeRecentView}}
<div class="individual-comment info-block">
<p class="block-title">
<span class="title cur">店铺推荐 SHOP RECOMMENDED</span>
<span class="sep">|</span>
<span class="title">最近浏览 RECENT REVIEW</span>
<span class="title hide">店铺推荐 SHOP RECOMMENDED</span>
<span class="sep hide">|</span>
<span class="title cur">最近浏览 RECENT REVIEW</span>
</p>
{{#if latestWalk}}
<div class="latest-walk">
... ...
... ... @@ -17,13 +17,13 @@ module.exports = {
cookieDomain: '.yohobuy.com',
domains: {
favApi: 'http://192.168.102.31:8092/brower',
api: 'http://api-test3.yohops.com:9999/',
service: 'http://service-test3.yohops.com:9999/',
//api: 'http://api-test3.yohops.com:9999/',
//service: 'http://service-test3.yohops.com:9999/',
//
api: 'http://api.yoho.cn/',
service: 'http://service.yoho.cn/',
//api: 'http://api.yoho.cn/',
//service: 'http://service.yoho.cn/',
// api: 'http://dev-api.yohops.com:9999/',
//api: 'http://dev-api.yohops.com:9999/',
// service: 'http://dev-service.yohops.com:9999/',
search: 'http://192.168.102.216:8080/yohosearch/'
... ...
... ... @@ -10,6 +10,11 @@
<meta name="apple-mobile-web-app-status-bar-style" content="black" />
<meta content="telephone=no" name="format-detection" />
<meta content="email=no" name="format-detection" />
<!-- oneapm js agent -->
<script type='text/javascript'>window.BWEUM||(BWEUM={});BWEUM.info = {"stand":true,"agentType":"browser","agent":"bi-collector.oneapm.com/static/js/bw-send-411.4.9.js","beaconUrl":"bi-collector.oneapm.com/beacon","licenseKey":"NQVuf~6yrQbvJnqr","applicationID":2283338};</script><script type="text/javascript">/*!OneAPM-v411.4.9 */!function(){window.NREUM||(window.NREUM={}),window.BWEUM||(window.BWEUM=window.NREUM);var a;window.BWEUM.require=a,window.apmFirstbyte=window.apmUserFirstbyte||(new Date).getTime(),a=function b(c,d,e){function f(h,i){if(!d[h]){if(!c[h]){var j="function"==typeof a&&a;if(!i&&j)return j(h,!0);if(g)return g(h,!0);var k=new Error("Cannot find module '"+h+"'");throw k.code="MODULE_NOT_FOUND",k}var l=d[h]={exports:{}};c[h][0].call(l.exports,function(a){var b=c[h][1][a];return f(b?b:a)},l,l.exports,b,c,d,e)}return d[h].exports}for(var g="function"==typeof a&&a,h=0;h<e.length;h++)f(e[h]);return f}({38:[function(a,b){b.exports=function(a){var b=document.createElement("a"),c=window.location,d={};b.href=a,d.port=b.port;var e=b.href.split("://");return!d.port&&e[1]&&(d.port=e[1].split("/")[0].split(":")[1]),d.port&&"0"!==d.port||(d.port="https"===e[0]?"443":"80"),d.hostname=b.hostname||c.hostname,d.pathname=b.pathname,"/"!==d.pathname.charAt(0)&&(d.pathname="/"+d.pathname),d.sameOrigin=!b.hostname||b.hostname===document.domain&&b.port===c.port&&b.protocol===c.protocol,d}},{}],34:[function(a,b){function c(){var a=m.info=window.BWEUM.info;if(a&&a.agent&&a.licenseKey&&a.applicationID&&i&&i.body){m.proto="https"===l.split(":")[0]||a.sslForHttp?"https://":"http://",g("mark",["onload",f()]);var b=i.createElement("script");b.src=0==a.agent.indexOf("//")?a.agent:m.proto+a.agent,b.src+="?v=411.4.9 ",i.body.appendChild(b)}}function d(){o||"complete"===i.readyState&&e()}function e(){g("mark",["domContent",f()])}function f(){return(new Date).getTime()}var g=a("handle"),h=window,i=h.document,j="addEventListener",k="attachEvent",l=(""+location).split("?")[0],m=b.exports={offset:window.apmFirstbyte||f(),origin:l,features:{}};g("mark",["firstbyte",window.apmFirstbyte||f()]),"complete"===document.readyState?(e(),c()):i[j]?(i[j]("DOMContentLoaded",e,!1),h[j]("load",c,!1)):(i[k]("onreadystatechange",d),h[k]("onload",c));var n=!1,o=!1;try{n=null==window.frameElement&&document.documentElement}catch(m){}n&&n.doScroll&&!function p(){if(!o){try{n.doScroll("left")}catch(a){return setTimeout(p,50)}o=!0,e()}}()},{handle:33}],33:[function(a,b){function c(a,b,c){return d.listeners(a).length?d.emit(a,b,c):(e[a]||(e[a]=[]),void e[a].push(b))}var d=a("ee").create(),e={};b.exports=c,c.ee=d,d.q=e},{ee:31}],36:[function(a,b){function c(a,b,c){b||(b=0),"undefined"==typeof c&&(c=a?a.length:0);for(var d=-1,e=c-b||0,f=new Array(0>e?0:e);++d<e;)f[d]=a[b+d];return f}b.exports=c},{}],31:[function(a,b){function c(a){function b(b,c,g){a&&a(b,c,g),g||(g={});var i=h(b),j=i.length,k={};try{k=f(g,e,d)}catch(l){}for(var m=0;j>m;m++)i[m].apply(k,c);return k}function g(a,b){j[a]=h(a).concat(b)}function h(a){return j[a]||[]}function i(){return c(b)}var j={};return{on:g,emit:b,create:i,listeners:h,_events:j}}function d(){return{}}var e="bw@context",f=a("gos");b.exports=c()},{gos:32}],32:[function(a,b){function c(a,b,c){if(d.call(a,b))return a[b];var e=c();if(Object.defineProperty&&Object.keys)try{return Object.defineProperty(a,b,{value:e,writable:!0,enumerable:!1}),e}catch(f){}try{a[b]=e}catch(f){}return e}var d=Object.prototype.hasOwnProperty;b.exports=c},{}]},{},[]),a=function c(b,d,e){function f(h,i){if(!d[h]){if(!b[h]){var j="function"==typeof a&&a;if(!i&&j)return j(h,!0);if(g)return g(h,!0);var k=new Error("Cannot find module '"+h+"'");throw k.code="MODULE_NOT_FOUND",k}var l=d[h]={exports:{}};b[h][0].call(l.exports,function(a){var c=b[h][1][a];return f(c?c:a)},l,l.exports,c,b,d,e)}return d[h].exports}for(var g="function"==typeof a&&a,h=0;h<e.length;h++)f(e[h]);return f}({1:[function(a){a("loader"),a("errorload"),a("xhrload"),a("perfload")},{errorload:5,loader:34,perfload:6,xhrload:7}],7:[function(a){function b(a){if("string"==typeof a&&a.length)return a.length;if("object"!=typeof a)return void 0;if("undefined"!=typeof ArrayBuffer&&a instanceof ArrayBuffer&&a.byteLength)return a.byteLength;if("undefined"!=typeof Blob&&a instanceof Blob&&a.size)return a.size;if("undefined"!=typeof FormData&&a instanceof FormData)return void 0;try{return JSON.stringify(a).length}catch(b){return void 0}}function c(a,b){return b}function d(a){a.send=o.wrapOld(a.send,"send-xhr-",c),a.onreadystatechange=o.wrapOld(a.onreadystatechange,"iexhr-onreadystatechange-",c),a.onerror=o.wrapOld(a.onerror,"iexhr-onerror-",c)}function e(a){var c=this.params,d=this.metrics;if(!this.ended){if(this.ended=!0,a.removeEventListener)for(var e=0;m>e;e++)a.removeEventListener(l[e],this.listener,!1);if(!c.aborted){if(d.duration=(new Date).getTime()-this.startTime,4===a.readyState){c.status=a.status;var f=a.responseType,g="arraybuffer"===f||"blob"===f||"json"===f?a.response:a.responseText,h=b(g);h&&(d.rxSize=h)}else c.status=0;d.cbTime=this.cbTime,c&&c.pathname&&c.pathname.indexOf("beacon/resources")<0&&i("xhr",[c,d,this.startTime,this.creatType])}}}function f(a,b){var c=j(b),d=a.params;d.host=c.hostname+":"+c.port,d.pathname=c.pathname,a.sameOrigin=c.sameOrigin}var g=window,h=(g.performance,window.XMLHttpRequest);if(h&&h.prototype&&!/CriOS/.test(navigator.userAgent)){a("loader").features.xhr=!0;var i=a("handle"),j=a("parse-url"),k=a("ee"),l=["load","error","abort","timeout"],m=l.length,n=a("loader_id"),o=a("wrap-function")(k);a("wrap-events"),a("wrap-xhr"),k.on("new-xhr",function(){this.totalCbs=0,this.called=0,this.cbTime=0,this.end=e,this.ended=!1,this.xhrGuids={}}),k.on("open-xhr-start",function(a){this.params={method:a[0]},f(this,a[1]),this.metrics={}}),k.on("open-xhr-end",function(a,b){b.__oldie&&d(b)}),k.on("send-xhr-start",function(a,c){var d=this.metrics,e=a[0],f=this;if(d&&e){var g=b(e);g&&(d.txSize=g)}if(this.startTime=(new Date).getTime(),this.listener=function(a){try{"abort"===a.type&&(f.params.aborted=!0),("load"!==a.type||f.called===f.totalCbs&&(f.onloadCalled||"function"!=typeof c.onload))&&f.end&&f.end(c)}catch(b){try{k.emit("internal-error",[b])}catch(d){}}},c.addEventListener)for(var h=0;m>h;h++)c.addEventListener(l[h],this.listener,!1)}),k.on("iexhr-onreadystatechange-start",function(a,b){if(1==b.readyState){var d=b.onreadystatechange;setTimeout(function(){b.onreadystatechange!==d&&(b.onreadystatechange=o.wrapOld(b.onreadystatechange,"iexhr-onreadystatechange-",c))},0)}4==b.readyState&&(this.xhrCbStart=(new Date).getTime())}),k.on("iexhr-onreadystatechange-end",function(a,b){var c=this;this.xhrCbStart&&k.emit("xhr-cb-time",[(new Date).getTime()-this.xhrCbStart,this.onload,b],b),4==b.readyState&&c.end(b)}),k.on("xhr-cb-time",function(a,b,c){this.cbTime+=a,b?this.onloadCalled=!0:this.called+=1,this.called!==this.totalCbs||!this.onloadCalled&&"function"==typeof c.onload||this.end(c)}),k.on("xhr-load-added",function(a,b){var c=""+n(a)+!!b;this.xhrGuids&&!this.xhrGuids[c]&&(this.xhrGuids[c]=!0,this.totalCbs+=1)}),k.on("xhr-load-removed",function(a,b){var c=""+n(a)+!!b;this.xhrGuids&&this.xhrGuids[c]&&(delete this.xhrGuids[c],this.totalCbs-=1)}),k.on("addEventListener-end",function(a,b){b instanceof XMLHttpRequest&&"load"===a[0]&&k.emit("xhr-load-added",[a[1],a[2]],b)}),k.on("removeEventListener-end",function(a,b){b instanceof XMLHttpRequest&&"load"===a[0]&&k.emit("xhr-load-removed",[a[1],a[2]],b)}),k.on("fn-start",function(a,b,c){b instanceof XMLHttpRequest&&("onload"===c&&(this.onload=!0),("load"===(a[0]&&a[0].type)||this.onload)&&(this.xhrCbStart=(new Date).getTime()))}),k.on("fn-end",function(a,b){this.xhrCbStart&&k.emit("xhr-cb-time",[(new Date).getTime()-this.xhrCbStart,this.onload,b],b)})}},{ee:31,handle:33,loader:34,loader_id:35,"parse-url":38,"wrap-events":28,"wrap-function":39,"wrap-xhr":30}],35:[function(a,b){function c(a){var b=typeof a;return!a||"object"!==b&&"function"!==b?-1:a===window?0:f(a,e,function(){return d++})}var d=1,e="bw@id",f=a("gos");b.exports=c},{gos:32}],6:[function(a){var b=window.performance;if(b&&b.timing&&b.getEntriesByType){var c=a("ee"),d=a("handle"),e=(a("wrap-timer"),a("loader"));e.features.stn=!0,c.on("fn-start",function(a){var b=a[0];b instanceof Event&&(this.bstStart=Date.now())}),c.on("fn-end",function(a,b){var c=a[0];c instanceof Event&&d("bst",[c,b,this.bstStart,Date.now()])})}},{ee:31,handle:33,loader:34,"wrap-timer":29}],5:[function(a){function b(a,b,d,g,i){try{j?j-=1:e("err",[i||new c(a,b,d)])}catch(k){try{e("ierr",[k,(new Date).getTime(),!0])}catch(l){}}return"function"==typeof h?h.apply(this,f(arguments)):!1}function c(a,b,c){this.message=a||"Uncaught error with no additional information",this.sourceURL=b,this.line=c}function d(a){e("err",[a,(new Date).getTime()])}var e=a("handle"),f=a("lodash._slice"),g=a("ee"),h=window.onerror,i=!1,j=0;a("loader").features.err=!0,window.onerror=b,window.BWEUM.noticeError=d;var k=window.XMLHttpRequest;try{throw new Error}catch(l){"stack"in l&&(a("wrap-timer"),"addEventListener"in window&&a("wrap-events"),k&&k.prototype&&k.prototype.addEventListener&&a("wrap-xhr"),i=!0)}g.on("fn-start",function(){i&&(j+=1)}),g.on("fn-err",function(a,b,c){i&&(this.thrown=!0,d(c))}),g.on("fn-end",function(){i&&!this.thrown&&j>0&&(j-=1)}),g.on("internal-error",function(a){e("ierr",[a,(new Date).getTime(),!0])})},{ee:31,handle:33,loader:34,"lodash._slice":36,"wrap-events":28,"wrap-timer":29,"wrap-xhr":30}],30:[function(a,b){function c(){j.inPlace(this,m,"fn-")}function d(a,b){j.inPlace(b,["onreadystatechange"],"fn-")}function e(a){a.open=j.wrapOld(a.open,"open-xhr-",f)}function f(a,b){return b}var g=a("ee").create(),h=a("wrap-events"),i=a("wrap-function"),j=i(g),k=i(h),l=window.XMLHttpRequest,m=["onload","onerror","onabort","onloadstart","onloadend","onprogress","ontimeout"];b.exports=g,window._ApmXMLHttpRequest=window.XMLHttpRequest,window.XMLHttpRequest=function(a){var b=new l(a);try{g.emit("new-xhr",[],b),l.prototype.addEventListener?(k.inPlace(b,["addEventListener","removeEventListener"],"-",function(a,b){return b}),b.addEventListener("readystatechange",c,!1)):(b.__oldie=!0,e(b))}catch(d){try{g.emit("internal-error",[d])}catch(f){}}return b},window.XMLHttpRequest.prototype=l.prototype,j.inPlace(XMLHttpRequest.prototype,["open","send"],"-xhr-",f),g.on("send-xhr-start",d),g.on("open-xhr-start",d)},{ee:31,"wrap-events":28,"wrap-function":39}],29:[function(a,b){function c(a,b,c){var d=a[0];"string"==typeof d&&(d=new Function(d)),a[0]=e(d,"fn-",null,c)}var d=(a("lodash._slice"),a("ee").create()),e=a("wrap-function")(d);b.exports=d,e.inPlace(window,["setTimeout","setInterval","setImmediate"],"setTimer-"),d.on("setTimer-start",c)},{ee:31,"lodash._slice":36,"wrap-function":39}],28:[function(a,b){function c(a){f.inPlace(a,["addEventListener","removeEventListener"],"-",d)}function d(a){return a[1]}var e=(a("lodash._slice"),a("ee").create()),f=a("wrap-function")(e),g=a("gos");if(b.exports=e,c(window),"getPrototypeOf"in Object){for(var h=document;h&&!h.hasOwnProperty("addEventListener");)h=Object.getPrototypeOf(h);h&&c(h);for(var i=XMLHttpRequest.prototype;i&&!i.hasOwnProperty("addEventListener");)i=Object.getPrototypeOf(i);i&&c(i)}else Object.prototype.hasOwnProperty.call(XMLHttpRequest,"addEventListener")&&c(XMLHttpRequest.prototype);e.on("addEventListener-start",function(a){if(a[1]){var b=a[1];"function"==typeof b?this.wrapped=a[1]=g(b,"bw@wrapped",function(){return f(b,"fn-",null,b.name||"anonymous")}):"function"==typeof b.handleEvent&&f.inPlace(b,["handleEvent"],"fn-")}}),e.on("removeEventListener-start",function(a){var b=this.wrapped;b&&(a[1]=b)})},{ee:31,gos:32,"lodash._slice":36,"wrap-function":39}],39:[function(a,b){function c(a){return!(a&&"function"==typeof a&&a.apply&&!a[f])}var d=a("ee"),e=a("lodash._slice"),f="bw@wrapper",g=Object.prototype.hasOwnProperty;b.exports=function(a){function b(a,b,d,g,i){function j(){var c=this;return h(a,b,c,e(arguments),d,g,i)}if(c(a))return a;b||(b="");try{j[f]=!0}catch(k){}return l(a,j),j}function h(a,b,c,d,e,f){var d,c,g,h;try{g=e&&e(d,c)||{}}catch(i){m([i,"",[d,c,f],g])}_apmfnName=a.name||"",k(b+"start",[d,c,f,_apmfnName],g);try{return h=a.apply(c,d)}catch(j){var l=window.console;throw void 0!=l&&l.error&&l.log&&void 0!=j.stack&&(l.log("OneAPM catch error"),l.error(j.stack)),k(b+"err",[d,c,j],g),j}finally{k(b+"end",[d,c,h,_apmfnName],g)}}function i(a,b,c){var a=a||function(){},b=b||"-";return function(){var d=this;return h(a,b,d,e(arguments),c)}}function j(a,d,e,f){e||(e="");var g,h,i,j="-"===e.charAt(0);for(i=0;i<d.length;i++)h=d[i],g=a[h],c(g)||(a[h]=b(g,j?h+e:e,f,h,a))}function k(b,c,d){try{a.emit(b,c,d)}catch(e){m([e,b,c,d])}}function l(a,b){if(Object.defineProperty&&Object.keys)try{var c=Object.keys(a);return c.forEach(function(c){Object.defineProperty(b,c,{get:function(){return a[c]},set:function(b){return a[c]=b,b}})}),b}catch(d){m([d])}for(var e in a)g.call(a,e)&&(b[e]=a[e]);return b}function m(b){try{a.emit("internal-error",b)}catch(c){}}return a||(a=d),b.inPlace=j,b.flag=f,b.wrapOld=i,b}},{ee:31,"lodash._slice":36}]},{},[1]),window.BWEUM.require=a}();
</script><!-- end oneapm agent -->
<link rel="dns-prefetch" href="//cdn.yoho.cn">
<link rel="dns-prefetch" href="//static.yohobuy.com">
<link rel="dns-prefetch" href="//img12.static.yhbimg.com">
... ...
{
"name": "yohobuy-node",
"version": "5.1.6",
"version": "5.2.0",
"private": true,
"description": "A New Yohobuy Project With Express",
"repository": {
... ... @@ -44,6 +44,7 @@
"md5": "^2.1.0",
"moment": "^2.14.1",
"morgan": "^1.7.0",
"oneapm": "^1.2.20",
"passport": "^0.3.2",
"passport-douban": "0.0.1",
"passport-local": "^1.0.0",
... ...

1.18 KB | W: | H:

1.33 KB | W: | H:

  • 2-up
  • Swipe
  • Onion skin
... ... @@ -13,19 +13,11 @@ var $pdUsed = $('#pay-delivery-used');
var $balance = $('#balance-detail');
var couponsTpl = Hbs.compile($('#coupons-tpl').html());
var coinTpl = Hbs.compile($('#yoho-coin-tpl').html());
var promotionTpl = Hbs.compile($('#promotion-list-tpl').html());
var $coin = $('#coin-used');
var $coinTip = $('#coin-tip');
var $coinSure = $('#coin-sure');
var coinMax = +$coin.data('max');
var coinStatus = {
err: '请输入一个正整数',
max: '您的有货币不足',
success: '抵扣',
maxUse: '您最多使用',
muPostfix: '个有货币'
};
var queryInfo;
var pkgCache = {};
... ... @@ -67,16 +59,18 @@ function updateUsedPdShow(info) {
}
// 订单计算
function compute() {
var coinUsed = $coin.data('coin');
// 传有货币数量则使用有货币,否者不使用,更改订单总价有货币使用数量重置为0
function compute(coin) {
var d = {
cartType: window.queryString().type,
deliveryWay: $('input[name="delivery-way-radio"]:checked').val(),
paymentType: $('#payment-way').data('id'),
coin: coinUsed ? parseInt(coinUsed, 10) : 0
coin: coin ? parseInt(coin, 10) : 0
};
var couponCode = $('#coupons-sure').data('coupons');
$coin.data('coin', d.coin);
if (couponCode) {
d.couponCode = couponCode;
}
... ... @@ -103,9 +97,14 @@ function compute() {
var res;
if (data.code === 200) {
res = data.data;
// update yoho coin max use num
$coin.data('max', res.canUseCoinNum);
// update yoho coin using
$('#using-coin-cont').html(coinTpl(res));
// update last order amount
$('#sum-row em').html(res.last_order_amount);
... ... @@ -178,63 +177,32 @@ if ($('#use-coupons').length) {
}
// 有货币
if ($coin) {
$coin.data($coin.data()); // 防止人为页面更改有货币使用数量
}
$('#use-coin, #coin-sure, #coin-cancel').click(function() {
$('.coin-trigger').toggleClass('hide');
});
$coin.on('propertychange input', function() {
var c = $.trim($coin.val());
var err = true;
if (c === '') {
// 输入框为空,确定按钮不可点
$coinTip.addClass('vhide');
$coinTip.text(coinStatus.err);
return;
} else if (!/^[1-9]\d*$/.test(c)) {
// 验证输入不为正整数
$coinTip.text(coinStatus.err);
} else if (+c > coinMax) {
// 有货币不足
$coinTip.text(coinStatus.max);
} else if (+c > $('#sum-row').data('amount') * 100) {
// 输入的有货币大于订单额度
$coinTip.text(coinStatus.maxUse + ($('#sum-row').data('amount') * 100) + coinStatus.muPostfix);
} else {
err = false;
$coinTip.text(coinStatus.success + (c / 100).toFixed(2) + '元');
// 已使用面板的数据显示更新
// $coinUsed.html(c);
// $coinDeduction.html((c / 100).toFixed(2));
}
if (err) {
$coinSure.addClass('disable');
$coinTip.removeClass('vhide');
} else {
$coinSure.removeClass('disable');
$coinTip.addClass('vhide');
}
});
$coinSure.click(function() {
if ($coinSure.hasClass('disable')) {
var data = $coin.data();
if ($coinSure.hasClass('disable') ||
data.coin === data.max) {
return;
}
$coin.data('coin', $.trim($coin.val()));
// coin change trigger compute
compute();
compute(data.max);
});
$('#coin-cancel').click(function() {
$coin.val('').data('coin', '');
$coinTip.addClass('vhide').text('');
var data = $coin.data();
if (data.coin * 1 === 0) {
return;
}
// coin cancel trigger compute
compute();
... ... @@ -242,11 +210,13 @@ $('#coin-cancel').click(function() {
// 结算信息列表中修改有货币按钮
$('.balance-detail').on('click', '.modify-coin', function() {
$('.coin-trigger').filter('.use-coin').addClass('hide').end().filter('.using-coin').removeClass('hide');
$('#use-coin').trigger('click');
});
// delivery way change trigger compute
$('input[name="delivery-way-radio"]').change(compute);
$('input[name="delivery-way-radio"]').change(function() {
compute();
});
// 去支付
$('#go-pay').click(function() {
... ...
... ... @@ -49,7 +49,7 @@ function validateInvoice($el) {
function pkgInvoice() {
var $contentChecked = $('input[name="invoice-content"]:checked');
var pkg = {
invocesType: $('.el-invoice').hasClass('focus') ? '1' : '2',
invocesType: $('.el-invoice').hasClass('focus') ? '2' : '1',
invoicesTitle: $('input[name="invoice-title"]').prop('checked') ? '个人' : $('#company-name').val(),
invoicesContent: $contentChecked.val(),
invoicesContentName: $contentChecked.data('name')
... ...
... ... @@ -43,8 +43,6 @@ if ($.inArray(homePage, ['boys', 'girls', 'kids', 'lifestyle']) > -1) {
});
}
lazyLoad($('img.lazy'));
if (homePage === 'boys') {
$('.slide-container').slider({
... ... @@ -73,3 +71,18 @@ $('.new-user-proList').slider2({
shownum: 5,
isCircle: false
});
if (window.cookie('_UID')) {
// 判断是否有新人专享
$.ajax({
type: 'GET',
url: '/channel/isNewUserAjax',
data: {},
success: function(res) {
if (!res.isNewUser) {
$('.new-user').addClass('hide');
}
}
});
}
... ...
... ... @@ -99,8 +99,7 @@ function yasEvent(op, parameter) {
parameter = $.extend({
C_ID: CID
}, parameter);
console.info(op);
console.info(parameter);
window._yas.sendCustomInfo({
op: op,
param: JSON.stringify(parameter)
... ...
... ... @@ -55,6 +55,7 @@ var $accountInput1 = $('#account1'),
$captchaImgInput = $('#captcha'),
$captchaImgWrapper = $('.captcha-wrap'),
$captchaImgPic = $captchaImgWrapper.find('#captcha-img'),
$showCaptchImg = false,
getCaptchaImgVal = function() {
return $.trim($captchaImgInput.val());
},
... ... @@ -281,6 +282,19 @@ accountChangeEvent.add(function(type) {
$qrCodeOverLayer.empty();
initQrCode(); // eslint-disable-line
}
// 密码登录的图形验证码
if (type === AccountLoginData.PasswordLogin.name) {
if ($showCaptchImg) {
$captchaImgWrapper.removeClass('hide');
}
}
if (type === AccountLoginData.SMSLogin.name) {
if ($showCaptchImg) {
$captchaImgWrapper.addClass('hide');
}
}
});
// 保留已输入的帐号信息
... ... @@ -303,6 +317,7 @@ mobileTipShowOnce.add(function() {
refreshSmsImgCallBack.add(function() {
$smsCaptchaImgPic.attr('src', CAPTCHA_IMG_URL + $.now());
$smsCaptchaImgInput.val('');
});
/** ************************************************************************/
... ... @@ -641,6 +656,11 @@ function validateCaptchaSmsAsync() {
isSmsCheckedSuccessFlag = true;
defer.resolve();
} else if (result.code === 501) {
showCaptchaSmsTip(result.message);
$captchaSmsTokenHideInput.val('');
defer.reject();
} else {
showCaptchaSmsTip('验证码不正确');
$captchaSmsTokenHideInput.val('');
... ... @@ -743,7 +763,7 @@ function smsCaptchaImgAsync() {
}
function validateSmsCaptchaImg() {
smsCaptchaImgLocal()
return smsCaptchaImgLocal()
.then(smsCaptchaImgAsync)
.then(hideSmsCaptchaImgTip);
}
... ... @@ -848,7 +868,6 @@ function validateWithPasswordMode() {
// 短信验证过程
function validateWithSmsMode() {
return validateAccount()
.then(validateSmsCaptchaImg)
.then(validateCaptchaSms);
}
... ... @@ -901,31 +920,31 @@ function preSmsLoginWithValidate() {
var defer = $.Deferred(); // eslint-disable-line
if (account === '') {
showAccountTip1('请输入手机号');
showAccountTip2('请输入手机号');
defer.reject();
return defer.reject().promise();
}
if (smsImg === '') {
showSmsCaptchaImgTip('请输入图形证码');
defer.reject();
return defer.reject().promise();
}
if (password === '') {
showCaptchaSmsTip('请输入短信验证码');
defer.reject();
return defer.reject().promise();
}
if (password === '' && account === '') {
// 账户名和密码都为空的情况下点击登陆,只在账户输入框后显示错误提示
showAccountTip1('请输入手机号和短信验证码');
showAccountTip2('请输入手机号和短信验证码');
$captchaSmsTip.addClass('hide');
$captchaSmsInput.addClass('error');
defer.reject();
return defer.reject().promise();
}
return defer.resolve().promise();
... ... @@ -946,7 +965,7 @@ function loginAsync() {
areaCode: getAreaCodeVal(),
account: currentLogin.getAccountVal(),
password: currentLogin.creditableToken(),
captcha: currentLogin.type() === 'password' ? getCaptchaImgVal() : getSmsCaptchaImgVal(),
captcha: currentLogin.type() === 'password' ? getCaptchaImgVal() : '',
isRemember: getRememberMeVal(),
loginType: currentLogin.type()
}
... ... @@ -978,6 +997,7 @@ function showCaptchaImgPic() {
$captchaImgPic.attr('src', CAPTCHA_IMG_URL + $.now());
$captchaImgInput.val('');
$captchaImgWrapper.removeClass('hide');
$showCaptchImg = true;
}
// 设置 refer 信息
... ... @@ -1087,10 +1107,12 @@ $captchaSmsBtn.on('click', function() {
return;
}
validateAccount().then(function() {
disable60sSendSmsBtn();
return sendCaptchaSmsAsync();
});
validateAccount()
.then(validateSmsCaptchaImg)
.then(function() {
disable60sSendSmsBtn();
return sendCaptchaSmsAsync();
});
});
// 记住登录状态
... ...
... ... @@ -24,7 +24,7 @@ var $main = $('.main'),
skn = $main.data('skn'),
deposit = $main.data('deposit') === 'Y',
secKill = $main.data('seckill') === 'Y',
limitCode = encodeURIComponent($main.data('limitcode'));
limitCode = $main.data('limitcode');
var SLIDETIME = 200;
... ... @@ -39,15 +39,19 @@ var oldtatus = {
html: '<a class="coupon-btn">去使用</a>'
};
var BRAND_FAV = {
add: 'add',
cancel: 'cancel'
};
var $saleReturn = $('#saleReturn');
var dialogTpl = require('hbs/product/coupon-dialog.hbs');
var $goodsIdArr = [],
pageNum = 1;
var $goodsIdArr = [];
function productUrl(s) {
return window.location.href + '?openby:yohobuy={"action":"go.productDetail","params":{"product_skn":"' + s + '"}}';
function limitedProductUrl(s) {
return window.location.href + '?openby:yohobuy={"action":"go.limitpurchase","params":{"lp":"' + s + '"}}';
}
function isEmpty(el) {
... ... @@ -151,7 +155,7 @@ bindEvent.add(function() {
var uid = getUid(); // eslint-disable-line
if (!uid) {
return $.Deferred().reject({refer: window.signinUrl()}).promise(); // eslint-disable-line
return $.Deferred().reject({data: {refer: window.signinUrl()}}).promise(); // eslint-disable-line
}
return $.getJSON('/product/detail/coupon', {
... ... @@ -161,10 +165,8 @@ bindEvent.add(function() {
if (result.code === 200) {
defer.resolve();
} else if (result.code === 400) {
defer.reject({refer: window.signinUrl()});
} else {
defer.reject();
defer.reject(result);
}
return defer.promise();
... ... @@ -410,7 +412,7 @@ bindEvent.add(function() {
$qrcode.qrcode({
render: 'table',
size: 140,
text: productUrl(skn)
text: limitedProductUrl(limitCode)
});
}
... ... @@ -630,9 +632,9 @@ bindEvent.add(function() {
function acquireCoupon($ele) {
var couponId = $ele.data('id');
var status = $ele.data('status');
var i = $ele.data('i');
var $item = $($couponItem.get(i));
var status = $item.data('status');
switch (status) {
case 1:
... ... @@ -642,9 +644,11 @@ bindEvent.add(function() {
$item.data('status', 3);
}).fail(function(err) {
if (err.refer) {
return window.jumpUrl(err.refer);
if (err.data && err.data.refer) {
return window.jumpUrl(err.data.refer);
}
alert(err.message);
});
break;
default:
... ... @@ -652,7 +656,8 @@ bindEvent.add(function() {
}
}
// 增加事件
// 清定原来的事件,增加新的事件
clickAcquireCouponEvent.empty();
clickAcquireCouponEvent.add(acquireCoupon);
});
... ... @@ -669,12 +674,14 @@ $(document).on('click', '.status', function() {
// 品牌收藏
$('#brand-favour').click(function() {
var $this = $(this);
var type = $this.hasClass('coled') ? BRAND_FAV.cancel : BRAND_FAV.add;
$.ajax({
type: 'POST',
url: '/product/index/favoriteBrand',
data: {
brandId: $this.data('id')
brandId: $this.data('id'),
type: type
}
}).then(function(data) {
if (data.code === 200) {
... ... @@ -1001,6 +1008,7 @@ $('.comments').on('click', '.img-preview .img-thumb', function() {
$t.removeClass('active');
}
});
$('.comments').on('click', '.img-preview [data-role="preview-close"]', function() {
var $img = $(this).closest('.img-preview').find('.img-wrap img'),
... ... @@ -1020,6 +1028,7 @@ $('.comments').on('click', '.img-preview [data-role="preview-left"]', function()
$img.data('rotate', rotate);
$img.css('transform', 'rotate(' + rotate + 'deg)');
});
$('.comments').on('click', '.img-preview [data-role="preview-right"]', function() {
var $img = $(this).closest('.img-preview').find('.img-wrap img'),
... ... @@ -1048,44 +1057,21 @@ function randomString(len) {
/*
* 页面加载完
*/
function initPageYas(pNum) {
var loadYas = {},
starIndex = (parseInt(pNum, 10) - 1) * 5,
endIndex = parseInt(pNum, 10) * 5;
var pageGoods = $goodsIdArr.slice(starIndex, endIndex);
loadYas = {
function initPageYas() {
var loadYas = {
REC_POSE: 100013,
REC_ID: randomString(40),
PRD_ID: pageGoods.join(','),
PRD_NUM: pageGoods.length,
PRD_ID: $goodsIdArr.join(','),
PRD_NUM: $goodsIdArr.length,
ORDER_CODE: '',
ACTION_ID: 0,
PAGE_NUM: pNum
PAGE_NUM: 1
};
// 关键词搜索结果页展示时
yas.givePoint('YB_CHOOSE_FOR_YOU_Y', loadYas);
}
/*
* 左右箭头埋点
*/
function arrowYas($arrow) {
var totalPage = Math.ceil($goodsIdArr.length / 5);
if ($arrow.hasClass('prev') && pageNum > 1) {
pageNum--;
}
if ($arrow.hasClass('next') && pageNum < totalPage) {
pageNum++;
}
initPageYas(pageNum);
}
// 店铺推荐
function loadRecommend() {
$.ajax({
... ... @@ -1103,18 +1089,21 @@ function loadRecommend() {
if (data.code === 200) {
if (pro.length === 0) {
$('.individual-comment').find('.block-title .title:first-child').addClass('hide');
$('.individual-comment').find('.block-title').find('.title')
.addClass('cur').prev('.sep').addClass('hide');
$('#recommend-shop').detach();
fetchLatestWalk(); // eslint-disable-line
return;
}
$('.individual-comment').find('.block-title .title').eq(0).removeClass('hide').addClass('cur');
$('.individual-comment').find('.block-title .title').eq(1).removeClass('cur');
$('.individual-comment').find('.block-title').find('.sep').removeClass('hide');
$('#recommend-shop').removeClass('hide');
$('#recommend-content').append(html);
$('.recommend-slider').slider2({
shownum: 5,
isCircle: false,
yasFun: arrowYas
isCircle: true
});
$('.recommend-slider .img-item .goods-id').each(function() {
... ... @@ -1127,32 +1116,29 @@ function loadRecommend() {
}
// 页面加载完,埋点
initPageYas(pageNum);
initPageYas();
});
}
// 点击为您推荐商品埋点
$('.recommend-slider .img-item').click(function() {
var $this = $(this);
var index = parseInt($this.index(), 10) + 1;
var page = index / 5 <= 1 ? '' : Math.ceil(index / 5) + '';
var num = index % 5 ? index % 5 + '' : '5';
var loadYas = {
REC_POSE: 100013,
REC_ID: randomString(40),
PRD_ID: $this.find('.goods-id').html(),
PRD_NUM: page + num,
ORDER_CODE: '',
ACTION_ID: 1,
PAGE_NUM: page === '' ? 1 : page
};
// 点击为您推荐商品埋点
$('.recommend-slider').on('click', '.img-item', function() {
var $this = $(this);
var proId = $this.find('.goods-id').html();
var loadYas = {
REC_POSE: 100013,
REC_ID: randomString(40),
PRD_ID: proId,
PRD_NUM: $goodsIdArr.indexOf(proId) + 1,
ORDER_CODE: '',
ACTION_ID: 1,
PAGE_NUM: 1
};
// 关键词搜索结果页展示时
yas.givePoint('YB_CHOOSE_FOR_YOU_Y', loadYas);
});
});
}
// 关键词搜索结果页展示时
yas.givePoint('YB_CHOOSE_FOR_YOU_Y', loadYas);
});
window.loadRecommend = loadRecommend;
... ... @@ -1228,6 +1214,7 @@ bindEvent.fire();
}
});
// 品牌收藏
$.ajax({
type: 'GET',
url: '/product/index/isfav',
... ... @@ -1235,7 +1222,7 @@ bindEvent.fire();
brandId: $('#brand-favour').data('id')
}
}).then(function(result) {
if (result.code === 200) {
if (result.code === 200 && result.data) {
$('#brand-favour').addClass('coled');
}
});
... ... @@ -1244,4 +1231,3 @@ bindEvent.fire();
// 数据懒加载
dataLazyLoad.init({cls: '.datalazyload', threshold: 0});
... ...
... ... @@ -12,6 +12,11 @@ var $brandFavor = $('#brand-favor'),
id = $brandFavor.data('id'),
isFavorite = $shopFavor.find('i').hasClass('coled');
var BRAND_FAV = {
add: 'add',
cancel: 'cancel'
};
/**
* 品牌收藏
*/
... ... @@ -20,7 +25,8 @@ $brandFavor.on('click', function() {
type: 'post',
url: '/product/index/favoriteBrand',
data: {
brandId: id
brandId: id,
type: $brandFavor.find('i').hasClass('coled') ? BRAND_FAV.cancel : BRAND_FAV.add
}
}).then(function(res) {
if (res.code === 200) {
... ...
... ... @@ -115,7 +115,7 @@ function getCouponInfo() {
// 设置优惠券领取状态
function setPicked(info) {
if (info) {
info.dom.text('已领取');
info.dom.addClass('picked').text('已领取');
info.status = 3;
}
}
... ...
... ... @@ -492,6 +492,95 @@
}
}
.using-coin {
text-align: left;
li {
padding-bottom: 10px;
}
.red {
color: #db6976;
}
.help-icon {
float: right;
cursor: pointer;
&:hover + .coin-tip-help {
display: block;
}
}
.coin-tip-help {
width: 304px;
padding: 6px 10px;
line-height: 2;
border: 1px solid #000;
background-color: #fff;
position: absolute;
margin-left: 56px;
margin-top: 6px;
display: none;
&:before {
content: '';
width: 12px;
height: 6px;
background-image: url('/cart/row.png');
display: block;
position: absolute;
top: -6px;
right: 10px;
}
> p:first-child {
font-weight: 700;
}
.rs-text {
color: #999;
}
}
.coin-use-hide {
color: #d4d4d4;
}
.coin-box {
display: inline-block;
width: 70px;
height: 24px;
line-height: 24px;
text-align: center;
border: 1px solid #d4d4d4;
margin: 0 6px;
}
.btns {
margin-top: 10px;
text-align: left;
span {
padding: 4px 14px;
cursor: pointer;
border: 1px solid #ccc;
}
.sure-btn {
color: #fff;
background-color: #000;
border-color: #000;
margin-right: 20px;
}
.coin-help {
float: right;
color: #5291f7;
}
}
}
.coin-sum-row,
.coin-tip-row {
padding: 10px 0;
... ...
... ... @@ -54,6 +54,14 @@
}
}
.sms-captcha-img-wrap {
position: relative;
.err-tip {
left: 335px;
}
}
/* 验证码 */
.captcha {
float: left;
... ...
... ... @@ -1246,7 +1246,7 @@
border-top: none;
.goods {
width: 1010px;
width: 990px;
margin: 0 auto;
height: auto;
... ... @@ -1254,6 +1254,10 @@
float: left;
width: 180px;
margin-right: 22px;
&:nth-child(5n) {
margin-right: 0;
}
}
}
... ... @@ -1407,7 +1411,7 @@
li {
float: left;
width: 200px;
width: 202px;
height: 280px;
overflow: hidden;
}
... ...
... ... @@ -62,7 +62,7 @@
.cp-info {
width: 130px;
padding: 16px 0 0 16px;
padding: 12px 0 0 16px;
float: left;
> p {
... ... @@ -72,8 +72,10 @@
}
.price {
font-size: 38px;
font-size: 36px;
font-weight: 500;
display: block;
margin-bottom: 4px;
}
.term {
... ... @@ -95,6 +97,12 @@
padding: 10px 20px;
}
.picked {
width: 60px;
padding: 10px;
line-height: 40px;
}
&.num1 {
.coupon-title {
width: 230px;
... ... @@ -120,6 +128,7 @@
font-size: 40px;
position: absolute;
margin-left: -270px;
margin-bottom: 0;
}
> p {
... ... @@ -136,9 +145,11 @@
}
}
.picked,
.pick-btn {
width: 100px;
line-height: 40px;
padding: 10px 20px;
white-space: nowrap;
}
}
... ... @@ -152,6 +163,10 @@
width: 224px;
padding: 12px 16px 0;
.price {
margin-bottom: 0;
}
.limit-text {
text-align: right;
margin-top: -20px;
... ... @@ -165,9 +180,11 @@
}
}
.picked,
.pick-btn {
width: 80px;
line-height: 40px;
padding: 10px 20px;
white-space: nowrap;
}
}
... ... @@ -202,7 +219,6 @@
.btn-end {
background: #b5b5b5;
}
}
}
... ... @@ -275,7 +291,6 @@
width: 94px;
}
}
}
.top-coupon-dialog {
... ...