Authored by 陈峰

merge couponcneter

... ... @@ -13,7 +13,7 @@ const bodyParser = require('body-parser');
const cookieParser = require('cookie-parser');
const favicon = require('serve-favicon');
const yohoLib = require('yoho-node-lib');
const session = require('express-session');
const session = require('yoho-express-session');
const memcached = require('connect-memcached');
const hbs = require('express-handlebars');
const pkg = require('./package.json');
... ... @@ -68,7 +68,9 @@ app.use(session({
},
store: new MemcachedStore({
hosts: config.memcache.session,
prefix: 'yohobuy_session:'
prefix: 'yohobuy_session:',
timeout: 1000,
retries: 0
})
}));
... ...
// 领券中心 by acgpiano 16-9-19
'use strict';
const model = require('../models/coupon-floor'),
headerModel = require('../../../doraemon/models/header');
exports.index = (req, res, next) => {
let uid = '';
if (req.yoho.isApp) {
uid = req.query.uid;
} else {
uid = req.user.uid;
}
model.floor({
uid: uid,
contentCode: req.query.code
}, req.yoho.isApp).then(result => {
res.render('coupon-floor', {
module: 'activity',
page: 'coupon-floor',
wechatShare: true,
title: '领券中心',
pageHeader: headerModel.setNav({
navTitle: '领券中心'
}),
content: result,
});
}).catch(next);
};
exports.receive = (req, res, next) => {
let receiveData = {
couponID: req.query.couponID,
code: req.query.code,
app_version: req.query.app_version,
};
let uid = '';
if (req.yoho.isApp) {
uid = req.query.uid;
} else {
uid = req.user.uid;
}
model.receiveCoupon(receiveData, req.yoho.isApp, uid).then(result => {
res.json(result);
}).catch(next);
};
... ...
// 领券中心 by acgpiano 16-9-19
'use strict';
const Promise = require('bluebird');
const api = global.yoho.API;
const _ = require('lodash');
const helpers = global.yoho.helpers;
const crypto = global.yoho.crypto;
const SUB_DOMAIN = '.dev.yohobuy.com',
OLD_MAIN = '//m.yohobuy.com',
SITE_MAIN = '//m.dev.yohobuy.com';
/**
* 仿php的strrpos
*/
const strrpos = (str1, str2) => {
return str1.indexOf(str2) > -1 ? str1.indexOf(str2) : false;
};
/**
* 仿php的strstr
*/
const strstr = (str1, str2, bfsearch) => {
if (str1.indexOf(str2) > -1) {
if (bfsearch) {
return str1.substring(0, str1.indexOf(str2));
} else {
return str1.substr(str1.indexOf(str2));
}
} else {
return false;
}
};
const rtrim = (str1, str2) => {
return str1[str1.length - 1] === str2 ? str1.substr(0, str1.length - 1) : str1;
};
const transHttpsUrl = url => {
return url.replace(/^\/\//, 'http://');
};
/**
* app内的分享按钮
*/
const getShare = (code, shareTitle, shareDesc, shareImg) => {
return {
shareLink: helpers.urlFormat('/coupon/floor', { code: code }, ''),
shareTitle: shareTitle || '',
shareDesc: shareDesc || '',
shareImg: shareImg || '',
hasWxShare: true,
};
};
/**
* 过滤app的url
*/
const _getFilterUrl = url => {
url = url.replace('.m.yohobuy.com', SUB_DOMAIN).replace(OLD_MAIN, SITE_MAIN).replace('www.yohobuy.com', SITE_MAIN);
if (strrpos(url, 'm.yohobuy.com') && !strrpos(url, 'sale.m.yohobuy.com') && !strrpos(url, 'cuxiao.m.yohobuy.com') &&
!strrpos(url, 'activity.m.yohobuy.com') && !strrpos(url, 'huodong.m.yohobuy.com') &&
strrpos(url, 'cdn.yoho.cn/myohobuy') && !strrpos(url, '/home/orders/pay')) {
url = url.replace('http://', '//');
}
if (strrpos(url, 'feature.yoho.cn')) {
url = transHttpsUrl(url);
}
let filter = strstr(url, 'openby:yohobuy=', true);
if (filter) {
return rtrim(rtrim(filter, '?'), '&');
} else {
return url;
}
};
/**
* 获得的数据处理
*/
const processFun = {
carousel_banner(data) {
if (!data.list || !data.list.length) {
return [];
}
for (let item of data.list) {
item.img = helpers.image(item.src, 0, 0);
if (typeof item.url !== 'string') {
item.url = '';
}
}
data.isCarouselBanner = true;
return data;
},
getCoupon(data, isApp) {
let result = [];
if (!data.length) {
return [];
}
let floorTitle = '',
item = data[0],
imageSrc = '';
for (let key in item) {
if (key === 'floorTitle') {
floorTitle = (_.has(item[key], 'text') && (item[key].text !== '')) ? item[key].text : '';
continue;
}
if (!item.encrypt) {
item.couponID = crypto.encryption('yoho9646abcdefgh', item.couponID);
item.encrypt = true;
}
imageSrc = helpers.image(item.image.src, 0, 0);
item.image.src = imageSrc;
item.image.url = isApp ? item.image.url : _getFilterUrl(item.image.url);
switch (item.status) {
case '1':
item.isGet = true;
break;
case '2':
item.isZero = true;
break;
case '3':
item.isGeted = true;
break;
default:
break;
}
}
if (floorTitle !== '') {
data[0].floorTitle = floorTitle;
data[0].showFloorTitle = true;
}
result = data[0];
result.isCoupon = true;
return result;
},
text(data) {
data.isTitle = true;
if (data.text) {
data.isShow = true;
}
return data;
},
single_image(data, isApp) {
data[0].isSingleImage = true;
data[0].url = isApp ? data[0].url : _getFilterUrl(data[0].url);
return data[0];
},
focus(data, isApp) {
let result = {};
for (let item of data) {
item.url = isApp ? item.url : _getFilterUrl(item.url);
}
result.isFocus = true;
result.data = data;
return result;
},
image_list(data, isApp) {
let result = {},
num,
width;
for (let image of data.list) {
num = data.title.column_num;
if (num === 0) {
image.src = image.src.replace('?imageView/{mode}/w/{width}/h/{height}', '');
} else {
if (640 % num === 0) {
width = parseInt(640 / num, 10);
width = !width ? 640 : width;
image.src = image.src.replace('?imageView/{mode}/w/{width}/h/{height}', '?imageView2/2/w/' + width);
image.src = helpers.image(image.src, width, 0);
} else {
image.src = image.src.replace('?imageView/{mode}/w/{width}/h/{height}', '');
}
}
if (isApp) {
image.url = !image.url ? 'javascript:void(0);' : image.url;
} else {
image.url = !image.url ? 'javascript:void(0);' : _getFilterUrl(image.url);
}
}
result.isImageList = true;
result.imageList = {
col: data.title.column_num,
title: data.title.title,
list: data.list,
};
return result;
},
};
const _getContent = (data, isApp) => {
let result = [],
build = [];
const TEMPLATE_LIST = ['single_image', 'focus'];
if (!data) {
return [];
}
for (let i = 0, n = data.length; i < n; i++) {
let fun = '';
if (!data[i] || typeof data[i] !== 'object' || !_.has(data[i], 'template_name')) {
if (data[i].templateName) {
fun = data[i].templateName;
} else {
continue;
}
}
if (TEMPLATE_LIST.indexOf(fun) === -1) {
fun = data[i].template_name;
}
if (!data[i].data || !_.has(processFun, fun)) {
continue;
}
// tar note 处理楼层标题
if (fun === 'getCoupon' && _.has(data[i - 1], 'template_name') && data[i - 1].template_name === 'text') {
data[i].data[0].floorTitle = data[i - 1].data;
}
build = processFun[fun](data[i].data, isApp);
if (!build) {
continue;
}
result.push(build);
}
build = [];
return result;
};
exports.floor = (params, isApp) => {
return Promise.coroutine(function*() {
let result = {},
resource = yield api.get('', Object.assign(params, {
method: 'app.promotion.queryCouponCenter',
}));
if (resource && resource.code === 200) {
result = _getContent(resource.data, isApp);
} else {
result.noData = true;
}
result.share = getShare(params.contentCode, '领券中心');
return result;
})();
};
/**
* 前端ajax领券
*/
exports.receiveCoupon = (receiveData, isApp, uid) => {
let returnData = {};
// 获取优惠券 ID
if (receiveData.couponID) {
receiveData.couponID = crypto.decrypt('yoho9646abcdefgh', receiveData.couponID);
}
// 登录后调用领券接口
return api.get('', {
method: 'app.promotion.getCoupon',
couponId: receiveData.couponID,
uid: uid,
}).then(result => {
switch (result.code) {
case 200:
returnData = {
msg: '领券成功!',
status: true,
};
break;
case 401:
returnData = {
code: 401,
message: '您已领取过优惠券'
};
break;
case 315:
returnData = {
code: 315,
message: '优惠券已过期'
};
break;
default:
returnData = {
msg: '领券失败!',
status: false,
};
break;
}
return returnData;
});
};
... ...
... ... @@ -16,6 +16,8 @@ const live = require(`${cRoot}/live`);
const invite = require(`${cRoot}/invite`);
const vipDay = require(`${cRoot}/vipDay`);
const couponFloor = require(`${cRoot}/coupon-floor`);
const auth = require('../../doraemon/middleware/auth');
const market = require(`${cRoot}/market`);
// routers
... ... @@ -28,6 +30,10 @@ router.get('/coupon/verify', coupon.verify);
router.get('/wechat/share', wechat.wechatShare);
router.get('/coupon/floor', auth, couponFloor.index);
router.get('/coupon/receiveCoupon', auth, couponFloor.receive);
router.get('/student', student.getUser, student.index);
router.get('/student/register', student.isLogin, student.register);
... ...
<div class="coupon-area-page yoho-page">
{{# content}}
{{#if isSingleImage}}
<a href="{{url}}"><img src="{{image src 0 0}}" class="just-img"/></a>
{{/if}}
{{#if isCarouselBanner}}
{{> resources/banner-top}}
{{/if}}
{{#if isFocus}}
{{> resources/banner-top}}
{{/if}}
{{#if isCoupon}}
<div class="coupon-floor" coupon-id="{{couponID}}">
{{#if showFloorTitle}}
<div class="floor-title">
{{floorTitle}}
</div>
{{/if}}
<div class="floor-main" style="background-image: url({{image.src}});">
<a href="{{image.url}}" class="main-left"></a>
{{#if isGet}}
<div class="main-right-receive">
<span class="on-receive"></span>
</div>
<a href="{{image.url}}" class="main-right-use" style="display: none">
<span class="received"></span>
</a>
{{/if}}
{{#if isGeted}}
<a href="{{image.url}}" class="main-right-use">
<span class="received"></span>
</a>
{{/if}}
{{#if isZero}}
<a href="{{image.url}}" class="main-right-go">
<span class="zero"></span>
</a>
{{/if}}
</div>
</div>
{{/if}}
{{#if isImageList}}
{{> coupon/imagelist}}
{{/if}}
{{#if isNewArrival}}
{{> coupon/newarrival}}
{{/if}}
{{# share}}
<input id="shareLink" type="hidden" value="{{shareLink}}">
<input id="shareDesc" type="hidden" value="{{shareDesc}}">
<input id="shareImg" type="hidden" value="{{shareImg}}">
<input id="shareTitle" type="hidden" value="{{shareTitle}}">
{{/ share}}
{{#if noData}}
<input id="noData" type="hidden">
{{/if}}
{{/ content}}
</div>
<div class="floor-mask"></div>
<div class="floor-message">
<div class="coupon-message-content"></div>
<div class="coupon-message-op">
<span class="coupon-message-op-rel">刷新</span>
</div>
</div>
<div class="floor-tooltip">
<div class="iconfont icon-box">&#xe648;</div>
<div class="icon-msg">领取成功</div>
</div>
\ No newline at end of file
... ...
<div class="coupon-floor" coupon-id="{{couponID}}">
{{#if showFloorTitle}}
<div class="floor-title">
{{floorTitle}}
</div>
{{/if}}
<div class="floor-main" style="background-image: url({{image.src}});">
<a href="{{image.url}}" class="main-left"></a>
{{#if isGet}}
<div class="main-right-receive">
<span class="on-receive"></span>
</div>
<a href="{{image.url}}" class="main-right-use" style="display: none">
<span class="received"></span>
</a>
{{/if}}
{{#if isGeted}}
<a href="{{image.url}}" class="main-right-use">
<span class="received"></span>
</a>
{{/if}}
{{#if isZero}}
<a href="{{image.url}}" class="main-right-go">
<span class="zero"></span>
</a>
{{/if}}
</div>
</div>
\ No newline at end of file
... ...
<div class="newfestival-container">
{{# slider}}
<div class="swiper-container newfestival-block">
<div class="swiper-wrapper">
{{# imgs}}
<div class="swiper-slide">
<a href="{{url}}">
<img src="{{src}}" alt="">
</a>
</div>
{{/ imgs}}
</div>
<div class="swiper-pagination"></div>
</div>
{{/ slider}}
</div>
\ No newline at end of file
... ...
<div class="newfestival-container">
{{# imageList}}
<div class="img-list newfestival-block newfestival-recom-{{col}} clearfix">
{{# title}}
<div class="new-arrival-header">
<span class="header-text"> {{.}}</span>
</div>
{{/ title}}
{{# list}}
<div class="newfestival-recom-item">
<a href="{{url}}" class="img-wrapper">
<img class="img" src="{{src}}" alt="" style="display:block">
</a>
</div>
{{/ list}}
</div>
{{/ imageList}}
</div>
\ No newline at end of file
... ...
... ... @@ -144,7 +144,7 @@ const _article = (param) => {
sort_id: param.type === '0' ? param.type : '1',
tag: param.tag ? param.tag : null,
author_id: param.authorId ? param.authorId : null,
limit: param.limit ? param.limit : null,
limit: param.limit ? param.limit : null
}, {
cache: true,
code: 200
... ...
... ... @@ -89,7 +89,8 @@ if (isProduction) {
master: ['memcache1.yohoops.org:12111', 'memcache2.yohoops.org:12111', 'memcache3.yohoops.org:12111'],
slave: ['memcache1.yohoops.org:12112', 'memcache2.yohoops.org:12112', 'memcache3.yohoops.org:12112'],
session: ['memcache1.yohoops.org:12111', 'memcache2.yohoops.org:12111', 'memcache3.yohoops.org:12111'],
timeout: 100,
reconnect: 5000,
timeout: 1000,
retries: 0
},
useCache: true,
... ... @@ -113,6 +114,7 @@ if (isProduction) {
slave: ['127.0.0.1:12112'],
session: ['127.0.0.1:12111'],
timeout: 100,
reconnect: 5000,
retries: 0
},
useCache: true
... ...
... ... @@ -26,7 +26,6 @@
"cookie-parser": "^1.4.3",
"express": "^4.14.0",
"express-handlebars": "^3.0.0",
"express-session": "^1.14.1",
"influxdb-winston": "^1.0.1",
"lodash": "^4.16.1",
"md5": "^2.1.0",
... ... @@ -43,6 +42,7 @@
"serve-favicon": "^2.3.0",
"uuid": "^2.0.3",
"winston": "^2.2.0",
"yoho-express-session": "^1.14.1",
"winston-daily-rotate-file": "^1.3.0",
"yoho-node-lib": "0.0.49"
},
... ...
/**
* Created by Acgpiano on 2016/9/19.
*/
var $ = require('yoho-jquery'),
Swiper = require('yoho-swiper'),
$receive = $('.main-right-receive'),
$mask = $('.floor-mask'),
$message = $('.floor-message'),
$tooltip = $('.floor-tooltip'),
tip = require('../plugin/tip');
var bannerSwiper;
// 获取url中的参数
function getUrlParam(name) {
// 构造一个含有目标参数的正则表达式对象
var reg = new RegExp('(^|&)' + name + '=([^&]*)(&|$)');
// 匹配目标参数
var r = window.location.search.substr(1).match(reg);
// 返回参数值
if (r !== null) {
return r[2];
}
return null;
}
$receive.on('click', function() {
var $curDom = $(this),
req = '';
if (getUrlParam('app_version')) {
req += '&app_version=' + getUrlParam('app_version');
}
if (getUrlParam('uid')) {
req += '&uid=' + getUrlParam('uid');
}
$.ajax({
url: '//m.yohobuy.com/coupon/receiveCoupon?code=' + getUrlParam('code') + req,
data: {
couponID: $curDom.parents('.coupon-floor').attr('coupon-id')
},
dataType: 'json',
success: function(data) {
var msg = data.msg,
status = data.status,
newUrl = data.url + '?code=' + getUrlParam('code');
if (data.isApp === true) {
newUrl = data.url;
}
if (data.noLogin === true) {
if ($('#intimacy-link').length <= 0) {
$('body').append('<a href=\'' + newUrl + '\' style="display:none;" id="intimacy-link">' +
'<span class="intimacy-link"></span></a>');
}
$('.intimacy-link').click();
} else {
if (status) {
$curDom.hide();
$curDom.next().show();
$tooltip.show();
setTimeout(function() {
$tooltip.hide();
}, 3000);
} else {
$message.find('.coupon-message-content').text(msg);
$mask.show();
$message.show();
}
}
},
error: function() {
tip.show('网络异常!');
}
});
});
$('.coupon-floor a, .banner-top a').on('click', function() {
if ($(this).attr('href').length <= 0 || $(this).attr('href') === '#') {
return false;
}
});
if ($('.banner-swiper').find('li').length > 1) {
bannerSwiper = new Swiper('.banner-swiper', {
lazyLoading: true,
lazyLoadingInPrevNext: true,
loop: true,
autoplay: 3000,
autoplayDisableOnInteraction: false,
paginationClickable: true,
slideElement: 'li',
pagination: '.banner-top .pagination-inner'
});
}
$('.coupon-message-op-rel').on('click', function() {
location.reload();
});
if ($('#noData').length > 0) {
if (location.href.indexOf('?openby:yohobuy=') <= 0) {
tip.show('网络异常!');
}
}
$mask.on('click', function() {
$mask.hide();
$message.hide();
});
... ...
... ... @@ -8,7 +8,7 @@ var swiper = new Swiper('.tab .swiper-container', {
lazyLoadingInPrevNext: true,
paginationClickable: true,
loop: true,
autoplay: 3000,
autoplay: 3000
});
require('lodash/commit');
... ...
... ... @@ -320,6 +320,8 @@ function givePoint(parameter) {
case 'lifestyle':
CID = 4;
break;
default:
CID = 1;
}
parameter = $.extend({
... ...
... ... @@ -301,7 +301,7 @@ starIScroll.iScroll.on('scroll', function() {
// } else {
// $avatarClone.hide();
// }
});
});
starIScroll.iScroll.on('scrollEnd', function() {
// $loadingTip.slideUp();
... ...
... ... @@ -110,7 +110,7 @@ page = {
$.get('/passport/sms_login/token.json', {
area: area,
mobile: mobile,
mobile: mobile
})
.done(function(res) {
if (res.code === 200) {
... ...
... ... @@ -3,12 +3,11 @@
overflow: hidden;
}
.just-img {
.just-img{
width: 100%;
float: left;
margin: 0;
margin:0;
}
.coupon-floor {
float: left;
width: 100%;
... ... @@ -32,13 +31,11 @@
.main-left {
float: left;
width: 467px;
width: 450px;
height: 160px;
}
.main-right-receive,
.main-right-use,
.main-right-go {
.main-right-receive, .main-right-use, .main-right-go {
float: right;
width: 113px;
height: 160px;
... ... @@ -56,13 +53,13 @@
display: inline-block;
width: 52px;
height: 54px;
background-image: url("/channel/click-txt.png");
background-image: resolve('activity/click-txt.png');
}
&.received {
width: 113px;
height: 140px;
background-image: url("/channel/received.png");
height: 132px;
background-image: resolve('activity/received.png');
position: absolute;
top: 0;
right: 0;
... ... @@ -70,8 +67,8 @@
&.zero {
width: 111px;
height: 140px;
background-image: url("/channel/zero.png");
height: 132px;
background-image: resolve('activity/zero.png');
position: absolute;
top: 0;
right: 0;
... ... @@ -87,7 +84,7 @@
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.5);
background-color: rgba(0, 0, 0, .5);
display: none;
z-index: 9;
}
... ... @@ -101,7 +98,7 @@
margin-left: -275px;
margin-top: -125px;
z-index: 10;
background-color: rgba(250, 250, 250, 0.92);
background-color: rgba(250, 250, 250, .92);
display: none;
border-radius: 10px;
... ... @@ -122,7 +119,7 @@
}
}
.floor-tooltip {
.floor-tooltip{
position: fixed;
top: 50%;
left: 50%;
... ... @@ -131,19 +128,19 @@
margin-left: -110px;
margin-top: -70px;
z-index: 11;
background-color: rgba(60, 60, 60, 0.7);
background-color: rgba(60, 60, 60, .7);
display: none;
border-radius: 8px;
color: #fff;
.icon-box {
.icon-box{
height: 84px;
line-height: 84px;
text-align: center;
}
.icon-msg {
.icon-msg{
height: 56px;
text-align: center;
}
}
}
\ No newline at end of file
... ...
... ... @@ -297,4 +297,6 @@
}
}
@import "student";
@import "live/index";
@import "coupon-floor";
... ...
... ... @@ -20,7 +20,6 @@
@import "thumb-row";
@import "notice";
@import "fresh-only";
@import "coupon";
@import "discount-list";
@import "left-right";
@import "cate";
... ...