Authored by 陈峰

merge

... ... @@ -14,13 +14,17 @@ const bundleModel = require(`${mRoot}/bundle`);
*/
exports.detail = (req, res, next) => {
bundleModel.detail(req.query).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);
};
... ...
... ... @@ -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`);
/**
... ... @@ -29,12 +30,32 @@ const detail = (params) => {
if (!params.skn) {
return Promise.resolve({});
}
let bundleIndex = (params.index || 1);
--bundleIndex;
return getBundleBySkn(params.skn).then(result => {
return {
bundleInfo: _.get(result, 'data.bundleInfo', {}),
productList: productProcess.processProductList(_.get(result, 'data.productList', []))
};
if (_.has(result, `data[${bundleIndex}]`)) {
let shareInfo = _.get(result, 'data[0].shareInfo', {});
return {
bundleDatas: _.map(result.data, (bundle, index) => {
return {
selected: index === bundleIndex,
title: _.get(bundle, 'bundleInfo.tabName') || '',
href: helpers.urlFormat('/product/bundle/detail', {skn: params.skn, index: ++index}),
};
}),
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;
... ...
<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
... ...
... ... @@ -35,7 +35,7 @@ const domains = {
module.exports = {
app: 'h5',
appVersion: '5.4.1', // 调用api的版本
appVersion: '5.5.0', // 调用api的版本
port: 6001,
siteUrl: '//m.yohobuy.com',
assetUrl: '//127.0.0.1:5001',
... ...
'use strict';
const fs = require('fs');
let devHost = '127.0.0.1';
let devHost = 'm.yohobuy.com';
fs.readFile('.devhost', (err, buf)=> {
if (!err) {
... ...
{{# bundleData}}
<div class="bundle-nav">
<div class="bundle-title">{{title}}</div>
<div class="bundle-right">
<a href="{{href}}">
{{#if description}}
<span class="bundle-desc">{{description}}</span>
{{/if}}
<span class="iconfont">&#xe604;</span>
</a>
</div>
</div>
<div class="bundle-product">
<div class="swiper-wrapper">
{{# productList}}
<div class="swiper-slide plus plus-{{@index}}"><span class="iconfont">&#xe624;</span></div>
<div class="swiper-slide product-box">
<a href="{{@root.bundleData.href}}"><img src="{{image default_images 155 206}}" alt="{{product_name}}"></a>
<div class="bundle-price">{{format_sales_price}}</div>
</div>
{{/ productList}}
</div>
</div>
{{/ bundleData}}
\ No newline at end of file
... ...
{{# bundleData}}
{{#if bundleDatas.length}}
<div class="bundle">
<div class="bundle-nav">
<div class="bundle-title">{{title}}</div>
<div class="bundle-right">
<a href="{{href}}">
{{#if description}}
<span class="bundle-desc">{{description}}</span>
{{/if}}
<span class="iconfont">&#xe604;</span>
</a>
</div>
</div>
<div class="bundle-product">
<div class="bundle-tabs any">
<div class="swiper-wrapper">
{{# productList}}
<div class="swiper-slide plus plus-{{@index}}"><span class="iconfont">&#xe624;</span></div>
<div class="swiper-slide product-box">
<a href="{{@root.bundleData.href}}"><img src="{{image default_images 155 206}}" alt="{{product_name}}"></a>
<div class="bundle-price">{{format_sales_price}}</div>
{{# bundleDatas}}
<div class="swiper-slide{{#if @first}} selected{{/if}}" data-index="{{@index}}">
<div class="line"></div>
<div class="title">
<span>{{tabName}}</span>
</div>
{{/ productList}}
</div>
{{/ bundleDatas}}
</div>
</div>
<div class="bundle-content">
{{> ./bundle-content}}
</div>
</div>
{{/ bundleData}}
\ No newline at end of file
{{/if}}
\ No newline at end of file
... ...
... ... @@ -60,6 +60,9 @@ var limitProductCode,
// 限购商品的skn。只有限购商品时才会设置。
skn;
// 套餐模式
var budnleMode;
// 量贩商品
var discountNum = $('#mnum').val() - 0,
discountLimit = false;
... ... @@ -140,6 +143,21 @@ function setLimitGoodModeWithSknId(code, sknId) {
skn = sknId;
}
/*
* 设置当前面板为套餐商品选择模式
*
* @param {String} sknId. 当前限购商品的sknId
*
* @return {undefined}
*/
function setBundleModeWithSknId(sknId) {
disableNumEdit();
isEdit = 1;
skn = sknId;
$('#chose-btn-sure').html('确认');
budnleMode = true;
}
// 删除面板
function removePannel() {
var $pannel = $('.chose-panel'),
... ... @@ -709,6 +727,23 @@ $yohoPage.on('touchstart', '.btn-minus', function() {
return;
}
if (budnleMode && cbFn) {
let sizeChose = $('.size-list').find('.chosed'),
sku = sizeChose.data('skuid'),
color = $('.color-list').find('.chosed').html().substring(0, 4) + '...',
size = sizeChose.html();
cbFn({
skn,
sku,
color,
size
});
confirming = false;
hide();
return false;
}
// 针对是否处于编辑模式设置不同的url和需要post的数据
if (isEdit) {
cartGoodData = {
... ... @@ -851,3 +886,4 @@ exports.remove = removePannel;
exports.setEditModeWithSknId = setEditModeWithSknId;
exports.disableNumEdit = disableNumEdit;
exports.setLimitGoodModeWithSknId = setLimitGoodModeWithSknId;
exports.setBundleModeWithSknId = setBundleModeWithSknId;
... ...
/**
* Created by targaryen on 2016/11/28.
*/
var $ = require('yoho-jquery'),
tip = require('../plugin/tip');
require('product/bundle/detail.page.css');
require('../common');
let $ = require('yoho-jquery'),
tip = require('plugin/tip'),
Swiper = require('yoho-swiper');
var chosePanelRender = require('../common/chose-panel'),
chosePanel = require('./bundle/chose-pannel');
require('common');
let share = require('common/share');
var $selectBtn = $('.select-btn'),
let chosePanelRender = require('common/chose-panel'),
chosePanel = require('cart/chose-panel');
let $selectBtn = $('.select-btn'),
$buyNowBtn = $('#bundle-buy-now');
// cookie 参数
var actCkOpthn = {
let actCkOpthn = {
path: '/cart/index'
};
$(function() {
window.setCookie('activity-info', '', actCkOpthn);
if ($('#shareUrl').length) {
share({
imgUrl: $('#shareImgUrl').val(),
title: decodeURIComponent($('#shareTitle').val()),
link: $('#shareUrl').val(),
desc: decodeURIComponent($('#shareSubTitle').val())
});
}
if ($('.bundle-tabs').find('.swiper-slide').length > 3) {
new Swiper('.bundle-tabs', {
freeMode: true,
slidesPerView: 'auto',
lazyLoading: true
});
}
});
/**
* 选择商品颜色等
*/
$selectBtn.on('touchend', function() {
var self = $(this);
let self = $(this);
$.post('/product/detail/info', {
id: self.data('id'),
productSkn: self.data('skn')
}, function(data) {
chosePanelRender(data);
chosePanel.init(self.data('skn'));
chosePanel.show();
chosePanel.init();
chosePanel.setBundleModeWithSknId(self.data('skn'));
chosePanel.show('', (productData) => {
var product = $('#gskn-' + productData.skn);
product.data('sku', productData.sku);
product.html('颜色:' + productData.color + ' 尺码:' + productData.size);
});
});
});
$('.goods-img').on('touchend', function() {
var packGood = $(this).parent().find('.select-btn');
let packGood = $(this).parent().find('.select-btn');
if (window._yas && window._yas.sendCustomInfo) {
window._yas.sendCustomInfo({
... ... @@ -54,11 +79,22 @@ $('.goods-img').on('touchend', function() {
});
$('.bundle-tabs').on('click', '.swiper-slide', (e) => {
let $tab = $(e.currentTarget);
if ($tab.hasClass('selected')) {
return;
}
let href = $tab.data('href');
window.location.href = href;
});
/**
* 立即购买
*/
$buyNowBtn.on('click', function() {
var bundleGoods = [],
let bundleGoods = [],
bundleId = $('#activityId').val(),
gskn = $('span[id^="gskn"]'),
gsknSelected = false,
... ...
... ... @@ -36,7 +36,8 @@ var $chosePanel = $('.chose-panel'),
$cartBar,
$soonSoldOut = $('.soonSoldOut-tag'),
$yohoPage = $('.yoho-page'),
single = $('#single').val() || 0;
single = $('#single').val() || 0,
$thumbImg;
var productSkn;
... ... @@ -73,6 +74,7 @@ function init(sknId) {
curSizeIndex = 0;
productSkn = sknId;
disableShowNum();
$thumbImg = $('.thumb-img');
}
// 删除面板
... ... @@ -424,7 +426,18 @@ $yohoPage.on('touchstart', '.btn-minus', function () {
);
}
});
$yohoPage.on('click', '.close', function() {
hide();
});
$yohoPage.on('touchstart', '.thumb-img', function() {
if ($thumbImg.hasClass('hover')) {
$thumbImg.removeClass('hover');
} else {
$thumbImg.addClass('hover');
}
});
exports.init = init;
exports.show = show;
exports.remove = removePannel;
... ...
... ... @@ -2,13 +2,85 @@
* Created by targaryen on 2016/11/25.
*/
var $ = require('yoho-jquery'),
let $ = require('yoho-jquery'),
Swiper = require('yoho-swiper');
let $bundle = $('#placeholder-bundle');
let bundleT = require('product/detail/bundle.hbs');
let bundleContentT = require('product/detail/bundle-content.hbs');
$(function() {
new Swiper('.bundle-product', {
freeMode: true,
slidesPerView: 5,
lazyLoading: true
});
});
let bundleObj = {
bundles: [],
bundleIndex: 0,
init(bundles) {
let self = this;
self.bundles = bundles;
try {
self.render();
self.regTabsSwiper();
self.regProductSwiper();
self.regEvent();
} catch (e) {
console.error(e);
}
},
render() {
let self = this;
var bundleHtml = bundleT({
bundleDatas: self.bundles,
bundleData: self.bundles[self.bundleIndex],
bundleIndex: self.bundleIndex
});
return $bundle.replaceWith(bundleHtml);
},
renderProduct() {
let self = this;
var bundleHtml = bundleContentT({
bundleData: self.bundles[self.bundleIndex],
});
$('.bundle-content').html(bundleHtml);
self.regProductSwiper();
},
regEvent() {
let self = this;
$('.bundle-tabs').on('click', '.swiper-slide', (e) => {
let index = $(e.currentTarget).data('index');
if (self.bundleIndex !== index) {
$(e.currentTarget).addClass('selected').siblings().removeClass('selected');
self.bundleIndex = index;
self.renderProduct();
}
});
},
regProductSwiper() {
let self = this;
if (self.bundles[self.bundleIndex].productList.length > 3) {
new Swiper('.bundle-product', {
freeMode: true,
slidesPerView: 'auto',
lazyLoading: true
});
}
},
regTabsSwiper() {
let self = this;
if (self.bundles.length > 3) {
$('.bundle-tabs').removeClass('any');
new Swiper('.bundle-tabs', {
freeMode: true,
slidesPerView: 'auto',
lazyLoading: true
});
}
}
};
module.exports = bundleObj;
... ...
... ... @@ -205,12 +205,10 @@ setTimeout(() => {
var promotionT = require('product/detail/promotion.hbs');
var feedbackT = require('product/detail/feedbacks.hbs');
var enterStoreT = require('product/detail/enterStore.hbs');
var bundleT = require('product/detail/bundle.hbs');
// placeholder
var $feedbackStore = $('#placeholder-feedback-store');
var $promotion = $('#placeholder-promotion');
var $bundle = $('#placeholder-bundle');
/**
* 渲染 feedback, 店铺, 替换placeholder
... ... @@ -249,19 +247,6 @@ setTimeout(() => {
return $placeholder.replaceWith(promotionHtml);
}
/**
* 渲染 套装,替换placeholder
* @param data
* @param $placeholder
* @returns {*}
*/
function renderBundle(data, $placeholder) {
var bundleHtml = bundleT({
bundleData: data.bundleData
});
return $placeholder.replaceWith(bundleHtml);
}
function promotionInit() {
var $goodsDiscount = $('#goodsDiscount');
... ... @@ -304,8 +289,8 @@ setTimeout(() => {
renderFeedbackStore(info, $feedbackStore);
renderPromotion(info, $promotion);
if (info.bundleData) {
renderBundle(info, $bundle);
if (info.bundleDatas && info.bundleDatas.length) {
require('./detail/bundle').init(info.bundleDatas);
$('.bundle').on('touchstart', function() {
if (window._yas && window._yas.sendCustomInfo) {
window._yas.sendCustomInfo({
... ... @@ -322,7 +307,6 @@ setTimeout(() => {
// step2: init js
require('./detail/comments-consults');
require('./detail/consultform'); // TODO
require('./detail/bundle');
promotionInit();
window.rePosFooter && window.rePosFooter();
});
... ...
... ... @@ -3,6 +3,69 @@
min-height: 1000px;
}
.bundle-tabs {
padding-left: 23px;
padding-right: 23px;
height: 76px;
border-bottom: solid 1PX #ddd;
overflow: hidden;
background-color: #fff;
&.any {
padding: 0;
.swiper-slide {
width: auto;
flex: 1;
}
}
.swiper-slide {
width: 168px;
text-align: center;
position: relative;
display: flex;
&:first-child {
.line {
display: none;
}
}
&.selected {
span {
color: #454545;
border-bottom: solid 2PX #454545;
}
}
.line {
width: 1px;
height: 28px;
margin-top: 24px;
float: left;
border-left: solid 1PX #ddd;
}
.title {
width: 100%;
flex: 1;
span {
display: inline-block;
min-width: 103px;
max-width: 100%;
color: #b2b2b2;
line-height: 76px;
height: 76px;
font-size: 28px;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
}
}
}
}
.bundle-detail-goods {
width: 100%;
height: 248px;
... ... @@ -67,6 +130,12 @@
background-color: #fff;
padding: 15px 30px;
.no-buy {
height: 92px;
line-height: 92px;
color: #d0021b;
}
.bundle-bar-md {
width: 400px;
display: inline-block;
... ...
@import "layout/swiper";
@import "detail";
@import "cart/chose-panel";
... ...
.bundle {
height: 344px;
height: 420px;
overflow: hidden;
background-color: #fff;
margin-bottom: 30px;
border-bottom: 1px solid #e0e0e0;
border-top: 1px solid #e0e0e0;
.bundle-tabs {
padding-left: 23px;
padding-right: 23px;
height: 76px;
border-bottom: solid 1PX #ddd;
&.any {
padding: 0;
.swiper-slide {
width: auto;
flex: 1;
}
}
.swiper-slide {
width: 168px;
text-align: center;
position: relative;
display: flex;
&:first-child {
.line {
display: none;
}
}
&.selected {
span {
color: #454545;
border-bottom: solid 2PX #454545;
}
}
.line {
width: 1px;
height: 28px;
margin-top: 24px;
float: left;
border-left: solid 1PX #ddd;
}
.title {
width: 100%;
flex: 1;
span {
display: inline-block;
min-width: 103px;
max-width: 100%;
color: #b2b2b2;
line-height: 76px;
height: 76px;
font-size: 28px;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
}
}
}
}
.bundle-nav {
overflow: hidden;
padding: 0 30px;
line-height: 88px;
border-bottom: 1px solid #e0e0e0;
line-height: 70px;
.bundle-title {
float: left;
... ... @@ -22,10 +83,11 @@
float: right;
.bundle-desc {
padding: 3px 5px;
padding: 0 10px;
border: 1px #d0021b solid;
border-radius: 5px;
color: #d0021b;
font-size: 12PX;
}
.iconfont {
... ... @@ -35,8 +97,8 @@
}
.bundle-product {
margin-top: 30px;
width: 100%;
margin-top: 10px;
.swiper-wrapper {
.plus {
... ... @@ -50,6 +112,7 @@
.plus-0 {
visibility: hidden;
margin: 0;
}
.product-box {
... ...