Showing 40 changed files with 1197 additions and 237 deletions
... ... @@ -30,8 +30,20 @@ const stringProcess = require('./utils/string-process');
const app = express();
// 向模板注入变量
global.devEnv = app.locals.devEnv = app.get('env') === 'development';
global.isProduction = app.locals.isProduction = app.get('env') === 'production';
switch (app.get('env')) {
case 'development':
global.devEnv = app.locals.devEnv = true;
break;
case 'test':
global.isTest = app.locals.isTest = true;
break;
case 'production':
global.isProduction = app.locals.isProduction = true;
break;
default:
break;
}
global.version = app.locals.version = pkg.version;
app.locals.startTime = moment().format('YYYYMMDDHH');
app.locals.currentYear = moment().format('YYYY');
... ...
... ... @@ -148,3 +148,23 @@ exports.redenvelope = (req, res, next) => {
res.jsonp(result);
}).catch(next);
};
exports.goods = function(req, res, next) {
let skns = req.query.skns || '';
if (!skns) {
return res.jsonp({
code: 403,
message: '参数错误'
});
}
req.ctx(model).getProductBySkns(skns).then(result => {
res.jsonp({
code: 200,
data: result,
timestamp: Date.parse(new Date()) / 1000
});
}).catch(next);
};
... ...
... ... @@ -37,34 +37,6 @@ class HaveGain {
account: '',
required: true,
fans: 0
},
{
name: '微信订阅号',
icon: '//cdn.yoho.cn/m-yohobuy-node/assets/img/weixin@2x.png',
type: 2,
account: '',
fans: 0
},
{
name: '抖音',
icon: '//cdn.yoho.cn/m-yohobuy-node/assets/img/douyin@2x.png',
type: 3,
account: '',
fans: 0
},
{
name: '微博',
icon: '//cdn.yoho.cn/m-yohobuy-node/assets/img/weibo@2x.png',
type: 4,
account: '',
fans: 0
},
{
name: 'Instagram',
icon: '//cdn.yoho.cn/m-yohobuy-node/assets/img/ins@2x.png',
type: 5,
account: '',
fans: 0
}
];
... ... @@ -165,6 +137,47 @@ class HaveGain {
return res.json(result);
}).catch(next);
}
promoDetail(req, res, next) {
let uid = req.user.uid;
let pid = req.params.id;
if (!pid) {
return next(Error('promo detail pid is empty'));
}
return req.ctx(haveGainModel).promoDetail(pid, uid).then(result => {
if (result.error) {
return next(result.error);
}
return res.render('have-gain/promoDetail', Object.assign({
page: 'have-gain-promodetail',
title: '活动说明'
}, result));
}).catch(next);
}
promoSubmit(req, res, next) {
let uid = req.user.uid;
let pid = req.params.id;
return req.ctx(haveGainModel).promoSubmit(pid, uid).then(result => {
if (result.error) {
return res.json({
code: 401,
message: result.error.message
});
}
return res.json({
code: 200,
...result
});
}).catch(next);
}
}
module.exports = new HaveGain();
... ...
... ... @@ -9,18 +9,35 @@ class featureModel extends global.yoho.BaseModel {
super(ctx);
}
_getProductBySkns(productObj, ctx) {
_getProductBySkns(productArr, ctx) {
let skns = [];
let list = _.isArray(productArr) ? productArr : [productArr];
_.forEach(list, value => {
let defSkns = value.defaultSkns || value.defaultSkn;
if (defSkns) {
value._defaultSkns = defSkns.split(',');
skns = [...skns, ...value._defaultSkns];
}
});
if (!skns.length) {
return Promise.resolve();
}
return this.get({
data: {
productSkn: productObj.defaultSkns,
productSkn: _.uniq(skns),
method: 'h5.product.batch'
},
param: {
cache: true
}
}).then((result) => {
productObj.defaultPros = [];
if (result && result.data && result.data.product_list && result.code === 200) {
let resList = {};
result.data.product_list.forEach(function(val) {
var obj = {
producturl: `//m.yohobuy.com/product/${val.product_skn}.html?openby:yohobuy={"action":"go.productDetail","params":{"product_skn":"${val.product_skn}","from_page_name":"${yasProcess.getPname(ctx.req)}","from_page_param":"${_.get(ctx,'req.url', '')}"}}`, // eslint-disable-line
... ... @@ -30,7 +47,11 @@ class featureModel extends global.yoho.BaseModel {
saleprice: val.sales_price,
marketprice: val.sales_price === val.market_price ? '' : val.market_price,
brandname: val.brand_name,
product_skn: val.product_skn
product_skn: val.product_skn,
product_price_plan_list: _.sortBy(val.product_price_plan_list, o => {
return +o.show_begin_time;
}),
stock_number: val.stock_number
};
if (val.shop_id) {
... ... @@ -39,7 +60,36 @@ class featureModel extends global.yoho.BaseModel {
obj.brandurl = `//m.yohobuy.com/product/shop?domain=${val.brand_domain}&openby:yohobuy={"action":"go.brand","params":{"brand_id":${val.brand_id}}}`; // eslint-disable-line
}
productObj.defaultPros.push(obj);
resList[val.product_skn] = obj;
});
_.forEach(list, value => {
let defaultPros = [];
let baseConf = {
searchCondition: value.searchCondition,
lefTopImg: value.lefTopImg,
rigTopImg: value.rigTopImg,
showPrdName: value.showPrdName,
showSalePrice: value.showSalePrice,
salePriceBgColor: value.salePriceBgColor,
fontColor: value.fontColor,
vipFontColor: value.vipFontColor,
vipBgColor: value.vipBgColor,
showVipPrice: value.showVipPrice,
brandImg: value.brandImg,
showBrandUrl: value.showBrandUrl
};
value._defaultSkns && value._defaultSkns.forEach(val => {
let pro = resList[val];
if (pro) {
defaultPros.push(Object.assign({conf: baseConf}, pro));
}
});
value.defaultPros = defaultPros;
});
}
});
... ... @@ -75,6 +125,47 @@ class featureModel extends global.yoho.BaseModel {
});
}
/**
* 拼团商品列表
*/
_getCollageProductList(collageInfo, ctx) { // eslint-disable-line
let activityId = collageInfo.collageActivityId;
if (!activityId) {
return Promise.resolve();
}
return this.get({
data: {
method: 'app.collage.productList.page',
activityId: activityId,
limit: 10
},
param: {
cache: true
}
}).then(result => {
if (result.code !== 200) {
return;
}
let replaceKey = '__skn__';
let replaceReg = new RegExp(replaceKey, 'g');
let productUrl = `//m.yohobuy.com/product/${replaceKey}.html?openby:yohobuy={"action":"go.productDetail","params":{"product_skn":"${replaceKey}","activity_id":"${activityId}","activity_type":"groupPurchase"}}`; // eslint-disable-line
let defaultPros = _.get(result, 'data.collageProductVoList', []);
// if (!ctx.req.yoho.isApp) {
// productUrl = 'javascript:;'; // eslint-disable-line
// }
defaultPros.forEach(val => {
val.producturl = productUrl.replace(replaceReg, val.productSkn);
});
collageInfo.defaultPros = defaultPros;
});
}
index(params) {
const self = this;
... ... @@ -106,15 +197,19 @@ class featureModel extends global.yoho.BaseModel {
data = data.data;
if (data && data.floors) {
data.floors.forEach(f => {
if (f.component && f.component[0] &&
f.component[0].type === 'productGroup') {
let componentArr = [];
let componentType = _.get(f, 'component[0].type');
if (componentType) {
f.component[0].isStyle2 = _.get(f, 'component[0].newStyle') === '2' && _.get(f, 'component[0].numOfOneRow') === '2';// eslint-disable-line
}
if (f.component && f.component[0] &&
f.component[0].type === 'productGroup' && f.component[0].defaultSkns) {
sknsArr.push(self._getProductBySkns(f.component[0], self.ctx));
componentArr.push(f.component[0]);
// sknsArr.push(self._getProductBySkns(f.component[0], self.ctx));
f.component[0].newStyle = _.get(f, 'component[0].newStyle') === '1';
}
... ... @@ -130,7 +225,7 @@ class featureModel extends global.yoho.BaseModel {
}
// 新增店铺组
if (_.get(f, 'component[0].type') === 'shopGroup') {
if (componentType === 'shopGroup') {
shopGroups.push(self._getShopGroup(f.component[0]));
}
... ... @@ -138,6 +233,30 @@ class featureModel extends global.yoho.BaseModel {
f.height = _.get(f, 'param.height') / 20;
}
if (componentType === 'swiperSkns') {
componentArr.push(f.component[0]);
// sknsArr.push(self._getProductBySkns(f.component[0], self.ctx));
}
if (componentType === 'collageSkns') {
// componentArr.push(f.component[0]);
sknsArr.push(self._getCollageProductList(f.component[0], self.ctx));
}
if (componentType === 'cutPriceSkn' && f.param.bgimg) {
// 阶梯降价楼层显示信息位置严重依赖图片尺寸
// 将楼层背景图提取到component内部以便对其尺寸控制
//
let skn = f.component[0].SKN;
f.component[0].producturl = `//m.yohobuy.com/product/${skn}.html?openby:yohobuy={"action":"go.productDetail","params":{"product_skn":"${skn}","from_page_name":"${yasProcess.getPname(self.ctx.req)}","from_page_param":"${_.get(self.ctx, 'req.url', '')}"}}`, // eslint-disable-line
f.component[0].bgImg = f.param.bgimg;
f.param.bgimg = '';
}
_.forEach(f.component, component => {
if (component.url && component.url.indexOf('go.productDetail') !== -1) {
... ... @@ -151,7 +270,15 @@ class featureModel extends global.yoho.BaseModel {
if (component.persenal_enable === '1') {
f.hide = true; // 个性化券楼层先不展示,前端异步查询到的时候,再展示
}
if (component.type === 'skn') {
componentArr.push(component);
}
});
if (componentArr.length) {
sknsArr.push(self._getProductBySkns(componentArr, self.ctx));
}
});
}
... ... @@ -199,6 +326,14 @@ class featureModel extends global.yoho.BaseModel {
});
}
getProductBySkns(skns) {
let obj = {defaultSkns: skns};
return this._getProductBySkns(obj, this.ctx).then(() => {
return obj.defaultPros;
});
}
/**
* 领取红包
*/
... ...
... ... @@ -112,4 +112,52 @@ module.exports = class extends global.yoho.BaseModel {
}
});
}
async promoDetail(pid, uid) {
return this.get({
data: {
method: 'app.union.shareOrder.queryActivityPage',
uid,
id: pid
}
}).then(result => {
if (result.code !== 200) {
return {
error: Error('出错了')
};
}
return {
status: result.data.status,
imageUrl: result.data.image,
content: result.data.content,
contentTitle: result.data.title,
url: result.data.url,
id: result.data.id
};
});
}
async promoSubmit(pid, uid) {
return this.get({
data: {
method: 'app.union.shareOrder.preJoinActivity',
uid: uid,
id: pid
}
}).then(result => {
if (result.code !== 200) {
return {
error: Error('出错了')
};
}
return {
data: {
...result.data
},
};
});
}
};
... ...
... ... @@ -272,6 +272,7 @@ router.get('/individuation/shop', individuation.shop);
router.get('/feature/:code.html', feature.index);
router.get('/featuresidebar/:code.html', feature.sidebar);
router.get('/featurebottombar/:code.html', feature.bottombar);
router.get('/feature/goods', feature.goods);
router.get('/feature/couponSend', feature.couponSend); // 获取优惠券
router.get('/tide/category', auth, tide.category); // 潮品推介
router.get('/tide/shop', auth, tide.shop); // 潮牌推介
... ... @@ -338,4 +339,8 @@ router.get('/have-gain/fail', auth, haveGain.fail); // 揮恣銝
router.post('/have-gain/resetApply', auth, haveGain.resetApply); // 有货有赚审核不通过,重新申请API
router.post('/have-gain/submitApply', auth, haveGain.submitApply); // 有货有赚-申请开通
// 有货有赚推广活动
router.get('/have-gain/promo/:id.html', haveGain.promoDetail);
router.post('/have-gain/promo/:id', auth, haveGain.promoSubmit);
module.exports = router;
... ...
... ... @@ -28,7 +28,7 @@
{{#isEqualOr type '' 'common_floor' 'fix'}}
{{! 普通楼层 顶悬浮}}
<div {{#if param.anchorname}} id="{{param.anchorname}}" {{/if}} {{#if param.tabname}} tabname="{{param.tabname}}" {{/if}}
{{#if id}} data-id="{{id}}" {{/if}} class="floor {{type}} {{#if hide}}hide{{/if}}" style="{{#if param.bgcolor}}background-color:{{param.bgcolor}}{{/if}}">
{{#if id}} data-id="{{id}}" {{/if}} class="floor clearfix {{type}} {{#if hide}}hide{{/if}}" style="{{#if param.bgcolor}}background-color:{{param.bgcolor}}{{/if}}">
{{#if param.bgimg}}
{{#isLazyLoad type @index}}
<img class="lazy" data-original="{{imageslim param.bgimg}}">
... ... @@ -114,6 +114,40 @@
{{> feature/product-new-style}} {{^}} {{> feature/product-old-style}}
{{/isEqualOr}}
{{/isEqualOr}}
{{#isEqualOr type 'collageSkns'}}
{{! 拼团}}
{{> feature/swiper-product-collage}}
{{/isEqualOr}}
{{#isEqualOr type 'shop'}}
{{! 店铺}}
<div class="product-container single-item3">
<a class="shop-container" href="{{jumpUrl}}">
<div class="feature-shop-info">
<image src="{{shopImge}}"></image>
</div>
</a>
</div>
{{/isEqualOr}}
{{#isEqualOr type 'skn'}}
{{! 商品}}
{{#defaultPros}}
<div class="product-container single-item3">
{{> feature/product-old-item}}
</div>
{{/defaultPros}}
{{/isEqualOr}}
{{#isEqualOr type 'swiperSkns'}}
{{! 商品侧滑组}}
{{> feature/swiper-product}}
{{/isEqualOr}}
{{#isEqualOr type 'cutPriceSkn'}}
{{! 阶梯降价}}
{{> feature/timed-cut-product}}
{{/isEqualOr}}
{{/component}}
</div>
{{/isEqualOr}}
... ...
... ... @@ -4,33 +4,10 @@
<div class="apply-title">基本信息</div>
<ul class="section-ul">
<li><span>姓名</span><input type="text" class="name" placeholder="请输入姓名" /></li>
<li class="border-node"><span>手机号码</span><input type="number" class="mobile" placeholder="请输入手机号码" /></li>
<li><span>手机号码</span><input type="number" class="mobile" placeholder="请输入手机号码" /></li>
<li><span>微信号</span><input type="text" class="wechat" placeholder="请输入微信号(选填)" /></li>
</ul>
</div>
<div class="section">
<div class="apply-title">完善信息</div>
{{#socialMediaList}}
<div class="party-icon-item">
<div class="public-info-section">
<img class="public-icon" src="{{icon}}" />
<div class="personal">
<div class="public-name">{{name}}</div>
<div class="account-name {{#if required}}required{{/if}}" data-type="{{type}}">
{{#if account}}
账号:<em>{{account}}</em>&nbsp;&nbsp;
粉丝:<em data-fans="{{fans}}">{{fans}}</em>
{{/if}}
</div>
</div>
</div>
{{#if account}}
<div class="fill-in disable">已填写</div>
{{else}}
<div class="fill-in">填写</div>
{{/if}}
</div>
{{/socialMediaList}}
<p class="other">如果您有其他渠道,可以添加我们的服务号“有货有赚”反馈,也可以了解您的申请状态<em class="added">点击添加</em></p>
<p class="other">提供微信号,方便邀您加入达人微信群,赚钱秘籍、特殊福利享不停!添加关注公众号“有货有赚”,申请状态、高佣活动早知道。<em class="added">点击添加</em></p>
</div>
<div class="agreement-section">
<div class="agreement">
... ...
<div class="promo-page">
<div class="promo-banner">
<img src="{{imageUrl}}">
</div>
<div class="promo-desc">
<div class="promo-desc__title">{{{contentTitle}}}</div>
<div class="promo-desc__content">{{{content}}}</div>
</div>
<div class="promo-status {{#isEqualOr status 2 3}} promo-status_submit {{else}} promo-status_over {{/isEqualOr}} js-submit" data-url="{{url}}" data-pid="{{id}}" data-status="{{status}}">
{{#isEqualOr status 1}}
活动未开始
{{/isEqualOr}}
{{#isEqualOr status 2}}
点击确认参加活动
{{/isEqualOr}}
{{#isEqualOr status 3}}
报名成功,去分享活动商品
{{/isEqualOr}}
{{#isEqualOr status 4}}
活动已结束,请关注其他活动
{{/isEqualOr}}
</div>
</div>
... ...
<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">
{{#if conf.lefTopImg}}
<img class="leftopimg lazy" data-original="{{image2 conf.lefTopImg q=85}}">
{{/if}}
{{#if conf.rigTopImg}}
<img class="rigtopimg lazy" data-original="{{image2 conf.rigTopImg q=85}}">
{{/if}}
<img class="product-detail-img product-detail-img-new lazy" data-original="{{image2 productimg q=85}}">
</div>
<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>
</a>
{{#if conf.brandImg}}
<a class="second-part">
<div class="new-brand-div">
{{#isEqualOr conf.showSalePrice '1'}}
<div class="new-price" style="{{#if conf.salePriceBgColor}}background:{{conf.salePriceBgColor}};{{/if}}{{#if conf.priceFontColor}}color:{{conf.priceFontColor}};{{/if}}">
<span class="sale-price"{{#if conf.fontColor}} style="color:{{conf.fontColor}};" {{/if}}>¥{{saleprice}}</span>
{{#if marketprice}}
<span class="market-price"{{#if conf.fontColor}} style="color:{{conf.fontColor}};" {{/if}}>¥{{marketprice}}</span>
{{/if}}
</div>
{{/isEqualOr}}
{{#isEqualOr conf.showVipPrice '1'}}
<div class="vipprice" style="{{#if conf.vipFontColor}}color:{{conf.vipFontColor}};{{/if}}{{#if conf.vipBgColor}}background:{{conf.vipBgColor}};{{/if}}">
<span class="vip-price-text">VIP价</span>
<span class="vip-price-val">¥{{vipprice}}</span>
</div>
{{/isEqualOr}}
</div>
<img class="brand-img" src="{{image2 conf.brandImg q=85}}">
</a>
{{/if}}
</div>
... ...
... ... @@ -6,43 +6,7 @@
<input class="imgwh" type="hidden" value="386x514">
{{#if defaultPros.length}}
{{#defaultPros}}
<div class="feature-product-info {{#if ../searchCondition}}novisible{{/if}}" data-skn="{{product_skn}}">
<a class="first-part product-detail" href='{{producturl}}'>
<div class="product-detail-imgbox">
{{#if ../lefTopImg}}
<img class="leftopimg lazy" data-original="{{image2 ../lefTopImg q=85}}">
{{/if}}
{{#if ../rigTopImg}}
<img class="rigtopimg lazy" data-original="{{image2 ../rigTopImg q=85}}">
{{/if}}
<img class="product-detail-img product-detail-img-new lazy" data-original="{{image2 productimg q=85}}">
</div>
<a class="new-brand-name {{#isEqualOr ../showBrandUrl '1'}}product-brand{{else}}product-detail{{/isEqualOr}}" href="{{brandurl}}">
<span class="brand-name" {{#if ../fontColor}} style="color:{{../fontColor}};" {{/if}}>{{brandname}}</span>
</a>
</a>
{{#if ../brandImg}}
<a class="second-part">
<div class="new-brand-div">
{{#isEqualOr ../showSalePrice '1'}}
<div class="new-price" style="{{#if ../salePriceBgColor}}background:{{../salePriceBgColor}};{{/if}}{{#if ../priceFontColor}}color:{{../priceFontColor}};{{/if}}">
<span class="sale-price"{{#if ../fontColor}} style="color:{{../fontColor}};" {{/if}}>¥{{saleprice}}</span>
{{#if marketprice}}
<span class="market-price"{{#if ../fontColor}} style="color:{{../fontColor}};" {{/if}}>¥{{marketprice}}</span>
{{/if}}
</div>
{{/isEqualOr}}
{{#isEqualOr ../showVipPrice '1'}}
<div class="vipprice" style="{{#if ../vipFontColor}}color:{{../vipFontColor}};{{/if}}{{#if ../vipBgColor}}background:{{../vipBgColor}};{{/if}}">
<span class="vip-price-text">VIP价</span>
<span class="vip-price-val">¥{{vipprice}}</span>
</div>
{{/isEqualOr}}
</div>
<img class="brand-img" src="{{image2 ../brandImg q=85}}">
</a>
{{/if}}
</div>
{{> feature/product-new-item}}
{{/defaultPros}}
{{else}}
<div class="feature-product-info novisible" data-skn="{{product_skn}}">
... ...
<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">
{{#if conf.lefTopImg}}
<img class="leftopimg lazy" data-original="{{image2 conf.lefTopImg q=85}}">
{{/if}}
{{#if conf.rigTopImg}}
<img class="rigtopimg lazy" data-original="{{image2 conf.rigTopImg q=85}}">
{{/if}}
<img class="product-detail-img lazy" data-original="{{image2 productimg q=85}}">
</div>
{{#isEqualOr conf.showPrdName '1'}}
<p class="product-name">{{productname}}</p>
{{/isEqualOr}}
<div class="product-detail-text">
{{#isEqualOr conf.showSalePrice '1'}}
<div class="price" style="{{#if conf.salePriceBgColor}}background:{{conf.salePriceBgColor}};{{/if}}">
<span class="sale-price"{{#if conf.fontColor}} style="color:{{conf.fontColor}};" {{/if}}>¥{{saleprice}}</span>
{{#if marketprice}}
<span class="market-price"{{#if conf.fontColor}} style="color:{{conf.fontColor}};" {{/if}}>¥{{marketprice}}</span>
{{/if}}
</div>
{{/isEqualOr}}
{{#isEqualOr conf.showVipPrice '1'}}
<div class="vipprice" style="{{#if conf.vipFontColor}}color:{{conf.vipFontColor}};{{/if}}{{#if conf.vipBgColor}}background:{{conf.vipBgColor}};{{/if}}">
<span class="vip-price-text">VIP价</span>
<span class="vip-price-val">¥{{vipprice}}</span>
</div>
{{/isEqualOr}}
</div>
</a>
{{#if conf.brandImg}}
<a class="second-part {{#isEqualOr conf.showBrandUrl '1'}}product-brand{{else}}product-detail{{/isEqualOr}}" href='{{brandurl}}'>
<div class="brand-div">
<span class="brand-name" {{#if conf.fontColor}} style="color:{{conf.fontColor}};" {{/if}}>{{brandname}}</span>
</div>
<img class="brand-img" src="{{image2 conf.brandImg q=85}}">
</a>
{{/if}}
</div>
... ...
... ... @@ -6,46 +6,7 @@
<input class="imgwh" type="hidden" value="386x514">
{{#if defaultPros.length}}
{{#defaultPros}}
<div class="feature-product-info {{#if ../searchCondition}}novisible{{/if}}" data-skn="{{product_skn}}">
<a class="first-part product-detail" href='{{producturl}}'>
<div class="product-detail-imgbox">
{{#if ../lefTopImg}}
<img class="leftopimg lazy" data-original="{{image2 ../lefTopImg q=85}}">
{{/if}}
{{#if ../rigTopImg}}
<img class="rigtopimg lazy" data-original="{{image2 ../rigTopImg q=85}}">
{{/if}}
<img class="product-detail-img lazy" data-original="{{image2 productimg q=85}}">
</div>
{{#isEqualOr ../showPrdName '1'}}
<p class="product-name">{{productname}}</p>
{{/isEqualOr}}
<div class="product-detail-text">
{{#isEqualOr ../showSalePrice '1'}}
<div class="price" style="{{#if ../salePriceBgColor}}background:{{../salePriceBgColor}};{{/if}}">
<span class="sale-price"{{#if ../fontColor}} style="color:{{../fontColor}};" {{/if}}>¥{{saleprice}}</span>
{{#if marketprice}}
<span class="market-price"{{#if ../fontColor}} style="color:{{../fontColor}};" {{/if}}>¥{{marketprice}}</span>
{{/if}}
</div>
{{/isEqualOr}}
{{#isEqualOr ../showVipPrice '1'}}
<div class="vipprice" style="{{#if ../vipFontColor}}color:{{../vipFontColor}};{{/if}}{{#if ../vipBgColor}}background:{{../vipBgColor}};{{/if}}">
<span class="vip-price-text">VIP价</span>
<span class="vip-price-val">¥{{vipprice}}</span>
</div>
{{/isEqualOr}}
</div>
</a>
{{#if ../brandImg}}
<a class="second-part {{#isEqualOr ../showBrandUrl '1'}}product-brand{{else}}product-detail{{/isEqualOr}}" href='{{brandurl}}'>
<div class="brand-div">
<span class="brand-name" {{#if ../fontColor}} style="color:{{../fontColor}};" {{/if}}>{{brandname}}</span>
</div>
<img class="brand-img" src="{{image2 ../brandImg q=85}}">
</a>
{{/if}}
</div>
{{> feature/product-old-item}}
{{/defaultPros}}
{{else}}
<div class="feature-product-info novisible" data-skn="{{product_skn}}">
... ...
... ... @@ -3,7 +3,9 @@
{{#isEqualOr ../numOfOneRow '2'}}
<a{{#isEqualOr ../jump2Shop '1'}} href="{{href}}"{{/isEqualOr}}class="pull-left shop-box">
<div class="shop-img">
<img class="left-icon lazy" data-original="{{image2 ../lefTopImg q=85}}" alt="">
{{#if ../lefTopImg}}
<img class="left-icon lazy" data-original="{{image2 ../lefTopImg q=85}}" alt="">
{{/if}}
<img class="lazy" data-original="{{image2 picture w=284 h=320 q=85}}" alt="">
</div>
<div class="shop-bottom-bar" style="background-image: url({{image2 ../brandImg w=290 h=60 q=85}})">
... ...
<div class="side-swiper-goods-wrap" {{#if proBgImg}} style="background:url({{image2 proBgImg q=85}}) repeat;background-size:100%;"{{/if}}>
<div class="side-swiper-content">
<ul>
{{#defaultPros}}
<li class="side-swiper-item" data-skn="{{productSkn}}">
<a href="{{producturl}}">
<div class="img-box">
{{#if ../lefTopImg}}
<img class="leftopimg lazy" data-original="{{image2 ../lefTopImg q=85}}">
{{/if}}
{{#if ../rigTopImg}}
<img class="rigtopimg lazy" data-original="{{image2 ../rigTopImg q=85}}">
{{/if}}
<img class="goods-pic lazy" data-original="{{image2 defaultImages w=213 h=284 q=85}}" alt="goods">
</div>
<div class="goods-info">
<div class="info-middle">
<div class="pro-price" style="{{#if ../priceFontColor}}color:{{../priceFontColor}};{{/if}}">
<span class="sale-price"{{#if ../fontColor}} style="color:{{../fontColor}};" {{/if}}>¥{{collagePrice}}</span>
{{#if marketPrice}}
<span class="market-price" {{#if ../fontColor}} style="color:{{../fontColor}};"{{/if}}>¥{{marketPrice}}</span>
{{/if}}
</div>
{{#isEqualOr ../showPrdName '1'}}
<div class="product-name">
<span {{#if ../fontColor}} style="color:{{../fontColor}};" {{/if}}>{{productName}}</span>
</div>
{{/isEqualOr}}
<div class="join-num">
{{joinPeopleNum}}人已拼
</div>
</div>
</div>
</a>
</li>
{{/defaultPros}}
</ul>
</div>
</div>
... ...
<div class="side-swiper-goods-wrap" {{#if proBgImg}} style="background:url({{image2 proBgImg q=85}}) repeat;background-size:100%;"{{/if}}>
<div class="side-swiper-content">
<ul>
{{#defaultPros}}
<li class="side-swiper-item" data-skn="{{product_skn}}">
<a href="{{producturl}}">
<div class="img-box">
{{#if ../lefTopImg}}
<img class="leftopimg lazy" data-original="{{image2 ../lefTopImg q=85}}">
{{/if}}
{{#if ../rigTopImg}}
<img class="rigtopimg lazy" data-original="{{image2 ../rigTopImg q=85}}">
{{/if}}
<img class="goods-pic lazy" data-original="{{image2 productimg q=85}}" alt="goods">
</div>
<div class="goods-info">
<div class="info-middle">
{{#isEqualOr ../showSalePrice '1'}}
<div class="pro-price" style="{{#if ../salePriceBgColor}}background:{{../salePriceBgColor}};{{/if}}{{#if ../priceFontColor}}color:{{../priceFontColor}};{{/if}}">
<span class="sale-price"{{#if ../fontColor}} style="color:{{../fontColor}};" {{/if}}>¥{{saleprice}}</span>
{{#if marketprice}}
<span class="market-price" {{#if ../fontColor}} style="color:{{../fontColor}};"{{/if}}>¥{{marketprice}}</span>
{{/if}}
</div>
{{/isEqualOr}}
{{#isEqualOr ../showBrandUrl '1'}}
<a class="brand-name" href="{{brandurl}}">
<span {{#if ../fontColor}} style="color:{{../fontColor}};" {{/if}}>{{brandname}}</span>
</a>
{{/isEqualOr}}
</div>
</div>
</a>
</li>
{{/defaultPros}}
</ul>
</div>
</div>
... ...
<div class="timed-cut-container" {{#if bgImg}} style="background-image:url({{image2 bgImg w=750 h=460 q=85}});"{{/if}} data-skn="{{SKN}}">
<a href="{{producturl}}">
<div class="act-time">
<p class="start-time" data-time="{{beginTime}}">开始时间:<span>{{beginTime}}</span></p>
<p class="end-time" data-time="{{endTime}}">结束时间:{{endTime}}</p>
</div>
<div class="now-price">¥<span></span></div>
<div class="limit-time"><p></p></div>
<div class="opt-btn"></div>
</a>
</div>
... ...
... ... @@ -4,6 +4,8 @@ const aes = require('./aes-pwd');
const authcode = require('../../../utils/authcode');
const logger = global.yoho.logger;
const sign = global.yoho.sign;
const config = global.yoho.config;
const utils = require('../../../utils');
const uuid = require('uuid');
const url = require('url');
const md5 = require('yoho-md5');
... ... @@ -99,7 +101,7 @@ class AuthModel extends global.yoho.BaseModel {
return md5(secretStr + clientSecret);
}
thirdLogin(req, res, uid) {
referUrl(req, res, uid, sessionKey) {
if (req.cookies.third_type && req.cookies.third_backurl && req.cookies.third_refer) {
let backurl = url.parse(req.cookies.third_backurl),
account = thirdAccount[req.cookies.third_type];
... ... @@ -119,16 +121,61 @@ class AuthModel extends global.yoho.BaseModel {
return {
refer: `${backurl.protocol}//${backurl.host}${backurl.pathname}?${queryStr}`
};
} else {
res.clearCookie('third_type', {
domain: 'yohobuy.com'
});
res.clearCookie('third_backurl', {
domain: 'yohobuy.com'
});
res.clearCookie('third_refer', {
domain: 'yohobuy.com'
});
try {
let refer = req.cookies.refer;
if (refer) {
refer = decodeURI(refer);
} else {
refer = `${config.siteUrl}/home`;
}
if (/sign|login/.test(refer)) {
refer = `${config.siteUrl}/home`;
}
refer = utils.refererLimit(refer);
let referUrl;
let backurl = url.parse(refer, false, true);
const qs = querystring.parse(backurl.query);
if (!qs.skcall) {
return; // 不处理 外层有各自的refer逻辑
}
let params = Object.assign({
uid: uid,
app_version: config.appVersion,
app_client_type: config.app,
session_key: sessionKey
}, qs);
let queryStr = _.join(_.map(params, (v, k) => {
return `${k}=${encodeURIComponent(v)}`;
}), '&');
if (backurl.hostname && backurl.protocol) {
referUrl = `${backurl.protocol}//${backurl.hostname}`;
}
referUrl = `${referUrl || ''}${backurl.pathname}?${queryStr}`;
return {
refer: referUrl
};
} catch (e) {
return;
}
}
res.clearCookie('third_type', {
domain: 'yohobuy.com'
});
res.clearCookie('third_backurl', {
domain: 'yohobuy.com'
});
res.clearCookie('third_refer', {
domain: 'yohobuy.com'
});
}
syncUserSession(uid, req, res, sessionKey) {
... ... @@ -192,8 +239,8 @@ class AuthModel extends global.yoho.BaseModel {
expires: new Date(Date.now() + 2592000000) // 有效期一年
});
// 第三方登录逻辑
return this.thirdLogin(req, res, uid);
// 登录回调地址
return this.referUrl(req, res, uid, sessionKey);
});
}
}
... ...
... ... @@ -2,7 +2,7 @@ const shelljs = require('shelljs');
const yargs = require('yargs');
const path = require('path');
const cssnano = require('cssnano');
const request = require('request');
const rp = require('request-promise');
const fs = require('fs');
const pkg = require('../package.json');
... ... @@ -33,19 +33,30 @@ new Promise((resolve, reject) => { // 加载manifest.json文件
cpPaths.push(`dist/statics/yohobuywap-node/${pkg.version}/manifest.json`);
resolve();
} else {
request({
url: `https://cdn.yoho.cn/yohobuywap-node/${pkg.version}/manifest.json`,
gzip: true,
json: true
}, (error, response, data) => {
if (error || !data || data.error) {
return reject(`download manifest.json faild:${error || !data || data.error}`);
return Promise.all([
rp({
url: `https://cdn.yoho.cn/yohobuywap-node/${pkg.version}/manifest.json`,
gzip: true,
json: true
}),
rp({
url: 'https://m.yohobuy.com/sw.js',
gzip: true
}),
]).then(results => {
const [manifest, sw] = results;
if (!manifest || !sw) {
throw 'manifest.json or sw.js download faild';
}
fs.writeFileSync(path.join(distDir, 'manifest.json'), JSON.stringify(data), {
fs.writeFileSync(path.join(distDir, 'manifest.json'), JSON.stringify(manifest), {
flag: 'w'
});
fs.writeFileSync(path.join(__dirname, '../public/static/sw.js'), sw, {
flag: 'w'
});
resolve();
});
}).catch(reject);
}
}).then(() => { // 拷贝node代码
cpPaths.forEach(p => {
... ...
... ... @@ -15,6 +15,7 @@ const domains = {
// api: 'http://api.yoho.cn/',
// service: 'http://service.yoho.cn/',
// liveApi: 'http://testapi.live.yohops.com:9999/',
// singleApi: 'http://api-test3.yohops.com:9999/',
... ... @@ -97,7 +98,7 @@ module.exports = {
}
},
console: {
level: 'info',
level: 'debug',
colorize: 'all',
prettyPrint: true,
debugStdout: true
... ...
... ... @@ -10,8 +10,6 @@ const sender = global.yoho.apmSender;
const config = global.yoho.config;
const hostname = require('os').hostname();
const routeEncode = require('./route-encode');
const pathWhiteList = require('./limiter/rules/path-white-list');
const ipWhiteList = require('./limiter/rules/ip-white-list');
const _ = require('lodash');
const replaceKey = '__refer__';
... ... @@ -125,7 +123,7 @@ exports.serverError = () => {
logger.error(err);
}
if (req.isApmReport && err.code !== 401) {
if (req.isApmReport && !err.apiError) {
// 上报服务端错误
sender.addMessage({
measurement: 'error-report',
... ... @@ -150,7 +148,7 @@ exports.serverError = () => {
});
}
if (err && err.code === 401) {
if (err.code === 401) {
logger.warn(`401 warn info:client_type=${req.query.client_type},req.user=${JSON.stringify(req.user)},req.query=${JSON.stringify(req.query)},cookies=${JSON.stringify(req.cookies)}`); // eslint-disable-line
if (req.xhr) {
... ... @@ -176,48 +174,27 @@ exports.serverError = () => {
refer: req.originalUrl
}));
}
} else if (err.apiRisk || err.code === 9999991 || err.code === 9999992) {
} else if (err.apiRisk) {
let remoteIp = req.yoho.clientIp;
if (!err.apiRisk && (_.includes(pathWhiteList(), req.path) || (await ipWhiteList(remoteIp)))) {
return _err510(req, res, 510, err);
}
if (remoteIp.indexOf(',') > 0) {
let arr = remoteIp.split(',');
remoteIp = arr[0];
}
let sessionLimitKey;
let isHuman;
if (err.apiRisk) {
sessionLimitKey = 'apiRiskValidate';
if (_.get(req.app.locals, 'wap.open.apmrisk', false)) {
cache.setAsync(`${config.app}:limit2:${remoteIp}`, 1, config.LIMITER_IP_TIME);
} else {
sessionLimitKey = 'apiLimitValidate';
isHuman = await cache.getAsync(`${config.app}:limiter:api:ishuman:${remoteIp}`);
cache.setAsync(`${config.app}:limiter:${remoteIp}`, 1, config.LIMITER_IP_TIME);
}
if (!isHuman) {
if (_.get(req.app.locals, 'wap.open.apmrisk', false)) {
cache.setAsync(`${config.app}:limit2:${remoteIp}`, 1, config.LIMITER_IP_TIME);
} else {
cache.setAsync(`${config.app}:limiter:${remoteIp}`, 1, config.LIMITER_IP_TIME);
}
req.session[sessionLimitKey] = true;
if (req.xhr) {
return res.status(510).json({
code: err.code,
data: {refer: checkRefer.replace(replaceKey, req.get('Referer') || '')}
});
}
req.session.apiRiskValidate = true;
return res.redirect(checkRefer.replace(replaceKey, req.protocol + '://' + req.get('host') + req.originalUrl));
if (req.xhr) {
return res.status(510).json({
code: err.code,
data: {refer: checkRefer.replace(replaceKey, req.get('Referer') || '')}
});
}
return res.redirect(checkRefer.replace(replaceKey, req.protocol + '://' + req.get('host') + req.originalUrl));
} else if (err.code === 9999991 || err.code === 9999992) {
return _err510(req, res, 510, err);
}
... ...
... ... @@ -5,8 +5,15 @@ module.exports = (app) => {
let manifest;
if (!app.locals.devEnv) {
manifest = require('../../manifest.json');
let manifestPath = '../../manifest.json';
if (app.locals.isTest) {
manifestPath = `../../dist/statics/${config.appName}/${app.locals.version}/manifest.json`;
}
manifest = require(manifestPath);
}
function getStatic(path, def) {
return _.get(manifest, path, `${config.assetUrl}${def}`);
}
... ...
... ... @@ -12,7 +12,7 @@
a.async = 1;
a.src = j;
m.parentNode.insertBefore(a, m);
}(window, document, 'script', (document.location.protocol === 'https:' ? 'https:' : 'http:') + '//cdn.yoho.cn/yas-jssdk/2.4.17/yas.js', '_yas'));
}(window, document, 'script', (document.location.protocol === 'https:' ? 'https:' : 'http:') + '//cdn.yoho.cn/yas-jssdk/2.4.18/yas.js', '_yas'));
var _hmt = _hmt || [];
... ...
{
"name": "yohobuywap-node",
"version": "6.7.13",
"version": "6.7.14",
"private": true,
"description": "A New Yohobuy Project With Express",
"repository": {
... ... @@ -21,7 +21,7 @@
"lint-js": "npm run -s lint:js -- .",
"lint-all": "echo \"JS: \";npm run -s lint-js;echo \"CSS: \";npm run -s lint-css",
"precommit": "lint-staged",
"prod": "git pull && webpack --config ./public/build/webpack.dll.indexcss.config.js && webpack --config ./public/build/webpack.prod.config.js && pm2 reload yohobuywap-node"
"prod": "git pull && yo-cli build --config ./build/yo.prod.conf.js && pm2 reload yohobuywap-node"
},
"lint-staged": {
"*.{js,vue}": [
... ... @@ -88,7 +88,7 @@
"xml2js": "^0.4.19",
"yoho-express-session": "^2.0.0",
"yoho-md5": "^2.0.0",
"yoho-node-lib": "=0.6.32",
"yoho-node-lib": "=0.6.34",
"yoho-zookeeper": "^1.0.10"
},
"devDependencies": {
... ...
... ... @@ -11,7 +11,9 @@ require('scss/feature.scss');
let isAndroid = /(Android)/i.test(navigator.userAgent);
let isWechat = /micromessenger/i.test(navigator.userAgent);
lazyLoad($('img.lazy'));
lazyLoad($('img.lazy'), {
q: 85
});
function swiperInit() {
$('.swiper-container').each(function() {
... ... @@ -305,6 +307,218 @@ function shopGroupInit() {
});
}
function convertTime(time) {
var anHour = 3600,
aMinute = 60,
aSecond = 1,
h = 0,
m = 0,
s = 0;
if (time > 1) {
h = Math.floor(time / anHour);
m = Math.floor(time / aMinute % 60);
s = Math.floor(time / aSecond % 60);
}
return `${h < 10 ? '0' : ''}${h}:${m < 10 ? '0' : ''}${m}:${s < 10 ? '0' : ''}${s}`;
}
function timedCutProductInit() {
let $timedCut = $('.timed-cut-container');
if (!$timedCut.length) {
return;
}
let timedCutArr = [];
let skns = [];
$timedCut.each(function() {
let $this = $(this),
skn = $this.data('skn');
if (skn) {
timedCutArr.push({
$price: $this.find('.now-price > span'),
$time: $this.find('.limit-time > p'),
$bth: $this.find('.opt-btn'),
startTimeStr: $this.find('.start-time').data('time'),
endTimeStr: $this.find('.end-time').data('time'),
skn: skn,
btnClass: '',
changeNowPrice: function(curPrice) {
if (this.curPrice !== curPrice) {
this.$price.text(curPrice);
this.curPrice = curPrice;
}
},
changeBtnClass: function(status) {
let className = 'btn-status' + status;
if (this.btnClass !== className) {
this.$bth.removeClass(this.btnClass);
this.$bth.addClass(className);
this.btnClass = className;
switch (+status) {
case 3:
this.$time.text('活动商品已售罄');
break;
case 4:
this.$time.text('活动已结束');
break;
default:
break;
}
}
}
});
skns.push(skn);
}
});
if (!skns.length) {
return;
}
$.ajax({
url: '//m.yohobuy.com/activity/feature/goods',
dataType: 'jsonp',
data: {
skns: skns.join(',')
},
success: function(res) {
if (res.code !== 200 || !res.data || !res.data.length) {
return;
}
let time = res.timestamp || Date.parse(new Date()) / 1000;
let list = {};
res.data.forEach(value => {
list[value.product_skn] = value;
});
timedCutArr.forEach(value => {
let info = list[value.skn] || {};
value.plan = info.product_price_plan_list || [];
value.stockNumber = +info.stock_number;
if (value.startTimeStr) {
value.startTime = Date.parse(new Date(value.startTimeStr)) / 1000;
}
if (value.endTimeStr) {
value.endTime = Date.parse(new Date(value.endTimeStr)) / 1000;
}
if (!value.startTime) {
value.startTime = value.plan[0] && value.plan[0].show_begin_time; // 活动开始时间
}
if (!value.endTime) {
value.endTime = value.plan[0] && value.plan[0].show_begin_time; // 活动结束时间
}
let plan = [];
value.plan.forEach(val => {
if (+val.effect_time > +value.endTime || +val.end_time < +value.startTime) {
return;
}
plan.push(val);
});
value.curEndTime = 0; // 当前价格档结束时间
value.saleprice = info.saleprice; // 商品售价
});
let timer;
let changeProductStatus = () => {
time++;
let endNum = 0;
timedCutArr.forEach(value => {
if (time > value.endTime) { // 【活动已结束】
value.changeBtnClass(4);
// 活动已结束时价格恢复售价
value.changeNowPrice(value.saleprice);
endNum++;
} else if (time >= value.startTime) { // 【活动进行中】
if (!value.stockNumber) { // 【活动进行中-售罄】
value.changeBtnClass(3);
return;
}
let curPrice;
value.changeBtnClass(2);
if (time >= value.curEndTime) {
let curEndTime,
curStartTime;
value.plan.forEach(val => {
if (!curEndTime && val.end_time - time > 0) {
curEndTime = +val.end_time;
curStartTime = +val.effect_time;
curPrice = +val.current_saleprice;
}
});
// 取不到下一档时价格恢复售价
curPrice = curPrice || value.saleprice;
value.curStartTime = curStartTime;
value.curEndTime = curEndTime;
}
let limitTime;
if (time >= value.curStartTime) {
limitTime = value.curEndTime - time;
} else {
// 当前降价未开始时价格恢复售价
curPrice = value.saleprice;
limitTime = value.curStartTime - time;
}
value.changeNowPrice(curPrice);
value.$time.text(`距离下次降价还剩 ${convertTime(limitTime)}`);
} else { // 【活动未开始】
value.changeBtnClass(1);
value.changeNowPrice(value.saleprice);
if (value.startTime) {
value.$time.text(`距离下次降价还剩 ${convertTime(value.startTime - time)}`);
} else {
value.$time.text('活动即将开始');
}
}
});
// 所有活动结束,清除定时器
if (timer && endNum === timedCutArr.length) {
clearInterval(timer);
}
};
changeProductStatus();
timer = setInterval(changeProductStatus, 1000);
}
});
}
$(function() {
if ($('.over').length) {
// 过期/删除 状态的 活动
... ... @@ -357,6 +571,9 @@ $(function() {
// 个性化店铺组
shopGroupInit();
// 阶梯降价
timedCutProductInit();
// 小程序相关处理
if (window.__wxjs_environment === 'miniprogram') {
require('./miniprogram');
... ...
... ... @@ -17,6 +17,7 @@ class HaveGainApplyPage extends Page {
$apply: $('.have-gain-apply'),
$nameInput: $('.section .name'),
$mobileInput: $('.section .mobile'),
$wxInput: $('.section .wechat'),
$fillIn: $('.party-icon-item .fill-in'),
$added: $('.other .added'),
$agreement: $('.agreement-section .agreement'),
... ... @@ -127,7 +128,6 @@ class HaveGainApplyPage extends Page {
let errStatus = 0;
let name = $.trim(this.selector.$nameInput.val());
let mobile = $.trim(this.selector.$mobileInput.val());
let wxInput = $('.account-name.required').find('em').length > 0;
if (name === '') {
errStatus = 1;
... ... @@ -135,8 +135,6 @@ class HaveGainApplyPage extends Page {
errStatus = 2;
} else if (!/^1[0-9]{10}$/.test(mobile)) {
errStatus = 21;
} else if (!wxInput) {
errStatus = 3;
}
if (errStatus) {
... ... @@ -205,6 +203,7 @@ class HaveGainApplyPage extends Page {
apply() {
let errStatus = this.changeBtnStatus();
let socialMediaList = [];
let union = {};
if (errStatus === 1) {
tip.show('请输入姓名');
... ... @@ -212,8 +211,6 @@ class HaveGainApplyPage extends Page {
tip.show('请输入手机号');
} else if (errStatus === 21) {
tip.show('请输入正确的手机号');
} else if (errStatus === 3) {
tip.show('请填写微信账号');
}
if (errStatus) {
... ... @@ -225,15 +222,14 @@ class HaveGainApplyPage extends Page {
return tip.show('请勾选《我已阅读并同意》');
}
this.selector.$fillIn.each((index, event) => {
let $accountName = $(event).closest('.party-icon-item').find('.account-name');
let wxAccount = $.trim(this.selector.$wxInput.val());
if (wxAccount) {
socialMediaList.push({
type: $accountName.data('type'),
account: $accountName.find('em').eq(0).text() || '',
fans: parseInt(`0${$accountName.find('em').eq(1).data('fans')}`, 10)
type: 1,
account: wxAccount
});
});
}
if (this.selector.isFlag) {
return false;
... ... @@ -241,14 +237,21 @@ class HaveGainApplyPage extends Page {
this.selector.isFlag = true;
if (this.query.union_type) {
union.union_type = this.query.union_type;
}
if (socialMediaList.length) {
union.socialMediaList = JSON.stringify(socialMediaList);
}
return this.ajax({
type: 'post',
url: `/activity/have-gain/submitApply${window.location.search}`,
data: {
data: Object.assign({
name: $.trim(this.selector.$nameInput.val()),
mobile: $.trim(this.selector.$mobileInput.val()),
socialMediaList: JSON.stringify(socialMediaList)
}
mobile: $.trim(this.selector.$mobileInput.val())
}, union)
}).then(res => {
this.selector.isFlag = false;
... ...
import 'scss/activity/have-gain-promodetail.page.scss';
import $ from 'yoho-jquery';
require('js/plugin/modal.alert');
const $promoStatus = $('.promo-status.js-submit');
function joinActivity(id) {
return $.post(`/activity/have-gain/promo/${id}`);
}
$promoStatus.on('click', function() {
const $this = $(this);
const url = $this.data('url');
const pid = $this.data('pid');
const status = parseInt($this.data('status'), 10);
if ($this.hasClass('promo-status_over')) {
return;
}
switch (status) {
case 2: {
if (pid) {
joinActivity(pid).then(result => {
if (result.code === 400) {
window.location.href = result.redirect;
return;
}
if (result.code !== 200) {
$.yAlert(result.data.message);
return;
}
if (result.data.result === 1) {
$promoStatus
.text('报名成功,去分享活动商品')
.data('status', 3);
$.yAlert(result.data.message);
} else if (result.data.result === 3) {
$promoStatus
.text('不符合条件')
.removeClass('promo-status_submit')
.addClass('promo-status_over');
$.yAlert(result.data.message);
} else {
$.yAlert(result.data.message);
}
});
}
break;
}
case 3: {
window.location.href = url;
break;
}
default:
// pass
break;
}
});
... ...
... ... @@ -244,13 +244,14 @@ cHammer.on('tap', function() {
$search.on('touchend', function() {
let $buriedpoint = $form.find('.buriedpoint');
let inputQuery = $buriedpoint.val();
if ($buriedpoint.val() === '') {
$buriedpoint.val($('#default-terms').val());
if (inputQuery === '') {
inputQuery = $('#default-terms').val();
}
// 保存搜索的内容
writeSearch.setHistoryValFun($buriedpoint.val());
writeSearch.setHistoryValFun(inputQuery);
if (security.hasDangerInput()) {
return false;
... ... @@ -261,15 +262,14 @@ $search.on('touchend', function() {
op: 'YB_KEYWORD_SEARCH_C',
param: JSON.stringify({
C_ID: C_ID,
KEYWORD: $buriedpoint.val(),
KEYWORD: inputQuery,
POS_ID: 0,
FLR_INDEX: 0
})
}, true);
}
$(this).closest('form').submit();
return false;
goSearch(inputQuery);
});
// 初始化历史搜索的内容
... ...
@import "have-gain-dialog";
body {
background-color: #fff;
}
.have-gain-apply {
background-color: #f0f0f0;
... ... @@ -35,10 +39,6 @@
}
}
li.border-node {
border: none;
}
.party-icon-item {
display: flex;
flex-direction: row;
... ... @@ -114,6 +114,10 @@
}
.agreement-section {
position: fixed;
bottom: 0;
left: 0;
right: 0;
margin: 30px 30px 0;
padding-bottom: 30px;
... ... @@ -149,7 +153,7 @@
height: 100px;
line-height: 100px;
background-color: #d0021b;
border-radius: 10px;
border-radius: 4px;
color: #fff;
text-align: center;
}
... ...
/* stylelint-disable */
.promo-status {
position: fixed;
bottom: 0;
width: 100%;
height: 110px;
color: white;
font-size: 32px;
text-align: center;
line-height: 110px;
}
.promo-status_submit {
background: #d0021b;
}
.promo-status_over {
background: #444;
}
.promo-desc__title {
font-size: 32px;
color: #444;
margin-top: 40px;
margin-bottom: 20px;
}
.promo-desc__content {
font-size: 28px;
color: #444;
line-height: 60px;
}
... ...
... ... @@ -5,3 +5,4 @@
@import "scss/feature/swiper.min";
@import "scss/feature/shop";
@import "scss/feature/bottom";
@import "scss/feature/timed-cut";
... ...
/* stylelint-disable */
.common_floor {
&.clearfix {
*zoom: 1;
&:before,
&:after {
content: "";
display: table;
}
&:after {
clear: both;
}
}
.single-item3:nth-of-type(3n+1) {
margin-left: 20px;
}
}
/* stylelint-enable */
.product-container {
overflow: hidden;
padding: 0 20px 10px;
font-size: 22px;
&.single-item3,
&.item3 {
padding: 0 20px 10px;
font-size: 20px;
.product-source {
width: calc(100% + 10px);
}
.feature-product-info {
width: 193px;
margin-right: 10px;
... ... @@ -70,6 +97,15 @@
}
}
&.single-item3 {
padding: 0;
float: left;
.feature-product-info {
margin: 16px 10px 16px 0;
}
}
.product-source {
display: block;
overflow: hidden;
... ... @@ -315,3 +351,105 @@
}
}
}
.side-swiper-goods-wrap {
color: #444;
-webkit-overflow-scrolling: touch;
overflow: hidden;
&:after {
content: "";
display: block;
margin-top: -70px;
}
ul {
padding: 25px 0 100px 26px;
white-space: nowrap;
}
.side-swiper-content {
overflow-x: auto;
}
.side-swiper-item {
display: inline-block;
width: 153px;
margin-right: 26px;
border-radius: 5px;
vertical-align: top;
a {
text-decoration: none;
color: #444;
}
.img-box {
height: 206px;
position: relative;
}
.goods-pic {
height: 100%;
width: 100%;
display: block;
}
.leftopimg,
.rigtopimg {
height: auto;
position: absolute;
top: 0;
width: 100%;
z-index: 1;
}
.leftopimg {
left: 0;
}
.rigtopimg {
right: 0;
}
.pro-price {
text-align: center;
color: #444;
padding: 6px;
font-size: 26px;
> span {
display: inline-block;
}
}
.market-price {
color: #bebebe;
margin-left: 6px;
font-size: 20px;
text-decoration: line-through;
}
.product-name,
.brand-name {
font-size: 24px;
line-height: 40px;
text-align: center;
display: block;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
color: #444;
}
.join-num {
font-size: 22px;
color: #bebebe;
text-align: center;
display: block;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
}
... ...
... ... @@ -108,6 +108,20 @@ $shop-width-3: 187px;
}
}
.single-item3 {
float: left;
width: 203px;
.shop-container .feature-shop-info {
margin: 16px 10px 16px 0;
> image {
width: 100%;
height: 100%;
}
}
}
/*
个性化店铺组与原有店铺组样式几乎完全不一样
*/
... ...
.timed-cut-container {
width: 100%;
height: 390px;
background-size: 100% 100%;
position: relative;
> a {
color: #444;
display: block;
width: 100%;
height: 100%;
}
.act-time {
font-size: 20px;
transform: scale(0.8, 0.8);
transform-origin: 0% 0%;
line-height: 1.3;
position: absolute;
top: 29%;
left: 11.6%;
}
.now-price {
font-size: 38px;
font-weight: bold;
font-style: italic;
position: absolute;
top: 46%;
left: 25%;
}
.limit-time {
width: 44%;
line-height: 85px;
font-weight: bold;
color: #fff;
text-align: center;
position: absolute;
bottom: 3%;
left: 8.4%;
> p {
display: inline-block;
width: 100%;
line-height: 1.4;
vertical-align: middle;
}
}
.opt-btn {
width: 85px;
height: 85px;
position: absolute;
bottom: 3%;
right: 8.1%;
background-size: 100% 100%;
}
.btn-status1 {
background-image: url("img/activity/feature/timed-cut-btn1.png");
}
.btn-status2 {
background-image: url("img/activity/feature/timed-cut-btn2.png");
}
.btn-status3 {
background-image: url("img/activity/feature/timed-cut-btn3.png");
}
.btn-status4 {
background-image: url("img/activity/feature/timed-cut-btn4.png");
}
}
... ...
... ... @@ -132,3 +132,4 @@ self.workbox.routing.registerRoute(args => {
})
]}).handle(args);
});
... ...
This diff could not be displayed because it is too large.