Showing 69 changed files with 2466 additions and 1483 deletions

Too many changes to show.

To preserve performance only 69 of 69+ files are displayed.

... ... @@ -143,3 +143,7 @@ public/bundle/*
.vscode/
.DS_Store
.devhost
### foreman ###
Procfile
.env
... ...
... ... @@ -90,8 +90,7 @@ const _handelPaymentInfo = (d) => {
_.forEach(d.goods_list, g => {
// link to goods
g.linkToGoods = helper.urlFormat(`/product/pro_${g.product_id}_${g.goods_id}/${g.cn_alphabet}.html`,
'', 'item');
g.linkToGoods = helper.getUrlBySkc(g.product_id, g.goods_id, g.cn_alphabet);
});
resData.goodsList = d.goods_list;
... ...
... ... @@ -263,7 +263,7 @@
</div>
<ul id="balance-detail" class="balance-detail right">
<li class="gain-coin">
<a class="gain-coin-tip" href="/help/?category_id=87" target="_blank"></a>
<a class="gain-coin-tip" href="/help/detail?id=105" target="_blank"></a>
共返YOHO币:{{gain_yoho_coin}}
</li>
{{#each promotion_formula_list}}
... ... @@ -326,7 +326,7 @@
<p class="btns">
<span id="coin-sure" class="coin-sure sure-btn">确定</span>
<span id="coin-cancel" class="coin-cancel cancel-btn">取消</span>
<a href="/help/?category_id=87" class="coin-help" target="_blank">有货币使用规则?</a>
<a href="/help/detail?id=105" class="coin-help" target="_blank">有货币使用规则?</a>
</p>
</div>
<input id="coin-used" type="hidden" data-coin="{{usedCoinNum}}" data-max={{canUseCoinNum}}>
... ...
... ... @@ -41,8 +41,7 @@ const index = (skn, limit) => {
market_price: mp === sp ? '' : ${helper.round(mp, 2)}`,
price: ${helper.round(sp, 2)}`,
product_name: hp.product_name,
url: helper.urlFormat(
`/product/pro_${hp.product_id}_${defaultGoods.goods_id}/${hp.cn_alphabet}.html`, null, 'item'),
url: helper.getUrlBySkc(hp.product_id, defaultGoods.goods_id, hp.cn_alphabet),
pic_url: helper.image(defaultGoods.images_url, 280, 382, 2, 70)
});
});
... ...
... ... @@ -17,7 +17,7 @@ let ALL_TYPES = {
ellipsis: 'p-pe-n'
};
exports.pager = function() {
exports.gpager = function() {
let options = arguments[arguments.length - 1];
... ...
... ... @@ -20,7 +20,7 @@
{{/ msgs}}
</div>
<div class="msg-pager pager">
{{pager baseUrl totalRecords=total page=page type="ellipsis" theme="msg-pager"}}
{{gpager baseUrl totalRecords=total page=page type="ellipsis" theme="msg-pager"}}
</div>
</div>
<div class="right-side">
... ...
... ... @@ -30,7 +30,7 @@
{{> msg}}
{{/ msgs}}
</div>
{{pager baseUrl totalRecords=total page=page type="ellipsis" theme="msg-pager"}}
{{gpager baseUrl totalRecords=total page=page type="ellipsis" theme="msg-pager"}}
</div>
</div>
<div class="right-side">
... ...
... ... @@ -12,7 +12,7 @@
{{/ msgs}}
</div>
{{pager baseUrl totalRecords=total page=page type="ellipsis" theme="msg-pager"}}
{{gpager baseUrl totalRecords=total page=page type="ellipsis" theme="msg-pager"}}
</div>
<div class="right-side">
{{> right-side}}
... ...
... ... @@ -18,6 +18,6 @@
</li>
{{/ list}}
</ul>
<div class="comment-pager pager">{{pager baseUrl totalRecords=commentNum page=page pageSize=pageSize type="ellipsis" theme="msg-pager"}}</div>
<div class="comment-pager pager">{{gpager baseUrl totalRecords=commentNum page=page pageSize=pageSize type="ellipsis" theme="msg-pager"}}</div>
</div>
{{/ comment}}
... ...
'use strict';
const yohobuy = (req, res, next) => {
res.render('help/yohobuy');
};
const newpower = (req, res, next) => {
res.render('help/newpower');
};
const contact = (req, res, next) => {
res.render('help/contact');
};
const privacy = (req, res, next) => {
res.render('help/privacy');
};
const yoholink = (req, res, next) => {
res.render('help/link');
};
module.exports = {
yohobuy,
newpower,
contact,
privacy,
yoholink
};
/**
* 帮助中心
* @author: jiangmin
* @date: 2016/07/25
*/
'use strict';
const helpModel = require('../models/help');
const index = (req, res, next) => {
let siteUrl = global.yoho.config.siteUrl;
let channel = req.query.channel ? req.query.channel : 'boys';
helpModel.helpData(channel).then(result => {
if (result.content.menuData.length === 0) {
return next();
}
res.render('help', Object.assign({
module: 'help',
page: 'help-index',
content: Object.assign({
siteUrl: siteUrl,
isHelp: true,
pathNav: [
{
href: siteUrl,
name: 'YOHO!BUY 有货首页'
},
{
name: '帮助中心'
}
]
}, result.content)
}, result.headerData));
}).catch(next);
};
/**
* 详情
*/
const detail = (req, res, next) => {
let q = req.query;
let params = {
id: parseInt(q.id || 1, 10),
contId: +req.query.contId || 0,
keywords: req.query.helpQuery,
channel: req.query.channel ? req.query.channel : 'boys',
url: req.originalUrl,
page: q.page || 1
};
let nav = [
{
href: global.yoho.config.siteUrl,
name: 'YOHO!BUY 有货首页'
},
{
name: '帮助中心',
href: '/help'
}
];
helpModel.detailData(params).then(result => {
let newData = result.newData;
let headerData = result.headerData;
if (result.newData.data.menuData.length === 0) {
return next();
}
if (!(typeof (newData.nav) === 'undefined')) {
nav = nav.concat(newData.nav);
}
res.render('detail', Object.assign({
module: 'help',
page: 'help',
content: Object.assign({
isHelp: true,
pathNav: nav,
helpQuery: req.query.helpQuery
}, newData.data),
qid: q.helpQuery ? false : params.id
}, headerData));
}).catch(next);
};
// 帮助搜索功能
const search = (req, res, next) => {
helpModel.searchData(req.query).then(result => {
res.json(result);
}).catch(next);
};
// 获取在线客服的链接
const onlineService = (req, res, next) => {
helpModel.onlineService().then(url => {
res.json(url);
}).catch(next);
};
module.exports = {
index,
detail,
search,
onlineService
};
... ...
'use strict';
const mRoot = '../models';
const index = (req, res, next) => {
res.render('help/index', {});
};
module.exports = {
index
};
/**
* sub app help
* @author: yyq<yanqing.yang@yoho.cn>
* @date: 2016/11/14
* help
* @author: lcy<chuanyang.liu@yoho.cn>
* @date: 2016/08/31
*/
'use strict';
var express = require('express'),
path = require('path');
var express = require('express'),
path = require('path');
var app = express();
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.use(global.yoho.hbs({
extname: '.hbs',
defaultLayout: 'layout',
layoutsDir: doraemon,
partialsDir: [path.join(__dirname, 'views/partial')],
views: path.join(__dirname, 'views/action'),
helpers: global.yoho.helpers
}));
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.use(global.yoho.hbs({
extname: '.hbs',
defaultLayout: 'layout',
layoutsDir: doraemon,
partialsDir: [path.join(__dirname, 'views/partial')],
views: path.join(__dirname, 'views/action'),
helpers: global.yoho.helpers
}));
// router
app.use(require('./router'));
app.use(require('./router'));
module.exports = app;
module.exports = app;
... ...
/**
* 帮助中心首页
* @author: wsl<shuiling.wang@yoho.cn>
* @date: 2016/12/13
*/
'use strict';
const api = global.yoho.API;
// 获取热词搜索
const getHotSearch = () => {
return api.get('', {
method: 'app.helper.hotSearch',
showPlatform: 'yohobuy_pc'
}, {
code: 200,
cache: true
});
};
// 获取首页帮助分类以及常见问题
const gethomeCategoryFaq = () => {
return api.get('', {
method: 'app.helper.homeCategoryFaq',
showPlatform: 'yohobuy_pc'
}, {
code: 200,
cache: true
});
};
// 获取自助服务
const getSelfService = () => {
return api.get('', {
method: 'app.helper.selfService',
showPlatform: 'yohobuy_pc'
}, {
code: 200
});
};
const helpSearch = (params) => {
return api.get('', {
method: 'app.helper.search',
showPlatform: 'yohobuy_pc',
keyword: params.keywords,
page: params.page,
viewNum: '15',
debug: 'XYZ'
}, {
code: 200
});
};
const allQA = (page) => {
return api.get('', {
method: 'app.helper.allQA',
showPlatform: 'yohobuy_pc',
viewNum: 15,
page: page
}, {
code: 200
});
};
const onlineService = () => {
return api.get('', {
method: 'app.helper.getServiceOnline'
});
};
module.exports = {
getHotSearch,
gethomeCategoryFaq,
getSelfService,
helpSearch,
allQA,
onlineService
};
... ...
/**
* 帮助中心
* @author: jiangmin
* @date: 2016/07/27
*/
'use strict';
const _ = require('lodash');
const helpApi = require('./help-api');
const headerModel = require('../../../doraemon/models/header');
const pager = require(`${global.utils}/pager`).setPager;
/**
* 根据id获取当前所在位置,拼接面包屑
* @param id
* @param menuData
* @returns {*[]}
* @private
*/
const _getNav = (id, menuData, url)=> {
for (let i = 0; i < menuData.length; i++) {
if (menuData[i].subsets) {
for (let j = 0; j < menuData[i].subsets.length; j++) {
if (menuData[i].subsets[j].id === id) {
return [
{
href: url,
name: menuData[i].categoryName
}, {
name: menuData[i].subsets[j].categoryName
}
];
}
}
} else {
if (menuData[i].id === id) {
return [
{
name: menuData[i].categoryName
}
];
}
}
}
};
// 首页链接组装
const _processLink = (list, id) => {
let params = '';
list = list || [];
_.forEach(list, d => {
if (id) {
params = 'id=' + id + '&contId=' + d.id;
} else {
params = 'id=' + d.id;
}
d.jumpLink = global.yoho.config.siteUrl + '/help/detail?' + params;
});
return list;
};
// 处理分类
const _processMenuType = (item) => {
let curMenu = {
id: item.id,
categoryName: item.categoryName
};
let subsets = [];
if (item.categoryItems) {
_.forEach(item.categoryItems, c => {
subsets.push({
id: c.id,
parendId: item.id,
categoryName: c.categoryName
});
});
curMenu.subsets = subsets;
}
return curMenu;
};
// 统计当前分类下的内容是否大于1
const _processCountLength = (c) => {
if (!c.contentItems) {
return false;
} else {
return c.contentItems.length > 1;
}
};
// 首页模块内容处理
const _processHomeCategoryFaq = (list) => {
let result = {
menuData: []
};
list = list || {};
// 常见问题
if (list.faqs) {
result.menuData.push({
id: 1,
categoryName: '常见问题'
});
}
_.forEach(list.categorys, (item) => {
let newCont = [];
result.menuData.push(_processMenuType(item));
if (item.categoryItems) {
item.categoryItems = _processLink(item.categoryItems);
} else {
item.contentItems = _processLink(item.contentItems, item.id);
}
switch (item.categoryName) {
case '新手指南':
_.forEach(item.categoryItems, (ng, k) => {
ng.index = k + 1;
});
item.categoryItems = _.chunk(item.categoryItems, 6);
result.newGuide = item;
break;
case '公告':
_.forEach(item.contentItems, (c, k) => {
c.caption = c.caption.substring(0, 10);
c.index = k;
});
_.chunk(item.contentItems, 2).forEach(data => {
newCont.push({
row: data
});
});
result.notice = newCont;
break;
default:
break;
}
});
result.problem = {
categoryName: '常见问题',
list: list.faqs
};
return result;
};
const returnCont = (data, contId) => {
let curCont = {};
if (!data.contentItems) {
return;
}
_.forEach(data.contentItems, c => {
if (c.id === contId) {
curCont = c;
}
});
return {
isShowMenu: _processCountLength(data),
id: data.id,
title: data.categoryName,
list: data.contentItems,
contId: contId ? contId : data.contentItems[0].id,
cont: contId ? curCont : data.contentItems[0]
};
};
// 处理详情内容
const _processDetailCont = (item, params) => {
let cont = false;
if (item.contentItems && item.id === params.id) {
return returnCont(item, params.contId);
}
if (item.categoryItems) {
_.forEach(item.categoryItems, c => {
if (c.id === params.id) {
cont = returnCont(c, params.contId);
}
});
return cont;
}
return false;
};
// 处理搜索结果内容
const _processSearch = (list, params) => {
list = list || [];
if (list.total === 0) {
return {
error: true
};
} else {
let page = pager(_.get(list, 'page_total', 0), {
page: params.page,
helpQuery: params.keywords
});
list = _.assign({
footPager: page
}, list);
}
return list;
};
// 详情内容及分类数据
const _processDetailData = (result, params) => {
let menuData = [];
let contData = false;
let data = _.get(result, '[2].data', {});
let nav = [];
// 常见问题
if (data.faqs) {
menuData.push({
id: 1,
categoryName: '常见问题'
});
if (params.id === 1 && !params.keywords) {
let page = pager(_.get(result, '[3].data.page_total', 0), {
id: params.id,
page: params.page
});
contData = {
isShowMenu: _processCountLength(data.faqs),
id: 1,
commonProblem: true,
faqs: data.faqs,
allQa: _.get(result, '[3].data.list', []),
footPager: page
};
}
}
// 其它分类数据处理
_.forEach(data.categorys, item => {
let resCont;
menuData.push(_processMenuType(item));
if (contData || params.keywords) {
return;
}
resCont = _processDetailCont(item, params);
if (resCont) {
contData = _.assign({
helpDetail: true
}, resCont);
}
});
if (params.keywords) {
nav = [
{
name: '搜索结果'
}
];
} else {
nav = _getNav(params.id, menuData, params.url);
}
return {
nav: nav,
data: {
menuData: menuData,
contData: contData
}
};
};
// 自助服务数据处理
const _processServiceData = (data) => {
_.forEach(data, (item, k) => {
item.index = k + 1;
});
return _.chunk(data, 4);
};
// 首页
const helpData = (channel) => {
return Promise.all([
headerModel.requestHeaderData(channel),
helpApi.getHotSearch(),
helpApi.gethomeCategoryFaq(),
helpApi.getSelfService()
]).then(result => {
return {
headerData: _.get(result, '[0]', {}),
content: _.assign({
hotSearch: _.slice(_.get(result, '[1].data', []), 0, 4),
selfService: {
categoryName: '自助服务',
list: _processServiceData(_.get(result, '[3].data', []))
}
}, _processHomeCategoryFaq(_.get(result, '[2].data', {})))
};
});
};
// 详情
const detailData = (params) => {
let promiseData = [
headerModel.requestHeaderData(params.channel),
helpApi.getHotSearch(),
helpApi.gethomeCategoryFaq()
];
if (params.id === 1 && !params.keywords) {
promiseData.push(helpApi.allQA(params.page));
}
return Promise.all(promiseData).then(result => {
let newData = _processDetailData(result, params);
_.set(newData, 'data.hotSearch', _.slice(_.get(result, '[1].data', []), 0, 4));
return {
headerData: _.get(result, '[0]', {}),
newData: newData
};
});
};
// 搜索
const searchData = (params) => {
return helpApi.helpSearch(params).then(result => {
return _.assign({
keywords: params.keywords
}, _processSearch(_.get(result, 'data', []), params));
});
};
// 在线客服
const onlineService = () => {
return helpApi.onlineService().then(result => {
return _.get(result, 'data.url', '');
});
};
module.exports = {
helpData,
detailData,
searchData,
onlineService
};
... ...
/**
* router of sub app help
* @author: yyq<yanqing.yang@yoho.cn>
* @date: 2016/11/14
* router of sub app me
* @author: xuqi<qi.xu@yoho.cn>
* @date: 2016/07/04
*/
'use strict';
... ... @@ -9,14 +9,14 @@
const router = require('express').Router(); // eslint-disable-line
const cRoot = './controllers';
const help = require(`${cRoot}/index`);
const about = require(`${cRoot}/about`);
router.get('/help', help.index);
// 帮助中心
const help = require(`${cRoot}/help`);
router.get('/yohobuy.html', about.yohobuy);
router.get('/newpower.html', about.newpower);
router.get('/contact.html', about.contact);
router.get('/privacy.html', about.privacy);
router.get('/link.html', about.yoholink);
// 帮助中心
router.get('/', help.index);
router.get('/detail', help.detail);
router.get('/search', help.search);
router.get('/onlineService', help.onlineService);
module.exports = router;
... ...
<div class="help-page blk-page">
<div class="center-content clearfix">
{{# content}}
{{!-- 头部面包屑 --}}
{{> common/path-nav}}
{{!-- 左侧菜单导航 --}}
<div class="help-navigation left">
<p class="title bold">帮助中心</p>
{{>menu}}
</div>
{{!-- 右侧页面内容 --}}
<div class="help-main left">
<div class="detail-search">
{{> search-form}}
</div>
<div class="detail-cont">
{{#contData}}
{{#if commonProblem}}
{{> common-problem}}
{{/if}}
{{#if helpDetail}}
{{> help-detail}}
{{/if}}
{{/contData}}
</div>
</div>
{{/ content}}
</div>
</div>
... ...
<div class="help-page blk-page">
<div class="center-content clearfix">
{{# content}}
{{!-- 头部面包屑 --}}
{{> common/path-nav}}
{{!-- 左侧菜单导航 --}}
<div class="help-navigation left">
<p class="title bold">帮助中心</p>
{{>menu}}
</div>
{{!-- 右侧页面内容 --}}
<div class="help-main left">
<div class="nav-top">
<span class="title-img"></span>
<ul class="notice" id="notice">
{{#each notice}}
<li>
{{#each row}}
<a class="notice-cont" href="{{jumpLink}}" target="_blank" data-index={{index}}><i class="dot-icon"></i> <span class="notice-txt">{{caption}}</span></a>
{{/each}}
</li>
{{/each}}
</ul>
{{> search-form}}
</div>
{{#newGuide}}
{{> nav-title}}
<ul class="menu-common new-guide">
{{#each categoryItems}}
<li>
{{#each .}}
<a href="{{jumpLink}}" target="_blank" {{#if @first}}style="margin-left: 0;"{{/if}} data-index={{index}}>
<img src="{{categoryIco}}" width="55" height="55">
<p>{{categoryName}}</p>
</a>
{{/each}}
</li>
{{/each}}
</ul>
{{/newGuide}}
{{#selfService}}
{{> nav-title}}
<ul class="menu-common self-service">
{{#each list}}
<li>
{{#each .}}
<a href="{{jumpUrl}}" target="_blank" {{#if @first}}style="margin-left: 0;"{{/if}} data-index={{index}}>
<img src="{{categoryIco}}" width="55" height="55">
<p>{{categoryName}}</p>
</a>
{{/each}}
</li>
{{/each}}
</ul>
{{/selfService}}
{{#problem}}
{{> nav-title}}
<div class="problem">
{{#each list}}
<a href="javascript:void(0);" data-ask="{{caption}}" data-answer="{{content}}"><i class="dot-icon"></i>{{caption}}</a>
{{/each}}
</div>
{{/problem}}
</div>
{{/ content}}
</div>
</div>
\ No newline at end of file
... ...
<div class="contact-about-page about-page center-content yoho-page">
<div class="about-nav right">
<ul>
<li><a href="/yohobuy.html">关于YOHO!BUY 有货</a></li>
<li><a href="/newpower.html">关于新力传媒</a></li>
<li class="act"><a>联系我们</a></li>
<li><a href="/privacy.html">隐私条款</a></li>
<li><a href="/link.html">友情链接</a></li>
</ul>
</div>
<div class="main-container">
<div class="text-title">联系我们</div>
<div class="text-info">
<p>
<strong>客户服务:</strong><br/>
电话:4008899646(工作日9:00-22:30)<br/>
EMAIL:service#yoho.cn (发送邮件时请将#换成@)
</p><br/>
<p>
<strong>广告服务:</strong><br/>
北京:(+86)10 56312657<br/>
上海:(+86)21 51698833*8005<br/>
广州:(+86)83831060<br/>
EMAIL:advertising#yoho.cn (发送邮件时请将#换成@)
</p><br/>
<p>
<strong>市场合作:</strong><br/>
北京:(+86)10 56312548<br/>
上海:(+86)21 51698833*8013<br/>
EMAIL:marketing#yoho.cn (发送邮件时请将#换成@)
</p><br/>
<p>
<strong>网站合作:</strong><br/>
EMAIL:community#yoho.cn (发送邮件时请将#换成@)
</p><br/>
<p>
<strong>有货品牌合作:</strong><br/>
上海:(+86)21 51698833*8007<br/>
广州:(+86)83831060<br/>
EMAIL:brands#yoho.cn (发送邮件时请将#换成@)
</p><br/>
<p>
<strong>有货推广合作:</strong><br/>
EMAIL:haizheng.zhao#yoho.cn (发送邮件时请将#换成@)
</p><br/>
<p>
<strong>南京新与力文化传播有限公司:</strong><br/>
地址:南京市建邺区嘉陵江东街18号国家广告产业园5栋17,18楼<br/>
邮编:210017<br/>
电话:(+86)25 87781000<br/>
传真:(+86)25 87781155<br/>
</p><br/>
<p>
<strong>南京新与力文化传播有限公司北京分公司:</strong><br/>
地址:北京市朝阳区建国路81号华贸中心1号楼3层<br/>
邮编:100025<br/>
电话:(+86)10 56312400<br/>
</p><br/>
<p>
<strong>南京新与力文化传播有限公司上海分公司:</strong><br/>
地址:上海市徐汇区富民路291号悟锦世纪大厦801室<br/>
邮编:200040<br/>
电话:(+86)21 51698833
</p><br/>
<p>
<strong>南京新与力文化传播有限公司广州分公司:</strong><br/>
地址:广州市天河区林和西路157号保利中汇大厦A座602室<br/>
邮编:510610<br/>
电话:(+86)20 83777600
</p><br/>
<p>
<strong>南京新与力文化传播有限公司香港分公司:</strong><br/>
地址:香港鰂魚涌海澤街28號東港中心1505室<br/>
电话:(+852)34602671
</p><br/>
</div>
</div>
</div>
<div class="newpower-about-page about-page center-content yoho-page">
<div class="about-nav right">
<ul>
<li><a href="/yohobuy.html">关于YOHO!BUY 有货</a></li>
<li class="act"><a>关于新力传媒</a></li>
<li><a href="/contact.html">联系我们</a></li>
<li><a href="/privacy.html">隐私条款</a></li>
<li><a href="/link.html">友情链接</a></li>
</ul>
</div>
<div class="main-container">
{{#if devEnv}}
<img src="//cdn.yoho.cn/yohobuy/assets/img/about/aboutnewpower.png?random=1466056691"/>
{{^}}
<img src="//cdn.yoho.cn/yohobuy/assets/img/about/aboutnewpower.png?random=1466056691"/>
{{/if}}
<div class="text-info">
<p style="font-family:微软雅黑; text-align:left;">
<span style="font-size:18px; line-height:68px;">一、公司概况:</span>
<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;南京新与力文化传播有限公司(简称新力传媒)——中国潮流文化生态圈的创造者和引领者。10年以来,YOHO!致力于中国潮流产业的发展,从一本《YOHO!潮流志》开始,延伸到网络社区、电子商务等等领域,成为中国最权威和最具影响力的潮流“营、销”平台。我们通过媒体+零售线上线下一体化布局,为中国数以亿计的潮流消费者提供潮流讯息、产品及服务,并传播积极健康、全球化的潮流生活方式,更为中国的年轻一代消费者带来了来自全球的潮流生活方式。公司总部位于南京建邺区国家广告产业园,并在北京、上海、广州、香港、东京设立了分(子)公司。公司已获得鼎晖投资、新加坡淡马锡祥峰基金、软银赛富基金、达晨创投、华人文化等数轮投资。公司致力于将“YOHO!”打造成为中国年轻人最喜爱和最值得信赖的品牌,引领中国潮流文化产业的发展。
<br/>
<br/>
<span style="font-size:18px; line-height:68px;">二、公司主要项目:</span>
<br/>
1、平面杂志及电子平台
<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;《YOHO!潮流志》、《YOHO!GIRL》为YOHO!旗下在国内潮流领域影响力的杂志媒体。《YOHO!潮流志》2005 年10月创刊。他是国内第一本完全原创版权的,提供潮流和 lifestyle 资讯,属于年轻人的潮流时尚半月刊,通过正规发行渠道(报刊亭、连锁商超等)发行至全国各大中城市,深受全国年轻人的喜爱。设计给国内年轻女性的中高端时装月刊《YOHO!GIRL》,2013年3月正式创刊,在香港、大陆以及日本东京茑屋地区同步发行。以大量独家资讯加上独特的编采手法,改变读者的阅读习惯,扩阔大家在时装、美容、设计、生活、次文化等各方面的视野。深入结构品牌背后的哲学和时装趋势,带领各读者一探最新时尚。
<br/>
<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;作为中国影响力最大、权威性最高、发行量最广的潮流杂志电子平台, “Yoho!Now”于 iOS 和 Android平台触亮全球潮流资讯,“Yoho!Now”7*24h 无休供应时装、运动、设计、科技、美容、家居、趣闻等严选潮流营养,并于每周发布特别线上专题,与读者Play and Learn。《YOHO!潮流志》和《YOHO!GIRL》亦于各自App內每周上架新鲜线上周刊,打包纸质版内容精华,汇通YOHO!潮流矩阵。
<br/>
<br/>
2、关于“Yoho!Buy有货”
<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;“Yoho!Buy有货”(www.yohobuy.com)——年轻人潮流购物中心,同样秉承YOHO!“年轻是种态度”的口号,Yoho!Buy有货专注于中国潮流趋势和受众的需要,凭借专业的买手团队和对中国潮流趋势敏锐的嗅觉,积极开拓符合中国年轻人喜爱的品牌和商品。销售包括国际知名、日韩港台流行、明星设计师、内地原创等等超过1000 个潮流品牌商品,满足18-35岁年轻群体的时尚个性化述求,涵盖男女服装、鞋帽、配件、童装及创意生活用品等。Yoho!Buy有货所销售的品牌均与品牌直接签订销售协议,保持货品与国际国内实体店铺同步,通过独家定制、限定发售、明星合作品牌等,并结合“逛”内容频道及社区互动引导消费。Yoho!Buy有货已成为中国年轻态群体最喜爱的潮流购物平台。
<br/>
<br/>
3、关于“mars - 新鲜好去处”
<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;“mars - 新鲜好去处”是一款由YOHO!出品的潮流生活应用,立志为百万年轻人打造最酷的“城市探索”线上枢纽。连续两周被 Apple 评选为App Store“最佳新应用”,并获得 2016 年“一月最佳 App”、“最佳生活 App”等推荐。mars深入探索全球热点城市潮流坐标,现已上线北京、上海、成都、台北、香港、东京、首尔、纽约、洛杉矶等城市,未来还将陆续上线更多城市。集优质潮流攻略、专属玩乐线路、每日热点话题等功能,邀集世界各地时髦生活方式达人与所有用户分享好去处,让潮流随时、随地、随享。我们的目标就是带你去那些“如果你不用 mars 可能一辈子都不知道”的潮流好去处。
</p>
</div>
</div>
</div>
<div class="privacy-about-page about-page center-content yoho-page">
<div class="about-nav right">
<ul>
<li><a href="/yohobuy.html">关于YOHO!BUY 有货</a></li>
<li><a href="/newpower.html">关于新力传媒</a></li>
<li><a href="/contact.html">联系我们</a></li>
<li class="act"><a>隐私条款</a></li>
<li><a href="/link.html">友情链接</a></li>
</ul>
</div>
<div class="main-container">
<div class="text-title">隐私条款</div>
<div class="text-info">
<p>
欢迎访问YOHO!BUY 有货!我们以本隐私申明声明对访问者隐私保护的许诺。<br>
<br>
<strong>YOHO!BUY</strong>
<strong>有货的信息收集与使用</strong><br>
YOHO!BUY 有货收集用户提交的个人识别信息(下称“个人识别信息”), 一旦注册,YOHO!BUY 有货用户即可以建立由一页或多页网页组成的含有用户信息的用户档案。YOHO!BUY 有货 将收集用户发布在其用户档案中的数据,包括但不限于: 会员信息,联系信息,购物&amp;着装习惯和喜爱品牌(合称为“用户档案信息”),我们使用这些信息来获得用户的统计资料。我们将会用这些统计数据来给我们的用户分类,以便有针对性地向我们的用户提供新的服务。我们会通过您的邮件地址来通知您这些新的服务。<br>
<br>
YOHO!BUY 有货同样从用户处收集其他非个人识别信息(下称“非个人识别信息”),包括IP地址、集合的用户数据和浏览器类型。该等数据会被用来管理YOHO!BUY 有货网站,跟踪使用记录,改进YOHO!BUY 有货网站的服务。该等非个人识别信息通常被用于下列目的:研究和分析站点的使用情况,订制您浏览的广告和内容,满足您对服务的要求,以及改进我们的服务。出于安全和监管的目的,用户的IP地址将会被记录。<br>
<br>
YOHO!BUY 有货或其商业伙伴可能在YOHO!BUY 有货上不时地进行促销或者抽奖。用户可能会被要求提供个人识别信息,包括姓名,电子邮件地址或家庭住址。因进行促销或者抽奖而收集个人识别信息时,您将清楚地被告知个人识别信息的收集方以及适用的隐私政策。<br>
<br>
<strong>YOHO!BUY</strong>
<strong>有货收集信息的共享与披露</strong><br>
除本隐私政策另有规定,YOHO!BUY 有货不会在未经您同意的情况下在YOHO!BUY 有货及其母公司、子公司或者关联公司(为本隐私政策之目的,包括遵守本隐私政策的技术提供者)之外泄露您的个人识别信息或者用户档案信息,除非我们认为这种披露是有必要的:(1)为遵守法律的要求或者回应YOHO!BUY 有货收到的传票、搜查令或者其他法律程序,而不论该等回应是否为适用法律所要求的;(2)为回应主管政府部门的要求;(3)为了保护公众和服务用户的安全;或者(4)为了维护YOHO!BUY 有货的法律权利和利益。<br>
当YOHO!BUY 有货出售YOHO!BUY 有货或其全部资产时,YOHO!BUY 有货保留向其继任者转让个人识别信息和用户档案信息的权利。<br>
YOHO!BUY 有货也可以向某些您明确同意接收其信息的广告合作伙伴转让您的个人识别信息和用户档案信息。因此进行个人识别信息的收集时,您将清楚地被告知适用的隐私政策。<br>
<br>
<br>
<br>
<strong>用户名和密码</strong><br>
YOHO!BUY 有货用户账号通过用户创设的密码确保其安全性。您应当对您密码的保密负全部责任。请不要和他人分享此信息。如果您泄漏了密码,您可能丢失了您的个人识别信息,并且有可能导致对您不利的司法行为。如果您和他人共享一台电脑,您应该在离开YOHO!服务时退出系统以保证您的信息不被后来使用该电脑者获取。<br>
因此不管任何原因使您的密码安全受到危及,您应该立即通过请与我们客服联系客服热线:400-889-9646和我们取得联系 。<br>
<br>
<strong>您的交易行为</strong><br>
我们跟踪IP地址仅仅只是为了安全的必要。如果我们没有发现任何安全问题,我们会及时删除我们收集到的IP地址。我们还跟踪全天的页面访问数据。全天页面访问数据被用来反映网站的流量,我们可以为未来的发展制定计划(例如,增加服务器)。<br>
<br>
<strong>邮件</strong>
<strong>/</strong>
<strong>短信</strong>
<strong>/</strong>
<strong>会刊服务</strong><br>
YOHO!BUY 有货保留通过邮件、短信、邮寄会刊的形式,对本网站注册、购物用户发送订单信息、促销活动等告知服务的权利。如果您在YOHO!BUY 有货注册、购物,表明您已默示同意接受此项服务。如果您不想接收来自YOHO!BUY 有货的邮件、短信或会刊,您可以向YOHO!BUY 有货客服提出退阅申请,并注明您的E-mail地址、手机号或相关地址信息,YOHO!BUY 有货会在收到申请后为您办理退阅。<br>
<br>
<strong>Cookies</strong>
<strong>的使用</strong><br>
YOHO!BUY 有货使用cookies来储存用户的喜好和记录活动信息以确保用户不会重复收到同样的广告和定制的时事通讯、广告以及基于浏览器类型和用户档案信息的网页内容。我们不会把在cookies中保存的信息与您在我们网站上提交的任何个人识别信息相连接。您可以通过设置您的浏览器以接受或者拒绝全部或部分的cookies,或要求在cookies被设置时通知您。由于每个浏览器是不同的,请查看浏览器的“帮助”菜单来了解如何更改您的cookies选择参数。但是,您应允许来自YOHO!BUY 有货的cookies以使您可以使用网站的更多的功能。<br>
<br>
<strong>外部链接</strong><br>
YOHO!BUY 有货包含其他网站的链接。YOHO!BUY 有货不对其他网站上的隐私政策和/或其执行承担责任。当链接到其他网站时,用户应该阅读该网站贴示的隐私政策。我们的隐私政策仅适用于YOHO!BUY 有货收集的信息。<br>
<br>
<strong>第三方广告</strong><br>
YOHO!BUY 有货可能会通过与第三方合作向用户提供YOHO!服务。因此,YOHO!BUY 有货可能向该第三方提供您提交给YOHO!BUY 有货的个人识别信息和用户档案信息;但该第三方应同意承担与YOHO!BUY 有货相同的责任以保护用户的隐私。另外,在不会披露用户的个人识别信息和用户档案信息的前提下,YOHO!BUY 有货可以对集合的用户个人识别信息和用户档案进行分析和商业性使用。<br>
<br>
<strong>安全</strong><br>
我们网站有相应的安全措施来确保我们掌握的信息不丢失,不被滥用和变造。这些安全措施包括向其它服务器备份数据和对用户密码。<br>
<br>
YOHO!BUY 有货会采取合理的防范措施以确保用户个人识别信息和用户档案信息的保密性。我们会采取合理措施保护存储在我们数据库中的用户个人识别信息和用户档案信息,并且对那些需要履行其工作职责的雇员,比如我们的客户服务人员和技术人员,获取用户个人识别信息和用户档案信息进行限制。请注意,我们无法保证用户个人识别信息和用户档案信息的安全性。未授权的登陆或使用、硬件或软件的故障、以及其他因素均可能在任何时候危及用户个人识别信息的安全性。<br>
<br>
<strong>隐私政策的变更</strong><br>
我们可能对本隐私政策不时进行修改。如果我们进行任何修改,我们将在YOHO!BUY 有货主页上发布为期30天的通知以使用户知道被修改内容的类型以及指示用户审阅更新的隐私政策。如果您在对本隐私政策任何细微修改发布后继续使用网站,则表示您同意遵守任何该等修改。<br>
<br>
<strong>联系我们</strong><br>
如果您就本隐私政策有任何疑问,请与我们客服联系客服热线:400-889-9646。<br>
</p>
</div>
</div>
</div>
<div class="yohobuy-about-page about-page center-content yoho-page">
<div class="about-nav right">
<ul>
<li class="act"><a>关于YOHO!BUY 有货</a></li>
<li><a href="/newpower.html">关于新力传媒</a></li>
<li><a href="/contact.html">联系我们</a></li>
<li><a href="/privacy.html">隐私条款</a></li>
<li><a href="/link.html">友情链接</a></li>
</ul>
</div>
<div class="main-container">
{{#if devEnv}}
<img src="//cdn.yoho.cn/yohobuy/assets/img/about/about.jpg?random=1466056691" />
{{^}}
<img src="//cdn.yoho.cn/yohobuy/assets/img/about/about.jpg?random=1466056691" />
{{/if}}
<div class="text-info">
<p style="font-family:微软雅黑; text-align:left;">关于“Yoho!Buy 有货”</p>
<p style="font-family:微软雅黑; text-align:left;">
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;“Yoho!Buy 有货”(
<a style=" font:#000;" href="//www.yohobuy.com" target="_blank">www.yohobuy.com</a>
)——年轻人潮流购物中心,同样秉承YOHO!“年轻是种态度”的口号,Yoho!Buy有货专注于中国潮流趋势和受众的需要,凭借专业的买手团队和对中国潮流趋势敏锐的嗅觉,积极开拓符合中国年轻人喜爱的品牌和商品。销售包括国际知名、日韩港台流行、明星设计师、内地原创等等超过1000 个潮流品牌商品,满足18-35岁年轻群体的时尚个性化述求,涵盖男女服装、鞋帽、配件、童装及创意生活用品等。Yoho!Buy有货所销售的品牌均与品牌直接签订销售协议,保持货品与国际国内实体店铺同步,通过独家定制、限定发售、明星合作品牌等,并结合“逛”内容频道及社区互动引导消费。Yoho!Buy有货已成为中国年轻态群体最喜爱的潮流购物平台。<br>
</p>
<p>
{{#if devEnv}}
<img src="//cdn.yoho.cn/yohobuy/assets/img/about/about_yohobuy.jpg?random=1466056691" />
{{^}}
<img src="//cdn.yoho.cn/yohobuy/assets/img/about/about_yohobuy.jpg?random=1466056691" />
{{/if}}
</p>
</div>
</div>
</div>
<div class="common-problem">
<h2 class="nav-title">常见问题</h2>
<div class="problem">
{{#faqs}}
<a href="javascript:void(0);" data-ask="{{caption}}" data-answer="{{content}}"><i class="dot-icon"></i>{{caption}}</a>
{{/faqs}}
</div>
<h2 class="all-problem-title nav-title">所有问题一览</h2>
<ul class="all-problem">
{{#allQa}}
<li class="problem-li">
<p class="title">{{caption}}</p>
<div class="cont">{{{content}}}</div>
</li>
{{/allQa}}
</ul>
{{> common/foot-pager}}
</div>
... ...
<div class="help-detail">
{{#if isShowMenu}}
<h2 class="nav-title">{{title}}</h2>
<div class="detail-problem">
{{#list}}
<a href="/help/detail?id={{../id}}&contId={{id}}" class="{{#isEqual id ../contId}}active{{/isEqual}}"><i class="dot-icon"></i>{{caption}}</a>
{{/list}}
</div>
{{/if}}
<div class="help-cont">
{{#cont}}
<h2 class="nav-title">{{caption}}</h2>
<div class="cont">{{{content}}}</div>
{{/cont}}
</div>
</div>
... ...
<ul class="nav">
{{#each menuData}}
{{#if subsets}}
<li class="big-category cateId-{{id}} subsets {{#isEqual id @root.qid}}selected{{/isEqual}}">
<div class="icon plus inline-block"></div>
<span class="menu-txt">{{categoryName}}</span>
</li>
{{#each subsets}}
<li class="smll-category cateId-{{id}} parentId-{{parendId}} {{#isEqual id @root.qid}}selected{{/isEqual}}" data-parent-id="{{parendId}}">
<span class="mult"></span>
<a href="/help/detail?id={{id}}"><span class="menu-txt">{{categoryName}}</span></a>
</li>
{{/each}}
{{else}}
<li class="big-category cateId-{{id}} {{#isEqual id @root.qid}}selected{{/isEqual}}">
<span class="mult"></span>
<a href="/help/detail?id={{id}}"><span class="menu-txt">{{categoryName}}</span></a>
</li>
{{/if}}
{{/each}}
</ul>
... ...
<div class="nav-title">
<div class="center-area">
<span class="title">{{categoryName}}</span>
</div>
</div>
... ...
<div class="search-box">
<div class="search-area">
<form id="help-search-form" action="{{siteUrl}}/help/detail">
<input type="text" class="help-search" autocomplete="off" name="helpQuery" value="{{helpQuery}}">
<input type="text" class="hide">
<span class="iconfont search-btn">&#xe6d5;</span>
</form>
</div>
<div class="keyword">
{{#each hotSearch}}
<a href="{{link}}">{{keyword}}</a>
{{/each}}
</div>
</div>
... ...
... ... @@ -9,13 +9,12 @@ const message = require('../models/message');
const index = (req, res, next) => {
let uid = req.user.uid;
let page = req.query.page || 1;
if (!uid) {
return next();
}
message.getMessageList(uid, page).then(result => {
message.getMessageList(uid, req.query || {}).then(result => {
res.render('message', result);
}).catch(next);
};
... ... @@ -23,13 +22,12 @@ const index = (req, res, next) => {
const detail = (req, res, next) => {
let uid = req.user.uid;
let id = parseInt(req.query.id, 10);
let page = req.query.page;
if (!uid || !id || !page) {
if (!uid || !id) {
return next();
}
message.getMessageDetail(uid, id, page).then(result => {
message.getMessageDetail(uid, req.query || {}).then(result => {
res.render('message-detail', result);
}).catch(next);
};
... ...
... ... @@ -40,7 +40,7 @@ const currencyData = (uid, condition)=>{
let currency = yield currencyList(uid, condition);
result.currency = currency.list;
result.pager = currency.pager;
result.coinHelperUrl = '//www.yohobuy.com/help/?category_id=87';// yoho币帮助
result.coinHelperUrl = '//www.yohobuy.com/help/detail?id=105';// yoho币帮助
result.tabs = currencyTabs(condition.queryType);
result.options = currencyOptions(condition);
return result;
... ...
... ... @@ -10,17 +10,31 @@ const api = global.yoho.API;
const _ = require('lodash');
const Promise = require('bluebird');
const userApi = require('./user-api');
const setPager = require(`${global.utils}/pager`).setPager;
const co = Promise.coroutine;
const getMessageAsync = (uid, page, size) => {
const getMessageTabList = (uid) => {
return api.get('', {
method: 'app.inbox.getlist',
method: 'app.inbox.getAllInboxCatInfo',
uid: uid
}, {code: 200});
};
const getMessageAsync = (uid, page, size, type) => {
let params = {
method: 'app.inbox.getlistnew',
uid: uid,
page: page || 1,
size: size || 10
}, {code: 200});
};
if (type) {
params.displayTab = type;
}
return api.get('', params, {code: 200});
};
const delMessageAsync = (uid, id) => {
... ... @@ -63,31 +77,99 @@ const getCouponAsync = (uid) => {
};
/**
* 未读消息
* @function unreadTotal
* @param { Number } uid 用户uid
* @return { Number } 未读消息数量
*/
const unreadTotal = (uid) => {
return api.get('', {
method: 'app.inbox.getTotal',
uid: uid,
is_read: 'N'
});
};
/**
* 获取消息列表
* @function getMessageList
* @param { Number } uid 用户uid
* @param { Number } page 页码
* @param { Object } params url参数
* @param { Number } limit 每页数目
* @return { Object } 消息列表数据
*/
const getMessageList = (uid, page, limit) => {
let process = function*() {
let resData = {};
let result = yield getMessageAsync(uid, page, limit);
const getMessageList = (uid, params, limit) => {
let resData = {};
let page = parseInt(`0${params.page}`, 10) || 1,
type = parseInt(`0${params.type}`, 10);
return Promise.all([
userApi.getUserInfo(uid),
getMessageTabList(uid),
getMessageAsync(uid, page, limit, type)
]).then(result => {
const msgBaseUrl = '/home/message';
resData.userThumb = _.get(result, '[0].data.head_ico', '');
let tabList = [{
name: '全部',
focus: !type,
href: msgBaseUrl
}];
let focusTabName = '';
_.forEach(_.get(result, '[1]data.list', []), value => {
let tab = {
name: `${value.inboxCatName}`,
focus: type === value.id * 1,
href: `${msgBaseUrl}?type=${value.id}`
};
if (value.unReadCount * 1) {
tab.name += ` (${value.unReadCount})`;
}
if (tab.focus) {
focusTabName = value.inboxCatName;
}
tabList.push(tab);
});
if (result.data) {
resData.tabList = tabList;
if (result[2].data) {
let data = result[2].data;
let msg = [];
_.forEach(_.get(result, 'data.list', []), value => {
_.forEach(_.get(data, 'list', []), value => {
// 信息过滤
if (value.type === '$inboxval' || value.type === 'notice') {
return;
}
let href = `/home/message/detail?id=${value.id}&page=${page}`;
href += type ? `&type=${type}` : '';
switch (value.type) {
case 'pullCoupon':
case 'button':
case 'pushCoupon':
break;
default:
if (value.pcLink) {
href = value.pcLink.replace('http:', '');
}
break;
}
msg.push({
id: value.id || 0,
href: `/home/message/detail?id=${value.id}&page=${page}`,
href: href,
title: value.title || '',
content: _.get(value, 'body.content', ''),
sender: value.from || '',
time: value.create_date,
isNew: value.is_read === 'Y' ? false : true
... ... @@ -96,40 +178,51 @@ const getMessageList = (uid, page, limit) => {
resData.messages = msg;
let pagerList = setPager(_.get(data, 'page_total', 1),
Object.assign(params, {page: page}));
resData.pager = Object.assign({
count: _.get(result, 'data.total', 0),
count: _.get(data, 'total', 0),
curPage: page,
totalPages: _.get(result, 'data.page_total', 0)
}, setPager(_.get(result, 'data.page_total', 0), {
page: page
}));
totalPages: _.get(data, 'page_total', 0)
}, pagerList);
}
if (_.isEmpty(resData.messages)) {
resData.messages = {empty: '您尚未收到任何短消息'};
resData.messages = {empty: `您尚未收到任何${focusTabName}消息`};
}
return resData;
};
return co(process)();
});
};
/**
* 获取消息内容
* @function getMessageDetail
* @param { Number } uid 用户uid
* @param { Number } page 页码
* @param { Object } params url参数
* @param { Number } limit 每页数目
* @return { Object } 消息列表数据
*/
const getMessageDetail = (uid, mid, page, limit) => {
const getMessageDetail = (uid, params, limit) => {
let mid = parseInt(`0${params.id}`, 10);
let page = parseInt(`0${params.page}`, 10) || 1;
let type = parseInt(`0${params.type}`, 10);
let process = function*() {
let result = yield Promise.all([
userApi.getUserInfo(uid),
getMessageAsync(uid, page, limit, type)
]);
let resData = {
backUrl: `/home/message?page=${page}`
backUrl: `/home/message?page=${page}`,
userThumb: _.get(result, '[0].data.head_ico', '')
};
let result = yield getMessageAsync(uid, page, limit);
let msg = _.find(_.get(result, 'data.list', []), {id: mid});
let msg = _.find(_.get(result, '[1]data.list', []), {id: mid});
if (type) {
resData.backUrl += `&type=${type}`;
}
if (!_.isEmpty(msg)) {
resData.message = {
... ... @@ -140,6 +233,26 @@ const getMessageDetail = (uid, mid, page, limit) => {
switch (msg.type) {
case 'pullCoupon': // eslint-disable-line
resData.message.birthCoupon = {
text: `${_.get(result, '[0].data.nickname', '')} 有货祝您生日快乐!感谢您对有货的支持,特赠您VIP生日专属礼,即刻享受生日福利吧!`
};
if (_.get(msg, 'body.is_collar', '') === 'Y') {
Object.assign(resData.message.birthCoupon, {
over: true,
overText: '已领取'
});
break;
}
if (_.get(msg, 'body.is_over_time', '') === 'Y') {
Object.assign(resData.message.birthCoupon, {
over: true,
overText: '生日券已过期'
});
break;
}
let couponInfo = yield getCouponAsync(uid);
let coupons = [];
... ... @@ -169,7 +282,7 @@ const getMessageDetail = (uid, mid, page, limit) => {
image: _.get(msg, 'body.image', ''),
content: _.get(msg, 'body.text', ''),
btnLink: _.get(msg, 'body.pc_link', ''),
btnName: _.get(msg, 'body.button_text', '')
btnName: _.get(msg, 'body.button_text', '') || '查看详情'
};
break;
case 'pushCoupon':
... ... @@ -222,8 +335,6 @@ const delMessage = (uid, mid) => {
return co(process)();
};
/**
* 删除用户消息
* @function getMessageDetail
... ... @@ -255,5 +366,6 @@ module.exports = {
getMessageDetail,
delMessage,
readMessage,
unreadTotal,
pickBirthCoupon
};
... ...
... ... @@ -30,8 +30,7 @@ const EXCHANGE_URI = '/home/returns/exchangeDetail';
const getProductUrlBySkc = (pid, gid, cnAlphabet) => {
cnAlphabet = cnAlphabet || 'cnalphabet';
return helpers.urlFormat(`/product/pro_${pid}_${gid}/${cnAlphabet}.html`,
{}, 'item');
return helpers.getUrlBySkc(pid, gid, cnAlphabet);
};
const setDetailGoods = (list) => {
... ...
... ... @@ -9,6 +9,7 @@ const express = require('express');
const router = express.Router(); // eslint-disable-line
const cRoot = './controllers';
const headerModel = require('../../doraemon/models/header');
const msgModel = require('./models/message');
const _ = require('lodash');
const helpers = global.yoho.helpers;
... ... @@ -16,7 +17,8 @@ const commentController = require(`${cRoot}/comment`);
// const consultController = require(`${cRoot}/consult`);
// const complaintsController = require(`${cRoot}/complaints`);
// const messageController = require(`${cRoot}/message`);
const messageController = require(`${cRoot}/message`);
// const returnsController = require(`${cRoot}/returns`);
// const IndexController = require(`${cRoot}/Index`);
// const CurrencyController = require(`${cRoot}/Currency`);
... ... @@ -35,60 +37,68 @@ const favoriteController = require(`${cRoot}/favorite`);
// const AddressController = require(`${cRoot}/address`);
// const GiftController = require(`${cRoot}/gift`);
const homeNav = [
{
title: '交易管理',
subNav: [
{name: '我的订单', href: '/home/orders', catchs: ['/home/orders', '/home/index']},
{name: '我的收藏', href: '/home/favorite'},
{name: '我的有货币', href: '/home/currency'},
{name: '我的红包', href: '/home/redenvelopes'},
{name: '我的优惠券', href: '/home/coupons'},
{name: '我的VIP', href: '/home/vip'}
]
},
{
title: '服务中心',
subNav: [
{name: '我的退/换货', href: '/home/returns'},
{name: '我的咨询', href: '/home/consult'},
{name: '我的评论', href: '/home/comment'},
{name: '我的投诉', href: '/home/complaints'},
{name: '我的信息', href: '/home/message', count: 0},
{name: '在线客服', href: 'http://chat8.live800.com/live800/chatClient/chatbox.jsp?companyID=620092&configID=149091&jid=8732423409&info=', isBlank: true}
]
},
{
title: '个人信息管理',
subNav: [
{name: '编辑个人资料', href: '/home/user'},
{name: '账号安全', href: '/home/account', catchs: [
'/home/account/userpwd',
'/home/account/email',
'/home/account/mobile',
'/home/account/checkverifycode',
'/home/account/checkpassword',
'/home/account/verifypassword',
'/home/account/modifypwd',
'/home/account/sendemail',
'/home/account/checkemail',
'/home/account/modifyemail',
'/home/account/sendemailsuccess',
'/home/account/mailresult',
'/home/account/checkmobile',
'/home/account/checkmobilemsg',
'/home/account/sendmobilemsg',
'/home/account/modifymobile'
]},
{name: '地址管理', href: '/home/address'},
{name: '兑换礼品卡', href: '/home/gift'}
]
}
];
const getActiveNav = (req)=>{
let mHomeNav = _.cloneDeep(homeNav);
const homeNav = (req) => {
return [
{
title: '交易管理',
subNav: [
{name: '我的订单', href: '/home/orders', catchs: ['/home/orders', '/home/index']},
{name: '我的收藏', href: '/home/favorite'},
{name: '我的有货币', href: '/home/currency'},
{name: '我的红包', href: '/home/redenvelopes'},
{name: '我的优惠券', href: '/home/coupons'},
{name: '我的VIP', href: '/home/vip'}
]
},
{
title: '服务中心',
subNav: [
{name: '我的退/换货', href: '/home/returns'},
{name: '我的咨询', href: '/home/consult'},
{name: '我的评论', href: '/home/comment'},
// {name: '我的投诉', href: '/home/complaints'},
{name: '我的信息', href: '/home/message', count: 0},
{
name: '在线客服',
href: _.get(req.app.locals.pc, 'clientService.new', false) ?
'/service/client' : 'http://chat8.live800.com/live800/chatClient/chatbox.jsp?companyID=620092&amp;configID=149091&amp;jid=8732423409',
isBlank: true
}
]
},
{
title: '个人信息管理',
subNav: [
{name: '编辑个人资料', href: '/home/user'},
{name: '账号安全', href: '/home/account', catchs: [
'/home/account/userpwd',
'/home/account/email',
'/home/account/mobile',
'/home/account/checkverifycode',
'/home/account/checkpassword',
'/home/account/verifypassword',
'/home/account/modifypwd',
'/home/account/sendemail',
'/home/account/checkemail',
'/home/account/modifyemail',
'/home/account/sendemailsuccess',
'/home/account/mailresult',
'/home/account/checkmobile',
'/home/account/checkmobilemsg',
'/home/account/sendmobilemsg',
'/home/account/modifymobile'
]},
{name: '地址管理', href: '/home/address'},
{name: '兑换礼品卡', href: '/home/gift'}
]
}
];
};
const getActiveNav = (req, count)=>{
let mHomeNav = _.cloneDeep(homeNav(req));
let activeNav = null;
mHomeNav = mHomeNav.map((item) => {
... ... @@ -104,6 +114,10 @@ const getActiveNav = (req)=>{
nav.active = true;
}
if (nav.name === '我的信息') {
nav.count = +count;
}
if (nav.catchs) {
if (nav.catchs.indexOf(curMatchPath) > -1) {
nav.active = true;
... ... @@ -127,31 +141,32 @@ const getActiveNav = (req)=>{
};
const getHomeNav = (req, res, next) => {
let navs = getActiveNav(req);
let activeNav = navs.activeNav;
let bread = [{href: helpers.urlFormat('/'), name: 'YOHO!BUY 有货首页'}];
if (activeNav) {
bread.push({
name: '个人中心',
href: helpers.urlFormat('/home')
});
bread.push({
name: activeNav.name
});
} else {
bread.push({
name: '个人中心'
});
}
res.locals.path = bread; // [{href: helpers.urlFormat('/'), name: 'YOHO!BUY 有货首页'}, {name: '个人中心'}];
res.locals.homeNav = navs.homeNav;
res.locals.userThumb = '//img10.static.yhbimg.com/headimg/' +
'2013/11/28/09/01cae078abe5fe320c88cdf4c220212688.gif?imageView/2/w/100/h/100';
next();
msgModel.unreadTotal(req.user.uid).then(result => {
let navs = getActiveNav(req, _.get(result, 'data.total', 0));
let activeNav = navs.activeNav;
let bread = [{href: helpers.urlFormat('/'), name: 'YOHO!BUY 有货首页'}];
if (activeNav) {
bread.push({
name: '个人中心',
href: helpers.urlFormat('/home')
});
bread.push({
name: activeNav.name
});
} else {
bread.push({
name: '个人中心'
});
}
res.locals.path = bread; // [{href: helpers.urlFormat('/'), name: 'YOHO!BUY 有货首页'}, {name: '个人中心'}];
res.locals.homeNav = navs.homeNav;
res.locals.userThumb = '//img10.static.yhbimg.com/headimg/' +
'2013/11/28/09/01cae078abe5fe320c88cdf4c220212688.gif?imageView/2/w/100/h/100';
next();
});
};
const getCommonHeader = (req, res, next) => {
let channel = req.query.channel ? req.query.channel : 'boys';
... ... @@ -180,11 +195,11 @@ router.get('/comment/order', [getCommonHeader, getHomeNav], commentController.co
// router.post('/complaints/cancel', complaintsController.cancel);
// 我的消息
// router.get('/message', messageController.index);
// router.get('/message/detail', messageController.detail);
// router.get('/message/del', messageController.delMsg);
// router.get('/message/read', messageController.readMsg);
// router.get('/message/pickCoupon', messageController.pickCoupon);
router.get('/message', [getCommonHeader, getHomeNav], messageController.index);
router.get('/message/detail', [getCommonHeader, getHomeNav], messageController.detail);
router.get('/message/del', messageController.delMsg);
router.get('/message/read', messageController.readMsg);
router.get('/message/pickCoupon', messageController.pickCoupon);
// 我的退/换货
// router.get('/returns', returnsController.index);
... ...
... ... @@ -230,7 +230,7 @@
</table>
<div class="order-balance">
<p class="back-coin">
<a href="/help/?category_id=87" class="yoho-coin" target="_blank"></a>共返YOHO币:{{totalYoho}}个
<a href="/help/detail?id=105" class="yoho-coin" target="_blank"></a>共返YOHO币:{{totalYoho}}个
</p>
{{#each orderBalance}}
<p>
... ...
... ... @@ -13,45 +13,70 @@
{{# message}}
<div class="text-title">
<h1>{{title}}</h1>
<span>{{sender}} 发送于{{time}}</span>
<span>{{sender}} 发送于{{time}}</span>
</div>
<div class="text-content">
{{# text}}
<!-- 文本消息 -->
<p>{{{content}}}</p>
{{/ text}}
{{# coupons}}
<!-- 优惠券消息 -->
<div class="coupon-item">
<div class="coupon-img">
<img src="//static.yohobuy.com/images/v2/activity/default_coupon.jpg">
</div>
<div class="coupon-info">
<p>{{remark}}</p>
{{#if url}}
<p>面值:{{price}}</p>
<p>有效期:{{useTime}}</p>
{{^}}
<p>使用时间:{{useTime}}</p>
<p>领取时间:{{pickTime}}</p>
{{/if}}
</div>
<div class="coupon-action">
{{#if url}}
<a href="{{url}}" class="view-coupon-btn">立即查看</a>
{{^}}
<a{{#if canPick}} class="pick-coupon-btn" data-id="{{id}}"{{/if}}>立即领取</a>
{{/if}}
</div>
{{# birthCoupon}}
<p>{{text}}</p>
<p class="birth-card">
{{#if @root.devEnv}}
<img src="////{{@root.devHost}}:5002/img/home/birth-card.jpg">
{{^}}
<img src="//cdn.yoho.cn/yohobuy-node/assets/img/home/birth-card.jpg">
{{/if}}
</p>
{{#if over}}
<div>{{overText}}</div>
{{^}}
<div class="show-birth-coupon"{{#if errMsg}} data-msg="{{errMsg}}"{{/if}}>点这里领取</div>
{{/if}}
{{/ birthCoupon}}
{{#if coupons}}
<div class="{{#if birthCoupon}}birth-coupon-wrap{{/if}}">
{{#if birthCoupon}}
<p>您365天内有且仅有一次领劵生日礼券的机会,每次限领1张哦</p>
{{/if}}
{{# coupons}}
<!-- 优惠券消息 -->
<div class="coupon-item">
<div class="coupon-img">
<img src="//static.yohobuy.com/images/v2/activity/default_coupon.jpg">
</div>
<div class="coupon-info">
<p>{{remark}}</p>
{{#if url}}
<p>面值:{{price}}</p>
<p>有效期:{{useTime}}</p>
{{^}}
<p>使用时间:{{useTime}}</p>
<p>领取时间:{{pickTime}}</p>
{{/if}}
</div>
<div class="coupon-action">
{{#if url}}
<a href="{{url}}" class="view-coupon-btn">立即查看</a>
{{^}}
<a{{#if canPick}} class="pick-coupon-btn" data-id="{{id}}"{{/if}}>立即领取</a>
{{/if}}
</div>
</div>
{{/ coupons}}
</div>
{{/ coupons}}
{{/if}}
{{# sale}}
<!-- 促销消息 -->
<div class="sale-img">
<img src="{{image2 image}}">
</div>
<p>{{{content}}}</p>
<a href="{{btnLink}}" class="sale-btn">{{btnName}}</a>
{{#if btnLink}}
<a href="{{btnLink}}" class="sale-btn">{{btnName}}</a>
{{/if}}
{{/ sale}}
</div>
{{/ message}}
... ... @@ -60,4 +85,4 @@
{{> help-us}}
</div>
</div>
\ No newline at end of file
</div>
... ...
... ... @@ -6,19 +6,19 @@
<div class="me-main">
<div class="message block">
<h2 class="title"></h2>
<p class="message-table-header table-header clearfix">
<span class="sender">发件人</span>
<span class="heading">标题</span>
<span class="time">发件时间</span>
<span class="action">操作</span>
</p>
<div class="msg-tabs-wrap">
<ul class="tabs-list clearfix">
{{# tabList}}
<li{{#if focus}} class="active"{{/if}}>
<a href="{{href}}">{{name}}</a>
</li>
{{/ tabList}}
</ul>
</div>
<div id="message-main-container">
{{> message/message-list}}
{{> pager}}
</div>
{{> pager}}
</div>
{{> help-us}}
</div>
</div>
\ No newline at end of file
</div>
... ...
... ... @@ -3,12 +3,15 @@
<h2 class="sub-title">
<div class="more"><a class="btn-edit" title="修改"></a></div>
{{subTitle}}
{{#if certified}}
<span class="sub-tips">学生身份已验证通过啦,赶紧去体验下<a class="tips-url" href="{{tipsUrl}}" target="_blank">我们的专属特权</a>吧!</span>
{{else}}
<span class="sub-tips"> 校园潮流季-我们的专属特权,进行学生身份验证即有惊喜哦,</span>
<a class="tips-url" href="{{tipsUrl}}" target="_blank">立即进行身份验证</a>
{{/if}}
{{#unless @root.pc.user.removeStudentIdentification}}
{{#if certified}}
<span class="sub-tips">学生身份已验证通过啦,赶紧去体验下<a class="tips-url" href="{{tipsUrl}}" target="_blank">我们的专属特权</a>吧!</span>
{{else}}
<span class="sub-tips"> 校园潮流季-我们的专属特权,进行学生身份验证即有惊喜哦,</span>
<a class="tips-url" href="{{tipsUrl}}" target="_blank">立即进行身份验证</a>
{{/if}}
{{/unless}}
</h2>
<form action="" {{# firstBox}}class="first" {{/firstBox}}>
<div class="box">
... ...
... ... @@ -4,29 +4,17 @@
{{> empty}}
{{/with}}
{{^}}
<table>
{{# messages}}
<tr{{#if isNew}} class="new-msg"{{/if}}>
<td width="37">
<input type="checkbox" class="msg-check" value="{{id}}">
</td>
<td class="td-sender"><a href="{{href}}">{{sender}}</a></td>
<td class="td-title"><a href="{{href}}">{{title}}</a></td>
<td width="130">{{time}}</td>
<td>
<a class="del-btn" data-id="{{id}}">删除</a>
</td>
</tr>
{{/ messages}}
<tr class="list-foot">
<td>
<input type="checkbox" class="choose-all">
</td>
<td colspan="4">
<button class="del-choose-btn">删除选中的消息</button>
<button class="read-choose-btn">标记为已读</button>
</td>
</tr>
</table>
{{# messages}}
<div class="msg-item{{#if isNew}} new-msg{{/if}}">
<a href="{{href}}">
<p class="it-title">{{title}}</p>
<p class="it-content">{{content}}</p>
<p class="it-time">{{time}}</p>
</a>
<div class="del-btn" data-id="{{id}}">
<i class="iconfont">&#xe60d;</i>
</div>
</div>
{{/ messages}}
{{/if}}
</div>
... ...
... ... @@ -2,7 +2,9 @@
<p class="title ucenter"></p>
<div class="user-thumb">
<div class="thumb-bg">
<img id="user-thumb" src="{{image2 userThumb}}">
{{#if userThumb}}
<img id="user-thumb" src="{{image2 userThumb w=100 h=100}}">
{{/if}}
</div>
</div>
{{# homeNav}}
... ... @@ -23,4 +25,4 @@
</ul>
</div>
{{/ homeNav}}
</div>
\ No newline at end of file
</div>
... ...
... ... @@ -85,7 +85,7 @@ let index = (req, res, next) => {
location: area || '+86',
defaultMobile: mobile,
captchaUrl: helpers.urlFormat('/passport/imagesNode', {t: Date.now()}),
itemUrl: helpers.urlFormat('/help/', {category_id: 143}),
itemUrl: helpers.urlFormat('/help/detail', {id: 103, contId: 197}),
referUrl: refer,
loginUrl: helpers.urlFormat('/signin.html', {refer: refer}),
coverHref: result.url,
... ...
... ... @@ -99,10 +99,19 @@ router.get('/passport/reg/index', reg.index);
// NOTE: 该接口的存在只是为了兼容前端 ajax 请求
router.post('/passport/reg/checkmobile', reg.fakeCheckMobile);
router.post('/passport/reg/piccaptcha', reg.checkCode, reg.picCaptcha);
router.post('/passport/reg/msgcaptcha', reg.checkMobileMiddleware, reg.msgCaptcha);
router.post('/passport/reg/sendBindMsg', reg.checkMobileMiddleware, reg.checkCode, reg.sendBindMsg);
router.post('/passport/reg/mobileregister', reg.checkMobileMiddleware, reg.checkPassword, reg.checkCode, reg.mobileRegister); //eslint-disable-line
router.post('/passport/reg/sendBindMsg',
captcha.requiredAPI,
reg.checkMobileMiddleware,
reg.sendBindMsg);
router.post('/passport/reg/mobileregister',
captcha.requiredAPI,
reg.checkMobileMiddleware,
reg.checkPassword,
reg.mobileRegister);
router.get('/passport/reg/success', reg.success);
/**
... ...
... ... @@ -13,7 +13,6 @@ const detailHelper = require(`${mRoot}/detail-helper`);
const moment = require('moment');
const DEFAULT_AVATAR_ICO = 'http://static.yohobuy.com/images/v3/boy.jpg';
const SEO_SLOGAN = 'YOHO!BUY 有货';
const _ = require('lodash');
const CHANNEL = {
... ...
... ... @@ -92,6 +92,12 @@ exports.index = (req, res, next) => {
if (_.isEmpty(_.get(resData, 'list.goods', []))) {
res.set('Cache-Control', 'no-cache');
}
// 商品详情页跳转过来带参数
if (req.query.phrase) {
resData.list.phrase = decodeURIComponent(req.query.phrase);
}
res.render('list/index', resData);
}).catch(next);
};
... ...
/*
* @Author: hongwei.gao
* @Date: 2016-12-28
*/
'use strict';
const mRoot = '../models';
const arrive = require(`${mRoot}/newArrive-service`);
/**
* 新品到着首页加载
* @param {[type]} req [description]
* @param {[type]} res [description]
* @return {[type]} [description]
*/
exports.index = (req, res, next) => {
let pjax = req.query._pjax;
// 加载最新上架数据
if (pjax) {
arrive.getRecList(req).then(result => {
Object.assign(result, {layout: false});
res.render('list/new-pro-list', result);
}).catch(next);
return;
}
// 加载所有
arrive.index(req).then(result => {
res.render('list/new-arrive', result);
}).catch(next);
};
... ...
... ... @@ -5,7 +5,7 @@
'use strict';
exports.if_cond = (left, operator, right, options) => {
exports.if_cond = function(left, operator, right, options) {
switch (operator) {
case '==':
return (left == right) ? options.fn(this) : options.inverse(this); // eslint-disable-line
... ... @@ -30,7 +30,7 @@ exports.if_cond = (left, operator, right, options) => {
}
};
exports.escapeType = (value) => {
exports.escapeType = function(value) {
let strs = value.split('');
... ... @@ -51,14 +51,14 @@ exports.escapeType = (value) => {
return strs.join('');
};
exports.escapeLength = (value) => {
let strs = value.split('');
exports.escapeLength = function(value) {
let strs = value.split('');
if (strs.length === 2) {
strs[2] = strs[1];
strs[1] = '&#12288;';
return strs.join('');
}
if (strs.length === 2) {
strs[2] = strs[1];
strs[1] = '&#12288;';
return strs.join('');
}
return strs.join('');
}
return strs.join('');
};
... ...
/**
* Created by TaoHuang on 2016/11/30.
*/
'use strict';
const api = require('./detail-product-api');
const type = {
package: 'package', // 套餐
bundle: 'bundle' // 量贩
};
const _getBundle = (data) => {
};
const getPackage = (data) => {
};
module.exports = {
}
... ... @@ -51,16 +51,6 @@ const getProductComfortAsync = (pid) => {
};
/**
* 模特卡
*/
const getProductModelCardAsync = (pid) => {
return api.get('', {
method: 'web.productModelcard.list',
product_id: pid
}, config.apiCache);
};
/**
* 模特试穿
*/
const getProductModelTryAsync = (skn) => {
... ... @@ -147,13 +137,10 @@ const getBundleAsync = (skn) => {
});
};
module.exports = {
getProductBannerAsync,
sizeInfoAsync,
getProductComfortAsync,
getProductModelCardAsync,
getProductModelTryAsync,
getProductAsync,
getPromotionAsync,
... ...
... ... @@ -13,6 +13,7 @@ const Fn = require('lodash/fp');
const cheerio = require('cheerio');
const url = require('url');
const helpers = global.yoho.helpers;
const config = global.yoho.config;
const crypto = global.yoho.crypto;
const videoPlayerTpl = require('../helper/video-player-tpl');
... ... @@ -61,7 +62,6 @@ const _getProductIntroAsync = (productId, productSkn) => {
let result = yield Promise.props({
sizeInfo: productAPI.sizeInfoAsync(productSkn),
productComfort: productAPI.getProductComfortAsync(productId),
productModelCard: productAPI.getProductModelCardAsync(productId),
productModelTry: productAPI.getProductModelTryAsync(productSkn)
});
... ... @@ -192,8 +192,10 @@ const _getVipDataByProductBaseInfo = (data, vipLevel, uid) => {
const _getProductActivityBanner = (additionalData) => {
let data = additionalData.productBanner;
if (_.isEmpty(data) || _.get(data, 'code', 400) !== 200 || !_.get(data, 'data.bannerImg')) {
return {};
if (_.isEmpty(data) ||
_.get(data, 'code', 400) !== 200 ||
!_.get(data, 'data.bannerImg')) {
return false;
}
return {
... ... @@ -212,16 +214,15 @@ const _getBundleAsync = (result) => {
};
const _getActivityDataByProductBaseInfo = (data) => {
let result = [];
return _.get(data, 'data', []).map(value => {
let des = value.promotionTitle.replace(/¥/g, '¥');
_.get(data, 'data', []).forEach(value => {
result.push({
return {
type: value.promotionType.replace(/¥/g, '¥'),
des: value.promotionTitle.replace(/¥/g, '¥')
});
des: des,
url: value.id && helpers.urlFormat('', {psp_id: value.id, phrase: encodeURIComponent(des)}, 'list')
};
});
return result;
};
/**
... ... @@ -279,7 +280,7 @@ const _getSkuDataByProductBaseInfo = (data) => {
let totalStorageNum = 0;
let skuGoods = null;// sku商品
let defaultImage = '';// 默认图
let chooseSkuFlag = false; // 选中状态
let defaultSkuFlag = false; // 选中状态
if (_.isEmpty(_.get(data, 'goods_list', []))) {
return {
... ... @@ -289,33 +290,34 @@ const _getSkuDataByProductBaseInfo = (data) => {
};
}
skuGoods = _.get(data, 'goods_list', []).reduce((acc, cur, pos)=> {
skuGoods = _.get(data, 'goods_list', []).reduce((goodsDetailList, goods)=> {
// 如果status为0,即skc下架时就跳过该商品$value['status'] === 0
let goodsGroup = {};
let goodsDetail = {};
if (_.isEmpty(cur.color_image)) {
return acc;
if (_.isEmpty(goods.color_image)) {
return goodsDetailList;
}
if (cur.images_list) {
if (goods.images_list) {
// 商品列表
goodsGroup.productSkc = cur.product_skc;
goodsGroup.src = cur.color_image;
goodsGroup.title = `${_.trim(data.product_name)} ${cur.factory_goods_name}`;
goodsGroup.name = cur.factory_goods_name;
goodsGroup.focus = false;
goodsGroup.total = 0;
goodsGroup.thumbs = [];
goodsGroup.size = [];
if (goodsGroup.title.length > 20) {
goodsGroup.title = goodsGroup.title.substr(0, 20) + '...';
goodsDetail.productSkc = goods.product_skc;
goodsDetail.src = goods.color_image;
goodsDetail.title = `${_.trim(data.product_name)} ${goods.factory_goods_name}`;
goodsDetail.name = goods.factory_goods_name;
goodsDetail.focus = false;
goodsDetail.total = 0;
goodsDetail.thumbs = [];
goodsDetail.size = [];
if (goodsDetail.title.length > 20) {
goodsDetail.title = goodsDetail.title.substr(0, 20) + '...';
}
}
_.get(cur, 'images_list', []).forEach((good) => {
_.get(goods, 'images_list', []).forEach((good) => {
if (good.image_url) {
goodsGroup.thumbs.push({
goodsDetail.thumbs.push({
url: '',
shower: good.image_url,
img: good.image_url
... ... @@ -324,51 +326,53 @@ const _getSkuDataByProductBaseInfo = (data) => {
});
// 缩略图空,不显示
if (_.isEmpty(goodsGroup.thumbs)) {
return acc;
if (_.isEmpty(goodsDetail.thumbs)) {
return goodsDetailList;
}
// 商品的尺码列表
_.get(cur, 'size_list', []).forEach((size) => {
_.get(goods, 'size_list', []).forEach((size) => {
if (data.attribute === 3) {
// 虚拟商品,门票默认最大为4,
size.storage_number = size.storage_number > 4 ? 4 : size.storage_number;
}
// 如果status为0,即skc下架时就跳过该商品
if (cur.status === 0) {
if (goods.status === 0) {
size.storage_number = 0;
}
// 是否显示到货通知
size.notify = size.isSuppled === 'Y' && size.storage_number === 0 ? 'Y' : 'N';
goodsGroup.size.push({
// 尺码信息
goodsDetail.size.push({
name: size.size_name,
sku: size.product_sku,
num: _.parseInt(size.storage_number),
goodsId: size.size_id,
notify: size.notify,
soldOut: _.parseInt(size.storage_number) === 0
soldOut: _.parseInt(size.storage_number) === 0,
info: _.get(size, 'size_info', '').replace(/\//ig, '-').replace(/ /ig, '/').replace(/:/ig, ' ')
});
// 单个sku商品的总数
goodsGroup.total += _.parseInt(size.storage_number);
goodsDetail.total += _.parseInt(size.storage_number);
if (goodsGroup.total > 0 && !chooseSkuFlag) { // 默认选中该sku商品
goodsGroup.focus = true;
defaultImage = goodsGroup.src; // 默认为选中的skc
chooseSkuFlag = true;// 选中sku商品
if (goodsDetail.total > 0 && !defaultSkuFlag) { // 默认选中该sku商品
goodsDetail.focus = true;
defaultImage = goodsDetail.src; // 默认为选中的skc
defaultSkuFlag = true;// 选中sku商品
}
goodsGroup.disable = !goodsGroup.total > 0;
goodsDetail.disable = !goodsDetail.total > 0;
totalStorageNum += _.parseInt(size.storage_number);
});
if (goodsGroup.focus) {
_.some(goodsGroup.size, function(value) {
if (goodsDetail.focus) {
_.some(goodsDetail.size, function(value) {
if (value.num !== 0) {
value.focus = true;
return true;
... ... @@ -377,11 +381,11 @@ const _getSkuDataByProductBaseInfo = (data) => {
});
}
acc.push(goodsGroup);
return acc;
goodsDetailList.push(goodsDetail);
return goodsDetailList;
}, []);
if (!_.isEmpty(skuGoods) && !chooseSkuFlag) { // 没有选中一个sku商品,默认选中第一个sku商品
if (!_.isEmpty(skuGoods) && !defaultSkuFlag) { // 没有选中一个sku商品,默认选中第一个sku商品
// 所有商品都售罄
_.head(skuGoods).focus = true;
defaultImage = _.head(skuGoods).src;
... ... @@ -509,16 +513,13 @@ function _getSortNavAsync(smallSortId, gender) {
// 保存在 gids 和 skns ,最近流览功能
const saveRecentGoodInCookies = (oldSkns, res, addSkns) => {
oldSkns = oldSkns ? oldSkns.split(',') : [];
oldSkns = _.reject(oldSkns, old => old === String(addSkns) ? true : false);
oldSkns.unshift(addSkns);
res.cookie('_browseskn', oldSkns.splice(0, 30).join(','), {
res.cookie('_browseskn', _.take(oldSkns, 30).join(','), {
maxAge: 2000000000,
domain: '.yohobuy.com'
domain: config.cookieDomain
});
};
... ... @@ -526,14 +527,13 @@ const saveRecentGoodInCookies = (oldSkns, res, addSkns) => {
* 获取商品的舒适度
*/
const _getProductComfort = (data) => {
let result = [];
let comfort = data.productComfort;
if (_.isEmpty(comfort) || !comfort || !comfort.data) {
return result;
return [];
}
_.get(comfort, 'data', []).forEach(value => {
return _.get(comfort, 'data', []).reduce((all, value) => {
let blocks = [];
let flag = false;
... ... @@ -550,19 +550,19 @@ const _getProductComfort = (data) => {
// 不存在
if (!flag) {
return;
return all;
}
// 存在,添加
result.push({
all.push({
name: value.caption.caption,
minDes: value.caption.low,
blocks: blocks,
maxDes: value.caption.high
});
});
return result;
return all;
}, []);
};
/**
... ... @@ -579,30 +579,26 @@ const _getBasicDescription = (productDescBo) => {
}
}(productDescBo.gender));
let basic = [
{
key: '编号',
value: productDescBo.erpProductId
},
{
key: '颜色',
value: productDescBo.factoryGoodsName,
dColor: true
},
{
key: '性别',
value: sex
}
];
_.get(productDescBo, 'standardBos', []).forEach(value => {
basic.push({
const basic = [{
key: '编号',
value: productDescBo.erpProductId
}, {
key: '颜色',
value: productDescBo.factoryGoodsName,
dColor: true
}, {
key: '性别',
value: sex
}];
return _.get(productDescBo, 'standardBos', []).reduce((all, value) => {
all.push({
key: value.standardName,
value: value.standardVal
});
});
return basic;
return all;
}, basic);
};
/**
... ... @@ -610,7 +606,7 @@ const _getBasicDescription = (productDescBo) => {
*/
const _getDescriptionDataBySizeInfo = (sizeInfo, additionalData) => {
if (!sizeInfo.productDescBo || !sizeInfo.productDescBo.erpProductId) {
return {};
return false;
}
return {
... ... @@ -751,18 +747,51 @@ const _getSizeData = (sizeInfo) => {
* 获取商品模特卡
* @param productId
*/
const _getProductModelCard = (additionalData) => {
let data = additionalData.productModelCard;
const _getProductModelCard = (sortId, sizeInfo) => {
if (!sortId || !_.includes([1, 3, 4], sortId)) {
return [];
}
if (_.isEmpty(data) || !data || _.get(data, 'code', 400) !== 200) {
const modelData = _.get(sizeInfo, 'modelCardsBo', []);
if (_.isEmpty(modelData)) {
return [];
}
return _.get(data, 'data', []).map((value) => ({
url: helpers.getForceSourceUrl(value.modelImg),
size: value.size,
name: value.modelName
}));
const TYPE_SORT = {
1: ['height', 'weight', 'shoulderWidth', 'bust', 'waist', 'dressSize'], // 上衣
3: ['height', 'weight', 'waist', 'hip', 'downDressSize'], // 裤子
4: ['height', 'weight', 'waist', 'hip', 'downDressSize'] // 裙子
};
const local_ = {
height: ['身高', 'cm'],
weight: ['体重', 'kg'],
shoulderWidth: ['肩宽', 'cm'],
bust: ['胸围', 'cm'],
waist: ['腰围', 'cm'],
dressSize: ['日常尺码', ''],
downDressSize: ['日常尺码', ''],
hip: ['臀围', 'cm']
};
return _.map(modelData, (model) => {
return {
avatar: _.get(model, 'avatar'),
name: _.get(model, 'modelName'),
size: _.get(model, 'size'),
desc: _.reduce(TYPE_SORT[sortId], (total, value) => {
if (model[value]) {
total.push({
key: local_[value][0],
value: model[value] + local_[value][1]
});
}
return total;
}, [])
};
});
};
/**
... ... @@ -771,7 +800,7 @@ const _getProductModelCard = (additionalData) => {
*/
const getReferenceDataBySizeInfo = (sizeInfo) => {
if (_.isEmpty(sizeInfo.modelBos)) {
return {};
return false;
}
// 模特试穿, 竖着输出排列显示
... ... @@ -891,7 +920,7 @@ const _getProductModelTry = (data) => {
let result = data.productModelTry;
if (_.isEmpty(result) || result.code !== 200 || _.isEmpty(result.data)) {
return {};
return false;
}
let modelTry = {
... ... @@ -927,60 +956,6 @@ const _getProductModelTry = (data) => {
};
/**
* 根据最大分类ID获取尺寸属性
* @param maxSortId
* @param sizeInfoBo
*/
const _getSizeAttrByMaxSortId = (maxSortId, sizeList) => {
if (_.isEmpty(sizeList)) {
return [];
}
// 不同分类,取得属性值不同
let attributeIds = (function(id) {
if (id === 1 && id === 2) {
return [3, 4];
} else if (id === 3) {
return [6, 10];
} else if (id === 6) {
return [13];
} else {
return [];
}
}(maxSortId));
let sizeInfos = [];
let attributeNames = {};
// 获取属性名称
_.get(sizeList, 'sizeAttributeBos', []).forEach((size) => {
attributeNames[size.id] = size.attributeName;
});
_.get(sizeList, 'sizeBoList', []).forEach((size) => {
let sizeValues = [];
_.get(size, 'sortAttributes', []).forEach((sort) => {
if (_.includes(attributeIds, sort.id)) {
if (sort.sizeValue) {
sizeValues.push(
`${attributeNames[sort.id]} ${sort.sizeValue}cm`
);
}
}
});
// 获取尺寸属性
if (!_.isEmpty(sizeValues)) {
sizeInfos[size.sizeName] = sizeValues.join(' / ');
}
});
return sizeInfos;
};
/**
* 商品尺码信息
*
* @param productSkn
... ... @@ -1004,24 +979,16 @@ const _getIntroInfo = (productSkn, maxSortId, additionalData)=> {
result.description = _getDescriptionDataBySizeInfo(sizeInfo, additionalData);
// 模特卡
result.modelCards = _getProductModelCard(additionalData);
result.modelCards = _getProductModelCard(maxSortId, sizeInfo);
// 试穿模特
let fittingReport = _getProductModelTry(additionalData);
if (!_.isEmpty(fittingReport)) {
result.fittingReport = fittingReport;
}
result.fittingReport = _getProductModelTry(additionalData);
// 尺寸数据
result.size = _getSizeData(sizeInfo);
// 模特数据
let reference = getReferenceDataBySizeInfo(sizeInfo);
if (!_.isEmpty(reference)) {
result.reference = reference;
}
result.reference = getReferenceDataBySizeInfo(sizeInfo);
// 洗涤材质
result.material = _getMaterialDataBySizeInfo(sizeInfo);
... ... @@ -1029,10 +996,6 @@ const _getIntroInfo = (productSkn, maxSortId, additionalData)=> {
// 商品详情页介绍
result.details = _getDetailDataBySizeInfo(sizeInfo);
// 获取尺寸说明
result.sizeTitleJson =
sizeInfo.sizeInfoBo ? JSON.stringify(_getSizeAttrByMaxSortId(maxSortId, sizeInfo.sizeInfoBo)) : '';
return result;
};
... ... @@ -1168,11 +1131,6 @@ const _detailDataPkg = (origin, uid, vipLevel, cookies) => {
); // 限购商品的状态
}
if (propOrigin('brand_info', '')) {
requestApi.brand =
brandService.getBrandByDomainAsync(propOrigin('brand_info.brand_domain')); // 品牌信息
}
if (propOrigin('bundle_type') === BUNDLE_PRODUCE) {
requestApi.bundle = productAPI.getBundleAsync(result.skn); // 量贩
}
... ... @@ -1184,7 +1142,6 @@ const _detailDataPkg = (origin, uid, vipLevel, cookies) => {
let promotionData = requestData.promotion;
let coupon = requestData.coupon;
let limitedInfo = requestData.limited;
let domainBrand = requestData.brand;
let bundle = requestData.bundle;
// 商品标签
... ... @@ -1196,12 +1153,13 @@ const _detailDataPkg = (origin, uid, vipLevel, cookies) => {
// 是否收藏
result.isCollect = favoriteData.product;
// 商品价格
// 带人民币符号的商品价格
result.marketPrice = propOrigin('format_market_price');
result.salePrice = propOrigin('format_sales_price');
result.hasOtherPrice = true;
if (result.salePrice === '0') {
//
if (result.salePrice === '0' || result.marketPrice === result.salePrice) {
delete result.salePrice;
result.hasOtherPrice = false;
}
... ... @@ -1222,7 +1180,7 @@ const _detailDataPkg = (origin, uid, vipLevel, cookies) => {
result.promotion = ((salePriceNum / marketPriceNum) * 10).toFixed(1);
// 只显示大于1折小于9折的折扣
if (1.0 >= result.promotion || result.promotion >= 9.0) {
if (result.promotion <= 1.0 || result.promotion >= 9.0) {
result.promotion = false;
}
}
... ... @@ -1409,18 +1367,6 @@ const _detailDataPkg = (origin, uid, vipLevel, cookies) => {
};
}
// 非普通商品导航条移除加入购物车按钮
const hasNavCart = (pro) => {
return !(pro.limitedsale === 'Y' ||
pro.secKill === 'Y' ||
pro.deposit === 'Y' ||
pro.presale === 'Y' ||
pro.bundle.type !== 0);
};
result.hasNavCart = hasNavCart(result);
// 电子票
result.isTicket = propOrigin('product_skn') === YOHOOD_TICKET;
if (virtualGoods && result.isTicket) {
... ... @@ -1457,8 +1403,12 @@ const _detailDataPkg = (origin, uid, vipLevel, cookies) => {
statGoodsInfo.productId = propOrigin('product_id');
statGoodsInfo.productName = result.name.replace('\'', '’');
statGoodsInfo.brandName = (result.brandName || '').replace('\'', '’');
statGoodsInfo.marketPrice = (result.marketPrice ? result.marketPrice : result.presalePrice).replace('¥', ''); // 数字
statGoodsInfo.salePrice = (result.salePrice ? result.salePrice : (result.marketPrice || result.presalePrice)).replace('¥', ''); // 数字
statGoodsInfo.marketPrice = (result.marketPrice ?
result.marketPrice :
result.presalePrice).replace('¥', ''); // 数字
statGoodsInfo.salePrice = (result.salePrice ?
result.salePrice :
(result.marketPrice || result.presalePrice)).replace('¥', ''); // 数字
statGoodsInfo.imageUrl = helpers.getForceSourceUrl(result.img);
statGoodsInfo.productUrl = 'http:' +
helpers.urlFormat(url.parse(propOrigin('product_url')).pathname, null, 'item');
... ... @@ -1545,7 +1495,8 @@ const getDetailHeader = (pid, uid, isStudent, vipLevel, dataMd5, cookie) => {
* 是否支持退换货,true 支持,false 不支持
*/
const saleReturn = (skn) => {
return productAPI.isSupportReturnedSale(skn).then(result => _.get(result, `data.${skn}`, 'N') === 'N' ? 'Y' : 'N');
return productAPI.isSupportReturnedSale(skn)
.then(result => _.get(result, `data.${skn}`, 'N') === 'N' ? 'Y' : 'N');
};
/**
... ... @@ -1642,7 +1593,7 @@ const recommendAsync = (skn, page, limit) => {
}
const formatPrice = p => ${p}`;
const productUrl = (pid, gid, cn) => helpers.urlFormat(`/product/pro_${pid}_${gid}/${cn}.html`, null, 'item');
const productUrl = (pid, gid, cn) => helpers.getUrlBySkc(pid, gid, cn);
const productImageUrl = Fn.pipe(Fn.prop('default_images'), _.partial(helpers.image, _, 280, 382, 2, 70));
let products = _.get(recommendData, 'data.product_list', []).map((rp) => {
... ...
/**
* 新品到着相关接口
* @author: yyq<yanqing.yang@yoho.cn>
* @date: 2016/7/17
*/
'use strict';
const api = global.yoho.API;
/**
* 为您推荐店铺API
*
*/
const recShop = (params) => {
let finalParams = {
method: 'app.newproduct.recshop'
};
Object.assign(finalParams, params);
return api.get('', finalParams);
};
/**
* 为您推荐品牌API
*
*/
const recBrand = (params) => {
let finalParams = {
method: 'app.newproduct.recbrand'
};
Object.assign(finalParams, params);
return api.get('', finalParams);
};
/**
* 最新上架API
*
*/
const recList = (params) => {
let finalParams = {
method: 'app.newproduct.reclist',
limit: 60
};
Object.assign(finalParams, params);
return api.get('', finalParams);
};
module.exports = {
recShop,
recBrand,
recList
};
... ...
/*
* @Author: hongwei.gao
* @Date: 2016-12-28
*/
'use strict';
const headerModel = require('../../../doraemon/models/header');
const api = require('./newArrive-api');
const _ = require('lodash');
const searchHandler = require('./search-handler');
const publicHandler = require('./public-handler');
const helpers = global.yoho.helpers;
const moment = require('moment');
const channelMap = {
boys: {
code: '29ce9c740c452b97d421f9630893dfe6',
yh_channel: 1,
gender: '1,3'
},
girls: {
code: 'cc145b163edb010c5d6320a2c680f24a',
yh_channel: 2,
gender: '2,3'
},
kids: {
code: '4eed401c1ba714099585b593dd25dfbe',
yh_channel: 3,
gender: '2,3'
},
lifestyle: {
code: 'c6c7421b3fddddf04799c13d3a84b4f2',
yh_channel: 4,
gender: '2,3'
}
};
/**
* 处理列表数据、及页码
* @param data
* @returns {{footPager: type[], newProList: Array}}
* @private
*/
const _proListHandler = (data, params) => {
let total = data.total || '',
proList = data.product_list || [],
newProList = [];
// 页码
let footPager = searchHandler.handlePagerData(total,
Object.assign(params, {limit: _.get(data, 'page_size', '50')}), true);
// 商品列表
_.forEach(proList, pro => {
let proObj = {};
// 应季热门
if (pro.recommend_type === 'seasonSort') {
let tags = [];
_.forEach(pro.data, subData => {
tags.push({
url: helpers.urlFormat('', {sort: subData.relationParameter}, 'list'),
name: subData.categoryName,
cateId: subData.categoryId
});
});
proObj.tags = tags;
proObj.tagType = true;
}
// 热门搜索
if (pro.recommend_type === 'hotSearchTerm') {
let tags = [];
_.forEach(pro.data, subData => {
tags.push({
url: helpers.urlFormat('', {query: subData}, 'search'),
name: subData
});
});
proObj.tags = tags;
proObj.tagType = true;
proObj.hotSearch = true;
}
// 店铺
if (pro.recommend_type === 'hotShop') {
proObj = {
url: helpers.urlFormat('', {shopId: pro.data.shops_id}, pro.data.shop_domain),
src: pro.data.shop_logo,
newNum: pro.data.new_product_num,
collNum: pro.data.favorite_num,
shopId: pro.data.shops_id,
shopName: pro.data.shop_name
};
proObj.shopType = true;
}
// 文章
if (pro.recommend_type === 'fashionArticle') {
proObj = {
url: helpers.urlFormat('/' + pro.data.id + '.html', {channel: params.channel}, 'guang'),
src: pro.data.src,
title: pro.data.title,
publishTime: moment(parseInt(pro.data.publish_time_long, 10)).format('YYYY年MM月DD HH:mm'),
num: pro.data.browse || 0,
articalId: pro.data.id
};
proObj.articalType = true;
}
// 普通商品
if (!pro.recommend_type) {
let defaultGoods = _.find(pro.goods_list, {is_default: 'Y'});
// 无默认商品取商品列表第一个
if (!defaultGoods) {
defaultGoods = pro.goods_list[0];
}
proObj = {
url: helpers.getUrlBySkc(pro.product_id, defaultGoods.goods_id, pro.cn_alphabet),
src: pro.default_images,
proName: pro.product_name,
salesPrice: pro.sales_price,
proSkn: pro.product_skn
};
proObj.goodsType = true;
}
proObj.recType = pro.recommend_type;
newProList.push(proObj);
});
return {
footPager: footPager,
newProList: newProList
};
};
/**
* 加载新品到着首页
* @param req
* @returns {Promise.<TResult>}
*/
const index = (req) => {
let channel = req.yoho.channel;
let params = {
yh_channel: channelMap[channel].yh_channel,
channel: channel,
uid: req.user.uid || ''
};
let shopParams = Object.assign({}, params, {contentCode: channelMap[channel].code});
let recParams = Object.assign({}, params, {
sort: req.query.sort || '',
page: req.query.page || 1
});
let cateId = req.query.cateId || '';
let apiMethod = [
headerModel.requestHeaderData(channel),
api.recShop(shopParams),
api.recBrand(params),
api.recList(Object.assign({}, params)), // 获取品类
api.recList(recParams)// 获取商品数据
];
return Promise.all(apiMethod).then(result => {
var respData = {
slide: {
list: []
},
recommond: {
name: '为您推荐',
dataList: []
},
newBrand: {
name: '新品牌入驻',
brandList: []
},
newProduct: {
name: '最新上架',
newProList: [],
ctyList: []
},
firstLook: {
name: '精彩抢先看',
lookBanner: {
list: []
},
lookTwoImg: []
}
};
// 头部数据
Object.assign(respData, result[0]);
// 面包屑头部
Object.assign(respData, searchHandler.handlePathNavData({}, {}, 'new', channel));
if (result[1].code === 200 && result[1].data) {
_.forEach(_.get(result, '[1].data.ads', []), ads => {
// banner
if (ads.template_name === 'focus') {
Object.assign(respData.slide.list, ads.data);
}
// 精彩想先看,左轮播右2图
if (ads.template_name === 'NL2R') {
Object.assign(respData.firstLook.lookBanner.list, ads.data.left);
Object.assign(respData.firstLook.lookTwoImg, ads.data.right);
}
});
}
// 新品牌入驻
if (result[2].code === 200 && result[2].data) {
let hotBrandsData = _.get(result, '[2].data.hot_brand_list', []),
recList = [];
_.forEach(hotBrandsData, hotBrand => {
recList.push({
url: helpers.urlFormat('', {shopId: hotBrand.shops_id}, hotBrand.shop_domain),
src: hotBrand.shop_logo,
num: hotBrand.new_product_num,
shopId: hotBrand.shops_id,
brandId: hotBrand.brand_id
});
});
// 为您推荐
Object.assign(respData.recommond.dataList, recList);
let brandsData = _.get(result, '[2].data.new_brand_list', []),
brandList = [];
_.forEach(brandsData, brand => {
brandList.push({
url: helpers.urlFormat('', {shopId: brand.shops_id}, brand.shop_domain),
src: brand.shop_logo,
shopId: brand.shops_id,
brandId: brand.brand_id
});
});
Object.assign(respData.newBrand.brandList, brandList);
}
// 最新上架
if (result[3].code === 200 && result[3].data) {
let groupSort = _.get(result, '[3].data.filter.group_sort', []),
ctyList = [];
// 推荐品类
_.forEach(groupSort, group =>{
_.forEach(group.sub, subSort =>{
let cateObj = {
cateId: subSort.category_id,
url: publicHandler.handleFilterUrl(params, {
sort: subSort.relation_parameter.sort,
cateId: subSort.category_id
}),
name: subSort.category_name,
active: false
};
if (ctyList.length < 20) {
// 默认选中判断
if (cateId === subSort.category_id) {
cateObj.active = true;
}
ctyList.push(cateObj);
} else {
return true;
}
});
});
Object.assign(respData.newProduct.ctyList, ctyList);
}
// 最新上架
if (result[4].code === 200 && result[4].data) {
// 列表数据
Object.assign(respData.newProduct, _proListHandler(result[4].data,
Object.assign({}, recParams, {channel: channel, cateId: cateId})));
}
// 数据为空,不显示页面模块
if (_.isEmpty(respData.slide.list)) {
delete respData.slide;
}
if (_.isEmpty(respData.recommond.dataList)) {
delete respData.recommond;
}
if (_.isEmpty(respData.newBrand.brandList)) {
delete respData.newBrand;
}
if (_.isEmpty(respData.newProduct.newProList) && _.isEmpty(respData.newProduct.ctyList)) {
delete respData.newProduct;
}
if (_.isEmpty(respData.firstLook.lookBanner.list) && _.isEmpty(respData.firstLook.lookTwoImg)) {
delete respData.firstLook;
}
return respData;
});
};
/**
* 加载最新上架数据
* @param req
* @returns {Promise.<TResult>}
*/
const getRecList = (req) => {
let channel = req.yoho.channel;
let params = {
yh_channel: channelMap[channel].yh_channel,
channel: channel,
uid: req.user.uid || ''
};
Object.assign(params, {
sort: req.query.sort || '',
cateId: req.query.cateId || '',
page: req.query.page || 1
});
let apiMethod = [
api.recList(params)
];
return Promise.all(apiMethod).then(result => {
let respData = {};
if (result[0].code === 200 && result[0].data) {
Object.assign(respData, _proListHandler(result[0].data, params));
}
return respData;
});
};
module.exports = {
index,
getRecList
};
... ...
... ... @@ -13,7 +13,6 @@ const config = global.yoho.config;
const helpers = global.yoho.helpers;
const cache = global.yoho.cache;
const logger = global.yoho.logger;
const images = require('../../../utils/images.js');
const getSortByConditionAsync = (condition) => {
return api.get('', Object.assign({
... ... @@ -288,191 +287,50 @@ const getBrandCouponAsync = (brandId, uid) => {
*/
const getBrandShop = (query) => {
let finalParams = {
// method: 'web.regular.groupsort'
method: 'web.search.shopInfo'
method: 'web.search.shopNewInfo'
};
Object.assign(finalParams, {keyword: query});
let cKey = getSearchCacheKey(finalParams);
return cache.get(cKey)
.catch(err => logger.debug(`product query save cache data fail:${err.toString()}`))
.then(cdata => {
let retObj;
try {
if (cdata) {
retObj = JSON.parse(cdata);
}
} catch (e) {
logger.debug('getBrandShop cache data parse fail.');
}
if (retObj) {
return retObj;
} else {
return api.get('', finalParams).then(ret => {
if (ret && ret.code === 200) {
saveCache(cKey, ret.data, CACHE_TIME_S);
return ret.data;
}
return null;
});
}
});
};
/**
* 根据品牌ID获取品牌下的店铺
* @return
*/
const getShopsByBrandId = bid => {
let finalParams = {
method: 'app.shop.queryShopsByBrandId',
brand_id: bid
};
let cKey = getSearchCacheKey(finalParams);
return cache.get(cKey)
.catch(err => logger.debug(`product query save cache data fail:${err.toString()}`))
.then(cdata => {
let cdataObj;
if (cdata) {
try {
cdataObj = JSON.parse(cdata);
} catch (e) {
logger.debug('getShopsByBrandId cache data parse fail.');
}
}
if (cdataObj) {
return cdataObj;
} else {
return api.get('', finalParams).then(ret => {
if (ret && ret.code === 200) {
saveCache(cKey, ret.data, CACHE_TIME_S);
return ret.data;
}
return null;
});
}
});
};
const shopFormat = shopDatas => {
let shopEntry = [];
_.forEach(shopDatas, val => {
let sorts = [];
let shopId = _.get(val, 'shop.shop_id', '');
let url = helpers.urlFormat('', {shopId: shopId}, val.shop.brand_domain);
if (val.shopSort) {
for (let ss of val.shopSort) {
if (!ss.sub) {
continue;
}
let isFull = false;
for (let misort of ss.sub) {
if (sorts.length >= 10) {
isFull = true;
break;
}
sorts.push({
href: `${url}&msort=${ss.sort_id}&misort=${misort.sort_id}`,
name: misort.sort_name
});
}
if (isFull) {
break;
}
}
}
shopEntry.push({
home: url,
logo: images.getImageUrl(val.shop.brand_ico, 80, 50, 1, 'brandLogo'),
shopName: val.shop.brand_name,
sort: sorts
});
});
return shopEntry;
return api.get('', Object.assign(finalParams, {keyword: query}), config.apiCache);
};
/**
* 根据搜索得到店铺/品牌 列表
* 根据搜索得到店铺/品牌
*/
const getShopList = params => {
if (!params || !params.query) {
return;
}
let brandShop;
let brandShops;
return getBrandShop(params.query).then(shop => { // 获取品牌,并根据品牌获取品牌下的所有店铺
return getBrandShop(params.query).then(shops => {
let shopEntry = {},
sort = _.get(shops, 'data.sortInfo.sort', {}),
shopInfo = _.get(shops, 'data.shopBrandInfo.shopInfo', {}) ||
_.get(shops, 'data.shopBrandInfo.brandInfo', {});
if (!shop || !shop.id) {
if (_.isEmpty(shopInfo)) {
return;
}
brandShop = shop;
return getShopsByBrandId(shop.id).then(shops => {
if (shops && shops.length) {
return shops;
} else {
return shop;
}
});
}).then(shops => { // 获取品牌/品牌店下所有的分类
if (_.isArray(shops)) {
brandShops = shops;
let promises = [];
for (let s of shops) {
promises.push(getSortList({
brand: s.brand_id || brandShop.id
}));
}
return Promise.all(promises);
} else if (shops && shops.id) {
return getSortList({
brand: shops.id
});
}
}).then(sorts => { // 数组则为品牌店列表,否则为品牌
let shopData = [];
if (_.isArray(sorts)) {
_.forEach(sorts, (val, index) => {
shopData.push({
shop: brandShops[index],
shopSort: val && val.data && !_.isFunction(val.data.sort) && val.data.sort
shopEntry = {
home: helpers.urlFormat('', '', shopInfo.shop_domain || shopInfo.brand_domain),
logo: shopInfo.shop_logo || shopInfo.brand_ico,
shopName: shopInfo.shop_name || shopInfo.brand_name,
sort: []
};
// 店铺/品牌的小分类
_.forEach(sort, (sortInfo) => {
_.forEach(_.get(sortInfo, 'sub', []), (subSort) => {
shopEntry.sort.push({
href: helpers.urlFormat('', {misort: subSort.sort_id},
shopInfo.shop_domain || shopInfo.brand_domain),
name: subSort.sort_name
});
});
} else if (sorts && sorts.code === 200 && sorts.data) {
shopData.push({
shop: brandShop,
shopSort: !_.isFunction(sorts.data.sort) && sorts.data.sort
});
}
return shopFormat(shopData);
});
return shopEntry;
});
};
... ... @@ -557,12 +415,9 @@ const getArticleByBrand = (brand, udid, limit) => {
};
const getBrands4Filter = (params) => {
let finalParams = {
return api.get('', Object.assign({
method: 'web.regular.aggBrand'
};
return api.get('', Object.assign(params, finalParams));
}, params));
};
module.exports = {
... ...
... ... @@ -41,7 +41,8 @@ const handleFilterUrl = (originParam, newParam, delParam) => {
_.forEach(tempOriginParam, function(value, key) {
if (!delParam[key] && value) {
dest += `${key}=${value}&`;
// NOTE: 这里会对 query 进行编码,因为 query 有可以能是中文
dest += key === 'query' ? `${key}=${encodeURIComponent(value)}&` : `${key}=${value}&`;
}
});
... ... @@ -1598,6 +1599,20 @@ exports.getSearchParams = params => {
nparams.price = nmp.join(',');
}
// 商品详情页促销跳转
if (params && params.psp_id) {
Object.assign(nparams, {
promotion_id: params.psp_id,
method: 'app.search.promotion'
});
}
/** 查询参数再处理 **/
// 对可能有中文的情况进行处理
if (params.query) {
params.query = decodeURIComponent(params.query);
}
return Object.assign({}, params, nparams);
};
... ...
... ... @@ -26,9 +26,25 @@ exports.getKeyActivity = (query) => {
* @return {[type]} [description]
*/
exports.getSearchData = (params, channel) => {
let searchParams = searchHandler.getSearchParams(params);
switch (channel) {
case 'boys':
searchParams.physical_channel = 1;
break;
case 'girls':
searchParams.physical_channel = 2;
break;
case 'kids':
searchParams.physical_channel = 3;
break;
case 'lifestyle':
searchParams.physical_channel = 4;
break;
default:
break;
}
// 调用接口
let apiMethod = [
headerModel.requestHeaderData(channel),
... ... @@ -37,11 +53,6 @@ exports.getSearchData = (params, channel) => {
searchApi.getShopList(params)
];
// 搜索店铺
/* if (params.query) {
apiMethod.push(searchApi.getBrandShop(params.query));
}*/
return api.all(apiMethod).then(result => {
let finalResult = {
headerData: Object.assign(result[0].headerData, {
... ... @@ -164,5 +175,13 @@ exports.getBrands4Filter = (params) => {
});
}
// 商品详情页促销跳转
if (params && params.psp_id) {
Object.assign(nparams, {
promotion_id: params.psp_id,
method: 'app.promotion.aggBrand'
});
}
return this.getListBrandsFilter(params, nparams);
};
... ...
... ... @@ -10,6 +10,8 @@ const router = require('express').Router(); // eslint-disable-line
const cRoot = './controllers';
const auth = require(`${global.middleware}/auth`);
// const filter = require(`${global.middleware}/filter-qs`); // 参数过滤
// 商品详情controller
const detail = require(`${cRoot}/detail`);
... ... @@ -40,6 +42,9 @@ const search = require(`${cRoot}/search`);
// 学生优惠controller
const students = require(`${cRoot}/students`);
// 新品到着controller
const newArrive = require(`${cRoot}/newArrive`);
// 商品促销routers
router.get('/sale', sale.index); // sale 首页
router.get('/sale/discount/detail', sale.discount); // 折扣专场详情页
... ... @@ -112,4 +117,7 @@ router.get('/students/verify', students.verify); // 身份验证
router.get('/students/userAcquireStatus', students.userAcquireStatus); // 获取优惠券领取状态
router.get('/students/list', students.list); // 获取优惠券领取状态
// 新品到着改版
router.get('/newArrive', newArrive.index); // 获取优惠券领取状态
module.exports = router;
... ...
<div class="home-page yoho-page {{pageType}}" data-page="{{pageType}}">
{{> common/path-nav}}
{{! 头部banner}}
{{# slide}}
{{> banner}}
{{/ slide}}
{{#recommond}}
<div class="recommond-floor">
{{> common/floor-header}}
<div id="rec-swiper" class="swiper-container new-arrival-swiper rec-swiper">
<div class="swiper-wrapper">
{{#dataList}}
<div class="swiper-slide" data-shopId="{{shopId}}" data-brandId="{{brandId}}">
<a class="rec-pro" href="{{url}}" target="_blank">
<img src="{{image2 src w=185 h=86}}">
<p class="new-num">上新<span>{{num}}</span></p>
</a>
</div>
{{/dataList}}
</div>
<a class="prev" href="javascript:;">
<span class="iconfont">&#xe609;</span>
</a>
<a class="next" href="javascript:;">
<span class="iconfont">&#xe608;</span>
</a>
</div>
</div>
{{/recommond}}
{{#newBrand}}
<div class="newBrand-floor">
{{> common/floor-header}}
<div id="brand-swiper" class="swiper-container new-arrival-swiper brand-swiper">
<div class="swiper-wrapper">
{{#brandList}}
<span class="swiper-slide" data-shopId="{{shopId}}" data-brandId="{{brandId}}">
<a class="" href="{{url}}" target="_blank">
<img src="{{image2 src w=185 h=86}}">
</a>
</span>
{{/brandList}}
</div>
<a class="prev" href="javascript:;">
<span class="iconfont">&#xe609;</span>
</a>
<a class="next" href="javascript:;">
<span class="iconfont">&#xe608;</span>
</a>
</div>
</div>
{{/newBrand}}
{{#firstLook}}
<div class="firstLook-floor clearfix">
{{> common/floor-header}}
{{#lookBanner}}
<div class="left-one">
<div class="slide-wrapper">
<ul>
{{# list}}
<li style="{{#if bgColor}}background:{{bgColor}}{{/if}}">
<a href="{{url}}" target= "_blank">
{{#if @first}}
<img src="{{image2 src w=785 h=420}}">
{{^}}
<img class="lazy" data-original="{{image2 src w=785 h=420}}" alt="">
{{/if}}
</a>
{{# tips}}
<div class="slide-tips">
<div class="g-mark"></div>
<p>{{.}}</p>
</div>
{{/ tips}}
</li>
{{/ list}}
</ul>
</div>
</div>
{{/lookBanner}}
<div class="right-two">
{{#lookTwoImg}}
<a class="first-right-img" href="{{url}}" target="_blank">
<img class="lazy" data-original="{{image2 src w=355 h=205}}" style="display: block; opacity: 1;">
</a>
{{/lookTwoImg}}
</div>
</div>
{{/firstLook}}
{{#newProduct}}
<div id="new-product-floor" class="newProduct-floor">
{{> common/floor-header}}
<div style="height:28px;" id="catagory-wrap">
<div class="all-catagory fixed-area clearfix">
<div class="catagory-text">推荐品类</div>
<ul class="catagory-navs clearfix">
{{#ctyList}}
<li {{#if active}} class="active" {{/if}} data-cateId="{{cateId}}">
<a href="{{url}}">{{name}}</a>
</li>
{{/ctyList}}
</ul>
</div>
</div>
<div id="pjax-container" class="new-arrive-list clearfix">
{{> list/new-arrive-list}}
</div>
</div>
{{/newProduct}}
<div id="new-arrive-latest" class="product-detail-page new-arrive-latest latest-walk">
<div class="bottom-tab">
<p>
<span class="bottom-title bottom-cur">最近浏览</span>
</p>
</div>
<div class="individual-comment info-block info-bottom">
<div class="latest-walk" style="display: block;">
<input id="latest-walk-count" type="hidden" value="5">
<div id="latest-walk-goods" class="goods clearfix"></div>
</div>
{{> product/latest-walk-tpl}}
<div class="lazy-load-object">
<textarea class="latest-walk-datalazyload" style="visibility: hidden;">
<script> fetchLatestWalk(); </script>
</textarea>
</div>
</div>
</div>
</div>
... ...
{{> list/new-arrive-list}}
... ...
<div class="product-detail-page yoho-page">
{{# detail}}
{{# banner}}
<div class="brand-banner" style="background:{{bgColor}}{{#if bgImg}} url({{image bgImg 1920 45}}){{/if}}">
<div class="center-content clearfix">
<a class="pull-left" href="{{homeUrl}}">
<img src="{{image2 logo}}">
</a>
<div class="opt pull-right">
<a class="home" href="{{homeUrl}}" title="{{brandName}}">
<span class="iconfont">&#xe61a;</span>
</a>
<span id="brand-favour" class="brand-fav{{#if isCollect}} coled{{/if}}" data-id="{{brandId}}">
<i class="iconfont">&#xe641;</i>
<span class="fav-num"></span>
</span>
</div>
</div>
</div>
{{/ banner}}
{{>product/brand-banner}}
<div class="center-content">
{{> common/path-nav}}
... ... @@ -38,550 +21,29 @@
</div>
{{/if}}
{{!-- 因接口原因,暂存size的title的值 --}}
<div id="size-title-json" style="display:none;">{{sizeTitleJson}}</div>
<div id="package" class="package-box clearfix"></div>
<div class="total-content">
<div class="other-infos">
<div class="description-material info-block head getnav" id="goodsMessage" data-id="0">
<p class="block-title">
<span class="title-head"> <span class="title cur">商品信息</span> </span>
</p>
{{#if description}}
<div class="description-content">
{{# description}}
<ul class="basic clearfix">
{{# basic}}
<li>
<em class="justpostion">
{{#if dColor}}
<span class="keySpace">{{{escapeType key}}}: </span>
<span id="desc-color" title="{{value}}" class="valueSpace">{{value}}</span>
{{^}}
<span class="keySpace">{{{escapeType key}}}: </span>
<span class="valueSpace">{{value}}</span>
{{/if}}
</em>
</li>
{{/ basic}}
</ul>
{{#if comfort}}
<ul class="comfort clearfix">
{{# comfort}}
<li class="pull-left">
<span class="comfort-title">{{{escapeLength name}}}</span>
<span class="min-des">{{minDes}}</span>
{{# blocks}}
<span class="comfort-block {{#if cur}}cur{{/if}}"></span>
{{/ blocks}}
<span class="max-des">{{maxDes}}</span>
</li>
{{/ comfort}}
</ul>
{{/if}}
{{/ description}}
</div>
{{/if}}
</div>
{{#if material.materialDetail}}<div class="description-material info-block">
<p class="block-title">
<span class="title-head"> <span class="title cur">材质洗涤</span> </span>
</p>
<div class="material-content">
{{# material}}
{{#if materialDetail}}
<ul class="material-detail">
{{# materialDetail}}
<li class="clearfix">
<div class="img-wrap clearfix">
<img src="{{image2 img}}">
<p class="name">{{name}}<br>{{enName}}</p>
</div>
<p class="text">{{text}}</p>
</li>
{{/ materialDetail}}
</ul>
{{/if}}
{{#if wash}}
<ul class="wash">
{{# wash}}
<li>
<img class="wash-icon" src="{{image2 img}}">
<p class="wash-name">{{name}}</p>
</li>
{{/ wash}}
</ul>
{{/if}}
{{/ material}}
</div>
</div>
{{/if}}
{{#if size.tbody}}<div class="description-material-tab info-block getnav" id="sizeMessage" data-id="1">
<p class="block-title" id="sizeTitle">
<span class="title-head"> <span class="title cur">尺码信息</span> </span>
</p>
<div class="size-content">
{{#if goodsInfo.virtualGoods}}
<!---虚拟商品-尺码信息没有--->
{{else}}
<div class="size-info ">
{{# size}}
<table class="size-table">
<thead>
<tr>
{{# thead}}
<th>{{name}}</th>
{{/ thead}}
</tr>
</thead>
<tbody>
{{# tbody}}
<tr>
{{#each .}}
<td>{{.}}</td>
{{/each}}
</tr>
{{/ tbody}}
</tbody>
</table>
<p class="size-tip">
※ 以上尺寸为实物人工测量,因测量方式不同会有1-2CM误差,相关数据仅作参考,以收到实物为准。 单位:CM
<br />
※ 参考尺码因衣服版型、剪裁不同会有误差,仅供参考
</p>
{{#if sizeImg}}
<img class="size-img" src="{{image2 sizeImg}}">
{{/if}}
{{/ size}}
</div>
{{/if}}
</div>
</div>
{{/if}}
{{#if reference}}
<div class="description-material-tab info-block">
<p class="block-title">
<span class="title-head"> <span class="title cur">试穿参考</span> </span>
</p>
<div class="model-content">
<div class="reference">
{{# reference}}
<table class="reference-table">
<thead>
<tr>
{{# thead}}
<th class="{{#if @first}}avatar-col{{/if}}{{#if modelCol}}model-col{{/if}}{{#if remarkCol}}remark-col{{/if}}">{{name}}</th>
{{/ thead}}
</tr>
</thead>
<tbody>
{{# tbody}}
<tr>
{{#each .}}
<td>
{{#if @first}}
<img class="avatar" src="{{image2 .}}">
{{^}}
{{.}}
{{/if}}
</td>
{{/each}}
</tr>
{{/ tbody}}
</tbody>
</table>
{{/ reference}}
<p class="size-tip">
※ 模特试穿中身高单位:CM,体重单位:KG,三围单位:CM
</p>
</div>
</div>
</div>
{{/if}}
{{#if modelCards}}
<div class="description-material-tab info-block">
<p class="block-title">
<span class="title-head"> <span class="title cur">模特信息</span> </span>
</p>
<div class="model-content">
<div class="ref-model">
<div class="ref-model">
{{# modelCards}}
<div class="model" style="background: url({{image2 url}}) no-repeat">
<span>试穿尺码: <em>{{size}}</em></span>
</div>
{{/ modelCards}}
</div>
</div>
{{#if fittingReport}}
<div class="fitting-report info-block">
<p class="block-title">
<span class="title cur">试穿报告</span>
</p>
{{# fittingReport}}
{{#if frImg}}
<div class="fr-img-wrap">
<img src="{{image2 frImg}}">
</div>
{{^}}
<table class="fitting-report-table">
<thead>
<tr>
{{# thead}}
<th>{{.}}</th>
{{/ thead}}
</tr>
</thead>
<tbody>
{{# tbody}}
<tr>
{{#each .}}
<td>{{.}}</td>
{{/each}}
</tr>
{{/ tbody}}
</tbody>
</table>
{{/if}}
{{/ fittingReport}}
</div>
{{/if}}
</div>
</div>
{{/if}}
<div class="details info-block getnav" id="goodsInside" data-id="2">
<p class="block-title" id="goodsTitle">
<span class="title-head"> <span class="title cur">商品详情</span> </span>
</p>
<div id="details-html" class="details-html">
<div class="lazy-load-object">
<textarea class="datalazyload" style="visibility: hidden;">
<script>
fetchHotArea();
</script>
</textarea>
</div>
{{{details}}}
{{#if goodsInfo.imageBanner}}
<a class="img-link" href="{{goodsInfo.imageBanner.url}}">
<img src="{{image2 goodsInfo.imageBanner.activityImg}}">
</a>
{{/if}}
</div>
</div>
{{#if comment}}
<div class="lazy-load-object">
<textarea class="datalazyload" style="visibility: hidden;">
<script>
fetchComment();
</script>
</textarea>
</div>
<div class="consult-comment info-block getnav" id="judge" data-id="3">
<p class="block-title" id="judgeTitle">
<span class="title-head"> <span class="title cur">商品评价</span> </span>
</p>
<div class="comments cc-content">
<div class="comment-tabs clearfix">
<h2 class="active" data-comment-type="7">
全部 ( <em class="comment-num all-comment-num">0</em> )
</h2>
<h2 data-comment-type="6">
有图 ( <em class="comment-num img-comment-num">0</em> )
</h2>
</div>
<div class="judge-content">
<div data-comment-list="7">
<ul>
<div class="img-4"><span class="img-4-message">暂无评论~</span></div>
</ul>
</div>
<div data-comment-list="6" class="m-hide">
<ul>
<div class="img-4"><span class="img-4-message">暂无评论~</span></div>
</ul>
</div>
</div>
</div>
</div>
<div class="lazy-load-object">
<textarea class="datalazyload" style="visibility: hidden;">
<script>
fetchComment();
</script>
</textarea>
</div>
{{/if}}
{{#if consult}}
<div class="consult-comment info-block getnav" id="goodsAsk" data-id="4">
<div class="lazy-load-object">
<textarea class="datalazyload" style="visibility: hidden;">
<script>
fetchConsult();
fetchRecommend();
</script>
</textarea>
</div>
<p class="block-title" id="goodsAskTitle">
<span class="title-head"> <span class="title cur">商品咨询</span> </span>
</p>
<div class="common-consults">
<div class="common-question">
<p>
<span class="top-question"><i class="iconfont">&#xe695;</i>商品都是正品吗?</span>
<span class="bottom-answer"><i class="iconfont">&#xe696;</i>有货www.yohobuy.com所售的商品均经品牌授权,
正品保障,支持专柜验货,与您亲临商场选购的商品一样享受相同的质量保证,
请您放心购买。</span>
</p>
</div>
<div class="common-question">
<p>
<span class="top-question"><i class="iconfont">&#xe695;</i>尺码表上的尺码标准吗?</span>
<span class="bottom-answer"><i class="iconfont">&#xe696;</i>有货所售商品尺寸均为人工实物测量,
可能会存在1-2cm的正常误差范围。</span>
</p>
</div>
<div class="common-question">
<p>
<span class="top-question"><i class="iconfont">&#xe695;</i>图片颜色和实物颜色相同吗?</span>
<span class="bottom-answer"><i class="iconfont">&#xe696;</i>有货所有商品均采用实物专业拍摄,但由于个人显示器不同,
可能导致实物与图片存在色差,最终颜色以实物为准。</span>
</p>
</div>
<div class="common-question">
<p>
<span class="top-question"><i class="iconfont">&#xe695;</i>发货及配送</span>
<span class="bottom-answer"><i class="iconfont">&#xe696;</i>当天下午3点前订单当天发,之后的订单隔天发,
合作快递有:韵达、EMS、顺丰、申通、圆通、宅急送,普通快递3-5天左右送达,顺丰速运1-2天送达。</span>
</p>
</div>
<div class="common-question">
<p>
<span class="top-question"><i class="iconfont">&#xe695;</i>退货or换货</span>
<span class="bottom-answer"><i class="iconfont">&#xe696;</i>签收商品未经穿着不影响二次销售的情况下,7日内退货,15日内换货;
退回商品保证吊牌、标签、包装完整,详情点击 <a href="http://www.yohobuy.com/help/?category_id=69" target="_blank">&#12288;&#12288;&gt;&gt;退换货政策</a></span>
</p>
</div>
<div class="lazy-load-object">
<textarea class="datalazyload" style="visibility: hidden;">
<script>
fetchConsult();
fetchRecommend();
</script>
</textarea>
</div>
<div class="common-question">
<p>
<span class="common-advice">
<a href="#textbox-wrapper" id="common-advice">
<i class="iconfont advice"> &#xe602;</i>
我要咨询&gt;
</a>
</span>
</p>
</div>
<div class="buy-consults">
<p class="block-title">
<span class="title-head">
<span class="title cur">购买咨询(<i class="consult-num">0</i></span>
</span>
</p>
</div>
<div id="consults-ul"></div>
<div class="common-question"></div>
<div class="consults-pager"></div>
<div id="textbox-wrapper" class="common-question input">
<textarea id="textbox" placeholder="请输入您的问题"></textarea>
<span id="submit-consult" class="btn">提交咨询</span>
</div>
</div>
<div class="lazy-load-object">
<textarea class="datalazyload" style="visibility: hidden;">
<script>
fetchConsult();
fetchRecommend();
</script>
</textarea>
</div>
</div>
{{/if}}
</div>
</div>
<div class="after-service">
<div class="lazy-load-object">
<textarea class="datalazyload" style="visibility: hidden;">
<script>
fetchReturn();
fetchRecommend();
</script>
</textarea>
</div>
<div id="after-service-switch" class="after-service-switch clearfix">
<span class="iconfont">&#xe628;</span>&nbsp;
售后服务
<span class="iconfont triangle">&#xe60b;</span>
</div>
<div class="after-service-content info-block">
<div class="block-title">
<span class="title-head">
<span class="title cur">退换货流程</span>
</span>
</div>
<div class="img-3"></div>
<div class="info-block">
<div class="block-title">
<span class="title-head">
<span class="title cur">有货承诺</span>
</span>
</div>
</div>
{{> product/description}}
{{> product/material}}
{{> product/size-desc-list}}
{{> product/reference}}
{{> product/model-cards}}
{{> product/fitting-report}}
{{> product/introduction}}
{{> product/comment}}
{{> product/consult}}
</div>
<div id="saleReturn" class="support-saleReturned-service"></div>
</div>
{{#unless @root.pc.product.removeRecentView}}
<div class="lazy-load-object">
<textarea class="datalazyload" style="visibility: hidden;">
<script>
fetchRecommend();
</script>
</textarea>
</div>
<div class="bottom-tab">
<p>
<span class="bottom-title bottom-cur">店铺推荐</span>
<span class="bottom-title">最近浏览</span>
<span class="bottom-title change">换一批
<span class="iconfont change-icon">&#xe639;</span>
</span>
</p>
</div>
{{> product/after-service}}
<div class="individual-comment info-block info-bottom">
{{#if latestWalk}}
<div class="latest-walk">
<input id="latest-walk-count" type="hidden" value="{{latestWalk}}">
<div id="latest-walk-goods" class="goods clearfix"></div>
{{> product/latest-walk-tpl}}
</div>
{{/if}}
{{> product/recommend-receiveview}}
<div id="recommend-shop" class="hide">
<div class="recommend-content clearfix">
<div class="recommend-slider">
<ul class=" img-list" id="recommend-content"></ul>
<div class="img-brand-switch">
<a class="prev iconfont" href="javascript:;">&#xe609;</a>
<a class="next iconfont" href="javascript:;">&#xe608;</a>
</div>
</div>
</div>
</div>
</div>
{{/unless}}
</div>
{{/ detail}}
</div>
{{# statGoodsInfo}}
<script type="text/javascript" src="//static.criteo.net/js/ld/ld.js" async="true"></script>
<script type="text/javascript">
window.criteo_q = window.criteo_q || [];
window.criteo_q.push(
{event: "setAccount", account: 16184},
{event: "setCustomerId", id: "{{uid}}"},
{event: "setSiteType", type: "d"},
{event: "viewItem", item: "{{skn}}"}
);
</script>
<script type="text/javascript">
var _mvq = _mvq || [];
_mvq.push(['$setAccount', 'm-23428-1']);
_mvq.push(['$setGeneral', 'goodsdetail', '', /*用户名*/ '', /*用户id*/ '']);
_mvq.push(['$logConversion']);
_mvq.push([
'$addGoods', /*分类id*/ '', /*品牌id*/ '', /*商品名称*/ '', /*商品ID*/ '{{skn}}', /*商品售价*/ '', /*商品图片url*/ '', /*分类名*/
'', /*品牌名*/ '', /*商品库存状态1或是0*/ '', /*网络价*/ '', /*收藏人数*/ ''
]);
_mvq.push(['$logData']);
(function() {
var mvl = document.createElement('script');
mvl.type = 'text/javascript';
mvl.async = true;
mvl.src = ('https:' == document.location.protocol ? 'https://static-ssl.mediav.com/mvl.js' : 'http://static.mediav.com/mvl.js');
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(mvl, s);
})();
</script>
<script>
window.PING_YOU_VIEW_ITEM = {
'product_no':'{{productId}}',
'spu_id': '{{skn}}',
'name': '{{{productName}}}',
'category': '{{{category}}}',
'brand': '{{{brandName}}}',
'price': {{salePrice}},
'orig_price': {{marketPrice}},
'currency_code': 'CNY',
'product_url': '{{{productUrl}}}',
'pic_size': '',// 宽x高
'pc_pic_url': '{{{imageUrl}}}',
'promotion': '',
'sold_out': {{soldOut}}
};
</script>
{{/statGoodsInfo}}
{{> product/stat}}
... ...
{{#newProList }}
{{!应季热门、热门搜索}}
{{#if tagType}}
<div class="good-info imgopacity" recommend-type="{{recType}}">
<div class="list-top-img {{#if hotSearch}}hot-search-img{{/if}}"></div>
<ul class="list-box clearfix">
{{#tags}}
<li data-cateId="{{cateId}}"><a href="{{url}}" target="_blank">{{name}}</a></li>
{{/tags}}
</ul>
</div>
{{/if}}
{{!普通商品}}
{{#if goodsType}}
<div class="good-info imgopacity" data-skn="{{proSkn}}">
<div class="good-detail-img">
<a class="good-thumb" href="{{url}}" target="_blank">
<img class="lazy" data-original="{{image2 src w=222 h=298}}" style="display: block; opacity: 1;">
</a>
</div>
<div class="good-detail-text">
<a href="{{url}}" target="_blank">{{proName}}</a>
<p class="price">
<span class="sale-priceprime-cost"> ¥{{salesPrice}}</span>
</p>
</div>
</div>
{{/if}}
{{!店铺}}
{{#if shopType}}
<div class="good-info imgopacity" recommend-type="{{recType}}" data-shopId="{{shopId}}">
<a class="brand-box" href="{{url}}" target="_blank">
<div class="logo-wrap">
<img class="lazy" data-original="{{image2 src w=185 h=86}}" style="display: block; opacity: 1;">
</div>
<div class="brand-info clearfix">
<p class="shop-name">{{shopName}}</p>
<p class="num-info">上新<span>{{newNum}}</span>&nbsp;&nbsp;<span>{{collNum}}</span>人收藏</p>
<span class="btn-tag tag-home">
<i class="iconfont">&#xe61a;</i> <em>进入店铺</em>
</span>
</div>
</a>
</div>
{{/if}}
{{!SK商品}}
{{#if skGoodsType}}
<div class="good-info imgopacity" data-skn="{{proSkn}}">
<div class="good-detail-img">
<a class="good-thumb" href="" target="_blank">
<img class="lazy" data-original="//img13.static.yhbimg.com/goodsimg/2016/11/08/16/0209f4293037c2c5ca85bf67991b691c9a.jpg?imageMogr2/thumbnail/280x373/extent/280x373/background/d2hpdGU=/position/center/quality/90" src="//img13.static.yhbimg.com/goodsimg/2016/11/08/16/0209f4293037c2c5ca85bf67991b691c9a.jpg?imageMogr2/thumbnail/280x373/extent/280x373/background/d2hpdGU=/position/center/quality/90" style="display: block; opacity: 1;">
</a>
</div>
<div class="ka-tag">
<p class="ka-name">STUSSY</p>
</div>
<div class="good-detail-text ka-detail-text">
<a href="" target="_blank">Preppy Elite 简约连帽棉衣【两色可选】</a>
<p class="price">
<span class="sale-priceprime-cost"> ¥379.00</span>
</p>
</div>
</div>
{{/if}}
{{!文章}}
{{#if articalType}}
<div class="good-info imgopacity" recommend-type="{{recType}}" data-articalId="{{articalId}}">
<div class="guang-box">
<div class="classification">
潮 品
</div>
<div class="type-icon fashion-good"></div>
<a class="guang-img" href="{{url}}" target="_blank">
<img class="lazy" data-original="{{image2 src w=222 h=140}}" style="display: block;">
</a>
<div class="msg-info">
<a class="msg-title" href="{{url}}" target="_blank" style="word-wrap: break-word;">{{title}}</a>
<p class="msg-app">
<span class="publish-time">
<i class="iconfont"></i>
{{publishTime}}
</span>
<span class="page-view">
<i class="iconfont"></i>
<em>{{num}}</em>
</span>
</p>
</div>
</div>
</div>
{{/if}}
{{/newProList }}
{{> common/foot-pager}}
... ...
... ... @@ -2,7 +2,7 @@
{{# shopEntry}}
<div class="shop-entry clearfix">
<a class="pull-left" href="{{home}}">
<img class="logo" src="{{image2 logo}}">
<img class="logo" src="{{image2 logo w=80 h=50}}">
</a>
<div class="name pull-left">
... ...
... ... @@ -3,7 +3,7 @@
<span class="title pull-left">&nbsp;&nbsp;销: </span>
{{#if_cond activity.length '>=' 3}}
<div class="activity-title">展开全部促销 <span class="iconfont index">&#xe610;</span> </div>
<div class="activity-title"><span>展开全部促销</span> <i class="iconfont index">&#xe610;</i> </div>
{{/if_cond}}
<div class="activity-container">
... ... @@ -11,7 +11,13 @@
{{#each activity}}
<li class="promotion-item">
<span class="ac-type">{{type}}</span>
<span class="ac-des {{#if_cond ../activity.length '>=' 3}}small{{/if_cond}}">{{des}}</span>
<span class="ac-des {{#if_cond ../activity.length '>=' 3}}small{{/if_cond}}">
{{#if url}}
<a target="_blank" href="{{url}}">{{des}}</a>
{{^}}
<span>{{des}}</span>
{{/if}}
</span>
</li>
{{/each}}
</ul>
... ... @@ -21,8 +27,14 @@
<ul class="activity">
{{#each activity}}
<li class="promotion-item {{#if_cond @index '>=' 3}}hide{{/if_cond}}">
<span class="ac-type">{{type}}</span>
<span class="ac-des {{#if_cond ../activity.length '>=' 3}}small{{/if_cond}}">{{des}}</span>
<span class="ac-type">{{type}}</span>
<span class="ac-des {{#if_cond ../activity.length '>=' 3}}small{{/if_cond}}">
{{#if url}}
<a target="_blank" href="{{url}}">{{des}}</a>
{{^}}
<span>{{des}}</span>
{{/if}}
</span>
</li>
{{/each}}
</ul>
... ...
<div class="after-service">
<div class="lazy-load-object">
<textarea class="datalazyload" style="visibility: hidden;">
<script>
fetchReturn();
fetchRecommend();
</script>
</textarea>
</div>
<div id="after-service-switch" class="after-service-switch clearfix">
<span class="iconfont">&#xe628;</span>&nbsp;
售后服务
<span class="iconfont triangle">&#xe6c1;</span>
</div>
<div class="after-service-content">
<div class="info-block">
<div class="block-title">
<span class="title-head">
<span class="title cur">退换货流程</span>
</span>
</div>
<div class="img-3"></div>
</div>
<div class="info-block">
<div class="block-title">
<span class="title-head">
<span class="title cur">有货承诺</span>
</span>
</div>
</div>
</div>
<div id="saleReturn" class="support-saleReturned-service"></div>
</div>
... ...
{{# banner}}
<div class="brand-banner" style="background:{{bgColor}}{{#if bgImg}} url({{image bgImg 1920 45}}){{/if}}">
<div class="center-content clearfix">
<a class="pull-left" href="{{homeUrl}}">
<img src="{{logo}}">
</a>
<div class="opt pull-right">
<a class="home" href="{{homeUrl}}" title="{{brandName}}">
<span class="iconfont">&#xe61a;</span>
</a>
<span id="brand-favour" class="brand-fav{{#if isCollect}} coled{{/if}}" data-id="{{brandId}}">
<i class="iconfont">&#xe641;</i>
<span class="fav-num"></span>
</span>
</div>
</div>
</div>
{{/ banner}}
... ...
{{#if comment}}
<div class="lazy-load-object">
<textarea class="datalazyload" style="visibility: hidden;">
<script>
fetchComment();
</script>
</textarea>
</div>
<div class="consult-comment info-block getnav" id="judge" data-id="3">
<p class="block-title" id="judgeTitle">
<span class="title-head"> <span class="title cur">商品评价</span> </span>
</p>
<div class="comments cc-content">
<div class="comment-tabs clearfix">
<h2 class="active" data-comment-type="7">
全部 ( <em class="comment-num all-comment-num">0</em> )
</h2>
<h2 data-comment-type="6">
有图 ( <em class="comment-num img-comment-num">0</em> )
</h2>
</div>
<div class="judge-content">
<div data-comment-list="7">
<ul>
<div class="img-4"><span class="img-4-message">暂无评论~</span></div>
</ul>
</div>
<div data-comment-list="6" class="m-hide">
<ul>
<div class="img-4"><span class="img-4-message">暂无评论~</span></div>
</ul>
</div>
</div>
</div>
</div>
<div class="lazy-load-object">
<textarea class="datalazyload" style="visibility: hidden;">
<script>
fetchComment();
</script>
</textarea>
</div>
{{/if}}
... ...
{{#if consult}}
<div class="consult-comment info-block getnav" id="goodsAsk" data-id="4">
<div class="lazy-load-object">
<textarea class="datalazyload" style="visibility: hidden;">
<script>
fetchConsult();
fetchRecommend();
</script>
</textarea>
</div>
<p class="block-title" id="goodsAskTitle">
<span class="title-head"> <span class="title cur">商品咨询</span> </span>
</p>
<div class="common-consults">
<div class="common-question">
<p>
<span class="top-question clearfix">
<i class="iconfont">&#xe695;</i>
<span class="question">商品都是正品吗?</span>
</span>
<span class="answer-wrapper clearfix">
<i class="iconfont">&#xe696;</i>
<span class="answer">
有货www.yohobuy.com所售的商品均经品牌授权,
正品保障,支持专柜验货,与您亲临商场选购的商品一样享受相同的质量保证,
请您放心购买。
</span>
</span>
</p>
</div>
<div class="common-question">
<p>
<span class="top-question clearfix">
<i class="iconfont">&#xe695;</i>
<span class="question">尺码表上的尺码标准吗?</span>
</span>
<span class="answer-wrapper clearfix">
<i class="iconfont">&#xe696;</i>
<span class="answer">
有货所售商品尺寸均为人工实物测量,可能会存在1-2cm的正常误差范围。
</span>
</span>
</p>
</div>
<div class="common-question">
<p>
<span class="top-question clearfix">
<i class="iconfont">&#xe695;</i>
<span class="question">图片颜色和实物颜色相同吗?</span>
</span>
<span class="answer-wrapper clearfix">
<i class="iconfont">&#xe696;</i>
<span class="answer">
有货所有商品均采用实物专业拍摄,但由于个人显示器不同,可能导致实物与图片存在色差,最终颜色以实物为准。
</span>
</span>
</p>
</div>
<div class="common-question">
<p>
<span class="top-question clearfix">
<i class="iconfont">&#xe695;</i>
<span class="question">发货及配送</span>
</span>
<span class="answer-wrapper clearfix">
<i class="iconfont">&#xe696;</i>
<span class="answer">
当天下午3点前订单当天发,之后的订单隔天发,合作快递有:韵达、EMS、顺丰、申通、圆通、宅急送,普通快递3-5天左右送达,顺丰速运1-2天送达。
</span>
</span>
</p>
</div>
<div class="common-question">
<p>
<span class="top-question clearfix">
<i class="iconfont">&#xe695;</i>
<span class="question">退货or换货</span>
</span>
<span class="answer-wrapper clearfix">
<i class="iconfont">&#xe696;</i>
<span class="answer">
签收商品未经穿着不影响二次销售的情况下,7日内退货,15日内换货;
退回商品保证吊牌、标签、包装完整,详情点击
<br />
<a href="http://www.yohobuy.com/help/detail?id=49"
target="_blank">&gt;&gt;退换货政策</a>
</span>
</span>
</p>
</div>
<div class="lazy-load-object">
<textarea class="datalazyload" style="visibility: hidden;">
<script>
fetchConsult();
fetchRecommend();
</script>
</textarea>
</div>
<div class="common-question">
<p>
<span class="common-advice">
<a href="#textbox-wrapper" id="common-advice">
<i class="iconfont advice"> &#xe602;</i>
我要咨询<i class="iconfont click">&#xe608;</i>
</a>
</span>
</p>
</div>
<div class="buy-consults">
<p class="block-title">
<span class="title-head">
<span class="title cur">购买咨询(<i class="consult-num">0</i></span>
</span>
</p>
</div>
<div id="consults-ul"></div>
<div class="common-question"></div>
<div class="consults-pager"></div>
<div id="textbox-wrapper" class="common-question input">
<textarea id="textbox" placeholder="请输入您的问题"></textarea>
<span id="submit-consult" class="btn">提交咨询</span>
</div>
</div>
<div class="lazy-load-object">
<textarea class="datalazyload" style="visibility: hidden;">
<script>
fetchConsult();
fetchRecommend();
</script>
</textarea>
</div>
</div>
{{/if}}
... ...
{{#if description}}
<div class="description-material info-block head getnav" id="goodsMessage" data-id="0">
<p class="block-title">
<span class="title-head"> <span class="title cur">商品信息</span> </span>
</p>
<div class="description-content">
{{# description}}
<ul class="basic clearfix">
{{# basic}}
<li>
<em class="justpostion">
{{#if dColor}}
<span class="keySpace">{{{escapeType key}}}: </span>
<span id="desc-color" title="{{value}}" class="valueSpace">{{value}}</span>
{{^}}
<span class="keySpace">{{{escapeType key}}}: </span>
<span class="valueSpace">{{value}}</span>
{{/if}}
</em>
</li>
{{/ basic}}
</ul>
{{#if comfort}}
<ul class="comfort clearfix">
{{# comfort}}
<li class="pull-left">
<span class="comfort-title">{{{escapeLength name}}}</span>
<span class="min-des">{{minDes}}</span>
{{# blocks}}
<span class="comfort-block {{#if cur}}cur{{/if}}"></span>
{{/ blocks}}
<span class="max-des">{{maxDes}}</span>
</li>
{{/ comfort}}
</ul>
{{/if}}
{{/ description}}
</div>
</div>
{{/if}}
... ...
... ... @@ -35,7 +35,7 @@
<div class="magnifier move-object hide"></div>
<div class="magnifier move-over"></div>
<div id="max" class="magnifier max hide">
<img id='big' src="{{image2 img w=1000 h=1333}}">
<img id='big' src="{{image2 img w=750 h=1000}}">
</div>
</div>
... ... @@ -48,14 +48,14 @@
{{# thumbs}}
<img class="thumb {{#if @first}}active{{/if}}" src="{{image2 img w=75 h=100}}"
data-shower="{{image2 shower w=420 h=560}}"
data-origin="{{image2 shower w=1001 h=1333}}">
data-origin="{{image2 shower w=750 h=1000}}">
{{/ thumbs}}
{{^}}
{{# thumbs}}
<img class="thumb lazy"
data-original="{{image2 img w=75 h=100}}"
data-shower="{{image2 shower w=420 h=560}}"
data-origin="{{image2 shower w=1001 h=1333}}">
data-origin="{{image2 shower w=750 h=1000}}">
{{/ thumbs}}
{{/if}}
</div>
... ... @@ -77,6 +77,8 @@
{{> product/coupon-list}}
<div class="line"></div>
<div class="trade-content">
<div id="type-chose" class="type-chose">
{{#if virtualGoods}}
... ... @@ -153,7 +155,7 @@
</span>
<span id="enable-notify" class="buy-btn hide"> <i class="iconfont">
&#xe63d;</i> <span>到货通知</span></span>
&#xe6e2;</i> <span>到货通知</span></span>
<span id="collect-product" class="{{#if isCollect}}coled {{/if}}collect-product">
... ...
{{#if fittingReport}}
<div class="fitting-report info-block">
<p class="block-title">
<span class="title cur">试穿报告</span>
</p>
{{# fittingReport}}
{{#if frImg}}
<div class="fr-img-wrap">
<img src="{{frImg}}">
</div>
{{^}}
<table class="fitting-report-table">
<thead>
<tr>
{{# thead}}
<th>{{.}}</th>
{{/ thead}}
</tr>
</thead>
<tbody>
{{# tbody}}
<tr>
{{#each .}}
<td>{{.}}</td>
{{/each}}
</tr>
{{/ tbody}}
</tbody>
</table>
{{/if}}
{{/ fittingReport}}
</div>
{{/if}}
... ...
<div class="details info-block getnav" id="goodsInside" data-id="2">
<p class="block-title" id="goodsTitle">
<span class="title-head"> <span class="title cur">商品详情</span> </span>
</p>
<div id="details-html" class="details-html">
<div class="lazy-load-object">
<textarea class="datalazyload" style="visibility: hidden;">
<script>
fetchHotArea();
</script>
</textarea>
</div>
{{{details}}}
{{#if goodsInfo.imageBanner.url}}
<a class="img-link" href="{{goodsInfo.imageBanner.url}}">
<img src="{{goodsInfo.imageBanner.activityImg}}">
</a>
{{/if}}
</div>
</div>
... ...
{{#if material.materialDetail}}<div class="description-material info-block">
<p class="block-title">
<span class="title-head"> <span class="title cur">材质洗涤</span> </span>
</p>
<div class="material-content">
{{# material}}
{{#if materialDetail}}
<ul class="material-detail">
{{# materialDetail}}
<li class="clearfix">
<div class="img-wrap clearfix">
<img src="{{img}}">
<p class="name">{{name}}<br>{{enName}}</p>
</div>
<p class="text">{{text}}</p>
</li>
{{/ materialDetail}}
</ul>
{{/if}}
{{#if wash}}
<ul class="wash">
{{# wash}}
<li>
<img class="wash-icon" src="{{img}}">
<p class="wash-name">{{name}}</p>
</li>
{{/ wash}}
</ul>
{{/if}}
{{/ material}}
</div>
</div>
{{/if}}
... ...