Authored by ccbikai

Merge branch 'feature/cate' into feature/product

/**
* 分类页面
*/
'use strict';
const cateModel = require('../models/cate');
const headerModel = require('../../../doraemon/models/header');
const helpers = global.yoho.helpers;
let index = (req, res, next) => {
cateModel.getCateData(req.yoho.channel).then((result) => {
res.render('cate', {
module: 'channel',
page: 'cate',
title: '商品分类',
pageHeader: headerModel.setNav({
navTitle: '商品分类'
}),
pageFooter: true,
category: {
nav: result.nav,
list: result.list,
searchUrl: helpers.urlFormat('/search', null, 'search')
}
});
}).catch(next);
};
module.exports = {
index
};
... ...
/**
* 分类页面 model
* @author: Bi Kai<kai.bi@yoho.cn>
* @date: 2016/07/06
*/
'use strict';
const _ = require('lodash');
const api = global.yoho.API;
const helpers = global.yoho.helpers;
const camelCase = global.yoho.camelCase;
const genderMap = {
boys: '1,3',
girls: '2,3',
kids: '1,2,3',
lifestyle: '1,2,3'
};
let _processCateData = (list, channel) => {
let nav = ['boys', 'girls', 'kids', 'lifestyle'];
nav = _.map(nav, function(item) {
return {
name: _.capitalize(item),
channel: item,
focus: item === channel
};
});
list = camelCase(list);
_.map(list, function(item, key) {
item.focus = key === channel;
_.map(item, function(firstItem) {
// 如果有二级菜单,二级菜单跳转,否则一级菜单跳转
if (firstItem.sub && firstItem.sub.length) {
_.map(firstItem.sub, function(secondItem) {
secondItem.url = helpers.urlFormat('/', {
sort: secondItem.categoryId,
sort_name: secondItem.categoryName,
gender: genderMap[channel] || ''
}, 'list');
});
} else {
firstItem.url = helpers.urlFormat('/', {
sort: firstItem.categoryId,
sort_name: firstItem.categoryName,
gender: genderMap[channel] || ''
}, 'list');
}
});
});
return {
nav,
list
};
};
let getCateData = (channel) => {
return api.get('', {
method: 'app.sort.get'
}, {
cache: true
}).then((result) => {
if (!result.code || result.code !== 200 || !result.data) {
return [];
}
// 统一频道名称
result.data.boys = result.data.boy;
result.data.girls = result.data.girl;
_.unset(result.data, 'boy');
_.unset(result.data, 'girl');
return result.data;
}).then((list) => {
return _processCateData(list, channel);
});
};
module.exports = {
getCateData
};
... ...
... ... @@ -9,6 +9,7 @@
const express = require('express');
const cRoot = './controllers';
const channel = require(cRoot);
const cate = require(cRoot + '/cate');
const router = express.Router(); // eslint-disable-line
... ... @@ -20,4 +21,6 @@ router.get('/lifestyle', channel.switchChannel, channel.lifestyle);
router.get('/channel/bottomBanner', channel.bottomBanner);
router.get('/cate', cate.index);
module.exports = router;
... ...
<div class="category-page yoho-page">
{{# category}}
<div id="search-input" class="search-input">
<a href={{searchUrl}}>
<i class="search-icon iconfont">&#xe60f;</i>
<p>搜索商品</p>
</a>
</div>
<ul class="category-nav clearfix">
{{# nav}}
<li class="{{#if focus}}focus{{/if}}" data-channel="{{channel}}">
<span>{{name}}</span>
</li>
{{/ nav}}
</ul>
<div class="category-container clearfix">
{{#each list}}
<div class="content {{@key}} {{#unless focus}}hide{{/unless}}">
<ul class="primary-level">
{{# this}}
<li class="p-level-item{{#if @first}} focus{{/if}}">
{{#if url}}
<a href={{url}}> {{categoryName}}</a>
{{^}}
{{categoryName}}
{{/if}}
</li>
{{/ this}}
</ul>
<div class="sub-level-container">
{{# this}}
<ul class="sub-level {{#unless @first}}hide{{/unless}}">
{{# sub}}
<li>
<a href={{url}}>
{{categoryName}}
</a>
</li>
{{/ sub}}
</ul>
{{/ this}}
</div>
</div>
{{/each}}
</div>
{{/ category}}
</div>
... ...
/**
* 分类
* @author: xuqi<qi.xu@yoho.cn>
* @date: 2015/10/14
*/
var $ = require('yoho-jquery');
var $nav = $('.category-nav'),
$categoryContainer = $('.category-container'),
$contents = $categoryContainer.children('.content'),
$subLevelItem = $categoryContainer.find('.sub-level li'),
$primaryItem = $categoryContainer.find('.primary-level li');
require('../common');
(function() {
var $header = $('.yoho-header'),
$search = $('#search-input');
var h = $(window).height() - $header.outerHeight() - $search.outerHeight() - $nav.outerHeight();
$categoryContainer.css('min-height', h);
$contents.height(h);
}());
$('#search-input').focus(function() {
$(this).blur();
});
$nav.on('contextmenu', function() {
return false;
});
$('.category-container').on('contextmenu', function() {
return false;
});
$nav.on('touchend touchcancel', function(e) {
var $this = $(e.target).closest('li'),
selector = '.' + $this.data('channel');
if ($this.hasClass('focus')) {
return;
}
$nav.find('li.focus').removeClass('focus');
$this.addClass('focus');
$contents.addClass('hide');
$contents.filter(selector).removeClass('hide');
});
$categoryContainer.on('touchend', function(e) {
var $this = $(e.target),
$subLevel,
$cur, index;
$cur = $this.closest('.p-level-item');
if ($cur.length > 0) {
index = $cur.index();
$subLevel = $this.closest('.content').find('.sub-level');
if ($this.hasClass('focus')) {
return;
}
$this.closest('.primary-level').children('.focus').removeClass('focus');
$this.addClass('focus');
$subLevel.not('.hide').addClass('hide');
$subLevel.eq(index).removeClass('hide');
}
});
$categoryContainer.find('.primary-level').on('touchstart touchend touchcancel', 'li', function() {
$primaryItem.removeClass('highlight');
$(this).addClass('highlight');
}).on('touchend touchcancel', 'li', function() {
$(this).removeClass('highlight');
});
$categoryContainer.find('.sub-level').on('touchstart', 'li', function() {
$subLevelItem.removeClass('highlight');
$(this).addClass('highlight');
}).on('touchend touchcancel', 'li', function() {
$(this).removeClass('highlight');
});
$nav.on('touchstart', 'li', function() {
$nav.find('li').removeClass('bytouch');
$(this).addClass('bytouch');
}).on('touchend touchcancel', 'li', function() {
$nav.find('li').removeClass('bytouch');
});
... ...
.category-page {
font-size: 30px;
.search-input {
position: relative;
background-color: #f8f8f8;
padding: 13px 20px;
p {
box-sizing: border-box;
width: 100%;
height: 60px;
line-height: 60px;
border: none;
padding-left: 66px;
border-radius: 60px;
font-size: 26px;
background: #fff;
color: #999;
}
}
.search-icon {
position: absolute;
top: 0;
bottom: 0;
left: 43px;
line-height: 86px;
color: #999;
}
.category-nav {
height: 70px;
border-bottom: 1px solid #e6e6e6;
li {
display: block;
box-sizing: border-box;
float: left;
height: 100%;
padding: 20px 0;
width: 25%;
text-align: center;
color: #999;
&:last-child {
border-right: none;
}
&.focus {
color: #000;
}
&.bytouch{
background:#eee;
}
}
span {
display: block;
width: 100%;
height: 30px;
line-height: 30px;
font-size: 30px;
border-right: 1px solid #e6e6e6;
}
li:last-child span {
border-right: 0;
}
}
.content {
background: #f8f8f8;
&.hide {
display: none;
}
}
.primary-level {
float: left;
box-sizing: border-box;
width: 45%;
> li {
height: 89px;
line-height: 89px;
padding: 0 32px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
&.focus {
background-color: #fff;
}
&.highlight {
background-color: #eee;
}
}
}
.sub-level-container {
float: left;
box-sizing: border-box;
background: #fff;
width: 55%;
height: 100%;
}
.sub-level {
width: 100%;
&.hide {
display: none;
}
> li {
box-sizing: border-box;
height: 89px;
line-height: 89px;
border-bottom: 1px solid #e6e6e6;
padding-left: 20px;
&.highlight {
background: #eee;
}
&:last-child {
border-bottom: none;
}
}
a {
display: block;
height: 100%;
width: 100%;
color: #000;
}
}
}
... ...
... ... @@ -23,6 +23,7 @@
@import "coupon";
@import "discount-list";
@import "left-right";
@import "cate";
.mobile-container {
margin-left: auto;
... ...