Authored by biao

Merge branch 'develop' into feature/return

Showing 66 changed files with 2873 additions and 718 deletions

Too many changes to show.

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

... ... @@ -20,6 +20,7 @@ const favicon = require('serve-favicon');
const session = require('express-session');
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');
... ... @@ -52,6 +53,7 @@ app.use(express.static(path.join(__dirname, 'public')));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: false}));
app.use(cookieParser());
app.use(multer());
app.use(session({
proxy: true,
... ...
... ... @@ -10,9 +10,12 @@ const editorialModel = require('../models/editorial');
const index = (req, res, next) => {
let pageNum = req.query.page || 1;
let limit = req.query.limit || 20;
let type = req.query.type || 0;
editorialModel.getIndexData(type).then((result) => {
// let gender = req.query.brand || 1;
editorialModel.getIndexData(type, pageNum, limit).then((result) => {
res.display('index', {
module: 'editorial',
page: 'index',
... ... @@ -25,7 +28,6 @@ const index = (req, res, next) => {
name: 'MEN首页'
},
{
link: '/editorial?type=1',
pathTitle: '资讯',
name: '资讯'
}
... ... @@ -47,10 +49,20 @@ const index = (req, res, next) => {
}).catch(next);
};
// const getChannelData = (channel, tag, title) => {
// }
const list = (req, res) => {
let pageNum = req.query.page || 1;
let limit = req.query.limit || 20;
let tag = req.params.tag || '暗黑';
let authorId = req.params.authorId || 0;
editorialModel.getListData().then((result) => {
// let curChannel = getChannelData(req.channel, req.query.query);
editorialModel.getListData(pageNum, limit, tag, authorId).then((result) => {
res.display('list', {
module: 'editorial',
page: 'list',
... ... @@ -66,9 +78,13 @@ const list = (req, res) => {
link: '/editorial?type=1',
pathTitle: '资讯',
name: '资讯'
},
{
pathTitle: req.query.query,
name: req.query.query
}
],
pathTitle: '户外',
pathTitle: req.query.query,
msg: result,
paginationOpts: {
page: pageNum, // current page: http://host/?page=2
... ... @@ -85,206 +101,158 @@ const list = (req, res) => {
});
};
const detail = (req, res) => {
const detail = (req, res, next) => {
let id = req.params.id || 52571;
// editorialModel.getListData().then( => {
res.display('detail', {
module: 'editorial',
page: 'detail',
title: '资讯详情',
editorialDetail: {
nav: [
{
link: '/editorial?type=0',
pathTitle: '首页',
name: 'MEN首页'
},
{
link: '/editorial?type=1',
pathTitle: '资讯',
name: '资讯'
}
],
header: {
title: '黑白搭配,穿衣灵感,黑白搭配,穿衣灵感,黑白搭配,穿衣灵感,黑白搭配,穿衣灵感,黑白搭配,穿衣灵感,黑白搭配,穿衣灵感',
avatar: '//devlup.com/wp-content/uploads/2013/07/images.jpg',
name: '二京赋',
time: '2016/07/05 19:36',
click: '26',
commentNum: '45'
},
content: {
pic: {
img: '#'
},
text: {
articleText: '我服务而恢复力而柔软如个为福建和爱我发'
},
relatedReco: {
relatedTitle: '推荐搭配',
goods: [
{
img: 'http://placehold.it/274x366',
link: '',
name: 'Fred Perry Bomber jacket',
price: '1015.00'
},
{
img: 'http://placehold.it/274x366',
link: '',
name: 'Fred Perry Bomber jacket',
price: '1015.00'
},
{
img: 'http://placehold.it/274x366',
link: '',
name: 'Fred Perry Bomber jacket',
price: '1015.00'
},
{
img: 'http://placehold.it/274x366',
link: '',
name: 'Fred Perry Bomber jacket',
price: '1015.00'
},
{
img: 'http://placehold.it/274x366',
link: '',
name: 'Fred Perry Bomber jacket',
price: '1015.00'
}
]
},
relatedGoods: {
relatedTitle: '推荐搭配',
goods: [
{
img: 'http://placehold.it/274x366',
link: '',
name: 'Fred Perry Bomber jacket',
price: '1015.00'
},
{
img: 'http://placehold.it/274x366',
link: '',
name: 'Fred Perry Bomber jacket',
price: '1015.00'
},
{
img: 'http://placehold.it/274x366',
link: '',
name: 'Fred Perry Bomber jacket',
price: '1015.00'
},
{
img: 'http://placehold.it/274x366',
link: '',
name: 'Fred Perry Bomber jacket',
price: '1015.00'
}
]
}
},
brands: {
relatedTitle: '推荐搭配',
relatedBrands: [
{
url: 'http://placehold.it/274x366',
thumb: 'wed',
name: 'Fred Perry'
},
{
url: 'http://placehold.it/274x366',
thumb: 'wed',
name: 'Fred Perry'
},
{
url: 'http://placehold.it/274x366',
thumb: 'wed',
name: 'Fred Perry'
},
{
url: 'http://placehold.it/274x366',
thumb: 'wed',
name: 'Fred Perry'
},
editorialModel.getDetailData(id).then((result) => {
res.display('detail', {
module: 'editorial',
page: 'detail',
title: '资讯详情',
editorialDetail: {
nav: [
{
url: 'http://placehold.it/274x366',
thumb: 'wed',
name: 'Fred Perry'
link: '/editorial?type=0',
pathTitle: '首页',
name: 'MEN首页'
},
{
url: 'http://placehold.it/274x366',
thumb: 'wed',
name: 'Fred Perry'
link: '/editorial?type=1',
pathTitle: '资讯',
name: '资讯'
},
{
url: 'http://placehold.it/274x366',
thumb: 'wed',
name: 'Fred Perry'
pathTitle: '资讯',
name: result.head.title
}
]
},
userInfo: {
likeNum: '10'
},
share: {
shareImg: 'hjchsk',
shareDesc: 'wjhdfwe',
weixinUrl: 'http://www.baidu.com'
},
tag: [
{
name: '户外'
},
{
name: '户外'
},
{
name: '户外'
},
{
name: '户外'
],
header: result.head,
content: result.content,
tags: result.tags,
userInfo: result.head,
comment: result.comment,
brands: result.brands,
article: {
nextChapter: '来来来,让我们好好聊聊',
lastChapter: '除了黑白灰'
},
{
name: '户外'
// content: {
// goods: [
// {
// img: 'http://placehold.it/274x366',
// link: '',
// name: 'Fred Perry Bomber jacket',
// price: '1015.00'
// }
// ]
// },
// relatedGoods: {
// relatedTitle: '推荐搭配',
// goods: [
// {
// img: 'http://placehold.it/274x366',
// link: '',
// name: 'Fred Perry Bomber jacket',
// price: '1015.00'
// }
//
// ]
// }
// },
// brands: [
// {
// url: 'http://placehold.it/274x366',
// thumb: 'wed',
// name: 'Fred Perry'
// },
// {
// url: 'http://placehold.it/274x366',
// thumb: 'wed',
// name: 'Fred Perry'
// },
// {
// url: 'http://placehold.it/274x366',
// thumb: 'wed',
// name: 'Fred Perry'
// },
// {
// url: 'http://placehold.it/274x366',
// thumb: 'wed',
// name: 'Fred Perry'
// }
// ],
share: {
shareImg: 'hjchsk',
shareDesc: 'wjhdfwe',
weixinUrl: 'www.baidu.com'
}
],
nextChapter: 'hbrfbhwej',
lastChapter: 'fwehjfdw',
comment: {
commentNum: '4',
list: [
{
avatar: '#',
name: 'rcfse',
content: 'cec',
time: 'efrf'
},
{
avatar: '#',
name: 'rcfse',
content: 'cec',
time: 'efrf'
}
]
},
helpers: {
// import component, path depends on your project
pagination: require('../../../doraemon/components/pagination/pagination').createPagination
}
},
helpers: {
// import component, path depends on your project
pagination: require('../../../doraemon/components/pagination/pagination').createPagination
}
});
});
}).catch(next);
};
// });
let setCollect = (req, res, next) => {
let uid = req.user.uid;
let id = req.params.id || 52571;
editorialModel.setCollect(id, uid).then((result) => {
res.json(result);
}).catch(next);
};
let cancelCollect = (req, res, next) => {
let uid = req.user.uid;
let id = req.params.id || 52571;
editorialModel.setCollect(id, uid).then((result) => {
res.json(result);
}).catch(next);
};
// 点赞
let setPraise = (req, res, next) => {
let udid = req.user.uid;
let id = req.params.id || 52571;
editorialModel.setPraise(id, udid).then((result) => {
res.json(result);
}).catch(next);
};
let cancelPraise = (req, res, next) => {
let udid = req.user.uid;
let id = req.params.id || 52571;
editorialModel.cancelPraise(id, udid).then((result) => {
res.json(result);
}).catch(next);
};
let addComment = (req, res, next) => {
let uid = req.user.uid;
let id = req.params.id || 52571;
let content = req.body.content;
editorialModel.setCollect(id, uid, content).then((result) => {
res.json(result);
}).catch(next);
};
module.exports = {
index, // 资讯页
list,
detail
detail,
setCollect,
cancelCollect,
setPraise,
cancelPraise,
addComment
};
... ...
... ... @@ -4,6 +4,8 @@ const serviceAPI = global.yoho.ServiceAPI;
// const api = global.yoho.API;
const camelCase = global.yoho.camelCase;
const _ = require('lodash');
const Promise = require('bluebird');
const co = Promise.coroutine;
// const moment = require('moment');
const logger = global.yoho.logger;
... ... @@ -38,6 +40,12 @@ const _processListData = (list) => {
data.publishTime = data.publishTime.replace(/年|月/g, '/');
data.publishTime = data.publishTime.replace(/日/g, '');
if (data.isPraise === 'N') {
data.isPraise = false;
} else {
data.isPraise = true;
}
return data;
});
... ... @@ -57,19 +65,23 @@ const _getResources = (type) => {
});
};
const _getBreakingSort = () => {
return serviceAPI.get('guang/api/*/article/getList', {}).then((result) => {
const _getBreakingSort = (type, pageNum, limit) => {
return serviceAPI.get('guang/api/*/article/getList', {
sort_id: type,
page: pageNum,
limit: limit
}).then((result) => {
if (result && result.code === 200) {
return _processListData(result.data);
} else {
logger.error('资讯列表数据返回 code 不是 200');
logger.error('资讯首页列表数据返回 code 不是 200');
return {};
}
});
};
const getIndexData = (type) => {
return Promise.all([_getResources(type), _getBreakingSort()])
const getIndexData = (type, pageNum, limit) => {
return Promise.all([_getResources(type), _getBreakingSort(type, pageNum, limit)])
.then((result) => {
return {
msgTypes: result[0],
... ... @@ -78,8 +90,13 @@ const getIndexData = (type) => {
});
};
const getListData = () => {
return serviceAPI.get('guang/api/*/article/getList', {}).then((result) => {
const getListData = (pageNum, limit, tag, authorId) => {
return serviceAPI.get('guang/api/*/article/getList', {
page: pageNum,
limit: limit,
tag: tag,
author_id: authorId
}).then((result) => {
if (result && result.code === 200) {
return _processListData(result.data);
} else {
... ... @@ -89,8 +106,313 @@ const getListData = () => {
});
};
// 详情页
const _getAuthorData = (id) => {
return serviceAPI.get('/guang/service/*/author/getAuthor', {
author_id: id
}).then((result) => {
if (result && result.code === 200) {
return result.data;
} else {
logger.error('作者信息返回 code 不是 200');
return {};
}
});
};
const _processHeadData = (list) => {
return co(function*() {
list = list || [];
list = camelCase(list);
let newData = {
headData: {},
tags: []
};
_.forEach(list, function(data, index) {
if (index === 0) {
if (data.isPraise === 'N') {
data.isPraise = false;
} else {
data.isPraise = true;
}
if (data.isFavor === 'N') {
data.isFavor = false;
} else {
data.isFavor = true;
}
newData.headData = {
title: data.intro,
click: data.viewNum,
time: data.publishTime,
isLike: data.isPraise,
isFavor: data.isFavor,
likeNum: data.praiseNum
};
}
if (index === 1) {
newData.headData = _.assign(newData.headData, {
authorId: data.authorId
});
_.forEach(data.tags, function(value) {
value.url = `/editorial/list/?query=${value.name}`;
});
newData.tags = data.tags;
}
if (index === 2) {
newData.headData = _.assign(newData.headData, {
commentNum: data.total
});
}
});
newData.headData.time = newData.headData.time.replace(/-/g, '/');
newData.headData.time = newData.headData.time.replace(':00', '', 2);
let id = newData.headData.authorId;
let data = yield _getAuthorData(id);
newData.headData = _.assign(newData.headData, {
authorUrl: data.url,
avatar: data.avatar,
name: data.name
});
return newData;
})();
};
// const _getGoodsSort = (skn) => {
// return api.get('', {
// product_skn: 51137901,
// method: 'h5.product.data'
// }).then((result) => {
// if (result && result.code === 200) {
// console.log(result)
// return result;
// } else {
// logger.error('数据返回 code 不是 200');
// return {};
// }
// });
// };
const _processContentData = (list) => {
list = list || [];
list = camelCase(list);
_.forEach(list, function(data) {
if (data.text) {
data.text.data.text = data.text.data.text.replace(/<.*?>/ig, '');
}
// if (data.goods) {
// console.log(data.goods)
// _.forEach(data.goods, function(data, index) {
// console.log(index)
// _.forEach(data, function(value) {
// // console.log(value)
// // // _getGoodsSort(value.id);
// });
// });
// }
});
return list;
};
// // const _processCommentsData = (list) => {
// // list = list || [];
// // list = camelCase(list);
// // //let commentNum = list.list.length;
// // console.log(list)
// // }
// // head数据
const _getHeadData = (id) => {
return serviceAPI.get('/guang/api/*/article/getArticleBaseInfo', {
id: id
}).then((result) => {
if (result && result.code === 200) {
return result.data;
} else {
logger.error('资讯详情head数据返回 code 不是 200');
return {};
}
});
};
// // content数据
const _getContentData = (id) => {
return serviceAPI.get('/guang/service/*/article/getArticleContent', {
article_id: id
}).then((result) => {
if (result && result.code === 200) {
return _processContentData(result.data);
} else {
logger.error('资讯详情内容数据返回 code 不是 200');
return {};
}
});
};
// // 文章信息
const _getArticleData = (id) => {
return serviceAPI.get('/guang/service/v2/article/getArticle', {
article_id: id
}).then((result) => {
if (result && result.code === 200) {
return result.data;
} else {
logger.error('资讯详情内容数据返回 code 不是 200');
return {};
}
});
};
// 评论列表
const _getCommentsData = (id) => {
return serviceAPI.get('/guang/api/*/comments/getList', {
article_id: id
}).then((result) => {
if (result && result.code === 200) {
return camelCase(result.data);
} else {
logger.error('评论内容数据返回 code 不是 200');
return {};
}
});
};
// 相关品牌
const _getRelateBrand = (id) => {
return serviceAPI.get('guang/service/v2/article/getBrand', {
article_id: id
}).then((result) => {
if (result && result.code === 200) {
return camelCase(result.data);
} else {
logger.error('相关文章数据返回 code 不是 200');
return {};
}
});
};
// 资讯收藏
const setCollect = (id, uid) => {
if (!uid) {
return Promise.resolve({
code: 400,
message: '未登录'
});
}
return serviceAPI.get('/guang/api/*/favorite/setFavorite', {
article_id: id,
uid: uid
});
};
// 取消收藏
const cancelCollect = (id, uid) => {
if (!uid) {
return Promise.resolve({
code: 400,
message: '未登录'
});
}
return serviceAPI.get('/guang/api/*/favorite/cancelFavorite', {
article_id: id,
uid: uid
});
};
// 点赞
const setPraise = (id, udid) => {
return serviceAPI.get('/guang/api/*/praise/setPraise', {
article_id: id,
udid: udid
});
};
// 取消点赞
const cancelPraise = (id, udid) => {
return serviceAPI.get('/guang/api/*/praise/cancel', {
article_id: id,
udid: udid
});
};
// 添加评论
const addComment = (id, uid, comment) => {
if (!uid) {
return Promise.resolve({
code: 400,
message: '未登录'
});
}
return serviceAPI.get('/guang/api/*/comments/add', {
article_id: id,
uid: uid,
content: comment
});
};
const getDetailData = (id) => {
return co(function *() {
let result = yield Promise.all([_getHeadData(id),
_getArticleData(id),
_getContentData(id),
_getCommentsData(id),
_getRelateBrand(id)]);
let res = yield _processHeadData([result[0], result[1], result[3]]);
return {
head: res.headData,
tags: res.tags,
content: result[2],
comment: result[3],
brands: result[4]
};
})();
};
module.exports = {
getIndexData,
getListData
getListData,
getDetailData,
setCollect,
cancelCollect,
setPraise,
cancelPraise,
addComment
};
... ...
... ... @@ -12,6 +12,13 @@ const editorial = require(cRoot + '/editorial');
router.get('/', editorial.index); // 资讯首页
router.get('/list', editorial.list); // 资讯列表页
router.get('/detail', editorial.detail);// 资讯详情页
router.get('/(:id).html', editorial.detail);// 资讯详情页
// router.get(/\/([\d]+).html/, editorial.detail);
router.post('/info/collect', editorial.setCollect);// 资讯收藏
router.post('/info/cancelcollect', editorial.cancelCollect);// 资讯取消收藏
router.get('/info/praise', editorial.setPraise);// 点赞
router.get('/info/cancelPraise', editorial.cancelPraise);// 取消点赞
router.post('/info/comment', editorial.addComment);// 添加评论
module.exports = router;
... ...
... ... @@ -27,35 +27,46 @@
<div class="article-main">
{{# content}}
{{# pic}}
{{# singleImage}}
{{# data}}
<div class="article-pic block">
<img src="{{img}}">
<img src="{{image src 930 660}}">
</div>
{{/ pic}}
{{/ data}}
{{/ singleImage}}
{{# text}}
<div class="article-text block">
<p>{{articleText}}</p>
{{# data}}
<p>{{text}}</p>
{{/ data}}
</div>
{{/ text}}
{{# relatedReco}}
{{# goodsGroup}}
<div class="related-reco">
{{> article-related}}
<div class="article-title">
<div class="title-line"></div>
<div class="text-center">
<div class="text">
<span>推荐搭配</span>
</div>
</div>
</div>
<div class="related-goods">
{{# goods}}
{{# list}}
{{> goods}}
{{/ goods}}
{{/ list}}
</div>
</div>
{{/ relatedReco}}
{{/ goodsGroup}}
{{# relatedGoods}}
<div class="related-reco">
{{> article-related}}
<div class="related-goods">
{{# goods}}
{{# goods}}
{{> goods}}
{{/ goods}}
</div>
... ... @@ -64,36 +75,40 @@
{{/ content}}
{{#if brands}}
{{# brands}}
<div class="related-brand">
{{> article-related}}
<div class="brands">
{{# relatedBrands}}
<div class="brand">
<a class="thumb" href="{{url}}" target="_blank">
<img src="{{thumb}}">
</a>
<p class="brand-name">{{name}}</p>
<div class="article-title">
<div class="title-line"></div>
<div class="text-center">
<div class="text">
<span>相关品牌</span>
</div>
{{/ relatedBrands}}
</div>
</div>
<div class="brands">
{{# brands}}
<div class="brand">
<a class="thumb" href="{{url}}" target="_blank">
<img src="{{thumb}}">
</a>
<p class="brand-name">{{name}}</p>
</div>
{{/ brands}}
</div>
</div>
{{/brands}}
{{/if}}
</div>
{{# userInfo}}
<div class="user-handle">
<ul class="clearfix">
<li id="prise-btn" class="like-status{{#isLike}} liked{{/isLike}}">
<li id="prise-btn" class="like-status{{# isLike}} liked{{/ isLike}}">
<a href="javascript:;">
<i class="iconfont">&#xe60e;</i>
<span class="like-num">{{likeNum}}</span>
</a>
</li>
<li id="collect-btn" class="sort-collect{{#isCollected}} collected{{/isCollected}}">
<li id="collect-btn" class="sort-collect{{# isCollected}} collected{{/ isCollected}}">
<a href="javascript:;">
<i class="iconfont">&#xe619;</i>
<span>收藏</span>
... ... @@ -104,19 +119,20 @@
{{/ userInfo}}
{{> share}}
<div class="article-tag">
<i class="tag-icon iconfont">&#xe615;</i>
<i class="tag-icon iconfont">&#xe648;</i>
<ul>
{{# tag}}
{{# tags}}
<li>
<a href="{{url}}" target="_blank">{{name}}</a>
</li>
{{/ tag}}
{{/ tags}}
</ul>
</div>
<div class="chapter">
{{# article}}
<p class="chapter-right">
<span>下一篇</span><br>
<a href="{{href}}">{{nextChapter}}</a>
... ... @@ -125,6 +141,7 @@
<span>上一篇</span><br>
<a href="{{href}}">{{lastChapter}}</a>
</p>
{{/ article}}
</div>
<div id="comment-area" class="comment-area">
... ... @@ -142,4 +159,4 @@
</div>
{{/ editorialDetail}}
</div>
\ No newline at end of file
</div>
... ...
{{# comment}}
<h4>
<span class="comment-num">{{commentNum}}</span>
<span class="comment-num">{{total}}</span>
条评论
</h4>
<p class="comments-empty">还没有评论,快抢沙发吧</p>
... ... @@ -9,12 +9,12 @@
{{# list}}
<li class="clearfix">
<div class="author">
<img class="comment-user-avatar" src="{{avatar}}" alt="">
<p class="comment-user-name">{{name}}</p>
<img class="comment-user-avatar" src="{{avator}}" alt="">
<p class="comment-user-name">{{username}}</p>
</div>
<div class="comment-info">
<p class="comment-content">{{content}}</p>
<p class="comment-time">{{time}}</p>
<p class="comment-time">{{createTime}}</p>
</div>
</li>
{{/ list}}
... ...
<div class="content-msg clearfix" data-id="{{id}}">
<div class="msg-left">{{categoryName}}</div>
<div class="msg-right">
<a class="msg-title" href="{{url}}" target="_blank">{{title}}</a>
<a href="{{url}}" target="_blank">
<a class="msg-title" href="/editorial/{{id}}.html" target="_blank">{{title}}</a>
<a href="/editorial/{{id}}.html" target="_blank">
<img src="{{image src 640 430 1}}">
</a>
<div class="content">{{intro}}</div>
... ... @@ -12,7 +12,7 @@
<b class="time-word">{{publishTime}}</b>
</span>
<span class="like-comment">
<i class="iconfont like-icon{{#if isPraise}} liked{{/if}}">&#xe60e;</i>
<i class="iconfont like-icon{{#if isPraise}}liked{{/if}}">&#xe60e;</i>
<b class="like-num">{{praiseNum}}</b>
</span>
</div>
... ...
/**
* [个人中心]个人设置-账号安全部分
* @author: jiangmin
* @date: 2016/07/13
*/
'use strict';
const accountModel = require('../models/account');
/**
* 修改密码
* @param req
* @param res
*/
const changePwd = (req, res) => {
let uid = req.user.uid;
// let uid = req.user.uid||"20000190" ;
let pwd = req.body.password;
accountModel.changePwd(uid, pwd).then(result=> {
// console.log("修改result", result);
res.send(result);
});
};
/**
* 验证手机号码
* @param req
* @param res
*/
const checkVerifyMobile = (req, res)=> {
let uid = req.user.uid;
// let uid = req.user.uid||"20000190";
let mobile = req.body.mobile;
let area = req.body.area;
// console.log(uid, mobile, area);
accountModel.checkVerifyMobile(uid, mobile, area).then(result=> {
// console.log("验证手机号码", result);
res.send(result);
});
};
/**
* 发送短信
* @param req
* @param res
*/
const sendMobileMsg = (req, res)=> {
let uid = req.user.uid;
// let uid = req.user.uid||"20000190";
let mobile = req.body.mobile;
let area = req.body.area || '+86';
// console.log(uid, mobile, area);
accountModel.sendMobileMsg(uid, mobile, area).then(result=> {
// console.log("发送短信result", result);
res.send(result);
});
};
/**
* 验证短信
* @param req
* @param res
*/
const checkVerifyMsg = (req, res)=> {
let code = req.body.code;
let mobile = req.body.mobile;
let area = req.body.area || '+86';
accountModel.checkVerifyMsg(code, mobile, area).then(result=> {
// console.log("短信验证result", result);
res.send(result);
});
};
/**
* 发送验证邮件
* @param req
* @param res
*/
const sendVerifyEmail = (req, res)=> {
let uid = req.user.uid;
// let uid = req.user.uid||"20000190";
let email = req.body.email;
accountModel.sendVerifyEmail(uid, email).then(result=> {
// console.log("发送验证邮件result", result);
res.send(result);
});
};
module.exports = {
changePwd: changePwd,
sendMobileMsg: sendMobileMsg,
checkVerifyMsg: checkVerifyMsg,
sendVerifyEmail: sendVerifyEmail,
checkVerifyMobile: checkVerifyMobile
};
... ...
... ... @@ -21,25 +21,25 @@ const _setDefault = (id, uid) => {
* 收货地址页面加载
*/
const index = (req, res, next) => {
let uid = req.user.uid || '123456';
let uid = req.user.uid || '20000190';
addressModel.getAddressDataAsync(uid, 20).then(result => {
let resultData = result.data;
let resultData = result.data ? result.data : result;
let length = resultData.length ? resultData.length : 0;
for (let i = 0; i < length; i++) {
resultData[i].default = resultData[i].is_default === 'Y';
resultData[i].mobile = resultData[i].mobile.substring(0, 3) + '****' +
resultData[i].mobile.substring(7, 11);
}
resultData.leftLength = 20 - length;
resultData.leftLength = 7 - length;
resultData.length = length;
res.render('index', {
res.display('index', {
module: 'me',
page: 'address',
isMe: true,
content: {
nav: mcHandler.getMeCrumb(),
nav: mcHandler.getMeCrumb('收货地址'),
navigation: mcHandler.getSideMenu('收货地址'),
banner: 'http://placehold.it/150x120',
address: true,
... ... @@ -50,44 +50,32 @@ const index = (req, res, next) => {
}).catch(next);
};
const getAddressList = (req, res) => {
addressModel.getAddressDataAsync('7566245', 20).then(result => {
const getAddressList = (req, res, next) => {
addressModel.getAddressDataAsync(req.user.uid, 20).then(result => {
if (result.data) {
let defaultAd = _.find(result.data, o => o.is_default === 'Y');
defaultAd && (defaultAd.focus = true);
}
res.send(result);
});
}).catch(next);
};
/**
* 添加地址
*/
const addAddressData = (req, res) => {
let uid = req.user.uid || '123456';
let uid = req.user.uid;
let address = req.body.address;
let areaCode = req.body.area_code;
let consignee = req.body.consignee;
let mobile = req.body.mobile;
let phone = req.body.phone;
let isInit = req.body.init; // 是否是初始地址
addressModel.addAddressData(uid, address, areaCode, consignee, mobile, phone).then(result => {
if (isInit) {
_setDefault(uid, result.data.id).then(defaultResult => {
if (defaultResult.code === 200) {
Object.assign(result.data, {
is_default: 'Y'
});
let isInit = req.body.init && req.body.init === 'true'; // 是否是初始地址
res.send(result);
}
});
} else {
res.send(result);
}
addressModel.addAddressData(uid, address, areaCode, consignee, mobile, phone, isInit).then(result => {
res.send(result);
});
};
... ... @@ -96,7 +84,7 @@ const addAddressData = (req, res) => {
*/
const updateAddressData = (req, res) => {
let id = req.body.id;
let uid = req.user.uid || '123456';
let uid = req.user.uid;
let address = req.body.address;
let areaCode = req.body.area_code;
let consignee = req.body.consignee;
... ... @@ -113,7 +101,7 @@ const updateAddressData = (req, res) => {
*/
const delAddressData = (req, res) => {
let id = req.body.id;
let uid = req.user.uid || '123456';
let uid = req.user.uid;
addressModel.delAddressData(id, uid).then(result => {
res.send(result);
... ... @@ -125,7 +113,7 @@ const delAddressData = (req, res) => {
*/
const setDefaultAddress = (req, res) => {
let id = req.body.id;
let uid = req.user.uid || '123456';
let uid = req.user.uid;
_setDefault(id, uid).then(result => {
res.send(result);
... ...
... ... @@ -18,15 +18,14 @@ const convertUnitTime = (src) => {
* yoho币页面加载
*/
const index = (req, res) => {
let uid = req.user.uid || '8041246';
var page = parseInt(req.query.page) || 1;
var queryType = parseInt(req.query.queryType) || 0;
var uid = req.user.uid;
var page = parseInt(req.query.page, 10) || 1;
var queryType = parseInt(req.query.queryType, 10) || 0;
var beginTime = req.query.beginTime || convertUnitTime(new Date() / 1000 - 3600 * 24 * 90);
var date1 = new Date().getTime() / 1000;
var date2 = new Date(beginTime).getTime() / 1000;
var selectIndex = parseInt((date1 - date2) / (3600 * 24 * 30 * 6));
var selectIndex = parseInt((date1 - date2) / (3600 * 24 * 30 * 6), 10);
console.log('请求参数:', 'page:' + page, 'queryType:' + queryType, 'beginTime:' + beginTime);
currencyModel.getIndexData(uid, page, queryType, beginTime).then(result=> {
result.list.tabs[queryType].isActive = true;
result.list.coinList.forEach(function(x) {
... ... @@ -39,14 +38,14 @@ const index = (req, res) => {
beginTime: beginTime
};
}
console.log('返回个数:' + result.list.total);
res.render('index', {
res.display('index', {
module: 'me',
page: 'currency',
isMe: true,
content: {
nav: mcHandler.getMeCrumb(),
navigation: mcHandler.getSideMenu('YOHO币'),
nav: mcHandler.getMeCrumb('我的YOHO币'),
navigation: mcHandler.getSideMenu('我的YOHO币'),
banner: 'http://placehold.it/150x120',
currency: true,
tabs: result.list.tabs,
... ... @@ -56,7 +55,7 @@ const index = (req, res) => {
paginationOpts: result.list.paginationOpts,
num: result.num.data,
selects: result.list.selects,
total: result.list.total
total: result.list.total ? result.list.total : 0
}
});
});
... ...
/**
* 我的收藏
* @author: jiangfeng<jeff.jiang@yoho.cn>
* @date: 2016/7/19
*/
'use strict';
const _ = require('lodash');
const cookie = global.yoho.cookie;
const camelCase = global.yoho.camelCase;
const config = global.yoho.config;
const mcHandler = require('../models/menu-crumb-handler');
const FavoriteData = require('../models/favorite');
const favorite = {
// 商品收藏页
goods(req, res, next) {
let q = req.query;
let page = parseInt(q.page || 1, 10);
let uid = cookie.getUid(req);
let sort = q.sort ? parseInt(q.sort, 10) : '';
let ret = {
module: 'me',
page: 'favorite',
title: '我的收藏',
isMe: true,
content: {
nav: mcHandler.getMeCrumb('我的收藏'),
navigation: mcHandler.getSideMenu('我的收藏'),
banner: 'http://placehold.it/150x120',
collection: true,
favorite: {
product: true,
title: '我的收藏'
}
}
};
FavoriteData.getFavoriteProduct({
page: 1,
limit: 500,
uid: uid
}).then(result => {
if (result && result.code === 200 && result.data) {
let data = camelCase(result.data);
let retData = {
siteUrl: config.siteUrl
};
retData.total = data.total;
retData.paginationData = {
page: page,
limit: 16,
total: data.total,
pageTotal: (data.total % 16 === 0 ? data.total / 16 : data.total / 16 + 1),
queryParams: q
};
retData.categoryList = data.categoryList;
retData.categoryList.unshift({
categoryId: '',
categoryName: '全部商品',
num: data.total
});
retData.categoryList.forEach(c => {
c.checked = c.categoryId === sort;
});
retData.products = data.productList.filter(p => {
return !sort || sort === p.categoryId;
}).slice((page - 1) * 16, page * 16);
retData.products.forEach(p => {
if (p.status === 0) {
p.stateText = '已下架';
}
if (p.storage === 0) {
p.stateText = '已售罄';
}
p.url = `/product/pro_${p.productId}_${p.goodsId}/${p.cnAlphabet}.html`;
p.imageUrl = p.image;
});
ret.content.favorite.data = retData;
}
res.display('index', ret);
}).catch(next);
},
brand(req, res, next) {
let q = req.query;
let page = parseInt(q.page || 1, 10);
let uid = cookie.getUid(req);
let limit = 5;
let ret = {
module: 'me',
page: 'favorite.brand',
title: '我的收藏',
isMe: true,
content: {
nav: mcHandler.getMeCrumb('我的收藏'),
navigation: mcHandler.getSideMenu('我的收藏'),
banner: 'http://placehold.it/150x120',
collection: true,
favorite: {
brand: true,
title: '我的收藏'
}
}
};
FavoriteData.getFavoriteBrand({
page: page,
limit: limit,
uid: uid
}).then(result => {
if (result && result.code === 200 && result.data) {
let data = camelCase(result.data);
let retData = {
siteUrl: config.siteUrl
};
retData.total = data.total;
retData.paginationData = {
page: page,
limit: limit,
total: data.total,
pageTotal: data.pageTotal,
queryParams: q
};
retData.brandList = data.brandList;
retData.brandList.forEach(b => {
b.newProduct.forEach(p => {
p.url = `${config.siteUrl}/product/pro_${p.productId}_${p.goods[0].id}/${p.cnAlphabet}.html`;
});
b.newProduct.push({
more: true
});
b.newProduct = _.chunk(b.newProduct, 4);
});
ret.content.favorite.data = retData;
}
res.display('index', ret);
}).catch(next);
},
editorial(req, res, next) {
let q = req.query;
let page = parseInt(q.page || 1, 10);
let uid = cookie.getUid(req);
let limit = 5;
let ret = {
module: 'me',
page: 'favorite.editorial',
title: '我的收藏',
isMe: true,
content: {
nav: mcHandler.getMeCrumb('我的收藏'),
navigation: mcHandler.getSideMenu('我的收藏'),
banner: 'http://placehold.it/150x120',
collection: true,
favorite: {
editorial: true,
title: '我的收藏'
}
}
};
FavoriteData.getFavoriteEditoreial({
uid: uid,
page: page,
limit: limit
}).then(result => {
if (result && result.code === 200 && result.data) {
let data = camelCase(result.data);
let retData = {
siteUrl: config.siteUrl,
editorialList: data.data
};
retData.total = data.total;
retData.paginationData = {
page: page,
limit: limit,
total: data.total,
pageTotal: data.totalPage,
queryParams: q
};
ret.content.favorite.data = retData;
}
res.display('index', ret);
}).catch(next);
},
cancel(req, res, next) {
let type = req.body.type;
let ids = req.body.ids;
let uid = cookie.getUid(req);
FavoriteData.cancelFavorite(uid, ids, type).then(result => {
if (result && result.code === 200) {
res.json({code: 200});
} else {
res.json({code: 400});
}
}).catch(next);
},
editorialCancel(req, res, next) {
let ids = req.body.ids;
let uid = cookie.getUid(req);
FavoriteData.cancelEditorialFavorite(uid, ids).then(result => {
if (result && result.code === 200) {
res.json({code: 200});
} else {
res.json({code: 400});
}
}).catch(next);
}
};
module.exports = favorite;
... ...
... ... @@ -58,7 +58,9 @@ const getOrderList = (req, res) => {
page: 'order',
isMe: true,
orderList: result.order.orderList,
paginationOpts: result.order.paginationOpts
paginationOpts: result.order.paginationOpts,
emptyMsg: result.order.emptyMsg,
showEmptyEn: result.order.showEmptyEn
});
});
};
... ... @@ -79,9 +81,9 @@ const getOrderTotal = (req, res) => {
const cancelOrder = (req, res) => {
const uid = req.user.uid || '10931021';
const code = req.query.orderCode;
const data = req.query;
orderModel.cancelOrder(uid, code).then(result => {
orderModel.cancelOrder(uid, data).then(result => {
res.json(result);
});
};
... ... @@ -121,14 +123,24 @@ const editOrder = (req, res) => {
});
};
const reAdd = (req, res) => {
const uid = req.user.uid || '10931021';
const code = req.query.orderCode;
orderModel.reAddCart(uid, code).then(result => {
res.json(result);
});
};
module.exports = {
index: index,
detail: detail,
getOrderList: getOrderList,
getOrderTotal: getOrderTotal,
cancelOrder: cancelOrder,
deleteOrder: deleteOrder,
editOrder: editOrder,
getExpressInfo: getExpressInfo,
getCancelOrderReason: getCancelOrderReason
index,
detail,
getOrderList,
getOrderTotal,
cancelOrder,
deleteOrder,
editOrder,
getExpressInfo,
getCancelOrderReason,
reAdd
};
... ...
... ... @@ -41,7 +41,7 @@ const refund = (req, res, next) => {
returns.getRefundGoodsData(code, uid).then(result => {
res.display('index', {
page: 'returns-refund',
page: 'refund',
content: result
});
}).catch(next);
... ... @@ -76,7 +76,7 @@ const refundDetail = (req, res, next) => {
returns.getRefundDetailData(applyId, uid).then(result => {
res.display('index', {
page: 'refund',
page: 'refund-detail',
content: result
});
}).catch(next);
... ...
/**
* [个人中心]个人设置
* @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;
const captchaUrl = helpers.urlFormat('/passport/images', {t: Date.now()});
// const captchaUrl = 'http://localhost:6003/passport/images?t=' + new Date().getTime();
// 根据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;
// let uid = req.user.uid || "20000190";
settingModel.getUserInfo(uid).then(result=> {
result.info.gender ? result.genders[result.info.gender - 1].checked = true :
result.genders[2].checked = true;
result.info.head_ico = result.info.head_ico ? helpers.image(result.info.head_ico, 400, 300, 2) : '';
result.info.mobile = result.info.mobile ?
result.info.mobile.substring(0, 3) + '****' + result.info.mobile.substring(7, 11) : '';
result.stepUrl = '/me/setting/step1';
res.display('index', {
module: 'me',
page: 'setting',
isMe: true,
content: {
nav: mcHandler.getMeCrumb('个人设置'),
navigation: mcHandler.getSideMenu('个人设置'),
banner: 'http://placehold.it/150x120',
setting: true,
title: '个人设置',
userInfo: result
}
});
}).catch(next);
};
/**
* 编辑信息
* @param req
* @param res
*/
const editUserInfo = (req, res)=> {
let uid = req.user.uid;
// let uid = req.user.uid || "20000190";
let query = req.body;
settingModel.editUserInfo(uid, query).then(result=> {
res.send(result);
});
};
/*
* step1
* */
const bindMobile = (req, res, next) => {
let uid = req.user.uid;
// let uid = req.user.uid || "20000190";
let type = req.params.type;
settingModel.getUserInfo(uid).then(result=> {
if (result.info.verify_mobile !== '') {
let info = result.info;
info.ellipsisMobile = info.verify_mobile.substring(0, 3) + '****' + info.verify_mobile.substring(7, 11);
info.checkCode = settingModel.cipheriv(info.uid + '.completeverify');
// info.checkCode = settingModel.cipheriv("20000190" + ".completeverify");
res.display('index', {
module: 'me',
page: 'setting',
isMe: true,
content: {
region: passportHelper.getCountry(),
location: '+86',
nav: mcHandler.getMeCrumb('个人设置'),
navigation: mcHandler.getSideMenu('个人设置'),
banner: 'http://placehold.it/150x120',
validateStep: true,
title: _getTitle(type).typeName,
proTitle: _getTitle(type).proName,
captchaUrl: captchaUrl,
isShowMobile: true,
data: info
}
});
}
next();
});
};
const bindEmail = (req, res, next) => {
let uid = req.user.uid;
// let uid = req.user.uid || "20000190";
let type = req.params.type;
settingModel.getUserInfo(uid).then(result=> {
if (result.info.verify_email !== '') {
let info = result.info;
info.ellipsisEmail = info.verify_email.substring(0, 3) + '****' + info.verify_email.substring(7, 11);
info.checkCode = settingModel.cipheriv(info.uid + '.completeverify');
// info.checkCode = settingModel.cipheriv("20000190" + ".completeverify");
res.display('index', {
module: 'me',
page: 'setting',
isMe: true,
content: {
nav: mcHandler.getMeCrumb('个人设置'),
navigation: mcHandler.getSideMenu('个人设置'),
banner: 'http://placehold.it/150x120',
validateStep: true,
title: _getTitle(type).typeName,
proTitle: _getTitle(type).proName,
captchaUrl: captchaUrl,
isShowEmail: true,
data: info
}
});
}
next();
});
};
const modifyPassword = (req, res) => {
let type = req.params.type;
let checkCode = settingModel.cipheriv(req.user.uid + '.completeverify');
// let checkCode = settingModel.cipheriv("20000190" + ".completeverify");
res.display('index', {
module: 'me',
page: 'setting',
isMe: true,
content: {
nav: mcHandler.getMeCrumb('个人设置'),
navigation: mcHandler.getSideMenu('个人设置'),
banner: 'http://placehold.it/150x120',
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') {
// if (codes[0] === "20000190" && 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');
// let checkCode = settingModel.cipheriv("20000190"+ ".completeoperate");
res.display('index', {
module: 'me',
page: 'setting',
isMe: true,
content: Object.assign({
region: passportHelper.getCountry(),
location: '+86',
nav: mcHandler.getMeCrumb('个人设置'),
navigation: mcHandler.getSideMenu('个人设置'),
banner: 'http://placehold.it/150x120',
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') {
// if (codes[0] === "20000190" && 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
};
res.display('index', {
module: 'me',
page: 'setting',
isMe: true,
content: Object.assign({
region: passportHelper.getCountry(),
location: '+86',
nav: mcHandler.getMeCrumb('个人设置'),
navigation: mcHandler.getSideMenu('个人设置'),
banner: 'http://placehold.it/150x120',
successStep: true,
captchaUrl: captchaUrl
}, result)
});
}
};
/*
* post1
* */
const validate1 = (req, res)=> {
co(function *() {
let type = req.params.type;
// let uid = req.user.uid || "20000190";
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
* */
const validate2 = (req, res)=> {
co(function *() {
let type = req.params.type;
let uid = req.user.uid;
// let uid = req.user.uid || "20000190";
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('')
});
}
}
})();
};
module.exports = {
index,
editUserInfo,
bindMobile,
bindEmail,
modifyPassword,
edit,
success,
validate1,
validate2
};
... ...
/**
* [个人中心]个人设置-账户安全部分
* @author: jiangmin
* @date: 2016/07/13
*/
'use strict';
const api = global.yoho.API;
/**
* 验证用户登录密码是否正确
* @param uid
* @param password
* @return type
*/
const verifyPwd = (uid, password)=> {
return api.get('', {
method: 'web.passport.verifyUserPwd',
uid: uid,
password: password
}).then(result => result);
};
/**
* 修改密码
* @param uid
* @param pwd
* @returns {*}
* @private
*/
const changePwd = (uid, pwd)=> {
return api.get('', {
method: 'web.passport.changePwd',
uid: uid,
newPassword: pwd
}).then(result => result);
};
/**
* 发送手机验证
* @param uid
* @param mobile
* @param area
*/
const sendMobileMsg = (uid, mobile, area)=> {
return api.get('', {
method: 'web.passport.sendcode',
uid: uid,
mobile: mobile,
area: area
}).then(result => result);
};
/**
* 验证短信验证码
* @param code
* @param mobile
* @param area
*/
const checkVerifyMsg = (code, mobile, area)=> {
return api.get('', {
method: 'web.passport.checkcode',
code: code,
mobile: mobile,
area: area
}).then(result => result);
};
/**
* 发送验证邮箱
* @param uid
* @param email
*/
const sendVerifyEmail = (uid, email)=> {
return api.get('', {
method: 'web.passport.verifyEmail',
uid: uid,
email: email
}).then(result => result);
};
/**
* 修改手机号前校验
* @param uid
* @param mobile
* @param area
*/
const checkVerifyMobile = (uid, mobile, area)=> {
return api.get('', {
method: 'web.passport.checkVerifyMobile',
uid: uid,
mobile: mobile,
area: area
}).then(result => result);
};
const modifyVerifyMobile = (uid, area, newMobile)=> {
return api.get('', {
method: 'web.passport.changeVerifyMobile',
uid: uid,
newMobile: newMobile,
area: area
}).then(result => result);
};
module.exports = {
verifyPwd: verifyPwd,
changePwd: changePwd,
sendMobileMsg: sendMobileMsg,
checkVerifyMsg: checkVerifyMsg,
sendVerifyEmail: sendVerifyEmail,
checkVerifyMobile: checkVerifyMobile,
modifyVerifyMobile: modifyVerifyMobile
};
... ...
... ... @@ -23,6 +23,22 @@ const getAddressDataAsync = (uid, limit) => {
}).then(result => result);
};
/**
* 设置默认地址
*
* @param id 地址id
* @param uid 用户ID
* @return array 地址接口返回的数据
*/
const setDefaultAddress = (id, uid) => {
return api.get('', {
method: 'app.address.setdefault',
id: id,
uid: uid
}).then(result => result);
};
/**
* 保存地址数据
*
... ... @@ -32,9 +48,10 @@ const getAddressDataAsync = (uid, limit) => {
* @param consignee 收货人
* @param mobile 手机号码
* @param phone 电话号码
* @param boolean init 是否是初始地址
* @return array 地址接口返回的数据
*/
const addAddressData = (uid, address, areaCode, consignee, mobile, phone) => {
const addAddressData = (uid, address, areaCode, consignee, mobile, phone, init) => {
return api.get('', {
method: 'app.address.add',
uid: uid,
... ... @@ -44,7 +61,20 @@ const addAddressData = (uid, address, areaCode, consignee, mobile, phone) => {
mobile: mobile,
phone: phone
}).then(result => {
// console.log("添加result",result);
if (result.code === 200 && init) {
return setDefaultAddress(result.data.id, uid).then(defaultResult => {
if (defaultResult.code === 200) {
// 若设置默认成功,扩展result设置默认标志位为Y
result.data.is_default = 'Y';
}
// 否则,返回原result
return result;
});
}
// 非初始地址或者新建不成功,直接返回result
return result;
});
};
... ... @@ -96,24 +126,6 @@ const delAddressData = (id, uid) => {
};
/**
* 设置默认地址
*
* @param id 地址id
* @param uid 用户ID
* @return array 地址接口返回的数据
*/
const setDefaultAddress = (id, uid) => {
return api.get('', {
method: 'app.address.setdefault',
id: id,
uid: uid
}).then(result => {
// console.log('设置默认result', result);
return result;
});
};
/**
* 获取地址信息
* @function getAddressData
* @return { Array } [返回带有areaId的地址数组]
... ...
/**
* 我的收藏查询
* @author: jiangfeng<jeff.jiang@yoho.cn>
* @date: 16/7/19
*/
'use strict';
const _ = require('lodash');
const API = global.yoho.API;
const ServiceAPI = global.yoho.ServiceAPI;
const favorite = {
getFavoriteProduct(param) {
let p = {
method: 'web.favorite.product'
};
return API.get('', _.assign(p, param));
},
getFavoriteBrand(param) {
let p = {
method: 'app.favorite.brand'
};
return API.get('', _.assign(p, param));
},
getFavoriteEditoreial(param) {
return ServiceAPI.get('/guang/api/*/favorite/getUserFavArticleList', param);
},
cancelFavorite(uid, ids, type) {
let p = {
method: 'web.favorite.cancel',
uid: uid,
favIds: ids,
type: type
};
return API.post('', p);
},
cancelEditorialFavorite(uid, ids) {
return ServiceAPI.get('/guang/api/*/favorite/cancelFavorite', {
article_id: ids,
uid: uid
});
}
};
module.exports = favorite;
... ...
... ... @@ -4,6 +4,8 @@ const api = global.yoho.API;
const camelCase = global.yoho.camelCase;
const moment = require('moment');
const helpers = global.yoho.helpers;
const _ = require('lodash');
const pageSize = 10;
... ... @@ -72,6 +74,7 @@ const invoiceText = {
2: '电子'
};
// 订单状态
const statusMap = {
0: {
... ... @@ -100,8 +103,8 @@ const statusMap = {
},
4: {
value: 2,
valueStr: '已发货',
step: 2,
valueStr: '待收货',
step: 3,
showGetBtn: true,
btns: btnMap.complete
},
... ... @@ -261,6 +264,12 @@ const _getUserOrder = (uid, type, page) => {
item.statusStr = statusMap[st].valueStr;
}
item.payUrl = helpers.urlFormat('/shopping/pay/online', {
code: item.orderCode
});
item.refundUrl = helpers.urlFormat('/me/return/refund/' + item.orderCode);
item.exchangeUrl = helpers.urlFormat('/me/return/exchange/' + item.orderCode);
});
return {
... ... @@ -282,11 +291,13 @@ const deleteOrder = (uid, code) => {
});
};
const cancelOrder = (uid, code) => {
const cancelOrder = (uid, data) => {
return api.get('', {
method: 'app.SpaceOrders.close',
uid: uid,
order_code: code
order_code: data.orderCode,
reason_id: data.reasonId,
reason: data.reason
}, {
cache: true
});
... ... @@ -328,6 +339,19 @@ const getOrderData = (uid, type, page) => {
]
};
const emptyMsg = {
1: {
text: '您暂时还没有订单',
showEmptyEn: true
},
2: {
text: '您暂时还没有待付款的订单'
},
3: {
text: '您暂时还没有待收货的订单'
}
};
type = parseInt(type, 10);
type = type < 4 ? type : 1;
... ... @@ -342,6 +366,11 @@ const getOrderData = (uid, type, page) => {
type: type
};
const empty = {
showEmptyEn: emptyMsg[type].showEmptyEn,
emptyMsg: emptyMsg[type].text
};
navBar.tabs[typeActiveIndexMap[type]].isActive = true;
const order = Object.assign(basicData, {
... ... @@ -357,7 +386,7 @@ const getOrderData = (uid, type, page) => {
} : false;
return {
order: Object.assign(order, paginationOpts)
order: Object.assign(order, paginationOpts, empty)
};
});
};
... ... @@ -375,6 +404,11 @@ const getOrderDetail = (uid, code) => {
detail.createTime = _convertUnixTime(detail.createTime);
if (detail.isCancel === 'N' &&
st === 0) {
detail.showLeftTime = true;
}
// 需要和接口确认如何获取运费,接口文档和线上数据不一致
// if (detail.shippingCost) {
// detail.shippingCost = _removeRmbIcon(detail.shippingCost);
... ... @@ -433,12 +467,23 @@ const editOrder = data => {
});
};
const reAddCart = (uid, code) => {
return api.get('', {
method: 'app.Shopping.readd',
uid: uid,
order_code: code
}, {
cache: true
});
};
module.exports = {
getOrderData: getOrderData,
getOrderDetail: getOrderDetail,
cancelOrder: cancelOrder,
getCancelOrderReason: getCancelOrderReason,
deleteOrder: deleteOrder,
editOrder: editOrder,
getExpressInfo: getExpressInfo
getOrderData,
getOrderDetail,
cancelOrder,
getCancelOrderReason,
deleteOrder,
editOrder,
getExpressInfo,
reAddCart: reAddCart
};
... ...
/**
* [个人中心]个人设置
* @author: jiangmin
* @date: 2016/07/13
*/
'use strict';
const api = global.yoho.API;
const crypto = require('crypto');
/**
* 查询个人信息
* @param uid
* @returns {*}
*/
const _getUserInfo = (uid) => {
return api.get('', {
method: 'app.passport.profile',
uid: uid
}).then(result => {
if (result && result.data) {
let genders = [
{
name: '男',
value: '1'
},
{
name: '女',
value: '2'
},
{
name: '保密',
value: '3'
}
];
return {
info: result.data,
genders: genders
};
}
});
};
const _getUserContactInfo = (uid)=> {
return api.get('', {
method: 'web.passport.getUserContacts',
uid: uid
}).then(result => result.data);
};
const getUserInfo = (uid) => {
let getData = [_getUserInfo(uid), _getUserContactInfo(uid)];
return Promise.all(getData).then(result => {
return {
info: result[0].info,
genders: result[0].genders,
concat: result[1]
};
});
};
const getVerifyInfo = (uid)=> {
return api.get('', {
method: 'web.passport.getUserVerifyInfo',
uid: uid
}).then(result => result);
};
const _editInfo = (uid, nickName, username, gender, birthday)=> {
return api.get('', {
method: 'app.passport.modifyBase',
uid: uid,
nick_name: nickName,
username: username,
gender: gender,
birthday: birthday
}).then(result => result);
};
const _editUserContactInfo = (uid, areaCode, mobile, fullAddress, zipCode)=> {
return api.get('', {
method: 'web.passport.modifyUserContacts',
uid: uid,
area_code: areaCode,
mobile: mobile,
full_address: fullAddress,
zip_code: zipCode
}).then(result => result);
};
const editUserInfo = (uid, info) => {
let getData = [
_editInfo(uid, info.nick_name, info.username, info.gender, info.birthday),
_editUserContactInfo(uid, info.area_code, info.mobile, info.full_address, info.zip_code)
];
return Promise.all(getData).then(result => result);
};
/**
* 加密
* @param data
* @returns {string}
*/
const cipheriv = (data) => {
let algorithm = 'aes-128-ecb';
let key = 'yoho9646yoho9646';
let clearEncoding = 'utf8';
let cipherEncoding = 'base64';
let iv = '';
let cipher = crypto.createCipheriv(algorithm, key, iv);
let cipherChunks = [];
cipherChunks.push(cipher.update(data, clearEncoding, cipherEncoding));
cipherChunks.push(cipher.final(cipherEncoding));
return cipherChunks.join('');
};
/**
* 解密
* @param data
* @returns {string}
*/
const decipheriv = (data) => {
let algorithm = 'aes-128-ecb';
let key = 'yoho9646yoho9646';
let decipherEncoding = 'utf8';
let clearEncoding = 'base64';
let iv = '';
let decipher = crypto.createDecipheriv(algorithm, key, iv);
let decipherChunks = [];
decipherChunks.push(decipher.update(data, clearEncoding, decipherEncoding));
decipherChunks.push(decipher.final(decipherEncoding));
return decipherChunks.join('');
};
module.exports = {
getUserInfo: getUserInfo,
getVerifyInfo: getVerifyInfo,
editUserInfo: editUserInfo,
cipheriv: cipheriv,
decipheriv: decipheriv
};
... ...
... ... @@ -8,11 +8,17 @@
const router = require('express').Router(); // eslint-disable-line
const cRoot = './controllers';
const auth = require(`${global.middleware}/auth`);
// const auth = require(`${global.middleware}/auth`);
// 订单
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`);
// 个人中心首页/订单
... ... @@ -25,6 +31,7 @@ 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('/return', returns.index);
... ... @@ -37,15 +44,49 @@ router.post('/return/refund/apply', returns.refundApply);
router.get('/return/getProductInfo', returns.getProductInfo);
// 个人中心首页/收货地址
router.get('/address', address.index);
router.post('/address/add', address.addAddressData);
router.post('/address/update', address.updateAddressData);
router.post('/address/del', address.delAddressData);
router.post('/address/default', address.setDefaultAddress);
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);
// 个人中心首页/YOHO币
router.get('/currency', currency.index);
router.get('/currency', auth, currency.index);
// 个人中心首页/个人设置
router.get('/setting', auth, setting.index);// 个人首页
router.post('/setting/editUserInfo', 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('/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', favorite.goods);
router.get('/collection/brand', favorite.brand);
router.get('/collection/editorial', favorite.editorial);
router.post('/collection/cancel', favorite.cancel);
router.post('/collection/editorial/cancel', favorite.editorialCancel);
module.exports = router;
... ...
<div class="me-page blk-page">
<div class="center-content clearfix">
{{# content}}
{{!-- 头部面包屑 --}}
{{!-- 头部面包屑 --}}
{{> path-nav}}
{{!-- 左侧菜单导航 --}}
... ... @@ -70,6 +70,15 @@
{{#if setting}}
{{> setting}}
{{/if}}
{{#if validateStep}}
{{> setting/act/step1}}
{{/if}}
{{#if operateStep}}
{{> setting/act/step2}}
{{/if}}
{{#if successStep}}
{{> setting/act/step3}}
{{/if}}
{{!-- 收货地址 --}}
{{#if address}}
... ...
<form id="address-form" name="address-form">
<div class="address-page">
<span class="blue tip">新增地址 电话为选填项,其他均为必填项</span>
<span class="blue tip"><em>新增地址</em>电话为选填项,其他均为必填项</span>
<div class="add-address-detail">
<div class="form-group">
<label class="label-name">&nbsp;&nbsp;收货人:</label>
... ...
... ... @@ -20,13 +20,13 @@
<td class="width-260">
<div>
<span class="blue opreation update-address" data-id="{{address_id}}">修改</span>
|
<em class="op-sep">|</em>
<span class="blue opreation del-address" data-id="{{address_id}}">删除</span>
{{#if default}}
{{#isY is_default}}
<span class="btn set-default opreation current-default ">默认地址</span>
{{else}}
{{^}}
<span class="btn set-default opreation " data-id="{{address_id}}">设为默认</span>
{{/if}}
{{/isY}}
</div>
</td>
</tr>
... ...
{{#favorite}}
{{> common/subtitle}}
<div class="order-nav">
<ul class="tabs clearfix">
<li class="{{#if product}}active{{/if}}">
<a href="/me/collection"><span class="badge"></span>商品收藏</a>
</li>
<li class="{{#if brand}}active{{/if}}">
<a href="/me/collection/brand"><span class="badge"></span>店铺收藏</a>
</li>
<li class="{{#if editorial}}active{{/if}}">
<a href="/me/collection/editorial"><span class="badge"></span>资讯收藏</a>
</li>
</ul>
</div>
{{#if product}}
{{> collection/product}}
{{/if}}
{{#if brand}}
{{> collection/brand}}
{{/if}}
{{#if editorial}}
{{> collection/editorial}}
{{/if}}
{{/favorite}}
... ...
{{# data}}
{{#if total}}
<div class="favorite-brands">
<div class="brands-list clearfix">
{{#each brandList}}
<div class="brand-raw clearfix">
<div class="check">
{{> icon/checkbox}}
</div>
<div class="brand-info" data-id="{{brandId}}">
<div class="brand-icon">
<img src="{{image brandIco 145 126}}" alt="">
</div>
<div class="brand-name">
{{brandName}}
</div>
<div class="tool-area clearfix">
<a class="btn white" href="/product/shop/{{brandDomain}}" target="_blank">去店铺页</a>
<span class="btn white cancel">取消收藏</span>
</div>
</div>
<div class="brand-products slide-container">
<div class="slide-switch">
<a class="prev" href="javascript:;">
<span class="iconfont">&#xe62c;</span>
</a>
<a class="next" href="javascript:;">
<span class="iconfont">&#xe629;</span>
</a>
</div>
<div class="slide-wrap">
<ul>
{{#each newProduct}}
<li class="clearfix">
{{#each this}}
{{#if more}}
<div class="goods-more">
<div class="more-text">MORE</div>
<p>查看更多</p>
</div>
{{^}}
<div class="goods-info">
<a href="{{url}}" target="_blank">
<img class="lazy thumb"
src="{{image defaultImages 148 196}}"
style="display: block;">
<div class="desc">
<span class="name">{{productName}}</span>
<p class="price">¥{{round salesPrice 2}}</p>
</div>
</a>
</div>
{{/if}}
{{/each}}
</li>
{{/each}}
</ul>
</div>
</div>
</div>
{{/each}}
</div>
<div class="favorite-footer">
<div class="favorite-tool">
<div class="check-all">
{{> icon/checkbox}}
<label>全选</label>
</div>
<div class="favorite-cancel">
取消收藏
</div>
</div>
{{{ pagination paginationData }}}
</div>
</div>
{{^}}
<div class="favorite-empty">
<p>您还没有收藏的店铺, 去<a href="{{siteUrl}}">首页</a>看看吧</p>
</div>
{{/if}}
{{/data}}
... ...
{{# data}}
{{#if total}}
<div class="favorite-editorials">
<div class="editorial-list clearfix">
{{#each editorialList}}
<div class="editorial-raw clearfix" data-id="{{id}}">
<div class="check">
{{> icon/checkbox}}
</div>
<div class="editorial-cover">
<a href="/editorial/{{id}}.html" target="_blank">
<img src="{{image src 240 160 1}}" alt="">
</a>
</div>
<div class="editorial-info">
<div class="editorial-title">
<a href="/editorial/{{id}}.html" target="_blank">
{{title}}
</a>
</div>
<div class="editorial-some">
<span class="author">{{author.name}}</span>
<span class="time">{{publishTime}}</span>
<span>浏览: {{viewsNum}}</span>
<span>评论: {{praiseNum}}</span>
</div>
<p class="summer">
{{intro}}
</p>
<div class="editorial-tags">
<span>户外</span>
<span>学院</span>
</div>
</div>
<div class="fav-cancel">
<span class="iconfont">&#xe614;</span>
</div>
</div>
{{/each}}
</div>
<div class="favorite-footer">
<div class="favorite-tool">
<div class="check-all">
{{> icon/checkbox}}
<label>全选</label>
</div>
<div class="favorite-cancel">
取消收藏
</div>
</div>
{{{ pagination paginationData }}}
</div>
</div>
{{^}}
<div class="favorite-empty">
<p>您还没有收藏的资讯, 去<a href="{{siteUrl}}/editorial">首页</a>看看吧</p>
</div>
{{/if}}
{{/data}}
... ...
{{# data}}
{{#if total}}
<div class="favorite-products">
<div class="products-cates clearfix">
{{#each categoryList}}
<div class="label {{#if checked}}focus{{/if}}">
<a href="?sort={{categoryId}}">{{categoryName}} ({{num}})</a>
</div>
{{/each}}
</div>
<div class="clearfix product-list">
{{#each products}}
<div class="goods-info" data-id="{{productId}}">
<div class="choose-icon">
<span class="iconfont">&#xe646;</span>
</div>
<div class="goods-img">
<img class="lazy thumb" data-original="{{imageUrl}}" style="display: block;">
{{#stateText}}
<div class="goods-state-bg"></div>
<div class="goods-state">
{{this}}
</div>
{{/stateText}}
</div>
<div class="desc">
<span class="name">{{productName}}</span>
<p class="price">¥{{round salesPrice 2}}</p>
</div>
<div class="tool-area clearfix">
<a class="btn white" href="{{url}}" target="_blank">立即购买</a>
<span class="btn white cancel">取消收藏</span>
</div>
</div>
{{/each}}
</div>
<div class="favorite-footer">
<div class="favorite-tool">
<div class="check-all">
{{> icon/checkbox}}
<label>全选</label>
</div>
<div class="favorite-cancel">
取消收藏
</div>
</div>
{{{ pagination paginationData }}}
</div>
</div>
{{^}}
<div class="favorite-empty">
<p>您还没有收藏的商品, 去<a href="{{siteUrl}}">首页</a>看看吧</p>
</div>
{{/if}}
{{/data}}
... ...
<div class="goods-list info-box">
<h4 class="status-title">商品清单</h4>
{{#isY isMultiPackage}}
<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 packageList}}
<div class="package-item">
<p class="package-title bold">包裹{{math @index '+' 1}}:{{#if @first}}总仓发货{{^}}异地调拨{{/if}}</p>
<ul class="package-goods clearfix">
{{#each goodsList}}
<li class="left">
<img class="lazy package-goods-img" data-original="{{image goodsImages 100 134}}">
</li>
{{/each}}
</ul>
<p class="package-shipping">运费:¥{{shoppingCost}}元(原价{{shoppingOrigCost}}元,优惠{{shoppingCutCost}}元)</p>
</div>
{{/each}}
</div>
</div>
{{/isY}}
<div class="table">
<ul class="header">
<li class="first">商品信息</li>
... ...
... ... @@ -13,6 +13,15 @@
</div>
</div>
{{#if showLeftTime}}
<div class="time">
<span>剩余支付时间:</span>
<span class="iconfont">&#xe606;</span>
<p class="left-time" data-left={{payLefttime}}></p>
<span class="tip">(逾期订单将自动取消)</span>
</div>
{{/if}}
{{#if steps}}
<div class="time-line">
<ul>
... ...
... ... @@ -19,18 +19,20 @@
{{#if showPayButton}}
<div class="pay-operation">
{{#if isOnlinePaid}}
<p class="left-time" data-left="{{payLefttime}}"></p>
<span class="iconfont">&#xe606;</span><p class="left-time" data-left="{{payLefttime}}"></p>
<a href="{{payUrl}}">
<span class="btn red">立即付款</span>
</a>
{{/if}}
<p class="subtext cancel">取消订单</p>
</div>
{{/if}}
{{#if showEditOption}}
<p class="subtext">评价晒单</p>
<a href="/me/return/refund/{{orderCode}}">
<a href="{{refundUrl}}">
<p class="subtext">申请退货</p>
</a>
<a href="/me/return/exchange/{{orderCode}}">
<a href="{{exchangeUrl}}">
<p class="subtext">申请换货</p>
</a>
<p class="subtext delete">删除订单</p>
... ... @@ -41,7 +43,7 @@
{{/if}}
<div class="buy-operation{{#unless showBuyBtn}} hide{{/unless}}">
<span class="btn black">再次购买</span>
<span class="btn black buy">再次购买</span>
<p class="subtext delete">删除订单</p>
</div>
... ... @@ -55,8 +57,10 @@
{{^}}
<div class="bg"></div>
<div class="msg">
<p class="msg-zh bold">您暂时还没有订单</p>
<p class="msg-zh bold">{{emptyMsg}}</p>
{{#if showEmptyEn}}
<p class="msg-en">You do not have an order for the time being</p>
{{/if}}
<span class="btn">去购物</span>
</div>
{{/if}}
... ...
<div class="user-setting">
{{> common/subtitle}}
{{> setting/content}}
</div>
... ...
{{> common/subtitle}}
<div class="progress">
<div class="progress-pic1"></div>
<div class="progress-text">
<span>验证身份</span>
<span class="gray-text">{{proTitle}}</span>
<span class="gray-text">完成</span>
</div>
{{#if isShowMobile}}
<div class="operate1">
{{#data}}
<div class="form-group">
<lable class="label-name">已绑定的手机号码:</lable>
<p id="cur-mobile">{{ellipsisMobile}}</p>
<input id="real-mobile" type="hidden" value="{{verify_mobile}}">
<input type="hidden" id="checkCode" value="{{checkCode}}">
</div>
{{/data}}
<div class="form-group">
<lable class="label-name">手机验证码:</lable>
<input id="msg-code" type="text" class="input small-input">
<span id="send-code" class="btn white">发送验证码</span>
</div>
<div class="form-group">
<span id="mobile-step1" class="btn submit">提交</span>
</div>
</div>
{{/if}}
{{#if isShowEmail}}
<div class="operate1">
{{#data}}
<div class="form-group">
<lable class="label-name">已绑定的邮箱:</lable>
<p>{{ellipsisEmail}}</p>
<input type="hidden" id="real-email" value="{{verify_email}}">
<input type="hidden" id="checkCode" value="{{checkCode}}">
</div>
{{/data}}
<div class="form-group">
<lable class="label-name">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;验证码:</lable>
<input id="captcha" type="text" class="input small-input">
<img id="captcha-img" class="captcha-img" src="{{captchaUrl}}" alt="">
<a class="change-captcha operation"><span class="iconfont gray operation">&#xe613;</span></a>
</div>
<div class="form-group">
<div id="email-step1" class="btn submit">提交</div>
</div>
</div>
<div class="operate2" hidden>
<p class="bold">已发送验证邮件至:123***123@qq.com</p>
<p>验证邮件24小时内有效,请尽快登录您的邮箱点击链接完成绑定</p>
<a target="_blank" href="http://mail.qq.com" class="button-icon button-red">
<span class="btn submit">查看验证邮件</span>
</a>
</div>
{{/if}}
{{#if isShowPassword}}
<div class="operate1">
<div class="form-group">
<lable class="label-name">请输入登录密码:</lable>
<input id="verifyPwd" type="password" class="input">
<input type="hidden" id="checkCode" value="{{checkCode}}">
</div>
<div class="form-group">
<lable class="label-name">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;验证码:</lable>
<input id="captcha" type="text" class="input small-input">
<img id="captcha-img" class="captcha-img" src="{{captchaUrl}}" alt="">
<a class="change-captcha operation"><span class="iconfont gray operation">&#xe613;</span></a>
<span class="tips-success blue ok">{{> icon/round-hook}}</span>
<span class="tips-error notok">{{> icon/error-round}}</span>
</div>
<div class="form-group">
<span id="pwd-step1" class="btn submit">提交</span>
</div>
</div>
{{/if}}
</div>
{{>setting/footer/verify}}
{{>setting/footer/bind-email}}
{{>setting/footer/email}}
... ...
{{> common/subtitle}}
<div class="progress">
<div class="progress-pic2"></div>
<div class="progress-text">
<span>验证身份</span>
<span>{{proTitle}}</span>
<span class="gray-text">完成</span>
</div>
{{#if isShowMobile}}
<div class="operate1">
<div class="form-group">
<lable id="cur-mobile" class="label-name">新的手机号码:</lable>
<select id="region" class="region" name="region">
{{#each region}}
<option {{#if selected}}selected="selected"{{/if}} value="{{areaCode}}">{{name}}</option>
{{/each}}
</select>
<span id="country-code" class="country-code">{{location}}</span>
<input id="real-mobile" type="text" class="input">
<span class="tips-success blue ok">{{> icon/round-hook}}</span>
<span class="tips-error notok">{{> icon/error-round}}</span>
<input type="hidden" id="checkCode" value="{{checkCode}}">
</div>
<div class="form-group">
<lable class="label-name">手机验证码:</lable>
<input id="msg-code" type="text" class="input small-input">
<span id="send-code2" class="btn white">发送验证码</span>
</div>
<div class="form-group">
<span id="mobile-step2" class="btn submit">提交</span>
</div>
</div>
{{/if}}
{{#if isShowEmail}}
<div class="operate1">
<div class="form-group">
<lable class="label-name">我的邮箱:</lable>
<input type="text" class="input">
<input type="hidden" id="checkCode" value="{{checkCode}}">
</div>
<div class="form-group">
<lable class="label-name">验证码:</lable>
<input id="captcha" type="text" class="input small-input">
<img id="captcha-img" class="captcha-img" src="{{captchaUrl}}" alt="">
<a class="change-captcha operation"><span class="iconfont gray operation">&#xe613;</span></a>
</div>
<div class="form-group">
<div id="email-step2" class="btn submit">提交</div>
</div>
</div>
<div class="operate2" hidden>
<p class="bold">已发送验证邮件至:123***123@qq.com</p>
<p>验证邮件24小时内有效,请尽快登录您的邮箱点击链接完成绑定</p>
<a target="_blank" href="http://mail.qq.com" class="button-icon button-red">
<span class="btn submit">查看验证邮件</span>
</a>
</div>
{{/if}}
{{#if isShowPassword}}
<div class="operate1">
<div class="form-group">
<lable class="label-name">输入新密码:</lable>
<input id="newPwd" type="password" class="input">
<input type="hidden" id="checkCode" value="{{checkCode}}">
</div>
<div class="form-group">
<lable class="label-name">验证新密码:</lable>
<input id="checkPwd" type="password" class="input">
<span class="tips-success blue ok">{{> icon/round-hook}}</span>
<span class="tips-error notok">{{> icon/error-round}}</span>
</div>
<div class="form-group">
<lable class="label-name">验证码:</lable>
<input id="captcha" type="text" class="input small-input">
<img id="captcha-img" class="captcha-img" src="{{captchaUrl}}" alt="">
<a class="change-captcha operation"><span class="iconfont gray operation">&#xe613;</span></a>
<span class="tips-success blue ok">{{> icon/round-hook}}</span>
<span class="tips-error notok">{{> icon/error-round}}</span>
</div>
<div class="form-group">
<span id="step2-pwd" class="btn submit">提交</span>
</div>
</div>
{{/if}}
</div>
{{>setting/footer/verify}}
{{>setting/footer/bind-email}}
{{>setting/footer/email}}
... ...
{{> common/subtitle}}
<div class="progress">
<div class="progress-pic3"></div>
<div class="progress-text">
<span>验证身份</span>
<span>{{proTitle}}</span>
<span>完成</span>
</div>
{{#if isModifyMobile}}
<div class="operate2">
<p class="bold"><span>{{> icon/round-hook}}</span>恭喜您,您已经成功更换了绑定手机</p>
<p>今后您可以使用新的手机号码+密码进行登录</p>
</div>
{{/if}}
{{#if isModifyEmail}}
<div class="operate2">
<p class="bold"><span>{{> icon/round-hook}}</span>恭喜您,您已经成功修改了绑定邮箱</p>
</div>
{{/if}}
{{#if isShowPassword}}
<div class="operate2">
<p class="bold"><span>{{> icon/round-hook}}</span>恭喜您,您已经成功修改了登录密码</p>
</div>
{{/if}}
{{#if isBindMobile}}
<div class="operate2">
<p class="bold"><span>{{> icon/round-hook}}</span>恭喜您,您已经成功绑定手机!</p>
</div>
{{/if}}
{{#if isBindEmail}}
<div class="operate2">
<p class="bold"><span>{{> icon/round-hook}}</span>恭喜您,您已经成功绑定了邮箱</p>
</div>
{{/if}}
</div>
... ...
<form id="setting-form" name="setting-form">
{{#userInfo}}
<div class="setting-page inline-block">
<input id="gender" type="hidden" value="{{info.gender}}">
<input id="area_code" type="hidden" value="{{concat.area_code}}">
<input id="zip_code" type="hidden" value="{{concat.zip_code}}">
<input id="infoMobile" type="hidden" value="{{info.mobile}}">
<div class="form-group">
<label class="label-name">真实姓名:</label>
<input id="username" class="input" type="text" placeholder="请输入2-12个汉字或英文"
value="{{info.username}}" minlength="2" maxlength="12">
</div>
<div class="form-group">
<label class="label-name">昵称:</label>
<input id="nick_name" class="input" type="text" placeholder="中文、英文、数字、-和_组合"
value="{{info.nickname}}" maxlength="10">
<span class="blue error-tips">{{> icon/error-round}}中文、英文、数字、-和_组合</span>
</div>
<div class="form-group">
<label class="label-name">性别:</label>
{{#each genders}}
<div class="input-radio inline-block operation" data-value="{{value}}">
{{> icon/radio}}
<label>{{name}}</label>
</div>
{{/each}}
</div>
<div class="form-group">
<label class="label-name">密码:</label>
<input class="input no-edit" value="********">
<a class="blue operation" href="{{stepUrl}}/modifyPassword">修改</a>
</div>
<div class="form-group">
<label class="label-name">手机:</label>
{{#if info.verify_mobile}}
<input id="mobile" class="input no-edit" value="{{info.mobile}}">
<a class="blue operation" href="{{stepUrl}}/modifyMobile">修改</a>
{{else}}
<input class="input" type="text" placeholder="请绑定手机" disabled>
<a class="blue operation" href="{{stepUrl}}/bindMobile">绑定</a>
{{/if}}
</div>
<div class="form-group">
<label class="label-name">邮箱:</label>
{{#if info.verify_email}}
<input class="input no-edit" value="{{info.mobile}}">
<!--<a class="blue operation" href="{{stepUrl}}/modifyEmail">修改</a>-->
<a class="blue operation">修改</a>
{{else}}
<input class="input" type="text" placeholder="请绑定邮箱" disabled>
<!--<a class="blue operation" href="{{stepUrl}}/bindEmail">绑定</a>-->
<a class="blue operation">绑定</a>
{{/if}}
</div>
<div class="form-group">
<label class="label-name">出生日期:</label>
<input id="birthday" class="input" type="text" value="{{info.birthday}}">
<span class="blue error-tips">{{> icon/error-round}}出生日期格式不对</span>
</div>
<div class="form-group-address">
<label class="label-name">居住地址:</label>
<div id="address"></div>
</div>
<div class="form-group">
<label class="label-name">详细地址:</label>
<input id="full_address" class="input big-input" type="text" placeholder="请填写详细地址"
maxlength="20" value="{{concat.full_address}}">
</div>
<div class="form-group">
<span class="btn operation" id="save-settings">保存</span>
</div>
</div>
<div class="user-icon inline-block">
{{#if info.head_ico}}
<img src="{{info.head_ico}}">
{{else}}
<div class="show-ico"></div>
<div class="edit-ico hide"></div>
{{/if}}
</div>
{{/userInfo}}
</form>
... ...
<div class="footer-tips" hidden>
<hr>
<p class="bold">为什么要绑定邮箱?</p>
<p>1.绑定邮箱可加强账户安全,您可以使用已绑定的邮箱快速找回密码</p>
<p>2.已绑定的邮箱可用于账户余额变动提醒</p>
</div>
... ...
<div class="footer-tips" hidden>
<hr>
<p class="bold">没有收到邮件?</p>
<p>1.请检查您的垃圾箱或者广告箱,邮件有可能被误认为垃圾邮件或者广告邮件</p>
<p>2.如果垃圾箱或者广告箱页没有收到,请尝试将<span class="blue">do_replay@yoho.cn</span>
添加为收件人白名单(可参考邮箱白名单设置)</p>
</div>
... ...
<div class="footer-tips">
<hr>
<p class="bold">为什么要进行身份验证?</p>
<p>1.为保障您的账户信息安全,在变更账户中的重要信息是需要进行身份验证,感谢您的理解与支持。</p>
<p>2.验证身份遇到问题?请拨打客服电话<span class="blue">400-889-9646</span>,客服将尽快联系您。</p>
</div>
... ...
... ... @@ -24,7 +24,7 @@ app.engine('.hbs', hbs({
defaultLayout: 'layout',
layoutsDir: doraemon,
partialsDir: ['./views/partial', `${doraemon}/partial`],
helpers: 'helpers'
helpers: global.yoho.helpers
}));
// router
... ...
... ... @@ -204,6 +204,15 @@
</pre>
</div>
</div>
<p class="title">19. 上传图片接口</p>
<div stlye="width: 200px;height:200px">
<form name="form1" method="post" enctype="multipart/form-data" action="/api/uploadImg">
<input type="file" name="filename" style="width:160px;" />
<input type="hidden" name="bucket" value="goodsimg" />
<input type="submit" name="Submit" value="上传" />
</form>
</div>
{{/ content}}
</div>
... ...
... ... @@ -35,7 +35,7 @@ passport.use(new LocalStrategy({
passReqToCallback: true
}, (req, username, password, done) => {
let area = req.body.area || '86';
let area = req.body.areaCode || '86';
if (isNaN(_.parseInt(area)) || _.isEmpty(username) || _.isEmpty(password)) {
logger.info(`【Passport Loginbad params, area:${area} account:${username} password:${password}`);
... ... @@ -43,7 +43,7 @@ passport.use(new LocalStrategy({
}
let verifyEmail = helpers.verifyEmail(username);
let verifyMobile = helpers.verifyAreaMobile(area + '-' + username, area);
let verifyMobile = area === '86' ? helpers.verifyAreaMobile(area + '-' + username) : true;
if (!verifyEmail && !verifyMobile) {
logger.info(`【Passport Loginbad account, email:${verifyEmail} mobile:${verifyMobile}`);
... ...
... ... @@ -16,10 +16,11 @@ const _ = require('lodash');
const index = (req, res, next) => {
service.indexPageDataAsync()
.then(result => {
res.render('back/index', Object.assign({
res.display('back/index', Object.assign({
module: 'passport',
page: 'back-index',
title: '找回密码'
title: '找回密码',
defaultHeader: false
}, result));
})
.catch(next);
... ... @@ -151,10 +152,11 @@ const validateEmailInSession = (req, res, next) => {
const sendEmailPage = (req, res, next) => {
passportHelper.getLeftBannerAsync()
.then(result => {
res.render('back/send-email', Object.assign({
res.display('back/send-email', Object.assign({
module: 'passport',
page: 'back-send-email-ok',
title: '邮件发送成功'
title: '邮件发送成功',
defaultHeader: false
}, {
sendEmail: {
coverHref: result.url,
... ... @@ -188,10 +190,11 @@ const validateCodeByEmailPage = (req, res, next) => {
const resetPasswordPage = (req, res) => {
let code = req.query.code || '';
res.render('back/reset-pwd', Object.assign({
res.display('back/reset-pwd', Object.assign({
module: 'passport',
page: 'back-reset-pwd',
title: '重置密码'
title: '重置密码',
defaultHeader: false
}, {
resetPwd: Object.assign({
code: code
... ... @@ -201,10 +204,11 @@ const resetPasswordPage = (req, res) => {
const verifyCodeByMobilePage = (req, res) => {
res.render('back/verification', Object.assign({
res.display('back/verification', Object.assign({
module: 'passport',
page: 'back-verify-mobile-code',
title: '手机验证'
title: '手机验证',
defaultHeader: false
}, {
verification: {
mobile: req.body.mobile,
... ... @@ -228,10 +232,11 @@ const validateSuccessStatusPage = (req, res, next) => {
const resetPwdSuccessPage = (req, res, next) => {
passportHelper.getLeftBannerAsync()
.then(result => {
res.render('back/reset-success', Object.assign({
res.display('back/reset-success', Object.assign({
module: 'passport',
page: 'back-index',
title: '重置密码成功'
title: '重置密码成功',
defaultHeader: false
}, {
resetSuccess: {
coverHref: result.url,
... ...
... ... @@ -26,10 +26,11 @@ const bind = {
let openId = req.query.openId;
let sourceType = req.query.sourceType;
res.render('bind/index', Object.assign({
res.display('bind/index', Object.assign({
module: 'passport',
page: 'bind',
title: '联合登录补全信息'
title: '联合登录补全信息',
defaultHeader: false
}, {
openId: openId,
sourceType: sourceType,
... ... @@ -44,10 +45,11 @@ const bind = {
let openId = req.query.thirdPart.openId;
let area = req.query.thirdPart.area;
res.render('bind/bind-set-pwd', Object.assign({
res.display('bind/bind-set-pwd', Object.assign({
module: 'passport',
page: 'bind-set-pwd',
title: '登录绑定'
title: '登录绑定',
defaultHeader: false
}, {
mobile: mobile,
sourceType: sourceType,
... ... @@ -63,10 +65,11 @@ const bind = {
const DEFAULT_URL = 'http://img10.static.yhbimg.com/headimg/2013/11/28/09/01cae078abe5fe320c88cdf4c220212688.gif?imageView/2/w/100/h/100';
let avatar = user.headImg || DEFAULT_URL;
res.render('bind/bind-confirm', Object.assign({
res.display('bind/bind-confirm', Object.assign({
module: 'passport',
page: 'bind-confirm',
title: '绑定确认'
title: '绑定确认',
defaultHeader: false
}, {
avatar: avatar,
name: user.username || '咸鸭蛋',
... ... @@ -91,10 +94,11 @@ const bind = {
let sourceInfo = sourceType.split('_');
let sourceName = Sources[sourceInfo[0]];
res.render('bind/bind-success', Object.assign({
res.display('bind/bind-success', Object.assign({
module: 'passport',
page: 'bind-success',
title: '绑定手机号'
title: '绑定手机号',
defaultHeader: false
}, {
goShopping: helpers.urlFormat('/'),
sourceName: sourceName
... ... @@ -106,10 +110,11 @@ const bind = {
let sourceInfo = sourceType.split('_');
let sourceName = Sources[sourceInfo[0]];
res.render('bind/relate-success', Object.assign({
res.display('bind/relate-success', Object.assign({
module: 'passport',
page: 'relate-success',
title: '关联手机号'
title: '关联手机号',
defaultHeader: false
}, {
goShopping: helpers.urlFormat('/'),
sourceName: sourceName
... ... @@ -122,10 +127,11 @@ const bind = {
const DEFAULT_URL = 'http://img10.static.yhbimg.com/headimg/2013/11/28/09/01cae078abe5fe320c88cdf4c220212688.gif?imageView/2/w/100/h/100';
let avatar = user.headImg || DEFAULT_URL;
res.render('bind/relate-confirm', Object.assign({
res.display('bind/relate-confirm', Object.assign({
module: 'passport',
page: 'relate-confirm',
title: '关联确认'
title: '关联确认',
defaultHeader: false
}, {
avatar: avatar,
name: user.username || '咸鸭蛋',
... ... @@ -161,10 +167,10 @@ const bind = {
return {code: 201, message: result.message, data: {user: user}};
});
} else if (result.code === 200 && result.data.is_register === 3) {
let nextUrl = helpers.urlFormat('/passport/thirdlogin/relate');
// 关联流程
return {code: 203, message: result.message, data: {next: nextUrl}};
return PassportHelper.getUserInfo(area, mobile).then(user => {
return {code: 203, message: result.message, data: {user: user}};
});
} else if (result.code === 506 || result.code === 505) {
return PassportHelper.getUserInfo(area, mobile).then(user => {
// 绑定流程:code=201 已注册 绑定过其他第三方
... ...
... ... @@ -29,7 +29,7 @@ function doPassportCallback(req, res, user) {
refer = config.siteUrl;
}
if (/sign|login/.test(refer)) {
if (/sign|login|passport/.test(refer)) {
refer = config.siteUrl;
}
... ... @@ -111,14 +111,15 @@ const local = {
areaName = area ? area.name : '';
}
res.render('login', {
res.display('login', {
loginPage: true,
defaultHeader: false,
passport: {
countryCode: bindArea,
countryName: areaName,
countryList: areaArr,
forgetPwd: helpers.urlFormat('/passport/back/index'),
fastReg: helpers.urlFormat('/passport/reg/index'),
fastReg: helpers.urlFormat('/passport/reg'),
weixinLogin: helpers.urlFormat('/passport/autosign/wechat'),
qqLogin: helpers.urlFormat('/passport/autosign/qq'),
weiboLogin: helpers.urlFormat('/passport/autosign/sina'),
... ... @@ -158,10 +159,10 @@ const local = {
refer = `${config.siteUrl}`;
}
if (/sign|login/.test(refer)) {
if (/sign|login|passport/.test(refer)) {
refer = `${config.siteUrl}`;
}
user.session = refer;
user.href = refer;
AuthHelper.syncUserSession(user.uid, req, res).then(() => {
res.json({
... ... @@ -219,7 +220,7 @@ const wechat = {
}
})(req, res, next);
} else {
return next(new Error('Auth State Mismatch'));
return next(new Error(`session:${req.session.authState},query:${req.query.state}`));
}
}
};
... ...
... ... @@ -30,22 +30,6 @@ let checkCode = (req, res, next) => {
};
/**
* 检查手机格式
*/
let checkMobileMiddleware = (req, res, next) => {
let mobile = +req.body.mobile;
let area = +req.body.area;
if (!_.isNumber(mobile) || !_.isNumber(area)) {
return res.json({
code: 400,
message: '手机号码格式不正确'
});
}
next();
};
/**
* 检查密码格式
*/
let checkPassword = (req, res, next) => {
... ... @@ -74,8 +58,9 @@ let index = (req, res) => {
domain: config.cookieDomain
});
res.render('reg/index', {
res.display('reg/index', {
title: '新用户注册',
defaultHeader: false,
passport: {
region: passportHelper.getCountry(),
location: '+86',
... ... @@ -95,8 +80,8 @@ let checkMobile = (req, res, next) => {
let data = {
code: 400
};
let mobile = +req.body.mobile;
let area = +req.body.area;
let mobile = req.body.mobile;
let area = req.body.area;
// 判断手机号是否检查超过指定次数
let regCheckKey = 'regCheckMobileNum_' + passportHelper.makeAreaMobile(area, mobile);
... ... @@ -113,7 +98,7 @@ let checkMobile = (req, res, next) => {
return res.json(data);
}
// 判断用户是否存在
// 判断用户是否存在
return userService.findByMobileAsync(area, mobile).then((user) => {
if (!_.isEmpty(user)) {
data.message = '手机号码已经存在';
... ... @@ -148,8 +133,8 @@ let sendBindMsg = (req, res, next) => {
data: ''
};
let mobile = +req.body.mobile;
let area = +req.body.area;
let mobile = req.body.mobile;
let area = req.body.area;
// 检查是否检查过
let checkNum = yield cache.get(`regCheckMobileNum_${passportHelper.makeAreaMobile(area, mobile)}`);
... ... @@ -192,9 +177,9 @@ let msgCaptcha = (req, res, next) => {
message: '',
data: ''
};
let area = +req.body.area;
let mobile = +req.body.mobile;
let code = +req.body.code; // 短信验证码
let area = req.body.area;
let mobile = req.body.mobile;
let code = req.body.code; // 短信验证码
regService.validMobileCode(area, mobile, code).then((result) => {
if (result.code) {
... ... @@ -242,9 +227,9 @@ let mobileRegister = (req, res, next) => {
yield cache.set(ipKey, ipTimes + 1, 3600);
let area = +req.body.area;
let mobile = +req.body.mobile;
let code = +req.body.code; // 短信验证码
let area = req.body.area;
let mobile = req.body.mobile;
let code = req.body.code; // 短信验证码
let password = req.body.password;
let result = yield regService.validMobileCode(area, mobile, code); // 验证注册的标识码是否有效
... ... @@ -281,7 +266,8 @@ let success = (req, res) => {
let goShoppingUrl = req.query.goShoppingUrl || config.siteUrl;
let mobile = req.query.mobile || '用户';
res.render('reg/success', {
res.display('reg/success', {
defaultHeader: false,
title: '注册成功',
passport: {
goUrl: goUrl,
... ... @@ -293,7 +279,6 @@ let success = (req, res) => {
module.exports = {
checkCode,
checkMobileMiddleware,
checkPassword,
index,
success,
... ...
... ... @@ -63,12 +63,12 @@ router.post('/autouserinfo/relateMobile', bind.relateMobile);
/**
* 注册页面路由
*/
router.get('/reg/index', reg.index);
router.post('/reg/checkmobile', reg.checkMobileMiddleware, reg.checkMobile);
router.get('/reg', reg.index);
router.post('/reg/checkmobile', reg.checkMobile);
router.post('/reg/piccaptcha', reg.checkCode, reg.picCaptcha);
router.post('/reg/msgcaptcha', reg.checkMobileMiddleware, reg.msgCaptcha);
router.post('/reg/sendBindMsg', reg.checkMobileMiddleware, reg.checkCode, reg.sendBindMsg);
router.post('/reg/mobileregister', reg.checkMobileMiddleware, reg.checkPassword, reg.checkCode, reg.mobileRegister);
router.post('/reg/msgcaptcha', reg.msgCaptcha);
router.post('/reg/sendBindMsg', reg.checkCode, reg.sendBindMsg);
router.post('/reg/mobileregister', reg.checkPassword, reg.checkCode, reg.mobileRegister);
router.get('/reg/success', reg.success);
/**
... ...
... ... @@ -43,7 +43,7 @@
<form id="back-form" class="back-form" action="/passport/back/email" method="post">
<li class="clearfix">
<select id="area" class="country-list" name="region">
<select id="area" class="country-list" name="area">
{{#each region}}
<option {{#if selected}}selected="selected"{{/if}} value="{{areaCode}}">{{name}}</option>
{{/each}}
... ...
... ... @@ -10,7 +10,11 @@
</li>
<li>
<div id="name" class="title center">
<span>咸鸭蛋</span>
{{#if name}}
<span>{{name}}</span>
{{^}}
<span>咸鸭蛋</span>
{{/if}}
</div>
</li>
... ...
... ... @@ -47,8 +47,8 @@
</li>
<li class="clearfix">
<span class="remember-me checked">
<span class="iconfont checkbox small">&#xe602;</span>
<span class="remember-me">
<span class="iconfont checkbox small">&#xe601;</span>
下次自动登录
</span>
... ...
... ... @@ -30,7 +30,65 @@ const product = (req, res, next) => {
code: 403,
message: '请登录后执行该操作',
data: {
refer: helpers.urlFormat('/signin')
refer: helpers.urlFormat('/passport/login')
}
});
}
res.json(resData);
};
const brand = (req, res, next) => {
let uid = req.user.uid;
let pid = req.body.brandId;
let type = (req.body.type === 'add');
let resData = {
code: 400,
message: '操作失败'
};
if (uid) {
if (pid) {
fav.toggleFavBrand(pid, uid, type).then(result => {
res.json(result);
}).catch(next);
return;
}
} else {
Object.assign(resData, {
code: 403,
message: '请登录后执行该操作',
data: {
refer: helpers.urlFormat('/passport/login')
}
});
}
res.json(resData);
};
const shop = (req, res, next) => {
let uid = req.user.uid;
let pid = req.body.shopId;
let type = (req.body.type === 'add');
let resData = {
code: 400,
message: '操作失败'
};
if (uid) {
if (pid) {
fav.toggleFavShop(pid, uid, type).then(result => {
res.json(result);
}).catch(next);
return;
}
} else {
Object.assign(resData, {
code: 403,
message: '请登录后执行该操作',
data: {
refer: helpers.urlFormat('/passport/login')
}
});
}
... ... @@ -38,5 +96,7 @@ const product = (req, res, next) => {
};
module.exports = {
product // 组件demo页
product,
brand,
shop
};
... ...
... ... @@ -9,246 +9,30 @@ const _ = require('lodash');
const Item = require('../models/item');
const index = (req, res, next) => {
// let data = {
// brandBanner: {
// bgColor: '#93897d',
// brandLogo: {
// link: '#',
// img: 'http://placehold.it/{width}x{height}'
// },
// brandHome: {
// link: '#'
// }
// },
// nav: [
// {
// link: '#',
// name: 'MEN首页'
// },
// {
// link: '#',
// name: '上衣'
// },
// {
// link: '#',
// name: '卫衣'
// },
// {
// name: 'Spring 2016NEWT-Shirt 2016迷彩蝴蝶夹克'
// }
// ],
// goodInfo: {
// name: 'Spring 2016NEWT-Shirt 2016迷彩蝴蝶夹克',
// brandName: 'Supreme',
// intro: '2016最新发布',
// img: 'http://placehold.it/{width}x{height}',
// sellPrice: 3199,
// marketPrice: 4009,
// colors: [
// {
// name: '黑色',
// title: '黑色',
// focus: true,
// thumbs: [
// 'http://placehold.it/{width}x{height}',
// 'http://placehold.it/{width}x{height}',
// 'http://placehold.it/{width}x{height}',
// 'http://placehold.it/{width}x{height}',
// 'http://placehold.it/{width}x{height}'
// ],
// sizes: [
// {
// name: 'S',
// title: 'S',
// sku: '12313',
// num: 10
// },
// {
// name: 'M',
// title: 'M',
// sku: '12314',
// num: 14
// },
// {
// name: 'L',
// title: 'L',
// sku: '12315',
// num: 0
// },
// {
// name: 'XL',
// title: 'XL',
// sku: '12316',
// num: 0
// }
// ],
// rgb: '#000'
// },
// {
// name: '黄色',
// title: '黄色',
// thumbs: [
// 'http://placehold.it/{width}x{height}',
// 'http://placehold.it/{width}x{height}'
// ],
// rgb: '#efdc0e',
// sizes: [
// {
// name: 'S',
// title: 'S',
// sku: '12313',
// num: 0
// },
// {
// name: 'M',
// title: 'M',
// sku: '12314',
// num: 14
// },
// {
// name: 'L',
// title: 'L',
// sku: '12315',
// num: 0
// },
// {
// name: 'XL',
// title: 'XL',
// sku: '12316',
// num: 23
// }
// ]
// },
// {
// name: '蓝色',
// title: '蓝色',
// thumbs: [
// 'http://placehold.it/{width}x{height}',
// 'http://placehold.it/{width}x{height}',
// 'http://placehold.it/{width}x{height}',
// 'http://placehold.it/{width}x{height}'
// ],
// rgb: '#2ea8e6'
// },
// {
// name: '绿色',
// title: '绿色',
// thumbs: [
// 'http://placehold.it/{width}x{height}',
// 'http://placehold.it/{width}x{height}',
// 'http://placehold.it/{width}x{height}',
// 'http://placehold.it/{width}x{height}'
// ],
// rgb: '#85b2ef'
// }
// ]
// },
// description: {
// titleEn: 'DESCRIPTION',
// titleCn: '商品信息',
// basic: [
// {
// key: '编号',
// value: '51144694'
// },
// {
// key: '颜色',
// value: '灰色'
// },
// {
// key: '性别',
// value: '男款'
// },
// {
// key: '经典款型',
// value: '灰色'
// }
// ]
// },
// material: {
// titleEn: 'MATERIALS',
// titleCn: '材料洗涤',
// detail: [
// {
// img: 'http://placehold.it/{width}x{height}',
// name: '皮革',
// nameEn: 'Leather',
// text: '不适宜沾水,避免硬物划花,使用专用清洁膏擦拭。长时间不着用,可用软毛巾抹掉表面尘土,上一层皮革保养油。建议几双鞋交替穿着,不穿时放置通风处保持鞋内干爽。'
// }
// ],
// wash: [
// {
// img: 'http://placehold.it/{width}x{height}',
// name: '分色洗涤'
// }
// ]
// },
// sizeInfo: {
// titleEn: 'SIZEINFO',
// titleCn: '尺码信息',
// param: {
// thead: [
// {
// width: 126,
// name: '吊牌尺码'
// },
// {
// width: 126,
// name: '后衣长'
// },
// {
// width: 126,
// name: '前衣长'
// }
// ],
// tbody: [
// ['XS', 66, 66],
// ['S', 66, 66],
// ['L', 66, 66]
// ]
// },
// taste: {
// thead: [
// {
// width: 170,
// name: '模特'
// },
// {
// width: 126,
// name: '身高'
// },
// {
// width: 126,
// name: '体重'
// }
// ],
// tbody: [
// [{
// img: 'http://placehold.it/{width}x{height}',
// name: 'Steven'
// }, 187, 66],
// [{
// img: 'http://placehold.it/{width}x{height}',
// name: 'Oliver'
// }, 183, 66]
// ]
// }
// },
// details: {
// titleEn: 'DETAILS',
// titleCn: '商品详情',
// content: 'aaaa'
// }
// };
Item.getProductItemData(req.params, req.user.uid).then(result => {
Item.getProductItemData(req.params, req.url, req.user.uid).then(result => {
if (_.isEmpty(result)) {
return next();
}
result.page = 'item';
res.display('item', result);
}).catch(next);
};
const getProductInfo = (req, res, next) => {
const productId = req.query.productId;
const skn = req.query.skn;
let uid;
if (req.user && req.user.uid) {
uid = req.user.uid;
}
Item.getProductInfo(productId, skn, uid).then(result => {
res.json(result);
}).catch(next);
};
module.exports = {
index // 组件demo页
index, // 组件demo页
getProductInfo
};
... ...
... ... @@ -10,7 +10,8 @@ const list = {
index: (req, res, next) => {
let q = req.query;
q.page = q.page || 1;
q.page = parseInt(q.page || 1, 10);
q.order = q.order || 's_n_desc';
let retData = {
module: 'product',
... ... @@ -26,6 +27,7 @@ const list = {
if (data.filter) {
retData.filter = DataHelper.filterHandle(data.filter, q);
retData.filter.showPrice = data.total > 10;
nav = _.concat(nav, retData.filter.nav);
}
... ... @@ -54,7 +56,8 @@ const list = {
newPage: (req, res, next) => {
let q = req.query;
q.page = q.page || 1;
q.page = parseInt(q.page || 1, 10);
q.order = q.order || 's_n_desc';
let retData = {
module: 'product',
... ... @@ -76,6 +79,7 @@ const list = {
if (data.filter) {
retData.filter = DataHelper.filterHandle(data.filter, q);
retData.filter.showPrice = data.total > 10;
}
retData.navPath = {
... ...
... ... @@ -16,13 +16,16 @@ const DataHelper = require('../models/helpers');
const Query = {
index: (req, res, next) => {
let q = req.query;
let query = q.query || '';
q.page = q.page || 1;
q.page = parseInt(q.page || 1, 10);
q.order = q.order || 's_n_desc';
let retData = {
module: 'product',
page: 'list',
title: '列表'
title: '列表',
query: query
};
Search.queryProduct(q).then(result => {
... ... @@ -32,11 +35,12 @@ const Query = {
let nav = [DataHelper.getChannelNav()];
nav.push({
name: `"${q.query}" ${data.total}个结果`
name: `"${query}" ${data.total}个结果`
});
if (data.filter) {
retData.filter = DataHelper.filterHandle(data.filter, q);
retData.filter.showPrice = data.total > 10;
}
retData.navPath = {
... ...
... ... @@ -15,6 +15,7 @@ const cookie = global.yoho.cookie;
const Search = require('../models/search');
const DataHelper = require('../models/helpers');
const ShopData = require('../models/shop-service');
const Editorial = require('../models/editorial');
const shop = {
index(req, res, next) {
... ... @@ -38,11 +39,45 @@ const shop = {
nav: nav
};
data.banner = result;
data.shopId = result.shopId;
data.mores = {};
result.menus.forEach(m => {
if (m.id) {
data.mores[m.id] = m;
}
});
return Promise.all([Search.queryProductOfBrand({
shop_id: result.shopId,
limit: 16,
page: 1
}), Editorial.getByBrand(result.brandId)]);
} else {
return false;
}
}).then(result => {
let productData = result[0];
let editorial = result[1];
data.showEditorial = editorial && editorial.length === 3;
data.editorial = editorial;
if (productData && productData.code === 200 && productData.data) {
let ret = camelCase(productData.data);
data.paginationData = {
page: 1,
limit: 16,
total: ret.total,
pageTotal: ret.pageTotal,
queryParams: req.query
};
data.products = DataHelper.handleProductList(ret.productList);
res.display('shop-index', data);
} else {
shop.list(req, res, next);
}
});
}).catch(next);
},
list(req, res, next) {
... ... @@ -57,11 +92,16 @@ const shop = {
let uid = cookie.getUid(req);
let q = req.query;
q.page = q.page || 1;
q.order = q.order || 's_n_desc';
q.page = parseInt(q.page || 1, 10);
ShopData.getShopHeadData(domain, uid).then(result => {
data.banner = result;
if (data.banner.banner) {
data.banner.banner = data.banner.banner.split('?')[0];
}
if (result.brandId) {
q.brand = result.brandId;
q.shop_id = result.shopId;
... ... @@ -80,6 +120,7 @@ const shop = {
if (ret.filter) {
delete q.brand;
data.filter = DataHelper.filterHandle(ret.filter, req.query);
data.filter.showPrice = ret.total > 10;
}
data.paginationData = {
... ... @@ -103,6 +144,46 @@ const shop = {
}
});
}).catch(next);
},
// 首页ajax加载所有商品
indexQuery(req, res, next) {
let shopId = req.query.shopId;
let page = parseInt(req.query.page || 1, 10);
let query = {
shop_id: shopId,
limit: 16,
page: page,
order: req.query.order || ''
};
let data = {};
return Search.queryProductOfBrand(query).then(result => {
if (result && result.code === 200 && result.data) {
let ret = camelCase(result.data);
data.paginationData = {
page: page,
limit: 16,
total: ret.total,
pageTotal: ret.pageTotal,
queryParams: req.query
};
let products = DataHelper.handleProductList(ret.productList);
products.forEach(p => {
p.defaultImages = global.yoho.helpers.image(p.defaultImages, 270, 366);
p.salesPrice = global.yoho.helpers.round(p.salesPrice, 2);
});
res.json(_.assign(data, {
products: products
}));
} else {
return Promise.reject('query shop index error');
}
}).catch(next);
}
};
... ...
... ... @@ -19,9 +19,9 @@ const getDomainInfo = domain => {
})();
};
const getBrandInfo = bid => {
const getBrandInfo = (bid, uid) => {
return co(function*() {
let brandInfo = yield api.getBrandInfo(bid);
let brandInfo = yield api.getBrandInfo(bid, uid);
if (!brandInfo.data || brandInfo.code !== 200) {
return {};
... ...
/**
* 获取店铺首页相关资讯
*
* @author: jiangfeng<jeff.jiang@yoho.cn>
* @date: 16/7/18
*/
const ServiceApi = global.yoho.ServiceAPI;
const camelCase = global.yoho.camelCase;
const editorial = {
getByBrand(brand) {
return ServiceApi.get('/guang/service/*/article/getArticleByBrand', {
brand_id: brand,
limit: 3
}).then(result => {
if (result && result.code === 200 && result.data) {
return camelCase(result.data);
} else {
return [];
}
});
}
};
module.exports = editorial;
... ...
... ... @@ -8,21 +8,21 @@
const api = global.yoho.API;
const addFavAsync = (uid, pid) => {
const addFavAsync = (uid, id, type) => {
return api.get('', {
method: 'app.favorite.add',
id: pid,
id: id,
uid: uid,
type: 'product'
type: type
});
};
const cancelFavAsync = (uid, pid) => {
const cancelFavAsync = (uid, id, type) => {
return api.get('', {
method: 'app.favorite.cancel',
fav_id: pid,
fav_id: id,
uid: uid,
type: 'product'
type: type
});
};
... ...
... ... @@ -10,13 +10,31 @@ const FavAPI = require('./favorite-api');
const toggleFavProduct = (productId, uid, isadd) => {
if (isadd) {
return FavAPI.addFavAsync(uid, productId);
return FavAPI.addFavAsync(uid, productId, 'product');
} else {
return FavAPI.cancelFavAsync(uid, productId);
return FavAPI.cancelFavAsync(uid, productId, 'product');
}
};
const toggleFavBrand = (brandId, uid, isadd) => {
if (isadd) {
return FavAPI.addFavAsync(uid, brandId, 'brand');
} else {
return FavAPI.cancelFavAsync(uid, brandId, 'brand');
}
};
const toggleFavShop = (shopId, uid, isadd) => {
if (isadd) {
return FavAPI.addFavAsync(uid, shopId, 'shop');
} else {
return FavAPI.cancelFavAsync(uid, shopId, 'shop');
}
};
module.exports = {
toggleFavProduct
toggleFavProduct,
toggleFavBrand,
toggleFavShop
};
... ...
... ... @@ -43,13 +43,17 @@ const helpers = {
},
colorConvert(colors) {
return colors.map((c) => {
return {
id: c.colorId,
title: c.colorName,
rgb: c.colorValue ? `url(${c.colorValue})` : '#' + c.colorCode
};
});
if (colors) {
return colors.map((c) => {
return {
id: c.colorId,
title: c.colorName,
rgb: c.colorValue ? `url(${c.colorValue})` : '#' + c.colorCode
};
});
} else {
return [];
}
},
getChannelNav() {
... ... @@ -106,6 +110,7 @@ const helpers = {
let brands = filter.brand;
let colors = this.colorConvert(filter.color);
let sorts = filter.groupSort;
let singleSort = false;
let filters = [];
let customPriceLow = '';
let customPriceHigh = '';
... ... @@ -117,34 +122,55 @@ const helpers = {
}
});
if (sorts && sorts.length === 1) {
singleSort = true;
if (sorts[0].sub && sorts[0].sub.length === 1) {
sorts[0].sub[0].checked = true;
}
sorts = sorts[0].sub;
}
let matchPrice = false;
priceRange = Object.keys(priceRange).map((k) => {
let prices = k.split(',');
let p = {
lower: prices[0],
higher: prices[1]
};
if (priceRange) {
priceRange = Object.keys(priceRange).map((k) => {
let prices = k.split(',');
let p = {
lower: prices[0],
higher: prices[1]
};
if (k === q.price) {
p.checked = true;
matchPrice = true;
filters.push(this.newFilter('price', q.price, ${prices[0]}-¥${prices[1]}`));
}
return p;
}).sort((a, b) => {
return a.lower - b.lower;
});
if (k === q.price) {
p.checked = true;
matchPrice = true;
}
return p;
}).sort((a, b) => {
return a.lower - b.lower;
});
if (!matchPrice && q.price) {
let prices = q.price.split(',');
let priceTxt = ${prices[0]}-¥${prices[1]}`;
customPriceLow = prices[0];
customPriceHigh = prices[1];
if (!matchPrice && q.price) {
let prices = q.price.split(',');
if (prices[1] === Number.MAX_SAFE_INTEGER.toString()) {
priceTxt = `大于¥${prices[0]}`;
customPriceHigh = '';
}
filters.push(this.newFilter('price', q.price, priceTxt));
filters.push(this.newFilter('price', q.price, ${prices[0]}-¥${prices[1]}`));
customPriceLow = prices[0];
customPriceHigh = prices[1];
}
}
if (!_.isArray(sizeInfo)) {
if (!_.isArray(sizeInfo) && sizeInfo) {
sizeInfo.checked = true;
sizeInfo = [sizeInfo];
}
... ... @@ -166,7 +192,9 @@ const helpers = {
return b.brandName;
}).join('、');
filters.push(this.newFilter('brand', q.brand, brandNames));
if (brandNames) {
filters.push(this.newFilter('brand', q.brand, brandNames));
}
}
if (q.color) {
... ... @@ -185,6 +213,7 @@ const helpers = {
return {
people: genders,
sortData: sorts,
singleSort: singleSort,
brandData: brands,
colors: colors,
size: sizeInfo,
... ... @@ -195,6 +224,7 @@ const helpers = {
customPriceLow: customPriceLow,
customPriceHigh: customPriceHigh,
showSize: !!q.sort,
showPrice: true,
nav: this.getSortNav(q.sort, sorts)
};
},
... ... @@ -209,11 +239,11 @@ const helpers = {
goodsId = goodsList[0].goodsId;
goodsList.forEach(o => {
o.url = `${config.siteUrl}/product/item/${g.productId}_${o.goodsId}.html`;
o.url = `${config.siteUrl}/product/pro_${g.productId}_${o.goodsId}/${o.cnAlphabet}.html`;
});
}
g.url = `${config.siteUrl}/product/item/${g.productId}_${goodsId}.html`;
g.url = `${config.siteUrl}/product/pro_${g.productId}_${goodsId}/${g.cnAlphabet}.html`;
});
}
return list;
... ...
... ... @@ -136,11 +136,34 @@ const _FashionTopGoodsStatus = (uid, showStatus, isBeginSale) => {
return resData;
};
const setSeoInfo = (goodInfo, nav) => {
let brandName = _.get(goodInfo, 'brandName', ''),
sortName = _.get(nav, '[1].name', '');
// if (goodInfo && goodInfo.brandName) {
// brandName = goodInfo.brandName;
// }
// if (!_.isEmpty(nav) && nav[1]) {
// sortName = nav[1].name;
// }
return {
title: `${brandName} ${sortName}|${goodInfo.name}正品`,
keywords: `${brandName} ${sortName},${brandName}正品官网专卖店,${brandName}官方授权店,${brandName}正品,` +
`${brandName}打折,${brandName}折扣店,${brandName}真品,${brandName}代购`,
description: _.get(goodInfo, 'share.shareDesc', goodInfo.name)
};
};
const setPathNav = (data, name) => {
let resData = {};
if (!_.isEmpty(data)) {
let navs = [];
let navs = [{
link: helpers.urlFormat(''),
name: 'MEN首页' // 待处理
}];
let sort = data.sort[0];
navs.push({
... ... @@ -185,6 +208,7 @@ const setPathNav = (data, name) => {
*/
const setBrandBanner = brand => {
let data = {
brandId: brand.id,
bgColor: '#000',
brandLogo: {
link: `/product/shop/${brand.brandDomain}`, // 品牌跳转链接 -- 待处理
... ... @@ -360,6 +384,14 @@ const setProductData = base => {
}
}
// 分享相关,产品的链接
resData.share = {
weixinUrl: helpers.urlFormat(base.mainPath),
shareTitle: resData.name,
shareImg: resData.img,
shareDesc: base.phrase
};
return resData;
};
... ... @@ -704,6 +736,7 @@ const setDetailData = sizeInfo => {
};
module.exports = {
setSeoInfo,
setBrandBanner,
setPathNav,
setProductData,
... ...
... ... @@ -7,6 +7,7 @@
const _ = require('lodash');
const itemAPI = require('./item-api');
const brandAPI = require('./brand-api');
const itemFUN = require('./item-handler');
const search = require('./search-api');
... ... @@ -14,8 +15,7 @@ const search = require('./search-api');
const _getMultiResourceByBaseInfo = (base) => {
let productId = base.id;
let skn = base.erpProductId;
// let brandId = base.brand.id ? base.brand.id : 0;
let brandId = base.brand.id ? base.brand.id : 0;
// 获取相关数据
let promiseData = [
... ... @@ -27,6 +27,7 @@ const _getMultiResourceByBaseInfo = (base) => {
if (base.uid) {
promiseData.push(itemAPI.getUserIsFav(base.uid, productId));
promiseData.push(brandAPI.getBrandInfo(brandId, base.uid));
}
return Promise.all(promiseData).then(result => {
... ... @@ -35,12 +36,13 @@ const _getMultiResourceByBaseInfo = (base) => {
comfort: result[1].data,
modelTry: result[2].data,
sort: result[3].data,
productFav: (result[4] && result[4].data)
productFav: (result[4] && result[4].data),
brandFav: (result[5] && result[5].data && result[5].data.is_favorite === 'Y')
};
});
};
let getProductItemData = (params, uid) => {
let getProductItemData = (params, url, uid) => {
let pid = params[0];
// let gid = params[1];
... ... @@ -55,6 +57,7 @@ let getProductItemData = (params, uid) => {
}
result.uid = uid;
result.mainPath = url;
// 商品基本信息
data.goodInfo = itemFUN.setProductData(result);
... ... @@ -67,12 +70,14 @@ let getProductItemData = (params, uid) => {
}
return _getMultiResourceByBaseInfo(result).then(mulRes => {
// 面包屑导航
Object.assign(data, itemFUN.setPathNav(mulRes.sort, result.productName));
// 收藏状态
_.set(data, 'brandBanner.brandFav', mulRes.brandFav);
_.set(data, 'goodInfo.productFav', mulRes.productFav);
// 面包屑导航
Object.assign(data, itemFUN.setPathNav(mulRes.sort, result.productName));
// DESCRIPTION商品描述
Object.assign(data, itemFUN.setDescriptionData(mulRes.sizeInfo, mulRes.comfort));
... ... @@ -85,12 +90,30 @@ let getProductItemData = (params, uid) => {
// DETAILS商品详情
Object.assign(data, itemFUN.setDetailData(mulRes.sizeInfo));
// 商品详情SEO
Object.assign(data, itemFUN.setSeoInfo(data.goodInfo, data.nav));
return data;
});
});
};
/**
* 获取商品尺寸,颜色,和缩略图
* @function getProductInfo
* @param { Number } productId 商品ID
* @param { String } uid 用户ID
* @param { Number } skn 商品skn
* @return { Object } 接口返回单个商品的基本信息
*/
const getProductInfo = (productId, uid, skn) => {
return itemAPI.getProductBaseAsync(productId, uid, skn).then(result => {
return itemFUN.setProductData(result);
});
};
module.exports = {
getProductItemData
getProductItemData,
getProductInfo
};
... ...
... ... @@ -3,12 +3,22 @@
const api = global.yoho.API;
const _ = require('lodash');
function clearEmptyVal(obj) {
function _paramHanlde(obj) {
_.keys(obj).forEach(k => {
if (obj[k] === null || obj[k] === '') {
_.unset(obj, k);
}
});
if (obj.price) {
let prices = obj.price.split(',');
if (!prices[1]) {
prices[1] = Number.MAX_SAFE_INTEGER;
obj.price = prices.join(',');
}
}
return obj;
}
... ... @@ -20,7 +30,7 @@ const Search = {
limit: 45
};
Object.assign(finalParams, clearEmptyVal(params));
Object.assign(finalParams, _paramHanlde(params));
return api.get('', finalParams);
},
... ... @@ -30,7 +40,7 @@ const Search = {
limit: 45
};
Object.assign(finalParams, clearEmptyVal(params));
Object.assign(finalParams, _paramHanlde(params));
return api.get('', finalParams);
},
... ... @@ -40,7 +50,7 @@ const Search = {
limit: 45
};
Object.assign(finalParams, clearEmptyVal(params));
Object.assign(finalParams, _paramHanlde(params));
return api.get('', finalParams);
},
... ...
... ... @@ -21,10 +21,10 @@ const _ = require('lodash');
*/
function shopMenu(domain) {
let menus = [
{name: '店铺首页', href: `/product/shop/${domain}`},
{name: '全部商品', href: `/product/shop/${domain}/list`, icon: '&#xe60a;'},
{name: '人气单品', href: `/product/shop/${domain}/list?order=xxx`},
{name: '新品上架', href: `/product/shop/${domain}/list?order=s_t_desc`}
{id: 'index', name: '店铺首页', href: `/product/shop/${domain}`},
{id: 'all', name: '全部商品', href: `/product/shop/${domain}/list`, icon: '&#xe60a;'},
{id: 'hot', name: '人气单品', href: `/product/shop/${domain}/list?order=s_n_desc`},
{id: 'new', name: '新品上架', href: `/product/shop/${domain}/list?order=s_t_desc`}
];
return menus;
... ...
... ... @@ -18,11 +18,15 @@ const query = require(cRoot + '/query');
router.get('/list', list.index); // 列表页面
router.get('/list/new', list.newPage); // 新品列表页
router.get(/\/item\/([\d]+)_([\d]+).html/, item.index); // 商品详情页
router.get(/\/pro_([\d]+)_([\d]+)\/(.*)/, item.index); // 商品详情routers
router.post('/item/togglecollect', fav.product); // 商品详情页
router.get('/item/getProductInfo', item.getProductInfo); // 商品详情信息
router.get('/shop/query/all', shop.indexQuery);
router.get('/shop/:domain/list', shop.list);
router.get('/shop/:domain', shop.index);
router.post('/shop/togglecollect', fav.shop);
router.post('/brand/togglecollect', fav.brand);
router.get('/query', query.index);
... ...
... ... @@ -93,6 +93,28 @@
<span>限购码已抢光</span>
{{/if}}
{{/ fashionTopGoods}}
{{#if soldOut}}
{{!-- <span>
点击
<i class="arr-notice blue">到货通知</i>
,到货第一时间通知您
</span> --}}
<script type="text/html" id="arrival-notice-tpl">
// <h1>到货通知</h1>
// <p>商品一旦在30日内到货,我们将会第一时间通知您,请及时关注哦!</p>
// <div class="phone-num">手机号<input type="text" class="notice-phone"></div>
// <p>
// <span class="iconfont add-fav checked">&#xe602;</span>
// 添加到收藏夹
// </p>
</script>
<script type="text/html" id="arrival-notice-success-tpl">
// <h1>到货通知</h1>
// <p>商品订阅到货通知成功!</p>
</script>
{{/if}}
</div>
<p class="btns">
{{#unless soldOut}}
... ... @@ -115,7 +137,7 @@
</span>
{{/if}}
{{/unless}}
<span id="sold-out" class="btn disable hide">已售罄</span>
<span id="sold-out" class="btn disable{{#unless soldOut}} hide{{/unless}}">已售罄</span>
<span id="collect-product" class="btn white{{#if productFav}} coll{{/if}}">
<span class="collecting">
<i class="iconfont">&#xe644;</i>
... ...
... ... @@ -4,24 +4,31 @@
{{> path-nav}}
{{/ navPath}}
</div>
<div class="center-content clearfix">
<div class="left">
{{!-- 筛选区域 --}}
{{#filter}}
{{> list/filter}}
{{> list/filter}}
{{/filter}}
</div>
<div class="right">
{{!-- 已选中条件 --}}
{{#filter}}
{{> list/filter-area}}
{{> list/filter-area}}
{{/filter}}
{{#if paginationData.total}}
{{!-- 排序 --}}
{{> list/order-area}}
{{!-- 商品列表 --}}
{{> list/goods-box}}
{{!-- 分页 --}}
{{{ pagination paginationData }}}
{{> list/order-area}}
{{!-- 商品列表 --}}
{{> list/goods-box}}
{{!-- 分页 --}}
{{{ pagination paginationData }}}
{{^}}
{{> list/empty}}
{{/if}}
</div>
</div>
</div>
... ...