Authored by 毕凯

Merge remote-tracking branch 'origin/master' into feature/trendRecode

Showing 73 changed files with 2803 additions and 995 deletions

Too many changes to show.

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

... ... @@ -196,6 +196,7 @@ try {
const layoutTools = require('./doraemon/middleware/layout-tools');
const seo = require('./doraemon/middleware/seo');
const pageCache = require('./doraemon/middleware/page-cache');
const downloadBar = require('./doraemon/middleware/download-bar');
// YOHO 前置中间件
app.use(tdkUrl());
... ... @@ -213,8 +214,9 @@ try {
}
app.use(layoutTools());
app.use(pageCache());
app.use(downloadBar());
require('./dispatch')(app);
app.all('*', errorHanlder.notFound()); // 404
... ...
... ... @@ -16,9 +16,14 @@ exports.submit = (req, res) => {
remoteIp = arr[0];
}
let key = `pc:limiter:${remoteIp}`;
let key10m = `pc:limiter:10m:${remoteIp}`;
cache.delAsync(key).then(() => {
Promise.all([
cache.delAsync(key),
cache.delAsync(key10m)
]).then(() => {
return res.json({
code: 200
});
... ...
'use strict';
const materialModel = require('../models/material-new');
const headerModel = require('../../../doraemon/models/header'); // 头部model
exports.list = (req, res, next) => {
let responseData = {
pageHeader: headerModel.setNav({
navTitle: '商品素材列表页',
}),
title: '商品素材列表页',
module: '3party',
page: 'material-new',
width750: true,
localCss: true
};
let params = {
uid: req.user.uid,
page: 1,
isApp: req.yoho.isApp,
unionType: req.query.union_type
};
req.ctx(materialModel).canLogin(params).then(result => {
if (result === 'N') {
return next();
} else {
req.ctx(materialModel).list(params).then(list => {
res.render('material-new', Object.assign(responseData, list));
}).catch(next);
}
}).catch(next);
};
... ...
'use strict';
const semver = require('semver');
const questionModel = require('../models/question');
const headerModel = require('../../../doraemon/models/header'); // 头部model
exports.list = (req, res, next) => {
let canShare = false;
if (req.yoho.isApp && req.query.app_version) {
let appVersion = req.query.app_version.split('.');
appVersion = `${appVersion[0]}.${appVersion[1]}.${appVersion[2]}`;
if (!semver.lt(appVersion, '5.9.0')) {
canShare = true;
}
}
req.ctx(questionModel).getQuestionList().then(result => {
res.render('question/list', {
title: '调研中心',
... ... @@ -14,6 +27,7 @@ exports.list = (req, res, next) => {
}),
list: result,
isApp: req.yoho.isApp,
canShare: canShare,
localCss: true
});
}).catch(next);
... ... @@ -45,7 +59,7 @@ exports.submit = (req, res, next) => {
// 标识问卷来源
if (req.yoho.isApp) {
params.sourceType = 'APP';
} else if (req.yoho.mobile) {
} else if (req.yoho.isMobile) {
params.sourceType = 'H5';
} else {
params.sourceType = 'PC';
... ...
... ... @@ -40,7 +40,7 @@ const itemXmlData = () => {// eslint-disable-line
return api.get('', {method: 'web.product.bdPromotion'}, {cache: 86400}).then(res => {
_.forEach(_.get(res, 'data', ''), val => {
urls.push({
url: 'https:' + helpers.urlFormat(`/product/${val.id}.html`, '', null),
url: 'https:' + helpers.urlFormat(`/product/${val.erpProductId}.html`, '', null),
changefreq: 'daily',
priority: 0.3
});
... ...
'use strict';
const platformApi = new global.yoho.ApiBase(global.yoho.config.domains.platformApi, {
name: 'imCs',
cache: global.yoho.cache,
useCache: false
});
const _ = require('lodash');
const utils = '../../../utils';
const productProcess = require(`${utils}/product-process`);
class materialModel extends global.yoho.BaseModel {
constructor(ctx) {
super(ctx);
}
canLogin(params) {
return platformApi.get('/platform/product/material/canlogin', {
uid: params.uid
}).then(result => {
if (result && result.code === 200) {
return result.data.canLogin;
}
});
}
list(params) {
let options = {
data: {
method: 'app.search.recommendProduct',
type: 'default',
limit: 24
},
param: {
code: 200
}
};
return this.get(options).then(result => {
if (result && result.code === 200) {
let resu = {
goods: []
};
if (_.get(result, 'data.product_list', [])) {
let build = [];
build = productProcess.processProductList(result.data.product_list || [], {
isApp: params.isApp,
showSimilar: false
});
if (params.unionType) {
_.forEach(build, (val) => {
let newUrl = val.url;
val.url = newUrl.replace('.html', `.html?union_type=${params.unionType}`);
});
}
resu.goods = build;
}
return resu;
}
});
}
}
module.exports = materialModel;
... ...
... ... @@ -6,6 +6,32 @@
const _ = require('lodash');
const _fillQuestionContents = data => {
if (data && +data.questionType === 3) {
data.questionContents = _.fill(Array(data.fillBlankNum || 1), true);
}
return data;
};
const _handelSubQuestion = (qs, jid) => {
if (qs) {
qs = _.concat([], qs);
_.forEach(qs, value => {
Object.assign(value, {
subQs: true,
jid: jid
});
_fillQuestionContents(value);
});
}
return qs;
};
module.exports = class extends global.yoho.BaseModel {
constructor(ctx) {
super(ctx);
... ... @@ -25,7 +51,7 @@ module.exports = class extends global.yoho.BaseModel {
}
});
return list;
return _.isEmpty(list) ? false : list;
});
}
getQuestionStatus(params) {
... ... @@ -54,10 +80,21 @@ module.exports = class extends global.yoho.BaseModel {
let data = _.get(result, '[1].data', {});
if (data.questions) {
_.forEach(data.questions, value => {
if (+value.questionType === 3) {
value.questionContents = _.fill(Array(value.fillBlankNum || 1), true);
_.forEach(data.questions, (value, key) => {
if (!_.isEmpty(value.questionContents)) {
_.forEach(value.questionContents, (subval, subkey) => {
if (!subval.jumpQuestion) {
return;
}
value.hasSub = true;
subval.jid = `${key}-${subkey}`;
subval.jumpQuestion = _handelSubQuestion(subval.jumpQuestion,
subval.jid);
});
}
_fillQuestionContents(value);
});
}
... ...
... ... @@ -13,7 +13,9 @@ const check = require(`${cRoot}/check`);
const question = require(`${cRoot}/question`);
const validateCode = require('../passport/controllers/validateCode');
const auth = require('../../doraemon/middleware/auth');
const material = require(`${cRoot}/material`);
// const material = require(`${cRoot}/material`);
const materialNew = require(`${cRoot}/material-new`);
// routers
... ... @@ -26,7 +28,6 @@ router.get('/questionnaire', auth, question.list);
router.post('/questionnaire/check', question.check);
router.post('/questionnaire/submit', question.submit);
router.get('/questionnaire/:id', auth, question.detail);
router.get('/material', auth, material.list);
router.get('/material/moreGoods', auth, material.moreGoods);
router.get('/material', auth, materialNew.list);
module.exports = router;
... ...
<div class="material-c reds-shop">
<div class="filter-box">
{{> product/filter-tab}}
{{> common/filter}}
</div>
<div id="all-goods" class="tab-panel active">
<div class="good-list-page yoho-page">
<div id="goods-container" class="goods-container">
<div class="default-goods container clearfix">
{{#goods}}
{{> common/goods}}
{{/goods}}
</div>
</div>
</div>
</div>
<input type="hidden" id="material-flag" value="material" />
</div>
... ...
... ... @@ -7,38 +7,17 @@
<div id="qs-wrap" class="qs-wrap" data-id="{{id}}" data-cid="{{uid}}" data-title="{{share.title}}" data-desc="{{share.subtitle}}" data-img="{{share.imgUrl}}">
{{# questions}}
<dl class="qs-item" data-index="{{questionIndex}}" data-type="{{questionType}}">
<dt>{{questionTitle}}</dt>
{{#isEqualOr questionType 1}}
{{# questionContents}}
<dd class="radio-option" data-index="{{@index}}">
<span class="iconfont">&#xe6ea;</span>
<div class="option-box">{{{option}}}</div>
{{#if addon}}
<input type="text">
{{/if}}
</dd>
{{/ questionContents}}
{{/isEqualOr}}
{{#isEqualOr questionType 2}}
{{# questionContents}}
<dd class="check-option" data-index="{{@index}}">
<span class="iconfont">&#xe6ea;</span>
<div class="option-box">{{{option}}}</div>
{{#if addon}}
<input type="text">
{{/if}}
</dd>
{{/ questionContents}}
{{/isEqualOr}}
{{> question/item}}
{{#isEqualOr questionType 3}}
{{#if hasSub}}
<div class="sub-qs-wrap">
{{# questionContents}}
<dd><textarea class="text-input"></textarea></dd>
{{# jumpQuestion}}
{{> question/item}}
{{/ jumpQuestion}}
{{/ questionContents}}
{{/isEqualOr}}
</dl>
</div>
{{/if}}
{{/ questions}}
</div>
... ...
<div class="qs-list-page">
{{#if list}}
<ul id="qs-list" class="qs-list">
<ul id="qs-list" class="qs-list{{#if canShare}} can-share{{/if}}">
{{#each list}}
<li data-id="{{id}}" data-title="{{title}}" data-desc="{{share.subtitle}}" data-img="{{share.imgUrl}}">{{index}}.{{title}}</li>
{{/each}}
</ul>
{{^}}
<div class="empty-list">
<p>调研问卷时间未开始,有货君正在生成调研问卷,<br>请您先逛一逛,稍后再来~~</p>
</div>
{{/if}}
<div id="tip-dialog" class="tip-dialog hide">
... ...
<dl class="{{#if subQs}}sub-qs-item sub-{{jid}} hide{{^}}qs-item{{/if}}" data-index="{{questionIndex}}" data-type="{{questionType}}">
<dt>{{questionTitle}}</dt>
{{#isEqualOr questionType 1}}
{{# questionContents}}
<dd class="radio-option" data-index="{{@index}}"{{#if jid}} data-jid="{{jid}}"{{/if}}>
<span class="iconfont">&#xe6ea;</span>
<div class="option-box">{{{option}}}</div>
{{#if addon}}
<input type="text">
{{/if}}
</dd>
{{/ questionContents}}
{{/isEqualOr}}
{{#isEqualOr questionType 2}}
{{# questionContents}}
<dd class="check-option" data-index="{{@index}}"{{#if jid}} data-jid="{{jid}}"{{/if}}>
<span class="iconfont">&#xe6ea;</span>
<div class="option-box">{{{option}}}</div>
{{#if addon}}
<input type="text">
{{/if}}
</dd>
{{/ questionContents}}
{{/isEqualOr}}
{{#isEqualOr questionType 3}}
{{# questionContents}}
<dd><textarea class="text-input"></textarea></dd>
{{/ questionContents}}
{{/isEqualOr}}
</dl>
... ...
/*
* @Author: Targaryen
* @Date: 2017-06-21 10:15:38
* @Last Modified by: Targaryen
*/
const _ = require('lodash');
const co = require('bluebird').coroutine;
const headerModel = require('../../../doraemon/models/header');
const BuyNowModel = require('../models/buy-now-model');
const addressModel = require('../models/address');
const userModel = require('../models/user');
const orderModel = require('../models/order');
const utils = '../../../utils';
const paymentProcess = require(`${utils}/payment-process`);
const crypto = global.yoho.crypto;
const logger = global.yoho.logger;
const helpers = global.yoho.helpers;
const camelCase = global.yoho.camelCase;
// cookie 参数
const actCkOpthn = {
path: '/cart/index'
};
class BuyNowController {
/**
* 确认订单页面
* @param {*} req
* @param {*} res
* @param {*} next
*/
orderEnsure(req, res, next) {
let orderInfo;
try {
orderInfo = JSON.parse(req.cookies.buynow_info);
} catch (e) {
logger.info(`orderEnsure: get buynow-order-info from cookie error:${JSON.stringify(e)}`);
orderInfo = {};
res.clearCookie('buynow_info', actCkOpthn);
}
let product_sku = req.query.product_sku;
let buy_number = req.query.buy_number;
if (!product_sku || !buy_number) {
return next();
}
if (product_sku !== orderInfo.product_sku) {
orderInfo = {};
}
co(function * () {
let result = yield req.ctx(BuyNowModel).payment({
uid: req.user.uid,
product_sku: product_sku,
sku_type: req.query.sku_type,
buy_number: buy_number,
yoho_coin_mode: parseInt(orderInfo.use_yoho_coin, 10) > 0 ? 1 : 0
});
let computeData = yield req.ctx(BuyNowModel).compute({
uid: req.user.uid,
product_sku: product_sku,
sku_type: req.query.sku_type,
buy_number: buy_number,
payment_type: orderInfo.payment_type,
delivery_way: orderInfo.delivery_way,
use_yoho_coin: parseInt(orderInfo.use_yoho_coin, 10),
coupon_code: orderInfo.coupon_code,
promotion_code: orderInfo.promotion_code
});
let validCouponCount = yield req.ctx(BuyNowModel).countUsableCoupon({
uid: req.user.uid,
product_sku: req.query.product_sku,
sku_type: req.query.sku_type,
buy_number: buy_number
});
let headerData = headerModel.setNav({
navTitle: '确认订单',
navBtn: false
});
// 兼容原有的数据格式
orderInfo.deliveryId = orderInfo.delivery_way;
orderInfo.deliveryTimeId = orderInfo.delivery_time;
orderInfo.couponCode = orderInfo.coupon_code;
orderInfo.yohoCoin = orderInfo.use_yoho_coin;
orderInfo.paymentType = orderInfo.payment_type;
let orderEnsure = _.assign(
paymentProcess.tranformPayment(result.data, orderInfo, null, null, computeData.data),
{
coupon: paymentProcess.coupon(
_.get(validCouponCount, 'data.count', 0),
orderInfo,
computeData.data
),
selectAddressUrl: helpers.urlFormat('/cart/index/buynow/selectAddress', {
product_sku: product_sku,
buy_number: buy_number
}),
selectCouponUrl: helpers.urlFormat('/cart/index/buynow/selectCoupon', {
product_sku: product_sku,
buy_number: buy_number
}),
isOrdinaryCart: true
}
);
return res.render('buynow/order-ensure', {
pageHeader: headerData,
module: 'buynow',
page: 'order-ensure',
title: '确认订单',
width750: true,
localCss: true,
product_sku: product_sku,
orderEnsure: orderEnsure
});
})().catch(next);
}
/**
* 参数更改,重新运算结算数据
* @param {*} req
* @param {*} res
* @param {*} next
*/
orderCompute(req, res, next) {
co(function * () {
let result = yield req.ctx(BuyNowModel).compute({
uid: req.user.uid,
cart_type: req.body.cart_type,
delivery_way: req.body.delivery_way,
payment_type: req.body.payment_type,
product_sku: req.body.product_sku,
buy_number: req.body.buy_number,
coupon_code: req.body.coupon_code,
use_yoho_coin: req.body.use_yoho_coin,
});
result.data.use_yoho_coin = paymentProcess.transPrice(result.data.use_yoho_coin);
result.data.yohoCoinCompute = paymentProcess.yohoCoinCompute(result.data);
return res.json(result.data);
})().catch(next);
}
/**
* 提交订单
* @param {*} req
* @param {*} res
* @param {*} next
*/
orderSub(req, res, next) {
let uid = req.user.uid;
let params = {
uid: uid,
product_sku: req.body.product_sku,
sku_type: req.body.sku_type,
buy_number: req.body.buy_number,
coupon_code: req.body.coupon_code,
address_id: parseInt(crypto.decrypt('', req.body.address_id), 10),
delivery_time: req.body.delivery_time,
delivery_way: req.body.delivery_way,
use_yoho_coin: req.body.use_yoho_coin,
use_red_envelopes: req.body.use_red_envelopes,
payment_id: req.body.payment_id,
payment_type: req.body.payment_type,
product_sku_list: req.body.product_sku_list,
is_print_price: req.body.is_print_price,
remark: req.body.remark,
activity_id: req.body.activity_id,
ip: req.yoho.clientIp
};
// 是否开发票
if (req.body.invoice && req.body.invoice === 'true') {
params.invoice = true;
params.invoices_type = req.body.invoices_type; // 发票类型:纸质 1,电子 2
params.invoices_title = req.body.invoices_title || '个人'; // 发票抬头,个人前端不传此值
params.receiverMobile = req.body.receiverMobile; // 接收人电话
// 购买方纳税人识别号
if (req.body.buyerTaxNumber) {
params.buyerTaxNumber = req.body.buyerTaxNumber;
}
}
if (req.cookies.mkt_code || req.cookies._QYH_UNION) {
let unionInfo = paymentProcess.unionInfoHandle(req.cookies, uid);
params.qhy_union = _.get(unionInfo, 'unionKey', false);
params.userAgent = _.get(unionInfo, 'userAgent', '');
}
co(function * () {
let result = yield req.ctx(BuyNowModel).submit(params);
// 提交成功清除Cookie
res.clearCookie('buynow_info', actCkOpthn);
return res.json(result);
})().catch(next);
}
/**
* 选择地址
* @param {*} req
* @param {*} res
* @param {*} next
*/
selectAddress(req, res, next) {
let uid = req.user.uid;
let product_sku = req.query.product_sku;
let buy_number = req.query.buy_number;
co(function * () {
let address = yield addressModel.addressData(uid);
let moreUrl = helpers.urlFormat('/cart/index/buynow/orderensure', {
product_sku: product_sku,
buy_number: buy_number
});
address = address.data;
let headerData = headerModel.setNav({
navTitle: '选择地址',
navBtn: false,
backUrl: moreUrl
});
res.render('select-address', {
module: 'buynow',
page: 'select-address',
pageHeader: headerData,
pageFooter: true,
moreUrl,
address,
localCss: true
});
})().catch(next);
}
/**
* 填写发票信息
* @param {*} req
* @param {*} res
* @param {*} next
*/
selectInvoice(req, res, next) {
let product_sku = req.query.product_sku;
let buy_number = req.query.buy_number;
let uid = req.user.uid;
let orderInfo;
try {
orderInfo = JSON.parse(req.cookies.buynow_info);
} catch (e) {
orderInfo = {};
}
co(function* () {
let userData = yield userModel.queryProfile(uid);
let mobile = _.get(userData, 'data.mobile', '');
let addresslist = yield userModel.addressTextData(uid);
let returnData = orderModel.processInvoiceData(orderInfo, mobile, addresslist);
let headerData = headerModel.setNav({
invoiceNotice: '发票须知',
navTitle: '发票信息',
navBtn: false
});
res.render('select-invoice', _.assign(returnData, {
pageHeader: headerData,
module: 'buynow',
page: 'select-invoice',
localCss: true,
addressMore: helpers.urlFormat('/cart/index/buynow/orderensure', {
product_sku: product_sku,
buy_number: buy_number
})
}));
})().catch(next);
}
/**
* 选择优惠券页面
*/
selectCoupon(req, res) {
let headerData = headerModel.setNav({
navTitle: '选择优惠券',
navBtn: false
});
res.render('select-coupon', {
module: 'buynow',
page: 'select-coupon',
title: '选择优惠券',
selectCouponPage: true,
pageHeader: headerData,
pageFooter: true,
localCss: true
});
}
/**
* 获取用户可用和不可用优惠券列表
* @param {*} req
* @param {*} res
* @param {*} next
*/
listCoupon(req, res, next) {
co(function* () {
let result = yield req.ctx(BuyNowModel).listCoupon({
uid: req.user.uid,
product_sku: req.query.product_sku,
sku_type: req.query.sku_type,
buy_number: req.query.buy_number
});
let finalResult = _.get(result, 'data', {});
res.json(camelCase(finalResult));
})().catch(next);
}
/**
* 使用优惠券
* @param {*} req
* @param {*} res
* @param {*} next
*/
useCoupon(req, res, next) {
co(function* () {
let result = yield req.ctx(BuyNowModel).useCoupon({
uid: req.user.uid,
product_sku: req.body.product_sku,
sku_type: req.body.sku_type,
buy_number: req.body.buy_number,
coupon_code: req.body.coupon_code
});
res.json(result);
})().catch(next);
}
/**
* 输入优惠券码使用优惠券
*/
usePromotionCode(req, res, next) {
co(function* () {
let result = yield req.ctx(BuyNowModel).usePromotionCode({
uid: req.user.uid,
product_sku: req.body.product_sku,
sku_type: req.body.sku_type,
buy_number: req.body.buy_number,
promotion_code: req.body.promotion_code
});
res.json(result);
})().catch(next);
}
}
module.exports = new BuyNowController();
... ...
... ... @@ -8,7 +8,7 @@ const userModel = require('../models/user');
const addressModel = require('../models/address');
const orderModel = require('../models/order');
const crypto = global.yoho.crypto;
const authcode = require(global.utils + '/authcode');
const paymentProcess = require(global.utils + '/payment-process');
const logger = global.yoho.logger;
// cookie 参数
... ... @@ -127,8 +127,8 @@ exports.orderEnsure = (req, res, next) => {
module: 'cart',
page: 'order-ensure',
width750: true,
title: '确认订单',
localCss: true
localCss: true,
title: '确认订单'
};
res.render('order-ensure', viewData);
... ... @@ -201,60 +201,25 @@ exports.orderSub = (req, res, next) => {
// 电子发票信息数组
let invoices = {};
if (orderInfo) {
if (orderInfo && orderInfo.invoice) {
invoices = {
invoices_type_id: orderInfo.invoiceType,
invoices_type: orderInfo.invoicesType,
receiverMobile: orderInfo.receiverMobile,
invoices_title: orderInfo.invoiceText ? orderInfo.invoiceText : '个人'
invoices_type_id: 12, // 发票类型写死【明细】
invoices_type: orderInfo.invoices_type, // 区分电子发票还是纸质发票
receiverMobile: orderInfo.receiverMobile, // 电话
invoices_title: orderInfo.invoices_title ? orderInfo.invoices_title : '个人' // 发票抬头,没有是个人
};
// 购买方纳税人识别号
if (orderInfo.buyerTaxNumber) {
invoices.buyerTaxNumber = orderInfo.buyerTaxNumber;
}
}
/* 判断是否是友盟过来的用户 */
let userAgent = null;
let unionKey = '';
let unionInfo = {};
let clientId = null;
if (req.cookies.mkt_code || req.cookies._QYH_UNION) {
/* tar modified 161108 添加新的联盟数据处理逻辑,兼容原有联盟数据处理,
区别是旧的北京写 cookie 加密过来,新的 node 写 cookie,没有加密 */
if (req.cookies._QYH_UNION) {
unionKey = authcode(req.cookies._QYH_UNION, 'q_union_yohobuy');
if (!unionKey) {
let encryData = crypto.decrypt('', decodeURIComponent(req.cookies._QYH_UNION));
encryData = encryData.substr(0, encryData.lastIndexOf('}') + 1);
let testQyhUnion = JSON.parse(encryData);
unionKey = testQyhUnion.client_id ? encryData : '';
}
try {
unionInfo = JSON.parse(unionKey);
} catch (e) {
unionInfo = {};
logger.error(`orderEnsure: _QYH_UNION:${req.cookies._QYH_UNION}`);
}
clientId = unionInfo && unionInfo.client_id;
} else {
let unionObj = {
client_id: req.cookies.mkt_code
};
if (req.cookies.union_data) {
unionObj.union_data = req.cookies.union_data;
}
unionKey = JSON.stringify(unionObj);
clientId = req.cookies.mkt_code;
}
/* 模拟APP的User-Agent */
userAgent = clientId ? 'YOHO!Buy/3.8.2.259(Model/PC;Channel/' +
clientId + ';uid/' + uid + ')' : null;
unionInfo = paymentProcess.unionInfoHandle(req.cookies, uid);
}
return co(function* () {
... ... @@ -263,10 +228,10 @@ exports.orderSub = (req, res, next) => {
// 接口需要的其他参数
let otherParams = {
isPrintPrice: isPrintPrice,
unionKey: unionKey, // 友盟数据
userAgent: userAgent,
unionKey: unionInfo.unionKey, // 友盟数据
userAgent: unionInfo.userAgent,
isWechat: req.yoho.isWechat,
ip: req.ip || '',
ip: req.yoho.clientIp,
udid: req.cookies._yasvd || 'yoho'
};
... ... @@ -415,6 +380,7 @@ exports.invoiceInfo = (req, res, next) => {
let addresslist = yield userModel.addressTextData(uid);
let returnData = orderModel.processInvoiceData(orderInfo, mobile, addresslist);
let headerData = headerModel.setNav({
invoiceNotice: '发票须知',
navTitle: '发票信息',
navBtn: false
});
... ...
... ... @@ -59,6 +59,8 @@ exports.ensure = (req, res, next) => {
return res.render('order-ensure', Object.assign({
module: 'cart',
page: 'seckill',
width750: true,
localCss: true,
pageHeader: headerModel.setNav({
navTitle: '确认订单',
backUrl: '/product/' + skn + '.html' // 商品url改版
... ... @@ -108,6 +110,8 @@ exports.ensure = (req, res, next) => {
navTitle: '确认订单',
backUrl: '/product/' + skn + '.html' // 商品url改版
}),
width750: true,
localCss: true,
cartToken: crypto.encryption(SLAT, [sku, activityId].join(''))
}, view));
})().catch(next);
... ...
/*
* @Author: Targaryen
* @Date: 2017-06-21 10:15:45
* @Last Modified by: Targaryen
*/
const api = global.yoho.API;
class BuyNowModel extends global.yoho.BaseModel {
constructor(ctx) {
super(ctx);
}
/**
* 获取用户可用的优惠券张数
* @param {*} params
*/
countUsableCoupon(params) {
return api.post('', {
method: 'app.Buynow.countUsableCoupon',
uid: params.uid,
product_sku: params.product_sku,
sku_type: params.sku_type || 'I',
buy_number: params.buy_number
}, {cache: false});
}
/**
* 获取用户可用和不可用优惠券列表
* @param {*} params
*/
listCoupon(params) {
return api.post('', {
method: 'app.Buynow.listCoupon',
uid: params.uid,
product_sku: params.product_sku,
sku_type: params.sku_type || 'I',
buy_number: params.buy_number
}, {cache: false});
}
/**
* 结算页面数据渲染
* @param {*} params
*/
payment(params) {
let finalParams = {
method: 'app.Buynow.payment',
uid: params.uid,
product_sku: params.product_sku,
sku_type: params.sku_type || 'I',
buy_number: params.buy_number,
yoho_coin_mode: params.yoho_coin_mode || 0, // 是否使用有货币
yoho_bill_term: 0, // H5 不支持分期
is_support_apple_pay: 'N', // H5 不支持 APPLE PAY
activity_id: params.activity_id || 0,
enable_red_envelopes: 0 // H5 不支持使用红包
};
return api.post('', finalParams, { cache: false });
}
/**
* 数据改变,重新计算结算数据
* @param {*} params
*/
compute(params) {
let finalParams = {
method: 'app.Buynow.compute',
uid: params.uid,
product_sku: params.product_sku,
sku_type: params.sku_type || 'I',
buy_number: params.buy_number,
payment_type: params.payment_type || 1,
delivery_way: params.delivery_way || 1,
use_red_envelopes: 0,
yoho_bill_term: 0,
activity_id: params.activity_id || 0
};
if (params.use_yoho_coin) {
finalParams.use_yoho_coin = params.use_yoho_coin;
}
if (params.coupon_code) {
finalParams.coupon_code = params.coupon_code;
}
if (params.promotion_code) {
finalParams.promotion_code = params.promotion_code;
}
if (params.coupon_code) {
finalParams.coupon_code = params.coupon_code;
}
return api.post('', finalParams, {cache: false});
}
/**
* 提交订单
* @param {*} params
*/
submit(params) {
let finalParams = {
method: 'app.Buynow.submit',
uid: params.uid,
product_sku: params.product_sku,
sku_type: params.sku_type || 'I',
buy_number: params.buy_number,
yoho_bill_term: 0,
address_id: params.address_id,
delivery_time: params.delivery_time,
delivery_way: params.delivery_way,
use_red_envelopes: 0,
payment_id: params.payment_id,
payment_type: params.payment_type || 1,
activity_id: params.activity_id || 0,
is_print_price: params.is_print_price || 'N'
};
// 发票类型:纸质 1,电子 2
if (params.invoices_type) {
finalParams.invoices_type = params.invoices_type;
}
// 发票抬头
if (params.invoices_title) {
finalParams.invoices_title = params.invoices_title;
}
// 发票种类写死明细
if (params.invoice) {
finalParams.invoice_content = 12;
}
// 收票人手机号码
if (params.receiverMobile) {
finalParams.receiverMobile = params.receiverMobile;
}
// 购买方纳税人识别号,需要开具电子发票且发票抬头为单位信息时为必填项
if (params.buyerTaxNumber) {
finalParams.buyerTaxNumber = params.buyerTaxNumber;
}
if (params.use_yoho_coin) {
finalParams.use_yoho_coin = params.use_yoho_coin;
}
if (params.remark) {
finalParams.remark = params.remark;
}
if (params.coupon_code) {
finalParams.coupon_code = params.coupon_code;
}
if (params.promotion_code) {
finalParams.promotion_code = params.promotion_code;
}
if (params.qhy_union) {
finalParams.qhy_union = params.qhy_union;
}
return api.post('', finalParams, {
headers: {
'X-Forwarded-For': params.ip || '',
'User-Agent': params.userAgent
}
});
}
/**
* 使用优惠券
* @param {*} params
*/
useCoupon(params) {
let finalParams = {
method: 'app.Buynow.useCoupon',
uid: params.uid,
product_sku: params.product_sku,
sku_type: params.sku_type || 'I',
buy_number: params.buy_number,
};
if (params.coupon_code) {
finalParams.coupon_code = params.coupon_code;
}
return api.post('', finalParams, {cache: false});
}
/**
* 使用优惠码
* @param {*} params
*/
usePromotionCode(params) {
let finalParams = {
method: 'app.Buynow.usePromotionCode',
uid: params.uid,
product_sku: params.product_sku,
sku_type: params.sku_type || 'I',
buy_number: params.buy_number
};
if (params.promotion_code) {
finalParams.promotion_code = params.promotion_code;
}
return api.post('', finalParams, {cache: false});
}
}
module.exports = BuyNowModel;
... ...
/**
* doc: http://git.yoho.cn/yoho-documents/api-interfaces/blob/master/%E8%AE%A2%E5%8D%95/%E7%AB%8B%E5%8D%B3%E8%B4%AD%E4%B9%B0.md
*/
'use strict';
const API = global.yoho.API;
const paymentProcess = require(global.utils + '/payment-process');
exports.payment = (options, orderInfo) => {
let queryData = Object.assign({
method: 'app.Buynow.payment',
}, options);
return API.post('', queryData)
.then(result => {
// TODO 数据处理
if (result.code === 200 && result.data) {
result.data = paymentProcess.tranformPayment(result.data, orderInfo);
}
return result;
});
};
exports.compute = options => {
let url = '';
let queryData = Object.assign({
method: 'app.Buynow.compute',
}, options);
return API.post(url, queryData);
};
exports.submit = options => {
let url = '';
let queryData = Object.assign({
method: 'app.Buynow.submit'
}, options);
return API.post(url, queryData, {
headers: {'X-Forwarded-For': options.ip || ''}
});
};
... ... @@ -8,29 +8,6 @@ const logger = global.yoho.logger;
const payModel = require('../models/pay');
/**
* 转换价格
*
* @param float|string $price 价格
* @param boolean $isSepcialZero 是否需要特殊的0,默认否
* @return float|string 转换之后的价格
*/
const transPrice = (price, isSepcialZero) => {
if (!price) {
price = 0;
}
if (!isSepcialZero) {
isSepcialZero = false;
}
if ((price || isSepcialZero) && _.isNumber(price)) {
return price.toFixed(2);
} else {
return price;
}
};
/**
* 调用购物车结算接口返回的数据处理
*
*
... ... @@ -137,7 +114,7 @@ exports.orderCompute = (uid, cartType, deliveryWay, paymentType, couponCode, yoh
return shoppingAPI.orderComputeAPI(uid, cartType, deliveryWay, paymentType,
couponCode, yohoCoin, skuList, activityInfo).then(result => {
if (result && result.data) {
result.data.use_yoho_coin = transPrice(result.data.use_yoho_coin);
result.data.use_yoho_coin = paymentProcess.transPrice(result.data.use_yoho_coin);
result.data.yohoCoinCompute = paymentProcess.yohoCoinCompute(result.data);
return result.data;
} else {
... ... @@ -150,11 +127,10 @@ exports.orderCompute = (uid, cartType, deliveryWay, paymentType, couponCode, yoh
exports.ticketsOrderCompute = (uid, productSku, buyNumber, yohoCoin) => {
return shoppingAPI.checkTickets(uid, productSku, buyNumber, yohoCoin).then(result => {
if (result && result.data) {
// result.data.shopping_cart_data.use_yoho_coin = transPrice(result.data.shopping_cart_data.use_yoho_coin);
// result.data.yohoCoinCompute = paymentProcess.yohoCoinCompute(result.data.shopping_cart_data);
let resu = {};
result.data.shopping_cart_data.use_yoho_coin = transPrice(result.data.shopping_cart_data.use_yoho_coin);
result.data.shopping_cart_data.use_yoho_coin =
paymentProcess.transPrice(result.data.shopping_cart_data.use_yoho_coin);
resu = result.data.shopping_cart_data;
resu.yohoCoinCompute = paymentProcess.yohoCoinCompute(result.data.shopping_cart_data);
... ...
... ... @@ -5,10 +5,8 @@ const _ = require('lodash');
const crypto = global.yoho.crypto;
const processInvoiceData = (orderInfo, mobile, addresslist) => {
let invoices_title = '';
let invoiceType = '7';
let invoices_title = false;
let invoices_type = '2';
let invoice_Top = '个人';
let addressId = orderInfo.addressId &&
parseInt(crypto.encryption('', orderInfo.addressId), 10) || 0;
... ... @@ -25,75 +23,35 @@ const processInvoiceData = (orderInfo, mobile, addresslist) => {
}
// 发票信息处理
if (orderInfo.invoiceType && orderInfo.invoiceTitle) {
invoices_title = orderInfo.invoiceText;
invoiceType = orderInfo.invoiceType * 1;
invoices_type = orderInfo.invoicesType * 1;
invoice_Top = orderInfo.invoiceTitle;
if (orderInfo.invoices_type && orderInfo.invoices_title) {
invoices_title = orderInfo.invoices_title;
invoices_type = orderInfo.invoices_type * 1;
}
let isCompany = invoices_title && invoices_title !== '个人';
return {
invoiceNotice: '发票须知',
phone: mobile ? mobile : '', // TODO 字符串替换 ****
phone: mobile ? mobile : '',
completeTel: mobile,
isCompany: invoice_Top !== '单位',
companyName: invoices_title,
isCompany: isCompany,
companyName: isCompany ? invoices_title : '个人(不可修改)',
buyerTaxNumber: orderInfo.buyerTaxNumber,
isPaper: invoices_type === 1,
invoicesType: [
{
id: '2',
type: '电子发票',
choosed: !invoices_type || invoices_type === 2,
},
{
id: '1',
type: '纸质发票',
choosed: invoices_type === 1
type: '电子发票'
}
],
invoiceTitle: [
{
type: '个人',
choosed: invoice_Top === '个人'
choosed: !isCompany
},
{
type: '单位',
choosed: invoice_Top === '单位'
choosed: isCompany
}
],
content: [
{
choosed: !invoiceType || invoiceType === 7,
id: 7,
text: '服装'
},
{
choosed: invoiceType === 9,
id: 9,
text: '配件'
},
{
choosed: invoiceType === 11,
id: 11,
text: '日用品'
},
// 暂停办公用品开票
// {
// choosed: invoiceType === 3,
// id: 3,
// text: '办公用品'
// },
{
choosed: invoiceType === 6,
id: 6,
text: '体育用品'
},
{
choosed: invoiceType === 10,
id: 10,
text: '数码产品'
},
]
};
... ...
... ... @@ -175,26 +175,31 @@ exports.orderSub = (uid, addressId, cartType, deliveryTime,
params.is_continue_buy = 'N';
}
// 发票内容写死明细
if (invoices.invoices_type_id) {
// 发票内容id--图书:1
params.invoice_content = invoices.invoices_type_id;
params.invoice_content = 12;
}
// 发票类型 纸质 1 ,电子 2
if (invoices.invoices_type) {
// 数字类型 发票类型 纸质 1 ,电子 2
params.invoices_type = invoices.invoices_type;
}
// 收票人手机号码
if (invoices.receiverMobile) {
// 发票人手机
params.receiverMobile = invoices.receiverMobile;
}
// 发票抬头
if (invoices.invoices_title) {
// 发票抬头 OR 填写单位名称,这二个是一个意思,只是叫法不一样
params.invoices_title = invoices.invoices_title;
}
// 购买方纳税人识别号,需要开具电子发票且发票抬头为单位信息时为必填项
if (invoices.buyerTaxNumber) {
params.buyerTaxNumber = invoices.buyerTaxNumber;
}
if (couponCode) {
params.coupon_code = couponCode;
}
... ...
... ... @@ -16,6 +16,7 @@ const countController = require(`${cRoot}/count`);
const payController = require(`${cRoot}/pay`);
const indexController = require(`${cRoot}/index`);
const ticketsConfirmController = require(`${cRoot}/ticketsConfirm`);
const BuyNowController = require(`${cRoot}/buy-now-controller`);
// Your controller here
router.all('/index/seckill/', authMW);
... ... @@ -34,7 +35,7 @@ router.get('/index/new/pay/alipayresult', authMW, payController.payAli);// 支
router.get('/index/new/orderEnsure', authMW, order.orderEnsure); // 订单结算
router.post('/index/new/orderCompute', authMW, order.orderCompute); // 结算页参数改变,重新运算
router.post('/index/new/orderSub', authMW, order.orderSub); // 结算页参数改变,重新运算
router.post('/index/new/orderSub', authMW, order.orderSub); // 订单提交
router.get('/index/new/selectCoupon', authMW, order.selectCoupon); // 选择优惠券 页面
router.get('/index/new/couponList', order.couponList); // [ajax]获取优惠券列表
router.post('/index/new/couponSearch', order.couponSearch); // [ajax]购物车输入优惠券码使用优惠券
... ... @@ -61,6 +62,16 @@ router.post('/index/new/giftinfo', indexController.giftinfo); // 获取购物车
router.post('/index/new/incrbundle', indexController.incrBundle); // 购物车增加套餐数量
router.post('/index/new/decrbundle', indexController.decrBundle); // 购物车减少加套餐数量
router.get('/index/buynow/orderensure', authMW, BuyNowController.orderEnsure); // 立即购买订单确认页面
router.post('/index/buynow/ordercompute', authMW, BuyNowController.orderCompute); // 立即购买订单重新计算
router.post('/index/buynow/ordersub', authMW, BuyNowController.orderSub); // 立即购买订单提交
router.get('/index/buynow/selectAddress', authMW, BuyNowController.selectAddress); // 选择地址
router.get('/index/buynow/selectInvoice', authMW, BuyNowController.selectInvoice); // 发票信息
router.get('/index/buynow/selectCoupon', authMW, BuyNowController.selectCoupon); // 选择优惠券页面
router.post('/index/buynow/useCoupon', BuyNowController.useCoupon); // [ajax]使用优惠券
router.post('/index/buynow/usePromotionCode', BuyNowController.usePromotionCode); // [ajax]输入优惠券码使用优惠券
router.get('/index/buynow/listCoupon', BuyNowController.listCoupon); // [ajax]获取优惠券列表
// 支付中心 URL,由于微信安全限制,在现有 URL 后追加 new ,通过 subDomain 中间件转发到此
router.get('/home/orders/paynew', authMW, payController.payCenter);
... ...
<div class="order-ensure-page yoho-page">
<input id="cart-token" type="hidden" name="token" value="{{cartToken}}">
{{# orderEnsure}}
{{#if addressInfo}}
<div class="address block address-wrap {{#if @root.pageChannel.boys}} boys{{/if}}{{#if @root.pageChannel.girls}} girls{{/if}}{{#if @root.pageChannel.kids}} kids{{/if}}{{#if @root.pageChannel.lifeStyle}} life-style{{/if}}" data-id ="{{addressId}}">
<div class="info">
<span class="info-name">{{name}}</span>
<span class="info-phone">{{phoneNum}}</span>
<a href="{{selectAddressUrl}}"><span class="info-address">{{addressInfo}}</span></a>
<i class="iconfont">&#xe637;</i>
</div>
<a class="rest" href="{{selectAddressUrl}}">其他地址<span class="iconfont">&#xe614;</span></a>
</div>
{{else}}
<div class="address block address-wrap not-address">
<i class="iconfont">&#xe637;</i>
<a class="choose" href="{{selectAddressUrl}}">请选择收货地址<span class="iconfont">&#xe614;</span></a>
</div>
{{/if}}
<section class="dispatch block">
<div class="sub-block payment-type">
<h3>
<p>支付方式</p>
{{#each paymentWay}}
{{#if recommend}}<span>{{name}}</span>{{/if}}
{{/each}}
<i class="iconfont down">&#xe616;</i>
<i class="iconfont hide up">&#xe615;</i>
</h3>
<ul>
{{#each paymentWay}}
{{#if isSupport}}
<li {{#if recommend}}class="chosed"{{/if}}>
<span>{{name}}</span>
<i class="right iconfont {{#if recommend}}icon-cb-radio{{else}}icon-radio{{/if}}" data-id="{{id}}" data-payment-type="{{paymentType}}"></i>
</li>
{{/if}}
{{/each}}
</ul>
</div>
<div class="sub-block delivery-id">
<h3>
<p>配送方式</p>
{{#each dispatchMode}}
{{#if isSelected}}<span>{{name}}:运费¥{{cost}}</span>{{/if}}
{{/each}}
<i class="iconfont down">&#xe616;</i>
<i class="iconfont hide up">&#xe615;</i>
</h3>
<ul class="dispatch-mode">
{{#each dispatchMode}}
<li {{#if isSelected}}class="chosed"{{/if}} data-id="{{id}}">
<span>{{name}}:运费¥{{cost}}</span>
<i class="right iconfont {{#if isSelected}}icon-cb-radio{{else}}icon-radio{{/if}}" data-id="{{id}}"></i>
</li>
{{/each}}
</ul>
</div>
<div class="sub-block dispatch-time">
<h3>
<p>送货时间</p>
{{#each dispatchTime}}
{{#if isSelected}}<span>{{name}}</span>{{/if}}
{{/each}}
<i class="iconfont down">&#xe616;</i>
<i class="iconfont hide up">&#xe615;</i>
</h3>
<ul>
<li class="dispatch-time-info">快递公司会尽力按您选择的送货时间配送,如遇特殊情况(天气、环境等)无法按您要求时间配送,还请您谅解。</li>
{{#each dispatchTime}}
<li {{#if isSelected}}class="chosed"{{/if}} data-id="{{id}}">
<span>{{name}}</span>
<i class="right iconfont radio {{#if isSelected}}icon-cb-radio{{else}}icon-radio{{/if}}" ></i>
</li>
{{/each}}
</ul>
</div>
</section>
{{#if isJit}}
{{> home/order/jit-more}}
{{/if}}
<section class="block goods-bottom">
{{#each goods}}
{{> home/order/good}}
{{/each}}
<div class="goods-num">{{num}}件商品 合计<span>{{goodsPrice}}</span></div>
</section>
<section class="block">
<ul class="sale-invoice">
{{#if isOrdinaryCart}}
<li class="coupon">
<a href="{{selectCouponUrl}}">
<span class="title">优惠券/优惠券码</span>
{{# coupon}}
{{#if couponName}}
<span class="used coupon-use" data-name="{{couponName}}">
{{couponName}}
<i class="iconfont">&#xe614;</i>
</span>
{{^}}
{{#unless isLimit}}
<span class="coupon-count">
{{#if count}}
{{count}}张可用
{{else}}
无可用
{{/if}}
<i class="iconfont">&#xe614;</i>
</span>
{{/unless}}
<span class="not-used coupon-use">
{{#if isLimit}}该商品不可使用优惠券{{/if}}
<i class="iconfont">&#xe614;</i>
</span>
{{/if}}
{{/coupon}}
</a>
</li>
{{/if}}
<li class="coin" data-yoho-coin="{{yohoCoinCompute.yohoCoin}}" data-yoho-coin-click={{yohoCoinCompute.yohoCoinClick}}>
<span class="title">有货币</span>
<span class="desc msg">{{yohoCoinCompute.yohoCoinMsg}}</span>
<span class="yoho-coin-help">?</span>
{{#if yohoCoinCompute.useYohoCoin}}
<span class="coin-check">
<i class="iconfont checkbox icon-cb-radio"></i>
</span>
{{else}}
<span class="coin-check">
<i class="iconfont checkbox icon-radio"></i>
</span>
{{/if}}
</li>
{{#if invoice}}
<li class="invoice {{#if needInvoice}}focus{{/if}}">
<input type="hidden" class="user-mobile" value="{{userMobile}}" />
<span class="title">发票</span>
<span class="iconfont checkbox {{#if needInvoice}}icon-cb-radio{{else}}icon-radio{{/if}}"></span>
<a id="invoice" class="invoice-info" href="/cart/index/buynow/selectInvoice?product_sku={{@root.product_sku}}">
<span class="title">发票信息</span>
<span class="invoice-type">{{invoiceText}}<i class="iconfont">&#xe614;</i></span>
</a>
</li>
{{/if}}
</ul>
<form id="msg" action="" method="post">
<input type="text" name="msg" value="{{msg}}" maxlength="40" placeholder="留言">
</form>
<ul class="sale-invoice">
<li class="no-print-price">
<span class="title">不打印价格</span>
<span class="desc">送朋友可不打印价格哦</span>
<span class="check">
<i class="iconfont checkbox{{#if isPrintPrice}} icon-radio{{else}} icon-cb-radio{{/if}}"></i>
</span>
</li>
</ul>
</section>
<section class="price-cal block">
<ul class="total">
{{#cartPayData}}
<li>
<p>{{promotion}}</p>
<span>{{promotion_amount}}</span>
</li>
{{/cartPayData}}
</ul>
<div class="price-cost">
实付金额
<span>¥{{round price 2}}</span>
</div>
{{#if returnYohoCoin}}
<div class="yoho-coin">
共返有货币: {{yohoCoinNum}}
</div>
{{/if}}
</section>
{{#if addressInfo}}
<div class="address-bottom">
<div class="back"></div>
<span>送至:{{addressInfo}}</span>
</div>
{{/if}}
<div class="bill">
您需要支付:<span>¥{{round price 2}}</span>
<a href="javascript:;">提交订单</a>
</div>
<div class="yoho-coin-help-dialog-bg"></div>
<div class="yoho-coin-help-dialog">
<div class="yoho-coin-title">有货币使用条件:</div>
<div class="yoho-coin-content">
<p>1.订单金额大于20元(含)</p>
<p>2.有货币数量大于{{yohoCoinCompute.yoho_coin_pay_rule.num_limit}}个(含)</p>
<p>3.有货币支付不得超过每笔订单应付金额的{{yohoCoinCompute.yoho_coin_pay_rule.max_pay_rate_desc}}</p>
<p>备注:使用有货币数量为{{yohoCoinCompute.yoho_coin_pay_rule.num_limit}}的整数倍,100有货币抵1元。</p>
</div>
<div class="yoho-coin-footer">知道了</div>
</div>
<input type="hidden" id="product-sku" name="product-sku" value="{{sku}}">
{{#with seckill}}
<input type="hidden" id="activity-id" name="activity-id" value="{{activityId}}">
{{/with}}
{{else}}
<div class="order-ensure-error">
{{message}}
</div>
{{/ orderEnsure}}
</div>
{{> rich_tip}}
... ...
... ... @@ -141,7 +141,7 @@
<span class="iconfont checkbox {{#if needInvoice}}icon-cb-radio{{else}}icon-radio{{/if}}"></span>
<a id="invoice" class="invoice-info" href="/cart/index/new/invoiceInfo">
<span class="title">发票信息</span>
<span class="invoice-type"><i class="iconfont">&#xe614;</i></span>
<span class="invoice-type">{{invoiceText}}<i class="iconfont">&#xe614;</i></span>
</a>
</li>
{{/if}}
... ... @@ -192,8 +192,8 @@
<a href="javascript:;">提交订单</a>
</div>
<div class="yoho-coin-help-dialog-bg hide"></div>
<div class="yoho-coin-help-dialog hide">
<div class="yoho-coin-help-dialog-bg"></div>
<div class="yoho-coin-help-dialog">
<div class="yoho-coin-title">有货币使用条件:</div>
<div class="yoho-coin-content">
<p>1.订单金额大于20元(含)</p>
... ...
<div class="invoice-info-page yoho-page">
<ul class="invoice-form">
<li>
<span class="title">发票类型:</span>
<div class="invoice-type">
{{#invoicesType}}
<span {{#if choosed}}class="on"{{/if}} data-id="{{id}}">{{type}}</span>
{{/invoicesType}}
</div>
</li>
<section class="invoice-type-sec">
<div class="invoice-type">
<span class="title">发票类型</span>
{{#invoicesType}}
<span id="eInvoices" data-id="{{id}}">{{type}}</span>
{{/invoicesType}}
</div>
<div class="tip">
<i class="iconfont icon-tip">&#xE61A;</i>电子发票与纸质发票具备同等法律效力,可支持报销入账
</div>
</section>
<header>发票信息</header>
<section class="invoice-info">
<li>
<span class="title">发票抬头:</span>
<div class="invoice-top">
{{#invoiceTitle}}
<span {{#if choosed}}class="on"{{/if}}><i class="iconfont choose {{#if choosed}}icon-cb-radio{{else}}icon-radio{{/if}}"></i>{{type}}</span>
{{/invoiceTitle}}
</div>
</li>
<li {{#isPaper}}style="display: none;"{{/isPaper}} class="tel-area">
<span class="title"><i class="txt-point">*</i>发票人手机:</span>
<li class="company-area">
<span class="title">发票抬头</span>
<input type="text" name="company" class="company" value="{{companyName}}" placeholder="请输入单位名称" maxlength="30"{{#unless isCompany}} disabled{{/unless}}></li>
<li class="tax-number"{{#unless isCompany}} style="display: none;"{{/unless}}>
<span class="title">税号</span>
<input type="text" id="buyerTaxNumber" name="buyerTaxNumber" class="number" value="{{buyerTaxNumber}}" placeholder="请输入正确的纳税人识别号" maxlength="30">
</li>
</section>
<header>收票人信息</header>
<section class="invoice-mem">
<li class="tel-area">
<span class="title">手机号</span>
<span class="phone">
<input type="hidden" class="copy-tel" value="{{completeTel}}">
<input type="text" name="tel" data-tel="{{completeTel}}" class="tel {{#phone}}istel{{/phone}}" value="{{phone}}" placeholder="可通过手机号在发票服务平台查询">
</span>
</li>
<li class="company-area" {{#isCompany}}style="display: none;"{{/isCompany}}><input type="text" name="company" class="company" value="{{companyName}}" placeholder="填写单位名称" maxlength="30"></li>
</ul>
<ul class="invoice-cont">
<li class="cont-title">
<span>发票内容:</span>
<span class="choose-cont" data-id=""></span>
</li>
{{#each content}}
<li><span class="iconfont choose {{#if choosed}}icon-cb-radio{{else}}icon-radio{{/if}}" data-id="{{id}}"></span>{{text}}</li>
{{/each}}
</ul>
</section>
<div class="btn-area"><span class="confirm-btn">确认</span></div>
<div class="btn-area"><span class="confirm-btn active">确认</span></div>
<div class="invoice-notice">
<div class="mask-bg"></div>
... ...
... ... @@ -12,9 +12,7 @@ const _ = require('lodash');
const helpers = global.yoho.helpers;
const getOnlineServiceInfo = (req, res, next) => {
let serviceUrl = _.get(req.app.locals.wap, 'clientService.new', false) ?
helpers.urlFormat('/service/im') :
'http://chat8.live800.com/live800/chatClient/chatbox.jsp?companyID=620092&configID=149091&jid=8732423409&info=';
let serviceUrl = helpers.urlFormat('/service/im');
onlineModel.getOnlineServiceInfo().then((result) => {
... ...
... ... @@ -18,9 +18,7 @@ const addressProcess = require(global.utils + '/address-process');
const orderDetailData = (req, res, next) => {
let uid = req.user.uid;
let orderCode = req.query.order_code;
let serviceUrl = _.get(req.app.locals.wap, 'clientService.new', false) ?
helpers.urlFormat('/service/im') :
'http://chat8.live800.com/live800/chatClient/chatbox.jsp?companyID=620092&configID=149091&jid=8732423409&info=';
let serviceUrl = helpers.urlFormat('/service/im');
if (req.query.openId) {
// 微信支付成功,发送支付确认接口
... ...
... ... @@ -108,10 +108,6 @@
<span>发票抬头</span>
<span class="invoice-fr invoice-title">{{title}}</span>
</li>
<li>
<span>发票内容</span>
<span class="invoice-fr">{{contentValue}}</span>
</li>
{{#if pdfUrl}}
<li>
<a href="{{pdfUrl}}"><span class="invoice-fr invoice-see">点击下载PDF发票</span></a>
... ...
... ... @@ -37,9 +37,7 @@ const bind = {
let openId = req.query.openId;
let sourceType = req.query.sourceType;
let serviceUrl = _.get(req.app.locals.wap, 'clientService.new', false) ?
helpers.urlFormat('/service/im') :
'http://chat8.live800.com/live800/chatClient/chatbox.jsp?companyID=620092&configID=149091&jid=8732423409&info=';
let serviceUrl = helpers.urlFormat('/service/im');
res.render('bind/index', {
bindIndex: true, // js标识
... ...
... ... @@ -178,9 +178,7 @@ let codeAction = (req, res, next) => {
});
}
let serviceUrl = _.get(req.app.locals.wap, 'clientService.new', false) ?
helpers.urlFormat('/service/im') :
'http://chat8.live800.com/live800/chatClient/chatbox.jsp?companyID=620092&configID=149091&jid=8732423409&info=';
let serviceUrl = helpers.urlFormat('/service/im');
res.render('reg/code', {
page: 'code',
... ...
... ... @@ -317,6 +317,7 @@ exports.index = (req, res, next) => {
/**
* 商品信息异步数据
* 可能已经废弃的代码
* @param {[type]} req [description]
* @param {[type]} res [description]
* @return {[type]} [description]
... ...
... ... @@ -140,23 +140,31 @@ const newDetail = {
},
indexData(req, res, next) {
if (!req.xhr) {
return next();
}
if (!req.body.id) {
// for guang
let allowOrigin = _.get(req, 'headers.origin', null) ?
req.headers.origin : req.protocol + '://guang.' + req.headers.host;
res.setHeader('Access-Control-Allow-Origin', allowOrigin);
res.setHeader('Access-Control-Allow-Credentials', 'true');
if (!req.query.id && !req.query.productSkn) {
return next();
}
let uid = req.user.uid || 0;
let shoppingKey = req.cookies._SPK || '';
let closeBuyNowButton = _.get(req.app.locals.wap, 'close.buyNowButton', false);
detailModel.getNewProductAsyncData(Object.assign({
id: req.body.id,
goodsId: req.body.goodsId,
productSkn: req.body.productSkn,
bundleType: req.body.bundleType,
id: req.query.id,
goodsId: req.query.goodsId,
productSkn: req.query.productSkn,
bundleType: req.query.bundleType,
uid: uid,
shoppingKey: shoppingKey,
ua: req.get('user-agent') || ''
ua: req.get('user-agent') || '',
from: req.query.from,
closeBuyNowButton: closeBuyNowButton
}, req.__User__)).then((result) => {
if (_.isEmpty(result)) {
return res.json({
... ...
... ... @@ -304,11 +304,47 @@ const keyword = (req, res, next) => {
}).catch(next);
};
// 关键词页with id
const keyId = (req, res, next) => {
let params = {
isSearch: true, // 搜索列表将最新改成默认的标识
cartUrl: helpers.urlFormat('/cart/index/index')
};
params.isApp = req.yoho.isApp;
params.physical_channel = req.yoho.channel && searchProcess.getChannelType(req.yoho.channel);
return searchModel.getSearchKeywordDataById(req.params.id, params, req.user.uid).then(result => {
let queryKey = result.queryKey;
// 唤起 APP 的路径
res.locals.appPath = `yohobuy://yohobuy.com/goapp?openby:yohobuy={"action":"go.list","params":${JSON.stringify(params)}}`;
res.render('search/list', {
_noLazy: true,
module: 'product',
page: 'search-list',
pageHeader: headerModel.setNav({
navTitle: queryKey
}),
goodList: params,
firstPageGoods: result || [],
fuzzyWord: result.fuzzyWord,
title: `${queryKey}价格_图片_品牌_怎么样-YOHO!BUY有货`,
keywords: `${queryKey},${queryKey}价格,${queryKey}图片,${queryKey}怎么样,${queryKey}品牌,YOHO!BUY有货`,
description: `YOHO!BUY有货网yohobuy.com是国内专业的${queryKey}网上潮流购物商城,为您找到${_.get(result,
'total', 0)}${queryKey}、产品的详细参数,实时报价,价格行情,图片、评价、品牌等信息。买${queryKey},就上YOHO!BUY有货`,
pageFooter: true
});
}).catch(next);
};
module.exports = {
list,
filter,
search,
index,
fuzzyDatas,
keyword
keyword,
keyId
};
... ...
... ... @@ -195,6 +195,7 @@ let _getFavorite = (productId, uid) => {
/**
* [商品获取数据] pagecache重构
* 可能是已经废弃的代码
*/
let getProductData = (data) => {
let finalResult;
... ... @@ -438,163 +439,9 @@ const _cartCount = (uid, shoppingKey) => {
};
/**
* [商品信息的异步数据获取] (优化)
*/
let getNewProductAsyncData = (data) => {
let params = {
method: 'app.product.data'
};
if (data.id) { // 通过 productId 获取商品详情
Object.assign(params, {
product_id: _.toString(data.id)
});
} else if (data.productSkn) { // 通过 productSkn 获取商品详情
Object.assign(params, {
product_skn: _.toString(data.productSkn)
});
}
if (data.uid) {
params.uid = data.uid;
}
params.is_student = data.isStudent ? 1 : 0;
params.current_vip_level = data.vipLevel;
// if (!params.is_student) {
// params.current_vip_level = data.vipLevel;
// }
return api.get('', params, {
code: 200,
cache: true
}).then(result => {
if (!result || result.code === 500 || !result.data) {
return {};
}
result = result.data;
result.goods_id = data.goodsId;
let apiArray = [
_cartCount(data.uid, data.shoppingKey),
_detailDataPkgAsync(result, data.uid, data.vipLevel, data.ua), // eslint-disable-line
_getFavorite(result.product_id, data.uid)
];
if (data.bundleType) {
apiArray.push(bundle.getBundleBySkn(data.productSkn));
}
return Promise.all(apiArray).then((res) => {
let cartCount = res[0];
let finalResult = res[1];
let isFavorite = res[2];
let bundleData = _.get(res[3], 'data', {});
if (cartCount) {
finalResult.cartCount = cartCount;
}
finalResult.isCollect = isFavorite;
if (finalResult.cartInfo) {
finalResult.cartInfo.isCollect = isFavorite;
}
finalResult.isStudent = data.isStudent;
let discountBuy = _.find(bundleData, bund => _.get(bund, 'bundleInfo.discountType') === 2);
/* 量贩 */
if (bundleData && discountBuy) {
let minBuyNum = discountBuy.bundleInfo.bundleCount;
let isNotEnough = true;
// 是否满足量贩购买要求:剩余商品数量大于量贩最小购买量
_.forEach(result.goods_list, goods => {
_.forEach(goods.size_list, sizes => {
if (sizes.storage_number >= minBuyNum) {
isNotEnough = false;
}
});
});
if (finalResult.cartInfo && isNotEnough) {
finalResult.cartInfo.soldOut = isNotEnough;
finalResult.cartInfo.addToCartUrl = false;
}
finalResult.discountBuy = {
num: minBuyNum,
promotionPhrase: discountBuy.bundleInfo.promotionPhrase,
discount: discountBuy.bundleInfo.discount
};
}
return finalResult;
});
});
};
/**
* [商品信息的异步数据获取]
*/
let getProductAsyncData = (data) => {
let finalResult;
let params = {
method: 'app.product.data'
};
if (data.id) { // 通过 productId 获取商品详情
Object.assign(params, {
product_id: _.toString(data.id)
});
} else if (data.productSkn) { // 通过 productSkn 获取商品详情
Object.assign(params, {
product_skn: _.toString(data.productSkn)
});
}
if (data.uid) {
params.uid = data.uid;
}
params.is_student = data.isStudent ? 1 : 0;
params.current_vip_level = data.vipLevel;
return api.get('', params, {
code: 200,
cache: true
}).then(result => {
if (!result || result.code === 500 || !result.data) {
return {};
}
result = result.data;
result.goods_id = data.goodsId;
return Promise.all([
_getPromotionInfo(result.product_skn),
_getFavorite(result.product_id, data.uid)
]).then((res) => {
result.promotionBoList = res[0];
let isFavorite = res[1];
return _detailDataPkgAsync(result, data.uid, data.vipLevel, data.ua).then(pkg => { // eslint-disable-line
finalResult = pkg;
finalResult.isCollect = isFavorite;
if (finalResult.cartInfo) {
finalResult.cartInfo.isCollect = isFavorite;
}
finalResult.isStudent = data.isStudent;
return finalResult;
});
});
});
};
/**
* [商品信息格式化异步接口]
*/
let _detailDataPkgAsync = (origin, uid, vipLevel, ua) => {
const _detailDataPkgAsync = (origin, uid, vipLevel, ua) => {
let dest = {}; // 结果输出
// 用户未登录时
... ... @@ -651,9 +498,7 @@ let _detailDataPkgAsync = (origin, uid, vipLevel, ua) => {
dest.isSecKill = origin.is_secKill; // 判断秒杀字段
}
if (origin.is_secKill) {
// dest.isDepositAdvance = origin.isDeposit_advance;// A定金预售字段 = origin.is_deposit_advance === 'Y'; // 是否定金预售
if (origin.is_deposit_advance) {
dest.isPresale = Boolean(origin.expect_arrival_time);
dest.isDepositAdvance = origin.is_deposit_advance; // 判断定金预售字段
}
... ... @@ -709,66 +554,79 @@ let _detailDataPkgAsync = (origin, uid, vipLevel, ua) => {
};
// 显示加入购物车链接
if (!soldOut && !notForSale && !preSale || origin.isLimitBuy) {
if (preSale) { // 预售
dest.cartInfo.preSale = true;
} else if (soldOut) { // 卖光了
dest.cartInfo.soldOut = true;
} else if (notForSale) { // 非卖品
dest.cartInfo.notForSale = true;
} else if (origin.is_deposit_advance === 'Y') { // 定金预售
dest.cartInfo.isDepositAdvance = true;
} else if (origin.isLimitBuy) { // 限购
Object.assign(dest.cartInfo, cartInfo, {
price: dest.goodsPrice.previousPrice ? dest.goodsPrice.previousPrice : '',
salePrice: dest.goodsPrice.currentPrice ? dest.goodsPrice.currentPrice : '',
});
// 限购商品
if (origin.isLimitBuy) {
return api.get('', {
method: 'app.limitProduct.productStatus',
limitProductCode: origin.limitProductCode,
uid: uid,
product_skn: origin.product_skn
}, {
code: 200,
cache: true
}).then((result) => {
if (result.data) {
if (!result.data.isLimitBuy) {
dest.cartInfo.soldOut = true;
return resolve(dest);
}
// 是否开售
let isBeginSale = (result.data.saleStatus === 1);
return api.get('', {
method: 'app.limitProduct.productStatus',
limitProductCode: origin.limitProductCode,
uid: uid,
product_skn: origin.product_skn
}, {
code: 200,
cache: true
}).then((result) => {
if (result.data) {
if (!result.data.isLimitBuy) {
dest.cartInfo.soldOut = true;
return resolve(dest);
}
// 限购商品有关的展示状态
let showStatus = 1;
// 是否开售
let isBeginSale = (result.data.saleStatus === 1);
origin.showStatus && (showStatus = parseInt(result.data.showStatus, 10));
// 限购商品有关的展示状态
let showStatus = 1;
// 处理限购商品有关的按钮状态
dest = _procShowStatus(dest, showStatus, isBeginSale);
origin.showStatus && (showStatus = parseInt(result.data.showStatus, 10));
dest.cartInfo.limitProductCode = origin.limitProductCode;
dest.cartInfo.limitCodeUrl = _getLimitCodeUrl(origin.limitProductCode, origin.product_skn, ua);
dest.cartInfo.limitProductPay = helpers.urlFormat('/cart/index/orderEnsure');
return resolve(dest);
} else {
dest.cartInfo.soldOut = true;
return resolve(dest);
}
// 处理限购商品有关的按钮状态
dest = _procShowStatus(dest, showStatus, isBeginSale);
});
} else {
dest.cartInfo.addToCartUrl = helpers.urlFormat('/product/buy_' + origin.product_id + '_' +
dest.cartInfo.limitProductCode = origin.limitProductCode;
dest.cartInfo.limitCodeUrl = _getLimitCodeUrl(origin.limitProductCode, origin.product_skn, ua);
dest.cartInfo.limitProductPay = helpers.urlFormat('/cart/index/orderEnsure');
return resolve(dest);
} else {
dest.cartInfo.soldOut = true;
return resolve(dest);
}
});
} else if (origin.from === 'detail' &&
origin.buy_now === 1 &&
!origin.closeBuyNowButton) { // 显示立即购买和加入购物车两个按钮,closeBuyNowButton 关闭开关
Object.assign(dest.cartInfo, cartInfo, {
price: dest.goodsPrice.previousPrice ? dest.goodsPrice.previousPrice : '',
salePrice: dest.goodsPrice.currentPrice ? dest.goodsPrice.currentPrice : '',
});
dest.showBuyNow = true;
dest.cartInfo.addToCartUrl = helpers.urlFormat('/product/buy_' + origin.product_id + '_' +
origin.goods_id + '.html');
} else { // 除了上面商品之外的普通商品
Object.assign(dest.cartInfo, cartInfo, {
price: dest.goodsPrice.previousPrice ? dest.goodsPrice.previousPrice : '',
salePrice: dest.goodsPrice.currentPrice ? dest.goodsPrice.currentPrice : '',
});
dest.cartInfo.addToCartUrl = helpers.urlFormat('/product/buy_' + origin.product_id + '_' +
origin.goods_id + '.html');
}
} else if (notForSale && !preSale) {
dest.cartInfo.notForSale = true;
} else if (soldOut && !preSale) {
dest.cartInfo.soldOut = true;
} else if (preSale) {
dest.cartInfo.preSale = true;
}
return resolve(dest);
}).then(result => {
// 虚拟商品(门票)
if (origin.attribute * 1 === 3) {
result.tickets = true;
result.cartInfo.addToCartUrl = false;
result.tickets = result.cartInfo.tickets = true;
result.ticketsConfirm = helpers.urlFormat('/cart/index/ticketsConfirm');
// 展览票
... ... @@ -795,6 +653,163 @@ let _detailDataPkgAsync = (origin, uid, vipLevel, ua) => {
});
};
/**
* [商品信息的异步数据获取] (优化)
*/
const getNewProductAsyncData = (data) => {
let params = {
method: 'app.product.data'
};
if (data.productSkn) { // 通过 productSkn 获取商品详情
Object.assign(params, {
product_skn: _.toString(data.productSkn)
});
} else if (data.id) { // 通过 productId 获取商品详情
Object.assign(params, {
product_id: _.toString(data.id)
});
}
if (data.uid) {
params.uid = data.uid;
}
params.is_student = data.isStudent ? 1 : 0;
params.current_vip_level = data.vipLevel;
// if (!params.is_student) {
// params.current_vip_level = data.vipLevel;
// }
return api.get('', params, {
code: 200,
cache: true
}).then(result => {
if (!result || result.code === 500 || !result.data) {
return {};
}
result = result.data;
result.goods_id = data.goodsId;
let apiArray = [
_cartCount(data.uid, data.shoppingKey),
_detailDataPkgAsync(_.assign(result, {
from: data.from,
closeBuyNowButton: data.closeBuyNowButton
}), data.uid, data.vipLevel, data.ua),
_getFavorite(result.product_id, data.uid)
];
if (data.bundleType) {
apiArray.push(bundle.getBundleBySkn(data.productSkn));
}
return Promise.all(apiArray).then((res) => {
let cartCount = res[0];
let finalResult = res[1];
let isFavorite = res[2];
let bundleData = _.get(res[3], 'data', {});
if (cartCount) {
finalResult.cartCount = cartCount;
}
finalResult.isCollect = isFavorite;
if (finalResult.cartInfo) {
finalResult.cartInfo.isCollect = isFavorite;
}
finalResult.isStudent = data.isStudent;
let discountBuy = _.find(bundleData, bund => _.get(bund, 'bundleInfo.discountType') === 2);
/* 量贩 */
if (bundleData && discountBuy) {
let minBuyNum = discountBuy.bundleInfo.bundleCount;
let isNotEnough = true;
// 是否满足量贩购买要求:剩余商品数量大于量贩最小购买量
_.forEach(result.goods_list, goods => {
_.forEach(goods.size_list, sizes => {
if (sizes.storage_number >= minBuyNum) {
isNotEnough = false;
}
});
});
if (finalResult.cartInfo && isNotEnough) {
finalResult.cartInfo.soldOut = isNotEnough;
finalResult.cartInfo.addToCartUrl = false;
}
finalResult.discountBuy = {
num: minBuyNum,
promotionPhrase: discountBuy.bundleInfo.promotionPhrase,
discount: discountBuy.bundleInfo.discount
};
}
return finalResult;
});
});
};
/**
* [商品信息的异步数据获取]
* 可能已经废弃的代码
*/
let getProductAsyncData = (data) => {
let finalResult;
let params = {
method: 'app.product.data'
};
if (data.productSkn) { // 通过 productSkn 获取商品详情
Object.assign(params, {
product_skn: _.toString(data.productSkn)
});
} else if (data.id) { // 通过 productId 获取商品详情
Object.assign(params, {
product_id: _.toString(data.id)
});
}
if (data.uid) {
params.uid = data.uid;
}
params.is_student = data.isStudent ? 1 : 0;
params.current_vip_level = data.vipLevel;
return api.get('', params, {
code: 200,
cache: true
}).then(result => {
if (!result || result.code === 500 || !result.data) {
return {};
}
result = result.data;
result.goods_id = data.goodsId;
return Promise.all([
_getPromotionInfo(result.product_skn),
_getFavorite(result.product_id, data.uid)
]).then((res) => {
result.promotionBoList = res[0];
let isFavorite = res[1];
return _detailDataPkgAsync(result, data.uid, data.vipLevel, data.ua).then(pkg => { // eslint-disable-line
finalResult = pkg;
finalResult.isCollect = isFavorite;
if (finalResult.cartInfo) {
finalResult.cartInfo.isCollect = isFavorite;
}
finalResult.isStudent = data.isStudent;
return finalResult;
});
});
});
};
/**
* 获取默认咨询列表
... ...
... ... @@ -162,6 +162,13 @@ const getShopIntro = (shopId, uid) => {
}
return api.get('', params, {code: 200}).then(result => {
if (result && result.data) {
const imgReg = /<img [^>]*src=['"]([^'"]+)[^>]*>/gi;
result.data.shop_intro = (result.data.shop_intro || '').replace(imgReg, function(match, url) {
return match.replace(url, url.replace('http:', ''));
});
}
return result && result.data;
});
};
... ...
... ... @@ -6,265 +6,16 @@ const _ = require('lodash');
const commentModel = require('./consult-comment');
const bundle = require('./bundle');
const utils = '../../../utils';
const productProcess = require(`${utils}/product-process`);
const detailProcess = require(`${utils}/detail-process`);
const api = global.yoho.API;
const helpers = global.yoho.helpers;
const tool = {
prodessDetailData(origin) {
let dest = {}; // 结果输出
// 商品名称
if (!origin.product_name) {
return dest;
}
dest.goodsName = origin.product_name;
// 是否是虚拟商品
// dest.virtualGoods = (origin.attribute * 1 === 3);
// 活动促销短语
origin.market_phrase && origin.market_phrase !== ' ' && (dest.marketPhrase = origin.market_phrase);
// 商品促销短语
origin.sales_phrase && origin.sales_phrase !== ' ' && (dest.goodsSubtitle = origin.sales_phrase);
// 商品标签
if (origin.tags) {
let productTags = {};
_.forEach(origin.tags, function(value) {
productTags[value] = true;
});
dest.tags = productTags;
}
// 商品价格
let goodsPrice = {
currentPrice: origin.format_sales_price === '0' ? origin.format_market_price : origin.format_sales_price
};
if (origin.format_sales_price !== '0' && origin.format_market_price !== origin.format_sales_price) {
goodsPrice.previousPrice = origin.format_market_price;
}
dest.goodsPrice = goodsPrice;
// 商品返回 YOHO 币
// origin.yohoCoinNum && (dest.commodityReturn = origin.yohoCoinNum);
// 上市期
origin.expect_arrival_time && (dest.periodOfMarket = origin.expect_arrival_time);
// 品牌信息
if (origin.shop_id) {
let extra = `?productSkn=${origin.product_skn}&shopId=${origin.shop_id}`;
dest.preferenceUrl = `/product/detail/preference${extra}`;
}
// dest.brandId = origin.brand_info && origin.brand_info.brand_id || 0;
dest.brandId = _.get(origin, 'brand_info.brand_id', 0);
dest.shopId = _.get(origin, 'shopId', 0);
dest.productSkn = origin.product_skn;
dest.id = origin.product_id;
dest.goodsId = origin.goods_id;
dest.isDepositAdvance = origin.is_deposit_advance === 'Y'; // 是否定金预售
dest.isSeckill = origin.is_secKill === 'Y'; // 是否秒杀
dest.isLimitBuy = origin.isLimitBuy; // 是否 限购
dest.isPresale = Boolean(origin.expect_arrival_time); // 是否普通预售
dest.bundleType = origin.bundle_type; // 商品活动标记
// 自定义 属性
dest.showCoupon = !(
dest.isDepositAdvance || dest.isSeckill || dest.isLimitBuy || dest.isPresale
); // 商品有限购、秒杀、定金预售、普通预售 不显示领
// 20170113 要求关闭商品详情页面领券功能
// dest.showCoupon = false;
// 商品信息
if (origin.goods_list.length) {
let goodsGroup = [];
// pagecache重构
_.forEach(origin.goods_list, function(value) {
// 商品分组
if (value.images_list) {
_.forEach(value.images_list, function(good) {
goodsGroup.push({
goodsId: value.goods_id,
img: good.image_url
});
});
}
});
// 商品图:多个
if (goodsGroup.length > 1) {
let bannerList = [];
_.forEach(goodsGroup, function(value) {
value.img = _.replace(value.img, '/quality/80', '/quality/70');
bannerList.push({
img: value.img
});
});
dest.bannerTop = {
list: bannerList
};
} else if (goodsGroup[0]) {
dest.bannerTop = {
img: goodsGroup[0].img
};
}
}
// 底部简介URL链接
dest.introUrl = '/product/detail/intro/' + origin.product_skn;
dest.brandName = _.get(origin, 'brand_info.brand_name', '');
dest.sortName = _.get(origin, 'middle_sort_name', '');
return dest;
},
/**
* 处理品牌关联店铺信息
* @param {array}
* @return {array}
*/
processShopsInfo(data) {
let enterStore = [];
_.forEach(data, function(value) {
let shopInfo = {
img: value.brand_ico,
storeName: value.brand_name
};
if (value.shop_id) {
shopInfo.url = helpers.urlFormat('/product/index/brand', {
shop_id: value.shop_id
});
} else {
shopInfo.url = helpers.urlFormat('', null, value.brand_domain);
}
enterStore.push(shopInfo);
});
return enterStore;
},
/**
* 处理商品 feedback
* @param data feedback要处理数据
* {
* comment, defaultConsult, userConsult
* }
* @param productId 商品id
* @return feedback
*/
processFeedback(data, productId) {
// let {comment, defaultConsult, userConsult} = data;
let comment = data.comment;
let defaultConsult = data.defaultConsult;
let userConsult = data.userConsult;
let feedbacks = {consults: [], consultsNum: 0};
Object.assign(feedbacks, comment);
// 商品评价
feedbacks.commentsUrl = helpers.urlFormat('/product/detail/comments', {
product_id: productId
});
/* 如果有用户咨询,显示用户咨询,否则显示常见问题 */
let obj = {};
if (userConsult.total) {
obj = {
commonConsults: false,
consultsNum: parseInt(userConsult.total, 10),
consults: _.take(userConsult.list, 2)
};
} else if (!_.isEmpty(defaultConsult) && !_.get(comment, 'consultsNum', 0)) {
obj = {
commonConsults: true,
consultsNum: true,
consults: _.take(defaultConsult.faq, 2)
};
}
Object.assign(feedbacks, obj);
if (_.get(feedbacks, 'consultsNum')) {
feedbacks.consultsUrl = helpers.urlFormat('/product/detail/consults', {
product_id: productId,
total: feedbacks.consultsNum
});
} else {
feedbacks.consultsUrl = helpers.urlFormat('/product/detail/consultform', {
product_id: productId
});
}
return feedbacks;
},
/**
* 套餐数据处理
* @param bundleData
* @param skn
* @returns {{}}
*/
processBundle(bundleData, skn, productId, index) {
let subPrice = _.get(bundleData, 'bundleInfo.subPrice', 0);
return {
tabName: _.get(bundleData, 'bundleInfo.tabName') || '',
title: _.get(bundleData, 'bundleInfo.bundleName') || '优惠套装',
href: helpers.urlFormat('/product/bundle/detail', {bundle_skn: skn, productId: productId, index: index}),
description: subPrice ? '立省¥' + subPrice : 0,
productList: productProcess.processProductList(bundleData && bundleData.productList)
};
},
const newDetail = {
/**
* 处理量贩数据
* @param finalResult
* @param bundleData
* 后端 Node 调用 indexRedirect
* seckill-detail.js
* new-detail.js
* @param {*} data
*/
processDiscount(finalResult, bundleData) {
finalResult.discountBuy = {
num: _.get(bundleData, 'bundleInfo.bundleCount', 1),
promotionPhrase: _.get(bundleData, 'bundleInfo.promotionPhrase', ''),
discount: _.get(bundleData, 'bundleInfo.discount', 1)
};
let oldPromotion = finalResult.promotion;
finalResult.promotion = [{
promotionTitle: _.get(bundleData, 'bundleInfo.promotionPhrase', ''),
promotionType: '量贩'
}];
_.forEach(oldPromotion, value => {
finalResult.promotion.push(value);
});
}
};
const newDetail = {
getProductData(data) {
let params = {
method: 'app.product.data'
... ... @@ -291,7 +42,7 @@ const newDetail = {
result.data.goods_id = data.goodsId;
result.data.shopId = _.get(result, 'data.shop_id', null);
return tool.prodessDetailData(result.data);
return detailProcess.prodessDetailData(result.data);
});
},
... ... @@ -330,7 +81,7 @@ const newDetail = {
finalResult.promotion = info[4];
finalResult.enterStore = info[0];
finalResult.feedbacks = tool.processFeedback({
finalResult.feedbacks = detailProcess.processFeedback({
comment: info[1],
defaultConsult: info[2],
userConsult: info[3]
... ... @@ -342,10 +93,10 @@ const newDetail = {
if (_.some(bundleDatas, data => _.get(data, 'bundleInfo.discountType') === 2)) {
let discountBuy = _.find(bundleDatas, bund => _.get(bund, 'bundleInfo.discountType') === 2);
tool.processDiscount(finalResult, discountBuy);
detailProcess.processDiscount(finalResult, discountBuy);
} else { /* 套装 */
finalResult.bundleDatas = _.map(bundleDatas, (data, index) => {
return tool.processBundle(data, skn, productId, ++index);
return detailProcess.processBundle(data, skn, productId, ++index);
});
}
... ... @@ -372,7 +123,7 @@ const newDetail = {
return api.get('', params, cacheConf)
.then(result => {
if (result && result.code === 200) {
return tool.processShopsInfo(result.data);
return detailProcess.processShopsInfo(result.data);
}
return [];
}, () => []);
... ...
... ... @@ -35,7 +35,7 @@ const getPreferenceData = (data) => {
default_images: value.default_images,
is_soon_sold_out: value.is_soon_sold_out === 'Y',
url: helpers.urlFormat(`/product/${value.product_skn}.html`), // 商品url改版
market_price: value.market_price,
market_price: value.market_price === value.sales_price ? false : value.market_price,
sales_price: value.sales_price
};
... ...
... ... @@ -13,6 +13,7 @@ const logger = global.yoho.logger;
const api = global.yoho.API;
const cache = require('memory-cache');
const helpers = global.yoho.helpers;
const redis = global.yoho.redis;
/**
* 封面图
... ... @@ -187,6 +188,11 @@ const _searchGoods = (params) => {
method = 'app.search.coupon';
}
// 物料商品列表增加
if (params.material === 'true') {
method = 'app.search.recommendProduct';
}
return api.get('', _.assign({
method: method
}, params), {
... ... @@ -249,8 +255,15 @@ const getSearchData = (params) => {
newList.list = productProcess.processProductList(result.data.product_list || [], {
isApp: params.isApp || (params.appVersion && params.appVersion !== 'false'),
gender: _coverChannel[params.coverChannel],
showSimilar: params.shop_id ? false : true
showSimilar: params.shop_id || params.material === 'true' ? false : true
});
if (params.unionType && (params.material === 'true')) {
_.forEach(newList.list, (val) => {
let newUrl = val.url;
val.url = newUrl.replace('.html', `.html?union_type=${params.unionType}`);
});
}
if (result.data.rec_shop_list && result.data.rec_shop_list.length > 0 &&
!params.shop_id && !params.brand && !params.isApp) {
... ... @@ -527,6 +540,41 @@ const getSearchKeywordData = (params, uid) => {
});
};
const getSearchKeywordDataById = (id, params, uid) => {
return redis.all([
['get', `golobal:yoho:seo:keywords:id:${id}`]
]).then(redisData => {
if (!redisData[0]) {
return Promise.reject('get redis canpin keywords by id error!' +
`key: golobal:yoho:seo:keywords:id:${id} value: ${redisData[0]}`);
}
redisData = JSON.parse(redisData[0]);
params.query = redisData.name;
return getSearchKeywordData(params, uid).then(result => {
result.queryKey = params.query;
if (!_.isEmpty(redisData.data)) {
_.forEach(redisData.data, value => {
if (!value) {
return;
}
Object.assign(value, {
name: value.keyword,
link: helpers.urlFormat(`/chanpin/${value.id}.html`, null)
});
});
_.set(result, 'fuzzyWord', redisData.data);
}
return result;
});
});
};
module.exports = {
getSearchData,
getFilterData,
... ... @@ -537,5 +585,6 @@ module.exports = {
getFuzzyDatas,
searchKeyActivity,
getBrandDomain,
getSearchKeywordData
getSearchKeywordData,
getSearchKeywordDataById
};
... ...
... ... @@ -77,8 +77,7 @@ router.get('/detail/preference', detail.preference); // 为你优选
router.get('/detail/consults', detail.consults); // 商品咨询页
router.get('/detail/consultform', auth, detail.consultform); // 商品咨询表单页
router.get('/detail/comments', detail.comments); // 商品评价
router.post('/detail/info', detail.getUser, detail.indexData); // 商品详情页-异步数据
router.post('/detail/newinfo', detail.getUser, newDetail.indexData); // 商品详情页-异步数据 (优化)
router.get('/detail/newinfo', detail.getUser, newDetail.indexData); // 商品详情页-异步数据 (优化)
router.post('/detail/consultsubmit', auth, detail.consultsubmit); // 商品咨询提交接口
... ... @@ -135,8 +134,9 @@ router.get('/seckill/get-product-list', seckill.getProductList); // 秒杀列表
// 搜索主页
router.get('/search/index', search.index);
// 搜索落地页
router.get('/search/keyword/:query', rewrite.sortParams, search.keyword);
// 推广落地页
router.get('/search/so/:query.html', rewrite.sortParams, search.keyword);
router.get('/search/chanpin/:id.html', rewrite.sortParams, search.keyId);
// 搜索落地页
router.get('/search/list', rewrite.sortParams, search.list);
... ...
... ... @@ -62,10 +62,11 @@ exports.getOrders = (req, res, next) => {
*
*/
exports.fetchHistory = (req, res) => {
const uid = req.user.uid || req.query.uid;
const encryptedUid = req.body.encryptedUid;
const endTime = req.body.endTime;
imApi.fetchImHistory(encryptedUid, endTime).then(result => {
imApi.fetchImHistory(uid, encryptedUid, endTime).then(result => {
res.json(result);
});
};
... ... @@ -78,11 +79,12 @@ exports.fetchHistory = (req, res) => {
* content 留言内容
*/
exports.saveMSG = (req, res) => {
let encryptedUid = req.body.encryptedUid;
const uid = req.user.uid || req.query.uid;
const encryptedUid = req.body.encryptedUid;
const conversationId = req.body.conversationId;
const content = req.body.content;
imApi.saveMessage(encryptedUid, conversationId, content)
imApi.saveMessage(uid, encryptedUid, conversationId, content)
.then(result => {
res.json(result);
});
... ... @@ -97,9 +99,10 @@ exports.saveMSG = (req, res) => {
* 2. 失败情况
*/
exports.fetchOrders = (req, res) => {
let encryptedUid = req.body.encryptedUid;
const uid = req.user.uid || req.query.uid;
const encryptedUid = req.body.encryptedUid;
imApi.fetchOrderList(encryptedUid)
imApi.fetchOrderList(uid, encryptedUid)
.then(result => {
imModel.handleOrderList(result.data, 128, 170);
res.json(result);
... ... @@ -112,7 +115,8 @@ exports.fetchOrders = (req, res) => {
};
exports.saveEvalute = (req, res) => {
const params = {};
const uid = req.user.uid || req.query.uid;
const params = { uid };
params.encryptedUid = req.body.encryptedUid;
params.conversationId = req.body.conversationId;
... ... @@ -140,7 +144,8 @@ exports.saveEvalute = (req, res) => {
exports.queryGlobalOrder = (req, res) => {
let encryptedUid = req.body.encryptedUid;
const uid = req.user.uid || req.query.uid;
const encryptedUid = req.body.encryptedUid;
let emptyOrder = {
code: 200,
... ... @@ -148,9 +153,12 @@ exports.queryGlobalOrder = (req, res) => {
message: '获取失败'
};
imApi.queryGlobalOrder(encryptedUid)
imApi.queryGlobalOrder(uid, encryptedUid)
.then(result=> {
imModel.handleOrderList(result.data, 128, 170);
if (result.code === 200) {
imModel.handleOrderList(result.data, 128, 170);
}
res.json(result);
}, () => {
res.json(emptyOrder);
... ... @@ -165,8 +173,10 @@ exports.queryGlobalOrder = (req, res) => {
*/
exports.queryReasons = (req, res) => {
const type = req.body.type;
const uid = req.user.uid || req.query.uid;
const encryptedUid = crypto.encryption(null, uid + '');
imApi.queryReasons(type)
imApi.queryReasons(uid, encryptedUid, type)
.then(result=> {
res.json(result);
})
... ...
... ... @@ -18,8 +18,9 @@ const ImService = new global.yoho.ApiBase(config.domains.imCs, {
* @param {int} conversationId 会话id
* @param {str} content 留言内容
*/
exports.saveMessage = (encryptedUid, conversationId, content) => {
exports.saveMessage = (uid, encryptedUid, conversationId, content) => {
let params = {
uid,
conversationId,
content,
encryptedUid
... ... @@ -38,8 +39,9 @@ exports.saveMessage = (encryptedUid, conversationId, content) => {
* @param [int] startTime
* @param [int] endTime
*/
exports.fetchImHistory = (encryptedUid, endTime, pageSize, startTime) => {
exports.fetchImHistory = (uid, encryptedUid, endTime, pageSize, startTime) => {
let params = {
uid,
encryptedUid
};
... ... @@ -66,8 +68,9 @@ exports.fetchImHistory = (encryptedUid, endTime, pageSize, startTime) => {
* @param {string} encryptedUid 用户加密uid
* @param {init} createTimeBegin 开始时间
*/
exports.fetchOrderList = (encryptedUid, createTimeBegin) => {
exports.fetchOrderList = (uid, encryptedUid, createTimeBegin) => {
let params = {
uid,
encryptedUid,
imgSize: '90x120',
};
... ... @@ -110,8 +113,9 @@ exports.saveEvalute = (params) => {
* 获取全球购的订单
*/
exports.queryGlobalOrder = encryptedUid => {
exports.queryGlobalOrder = (uid, encryptedUid) => {
let params = {
uid,
encryptedUid
};
... ... @@ -122,9 +126,11 @@ exports.queryGlobalOrder = encryptedUid => {
* 获取评价原因
* @param type 客服设置类型
*/
exports.queryReasons = type => {
exports.queryReasons = (uid, encryptedUid, type) => {
let params = {
type
uid,
type,
encryptedUid
};
return ImService.post('/api/evalute/queryReasonBySettingType', params);
... ...
... ... @@ -22,9 +22,5 @@
<p>抱歉,没有找到与“<span class="noKey"></span>”相关的问题,</p>
<p>您可以换个词再试试</p>
</div>
{{#if @root.wap.clientService.new}}
<div class="fix-tip">没有相关问题,请联系<a href="/service/im">在线客服</a></div>
{{else}}
<div class="fix-tip">没有相关问题,请联系<a href="http://chat8.live800.com/live800/chatClient/chatbox.jsp?companyID=620092&configID=149091&jid=8732423409&info=">在线客服</a></div>
{{/if}}
</div>
... ...
<div class="list-group">
{{#if @root.wap.clientService.new}}
<a class="list clearfix" href="/service/im">
{{else}}
<a class="list clearfix" href="http://chat8.live800.com/live800/chatClient/chatbox.jsp?companyID=620092&configID=149091&jid=8732423409&info=">
{{/if}}
<i class="gm-ico icon"></i>
<div style="border-bottom: solid 1px #e6e6e6;">
<p class="title">在线客服</p>
... ...
... ... @@ -104,7 +104,8 @@ const cachePage = {
'/activity/shopNav': 30 * SECOND,
// 关键词页面
'/product/search/keyword/:query': 7 * DAY
'/product/search/so/:query.html': 7 * DAY,
'/product/search/chanpin/:id.html': 7 * DAY
};
... ...
... ... @@ -102,6 +102,7 @@ module.exports = {
notifyUrl: domains.service + 'payment/weixin_notify',
},
maxQps: 1200,
maxQps10m: 2500,
geetestJs: '//static.geetest.com/static/tools/gt.js',
jsSdk: '//cdn.yoho.cn/js-sdk/1.2.2/jssdk.js',
redis: {
... ...
'use strict';
module.exports = () => {
return (req, res, next) => {
if (req.query.nodownload) {
res.cookie('nodownload', 'true', {
domain: 'm.yohobuy.com',
expires: new Date(Date.now() + 24 * 3600 * 1000)
});
}
if (req.query.nogoback) {
res.cookie('nogoback', 'true', {
domain: 'm.yohobuy.com',
expires: new Date(Date.now() + 24 * 3600 * 1000)
});
}
if (req.query.nodownload || req.cookies.nodownload) {
res.locals.nodownload = true;
}
if (req.query.nogoback || req.cookies.nogoback) {
res.locals.nogoback = true;
}
next();
};
};
... ...
... ... @@ -5,12 +5,13 @@ const _ = require('lodash');
const WHITE_LIST = [
'/3party/check',
'/3party/check/submit',
'/passport/imagesNode',
'/passport/cert/headerTip',
'/passport/captcha/get',
'/passport/images',
'/passport/img-check.jpg',
'/3party/check/submit'
'/passport/geetest/register'
];
module.exports = (req, res, next) => {
... ...
... ... @@ -5,11 +5,14 @@ const cache = global.yoho.cache.master;
const config = global.yoho.config;
const ONE_DAY = 60 * 60 * 24;
const MAX_QPS = config.maxQps;
const MAX_QPS_10m = config.maxQps10m;
const _ = require('lodash');
const PAGES = {
'/product/\\/pro_([\\d]+)_([\\d]+)\\/(.*)/': 5,
'/product/list/index': 5
'/product/^\\/(\\d+)\\.html/': 5,
'/product/list/index': 5,
'/product/index/index': 5,
'/product/search/list': 5
};
function urlJoin(a, b) {
... ... @@ -27,6 +30,7 @@ module.exports = (limiter, policy) => {
res = limiter.res;
const key = `pc:limiter:${limiter.remoteIp}`;
const key10m = `pc:limiter:10m:${limiter.remoteIp}`;
res.on('render', function() {
let route = req.route ? req.route.path : '';
... ... @@ -39,37 +43,55 @@ module.exports = (limiter, policy) => {
let pageKey = urlJoin(appPath, route.toString()); // route may be a regexp
let pageIncr = PAGES[pageKey] || 0;
if (/^\/p([\d]+)/.test(req.path)) {
pageIncr = 5;
}
if (pageIncr > 0) {
cache.incrAsync(key, pageIncr, () => {});
cache.incrAsync(key, pageIncr);
cache.incrAsync(key10m, pageIncr);
}
});
return cache.getAsync(key).then((result) => {
logger.debug('qps limiter: ' + key + '@' + result + ' max: ' + MAX_QPS);
return cache.getMultiAsync([key, key10m]).then((results) => {
let result = results[key];
let result10m = results[key10m];
if (result && _.isNumber(result)) {
logger.debug('qps limiter: ' + key + '@' + result + ' max: ' + MAX_QPS);
logger.debug('qps limiter 10m: ' + key10m + '@' + result10m + ' max: ' + MAX_QPS_10m);
if (result === -1) {
return Promise.resolve(true);
}
// 默认数据设置
if (!result && !_.isNumber(result)) {
cache.setAsync(key, 1, 60); // 设置key,1m失效
}
if (result > MAX_QPS) { // 判断 qps
cache.touch(key, ONE_DAY);
logger.debug('req limit', key);
if (!result10m && !_.isNumber(result10m)) {
cache.setAsync(key10m, 1, 600); // 设置key,10m失效
}
return Promise.resolve(policy);
} else {
cache.incrAsync(key, 1); // qps + 1
return Promise.resolve(true);
// 第一次访问,都没计数,直接过
if (!result && !_.isNumber(result) && !result10m && !_.isNumber(result10m)) {
return Promise.resolve(true);
}
}
} else {
cache.setAsync(key, 1, 60); // 设置key,1m失效
if (result === -1 || result10m === -1) {
return Promise.resolve(true);
}
// 判断 qps 10分钟
if (result10m > MAX_QPS_10m) {
cache.touch(key10m, ONE_DAY);
logger.debug('req limit', key10m);
return Promise.resolve(policy);
}
// 判断 qps 1分钟
if (result > MAX_QPS) {
cache.touch(key, ONE_DAY);
logger.debug('req limit', key);
return Promise.resolve(policy);
}
cache.incrAsync(key, 1); // qps + 1
cache.incrAsync(key10m, 1); // qps + 1
return Promise.resolve(true);
});
};
... ...
const _ = require('lodash');
const redis = require('redis');
const bluebird = require('bluebird');
const config = require('../../config/common');
... ... @@ -9,6 +11,18 @@ try {
bluebird.promisifyAll(redis.RedisClient.prototype);
bluebird.promisifyAll(redis.Multi.prototype);
client.all = args => {
if (!client.ready) {
if (Array.isArray(args)) {
return Promise.resolve(_.fill(args, false));
} else {
return Promise.resolve(false);
}
}
return client.multi.call(client, args).execAsync();
};
client.on('error', function() {
global.yoho.redis = '';
});
... ...
... ... @@ -84,14 +84,8 @@ module.exports = () => {
}
break;
}
} else {
let soReg = /\/so\/(.*).html/;
if (soReg.test(req.path)) {
soReg.exec(req.url);
req.url = `/product/search/keyword/${RegExp.$1}`;
}
}
next();
};
};
... ...
... ... @@ -61,6 +61,11 @@ module.exports = () => {
req.url = '/activity/couponSend';
}
if (/\/chanpin\/(.*).html/.test(req.url) || /\/so\/(.*).html/.test(req.url)) {
// 获取seo兼容
req.url = `/product/search${req.path}`;
}
next();
};
};
... ...
... ... @@ -79,6 +79,9 @@
</div>
{{> download-app}}
{{#if nodownload}}
<input type="hidden" id="no-download" value="no-download">
{{/if}}
{{#ifand isProduction wap.open.bughd}}
<script type="text/javascript" src="//cdn.yoho.cn/tool/bj-report-tryjs.min.js?t={{startTime}}" crossOrigin="anonymous"></script>
<script type="text/javascript">
... ...
... ... @@ -4,9 +4,11 @@
{{^}}
<header id="yoho-header" class="yoho-header">
{{/ @root.pageChannel}}
{{#unless @root.nogoback}}
{{#navBack}}
<a href="{{#if backUrl}}{{backUrl}}{{^}}javascript:history.go(-1);{{/if}}" class="iconfont nav-back">&#xe610;</a>
{{/navBack}}
{{/unless}}
{{#navBtn}}
<span class="iconfont nav-home">&#xe638;</span>
{{/navBtn}}
... ... @@ -42,6 +44,9 @@
{{channel}} <span class="iconfont">&#xe616;</span>
</span>
{{/saleNav}}
{{#invoiceNotice}}
<span class="invoice-btn">{{.}}</span>
{{/invoiceNotice}}
</header>
{{#if saleNav.list}}
<div class="sale-nav-select">
... ...
const shelljs = require('shelljs');
const path = require('path');
const ext = process.platform === 'win32' ? '.cmd' : ''; // Windows 平台需要加后缀
const lintPath = {
js: path.resolve('./node_modules/.bin/eslint'),
css: path.resolve('./node_modules/.bin/stylelint')
};
const jsfiles = ['.', 'public/vue'];
const cssfiles = ['public/scss/**/*.css', 'public/vue/**/*.vue'];
jsfiles.forEach(function(filepath) {
console.log(`JS ${filepath} 检查结果:`);
shelljs.exec(`${lintPath.js}${ext} -f table -c .eslintrc --cache ${filepath}`);
});
cssfiles.forEach(function(filepath) {
console.log(`CSS ${filepath} 检查结果:`);
shelljs.exec(`${lintPath.css}${ext} --syntax scss --cache --config .stylelintrc --custom-formatter ./node_modules/stylelint-formatter-table/index.js "${filepath}"`); // eslint-disable-line
});
const shelljs = require('shelljs');
const path = require('path');
const changeFiles = {
js: shelljs.exec('git diff --cached --name-only --diff-filter=ACM | grep .js$', {silent: true}).stdout,
css: shelljs.exec('git diff --cached --name-only --diff-filter=ACM | grep .css$', {silent: true}).stdout,
vue: shelljs.exec('git diff --cached --name-only --diff-filter=ACM | grep .vue$', {silent: true}).stdout,
};
const lintPath = {
js: path.resolve('./node_modules/.bin/eslint'),
css: path.resolve('./node_modules/.bin/stylelint')
};
const lintResult = {
js: {},
css: {},
vueScript: {},
vueStyle: {}
};
const ext = process.platform === 'win32' ? '.cmd' : ''; // Windows 平台需要加后缀
// 在执行检查脚本的时候,不显示 NPM 错误日志
if (!shelljs.grep('npm run -s', path.resolve('./.git/hooks/pre-commit')).stdout.trim()) {
shelljs.sed('-i', 'npm run', 'npm run -s', path.resolve('./.git/hooks/pre-commit'));
}
if (changeFiles.js) {
changeFiles.js = changeFiles.js.replace(/\n/g, ' ');
lintResult.js = shelljs.exec(`${lintPath.js}${ext} -c .eslintrc --cache ${changeFiles.js}`);
}
if (changeFiles.css) {
changeFiles.css = changeFiles.css.replace(/\n/g, ' ');
lintResult.css = shelljs.exec(`${lintPath.css}${ext} --syntax scss --config .stylelintrc ${changeFiles.css}`);
}
if (changeFiles.vue) {
changeFiles.vue = changeFiles.vue.replace(/\n/g, ' ');
lintResult.vueScript = shelljs.exec(`${lintPath.js}${ext} -c .eslintrc --cache ${changeFiles.vue}`);
lintResult.vueStyle = shelljs.exec(`${lintPath.css}${ext} --syntax scss --extract --config .stylelintrc ${changeFiles.vue}`); // eslint-disable-line
}
const errorCode = lintResult.js.code || lintResult.css.code || lintResult.vueScript.code || lintResult.vueStyle.code;
if (errorCode) {
process.exit(errorCode); // eslint-disable-line
}
{
"name": "m-yohobuy-node",
"version": "5.8.1",
"version": "5.8.10",
"private": true,
"description": "A New Yohobuy Project With Express",
"repository": {
... ... @@ -13,12 +13,29 @@
"static": "webpack-dev-server --config ./public/build/webpack.dev.config.js",
"build": "webpack --config ./public/build/webpack.prod.config.js",
"debug": "DEBUG=\"express:*\" nodemon -e js,hbs -i public/ app.js",
"lint-js": "eslint -c .eslintrc --cache .",
"lint-css": "stylelint --syntax scss --cache --config .stylelintrc 'public/scss/**/*.css'",
"lint-vue-js": "eslint -c .eslintrc --cache public/vue",
"lint-vue-css": "stylelint --syntax scss --extract --cache --config .stylelintrc 'public/scss/**/*.vue'",
"lint-all": "node lint-all.js",
"precommit": "node lint-commit.js"
"lint-js": "lint-js",
"lint-css": "lint-css",
"lint-all": "lint-all",
"precommit": "lint-commit"
},
"config": {
"lintJs": [
{
"title": "JS",
"path": [
"."
]
}
],
"lintCss": [
{
"title": "CSS",
"path": [
"public/scss/**/*.css",
"public/**/*.vue"
]
}
]
},
"license": "MIT",
"dependencies": {
... ... @@ -109,6 +126,7 @@
"yoho-jquery": "^2.2.4",
"yoho-jquery-lazyload": "^1.9.12",
"yoho-jquery-qrcode": "^0.14.0",
"yoho-lint": "^1.0.1",
"yoho-mlellipsis": "0.0.3",
"yoho-qs": "^1.0.1",
"yoho-swiper": "^3.3.1",
... ...
... ... @@ -60,7 +60,12 @@
</div>
</div>
<div class="btn-wrap">
<button id="chose-btn-sure" class="btn btn-sure">{{@root.buttonText}}</button>
{{#if @root.buttonText.double}}
<button id="chose-btn-buynow" class="btn btn-sure-buynow">立即购买</button>
<button id="chose-btn-sure" class="btn btn-sure-addtocart">加入购物车</button>
{{^}}
<button id="chose-btn-sure" class="btn btn-sure">{{@root.buttonText.text}}</button>
{{/if}}
</div>
</div>
</div>
... ...
... ... @@ -19,7 +19,13 @@
<div class="tip{{#unless @root.isCollect}} opa{{/unless}}">{{#if @root.isCollect}}已收藏{{else}}收藏{{/if}}</div>
</a>
{{#if addToCartUrl}}
<a id="addtoCart" href="javascript:;" class="addto-cart add-to-cart-url">{{#if tickets}}立即购买{{else}}加入购物车{{/if}}</a>
<a id="addtoCart" href="javascript:;" class="addto-cart add-to-cart-url">加入购物车</a>
{{/if}}
{{#if tickets}}
<a id="addtoCart" href="javascript:;" class="addto-cart add-to-cart-url">立即购买</a>
{{/if}}
{{#if isDepositAdvance}}
<a id="isDepositAdvance" href="javascript:;" class="addto-cart add-to-cart-url">立即购买</a>
{{/if}}
{{#if soldOut}}
<a id="soldOut" href="javascript:;" class="sold-out">已售罄</a>
... ...
'use strict';
import {
Controller
} from 'yoho-mvc';
const allProduct = require('../../product/shop/all-product');
const lazyLoad = require('yoho-jquery-lazyload');
class MaterialController extends Controller {
constructor() {
super();
allProduct.getFilter();
lazyLoad($('img.lazy'));
}
}
module.exports = MaterialController;
... ...
require('3party/material-new.page.css');
const MaterialNewController = require('./controller');
new MaterialNewController();
... ...
... ... @@ -11,7 +11,7 @@ let question = {
let that = this;
this.$errTip = $('.error-tip');
this.$item = $('.qs-item', this.$base);
this.$item = $('.qs-item, .sub-qs-item', this.$base);
this.startTime = Date.parse(new Date()) / 1000;
if (this.$base.length) {
... ... @@ -44,11 +44,17 @@ let question = {
let that = this;
this.$base.on('click', '.radio-option', function() {
let $this = $(this);
let $this = $(this),
$par = $this.parent();
let jid = $this.data('jid');
if (!$this.hasClass('on')) {
$this.siblings('.on').removeClass('on');
$this.addClass('on');
if ($par.hasClass('qs-item')) {
that.setSubQuestion($par.next('.sub-qs-wrap'), jid);
}
}
}).on('click', '.check-option', function() {
let $this = $(this);
... ... @@ -65,21 +71,48 @@ let question = {
window.event.cancelBubble = true;
}
});
$('.submit-btn').click(function() {
that.saveAnswers(that.packAnswersInfo());
});
},
setSubQuestion: function($wrap, ids) {
if (!$wrap.length) {
return;
}
$wrap.slideUp();
$wrap.children().addClass('hide');
if (typeof ids === 'string' || typeof ids === 'number') {
ids = [ids];
}
if (!Array.isArray(ids)) {
return;
}
let i;
for (i = 0; i < ids.length; i++) {
if (ids[i]) {
$wrap.find('.sub-' + ids[i]).removeClass('hide');
}
}
$wrap.slideDown();
},
packAnswersInfo: function() {
let that = this;
let answer = [];
let $errDom;
this.$item.each(function() {
if ($errDom) {
let $this = $(this);
if ($errDom || $this.hasClass('hide')) {
return;
}
let $this = $(this);
let data = $this.data();
let ans = [];
let errText = '';
... ... @@ -163,10 +196,18 @@ let question = {
}
},
saveAnswers: function(info) {
if (!info || !info.length) {
var that = this;
if (this.saving || !info || !info.length) {
return;
}
this.saving = true;
setTimeout(function() {
that.saving = false;
}, 5000);
$.ajax({
type: 'POST',
url: '/3party/questionnaire/submit',
... ... @@ -178,6 +219,7 @@ let question = {
frontAnswers: JSON.stringify(info)
}
}).then(function(data) {
that.saving = false;
if (data.code === 200) {
tipDg.show('调查问卷已成功提交,感谢您的帮助!');
... ...
... ... @@ -99,6 +99,8 @@ tipDialog.init();
let $list = $('#qs-list');
let canShare = $list.hasClass('can-share');
$list.on('click', 'li', function() {
let data = $(this).data();
... ... @@ -110,10 +112,10 @@ $list.on('click', 'li', function() {
if (resData.code === 200) {
jumpQuestionDetail(data);
} else if (resData.code === 206) {
if (yoho && yoho.isApp) {
if (canShare && yoho && yoho.isApp) {
yoho.invokeMethod('go.showShareAlert', {
title: data.title,
link: 'http://m.yohobuy.com/3party/questionnaire/' + data.id,
link: 'https://m.yohobuy.com/3party/questionnaire/' + data.id,
desc: data.desc,
imgUrl: data.img
});
... ...
... ... @@ -19,10 +19,6 @@ let shareData = {
require('common');
require('common/share')(shareData);
if ($('.share-buy-page').height() < $(window).height()) {
$('.share-buy-page').height($(window).height());
}
if (yoho.isApp) {
if (window.queryString.act_id) {
shareData.link = 'http://m.yohobuy.com/activity/share-buy?act_id=' + window.queryString.act_id;
... ...
/*
* @Author: Targaryen
* @Date: 2017-06-21 10:30:21
* @Last Modified by: Targaryen
*/
require('buynow/order-ensure.page.css');
const $ = require('yoho-jquery');
const lazyLoad = require('yoho-jquery-lazyload');
const cookie = require('yoho-cookie');
const qs = require('yoho-qs');
let tip = require('plugin/tip'),
loading = require('plugin/loading'),
order = require('./order-info'),
richTip = require('plugin/rich-tip');
let $invoice = $('.invoice'),
$couponUse = $('.coupon-use.used'),
$addressWrap = $('.address-wrap'),
$coinCheck = $('.coin-check'),
$coinLi = $('li.coin'),
$subBlock = $('.sub-block'),
$ticketsMobile = $('#mobile'),
payType,
queryString = $.queryString(),
orderInfo = order.orderInfo,
isSubmiting,
dispatchInfo,
total,
isTickets = $('#ticketsPage').val(),
productSku = $('#productSku').val(),
buyNumber = $('#buyNumber').val(),
headerTop = $('#yoho-header').outerHeight(),
isYohoCoinClick = $coinLi.data('yoho-coin-click') * 1, // 判断有货币是否可以单击
addressTop = $('.address-wrap').outerHeight(),
$message = $('#msg'),
$noPrintPrice = $('.no-print-price');
require('common');
lazyLoad();
// 存 COOKIE
orderInfo('product_sku', qs.product_sku);
function getQueryParam() {
let queryArray = location.search.substr(1).split('&'),
i,
subArr = [],
obj = {};
for (i = 0; i < queryArray.length; i++) {
subArr = queryArray[i].split('=');
obj[subArr[0]] = subArr[1];
subArr = [];
}
return obj;
}
function isLimitGood() {
return getQueryParam().limitproductcode;
}
// 电子票下单
function _ticketsConfirm() {
let data = {
productSku: productSku,
buyNumber: buyNumber,
mobile: $ticketsMobile.val(),
useYohoCoin: orderInfo('use_yoho_coin')
};
if (!$ticketsMobile.val()) {
tip.show('手机号必填');
return;
}
$.ajax({
url: '/cart/index/submitTicket',
type: 'POST',
dataType: 'json',
data: data,
success: function(ticket) {
// 下单成功调整支付页面
if (ticket.code === 200) {
window.location.href = '/home/orders/paynew?order_code=' + ticket.data.order_code;
} else {
tip.show(ticket.message);
}
},
error: function() {
tip.show('网络异常~');
}
});
}
if (window.getUid() !== orderInfo('uid')) {
order.init();
window.location.reload();
}
if ($couponUse.data('name') !== orderInfo('couponName')) {
orderInfo('coupon_code', null);
orderInfo('couponName', null);
}
isLimitGood() && (function() {
let a = [];
let data = getQueryParam();
data.type = 'limitcode';
a.push(data);
orderInfo('skuList', JSON.stringify(a));
orderInfo('limitUrlSufix', location.search);
}());
if (queryString.cartType || queryString.carttype || !orderInfo('cartType')) {
orderInfo('cartType', queryString.cartType || queryString.carttype || 'ordinary');
}
$('.checkbox').on('touchstart', function(e) {
let $this = $(this);
if ($(e.target).closest('.coin-check').length && !isYohoCoinClick) {
return true;
}
if ($this.hasClass('icon-cb-radio')) {
$this.removeClass('icon-cb-radio').addClass('icon-radio');
return;
}
if ($this.hasClass('icon-radio')) {
$this.removeClass('icon-radio').addClass('icon-cb-radio');
}
});
$invoice.on('touchend', '.checkbox', function(e) {
let $this = $(this);
orderInfo('invoice', $this.hasClass('icon-cb-radio'));
if ($this.hasClass('icon-cb-radio')) {
$invoice.addClass('focus');
}
if ($this.hasClass('icon-radio')) {
$invoice.removeClass('focus');
orderInfo('invoices_title', null);
orderInfo('invoices_type', null);
orderInfo('receiverMobile', null);
orderInfo('buyerTaxNumber', null);
}
e.preventDefault();
e.stopPropagation();
});
function updateDeliverWay(deliver_way) {
let $moreJit = $('.more-jit a').get(0),
url;
if ($moreJit) {
url = $moreJit.href;
} else {
return;
}
if (url.indexOf('deliveryId') < 0) {
$moreJit.href = url + '&deliveryId=' + deliver_way;
} else {
$moreJit.href = url.replace(/deliveryId=(\d)/, 'deliveryId=' + deliver_way);
}
}
function orderCompute() {
let use_yoho_coin = orderInfo('use_yoho_coin'),
deliver_way = orderInfo('delivery_way'),
data = {
product_sku: qs.product_sku,
buy_number: qs.buy_number,
cart_type: orderInfo('cartType') || 'ordinary',
delivery_way: orderInfo('delivery_way'),
payment_type: orderInfo('payment_type'),
coupon_code: orderInfo('coupon_code'),
use_yoho_coin: use_yoho_coin,
skuList: isLimitGood() ? orderInfo('skuList') : void 0
};
loading.showLoadingMask();
$.ajax({
method: 'POST',
url: '/cart/index/buynow/ordercompute',
data: data
}).then(function(res) {
if ($.type(res) !== 'object') {
window.location.reload();
} else {
if (typeof res.last_order_amount !== 'undefined') {
res.last_order_amount = (+res.last_order_amount).toFixed(2);
}
if (res.use_yoho_coin) {
$coinCheck.find('em').html('- ¥ ' + res.use_yoho_coin);
$coinCheck.find('em').show();
}
$coinLi.find('.msg').html(res.yohoCoinCompute.yohoCoinMsg);
isYohoCoinClick = res.yohoCoinCompute.yohoCoinClick * 1;
$('.coin').data('yoho-coin', res.yohoCoinCompute.yohoCoin);
total = '';
if (res.promotion_formula_list) {
$.each(res.promotion_formula_list, function(index, value) {
total += '<li>' +
'<p>' + value.promotion + '</p>' +
'<span>' + value.promotion_amount + '</span>' +
'</li>';
});
$('.price-cost span').html('¥' + res.last_order_amount);
$('.bill span').html('¥' + res.last_order_amount);
$('.total').html(total);
}
updateDeliverWay(deliver_way);
}
}).fail(function() {
window.location.reload();
}).always(function() {
loading.hideLoadingMask();
});
}
function submitOrder() {
let msg = $('#msg').find('input').val() || orderInfo('msg');
if (isSubmiting) {
return false;
}
if (msg) {
if (msg.length > 40) {
tip.show('留言不得超过40个汉字');
return;
}
}
loading.showLoadingMask();
isSubmiting = true;
let postData = {
product_sku: qs.product_sku,
buy_number: qs.buy_number,
address_id: orderInfo('address_id'),
delivery_way: orderInfo('delivery_way'),
delivery_time: orderInfo('delivery_time'),
msg: msg,
is_print_price: orderInfo('is_print_price'),
payment_id: orderInfo('payment_id'),
payment_type: orderInfo('payment_type'), // 支付方式
coupon_code: orderInfo('coupon_code'),
use_yoho_coin: orderInfo('use_yoho_coin')
};
if (orderInfo('invoice')) {
Object.assign(postData, {
invoice: orderInfo('invoice'),
invoices_title: orderInfo('invoices_title'), // 发票抬头
invoices_type: orderInfo('invoices_type'), // 发票类型 1 纸质 2 电子
receiverMobile: orderInfo('receiverMobile'), // 接收人电话
buyerTaxNumber: orderInfo('buyerTaxNumber') // 购买方纳税人识别号,需要开具
});
}
$.ajax({
method: 'POST',
url: '/cart/index/buynow/ordersub',
data: postData
}).then(function(res) {
let url;
if (!res) {
tip.show('系统繁忙,请稍后再试!');
return;
}
if (res.code === 200) {
if (payType === 2) {
// 货到付款的进入订单页面
url = '/home/orderDetail?order_code=' + res.data.order_code;
} else {
url = '/home/orders/paynew?order_code=' + res.data.order_code;
}
if (window._yas && window._yas.sendCustomInfo) {
window._yas.sendCustomInfo({
op: 'YB_SC_TOPAY_CLICK',
param: JSON.stringify({
C_ID: window._ChannelVary[cookie.get('_Channel')],
ORDER_CODE: res.data.order_code + '',
PRD_NUM: $('#goods-num').val(),
ORDER_AMOUNT: res.data.order_amount
})
}, true);
}
if (window._fxcmd) {
window._fxcmd.push(['trackOrder', {
oid: res.data.order_code,
otp: res.data.order_amount,
u_info: cookie.get('_UID'),
u_type: cookie.get('_isNewUser') ? 1 : 0
}, []]);
}
cookie.remove(['buynow_info']);
window.location.href = url;
} else if (res.code === 409) {
richTip.show(res.message, res.buttons);
} else if (res.message) {
tip.show(res.message);
}
}).fail(function() {
tip.show('系统繁忙,请稍后再试!');
}).always(function() {
isSubmiting = false;
loading.hideLoadingMask();
});
}
// 界面点击,状态存 cookie
if (!orderInfo('address_id')) {
orderInfo('address_id', $addressWrap.data('id'));
}
$('.delivery-id').on('touchend', 'li', function() {
orderInfo('delivery_way', $(this).data('id'));
// 实付金额发生变化,使用有货币为0
orderInfo('use_yoho_coin', 0);
$('.coin').find('.checkbox').removeClass('icon-cb-radio').addClass('icon-radio');
orderCompute();
});
$('.payment-type').on('touchend', 'li', function() {
let $paymentType = $('.icon-cb-radio', this);
orderInfo('payment_id', $paymentType.data('id')); // 支付方式id
orderInfo('payment_type', $paymentType.data('payment-type')); // 支付方式
});
$('.dispatch-time').on('touchend', 'li', function() {
orderInfo('delivery_time', $(this).data('id'));
});
$('.yoho-coin-help-dialog-bg, .yoho-coin-footer').on('touchend', function(e) {
e.preventDefault();
$('.yoho-coin-help-dialog-bg').removeClass('show');
$('.yoho-coin-help-dialog').removeClass('show');
});
$('.coin').on('touchend', function(e) {
let $this = $(this);
if ($(e.target).closest('.yoho-coin-help').length) {
$('.yoho-coin-help-dialog-bg').addClass('show');
$('.yoho-coin-help-dialog').addClass('show');
return true;
}
if ($(e.target).closest('.coin-check').length <= 0) {
return false;
}
if (!isYohoCoinClick) {
return true;
}
if ($this.find('.checkbox').hasClass('icon-cb-radio')) {
orderInfo('use_yoho_coin', $this.data('yoho-coin'));
$this.find('.can-use').hide();
} else {
orderInfo('use_yoho_coin', 0);
$this.find('.coin-check em').hide();
$this.find('.can-use').show();
$this.find('.used').hide();
}
orderCompute();
});
/**
* 是否打印价格
*/
$noPrintPrice.on('touchend', '.checkbox', function(e) {
let $this = $(this);
orderInfo('is_print_price', $this.hasClass('icon-cb-radio') ? 'N' : 'Y');
e.preventDefault();
e.stopPropagation();
});
$invoice.find('[name="invoice-title"]').on('blur', function() {
orderInfo('invoices_title', $(this).val());
}).end().find('.invoice-type').on('change', function() {
orderInfo('invoices_type_id', $(this).val());
});
$('#msg').find('textarea').on('blur', function() {
orderInfo('msg', $(this).val());
});
$('form').on('submit', function() {
return false;
});
$('.dispatch').on('touchend', 'h3', function() {
if ($(this).siblings('ul').is(':hidden')) {
$('.dispatch h3').removeClass('border-none');
$(this).addClass('border-none');
$('.down').removeClass('hide');
$('.up').addClass('hide');
$('.up', this).removeClass('hide');
$('.down', this).addClass('hide');
$('.dispatch ul').hide();
$(this).siblings('ul').show();
} else {
$(this).removeClass('border-none');
$('.down', this).removeClass('hide');
$('.up', this).addClass('hide');
$(this).siblings('ul').hide();
}
});
$subBlock.on('touchstart', 'li', function() {
// 送货时间提示语li,不响应事件
if ($(this).hasClass('dispatch-time-info')) {
return true;
}
$.each($(this).parents('ul').find('i'), function() {
$(this).parents('ul').find('i').removeClass('icon-cb-radio').addClass('icon-radio');
});
let self = $(this);
setTimeout(function() {
self.parents('ul').hide();
}, 300);
$('.down').removeClass('hide');
$('.up').addClass('hide');
$('.dispatch h3').removeClass('border-none');
dispatchInfo = $(this).find('span').html();
$(this).parents('.sub-block').find('h3 span').html(dispatchInfo);
if ($(this).find('i').hasClass('icon-cb-radio')) {
$(this).find('i').addClass('icon-radio');
} else if ($(this).find('i').hasClass('icon-radio')) {
$(this).find('i').addClass('icon-cb-radio');
}
});
$('.bill a').on('touchstart', function() {
let $paymentType;
if (isTickets) {
_ticketsConfirm();
return;
}
$paymentType = $('.payment-type .icon-cb-radio');
orderInfo('payment_id', $paymentType.data('id')); // 支付方式id
orderInfo('payment_type', $paymentType.data('payment-type')); // 支付方式
payType = $paymentType.data('payment-type');
submitOrder();
});
function phoneHidden(phone) {
phone = phone || '';
return phone.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2');
}
$('.info-phone').html(phoneHidden($('.info-phone').html()));
if (orderInfo('address') && orderInfo('address').is_support === 'N') {
orderInfo('delivery_way', $('.delivery-id .icon-cb-radio').data('id'));
orderCompute();
}
// 校验手机号
$ticketsMobile.blur(function() {
let reg = /^[0123456789]{1,30}$/;
let mobile = $ticketsMobile.val();
if (!reg.test(mobile)) {
tip.show('手机号码不正确!');
}
});
// 留言点击滚动屏幕
$message.on('click', function() {
$('html,body').animate({
scrollTop: $message.offset().top
}, 500);
});
$(window).scroll(function() {
if ($(this).scrollTop() >= (headerTop + addressTop)) {
$('.address-bottom').show();
} else {
$('.address-bottom').hide();
}
});
... ...
/*
* @Author: Targaryen
* @Date: 2017-06-22 13:51:16
* @Last Modified by: Targaryen
* @Last Modified time: 2017-06-26 17:47:49
*/
require('common');
let info = window.cookie('buynow_info');
// cookie 参数
let actCkOpthn = {
path: '/cart/index'
};
function init() {
info = {
product_sku: null,
uid: window.getUid(),
delivery_way: $('.dispatch-mode .chosed').data('id') || 1,
delivery_time: 1,
payment_id: 1,
use_yoho_coin: 0,
address_id: null,
coupon_code: null,
couponName: null,
invoice: null, // 是否选择了发票
invoices_type: null, // 发票类型: 电子 or 纸质
invoices_title: null, // 发票抬头
receiverMobile: null, // 接收人电话
isModifyTel: false,
msg: null,
cartType: 'ordinary'
};
window.setCookie('buynow_info', JSON.stringify(info), actCkOpthn);
}
// info 必须是 JSON 字符串
try {
info = JSON.parse(info);
} catch (e) {
init();
}
exports.init = init;
exports.orderInfo = function(key, value) {
if (typeof value === 'undefined') {
return info[key];
}
info[key] = value;
window.setCookie('buynow_info', JSON.stringify(info), actCkOpthn);
};
... ...
/*
* @Author: Targaryen
* @Date: 2017-06-23 11:43:18
* @Last Modified by: Targaryen
* @Last Modified time: 2017-06-23 11:43:18
*/
require('cart/select-address.page.css');
let $ = require('yoho-jquery'),
orderInfo = require('./order-info').orderInfo;
let $confim = $('.confim-mask'),
deleteId;
require('../cart/address/address');
require('common');
$('.address-item').on('click', function() {
let $this = $(this);
let addressId = decodeURIComponent($this.data('address-id'));
let address = {
address_id: addressId,
consignee: $this.find('.name').text(),
mobile: $this.find('.tel').text(),
address_info: $this.find('.address-info').text(),
is_support: $this.data('is-support')
};
orderInfo('address_id', addressId);
orderInfo('address', address);
window.location.href = $this.data('href') + (orderInfo('limitUrlSufix') || '');
}).on('click', '.edit', function() {
window.location.href = $(this).data('href');
return false;
}).on('click', '.del', function() {
deleteId = $(this).data('id');
});
$confim.on('click', '.confim', function() {
if (orderInfo('address_id') === deleteId) {
orderInfo('address_id', null);
orderInfo('address', null);
}
});
... ...
/*
* @Author: Targaryen
* @Date: 2017-06-23 11:43:44
* @Last Modified by: Targaryen
* @Last Modified time: 2017-06-27 14:58:41
*/
require('cart/select-coupon.page.css');
const qs = require('yoho-qs');
let $ = require('yoho-jquery'),
ellipsis = require('yoho-mlellipsis'),
loading = require('plugin/loading'),
tip = require('plugin/tip'),
conponTmpl = require('cart/select-coupon/coupon.hbs'),
conponNotAvaliableTmpl = require('cart/select-coupon/coupon-not-avaliable.hbs'),
orderInfo = require('./order-info').orderInfo;
let isGetData;
let $newCoupon = $('#new-coupon'),
linkUrl = document.referrer,
$couponList = $('#coupon-list');
let winH = $(window).height();
require('common');
function fixedLayOut() {
let $null = $('.null'),
navH = $('.nav-title').height(),
nullH = $null.height();
if ($null.length === 0) {
return false;
}
$null.css({
top: winH / 2 - nullH / 2 + navH
});
}
ellipsis.init();
function goToBack() {
if (linkUrl) {
window.location.href = linkUrl;
} else {
history.go(-1);
}
}
$newCoupon.on('submit', function() {
let $this = $(this);
let couponCode = $this.find('[name="couponCode"]').val();
if (!couponCode) {
tip.show('请输入优惠券码');
return false;
}
$.ajax({
method: 'POST',
url: '/cart/index/buynow/usePromotionCode',
data: {
promotion_code: couponCode,
buy_number: qs.buy_number
}
}).then(function(res) {
if (res.code === 200) {
tip.show('优惠券可用');
// 实付金额发生变化,使用有货币为0
orderInfo('use_yoho_coin', 0);
orderInfo('coupon_code', res.data.coupon_code);
orderInfo('couponName', res.data.coupon_title);
goToBack();
} else {
tip.show(res.message);
}
}).fail(function() {
tip.show('网络错误');
});
return false;
});
$couponList.on('touchstart', '.employ-main', function() {
let $this = $(this);
$this.siblings().removeClass('focus');
$this.addClass('focus');
}).on('touchend touchcancel', '.employ-main', function() {
let $this = $(this);
$this.siblings().removeClass('focus');
$this.removeClass('focus');
});
$('body').on('touchend', '.not-use', function() {
orderInfo('coupon_code', null);
orderInfo('couponName', null);
// 实付金额发生变化,使用有货币为0
orderInfo('use_yoho_coin', 0);
goToBack();
});
$newCoupon.find('input').on('input', function() {
if ($(this).val() !== '') {
$newCoupon.find('.submit').css('background', '#444');
} else {
$newCoupon.find('.submit').css('background', '#b0b0b0');
}
});
function getCouponHandle(allCoupons) {
let notAvailableCoupons,
coupons;
// 把可用和不可用的优惠券分离出来
notAvailableCoupons = allCoupons.unusableCoupons;
coupons = allCoupons.usableCoupons;
// 没有优惠券
if (!(notAvailableCoupons.length || coupons.length)) {
$('.coupon-wrap').html($('#tmpl-no-coupon').html());
fixedLayOut();
return;
}
$.each(coupons, function(i, coupon) {
coupon.couponValue = Math.floor(coupon.couponValue);
coupon.couponDetailInfomation = coupon.couponName;
});
$.each(notAvailableCoupons, function(i, coupon) {
coupon.couponValue = Math.floor(coupon.couponValue);
coupon.couponDetailInfomation = coupon.couponName;
});
// 渲染可用的优惠券
$couponList.append(conponTmpl({
coupons: coupons
})).find('.employ-main').on('touchstart', function() {
let couponCode = $(this).data('coupon-code');
$.ajax({
method: 'POST',
url: '/cart/index/buynow/useCoupon',
data: {
product_sku: qs.product_sku,
buy_number: qs.buy_number,
coupon_code: couponCode
}
}).then(function(res) {
if (res.code === 200) {
orderInfo('coupon_code', res.data.coupon_code);
orderInfo('couponName', res.data.coupon_title);
// 实付金额发生变化,使用有货币为0
orderInfo('use_yoho_coin', 0);
goToBack();
} else if (res.message) {
tip.show(res.message);
}
}).fail(function() {
tip.show('网络错误');
});
});
if (notAvailableCoupons.length) {
$('.not-avaliable-coupon-line').show();
}
$('#coupon-list-not').append(conponNotAvaliableTmpl({
notAvailableCoupons: notAvailableCoupons
}));
window.rePosFooter();
}
function getCouponData() {
if (isGetData) {
return;
}
loading.showLoadingMask();
isGetData = true;
$.ajax({
type: 'GET',
url: '/cart/index/buynow/listCoupon',
data: {
product_sku: qs.product_sku,
buy_number: qs.buy_number
},
dataType: 'json'
}).then(getCouponHandle).always(function() {
isGetData = false;
loading.hideLoadingMask();
});
}
getCouponData();
... ...
/*
* @Author: Targaryen
* @Date: 2017-06-23 11:43:34
* @Last Modified by: Targaryen
*/
require('cart/select-invoice.page.css');
let $ = require('yoho-jquery'),
tip = require('plugin/tip'),
dialog = require('plugin/dialog'),
order = require('./order-info');
let $invoiceNotice = $('.invoice-notice'),
$taxNumber = $('.tax-number'),
$editFlag = $('.edit-flag'),
$tel = $('.tel'),
$company = $('.company'),
$copyTel = $('.copy-tel');
let $confirmBtn = $('.confirm-btn');
let $buyerTaxNumber = $('#buyerTaxNumber');
let eInvoiceType = $('#eInvoices').data('id');
let orderInfo = order.orderInfo;
let linkUrl = document.referrer;
let isModifyTel = false;
let C_ID = window._ChannelVary[window.cookie('_Channel')] || 1;
require('common');
require('cartbuynow/select-invoice');
if (window.getUid() !== orderInfo('uid')) {
order.init();
window.location.reload();
}
function goToBack() {
if (linkUrl) {
window.location.href = linkUrl;
} else {
history.go(-1);
}
}
/**
* 切换确认按钮激活状态
*/
function switchBtnStatus() {
if ($('.invoice-top').find('.on').text() === '单位') {
if ($buyerTaxNumber.val() && $company.val() && $tel.val()) {
$confirmBtn.addClass('active');
} else {
$confirmBtn.removeClass('active');
}
} else {
if ($tel.attr('data-tel')) {
$confirmBtn.addClass('active');
} else {
$confirmBtn.removeClass('active');
}
}
}
/**
* 发票抬头输入监听
*/
$company.bind('input', function() {
switchBtnStatus();
});
/**
* 手机号输入监听
*/
$tel.bind('input', function() {
switchBtnStatus();
});
/**
* 税号输入监听
*/
$buyerTaxNumber.bind('input', function() {
switchBtnStatus();
});
// 单选效果
function chooseAction(pDom, dom) {
if (dom.hasClass('icon-cb-radio')) {
return;
} else {
pDom.find('.choose').removeClass('icon-cb-radio icon-radio').addClass('icon-radio');
dom.removeClass('icon-radio').addClass('icon-cb-radio');
dom.parent().addClass('on');
dom.parent().siblings().removeClass('on');
$editFlag.val('true');
}
}
// 确认表单事件
function confirmAction() {
let title = $('.invoice-top').find('.on').text(),
buyerTaxNumber = $buyerTaxNumber.val(),
tel = $tel.attr('data-tel'),
company = $company.val();
if ($editFlag.val() === 'true') {
if (!tel) {
tip.show('请输入正确手机号');
$tel.focus();
return false;
} else if (title === '单位' && company.length === 0) {
tip.show('请填写发票抬头');
$company.focus();
return false;
} else if (title === '单位' && company.length > 30) {
tip.show('发票抬头不得超过30个汉字');
$company.focus();
return false;
} else if (title === '单位' && !buyerTaxNumber) {
tip.show('请输入正确的15位或18位纳税人识别号');
$company.focus();
return false;
} else {
dialog.showDialog({
dialogText: '确认保存修改内容?',
hasFooter: {
leftBtnText: '取消',
rightBtnText: '确定'
}
}, function() {
orderInfo('invoices_type', eInvoiceType);
orderInfo('invoices_title', title === '单位' ? company : '');
orderInfo('receiverMobile', tel);
orderInfo('buyerTaxNumber', title === '单位' ? buyerTaxNumber : '');
if (isModifyTel && $copyTel !== tel) {
orderInfo('isModifyTel', true);
} else {
orderInfo('isModifyTel', false);
}
dialog.showDialog({
dialogText: '保存成功',
autoHide: true,
fast: true
});
goToBack();
}, function() {
goToBack();
});
}
} else {
goToBack();
}
}
// 发票抬头、发票内容选择
$('.invoice-top span, .invoice-cont li').not('.invoice-cont .cont-title').on('touchstart', function() {
chooseAction($(this).parent(), $(this).find('.choose'));
if ($(this).text() === '单位') {
$company.val('');
$company.removeAttr('disabled');
$taxNumber.slideDown();
}
if ($(this).text() === '个人') {
$company.val('个人(不可修改)');
$company.attr('disabled', 'true');
$taxNumber.slideUp();
}
switchBtnStatus();
});
// 发票须知
$('.invoice-btn').on('touchstart', function() {
$invoiceNotice.fadeIn();
return false;
});
// 关闭发票须知弹框
$('.think-ok, .mask-bg').on('touchstart', function() {
$invoiceNotice.fadeOut();
});
// 电话清空
$('.istel').one('input', function() {
$(this).val('').removeClass('istel');
});
$tel.on('input', function() {
$(this).attr('data-tel', $(this).val());
$editFlag.val('true');
isModifyTel = true;
});
$company.on('input', function() {
$editFlag.val('true');
});
// 确认及返回事件
$('.confirm-btn, .nav-back').on('touchstart', function(e) {
setTimeout(function() {
if (window._yas && window._yas.sendCustomInfo) {
window._yas.sendCustomInfo({
op: 'YB_SC_INVOICE_INFO_SAVE',
param: JSON.stringify({
C_ID: C_ID,
INVOICE_TYPE: eInvoiceType,
INVOICE_TITLE: $('.invoice-top').find('.on').text(),
INVOICE_CONTENT: 12
})
}, true);
}
}, 200);
e.preventDefault();
confirmAction();
});
... ...
... ... @@ -352,7 +352,9 @@ let goodObj = {
chosePanel.show({
data,
disableNum: !isEditNum,
buttonText: '确认'
buttonText: {
text: '确认'
}
}).then(result => {
if (result && result.sku) {
let goodData = {
... ...
... ... @@ -35,34 +35,10 @@ let $invoice = $('.invoice'),
$message = $('#msg'),
$noPrintPrice = $('.no-print-price');
let orderCont = cookie.get('order-info') && JSON.parse(cookie.get('order-info'));
let invoiceCont = {
7: '服装',
1: '图书',
9: '配件',
11: '日用品',
3: '办公用品',
6: '体育用品',
10: '数码产品'
},
invoicesType = {
1: '纸质',
2: '电子'
};
require('common');
lazyLoad();
// 初始化发票信息
function invoiceInit() {
if (orderCont.invoiceType) {
$('.invoice-type').text(invoiceCont[orderCont.invoiceType] + '(' + invoicesType[orderCont.invoicesType] + ')');
} else {
$('.invoice-type').text('服装(电子)');
}
}
function getQueryParam() {
let queryArray = location.search.substr(1).split('&'),
i,
... ... @@ -115,17 +91,6 @@ if (queryString.cartType || queryString.carttype || !orderInfo('cartType')) {
orderInfo('cartType', queryString.cartType || queryString.carttype || 'ordinary');
}
// function dispacthTapEvt(e) {
// let $cur = $(e.target).closest('li');
// if ($cur.length === 0 || $cur.hasClass('chosed')) {
// return;
// }
// $cur.siblings('li.chosed').removeClass('chosed');
// $cur.addClass('chosed');
// }
$('.checkbox').on('touchstart', function(e) {
let $this = $(this);
... ... @@ -143,31 +108,24 @@ $('.checkbox').on('touchstart', function(e) {
}
});
$invoice.on('touchend', '.checkbox', function() {
$invoice.on('touchend', '.checkbox', function(e) {
let $this = $(this);
orderInfo('invoice', $this.hasClass('icon-cb-radio'));
if ($this.hasClass('icon-cb-radio')) {
$invoice.addClass('focus');
orderInfo('invoiceText', '');
orderInfo('invoiceType', '7');
orderInfo('receiverMobile', $('.user-mobile').val());
orderInfo('invoicesType', '2');
orderInfo('invoiceTitle', '个人');
}
if ($this.hasClass('icon-radio')) {
$invoice.removeClass('focus');
orderInfo('invoiceText', null);
orderInfo('invoiceType', null);
orderInfo('invoices_title', null);
orderInfo('invoices_type', null);
orderInfo('receiverMobile', null);
orderInfo('invoicesType', null);
orderInfo('invoiceTitle', null);
orderInfo('buyerTaxNumber', null);
}
orderCont = cookie.get('order-info') && JSON.parse(cookie.get('order-info'));
invoiceInit();
e.preventDefault();
e.stopPropagation();
});
function updateDeliverId(id) {
let $moreJit = $('.more-jit a').get(0),
url;
... ... @@ -251,24 +209,12 @@ function orderCompute() {
}
function submitOrder() {
let invoiceText = $invoice.find('[name="invoice-title"]').val() || orderInfo('invoiceText'),
msg = $('#msg').find('input').val() || orderInfo('msg');
let msg = $('#msg').find('input').val() || orderInfo('msg');
if (isSubmiting) {
return false;
}
// if (orderInfo('invoice')) {
// if (!invoiceText) {
// tip.show('请输入发票抬头');
// return;
// }
// if (invoiceText.length > 30) {
// tip.show('发票抬头不得超过30个汉字');
// return;
// }
// }
if (msg) {
if (msg.length > 40) {
tip.show('留言不得超过40个汉字');
... ... @@ -277,25 +223,35 @@ function submitOrder() {
}
loading.showLoadingMask();
isSubmiting = true;
let postData = {
addressId: orderInfo('addressId'),
cartType: orderInfo('cartType') || 'ordinary',
deliveryId: orderInfo('deliveryId'),
deliveryTimeId: orderInfo('deliveryTimeId'),
msg: msg,
isPrintPrice: orderInfo('isPrintPrice'),
paymentTypeId: orderInfo('paymentTypeId'),
paymentType: orderInfo('paymentType'), // 支付方式
couponCode: orderInfo('couponCode'),
yohoCoin: orderInfo('yohoCoin'),
skuList: isLimitGood() ? orderInfo('skuList') : void 0
};
if (orderInfo('invoice')) {
Object.assign(postData, {
invoice: orderInfo('invoice'),
invoices_title: orderInfo('invoices_title'), // 发票抬头
invoices_type: orderInfo('invoices_type'), // 发票类型 1 纸质 2 电子
receiverMobile: orderInfo('receiverMobile'), // 接收人电话
buyerTaxNumber: orderInfo('buyerTaxNumber') // 购买方纳税人识别号,需要开具
});
}
$.ajax({
method: 'POST',
url: '/cart/index/new/orderSub',
data: {
addressId: orderInfo('addressId'),
cartType: orderInfo('cartType') || 'ordinary',
deliveryId: orderInfo('deliveryId'),
deliveryTimeId: orderInfo('deliveryTimeId'),
invoiceText: orderInfo('invoice') ? invoiceText : null,
invoiceType: orderInfo('invoice') ? ($invoice.find('.invoice-type').val() ||
orderInfo('invoiceType')) : null,
msg: msg,
isPrintPrice: orderInfo('isPrintPrice'),
paymentTypeId: orderInfo('paymentTypeId'),
paymentType: orderInfo('paymentType'), // 支付方式
couponCode: orderInfo('couponCode'),
yohoCoin: orderInfo('yohoCoin'),
skuList: isLimitGood() ? orderInfo('skuList') : void 0
}
data: postData
}).then(function(res) {
let url;
... ... @@ -380,16 +336,16 @@ $('.dispatch-time').on('touchend', 'li', function() {
$('.yoho-coin-help-dialog-bg, .yoho-coin-footer').on('touchend', function(e) {
e.preventDefault();
$('.yoho-coin-help-dialog-bg').addClass('hide');
$('.yoho-coin-help-dialog').addClass('hide');
$('.yoho-coin-help-dialog-bg').removeClass('show');
$('.yoho-coin-help-dialog').removeClass('show');
});
$('.coin').on('touchend', function(e) {
let $this = $(this);
if ($(e.target).closest('.yoho-coin-help').length) {
$('.yoho-coin-help-dialog-bg').removeClass('hide');
$('.yoho-coin-help-dialog').removeClass('hide');
$('.yoho-coin-help-dialog-bg').addClass('show');
$('.yoho-coin-help-dialog').addClass('show');
return true;
}
... ... @@ -413,14 +369,6 @@ $('.coin').on('touchend', function(e) {
orderCompute();
});
$invoice.on('touchend', '.checkbox', function(e) {
let $this = $(this);
orderInfo('invoice', $this.hasClass('icon-cb-radio'));
e.preventDefault();
e.stopPropagation();
});
/**
* 是否打印价格
*/
... ... @@ -566,9 +514,6 @@ $ticketsMobile.blur(function() {
}
});
// 初始化发票信息内容
invoiceInit();
// 留言点击滚动屏幕
$message.on('click', function() {
$('html,body').animate({
... ...
... ... @@ -22,9 +22,8 @@ function init() {
couponCode: null,
couponName: null,
invoice: null,
invoiceText: null,
invoiceType: null,
invoiceTitle: null,
invoices_title: null,
invoices_type: null,
receiverMobile: null,
isModifyTel: false,
invoicesType: null,
... ...
'use strict';
require('./seckill/order-ensure');
... ...
... ... @@ -4,7 +4,7 @@
* @author: xuqi<qi.xu@yoho.cn>
* @date: 2015/11/12
*/
require('cart/order-ensure.page.css');
require('common.js');
let lazyLoad = require('yoho-jquery-lazyload'),
... ...