Authored by 毕凯

Merge branch 'feature/reds' into 'release/5.6'

红人店铺



See merge request !462
... ... @@ -13,7 +13,8 @@ const headerModel = require('../../../doraemon/models/header');
const _ = require('lodash');
const helpers = global.yoho.helpers;
const productProcess = require(`${utils}/product-process`);
const redShopPrcs = require(`${utils}/redshop-process`);
const co = require('bluebird').coroutine;
/**
* 从 useragent 获取 uid
... ... @@ -378,32 +379,41 @@ const shop = {
* 红人店铺
*/
redShop(req, res, next) {
let shopId = 34; // test
let shopId = req.query.shop_id; // test3 792
let channel = req.yoho.channel || 'boys';
let gender = req.query.gender;
let uid = req.user.uid || 0;
let udid = req.sessionID || 'yoho';
Promise.all([
redsShopModel.getBanner(shopId), // 0: 获取红人店 banner
redsShopModel.getShopsBrands(shopId), // 1: 获取店铺品牌数据
redsShopModel.getIntro(shopId), // 2. 获取店铺介绍
redsShopModel.getShopsdecorator(shopId) // 3. 获取店铺装修元素
]).then(valArr => {
let banner = _.get(valArr[0], 'data.banner');
if (!shopId) {
return next();
}
let brand = _.get(valArr[1], 'data[0]', {});
let introData = valArr[2];
let decoratorsData = valArr[3];
co(function* () {
let bannerData = yield redsShopModel.getBanner(shopId);
let shopData = yield redsShopModel.getIntro(shopId);
let favCountData = yield redsShopModel.favCount(shopId, uid, channel, udid);
let decoratorsData = yield redsShopModel.getShopsdecorator(shopId);
let categoryData = yield redsShopModel.getShopCategory(shopId, channel, gender);
let banner = _.get(bannerData, 'data.banner');
let shopInfo = redShopPrcs.shopIntro(_.get(shopData, 'data', {}));
let favCount = _.get(favCountData, 'data[0].approximateCount', '2.1w');
let decorators = redShopPrcs.floor(_.get(decoratorsData, 'data.modules', []));
let category = redShopPrcs.category(_.get(categoryData, 'data', []), shopId);
res.render('newshop/shop-reds', {
pageHeader: headerModel.setNav({
navTitle: shop.shop_name || '店铺'
}),
width750: true,
localCss: true,
module: 'product',
page: 'reds-shop',
shopId,
banner, brand, introData, decoratorsData,
time3: [0, 1, 2]
banner, shopInfo, favCount, decorators, category
});
}).catch(next);
})().catch(next);
},
/**
... ...
... ... @@ -4,50 +4,41 @@
'use strict';
const api = global.yoho.API;
const singleAPI = global.yoho.SingleAPI;
/**
* 获取红人店铺 banner
* doc: http://git.yoho.cn/yoho-documents/api-interfaces/blob/master/商品列表/店铺装修.md
* @param int shopId 店铺id
* 频道
* @type {{}}
*/
exports.getBanner = shopId => {
let params = {
// method: 'app.popular.shop.banner',
method: 'app.shop.banner', // TODO: this is mock api,use up
shop_id: shopId,
app_type: 0 // 0 有货 1 blk
};
return api.get('', params, {cache: true, code: 200});
const yhChannel = {
boys: 1,
girls: 2,
kids: 3,
lifestyle: 4
};
/**
* 获取店铺 品牌数据
* 获取红人店铺 banner
* doc: http://git.yoho.cn/yoho-documents/api-interfaces/blob/master/商品列表/店铺装修.md
* @param int shopId 店铺id
*/
exports.getShopsBrands = shopId => {
exports.getBanner = shopId => {
let params = {
method: 'app.shops.getShopsBrands',
method: 'app.popular.shop.banner',
shop_id: shopId
};
return api.get('', params, {cache: true, code: 200});
};
/**
* 获取店铺 介绍
* @param int shopId 店铺id
*/
exports.getIntro = shopId => {
let params = {
// method: 'app.popular.shops.getIntro',
method: 'app.shops.getIntro',
shop_id: shopId,
app_type: 0
shop_id: shopId
};
return api.get('', params, {cache: true, code: 200});
... ... @@ -62,9 +53,37 @@ exports.getIntro = shopId => {
exports.getShopsdecorator = shopId => {
let params = {
method: 'app.popular.shopsdecorator',
shop_id: shopId,
app_type: 0
shop_id: shopId
};
return api.get('', params, {cache: true, code: 200});
};
/**
* 获取店铺下面的所有分类
* @param {int} shopId 店铺id
* @param {string} channel 频道
* @return array
*/
exports.getShopCategory = (shopId, channel, gender) => {
return api.get('', {
method: 'app.shop.getSortInfo',
yh_channel: yhChannel[channel],
gender: gender || '1,3',
shop_id: shopId
});
};
/**
* 店铺收藏数量
*/
exports.favCount = (shopId, uid, channel, udid) => {
return singleAPI.get('favorite', {
method: 'app.favorite.queryFavoriteCountByShopIds',
favIds: shopId,
type: 'shop',
udid: udid,
uid: uid,
physical_channel: yhChannel[channel],
});
};
... ...
... ... @@ -160,7 +160,7 @@ router.get('/index/baseShopFav', newShop.baseShopFav);
router.get('/index/brandFav', newShop.brandFav);
router.get('/new/shop/hotlist', newShop.shopHotList);
router.get('/red_shop', newShop.redShop); // TODO,TODO,TODO,TODO
router.get('/red-shop', newShop.redShop);
// end- 店铺重构
... ...
{{!--
desc: 红人店铺
--}}
<input type="hidden" name="shop-id" class="shop-id" value="{{shopId}}">
<div class="reds-shop">
{{!--shop-header--}}
<div class="shop-header brand-header" data-id="{{brand.brand_id}}">
<img class="banner" {{#if banner}} src="{{image banner 750 234}}"{{/if}} alt="banner">
<div class="shop-info">
<img class="logo" src="{{image brand.brand_ico 120 120}}" alt="logo">
<div class="shop-info-base">
<h1 class="shopname">{{brand.brand_name}}</h1>
<div class="favs">粉丝数: 534 <i class="iconfont favs-btn like">&#xe605;</i></div>
</div>
<div class="shop-intro">
<div class="line-clamp-2">这里是介绍这里是介绍这里是介绍这里是介绍这里是介绍这里是介绍这里是介绍这里是介绍这里是介绍这里是介绍这里是介绍</div>
<div class="shop-intro-folder">
<i class="iconfont">&#xe616;</i>
<div class="shop-header brand-header">
{{#if banner}}
<div class="branner-top">
<img class="shop-back-img" src="{{image banner 750 234}}">
{{#if shopInfo.shop_logo}}
<img class="logo" src="{{image shopInfo.shop_logo 120 120}}">
{{/if}}
<p class="store-name">{{shopInfo.shop_name}}</p>
<div class="fav-box clearfix">
<div class="favs pull-left">粉丝数: {{favCount}} </div>
<div class="not-collect pull-left" id="collect" data-bp-id="shop_branner_collect_1"></div>
</div>
</div>
</div>
{{/if}}
</div>
{{!--shop-tab-nav: 红人首页 | 全部商品--}}
{{!--shop-tab-nav: 首页 | 全部商品--}}
<div class="tab">
<ul class="shop-tabs tab-navs" data-sticky>
<li class="shop-tab-nav tab-nav active">
<a href="#red-index" data-trigger="tab">红人首页</a>
<span data-target="#red-index" data-trigger="tab" data-funHome>首页</span>
</li>
<em>|</em>
<li class="shop-tab-nav tab-nav">
<span data-target="#all-goods" data-trigger="tab" data-funGetNewGoods>上新</span>
</li>
<em>|</em>
<li class="shop-tab-nav tab-nav">
<a href="#all-goods" data-trigger="tab">全部商品</a>
<span data-target="#all-goods" data-trigger="tab" data-funGetAllGoods>全部商品</span>
</li>
</ul>
{{!--筛选tab--}}
<div class="filter-box">
{{> product/filter-tab}}
{{> common/filter}}
</div>
<div class="tab-panels">
{{!--shop-tab: 红人首页--}}
<div id="red-index" class="tab-panel active">
{{!--shop-tab: 首页--}}
<div id="red-index" class="tab-panel red-shop-index active">
<div class="shop-coupon coupon-group"></div>
{{!--<div class="shop-coupon coupon-content">
{{#each time3}}
<div class="coupon-small">
<div class="coupon-left">
<span class="coupon-left-price">
<span class="coupon-sign">¥</span>
<span class="coupon-price">88</span>
</span>
<span class="coupon-left-name">
VANS圣诞礼券:满588减88
</span>
</div>
<div class="coupon-right receive-btn">
立即领取
</div>
</div>
{{/each}}
</div>--}}
<div class="shop-swiper">
</div>
{{!--视屏--}}
<div class="shop-video shop-section">
<header>
<i class="section-more iconfont">&#xe606;</i>
<h4 class="section-title">视屏直播</h4>
</header>
<div class="video-player">
<div class="video-poster">
<div class="video-meta-customers">
<i class="iconfont">&#xe602;</i>&nbsp;&nbsp;<span>13145</span>
</div>
</div>
</div>
<div class="video-intro">
<h6 class="video-title">这是视屏标题</h6>
<p class="text-line-2">这是视屏内容这是视屏内容这是视屏内容这是视屏内容这是视屏内容这是视屏内容这是视屏内容这是视屏内容</p>
</div>
</div>
{{!--人气单品--}}
<div class="shop-hot shop-section">
<header>
{{!--<i class="section-more iconfont">&#xe606;</i>--}}
<h4 class="section-title">人气单品</h4>
</header>
<div class="section-content">
<div class="items-s1">
{{> item}}
</div>
<div class="items-s2">
{{> item}}
</div>
{{!--风格: 3图2列, 大图 在左--}}
<div class="items-3-2 items-3-2-left">
{{#each time3}}
{{> item}}
{{/each}}
</div>
</div>
{{!--风格: 3图2列, 大图 在右--}}
<div class="items-3-2 items-3-2-right">
{{#each time3}}
{{> item}}
{{/each}}
</div>
<div class="shop-item-div"></div>
<div class="items-s1">
{{> item}}
</div>
{{!--风格: 3图 3列--}}
<div class="items-3-3">
{{#each time3}}
{{> item}}
{{/each}}
</div>
<div class="items-c2">
{{#each time3}}
{{> item}}
{{/each}}
</div>
{{!--风格: 3图 3列--}}
<div class="items-3-3 items-small">
{{#each time3}}
{{> item}}
{{/each}}
{{#each time3}}
{{> item}}
{{/each}}
{{> reds-shop/modules}}
</div>
{{!--shop-tab: 全部商品--}}
<div id="all-goods" class="tab-panel">
<div class="good-list-page yoho-page">
<div id="goods-container" class="goods-container">
<div class="default-goods container clearfix"></div>
</div>
</div>
</div>
{{!--shop-tab: 全部商品--}}
<div id="all-goods" class="tab-panel"></div>
</div>
</div>
</div>
{{#*inline 'item'}}
<div class="item">
<img class="item-pic" src="http://img1.gamersky.com/image2016/12/20161224_zl_91_3/gamersky_02origin_03_201612241718D33.jpg" alt="">
<div class="item-info">
<div class="">
ABCDEFG ABCDEFG
</div>
<div>
<span class="new-price">¥ 199.00</span>
<span class="price">¥ 299.00</span>
</div>
</div>
</div>
{{/inline}}
\ No newline at end of file
<input type="hidden" id="shopId" name="shopId" class="shop-id" value="{{shopId}}">
{{> reds-shop/footer}}
\ No newline at end of file
... ...
<div class="item">
<img class="item-pic" src="http://img1.gamersky.com/image2016/12/20161224_zl_91_3/gamersky_02origin_03_201612241718D33.jpg" alt="">
<div class="item-info">
<div class="">
ABCDEFG ABCDEFG
</div>
<div>
<span class="new-price">¥ 199.00</span>
<span class="price">¥ 299.00</span>
</div>
</div>
</div>
\ No newline at end of file
<div class="shop-foot-wrapper">
<ul>
<li data-bp-id="shop_footnav_one_1">
{{#if category.url}}
<a href="{{category.url}}">商品分类</a>
{{^}}
<span id="shop-category">商品分类</span>
<div class="sub-group hide">
<dl>
{{# category.list}}
<dd data-bp-id="shop_subgroup_{{name}}_1"><a href="{{url}}">{{name}}</a></dd>
{{/ category.list}}
</dl>
<div class="sharp"></div>
</div>
{{/if}}
<div class="wall"></div>
</li>
<li data-bp-id="shop_footnav_three_1">
<a href="{{shopInfo.shop_intro_link}}">店铺简介</a>
</li>
</ul>
</div>
... ...
<div class="item">
{{#if link}}
<a href="{{link}}">
<img class="item-pic" src="{{src}}" alt="">
</a>
{{^}}
<img class="item-pic" src="{{src}}" alt="">
{{/if}}
{{#if showProductInfo}}
<div class="item-info">
<div>{{text}}</div>
</div>
{{/if}}
</div>
... ...
{{#each decorators}}
{{#isEqual module_type 'Title'}}
<header class="section-header">
<div class="section-title">{{../text}}</div>
{{#if ../link}}
<a class="section-more" href="{{../link}}"><i class="iconfont">&#xe606;</i></a>
{{/if}}
</header>
{{#if ../isModuleMargin}}
<div class="margin-bottom"></div>
{{/if}}
{{/isEqual}}
{{#isEqual module_type 'CarouselImage'}}
<div class="shop-swiper shop-swiper-{{../num}}">
<ul class="swiper-wrapper">
{{#each ../pics}}
<li class="swiper-slide">
{{#if link}}
<a href="{{link}}">
<img src="{{src}}" alt="">
</a>
{{^}}
<img src="{{src}}" alt="">
{{/if}}
</li>
{{/each}}
</ul>
</div>
{{#if ../isModuleMargin}}
<div class="margin-bottom"></div>
{{/if}}
{{/isEqual}}
{{#isEqual module_type 'Video'}}
<div class="shop-video shop-section">
<div class="video-player" style="background-image: url({{../pic}})">
<div class="video-poster">
<div class="video-meta-customers">
<i class="iconfont">&#xe602;</i>&nbsp;&nbsp;<span>13145</span>
</div>
</div>
</div>
<div class="video-intro">
<h6 class="video-title">{{../title}}</h6>
<p class="text-line-2">{{../content}}</p>
</div>
</div>
{{#if ../isModuleMargin}}
<div class="margin-bottom"></div>
{{/if}}
{{/isEqual}}
{{#isEqual module_type 'SingleImage'}}
<div class="items-s1">
{{#each ../pics}}
{{> reds-shop/item}}
{{/each}}
</div>
{{#if ../isModuleMargin}}
<div class="margin-bottom"></div>
{{/if}}
{{/isEqual}}
{{#isEqual module_type 'DoubleImage'}}
<div class="items-s2">
{{#each ../pics}}
{{> reds-shop/item}}
{{/each}}
</div>
{{#if ../isModuleMargin}}
<div class="margin-bottom"></div>
{{/if}}
{{/isEqual}}
{{#isEqual module_type 'TripleImage'}}
<div class="{{#isEqual ../displayType 1}}items-3-2 items-3-2-left{{/isEqual}}{{#isEqual ../displayType 2}}items-3-2 items-3-2-right{{/isEqual}}{{#isEqual ../displayType 3}}items-3-3{{/isEqual}}{{#isEqual ../displayType 4}}items-3-3 items-small{{/isEqual}}">
{{#each ../pics}}
{{> reds-shop/item}}
{{/each}}
</div>
{{#if ../isModuleMargin}}
<div class="margin-bottom"></div>
{{/if}}
{{/isEqual}}
{{#isEqual module_type 'FourImage'}}
<div class="items-s4">
{{#each ../pics}}
{{> reds-shop/item}}
{{/each}}
</div>
{{#if ../isModuleMargin}}
<div class="margin-bottom"></div>
{{/if}}
{{/isEqual}}
{{#isEqual module_type 'SknList'}}
<div class="index-goods-container" data-skns="{{../skns}}"></div>
{{#if ../isModuleMargin}}
<div class="margin-bottom"></div>
{{/if}}
{{/isEqual}}
{{/each}}
... ...
... ... @@ -17,7 +17,7 @@
* </div>
* </div>
*/
const $ = require('yoho-jquery');
let Tab = function(elem) {
this.$elem = $(elem);
... ... @@ -29,7 +29,7 @@ Tab.prototype.show = function() {
let selector = elem.dataset.target;
if (!selector) {
selector = elem.getAttribute('href') || '';
selector = elem.getAttribute('data-target') || '';
selector = /^#[a-z]/i.test(selector) ? selector : null;
}
... ... @@ -38,7 +38,7 @@ Tab.prototype.show = function() {
let $target = $(targetSelector);
if ($nav.hasClass('active')) {
if ($nav.hasClass('active') || $nav.parent().hasClass('active')) {
return;
}
... ... @@ -75,12 +75,27 @@ $.fn.yoTab.constructor = Tab;
$(document).on('click', '[data-trigger=tab]', function(event) {
let $nav = $(event.target);
let fun = '';
if ($nav.hasClass('active') || $nav.parent().hasClass('active')) {
return false;
}
$.each($nav.data(), function(index) {
if (index.substr(0, 3) === 'fun') {
fun = index.substr(3, index.length - 3);
if ($.isFunction(Tab.prototype[fun])) {
Plugin.call($nav, fun);
}
}
});
event.preventDefault();
event.stopPropagation();
let $nav = $(event.target);
Plugin.call($nav, 'show');
});
module.exports = Tab;
... ...
require('layout/_swiper.css');
require('product/search/list.page.css');
require('product/shop/redshop.page.css');
require('plugin/sticky');
require('plugin/tab');
const $ = require('yoho-jquery');
const allProduct = require('./shop/all-product');
let Tab = require('../plugin/tab');
let $filterBox = $('.filter-box');
let $shopCategory = $('#shop-category');
Tab.prototype.home = function() { // 隐藏筛选 TAB
$filterBox.css('display', 'none');
};
Tab.prototype.getallgoods = function() { // 显示筛选 TAB
$filterBox.css('display', 'block');
allProduct.getGoodsList({type: 'default', page: 1});
};
Tab.prototype.getnewgoods = function() {
$filterBox.css('display', 'none');
allProduct.getGoodsList({type: 'new', page: 1});
};
/**
* 商品分类展示隐藏
*/
if ($shopCategory.length > 0) {
$shopCategory.on('click', function() {
$('.sub-group').toggleClass('hide');
});
}
// 页面打开直接加载筛选项
allProduct.getFilter();
require('../plugin/sticky');
require('./shop/coupon');
require('./shop/red-shop');
... ...
/*
* @Author: Targaryen
* @Date: 2017-03-24 13:43:55
* @Last Modified by: Targaryen
* @Last Modified time: 2017-03-31 14:46:52
*/
/** *****************************
* 红人店铺使用的全部商品页面碎片
*******************************/
const filter = require('../../plugin/filter');
const lazyLoad = require('yoho-jquery-lazyload');
let noResultHbs = require('product/search/no-result-new.hbs');
let $goodsContainer = $('#goods-container');
let $container = $goodsContainer.children('.default-goods'); // 承载商品列表的容器
let $listNav = $('#list-nav'); // 筛选项列表
let $pre = $listNav.find('.active'); // 记录进入筛选前的active项,初始为选中项
let $allGoodsTabPage = $(document.getElementById('all-goods'));
let $filterBody = $('.filter-body');
const shopId = $('#shopId').val();
let navInfo = {
price: {
order: 1,
end: false
},
discount: {
order: 1,
end: false
},
default: {
order: 0,
end: false,
type: 'default'
},
new: {
order: 0,
end: false
},
sale: {
order: 0,
end: false
}
};
let beforeScroll = document.body.scrollTop; // 滚动前位置记录
let navType = 'default'; // 目前激活的导航页面
let defaultOpt = Object.assign({}, navInfo.default, {shop_id: shopId}); // 默认参数
let onSearching = false; // 是否正在搜索
let isScrollLoad = false; // 是否是滚动加载
let page = 1; // 页码
let nav;
/**
* 处理筛选参数
*/
const handleChoseFilter = function() {
$.each($filterBody.find('.chosed'), function(index, elem) {
let choseOpt = {};
choseOpt[$(elem).parent().data('type')] = $(elem).data('id');
Object.assign(defaultOpt, choseOpt);
});
};
/**
* 获取商品列表
*/
const getGoodsList = params => {
handleChoseFilter();
if (!onSearching) {
Object.assign(defaultOpt, {
page: page++
});
}
// 有参数,参数优先,滚动加载相关参数重置
if (params) {
Object.assign(defaultOpt, params);
if (params.page) {
page = params.page + 1;
}
isScrollLoad = false;
beforeScroll = document.body.scrollTop;
}
if (nav && nav.end) {
return false;
}
if (!onSearching) {
onSearching = true;
$.ajax({
type: 'GET',
url: location.protocol + '//m.yohobuy.com/product/search/search',
data: defaultOpt,
xhrFields: {
withCredentials: true
},
beforeSend: function() {
if ($('.no-result-new').length > 0) {
$('.no-result-new').remove();
}
$container.append('<div class="search-divide">正在加载...</div>');
},
success: function(result) {
// 去掉正在加载
$('.search-divide').remove();
let noResult = !result || result.length < 1 || (result.list && result.list.length < 1);
// 没有结果输出没有结果页面
if (noResult) {
if (isScrollLoad) {
$container.append('<div class="search-divide">没有更多内容了...</div>');
} else {
$container.html(noResultHbs());
}
if (nav) {
nav.end = true;
}
onSearching = false;
return false;
}
if (isScrollLoad) {
$container.append(result);
} else {
$container.html(result);
}
lazyLoad($container.find('img[class=lazy]').not('img[src]'));
onSearching = false;
},
error: function() {
let $divide = $('.search-divide');
$divide.text('加载失败,点击重试');
$divide.one('click', function() {
$divide.text('正在加载...');
getGoodsList();
});
onSearching = false;
}
});
}
};
/**
* 加载筛选数据
*/
const getFilter = function() {
$.ajax({
type: 'GET',
url: location.protocol + '//m.yohobuy.com/product/search/filter',
data: defaultOpt,
success: function(data) {
if (!data) {
return false;
}
$goodsContainer.append(data);
// 初始化filter&注册filter回调
filter.initFilter({
fCbFn: getGoodsList,
hCbFn: function() {
// 切换active状态到$pre上
$pre.addClass('active');
$pre.siblings('.filter').removeClass('active');
}
});
$filterBody = $('.filter-body');
}
});
};
$listNav.bind('contextmenu', function() {
return false;
});
$listNav.on('touchend touchcancel', function(e) {
page = 0;
beforeScroll = $(window).scrollTop();
isScrollLoad = false;
let $this = $(e.target).closest('li'); // 被点击的 Tab
let $active;
if ($this.hasClass('filter')) { // 筛选面板
// 筛选面板切换状态
if ($this.hasClass('active')) {
filter.hideFilter();
// 点击筛选前的 active 项恢复 active
$pre.addClass('active');
$this.removeClass('active');
} else {
$pre = $this.siblings('.active');
$pre.removeClass('active');
$this.addClass('active');
filter.showFilter();
}
} else { // 排序改变
if ($this.hasClass('new')) {
navType = 'new';
} else if ($this.hasClass('price')) {
navType = 'price';
} else if ($this.hasClass('discount')) {
navType = 'discount';
} else if ($this.hasClass('default')) {
navType = 'default';
} else if ($this.hasClass('sale')) {
navType = 'sale';
}
// 更新当前排序:默认、最新、价格、折扣
nav = navInfo[navType];
if ($this.hasClass('active')) {
// 默认、最新无排序切换
if ($this.hasClass('default') || $this.hasClass('new')) {
return false;
}
if ($this.hasClass('price') || $this.hasClass('discount')) {
// 价格或折扣切换排序状态
$this.find('.icon > .iconfont').toggleClass('cur');
$pre = $this; // 更新 pre 为当前项
nav.order = nav.order === 0 ? 1 : 0; // 切换排序
}
} else {
$active = $this.siblings('.active');
$pre = $this; // $pre为除筛选导航的其他导航项,若当前active的为筛选,则把$pre置为当前点击项
if ($active.hasClass('filter')) {
// 若之前active项为筛选,则隐藏筛选面板
filter.hideFilter();
}
$active.removeClass('active');
$this.addClass('active');
}
/* 排序条件更新 */
defaultOpt.type = navType;
Object.assign(defaultOpt, nav);
getGoodsList();
}
});
/**
* 当scroll到1/2$goodsContainer高度后继续请求下一页数据
*/
const scrollHandler = function() {
if ($allGoodsTabPage.hasClass('active') && $(window).scrollTop() > $goodsContainer.height() * 0.6) {
isScrollLoad = true;
getGoodsList();
}
};
/**
* 滚动加载
*/
$(window).scroll(function() {
setTimeout(function() {
let afterScroll = document.body.scrollTop;
if (afterScroll - beforeScroll > 0) {
window.requestAnimationFrame(scrollHandler);
beforeScroll = afterScroll;
} else {
return false;
}
}, 5);
});
module.exports = {
getGoodsList,
getFilter
};
... ...
/*
* @Author: Targaryen
* @Date: 2017-03-23 11:31:51
* @Last Modified by: Targaryen
* @Last Modified time: 2017-04-01 16:58:34
*/
/** *****************
* 红人店铺首页
********************/
const Swiper2 = require('yoho-swiper2');
let tip = require('../../plugin/tip');
let $goodsContainer = $('.index-goods-container');
let $collect = $('#collect');
const shopId = $('#shopId').val();
/**
* 异步检测是否已经收藏
*/
$.ajax({
type: 'GET',
url: location.protocol + '//m.yohobuy.com/product/index/shopFav',
xhrFields: {
withCredentials: true
},
data: {
shopId: shopId
},
success: function(data) {
if (data.collect) {
$collect.attr('class', 'already-collect pull-left');
}
},
error: function() {
tip.show('网络断开连接了~');
}
});
/**
* 异步加载人气单品
*/
$.each($goodsContainer, function(index, elem) {
$.ajax({
type: 'GET',
url: location.protocol + '//m.yohobuy.com/product//new/shop/hotlist',
xhrFields: {
withCredentials: true
},
data: {
skns: $(elem).data('skns')
},
success: function(result) {
$(elem).html(result);
}
});
});
/**
* 店铺轮播图
*/
if ($('.shop-swiper')) {
let num = $('.shop-swiper').length;
for (let i = 1; i <= num; i++) {
new Swiper2('.shop-swiper-' + i, {
lazyLoading: true,
lazyLoadingInPrevNext: true,
loop: true,
autoplay: 3000,
slideElement: 'li',
paginationClickable: true,
pagination: $(this).closest('.shop-swiper-' + i).find('.pagination-inner').get(0)
});
}
}
/**
* 店铺收藏取消收藏操作
*/
$collect.on('click', function() {
let options = {
id: shopId,
opt: 'ok',
type: 'shop'
};
if ($collect.hasClass('already-collect')) {
options.opt = 'cancel';
}
$.ajax({
method: 'get',
url: location.protocol + '//m.yohobuy.com/product/opt/favoriteBrand',
xhrFields: {
withCredentials: true
},
data: options,
success: function(result) {
if (result.code === 200) {
if ($collect.hasClass('already-collect')) {
$collect.attr('class', 'not-collect pull-left');
tip.show('店铺取消收藏成功');
} else {
$collect.attr('class', 'already-collect pull-left');
tip.show('店铺收藏成功');
}
}
if (result.code === 400) {
if ($('#jump-login').length <= 0) {
$('body').append('<a href=\'' + result.data + '\'><span id="jump-login"><span></a>');
}
$('#jump-login').click();
}
}
});
});
... ...
.shop-foot-wrapper {
position: fixed;
left: 0;
bottom: 0;
display: table;
width: 100%;
height: 44PX;
line-height: 44PX;
font-size: 14PX;
background: #fff;
border-top: 1px solid #e0e0e0;
z-index: 2;
ul {
display: table-row;
}
li {
display: table-cell;
text-align: center;
.wall {
width: 0;
height: 14PX;
margin-top: 15PX;
float: right;
border-right: 1px solid #e0e0e0;
display: inline-block;
}
}
.sub-group {
position: absolute;
background: #fff;
border: 1px solid #e0e0e0;
border-radius: 12px;
bottom: 104px;
width: 40%;
margin-left: 5%;
dl {
padding: 0 30px;
margin: 0 auto;
}
dd {
line-height: 80px;
text-align: center;
border-top: 1px solid #e0e0e0;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
a {
color: #444;
}
}
dd:first-child {
border-top: 0;
}
}
.sharp {
position: absolute;
width: 100%;
height: 10px;
background: resolve("product/sharp.png") no-repeat center center;
}
.foot-list-3 .sub-group {
width: 29%;
margin-left: 2%;
}
}
... ...
.shop-header {
.banner {
height: 234px;
.reds-shop {
margin-bottom: 80px;
.pull-left {
float: left;
}
.clearfix:after {
content: "";
display: table;
clear: both;
}
}
.shop-info {
position: relative;
padding-right: 30px;
padding-left: 30px;
.branner-top {
width: 100%;
height: 234px;
position: relative;
overflow: hidden;
.shop-back-img {
height: 100%;
width: 100%;
}
}
.logo {
position: absolute;
top: -40px;
width: 120px;
height: 120px;
box-shadow: 0 0 2px 1px #dedede;
overflow: hidden;
left: 30px;
bottom: 30px;
width: 100px;
height: 100px;
}
.shopname {
font-size: 32px;
color: #444;
margin-left: 180px;
.store-name {
color: #fff;
font-size: 28px;
position: absolute;
overflow: hidden;
left: 148px;
bottom: 20px;
}
.favs-btn {
margin-left: 30px;
.fav-box {
position: absolute;
bottom: 20px;
right: 30px;
border-radius: 10px;
text-align: center;
background-size: contain;
color: #fff;
font-size: 28px;
&.like {
color: #e33333;
.favs {
line-height: 48px;
margin-right: 16px;
padding-top: 4px;
}
}
}
.shop-info-base {
display: flex;
justify-content: space-between;
line-height: 1;
padding-top: 38px;
padding-bottom: 35px;
}
.shop-intro {
font-size: 28px;
color: #444;
}
.already-collect {
width: 128px;
height: 50px;
border-radius: 10px;
background-image: url("/product/already-collect.png") no-repeat;
background-size: contain;
}
.shop-intro-folder {
margin-top: 26px;
margin-bottom: 24px;
text-align: center;
font-size: 18px;
line-height: 1;
.not-collect {
width: 128px;
height: 50px;
border-radius: 10px;
background-image: url("/product/not-collect.png") no-repeat;
background-size: contain;
}
}
... ...
.shop-tabs {
display: flex;
justify-content: space-around;
width: 100%;
font-size: 30px;
line-height: 80px;
border-top: 1PX solid #dededf;
border-bottom: 1PX solid #dededf;
background-color: #fff;
.reds-shop {
.shop-tabs {
display: flex;
justify-content: space-around;
width: 100%;
font-size: 30px;
line-height: 80px;
border-top: 1PX solid #dededf;
border-bottom: 1PX solid #dededf;
background-color: #fff;
em {
color: #dededf;
}
em {
color: #dededf;
}
&.sticky {
z-index: 10;
&.sticky {
z-index: 10;
}
}
}
.shop-tab-nav {
color: #dededf;
.shop-tab-nav {
color: #dededf;
width: 33.33%;
text-align: center;
&.active {
color: #434241;
}
span {
display: inline-block;
width: 100%;
}
&.active {
color: #434241;
}
a {
color: inherit;
a {
color: inherit;
}
}
}
... ...
.reds-shop .filter-box {
display: none;
.list-nav {
border-top: 2px solid #fff;
border-bottom: 1px solid #e6e6e6;
> li {
float: left;
width: 20%;
height: 33PX;
line-height: 33PX;
text-align: center;
font-size: 14PX;
}
.bytouch {
background: #eee;
}
a {
display: block;
box-sizing: border-box;
width: 100%;
height: 100%;
color: #999;
}
.nav-txt {
display: inline-block;
height: 100%;
box-sizing: border-box;
}
.active > a {
color: #000;
.iconfont {
color: #999;
&.cur {
color: #000;
}
}
}
.new .iconfont {
transform: scale(0.8);
font-weight: bold;
font-size: 12PX;
}
.filter .iconfont {
font-size: 12PX;
transition: transform 0.1 ease-in;
}
.filter.active .iconfont {
transform: rotate(-180deg);
}
.icon {
position: relative;
i {
position: absolute;
transform: scale(0.8);
font-weight: bold;
}
.up {
top: -11PX;
}
.down {
top: -4PX;
}
}
}
}
... ...
/*
红人首页
*/
.shop-section {
header {
* @Author: Targaryen
* @Date: 2017-03-23 17:12:53
* @Last Modified by: Targaryen
* @Last Modified time: 2017-04-01 17:09:05
*/
// 红人店铺首页
/* 标题 */
.reds-shop .red-shop-index {
.section-header {
font-size: 32px;
font-weight: bold;
color: #444;
... ... @@ -13,6 +19,7 @@
}
.section-title {
font-size: 32px;
text-align: center;
}
... ... @@ -20,55 +27,9 @@
font-size: 40px;
color: #a9a9a9;
float: right;
margin-top: -82px;
}
}
.shop-coupon {
background-color: #f0f0f0;
}
.shop-swiper {
height: 234px;
}
.shop-video {
.video-player {
height: 363px;
}
.video-intro {
padding: 30px;
}
.video-title {
font-size: 36px;
color: #444;
margin-bottom: 30px;
}
.video-desc {
font-size: 28px;
color: #444;
}
.video-poster {
position: relative;
height: 363px;
color: #fff;
}
.video-meta-customers {
position: absolute;
top: 20px;
right: 30px;
font-size: 24px;
padding: 10px 20px;
border-radius: 50px;
background-color: rgba(0, 0, 0, 0.5);
}
}
.shop-hot {
.item {
position: relative;
}
... ... @@ -105,19 +66,19 @@
position: relative;
.item {
height: 234px;
width: 50%;
height: 375px;
float: left;
}
.item-info {
height: 70px;
display: flex;
justify-content: space-between;
align-items: center;
background-color: rgba(0, 0, 0, 0.5);
}
}
.items-3-2 {
width: 100%;
font-size: 18px;
overflow: hidden;
... ... @@ -139,10 +100,42 @@
.items-3-2-left .item {
float: left;
&:nth-child(2) {
background-color: #f5f7f6;
img {
width: auto;
}
}
&:nth-child(3) {
background-color: #f5f7f6;
img {
width: auto;
}
}
}
.items-3-2-right .item {
float: right;
&:nth-child(1) {
background-color: #f5f7f6;
img {
width: auto;
}
}
&:nth-child(2) {
background-color: #f5f7f6;
img {
width: auto;
}
}
}
/* 风格: 3图 3列 */
... ... @@ -165,6 +158,24 @@
}
}
.items-s4 {
.item {
float: left;
width: 25%;
height: 227.5px;
}
.item > a > img {
height: 187.5px;
}
.item-info {
text-align: center;
color: #000;
position: relative;
}
}
.items-small {
.item {
height: 250px;
... ... @@ -193,9 +204,74 @@
background-color: rgba(0, 0, 0, 0.5);
}
}
}
.shop-item-div {
height: 30px;
background-color: #f0f0f0;
.index-goods-container {
position: relative;
min-height: auto !important;
padding-left: 0.375rem;
padding-top: 0.2rem;
display: inline-block;
}
.shop-coupon {
background-color: #f0f0f0;
}
.shop-swiper {
position: relative;
width: 750px;
height: 234px;
overflow: hidden;
ul {
width: 100%;
}
}
.shop-video {
.video-player {
height: 363px;
}
.video-intro {
padding: 30px;
}
.video-title {
font-size: 36px;
color: #444;
margin-bottom: 30px;
}
.video-desc {
font-size: 28px;
color: #444;
}
.video-poster {
position: relative;
height: 363px;
color: #fff;
}
.video-meta-customers {
position: absolute;
top: 20px;
right: 30px;
font-size: 24px;
padding: 10px 20px;
border-radius: 50px;
background-color: rgba(0, 0, 0, 0.5);
}
}
.shop-item-div {
height: 30px;
background-color: #f0f0f0;
}
.margin-bottom {
width: 100%;
height: 40px;
}
}
... ...
... ... @@ -5,3 +5,5 @@
@import "reds-shop/header";
@import "reds-shop/nav-tab";
@import "reds-shop/section";
@import "reds-shop/nav";
@import "reds-shop/footer";
... ...
/*
* @Author: Targaryen
* @Date: 2017-03-23 11:02:31
* @Last Modified by: Targaryen
* @Last Modified time: 2017-03-31 16:57:27
*/
/* 红人店铺数据处理 */
const _ = require('lodash');
const helpers = global.yoho.helpers;
let countCarouselImage = 0; // 轮播图模块统计
/**
* 链接处理
* @param {*} linkParent
*/
const _linkhandle = (linkParent) => {
if (linkParent.linkType) {
switch (parseInt(linkParent.linkType, 10)) {
case 0:
return helpers.urlFormat('', {
categoryId: linkParent.resource
}, 'list');
case 1:
return helpers.urlFormat('/product/' + linkParent.resource + '.html');
case 2:
return linkParent.resource;
default:
break;
}
} else {
return false;
}
};
/**
* 图片处理
* @param {*} moduleData
*/
const _picsHandle = (moduleData) => {
let pics = [];
_.forEach(_.get(moduleData, 'data', []), value => {
let showProductInfo = false;
if (_.has(value, 'text') && value.text) {
if (_.has(value, 'showProductInfo')) {
showProductInfo = value.showProductInfo;
}
}
pics.push({
src: value.pic,
link: _linkhandle(value),
text: value.text,
showProductInfo: showProductInfo
});
});
return pics;
};
/**
* 红人店铺楼层数据处理工具
*/
const _tools = {
/**
* 模块标题
* @param {*} moduleData
*/
title(moduleData) {
return {
module_type: 'Title',
text: _.get(moduleData, 'data[0].text', ''),
isModuleMargin: _.get(moduleData, 'properties.isModuleMargin', 0),
link: _linkhandle(_.get(moduleData, 'data[0]', 0))
};
},
/**
* 视频模块
* @param {*} moduleData
*/
video(moduleData) {
return {
module_type: 'Video',
title: _.get(moduleData, 'data[0].text.title', ''),
content: _.get(moduleData, 'data[0].text.content', ''),
pic: _.get(moduleData, 'data[0].pic', ''),
isModuleMargin: _.get(moduleData, 'properties.isModuleMargin', 0),
};
},
/**
* 轮播图
* @param {*} moduleData
*/
carouselImage(moduleData) {
return {
module_type: 'CarouselImage',
num: countCarouselImage,
pics: _picsHandle(moduleData),
isModuleMargin: Boolean(_.get(moduleData, 'properties.isModuleMargin', 0)),
};
},
/**
* 一张图片
* @param {*} moduleData
*/
singleImage(moduleData) {
return {
module_type: 'SingleImage',
pics: [{
src: _.get(moduleData, 'data[0].pic', '')
}],
text: _.get(moduleData, 'data[0].text', ''),
width: _.get(moduleData, 'properties.width', ''),
height: _.get(moduleData, 'data[0].text', ''),
moduleHeight: _.get(moduleData, 'properties.moduleHeight', ''),
isModuleMargin: _.get(moduleData, 'properties.isModuleMargin', 0),
};
},
/**
* 两张图片
* @param {*} moduleData
*/
doubleImage(moduleData) {
return {
module_type: 'DoubleImage',
pics: _picsHandle(moduleData),
isModuleMargin: _.get(moduleData, 'properties.isModuleMargin', 0),
};
},
/**
* 三张图片
* @param {*} moduleData
*/
tripleImage(moduleData) {
let displayType = _.get(moduleData, 'properties.displayType', 0);
return {
module_type: 'TripleImage',
pics: _picsHandle(moduleData),
isModuleMargin: _.get(moduleData, 'properties.isModuleMargin', 0),
displayType: parseInt(displayType, 10),
};
},
/**
* 四张图片
* @param {*} moduleData
*/
fourImage(moduleData) {
return {
module_type: 'FourImage',
pics: _picsHandle(moduleData),
isModuleMargin: _.get(moduleData, 'properties.isModuleMargin', 0)
};
},
/**
* 商品列表
* @param {*} moduleData
*/
sknList(moduleData) {
let skns = '';
_.forEach(_.get(moduleData, 'data', []), value => {
skns += value + ',';
});
return {
module_type: 'SknList',
skns: skns,
};
}
};
/**
* 处理红人店铺楼层
* @param {*} decoratorsData
*/
const floor = (decoratorsData) => {
let finalData = [];
countCarouselImage = 0;
_.forEach(decoratorsData, value => {
try {
value.module_data = JSON.parse(value.module_data);
} catch (error) {
console.log(error);
}
switch (value.module_type) {
case 'Title':
finalData.push(_tools.title(value.module_data));
break;
case 'Video':
finalData.push(_tools.video(value.module_data));
break;
case 'CarouselImage':
countCarouselImage++;
finalData.push(_tools.carouselImage(value.module_data));
break;
case 'SingleImage':
finalData.push(_tools.singleImage(value.module_data));
break;
case 'DoubleImage':
finalData.push(_tools.doubleImage(value.module_data));
break;
case 'TripleImage':
finalData.push(_tools.tripleImage(value.module_data));
break;
case 'FourImage':
finalData.push(_tools.fourImage(value.module_data));
break;
case 'SknList':
finalData.push(_tools.sknList(value.module_data));
break;
default:
break;
}
});
return finalData;
};
/**
* 店铺介绍处理
* @param {*} params
*/
const shopIntro = (params) => {
if (params) {
params.shop_intro_link = helpers.urlFormat('/product/index/intro', {shop_id: params.shops_id});
}
return params;
};
/**
* 店铺分类处理
* @param {*} params
*/
const category = (params, shopId) => {
let categoryData = {
list: [],
url: ''
};
if (!params) {
return categoryData;
}
if (params.length > 6) {
categoryData.url = helpers.urlFormat('/product/index/category', {
shop_id: shopId
});
} else {
_.forEach(params, value => {
categoryData.list.push({
url: helpers.urlFormat('', {
shop_id: shopId,
sort: (value.relation_parameter && value.relation_parameter.sort) || ''
}, 'search'),
categoryId: value.category_id,
name: value.category_name
});
});
}
return categoryData;
};
module.exports = {
floor,
shopIntro,
category
};
... ...