Authored by 郝肖肖

Merge branch 'release/5.4.1' into feature/renameCss

Showing 52 changed files with 4557 additions and 15 deletions

Too many changes to show.

To preserve performance only 52 of 52+ files are displayed.

{
"presets": ["es2015"],
"plugins": ["transform-runtime"],
"comments": false
}
... ...
... ... @@ -3,6 +3,9 @@
"parserOptions": {
"sourceType": "module"
},
"plugins": [
"html"
],
"rules": {
"max-len": [0, 50, 4],
"camelcase": "off",
... ...
... ... @@ -120,6 +120,8 @@ nbactions.xml
# sftp configuration file
sftp-config.json
### TSD ###
typings/
### Vim ###
# swap
... ...
{
"extends": "stylelint-config-yoho",
"processors": ["stylelint-processor-html"],
"rules": {
"string-quotes": "double"
}
... ...
/**
* 潮流之旅
* <jing.li@yoho.cn>
* 2016/12/19
*/
'use strict';
const headerModel = require('../../../doraemon/models/header');
const trendModel = require('../models/trend');
let responseData = {
module: 'activity',
page: 'trend',
width750: true,
localCss: true,
pageFooter: true,
};
exports.store = function(req, res, next) {
Object.assign(responseData, {
pageHeader: headerModel.setNav({
navTitle: '门店信息'
}),
title: '门店信息'
});
let params = {
storeId: req.query.storeId,
isFront: req.query.isFront || req.cookies.isFront
};
trendModel.store(params).then((result) => {
res.render('trend/store', Object.assign(responseData, result));
}).catch(next);
};
exports.articleList = function(req, res, next) {
Object.assign(responseData, {
pageHeader: headerModel.setNav({
navTitle: '活动资讯'
}),
title: '活动资讯'
});
let params = {
storeId: req.query.storeId,
isFront: req.query.isFront || req.cookies.isFront
};
trendModel.articleList(params).then((result) => {
res.render('trend/article-list', Object.assign(responseData, result));
}).catch(next);
};
exports.map = function(req, res) {
Object.assign(responseData, {
pageHeader: headerModel.setNav({
navTitle: '地图'
}),
title: '地图'
});
res.render('trend/map', responseData);
};
exports.articleDetail = function(req, res, next) {
Object.assign(responseData, {
pageHeader: headerModel.setNav({
navTitle: '活动资讯详情'
}),
title: '活动资讯详情'
});
let params = {
informationId: req.query.informationId,
isFront: req.query.isFront || req.cookies.isFront
};
trendModel.articleDetail(params).then((result) => {
res.render('trend/article-detail', Object.assign(responseData, result));
}).catch(next);
};
exports.classList = function(req, res, next) {
Object.assign(responseData, {
pageHeader: headerModel.setNav({
navTitle: '潮流课堂'
}),
title: '潮流课堂'
});
let params = {
storeId: req.query.storeId,
activityType: 1,
isFront: req.query.isFront || req.cookies.isFront
};
trendModel.classActList(params).then((result) => {
res.render('trend/class', Object.assign(responseData, result));
}).catch(next);
};
exports.activity = function(req, res, next) {
Object.assign(responseData, {
pageHeader: headerModel.setNav({
navTitle: '活动'
}),
title: '活动'
});
let params = {
storeId: req.query.storeId,
activityType: 2,
isFront: req.query.isFront || req.cookies.isFront
};
trendModel.classActList(params).then((result) => {
res.render('trend/activity', Object.assign(responseData, result));
}).catch(next);
};
exports.actDetail = function(req, res, next) {
Object.assign(responseData, {
pageHeader: headerModel.setNav({
navTitle: '活动详情'
}),
title: '活动详情'
});
let params = {
activityId: req.query.activityId,
name: req.query.name,
price: req.query.price,
startDate: req.query.startDate,
endDate: req.query.endDate,
startTime: req.query.startTime,
endTime: req.query.endTime,
status: req.query.status,
storeId: req.query.storeId,
activityType: 2,
isFront: req.query.isFront || req.cookies.isFront
};
trendModel.classActDetail(params).then((result) => {
res.render('trend/class-detail', Object.assign(responseData, result));
}).catch(next);
};
exports.classDetail = function(req, res, next) {
Object.assign(responseData, {
pageHeader: headerModel.setNav({
navTitle: '潮流课堂详情'
}),
title: '潮流课堂详情'
});
let params = {
activityId: req.query.activityId,
name: req.query.name,
price: req.query.price,
startDate: req.query.startDate,
endDate: req.query.endDate,
startTime: req.query.startTime,
endTime: req.query.endTime,
status: req.query.status,
storeId: req.query.storeId,
activityType: 1,
isFront: req.query.isFront || req.cookies.isFront
};
trendModel.classActDetail(params).then((result) => {
res.render('trend/class-detail', Object.assign(responseData, result));
}).catch(next);
};
exports.appointment = function(req, res, next) {
Object.assign(responseData, {
pageHeader: headerModel.setNav({
navTitle: '预约',
}),
title: '预约'
});
let params = {
storeId: req.query.storeId,
activityType: req.query.typeStatus,
uid: req.user.uid,
isFront: req.query.isFront || req.cookies.isFront
};
trendModel.appointment(params).then((result) => {
res.render('trend/appointment', Object.assign(responseData, result));
}).catch(next);
};
exports.travel = function(req, res, next) {
Object.assign(responseData, {
pageHeader: headerModel.setNav({
navTitle: '潮流之旅'
}),
title: '潮流之旅'
});
let params = {
id: req.query.id,
storeId: req.query.storeId,
activityType: 3,
isFront: req.query.isFront || req.cookies.isFront,
};
trendModel.travel(params).then((result) => {
res.cookie('travelId', result.travelId, {
domain: 'yohobuy.com',
path: '/'
});
res.render('trend/travel', Object.assign(responseData, result));
}).catch(next);
};
exports.adviser = function(req, res, next) {
Object.assign(responseData, {
pageHeader: headerModel.setNav({
navTitle: '潮流顾问'
}),
title: '潮流顾问'
});
let params = {
id: req.query.id,
activityId: req.query.id,
activityType: 3,
storeId: req.query.storeId,
isFront: req.query.isFront || req.cookies.isFront
};
trendModel.adviser(params).then((result) => {
res.render('trend/adviser', Object.assign(responseData, result));
}).catch(next);
};
exports.kids = function(req, res, next) {
Object.assign(responseData, {
pageHeader: headerModel.setNav({
navTitle: '潮童造型'
}),
title: '潮童造型'
});
let params = {
storeId: req.query.storeId,
id: req.query.id,
isFront: req.query.isFront || req.cookies.isFront
};
trendModel.kids(params).then((result) => {
res.render('trend/kids', Object.assign(responseData, result));
}).catch(next);
};
exports.photography = function(req, res, next) {
Object.assign(responseData, {
pageHeader: headerModel.setNav({
navTitle: '儿童摄影'
}),
title: '儿童摄影'
});
let params = {
storeId: req.query.storeId,
id: req.query.id,
activityType: 4,
isFront: req.query.isFront || req.cookies.isFront
};
trendModel.photography(params).then((result) => {
res.render('trend/photography', Object.assign(responseData, result));
}).catch(next);
};
exports.kidStyle = function(req, res, next) {
Object.assign(responseData, {
pageHeader: headerModel.setNav({
navTitle: '儿童造型'
}),
title: '儿童造型'
});
let params = {
storeId: req.query.storeId,
id: req.query.id,
activityType: 5,
isFront: req.query.isFront || req.cookies.isFront
};
trendModel.kidStyle(params).then((result) => {
res.render('trend/kidStyle', Object.assign(responseData, result));
}).catch(next);
};
exports.styleDetail = function(req, res, next) {
Object.assign(responseData, {
pageHeader: headerModel.setNav({
navTitle: req.query.styleName
}),
title: req.query.styleName
});
let params = {
storeId: req.query.storeId,
styleId: req.query.id,
isFront: req.query.isFront || req.cookies.isFront
};
trendModel.styleDetail(params).then((result) => {
res.render('trend/style-detail', Object.assign(responseData, result));
}).catch(next);
};
exports.packageDetail = function(req, res, next) {
Object.assign(responseData, {
pageHeader: headerModel.setNav({
navTitle: '套餐详情'
}),
title: '套餐详情'
});
let params = {
id: req.query.id,
isFront: req.query.isFront || req.cookies.isFront
};
trendModel.packageDetail(params).then((result) => {
res.render('trend/package-detail', Object.assign(responseData, result));
}).catch(next);
};
exports.cutter = function(req, res, next) {
Object.assign(responseData, {
pageHeader: headerModel.setNav({
navTitle: req.query.cutterName
}),
title: req.query.cutterName
});
let params = {
storeId: req.query.storeId,
activityType: 5,
id: req.query.id,
activityId: req.query.id,
isFront: req.query.isFront || req.cookies.isFront
};
trendModel.cutter(params).then((result) => {
res.render('trend/cutter', Object.assign(responseData, result));
}).catch(next);
};
exports.orderList = function(req, res, next) {
Object.assign(responseData, {
pageHeader: headerModel.setNav({
navTitle: '我的预约'
}),
title: '我的预约'
});
let params = {
storeId: req.query.storeId,
uid: req.user.uid,
isFront: req.query.isFront || req.cookies.isFront
};
trendModel.orderList(params).then((result) => {
res.render('trend/order-list', Object.assign(responseData, result));
}).catch(next);
};
exports.orderDetail = function(req, res, next) {
Object.assign(responseData, {
pageHeader: headerModel.setNav({
navTitle: '预约详情'
}),
title: '预约详情'
});
let params = {
storeId: req.query.storeId,
uid: req.user.uid,
id: req.query.id,
showBtn: req.query.showBtn || '',
isFront: req.query.isFront || req.cookies.isFront
};
trendModel.orderDetail(params).then((result) => {
res.render('trend/order-detail', Object.assign(responseData, result));
}).catch(next);
};
// 选择页面
exports.chosenPackage = function(req, res, next) {
Object.assign(responseData, {
pageHeader: headerModel.setNav({
navTitle: '选择套餐'
}),
title: '选择套餐'
});
let params = {
storeId: req.query.storeId,
activityType: req.query.typeStatus,
isFront: req.query.isFront || req.cookies.isFront
};
trendModel.chosenPackage(params).then((result) => {
res.render('trend/chosen-package', Object.assign(responseData, result));
}).catch(next);
};
exports.chosenStyle = function(req, res, next) {
Object.assign(responseData, {
pageHeader: headerModel.setNav({
navTitle: '选择风格'
}),
title: '选择风格'
});
let params = {
storeId: req.query.storeId,
isFront: req.query.isFront || req.cookies.isFront
};
trendModel.chosenStyle(params).then((result) => {
res.render('trend/chosen-style', Object.assign(responseData, result));
}).catch(next);
};
exports.chosenTime = function(req, res, next) {
Object.assign(responseData, {
pageHeader: headerModel.setNav({
navTitle: '选择时间'
}),
title: '选择时间'
});
let params = {
activityType: req.query.typeStatus,
activityId: req.cookies.packageId || req.query.activityId || req.cookies.adviserId,
travelId: req.cookies.travelId,
isFront: req.query.isFront || req.cookies.isFront
};
trendModel.chosenTime(params).then((result) => {
res.render('trend/chosen-time', Object.assign(responseData, result));
}).catch(next);
};
exports.chosenCutter = function(req, res, next) {
Object.assign(responseData, {
pageHeader: headerModel.setNav({
navTitle: '选择发型师'
}),
title: '选择发型师'
});
let params = {
storeId: req.query.storeId,
isFront: req.query.isFront || req.cookies.isFront
};
trendModel.chosenCutter(params).then((result) => {
res.render('trend/chosen-cutter', Object.assign(responseData, result));
}).catch(next);
};
exports.chosenAdviser = function(req, res, next) {
Object.assign(responseData, {
pageHeader: headerModel.setNav({
navTitle: '潮流顾问'
}),
title: '潮流顾问'
});
let params = {
storeId: req.query.storeId,
activityType: req.query.typeStatus,
isFront: req.query.isFront || req.cookies.isFront,
hairStylistId: req.cookies.travelId
};
trendModel.chosenAdviser(params).then((result) => {
res.render('trend/chosen-adviser', Object.assign(responseData, result));
}).catch(next);
};
exports.getTimeList = function(req, res, next) {
Object.assign(responseData, {
pageHeader: headerModel.setNav({
navTitle: '选择时间'
}),
title: '选择时间'
});
let params = {
storeId: req.query.storeId,
dateTime: req.query.dateTime,
appointType: req.query.appointType,
activityId: req.cookies.packageId || req.query.activityId || req.cookies.adviserId,
travelId: req.cookies.travelId,
isFront: req.query.isFront || req.cookies.isFront,
userId: req.query.userId
};
trendModel.getTimeList(params).then((result) => {
res.json(result);
}).catch(next);
};
exports.addOrder = function(req, res, next) {
let params = {
storeId: req.query.storeId,
appointTime: req.query.appointTime,
appointUserName: req.query.appointUserName,
appointMobile: req.query.appointMobile,
uid: req.query.uid,
activityId: req.query.activityId,
appointContent: req.query.appointContent,
userNote: req.query.userNote,
appointPersonNum: req.query.appointPersonNum,
styles: req.query.styles,
isFront: req.query.isFront || req.cookies.isFront
};
trendModel.addOrder(params).then((result) => {
res.json(result);
}).catch(next);
};
exports.delOrder = function(req, res, next) {
let params = {
id: req.query.id,
isFront: req.query.isFront || req.cookies.isFront
};
trendModel.delOrder(params).then((result) => {
res.json(result);
}).catch(next);
};
exports.needKnow = function(req, res) {
Object.assign(responseData, {
pageHeader: headerModel.setNav({
navTitle: '预约须知'
}),
title: '预约须知'
});
res.render('trend/need-know', responseData);
};
exports.success = function(req, res) {
Object.assign(responseData, {
pageHeader: headerModel.setNav({
navTitle: '预约成功'
}),
title: '预约成功'
});
res.render('trend/success', Object.assign(responseData, {storeId: req.query.storeId}));
};
exports.changeDate = function(req, res, next) {
let params = {
id: req.query.id,
appointTimeStr: req.query.appointTimeStr,
isFront: req.query.isFront || req.cookies.isFront
};
trendModel.changeDate(params).then((result) => {
res.json(result);
}).catch(next);
};
exports.getAbleTime = function(req, res, next) {
let params = {
activityType: req.query.activityType,
activityId: req.query.activityId,
isFront: req.query.isFront || req.cookies.isFront
};
trendModel.getAbleTime(params).then((result) => {
res.json(result);
}).catch(next);
};
\ No newline at end of file
... ...
/**
* 潮流之旅
* <jing.li@yoho.cn>
* 2017/1/3
*/
'use strict';
const service = global.yoho.ServiceAPI;
const moment = require('moment');
const helpers = global.yoho.helpers;
// 格式年月日
const _formatDay = (day) => {
return moment(day, 'YYYY/MM/DD').format('YYYY年MM月DD日');
};
// 格式年月日
const _originDay = (day) => {
return moment(day, 'YYYY年MM月DD日 HH:mm').format('YYYY/MM/DD HH:mm');
};
// 所有时间
const _MYDHm = (day) => {
return moment(day, 'YYYY/MM/DD').format('YYYY年MM月DD日 HH:mm');
};
// 月日时分
const _MDHm = (day) => {
return moment(day, 'YYYY/MM/DD').format('MM月DD日 HH:mm');
};
// 格式年月日2
const _formatDay2 = (day) => {
return moment(day, 'YYYY/MM/DD').format('YY年MM月DD日');
};
// 只要月日
const _MD = (day) => {
return moment(day, 'YYYY/MM/DD').format('MM月DD日');
};
// 只要月日
const _D = (day) => {
return moment(day, 'YYYY/MM/DD').format('DD日');
};
// 只要时分
const _HM = (day) => {
return moment(day, 'YYYY/MM/DD').format('HH:mm');
};
// 资讯列表
const info = (params) => {
return service.get('InformationController/getFrontAllList', {
storeId: params.storeId,
isFront: params.isFront
}, {
cache: true,
code: 200
});
};
// 店铺信息
const storeInfo = (params) => {
return service.get('StoreController/getStoreInfoExtById', {
storeId: params.storeId,
isFront: params.isFront
}, {
cache: true,
code: 200
});
};
// 店铺可预约项目
const storeSon = (params) => {
return service.get('MenuConfigController/getChildrenNodeById', {
storeId: params.storeId,
id: 0,
isFront: params.isFront
}, {
cache: true,
code: 200
});
};
// 店铺
const store = (params) => {
return Promise.all([
info(params),
storeInfo(params),
storeSon(params)
]).then(result => {
let resu = {
infos: [],
detail: {},
storeSon: []
};
if (result) {
if (result[0] && result[0].data) {
resu.infos = result[0].data;
}
if (result[1] && result[1].data) {
resu.detail = result[1].data;
}
if (result[2] && result[2].data) {
let build = [];
result[2].data.forEach(val => {
build.push({
img: val.thumbnailUrl,
href: val.url
});
});
resu.storeSon = build;
}
}
return resu;
});
};
// 文章详情
const articleDetail = (params) => {
return service.get('InformationController/getFrontContentById', {
informationId: params.informationId,
isFront: params.isFront
}, {
cache: true,
code: 200
}).then(result => {
let resu = {};
if (result && result.data) {
resu = result.data;
}
return resu;
});
};
// 店铺文章列表
const articleList = (params) => {
return service.get('InformationController/getFrontAllList', {
storeId: params.storeId,
isFront: params.isFront
}, {
cache: true,
code: 200
}).then(result => {
let resu = {
infos: []
};
if (result && result.data) {
resu.infos = result.data;
}
return resu;
});
};
// 文章详情
const useList = (params) => {
return service.get('ActivityConfigController/getActivityNowList', {
storeId: params.storeId,
activityType: params.activityType,
isFront: params.isFront
}, {
cache: true,
code: 200
}).then(result => {
return result;
});
};
// 文章详情-过期
const oldList = (params) => {
return service.get('ActivityConfigController/getActivityEndList', {
storeId: params.storeId,
activityType: params.activityType,
isFront: params.isFront
}, {
cache: true,
code: 200
}).then(result => {
let resu = [];
if (result && result.data) {
resu = result.data;
}
return resu;
});
};
// 潮流课堂,活动列表
const classActList = (params) => {
return Promise.all([
useList(params),
oldList(params)
]).then(result => {
let resu = {
list: [],
oldList: []
};
if (result && result[0] && result[0].data) {
let build = [];
result[0].data.forEach(val => {
let endDate = '';
let status = 0;// 0:已过期 ,1:可预约,2:已约满,3:免预约
if (val.isAppointment === 0) {
status = 3;
} else {
if (val.appointStatus === 1) {
status = 1;
} else {
status = 2;
}
}
if (val.activityStartDate.split('/')[0] === val.activityEndDate.split('/')[0]) {
endDate = _MD(val.activityEndDate);
if (val.activityStartDate.split('/')[1] === val.activityEndDate.split('/')[1]) {
endDate = _D(val.activityEndDate);
}
} else {
endDate = _formatDay2(val.activityEndDate);
}
build.push({
name: val.activityName,
image: val.image.split(',')[0],
startDate: _formatDay(val.activityStartDate),
endDate: endDate,
startTime: val.activityDayStartTime,
endTime: val.activityDayEndTime,
free: val.isFree === 1,
price: helpers.round(val.price, 0),
needApo: val.isAppointment === 1,
apoStatus: val.appointStatus === 1,
id: val.id,
status: status,
storeId: params.storeId
});
});
resu.list = build;
}
if (result && result[1]) {
let build = [];
let status = 0;
result[1].forEach(val => {
let endDate = '';
if (val.activityStartDate.split('/')[0] === val.activityEndDate.split('/')[0]) {
endDate = _MD(val.activityEndDate);
if (val.activityStartDate.split('/')[1] === val.activityEndDate.split('/')[1]) {
endDate = _D(val.activityEndDate);
}
} else {
endDate = _formatDay2(val.activityEndDate);
}
build.push({
name: val.activityName,
image: val.image.split(',')[0],
startDate: _formatDay(val.activityStartDate),
endDate: endDate,
startTime: val.activityDayStartTime,
endTime: val.activityDayEndTime,
end: true,
free: true,
id: val.id,
status: status,
storeId: params.storeId
});
});
resu.oldList = build;
}
return resu;
});
};
// 潮流课堂,活动详情
const classActDetail = (params) => {
return service.get('ActivityConfigController/getFrontDetailById', {
activityId: params.activityId,
isFront: params.isFront
}, {
cache: true,
code: 200
}).then(result => {
let resu = {};
if (result && result.data) {
resu = {
content: result.data.detail,
name: params.name,
price: params.price,
startDate: params.startDate,
endDate: params.endDate,
startTime: params.startTime,
endTime: params.endTime,
status: params.status || '0',
storeId: params.storeId,
activityType: params.activityType,
id: params.activityId,
};
}
return resu;
});
};
// 潮流之旅详情
const travelDetail = (params) => {
return service.get('MenuConfigController/getFrontMainTour', {
storeId: params.storeId,
isFront: params.isFront
}, {
cache: true,
code: 200
}).then(result => {
let resu = '';
Object.assign(params, {hairStylistId: result.data.id});
return Promise.all([
adviserList(params),
getDate2(params)
]).then(newResult => {
resu = Object.assign(result.data, {advisersList: newResult[0].data});
resu = Object.assign(result.data, {dateList: newResult[1].data});
return resu;
});
});
};
// 潮流顾问,发型师套餐列表
const adviserList = (params) => {
return service.get('ActivityConfigController/getActivityList', {
storeId: params.storeId,
activityType: params.activityType,
id: params.id || '',
hairStylistId: 8 || '',
isFront: params.isFront
}, {
cache: true,
code: 200
}).then(result => {
return result;
});
};
// 潮流之旅
const travel = (params) => {
return Promise.all([
travelDetail(params)
]).then(result => {
let resu = {
content: '',
adviser: [],
dateList: [],
storeId: params.storeId,
travelId: ''
};
if (result && result[0]) {
resu.travelId = result[0].id;
resu.content = result[0].tourDetail;
let build = [];
result[0].advisersList.forEach(val => {
build.push({
name: val.activityName,
summary: val.summary,
image: val.image,
id: val.id,
typeStatus: params.activityType,
storeId: params.storeId
});
});
resu.adviser = build;
let build2 = [];
for(let item in result[0].dateList){
build2.push({
date: _MD(item),
week: result[0].dateList[item],
dateOrigin: item,
dateParse: Date.parse(item) / 1000
});
}
resu.dateList = build2;
}
return resu;
});
};
// 潮流顾问,摄影,发型师,套餐详情
const adviserDetail = (params) => {
return service.get('ActivityConfigController/getFrontActivityInfoById', {
activityId: params.id,
isFront: params.isFront
}, {
cache: true,
code: 200
}).then(result => {
return result;
});
};
// 潮流顾问详情
const adviser = (params) => {
return Promise.all([
adviserDetail(params),
getDate(params)
]).then(result => {
let resu = {
detail: {},
content: {},
dateList: [],
};
if (result && result[0] && result[0].data) {
resu.detail = {
name: result[0].data.activityName,
summary: result[0].data.summary,
image: result[0].data.image,
};
resu.content = result[0].data.detail;
}
let build = [];
if (result && result[1] && result[1].data) {
for(let item in result[1].data){
build.push({
date: _MD(item),
week: result[1].data[item],
dateOrigin: item,
dateParse: Date.parse(item) / 1000
});
}
resu.dateList = build;
}
return resu;
});
};
// 摄影详情
const photographyDetail = (params) => {
return service.get('MenuConfigController/getFrontMenuById', {
id: params.id,
isFront: params.isFront
}, {
cache: true,
code: 200
}).then(result => {
return result;
});
};
// 获取风格
const getStyle = (params) => {
return service.get('MenuConfigController/getFrontMenuPhotoStyle', {
storeId: params.storeId,
id: params.styleId || '',
isFront: params.isFront
}, {
cache: true,
code: 200
}).then(result => {
return result;
});
};
// 获取日期,星期
const getDate = (params) => {
if (!params.activityId) {
params.activityId = params.travelId;
params.activityType = 6;
}
return service.get('ActivityConfigController/getAppointInfoById', {
activityId: params.activityId,
activityType: params.activityType,
isFront: params.isFront
}, {
cache: true,
code: 200
}).then(result => {
return result;
});
};
// 获取日期,星期(所有潮流顾问, 发型师详情页)
const getDate2 = (params) => {
return service.get('ActivityConfigController/getAppointDateForTour', {
storeId: params.storeId,
activityType: params.activityType,
hairStylistId: params.id || '',
isFront: params.isFront
}, {
cache: true,
code: 200
}).then(result => {
return result;
});
};
// 获取风格热推
const getStylePush = (params) => {
return service.get('MenuConfigController/getFrontMenuPhotoStyle', {
storeId: params.storeId,
isPush: 1,
isFront: params.isFront
}, {
cache: true,
code: 200
}).then(result => {
return result;
});
};
// 获取时间列表
const getTimeList = (params) => {
if (!params.activityId) {
params.activityId = params.travelId;
params.appointType = 6;
}
let ajaxUrl = '';
if (params.userId) {
ajaxUrl = 'ActivityConfigController/getAppointTimeForTour';
} else {
ajaxUrl = 'AppointmentController/getAppointTime';
}
return service.get(ajaxUrl, {
storeId: params.storeId,
activityId: params.activityId,
appointType: params.appointType,
activityType: params.appointType,
hairStylistId: params.userId,
dateTime: params.dateTime,
isFront: params.isFront,
}, {
cache: true,
code: 200
}).then(result => {
let resu = {
getTimeList: [],
appointNum: 0
};
let build = [];
if (result && result.data && result.data.timeMap) {
for(let item in result.data.timeMap){
build.push({
time: _HM(new Date(item * 1000)),
originTime: item,
use: result.data.timeMap[item],
date2: _MDHm(new Date(item * 1000)),
date: _MYDHm(new Date(item * 1000)),
});
}
resu.appointNum = result.data.appointNum;
resu.getTimeList = build;
}
return resu;
});
};
// 摄影
const photography = (params) => {
return Promise.all([
photographyDetail(params),
getStyle(params),
adviserList(params),
getStylePush(params),
]).then(result => {
let resu = {
content: '',
detail: {},
styleList: [],
packageList: [],
swiper: [],
storeId: params.storeId
};
if (result) {
if (result[0] && result[0].data) {
resu.detail = {
bigPic: result[0].data.mainPushUrl
};
resu.content = result[0].data.detail;
}
if (result[1] && result[1].data) {
let build = [];
result[1].data.forEach(val => {
build.push({
img: val.styleImage,
id: val.id,
name: val.styleName
});
});
resu.styleList = build;
}
if (result[2] && result[2].data) {
let build = [];
result[2].data.forEach(val => {
build.push({
name: val.activityName,
free: val.isFree === 1,
price: val.price,
summary: val.summary,
id: val.id
});
});
resu.packageList = build;
}
if (result[3] && result[3].data) {
let build = [];
result[3].data.forEach(val => {
build.push({
pic: val.styleImage,
name: val.styleName,
introduction: val.introduction,
id: val.id,
storeId: params.storeId
});
});
resu.swiper = build;
}
}
return resu;
});
};
// 套餐详情
const packageDetail = (params) => {
return Promise.all([
adviserDetail(params)
]).then(result => {
let resu = {
detail: {},
content: {},
isAppointment: false
};
if (result && result[0] && result[0].data) {
resu.detail = {
name: result[0].data.activityName,
summary: result[0].data.summary,
free: result[0].data.isFree === 1,
price: result[0].data.price,
img: result[0].data.image,
limit: result[0].data.styleNumber,
styleId: result[0].data.styleList
};
resu.isAppointment = result[0].data.isAppointment === 1;
resu.content = result[0].data.detail;
}
return resu;
});
};
// 风格详情
const styleDetail = (params) => {
return Promise.all([
getStyle(params)
]).then(result => {
let resu = {
introduction: '',
picList: []
};
let bulid = [];
if (result && result[0] && result[0].data && result[0].data[0]) {
resu.introduction = result[0].data[0].introduction;
resu.picList = result[0].data[0].styleDemo.split(',');
resu.picList.forEach(val => {
bulid.push({
imgSrc: val
});
});
resu.picList = bulid;
}
return resu;
});
};
// 预约
const appointment = (params) => {
return Promise.all([
storeInfo(params)
]).then(result => {
let resu = {
storeInfo: {},
storeId: params.storeId,
typeStatus: params.activityType,
uid: params.uid,
cutterChosen: params.activityType === '5',
styleChosen: params.activityType === '4',
adviserChosen: params.activityType === '3',
packageChosen: params.activityType === '4' || params.activityType === '5',
sexInp: params.activityType === '4' || params.activityType === '5',
ageInp: params.activityType === '4' || params.activityType === '5',
babyName: params.activityType === '4' || params.activityType === '5',
classChosen: params.activityType === '1',
actChosen: params.activityType === '2',
hideChosen: params.activityType === '3' ? false : true,
};
if (result && result[0] && result[0].data) {
resu.storeInfo = {
name: result[0].data.storeName,
adr: result[0].data.address,
telephone: result[0].data.telephone,
};
}
return resu;
});
};
// 选择套餐
const chosenPackage = (params) => {
return Promise.all([
adviserList(params)
]).then(result => {
let resu = {
packageChosen: []
};
if (result && result[0] && result[0].data) {
let build = [];
result[0].data.forEach(val => {
build.push({
name: val.activityName,
summary: val.summary,
free: val.isFree === 1,
price: val.price,
id: val.id,
foot: true,
limit: val.styleNumber,
styleId: val.styleList
});
resu.packageChosen = build;
});
}
return resu;
});
};
// 选择风格
const chosenStyle = (params) => {
return Promise.all([
getStyle(params)
]).then(result => {
let resu = {
styleList: [],
};
if (result && result[0] && result[0].data) {
let build = [];
result[0].data.forEach(val => {
build.push({
name: val.styleName,
id: val.id
});
resu.styleList = build;
});
}
return resu;
});
};
// 选择时间
const chosenTime = (params) => {
return Promise.all([
getDate(params)
]).then(result => {
let resu = {
dateList: [],
needAdv: params.activityType === '3',
hide: params.activityType === '1',
};
let build = [];
if (result && result[0] && result[0].data) {
for(let item in result[0].data){
build.push({
date: _MD(item),
week: result[0].data[item],
dateOrigin: item,
dateParse: Date.parse(item) / 1000
});
}
resu.dateList = build;
}
return resu;
});
};
// 选择发型师
const chosenCutter = (params) => {
return Promise.all([
cutterList(params),
]).then(result => {
let resu = {};
if (result[0] && result[0].data) {
let build = [];
result[0].data.forEach(val => {
build.push({
name: val.stylistName,
level: val.stylistLevelStr,
price: val.minPrice,
img: val.stylistPhoto,
radio: true,
arr: false,
free: val.minPrice === -1,
noPackage: val.minPrice === null
});
});
resu.cutterList = build;
}
return resu;
});
};
// 选择潮流顾问
const chosenAdviser = (params) => {
return Promise.all([
adviserList(params),
]).then(result => {
let resu = {
adviser: []
};
if (result && result[0] && result[0].data) {
let build = [];
result[0].data.forEach(val => {
build.push({
name: val.consultantName,
summary: val.summary,
image: val.image,
id: val.id
});
});
resu.adviser = build;
}
return resu;
});
};
// 提交预约
const addOrder = (params) => {
return service.get('AppointmentController/addAppointmentRecord', {
storeId: params.storeId,
appointTime: params.appointTime,
appointUserName: params.appointUserName,
appointMobile: params.appointMobile,
uid: params.uid,
activityId: params.activityId,
appointContent: params.appointContent,
userNote: params.userNote,
appointPersonNum: params.appointPersonNum,
styles: params.styles,
appointStatus: 1,
isFront: params.isFront
}).then(result => {
return result;
});
};
// 我的预约列表,详情
const orderList1 = (params) => {
return service.get('AppointmentController/getMyAppointmentList', {
storeId: params.storeId,
uid: params.uid,
statusList: params.statusList,
id: params.id || ''
}).then(result => {
return result;
});
};
// 我的预约
const orderList = (params) => {
let params1 = params;
let params2 = params;
return Promise.all([
orderList1(Object.assign(params1, {statusList: '1,2'})),
orderList1(Object.assign(params2, {statusList: '3,4'}))
]).then(result => {
let resu = {
list1: [],
list2: [],
noOrder: false
};
if (result) {
if (result[0] && result[0].data) {
console.log(result[0].data);
let build = [];
result[0].data.forEach(val => {
build.push({
name: val.activityName,
status: val.appointStatusStr,
createTime: _MYDHm(new Date(val.appointTime * 1000)),
originTime: val.appointTime,
id: val.id,
storeId: params.storeId,
typeStatus: val.activityType,
activityId: val.activityId
});
});
resu.list1 = build;
}
if (result[1] && result[1].data) {
let build = [];
result[1].data.forEach(val => {
build.push({
name: val.activityName,
status: val.appointStatusStr,
createTime: _MYDHm(new Date(val.appointTime * 1000)),
originTime: val.appointTime,
id: val.id,
storeId: params.storeId
});
});
resu.list2 = build;
}
if (!result[0].data && !result[1].data) {
resu.noOrder = true;
}
}
return resu;
});
};
// 我的预约
const orderDetail = (params) => {
return Promise.all([
orderList1(params),
storeInfo(params)
]).then(result => {
let resu = {
storeInfo: {},
userInfo: {},
storeId: params.storeId,
id: params.id
};
if (result) {
if (result[1] && result[1].data) {
resu.storeInfo = {
name: result[1].data.storeName,
adr: result[1].data.address,
telephone: result[1].data.telephone,
storeId: result[1].data.storeId,
longitude: result[1].data.longitude,
latitude: result[1].data.latitude,
storeName: result[1].data.storeName,
address: result[1].data.address,
telephone: result[1].data.telephone,
introduction: result[1].data.introduction,
pictureUrl: result[1].data.pictureUrl
};
}
if (result[0] && result[0].data) {
let appointContent = JSON.parse(result[0].data[0].appointContent);
resu.userInfo = {
babyName: appointContent.name,
babyAge: appointContent.age === 'NaN' ? '' : appointContent.age,
babySex: appointContent.sex === 'undefined' ? '' : appointContent.sex,
userNote: result[0].data[0].userNote,
appointMobile: result[0].data[0].appointMobile,
appointTime: _MYDHm(new Date(result[0].data[0].appointTime * 1000)),
originTime: result[0].data[0].appointTime,
storeId: params.storeId,
activityId: result[0].data[0].activityId,
stylesName: result[0].data[0].stylesName,
typeStatus: result[0].data[0].activityType,
status: result[0].data[0].appointStatusStr,
id: result[0].data[0].id,
showBtn: params.showBtn === 'true',
originUrl: result[0].data[0].url,
personName: result[0].data[0].personName,
personId: result[0].data[0].personId,
num: result[0].data[0].appointPersonNum
};
}
}
let newNarams = '';
if (result[0] && result[0].data) {
newNarams = {
id: result[0].data[0].activityId,
isFront: params.isFront
};
}
return adviserDetail(newNarams).then(newResult => {
let adviserDetail= '';
if (newResult && newResult.data) {
adviserDetail = {
name: newResult.data.activityName,
summary: newResult.data.summary,
free: newResult.data.isFree === 1,
price: newResult.data.price,
id: newResult.data.id,
kidStyle: newResult.data.activityType === 5,
photography: newResult.data.activityType === 4,
adviser: newResult.data.activityType === 3,
act: newResult.data.activityType === 2,
class: newResult.data.activityType === 1,
activityType: newResult.data.activityType,
storeId: params.storeId,
startDate: newResult.data.activityStartDate,
endDate: newResult.data.activityEndDate,
startTime: newResult.data.activityDayStartTime,
endTime: newResult.data.activityDayEndTime
};
}
resu = Object.assign(resu, {adviserDetail: adviserDetail});
return resu;
});
});
};
// 发型师列表
const cutterList = (params) => {
return service.get('MenuConfigController/getFrontMenuStylist', {
storeId: params.storeId,
id: params.id || '',
isFront: params.isFront
}).then(result => {
return result;
});
};
const cutterList2 = (params) => {
return service.get('MenuConfigController/getFrontMenuStylist', {
storeId: params.storeId,
isFront: params.isFront
}).then(result => {
return result;
});
};
// 儿童造型
const kidStyle = (params) => {
return Promise.all([
cutterList2(params),
adviserList(params),
photographyDetail(params),
]).then(result => {
let resu = {
cutterList: [],
storeId: params.storeId,
detail: {},
content: ''
};
if (result) {
if (result[0] && result[0].data) {
let build = [];
result[0].data.forEach(val => {
build.push({
name: val.stylistName,
level: val.stylistLevelStr,
price: val.minPrice,
img: val.stylistPhoto,
id: val.id,
radio: false,
arr: true,
storeId: params.storeId,
free: val.minPrice === -1,
noPackage: val.minPrice === null
});
});
resu.cutterList = build;
}
if (result[1] && result[1].data) {
let build = [];
result[1].data.forEach(val => {
build.push({
name: val.activityName,
free: val.isFree === 1,
price: val.price,
summary: val.summary,
id: val.id
});
});
resu.packageList = build;
}
if (result[2] && result[2].data) {
resu.detail = {
bigPic: result[2].data.mainPushUrl
};
resu.content = result[2].data.detail;
}
}
return resu;
});
};
// 潮童造型
const kids = (params) => {
return Promise.all([
storeSon(params)
]).then(result => {
let resu = {
storeSon: []
};
if (result && result[0] && result[0].data) {
let build = [];
result[0].data.forEach(val => {
build.push({
img: val.thumbnailUrl,
href: val.url
});
});
resu.storeSon = build;
}
return resu;
});
};
// 发型师
const cutter = (params) => {
return Promise.all([
cutterList(params),
adviserList(params),
getDate2(params)
]).then(result => {
let resu = {
packageList: [],
stylist: [],
dateList: [],
showBtn: ''
};
if (result) {
if (result[0] && result[0].data) {
let val = result[0].data[0];
resu = {
image: val.stylistPhoto,
name: val.stylistName,
summary: val.stylistLevelStr,
intro: val.introduction,
};
resu.showBtn = val.isAppointment ===1;
resu.stylist = val.stylistWorks.split(',');
}
if (result[1] && result[1].data) {
let build = [];
result[1].data.forEach(val => {
build.push({
name: val.activityName,
free: val.isFree === 1,
price: val.price,
summary: val.summary,
id: val.id
});
});
resu.packageList = build;
}
if (result[2] && result[2].data) {
let build = [];
if (result && result[2] && result[2].data) {
for(let item in result[2].data){
build.push({
date: _MD(item),
week: result[2].data[item],
dateOrigin: item,
dateParse: Date.parse(item) / 1000
});
}
resu.dateList = build;
}
}
}
return resu;
});
};
// 删除预约订单
const delOrder = (params) => {
return service.get('AppointmentController/frontCancelAppoint', {
id: params.id,
isFront: params.isFront
}).then(result => {
return result;
});
};
// 修改预约时间
const changeDate = (params) => {
let appointTimeStr = _originDay(params.appointTimeStr);
return service.get('AppointmentController/updateFrontAppointTime', {
id: params.id,
appointTimeStr: appointTimeStr,
isFront: params.isFront
}).then(result => {
return result;
});
};
// 获取可用时间
const getAbleTime = (params) => {
return service.get('ActivityConfigController/getAppointTime4Activity', {
activityType: params.activityType,
activityId: params.activityId,
isFront: params.isFront
}).then(result => {
return result;
});
};
module.exports = {
store,
articleDetail,
articleList,
classActList,
classActDetail,
travel,
adviser,
photography,
packageDetail,
styleDetail,
appointment,
chosenPackage,
chosenStyle,
chosenTime,
getTimeList,
addOrder,
orderList,
orderDetail,
kidStyle,
chosenCutter,
chosenAdviser,
cutter,
delOrder,
changeDate,
kids,
getAbleTime
};
... ...
... ... @@ -8,13 +8,13 @@
const router = require('express').Router(); // eslint-disable-line
const cRoot = './controllers';
const auth = require('../../doraemon/middleware/auth');
const demo = require(`${cRoot}/demo`);
const coupon = require(`${cRoot}/coupon`);
const wechat = require(`${cRoot}/wechat`);
const student = require(`${cRoot}/student`);
const live = require(`${cRoot}/live`);
const invite = require(`${cRoot}/invite`);
const auth = require('../../doraemon/middleware/auth');
const couponFloor = require(`${cRoot}/coupon-floor`);
const vipDay = require(`${cRoot}/vipDay`);
... ... @@ -30,6 +30,8 @@ const share = require(`${cRoot}/share`);
const aliCloud = require(`${cRoot}/ali-cloud`);
const studentMarket = require(`${cRoot}/student-market`);
const trend = require(`${cRoot}/trend`);
const promotion = require(`${cRoot}/promotion`);
const individuation = require(`${cRoot}/individuation`);
... ... @@ -149,6 +151,60 @@ router.get('/wechat/1111', wechat.feature);
router.get('/student-market', student.getUser, studentMarket.index);
// 潮流之旅-资讯
router.get('/trend/store', trend.store);
router.get('/trend/article-list', trend.articleList);
router.get('/trend/article-detail', trend.articleDetail);
router.get('/trend/map', trend.map);
// 潮流之旅-潮流课堂-活动
router.get('/trend/class', trend.classList);
router.get('/trend/activity', trend.activity);
router.get('/trend/class-detail', trend.classDetail);
router.get('/trend/act-detail', trend.actDetail);
router.get('/trend/appointment', auth, trend.appointment);
// 潮流之旅-潮流之旅-顾问
router.get('/trend/travel', trend.travel);
router.get('/trend/adviser', trend.adviser);
// 潮流之旅-潮童-摄影
router.get('/trend/kids', trend.kids);
router.get('/trend/photography', trend.photography);
router.get('/trend/style-detail', trend.styleDetail);
router.get('/trend/package-detail', trend.packageDetail);
// 潮流之旅-儿童造型
router.get('/trend/kid-style', trend.kidStyle);
router.get('/trend/cutter', trend.cutter);
// 潮流之旅-我的预约
router.get('/trend/order-list', auth, trend.orderList);
router.get('/trend/order-detail', auth, trend.orderDetail);
// 选择页
router.get('/trend/chosen-package', trend.chosenPackage);
router.get('/trend/chosen-style', trend.chosenStyle);
router.get('/trend/chosen-time', trend.chosenTime);
router.get('/trend/chosen-cutter', trend.chosenCutter);
router.get('/trend/chosen-adviser', trend.chosenAdviser);
router.get('/trend/need-know', trend.needKnow);
// 获取时间列表
router.get('/trend/getTimeList', trend.getTimeList);
router.get('/trend/getAbleTime', trend.getAbleTime);
// 增加预约订单
router.get('/trend/addOrder', trend.addOrder);
// 删除预约订单
router.get('/trend/delOrder', trend.delOrder);
// 修改预约时间
router.get('/trend/changeDate', trend.changeDate);
// 预约成功页
router.get('/trend/success', trend.success);
// 学生营销推广 2016.12.06 by jing.li@yoho.cn
router.get('/promotion', promotion.index);
... ...
... ... @@ -19,10 +19,10 @@
<section class="s-feild">
<label>身份证号</label><input type="text" id="tb_cert_no" name="tb_cert_no" placeholder="请输入您身份证号码" maxlength="18">
</section>
<section class="s-feild" data-aslider-in="province|fade">
<section class="s-feild province-select" data-aslider-in="province|fade">
<label>学校省份</label><input type="text" id="s-province-tb" name="s-province-tb" readonly="readonly" placeholder="请选择省份"><span class="s-select iconfont" >&#xe604;</span>
</section>
<section class="s-feild" data-aslider-in="school|fade" aslider-isShow="false">
<section class="s-feild school-select" data-aslider-in="school|fade" aslider-isShow="false">
<label>学校名称</label><input type="text" id="s-school-tb" name="s-school-tb" readonly="readonly" placeholder="请选择您的所在学校"><span id='s-toast-school' class="s-select iconfont">&#xe604;</span>
</section>
... ...
<div class="trend-c no-pb share-activity">
<div class="package-top">
<span></span>
预约后需到店付款
</div>
{{# list}}
{{> trend/activity}}
{{/ list}}
<div class="big-title-2">精彩回顾</div>
{{# oldList}}
{{> trend/activity}}
{{/ oldList}}
</div>
\ No newline at end of file
... ...
<div class="trend-c">
{{# detail}}
{{> trend/adviser-info}}
{{/ detail}}
<div class="box">
<div class="content content-padding">{{{content}}}</div>
</div>
{{#if dateList}}
<div class="big-title">
可预约时间
</div>
{{> trend/date-list}}
{{/if}}
<div class="s-tip">
<p>小贴士:</p>
<p>1、活动当天记得提前10-15分钟到店,以保证您能够准时参加活动;</p>
<p>2、您可以和2-3名好友一起来参加活动,共同体验潮流之旅;</p>
<p>3、活动时长预估时间,如超出时间请您谅解。</p>
</div>
<a class="foot-btn ok" href="//m.yohobuy.com/activity/trend/appointment?storeId={{storeId}}&typeStatus=3">立即预约</a>
</div>
\ No newline at end of file
... ...
<div class="trend-c no-pb">
{{# storeInfo}}
<div class="apt-info">
<div>当前预约门店:{{name}}</div>
<div>
<span class="icon-pic adr"></span>
门店地址:{{adr}}
</div>
<a href="tel:{{telephone}}">
<div>
<span class="icon-pic tel"></span>
门店电话:{{telephone}}
</div>
</a>
</div>
{{/ storeInfo}}
<div class="chosen chosen-select">
{{# classChosen}}
<div class="chose-item select depend">
<span class="label">潮流课堂</span>
<input class="inp chosen-class eps" type="text" label="潮流课堂" placeholder="未选择" readonly="readonly" />
<span class="iconfont icon-arr">&#xe604;</span>
</div>
{{/ classChosen}}
{{# actChosen}}
<div class="chose-item select depend">
<span class="label">活动</span>
<input class="inp chosen-class eps" type="text" label="活动" placeholder="未选择" readonly="readonly" />
<span class="iconfont icon-arr">&#xe604;</span>
</div>
{{/ actChosen}}
{{# cutterChosen}}
<div class="chose-item select depend">
<span class="label">发型师</span>
<a href="http://m.yohobuy.com/activity/trend/chosen-cutter?storeId={{storeId}}&chosenType=5&typeStatus={{typeStatus}}">
<input class="inp chosen-cutter eps require" type="text" label="发型师" placeholder="未选择" readonly="readonly" />
</a>
<span class="iconfont icon-arr">&#xe604;</span>
</div>
{{/ cutterChosen}}
{{# packageChosen}}
<div class="chose-item select depend">
<span class="label">选择套餐</span>
<a href="http://m.yohobuy.com/activity/trend/chosen-package?storeId={{storeId}}&chosenType=4&typeStatus={{typeStatus}}">
<input class="inp chosen-package eps require" label="套餐" type="text" placeholder="未选择" readonly="readonly" />
</a>
<span class="iconfont icon-arr">&#xe604;</span>
</div>
{{/ packageChosen}}
{{# styleChosen}}
<div class="chose-item select need">
<span class="label">选择风格</span>
<a href="http://m.yohobuy.com/activity/trend/chosen-style?storeId={{storeId}}&chosenType=1&typeStatus={{typeStatus}}">
<input class="inp chosen-style eps require" type="text" label="风格" placeholder="未选择" readonly="readonly" />
</a>
<span class="iconfont icon-arr">&#xe604;</span>
</div>
{{/ styleChosen}}
{{# adviserChosen}}
<div class="chose-item select{{#if hideChosen}} depend{{/if}}">
<span class="label">潮流顾问</span>
<a href="http://m.yohobuy.com/activity/trend/chosen-adviser?storeId={{storeId}}&chosenType=3&typeStatus={{typeStatus}}">
<input class="inp chosen-adviser eps require" type="text" label="顾问" placeholder="未选择" readonly="readonly" />
</a>
<span class="iconfont icon-arr">&#xe604;</span>
</div>
{{/ adviserChosen}}
<div class="chose-item select{{#if hideChosen}} need{{/if}}">
<span class="label">选择时间</span>
<a href="http://m.yohobuy.com/activity/trend/chosen-time?storeId={{storeId}}&chosenType=2&typeStatus={{typeStatus}}">
<input class="inp chosen-time require" type="text" label="时间" placeholder="未选择" readonly="readonly" />
</a>
<span class="iconfont icon-arr">&#xe604;</span>
</div>
</div>
<div class="chosen chosen-info">
<div class="chose-item input">
<span class="label">{{#if babyName}}宝宝{{/if}}姓名</span>
<input class="inp cookie require" label="{{#if babyName}}宝宝{{/if}}姓名" type="text" id="name" placeholder="输入{{#if babyName}}宝宝{{/if}}姓名" />
</div>
{{# sexInp}}
<div class="chose-item input">
<span class="label">宝宝性别</span>
<input type="hidden" />
<input type="radio" name="sex" checked="checked" class="diy-2 cookie2" />
<label name="男"></label>
<input type="radio" name="sex" class="diy-2 cookie2" />
<label name="女"></label>
</div>
{{/ sexInp}}
{{# ageInp}}
<div class="chose-item input">
<span class="label">宝宝年龄</span>
<input type="text" class="inp inp-s cookie require" label="宝宝年龄" id="age" placeholder="输入年龄" />
<input type="radio" name="birth" checked="checked" class="diy-2 cookie2" />
<label></label>
<input type="radio" name="birth" class="diy-2 cookie2" />
<label></label>
</div>
{{/ ageInp}}
<div class="chose-item input">
<span class="label">手机号码</span>
<input class="inp cookie require" type="text" label="手机号码" id="tel" placeholder="输入手机号" />
</div>
<div class="chose-item input">
<span class="label">人数</span>
<div class="num">
<a class="minus-btn"></a>
<input type="text" id="num" value="1" max="1" readonly="readonly" />
<a class="plus-btn"></a>
</div>
</div>
<div class="textarea">
<textarea class="cookie" id="note">添加备注(选填)</textarea>
</div>
</div>
<div class="need-know">
<input type="checkbox" class="diy diy-3" checked="ckecked" />
我已阅读
<a href="http://m.yohobuy.com/activity/trend/need-know">
{{# classChosen}}潮流课堂{{/ classChosen}}
{{# adviserChosen}}潮流之旅{{/ adviserChosen}}
{{# babyName}}潮童造型{{/ babyName}}
{{# actChosen}}活动{{/ actChosen}}
预约须知
</a>
</div>
<a class="foot-btn ok dia-tip order-submit">确认预约</a>
<div class="right-side" id="dia-tip">
{{> trend/dia-tip}}
</div>
<input type="hidden" id="uid" value="{{uid}}" />
</div>
\ No newline at end of file
... ...
<div class="trend-c no-pb share-article">
<div class="article-detail">
<img src="{{image coverUrl}}">
<p class="title">{{title}}</p>
<p>{{summary}}</p>
<div class="content">{{{content}}}</div>
</div>
</div>
\ No newline at end of file
... ...
<div class="trend-c no-pb share-store">
{{# infos}}
{{> trend/article}}
{{/ infos}}
</div>
\ No newline at end of file
... ...
<div class="trend-c">
<div class="side-main">
<div class="adviser-chosen">
<label class="top">
<input type="radio" name="adviser" class="diy" data="不预约潮流顾问" />
不预约潮流顾问
</label>
<div class="chosen-list">
{{# adviser}}
<label class="item clearfix">
<input type="radio" name="adviser" id="{{id}}" class="diy" data="{{name}}" />
<div class="pic">
<img src="{{image image}}">
</div>
<div class="info">
<p class="name">{{name}}</p>
<p class="intro">{{summary}}</p>
</div>
</label>
{{/ adviser}}
</div>
</div>
</div>
<a class="foot-btn ok chosen-btn">确定</a>
</div>
\ No newline at end of file
... ...
<div class="trend-c">
<div class="side-main">
<div class="adviser-chosen">
<label class="top">
<input type="radio" name="cutter" class="diy" data="不预约发型师" />
不预约发型师
</label>
<div class="cutter side">
{{# cutterList}}
<label class="cutter-item clearfix">
{{# radio}}
<input type="radio" name="cutter" class="diy" data={{name}} />
{{/ radio}}
<div class="pic">
<img src="{{image img}}">
</div>
<div class="tip">
<div class="name">{{name}}</div>
<div class="intro">{{level}}</div>
</div>
{{#if noPackage}}
<span class="iconfont icon-arr">&#xe604;</span>
{{else}}
<div class="price">
<span>¥</span>{{#if free}}0{{else}}{{price}}{{/if}}<span></span>
</div>
{{/if}}
</label>
{{/ cutterList}}
</div>
</div>
</div>
<a class="foot-btn ok chosen-btn">确定</a>
</div>
\ No newline at end of file
... ...
<div class="trend-c">
<div class="side-main">
<div class="package-c">
<ul class="package">
{{# packageChosen}}
{{> trend/package}}
{{/ packageChosen}}
</ul>
</div>
</div>
<a class="foot-btn ok chosen-btn">确定</a>
</div>
\ No newline at end of file
... ...
<div class="trend-c">
<div class="side-main grey-bg">
<div class="style-c">
<div class="top"><span class="icon-pic tip"></span>如更换套餐请重新选择</div>
<p class="style-tip">当前套餐可选风格<span class="total"></span>种,已选<span class="now"></span></p>
<ul class="style-ul clearfix">
{{# styleList}}
<li id="{{id}}" class="disabled">&nbsp{{name}}&nbsp</li>
{{/ styleList}}
</ul>
<ul class="style-ul later clearfix">
<li class="not">我还没想好选什么风格</li>
</ul>
</div>
</div>
<a class="foot-btn ok chosen-btn">确定</a>
</div>
\ No newline at end of file
... ...
<div class="trend-c chosen-time">
<p class="date-tip {{#if hide}}hide{{/if}}"><span class="icon-pic tip"></span>如更换{{#if needAdv}}顾问{{else}}套餐{{/ if}}请重新选择</p>
<div class="side-main">
<div class="time-nav wrapper clearfix">
<ul class="nav-ul">
<li class="nav-item disable"></li>
<li class="nav-item disable"></li>
{{# dateList}}
<li class="nav-item" data="{{dateOrigin}}" time="{{dateParse}}">
<p>{{date}}</p>
<p>{{week}}</p>
</li>
{{/ dateList}}
<li class="nav-item disable"></li>
<li class="nav-item disable"></li>
</ul>
</div>
<div class="time-list clearfix">
</div>
</div>
<a class="foot-btn ok chosen-btn">确定</a>
</div>
\ No newline at end of file
... ...
<div class="trend-c">
<div class="class class-detail">
<div class="class-item clearfix">
<div class="info">
<span class="name" id="{{id}}">{{name}}</span>
{{#if price}}
<span class="price"><span>¥</span>{{price}}</span>
{{else}}
<span class="price">免费</span>
{{/if}}
</div>
<div class="tip">
<div>
<p>日期:{{startDate}}{{endDate}}</p>
<p>时间:{{startTime}}{{endTime}}</p>
</div>
</div>
<div class="content">
{{{content}}}
</div>
</div>
</div>
{{> (lookup . 'status')}}
{{#*inline '1'}}
<a class="foot-btn ok clearCookie" href="//m.yohobuy.com/activity/trend/appointment?storeId={{storeId}}&typeStatus={{activityType}}">立即预约</a>
{{/inline}}
{{#*inline '2'}}
<a class="foot-btn full">已约满</a>
{{/inline}}
{{#*inline '0'}}
<a class="foot-btn full">已结束</a>
{{/inline}}
{{#*inline '3'}}
{{/inline}}
</div>
... ...
<div class="trend-c no-pb share-class">
<div class="package-top">
<span></span>
预约后需到店付款
</div>
{{# list}}
{{> trend/class}}
{{/ list}}
<div class="big-title-2">精彩回顾</div>
{{# oldList}}
{{> trend/class}}
{{/ oldList}}
</div>
\ No newline at end of file
... ...
<div class="trend-c share-cutter">
{{> trend/adviser-info}}
<div class="big-title">造型套餐</div>
<div class="package-top">
<span></span>
预约后需到店付款
</div>
{{# packageList}}
{{> trend/cutter-package}}
{{/ packageList}}
<div class="big-title">可预约时间</div>
{{> trend/date-list}}
<div class="big-title">作品展示</div>
<div class="display-list clearfix">
<div class="pull-pic-list clearfix">
{{# stylist}}
<div class="box">
<img src="{{image this}}" />
</div>
{{/ stylist}}
</div>
</div>
{{#if showBtn}}
<a class="foot-btn ok" href="//m.yohobuy.com/activity/trend/appointment?storeId={{storeId}}&typeStatus=5">立即预约</a>
{{/if}}
<div class="big-pic">
<div class="bg"></div>
<div class="swiper-c">
<div class="swiper-container">
<div class="swiper-wrapper">
{{# stylist}}
<div class="swiper-slide">
<img src="{{image this}}" />
</div>
{{/ stylist}}
</div>
<div class="swiper-pagination"></div>
</div>
</div>
</div>
</div>
\ No newline at end of file
... ...
<div class="trend-c kid-style">
<div class="box-padding">
{{# detail}}
{{#if bigPic}}
<img src="{{image bigPic}}">
{{/ if}}
{{/ detail}}
<div class="left-title">儿童造型</div>
{{#if content}}
<div class="content">{{{content}}}</div>
{{/if}}
</div>
<div class="tip-tittle">
<span class="icon-pic tip"></span>您可以选择<span class="red">预约发型师</span>或者<span class="red">直接预约套餐</span>来理发
</div>
<div class="big-title">发型师</div>
<div class="cutter">
{{# cutterList}}
{{> trend/cutter}}
{{/ cutterList}}
</div>
<div class="big-title">造型套餐</div>
<div class="package-top">
<span></span>
预约后需到店付款
</div>
{{# packageList}}
{{> trend/cutter-package}}
{{/packageList}}
<a class="foot-btn ok clearCookie" href="//m.yohobuy.com/activity/trend/appointment?storeId={{storeId}}&typeStatus=5">立即预约</a>
</div>
\ No newline at end of file
... ...
<div class="trend-c">
<div class="kids-pic">
{{# storeSon}}
<a href={{href}}>
<img src="{{image img}}">
</a>
{{/ storeSon}}
</div>
</div>
\ No newline at end of file
... ...
<div class="trend-c map-c share-store">
<script type="text/javascript" src="http://api.map.baidu.com/api?v=2.0&ak=55E5CFCa68831302cebe0acdd575c77d"></script>
<script type="text/javascript" src="http://api.map.baidu.com/library/SearchInfoWindow/1.5/src/SearchInfoWindow_min.js"></script>
<div id="map"></div>
</div>
\ No newline at end of file
... ...
<div class="trend-c">
<div class="content box-padding">
<h1 style="text-align:center;">YO!SMILE拍摄服务协议</h1>
经我们双方共同协商,就YO!SMILE儿童摄影(以下简称:YO!SMILE)为您提供儿童影像服务,达成如下服务协议:<br />
1、拍摄项目为您选择预定的套餐,拍摄服务的收费总额即为您预定的套餐价格。套餐所付价格即为全部服务费用,过程中没有二次消费。如需出外景拍摄,请客人自备车辆,门票等额外费用,由客人承担。所有拍摄均按预定的套系内容提供相应的造型服务不提供服装,客人可免费借用YOHO!有货南京艾尚店的服装,或者自带准备的服饰,我们都将为您提供意见参考。如选择借用YOHO!有货线下实体店的服装,拍摄中人为产生不可修复的情况需酌情赔偿。(服饰准备详见“常见问题”)<br />
2、YO!SMILE为您提供您所预定套餐内的所有产品和服务。除此外,我们还提供其他有偿服务:如额外精修入册、增加升级相册、定制油画布画框和其他等产品。<br />
3、所有可预定的档期,已公布在预定系统。您在预定档期后,我们会电话联系您,确认您的订单内容,并且您需要支付500元作为定金(此定金含在套餐总额内),支付方式为支付宝、微信、银行转账。我们不接受已预定成功的客人以各种形式转让给他人拍摄,所有拍摄信息以您填写的内容为准。<br />
4、收取定金的目的是为了确定每位客人的拍摄意向。一旦确定拍摄意向,摄影师和助理就开始作拍摄准备,当然也是为了让您不随意变更或者被变更或被取消拍摄计划造成时间上的浪费。如需延期或者取消拍摄,需提前3个工作日与我们联系,我们可帮您协调解决,如没有提前3个工作日联系,我们将收取已支付的定金50%作为档期空缺的风险补偿或手续费,不予退还。<br />
5、拍摄当天,您须向YO!SMILE以支付宝、微信、银行卡、现金的形式付清拍摄尾款。未支付定金的预订视为无效,由于未及时支付定金而导致超时定单被取消的,我们不承担任何责任。拍摄当天因不可避免的原因,如小朋友生病、恶劣天气状况等,可以与客服协调更换时间,更换拍摄的有效期为首次预定拍摄时间的半年内进行拍摄,费用不变。如超过时间,套餐价格如有更改,将按照新的套餐拍摄价格收费。<br />
6、我们按您所选择预定的套餐拍摄标准为您提供优质的服务,保证拍摄质量。但因我们的影像服务为创意拍摄,所以在拍摄前,请您考虑清楚再决定是否需要预定。在拍摄时,也请给予摄影师自由发挥的空间。如果拍摄已完成且您已确认照片没有问题,此后不再作退款或补拍。由于我们单方面的责任,导致拍摄无法开始或提前终止,我们将主动与您协商调换拍摄时间,也可以与您协商部分退款,部分退款的金额不超过您预定套餐价格的50%。如达成部分退款的协议,那么双方的服务关系将立即终止。在达成该退款协议之前拍摄或制作的照片或产品,YO!SMILE有权作报废处理。如不同意这一条款,将无法获得部分退款。如果您已确认过照片本身没有问题,但如相册、相框等实物印品存在错误或明显的瑕疵,我们给予免费更换同产品,但不作退款或替换等值产品的服务。如发现以上问题需要更换产品,在更换新品前必须向我们退回原有产品。<br />
7、YO!SMILE拥有所有拍摄照片的著作权(版权),我们在本营业场所、官方微博、官方微信有对所拍摄照片展示的权利。如借用的YOHO!有货的服装,YOHO!有货也拥有相关照片展示的权利。未经YO!SMILE同意,您不得将拍摄图片等资料外泄和转让至第三方。YO!SMILE也将保证恪守职业道德,不会将拍摄的图片和个人资料外泄或用于其他以盈利为目的的商业用途。如一方因以上问题给对方蒙受损失的,受损失方有追究对方责任和索赔的权利。<br />
8、作为拍摄对象(未成年子女)的监护人,您在YO!SMILE工作环境内,须管好未成年孩子,履行监护权。因看护不到位,造成被监护人伤害的,我们不承担相应责任。<br />
9、在为客人服务(拍摄)期间,客人须积极配合我们的拍摄工作,由于客人配合不积极或其他原因造成本协议约定的服务不能履行的,后果由客人承担。<br />
10、本协议执行期间,如遇不可抗力(包括但不限于因天气等原因导致无法按时完成拍摄),致使本协议无法履行时,双方应本着友善的态度协商解决,我们也会重新安排档期(有效期为首次预定拍摄时间的半年有效时间内进行拍摄)。<br />
11、所有原片,YO!SMILE将在成品交付后为您保存3个月时间(由取件日起计算),到期后将全部删除,请您保存好与相册一同附送的光盘。如有遗失,3个月内我们都将为您再次刻制寄送光盘文件(快递费用自理)。<br />
12、我们双方都可以对本协议的条款进行修改或作出补充,条款的修订须由双方以书面形式签定补充协议,补充协议与本协议具有同等法律效力。<br />
13、YO!SMILE保留对以上协议条款进行更改的权利。若希望在协议变更后继续使用我们提供的服务,您须同意接受任何更改后协议的约束。客人预定或购买YO!SMILE儿童摄影服务的权限是以遵守这些条款为明确条件的。<br />
本服务协议自您同意确认之日起生效。本协议内容如与国家相关法律、法规相悖,以法律、法规的规定为准。如违反了任何一项条款,都有可能导致我们终止向您提供服务。
</div>
</div>
\ No newline at end of file
... ...
<div class="trend-c share-order">
{{# userInfo}}
<div class="detail-top">预约状态:{{status}}</div>
{{/ userInfo}}
<div class="detail-list">
{{#storeInfo}}
<a class="list-item" href="//m.yohobuy.com/activity/trend/store?storeId={{storeId}}">
<span class="icon-pic shop"></span>
门店:{{name}}
<span class="iconfont icon-arr">&#xe604;</span>
</a>
<a class="list-item"{{#if longitude}} href="//m.yohobuy.com/activity/trend/map?jd={{longitude}}&wd={{latitude}}&name={{storeName}}&intro={{introduction}}&tel={{telephone}}&adr={{address}}&pic={{image pictureUrl}}"{{/if}}>
<span class="icon-pic adr"></span>
门店地址:{{adr}}
{{#if longitude}}
<span class="iconfont icon-arr">&#xe604;</span>
{{/if}}
</a>
<a class="list-item" href="tel:{{telephone}}">
<span class="icon-pic tel"></span>
门店电话:{{telephone}}
<span class="iconfont icon-arr">&#xe604;</span>
</a>
{{/ storeInfo}}
</div>
{{# adviserDetail}}
<div class="detail-list">
{{# adviser}}
<a class="list-item" href="{{../userInfo/originUrl}}">
<span class="big">潮流之旅</span>
<span class="iconfont icon-arr">&#xe604;</span>
</a>
{{/ adviser}}
{{# photography}}
<a class="list-item" href="{{../userInfo/originUrl}}">
<span class="big">儿童摄影</span>
<span class="iconfont icon-arr">&#xe604;</span>
</a>
{{/ photography}}
{{# kidStyle}}
<a class="list-item" href="{{../userInfo/originUrl}}">
<span class="big">儿童造型</span>
<span class="iconfont icon-arr">&#xe604;</span>
</a>
{{/ kidStyle}}
{{# class}}
<a class="list-item" href="{{../userInfo/originUrl}}">
<span class="big">潮流课堂</span>
<span class="iconfont icon-arr">&#xe604;</span>
</a>
{{/ class}}
{{# act}}
<a class="list-item" href="{{../userInfo/originUrl}}">
<span class="big">活动</span>
<span class="iconfont icon-arr">&#xe604;</span>
</a>
{{/ act}}
</div>
<div class="detail-list{{# adviser}} hide{{/ adviser}}">
<div class="list-item">
<div class="package-item">
<div class="top clearfix">
<div class="name">{{name}}</div>
<div class="price">
{{#if free}}
免费
{{else}}
<span>¥</span>{{price}}
{{/if}}
</div>
</div>
<div class="main">{{summary}}</div>
</div>
{{# kidStyle}}
<a href="//m.yohobuy.com/activity/trend/package-detail?id={{id}}" class="order-a">
<span class="big">查看套餐详情</span>
<span class="iconfont icon-arr">&#xe604;</span>
</a>
{{/ kidStyle}}
{{# photography}}
<a href="//m.yohobuy.com/activity/trend/package-detail?id={{id}}" class="order-a">
<span class="big">查看套餐详情</span>
<span class="iconfont icon-arr">&#xe604;</span>
</a>
{{/ photography}}
{{# act}}
<a href="//m.yohobuy.com/activity/trend/act-detail?activityId={{id}}&name={{name}}&price={{price}}&startDate={{startDate}}&endDate={{endDate}}&startTime={{startTime}}&endTime={{endTime}}&status=1&storeId={{storeId}}" class="order-a">
<span class="big">查看活动详情</span>
<span class="iconfont icon-arr">&#xe604;</span>
</a>
{{/ act}}
{{# class}}
<a href="//m.yohobuy.com/activity/trend/class-detail?activityId={{id}}&name={{name}}&price={{price}}&startDate={{startDate}}&endDate={{endDate}}&startTime={{startTime}}&endTime={{endTime}}&status=1&storeId={{storeId}}" class="order-a">
<span class="big">查看课堂详情</span>
<span class="iconfont icon-arr">&#xe604;</span>
</a>
{{/ class}}
</div>
</div>
{{/ adviserDetail}}
<div class="detail-list">
{{# userInfo}}
<div class="list-item padding">
{{#if ../adviserDetail/adviser}}
<div class="chosen chosen-detail">
<a class="chose-item select" href="//m.yohobuy.com/activity/trend/adviser?id={{../adviserDetail/id}}&typeStatus={{../adviserDetail/activityType}}&storeId={{../adviserDetail/storeId}}">
<span class="label">潮流顾问</span>
<input class="inp eps" type="text" value="{{../userInfo/personName}}" readonly="readonly" />
<span class="iconfont icon-arr">&#xe604;</span>
</a>
</div>
{{/if}}
{{#if ../adviserDetail/kidStyle}}
<div class="chosen chosen-detail">
<a class="chose-item select" href="//m.yohobuy.com/activity/trend/cutter?storeId={{../adviserDetail/storeId}}&id={{../userInfo/personId}}&typeStatus={{../adviserDetail/activityType}}&cutterName={{../userInfo/personName}}">
<span class="label">发型师</span>
<input class="inp eps" type="text" value="{{../userInfo/personName}}" readonly="readonly" />
<span class="iconfont icon-arr">&#xe604;</span>
</a>
</div>
{{/if}}
{{#if stylesName}}
<p class="tip-top">风格</p>
<p class="tip-main">{{stylesName}}</p>
{{/if}}
<p class="tip-top">预约时间</p>
<p class="tip-main"><span id="detail-time" date="{{originTime}}">{{appointTime}}</span>
{{#if showBtn}}
<a class="chan-btn" id={{id}} href="//m.yohobuy.com/activity/trend/chosen-time?storeId={{storeId}}&activityId={{activityId}}&typeStatus={{typeStatus}}&chosenType=2&order=true">更改</a>
{{/if}}
</p>
</div>
{{/ userInfo}}
</div>
<div class="detail-list">
{{# userInfo}}
<div class="list-item padding detail-info">
<div>
<span class="tip-top">{{#if babyAge}}宝宝{{/if}}姓名:</span>
<span class="tip-main">{{babyName}}</span>
</div>
{{#if babySex}}
<div>
<span class="tip-top">宝宝性别:</span>
<span class="tip-main">{{babySex}}</span>
</div>
{{/if}}
{{#if babyAge}}
<div>
<span class="tip-top">宝宝年龄:</span>
<span class="tip-main">{{babyAge}}</span>
</div>
{{/if}}
<div>
<span class="tip-top">手机{{#if babyAge}}号码{{/if}}</span>
<span class="tip-main">{{appointMobile}}</span>
</div>
<div>
<span class="tip-top">人数:</span>
<span class="tip-main">{{num}}</span>
</div>
{{#if userNote}}
<div>
<span class="tip-top">备注:</span>
<span class="tip-main">{{userNote}}</span>
</div>
{{/ if}}
</div>
{{/ userInfo}}
</div>
{{# userInfo}}
{{#if showBtn}}
<div class="order-btn">
<a id="{{id}}">取消预订</a>
</div>
{{/if}}
{{/ userInfo}}
</div>
\ No newline at end of file
... ...
<div class="trend-c share-order" {{#if noOrder}}style="background-color: #fff;"{{/if}}>
{{#if noOrder}}
<div class="success">
<div class="success-pic fail-pic"></div>
<p class="title">您还没有预约,快去预约吧</p>
</div>
{{/if}}
<div class="order-list clearfix">
{{# list1}}
<a class="order-item clearfix" href="//m.yohobuy.com/activity/trend/order-detail?id={{id}}&storeId={{storeId}}&showBtn=true&typeStatus={{typeStatus}}&activityId={{activityId}}">
<div class="info">
<div class="name">{{name}}
<span class="iconfont icon-arr">&#xe604;</span>
</div>
<div class="time" date="{{originTime}}">{{createTime}}</div>
</div>
<div class="sou">{{status}}</div>
</a>
{{/ list1}}
</div>
{{#if list2}}
<div class="order-pic"></div>
{{/if}}
<div class="order-list clearfix">
{{# list2}}
<a class="order-item clearfix" href="//m.yohobuy.com/activity/trend/order-detail?id={{id}}&storeId={{storeId}}">
<div class="info">
<div class="name">{{name}}
<span class="iconfont icon-arr">&#xe604;</span>
</div>
<div class="time" date="{{originTime}}">{{createTime}}</div>
</div>
<div class="sou">{{status}}</div>
</a>
{{/ list2}}
</div>
</div>
\ No newline at end of file
... ...
<div class="trend-c package-detail">
{{# detail}}
<img src="{{image img}}">
<div class="package-item only">
<div class="top clearfix package-detail">
<div class="name eps">{{name}}</div>
{{#if free}}
<div class="price">免费</div>
{{else}}
<div class="price"><span>¥</span>{{price}}</div>
{{/if}}
</div>
<div class="main">
<p>{{summary}}</p>
</div>
</div>
<input class="limit" type="hidden" value="{{limit}}" />
<input class="styleid" type="hidden" value="{{styleId}}" />
{{/ detail}}
<div class="content content-padding">{{{content}}}</div>
{{#if isAppointment}}
<a class="foot-btn ok" href="//m.yohobuy.com/activity/trend/appointment?storeId={{storeId}}&typeStatus=4">确认预约</a>
{{/if}}
</div>
\ No newline at end of file
... ...
<div class="trend-c">
<div class="box-padding">
{{# detail}}
{{#if bigPic}}
<img src="{{image bigPic}}">
{{/if}}
{{/ detail}}
<div class="left-title">儿童摄影</div>
{{#if content}}
<div class="content">{{{content}}}</div>
{{/if}}
</div>
<div class="big-title">当季最IN主题</div>
<div class="swiper-c">
<div class="swiper-container">
<div class="swiper-wrapper">
{{# swiper}}
<div class="swiper-slide">
<a class="pic" href="http://m.yohobuy.com/activity/trend/style-detail?id={{id}}&storeId={{storeId}}&styleName={{name}}">
<img src="{{image pic}}">
</a>
<p class="title eps">{{name}}</p>
<p class="main">{{introduction}}</p>
</div>
{{/ swiper}}
</div>
<div class="swiper-pagination"></div>
</div>
</div>
<div class="tab clearfix">
<div class="tab-top">
<span class="active">风格</span>
<span>套餐</span>
</div>
<div class="tab-item hide">
<ul class="tab-ul clearfix">
{{# styleList}}
<li>
<a href="http://m.yohobuy.com/activity/trend/style-detail?id={{id}}&storeId={{../storeId}}&styleName={{name}}">
<img src="{{image img}}">
</a>
</li>
{{/ styleList}}
</ul>
</div>
<div class="tab-item hide">
<div class="package-top">
<span></span>
预约后需到店付款
</div>
<ul class="package">
{{# packageList}}
{{> trend/package}}
{{/ packageList}}
</ul>
</div>
</div>
<a class="foot-btn ok clearCookie" href="//m.yohobuy.com/activity/trend/appointment?storeId={{storeId}}&typeStatus=4">立即预约</a>
</div>
\ No newline at end of file
... ...
<div class="trend-c no-pb share-store">
{{# infos}}
{{> trend/article}}
{{/ infos}}
{{#if infos}}
{{#detail}}
<a class="more-article" href="//m.yohobuy.com/activity/trend/article-list?storeId={{storeId}}">更多活动咨询
<span class="iconfont icon-arr">&#xe604;</span>
</a>
{{/ detail}}
{{/if}}
<div class="article">
<div class="article-item">
{{#detail}}
<div class="pic">
<img src="{{image pictureUrl}}">
</div>
<p class="title">{{storeName}}</p>
<div class="tip">{{introduction}}</div>
<div class="list">
<a class="list-item">
<span class="icon-pic clock"></span>
营业时间:{{businessTime}}
<span class="iconfont icon-arr">&#xe604;</span>
</a>
<a class="list-item" href="//m.yohobuy.com/activity/trend/map?jd={{longitude}}&wd={{latitude}}&name={{storeName}}&intro={{introduction}}&tel={{telephone}}&adr={{address}}&pic={{image pictureUrl}}">
<span class="icon-pic adr"></span>
门店地址:{{address}}
<span class="iconfont icon-arr">&#xe604;</span>
</a>
<a class="list-item" href="tel:{{telephone}}">
<span class="icon-pic tel"></span>
门店电话:{{telephone}}
<span class="iconfont icon-arr">&#xe604;</span>
</a>
</div>
{{/ detail}}
</div>
</div>
<div class="appointment">
<div class="title">活动预约</div>
{{# storeSon}}
<a class="appointment-item" href="{{href}}">
<img src="{{image img}}">
</a>
{{/ storeSon}}
</div>
</div>
\ No newline at end of file
... ...
<div class="trend-c">
<div class="box-padding style-detail">
<div class="content">{{introduction}}</div>
<div class="pull-pic-list clearfix">
{{# picList}}
<div class="box">
<img src="{{image imgSrc}}" />
</div>
{{/ picList}}
</div>
</div>
<a class="foot-btn ok" href="//m.yohobuy.com/activity/trend/appointment?storeId={{storeId}}&typeStatus=4">立即预约</a>
<div class="big-pic">
<div class="bg"></div>
<div class="swiper-c">
<div class="swiper-container">
<div class="swiper-wrapper">
{{# picList}}
<div class="swiper-slide">
<img src="{{image imgSrc}}" />
</div>
{{/ picList}}
</div>
<div class="swiper-pagination"></div>
</div>
</div>
</div>
</div>
\ No newline at end of file
... ...
<div class="trend-c" style="background-color: #fff;">
<div class="success">
<div class="success-pic"></div>
<p class="title">恭喜您预约成功</p>
<p class="tip">点击我的预约,查看您的预约项目</p>
<a href="//m.yohobuy.com/activity/trend/order-list?storeId={{storeId}}">我的预约</a>
</div>
</div>
\ No newline at end of file
... ...
<div class="trend-c travel">
<div class="box">
<div class="content content-padding2">
{{{content}}}
</div>
</div>
<div class="big-title">
潮流顾问
</div>
{{# adviser}}
{{> trend/adviser}}
{{/ adviser}}
<div class="big-title">
可预约时间
</div>
{{> trend/date-list}}
<div class="s-tip">
<p>小贴士:</p>
<p>1、活动当天记得提前10-15分钟到店,以保证您能够准时参加活动;</p>
<p>2、您可以和2-3名好友一起来参加活动,共同体验潮流之旅;</p>
<p>3、活动时长预估时间,如超出时间请您谅解。</p>
</div>
<a class="foot-btn ok clearCookie" href="//m.yohobuy.com/activity/trend/appointment?storeId={{storeId}}&typeStatus=3">立即预约</a>
</div>
\ No newline at end of file
... ...
<div class="class">
<div class="class-item clearfix">
<a class="pic" href="//m.yohobuy.com/activity/trend/act-detail?activityId={{id}}&name={{name}}&price={{price}}&startDate={{startDate}}&endDate={{endDate}}&startTime={{startTime}}&endTime={{endTime}}&status={{status}}&storeId={{storeId}}">
<img src="{{image image}}">
</a>
<div class="info">
<span class="name">{{name}}</span>
{{#if free}}
<span class="free">免费</span>
{{else}}
<span class="price"><span>¥</span>{{price}}</span>
{{/if}}
</div>
<div class="tip">
<div>
<p>日期:{{startDate}}{{endDate}}</p>
<p>时间:{{startTime}}{{endTime}}</p>
</div>
{{#if end}}
<a class="end">已结束</a>
{{else}}
{{#if needApo}}
{{#if apoStatus}}
<a href="//m.yohobuy.com/activity/trend/act-detail?activityId={{id}}&name={{name}}&price={{price}}&startDate={{startDate}}&endDate={{endDate}}&startTime={{startTime}}&endTime={{endTime}}&status={{status}}&storeId={{storeId}}">立即预约</a>
{{else}}
<a class="disable">已约满</a>
{{/if}}
{{else}}
<a class="any-time">免预约</a>
{{/if}}
{{/if}}
</div>
</div>
</div>
\ No newline at end of file
... ...
<div class="adviser-header">
<div class="bg-pic" style="background-image:url({{image image}})"></div>
<div class="adviser-info">
<img class="pic" src="{{image image}}">
<div class="name">{{name}}</div>
<div class="intro">{{summary}}</div>
<div class="info">{{intro}}</div>
</div>
</div>
\ No newline at end of file
... ...
<div class="adviser">
<a class="adviser-item" href="//m.yohobuy.com/activity/trend/adviser?id={{id}}&typeStatus={{typeStatus}}&storeId={{storeId}}">
<div class="pic">
<img src="{{image image}}">
</div>
<div class="info">
<div class="name eps">{{name}}</div>
<div class="intro">{{summary}}</div>
</div>
<span class="iconfont icon-arr">&#xe604;</span>
</a>
</div>
\ No newline at end of file
... ...
<div class="article">
<div class="article-item">
<a class="pic" href="//m.yohobuy.com/activity/trend/article-detail?informationId={{id}}">
<img src="{{image coverUrl}}">
</a>
<p class="title">{{title}}</p>
<div class="tip">
{{summary}}
<a href="//m.yohobuy.com/activity/trend/article-detail?informationId={{id}}">查看详情</a>
</div>
</div>
</div>
\ No newline at end of file
... ...
<div class="class">
<div class="class-item clearfix">
<a class="pic" href="//m.yohobuy.com/activity/trend/class-detail?activityId={{id}}&name={{name}}&price={{price}}&startDate={{startDate}}&endDate={{endDate}}&startTime={{startTime}}&endTime={{endTime}}&status={{status}}&storeId={{storeId}}">
<img src="{{image image}}">
</a>
<div class="info">
<span class="name">{{name}}</span>
{{#if free}}
<span class="free">免费</span>
{{else}}
<span class="price"><span>¥</span>{{price}}</span>
{{/if}}
</div>
<div class="tip">
<div>
<p>日期:{{startDate}}{{endDate}}</p>
<p>时间:{{startTime}}{{endTime}}</p>
</div>
{{#if end}}
<a class="end">已结束</a>
{{else}}
{{#if needApo}}
{{#if apoStatus}}
<a href="//m.yohobuy.com/activity/trend/class-detail?activityId={{id}}&name={{name}}&price={{price}}&startDate={{startDate}}&endDate={{endDate}}&startTime={{startTime}}&endTime={{endTime}}&status={{status}}&storeId={{storeId}}">立即预约</a>
{{else}}
<a class="disable">已约满</a>
{{/if}}
{{else}}
<a class="any-time">免预约</a>
{{/if}}
{{/if}}
</div>
</div>
</div>
\ No newline at end of file
... ...
<li class="package-item">
<a href="//m.yohobuy.com/activity/trend/package-detail?id={{id}}&type=cutter">
<div class="top clearfix">
<div class="name">{{name}}</div>
<div class="price">
{{#if free}}
免费
{{else}}
<span>¥</span>{{price}}
{{/if}}
</div>
</div>
<div class="main">
<p>{{{summary}}}</p>
</div>
</a>
{{# foot}}
<div class="foot">
<input type="radio" name="package" class="diy" data="{{name}}" id="{{id}}" />
选择套餐
</div>
{{/ foot}}
</li>
... ...
<a class="cutter-item clearfix" href="//m.yohobuy.com/activity/trend/cutter?storeId={{storeId}}&id={{id}}&typeStatus=5&cutterName={{name}}">
{{# radio}}
<input type="radio" name="cutter" class="diy" data={{name}} />
{{/ radio}}
<div class="pic">
<img src="{{image img}}">
</div>
<div class="tip">
<div class="name">{{name}}</div>
<div class="intro">{{level}}</div>
</div>
{{#if noPackage}}
{{else}}
<div class="price">
<span>¥</span>{{#if free}}0{{else}}{{price}}{{/if}}<span></span>
</div>
{{/if}}
{{# arr}}
<span class="iconfont icon-arr">&#xe604;</span>
{{/ arr}}
</a>
\ No newline at end of file
... ...
<div class="date-c clearfix">
<div class="time-nav wrapper clearfix">
<ul class="nav-ul">
<li class="nav-item disable"></li>
<li class="nav-item disable"></li>
{{# dateList}}
<li class="nav-item" data="{{dateOrigin}}" time="{{dateParse}}">
<p>{{date}}</p>
<p>{{week}}</p>
</li>
{{/ dateList}}
<li class="nav-item disable"></li>
<li class="nav-item disable"></li>
</ul>
</div>
<ul class="date-list clearfix"></ul>
<div class="date-type"></div>
</div>
\ No newline at end of file
... ...
<div class="side-main">
<header id="yoho-header" class="yoho-header boys">
<a class="iconfont nav-back"></a>
<p class="nav-title">潮流课堂预约须知</p>
</header>
<p>潮流课堂预约须知</p>
</div>
\ No newline at end of file
... ...
<li class="package-item">
<a href="//m.yohobuy.com/activity/trend/package-detail?id={{id}}">
<div class="top clearfix">
<div class="name">{{name}}</div>
<div class="price">
{{#if free}}
免费
{{else}}
<span>¥</span>{{price}}
{{/if}}
</div>
</div>
<div class="main">
<p>{{{summary}}}</p>
</div>
</a>
{{# foot}}
<div class="foot">
<input type="radio" name="package" class="diy" data="{{name}}" id="{{id}}" limit="{{limit}}" styleId="{{styleId}}" />
选择套餐
</div>
{{/ foot}}
</li>
... ...
/**
* 购物车
* @author: feng.chen<feng.chen@yoho.cn>
* @date: 2016/12/21
*/
'use strict';
const helpers = global.yoho.helpers;
const headerModel = require('../../../doraemon/models/header'); // 头部model
const indexModel = require('../models/index');
/**
* [购物车首页]
*/
const index = (req, res) => {
let isLogin = req.user && req.user.uid,
pageData = {
isLogin,
signurl: helpers.urlFormat('/signin.html', {
refer: '/cart/index/index'
})
};
res.render('index', Object.assign(pageData, {
title: '购物车',
module: 'cart',
page: 'index',
localCss: true,
width750: true,
pageHeader: headerModel.setNav({
navTitle: '购物车',
navBack: true,
suggestSub: {
text: ' '
},
navBtn: false
})
}));
};
/**
* [购物车数据]
*/
const indexData = (req, res, next) => {
if (!req.xhr) {
return next();
}
let shoppingKey = req.cookies._SPK || '',
channel = req.cookies._Channel,
cartType = req.cookies.cartType || 'ordinary',
uid = req.user && req.user.uid;
// shoppingKey = 'dc9d09e2ffd8607f2cfd8b9c95962923';
// uid = 20422448;
return indexModel.indexData(uid, shoppingKey, channel, cartType).then(data => {
data ? res.json({
code: 200,
data
}) : res.status(400).json({
message: '操作失败'
});
}).catch(next);
};
/**
* [选择或者取消商品]
*/
const select = (req, res, next) => {
if (!req.xhr) {
return next();
}
let shoppingKey = req.cookies._SPK || '',
uid = req.user && req.user.uid;
let skuList = req.body.skuList,
cartType = req.cookies.cartType || 'ordinary';
if (!skuList || !skuList.length) {
return res.json({
code: 400,
message: '参数错误'
});
}
// shoppingKey = 'dc9d09e2ffd8607f2cfd8b9c95962923';
// uid = 20422448;
return indexModel.selectGood(uid, skuList, shoppingKey, cartType).then(data => {
data ? res.json({
code: 200,
data
}) : res.status(400).json({
message: '操作失败'
});
}).catch(next);
};
/**
* [移出购物车]
*/
const del = (req, res, next) => {
if (!req.xhr) {
return next();
}
let shoppingKey = req.cookies._SPK || '',
uid = req.user && req.user.uid;
let skuList = req.body.skuList,
cartType = req.cookies.cartType || 'ordinary';
if (!skuList || !skuList.length) {
return res.json({
code: 400,
message: '参数错误'
});
}
// shoppingKey = 'dc9d09e2ffd8607f2cfd8b9c95962923';
// uid = 20422448;
return indexModel.removeFromCart(uid, skuList, shoppingKey, cartType).then(data => {
data ? res.json({
code: 200,
data
}) : res.status(400).json({
message: '操作失败'
});
}).catch(next);
};
/**
* [加入购物车]
*/
const add = (req, res, next) => {
if (!req.xhr) {
return next();
}
let shoppingKey = req.cookies._SPK || '',
uid = req.user && req.user.uid;
let productSku = req.body.productSku,
buyNumber = req.body.buyNumber || 1,
goodsType = req.body.goodsType || 0,
promotionId = req.body.promotionId || 0,
isEdit = req.body.isEdit || 0;
if (!productSku) {
return res.json({
code: 400,
message: '参数错误'
});
}
// shoppingKey = 'dc9d09e2ffd8607f2cfd8b9c95962923';
// uid = 20422448;
return indexModel.addToCart(productSku, buyNumber, goodsType, isEdit, promotionId, uid, shoppingKey).then(data => {
data ? res.json(data) : res.status(400).json({
message: '操作失败'
});
}).catch(next);
};
/**
* [获取购物车数据]
*/
const goodinfo = (req, res, next) => {
if (!req.xhr) {
return next();
}
let result = {};
let uid = req.user && req.user.uid,
buyNum = req.body.buy_num,
mnum = req.body.mnum,
skn = req.body.skn,
promotionId = req.body.promotion_id;
if (!buyNum || !skn) {
return res.json({
code: 400,
message: '参数错误'
});
}
return indexModel.cartProductData(uid, skn, buyNum).then(data => {
return new Promise((resolve) => {
if (mnum && data) {
return indexModel.handleBundleInfo(skn).then(disRes => {
result.discountBuy = disRes;
resolve(data);
});
}
resolve(data);
}).then(cartInfo => {
result.cartInfo = cartInfo;
cartInfo ? res.json(Object.assign({
code: 200,
promotionId: promotionId
}, result)) : res.status(400).json({
message: '操作失败'
});
});
}).catch(next);
};
/**
* [加入收藏]
*/
const col = (req, res, next) => {
if (!req.xhr) {
return next();
}
let uid = req.user && req.user.uid;
let skuList = req.body.skuList,
cartType = req.cookies.cartType || 'ordinary';
if (!skuList || !skuList.length) {
return res.json({
code: 400,
message: '参数错误'
});
}
// shoppingKey = 'dc9d09e2ffd8607f2cfd8b9c95962923';
// uid = 20422448;
if (!uid) {
return res.json({
code: 401,
message: '请先登录',
data: helpers.urlFormat('/signin.html')
});
}
return indexModel.addToFav(uid, skuList, cartType).then(data => {
data ? res.json({
code: 200,
data
}) : res.status(400).json({
message: '操作失败'
});
}).catch(next);
};
/**
* [修改购物车数量]
*/
const modifyNum = (req, res, next) => {
if (!req.xhr) {
return next();
}
let uid = req.user && req.user.uid,
shoppingKey = req.cookies._SPK || '',
sku = req.body.sku,
increaseNum = req.body.increaseNum,
decreaseNum = req.body.decreaseNum;
if (!sku || (!increaseNum && !decreaseNum)) {
return res.json({
code: 400,
message: '参数错误'
});
}
// shoppingKey = 'dc9d09e2ffd8607f2cfd8b9c95962923';
// uid = 20422448;
let promise;
if (increaseNum > 0) {
promise = indexModel.increaseProductNum(uid, sku, increaseNum, shoppingKey);
} else if (decreaseNum > 0) {
promise = indexModel.decreaseProductNum(uid, sku, decreaseNum, shoppingKey);
}
return promise.then(data => {
if (data && data.code === 200 && data.data) {
res.json({
code: 200,
goodsCount: data.data.goods_count
});
} else {
res.json({
code: 400,
message: data.message
});
}
}).catch(next);
};
/**
* [修改购物车数据]
*/
const modify = (req, res, next) => {
if (!req.xhr) {
return next();
}
let uid = req.user && req.user.uid,
shoppingKey = req.cookies._SPK || '';
let oldProductSku = req.body.old_product_sku || 0,
newProductSku = req.body.new_product_sku || 0,
buyNumber = req.body.buy_number || 0,
selected = req.body.selected;
if (!oldProductSku || !newProductSku) {
return res.json({
code: 400,
message: '参数错误'
});
}
// shoppingKey = 'dc9d09e2ffd8607f2cfd8b9c95962923';
// uid = 20422448;
return indexModel.modifyCartProduct(uid, [{
old_product_sku: oldProductSku,
new_product_sku: newProductSku,
buy_number: buyNumber,
selected: selected
}], shoppingKey).then(data => {
data ? res.json(data) : res.status(400).json({
message: '操作失败'
});
}).catch(next);
};
/**
* [修改购物车赠品、加价购数据]
*/
const modifyPriceGift = (req, res, next) => {
if (!req.xhr) {
return next();
}
let uid = req.user && req.user.uid,
shoppingKey = req.cookies._SPK || '';
let newProductSku = req.body.new_product_sku || 0,
newProductSkn = req.body.new_product_skn || 0,
promotionId = req.body.promotionId || 0;
if (!promotionId || !newProductSku) {
return res.json({
code: 400,
message: '参数错误'
});
}
// shoppingKey = 'dc9d09e2ffd8607f2cfd8b9c95962923';
// uid = 20422448;
return indexModel.modifyCartPriceGiftProduct(uid, newProductSku, newProductSkn, promotionId, shoppingKey).then(data => {
data ? res.json(data) : res.status(400).json({
message: '操作失败'
});
}).catch(next);
};
/**
* [获取赠品商品列表]
*/
const gift = (req, res, next) => {
let cartType = req.cookies.cartType || 'ordinary',
promotionIds = req.query.promotion_ids;
if (!promotionIds) {
return next();
}
return indexModel.getPriceGiftList(promotionIds, 'Gift').then(data => {
res.render('gift', Object.assign(data, {
title: '赠品',
module: 'cart',
page: 'gift',
localCss: true,
pageHeader: headerModel.setNav({
navTitle: '赠品',
navBack: true,
suggestSub: {
text: ' '
},
navBtn: false
})
}, {
giftPage: true,
cartType: cartType
}));
}).catch(next);
};
/**
* [获取加价购商品列表]
*/
const advanceBuy = (req, res, next) => {
let cartType = req.cookies.cartType || 'ordinary',
promotionIds = req.query.promotion_ids;
if (!promotionIds) {
return next();
}
return indexModel.getPriceGiftList(promotionIds, 'Needpaygift').then(data => {
res.render('gift', Object.assign(data, {
title: '加价购',
module: 'cart',
page: 'gift',
localCss: true,
pageHeader: headerModel.setNav({
navTitle: '加价购',
navBack: true,
suggestSub: {
text: ' '
},
navBtn: false
})
}, {
advanceBuyPage: true,
cartType: cartType
}));
}).catch(next);
};
/**
* [获取购物车加价购商品数据]
*/
const giftinfo = (req, res, next) => {
if (!req.xhr) {
return next();
}
let skn = req.body.skn,
promotionId = req.body.promotionId;
if (!skn) {
return res.json({
code: 400,
message: '参数错误'
});
}
return indexModel.giftProductData(skn, promotionId).then(data => {
data ? res.json({
promotionId: promotionId,
cartInfo: data
}) : res.status(400).json({
message: '操作失败'
});
}).catch(next);
};
module.exports = {
index,
indexData,
select,
del,
goodinfo,
col,
modifyNum,
add,
modify,
gift,
giftinfo,
advanceBuy,
modifyPriceGift
};
... ...
'use strict';
const _ = require('lodash');
const helpers = global.yoho.helpers;
const co = require('bluebird').coroutine;
const cartModel = require('../models/cart');
const headerModel = require('../../../doraemon/models/header');
const userModel = require('../../serverAPI/user');
const addressModel = require('../../serverAPI/user/address');
const orderModel = require('../models/order');
const crypto = global.yoho.crypto;
const authcode = require(global.utils + '/authcode');
const logger = global.yoho.logger;
// cookie 参数
const actCkOpthn = {
expires: 0,
path: '/cart/index',
domain: 'm.yohobuy.com'
};
exports.orderEnsure = (req, res, next) => {
let headerData = headerModel.setNav({
navTitle: '确认订单',
navBtn: false
});
let uid = req.user.uid;
let returnUrl = helpers.urlFormat('/cart/index/index');
let cartType = req.query.cartType;
let orderInfo;
try {
orderInfo = JSON.parse(req.cookies['order-info']);
} catch (e) {
logger.info(`orderEnsure: get orderInfo from cookie error:${JSON.stringify(e)}`);
orderInfo = {};
res.cookie('order-info', null, actCkOpthn);
}
if (!cartType) {
cartType = _.get(orderInfo, 'cartType', 'ordinary');
}
// 如果传递了code, skn, sku, buy_number 就代表限购商品
let limitProductCode = req.query.limitproductcode || '';
let sku = req.query.sku || '';
let skn = req.query.skn || '';
let buyNumber = req.query.buy_number || 1;
if (limitProductCode) {
headerData.backUrl = req.get('Referer') || returnUrl;
} else {
headerData.backUrl = returnUrl;
}
let orderPromise;
let userProfilePromise = userModel.queryProfile(uid);
let addressPromise = addressModel.addressData(uid);
if (req.query.activityType === 'bundle') {
let activityInfo = JSON.parse(req.cookies['activity-info']);
orderPromise = cartModel.cartPay(uid, cartType, orderInfo, sku, skn, buyNumber, activityInfo);
} else {
orderPromise = cartModel.cartPay(uid, cartType, orderInfo, sku, skn, buyNumber);
}
return Promise.all([orderPromise, userProfilePromise, addressPromise]).then(result => {
let order = result[0];
let userProfile = result[1];
let address = result[2];
if (order.cartUrl) {
logger.info(`orderEnsure: order cartUrl has value:${order.cartUrl}, order data is null`);
return res.redirect(order.cartUrl);
}
if (req.xhr) {
logger.info(`orderEnsure: ajax request, return json:${JSON.stringify(order)}`);
return res.json(order);
}
// 获取用户完整手机号
let mobile = _.get(userProfile, 'data.mobile', '');
let orderAddress = _.get(order, 'address', []);
let addressList = _.get(address, 'data', []);
orderAddress.length && _.forEach(addressList, address => { //eslint-disable-line
if (address.address_id === orderAddress.address_id) {
mobile = address.mobile;
return false;
}
});
let viewData = {
orderEnsurePage: true,
isOrdinaryCart: cartType !== 'advance',
orderEnsure: _.assign(order, {
isOrdinaryCart: cartType !== 'advance'
}),
userMobile: mobile,
pageHeader: headerData,
pageFooter: false,
module: 'cart',
page: 'order-ensure',
width750: true,
title: '确认订单'
};
res.render('order-ensure', viewData);
}).catch(next);
};
/**
* 购物车选择改变字段,重新运算订单数据
*/
exports.orderCompute = (req, res, next) => {
let cartType = req.body.cartType || 'ordinary';
let deliveryId = req.body.deliveryId || 1;
let paymentTypeId = req.body.paymentTypeId || 1;
let couponCode = req.body.couponCode || null;
let yohoCoin = req.body.yohoCoin || null;
let productSku = req.body.productSku || null;
let buyNumber = req.body.buyNumber || null;
let uid = req.user.uid;
let skuList = req.body.skuList;
let type = req.body.type;
if (type !== 'tickets') {
if (req.body.activityType === 'bundle') {
let activityInfo = JSON.parse(req.cookies['activity-info']);
cartModel.orderCompute(uid, cartType, deliveryId, paymentTypeId, couponCode, yohoCoin, null, activityInfo).then(result => {
res.json(result);
}).catch(next);
} else {
cartModel.orderCompute(uid, cartType, deliveryId, paymentTypeId, couponCode, yohoCoin, skuList).then(result => {
res.json(result);
}).catch(next);
}
} else {
cartModel.ticketsOrderCompute(uid, productSku, buyNumber, yohoCoin).then(result => {
res.json(result);
}).catch(next);
}
};
/**
* 确认结算订单
*/
exports.orderSub = (req, res, next) => {
let uid = req.user.uid;
let addressId = parseInt(crypto.decrypt('', req.body.addressId), 10);
let cartType = req.body.cartType || 'ordinary';
let deliveryTimeId = req.body.deliveryTimeId || 1;
let deliveryId = req.body.deliveryId || 1;
let paymentTypeId = req.body.paymentTypeId || 15;
let paymentType = req.body.paymentType || 1;
let msg = req.body.msg || null;
let couponCode = req.body.couponCode || null;
let yohoCoin = req.body.yohoCoin || 1;
let skuList = req.body.skuList || '';
let orderInfo;
try {
orderInfo = JSON.parse(req.cookies['order-info']);
} catch (e) {
orderInfo = {};
res.cookie('order-info', null, actCkOpthn);
}
let times = req.body.times || 1;
// 电子发票信息数组
let invoices = {};
if (orderInfo) {
invoices = {
invoices_type_id: orderInfo.invoiceType,
invoices_type: orderInfo.invoicesType,
receiverMobile: orderInfo.receiverMobile,
invoices_title: orderInfo.invoiceText ? orderInfo.invoiceText : '个人'
};
}
/* 判断是否是友盟过来的用户 */
let userAgent = null;
let unionKey = '';
let unionInfo = {};
if (req.cookies.mkt_code || req.cookies._QYH_UNION) {
/*
*1、http://union.yohobuy.com/go?client_id=3415&aid=0118&channel=3415&cid=3601&wi=NDgwMDB8dGVzdA==&target=http://m.yohobuy.com/
*2、http://union.yoho.cn/union/jump?channel_id=51fanli&u_id=6&tracking_code=fanli123&target_url=http%3a%2f%2fm.yohobuy.com%3funion_type%3d3063%26utm_source%3dmfanli%26utm_medium%3dcps%26utm_campaign%3dmpfanli
*3、union.yohobuy.com/go/proxy?utm_medium=none&utm_campaign=none&client_id=991002&ads_code=&go_url=https%253A%252F%252Fm.yohobuy.com%252F%253Futm_source%253Dhyyx%2526utm_medium%253Dnone%2526utm_campaign%253Dnone%2526union_type%253D991002&channel_code=hyyx&append=&mbr_name=&u_id=&aid=&channel=cps&cid=&wi=
**/
/* tar modified 161108 添加新的联盟数据处理逻辑,兼容原有联盟数据处理,
区别是旧的北京写 cookie 加密过来,新的 node 写 cookie,没有加密 */
if (req.cookies._QYH_UNION) {
unionKey = authcode(req.cookies._QYH_UNION, 'q_union_yohobuy');
if (!unionKey) {
let encryData = crypto.decrypt('', decodeURIComponent(req.cookies._QYH_UNION));
encryData = encryData.substr(0, encryData.lastIndexOf('}') + 1);
let testQyhUnion = JSON.parse(encryData);
unionKey = testQyhUnion.client_id ? encryData : '';
}
} else {
unionKey = '{"client_id":' + req.cookies.mkt_code + '}';
}
/* 检查联盟参数是否有效 */
unionInfo = unionKey ? JSON.parse(unionKey) : {};
/* 模拟APP的User-Agent */
userAgent = unionInfo.client_id ? 'YOHO!Buy/3.8.2.259(Model/PC;Channel/' +
unionInfo.client_id + ';uid/' + uid + ')' : null;
}
return co(function* () {
let result;
/* tar modified 161206 套餐 */
if (req.body.activityType === 'bundle') {
let activityInfo = JSON.parse(req.cookies['activity-info']);
result = yield cartModel.orderSub(uid, addressId, 'bundle', deliveryTimeId,
deliveryId, invoices, paymentTypeId, paymentType, msg, couponCode,
yohoCoin, null, unionKey, userAgent, times, activityInfo);
} else {
result = yield cartModel.orderSub(uid, addressId, cartType, deliveryTimeId,
deliveryId, invoices, paymentTypeId, paymentType, msg, couponCode,
yohoCoin, skuList, unionKey, userAgent);
}
if (unionInfo && result.data) {
result.data.unionCookie = unionInfo;
} else {
logger.info(`orderEnsure: unionInfo:${JSON.stringify(unionInfo)}, result data:${JSON.stringify(result.data)}`);
}
// 提交成功清除Cookie
orderInfo = {};
res.cookie('order-info', null, actCkOpthn);
if (result.code === 409) {
return res.json(decodeURI(result));
} else {
return res.json(result);
}
})().catch(next);
};
/**
* 下单流程 选择优惠券
*/
exports.selectCoupon = (req, res) => {
let headerData = headerModel.setNav({
navTitle: '选择优惠券',
backUrl: helpers.urlFormat('/cart/index/new/orderEnsure', {cartType: req.cookies._cartType}),
navBtn: false
});
res.render('select-coupon', {
module: 'cart',
page: 'select-coupon',
title: '选择优惠券',
selectCouponPage: true,
pageHeader: headerData,
pageFooter: true
});
};
/**
* 购物车结算--获取优惠券列表
*/
exports.couponList = (req, res, next) => {
let uid = req.user.uid;
if (req.xhr) {
return cartModel.getCouponList(uid)
.then(data => {
res.json(data);
}).catch(next);
} else {
return next();
}
};
/**
* 购物车输入优惠券码使用优惠券
*/
exports.couponSearch = (req, res, next) => {
let couponCode = req.body.couponCode || '';
let uid = req.user.uid;
co(function* () {
if (req.xhr) {
let result = yield cartModel.searchCoupon(uid, couponCode);
res.json(result);
} else {
return next();
}
})().catch(next);
};
/**
* 选择地址
*/
exports.selectAddress = (req, res, next) => {
let uid = req.user.uid;
return addressModel.addressData(uid).then(address => {
let moreUrl = (req.get('Referer') && !/\/home\/addressAct/.test(req.get('Referer')) &&
!/selectAddress/.test(req.get('Referer'))) ?
req.get('Referer') : helpers.urlFormat('/cart/index/new/orderEnsure', {cartType: req.cookies._cartType}); // 取跳过来的url
address = address.data;
// 购物车订单进来,秒杀进来
if (
moreUrl.indexOf('/cart/index/new/orderEnsure') !== -1 ||
moreUrl.indexOf('/cart/index/seckill') !== -1
) {
req.session.addressMore = moreUrl; // TODO: 注意cookie-session
}
// moreUrl = req.session.addressMore;
let headerData = headerModel.setNav({
navTitle: '选择地址',
navBtn: false,
backUrl: moreUrl
});
res.render('select-address', {
module: 'cart',
page: 'select-address',
pageHeader: headerData,
pageFooter: true,
moreUrl,
address
});
}).catch(next);
};
/**
* 发票信息
*/
exports.invoiceInfo = (req, res, next) => {
let uid = req.user.uid;
let cookieData = req.cookies['order-info'];
let orderInfo = JSON.parse(cookieData);
co(function* () {
let userData = yield userModel.queryProfile(uid);
let mobile = _.get(userData, 'data.mobile', '');
let addresslist = yield userModel.addressTextData(uid);
let returnData = orderModel.processInvoiceData(orderInfo, mobile, addresslist);
let headerData = headerModel.setNav({
navTitle: '发票信息',
navBtn: false
});
res.render('select-invoice', _.assign(returnData, {
pageHeader: headerData,
module: 'cart',
page: 'select-invoice'
}));
})().catch(next);
};
/**
* JIT 拆单配送信息页面
*/
exports.jitDetail = (req, res, next) => {
let cartType = req.query.cartType;
let headerData = headerModel.setNav({
navTitle: '配送信息',
navBtn: false
});
cartModel.jitDetailData(
req.user.uid,
cartType,
req.query.skuList,
req.query.orderCode,
req.session.TOKEN,
req.query.deliveryId,
req.query.paymentType,
req.query.couponCode,
req.query.yohoCoin
).then(result => {
if (cartType) {
_.assign(headerData, {
backUrl: result.returnUrl
});
}
res.render('jit-detail', _.assign(result, {
pageHeader: headerData,
jitDetailPage: true,
module: 'cart',
page: 'jit-detail',
}));
}).catch(next);
};
... ...
/**
* 支付成功页
* @author: jing.li<jing.li@yoho.cn>
* @date: 2016/10/25
/*
* 支付
* @Author: Targaryen
* @Date: 2017-01-04 15:17:51
* @Last Modified by: Targaryen
* @Last Modified time: 2017-02-20 18:16:09
*/
'use strict';
const mRoot = '../models';
const payModel = require(`${mRoot}/pay`);
const payTool = payModel.payTool;
const headerModel = require('../../../doraemon/models/header'); // 头部model
const co = require('bluebird').coroutine;
const helpers = global.yoho.helpers;
const Payment = require('../helpers/payment');
const WxPay = require('../helpers/pay/wechat');
const common = require('../helpers/pay/common');
const logger = global.yoho.logger;
/**
* 支付中心
* @param req
* @param res
* @param next
*/
const payCenter = (req, res, next) => {
let orderCode = req.query.order_code;
let uid = req.user.uid;
let sessionKey = req.session.TOKEN;
let userAgent = req.get('User-Agent');
let hasWxShare = Boolean(userAgent.match(/MicroMessenger/i) && userAgent.match(/MicroMessenger/i).length > 0);
if (!orderCode || !uid) {
logger.info(`payCenter:no orderCode or uid:orderCode ${orderCode}, uid ${uid}`);
res.redirect('/');
}
if (sessionKey) {
sessionKey = sessionKey.substr(0, sessionKey.length - 8);
} else {
logger.info(`payCenter: orderCode-${orderCode} no sessionKey`);
}
co(function* () {
let orderDetail = yield payModel.payCenter({
orderCode: orderCode,
uid: uid,
sessionKey: sessionKey
});
/* 判断订单是否已付款, 已付款跳到订单详情页 */
if (orderDetail.payment_status === 'Y') {
logger.info(`payCenter: orderCode-${orderCode} already paied`);
return res.redirect(helpers.urlFormat('/cart/shopping/pay/payZero', {order_code: orderCode}));
}
if (hasWxShare) {
let openId = req.cookies['weixinOpenId' + orderCode];
if (!openId) {
let getOpenidResult = yield WxPay.getOpenid(req.query.code, req.originalUrl);
if (getOpenidResult.openid) {
openId = getOpenidResult.openid;
}
if (getOpenidResult.redirectUrl) {
return res.redirect(getOpenidResult.redirectUrl);
}
if (openId) {
res.cookie('weixinOpenId' + orderCode, openId, {
domain: 'yohobuy.com',
expires: new Date(Date.now() + 24 * 60 * 60 * 1000)
});
}
}
}
let responseData = {
pageHeader: headerModel.setNav({
navTitle: '支付中心',
backUrl: 'javascript:void(0);'
}),
module: 'cart',
page: 'pay',
title: '支付中心 | Yoho!Buy有货 | 潮流购物逛不停',
payAppInfo: payTool.payAppInfo(orderCode),
orderCode: orderCode,
hasWxShare: hasWxShare,
orderTotal: orderDetail.payment_amount || 0,
orderTotalFormat: parseInt(orderDetail.payment_amount, 10),
orderCount: payTool.calBuyNumCount(orderDetail.order_goods),
uid: uid,
isOldUser: Boolean(req.cookies._isOldUser && req.cookies._isOldUser === '4')
};
res.render('pay/pay-center', responseData);
})().catch(next);
};
/**
* 统一支付入口
* @param req
* @param res
*/
const pay = (req, res, next) => {
let orderCode = req.query.order_code;
let user = req.user;
let uid = req.user.uid;
let sessionKey = req.session.TOKEN;
let payment = req.query.payment;
let paymentCode = common.getPaymentCode(payment);
let openId = req.cookies['weixinOpenId' + orderCode];
let ip = req.ip;
if (ip.substr(0, 7) === '::ffff:') {
ip = ip.substr(7);
}
if (!orderCode || !uid) {
return res.redirect('/');
}
co(function* () {
let orderDetail = yield payModel.getOtherDetail({
uid: uid,
orderCode: orderCode,
sessionKey: sessionKey
});
if (!orderDetail || !orderDetail.data) {
return res.json({
code: 400,
msg: '没有找到该订单!'
});
}
if (orderDetail.data.is_cancel === 'Y') {
let url = helpers.urlFormat('/home/orders/detail', { order_code: orderCode });
return res.json({
code: 400,
msg: '订单已经取消'
}).redirect(url);
}
Payment.pay(user, orderDetail.data, payment, {
protocol: req.protocol,
openId: openId,
ip: ip
}).then(result => {
if (result && paymentCode === payModel.payments.wechat) {
return res.json(result);
}
if (result && result.data && result.data.href && paymentCode === payModel.payments.alipay) {
return res.redirect(result.data.href);
} else {
return res.redirect('/');
}
});
})().catch(next);
};
// 货到付款
const payCod = (req, res, next) => {
... ... @@ -23,12 +177,16 @@ const payCod = (req, res, next) => {
title: '支付中心 | Yoho!Buy有货 | 潮流购物逛不停'
};
let sessionKey = req.session.TOKEN;
let param = {
uid: req.user.uid,
udid: req.sessionID || require('md5')(req.ip) || 'yoho',
orderCode: req.query.order_code,
contentCode: '78d0fb6c97d691863286edcb4d8abfa9',
client_id: req.cookies._yasvd || ''
client_id: req.cookies._yasvd || '',
sessionKey: sessionKey && sessionKey.substr(0, sessionKey.length - 8) || ''
};
// 如果没有uid,跳转到首页
... ... @@ -47,7 +205,7 @@ const payCod = (req, res, next) => {
}).catch(next);
};
// 支付宝支付
// 支付宝支付结果页
const payAli = (req, res, next) => {
let headerData = headerModel.setNav({
navTitle: '支付完成'
... ... @@ -111,6 +269,14 @@ const payZero = (req, res, next) => {
title: '支付中心 | Yoho!Buy有货 | 潮流购物逛不停'
};
let responseFailure = {
pageHeader: headerModel.setNav({
navTitle: '支付中心',
navBtn: false
}),
title: '支付中心 | Yoho!Buy有货 | 潮流购物逛不停'
};
let param = {
uid: req.user.uid,
udid: req.sessionID || require('md5')(req.ip) || 'yoho',
... ... @@ -126,8 +292,13 @@ const payZero = (req, res, next) => {
}
payModel.getPayAli(param).then(result => {
if (result.match === true) {
res.render('pay/pay-ali', Object.assign(responseData, result));
if (result.isCancel && result.isCancel === true) {
return res.render('pay/pay-failure', responseFailure);
} else {
res.render('pay/pay-ali', Object.assign(responseData, result));
}
} else {
res.redirect('/');
}
... ... @@ -136,6 +307,8 @@ const payZero = (req, res, next) => {
};
module.exports = {
payCenter,
pay,
payCod,
payAli,
payZero
... ...
... ... @@ -2,6 +2,7 @@
* 秒杀结算
*/
'use strict';
const _ = require('lodash');
const crypto = global.yoho.crypto;
const co = require('bluebird').coroutine;
const seckillModel = require('../models/seckill');
... ... @@ -38,6 +39,10 @@ exports.ensure = (req, res, next) => {
uid
};
let skillData = yield seckillModel.skillData(skn); // 根据skn查活动信息
let view = {
orderEnsure: false,
message: ''
};
skillData = skillData.data;
... ... @@ -50,14 +55,31 @@ exports.ensure = (req, res, next) => {
skillData &&
skillData.secKillSku.some(obj => obj.productSku === sku) // skn has sku;
)) {
return Promise.reject('活动不存在');
view.message = '挤爆啦,系统繁忙';
return res.render('order-ensure', Object.assign({
module: 'cart',
page: 'seckill',
pageHeader: headerModel.setNav({
navTitle: '确认订单',
backUrl: '/product/show_' + skn + '.html'
}),
}, view));
}
paymentOption.activity_id = activityId = skillData.activityId;
let orderComputerData;
if (orderInfo) {
orderComputerData = yield seckillModel.compute(_.assign(paymentOption, {
delivery_way: orderInfo.deliveryId,
payment_type: orderInfo.paymentType,
use_yoho_coin: orderInfo.yohoCoin
}));
}
// 获取结算 数据
let paymentInfo = yield seckillModel.payment(paymentOption, orderInfo);
let view;
let paymentInfo = yield seckillModel.payment(paymentOption, orderInfo, orderComputerData.data);
if (paymentInfo.code !== 200) {
view = {
... ... @@ -158,8 +180,8 @@ exports.submit = (req, res, next) => {
}
if ([uid, sku, activityId, addressId, deliveryTime,
deliveryWay, paymentId, paymentType
].some(field => !field)) {
deliveryWay, paymentId, paymentType
].some(field => !field)) {
return res.status(400).json({
code: 400,
message: BAD_REQUEST
... ...
/**
* TAR NOTE: 从 YOHO-BLK 项目复制,未针对本项目做适配
* @author: jiangfeng<jeff.jiang@yoho.cn>
* @date: 16/7/22
*/
'use strict';
const config = global.yoho.config;
const helpers = global.yoho.helpers;
const common = require('./common');
const sign = require('./sign');
const payHelpersBank = require('./bank');
const md5 = require('md5');
const logger = global.yoho.logger;
const ALIPAY_URL = 'https://mapi.alipay.com/gateway.do';
const Alibank = {
pay(user, order, param, protocol) {
let payParams = JSON.parse(param.payParams);
let extraParam = JSON.stringify({
sign_id_ext: user.uid,
defaultbank: param.bankCode || ''
});
let params = {
service: 'create_direct_pay_by_user',
partner: payParams.merchant_id,
_input_charset: 'utf-8',
notify_url: config.pay.serviceNotify + 'payment/alipay_notify',
return_url: protocol + ':' + helpers.urlFormat('/shopping/pay/callback/alibank'),
subject: 'BLK订单号:' + order.order_code,
out_trade_no: order.order_code,
it_b_pay: common.getPayExpireMin(order.pay_expire) + 'm',
total_fee: order.payment_amount,
payment_type: '1',
defaultbank: param.bankCode,
seller_email: payParams.merchant_other_code,
extra_common_param: extraParam
};
// TODO 防钓鱼配置,参考php
let signStr = md5(sign.raw(params) + payParams.merchant_key);
let body = sign.rawUncode(params) + '&sign=' + signStr + '&sign_type=MD5';
return {
code: 200,
data: {
href: ALIPAY_URL + '?' + body
}
};
},
notify(data, param) {
let payParams = param.payParams && JSON.parse(param.payParams) || {};
let orderCode = parseInt(data.out_trade_no, 10);
let extraParam = data.extra_common_param && JSON.parse(data.extra_common_param) || {};
let bankName = payHelpersBank.getList()[extraParam.defaultbank] &&
payHelpersBank.getList()[extraParam.defaultbank].name || '';
logger.info(`Alibank notify, params = ${JSON.stringify(data)}`);
if (!this.checkNotify(data, payParams)) {
return {payResult: -1, bankName: bankName};
} else {
return {
bankName: bankName,
orderCode: orderCode,
payResult: data.trade_status === 'TRADE_SUCCESS' ? 200 : 400,
payTime: data.gmt_payment || '',
totalFee: data.total_fee,
resultMsg: data.notify_type,
payOrderCode: orderCode,
tradeNo: data.trade_no,
bankBillNo: data.bank_seq_no || ''
};
}
},
checkNotify(data, payParams) {
let signValue = data.sign;
if (!payParams || !data) {
return false;
}
delete data.sign;
delete data.sign_type;
delete data.code;
let signStr = md5(sign.raw(data) + payParams.merchant_key);
return signValue === signStr;
}
};
module.exports = Alibank;
... ...
/**
*
* @author: jiangfeng<jeff.jiang@yoho.cn>
* @date: 16/7/22
*/
'use strict';
const config = global.yoho.config;
const helpers = global.yoho.helpers;
const sign = require('./sign');
const md5 = require('md5');
const moment = require('moment');
const logger = global.yoho.logger;
const AlipayConfig = config.alipayConfig;
const Alipay = {
pay(user, order, param, protocol) {
let params = {
service: AlipayConfig.service,
partner: AlipayConfig.partner,
_input_charset: AlipayConfig.inputCharset,
notify_url: AlipayConfig.notifyUrl,
return_url: protocol + ':' + helpers.urlFormat(AlipayConfig.returnUrl),
subject: '有货订单号:' + order.order_code,
out_trade_no: order.order_code,
it_b_pay: moment(order.pay_expire).format('YYYY-MM-DD HH:mm'),
total_fee: parseFloat(order.payment_amount),
seller_id: AlipayConfig.partner,
payment_type: '1',
show_url: protocol + ':' + helpers.urlFormat('/home/orderdetail', { order_code: order.order_code })
};
// TODO 防钓鱼配置,参考php
let signStr = md5(sign.raw(params) + AlipayConfig.alipayKey);
let body = sign.rawUncode(params) + '&sign=' + signStr + '&sign_type=MD5';
return {
code: 200,
data: {
href: AlipayConfig.payUrl + '?' + body
}
};
},
notify(data, param) {
let payParams = JSON.parse(param.payParams);
logger.info(`Alipay notify, params = ${JSON.stringify(data)}`);
if (!this.checkNotify(data, payParams)) {
return { payResult: -1 };
} else {
let orderCode = parseInt(data.out_trade_no, 10);
return {
bankName: '',
orderCode: orderCode,
payResult: data.trade_status === 'TRADE_SUCCESS' ? 200 : 400,
payTime: data.gmt_payment || '',
totalFee: data.total_fee,
resultMsg: data.notify_type,
payOrderCode: orderCode,
tradeNo: data.trade_no,
bankBillNo: ''
};
}
},
checkNotify(data, payParams) {
let signValue = data.sign;
delete data.sign;
delete data.sign_type;
delete data.code;
let signStr = md5(sign.raw(data) + payParams.merchant_key);
return signValue === signStr;
}
};
module.exports = Alipay;
... ...
/**
* Created by TaoHuang on 2016/7/18.
*/
'use strict';
const Bank = {
getList() {
return {
BOCB2C: {
name: '中国银行',
ico: '//static.yohobuy.com/images/pay/icon/zhongguo.png'
},
ABC: {
name: '中国农业银行',
ico: '//static.yohobuy.com/images/pay/icon/nongye.png'
},
SPABANK: {
name: '平安银行',
ico: '//static.yohobuy.com/images/pay/icon/pingan.png'
},
CMBC: {
name: '中国民生银行',
ico: '//static.yohobuy.com/images/pay/icon/minsheng.png'
},
ICBCB2C: {
name: '中国工商银行',
ico: '//static.yohobuy.com/images/pay/icon/gongshang.png'
},
SPDB: {
name: '浦发银行',
ico: '//static.yohobuy.com/images/pay/icon/pufa.png'
},
BJRCB: {
name: '北京农商银行',
ico: '//static.yohobuy.com/images/pay/icon/beijingnongshang.png'
},
HZCBB2C: {
name: '杭州银行',
ico: '//static.yohobuy.com/images/pay/icon/hangzhou.png'
},
CMB: {
name: '招商银行',
ico: '//static.yohobuy.com/images/pay/icon/zhaoshang.png'
},
CIB: {
name: '兴业银行',
ico: '//static.yohobuy.com/images/pay/icon/xingye.png'
},
FDB: {
name: '富滇银行',
ico: '//static.yohobuy.com/images/pay/icon/fudian.png'
},
CEBDEBIT: {
name: '中国光大银行',
ico: '//static.yohobuy.com/images/pay/icon/guangda.png'
},
CCB: {
name: '中国建设银行',
ico: '//static.yohobuy.com/images/pay/icon/zhongguojianshe.png'
},
GDB: {
name: '广发银行',
ico: '//static.yohobuy.com/images/pay/icon/guangfa.png'
},
POSTGC: {
name: '中国邮政储蓄',
ico: '//static.yohobuy.com/images/pay/icon/zhongguoyouzhengchuxu.png'
},
SHBANK: {
name: '上海银行',
ico: '//static.yohobuy.com/images/pay/icon/shanghai.png'
},
NBBANK: {
name: '宁波银行',
ico: '//static.yohobuy.com/images/pay/icon/ningbo.png'
}
};
}
};
module.exports = Bank;
... ...
/**
*
* @author: jiangfeng<jeff.jiang@yoho.cn>
* @date: 16/7/22
*/
'use strict';
const moment = require('moment');
const xml2js = require('xml2js');
const common = {
getPayExpireMin(expire) {
let defaultValue = 120;
if (expire) {
let expireTime = moment(expire, 'YYYY-MM-DD HH:mm:ss');
let diff = expireTime.diff(moment());
return Math.floor(diff / 1000 / 60);
// if (diff > 0) {
// return Math.floor(diff / 1000 / 60);
// } else {
// return 0;
// }
} else {
return defaultValue;
}
},
getPayExpireCouple(expire) {
let start = expire ? moment(expire, 'YYYY-MM-DD HH:mm:ss') : moment();
let end = expire ? moment(expire, 'YYYY-MM-DD HH:mm:ss') : moment();
return {
start: start.subtract(2, 'hours'),
end: end.add(5, 'minutes')
};
},
nonceStr(length) {
length = length || 32;
let chars = 'abcdefghijklmnopqrstuvwxyz0123456789';
let str = '';
for (let i = 0; i < length; i++) {
str += chars[parseInt(Math.random() * length, 10)];
}
return str;
},
toXml(obj, root) {
let xmlBuilder = new xml2js.Builder({
rootName: root || 'xml'
});
return xmlBuilder.buildObject(obj);
},
xml2Obj(xml) {
let xmlParser = new xml2js.Parser({
trim: true,
explicitArray: false
});
return new Promise((resolve, reject) => {
xmlParser.parseString(xml, (err, result) => {
if (err) {
reject(err);
} else {
resolve(result);
}
});
});
},
getPaymentCode(payment) {
let paymentPars = payment.split('_');
if (paymentPars.length !== 2) {
return false;
} else {
return paymentPars[0] * 1;
}
}
};
module.exports = common;
... ...
/**
*
* @author: jiangfeng<jeff.jiang@yoho.cn>
* @date: 16/7/22
*/
'use strict';
const Sign = {
raw(args) {
let keys = Object.keys(args);
keys = keys.filter(k => {
return args[k] === '' || args[k] === 'undefined' ? false : true;
}).sort();
return keys.map(k => {
return k + '=' + decodeURI(args[k]);
}).join('&');
},
rawUncode(args) {
let keys = Object.keys(args);
keys = keys.filter(k => {
return args[k] === '' || args[k] === 'undefined' ? false : true;
}).sort();
return keys.map(k => {
return k.toLowerCase() + '=' + args[k];
}).join('&');
}
};
module.exports = Sign;
... ...