团购:基础接口

This commit is contained in:
luying
2022-10-09 19:11:29 +08:00
parent 9ba3081e54
commit 2d3a1c7c30
16 changed files with 542 additions and 5 deletions
@@ -59,6 +59,7 @@ export enum ACTIVITY_TYPE {
SHOP = 44, // 限时商店
GUIDE_GACHA = 45, // 500抽
POP_NOTICE = 46, // 打脸公告
GROUP_SHOP = 49, // 团购
}
/**
@@ -240,4 +241,10 @@ export enum POP_NOTICE_TIME_SHOW_TYPE {
READ_STR = 1, // 读time字段字符串
READ_COUNTDOWN = 2, // 读倒计时
NO = 3, // 不显示
}
export enum GROUP_SHOP_PRICE_STATUS {
NOT_ENOUGH = 0, // 客户端的价格不足当前价格
NORMAL = 1, // 正好
OVER = 2, // 客户端的价格高于当前价格
}
+2
View File
@@ -21,6 +21,7 @@ export const CHANNEL_PREFIX = {
CITY: 'city', // 军团活动,诸侯混战,按城池分channel
GUILD_AUCTION: 'g_auction', // 军团拍卖
WORLD_AUCTION: 'w_auction', // 军团拍卖
GROUP_SHOP: 'groupShop', // 团购页面
}
export const getChannelType = function(prefix: string) {
@@ -164,4 +165,5 @@ export const PUSH_ROUTE = {
LADDER_CHECK_STOP: 'onLadderCheckStop',
LADDER_BATTLE_STOP: 'onLadderBattleStop',
LADDER_RANK_UPDATE: 'onLadderRankUpdate',
GROUP_SHOP_UPDATE: 'onGroupShopUpdate',
}
+1
View File
@@ -1041,6 +1041,7 @@ export enum ITEM_CHANGE_REASON {
USE_VOUCHER = 150, // 使用代金券
LADDER_BUY_CNT = 151, // 名将擂台购买次数
LADDER_BATTLE_REWARD = 152, // 名将擂台关卡奖励
ACT_GROUP_SHOP_BUY = 153, // 团购
}
export enum TA_EVENT {
+5
View File
@@ -504,6 +504,11 @@ export const STATUS = {
ACTIVITY_POP_UP_MUST_BUY: { code: 50037, simStr: '该礼包必须购买' },
DAILY_COIN_BOX_NOT_FOUND: { code: 50038, simStr: '未找到该宝箱' },
DAILY_COIN_BOX_CANNOT_RECEIVE: {code: 50013, simStr: '该宝箱不可领取' },
ACTIVITY_GROUP_SHOP_BUY_CNT_MAX: { code: 50039, simStr: '购买次数超过最大值' },
ACTIVITY_GROUP_SHOP_ITEM_NOT_FOUND: { code: 50040, simStr: '未找到该商品' },
ACTIVITY_GROUP_SHOP_PRICE_ERR: { code: 50041, simStr: '提供的折扣未达到该价格' },
// GM后台相关状态 60000 - 69999
GM_ERR_PASSWORD: { code: 60001, simStr: '账号或密码错误' },
GM_MISS_API: { code: 60002, simStr: '未找到该接口' },
+80
View File
@@ -0,0 +1,80 @@
import BaseModel from './BaseModel';
import { index, getModelForClass, prop, DocumentType } from '@typegoose/typegoose';
import { GroupShopDiscount } from '../domain/activityField/groupShopField';
import { nowSeconds } from '../pubUtils/timeUtil';
export class GroupShopRecord {
@prop({ required: true })
time: number; // 达成时间
@prop({ required: true })
sum: number; // 达成时的总额
@prop({ required: true })
discountId: number; // 达成时的折扣
@prop({ required: true })
discount: number; // 达成时的折扣
@prop({ required: true })
price: number; // 达成时的价格
constructor(curDiscount: GroupShopDiscount) {
this.time = nowSeconds();
if(curDiscount) {
this.sum = curDiscount.sum;
this.discountId = curDiscount.id;
this.discount = curDiscount.discount;
this.price = curDiscount.price;
}
}
}
/**
* 活动系统 - 团购总记录
*/
@index({ activityId: 1 })
export default class Activity_Group_Shop_Rec extends BaseModel {
@prop({ required: true })
activityId: number; // 活动Id
@prop({ required: true })
id: number; // item 唯一id
@prop({ required: true })
gid: number; // 物品id
@prop({ required: true })
sum: number; // 总购买次数
@prop({ required: true, type: GroupShopRecord, _id: false })
records: GroupShopRecord[]; // 记录
public static async findByActivity(activityId: number) {
let result: ActivityGroupShopRecType[] = await ActivityGroupShopRecModel.find({ activityId }).lean();
return result;
}
public static async incBuyCnt(activityId: number, id: number, gid: number, inc: number) {
let result: ActivityGroupShopRecType = await ActivityGroupShopRecModel.findOneAndUpdate(
{ activityId, id }, { $inc: { sum: inc }, $set: { gid } }, { new: true, upsert: true }
).lean();
return result;
}
public static async addRecord(activityId: number, id: number, record: GroupShopRecord) {
let result: ActivityGroupShopRecType = await ActivityGroupShopRecModel.findOneAndUpdate(
{ activityId, id }, { $push: { records: record } }, { new: true, upsert: true }
).lean();
return result;
}
}
export const ActivityGroupShopRecModel = getModelForClass(Activity_Group_Shop_Rec);
export interface ActivityGroupShopRecType extends Pick<DocumentType<Activity_Group_Shop_Rec>, keyof Activity_Group_Shop_Rec> { }
export type ActivityGroupShopRecTypeParam = Partial<ActivityGroupShopRecType>; // 将所有字段变成可选项
+86
View File
@@ -0,0 +1,86 @@
import BaseModel from './BaseModel';
import { index, getModelForClass, prop, DocumentType } from '@typegoose/typegoose';
import { nowSeconds } from '../pubUtils/timeUtil';
import { GroupShopDiscount } from '../domain/activityField/groupShopField';
/**
* 活动系统 - 团购玩家记录
*/
@index({ activityId: 1 })
@index({ activityId: 1, roleId: 1 })
@index({ activityId: 1, roleId: 1, id: 1, discountId: 1 })
export class GroupShopBuyRecord {
@prop({ required: true })
time: number; // 购买时间
@prop({ required: true })
sum: number; // 达成时的总额
@prop({ required: true })
discountId: number; // 达成时的折扣
@prop({ required: true })
discount: number; // 达成时的折扣
@prop({ required: true })
price: number; // 达成时的价格
@prop({ required: true })
buyCnt: number; // 购买次数
@prop({ required: true })
refundPrice: number; // 退费价格
constructor(curDiscount: GroupShopDiscount, buyCnt: number) {
this.time = nowSeconds();
if(curDiscount) {
this.sum = curDiscount.sum;
this.discountId = curDiscount.id;
this.discount = curDiscount.discount;
this.price = curDiscount.price;
}
this.buyCnt = buyCnt;
this.refundPrice = 0;
}
}
export default class Activity_Group_Shop_User_Rec extends BaseModel {
@prop({ required: true })
activityId: number; // 活动Id
@prop({ required: true })
roleId: string; // 玩家Id
@prop({ required: true })
id: number; // 唯一id
@prop({ required: true })
gid: number; // 物品id
@prop({ required: true })
buyCnt: number; // 购买次数
@prop({ required: true, type: GroupShopBuyRecord, _id: false })
records: GroupShopBuyRecord[]; // 购买次数
public static async findByActivityAndRoleId(activityId: number, roleId: string) {
let result: ActivityGroupShopUserRecType[] = await ActivityGroupShopUserRecModel.find({ roleId, activityId }).lean();
return result;
}
public static async incBuyCnt(activityId: number, roleId: string, id: number, gid: number, inc: number, record: GroupShopBuyRecord) {
let result: ActivityGroupShopUserRecType = await ActivityGroupShopUserRecModel.findOneAndUpdate(
{ roleId, activityId, id }, { $inc: { buyCnt: inc }, $setOnInsert: { gid }, $push: { records: record } }, { new: true, upsert: true }
).lean();
return result;
}
}
export const ActivityGroupShopUserRecModel = getModelForClass(Activity_Group_Shop_User_Rec);
export interface ActivityGroupShopUserRecType extends Pick<DocumentType<Activity_Group_Shop_User_Rec>, keyof Activity_Group_Shop_User_Rec> { }
export type ActivityGroupShopUserRecTypeParam = Partial<ActivityGroupShopUserRecType>; // 将所有字段变成可选项
@@ -0,0 +1,174 @@
import { ActivityModelType } from '../../db/Activity';
import { ActivityGroupShopRecType } from '../../db/ActivityGroupShopRec';
import { ActivityGroupShopUserRecType } from '../../db/ActivityGroupShopUserRec';
import { ActivityBase } from './activityField';
// 数据库
interface GroupShopTimerInDb {
time: number; // 活动开始之后的时间
sum: number; // 如果次数不足sum次则强行设成sum次
}
interface GroupShopDiscountInDb {
id: number; // 折扣id
sum: number; // 累计购买次数
discount: number; // 显示折扣
price: number; // 真实价格
}
interface GroupShopItemInDb {
id: number; // 唯一id
gid: number; // 物品id
count: number; // 一次购买能购买多少
max: number; // 单人可以购买多少次
price: number; // 无折扣单价
discount: GroupShopDiscountInDb[];
timers: GroupShopTimerInDb[]; // 定时器
}
interface GroupShopInDb {
items: GroupShopItemInDb[];
}
// 数据
class GroupShopTimer {
time: number; // 活动开始之后的时间
itemId: number; // items唯一id
sum: number; // 如果次数不足sum次则强行设成sum次
constructor(id: number, data: GroupShopTimerInDb) {
this.time = data.time;
this.sum = data.sum;
this.itemId = id;
}
}
export class GroupShopDiscount {
id: number = 0; // 折扣唯一id
sum: number = 0; // 累计购买次数
discount: number = 0; // 显示折扣
price: number = 0; // 真实价格
constructor(price: number, data?: GroupShopDiscountInDb) {
if(data) {
this.id = data.id;
this.sum = data.sum;
this.discount = data.discount;
this.price = data.price;
} else {
this.price = price;
}
}
}
class GroupShopItem {
id: number; // 唯一id
gid: number; // 物品id
count: number; // 一次购买能购买多少
max: number; // 单人可以购买多少次
price: number; // 无折扣单价
discount: GroupShopDiscount[] = [];
sum: number = 0; // 总价格
curDiscount: GroupShopDiscount;
hasBoughtCnt: number = 0; // 玩家购买次数
constructor(item: GroupShopItemInDb) {
this.id = item.id;
this.gid = item.gid;
this.count = item.count;
this.max = item.max;
this.price = item.price;
if(item.discount && item.discount.length > 0) {
for(let discount of item.discount) {
this.discount.push(new GroupShopDiscount(item.price, discount));
}
}
}
setSum(sum: number) {
this.sum = sum;
this.checkDiscountBySum(sum);
}
checkDiscountBySum(sum: number) {
for(let obj of this.discount) {
if(obj.sum > sum) break;
this.curDiscount = new GroupShopDiscount(this.price, obj);
}
}
setPlayerCnt(cnt: number) {
this.hasBoughtCnt += cnt;
}
checkBuyCnt(buyCnt: number) {
return this.hasBoughtCnt + buyCnt <= this.max;
}
getCurDiscount() {
return this.curDiscount? this.curDiscount: new GroupShopDiscount(this.price);
}
}
// 团购活动数据
export class GroupShopData extends ActivityBase {
items: GroupShopItem[] = [];
timer: GroupShopTimer[] = [];
private itemMap: Map<number, number> = new Map(); // id => index
constructor(activityData: ActivityModelType, createTime: number, serverTime: number) {
super(activityData, createTime, serverTime);
this.initData(activityData.data)
}
public initData(data: string) {
let dataObj: GroupShopInDb = JSON.parse(data);
if(!dataObj.items || dataObj.items.length <= 0) return;
for(let item of dataObj.items) {
this.items.push(new GroupShopItem(item));
this.itemMap.set(item.id, this.items.length - 1);
if(item.timers && item.timers.length > 0) {
for(let timer of item.timers) {
this.timer.push(new GroupShopTimer(item.id, timer));
}
}
}
}
public findItemById(id: number) {
let index = this.itemMap.get(id);
return this.items[index];
}
public setRecords(data: ActivityGroupShopRecType[]) {
for(let { id, sum } of data) {
let item = this.findItemById(id);
if(item) item.setSum(sum);
}
}
public incAllRecord(data: ActivityGroupShopRecType) {
if(!data) return false;
let item = this.findItemById(data.id);
let oldDiscountId = item.getCurDiscount().id;
item.setSum(data.sum);
let newDiscountId = item.getCurDiscount().id;
return oldDiscountId != newDiscountId;
}
public setPlayerRecord(data: ActivityGroupShopUserRecType[]) {
for(let { id, buyCnt } of data) {
let item = this.findItemById(id);
if(item) item.setPlayerCnt(buyCnt);
}
}
public getShowResult() {
return {
...this.getBaseKeys(),
items: this.items,
}
}
}
@@ -250,5 +250,11 @@
"activityType": 46,
"name": "POP_NOTICE",
"string": "打脸公告"
},
{
"id": 49,
"activityType": 49,
"name": "GROUP_SHOP",
"string": "团购"
}
]
+1 -1
View File
@@ -33,6 +33,6 @@
"DEBUG_TIME": 1,
"CHECK_WORD": 1,
"CAN_PAY": 1,
"SKIP_ENCODE": 0,
"SKIP_ENCODE": 1,
"NEED_REBATE": 0
}