Authored by 陈峰

Merge branch 'feature/group-home-correct' into 'release/6.9.2'

Feature/group home correct



See merge request !1737
... ... @@ -24,6 +24,30 @@ function index(req, res, next) {
}).catch(next);
}
function goodsTab(req, res, next) {
req.ctx(GroupService).goodsTab().then(result => {
return res.json({filterList: result.filterGroupList});
}).catch(next);
}
function newIndex(req, res, next) {
req.ctx(GroupService).newGroupIndex().then(result => {
console.log(result);
return res.render('group/newIndex', {
title: '有货福利团',
page: 'group',
localCss: true,
nodownload: true,
width750: true,
wechatShare: true,
floors: result.index,
tabs: result.tabData,
filterList: result.filterGroupList,
shareInfo: result.shareInfo
});
}).catch(next);
}
function groupListIndex(req, res, next) {
let params = Object.assign({}, req.query);
let uid = 0;
... ... @@ -369,6 +393,7 @@ function loadOrder(req, res, next) {
module.exports = {
index,
newIndex,
groupListIndex,
groupList,
progress,
... ... @@ -380,5 +405,6 @@ module.exports = {
filter,
searchList,
delOrder,
cancelOrder
cancelOrder,
goodsTab
};
... ...
... ... @@ -18,12 +18,33 @@ const contentCodes = {
}
} [isProd ? 'production' : 'test'];
const newContentCodes = {
test: {
home: 'd9101626ba774147080596e482e5f697'
},
production: {
home: 'd9101626ba774147080596e482e5f697'
}
} [isProd ? 'production' : 'test'];
class GroupService extends global.yoho.BaseModel {
constructor(ctx) {
super(ctx);
this.api = new GroupApi(ctx);
}
async newIndex() {
try {
const result = await this.api._getResourceCode({
contentCode: newContentCodes.home
});
return result;
} catch (e) {
throw new Error('Group index fail to load resources.');
}
}
async index() {
try {
const result = await this.api._getResourceCode({
... ... @@ -157,6 +178,48 @@ class GroupService extends global.yoho.BaseModel {
return result;
}
async newGroupIndex(tabIndex) {
let result = {};
let tabCurrentIndex = tabIndex || 0;
result.index = await this.newIndex();
let filters = [];
result.index.forEach(item => {
if (item.template_name === 'guessLike') {
filters = item.data;
}
});
filters.forEach(item => {
item.queryString = JSON.stringify(item.query);
});
let indexFilter = filters[tabCurrentIndex] || {};
let query = {};
console.log(filters);
console.log(indexFilter);
indexFilter.query.forEach(item => {
query = Object.assign(query, item);
});
result.filterGroupList = await this.filterGroupList({
...query,
joinLimit: null
});
return result;
}
async goodsTab(query, result = {}) {
result.filterGroupList = await this.filterGroupList({
...query,
joinLimit: null
});
return result;
}
async groupListIndex(params, uid) {
let result = {};
... ... @@ -255,6 +318,7 @@ class GroupService extends global.yoho.BaseModel {
val.sales_price = val.sales_price ? val.sales_price.toFixed(2) : '';
val.market_price = val.market_price ? val.market_price.toFixed(2) : '';
val.collagePrice = val.collagePrice ? val.collagePrice.toFixed(2) : '';
val.joinLimitStr = val.join_limit === 1 ? '邀新团' : '普通团';
});
}
return finalResult;
... ...
... ... @@ -383,8 +383,10 @@ router.post('/yoluck/detail/mylist.html', swtichYoLuck(yoluck.getActivityCodeLis
// 拼团
router.get('/group', group.index); // 拼团首页
router.get('/group/newIndex', group.newIndex); // 拼团首页
router.get('/group/list', group.groupListIndex); // 拼团列表页
router.get('/group/goods-list', group.groupList); // 拼团列表
router.get('/group/goods-tab', group.goodsTab);
router.get('/group/filter', group.filter); // 首页筛选结果页
router.get('/group/search', group.searchList); // 首页筛选列表
router.get('/group/progress', auth, group.progress); // 拼团状态详情页
... ...
<div class="group" data-share-img="{{shareInfo.bigImage}}" data-share-title="{{shareInfo.title}}" data-share-content="{{shareInfo.content}}">
<div class="resources">
<div class="floors">
{{#each floors}}
{{#ifcond template_name "==" 'focus'}}
{{> group/resources/focus}}
{{/ifcond}}
{{#ifcond template_name "==" 'newSingleImage'}}
{{> group/resources/new-single-image}}
{{/ifcond}}
{{#ifcond template_name "==" 'twoPicture'}}
{{> group/resources/two-image}}
{{/ifcond}}
{{#ifcond template_name "==" 'image_list'}}
{{> group/resources/four-image}}
{{/ifcond}}
{{#ifcond template_name "==" 'splitJointImg'}}
{{> group/resources/split-image}}
{{/ifcond}}
{{#ifcond template_name "==" 'collageBuyPrdList'}}
{{> group/resources/collage-buy-prd-list}}
{{/ifcond}}
{{#ifcond template_name "==" 'guessLike'}}
{{> group/resources/guess-like}}
{{/ifcond}}
{{/each}}
</div>
{{!-- <div id='fixedTab' class="tab-filter" data-group="{{#if tabs.joinLimit}}{{tabs.joinLimit}}{{/if}}">
{{#if tabs.showTab}}
<div class="tab group-tab">
<div class="tab-item">
<div class="tiptext active" data-channel="newGroup">邀新团</div>
</div>
<div class="tab-item">
<div class="tiptext" data-channel="normalGroup">普通团</div>
</div>
</div>
{{/if}}
{{> group/resources/filter-tab}}
</div> --}}
<div id="goodsContainer" class="goods-container">
{{#if filterList.length}}
<div class="new-goods-list">
{{#each filterList}}
{{> group/resources/new-index-filter-list-item}}
{{/each}}
</div>
{{/if}}
</div>
{{!-- {{> group/resources/filter-page}} --}}
</div>
<a class="bottom" href="/activity/group/order">我的拼团</a>
</div>
\ No newline at end of file
... ...
{{#data.data}}
{{#if prdList}}
<div class="resource-collage-buy-prd-list">
{{#each prdList}}
<div id="{{../../template_id}}" name="{{../../template_intro}}" class="product-item" data-product-skn="{{productSkn}}"
data-activity-id="{{activityId}}">
<div class="product-image-bg">
<img src="{{image2 defaultImages w=188 h=250 q=60 mode=3}}"></img>
</div>
<div class="product-name">{{brandName}}</div>
<div class='product-price-wrap'>
<span class='product-price'>{{formatCollagePrice}}</span>
<span class='product-market-price'>{{marketPrice}}</span>
{{#data}}
{{#ifcond layout_float "==" 'H'}}
{{#if data.prdList}}
<div class="resource-collage-buy-prd-list">
{{#each data.prdList}}
<div id="{{../../template_id}}" name="{{../../template_intro}}" class="product-item" data-product-skn="{{productSkn}}"
data-activity-id="{{activityId}}">
<div class="product-image-bg">
<img src="{{image2 defaultImages w=188 h=250 q=60 mode=3}}"></img>
</div>
<div class="product-name">{{brandName}}</div>
<div class='product-price-wrap'>
<span class='product-price'>{{formatCollagePrice}}</span>
<span class='product-market-price'>{{marketPrice}}</span>
</div>
<div class='product-joinnum'>{{collagedPersonNum}} 人已拼</div>
</div>
{{/each}}
</div>
{{/if}}
{{/ifcond}}
{{#ifcond layout_float '==' 'C'}}
{{#if data.prdList}}
<div class="resource-collage-buy-prd-list-c" data-prd-list-length="{{data.prdList.length}}">
<div class="collage-buy-title">{{../template_intro}}</div>
<div class="swiper-container">
<div class="swiper-wrapper">
{{#each data.prdList}}
<div class="swiper-slide" data-product-skn="{{productSkn}}"
data-activity-id="{{activityId}}">
<div class="product-image-bg">
<img src="{{image2 defaultImages w=188 h=250 q=60 mode=3}}"></img>
</div>
<div class="product-name">{{brandName}}</div>
<div class='product-price-wrap'>
<span class='product-people-number'>{{joinPeopleNum}}人团</span>
<span class='product-price'>{{formatCollagePrice}}</span>
</div>
{{#if collagedPersonNum}}
<div class="product-price-wrap">
<span class="product-sell-number">已拼{{collagedPersonNum}}</span>
</div>
{{/if}}
</div>
{{/each}}
</div>
<div class="swiper-pagination"></div>
</div>
<div class='product-joinnum'>{{collagedPersonNum}} 人已拼</div>
</div>
{{/each}}
</div>
{{/if}}
{{/data.data}}
\ No newline at end of file
{{/if}}
{{/ifcond}}
{{/data}}
\ No newline at end of file
... ...
<div class="guess-like">
<div class="wapper">
<div class="guess-scroll">
{{#each data}}
<div class="guess-tab" data-query="{{queryString}}">
<img src="{{image2 src w=160 h=80 q=60 mode=3}}" />
</div>
{{/each}}
</div>
</div>
</div>
\ No newline at end of file
... ...
<div class="new-index-filter-list-item" data-activity-id="{{activity_id}}" data-product-skn="{{product_skn}}">
<div class="group-product-header">
{{#ifcond joinLimitStr "==" "邀新团"}}
<div class="new-group-product-left-icon">
<span class="new-group-product-left-icon-number"></span>
</div>
{{/ifcond}}
{{#if @root.lazyLoad}}
<img class="lazy new-group-product-image" data-original="{{image2 default_images w=400 h=390 q=60 mode=3}}" />
{{else}}
<img class="new-group-product-image" src="{{image2 default_images w=400 h=390 q=60 mode=3}}" />
{{/if}}
</div>
<div class="new-group-product-info-bg">
<div class="new-group-product-name">{{product_name}}</div>
<div class="new-group-price">
<div class="group-free-number">
<div class="new-group-free-post"></div>
<div class="new-group-number forcefontsize10">已拼{{joinPeopleNum}}</div>
</div>
<div class="new-group-prict-bg">
<div class="new-group-number-price">
<span class="new-group-people-numer">{{people_num}}人团</span>
<span class="new-group-price-collage">{{collage_price_str}}</span>
</div>
<div class="new-market-button">
<span class="new-group-price-market">单人价{{market_price_str}}</span>
<div class="go-group-product"></div>
</div>
</div>
</div>
</div>
</div>
... ...
{
"name": "yohobuywap-node",
"version": "6.9.0-4",
"version": "6.9.2-1",
"private": true,
"description": "A New Yohobuy Project With Express",
"repository": {
... ...
<div class="new-index-filter-list-item" data-activity-id="{{activity_id}}" data-product-skn="{{product_skn}}">
<div class="group-product-header">
{{#ifcond joinLimitStr "==" "邀新团"}}
<div class="new-group-product-left-icon">
<span class="new-group-product-left-icon-number"></span>
</div>
{{/ifcond}}
{{#if @root.lazyLoad}}
<img class="lazy new-group-product-image" data-original="{{image2 default_images w=400 h=390 q=60 mode=3}}" />
{{else}}
<img class="new-group-product-image" src="{{image2 default_images w=400 h=390 q=60 mode=3}}" />
{{/if}}
</div>
<div class="new-group-product-info-bg">
<div class="new-group-product-name">{{product_name}}</div>
<div class="new-group-price">
<div class="group-free-number">
<div class="new-group-free-post"></div>
<div class="new-group-number forcefontsize10">已拼{{joinPeopleNum}}</div>
</div>
<div class="new-group-prict-bg">
<div class="new-group-number-price">
<span class="new-group-people-numer">{{people_num}}人团</span>
<span class="new-group-price-collage">{{collage_price_str}}</span>
</div>
<div class="new-market-button">
<span class="new-group-price-market">单人价{{market_price_str}}</span>
<div class="go-group-product"></div>
</div>
</div>
</div>
</div>
</div>
... ...
... ... @@ -8,6 +8,7 @@ import lazyLoad from 'yoho-jquery-lazyload';
import innerScroll from 'js/plugin/inner-scroll';
import sharePlugin from 'js/common/share';
const querystring = require('querystring');
let groupListItem = require('hbs/activity/group/group-list-product.hbs');
class Group extends Page {
constructor() {
... ... @@ -20,7 +21,10 @@ class Group extends Page {
groupTab: $('.group-tab'),
filterTab: $('.filter-nav'),
groupListContent: $('.goods-list'),
resourceList: $('.resource-collage-buy-prd-list')
resourceList: $('.resource-collage-buy-prd-list'),
resourceListC: $('.resource-collage-buy-prd-list-c'),
goodsList: $('.new-goods-list'),
guessLike: $('.guess-tab')
};
this.shareData = {
shareImgUrl: $('.group').data('share-img'),
... ... @@ -74,6 +78,7 @@ class Group extends Page {
this.shareInfo();
this.bindEvents();
this.swiperTop();
this.swiperGroup();
this.filterInit();
let self = this;
... ... @@ -147,6 +152,9 @@ class Group extends Page {
this.selector.filterTab.on('click', 'li', this.filterTabChange.bind(this));
this.selector.groupListContent.on('click', '.group-product-cell', this.checkDetail.bind(this));
this.selector.resourceList.on('click', '.product-item', this.checkDetail.bind(this));
this.selector.resourceListC.on('click', '.swiper-slide', this.checkDetail.bind(this));
this.selector.goodsList.on('click', '.new-index-filter-list-item', this.checkDetail.bind(this));
this.selector.guessLike.on('click', this.guessLikeTabChange.bind(this));
}
fixedTab() {
let listHeight = this.selector.groupListContent.height();
... ... @@ -169,6 +177,26 @@ class Group extends Page {
window.location.href = `/activity/group/detail?activityId=${activityId}&productSkn=${productSkn}`;
}
guessLikeTabChange(e) {
let $this = $(e.currentTarget);
let query = $this.data('query');
let queryObject = {};
query.forEach(item => {
queryObject = Object.assign(queryObject, item);
});
$.ajax({
type: 'GET',
url: '/activity/group/goods-tab',
data: queryObject,
success: (data) => {
// $('.filter-mask').remove();
// $('.group').append(data);
this.renderMoreData(data.filterList || []);
}
});
}
// 筛选tab切换
filterTabChange(e) {
let $this = $(e.currentTarget);
... ... @@ -282,6 +310,18 @@ class Group extends Page {
this.search();
}
swiperGroup() {
if ($('.resource-collage-buy-prd-list-c').data('prd-list-length') > 0) {
new Swiper('.swiper-container', {
slidesPerView: 3,
spaceBetween: 20,
slidesPerGroup: 3,
pagination: '.swiper-pagination',
paginationClickable: true,
});
}
}
// 顶部swiper
swiperTop() {
if ($('.banner-swiper').find('li').size() > 1) {
... ... @@ -430,6 +470,15 @@ class Group extends Page {
}
}
renderMoreData(list) {
let appendHtml = '';
list.forEach(item => {
appendHtml += groupListItem(item);
});
$('.new-goods-list').html(appendHtml);
}
// 筛选初始化
filterInit() {
let selectedChannel = this.selectedChannel;
... ...
.resource-collage-buy-prd-list-c {
margin-left: 20px;
margin-right: 20px;
margin-top: 20px;
margin-bottom: 10px;
background: white;
border-radius: 10px;
.collage-buy-title {
font-family: PingFang-SC-Semibold, sans-serif;
font-size: 32px;
color: #444;
padding-top: 20px;
padding-left: 20px;
padding-bottom: 20px;
}
.swiper-container {
height: 450px;
margin-left: 20px;
margin-right: 20px;
}
.swiper-pagination .swiper-pagination-bullet-active {
background: #444;
}
.swiper-slide {
text-align: center;
font-size: 18px;
height: 88%;
.product-image-bg {
height: 250px;
overflow: hidden;
}
.product-name {
font-family: PingFang-SC-Regular, sans-serif;
color: #222;
text-align: left;
font-size: 22px;
padding-bottom: 20px;
padding-top: 20px;
overflow: hidden;
text-overflow: ellipsis;
height: 80px;
}
.product-price-wrap {
text-align: left;
}
.product-price {
letter-spacing: 0;
font-weight: 500;
font-family: BrownStd-Bold, sans-serif;
font-size: 30px;
color: #d0021b;
}
.product-people-number {
font-family: PingFangSC-Regular, sans-serif;
font-size: 22px;
color: #d0021b;
letter-spacing: 0;
}
.product-sell-number {
font-family: PingFangSC-Regular, sans-serif;
font-size: 11px;
color: #b0b0b0;
}
.product-market-price {
font-size: 18px;
color: #b0b0b0;
letter-spacing: 0;
margin-left: 10px;
text-decoration: line-through;
}
}
}
.resource-collage-buy-prd-list {
width: 100%;
height: 440px;
... ...
.guess-like {
overflow: hidden;
height: 80px;
.wapper {
overflow-x: scroll;
-ms-overflow-style: none;
overflow: -moz-scrollbars-none;
.guess-scroll {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
width: auto;
min-width: 100%;
.guess-tab {
min-width: 160px;
}
}
}
.wapper::-webkit-scrollbar { width: 0 !important; }
}
... ...
... ... @@ -5,8 +5,10 @@
@import "floor/two-image";
@import "floor/split-image";
@import "floor/collage-buy-list";
@import "floor/guess-like";
@import "tabs";
@import "filter-list";
@import "new-filter-list";
.group {
.resources {
... ... @@ -31,6 +33,7 @@
.floors {
border-bottom: 10px solid #f0f0f0;
background: #f0f0f0;
}
.tab {
... ...
.goods-container {
background: #f0f0f0;
}
.new-goods-list {
display: flex;
flex-direction: column;
margin: 0 20px;
}
.new-index-filter-list-item:first-child {
margin-top: 0;
}
.new-index-filter-list-item {
background: white;
flex: 1;
display: flex;
margin-bottom: 10px;
margin-top: 10px;
.new-group-product-image {
margin: 20px;
width: 162px;
height: 220px;
}
.new-group-product-info-bg {
flex-grow: 1;
display: flex;
flex-direction: column;
justify-content: space-between;
margin-bottom: 20px;
}
.new-group-product-name {
margin-top: 20px;
margin-right: 20px;
font-family: PingFang-SC-Regular, sans-serif;
color: #222;
letter-spacing: 0;
line-height: 36px;
height: 56px;
font-size: 24px;
display: -webkit-box;
overflow: hidden;
text-overflow: ellipsis;
word-wrap: break-word;
white-space: normal !important;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}
.new-group-free-post {
width: 60px;
height: 38px;
background: url("img/activity/group/group/new-free-post@3x.png") no-repeat;
background-size: contain;
margin-right: 20px;
}
.new-market-button {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: flex-end;
}
.go-group-product {
width: 160px;
height: 60px;
background: url("img/activity/group/group/go-group@3x.png") no-repeat;
background-size: contain;
left: -5px;
}
.group-free-number {
display: flex;
flex-direction: row;
align-items: flex-start;
}
.new-group-number {
font-family: PingFang-SC-Regular, sans-serif;
letter-spacing: 0;
box-sizing: border-box;
height: 30px;
line-height: 30px;
padding-left: 20px;
padding-right: 20px;
border-radius: 15px;
border: 0.5px #222 solid;
color: #222;
}
.forcefontsize10 {
display: inline-block;
font-size: 12px;
-webkit-text-size-adjust: none;
transform: scale(0.83, 0.83);
}
.new-group-prict-bg {
display: flex;
flex-direction: column;
font-size: 22px;
}
.new-group-price {
display: flex;
flex-direction: column;
justify-content: space-between;
flex-grow: 1;
margin-right: 20px;
}
.new-group-number-price {
color: #d0021b;
}
.new-group-price-collage {
margin-left: 20px;
font-size: 36px;
}
.new-group-price-market {
font-family: PingFang-SC-Regular, sans-serif;
font-size: 12px;
color: #b0b0b0;
}
.new-group-product-left-icon {
position: absolute;
top: 40px;
width: 88px;
height: 40px;
left: 0;
font-size: 22px;
background: url("img/activity/group/group/Rectangle@3x.png") no-repeat;
background-size: contain;
}
.new-group-product-left-icon-number {
display: inline-block;
color: #fff;
font-size: 22px;
margin-left: 12px;
margin-top: 5px;
}
}
... ...