Authored by 沈志敏

全球购详情页

... ... @@ -89,9 +89,27 @@ const detail = (req, res, next) => {
}).catch(next);
};
const gethtml = (req, res, next) => {
let skn = req.query.skn;
if (!skn) {
return next();
}
let params = {
product_skn: skn,
uid: req.user.uid || 0,
client_type: 'iphone' // todo
};
model.gethtml(params).then((html) => {
res.send(html);
}).catch(next);
}
module.exports = {
list,
search,
detail
detail,
gethtml
};
... ...
... ... @@ -3,6 +3,7 @@
const utils = '../../../utils';
const productProcess = require(`${utils}/product-process`);
const globalapi = global.yoho.GlobalAPI;
const $ = require('cheerio');
exports.list = (param) => {
return globalapi.get('product/api/v2/detail/getlist', param).then((result) => {
... ... @@ -35,7 +36,58 @@ exports.getBrand = (param) => {
};
exports.detail = (param) => {
return globalapi.get('product/api/v2/detail/get', param).then((data) => {
return data.data || {};
return globalapi.get('product/api/v2/detail/get', param).then((result) => {
if (!result || !result.data) {
return {};
}
result = result.data;
let goods = result.goods_list || [];
if (goods.length === 1) {
result.bannerTop = {
img: (goods[0].images_list[0] || {}).image_url
};
} else {
result.bannerTop = {
list: goods.map((g) => {
return {
img: (g.images_list[0] || {}).image_url
}
})
}
}
result.show_final_price = result.formart_final_price;
if (result.formart_final_price !== result.formart_orign_price) {
result.show_orign_price = result.formart_orign_price;
}
result.show_sales_price = result.format_sales_price;
if (result.format_market_price !== result.format_sales_price) {
result.show_market_price = result.format_market_price;
}
if (result.brand_info && result.brand_info.brand_id) {
result.brand_info.brand_url = `//m.yohobuy.com/product/global/list?brand=${result.brand_info.brand_id}`;
}
return result;
});
};
exports.gethtml = (param) => {
return globalapi.get('product/api/v1/detail/gethtml', param,{
cache: true
}).then((result) => {
result = result || '';
result = $.load(result);
result = result('.good-detail-page');
return (result.html() || '').replace(/<img src=/g, '<img class="lazy" src="data:image/gif;' +
'base64,R0lGODlhAQABAJEAAAAAAP///93d3f///yH5BAEAAAMALAAAAAABAAEAAAICVAEAOw=="' +
' data-original=').replace(/<img border="0" src=/g, '<img border="0" class="lazy" ' +
'src="data:image/gif;base64,' +
'R0lGODlhAQABAJEAAAAAAP///93d3f///yH5BAEAAAMALAAAAAABAAEAAAICVAEAOw=="' +
' data-original=');
});
}
... ...
... ... @@ -206,5 +206,6 @@ router.get('/index/allBrand', newShop.allBrand); // 店铺全部品牌
router.get('/global/list', globalPro.list); // 全球购列表页
router.get('/global/search', globalPro.search); // 全球购列表页搜索数据
router.get(/^\/global\/(\d+)\.html/, globalPro.detail); // 全球购店铺详情页
router.get('/global/gethtml', globalPro.gethtml); // 全球购商品信息
module.exports = router;
... ...
{{# result}}
<div id="global-detail-page" class="global-detail-page yoho-page" data-skn="{{product_skn}}">
<div class="banner-container">
<div class="global-tag">
<div class="global-country">
{{#isEqualOr is_plane 'Y'}}
<span class="global-plane"></span>
{{/isEqualOr}}
<span>{{country_name}}</span>
</div>
{{#isEqualOr is_limited 'Y'}}
<div class="global-limited">
<span>限量</span>
</div>
{{/isEqualOr}}
</div>
{{# bannerTop}}
{{> detail/banner-swiper-arrow}}
{{/ bannerTop}}
</div>
<div class="goods-name"><span class="name">{{product_name}}</span></div>
<div class="price-date">
<div>
<span class="final-price">{{show_final_price}}</span>
{{# show_orign_price}}
<span class="orign-price">{{.}}</span>
{{/ show_orign_price}}
</div>
<div>
<span class="sales-price">当前价:{{show_sales_price}}</span>
{{# show_market_price}}
<span class="market-price">原价:{{.}}</span>
{{/ show_market_price}}
</div>
</div>
<div class="country">
<span class="country-name">{{country_name}}</span>
<span class="product-source">{{product_source}}</span>
</div>
<div class="illustrate">
<div class="illustrate-title"></div>
<div class="illustrate-contents"></div>
</div>
{{# brand_info}}
<div class="enter-store">
{{#if brand_ico}}
<a class="store-logo" href="{{brand_url}}">
<img class="lazy" src="{{image2 brand_ico w=47 h=47 q=60}}" alt="{{brand_name}}">
</a>
{{/if}}
<a class="store-name" href="{{brand_url}}">{{brand_name}}</a>
<a class="store-link" href="{{brand_url}}">进入店铺<span class="iconfont">&#xe604;</span></a>
</div>
{{/ brand_info}}
<div class="customer-service">
<a href="{{customer_service}}">
<span class="customer-name">全球购购物须知</span>
<span class="customer-link iconfont">&#xe604;</span>
</a>
</div>
<div id="productDesc" class="product-desc"></div>
<div class="cart-bar">
<a href="javascript:;" class="num-incart iconfont">&#xe62c;</a>
<a href="javascript:;" class="addto-cart add-to-cart-url">下载APP购买</a>
</div>
</div>
{{/ result}}
... ...
'use strict';
import {
Controller
} from 'yoho-mvc';
import {
DetailView
} from './view';
import {
globalSearch as search
} from '../models';
class ListController extends Controller {
constructor() {
super();
this.detail = new DetailView();
this.created();
}
created() {
let skn = this.detail.getSkn();
if (!skn) {
return;
}
setTimeout(()=> {
search('//m.yohobuy.com/product/global/gethtml', {
skn: skn
}).then((html)=>{
this.detail.setDetailHtml(html)
})
}, 500);
}
}
module.exports = ListController;
\ No newline at end of file
... ...
require('product/global/detail.page.css');
const DetailController = require('./controller');
require('common/footer');
new DetailController();
... ...
import {
View
} from 'yoho-mvc';
let Swiper = require('yoho-swiper');
let lazyLoad = require('yoho-jquery-lazyload');
export class DetailView extends View {
constructor() {
super('#global-detail-page');
setTimeout(() => {
new Swiper('.banner-swiper', {
preloadImages: false,
lazyLoading: true,
lazyLoadingInPrevNext: true,
lazyLoadingOnTransitionStart: true,
paginationClickable: true,
pagination: '.banner-top .pagination-inner',
nextButton: '.my-swiper-button-next',
prevButton: '.my-swiper-button-prev',
spaceBetween: 3
});
}, 500);
let $cartBar = $('.cart-bar');
let timer = setInterval(function() {
if ($cartBar) {
window.reMarginFooter('.cart-bar');
clearInterval(timer);
} else {
$cartBar = $('.cart-bar');
}
}, 500);
}
setDetailHtml(htmldata) {
let $productDesc = $('#productDesc');
$productDesc.append(htmldata);
window.rePosFooter && window.rePosFooter();
lazyLoad($productDesc.find('img.lazy'));
this.productDescStyle();
}
productDescStyle() {
new Swiper('#swiper-recommend', {
slidesPerView: 'auto',
grabCursor: true,
slideElement: 'a',
lazyLoading: true,
watchSlidesVisibility: true
});
var $service = $('.service-cont'),
serviceH = $service.height(),
serviceLi = $service.find('li'),
showH = parseInt(serviceLi.eq(0).height()) + parseInt(serviceLi.eq(1).height()) - parseInt(serviceLi.eq(1).find('.service-answer').height()) / 2;
$service.css({
height: showH,
overflow: 'hidden'
});
this.operation = {
showH,
serviceH
}
this.on('click', '.service-operation', this.serviceOperation.bind(this));
}
serviceOperation(e,) {
function serviceState(opt) {
opt.dom.html(opt.txt + '<i class="service-icon shrink-btn-' + opt.btnClass + '"></i>');
$('.service-cont').animate({
height: opt.height
}, 0, function() {
$(this).css({
overflow: opt.of
});
});
}
let $this = $(e.currentTarget);
let curState = $this.find('i').hasClass('shrink-btn-up');
if (curState) {
serviceState({
'dom': $this,
'txt': '展开',
'btnClass': 'down',
'height': this.operation.showH,
'of': 'hidden'
});
} else {
serviceState({
'dom': $this,
'txt': '收起',
'btnClass': 'up',
'height': this.operation.serviceH,
'of': 'visible'
});
}
}
getSkn() {
return this.$base.data('skn');
}
};
\ No newline at end of file
... ...
... ... @@ -9,7 +9,7 @@ import {
} from './view';
import {
search
globalSearch as search
} from '../models';
let filter = require('plugin/filter');
... ... @@ -107,7 +107,7 @@ class ListController extends Controller {
});
this.searching = true;
search(params).then(data => {
search('//m.yohobuy.com/product/global/search', params).then(data => {
this.nav.page = page;
if (!data) {
... ...
... ... @@ -4,10 +4,10 @@ import {
http
} from 'yoho-mvc';
function search(data) {
function globalSearch(url, data) {
return http({
type: 'GET',
url: location.protocol + '//m.yohobuy.com/product/global/search',
url: location.protocol + url,
data: data,
xhrFields: {
withCredentials: true
... ... @@ -16,5 +16,5 @@ function search(data) {
}
export {
search
globalSearch
};
... ...
.global-detail-page {
background: rgb(244, 244, 244);
.global-tag {
position: absolute;
top: 10px;
left: 10px;
z-index: 2;
}
.global-country {
float: left;
background: rgb(70, 46, 61);
color: #fff;
padding: 2px 8px;
font-size: 16px;
span {
float: left;
}
}
.global-plane {
width: 21px;
height: 21px;
background-image: resolve("product/airplane.png");
background-repeat: no-repeat;
background-size: cover;
margin-right: 10px;
margin-top: 2px;
}
.global-limited {
float: left;
top: 10px;
border: 1px solid rgb(70, 46, 61);
margin-left: 5px;
padding: 0 5px;
font-size: 16px;
}
.banner-container {
position: relative;
background-color: #fff;
min-height: 660px;
}
.banner-top-single {
overflow: hidden;
margin: 0 auto;
img {
margin-top: 30px;
margin-bottom: 30px;
width: 448px;
}
&.hover {
position: fixed;
width: 100%;
background-color: black;
height: 100%;
top: 0;
left: 0;
right: 0;
border: 0;
z-index: 999;
display: -webkit-flex;
display: -moz-flex;
display: -ms-flex;
display: -o-flex;
display: flex;
-ms-align-items: center;
align-items: center;
img {
margin-top: initial;
margin-bottom: initial;
width: 100%;
}
}
}
.banner-top {
position: relative;
overflow: hidden;
min-height: 660px;
display: flex;
align-items: center;
&.hover {
position: fixed;
width: 100%;
background-color: black;
height: 100%;
top: 0;
left: 0;
right: 0;
border: 0;
z-index: 999;
.banner-swiper {
width: 100%;
height: auto;
margin: 0 !important;
overflow: initial !important;
max-height: initial !important;
ul {
max-height: initial !important;
}
}
.swiper-pagination-bullet-active {
background-color: #fff !important;
}
}
.swiper-pagination {
position: absolute;
bottom: 40px;
z-index: 2;
.pagination-inner {
span {
background-color: #b0b0b0;
}
.swiper-pagination-bullet {
margin-right: 2PX;
}
.swiper-pagination-bullet-active {
background-color: #000;
}
}
}
}
.banner-swiper {
overflow: hidden;
margin: 30px 96px;
width: 448px;
min-height: 600px;
ul {
position: relative;
height: auto;
li {
float: left;
img {
height: auto;
}
}
}
}
.goods-name {
box-sizing: border-box;
padding: 20px 28px;
width: 100%;
background-color: #515150;
color: #fff;
.name {
font-size: 28px;
line-height: 48px;
}
}
.price-date {
height: 112px;
border-bottom: 1px solid #eee;
padding: 15px 30px;
background: #fff;
.final-price {
font-size: 34px;
color: #d0021b;
margin-right: 5px;
}
.orign-price {
text-decoration: line-through;
color: #b0b0b0;
}
.sales-price,
.market-price {
font-size: 24px;
color: #b0b0b0;
}
.market-price {
text-decoration: line-through;
margin-left: 5px;
}
}
.country {
height: 88px;
padding: 30px;
border-bottom: 1px solid #eee;
background: #fff;
.country-name {
float: left;
height: 28px;
background: rgb(70, 46, 61);
color: #fff;
font-size: 18px;
line-height: 28px;
padding: 0 10px;
margin-right: 15px;
}
.product-source {
float: left;
height: 28px;
line-height: 28px;
font-size: 28px;
}
}
.enter-store {
position: relative;
margin-top: 30px;
overflow: hidden;
padding: 0 180px 0 114px;
background-color: #fff;
text-overflow: ellipsis;
white-space: nowrap;
line-height: 84px;
border-top: 1px solid #eee;
border-bottom: 1px solid #eee;
.store-logo {
position: absolute;
top: 1px;
left: 0;
margin-left: 30px;
width: 68px;
height: 84px;
text-align: center;
font-size: 0;
img {
display: inline-block;
width: auto;
height: 68px;
vertical-align: middle;
}
}
.store-name {
color: #444;
font-size: 34px;
}
.store-link {
position: absolute;
top: 1px;
right: 0;
padding-right: 30px;
color: #b0b0b0;
text-align: right;
span {
font-size: inherit;
}
}
}
.customer-service {
margin-top: 30px;
height: 110px;
line-height: 110px;
background-color: #fff;
padding-left: 30px;
font-size: 28px;
border-top: 1px solid #eee;
border-bottom: 1px solid #eee;
a {
display: block;
height: 100%;
width: 100%;
overflow: hidden;
}
.customer-name {
float: left;
color: #444;
}
.customer-link {
float: right;
padding-right: 30px;
color: #b0b0b0;
}
}
.cart-bar {
position: fixed;
bottom: 0;
z-index: 2;
height: 120px;
width: 100%;
border-top: 1px solid #e0e0e0;
background-color: #fff;
text-align: center;
overflow: hidden;
.num-incart {
position: absolute;
color: #444;
font-size: 47px;
top: 50%;
left: 28px;
transform: translateY(-50%);
}
.addto-cart {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 260px;
height: 80px;
background-color: #eb0313;
color: #fff;
text-align: center;
font-size: 32px;
line-height: 80px;
}
.num-tag {
position: absolute;
top: 0;
right: -15px;
display: block;
width: 30px;
height: 30px;
border-radius: 50%;
background: #eb0313;
color: #fff;
text-align: center;
font-size: 20px;
line-height: 30px;
&.hide {
display: none;
}
}
}
}
... ...
.global-detail-page .product-desc {
margin-top: 30px;
font-size: 12px;
.info {
margin: 20px 0;
padding: 0 10px 20px;
background: #fff;
border-top: 1px solid #e0e0e0;
border-bottom: 1px solid #e0e0e0;
}
.service-info {
padding-bottom: 0;
}
.brand-intro {
font-size: 21px;
}
.info:first-child {
margin-top: 0;
}
.info h2 {
text-align: left;
margin-bottom: 5px;
font-size: 28px;
font-weight: normal;
margin: 0;
height: 93px;
line-height: 93px;
border-bottom: 1px solid #f0f0f0;
margin-bottom: 10px;
}
.info h2 span {
font-size: 12px;
text-transform: uppercase;
color: #c0c0c0;
}
.good-sure {
padding-top: 5px;
margin-bottom: -20px;
border-bottom: none;
}
.description {
border-top: none;
}
.description table {
background: #fff;
width: 100%;
border-collapse: collapse;
border-spacing: 0;
}
.description td {
text-align: left;
padding: 5px 10px;
border: 1px solid #fff;
background: #eee;
font-size: 12px;
}
.details {
overflow-x: hidden;
}
.details p {
width: 100%;
line-height: 45px;
font-size: 25px;
}
.details img, .size img, .good-sure img, .brand-intro img {
width: 100%;
}
.table-wrap {
width: 100%;
overflow-x: auto;
}
.size table {
width: 100%;
border-collapse: collapse;
border-spacing: 2;
}
.size th,
.size td {
font-weight: normal;
height: 30px;
background: #eee;
padding-left: 10px;
padding-right: 10px;
border: 1px solid #fff;
min-width: 50px;
text-align: center;
}
.details table{
display: none;
}
.recommend-for-you {
border-bottom: none;
}
.recommend-for-you {
padding: 30px 0;
border-top: 1px solid #e0e0e0;
border-bottom: 1px solid #e0e0e0;
background: #fff;
}
.recommend-for-you .title {
font-size: 32px;
line-height: 88px;
text-align: center;
color: #444;
}
.recommend-for-you .swiper-container {
padding: 30px 0 20px;
width: 100%;
}
.recommend-for-you .swiper-container .swiper-slide {
padding: 0 10px;
float: left;
width: 156px;
}
.recommend-for-you .swiper-container .swiper-slide:first-child {
padding-left: 30px;
}
.recommend-for-you .swiper-container .swiper-slide:last-child {
padding-right: 30px;
}
.recommend-for-you .swiper-container .swiper-slide img {
width: 100%;
height: 208px;
}
.recommend-for-you .sale-name {
overflow: hidden;
text-overflow: ellipsis;
width: 100%;
white-space: nowrap;
margin-top: 20px;
color: gray;
}
.recommend-for-you .price {
position: relative;
margin-top: 8px;
font-size: 24px;
line-height: 1;
}
.recommend-for-you .price .sale-price {
display: block;
color: #d9134f;
margin-right: 8px;
}
.recommend-for-you .price .old-price {
display: block;
color: #b0b0b0;
text-decoration: line-through;
}
.recommend-for-you .price .no-price {
color: #444;
}
.service-cont p {
line-height: 30px;
text-indent: 0;
position: relative;
padding:0 20px 0 42px;
margin: 20px 0;
}
.service-cont>li {
padding: 10px 0 0 0;
margin-left: 20px;
border-bottom: 1px solid #e0e0e0;
}
.service-cont>li:last-child {
border-bottom: none;
}
.service-cont .service-prob:before,
.service-cont .service-answer:before {
content: '';
width: 30.8px;
height: 30.8px;
float: left;
margin-right: 20px;
position: absolute;
left: 0px;
background-size: contain;
}
.service-cont .service-prob:before {
background-image: url('http://cdn.yoho.cn/global/images/service-q.png');
background-repeat: no-repeat;
}
.service-cont .service-answer:before {
background-image: url('http://cdn.yoho.cn/global/images/service-a.png');
background-repeat: no-repeat;
}
.service-cont .service-prob {
font-size: 24px;
color: #444344;
}
.service-cont .service-answer {
font-size: 22px;
color: #b0b0b0;
line-height: 36px;
}
.service-operation {
border-top: 1px solid #e0e0e0;
text-align: center;
height: 80px;
line-height: 80px;
font-size: 24px;
color: #b0b0b0;
}
.service-icon {
display: inline-block;
}
.shrink-btn-down {
background-image: url('http://cdn.yoho.cn/global/images/service_down.png');
background-repeat: no-repeat;
}
.shrink-btn-up {
background-image: url('http://cdn.yoho.cn/global/images/service_up.png');
background-repeat: no-repeat;
}
.shrink-btn-up,
.shrink-btn-down {
width: 16px;
height: 9px;
vertical-align: middle;
margin-left: 10px;
cursor: pointer;
background-size: contain;
}
}
\ No newline at end of file
... ...
@import "detail";
@import "global_product";
@import "layout/swiper";
@import "channel/banner-top";
\ No newline at end of file
... ...