后台:礼包码

This commit is contained in:
luying
2021-12-10 17:36:01 +08:00
parent ecca95b40b
commit cb999cec10
12 changed files with 255 additions and 174 deletions
+5
View File
@@ -770,4 +770,9 @@ export enum SERVER_TIMER {
TEN_HALF = 2, // 10:30
FIFTEEN_HALF = 3, // 15:30
NINETEEN_HALF = 4, // 19:30
}
export enum GIFT_GENERATE_TYPE {
ONE_TO_ONE = 1, // 一人一码,一条码只能被用一次
ONE_TO_MANY = 2, // 通码,一条码能被多人使用,每个人只能用一次
}
+41 -38
View File
@@ -1,7 +1,8 @@
import BaseModel from './BaseModel';
import { getModelForClass, prop, DocumentType, modelOptions } from '@typegoose/typegoose';
import { CounterModel } from './Counter';
import { COUNTER } from '../consts';
import { COUNTER, GIFT_GENERATE_TYPE } from '../consts';
import { SearchGiftCodeParam } from '../domain/backEndField/search';
class Rewards {
@prop({ required: true })
@@ -15,81 +16,84 @@ class Rewards {
**/
@modelOptions({ schemaOptions: { id: false } })
export default class GiftCode extends BaseModel {
@prop({ required: true, default: '' })
@prop({ required: true })
id: number; // 唯一id
@prop({ required: true, default: '' })
name: string; // 礼包码名
@prop({ required: true, default: false })
isLimit: boolean; // 每个码是否有使用次数限制
@prop({ required: true, default: 0 })
count: number; // 每个码可使用次数
@prop({ required: true, type: Rewards, _id: false })
goods: Rewards[]; // 奖励
@prop({ required: true })
beginTime: Date; // 开始时间
beginTime: number; // 开始时间
@prop({ required: true })
endTime: Date; // 结束时间
endTime: number; // 结束时间
@prop({ required: true, default: 0 })
codeLen: number; // 礼包码位数
@prop({ required: true, default: '' })
remark: string; // 备注
@prop({ required: true, default: 0 })
generateType: number; // 生成类型
@prop({ required: true, default: 0, enum: GIFT_GENERATE_TYPE })
generateType: GIFT_GENERATE_TYPE; // 生成类型
@prop({ required: true, default: 0 })
generateCnt: number; // 生成条数,giftCodeDetail的数量
@prop({ required: true, default: '' })
generateCode: string; // 单条的生成的那一个code
generateCnt: number; // 生成条数,giftCodeDetail的数量
@prop({ required: true, default: 0 })
usedNum: number; // 使用次数
public static async findData(id: number) {
@prop({ required: true, default: true })
isEnable: boolean; // 是否可以使用
public static async findByGiftId(id: number) {
let rec: GiftCodeType = await GiftCodeModel.findOne({ id }).lean();
return rec;
}
public static async updateData(id: string|number, values: GiftCodeParam, uid = 1) {
if(id == 'new') {
id = await CounterModel.getNewCounter(COUNTER.GIFT_CODE);
}
public static async createData(values: GiftCodeParam, uid = 1) {
let id = await CounterModel.getNewCounter(COUNTER.GIFT_CODE);
let doc = new GiftCodeModel();
let createObj = doc.toJSON();
delete values.id;
delete createObj._id;
delete createObj.id;
for(let key in values) {
delete createObj[key];
}
let obj = doc.toJSON();
let update = Object.assign(obj, values, { id });
let rec: GiftCodeType = await GiftCodeModel.findOneAndUpdate({ id }, { $set: {...values, updatedBy: uid}, $setOnInsert: { ...createObj, createdBy: uid } },
let rec: GiftCodeType = await GiftCodeModel.findOneAndUpdate({ id }, { $set: { updatedBy: uid}, $setOnInsert: { ...update, createdBy: uid } },
{ new: true, upsert: true }).lean(true);
return rec;
}
public static async updateData(id: number, values: GiftCodeParam, uid = 1) {
let rec: GiftCodeType = await GiftCodeModel.findOneAndUpdate({ id }, { $set: {...values, updatedBy: uid} },
{ new: true }).lean(true);
return rec;
}
public static async increaseUsedNum(id: number) {
let result: GiftCodeType = await GiftCodeModel.findOneAndUpdate({ id }, { $inc: { usedNum: 1 } }, { new: true }).lean();
return result;
}
private static getSearchObj(form: { name?: string, current?: boolean }) {
public static async increateGenerateNum(id: number, count: number) {
let result: GiftCodeType = await GiftCodeModel.findOneAndUpdate({ id }, { $inc: { generateCnt: count } }, { new: true }).lean();
return result;
}
private static getSearchObj(form: SearchGiftCodeParam) {
let searchObj = {};
if(form.id) searchObj['id'] = form.id;
if (form.name != undefined) searchObj['name'] = { $regex: new RegExp(form.name.toString(), 'i') };
if (form.current) {
searchObj['beginTime'] = { $lte: new Date };
searchObj['endTime'] = { $gte: new Date };
if (form.createTimeStart && form.createTimeEnd) {
searchObj['createdAt'] = { $lte: new Date(form.createTimeEnd * 1000), $gte: new Date(form.createTimeStart * 100) };
}
return searchObj
}
public static async findByCondition(page: number, pageSize: number, sortField: string, sortOrder: string, form: { name?: string, current?: boolean } = {}) {
public static async findByCondition(page: number, pageSize: number, sortField: string, sortOrder: string, form:SearchGiftCodeParam = {}) {
let searchObj = this.getSearchObj(form);
let sort = {};
@@ -105,7 +109,7 @@ export default class GiftCode extends BaseModel {
}
public static async countByCondition(form: { name?: string, current?: boolean } = {}) {
public static async countByCondition(form: SearchGiftCodeParam = {}) {
let searchObj = this.getSearchObj(form);
const result = await GiftCodeModel.count(searchObj);
@@ -113,7 +117,6 @@ export default class GiftCode extends BaseModel {
}
}
export const GiftCodeModel = getModelForClass(GiftCode);
export let GiftCodeModel = getModelForClass(GiftCode);
export interface GiftCodeType extends Pick<DocumentType<GiftCode>, keyof GiftCode> { }
export type GiftCodeParam = Partial<GiftCodeType>;
+53 -18
View File
@@ -1,7 +1,23 @@
import BaseModel from './BaseModel';
import { index, getModelForClass, prop, DocumentType, modelOptions, Ref, mongoose } from '@typegoose/typegoose';
import GiftCode, { GiftCodeType } from './GiftCode';
import { genCode } from '../pubUtils/util';
import { index, getModelForClass, prop, DocumentType, modelOptions } from '@typegoose/typegoose';
import { GIFT_GENERATE_TYPE } from '../consts';
import { GiftCodeModel, GiftCodeType } from './GiftCode';
import { nowSeconds } from '../pubUtils/timeUtil';
import { genCode } from '@pubUtils/util';
class RoleRecord {
@prop({ required: true, default: '' })
roleId: string;
@prop({ required: true, default: '' })
roleName: string;
@prop({ required: true, default: 0 })
serverId: number;
@prop({ required: true, default: 0 })
time: number;
}
/**
* 举报记录
@@ -9,15 +25,28 @@ import { genCode } from '../pubUtils/util';
@modelOptions({ schemaOptions: { id: false } })
@index({ code: 1 })
export default class GiftCodeDetail extends BaseModel {
@prop({ required: true, default: '' })
giftId: number; // giftCode表的id
@prop({ required: true, default: '' })
giftName: string; // giftCode表的name
@prop({ required: true, default: 0, enum: GIFT_GENERATE_TYPE })
generateType: GIFT_GENERATE_TYPE; // 一人一码or通码
@prop({ required: true, default: '' })
code: string; // 兑换码
@prop({ ref: 'GiftCode', type: mongoose.Schema.Types.ObjectId })
giftCode: Ref<GiftCode>;
@prop({ required: true, default: '' })
usedNum: number; // 该码使用次数
@prop({ required: true, type: String })
roleIds: string[];
@prop({ required: true, type: RoleRecord, _id: false })
record: RoleRecord[];
// 根据code
public static async findByCode(code: string) {
@@ -25,27 +54,33 @@ export default class GiftCodeDetail extends BaseModel {
return result;
}
public static async findByGiftCode(giftCode: GiftCodeType) {
let result: GiftCodeDetailType[] = await GiftCodeDetailModel.find({ giftCode: giftCode._id }).lean();
public static async findAllCodeByGiftId(id: number, cnt: number) {
let n = Math.ceil(cnt/1000);
let result: GiftCodeDetailType[] = [];
for(let i = 0; i < n; i++) {
let codes = await GiftCodeDetailModel.find({ giftId: id }).limit(1000).skip(i * 1000).sort({ _id: 1 }).lean();
result.push(...codes);
}
return result;
}
public static async increaseUsedNum(code: string) {
let result: GiftCodeDetailType = await GiftCodeDetailModel.findOneAndUpdate({ code }, { $inc: { usedNum: 1 } }, { new: true }).lean();
public static async increaseUsedNum(code: string, roleId: string, roleName: string, serverId: number) {
let result: GiftCodeDetailType = await GiftCodeDetailModel.findOneAndUpdate({ code }, {
$inc: { usedNum: 1 }, $push: { roleIds: roleId, record: { roleId, roleName, serverId, time: nowSeconds() } }
}, { new: true }).lean();
return result;
}
public static async generateOne(giftCode: GiftCodeType, code: string, uid = 1 ) {
let result = await GiftCodeDetailModel.insertMany([{ giftCode: giftCode._id, code, usedNum: 0, createdBy: uid, updatedBy: uid }]);
return result;
}
public static async generateMany(giftCode: GiftCodeType, generateNum: number, codeLen: number, uid = 1) {
public static async generateMany(giftCode: GiftCodeType, count = 1, uid = 1) {
let insertArr: GiftCodeDetailParam[] = [];
for(let i = 0; i < generateNum; i++) {
insertArr.push({ giftCode: giftCode._id, code: genCode(codeLen), usedNum: 0, createdBy: uid, updatedBy: uid });
for(let i = 0; i < count; i++) {
insertArr.push({
giftId: giftCode.id, giftName: giftCode.name, generateType: giftCode.generateType,
code: genCode(giftCode.codeLen), usedNum: 0, createdBy: uid, updatedBy: uid
});
}
let result = await GiftCodeDetailModel.insertMany(insertArr);
await GiftCodeModel.increateGenerateNum(giftCode.id, count);
return result;
}
-36
View File
@@ -1,36 +0,0 @@
import BaseModel from './BaseModel';
import { index, getModelForClass, prop, DocumentType, modelOptions, Ref, mongoose } from '@typegoose/typegoose';
import GiftCode, { GiftCodeType } from './GiftCode';
/**
* 举报记录
**/
@modelOptions({ schemaOptions: { id: false } })
@index({ roleId: 1, code: 1 })
export default class UserGiftCode extends BaseModel {
@prop({ required: true, default: '' })
roleId: string; // 玩家id
@prop({ required: true, default: '' })
code: string; // 兑换码
@prop({ ref: 'GiftCode', type: mongoose.Schema.Types.ObjectId })
giftCode: Ref<GiftCode>;
// 根据code
public static async findByCode(roleId: string, code: string) {
let result: UserGiftCodeType = await UserGiftCodeModel.findOne({ roleId, code }).lean();
return result;
}
public static async createCode(roleId: string, code: string, gitCode: GiftCodeType) {
let result: UserGiftCodeType = await UserGiftCodeModel.findOneAndUpdate({ roleId, code }, { $setOnInsert: { gitCode: gitCode._id } }, { new: true, upsert: true}).lean()
return result;
}
}
export const UserGiftCodeModel = getModelForClass(UserGiftCode);
export interface UserGiftCodeType extends Pick<DocumentType<UserGiftCode>, keyof UserGiftCode> { }
export type UserGiftCodeParam = Partial<UserGiftCodeType>;
+71 -2
View File
@@ -1,7 +1,9 @@
import { GM_MAIL_TYPE, MAIL_TIME_TYPE, SERVER_TIMER } from "../../consts";
import { isArray } from 'underscore';
import { GIFT_GENERATE_TYPE, GM_MAIL_TYPE, MAIL_TIME_TYPE, SERVER_TIMER } from "../../consts";
import { isArray, isNumber, isString } from 'underscore';
import ServerStategy, { GMMail } from "../../db/ServerStategy";
import { RegionType } from "../../db/Region";
import { RewardInter } from "../../pubUtils/interface";
import { isTimestamp } from '../../pubUtils/util';
export class UpdateMailParams {
hasGoods: boolean = false; // 是否有道具
@@ -156,4 +158,71 @@ export class CreateServerParam {
if(this.hasCircleMail && !this.circleMail) return false;
return true;
}
}
export class CreateGiftCode {
name: string; // 礼包码名
goods: RewardInter[]; // 奖励
beginTime: number; // 开始时间
endTime: number; // 结束时间
codeLen: number; // 礼包码位数
remark: string = ''; // 备注
generateType: GIFT_GENERATE_TYPE; // 生成类型
constructor(obj: any) {
this.name = obj.name;
this.goods = obj.goods;
this.beginTime = obj.beginTime;
this.endTime = obj.endTime;
this.codeLen = obj.codeLen;
this.remark = obj.remark;
this.generateType = obj.generateType;
}
checkParams() {
if(!isString(this.name)) return false;
if(!isArray(this.goods)) return false;
for(let { id, count } of this.goods) {
if(!isNumber(id) || !isNumber(count)) return false;
}
if(!isTimestamp(this.beginTime) || !isTimestamp(this.endTime)) return false;
if(!isNumber(this.codeLen) || this.codeLen <= 0) return false;
if(this.generateType != GIFT_GENERATE_TYPE.ONE_TO_MANY && this.generateType != GIFT_GENERATE_TYPE.ONE_TO_ONE) {
return false
}
return true;
}
}
export class UpdateGiftCode {
id: number;
name: string; // 礼包码名
goods: RewardInter[]; // 奖励
beginTime: number; // 开始时间
endTime: number; // 结束时间
codeLen: number; // 礼包码位数
remark: string = ''; // 备注
constructor(id: number, obj: any) {
this.id = id;
this.name = obj.name;
this.goods = obj.goods;
this.beginTime = obj.beginTime;
this.endTime = obj.endTime;
this.codeLen = obj.codeLen;
this.remark = obj.remark;
}
checkParams() {
if(!isNumber(this.id) || this.id <= 0) return false
if(!isString(this.name)) return false;
if(!isArray(this.goods)) return false;
for(let { id, count } of this.goods) {
if(!isNumber(id) || !isNumber(count)) return false;
}
if(!isTimestamp(this.beginTime) || !isTimestamp(this.endTime)) return false;
if(!isNumber(this.codeLen) || this.codeLen <= 0) return false;
return true;
}
}
+8
View File
@@ -43,4 +43,12 @@ export interface SearchMarqueeParam {
createTimeEnd?: number;
sendTimeStart?: number;
sendTimeEnd?: number;
}
export interface SearchGiftCodeParam {
env?: string;
id?: number;
name?: string;
createTimeStart?: number;
createTimeEnd?: number;
}
-2
View File
@@ -90,7 +90,6 @@ import { ScriptBarrageModel } from '../db/ScriptBarrage';
import { ServerMailModel } from '../db/ServerMail';
import { UserGachaModel } from '../db/UserGacha';
import { UserGachaRecModel } from '../db/UserGachaRec';
import { UserGiftCodeModel } from '../db/UserGiftCode';
import { UserGuildActivityRecModel } from '../db/UserGuildActivityRec';
import { UserOrderModel } from '../db/UserOrder';
import { UserShopModel } from '../db/UserShop';
@@ -462,7 +461,6 @@ export async function deletRole(roleId: string) {
await TowerTaskRecModel.deleteMany({ roleId });
await UserGachaModel.deleteMany({ roleId });
await UserGachaRecModel.deleteMany({ roleId });
await UserGiftCodeModel.deleteMany({ roleId });
await UserGuildModel.deleteMany({ roleId });
await UserGuildActivityRecModel.deleteMany({ roleId });
await UserGuildApplyModel.deleteMany({ roleId });
+7
View File
@@ -1,6 +1,7 @@
import { STATUS } from './../consts/statusCode';
import { HeroModel, HeroType } from '../db/Hero';
import { isNumber } from 'underscore';
const csprng = require('csprng');
import fs = require('fs');
@@ -668,4 +669,10 @@ export async function checkWhiteList(env: string, ip: string, uid: number, serve
if(!!result) return true;
}
return false
}
export function isTimestamp(time: number, len = 10) {
if(!isNumber(time)) return false;
if(time.toString().length != len) return false;
return true;
}