From b2cacee61b480602b1d70a4fea84e3ad6256de24 Mon Sep 17 00:00:00 2001 From: zhl Date: Fri, 14 May 2021 17:38:11 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=BA=97=E9=93=BA=E4=BF=A1?= =?UTF-8?q?=E6=81=AF=E7=9A=84=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- doc/api.md | 39 +++++ package.json | 5 +- src/api/controllers/shop.controller.ts | 29 ++++ src/models/shop/ShopActivity.ts | 201 ++++++++++++++++++++++++- src/models/shop/ShopExam.ts | 10 +- yarn.lock | 2 +- 6 files changed, 277 insertions(+), 9 deletions(-) diff --git a/doc/api.md b/doc/api.md index ba460f6..8a8697b 100644 --- a/doc/api.md +++ b/doc/api.md @@ -283,4 +283,43 @@ } } } +``` + + +### 8. 获取店铺信息 + +1. Method: POST +2. URI: /api/:accountid/shop + +| 字段 | 说明 | +| -------- | -------------------------------------- | +| accountid | 帐号id | + +> POST参数 + + +| 字段 | 说明 | +| -------- | -------------------------------------- | +| sid | 店铺id | + +3. Response: JSON + +```js +{ + "id": "607ff59d4a4e16687a3b7079", // 店铺id + "name": "一品漫城", // 店铺名 + "area": "上海市-上海市-闵行区", // 区域 + "logo": "https://resource.kingsome.cn/game607fd53cb40504740fdccb13.png", // 店铺logo + "exam": { // 店铺测验信息 + "id": "609e13eeccc78154ac683583", //id + "name": "第一期测试" // 测验 + }, + "activity": { // 活动信息 + "id": "608bdf61cecfcc2f45247663", // 活动id + "name": "第一个活动", // 活动名 + "desc": "", // 活动简介 + "curren": 1621008800000 // 当前正在进行的活动开始时间, 没有该字段或undefined的话, 说明没有当前进行中的活动 + "next": 1621008900000 // 下一个活动开始时间, 没有该字段或undefined的话, 说明没有即将开始的活动 + } + } ``` \ No newline at end of file diff --git a/package.json b/package.json index 627e3d7..a73fe9a 100644 --- a/package.json +++ b/package.json @@ -34,6 +34,7 @@ "fs-jetpack": "^4.1.0", "iconv-lite": "^0.6.2", "mime-types": "^2.1.27", + "moment": "^2.29.1", "mongoose": "5.10.3", "mongoose-findorcreate": "^3.0.0", "qrcode": "^1.4.4", @@ -47,12 +48,12 @@ "wechat-oauth": "^1.5.0" }, "devDependencies": { + "@typegoose/auto-increment": "^0.4.1", + "@typegoose/typegoose": "^7.4.6", "@types/debug": "^4.1.5", "@types/dotenv": "^8.2.0", "@types/mongoose": "5.10.3", "@types/node": "^14.14.20", - "@typegoose/auto-increment": "^0.4.1", - "@typegoose/typegoose": "^7.4.6", "@types/redis": "^2.8.28", "ts-node": "^9.1.1", "tsconfig-paths": "^3.9.0", diff --git a/src/api/controllers/shop.controller.ts b/src/api/controllers/shop.controller.ts index 7e14495..2a2cb35 100644 --- a/src/api/controllers/shop.controller.ts +++ b/src/api/controllers/shop.controller.ts @@ -1,6 +1,10 @@ import BaseController from '../../common/base.controller' import { Shop } from '../../models/shop/Shop' import { role, router } from '../../decorators/router' +import { isObjectId } from '../../utils/string.util' +import { ZError } from '../../common/ZError' +import { ShopExam } from '../../models/shop/ShopExam' +import { ShopActivity } from '../../models/shop/ShopActivity' class ShopController extends BaseController { @@ -84,4 +88,29 @@ class ShopController extends BaseController { return {} } + @role('anon') + @router('post /api/:accountid/shop') + async shopInfo(req, res) { + let { sid } = req.params + if (!sid || !isObjectId(sid)) { + throw new ZError(10, '没有店铺id或者店铺id格式不正确, 测试使用: 607ff59d4a4e16687a3b7079') + } + let rspData: any = {} + let shop = await Shop.findById(sid) + if (!shop) { + throw new ZError(11, '未找到对应的店铺') + } + rspData.id = shop.id + rspData.name = shop.showName + rspData.area = shop.areaStr + rspData.logo = shop.logo + const now = Date.now() + let exam = await ShopExam.findOne({shop: sid, beginTime: {$lte: now}, endTime: {$gte: now}, active: true, deleted: false}) + if (exam) { + rspData.exam = {id : exam.id, name: exam.name, desc: exam.desc} + } + let activity = await ShopActivity.getActivityOne(sid) + rspData.activity = activity + return rspData + } } diff --git a/src/models/shop/ShopActivity.ts b/src/models/shop/ShopActivity.ts index c372669..2571ace 100644 --- a/src/models/shop/ShopActivity.ts +++ b/src/models/shop/ShopActivity.ts @@ -7,6 +7,8 @@ import { import { BaseModule } from '../Base' import { noJson } from '../../decorators/nojson' import { Severity } from '@typegoose/typegoose/lib/internal/constants' +import moment from 'moment' +import { GameEnv } from '../../config/GameEnv' export class ActivityRewardClass { @prop() @@ -78,7 +80,7 @@ export class ShopActivityClass extends BaseModule { @prop({ type: () => [Number] }) public weekDays: number[] /** - * 活动正式开始时间, 从0点开始 + * 活动正式开始时间, 从0点开始, 秒 * @type {number} */ @prop({ type: () => [Number] }) @@ -159,6 +161,203 @@ export class ShopActivityClass extends BaseModule { let sort = {_id: -1} return { opt, sort } } + public static async getActivityOne(shop: string) { + let record = await ShopActivity.findOne({shop , active: true, deleted: false}) + if (!record) { + return null + } + + let result: any = {id: record.id, name: record.name, desc: record.desc} + result.current = getCurrentTime(record) + result.next = getNextTime(record, result.current) + return result + } } export const ShopActivity = getModelForClass(ShopActivityClass, { existingConnection: ShopActivityClass.db }) + +function fetchCurrentGameTime(times: number[], gameTime: number, prepareTime: number) { + const today = moment().startOf('day').toDate().getTime() + const now = Date.now() + for (let _t of times) { + let begTime = _t * 1000 + today + let preTime = begTime - prepareTime * 60 * 1000 + let endTime = begTime + gameTime + if (now >= preTime && now <= endTime) { + return begTime + } + } +} + +function getCurrentTime(record: any) { + const cfg = new GameEnv() + const gameTime = (cfg.pvpInterval + cfg.effectTimeLong) * record.qcount * 1000 + const today = moment().startOf('day').toDate().getTime() + switch (record.repeatType) { + case 0: //指定时间和日期 + let day = record.beginDays.find(o => o === today) + if (!day) { + return null + } + return fetchCurrentGameTime(record.beginTime, gameTime, record.prepareTime) + + case 1: //每天固定时间进行的 + // 开始时间大于今天或结束时间小于今天的, 去除 + if (record.beginDay > today || record.endDay < today) { + return null + } + return fetchCurrentGameTime(record.beginTime, gameTime, record.prepareTime) + case 2: //每周固定时间进行的 + // 开始时间大于今天或结束时间小于今天的, 去除 + if (record.beginDay > today || record.endDay < today) { + return null + } + const dayOfWeek = moment().weekday() + if (!record.weekDays.find(o => o === dayOfWeek)) { + return null + } + return fetchCurrentGameTime(record.beginTime, gameTime, record.prepareTime) + case 3: //每月固定时间进行的 + // 开始时间大于今天或结束时间小于今天的, 去除 + if (record.beginDay > today || record.endDay < today) { + return null + } + const dayOfMonth = moment().date() + if (!record.monthDays.find(o => o === dayOfMonth)) { + return null + } + return fetchCurrentGameTime(record.beginTime, gameTime, record.prepareTime) + } + return null +} + + +function getNextTime(record: any, current: number | null) { + const today = moment().startOf('day').toDate().getTime() + let times: number[] = [] + const now = Date.now() + switch (record.repeatType) { + case 0: //指定时间和日期 + for (let _d of record.beginDays) { + if (_d < today) { + continue + } + for (let _t of record.beginTime) { + times.push(_t * 1000 + _d) + } + } + for (let _t of times) { + if (!current && _t > now) { + return _t + } + if (_t > current && _t > now) { + return _t + } + } + break + case 1: //每天固定时间进行的 + // 结束时间小于今天的, 去除 + if (record.endDay < today) { + return null + } + if (!record.beginTime) { + return null + } + for (let _t of record.beginTime) { + times.push(_t * 1000 + today) + } + let nextDay = moment().startOf('day').add(1, 'day').toDate().getTime() + for (let _t of record.beginTime) { + times.push(_t * 1000 + nextDay) + } + + for (let _t of times) { + if (!current && _t > now) { + return _t + } + if (_t > current && _t > now) { + return _t + } + } + break + case 2: //每周固定时间进行的 + // 结束时间小于今天的, 去除 + if (record.endDay < today) { + return null + } + if (!record.weekDays || record.weekDays.length ===0 || !record.beginTime) { + return null + } + const dayOfWeek = moment().weekday() + record.weekDays.sort() + let days: number[] = [] + for (let _d of record.weekDays) { + if (_d >= dayOfWeek) { + days.push(_d) + } + if (days.length >= 2) { + break + } + } + if (days.length < 2) { + days.push(record.weekDays[0] + 7) + } + const weekStart = moment().startOf('week').toDate().getTime() + for (let _d of days) { + for (let _t of record.beginTime) { + times.push(_t * 1000 + weekStart + _d * 24 * 3600 * 1000) + } + } + + for (let _t of times) { + if (!current && _t > now) { + return _t + } + if (_t > current && _t > now) { + return _t + } + } + break + case 3: //每月固定时间进行的 + // 结束时间小于今天的, 去除 + if (record.endDay < today) { + return null + } + if (record.monthDays.length == 0 || !record.beginTime) { + return null + } + const dayOfMonth = moment().date() + record.monthDays.sort() + let mdays: number[] = [] + for (let _d of record.monthDays) { + if (_d < dayOfMonth) { + continue + } + mdays.push(_d) + if (mdays.length >= 2) { + break + } + } + const monthStart: number = moment().startOf('month').toDate().getTime() + for (let _d of mdays) { + for (let _t of record.beginTime) { + times.push(_t * 1000 + monthStart + _d * 24 * 3600 * 1000) + } + } + if (mdays.length < 2) { + const nextMonth = moment().startOf('month').add(1, 'month').toDate().getTime() + for (let _t of record.beginTime) { + times.push(_t * 1000 + nextMonth + record.monthDays[0] * 24 * 3600 * 1000) + } + } + for (let _t of times) { + if (!current && _t > now) { + return _t + } + if (_t > current && _t > now) { + return _t + } + } + } + return null +} diff --git a/src/models/shop/ShopExam.ts b/src/models/shop/ShopExam.ts index 63ee366..1b4ace0 100644 --- a/src/models/shop/ShopExam.ts +++ b/src/models/shop/ShopExam.ts @@ -70,15 +70,15 @@ export class ShopExamClass extends BaseModule { * 活动正式开始时间, 从0点开始 * @type {number} */ - @prop({ type: () => [Number] }) - public beginTime: number[] + @prop({ default: 0 }) + public beginTime: number /** * 结束时间 - * @type {number[]} + * @type {number} */ - @prop({ type: () => [Number] }) - public endTime: number[] + @prop({ default: 4102416001000 }) + public endTime: number @prop({_id: false, type: [ExamRewardClass]}) public rewardInfo: ExamRewardClass[]; diff --git a/yarn.lock b/yarn.lock index 83a40aa..7c9a425 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1554,7 +1554,7 @@ mkdirp@^1.0.4: resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== -moment@^2.16.0: +moment@^2.16.0, moment@^2.29.1: version "2.29.1" resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.1.tgz#b2be769fa31940be9eeea6469c075e35006fa3d3" integrity sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==