index-service.js 10.8 KB
'use strict';

const Promise = require('bluebird');
const co = Promise.coroutine;
const _ = require('lodash');
const Fn = require('lodash/fp');

const helpers = global.yoho.helpers;

const OrderService = require('./orders-service');
const IndexApi = require('./index-api');
const UserApi = require('./user-api');
const MsgApi = require('./message');
const headerModel = require('../../../doraemon/models/header');
const cache = global.yoho.cache;
const cachePreKey = 'HOME_INDEX_';
const defaultAvatar = '//img10.static.yhbimg.com/headimg/' +
    '2013/11/28/09/01cae078abe5fe320c88cdf4c220212688.gif?imageView/2/w/100/h/100';


const numbersKey = {
    pending: 'pengding',
    unread: 'unread',
    needComment: 'needComment'
};

const CHANNEL_NUM = {
    boys: 1,
    girls: 2,
    kids: 3,
    lifestyle: 4
};

const IMG_DOMAIN = {
    '01': [
        'img10.static.yhbimg.com',
        'img11.static.yhbimg.com'
    ],
    '02': [
        'img12.static.yhbimg.com',
        'img13.static.yhbimg.com'
    ]
};


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

    /**
     * 处理品牌的图片
     */
    _handleBrandLogo(url) {
        if (_.startsWith(url, 'http://') || !url) {
            return url;
        }

        let node = url.substr(15, 2);

        return `//${IMG_DOMAIN[node][(url.length % 2)]}/brandLogo${url}`;
    }

    _channelNum(channel) {
        return CHANNEL_NUM[channel] || CHANNEL_NUM.boys;
    }

    /**
     * 处理品牌
     */
    _handleBrand(brands, needNum) {
        let that = this;

        const handle = Fn.pipe(Fn.filter({is_hot: 'Y'}), Fn.take(needNum), Fn.map((brand) => ({
            href: helpers.urlFormat('', null, brand.brand_domain),
            logo: that._handleBrandLogo(brand.brand_ico, 'brandLogo'),
            name: brand.brand_name
        })));

        return handle(brands);
    }

    /**
     * 处理商品
     */
    _handleProduct(products) {
        return products.map(product => {
            let img = helpers.image(_.get(product, 'default_images', ''), 100, 100);

            if (img.indexOf('imageView') !== -1) {
                img = img.split('imageView', 1) +
                    'imageMogr2/thumbnail/100x100/extent/100x100/background/d2hpdGU=/position/center/quality/90';
            }

            return {
                href: helpers.getUrlBySkc(product.product_skn),
                thumb: img,
                name: product.product_name,
                price: product.sales_price,
                productId: product.product_id
            };
        });
    }

    /**
     * 消息数量提示
     */
    _msgNumber(uid, udid) {
        let that = this;

        return co(function * () {
            let result = [
                {href: helpers.urlFormat('/home/orders'), name: '待处理订单', count: 0},
                {href: helpers.urlFormat('/home/message'), name: '未读消息', count: 0},
                {href: helpers.urlFormat('/home/comment'), name: '待评论商品', count: 0}
            ];

            let reqData = yield Promise.props({
                pending: new IndexApi(that.ctx).pendingOrderCount(uid), // 待处理订单
                unread: new IndexApi(that.ctx).unreadMessageCount(uid, udid), // 未读消息
                needComment: new IndexApi(that.ctx).needCommentCount(uid) // 待评论商品
            });

            result[0].count = _.get(reqData, 'pending.data.count', 0);
            result[1].count = _.get(reqData, 'unread.data.inbox_total', 0);
            result[2].count = _.get(reqData, 'needComment.data', 0);

            return result;
        })();
    }

    /**
     * 最新订单
     */
    _recentOrder(uid) {
        let orderServiceModel = new OrderService(this.ctx);

        return orderServiceModel.getOrders(uid, 1, 2, orderServiceModel.ORDER_TYPE.all).then(latestOrder => {
            return {
                more: helpers.urlFormat('/home/orders'),
                orders: latestOrder
            };
        });
    }

    /**
     * 你喜欢的品牌
     */
    _guessYouLikeBrand() {
        const NEED_BRAND_NUM = 6;

        return new IndexApi(this.ctx).guessBrand().then(brand => {
            return this._handleBrand(_.get(brand, 'data', []), NEED_BRAND_NUM);
        });
    }

    /**
     * 新品
     */
    _newProduct() {
        return new IndexApi(this.ctx).newArrival().then(newProduct => {
            return this._handleProduct(_.get(newProduct, 'data.product_list', []));
        });
    }

    /**
     * 为你优选
     */
    _recommend(channelNum, uid, udid) {
        return new IndexApi(this.ctx).recommend(channelNum, uid, udid, '100004', 30).then(resData => {
            return this._handleProduct(_.get(resData, 'data.product_list', []));
        });
    }

    /**
     * 底部banner
     */
    _footerBanner() {
        const CODE = '20110609-152143';

        return new IndexApi(this.ctx).getByNodeContent(CODE, {}, {cache: 86400}).then(banner => {
            return _.get(banner, 'data', '').replace(/http:\/\//g, '//');
        });
    }

    /**
     * 取消订单
     */
    _cancelReason() {
        return new OrderService(this.ctx).closeReason();
    }

    // 个人中心首页 异步获取新品上架数据
    async newArrive() {
        let arriveCaceKey = `${cachePreKey}arrive`;
        let arrive = await cache.get(arriveCaceKey);

        if (!arrive) {
            let arriveOrigin = await new IndexApi(this.ctx).newArrival();

            arrive = this._handleProduct(_.get(arriveOrigin, 'data.product_list', []));
            if (!_.isEmpty(arrive)) {
                cache.set(arriveCaceKey, arrive, 3600);
            }
        } else {
            arrive = JSON.parse(arrive);
        }

        return Promise.resolve({newArrive: arrive});
    }

    // 推荐数据
    async recommend(uid, udid, channelNum) {
        let recommendCaceKey = `${cachePreKey}recommend`;
        let recommend = await cache.get(recommendCaceKey);

        if (!recommend) {
            let recommendOrigin = await new IndexApi(this.ctx).recommend(channelNum, uid, udid, '100004', 30);

            recommend = this._handleProduct(_.get(recommendOrigin, 'data.product_list', []));
            if (!_.isEmpty(recommend)) {
                cache.set(recommendCaceKey, recommend, 3600);
            }
        } else {
            recommend = JSON.parse(recommend);
        }

        return Promise.resolve({recommend: recommend});
    }

    // 个人中心首页 异步获取品牌数据
    async brands() {
        let brandsCaceKey = `${cachePreKey}brands`;
        let brand = await cache.get(brandsCaceKey);

        if (!brand) {
            let brandOrigin = await new IndexApi(this.ctx).guessBrand();

            brand = this._handleBrand(_.get(brandOrigin, 'data', []), 6);
            if (!_.isEmpty(brand)) {
                cache.set(brandsCaceKey, brand, 86400);
            }
        } else {
            brand = JSON.parse(brand);
        }

        return Promise.resolve({brands: brand, more: '/brands'});
    }

    // 个人中心异步查询我的消息和头像
    async newsAvatar(uid) {
        let result = await Promise.props(
            {
                profile: new UserApi(this.ctx).getUserInfo(uid),
                msg: new MsgApi(this.ctx).unreadTotal(uid)
            }
        );
        let avatar = helpers.image(_.get(result, 'profile.data.head_ico', ''), 100, 100) || defaultAvatar;
        let msgCount = _.get(result, 'msg.data.total', 0);

        return Promise.resolve({avatar: avatar, msg: msgCount});
    }

    // 首页顶部数量
    async numbers(uid, udid) {
        let result = {};
        let numbers = await Promise.props({
            pending: new IndexApi(this.ctx).pendingOrderCount(uid), // 待处理订单
            unread: new IndexApi(this.ctx).unreadMessageCount(uid, udid), // 未读消息
            needComment: new IndexApi(this.ctx).needCommentCount(uid) // 待评论商品
        });

        result[numbersKey.pending] = _.get(numbers, 'pending.data.count', 0);
        result[numbersKey.unread] = _.get(numbers, 'unread.data.inbox_total', 0);
        result[numbersKey.needComment] = _.get(numbers, 'needComment.data', 0);

        return Promise.resolve(result);
    }


    // 个人中心首页同步数据
    async indexNew(uid, udid, channel, isStudent) {
        let indexData = await Promise.props({
            header: headerModel.requestHeaderData(channel),
            recentOrder: this._recentOrder(uid),
            footerBanner: this._footerBanner(),
            reason: this._cancelReason()
        });

        return Object.assign(
            {
                content: {
                    content: {
                        messages: [
                            {href: helpers.urlFormat('/home/orders'), name: '待处理订单', id: numbersKey.pending, count: 0},
                            {href: helpers.urlFormat('/home/message'), name: '未读消息', id: numbersKey.unread, count: 0},
                            {href: helpers.urlFormat('/home/comment'), name: '待评论商品',
                                id: numbersKey.needComment, count: 0}
                        ],
                        certifiedName: +isStudent ? '学生身份已验证' : '身份验证',
                        certifiedUrl: helpers.urlFormat('/product/students/'),
                        latestOrders: Object.assign(indexData.recentOrder, {cancelReason: indexData.reason})
                    },
                    banner: indexData.footerBanner
                }
            },
            {
                header: indexData.header
            }
        );
    }

    index(uid, udid, channel, isStudent) {
        let that = this;

        return co(function * () {
            let reqData = yield Promise.props({
                msgNumber: that._msgNumber(uid, udid),
                recentOrder: that._recentOrder(uid),
                guessBrand: that._guessYouLikeBrand(),
                newProduct: that._newProduct(),
                recommendProduct: that._recommend(that._channelNum(channel), uid, udid),
                footerBanner: that._footerBanner(),
                reason: that._cancelReason()
            });

            return {
                content: {
                    certifiedName: +isStudent ? '学生身份已验证' : '身份验证',
                    certifiedUrl: helpers.urlFormat('/product/students/'),
                    messages: reqData.msgNumber,
                    latestOrders: Object.assign(reqData.recentOrder, {cancelReason: reqData.reason}),
                    favBrand: {
                        more: '/brands',
                        brands: reqData.guessBrand
                    },
                    newArrival: reqData.newProduct
                },
                recommend: reqData.recommendProduct,
                banner: reqData.footerBanner
            };
        })();
    }
};