Authored by 周少峰

Merge branch 'feature/like' into feature/payOrderCtx

... ... @@ -6,8 +6,7 @@
'use strict';
const Promise = require('bluebird');
const co = Promise.coroutine;
const favoriteService = require('../models/favorite-service');
const favoriteModel = require('../models/favorite-model');
const TABS = {
product: 'product',
... ... @@ -24,6 +23,7 @@ const index = (req, res, next)=> {
let reduction = req.query.is_reduction || 'N';
let promotion = req.query.is_promotion || 'N';
let limit = +req.query.limit || 10;
let favoriteService = req.ctx(favoriteModel);
co(function*() {
let data = {};
... ... @@ -58,6 +58,7 @@ const newProduct = (req, res, next) => {
let page = +req.query.page || 1;
let limit = +req.query.limit || 10;
let id = +req.query.id || 0;
let favoriteService = req.ctx(favoriteModel);
if (!id) {
return res.json({
... ... @@ -79,6 +80,8 @@ const reduction = (req, res, next) => {
let page = +req.query.page || 1;
let type = req.query.type || '';
let limit = 10;
let favoriteService = req.ctx(favoriteModel);
favoriteService.reductionAsync(uid, page, limit, type, 0, 'Y').then((result) => {
return res.render('home/favorite/reduction', result);
... ... @@ -89,6 +92,7 @@ const notice = (req, res, next) => {
let uid = req.user.uid;
let id = req.query.id;
let mobile = req.query.mobile;
let favoriteService = req.ctx(favoriteModel);
favoriteService.enableNoticeAsync(uid, mobile, id).then((result) => {
return res.json(result);
... ... @@ -98,6 +102,7 @@ const notice = (req, res, next) => {
const cancelNotice = (req, res, next) => {
let uid = req.user.uid;
let id = req.query.id;
let favoriteService = req.ctx(favoriteModel);
favoriteService.disableNoticeAsync(uid, id).then((result) => {
return res.json(result);
... ... @@ -109,6 +114,7 @@ const cancel = (req, res, next) => {
let id = req.query.id;
let type = req.query.type || 'product';
let group = req.query.group || {};
let favoriteService = req.ctx(favoriteModel);
if (!uid || !id) {
return res.json({
... ...
'use strict';
const api = global.yoho.API;
const service = global.yoho.ServiceAPI;
const _ = require('lodash');
// const URL_PRODUCT_FAVORITE = 'shops/service/v1/favorite/';
const URL_ARTICLE_FAVORITE = '/guang/api/v1/favorite/';
// const URL_ARTICLE_FAVORITE_BRAND = '/guang/service/v2/favorite/toggleBrand';
/**
* 根据uid和商品的id查询是否被用户收藏
* @param int $uid
* @param int $productId
* @return boolean 收藏 true 未收藏 false
*/
const getUidProductFav = (uid, productId)=> {
let options = {
method: 'web.favorite.isFavorite',
id: productId,
uid: uid,
type: 'product'
};
return api.get('', options);
};
const favoriteArticleData = (uid, udid, page, limit)=> {
let options = {
uid: uid,
udid: udid,
page: page,
limit: limit
};
return service.get(URL_ARTICLE_FAVORITE + 'getUserFavArticleList', options);
};
const cancelArticle = (uid, id) => {
return service.get(URL_ARTICLE_FAVORITE + 'cancelFavorite', {
uid: uid,
article_id: id
});
};
const getFavoriteProductList = (uid, page, limit)=> {
let options = {
method: 'web.favorite.product',
uid: uid,
page: 0,
limit: limit || 10
};
return api.get('', options);
};
const redutionCount = (uid)=> {
return api.get('', {
method: 'web.redution.count',
uid: uid
});
};
const favoriteBrandData = (uid, page, limit) => {
return api.get('', {
method: 'app.favorite.brand',
uid: uid,
page: page || 1,
limit: limit || 10
});
};
const redutionAdd = (uid, mobile, pid) => {
return api.get('', {
method: 'web.redution.add',
uid: uid,
mobile: mobile,
productId: pid
});
};
const redutionCancel = (uid, pid) => {
return api.get('', {
method: 'web.redution.cancel',
uid: uid,
productIds: pid
});
};
const _cancel = (type, uid, ids) => {
return api.get('', {
method: 'web.favorite.cancel',
favIds: ids,
uid: uid,
type: type
});
};
module.exports = {
getUidProductFav,
getFavoriteProductList,
favoriteArticleData,
favoriteBrandData,
redutionCount,
redutionAdd,
redutionCancel,
cancel: {
product: _.partial(_cancel, 'product', _, _),
shop: _.partial(_cancel, 'shop', _, _),
brand: _.partial(_cancel, 'brand', _, _),
article: cancelArticle
}
};
... ... @@ -4,9 +4,8 @@ const Promise = require('bluebird');
const co = Promise.coroutine;
const _ = require('lodash');
const helpers = global.yoho.helpers;
const pager = require('./pager').handlePagerData;
const favoriteApi = require('./favorite-api');
const URL_ARTICLE_FAVORITE = '/guang/api/v1/favorite/';
const TABS = [
{type: 'product', name: '商品收藏'},
... ... @@ -14,384 +13,501 @@ const TABS = [
{type: 'article', name: '文章收藏'}
];
const getFavoriteTabs = (type) => {
type = type || 'product';
module.exports = class favorite extends global.yoho.BaseModel {
constructor(ctx) {
super(ctx);
}
return TABS.map((item) => {
item.active = item.type === type;
item.url = helpers.urlFormat('/home/favorite', {type: item.type});
return item;
});
};
const _getSortInfo = (categoryList, sort)=> {
if (_.isEmpty(categoryList)) {
return false;
getFavoriteTabs(type) {
type = type || 'product';
return TABS.map((item) => {
item.active = item.type === type;
item.url = helpers.urlFormat('/home/favorite', {type: item.type});
return item;
});
}
let result = {};
_getSortInfo(categoryList, sort) {
if (_.isEmpty(categoryList)) {
return false;
}
result.all = categoryList.map((category) => {
return {
name: category.category_name,
url: helpers.urlFormat('/home/favorite', {sort_id: category.category_id}),
count: category.num,
focus: category.category_id === sort
};
});
let defaultCategory = {
name: '全部',
url: helpers.urlFormat('/home/favorite'),
count: _.sumBy(categoryList, category => category.num),
focus: sort === 0
};
result.all.unshift(defaultCategory);
result.default = result.all.slice(0, 7);
return result;
};
let result = {};
const getGoodsInfo = (data, page, limit)=> {
let result = data.slice((page - 1) * limit, page * limit).map((item) => {
return {
skn: item.product_id,
img: helpers.image(item.image, 100, 100),
name: item.product_name,
url: helpers.getUrlBySkc(item.product_skn),
price: item.sales_price,
priceDown: item.price_down,
buyNow: helpers.getUrlBySkc(item.product_skn),
soldOut: item.storage === 0 ? true : '',
hadNoticed: item.is_subscribe_reduction === 'Y' ? true : '',
activites: {
count: item.promotion_list ? item.promotion_list.length : 0,
list: _.get(item, 'promotion_list', []).map((val) => {
return {
type: val.promotion_type,
name: val.promotion_title
};
})
}
};
});
result.all = categoryList.map((category) => {
return {
name: category.category_name,
url: helpers.urlFormat('/home/favorite', {sort_id: category.category_id}),
count: category.num,
focus: category.category_id === sort
};
});
if (_.isEmpty(result)) {
return {
empty: '您没有收藏商品'
let defaultCategory = {
name: '全部',
url: helpers.urlFormat('/home/favorite'),
count: _.sumBy(categoryList, category => category.num),
focus: sort === 0
};
}
return result;
};
result.all.unshift(defaultCategory);
result.default = result.all.slice(0, 7);
return result;
}
/**
* 降价提醒
*/
const _redutionCount = (uid)=> {
return co(function*() {
let data = yield favoriteApi.redutionCount(uid);
let result = {
count: 0,
phone: '',
url: '/home/favorite/reduction'
};
getGoodsInfo(data, page, limit) {
let result = data.slice((page - 1) * limit, page * limit).map((item) => {
return {
skn: item.product_id,
img: helpers.image(item.image, 100, 100),
name: item.product_name,
url: helpers.getUrlBySkc(item.product_skn),
price: item.sales_price,
priceDown: item.price_down,
buyNow: helpers.getUrlBySkc(item.product_skn),
soldOut: item.storage === 0 ? true : '',
hadNoticed: item.is_subscribe_reduction === 'Y' ? true : '',
activites: {
count: item.promotion_list ? item.promotion_list.length : 0,
list: _.get(item, 'promotion_list', []).map((val) => {
return {
type: val.promotion_type,
name: val.promotion_title
};
})
}
};
});
if (data.data.num) {
result.count = +data.data.num;
result.phone = data.data.mobile;
if (_.isEmpty(result)) {
return {
empty: '您没有收藏商品'
};
}
return result;
})();
};
}
/**
* 降价提醒
*/
_redutionCount(uid) {
let that = this;
return co(function*() {
let data = yield that.redutionCount(uid);
let result = {
count: 0,
phone: '',
url: '/home/favorite/reduction'
};
const favoriteProductListAsync = (uid, page, limit, selectedSort, subscribe, reduction, promotion, query) => {
return co(function*() {
let result = {
sort: {},
reduction: {},
filter: {},
goods: {},
pager: {}
};
if (data.data.num) {
result.count = +data.data.num;
result.phone = data.data.mobile;
}
return result;
})();
}
favoriteProductListAsync(uid, page, limit, selectedSort, subscribe, reduction, promotion, query) {
let that = this;
let product = yield favoriteApi.getFavoriteProductList(uid, 1, 500);
result.sort = _getSortInfo(_.get(product, 'data.category_list'), selectedSort);
result.reduction = yield _redutionCount(uid);
let productList = (function() {
let products = _.get(product, 'data.product_list', []);
if (reduction === 'Y' && promotion === 'Y') {
// 参加活动的降价商品
return products.filter(pro => pro.is_price_down === 'Y' && pro.is_join_promotion === 'Y');
} else if (selectedSort) {
// 商品分类过滤
return products.filter(pro => pro.category_id === selectedSort);
} else if (subscribe === 'Y') {
// 订阅降价通知过滤
return products.filter(pro => pro.is_subscribe_reduction === 'Y');
} else if (reduction === 'Y') {
// 降价商品过滤
return products.filter(pro => pro.is_price_down === 'Y');
} else if (promotion === 'Y') {
// 参加活动商品过滤
return products.filter(pro => pro.is_join_promotion === 'Y');
} else {
return products;
return co(function*() {
let result = {
sort: {},
reduction: {},
filter: {},
goods: {},
pager: {}
};
let product = yield that.getFavoriteProductList(uid, 1, 500);
result.sort = that._getSortInfo(_.get(product, 'data.category_list'), selectedSort);
result.reduction = yield that._redutionCount(uid);
let productList = (function() {
let products = _.get(product, 'data.product_list', []);
if (reduction === 'Y' && promotion === 'Y') {
// 参加活动的降价商品
return products.filter(pro => pro.is_price_down === 'Y' && pro.is_join_promotion === 'Y');
} else if (selectedSort) {
// 商品分类过滤
return products.filter(pro => pro.category_id === selectedSort);
} else if (subscribe === 'Y') {
// 订阅降价通知过滤
return products.filter(pro => pro.is_subscribe_reduction === 'Y');
} else if (reduction === 'Y') {
// 降价商品过滤
return products.filter(pro => pro.is_price_down === 'Y');
} else if (promotion === 'Y') {
// 参加活动商品过滤
return products.filter(pro => pro.is_join_promotion === 'Y');
} else {
return products;
}
}());
result.filter = (function() {
if (reduction === 'N' && promotion === 'N') {
return {
reductionUrl: helpers.urlFormat('/home/favorite', {is_reduction: 'Y'}),
reductionChecked: '',
activityUrl: helpers.urlFormat('/home/favorite', {is_promotion: 'Y'}),
activityChecked: ''
};
} else if (reduction === 'N' && promotion === 'Y') {
return {
reductionUrl: helpers.urlFormat('/home/favorite', {is_reduction: 'Y', is_promotion: 'Y'}),
reductionChecked: '',
activityUrl: helpers.urlFormat('/home/favorite'),
activityChecked: ''
};
} else if (reduction === 'Y' && promotion === 'N') {
return {
reductionUrl: helpers.urlFormat('/home/favorite'),
reductionChecked: '',
activityUrl: helpers.urlFormat('/home/favorite', {is_reduction: 'Y', is_promotion: 'Y'}),
activityChecked: ''
};
} else {
return {
reductionUrl: helpers.urlFormat('/home/favorite', {is_promotion: 'Y'}),
reductionChecked: '',
activityUrl: helpers.urlFormat('/home/favorite', {is_reduction: 'Y'}),
activityChecked: ''
};
}
}());
let total = productList.length;
let pageTotal = Math.ceil(total / limit);
page = page > pageTotal ? pageTotal : page;
result.goods = that.getGoodsInfo(productList, page, limit);
result.pager = pager(total, Object.assign(query, {hasCheckAll: true}));
return result;
})();
}
favoriteBrandListAsync(uid, page, limit, type) {
let that = this;
return co(function*() {
let result = {
brands: {
empty: '您没有收藏品牌',
pager: {}
}
};
let brand = yield that.favoriteBrandData(uid, page, limit);
if (!brand.data || !brand.data.page_total) {
return result;
}
}());
result.filter = (function() {
if (reduction === 'N' && promotion === 'N') {
return {
reductionUrl: helpers.urlFormat('/home/favorite', {is_reduction: 'Y'}),
reductionChecked: '',
activityUrl: helpers.urlFormat('/home/favorite', {is_promotion: 'Y'}),
activityChecked: ''
};
} else if (reduction === 'N' && promotion === 'Y') {
return {
reductionUrl: helpers.urlFormat('/home/favorite', {is_reduction: 'Y', is_promotion: 'Y'}),
reductionChecked: '',
activityUrl: helpers.urlFormat('/home/favorite'),
activityChecked: ''
};
} else if (reduction === 'Y' && promotion === 'N') {
return {
reductionUrl: helpers.urlFormat('/home/favorite'),
reductionChecked: '',
activityUrl: helpers.urlFormat('/home/favorite', {is_reduction: 'Y', is_promotion: 'Y'}),
activityChecked: ''
};
} else {
if (!brand.data.brand_list) {
return result;
}
result.brands = _.get(brand, 'data.brand_list', []).map((item) => {
return {
reductionUrl: helpers.urlFormat('/home/favorite', {is_promotion: 'Y'}),
reductionChecked: '',
activityUrl: helpers.urlFormat('/home/favorite', {is_reduction: 'Y'}),
activityChecked: ''
id: item.brand_id,
brandOrShopType: item.brandOrShopType || '',
shop_id: item.shop_id || '',
img: helpers.image(item.brand_ico, 100, 100),
url: helpers.urlFormat('', {shopId: item.shop_id || ''}, item.brand_domain),
name: item.brand_name,
naCount: item.new_product_num,
colCount: item.brand_favorite_num
};
}
}());
});
let total = productList.length;
let pageTotal = Math.ceil(total / limit);
let total = brand.data.total || 0;
page = page > pageTotal ? pageTotal : page;
page = brand.data.page || 0;
result.pager = pager(total, {page, limit, type, hasCheckAll: true});
return result;
})();
}
result.goods = getGoodsInfo(productList, page, limit);
result.pager = pager(total, Object.assign(query, {hasCheckAll: true}));
favoriteArticleListAsync(uid, udid, page, limit, type) {
let that = this;
return result;
})();
};
return co(function*() {
let result = {};
const favoriteBrandListAsync = (uid, page, limit, type)=> {
return co(function*() {
let result = {
brands: {
empty: '您没有收藏品牌',
pager: {}
let articles = yield that.favoriteArticleData(uid, udid, page, limit);
result.articles = _.get(articles, 'data.data', []).map((item) => {
return {
id: item.id,
name: item.title,
img: helpers.image(item.src, 146, 96),
desc: item.intro,
url: helpers.urlFormat(`/guang/${item.id}.html`, null)
};
});
let total = articles.data.total || 0;
result.pager = pager(total, {page, limit, type, hasCheckAll: true});
if (_.isEmpty(result.articles)) {
result.articles = {
empty: '你尚未收藏任何文章!'
};
}
};
let brand = yield favoriteApi.favoriteBrandData(uid, page, limit);
if (!brand.data || !brand.data.page_total) {
return result;
}
})();
}
if (!brand.data.brand_list) {
return result;
}
newProductAsync(uid, page, limit, id) {
let that = this;
result.brands = _.get(brand, 'data.brand_list', []).map((item) => {
return {
id: item.brand_id,
brandOrShopType: item.brandOrShopType || '',
shop_id: item.shop_id || '',
img: helpers.image(item.brand_ico, 100, 100),
url: helpers.urlFormat('', {shopId: item.shop_id || ''}, item.brand_domain),
name: item.brand_name,
naCount: item.new_product_num,
colCount: item.brand_favorite_num
};
});
return co(function * () {
let products = yield that.favoriteBrandData(uid, page, limit);
let total = brand.data.total || 0;
return _.get(products, 'data.brand_list', []).reduce((total, cur) => {
if (id !== cur.brand_id) {
return total;
}
page = brand.data.page || 0;
result.pager = pager(total, {page, limit, type, hasCheckAll: true});
return result;
})();
};
if (cur.new_product_num === 0) {
return total;
}
const favoriteArticleListAsync = (uid, udid, page, limit, type)=> {
return co(function*() {
let result = {};
total = _.concat(total, _.take(_.get(cur, 'new_product', []), 20).map((pro) => {
return {
img: pro.default_images,
url: helpers.getUrlBySkc(pro.product_skn),
name: pro.product_name,
salePrice: pro.sales_price === pro.market_price ? '' : pro.sales_price,
marketPrice: pro.market_price
};
}));
return total;
}, []);
})();
}
let articles = yield favoriteApi.favoriteArticleData(uid, udid, page, limit);
reductionAsync(uid, page, limit) {
let result = {};
result.articles = _.get(articles, 'data.data', []).map((item) => {
result.tabs = this.getFavoriteTabs('product');
return this.favoriteProductListAsync(uid, page, limit, 0, 'Y').then((products) => {
result.goods = products.goods;
result.reductionUrl = helpers.urlFormat('/home/fovorite');
return {
id: item.id,
name: item.title,
img: helpers.image(item.src, 146, 96),
desc: item.intro,
url: helpers.urlFormat(`/guang/${item.id}.html`, null)
meFavoritePage: true,
meFavorite: result
};
});
let total = articles.data.total || 0;
}
result.pager = pager(total, {page, limit, type, hasCheckAll: true});
enableNoticeAsync(uid, mobile, id) {
let that = this;
if (_.isEmpty(result.articles)) {
result.articles = {
empty: '你尚未收藏任何文章!'
return co(function *() {
let result = {
code: 400,
message: '订阅失败'
};
}
return result;
})();
};
if (!uid || !mobile || !id) {
return result;
}
const newProductAsync = (uid, page, limit, id) => {
return co(function * () {
let products = yield favoriteApi.favoriteBrandData(uid, page, limit);
let data = yield that.redutionAdd(uid, mobile, id);
return _.get(products, 'data.brand_list', []).reduce((total, cur) => {
if (id !== cur.brand_id) {
return total;
if (data.code === 200) {
result.code = 200;
return data;
}
if (cur.new_product_num === 0) {
return total;
if (data.code === 500) {
result.code = 500;
switch (data.message) {
case 'count must be lt 5':
result.message = '您的订阅数已经到达上限';
break;
case 'mobile must bu not null':
result.message = '请填写手机号';
break;
default:
result.message = '订阅失败';
break;
}
}
total = _.concat(total, _.take(_.get(cur, 'new_product', []), 20).map((pro) => {
return result;
})();
}
disableNoticeAsync(uid, id) {
let that = this;
return co(function * () {
if (!uid || !id) {
return {
img: pro.default_images,
url: helpers.getUrlBySkc(pro.product_skn),
name: pro.product_name,
salePrice: pro.sales_price === pro.market_price ? '' : pro.sales_price,
marketPrice: pro.market_price
code: 400,
message: '取消失败'
};
}));
}
return total;
}, []);
})();
};
return yield that.redutionCancel(uid, id);
})();
}
const reductionAsync = (uid, page, limit) =>{
let result = {};
/**
* ids 是 group,品牌删除
*/
cancelBrandAsync(uid, ids, group) {
let that = this;
result.tabs = getFavoriteTabs('product');
return favoriteProductListAsync(uid, page, limit, 0, 'Y').then((products) => {
result.goods = products.goods;
result.reductionUrl = helpers.urlFormat('/home/fovorite');
return {
meFavoritePage: true,
meFavorite: result
};
});
return co(function *() {
let result;
};
if (group.bid) {
result = yield that._cancel('brand', uid, group.bid);
}
const enableNoticeAsync = (uid, mobile, id) => {
return co(function *() {
let result = {
code: 400,
message: '订阅失败'
};
if (group.sid) {
result = yield that._cancel('shop', uid, group.sid);
}
if (!group) {
result = yield that._cancel('brand', uid, ids);
}
console.log(result);
if (!uid || !mobile || !id) {
return result;
})();
}
/**
* ids 可能是 group
*/
cancelAsync(uid, ids, group, type) {
if (type === 'brand') {
return this.cancelBrandAsync(uid, ids, group);
} else if (type === 'article') {
return this.cancelArticle(uid, ids);
}
let data = yield favoriteApi.redutionAdd(uid, mobile, id);
return this._cancel(type, uid, ids);
}
if (data.code === 200) {
result.code = 200;
return data;
}
if (data.code === 500) {
result.code = 500;
switch (data.message) {
case 'count must be lt 5':
result.message = '您的订阅数已经到达上限';
break;
case 'mobile must bu not null':
result.message = '请填写手机号';
break;
default:
result.message = '订阅失败';
break;
}
}
return result;
})();
};
/** ***data api below*****/
const disableNoticeAsync = (uid, id) => {
return co(function * () {
if (!uid || !id) {
return {
code: 400,
message: '取消失败'
};
}
/**
* 根据uid和商品的id查询是否被用户收藏
* @param int $uid
* @param int $productId
* @return boolean 收藏 true 未收藏 false
*/
getUidProductFav(uid, productId) {
let data = {
method: 'web.favorite.isFavorite',
id: productId,
uid: uid,
type: 'product'
};
return yield favoriteApi.redutionCancel(uid, id);
})();
};
return this.get({data: data});
}
/**
* ids 是 group,品牌删除
*/
const cancelBrandAsync = co(function * (uid, ids, group) {
favoriteBrandData(uid, page, limit) {
return this.get({data: {
method: 'app.favorite.brand',
uid: uid,
page: page || 1,
limit: limit || 10
}});
}
let result;
getFavoriteProductList(uid, page, limit) {
let data = {
method: 'web.favorite.product',
uid: uid,
page: 0,
limit: limit || 10
};
if (group.bid) {
result = yield favoriteApi.cancel.brand(uid, group.bid);
return this.get({data: data});
}
if (group.sid) {
result = yield favoriteApi.cancel.shop(uid, group.sid);
redutionAdd(uid, mobile, pid) {
return this.get({data: {
method: 'web.redution.add',
uid: uid,
mobile: mobile,
productId: pid
}});
}
if (!group) {
result = yield favoriteApi.cancel.brand(uid, ids);
redutionCount(uid) {
return this.get({data: {
method: 'web.redution.count',
uid: uid
}});
}
return result;
});
_cancel(type, uid, ids) {
return this.get({data: {
method: 'web.favorite.cancel',
favIds: ids,
uid: uid,
type: type
}});
}
/**
* ids 可能是 group
*/
const cancelAsync = (uid, ids, group, type) => {
if (type === 'brand') {
return cancelBrandAsync(uid, ids, group);
redutionCancel(uid, pid) {
return this.get({data: {
method: 'web.redution.cancel',
uid: uid,
productIds: pid
}});
}
return favoriteApi.cancel[type](uid, ids);
};
favoriteArticleData(uid, udid, page, limit) {
let data = {
uid: uid,
udid: udid,
page: page,
limit: limit
};
return this.get({
url: URL_ARTICLE_FAVORITE + 'getUserFavArticleList',
data: data,
api: global.yoho.ServiceAPI
});
}
cancelArticle(uid, id) {
return this.get({
url: URL_ARTICLE_FAVORITE + 'cancelFavorite',
data: {
uid: uid,
article_id: id
},
api: global.yoho.ServiceAPI
});
}
module.exports = {
getFavoriteTabs,
favoriteBrandListAsync,
favoriteProductListAsync,
favoriteArticleListAsync,
newProductAsync,
reductionAsync,
enableNoticeAsync,
disableNoticeAsync,
cancelBrandAsync,
cancelAsync
};
... ...