Authored by 郝肖肖

merage master

Showing 80 changed files with 1362 additions and 1203 deletions

Too many changes to show.

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

... ... @@ -22,7 +22,6 @@ const memcached = require('connect-memcached');
const hbs = require('express-handlebars');
const multer = require('connect-multiparty');
const pkg = require('./package.json');
const yohoLib = require('yoho-node-lib');
const app = express();
... ... @@ -64,7 +63,7 @@ app.use(session({
name: 'yohoblk-session',
cookie: {
domain: config.cookieDomain,
httpOnly: false
httpOnly: true
},
store: new MemcachedStore({
hosts: config.memcache.session,
... ... @@ -91,10 +90,12 @@ try {
const errorHanlder = require(`${global.middleware}/error-handler`);
const setPageInfo = require(`${global.middleware}/set-pageinfo`);
const display = require(`${global.middleware}/display`);
const safeRedirect = require(`${global.middleware}/safe-redirect`).middleware;
// YOHO 前置中间件
app.use(mobileCheck());
app.use(setYohoData());
app.use(safeRedirect());
app.use(user());
app.use(seo());
app.use(setPageInfo());
... ...
... ... @@ -22,19 +22,19 @@ const index = (req, res, next) => {
if (channel === 'women') {
contentCode = '527079e6c46d0f125eb46b835968971b';
name = 'WOMEN首页';
link = 'http://www.yohoblk.com/women';
link = '//www.yohoblk.com/women';
channel = 302;
gender = '2,3';
} else if (channel === 'lifestyle') {
contentCode = '94b5ed607b6d565ffc29c2c04be121dc';
name = 'LIFT STYLE首页';
link = 'http://www.yohoblk.com/lifestyle';
link = '//www.yohoblk.com/lifestyle';
channel = 303;
gender = '1,2,3';
} else {
contentCode = '81886aaa5e82e3741bc1ba1e04ec7706';
name = 'MEN首页';
link = 'http://www.yohoblk.com';
link = '//www.yohoblk.com';
channel = 301;
gender = '1,3';
}
... ...
... ... @@ -6,7 +6,7 @@
<ul class="clearfix">
{{#each tabs}}
<li>
<a href="{{url}}" target="_blank">
<a href="{{https url}}" target="_blank">
<div class="g-mask"></div>
<p class="tips">{{name}}</p>
<img class="lazy" data-original="{{image src 370 304 1}}"/>
... ... @@ -20,7 +20,7 @@
<div class="category-nav">
{{#each category}}
<a href="#{{key}}" class="{{key}}">{{key}}</a>
{{/each}}
{{/each}}
</div>
</div>
... ... @@ -29,4 +29,4 @@
</div>
{{/ brand}}
</div>
\ No newline at end of file
</div>
... ...
... ... @@ -7,6 +7,7 @@
'use strict';
const model = require('../models');
const config = global.yoho.config;
exports.index = (req, res) => {
const channelType = req.path.substring(1) || 'men';
... ... @@ -15,7 +16,7 @@ exports.index = (req, res) => {
// 设置当前频道
res.cookie('_Channel', channelType, {
domain: '.yohoblk.com'
domain: config.cookieDomain
});
req.yoho.channel = channelType;
... ...
... ... @@ -55,6 +55,9 @@ const _getTitle = t => {
* @return {Object} 处理之后的数据
*/
const getSliderData = d => {
_.forEach(d, img => {
img.src = _.split(img.src, '?')[0];
});
return {
slider: d
... ...
<div class="ad-banner">
{{#adBanner}}
<a href="{{url}}" target="_blank">
<a href="{{https url}}" target="_blank">
<img class="lazy-img" data-original="{{image src 1150 163}}" title="{{title}}" alt="{{alt}}">
</a>
{{/adBanner}}
... ...
<div class="ad-container clearfix">
{{# brandsAd}}
<div class="ad {{#if @first}}first{{/if}}">
<a href="{{url}}" target="_blank">
<a href="{{https url}}" target="_blank">
<img class="lazy-img" data-original="{{image src 298 298}}" alt="">
</a>
{{> brand-text-box}}
... ...
{{# classicBrands}}
<div class="brand-img-box {{#if right}}right{{/if}} {{#if bottomSpace}}mb10{{/if}}">
{{# big}}
<a href="{{url}}" target="_blank">
<a href="{{https url}}" target="_blank">
<img class="big-img" src="{{image src 565 340}}">
</a>
{{/ big}}
{{# small}}
<a href="{{url}}" target="_blank">
<a href="{{https url}}" target="_blank">
<img class="small-img {{#if @first}}first{{/if}}" src="{{image src 281 285}}">
</a>
{{/ small}}
... ...
<div class="brand-text-box">
<h4>{{productName}}</h4>
<p>{{productDesc}}</p>
<a href="{{url}}" target="_blank">
<a href="{{https url}}" target="_blank">
<button>{{btnText}}</button>
</a>
</div>
... ...
... ... @@ -5,7 +5,7 @@
<div class="news left">
{{# big}}
<span class="box">
<a href="{{url}}" target="_blank">
<a href="{{https url}}" target="_blank">
<img class="lazy-img" data-original="{{image src 395 495}}" alt="{{alt}}">
</a>
<div class="editorial-title"><div><p>{{title}}</p></div></div>
... ... @@ -15,7 +15,7 @@
<div class="news right">
{{# small}}
<span class="box {{#if bottomSpace}}bottom-space{{/if}} {{#if rightSpace}}right-space{{/if}}">
<a href="{{url}}" target="_blank">
<a href="{{https url}}" target="_blank">
<img class="lazy-img" data-original="{{image src 360 240}}" alt="{{alt}}">
</a>
<div class="editorial-title"><div><p>{{title}}</p></div></div>
... ...
... ... @@ -4,21 +4,21 @@
{{# newArrivals}}
<div class="arrival-item {{#if smallImg}}small-img{{/if}} {{#if @last}}last{{^}}normal{{/if}}">
{{#if even}}
<a href="{{url}}" target="_blank">
<a href="{{https url}}" target="_blank">
<img class="lazy-img" data-original="{{#if smallImg}}{{image src 218 490}}{{^}}{{image src 327 490}}{{/if}}" alt="{{alt}}">
</a>
<div class="brand-name">
<a href="{{url}}" target="_blank">
<a href="{{https url}}" target="_blank">
<span class="bottom">{{title}}</span>
</a>
</div>
{{^}}
<div class="brand-name">
<a href="{{url}}" target="_blank">
<a href="{{https url}}" target="_blank">
<span class="top">{{title}}</span>
</a>
</div>
<a href="{{url}}" target="_blank">
<a href="{{https url}}" target="_blank">
<img class="lazy-img" data-original="{{#if smallImg}}{{image src 218 490}}{{^}}{{image src 327 490}}{{/if}}" alt="{{alt}}">
</a>
{{/if}}
... ...
... ... @@ -3,7 +3,7 @@
<ul>
{{# slider}}
<li class="banner-item" style="{{#if bgColor}}background-color:{{bgColor}}{{/if}}; background-image:url('{{image src 1150 570}}')">
<a href="{{url}}" target= "_blank"></a>
<a href="{{https url}}" target= "_blank"></a>
{{# tips}}
<div class="slide-tips">
<div class="g-mark"></div>
... ... @@ -20,7 +20,7 @@
<ul class="clearfix">
{{# pagination}}
<li>
<a href="{{url}}" target="_blank"></a>
<a href="{{https url}}" target="_blank"></a>
<img src="{{image src 138 54}}" alt="">
</li>
{{/ pagination}}
... ...
... ... @@ -29,15 +29,15 @@ const index = (req, res, next) => {
if (channel === 'men') {
gender = '1,3';
name = 'MEN首页';
link = 'http://www.yohoblk.com';
link = '//www.yohoblk.com';
} else if (channel === 'women') {
gender = '2,3';
name = 'WOMEN首页';
link = 'http://www.yohoblk.com/women';
link = '//www.yohoblk.com/women';
} else {
gender = '3,3';
name = 'LIFESTYLE首页';
link = 'http://www.yohoblk.com/lifestyle';
link = '//www.yohoblk.com/lifestyle';
}
editorialModel.getIndexData(pageNum, limit, appType, udid, gender).then((result) => {
... ... @@ -95,15 +95,15 @@ const list = (req, res) => {
if (channel === 'men') {
gender = '1,3';
name = 'MEN首页';
link = 'http://www.yohoblk.com';
link = '//www.yohoblk.com';
} else if (channel === 'women') {
gender = '2,3';
name = 'WOMEN首页';
link = 'http://www.yohoblk.com/women';
link = '//www.yohoblk.com/women';
} else {
gender = '3,3';
name = 'LIFESTYLE首页';
link = 'http://www.yohoblk.com/lifestyle';
link = '//www.yohoblk.com/lifestyle';
}
if (tag) {
... ... @@ -126,7 +126,7 @@ const list = (req, res) => {
name: name
},
{
link: 'http://www.yohoblk.com/editorial',
link: '//www.yohoblk.com/editorial',
pathTitle: '资讯',
name: 'Editorial资讯'
},
... ... @@ -138,7 +138,7 @@ const list = (req, res) => {
pathTitle: req.query.query || result.authorName,
msg: result.tabs,
paginationOpts: {
page: pageNum, // current page: http://host/?page=2
page: pageNum, // current page: //host/?page=2
limit: 20, // per_page records' number
total: result.total, // total page number
queryParams: req.query
... ... @@ -171,15 +171,15 @@ const detail = (req, res, next) => {
if (channel === 'men') {
name = 'MEN首页';
link = 'http://www.yohoblk.com';
link = '//www.yohoblk.com';
gender = '1,3';
} else if (channel === 'women') {
name = 'WOMEN首页';
link = 'http://www.yohoblk.com/women';
link = '//www.yohoblk.com/women';
gender = '2,3';
} else {
name = 'LIFESTYLE首页';
link = 'http://www.yohoblk.com/lifestyle';
link = '//www.yohoblk.com/lifestyle';
gender = '3,3';
}
... ... @@ -196,7 +196,7 @@ const detail = (req, res, next) => {
name: name
},
{
link: 'http://www.yohoblk.com/editorial',
link: '//www.yohoblk.com/editorial',
pathTitle: '资讯',
name: 'Editorial资讯'
},
... ...
... ... @@ -219,15 +219,19 @@ const _getRelatedData = (idList) => {
if (result && result.code === 200) {
_.forEach(result.data.product_list, function(data) {
productList.push({
name: data.product_name,
price: data.sales_price,
productId: data.product_id,
cnAlphabet: data.cn_alphabet,
productSkn: data.product_skn
});
if (data) {
productList.push({
name: data.product_name,
price: data.sales_price,
productId: data.product_id,
cnAlphabet: data.cn_alphabet,
productSkn: data.product_skn
});
}
});
return productList;
... ...
... ... @@ -9,13 +9,13 @@
<div class="article-info">
<div class="article-author">
<div class="author-avatar">
<a href="{{authorUrl}}" target="_blank">
<a href="{{https authorUrl}}" target="_blank">
<img class="lazy" data-original="{{avatar}}">
</a>
</div>
</div>
<div class="author-info">
<a class="author-name" href="{{authorUrl}}">{{name}}</a>
<a class="author-name" href="{{https authorUrl}}">{{name}}</a>
</div>
<div class="article-status">
<span class="article-time brown-light">{{time}}</span>
... ... @@ -105,7 +105,7 @@
<div class="brands">
{{# brands}}
<div class="brand">
<a class="thumb" href="{{url}}" target="_blank">
<a class="thumb" href="{{https url}}" target="_blank">
<img src="{{image thumb 100 100 2}}">
</a>
<p class="brand-name">{{name}}</p>
... ... @@ -144,7 +144,7 @@
<ul id="tags">
{{# tags}}
<li>
<a href="{{url}}" target="_blank">{{name}}</a>
<a href="{{https url}}" target="_blank">{{name}}</a>
</li>
{{/ tags}}
</ul>
... ... @@ -155,7 +155,7 @@
<p class="chapter-right">
<span>下一篇</span><br>
{{# nextArticle}}
<a href="{{href}}">{{nextChapter}}</a>
<a href="{{https href}}">{{nextChapter}}</a>
{{/ nextArticle}}
</p>
... ... @@ -163,7 +163,7 @@
<p class="chapter-left">
<span>上一篇</span><br>
{{# perArticle}}
<a href="{{href}}">{{lastChapter}}</a>
<a href="{{https href}}">{{lastChapter}}</a>
{{/ perArticle}}
</p>
... ...
<div class="good-info" data-skn="{{skn}}">
<a href="{{link}}" target="_blank">
<a href="{{https link}}" target="_blank">
<img class="thumb" src="{{image src 219 295}}">
</a>
<div class="desc">
<a class="name" href="{{link}}" target="_blank">{{name}}</a>
<a class="name" href="{{https link}}" target="_blank">{{name}}</a>
<p class="price">{{price}}</p>
</div>
</div>
\ No newline at end of file
</div>
... ...
... ... @@ -6,6 +6,7 @@
'use strict';
const mcHandler = require('../models/menu-crumb-handler');
const addressModel = require('../models/address');
const cleanHtml = require(`${global.utils}/cleanHtml`);
const crypto = global.yoho.crypto;
const config = global.yoho.config;
const logger = global.yoho.logger;
... ... @@ -35,6 +36,7 @@ const index = (req, res, next) => {
resultData[i].default = resultData[i].is_default === 'Y';
resultData[i].mobile = resultData[i].mobile.replace(reg, '$1****$2');
resultData[i].id = crypto.encryption(config.crypto.common, resultData[i].address_id + '');
resultData[i].address = cleanHtml.htmlDecode(resultData[i].address);
}
resultData.leftLength = 7 - length;
resultData.length = length;
... ... @@ -62,6 +64,7 @@ const getAddressList = (req, res, next) => {
_.each(result.data, (d) => {
d.address_id = crypto.encryption(config.crypto.common, d.address_id + '');
d.address = cleanHtml.htmlDecode(d.address);
});
defaultAd && (defaultAd.focus = true);
... ... @@ -75,7 +78,7 @@ const getAddressList = (req, res, next) => {
*/
const addAddressData = (req, res, next) => {
let uid = req.user.uid;
let address = req.body.address;
let address = cleanHtml.htmlEncode(req.body.address);
let areaCode = req.body.area_code;
let consignee = req.body.consignee;
let mobile = req.body.mobile;
... ... @@ -101,7 +104,7 @@ const updateAddressData = (req, res, next) => {
let id = crypto.decrypt(config.crypto.common, req.body.id);
let uid = req.user.uid;
let address = req.body.address;
let address = cleanHtml.htmlEncode(req.body.address);
let areaCode = req.body.area_code;
let consignee = req.body.consignee;
let mobile = req.body.mobile;
... ...
... ... @@ -27,7 +27,7 @@ const favorite = {
content: {
nav: mcHandler.getMeCrumb('我的收藏'),
navigation: mcHandler.getSideMenu('我的收藏'),
banner: 'http://placehold.it/150x120',
banner: '//placehold.it/150x120',
collection: true,
favorite: {
product: true,
... ... @@ -108,7 +108,7 @@ const favorite = {
content: {
nav: mcHandler.getMeCrumb('我的收藏'),
navigation: mcHandler.getSideMenu('我的收藏'),
banner: 'http://placehold.it/150x120',
banner: '//placehold.it/150x120',
collection: true,
favorite: {
brand: true,
... ... @@ -178,7 +178,7 @@ const favorite = {
content: {
nav: mcHandler.getMeCrumb('我的收藏'),
navigation: mcHandler.getSideMenu('我的收藏'),
banner: 'http://placehold.it/150x120',
banner: '//placehold.it/150x120',
collection: true,
favorite: {
editorial: true,
... ...
... ... @@ -8,6 +8,7 @@
const mcHandler = require('../models/menu-crumb-handler');
const orderModel = require('../models/order');
const cleanHtml = require(`${global.utils}/cleanHtml`);
const _ = require('lodash');
const crypto = global.yoho.crypto;
const config = global.yoho.config;
... ... @@ -48,6 +49,16 @@ const detail = (req, res, next) => {
pageData.orderDetail.orderCodeM = crypto.encryption(config.crypto.common, pageData.orderDetail.orderCode);
}
// 转译
if (pageData.orderDetail) {
pageData.orderDetail.address = cleanHtml.htmlDecode(pageData.orderDetail.address);
pageData.orderDetail.allAddress = cleanHtml.htmlDecode(pageData.orderDetail.allAddress);
pageData.orderDetail.remark = cleanHtml.htmlDecode(pageData.orderDetail.remark);
if (pageData.orderDetail.invoice) {
pageData.orderDetail.invoice.title = cleanHtml.htmlDecode(pageData.orderDetail.invoice.title);
}
}
res.display('index', {
isMe: true,
page: 'order-detail',
... ...
/**
* [个人中心]个人设置
* @author: jiangmin
* @date: 2016/07/13
*/
'use strict';
const mcHandler = require('../models/menu-crumb-handler');
const helpers = global.yoho.helpers;
const settingModel = require('../models/setting');
const accountModel = require('../models/account');
const passportHelper = require('../../passport/models/passport-helper');
const Promise = require('bluebird');
const co = Promise.coroutine;
var fs = require('fs');
var path = require('path');
const uuid = require('uuid');
const os = require('os');
const _ = require('lodash');
const regMobile = /(\d{3})\d{4}(\d{4})/;// 正则匹配替换手机号码中间4位
const regEmail = /(\d{3})\d{4}/;// 正则匹配替换邮箱中间4位
const captchaUrl = helpers.urlFormat('/passport/images', {t: Date.now()});
// 根据type获取标题
const _getTitle = (type)=> {
let typeName;
let proName;
let isModifyMobile = false;
let isBindMobile = false;
let isModifyEmail = false;
let isBindEmail = false;
let isShowPassword = false;
switch (type) {
case 'modifyPassword':
typeName = '修改密码';
proName = '输入新密码';
isShowPassword = true;
break;
case 'modifyMobile':
typeName = '修改手机号码';
proName = '绑定手机';
isModifyMobile = true;
break;
case 'bindMobile':
typeName = '绑定手机号码';
proName = '绑定手机';
isBindMobile = true;
break;
case 'modifyEmail':
typeName = '修改邮箱';
proName = '绑定邮箱';
isModifyEmail = true;
break;
case 'bindEmail':
typeName = '绑定邮箱';
proName = '绑定邮箱';
isBindEmail = true;
break;
default:
typeName = '';
break;
}
return {
typeName: typeName,
proName: proName,
isModifyMobile,
isBindMobile,
isModifyEmail,
isBindEmail,
isShowPassword
};
};
/**
* 个人设置页面加载
*/
const index = (req, res, next) => {
let uid = req.user.uid;
Promise.all([settingModel.getUserInfo(uid), mcHandler.getMeThumb()]).then(result => {
const thumb = result[1];
let user = result[0];
user.info.gender ? user.genders[user.info.gender - 1].checked = true :
user.genders[2].checked = true;
user.info.head_ico = user.info.head_ico ? helpers.image(user.info.head_ico, 400, 300, 2) : '';
user.info.mobile = user.info.mobile ? user.info.mobile.replace(regMobile, '$1****$2') : '';
user.stepUrl = '/me/setting/step1';
if (user.info.birthday) {
let a = user.info.birthday.split('-');
_.forEach(user.date.selectYear, function(x) {
if (x.value === a[0]) {
x.isSelected = 'selected';
}
});
_.forEach(user.date.selectMonth, function(x) {
if (parseInt(x.value, 10) === parseInt(a[1], 10)) {
x.isSelected = 'selected';
}
});
_.forEach(user.date.selectDay, function(x) {
if (parseInt(x.value, 10) === parseInt(a[2], 10)) {
x.isSelected = 'selected';
}
});
}
res.display('index', {
module: 'me',
page: 'setting',
isMe: true,
content: {
nav: mcHandler.getMeCrumb('个人设置'),
navigation: mcHandler.getSideMenu('个人设置'),
banner: thumb,
setting: true,
title: '个人设置',
userInfo: user,
_token: req.csrfToken()
}
});
}).catch(next);
};
/**
* 编辑信息
* @param req
* @param res
* @param next
*/
const editUserInfo = (req, res, next)=> {
let uid = req.user.uid;
let query = req.body;
settingModel.editUserInfo(uid, query).then(result=> {
res.send(result);
}).catch(next);
};
/*
* step1 绑定的手机号码身份验证
* */
const bindMobile = (req, res, next) => {
let uid = req.user.uid;
let type = req.params.type;
settingModel.getUserInfo(uid).then(result=> {
if (result.info.verify_mobile !== '') {
mcHandler.getMeThumb().then((thumb) => {
let info = result.info;
info.ellipsisMobile = info.verify_mobile.replace(regMobile, '$1****$2');
info.checkCode = settingModel.cipheriv(info.uid + '.completeverify');
res.display('index', {
module: 'me',
page: 'setting',
isMe: true,
content: {
region: passportHelper.getCountry(),
location: '+86',
nav: mcHandler.getMeCrumb('个人设置'),
navigation: mcHandler.getSideMenu('个人设置'),
banner: thumb,
validateStep: true,
title: _getTitle(type).typeName,
proTitle: _getTitle(type).proName,
captchaUrl: captchaUrl,
isShowMobile: true,
data: info
}
});
});
}
next();
});
};
/**
* step1 绑定的邮箱进行身份验证
*/
const bindEmail = (req, res, next) => {
let uid = req.user.uid;
let type = req.params.type;
settingModel.getUserInfo(uid).then(result=> {
if (result.info.verify_email !== '') {
let info = result.info;
info.ellipsisEmail = info.verify_email.replace(regEmail, '$1****');
info.checkCode = settingModel.cipheriv(info.uid + '.completeverify');
mcHandler.getMeThumb().then((thumb) => {
res.display('index', {
module: 'me',
page: 'setting',
isMe: true,
content: {
nav: mcHandler.getMeCrumb('个人设置'),
navigation: mcHandler.getSideMenu('个人设置'),
banner: thumb,
validateStep: true,
title: _getTitle(type).typeName,
proTitle: _getTitle(type).proName,
captchaUrl: captchaUrl,
isShowEmail: true,
data: info
}
});
});
}
next();
});
};
/**
*step1 登录密码进行身份验证
*/
const modifyPassword = (req, res) => {
let type = req.params.type;
let checkCode = settingModel.cipheriv(req.user.uid + '.completeverify');
mcHandler.getMeThumb().then((thumb) => {
res.display('index', {
module: 'me',
page: 'setting',
isMe: true,
content: {
nav: mcHandler.getMeCrumb('个人设置'),
navigation: mcHandler.getSideMenu('个人设置'),
banner: thumb,
validateStep: true,
title: _getTitle(type).typeName,
proTitle: _getTitle(type).proName,
captchaUrl: captchaUrl,
isShowPassword: true,
checkCode: checkCode
}
});
});
};
/*
* step2 操作界面-渲染页面
* */
const edit = (req, res)=> {
let type = req.params.type;
let code = settingModel.decipheriv(req.query.checkCode.split(' ').join('+'));
let codes = code.split('.');
if (parseInt(codes[0], 10) === req.user.uid && codes[1] === 'completeverify') {
let result = {
title: _getTitle(type).typeName,
proTitle: _getTitle(type).proName,
isShowMobile: _getTitle(type).isModifyMobile || _getTitle(type).isBindMobile,
isShowEmail: _getTitle(type).isModifyEmail || _getTitle(type).isBindEmail,
isShowPassword: _getTitle(type).isShowPassword
};
let checkCode = settingModel.cipheriv(req.user.uid + '.completeoperate');
mcHandler.getMeThumb().then((thumb) => {
res.display('index', {
module: 'me',
page: 'setting',
isMe: true,
content: Object.assign({
region: passportHelper.getCountry(),
location: '+86',
nav: mcHandler.getMeCrumb('个人设置'),
navigation: mcHandler.getSideMenu('个人设置'),
banner: thumb,
operateStep: true,
stepUrl: '/me/setting/step3/' + type,
captchaUrl: captchaUrl,
checkCode: checkCode
}, result)
});
});
}
};
/*
* step3 操作成功-渲染界面
* */
const success = (req, res)=> {
let type = req.params.type;
let code = settingModel.decipheriv(req.query.checkCode.split(' ').join('+'));
let codes = code.split('.');
if (parseInt(codes[0], 10) === req.user.uid && codes[1] === 'completeoperate') {
let result = {
title: _getTitle(type).typeName,
proTitle: _getTitle(type).proName,
isModifyMobile: _getTitle(type).isModifyMobile,
isBindMobile: _getTitle(type).isBindMobile,
isModifyEmail: _getTitle(type).isModifyEmail,
isBindEmail: _getTitle(type).isBindEmail,
isShowPassword: _getTitle(type).isShowPassword
};
mcHandler.getMeThumb().then((thumb) => {
res.display('index', {
module: 'me',
page: 'setting',
isMe: true,
content: Object.assign({
region: passportHelper.getCountry(),
location: '+86',
nav: mcHandler.getMeCrumb('个人设置'),
navigation: mcHandler.getSideMenu('个人设置'),
banner: thumb,
successStep: true,
captchaUrl: captchaUrl
}, result)
});
});
}
};
/*
* post1 第一步身份验证的post请求
* */
const validate1 = (req, res)=> {
co(function *() {
let type = req.params.type;
let uid = req.user.uid;
let body = req.body;
if (type === 'password') {
let a = yield accountModel.verifyPwd(uid, body.password);
res.send(a);
} else if (type === 'mobile') {
let a = yield accountModel.checkVerifyMsg(body.code, body.mobile, body.area);
res.send(a);
} else if (type === 'email') {
let a = yield accountModel.sendVerifyEmail(uid, body.email);
res.send(a);
}
})();
};
/*
* post2 第二步具体操作的post请求
* */
const validate2 = (req, res)=> {
co(function *() {
let type = req.params.type;
let uid = req.user.uid;
let body = req.body;
if (type === 'password') {
let a = yield accountModel.changePwd(uid, body.password);
res.send(a);
} else if (type === 'mobile') {
let a = yield accountModel.checkVerifyMsg(body.code, body.mobile, body.area);
let b = yield accountModel.modifyVerifyMobile(uid, body.area, body.mobile);
let msg = [];
if (a.code === 200 && b.code === 200) {
res.send({
code: 200,
data: {}
});
} else {
if (a.code !== 200) {
msg.push('<p>图片验证:' + a.message + '</p>');
}
if (b.code !== 200) {
msg.push('<p>修改号码:' + a.message + '</p>');
}
res.send({
code: 500,
message: msg.join('')
});
}
}
})();
};
/**
* 文件处理中间件
* @param req
* @param res
* @param next
*/
function getfilePath(req, res, next) {
const fid = uuid.v4();
const filePath = path.join(os.tmpdir(), fid);
const uploadStream = fs.createWriteStream(filePath);
req.filePath = filePath;
req.pipe(uploadStream);
uploadStream.on('finish', function() {
next();
});
}
/**
* 修改头像
* @param req
* @param res
*/
const modifyHead = (req, res)=> {
let uid = req.user.uid;
let bucket = 'yhb-head';
let filePath = req.filePath;
settingModel.modifyHead(uid, bucket, filePath).then(result=> {
res.send(result);
});
};
module.exports = {
index,
editUserInfo,
bindMobile,
bindEmail,
modifyPassword,
edit,
success,
validate1,
validate2,
getfilePath,
modifyHead
};
/**
* [个人中心]个人设置
* @author: jiangmin
* @date: 2016/07/13
*/
'use strict';
const mcHandler = require('../models/menu-crumb-handler');
const helpers = global.yoho.helpers;
const config = global.yoho.config;
const settingModel = require('../models/setting');
const accountModel = require('../models/account');
const passportHelper = require('../../passport/models/passport-helper');
const Promise = require('bluebird');
const co = Promise.coroutine;
var fs = require('fs');
var path = require('path');
const uuid = require('uuid');
const os = require('os');
const _ = require('lodash');
const regMobile = /(\d{3})\d{4}(\d{4})/; // 正则匹配替换手机号码中间4位
const regEmail = /(\d{3})\d{4}/; // 正则匹配替换邮箱中间4位
const captchaUrl = helpers.urlFormat('/passport/images', {
t: Date.now()
});
// 根据type获取标题
const _getTitle = (type) => {
let typeName;
let proName;
let isModifyMobile = false;
let isBindMobile = false;
let isModifyEmail = false;
let isBindEmail = false;
let isShowPassword = false;
switch (type) {
case 'modifyPassword':
typeName = '修改密码';
proName = '输入新密码';
isShowPassword = true;
break;
case 'modifyMobile':
typeName = '修改手机号码';
proName = '绑定手机';
isModifyMobile = true;
break;
case 'bindMobile':
typeName = '绑定手机号码';
proName = '绑定手机';
isBindMobile = true;
break;
case 'modifyEmail':
typeName = '修改邮箱';
proName = '绑定邮箱';
isModifyEmail = true;
break;
case 'bindEmail':
typeName = '绑定邮箱';
proName = '绑定邮箱';
isBindEmail = true;
break;
default:
typeName = '';
break;
}
return {
typeName: typeName,
proName: proName,
isModifyMobile,
isBindMobile,
isModifyEmail,
isBindEmail,
isShowPassword
};
};
const cookieHelper = {
setVal(res, k, v, ops) {
res.cookie(k, v, Object.assign({
domain: config.cookieDomain,
httpOnly: true
}, ops));
},
getVal(req, k) {
return req.cookies[k];
}
};
/**
* 个人设置页面加载
*/
const index = (req, res, next) => {
let uid = req.user.uid;
Promise.all([settingModel.getUserInfo(uid), mcHandler.getMeThumb()]).then(result => {
const thumb = result[1];
let user = result[0];
user.info.gender ? user.genders[user.info.gender - 1].checked = true :
user.genders[2].checked = true;
user.info.head_ico = user.info.head_ico ? helpers.image(user.info.head_ico, 400, 300, 2) : '';
user.info.mobile = user.info.mobile ? user.info.mobile.replace(regMobile, '$1****$2') : '';
user.stepUrl = '/me/setting/step1';
if (user.info.birthday) {
let a = user.info.birthday.split('-');
_.forEach(user.date.selectYear, function(x) {
if (x.value === a[0]) {
x.isSelected = 'selected';
}
});
_.forEach(user.date.selectMonth, function(x) {
if (parseInt(x.value, 10) === parseInt(a[1], 10)) {
x.isSelected = 'selected';
}
});
_.forEach(user.date.selectDay, function(x) {
if (parseInt(x.value, 10) === parseInt(a[2], 10)) {
x.isSelected = 'selected';
}
});
}
res.display('index', {
module: 'me',
page: 'setting',
isMe: true,
content: {
nav: mcHandler.getMeCrumb('个人设置'),
navigation: mcHandler.getSideMenu('个人设置'),
banner: thumb,
setting: true,
title: '个人设置',
userInfo: user,
_token: req.csrfToken()
}
});
}).catch(next);
};
/**
* 编辑信息
* @param req
* @param res
* @param next
*/
const editUserInfo = (req, res, next) => {
let uid = req.user.uid;
let query = req.body;
settingModel.editUserInfo(uid, query).then(result => {
res.send(result);
}).catch(next);
};
/*
* step1 绑定的手机号码身份验证
* */
const bindMobile = (req, res, next) => {
let uid = req.user.uid;
let type = req.params.type;
settingModel.getUserInfo(uid).then(result => {
if (result.info.verify_mobile !== '') {
mcHandler.getMeThumb().then((thumb) => {
let info = result.info;
info.ellipsisMobile = info.verify_mobile.replace(regMobile, '$1****$2');
info.checkCode = req.csrfToken();
res.display('index', {
module: 'me',
page: 'setting',
isMe: true,
content: {
region: passportHelper.getCountry(),
location: '+86',
nav: mcHandler.getMeCrumb('个人设置'),
navigation: mcHandler.getSideMenu('个人设置'),
banner: thumb,
validateStep: true,
title: _getTitle(type).typeName,
proTitle: _getTitle(type).proName,
captchaUrl: captchaUrl,
isShowMobile: true,
data: info
}
});
});
}
next();
});
};
/**
* step1 绑定的邮箱进行身份验证
*/
const bindEmail = (req, res, next) => {
let uid = req.user.uid;
let type = req.params.type;
settingModel.getUserInfo(uid).then(result => {
if (result.info.verify_email !== '') {
let info = result.info;
info.ellipsisEmail = info.verify_email.replace(regEmail, '$1****');
info.checkCode = req.csrfToken();
mcHandler.getMeThumb().then((thumb) => {
res.display('index', {
module: 'me',
page: 'setting',
isMe: true,
content: {
nav: mcHandler.getMeCrumb('个人设置'),
navigation: mcHandler.getSideMenu('个人设置'),
banner: thumb,
validateStep: true,
title: _getTitle(type).typeName,
proTitle: _getTitle(type).proName,
captchaUrl: captchaUrl,
isShowEmail: true,
data: info
}
});
});
}
next();
});
};
/**
*step1 登录密码进行身份验证
*/
const modifyType = (req, res) => {
let type = req.params.type;
mcHandler.getMeThumb().then((thumb) => {
res.display('index', {
module: 'me',
page: 'setting',
isMe: true,
content: {
nav: mcHandler.getMeCrumb('个人设置'),
navigation: mcHandler.getSideMenu('个人设置'),
banner: thumb,
validateStep: true,
title: _getTitle(type).typeName,
proTitle: _getTitle(type).proName,
captchaUrl: captchaUrl,
isShowPassword: true,
checkCode: req.csrfToken()
}
});
});
};
/*
* step2 操作界面-渲染页面
* */
const edit = (req, res) => {
let type = req.params.type;
if (Number(cookieHelper.getVal(req, type + '_STEP')) !== 1) {
res.redirect(helpers.urlFormat('/me/setting/step1/' + type));
return;
}
let result = {
title: _getTitle(type).typeName,
proTitle: _getTitle(type).proName,
isShowMobile: _getTitle(type).isModifyMobile || _getTitle(type).isBindMobile,
isShowEmail: _getTitle(type).isModifyEmail || _getTitle(type).isBindEmail,
isShowPassword: _getTitle(type).isShowPassword
};
mcHandler.getMeThumb().then((thumb) => {
res.display('index', {
module: 'me',
page: 'setting',
isMe: true,
content: Object.assign({
region: passportHelper.getCountry(),
location: '+86',
nav: mcHandler.getMeCrumb('个人设置'),
navigation: mcHandler.getSideMenu('个人设置'),
banner: thumb,
operateStep: true,
stepUrl: '/me/setting/step3/' + type,
captchaUrl: captchaUrl,
checkCode: req.csrfToken()
}, result)
});
});
};
/*
* step3 操作成功-渲染界面
* */
const success = (req, res) => {
let type = req.params.type;
let step = Number(cookieHelper.getVal(req, type + '_STEP')) || 0;
if (step !== 2) {
res.redirect(helpers.urlFormat('/me/setting/step' + (step + 1) + '/' + type));
return;
}
cookieHelper.setVal(res, type + '_STEP', 0, {
maxAge: -1
});
let result = {
title: _getTitle(type).typeName,
proTitle: _getTitle(type).proName,
isModifyMobile: _getTitle(type).isModifyMobile,
isBindMobile: _getTitle(type).isBindMobile,
isModifyEmail: _getTitle(type).isModifyEmail,
isBindEmail: _getTitle(type).isBindEmail,
isShowPassword: _getTitle(type).isShowPassword
};
mcHandler.getMeThumb().then((thumb) => {
res.display('index', {
module: 'me',
page: 'setting',
isMe: true,
content: Object.assign({
region: passportHelper.getCountry(),
location: '+86',
nav: mcHandler.getMeCrumb('个人设置'),
navigation: mcHandler.getSideMenu('个人设置'),
banner: thumb,
successStep: true,
captchaUrl: captchaUrl
}, result)
});
});
};
/*
* post1 第一步身份验证的post请求
* */
const validate1 = (req, res) => {
co(function*() {
let type = req.params.type;
let uid = req.user.uid;
let body = req.body;
let a;
if (type === 'password') {
a = yield accountModel.verifyPwd(uid, body.password);
} else if (type === 'mobile') {
a = yield accountModel.checkVerifyMsg(body.code, body.mobile, body.area);
} else if (type === 'email') {
a = yield accountModel.sendVerifyEmail(uid, body.email);
}
if (a) {
cookieHelper.setVal(res, req.body.type + '_STEP', 1);
res.send(a);
}
})();
};
/*
* post2 第二步具体操作的post请求
* */
const validate2 = (req, res) => {
co(function*() {
let type = req.params.type;
let uid = req.user.uid;
let body = req.body;
if (type === 'password') {
let a = yield accountModel.changePwd(uid, body.password);
if (a.code === 200) {
cookieHelper.setVal(res, body.type + '_STEP', 2);
res.send(a);
}
} else if (type === 'mobile') {
let a = yield accountModel.checkVerifyMsg(body.code, body.mobile, body.area);
let b = yield accountModel.modifyVerifyMobile(uid, body.area, body.mobile);
if (a.code === 200 && b.code === 200) {
cookieHelper.setVal(res, body.type + '_STEP', 2);
res.send({
code: 200,
data: {}
});
} else {
let msg = [];
if (a.code !== 200) {
msg.push('<p>图片验证:' + a.message + '</p>');
}
if (b.code !== 200) {
msg.push('<p>修改号码:' + a.message + '</p>');
}
res.send({
code: 500,
message: msg.join('')
});
}
}
})();
};
/**
* 文件处理中间件
* @param req
* @param res
* @param next
*/
function getfilePath(req, res, next) {
const fid = uuid.v4();
const filePath = path.join(os.tmpdir(), fid);
const uploadStream = fs.createWriteStream(filePath);
req.filePath = filePath;
req.pipe(uploadStream);
uploadStream.on('finish', function() {
next();
});
}
/**
* 修改头像
* @param req
* @param res
*/
const modifyHead = (req, res) => {
let uid = req.user.uid;
let bucket = 'yhb-head';
let filePath = req.filePath;
settingModel.modifyHead(uid, bucket, filePath).then(result => {
res.send(result);
});
};
module.exports = {
index,
editUserInfo,
bindMobile,
bindEmail,
modifyType,
edit,
success,
validate1,
validate2,
getfilePath,
modifyHead
};
... ...
... ... @@ -33,52 +33,39 @@ const paymentTypeStr = {
// 订单操作按钮
const btnMap = {
all: [
{
isPayBtn: true,
name: '立即付款',
classStr: 'btn red pay-btn mr'
},
{
name: '取消订单',
classStr: 'btn white cancel-btn mr'
},
{
isEditBtn: true,
name: '修改订单',
classStr: 'btn white edit-btn'
}
],
cancel: [
{
name: '取消订单',
classStr: 'btn white cancel-btn'
}
],
edit: [
{
isEditBtn: true,
name: '修改订单',
classStr: 'btn white edit-btn'
}
],
complete: [
{
name: '确认收货',
classStr: 'btn complete-btn'
}
],
special: [
{
isEditBtn: true,
name: '修改订单',
classStr: 'btn white edit-btn mr'
},
{
name: '取消订单',
classStr: 'btn white cancel-btn'
}
]
all: [{
isPayBtn: true,
name: '立即付款',
classStr: 'btn red pay-btn mr'
}, {
name: '取消订单',
classStr: 'btn white cancel-btn mr'
}, {
isEditBtn: true,
name: '修改订单',
classStr: 'btn white edit-btn'
}],
cancel: [{
name: '取消订单',
classStr: 'btn white cancel-btn'
}],
edit: [{
isEditBtn: true,
name: '修改订单',
classStr: 'btn white edit-btn'
}],
complete: [{
name: '确认收货',
classStr: 'btn complete-btn'
}],
special: [{
isEditBtn: true,
name: '修改订单',
classStr: 'btn white edit-btn mr'
}, {
name: '取消订单',
classStr: 'btn white cancel-btn'
}]
};
const invoiceText = {
... ... @@ -196,20 +183,15 @@ const _convertAddress = (addressList, createTime) => {
* @return { [Object] }
*/
const _getStepByOrderStatus = st => {
let steps = [
{
stepStr: '1.提交订单'
},
{
stepStr: '2.商品出库'
},
{
stepStr: '3.等待收货'
},
{
stepStr: '4.交易完成'
}
];
let steps = [{
stepStr: '1.提交订单'
}, {
stepStr: '2.商品出库'
}, {
stepStr: '3.等待收货'
}, {
stepStr: '4.交易完成'
}];
let curStep = statusMap[st].step;
for (let i = 0; i < curStep; i++) {
... ... @@ -415,24 +397,19 @@ const getExpressInfo = (uid, code) => {
*/
const getOrderData = (uid, type, page) => {
const navBar = {
tabs: [
{
text: '全部订单',
typeStr: 'all'
},
{
text: '待付款',
typeStr: 'paying'
},
{
text: '待发货',
typeStr: 'willdeliver'
},
{
text: '待收货',
typeStr: 'delivering'
}
]
tabs: [{
text: '全部订单',
typeStr: 'all'
}, {
text: '待付款',
typeStr: 'paying'
}, {
text: '待发货',
typeStr: 'willdeliver'
}, {
text: '待收货',
typeStr: 'delivering'
}]
};
const emptyObject = {
... ... @@ -493,7 +470,9 @@ const getOrderData = (uid, type, page) => {
} : false;
return {
order: Object.assign(order, paginationOpts, {orderData: empty})
order: Object.assign(order, paginationOpts, {
orderData: empty
})
};
});
};
... ... @@ -538,7 +517,6 @@ const getOrderDetail = (uid, code) => {
if (detail.isCancel !== 'Y') {
detail.steps = _getStepByOrderStatus(st);
console.log(st);
statusMap[st].btns.forEach(function(btn) {
btns.push(btn);
});
... ... @@ -561,7 +539,7 @@ const getOrderDetail = (uid, code) => {
if (parseInt(detail.paymentType, 10) === 2 &&
(statusMap[st].valueStr === '备货中' ||
detail.statusStr === '备货中')) {
detail.statusStr === '备货中')) {
detail.btns = btnMap.special;
} else {
detail.statusStr = statusMap[st].valueStr;
... ...
/**
* router of sub app me
* @author: xuqi<qi.xu@yoho.cn>
* @date: 2016/07/04
*/
'use strict';
/**
* router of sub app me
* @author: xuqi<qi.xu@yoho.cn>
* @date: 2016/07/04
*/
'use strict';
const router = require('express').Router(); // eslint-disable-line
const cRoot = './controllers';
const auth = require(`${global.middleware}/auth`);
const csurf = require('csurf');
const csrf = csurf();
// 订单
const order = require(`${cRoot}/order`);
const address = require(`${cRoot}/address`);
const currency = require(`${cRoot}/currency`);
const setting = require(`${cRoot}/setting`);
const account = require(`${cRoot}/account`);
const favorite = require(`${cRoot}/favorite`);
const returns = require(`${cRoot}/returns`);
// 个人中心首页/订单
router.get(['/', '/order'], auth, order.index);
router.get(['/', '/order/detail'], auth, order.detail);
router.get('/getOrderList', order.getOrderList);
router.get('/getOrderTotal', order.getOrderTotal);
router.get('/deleteOrder', order.deleteOrder);
router.get('/cancelOrder', order.cancelOrder);
router.get('/getCancelOrderReason', order.getCancelOrderReason);
router.get('/getExpressInfo', order.getExpressInfo);
router.get('/editOrder', order.editOrder);
router.get('/reAdd', order.reAdd);
router.get('/confirmReceive', order.confirmReceive);
// 退换货
router.get('/return', auth, returns.index);
router.get('/return/refund', auth, returns.refund);
router.get('/return/exchange', auth, returns.exchange);
router.get('/return/refund/detail', auth, returns.refundDetail);
router.get('/return/exchange/detail', auth, returns.exchangeDeatail);
router.post('/return/refund/apply', auth, returns.refundApply);
router.post('/return/cancel', auth, returns.cancelApply);
router.post('/return/setEepress', auth, returns.setEepress);
router.get('/return/getProductInfo', returns.getProductInfo);
router.get('/return/submitExchange', auth, returns.exchangeSubmit);
router.get('/return/unionInfo', returns.getUnion);
router.get('/return/getChangeType', returns.getChangeType);
// 个人中心首页/收货地址
router.get('/address', auth, address.index);
router.post('/address/add', auth, address.addAddressData);
router.post('/address/update', auth, address.updateAddressData);
router.post('/address/del', auth, address.delAddressData);
router.post('/address/default', auth, address.setDefaultAddress);
router.get('/address/list', address.getAddressList); // 获取地址列表
router.get('/address/areas/:areaId', address.getAddressData);
// 个人中心首页/有货币
router.get('/currency', auth, currency.index);
// 个人中心首页/个人设置
router.get('/setting', csrf, auth, setting.index);// 个人首页
router.post('/setting/editUserInfo', csrf, auth, setting.editUserInfo);// 修改接口
// 第一步
router.get('/setting/step1/:type', auth, setting.bindMobile, setting.bindEmail, setting.modifyPassword);
// 第一步post
router.post('/setting/step1/:type', auth, setting.validate1);
// 第二步
router.get('/setting/step2/:type', auth, setting.edit);
// 第二步post
router.post('/setting/step2/:type', auth, setting.validate2);
// 第三步
router.get('/setting/step3/:type', auth, setting.success);
router.post('/setting/modifyHead', auth, setting.getfilePath, setting.modifyHead);
router.post('/account/changePwd', auth, account.changePwd);
router.post('/account/sendMobileMsg', auth, account.sendMobileMsg);
router.post('/account/checkVerifyMsg', auth, account.checkVerifyMsg);
router.post('/account/sendVerifyEmail', auth, account.sendVerifyEmail);
router.post('/account/checkVerifyMobile', auth, account.checkVerifyMobile);
// 我的收藏
router.get('/collection', auth, favorite.goods);
router.get('/collection/brand', auth, favorite.brand);
router.get('/collection/editorial', auth, favorite.editorial);
router.post('/collection/cancel', auth, favorite.cancel);
router.post('/collection/cancel/multi', auth, favorite.cancelMulti);
router.post('/collection/editorial/cancel', auth, favorite.editorialCancel);
module.exports = router;
const cRoot = './controllers';
const auth = require(`${global.middleware}/auth`);
const csurf = require('csurf');
const csrf = csurf();
// 订单
const order = require(`${cRoot}/order`);
const address = require(`${cRoot}/address`);
const currency = require(`${cRoot}/currency`);
const setting = require(`${cRoot}/setting`);
const account = require(`${cRoot}/account`);
const favorite = require(`${cRoot}/favorite`);
const returns = require(`${cRoot}/returns`);
// 个人中心首页/订单
router.get(['/', '/order'], auth, order.index);
router.get(['/', '/order/detail'], auth, order.detail);
router.get('/getOrderList', order.getOrderList);
router.get('/getOrderTotal', order.getOrderTotal);
router.get('/deleteOrder', order.deleteOrder);
router.get('/cancelOrder', order.cancelOrder);
router.get('/getCancelOrderReason', order.getCancelOrderReason);
router.get('/getExpressInfo', order.getExpressInfo);
router.get('/editOrder', order.editOrder);
router.get('/reAdd', order.reAdd);
router.get('/confirmReceive', order.confirmReceive);
// 退换货
router.get('/return', auth, returns.index);
router.get('/return/refund', auth, returns.refund);
router.get('/return/exchange', auth, returns.exchange);
router.get('/return/refund/detail', auth, returns.refundDetail);
router.get('/return/exchange/detail', auth, returns.exchangeDeatail);
router.post('/return/refund/apply', auth, returns.refundApply);
router.post('/return/cancel', auth, returns.cancelApply);
router.post('/return/setEepress', auth, returns.setEepress);
router.get('/return/getProductInfo', returns.getProductInfo);
router.get('/return/submitExchange', auth, returns.exchangeSubmit);
router.get('/return/unionInfo', returns.getUnion);
router.get('/return/getChangeType', returns.getChangeType);
// 个人中心首页/收货地址
router.get('/address', auth, address.index);
router.post('/address/add', auth, address.addAddressData);
router.post('/address/update', auth, address.updateAddressData);
router.post('/address/del', auth, address.delAddressData);
router.post('/address/default', auth, address.setDefaultAddress);
router.get('/address/list', address.getAddressList); // 获取地址列表
router.get('/address/areas/:areaId', address.getAddressData);
// 个人中心首页/有货币
router.get('/currency', auth, currency.index);
// 个人中心首页/个人设置
router.get('/setting', csrf, auth, setting.index); // 个人首页
router.post('/setting/editUserInfo', csrf, auth, setting.editUserInfo); // 修改接口
// 第一步
router.get('/setting/step1/:type', csrf, auth, setting.bindMobile, setting.bindEmail, setting.modifyType);
// 第一步post
router.post('/setting/step1/:type', csrf, auth, setting.validate1);
// 第二步
router.get('/setting/step2/:type', csrf, auth, setting.edit);
// 第二步post
router.post('/setting/step2/:type', csrf, auth, setting.validate2);
// 第三步
router.get('/setting/step3/:type', auth, setting.success);
router.post('/setting/modifyHead', auth, setting.getfilePath, setting.modifyHead);
router.post('/account/changePwd', auth, account.changePwd);
router.post('/account/sendMobileMsg', auth, account.sendMobileMsg);
router.post('/account/checkVerifyMsg', auth, account.checkVerifyMsg);
router.post('/account/sendVerifyEmail', auth, account.sendVerifyEmail);
router.post('/account/checkVerifyMobile', auth, account.checkVerifyMobile);
// 我的收藏
router.get('/collection', auth, favorite.goods);
router.get('/collection/brand', auth, favorite.brand);
router.get('/collection/editorial', auth, favorite.editorial);
router.post('/collection/cancel', auth, favorite.cancel);
router.post('/collection/cancel/multi', auth, favorite.cancelMulti);
router.post('/collection/editorial/cancel', auth, favorite.editorialCancel);
module.exports = router;
... ...
... ... @@ -10,13 +10,13 @@
<ul class="nav">
{{#each navigation}}
<li class="nav-row{{#if focus}} focus{{/if}}">
<a href="{{link}}">{{name}}</a>
<a href="{{https link}}">{{name}}</a>
</li>
{{/each}}
</ul>
{{#banner}}
{{#if banner}}
<a href="{{url}}" target="_blank">
<a href="{{https url}}" target="_blank">
<img class="banner-img" data-original="{{image banner 150 120}}">
</a>
{{/if}}
... ...
... ... @@ -26,15 +26,15 @@
{{/stateText}}
</div>
<div class="desc">
<div class="brand-name"><a href="{{url}}" target="_blank">{{brandName}}</a></div>
<div class="product-name"><a href="{{url}}" target="_blank">{{productName}}</a></div>
<div class="brand-name"><a href="{{https url}}" target="_blank">{{brandName}}</a></div>
<div class="product-name"><a href="{{https url}}" target="_blank">{{productName}}</a></div>
<p class="price">¥{{round salesPrice 2}}</p>
</div>
<div class="tool-area clearfix">
{{#if hideBtn}}
{{^}}
<a class="btn white" href="{{url}}" target="_blank">立即购买</a>
<a class="btn white" href="{{https url}}" target="_blank">立即购买</a>
{{/if}}
<span class="btn white cancel">取消收藏</span>
</div>
... ... @@ -58,7 +58,7 @@
</div>
{{^}}
<div class="favorite-empty">
<p>您还没有收藏的商品, 去<a href="{{siteUrl}}">首页</a>看看吧</p>
<p>您还没有收藏的商品, 去<a href="{{https siteUrl}}">首页</a>看看吧</p>
</div>
{{/if}}
{{/data}}
... ...
... ... @@ -56,7 +56,7 @@
{{#if auditSuccess}}
<div class="order">
<a href="{{view}}" target="_blank"><span class="check">查看</span></a>
<a href="{{https view}}" target="_blank"><span class="check">查看</span></a>
<span class="exchange-order">换货订单</span>
</div>
{{/if}}
... ... @@ -115,9 +115,9 @@
<p class="address-title">收货地址</p>
<div class="address-detail">
<p>所在区域:{{city}}{{county}}</p>
<p>&nbsp货 &nbsp人:{{consigneeName}}</p>
<p>详细地址:{{address}}</p>
<p>联系电话:{{mobile}}</p>
<p>&nbsp货 &nbsp人:{{consigneeName}}</p>
<p>详细地址:{{address}}</p>
<p>联系电话:{{mobile}}</p>
</div>
</div>
{{/if}}
... ...
... ... @@ -7,7 +7,7 @@
{{# btns}}
<li>
{{#if isPayBtn}}
<a href="{{payUrl}}" target="_blank">
<a href="{{https payUrl}}" target="_blank">
<span class="{{classStr}}">{{name}}</span>
</a>
{{^}}
... ...
<div class="good-info {{#if @last}}last{{/if}}">
<a href="{{goodUrl}}" target="_blank">
<a href="{{https goodUrl}}" target="_blank">
<img src="{{image goodsImage 65 90}}">
</a>
<div class="detail">
<a href="{{goodUrl}}" target="_blank">
<a href="{{https goodUrl}}" target="_blank">
<p class="with-bottom-space good-name-text">{{productName}}</p>
</a>
<span class="with-space">颜色:{{colorName}}</span>
... ...
... ... @@ -6,7 +6,7 @@
<p class="{{#if @last}}last{{/if}}">
¥{{goodsPrice}}
{{#if changed}}
<a href="{{returnUrl}}">
<a href="{{https returnUrl}}">
<span class="btn white change-tag">已退换</span>
</a>
{{/if}}
... ...
... ... @@ -14,7 +14,7 @@
</div>
<div class="common-column special-border status">
<p class="bold status-str">{{statusStr}}</p>
<a href="{{detailUrl}}" target="_blank">
<a href="{{https detailUrl}}" target="_blank">
<p class="subtext check-detail">查看详情</p>
</a>
</div>
... ... @@ -25,7 +25,7 @@
{{#if showLeftTime}}
<span class="iconfont hide-when-invalid">&#xe606;</span><p class="left-time" data-left="{{payLefttime}}"></p>
{{/if}}
<a href="{{payUrl}}">
<a href="{{https payUrl}}">
<span class="btn red hide-when-invalid ">立即付款</span>
</a>
{{/if}}
... ... @@ -33,10 +33,10 @@
</div>
{{/if}}
{{#if showEditOption}}
<a href="{{refundUrl}}" class="{{#if hideChange}}disable{{/if}}">
<a href="{{https refundUrl}}" class="{{#if hideChange}}disable{{/if}}">
<p class="subtext">申请退货</p>
</a>
<a href="{{exchangeUrl}}" class="{{#if hideChange}}disable{{/if}}">
<a href="{{https exchangeUrl}}" class="{{#if hideChange}}disable{{/if}}">
<p class="subtext">申请换货</p>
</a>
<p class="subtext delete">删除订单</p>
... ... @@ -66,7 +66,7 @@
{{#if showEmptyEn}}
<p class="msg-en">You do not have an order for the time being</p>
{{/if}}
<a href="{{url}}">
<a href="{{https url}}">
<span class="btn">{{btnText}}</span>
</a>
</div>
... ...
... ... @@ -140,7 +140,7 @@
<dd>
<label>照片凭证:</label>
{{# evidence}}
<a href="{{this}}" class="evidence-img" target="_blank">
<a href="{{https this}}" class="evidence-img" target="_blank">
<img class="lazy" data-original="{{this}}">
</a>
{{/ evidence}}
... ... @@ -152,4 +152,4 @@
{{/ goods}}
</div>
</div>
{{/ refundDetail}}
\ No newline at end of file
{{/ refundDetail}}
... ...
... ... @@ -17,12 +17,12 @@
<div class="goods-item clearfix">
<div class="check" data-skn="{{skn}}" data-skc="{{skc}}" data-sku="{{sku}}" data-price="{{price}}" data-type="{{typeId}}">{{> icon/checkbox}}</div>
<div class="img">
<a href="{{href}}" title="{{name}}" target="_blank">
<a href="{{https href}}" title="{{name}}" target="_blank">
<img class="lazy" data-original="{{image img 70 90}}">
</a>
</div>
<div class="info">
<p><a href="{{href}}" class="title" title="{{name}}" target="_blank">{{name}}</a></p>
<p><a href="{{https href}}" class="title" title="{{name}}" target="_blank">{{name}}</a></p>
<p>颜色:{{color}}&nbsp;尺码:{{size}}</p>
<p>×{{num}}</p>
</div>
... ...
... ... @@ -25,7 +25,7 @@
<p class="subtext cancel-apply" data-type="{{type}}" data-apply-id="{{id}}">取消申请</p>
{{/ ../this}}
{{/isY}}
<a href="{{detailUrl}}" target="_blank">
<a href="{{https detailUrl}}" target="_blank">
<p class="subtext check-detail">查看详情</p>
</a>
</div>
... ...
... ... @@ -39,7 +39,7 @@ const index = (req, res) => {
queryParams: req.query
},
goods: {
img: 'http://placehold.it/274x366',
img: '//placehold.it/274x366',
link: '',
name: 'Fred Perry Bomber jacket',
price: '1015.00'
... ...
... ... @@ -20,7 +20,7 @@ const Sources = {
wechat: '微信'
};
const DEFAULT_URL = 'http://img10.static.yhbimg.com/headimg/2013/11/28/09/01cae078abe5fe320c88cdf4c220212688.gif?imageView/2/w/100/h/100';
const DEFAULT_URL = '//img10.static.yhbimg.com/headimg/2013/11/28/09/01cae078abe5fe320c88cdf4c220212688.gif?imageView/2/w/100/h/100';
/**
* 首页
... ...
... ... @@ -19,6 +19,7 @@ const config = global.yoho.config;
const cache = global.yoho.cache;
const LoginService = require('../models/login-service');
const PassportHelper = require('../models/passport-helper');
const safeRedirect = require('../../../doraemon/middleware/safe-redirect').safeRedirect;
const loginPageURL = `${config.siteUrl}/passport/login`;
const BlockRedirectFilter = /sign|login|passport/;
... ... @@ -74,7 +75,8 @@ const common = {
refer = req.get('Referer');
}
refer && res.cookie('refer', encodeURI(refer), {
domain: config.cookieDomain
domain: config.cookieDomain,
httpOnly: true
});
next();
},
... ... @@ -84,7 +86,11 @@ const common = {
*/
needCaptcha: (req, res, next) => {
let account = req.query.account;
let result = {code: 400, message: '', data: ''};
let result = {
code: 400,
message: '',
data: ''
};
const MAX_ALLOW_ERROR_LOGIN = 3;
if (account) {
... ... @@ -93,7 +99,9 @@ const common = {
cache.get(errorLoginKey).then(errloginTimes => {
errloginTimes = parseInt(errloginTimes, 0) || 0;
if (!isNaN(errloginTimes) && errloginTimes >= MAX_ALLOW_ERROR_LOGIN) {
result.data = {needCaptcha: true};
result.data = {
needCaptcha: true
};
}
res.json(result);
}).catch(next);
... ... @@ -110,7 +118,8 @@ const local = {
loginPage: (req, res) => {
// 设置登录有效时间30分钟, 防机器刷,cache不稳定,改为cookie
res.cookie('LE' + md5('_LOGIN_EXPIRE'), (new Date()).getTime() / 1000 + 1800, {
domain: config.cookieDomain
domain: config.cookieDomain,
httpOnly: true
});
let loginMobile = _.trim(req.query.bindMobile || '');
... ... @@ -131,8 +140,12 @@ const local = {
defaultHeader: false,
passport: {
countryCode: loginCountryCode,
countryName: {text: defaultCountryName},
country: {list: countries},
countryName: {
text: defaultCountryName
},
country: {
list: countries
},
forgetPwd: helpers.urlFormat('/passport/back/index'),
fastReg: helpers.urlFormat('/passport/reg'),
weixinLogin: helpers.urlFormat('/passport/autosign/wechat'),
... ... @@ -158,7 +171,7 @@ const local = {
});
} else {
// 同步用户数据
co(function * () {
co(function*() {
let isRemember = req.body.isRemember === 'true';
let refer = req.cookies.refer;
... ... @@ -176,7 +189,7 @@ const local = {
res.json({
code: 200,
data: {
refer: refer
refer: safeRedirect(refer)
}
});
});
... ...
... ... @@ -9,6 +9,7 @@ const RegService = require('../models/reg-service');
const UserService = require('../models/user-service');
const LoginService = require('../models/login-service');
const config = require('../../../config/common');
const safeRedirect = require('../../../doraemon/middleware/safe-redirect').safeRedirect;
let helpers = global.yoho.helpers;
let cache = global.yoho.cache;
... ... @@ -55,20 +56,31 @@ let index = (req, res) => {
let refer = req.query.refer;
refer && res.cookie('refer', encodeURI(refer), {
domain: config.cookieDomain
domain: config.cookieDomain,
httpOnly: true
});
res.display('reg/index', {
title: '新用户注册',
defaultHeader: false,
passport: {
country: {list: passportHelper.getCountry()},
country: {
list: passportHelper.getCountry()
},
location: '+86',
countryName: {text: '中国'},
captchaUrl: helpers.urlFormat('/passport/images', {t: Date.now()}),
itemUrl: helpers.urlFormat('/help', {id: 5}),
countryName: {
text: '中国'
},
captchaUrl: helpers.urlFormat('/passport/images', {
t: Date.now()
}),
itemUrl: helpers.urlFormat('/help', {
id: 5
}),
referUrl: refer,
loginUrl: helpers.urlFormat('/passport/login', {refer: refer}),
loginUrl: helpers.urlFormat('/passport/login', {
refer: refer
}),
regBtnText: '立即注册'
}
});
... ... @@ -252,10 +264,10 @@ let mobileRegister = (req, res, next) => {
code: 200,
message: '注册成功',
data: {
href: helpers.urlFormat('/passport/reg/success', {
href: safeRedirect(helpers.urlFormat('/passport/reg/success', {
next: cookie.getRefer(req, '/?go=1'),
goShoppingUrl: config.siteUrl
})
}))
}
});
});
... ... @@ -274,8 +286,8 @@ let success = (req, res) => {
defaultHeader: false,
title: '注册成功',
passport: {
goUrl: goUrl,
goShopping: goShoppingUrl,
goUrl: safeRedirect(goUrl),
goShopping: safeRedirect(goShoppingUrl),
mobile: mobile
}
});
... ...
... ... @@ -5,7 +5,7 @@
'use strict';
const api = global.yoho.API;
const YOHOBUY_URL = 'http://www.yohobuy.com/';
const YOHOBUY_URL = '//www.yohobuy.com/';
/**
* 获取地区数据
... ...
... ... @@ -46,18 +46,21 @@ const syncUserSession = (uid, req, res) => {
req.session._USERNAME = name;
res.cookie('_UID', uidCookie, {
domain: config.cookieDomain
domain: config.cookieDomain,
httpOnly: true
});
res.cookie('_USERNAME', name, {
domain: config.cookieDomain
domain: config.cookieDomain,
httpOnly: true
});
}
req.session._TOKEN = token; // esline-disable-line
req.session._LOGIN_UID = uid; // esline-disable-line
res.cookie('_TOKEN', token, {
domain: config.cookieDomain
domain: config.cookieDomain,
httpOnly: true
}); // esline-disable-line
});
... ... @@ -72,11 +75,13 @@ const rememberAccountAsync = (accountInfo, req, res) => {
res.cookie('isRemember', true, {
maxAge: aWeek,
domain: config.cookieDomain
domain: config.cookieDomain,
httpOnly: true
});
res.cookie('remem', rememKey, {
maxAge: aWeek,
domain: config.cookieDomain
domain: config.cookieDomain,
httpOnly: true
});
return cache.set(rememKey, accountInfo);
... ...
... ... @@ -6,7 +6,7 @@
const api = require('./user-api');
const helpers = global.yoho.helpers;
const DEFAULT_HEAD_IMG_ICO = 'http://img10.static.yhbimg.com/headimg/2013/11/28/09/01cae078abe5fe320c88cdf4c220212688.gif?imageView/2/w/100/h/100';
const DEFAULT_HEAD_IMG_ICO = '//img10.static.yhbimg.com/headimg/2013/11/28/09/01cae078abe5fe320c88cdf4c220212688.gif?imageView/2/w/100/h/100';
/**
* 第三方登录 根据手机号获取用户相关信息
... ...
... ... @@ -59,7 +59,7 @@
<li class="clearfix">
<div>
<a class="btn to-my-email" href="{{email}}" target="_blank" class="btn_b_ar_r">去我的邮箱</a>
<a class="btn to-my-email" href="{{https email}}" target="_blank" class="btn_b_ar_r">去我的邮箱</a>
</div>
</li>
</ul>
... ...
... ... @@ -9,7 +9,7 @@
<img id="avatar" class="avatar" src="{{avatar}}">
{{^}}
<img id="avatar" class="avatar"
src="http://img10.static.yhbimg.com/headimg/2013/11/28/09/01cae078abe5fe320c88cdf4c220212688.gif?imageView/2/w/100/h/100">
src="//img10.static.yhbimg.com/headimg/2013/11/28/09/01cae078abe5fe320c88cdf4c220212688.gif?imageView/2/w/100/h/100">
{{/if}}
</div>
</li>
... ... @@ -44,8 +44,8 @@
<li>
<div class="quick-link">
<a class="blue left" href="{{bindUrl}}">绑定其他手机号</a>
<a class="blue right" href="{{loginUrl}}">使用手机号登录</a>
<a class="blue left" href="{{https bindUrl}}">绑定其他手机号</a>
<a class="blue right" href="{{https loginUrl}}">使用手机号登录</a>
</div>
</li>
</ul>
... ...
... ... @@ -9,7 +9,7 @@
<img id="avatar" class="avatar" src="{{avatar}}">
{{^}}
<img id="avatar" class="avatar"
src="http://img10.static.yhbimg.com/headimg/2013/11/28/09/01cae078abe5fe320c88cdf4c220212688.gif?imageView/2/w/100/h/100">
src="//img10.static.yhbimg.com/headimg/2013/11/28/09/01cae078abe5fe320c88cdf4c220212688.gif?imageView/2/w/100/h/100">
{{/if}}
</div>
</li>
... ... @@ -38,16 +38,16 @@
<li>
<div>
<a id="next" class="btn btn-fixed-height" href="{{bindUrl}}">绑定其他手机号</a>
<a id="next" class="btn btn-fixed-height" href="{{https bindUrl}}">绑定其他手机号</a>
</div>
</li>
<li>
<div class="quick-link center">
<a class="blue" href="{{loginUrl}}">使用手机号登录</a>
<a class="blue" href="{{https loginUrl}}">使用手机号登录</a>
</div>
</li>
</ul>
</div>
</div>
\ No newline at end of file
</div>
... ...
... ... @@ -17,10 +17,10 @@
<li>
<div>
<a class="btn btn-fixed-height" href="{{goShopping}}">开始购物</a>
<a class="btn btn-fixed-height" href="{{xssURI goShopping}}">开始购物</a>
</div>
</li>
</ul>
</div>
</div>
\ No newline at end of file
</div>
... ...
... ... @@ -5,7 +5,7 @@
<li class="clearfix big-width">
<div id="avatar" class="center">
<img class="avatar"
src="http://img10.static.yhbimg.com/headimg/2013/11/28/09/01cae078abe5fe320c88cdf4c220212688.gif?imageView/2/w/100/h/100">
src="//img10.static.yhbimg.com/headimg/2013/11/28/09/01cae078abe5fe320c88cdf4c220212688.gif?imageView/2/w/100/h/100">
</div>
</li>
<li>
... ... @@ -20,7 +20,7 @@
<li class="clearfix">
<div id="confirmInfo" class="confirmInfo">
<div class="desc center">手机号{{mobile}}已经被以上用户注册,点击<a class="blue underline" href="{{signinUrl}}">登录该帐号</a>
<div class="desc center">手机号{{mobile}}已经被以上用户注册,点击<a class="blue underline" href="{{https signinUrl}}">登录该帐号</a>
</div>
<div class="desc"></div>
<div class="desc center">您可以使用此号码进行帐户关联或者更换一个新的手机号码</div>
... ... @@ -34,7 +34,7 @@
<li>
<div class="quick-btn">
<a id="relate-btn" class="btn btn-fixed-height left">关联此手机号</a>
<a class="btn btn-fixed-height right" href="{{relateUrl}}" >更换新手机号</a>
<a class="btn btn-fixed-height right" href="{{https relateUrl}}" >更换新手机号</a>
</div>
</li>
... ... @@ -51,4 +51,4 @@
<input id="area" type="hidden" value="{{area}}">
<input id="sourceType" type="hidden" value="{{sourceType}}">
<input id="openId" type="hidden" value="{{openId}}">
</div>
\ No newline at end of file
</div>
... ...
... ... @@ -16,9 +16,9 @@
<li>
<div>
<a class="btn btn-fixed-height" href="{{goShopping}}">开始购物</a>
<a class="btn btn-fixed-height" href="{{xssURI goShopping}}">开始购物</a>
</div>
</li>
</ul>
</div>
</div>
\ No newline at end of file
</div>
... ...
... ... @@ -62,22 +62,22 @@
</span>
<span class="right">
<a class="blue forget-password" href="{{forgetPwd}}">忘记密码</a>
<a class="blue forget-password" href="{{https forgetPwd}}">忘记密码</a>
</span>
</li>
<li class="clearfix third-party-login">
<a href="{{weixinLogin}}">
<a href="{{https weixinLogin}}">
<span class="iconfont weixin">&#xe642;</span>
</a>
<a href="{{qqLogin}}">
<a href="{{https qqLogin}}">
<span class="iconfont qq">&#xe641;</span>
</a>
<a href="{{weiboLogin}}">
<a href="{{https weiboLogin}}">
<span class="iconfont weibo">&#xe640;</span>
</a>
<a href="{{alipayLogin}}">
<a href="{{https alipayLogin}}">
<span class="iconfont alipay">&#xe63f;</span>
</a>
</li>
... ... @@ -88,7 +88,7 @@
</span>
<span>
<a class="blue" href="{{fastReg}}">快速注册</a>
<a class="blue" href="{{https fastReg}}">快速注册</a>
</span>
</li>
</ul>
... ...
... ... @@ -73,7 +73,7 @@
我已阅读并同意遵守
</span>
<span class="right">
<a class="blue go-yoho-items" href="{{itemUrl}}" target="_blank">YOHO!有货服务条款</a>
<a class="blue go-yoho-items" href="{{https itemUrl}}" target="_blank">YOHO!有货服务条款</a>
</span>
</li>
<li class="clearfix">
... ... @@ -86,7 +86,7 @@
<li class="clearfix quick-login-container">
<div style="width: 100%;text-align: center">
已注册YOHO!BLK账号
<a class="blue go-login" href="{{loginUrl}}">快速登录</a>
<a class="blue go-login" href="{{https loginUrl}}">快速登录</a>
</div>
</li>
</ul>
... ...
... ... @@ -21,6 +21,7 @@ const Query = {
q.page = parseInt(q.page || 1, 10);
q.order = q.order || 's_n_desc';
q.yh_channel = channel;
let retData = {
module: 'product',
... ... @@ -46,7 +47,7 @@ const Query = {
retData.filter = DataHelper.filterHandle(data.filter, q);
retData.filter.showPrice = data.total > 10;
retData.filter.showInfo = (retData.filter.style && retData.filter.style.length > 0)
|| (data.standard && data.standard.length > 0); //eslint-disable-line
|| (data.standard && data.standard.length > 0); //eslint-disable-line
retData.filter.useSmallSort = 1;
}
... ...
... ... @@ -18,8 +18,8 @@ const SingleAPI = global.yoho.SingleAPI;
*/
const getProductBaseAsync = (productId, uid, skn) => {
let params = {
method: 'h5.product.data',
productId: productId
method: 'app.product.data',
product_id: productId
};
if (uid) {
... ...
... ... @@ -255,12 +255,12 @@ const setBrandBanner = (base, brand, shop) => {
let resData = {},
banner = {};
if (base.brand) {
let info = base.brand;
if (base.brandInfo) {
let info = base.brandInfo;
// 基础品牌数据
banner = {
brandId: info.id,
brandId: info.brandId,
bgColor: '#000',
brandLogo: {
link: `/product/shop/${info.brandDomain}`, // 品牌跳转链接
... ... @@ -319,12 +319,12 @@ const setBrandBanner = (base, brand, shop) => {
*/
const setProductData = base => {
let resData = {
id: base.id,
id: base.productId,
name: base.productName,
brandName: _.has(base, 'brand.brandName') ? base.brand.brandName : '',
brandName: _.has(base, 'brandInfo.brandName') ? base.brandInfo.brandName : '',
intro: base.salesPhrase,
sellPrice: base.productPriceBo.salesPrice,
marketPrice: base.productPriceBo.marketPrice,
sellPrice: base.salesPrice,
marketPrice: base.marketPrice,
total: 0
};
... ... @@ -350,7 +350,7 @@ const setProductData = base => {
return;
}
if (value.goodsImagesList) {
if (value.imagesList) {
group = {
name: value.colorName,
title: `${resData.name} ${value.colorName}`,
... ... @@ -361,7 +361,7 @@ const setProductData = base => {
// 有颜色图片时显示颜色图片,无颜色图片时显示rgb值
// 都没有则显示商品图
if (value.colorValue) {
group.bgImg = value.colorValue;
group.bgImg = helpers.image(value.colorValue, 30, 30);
} else if (value.colorCode) {
group.rgb = `#${value.colorCode}`;
} else {
... ... @@ -369,7 +369,7 @@ const setProductData = base => {
}
// 商品颜色列表
_.forEach(value.goodsImagesList, function(subValue) {
_.forEach(value.imagesList, function(subValue) {
thumbs.push(subValue.imageUrl);
});
group.thumbs = thumbs;
... ... @@ -390,22 +390,22 @@ const setProductData = base => {
}
// 商品尺码列表
_.forEach(value.goodsSizeBoList, function(subValue) {
_.forEach(value.sizeList, function(subValue) {
let size = {
name: subValue.sizeName,
title: subValue.sizeName,
sku: subValue.goodsSizeSkuId,
num: _.toInteger(subValue.goodsSizeStorageNum),
goodsId: subValue.goodsId
sku: subValue.productSku,
num: _.toInteger(subValue.storageNumber),
goodsId: value.goodsId
};
// 虚拟商品,增加为一件
if (subValue.attribute === 3) {
if (base.attribute === 3) {
size.num = size.num > 1 ? 1 : 0;
}
// 如果status为0,即skc下架时,则库存设为0
if (subValue.status === 0) {
if (base.status === 0 || subValue.status === 0) {
size.num = 0;
}
... ... @@ -439,7 +439,7 @@ const setProductData = base => {
}
// 限购商品
if (base.isLimitBuy === 'Y') {
if (base.isLimitBuy === true) {
let isBeginSale = (base.saleStatus && +base.saleStatus) === 1; // 是否开售
let showStatus = 1; // 限购商品有关的展示状态
... ...
... ... @@ -10,9 +10,8 @@ const itemApi = require('./item-api');
const brandApi = require('./brand-api');
const shopApi = require('./shop-api');
const itemFun = require('./item-handler');
const search = require('./search-api');
const camelCase = global.yoho.camelCase;
/**
* 根据商品基本信息获取商品品牌、材质、尺码、描述、详情等
... ... @@ -21,10 +20,10 @@ const search = require('./search-api');
* @return { Object } 返回单个商品品牌、材质、尺码、描述、详情等信息
*/
const _getMultiResourceByBaseInfo = (base) => {
const productId = base.id;
const skn = base.erpProductId;
const brandId = base.brandId || 0;
const brandDomain = _.get(base, 'brand.brandDomain', false);
const productId = base.productId;
const skn = base.productSkn;
const brandId = base.brandInfo.brandId || 0;
const brandDomain = _.get(base, 'brandInfo.brandName', false);
const shopId = base.shopId || 0;
let apiIndex = {};
... ... @@ -57,6 +56,7 @@ const _getMultiResourceByBaseInfo = (base) => {
}
return Promise.all(promiseData).then(result => {
return {
sizeInfo: result[0],
comfort: result[1].data,
... ... @@ -91,14 +91,22 @@ const getProductItemData = (params, url, uid) => {
let resData = {};
let data = {};
// 如果status为0,即商品下架时则返回空对象
if (!result.status) {
return resData;
result = camelCase(result.data);
if (!result) {
return;
}
// 如果status为0,即商品下架时则返回空对象
// if (!result.status) {
// return resData;
// }
if (!result.productName &&
!result.erpProductId &&
!result.productPriceBo) {
!result.productSkn &&
!result.salesPrice &&
!result.marketPrice
) {
return resData;
}
... ... @@ -109,12 +117,11 @@ const getProductItemData = (params, url, uid) => {
data.goodInfo = itemFun.setProductData(result);
// BRAND品牌简介
if (result.brand) {
Object.assign(data, itemFun.setBrandIntro(result.brand));
if (result.brandInfo) {
Object.assign(data, itemFun.setBrandIntro(result.brandInfo));
}
return _getMultiResourceByBaseInfo(result).then(mulRes => {
Object.assign(data,
itemFun.setBrandBanner(result, mulRes.brandBanner, mulRes.shopInfo), // banner
itemFun.setPathNav(mulRes.sort, result.productName, params.channel), // 面包屑导航
... ...
... ... @@ -37,18 +37,19 @@ function _paramHanlde(obj) {
// let _gender;
//
// if (obj.yh_channel) {
// switch (obj.yh_channel) {
// case 'men':
// _gender = '1,3';
// break;
// case 'women':
// _gender = '2,3';
// break;
// default:
// break;
// }
// }
if (obj.yh_channel) {
switch (obj.yh_channel) {
case 'men':
obj.yh_channel = '301';
break;
case 'women':
obj.yh_channel = '302';
break;
default:
obj.yh_channel = '303';
break;
}
}
// if (obj.gender || _gender) {
// obj.gender = obj.gender || _gender;
... ...
... ... @@ -19,7 +19,7 @@
{{#if banner.src}}
<div class="banner-img"
style="height: 200px;margin-bottom:30px;">
<a href="{{banner.url}}" target="_blank">
<a href="{{https banner.url}}" target="_blank">
<img src="{{image banner.src 850 200 1}}" alt="{{banner.alt}}" width="850" height="200">
</a>
</div>
... ...
... ... @@ -16,14 +16,14 @@
<div class="center-content clearfix slide-warp">
{{#each largeSlideImg}}
<div class="slide-left">
<a href="{{url}}">
<a href="{{https url}}">
<img src="{{src}}" alt="">
</a>
</div>
{{/each}}
<div class="slide-right">
{{#each oneRowTwoColImages}}
<a href="{{url}}">
<a href="{{https url}}">
<img src="{{src}}" alt="">
</a>
{{/each}}
... ... @@ -92,11 +92,11 @@
<div class="goods-wrap">
{{#each products}}
<div class="goods-info" data-skn="{{productSkn}}">
<a href="{{url}}" target="_blank">
<a href="{{https url}}" target="_blank">
<img class="lazy thumb" data-original="{{image defaultImages 270 366}}" style="display: block;">
</a>
<div class="desc">
<a class="name" href="{{url}}" target="_blank">{{productName}}</a>
<a class="name" href="{{https url}}" target="_blank">{{productName}}</a>
<p class="price">¥{{round salesPrice 2}}</p>
</div>
</div>
... ... @@ -114,7 +114,7 @@
<div class="editorial-wrap clearfix">
{{#each editorial}}
<div class="editorial-info">
<a href="{{url}}" target="_blank">
<a href="{{https url}}" target="_blank">
<img class="lazy thumb" alt="{{title}}" data-original="{{image src 368 240 1}}" width="368"
height="240" style="display: block;">
</a>
... ...
... ... @@ -4,20 +4,20 @@
<div class="opt-wrap">
<div class="center-content clearfix">
{{# brandLogo}}
<a href="{{link}}" class="brand-logo">
<a href="{{https link}}" class="brand-logo">
<img src="{{image img 108 45}}">
</a>
{{/ brandLogo}}
<p class="opt right">
{{# brandHome}}
<a href="{{link}}">
<a href="{{https link}}">
<i class="iconfont">&#xe634;</i>
{{text}}
</a>
{{/ brandHome}}
{{# brandIntro}}
<a href="{{link}}">
<a href="{{https link}}">
<i class="iconfont">&#xe63d;</i>
{{text}}
</a>
... ...
... ... @@ -2,7 +2,7 @@
{{#each products}}
<div class="goods" data-id="{{productId}}" data-url="{{url}}">
<div class="goods-img">
<a href="{{url}}" target="_blank">
<a href="{{https url}}" target="_blank">
<img class="lazy" data-original="{{image defaultImages 263 351}}" width="263" height="351" alt="">
</a>
</div>
... ... @@ -12,7 +12,7 @@
</div>
{{/if}}
<div class="goods-name">
<a href="{{url}}" target="_blank">{{productName}}</a>
<a href="{{https url}}" target="_blank">{{productName}}</a>
</div>
<div class="goods-price">
<span>¥{{round salesPrice}}</span>
... ...
... ... @@ -3,7 +3,7 @@
<ul class="shop-menu">
{{#each menus}}
<li>
<a href="{{url}}">
<a href="{{https url}}">
{{name}}
{{#icon}}
<i class="iconfont">&#xe60a;</i>
... ...
... ... @@ -7,6 +7,7 @@
'use strict';
const orderModel = require('../models/order');
const cleanHtml = require(`${global.utils}/cleanHtml`);
const _ = require('lodash');
... ... @@ -24,20 +25,19 @@ const index = (req, res, next) => {
// 设置头部路径索引focus
data.bcNavFocus = 2;
data.delivery_way = _.concat(_.find(data.delivery_way, {delivery_way_id: 1}));
data.delivery_way = _.concat(_.find(data.delivery_way, {
delivery_way_id: 1
}));
// 发票抬头
data.invoices.invoiceTitle = [
{
name: '个人',
value: 1,
myClass: 'personal'
},
{
name: '单位',
value: 2
}
];
data.invoices.invoiceTitle = [{
name: '个人',
value: 1,
myClass: 'personal'
}, {
name: '单位',
value: 2
}];
// 返回购物车链接
data.goCartLink = helper.urlFormat('/shopping/cart');
... ... @@ -50,20 +50,20 @@ const index = (req, res, next) => {
});
// 是否打印价格radio
data.printPriceRadio = [
{
value: '1',
name: '是'
},
{
value: '0',
name: '否',
checked: true
}
];
data.printPriceRadio = [{
value: '1',
name: '是'
}, {
value: '0',
name: '否',
checked: true
}];
if (data.delivery_address) {
data.delivery_address.address = cleanHtml.htmlDecode(data.delivery_address.address);
}
res.header('Cache-Control', 'no-store');
res.display('order', {
content: data,
defaultHeader: false
... ... @@ -98,6 +98,9 @@ const orderSub = (req, res, next) => {
other.address_id = crypto.decrypt(config.crypto.common, other.address_id);
}
other.remark = cleanHtml.htmlEncode(other.remark);
other.invoices_title = cleanHtml.htmlEncode(other.invoices_title);
orderModel.submit(req.user.uid, other).then(result => {
// 拼接地址
... ...
... ... @@ -9,6 +9,7 @@
const PayData = require('../models/pay');
const OrderData = require('../models/order');
const PayHelpers = require('../helpers/payment');
const cleanHtml = require(`${global.utils}/cleanHtml`);
const camelCase = global.yoho.camelCase;
const helpers = global.yoho.helpers;
const _ = require('lodash');
... ... @@ -36,6 +37,9 @@ const online = (req, res, next) => {
}
});
if (order.address) {
order.address = cleanHtml.htmlDecode(order.address);
}
if (amount > 0) {
res.display('pay', Object.assign({
... ... @@ -52,7 +56,9 @@ const online = (req, res, next) => {
cost: order.paymentAmount,
orderNum: order.orderCode,
coin: coin,
orderHref: helpers.urlFormat('/me/order/detail', {orderCode: order.orderCode}),
orderHref: helpers.urlFormat('/me/order/detail', {
orderCode: order.orderCode
}),
walkHref: helpers.urlFormat('/')
}
});
... ... @@ -171,7 +177,9 @@ const callback = (req, res) => {
cost: order.paymentAmount,
orderNum: order.orderCode,
coin: coin,
orderHref: helpers.urlFormat('/me/order/detail', {orderCode: order.orderCode}),
orderHref: helpers.urlFormat('/me/order/detail', {
orderCode: order.orderCode
}),
walkHref: helpers.urlFormat('/')
}
});
... ...
... ... @@ -8,71 +8,71 @@ const Bank = {
return {
BOCB2C: {
name: '中国银行',
ico: 'http://static.yohobuy.com/images/pay/icon/zhongguo.png'
ico: '//static.yohobuy.com/images/pay/icon/zhongguo.png'
},
ABC: {
name: '中国农业银行',
ico: 'http://static.yohobuy.com/images/pay/icon/nongye.png'
ico: '//static.yohobuy.com/images/pay/icon/nongye.png'
},
SPABANK: {
name: '平安银行',
ico: 'http://static.yohobuy.com/images/pay/icon/pingan.png'
ico: '//static.yohobuy.com/images/pay/icon/pingan.png'
},
CMBC: {
name: '中国民生银行',
ico: 'http://static.yohobuy.com/images/pay/icon/minsheng.png'
ico: '//static.yohobuy.com/images/pay/icon/minsheng.png'
},
ICBCB2C: {
name: '中国工商银行',
ico: 'http://static.yohobuy.com/images/pay/icon/gongshang.png'
ico: '//static.yohobuy.com/images/pay/icon/gongshang.png'
},
SPDB: {
name: '浦发银行',
ico: 'http://static.yohobuy.com/images/pay/icon/pufa.png'
ico: '//static.yohobuy.com/images/pay/icon/pufa.png'
},
BJRCB: {
name: '北京农商银行',
ico: 'http://static.yohobuy.com/images/pay/icon/beijingnongshang.png'
ico: '//static.yohobuy.com/images/pay/icon/beijingnongshang.png'
},
HZCBB2C: {
name: '杭州银行',
ico: 'http://static.yohobuy.com/images/pay/icon/hangzhou.png'
ico: '//static.yohobuy.com/images/pay/icon/hangzhou.png'
},
CMB: {
name: '招商银行',
ico: 'http://static.yohobuy.com/images/pay/icon/zhaoshang.png'
ico: '//static.yohobuy.com/images/pay/icon/zhaoshang.png'
},
CIB: {
name: '兴业银行',
ico: 'http://static.yohobuy.com/images/pay/icon/xingye.png'
ico: '//static.yohobuy.com/images/pay/icon/xingye.png'
},
FDB: {
name: '富滇银行',
ico: 'http://static.yohobuy.com/images/pay/icon/fudian.png'
ico: '//static.yohobuy.com/images/pay/icon/fudian.png'
},
CEBDEBIT: {
name: '中国光大银行',
ico: 'http://static.yohobuy.com/images/pay/icon/guangda.png'
ico: '//static.yohobuy.com/images/pay/icon/guangda.png'
},
CCB: {
name: '中国建设银行',
ico: 'http://static.yohobuy.com/images/pay/icon/zhongguojianshe.png'
ico: '//static.yohobuy.com/images/pay/icon/zhongguojianshe.png'
},
GDB: {
name: '广发银行',
ico: 'http://static.yohobuy.com/images/pay/icon/guangfa.png'
ico: '//static.yohobuy.com/images/pay/icon/guangfa.png'
},
POSTGC: {
name: '中国邮政储蓄',
ico: 'http://static.yohobuy.com/images/pay/icon/zhongguoyouzhengchuxu.png'
ico: '//static.yohobuy.com/images/pay/icon/zhongguoyouzhengchuxu.png'
},
SHBANK: {
name: '上海银行',
ico: 'http://static.yohobuy.com/images/pay/icon/shanghai.png'
ico: '//static.yohobuy.com/images/pay/icon/shanghai.png'
},
NBBANK: {
name: '宁波银行',
ico: 'http://static.yohobuy.com/images/pay/icon/ningbo.png'
ico: '//static.yohobuy.com/images/pay/icon/ningbo.png'
}
};
}
... ...
{{> settle-header}}
<div class="shopping-order-page blk-page">
{{# content}}
<div class="center-content">
{{> bc-nav}}
<div class="address-info order-block">
<p class="title">
收货信息
<span class="right new-address">
新增收货地址
<i class="iconfont">&#xe61f;</i>
</span>
</p>
<div class="content">
<ul id="address-list" class="clearfix address-list shrink"></ul>
<p class="address-all vhide">
显示全部地址
<span class="iconfont">&#xe616;</span>
</p>
</div>
</div>
<div class="payment-type order-block">
<p class="title">支付方式</p>
<ul class="content">
<li class="chose-row clearfix focus">
<span class="chose-block">在线支付</span>
<span class="tip-text">支持主流银行卡、微信、支付宝、银联等平台付款,方便快捷</span>
</li>
</ul>
</div>
<div class="dispatch-type order-block">
<p class="title">配送方式</p>
<ul class="content">
{{#each delivery_way}}
<li class="chose-row clearfix{{#if @first}} focus{{/if}}" data-id="{{delivery_way_id}}">
<span class="chose-block">{{delivery_way_name}}:运费¥{{round delivery_way_cost 2}}</span>
</li>
{{/each}}
</ul>
</div>
<div class="order-info order-block">
<div class="order-inner">
<p class="title">
订单信息
<a class="right go-cart-link" href="{{goCartLink}}">
返回购物袋修改
<span class="iconfont">&#xe61e;</span>
</a>
</p>
{{#with shopping_cart_data}}
{{#isY is_multi_package}}
<div class="multi-package-row">
温馨提示:您购买的商品<em class="blue">分属不同仓库</em>,需要调拨,将被拆分成多个包裹送达
<span class="iconfont show-package">&#xe643;</span>
<div class="package-list hide">
<div class="package-up-icon"></div>
{{#each ../package_list}}
<div class="package-item">
<p class="package-title bold">包裹{{math @index '+' 1}}:{{#if @first}}总仓发货{{^}}异地调拨{{/if}}</p>
{{#if showToggle}}
<span class="iconfont toggle-icon left-icon">&#xe607;</span>
<span class="iconfont toggle-icon right-icon">&#xe61e;</span>
{{/if}}
<div class="package-goods-wrap">
<ul class="package-goods clearfix">
{{#each goods_list}}
<li class="left">
<img class="lazy package-goods-img" data-original="{{image goods_images 100 134}}">
</li>
{{/each}}
</ul>
</div>
<p class="package-shipping">运费:¥{{shopping_cost}}元(原价{{shopping_orig_cost}}元,优惠{{shopping_cut_cost}}元)</p>
</div>
{{/each}}
</div>
</div>
{{/isY}}
{{/with}}
<div class="content">
<p class="order-table-head clearfix">
<span class="info">商品信息</span>
<span class="color-size">颜色尺码</span>
<span class="price">单价</span>
<span class="number">数量</span>
</p>
<ul class="order-table-body">
{{#each goods_list}}
<li class="order-goods clearfix">
<a class="goods-img inline-block" href="{{link}}" target="_blank">
<img class="lazy" data-original="{{image goods_images 100 148}}">
{{#if isGift}}
<span class="gift-tag">赠品</span>
{{/if}}
</a>
<p class="brand-and-name inline-block">
<a class="brand-name" href="{{brandUrl}}" target="_blank">{{brand_name}}</a>
<a class="name" href="{{link}}" target="_blank">{{product_name}}</a>
</p>
<p class="color-size">
<span class="color">颜色:{{color_name}}</span>
<span class="size">尺码:{{size_name}}</span>
</p>
<p class="price">
¥{{round last_price 2}}
</p>
<p class="number">
<span class="iconfont">&#xe61d;</span>
{{buy_number}}
</p>
</li>
{{/each}}
</ul>
</div>
</div>
</div>
<div class="invoice-info order-block">
<p class="title">发票信息</p>
<div id="invoice-content" class="content">
<div class="invoice-radio">
{{> icon/radio}}
<label>发票开具</label>
</div>
</div>
</div>
<div class="coin-and-remark">
<div class="coin">
<p class="title">
<span class="iconfont coin-ctrl">&#xe639;</span>
<span class="coin-ctrl">使用有货币</span>
</p>
<div class="content hide">
<div class="using-coin">
本次使用有货币
<input id="input-coin" class="input coin-input" type="text" data-max="{{yoho_coin}}">
您当前共有有货币<em class="blue">{{yoho_coin}}</em>
<span id="coin-tip" class="coin-tip block blue vhide">抵扣¥<em class="balance-coin"></em></span>
<span id="coin-sure" class="btn disable">确定</span>
</div>
<div class="used-coin hide">
本次使用有货币<em id="coin-used" class="blue"></em>个,本次抵扣<span class="blue">¥<em id="coin-deduction"></em></span>
<span class="btn white modify">修改</span>
<span class="btn white cancel">取消使用</span>
</div>
</div>
</div>
<div class="remark">
<p class="title">
<span class="iconfont remark-ctrl">&#xe639;</span>
<span class="remark-ctrl">添加备注信息</span>
</p>
<div class="content hide">
<textarea id="remark-content" class="remark-content" placeholder="声明:备注中有关收货人信息、支付方式、配送方式、发票信息等购买要求一律以上面的选择为准,备注无效"></textarea>
<div id="print-price" class="print-price">
是否打印价格:
<div class="print-price-radio-group">
{{#each printPriceRadio}}
<div class="print-price-radio" data-value="{{value}}">
<label>{{name}}</label>
{{> icon/radio}}
</div>
{{/each}}
<span class="remark-tip">(如:送朋友的商品可不打印价格哦!)</span>
</div>
</div>
</div>
</div>
</div>
<div class="balance clearfix">
{{# shopping_cart_data}}
<div class="balance-info left">
<p class="receiver-wrap">
{{#with ../delivery_address}}
<i>收货信息:</i>
<em id="receiver">{{consignee}} {{mobile}} {{area}} {{address}}</em>
{{/with}}
<span class="right">{{selected_goods_count}}件商品</span>
</p>
<p>
支付方式:<em id="balance-pay-type">在线支付</em>
</p>
</div>
<ul id="balance-list" class="balance-list right">
{{#each promotion_formula_list}}
<li>
<span class="balance-title">
{{promotion}}
{{#if shippingCut}}
<em>(原价:{{shippingOrigin}}元,优惠:{{shippingCut}}元)</em>
{{/if}}
</span>
<span class="balance-cost">{{promotion_amount}}</span>
</li>
{{/each}}
<li class="need-pay">
<span class="balance-title">应付金额{{#if shipping_cost}}(含运费){{/if}}</span>
<span id="balance-cost" class="balance-cost" data-cost="{{last_order_amount}}">¥<em>{{round last_order_amount 2}}</em></span>
</li>
<li>
<span id="submit-order" class="btn submit-order">提交订单</span>
</li>
</ul>
{{/ shopping_cart_data}}
</div>
{{!-- 服务端渲染,客户端使用 --}}
<script id="invoice-dialog-tpl" type="text/html">
<p class="dialog-title">发票信息</p>
<ul class="invoice-tab">
<li class="btn paper-invoice">纸质发票</li>
</ul>
<div class="invoice-entity el">
<div class="row clearfix">
<span class="label">
<em class="required-mark">*</em>
发票抬头:
</span>
<div class="row-content">
<div class="invoice-title-radio-group">
{{#each invoices.invoiceTitle}}
<div class="invoice-title-radio{{#if myClass}} {{myClass}}{{/if}}" data-value="{{value}}">
{{> icon/radio}}
<label>{{name}}</label>
</div>
{{/each}}
</div>
<div>
<input class="input invoice-title-input hide" type="text" maxlength="30" placeholder="请填写单位名称">
<span class="input-tip invoice-title-tip blue hide">
<span class="iconfont">&#xe60c;</span>
请填写发票抬头
</span>
</div>
</div>
</div>
<div class="row clearfix">
<span class="label">
<em class="required-mark">*</em>
发票内容:
</span>
<div class="row-content">
<div class="invoice-content-radio-group">
{{#each invoices.invoiceContentList}}
<div class="invoice-content-radio" data-value="{{invoices_type_id}}">
{{> icon/radio}}
<label>{{invoices_type_name}}</label>
</div>
{{/each}}
</div>
</div>
</div>
</div>
</script>
</div>
{{/ content}}
</div>
\ No newline at end of file
{{> settle-header}}
<div class="shopping-order-page blk-page">
{{# content}}
<div class="center-content">
{{> bc-nav}}
<div class="address-info order-block">
<p class="title">
收货信息
<span class="right new-address">
新增收货地址
<i class="iconfont">&#xe61f;</i>
</span>
</p>
<div class="content">
<ul id="address-list" class="clearfix address-list shrink"></ul>
<p class="address-all vhide">
显示全部地址
<span class="iconfont">&#xe616;</span>
</p>
</div>
</div>
<div class="payment-type order-block">
<p class="title">支付方式</p>
<ul class="content">
<li class="chose-row clearfix focus">
<span class="chose-block">在线支付</span>
<span class="tip-text">支持主流银行卡、微信、支付宝、银联等平台付款,方便快捷</span>
</li>
</ul>
</div>
<div class="dispatch-type order-block">
<p class="title">配送方式</p>
<ul class="content">
{{#each delivery_way}}
<li class="chose-row clearfix{{#if @first}} focus{{/if}}" data-id="{{delivery_way_id}}">
<span class="chose-block">{{delivery_way_name}}:运费¥{{round delivery_way_cost 2}}</span>
</li>
{{/each}}
</ul>
</div>
<div class="order-info order-block">
<div class="order-inner">
<p class="title">
订单信息
<a class="right go-cart-link" href="{{https goCartLink}}">
返回购物袋修改
<span class="iconfont">&#xe61e;</span>
</a>
</p>
{{#with shopping_cart_data}}
{{#isY is_multi_package}}
<div class="multi-package-row">
温馨提示:您购买的商品<em class="blue">分属不同仓库</em>,需要调拨,将被拆分成多个包裹送达
<span class="iconfont show-package">&#xe643;</span>
<div class="package-list hide">
<div class="package-up-icon"></div>
{{#each ../package_list}}
<div class="package-item">
<p class="package-title bold">包裹{{math @index '+' 1}}:{{#if @first}}总仓发货{{^}}异地调拨{{/if}}</p>
{{#if showToggle}}
<span class="iconfont toggle-icon left-icon">&#xe607;</span>
<span class="iconfont toggle-icon right-icon">&#xe61e;</span>
{{/if}}
<div class="package-goods-wrap">
<ul class="package-goods clearfix">
{{#each goods_list}}
<li class="left">
<img class="lazy package-goods-img" data-original="{{image goods_images 100 134}}">
</li>
{{/each}}
</ul>
</div>
<p class="package-shipping">运费:¥{{shopping_cost}}元(原价{{shopping_orig_cost}}元,优惠{{shopping_cut_cost}}元)</p>
</div>
{{/each}}
</div>
</div>
{{/isY}}
{{/with}}
<div class="content">
<p class="order-table-head clearfix">
<span class="info">商品信息</span>
<span class="color-size">颜色尺码</span>
<span class="price">单价</span>
<span class="number">数量</span>
</p>
<ul class="order-table-body">
{{#each goods_list}}
<li class="order-goods clearfix">
<a class="goods-img inline-block" href="{{https link}}" target="_blank">
<img class="lazy" data-original="{{image goods_images 100 148}}">
{{#if isGift}}
<span class="gift-tag">赠品</span>
{{/if}}
</a>
<p class="brand-and-name inline-block">
<a class="brand-name" href="{{https brandUrl}}" target="_blank">{{brand_name}}</a>
<a class="name" href="{{https link}}" target="_blank">{{product_name}}</a>
</p>
<p class="color-size">
<span class="color">颜色:{{color_name}}</span>
<span class="size">尺码:{{size_name}}</span>
</p>
<p class="price">
¥{{round last_price 2}}
</p>
<p class="number">
<span class="iconfont">&#xe61d;</span>
{{buy_number}}
</p>
</li>
{{/each}}
</ul>
</div>
</div>
</div>
<div class="invoice-info order-block">
<p class="title">发票信息</p>
<div id="invoice-content" class="content">
<div class="invoice-radio">
{{> icon/radio}}
<label>发票开具</label>
</div>
</div>
</div>
<div class="coin-and-remark">
<div class="coin">
<p class="title">
<span class="iconfont coin-ctrl">&#xe639;</span>
<span class="coin-ctrl">使用有货币</span>
</p>
<div class="content hide">
<div class="using-coin">
本次使用有货币
<input id="input-coin" class="input coin-input" type="text" data-max="{{yoho_coin}}">
您当前共有有货币<em class="blue">{{yoho_coin}}</em>
<span id="coin-tip" class="coin-tip block blue vhide">抵扣¥<em class="balance-coin"></em></span>
<span id="coin-sure" class="btn disable">确定</span>
</div>
<div class="used-coin hide">
本次使用有货币<em id="coin-used" class="blue"></em>个,本次抵扣<span class="blue">¥<em id="coin-deduction"></em></span>
<span class="btn white modify">修改</span>
<span class="btn white cancel">取消使用</span>
</div>
</div>
</div>
<div class="remark">
<p class="title">
<span class="iconfont remark-ctrl">&#xe639;</span>
<span class="remark-ctrl">添加备注信息</span>
</p>
<div class="content hide">
<textarea id="remark-content" class="remark-content" placeholder="声明:备注中有关收货人信息、支付方式、配送方式、发票信息等购买要求一律以上面的选择为准,备注无效"></textarea>
<div id="print-price" class="print-price">
是否打印价格:
<div class="print-price-radio-group">
{{#each printPriceRadio}}
<div class="print-price-radio" data-value="{{value}}">
<label>{{name}}</label>
{{> icon/radio}}
</div>
{{/each}}
<span class="remark-tip">(如:送朋友的商品可不打印价格哦!)</span>
</div>
</div>
</div>
</div>
</div>
<div class="balance clearfix">
{{# shopping_cart_data}}
<div class="balance-info left">
<p class="receiver-wrap">
{{#with ../delivery_address}}
<i>收货信息:</i>
<em id="receiver">{{consignee}} {{mobile}} {{area}} {{address}}</em>
{{/with}}
<span class="right">{{selected_goods_count}}件商品</span>
</p>
<p>
支付方式:<em id="balance-pay-type">在线支付</em>
</p>
</div>
<ul id="balance-list" class="balance-list right">
{{#each promotion_formula_list}}
<li>
<span class="balance-title">
{{promotion}}
{{#if shippingCut}}
<em>(原价:{{shippingOrigin}}元,优惠:{{shippingCut}}元)</em>
{{/if}}
</span>
<span class="balance-cost">{{promotion_amount}}</span>
</li>
{{/each}}
<li class="need-pay">
<span class="balance-title">应付金额{{#if shipping_cost}}(含运费){{/if}}</span>
<span id="balance-cost" class="balance-cost" data-cost="{{last_order_amount}}">¥<em>{{round last_order_amount 2}}</em></span>
</li>
<li>
<span id="submit-order" class="btn submit-order">提交订单</span>
</li>
</ul>
{{/ shopping_cart_data}}
</div>
{{!-- 服务端渲染,客户端使用 --}}
<script id="invoice-dialog-tpl" type="text/html">
<p class="dialog-title">发票信息</p>
<ul class="invoice-tab">
<li class="btn paper-invoice">纸质发票</li>
</ul>
<div class="invoice-entity el">
<div class="row clearfix">
<span class="label">
<em class="required-mark">*</em>
发票抬头:
</span>
<div class="row-content">
<div class="invoice-title-radio-group">
{{#each invoices.invoiceTitle}}
<div class="invoice-title-radio{{#if myClass}} {{myClass}}{{/if}}" data-value="{{value}}">
{{> icon/radio}}
<label>{{name}}</label>
</div>
{{/each}}
</div>
<div>
<input class="input invoice-title-input hide" type="text" maxlength="30" placeholder="请填写单位名称">
<span class="input-tip invoice-title-tip blue hide">
<span class="iconfont">&#xe60c;</span>
请填写发票抬头
</span>
</div>
</div>
</div>
<div class="row clearfix">
<span class="label">
<em class="required-mark">*</em>
发票内容:
</span>
<div class="row-content">
<div class="invoice-content-radio-group">
{{#each invoices.invoiceContentList}}
<div class="invoice-content-radio" data-value="{{invoices_type_id}}">
{{> icon/radio}}
<label>{{invoices_type_name}}</label>
</div>
{{/each}}
</div>
</div>
</div>
</div>
</script>
</div>
{{/ content}}
</div>
... ...
... ... @@ -27,8 +27,8 @@
</div>
<div class="btns right">
<a class="btn go-check-order" href="{{orderHref}}">查看订单详情</a>
<a class="btn" href="{{walkHref}}">继续逛逛</a>
<a class="btn go-check-order" href="{{https orderHref}}">查看订单详情</a>
<a class="btn" href="{{https walkHref}}">继续逛逛</a>
</div>
</div>
... ...
... ... @@ -11,7 +11,7 @@ const isTest = process.env.NODE_ENV === 'test';
module.exports = {
app: 'web',
appVersion: '4.6.0', // 调用api接口版本
appVersion: '4.9.0', // 调用api接口版本
port: 6003,
siteUrl: '//www.yohoblk.com',
signExtend: {
... ... @@ -135,9 +135,9 @@ if (isProduction) {
appName: 'www.yohoblk.com for test',
domains: {
singleApi: 'http://192.168.102.31:8092/',
api: 'http://testapi.yoho.cn:28078/',
service: 'http://testservice.yoho.cn:28077/',
search: 'http://192.168.102.216:8080/yohosearch/'
api: process.env.TEST_API || 'http://testapi.yoho.cn:28078/',
service: process.env.TEST_SERVICE || 'http://testservice.yoho.cn:28077/',
search: process.env.TEST_SEARCH || 'http://192.168.102.216:8080/yohosearch/'
},
useOneapm: true,
useCache: true,
... ...
module.exports = {
domains: [
'www.yohoblk.com',
'm.yohoblk.com',
'www.yohobuy.com',
'm.yohobuy.com',
'www.yohoshow.com',
'www.yohood.cn'
]
};
... ...
... ... @@ -40,8 +40,6 @@ exports.serverError = () => {
logger.error(`error at path: ${req.url}`);
logger.error(err);
if (!res.headersSent) {
let renderErrPage;
if (req.xhr) {
return res.status(500).json({
code: 500,
... ... @@ -49,7 +47,7 @@ exports.serverError = () => {
});
}
renderErrPage = (result) => {
const renderErrPage = (result) => {
res.status(500).display('error/500', {
module: 'common',
page: 'error',
... ...
/**
* 手机访问检测
* @author:
* @date:
*/
'use strict';
module.exports = () => {
return (req, res, next) => {
/**
* 手机访问检测
* @author:
* @date:
*/
'use strict';
module.exports = () => {
return (req, res, next) => {
let isMobile = /(nokia|iphone|android|ipad|motorola|^mot\-|softbank|foma|docomo|kddi|up\.browser|up\.link|htc|dopod|blazer|netfront|helio|hosin|huawei|novarra|CoolPad|webos|techfaith|palmsource|blackberry|alcatel|amoi|ktouch|nexian|samsung|^sam\-|s[cg]h|^lge|ericsson|philips|sagem|wellcom|bunjalloo|maui|symbian|smartphone|midp|wap|phone|windows ce|iemobile|^spice|^bird|^zte\-|longcos|pantech|gionee|^sie\-|portalmmm|jig\s browser|hiptop|^ucweb|^benq|haier|^lct|opera\s*mobi|opera\*mini|320x320|240x320|176x220)/i.test(req.get('user-agent')); // eslint-disable-line
let isWechat = /(MicroMessenger)/i.test(req.get('user-agent')); // eslint-disable-line
if (isMobile && req.url === '/') {
return res.redirect('//www.yohoshow.com/about/index/blkqr');
}
if (isMobile) {
// http://jira.yoho.cn:8888/browse/BLK-2051
return res.redirect(`//m.yohoblk.com${req.url}`);
}
next();
};
};
if (isMobile && req.url === '/') {
return res.redirect('//www.yohoshow.com/about/index/blkqr');
}
if (isMobile) {
// http://jira.yoho.cn:8888/browse/BLK-2051
return res.redirect(`//m.yohoblk.com${req.url}`);
}
next();
};
};
... ...
/**
* 安全重定向 301、302跳转只允许白名单中的URL
*
* @author: Aiden Xu<aiden.xu@yoho.cn>
* @date: 2016/6/22
*/
'use strict';
const url = require('url');
const domains = require('../../config/safe-domain').domains;
const _ = require('lodash');
/**
* 检查域名安全性
*
* @param uri
*/
const safeRedirect = (uri) => {
let formalUrl = url.parse(uri); // 匹配标准的URL
let informalUrl = uri.match(/^\/\/([\w\d\-.]+).*/); // 尝试匹配 '//' 开头的不规范的URL
let matchFunc;
if (formalUrl.protocol) {
// 在白名单中尝试匹配
matchFunc = (item)=> {
return item === formalUrl.host;
};
} else if (informalUrl && informalUrl.length > 0) {
matchFunc = (item)=> {
return item === informalUrl[1];
};
}
return _.some(domains, matchFunc) ? uri : '/';
};
/**
* 安全重定向中间件
*
* @returns {function(*, *=, *)}
*/
const middleware = () => {
return (req, res, next) => {
const expressRedirect = res.redirect;
res.redirect = function(uri) {
const safeUri = safeRedirect(uri);
let args = [];
if (arguments.length === 1) {
args[0] = safeUri;
} else if (arguments.length === 2) {
args[1] = safeUri;
}
return expressRedirect.apply(res, args);
};
next();
};
};
module.exports = {
safeRedirect,
middleware
};
... ...
... ... @@ -33,7 +33,7 @@ const getMenuData = () => (
cn: '潮流嘉年华',
en: 'YO\'HOOD'
}, {
link: '//www.yohobuy.com',
link: 'http://www.yohobuy.com',
cn: '有货',
en: 'YOHO!BUY'
}]
... ...
... ... @@ -3,6 +3,6 @@
<div class="tips">
<span class="tip">哎呀,您访问的页面走丢了...</span>
<span class="tips-english">404 File Not Found, Sorry</span>
<span>建议您:<a href="javascript:location.reload()">刷新该网页/ </a><a href="javascript:history.go(-1)">返回上一页/</a> <a href="http://www.yohoblk.com">去首页看看</a></span>
<span>建议您:<a href="javascript:location.reload()">刷新该网页/ </a><a href="javascript:history.go(-1)">返回上一页/</a> <a href="//www.yohoblk.com">去首页看看</a></span>
</div>
</div>
\ No newline at end of file
</div>
... ...
... ... @@ -3,6 +3,6 @@
<div class="tips">
<span class="tip">哎呀,程序出错了...</span>
<span class="tips-english">500-Server Internal Error</span>
<span>建议您:<a href="javascript:location.reload()">刷新该网页/ </a><a href="javascript:history.go(-1)">返回上一页/</a> <a href="http://www.yohoblk.com">去首页看看</a></span>
<span>建议您:<a href="javascript:location.reload()">刷新该网页/ </a><a href="javascript:history.go(-1)">返回上一页/</a> <a href="//www.yohoblk.com">去首页看看</a></span>
</div>
</div>
\ No newline at end of file
</div>
... ...
<div class="blk-footer">
<div class="center-content">
<ul class="about-us clearfix">
<li><a href="{{siteUrl}}">BLK首页</a></li>
<li><a href="{{https siteUrl}}">BLK首页</a></li>
<li>
<a href="http://chat8.live800.com/live800/chatClient/chatbox.jsp?companyID=703953&configID=149819&jid=1099911094" target="_blank">客户服务</a>
</li>
<li><a href="{{siteUrl}}/help?id=2" target="_blank">支付方式</a></li>
<li><a href="{{siteUrl}}/help?id=31" target="_blank">配送方式</a></li>
<li><a href="{{siteUrl}}/help?id=41" target="_blank">售后服务</a></li>
<li><a href="{{https siteUrl}}/help?id=2" target="_blank">支付方式</a></li>
<li><a href="{{https siteUrl}}/help?id=31" target="_blank">配送方式</a></li>
<li><a href="{{https siteUrl}}/help?id=41" target="_blank">售后服务</a></li>
</ul>
<div class="record-info">
<p>
... ... @@ -20,4 +20,4 @@
<div class="return-top hide">
{{> icon/up}}
</div>
</div>
\ No newline at end of file
</div>
... ...
<div class="goods-info" data-skn="{{skn}}">
<a href="{{link}}" target="_blank">
<img class="lazy thumb" data-original="{{img}}">
</a>
<div class="desc">
<a class="name" href="{{link}}" target="_blank">{{name}}</a>
<p class="price">{{price}}</p>
</div>
</div>
\ No newline at end of file
<div class="goods-info" data-skn="{{skn}}">
<a href="{{https link}}" target="_blank">
<img class="lazy thumb" data-original="{{img}}">
</a>
<div class="desc">
<a class="name" href="{{https link}}" target="_blank">{{name}}</a>
<p class="price">{{price}}</p>
</div>
</div>
... ...
... ... @@ -5,7 +5,7 @@
<ul class="main-nav-list">
{{# navbars}}
<li class="nav-item{{#if cur}} cur{{/if}}">
<a href="{{link}}"{{#if isNewPage}} target="_blank"{{/if}}>
<a href="{{https link}}"{{#if isNewPage}} target="_blank"{{/if}}>
<span class="nav-en">{{en}}</span>
<span class="nav-cn">{{cn}}</span>
</a>
... ... @@ -22,7 +22,7 @@
<ul class="sub-nav-list clearfix">
{{# subNav}}
<li{{#if thirdNav}} class="contain-third"{{/if}}>
<a href="{{link}}">
<a href="{{https link}}">
{{en}}{{cn}}
</a>
{{#if thirdNav}}
... ... @@ -33,14 +33,14 @@
{{# this}}
{{#if category}}
<dt>
<a href="{{link}}">{{name}}</a>
<a href="{{https link}}">{{name}}</a>
{{#if hot}}
<span class="hot iconfont">&#xe650;</span>
{{/if}}
</dt>
{{^}}
<dd>
<a href="{{link}}">{{name}}</a>
<a href="{{https link}}">{{name}}</a>
{{#if hot}}
<span class="hot iconfont">&#xe650;</span>
{{/if}}
... ... @@ -81,4 +81,4 @@
</div>
</div>
</div>
{{/ navMenu}}
\ No newline at end of file
{{/ navMenu}}
... ...
... ... @@ -2,13 +2,13 @@
<p class="path-nav">
{{#each nav}}
{{#if link}}
<a {{#if @last}}class="last"{{/if}} href="{{link}}" title="{{pathTitle}}">{{{name}}}</a>
<a {{#if @last}}class="last"{{/if}} href="{{https link}}" title="{{pathTitle}}">{{{name}}}</a>
{{^}}
<span {{#if @last}}class="last"{{/if}} title="{{pathTitle}}">{{{name}}}</span>
{{/if}}
{{#unless @last}}
<span class="iconfont icon">&frasl;</span>
<span class="icon">&frasl;</span>
{{/unless}}
{{/each}}
</p>
... ...
<div class="blk-settle-header">
<div class="center-content">
<div class="main-logo">
<a href="{{siteUrl}}"></a>
<a href="{{https siteUrl}}"></a>
</div>
<ul class="header-tools right clearfix">
<li>
{{#if userName}}
Hi~
<a href="{{siteUrl}}/me">{{userName}}</a>
<a href="{{siteUrl}}/passport/logout">[退出]</a>
<a href="{{https siteUrl}}/me">{{userName}}</a>
<a href="{{https siteUrl}}/passport/logout">[退出]</a>
{{^}}
<a href="{{siteUrl}}/passport/login">登录</a> |
<a href="{{siteUrl}}/passport/reg">注册</a>
<a href="{{https siteUrl}}/passport/login">登录</a> |
<a href="{{https siteUrl}}/passport/reg">注册</a>
{{/if}}
</li>
<li><a href="{{siteUrl}}/me">个人中心</a></li>
<li><a href="{{siteUrl}}/help">帮助中心</a></li>
<li><a href="{{https siteUrl}}/me">个人中心</a></li>
<li><a href="{{https siteUrl}}/help">帮助中心</a></li>
</ul>
</div>
</div>
\ No newline at end of file
</div>
... ...
<div class="blk-sign-header">
<div class="center-content">
<div class="main-logo">
<a href="{{siteUrl}}"></a>
<a href="{{https siteUrl}}"></a>
</div>
<ul class="header-tools right clearfix">
<li>
{{#if userName}}
Hi~
<a href="{{siteUrl}}/me">{{userName}}</a>
<a href="{{siteUrl}}/passport/logout">[退出]</a>
<a href="{{https siteUrl}}/me">{{userName}}</a>
<a href="{{https siteUrl}}/passport/logout">[退出]</a>
{{^}}
<a href="{{siteUrl}}/passport/login">登录</a> |
<a href="{{siteUrl}}/passport/reg">注册</a>
<a href="{{https siteUrl}}/passport/login">登录</a> |
<a href="{{https siteUrl}}/passport/reg">注册</a>
{{/if}}
</li>
<li><a href="{{siteUrl}}">首页</a></li>
<li><a href="{{siteUrl}}/help">帮助中心</a></li>
<li><a href="{{https siteUrl}}">首页</a></li>
<li><a href="{{https siteUrl}}/help">帮助中心</a></li>
<li>客服电话<span>400-889-9646</span></li>
</ul>
</div>
</div>
\ No newline at end of file
</div>
... ...
... ... @@ -64,7 +64,7 @@
"winston-daily-rotate-file": "^1.1.4",
"xml2js": "^0.4.17",
"xss": "^0.2.13",
"yoho-node-lib": "0.0.45"
"yoho-node-lib": "0.0.51"
},
"devDependencies": {
"autoprefixer": "^6.3.6",
... ...
... ... @@ -98,7 +98,7 @@ $('#collect-btn').click(function() {
new _alert(data.message).show();
$this.toggleClass('collected');
} else if (data.code === 400) {
window.location.href = 'http://www.yohoblk.com/passport/login';
window.location.href = '//www.yohoblk.com/passport/login';
} else {
new _alert(data.message).show();
}
... ... @@ -148,7 +148,7 @@ function comment() {
// clear comment-text
$('#comment-info').val('').keyup();
} else if (data.code === 400) {
window.location.href = 'http://www.yohoblk.com/passport/login';
window.location.href = '//www.yohoblk.com/passport/login';
} else {
new _alert(data.message).show();
}
... ...
... ... @@ -15,9 +15,9 @@ var $address = $('#addressDetail');
var $mobile = $('#mobile');
var $phone = $('#phone');
var addressForm = $('.form-group-address');
var currentLength = $('.a-table').find('tr').length - 1;// 当前地址条数
var leftLength = 7 - currentLength;// 还剩地址条数
var reg = new RegExp(/^(0|86|17951)?(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$/);// 手机号码校验
var currentLength = $('.a-table').find('tr').length - 1; // 当前地址条数
var leftLength = 7 - currentLength; // 还剩地址条数
var reg = new RegExp(/^(0|86|17951)?(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$/); // 手机号码校验
require('./me');
require('../plugins/check');
... ... @@ -26,7 +26,9 @@ require('yoho-jquery-placeholder');
$('[placeholder]').placeholder();
$(function() {
var address = cascadingAddress({el: '#address'});
var address = cascadingAddress({
el: '#address'
});
/**
* 公共方法
... ... @@ -61,14 +63,14 @@ $(function() {
info.consignee === '' ? $consignee.next().show() : $consignee.next().hide();
info.address === '' ? $address.next().show() : $address.next().hide();
typeof (info.area_code) === 'undefined' ?
addressForm.css('margin-bottom', '20px').find('.error-tips').show() :
typeof(info.area_code) === 'undefined' ?
addressForm.css('margin-bottom', '20px').find('.error-tips').show() :
addressForm.css('margin-bottom', '70px').find('.error-tips').hide();
if (info.id) {
info.mobile === '' ? $mobile.next().show() : $mobile.next().hide();
if (info.consignee === '' || info.address === '' || info.mobile === '' ||
typeof (info.area_code) === 'undefined') {
typeof(info.area_code) === 'undefined') {
flag = false;
}
return flag;
... ... @@ -77,7 +79,7 @@ $(function() {
(!reg.test(info.mobile) ? $mobile.next().html('手机号码格式不对').show() : $mobile.next().hide());
if (info.consignee === '' || info.address === '' || info.mobile === '' || !reg.test(info.mobile) ||
typeof (info.area_code) === 'undefined') {
typeof(info.area_code) === 'undefined') {
flag = false;
}
return flag;
... ... @@ -144,7 +146,7 @@ $(function() {
if (Bll.check(info) === true) {
console.log(info.id);
// console.log(info.id);
// 新增
if (info.id === '') {
... ... @@ -292,8 +294,11 @@ $(function() {
$(this).find('.set').css('display', 'inline-block');
});
$('.table-body').on('mouseout',function(){
var tmpset=$(this).find('.set');
if(tmpset.css('display')== 'inline-block')tmpset.hide();
$('.table-body').on('mouseout', function() {
var tmpset = $(this).find('.set');
if (tmpset.css('display') === 'inline-block') {
tmpset.hide();
}
});
});
... ...
... ... @@ -53,7 +53,7 @@ function setExchangeEepress(eid, num) {
number: num
},
success: function(data) {
console.log(data);
// console.log(data);
if (data.code === 200) {
location.reload();
}
... ... @@ -81,7 +81,7 @@ $showExpress.on('click', '.reset-express', function() {
$editExpress.removeClass('hide');
});
console.log($('.reason-info').find('span').text().length);
// console.log($('.reason-info').find('span').text().length);
if (remark <= 5) {
$('.reason-info').hide();
... ...