后台:礼包码

This commit is contained in:
luying
2021-07-09 18:36:24 +08:00
parent 551591e260
commit 21518ed8a7
9 changed files with 378 additions and 5 deletions

View File

@@ -19,6 +19,9 @@ import { checkTaskWithHero, checkTaskWithEquip, checkTask, checkTaskWithArgs, ch
import { useGiftPackage } from "../../../services/activity/giftPackageService";
import { getAp, setAp, setApBuyTimes } from "../../../services/actionPointService";
import { ActionPointModel } from "../../../db/ActionPoint";
import { GiftCodeDetailModel } from "../../../db/GiftCodeDetail";
import { GiftCodeType, GiftCodeModel } from "../../../db/GiftCode";
import UserGiftCode, { UserGiftCodeModel } from "../../../db/UserGiftCode";
export default function (app: Application) {
return new ItemHandler(app);
@@ -141,6 +144,35 @@ export class ItemHandler {
});
}
// 兑换礼包码
public async useGiftCode(msg: { code: string }, session: BackendSession) {
const roleId: string = session.get('roleId');
const roleName: string = session.get('roleName');
const sid: string = session.get('sid');
const { code } = msg;
let giftCodeDetail = await GiftCodeDetailModel.findByCode(code);
let giftCode = <GiftCodeType>giftCodeDetail.giftCode;
if(giftCode.isLimit && giftCodeDetail.usedNum >= giftCode.count) {
return resResult(STATUS.GIFT_CODE_USED_NUM_MAX);
}
if(giftCode.beginTime > new Date()) return resResult(STATUS.GIFT_CODE_NOT_START);
if(giftCode.endTime < new Date()) return resResult(STATUS.GIFT_CODE_HAS_EXPIRED);
let userGiftCode = await UserGiftCodeModel.findByCode(roleId, code);
if(userGiftCode) {
return resResult(STATUS.YOU_HAVE_USED_THIS_CODE);
}
await UserGiftCode.createCode(roleId, code, giftCode);
await GiftCodeDetailModel.increaseUsedNum(code);
await GiftCodeModel.increaseUsedNum(giftCode.id);
let goods = await addItems(roleId, roleName, sid, giftCode.goods);
return resResult(STATUS.SUCCESS, { goods });
}
public async debugIncAp(msg: { magicWord: string, ap: number }, session: BackendSession) {
const { magicWord } = msg;
if (magicWord !== DEBUG_MAGIC_WORD) {

View File

@@ -127,4 +127,44 @@ export default class UserController extends Controller {
const { selectedRowKeys: roleIdAndIds, count } = ctx.request.body;
ctx.body = await ctx.service.users.setItemCount(roleIdAndIds, count);
}
public async getGiftCodeList() {
const { ctx } = this;
const { page, pageSize, sortField, sortOrder, form } = ctx.request.body;
ctx.body = await ctx.service.users.getGiftCodeList(page, pageSize, sortField, sortOrder, form);
}
public async updateGiftCode() {
const { ctx } = this;
const { id, values } = ctx.request.body;
ctx.body = await ctx.service.users.updateGiftCode(id, values);
}
public async generateGiftCode() {
const { ctx } = this;
const { id, generateType, code, generateNum, codeLen } = ctx.request.body;
if(generateType == 1) {
if(!generateNum) {
ctx.body = ctx.service.utils.resResult(STATUS.WRONG_PARMS);
return
}
} else if (generateType == 2) {
if(!code) {
ctx.body = ctx.service.utils.resResult(STATUS.WRONG_PARMS);
return
}
} else {
ctx.body = ctx.service.utils.resResult(STATUS.WRONG_PARMS);
return
}
ctx.body = await ctx.service.users.generateGiftCode(id, generateType, code, generateNum, codeLen);
}
public async getGiftCodeDetails() {
const { ctx } = this;
const { id } = ctx.params;
ctx.body = await ctx.service.users.getGiftCodeDetails(parseInt(id));
return
}
}

View File

@@ -42,6 +42,11 @@ export default (app: Application) => {
router.post('/api/users/deleteequip', tokenParser, controller.users.deleteEquip);
router.post('/api/users/deleteitem', tokenParser, controller.users.deleteItem);
router.post('/api/users/setitemcount', tokenParser, controller.users.setItemCount);
router.post('/api/users/getgiftcodelist', controller.users.getGiftCodeList);
router.post('/api/users/updategiftcode', controller.users.updateGiftCode);
router.post('/api/users/generategiftcode', controller.users.generateGiftCode);
// router.post('/api/users/delgiftCode', controller.users.delGiftCode);
router.get('/api/users/getgiftcodedetails/:id/:filename', controller.users.getGiftCodeDetails);
router.post('/api/game/getserverenv', tokenParser, controller.game.getServerEnv);
router.post('/api/game/getserverlistbyenv', tokenParser, controller.game.getServerListByEnv);

View File

@@ -33,6 +33,10 @@ import { FriendShipModel } from '@db/FriendShip';
import { FriendApplyModel } from '@db/FriendApply';
import { FriendRelationModel } from '@db/FriendRelation';
import { createHero as pubCreateHero, addSkin } from '@pubUtils/itemUtils';
import { GiftCodeModel } from '@db/GiftCode';
import { GiftCodeDetailModel } from '@db/GiftCodeDetail';
// import * as fs from 'fs';
/**
* Test Service
@@ -657,4 +661,76 @@ export default class GMUsers extends Service {
return ctx.service.utils.resResult(STATUS.INTERNAL_ERR);
}
}
public async getGiftCodeList(page: number, pageSize: number, sortField: string, sortOrder: string, form: { name?: string, current?: boolean, } = {}) {
const { ctx } = this;
const list = await GiftCodeModel.findByCondition(page, pageSize, sortField, sortOrder, form);
const total = await GiftCodeModel.countByCondition( form )
return ctx.service.utils.resResult(STATUS.SUCCESS, {
list: list.map(cur => {
return { ...cur, beginTime: cur.beginTime.getTime(), endTime: cur.endTime.getTime() }
}), total
});
}
public async updateGiftCode(id: string|number, params: any) {
const { ctx } = this;
if(params.beginTime) params.beginTime = new Date(params.beginTime);
if(params.endTime) params.endTime = new Date(params.endTime);
try{
params.goods = JSON.parse(params.goods);
} catch(e) {
console.error(e);
return ctx.body = ctx.service.utils.resResult(STATUS.WRONG_PARMS);
}
const result = await GiftCodeModel.updateData(id, params, ctx.user?.uid);
if(!result) return ctx.service.utils.resResult(STATUS.INTERNAL_ERR);
return ctx.service.utils.resResult(STATUS.SUCCESS);
}
public async generateGiftCode(id: number, generateType: 1|2, code: string, generateNum: number, codeLen: number = 8) {
const { ctx } = this;
let giftCode = await GiftCodeModel.findData(id);
if(!giftCode) return ctx.service.utils.resResult(STATUS.WRONG_PARMS);
let length = 0, isLimit = false, count = 0, generateCode = '';
if(generateType == 1) {
let generateResult = await GiftCodeDetailModel.generateMany(giftCode, generateNum, codeLen, ctx.user?.uid);
length = generateResult.length;
isLimit = true;
count = 1;
} else if (generateType == 2) {
let generateResult = await GiftCodeDetailModel.generateOne(giftCode, code, ctx.user?.uid);
length = generateResult.length;
generateCode = code;
}
if(length <= 0) return ctx.service.utils.resResult(STATUS.INTERNAL_ERR);
giftCode = await GiftCodeModel.updateData(id, { generateCnt: giftCode.generateCnt + length, generateType, isLimit, count, generateCode }, ctx.user?.uid);
return ctx.service.utils.resResult(STATUS.SUCCESS, { giftCode })
}
public async getGiftCodeDetails(id: number) {
const { ctx } = this;
let giftCode = await GiftCodeModel.findData(id);
if(!giftCode) return ctx.service.utils.resResult(STATUS.WRONG_PARMS);
let { generateCnt } = giftCode;
let limit = 1000;
let n = Math.ceil(generateCnt / limit);
let codes: string[] = [];
for(let i = 0; i < n; i++) {
let giftCodeDetails = await GiftCodeDetailModel.findByGiftCode(giftCode);
for(let {code} of giftCodeDetails) {
codes.push(code);
}
}
console.log(id, codes.join())
ctx.set('Content-Type', 'application/octet-stream');
return Buffer.from(codes.join('\n'));
}
}

View File

@@ -40,7 +40,8 @@ export const COUNTER = {
SERVER_BY_TYPE: { name: 'serverby', def: 1 },
SERVER: { name: 'server', def: 1 },
ACTIVITY_GROUP_TYPE: { name: 'actgrptype', def: 1 },
NOTICE: { name: 'notice', def: 1 }
NOTICE: { name: 'notice', def: 1 },
GIFT_CODE: { name: 'giftCode', def: 1 },
};
export const DEFAULT_HEROES = [19, 53, 46, 40, 22, 56, 32, 28, 18];

View File

@@ -330,10 +330,17 @@ export const STATUS = {
GACHA_COST_NOT_ENOUGH: { code: 31101, simStr: '招募券不足' },
GACHA_NOT_ASSIGN: { code: 31102, simStr: '请选择武将' },
GACHA_HOPE_NOT_GOLD: { code: 31103, simStr: '武将品质错误' },
GACHA_CAN_NOT_PICK: { code: 31004, simStr: '不可选择该武将' },
GACHA_TURNTABLE_POINT_NOT_ENOUGH: { code: 31005, simStr: '转盘积分不足' },
GACHA_HAS_VISITED: { code: 31006, simStr: '该武将已拜访过' },
GACHA_VISITED_COUNT_OVER: { code: 31007, simStr: '今天武将拜访已超过次数' },
GACHA_CAN_NOT_PICK: { code: 31104, simStr: '不可选择该武将' },
GACHA_TURNTABLE_POINT_NOT_ENOUGH: { code: 31105, simStr: '转盘积分不足' },
GACHA_HAS_VISITED: { code: 31106, simStr: '该武将已拜访过' },
GACHA_VISITED_COUNT_OVER: { code: 31107, simStr: '今天武将拜访已超过次数' },
// 礼包码 31201-31300
GIFT_CODE_USED_NUM_MAX: { code: 31201, simStr: '礼包码使用次数超过' },
YOU_HAVE_USED_THIS_CODE: { code: 31202, simStr: '您已使用过该码' },
GIFT_CODE_NOT_START: { code: 31203, simStr: '礼包码未生效' },
GIFT_CODE_HAS_EXPIRED: { code: 31204, simStr: '礼包码已失效' },
// 社交相关状态 40000 - 49999
SYS_CHANNEL_AUTH_NOT_ENOUGH: { code: 40000, simStr: '无法在系统频道发送消息' },
UPDATE_PRIVATE_MSG_READ_TIME_ERR: { code: 40001, simStr: '更新私聊阅读时间失败' },

119
shared/db/GiftCode.ts Normal file
View File

@@ -0,0 +1,119 @@
import BaseModel from './BaseModel';
import { getModelForClass, prop, DocumentType, modelOptions } from '@typegoose/typegoose';
import { CounterModel } from './Counter';
import { COUNTER } from '../consts';
class Rewards {
@prop({ required: true })
id: number;
@prop({ required: true })
count: number;
}
/**
* 举报记录
**/
@modelOptions({ schemaOptions: { id: false } })
export default class GiftCode extends BaseModel {
@prop({ required: true, default: '' })
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; // 开始时间
@prop({ required: true })
endTime: Date; // 结束时间
@prop({ required: true, default: '' })
remark: string; // 备注
@prop({ required: true, default: 0 })
generateType: number; // 生成类型
@prop({ required: true, default: 0 })
generateCnt: number; // 已生成条数giftCodeDetail的数量
@prop({ required: true, default: '' })
generateCode: string; // 单条的生成的那一个code
@prop({ required: true, default: 0 })
usedNum: number; // 使用次数
public static async findData(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);
}
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 rec: GiftCodeType = await GiftCodeModel.findOneAndUpdate({ id }, { $set: {...values, updatedBy: uid}, $setOnInsert: { ...createObj, createdBy: uid } },
{ new: true, upsert: 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 }) {
let searchObj = {};
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 };
}
return searchObj
}
public static async findByCondition(page: number, pageSize: number, sortField: string, sortOrder: string, form: { name?: string, current?: boolean } = {}) {
let searchObj = this.getSearchObj(form);
let sort = {};
if (sortField && sortOrder) {
if (sortOrder == 'ascend') {
sort[sortField] = 1;
} else if (sortOrder == 'descend') {
sort[sortField] = -1;
}
}
const result: GiftCodeType[] = await GiftCodeModel.find(searchObj, { _id: 0 }).limit(pageSize).skip((page - 1) * pageSize).sort(sort).lean({ getters: true, virtuals: true });
return result;
}
public static async countByCondition(form: { name?: string, current?: boolean } = {}) {
let searchObj = this.getSearchObj(form);
const result = await GiftCodeModel.count(searchObj);
return result;
}
}
export const GiftCodeModel = getModelForClass(GiftCode);
export interface GiftCodeType extends Pick<DocumentType<GiftCode>, keyof GiftCode> { }
export type GiftCodeParam = Partial<GiftCodeType>;

View File

@@ -0,0 +1,57 @@
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';
/**
* 举报记录
**/
@modelOptions({ schemaOptions: { id: false } })
@index({ code: 1 })
export default class GiftCodeDetail extends BaseModel {
@prop({ required: true, default: '' })
code: string; // 兑换码
@prop({ ref: 'GiftCode', type: mongoose.Schema.Types.ObjectId })
giftCode: Ref<GiftCode>;
@prop({ required: true, default: '' })
usedNum: number; // 该码使用次数
// 根据code
public static async findByCode(code: string) {
let result: GiftCodeDetailType = await GiftCodeDetailModel.findOne({ code }).populate('giftCode').lean(true);
return result;
}
public static async findByGiftCode(giftCode: GiftCodeType) {
let result: GiftCodeDetailType[] = await GiftCodeDetailModel.find({ giftCode: giftCode._id }).lean();
return result;
}
public static async increaseUsedNum(code: string) {
let result: GiftCodeDetailType = await GiftCodeDetailModel.findOneAndUpdate({ code }, { $inc: { usedNum: 1 } }, { 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) {
let insertArr: GiftCodeDetailParam[] = [];
for(let i = 0; i < generateNum; i++) {
insertArr.push({ giftCode: giftCode._id, code: genCode(codeLen), usedNum: 0, createdBy: uid, updatedBy: uid });
}
let result = await GiftCodeDetailModel.insertMany(insertArr);
return result;
}
}
export const GiftCodeDetailModel = getModelForClass(GiftCodeDetail);
export interface GiftCodeDetailType extends Pick<DocumentType<GiftCodeDetail>, keyof GiftCodeDetail> { }
export type GiftCodeDetailParam = Partial<GiftCodeDetailType>;

36
shared/db/UserGiftCode.ts Normal file
View File

@@ -0,0 +1,36 @@
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>;