/** * 商品详情models * @author: xuqi<qi.xu@yoho.cn> * @date: 2016/5/6 */ 'use strict'; const Promise = require('bluebird'); const co = Promise.coroutine; 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'); const hotAreaService = require('./detail-hotarea-service'); const brandService = require('./brand-service'); const favoriteBrandService = require('./favorite-brand-service'); const favoriteProductService = require('./favorite-product-service'); const shopService = require('./shop-service'); const searchAPI = require('./search-api'); const homeService = require('./home-service'); const HeaderModel = require('../../../doraemon/models/header'); const BLANK_STR = ' '; // 展览票 const EXHIBITION_TICKET = 51335912; const _getProductAdditionInfoAsync = (data) => { return co(function * () { 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 = { 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.props(promiseData); return result; })(); }; /** * 获取商品的喜欢 * pid : product id * bid : brand id */ const _getProductFavoriteDataAsync = (uid, pid, bid) => { return co(function*() { let result = { product: false, brand: false }; if (!uid) { return result; } if (pid) { let productData = yield favoriteProductService.isFavoriteAsync(uid, pid); result.product = productData.code === 200 && productData.data ? true : false; } if (bid) { let brandData = yield favoriteBrandService.isFavoriteAsync(uid, bid); result.brand = brandData.code && brandData.code === 200 ? true : false; } return result; })(); }; // 商品标签 const _getTagsDataByProductInfo = (data) => { let tags = {}; _.get(data, 'tags', []).forEach((value) => { switch (value) { case 'is_soon_sold_out': // 即将售磬 tags.isFew = true; break; case 'is_new': // 新品NEW tags.isNew = true; break; case 'is_discount': // SALE tags.isSale = true; break; case 'is_limited': // 限量 tags.isLimit = true; break; case 'is_yohood': // YOHOOD tags.isNewFestival = true; break; case 'is_advance': // 再到着 tags.isReNew = true; break; case 'mid_year':// 年中热促 tags.isYearMidPromotion = true; break; case 'year_end':// 年终大促 tags.isYearEndPromotion = true; break; default: break; } }); return tags; }; // vip 价格 const _getVipDataByProductBaseInfo = (data, vipLevel, uid) => { vipLevel = vipLevel || 0; uid = uid || 0; if (_.isEmpty(_.get(data, 'vip', []))) { return null; } let isVip = (_v) => _v > 0; let isLogin = (_u) => _u > 0; let isNormalUser = () => isLogin(uid) && !isVip(vipLevel); let isVipUser = () => isLogin(uid) && isVip(vipLevel); let vipData = {}; vipData.unLogin = isLogin(uid) ? false : helpers.urlFormat('/signin.html'); vipData.normalUser = isNormalUser(); if (isVipUser()) { vipData.prices = data.vip.map(value => ({ price: value.price, name: value.caption, cur: detailHelper.vipLevel(value.caption + '会员') === vipLevel })); } vipData.vipSchedualUrl = helpers.urlFormat('/home/vip', { t: _.random(10000, 9999999) }); return vipData; }; // 活动 const _getProductActivityBanner = (additionalData) => { let data = additionalData.productBanner; if (_.isElement(data) || _.get(data, 'code', 400) !== 200 || !_.get(data, 'data.bannerImg')) { return {}; } return { activityImg: helpers.image(data.data.bannerImg, 260, 64), url: data.data.promotionUrl }; }; const _getActivityDataByProductBaseInfo = (data, additionalData) => { let result = []; let activityBanner = _getProductActivityBanner(additionalData); if (!_.isEmpty(activityBanner)) { result.push(activityBanner); } _.get(data, 'data', []).forEach(value => { result.push({ type: value.promotionType.replace(/¥/g, '¥'), des: value.promotionTitle.replace(/¥/g, '¥') }); }); return result; }; /** * 获取商品咨询和评论数据 * @param data */ const _getConsultCommentDataByProductInfo = () => { return { commentUrl: helpers.urlFormat('/home/comment') }; }; /** * 获取品牌数据 */ const _getBrandDataByProductBaseInfo = (data, additionalData) => { if (!data.brand_info) { return {}; } let brandId = data.brand_info.id; let bgImg = ''; let logo = ''; let bannerInfo = null; let result = additionalData.bannerInfo; if (_.isEmpty(result)) { return {}; } if (_.get(data, 'brand_info.brand_ico')) { logo = helpers.getForceSourceUrl(data.brand_info.brand_ico); } if (result.code && result.code === 200 && result.data) { bannerInfo = result.data; if (bannerInfo.bannerUrl) { bgImg = helpers.getForceSourceUrl(bannerInfo.bannerUrl); } } // banner的logo if (bannerInfo && bannerInfo.logo) { logo = helpers.getForceSourceUrl(bannerInfo.logo); } let homeUrl = 'javascript:void(0)'; // eslint-disable-line no-script-url if (data.brand_info.brand_domain) { homeUrl = helpers.urlFormat('', null, data.brand_info.brand_domain); } // 导航的品牌banner return { brandId: brandId, bgColor: bannerInfo && bannerInfo.colorValue ? bannerInfo.colorValue : '#000000', bgImg: bgImg, logo: logo, alt: data.brand_info.brand_name, brandName: data.brand_info.brand_name, brandDomain: data.brand_info.brand_domain, homeUrl: homeUrl }; }; /** * 获得sku商品数据 */ const _getSkuDataByProductBaseInfo = (data) => { let totalStorageNum = 0; let skuGoods = null;// sku商品 let defaultImage = '';// 默认图 let chooseSkuFlag = false; // 选中状态 if (!data.goods_list) { return { totalStorageNum, skuGoods, defaultImage }; } skuGoods = _.get(data, 'goods_list', []).reduce((acc, cur, pos)=> { // 如果status为0,即skc下架时就跳过该商品$value['status'] === 0 let goodsGroup = {}; if (_.isEmpty(cur.color_image)) { return acc; } 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 = []; } _.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 (_.isEmpty(goodsGroup.thumbs)) { return acc; } // 默认第一张图片 if (pos === 0) { defaultImage = helpers.image(cur.color_image, 420, 560); } // 商品的尺码列表 _.get(cur, 'size_list', []).forEach((size) => { if (data.attribute === 3) { // 虚拟商品,门票默认最大为4, size.storage_number = size.storage_number > 4 ? 4 : size.storage_number; } // 如果status为0,即skc下架时就跳过该商品 if (cur.status === 0) { size.storage_number = 0; } goodsGroup.size.push({ name: size.size_name, sku: size.product_sku, num: _.parseInt(size.storage_number), goodsId: size.size_id }); // 单个sku商品的总数 goodsGroup.total += _.parseInt(size.storage_number); 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; } return { defaultImage: defaultImage, skuGoods: skuGoods, totalStorageNum: totalStorageNum }; }; /** * 处理限购商品的有关按钮状态(或取现购买以及底部商品购买按钮) * * @param int $uid * @param int $showStatus 限购商品的关联状态 * @param boolean $isBeginSale 限购商品是否已开售 */ const _getFashionTopGoodsStatus = (uid, showStatus, isBeginSale) => { // 潮流尖货状态 // getLimitedCode //限购码状态 // hadLimitedCode //是否已经获取限购码 // limitedCodeSoldOut //限购码是否已经抢光 // openSoon//即将开售 // dis //失效 // buyNow //是否立即购买 let result = { getLimitedCode: false, hadLimitedCode: false, limitedCodeSoldOut: false, openSoon: false, dis: false, buyNow: false, soldOut: false, getLimitedCodeDis: false }; // 显示获取限购码按钮 switch (showStatus) { case 1: // 开售前/后,立即分享获得限购码(用户未领取限购码) if (isBeginSale) { result.buyNow = true; result.dis = true; } else { result.openSoon = true; result.hadLimitedCode = false; } result.getLimitedCode = true; break; case 2: // 开售后,限购码已抢光(用户未领取限购码) result.buyNow = true; result.dis = true; result.limitedCodeSoldOut = true; result.hadLimitedCode = false; break; case 3: // 开售后,商品已经售罄 result.soldOut = true; break; case 4:// 开售后,立即购买(用户已领取限购码) result.buyNow = true; result.dis = false; result.hadLimitedCode = true; if (uid) { // 限购码失效 result.getLimitedCodeDis = true; } break; case 5: // 开售前,限购码已被抢光(用户未领取限购码) result.openSoon = true; result.hadLimitedCode = true; result.limitedCodeSoldOut = true; break; case 6: // 开售前,即将开售(用户已领取限购码) result.openSoon = true; result.hadLimitedCode = true; if (uid) { // 限购码失效 result.getLimitedCodeDis = true; } break; case 7: // 开售后,用户已经用获得的限购码购买过商品 result.buyNow = true; result.dis = true; result.hadLimitedCode = true; if (uid) { // 限购码失效 result.getLimitedCodeDis = true; } break; default: break; } return result; }; /** * 获取分类导航列表 */ function _getSortNavAsync(smallSortId, gender) { return co(function*() { let data = yield searchAPI.getSortByConditionAsync({sort: smallSortId}); if (_.isEmpty(data)) { return []; } let navs = []; let sort = _.get(data, 'data.sort[0]', {}); // 一级分类 navs.push({ href: helpers.urlFormat('', {msort: sort.sort_id, gender: gender}, 'list'), name: sort.sort_name, pathTitle: sort.sort_name }); if (sort.sub) { // 二级分类 let subSort = _.head(sort.sub) || {}; navs.push({ href: helpers.urlFormat('', {msort: sort.sort_id, misort: subSort.sort_id, gender: gender}, 'list'), name: subSort.sort_name, pathTitle: subSort.sort_name }); } return navs; })(); } // 保存在 gids 和 skns ,最近流览功能 const saveRecentGoodInCookies = (oldGids, oldSkns, res, addGids, addSkns) => { oldGids = (oldGids || '').split(','); oldSkns = (oldSkns || '').split(','); addSkns = `${addSkns}-${addGids}`; _.remove(oldGids, addGids); _.remove(oldSkns, addSkns); oldGids.unshift(addGids); oldSkns.unshift(addSkns); res.cookie('_browse', oldGids.splice(0, 30).join(','), { maxAge: 2000000000, domain: 'yohobuy.com' }); res.cookie('_browseskn', oldSkns.splice(0, 30).join(','), { maxAge: 2000000000, domain: 'yohobuy.com' }); }; /** * 获取商品的舒适度 */ const _getProductComfort = (data) => { let result = []; let comfort = data.productComfort; if (_.isEmpty(comfort) || !comfort || !comfort.data) { return result; } _.get(comfort, 'data', []).forEach(value => { let blocks = []; let flag = false; _.range(1, 6).forEach(i => { if (i === value.wearSense.value) { flag = true; blocks.push({ cur: true }); } else { blocks.push({}); } }); // 不存在 if (!flag) { return; } // 存在,添加 result.push({ name: value.caption.caption, minDes: value.caption.low, blocks: blocks, maxDes: value.caption.high }); }); return result; }; /** * 基础商品描述 */ const _getBasicDescription = (productDescBo) => { let sex = (function(gender) { if (gender === 1) { return '男款'; } else if (gender === 2) { return '女款'; } else { return '通用'; } }(productDescBo.gender)); let basic = [ { key: '编号', value: productDescBo.erpProductId }, { key: '颜色', value: productDescBo.colorName, dColor: true }, { key: '性别', value: sex } ]; _.get(productDescBo, 'standardBos', []).forEach(value => { basic.push({ key: value.standardName, value: value.standardVal }); }); return basic; }; /** * 获得描述数据 */ const _getDescriptionDataBySizeInfo = (sizeInfo, additionalData) => { if (!sizeInfo.productDescBo || !sizeInfo.productDescBo.erpProductId) { return {}; } return { basic: _getBasicDescription(sizeInfo.productDescBo), comfort: _getProductComfort(additionalData) }; }; /** * 使sizeBoList id以 sizeAttributeBos id顺序一样 * @param sizeInfoBo */ const _sizeInfoBoSort = (sizeInfoBo) => { if (!sizeInfoBo.sizeBoList || !sizeInfoBo.sizeAttributeBos) { return {}; } _.get(sizeInfoBo, 'sizeBoList', []).forEach((sizeBoList, sizek)=> { let sortAttr = {}; sizeBoList.sortAttributes.forEach(sortAttributes => { sortAttr[sortAttributes.id] = sortAttributes; }); sizeInfoBo.sizeBoList[sizek].sortAttributes = sortAttr; }); _.get(sizeInfoBo, 'sizeBoList', []).forEach((sizeBoList, sizek)=> { let sortAttr = []; sizeInfoBo.sizeAttributeBos.forEach(val => { if (sizeBoList.sortAttributes[val.id]) { sortAttr.push(sizeBoList.sortAttributes[val.id]); } }); sizeInfoBo.sizeBoList[sizek].sortAttributes = sortAttr; }); return sizeInfoBo; }; /** * 获取尺寸信息 * @param sizeInfo * @returns {{}} */ const _getSizeData = (sizeInfo) => { // 尺码信息 if (!_.has(sizeInfo, 'sizeInfoBo')) { return {}; } sizeInfo.sizeInfoBo = _sizeInfoBoSort(sizeInfo.sizeInfoBo); let boyReference = _.get(sizeInfo, 'productExtra.boyReference', false); let girlReference = _.get(sizeInfo, 'productExtra.girlReference', false); let gender = _.get(sizeInfo, 'productDescBo.gender', 3); let referenceName = (function() { if (gender === 3 && boyReference) { return '参考尺码(男)'; } else if (gender === 3 && girlReference) { return '参考尺码(女)'; } else { return '参考尺码'; } }()); // 判断是否显示参考尺码 let showReference = (boyReference && _.get(sizeInfo, 'sizeInfoBo.sizeBoList[0].boyReferSize', false)) || (girlReference && _.get(sizeInfo, 'sizeInfoBo.sizeBoList[0].girlReferSize', false)); if (!_.has(sizeInfo, 'sizeInfoBo.sizeAttributeBos')) { return {}; } // 尺码信息头部 let size = { thead: [{name: '吊牌尺码', id: ''}], tbody: [] }; // 显示参考尺码 if (showReference) { size.thead[1] = {name: referenceName, id: ''}; } _.get(sizeInfo, 'sizeInfoBo.sizeAttributeBos', []).forEach((value) => { size.thead.push({ name: value.attributeName || ' ', id: value.id }); }); _.get(sizeInfo, 'sizeInfoBo.sizeBoList', []).forEach((value) => { let sizes = []; // 吊牌尺码 sizes.push(value.sizeName); // 判断是否显示参考尺码 if (boyReference && (gender === 1 || gender === 3) && showReference) { sizes.push(_.get(value, 'boyReferSize.referenceName', ' ')); } else if (girlReference && (gender === 2 || gender === 3) && showReference) { sizes.push(_.get(value, 'girlReferSize.referenceName', ' ')); } else { if (size.thead[1] && showReference) { size.thead[1] = {}; } } // 其他尺码信息 _.get(value, 'sortAttributes', []).forEach(attr => { sizes.push(_.get(attr, 'sizeValue', BLANK_STR)); }); // 尺码信息 size.tbody.push(sizes); }); // 参考尺码为空 if (_.isEmpty(size.thead[1]) && showReference) { // 移除这个值 size.thead.splice(1, 1); } // 测量方式 if (sizeInfo.sizeImage) { size.sizeImg = sizeInfo.sizeImage; } return size; }; /** * 获取商品模特卡 * @param productId */ const _getProductModelCard = (additionalData) => { let data = additionalData.productModelCard; if (_.isEmpty(data) || !data || _.get(data, 'code', 400) !== 200) { return []; } return _.get(data, 'data', []).map((value) => ({ url: helpers.getForceSourceUrl(value.modelImg), size: value.size, name: value.modelName })); }; /** * 获取模特数据 * @param sizeInfo */ const getReferenceDataBySizeInfo = (sizeInfo) => { if (_.isEmpty(sizeInfo.modelBos)) { return {}; } // 模特试穿, 竖着输出排列显示 // 模特信息 let reference = { thead: [ {name: ''}, {name: '模特', modelCol: true}, {name: '身高'}, {name: '体重'}, {name: '三围'}, {name: '吊牌尺码'}, {name: '试穿描述'} ], tbody: [] }; // 模特数据 sizeInfo.modelBos.forEach((value) => { let modelValue = [ helpers.getForceSourceUrl(value.avatar), value.modelName, value.height, value.weight, value.vitalStatistics, value.fitModelBo.fit_size, value.fitModelBo.feel ]; // 是否有备注 if (_.get(value, 'fitModelBo.fit_remark')) { modelValue.push(value.fitModelBo.fit_remark); reference.thead[7] = {name: '备注', remarkCol: true}; } reference.tbody.push(modelValue); }); return reference; }; /** * 获取洗涤材质 * @param sizeInfo */ const _getMaterialDataBySizeInfo = (sizeInfo) => { // 洗涤提示 // 商品材质[洗涤说明] return { wash: _.get(sizeInfo, 'washTipsList', []).map((value) => ({ name: value.caption, img: value.img })), materialDetail: _.get(sizeInfo, 'productMaterialList', []).map((value) => ({ img: value.imageUrl, name: value.caption, enName: value.encaption, text: value.remark })) }; }; /** * 获取商品详情页介绍 * @param sizeInfo */ const _getDetailDataBySizeInfo = (sizeInfo) => { let details = ''; // 详情文字 if (_.has(sizeInfo, 'productDescBo.phrase')) { details += `${sizeInfo.productDescBo.phrase}<br/>`; } // 图片换成懒加载方式 const replacePairs = { '<img src=': '<img class="lazy" src="data:image/gif;base64,R0lGODlhAQABAJEAAAAAAP///93d3f' + '///yH5BAEAAAMALAAAAAABAAEAAAICVAEAOw==" data-original=', '<img border="0" src=': '<img border="0" class="lazy" src="data:image/gif;base64,R0lGODlhAQABAJEAAAAAAP' + '///93d3f///yH5BAEAAAMALAAAAAABAAEAAAICVAEAOw==" data-original=', '.jpg': '.jpg?imageView2/0/q/90' }; let intro = _.get(sizeInfo, 'productIntroBo.productIntro', ''); // 详情配图 _(replacePairs).forEach((value, key)=> { intro = _.replace(intro, new RegExp(key, 'gm'), value); }); details += intro; return details; }; /** * 获取模特试穿 * @param productSkn */ const _getProductModelTry = (data) => { let result = data.productModelTry; if (_.isEmpty(result) || result.code !== 200 || _.isEmpty(result.data)) { return {}; } let modelTry = { thead: ['模特', '身高', '体重', '三围', '试穿尺码', '试穿描述'], tbody: [] }; // 显示模特信息 _.get(result, 'data.modelTryBoList', []).forEach((value) => { if (value.modelBo && value.sizeBo && value.modelBo.modelName && value.sizeBo.sizeName) { modelTry.tbody.push([ value.modelBo.modelName, value.modelBo.height, value.modelBo.weight, value.modelBo.vitalStatistics, value.sizeBo.sizeName, value.tryDesc ]); } }); if (_.has(result, 'data.modelTryImgBoList')) { let tryImg = _.head(result.data.modelTryImgBoList); modelTry.frImg = helpers.getForceSourceUrl(tryImg.tryImg); } return modelTry; }; /** * 根据最大分类ID获取尺寸属性 * @param maxSortId * @param sizeInfoBo */ const _getSizeAttrByMaxSortId = (maxSortId, sizeList) => { if (_.isEmpty(sizeList)) { return []; } // 不同分类,取得属性值不同 let attributeIds = (function(id) { if (id === 1 && id === 2) { return [3, 4]; } else if (id === 3) { return [6, 10]; } else if (id === 6) { return [13]; } else { return []; } }(maxSortId)); let sizeInfos = []; let attributeNames = {}; // 获取属性名称 _.get(sizeList, 'sizeAttributeBos', []).forEach((size) => { attributeNames[size.id] = size.attributeName; }); _.get(sizeList, 'sizeBoList', []).forEach((size) => { let sizeValues = []; _.get(size, 'sortAttributes', []).forEach((sort) => { if (_.includes(attributeIds, sort.id)) { if (sort.sizeValue) { sizeValues.push( `${attributeNames[sort.id]} ${sort.sizeValue}cm` ); } } }); // 获取尺寸属性 if (!_.isEmpty(sizeValues)) { sizeInfos[size.sizeName] = sizeValues.join(' / '); } }); return sizeInfos; }; /** * 商品尺码信息 * * @param productSkn * @param maxSortId * @return object */ const _getSizeInfo = (productSkn, maxSortId, additionalData)=> { if (!productSkn) { return {}; } let sizeInfo = additionalData.sizeInfo; if (_.isEmpty(sizeInfo)) { return {}; } let result = {}; // 描述数据 result.description = _getDescriptionDataBySizeInfo(sizeInfo, additionalData); // 模特卡 result.modelCards = _getProductModelCard(additionalData); // 试穿模特 let fittingReport = _getProductModelTry(additionalData); if (!_.isEmpty(fittingReport)) { result.fittingReport = fittingReport; } // 尺寸数据 result.size = _getSizeData(sizeInfo); // 模特数据 let reference = getReferenceDataBySizeInfo(sizeInfo); if (!_.isEmpty(reference)) { result.reference = reference; } // 洗涤材质 result.material = _getMaterialDataBySizeInfo(sizeInfo); // 商品详情页介绍 result.details = _getDetailDataBySizeInfo(sizeInfo); // 获取尺寸说明 result.sizeTitleJson = sizeInfo.sizeInfoBo ? JSON.stringify(_getSizeAttrByMaxSortId(maxSortId, sizeInfo.sizeInfoBo)) : ''; return result; }; /** * 获取seo信息 * * @param array $goodsInfo * @param array $navs * @return array */ const _getSeoByGoodsInfo = function(goodsInfo, navs) { let title = ''; let keywords = ''; let brandName = ''; let sortName = ''; let description = ''; goodsInfo = goodsInfo || {}; navs = navs || []; if (!_.isEmpty(goodsInfo.brandName)) { title = goodsInfo.brandName + ' '; brandName = goodsInfo.brandName; } if (_.get(navs, '[1].name')) { sortName = navs[1].name; title += navs[1].name + '|'; } title += goodsInfo.name + '正品 '; keywords = brandName + sortName + ',' + brandName + '官网专卖店,' + brandName + '官方授权店,' + brandName + '正品,' + brandName + '打折,' + brandName + '折扣店,' + brandName + '真品,' + brandName + '代购'; description = !goodsInfo.shareDesc ? goodsInfo.name : goodsInfo.shareDesc; return { title: title, keywords: keywords, description: description }; }; /** * 详情页数据格式化 * @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); } // 有货币 if (!_.includes(['', '0'], propOrigin('yohoCoinNum'))) { const C_VALUE = { type: '返有货币', des: '每件返 ', rest: '个 有货币' }; result.activity.push({ type: C_VALUE.type, des: `${C_VALUE.des}${propOrigin('yohoCoinNum')}${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('isLimitBuy', false)) { // 是否开售 let isBeginSale = propOrigin('saleStatus', 0) === 1; // 限购商品有关的展示状态 let showStatus = propOrigin('showStatus', 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('product_id'); statGoodsInfo.productName = result.name.replace('\'', '’'); statGoodsInfo.brandName = (result.brandName || '').replace('\'', '’'); statGoodsInfo.marketPrice = result.marketPrice.replace('¥', ''); // 数字 statGoodsInfo.salePrice = (result.salePrice ? result.salePrice : result.marketPrice).replace('¥', ''); // 数字 statGoodsInfo.imageUrl = 'http:' + result.img.split('?')[0]; statGoodsInfo.productUrl = 'http:' + helpers.urlFormat(url.parse(propOrigin('product_url')).pathname, null, 'item'); statGoodsInfo.smallSortId = result.smallSortId; statGoodsInfo.soldOut = soldOut ? 1 : 0; 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; } } } // 获取商品尺寸相关 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) => { return co(function * () { let result = {}; let currentUserProductInfo = _.partial(_detailDataPkg, _, data.uid, data.vipLevel); // 获取商品信息 let productInfo = yield productAPI.getProductAsync(data.pid, data.uid, data.isStudent, data.vipLevel) .then(currentUserProductInfo); if (_.isEmpty(productInfo) || _.isEmpty(productInfo.goodsInfo)) { return Promise.reject({ code: 404 }); } let requestData = yield Promise.all([ _getSortNavAsync(productInfo.goodsInfo.smallSortId, data.gender), HeaderModel.requestHeaderData(data.channel), productAPI.isSupportReturnedSale(productInfo.goodsInfo.skn) ]); // 分类导航 ,seo let navs = requestData[0]; let seo = _getSeoByGoodsInfo(productInfo.goodsInfo, navs); result.seo = seo; // 最近浏览功能 ,限量商品不能使用这个功能 if (!_.has(productInfo, 'goodsInfo.fashionTopGoods')) { data.saveInCookies(data.gid, _.get(productInfo, 'goodsInfo.skn', '')); } result.headerData = requestData[1].headerData; result.productDetailPage = true; result.detail = productInfo; result.statGoodsInfo = Object.assign({fullSortName: navs.map(x => x.name).join('-')}, productInfo.statGoodsInfo ); // 是否支持退换货,true 支持,false 不支持 result.detail.supportSaleReturnedService = _.get(requestData, `[2].data.${productInfo.goodsInfo.skn}`, 'N') === 'N'; // 导航 result.detail.pathNav = _.concat( homeService.getHomeChannelNav(data.channel), navs, [{name: productInfo.goodsInfo.name}] ); result.detail.latestWalk = 5; return result; })(); }; module.exports = { indexCommentAsync: commentService.indexAsync, // 获取评论列表 getShareOrderListAsync: commentService.getShareOrderListAsync, // 获取评论列表 indexConsultAsync: consultService.indexAsync, // 获取咨询列表 createConsultAsync: consultService.createAsync, // 添加咨询 showMainAsync: showMainAsync, // 获取某一个商品详情主页面 indexHotAreaAsync: hotAreaService.indexAsync, // 获取某一个商品的热区数据 saveRecentGoodInCookies, // 保存最近的商品 getDetailHeader };