Authored by 姜枫

完善列表,添加店铺首页

... ... @@ -11,39 +11,39 @@
const _ = require('lodash');
const camelCase = global.yoho.camelCase;
// const cookie = global.yoho.cookie;
const BrandData = require('../models/brand-service');
const cookie = global.yoho.cookie;
const Search = require('../models/search');
const DataHelper = require('../models/helpers');
function bannerFormat(banner) {
let url = banner.brandBanner;
return {
bgImg: url.split('?')[0],
brandIntro: {
text: '品牌介绍'
},
height: 150,
info: banner.brandIntro,
name: banner.brandName
};
}
function shopMenu(domain) {
let menus = [
{name: '店铺首页', href: `/product/shop/${domain}`},
{name: '全部商品', href: `/product/shop/${domain}/list`, icon: ''},
{name: '人气单品', href: `/product/shop/${domain}/list?order=xxx`},
{name: '新品上架', href: `/product/shop/${domain}/list?order=s_t_desc`}
];
return menus;
}
const ShopData = require('../models/shop-service');
const shop = {
index(req, res) {
res.send('shop index');
index(req, res, next) {
let domain = req.params.domain;
let uid = cookie.getUid(req);
let data = {
module: 'product',
page: 'shop',
title: domain
};
ShopData.getShopHeadData(domain, uid).then(result => {
if (result.shopId) {
let nav = [DataHelper.getChannelNav()];
nav.push({
name: result.name
});
data.navPath = {
nav: nav
};
data.banner = result;
res.display('shop-index', data);
} else {
shop.list(req, res, next);
}
});
},
list(req, res, next) {
let data = {
... ... @@ -54,19 +54,17 @@ const shop = {
let nav = [DataHelper.getChannelNav()];
let domain = req.params.domain;
// let uid = cookie.getUid(req);
let uid = cookie.getUid(req);
let q = req.query;
q.page = q.page || 1;
data.shopMenu = shopMenu(domain);
BrandData.getBrandByDomainAsync(domain).then(result => {
console.log(result);
data.brandBanner = bannerFormat(result);
q.brand = result.id;
q.shop_id = q.shopId || '';
ShopData.getShopHeadData(domain, uid).then(result => {
data.banner = result;
q.brand = result.brandId;
q.shop_id = result.shopId;
nav.push({
name: result.brandName
name: result.name
});
}).then(() => {
return Search.queryProductOfBrand(q).then(result => {
... ...
... ... @@ -6,22 +6,25 @@
const api = global.yoho.API;
const getBannerInfoAsync = bid => {
return api.get('', {
method: 'web.brand.banner',
brand_id: bid
});
const BrandApi = {
getBrandInfo(bid, uid) {
let params = {
method: 'app.brand.getBrandIntro',
brand_id: bid
};
};
if (uid) {
params.uid = uid;
}
return api.get('', params);
},
const getBrandLogoByDomainAsync = domain => {
return api.get('', {
domain: domain,
method: 'web.brand.byDomain'
});
getDomainInfo(domain) {
return api.get('', {
domain: domain,
method: 'web.brand.byDomain'
});
}
};
module.exports = {
getBannerInfoAsync,
getBrandLogoByDomainAsync
};
module.exports = BrandApi;
... ...
... ... @@ -8,21 +8,20 @@ const co = Promise.coroutine;
const api = require('./brand-api');
const camelCase = global.yoho.camelCase;
const getBrandByDomainAsync = domain => {
const getDomainInfo = domain => {
return co(function*() {
let brandInfo = yield api.getBrandLogoByDomainAsync(domain);
let brandInfo = yield api.getDomainInfo(domain);
if (!brandInfo.data || brandInfo.code !== 200) {
return {};
}
return camelCase(brandInfo.data);
})();
};
const getBannerInfoAsync = bid => {
const getBrandInfo = bid => {
return co(function*() {
let brandInfo = yield api.getBannerInfoAsync(bid);
let brandInfo = yield api.getBrandInfo(bid);
if (!brandInfo.data || brandInfo.code !== 200) {
return {};
... ... @@ -33,6 +32,6 @@ const getBannerInfoAsync = bid => {
};
module.exports = {
getBrandByDomainAsync,
getBannerInfoAsync: getBannerInfoAsync
getDomainInfo,
getBrandInfo
};
... ...
/**
* 店铺相关api调用
*
* @author: jiangfeng<jeff.jiang@yoho.cn>
* @date: 2016/07/14
**/
'use strict';
const Api = global.yoho.API;
const ShopApi = {
getShopIntro(shopId, uid) {
let param = {
method: 'app.shops.getIntro',
shop_id: shopId
};
if (uid) {
param.uid = uid;
}
return Api.get('', param);
},
getShopDecorator(shopId) {
let param = {
method: 'app.shopsdecorator.getList',
shop_id: shopId
};
return Api.get('', param);
},
getShopSorts(shopId, channel, gender) {
let param = {
method: 'app.shop.getSortInfo',
shop_id: shopId
};
if (channel) {
param.yh_channel = channel;
}
if (gender) {
param.gender = gender;
}
return Api.get('', param);
}
};
module.exports = ShopApi;
... ...
/**
* 店铺相关数据处理
*
* @author: jiangfeng<jeff.jiang@yoho.cn>
* @date: 2016/07/14
**/
'use strict';
const Promise = require('bluebird');
const co = Promise.coroutine;
const camelCase = global.yoho.camelCase;
const BrandService = require('./brand-service');
const ShopApi = require('./shop-api');
const _ = require('lodash');
/**
* 处理店铺默认菜单
* @param domain
* @returns {*[]}
*/
function shopMenu(domain) {
let menus = [
{name: '店铺首页', href: `/product/shop/${domain}`},
{name: '全部商品', href: `/product/shop/${domain}/list`, icon: '&#xe60a;'},
{name: '人气单品', href: `/product/shop/${domain}/list?order=xxx`},
{name: '新品上架', href: `/product/shop/${domain}/list?order=s_t_desc`}
];
return menus;
}
/**
* 处理店铺首页资源位数据
* @param data
* @returns {{}}
*/
function resourceDataHandle(data) {
let resource = {};
if (data && _.isArray(data)) {
data.forEach(d => {
resource[d.resourceName] = JSON.parse(d.resourceData);
});
}
return resource;
}
const ShopService = {
getShopIntro(shopId, uid) {
return co(function*() {
let shopIntro = yield ShopApi.getShopIntro(shopId, uid);
if (shopIntro && shopIntro.code === 200) {
return camelCase(shopIntro.data);
} else {
return {};
}
})();
},
getShopDecorator(shopId) {
return co(function*() {
let data = yield ShopApi.getShopDecorator(shopId);
if (data && data.code === 200) {
return camelCase(data.data);
} else {
return {};
}
})();
},
getShopSecondSorts(shopId) {
return co(function*() {
let data = yield ShopApi.getShopSorts(shopId);
if (data && data.code === 200) {
let sorts = camelCase(data.data);
return sorts.sort((a, b) => {
return a.sub.length >= b.sub.length;
});
} else {
return [];
}
})();
},
getShopHeadData(domain, uid) {
return co(function*() {
let domainInfo = yield BrandService.getDomainInfo(domain);
let info = {
brandId: domainInfo.id,
shopId: ''
};
if (domainInfo.shopId) {
let shopId = domainInfo.shopId;
let shopIntro = yield ShopService.getShopIntro(shopId, uid);
info.shopId = shopId;
info.name = shopIntro.shopName;
info.info = shopIntro.shopIntro;
info.btnName = '店铺介绍';
info.isFavorite = shopIntro.isFavorite === 'Y';
let shopData = yield Promise.all([ShopService.getShopDecorator(shopId),
ShopService.getShopSecondSorts(shopId)]);
let shopList = shopData[0];
let sorts = shopData[1];
let resources = resourceDataHandle(shopList.list);
info.sorts = sorts;
if (resources.shopTopBanner_base && resources.shopTopBanner_base.length > 0) { // eslint-disable-line
info.banner = resources.shopTopBanner_base[0].shopSrc; // eslint-disable-line
}
info.resources = resources;
info.menus = shopMenu(domain);
} else {
let brandId = domainInfo.id;
let brandInfo = yield BrandService.getBrandInfo(brandId, uid);
info.name = brandInfo.brandName;
info.info = brandInfo.brandIntro;
info.btnName = '品牌介绍';
info.isFavorite = brandInfo.isFavorite === 'Y';
info.banner = domainInfo.brandBanner;
}
return info;
})();
}
};
module.exports = ShopService;
... ...
<div class="blk-page yoho-shop-index">
<div class="center-content">
{{# navPath}}
{{> path-nav}}
{{/ navPath}}
</div>
<div class="center-content clearfix">
{{> brand-banner-list }}
{{> list/shop-menu }}
{{> list/banner-info }}
</div>
{{# banner.resources}}
{{#if newProducts}}
<div class="center-content clearfix slide-warp">
{{#each largeSlideImg}}
{{#each data}}
<div class="slide-left">
<a href="{{url}}">
<img src="{{src}}" alt="">
</a>
</div>
{{/each}}
{{/each}}
<div class="slide-right">
{{#each oneRowTwoColImages}}
{{#each data}}
<a href="{{url}}">
<img src="{{src}}" alt="">
</a>
{{/each}}
{{/each}}
</div>
</div>
{{/if}}
{{#if newProducts}}
<div class="center-content clearfix new-arrival-warp">
<div class="floor-header clearfix">
<h2 class="floor-title en-size">NEW ARRIVALS</h2>
<p class="floor-title zh-size">最新上架</p>
<a class="floor-more" href="#">MORE</a>
</div>
<div class="goods-wrap">
{{#each newProducts}}
<div class="goods-info" data-skn="{{productSkn}}">
<a href="" target="_blank">
<img class="lazy thumb" data-original="{{src}}" style="display: block;">
</a>
<div class="desc">
<a class="name" href="" target="_blank">{{productName}}</a>
<p class="price">{{round salesPrice 2}}</p>
</div>
</div>
{{/each}}
</div>
</div>
{{/if}}
{{#if hotProducts}}
<div class="center-content clearfix hot-product-warp">
<div class="floor-header clearfix">
<h2 class="floor-title en-size">HOT</h2>
<p class="floor-title zh-size">人气单品</p>
<a class="floor-more" href="#">MORE</a>
</div>
<div class="goods-wrap">
{{#each hotProducts}}
<div class="goods-info" data-skn="{{productSkn}}">
<a href="" target="_blank">
<img class="lazy thumb" data-original="{{src}}" style="display: block;">
</a>
<div class="desc">
<a class="name" href="" target="_blank">{{productName}}</a>
<p class="price">{{round salesPrice 2}}</p>
</div>
</div>
{{/each}}
</div>
</div>
{{/if}}
{{/ banner.resources}}
<div class="center-content clearfix all-product-warp">
<div class="floor-header clearfix">
<h2 class="floor-title en-size">ALL</h2>
<p class="floor-title zh-size">全部商品</p>
</div>
{{> list/shop-sort}}
{{> list/order-area}}
<div class="goods-wrap">
</div>
</div>
</div>
... ...
{{# brandBanner}}
{{# banner}}
<div class="brand-banner">
<div class="brand-img" style="height:150px; background: url('{{image bgImg 1150 150}}')"></div>
<div class="brand-img" style="height:150px; background: url('{{image banner 1150 150}}')"></div>
<p class="opts">
{{# brandIntro}}
<a id="brand-info">
<i class="iconfont">&#xe631;</i>
{{text}}
</a>
{{/ brandIntro}}
<a id="brand-info">
<i class="iconfont">&#xe631;</i>
{{btnName}}
</a>
<span id="brand-fav" class="brand-fav{{#if coled}} coled{{/if}}">
<span id="brand-fav" class="brand-fav{{#if isFavorite}} coled{{/if}}">
{{> icon/collection}}
</span>
</p>
</div>
{{/brandBanner}}
{{/banner}}
... ...
... ... @@ -11,9 +11,9 @@
{{productName}}
</div>
<div class="goods-price">
<span>¥{{salesPrice}}</span>
<span>¥{{round salesPrice}}</span>
{{#if marketPrice}}
<b>¥{{marketPrice}}</b>
<b>¥{{round marketPrice}}</b>
{{/if}}
</div>
<div class="goods-list hide">
... ...
<ul class="shop-menu">
{{#each shopMenu}}
<li>
<a href="{{href}}">
{{name}}
{{#icon}}
<i class="iconfont">&#xe60a;</i>
{{/icon}}
</a>
</li>
{{/each}}
</ul>
{{# banner}}
{{#if menus}}
<ul class="shop-menu">
{{#each menus}}
<li>
<a href="{{href}}">
{{name}}
{{#icon}}
<i class="iconfont">&#xe60a;</i>
{{/icon}}
</a>
</li>
{{/each}}
</ul>
{{/if}}
{{/ banner}}
... ...
<div class="shop-sort">
<div class="all">所有商品</div>
<div class="sort-list">
<div><a href="#">女装</a></div>
<div><a href="#">男装</a></div>
{{# each banner.sorts}}
<div><a href="#">{{categoryName}}</a></div>
{{/ each}}
</div>
<div class="more">MORE</div>
</div>
... ...
... ... @@ -59,7 +59,7 @@
"uuid": "^2.0.2",
"winston": "^2.2.0",
"winston-daily-rotate-file": "^1.1.4",
"yoho-node-lib": "0.0.17"
"yoho-node-lib": "0.0.20"
},
"devDependencies": {
"autoprefixer": "^6.3.6",
... ...
var lazyload = require('yoho-jquery-lazyload');
lazyload();
... ...
@import 'list';
@import 'item';
@import 'shop-list';
@import '_shop.css';
/* 组件 */
@import 'brand-banner';
... ...
.yoho-product-list {
@import "order-area";
font-size: 14px;
.btn {
... ... @@ -239,92 +239,6 @@
}
}
.order-area {
border-top: 1px solid #eee;
border-bottom: 1px solid #eee;
color: #878787;
font-weight: 700;
.order {
display: inline-block;
margin: 14px 15px;
height: 24px;
line-height: 24px;
cursor: pointer;
}
.dest {
display: inline-block;
position: relative;
width: 15px;
height: 24px;
line-height: 24px;
margin: 14px 15px;
margin-left: -10px;
margin-bottom: -10px;
cursor: pointer;
.iconfont {
display: block;
font-size: 12px;
height: 12px;
line-height: 12px;
position: absolute;
}
.iconfont.selected {
color: #1b1b1b;
}
.iconfont.up {
top: -2px;
}
.iconfont.down {
top: 8px;
}
}
.order.selected {
color: #1b1b1b;
}
.right {
width: auto;
height: 24px;
line-height: 24px;
margin-top: 12px;
label {
color: #1b1b1b;
font-weight: 700;
display: inline-block;
}
label.page-info {
margin: 0 25px;
}
.page {
color: #1b1b1b;
font-weight: 700;
border: 2px solid #1b1b1b;
width: 24px;
height: 24px;
line-height: 24px;
display: inline-block;
font-size: 14px;
text-align: center;
margin-right: 8px;
cursor: pointer;
}
.page.disable {
color: #878787;
border: 2px solid #878787;
}
}
}
.goods-area {
margin: 0 -12px;
... ...
.order-area {
border-top: 1px solid #eee;
border-bottom: 1px solid #eee;
color: #878787;
font-weight: 700;
.order {
display: inline-block;
margin: 14px 15px;
height: 24px;
line-height: 24px;
cursor: pointer;
}
.dest {
display: inline-block;
position: relative;
width: 15px;
height: 24px;
line-height: 24px;
margin: 14px 15px;
margin-left: -10px;
margin-bottom: -10px;
cursor: pointer;
.iconfont {
display: block;
font-size: 12px;
height: 12px;
line-height: 12px;
position: absolute;
}
.iconfont.selected {
color: #1b1b1b;
}
.iconfont.up {
top: -2px;
}
.iconfont.down {
top: 8px;
}
}
.order.selected {
color: #1b1b1b;
}
.right {
width: auto;
height: 24px;
line-height: 24px;
margin-top: 12px;
label {
color: #1b1b1b;
font-weight: 700;
display: inline-block;
}
label.page-info {
margin: 0 25px;
}
.page {
color: #1b1b1b;
font-weight: 700;
border: 2px solid #1b1b1b;
width: 24px;
height: 24px;
line-height: 24px;
display: inline-block;
font-size: 14px;
text-align: center;
margin-right: 8px;
cursor: pointer;
}
.page.disable {
color: #878787;
border: 2px solid #878787;
}
}
}
... ...
.yoho-product-list {
.yoho-product-list,
.yoho-shop-index {
.brand-banner {
width: 100%;
... ... @@ -52,6 +53,139 @@
}
.yoho-shop-index {
font-size: 14px;
@import "order-area";
.slide-warp {
margin-bottom: 80px;
.slide-left {
float: left;
width: 375px;
height: 400px;
margin-right: 20px;
}
.slide-right {
float: right;
width: 360px;
height: 400px;
a {
display: block;
img {
width: 100%;
height: 190px;
}
}
a:first-child {
margin-bottom: 20px;
}
}
}
.new-arrival-warp,
.hot-product-warp {
margin-bottom: 75px;
}
.new-arrival-warp,
.all-product-warp {
.goods-wrap {
margin: 30px -10px 0;
.goods-info {
display: inline-block;
width: 270px;
margin: 0 9px;
border-width: 1px;
}
}
}
.hot-product-warp {
.goods-wrap {
margin: 30px -10px 0;
.goods-info {
position: relative;
display: inline-block;
width: 369px;
height: 495px;
margin: 0 9px;
border-width: 1px;
.desc {
position: absolute;
bottom: 0;
width: 100%;
background-color: #000;
opacity: 0.6;
padding: 20px 0;
color: #fff;
}
}
}
}
.floor-header {
position: relative;
.floor-more {
position: absolute;
right: 0;
bottom: 0;
font-size: 14px;
font-weight: 700;
}
}
.shop-sort {
margin: 30px 0;
height: 30px;
vertical-align: middle;
font-size: 14px;
.all {
color: #f31a2a;
height: 30px;
line-height: 30px;
float: left;
border-right: 1px solid #bbb;
padding-right: 15px;
font-weight: 700;
}
.more {
height: 30px;
line-height: 30px;
float: right;
font-weight: 700;
}
.sort-list {
float: left;
height: 30px;
line-height: 30px;
div {
float: left;
margin: 0 5px;
padding: 0 10px;
height: 30px;
}
div:hover {
background-color: #000;
a {
color: #fff !important;
}
}
}
}
}
.yoho-dialog.brand-info-dialog {
width: 900px;
height: 600px;
... ...