Authored by jinhu.tung

Merge branch 'develop' of git.yoho.cn:fe/yoho-blk into develop

Showing 100 changed files with 1622 additions and 934 deletions

Too many changes to show.

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

... ... @@ -51,7 +51,7 @@ app.engine('.hbs', hbs({
app.use(favicon(path.join(__dirname, '/public/favicon.ico')));
app.use(express.static(path.join(__dirname, 'public')));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: false}));
app.use(bodyParser.urlencoded({extended: true}));
app.use(cookieParser());
app.use(multer());
... ...
... ... @@ -29,7 +29,7 @@ const index = (req, res, next) => {
let reg = /(\d{3})\d{4}(\d{4})/;
for (let i = 0; i < length; i++) {
resultData[i].mobile = resultData[i].mobile.replace(reg, "$1****$2");
resultData[i].mobile = resultData[i].mobile.replace(reg, '$1****$2');
}
resultData.leftLength = 7 - length;
resultData.length = length;
... ...
... ... @@ -28,7 +28,7 @@ const index = (req, res, next) => {
currencyModel.getIndexData(uid, page, queryType, beginTime).then(result=> {
result.list.tabs[queryType].isActive = true;
result.list.coinList.forEach(function (x) {
result.list.coinList.forEach(function(x) {
x.date = x.date.replace(/\-/g, '.');
});
result.list.selects[selectIndex].isSelected = 'selected';
... ...
... ... @@ -58,9 +58,7 @@ const getOrderList = (req, res) => {
page: 'order',
isMe: true,
orderList: result.order.orderList,
paginationOpts: result.order.paginationOpts,
emptyMsg: result.order.emptyMsg,
showEmptyEn: result.order.showEmptyEn
orderData: result.order
});
});
};
... ...
... ... @@ -13,7 +13,7 @@ const _ = require('lodash');
* 退换货列表页
*/
const index = (req, res, next) => {
const uid = global.yoho.uid;
const uid = req.user.uid;
const page = req.query.page;
returns.getUserReturn(uid, page).then(result => {
... ... @@ -95,7 +95,7 @@ const refundDetail = (req, res, next) => {
*/
const exchange = (req, res, next) => {
const code = req.params.orderCode;
const uid = req.user.uid || 8050882;
const uid = req.user.uid;
returns.getChangeGoodsList(code, uid).then(result => {
res.display('index', {
... ... @@ -158,7 +158,7 @@ const exchangeDeatail = (req, res) => {
* 换货申请提交
*/
const exchangeSubmit = (req, res, next) => {
const uid = req.user.uid || '8050882';
const uid = req.user.uid;
returns.submitChange(req.query, uid).then(result => {
res.json(result);
... ...
... ... @@ -12,13 +12,14 @@ const accountModel = require('../models/account');
const passportHelper = require('../../passport/models/passport-helper');
const Promise = require('bluebird');
const co = Promise.coroutine;
const regMobile = /(\d{3})\d{4}(\d{4})/;//正则匹配替换手机号码中间4位
var fs = require('fs');
var path = require('path');
const uuid = require('uuid');
const os = require('os');
const regMobile = /(\d{3})\d{4}(\d{4})/;// 正则匹配替换手机号码中间4位
const captchaUrl = helpers.urlFormat('/passport/images', {t: Date.now()});
// const captchaUrl = 'http://localhost:6003/passport/images?t=' + new Date().getTime();
// 根据type获取标题
const _getTitle = (type)=> {
let typeName;
... ... @@ -80,8 +81,9 @@ const index = (req, res, next) => {
result.info.gender ? result.genders[result.info.gender - 1].checked = true :
result.genders[2].checked = true;
result.info.head_ico = result.info.head_ico ? helpers.image(result.info.head_ico, 400, 300, 2) : '';
result.info.mobile = result.info.mobile ? result.info.mobile.replace(regMobile, "$1****$2") : '';
result.info.mobile = result.info.mobile ? result.info.mobile.replace(regMobile, '$1****$2') : '';
result.stepUrl = '/me/setting/step1';
res.display('index', {
module: 'me',
page: 'setting',
... ... @@ -125,7 +127,7 @@ const bindMobile = (req, res, next) => {
if (result.info.verify_mobile !== '') {
let info = result.info;
info.ellipsisMobile = info.verify_mobile.replace(regMobile, "$1****$2");
info.ellipsisMobile = info.verify_mobile.replace(regMobile, '$1****$2');
info.checkCode = settingModel.cipheriv(info.uid + '.completeverify');
res.display('index', {
... ... @@ -350,6 +352,40 @@ const validate2 = (req, res)=> {
})();
};
/**
* 文件处理中间件
* @param req
* @param res
* @param next
*/
function getfilePath(req, res, next) {
const fid = uuid.v4();
const filePath = path.join(os.tmpdir(), fid);
const uploadStream = fs.createWriteStream(filePath);
req.filePath = filePath;
req.pipe(uploadStream);
uploadStream.on('finish', function() {
next();
});
}
/**
* 修改头像
* @param req
* @param res
*/
const modifyHead = (req, res)=> {
let uid = req.user.uid || '8041246';
let bucket = 'yhb-head';
let filePath = req.filePath;
settingModel.modifyHead(uid, bucket, filePath).then(result=> {
res.send(result);
});
};
module.exports = {
index,
editUserInfo,
... ... @@ -359,5 +395,7 @@ module.exports = {
edit,
success,
validate1,
validate2
validate2,
getfilePath,
modifyHead
};
... ...
... ... @@ -9,6 +9,7 @@ var express = require('express'),
path = require('path'),
hbs = require('express-handlebars');
var app = express();
// set view engin
... ... @@ -28,6 +29,7 @@ app.engine('.hbs', hbs({
helpers: global.yoho.helpers
}));
// router
app.use(require('./router'));
... ...
... ... @@ -220,6 +220,7 @@ const _getUserOrder = (uid, type, page) => {
let total = false;
let curPage = 1;
if (result && result.data) {
orderList = camelCase(result.data.order_list);
total = result.data.total;
... ... @@ -229,6 +230,29 @@ const _getUserOrder = (uid, type, page) => {
orderList.forEach(item => {
const ot = parseInt(item.orderType, 10);
const st = parseInt(item.status, 10);
let hasRefund = false;
let canRefund = false;
item.orderGoods.forEach(good => {
let cnAlphabet = good.cnAlphabet ? good.cnAlphabet : '';
good.goodUrl = helpers.urlFormat(`/product/pro_${good.productId}_${good.goodsId}/${cnAlphabet}.html`);
// 判断该订单是否有换货商品
if (good.refundNum) {
hasRefund = true;
good.changed = true;
good.returnUrl = helpers.urlFormat('/me/return');
// 判断该订单是否可以退换货
} else if (good.buyNumber !== good.refund) {
canRefund = true;
}
});
item.showRefund = hasRefund;
item.hideChange = !canRefund;
// 转换订单创建时间
item.createTime = _convertUnixTime(item.createTime);
... ... @@ -252,6 +276,7 @@ const _getUserOrder = (uid, type, page) => {
// 在线支付和货到付款有按钮的差异
item.isOnlinePaid = parseInt(item.paymentType, 10) === 1;
item.isRefundOrder = ot === 7;
if (item.isCancel === 'Y') {
item.showBuyBtn = true;
... ... @@ -269,9 +294,9 @@ const _getUserOrder = (uid, type, page) => {
});
return {
orderList: orderList,
total: total,
curPage: curPage
orderList,
total,
curPage
};
});
};
... ... @@ -325,22 +350,28 @@ const getOrderData = (uid, type, page) => {
typeStr: 'paying'
},
{
text: '待货',
text: '待货',
typeStr: 'delivering'
}
]
};
const emptyMsg = {
const emptyObject = {
1: {
text: '您暂时还没有订单',
showEmptyEn: true
emptyMsg: '暂时还没有订单哦~',
showEmptyEn: true,
btnText: '去首页看看',
url: '/'
},
2: {
text: '您暂时还没有待付款的订单'
emptyMsg: '没有待付款的订单哦~',
btnText: '查看全部订单',
url: '/me/'
},
3: {
text: '您暂时还没有待收货的订单'
emptyMsg: '没有待收货的订单哦~',
btnText: '查看全部订单',
url: '/me/'
}
};
... ... @@ -358,10 +389,7 @@ const getOrderData = (uid, type, page) => {
type: type
};
const empty = {
showEmptyEn: emptyMsg[type].showEmptyEn,
emptyMsg: emptyMsg[type].text
};
const empty = emptyObject[type];
navBar.tabs[typeActiveIndexMap[type]].isActive = true;
... ...
/**
* 商品基本信息
* 退换货API
* @author: yyq<yanqing.yang@yoho.cn>
* @date: 2016/7/19
*/
... ... @@ -7,12 +7,25 @@
const api = global.yoho.API;
/**
* 获取快递公司列表API
* @function getExpressCompanyAsync
* @return { Object } 快递公司列表
*/
const getExpressCompanyAsync = () => {
return api.get('', {
method: 'app.express.getExpressCompany'
}, {code: 200});
};
/**
* 获取订单信息API
* @function getOrderInfoAsync
* @param { number } orderCode 订单编号
* @param { number } uid 用户uid
* @param { string } sessionKey session
* @return { Object } 订单信息
*/
const getOrderInfoAsync = (orderCode, uid, sessionKey) => {
return api.get('', {
method: 'app.SpaceOrders.info',
... ... @@ -22,6 +35,13 @@ const getOrderInfoAsync = (orderCode, uid, sessionKey) => {
}, {code: 200});
};
/**
* 获取订单退货信息API
* @function getRefundGoodsAsync
* @param { number } orderCode 订单编号
* @param { number } uid 用户uid
* @return { Object } 订单退货信息
*/
const getRefundGoodsAsync = (orderCode, uid) => {
return api.get('', {
method: 'app.refund.goodsList',
... ... @@ -30,6 +50,13 @@ const getRefundGoodsAsync = (orderCode, uid) => {
}, {code: 200});
};
/**
* 获取退货详情信息API
* @function getRefundDetailAsync
* @param { number } applyId 退货申请id
* @param { number } uid 用户uid
* @return { Object } 退货详情信息
*/
const getRefundDetailAsync = (applyId, uid) => {
return api.get('', {
method: 'app.refund.detail',
... ... @@ -38,6 +65,15 @@ const getRefundDetailAsync = (applyId, uid) => {
}, {code: 200});
};
/**
* 退货申请提交API
* @function refundSubmitAsync
* @param { number } orderCode 订单编号
* @param { number } uid 用户uid
* @param { Object } goods 退货商品信息
* @param { Object } payment 退款信息
* @return { Object } 退货申请结果
*/
const refundSubmitAsync = (orderCode, uid, goods, payment) => {
return api.get('', {
method: 'app.refund.submit',
... ... @@ -48,6 +84,13 @@ const refundSubmitAsync = (orderCode, uid, goods, payment) => {
}, {code: 200});
};
/**
* 获取换货商品信息API
* @function getChangeGoodsListAsync
* @param { number } orderCode 订单编号
* @param { number } uid 用户uid
* @return { Object } 换货商品信息
*/
const getChangeGoodsListAsync = (orderCode, uid) => {
return api.get('', {
method: 'app.change.goodsList',
... ... @@ -56,6 +99,13 @@ const getChangeGoodsListAsync = (orderCode, uid) => {
});
};
/**
* 获取商品信息API
* @function getProductInfoAsync
* @param { number } productId 商品id
* @param { number } productSkn 商品skn
* @return { Object } 商品信息
*/
const getProductInfoAsync = (productId, productSkn) => {
return api.get('', {
method: 'app.product.data',
... ... @@ -64,6 +114,13 @@ const getProductInfoAsync = (productId, productSkn) => {
});
};
/**
* 获取换货详情API
* @function getExchangeDetail
* @param { number } id 收藏id
* @param { number } uid 用户uid
* @return { Object } 换货详情
*/
const getExchangeDetail = (id, uid) => {
return api.get('', {
method: 'app.change.detail',
... ... @@ -72,6 +129,13 @@ const getExchangeDetail = (id, uid) => {
});
};
/**
* 换货申请提交API
* @function changeSubmitAsync
* @param { number } data 换货信息
* @param { number } uid 用户uid
* @return { Object } 换货申请结果
*/
const changeSubmitAsync = (data, uid) => {
const requestData = Object.assign(data, {
method: 'app.change.submit',
... ... @@ -82,6 +146,14 @@ const changeSubmitAsync = (data, uid) => {
return api.get('', requestData);
};
/**
* 设置寄回快递信息API
* @function setExpressNumberAsync
* @param { number } uid 用户uid
* @param { number } param 寄回快递信息
* @param { boolean } isChange 是否换货 true--换货 false--退货
* @return { Object } 设置快递结果
*/
const setExpressNumberAsync = (uid, param, isChange) => {
return api.post('', {
method: isChange ? 'app.change.setexpress' : 'app.refund.setexpress',
... ... @@ -93,6 +165,14 @@ const setExpressNumberAsync = (uid, param, isChange) => {
});
};
/**
* 取消退换货API
* @function cancelReturnAsync
* @param { number } id 收藏id
* @param { number } uid 用户uid
* @param { boolean } isChange 是否换货 true--换货 false--退货
* @return { Object } 取消结果
*/
const cancelReturnAsync = (id, uid, isChange) => {
return api.post('', {
method: isChange ? 'app.change.cancel' : 'app.refund.cancel',
... ... @@ -101,6 +181,11 @@ const cancelReturnAsync = (id, uid, isChange) => {
});
};
/**
* 获取退货银行列表API
* @function getRefundBank
* @return { Object } 银行列表信息
*/
const getRefundBank = () => {
return api.get('', {
method: 'app.refund.refundBank'
... ...
... ... @@ -25,20 +25,6 @@ const returnAddress = {
phone: '17714194699'
};
// const _reduceArrByProductSku = data => {
// const d = [];
//
// d.push(data[0]);
//
// data.reduce((p, c) => { //eslint-disable-line
// if (p && c && p.productSku !== c.productSku) {
// d.push[c];
// }
// });
//
// return d;
// };
/**
* 获取用户退换货列表
* @function getUserReturn
... ... @@ -63,6 +49,16 @@ const getUserReturn = (uid, page) => {
2: '换货'
};
const urlIndex = {
1: '/me/return/refund/detail/',
2: '/me/return/exchange/detail/'
};
const typeIndex = {
1: 'refund',
2: 'exchange'
};
let data = {};
let paginationOpts = false;
... ... @@ -77,15 +73,21 @@ const getUserReturn = (uid, page) => {
}
} : false;
data.list.forEach(item => {
item.orderGoods = item.goods;
item.createTime = item.orderCreateTime;
item.hidePrice = true;
item.showStatus = true;
item.refundStr = refundStr[item.refundType];
item.detailUrl = helpers.urlFormat(urlIndex[item.refundType] + item.id);
item.type = typeIndex[item.refundType];
item.orderGoods.forEach(good => {
let cnAlphabet = good.cnAlphabet ? good.cnAlphabet : '';
item.orderGoods.forEach(it => {
it.hidePrice = true;
good.hidePrice = true;
good.goodUrl = helpers.urlFormat(`/product/pro_${good.productId}_${good.goodsId}/${cnAlphabet}.html`); // eslint-disable-line
});
});
}
... ... @@ -218,7 +220,10 @@ const _setReturnStatus = (list, half) => {
* @return { Object } 订单退货信息
*/
const _setRefundGoodList = (data) => {
let resData = {};
let resData = {
specialNotice: data.special_notice,
speclialReason: data.special_return_reason
};
if (data.goods_list) {
let goods = [];
... ... @@ -229,7 +234,11 @@ const _setRefundGoodList = (data) => {
goods.push({
href: helpers.urlFormat(`/product/pro_${value.product_id}_${value.goods_id}/${cnAlphabet}.html`),
img: value.goods_image,
name: value.product_name,
name: _.truncate(value.product_name, {
length: 34,
omission: '...'
}),
title: value.product_name,
size: value.size_name,
color: value.color_name,
num: 1, // 接口目前不支持
... ... @@ -239,6 +248,7 @@ const _setRefundGoodList = (data) => {
sku: value.product_sku,
type: value.goods_type,
typeId: value.goods_type_id,
limitReturn: value.is_limit_skn === 'Y',
reasonList: data.return_reason
});
... ... @@ -248,7 +258,6 @@ const _setRefundGoodList = (data) => {
});
resData.goods = goods;
}
resData.speclialReason = data.special_return_reason;
let returnMode = [];
... ... @@ -261,13 +270,23 @@ const _setRefundGoodList = (data) => {
// 退货类型根据id匹配
switch (mode.id) {
case 1:
Object.assign(mode, {
name: value.name,
tip: '退款会返到您购买时支付的账户中'
});
break;
case 2:
mode.class = 'ali-item';
mode.alipay = true;
Object.assign(mode, {
class: 'ali-item',
alipay: true
});
break;
case 3:
mode.class = 'union-item';
mode.unionpay = true;
Object.assign(mode, {
class: 'union-item',
unionpay: true
});
break;
default:
mode.name = value.name;
... ... @@ -288,16 +307,17 @@ const _setRefundGoodList = (data) => {
*/
const _setRefundDetailData = (data) => {
let resData = {
id: data.id || 0
id: data.id || 0,
orderCode: data.source_order_code || ''
};
data.status = 20;
switch (data.status) {
case 10:
resData.orderReview = {pass: true};
resData.refundExpress = true;
resData.refundAddress = returnAddress;
Object.assign(resData, {
orderReview: {pass: true},
refundExpress: true,
refundAddress: returnAddress
});
break;
case 20:
resData.refundExpress = true;
... ... @@ -339,12 +359,13 @@ const _setRefundDetailData = (data) => {
let goods = [];
_.forEach(data.goods_list, value => {
let cnAlphabet = value.cn_alphabet ? value.cn_alphabet : '';
goods.push({
href: helpers.urlFormat(`/product/pro_${value.product_id}_${value.goods_id}/${cnAlphabet}.html`),
img: value.goods_image,
name: value.product_name,
name: _.truncate(value.product_name, {
length: 34,
omission: '...'
}),
title: value.product_name,
size: value.size_name,
color: value.color_name,
num: 1, // 接口目前不支持
... ... @@ -399,17 +420,23 @@ const _setExchangeDetailData = (data) => {
switch (data.status) {
case 0:
list.audit = true;
list.reminder = true;
Object.assign(list, {
audit: true,
reminder: true
});
break;
case 10:
list.through = true;
list.reminder = true;
Object.assign(list, {
through: true,
reminder: true
});
if (data.deliveryTpyeName === '寄回换货') {
list.logistics = true;
list.sendBack = true;
list.exchangeAddress = returnAddress;
Object.assign(list, {
logistics: true,
sendBack: true,
exchangeAddress: returnAddress
});
} else {
list.inDoor = true;
}
... ... @@ -421,13 +448,17 @@ const _setExchangeDetailData = (data) => {
}
break;
case 50:
list.send = true;
list.reminder = true;
list.auditSuccess = true;
Object.assign(list, {
send: true,
reminder: true,
auditSuccess: true
});
break;
case 40:
list.finish = true;
list.auditSuccess = true;
Object.assign(list, {
finish: true,
auditSuccess: true
});
break;
case 91:
list.abolish = true;
... ... @@ -458,9 +489,11 @@ const getRefundGoodsData = (orderCode, uid) => {
};
if (result.data) {
Object.assign(resData.returns.refund, _setRefundGoodList(result.data), {
orderCode: orderCode
});
Object.assign(
resData.returns.refund,
_setRefundGoodList(result.data),
{orderCode: orderCode}
);
}
return resData;
... ... @@ -495,12 +528,11 @@ const getRefundDetailData = (applyId, uid) => {
data.expressList = _setExpressData(result[1].data);
}
// 设置状态进度
Object.assign(resData.returns.refundDetail, _setReturnStatus(data.statusList, !data.status));
// 设置退货详情信息
Object.assign(resData.returns.refundDetail, _setRefundDetailData(data));
Object.assign(
resData.returns.refundDetail,
_setReturnStatus(data.statusList, !data.status), // 设置状态进度
_setRefundDetailData(data) // 设置退货详情信息
);
}
return resData;
... ... @@ -572,18 +604,16 @@ const getChangeGoodsList = (orderCode, uid) => {
if (result && result.data) {
data = camelCase(result.data);
// data.goodsList = _reduceArrByProductSku(data.goodsList);
data.hidePrice = true;
data.orderCode = orderCode;
data.goodsList.forEach(good => {
good.showCheckbox = true;
good.hidePrice = true;
// good.buyNumber = good.num;
good.buyNumber = 1;
});
if (data.goodsList) {
data.goodsList.forEach(good => {
good.showCheckbox = true;
good.hidePrice = true;
good.buyNumber = 1;
});
}
}
... ... @@ -615,19 +645,18 @@ const getExchangeDetailData = (id, uid) => {
};
if (result[0] && result[0].data) {
let data = result[0].data;
if (result[1] && result[1].data) {
data.expressList = _setExpressData(result[1].data);
}
Object.assign(exchangeData.exchangeDetail, _setReturnStatus(data.statusList));// 头部
Object.assign(exchangeData.exchangeDetail, _setExchangeDetailData(data));
Object.assign(exchangeData.exchangeDetail, camelCase(data));
Object.assign(
exchangeData.exchangeDetail,
_setReturnStatus(data.statusList),
_setExchangeDetailData(data),
camelCase(data)
);
}
return exchangeData;
... ...
... ... @@ -8,6 +8,7 @@
const api = global.yoho.API;
const crypto = require('crypto');
const fs = require('fs');
/**
* 查询个人详细信息
... ... @@ -179,9 +180,28 @@ const decipheriv = (data) => {
return decipherChunks.join('');
};
/**
* 上传头像
* @param uid
* @param bucket
* @param fileData
*/
const modifyHead = (uid, bucket, fileData)=> {
return api.postFile('', {
method: 'app.passport.modifyHead',
uid: uid,
bucket: bucket
}, {
file_data: fs.createReadStream(fileData)
});
};
module.exports = {
getUserInfo,
editUserInfo,
cipheriv,
decipheriv
decipheriv,
modifyHead
};
... ...
... ... @@ -10,7 +10,6 @@ const router = require('express').Router(); // eslint-disable-line
const cRoot = './controllers';
const auth = require(`${global.middleware}/auth`);
// const auth = require(`${global.middleware}/auth`);
// 订单
const order = require(`${cRoot}/order`);
... ... @@ -78,6 +77,8 @@ router.post('/setting/step2/:type', auth, setting.validate2);
// 第三步
router.get('/setting/step3/:type', auth, setting.success);
router.post('/setting/modifyHead', auth, setting.getfilePath, setting.modifyHead);
router.post('/account/changePwd', auth, account.changePwd);
router.post('/account/sendMobileMsg', auth, account.sendMobileMsg);
router.post('/account/checkVerifyMsg', auth, account.checkVerifyMsg);
... ... @@ -85,7 +86,6 @@ router.post('/account/sendVerifyEmail', auth, account.sendVerifyEmail);
router.post('/account/checkVerifyMobile', auth, account.checkVerifyMobile);
// 我的收藏
router.get('/collection', auth, favorite.goods);
router.get('/collection/brand', auth, favorite.brand);
... ...
<div class="good-info {{#if @last}}last{{/if}}">
<img src="{{image goodsImage 65 90}}">
<a href="{{goodUrl}}" target="_blank">
<img src="{{image goodsImage 65 90}}">
</a>
<div class="detail">
<p class="with-bottom-space">{{productName}}</p>
<a href="{{goodUrl}}" target="_blank">
<p class="with-bottom-space">{{productName}}</p>
</a>
<span class="with-space">颜色:{{colorName}}</span>
<span>尺码:
<span class="bold">{{sizeName}}</span>
... ...
... ... @@ -3,7 +3,14 @@
{{> order/good-info}}
{{#unless hidePrice}}
<div class="sub-column right-border bold">
<p class="{{#if @last}}last{{/if}}">¥{{goodsPrice}}</p>
<p class="{{#if @last}}last{{/if}}">
¥{{goodsPrice}}
{{#if changed}}
<a href="{{returnUrl}}">
<span class="btn white change-tag">已退换</span>
</a>
{{/if}}
</p>
</div>
<div class="sub-column right-border special-column bold">
<p class="bold">{{buyNumber}}</p>
... ...
... ... @@ -8,6 +8,9 @@
<div class="common-column special-border">
<p class="bold">¥{{amount}}</p>
<p class="subtext">{{paymentTypeStr}}</p>
{{#if isRefundOrder}}
<p class="subtext refund-tag">换货订单</p>
{{/if}}
</div>
<div class="common-column special-border status">
<p class="bold status-str">{{statusStr}}</p>
... ... @@ -29,10 +32,10 @@
{{/if}}
{{#if showEditOption}}
<p class="subtext">评价晒单</p>
<a href="{{refundUrl}}">
<a href="{{refundUrl}}" class="{{#if hideChange}}disable{{/if}}">
<p class="subtext">申请退货</p>
</a>
<a href="{{exchangeUrl}}">
<a href="{{exchangeUrl}}" class="{{#if hideChange}}disable{{/if}}">
<p class="subtext">申请换货</p>
</a>
<p class="subtext delete">删除订单</p>
... ... @@ -56,12 +59,16 @@
{{/if}}
{{^}}
<div class="bg"></div>
{{#orderData}}
<div class="msg">
<p class="msg-zh bold">{{emptyMsg}}</p>
{{#if showEmptyEn}}
<p class="msg-en">You do not have an order for the time being</p>
{{/if}}
<span class="btn">去购物</span>
<a href="{{url}}">
<span class="btn">{{btnText}}</span>
</a>
</div>
{{/orderData}}
{{/if}}
</div>
... ...
... ... @@ -36,8 +36,10 @@
</p>
<p>
我们会在入库后的1-3个工作日内处理您的退款,如有疑问,请联系
<span class="iconfont">&#xe61c;</span>
<span>在线客服</span>
<a href="http://chat8.live800.com/live800/chatClient/chatbox.jsp?companyID=620092&configID=149091&jid=8732423409" class="online-service">
<span class="iconfont blue">&#xe61c;</span>
<span class="blue">在线客服</span>
</a>
</p>
</div>
{{/ backStorage}}
... ... @@ -74,7 +76,7 @@
<div class="edit-content{{#if number}} hide{{/if}}"{{# expressList}} data-{{id}}="{{name}}"{{/ expressList}}>
<h4 class="third-title">填写物流</h4>
<p>请您在<span class="blue">7月30日24:00</span>将商品寄回并填写物流,逾期将自动取消申请</p>
<p>请您在<span class="blue">7天内</span>将商品寄回并填写物流,逾期将自动取消申请</p>
<dl class="express-wrap">
<dd>
物流公司:
... ... @@ -109,7 +111,7 @@
{{/ refundAddress}}
<div class="refund-detail-goods">
<h4 class="third-title">退货商品&nbsp;&nbsp;&nbsp;&nbsp;订单编号:{{id}}</h4>
<h4 class="third-title">退货商品&nbsp;&nbsp;&nbsp;&nbsp;订单编号:{{orderCode}}</h4>
<ul class="goods-header">
<li class="info">商品信息</li>
<li>退货原因</li>
... ... @@ -118,10 +120,10 @@
{{# goods}}
<div class="goods-item clearfix">
<div class="img">
<img class="lazy" data-original="{{image img 70 90}}">
<img class="lazy" title="{{title}}" data-original="{{image img 70 90}}">
</div>
<div class="info">
<p><a href="{{href}}">{{name}}</a></p>
<p><span title="{{title}}">{{name}}</span></p>
<p>颜色:{{color}}&nbsp;尺码:{{size}}</p>
<p>×{{num}}</p>
</div>
... ...
... ... @@ -16,10 +16,12 @@
<div class="goods-item clearfix">
<div class="check" data-skn="{{skn}}" data-skc="{{skc}}" data-sku="{{sku}}" data-price="{{price}}" data-type="{{typeId}}">{{> icon/checkbox}}</div>
<div class="img">
<img class="lazy" data-original="{{image img 70 90}}">
<a href="{{href}}" title="{{title}}" target="_blank">
<img class="lazy" data-original="{{image img 70 90}}">
</a>
</div>
<div class="info">
<p><a href="{{href}}">{{name}}</a></p>
<p><a href="{{href}}" class="title" title="{{title}}" target="_blank">{{name}}</a></p>
<p>颜色:{{color}}&nbsp;尺码:{{size}}</p>
<p>×{{num}}</p>
</div>
... ... @@ -37,6 +39,19 @@
<span class="iconfont">&#xe61f;</span>
</div>
<div class="price">¥{{round price 2}}</div>
{{#if limitReturn}}
<div class="limit-return">
<span class="limit-return-tip blue">
该商品不支持7天无理由退换
<i class="iconfont">&#xe612;</i>
<div class="limit-return-wrap">
<div class="code-horn"></div>
<p>考虑到个人卫生,例如内衣、内裤、袜子等贴身塑身类商品,不支持无理由退换货</p>
<p>香水、香薰、化妆品等特殊商品,无质量问题,不支持无理由退换货</p>
</div>
</span>
</div>
{{/if}}
{{> returns/special-reason}}
</div>
{{/ goods}}
... ... @@ -48,6 +63,9 @@
<div>
{{# returnMode}}
<label class="type-item {{class}}{{#if cur}} cur{{/if}}" title="{{title}}" data-id="{{id}}">{{name}}</label>
{{#if tip}}
<span class="type-tip">{{tip}}</span>
{{/if}}
{{/ returnMode}}
</div>
{{# returnMode}}
... ...
... ... @@ -31,7 +31,7 @@
</div>
</div>
</div>
<div class="form">
<div class="form hide">
<div class="group color">
<span class="title">
<span class="asterisk">*</span>
... ... @@ -51,37 +51,40 @@
{{/goodsList}}
</div>
</div>
{{/returnsChange}}
<div class="change-type">
<span class="box-title">换货方式</span>
<span class="type active" data-type="10">寄回换货</span>
<span class="type" data-type="11">上门取货</span>
</div>
{{#address}}
<div class="express-info-box">
<span class="box-title">收货信息</span>
<div class="application-form">
<div class="input-group">
<span class="asterisk">*</span>
<label for="city" class="change-area">所在区域:</label>
<span id="city" class="cascading-address"></span>
<span id="city" class="cascading-address" data-code="{{areaCode}}"></span>
</div>
<div class="input-group require">
<span class="asterisk">*</span>
<label for="person">收货人:</label>
<input id="user" class="input" type="text" name="person">
<input id="user" class="input" type="text" name="person" value="{{consignee}}">
</div>
<div class="input-group require">
<span class="asterisk">*</span>
<label for="address">详细地址:</label>
<input id="addr" class="input" type="text" name="address">
<input id="addr" class="input" type="text" name="address" value="{{address}}">
</div>
<div class="input-group require">
<span class="asterisk">*</span>
<label for="mobile">手机号码:</label>
<input id="mob" class="input" type="text" name="mobile">
<input id="mob" class="input" type="text" name="mobile" value="{{mobile}}">
</div>
</div>
</div>
{{/address}}
{{/returnsChange}}
<span class="btn confirm">确定</span>
<span class="btn confirm right">提交申请</span>
</div>
... ...
... ... @@ -19,8 +19,14 @@
<p class="subtext badge refund-type">{{refundStr}}</p>
</div>
<div class="common-column special-border operation">
<p class="subtext">取消申请</p>
<p class="subtext">查看详情</p>
{{#isY canCancel}}
{{# ../this}}
<p class="subtext cancel-apply" data-type="{{type}}" data-apply-id="{{id}}">取消申请</p>
{{/ ../this}}
{{/isY}}
<a href="{{detailUrl}}">
<p class="subtext">查看详情</p>
</a>
</div>
</div>
</div>
... ...
... ... @@ -17,6 +17,10 @@
<span class="iconfont">&#xe61f;</span>
</div>
<span class="img-up-tip">0/4</span>
<span class="warn hide">
<span class="iconfont blue">&#xe60d;</span>
<span class="blue">最多上传4张照片</span>
</span>
</div>
</div>
</div>
... ...
... ... @@ -9,6 +9,7 @@
<label class="label-name">真实姓名:</label>
<input id="username" class="input" type="text" placeholder="请输入2-12个汉字或英文"
value="{{info.username}}" minlength="2" maxlength="12">
<span class="blue error-tips">{{> icon/error-round}}2-12个汉字或英文</span>
</div>
<div class="form-group">
<label class="label-name">昵称:</label>
... ... @@ -71,7 +72,8 @@
</div>
<div class="user-icon inline-block">
{{#if info.head_ico}}
<img src="{{info.head_ico}}">
<div class="show-ico"><img src="{{info.head_ico}}"></div>
<div class="edit-ico hide"></div>
{{else}}
<div class="show-ico"></div>
<div class="edit-ico hide"></div>
... ...
... ... @@ -6,15 +6,12 @@
'use strict';
const helpers = global.yoho.helpers;
const service = require('../models/back-service');
const passportHelper = require('../models/passport-helper');
const BackService = require('../models/back-service');
const PassportHelper = require('../models/passport-helper');
const _ = require('lodash');
/**
* 找回密码主页面
*/
const index = (req, res, next) => {
service.indexPageDataAsync()
BackService.indexPageDataAsync()
.then(result => {
res.display('back/index', Object.assign({
module: 'passport',
... ... @@ -26,14 +23,11 @@ const index = (req, res, next) => {
.catch(next);
};
/**
* 校验用户输入信息,是否是已经注册的用户
*/
const validateInputAPI = (req, res, next) => {
let userInput = req.body.phoneNum || '';
let areaCode = (req.body.area || '86').replace('+', '');
service.validateEmailOrMobileAsync(userInput, areaCode)
BackService.validateEmailOrMobileAsync(userInput, areaCode)
.then(result => {
req.inputInfo = result;
next();
... ... @@ -46,14 +40,11 @@ const validateInputAPI = (req, res, next) => {
});
};
/**
* 校验用户输入信息,是否是已经注册的用户
*/
const validateInputPage = (req, res, next) => {
let userInput = req.body.phoneNum || '';
let areaCode = (req.body.area || '86').replace('+', '');
service.validateEmailOrMobileAsync(userInput, areaCode)
BackService.validateEmailOrMobileAsync(userInput, areaCode)
.then(result => {
req.inputInfo = result;
next();
... ... @@ -66,7 +57,7 @@ const validateInputPage = (req, res, next) => {
const getUserInfoAPI = (req, res, next) => {
let inputInfo = req.inputInfo;
service.findUserAsync(inputInfo.type, inputInfo.phone, inputInfo.area)
BackService.findUserAsync(inputInfo.type, inputInfo.phone, inputInfo.area)
.then(result => {
res.json(result);
})
... ... @@ -76,7 +67,7 @@ const getUserInfoAPI = (req, res, next) => {
const sendCodePage = (req, res, next) => {
let inputInfo = req.inputInfo;
service.sendCodeToUserAsync(inputInfo.type, inputInfo.phone, inputInfo.area)
BackService.sendCodeToUserAsync(inputInfo.type, inputInfo.phone, inputInfo.area)
.then(result => {
if (!(result.code && result.code === 200)) {
return res.redirect(helpers.urlFormat('/passport/back/index'));
... ... @@ -109,7 +100,7 @@ const sendBackMobileAPI = (req, res, next) => {
let mobile = req.body.mobile || '';
let area = req.body.area || '86';
service.sendCodeToMobileAsync(area, mobile)
BackService.sendCodeToMobileAsync(area, mobile)
.then(result => {
res.json(result);
})
... ... @@ -120,7 +111,7 @@ const validateMobileAPI = (req, res, next) => {
let mobile = req.body.mobile || '';
const ERR = {code: 400, message: '验证失败'};
if (!passportHelper.validator.verifyMobile(mobile)) {
if (!PassportHelper.validator.verifyMobile(mobile)) {
return res.json(ERR);
}
... ... @@ -163,7 +154,7 @@ const validateCodeByEmailPage = (req, res, next) => {
return next();
}
service.checkEmailCodeAsync(code)
BackService.checkEmailCodeAsync(code)
.then(result => {
if (!result) {
return res.redirect(helpers.urlFormat('/passport/back/index'));
... ... @@ -241,7 +232,7 @@ const verifyCodeByMobileAPI = (req, res) => {
return res.json(ERR);
}
service.verifyCodyByMobileAsync(area, mobile, mobileCode)
BackService.verifyCodyByMobileAsync(area, mobile, mobileCode)
.then(result => {
res.json(result);
})
... ... @@ -280,7 +271,7 @@ const validateCodeByMobilePage = (req, res, next) => {
};
code = new Buffer(code, 'base64').toString();
req.mobileAuth = service.authRequest(data, code);
req.mobileAuth = BackService.authRequest(data, code);
next();
};
... ... @@ -288,7 +279,7 @@ const validateCodeByMobilePage = (req, res, next) => {
const validatePwdPage = (req, res, next) => {
let pwd = req.body.pwd || '';
if (!passportHelper.validator.isPassword(pwd)) {
if (!PassportHelper.validator.verifyPassword(pwd)) {
return res.redirect(helpers.urlFormat('/passport/back/index'));
}
... ... @@ -300,7 +291,7 @@ const updatePwdAPI = (req, res, next) => {
let mobileAuth = req.mobileAuth || {};
let newPassword = req.body.pwd || '';
service.updatePwdAsync(code, mobileAuth, newPassword)
BackService.updatePwdAsync(code, mobileAuth, newPassword)
.then(result => {
if (result.status) {
req.session.successType = result.type;
... ...
... ... @@ -9,6 +9,7 @@
const _ = require('lodash');
const helpers = global.yoho.helpers;
const PassportHelper = require('../models/passport-helper');
const UserService = require('../models/user-service');
const BindService = require('../models/bind-service');
const LoginService = require('../models/login-service');
... ... @@ -21,267 +22,293 @@ const Sources = {
const DEFAULT_URL = 'http://img10.static.yhbimg.com/headimg/2013/11/28/09/01cae078abe5fe320c88cdf4c220212688.gif?imageView/2/w/100/h/100';
const bind = {
indexPage: (req, res) => {
let openId = req.query.openId;
let sourceType = req.query.sourceType;
res.display('bind/index', Object.assign({
module: 'passport',
page: 'bind',
title: '联合登录补全信息',
defaultHeader: false
}, {
openId: openId,
sourceType: sourceType,
country: {list: PassportHelper.getCountry()},
local: '+86',
countryName: {text: '中国'},
imgCaptcha: helpers.urlFormat('/passport/images', {t: Date.now()})
}));
},
bindSetPwdPage: (req, res) => {
let mobile = req.query.thirdPart.mobile;
let sourceType = req.query.thirdPart.sourceType;
let openId = req.query.thirdPart.openId;
let area = req.query.thirdPart.area;
res.display('bind/bind-set-pwd', Object.assign({
module: 'passport',
page: 'bind-set-pwd',
title: '登录绑定',
defaultHeader: false
}, {
mobile: mobile,
sourceType: sourceType,
openId: openId,
area: area
}));
},
bindConfirmPage: (req, res) => {
let thirdPart = req.query.thirdPart;
let user = req.query.user;
let avatar = user.headImg || DEFAULT_URL;
res.display('bind/bind-confirm', Object.assign({
module: 'passport',
page: 'bind-confirm',
title: '绑定确认',
defaultHeader: false
}, {
avatar: avatar,
name: user.username || '咸鸭蛋',
bindSuccess: helpers.urlFormat('/thirdlogin/bindSuccess', {
sourceType: thirdPart.sourceType
}),
bindUrl: helpers.urlFormat('/passport/thirdlogin/index', {
openId: thirdPart.openId,
sourceType: thirdPart.sourceType
}),
loginUrl: helpers.urlFormat('/passport/login'),
mobile: thirdPart.mobile,
const indexPage = (req, res) => {
let openId = req.query.openId;
let sourceType = req.query.sourceType;
res.display('bind/index', Object.assign({
module: 'passport',
page: 'bind',
title: '联合登录补全信息',
defaultHeader: false
}, {
openId: openId,
sourceType: sourceType,
country: {list: PassportHelper.getCountry()},
local: '+86',
countryName: {text: '中国'},
imgCaptcha: helpers.urlFormat('/passport/images', {t: Date.now()})
}));
};
const bindSetPwdPage = (req, res) => {
let mobile = req.query.thirdPart.mobile;
let sourceType = req.query.thirdPart.sourceType;
let openId = req.query.thirdPart.openId;
let area = req.query.thirdPart.area;
res.display('bind/bind-set-pwd', Object.assign({
module: 'passport',
page: 'bind-set-pwd',
title: '登录绑定',
defaultHeader: false
}, {
mobile: mobile,
sourceType: sourceType,
openId: openId,
area: area
}));
};
const bindConfirmPage = (req, res) => {
let thirdPart = req.query.thirdPart;
let user = req.query.user;
let avatar = user.headImg || DEFAULT_URL;
res.display('bind/bind-confirm', Object.assign({
module: 'passport',
page: 'bind-confirm',
title: '绑定确认',
defaultHeader: false
}, {
avatar: avatar,
name: user.username || '咸鸭蛋',
bindSuccess: helpers.urlFormat('/thirdlogin/bindSuccess', {
sourceType: thirdPart.sourceType
}),
bindUrl: helpers.urlFormat('/passport/thirdlogin/index', {
openId: thirdPart.openId,
area: thirdPart.area,
code: thirdPart.code,
sourceType: thirdPart.sourceType
}));
},
bindSuccessPage: (req, res) => {
let sourceType = _.trim(req.query.sourceType);
let sourceInfo = sourceType.split('_');
let sourceName = Sources[sourceInfo[0]];
res.display('bind/bind-success', Object.assign({
module: 'passport',
page: 'bind-success',
title: '绑定手机号',
defaultHeader: false
}, {
goShopping: helpers.urlFormat('/'),
sourceName: sourceName
}));
},
bindedPage: (req, res) => {
let thirdPart = req.query.thirdPart;
let user = req.query.user;
let avatar = user.headImg || DEFAULT_URL;
res.display('bind/bind-done', Object.assign({
module: 'passport',
page: 'bind-success',
title: '绑定手机号',
defaultHeader: false
}, {
avatar: avatar,
name: user.username || '咸鸭蛋',
loginUrl: helpers.urlFormat('/passport/login'),
bindUrl: helpers.urlFormat('/passport/thirdlogin/index', {
openId: thirdPart.openId,
sourceType: thirdPart.sourceType
})
}));
},
relateSuccessPage: (req, res) => {
let sourceType = _.trim(req.query.sourceType);
let sourceInfo = sourceType.split('_');
let sourceName = Sources[sourceInfo[0]];
res.display('bind/relate-success', Object.assign({
module: 'passport',
page: 'relate-success',
title: '关联手机号',
defaultHeader: false
}, {
goShopping: helpers.urlFormat('/'),
sourceName: sourceName
}));
},
relateConfirmPage: (req, res) => {
let thirdPart = req.query.thirdPart;
let user = req.query.user;
let avatar = user.headImg || DEFAULT_URL;
res.display('bind/relate-confirm', Object.assign({
module: 'passport',
page: 'relate-confirm',
title: '关联确认',
defaultHeader: false
}, {
avatar: avatar,
name: user.username || '咸鸭蛋',
relateUrl: helpers.urlFormat('/passport/thirdlogin/index', {
openId: thirdPart.openId,
sourceType: thirdPart.sourceType
}),
signinUrl: helpers.urlFormat('/passport/login'),
mobile: thirdPart.mobile,
area: thirdPart.area,
sourceType: thirdPart.sourceType,
openId: thirdPart.openId
}));
},
bindCheck: (req, res, next) => {
let mobile = req.body.mobile;
let openId = req.body.openId;
let area = req.body.area || '86';
let sourceType = req.body.sourceType;
if (mobile && openId && area && sourceType) {
BindService.bindCheckAsync(mobile, openId, sourceType, area).then(result => {
if (!result || !result.code) {
return {code: 400, message: '', data: ''};
} else if (result.code === 200 && result.data.is_register === 0) {
let nextUrl = helpers.urlFormat('/passport/thirdlogin/bindSetPwd');
// 绑定流程:code=200 未注册,可绑定
return {code: 200, message: result.message, data: {next: nextUrl}};
} else if (result.code === 200 && result.data.is_register === 1) {
return PassportHelper.getUserInfo(area, mobile).then(user => {
// 绑定流程:code=201 已注册 绑定过其他第三方
return {code: 201, message: result.message, data: {user: user}};
});
} else if (result.code === 200 && result.data.is_register === 3) {
// 关联流程
return PassportHelper.getUserInfo(area, mobile).then(user => {
return {code: 203, message: result.message, data: {user: user}};
});
} else if (result.code === 506 || result.code === 505) {
return PassportHelper.getUserInfo(area, mobile).then(user => {
// 绑定流程:code=201 已注册 绑定过其他第三方
return {code: 205, message: result.message, data: {user: user}};
});
} else {
return {code: result.code, message: result.message, data: result.data ? result.data : ''};
}
}).then(result => {
res.json(result);
}).catch(next);
} else {
res.json({code: 400, message: '', data: ''});
}
},
sendBindMsg: (req, res, next) => {
let mobile = req.body.mobile;
let area = req.body.area;
BindService.sendBindMsgAsync(area, mobile).then(result => {
if (result && result.code) {
res.json(result);
} else {
res.json({code: 400, message: '', data: ''});
}
}).catch(next);
},
checkBindMsg: (req, res, next) => {
let mobile = req.body.mobile;
let area = req.body.area;
let code = req.body.code;
BindService.checkBindCodeAsync(area, mobile, code).then(result => {
if (result && result.code) {
res.json(result);
} else {
res.json({code: 400, message: '', data: ''});
}
}).catch(next);
},
bindMobile: (req, res, next) => {
let mobile = _.trim(req.body.mobile);
let area = _.trim(req.body.area) || '86';
let openId = _.trim(req.body.openId);
let sourceType = _.trim(req.body.sourceType);
let password = _.trim(req.body.password) || '';
BindService.bindMobileAsync(openId, sourceType, mobile, area, password).then(result => {
if (result && result.code) {
if (result.code === 200 && result.data && result.data.uid) {
let refer = helpers.urlFormat('/passport/thirdlogin/bindsuccess', {
sourceType: sourceType + '_bind'
});
return LoginService.syncUserSession(result.data.uid, req, res).then(() => {
return {code: 200, message: result.message, data: {refer: refer}};
});
} else {
return {code: result.code, message: result.message, data: {refer: ''}};
}
} else {
}),
loginUrl: helpers.urlFormat('/passport/login'),
mobile: thirdPart.mobile,
openId: thirdPart.openId,
area: thirdPart.area,
code: thirdPart.code,
sourceType: thirdPart.sourceType
}));
};
const bindSuccessPage = (req, res) => {
let sourceType = _.trim(req.query.sourceType);
let sourceInfo = sourceType.split('_');
let sourceName = Sources[sourceInfo[0]];
res.display('bind/bind-success', Object.assign({
module: 'passport',
page: 'bind-success',
title: '绑定手机号',
defaultHeader: false
}, {
goShopping: helpers.urlFormat('/'),
sourceName: sourceName
}));
};
const bindedPage = (req, res) => {
let thirdPart = req.query.thirdPart;
let user = req.query.user;
let avatar = user.headImg || DEFAULT_URL;
res.display('bind/bind-done', Object.assign({
module: 'passport',
page: 'bind-success',
title: '绑定手机号',
defaultHeader: false
}, {
avatar: avatar,
name: user.username || '咸鸭蛋',
loginUrl: helpers.urlFormat('/passport/login'),
bindUrl: helpers.urlFormat('/passport/thirdlogin/index', {
openId: thirdPart.openId,
sourceType: thirdPart.sourceType
})
}));
};
const relateSuccessPage = (req, res) => {
let sourceType = _.trim(req.query.sourceType);
let sourceInfo = sourceType.split('_');
let sourceName = Sources[sourceInfo[0]];
res.display('bind/relate-success', Object.assign({
module: 'passport',
page: 'relate-success',
title: '关联手机号',
defaultHeader: false
}, {
goShopping: helpers.urlFormat('/'),
sourceName: sourceName
}));
};
const relateConfirmPage = (req, res) => {
let thirdPart = req.query.thirdPart;
let user = req.query.user;
let avatar = user.headImg || DEFAULT_URL;
res.display('bind/relate-confirm', Object.assign({
module: 'passport',
page: 'relate-confirm',
title: '关联确认',
defaultHeader: false
}, {
avatar: avatar,
name: user.username || '咸鸭蛋',
relateUrl: helpers.urlFormat('/passport/thirdlogin/index', {
openId: thirdPart.openId,
sourceType: thirdPart.sourceType
}),
signinUrl: helpers.urlFormat('/passport/login'),
mobile: thirdPart.mobile,
area: thirdPart.area,
sourceType: thirdPart.sourceType,
openId: thirdPart.openId
}));
};
const bindCheck = (req, res, next) => {
let mobile = req.body.mobile;
let openId = req.body.openId;
let area = req.body.area || '86';
let sourceType = req.body.sourceType;
if (mobile && openId && area && sourceType) {
/**
* 接口绑定返回值:
* code:200,is_register=0 // 绑定流程:未注册,可绑定
* code:200,is_register=1 // 绑定流程:已注册绑定过其他第三方
* code:200:is_register=3 // 关联流程
* code:505 // 手机号码注册过,而且该第三方也已经绑定过手机号
* code:506 // 手机号码注册过,而且该手机号码也已经绑定过该类型第三方
*/
BindService.bindCheckAsync(mobile, openId, sourceType, area).then(result => {
if (!result || !result.code) {
return {code: 400, message: '', data: ''};
}
}).then(result => {
res.json(result);
}).catch(next);
},
relateMobile: (req, res, next) => {
let mobile = req.body.mobile;
let openId = req.body.openId;
let areaCode = req.body.areaCode || '86';
let sourceType = req.body.sourceType;
return BindService.relateMobileAsync(openId, sourceType, mobile, areaCode).then(result => {
if (result && result.code) {
if (result.code === 200 && result.data && result.data.uid) {
let refer = helpers.urlFormat('/passport/thirdlogin/relatesuccess', {
sourceType: sourceType + '_bind'
});
return LoginService.syncUserSession(result.data.uid, req, res).then(() => {
return {code: 200, message: result.message, data: {refer: refer}};
});
} else {
return {code: result.code, message: result.message, data: {refer: ''}};
}
} else if (result.code === 200 && result.data.is_register === 0) {
let nextUrl = helpers.urlFormat('/passport/thirdlogin/bindSetPwd');
// 绑定流程:code=200 未注册,可绑定
return {code: 200, message: result.message, data: {next: nextUrl}};
} else if (result.code === 200 && result.data.is_register === 1) {
return UserService.getUserInfoAsync(area, mobile).then(user => {
// 绑定流程:code=201 已注册 绑定过其他第三方
return {code: 201, message: result.message, data: {user: user}};
});
} else if (result.code === 200 && result.data.is_register === 3) {
// 关联流程
return UserService.getUserInfoAsync(area, mobile).then(user => {
return {code: 203, message: result.message, data: {user: user}};
});
} else if (result.code === 506 || result.code === 505) {
return UserService.getUserInfoAsync(area, mobile).then(user => {
// 绑定流程:code=201 已注册 绑定过其他第三方
return {code: 205, message: result.message, data: {user: user}};
});
} else {
return {code: 400, message: '', data: ''};
return {code: result.code, message: result.message, data: result.data ? result.data : ''};
}
}).then(result => {
res.json(result);
}).catch(next);
} else {
res.json({code: 400, message: '', data: ''});
}
};
module.exports = bind;
const sendBindMsg = (req, res, next) => {
let mobile = req.body.mobile;
let area = req.body.area;
BindService.sendBindMsgAsync(area, mobile).then(result => {
if (result && result.code) {
res.json(result);
} else {
res.json({code: 400, message: '', data: ''});
}
}).catch(next);
};
const checkBindMsg = (req, res, next) => {
let mobile = req.body.mobile;
let area = req.body.area;
let code = req.body.code;
BindService.checkBindCodeAsync(area, mobile, code).then(result => {
if (result && result.code) {
res.json(result);
} else {
res.json({code: 400, message: '', data: ''});
}
}).catch(next);
};
const bindMobile = (req, res, next) => {
let mobile = _.trim(req.body.mobile);
let area = _.trim(req.body.area) || '86';
let openId = _.trim(req.body.openId);
let sourceType = _.trim(req.body.sourceType);
let password = _.trim(req.body.password) || '';
BindService.bindMobileAsync(openId, sourceType, mobile, area, password).then(result => {
if (result && result.code) {
if (result.code === 200 && result.data && result.data.uid) {
let refer = helpers.urlFormat('/passport/thirdlogin/bindsuccess', {
sourceType: sourceType + '_bind'
});
return LoginService.syncUserSession(result.data.uid, req, res).then(() => {
return {code: 200, message: result.message, data: {refer: refer}};
});
} else {
return {code: result.code, message: result.message, data: {refer: ''}};
}
} else {
return {code: 400, message: '', data: ''};
}
}).then(result => {
res.json(result);
}).catch(next);
};
const relateMobile = (req, res, next) => {
let mobile = req.body.mobile;
let openId = req.body.openId;
let areaCode = req.body.areaCode || '86';
let sourceType = req.body.sourceType;
return BindService.relateMobileAsync(openId, sourceType, mobile, areaCode).then(result => {
if (result && result.code) {
if (result.code === 200 && result.data && result.data.uid) {
let refer = helpers.urlFormat('/passport/thirdlogin/relatesuccess', {
sourceType: sourceType + '_bind'
});
return LoginService.syncUserSession(result.data.uid, req, res).then(() => {
return {code: 200, message: result.message, data: {refer: refer}};
});
} else {
return {code: result.code, message: result.message, data: {refer: ''}};
}
} else {
return {code: 400, message: '', data: ''};
}
}).then(result => {
res.json(result);
}).catch(next);
};
module.exports = {
indexPage, // 首页
bindSetPwdPage, // 设置密码页面
bindConfirmPage, // 绑定确认页面
bindSuccessPage, // 绑定成功页面
bindedPage, // 已绑定相同类型第三方的页面
relateConfirmPage, // 关联确认页面
relateSuccessPage, // 关联成功页面
bindCheck, // 检查第三方和手机号的绑定情况
sendBindMsg, // 发送绑定手机验证码
checkBindMsg, // 检查手机验证码
bindMobile, // 绑定手机号
relateMobile // 关联手机号
};
... ...
... ... @@ -62,8 +62,8 @@ const requiredPost = (req, res) => {
};
module.exports = {
requiredAPI,
requiredPage,
generate,
requiredPost
requiredAPI, // 中间件的验证
requiredPage, // 跳转页面的验证
generate, // 生成验证码
requiredPost // 端点验证码
};
... ...
... ... @@ -21,21 +21,14 @@ const LoginService = require('../models/login-service');
const PassportHelper = require('../models/passport-helper');
const loginPageURL = `${config.siteUrl}/passport/login`;
const blockRedirectFilter = /sign|login|passport/;
// 第三方登录回调
function doPassportCallback(req, res, user) {
const _doPassportCallback = (req, res, user) => {
let shoppingKey = cookie.getShoppingKey(req);
let refer = req.cookies.refer;
let refer = req.cookies.refer || config.siteUrl;
if (refer) {
refer = decodeURI(req.cookies.refer);
} else {
refer = config.siteUrl;
}
if (/sign|login|passport/.test(refer)) {
refer = config.siteUrl;
}
refer = !blockRedirectFilter.test(decodeURI(refer)) ? decodeURI(refer) : config.siteUrl;
if (user.openId && user.nickname) {
let signinByOpenID = LoginService.signinByOpenIDAsync(
... ... @@ -63,7 +56,7 @@ function doPassportCallback(req, res, user) {
} else {
return Promise.resolve(res.redirect(loginPageURL));
}
}
};
const common = {
beforeLogin: (req, res, next) => {
... ... @@ -104,33 +97,33 @@ const local = {
domain: config.cookieDomain
});
let bindMobile = _.trim(req.query.bindMobile || '');
let bindArea = '+' + _.trim(req.query.bindArea || '86');
let areaArr = PassportHelper.getCountry();
let areaName = '';
let loginMobile = _.trim(req.query.bindMobile || '');
let loginCountryCode = '+' + _.trim(req.query.bindArea || '86');
let countries = PassportHelper.getCountry();
let defaultCountryName = '';
if (bindArea) {
let area = areaArr.find((a) => {
return a.areaCode === bindArea;
if (loginCountryCode) {
let area = countries.find((a) => {
return a.areaCode === loginCountryCode;
});
areaName = area ? area.name : '';
defaultCountryName = area ? area.name : '';
}
res.display('login', {
loginPage: true,
defaultHeader: false,
passport: {
countryCode: bindArea,
countryName: {text: areaName},
country: {list: areaArr},
countryCode: loginCountryCode,
countryName: {text: defaultCountryName},
country: {list: countries},
forgetPwd: helpers.urlFormat('/passport/back/index'),
fastReg: helpers.urlFormat('/passport/reg'),
weixinLogin: helpers.urlFormat('/passport/autosign/wechat'),
qqLogin: helpers.urlFormat('/passport/autosign/qq'),
weiboLogin: helpers.urlFormat('/passport/autosign/sina'),
alipayLogin: helpers.urlFormat('/passport/autosign/alipay'),
bindMobile: bindMobile
bindMobile: loginMobile
},
module: 'passport',
page: 'login',
... ... @@ -153,7 +146,7 @@ const local = {
let refer = req.cookies.refer;
if (isRemember) {
yield LoginService.rememberAccount({
yield LoginService.rememberAccountAsync({
area: req.body.areaCode || '86',
account: req.body.account,
password: req.body.password
... ... @@ -166,7 +159,7 @@ const local = {
refer = `${config.siteUrl}`;
}
if (/sign|login|passport/.test(refer)) {
if (blockRedirectFilter.test(refer)) {
refer = `${config.siteUrl}`;
}
... ... @@ -183,11 +176,12 @@ const local = {
})(req, res, next);
},
logout: (req, res) => {
req.session = null;
req.session.destroy();
res.clearCookie('_UID', {
domain: config.cookieDomain
});
res.clearCookie('_TOKEN', {
domain: config.cookieDomain
});
... ... @@ -231,7 +225,7 @@ const wechat = {
log.error(`wechat authenticate error : ${JSON.stringify(err)}`);
return res.redirect(loginPageURL);
} else {
doPassportCallback(req, res, {
_doPassportCallback(req, res, {
openId: user._json.openid,
unionId: user._json.unionid || user.id,
nickname: user._json.nickname || user.displayName,
... ... @@ -264,7 +258,7 @@ const sina = {
let nickname = user.screen_name;
let openId = user.id;
doPassportCallback(req, res, {
_doPassportCallback(req, res, {
openId: openId,
nickname: nickname,
sourceType: 'sina'
... ... @@ -291,10 +285,11 @@ const qq = {
log.error(`qq authenticate error : ${JSON.stringify(err)}`);
return res.redirect(loginPageURL);
}
let nickname = user.nickname;
let openId = user.id;
doPassportCallback(req, res, {
_doPassportCallback(req, res, {
openId: openId,
nickname: nickname,
sourceType: 'qq'
... ... @@ -316,10 +311,11 @@ const alipay = {
log.error(`alipay authenticate error : ${JSON.stringify(err)}`);
return res.redirect(loginPageURL);
}
let nickname = user.realName;
let openId = user.userId;
doPassportCallback(req, res, {
_doPassportCallback(req, res, {
openId: openId,
nickname: nickname,
sourceType: 'alipay'
... ... @@ -329,10 +325,10 @@ const alipay = {
};
module.exports = {
common: common,
local: local,
wechat: wechat,
qq: qq,
sina: sina,
alipay: alipay
common,
local, // 本地系统登录
wechat, // 微信登录
qq, // QQ登录
sina, // 新浪登录
alipay // 支付宝登录
};
... ...
... ... @@ -279,13 +279,13 @@ let success = (req, res) => {
};
module.exports = {
checkCode,
checkPassword,
index,
success,
checkMobile,
picCaptcha,
sendBindMsg,
msgCaptcha,
mobileRegister
checkCode, // 检查图形验证码中间件
checkPassword, // 检查密码格式
index, // 首页
success, // 成功页
checkMobile, // 检查手机号码是否注册过
picCaptcha, // 检查图形验证码
sendBindMsg, // 发送注册验证码
msgCaptcha, // 验证图形验证码
mobileRegister // 手机号注册
};
... ...
... ... @@ -11,9 +11,9 @@ const moment = require('moment');
const helpers = global.yoho.helpers;
const api = require('./back-api');
const userService = require('./user-service');
const passportHelper = require('./passport-helper');
const backHelper = require('./back-helper');
const UserService = require('./user-service');
const PassportHelper = require('./passport-helper');
const BackHelper = require('./back-helper');
/**
* 验证手机和邮箱输入正确性
... ... @@ -22,13 +22,13 @@ const validateEmailOrMobileAsync = (userInput, areaCode) => {
return new Promise(function(resolve, rejected) {
let result = {type: 'email', area: '', phone: ''};
if (passportHelper.validator.verifyEmail(userInput)) {
if (PassportHelper.validator.verifyEmail(userInput)) {
result.type = 'email';
result.area = '';
result.phone = userInput;
resolve(result);
} else if (passportHelper.validator.verifyMobile(userInput)) {
} else if (PassportHelper.validator.verifyMobile(userInput)) {
result.type = 'mobile';
result.area = areaCode;
result.phone = userInput;
... ... @@ -54,8 +54,8 @@ const findUserAsync = (type, phone, area) => {
};
const findBy = {
email: userService.findByEmailAsync,
mobile: (phone1, area1) => userService.findByMobileAsync(area1, phone1) // 交换参数
email: UserService.findByEmailAsync,
mobile: (phone1, area1) => UserService.findByMobileAsync(area1, phone1) // 交换参数
};
const OK = {code: 200, message: MESSAGE.ok};
... ... @@ -97,7 +97,7 @@ const sendCodeToMobileAsync = (areaCode, mobile) => {
*/
const indexPageDataAsync = () => {
return co(function *() {
let countryList = passportHelper.getCountry();
let countryList = PassportHelper.getCountry();
return {
back: {
... ... @@ -133,7 +133,7 @@ const verifyCodyByMobileAsync = (area, mobile, mobileCode) => {
createdAt: moment().unix()
};
data.code = new Buffer(backHelper.makeToken(data)).toString('base64');
data.code = new Buffer(BackHelper.makeToken(data)).toString('base64');
return {
code: 200,
... ... @@ -148,7 +148,7 @@ const verifyCodyByMobileAsync = (area, mobile, mobileCode) => {
* 手机 token 合法性验证
*/
const authRequest = (data, token) => {
if (!backHelper.validateToken(data, token)) {
if (!BackHelper.validateToken(data, token)) {
return {};
}
... ...
... ... @@ -9,6 +9,9 @@
const api = global.yoho.API;
/**
* 登录检查用户是否登录注册
*/
const bindCheckAsync = (mobile, openId, sourceType, area) => {
let params = {
method: 'app.passport.signCheck',
... ... @@ -21,6 +24,9 @@ const bindCheckAsync = (mobile, openId, sourceType, area) => {
return api.get('', params);
};
/**
* 发送绑定信息短信
*/
const sendBindMsgAsync = (area, mobile) => {
let params = {
method: 'app.passport.smsbind',
... ... @@ -31,6 +37,9 @@ const sendBindMsgAsync = (area, mobile) => {
return api.get('', params);
};
/**
* 验证手机注册码
*/
const checkBindCodeAsync = (area, mobile, code) => {
return api.get('', {
method: 'app.register.validRegCode',
... ... @@ -40,6 +49,9 @@ const checkBindCodeAsync = (area, mobile, code) => {
});
};
/**
* 绑定用户信息接口
*/
const bindMobileAsync = (openId, sourceType, mobile, area, password, nickname) => {
let params = {
method: 'app.passport.bind',
... ... @@ -60,6 +72,9 @@ const bindMobileAsync = (openId, sourceType, mobile, area, password, nickname) =
return api.get('', params);
};
/**
* 关联用户信息
*/
const relateMobileAsync = (openId, sourceType, mobile, area) => {
return api.get('', {
method: 'app.passport.relatedMobile',
... ... @@ -70,6 +85,9 @@ const relateMobileAsync = (openId, sourceType, mobile, area) => {
});
};
/**
* 改变手机号检查
*/
const changeCheckAsync = (mobile, area) => {
return api.get('', {
method: 'app.passport.changeCheck',
... ... @@ -78,6 +96,9 @@ const changeCheckAsync = (mobile, area) => {
});
};
/**
* 改变手机号绑定
*/
const changeMobileAsync = (uid, mobile, area, code) => {
return api.get('', {
method: 'app.passport.changeMobile',
... ...
... ... @@ -7,6 +7,9 @@
const _ = require('lodash');
const Captchapng = require('captchapng');
/**
* 生成验证码
*/
exports.generateCaptcha = (width, height, length) => {
let min = Math.pow(10, (length - 1 || 1));
let max = Math.pow(10, (length - 1 || 1)) * 9;
... ...
... ... @@ -6,6 +6,9 @@
const api = global.yoho.API;
/**
* 手机或邮箱登录
*/
const signinAsync = (area, profile, password, shoppingKey) => {
let param = {
method: 'app.passport.signin',
... ... @@ -21,6 +24,9 @@ const signinAsync = (area, profile, password, shoppingKey) => {
return api.post('', param);
};
/**
* 除微信第三方登录
*/
const signinByOtherOpenIDAsync = (nickname, openId, sourceType, shoppingKey) => {
let param = {
nickname: nickname,
... ... @@ -36,6 +42,9 @@ const signinByOtherOpenIDAsync = (nickname, openId, sourceType, shoppingKey) =>
return api.get('', param);
};
/**
* 微信第三方登录
*/
const signinByWechatAsync = (nickname, openId, sourceType, shoppingKey, unionId) => {
let param = {
nickname: nickname,
... ...
... ... @@ -11,7 +11,7 @@ const sign = global.yoho.sign;
const config = global.yoho.config;
const api = require('./login-api');
const userService = require('./user-service');
const UserService = require('./user-service');
const signinByOpenIDAsync = (nickname, openId, sourceType, shoppingKey, unionId) => {
let signinFunc = {
... ... @@ -26,7 +26,7 @@ const signinByOpenIDAsync = (nickname, openId, sourceType, shoppingKey, unionId)
};
const syncUserSession = (uid, req, res) => {
return userService.profile(uid).then((userInfo) => {
return UserService.profileAsync(uid).then((userInfo) => {
let token = sign.makeToken(uid);
let user = userInfo.data;
... ... @@ -55,7 +55,7 @@ const syncUserSession = (uid, req, res) => {
});
};
const rememberAccount = (accountInfo, req, res) => {
const rememberAccountAsync = (accountInfo, req, res) => {
let aWeek = (new Date()).getTime() / 1000 + 504000; // 504000-一周
let rememKey = md5(md5(accountInfo.account + accountInfo.password + accountInfo.area));
... ... @@ -76,5 +76,5 @@ module.exports = {
signinAsync: api.signinAsync,
signinByOpenIDAsync,
syncUserSession,
rememberAccount
rememberAccountAsync
};
... ...
... ... @@ -5,11 +5,6 @@
const _ = require('lodash');
const helpers = global.yoho.helpers;
const UserService = require('./user-service');
const DEFAULT_HEAD_IMG_ICO = 'http://img10.static.yhbimg.com/headimg/2013/11/28/09/01cae078abe5fe320c88cdf4c220212688.gif?imageView/2/w/100/h/100';
/**
* 国家数据
*/
... ... @@ -86,7 +81,7 @@ const verifyEmail = email => {
return false;
}
const emailRegExp = /^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/;
const emailRegExp = /^[\.a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/;
return emailRegExp.test(email);
};
... ... @@ -106,7 +101,7 @@ const verifyMobile = phone => {
/**
* 密码是否合法
*/
const isPassword = pwd => {
const verifyPassword = pwd => {
if (!pwd) {
return false;
}
... ... @@ -116,32 +111,11 @@ const isPassword = pwd => {
return pwdRegexp.test(_.trim(pwd));
};
/**
* 第三方登录 根据手机号获取用户相关信息
*/
const getUserInfo = (area, mobile) => {
return UserService.findByMobileAsync(area, mobile).then(user => {
let profile = (user.profile_name || mobile).toString();
if ((profile.length === 11 && profile.indexOf('*') < 0) || (profile.indexOf('-') >= 0 &&
profile.indexOf('*') < 0)) {
profile = profile.substring(0, 3) + '****' + profile.substring(7, 11);
}
return {
username: profile,
headImg: user.head_ico ? helpers.image(user.head_ico, 100, 100, 2) : DEFAULT_HEAD_IMG_ICO,
bindLogin: helpers.urlFormat('/signin', { bindMobile: mobile, bindArea: area })
};
});
};
module.exports = {
validator: {
verifyMobile,
verifyEmail,
isPassword
verifyPassword
},
getCountry,
getUserInfo
getCountry
};
... ...
... ... @@ -4,6 +4,9 @@
'use strict';
const api = global.yoho.API;
/**
* 发送注册验证码
*/
let sendCodeToMobileAsync = (area, mobile) => {
let params = {
method: 'app.register.sendRegCodeToMobile',
... ... @@ -14,6 +17,9 @@ let sendCodeToMobileAsync = (area, mobile) => {
return api.post('', params);
};
/**
* 检查注册验证码
*/
let validMobileCodeAsync = (area, mobile, code) => {
let params = {
method: 'app.register.validRegCode',
... ... @@ -25,6 +31,9 @@ let validMobileCodeAsync = (area, mobile, code) => {
return api.post('', params);
};
/**
* 注册帐号
*/
let regMobileAsync = (area, mobile, password, shoppingKey)=> {
let params = {
method: 'app.passport.register',
... ...
... ... @@ -46,7 +46,10 @@ const findByEmailAsync = (email) => {
});
};
const profile = (uid) => {
/**
* 获得个人信息
*/
const profileAsync = (uid) => {
let param = {
uid: uid,
method: 'app.passport.profile'
... ... @@ -58,5 +61,5 @@ const profile = (uid) => {
module.exports = {
findByMobileAsync,
findByEmailAsync,
profile
profileAsync
};
... ...
... ... @@ -4,5 +4,28 @@
'use strict';
const api = require('./user-api');
const helpers = global.yoho.helpers;
module.exports = api;
const DEFAULT_HEAD_IMG_ICO = 'http://img10.static.yhbimg.com/headimg/2013/11/28/09/01cae078abe5fe320c88cdf4c220212688.gif?imageView/2/w/100/h/100';
/**
* 第三方登录 根据手机号获取用户相关信息
*/
const getUserInfoAsync = (area, mobile) => {
return api.findByMobileAsync(area, mobile).then(user => {
let profile = (user.profile_name || mobile).toString();
if ((profile.length === 11 && profile.indexOf('*') < 0) || (profile.indexOf('-') >= 0 &&
profile.indexOf('*') < 0)) {
profile = profile.substring(0, 3) + '****' + profile.substring(7, 11);
}
return {
username: profile,
headImg: user.head_ico ? helpers.image(user.head_ico, 100, 100, 2) : DEFAULT_HEAD_IMG_ICO,
bindLogin: helpers.urlFormat('/signin', {bindMobile: mobile, bindArea: area})
};
});
};
module.exports = Object.assign(api, {getUserInfoAsync});
... ...
... ... @@ -67,7 +67,7 @@
<li>
<div>
<input id="reset-pwd-btn" class="reset-pwd-btn disable" type="submit" value="下一步">
<input id="reset-pwd-btn" class="reset-pwd-btn disable" type="submit" value="下一步" disabled>
</div>
</li>
... ...
... ... @@ -42,7 +42,7 @@
</li>
<div class="success-text">
<div class="title">恭喜您设置完成,请妥善保存您的密码!</div>
<div class="small-title">恭喜您设置完成,请妥善保存您的密码!</div>
<div class="time">页面将在&nbsp;<span id="count-down" class="blue">5</span>&nbsp;秒后将跳转至首页</div>
</div>
</ul>
... ...
... ... @@ -54,7 +54,7 @@ const list = {
queryParams: q
};
res.display('list', _.assign(retData, {
products: DataHelper.handleProductList(data.productList),
products: DataHelper.handleProductList(data.productList, q),
order: q.order
}));
} else {
... ... @@ -74,7 +74,7 @@ const list = {
let retData = {
module: 'product',
page: 'list',
title: '列表'
title: '新品'
};
Promise.all([Resouces.newProductBanner(), Search.queryAllSort(), Search.queryNewProduct(q)]).then(result => {
... ... @@ -108,7 +108,7 @@ const list = {
queryParams: q
};
res.display('newList', _.assign(retData, {
products: DataHelper.handleProductList(data.productList),
products: DataHelper.handleProductList(data.productList, q),
order: q.order
}));
} else {
... ...
... ... @@ -28,7 +28,9 @@ const Query = {
query: query
};
Promise.all([Search.queryAllSort(), Search.queryProduct(q)]).then(allResult => {
Promise.all([Search.queryAllSort({
query: query
}), Search.queryProduct(q)]).then(allResult => {
let allSort = camelCase(allResult[0]);
let result = allResult[1];
... ... @@ -41,9 +43,11 @@ const Query = {
});
if (data.filter) {
data.filter.standard = data.standard;
data.filter.groupSort = DataHelper.sortConvert(allSort.data.sort);
retData.filter = DataHelper.filterHandle(data.filter, q);
retData.filter.showPrice = data.total > 10;
retData.filter.showInfo = retData.filter.style || data.standard;
}
retData.navPath = {
... ... @@ -58,7 +62,7 @@ const Query = {
queryParams: q
};
res.display('list', _.assign(retData, {
products: DataHelper.handleProductList(data.productList),
products: DataHelper.handleProductList(data.productList, q),
order: q.order
}));
} else {
... ...
... ... @@ -109,49 +109,51 @@ const shop = {
nav.push({
name: result.name
});
} else {
res.status(404);
return Promise.reject('brand-not-found');
}
}).then(() => {
return Promise.all([Search.queryAllSort({
brand: q.brand,
shop: q.shop_id,
small_sort: 1
}), Search.queryProductOfBrand(q)]).then(allResult => {
let allSort = camelCase(allResult[0]);
let result = allResult[1];
if (result && result.code === 200 && result.data) {
let ret = camelCase(result.data);
if (ret.filter) {
delete q.brand;
ret.filter.groupSort = DataHelper.sortConvert(allSort.data.sort);
data.filter = DataHelper.filterHandle(ret.filter, req.query);
data.filter.showPrice = ret.total > 10;
return result.brandId;
}).then((brandId) => {
if (brandId) {
return Promise.all([Search.queryAllSort({
brand: q.brand,
shop: q.shop_id,
small_sort: 1
}), Search.queryProductOfBrand(q)]).then(allResult => {
let allSort = camelCase(allResult[0]);
let result = allResult[1];
if (result && result.code === 200 && result.data) {
let ret = camelCase(result.data);
if (ret.filter) {
delete q.brand;
ret.filter.groupSort = DataHelper.sortConvert(allSort.data.sort);
data.filter = DataHelper.filterHandle(ret.filter, req.query);
data.filter.showPrice = ret.total > 10;
}
data.paginationData = {
page: q.page,
limit: ret.limit || 45,
total: ret.total,
pageTotal: ret.pageTotal,
queryParams: req.query
};
data.navPath = {
nav: nav
};
res.display('shop-list', _.assign(data, {
products: DataHelper.handleProductList(ret.productList, q),
order: q.order
}));
} else {
return Promise.reject('query shop index error');
}
data.paginationData = {
page: q.page,
limit: ret.limit || 45,
total: ret.total,
pageTotal: ret.pageTotal,
queryParams: req.query
};
data.navPath = {
nav: nav
};
res.display('shop-list', _.assign(data, {
products: DataHelper.handleProductList(ret.productList),
order: q.order
}));
} else {
return Promise.reject('query shop index error');
}
});
});
} else {
return next();
}
}).catch(next);
},
... ...
... ... @@ -44,6 +44,45 @@ const helpers = {
return letters;
},
getLettersFromBrand(brands, numberIndex) {
numberIndex = numberIndex || 0;
let letters = new Set();
let other = false;
_.forEach(brands, (b) => {
let name = b.brandNameEn || b.brandName;
let char = name.toLowerCase().charAt(0);
if ((char >= 'a' && char <= 'z') || (char >= 'A' && char <= 'Z')) {
letters.add(char);
} else {
other = true;
}
});
letters = Array.from(letters).sort().map(s => {
return {
letter: s.toUpperCase(),
selected: false
};
});
if (other && numberIndex === -1) {
letters.push({
letter: '0-9',
selected: false
});
} else if (other && numberIndex === 0) {
letters.unshift({
letter: '0-9',
selected: false
});
}
return letters;
},
/**
* 男女条件
* @returns {*[]}
... ... @@ -270,6 +309,33 @@ const helpers = {
});
}
if (q.style) {
let styleNames = filter.style.filter(s => {
return (',' + q.style + ',').indexOf(',' + s.styleId + ',') >= 0;
}).map(s => {
s.checked = true;
return s.styleName;
}).join(',');
if (styleNames) {
styleNames = styleNames.length > 10 ? styleNames.substr(0, 10) + '...' : styleNames;
filters.push(this.newFilter('style', q.style, styleNames));
}
}
if (q.standard) {
let standardIds = q.standard.split(',');
filter.standard.forEach(s => {
s.sub.forEach(b => {
if (b.standardId === parseInt(standardIds[1], 10)) {
b.checked = true;
filters.push(this.newFilter('standard', q.standard, b.standardName));
}
});
});
}
return {
people: genders,
sortData: sorts,
... ... @@ -277,10 +343,12 @@ const helpers = {
brandData: brands,
colors: colors,
size: sizeInfo,
style: filter.style,
standard: filter.standard,
priceRange: priceRange,
filters: filters,
showFilters: filters.length > 0,
letters: this.brandLetters(),
letters: this.getLettersFromBrand(brands),
customPriceLow: customPriceLow,
customPriceHigh: customPriceHigh,
showSize: showSize,
... ... @@ -294,10 +362,11 @@ const helpers = {
* @param list
* @returns {*}
*/
handleProductList(list) {
handleProductList(list, q) {
if (_.isArray(list)) {
list.forEach(g => {
let goodsList = g.goodsList;
let defaultImages = g.defaultImages;
let goodsId;
if (goodsList && goodsList.length > 0) {
... ... @@ -305,9 +374,13 @@ const helpers = {
goodsList.forEach(o => {
o.url = `${config.siteUrl}/product/pro_${g.productId}_${o.goodsId}/${o.cnAlphabet}.html`;
if (q.color && q.color === o.colorId) {
defaultImages = o.imagesUrl;
}
});
}
g.salesPrice = g.salesPrice || g.marketPrice;
g.defaultImages = defaultImages;
if (g.salesPrice === g.marketPrice) {
delete g.marketPrice;
}
... ...
... ... @@ -29,6 +29,13 @@ function _paramHanlde(obj) {
}
}
if (obj.standard) {
let standards = obj.standard.split(',');
obj.standard_id = standards[0];
obj.standard_value_id = standards[1];
}
return obj;
}
... ...
... ... @@ -137,18 +137,68 @@
</div>
{{/if}}
<div class="yoho-ui-accordion">
<h3>颜色</h3>
<div class="body">
<div class="color-body nano">
<div class="nano-content">
{{#each colors}}
<div class="input-radio" data-value="{{id}}">
{{> round-color}}
<label>{{title}}</label>
</div>
{{/each}}
{{#if colors}}
<div class="yoho-ui-accordion">
<h3>颜色</h3>
<div class="body">
<div class="color-body nano">
<div class="nano-content">
{{#each colors}}
<div class="input-radio" data-value="{{id}}">
{{> round-color}}
<label>{{title}}</label>
</div>
{{/each}}
</div>
</div>
</div>
</div>
</div>
{{/if}}
{{#if showInfo}}
<div class="blank-div"></div>
<div class="title">商品属性</div>
{{#if style}}
<div class="yoho-ui-accordion">
<h3>风格</h3>
<div class="body">
<div class="style-mulit-btn">
<span class="btn white">多选</span>
</div>
<div class="style-body nano">
<div class="nano-content">
{{#each style}}
<div class="input-radio" data-value="{{styleId}}">
{{> icon/radio }}
<label>{{styleName}}</label>
</div>
{{/each}}
</div>
</div>
<div class="style-btns hide">
<span class="btn disable large confirm">确定</span>
<span class="btn large cancel">取消</span>
</div>
</div>
{{#if standard}}
{{#each standard}}
<h3>{{standardName}}</h3>
<div class="body" data-value="{{standardId}}">
<div class="standard-body nano">
<div class="nano-content">
{{#each sub}}
<div class="input-radio" data-value="{{standardId}}">
{{> icon/radio }}
<label>{{standardName}}</label>
</div>
{{/each}}
</div>
</div>
</div>
{{/each}}
{{/if}}
</div>
{{/if}}
{{/if}}
... ...
... ... @@ -13,10 +13,6 @@ const camelCase = global.yoho.camelCase;
const helpers = global.yoho.helpers;
const Payments = {
alipay: 2
};
/**
* 支付页
* @param req
... ... @@ -76,7 +72,7 @@ const toPay = (req, res, next) => {
*/
const callback = (req, res) => {
let type = req.params.type;
let payId = Payments[type];
let payId = PayData.payments[type];
let query = req.query;
PayHelpers.afterPay(query, payId, req.user).then(result => {
... ...
... ... @@ -25,7 +25,7 @@ const Alipay = {
partner: payParams.merchant_id,
_input_charset: 'utf-8',
notify_url: config.pay.serviceNotify + 'payment/alipay_notify',
return_url: helpers.urlFormat('/shopping/pay/callback/alipay'),
return_url: 'http:' + helpers.urlFormat('/shopping/pay/callback/alipay'),
subject: '有货订单号:' + order.orderId,
out_trade_no: order.orderCode,
it_b_pay: common.getPayExpireMin(order.payExpire) + 'm',
... ...
... ... @@ -24,7 +24,7 @@ const Payment = {
};
if (payInfo && payInfo.id === method) {
if (method === 2) {
if (method === PayData.payments.alipay) {
result = Alipay.pay(user, order, payInfo);
}
}
... ... @@ -77,7 +77,7 @@ const Payment = {
let payInfo = yield PayData.getPaymentInfo(payId);
let payResult = {};
if (payId === 2) {
if (payId === PayData.payments.alipay) {
payResult = Alipay.notify(query, payInfo);
payResult.bankName = payResult.bankName || payInfo.payName || '';
... ...
... ... @@ -122,7 +122,7 @@ const compute = (uid, yohoCoin) => {
* 提交订单api调用
* @param number uid user id
* @param number address_id 地址id
* @param number yohoCoin 使用的有货币
* @param number use_yoho_coin 使用的有货币(元)
* @param string invoices_title 发票抬头
* @param int invoices_type_id 发票内容
* @param string remark 备注
... ... @@ -137,7 +137,7 @@ const _submit = (uid, other) => {
method: 'app.Shopping.submit',
uid: uid,
address_id: other.address_id,
yohoCoin: other.yohoCoin,
use_yoho_coin: other.use_yoho_coin,
remark: other.remark,
isPrintPrice: other.isPrintPrice,
delivery_time: other.delivery_time,
... ... @@ -163,20 +163,15 @@ const _submit = (uid, other) => {
*/
const submit = (uid, other) => {
let theOther = {};
let coin = other.coin;
Object.assign(theOther, other, {
delivery_time: 2, // 平时和周末都送货
delivery_way: 1, // 普通快递
payment_id: 1, // 支付宝
payment_type: 1 // 在线支付
payment_type: 1, // 在线支付
use_yoho_coin: other.use_yoho_coin / 100 // 有货币稀释
});
// 有货币稀释
if (coin) {
coin = coin / 100;
}
return _submit(uid, theOther).then(result => result);
};
... ...
... ... @@ -49,7 +49,7 @@ const updateOrderPayBank = (code, payment, bankCode) => {
const sendPayConfirm = (code, payment, uid) => {
return api.get('', {
method: 'app.SpaceOrders.payConfirm',
orderCode: code,
order_code: code,
payment_id: payment,
uid: uid
});
... ...
... ... @@ -17,6 +17,10 @@ const logger = global.yoho.logger;
const _ = require('lodash');
const payments = {
alipay: 2
};
/**
* 获取在线支付方式
* @returns {*|Promise.<TResult>}
... ... @@ -28,13 +32,13 @@ const getOnlinePayProvider = () => {
}
let online = _(result.data)
.filter(i => _.includes(['Alipay'], i.payCode))
.filter(i => _.includes([payments.alipay], i.id))
.map(i => {
return {
id: i.id,
name: i.payName,
img: i.payIcon,
selected: i.payCode === 'Alipay'
selected: i.id === payments.alipay
};
})
.value();
... ... @@ -223,6 +227,7 @@ module.exports = {
setOrderPayBank,
updateOrderPayBank,
sendPayConfirm,
procOrderData
procOrderData,
payments
};
... ...
... ... @@ -203,58 +203,7 @@
{{/ shopping_cart_data}}
</div>
<script id="balance-tpl" type="text/html">
\{{#each promotion_formula_list}}
<li>
<span class="balance-title">\{{promotion}}</span>
<span class="balance-cost">\{{promotion_amount}}</span>
</li>
\{{/each}}
<li class="need-pay">
<span class="balance-title">应付金额\{{#if shipping_cost}}(含运费)\{{/if}}:</span>
<span id="balance-cost" class="balance-cost" data-cost="{{last_order_amount}}">¥<em>\{{round last_order_amount 2}}</em></span>
</li>
<li>
<span id="submit-order" class="btn submit-order">提交订单</span>
</li>
</script>
<script id="address-list-tpl" type="text/html">
\{{#each address}}
<li class="address\{{#isY is_default}} default\{{/isY}}\{{#if focus}} focus\{{/if}}"
data-id="\{{address_id}}" data-name="\{{consignee}}" data-mobile="\{{mobile}}"
data-phone="\{{phone}}" data-areacode="\{{area_code}}" data-area="\{{area}}"" data-address="\{{address}}">
<div class="address-header"></div>
<div class="address-content">
<p class="default-or-not">
<span class="default-tag">默认地址</span>
<span class="set-default">设为默认</span>
</p>
<p class="name-and-phone">
\{{consignee}}
<span class="phone bold">\{{mobile}}</span>
</p>
<p class="address-area bold">\{{area}}</p>
<p class="address-detail">\{{address}}</p>
<p class="address-opration">
<span class="modify">修改</span>
<span class="delete">删除</span>
</p>
</div>
<span class="address-chosed iconfont">&#xe63b;</span>
</li>
\{{/each}}
\{{#if hasNew}}
<li class="new-address-block">
<span class="iconfont">&#xe645;</span>
增加收货地址
</li>
\{{/if}}
</script>
{{!-- 服务端渲染,客户端使用 --}}
<script id="invoice-dialog-tpl" type="text/html">
<p class="dialog-title">发票信息</p>
<ul class="invoice-tab">
... ... @@ -303,101 +252,6 @@
</div>
</div>
</script>
<script id="address-dialog-tpl" type="text/html">
<p class="dialog-title">
\{{#if updateAddress}}
修改地址
\{{^}}
新增地址
\{{/if}}
</p>
<form id="address-form" name="address-form">
<div class="address-page">
<span class="tip">
<em class="blue">
\{{#if updateAddress}}
修改地址
\{{^}}
新增地址
\{{/if}}
</em>
电话为选填项,其他均为必填项
</span>
<div class="add-address-detail" data-id="\{{id}}">
<div class="form-group">
<label class="label-name">
<em class="required-mark">*</em>
收货人:
</label>
<input class="input address-name" type="text" placeholder="请输入您的姓名" maxlength="12" value="\{{name}}">
<span class="blue error-tips">
{{> icon/error-round}}
<em></em>
</span>
</div>
<div class="form-group clearfix">
<label class="label-name">
<em class="required-mark">*</em>
所在区域:
</label>
<div id="address" class="clearfix"></div>
<span class="blue error-tips">
{{> icon/error-round}}
请填写完整的省市区信息
</span>
</div>
<div class="form-group">
<label class="label-name">
<em class="required-mark">*</em>
详细地址:
</label>
<input class="input address-detail" type="text" placeholder="街道名称或小区名称" maxlength="60" value="\{{detail}}">
<span class="blue error-tips">
{{> icon/error-round}}
<em></em>
</span>
</div>
<div class="form-group">
<label class="label-name">
<em class="required-mark">*</em>
手机号码:
</label>
<input class="input address-mobile" type="text" placeholder="请输入手机号码(重要必填)" maxlength="11" value="\{{mobile}}">
<span class="blue error-tips">
{{> icon/error-round}}
<em></em>
</span>
</div>
<div class="form-group">
<label class="label-name">电话号码:</label>
<input class="input address-phone" type="text" placeholder="请输入电话号码(选填)" value="\{{phone}}" maxlength="15">
<span class="blue error-tips">
{{> icon/error-round}}
<em></em>
</span>
</div>
</div>
</div>
</form>
</script>
<script id="checked-invoice-show-tpl" type="text/html">
<div class="invoice-radio">
\{{#if checked}}
<span class="iconfont radio checked">&#xe603;</span>
\{{^}}
<span class="iconfont radio">&#xe604;</span>
\{{/if}}
<label>发票开具</label>
</div>
\{{#if invoiceTitle}}
<p class="invoice-detail" data-title="\{{invoiceTitle}}" data-content="\{{content}}">
<em>\{{invoiceTitle}}</em><em>\{{invoiceContent}}</em>
<span class="modify-invoice btn white">修改</span>
</p>
\{{/if}}
</script>
</div>
{{/ content}}
</div>
\ No newline at end of file
... ...
... ... @@ -65,7 +65,7 @@ module.exports = {
}
},
pay: {
serviceNotify: 'http://testservice.yoho.cn:28077/'
serviceNotify: 'http://devservice.yoho.cn:58077/'
}
};
... ...
const headerModel = require('../models/header');
const logger = global.yoho.logger;
/**
* 404 错误
* @return {[type]}
*/
const headerModel = require('../models/header');
const logger = global.yoho.logger;
exports.notFound = () => {
return (req, res, next) => {
return (req, res) => {
if (req.xhr) {
return res.status(404).json({
code: 404,
... ... @@ -14,14 +15,11 @@ exports.notFound = () => {
});
}
headerModel.requestHeaderData().then((result) => {
return res.display('error/404', {
module: 'common',
page: 'error',
title: '页面不存在 | Yoho!Buy有货 | 潮流购物逛不停',
headerData: result.headerData
});
}).catch(next);
return res.display('error/404', {
module: 'common',
page: 'error',
title: '页面不存在 | Yoho!Buy有货 | 潮流购物逛不停'
});
};
};
... ... @@ -52,7 +50,7 @@ exports.serverError = () => {
});
};
return headerModel.requestHeaderData().then(renderErrPage).catch(() => {
return headerModel.requestHeaderData(req.yoho.channel).then(renderErrPage).catch(() => {
renderErrPage();
});
}
... ...
... ... @@ -5,6 +5,9 @@ const cookie = global.yoho.cookie;
const cache = global.yoho.cache;
const loginService = require('../../apps/passport/models/login-service');
/**
* 已登录用户的信息,包括记住我功能。
*/
module.exports = () => {
return (req, res, next) => {
req.getUrl = function() {
... ...
... ... @@ -54,14 +54,14 @@ const getNavBar = (data, type) => {
let navBars = [];
_.forEach(data, item => {
let obj = {},
let obj = {
link: item.sort_url,
cn: item.sort_name,
en: item.sort_name_en,
isNewPage: item.is_new_page === 'Y'
},
lowEn = _.camelCase(item.sort_name_en).toLowerCase();
obj.link = item.sort_url;
obj.cn = item.sort_name;
obj.en = item.sort_name_en;
obj.isNewPage = item.is_new_page === 'Y' ? true : false;
if (type === lowEn) {
obj.cur = true;
}
... ... @@ -132,17 +132,19 @@ const getSubNav = (data, type) => {
_.forEach(data, it => {
if (type === _.camelCase(it.sort_name_en).toLowerCase()) {
_.forEach(it.sub, item => {
let obj = {};
obj.link = item.sort_url;
obj.cn = item.sort_name;
obj.en = item.sort_name_en;
obj.isHot = item.is_hot === 'Y' ? true : false;
obj.isNew = item.is_new === 'Y' ? true : false;
let obj = {
link: item.sort_url,
cn: item.sort_name,
en: item.sort_name_en,
isHot: item.is_hot === 'Y',
isNew: item.is_new === 'Y'
};
if (item.sub) {
obj.thirdNav = getThirdNav(item.sub);
obj.imgCode = item.content_code;
Object.assign(obj, {
thirdNav: getThirdNav(item.sub),
imgCode: item.content_code
});
}
subNav.push(obj);
... ... @@ -153,9 +155,6 @@ const getSubNav = (data, type) => {
return subNav;
};
/**
* 处理接口返回的数据
* @param {object} 接口返回的对象
... ... @@ -189,14 +188,12 @@ const requestNavBar = (type) => {
});
};
/**
* 请求头部数据
* @param {String} 频道类型
* @return {promise}
*/
exports.requestHeaderData = (type) => {
const requestHeaderData = (type) => {
let arr = [
getMenuData()
];
... ... @@ -211,3 +208,7 @@ exports.requestHeaderData = (type) => {
}, result[1]);
});
};
module.exports = {
requestHeaderData // 请求头部数据
};
... ...
<label class="round-color{{#if cur}} cur{{/if}}" title="{{title}}" style="background: {{rgb}}">
<label class="round-color{{#if cur}} cur{{/if}}" title="{{title}}">
<div class="icon-back" style="background: {{rgb}}"></div>
<span class="iconfont icon-cover">&#xe61b;</span>
<span class="iconfont icon-round">&#xe620;</span>
</label>
\ No newline at end of file
... ...
... ... @@ -61,7 +61,7 @@
"uuid": "^2.0.2",
"winston": "^2.2.0",
"winston-daily-rotate-file": "^1.1.4",
"yoho-node-lib": "0.0.23"
"yoho-node-lib": "0.0.28"
},
"devDependencies": {
"autoprefixer": "^6.3.6",
... ...
... ... @@ -3,11 +3,11 @@
{
"name": "yohoblk-node",
"script": "app.js",
"instances": "max",
"instances": "0",
"exec_mode": "cluster",
"env": {
"PORT": 6003
}
}
]
}
\ No newline at end of file
}
... ...
/**
* 判断值是否是'Y'
* @author: xuqi<qi.xu@yoho.cn>
* @date: 2016/7/27
*/
module.exports = function(value, options) {
if (value === 'Y') {
return options.fn(this);
} else {
return options.inverse(this);
}
};
... ...
/**
* 精确n位小数
* @author: xuqi<qi.xu@yoho.cn>
* @date: 2016/7/27
*/
/**
* @param num 数字
* @param precision 精确度,默认2
*/
module.exports = function(num, precision) {
precision = precision ? parseInt(precision, 10) : 2;
num = (num === +num) ? (+num).toFixed(precision) : (Math.round(num, precision)).toFixed(precision);
return num;
};
... ...
No preview for this file type
... ... @@ -51,8 +51,6 @@ $searchForm.on('keyup', '#search-key', function(e) {
if (key) {
$searchForm.submit();
}
} else {
$searchKey.val(key.replace(new RegExp('\'', 'gm'), ''));
}
if (key) {
... ...
... ... @@ -4,6 +4,11 @@
* @date: 2017/7/5
*/
/**
* 获取cookie值
* @param name [string] cookie键名
* @return [string] cookie值
*/
function cookie(name) {
var re = new RegExp(name + '=([^;$]*)', 'i'),
matchPattern = '$1';
... ... @@ -11,6 +16,12 @@ function cookie(name) {
return re.test(decodeURIComponent(document.cookie)) ? RegExp[matchPattern] : '';
}
/**
* 设置cookie
* @param name [string] cookie键名
* @param value [string] cookie值
* @pamra options [object] cookie参数项
*/
function setCookie(name, value, options) {
var expires = '',
path,
... ... @@ -42,6 +53,10 @@ function setCookie(name, value, options) {
}
}
/**
* query参数解析
* @return [object] query key-value map
*/
function queryString() {
var vars = {},
hash,
... ... @@ -56,6 +71,11 @@ function queryString() {
return vars;
}
/**
* 获取字符串长度(一个中文=2个字符)
* @param str [string]
* @return [num] 字符串长度
*/
function getStrLength(str) {
var cArr = str.match(/[\u4e00-\u9fa5a]/ig);
... ... @@ -63,8 +83,8 @@ function getStrLength(str) {
}
module.exports = {
cookie: cookie, // 获取cookie
setCookie: setCookie, // 设置cookie
queryString: queryString, // query参数解析
getStrLength: getStrLength // 获取字符串长度(一个中文=2个字符)
cookie: cookie,
setCookie: setCookie,
queryString: queryString,
getStrLength: getStrLength
};
... ...
... ... @@ -8,6 +8,9 @@ var $ = require('yoho-jquery');
var $returnTop = $('.return-top');
/**
* 是否显示返回顶部按钮
*/
function showOrNot() {
if ($(window).height() >= $(document).height()) {
$returnTop.addClass('hide');
... ...
... ... @@ -17,11 +17,11 @@ var page = 1;
var Bll = {
// 获取路由中的请求参数
getQueryString: function() {
let queryArr = location.search.substr(1).split('&');
let query = {};
var queryArr = location.search.substr(1).split('&');
var query = {};
queryArr.forEach(function(pair) {
let arr = pair.split('=');
var arr = pair.split('=');
query[arr[0]] = arr[1];
});
... ... @@ -33,7 +33,7 @@ var Bll = {
delivering: 2
},
getDataList: function(type1, page1, beginTime1) {
let query = ['page=' + page1, 'queryType=' + type1, 'beginTime=' + beginTime1];
var query = ['page=' + page1, 'queryType=' + type1, 'beginTime=' + beginTime1];
location.search = query.join('&');
}
... ... @@ -44,7 +44,7 @@ require('./me');
// tab切换
$('.tabs li').on('click', function() {
let $this = $(this);
var $this = $(this);
type = Bll.typeMap[$this.data('type')];
page = 1;
... ... @@ -60,7 +60,7 @@ $('.tabs li').on('click', function() {
// 时间控件切换
$('#begin-time').on('change', function() {
let months = parseInt($(this).val(), 10);
var months = parseInt($(this).val(), 10);
type = Bll.getQueryString().queryType || 1;
page = 1;
... ...
... ... @@ -267,10 +267,14 @@ function bindCheckboxEvent() {
type: 'checkbox',
group: 'exchange-good',
onChange: function(ele, checked) {
var $box = $(ele).closest('.change-info-box');
if (checked) {
$(ele).closest('.change-info-box').addClass('will-change');
$box.addClass('will-change');
$box.find('.form').removeClass('hide');
} else {
$(ele).closest('.change-info-box').removeClass('will-change');
$box.removeClass('will-change');
$box.find('.form').addClass('hide');
}
}
});
... ... @@ -288,6 +292,7 @@ function submitChange(d) {
}
}).fail(function(err) {
console.log(err);
new _alert('<h1>出错了!</h1>').show();
});
}
... ... @@ -385,10 +390,14 @@ function bindBlurEvent() {
}
function initAddr() {
function initAddr(areaCode) {
addr = addrSelector({
el: '#city'
});
if (areaCode) {
addr.setAddress(areaCode.toString());
}
}
function bindUploadEvent() {
... ... @@ -416,9 +425,13 @@ function bindUploadEvent() {
$(that).before(img);
number += 1;
$t.text(number + '/4');
} else {
new _alert(result.message).show();
}
}
});
} else {
$(that).siblings('.warn').removeClass('hide');
}
});
}
... ... @@ -429,7 +442,7 @@ $(document).on('ready', function() {
bindTypeEvent();
bindCheckboxEvent();
bindConfirmEvent();
initAddr();
initAddr($('#city').data('code'));
bindBlurEvent();
bindUploadEvent();
});
... ...
... ... @@ -245,6 +245,10 @@ $('.tabs li').on('click', function() {
});
$('a.disable').on('click', function() {
return false;
});
function bindDeleteEvent() {
$('.delete').on('click', function() {
var $this = $(this);
... ...
... ... @@ -139,7 +139,7 @@ function getCancelReason(code, onCancel) {
showDiaglog(tpl, code, onCancel);
}
}) .fail(function(err) {
}).fail(function(err) {
console.log(err);
});
}
... ...
... ... @@ -18,6 +18,11 @@ var $expressCompany = $('.express-company'),
var id = $mainWrap.data('id'),
expressList = $editExpress.data();
$('.blk-footer .return-top').remove(); // 移除通用的返回顶部组件
require('../common/header'); // header
require('../common/return-top'); // return-top
function cancelRefundApply() {
$.ajax({
type: 'POST',
... ...
... ... @@ -6,7 +6,8 @@
var $ = require('yoho-jquery'),
lazyload = require('yoho-jquery-lazyload'),
handlebars = require('yoho-handlebars'),
upload = require('../plugins/upload');
upload = require('../plugins/upload'),
Alert = require('../plugins/dialog').Alert;
var $refundTable = $('.refund-goods'),
$check = $('.check'),
... ... @@ -33,7 +34,11 @@ var tpl = '<div class="img-wrap" data-img="{{data}}">' +
var checked;
$('.blk-footer .return-top').remove(); // 移除通用的返回顶部组件
require('../plugins/check');
require('../common/header'); // header
require('../common/return-top'); // return-top
lazyload($('img.lazy'));
... ... @@ -211,15 +216,16 @@ $refundTable.on('change', '.refund-reason', function() {
num = $this.data('num') || 0;
if (num > 3) {
new Alert('<h1>最多上传4张凭证</h1>').show();
return;
}
upload.up({
callback: function(result) {
if (result && result.code === 200) {
$this.before(imgFn(result));
$this.siblings('.img-up-tip').text(++num + '/4');
$this.data('num', num);
$this.before(imgFn(result));
}
}
});
... ... @@ -264,11 +270,16 @@ $applyBtn.click(function() {
url: '/me/return/refund/apply',
data: param,
success: function(data) {
var message;
if (data.code === 200) {
if (data.data && data.data.refer) {
location.href = data.data.refer;
}
$tip.text('申请成功').removeClass('hide');
} else {
message = data.message || '申请提交失败';
new Alert('<h1>' + message + '</h1>').show();
}
}
});
... ...
var _alert = require('../plugins/dialog').Alert;
$('.cancel-apply').on('click', function() {
var id = $(this).data('applyId');
var type = $(this).data('type');
$.ajax({
url: '/me/return/cancel',
method: 'POST',
data: {
type: type,
id: id
}
}).done(function(result) {
if (result.code === 200) {
location.reload();
} else {
new _alert(result.message).show();
}
}).fail(function(err) {
console.log(err);
new _alert('出错了').show();
});
});
... ...
... ... @@ -7,40 +7,41 @@ var cascadingAddress = require('../plugins/cascading-address');
var dialog = require('../plugins/dialog');
var _dialog = dialog.Dialog;
var _alert = dialog.Alert;
var modifyHead = require('./setting/modifyHead');// flash操作
var tip;// 头像编辑弹框
var headHtml = modifyHead.swfobject('head', '600px', '400px', '../../img/me/head.swf?code=' + Math.random() +
'&upload_url=' + encodeURIComponent(location.protocol + '//' +
location.hostname + ':' + location.port + '/me/setting/modifyHead'));
var Bll = {
setIcon: function() {
var html = [];
html.push('<form id="upload_form" method="post" action="" onsubmit="return checkForm()">');
html.push('<div class="post-picture inline-block">');
html.push('<div class="choose-avatar"></div>');
html.push('<div class="post-file"><input id="avatar" name="avatar" type="file" value="点击上传"></div>');
html.push('<p class="post-limit">支持JPG、GIF、PNG、JPEG、BMP格式,文件小于3M</p>');
html.push('</div>');
html.push(' <div class="show-picture inline-block" ><img id="post-picture">');
html.push(' </div>');
html.push('<div class="preview-picture inline-block">');
html.push('<div class="small-preview"></div>');
html.push('<div style="width: 600px;height: 400px">');
html.push(headHtml);
html.push('</div>');
html.push('</form>');
return html.join('');
},
validate: function(info) {
var regBirth = new RegExp(/^[1-2][0-9][0-9][0-9]-[0-1]{0,1}[0-9]-[0-3]{0,1}[0-9]$/);
var regName = new RegExp(/^[\u4e00-\u9fa5_-a-zA-Z0-9]+$/);
var regRealName = new RegExp(/^[\u4e00-\u9fa5a-zA-Z]{2,12}$/);
var birthdayForm = $('#birthday');
var nickForm = $('#nick_name');
var realNameForm = $('#username');
var addressForm = $('.form-group-address');
var flag = true;
!regBirth.test(info.birthday) ? birthdayForm.next().show() : birthdayForm.next().hide();
!regName.test(info.nick_name) ? nickForm.next().show() : nickForm.next().hide();
!regRealName.test(info.username) ? realNameForm.next().show() : realNameForm.next().hide();
typeof (info.area_code) === 'undefined' ?
addressForm.css('margin-bottom', '20px').find('.error-tips').show() :
addressForm.css('margin-bottom', '70px').find('.error-tips').hide();
if (!regBirth.test(info.birthday) || !regName.test(info.nick_name) || typeof (info.area_code) === 'undefined') {
if (!regBirth.test(info.birthday) || !regName.test(info.nick_name) ||
!regRealName.test(info.username) || typeof (info.area_code) === 'undefined') {
flag = false;
}
return flag;
... ... @@ -49,9 +50,12 @@ var Bll = {
require('./me');
require('../plugins/check');
require('../me/setting/step1');
require('../me/setting/step2');
require('../me/setting/step3');
// 第一步:身份验证
require('../me/setting/validate');
// 第二步:操作
require('../me/setting/operate');
// 编辑头像移入移出切换效果
... ... @@ -63,9 +67,8 @@ $('.user-icon').hover(function() {
// 编辑头像打开弹框
$(document).on('click', '.edit-ico', function() {
var tip = new _dialog({
tip = new _dialog({
className: 'settled-success',
title: '自定义头像',
content: Bll.setIcon(),
btns: [
{
... ... @@ -73,7 +76,7 @@ $(document).on('click', '.edit-ico', function() {
btnClass: ['apply'],
name: '保存',
cb: function() {
tip.close();
modifyHead.uploadImage();
}
},
{
... ... @@ -88,19 +91,21 @@ $(document).on('click', '.edit-ico', function() {
}).show();
});
$(document).on('change', '#avatar', function() {
/* var oFile = $("#avatar")[0].files[0];
var oImage = document.getElementById('post-picture');
var oReader = new FileReader();
oReader.onload = function (e) {
oImage.src = e.target.result;
$(".post-picture").hide();
$("#post-picture").show();
};
oReader.readAsDataURL(oFile);*/
});
/**
* 头像上传处理
* @param obj
*/
window.receive_image_bytes = function(obj) {
var result = JSON.parse(obj);
if (result.code === 200) {
tip.close();
$('.show-ico img').attr('src', result.data.image_url.split('?')[0]);
} else {
tip.close();
new _alert('头像修改失败!').show();
}
};
$(function() {
var address = cascadingAddress({el: '#address'});
... ...
/**
* [个人中心]个人设置-编辑头像中flash相关操作
* @author: jiangmin
* @date: 2016/07/14
*/
/**
* 设置flash样式,并返回html
* @param id
* @param width
* @param height
* @param url
* @returns {string}
*/
function swfobject(id, width, height, url) {
var _html = '<object id="' + id + '" width="' + width + '" height="' + height + '" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000">' +
'<param value="' + url + '" name="movie"> ' +
'<param value="high" name="quality"> ' +
'<param value="#E0E0E0" name="bgcolor"> ' +
'<param name="allowFullScreen" value="true"> ' +
'<param value="always" name="allowScriptAccess"> ' +
'<param value="transparent" name="wmode"> ' +
'<embed width="' + width + '" height="' + height + '" name="' + id + '" align="middle" pluginspage="http://www.macromedia.com/go/getflashplayer" type="application/x-shockwave-flash" allowfullscreen="true" allowscriptaccess="always" loop="false" play="true" bgcolor="#E0E0E0" quality="high" wmode="transparent" name="vMessage" src="' + url + '"> ' +
'</object>';
return _html;
}
function getFlashMovieObject(movieName) {
if (window.document[movieName]) {
return window.document[movieName];
}
if (navigator.appName.indexOf('Microsoft Internet') === -1) {
if (document.embeds && document.embeds[movieName]) {
return document.embeds[movieName];
}
} else { // if (navigator.appName.indexOf("Microsoft Internet")!=-1)
return document.getElementById(movieName);
}
}
/**
* 上传图片,点击确定时调用
*/
function uploadImage() {
var viFlash = getFlashMovieObject('head');
viFlash.upload_image();
}
module.exports = {
swfobject,
uploadImage
};
... ...
... ... @@ -20,9 +20,7 @@ var disableSMSBtn = function() {
second -= 1;
if (second < 0) {
second = 60;
$sms.text('获取短信验证码');
$sms.removeClass('disable');
$sms.removeClass('progress');
$sms.removeClass('progress').removeClass('disable').text('获取短信验证码');
} else {
$sms.add('progress');
$sms.text(second + '秒后可重新操作');
... ...
/**
* 找回密码
* @author: xuqi<qi.xu@yoho.cn>
* @date: 2015/12/14
* @author: TaoHuang
* @date: 2016/7/18
*/
var $ = require('yoho-jquery'),
... ... @@ -18,7 +18,6 @@ var $regionCodeText = $('#country-code'),
$nextBtn = $('#find-btn'),
$form = $('#back-form');
var emailRegx = regx.emailRegx,
phoneRegx = regx.phoneRegx;
... ... @@ -45,6 +44,9 @@ function hideTip(ele) {
require('yoho-jquery-placeholder');
/**
* 刷新图形验证码
*/
function refreshImgCaptcha() {
var time = new Date(),
$captchaImg = $('#captcha-img'),
... ... @@ -53,12 +55,15 @@ function refreshImgCaptcha() {
$('#captcha-img').attr('src', captchaImgSrc + '?t=' + time.getTime());
}
/**
* 异步验证手机是否有人注册
*/
function validatePhoneNumAsync() {
return $.ajax({
type: 'POST',
url: '/passport/back/authcode',
data: {
phoneNum: $phoneNumInput.val(),
phoneNum: $.trim($phoneNumInput.val()),
area: $regionCodeText.text()
}
}).then(function(data) {
... ... @@ -74,11 +79,18 @@ function validatePhoneNumAsync() {
});
}
/**
* 提交结果
*/
function nextStep(url) {
$form.attr('action', url);
$form.submit();
}
/**
* 本地验证手机号
* 注意:国际号码不做验证
*/
function validatePhoneNumLocal() {
var val = $.trim($phoneNumInput.val());
... ... @@ -110,6 +122,9 @@ function validatePhoneNumLocal() {
}
}
/**
* 整合本地和异步验证
*/
function validatePhoneNum() {
function validate() {
var defer = $.Deferred(); //eslint-disable-line
... ... @@ -138,6 +153,9 @@ function validatePhoneNum() {
});
}
/**
* 本地图形验证码验证
*/
function validateImgCaptchaLocal() {
var v = $.trim($imgCaptchaInput.val());
... ... @@ -152,6 +170,9 @@ function validateImgCaptchaLocal() {
return true;
}
/**
* 异步验证图形验证码
*/
function validateImgCaptchaAsync() {
return $.ajax({
type: 'POST',
... ... @@ -169,6 +190,9 @@ function validateImgCaptchaAsync() {
});
}
/**
* 整合本地和异步验证过程
*/
function validateImgCaptcha() {
function validate() {
var defer = $.Deferred(); //eslint-disable-line
... ... @@ -196,6 +220,9 @@ function validateImgCaptcha() {
});
}
/**
* 邮箱自动补全
*/
emailAc($phoneNumInput, function() {
validatePhoneNum();
});
... ... @@ -207,6 +234,7 @@ $('input').placeholder();
exports.init = function() {
// 监听事件 phone-num 和 captcha-img
ep.tail('phone-num', 'captcha-img', function(phoneAuth, imgAuth) {
if (phoneAuth && imgAuth) {
$nextBtn.removeClass('disable');
... ... @@ -215,12 +243,14 @@ exports.init = function() {
}
});
// 监听事件 phone-num
ep.on('phone-num', function(auth) {
if (auth) {
hideTip($phoneNumInput);
}
});
// 监听事件 captcha-img
ep.on('captcha-img', function(auth) {
if (auth) {
hideTip($imgCaptchaInput);
... ... @@ -264,6 +294,7 @@ exports.init = function() {
refreshImgCaptcha();
});
// 变换图标
function changeHeader() {
var $indicator = $regionSelectHeader.find('.iconfont');
... ... @@ -281,11 +312,9 @@ exports.init = function() {
var name = $clickItem.data('value');
var $selectedItem = $clickItem.siblings('.selected');
$selectedItem.find('.iconfont').html('');
$selectedItem.removeClass('selected');
$selectedItem.find('.iconfont').html('').removeClass('selected');
$clickItem.find('.iconfont').html(selectedIcon);
$clickItem.addClass('selected');
$clickItem.find('.iconfont').html(selectedIcon).addClass('selected');
$regionSelectHeader.find('.name').html(name);
$regionCodeText.text(areaCode);
... ...
/**
* 找回密码
* @author: xuqi<qi.xu@yoho.cn>
* @date: 2015/12/14
* 找回密码设置密码
* @author: TaoHuang
* @date: 2016/7/18
*/
var $ = require('yoho-jquery');
... ... @@ -34,11 +34,12 @@ require('yoho-jquery-placeholder');
// IE8 placeholder
$('input').placeholder();
// 同时监听 pwd 和 repwd 事件
ep.tail('pwd', 'repwd', function(pwd, repwd) {
if (pwd && repwd) {
$next.removeClass('disable');
$next.removeClass('disable').prop('disabled', false);
} else {
$next.addClass('disable');
$next.addClass('disable').prop('disabled', true);
}
});
... ... @@ -84,12 +85,14 @@ $repasswordInput.on('keyup blur', function() {
ep.emit('repwd', true);
});
// 监听 repwd 事件
ep.on('repwd', function(repwdAuth) {
if (repwdAuth) {
hideTip($repasswordInput);
}
});
// 监听 pwd 事件
ep.on('pwd', function(pwdAuth) {
if (pwdAuth) {
hideTip($passwordInput);
... ...
... ... @@ -24,6 +24,7 @@ function hideTip(ele) {
return ele.next('.tips').addClass('hide');
}
// 发送短信验证码
function sendSMSCaptchaAsync() {
return $.post('/passport/back/sendbackmobile', {
mobile: $('#mobile').val(),
... ... @@ -36,12 +37,9 @@ function disableSMSBtn() {
second -= 1;
if (second < 0) {
second = 60;
$smsCaptchaCtrl.text('获取短信验证码');
$smsCaptchaCtrl.removeClass('disable');
$smsCaptchaCtrl.removeClass('second-progress');
$smsCaptchaCtrl.text('获取短信验证码').removeClass('disable').removeClass('second-progress');
} else {
$smsCaptchaCtrl.addClass('second-progress');
$smsCaptchaCtrl.text(second + '秒后可重新操作');
$smsCaptchaCtrl.addClass('second-progress').text(second + '秒后可重新操作');
window.setTimeout(disableSMSBtn, 1000);
}
}
... ...
/**
* Created by TaoHuang on 2016/6/21.
*/
require('./bind/third-pwd');
... ...
/**
* Created by TaoHuang on 2016/6/21.
*/
require('./bind/third-login');
... ...
... ... @@ -48,20 +48,19 @@ function hideTip(ele) {
return ele.next('.tips').addClass('hide');
}
// 短信验证码60s时间
function disableSMSBtn() {
second -= 1;
if (second < 0) {
second = 60;
$smsCaptchaCtrl.text('获取短信验证码');
$smsCaptchaCtrl.removeClass('disable');
$smsCaptchaCtrl.removeClass('second-progress');
$smsCaptchaCtrl.text('获取短信验证码').removeClass('disable').removeClass('second-progress');
} else {
$smsCaptchaCtrl.addClass('second-progress');
$smsCaptchaCtrl.text(second + '秒后可重新操作');
$smsCaptchaCtrl.addClass('second-progress').text(second + '秒后可重新操作');
window.setTimeout(disableSMSBtn, 1000);
}
}
// 发送短信验证码
function sendSMSCaptcha() {
return $.ajax({
type: 'POST',
... ... @@ -73,6 +72,7 @@ function sendSMSCaptcha() {
});
}
// 刷新图形验证码
function refreshImgCaptcha() {
var time = new Date(),
$captchaImg = $('.img-captcha'),
... ... @@ -81,7 +81,8 @@ function refreshImgCaptcha() {
$captchaImg.attr('src', captchaImgSrc + '?t=' + time.getTime());
}
function validateImgCaptcha() {
// 异步验证图形码
function validateImgCaptchaAsync() {
return $.ajax({
type: 'POST',
url: '/passport/images/check',
... ... @@ -91,7 +92,8 @@ function validateImgCaptcha() {
});
}
function validateSMSCaptcha() {
// 异步验证短信码
function validateSMSCaptchaAsync() {
return $.ajax({
type: 'POST',
url: '/passport/autouserinfo/checkBindMsg',
... ... @@ -103,6 +105,7 @@ function validateSMSCaptcha() {
});
}
// 同时监听三个事件
ep.tail('phoneNum', 'img-captcha', 'sms-captcha', function(phoneAuth, imgAuth, smsAuth) {
if (phoneAuth && imgAuth && smsAuth) {
... ... @@ -113,6 +116,7 @@ ep.tail('phoneNum', 'img-captcha', 'sms-captcha', function(phoneAuth, imgAuth, s
});
// 选择国家,变换图标
function changeHeader() {
var $indicator = $regionSelectHeader.find('.iconfont');
... ... @@ -130,11 +134,9 @@ $regionSelectList.on('click', '.option', function() {
var name = $clickItem.data('value');
var $selectedItem = $clickItem.siblings('.selected');
$selectedItem.find('.iconfont').html('');
$selectedItem.removeClass('selected');
$selectedItem.find('.iconfont').html('').end().removeClass('selected');
$clickItem.find('.iconfont').html(selectedIcon);
$clickItem.addClass('selected');
$clickItem.find('.iconfont').html(selectedIcon).end().addClass('selected');
$regionSelectHeader.find('.name').html(name);
$regionCodeText.text(areaCode);
... ... @@ -149,6 +151,7 @@ $regionSelectHeader.on('click', function() {
changeHeader();
});
// 确定事件都验证通过
ep.tail('phoneNum', 'img-captcha', function(phoneAuth, imgAuth) {
if (phoneAuth && imgAuth && !$smsCaptchaCtrl.hasClass('second-progress')) {
$smsCaptchaCtrl.removeClass('disable');
... ... @@ -208,7 +211,7 @@ $imgCaptchaInput.on('blur', function() {
break;
}
validateImgCaptcha().then(function(result) {
validateImgCaptchaAsync().then(function(result) {
if (result.code === 200) {
ep.emit('img-captcha', true);
} else {
... ... @@ -240,7 +243,7 @@ $smsCaptchaInput.on('blur', function() {
return;
}
validateSMSCaptcha().then(function(result) {
validateSMSCaptchaAsync().then(function(result) {
if (result.code === 200) {
ep.emit('sms-captcha', true);
} else {
... ... @@ -263,11 +266,13 @@ $smsCaptchaCtrl.on('click', function() {
sendSMSCaptcha();
});
// 统一设置用户信息
function setUserInfo(user) {
$('.username').val(user.username);
$('.headImg').val(user.headImg);
}
// 统一设置第三方的信息
function setThirdPartInfo(third) {
$('.openId').val(third.openId);
$('.sourceType').val(third.sourceType);
... ... @@ -278,29 +283,34 @@ function setThirdPartInfo(third) {
$('.code').val(third.code);
}
// 发送数据到设置密码页面
function setPwdPage(thirdPart) {
setThirdPartInfo(thirdPart);
$bindsetpwdForm.submit();
}
// 发送数据到绑定确认页面
function bindConfirmPage(thirdPart, user) {
setThirdPartInfo(thirdPart);
setUserInfo(user);
$bindConfirmForm.submit();
}
// 发送数据到关联页面
function relateConfirmPage(thirdPart, user) {
setThirdPartInfo(thirdPart);
setUserInfo(user);
$relateConfirmForm.submit();
}
// 发送数据到已绑定页面
function bindedPage(thirdPart, user) {
setThirdPartInfo(thirdPart);
setUserInfo(user);
$bindedForm.submit();
}
// 下一步
function nextPage() {
var thirdPart = {
mobile: $phoneNumInput.val(),
... ...
... ... @@ -34,6 +34,7 @@ function hideTip(ele) {
return ele.next('.tips').addClass('hide');
}
// 确保二次密码输入正确
ep.tail('pwd', 'repwd', function(pwd, repwd) {
if (pwd && repwd) {
$next.removeClass('disable');
... ... @@ -88,6 +89,7 @@ $repasswordInput.on('keyup blur', function() {
hideTip($repasswordInput);
});
// 下一步
function nextPage() {
$.ajax({
type: 'POST',
... ...
/**
* Created by TaoHuang on 2016/6/21.
*/
require('./login/index');
... ...
... ... @@ -95,6 +95,7 @@ function validateAccountLocal() {
}
}
// 异步验证帐号是否存在
function validateAccountAsync() {
return $.ajax({
type: 'POST',
... ... @@ -113,6 +114,7 @@ function validateAccountAsync() {
});
}
// 整合本地和异步验证信息
function validateAccount() {
function validate() {
var defer = $.Deferred(); // eslint-disable-line
... ... @@ -229,6 +231,7 @@ function login() {
});
}
// 邮箱自动补全,并验证信息
mailAc($phoneNumInput, function() {
function throttle() {
return $.ajax({
... ... @@ -266,6 +269,7 @@ $phoneNumInput.on('focus', function() {
$('[placeholder]').placeholder();
// 改变选择图标
function changeHeader() {
var $indicator = $regionSelectHeader.find('.iconfont');
... ... @@ -283,11 +287,9 @@ $regionSelectList.on('click', '.option', function() {
var name = $clickItem.data('value');
var $selectedItem = $clickItem.siblings('.selected');
$selectedItem.find('.iconfont').html('');
$selectedItem.removeClass('selected');
$selectedItem.find('.iconfont').html('').removeClass('selected');
$clickItem.find('.iconfont').html(selectedIcon);
$clickItem.addClass('selected');
$clickItem.find('.iconfont').html(selectedIcon).addClass('selected');
$regionSelectHeader.find('.name').html(name);
$regionCodeText.text(areaCode);
... ... @@ -350,6 +352,7 @@ if (($phoneNumInput.val() !== '' || $phoneNumInput.val() === $phoneNumInput.attr
$passwordInput.focus();
}
// 同时监听三个事件
ep.tail('phone', 'password', 'captcha', function(phoneAuth, passwordAuth, captchaAuth) {
if (phoneAuth && passwordAuth && captchaAuth) {
$loginBtn.removeClass('auth_ok');
... ...
/**
* Created by TaoHuang on 2016/6/21.
*/
var reg = require('./reg/reg');
reg.init('reg');
reg.init();
... ...
... ... @@ -190,8 +190,8 @@ function validateSMSCaptchaAsync() {
type: 'POST',
url: '/passport/reg/msgcaptcha',
data: {
code: $smsCaptchaInput.val(),
mobile: $phoneNumInput.val(),
code: $.trim($smsCaptchaInput.val()),
mobile: $.trim($phoneNumInput.val()),
area: $regionCodeText.text().split('+')[1]
}
}).then(function(data) {
... ... @@ -239,7 +239,7 @@ function validateSMSCaptcha() {
}
function validatePhoneNumLocal() {
var phoneNum = $phoneNumInput.val(),
var phoneNum = $.trim($phoneNumInput.val()),
length = phoneNum.length,
regionCode = $regionCodeText.text();
... ... @@ -310,6 +310,7 @@ function validatePasswordLocal() {
}
}
// 验证密码合法性
function validatePassword() {
function validate() {
var defer = $.Deferred(); // eslint-disable-line
... ... @@ -359,13 +360,14 @@ function validatePasswordComplexLocal($obj) {
}
}
// 注册
function register() {
$.ajax({
type: 'POST',
url: '/passport/reg/mobileregister',
data: {
area: $regionCodeText.text().split('+')[1],
mobile: $phoneNumInput.val(),
mobile: $.trim($phoneNumInput.val()),
verifyCode: $imgCaptchaInput.val(),
code: $smsCaptchaInput.val(),
password: $passwordInput.val()
... ... @@ -406,28 +408,27 @@ function register() {
});
}
// 发送短信验证码
function sendSMSCaptcha() {
$.ajax({
type: 'POST',
url: '/passport/reg/sendBindMsg',
data: {
area: $regionCodeText.text().split('+')[1],
mobile: $phoneNumInput.val(),
mobile: $.trim($phoneNumInput.val()),
verifyCode: $imgCaptchaInput.val()
}
});
}
// 短信验证码重新发送
function disableSMSBtn() {
second -= 1;
if (second < 0) {
second = 60;
$smsCaptchaCtrl.text('获取短信验证码');
$smsCaptchaCtrl.removeClass('disable');
$smsCaptchaCtrl.removeClass('second-progress');
$smsCaptchaCtrl.text('获取短信验证码').removeClass('disable').removeClass('second-progress');
} else {
$smsCaptchaCtrl.addClass('second-progress');
$smsCaptchaCtrl.text(second + '秒后可重新操作');
$smsCaptchaCtrl.addClass('second-progress').text(second + '秒后可重新操作');
window.setTimeout(disableSMSBtn, 1000);
}
}
... ... @@ -524,11 +525,9 @@ exports.init = function() {
var name = $clickItem.data('value');
var $selectedItem = $clickItem.siblings('.selected');
$selectedItem.find('.iconfont').html('');
$selectedItem.removeClass('selected');
$selectedItem.find('.iconfont').html('').removeClass('selected');
$clickItem.find('.iconfont').html(selectedIcon);
$clickItem.addClass('selected');
$clickItem.find('.iconfont').html(selectedIcon).addClass('selected');
$regionSelectHeader.find('.name').html(name);
$regionCodeText.text(areaCode);
... ...
... ... @@ -25,8 +25,9 @@ function _favBrand(brandId, isAdd) {
}
$('#brand-fav').click(function() {
var shopId = $(this).parents('.brand-banner').data('shop');
var brandId = $(this).parents('.brand-banner').data('brand');
var $banner = $(this).parents('.brand-banner');
var shopId = $banner.data('shop');
var brandId = $banner.data('brand');
var isAdd = $(this).hasClass('coled');
if (shopId) {
... ...
... ... @@ -9,6 +9,7 @@ var YohoListPage = {
rootDoc: $('.yoho-product-list'),
brandsDoc: $('.yoho-product-list .brand-list'),
mulitBrand: false,
mulitStyle: false,
goodsWrapper: $('.goods-area .goods-wrapper'),
goodsWrapperState: false,
page: query.page || 1,
... ... @@ -20,23 +21,7 @@ var YohoListPage = {
require('../../common/header');
lazyload();
$('.nano').nanoScroller();
$('.yoho-ui-accordion', this.rootDoc).each(function() {
var opts = {
collapsible: true,
heightStyle: 'content',
active: 0
};
if ($(this).hasClass('no-active')) {
opts.active = false;
}
$(this).find('h3').each(function(index) {
if ($(this).hasClass('active')) {
opts.active = index;
}
});
$(this).accordion(opts);
});
YohoListPage.initAccordion();
$('.sex-body .input-radio', this.rootDoc).check({
type: 'radio',
... ... @@ -57,7 +42,8 @@ var YohoListPage = {
YohoListPage.go({
msort: categoryId,
misort: subCategoryId
misort: subCategoryId,
page: 1
});
}
});
... ... @@ -98,9 +84,61 @@ var YohoListPage = {
YohoListPage.go({color: $(this).data('value')});
});
$('.style-body .input-radio', this.rootDoc).check({
type: 'radio',
group: 'style',
onChange: function(ele, checked, value) {
if (!YohoListPage.mulitStyle) {
YohoListPage.go({style: value});
} else {
$('.style-btns', this.rootDoc).removeClass('hide');
if ($('.style-body .input-radio', this.rootDoc).check('getChecked').values.length > 0) {
$('.style-btns .confirm', this.rootDoc).removeClass('disable');
} else {
$('.style-btns .confirm', this.rootDoc).addClass('disable');
}
}
}
});
$('.standard-body .input-radio', this.rootDoc).check({
type: 'radio',
group: 'standard',
onChange: function(ele, checked, value) {
var parentId = $(ele).parents('.body').data('value');
YohoListPage.go({
standard: parentId + ',' + value
});
}
});
YohoListPage.eventBind();
},
initAccordion() {
$('.yoho-ui-accordion', this.rootDoc).each(function() {
var opts = {
collapsible: true,
heightStyle: 'content',
active: 0
};
if ($(this).hasClass('no-active')) {
opts.active = false;
}
$(this).find('h3').each(function(index) {
if ($(this).hasClass('active')) {
opts.active = index;
}
});
$(this).accordion(opts);
});
},
eventBind: function() {
$(window).resize(function() {
YohoListPage.initAccordion();
});
$('.mulit-choose', this.rootDoc).click(function() {
YohoListPage.openBrandMulitChoose();
});
... ... @@ -132,6 +170,18 @@ var YohoListPage = {
}
});
$('.style-btns .cancel', this.rootDoc).click(function() {
YohoListPage.closeStyleMulit();
});
$('.style-btns .confirm', this.rootDoc).click(function() {
if (!$(this).hasClass('disable')) {
YohoListPage.go({
style: $('.style-body .input-radio', YohoListPage.rootDoc).check('getChecked').values.join(',')
});
}
});
$('.yoho-product-list .brand-body input').on('keyup', function() {
YohoListPage.filterBrand($(this).val().toLowerCase());
});
... ... @@ -229,6 +279,14 @@ var YohoListPage = {
});
}
});
$('.style-mulit-btn .btn', this.rootDoc).click(function() {
if ($(this).hasClass('white')) {
YohoListPage.openStyleMulit();
} else {
YohoListPage.closeStyleMulit();
}
});
},
openBrandMulitChoose: function() {
$('.yoho-product-list .mulit-choose').hide();
... ... @@ -248,6 +306,26 @@ var YohoListPage = {
type: 'radio'
});
},
openStyleMulit: function() {
$('.style-btns', this.rootDoc).removeClass('hide');
$('.style-body .input-radio', this.rootDoc).check({
type: 'checkbox'
});
YohoListPage.mulitStyle = true;
$('.style-mulit-btn .btn').removeClass('white');
},
closeStyleMulit: function() {
$('.style-btns', this.rootDoc).addClass('hide');
$('.style-body .input-radio', this.rootDoc).check('unCheckAll');
$('.style-body .input-radio', this.rootDoc).check({
type: 'radio'
});
YohoListPage.mulitStyle = false;
$('.style-mulit-btn .btn').addClass('white');
},
showBrandMulitBtn: function() {
$('.brand-btns', this.rootDoc).removeClass('hide');
if (YohoListPage.getSelectBrands().length > 0) {
... ...
... ... @@ -277,14 +277,14 @@ var Cart = {
* @params { Function } callback 移入收藏夹成功后回调
*/
sendToFavorite: function(products, callback) {
var msg = '确定要将该商品从购物车中移入收藏吗?<br/>移入收藏后该商品将不在购物车中显示';
var msg = '<p>确定要将该商品从购物车中移入收藏吗?</p><p>移入收藏后该商品将不在购物车中显示</p>';
var dialog;
if (!products.length) {
new _alert('请至少选中一件商品!').show();
} else {
if (products.length > 1) {
msg = '确定要将已选中的商品从购物车中移入收藏吗?<br/>移入收藏后已选中的商品将不在购物车中显示';
msg = '<p>确定要将已选中的商品从购物车中移入收藏吗?</p><p>移入收藏后已选中的商品将不在购物车中显示</p>';
}
// callback存在说明从删除模块收藏
... ...
... ... @@ -5,7 +5,6 @@
*/
var $ = require('yoho-jquery'),
Hbs = require('yoho-handlebars'),
lazyLoad = require('yoho-jquery-lazyload');
var Alert = require('../plugins/dialog').Alert;
... ... @@ -34,7 +33,7 @@ var $printPrice = $('#print-price');
var $invoice = $('#invoice-content');
var balanceTpl = Hbs.compile($('#balance-tpl').html());
var balanceTpl = require('../../tpl/shopping/balance.hbs');
var pkgCache = {};
... ... @@ -47,13 +46,6 @@ require('../plugins/check'); // before 地址和发票
require('./order/address'); // 地址
require('./order/invoice'); // 发票
// clint helper round
Hbs.registerHelper('round', function(num, precision) {
precision = precision ? parseInt(precision, 10) : 2;
num = (num === +num) ? (+num).toFixed(precision) : (Math.round(num, precision)).toFixed(precision);
return num;
});
lazyLoad($('img.lazy'));
// dot
... ... @@ -260,7 +252,7 @@ $('.print-price-radio').check({
$('#balance-list').on('click', '#submit-order', function() {
var reqParam = {
address_id: $('.address.focus').data('id'),
yohoCoin: getCoinUsed(),
use_yoho_coin: getCoinUsed(),
remark: $('#remark-content').val(),
isPrintPrice: $printPrice.printPrice
};
... ...
... ... @@ -5,7 +5,6 @@
*/
var $ = require('yoho-jquery'),
Hbs = require('yoho-handlebars'),
cascadingAddress = require('../../plugins/cascading-address'),
common = require('../../common'),
popup = require('../../plugins/dialog');
... ... @@ -41,17 +40,8 @@ function setAllOfAddress() {
}
}
// 判断是否是Y
Hbs.registerHelper('isY', function(value, options) {
if (value === 'Y') {
return options.fn(this);
} else {
return options.inverse(this);
}
});
addressDialogTpl = Hbs.compile($('#address-dialog-tpl').html());
addressTpl = Hbs.compile($('#address-list-tpl').html());
addressDialogTpl = require('../../../tpl/shopping/address-dialog.hbs');
addressTpl = require('../../../tpl/shopping/address-list.hbs');
// address dialog 数据验证
function validateAddress($el) {
... ...
... ... @@ -5,10 +5,9 @@
*/
var $ = require('yoho-jquery'),
hbs = require('yoho-handlebars'),
Dialog = require('../../plugins/dialog').Dialog;
var checkedInvoiceTpl = hbs.compile($('#checked-invoice-show-tpl').html());
var checkedInvoiceTpl = require('../../../tpl/shopping/checked-invoice-show.hbs');
var $invoiceContent = $('#invoice-content');
... ...
... ... @@ -314,7 +314,7 @@
.search-key {
width: 260px;
height: 30px;
padding: 10px;
padding: 0 10px;
background: none;
border: none;
color: #fff;
... ...
... ... @@ -8,17 +8,23 @@
.iconfont {
font-size: 30px;
position: absolute;
top: 0;
left: 0;
}
.icon-back {
width: 90%;
height: 90%;
margin: 5%;
}
.icon-cover {
color: #fff;
color: #fefefe;
}
.icon-round {
color: #eee;
top: 0;
left: 0;
position: absolute;
}
&.cur .icon-round {
... ...
... ... @@ -80,6 +80,8 @@
overflow: hidden;
text-overflow: ellipsis;
line-height: 18px;
margin-top: 10px;
padding: 0 10px;
}
.price {
... ... @@ -118,7 +120,7 @@
.slide-switch {
display: block;
position: absolute;
top: 70px;
top: 90px;
width: 100%;
.iconfont {
... ...
... ... @@ -14,6 +14,29 @@
margin: $space 0;
}
.refund-tag {
width: 55%;
padding: 5px 0;
border-radius: 10px;
margin: 0 auto;
background-color: orange;
color: #fff;
}
.change-tag {
margin: 10px auto 0;
color: #1b1b1b;
&:hover {
background-color: #1b1b1b;
color: #fff;
}
}
a.disable {
color: #ccc;
}
.badge {
min-width: 16px;
line-height: 16px;
... ...
... ... @@ -21,6 +21,24 @@
}
}
.iconfont {
&.checkbox {
position: relative;
top: -70px;
margin-right: 10px;
font-size: 14px;
cursor: pointer;
}
}
.warn {
font-size: 12px;
.iconfont {
font-size: 18px;
}
}
.header {
.info {
width: 540px;
... ... @@ -156,16 +174,6 @@
}
}
.iconfont {
&.checkbox {
position: relative;
top: -70px;
margin-right: 10px;
font-size: 14px;
cursor: pointer;
}
}
img.envidence {
width: 60px;
height: 60px;
... ...
... ... @@ -40,6 +40,14 @@
.cancel-btn {
display: inline-block;
}
.online-service {
margin-left: 14px;
> * {
font-size: 14px;
}
}
}
.return-express {
... ...
... ... @@ -57,6 +57,10 @@
line-height: 1.5;
}
.title:hover {
text-decoration: underline;
}
.num > * {
height: 28px;
line-height: 28px;
... ... @@ -77,6 +81,33 @@
width: 40px;
}
.limit-return {
width: 100%;
height: auto;
text-align: left;
line-height: 1;
padding-top: 20px;
padding-left: 70px;
}
.limit-return .iconfont {
font-size: 14px;
}
.limit-return-tip {
font-size: 12px;
padding-right: 16px;
position: relative;
}
.limit-return-tip:hover {
cursor: pointer;
}
.limit-return-tip:hover .limit-return-wrap {
display: block;
}
.special-reason {
width: 100%;
height: auto;
... ... @@ -91,6 +122,28 @@
border: 1px solid #eee;
}
}
.limit-return-wrap {
width: 280px;
line-height: 1.5;
background: #fff;
padding: 10px;
color: #1d1d1d;
border: 2px solid #bcbcbc;
position: absolute;
left: 100%;
top: -8px;
display: none;
.code-horn {
width: 7px;
height: 12px;
background: resolve('me/code-horn.png') no-repeat;
position: absolute;
left: -7px;
top: 6px;
}
}
}
.refund-type {
... ... @@ -113,6 +166,11 @@
}
}
.type-tip {
line-height: 38px;
color: #999;
}
.ali-item {
background: resolve('me/alipay.png') no-repeat center center;
}
... ...