Authored by hongweigao

Merge branch 'feature/brands' into release/5.1

# Conflicts:
#	config/common.js
#	package.json
#	public/font/iconfont.eot
#	public/font/iconfont.svg
#	public/font/iconfont.ttf
#	public/font/iconfont.woff
#	utils/pager.js
/**
* 品牌一览 controller
* @author: ghw<hongwei.gao@yoho.cn>
* @date: 2016/9/29
*/
'use strict';
const mRoot = '../models';
const brandsService = require(`${mRoot}/brands-service`); // students model
/**
* brands 首页
* @param {[type]} req [description]
* @param {[type]} res [description]
* @return {[type]} [description]
*/
exports.index = (req, res, next) => {
let channel = req.query.channel || req.cookies._Channel || 'boys';
brandsService.getBrandViewList(channel, req).then(result => {
res.render('brands', result);
}).catch(next);
};
/**
* brandList-Ajax调用
*/
exports.brandList = (req, res, next) => {
let channel = req.query.channel || req.cookies._Channel || 'boys';
brandsService.getBrandList(channel, req.body.start).then(result => {
res.render('brand-list', Object.assign({layout: false}, result));
}).catch(next);
};
/**
* 品牌接口数据
*
* @param string brandId 获取品牌ID
* @return json
*/
exports.brandInfo = (req, res, next) => {
let brandId = req.query.brandId || 0;
brandsService.brandInfo(brandId, req.user.uid).then(result => {
res.json(result);
}).catch(next);
};
/**
* 品牌plusstar列表
*/
exports.plusstarList = (req, res, next) => {
let channel = req.query.channel || req.cookies._Channel || 'boys';
brandsService.plusstarList(channel, req).then(result => {
res.render('plusstar', result);
}).catch(next);
};
... ...
/**
* router of sub app brands
* @author: ghw<hongwei.gao@yoho.cn>
* @date: 2016/09/29
*/
var express = require('express'),
path = require('path'),
hbs = require('express-handlebars');
var app = express();
// set view engin
var doraemon = path.join(__dirname, '../../doraemon/views'); // parent view root
app.on('mount', function(parent) {
delete parent.locals.settings; // 不继承父 App 的设置
Object.assign(app.locals, parent.locals);
});
app.set('views', path.join(__dirname, 'views/action'));
app.engine('.hbs', hbs({
extname: '.hbs',
defaultLayout: 'layout',
layoutsDir: doraemon,
partialsDir: [path.join(__dirname, 'views/partial'), `${doraemon}/partial`],
helpers: global.yoho.helpers
}));
// router
app.use(require('./router'));
module.exports = app;
... ...
/**
* 品牌一览 api
* @author: ghw<hongwei.gao@yoho.cn>
* @date: 2016/9/29
*/
'use strict';
const api = global.yoho.API;
const serviceAPI = global.yoho.ServiceAPI;
/**
* 分开取数,品牌一览 顶部的轮翻广告及热门品牌数据-PC
* 顶部的轮翻广告及热门品牌数据
* @param string $contentCode 获取广告资源需要的位置码
*/
const getBrandTopData = (contentCode) => {
return serviceAPI.get('operations/api/v5/resource/get', {
content_code: contentCode
}, {cache: 3600});
};
/**
* 分开取数,获取品牌一览 "按字母'A-Z'分组的品牌列表数据"
* @param int $channel 频道标识 1:男,2:女,3:潮童,4:创意生活
*/
const getBrandListData = channel => {
let params = {method: 'app.brand.brandlist'};
if (!isNaN(channel)) {
params.yh_channel = channel;
}
return api.get('', params);
};
/**
* 获取品牌简介
*
* @param integer $brandId 品牌ID
* @param int 用户ID
* @return array 品牌介绍信息
*/
const getBrandIntro = (brandId, uid) => {
let param = {};
if (!uid) {
param.cache = 3600;
}
return api.get('', {
method: 'app.brand.getBrandIntro',
brand_id: brandId,
uid: uid
}, param);
};
/**
* 获取品牌中产品图片
* @param int 品牌ID
* @return array 品牌产品信息
*/
const getProductByBrand = (brandId, limit) => {
return api.get('', {
method: 'web.search.search',
brand: brandId,
limit: limit
});
};
/**
* 获取品牌信息
*
* @param array $ids
* @return array
*/
const getBrandInfoByIds = (ids) => {
return api.get('', {
method: 'web.brand.info',
ids: ids instanceof Array ? ids.join(',') : parseInt(ids, 10)
}, {cache: 3600});
};
/**
* 获取品牌列表
*
* @param int $brandType
* @param string $gender
* @param string $type
* @return array
*/
const getPlusstarList = (brandType, gender) => {
return serviceAPI.get('guang/api/v3/plustar/getlist', {
gender: gender,
brand_type: brandType
}, {cache: 3600});
};
module.exports = {
getBrandTopData,
getBrandListData,
getBrandIntro,
getProductByBrand,
getPlusstarList,
getBrandInfoByIds
};
... ...
/**
* 品牌一览 model
* @author: ghw<hongwei.gao@yoho.cn>
* @date: 2016/9/29
*/
'use strict';
const Promise = require('bluebird');
const co = Promise.coroutine;
const _ = require('lodash');
const helpers = global.yoho.helpers;
const brandApi = require('./brands-api');
const serviceApi = global.yoho.ServiceAPI;
// 品牌一览资源位CODE码
const channelCode = {
boys_brand: '8b16b7baf9a66fbe553a6caa97d2ce2a',
girls_brand: 'c95ae9e40f0add10549b819f821ad626',
kids_brand: 'c575c6bfdfa4125fae7d24bbec7119c8',
lifestyle_brand: '84b7926282fdef92f1039bdcf77c18ba',
brand_list: 'f0f72b1e8f30e6ad086dfc4401f3a856', // 品牌列表资源位CODE码
brand_plusstar_banner_boys: 'd0149783b8dd2adaf083fd10556c39a9',
brand_plusstar_banner_girls: 'd0149783b8dd2adaf083fd10556c39a9',
brand_plusstarindex_boys: 'a833aed63d28457156310e97faa7fa37', // plusstarindex男首资源位
brand_plusstarindex_girls: '6e4f162be3b3ba44f3bfcf1c38bdb745' // plusstarindex女首资源位
};
const BOYS = 'boys';
const GIRLS = 'girls';
const KIDS = 'kids';
const LIFESTYLE = 'lifestyle';
/**
* 获取品牌一览资源位&channelType
*
* @param string $channelStr
* @return array
*/
const switchBrandParams = channel => {
let req = {};
switch (channel) {
case BOYS:
req = {
channelType: 1,
brandCode: channelCode.brand_plusstar_banner_boys
};
break;
case GIRLS:
req = {
channelType: 2,
brandCode: channelCode.brand_plusstar_banner_girls
};
break;
case KIDS:
req = {
channelType: 3,
brandCode: channelCode.kids_brand
};
break;
case LIFESTYLE:
req = {
channelType: 4,
brandCode: channelCode.lifestyle_brand
};
break;
default:
req = {
channelType: 1,
brandCode: channelCode.boys_brand
};
break;
}
return req;
};
/**
* 获取品牌一览页面,品牌top
* @param string $channel 频道名称
*/
const getBrandViewTop = channel => {
return co(function*() {
let switchParams = switchBrandParams(channel);
let res = yield brandApi.getBrandTopData(switchParams.brandCode);
let result = {},
brandAds = [],
brandLogos = [];
// 头部10个品牌小图块 url
if (res.data[1].data && res.data[1].data.list) {
_.forEach(res.data[1].data.list, subValue => {
brandAds.push({
name: subValue.name,
src: helpers.image(subValue.src, 80, 50, 3),
url: helpers.urlFormat(subValue.url)
});
});
}
// 头部品牌图块,广告位
if (res.data[0].data) {
_.forEach(res.data[0].data, (subValue, k) => {
let srcUrl;
// kids lifestyle 第一张图尺寸不同
if (switchParams.channelType === 1 || switchParams.channelType === 2) {
srcUrl = helpers.image(subValue.src, 222, 180, 3);
} else {
srcUrl = (k === 0) ? helpers.image(subValue.src, 570, 280, 3) :
helpers.image(subValue.src, 280, 280, 3);
}
brandLogos.push({
name: subValue.title,
src: srcUrl,
url: helpers.urlFormat(subValue.url)
});
});
}
// 整合brandTop数据结构,boys、girls
if (switchParams.channelType === 1 || switchParams.channelType === 2) {
result.isTab = true;
}
result.tabHeader = brandLogos;
result.logos = brandAds;
return result;
})();
};
/**
* 获取品牌一览list
* @param string $channel 频道名称
* @param int start 开始位置 1 开始
* @param int length 取数长度 0 取到最后
*/
const getBrandViewList = (channel, start, length) => {
return co(function*() {
let switchParams = switchBrandParams(channel);
let res = yield brandApi.getBrandListData(switchParams.channelType);
let result = [],
navigation = [];
// 品牌list A-Z 0-9
if (res.data.brands) {
_.forEach(res.data.brands, (subValue, key) => {
let listTmp = [];
_.forEach(subValue, ssubValue => {
// 为品牌名称
let href;
if (switchParams.channelType === 1) {
href = helpers.urlFormat(ssubValue.brand_domain) + '?gender=1,3';
} else if (switchParams.channelType === 2) {
href = helpers.urlFormat(ssubValue.brand_domain) + '?gender=2,3';
} else {
href = helpers.urlFormat(ssubValue.brand_domain);
}
let brandItem = {
name: ssubValue.brand_name,
key: ssubValue.id,
href: href
};
if (ssubValue.is_hot === 'Y') {
brandItem.hot = 'hot';
}
listTmp.push(brandItem);
});
navigation.push(key);
result.push({
key: key,
val: listTmp
});
});
}
// 只取部分数据
let begin;
begin = (start - 1) ? (start - 1) : 0;
begin = (begin > 0) ? begin : 0;
result = length ? result.slice(begin, length + begin) : result.slice(begin);
result.navigation = navigation;
return result;
})();
};
/**
* 获取单个广告浮窗内容
*
* @param int $brandId
* @param int $uid
* @return array
*/
const getBrandInfo = (brandId, uid) => {
return co(function*() {
let data = {},
imgs = [];
// 获取品牌简介
let res = yield brandApi.getBrandIntro(brandId, uid);
if (res.data) {
// 获取品牌下的产品信息
let proInfo = yield brandApi.getProductByBrand(brandId, 3);
let proInfoTmp = proInfo.data.product_list;
if (!_.isEmpty(proInfoTmp)) {
_.forEach(proInfoTmp, subValue => {
imgs.push({
src: helpers.image(subValue.default_images, 80, 100)
});
});
}
// 整合
data = {
key: res.data.brand_id,
icon: helpers.image(res.data.brand_ico, 80, 50),
title: res.data.brand_name,
content: res.data.brand_intro,
subtitle: 'FEATURED ITEMS',
imgs: imgs
};
}
return data;
})();
};
/**
* 多个品牌ID获取品牌信息
*
* @param array $brandIds
* @return array
*/
const getBrandInfoByIds = (brandIds) => {
return co(function*() {
let data = yield brandApi.getBrandInfoByIds(brandIds);
let brandsInfo = {};
if (data.data && data.code === 200) {
_.forEach(data.data, (subValue, k) => {
subValue.desc = _.trim(subValue.brand_intro.replace('/[\r\n\t ]/g', ''));
subValue.url = helpers.urlFormat(subValue.brand_domain);
delete subValue.brand_intro;
brandsInfo[k] = subValue;
});
}
return brandsInfo;
})();
};
/**
* 获取plusstar品牌列表项目
*
* @param string $channel
* @return array
*/
const getPlusstarBrandListItem = (channel) => {
return co(function*() {
let code = channel === 'girls' ? channelCode.brand_plusstar_banner_girls :
channelCode.brand_plusstar_banner_boys;
// 资源位数据
let resource = yield serviceApi.get('operations/api/v5/resource/get', {content_code: code}, {cache: 3600});
let items = [];
if (resource.data && resource.code === 200) {
items[0] = {name: '所有品牌', src: '', url: helpers.urlFormat('/brands'), brandType: ''};
items[1] = {name: '设计新潮', src: '', url: '', brandType: 4};
items[2] = {name: '潮流经典', src: '', url: '', brandType: 1};
items[3] = {name: '明星潮牌', src: '', url: '', brandType: 2};
items[4] = {name: '原创潮牌', src: '', url: '', brandType: 3};
let resourceData = resource.data,
pos = 0;
_.forEach(items, (subValue, k) => {
if (_.isEmpty(subValue.url)) {
subValue.url = helpers.urlFormat('/brands/plusstar?id=' + k);
}
if (pos in resourceData[0].data) {
subValue.url = helpers.urlFormat(resourceData[0].data[pos].url);
subValue.src = helpers.image(resourceData[0].data[pos].src, 222, 180, 1);
subValue.name = resourceData[0].data[pos].title;
}
pos++;
});
}
return items;
})();
};
/**
* 获取Plustar列表
*
* @param string $brandType
* @param string $gender
* @return array
*/
const getPlustarList = (brandType, gender) => {
return co(function*() {
let list = yield brandApi.getPlusstarList(brandType, gender);
let brandList = {},
data = {},
brandsIds = [];
if (list.data.data.list) {
brandList = list.data.data.list[0];
}
if (brandList.data) {
_.forEach(brandList.data, brand => {
let src = '';
if (brand.data[0]) {
src = helpers.image(brand.data[0].src, 320, 160, 1);
}
data[brand.brand_id] = {
brand_id: brand.brand_id,
name: brand.brand_name,
sort_id: brand.sort_id,
src: src,
desc: '',
url: ''
};
brandsIds.push(brand.brand_id);
});
}
return {brandsIds: brandsIds, data: data};
})();
};
module.exports = {
getBrandViewTop,
getBrandViewList,
getBrandInfo,
getBrandInfoByIds,
getPlusstarBrandListItem,
getPlustarList
};
... ...
/**
* 品牌一览 controller
* @author: ghw<hongwei.gao@yoho.cn>
* @date: 2016/9/29
*/
'use strict';
const Promise = require('bluebird');
const co = Promise.coroutine;
const api = global.yoho.API;
const headerModel = require('../../../doraemon/models/header');
const brandsModel = require('./brands-model');
const _ = require('lodash');
const helpers = global.yoho.helpers;
const pager = require(`${global.utils}/pager`).setPager;
// 添加网站的SEO
const seoMap = {
boys: {
title: '品牌一览|男装品牌排行榜,男装品牌大全|YOHO!BUY 有货 100%正品保证',
keywords: '品牌一览,男装品牌,男装品牌排行榜,男装品牌大全,YOHO!BUY 有货',
description: 'YOHO!BUY 有货男装品牌一览汇集国内国际各大男装品牌大全,为广大爱好时尚的男士青年提供品牌男装、' +
'休闲男装、商务男装.YOHO!BUY 有货,100%正品保证'
},
girls: {
title: '品牌一览|女装品牌排行榜,女装品牌大全|YOHO!BUY 有货 100%正品保证',
keywords: '品牌一览,女装品牌,女装品牌排行榜,女装品牌大全,YOHO!BUY 有货',
description: 'YOHO!BUY 有货女装品牌一览汇集国内国际各大女装品牌,为广大爱美女生提供品牌女装、休闲女装、' +
'商务女装.买品牌女装就上YOHO!BUY 有货,100%正品保证'
},
kids: {
title: '品牌一览|童装童鞋品牌,儿童鞋包配饰排行榜,潮童品牌大全|YOHO!BUY 有货 100%正品保证',
keywords: '童装品牌,童装童鞋排行榜,儿童鞋包配饰排行榜,潮童品牌大全,品牌一览,YOHO!BUY 有货',
description: 'YOHO!BUY 有货童装品牌一览汇集国内国际各大童装品牌大全,为广大爱好潮流的儿童提供品牌童装、童鞋,' +
'儿童鞋包配饰.YOHO!BUY 有货,100%正品保证'
},
lifestyle: {
title: '品牌一览|数码3c,居家,玩具娱乐,文具,美妆品牌|YOHO!BUY 有货 100%正品保证',
keywords: '数码3c品牌,居家品牌,玩具娱乐品牌,文具品牌,美妆品牌',
description: 'YOHO!BUY 有货女装品牌一览汇集国内国际各大数码3c品牌,居家品牌,玩具娱乐品牌,文具品牌,' +
'美妆品牌.买创意生活家居就上YOHO!BUY 有货,100%正品保证'
}
};
/**
* 获取品牌一览list
* @param string $channel 频道名称
* @param int start 开始位置 1 开始
* @param int length 取数长度 0 取到最后
*/
exports.getBrandViewList = (channel) => {
let apiMethod = [
headerModel.requestHeaderData(channel),
brandsModel.getBrandViewTop(channel),
brandsModel.getBrandViewList(channel, 1, 5) // 分屏加载
];
return api.all(apiMethod).then(result => {
let responseData = {
module: 'brands',
page: 'brands'
};
// 头部数据
Object.assign(responseData, result[0]);
// 品牌一览列表
responseData.brands = result[1];
responseData.brands.navigation = result[2].navigation;
responseData.brands.category = result[2];
// SEO
Object.assign(responseData, seoMap[channel]);
return responseData;
});
};
/**
* brandList-Ajax调用
*/
exports.getBrandList = (channel, start) => {
let apiMethod = [
brandsModel.getBrandViewList(channel, start)
];
return api.all(apiMethod).then(result => {
let responseData = {};
// 品牌一览列表
responseData.category = result[0];
return responseData;
});
};
/**
* 品牌接口数据
*
* @param string brandId 获取品牌ID
* @return json
*/
exports.brandInfo = (brandId, uid) => {
let apiMethod = [
brandsModel.getBrandInfo(brandId, uid)
];
return api.all(apiMethod).then(result => {
return {
code: _.isEmpty(result[0]) ? 400 : 200,
brand: _.isEmpty(result[0]) ? '' : result[0]
};
});
};
/**
* 多个品牌ID获取品牌信息
*
* @param array $brandIds
* @return array
*/
exports.plusstarList = (channel, req) => {
return co(function*() {
let headerData = yield headerModel.requestHeaderData(channel);
let responseData = {
module: 'brands',
page: 'brands',
brandsHomePage: true
};
let genderChannel;
if (channel === 'boys') {
genderChannel = '1,3';
} else if (channel === 'girls') {
genderChannel = '2,3';
} else {
genderChannel = '1,2,3';
}
let id = req.query.id || '',
gender = req.query.gender || genderChannel,
limit = 20,
page = parseInt(req.query.page, 10) || 1;
let items = yield brandsModel.getPlusstarBrandListItem(channel);
let brandType = 1;
if (items[id]) {
brandType = items[id].brandType;
}
let plustarList = yield brandsModel.getPlustarList(brandType, gender);
let list = plustarList.data;
let brandIds = [],
brands = [],
pageList = {};
brandIds = plustarList.brandsIds.slice((page - 1) * limit, page * limit);
if (plustarList.brandsIds.length > limit) {
pageList = pager(Math.ceil(plustarList.brandsIds.length / limit), {
page: page,
id: id
});
}
if (brandIds.length > 0) {
// 获取品牌信息
let brandsInfo = yield brandsModel.getBrandInfoByIds(brandIds);
_.forEach(brandIds, brandId => {
if (brandsInfo[brandId]) {
list[brandId].desc = brandsInfo[brandId].desc;
list[brandId].url = helpers.urlFormat(brandsInfo[brandId].url + '?gender=' + gender);
}
brands.push(list[brandId]);
});
}
let data = {
brandsHomePage: true,
brands: {
items: brands,
tabs: items
}
};
// 头部数据
Object.assign(responseData, headerData);
// 产品信息
Object.assign(responseData, data);
// 页码
Object.assign(responseData, pageList);
// SEO
Object.assign(responseData, seoMap[channel]);
return responseData;
})();
};
... ...
/**
* router of sub app brands
* @author: ghw<hongwei.gao@yoho.cn>
* @date: 2016/09/29
*/
'use strict';
const express = require('express');
const cRoot = './controllers';
const router = express.Router(); // eslint-disable-line
const brandsController = require(`${cRoot}/brands`);
// 品牌一览
router.get('', brandsController.index);
// 悬浮出现品牌信息
router.get('/brandinfo', brandsController.brandInfo);
// 品牌没有加载完全,继续加载
router.post('/brandList', brandsController.brandList);
// brands/plusstar
router.get('/plusstar', brandsController.plusstarList);
module.exports = router;
... ...
<div class="home-page yoho-page brands" data-page="brands">
{{# brands}}
{{> common/path-nav}}
{{#if isTab}}
<div class="brands-tabs">
<ul class="clearfix">
{{#each tabHeader}}
<li>
<a href="{{url}}">
<div class="g-mask"></div>
<p class="tips">{{name}}</p>
<img class="lazy" data-original="{{src}}"/>
</a>
</li>
{{/each}}
</ul>
<div class="hover-contain">
<div class="hoverarr">
<i></i>
</div>
</div>
</div>
{{^}}
<ul class="brands-ad clearfix">
{{#each tabHeader}}
<li>
<a href="{{url}}" target="_blank">
<img class="lazy" data-original="{{src}}">
</a>
</li>
{{/each}}
</ul>
{{/if}}
<div class="brands-logo clearfix">
{{#each logos}}
<a href="{{url}}" title="{{name}}" target="_blank">
<img class="lazy" data-original="{{src}}">
</a>
{{/each}}
</div>
<div class="brands-category">
<div class="category-nav">
<span>BRANDS A-Z:</span>
{{#each navigation}}
<a href="#{{this}}">{{this}}</a>
{{/each}}
</div>
</div>
<div class="brands-list" >
{{> brand-list}}
</div>
{{/ brands}}
</div>
... ...
{{> layout/header}}
<div class="home-page yoho-page brands" data-page="brands">
{{# brands}}
{{! 头部banner}}
{{# slide}}
{{>index/slide-banner}}
{{/ slide}}
{{! 品牌 BRAND}}
{{# brand}}
{{> index/floor-header}}
<div class="brandfloor clearfix">
<ul class="g-list">
{{# list}}
<li>
<a href="{{url}}" target= "_blank">
<img class="lazy" data-original="{{src}}" alt="">
</a>
</li>
{{/ list}}
</ul>
</div>
{{/ brand}}
{{! 单品 SINGLE GOODS}}
{{# singlegoods}}
{{> index/floor-header}}
<div class="singlegoods clearfix">
<ul class="g-list">
{{# list}}
<li>
<a href="{{url}}" target= "_blank">
<img class="lazy" data-original="{{src}}" alt="">
<div class="singlegoods-title">
<div class="g-mask"></div>
<p>{{name}}</p>
</div>
</a>
</li>
{{/ list}}
</ul>
</div>
{{/ singlegoods}}
{{!视频 VIDEO}}
{{# video}}
{{> index/floor-header}}
<div class="video clearfix">
<ul class="g-list">
{{# list}}
<li>
<a href="{{url}}" target= "_blank">
<img class="lazy" data-original="{{src}}" alt="" /><i class="video-play"></i>
<div class="video-title">
<div class="g-mask"></div>
<p>{{name}}</p>
</div>
</a>
</li>
{{/ list}}
</ul>
</div>
{{/ video}}
{{!新闻 NEWS}}
{{# news}}
{{> index/floor-header}}
<div class="news clearfix">
<div class="news-pic">
{{# pics}}
{{>index/slide-banner}}
{{/ pics}}
</div>
<div class="news-txt">
{{# txts}}
<ul>
{{#each list}}
<li>
<i class="iconfont">&#xe619;</i><a href="{{url}}">{{name}}</a>
</li>
{{/each}}
</ul>
{{/ txts}}
</div>
</div>
{{/ news}}
{{!推广 AD}}
{{# ads}}
<div class="ads clearfix">
<ul class="g-list">
{{# list}}
<li>
<a href="{{url}}" target= "_blank">
<img class="lazy" data-original="{{src}}" alt="">
<span class="name g-title">{{name}}</span>
<span class="des g-title">{{des}}</span>
</a>
</li>
{{/ list}}
</ul>
</div>
{{/ ads}}
{{/ brands}}
</div>
{{> layout/footer}}
\ No newline at end of file
... ...
{{> layout/header}}
<div class="home-page yoho-page brands" data-page="brands">
{{# brands}}
<div class="sit-nav">
<a href="#">BOYS首页</a><span class="sep">></span><a href="#">品牌一览</a>
</div>
<div class="brands-tabs height-initial">
<ul class="clearfix">
{{#each tabs}}
<li>
<a href="{{url}}" target="_blank">
<div class="g-mask"></div>
<p class="tips">{{name}}</p>
<img class="lazy" data-original="{{src}}"/>
</a>
</li>
{{/each}}
</ul>
<div class="hover-contain">
<div class="hoverarr">
<i></i>
</div>
</div>
</div>
<div class="brands-items clearfix">
{{#each items}}
<div class="brands-item clearfix">
<a class="brands-pic" title="{{name}}" href="{{url}}" target="_blank">
<img class="lazy" data-original="{{src}}"/>
</a>
<div class="brand-info">
<a title="{{name}}" href="{{url}}" target="_blank">
<h3>
{{name}}
</h3>
</a>
<div class="brand-desc">{{desc}}</div>
</div>
</div>
{{/each}}
</div>
<div class="pagination">
<a href="#" class="page_pre" title="上一页"><i class="iconfont">&#xe60f;</i>上一页</a>
<a href="#"><span>1</span></a>
<a href="#" class="cur"><span>2</span></a>
<a href="#"><span>3</span></a>
<a href="#"><span>4</span></a>
<a href="#"><span>5</span></a>
<a><span>...</span></a>
<a href="#"><span>215</span></a>
<a href="#" title="下一页">下一页<i class="iconfont">&#xe60e;</i></a>
</div>
{{/ brands}}
</div>
{{> layout/footer}}
\ No newline at end of file
... ...
<div class="home-page yoho-page brands" data-page="brands">
{{# brands}}
{{> common/path-nav}}
<div class="brands-tabs height-initial">
<ul class="clearfix">
{{#each tabs}}
<li>
<a href="{{url}}">
<div class="g-mask"></div>
<p class="tips">{{name}}</p>
<img class="lazy" data-original="{{src}}"/>
</a>
</li>
{{/each}}
</ul>
<div class="hover-contain">
<div class="hoverarr">
<i></i>
</div>
</div>
</div>
<div class="brands-items clearfix">
{{#each items}}
<div class="brands-item clearfix">
<a class="brands-pic" title="{{name}}" href="{{url}}" target="_blank">
<img class="lazy" data-original="{{src}}"/>
</a>
<div class="brand-info">
<a title="{{name}}" href="{{url}}" target="_blank">
<h3>
{{name}}
</h3>
</a>
<div class="brand-desc">{{desc}}</div>
</div>
</div>
{{/each}}
</div>
{{/ brands}}
<div class="pagination clearfix">
{{# prePage}}
<a href="{{url}}" title="上一页">上一页<span class="iconfont">&#xe60e;</span></a>
{{/ prePage}}
{{# pages}}
<a{{#if url}} href="{{url}}"{{/if}}{{#if cur}} class="cur"{{/if}}>{{num}}</a>
{{/ pages}}
{{# nextPage}}
<a href="{{url}}" title="下一页">下一页<span class="iconfont">&#xe60c;</span></a>
{{/ nextPage}}
</div>
</div>
... ...
{{> layout/header}}
<div class="home-page yoho-page brands" data-page="brands">
{{# brands}}
{{! 头部banner}}
{{# slide}}
{{>index/slide-banner}}
{{/ slide}}
{{! 品牌 BRAND}}
{{# brand}}
{{> index/floor-header}}
<div class="brandfloor list-floor clearfix">
<ul class="g-list">
{{# list}}
<li>
<a href="{{href}}" target= "_blank">
<img class="lazy" data-original="{{img}}" alt="">
</a>
</li>
{{/ list}}
</ul>
</div>
{{/ brand}}
{{! 单品 SINGLE GOODS}}
{{# singlegoods}}
{{> index/floor-header}}
<div class="singlegoods list-floor clearfix">
<ul class="g-list">
{{# list}}
<li>
<a href="{{href}}" target= "_blank">
<img class="lazy" data-original="{{img}}" alt="">
<div class="singlegoods-title">
<div class="g-mask"></div>
<p>{{name}}</p>
</div>
</a>
</li>
{{/ list}}
</ul>
</div>
{{/ singlegoods}}
{{!视频 VIDEO}}
{{# video}}
{{> index/floor-header}}
<div class="video list-floor clearfix">
<ul class="g-list">
{{# list}}
<li>
<a href="{{href}}" target= "_blank">
<img class="lazy" data-original="{{img}}" alt="" /><i class="video-play"></i>
<div class="video-title">
<div class="g-mask"></div>
<p>{{name}}</p>
</div>
</a>
</li>
{{/ list}}
</ul>
</div>
{{/ video}}
{{!新闻 NEWS}}
{{# news}}
{{> index/floor-header}}
<div class="news clearfix">
<div class="news-pic">
{{# pics}}
{{>index/slide-banner}}
{{/ pics}}
</div>
<div class="news-txt">
{{# txts}}
<ul>
{{#each list}}
<li>
<i class="iconfont">&#xe619;</i><a href="{{href}}" target= "_blank">{{name}}</a>
</li>
{{/each}}
</ul>
{{/ txts}}
</div>
</div>
{{/ news}}
{{!推广 AD}}
{{# ads}}
<div class="ads list-floor clearfix">
<ul class="g-list">
{{# list}}
<li>
<a href="{{href}}" target= "_blank">
<img class="lazy" data-original="{{img}}" alt="">
<span class="name g-title">{{name}}</span>
<span class="des g-title">{{des}}</span>
</a>
</li>
{{/ list}}
</ul>
</div>
{{/ ads}}
{{/ brands}}
</div>
{{> layout/footer}}
\ No newline at end of file
... ...
{{#each category}}
<dl class="clearfix" name="{{key}}">
<dt>{{key}}</dt>
<dd>
<ul class="clearfix">
{{#each val}}
<li>
<a class="{{hot}}" data-key="{{key}}" href="{{href}}" target="_blank">
<span>{{name}}</span>
</a>
{{# hot}}
<i class="iconfont">&#xe62c;</i>
{{/ hot}}
</li>
{{/each}}
</ul>
</dd>
</dl>
{{/each}}
... ...
... ... @@ -16,11 +16,8 @@ module.exports = {
siteUrl: 'http://www.yohobuy.com',
domains: {
favApi: 'http://192.168.102.31:8092/brower',
api: 'http://api.yoho.cn/',
service: 'http://service.yoho.cn/',
// api: 'http://api-test1.yohops.com:9999/',
// service: 'http://service-test1.yohops.com:9999/',
api: 'http://api-test1.yohops.com:9999/',
service: 'http://service-test1.yohops.com:9999/',
search: 'http://192.168.102.216:8080/yohosearch/'
},
subDomains: {
... ... @@ -39,8 +36,7 @@ module.exports = {
master: ['127.0.0.1:11211'],
slave: ['127.0.0.1:11211'],
session: ['127.0.0.1:11211'],
reconnect: 5000,
timeout: 100,
timeout: 1000,
retries: 0
},
interfaceShunt: {
... ... @@ -119,9 +115,8 @@ if (isProduction) {
master: ['127.0.0.1:12111'],
slave: ['127.0.0.1:12112'],
session: ['127.0.0.1:12111'],
timeout: 100,
retries: 0,
reconnect: 5000
timeout: 1000,
retries: 0
}
});
}
... ...
... ... @@ -14,4 +14,5 @@ module.exports = app => {
app.use('/product', require('./apps/product')); // 商品相关页面
app.use(require('./apps/passport')); // 登录注册
app.use('/home', require('./apps/home')); // 会员中心
app.use('/brands', require('./apps/brands'));
};
... ...
{
"name": "yohobuy-node",
"version": "5.0.2",
"version": "4.9.7",
"private": true,
"description": "A New Yohobuy Project With Express",
"repository": {
... ... @@ -38,6 +38,7 @@
"cookie-parser": "^1.4.3",
"express": "^4.13.1",
"express-handlebars": "^3.0.0",
"express-session": "^1.13.0",
"influxdb-winston": "^1.0.1",
"lodash": "^4.13.1",
"md5": "^2.1.0",
... ... @@ -58,7 +59,6 @@
"uuid": "^2.0.2",
"winston": "^2.2.0",
"winston-daily-rotate-file": "^1.1.4",
"yoho-express-session": "^1.14.1",
"yoho-node-lib": "0.0.52"
},
"devDependencies": {
... ... @@ -101,9 +101,8 @@
"yoho-handlebars": "^4.0.5",
"yoho-jquery": "^1.12.4",
"yoho-jquery-lazyload": "^1.9.7",
"yoho-jquery-pjax": "0.0.1",
"yoho-jquery-placeholder": "^2.3.1",
"yoho-jquery-qrcode": "^0.14.0",
"yoho-slider": "0.0.2"
"yoho-slider": "0.0.2",
"yoho-jquery-dotdotdot": "0.0.1"
}
}
... ...
/**
* 首页
* @author: xuqi<qi.xu@yoho.cn>
* @date: 2015/11/23
*/
var $ = require('yoho-jquery'),
lazyLoad = require('yoho-jquery-lazyload');
var Handlebars = require('yoho-handlebars');
var $tabs = $('.brands-tabs');
var $list = $('.brands-list');
var $gory = $('.brands-category');
var $news = $('.news-txt ul');
var $clearfix = $list.find('dl.clearfix');
var $brand = $list.find('li>a');
var $category = $gory.find('a');
var $tab = $tabs.find('li>a');
var $arr = $tabs.find('.hoverarr');
var $thisTab;
var categoryHeight = $category.height();
var categoryTop = $category.offset() ? $category.offset().top : 0;
var newsHeight = $news.height();
var newsTop = $news.offset() ? $news.offset().top : 0;
var timeout, _id;
// 用于临时存储数据
var tempdata = {};
var templete = '<div class="brands-dialog">';
require('../common');
require('yoho-jquery-dotdotdot');
templete += ' <div class="brands-layer">';
templete += ' <div class="layer-content">';
templete += ' <div class="title">{{title}}</div>';
templete += ' <div class="clearfix desc">';
templete += ' <img src="{{icon}}">';
templete += ' <p class="right">{{content}}</p>';
templete += ' </div> ';
templete += ' <div class="featured">';
templete += ' <p>{{subtitle}}</p> ';
templete += ' <div class="clearfix"> ';
templete += ' {{#each imgs}}';
templete += ' <img src="{{src}}">';
templete += ' {{/each}}';
templete += ' </div>';
templete += ' </div>';
templete += ' </div>';
templete += ' </div>';
templete += '</div>';
$('.brand-desc').dotdotdot();
lazyLoad($('img.lazy'));
// $('.slide-container').slider({
// orient: true
// });
$.easing.easeOutQuint = function(x, t, b, c, d) {
return c * ((t = t / d - 1) * t * t * t * t + 1) + b;
};
function getQueryString(name) {
var reg = new RegExp('(^|&)' + name + '=([^&]*)(&|$)');
var r = window.location.search.substr(1).match(reg);
if (r !== null) {
return window.unescape(r[2]);
}
return null;
}
// 格式化资讯NEWS标题数量
if ($news.length) {
$news.find('li').each(function() {
var $dom = $(this);
var domHeight = $dom.offset().top - newsTop + $dom.height();
if (domHeight > newsHeight) {
$dom.hide();
}
});
}
// 头部图片TAB切换展示
$tab.eq(0).parent('li').find('.brands-content').css('z-index', '1');
_id = getQueryString('id') ? getQueryString('id') : 0;
// 设置对应TAB选中
$thisTab = $tab.eq(_id);
$thisTab.find('.g-mask').addClass('g-mask-on');
if (_id && $thisTab.length) {
$arr.css({
left: parseFloat($thisTab.offset().left) - parseFloat($tabs.offset().left)
});
}
$tab.hover(function() {
var $this = $(this);
clearTimeout(timeout);
timeout = setTimeout(function() {
var targetLeft = parseFloat($this.offset().left) - parseFloat($tabs.offset().left);
$arr.animate({
left: targetLeft
}, 200, 'easeOutQuint');
}, 50);
$tabs.find('.brands-content').removeAttr('style');
$this.parent('li').find('.brands-content').css('z-index', '1');
}, function() {
clearTimeout(timeout);
});
// 品牌类别滚动事件
$(window).scroll(function() {
if ($(this).scrollTop() >= categoryTop) {
$gory.addClass('category-fix');
} else {
$gory.removeClass('category-fix');
}
});
// 点击字母,页面滚动到相关区域
$category.click(function() {
var name = $(this).attr('href').split('#')[1];
var targetTop = $list.find('[name="' + name + '"]').offset().top - categoryHeight;
if (!$gory.hasClass('category-fix')) {
targetTop -= categoryHeight;
}
$('html,body').animate({
scrollTop: targetTop
}, 200);
return false;
});
// 浮层代码
function bindTemplete($select, data, tmp) {
var $this = $select;
var offset = {
width: $this.width(),
left: $this.offset().left,
right: parseFloat($(window).width()) - parseFloat($this.offset().left) - parseFloat($this.width())
};
var $parent = $this.parent('li');
var myTemplate;
$list.find('.brands-dialog').remove();
myTemplate = Handlebars.compile(tmp);
$parent.append(myTemplate(data));
$parent.find('.right').dotdotdot();
if (offset.right - 350 < 0) {
$parent.find('.brands-layer')
.addClass('brands-layer-right').css('left', -330 - offset.width);
}
}
// 鼠标悬浮品牌,请求数据,并且展示
function bindHoverEvent() {
$brand.unbind('mouseenter').unbind('mouseleave').hover(function() {
var $this = $(this);
var key = $this.attr('data-key');
var options = {
url: '/brands/brandinfo',
type: 'get',
data: {
brandId: key
},
success: function(_data) {
if (_data.code === 200 && _data.brand) {
if (!tempdata.hasOwnProperty(_data.brand.key)) {
tempdata[_data.brand.key] = _data.brand;
}
bindTemplete($this, tempdata[_data.brand.key], templete);
}
}
};
clearTimeout(timeout);
timeout = setTimeout(function() {
if (!tempdata.hasOwnProperty(key)) {
$.ajax(options);
} else {
bindTemplete($this, tempdata[key], templete);
}
}, 200);
}, function() {
clearTimeout(timeout);
$list.find('.brands-dialog').remove();
});
}
if ($clearfix.length < 26) {
$.ajax({
url: '/brands/brandList',
type: 'POST',
data: {
start: $clearfix.length ? ($clearfix.length + 1) : 1
},
success: function(_data) {
if (_data) {
$list.append(_data);
$brand = $list.find('li>a');
bindHoverEvent();
}
}
});
}
bindHoverEvent();
... ...
... ... @@ -64,7 +64,7 @@ exports.setPager = (total, params)=>{
for (i = 1; i <= len; i++) {
let p = currentPage + i + 2;
if (i > total) {
if (p > total) {
break;
}
... ... @@ -78,7 +78,7 @@ exports.setPager = (total, params)=>{
for (i = 1; i <= len; i++) {
let p = currentPage - i - 2;
if (i < 1) {
if (p < 1) {
break;
}
... ...