Authored by ccbikai(👎🏻🍜)

Merge branch 'master' into develop

... ... @@ -31,10 +31,10 @@ const component = {
});
},
product(req, res, next) {
const pid = req.params[0];// , goodsId = req.params[1];
const pid = req.params[0]; // , goodsId = req.params[1];
let params = {
productId: _.toString(pid),
product_id: _.toString(pid),
uid: req.user.uid || 0
};
... ... @@ -52,6 +52,17 @@ const component = {
res.json(result);
}).catch(next);
},
brand(req, res, next) {
const brandId = req.params[0];
model.brand({
uid: req.user.uid || 0,
brand_id: brandId,
gender: req.query.gender || '1,2,3'
}).then(result => {
res.json(result);
}).catch(next);
},
/**
* 加入购物车接口
... ... @@ -59,10 +70,10 @@ const component = {
*/
addToCart(req, res, next) {
let params = {
product_sku: req.body.productSku, // 商品SKU
buy_number: req.body.buyNumber, // 购买数量
goods_type: req.body.goodsType || 0, // 商品类型,0表示普通商品,1表示加价购商品
edit_product_sku: req.body.isEdit || 0, // 是否是编辑商品SKU,0表示不是编辑
product_sku: req.body.productSku, // 商品SKU
buy_number: req.body.buyNumber, // 购买数量
goods_type: req.body.goodsType || 0, // 商品类型,0表示普通商品,1表示加价购商品
edit_product_sku: req.body.isEdit || 0, // 是否是编辑商品SKU,0表示不是编辑
selected: 'Y',
promotion_id: req.body.promotionId || null, // 促销id,默认null(加价购有关)
uid: req.user.uid || 0,
... ... @@ -72,7 +83,9 @@ const component = {
model.addToCart(params).then(result => {
if (result.code === 200) {
// 将 shopping_key 写入Cookie
res.cookie('_SPK', result.data.shopping_key, {maxAge: 86400 * 360});
res.cookie('_SPK', result.data.shopping_key, {
maxAge: 86400 * 360
});
}
res.json(result);
}).catch(next);
... ... @@ -151,4 +164,4 @@ const component = {
}
};
module.exports = component;
module.exports = component;
\ No newline at end of file
... ...
... ... @@ -6,6 +6,7 @@
'use strict';
const api = global.yoho.API;
const camelCase = global.yoho.camelCase;
/**
* 商品详情
... ... @@ -13,31 +14,38 @@ const api = global.yoho.API;
const model = {
product(params) {
return api.get('', Object.assign({
method: 'h5.product.data'
}, params))
.then(result => {
// result.storage 的 数值 不可靠,循环累加 库存
let storage = 0;
method: 'app.product.data'
}, params), {
code: 200
}).then(result => {
if (result.data) {
let storage = 0; // result.storage 的 数值 不可靠,循环累加 库存
const goodsList = result.data.goods_list;
if (result.goodsList) {
for (let good of result.goodsList) {
for (let size of good.goodsSizeBoList) {
storage += size.goodsSizeStorageNum;
if (goodsList) {
for (let good of goodsList) {
for (let size of good.size_list) {
storage += size.storage_number;
}
}
}
result.storage = storage;
return result;
});
},
result.data.storage = storage;
}
return result;
}).then(camelCase);
},
intro(params) {
return api.get('', Object.assign({
method: 'h5.product.intro'
}, params));
},
brand(params) {
return api.get('', Object.assign({
method: 'app.shop.queryShopsByBrandId'
}, params)).then(camelCase);
},
/**
* 加入购物车接口
... ... @@ -80,4 +88,4 @@ const model = {
}
};
module.exports = model;
module.exports = model;
\ No newline at end of file
... ...
... ... @@ -46,6 +46,7 @@ const detail = require(`${cRoot}/detail`);
router.get(/\/product\/pro_([\d]+)_([\d]+)\/(.*).html/, detail.index); // 商品详情routers
router.get(/\/product\/product_([\d]+)\.json/, detail.product);
router.get(/\/product\/intro_([\d]+)\.json/, detail.intro);
router.get(/\/product\/brand_([\d]+)\.json/, detail.brand);
router.post(/\product\/cart.json/, detail.addToCart);
router.post(/\product\/favorite.json/, auth, detail.favorite);
router.get(/\/product\/cart-count.json/, detail.getCartCount);
... ...
... ... @@ -33,7 +33,7 @@ const getImgUrl = function(src, width = 300, height = 300, mode = 2) {
};
return dict[$0];
}).replace('http:', '') + '/interlace/1' : '';
}).replace(/https?:/, '') + '/interlace/1' : '';
};
// 退换货 申请 成功, 打开 modal
... ... @@ -89,4 +89,4 @@ module.exports = {
getImgUrl,
applySuccuss,
visibilitychange
};
\ No newline at end of file
};
... ...
/*
* @Author: Targaryen
* @Date: 2016-08-02 17:29:52
* @Last Modified by: Targaryen
* @Last Modified time: 2016-08-02 17:42:26
*/
* @Author: Targaryen
* @Date: 2016-08-02 17:29:52
* @Last Modified by: Targaryen
* @Last Modified time: 2016-08-02 17:42:26
*/
module.exports = (Vue) => {
Vue.directive('lazy-html', function(html) {
// TODO 首屏幕不使用
html = html.replace(/<img [^>]*src=['"]([^'"]+)[^>]*>/gi, '<img v-bind:src="\'$1\'">');
html = html.replace(/<img [^>]*src=['"]([^'"]+)[^>]*>/gi, '<img v-bind:src="\'$1\'">').replace(/https?:/gi, '');
this.el.innerHTML = html;
this.vm.$compile(this.el);
});
... ...
... ... @@ -2,14 +2,19 @@ const Vue = require('vue');
const lazyload = require('vue-lazyload');
const directive = require('common/vue-directive');
const app = require('editorial/detail.vue');
const yoho = require('yoho');
require('common/vue-filter')(Vue);
Vue.use(lazyload, { preLoad: 3 });
Vue.use(lazyload, {
preLoad: 3
});
Vue.use(directive);
new Vue({
el: '#app',
components: {
app
}
});
yoho.ready(() => {
new Vue({
el: '#app',
components: {
app
}
});
});
\ No newline at end of file
... ...
<template>
<div class="cate-page" id='cate-page'>
<div class="cate-container clearfix">
<div class="content" style="height: 522px;">
<div class="content">
<ul class="primary-level">
<li v-for="(index, ca) in cateNavLeftData" class="ellipsis" :class="{focus: index === leftcurrent}" class="p-level-item" @click='cateNavLeftFun(index, ca.relationParameter.sort, ca.categoryName)'>
{{ca.categoryName}}
... ... @@ -213,6 +213,8 @@
}
</style>
<script>
const $ = require('jquery');
module.exports = {
props: {
category: {
... ... @@ -275,6 +277,16 @@
},
created() {
this.categoryChangeHandler();
window.addEventListener('touchstart', () => {
const c = $('.content');
const h = c.height();
const h1 = document.body.offsetHeight;
if (h <= h1) {
c.css('height', h1);
}
});
}
};
</script>
... ...
... ... @@ -6,7 +6,7 @@
</div>
<div class="text-box">
<h3 class="line-clamp-2">{{entity.productName}}</h3>
<h4>{{entity.productPriceBo && entity.productPriceBo.formatSalesPrice}}</h4>
<h4>{{entity.formatSalesPrice !== '0' ? entity.formatSalesPrice : entity.formatMarketPrice}}</h4>
</div>
</div>
... ... @@ -239,13 +239,13 @@
thumbnails[goods.colorId] = goods.colorImage;
// 生成colorId 与 size的 映射
colorSizes[goods.colorId] = goods.goodsSizeBoList.map((size)=> {
colorSizes[goods.colorId] = goods.sizeList.map((size)=> {
if (!stocks[goods.colorId]) {
stocks[goods.colorId] = 0;
}
// 默认选中有库存的第一个颜色尺码
if (size.goodsSizeStorageNum > 0) {
if (size.storageNumber > 0) {
if (!selection.color) {
self.selection.color = selection.color = {
text: goods.colorName,
... ... @@ -254,24 +254,24 @@
};
}
if (!selection.size && size.goodsSizeStorageNum > 0) {
if (!selection.size && size.storageNumber > 0) {
self.selection.size = selection.size = {
text: size.sizeName,
value: size.goodsSizeSkuId,
goodsId: size.goodsId,
value: size.productSku,
goodsId: goods.goodsId,
disabled: false
};
}
}
// 计算所有尺码的库存
stocks[goods.colorId] += size.goodsSizeStorageNum;
stocks[goods.colorId] += size.storageNumber;
return {
text: size.sizeName,
value: size.goodsSizeSkuId,
disabled: size.goodsSizeStorageNum === 0,
goodsId: size.goodsId
value: size.productSku,
disabled: size.storageNumber === 0,
goodsId: goods.goodsId
};
});
... ... @@ -286,13 +286,18 @@
this.selection.color = selection.color = this.colors[0];
}
this.sizes = colorSizes[selection.color.value];
this.colorSizes = colorSizes;
this.thumbnails = thumbnails;
// 选择默认值
this.$emit('feature:color.select', selection.color);
this.$emit('feature:size.select', selection.size);
if (selection.color) {
this.sizes = colorSizes[selection.color.value];
this.$emit('feature:color.select', selection.color);
}
if (selection.size) {
this.$emit('feature:size.select', selection.size);
}
}
},
components: {
... ... @@ -378,7 +383,7 @@
return;
}
const param = Object.assign({goodsId: this.entity.id}, this.selection);
const param = Object.assign({goodsId: this.entity.productId}, this.selection);
this.onAddToCart(param, this);
},
... ...
... ... @@ -159,9 +159,8 @@
// 查询 商品 feature
queryProductFeature(pid) {
$.get(`/product/product_${pid}.json`).then(result => {
this.entity = result;
this.entity = result.data || {};
this.showFeatureSelector = true;
return result;
});
},
... ...
... ... @@ -4,25 +4,25 @@
<image-carousel :goods="entity.goodsList"></image-carousel>
<div class="title-box">
<h1 class="line-clamp-2">{{entity.productName}}</h1>
<i class="price" v-if="entity.productPriceBo.marketPrice > entity.productPriceBo.salesPrice"
:class="{'strike-through': entity.productPriceBo.salesPrice > 0}">{{entity.productPriceBo.formatMarketPrice}}</i>
<i class="price" v-if="entity.marketPrice > entity.salesPrice"
:class="{'strike-through': entity.salesPrice > 0}">{{entity.formatMarketPrice}}</i>
<i v-if="entity.productPriceBo.salesPrice > 0"
:class="{price: true, highlight: entity.productPriceBo.marketPrice > entity.productPriceBo.salesPrice}">
{{entity.productPriceBo.formatSalesPrice}}
<i v-if="entity.salesPrice > 0"
:class="{price: true, highlight: entity.marketPrice > entity.salesPrice}">
{{entity.formatSalesPrice !== '0' ? entity.formatSalesPrice : entity.formatMarketPrice}}
</i>
</div>
</show-box>
<show-box class="brand" v-if="entity.brand">
<img :src="entity.brand.brandIco | resize 110 68"/>
<show-box class="brand" v-if="brand">
<img :src="brand.brandIco | resize 110 68"/>
<h2>{{entity.brand.brandName}}</h2>
<h2>{{brand.brandName}}</h2>
<div class="brand-go">
<span>进入店铺</span>
<span class="icon icon-right"></span>
</div>
<a :href="entity.brand.brandDomain | brandUrl"></a>
<a :href="brand.brandDomain | brandUrl"></a>
</show-box>
<show-box v-if="intro.productDescBo">
... ... @@ -125,7 +125,7 @@
<ul v-for="item in intro.productMaterialList">
<div>
<div class="image-box">
<img :src="item.imageUrl" width="86" height="35"/>
<img :src="item.imageUrl | resize 86 35" width="86" height="35"/>
</div>
<div class="text-box">
<div>{{item.caption}}</div>
... ... @@ -153,10 +153,10 @@
<h2>商品详情</h2>
<i>DETAILS</i>
<p v-if="entity.brand && entity.brand.brandIntro" v-lazy-html="entity.brand.brandIntro">
<p v-if="brand && brand.brandIntro" v-lazy-html="brand.brandIntro">
</p>
<p v-if="entity.brand && intro.productIntroBo" v-lazy-html="intro.productIntroBo.productIntro">
<p v-if="brand && intro.productIntroBo" v-lazy-html="intro.productIntroBo.productIntro">
</p>
</show-box>
... ... @@ -412,11 +412,8 @@
yoho: yoho,
intro: {},
firstImage: '',
brand: null,
entity: {
brand: {
brandName: '',
brandIco: ''
},
productPriceBo: {
formatMarketPrice: ''
}
... ... @@ -480,7 +477,7 @@
toggleFavorite: function() {
$.post('/product/favorite.json', {
operation: this.entity.isCollect === 'Y' ? 'remove' : 'add',
id: this.entity.productPriceBo.productId
id: this.entity.productId
}).then((result)=> {
if (result.code === 200) {
tip(this.entity.isCollect === 'Y' ? '取消收藏成功' : '收藏成功');
... ... @@ -516,9 +513,10 @@
// 读取基础数据
$.get(`/product/product_${pid}.json`).then((result) => {
// TODO: 异常处理
this.entity = result;
if (!result.data) {
return;
}
this.entity = result.data;
if (this.entity.storage === 0 || this.entity.status === 0) {
this.isSoldOut = true;
}
... ... @@ -546,12 +544,23 @@
})
});
return result;
}).then((result)=> {
// 读取商品详情
$.get(`/product/product/intro_${pid}.json`, {skn: result.productPriceBo.productSkn}).then(intro => {
this.intro = intro;
});
return result.data;
}).then((data)=> {
if (data) {
// 读取商品详情
$.get(`/product/product/intro_${pid}.json`, {skn: data.productSkn}).then(intro => {
this.intro = intro;
if (this.intro.sizeImage) {
this.intro.sizeImage = this.intro.sizeImage.replace(/https?:/, '');
}
});
if (data.brandInfo && data.brandInfo.brandId) {
$.get(`/product/product/brand_${data.brandInfo.brandId}.json`).then(brand => {
this.brand = brand.data && brand.data.length ? brand.data[0] : {};
});
}
}
})
.always(() => {
this.isReady = true;
... ...
... ... @@ -64,7 +64,7 @@ module.exports = (list, options) => {
_.forEach(list, (product) => {
// 商品信息有问题,则不显示
if (!product.productId || !product.goodsList || !product.goodsList.length) {
if (!product || !product.productId || !product.goodsList || !product.goodsList.length) {
return;
}
... ... @@ -134,4 +134,4 @@ module.exports = (list, options) => {
});
return pruductList;
};
};
\ No newline at end of file
... ...