list-service.js 3.88 KB
const _ = require('lodash');
const ListModel = require('./list-api');
const logger = global.yoho.logger;

const {CHANNELS, MAX_URL} = require('./vars');

const listHandle = require('./list-handler');
const SearchModel = require('./search-service');
const {fullParamToMinPath} = require('../utils/parameter');

function tplUrl(path) {
    return `${path}`;
}

function indexUrl(type, page) {
    return `/sitemap_${type}/list_${page}.xml`;
}

const DELAY = 10;

module.exports = class extends global.yoho.BaseModel {
    constructor(ctx) {
        super(ctx);

        this.listModel = new ListModel(ctx);
        this.searchModel = new SearchModel(ctx);
    }

    async _getList() {
        const list = await Promise.map(Object.values(CHANNELS), async (channel) => {
            return this._getChannel(channel);
        }, {concurrency: 1});

        let result = [];

        list.forEach(({gender, color, style, brand, sort}) => {
            result = _.concat(result, gender, color, style, brand, sort);
        });

        result = _.sortBy(result);
        result = _.sortedUniq(result);
        return result;
    }

    async getUrls(page) {
        const result = await this._getList();
        const chunks = _.chunk(result, MAX_URL);

        if (page <= 0) {
            page = 1;
        }

        if (page > chunks.length) {
            page = chunks.length;
        }

        return chunks[page - 1];
    }

    async getIndex(type) {
        const result = await this._getList();
        const chunks = _.chunk(result, MAX_URL);

        return chunks.map((v, i) => indexUrl(type, i + 1));
    }

    async _getChannel(channel) {
        const sortResult = await this.listModel.getSortList(channel);

        logger.info('get sort from ' + channel);

        const {allSort: {list}} = listHandle.handleSortData(sortResult.data, {}, {}, '/list');

        const result = {
            gender: [],
            color: [],
            style: [],
            brand: [],
            sort: []
        };

        await Promise.map(list, async ({childList}) => {
            await Promise.delay(DELAY);
            await Promise.map(childList, async ({categoryId, href}) => {
                await Promise.delay(DELAY);
                try {
                    const params = {category_id: categoryId};
                    const products = await this.listModel.getProductList(params);

                    logger.info('get products from cid:' + categoryId);

                    const {gender, color, seniorChose} = listHandle.handleFilterData(products.data, params, '/list');

                    result.sort.push(tplUrl(href));

                    (gender || []).reduce((total, cur) => {
                        total.push(tplUrl(cur.href));
                        return total;
                    }, result.gender);

                    (color || []).reduce((total, cur) => {
                        total.push(tplUrl(cur.href));
                        return total;
                    }, result.color);

                    if (_.get(seniorChose, '[0].attr', '') === 'style') {
                        _.get(seniorChose[0], 'sub', []).reduce((total, cur) => {
                            total.push(tplUrl(cur.href));
                            return total;
                        }, result.style);
                    }

                    const brands = await this.searchModel.getBrands(params);

                    logger.info('get brands from cid:' + categoryId);

                    (brands || []).reduce((total, b) => {
                        const brandUrl = fullParamToMinPath('/list', Object.assign(params, {brand: b.id}));

                        total.push(tplUrl(brandUrl));
                        return total;
                    }, result.brand);
                } catch (e) {
                    logger.error(e);
                }
            }, {concurrency: 1});
        }, {concurrency: 1});

        return result;
    }
};