Authored by 陈峰

Merge branch 'release/6.8.6' into 'master'

Release/6.8.6



See merge request !1698
... ... @@ -14,6 +14,7 @@ exports.index = function(req, res, next) {
if (!result) {
return next();
}
let title = stringProcess.paramsFilter(req.query.title) || result.name || '专题活动';
let shareId = _.parseInt(stringProcess.paramsFilter(req.query.share_id));
... ...
... ... @@ -349,6 +349,15 @@ class featureModel extends global.yoho.BaseModel {
}, f.component[0].searchCondition || {});
f.component[0].newStyle = _.get(f, 'component[0].newStyle') === '1';
}
// 对背景图做特殊处理
if (f.component && f.component[0] && f.component[0].type === 'productGroup') {
if (f.param.bgimg) { // 对背景图做特殊处理
f.param._bgimgFill = f.param.bgimg;
f.param.bgimg = '';
}
}
// 新增店铺组
... ... @@ -356,6 +365,32 @@ class featureModel extends global.yoho.BaseModel {
shopGroups.push(self._getShopGroup(f.component[0]));
}
// 店铺加商品组
if (componentType === 'shopAndProduct') {
let shop = f.component[0];
shop.jumpUrl = `//m.yohobuy.com/product/shop?shop_id=${shop.shopId}&openby:yohobuy=
{"action":"go.shop","params":{"shop_id":"${shop.shopId}","shop_template_type":"2"}}`;
shop.numOfOneRow = '3';
if (shop.searchCondition) {
shop.searchCondition.limit = '3'; // 强制把数量限制为3个
if (shop.favourite_prds_enable === '1') {
shop.searchCondition = Object.assign({
maybeLike: '1',
limit: '60'
}, shop.searchCondition || {});
shop.newStyle = _.get(f, 'component[0].newStyle') === '1';
}
} else if (shop.defaultSkn) {
componentArr.push(shop);
}
if (f.param.bgimg) { // 对背景图做特殊处理
f.param._bgimgFill = f.param.bgimg;
f.param.bgimg = '';
}
}
if (_.get(f, 'type') === 'bottombar') {
f.height = _.get(f, 'param.height') / 20;
}
... ...
... ... @@ -108,6 +108,30 @@
{{/if}}
{{/isEqualOr}}
{{#isEqualOr type 'shopAndProduct'}}
<!--一个店铺带两个商品-->
<div class="shop-product-container {{#isEqualOr position '1'}}right{{^}}left{{/isEqualOr}}">
<div class="product-container single-item3 {{#isEqualOr position '1'}}right{{^}}left{{/isEqualOr}} shop-wrapper">
<a class="shop-container" href="{{jumpUrl}}" target="_blank">
<div class="feature-shop-info">
<image class="lazy" data-original="{{image2 shopBgImage w=213 h=224 q=80}}"></image>
</div>
</a>
</div>
<div class="product-wrapper">
{{#isEqualOr newStyle '1'}}
{{> feature/product-new-style}}
{{^}}
{{> feature/product-old-style}}
{{/isEqualOr}}
</div>
<div class="clearfix"></div>
</div>
{{/isEqualOr}}
{{#isEqualOr type 'productGroup'}}
{{! 商品池}}
{{#isEqualOr newStyle '1'}}
... ...
<div class="feature-product-info {{#if conf.searchCondition}}novisible{{/if}}" data-skn="{{product_skn}}">
<a class="first-part product-detail" href='{{producturl}}'>
<div class="product-detail-imgbox">
... ... @@ -11,6 +12,17 @@
<a class="new-brand-name {{#isEqualOr conf.showBrandUrl '1'}}product-brand{{else}}product-detail{{/isEqualOr}}" href="{{brandurl}}">
<span class="brand-name" {{#if conf.fontColor}} style="color:{{conf.fontColor}};" {{/if}}>{{brandname}}</span>
</a>
<div class="sales-imgs-new">
{{#isEqualOr conf.isAdvance '1'}}
<div class="advance" style="background-image: url({{imageslim conf.advanceBgImg}});display:inline-block;">
<img src="{{imageslim conf.advanceBgImg}}" class="img-seat">
<span class="advance-price">¥{{curPlanPrice}}</span>
</div>
{{/isEqualOr}}
{{#if conf.leftDownImg}}
<img class="leftdownimg lazy" data-original="{{image2 conf.leftDownImg q=85}}">
{{/if}}
</div>
</div>
</a>
{{#if conf.brandImg}}
... ...
... ... @@ -21,7 +21,7 @@
{{/isEqualOr}}
{{#isEqualOr status 3}}
<div class="counter-num" > 等待开奖中 </div>
<div class="counter-num" > 待开奖 </div>
{{/isEqualOr}}
{{#isEqualOr status 4}}
... ... @@ -29,7 +29,7 @@
{{/isEqualOr}}
{{#isEqualOr status 5}}
<div class="counter-num" > 人数不足 活动结束 </div>
<div class="counter-num" > 待开奖 </div>
{{/isEqualOr}}
</div>
... ...
... ... @@ -13,7 +13,7 @@
{{/ifcond}}
{{#ifcond status '===' 3}}
<div class="btn">等待开奖中</div>
<div class="btn">待开奖</div>
{{/ifcond}}
{{#ifcond status '===' 4}}
... ... @@ -21,7 +21,7 @@
{{/ifcond}}
{{#ifcond status '===' 5}}
<div class="btn">人数不足 活动结束</div>
<div class="btn">待开奖</div>
{{/ifcond}}
{{#isEqualOr status 1 2 6}}
... ...
<div class="product-status">
{{#isEqualOr status 0}}
<div class="btn cancel" >活动结束</div>
{{/isEqualOr}}
{{#isEqualOr status 1}}
<div class="btn cancel" >即将开始</div>
{{/isEqualOr}}
{{#isEqualOr status 0}}
<div class="btn cancel">活动结束</div>
{{/isEqualOr}}
{{#isEqualOr status 2}}
<a class="btn ok js-join" data-id="{{id}}">参加抽奖</a>
{{/isEqualOr}}
{{#isEqualOr status 1}}
<div class="btn cancel">即将开始</div>
{{/isEqualOr}}
{{#isEqualOr status 3 4}}
<div class="btn cancel">活动结束</div>
{{/isEqualOr}}
{{#isEqualOr status 2}}
<a class="btn ok js-join" data-id="{{id}}">参加抽奖</a>
{{/isEqualOr}}
{{#isEqualOr status 3}}
<div class="btn cancel">待开奖</div>
{{/isEqualOr}}
{{#isEqualOr status 4}}
<div class="btn cancel">活动结束</div>
{{/isEqualOr}}
{{#isEqualOr status 5}}
<div class="btn cancel">人数不足 活动结束</div>
{{/isEqualOr}}
{{#isEqualOr status 5}}
<div class="btn cancel">待开奖</div>
{{/isEqualOr}}
</div>
... ...
... ... @@ -85,6 +85,7 @@ const select = (req, res, next) => {
let shoppingKey = req.cookies._SPK || '',
uid = req.user && req.user.uid;
let skuList = req.body.skuList,
modeType = req.body.modeType,
cartType = req.cookies.cartType || 'ordinary';
if (!skuList || !skuList.length) {
... ... @@ -97,13 +98,24 @@ const select = (req, res, next) => {
// shoppingKey = 'dc9d09e2ffd8607f2cfd8b9c95962923';
// uid = 20422448;
return req.ctx(cartModel).selectGood(uid, skuList, shoppingKey, cartType).then(data => {
data ? res.json({
code: 200,
data
}) : res.status(400).json({
message: '操作失败'
});
return req.ctx(cartModel).selectGood(uid, skuList, shoppingKey, cartType, modeType).then(data => {
if (data) {
if (data.code !== 500) {
res.json({
code: 200,
data
});
} else {
res.status(400).json({
code: 500,
message: data.message || '操作失败!'
});
}
} else {
res.status(400).json({
message: '操作失败'
});
}
}).catch(next);
};
... ...
... ... @@ -38,17 +38,25 @@ class cartModel extends global.yoho.BaseModel {
* @param int $uid 用户ID
* @param string $sku 商品sku列表
* @param string $shoppingKey 未登录用户唯一识别码
* @param modeType 新增参数 0或者不传表示普通模式,1表示编辑模式,编辑模式接口不返回500错误
* @return array 购物车接口返回的数据
*/
selectGood(uid, sku, shoppingKey, cartType) {
selectGood(uid, sku, shoppingKey, cartType, modeType) {
return this.get({data: {
method: 'app.Shopping.selectedAndQryCart',
product_sku_list: sku,
uid: uid,
shopping_key: shoppingKey,
is_support_mlp: 'Y'
is_support_mlp: 'Y',
mode_type: modeType ? modeType : 0
}}).then((data) => {
return data.code === 200 ? cartProcess.processData(data, cartType) : void 0;
if (data.code === 200) {
return cartProcess.processData(data, cartType);
} else if (data.code === 500) {
return data;
} else {
return void 0;
}
});
}
... ...
... ... @@ -479,6 +479,8 @@ module.exports = class extends global.yoho.BaseModel {
dest.productSkn = origin.product_skn;
dest.goodsName = origin.product_name;
dest.startSaleTime = origin.startSaleTime;
dest.startSaleTimeStr = origin.startSaleTimeStr;
// 线下店商品展示限制
dest.storeGood = origin.store_show_status === 3 || origin.store_show_status === 4;
... ...
... ... @@ -31,7 +31,7 @@ const domains = {
liveApi: 'http://testapi.live.yohops.com:9999/',
singleApi: 'http://api-test3.dev.yohocorp.com/',
ufo: 'http://java-yohoufo-fore.test3.ingress.dev.yohocorp.com/ufo-gateway/',
yoLuck: 'http://limit-yoho-activity-platform.test3.ingress.dev.yohocorp.com',
yoLuck: 'http://yoho-activity-platform.test3.ingress.dev.yohocorp.com',
imSocket: 'wss://imsocket.yohobuy.com:443',
imCs: 'https://imhttp.yohobuy.com/api',
... ... @@ -306,7 +306,7 @@ if (isProduction) {
platformApi: 'http://192.168.102.48:8088/',
extstore: 'http://extstore-test1.yohops.com',
yohoNowApi: process.env.YOHO_NOW_API || 'http://yohonow-test.yohops.com:9999/',
yoLuck: process.env.YOLUCK_API || 'http://limit-yoho-activity-platform.test3.ingress.dev.yohocorp.com'
yoLuck: process.env.YOLUCK_API || 'http://yoho-activity-platform.test3.ingress.dev.yohocorp.com'
},
useCache: true,
alipayConfig: {
... ...
... ... @@ -54,6 +54,10 @@ module.exports = () => {
// IP 地址
yoho.clientIp = _getClientIp(req);
if (req.query.fullscreen) {
yoho.fullScreen = true;
}
yoho.isMobile = /(nokia|iphone|android|ipad|motorola|^mot\-|softbank|foma|docomo|kddi|up\.browser|up\.link|htc|dopod|blazer|netfront|helio|hosin|huawei|novarra|CoolPad|webos|techfaith|palmsource|blackberry|alcatel|amoi|ktouch|nexian|samsung|^sam\-|s[cg]h|^lge|ericsson|philips|sagem|wellcom|bunjalloo|maui|symbian|smartphone|midp|wap|phone|windows ce|iemobile|^spice|^bird|^zte\-|longcos|pantech|gionee|^sie\-|portalmmm|jig\s browser|hiptop|^ucweb|^benq|haier|^lct|opera\s*mobi|opera\*mini|320x320|240x320|176x220)/i.test(req.get('User-Agent') || ''); // eslint-disable-line
yoho.isWechat = /micromessenger/i.test(req.get('User-Agent') || '');
yoho.isWeibo = /weibo/i.test(req.get('User-Agent') || '');
... ... @@ -71,6 +75,10 @@ module.exports = () => {
res.locals.indexUrl = helpers.urlFormat('/?go=1'); // 悬挂首页
res.locals.showHeader = true;
if (req.query.noheader) {
res.locals.showHeader = false;
}
next();
};
};
... ...
... ... @@ -77,7 +77,7 @@
<link rel="apple-touch-startup-image" href="https://cdn.yoho.cn/h5/forios/startup/startup-orange-5.png" media="screen and (max-device-width: 640px)">
</head>
<body class="{{pageStyle}}{{#if isWechat}} wechat-body{{/if}}{{#if width750}} width750{{/if}}{{#if isPassportPage}} passport-body{{/if}}{{#if isStarIndexPage}} star-index-bg{{/if}}{{#if isStarDetailPage}} star-class-body{{/if}}{{#if isInstallmentPage}}{{#unless notOpen}} installment-body{{/unless}}{{/if}}{{#if @root.isMarsApp}} is-mars-app{{/if}}{{#if @root.isNowApp}} is-now-app{{/if}}">
<div class="main-wrap" id="main-wrap"{{#if appPath}} data-apppath='{{{appPath}}}'{{/if}}{{#if miniPath}} data-miniPath='{{{miniPath}}}'{{/if}}{{#if @root.wap.wechat.miniAutoJump}} data-miniautojump="1"{{/if}}{{#if @root.wap.wechat.backDownload}} data-backDownload='{{@root.wap.wechat.backDownload}}'{{/if}}>
<div class="main-wrap{{#if fullScreen}} full-screen{{/if}}" id="main-wrap"{{#if appPath}} data-apppath='{{{appPath}}}'{{/if}}{{#if miniPath}} data-miniPath='{{{miniPath}}}'{{/if}}{{#if @root.wap.wechat.miniAutoJump}} data-miniautojump="1"{{/if}}{{#if @root.wap.wechat.backDownload}} data-backDownload='{{@root.wap.wechat.backDownload}}'{{/if}}>
{{#if systemUpdate}}
{{> updata}}
... ...
{
"name": "yohobuywap-node",
"version": "6.8.77",
"version": "6.8.79",
"private": true,
"description": "A New Yohobuy Project With Express",
"repository": {
... ...
... ... @@ -13,7 +13,7 @@
{{/ifcond}}
{{#ifcond status '===' 3}}
<div class="btn">等待开奖中</div>
<div class="btn">待开奖</div>
{{/ifcond}}
{{#ifcond status '===' 4}}
... ... @@ -21,7 +21,7 @@
{{/ifcond}}
{{#ifcond status '===' 5}}
<div class="btn">人数不足 活动结束</div>
<div class="btn">待开奖</div>
{{/ifcond}}
{{#is-equal-or status 1 2 6}}
... ...
<div class="product-status">
{{#is-equal-or status 0}}
<div class="btn cancel" >活动结束</div>
{{/is-equal-or}}
{{#is-equal-or status 0}}
<div class="btn cancel">活动结束</div>
{{/is-equal-or}}
{{#is-equal-or status 1}}
<div class="btn cancel">即将开始</div>
{{/is-equal-or}}
{{#is-equal-or status 1}}
<div class="btn cancel" >即将开始</div>
{{/is-equal-or}}
{{#is-equal-or status 2}}
<a class="btn ok js-join" data-id="{{id}}">参加抽奖</a>
{{/is-equal-or}}
{{#is-equal-or status 2}}
<a class="btn ok js-join" data-id="{{id}}">参加抽奖</a>
{{/is-equal-or}}
{{#is-equal-or status 3}}
<div class="btn cancel">待开奖</div>
{{/is-equal-or}}
{{#is-equal-or status 3 4}}
<div class="btn cancel">活动结束</div>
{{/is-equal-or}}
{{#is-equal-or status 4}}
<div class="btn cancel">活动结束</div>
{{/is-equal-or}}
{{#is-equal-or status 5}}
<div class="btn cancel">人数不足 活动结束</div>
{{/is-equal-or}}
{{#is-equal-or status 5}}
<div class="btn cancel">待开奖</div>
{{/is-equal-or}}
</div>
... ...
<div class="good-item{{#if lowStocks}} low-stocks{{/if}}{{#if isStudents}} is-students{{/if}}{{#if isVipPrice}} is-vip-price{{/if}}{{#ifand checked showCheckbox}} is-checked{{/ifand}}{{#if noEdit}} no-edit{{/if}}{{#if inValid}} in-valid{{/if}}{{#if inValidLow}} in-valid-low{{/if}}{{#ifor isGift isAdvanceBuy}} is-gift{{/ifor}}" data-promotion="{{promotion_id}}" data-id="{{id}}" data-skn="{{skn}}" data-mnum="{{minNumber}}" data-link="{{link}}" data-activityid="{{parent.poolId}}" data-poolbatchno="{{parent.poolBatchNo}}">
<div class="opt">
{{#if showCheckbox}}
<i class="iconfont chk select{{#if checked}} checked{{/if}}"></i>
<i class="iconfont {{#if sale_time_str}}presale{{/if}} chk select{{#if checked}} checked{{/if}}"></i>
{{/if}}
<i class="iconfont chk edit"></i>
{{#inValid}}
... ...
... ... @@ -61,8 +61,13 @@
</div>
</div>
<div class="btn-wrap">
{{#if @root.buttonText.double}}
<button id="chose-btn-buynow" class="btn btn-sure-buynow">立即购买</button>
{{#if @root.startSaleTimeStr}}
<button disabled="disabled" class="btn btn-cannot-buynow">立即购买</button>
{{else}}
<button id="chose-btn-buynow" class="btn btn-sure-buynow">立即购买</button>
{{/if}}
<button id="chose-btn-sure" class="btn btn-sure-addtocart">加入购物车</button>
{{^}}
<button id="chose-btn-sure" class="btn btn-sure">{{@root.buttonText.text}}</button>
... ...
... ... @@ -881,6 +881,56 @@ function activityPlan() {
}
}
function changeShopAndProductHeightSingle(parent, className) {
let img = $(parent).find('.' + className);
if (img[0] && !img.hasClass('completed')) {
// console.log(img[0].src, /(\.jpg|\.png)/.test(img[0].src));
if (/(\.jpg|\.png)/.test(img[0].src)) {
let image = new Image();
image.src = img[0].src;
image.onload = function() {
img.removeClass(className);
img.addClass('completed');
let height = $(parent).find('.product-wrapper .feature-product-info').height();
$(parent).find('.shop-wrapper .feature-shop-info').height(height);
};
} else {
setTimeout(changeShopAndProductHeightSingle, 300, parent, className);
}
}
}
// 改变店铺+商品组中店铺的高度
function changeShopAndProductHeight() {
$('.shop-product-container').each(function() {
let img = $(this).find('.product-detail-img').eq(0);
let that = this;
if (img[0] && !img.hasClass('completed')) {
// console.log(img[0].src, /(\.jpg|\.png)/.test(img[0].src));
if (/(\.jpg|\.png)/.test(img[0].src)) {
let image = new Image();
image.src = img[0].src;
image.onload = function() {
img.addClass('completed');
let height = $(that).find('.product-wrapper .feature-product-info').height();
$(that).find('.shop-wrapper .feature-shop-info').height(height);
};
} else {
let className = 'no-completed-' + Math.random().toString(16).substr(2, 8);
img.addClass(className);
setTimeout(changeShopAndProductHeightSingle, 300, that, className);
}
}
});
}
$(function() {
if ($('.over').length) {
// 过期/删除 状态的 活动
... ... @@ -945,6 +995,8 @@ $(function() {
// 定时计划
activityPlan();
changeShopAndProductHeight();
// 小程序相关处理
if (!window.WeixinJSBridge || !window.WeixinJSBridge.invoke) {
document.addEventListener('WeixinJSBridgeReady', miniProgramHandleInit, false);
... ...
... ... @@ -10,6 +10,7 @@ let $ = require('yoho-jquery'),
tip = require('js/plugin/tip'),
chosePanel = require('js/common/chose-panel-new'),
loading = require('js/plugin/loading'),
isModify = false,
dialog = require('js/plugin/dialog');
let goodObj = {
... ... @@ -198,14 +199,17 @@ let goodObj = {
return;
}
self.handle.posting = true;
let modeType = isModify ? 1 : 0;
let skuData = self.getSelectGoodData(eles, selectAll);
loading.showLoading();
return $.ajax({
type: 'post',
url: '/cart/index/new/select',
data: {
skuList: JSON.stringify(skuData)
skuList: JSON.stringify(skuData),
modeType: modeType
},
complete: () => {
self.handle.posting = false;
... ... @@ -317,6 +321,7 @@ let goodObj = {
});
},
getSelectGoodData(eles, selectAll) {
return Array.from(eles.map((i, ele) => {
let $this = $(ele),
$good = $this.closest('.good-item'),
... ... @@ -324,7 +329,6 @@ let goodObj = {
promotion = $good.data('promotion'),
batch_no = $good.data('poolbatchno'),
activity_id = $good.data('activityid');
let goodInfo = {};
goodInfo.goods_type = $('#cartType').val();
... ... @@ -333,6 +337,9 @@ let goodObj = {
} else {
goodInfo.selected = $this.hasClass('checked') ? 'N' : 'Y';
}
if ($this.hasClass('presale') && isModify) {
goodInfo.selected = 'N';
}
goodInfo.product_sku = id;
goodInfo.promotion_id = promotion;
goodInfo.buy_number = $good.find('.good-num').val();
... ... @@ -346,6 +353,7 @@ let goodObj = {
if (batch_no) {
goodInfo.batch_no = batch_no;
}
isModify = false;
return goodInfo;
}));
... ... @@ -392,6 +400,7 @@ let goodObj = {
}).done(function(res) {
if (res && res.code === 200) {
$(e.delegateTarget).data('id', result.sku.skuId);
isModify = true;
if (!$(e.delegateTarget).find('.chk.select').hasClass('checked')) {
self.selectGood($(e.delegateTarget).find('.chk.select'));
} else {
... ... @@ -471,6 +480,7 @@ let goodObj = {
goodNum = parseInt($(e.delegateTarget).find('.good-num').val(), 10);
let max = parseInt($(e.delegateTarget).find('.good-num').data('max'), 10);
isModify = true;
if (!$(e.delegateTarget).find('.chk.select').hasClass('checked') && goodNum <= max) {
self.handle.posting = false;
self.selectGood($(e.delegateTarget).find('.chk.select'));
... ...
... ... @@ -392,6 +392,16 @@
float: left;
}
.btn-cannot-buynow {
width: 50%;
height: 80px;
border: none;
background: #b0b0b0;
color: #fff;
font-size: 32px;
float: left;
}
.btn-sure-addtocart {
width: 50%;
height: 80px;
... ...
... ... @@ -51,6 +51,8 @@
}
.new-price {
text-align: center;
> .sale-price {
margin-left: 6px;
font-size: 24px;
... ... @@ -361,6 +363,60 @@
}
}
.shop-product-container {
padding-bottom: 10px;
overflow: hidden;
.product-container {
padding: 0;
margin: 0;
}
.product-wrapper {
overflow: hidden;
}
.shop-wrapper {
display: inline-block;
height: 100%;
a {
height: 100%;
}
.feature-shop-info {
height: 100%;
}
}
&.left .shop-wrapper {
margin-top: 10px;
}
&.left .product-wrapper {
.product-source .feature-product-info:nth-child(n+4) {
display: none;
}
}
&.right .shop-wrapper {
overflow: hidden;
padding-top: 10px;
margin-left: 0 !important;
margin-right: 10px;
}
&.right .product-wrapper {
overflow: hidden;
padding: 0;
margin-left: 20px;
.product-source .feature-product-info:nth-child(n+4) {
display: none;
}
}
}
.is-style-2 {
padding: 0 30px 10px;
... ...
... ... @@ -114,6 +114,14 @@ $margin-right-3: 7px;
float: left;
width: 203px;
&.left {
float: left;
}
&.right {
float: right;
}
.shop-container .feature-shop-info {
margin: 16px 10px 16px 0;
... ... @@ -124,9 +132,7 @@ $margin-right-3: 7px;
}
}
/*
个性化店铺组与原有店铺组样式几乎完全不一样
*/
/* 个性化店铺组与原有店铺组样式几乎完全不一样 */
.shop-individuation {
&.shop-two,
&.shop-three {
... ...
... ... @@ -67,6 +67,14 @@ button {
margin-left: auto;
max-width: 640px;
width: 100%;
&.full-screen {
max-width: initial !important;
.mobile-container {
max-width: initial !important;
}
}
}
/* 字体名称勿改的,APP做IP直连有使用到 */
... ...
... ... @@ -111,7 +111,8 @@ const formatCartGoods = (goodData, isAdvanceCart, isValid, inValidLow) => {
isVipPrice: goodData.sales_price !== goodData.last_vip_price && goodData.discount_tag === 'V',
isStudents: goodData.sales_price !== goodData.last_vip_price && goodData.discount_tag === 'S',
count: goodData.buy_number,
promotion_id: _.toNumber(goodData.promotion_id) === 0 ? '' : goodData.promotion_id
promotion_id: _.toNumber(goodData.promotion_id) === 0 ? '' : goodData.promotion_id,
sale_time_str: !!goodData.sale_time_str // 如果有sale_time_str字段有值。则为true
};
goodData.storage_number = _.parseInt(goodData.storage_number);
... ...