... ... @@ -26,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,
... ... @@ -39,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;
... ... @@ -170,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,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,88 +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);
console.log(cur.colorImage);
console.log(defaultImage);
}
// 缩略图空,不显示
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 {
... ... @@ -467,9 +433,10 @@ const _getFashionTopGoodsStatus = (uid, showStatus, isBeginSale) => {
if (uid) { // 限购码失效
result.getLimitedCodeDis = true;
}
break;
default:
break;
}
return result;
};
... ... @@ -532,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 { // eslint-disable-line
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;
... ... @@ -879,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)
};
};
... ... @@ -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 [];
}
... ... @@ -1130,7 +837,9 @@ const _getDetailDataBySizeInfo = (sizeInfo) => {
// 详情配图
_(replacePairs).forEach((value, key)=> {
intro = _.replace(intro, key, value);
let re = new RegExp(key, 'gm');
intro = _.replace(intro, re, value);
});
details += intro;
... ... @@ -1142,8 +851,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 {};
... ... @@ -1242,12 +951,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 {};
... ... @@ -1256,13 +965,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;
... ... @@ -1331,6 +1040,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) => {
... ... @@ -1365,12 +1331,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
);
... ... @@ -1391,7 +1355,6 @@ const showMainAsync = (data) => {
})();
};
module.exports = {
indexCommentAsync: commentService.indexAsync, // 获取评论列表
getShareOrderListAsync: commentService.getShareOrderListAsync, // 获取评论列表
... ... @@ -1399,5 +1362,6 @@ module.exports = {
createConsultAsync: consultService.createAsync, // 添加咨询
showMainAsync: showMainAsync, // 获取某一个商品详情主页面
indexHotAreaAsync: hotAreaService.indexAsync, // 获取某一个商品的热区数据
saveRecentGoodInCookies // 保存最近的商品
saveRecentGoodInCookies, // 保存最近的商品
getDetailHeader
};
... ...
... ... @@ -376,8 +376,7 @@ exports.getSaleDiscountData = (params, channel) => {
// 处理分页等筛选信息
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, 'default')
... ...
{{> product/detail-header}}
\ No newline at end of file
... ...
... ... @@ -171,7 +171,7 @@
</div>
<div class="chose-size row clearfix {{#if isTicket}} hide {{/if}}">
<input type="hidden" name="isTicket" value="{{isTicket}}" />
<input type="hidden" name="isTicket" value="{{isTicket}}"/>
<span class="title pull-left">
选区域:
</span>
... ... @@ -274,39 +274,41 @@
</div>
</div>
<p class="row">
{{#if virtualGoods}}
{{!-- 电子门票按钮 --}}
{{#if isVirtualBtn}}
<form name="ticket-form" action="//www.yohobuy.com/cart/index/ticketEnsure" method="POST" class="hide"></form>
<span id="buy-ticket" class="buy-ticket buy-now item-buy{{#if dis}} dis{{/if}}" >立即购买</span>
{{/if}}
{{else}}
{{!-- 各颜色下所有尺码均售罄则只显示售罄按钮 --}}
{{#unless soldOut}}
{{# buyNow}}
<span id="buy-now" class="buy-btn buy-now item-buy{{#if dis}} dis{{/if}}"
data-base="{{buyNowBase}}">立即购买</span>
{{/ buyNow}}
{{# openSoon}}
<span id="open-soon" class="buy-btn item-buy dis">即将开售</span>
{{/ openSoon}}
{{#if notForSale}}
<span class="buy-btn dis">
<p class="row">
{{#if virtualGoods}}
{{!-- 电子门票按钮 --}}
{{#if isVirtualBtn}}
<form name="ticket-form" action="//www.yohobuy.com/cart/index/ticketEnsure"
method="POST"
class="hide"></form>
<span id="buy-ticket" class="buy-ticket buy-now item-buy{{#if dis}} dis{{/if}}">立即购买</span>
{{/if}}
{{else}}
{{!-- 各颜色下所有尺码均售罄则只显示售罄按钮 --}}
{{#unless soldOut}}
{{# buyNow}}
<span id="buy-now" class="buy-btn buy-now item-buy{{#if dis}} dis{{/if}}"
data-base="{{buyNowBase}}">立即购买</span>
{{/ buyNow}}
{{# openSoon}}
<span id="open-soon" class="buy-btn item-buy dis">即将开售</span>
{{/ openSoon}}
{{#if notForSale}}
<span class="buy-btn dis">
<i class="iconfont">&#xe61c;</i>
非买品
</span>
{{/if}}
{{#if addToCart}}
<span id="add-to-cart" class="buy-btn item-buy add-to-cart">
{{/if}}
{{#if addToCart}}
<span id="add-to-cart" class="buy-btn item-buy add-to-cart">
<i class="iconfont">&#xe61b;</i>
添加到购物车
</span>
{{/if}}
{{/unless}}
{{/if}}
{{/if}}
{{/unless}}
{{/if}}
<span id="sold-out" class="buy-btn dis{{#unless soldOut}} hide{{/unless}}">
<span id="sold-out" class="buy-btn dis{{#unless soldOut}} hide{{/unless}}">
<i class="iconfont">&#xe61c;</i>
已售罄
</span>
... ... @@ -615,7 +617,8 @@
<div class="text">
<h4>退换货承诺</h4>
<p>
自您签收商品7日内可以退货,15日内可以换货,在商品不影响二次销售的情况下,YOHO!BUY 有货将为您办理退换货服务,请在网站提交"退换货"申请。需要说明的是:非质量问题的退换货,来回运费由您承担。</p>
自您签收商品7日内可以退货,15日内可以换货,在商品不影响二次销售的情况下,YOHO!BUY
有货将为您办理退换货服务,请在网站提交"退换货"申请。需要说明的是:非质量问题的退换货,来回运费由您承担。</p>
<h4>退换货方式</h4>
<p>
针对国内大中型城市,YOHO!BUY 有货开通了<span class="orange">"上门换货"</span>服务,上门服务区域及费用请联系客服中心;若您所在的区域不在上门换货范围内,请您选择普通快递将商品、内包装、赠品及发货单等一并寄回。质量问题的退换货,目前不支持运费到付款业务,请您先垫付运费寄回。如需退换货,请致电客服电话:400-889-9646。
... ... @@ -701,7 +704,10 @@
_mvq.push(['$setAccount', 'm-23428-1']);
_mvq.push(['$setGeneral', 'goodsdetail', '', /*用户名*/ '', /*用户id*/ '']);
_mvq.push(['$logConversion']);
_mvq.push(['$addGoods', /*分类id*/ '', /*品牌id*/ '', /*商品名称*/ '', /*商品ID*/ '{{skn}}', /*商品售价*/ '', /*商品图片url*/ '', /*分类名*/ '', /*品牌名*/ '', /*商品库存状态1或是0*/ '', /*网络价*/ '', /*收藏人数*/ '']);
_mvq.push([
'$addGoods', /*分类id*/ '', /*品牌id*/ '', /*商品名称*/ '', /*商品ID*/ '{{skn}}', /*商品售价*/ '', /*商品图片url*/ '', /*分类名*/
'', /*品牌名*/ '', /*商品库存状态1或是0*/ '', /*网络价*/ '', /*收藏人数*/ ''
]);
_mvq.push(['$logData']);
var _goodsData = {
id: '{{productId}}',// 商品ID
... ... @@ -727,7 +733,7 @@
{{/statGoodsInfo}}
<script type="text/javascript">
(function () {
(function() {
try {
var timestamp = (new Date()).valueOf();
var view = document.createElement('img');
... ...
{{# goodsInfo}}
<div class="pull-left imgs clearfix">
<div class="pull-left img">
<div class="tags clearfix">
{{# tags}}
{{# isNew}}
<span class="good-tag new-tag">NEW</span>
{{/ isNew}}
{{# isReNew}}
<span class="good-tag renew-tag">再到着</span>
{{/ isReNew}}
{{# isSale}}
<span class="good-tag sale-tag">SALE</span>
{{/ isSale}}
{{# isNewFestival}}
<span class="good-tag new-festival-tag">新品节</span>
{{/ isNewFestival}}
{{# isLimit}}
<span class="good-tag limit-tag">限量商品</span>
{{/ isLimit}}
{{# isYearEndPromotion}}
<span class="good-tag yep-tag">年终大促</span>
{{/ isYearEndPromotion}}
{{# isYearMidPromotion}}
<span class="good-tag ymp-tag">年中热促</span>
{{/ isYearMidPromotion}}
{{/ tags}}
</div>
<img id="img-show" class="img-show" src="{{img}}">
</div>
<div id="thumbs" class="pull-right thumbs">
{{# colors}}
<div class="thumb-wrap{{#unless focus}} hide{{/unless}}">
{{#if focus}}
{{# thumbs}}
<img class="thumb" src="{{img}}" data-shower="{{shower}}">
{{/ thumbs}}
{{^}}
{{# thumbs}}
<img class="thumb lazy" data-original="{{img}}" data-shower="{{shower}}">
{{/ thumbs}}
{{/if}}
</div>
{{/ colors}}
</div>
</div>
<div class="pull-right infos">
<p class="name">
{{name}}
{{#if saleTip}}
<span class="sale-tip">{{saleTip}}</span>
{{/if}}
</p>
<a class="brand-name" href="{{brandUrl}}">{{brandName}}</a>
<p class="market-price">
<span class="title">市场价:</span>
<span class="price{{#if hasOtherPrice}} has-other-price{{/if}}">{{marketPrice}}</span>
</p>
{{#if salePrice}}
<p class="sale-price">
<span class="title">促销价:</span>
<span class="price">{{salePrice}}</span>
</p>
{{/if}}
{{#if presalePrice}}
<p class="presale-price">
<span class="title">预售价:</span>
<span class="price">{{presalePrice}}</span>
<span class="arrival-date">上市期:{{arrivalDate}}</span>
</p>
{{/if}}
{{#if advancePrice}}
<p class="advance-price">
<span class="title">先行价:</span>
<span class="price">{{advancePrice}}</span>
</p>
{{/if}}
{{# vipPrice}}
<p class="vip-price">
{{#if unLogin}}
登录后即可查看vip价格
<a class="login-url" href="{{unLogin}}">立即登录</a>
{{/if}}
{{#if normalUser}}
<span class="vip-price-item">您当前是普通会员,成为VIP享受更多优惠!</span>
{{/if}}
{{# prices}}
<span class="vip-price-item{{#if cur}} cur{{/if}}">
{{name}}
<em>
{{price}}
</em>
</span>
{{/ prices}}
{{#unless unLogin}}
<a class="vip-schedual" href="{{vipSchedualUrl}}">查看我的VIP进度</a>
{{/unless}}
</p>
{{/ vipPrice}}
{{#if studentsPrice}}
<p class="students-price">
<span class="title">学生价</span>
<span class="price">{{studentsPrice}}</span>
</p>
{{/if}}
{{#if activity}}
<ul class="activity">
{{#each activity}}
<li>
{{#if activityImg}}
<a class="img-link" href="{{url}}">
<img src="{{activityImg}}">
</a>
{{^}}
<span class="ac-type">{{type}}</span>
<span class="ac-des">{{des}}</span>
{{/if}}
</li>
{{/each}}
</ul>
{{/if}}
<div class="trade-content">
<div id="type-chose" class="type-chose">
{{#if virtualGoods}}
<div class="chose-ticket chose-color row clearfix">
<span class="title pull-left">选日期:</span>
<ul class="colors pull-left clearfix">
{{#each colors}}
<li class="{{#if focus}}focus{{/if}} {{#if disable}}disable{{/if}} pull-left"
title="{{title}}" data-color="{{name}}" data-total="{{total}}">
{{name}}
</li>
{{/each}}
</ul>
</div>
<div class="chose-size row clearfix {{#if isTicket}} hide {{/if}}">
<input type="hidden" name="isTicket" value="{{isTicket}}"/>
<span class="title pull-left">
选区域:
</span>
<div id="sizes" class="size-wrapper pull-left">
{{#each colors}}
<ul class="size{{#unless focus}} hide{{/unless}}">
{{#each size}}
<li {{#unless num}}class="disable"{{/unless}} data-sku="{{sku}}"
data-num="{{num}}" data-name="{{name}}">{{name}}</li>
{{/each}}
<span class="size-warn warn-tip hide">
<i class="iconfont">&#xe62c;</i>
请选择区域
</span>
</ul>
{{/each}}
</div>
</div>
{{else}}
<div class="chose-color row clearfix">
<span class="title pull-left">选颜色:</span>
<ul class="colors pull-left clearfix">
{{#each colors}}
<li class="{{#if focus}}focus{{/if}} {{#if disable}}disable{{/if}} pull-left"
title="{{title}}" data-color="{{name}}" data-total="{{total}}">
<img src="{{src}}">
</li>
{{/each}}
</ul>
</div>
<div class="chose-size row clearfix">
<span class="title pull-left">
选尺码:
</span>
<div id="sizes" class="size-wrapper pull-left">
{{#each colors}}
<ul class="size{{#unless focus}} hide{{/unless}}">
{{#each size}}
<li {{#unless num}}class="disable"{{/unless}} data-sku="{{sku}}"
data-num="{{num}}" data-name="{{name}}">{{name}}</li>
{{/each}}
{{#unless virtualGoods}}
<span class="size-ruler"></span>
{{/unless}}
<span class="size-warn warn-tip hide">
<i class="iconfont">&#xe61f;</i>
请选择尺码
</span>
</ul>
{{/each}}
{{#unless virtualGoods}}
<p class="color-size-tip hide"></p>
{{/unless}}
</div>
</div>
{{/if}}
<div class="chose-count row clearfix">
<span class="title pull-left">选数量:</span>
<div class="num-wraper pull-left clearfix">
<span id="num" class="num pull-left">1</span>
<span class="minus-plus pull-left">
<i id="plus-num" class="plus iconfont">&#xe607;</i>
<i id="minus-num" class="minus dis iconfont">&#xe60b;</i>
</span>
{{#each tags}}
{{#if isFew}}
<span class="warn-tip">即将售罄</span>
{{/if}}
{{/each}}
{{# fashionTopGoods}}
{{#if getLimitedCode}}
<span class="lc-btn get-lc{{#if getLimitedCodeDis}} dis{{/if}}">获取限购码</span>
<div class="lc-container hide">
<span class="lc-arrow"></span>
<div class="lc-content">
<div class="qr-code"></div>
<p class="title">打开APP扫描二维码获取限购码</p>
<p class="sub-title">商品开售后即可购买</p>
</div>
</div>
{{/if}}
{{#if hadLimitedCode}}
<span class="lc-btn had-lc">已获取限购码</span>
{{/if}}
{{#if limitedCodeSoldOut}}
<span class="lc-btn lc-sold-out">限购码已抢光</span>
{{/if}}
{{/ fashionTopGoods}}
</div>
</div>
<p class="row">
{{#if virtualGoods}}
{{!-- 电子门票按钮 --}}
{{#if isVirtualBtn}}
<form name="ticket-form" action="//www.yohobuy.com/cart/index/ticketEnsure" method="POST"
class="hide"></form>
<span id="buy-ticket" class="buy-ticket buy-now item-buy{{#if dis}} dis{{/if}}">立即购买</span>
{{/if}}
{{else}}
{{!-- 各颜色下所有尺码均售罄则只显示售罄按钮 --}}
{{#unless soldOut}}
{{# buyNow}}
<span id="buy-now" class="buy-btn buy-now item-buy{{#if dis}} dis{{/if}}"
data-base="{{buyNowBase}}">立即购买</span>
{{/ buyNow}}
{{# openSoon}}
<span id="open-soon" class="buy-btn item-buy dis">即将开售</span>
{{/ openSoon}}
{{#if notForSale}}
<span class="buy-btn dis">
<i class="iconfont">&#xe61c;</i>
非买品
</span>
{{/if}}
{{#if addToCart}}
<span id="add-to-cart" class="buy-btn item-buy add-to-cart">
<i class="iconfont">&#xe61b;</i>
添加到购物车
</span>
{{/if}}
{{/unless}}
{{/if}}
<span id="sold-out" class="buy-btn dis{{#unless soldOut}} hide{{/unless}}">
<i class="iconfont">&#xe61c;</i>
已售罄
</span>
<span id="collect-product" class="{{#if isCollect}}coled {{/if}}collect-product">
<i class="iconfont">&#xe611;</i>
{{#if isCollect}}
<em>已收藏</em>
{{^}}
<em>收藏商品</em>
{{/if}}
</span>
</p>
<div class="share-row">
<span class="title pull-left">分享商品:</span>
{{> common/share }}
</div>
</div>
<div id="balance" class="balance">
<p class="success-tip">商品已成功添加到购物车!</p>
<p class="cart-total">购物车一共有<span id="cart-num">0</span>件商品</p>
<p class="balance-btns">
<a class="go-cart buy-btn" href="{{goCartUrl}}">
去购物车结算
<i class="iconfont">&#xe60c;</i>
</a>
<span id="keep-shopping" class="keep-shopping">
继续购物
</span>
</p>
</div>
</div>
</div>
{{/ goodsInfo}}
\ No newline at end of file
... ...
... ... @@ -33,9 +33,9 @@ module.exports = {
useOneapm: false,
useCache: false,
memcache: {
master: ['192.168.102.222:11213'],
slave: ['192.168.102.222:11213'],
session: ['192.168.102.222:11213'],
master: ['127.0.0.1:11211'],
slave: ['127.0.0.1:11211'],
session: ['127.0.0.1:11211'],
reconnect: 5000,
timeout: 100,
retries: 0
... ...
... ... @@ -17,7 +17,7 @@ module.exports = () => {
// 用户是否学生
if (req.user.uid && req.cookies.isStudent) {
req.user.isStudent = req.cookies.isStudent;
req.user.isStudent = req.cookies.isStudent || 0;
}
// 从 SESSION 中获取到当前登录用户的 UID
... ...
{{#if pathNav}}
<p class="path-nav">
{{#each pathNav}}
{{#if href}}
<a {{#if @last}}class="last"{{/if}} href="{{href}}" title="{{pathTitle}}">{{{name}}}</a>
{{^}}
<span {{#if @last}}class="last"{{/if}} title="{{pathTitle}}">{{{name}}}</span>
{{/if}}
{{#if name}}
{{#if href}}
<a {{#if @last}}class="last"{{/if}} href="{{href}}" title="{{pathTitle}}">{{{name}}}</a>
{{^}}
<span {{#if @last}}class="last"{{/if}} title="{{pathTitle}}">{{{name}}}</span>
{{/if}}
{{#unless @last}}
<span class="iconfont">&#xe60c;</span>
{{/unless}}
{{#unless @last}}
<span class="iconfont">&#xe60c;</span>
{{/unless}}
{{/if}}
{{/each}}
</p>
{{/if}}
\ No newline at end of file
... ...
... ... @@ -78,7 +78,7 @@
</p>
<div class="hideList hide">
{{#goodsList}}
<li data-src="{{image imagesUrl 280 374}}" data-url="{{../url}}"></li>
<li data-src="{{image images_url 280 374}}" data-url="{{../url}}"></li>
{{/goodsList}}
</div>
</div>
... ...
/**
* 商品详情页
* @author: xuqi<qi.xu@yoho.cn>
* @date: 2015/12/23
* @author: tao.huang<tao.huang@yoho.cn>
* @date: 2016/9/22
*/
/**
* 说明:这里有一些优化方法。
* 页面已经被 nginx 缓存,变化后的数据需要通过 ajax 进行获取后,重新绑定事件。
*/
var $ = require('yoho-jquery'),
lazyLoad = require('yoho-jquery-lazyload'),
Handlebars = require('yoho-handlebars');
var $main = $('.main'),
id = $main.data('id');
var SLIDETIME = 200;
var colTxt = {
def: '收藏商品',
coled: '已收藏',
hover: '取消收藏'
};
var $imgShow = $('#img-show'),
$thumbs = $('#thumbs > .thumb-wrap');
... ... @@ -30,28 +46,12 @@ var $descColor = $('#desc-color');
var thumbsLoaded = {};
var $main = $('.main'),
id = $main.data('id'),
isTicket = $('input[name="isTicket"]').length > 0 && $('input[name="isTicket"]').val() === 'true';
var isTicket = $('input[name="isTicket"]').length > 0 && $('input[name="isTicket"]').val() === 'true';
var maxStock = -1; // 记录当前选中的颜色-尺码的库存量,若为-1,代表未选择尺码
var SLIDETIME = 200;
var colTxt = {
def: '收藏商品',
coled: '已收藏',
hover: '取消收藏'
};
var Alert = require('../common/dialog').Alert;
require('./detail/latest-walk');
require('../plugins/share');
require('../common');
function imgShow(src) {
$imgShow.attr('src', src);
}
... ... @@ -111,7 +111,7 @@ function showSizeWarn() {
jsonHtml = $sizeTitleJson.html(),
sizeTitle;
if (jsonHtml === '') {
if (!jsonHtml) {
return;
}
... ... @@ -245,7 +245,7 @@ $size.on('click', 'li', function() {
}, 300);
});
// 数量
// 增加购买数量
$plusNum.click(function() {
var num = getNum();
... ... @@ -279,6 +279,7 @@ $plusNum.click(function() {
return false;
});
// 减少购买数量
$minusNum.click(function() {
var num = getNum();
... ... @@ -472,6 +473,27 @@ $('.buy-btn').mouseover(function() {
$(this).removeClass('hover');
});
// 只有一个尺码(多个或一个颜色)时默认选中第一个未售罄的颜色的第一个尺码
(function() {
var hasOnlyOneSize = true,
i;
for (i = 0; i < $sizes.length; i++) {
if ($sizes.eq(i).find('li').length !== 1) {
hasOnlyOneSize = false;
break;
}
}
if (hasOnlyOneSize) {
$sizes.eq($('.colors .focus').index()).find('li').click();
}
}());
require('../common'); // yas
require('./detail/latest-walk'); // 最近浏览
require('../plugins/share'); // 分享
// 商品详情/材质洗涤切换
$('.description-material').on('click', '.title', function() {
var $this = $(this),
... ...
... ... @@ -49,6 +49,7 @@
.main {
width: 990px;
margin: 0 auto;
min-height: 560px;
.infos {
width: 465px;
... ...