Authored by huangyCode

Merge branch 'feature/group-buy' of http://git.yoho.cn/fe/yohobuywap-node into feature/group-buy

@@ -58,7 +58,17 @@ function groupList(req, res, next) { @@ -58,7 +58,17 @@ function groupList(req, res, next) {
58 }); 58 });
59 }).catch(next); 59 }).catch(next);
60 } 60 }
  61 +function filter(req, res, next) {
  62 + let params = Object.assign({}, req.query);
61 63
  64 + req.ctx(GroupService).filterData(params).then((result) => {
  65 + res.render('group/filter', {
  66 + layout: false,
  67 + params: params,
  68 + filter: result
  69 + });
  70 + }).catch(next);
  71 +}
62 function progress(req, res, next) { 72 function progress(req, res, next) {
63 const uid = req.user.uid; 73 const uid = req.user.uid;
64 const groupNo = req.query.groupNo; 74 const groupNo = req.query.groupNo;
@@ -152,5 +162,6 @@ module.exports = { @@ -152,5 +162,6 @@ module.exports = {
152 groupList, 162 groupList,
153 progress, 163 progress,
154 goodsDetail, 164 goodsDetail,
155 - order 165 + order,
  166 + filter
156 }; 167 };
@@ -79,6 +79,24 @@ class GroupApi extends global.yoho.BaseModel { @@ -79,6 +79,24 @@ class GroupApi extends global.yoho.BaseModel {
79 })); 79 }));
80 } 80 }
81 81
  82 + _getFilterData(params) {
  83 + let option = {
  84 + data: {
  85 + method: 'app.collage.filter',
  86 + ...params
  87 + },
  88 + param: {
  89 + code: 200
  90 + }
  91 + };
  92 +
  93 + return this.get(option).then((result => {
  94 + let filterData = result.data;
  95 +
  96 + return filterData;
  97 + }));
  98 + }
  99 +
82 /** 100 /**
83 * 拼团详情 101 * 拼团详情
84 * @param uid 102 * @param uid
1 const GroupApi = require('./group-api'); 1 const GroupApi = require('./group-api');
2 const _ = require('lodash'); 2 const _ = require('lodash');
  3 +const filterProcess = require('../../../utils/group-filter-process');
3 4
4 class GroupService extends global.yoho.BaseModel { 5 class GroupService extends global.yoho.BaseModel {
5 constructor(ctx) { 6 constructor(ctx) {
@@ -20,7 +21,11 @@ class GroupService extends global.yoho.BaseModel { @@ -20,7 +21,11 @@ class GroupService extends global.yoho.BaseModel {
20 } 21 }
21 22
22 23
23 - async groupResult({groupNo, activityId, uid} = {}) { 24 + async groupResult({
  25 + groupNo,
  26 + activityId,
  27 + uid
  28 + } = {}) {
24 try { 29 try {
25 const [detail, recommend] = await Promise.all([ 30 const [detail, recommend] = await Promise.all([
26 this.api.groupDetail({ 31 this.api.groupDetail({
@@ -66,7 +71,12 @@ class GroupService extends global.yoho.BaseModel { @@ -66,7 +71,12 @@ class GroupService extends global.yoho.BaseModel {
66 } 71 }
67 } 72 }
68 73
69 - async groupResultRec({activityId, uid, page, limit} = {}) { 74 + async groupResultRec({
  75 + activityId,
  76 + uid,
  77 + page,
  78 + limit
  79 + } = {}) {
70 try { 80 try {
71 const recommend = await this.api.activityRecommend({ 81 const recommend = await this.api.activityRecommend({
72 uid, 82 uid,
@@ -97,6 +107,11 @@ class GroupService extends global.yoho.BaseModel { @@ -97,6 +107,11 @@ class GroupService extends global.yoho.BaseModel {
97 } 107 }
98 return tabsData; 108 return tabsData;
99 } 109 }
  110 + async filterData(params) {
  111 + let result = await this.api._getFilterData(params);
  112 +
  113 + return filterProcess.processFilter(result.filter || []);
  114 + }
100 115
101 async filterGroupList(params) { 116 async filterGroupList(params) {
102 const initParams = { 117 const initParams = {
@@ -369,6 +369,7 @@ router.post('/yoluck/detail/mylist.html', yoluck.getActivityCodeList); @@ -369,6 +369,7 @@ router.post('/yoluck/detail/mylist.html', yoluck.getActivityCodeList);
369 router.get('/group', group.index); // 拼团首页 369 router.get('/group', group.index); // 拼团首页
370 router.get('/group/list', group.groupListIndex); // 拼团列表页 370 router.get('/group/list', group.groupListIndex); // 拼团列表页
371 router.get('/group/goods-list', group.groupList); // 拼团列表 371 router.get('/group/goods-list', group.groupList); // 拼团列表
  372 +router.get('/group/filter', group.filter); // 首页筛选结果
372 router.get('/group/progress', auth, group.progress); // 拼团状态详情页 373 router.get('/group/progress', auth, group.progress); // 拼团状态详情页
373 router.get('/group/goodsDetail', group.goodsDetail); 374 router.get('/group/goodsDetail', group.goodsDetail);
374 router.get('/group/order', auth, group.order); // 我的拼团 375 router.get('/group/order', auth, group.order); // 我的拼团
  1 +{{> group/resources/filter-page}}
@@ -23,7 +23,6 @@ @@ -23,7 +23,6 @@
23 {{/each}} 23 {{/each}}
24 </div> 24 </div>
25 <div id='fixedTab' class="tab-filter"> 25 <div id='fixedTab' class="tab-filter">
26 - {{!-- {{#if floatTab}} float{{/if}}{{#if !tabs.showTab}} only-filter{{/if}} --}}  
27 {{#if tabs.showTab}} 26 {{#if tabs.showTab}}
28 <div class="tab group-tab"> 27 <div class="tab group-tab">
29 <div class="tab-item"> 28 <div class="tab-item">
@@ -46,7 +45,7 @@ @@ -46,7 +45,7 @@
46 </div> 45 </div>
47 {{/if}} 46 {{/if}}
48 47
49 - {{> common/filter}} 48 + {{!-- {{> group/resources/filter-page}} --}}
50 </div> 49 </div>
51 <a class="bottom" href="/activity/group/order">我的拼团</a> 50 <a class="bottom" href="/activity/group/order">我的拼团</a>
52 51
@@ -4,62 +4,69 @@ @@ -4,62 +4,69 @@
4 <div class="inner-card go-join" data-product-skn="{{yourJoinItem.productSkn}}" 4 <div class="inner-card go-join" data-product-skn="{{yourJoinItem.productSkn}}"
5 data-activity-id="{{activityId}}" data-group-no="{{groupNo}}" data-page-go="{{pageGo}}"> 5 data-activity-id="{{activityId}}" data-group-no="{{groupNo}}" data-page-go="{{pageGo}}">
6 <img src="{{image2 yourJoinItem.productIcon w=200 h=282}}" alt="" class="card-pre-img"> 6 <img src="{{image2 yourJoinItem.productIcon w=200 h=282}}" alt="" class="card-pre-img">
7 - <div class="info" > 7 + <div class="info">
8 <div class="name">{{yourJoinItem.productName}}</div> 8 <div class="name">{{yourJoinItem.productName}}</div>
9 <div class="group-price">{{yourJoinItem.productGroupPrice}}</div> 9 <div class="group-price">{{yourJoinItem.productGroupPrice}}</div>
10 <div class="single-buy-price">单人购买:<span class="line-through">{{yourJoinItem 10 <div class="single-buy-price">单人购买:<span class="line-through">{{yourJoinItem
11 .productSalePrice}}</span></div> 11 .productSalePrice}}</span></div>
12 </div> 12 </div>
13 </div> 13 </div>
14 -  
15 - <div class="members">  
16 - {{#membershipItems}}  
17 - {{#if empty}}  
18 - <div class="meb-item empty"></div>  
19 - {{else}}  
20 - <div class="meb-item">  
21 - <img class="avatar" src="{{image2 headUrl w=160 h=160}}" alt="">  
22 - {{#if @first}}  
23 - <span class="leader-badge"></span> 14 + <div class="card-body">
  15 + <div class="members">
  16 + {{#membershipItems}}
  17 + {{#if empty}}
  18 + <div class="meb-item empty"></div>
  19 + {{else}}
  20 + <div class="meb-item">
  21 + <img class="avatar" src="{{image2 headUrl w=160 h=160}}" alt="">
  22 + {{#if @first}}
  23 + <span class="leader-badge"></span>
  24 + {{/if}}
  25 + </div>
24 {{/if}} 26 {{/if}}
  27 + {{/membershipItems}}
25 </div> 28 </div>
26 - {{/if}}  
27 - {{/membershipItems}}  
28 - </div>  
29 29
30 - {{#ifcond pageGo '===' 1}}  
31 - <div class="status-text">还差{{lackNum}}人拼团成功,剩余时间</div>  
32 - <div class="status-btn positive">邀请小伙伴拼团</div>  
33 - {{/ifcond}} 30 + {{#ifcond pageGo '===' 1}}
  31 + <div class="status-tip">还差<span class="red">{{lackNum}}</span>拼团成功,剩余时间</div>
  32 + {{> group/progress-countdown}}
  33 + <div class="status-btn positive">邀请小伙伴拼团{{#ifcond joinLimit '==' 1}}(仅限新人){{/ifcond}}</div>
  34 + {{/ifcond}}
34 35
35 - {{#ifcond pageGo '===' 2}}  
36 - <div class="status-text">还差{{lackNum}}人拼团成功,剩余时间</div>  
37 - {{/ifcond}} 36 + {{#ifcond pageGo '===' 2}}
  37 + <div class="status-tip">还差<span class="red">{{lackNum}}</span>拼团成功,剩余时间</div>
  38 + {{> group/progress-countdown}}
  39 + <div class="status-btn positive">去参团</div>
  40 + {{/ifcond}}
38 41
39 - {{#ifcond pageGo '===' 3}}  
40 - <div class="status-text">还差{{lackNum}}人拼团成功,剩余时间</div>  
41 - <div class="status-btn positive">邀请小伙伴拼团</div>  
42 - {{/ifcond}} 42 + {{#ifcond pageGo '===' 3}}
  43 + <div class="status-tip">还差<span class="red">{{lackNum}}</span>拼团成功,剩余时间</div>
  44 + {{> group/progress-countdown}}
  45 + <div class="status-btn positive">邀请小伙伴拼团{{#ifcond joinLimit '==' 1}}(仅限新人){{/ifcond}}</div>
  46 + {{/ifcond}}
43 47
44 - {{#ifcond pageGo '===' 4}}  
45 - <div class="status-text">拼团成功</div>  
46 - {{/ifcond}} 48 + {{#ifcond pageGo '===' 4}}
  49 + <div class="status-text">拼团成功</div>
  50 + <div class="status-btn">查看更多拼团活动</div>
  51 + {{/ifcond}}
47 52
48 - {{#ifcond pageGo '===' 5}}  
49 - <div class="status-text">你来晚了 你的好友拼团已经成功</div>  
50 - {{/ifcond}} 53 + {{#ifcond pageGo '===' 5}}
  54 + <div class="status-text">你来晚了 你的好友拼团已经成功</div>
  55 + <div class="status-btn positive">我也要开团</div>
  56 + {{/ifcond}}
51 57
  58 + {{#ifcond pageGo '===' 6}}
  59 + <div class="status-text">拼团失败</div>
  60 + <div class="status-btn">查看更多拼团活动</div>
  61 + {{/ifcond}}
52 62
53 - {{#ifcond pageGo '===' 6}}  
54 - <div class="status-text">拼团失败</div>  
55 - {{/ifcond}} 63 + {{#ifcond pageGo '===' 7}}
  64 + <div class="status-text">拼团失败</div>
  65 + <div class="status-btn">查看更多拼团活动</div>
  66 + {{/ifcond}}
56 67
57 - {{#ifcond pageGo '===' 7}}  
58 - <div class="status-text">拼团失败</div>  
59 - <div class="status-btn">查看更多拼团活动</div>  
60 - {{/ifcond}}  
61 -  
62 - <a class="tip" href="http://m.yohobuy.com/activity/group">支付开团-支付参团-凑齐人数发货-凑不齐退款 玩法介绍》</a> 68 + <a class="tip" href="http://m.yohobuy.com/activity/group">支付开团-支付参团-凑齐人数发货-凑不齐退款 玩法介绍》</a>
  69 + </div>
63 </div> 70 </div>
64 {{/data}} 71 {{/data}}
65 <div class="divide"></div> 72 <div class="divide"></div>
  1 +<div class="count-down">
  2 + <span class="digit-square">1</span>
  3 + <span class="digit-square">1</span> :
  4 + <span class="digit-square">1</span>
  5 + <span class="digit-square">1</span> :
  6 + <span class="digit-square">1</span>
  7 + <span class="digit-square">1</span>
  8 +</div>
  1 +{{# filter}}
  2 +<div class="filter-mask hide">
  3 + <div class="filter-body">
  4 + <ul class="classify">
  5 + {{#each classify}}
  6 + <li class="classify-item{{#if @first}} active{{/if}}" data-bp-id="filter_classify_{{name}}_true">
  7 + <p class="shower{{#if default}} default{{/if}}">
  8 + <span class="title">{{title}}</span>
  9 + {{name}}
  10 + </p>
  11 + <ul class="sub-classify" data-type={{dataType}}>
  12 + {{# subs}}
  13 + <li class="sub-item{{#if chosed}} chosed{{/if}}" data-id={{dataId}}
  14 + data-bp-id="filter_subclassify_{{name}}_true">
  15 + {{name}}
  16 + <i class="iconfont chosed-icon">&#xe617;</i>
  17 + </li>
  18 + {{/ subs}}
  19 + </ul>
  20 + </li>
  21 + {{/each}}
  22 + </ul>
  23 + </div>
  24 + <div class="cancelBtn">取消</div>
  25 +</div>
  26 +{{/ filter}}
@@ -7,7 +7,7 @@ @@ -7,7 +7,7 @@
7 </li> --}} 7 </li> --}}
8 <li class="new active" data-type="new" data-order="s_t_desc"> 8 <li class="new active" data-type="new" data-order="s_t_desc">
9 <a href="javascript:void(0);"> 9 <a href="javascript:void(0);">
10 - <span class="span-test">新品</span> 10 + <span class="span-test">最新</span>
11 </a> 11 </a>
12 </li> 12 </li>
13 <li class="popularity" data-type="popularity" data-order="h_v_desc"> 13 <li class="popularity" data-type="popularity" data-order="h_v_desc">
@@ -2,10 +2,10 @@ import 'scss/activity/group/group.page.scss'; @@ -2,10 +2,10 @@ import 'scss/activity/group/group.page.scss';
2 import Swiper from 'yoho-swiper'; 2 import Swiper from 'yoho-swiper';
3 import $ from 'yoho-jquery'; 3 import $ from 'yoho-jquery';
4 import Page from 'js/yoho-page'; 4 import Page from 'js/yoho-page';
  5 +import filter from 'js/plugin/filter';
5 6
6 // import lazyLoad from 'yoho-jquery-lazyload'; 7 // import lazyLoad from 'yoho-jquery-lazyload';
7 // import tip from 'js/plugin/tip'; 8 // import tip from 'js/plugin/tip';
8 -// import filter from 'js/plugin/filter';  
9 // import loading from 'js/plugin/loading'; 9 // import loading from 'js/plugin/loading';
10 10
11 class Group extends Page { 11 class Group extends Page {
@@ -21,33 +21,35 @@ class Group extends Page { @@ -21,33 +21,35 @@ class Group extends Page {
21 }; 21 };
22 this.navInfo = { 22 this.navInfo = {
23 new: { 23 new: {
24 - order: 1,  
25 reload: true, 24 reload: true,
26 page: 1, 25 page: 1,
27 end: false 26 end: false
28 }, 27 },
29 popularity: { 28 popularity: {
30 - order: 1,  
31 reload: true, 29 reload: true,
32 - page: 1, 30 + page: 0,
33 end: false 31 end: false
34 }, 32 },
35 price: { 33 price: {
36 - order: 1, 34 + order: 's_p_asc',
37 reload: true, 35 reload: true,
38 page: 0, 36 page: 0,
39 end: false 37 end: false
40 } 38 }
41 }; 39 };
42 this.noResult = '<p class="no-result">未找到相关搜索结果</p>'; 40 this.noResult = '<p class="no-result">未找到相关搜索结果</p>';
43 - this.$pre = this.selector.filterTab.find('.active'); 41 +
  42 +
  43 +
44 this.selectedChannel = 'newGroup'; 44 this.selectedChannel = 'newGroup';
45 this.filterTab = { 45 this.filterTab = {
46 newGroup: { 46 newGroup: {
  47 + $pre: this.selector.filterTab.find('.active'), // 记录新团筛选tab的激活项
47 joinLimit: 1, 48 joinLimit: 1,
48 order: 's_t_desc' 49 order: 's_t_desc'
49 }, 50 },
50 normalGroup: { 51 normalGroup: {
  52 + $pre: this.selector.filterTab.find('.active'), // 记录普通团筛选tab的激活项
51 joinLimit: 2, 53 joinLimit: 2,
52 order: 's_t_desc' 54 order: 's_t_desc'
53 } 55 }
@@ -58,7 +60,7 @@ class Group extends Page { @@ -58,7 +60,7 @@ class Group extends Page {
58 }; 60 };
59 this.bindEvents(); 61 this.bindEvents();
60 this.swiperTop(); 62 this.swiperTop();
61 - 63 + this.filterInit();
62 $(window).scroll(() => { 64 $(window).scroll(() => {
63 window.requestAnimationFrame(this.scrollHandler.bind(this)); 65 window.requestAnimationFrame(this.scrollHandler.bind(this));
64 }); 66 });
@@ -94,38 +96,82 @@ class Group extends Page { @@ -94,38 +96,82 @@ class Group extends Page {
94 } 96 }
95 filterTabChange(e) { 97 filterTabChange(e) {
96 let $this = $(e.currentTarget); 98 let $this = $(e.currentTarget);
97 - let order = $this.data('order');  
98 let navType = $this.data('type'); 99 let navType = $this.data('type');
99 let currentChannel = this.selectedChannel; 100 let currentChannel = this.selectedChannel;
100 let nav = this.navInfo[navType]; 101 let nav = this.navInfo[navType];
101 102
102 - if ($this.hasClass('new') || $this.hasClass('popularity')) { 103 + // 筛选状态设置
  104 + if ($this.hasClass('filter')) {
  105 + if ($this.hasClass('active')) {
  106 + $('.filter-mask').addClass('hide');
  107 + $this.removeClass('active');
  108 +
  109 + } else {
  110 + $this.addClass('active');
  111 + filter.showFilter();
  112 + }
  113 + } else {
103 this.selector.filterTab.children('li').removeClass('active'); 114 this.selector.filterTab.children('li').removeClass('active');
104 $this.addClass('active'); 115 $this.addClass('active');
105 - this.filterTab[currentChannel].order = order; 116 + this.filterTab[currentChannel].$pre = $this;
  117 + }
106 118
107 - this.search(); 119 + // 最新和人气
  120 + if ($this.hasClass('new') || $this.hasClass('popularity')) {
  121 + nav.reload = true;
  122 + nav.order = $this.data('order');
  123 + this.filterTab[currentChannel].order = nav.order;
108 } 124 }
109 - if ($this.hasClass('price') || $this.hasClass('discount')) {  
110 125
111 - // 价格/折扣切换排序状态 126 + // 价格切换排序状态
  127 + if ($this.hasClass('price')) {
112 $this.find('.icon > .iconfont').toggleClass('cur'); 128 $this.find('.icon > .iconfont').toggleClass('cur');
113 - nav.reload = true; // 重置reload,HTML会被替换为逆序的HTML  
114 - nav.order = nav.order === 0 ? 1 : 0; // 切换排序 129 + nav.reload = true;
  130 + nav.order = nav.order === 's_p_asc' ? 's_p_desc' : 's_p_asc'; // 切换排序
  131 + this.filterTab[currentChannel].order = nav.order;
  132 + }
115 133
116 134
117 - } 135 + this.search();
118 } 136 }
119 137
120 groupTabChange(e) { 138 groupTabChange(e) {
121 let target = $(e.target); 139 let target = $(e.target);
122 let channel = target.data('channel'); 140 let channel = target.data('channel');
  141 + let navInfo = this.navInfo;
  142 + let filterTab = this.filterTab[channel];
123 143
  144 + // 切换tab
124 if (!target.hasClass('active')) { 145 if (!target.hasClass('active')) {
125 this.selector.groupTab.find('.tiptext').removeClass('active'); 146 this.selector.groupTab.find('.tiptext').removeClass('active');
126 target.addClass('active'); 147 target.addClass('active');
127 } 148 }
128 this.selectedChannel = channel; 149 this.selectedChannel = channel;
  150 +
  151 + // 筛选tab状态重置
  152 + for (let i in navInfo) {
  153 + if (navInfo.hasOwnProperty(i)) {
  154 + navInfo[i].reload = true;
  155 + navInfo[i].end = false;
  156 +
  157 + if (navInfo[i].hasOwnProperty('order')) {
  158 + navInfo[i].order = 's_p_asc';
  159 + }
  160 + }
  161 + }
  162 + this.selector.filterTab.children('li').removeClass('active');
  163 + filterTab.$pre.addClass('active');
  164 +
  165 + // 价格筛选状态设置
  166 + if (filterTab.$pre.hasClass('price')) {
  167 + navInfo.price.order = filterTab.order;
  168 + filterTab.$pre.find('.icon > .iconfont').removeClass('cur');
  169 + if (navInfo.price.order === 's_p_asc') {
  170 + filterTab.$pre.find('.icon > .up').addClass('cur');
  171 + } else {
  172 + filterTab.$pre.find('.icon > .down').addClass('cur');
  173 + }
  174 + }
129 this.search(); 175 this.search();
130 } 176 }
131 177
@@ -154,7 +200,7 @@ class Group extends Page { @@ -154,7 +200,7 @@ class Group extends Page {
154 search() { 200 search() {
155 let params = this.filterTab[this.selectedChannel]; 201 let params = this.filterTab[this.selectedChannel];
156 202
157 - console.log(params); 203 + console.log(params, this.navInfo.price);
158 204
159 // let setting; 205 // let setting;
160 206
@@ -176,35 +222,35 @@ class Group extends Page { @@ -176,35 +222,35 @@ class Group extends Page {
176 } 222 }
177 223
178 // 筛选初始化 224 // 筛选初始化
179 - // filterInit(option) {  
180 - // let $filterMask;  
181 -  
182 - // $.ajax({  
183 - // type: 'GET',  
184 - // url: '/product/sale/filter',  
185 - // data: $.extend(defaultOpt, {  
186 - // saleType: '1'  
187 - // }, option),  
188 - // success: function(data) {  
189 - // $filterMask && $filterMask.remove();  
190 -  
191 - // this.selector.groupListContent.append(data);  
192 -  
193 - // $filterMask = $('.filter-mask');  
194 -  
195 - // // 初始化filter&注册filter回调  
196 - // filter.initFilter({  
197 - // fCbFn: this.search,  
198 - // hCbFn: function() {  
199 - // // 切换active状态到$pre上  
200 - // this.$pre.addClass('active');  
201 - // this.$pre.siblings().removeClass('active');  
202 - // },  
203 - // missStatus: true  
204 - // });  
205 - // }  
206 - // });  
207 - // } 225 + filterInit() {
  226 + let $filterMask;
  227 + let requestParams = this.filterTab[this.selectedChannel];
  228 + let filterTab = this.selector.filterTab;
  229 +
  230 + delete requestParams.$pre;
  231 + console.log(requestParams);
  232 + $.ajax({
  233 + type: 'GET',
  234 + url: '/activity/group/filter',
  235 + data: requestParams,
  236 + success: function(data) {
  237 + $filterMask && $filterMask.remove();
  238 +
  239 + $('.group').append(data);
  240 +
  241 + $filterMask = $('.filter-mask');
  242 +
  243 + // 初始化filter&注册filter回调
  244 + filter.initFilter({
  245 + fCbFn: this.search,
  246 + hCbFn: function() {
  247 + filterTab.children('.filter').removeClass('active');
  248 + },
  249 + missStatus: true
  250 + });
  251 + }
  252 + });
  253 + }
208 } 254 }
209 255
210 $(() => { 256 $(() => {
@@ -4,47 +4,41 @@ @@ -4,47 +4,41 @@
4 .card { 4 .card {
5 position: relative; 5 position: relative;
6 width: 680px; 6 width: 680px;
7 - height: 690px;  
8 margin: 0 auto; 7 margin: 0 auto;
9 background: #fff; 8 background: #fff;
10 box-shadow: 0 0 20px rgba(205, 205, 205, 0.5); 9 box-shadow: 0 0 20px rgba(205, 205, 205, 0.5);
11 } 10 }
12 11
13 .status-text { 12 .status-text {
14 - position: absolute;  
15 - bottom: 250px;  
16 - left: 50%;  
17 - transform: translateX(-50%);  
18 font-size: 36px; 13 font-size: 36px;
19 color: #444; 14 color: #444;
20 - letter-spacing: -1px;  
21 text-align: center; 15 text-align: center;
22 font-weight: bold; 16 font-weight: bold;
23 } 17 }
24 18
25 .status-btn { 19 .status-btn {
26 - position: absolute;  
27 - bottom: 130px;  
28 - left: 50%; 20 + display: inline-block;
29 height: 80px; 21 height: 80px;
30 padding: 0 50px; 22 padding: 0 50px;
  23 + min-width: 380px;
  24 + margin-top: 40px;
31 font-size: 32px; 25 font-size: 32px;
32 color: #fff; 26 color: #fff;
33 text-align: center; 27 text-align: center;
34 line-height: 80px; 28 line-height: 80px;
35 border-radius: 40px; 29 border-radius: 40px;
36 background-color: #000; 30 background-color: #000;
37 - transform: translateX(-50%);  
38 31
39 &.positive { 32 &.positive {
40 background: #d0021b; 33 background: #d0021b;
  34 + margin-top: 60px;
41 } 35 }
42 } 36 }
43 37
44 .inner-card { 38 .inner-card {
45 position: absolute; 39 position: absolute;
46 left: 44px; 40 left: 44px;
47 - top: -140px; 41 + top: -128px;
48 width: 600px; 42 width: 600px;
49 height: 282px; 43 height: 282px;
50 background: #fff; 44 background: #fff;
@@ -80,44 +74,59 @@ @@ -80,44 +74,59 @@
80 } 74 }
81 } 75 }
82 76
  77 + .card-body {
  78 + position: relative;
  79 + width: 680px;
  80 + padding-top: 152px;
  81 + padding-bottom: 130px;
  82 + text-align: center;
  83 + }
  84 +
83 .members { 85 .members {
84 - position: absolute;  
85 - top: 194px;  
86 - left: 0;  
87 - right: 0; 86 + margin-top: 40px;
88 font-size: 0; 87 font-size: 0;
89 text-align: center; 88 text-align: center;
90 - }  
91 89
92 - .meb-item {  
93 - position: relative;  
94 - display: inline-block;  
95 - width: 80px;  
96 - height: 80px;  
97 - margin-left: 40px;  
98 - border-radius: 40px; 90 + .meb-item {
  91 + position: relative;
  92 + display: inline-block;
  93 + width: 80px;
  94 + height: 80px;
  95 + margin-left: 40px;
  96 + border-radius: 40px;
99 97
100 - &:first-child {  
101 - margin-left: 0;  
102 - } 98 + &:first-child {
  99 + margin-left: 0;
  100 + }
103 101
104 - &.empty {  
105 - background-image: url("img/activity/group/member-empty.png");  
106 - background-size: 80px 80px;  
107 - } 102 + &.empty {
  103 + background-image: url("img/activity/group/member-empty.png");
  104 + background-size: 80px 80px;
  105 + }
108 106
109 - .avatar {  
110 - border-radius: 40px; 107 + .avatar {
  108 + border-radius: 40px;
  109 + }
  110 +
  111 + .leader-badge {
  112 + position: absolute;
  113 + top: 0;
  114 + left: 0;
  115 + width: 80px;
  116 + height: 80px;
  117 + background-image: url("img/activity/group/member-leader.png");
  118 + background-size: 80px 80px;
  119 + }
111 } 120 }
  121 + }
112 122
113 - .leader-badge {  
114 - position: absolute;  
115 - top: 0;  
116 - left: 0;  
117 - width: 80px;  
118 - height: 80px;  
119 - background-image: url("img/activity/group/member-leader.png");  
120 - background-size: 80px 80px; 123 + .status-tip {
  124 + font-size: 24px;
  125 + margin-top: 38px;
  126 + margin-bottom: 20px;
  127 +
  128 + .red {
  129 + color: #d0021b;
121 } 130 }
122 } 131 }
123 132
@@ -128,6 +137,7 @@ @@ -128,6 +137,7 @@
128 left: 28px; 137 left: 28px;
129 font-size: 24px; 138 font-size: 24px;
130 color: #b0b0b0; 139 color: #b0b0b0;
  140 + text-align: left;
131 letter-spacing: -0.68px; 141 letter-spacing: -0.68px;
132 } 142 }
133 143
@@ -253,4 +263,16 @@ @@ -253,4 +263,16 @@
253 width: 104px; 263 width: 104px;
254 height: 110px; 264 height: 110px;
255 } 265 }
  266 +
  267 + .count-down {
  268 + .digit-square {
  269 + display: inline-block;
  270 + width: 36px;
  271 + height: 44px;
  272 + font-size: 28px;
  273 + color: #fff;
  274 + line-height: 44px;
  275 + background-color: #000;
  276 + }
  277 + }
256 } 278 }
@@ -34,6 +34,10 @@ @@ -34,6 +34,10 @@
34 &.cur { 34 &.cur {
35 color: #000; 35 color: #000;
36 } 36 }
  37 +
  38 + &.drop {
  39 + color: #000;
  40 + }
37 } 41 }
38 } 42 }
39 43
@@ -70,3 +74,117 @@ @@ -70,3 +74,117 @@
70 } 74 }
71 } 75 }
72 } 76 }
  77 +
  78 +.filter-mask {
  79 + position: fixed;
  80 + top: 0;
  81 + right: 0;
  82 + left: 0;
  83 + z-index: 2;
  84 + height: 100%;
  85 + background: rgba(0, 0, 0, 0.1);
  86 +}
  87 +
  88 +.cancel-btn {
  89 + position: absolute;
  90 + right: 0;
  91 + left: 0;
  92 + bottom: 0;
  93 + height: 80px;
  94 + line-height: 80px;
  95 + text-align: center;
  96 + z-index: 2;
  97 + background-color: #444;
  98 + color: #fff;
  99 +}
  100 +
  101 +.filter-body {
  102 + position: absolute;
  103 + top: 0;
  104 + right: 0;
  105 + left: 0;
  106 + bottom: 80px;
  107 + z-index: 2;
  108 + background: #fff;
  109 + color: #000;
  110 + font-size: 28px;
  111 + cursor: pointer;
  112 +
  113 + .classify {
  114 + width: 50%;
  115 + height: 100%;
  116 + background: #f8f8f8;
  117 +
  118 + > li {
  119 + height: 120px;
  120 + line-height: 120px;
  121 +
  122 + > * {
  123 + box-sizing: border-box;
  124 + }
  125 +
  126 + &.active {
  127 + background: #fff;
  128 + }
  129 +
  130 + .shower {
  131 + overflow: hidden;
  132 + padding-left: 40px;
  133 + width: 100%;
  134 + color: #333;
  135 + text-overflow: ellipsis;
  136 + white-space: nowrap;
  137 +
  138 + &.highlight {
  139 + background: #eee;
  140 + }
  141 + }
  142 +
  143 + .default {
  144 + color: #999;
  145 + }
  146 +
  147 + .title {
  148 + float: left;
  149 + color: #000;
  150 + }
  151 + }
  152 + }
  153 +
  154 + .sub-classify {
  155 + position: absolute;
  156 + top: 0;
  157 + left: 50%;
  158 + display: none;
  159 + overflow: auto;
  160 + -webkit-overflow-scrolling: touch;
  161 + width: 50%;
  162 + height: 880px;
  163 +
  164 + > li {
  165 + overflow: hidden;
  166 + padding-left: 30px;
  167 + height: 120px;
  168 + border-bottom: 1px solid #e6e6e6;
  169 + text-overflow: ellipsis;
  170 + white-space: nowrap;
  171 + line-height: 120px;
  172 +
  173 + &.highlight {
  174 + background: #eee;
  175 + }
  176 + }
  177 +
  178 + .chosed-icon {
  179 + display: none;
  180 + }
  181 +
  182 + .chosed .chosed-icon {
  183 + display: inline;
  184 + }
  185 + }
  186 +
  187 + .active > .sub-classify {
  188 + display: block;
  189 + }
  190 +}
  1 +const _ = require('lodash');
  2 +
  3 +const toArray = (obj) => {
  4 + if (_.isArray(obj)) {
  5 + return obj;
  6 + }
  7 + let arr = [];
  8 +
  9 + _.forEach(obj, (v, k) => {
  10 + if (_.isObject(v)) {
  11 + v._key = k;
  12 + } else {
  13 + v = {
  14 + _key: k,
  15 + _value: v
  16 + };
  17 + }
  18 + arr.push(v);
  19 + });
  20 +
  21 + return arr;
  22 +};
  23 +
  24 +/**
  25 + * 按照数组中指定字段排序二维数组
  26 + *
  27 + * @param array list 需要排序的数组
  28 + * @param string key 字段名称
  29 + * @param boolean 有 desc 时候降序排列,默认为false
  30 + */
  31 +const _sortListByField = (list, key, desc) => {
  32 + let array = toArray(list);
  33 +
  34 + return array.sort(function(a, b) {
  35 + a = a._key.split(',')[0] * 1;
  36 + b = b._key.split(',')[0] * 1;
  37 + return desc ? a < b : a > b;
  38 + });
  39 +};
  40 +
  41 +/**
  42 + * 处理筛选数据
  43 + * @param list
  44 + * @param string | options
  45 + * @return array 处理之后的筛选数据
  46 + */
  47 +exports.processFilter = (list, options) => {
  48 + const filters = {
  49 + classify: []
  50 + };
  51 +
  52 + const filtersType = {
  53 + brand: {
  54 + name: '所有品牌',
  55 + title: '品牌',
  56 + dataId: 'id',
  57 + subsName: 'brand_name',
  58 + firstSub: 0,
  59 + dataType: 'brand',
  60 + sortNum: '1'
  61 + },
  62 + color: {
  63 + name: '所有颜色',
  64 + title: '颜色',
  65 + dataId: 'color_id',
  66 + subsName: 'color_name',
  67 + firstSub: 0,
  68 + dataType: 'color',
  69 + sortNum: '4'
  70 + },
  71 + discount: {
  72 + name: '所有商品',
  73 + title: '折扣',
  74 + dataId: 'key',
  75 + subsName: 'name',
  76 + firstSub: '0,1',
  77 + dataType: 'p_d',
  78 + sortNum: '7'
  79 + },
  80 + gender: {
  81 + name: '所有性别',
  82 + title: '性别',
  83 + dataId: 'key',
  84 + subsName: 'flag',
  85 + firstSub: '1,2,3',
  86 + dataType: 'gender',
  87 + sortNum: '0'
  88 + },
  89 + group_sort: {
  90 + name: '所有品类',
  91 + title: '品类',
  92 + dataId: 'relation_parameter',
  93 + subsName: 'category_name',
  94 + firstSub: 0,
  95 + dataType: 'sort',
  96 + sortNum: '3'
  97 + },
  98 + priceRange: {
  99 + name: '所有价格',
  100 + title: '价格',
  101 + dataId: 'key',
  102 + subsName: 'flag',
  103 + firstSub: 0,
  104 + dataType: 'price',
  105 + sortNum: '6'
  106 + },
  107 + size: {
  108 + name: '所有尺码',
  109 + title: '尺码',
  110 + dataId: 'size_id',
  111 + subsName: 'size_name',
  112 + firstSub: 0,
  113 + dataType: 'size',
  114 + sortNum: '5'
  115 + },
  116 + ageLevel: {
  117 + name: '所有人群',
  118 + title: '人群',
  119 + dataId: 'id',
  120 + subsName: 'name',
  121 + firstSub: 0,
  122 + dataType: 'ageLevel',
  123 + sortNum: '2'
  124 + }
  125 + };
  126 +
  127 + options = Object.assign({
  128 + gender: '1,2,3', // 默认选择的性别,默认1,2,3表示所有
  129 + exclude: null // 需要排除的字段
  130 + }, options);
  131 +
  132 + _.forEach(list, (item) => {
  133 + let classify = {
  134 + subs: []
  135 + };
  136 + let key = item.filterId;
  137 +
  138 + if (!filtersType[key]) {
  139 + return;
  140 + }
  141 +
  142 + if ((options.hideSize && key === 'size') || (options.hideSort && key === 'group_sort')) {
  143 + return;
  144 + }
  145 +
  146 + classify.dataType = filtersType[key].dataType;
  147 + classify.name = filtersType[key].name;
  148 + classify.title = filtersType[key].title;
  149 +
  150 + classify.subs.push({
  151 + chosed: true,
  152 + dataId: filtersType[key].firstSub,
  153 + name: filtersType[key].name
  154 + });
  155 +
  156 + // 折扣,价格区间,需要排序
  157 + if (key === 'discount' || key === 'priceRange') {
  158 + item = _sortListByField(item, 'name');
  159 + }
  160 +
  161 + _.forEach(item.itemList, (sub) => {
  162 + let subs = {};
  163 +
  164 + subs.dataId = sub.itemId;
  165 + subs.name = sub.itemName;
  166 +
  167 + // if (key === 'discount') {
  168 + // subs.dataId = sub._key;
  169 + // } else if (key === 'priceRange') {
  170 + // subs.dataId = sub._key;
  171 + // } else if (filtersType[key].dataId === 'key') {
  172 + // subs.dataId = index;
  173 + // } else if (filtersType[key].dataId === 'relation_parameter') {
  174 + // subs.dataId = sub.relation_parameter['sort']; // eslint-disable-line
  175 + // } else {
  176 + // subs.dataId = sub[filtersType[key].dataId];
  177 + // }
  178 +
  179 + // if (key === 'priceRange') {
  180 + // subs.name = sub._value.replace('¥', '¥');
  181 + // } else if (filtersType[key].subsName === 'flag') {
  182 + // subs.name = sub;
  183 + // } else {
  184 + // subs.name = sub[filtersType[key].subsName];
  185 +
  186 + // if (key === 'discount') {
  187 + // subs.name = subs.name + '折商品';
  188 + // }
  189 + // }
  190 +
  191 + if (options[classify.dataType] + '' === subs.dataId + '') {
  192 + subs.chosed = true;
  193 + classify.subs[0].chosed = false;
  194 + }
  195 +
  196 + classify.subs.push(subs);
  197 + });
  198 +
  199 + filters.classify[filtersType[key].sortNum] = classify;
  200 + });
  201 +
  202 + return filters;
  203 +};