Authored by 郝肖肖

'个性化数据'

'use strict';
const TideModel = require('../models/tide');
const headerModel = require('../../../doraemon/models/header');
/**
* 潮品推介
*/
exports.category = (req, res, next) => {
let uid = req.user.uid || req.query.uid;
let params = {
uid: uid,
isApp: req.yoho.isApp,
scene: req.query.scene || 1
};
let renders = {};
if (!req.yoho.isApp) {
renders = {
title: req.query.title || '潮流推荐 | Yoho!Buy有货 | 潮流购物逛不停',
pageHeader: headerModel.setNav({
navTitle: req.query.title || '潮流推荐'
}),
pageFooter: true,
};
}
return req.ctx(TideModel).tideCategory(params).then(result => {
res.render('tide/category', Object.assign(renders, {
module: 'tide',
page: 'category',
width750: true,
localCss: true,
result: result
}));
}).catch(next);
};
/**
* 潮牌推介
*/
exports.shop = (req, res, next) => {
let uid = req.user.uid || req.query.uid;
let params = {
uid: uid,
isApp: req.yoho.isApp,
scene: req.query.scene || 1
};
let renders = {};
if (!req.yoho.isApp) {
renders = {
title: req.query.title || '潮流推荐 | Yoho!Buy有货 | 潮流购物逛不停',
pageHeader: headerModel.setNav({
navTitle: req.query.title || '潮流推荐'
}),
pageFooter: true,
};
}
return req.ctx(TideModel).tideShop(params).then((result) => {
res.render('tide/shop', Object.assign(renders, {
module: 'tide',
page: 'shop',
width750: true,
localCss: true,
result: result
}));
}).catch(next);
};
... ...
'use strict';
const _ = require('lodash');
const helpers = global.yoho.helpers;
const ROOTPATH = '../../../';
const contentCodeConfig = require(`${ROOTPATH}config/content-code`);
const productProcess = require(`${ROOTPATH}utils/product-process`);
class TideModel extends global.yoho.BaseModel {
constructor(ctx) {
super(ctx);
}
tideCategory(params) {
return Promise.all([
this.getResource(Object.assign({
content_code: contentCodeConfig.tide.category
}, params)),
this.crmRecommendSort(params)
]).then(res => {
let tide = {
resource: _.get(res[0], 'data', []),
contents: []
};
let sindex = _.findIndex(tide.resource, {template_name: 'image_list'});
if (sindex > -1) {
tide.resource[sindex].title = '# 精彩活动 #';
}
_.each(_.get(res[1], 'data', []), (item, index) => {
item.sortInfo = item.sortInfo || {};
let goods = productProcess.processProductList(item.productList || [], {
isApp: params.isApp,
showSimilar: false
});
let tdata = {
sortInfo: Object.assign({}, item.sortInfo, {
url: helpers.urlFormat(`/list/mi${item.sortInfo.itemId}`, {
'openby:yohobuy': `{"action":"go.list","params":{"misort":"${item.sortInfo.itemId}"}}`
})
}),
goods: goods
};
if (index === 0) {
tdata.title = '# 潮品推介 #';
} else {
tdata.borderTop = true;
}
tide.contents.push(tdata);
});
return tide;
});
}
// 促购个性化3个品类商品推荐
crmRecommendSort(params) {
return this.get({
data: Object.assign({
method: 'app.product.crmRecommend.sort'
}, params)
});
}
// 促购个性化店铺商品推荐(1个店铺+店铺下6个商品)
crmRecommendShopSix(params) {
return this.get({
data: Object.assign({
method: 'app.product.crmRecommend.shopSix'
}, params)
});
}
// 促购个性化店铺推荐(9个店铺)
crmRecommendShop(params) {
return this.get({
data: Object.assign({
method: 'app.product.crmRecommend.shop'
}, params)
});
}
// 促购个性化店铺推荐(30个商品)
crmRecommendProduct(params) {
return this.get({
data: Object.assign({
method: 'app.product.crmRecommend.product'
}, params)
});
}
tideShop(params) {
return Promise.all([
this.getResource(Object.assign({
content_code: contentCodeConfig.tide.brand
}, params)),
this.crmRecommendShopSix(params),
this.crmRecommendShop(params),
this.crmRecommendProduct(params)
]).then(res => {
let tide = {
resource: _.get(res[0], 'data', []),
brands: [],
shopInfo: [],
contents: []
};
let sindex = _.findIndex(tide.resource, {template_name: 'image_list'});
if (sindex > -1) {
tide.resource[sindex].title = '# 精彩活动 #';
}
let shopInfo = _.get(res[1], 'data.shopInfo', {});
if (shopInfo.shopId) {
shopInfo.url = helpers.urlFormat(`/shop/${shopInfo.shopDomain}-${shopInfo.shopId}.html`, {
'openby:yohobuy': `{"action":"go.shop","params":{"shop_id":"${shopInfo.shopId}","shop_template_type":"${shopInfo.shopTemplateType}","shop_name":"${shopInfo.shopName}"}}` //eslint-disable-line
});
}
if (shopInfo.shopId || _.get(res[1], 'data.productList', []).length) {
tide.shopInfo.push({
title: '# 为你精选 #',
shopInfo: shopInfo,
goods: productProcess.processProductList(_.get(res[1], 'data.productList', []), {
isApp: params.isApp,
showSimilar: false
})
});
}
_.each(_.get(res[2], 'data', []), (item) => {
tide.brands.push(Object.assign({}, item, {
url: helpers.urlFormat(`/shop/${item.shopDomain}-${item.shopId}.html`, {
'openby:yohobuy': `{"action":"go.shop","params":{"shop_id":"${item.shopId}","shop_template_type":"${item.shopTemplateType}","shop_name":"${item.shopName}"}}` //eslint-disable-line
})
}));
});
if (_.get(res[3], 'data', []).length) {
tide.contents.push({
title: '# 潮品推介 #',
goods: productProcess.processProductList(_.get(res[3], 'data', []), {
isApp: params.isApp,
showSimilar: false
})
});
}
return tide;
});
}
getResource(params) {
return this.get({
url: 'operations/api/v5/resource/get',
data: Object.assign({
platform: 'iphone'
}, params),
api: global.yoho.ServiceAPI,
param: {cache: true}
}).then(result => {
return result;
});
}
}
module.exports = TideModel;
... ...
... ... @@ -38,6 +38,8 @@ const individuation = require(`${cRoot}/individuation`);
const feature = require(`${cRoot}/feature`);
const tide = require(`${cRoot}/tide`);
const appDownloads = require(`${cRoot}/app-downloads`);
const redbag = require(`${cRoot}/redbag`);
... ... @@ -268,6 +270,8 @@ router.get('/feature/:code.html', feature.index);
router.get('/featuresidebar/:code.html', feature.sidebar);
router.get('/featurebottombar/:code.html', feature.bottombar);
router.get('/feature/couponSend', feature.couponSend); // 获取优惠券
router.get('/tide/category', auth, tide.category); // 潮品推介
router.get('/tide/shop', auth, tide.shop); // 潮牌推介
// 2016 年度账单
router.get('/annual-account', annualAccount.index);
... ...
<div class="activity-cate-page">
<div class="brand-block"></div>
<div class="tide-promotion-container">
<div class="tide-title"># 潮品推介 #</div>
<div class="tide-goods">
<div class="goods">
<div class="goods-img"><img src="//img11.static.yhbimg.com/goodsimg/2018/03/30/14/01a5f5036a8829c4c01aa8d02b1f9f9ac7.png?imageMogr2/thumbnail/235x314/background/d2hpdGU=/position/center/quality/60" /></div>
<div class="goods-name">adidas Originals </div>
<div class="goods-footer">
<div class="goods-price">¥249 <span class="old-price">¥249</span></div>
<div class="cart-icon"></div>
</div>
</div>
</div>
</div>
</div>
... ...
<div class="activity-tide-page">
{{> tide/resource-top resource=result.resource}}
{{#result.contents}}
{{#if title}}
<div class="tide-title">{{title}}</div>
{{/if}}
{{#if borderTop}}
<div class="tide-border-top"></div>
{{/if}}
<div class="tide-goods">
{{#if sortInfo.imageUrl}}
<div class="cate-block">
<a href="{{sortInfo.url}}">
<img class="lazy" data-original="{{image sortInfo.imageUrl 217 300 1}}" />
</a>
</div><!--/cate-block-->
{{/if}}
{{> tide/goods}}
</div><!--/tide-goods-->
{{/result.contents}}
{{> tide/resource-bottom resource=result.resource}}
</div>
... ...
<div class="activity-tide-page">
{{> tide/resource-top resource=result.resource}}
{{#result.shopInfo}}
{{#if title}}
<div class="tide-title">{{title}}</div>
{{/if}}
<div class="tide-goods">
{{> tide/shop-info}}
{{> tide/goods}}
</div><!--/tide-goods-->
{{/result.shopInfo}}
{{#if result.brands}}
<div class="tide-title"># 潮牌推介 #</div>
<div class="tide-brand">
{{> tide/brands brands=result.brands}}
</div>
{{/if}}
{{#result.contents}}
{{#if title}}
<div class="tide-title">{{title}}</div>
{{/if}}
{{#if borderTop}}
<div class="tide-border-top"></div>
{{/if}}
<div class="tide-goods">
{{> tide/shop-info}}
{{#if sorts.sortImg}}
<div class="cate-block">
<img class="lazy" data-original="{{image sorts.sortImg 216 300 1}}">
</div><!--/cate-block-->
{{/if}}
{{> tide/goods}}
</div><!--/tide-goods-->
{{/result.contents}}
{{> tide/resource-bottom resource=result.resource}}
</div>
... ...
{{#brands}}
<div class="brand">
<a href="{{url}}">
<div class="brand-block">
<img class="brand-img lazy" data-original="{{image imageUrl 216 270 2}}" alt="{{name}}">
<div class="goods-name ellipsis">{{shopName}}</div>
</div>
<div class="entry-brand">
进入店铺&nbsp;&nbsp;<span class="iconfont">&#xe614;</span>
</div>
</a>
</div>
{{/brands}}
... ...
{{#goods}}
<div class="goods">
<a class="good-thumb" href="{{url}}">
<div class="goods-img">
<img class="lazy" data-original="{{image default_images 217 288 1}}" alt="{{imgAlt}}">
</div>
<div class="goods-footer">
<div class="goods-name ellipsis">{{brand_name}}</div>
<div class="goods-bottom">
<div class="sales-price">
¥{{round sales_price 0}}{{#if market_price}}&nbsp;&nbsp;<span class="market-price">¥{{round market_price 0}}</span>{{/if}}
</div>
<div class="cart-icon"></div>
</div>
</div>
</a>
</div>
{{/goods}}
... ...
{{#resource}}
{{#isEqualOr template_name 'image_list'}}
{{#if title}}<div class="tide-title">{{title}}</div>{{/if}}
<div class="wonderful-container">
{{#isEqualOr data.title.column_num '1'}}
{{#each data.list}}
<div class="wonderful-big">
<a href="{{url}}">
<img class="lazy" data-original="{{image src 670 330 1}}" />
<div class="see-block">点击查看&nbsp;&nbsp;<span class="iconfont">&#xe614;</span></div>
</a>
</div>
{{/each}}
{{/isEqualOr}}
{{#isEqualOr data.title.column_num '2'}}
{{#each data.list}}
<div class="wonderful-small">
<a href="{{url}}">
<img class="lazy" data-original="{{image src 320 220 1}}" />
<div class="see-block">点击查看&nbsp;&nbsp;<span class="iconfont">&#xe614;</span></div>
</a>
</div>
{{/each}}
{{/isEqualOr}}
</div>
{{/isEqualOr}}
{{#isEqualOr template_name 'divideImage'}}
{{#each data}}
<div class="footer-banner">
<a href="{{url}}">
<img class="lazy" data-original="{{image src 750 500 1}}" />
</a>
</div>
{{/each}}
{{/isEqualOr}}
{{/resource}}
... ...
{{#resource}}
{{#isEqualOr template_name 'single_image'}}
{{#each data}}
<div class="brand-banner">
<img src="{{image src 750 360 1}}" />
</div>
{{/each}}
{{/isEqualOr}}
{{/resource}}
... ...
{{#if shopInfo.imageUrl}}
<div class="brand-block-big">
<a href="{{shopInfo.url}}">
<img class="brand-img" src="{{image shopInfo.imageUrl 314 352 2}}" alt="{{shopInfo.shopName}}" />
</a>
<a href="{{shopInfo.url}}">
<div class="brand-info">
<div class="brand-logo">
<img src="{{image shopInfo.logoUrl 130 130 2}}" />
</div>
<div class="name">{{shopInfo.shopName}}</div>
<div class="promotion-title ellipsis">{{shopInfo.promotionTitle}}</div>
<div class="entry-brand">进入店铺&nbsp;&nbsp;<span class="iconfont">&#xe614;</span></div>
</div>
</a>
</div>
{{/if}}
... ...
... ... @@ -68,6 +68,12 @@ const liveContentCode = {
index: '345c80537dca15611f37ae4863004bfe'
};
// 个性化推荐
const tideContentCode = {
category: 'f5fccd93c21f740d7dd4a39aa938ee01', // 潮品类推介
brand: 'cfae8d475468b3109115d1c45596e155', // 潮品牌推介
};
module.exports = {
sale: saleContentCode,
outlet: outletContentCode,
... ... @@ -76,5 +82,6 @@ module.exports = {
guang: guangContentCode,
new: newContentCode, // TODO: remove
newV2: newContentCodeV2,
live: liveContentCode
live: liveContentCode,
tide: tideContentCode
};
... ...
import 'tide/category.page.css';
import $ from 'yoho-jquery';
import Page from 'yoho-page';
import lazyLoad from 'yoho-jquery-lazyload';
import share from 'common/share';
class TideCategory extends Page {
constructor() {
super();
this.selector = {
$tidePage: $('.activity-tide-page'),
};
this.init();
}
init() {
lazyLoad(this.selector.$tidePage.find('img.lazy'));
share({});
}
}
$(() => {
new TideCategory();
});
... ...
import 'tide/category.page.css';
import $ from 'yoho-jquery';
import Page from 'yoho-page';
import lazyLoad from 'yoho-jquery-lazyload';
import share from 'common/share';
class TideShop extends Page {
constructor() {
super();
this.selector = {
$tidePage: $('.activity-tide-page'),
};
this.init();
}
init() {
lazyLoad(this.selector.$tidePage.find('img.lazy'));
share({});
}
}
$(() => {
new TideShop();
});
... ...
.activity-tide-page {
.ellipsis {
display: -webkit-box !important;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
overflow: hidden;
}
.tide-title {
font-weight: 900;
font-size: 37px;
color: #000;
text-align: center;
padding: 30px 0 5px;
letter-spacing: 10px;
}
.tide-goods,
.tide-brand {
margin: 0 30px 0 39px;
display: flex;
flex-wrap: wrap;
}
.tide-brand {
.brand {
margin: 25px 10px 0 0;
width: 216px;
height: 282px;
background-color: #f7f8f8;
.brand-block {
width: 216px;
height: 242px;
overflow: hidden;
position: relative;
&:after {
content: "";
width: 216px;
height: 114px;
background-image: url("/activity/tide-brand-bg.png");
background-repeat: no-repeat;
background-size: contain;
margin-right: 10px;
position: absolute;
bottom: 0;
}
.brand-logo {
width: 130px;
height: 130px;
overflow: hidden;
position: absolute;
top: 70px;
left: 50%;
margin-left: -65px;
opacity: 0.6;
z-index: 3;
}
.goods-name {
font-size: 16px;
color: #fff;
position: absolute;
width: inherit;
text-align: center;
bottom: 10px;
z-index: 3;
padding: 0 5px;
-webkit-line-clamp: 1;
font-weight: bold;
}
}
.entry-brand {
width: inherit;
border: 2px solid #bdbdbd;
text-align: center;
font-size: 21px;
font-weight: bold;
height: 40px;
line-height: 40px;
background-color: #fff;
border-top: none;
span {
font-size: 13px;
vertical-align: middle;
}
}
}
}
.tide-goods {
.cate-block {
margin: 25px 10px 0 0;
width: 217px;
height: 288px;
overflow: hidden;
background-color: #f7f8f8;
}
.goods {
margin: 25px 10px 0 0;
width: 217px;
height: 288px;
background-color: #f7f8f8;
position: relative;
.goods-img img {
width: 217px;
height: 288px;
}
.goods-footer {
font-size: 19px;
color: #fff;
font-weight: bold;
position: absolute;
bottom: 0;
width: 100%;
padding: 3px 15px;
opacity: 0.7;
background-color: #000;
.goods-name {
-webkit-line-clamp: 1;
word-wrap: normal;
}
.goods-bottom {
display: flex;
justify-content: space-between;
align-items: center;
}
}
.market-price {
font-size: 13px;
color: #ccc;
font-weight: normal;
}
.cart-icon {
width: 25px;
height: 20px;
background-image: url("/activity/cart-icon.png");
background-repeat: no-repeat;
background-size: contain;
margin-right: 10px;
}
}
}
.wonderful-container {
display: flex;
flex-wrap: wrap;
margin: 20px 20px 0 40px;
.wonderful-big {
margin-right: 20px;
margin-bottom: 40px;
width: 670px;
height: 306px;
position: relative;
img {
width: 100%;
height: 100%;
overflow: hidden;
}
}
.wonderful-small {
margin-right: 20px;
margin-bottom: 40px;
width: 325px;
height: 220px;
position: relative;
img {
width: inherit;
height: inherit;
overflow: hidden;
}
}
.see-block {
background-color: #000;
text-align: center;
font-size: 17px;
color: #fff;
width: 180px;
height: 40px;
line-height: 40px;
bottom: -20px;
position: absolute;
left: 50%;
margin-left: -100px;
box-shadow: 1px 1px 1px #000;
span {
font-size: 15px;
}
}
}
.brand-block-big {
width: 650px;
display: flex;
flex-wrap: wrap;
margin: 25px 10px 0 20px;
.brand-img {
width: 314px;
height: 352px;
overflow: hidden;
margin-right: 15px;
}
.brand-info {
width: 314px;
height: 352px;
border: 4px solid #eaeaea;
text-align: center;
position: relative;
&:before {
content: "";
width: 31px;
height: 45px;
background-image: url("/activity/l-arrow-icon.png");
background-repeat: no-repeat;
background-size: contain;
position: absolute;
left: -31px;
top: 50%;
margin-top: -22px;
}
.brand-logo {
width: 210px;
height: 105px;
overflow: hidden;
margin: 40px auto 20px;
}
.name {
font-size: 20px;
color: #000;
margin: 5px 0;
}
.promotion-title {
font-size: 24px;
margin: 10px;
-webkit-line-clamp: 2;
}
.promotion-title .minus {
color: #f00000;
}
.entry-brand {
background-color: #000;
text-align: center;
font-size: 19px;
font-weight: bold;
color: #fff;
width: 160px;
height: 30px;
line-height: 30px;
box-shadow: 1px 1px 1px #000;
display: inline-block;
span {
font-size: 17px;
}
}
}
}
.tide-border-top {
margin: 35px 30px 10px 40px;
border-top: 2px solid #b0b0b0;
}
}
... ...