Merge branch 'feature/backend'

This commit is contained in:
luying
2021-12-18 13:14:15 +08:00
125 changed files with 9262 additions and 2385 deletions

View File

@@ -5,9 +5,17 @@ export enum MAIL_STATUS {
RECEIVED = 2,
};
export const MAIL_TEM_TYPE = {
GAMEMAIL: 1,
GMTYPE: 2,
export enum MAIL_TIME_TYPE {
IMMEDIATE = 1, // 即时邮件
DELAY = 2, // 延时邮件
CIRCLE = 3, // 循环邮件
};
export enum GM_MAIL_STATUS {
CREATE = 0, // 创建
PASS = 1, // 审批通过
NOT_PASS = -1, // 审批不通过
};
export enum GM_MAIL_TYPE {
@@ -43,4 +51,5 @@ export enum MAIL_TYPE {
TREAT_GUILD_INFO = 22, // 月卡奖品
};
export const SEND_NAME = '系统';
export const SEND_NAME = '系统';
export const SEND_TITLE = '系统邮件';

View File

@@ -21,6 +21,7 @@ export const TEEN_DAILY_MAX_TIME = 1.5 * 60 * 60; // 未成年人工作日每天
export const GUEST_DAY = 15; // 同一设备15天内不得重复体验游客模式
export const REFRESH_TIME = 5; // 统一一天刷新时间
export const REF_CIRCLE_MAIL_TIME = 3; // 统一一天刷新定期邮件时间
export const PUSH_BATCH = 100; // 推送分批人数
export const PUSH_INTERVAL = 5 * 1000; // 分批时间5秒一批
export enum TIME_OUTPUT_TYPE {
@@ -47,6 +48,7 @@ export const COUNTER = {
NOTICE: { name: 'notice', def: 1 },
GIFT_CODE: { name: 'giftCode', def: 1 },
PVP_SEASON_NUM: { name: 'pvpSeason', def: 1 },
REGION: { name: 'region', def: 1 }
};
export const DEFAULT_HEROES = [19, 53,];
@@ -695,7 +697,14 @@ export enum GACHA_CONTENT_TYPE {
export const GACHA_OCCUPY_HID = 9999; // 抽卡里占位的武将
export enum MARQUEE_TYPE {
// 跑马灯显示类型
export enum MARQUEE_SHOW_TYPE {
ONCE = 1, // 一次性
CIRCLE = 2, // 循环
}
// 推送时间类型
export enum MARQUEE_TIME_TYPE {
INSTANT = 1, // 发送后立刻推送
SCHEDULE = 2, // 定时器
}
@@ -705,11 +714,12 @@ export enum SERVER_STATUS {
HOT = 2, // 火爆
WILL_OPEN = 3, // 即将开启
MAINTENANCE = 4, // 维护中
HIDE = 0, // 隐藏
}
export enum WHITE_LIST_TYPE {
IP = 1, // ip地址
TEL = 2, // 玩家手机
UID = 2, // 玩家
}
// 获取道具类型
@@ -748,6 +758,25 @@ export enum THINKING_DATA_MODE_LIST {
}
export let THINKING_DATA_MODE = THINKING_DATA_MODE_LIST.DEBUG;
export enum BLOCK_TYPE {
NOT = 0,
BAN = 1,
BLOCK = 2,
}
export enum SERVER_TIMER {
FIVE_HALF = 1, // 5:30
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, // 通码,一条码能被多人使用,每个人只能用一次
}
export enum ITEM_CHANGE_REASON {
DEBUG = 0, // debug接口、后台
RENAME = 1, // 重命名

View File

@@ -10,6 +10,8 @@ export const STATUS = {
SERVER_MAINTENANCE: { code: 7, simStr: '服务器维护中' },
VERSION_ERR: { code: 8, simStr: '版本号太低,请更新' },
BLOCK_WORDS: { code: 9, simStr: '内容有不合法词汇' },
BLOCKED: { code: 10, simStr: '您已被封禁' },
BANNED: { code: 11, simStr: '您已被禁言' },
GLOBAL_ERR: { code: 1003, simStr: '服务器内部错误' },
// http请求
REQUEST_TIME_OUT: { code: 2000, simStr: '请求超时' },
@@ -35,6 +37,7 @@ export const STATUS = {
ROLE_EXIST: { code: 10017, simStr: '账号已存在' },
CHANNEL_ERR: { code: 10018, simStr: '无此渠道' },
VALIDATE_ERR: { code: 10019, simStr: '渠道校验错误' },
SERVER_STOP_REGISTER: { code: 10020, simStr: '服务器已停止注册' },
// 战斗相关状态 20000 - 29999
// 战斗通用 20000 - 20099
BATTLE_MISS_INFO: { code: 20001, simStr: '缺少关卡信息' },
@@ -184,6 +187,7 @@ export const STATUS = {
HAS_RECEIVE_WISH_GOOD: { code: 20930, simStr: '玩家已经收到许愿物品' },
NOT_WISH_THE_QUALITY_GOODS: { code: 20931, simStr: '不能够许愿该品质的物品' },
GUILD_PAY_CONDITION: { code: 20932, simStr: '充值金额不足' },
GUILD_USER_IS_LEADER: { code: 20933, simStr: '该成员已经是团长' },
GUILD_SCRIPT_IS_OPENED_TODAY: { code: 20950, simStr: '今日已开启过演武场' },
GUILD_SCRIPT_NOT_OPENED: { code: 20951, simStr: '演武场未开启' },
@@ -241,6 +245,7 @@ export const STATUS = {
ROLE_IS_NOT_INIT: { code: 30006, simStr: '玩家未初始化' },
AP_BUY_TIMES_LACK: { code: 30007, simStr: '购买次数不足' },
CONSUME_TYPE_ERR: { code: 30008, simStr: '道具类型错误' },
DB_DATA_NOT_FOUND: { code: 30009, simStr: '数据库数据未找到' },
// 武将养成通用 30100 - 30199
@@ -437,6 +442,8 @@ export const STATUS = {
GM_ACTIVITY_NOT_FIT_GROUP_TYPE: { code: 60021, simStr: '该活动不满足该活动组类型' },
GM_MARQUEE_ERR: { code: 60022, simStr: '跑马灯定时设置错误' },
GM_MARQUEE_CANCEL_ERR: { code: 60023, simStr: '取消失败' },
GM_MAIL_NOT_FOUND: { code: 60024, simStr: '未找到该邮件' },
GM_MAIL_HAS_SENT: { code: 60025, simStr: '邮件已经审批过了' },
// 支付相关状态 70000 - 79999
NO_PRODUCT_ID: { code: 70001, simStr: '无效商品' },
NO_PAY_TYPE: { code: 70002, simStr: '无效支付类型' },

View File

@@ -37,7 +37,8 @@ export default class AccuseRec extends BaseModel {
}
private static getSearchObj(form: {}) {
let searchObj = form;
let searchObj = {};
console.log(form);
return searchObj
}
@@ -52,6 +53,7 @@ export default class AccuseRec extends BaseModel {
sort[sortField] = -1;
}
}
console.log('page', page, 'pageSize', pageSize, 'sort', sort)
const result: AccuseRecType[] = await AccuseRecModel.find(searchObj).limit(pageSize).skip((page - 1) * pageSize).sort(sort).lean({ getters: true, virtuals: true });
return result;

View File

@@ -107,6 +107,21 @@ export default class Activity extends BaseModel {
return result;
}
public static async findAllActivities() {
let all: ActivityModelType[] = [];
let createdAt;
for(let i = 0; i < 9999; i++) { // 防死循环
let condition = {};
if(createdAt) condition['createdAt'] = { $gt: createdAt }
let cur: ActivityModelType[] = await ActivityModel.find(condition).limit(1000).sort({ createdAt: 1 }).lean();
if(cur.length == 0) break;
createdAt = cur[cur.length - 1].createdAt;
all.push(...cur);
}
return all;
}
//查询
public static async findByCondition(page: number, pageSize: number, sortField: string = 'updatedAt', sortOrder: string = 'descend', type: number = 0, groupId: number = 0, current: boolean = false, activityId: number = 0) {
let searchObj = {};

View File

@@ -107,6 +107,12 @@ export default class Activity_Group extends BaseModel {
return result;
}
//获取所有活动组
public static async findAllActivityGroup() {
let result: ActivityGroupModelType[] = await ActivityGroupModel.find({}).lean();
return result;
}
//删除组
public static async deleteGroup(groupId: number) {
let result = await ActivityGroupModel.deleteMany({ groupId });
@@ -138,6 +144,20 @@ export default class Activity_Group extends BaseModel {
const result = await ActivityGroupModel.count(searchObj);
return result;
}
public static async findAllActivityGroups() {
let all: ActivityGroupModelType[] = [];
let createdAt;
for(let i = 0; i < 9999; i++) { // 防死循环
let condition = {};
if(createdAt) condition['createdAt'] = { $gt: createdAt }
let cur = await ActivityGroupModel.find(condition).limit(1000).sort({ createdAt: 1 }).lean();
if(cur.length == 0) break;
createdAt = cur[cur.length - 1].createdAt;
all.push(...cur);
}
return all;
}
}
export const ActivityGroupModel = getModelForClass(Activity_Group);

View File

@@ -89,6 +89,19 @@ export default class Activity_GroupType extends BaseModel {
return result;
}
public static async findAllActivityGroupTypes() {
let all: ActivityGroupTypeInter[] = [];
let createdAt;
for(let i = 0; i < 9999; i++) { // 防死循环
let condition = {};
if(createdAt) condition['createdAt'] = { $gt: createdAt }
let cur: ActivityGroupTypeInter[] = await ActivityGroupTypeModel.find(condition).limit(1000).sort({ createdAt: 1 }).lean();
if(cur.length == 0) break;
createdAt = cur[cur.length - 1].createdAt;
all.push(...cur);
}
return all;
}
}
export const ActivityGroupTypeModel = getModelForClass(Activity_GroupType);

View File

@@ -38,7 +38,7 @@ export default class Api extends BaseModel {
}
export let ApiModel: ReturnModelType<typeof Api, {}> = getModelForClass(Api);
export let ApiModel: ReturnModelType<typeof Api, {}>;
export function loadApiModel(connect: mongoose.Connection) {
ApiModel = getModelForClass(Api, {
existingConnection: connect

40
shared/db/CounterAll.ts Normal file
View File

@@ -0,0 +1,40 @@
import BaseModel from './BaseModel';
import { index, getModelForClass, prop, DocumentType, ReturnModelType, mongoose } from '@typegoose/typegoose';
/**
* 自增 ID
*/
@index({ name: 1 })
export default class CounterAll extends BaseModel {
@prop({ required: true })
name: string;
@prop({ required: true, default: 1 })
seq: number;
public static async getNewCounter(param:{name: string, def: number}, lean = true) {
let {name, def:defaultVal} = param;
let counter: CounterType = await CounterAllModal.findOneAndUpdate({ name }, { $inc: { seq: 1 } }, { new: true, upsert: true }).lean(lean);
if(!counter || (counter&&counter.seq == 1) && defaultVal != 1) {
counter = await CounterAllModal.findOneAndUpdate({ name }, { $set: { seq: defaultVal } }, { new: true, upsert: true }).lean(lean);
}
return counter?.seq;
}
public static async getCounter(param:{name: string, def: number}, lean = true) {
let {name, def:defaultVal} = param;
let counter: CounterType = await CounterAllModal.findOne({ name }).lean(lean);
return counter?.seq||defaultVal;
}
}
export let CounterAllModal: ReturnModelType<typeof CounterAll, {}>;
export function loadCounterModal(connect: mongoose.Connection) {
CounterAllModal = getModelForClass(CounterAll, {
existingConnection: connect
});
}
export interface CounterType extends Pick<DocumentType<CounterAll>, keyof CounterAll>{};

View File

@@ -4,6 +4,7 @@ import { COUNTER } from '../consts';
import { CounterModel } from './Counter';
import { HeroModel } from './Hero';
import { RoleModel } from './Role';
import { SearchEquipParam } from '../domain/backEndField/search';
export class RandSe {
@prop({ required: true })
@@ -193,6 +194,36 @@ export default class Equip extends BaseModel {
return result;
}
private static getSearchObj(form: SearchEquipParam) {
let searchObj = {};
if(form.roleId) searchObj['roleId'] = form.roleId;
if(form.roleName) searchObj['roleName'] = { $regex: new RegExp(form.roleName.toString(), 'i') };
if(form.id) searchObj['id'] = form.id;
return searchObj
}
public static async findByCondition(page: number, pageSize: number, sortField: string = 'updatedAt', sortOrder: string = 'descend', form: SearchEquipParam = {}) {
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: EquipType[] = await EquipModel.find(searchObj).limit(pageSize).skip((page - 1) * pageSize).sort(sort).lean({ getters: true, virtuals: true });
return result;
}
public static async countByCondition(form: SearchEquipParam = {}) {
let searchObj = this.getSearchObj(form);
const result = await EquipModel.count(searchObj);
return result;
}
}
export const EquipModel = getModelForClass(Equip);

View File

@@ -74,7 +74,7 @@ export default class GMGroup extends BaseModel {
}
export let GMGroupModel: ReturnModelType<typeof GMGroup, {}> = getModelForClass(GMGroup);
export let GMGroupModel: ReturnModelType<typeof GMGroup, {}>;
export function loadGMGroupModel(connect: mongoose.Connection) {
GMGroupModel = getModelForClass(GMGroup, {
existingConnection: connect

View File

@@ -2,8 +2,13 @@
* 邮件的模板在GM后台能看到的邮件列表
*/
import BaseModel from './BaseModel';
import { getModelForClass, prop, DocumentType } from '@typegoose/typegoose';
import { nowSeconds } from '../pubUtils/timeUtil';
import { getModelForClass, prop, DocumentType, mongoose, ReturnModelType } from '@typegoose/typegoose';
import { GM_MAIL_STATUS, GM_MAIL_TYPE, MAIL_TIME_TYPE } from '../consts';
import { SearchMailParam } from '../domain/backEndField/search';
import { getCurDay, nowSeconds } from '../pubUtils/timeUtil';
import { GMMail as StategyMail } from './ServerStategy';
import { ServerlistType } from './Serverlist';
import moment = require('moment');
class Reward {
@prop({ required: true })
@@ -12,28 +17,111 @@ class Reward {
count: number;
}
export class Receiver {
@prop({ required: true })
env: string;
@prop({ required: true })
serverId: number;
@prop({ required: true })
roleId?: string;
@prop({ required: true })
roleName?: string;
}
export default class GMMail extends BaseModel {
@prop({ required: false})
hasGoods: boolean; // 有效时间,单位小时
@prop({ required: true, type: Reward, default: [], _id: false })
goods: Reward[];
@prop({ required: true, default: true })
useTempTime: boolean; // 生成邮件是否按照模板时间
timeType: MAIL_TIME_TYPE; // 邮件时间类型
@prop({ required: false})
continueHour: number; // 如果不按模板时间sendTime为生成单独邮件的时候endTime为sendTime+continueHour,单位小时
expire: number; // 有效时间,单位小时
@prop({ required: true })
sendTime: number; // 如果按照模板时间发送时间10位时间戳
startTime: number; // 发送时间,延时邮件使用
@prop({ required: true })
endTime: number; // 如果按照模板时间过期时间10位时间
circleStart: number; // 循环邮件开始循环时间
@prop({ required: true })
circleEnd: number; // 循环邮件结束循环时间
@prop({ required: true })
circleDay: number; // 循环时间每周几0表示每天
@prop({ required: true })
circleHour: string; // 几点发送
@prop({ required: true })
title: string;
@prop({ required: true })
content: string;
@prop({ required: true })
sendName: string;
@prop({ required: true })
mailType: GM_MAIL_TYPE; // 收件人类型
@prop({ required: true, type: Receiver, _id: false })
receivers: Receiver[];
@prop({ required: true })
reason: string; // 原因
@prop({ required: true, default: false })
isSp: boolean; // 特殊邮件
@prop({ required: true, default: 0 })
status: GM_MAIL_STATUS; // 邮件状态
@prop({ required: true })
viewBy: number; // 审核人
@prop({ required: true })
viewAt: Date; // 审核时间
@prop({ required: true })
sendTime: string; // 发送时间
public setByRegionStategy(type: 'openMail'|'circleMail', gmmail: StategyMail, newServer: ServerlistType, uid) {
this.hasGoods = !!gmmail.goods?.length;
this.goods = gmmail.goods;
this.timeType = type == 'openMail'? MAIL_TIME_TYPE.DELAY: MAIL_TIME_TYPE.CIRCLE;
this.expire = gmmail.expire;
if(type == 'openMail') {
this.startTime = nowSeconds();
} else {
this.circleStart = nowSeconds();
this.circleEnd = nowSeconds() + gmmail.circleContinueDay * 24 * 60 * 60;
this.circleDay = gmmail.circleDay;
this.circleHour = gmmail.circleHour;
}
this.title = gmmail.title;
this.content = gmmail.content;
this.sendName = gmmail.sendName;
this.mailType = GM_MAIL_TYPE.SERVER;
this.receivers = [{
env: newServer.env,
serverId: newServer.id
}];
this.reason = gmmail.reason;
this.isSp = gmmail.isSp;
this.status = GM_MAIL_STATUS.PASS;
this.viewBy = uid;
this.viewAt = new Date();
if (type == 'openMail') {
this.sendTime = moment(this.startTime * 1000).format('YYYY-MM-DD HH:mm:ss');
} else {
this.sendTime = (this.circleDay == 0?'每天': '每周'+this.circleDay) + ' ' + this.circleHour;
}
}
public static async addMail(params: GMMailTypeParam, uid = 1) {
const doc = new GMMailModel();
@@ -52,25 +140,21 @@ export default class GMMail extends BaseModel {
return result;
}
public static async getMail(updatedMailAt: number, lean = true) {
const result: GMMailType[] = await GMMailModel.find({ $or: [{updatedAt: { $gte: new Date(updatedMailAt) }}, {sendTime: { $lte: nowSeconds() }}], endTime: { $gte: nowSeconds()} }).lean(lean);
return result;
}
public static async getMails( lean = true) {
const result: GMMailType[] = await GMMailModel.find({ endTime: { $gte: nowSeconds() }}).lean(lean);
return result;
}
private static getSearchObj(form: {_id?: string, content?: string}) {
private static getSearchObj(form: SearchMailParam) {
let searchObj = {};
if(form['_id']) searchObj['_id'] = form._id;
if(form['content']) searchObj['context'] = { $regex: new RegExp(form.content.toString(), 'i') }
if(form.createTimeStart) searchObj['createdAt'] = { $gt: new Date(form.createTimeStart * 1000) };
if(form.createTimeEnd) searchObj['createdAt'] = { $lt: new Date(form.createTimeEnd * 1000) };
if(form.serverId) searchObj['receivers.serverId'] = form.serverId;
if(form.roleId) searchObj['receivers.roleId'] = form.roleId;
if(form.roleName) searchObj['receivers.roleName'] = { $regex: new RegExp(form.roleName.toString(), 'i') }
if(form.status) searchObj['status'] = form.status;
if(form.mailType) searchObj['mailType'] = form.mailType;
if(form.hasGoods != undefined) searchObj['hasGoods'] = form.hasGoods;
if(form.title) searchObj['title'] = { $regex: new RegExp(form.title.toString(), 'i') }
return searchObj
}
public static async findByCondition(page: number, pageSize: number, sortField: string, sortOrder: string, form: {_id?: string, content?: string} = {}) {
public static async findByCondition(page: number, pageSize: number, sortField: string, sortOrder: string, form: SearchMailParam = {}) {
let searchObj = this.getSearchObj(form);
let sort = {};
@@ -86,17 +170,31 @@ export default class GMMail extends BaseModel {
}
public static async countByCondition(form: {_id?: string, content?: string} = {}) {
public static async countByCondition(form: SearchMailParam = {}) {
let searchObj = this.getSearchObj(form);
const result = await GMMailModel.count(searchObj);
return result;
}
public static async findCircleMails(env: string) {
const result: GMMailType[] = await GMMailModel.find({
timeType: MAIL_TIME_TYPE.CIRCLE,
circleStart: { $lt: nowSeconds() }, circleEnd: { $gte: nowSeconds() },
circleDay: { $in: [0, getCurDay(true)] }, 'receivers.env': env,
status: GM_MAIL_STATUS.PASS
});
return result;
}
}
export const GMMailModel = getModelForClass(GMMail);
export let GMMailModel: ReturnModelType<typeof GMMail, {}>;
export function loadGMMailModel(connect: mongoose.Connection) {
GMMailModel = getModelForClass(GMMail, {
existingConnection: connect
});
}
export interface GMMailType extends Pick<DocumentType<GMMail>, keyof GMMail> { };

View File

@@ -28,7 +28,7 @@ export default class GMRecord extends BaseModel {
}
export let GMRecordModel: ReturnModelType<typeof GMRecord, {}> = getModelForClass(GMRecord);
export let GMRecordModel: ReturnModelType<typeof GMRecord, {}>;
export function loadGMRecordModel(connect: mongoose.Connection) {
GMRecordModel = getModelForClass(GMRecord, {
existingConnection: connect

View File

@@ -85,7 +85,7 @@ export default class GMUser extends BaseModel {
}
}
export let GMUserModel: ReturnModelType<typeof GMUser, {}> = getModelForClass(GMUser);
export let GMUserModel: ReturnModelType<typeof GMUser, {}>;
export function loadGMUserModel(connect: mongoose.Connection) {
GMUserModel = getModelForClass(GMUser, {
existingConnection: connect

View File

@@ -32,7 +32,7 @@ export default class GMUserGroup extends BaseModel {
}
}
export let GMUserGroupModel: ReturnModelType<typeof GMUserGroup, {}> = getModelForClass(GMUserGroup);
export let GMUserGroupModel: ReturnModelType<typeof GMUserGroup, {}>;
export function loadGMUserGroupModel(connect: mongoose.Connection) {
GMUserGroupModel = getModelForClass(GMUserGroup, {
existingConnection: connect

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>;

View File

@@ -1,7 +1,24 @@
import BaseModel from './BaseModel';
import { index, getModelForClass, prop, DocumentType, modelOptions, Ref, mongoose } from '@typegoose/typegoose';
import GiftCode, { GiftCodeType } from './GiftCode';
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';
import { SearchGiftCodeDetailParam } from '../domain/backEndField/search';
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,43 +26,101 @@ 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) {
let result: GiftCodeDetailType = await GiftCodeDetailModel.findOne({ code }).populate('giftCode').lean(true);
let result: GiftCodeDetailType = await GiftCodeDetailModel.findOne({ code }).lean(true);
return result;
}
public static async findByGiftCode(giftCode: GiftCodeType) {
let result: GiftCodeDetailType[] = await GiftCodeDetailModel.find({ giftCode: giftCode._id }).lean();
public static async checkHasUsed(roleId: string, id: number) {
let result = await GiftCodeDetailModel.exists({ giftId: id, 'record.roleId': roleId });
return result;
}
public static async increaseUsedNum(code: string) {
let result: GiftCodeDetailType = await GiftCodeDetailModel.findOneAndUpdate({ code }, { $inc: { usedNum: 1 } }, { new: true }).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 generateOne(giftCode: GiftCodeType, code: string, uid = 1 ) {
let result = await GiftCodeDetailModel.insertMany([{ giftCode: giftCode._id, code, usedNum: 0, createdBy: uid, updatedBy: uid }]);
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 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;
}
private static getSearchObj(form: SearchGiftCodeDetailParam) {
let searchObj = {};
if(form.giftId) searchObj['giftId'] = form.giftId;
if (form.giftName != undefined) searchObj['giftName'] = { $regex: new RegExp(form.giftName.toString(), 'i') };
if(form.generateType) searchObj['generateType'] = form.generateType;
if(form.code) searchObj['code'] = form.code;
if(form.roleId) searchObj['record.roleId'] = form.roleId;
if (form.roleName != undefined) searchObj['record.roleName'] = { $regex: new RegExp(form.roleName.toString(), 'i') };
return searchObj
}
public static async findByCondition(page: number, pageSize: number, sortField: string, sortOrder: string, form:SearchGiftCodeDetailParam = {}) {
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: GiftCodeDetailType[] = await GiftCodeDetailModel.find(searchObj, { _id: 0 }).limit(pageSize).skip((page - 1) * pageSize).sort(sort).lean({ getters: true, virtuals: true });
return result;
}
public static async countByCondition(form: SearchGiftCodeDetailParam = {}) {
let searchObj = this.getSearchObj(form);
const result = await GiftCodeDetailModel.count(searchObj);
return result;
}

View File

@@ -5,6 +5,7 @@ import { GUILD_STRUCTURE, GUILD_STATUS, GUILD_PER_PAGE, GUILD_SELECT, REDIS_KEY,
import { getZeroPoint, getZeroPointD, nowSeconds } from '../pubUtils/timeUtil';
import { reduceCe } from '../pubUtils/util';
import { gameData } from '../pubUtils/data';
import { SearchGuildParam } from '../domain/backEndField/search';
class Structure {
@prop({ required: true })
@@ -132,7 +133,7 @@ export default class Guild extends BaseModel {
return result;
}
public static async findByCondition(page: number, showPeopleMax: boolean, name: string, serverId: number) {
public static async getGuildList(page: number, showPeopleMax: boolean, name: string, serverId: number) {
const condition = { status: GUILD_STATUS.RUNNING, serverId };
if(!showPeopleMax) {
condition['isMemberMax'] = false;
@@ -193,6 +194,7 @@ export default class Guild extends BaseModel {
public static async dismiss(code: string, serverId: number) {
const result: GuildType = await GuildModel.findOneAndUpdate({ code, status: GUILD_STATUS.RUNNING, serverId }, { status: GUILD_STATUS.DISMISSED }, { new: true })
.populate('leader', {roleId: 1, _id: 0}, 'Role')
.select('+members').lean();
return result;
}
@@ -277,6 +279,41 @@ export default class Guild extends BaseModel {
const role: RoleType = await GuildModel.findOneAndUpdate({ code, serverId }, { $set: { sdkMark: true } }, { new: true }).select(select).lean({ getters, virtuals: true });
return role;
}
private static getSearchObj(form: SearchGuildParam) {
let searchObj = {};
if (form.serverId) searchObj['serverId'] = form.serverId;
if (form.name) searchObj['name'] = { $regex: new RegExp(form.name.toString(), 'i') };
return searchObj
}
public static async findByCondition(page: number, pageSize: number, sortField: string = 'updatedAt', sortOrder: string = 'descend', form: SearchGuildParam = {}) {
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: GuildType[] = await GuildModel
.find(searchObj).limit(pageSize).skip((page - 1) * pageSize).sort(sort)
.select('-_id -__v -updatedAt +serverId')
.populate('leader', { roleId: 1, roleName: 1, _id: 0 }, 'Role')
.lean({ getters: true, virtuals: true });
return result;
}
public static async countByCondition(form: SearchGuildParam = {}) {
let searchObj = this.getSearchObj(form);
const result = await GuildModel.count(searchObj);
return result;
}
}
export const GuildModel = getModelForClass(Guild);

View File

@@ -57,7 +57,7 @@ export default class HangUpRecord extends BaseModel {
}
public static async updateRec(roleId: string, roleName: string, endLv: number, endTime: Date, needReceiveGoods: Array<{gid:number, count: number}>, lean = true) {
await HangUpRecordModel.findOneAndUpdate({roleId, received: false}, {endLv, endTime, received: true, notReceivedGoods: needReceiveGoods}).lean(lean);
await HangUpRecordModel.updateMany({roleId, received: false}, {endLv, endTime, received: true, notReceivedGoods: needReceiveGoods});
const recDoc = new HangUpRecordModel();
const update = Object.assign(recDoc.toJSON(), {roleId, roleName, startTime: endTime, startLv: endLv});
delete update._id;

View File

@@ -5,6 +5,7 @@ import { CounterModel } from './Counter';
import { COUNTER, EQUIP_TYPE, HERO_CE_RATIO } from '../consts';
import { reduceCe } from '../pubUtils/util';
import Skin from './Skin';
import { SearchHeroParam } from '../domain/backEndField/search';
type CeAttrUpdate = Partial<CeAttrData>;
export class CeAttrData {
@@ -300,20 +301,6 @@ export default class Hero extends BaseModel {
return hero;
}
public static async findByField(field: string, value?: number | string, lean = true) {
let searchObj = {};
if (field != 'all') {
if (field == 'roleName') {
searchObj['roleName'] = { $regex: new RegExp(value.toString(), 'i') }
} else {
searchObj[field] = value;
}
}
//.select('uid tel username')
const user: HeroType[] = await HeroModel.find(searchObj, {_id: 0}).lean(lean);
return user;
}
public static async getAllRank(serverId: number, select?: string, limit = 200) {
let result: HeroType[] = await HeroModel.find({ serverId }, { _id: false }).select(select).limit(limit).sort({ ce: -1, updatedAt: 1 }).lean({ getters: true });
return result;
@@ -328,6 +315,37 @@ export default class Hero extends BaseModel {
let result: HeroType[] = await HeroModel.find({ serverId, hid }, { _id: false }).select(select).limit(limit).lean({ getters: true });
return result;
}
private static getSearchObj(form: SearchHeroParam) {
let searchObj = {};
if(form.roleId) searchObj['roleId'] = form.roleId;
if(form.roleName) searchObj['roleName'] = { $regex: new RegExp(form.roleName.toString(), 'i') };
if(form.hid) searchObj['hid'] = form.hid;
return searchObj
}
public static async findByCondition(page: number, pageSize: number, sortField: string = 'updatedAt', sortOrder: string = 'descend', form: SearchHeroParam = {}) {
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: HeroType[] = await HeroModel.find(searchObj).limit(pageSize).skip((page - 1) * pageSize).sort(sort).lean({ getters: true, virtuals: true });
return result;
}
public static async countByCondition(form: SearchHeroParam = {}) {
let searchObj = this.getSearchObj(form);
const result = await HeroModel.count(searchObj);
return result;
}
}
export const HeroModel = getModelForClass(Hero);

View File

@@ -2,6 +2,7 @@ import BaseModel from './BaseModel';
import { index, getModelForClass, prop, DocumentType, modelOptions } from '@typegoose/typegoose';
import { findIndex } from 'underscore';
import { BAG } from '../pubUtils/dicParam';
import { SearchItemParam } from '../domain/backEndField/search';
// const Transaction = require("mongoose-transactions");
@index({ roleId: 1, id: 1 })
@index({ seqId: 1 })
@@ -101,18 +102,35 @@ export default class Item extends BaseModel {
return result;
}
public static async findByField(field: string, value?: number|string, lean = true) {
private static getSearchObj(form: SearchItemParam) {
let searchObj = {};
if(field != 'all') {
if(field == 'roleName') {
searchObj['roleName'] = { $regex: new RegExp(value.toString(), 'i') }
} else {
searchObj[field] = value;
if (form.roleId) searchObj['roleId'] = form.roleId;
if (form.roleName) searchObj['roleName'] = { $regex: new RegExp(form.roleName.toString(), 'i') };
if (form.id) searchObj['id'] = form.id;
return searchObj
}
public static async findByCondition(page: number, pageSize: number, sortField: string = 'updatedAt', sortOrder: string = 'descend', form: SearchItemParam = {}) {
let searchObj = this.getSearchObj(form);
let sort = {};
if (sortField && sortOrder) {
if (sortOrder == 'ascend') {
sort[sortField] = 1;
} else if (sortOrder == 'descend') {
sort[sortField] = -1;
}
}
//.select('uid tel username')
const user: ItemType[] = await ItemModel.find(searchObj).lean(lean);
return user;
const result: ItemType[] = await ItemModel.find(searchObj).limit(pageSize).skip((page - 1) * pageSize).sort(sort).select('-_id -__v -createdAt -updatedAt').lean({ getters: true, virtuals: true });
return result;
}
public static async countByCondition(form: SearchItemParam = {}) {
let searchObj = this.getSearchObj(form);
const result = await ItemModel.count(searchObj);
return result;
}
}

View File

@@ -1,6 +1,5 @@
import BaseModel from './BaseModel';
import { prop, Ref, mongoose } from '@typegoose/typegoose';
import GMMail from './GMMail';
import { prop } from '@typegoose/typegoose';
class Reward {
@prop({ required: true })
@@ -12,10 +11,10 @@ class Reward {
export default class MailTemp extends BaseModel {
@prop({ required: true })
contentId: number; // dic_email_content.json中的id
gmmailId: string;
@prop({ ref: 'GMMail', type: mongoose.Schema.Types.ObjectId })
mail: Ref<GMMail>;
@prop({ required: true })
contentId: number; // dic_email_content.json中的id
@prop({ required: true })
sendTime: number;
@@ -23,12 +22,15 @@ export default class MailTemp extends BaseModel {
@prop({ required: true })
endTime: number;
@prop({ required: true, type: String, _id: false})
params: string[];
@prop({ required: true })
title: string; // 标题
@prop({ required: true })
sendName: string; // 发件人
@prop({ required: true })
content: string; // 内容
@prop({ required: true })
hasGoods: boolean;

View File

@@ -1,107 +0,0 @@
import BaseModel from './BaseModel';
import { index, getModelForClass, prop, DocumentType, mongoose, Ref } from '@typegoose/typegoose';
import Marquee, { MarqueeType } from './Marquee';
import Notice, { NoticeType } from './Notice';
import GMMail from './GMMail';
import { genCode } from '../pubUtils/util';
import { GMMailType } from './GMMail';
/**
* 开服策略
*/
@index({ id: 1 })
export default class Maintenance extends BaseModel {
@prop({ required: true })
code: string; // 策略唯一标志
@prop({ required: true, type: Number })
serverIds: number[]; // 服务器类型
@prop({ required: true })
isOpen: boolean; // 维护是否使用
@prop({ required: true })
startTime: Date; // 维护开始时间
@prop({ ref: () => Marquee, type: mongoose.Schema.Types.ObjectId })
marquee: Ref<Marquee>; // 跑马灯连接到marquee表
@prop({ ref: () => Notice, type: mongoose.Schema.Types.ObjectId })
notice: Ref<Notice>; // 维护公告
@prop({ ref: () => GMMail, type: mongoose.Schema.Types.ObjectId })
mail: Ref<GMMail>; // 维护结束邮件
public static async createData(values: MaintenanceTypeParam, marquee: MarqueeType, notice: NoticeType, mail: GMMailType, uid = 1) {
const code = genCode(8);
const rec: MaintenanceType = await MaintenanceModel.findOneAndUpdate({ code }, {
$setOnInsert: {...values, code, isOpen: false, marquee: marquee._id, notice: notice._id, mail: mail._id, createdBy: uid}, $set: { updatedBy: uid }
}, { new: true, upsert: true }).lean();
return rec;
}
public static async updateData(code: string, values: MaintenanceTypeParam, uid = 1) {
const rec: MaintenanceType = await MaintenanceModel.findOneAndUpdate({ code }, { $set: { ...values, updatedBy: uid } }, { new: true, upsert: true })
.populate('marquee', 'code')
.populate('notice')
.populate('mail')
.lean();
return rec;
}
public static async findOpenMaintenance() {
const rec: MaintenanceType = await MaintenanceModel.findOne({ isOpen: true }, { _id: 0 }).populate('marquee').populate('notice').populate('mail').lean();
return rec;
}
public static async findByCode(code: string) {
const rec: MaintenanceType = await MaintenanceModel.findOne({ code }).populate('marquee').populate('notice').populate('mail').lean();
return rec;
}
public static async updateStatusByCode(code: string, isOpen: boolean, uid = 1) {
const rec: MaintenanceType = await MaintenanceModel.findOneAndUpdate({ code }, { $set: { isOpen, updatedBy: uid } }).populate('marquee').populate('notice').populate('mail').lean();
return rec;
}
private static getSearchObj(form: { isOpen?: boolean }) {
let searchObj = {};
if (form.isOpen) searchObj['isOpen'] = form.isOpen;
return searchObj
}
public static async findByCondition(page: number, pageSize: number, sortField: string, sortOrder: string, form: { isOpen?: 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: MaintenanceType[] = await MaintenanceModel.find(searchObj, { _id: 0 })
.populate('marquee').populate('notice', '+showStartTime +showEndTime').populate('mail')
.limit(pageSize).skip((page - 1) * pageSize).sort(sort).lean({ getters: true, virtuals: true });
return result;
}
public static async countByCondition(form: { isOpen?: boolean } = {}) {
let searchObj = this.getSearchObj(form);
const result = await MaintenanceModel.count(searchObj);
return result;
}
}
export const MaintenanceModel = getModelForClass(Maintenance);
export interface MaintenanceType extends Pick<DocumentType<Maintenance>, keyof Maintenance> { }
export type MaintenanceTypeParam = Partial<MaintenanceType>; // 将所有字段变成可选项

View File

@@ -1,36 +1,74 @@
import BaseModel from './BaseModel';
import { index, getModelForClass, prop, DocumentType, modelOptions } from '@typegoose/typegoose';
import { MARQUEE_TYPE } from '../consts';
import { index, getModelForClass, prop, DocumentType, modelOptions, ReturnModelType, mongoose } from '@typegoose/typegoose';
import { MARQUEE_SHOW_TYPE, MARQUEE_TIME_TYPE } from '../consts';
import { genCode } from '../pubUtils/util';
import { SearchMarqueeParam } from '../domain/backEndField/search';
import { nowSeconds } from '../pubUtils/timeUtil';
/**
* 跑马灯
**/
class Receiver {
@prop({ required: true })
regionId: number;
@prop({ required: true })
env: string;
@prop({ required: true })
serverId: number;
}
@modelOptions({ schemaOptions: { id: false } })
@index({ code: 1 })
export default class Marquee extends BaseModel {
@prop({ required: true })
code: string; // 跑马灯唯一标识
@prop({ required: true, type: Number })
serverIds: number[]; // 推送服务器
@prop({ required: true, enum: MARQUEE_TYPE })
type: MARQUEE_TYPE; // 推送类型
@prop({ required: true })
startTime: Date; // 活动开始时间
receiverType: number; // 推送目标
@prop({ required: true })
endTime: Date; // 活动结束时间
@prop({ required: true, type: Receiver, _id: false })
receivers: Receiver[]; // 推送服务器
@prop({ required: true })
interval: number; // 活动结束时间
@prop({ required: true, enum: MARQUEE_TIME_TYPE })
timeType: MARQUEE_TIME_TYPE; // 推送时间类型,立刻/定时
@prop({ required: true, enum: MARQUEE_SHOW_TYPE })
showType: MARQUEE_SHOW_TYPE; // 推送显示类型,一次性/循环
@prop({ required: true, default: 0 })
startTime: number; // 循环开始时间/定时开始时间
@prop({ required: true, default: 0 })
endTime: number; // 循环结束时间
@prop({ required: true, default: 0 })
interval: number; // 推送间隔
@prop({ required: true })
content: string; // 广播内容
@prop({ required: true })
isRunning: boolean; // 当前正在发布
@prop({ required: true, default: true })
isEnable: boolean; // 当前正在发布
setByForm(obj: any) {
this.code = obj.code;
this.receiverType = obj.receiverType;
this.receivers = obj.receivers;
this.timeType = obj.timeType;
this.showType = obj.showType;
if(this.timeType == MARQUEE_TIME_TYPE.INSTANT) {
this.startTime = nowSeconds();
} else {
this.startTime = obj.startTime;
}
if(this.showType == MARQUEE_SHOW_TYPE.CIRCLE) {
this.endTime = this.startTime + obj.continueMinute * 60;
this.interval = obj.interval;
}
this.content = obj.content;
}
/**
* 创建跑马灯
@@ -38,7 +76,7 @@ export default class Marquee extends BaseModel {
* @param uid 后台操作人
*/
public static async createData(params: MarqueeParam, uid = 1) {
const code = genCode(10);
const code = genCode(6);
const doc = new MarqueeModel();
const update = Object.assign(doc.toJSON(), params, { code, createdBy: uid, updatedBy: uid });
const result: MarqueeType = await MarqueeModel.findOneAndUpdate({ code }, { $setOnInsert: update }, { new: true, upsert: true }).lean();
@@ -69,21 +107,33 @@ export default class Marquee extends BaseModel {
/**
* 查询所有生效中的跑马灯
*/
public static async findEffectiveMarque() {
const result: MarqueeType[] = await MarqueeModel.find({ type: MARQUEE_TYPE.SCHEDULE, startTime: { $lte: new Date() }, endTime: { $gte: new Date() } }).lean();
public static async findEffectiveMarque(env: string) {
const result: MarqueeType[] = await MarqueeModel.find({
$or: [
{ showType: MARQUEE_SHOW_TYPE.CIRCLE, startTime: { $lte: nowSeconds() }, endTime: { $gte: nowSeconds() }},
{ showType: MARQUEE_SHOW_TYPE.ONCE, startTime: { $lte: nowSeconds() }}
],
isEnable: true,
'receivers.env': env
}).lean();
return result;
}
private static getSearchObj(form: { type?: number, current?: boolean, content?: string }) {
private static getSearchObj(form: SearchMarqueeParam) {
let searchObj = {};
if(form['type']) searchObj['type'] = form.type;
if(form['current']) searchObj['isRunning'] = form.current
if(form['content']) searchObj['content'] = { $regex: new RegExp(form.content.toString(), 'i') };
if(form.code) searchObj['code'] = form.code;
if(form.createdBy) searchObj['createdBy'] = form.createdBy
if(form.createTimeStart && form.createTimeEnd) {
searchObj['createdAt'] = { $gt: new Date(form.createTimeStart * 1000), $lt: new Date(form.createTimeEnd * 1000) };
}
if(form.sendTimeStart && form.sendTimeEnd) {
searchObj['startTime'] = { $gt: form.sendTimeStart, $lt: form.sendTimeEnd }
}
return searchObj
}
public static async findByCondition(page: number, pageSize: number, sortField: string = 'updatedAt', sortOrder: string = 'descend', form: { type?: number, current?: boolean, content?: string } = {}) {
public static async findByCondition(page: number, pageSize: number, sortField: string = 'updatedAt', sortOrder: string = 'descend', form: SearchMarqueeParam = {}) {
let searchObj = this.getSearchObj(form);
let sort = {};
@@ -94,12 +144,12 @@ export default class Marquee extends BaseModel {
sort[sortField] = -1;
}
}
const result: MarqueeType[] = await MarqueeModel.find(searchObj).limit(pageSize).skip((page - 1) * pageSize).sort(sort).select('+sort +showStartTime +showEndTime +serverType +isEnable').lean({ getters: true, virtuals: true });
const result: MarqueeType[] = await MarqueeModel.find(searchObj).limit(pageSize).skip((page - 1) * pageSize).sort(sort).lean({ getters: true, virtuals: true });
return result;
}
public static async countByCondition(form: { type?: number, current?: boolean, content?: string } = {}) {
public static async countByCondition(form: SearchMarqueeParam = {}) {
let searchObj = this.getSearchObj(form);
const result = await MarqueeModel.count(searchObj);
@@ -108,7 +158,12 @@ export default class Marquee extends BaseModel {
}
export const MarqueeModel = getModelForClass(Marquee);
export let MarqueeModel: ReturnModelType<typeof Marquee, {}>;
export function loadMarqueeModel(connect: mongoose.Connection) {
MarqueeModel = getModelForClass(Marquee, {
existingConnection: connect
});
}
export interface MarqueeType extends Pick<DocumentType<Marquee>, keyof Marquee> {};
export type MarqueeParam = Partial<MarqueeType>;

View File

@@ -2,7 +2,6 @@ import BaseModel from './BaseModel';
import { index, getModelForClass, prop, DocumentType, modelOptions } from '@typegoose/typegoose';
import { COUNTER } from '../consts'
import { CounterModel } from './Counter';
import moment = require('moment');
/**
* 游戏字段接口
@@ -23,17 +22,7 @@ export default class Notice extends BaseModel {
content: string; // 公告内容
@prop({ required: true })
timeStr: string; // 时间显示
@prop({ required: true })
startTime: Date; // 活动开始时间
@prop({ required: true })
endTime: Date; // 活动结束时间
public get time() {
let startTime = moment(this.startTime).format('YYYY/MM/DD');
let endTime = moment(this.endTime).format('YYYY/MM/DD');
return this.timeStr.replace(/%startTime/g, startTime).replace(/%endTime/g, endTime);
}
time: string; // 时间显示
@prop({ required: true, select: false })
sort: number;
@@ -42,15 +31,14 @@ export default class Notice extends BaseModel {
showStartTime: Date;
@prop({ required: true, select: false })
showEndTime: Date;
@prop({ required: true, select: false })
serverType: string; // 服务器类型
@prop({ required: true, select: false })
isEnable: boolean;
public static async getAllNotice(serverType: string) {
public static async getAllNotice() {
let curTime = new Date();
let notices: NoticeType[] = await NoticeModel.find({ showStartTime: { $lte: curTime }, showEndTime: { $gte: curTime }, isEnable: true, serverType })
let notices: NoticeType[] = await NoticeModel.find({ showStartTime: { $lte: curTime }, showEndTime: { $gte: curTime }, isEnable: true })
.sort({ sort: -1, createTime: -1 })
.lean({ virtuals: true });
return notices;
@@ -73,7 +61,6 @@ export default class Notice extends BaseModel {
private static getSearchObj(form: { type?: number, content?: string }) {
let searchObj = {};
if(form['type']) searchObj['type'] = form.type;
if(form['content']) searchObj['content'] = { $regex: new RegExp(form.content.toString(), 'i') };
return searchObj
}
@@ -89,7 +76,7 @@ export default class Notice extends BaseModel {
sort[sortField] = -1;
}
}
const result: NoticeType[] = await NoticeModel.find(searchObj).limit(pageSize).skip((page - 1) * pageSize).sort(sort).select('+sort +showStartTime +showEndTime +serverType +isEnable').lean({ getters: true, virtuals: true });
const result: NoticeType[] = await NoticeModel.find(searchObj).limit(pageSize).skip((page - 1) * pageSize).sort(sort).select('+sort +showStartTime +showEndTime +isEnable').lean({ getters: true, virtuals: true });
return result;
}

View File

@@ -41,6 +41,9 @@ export default class RScriptRecord extends BaseModel {
return items;
}
public static async deleteByWarType(roleId: string, warType: number) {
return await RScriptRecordModel.deleteMany({ roleId, warType });
}
public static async deleteByWarId(roleId: string, battleId: number[]) {
return await RScriptRecordModel.deleteMany({ roleId, battleId: { $in: battleId } });
}

94
shared/db/Region.ts Normal file
View File

@@ -0,0 +1,94 @@
import { COUNTER } from './../consts';
import { CounterModel } from './Counter';
import BaseModel from './BaseModel';
import { index, getModelForClass, prop, DocumentType, mongoose, ReturnModelType } from '@typegoose/typegoose';
import ServerStategy from './ServerStategy';
import { ServerlistType } from './Serverlist';
/**
* 大区数据
*/
@index({ id: 1 })
export default class Region extends BaseModel {
@prop({ required: true })
id: number; // 大区id
@prop({ required: true })
name: string; // 大区名
@prop({ required: true })
prefix: string; // 区名前缀
@prop({ required: true })
env: string; // 环境变量
@prop({ required: true })
gmLink: string; // 短链接地址
@prop({ required: true })
gameHost: string; // 长链接地址
@prop({ required: true })
gmPort: number; // 长链接地址
@prop({ required: true })
latestServer: number; // 最新服
@prop({ required: true })
latestServerUniqId: number; // 最新服唯一id
@prop({ required: true })
serverCount: number; // 总数
@prop({ required: true })
remark: string; // 备注
@prop({ required: true, type: () => ServerStategy, _id: false })
stategy: ServerStategy; // 策略配置
public static async createNewRegion(params: RegionUpdate, uid = 1) {
let id = await CounterModel.getNewCounter(COUNTER.REGION);
const rec: RegionType = await RegionModel.findOneAndUpdate({ id }, { $setOnInsert: { ...params, createdBy: uid}, $set: { updatedBy: uid } }, { new: true, upsert: true }).lean();
return rec;
}
public static async updateRegion(id: number, params: RegionUpdate, uid = 1) {
const rec: RegionType = await RegionModel.findOneAndUpdate({ id }, { $set: { ...params, updatedBy: uid } }, { new: true }).lean();
return rec;
}
public static async newServer(id: number, newServer: ServerlistType, uid = 1) {
const rec: RegionType = await RegionModel.findOneAndUpdate({ id }, {
$set: { latestServer: newServer.serverId, latestServerUniqId: newServer.id, updatedBy: uid },
$inc: { serverCount: 1 }
}, { new: true }).lean();
return rec;
}
public static async getAllRegion() {
const rec: RegionType[] = await RegionModel.find().select('-_id -stategy').lean();
return rec;
}
public static async findRegionById(id: number) {
const rec: RegionType = await RegionModel.findOne({ id }).select('-_id').lean();
return rec;
}
public static async findRegionByEnv(env: string) {
const rec: RegionType = await RegionModel.findOne({ env }).select('-_id').lean();
return rec;
}
}
export let RegionModel: ReturnModelType<typeof Region, {}>;
export function loadRegionModel(connect: mongoose.Connection) {
RegionModel = getModelForClass(Region, {
existingConnection: connect
});
}
export interface RegionType extends Pick<DocumentType<Region>, keyof Region> { };
export type RegionUpdate = Partial<RegionType>; // 将所有字段变成可选项

View File

@@ -0,0 +1,63 @@
import BaseModel from './BaseModel';
import { prop, DocumentType, getModelForClass } from '@typegoose/typegoose';
import { WHITE_LIST_TYPE } from '../consts';
export default class RegionWhiteList extends BaseModel {
@prop({ required: true })
code: string; // 编码
@prop({ required: true })
regionId: number; // 大区区号
@prop({ required: true })
env: string; // 环境变量
@prop({ required: true, enum: WHITE_LIST_TYPE })
type: WHITE_LIST_TYPE; // 环境变量
@prop({ required: true })
ip: string; // ip
@prop({ required: true })
serverId: number; // 小区id
@prop({ required: true })
uid: number; // 玩家uid
@prop({ required: true })
roleId: string; // 玩家角色id
@prop({ required: true })
roleName: string; // 玩家角色名
public static async checkIp(env: string, ip: string) {
const rec = await WhiteListModel.exists({ env, ip });
return rec;
}
public static async checkUid(env: string, serverId: number, uid: number) {
const rec = await WhiteListModel.exists({ env, serverId, uid });
return rec;
}
public static async findByRegionId(regionId: number) {
const rec: WhiteListModelType[] = await WhiteListModel.find({ regionId });
return rec;
}
public static async updateWhiteList(code: string, params: WhiteListModelTypeParam) {
const rec: WhiteListModelType = await WhiteListModel.findOneAndUpdate({ code }, params, { new: true, upsert: true }).lean();
return rec;
}
public static async deleteWhiteList(code: string) {
const rec: WhiteListModelType = await WhiteListModel.findOneAndDelete({ code }).lean();
return rec;
}
}
export let WhiteListModel = getModelForClass(RegionWhiteList)
export interface WhiteListModelType extends Pick<DocumentType<RegionWhiteList>, keyof RegionWhiteList> { }
export type WhiteListModelTypeParam = Partial<WhiteListModelType>; // 将所有字段变成可选项

View File

@@ -1,4 +1,4 @@
import { ROLE_TERAPH, ROLE_SELECT, ABI_TYPE, HERO_CE_RATIO } from './../consts';
import { ROLE_TERAPH, ROLE_SELECT, ABI_TYPE, HERO_CE_RATIO, BLOCK_TYPE } from './../consts';
import BaseModel from './BaseModel';
import { index, getModelForClass, prop, DocumentType, Ref, mongoose } from '@typegoose/typegoose';
import User from './User';
@@ -7,6 +7,7 @@ import { nowSeconds, getTimeFunD } from '../pubUtils/timeUtil';
import { Figure } from '../domain/dbGeneral';
import * as dicParam from '../pubUtils/dicParam';
import Hero from './Hero';
import { SearchRoleParam } from '../domain/backEndField/search';
type CeAttrUpdate = Partial<CeAttrDataRole>;
// role表属性格式
@@ -146,8 +147,10 @@ export default class Role extends BaseModel {
serverType: string; // 服务器类型
@prop({ required: true })
serverId: number; // 区服 id
@prop({ required: true, default: false })
blocked: boolean; // 是否屏蔽
@prop({ required: true, default: 0 })
blockType: BLOCK_TYPE; // 封禁类型 1-封言 2-封禁
@prop({ required: true, default: '' })
blockReason: string; // 封禁理由
@prop({ required: true })
code: string; // 邀请码
@prop({ required: true, default: false })
@@ -359,6 +362,15 @@ export default class Role extends BaseModel {
const role: RoleType = await RoleModel.findOne({ roleId }).select(select).lean({ getters, virtuals });
return role;
}
public static async findByRoleIds(roleIds: string[], select?: string, getters = false, virtuals = true) {
const role: RoleType[] = await RoleModel.find({ roleId: { $in: roleIds } }).select(select).lean({ getters, virtuals });
return role;
}
public static async findByRoleName(roleName: string, select?: string, getters = false, virtuals = true) {
const role: RoleType = await RoleModel.findOne({ roleName }).select(select).lean({ getters, virtuals });
return role;
}
public static async createRole(uid: number, serverId: number, roleInfo: { roleId: string; roleName: string; seqId: number; code: string, lv?: number, exp?: number }, lean = true) {
const user = await User.findUserByUid(uid);
@@ -370,19 +382,6 @@ export default class Role extends BaseModel {
return role;
}
public static async findRoleByField(field: string, value?: Array<number | string>, select?: string, getters = false) {
let searchObj = {};
if (field != 'all') {
searchObj[field] = {
$in: value
};
}
const user: RoleType[] = await RoleModel.find(searchObj).select(select).lean({ getters, virtuals: true });
return user;
}
public static async setEventStatus(roleId: string, eventStatus: number, lean = true) {
let role: RoleType = await RoleModel.findOneAndUpdate({ roleId }, { eventStatus }, { new: true }).lean(lean);
return role;
@@ -742,6 +741,38 @@ export default class Role extends BaseModel {
return role;
}
private static getSearchObj(form: SearchRoleParam) {
let searchObj = {};
if(form.uid) searchObj['userInfo.uid'] = form.uid;
if(form.roleId) searchObj['roleId'] = form.roleId;
if(form.roleName) searchObj['roleName'] = { $regex: new RegExp(form.roleName.toString(), 'i') };
return searchObj
}
public static async findByCondition(page: number, pageSize: number, sortField: string = 'updatedAt', sortOrder: string = 'descend', form: SearchRoleParam = {}) {
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: RoleType[] = await RoleModel.find(searchObj).limit(pageSize).skip((page - 1) * pageSize).sort(sort).lean({ getters: true, virtuals: true });
return result;
}
public static async countByCondition(form: SearchRoleParam = {}) {
let searchObj = this.getSearchObj(form);
const result = await RoleModel.count(searchObj);
return result;
}
}
export const RoleModel = getModelForClass(Role);

View File

@@ -1,91 +1,84 @@
import BaseModel from './BaseModel';
import { index, getModelForClass, prop, DocumentType } from '@typegoose/typegoose';
import { CounterModel } from './Counter';
import { COUNTER } from '../consts';
import { prop, DocumentType, } from '@typegoose/typegoose';
import { GM_MAIL_TYPE, MAIL_TIME_TYPE } from '../consts';
/**
* 开服策略
*/
@index({ id: 1 })
class Reward {
@prop({ required: true })
id: number;
@prop({ required: true })
count: number;
}
export default class ServerStategy extends BaseModel {
@prop({ required: true })
id: number; // 策略唯一id
@prop({ required: true })
name: string; // 策略名
export class GMMail {
@prop({ required: false})
hasGoods: boolean; // 有效时间,单位小时
@prop({ required: true, type: Reward, default: [], _id: false })
goods: Reward[];
@prop({ required: true, default: true })
timeType: MAIL_TIME_TYPE; // 邮件时间类型
@prop({ required: false})
expire: number; // 有效时间,单位小时
@prop({ required: true })
circleContinueDay: number; // 循环邮件持续天数
@prop({ required: true })
circleDay: number; // 循环时间每周几0表示每天
@prop({ required: true })
circleHour: string; // 几点发送
@prop({ required: true })
title: string;
@prop({ required: true })
content: string;
@prop({ required: true })
sendName: string;
@prop({ required: true })
mailType: GM_MAIL_TYPE; // 收件人类型
@prop({ required: true })
reason: string; // 原因
@prop({ required: true, default: false })
isSp: boolean; // 特殊邮件
}
export default class ServerStategy {
@prop({ required: true, default: false })
isDefault: boolean; // 是否是自动开服默认使用的策略
@prop({ required: true, default: 0 })
maxPlayerCnt: number; // 人数上限
@prop({ required: true, default: 0, type: Number })
timers: number[]; // 开服时间点
@prop({ required: true, type: Number })
activityGroupId: number[]; // 选择活动组
@prop({ required: true, type: Number })
mails: number[]; // 选择邮件模板
@prop({ required: true, type: Number })
marquees: number[]; // 选择跑马灯
@prop({ required: true, type: Number })
notices: number[]; // 选择公告
public static async findBySId(id: number) {
const result: ServerStategyType = await ServerStategyModel.findOne({ id }, { _id: 0 }).lean({ getters: true, virtuals: true });
return result;
@prop({ required: true, type: GMMail, _id: false })
openMail: GMMail;
}
@prop({ required: true, type: GMMail, _id: false })
circleMail: GMMail;
@prop({ required: true, default: 0 })
stopRegisterTime: number; // 关闭注册时间
private static getSearchObj(form: { id?: number, name?: string, isDefault?: boolean }) {
let searchObj = {};
if (form.id != undefined) searchObj['id'] = form.id;
if (form.name != undefined) searchObj['name'] = { $regex: new RegExp(form.name.toString(), 'i') };
if (form.isDefault != undefined) searchObj['isDefault'] = form.isDefault;
return searchObj
}
public static async findByCondition(page: number, pageSize: number, sortField: string, sortOrder: string, form: { id?: number, name?: string, isDefault?: 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: ServerStategyType[] = await ServerStategyModel.find(searchObj, { _id: 0 }).limit(pageSize).skip((page - 1) * pageSize).sort(sort).lean({ getters: true, virtuals: true });
return result;
}
public static async countByCondition(form: { id?: number, name?: string, isDefault?: boolean } = {}) {
let searchObj = this.getSearchObj(form);
const result = await ServerStategyModel.count(searchObj);
return result;
}
private static async unsetDefault() {
const rec = await ServerStategyModel.updateMany({ isDefault: true }, { $set: { isDefault: false } });
return rec;
}
public static async updateServerStategy(values: ServerStategyTypeParam & {id: string|number}, uid = 1) {
let id = values.id;
if(id == 'new') {
id = await CounterModel.getNewCounter(COUNTER.SERVER_STATEGY);
}
if(values.isDefault) {
await this.unsetDefault();
}
delete values.id;
let rec: ServerStategyType = await ServerStategyModel.findOneAndUpdate({ id }, { $set: {...values, updatedBy: uid}, $setOnInsert: { createdBy: uid } },
{ new: true, upsert: true }).lean(true);
return rec;
constructor(stategy: ServerStategyUpdate & { hasOpenMail: boolean, hasCircleMail: boolean}) {
this.maxPlayerCnt = stategy.maxPlayerCnt;
this.timers = stategy.timers;
this.activityGroupId = stategy.activityGroupId;
this.stopRegisterTime = stategy.stopRegisterTime;
if(stategy.hasCircleMail) this.circleMail = stategy.circleMail;
if(stategy.hasOpenMail) this.openMail = stategy.openMail;
}
}
export const ServerStategyModel = getModelForClass(ServerStategy);
export interface ServerStategyType extends Pick<DocumentType<ServerStategy>, keyof ServerStategy> { }
export type ServerStategyTypeParam = Partial<ServerStategyType>; // 将所有字段变成可选项
export interface ServerStategyType extends Pick<DocumentType<ServerStategy>, keyof ServerStategy> { };
export type ServerStategyUpdate = Partial<ServerStategyType>; // 将所有字段变成可选项

View File

@@ -1,25 +1,49 @@
import BaseModel from './BaseModel';
import { index, getModelForClass, prop, DocumentType, modelOptions } from '@typegoose/typegoose';
import { GameModel } from './Game';
import { CounterModel } from './Counter';
import { index, getModelForClass, prop, DocumentType, modelOptions, ReturnModelType, mongoose } from '@typegoose/typegoose';
import { CounterAllModal } from './CounterAll';
import { COUNTER, SERVER_STATUS } from '../consts';
import { ServerStategyTypeParam } from './ServerStategy';
import { getServerName, getServerGroupName } from '../pubUtils/data';
import { CreateServerParam } from '../domain/backEndField/params';
import { RegionType } from './Region';
import { nowSeconds } from '../pubUtils/timeUtil';
import { gameData } from '../pubUtils/data';
// 暂时服务器列表是从game表取的之后会转移到使用这张表目前用作查询该服战力中位数
export class Maintenance {
@prop({ required: true })
batchCode: string; // 批次,如果是从大区列表维护就是一批的,小区列表上就是一服一个
@prop({ required: true })
isOpen: boolean; // 维护是否使用
@prop({ required: true })
startTime: number; // 维护开始时间
@prop({ required: true })
endTime: number; // 维护结束时间
@prop({ required: true })
hasNotify: boolean; // 是否有维护通知
}
/**
* 游戏字段接口
*/
@index({ id: 1 })
@index({ env: 1 })
@modelOptions({ schemaOptions: { id: false } })
export default class Serverlist extends BaseModel {
@prop({ required: true, default: 1 })
gameId: number; // 游戏id Game表的id
regionId: number; // 大区id
@prop({ required: true })
id: number; // 小区id 自增
env: string; // 环境变量
@prop({ required: true })
prefix: string; // 前缀
@prop({ required: true })
id: number; // 小区id 自增全大区共用自增counter玩家role表中存的就是这个serverId
@prop({ required: true })
serverId: number; // 相同serverType下的id不同serverType下id一定不同但是serverId可能相同
@@ -28,16 +52,10 @@ export default class Serverlist extends BaseModel {
name: string; // 小区区名
@prop({ required: true })
groupId: number; // 区id
groupId: number; // 区id
@prop({ required: true })
groupName: string; // 区区名
@prop({ required: true })
host: string; // pinus连接地址
@prop({ required: false, default: 3014 })
port: number; // pinus端口
groupName: string; // 区区名
@prop({ required: true, default: 1, enum: SERVER_STATUS })
serverStatus: number; // 服务器状态
@@ -46,38 +64,57 @@ export default class Serverlist extends BaseModel {
activityGroupId: number[]; // 活动组
public get status() {
let now = new Date();
if (now > this.openTime) {
return this.serverStatus;
let now = nowSeconds();
if (now < this.openTime) {
return SERVER_STATUS.WILL_OPEN;
} else if (this.maintenance && this.maintenance.isOpen && this.maintenance.startTime < now && this.maintenance.endTime > now) {
return SERVER_STATUS.MAINTENANCE;
} else {
return SERVER_STATUS.WILL_OPEN; // 未开服
return this.serverStatus; // 未开服
}
}
@prop({ required: true })
openTime: Date;
openTime: number;
@prop({ required: true })
serverType: string;
stopRegisterTime: number;
@prop({ required: true, default: true })
canRegister: boolean;
@prop({ required: true, default: 0 })
maxPlayerCnt: number; // 最大玩家人数
playerCnt: number; // 当前玩家人数
@prop({ required: true, default: 0 })
medianCe: number; // 中位数武将战力、缩小10000倍后的结果
@prop({ required: true, type: Maintenance, _id: false })
maintenance: Maintenance
public static async getAllServerList() {
let servers: ServerlistType[] = await ServerlistModel.find().lean({ getters: true, virtuals: true });
return servers;
let id = await CounterAllModal.getCounter(COUNTER.SERVER);
let result: ServerlistType[] = [];
let n = Math.ceil(id/1000);
for(let i = 0; i < n; i++) {
let servers: ServerlistType[] = await ServerlistModel.find().limit(1000).skip(i * 1000).lean({ getters: true, virtuals: true });
result.push(...servers);
}
return result;
}
public static async findByServerId(serverId: number) {
let server: ServerlistType = await ServerlistModel.findOne({ id: serverId }).select('medianCe activityGroupId').lean({ getters: true, virtuals: true });
let server: ServerlistType = await ServerlistModel.findOne({ id: serverId }).lean({ getters: true, virtuals: true });
return server;
}
public static async findByServerIds(serverIds: number[]) {
let servers: ServerlistType[] = await ServerlistModel.find({ id: { $in: serverIds } }).select('medianCe activityGroupId').lean({ getters: true, virtuals: true });
return servers;
}
public static async updateByServerId(serverId: number, update: ServerlistUpdate) {
let server: ServerlistType = await ServerlistModel.findOneAndUpdate({ id: serverId }, { $set: update }).lean({ getters: true, virtuals: true });
let server: ServerlistType = await ServerlistModel.findOneAndUpdate({ id: serverId }, { $set: update }, {new: true}).lean({ getters: true, virtuals: true });
return server;
}
@@ -86,81 +123,33 @@ export default class Serverlist extends BaseModel {
return result;
}
public static async updateGroupName(groupId: number, groupName: string) {
let server = await ServerlistModel.updateMany({ groupId }, { $set: { groupName } });
return server;
}
public static async newServer(params: { serverType: string, openTime: Date, name?: string }, stategy: ServerStategyTypeParam, uid = 1 ) {
let { serverType, name } = params;
let serverEnvs = await GameModel.getServerEnvList();
let curEnv = serverEnvs.find(cur => cur.serverType == serverType);
if(!curEnv) return false;
let { gameHost: host } = curEnv;
public static async newServer(params: CreateServerParam, region: RegionType, serverId: number, uid = 1 ) {
let dicServerName = gameData.serverNames.get(serverId);
let { prefix, id: regionId, env } = region;
// 分大区
let groupId = await CounterModel.getCounter(COUNTER.SERVER_GROUP);
let groupServerCount = await ServerlistModel.countByCondition({ serverType, groupId });
if(groupServerCount > 10) {
groupId = await CounterModel.getNewCounter(COUNTER.SERVER_GROUP);
}
let groupName = getServerGroupName(groupId)||"";
let serverId = await CounterModel.getNewCounter({ name: `${COUNTER.SERVER_BY_TYPE.name}_${serverType}`, def: COUNTER.SERVER_BY_TYPE.def });
let id = await CounterModel.getNewCounter(COUNTER.SERVER);
if(!name) name = getServerName(id)||"";
let id = await CounterAllModal.getNewCounter(COUNTER.SERVER);
let { openTime, stopRegisterTime: hour, activityGroupId } = params;
let { sname: name, groupId, groupName } = dicServerName;
let stopRegisterTime = openTime + hour * 60 * 60;
const doc = new ServerlistModel();
const update = Object.assign(doc.toJSON(), params, { id, serverId, host, groupId, groupName, name, createdBy: uid, updatedBy: uid }, { activityGroupId: stategy.activityGroupId, maxPlayerCnt: stategy.maxPlayerCnt});
const update = Object.assign(doc.toJSON(), {
id, regionId, env, prefix,
serverId, name, groupId, groupName, activityGroupId,
openTime, stopRegisterTime,
createdBy: uid, updatedBy: uid
});
// 旧服修改状态
await ServerlistModel.updateMany({ env, serverStatus: SERVER_STATUS.NEW }, { $set: { serverStatus: SERVER_STATUS.HOT } })
let server: ServerlistType = await ServerlistModel.findOneAndUpdate({ id }, { $setOnInsert: update }, { new: true, upsert: true }).lean({ getters: true, virtuals: true });
return server;
}
public static async findByServerType(serverType?: string) {
let condition = {};
if(serverType) {
condition['serverType'] = serverType;
}
let server: ServerlistType[] = await ServerlistModel.find(condition).sort({ id: -1 }).lean({ getters: true, virtuals: true });
public static async findByEnv(env?: string) {
let server: ServerlistType[] = await ServerlistModel.find({ env, serverStatus: { $gt: 0 } }).sort({ id: -1 }).lean({ getters: true, virtuals: true });
return server;
}
private static getSearchObj(form: { id?: number, serverId?: string|number, name?: string, groupName?: string, groupId?: number, serverType?: string }) {
let searchObj = {};
if (form.id != undefined) searchObj['id'] = form.id;
if (form.serverId != undefined) searchObj['serverId'] = form.serverId;
if (form.groupId != undefined) searchObj['groupId'] = form.groupId;
if (form.name != undefined) searchObj['name'] = { $regex: new RegExp(form.name.toString(), 'i') };
if (form.groupName != undefined) searchObj['groupName'] = { $regex: new RegExp(form.groupName.toString(), 'i') };
if (form.serverType != undefined) searchObj['serverType'] = form.serverType;
return searchObj
}
public static async findByCondition(page: number, pageSize: number, sortField: string, sortOrder: string, form: { id?: number, serverId?: string|number, name?: string, groupName?: string, groupId?: number, serverType?: string } = {}) {
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: ServerlistType[] = await ServerlistModel.find(searchObj, { _id: 0 }).limit(pageSize).skip((page - 1) * pageSize).sort(sort).lean({ getters: true, virtuals: true });
return result;
}
public static async countByCondition(form: { id?: number, serverId?: string|number, name?: string, groupName?: string, groupId?: number, serverType?: string } = {}) {
let searchObj = this.getSearchObj(form);
const result = await ServerlistModel.count(searchObj);
return result;
}
//根据多个活动id查询活动数据
public static async findServerByIds(ids: number[]) {
let result: ServerlistType[] = await ServerlistModel.find({ id: { $in: ids } }).lean();
@@ -181,9 +170,19 @@ export default class Serverlist extends BaseModel {
return result;
}
public static async incRoleCnt(serverId: number) {
let server: ServerlistType = await ServerlistModel.findOneAndUpdate({ serverId }, { $inc: { playerCnt: 1 } });
return server;
}
}
export const ServerlistModel = getModelForClass(Serverlist);
export let ServerlistModel: ReturnModelType<typeof Serverlist, {}>;
export function loadServerlistModel(connect: mongoose.Connection) {
ServerlistModel = getModelForClass(Serverlist, {
existingConnection: connect
});
}
export interface ServerlistType extends Pick<DocumentType<Serverlist>, keyof Serverlist> {
id: number;

View File

@@ -1,5 +1,6 @@
import BaseModel from './BaseModel';
import { index, getModelForClass, prop, DocumentType } from '@typegoose/typegoose';
import { gameData } from '../pubUtils/data';
class WarStatus {
@prop({ required: true })
@@ -86,6 +87,17 @@ export default class TowerRecord extends BaseModel {
return rec;
}
public static async insertTowerRec(roleId: string, lv: number) {
let insertParams = [];
let doc = new TowerRecordModel();
for(let [towerLv, { warArray }] of gameData.tower) {
if(towerLv < lv) {
insertParams.push({...doc.toJSON(), roleId, lv: towerLv, warStatus: warArray.map(warId => ({ warId, status: true })), passed: true})
} else if (towerLv == lv) {
insertParams.push({...doc.toJSON(), roleId, lv: towerLv, warStatus: warArray.map(warId => ({ warId, status: true })), passed: false})
}
}
}
public static async deleteAccount(roleId: string) {
let result = await TowerRecordModel.deleteMany({roleId});

View File

@@ -4,6 +4,7 @@ import BaseModel from './BaseModel';
import { index, getModelForClass, prop, DocumentType } from '@typegoose/typegoose';
import { genCode, aesEncryptcfb, aesDecryptcfb } from '../pubUtils/util';
import { LoginValidateData37, ChannelInfo } from '../domain/sdk';
import { SearchUserParam } from '../domain/backEndField/search';
const bcrypt = require('bcrypt');
const SALT_WORK_FACTOR = 5
@@ -43,7 +44,7 @@ export default class User extends BaseModel {
@prop({ required: true, _id: false })
channelInfo: LoginValidateData37|{}; // 渠道数据
@prop({ required: true, set: (val: string) => aesEncryptcfb(val, ENCRYPT_KEY, ENCRYPT_IV), get: (val: string) => aesDecryptcfb(val, ENCRYPT_KEY, ENCRYPT_IV) })
@prop({ required: true, set: (val: string) => aesEncryptcfb(val, ENCRYPT_KEY, ENCRYPT_IV), get: (val: string) => val?aesDecryptcfb(val, ENCRYPT_KEY, ENCRYPT_IV):'' })
tel: string; // 账号
@prop({ required: true, default: '' })
@@ -107,10 +108,6 @@ export default class User extends BaseModel {
@prop({ required: true, default: false })
blocked: boolean;
// 用户权限0-普通用户1-测试用户
@prop({ required: true, default: 0 })
auth: number;
// 个推CID
@prop({ required: false, default: "" })
getuiCID: string;
@@ -279,21 +276,41 @@ export default class User extends BaseModel {
return user;
}
public static async findUserByField(field: string, value?: Array<number | string>) {
let searchObj = {};
if (field != 'all') {
searchObj[field] = {
$in: value
};
}
const user: UserType[] = await UserModel.find(searchObj).select('uid tel username serverType auth').lean({ getters: true });
public static async updatePlayTime(userCode: string, isGuest: boolean, todayPlayTime: number, playTime: number) {
const user: UserType = await UserModel.findOneAndUpdate({ userCode }, { $set: { guestTime: isGuest?playTime: 0, todayPlayTime: todayPlayTime, playTime } }, { new: true }).lean({ getters: true });
return user;
}
public static async updatePlayTime(userCode: string, isGuest: boolean, todayPlayTime: number, playTime: number) {
const user: UserType = await UserModel.findOneAndUpdate({ userCode }, { $set: { guestTime: isGuest?playTime: 0, todayPlayTime: todayPlayTime, playTime } }, { new: true }).lean({ getters: true });
return user;
private static getSearchObj(form: SearchUserParam) {
let searchObj = {};
if(form['uid']) searchObj['uid'] = form.uid;
if(form['tel']) searchObj['tel'] = form.tel;
if(form.channelType && form.channelType != 'normal') searchObj['channelType'] = form.channelType;
return searchObj
}
public static async findByCondition(page: number, pageSize: number, sortField: string = 'updatedAt', sortOrder: string = 'descend', form: SearchUserParam = {}) {
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: UserType[] = await UserModel.find(searchObj).limit(pageSize).skip((page - 1) * pageSize).sort(sort).select('-_id -__v -password -salt -token').lean({ getters: true, virtuals: true });
return result;
}
public static async countByCondition(form: SearchUserParam = {}) {
let searchObj = this.getSearchObj(form);
const result = await UserModel.count(searchObj);
return result;
}
}

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>;

View File

@@ -1,27 +0,0 @@
import BaseModel from './BaseModel';
import { prop, DocumentType, getModelForClass } from '@typegoose/typegoose';
import { WHITE_LIST_TYPE } from '../consts';
export default class WhiteList extends BaseModel {
@prop({ required: true, enum: WHITE_LIST_TYPE })
type: WHITE_LIST_TYPE; // 区号
@prop({ required: true })
str: string; // ip或手机号
public static async checkIp(ip: string) {
const rec: WhiteListModelType = await WhiteListModel.findOne({ type: WHITE_LIST_TYPE.IP, str: ip }).lean();
return rec;
}
public static async checkTel(tel: string) {
const rec: WhiteListModelType = await WhiteListModel.findOne({ type: WHITE_LIST_TYPE.TEL, str: tel }).lean();
return rec;
}
}
export const WhiteListModel = getModelForClass(WhiteList);
export interface WhiteListModelType extends Pick<DocumentType<WhiteList>, keyof WhiteList> { }
export type WhiteListModelTypeParam = Partial<WhiteListModelType>; // 将所有字段变成可选项

View File

@@ -4,11 +4,22 @@ import { loadGMGroupModel } from "./GMGroup";
import { loadGMRecordModel } from "./GMRecord";
import { loadGMUserModel } from './GMUser'
import { loadGMUserGroupModel } from "./GMUserGroup";
import { loadRegionModel } from "./Region";
import { loadServerlistModel } from "./Serverlist";
import { loadGMMailModel } from './GMMail';
import { loadCounterModal } from "./CounterAll";
import { loadMarqueeModel } from "./Marquee";
export function loadGmDb(connect: mongoose.Connection) {
// console.log('************')
loadApiModel(connect);
loadGMGroupModel(connect);
loadGMUserModel(connect);
loadGMUserGroupModel(connect);
loadGMRecordModel(connect);
loadRegionModel(connect);
loadServerlistModel(connect);
loadGMMailModel(connect);
loadCounterModal(connect);
loadMarqueeModel(connect);
}

View File

@@ -0,0 +1,265 @@
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; // 是否有道具
goods: {id: number; count: number}[];
timeType: MAIL_TIME_TYPE; // 邮件时间类型
expire: number; // 有效时间,单位小时
startTime: number; // 发送时间,延时邮件使用
circleStart: number; // 循环邮件开始循环时间
circleEnd: number; // 循环邮件结束循环时间
circleDay: number; // 循环时间每周几0表示每天
circleHour: string; // 几点发送
title: string;
content: string;
sendName: string;
mailType: GM_MAIL_TYPE; // 收件人类型
receivers: {env: string; serverId: number; roleId: string; roleName: string; }[];
reason: string; // 原因
isSp: boolean = false; // 特殊邮件
isSingle: boolean;
constructor(obj: UpdateMailParams) {
this.goods = obj.goods;
this.hasGoods = obj.goods?.length > 0;
this.timeType = obj.timeType;
this.expire = obj.expire;
this.startTime = obj.startTime;
this.circleStart = obj.circleStart;
this.circleEnd = obj.circleEnd;
this.circleDay = obj.circleDay;
this.circleHour = obj.circleHour;
this.title = obj.title;
this.content = obj.content;
this.sendName = obj.sendName;
if(obj.isSingle == true) {
this.mailType = GM_MAIL_TYPE.SINGLE;
} else if (obj.isSingle == false) {
this.mailType = GM_MAIL_TYPE.SERVER;
}
this.receivers = obj.receivers;
this.reason = obj.reason;
}
checkParams() {
if(!this.title || !this.content || !this.sendName || !this.reason) return false;
if(this.timeType == MAIL_TIME_TYPE.IMMEDIATE) {
if(!this.expire) return false;
} else if (this.timeType == MAIL_TIME_TYPE.DELAY) {
if(!this.expire || !this.startTime) return false;
} else if (this.timeType == MAIL_TIME_TYPE.CIRCLE) {
if(!this.expire || !this.circleStart || !this.circleEnd || this.circleDay == undefined || !this.circleHour)
return false;
}
if(!this.receivers || !isArray(this.receivers)) return false;
if(!this.mailType) return false;
for(let { serverId, roleId, roleName } of this.receivers) {
if(!serverId) return false;
if(this.mailType == GM_MAIL_TYPE.SINGLE||this.mailType == GM_MAIL_TYPE.GROUP) {
if(!roleId || !roleName) return false;
}
}
return true;
}
}
export class UpdateRegionParams {
id: number|'new' = 0; // 大区id
name: string = ''; // 大区名
prefix: string = ''; // 区名前缀
remark: string = '';
maxPlayerCnt: number = 0;
timers: SERVER_TIMER[] = [];
activityGroupId: number[] = [];
openMail?: GMMail;
circleMail?: GMMail;
stopRegisterTime: number = 0;
hasOpenMail: boolean = false;
hasCircleMail: boolean = false;
constructor(obj: UpdateRegionParams) {
for(let key in obj) {
this[key] = obj[key];
}
}
checkParams() {
if(!this.id || !this.name || !this.prefix || !this.maxPlayerCnt || !isArray(this.timers) || this.timers.length <= 0 || !isArray(this.activityGroupId) || this.activityGroupId.length <= 0 ) {
return false
}
return true;
}
getUpdateParam(oldRegion?: RegionType) {
if(!oldRegion) {
let stategy = new ServerStategy(this);
return {
name: this.name,
prefix: this.prefix,
remark: this.remark,
stategy
}
} else {
let stategy = new ServerStategy(this);
return {
name: this.name||oldRegion.name,
prefix: this.prefix||oldRegion.prefix,
remark: this.remark||oldRegion.remark,
stategy: { ...(oldRegion.stategy||{}), ...stategy }
}
}
}
}
export class CreateServerParam {
env: string = '';
openTime: number = 0;
activityGroupId: number[] = [];
hasOpenMail: boolean = false;
openMail?: GMMail;
hasCircleMail: boolean = false;
circleMail?: GMMail;
stopRegisterTime: number = 0;
constructor(obj?: any) {
if(obj) {
for(let key in obj) {
this[key] = obj[key];
}
}
}
setByRegionStategy(region: RegionType, openTime: number) {
this.env = region.env;
this.openTime = openTime;
if(region.stategy) {
this.activityGroupId = region.stategy.activityGroupId;
this.hasOpenMail = !!region.stategy.openMail;
this.openMail = region.stategy.openMail;
this.hasCircleMail = !!region.stategy.circleMail;
this.circleMail = region.stategy.circleMail;
this.stopRegisterTime = region.stategy.stopRegisterTime;
}
}
checkParams() {
if(!this.env || !this.openTime || !this.stopRegisterTime || !isArray(this.activityGroupId) || this.activityGroupId.length <= 0 ) {
return false
}
if(this.hasOpenMail && !this.openMail) return false;
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;
}
}
export class GuildFormParam {
code: string;
name: string;
notice: string;
fund: number;
lv: number;
equipProduce: number;
boss: number;
train: number;
wishPool: number;
store: number;
donate: number;
constructor(obj?: any) {
if(obj) {
for(let key in obj) {
this[key] = obj[key];
}
}
}
checkParams() {
if(!this.code || !isString(this.code)) return false;
if(this.name && !isString(this.name)) return false;
if(this.notice && !isString(this.notice)) return false;
if(this.fund && !isNumber(this.fund)) return false;
if(this.lv && !isNumber(this.lv)) return false;
if(this.equipProduce && !isNumber(this.equipProduce)) return false;
if(this.boss && !isNumber(this.boss)) return false;
if(this.train && !isNumber(this.train)) return false;
if(this.wishPool && !isNumber(this.wishPool)) return false;
if(this.store && !isNumber(this.store)) return false;
if(this.donate && !isNumber(this.donate)) return false;
return true;
}
}

View File

@@ -0,0 +1,74 @@
import { GM_MAIL_STATUS, GM_MAIL_TYPE } from "../../consts";
export interface SearchUserParam {
uid?: number;
tel?: string;
channelType?: string;
}
export interface SearchRoleParam {
uid?: number; // 玩家id
roleId?: string; // 角色id
roleName?: string; // 昵称
}
export interface SearchHeroParam {
roleId?: string;
roleName?: string;
hid?: number;
}
export interface SearchEquipParam {
roleId?: string;
roleName?: string;
id?: number;
}
export interface SearchItemParam {
roleId?: string;
roleName?: string;
id?: number;
}
export interface SearchGuildParam {
serverId?: number;
name?: string;
}
export interface SearchMailParam {
createTimeStart?: number;
createTimeEnd?: number;
serverId?: number;
roleId?: string;
roleName?: string;
title?: string;
status?: GM_MAIL_STATUS;
mailType?: GM_MAIL_TYPE;
hasGoods?: boolean;
}
export interface SearchMarqueeParam {
code?: string;
createdBy?: number;
createTimeStart?: number;
createTimeEnd?: number;
sendTimeStart?: number;
sendTimeEnd?: number;
}
export interface SearchGiftCodeParam {
env?: string;
id?: number;
name?: string;
createTimeStart?: number;
createTimeEnd?: number;
}
export interface SearchGiftCodeDetailParam {
giftId?: number;
giftName?: string;
generateType?: number;
code?: string;
roleId?: string;
roleName?: string;
}

View File

@@ -1,5 +1,4 @@
import { RoleType } from '../../db/Role';
import { getSeconds } from '../../pubUtils/timeUtil';
import { ServerlistType } from '../../db/Serverlist';
export class ServerParam {
@@ -7,22 +6,18 @@ export class ServerParam {
serverId: number; // 显示的区号
serverStr: string; // 显示的区号 S1
name: string; // 区名
host: string; // pinus地址
port: number; // pinus端口
host: string = ''; // pinus地址
port: number = 0; // pinus端口
status: number; // 状态
openTime: number; // 开服时间
serverType: string; // 分区类型 官服 测试服 开发服
constructor(server: ServerlistType) {
this.id = server.id;
this.serverId = server.serverId;
this.serverStr = `S${server.serverId}`;
this.serverStr = `${server.prefix}${server.serverId}`;
this.name = server.name;
this.host = server.host;
this.port = server.port;
this.status = server.status;
this.openTime = getSeconds(server.openTime);
this.serverType = server.serverType;
this.openTime = server.openTime;
}
}
@@ -35,15 +30,17 @@ export class GroupParam {
constructor(server: ServerlistType) {
this.groupId = server.groupId;
this.groupName = server.groupName;
this.groupStr = `S${server.serverId}-S${server.serverId + 9}`;
this.groupStr = `${server.prefix}${server.serverId}`;
this.servers = new Array<ServerParam>();
}
public pushServer(server: ServerlistType) {
let srv = new ServerParam(server);
this.servers.push(srv);
let min = this.servers.reduce((pre, cur) => pre < cur? pre: cur);
this.groupStr = `${min.serverId}-${min.serverId + 9}`
this.servers.sort((a, b) => b.serverId - a.serverId);
let min = this.servers[this.servers.length - 1];
let max = this.servers[0];
this.groupStr = `${min.serverStr}-${max.serverStr}`
}
}

View File

@@ -76,20 +76,12 @@ export class MailParam {
}
setContent(mail: MailType|GroupMailType|ServerMailType) {
let { contentId = 0, params, goods, sendName } = mail;
let { contentId = 0, goods, sendName, content, title } = mail;
let dicMail = gameData.mail.get(contentId);
if(!dicMail) dicMail = gameData.mail.get(0);
this.content = this.getContent(dicMail.content, params);
this.title = title;
this.content = content;
this.sendName = sendName||SEND_NAME;
this.goods = goods;
}
getContent(content: string, params: string[]) {
if(!content) content = '%d';
for(let p of params) {
content = content.replace(/%d/, p);
}
return content
}
}

View File

@@ -83,7 +83,7 @@ import { dicRecruit, loadRecruit } from './dictionary/DicRecruit';
import { loadRMB, dicRMB } from './dictionary/DicRMB';
import { dicActivityType, loadActivityType } from './dictionary/DicActivityType';
import { DicTaskType, dicTaskTypeDesc, loadTaskType } from './dictionary/DicTaskType';
import { dicServerName, dicServerGroupName, loadServerName } from "./dictionary/DicServerName";
import { dicServerName, loadServerName } from "./dictionary/DicServerName";
import { dicAp, loadAp, dicApMaxLevel } from './dictionary/DicAp';
import { dicApBuy, dicApMaxBuyTimes, loadApBuy } from "./dictionary/DicApBuy";
import { dicKingExpRatio, loadKingExpRatio } from './dictionary/DicKingExpRatio';
@@ -224,7 +224,6 @@ export const gameData = {
activityType: dicActivityType,
taskTypeDesc: dicTaskTypeDesc,
serverNames: dicServerName,
serverGroupNames: dicServerGroupName,
ap: dicAp,
apMaxLevel: dicApMaxLevel,
apBuy: dicApBuy,
@@ -718,22 +717,6 @@ function getCeRatio() {
});
}
// 根据groupId获得当前大区名
export function getServerGroupName(groupId: number) {
let name = gameData.serverGroupNames.get(groupId);
if(!name) {
let maxId = 0;
gameData.serverGroupNames.forEach((gname, id) => {
if(id > maxId) {
maxId = id;
name = gname;
}
})
}
return name;
}
// 根据服务器id获得当前大区名
export function getServerName(id: number) {
let name = gameData.serverNames.get(id);

View File

@@ -7,6 +7,8 @@ export interface DicMail {
readonly id: number;
// 内容 %d 替换
readonly content: string;
readonly title: string;
readonly sendName: string;
readonly time: number;
}
@@ -16,6 +18,8 @@ export function loadMail() {
let arr = readFileAndParse(FILENAME.DIC_MAIL);
arr.forEach(o => {
if(o.title == '&') o.title = '';
if(o.sendName == '&') o.sendName = '';
o.time = o.time * 60 * 60;
dicMail.set(o.id, o);
});

View File

@@ -1,4 +1,4 @@
// 武将特技表
// 服务器名
import { readFileAndParse } from '../util'
import { FILENAME } from '../../consts'
@@ -6,32 +6,21 @@ export interface DicServerName {
// id
readonly id: number;
// 小区名
readonly name: string;
readonly sname: string;
// 大区id
readonly groupId: number;
// 大区名
readonly groupName: string;
}
export const dicServerName = new Map<number, string>();
export const dicServerGroupName = new Map<number, string>();
export const dicServerName = new Map<number, DicServerName>();
export function loadServerName() {
dicServerName.clear();
dicServerGroupName.clear();
{
let arr = readFileAndParse(FILENAME.DIC_SERVER_NAME);
arr.forEach(o => {
let { id, sname } = o;
dicServerName.set(id, sname);
});
arr = undefined;
}
let arr = readFileAndParse(FILENAME.DIC_SERVER_NAME);
{
let arr = readFileAndParse(FILENAME.DIC_SERVER_GROUP_NAME);
arr.forEach(o => {
let { id, groupName } = o;
dicServerGroupName.set(id, groupName);
});
arr = undefined;
}
arr.forEach(o => {
dicServerName.set(o.id, o);
});
arr = undefined;
}

View File

@@ -1,71 +0,0 @@
import { mailInit, setMails, GMMail } from '../gmData/gmMail';
import { nowSeconds } from '../timeUtil';
const ALL_SERVER = 0;
export let gmData:any = {};
export async function init() {
gmData.mails = await mailInit();
}
export function getGmMails(updatedMailAt: number, serverId: number) {
let list = [];
let nowTime = nowSeconds();
let serverIds = [serverId, ALL_SERVER];
for (let serverId of serverIds) {
let gmServerData = gmData.mails.get(serverId);
if (!gmServerData)
continue;
gmServerData.forEach((gmMail)=>{
if (gmMail.updatedAt >= updatedMailAt || gmMail.sendTime > updatedMailAt || gmMail.endTime > nowTime )
list.push(gmMail);
});
}
return list;
}
export function getUseGmMails(serverId: number) {
let list = new Map<string, GMMail>();
let serverIds = [serverId, ALL_SERVER];
let nowTime = nowSeconds();
for (let serverId of serverIds) {
let gmServerData = gmData.mails.get(serverId);
if (!gmServerData)
continue;
gmServerData.forEach((gmMail)=>{
if (gmMail.endTime > nowTime)
list.set(gmMail.id, gmMail);
});
}
return list;
}
export function getGmMailById(id: string, serverId: number, nowTime: number) {
let gmMail;
if (!!gmData.mails.get(serverId)) {
gmMail = gmData.mails.get(serverId).get(id);
}
if (!gmMail) {
if (!!gmData.mails.get(ALL_SERVER)) {
gmMail = gmData.mails.get(ALL_SERVER).get(id);
}
}
if (!gmMail || gmMail.endTime < nowTime)
return null;
return gmMail;
}
export function setGmMails(mails: GMMail[]) {
setMails(mails, gmData.mails);
}
export function getGmUseMails(serverId: number) {
let list = new Map<number, any>();
if (!!gmData.mails.get(serverId)) {
list = gmData.mails.get(serverId);
}
let serverMail = gmData.mails.get(ALL_SERVER);
if (!!serverMail) {
list = Object.assign(list, serverMail);
}
return list;
}

View File

@@ -1,61 +0,0 @@
type KeysEnum<T> = { [P in keyof Required<T>]: true };
import { RewardInter } from '../interface';
import { GMMailModel } from '../../db/GMMail';
const _ = require('lodash');
export interface GMMail {
readonly id: string;
readonly sendRoles?: Array<{roleId: string, status: number}>;
readonly goods: Array<RewardInter>;
readonly sendTime: number;
readonly endTime: number;
readonly content: string;
readonly gmMailType: number;
readonly updatedAt: number;
readonly serverId: number;
readonly sendName: string;
}
const GMMailKeys: KeysEnum<GMMail> = {
id: true,
sendRoles: true,
goods: true,
sendTime: true,
endTime: true,
content: true,
gmMailType: true,
updatedAt: true,
serverId: true,
sendName: true
};
export async function mailInit() {
let gmMail = new Map<number, any>();
let mails = await GMMailModel.getMails();
mails.map((o:any)=>{
o.id = o._id.toString();
o.updatedAt = Math.floor(o.updatedAt.getTime()/1000);
let mail = gmMail.get(o.serverId);
if (!mail)
mail = new Map<string, GMMail>();
o.sendName = o.sendName||'系统';
mail.set(o.id, _.pick(o, Object.keys(GMMailKeys)));
gmMail.set(o.serverId, mail);
});
return gmMail;
}
export function setMails(mails:GMMail[], gmMail) {
mails.map((o:any)=>{
o.id = o._id.toString();
o.updatedAt = Math.floor(o.updatedAt.getTime()/1000);
o.sendName = o.sendName||'系统';
let mail = gmMail.get(o.serverId);
if (!mail)
mail = new Map<string, GMMail>();
mail.set(o.id, _.pick(o, Object.keys(GMMailKeys)));
gmMail.set(o.serverId, mail);
});
}

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';
@@ -463,7 +462,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 });

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');
@@ -10,8 +11,7 @@ import { HERO_CE_RATIO, ABI_STAGE, GACHA_TO_FLOOR, REFRESH_TIME, ROBOT_SYS_TYPE,
import { findIndex } from 'underscore';
import { getTimeFunM } from './timeUtil';
import { Floor } from '../domain/activityField/gachaField';
import { WhiteListModel } from '../db/WhiteList';
import { UserModel } from '../db/User';
import { WhiteListModel } from '../db/RegionWhiteList';
const randomName = require("chinese-random-name");
const moment = require('moment');
const crypto = require('crypto');
@@ -659,28 +659,24 @@ export function getFloorStatus(gachaId: number, floor: Floor[]) {
});
}
export async function checkWhiteListWithUid(uid: number) {
let user = await UserModel.findUserByUid(uid);
if(!user) return false;
let { tel, ip, auth } = user;
return await checkWhiteList(tel, ip, auth);
}
export async function checkWhiteList(tel: string, ip: string, auth: number) {
if(auth == 1) {
return true;
}
if(tel) {
let result = await WhiteListModel.checkTel(tel);
export async function checkWhiteList(env: string, ip: string, uid: number, serverId: number) {
if(ip) {
let result = await WhiteListModel.checkIp(env, ip);
if(!!result) return true;
}
if(ip) {
let result = await WhiteListModel.checkIp(ip);
if(uid && serverId) {
let result = await WhiteListModel.checkUid(env, serverId, uid);
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;
}
export function getReasonByWarType(warType: number) {
switch(warType) {
case WAR_TYPE.NORMAL:

View File

@@ -1,119 +1,149 @@
[
{
"id": 0,
"title": "邮件标题",
"title": "&",
"sendName": "&",
"content": "%d",
"time": 24
},
{
"id": 1,
"title": "&",
"sendName": "&",
"content": "您对军团%d的申请被拒绝",
"time": 24
},
{
"id": 2,
"title": "&",
"sendName": "&",
"content": "由于被弹劾,您在军团%d的大将军职务已卸任",
"time": 24
},
{
"id": 3,
"title": "&",
"sendName": "&",
"content": "您被任命为军团%d的大将军",
"time": 24
},
{
"id": 4,
"title": "&",
"sendName": "&",
"content": "您被军团%d踢出",
"time": 24
},
{
"id": 5,
"title": "&",
"sendName": "&",
"content": "亲爱的小将军,您昨日的军团活跃奖励忘记领取了,现已通过邮件发放,请查收",
"time": 24
},
{
"id": 6,
"title": "&",
"sendName": "&",
"content": "您被任命为军团%d的管理",
"time": 24
},
{
"id": 7,
"title": "&",
"sendName": "&",
"content": "您已卸任军团%d的管理",
"time": 24
},
{
"id": 8,
"title": "&",
"sendName": "&",
"content": "小将军您的军团已开启boss%d请赶往支援",
"time": 24
},
{
"id": 9,
"title": "&",
"sendName": "&",
"content": "恭喜小将军军团上下一心已成功压制boss%d您在此次压制中获得如下奖励",
"time": 24
},
{
"id": 10,
"title": "&",
"sendName": "&",
"content": "小将军,您在上周军团练兵场中有奖励尚未领取,奖励如下:",
"time": 24
},
{
"id": 11,
"title": "&",
"sendName": "&",
"content": "小将军,%d赠送您一个%d请查收",
"time": 24
},
{
"id": 12,
"title": "&",
"sendName": "&",
"content": "亲爱的小将军,您在%d赛季结算奖励如下:",
"time": 24
},
{
"id": 13,
"title": "&",
"sendName": "&",
"content": "恭喜小将军,您在%d赛季最终获得了第%d名获得如下奖励",
"time": 24
},
{
"id": 14,
"title": "&",
"sendName": "&",
"content": "亲爱的小将军,您参与军团活动奖励已通过邮件发放,请查收:",
"time": 24
},
{
"id": 15,
"title": "&",
"sendName": "&",
"content": "小将军很抱歉,您在拍卖行的出价已被超过,元宝退还给您,请查收:",
"time": 24
},
{
"id": 16,
"title": "&",
"sendName": "&",
"content": "恭喜小将军,您已在拍卖行成功拍下以下物品,请查收:",
"time": 24
},
{
"id": 17,
"title": "&",
"sendName": "&",
"content": "亲爱的小将军,您昨日的拍卖分红忘记领取了,现已通过邮件发放,请查收",
"time": 24
},
{
"id": 18,
"title": "&",
"sendName": "&",
"content": "亲爱的小将军,您的背包中装备数量已满,请及时清理背包哦。溢出装备已通过邮件发放,请查收",
"time": 24
},
{
"id": 19,
"title": "&",
"sendName": "&",
"content": "亲爱的小将军,派遣任务已开始下一天的任务,前一天未完成的派遣任务已通过邮件发放,请查收",
"time": 24
},
{
"id": 20,
"title": "&",
"sendName": "&",
"content": "亲爱的小将军,以下是您未领取的【月卡】每日奖励,请查收",
"time": 24
},
{
"id": 21,
"content": "修改账号名",
"time": 24
},
{
"id": 22,
"content": "修改公会名或公会公告",
"time": 24
}
]

File diff suppressed because it is too large Load Diff