Blame view

apps/product/controllers/seckill.js 9.96 KB
陈峰 authored
1 2 3 4 5 6 7
/**
 * 秒杀页面
 * @author: 陈峰<feng.chen@yoho.cn>
 * @date: 2016/09/08
 */

'use strict';
陈轩 authored
8
const Promise = require('bluebird');
陈轩 authored
9
const logger = global.yoho.logger;
陈轩 authored
10
const moment = require('moment');
11
const mRoot = '../models';
陈峰 authored
12
const headerModel = require('../../../doraemon/models/header');
13
const seckillModel = require(`${mRoot}/seckill`);
陈峰 authored
14
15 16 17 18 19
let headerData = headerModel.setNav({
    navTitle: '秒杀活动',
    navBtn: true,
});
20 21 22 23 24
/**
 * [时间缺0补0]
 */
const _timeFormat = (tick) => {
    return tick < 10 ? `0${tick}` : tick;
陈轩 authored
25 26
};
陈轩 authored
27
陈轩 authored
28
/**
陈轩 authored
29 30 31 32 33 34 35 36 37 38 39 40 41
 *  秒杀商品 添加 自定义属性
 *  ----------------------------------------
 * 已开抢
 *      product.over [APP,H5: 1.已抢光 2.过了endTime]
 *      product.isSeckill [APP,H5 秒杀中, 与over互斥]
 * 抢购中:
 *      product.over
 *      product.isSeckill
 * 即将开抢:
 *      product.wait = true
 *      product.remindFlag = true   [APP: 已添加提醒]
 *      product.remindFalg = false  [APP: 默认提醒状态]
 *      Product.hideRemind = true   [APP: queryRemindList接口失败的情况下]
陈轩 authored
42
 */
陈轩 authored
43
function _productAddFlag(productList, remindList) {
陈轩 authored
44 45
    let now = Date.now();
陈轩 authored
46 47 48 49 50
    productList
        .sort((a, b) => b.orderBy - a.orderBy)
        .forEach(product => {
            let startTime = product.startTime * 1000; // s to ms
            let endTime = product.endTime * 1000;
陈轩 authored
51
陈轩 authored
52
            product.remindFlag = false;
53
            product.readableTime = moment.unix(product.startTime).format('MM月DD日 HH:mm');
陈轩 authored
54 55 56

            if (now < startTime) { // 未开抢
                product.wait = true;
陈轩 authored
57
                product.isSeckill = true;
陈轩 authored
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73

                if (!remindList) {
                    product.hideRemind = true;
                } else if (remindList.length) {
                    for (let i = 0, j = remindList.length; i < j; i++) {
                        if (remindList[i].productSkn === product.productSkn) {  // remind on;
                            product.remindFlag = true;
                            remindList.splice(i, 1);
                            break;
                        }
                    }
                }
            } else if (product.secKillStatus === 0 || (now > endTime)) { // 确实已抢光, 过了秒杀时间
                product.over = true;
            }
        });
陈轩 authored
74 75

    return productList;
76
}
陈峰 authored
77 78

/**
陈轩 authored
79 80 81 82
 *    获取 秒杀产品列表
 */
function fetchProductList(activityInfo, uid) {
    let activityId = activityInfo.activityId;
陈轩 authored
83
    let hasRemindAttr = activityInfo.isApp && uid && (Date.now() < activityInfo.startTime);
陈轩 authored
84 85 86 87 88 89 90 91 92 93 94

    let productList = seckillModel.queryProductList(activityId);
    let remindList = hasRemindAttr ? seckillModel.queryRemindList(activityId, uid) : {
        code: 200,
        data: []
    };

    return Promise.all([productList, remindList])
        .then(res => {
            let r1 = res[0];
            let r2 = res[1];
陈轩 authored
95
            let result = [];
陈轩 authored
96 97 98 99 100

            if (r1.code !== 200) {
                return result;
            }
陈轩 authored
101 102 103
            result = r2.data ?
                _productAddFlag(r1.data, r2.data) :
                _productAddFlag(r1.data);
陈轩 authored
104 105 106 107 108

            return result;
        });
}
109
陈峰 authored
110 111 112
/**
 * [秒杀列表页面]
 */
113 114 115 116 117 118 119
const index = (req, res) => {
    return res.render('seckill', {
        title: '秒杀活动',
        pageHeader: headerData,
        pageStyle: 'seckill-page',
        pageFooter: true,
        width750: true,
陈轩 authored
120
    });
121
};
陈轩 authored
122
123 124 125 126 127
/**
 *  [秒杀列表 页面 初始数据]
 */
const indexData = (req, res, next) => {
    let focusTime = Number.parseInt(req.query.time, 10) || 0;
陈轩 authored
128
    let result = {};
陈轩 authored
129 130
    let uid = req.yoho.isApp && req.query.uid;
131
    return seckillModel.queryActivity().then((resultActivity) => {
陈轩 authored
132
        // console.log(resultActivity)
陈轩 authored
133
        let focusIndex = false;
134
陈峰 authored
135 136
        // let nowTime = Date.now();
        if (!resultActivity.data) {
137
            return next();
陈峰 authored
138 139
        }
        result.currentTime = resultActivity.data.currentTime * 1000;
140
        if (resultActivity.code !== 200) {
141 142
            return next();
        }
143
陈轩 authored
144 145 146 147 148
        if (!(
                resultActivity.data &&
                resultActivity.data.secKillProductVoList &&
                resultActivity.data.secKillProductVoList.length
            )) {
149
            return res.json({
陈轩 authored
150 151
                title: '秒杀活动',
                pageHeader: headerData,
陈轩 authored
152
                error: '来晚啦~秒杀已结束'
陈轩 authored
153
            });
154 155
        }
陈轩 authored
156
        result.activitys = resultActivity.data.secKillProductVoList.sort((a, b) => a.startTime - b.startTime); // orderBy startTime ASC
陈轩 authored
157 158 159 160

        if (focusTime) {
            focusTime = moment(focusTime, 'YYYYMMDDHHmmss').unix();
            focusIndex = result.activitys.findIndex(activity=> activity.startTime === focusTime);
陈轩 authored
161
陈轩 authored
162 163 164
            if (focusIndex !== -1) {
                result.activitys[focusIndex].focus = true;
                focusIndex = true;
陈轩 authored
165 166
            } else {
                focusIndex = false;
陈轩 authored
167 168 169
            }
        }
170
171 172 173 174 175 176 177 178 179 180 181
        result.activitys.forEach((activity, i) => {
            let date,
                hour = 0,
                minute = 0;

            activity.startTime *= 1000;
            date = new Date(activity.startTime);
            hour = date.getHours();
            minute = date.getMinutes();
            activity.time = `${_timeFormat(hour)}:${_timeFormat(minute)}`;
陈峰 authored
182
            if (result.currentTime > activity.startTime) { // 当前时间大于这个时间段,已经开始和即将开始两种情况
183 184
                if (i < result.activitys.length - 1) {
                    let nextTime = result.activitys[i + 1].startTime * 1000;
陈轩 authored
185
陈峰 authored
186
                    if (result.currentTime < nextTime) { // 下一个时间段与当前时间来区别是否正在抢购
187
                        activity.now = true;
陈轩 authored
188
                        focusIndex || (activity.focus = focusIndex = true);
189
                    } else {
190
                        activity.over = true;
191
                    }
192 193
                } else { // 大于这个时间段但是后面没有秒抢时间端了,则依然显示抢购中
                    activity.now = true;
陈轩 authored
194
                    focusIndex || (activity.focus = focusIndex = true);
195
                }
196 197
            } else {
                activity.wait = true;
198
            }
199 200
        });
        if (result.activitys.length && result.activitys.findIndex(activity => activity.focus) < 0) {
陈轩 authored
201 202
            let i = result.activitys.length;
203 204 205
            // 没有focus的活动,则focus 最后一个 over 的活动
            while (i) {
                let activity = result.activitys[i - 1];
陈轩 authored
206
207 208
                if (activity.over) {
                    activity.focus = true;
陈轩 authored
209 210
                    break;
                }
211 212 213

                i = i - 1;
            }
陈轩 authored
214 215

            // 没有over,全部都是未开抢,则focus第一个
216
            if (!i) {
陈轩 authored
217 218
                result.activitys[0].focus = true;
            }
219 220
        }
        let focusActivity = result.activitys.find(activity => activity.focus);
陈轩 authored
221 222 223 224 225
        let activityInfo = {
            activityId: focusActivity.activityId,
            startTime: focusActivity.startTime * 1000,
            isApp: req.yoho.isApp
        };
陈轩 authored
226
陈轩 authored
227 228
        return fetchProductList(activityInfo, uid).then((resultProducts) => {
            result.products = resultProducts;
lijing authored
229
陈轩 authored
230
            res.json(result);
陈轩 authored
231 232
        });
    });
233
234
};
235
236 237 238 239 240
/**
 * [xhr根据活动id获取商品列表]
 */
const getProductList = (req, res, next) => {
    if (!req.xhr) {
241
        return next();
242
    }
陈轩 authored
243
    let activityId = Number(req.query.activityId);
陈轩 authored
244
    let startTime = Number(req.query.startTime);
陈轩 authored
245
    let uid = req.yoho.isApp && req.query.uid;
陈轩 authored
246
247 248 249
    if (!activityId) {
        return next();
    }
陈轩 authored
250
陈轩 authored
251 252 253 254 255
    let activityInfo = {
        isApp: req.yoho.isApp,
        activityId,
        startTime
    };
陈轩 authored
256
陈轩 authored
257
    return fetchProductList(activityInfo, uid).then(resultProducts => {
陈轩 authored
258
        res.json({products: resultProducts});
陈轩 authored
259 260
    }).catch(error => {
        logger.error(error);
陈轩 authored
261 262
    });
};
陈峰 authored
263
陈轩 authored
264 265 266 267 268 269 270 271 272
// only app
const remind = (req, res, next) => {
    if (!(req.yoho.isApp && req.xhr)) {
        return res.status(404).json({
            msg: '请求不合法'
        });
    }

    return seckillModel.remind({
lijing authored
273 274 275 276 277 278 279
        on_off: req.body.on_off === 'true' ? true : false,
        activity_id: Number.parseInt(req.body.activity_id, 10),
        product_skn: Number.parseInt(req.body.product_skn, 10),
        uid: Number.parseInt(req.body.uid, 10),
        sec_kill_id: Number.parseInt(req.body.sec_kill_id, 10),
        app_type: 0
    })
陈轩 authored
280 281 282
        .then(result => {
            return res.json(result);
        });
陈轩 authored
283
};
陈轩 authored
284
陈轩 authored
285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336
// Middleware:检测 app_version 是否正确
// @param okVersion string  "5.1.0" [master_version, minor_version, patch_version]
// TODO: 可以移到 middleware;
const checkAppVer = function(okVersion) {
    return (req, res, next) => {
        /**
         * [比较app版本]
         * @param okVersion string '5.1.0'
         * @param curVersion string
         * @returns -1: 小于, 0 等于, 1大于
         */

        let compareVersion = (okVersion, curVersion) => { //eslint-disable-line
            let result = 0; // -1: 小于, 0 等于, 1 大于

            if (okVersion === curVersion) {
                return result;
            }

            okVersion = okVersion.split('.');
            curVersion = curVersion.split('.');

            for (var i = 0; i < 3; i++) {
                let standard = Number.parseInt(okVersion[i], 10) || 0;
                let cur = Number.parseInt(curVersion[i], 10) || 0;

                if (cur < standard) {
                    result = -1;
                    break;
                } else if (cur > standard) {
                    result = 1;
                    break;
                }
            }

            return result;
        };


        if (req.yoho.isApp) {
            let curVersion = req.query.app_version;
            let isOld = compareVersion(okVersion, curVersion) === -1;

            if (isOld) {
                return res.redirect('/passport/update');
            }
        }

        next();
    };
};
陈峰 authored
337
module.exports = {
338
    index,
339
    indexData,
陈轩 authored
340
    getProductList,
陈轩 authored
341 342
    remind,
    checkAppVer
343
};