search.js 10.8 KB
/**
 * search controller
 * @author: wsl<shuiling.wang@yoho.cn>
 * @date: 2016/7/21
 */

'use strict';
const utils = '../../../utils';
const mRoot = '../models';
const headerModel = require('../../../doraemon/models/header');
const searchModel = require(`${mRoot}/search`);
const _ = require('lodash');
const helpers = global.yoho.helpers;
const stringProcess = require(`${utils}/string-process`);
const searchProcess = require(`${utils}/search-process`);
const productProcess = require(`${utils}/product-process`);
const listParamsProcess = require(`${utils}/list-params-process`);
const co = require('bluebird').coroutine;

/**
 * 搜索主页
 */
exports.index = (req, res, next) => {
    let title = '搜索',
        uid = req.user.uid || 0;

    ((render) => {
        if (_.get(req, 'app.locals.wap.search.removeHotSearch', false)) {
            render([]);
        } else {

            req.ctx(searchModel).getSearchIndex({
                gender: req.yoho.channel || 'boys',
                uid: uid
            }).then((result) => {
                render(result);
            }).catch(next);
        }

    })((result) => {
        let appParams = _.assign({keyword: req.query.query}, req.query);

        // 唤起 APP 的路径
        res.locals.appPath = `yohobuy://yohobuy.com/goapp?openby:yohobuy={"action":"go.searchlist","params":${JSON.stringify(appParams)}}`;

        res.render('search/index', Object.assign({
            module: 'product',
            page: 'search-index',
            pageHeader: headerModel.setNav({
                navTitle: title
            }),
            pageFooter: true,
            width750: true,
            search: {
                defaultTerms: (result && result.defaultTerms && result.defaultTerms.length) ?
                    result.defaultTerms[0].content : '',
                url: helpers.urlFormat('/', null, 'search'),
                hotTerms: result.hotTerms,
                wantTerms: result.guessTerms
            }

        }, searchProcess.getListSeoData()));
    });
};

/**
 * 搜索落地页
 */
exports.list = (req, res, next) => {
    let params = Object.assign({
        isSearch: true, // 搜索列表将最新改成默认的标识
        cartUrl: helpers.urlFormat('/cart/index/index')
    }, req.query, {query: (req.query.query || '').toString()});
    let title = '';
    let isQueryFirstClass = false; // 标识用户搜的是不是一级品类
    let isQuerySecondClass = false; // 标识用户搜的是不是二级品类
    let uid = req.user.uid;

    if (params.shop_id) {
        params.shopId = params.shop_id;
    }

    params.isApp = req.yoho.isApp;
    params.physical_channel = req.yoho.channel && searchProcess.getChannelType(req.yoho.channel);

    // 唤起 APP 的路径
    res.locals.appPath = `yohobuy://yohobuy.com/goapp?openby:yohobuy={"action":"go.list","params":${JSON.stringify(params)}}`;

    return req.ctx(searchModel).searchKeyActivity(params.query || '').then(activityResult => {
        let activity = _.get(activityResult, 'urlobj.appUrl', '');

        if (activity) {
            return res.redirect(activity);
        } else {
            // 获取第一页数据做服务端渲染
            let initialData = _.assign({
                type: 'default',
                order: '0',
                page: 1,
                limit: 24
            }, params);

            if (uid) {
                initialData.uid = uid;
            }

            /* 判断是不是品牌, 是品牌跳到品牌列表页(显示搜索框),判断是不是品类, 是品类加导航标题(不显示搜索框) */
            return Promise.all([
                req.ctx(searchModel).getBrandDomain(params.query.toLowerCase()),
                req.ctx(searchModel).getClassNames(),
                req.ctx(searchModel).getSearchData(initialData)
            ]).then(result => {

                // 推荐词条件判断 redmine: 18567
                if (result[2].suggestion && result[2].suggestion.isNeedSuggestion &&
                    result[2].suggestion.termsSuggestion.length) {
                    params.newquery = result[2].suggestion.termsSuggestion[0].name;
                }

                if (result[2] && result[2].brandWay) {
                    params.brandWay = result[2].brandWay;
                }

                if (params.query) {
                    // 品类名称为空时跳出
                    if (!result[1]) {
                        return;
                    }

                    _.forEach(result[1].first, (obj) => {
                        // 精确查一级品类
                        if (obj === params.query) {
                            isQueryFirstClass = true;
                            return false;
                        }
                    });

                    _.forEach(result[1].second, (obj) => {
                        // 精确查二级品类
                        if (obj === params.query) {
                            isQuerySecondClass = true;
                            return false;
                        }
                    });
                } else {
                    params.query = '';
                }

                // 搜索是一级品类
                if (isQueryFirstClass) {
                    title = '全部' + params.query;
                } else if (isQuerySecondClass) { // 搜索是二级品类
                    title = params.query;
                } else { // 搜索其它内容
                    if (params.query || params.form) {
                        params.search = {
                            default: params.query === '' ? false : params.query,
                            url: helpers.urlFormat('/', null, 'search')
                        };
                    }
                    title = '搜索';
                }

                title = params.title ? params.title : title;

                res.render('search/list', {
                    _noLazy: true,
                    module: 'product',
                    page: 'search-list',
                    localCss: true,
                    pageHeader: headerModel.setNav({
                        navTitle: title
                    }),
                    title: title,
                    goodList: params,
                    firstPageGoods: result[2] || [],
                    suggestion: result[2].suggestion || [],
                    pageFooter: true,
                    shopId: params.shop_id || ''
                });
            }).catch(next);
        }
    }).catch(next);
};

/**
 * 联动搜索
 */
exports.fuzzyDatas = (req, res, next) => {
    let params = req.query.keyword;

    req.ctx(searchModel).getFuzzyDatas(params).then((result) => {
        res.json(result);
    }).catch(next);
};


/**
 * ajax 商品数据请求
 */
exports.search = (req, res, next) => {
    let params = Object.assign({}, req.query);
    let uid = req.user.uid || 0;

    if (uid) {
        params.uid = uid;
    }

    if (params.query) {
        params.query = stringProcess.decodeURIComponent(params.query);
    }

    params.isApp = req.yoho.isApp;
    params.limit = 24;
    params.physical_channel = req.yoho.channel && searchProcess.getChannelType(req.yoho.channel);

    req.ctx(searchModel).getSearchData(params).then((result) => {

        if (result.list && result.list.length > 0) {
            res.render('search/page', {
                layout: false,
                new: result.list,
                suggestion: result.suggestion || [],
                total: result.total,
                _noLazy: params.noLazy || false
            });
        } else {
            res.json(result);
        }
    }).catch(next);
};

/**
 * 筛选
 */
exports.filter = (req, res, next) => {
    let allowOrigin = _.get(req, 'headers.origin', null) ?
        req.headers.origin : req.protocol + '://' + req.headers.host;

    res.setHeader('Access-Control-Allow-Origin', allowOrigin);
    res.setHeader('Access-Control-Allow-Credentials', 'true');

    let params = {};
    let currentUrlParams = {}; // 页面链接伪静态固定参数

    if (req.query.isShopList === 'Y') {
        let shopId;
        let pathSplitArr = _.compact(_.split(req.query.currentUrl, '/'));
        let pathParams = _.last(pathSplitArr);

        if (pathSplitArr.length === 2) {
            shopId = _.last(_.split(pathParams, '-'));
        } else {
            currentUrlParams = listParamsProcess.getParams(pathParams);

            let shopInfoPath = _.replace(req.query.currentUrl, `/${pathParams}`, '');

            shopId = _.last(_.split(shopInfoPath, '-'));
        }

        _.assign(req.query, currentUrlParams, {shop_id: shopId});
    } else {
        currentUrlParams = listParamsProcess.getParams(_.last(_.split(req.query.currentUrl, '/')));
    }

    delete req.query.currentUrl;
    delete req.query.page;

    _.assign(params, currentUrlParams, req.query);

    let uid = req.user.uid || 0;

    if (uid) {
        params.uid = uid;
    }

    req.ctx(searchModel).getFilterData(params).then((result) => {
        res.render('search/filter', {
            layout: false,
            params: params,
            filter: result
        });
    }).catch(next);
};

/**
 * 搜索品牌下的商品
 */
exports.searchBrandGoods = (req, res, next) => {
    let allowOrigin = _.get(req, 'headers.origin', null) ?
        req.headers.origin : req.protocol + '://' + req.headers.host;

    res.setHeader('Access-Control-Allow-Origin', allowOrigin);
    res.setHeader('Access-Control-Allow-Credentials', 'true');

    co(function* () {
        let goodListApi = yield req.ctx(searchModel).getBrandGoods(req.query);

        let goodsData = _.get(goodListApi, 'data', []);
        let goodsList = productProcess.processProductList(_.get(goodListApi, 'data.product_list', []));

        if (goodsList) {
            res.render('search/goods-list-ajax', {
                layout: false,
                goodsList: goodsList,
                _noLazy: req.query.noLazy || false
            });
        } else {
            res.json(goodsData);
        }
    })().catch(next);
};

/**
 * 搜索店铺下的商品
 */
exports.searchShopGoods = (req, res, next) => {
    let allowOrigin = _.get(req, 'headers.origin', null) ?
        req.headers.origin : req.protocol + '://' + req.headers.host;

    res.setHeader('Access-Control-Allow-Origin', allowOrigin);
    res.setHeader('Access-Control-Allow-Credentials', 'true');

    co(function* () {
        let goodListApi = yield req.ctx(searchModel).getShopGoods(req.query);

        let goodsData = _.get(goodListApi, 'data', []);
        let goodsList = productProcess.processProductList(_.get(goodListApi, 'data.product_list', []));

        if (goodsList) {
            res.render('search/goods-list-ajax', {
                layout: false,
                goodsList: goodsList,
                _noLazy: req.query.noLazy || false
            });
        } else {
            res.json(goodsData);
        }
    })().catch(next);
};