Authored by 梁志锋

merger 商品详情页

... ... @@ -100,7 +100,6 @@ try {
// YOHO 后置中间件
app.use(errorHanlder.serverError());
} catch (err) {
console.error(err);
logger.error(err);
}
... ...
... ... @@ -10,8 +10,11 @@ const mRoot = '../models';
const headerModel = require('../../../doraemon/models/header'); // 头部model
const detailModel = require(`${mRoot}/detail`); // 商品详情 model
const introModel = require(`${mRoot}/intro`); // 商品尺码信息 model
const preference = require(`${mRoot}/preference`); // 商品偏好 model
const preferenceModel = require(`${mRoot}/preference`); // 商品偏好 model
const detailRelated = require(`${mRoot}/consult-comment`); // 商品评论咨询 model
const _ = require('lodash');
const helpers = global.yoho.helpers;
/**
* 商品基本信息
... ... @@ -34,6 +37,9 @@ exports.index = (req, res, next) => {
uid: uid,
ua: req.get('user-agent') || ''
}).then((result) => {
if (_.isEmpty(result)) {
return next();
}
res.render('detail/detail', {
pageHeader: headerData,
result: result,
... ... @@ -71,8 +77,8 @@ exports.intro = (req, res, next) => {
* @param {[type]} res [description]
* @return {[type]} [description]
*/
exports.preference = (req, res) => {
preference({
exports.preference = (req, res, next) => {
preferenceModel({
productskn: req.query.productSkn,
yhchannel: req.yoho.channel,
brandId: req.query.brandId
... ... @@ -80,19 +86,24 @@ exports.preference = (req, res) => {
res.render('detail/preference', Object.assign({
layout: false
}, result));
});
}).catch(next);
};
/**
* 购买评价页
*/
exports.comments = (req, res, next) => {
if (!req.query.product_id) {
return next();
}
let headerData = headerModel.setNav({
navTitle: '购买评价'
});
detailRelated.comments(req.query).then((result) => {
res.render('detail/comments', Object.assign({
title: '购买评价',
pageHeader: headerData,
pageFooter: true
}, result));
... ... @@ -103,12 +114,17 @@ exports.comments = (req, res, next) => {
* 购买咨询
*/
exports.consults = (req, res, next) => {
if (!req.query.product_id) {
return next();
}
let headerData = headerModel.setNav({
navTitle: '购买咨询'
});
detailRelated.consults(req.query).then((result) => {
res.render('detail/consults', Object.assign({
title: '购买咨询',
pageHeader: headerData,
pageFooter: true
}, result));
... ... @@ -116,17 +132,46 @@ exports.consults = (req, res, next) => {
};
/**
* 咨询点赞
*/
exports.consultUpvoteOrUseful = (req, res, next) => {
let uid = req.user.uid || 0;
if (!uid) {
return res.json({
code: 401,
message: '用户id为空',
data: helpers.urlFormat('/signin.html', {
refer: helpers.urlFormat('/product/detail/consults', {
product_id: req.body.product_id,
total: req.body.total
})
})
});
}
req.body.isUpvote = /upvote/.test(req.path);
req.body.uid = uid;
detailRelated.upvoteConsult(req.body).then((result) => {
res.json(result);
}).catch(next);
};
/**
* 咨询表单页
*/
exports.consultform = (req, res, next) => {
if (!req.query.product_id) {
return next();
}
let headerData = headerModel.setNav({
navTitle: '我要咨询'
});
if (!req.query.product_id) {
return next();
}
res.render('detail/consult-form', {
title: '我要咨询',
pageHeader: headerData,
productId: req.query.product_id,
formUrl: '/product/detail/consultsubmit',
... ...
... ... @@ -6,8 +6,9 @@
'use strict';
const api = global.yoho.API;
const _ = require('lodash');
const api = global.yoho.API;
const helpers = global.yoho.helpers;
/**
* 获取默认咨询列表
... ... @@ -31,33 +32,6 @@ const _getCommonConsult = () => {
};
/**
* 处理评价列表数据
* @data {[object]} 评价列表原始数据
* @return {[object]}
*/
const _formatCommentsList = (data) => {
let comment = {
list: [],
total: 0
};
if (data.length) {
_.forEach(data, (value) => {
comment.list.push({
userName: value.nickname,
desc: `${value.color_name}/${value.size_name}`,
content: value.content,
time: value.create_time
});
comment.total = value.total;
});
}
return comment;
};
/**
* 处理咨询列表数据
* @data {[object]} 咨询列表原始数据
* @return {[object]}
... ... @@ -84,34 +58,6 @@ const _formatConsultsList = (data) => {
};
/**
* 获取评价数据
* @id {[number]} 商品id
* @page {[number]} 页码
* @limit {[number]} 每页评价数量
* @return {[object]}
*/
const _getComments = (id, page, limit) => {
let params = {
method: 'app.comment.li',
product_id: id,
page: page ? page : 1,
limit: limit ? limit : 300
};
return api.get('', params, {
code: 200
}).then(result => {
let data = {};
if (result.data) {
Object.assign(data, _formatCommentsList(result.data));
}
return data;
});
};
/**
* 获取咨询数据
* @id {[number]} 商品id
* @page {[number]} 页码
... ... @@ -144,19 +90,62 @@ const _getConsults = (id, page, limit) => {
};
/**
* 处理评论数据
*/
let _processComment = (data) => {
let result = {
commentsNum: data.pageResponse.totalCount,
comments: []
};
_.forEach(data.pageResponse.list, (item) => {
result.comments.push({
userName: item.userInfo.nickName,
desc: `${item.goods.color_name}/${item.goods.size_name}`,
content: item.content,
time: helpers.dateFormat('YYYY-MM-DD HH:mm:ss', new Date(item.createTime * 1000))
});
});
return result;
};
/**
* 获取评论信息
*/
let getCommentInfo = (params) => {
return api.get('', Object.assign({
method: 'show.productShareOrderList',
limit: '1',
page: '1',
filterId: '7'
}, params), {
cache: true
}).then((result) => {
if (result.code === 200) {
return _processComment(result.data);
}
return {};
});
};
/**
* 购买评价列表
* @param {[object]} 查询参数
* @return {[object]}
*/
let comments = (params) => {
return _getComments(params.product_id, 1, 60).then(result => {
return getCommentInfo({
productId: params.product_id,
limit: '60'
}).then(result => {
let data = {};
if (result.list && result.list.length) {
if (result.total) {
_.set(data, 'pageHeader.navTitle', `购买评价(${result.total})`);
if (result.comments && result.comments.length) {
if (result.commentsNum) {
_.set(data, 'pageHeader.navTitle', `购买评价(${result.commentsNum})`);
}
data.comments = result.list;
data.comments = result.comments;
}
return data;
... ... @@ -186,10 +175,20 @@ let consults = (params) => {
data.consults = result[1].list;
}
data.showReadMore = result[1].list.length > 2;
return data;
});
};
let upvoteConsult = (params) => {
return api.get('', {
method: params.isUpvote ? 'app.consult.like' : 'app.consult.useful',
id: params.id,
uid: params.uid
});
};
/**
* 购买咨询列表
* @uid {[number]} 用户id
... ... @@ -214,7 +213,9 @@ let addConsult = (uid, productId, content) => {
};
module.exports = {
getCommentInfo, // 商品详情相关,获取评价,来自晒单
comments, // 商品详情相关-购买评价
consults, // 商品详情相关-购买咨询
addConsult // 商品详情相关-添加咨询
addConsult, // 商品详情相关-添加咨询
upvoteConsult // 咨询点赞
};
... ...
... ... @@ -6,8 +6,10 @@
'use strict';
const api = global.yoho.API;
const _ = require('lodash');
const comment = require('./consult-comment');
const api = global.yoho.API;
const helpers = global.yoho.helpers;
/**
... ... @@ -237,23 +239,6 @@ const _detailDataPkg = (origin, uid, vipLevel, ua) => {
dest.periodOfMarket = `${origin.expectArrivalTime}月`;
}
// 促销信息 TODO: 换新接口
if (origin.promotionBoList) {
let discountList = [];
_.forEach(origin.promotionBoList, function(value) {
discountList.push({
text: `【${value.promotionType}${value.promotionTitle}`
});
});
if (discountList.length) {
dest.goodsDiscount = {
list: discountList
};
}
}
// 商品咨询
dest.feedbacks = {
consults: [],
... ... @@ -277,7 +262,7 @@ const _detailDataPkg = (origin, uid, vipLevel, ua) => {
if (_.has(dest, 'feedbacks.consultsNum')) {
consultParams.total = dest.feedbacks.consultsNum;
dest.feedbacks.consultsUrl = helpers.urlFormat('/product/detail/consult', consultParams);
dest.feedbacks.consultsUrl = helpers.urlFormat('/product/detail/consults', consultParams);
} else {
dest.feedbacks.consultsUrl = helpers.urlFormat('/product/detail/consultform', consultParams);
}
... ... @@ -367,7 +352,7 @@ const _detailDataPkg = (origin, uid, vipLevel, ua) => {
};
allSizeList[sizeName] = (allSizeList[sizeName] === null ||
typeof allSizeList[sizeName] === 'undefined') ? build :
typeof allSizeList[sizeName] === 'undefined') ? build :
allSizeList[sizeName];
colorStorageNum += parseInt(size.goodsSizeStorageNum, 10);
... ... @@ -399,10 +384,10 @@ const _detailDataPkg = (origin, uid, vipLevel, ua) => {
sizeGroup[0] = {
size: []
};
_.forEach(allSizeList, function(value) {
_.forEach(allSizeList, function(value, key) {
// 默认尺码
sizeGroup[0].size.push({
name: sizeName,
name: key,
sizeNum: _.toNumber(value.storage) > 0 ? true : false,
id: value.id
});
... ... @@ -415,10 +400,10 @@ const _detailDataPkg = (origin, uid, vipLevel, ua) => {
_.forEach(colorList, function(colorArr) {
colorArr.colorNum = 0;
if (colorStorageGroup[colorArr.skcId] &&
colorStorageGroup[colorArr.skcId][sizeName]) {
colorArr.colorNum = colorStorageGroup[colorArr.skcId][sizeName];
colorStorageGroup[colorArr.skcId][key]) {
colorArr.colorNum = colorStorageGroup[colorArr.skcId][key];
}
colorGroup[i].color.push(colorArr);
colorGroup[i].color.push(Object.assign({}, colorArr));
});
colorGroup[i].id = value.id;
... ... @@ -443,6 +428,7 @@ const _detailDataPkg = (origin, uid, vipLevel, ua) => {
++i;
});
// 商品图:多个
if (goodsGroup.length > 1) {
let bannerList = [];
... ... @@ -492,7 +478,7 @@ const _detailDataPkg = (origin, uid, vipLevel, ua) => {
if (origin.isLimitBuy === 'Y') {
// 是否开售
let isBeginSale = (origin.saleStatus !== null && typeof origin.saleStatus !== 'undefined' &&
origin.saleStatus === 1);
origin.saleStatus === 1);
// 限购商品有关的展示状态
let showStatus = 1;
... ... @@ -560,6 +546,28 @@ let _getPromotionInfo = (skn) => {
});
};
/**
* 获取默认咨询列表
*/
const _getCommonConsult = () => {
let params = {
method: 'app.consult.common'
};
return api.get('', params, {
code: 200
}).then(result => {
let data = {};
if (result.data) {
data = result.data;
}
return data;
});
};
let getProductData = (data) => {
let finalResult;
let params = {
... ... @@ -577,12 +585,32 @@ let getProductData = (data) => {
return api.get('', params, {
cache: true
}).then(result => {
return Promise.all([_getShopsInfo(result.brandId), _getPromotionInfo(result.erpProductId)]).then((info) => {
if (result.code === 500) {
return {};
}
return Promise.all([
_getShopsInfo(result.brandId),
_getPromotionInfo(result.erpProductId),
comment.getCommentInfo({
productId: result.id
}),
_getCommonConsult()
]).then((info) => {
result.promotionBoList = info[1];
finalResult = _detailDataPkg(result, data.uid, data.vipLevel, data.ua);
finalResult.enterStore = info[0];
Object.assign(finalResult.feedbacks, info[2]);
if (!_.isEmpty(info[3]) && !_.get(info[2], 'feedbacks.consultsNum', 0)) {
Object.assign(finalResult.feedbacks, {
commonConsults: true,
consultsNum: true,
consults: _.take(info[3], 2)
});
}
return finalResult;
});
... ...
... ... @@ -32,9 +32,12 @@ router.get('/detail/intro/:productskn', detail.intro); // 商品内嵌页
router.get('/detail/preference', detail.preference); // 为你优选
router.get('/detail/consults', detail.consults); // 商品咨询页
router.get('/detail/consultform', auth, detail.consultform); // 商品咨询表单页
router.get('/detail/comments', detail.comments);
router.get('/detail/comments', detail.comments); // 商品评价
router.post('/detail/consultsubmit', auth, detail.consultsubmit); // 商品咨询提交接口
router.post('/detail/consultupvote', detail.consultUpvoteOrUseful); // 商品咨询提交接口
router.post('/detail/consultuseful', detail.consultUpvoteOrUseful); // 商品咨询提交接口
router.get('/sale', sale.index);
router.get('/sale/discount', sale.discount);
router.get('/sale/discount/detail', sale.discountDetail);
... ...
... ... @@ -9,8 +9,8 @@
</div>
{{/ comments}}
</div>
{{#if loadmore}}
<input id="loadMoreUrl" type="hidden" value="{{loadMoreUrl}}">
{{/if}}
</div>
\ No newline at end of file
</div>
... ...
... ... @@ -66,4 +66,4 @@
{{/ faq}}
</div>
{{/if}}
</div>
\ No newline at end of file
</div>
... ...
<ul id="nav-tab" class="nav-tab clearfix">
<li class="comment-nav tap-hightlight">商品评价(<span class="comments-num">{{commentsNum}}</span>)</li>
<li class="consult-nav tap-hightlight">购买咨询(<span class="consults-num">{{consultsNum}}</span>)</li>
{{#if commonConsults}}
<li class="consult-nav tap-hightlight">常见问题</li>
{{^}}
<li class="consult-nav tap-hightlight">购买咨询(<span class="consults-num">{{consultsNum}}</span>)</li>
{{/if}}
</ul>
<div id="feedback-content" >
<div class="comment-content content ">
... ...

6.28 KB | W: | H:

4.79 KB | W: | H:

  • 2-up
  • Swipe
  • Onion skin
... ... @@ -41,6 +41,7 @@ var navtabEle = document.getElementById('nav-tab'),
$('#feedback-content .consult-content').removeClass('hide');
}
$('.goods-consults .consult-item:lt(2)').removeClass('hide');
}());
if (navtabHammer) {
... ... @@ -91,8 +92,7 @@ if ($('.goods-consults-page').length > 0) {
if (readmoreHammer) {
readmoreHammer.on('tap', function() {
$('.readmore').hide();
$('.goods-consults.customer-consults').removeClass('customer-consults');
$('.goods-consults').find('.consult-item').removeClass('hide');
return false;
});
}
... ...
... ... @@ -47,28 +47,27 @@ function hiddenTips($ele) {
// }
// }
function wrapElements(selector, count) {
var elArr = null;
// function wrapElements(selector, count) {
// var elArr = null;
$(selector).each(function(idx) {
elArr = $(selector).slice(idx, idx + count);
// $(selector).each(function(idx) {
// elArr = $(selector).slice(idx, idx + count);
if (elArr.length === count && idx % count === 0) {
$(elArr).wrapAll($('<div class="js-wraper"></div>'));
}
});
}
// if (elArr.length === count && idx % count === 0) {
// $(elArr).wrapAll($('<div class="js-wraper"></div>'));
// }
// });
// }
function search() {
if (searching || end) {
if (searching || end || !introUrl) {
return;
}
searching = true;
// alert($('#reference-swiper-container .swiper-wrapper').width());
loading.showLoadingMask();
$.ajax({
... ... @@ -98,7 +97,7 @@ function search() {
// if (!isFlexSupport()) {
// $('.detail .column').removeClass('column').addClass('oldbox');
// }
wrapElements('.detail .column', 2);
// wrapElements('.detail .column', 2);
searching = false;
end = true;
loading.hideLoadingMask();
... ...
... ... @@ -56,26 +56,28 @@ $basicBtnC: #eb0313;
&.table {
width: 100%;
.js-wraper {
display: flex;
flex-wrap: wrap;
justify-content: flex-start;
}
overflow: hidden;
.column {
display: flex;
flex-basis: 49.9%;
align-items: center;
box-sizing: border-box;
padding: 6px 3%;
width: 49.9%;
border: 1px solid #fff;
background-color: $tableCellC;
word-wrap: break-word;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
font-size: 24px;
}
.column:nth-child(2n+1) {
float: left;
}
.column:nth-child(2n+2) {
float: right;
}
.oldbox {
float: left;
overflow: hidden;
... ... @@ -384,13 +386,13 @@ $basicBtnC: #eb0313;
text-align: left;
.vip-img {
background: resolve('product/silver.png') no-repeat;
background: resolve("product/silver.png") no-repeat;
}
}
&:nth-child(2) {
.vip-img {
background: resolve('product/golden.png') no-repeat;
background: resolve("product/golden.png") no-repeat;
}
}
... ... @@ -398,7 +400,7 @@ $basicBtnC: #eb0313;
text-align: right;
.vip-img {
background: resolve('product/platinum.png') no-repeat;
background: resolve("product/platinum.png") no-repeat;
}
}
}
... ... @@ -744,15 +746,14 @@ $basicBtnC: #eb0313;
top: 0;
left: 48px;
display: block;
width: 72px;
height: 72px;
width: 30px;
height: 30px;
border-radius: 50%;
background: $basicBtnC;
color: #fff;
text-align: center;
font-size: 40px;
line-height: 72px;
transform: scale(0.5);
font-size: 20px;
line-height: 30px;
&.hide {
display: none;
... ... @@ -768,3 +769,7 @@ $basicBtnC: #eb0313;
top: 40%;
}
}
iframe {
display: none;
}
... ...
... ... @@ -4,10 +4,8 @@
padding-bottom: 20px;
.service {
margin-left: 50px;
width: 494px;
height: 28px;
background: resolve('product/service.png') no-repeat;
background: resolve("product/service.png") no-repeat;
background-size: cover;
}
... ...