团购:基础接口
This commit is contained in:
@@ -0,0 +1,106 @@
|
|||||||
|
import { Application, BackendSession, HandlerService, } from "pinus";
|
||||||
|
import { resResult } from "../../../pubUtils/util";
|
||||||
|
import { STATUS, ITEM_CHANGE_REASON, GROUP_SHOP_PRICE_STATUS, PUSH_ROUTE, } from "../../../consts";
|
||||||
|
import { getGroupShopData, getGroupShopDataShow, getGroupShopPriceStatus } from "../../../services/activity/groupShopService";
|
||||||
|
import { addItems, getGoldObject, handleCost } from "../../../services/role/rewardService";
|
||||||
|
import { ActivityGroupShopUserRecModel, GroupShopBuyRecord } from "../../../db/ActivityGroupShopUserRec";
|
||||||
|
import { ActivityGroupShopRecModel, GroupShopRecord } from "../../../db/ActivityGroupShopRec";
|
||||||
|
import { pick } from "underscore";
|
||||||
|
import { addRoleToGroupShopChannel, leaveGroupShopChannel } from "../../../services/chatChannelService";
|
||||||
|
import { sendMessageToGroupShopWithSuc } from "../../../services/pushService";
|
||||||
|
|
||||||
|
export default function (app: Application) {
|
||||||
|
new HandlerService(app, {});
|
||||||
|
return new GroupShopHandler(app);
|
||||||
|
}
|
||||||
|
|
||||||
|
export class GroupShopHandler {
|
||||||
|
constructor(private app: Application) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 1. 进入团购主页面
|
||||||
|
* @param {{}} msg
|
||||||
|
* @param {BackendSession} session
|
||||||
|
* @memberof GroupShopHandler
|
||||||
|
*/
|
||||||
|
async getGroupShopPage(msg: { activityId: number }, session: BackendSession) {
|
||||||
|
const { activityId } = msg;
|
||||||
|
const roleId: string = session.get('roleId');
|
||||||
|
const sid: string = session.get('sid');
|
||||||
|
|
||||||
|
let playerData = await getGroupShopDataShow(activityId, roleId);
|
||||||
|
if (!playerData) {
|
||||||
|
return resResult(STATUS.ACTIVITY_MISSING);
|
||||||
|
}
|
||||||
|
await addRoleToGroupShopChannel(roleId, sid);
|
||||||
|
|
||||||
|
return resResult(STATUS.SUCCESS, { playerData });
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 2. 离开团购主页面
|
||||||
|
* @param {{}} msg
|
||||||
|
* @param {BackendSession} session
|
||||||
|
* @memberof GroupShopHandler
|
||||||
|
*/
|
||||||
|
async leaveGroupShopPage(msg: { activityId: number }, session: BackendSession) {
|
||||||
|
const roleId: string = session.get('roleId');
|
||||||
|
const sid: string = session.get('sid');
|
||||||
|
|
||||||
|
await leaveGroupShopChannel(roleId, sid)
|
||||||
|
return resResult(STATUS.SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 3. 购买
|
||||||
|
* @param {{}} msg
|
||||||
|
* @param {BackendSession} session
|
||||||
|
* @memberof GroupShopHandler
|
||||||
|
*/
|
||||||
|
async buy(msg: { activityId: number, price: number, id: number, buyCnt: number }, session: BackendSession) {
|
||||||
|
const { activityId, price: clientPrice, id, buyCnt } = msg;
|
||||||
|
const roleId: string = session.get('roleId');
|
||||||
|
const roleName: string = session.get('roleName');
|
||||||
|
const sid: string = session.get('sid');
|
||||||
|
|
||||||
|
let playerData = await getGroupShopData(activityId, roleId);
|
||||||
|
if (!playerData) return resResult(STATUS.ACTIVITY_MISSING);
|
||||||
|
|
||||||
|
let item = playerData.findItemById(id);
|
||||||
|
if (!item) return resResult(STATUS.ACTIVITY_GROUP_SHOP_ITEM_NOT_FOUND);
|
||||||
|
if(!item.checkBuyCnt(buyCnt)) return resResult(STATUS.ACTIVITY_GROUP_SHOP_BUY_CNT_MAX);
|
||||||
|
|
||||||
|
let curDiscount = item.getCurDiscount();
|
||||||
|
let priceStatus = getGroupShopPriceStatus(clientPrice, curDiscount.price);
|
||||||
|
if(priceStatus == GROUP_SHOP_PRICE_STATUS.NOT_ENOUGH) return resResult(STATUS.ACTIVITY_GROUP_SHOP_PRICE_ERR);
|
||||||
|
let cost = [getGoldObject(curDiscount.price)];
|
||||||
|
let result = await handleCost(roleId, sid, cost, ITEM_CHANGE_REASON.ACT_GROUP_SHOP_BUY);
|
||||||
|
if(!result) return resResult(STATUS.BATTLE_GOLD_NOT_ENOUGH);
|
||||||
|
|
||||||
|
// 玩家添加次数
|
||||||
|
let playerRecord = await ActivityGroupShopUserRecModel.incBuyCnt(activityId, roleId, id, item.gid, buyCnt, new GroupShopBuyRecord(curDiscount, buyCnt));
|
||||||
|
playerData.setPlayerRecord([playerRecord]);
|
||||||
|
// 全服添加次数
|
||||||
|
let serverRecord = await ActivityGroupShopRecModel.incBuyCnt(activityId, id, item.gid, buyCnt);
|
||||||
|
let isRankUp = playerData.incAllRecord(serverRecord);
|
||||||
|
|
||||||
|
item = playerData.findItemById(id);
|
||||||
|
let nextDiscount = item.getCurDiscount();
|
||||||
|
if(isRankUp) {
|
||||||
|
await ActivityGroupShopRecModel.addRecord(activityId, id, new GroupShopRecord(nextDiscount));
|
||||||
|
// 推送频道
|
||||||
|
await sendMessageToGroupShopWithSuc(PUSH_ROUTE.GROUP_SHOP_UPDATE, { activityId, id, curDiscount: nextDiscount });
|
||||||
|
}
|
||||||
|
let reward = [{ id: item.gid, count: item.count * buyCnt }];
|
||||||
|
let goods = await addItems(roleId, roleName, sid, reward, ITEM_CHANGE_REASON.ACT_GROUP_SHOP_BUY);
|
||||||
|
|
||||||
|
return resResult(STATUS.SUCCESS, {
|
||||||
|
curItem: pick(item, ['id', 'gid', 'sum', 'hasBoughtCnt']),
|
||||||
|
goods,
|
||||||
|
status: priceStatus,
|
||||||
|
oldDiscount: curDiscount,
|
||||||
|
nextDiscount
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,7 +11,7 @@ import { COM_BTL_QUALITY, HERO_SELECT, DEBUG_MAGIC_WORD, REDIS_KEY, TASK_TYPE, E
|
|||||||
import { nowSeconds, getZeroPoint } from '../../../pubUtils/timeUtil';
|
import { nowSeconds, getZeroPoint } from '../../../pubUtils/timeUtil';
|
||||||
import { rmRoleFromQueue, roleLeave, getRoleOnlineInfo, roleLogin, getOnlineRoleByUserCode } from '../../../services/redisService';
|
import { rmRoleFromQueue, roleLeave, getRoleOnlineInfo, roleLogin, getOnlineRoleByUserCode } from '../../../services/redisService';
|
||||||
|
|
||||||
import { addRoleToGuildChannel, addRoleToSysChannel, addRoleToWorldChannel, leaveGuildAuctionChannel, leaveGuildChannel, leaveSysChannel, leaveWorldAuctionChannel, leaveWorldChannel, recentGuildMsgs, recentPrivateChatInfos, recentSysMsgs, recentWorldMsgs } from '../../../services/chatService';
|
import { addRoleToGuildChannel, addRoleToSysChannel, addRoleToWorldChannel, leaveGroupShopChannel, leaveGuildAuctionChannel, leaveGuildChannel, leaveSysChannel, leaveWorldAuctionChannel, leaveWorldChannel, recentGuildMsgs, recentPrivateChatInfos, recentSysMsgs, recentWorldMsgs } from '../../../services/chatService';
|
||||||
import { reportOneOnline, savePlayTime } from '../../../services/authenticateService';
|
import { reportOneOnline, savePlayTime } from '../../../services/authenticateService';
|
||||||
import { checkTaskInEntry, } from '../../../services/task/taskService';
|
import { checkTaskInEntry, } from '../../../services/task/taskService';
|
||||||
import { pushData, kickUser, getModuleData, assignServer, leaveServer } from '../../../services/connectorService';
|
import { pushData, kickUser, getModuleData, assignServer, leaveServer } from '../../../services/connectorService';
|
||||||
@@ -205,6 +205,7 @@ export class EntryHandler {
|
|||||||
await leaveGuildChannel(roleId, sid, guildCode);
|
await leaveGuildChannel(roleId, sid, guildCode);
|
||||||
await leaveGuildAuctionChannel(roleId, sid, guildCode);
|
await leaveGuildAuctionChannel(roleId, sid, guildCode);
|
||||||
await leaveWorldAuctionChannel(roleId, sid, serverId);
|
await leaveWorldAuctionChannel(roleId, sid, serverId);
|
||||||
|
await leaveGroupShopChannel(roleId, sid);
|
||||||
RoleModel.updateRoleInfo(roleId, { quitTime: nowSeconds() });
|
RoleModel.updateRoleInfo(roleId, { quitTime: nowSeconds() });
|
||||||
// if(teamCode) { // 如果有寻宝中的队伍,那么等于战败
|
// if(teamCode) { // 如果有寻宝中的队伍,那么等于战败
|
||||||
// setComBtlOnUserLeave(roleId, teamCode)
|
// setComBtlOnUserLeave(roleId, teamCode)
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ import { isArray } from 'underscore';
|
|||||||
import { getGuideGachaData } from './gachaService';
|
import { getGuideGachaData } from './gachaService';
|
||||||
import { getPopNoticeData } from './popNoticeService';
|
import { getPopNoticeData } from './popNoticeService';
|
||||||
import { _getActivities, _getActivitiesByServerId, _getActivitiesByType, _getActivityById } from './activityRemoteService';
|
import { _getActivities, _getActivitiesByServerId, _getActivitiesByType, _getActivityById } from './activityRemoteService';
|
||||||
|
import { getGroupShopDataShow } from './groupShopService';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取活动数据
|
* 获取活动数据
|
||||||
@@ -222,6 +223,11 @@ export async function getActivity(serverId: number, roleId: string, guildCode: s
|
|||||||
activityData = await getPopNoticeData(serverId, activityId, roleId);
|
activityData = await getPopNoticeData(serverId, activityId, roleId);
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
case ACTIVITY_TYPE.GROUP_SHOP:
|
||||||
|
{
|
||||||
|
activityData = await getGroupShopDataShow(activityId, roleId);
|
||||||
|
break
|
||||||
|
}
|
||||||
default: {
|
default: {
|
||||||
console.log('未知活动类型.........', activityType)
|
console.log('未知活动类型.........', activityType)
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -0,0 +1,41 @@
|
|||||||
|
import { GROUP_SHOP_PRICE_STATUS } from "../../consts";
|
||||||
|
import { ActivityGroupShopRecModel } from "../../db/ActivityGroupShopRec";
|
||||||
|
import { ActivityGroupShopUserRecModel } from "../../db/ActivityGroupShopUserRec";
|
||||||
|
import { GroupShopData } from "../../domain/activityField/groupShopField";
|
||||||
|
import { getRoleCreateTime, getServerCreateTime } from "../redisService";
|
||||||
|
import { getActivityById } from "./activityService";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 玩家活动数据
|
||||||
|
*
|
||||||
|
* @param {number} serverId 区Id
|
||||||
|
* @param {number} activityId 活动Id
|
||||||
|
* @param {string} roleId 角色Id
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
export async function getGroupShopData(activityId: number, roleId: string) {
|
||||||
|
let activityData = await getActivityById(activityId);
|
||||||
|
let createTime = await getRoleCreateTime(roleId);
|
||||||
|
|
||||||
|
let playerData = new GroupShopData(activityData, createTime, 0);
|
||||||
|
let serverRecords = await ActivityGroupShopRecModel.findByActivity(activityId);
|
||||||
|
playerData.setRecords(serverRecords);
|
||||||
|
let playerRecords = await ActivityGroupShopUserRecModel.findByActivityAndRoleId(activityId, roleId);
|
||||||
|
playerData.setPlayerRecord(playerRecords);
|
||||||
|
|
||||||
|
return playerData;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getGroupShopDataShow(activityId: number, roleId: string) {
|
||||||
|
let playerData = await getGroupShopData(activityId, roleId);
|
||||||
|
if(playerData && playerData.canShow && playerData.canShow()) {
|
||||||
|
return playerData.getShowResult();
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getGroupShopPriceStatus(clientPrice: number, price: number) {
|
||||||
|
if(clientPrice == price) return GROUP_SHOP_PRICE_STATUS.NORMAL;
|
||||||
|
if(clientPrice < price) return GROUP_SHOP_PRICE_STATUS.NOT_ENOUGH;
|
||||||
|
return GROUP_SHOP_PRICE_STATUS.OVER;
|
||||||
|
}
|
||||||
@@ -56,6 +56,11 @@ export async function addRoleToWorldAuctionChannel(roleId: string, sid: string,
|
|||||||
await addRoleToChannel(roomId, roleId, sid);
|
await addRoleToChannel(roomId, roleId, sid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function addRoleToGroupShopChannel(roleId: string, sid: string) {
|
||||||
|
const roomId = groupRoomId(CHANNEL_PREFIX.GROUP_SHOP);
|
||||||
|
await addRoleToChannel(roomId, roleId, sid);
|
||||||
|
}
|
||||||
|
|
||||||
async function leaveChannel(roomId: string, roleId: string, sid: string) {
|
async function leaveChannel(roomId: string, roleId: string, sid: string) {
|
||||||
const channelSid = await channelServer(roomId);
|
const channelSid = await channelServer(roomId);
|
||||||
await pinus.app.rpc.chat.chatRemote.leaveChannel.toServer(channelSid, roomId, roleId, sid);
|
await pinus.app.rpc.chat.chatRemote.leaveChannel.toServer(channelSid, roomId, roleId, sid);
|
||||||
@@ -86,6 +91,11 @@ export async function leaveWorldAuctionChannel(roleId: string, sid: string, serv
|
|||||||
await leaveChannel(roomId, roleId, sid);
|
await leaveChannel(roomId, roleId, sid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function leaveGroupShopChannel(roleId: string, sid: string) {
|
||||||
|
const roomId = groupRoomId(CHANNEL_PREFIX.GROUP_SHOP);
|
||||||
|
await leaveChannel(roomId, roleId, sid);
|
||||||
|
}
|
||||||
|
|
||||||
export async function leaveGuildChannel(roleId: string, sid: string, guildCode: string) {
|
export async function leaveGuildChannel(roleId: string, sid: string, guildCode: string) {
|
||||||
if (!guildCode) return;
|
if (!guildCode) return;
|
||||||
const roomId = groupRoomId(CHANNEL_PREFIX.GUILD, guildCode);
|
const roomId = groupRoomId(CHANNEL_PREFIX.GUILD, guildCode);
|
||||||
@@ -122,6 +132,12 @@ export async function getWorldAuctionChannelSid(serverId: number) {
|
|||||||
return channelSid;
|
return channelSid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function getGroupShopSid() {
|
||||||
|
const roomId = groupRoomId(CHANNEL_PREFIX.GROUP_SHOP);
|
||||||
|
const channelSid = await channelServer(roomId);
|
||||||
|
return channelSid;
|
||||||
|
}
|
||||||
|
|
||||||
async function delChannel(roomId: string) {
|
async function delChannel(roomId: string) {
|
||||||
const channelSid = await channelServer(roomId);
|
const channelSid = await channelServer(roomId);
|
||||||
await pinus.app.rpc.chat.chatRemote.deleteChannel.toServer(channelSid, roomId);
|
await pinus.app.rpc.chat.chatRemote.deleteChannel.toServer(channelSid, roomId);
|
||||||
|
|||||||
@@ -38,8 +38,8 @@ export function privateRoomId(roleId: string, targetRoleId: string) {
|
|||||||
* @param {string} channelId
|
* @param {string} channelId
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export function groupRoomId(channel: string, channelId: string | number) {
|
export function groupRoomId(channel: string, channelId?: string | number) {
|
||||||
return `${channel}_${channelId}`;
|
return channelId?`${channel}_${channelId}`: `${channel}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function msgCounterName(roomId: string) {
|
function msgCounterName(roomId: string) {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { Channel, pinus } from "pinus";
|
import { Channel, pinus } from "pinus";
|
||||||
import { CHANNEL_PREFIX, PUSH_BATCH, PUSH_INTERVAL, PUSH_ROUTE, STATUS } from "../consts";
|
import { CHANNEL_PREFIX, PUSH_BATCH, PUSH_INTERVAL, PUSH_ROUTE, STATUS } from "../consts";
|
||||||
import { genCode, resResult } from "../pubUtils/util";
|
import { genCode, resResult } from "../pubUtils/util";
|
||||||
import { getCityChannelSid, getGuildChannelSid, getWorldChannelSid, groupRoomId } from "./chatService";
|
import { getCityChannelSid, getGuildChannelSid, getWorldChannelSid, groupRoomId, getGroupShopSid } from "./chatService";
|
||||||
import { getAllOnlineRoles, getRoleOnlineInfo } from "./redisService";
|
import { getAllOnlineRoles, getRoleOnlineInfo } from "./redisService";
|
||||||
import { errlogger, infologger } from '../util/logger';
|
import { errlogger, infologger } from '../util/logger';
|
||||||
import { MsgEncrypt } from "../pubUtils/sysUtil";
|
import { MsgEncrypt } from "../pubUtils/sysUtil";
|
||||||
@@ -64,6 +64,12 @@ export async function sendMessageToCity(cityId: number, route: string, data: any
|
|||||||
await pinus.app.rpc.chat.chatRemote.pushMessage.toServer(channelSid, roomId, route, data);
|
await pinus.app.rpc.chat.chatRemote.pushMessage.toServer(channelSid, roomId, route, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function sendMessageToGroupShopWithSuc(route: string, data: any) {
|
||||||
|
let channelSid = await getGroupShopSid();
|
||||||
|
let roomId = groupRoomId(CHANNEL_PREFIX.GROUP_SHOP);
|
||||||
|
await pinus.app.rpc.chat.chatRemote.pushMessage.toServer(channelSid, roomId, route, resResult(STATUS.SUCCESS, data));
|
||||||
|
}
|
||||||
|
|
||||||
export async function sendMessageToUserWithSuc(roleId: string, route: string, data: any, sid?: string) {
|
export async function sendMessageToUserWithSuc(roleId: string, route: string, data: any, sid?: string) {
|
||||||
await sendMessageToUser(roleId, route, resResult(STATUS.SUCCESS, data), sid);
|
await sendMessageToUser(roleId, route, resResult(STATUS.SUCCESS, data), sid);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,6 +59,7 @@ export enum ACTIVITY_TYPE {
|
|||||||
SHOP = 44, // 限时商店
|
SHOP = 44, // 限时商店
|
||||||
GUIDE_GACHA = 45, // 500抽
|
GUIDE_GACHA = 45, // 500抽
|
||||||
POP_NOTICE = 46, // 打脸公告
|
POP_NOTICE = 46, // 打脸公告
|
||||||
|
GROUP_SHOP = 49, // 团购
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -240,4 +241,10 @@ export enum POP_NOTICE_TIME_SHOW_TYPE {
|
|||||||
READ_STR = 1, // 读time字段字符串
|
READ_STR = 1, // 读time字段字符串
|
||||||
READ_COUNTDOWN = 2, // 读倒计时
|
READ_COUNTDOWN = 2, // 读倒计时
|
||||||
NO = 3, // 不显示
|
NO = 3, // 不显示
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum GROUP_SHOP_PRICE_STATUS {
|
||||||
|
NOT_ENOUGH = 0, // 客户端的价格不足当前价格
|
||||||
|
NORMAL = 1, // 正好
|
||||||
|
OVER = 2, // 客户端的价格高于当前价格
|
||||||
}
|
}
|
||||||
@@ -21,6 +21,7 @@ export const CHANNEL_PREFIX = {
|
|||||||
CITY: 'city', // 军团活动,诸侯混战,按城池分channel
|
CITY: 'city', // 军团活动,诸侯混战,按城池分channel
|
||||||
GUILD_AUCTION: 'g_auction', // 军团拍卖
|
GUILD_AUCTION: 'g_auction', // 军团拍卖
|
||||||
WORLD_AUCTION: 'w_auction', // 军团拍卖
|
WORLD_AUCTION: 'w_auction', // 军团拍卖
|
||||||
|
GROUP_SHOP: 'groupShop', // 团购页面
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getChannelType = function(prefix: string) {
|
export const getChannelType = function(prefix: string) {
|
||||||
@@ -164,4 +165,5 @@ export const PUSH_ROUTE = {
|
|||||||
LADDER_CHECK_STOP: 'onLadderCheckStop',
|
LADDER_CHECK_STOP: 'onLadderCheckStop',
|
||||||
LADDER_BATTLE_STOP: 'onLadderBattleStop',
|
LADDER_BATTLE_STOP: 'onLadderBattleStop',
|
||||||
LADDER_RANK_UPDATE: 'onLadderRankUpdate',
|
LADDER_RANK_UPDATE: 'onLadderRankUpdate',
|
||||||
|
GROUP_SHOP_UPDATE: 'onGroupShopUpdate',
|
||||||
}
|
}
|
||||||
@@ -1041,6 +1041,7 @@ export enum ITEM_CHANGE_REASON {
|
|||||||
USE_VOUCHER = 150, // 使用代金券
|
USE_VOUCHER = 150, // 使用代金券
|
||||||
LADDER_BUY_CNT = 151, // 名将擂台购买次数
|
LADDER_BUY_CNT = 151, // 名将擂台购买次数
|
||||||
LADDER_BATTLE_REWARD = 152, // 名将擂台关卡奖励
|
LADDER_BATTLE_REWARD = 152, // 名将擂台关卡奖励
|
||||||
|
ACT_GROUP_SHOP_BUY = 153, // 团购
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum TA_EVENT {
|
export enum TA_EVENT {
|
||||||
|
|||||||
@@ -504,6 +504,11 @@ export const STATUS = {
|
|||||||
ACTIVITY_POP_UP_MUST_BUY: { code: 50037, simStr: '该礼包必须购买' },
|
ACTIVITY_POP_UP_MUST_BUY: { code: 50037, simStr: '该礼包必须购买' },
|
||||||
DAILY_COIN_BOX_NOT_FOUND: { code: 50038, simStr: '未找到该宝箱' },
|
DAILY_COIN_BOX_NOT_FOUND: { code: 50038, simStr: '未找到该宝箱' },
|
||||||
DAILY_COIN_BOX_CANNOT_RECEIVE: {code: 50013, 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后台相关状态 60000 - 69999
|
||||||
GM_ERR_PASSWORD: { code: 60001, simStr: '账号或密码错误' },
|
GM_ERR_PASSWORD: { code: 60001, simStr: '账号或密码错误' },
|
||||||
GM_MISS_API: { code: 60002, simStr: '未找到该接口' },
|
GM_MISS_API: { code: 60002, simStr: '未找到该接口' },
|
||||||
|
|||||||
@@ -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>; // 将所有字段变成可选项
|
||||||
@@ -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,
|
"activityType": 46,
|
||||||
"name": "POP_NOTICE",
|
"name": "POP_NOTICE",
|
||||||
"string": "打脸公告"
|
"string": "打脸公告"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 49,
|
||||||
|
"activityType": 49,
|
||||||
|
"name": "GROUP_SHOP",
|
||||||
|
"string": "团购"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -33,6 +33,6 @@
|
|||||||
"DEBUG_TIME": 1,
|
"DEBUG_TIME": 1,
|
||||||
"CHECK_WORD": 1,
|
"CHECK_WORD": 1,
|
||||||
"CAN_PAY": 1,
|
"CAN_PAY": 1,
|
||||||
"SKIP_ENCODE": 0,
|
"SKIP_ENCODE": 1,
|
||||||
"NEED_REBATE": 0
|
"NEED_REBATE": 0
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user