search.js 9.13 KB
/**
 * search model
 * @author: wsl<shuiling.wang@yoho.cn>
 * @date: 2016/07/21
 */
'use strict';
const utils = '../../../utils';
const productProcess = require(`${utils}/product-process`);
const searchProcess = require(`${utils}/search-process`);
const _ = require('lodash');
const logger = global.yoho.logger;
const api = global.yoho.API;
const camelCase = global.yoho.camelCase;
const cache = require('memory-cache');


/**
 * 封面图
 * @type {{boys: string, gilrs: string}}
 */
const _coverChannel = {
    boys: '1,3',
    gilrs: '2,3'
};

/**
 * 品牌名称处理
 * @param  {[object]} list
 * @return {[object]}
 */
const _processBrandNames = (list) => {
    const formatData = [];
    const brandDomainMap = {}, brandNameMap = {};
    const ttl = 60000; // 默认缓存一分钟
    let brandDomain = '';
    let brandName = '';

    list = list || [];

    _.forEach(list, (item) => {
        _.forEach(item, (obj) => {
            brandDomain = obj.brand_domain && obj.brand_domain.toLowerCase();
            brandName = obj.brand_name && obj.brand_name.toLowerCase();

            if (brandDomain && brandName) {
                formatData.push({
                    brandDomain: brandDomain,
                    brandName: brandName
                });

                brandDomainMap[brandDomain] = brandDomain;
                brandNameMap[brandName] = brandDomain;
            }
        });
    });

    cache.put('brandDomainMap', brandDomainMap, ttl);
    cache.put('brandNameMap', brandNameMap, ttl);

    return formatData;
};

/**
 * 品牌名称处理
 * @param  {[object]} list
 * @return {[object]}
 */
const _processClassNames = (list) => {
    const formatData = {
        first: {},
        second: {}
    };

    list = list || [];

    _.forEach(list, (item) => {
        _.forEach(item, (obj) => {
            formatData.first[obj.category_id] = obj.category_name;

            if (obj.sub) {
                _.forEach(obj.sub, (sub) => {
                    formatData.second[sub.category_id] = sub.category_name;
                });
            }

        });
    });

    return formatData;
};

/**
 * 商品搜索接口请求
 * @param  {[object]} params
 * @return {[array]}
 */
const _searchGoods = (params) => {
    let method = 'app.search.li';

    /* tar add 160823 店铺销售类目 */
    if (params.filter_poolId) {
        method = 'app.search.pool';
        Object.assign(params, {
            productPool: params.filter_poolId
        });
        delete params.filter_poolId;
    }

    if (params.shop_id && !params.productPool) {
        method = 'app.search.li';
    } else if (params.brand && !params.productPool) {
        method = 'app.search.brand';
    }

    // 排除基本筛选项默认值为0的对象
    for (let str in params) {
        if (str !== 'order' && params[str] === '0' || params[str] === null) {
            delete params[str];
        }
    }

    if (params.channel) {
        params.yh_channel = searchProcess.getChannelType(params.channel);
        delete params.channel;
    }

    if (params.query) {
        params.query = params.query.replace(/\+/g, ',');
    }

    params = _.assign({
        limit: '60',
        status: 1,
        sales: 'Y',
        stocknumber: 1,
        attribute_not: 2
    }, params);

    if (params.type === 'default') {
        // 筛选 默认 不传order
        delete params.order;
    } else if (params.order) {
        params.order = searchProcess.getTypeCont(params.type || '', params.order);
    } else {
        params.order = 's_t_asc';
    }

    // 学生返币查询
    if (params.coin) {
        method = 'app.student.rebate';
        delete params.filter_poolId;

        if (params.type === 'newest') {
            delete params.order;
            delete params.type;
        }
    }

    if (params.isblknew) {
        method = 'app.search.newProduct';
        params.app_type = 1;
    }
    if (params.promotion_id) {
        method = 'app.search.promotion';
    }

    if (params.students) {
        method = 'app.student.discount';
    }

    return api.get('', _.assign({
        method: method
    }, params), {
        cache: true
    });
};

/**
 * 获取商品数据
 */
const getSearchData = (params) => {
    return _searchGoods(params).then((result) => {
        if (result && result.code === 200) {
            let newList = {};

            newList.list = productProcess.processProductList(result.data.product_list || [], {
                isApp: params.isApp || (params.appVersion && params.appVersion !== 'false'),
                gender: _coverChannel[params.coverChannel]
            });

            if (parseInt(params.page, 10) === 1) {
                newList.total = result.data.total;
            }

            return newList;
        } else {
            logger.error('get product search api return code is not 200');
            return [];
        }
    });
};

/**
 * 获取筛选数据
 * @param  {[object]} params
 * @return {[array]}
 */
const getFilterData = (params) => {
    return _searchGoods(params).then((result) => {
        if (result && result.code === 200) {
            return productProcess.processFilter(result.data.filter || []);
        } else {
            logger.error('get filter data api return code is not 200');
            return [];
        }
    });
};

/**
 * 获取筛选数据
 * @param  {[object]} params
 * @return {[array]}
 */
const getFilterSearchData = (params) => {
    return _searchGoods(params).then((result) => {
        if (result && result.code === 200) {
            return result.data;
        } else {
            logger.error('get filter data api return code is not 200');
            return [];
        }
    });
};

/**
 * 获取所有的品类名称
 **/
const getClassNames = () => {
    return api.get('', {
        method: 'app.sort.get'
    }, {
        cache: true
    }).then((result) => {
        if (result && result.code === 200) {
            return _processClassNames(result.data);
        } else {
            logger.error('get category name api return code is not 200');
            return {};
        }
    });
};

/**
 * 获取所有的品牌名称
 **/
const getAllBrandNames = () => {
    return api.get('', {
        method: 'app.brand.brandlist'
    }, {
        cache: true
    }).then((result) => {
        if (result && result.code === 200) {
            return _processBrandNames(result.data.brands);
        } else {
            logger.error('get brand all name data api return code is not 200');
            return {};
        }
    });
};

/**
 * 搜索主页
 */
const getSearchIndex = (uid) => {
    return api.get('', {
        method: 'app.search.getTerms',
        uid: uid
    }, {
        cache: true
    }).then((result) => {
        if (result && result.code === 200) {
            if (result.data.hotTerms && result.data.hotTerms.length > 10) {
                result.data.hotTerms = result.data.hotTerms.slice(0, 10);
            }

            if (result.data.guessTerms && result.data.guessTerms.length > 10) {
                result.data.guessTerms = result.data.guessTerms.slice(0, 10);
            }

            return result.data;
        } else {
            logger.error('Hot Search return code is not 200');
            return {};
        }
    });
};

/**
 * 获取联想词
 * @param params
 * @returns {*|Promise.<TResult>}
 */
const getFuzzyDatas = (params) => {
    return api.get('', {
        method: 'app.search.fuzzy',
        keyword: params
    }, {
        cache: true
    }).then((result) => {
        if (result && result.code === 200) {
            return result.data;
        } else {
            logger.error('FuzzyDatas return code is not 200');
            return {};
        }
    });
};

/**
 * 查询关键词是否正参加活动
 * @param params
 * @returns {*|Promise.<TResult>}
 */
const searchKeyActivity = (params) => {
    return api.get('', {
        method: 'app.search.word',
        query: params
    }, {
        cache: true,
        code: 200
    }).then(result => {
        if (result && result.data) {
            return result.data;
        } else {
            return {};
        }
    });
};

/**
 * 检查字符串是否是品牌域/品牌名称
 *
 * @param query
 * @returns {*|Promise.<TResult>}
 */
const getBrandDomain = (query) => {
    let brandDomainMap = cache.get('brandDomainMap');
    let brandNameMap = cache.get('brandNameMap');

    const fn = () => {
        brandDomainMap = cache.get('brandDomainMap');
        brandNameMap = cache.get('brandNameMap');

        let ret = null;

        if (!_.isEmpty(brandDomainMap) && brandDomainMap.hasOwnProperty(query)) {
            ret = brandDomainMap[query] || null;
        }

        if (!_.isEmpty(brandNameMap) && brandNameMap.hasOwnProperty(query)) {
            ret = brandNameMap[query] || null;
        }

        return Promise.resolve(ret);
    };

    if (brandDomainMap && brandNameMap) {
        logger.debug('Using cached brand data.');
        return fn();
    } else {
        logger.debug('Reloading brand data...');
        return getAllBrandNames().then(fn);
    }
};

module.exports = {
    getSearchData,
    getFilterData,
    getFilterSearchData,
    getAllBrandNames,
    getClassNames,
    getSearchIndex,
    getFuzzyDatas,
    searchKeyActivity,
    getBrandDomain
};