Showing 49 changed files with 1427 additions and 2512 deletions

Too many changes to show.

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

... ... @@ -51,6 +51,11 @@ app.set('etag', false);
app.enable('trust proxy');
// 请求限制中间件
if (!app.locals.devEnv) {
app.use(require('./doraemon/middleware/limiter'));
}
// 指定libray目录
global.utils = path.resolve('./utils');
... ...
'use strict';
const _ = require('lodash');
const cache = global.yoho.cache.master;
exports.index = (req, res) => {
res.render('check', {
width750: true,
localCss: true
});
};
exports.submit = (req, res) => {
let captchaCode = _.get(req.session, 'captcha');
let remoteIp = req.get('X-Forwarded-For') || req.ip;
if (remoteIp.indexOf(',') > 0) {
let arr = remoteIp.split(',');
remoteIp = arr[0];
}
if (req.body.captcha === captchaCode) {
let key = `pc:limiter:${remoteIp}`;
cache.delAsync(key).then(() => {
return res.json({
code: 200
});
}).catch(() => {
return res.json({
code: 400
});
});
} else {
return res.json({
code: 400
});
}
};
... ...
... ... @@ -9,9 +9,12 @@
const router = require('express').Router(); // eslint-disable-line
const cRoot = './controllers';
const ads = require(`${cRoot}/ads`);
const check = require(`${cRoot}/check`);
// routers
router.get('/ads', ads.index);
router.get('/check', check.index);
router.post('/check/submit', check.submit);
module.exports = router;
... ...
<div class="check-page">
<div class="title">请输入正确的验证码,继续访问</div>
<div id="js-img-check"></div>
<div class="submit">
确认
</div>
</div>
... ...
'use strict';
const model = require('../models/feature');
exports.index = function(req, res, next) {
model.index({
code: req.params.code,
type: req.query.type
}).then((result) => {
res.render('feature', {
module: 'activity',
page: 'feature',
title: result.name || 'Yoho!Buy有货',
content: result,
isFeature: true
});
}).catch(next);
};
... ...
'use strict';
const api = global.yoho.API;
const helpers = global.yoho.helpers;
const _getProductBySkns = function(productObj) {
return api.get('', {
productSkn: productObj.defaultSkns,
method: 'h5.product.batch'
}).then((result) => {
productObj.defaultPros = [];
if (result && result.data && result.data.product_list && result.code === 200) {
result.data.product_list.forEach(function(val) {
var goods_id = Array.isArray(val.goods_list) && val.goods_list.length ? val.goods_list[0].goods_id : null;
var obj = {
producturl: `//m.yohobuy.com/product/pro_${val.product_id}_${goods_id}/${val.cn_alphabet}.html?openby:yohobuy={"action":"go.productDetail","params":{"product_skn":${val.product_skn}}}`,
productimg: helpers.image(val.default_images, 213, 284, 2, 60).replace('quality/80', 'quality/60'),
productname: val.product_name,
saleprice: val.sales_price,
marketprice: val.sales_price === val.market_price ? '' : val.market_price,
brandname: val.brand_name
};
if (val.shop_id) {
obj.brandurl = `//m.yohobuy.com/product/index/brand?domain=${val.brand_domain}&openby:yohobuy={"action":"go.shop","params":{"shop_id":${val.shop_id},"shop_template_type":${val.shop_template_type}}}`;
} else {
obj.brandurl = `//m.yohobuy.com/product/index/brand?domain=${val.brand_domain}&openby:yohobuy={"action":"go.brand","params":{"brand_id":${val.brand_id}}}`;
}
productObj.defaultPros.push(obj);
});
}
});
};
module.exports = {
index: function(params) {
return Promise.coroutine(function*() {
if (!params.code) {
return Promise.resolve({});
}
let data,
sknsArr = [];
if (params.type === 'preview') { // 开发/预览模式
data = yield api.get('', {
method: 'app.activity.template.ignoreCache',
activity_id: params.code
});
} else {
data = yield api.get('', { // 生产模式
method: 'app.activity.template',
activity_id: params.code
}, {
cache: true
});
}
if (data.code === 200) {
data = data.data;
}
if (data.floors) {
data.floors.forEach(function(f) {
if (f.component && f.component[0] && f.component[0].type === 'productGroup' && f.component[0].defaultSkns) {
sknsArr.push(_getProductBySkns(f.component[0]));
}
});
}
if (sknsArr.length) {
yield Promise.all(sknsArr);
}
return data;
})();
}
};
... ...
... ... @@ -36,6 +36,8 @@ const promotion = require(`${cRoot}/promotion`);
const individuation = require(`${cRoot}/individuation`);
const feature = require(`${cRoot}/feature`);
const appDownloads = require(`${cRoot}/app-downloads`);
const redbag = require(`${cRoot}/redbag`);
... ... @@ -224,6 +226,9 @@ router.get('/redbag/2017', redbag.index);
// 获取活动页面个性化推荐商品数据
router.get('/individuation', individuation.productLst);
// 活动页模版
router.get('/feature/:code', feature.index);
// 2016 年度账单
router.get('/annual-account', annualAccount.index);
router.get('/annual-account/share', annualAccount.share);
... ...
<div class="feature-page yoho-page">
{{#content.share}}
<input id="shareLink" type="hidden" value="{{shareUrl}}">
<input id="shareDesc" type="hidden" value="{{shareTitleSub}}">
<input id="shareImg" type="hidden" value="{{shareImage}}">
<input id="shareTitle" type="hidden" value="{{shareTitleMain}}">
{{/content.share}}
{{#content.floors}}
{{#isEqualOr type 'sidebar'}}
{{! 侧悬浮}}
<div class="cexuanfu" id="load_cxf"></div>
{{/isEqualOr}}
{{#isEqualOr type '' 'common_floor' 'fix'}}
{{! 普通楼层 顶悬浮}}
<div {{#if param.anchorname}}id="{{param.anchorname}}"{{/if}} {{#if id}}data-id="{{id}}"{{/if}} class="floor {{type}}"
style="{{#if param.bgcolor}}background-color:{{param.bgcolor}}{{/if}}">
{{#if param.bgimg}}
<img src="{{image2 param.bgimg q=60}}">
{{/if}}
{{#component}}
{{#isEqualOr type 'link'}}
{{! 普通组件}}
<a class="anchor" style="{{styleFormat this percent=1}}" href="{{#if url}}{{url}}{{else}}javascript:void(0);{{/if}}" fp="{{getAnalysis ../this @index}}"></a>
{{/isEqualOr}}
{{#isEqualOr type 'coupon'}}
{{! 优惠券}}
<a class="anchor yoho-conpon" style="{{styleFormat this percent=1}}" data-token="{{token}}" href="{{#if url}}{{url}}{{else}}javascript:void(0);{{/if}}" fp="{{getAnalysis ../this @index}}"></a>
{{/isEqualOr}}
{{#isEqualOr type 'yohoCoin'}}
{{! 有货币}}
<a class="anchor yoho-coin" style="{{styleFormat this percent=1}}" data-token="{{token}}" href="{{#if url}}{{url}}{{else}}javascript:void(0);{{/if}}" fp="{{getAnalysis ../this @index}}"></a>
{{/isEqualOr}}
{{#isEqualOr type 'video'}}
{{! 视频}}
<a class="anchor video-bg" style="{{styleFormat this percent=1}}" href="{{#if url}}{{url}}{{else}}javascript:void(0);{{/if}}" fp="{{getAnalysis ../this @index}}"></a>
<div class="video-android-close hide"></div>
<div class="video-android-bg hide"></div>
<video class="video" controls loop preload="meta" name="media">
<source src="{{videoSrc}}">
</video>
{{/isEqualOr}}
{{#isEqualOr type 'marquee' 'swiper'}}
{{! 轮播/滑动}}
<div class="swiper-container {{type}}" data-loop="{{loop}}" {{#if spaceBetween}}data-spacebetween="{{spaceBetween}}"{{/if}} {{#if autoplay}}data-autoplay="{{autoplay}}"{{/if}}>
<div class="swiper-wrapper">
{{#list}}
<div class="swiper-slide" style="{{styleFormat this percent=1}}">
<img src="{{image2 src q=60}}">
<a class="anchor" href="{{#if link}}{{link}}{{else}}javascript:void(0);{{/if}}" fp="{{getAnalysis ../../this @index}}"></a>
</div>
{{/list}}
</div>
{{#isEqualOr type 'marquee'}}
<div class="swiper-pagination"></div>
{{/isEqualOr}}
</div>
{{/isEqualOr}}
{{#isEqualOr type 'tab'}}
{{! tab}}
<div class="tab-container">
{{#repeat count}}
<a class="anchor {{#if @first}}active{{/if}}" style="{{tabStyle @index ../count}}"></a>
{{/repeat}}
</div>
{{/isEqualOr}}
{{#isEqualOr type 'productGroup'}}
{{! 商品池}}
<div class="product-container item{{numOfOneRow}}" {{#if proBgImg}}style="background:url({{proBgImg}})repeat;"{{/if}}>
<div class="product-source" {{#unless defaultPros.length}} {{#if searchCondition }}cloneitem="{{searchCondition.limit}}"{{/if}}{{/unless}} condition='{{stringify searchCondition}}' fp="{{getAnalysis ../this @index}}">
<input class="imgwh" type="hidden" value="193x257">
{{#if defaultPros.length}}
{{#defaultPros}}
<div class="feature-product-info {{#if ../condition}}novisible{{/if}}">
<a class="first-part product-detail" href='{{producturl}}'>
<div class="product-detail-imgbox">
{{#if ../lefTopImg}}<img class="leftopimg" src="{{image2 ../lefTopImg q=60}}">{{/if}}
{{#if ../rigTopImg}}<img class="rigtopimg" src="{{image2 ../rigTopImg q=60}}">{{/if}}
<img class="product-detail-img" src="{{image2 productimg q=60}}">
</div>
{{#isEqualOr ../showPrdName '1'}}<p class="product-name">{{productname}}</p>{{/isEqualOr}}
<div class="product-detail-text">
<div class="price">
<span class="sale-price"{{#if ../fontColor}}style="color:{{../fontColor}};"{{/if}}>¥{{saleprice}}</span>
{{#if marketprice}}<span class="market-price">¥{{marketprice}}</span>{{/if}}
</div>
</div>
</a>
{{#if ../brandImg}}
<a class="second-part {{#isEqualOr ../showBrandUrl '1'}}product-brand{{else}}product-detail{{/isEqualOr}}" href='{{brandurl}}'>
<div class="brand-div">
<span class="brand-name"{{#if ../fontColor}}style="color:{{../fontColor}};"{{/if}}>{{brandname}}</span>
</div>
<img class="brand-img" src="{{image2 ../brandImg q=60}}">
</a>
{{/if}}
</div>
{{/defaultPros}}
{{else}}
<div class="feature-product-info novisible">
<a class="first-part product-detail" href=''>
<div class="product-detail-imgbox">
{{#if lefTopImg}}<img class="leftopimg" src="{{image2 lefTopImg q=60}}">{{/if}}
{{#if rigTopImg}}<img class="rigtopimg" src="{{image2 rigTopImg q=60}}">{{/if}}
<img class="product-detail-img" src="">
</div>
{{#isEqualOr showPrdName '1'}}<p class="product-name"></p>{{/isEqualOr}}
<div class="product-detail-text">
<div class="price">
<span class="sale-price"{{#if fontColor}}style="color:{{fontColor}};"{{/if}}></span>
<span class="market-price"></span>
</div>
</div>
</a>
{{#if brandImg}}
<a class="second-part {{#isEqualOr showBrandUrl '1'}}product-brand{{else}}product-detail{{/isEqualOr}}" href=''>
<div class="brand-div">
<span class="brand-name" {{#if fontColor}}style="color:{{fontColor}};"{{/if}}></span>
</div>
<img class="brand-img" src="{{image2 brandImg q=60}}">
</a>
{{/if}}
</div>
{{/if}}
</div>
</div>
{{/isEqualOr}}
{{/component}}
</div>
{{/isEqualOr}}
{{/content.floors}}
</div>
\ No newline at end of file
... ...
... ... @@ -6,6 +6,7 @@
'use strict';
const helpers = global.yoho.helpers;
const _ = require('lodash');
const headerModel = require('../../../doraemon/models/header'); // 头部model
const indexModel = require('../models/index');
... ... @@ -153,6 +154,11 @@ const add = (req, res, next) => {
// uid = 20422448;
return indexModel.addToCart(productSku, buyNumber, goodsType, isEdit, promotionId, uid, shoppingKey).then(data => {
if (!shoppingKey && _.has(data, 'data.shopping_key')) {
res.cookie('_SPK', data.data.shopping_key, {
expires: new Date(Date.now() + 86400 * 360)
});
}
data ? res.json(data) : res.status(400).json({
message: '操作失败'
});
... ...
... ... @@ -181,6 +181,7 @@ exports.orderSub = (req, res, next) => {
let yohoCoin = req.body.yohoCoin || 0;
let skuList = req.body.skuList || '';
let orderInfo;
let isWechat = req.yoho.isWechat;
try {
orderInfo = JSON.parse(req.cookies['order-info']);
... ... @@ -260,11 +261,11 @@ exports.orderSub = (req, res, next) => {
result = yield cartModel.orderSub(uid, addressId, 'bundle', deliveryTimeId,
deliveryId, invoices, paymentTypeId, paymentType, msg, couponCode,
yohoCoin, null, unionKey, userAgent, times, activityInfo, ip);
yohoCoin, null, unionKey, userAgent, times, activityInfo, ip, isWechat);
} else {
result = yield cartModel.orderSub(uid, addressId, cartType, deliveryTimeId,
deliveryId, invoices, paymentTypeId, paymentType, msg, couponCode,
yohoCoin, skuList, unionKey, userAgent, null, null, ip);
yohoCoin, skuList, unionKey, userAgent, null, null, ip, isWechat);
}
// 提交成功清除Cookie
... ... @@ -345,9 +346,7 @@ exports.selectAddress = (req, res, next) => {
let moreUrl = (req.get('Referer') && !/\/home\/addressAct/.test(req.get('Referer')) &&
!/selectAddress/.test(req.get('Referer'))) ?
req.get('Referer') : helpers.urlFormat('/cart/index/new/orderEnsure', {
cartType: req.cookies._cartType
}); // 取跳过来的url
req.get('Referer') : ''; // 取跳过来的url
address = address.data;
... ... @@ -359,7 +358,9 @@ exports.selectAddress = (req, res, next) => {
req.session.addressMore = moreUrl; // TODO: 注意cookie-session
}
// moreUrl = req.session.addressMore;
moreUrl = req.session.addressMore || moreUrl || helpers.urlFormat('/cart/index/new/orderEnsure', {
cartType: req.cookies._cartType
});
let headerData = headerModel.setNav({
navTitle: '选择地址',
... ...
... ... @@ -178,12 +178,13 @@ exports.ticketsOrderCompute = (uid, productSku, buyNumber, yohoCoin) => {
* @param string|null $userAgent 联盟过来用户下单时需要的User-Agent信息
* @param int $times
* @param null $activityInfo 套餐数据
* @param isWechat 是否是微信商城
* @return array 接口返回的数据
*/
exports.orderSub = (uid, addressId, cartType, deliveryTime,
deliveryWay, invoices, paymentId, paymentType, remark,
couponCode, yohoCoin, skuList, qhyUnio,
userAgent, times, activityInfo, ip) => {
userAgent, times, activityInfo, ip, isWechat) => {
if (!qhyUnio) {
qhyUnio = '';
}
... ... @@ -215,7 +216,7 @@ exports.orderSub = (uid, addressId, cartType, deliveryTime,
return shoppingAPI.orderSub(uid, addressId, cartType, deliveryTime,
deliveryWay, invoices, paymentId, paymentType,
remark, couponCode, yohoCoin, skuList, qhyUnio,
userAgent, times, activityInfo, ip).then(orderSubRes => {
userAgent, times, activityInfo, ip, isWechat).then(orderSubRes => {
let finalResult = {};
if (orderSubRes && orderSubRes.data && orderSubRes.data.is_hint === 'Y') {
... ...
... ... @@ -7,6 +7,7 @@
const _ = require('lodash');
const api = global.yoho.API;
const helpers = global.yoho.helpers;
const utils = require('../../../utils');
const genderMap = {
boys: '1,3',
... ... @@ -33,27 +34,27 @@ let _processCateData = (list, channel) => {
// 如果有二级菜单,二级菜单跳转,否则一级菜单跳转
if (firstItem.sub && firstItem.sub.length) {
_.map(firstItem.sub, function(secondItem) {
secondItem.url = helpers.urlFormat('/', {
secondItem.url = helpers.urlFormat('/', utils.mapSort({
sort: _.get(secondItem, 'relation_parameter.sort'),
sort_name: secondItem.category_name,
gender: genderMap[key] || ''
}, 'list');
}), 'list');
});
firstItem.sub.unshift({
category_name: `全部${firstItem.category_name}`,
url: helpers.urlFormat('/', {
url: helpers.urlFormat('/', utils.mapSort({
sort: _.get(firstItem, 'relation_parameter.sort'),
sort_name: firstItem.category_name,
gender: genderMap[key] || ''
}, 'list')
}), 'list')
});
} else {
firstItem.url = helpers.urlFormat('/', {
firstItem.url = helpers.urlFormat('/', utils.mapSort({
sort: _.get(firstItem, 'relation_parameter.sort'),
sort_name: firstItem.category_name,
gender: genderMap[key] || ''
}, 'list');
}), 'list');
}
});
});
... ...
... ... @@ -103,7 +103,7 @@ const editorRedirect = (req, res, next) => {
param = '?' + param;
}
redirectUrl += `-${id}/${param}`;
res.redirect(redirectUrl);
res.redirect(301, redirectUrl);
} else {
return next();
}
... ...
... ... @@ -469,7 +469,7 @@ const indexRedirect = (req, res, next) => {
param = '?' + param;
}
redirectUrl += `${id}.html${param}`;
res.redirect(redirectUrl);
res.redirect(301, redirectUrl);
} else {
return next();
}
... ...
... ... @@ -3,7 +3,7 @@
const headerModel = require('../../../doraemon/models/header'), // 头部model
model = require('../models/coupons');
// 处理Ajax请求,status为使用状态
// status为使用状态
const index = (req, res, next) => {
model.couponData({
method: 'app.coupons.li',
... ... @@ -21,15 +21,26 @@ const index = (req, res, next) => {
title: '优惠券',
pageFooter: true,
list: result,
used: req.body.status === '1' ? true : false,
localCss: true
};
req.body.page && (req.body.page !== '1' || req.body.status === '1') && (options.layout = false);
res.render('coupons', options);
}).catch(next);
};
const couponsAjax = (req, res, next) => {
model.couponData({
method: 'app.coupons.li',
uid: req.user.uid,
status: parseInt(req.body.status || 0, 10),
page: parseInt(req.body.page || 1, 10),
limit: 10,
}).then(result => {
res.json(result);
}).catch(next);
};
module.exports = {
index,
couponsAjax
};
... ...
... ... @@ -36,8 +36,12 @@ exports.order = (req, res, next) => {
return Promise.all([
orderModel.order(params),
orderModel.getOrders(initialData)
orderModel.getOrders(initialData),
orderModel.refundReason()
]).then(result => {
// 申请退款原因
let refundReason = result[2];
res.render('order', {
module: 'home',
page: 'order',
... ... @@ -49,6 +53,7 @@ exports.order = (req, res, next) => {
localCss: true,
pageFooter: true,
order: result[0] || [],
refundReason: refundReason,
walkwayUrl: result[1] && result[1].length ? '' : '//m.yohobuy.com/product/new',
firstPageOrdersList: result[1] || []
});
... ...
... ... @@ -10,7 +10,10 @@ const helpers = global.yoho.helpers;
const _ = require('lodash');
const headerModel = require('../../../doraemon/models/header'); // 头部model
const orderDetailModel = require('../models/orderDetail');
const orderModel = require('../models/order');
const payModel = require('../../cart/models/pay');
const addressModel = require('../models/address');
const addressProcess = require(global.utils + '/address-process');
const orderDetailData = (req, res, next) => {
let uid = req.user.uid;
... ... @@ -24,12 +27,24 @@ const orderDetailData = (req, res, next) => {
payModel.sendPayConfirm(orderCode, 22, uid);
}
orderDetailModel.orderDetailData(uid, orderCode).then(result => {
if (!result || _.isEmpty(result)) {
Promise.all([
orderDetailModel.orderDetailData(uid, orderCode),
orderDetailModel.closeReasons(),
orderModel.refundReason()
]).then(result => {
let orderDetail = result[0];
let cancelReason = result[1];
let refundReason = result[2];
Object.assign(orderDetail, {
cancelReason: cancelReason
});
if (!orderDetail || _.isEmpty(orderDetail)) {
return next(404);
}
result.serviceUrl = serviceUrl;
orderDetail.serviceUrl = serviceUrl;
res.render('orderDetail', {
module: 'home',
page: 'orderdetail',
... ... @@ -39,7 +54,8 @@ const orderDetailData = (req, res, next) => {
}),
title: '订单详情',
pageFooter: true,
orderDetail: result,
orderDetail: orderDetail,
refundReason: refundReason,
localCss: true,
});
}).catch(next);
... ... @@ -81,6 +97,28 @@ const cancelOrder = (req, res, next) => {
};
/**
* 申请退款
*/
const refundApply = (req, res, next) => {
let orderCode = req.query.id;
if (!orderCode) {
return res.json({
code: 404,
msg: '订单号不存在!'
});
}
orderDetailModel.refundApply({
orderCode: req.query.id,
uid: req.user.uid,
reasonId: req.query.reasonId || 1,
reason: req.query.reason
}).then(result => {
res.json(result);
}).catch(next);
};
/**
* 我的订单-查看物流信息
*/
const logistic = (req, res, next) => {
... ... @@ -97,10 +135,88 @@ const logistic = (req, res, next) => {
}).catch(next);
};
/**
* 订单修改地址页面
*/
const addressModify = (req, res, next) => {
let uid = req.user.uid;
let orderCode = req.query.orderCode;
let areaCode = req.query.areaCode;
let provinceAreaCode = req.query.provinceAreaCode || false;
addressModel.getAddressData({uid: uid}).then(result => {
let userAddressList = result;
let addressData = addressProcess.getAddressByAreaCode(areaCode,
_.get(userAddressList, 'data', [])) || {};
Object.assign(addressData, {
orderCode: orderCode,
});
if (provinceAreaCode) {
// 不允许修改省份,字符串拆分
let areaArray = addressData.area.split(' ');
let area = _.slice(areaArray, 1);
Object.assign(addressData, {
changeProvince: false,
provinceCode: provinceAreaCode,
province: areaArray[0],
area: area
});
} else {
Object.assign(addressData, {
changeProvince: true,
});
}
res.render('order-address-modify', Object.assign(addressData, {
pageHeader: headerModel.setNav({
navTitle: '修改地址',
navBtn: false
}),
module: 'home',
page: 'order-address-modify',
localCss: true
}));
}).catch(next);
};
/**
* 修改订单地址
* @param {*} req
* @param {*} res
* @param {*} next
*/
const changeAddress = (req, res, next) => {
let uid = req.user.uid;
if (!uid) {
return res.json({
code: 502,
msg: '用户数据不存在!'
});
}
orderDetailModel.changeAddress({
uid: req.user.uid,
orderCode: req.body.orderCode,
username: req.body.username,
areaCode: req.body.area_code,
address: req.body.address,
mobile: req.body.mobile
}).then(result => {
res.json(result);
}).catch(next);
};
module.exports = {
orderDetailData,
delOrder,
readdData,
cancelOrder,
logistic
refundApply,
logistic,
addressModify,
changeAddress
};
... ...
... ... @@ -100,7 +100,8 @@ const address = (params) => {
/* 加密地址 ID */
_.forEach(selfAddress.data, (value, key) => {
selfAddress.data[key].address_id = encodeURIComponent(crypto.encryption(null, selfAddress.data[key].address_id));
selfAddress.data[key].address_id =
encodeURIComponent(crypto.encryption(null, selfAddress.data[key].address_id));
});
/* 如果有 ID 是地址编辑页面 */
... ... @@ -218,5 +219,6 @@ module.exports = {
setDefaultAddress,
locationList,
newGetAddress,
chooseAddress
chooseAddress,
getAddressData: _getAddressData
};
... ...
... ... @@ -2,14 +2,40 @@
'use strict';
const api = global.yoho.API;
const helpers = global.yoho.helpers;
const couponData = (params) => {
return api.get('', params).then(result => {
if (result && result.data && result.data.info) {
return result.data.info;
} else {
return 0;
if (result && result.data && result.data.couponList) {
let status0 = params.status === 0;
let status1 = params.status === 1;
return result.data.couponList.map(function(elem) {
delete elem.id;
elem.isNoLimit = elem.isNoLimit === 'true';// 全场通用
elem.isDiscount = (`,${elem.shopPriceLimits},`).indexOf(',1,') !== -1;// 三折以下
elem.isLimited = (`,${elem.shopPriceLimits},`).indexOf(',2,') !== -1;// 限量
elem.brandNameLimits = elem.brandNameLimit && elem.brandNameLimit.join('、');
elem.sortNameLimits = elem.sortNameLimit && elem.sortNameLimit.join('、');
if (status0) {
elem.bestowLink = helpers.urlFormat('/product/index/index',
{
coupon_id: elem.couponId,
title: '优惠活动商品',
intro_text: `以下商品可使用【${elem.couponDetailInfomation}】优惠券`
}
);
} else if (status1) {
elem.employbg = true;
}
return elem;
});
}
return [];
});
};
... ...
... ... @@ -263,21 +263,21 @@ const _getNavs = (type) => {
};
/**
* 订单页面数据
* 订单页面导航条和取消订单原因
* @param params
* @returns {*|Promise.<TResult>}
*/
const order = (params) => {
let finalResult = {};
Object.assign(finalResult, {navs: _getNavs(params.type)});
let finalResult = {
navs: _getNavs(params.type)
};
return api.get('', _.assign({
method: 'app.SpaceOrders.closeReasons'
}, params), {
cache: true,
code: 200
}).then((result) => {
}).then(result => {
if (result.data) {
Object.assign(finalResult, {cancelReason: result.data});
... ... @@ -288,6 +288,17 @@ const order = (params) => {
};
/**
* 申请退款原因
*/
const refundReason = () => {
return api.get('', {
method: 'app.SpaceOrders.refundApplyReasons'
}, {code: 200, cache: true}).then(result => {
return _.get(result, 'data', []);
});
};
/**
* 获取订单列表
* @param params
*/
... ... @@ -333,6 +344,15 @@ const getOrders = (params) => {
});
}
/* 申请退款 */
if (parseInt(value.payment_type, 10) === 1 &&
value.payment_status === 'Y' &&
4 <= parseInt(value.status, 10) <= 5) {
Object.assign(perOrder, {
refundApply: true
});
}
finalResult.push(perOrder);
});
}
... ... @@ -343,5 +363,6 @@ const getOrders = (params) => {
module.exports = {
order,
getOrders
getOrders,
refundReason
};
... ...
... ... @@ -180,7 +180,7 @@ const orderDetailData = (uid, orderCode) => {
method: 'app.SpaceOrders.detail',
uid: uid,
order_code: orderCode
}).then((result) => {
}).then(result => {
if (result && result.code === 200) {
let orderDetail = camelCase(result.data);
... ... @@ -286,9 +286,15 @@ const orderDetailData = (uid, orderCode) => {
orderDetail = _.assign(orderDetail, {
goodsAmount: orderDetail.paymentAmount,
url: '/home/addressModify?orderCode=' + orderCode + '&relation=' + orderDetail.relation
url: '/home/orders/addressModify?orderCode=' + orderCode +
'&areaCode=' + orderDetail.areaCode
});
// 如果允许修改省
if (orderDetail.isSupportChangeProvince === 'Y' && orderDetail.provinceAreaCode) {
orderDetail.url = orderDetail.url + '&provinceAreaCode=' + orderDetail.provinceAreaCode;
}
// 为支付的拆单配送信息
if (orderDetail.isMultiPackage && orderDetail.isMultiPackage === 'Y') {
let jitInfo = {
... ... @@ -309,18 +315,17 @@ const orderDetailData = (uid, orderCode) => {
orderDetail.invoice.type = (orderDetail.invoice.type + '' === '2');
}
// 取消订单原因列表
let resons = closeReasons();
return closeReasons().then(list => {
resons = list;
orderDetail = _.assign(orderDetail, {
cancelReason: resons
/* 申请退款 */
if (orderDetail.isMultiPackage === 'N' &&
parseInt(orderDetail.paymentType, 10) === 1 &&
orderDetail.paymentStatus === 'Y' &&
4 <= parseInt(orderDetail.status, 10) <= 5) {
Object.assign(orderDetail, {
refundApply: true
});
}
return orderDetail;
});
return orderDetail;
} else {
logger.error('detail info return no 200');
return {};
... ... @@ -373,6 +378,19 @@ const cancelOrder = (orderCode, uid, reasonId, gender, channel, reason) => {
});
};
/**
* 申请退款
*/
const refundApply = (params) => {
return api.get('', {
method: 'app.SpaceOrders.refundApply',
uid: params.uid,
order_code: params.orderCode,
reason_id: params.reasonId,
reason: params.reason
});
};
/*
* 我的订单-查看物流
* @param int $orderCode 订单号
... ... @@ -446,11 +464,43 @@ const logistics = (orderCode, uid) => {
});
};
/**
* 修改订单地址
* @param {参数} params
*/
const changeAddress = (params) => {
let apiParams = {
method: 'app.SpaceOrders.updateDeliveryAddress',
order_code: params.orderCode,
uid: params.uid,
user_name: params.username,
area_code: params.areaCode,
address: params.address,
mobile: params.mobile
};
if (params.addressId) {
Object.assign(apiParams, {
address_id: params.addressId
});
}
if (params.phone) {
Object.assign(apiParams, {
phone: params.phone
});
}
return api.post('', apiParams);
};
module.exports = {
orderDetailData,
closeReasons,
delOrder,
readdData,
cancelOrder,
logistics
refundApply,
logistics,
changeAddress
};
... ...
... ... @@ -55,6 +55,10 @@ router.get('/orders/detail', auth, orderDetailController.orderDetailData); // è®
router.get('/delOrder', auth, orderDetailController.delOrder); // 删除订单
router.get('/readd', auth, orderDetailController.readdData); // 再次购买
router.get('/cancelOrder', auth, orderDetailController.cancelOrder); // 取消订单
router.get('/refundApply', auth, orderDetailController.refundApply); // 申请退款
router.get('/orders/addressModify', auth, orderDetailController.addressModify); // 订单详情地址修改页面
router.post('/orders/changeAddress', orderDetailController.changeAddress); // 提交新的地址数据
router.get('/', homeController.index); // 个人中心首页
router.get('/mydetails', auth, homeController.myDetails); // 个人基本资料页面
... ... @@ -77,6 +81,7 @@ router.post('/favoriteDel', auth, favorite.favoriteDelete);// å–消收è—
// 优惠券
router.use('/coupons', auth, coupons.index);
router.use('/couponsAjax', coupons.couponsAjax);
// 帮助中心
router.get('/help', help.index);
... ...
<div class="yoho-page my-coupon-page">
<div class="employ">
<span class="active">未使用</span>
<span>已使用</span>
</div>
<div id="employ" class="coupon-list">
{{#if list}}
{{#list}}
<div class="employ-main">
<span>{{money}}</span>
<p class="coupon-name">{{coupon_name}}</p>
<p>有效期:{{couponValidity}}</p>
{{#if ../used}}
<i></i>
{{/if}}
</div>
{{/list}}
<div class="coupon-tab">
<ul>
<li class="activate">未使用</li>
<li>已使用</li>
</ul>
</div>
{{else}}
<div class="null">
<i></i>
<p>您还没有优惠券!</p>
<a href="/product/new">随便逛逛</a>
</div>
{{!--coupon-list start--}}
<div class="coupon-list coupon-tab1">
{{#each list}}
<div class="coupon-group" data-coupon-id={{couponId}}>
<div class="coupon-header">{{couponDetailInfomation}}</div>
<div class="coupon-content">
<div class="coupon-content-group1">
<p class="coupon-money">{{couponValue}}</p>
<p>{{rule4ShortName}}</p>
</div>
<div class="coupon-content-group2">
<div class="coupon-content-group2-table">
<div>
{{couponValidity}}
{{#if overState}}<span class="coupon-soon-expire">{{overState}}</span>{{/if}}
</div>
<div>
<div class="left down info-btn">详细信息<i class="iconfont"></i></div>
<div class="right">
{{#if employbg}}
<span class="employ"></span>
{{else if bestowLink}}
<a href="javascript:void(0);" data-link="{{bestowLink}}" class="btn">立即使用</a>
{{/if}}
</div>
</div>
</div>
</div>
</div>
<div class="coupon-footer hide">
{{#if isNoLimit}}
<p>全场通用</p>
{{/if}}
{{/if}}
</div>
<div id="employ2" class="coupon-list">
</div>
\ No newline at end of file
{{#if brandNameLimits}}
<p>限品牌:{{brandNameLimits}}</p>
{{/if}}
{{#if sortNameLimits}}
<p>限品类:{{sortNameLimits}}</p>
{{/if}}
<p>特例商品(秒杀、限定、境外、预售{{#if isDiscount}}、3折以下{{/if}}{{#if isDiscount}}、限量{{/if}}等)暂不支持使用优惠券。</p>
{{#if explains}}<p>说明:{{explains}}</p>{{/if}}
</div>
</div>
{{/each}}
</div>
{{!--coupon-list end--}}
<div class="coupon-list coupon-tab2"></div>
<div class="coupon-list coupon-tab3"></div>
</div>
... ...
<div class="address-modify">
{{#unless changeProvince}}
<div class="tip">由于需要仓库调拨,目前暂不支持省地址修改,请您谅解!</div>
{{/unless}}
<form class="form edit-address" id="areaForm">
<div class="form-group">
<label for="username">收货人:</label>
<input name="username" type="text" value="{{consignee}}">
</div>
<div class="form-group">
<label for="phone">联系电话:</label>
<input name="phone" type="text" value="{{mobile}}">
</div>
{{#unless changeProvince}}
<div class="form-group disable">
<label for="province">所在省:</label>
<input name="province" type="text" value="{{province}}" class="disable" readonly>
<input name="provinceCode" type="hidden" value="{{provinceCode}}">
</div>
{{/unless}}
<div class="form-group" id="area">
<label for="area">所在地区:</label>
<input name="area" type="text" value="{{area}}" readonly>
<input name="area_code" type="hidden" value={{area_code}}>
</div>
<div class="form-group">
<label for="address" class="label-address">详细地址:</label>
<textarea name="address" type="text" value="" maxlength="255">{{address}}
</textarea>
</div>
<input type="hidden" name="orderCode" value="{{orderCode}}">
</form>
<div class="tip"><span class="iconfont icon-info"></span>修改地址仅可修改一次,且会影响送货时间,请您谅解!</div>
<div class="btn-sure-line">
<button id="btnSure" class="btn-sure">确认修改</button>
</div>
</div>
<div id="vAddressAct">
<vue-address-act></vue-address-act>
</div>
\ No newline at end of file
... ...
... ... @@ -44,5 +44,21 @@
</div>
</div>
{{/ order}}
{{!-- 申请退款原因 --}}
<div class="refund-reason-mask">
<div class="refund-reason-box" >
<div class="box-head"><span class="box-cmp">完成</span></div>
<div class="swiper-container refund-box-main">
<ul class="swiper-wrapper">
{{#refundReason}}
<li class="swiper-slide" data-reason-id="{{id}}"><span >{{reason}}</span></li>
{{/refundReason}}
</ul>
<div class="refund-active-mask"></div>
</div>
</div>
</div>
</div>
... ...
... ... @@ -153,6 +153,11 @@
<span class="btn btn-check-logistics">查看二维码</span>
</a>
{{/if}}
{{!-- 申请退款 --}}
{{#if refundApply}}
<span class="btn btn-refund">申请退款</span>
{{/if}}
{{/if}}
</div>
</div>
... ... @@ -171,6 +176,22 @@
</div>
</div>
{{/ orderDetail}}
{{!-- 申请退款原因 --}}
<div class="refund-reason-mask">
<div class="refund-reason-box" >
<div class="box-head"><span class="box-cmp">完成</span></div>
<div class="swiper-container refund-box-main">
<ul class="swiper-wrapper">
{{#refundReason}}
<li class="swiper-slide" data-reason-id="{{id}}"><span >{{reason}}</span></li>
{{/refundReason}}
</ul>
<div class="refund-active-mask"></div>
</div>
</div>
</div>
</div>
<script>_ozprm = "orderid={{orderCode}}&ordertotal={{orderTotal}}";</script>
<script type="text/javascript" src="//static.yohobuy.com/m/v1/js/AG_Tracking.js"></script>
... ...
... ... @@ -111,7 +111,9 @@ const local = {
res.render('login', {
width750: true,
loginIndex: true, // 模板中使用JS的标识
captchaShow: _.get(req.session, 'login.errorCount') <= 0,
// captchaShow: _.get(req.session, 'login.errorCount') <= 0,
captchaShow: true, // 170306 因为暴力破解密码问题,要求每次都展示验证码
// 返回的URL链接
backUrl: 'javascript:history.go(-1)', // eslint-disable-line
... ... @@ -162,7 +164,9 @@ const local = {
// 返回的URL链接
backUrl: 'javascript:history.go(-1)', // eslint-disable-line
loginInternational: true, // 模板中使用JS的标识
captchaShow: _.get(req.session, 'login.errorCount') <= 0,
// captchaShow: _.get(req.session, 'login.errorCount') <= 0,
captchaShow: true, // 170306 因为暴力破解密码问题,要求每次都展示验证码
isPassportPage: true, // 模板中模块标识
headerText: '登录',
areaCode: '+86', // 默认区号
... ... @@ -173,6 +177,10 @@ const local = {
});
},
login: (req, res, next) => {
// 170306 因为暴力破解密码问题,要求每次都校验验证码
_.set(req.session, 'login.errorCount', 0);
let count = _.get(req.session, 'login.errorCount');
if (count == null) { // eslint-disable-line
... ...
... ... @@ -13,14 +13,18 @@ const bundleModel = require(`${mRoot}/bundle`);
* @param next
*/
exports.detail = (req, res, next) => {
bundleModel.detail(req.query).then(result => {
bundleModel.detail(req.query, req.yoho.isApp).then(result => {
if (result.bundleDatas.length <= 3) {
result.any = true;
}
res.render('bundle/detail', Object.assign({
module: 'product',
page: 'bundle',
pageHeader: headerModel.setNav({
navTitle: '优惠套餐',
navTitle: result.bundleInfo.bundleName,
navBtn: false
})
}),
localCss: true
}, result));
}).catch(next);
};
... ...
... ... @@ -237,7 +237,7 @@ const category = (req, res, next) => {
initialData.uid = uid;
}
searchModel.getSearchData(initialData).then((firstScreenGoodsList) => {
searchModel.getSearchData(initialData).then((firstPageGoods) => {
res.render('search/goods-list', {
_noLazy: true, // 首屏不使用lazyload
module: 'product',
... ... @@ -246,7 +246,8 @@ const category = (req, res, next) => {
navTitle: req.query.title || req.query.sort_name
}),
goodList: params,
firstPageGoodsList: firstScreenGoodsList.list,
firstPageGoods: firstPageGoods || [],
suggestion: firstPageGoods.suggestion || [],
showDownloadApp: true,
pageFooter: true,
category: true,
... ...
... ... @@ -86,7 +86,7 @@ const newDetail = {
reject();
}
}).then(skn => {
return res.redirect(`/product/${skn}.html${param}`);
return res.redirect(301, `/product/${skn}.html${param}`);
}, () => {
return next();
});
... ...
... ... @@ -70,7 +70,15 @@ const shop = {
let brandShop = shopResult[0];
let newGoods = shopResult[1];
params.newGoods = newGoods.list;
params.newGoods = newGoods.list || [];
params.suggestion = newGoods.suggestion || [];
// 推荐词条件判断 redmine: 18567
if (params.suggestion && params.suggestion.isNeedSuggestion &&
params.suggestion.termsSuggestion.length) {
params.newquery = params.suggestion.termsSuggestion[0].name;
}
if (brandId === 0) {
params.query = domain;
}
... ... @@ -119,6 +127,7 @@ const shop = {
navTitle: title !== '' ? title : domain
}),
goodList: params,
suggestion: params.suggestion || [],
showDownloadApp: true,
pageFooter: true,
title: title + '|' + title + '潮流服装服饰-Yoho!Buy有货',
... ...
... ... @@ -35,7 +35,7 @@ const blkNewGoods = (req, res, next) => {
initialData.uid = uid;
}
searchModel.getSearchData(initialData).then(firstScreenGoodsList => {
searchModel.getSearchData(initialData).then(firstPageGoods => {
res.render('search/goods-list', {
module: 'product',
page: 'search-list',
... ... @@ -43,7 +43,7 @@ const blkNewGoods = (req, res, next) => {
navTitle: req.query.title || req.query.sort_name || '新品抢先看'
}),
goodList: params,
firstPageGoodsList: firstScreenGoodsList.list,
firstPageGoods: firstPageGoods || [],
showDownloadApp: true,
pageFooter: true
});
... ...
... ... @@ -20,9 +20,8 @@ const list = (req, res, next) => {
let params = Object.assign({
isSearch: true, // 搜索列表将最新改成默认的标识
cartUrl: helpers.urlFormat('/cart/index/index')
}, req.query);
}, req.query, {query: (req.query.query || '').toString()});
let title = '';
let query = (req.query.query || '').toString();
let isQueryFirstClass = false; // 标识用户搜的是不是一级品类
let isQuerySecondClass = false; // 标识用户搜的是不是二级品类
let domain = null;
... ... @@ -32,7 +31,6 @@ const list = (req, res, next) => {
params.shopId = params.shop_id;
}
params.query = query;
params.isApp = req.yoho.isApp;
params.physical_channel = req.yoho.channel && searchProcess.getChannelType(req.yoho.channel);
... ... @@ -50,34 +48,37 @@ const list = (req, res, next) => {
limit: 12
}, params);
if (query) {
query = query.toLowerCase();
}
if (uid) {
initialData.uid = uid;
}
/* 判断是不是品牌, 是品牌跳到品牌列表页(显示搜索框),判断是不是品类, 是品类加导航标题(不显示搜索框) */
return Promise.all([
searchModel.getBrandDomain(query),
searchModel.getBrandDomain(params.query.toLowerCase()),
searchModel.getClassNames(),
searchModel.getSearchData(initialData)
]).then(result => {
if (query) {
// 推荐词条件判断 redmine: 18567
if (result[2].suggestion && result[2].suggestion.isNeedSuggestion &&
result[2].suggestion.termsSuggestion.length) {
params.newquery = result[2].suggestion.termsSuggestion[0].name;
}
if (params.query) {
domain = result[0];
// 跳转到品牌商品列表页
if (domain !== null && !params.shop_id) {
let urlPro = {
from: 'search',
query: query
}
query: params.query
};
if (req.query.app_type) {
urlPro = _.assign(urlPro, {
app_type: req.query.app_type
})
});
}
let url = helpers.urlFormat('', urlPro, domain);
... ... @@ -92,7 +93,7 @@ const list = (req, res, next) => {
_.forEach(result[1].first, (obj) => {
// 精确查一级品类
if (obj === query) {
if (obj === params.query) {
isQueryFirstClass = true;
return false;
}
... ... @@ -100,7 +101,7 @@ const list = (req, res, next) => {
_.forEach(result[1].second, (obj) => {
// 精确查二级品类
if (obj === query) {
if (obj === params.query) {
isQuerySecondClass = true;
return false;
}
... ... @@ -111,13 +112,13 @@ const list = (req, res, next) => {
// 搜索是一级品类
if (isQueryFirstClass) {
title = '全部' + query;
title = '全部' + params.query;
} else if (isQuerySecondClass) { // 搜索是二级品类
title = query;
title = params.query;
} else { // 搜索其它内容
if (query || params.form) {
if (params.query || params.form) {
params.search = {
default: query === '' ? false : query,
default: params.query === '' ? false : params.query,
url: helpers.urlFormat('', null, 'search')
};
}
... ... @@ -135,7 +136,8 @@ const list = (req, res, next) => {
}),
title: title,
goodList: params,
firstPageGoodsList: result[2].list || [],
firstPageGoods: result[2] || [],
suggestion: result[2].suggestion || [],
pageFooter: true,
shopId: params.shop_id || ''
});
... ... @@ -170,7 +172,9 @@ const index = (req, res, next) => {
pageFooter: true,
width750: true,
search: {
defaultTerms: (result && result.hotTerms && result.hotTerms.defaultTerms && result.hotTerms.defaultTerms.length !== 0) ? result.hotTerms.defaultTerms[0].content : '',
defaultTerms: (result && result.hotTerms &&
result.hotTerms.defaultTerms && result.hotTerms.defaultTerms.length !== 0) ?
result.hotTerms.defaultTerms[0].content : '',
url: helpers.urlFormat('', null, 'search'),
hotTerms: result.hotTerms,
wantTerms: result.guessTerms
... ...
/**
* 商品详情controller
* @author: xuqi<qi.xu@yoho.cn>
* @date: 2016/5/6
* 新版商品详情页面
*/
'use strict';
const mRoot = '../models';
const headerModel = require('../../../doraemon/models/header'); // 头部model
const detailModel = require(`${mRoot}/seckill-detail`); // 商品详情 model
const introModel = require(`${mRoot}/intro`); // 商品尺码信息 model
const preferenceModel = require(`${mRoot}/preference`); // 商品偏好 model
const detailRelated = require(`${mRoot}/consult-comment`); // 商品评论咨询 model
const _ = require('lodash');
const detailModel = require('../models/detail');
const newDetailModel = require('../models/seckill-detail');
const listModel = require('../models/list');
const headerModel = require('../../../doraemon/models/header'); // 头部model
const helpers = global.yoho.helpers;
exports.getUser = (req, res, next) => {
let uid = req.user.uid,
result = {
isStudent: false
};
detailModel.getUserProfile(uid).then((data) => {
result.isStudent = data.data && data.data.vip_info && data.data.vip_info.is_student ? true : false;
result.vipLevel = (data.data && data.data.vip_info && data.data.vip_info.cur_level) || '0';
req.__User__ = result;
next();
}).catch(next);
};
// /**
// * 商品基本信息
// * @param {[type]} req [description]
// * @param {[type]} res [description]
// * @return {[type]} [description]
// */
// exports.index = (req, res, next) => {
// if (!req.params[0] || !req.params[1]) {
// return next();
// }
// let uid = req.user.uid || 0;
// let headerData = headerModel.setNav({
// navTitle: '商品详情'
// });
// detailModel.getProductData({
// id: req.params[0],
// goodsId: req.params[1],
// uid: uid,
// ua: req.get('user-agent') || ''
// }).then((result) => {
// if (_.isEmpty(result)) {
// return next();
// }
// result.studentPrice = req.__User__.isStudent && result && result.goodsPrice && result.goodsPrice.studentPrice ? result.goodsPrice.studentPrice : false;
// res.render('detail/detail', {
// pageHeader: headerData,
// result: result,
// page: 'detail',
// title: result.goodsName,
// pageFooter: true
// });
// }).catch(next);
// };
// /**
// * 商品基本信息 SKN 进入
// * @param {[type]} req [description]
// * @param {[type]} res [description]
// * @return {[type]} [description]
// */
// exports.indexSkn = (req, res, next) => {
// if (!req.params[0]) {
// return next();
// }
// let uid = req.user.uid || 0;
// let headerData = headerModel.setNav({
// navTitle: '商品详情'
// });
// detailModel.getProductData({
// productSkn: req.params[0],
// uid: uid,
// ua: req.get('user-agent') || ''
// }).then((result) => {
// if (_.isEmpty(result)) {
// return next();
// }
// result.studentPrice = req.__User__.isStudent && result && result.goodsPrice && result.goodsPrice.studentPrice ? result.goodsPrice.studentPrice : false;
// res.render('detail/detail', {
// pageHeader: headerData,
// result: result,
// page: 'detail',
// title: result.goodsName,
// pageFooter: true
// });
// }).catch(next);
// };
/**
* 商品尺码信息详情
* @param {[type]} req [description]
* @param {[type]} res [description]
* @return {[type]} [description]
*/
exports.intro = (req, res, next) => {
if (!req.params.productskn) {
return next();
}
introModel.getintroIntro({
productskn: req.params.productskn
}, req).then(html => {
res.send(html);
});
// introModel.getintroData({
// productskn: req.params.productskn
// }, req).then((result) => {
// res.render('detail/intro', {
// result: result,
// layout: false
// });
// }).catch(next);
};
/**
* 为你优选
* @param {[type]} req [description]
* @param {[type]} res [description]
* @return {[type]} [description]
*/
exports.preference = (req, res, next) => {
preferenceModel({
productskn: req.query.productSkn,
yhchannel: req.yoho.channel,
brandId: req.query.brandId
}).then((result) => {
res.render('detail/preference', Object.assign({
layout: false
}, result));
}).catch(next);
};
/**
* 购买评价页
*/
exports.comments = (req, res, next) => {
if (!req.query.product_id) {
return next();
}
let headerData = headerModel.setNav({
navTitle: '购买评价'
});
detailRelated.comments(req.query).then((result) => {
res.render('detail/comments', Object.assign({
title: '购买评价',
pageHeader: headerData,
pageFooter: true
}, result));
}).catch(next);
};
/**
* 购买咨询
*/
exports.consults = (req, res, next) => {
if (!req.query.product_id) {
return next();
}
let headerData = headerModel.setNav({
navTitle: '购买咨询'
});
detailRelated.consults(req.query).then((result) => {
res.render('detail/consults', Object.assign({
title: '购买咨询',
pageHeader: headerData,
pageFooter: true
}, result));
}).catch(next);
};
/**
* 咨询点赞
*/
exports.consultUpvoteOrUseful = (req, res, next) => {
let uid = req.user.uid || 0;
if (!uid) {
return res.json({
code: 401,
message: '用户id为空',
data: helpers.urlFormat('/signin.html', {
refer: helpers.urlFormat('/product/detail/consults', {
product_id: req.body.productId,
total: req.body.total
})
})
});
}
req.body.isUpvote = /upvote/.test(req.path);
req.body.uid = uid;
detailRelated.upvoteConsult(req.body).then((result) => {
res.json(result);
}).catch(next);
};
/**
* 咨询表单页
*/
exports.consultform = (req, res, next) => {
if (!req.query.product_id) {
return next();
}
let headerData = headerModel.setNav({
navTitle: '我要咨询'
});
res.render('detail/consult-form', {
title: '我要咨询',
pageHeader: headerData,
productId: req.query.product_id,
formUrl: '/product/detail/consultsubmit',
pageFooter: true
});
};
/**
* 咨询提交接口
*/
exports.consultsubmit = (req, res, next) => {
let data = {
code: 400,
message: '请输入咨询内容',
data: ''
};
// 判断参数是否存在
if (!req.body.product_id || !req.body.content) {
return res.json(data);
}
detailRelated.addConsult(req.user.uid, req.body.product_id, req.body.content).then((result) => {
if (result) {
Object.assign(data, result);
}
return res.json(data);
}).catch(next);
};
/**
* 商品基本信息 SKN 进入 pagecache重构
* @param {[type]} req [description]
* @param {[type]} res [description]
* @return {[type]} [description]
*/
exports.indexSkn = (req, res, next) => {
if (!req.params[0]) {
return next();
}
// let uid = req.user.uid || 0;// pagecache重构
let headerData = headerModel.setNav({
navTitle: '商品详情'
});
detailModel.getProductData({
productSkn: req.params[0],
// uid: uid,
ua: req.get('user-agent') || ''
}).then((result) => {
if (_.isEmpty(result)) {
const newDetail = {
index(req, res, next) {
let id;
let goodsId;
let productSkn;
if (req.params[0] && req.params[1]) {
id = req.params[0];
goodsId = req.params[1];
} else if (req.params[0]) {
productSkn = req.params[0];
} else {
return next();
}
// pagecache重构
// result.studentPrice = req.__User__.isStudent && result && result.goodsPrice && result.goodsPrice.studentPrice ? result.goodsPrice.studentPrice : false;
res.render('detail/detail', {
pageHeader: headerData,
result: result,
page: 'seckill-detail',
title: result.goodsName,
pageFooter: true,
localCss: true
let headerData = headerModel.setNav({
navTitle: '商品详情'
});
}).catch(next);
};
/**
* 商品基本信息 pagecache重构
* @param {[type]} req [description]
* @param {[type]} res [description]
* @return {[type]} [description]
*/
exports.index = (req, res, next) => {
if (!req.params[0] || !req.params[1]) {
return next();
}
newDetailModel.getProductData({
id: id,
goodsId: goodsId,
productSkn: productSkn,
ua: req.get('user-agent') || ''
}).then((result) => {
if (_.isEmpty(result)) {
return next();
}
// result.id = id;
// result.goodsId = goodsId;
let appParams = {product_skn: result.productSkn};
let appPath = 'yohobuy://yohobuy.com/goapp?openby:yohobuy={"action":"go.productDetail","params":' +
JSON.stringify(appParams) +
'}';
res.render('detail/new/detail', {
pageHeader: headerData,
result: result,
page: 'seckill-detail',
title: result.goodsName,
pageFooter: true,
localCss: true,
appPath: appPath
});
}).catch(next);
},
// let uid = req.user.uid || 0; // pagecache重构
let headerData = headerModel.setNav({
navTitle: '商品详情'
});
detailModel.getProductData({
id: req.params[0],
goodsId: req.params[1],
/*
* 商品基本信息 SKN 进入 pagecache重构
*/
sknData(req, res, next) {
let brandId = req.query.brandId;
let productId = req.query.productId;
let skn = req.query.skn;
let bundleType = req.query.bundleType;
let gid = req.query.gid;
// uid: uid,
ua: req.get('user-agent') || ''
}).then((result) => {
if (_.isEmpty(result)) {
if ([brandId, productId].some(val => !val)) {
return next();
}
// pagecache重构
// result.studentPrice = req.__User__.isStudent && result && result.goodsPrice && result.goodsPrice.studentPrice ? result.goodsPrice.studentPrice : false;
res.render('detail/detail', {
pageHeader: headerData,
result: result,
page: 'seckill-detail',
title: result.goodsName,
pageFooter: true,
localCss: true
newDetailModel.querySknData({
skn,
brandId,
productId,
bundleType,
gid
}).then(result => {
if (_.isEmpty(result)) {
return next();
}
res.json(result);
});
}).catch(next);
};
},
/**
* 商品信息异步数据
* @param {[type]} req [description]
* @param {[type]} res [description]
* @return {[type]} [description]
*/
exports.indexData = (req, res, next) => {
if (!req.xhr) {
return next();
}
if (!req.body.id) {
return next();
}
let uid = req.user.uid || 0;
detailModel.getProductAsyncData(Object.assign({
id: req.body.id,
goodsId: req.body.goodsId,
productSkn: req.body.productSkn,
uid: uid,
ua: req.get('user-agent') || ''
}, req.__User__)).then((result) => {
if (_.isEmpty(result)) {
indexData(req, res, next) {
if (!req.xhr) {
return next();
}
if (!req.body.id) {
return next();
}
let uid = req.user.uid || 0;
let shoppingKey = req.cookies._SPK || '';
detailModel.getNewProductAsyncData(Object.assign({
id: req.body.id,
goodsId: req.body.goodsId,
productSkn: req.body.productSkn,
bundleType: req.body.bundleType,
uid: uid,
shoppingKey: shoppingKey,
ua: req.get('user-agent') || ''
}, req.__User__)).then((result) => {
if (_.isEmpty(result)) {
return res.json({
code: 400,
message: '数据错误'
});
}
result.studentPrice = req.__User__.isStudent && result && result.goodsPrice &&
result.goodsPrice.studentPrice ? result.goodsPrice.studentPrice : false;
return res.json(result);
}).catch(next);
},
/**
* 商品收藏/取消收藏
*/
favoriteProduct(req, res, next) {
let allowOrigin = _.get(req, 'headers.origin', null) ?
req.headers.origin : req.protocol + '://' + req.headers.host;
res.setHeader('Access-Control-Allow-Origin', allowOrigin);
res.setHeader('Access-Control-Allow-Credentials', 'true');
let uid = req.user.uid;
if (!uid) {
return res.json({
code: 400,
message: '数据错误'
});
data: helpers.urlFormat('/signin.html', {
refer: req.headers.referer
})});
}
result.studentPrice = req.__User__.isStudent && result && result.goodsPrice && result.goodsPrice.studentPrice ? result.goodsPrice.studentPrice : false;
return res.json(result);
}).catch(next);
};
// 获取秒杀信息
exports.getSeckillData = (req, res) => {
if (req.body.opt === 'ok') {
listModel.setFavorite(req.body.id, uid, 'product').then(result => {
return res.json(result);
}).catch(next);
} else {
listModel.setFavoriteCancel(req.body.id, uid, 'product').then(result => {
return res.json(result);
}).catch(next);
}
},
/**
* 限购商品说明页面
*/
limitHelp(req, res) {
res.render('detail/limit-help', {
module: 'product',
page: 'limit-help'
});
},
detailModel.getSeckillData({
// 获取秒杀信息
getSeckillData(req, res) {
productskn: req.params.productskn
newDetailModel.getSeckillData({
}, req).then(result => {
productskn: req.params.productskn
return res.json(result);
}, req).then(result => {
});
return res.json(result);
});
}
};
module.exports = newDetail;
... ...
... ... @@ -5,6 +5,7 @@
const utils = '../../../utils';
const _ = require('lodash');
const api = global.yoho.API;
const helpers = global.yoho.helpers;
const productProcess = require(`${utils}/product-process`);
/**
... ... @@ -25,16 +26,41 @@ const getBundleBySkn = (productSkn) => {
* @param params
* @returns {*}
*/
const detail = (params) => {
if (!params.skn) {
const detail = (params, isApp) => {
if (!params.skn && !params.bundle_skn) {
return Promise.resolve({});
}
let bundleIndex = (params.index || 1);
return getBundleBySkn(params.skn).then(result => {
return {
bundleInfo: _.get(result, 'data.bundleInfo', {}),
productList: productProcess.processProductList(_.get(result, 'data.productList', []))
};
--bundleIndex;
return getBundleBySkn(params.skn || params.bundle_skn).then(result => {
if (_.has(result, `data[${bundleIndex}]`)) {
let shareInfo = _.get(result, 'data[0].shareInfo', {});
return {
bundleDatas: _.map(result.data, (bundle, index) => {
let query = {skn: params.skn, index: index + 1};
if (isApp) {
query.app_version = isApp;
}
return {
selected: index === bundleIndex,
title: _.get(bundle, 'bundleInfo.tabName') || '',
href: helpers.urlFormat('/product/bundle/detail', query),
};
}),
shareInfo: {
imgUrl: `http:${helpers.image(shareInfo.imgUrl, 300, 300)}`,
subTitle: encodeURIComponent(shareInfo.subTitle),
title: encodeURIComponent(shareInfo.title),
url: shareInfo.url
},
bundleInfo: _.get(result, `data[${bundleIndex}].bundleInfo`, {}),
productList: productProcess.processProductList(_.get(result, `data[${bundleIndex}].productList`, []))
};
}
return {};
});
};
... ...
... ... @@ -223,12 +223,13 @@ const tool = {
* @param skn
* @returns {{}}
*/
processBundle(bundleData, skn, gid) {
processBundle(bundleData, skn, gid, index) {
let subPrice = _.get(bundleData, 'bundleInfo.subPrice', 0);
return {
title: '优惠套装',
href: helpers.urlFormat('/product/bundle/detail', {skn: skn, gid: gid}),
tabName: _.get(bundleData, 'bundleInfo.tabName') || '',
title: _.get(bundleData, 'bundleInfo.bundleName') || '优惠套装',
href: helpers.urlFormat('/product/bundle/detail', {skn: skn, gid: gid, index: index}),
description: subPrice ? '立省¥' + subPrice : 0,
productList: productProcess.processProductList(bundleData && bundleData.productList)
};
... ... @@ -330,16 +331,15 @@ const newDetail = {
userConsult: info[3]
}, productId);
let bundleData = _.get(info[5], 'data', null);
/* 套装 */
if (bundleData && _.get(bundleData, 'bundleInfo.discountType', null) === 1) {
finalResult.bundleData = tool.processBundle(bundleData, skn, gid);
}
let bundleDatas = _.get(info[5], 'data', []);
/* 量贩 */
if (bundleData && _.get(bundleData, 'bundleInfo.discountType', null) === 2) {
tool.processDiscount(finalResult, bundleData);
if (_.some(bundleDatas, data => data.discountType === 2)) {
tool.processDiscount(finalResult, _.find(bundleDatas, data => data.discountType === 2));
} else { /* 套装 */
finalResult.bundleDatas = _.map(bundleDatas, (data, index) => {
return tool.processBundle(data, skn, gid, ++index);
});
}
return finalResult;
... ...
... ... @@ -171,6 +171,11 @@ const _searchGoods = (params) => {
method = 'app.student.discount';
}
// 个人中心优惠券立即使用 - 商品列表
if (params.coupon_id) {
method = 'app.search.coupon';
}
return api.get('', _.assign({
method: method
}, params), {
... ... @@ -186,16 +191,37 @@ const getSearchData = (params) => {
return _searchGoods(params).then((result) => {
if (result && result.code === 200) {
let newList = {};
let suggestion = {};
newList.list = productProcess.processProductList(result.data.product_list || [], {
isApp: params.isApp || (params.appVersion && params.appVersion !== 'false'),
gender: _coverChannel[params.coverChannel]
});
params.page = parseInt(params.page, 10);
result.data.total = parseInt(result.data && result.data.total || 0, 10);
if (parseInt(params.page, 10) === 1) {
if (params.page === 1) {
newList.total = result.data.total;
}
// 搜索过来的 推荐词条件判断 redmine: 18567
if (params.from === 'search' && params.page === 1 && (result.data.isChangedQuery === 'Y' ||
result.data.total <= 20 || params.needSuggestion === 'Y')) {
params.isChangedQuery = result.data.isChangedQuery === 'Y';
suggestion = {
isNeedSuggestion: params.isChangedQuery || params.needSuggestion === 'Y', // 是否是关键词搜索判断
termsSuggestion: productProcess.termsSuggestion(
result.data.suggestion && result.data.suggestion.terms_suggestion || [], params
),
isMaybeLike: (params.isChangedQuery || params.needSuggestion === 'Y') &&
result.data.total > 0 ? false : true // 猜你喜欢显示不显示判断
};
suggestion.isNeedSuggestionOne = suggestion.termsSuggestion.length > 1;// 如果只有一个<或者试试不显示>
}
newList.suggestion = suggestion;
return newList;
} else {
logger.error('get product search api return code is not 200');
... ...
/**
* 商品详情models
* @author: xuqi<qi.xu@yoho.cn>
* @date: 2016/5/6
* [商品获取数据]
*/
'use strict';
const _ = require('lodash');
const comment = require('./consult-comment');
const commentModel = require('./consult-comment');
const bundle = require('./bundle');
const productProcess = require(`${utils}/product-process`);
const api = global.yoho.API;
const singleAPI = global.yoho.SingleAPI;
const helpers = global.yoho.helpers;
const SINGLE_TICKETS_SKN = 51335912; // 展览票
const tool = {
prodessDetailData(origin) {
let dest = {}; // 结果输出
/**
* 获取用户数据信息
* @param {[string]} uid
* @return {[array]}
*/
const _getUserProfile = (uid) => {
if (!uid) {
return Promise.resolve({
code: 200,
data: {}
});
}
return api.get('', {
method: 'app.passport.profile',
uid: uid
}, {
cache: true
});
};
/**
* 处理品牌关联店铺信息
* @param {array}
* @return {array}
*/
const _processShopsInfo = (data) => {
let enterStore = [];
_.forEach(data, function(value) {
let shopInfo = {
img: value.brand_ico,
storeName: value.brand_name
};
if (value.shop_id) {
shopInfo.url = helpers.urlFormat('/product/index/brand', {
shop_id: value.shop_id
});
} else {
shopInfo.url = helpers.urlFormat('', null, value.brand_domain);
// 商品名称
if (!origin.product_name) {
return dest;
}
enterStore.push(shopInfo);
});
return enterStore;
};
/**
* 处理限购商品的有关按钮状态(或取现购买以及底部商品购买按钮)
* @param {array} 需要处理的数据
* @param {int} 限购商品的关联状态
* @param {Boolean} 限购商品是否已开售
* @return {array}
*/
const _procShowStatus = (data, showStatus, isBeginSale) => {
switch (showStatus) {
case 1: // 开售前/后,立即分享获得限购码(用户未领取限购码)
// 显示获取限购码按钮
data.canGetLimitCode = true;
if (isBeginSale) { // 开售后
data.cartInfo.noLimitCode = true;
} else {
data.cartInfo.limitNotForSale = true;
}
break;
case 2: // 开售后,限购码已抢光(用户未领取限购码)
data.codeEmpty = true;
data.cartInfo.noLimitCode = true;
break;
case 3: // 开售后,商品已经售罄
data.noLimitGoodsBtn = true;
data.cartInfo.soldOut = true;
break;
case 4: // 开售后,立即购买(用户已领取限购码)
data.gotCode = true;
data.cartInfo.canNotBuy = true;
break;
case 5: // 开售前,限购码已被抢光(用户未领取限购码)
data.codeEmpty = true;
data.cartInfo.limitNotForSale = true;
break;
case 6: // 开售前,即将开售(用户已领取限购码)
data.gotCode = true;
data.cartInfo.limitNotForSale = true;
break;
case 7: // 开售后,用户已经用获得的限购码购买过商品
data.gotCode = true;
data.cartInfo.noLimitCode = true;
break;
default:
break;
}
dest.goodsName = origin.product_name;
return data;
};
// 是否是虚拟商品
// dest.virtualGoods = (origin.attribute * 1 === 3);
/**
* 根据设备类型获得限购商品跳转app的url
* @param {string} productCode 限购商品码
* @param {string} skn 限购商品skn
* @return {string} 限购商品跳转url
*/
const _getLimitCodeUrl = (productCode, skn, ua) => {
let url = 'yohoapp://yoho.app/openwith?limit_product_code=' + productCode +
'&product_skn=' + skn;
// 活动促销短语
origin.market_phrase && origin.market_phrase !== ' ' && (dest.marketPhrase = origin.market_phrase);
let isIphone = String(ua).indexOf('iPhone') >= 0;
let isIpad = ua.indexOf('iPad') >= 0;
// 商品促销短语
origin.sales_phrase && origin.sales_phrase !== ' ' && (dest.goodsSubtitle = origin.sales_phrase);
if (isIphone || isIpad) {
let params = {};
// 商品标签
if (origin.tags) {
let productTags = {};
params.lp = productCode;
url = 'yohobuy://' + helpers.urlFormat('/limitpurchase', params);
}
return url;
};
_.forEach(origin.tags, function(value) {
productTags[value] = true;
});
/**
* 详情页数据格式化
* @param origin Object 原始数据
* @return dest Object 格式化数据
*/
// 老接口h5的代码
// const _detailDataPkg = (origin, uid, vipLevel, ua) => {
// let dest = {}, // 结果输出
// thumbImageList = [],
// colorGroup = {},
// sizeGroup = [],
// totalStorageNum = 0;
// // 商品名称
// if (origin.productName === null || typeof origin.productName === 'undefined') {
// return dest;
// }
// dest.goodsName = origin.productName;
// // 是否是虚拟商品
// dest.virtualGoods = origin.attribute * 1 === 3 ? true : false;
// // 用户未登录时
// if (!uid) {
// let params = {};
// params.refer = helpers.urlFormat('/product/' + origin.erpProductId + '.html');
// dest.loginUrl = helpers.urlFormat('/signin.html', params);
// }
// // 商品促销短语
// if (origin.salesPhrase) {
// dest.goodsSubtitle = origin.salesPhrase;
// }
// // 促销信息 TODO: 换新接口
// if (origin.promotionBoList) {
// let discountList = [];
// _.forEach(origin.promotionBoList, function(value) {
// discountList.push({
// text: `【${value.promotionType}】${value.promotionTitle}`
// });
// });
// if (discountList.length) {
// dest.goodsDiscount = {
// list: discountList
// };
// }
// }
// // 商品标签
// if (origin.productTagBoList) {
// let productTags = {};
// _.forEach(origin.productTagBoList, function(value) {
// switch (value.tagLabel) {
// case 'is_soon_sold_out':
// productTags.is_soon_sold_out = true;
// break;
// case 'is_new':
// productTags.is_new = true;
// break;
// case 'is_discount':
// productTags.is_discount = true;
// break;
// case 'is_limited':
// productTags.is_limited = true;
// break;
// case 'is_yohood':
// productTags.is_yohood = true;
// break;
// case 'is_advance':
// productTags.is_advance = true;
// break;
// default:
// break;
// }
// });
// dest.tags = productTags;
// }
// // 商品价格
// if (origin.productPriceBo) {
// let originPrice = origin.productPriceBo;
// let goodsPrice = {
// currentPrice: originPrice.formatSalesPrice
// };
// if (originPrice.formatMarketPrice !== originPrice.formatSalesPrice) {
// goodsPrice.previousPrice = originPrice.formatMarketPrice;
// }
// dest.goodsPrice = goodsPrice;
// // 商品返回 有货币
// if (originPrice.yohoCoinNum) {
// dest.commodityReturn = originPrice.yohoCoinNum;
// }
// }
// // VIP 商品价格
// if (origin.productPriceBo.vipPrices) {
// let vipList = [];
// _.forEach(origin.productPriceBo.vipPrices, function(value) {
// vipList.push({
// level: value.vipLevel,
// text: value.vipPrice,
// currentLevel: (value.vipLevel === vipLevel)
// });
// });
// if (vipList.length) {
// dest.vipLevel = {
// list: vipList
// };
// }
// }
// // 上市期
// if (origin.expectArrivalTime) {
// dest.periodOfMarket = `${origin.expectArrivalTime}月`;
// }
// // 商品咨询
// dest.feedbacks = {
// consults: [],
// consultsNum: 0
// };
// let consultParams = {
// product_id: origin.id
// };
// if (_.has(dest, 'feedbacks.consultsNum')) {
// consultParams.total = dest.feedbacks.consultsNum;
// dest.feedbacks.consultsUrl = helpers.urlFormat('/product/detail/consults', consultParams);
// } else {
// dest.feedbacks.consultsUrl = helpers.urlFormat('/product/detail/consultform', consultParams);
// }
// // 商品评价
// dest.feedbacks.commentsNum = 0;
// if (origin.commentBoWrapper) {
// dest.feedbacks.commentsNum = origin.commentBoWrapper.commentTotal;
// let commentList = [];
// _.forEach(origin.commentBoWrapper.commentBoList, function(value) {
// commentList.push({
// userName: value.nickName,
// desc: `${value.colorName}/${value.sizeName}`,
// content: value.content ? value.content : '',
// time: value.createTime
// });
// });
// dest.feedbacks.comments = commentList;
// dest.feedbacks.commentsUrl = helpers.urlFormat('/product/detail/comments', {
// product_id: origin.id,
// total: dest.feedbacks.commentsNum
// });
// }
// // 品牌信息
// if (origin.brand) {
// let extra = `?productSkn=${origin.erpProductId}&brandId=${origin.brand.id}`;
// dest.preferenceUrl = `/product/detail/preference${extra}`;
// }
// dest.productSkn = origin.erpProductId;
// // 商品信息
// if (origin.goodsList) {
// let goodsGroup = [],
// sizeName = '',
// colorList = [],
// sizeList = {},
// allSizeList = {},
// colorStorageGroup = {},
// colorStorageNum = 0;
// _.forEach(origin.goodsList, function(value) {
// if (value.status === 0) {
// return;
// }
// colorStorageNum = 0;
// // 商品分组
// if (value.goodsImagesList) {
// _.forEach(value.goodsImagesList, function(good) {
// goodsGroup.push({
// goodsId: good.goodsId,
// img: good.imageUrl
// });
// });
// }
// // 商品的尺码列表
// colorStorageGroup[value.productSkc] = {};
// if (value.goodsSizeBoList) {
// sizeList[value.productSkc] = [];
// _.forEach(value.goodsSizeBoList, function(size) {
// sizeList[value.productSkc].push({
// id: size.id,
// skuId: size.goodsSizeSkuId,
// goodsId: size.goodsId,
// colorId: size.colorId,
// name: size.sizeName,
// sizeNum: size.goodsSizeStorageNum
// });
// sizeName = size.sizeName;
// // 所有尺码列表,赋值用于前端展示默认尺码的时候
// // 判断出没有库存则显示灰色
// let build = {
// id: size.id,
// storage: size.goodsSizeStorageNum
// };
// allSizeList[sizeName] = (allSizeList[sizeName] === null ||
// typeof allSizeList[sizeName] === 'undefined') ? build :
// allSizeList[sizeName];
// colorStorageNum += parseInt(size.goodsSizeStorageNum, 10);
// colorStorageGroup[value.productSkc][sizeName] = parseInt(size.goodsSizeStorageNum, 10);
// });
// // 颜色分组
// colorList.push({
// id: value.colorId,
// skcId: value.productSkc,
// name: value.colorName,
// goodsName: value.goodsName,
// colorNum: colorStorageNum
// });
// }
// // 缩略图
// thumbImageList.push({
// img: value.colorImage
// });
// // 商品库存总数
// totalStorageNum += _.toNumber(colorStorageNum);
// });
// // 遍历所有尺码,构建颜色显示数据
// let i = 1;
// sizeGroup[0] = {
// size: []
// };
// _.forEach(allSizeList, (value, key) => {
// // 默认尺码
// sizeGroup[0].size.push({
// name: key,
// sizeNum: _.toNumber(value.storage) > 0 ? true : false,
// id: value.id
// });
// colorGroup[i] = {
// color: []
// };
// // 各个颜色的尺码, 每行显示一个尺码对应的颜色
// _.forEach(colorList, (colorArr) => {
// let tempColorArr = _.cloneDeep(colorArr);
// if (colorStorageGroup[tempColorArr.skcId] &&
// colorStorageGroup[tempColorArr.skcId][key]) {
// tempColorArr.colorNum = colorStorageGroup[tempColorArr.skcId][key];
// } else {
// tempColorArr.colorNum = 0;
// }
// colorGroup[i].color.push(Object.assign({}, tempColorArr));
// });
// colorGroup[i].id = value.id;
// ++i;
// });
// colorGroup[0] = {
// color: []
// };
// // 遍历所有颜色, 构建尺码显示数据
// i = 1;
// _.forEach(colorList, function(value) {
// // 各个尺码的颜色, 每行显示一个颜色的对应尺码
// sizeGroup[i] = {
// size: sizeList[value.skcId],
// colorId: value.skcId
// };
// // 默认颜色
// colorGroup[0].color.push(value);
// ++i;
// });
// // 商品图:多个
// if (goodsGroup.length > 1) {
// let bannerList = [];
// _.forEach(goodsGroup, function(value) {
// bannerList.push({
// img: value.img
// });
// });
// dest.bannerTop = {
// list: bannerList
// };
// } else if (goodsGroup[0] !== null && typeof goodsGroup[0] !== 'undefined') {
// dest.bannerTop = {
// img: goodsGroup[0].img
// };
// }
// }
// // 悬浮的购物车信息
// dest.cartInfo = {
// cartUrl: helpers.urlFormat('/cart/index/index'),
// numInCart: 0,
// goodsInstore: origin.storage
// };
// let soldOut = (origin.storage === 0) || (origin.status === 0 || totalStorageNum === 0);
// let notForSale = origin.attribute === 2;
// // 显示加入购物车链接
// if (!soldOut && !notForSale) {
// _.orderBy(colorGroup);
// Object.assign(dest.cartInfo, {
// productId: origin.id,
// thumbs: thumbImageList,
// name: dest.goodsName ? dest.goodsName : '',
// price: dest.goodsPrice.previousPrice ? dest.goodsPrice.previousPrice : '',
// salePrice: dest.goodsPrice.currentPrice ? dest.goodsPrice.currentPrice : '',
// totalNum: totalStorageNum,
// colors: _.toArray(colorGroup),
// sizes: sizeGroup
// });
// // 限购商品
// if (origin.isLimitBuy === 'Y') {
// // 是否开售
// let isBeginSale = (origin.saleStatus !== null && typeof origin.saleStatus !== 'undefined' &&
// origin.saleStatus === 1);
// // 限购商品有关的展示状态
// let showStatus = 1;
// if (origin.showStatus !== null && typeof origin.showStatus !== 'undefined') {
// showStatus = parseInt(origin.showStatus, 10);
// }
// // 处理限购商品有关的按钮状态
// dest = _procShowStatus(dest, showStatus, isBeginSale);
// dest.cartInfo.limitProductCode = origin.limitProductCode;
// dest.cartInfo.limitCodeUrl = _getLimitCodeUrl(origin.limitProductCode, origin.erpProductId, ua);
// dest.cartInfo.limitProductPay = helpers.urlFormat('/cart/index/orderEnsure');
// } else {
// dest.cartInfo.addToCartUrl = helpers.urlFormat('/product/buy_' + origin.id + '_' +
// origin.goodsList.id + '.html');
// }
// } else if (notForSale) {
// dest.cartInfo.notForSale = true;
// } else if (soldOut) {
// dest.cartInfo.soldOut = true;
// }
// // 是否收藏
// dest.isCollect = false;
// if (origin.isCollect !== null && typeof origin.isCollect !== 'undefined' && origin.isCollect === 'Y') {
// dest.isCollect = true;
// dest.cartInfo.isCollect = true;
// }
// // 底部简介URL链接
// dest.introUrl = '/product/detail/intro/' + origin.erpProductId;
// dest.id = origin.id;
// // 虚拟商品(门票)
// if (origin.attribute * 1 === 3) {
// dest.tickets = true;
// dest.ticketsConfirm = helpers.urlFormat('/cart/index/ticketsConfirm');
// // 展览票
// if (origin.erpProductId * 1 === SINGLE_TICKETS_SKN) {
// dest.single = true;
// } else {
// // 套票
// dest.package = true;
// }
// // 购票限制
// dest.cartInfo.limit = 4;
// // 清空活动
// dest.goodsDiscount = [];
// // 来自登录页,自动弹出选择框
// // if (isset($_GET['product_type']) && $_GET['product_type'] == 'ticket') {
// // $result['showPannel'] = true;
// // }
// }
// return dest;
// };
// const _detailDataPkg = (origin, uid, vipLevel, ua) => {
// let dest = {}, // 结果输出
// thumbImageList = [],
// colorGroup = {},
// sizeGroup = [],
// totalStorageNum = 0;
// // 商品名称
// if (!origin.productName) {
// dest.feedbacks = {};
// return dest;
// }
// dest.goodsName = origin.productName;
// // 是否是虚拟商品
// dest.virtualGoods = (origin.attribute * 1 === 3);
// // 用户未登录时
// if (!uid) {
// dest.loginUrl = helpers.urlFormat('/signin.html', {
// refer: helpers.urlFormat('/product/' + origin.productSkn + '.html')
// });
// }
// // 商品促销短语
// origin.salesPhrase && (dest.goodsSubtitle = origin.salesPhrase);
// // 促销信息 TODO: 换新接口
// if (origin.promotionBoList) {
// let discountList = [];
// _.forEach(origin.promotionBoList, function(value) {
// discountList.push({
// text: `【${value.promotionType}】${value.promotionTitle}`
// });
// });
// discountList.length && (dest.goodsDiscount = {
// list: discountList
// });
// }
// // 商品标签
// if (origin.tags) {
// let productTags = {};
// _.forEach(origin.tags, function(value) {
// productTags[value] = true;
// });
// dest.tags = productTags;
// }
// // 商品价格
// let goodsPrice = {
// currentPrice: origin.formatSalesPrice === '0' ? origin.formatMarketPrice : origin.formatSalesPrice
// };
// if (origin.formatSalesPrice !== '0' && origin.formatMarketPrice !== origin.formatSalesPrice) {
// goodsPrice.previousPrice = origin.formatMarketPrice;
// }
// dest.goodsPrice = goodsPrice;
// // 商品返回 YOHO 币
// origin.yohoCoinNum && (dest.commodityReturn = origin.yohoCoinNum);
// // VIP 商品价格
// if (origin.vip) {
// let vipList = [];
// let levelList = {
// 银卡: 1,
// 金卡: 2,
// 白金: 3
// };
// _.forEach(origin.vip, function(value) {
// vipList.push({
// level: levelList[value.caption],
// text: value.price,
// currentLevel: (value.vipLevel === vipLevel)
// });
// });
// vipList.length && (dest.vipLevel = {
// list: vipList
// });
// }
// // 上市期
// origin.expectArrivalTime && (dest.periodOfMarket = `${origin.expectArrivalTime}月`);
// // 商品咨询
// dest.feedbacks = {
// consults: [],
// consultsNum: 0
// };
// let consultParams = {
// product_id: origin.productId
// };
// if (_.has(dest, 'feedbacks.consultsNum')) {
// consultParams.total = dest.feedbacks.consultsNum;
// dest.feedbacks.consultsUrl = helpers.urlFormat('/product/detail/consults', consultParams);
// } else {
// dest.feedbacks.consultsUrl = helpers.urlFormat('/product/detail/consultform', consultParams);
// }
// // 商品评价
// dest.feedbacks.commentsUrl = helpers.urlFormat('/product/detail/comments', {
// product_id: origin.productId,
// });
// // 品牌信息
// if (origin.brand) {
// let extra = `?productSkn=${origin.productSkn}&brandId=${origin.brandInfo.brandId}`;
// dest.preferenceUrl = `/product/detail/preference${extra}`;
// }
// dest.productSkn = origin.productSkn;
// // 商品信息
// if (origin.goodsList) {
// let goodsGroup = [],
// sizeName = '',
// colorList = [],
// sizeList = {},
// allSizeList = {},
// colorStorageGroup = {},
// colorStorageNum = 0;
// _.forEach(origin.goodsList, function(value) {
// if (value.status === 0) {
// return;
// }
// colorStorageNum = 0;
// // 商品分组
// if (value.imagesList) {
// _.forEach(value.imagesList, function(good) {
// goodsGroup.push({
// goodsId: value.goodsId,
// img: good.imageUrl
// });
// });
// }
// // 商品的尺码列表
// colorStorageGroup[value.productSkc] = {};
// if (value.sizeList) {
// sizeList[value.productSkc] = [];
// _.forEach(value.sizeList, function(size) {
// sizeList[value.productSkc].push({
// id: size.sizeId,
// skuId: size.productSku,
// goodsId: value.goodsId,
// colorId: value.colorId,
// name: size.sizeName,
// sizeNum: size.storageNumber
// });
// sizeName = size.sizeName;
// // 所有尺码列表,赋值用于前端展示默认尺码的时候
// // 判断出没有库存则显示灰色
// let build = {
// id: size.sizeId,
// storage: size.storageNumber
// };
// allSizeList[sizeName] = (allSizeList[sizeName] === null ||
// typeof allSizeList[sizeName] === 'undefined') ? build : allSizeList[sizeName];
// colorStorageNum += parseInt(size.storageNumber, 10);
// colorStorageGroup[value.productSkc][sizeName] = parseInt(size.storageNumber, 10);
// });
// // 颜色分组
// colorList.push({
// id: value.colorId,
// skcId: value.productSkc,
// name: value.colorName,
// colorNum: colorStorageNum
// });
// }
// // 缩略图
// thumbImageList.push({
// img: value.colorImage
// });
// // 商品库存总数
// totalStorageNum += _.toNumber(colorStorageNum);
// });
// // 遍历所有尺码,构建颜色显示数据
// let i = 1;
// sizeGroup[0] = {
// size: []
// };
// _.forEach(allSizeList, (value, key) => {
// // 默认尺码
// sizeGroup[0].size.push({
// name: key,
// sizeNum: _.toNumber(value.storage) > 0 ? true : false,
// id: value.id
// });
// colorGroup[i] = {
// color: []
// };
// // 各个颜色的尺码, 每行显示一个尺码对应的颜色
// _.forEach(colorList, (colorArr) => {
// let tempColorArr = _.cloneDeep(colorArr);
// if (colorStorageGroup[tempColorArr.skcId] &&
// colorStorageGroup[tempColorArr.skcId][key]) {
// tempColorArr.colorNum = colorStorageGroup[tempColorArr.skcId][key];
// } else {
// tempColorArr.colorNum = 0;
// }
// colorGroup[i].color.push(Object.assign({}, tempColorArr));
// });
// colorGroup[i].id = value.id;
// ++i;
// });
// colorGroup[0] = {
// color: []
// };
// // 遍历所有颜色, 构建尺码显示数据
// i = 1;
// _.forEach(colorList, function(value) {
// // 各个尺码的颜色, 每行显示一个颜色的对应尺码
// sizeGroup[i] = {
// size: sizeList[value.skcId],
// colorId: value.skcId
// };
// // 默认颜色
// colorGroup[0].color.push(value);
// ++i;
// });
// // 商品图:多个
// if (goodsGroup.length > 1) {
// let bannerList = [];
// _.forEach(goodsGroup, function(value) {
// bannerList.push({
// img: value.img
// });
// });
// dest.bannerTop = {
// list: bannerList
// };
// } else if (goodsGroup[0]) {
// dest.bannerTop = {
// img: goodsGroup[0].img
// };
// }
// }
// // 悬浮的购物车信息
// dest.cartInfo = {
// cartUrl: helpers.urlFormat('/cart/index/index'),
// numInCart: 0,
// goodsInstore: origin.storageSum
// };
// let soldOut = (origin.storageSum === 0) || (totalStorageNum === 0); // status
// let notForSale = origin.attribute === 2;
// // 显示加入购物车链接
// if (!soldOut && !notForSale) {
// _.orderBy(colorGroup);
// Object.assign(dest.cartInfo, {
// productId: origin.productId,
// thumbs: thumbImageList,
// name: dest.goodsName ? dest.goodsName : '',
// price: dest.goodsPrice.previousPrice ? dest.goodsPrice.previousPrice : '',
// salePrice: dest.goodsPrice.currentPrice ? dest.goodsPrice.currentPrice : '',
// totalNum: totalStorageNum,
// colors: _.toArray(colorGroup),
// sizes: sizeGroup
// });
// // 限购商品
// if (origin.isLimitBuy) {
// // 是否开售
// let isBeginSale = (origin.saleStatus === 1);
// // 限购商品有关的展示状态
// let showStatus = 1;
// origin.showStatus && (showStatus = parseInt(origin.showStatus, 10));
// // 处理限购商品有关的按钮状态
// dest = _procShowStatus(dest, showStatus, isBeginSale);
// dest.cartInfo.limitProductCode = origin.limitProductCode;
// dest.cartInfo.limitCodeUrl = _getLimitCodeUrl(origin.limitProductCode, origin.productSkn, ua);
// dest.cartInfo.limitProductPay = helpers.urlFormat('/cart/index/orderEnsure');
// } else {
// dest.cartInfo.addToCartUrl = helpers.urlFormat('/product/buy_' + origin.productId + '_' +
// origin.goodsList.goodsId + '.html');
// }
// } else if (notForSale) {
// dest.cartInfo.notForSale = true;
// } else if (soldOut) {
// dest.cartInfo.soldOut = true;
// }
// // 是否收藏
// dest.isCollect = false;
// if (origin.isCollect === 'Y') {
// dest.isCollect = true;
// dest.cartInfo.isCollect = true;
// }
// // 底部简介URL链接
// dest.introUrl = '/product/detail/intro/' + origin.productSkn;
// dest.id = origin.productId;
// // 虚拟商品(门票)
// if (origin.attribute * 1 === 3) {
// dest.tickets = true;
// dest.ticketsConfirm = helpers.urlFormat('/cart/index/ticketsConfirm');
// // 展览票
// if (origin.productSkn * 1 === SINGLE_TICKETS_SKN) {
// dest.single = true;
// } else {
// // 套票
// dest.package = true;
// }
// // 购票限制
// dest.cartInfo.limit = 4;
// // 清空活动
// dest.goodsDiscount = [];
// // 来自登录页,自动弹出选择框
// // if (isset($_GET['product_type']) && $_GET['product_type'] == 'ticket') {
// // $result['showPannel'] = true;
// // }
// }
// return dest;
// };
let _getShopsInfo = (brandId) => {
if (!brandId) {
return Promise.resolve([]);
}
return api.get('', {
method: 'app.shop.seckill.queryShopsByBrandId',
brand_id: _.toString(brandId)
}, {
cache: true
}).then(shops => {
if (shops.code === 200) {
return _processShopsInfo(shops.data);
dest.tags = productTags;
}
return [];
});
};
// 商品价格
let goodsPrice = {
currentPrice: origin.format_sales_price === '0' ? origin.format_market_price : origin.format_sales_price
};
let _getPromotionInfo = (skn) => {
return api.get('', {
method: 'app.product.seckill.promotion',
product_skn: _.toString(skn)
}, {
cache: true
}).then((result) => {
if (result.code === 200) {
return result.data;
if (origin.format_sales_price !== '0' && origin.format_market_price !== origin.format_sales_price) {
goodsPrice.previousPrice = origin.format_market_price;
}
return {};
});
};
dest.goodsPrice = goodsPrice;
/**
* [单独获取用户收藏商品状态]
*/
let _getFavorite = (productId, uid) => {
if (!uid) {
return Promise.resolve({});
}
return singleAPI.get('favorite', {
method: 'app.favorite.isFavoriteNew',
uid: uid,
id: productId
}).then((result) => {
if (result.code === 200) {
return result.data;
}
// 商品返回 YOHO 币
// origin.yohoCoinNum && (dest.commodityReturn = origin.yohoCoinNum);
return {};
});
};
// 上市期
origin.expect_arrival_time && (dest.periodOfMarket = origin.expect_arrival_time);
// let getProductData = (data) => {
// let finalResult;
// let params = {
// method: 'app.product.seckill.data'
// };
// if (data.id) { // 通过 productId 获取商品详情
// Object.assign(params, {
// product_id: _.toString(data.id)
// });
// } else if (data.productSkn) { // 通过 productSkn 获取商品详情
// Object.assign(params, {
// product_skn: _.toString(data.productSkn)
// });
// }
// if (data.uid) {
// params.uid = data.uid;
// }
// return _getUserProfile(params.uid).then((user) => {
// data.vipLevel = (user.data && user.data.vip_info && user.data.vip_info.cur_level) || '0';
// data.isStudent = (user.data && user.data.vip_info && user.data.vip_info.is_student) ? true : false;
// params.is_student = data.isStudent ? 1 : 0;
// params.current_vip_level = data.vipLevel;
// return api.get('', params, {
// code: 200
// }).then(global.yoho.camelCase).then(result => {
// if (result.code === 500 || !result.data) {
// return {};
// }
// result = result.data;
// return Promise.all([
// _getShopsInfo(_.get(result, 'brandInfo.brandId', 0)),
// _getPromotionInfo(result.productSkn),
// comment.getCommentInfo({
// productId: result.productId
// }),
// _getCommonConsult(),
// comment.getConsults(result.productId, 1, 2)
// ]).then((info) => {
// result.promotionBoList = info[1];
// finalResult = _detailDataPkg(result, data.uid, data.vipLevel, data.ua);
// finalResult.enterStore = info[0];
// finalResult.isStudent = data.isStudent;
// Object.assign(finalResult.feedbacks, info[2]);
// /* 如果有咨询,显示咨询,否则显示常见问题 */
// if (info[4].total) {
// finalResult.feedbacks.consultsNum = parseInt(info[4].total, 10);
// Object.assign(finalResult.feedbacks, {
// commonConsults: false,
// consultsNum: parseInt(info[4].total, 10),
// consults: _.take(info[4].list, 2)
// });
// } else if (!_.isEmpty(info[3]) && !_.get(info[2], 'feedbacks.consultsNum', 0)) {
// Object.assign(finalResult.feedbacks, {
// commonConsults: true,
// consultsNum: true,
// consults: _.take(info[3], 2)
// });
// }
// return finalResult;
// });
// });
// });
// };
//
/**
* [商品获取数据] pagecache重构
*/
let getProductData = (data) => {
let finalResult;
let params = {
method: 'app.product.seckill.data'
};
if (data.id) { // 通过 productId 获取商品详情
Object.assign(params, {
product_id: _.toString(data.id)
});
} else if (data.productSkn) { // 通过 productSkn 获取商品详情
Object.assign(params, {
product_skn: _.toString(data.productSkn)
});
}
// 品牌信息
if (origin.shop_id) {
let extra = `?productSkn=${origin.product_skn}&shopId=${origin.shop_id}`;
// pagecache重构
// if (data.uid) {
// params.uid = data.uid;
// }
// pagecache重构
// return _getUserProfile(params.uid).then((user) => {
// data.vipLevel = (user.data && user.data.vip_info && user.data.vip_info.cur_level) || '0';
// data.isStudent = (user.data && user.data.vip_info && user.data.vip_info.is_student) ? true : false;
// params.is_student = data.isStudent ? 1 : 0;
// params.current_vip_level = data.vipLevel;
return api.get('', params, {
code: 200,
cache: true
}).then(result => {
if (result.code === 500 || !result.data) {
return {};
dest.preferenceUrl = `/product/detail/preference${extra}`;
}
result = result.data;
result.goods_id = data.goodsId;
return Promise.all([
_getShopsInfo(_.get(result, 'brand_info.brand_id', 0)),
// _getPromotionInfo(result.product_skn),
comment.getCommentInfo({
productId: result.product_id
}),
_getCommonConsult(),
comment.getConsults(result.product_id, 1, 2)
]).then((info) => {
// result.promotionBoList = info[1];
// finalResult = _detailDataPkg(result, data.uid, data.vipLevel, data.ua);
finalResult = _detailDataPkg(result, data.ua);
finalResult.enterStore = info[0];
finalResult.isStudent = data.isStudent;
Object.assign(finalResult.feedbacks, info[1]);
/* 如果有咨询,显示咨询,否则显示常见问题 */
if (info[3].total) {
finalResult.feedbacks.consultsNum = parseInt(info[3].total, 10);
Object.assign(finalResult.feedbacks, {
commonConsults: false,
consultsNum: parseInt(info[3].total, 10),
consults: _.take(info[3].list, 2)
});
} else if (!_.isEmpty(info[2]) && !_.get(info[1], 'feedbacks.consultsNum', 0)) {
Object.assign(finalResult.feedbacks, {
commonConsults: true,
consultsNum: true,
consults: _.take(info[2], 2)
});
}
return finalResult;
});
});
// });
};
/**
* [商品数据格式化] pagecache重构
*/
// const _detailDataPkg = (origin, uid, vipLevel, ua) => {
const _detailDataPkg = (origin, ua) => {
let dest = {}, // 结果输出
thumbImageList = [],
colorGroup = {},
sizeGroup = [],
totalStorageNum = 0;
// 商品名称
if (!origin.product_name) {
dest.feedbacks = {};
return dest;
}
dest.goodsName = origin.product_name;
// 是否是虚拟商品
dest.virtualGoods = (origin.attribute * 1 === 3);
// 用户未登录时 pagecache重构
// if (!uid) {
// dest.loginUrl = helpers.urlFormat('/signin.html', {
// refer: helpers.urlFormat('/product/' + origin.product_skn + '.html')
// });
// }
// 商品促销短语
origin.sales_phrase && (dest.goodsSubtitle = origin.sales_phrase);
// 促销信息 TODO: 换新接口 pagecache重构
// if (origin.promotionBoList) {
// let discountList = [];
// _.forEach(origin.promotionBoList, function(value) {
// discountList.push({
// text: `【${value.promotionType}】${value.promotionTitle}`
// });
// });
// discountList.length && (dest.goodsDiscount = {
// list: discountList
// });
// }
// 商品标签
if (origin.tags) {
let productTags = {};
_.forEach(origin.tags, function(value) {
productTags[value] = true;
});
// dest.brandId = origin.brand_info && origin.brand_info.brand_id || 0;
dest.brandId = _.get(origin, 'brand_info.brand_id', 0);
dest.productSkn = origin.product_skn;
dest.id = origin.product_id;
dest.tags = productTags;
}
dest.goodsId = origin.goods_id;
dest.isDepositAdvance = origin.is_deposit_advance === 'Y'; // 是否定金预售
dest.isSeckill = origin.is_secKill === 'Y'; // 是否秒杀
dest.isLimitBuy = origin.isLimitBuy; // 是否 限购
dest.isPresale = Boolean(origin.expect_arrival_time); // 是否普通预售
dest.bundleType = origin.bundle_type; // 商品活动标记
// 自定义 属性
dest.showCoupon = !(
dest.isDepositAdvance || dest.isSeckill || dest.isLimitBuy || dest.isPresale
); // 商品有限购、秒杀、定金预售、普通预售 不显示领
// 20170113 要求关闭商品详情页面领券功能
// dest.showCoupon = false;
// 商品信息
if (origin.goods_list.length) {
let goodsGroup = [];
// pagecache重构
_.forEach(origin.goods_list, function(value) {
// 商品分组
if (value.images_list) {
_.forEach(value.images_list, function(good) {
goodsGroup.push({
goodsId: value.goods_id,
img: good.image_url
});
});
}
});
// 商品价格 pagecache重构
// let goodsPrice = {
// currentPrice: origin.format_sales_price === '0' ? origin.format_market_price : origin.format_sales_price
// };
// if (origin.format_sales_price !== '0' && origin.format_market_price !== origin.format_sales_price) {
// goodsPrice.previousPrice = origin.format_market_price;
// }
// dest.goodsPrice = goodsPrice;
// 商品返回 YOHO 币 pagecache重构
// origin.yohoCoinNum && (dest.commodityReturn = origin.yohoCoinNum);
// VIP 商品价格 pagecache重构
// if (origin.vip) {
// let vipList = [];
// let levelList = {
// 银卡: 1,
// 金卡: 2,
// 白金: 3
// };
// _.forEach(origin.vip, function(value) {
// vipList.push({
// level: levelList[value.caption],
// text: value.price,
// currentLevel: (value.vipLevel === vipLevel)
// });
// });
// vipList.length && (dest.vipLevel = {
// list: vipList
// });
// }
// 上市期
origin.expectArrivalTime && (dest.periodOfMarket = `${origin.expectArrivalTime}月`);
// 商品咨询
dest.feedbacks = {
consults: [],
consultsNum: 0
};
let consultParams = {
product_id: origin.product_id
};
if (_.has(dest, 'feedbacks.consultsNum')) {
consultParams.total = dest.feedbacks.consultsNum;
dest.feedbacks.consultsUrl = helpers.urlFormat('/product/detail/consults', consultParams);
} else {
dest.feedbacks.consultsUrl = helpers.urlFormat('/product/detail/consultform', consultParams);
}
// 商品评价
dest.feedbacks.commentsUrl = helpers.urlFormat('/product/detail/comments', {
product_id: origin.product_id
});
// 商品图:多个
if (goodsGroup.length > 1) {
let bannerList = [];
// 品牌信息
if (origin.brand) {
let extra = `?productSkn=${origin.product_skn}&brandId=${origin.brand_info.brand_id}`;
_.forEach(goodsGroup, function(value) {
value.img = _.replace(value.img, '/quality/80', '/quality/70');
dest.preferenceUrl = `/product/detail/preference${extra}`;
dest.brandId = origin.brand_info.brand_id;
}
bannerList.push({
img: value.img
});
});
dest.productSkn = origin.product_skn;
// 商品信息
if (origin.goods_list.length) {
let goodsGroup = [];
// pagecache重构
// sizeName = '',
// colorList = [],
// sizeList = {},
// allSizeList = {},
// colorStorageGroup = {},
// colorStorageNum = 0;
// pagecache重构
_.forEach(origin.goods_list, function(value) {
if (value.status === 0) {
return;
dest.bannerTop = {
list: bannerList
};
} else if (goodsGroup[0]) {
dest.bannerTop = {
img: goodsGroup[0].img
};
}
}
// colorStorageNum = 0;
// 底部简介URL链接
dest.introUrl = '/product/detail/intro/' + origin.product_skn;
// 商品分组
if (value.images_list) {
_.forEach(value.images_list, function(good) {
goodsGroup.push({
goodsId: value.goods_id,
img: good.image_url
});
return dest;
},
/**
* 处理品牌关联店铺信息
* @param {array}
* @return {array}
*/
processShopsInfo(data) {
let enterStore = [];
_.forEach(data, function(value) {
let shopInfo = {
img: value.brand_ico,
storeName: value.brand_name
};
if (value.shop_id) {
shopInfo.url = helpers.urlFormat('/product/index/brand', {
shop_id: value.shop_id
});
} else {
shopInfo.url = helpers.urlFormat('', null, value.brand_domain);
}
// // 商品的尺码列表
// colorStorageGroup[value.product_skc] = {};
// if (value.size_list) {
// sizeList[value.product_skc] = [];
// _.forEach(value.size_list, function(size) {
// sizeList[value.product_skc].push({
// id: size.size_id,
// skuId: size.product_sku,
// goodsId: value.goods_id,
// colorId: value.color_id,
// name: size.size_name,
// sizeNum: size.storage_number
// });
// sizeName = size.size_name;
// // 所有尺码列表,赋值用于前端展示默认尺码的时候
// // 判断出没有库存则显示灰色
// let build = {
// id: size.size_id,
// storage: size.storage_number
// };
// allSizeList[sizeName] = (allSizeList[sizeName] === null ||
// typeof allSizeList[sizeName] === 'undefined') ? build : allSizeList[sizeName];
// colorStorageNum += parseInt(size.storage_number, 10);
// colorStorageGroup[value.product_skc][sizeName] = parseInt(size.storage_number, 10);
// });
// // 颜色分组
// colorList.push({
// id: value.color_id,
// skcId: value.product_skc,
// name: value.color_name,
// colorNum: colorStorageNum
// });
// }
// // 缩略图
// thumbImageList.push({
// img: value.color_image
// });
// // 商品库存总数
// totalStorageNum += _.toNumber(colorStorageNum);
// });
// // 遍历所有尺码,构建颜色显示数据
// let i = 1;
// sizeGroup[0] = {
// size: []
// };
// _.forEach(allSizeList, (value, key) => {
// // 默认尺码
// sizeGroup[0].size.push({
// name: key,
// sizeNum: _.toNumber(value.storage) > 0 ? true : false,
// id: value.id
// });
// colorGroup[i] = {
// color: []
// };
// // 各个颜色的尺码, 每行显示一个尺码对应的颜色
// _.forEach(colorList, (colorArr) => {
// let tempColorArr = _.cloneDeep(colorArr);
// if (colorStorageGroup[tempColorArr.skcId] &&
// colorStorageGroup[tempColorArr.skcId][key]) {
// tempColorArr.colorNum = colorStorageGroup[tempColorArr.skcId][key];
// } else {
// tempColorArr.colorNum = 0;
// }
// colorGroup[i].color.push(Object.assign({}, tempColorArr));
// });
// colorGroup[i].id = value.id;
// ++i;
// });
// colorGroup[0] = {
// color: []
// };
// // 遍历所有颜色, 构建尺码显示数据
// i = 1;
// _.forEach(colorList, function(value) {
// // 各个尺码的颜色, 每行显示一个颜色的对应尺码
// sizeGroup[i] = {
// size: sizeList[value.skcId],
// colorId: value.skcId
// };
// // 默认颜色
// colorGroup[0].color.push(value);
// ++i;
enterStore.push(shopInfo);
});
return enterStore;
},
/**
* 处理商品 feedback
* @param data feedback要处理数据
* {
* comment, defaultConsult, userConsult
* }
* @param productId 商品id
* @return feedback
*/
processFeedback(data, productId) {
// let {comment, defaultConsult, userConsult} = data;
let comment = data.comment;
let defaultConsult = data.defaultConsult;
let userConsult = data.userConsult;
let feedbacks = {consults: [], consultsNum: 0};
Object.assign(feedbacks, comment);
// 商品评价
feedbacks.commentsUrl = helpers.urlFormat('/product/detail/comments', {
product_id: productId
});
/* 如果有用户咨询,显示用户咨询,否则显示常见问题 */
let obj = {};
// 商品图:多个
if (goodsGroup.length > 1) {
let bannerList = [];
_.forEach(goodsGroup, function(value) {
bannerList.push({
img: value.img
});
});
dest.bannerTop = {
list: bannerList
if (userConsult.total) {
obj = {
commonConsults: false,
consultsNum: parseInt(userConsult.total, 10),
consults: _.take(userConsult.list, 2)
};
} else if (goodsGroup[0]) {
dest.bannerTop = {
img: goodsGroup[0].img
} else if (!_.isEmpty(defaultConsult) && !_.get(comment, 'consultsNum', 0)) {
obj = {
commonConsults: true,
consultsNum: true,
consults: _.take(defaultConsult.faq, 2)
};
}
}
// 悬浮的购物车信息
dest.cartInfo = {
cartUrl: helpers.urlFormat('/cart/index/index'),
numInCart: 0,
goodsInstore: origin.storage_sum
};
// pagecache重构
// let soldOut = (origin.storage_sum === 0) || (totalStorageNum === 0); // status
// let notForSale = origin.attribute === 2;
// 显示加入购物车链接 pagecache重构
// if (!soldOut && !notForSale) {
// _.orderBy(colorGroup);
// Object.assign(dest.cartInfo, {
// productId: origin.product_id,
// thumbs: thumbImageList,
// name: dest.goodsName ? dest.goodsName : '',
// price: dest.goodsPrice.previousPrice ? dest.goodsPrice.previousPrice : '',
// salePrice: dest.goodsPrice.currentPrice ? dest.goodsPrice.currentPrice : '',
// totalNum: totalStorageNum,
// colors: _.toArray(colorGroup),
// sizes: sizeGroup
// });
// // 限购商品
// if (origin.isLimitBuy) {
// // 是否开售
// let isBeginSale = (origin.saleStatus === 1);
// // 限购商品有关的展示状态
// let showStatus = 1;
// origin.showStatus && (showStatus = parseInt(origin.showStatus, 10));
// // 处理限购商品有关的按钮状态
// dest = _procShowStatus(dest, showStatus, isBeginSale);
// dest.cartInfo.limitProductCode = origin.limitProductCode;
// dest.cartInfo.limitCodeUrl = _getLimitCodeUrl(origin.limitProductCode, origin.product_skn, ua);
// dest.cartInfo.limitProductPay = helpers.urlFormat('/cart/index/orderEnsure');
// } else {
// dest.cartInfo.addToCartUrl = helpers.urlFormat('/product/buy_' + origin.product_id + '_' +
// origin.goods_list.goods_id + '.html');
// }
// } else if (notForSale) {
// dest.cartInfo.notForSale = true;
// } else if (soldOut) {
// dest.cartInfo.soldOut = true;
// }
// // 是否收藏
// dest.isCollect = false;
// if (origin.is_collect === 'Y') {
// dest.isCollect = true;
// dest.cartInfo.isCollect = true;
// }
// 底部简介URL链接
dest.introUrl = '/product/detail/intro/' + origin.product_skn;
dest.id = origin.product_id;
dest.goodsId = origin.goods_id;
return dest;
};
/**
* [商品信息的异步数据获取]
*/
let getProductAsyncData = (data) => {
let finalResult;
let params = {
method: 'app.product.seckill.data'
};
if (data.id) { // 通过 productId 获取商品详情
Object.assign(params, {
product_id: _.toString(data.id)
});
} else if (data.productSkn) { // 通过 productSkn 获取商品详情
Object.assign(params, {
product_skn: _.toString(data.productSkn)
});
}
if (data.uid) {
params.uid = data.uid;
}
params.is_student = data.isStudent ? 1 : 0;
params.current_vip_level = data.vipLevel;
Object.assign(feedbacks, obj);
return api.get('', params, {
code: 200,
cache: true
}).then(result => {
if (result.code === 500 || !result.data) {
return {};
if (_.get(feedbacks, 'consultsNum')) {
feedbacks.consultsUrl = helpers.urlFormat('/product/detail/consults', {
product_id: productId,
total: feedbacks.consultsNum
});
} else {
feedbacks.consultsUrl = helpers.urlFormat('/product/detail/consultform', {
product_id: productId
});
}
result = result.data;
result.goods_id = data.goodsId;
return Promise.all([_getPromotionInfo(result.product_skn), _getFavorite(result.product_id, data.uid)]).then((res) => {
result.promotionBoList = res[0];
var isFavorite = res[1];
finalResult = _detailDataPkgAsync(result, data.uid, data.vipLevel, data.ua);
finalResult.isCollect = isFavorite;
if (finalResult.cartInfo) {
finalResult.cartInfo.isCollect = isFavorite;
}
finalResult.isStudent = data.isStudent;
return finalResult;
});
});
};
/**
* [商品信息格式化异步接口]
*/
let _detailDataPkgAsync = (origin, uid, vipLevel, ua) => {
let dest = {}, // 结果输出
thumbImageList = [],
colorGroup = {},
sizeGroup = [],
totalStorageNum = 0;
// 用户未登录时
if (!uid) {
dest.loginUrl = helpers.urlFormat('/signin.html', {
refer: helpers.urlFormat('/product/' + origin.product_skn + '.html') // 商品url改版
});
}
// 商品名称
if (!origin.product_name) {
dest.feedbacks = {};
return dest;
}
dest.goodsName = origin.product_name;
// 商品促销短语
origin.sales_phrase && (dest.goodsSubtitle = origin.sales_phrase);
return feedbacks;
},
/**
* 套餐数据处理
* @param bundleData
* @param skn
* @returns {{}}
*/
processBundle(bundleData, skn, gid) {
let subPrice = _.get(bundleData, 'bundleInfo.subPrice', 0);
return {
title: '优惠套装',
href: helpers.urlFormat('/product/bundle/detail', {skn: skn, gid: gid}),
description: subPrice ? '立省¥' + subPrice : 0,
productList: productProcess.processProductList(bundleData && bundleData.productList)
};
},
/**
* 处理量贩数据
* @param finalResult
* @param bundleData
*/
processDiscount(finalResult, bundleData) {
finalResult.discountBuy = {
num: _.get(bundleData, 'bundleInfo.bundleCount', 1),
promotionPhrase: _.get(bundleData, 'bundleInfo.promotionPhrase', ''),
discount: _.get(bundleData, 'bundleInfo.discount', 1)
};
// 促销信息 TODO: 换新接口
if (origin.promotionBoList) {
let discountList = [];
let oldPromotion = finalResult.promotion;
_.forEach(origin.promotionBoList, function(value) {
discountList.push({
text: `【${value.promotionType}${value.promotionTitle}`
});
});
finalResult.promotion = [{
promotionTitle: _.get(bundleData, 'bundleInfo.promotionPhrase', ''),
promotionType: '量贩'
}];
discountList.length && (dest.goodsDiscount = {
list: discountList
_.forEach(oldPromotion, value => {
finalResult.promotion.push(value);
});
}
};
// 商品价格
let goodsPrice = {
currentPrice: origin.format_sales_price === '0' ? origin.format_market_price : origin.format_sales_price
};
if (origin.format_sales_price !== '0' && origin.format_market_price !== origin.format_sales_price) {
goodsPrice.previousPrice = origin.format_market_price;
}
dest.goodsPrice = goodsPrice;
// 商品返回 YOHO 币
origin.yohoCoinNum && (dest.commodityReturn = origin.yohoCoinNum);
// VIP 商品价格
if (origin.vip) {
let vipList = [];
let levelList = {
银卡: 1,
金卡: 2,
白金: 3
const newDetail = {
getProductData(data) {
let params = {
method: 'app.product.data'
};
_.forEach(origin.vip, function(value) {
vipList.push({
level: levelList[value.caption],
text: value.price,
currentLevel: (levelList[value.caption] === parseInt(vipLevel, 10))
if (data.id) { // 通过 productId 获取商品详情
Object.assign(params, {
product_id: data.id
});
});
vipList.length && (dest.vipLevel = {
list: vipList
});
}
} else if (data.productSkn) { // 通过 productSkn 获取商品详情
Object.assign(params, {
product_skn: data.productSkn
});
}
// 商品信息
if (origin.goods_list.length) {
let goodsGroup = [],
sizeName = '',
colorList = [],
sizeList = {},
allSizeList = {},
colorStorageGroup = {},
colorStorageNum = 0;
_.forEach(origin.goods_list, function(value) {
if (value.status === 0) {
return;
return api.get('', params, {
code: 200,
cache: true
}).then(result => {
if (!result || result.code === 500 || !result.data) {
return {};
}
colorStorageNum = 0;
// 商品分组
if (value.images_list) {
_.forEach(value.images_list, function(good) {
goodsGroup.push({
goodsId: value.goods_id,
img: good.image_url
});
});
}
result.data.goods_id = data.goodsId;
// 商品的尺码列表
colorStorageGroup[value.product_skc] = {};
if (value.size_list) {
sizeList[value.product_skc] = [];
_.forEach(value.size_list, function(size) {
sizeList[value.product_skc].push({
id: size.size_id,
skuId: size.product_sku,
goodsId: value.goods_id,
colorId: value.color_id,
name: size.size_name,
sizeNum: size.storage_number
});
return tool.prodessDetailData(result.data);
});
},
/*
获取 促销,评论,咨询,品牌信息
*/
querySknData(params) {
let brandId = params.brandId;
let productId = params.productId;
let skn = params.skn;
let gid = params.gid;
let apiArray = [
this.queryShopsByBrandId(brandId), // 0 品牌信息
commentModel.getCommentInfo({
productId: productId
}), // 1 评论信息
commentModel.getCommonConsult(), // 2 默认咨询信息
commentModel.getConsults(productId, 1, 2), // 3 咨询列表
this.queryPromotion(skn), // 4 促销活动
];
if (params.bundleType) {
apiArray.push(bundle.getBundleBySkn(skn));
}
sizeName = size.size_name;
return Promise.all(apiArray).then(info => {
let finalResult = {
promotion: null,
enterStore: null,
feedbacks: {
consults: [],
consultsNum: 0
},
};
// 所有尺码列表,赋值用于前端展示默认尺码的时候
// 判断出没有库存则显示灰色
let build = {
id: size.size_id,
storage: size.storage_number
};
finalResult.promotion = info[4];
finalResult.enterStore = info[0];
finalResult.feedbacks = tool.processFeedback({
comment: info[1],
defaultConsult: info[2],
userConsult: info[3]
}, productId);
allSizeList[sizeName] = (allSizeList[sizeName] === null ||
typeof allSizeList[sizeName] === 'undefined') ? build : allSizeList[sizeName];
colorStorageNum += parseInt(size.storage_number, 10);
colorStorageGroup[value.product_skc][sizeName] = parseInt(size.storage_number, 10);
});
let bundleData = _.get(info[5], 'data', null);
// 颜色分组
colorList.push({
id: value.color_id,
skcId: value.product_skc,
name: value.factory_goods_name || value.color_name,
colorNum: colorStorageNum
});
/* 套装 */
if (bundleData && _.get(bundleData, 'bundleInfo.discountType', null) === 1) {
finalResult.bundleData = tool.processBundle(bundleData, skn, gid);
}
// 缩略图
thumbImageList.push({
img: helpers.image(value.color_image, 60, 60)
});
/* 量贩 */
if (bundleData && _.get(bundleData, 'bundleInfo.discountType', null) === 2) {
tool.processDiscount(finalResult, bundleData);
}
// 商品库存总数
totalStorageNum += _.toNumber(colorStorageNum);
return finalResult;
});
},
// 遍历所有尺码,构建颜色显示数据
let i = 1;
// ------------------------------接口
sizeGroup[0] = {
size: []
/*
接口: 根据BrandID, 查询品牌信息
*/
queryShopsByBrandId(brandId) {
let params = {
method: 'app.shop.queryShopsByBrandId',
brand_id: brandId
};
_.forEach(allSizeList, (value, key) => {
// 默认尺码
sizeGroup[0].size.push({
name: key,
sizeNum: _.toNumber(value.storage) > 0 ? true : false,
id: value.id
});
colorGroup[i] = {
color: []
};
// 各个颜色的尺码, 每行显示一个尺码对应的颜色
_.forEach(colorList, (colorArr) => {
let tempColorArr = _.cloneDeep(colorArr);
let cacheConf = {
cache: true
};
if (colorStorageGroup[tempColorArr.skcId] &&
colorStorageGroup[tempColorArr.skcId][key]) {
tempColorArr.colorNum = colorStorageGroup[tempColorArr.skcId][key];
} else {
tempColorArr.colorNum = 0;
return api.get('', params, cacheConf)
.then(result => {
if (result && result.code === 200) {
return tool.processShopsInfo(result.data);
}
colorGroup[i].color.push(Object.assign({}, tempColorArr));
});
colorGroup[i].id = value.id;
++i;
});
colorGroup[0] = {
color: []
return [];
}, () => []);
},
/**
* 接口: 商品 促销活动
*/
queryPromotion(skn) {
let params = {
method: 'app.product.promotion',
product_skn: skn
};
// 遍历所有颜色, 构建尺码显示数据
i = 1;
_.forEach(colorList, function(value) {
// 各个尺码的颜色, 每行显示一个颜色的对应尺码
sizeGroup[i] = {
size: sizeList[value.skcId],
colorId: value.skcId
};
// 默认颜色
colorGroup[0].color.push(value);
++i;
});
}
let soldOut = (origin.storage_sum === 0) || (totalStorageNum === 0); // status
let notForSale = origin.attribute === 2;
// 悬浮的购物车信息
dest.cartInfo = {
cartUrl: helpers.urlFormat('/cart/index/index'),
numInCart: 0,
goodsInstore: origin.storage_sum
};
// 显示加入购物车链接
if (!soldOut && !notForSale) {
_.orderBy(colorGroup);
Object.assign(dest.cartInfo, {
productId: origin.product_id,
thumbs: thumbImageList,
name: dest.goodsName || '',
price: dest.goodsPrice.previousPrice ? dest.goodsPrice.previousPrice : '',
salePrice: dest.goodsPrice.currentPrice ? dest.goodsPrice.currentPrice : '',
totalNum: totalStorageNum,
colors: _.toArray(colorGroup),
sizes: sizeGroup
});
let cacheConf = {
cache: true
};
// 限购商品
if (origin.isLimitBuy) {
return api.get('', {
method: 'app.limitProduct.productStatus',
limitProductCode: origin.limitProductCode,
uid: uid,
product_skn: origin.product_skn
}, {
code: 200,
cache: true
}).then((result) => {
if (result.data) {
if (!result.data.isLimitBuy) {
dest.cartInfo.soldOut = true;
return callback();
}
// 是否开售
let isBeginSale = (result.data.saleStatus === 1);
// 限购商品有关的展示状态
let showStatus = 1;
origin.showStatus && (showStatus = parseInt(result.data.showStatus, 10));
// 处理限购商品有关的按钮状态
dest = _procShowStatus(dest, showStatus, isBeginSale);
dest.cartInfo.limitProductCode = origin.limitProductCode;
dest.cartInfo.limitCodeUrl = _getLimitCodeUrl(origin.limitProductCode, origin.product_skn, ua);
dest.cartInfo.limitProductPay = helpers.urlFormat('/cart/index/orderEnsure');
return callback();
} else {
dest.cartInfo.soldOut = true;
return callback();
return api.get('', params, cacheConf)
.then(result => {
if (result && result.code === 200) {
return result.data;
}
return {};
});
} else {
dest.cartInfo.addToCartUrl = helpers.urlFormat('/product/buy_' + origin.product_id + '_' +
origin.goods_id + '.html');
return callback();
}
} else if (notForSale) {
dest.cartInfo.notForSale = true;
return callback();
} else if (soldOut) {
dest.cartInfo.soldOut = true;
return callback();
}
// 是否收藏 使用单独收藏接口获取
// dest.isCollect = false;
// if (origin.is_collect === 'Y') {
// dest.isCollect = true;
// dest.cartInfo.isCollect = true;
// }
function callback() {
// 虚拟商品(门票)
if (origin.attribute * 1 === 3) {
dest.tickets = true;
dest.ticketsConfirm = helpers.urlFormat('/cart/index/ticketsConfirm');
// 展览票
if (origin.product_skn * 1 === SINGLE_TICKETS_SKN) {
dest.single = true;
} else {
// 套票
dest.package = true;
}
// 购票限制
dest.cartInfo.limit = 4;
// 清空活动
dest.goodsDiscount = [];
// 来自登录页,自动弹出选择框
// if (isset($_GET['product_type']) && $_GET['product_type'] == 'ticket') {
// $result['showPannel'] = true;
// }
}
dest.id = origin.product_id;
dest.goodsId = origin.goods_id;
return Promise.resolve(dest);
}
return api.get('', {
method: 'app.shop.seckill.queryShopsByBrandId',
brand_id: _.toString(brandId)
}, {
cache: true
}).then(shops => {
if (shops && shops.code === 200) {
return _processShopsInfo(shops.data);
}
return [];
});
};
/**
* 获取默认咨询列表
*/
const _getCommonConsult = () => {
let params = {
method: 'app.consult.seckill.common'
};
return api.get('', params, {
code: 200
}).then(result => {
let data = {};
if (result.data) {
data = result.data;
}
},
/**
* 获取秒杀列表
*/
getSeckillData(param) {
let params = {
method: 'app.seckill.data',
product_skn: param.productskn
};
return data;
});
};
return api.get('', params, {
code: 200
})
/**
* [根据商品SKN获取商品的简要信息]
* @param {[array]} skns [skns]
* @return {[type]}
*/
let _productInfoBySkns = (skns) => {
// 调用搜索接口
let param = {
method: 'app.search.li',
query: skns.join(' '),
limit: skns.length,
order: 's_t_desc'
};
return api.get('', param, {
cache: true
});
};
// mock
.catch()
.then(result => {
let data = {};
/**
* 获取秒杀列表
*/
const getSeckillData = (param) => {
let params = {
method: 'app.seckill.data',
product_skn: param.productskn
};
return api.get('', params, {
code: 200
})
// mock
.catch()
.then(result => {
let data = {};
if (result.data) {
data = result.data;
if (data.storageSum > 0) {
data.storageSum = 1;
}
if (data.secKillSku) {
_.forEach(data.secKillSku, item => {
if (item.storageNum > 0) {
item.storageNum = 1;
}
});
if (result.data) {
data = result.data;
if (data.storageSum > 0) {
data.storageSum = 1;
}
if (data.secKillSku) {
_.forEach(data.secKillSku, item => {
if (item.storageNum > 0) {
item.storageNum = 1;
}
});
}
} else {
data.status = 0;
}
} else {
data.status = 0;
}
return data;
});
return data;
});
}
};
module.exports = {
getSeckillData,
getProductData,
getProductAsyncData,
getUserProfile: _getUserProfile,
productInfoBySkns: _productInfoBySkns
};
module.exports = newDetail;
... ...
... ... @@ -58,7 +58,7 @@ const bundle = require(`${cRoot}/bundle`);
// /pro_136349_455445/HEARTSOFARMianMaShuJiaoXiuXianKuPS1684.html
// 因为正则匹配原因,秒杀详情页路由要放在普通详情页前面,待解决
router.get(/^\/seckill\/show_([\d]+)/, seckillDetail.indexSkn); // 秒杀商品详情页 SKN 进入
router.get(/^\/seckill\/show_([\d]+)/, seckillDetail.index); // 秒杀商品详情页 SKN 进入
router.get(/^\/seckill\/pro_([\d]+)_([\d]+)/, seckillDetail.index); // 秒杀商品详情页进入
router.get(/^\/pro_([\d]+)_([\d]+)/, newDetail.indexRedirect); // 商品详情页
// /show_51047967.html
... ... @@ -130,7 +130,7 @@ router.get('/seckill/get-product-list', seckill.getProductList); // 秒杀列表
router.get('/search/index', search.index);
// 搜索落地页
router.get('/search/list', search.list);
router.get('/search/list', rewrite.sortParams, search.list);
// filter
router.get('/search/filter', search.filter);
... ... @@ -142,8 +142,8 @@ router.get('/search/fuzzyDatas', search.fuzzyDatas);
router.get('/search/search', search.search);
// 品类
router.get('/index/index', list.category);
router.get('/list/index', list.category); // 兼容 PC 的链接
router.get('/index/index', rewrite.sortParams, list.category);
router.get('/list/index', rewrite.sortParams, list.category); // 兼容 PC 的链接
// 品牌 | 店铺
router.get('/index/shopAppCookie', list.shopAppCookie);
... ...
<div class="yoho-page bundle-body">
<div class="bundle-tabs{{#if any}} any{{/if}}">
<div class="swiper-wrapper">
{{# bundleDatas}}
<div class="swiper-slide{{#if selected}} selected{{/if}}" data-index="{{@index}}" data-href="{{href}}">
<div class="line"></div>
<div class="title">
<span>{{title}}</span>
</div>
</div>
{{/ bundleDatas}}
</div>
</div>
{{# productList}}
<div class="bundle-detail-goods">
<div class="goods-img"><a href="{{url}}"><img src="{{image default_images 155 206}}" alt=""></a></div>
... ... @@ -16,17 +28,29 @@
<div class="chose-panel"></div>
{{# bundleInfo}}
<div class="bundle-bar clearfix">
<div class="bundle-bar-md">
<div class="bundle-price">
{{#if subPrice}}
<span class="bundle-discount">立省¥{{subPrice}}</span>
{{/if}}
<span>套餐价: {{discountPriceStr}}</span>
{{#if @root.isApp}}
<div class="no-buy">抱歉,套装商品仅支持在最新版app购买,请升级!</div>
{{^}}
<div class="bundle-bar-md">
<div class="bundle-price">
{{#if subPrice}}
<span class="bundle-discount">立省¥{{subPrice}}</span>
{{/if}}
<span>套餐价: {{discountPriceStr}}</span>
</div>
<div class="sale-price">销售价: {{salesPriceStr}}</div>
</div>
<div class="sale-price">销售价: {{salesPriceStr}}</div>
</div>
<button id="bundle-buy-now" class="bundle-buy-btn">立即购买</button>
<button id="bundle-buy-now" class="bundle-buy-btn">立即购买</button>
{{/if}}
</div>
<input type="hidden" id="activityId" value="{{bundleId}}">
{{/ bundleInfo}}
{{#shareInfo}}
<input type="hidden" id="shareImgUrl" value="{{imgUrl}}">
<input type="hidden" id="shareSubTitle" value="{{subTitle}}">
<input type="hidden" id="shareTitle" value="{{title}}">
<input type="hidden" id="shareUrl" value="{{url}}">
{{/shareInfo}}
</div>
\ No newline at end of file
... ...
... ... @@ -52,44 +52,14 @@
<!-- 优惠卷 -->
<div class="coupon-group"></div>
<!-- /品牌页面 -->
<ul id="list-nav" class="list-nav clearfix">
<li class="default active buriedpoint first-li-more" data-bp-id="shop_listnav_default_1">
<a href="javascript:void(0);">
<span class="nav-txt">默认</span>
<span class="iconfont up cur hide">&#xe615;</span>
<span class="iconfont down cur">&#xe616;</span>
</a>
</li>
<li class="price buriedpoint" data-bp-id="shop_listnav_price_1">
<a href="javascript:void(0);">
<span class="nav-txt">价格</span>
<span class="icon">
<i class="iconfont up cur">&#xe615;</i>
<i class="iconfont down">&#xe616;</i>
</span>
</a>
</li>
<li class="discount buriedpoint" data-bp-id="shop_listnav_discount_1">
<a href="javascript:void(0);">
<span class="nav-txt">折扣</span>
<span class="icon">
<i class="iconfont up cur">&#xe615;</i>
<i class="iconfont down">&#xe616;</i>
</span>
</a>
</li>
<li class="filter buriedpoint" data-bp-id="shop_listnav_filter_1">
<a href="javascript:void(0);">
<span class="nav-txt">筛选</span>
<span class="iconfont cur">&#xe613;</span>
</a>
</li>
</ul>
<!--搜索默认排序列表-->
{{> product/search-default-sort-list}}
{{!--筛选tab--}}
{{> product/filter-tab}}
<div id="goods-container" class="goods-container">
{{!--搜索推荐词模板--}}
{{> search/search-word-content}}
<div class="default-goods container clearfix">
{{#newGoods}}
{{> common/goods}}
... ... @@ -102,6 +72,14 @@
{{> common/filter}}
</div>
{{> common/query-param}} {{> common/suspend-cart}} {{/ goodList}}
{{!--搜索列表显示过少,显示猜您喜欢--}}
{{#if @root.suggestion.isMaybeLike}}
<div class="maybe-like-search">您可能喜欢的</div>
<div id="goods-list" class="maybe-like-goods"></div>
{{/if}}
{{> common/query-param}}
{{> common/suspend-cart}}
{{/ goodList}}
<input type="text" class="domain" style="display:none" value={{domain}}>
</div>
... ...
<div class="good-list-page yoho-page">
{{# goodList}}
{{# goodList}}
<!-- 基础店铺页面 -->
{{# baseShopHome}}
<div id="brand-header" class="brand-header" data-id={{id}} data-isbaseshop="{{isBaseShop}}">
... ... @@ -27,45 +27,14 @@
</div>
<input type="hidden" name="app_version" value="{{appVersion}}">
{{/ baseShopHome}}
<!-- 优惠卷 -->
<div class="coupon-group"></div>
<!-- /基础店铺页面 -->
<ul id="list-nav" class="list-nav clearfix">
<li class="default active buriedpoint first-li-more" data-bp-id="shop_listnav_default_1">
<a href="javascript:void(0);">
<span class="nav-txt">默认</span>
<span class="iconfont up cur hide">&#xe615;</span>
<span class="iconfont down cur">&#xe616;</span>
</a>
</li>
<li class="price buriedpoint" data-bp-id="shop_listnav_price_1">
<a href="javascript:void(0);">
<span class="nav-txt">价格</span>
<span class="icon">
<i class="iconfont up cur">&#xe615;</i>
<i class="iconfont down">&#xe616;</i>
</span>
</a>
</li>
<li class="discount buriedpoint" data-bp-id="shop_listnav_discount_1">
<a href="javascript:void(0);">
<span class="nav-txt">折扣</span>
<span class="icon">
<i class="iconfont up cur">&#xe615;</i>
<i class="iconfont down">&#xe616;</i>
</span>
</a>
</li>
<li class="filter buriedpoint" data-bp-id="shop_listnav_filter_1">
<a href="javascript:void(0);">
<span class="nav-txt">筛选</span>
<span class="iconfont cur">&#xe613;</span>
</a>
</li>
</ul>
<!--搜索默认排序列表-->
{{> product/search-default-sort-list}}
{{!--筛选tab--}}
{{> product/filter-tab}}
<div id="goods-container" class="goods-container">
<div class="default-goods container clearfix">
... ... @@ -79,6 +48,8 @@
{{> common/filter}}
</div>
{{> common/query-param}} {{> common/suspend-cart}} {{/ goodList}}
<input type="text" class="shopId" style="display:none" value={{shopId}}>
{{> common/query-param}}
{{> common/suspend-cart}}
{{/ goodList}}
<input type="text" class="shopId" style="display:none" value={{shopId}}>
</div>
... ...
... ... @@ -119,11 +119,14 @@
<div class="discount-area first" id="navlist2">
<ul id="list-nav" class="home-sub-nav list-nav pos-list clearfix">
<li class="default active buriedpoint first-li-more" data-bp-id="shop_listnav_default_1">
<li class="default active buriedpoint" data-bp-id="shop_listnav_default_1">
<a href="javascript:void(0);">
<span class="nav-txt">默认</span>
<span class="iconfont up cur hide">&#xe615;</span>
<span class="iconfont down cur">&#xe616;</span>
</a>
</li>
<li class="new buriedpoint" data-bp-id="shop_listnav_new_1">
<a href="javascript:void(0);">
<span class="nav-txt">最新</span>
</a>
</li>
<li class="price buriedpoint" data-bp-id="shop_listnav_price_1">
... ... @@ -151,12 +154,6 @@
</a>
</li>
</ul>
<div class='new-list classics hide'>
<ul>
<li class='active default' data-bp-id='shop_listnav_default_1'>默认</li>
<li class='new' data-bp-id='shop_listnav_new_1'>最新</li>
</ul>
</div>
</div>
<div class="discount-area first">
... ... @@ -189,11 +186,14 @@
</ul>
<ul id="pos-list" class="home-sub-nav pos-list hide">
<li class="default active buriedpoint first-li-more" data-bp-id="shop_listnav_default_1">
<li class="default active buriedpoint" data-bp-id="shop_listnav_default_1">
<a href="javascript:void(0);">
<span class="nav-txt">默认</span>
<span class="iconfont up cur hide">&#xe615;</span>
<span class="iconfont down cur">&#xe616;</span>
</a>
</li>
<li class="new buriedpoint" data-bp-id="shop_listnav_new_1">
<a href="javascript:void(0);">
<span class="nav-txt">最新</span>
</a>
</li>
<li class="price buriedpoint" data-bp-id="shop_poslist_price_1">
... ...
<div class="discount-detail-page goods-page yoho-page" data-product-pool="{{product_pool}}">
{{> sale/banner}}
<div>
<ul id="list-nav" class="list-nav clearfix">
<li class="default active first-li-more">
<a href="javascript:void(0);">
<span class="span-test">默认</span>
<span class="iconfont up cur hide">&#xe615;</span>
<span class="iconfont down cur">&#xe616;</span>
</a>
</li>
<li class="price">
<a href="javascript:void(0);">
<span class="span-test">价格</span>
<span class="icon">
<i class="iconfont up cur">&#xe615;</i>
<i class="iconfont down">&#xe616;</i>
</span>
</a>
</li>
<li class="discount">
<a href="javascript:void(0);">
<span class="span-test">折扣</span>
<span class="icon">
<i class="iconfont up cur">&#xe615;</i>
<i class="iconfont down">&#xe616;</i>
</span>
</a>
</li>
<li class="filter">
<a href="javascript:void(0);">
<span class="span-test">筛选</span>
<span class="iconfont cur">&#xe613;</span>
</a>
</li>
</ul>
<!--搜索默认排序列表-->
{{> product/search-default-sort-list}}
</div>
{{!--筛选tab--}}
{{> product/filter-tab}}
{{> sale/common}}
<input type="hidden" id="discount" value="discount">
</div>
\ No newline at end of file
</div>
... ...
... ... @@ -48,8 +48,12 @@
{{/floorHeader}}
<div class="sale-nav-wrap">
{{> common/filter-nav}}
<div class='list-nav-layer'>
{{!--筛选tab--}}
{{> product/filter-tab}}
</div>
</div>
{{> sale/common}}
{{> common/suspend-home}}
</div>
... ...
<div class="sale-vip-page goods-page yoho-page">
{{> sale/banner}}
<div class='list-nav-layer'>
<ul id="list-nav" class="list-nav clearfix">
<li class="default active first-li-more">
<a href="javascript:void(0);">
<span class="span-test">默认</span>
<span class="iconfont up cur hide">&#xe615;</span>
<span class="iconfont down cur">&#xe616;</span>
</a>
</li>
<li class="price">
<a href="javascript:void(0);">
<span class="span-test">价格</span>
<span class="icon">
<i class="iconfont up cur">&#xe615;</i>
<i class="iconfont down">&#xe616;</i>
</span>
</a>
</li>
<li class="sale">
<a href="javascript:void(0);">
<span class="span-test">销量</span>
</a>
</li>
<li class="filter">
<a href="javascript:void(0);">
<span class="span-test">筛选</span>
<span class="iconfont cur">&#xe613;</span>
</a>
</li>
</ul>
<!--搜索默认排序列表-->
{{> product/search-default-sort-list}}
{{!--筛选tab--}}
{{> product/filter-tab}}
</div>
{{> sale/common}}
</div>
\ No newline at end of file
</div>
... ...
... ... @@ -4,8 +4,8 @@
<div id="search-input" class="search-input">
<form id="search-form" action="{{url}}" method="get">
<i class="search-icon iconfont">&#xe60f;</i>
<input type="text" placeholder="{{#if defaultTerms}}{{defaultTerms}}{{else}}搜索商品、品牌{{/if}}" name="query" data-bp-id="search_page_input_1" class="buriedpoint" autocomplete="off">
<input type="hidden" name="from" value="search">
<input type="text" placeholder="{{#if defaultTerms}}{{defaultTerms}}{{else}}搜索商品、品牌{{/if}}" name="query" data-bp-id="search_page_input_1" class="buriedpoint" autocomplete="off">
<i class="clear-input iconfont hide">&#xe626;</i>
<span id="search" class="search buriedpoint" type="submit" data-bp-id="search_index_one_0">搜索</span>
</form>
... ...
... ... @@ -222,7 +222,7 @@
</a>
</li>
</ul>
<!--搜索默认排序列表-->
{{> product/search-default-sort-list}}
</div>
... ...