diff --git a/game-server/app/servers/gm/handler/gmHandler.ts b/game-server/app/servers/gm/handler/gmHandler.ts index fb5a0d1ec..6a40cca8a 100644 --- a/game-server/app/servers/gm/handler/gmHandler.ts +++ b/game-server/app/servers/gm/handler/gmHandler.ts @@ -4,7 +4,7 @@ import { EventRecordModel } from '../../../db/EventRecord'; import { getEvent } from '../../../services/eventSercive'; import { getRandSingleEelm, resResult } from '../../../pubUtils/util'; import { STATUS } from '../../../consts/statusCode'; -import { GMMailModel } from '../../../db/GMMail'; +import { GMMailModel, GMMailType } from '../../../db/GMMail'; import { delGuildActivityRank, getRoleOnlineInfo } from '../../../services/redisService'; import { SendMailFun } from '../../../services/mailService'; import { GM_MAIL_STATUS, GM_MAIL_TYPE, MAIL_TIME_TYPE, REF_CIRCLE_MAIL_TIME } from '../../../consts'; @@ -31,13 +31,41 @@ export class GmHandler { constructor(private app: Application) { } - - //对接gm后台,下发邮件 - async sendMail(msg: { id: string, isPass: boolean }, session: BackendSession) { + async sendSingleMail(msg: { id: string, isPass: boolean }, session: BackendSession) { const uid: number = session.get('uid') let { id, isPass } = msg; - let gmmail = await GMMailModel.getGmMailById(id); + let gmmail = await GMMailModel.getGmMailByIdAndType(id, GM_MAIL_TYPE.SINGLE, true); if(!gmmail) return resResult(STATUS.GM_MAIL_NOT_FOUND); + return await this.sendMail(gmmail, isPass, uid); + } + + async sendSingleMailTxt(msg: { id: string, isPass: boolean }, session: BackendSession) { + const uid: number = session.get('uid') + let { id, isPass } = msg; + let gmmail = await GMMailModel.getGmMailByIdAndType(id, GM_MAIL_TYPE.SINGLE, false); + if(!gmmail) return resResult(STATUS.GM_MAIL_NOT_FOUND); + return await this.sendMail(gmmail, isPass, uid); + } + + async sendServerMail(msg: { id: string, isPass: boolean }, session: BackendSession) { + const uid: number = session.get('uid') + let { id, isPass } = msg; + let gmmail = await GMMailModel.getGmMailByIdAndType(id, GM_MAIL_TYPE.SERVER, true); + if(!gmmail) return resResult(STATUS.GM_MAIL_NOT_FOUND); + return await this.sendMail(gmmail, isPass, uid); + } + + async sendSserverMailTxt(msg: { id: string, isPass: boolean }, session: BackendSession) { + const uid: number = session.get('uid') + let { id, isPass } = msg; + let gmmail = await GMMailModel.getGmMailByIdAndType(id, GM_MAIL_TYPE.SERVER, false); + if(!gmmail) return resResult(STATUS.GM_MAIL_NOT_FOUND); + return await this.sendMail(gmmail, isPass, uid); + } + + //对接gm后台,下发邮件 + async sendMail(gmmail: GMMailType, isPass: boolean, uid: number) { + let id = gmmail._id; let { receivers, mailType, status, timeType, startTime, circleHour, circleDay } = gmmail; if(status != GM_MAIL_STATUS.CREATE) { return resResult(STATUS.GM_MAIL_HAS_SENT); diff --git a/gm-server/app/controller/log.ts b/gm-server/app/controller/log.ts new file mode 100644 index 000000000..f908039b5 --- /dev/null +++ b/gm-server/app/controller/log.ts @@ -0,0 +1,11 @@ +import { Controller } from 'egg'; + +export default class LogController extends Controller { + + public async getGmLog() { + const { ctx } = this; + const { pageSize, page, form } = ctx.request.body; + ctx.body = await ctx.service.log.getGmLog(page, pageSize, form); + } + +} diff --git a/gm-server/app/router.ts b/gm-server/app/router.ts index 406ba6630..87c4675a8 100644 --- a/gm-server/app/router.ts +++ b/gm-server/app/router.ts @@ -94,4 +94,6 @@ export default (app: Application) => { router.post('/api/mail/updatesinglemailtxt', tokenParser, controller.mail.updateGMMail); router.post('/api/mail/updateservermail', tokenParser, controller.mail.updateGMMail); router.post('/api/mail/updateservermailtxt', tokenParser, controller.mail.updateGMMail); + + router.post('/api/log/getgmlog', controller.log.getGmLog); }; diff --git a/gm-server/app/service/GmUser.ts b/gm-server/app/service/GmUser.ts index 4a784979f..2bd3a255d 100644 --- a/gm-server/app/service/GmUser.ts +++ b/gm-server/app/service/GmUser.ts @@ -101,6 +101,7 @@ export default class GMUsers extends Service { return this.ctx.service.utils.resResult(STATUS.INTERNAL_ERR); } } + /** * 创建后台账号 */ diff --git a/gm-server/app/service/Log.ts b/gm-server/app/service/Log.ts new file mode 100644 index 000000000..8425cda11 --- /dev/null +++ b/gm-server/app/service/Log.ts @@ -0,0 +1,21 @@ +import { Service } from 'egg'; +import { STATUS } from '@consts'; +import { SearchLogParam } from '@domain/backEndField/search'; +import { GMRecordModel } from '@db/GMRecord'; + +/** + * Test Service + */ +export default class Log extends Service { + + /** + * 修改用户组 + */ + public async getGmLog(page: number, pageSize: number, form: SearchLogParam) { + const {ctx} = this; + + let list = await GMRecordModel.findByCondition(page, pageSize, form); + return ctx.service.utils.resResult(STATUS.SUCCESS, { list }); + } + +} diff --git a/gm-server/typings/app/controller/index.d.ts b/gm-server/typings/app/controller/index.d.ts index d7f45fcc4..0ec533554 100644 --- a/gm-server/typings/app/controller/index.d.ts +++ b/gm-server/typings/app/controller/index.d.ts @@ -6,6 +6,7 @@ import ExportActivity from '../../../app/controller/activity'; import ExportGame from '../../../app/controller/game'; import ExportGmaccount from '../../../app/controller/gmaccount'; import ExportHome from '../../../app/controller/home'; +import ExportLog from '../../../app/controller/log'; import ExportLogin from '../../../app/controller/login'; import ExportMail from '../../../app/controller/mail'; import ExportUpload from '../../../app/controller/upload'; @@ -17,6 +18,7 @@ declare module 'egg' { game: ExportGame; gmaccount: ExportGmaccount; home: ExportHome; + log: ExportLog; login: ExportLogin; mail: ExportMail; upload: ExportUpload; diff --git a/gm-server/typings/app/service/index.d.ts b/gm-server/typings/app/service/index.d.ts index 89ca7225f..93acc9337 100644 --- a/gm-server/typings/app/service/index.d.ts +++ b/gm-server/typings/app/service/index.d.ts @@ -9,6 +9,7 @@ type AutoInstanceType; game: AutoInstanceType; gmUser: AutoInstanceType; + log: AutoInstanceType; mail: AutoInstanceType; test: AutoInstanceType; utils: AutoInstanceType; diff --git a/shared/consts/constModules/sysConst.ts b/shared/consts/constModules/sysConst.ts index 37fba9b75..ae59f05bd 100644 --- a/shared/consts/constModules/sysConst.ts +++ b/shared/consts/constModules/sysConst.ts @@ -980,4 +980,18 @@ export enum GM_API_TYPE { del = 'del', // 删 update = 'update', // 改 find = 'find', // 查 +} + +export enum LOG_TYPE { + LOGIN = 'login', // 登录 + LOGINOUT = 'logout', // 登出 + CE_CHANGE = 'ceChange', // 战力变化 + PAY = 'pay', // 充值 + ITEM_CHANGE = 'itemChange', // 道具变动 + RECEIVE_MAIL = 'receiveMail', // 领取邮件 +} + +export enum CE_CHANGE_REASON { + HERO = 'hero', // 武将 + } \ No newline at end of file diff --git a/shared/db/GMMail.ts b/shared/db/GMMail.ts index 98b11f98d..a8844dd06 100644 --- a/shared/db/GMMail.ts +++ b/shared/db/GMMail.ts @@ -140,6 +140,11 @@ export default class GMMail extends BaseModel { return result; } + public static async getGmMailByIdAndType(_id: string, mailType: GM_MAIL_TYPE, hasGoods: boolean) { + const result: GMMailType = await GMMailModel.findOne({ _id, mailType, hasGoods }).lean(); + return result; + } + private static getSearchObj(form: SearchMailParam) { let searchObj = {}; if(form.createTimeStart) searchObj['createdAt'] = { $gt: new Date(form.createTimeStart * 1000) }; diff --git a/shared/db/GMRecord.ts b/shared/db/GMRecord.ts index 3018943f6..6c574644f 100644 --- a/shared/db/GMRecord.ts +++ b/shared/db/GMRecord.ts @@ -1,6 +1,7 @@ import BaseModel from './BaseModel'; import { index, getModelForClass, prop, DocumentType, ReturnModelType, mongoose } from '@typegoose/typegoose'; import { gameData } from '../pubUtils/data'; +import { SearchLogParam } from '../domain/backEndField/search'; /** * GM用户组接口 @@ -22,6 +23,9 @@ export default class GMRecord extends BaseModel { @prop({ required: true }) apiName: string; + @prop({ required: true }) + apiModule: string; + @prop({ required: true }) body: string; @@ -30,10 +34,28 @@ export default class GMRecord extends BaseModel { public static async createRecord(uid: number, env: string, api: string, body: string, result: string) { let dicApi = gameData.apiByUrl.get(api); - const r = await GMRecordModel.insertMany({uid, env, api, apiName: dicApi?.name, body, result}); + const r = await GMRecordModel.insertMany({uid, env, api, apiName: dicApi?.name, apiModule: dicApi?.module, body, result}); return r; } + private static getSearchObj(form: SearchLogParam) { + let searchObj = {}; + if (form.env) searchObj['env'] = form.env; + if (form.uid) searchObj['uid'] = form.uid; + if (form.apiModule) searchObj['apiModule'] = form.apiModule; + if (form.api) searchObj['api'] = form.api; + 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, form: SearchLogParam = {}) { + let searchObj = GMRecordModel.getSearchObj(form); + const result: GMRecordType[] = await GMRecordModel.find(searchObj).limit(pageSize).skip((page - 1) * pageSize).sort({ createdAt: -1 }).select('-_id').lean({ getters: true, virtuals: true }); + return result; + + } } export let GMRecordModel: ReturnModelType; diff --git a/shared/db/UserLog.ts b/shared/db/UserLog.ts new file mode 100644 index 000000000..7cd9185c9 --- /dev/null +++ b/shared/db/UserLog.ts @@ -0,0 +1,104 @@ +import BaseModel from './BaseModel'; +import { index, getModelForClass, prop, DocumentType } from '@typegoose/typegoose'; + +class Reward { + @prop({ required: true }) + id: number; + @prop({ required: true }) + count: number; +} + +/** + * 玩家充值订单 +*/ +@index({ localOrderID: 1 }) + +export default class UserLog extends BaseModel { + + @prop({ required: true }) + type: string; // 类型 LOG_TYPE + + @prop({ required: true }) + uid: number; // uid + + @prop({ required: true }) + roleId: string; // 角色id + + @prop({ required: true }) + roleName: string; // 角色名 + + @prop({ required: false }) + ip: string; // ip + + // 战力相关 + @prop({ required: false }) + inc: number; // 改变值 战力改变/道具数量改变 + + @prop({ required: false }) + count: number; // 变化后的值 战力改变/道具数量改变 + + @prop({ required: false }) + ceChangeReason: number; // 战力变化原因 + + @prop({ required: false }) + ceChangeReasonInfo: string; // 战力变化原因信息,如武将id等 + + // 充值相关 + @prop({ required: false }) + productId: string; // 商品id + + @prop({ required: false }) + productName: string; // 商品名字 + + @prop({ required: false }) + price: number; // 充值金额 + + @prop({ required: false }) + isYuanbao: boolean; // 是否为代币 + + @prop({ required: false }) + localOrderId: string; // 订单id + + @prop({ required: false }) + totalPay: number; // 总充值金额 + + @prop({ required: false }) + orderStatus: number; // 订单状态 + + // 道具相关 + @prop({ required: false }) + itemId: number; // 道具id + + @prop({ required: false }) + itemName: string; // 道具名 + + @prop({ required: false }) + itid: number; // 道具类型 + + @prop({ required: false }) + itemChangeModule: string; // 道具变更模块 + + @prop({ required: false }) + itemChangeReason: number; // 道具变更来源 + + // 邮件日志 + @prop({ required: false }) + mailId: string; // 邮件id + + @prop({ required: false, type: Reward, _id: false }) + goods: Reward[]; // 邮件附带道具 + + @prop({ required: false }) + mailContent: string; // 邮件正文 + + @prop({ required: false }) + mailTitle: string; // 邮件标题 + + @prop({ required: false }) + mailSendName: string; // 邮件发件人 +} + +export const UserLogModel = getModelForClass(UserLog); + +export interface UserLogModelType extends Pick, keyof UserLog> { } +export type UserLogModelTypeParam = Partial; // 将所有字段变成可选项 \ No newline at end of file diff --git a/shared/domain/backEndField/search.ts b/shared/domain/backEndField/search.ts index 03b324ef5..3612af716 100644 --- a/shared/domain/backEndField/search.ts +++ b/shared/domain/backEndField/search.ts @@ -71,4 +71,13 @@ export interface SearchGiftCodeDetailParam { code?: string; roleId?: string; roleName?: string; +} + +export interface SearchLogParam { + env?: string; + apiModule?: string; + api?: string; + createTimeStart?: number; + createTimeEnd?: number; + uid?: number; } \ No newline at end of file diff --git a/shared/pubUtils/logUtil.ts b/shared/pubUtils/logUtil.ts new file mode 100644 index 000000000..1480718f4 --- /dev/null +++ b/shared/pubUtils/logUtil.ts @@ -0,0 +1,3 @@ +export function saveUserLog() { + +} \ No newline at end of file diff --git a/shared/resource/jsons/dic_api.json b/shared/resource/jsons/dic_api.json index bcc551482..cb5ec1473 100644 --- a/shared/resource/jsons/dic_api.json +++ b/shared/resource/jsons/dic_api.json @@ -471,7 +471,7 @@ { "id": 68, "api": "/api/mail/getcreatesinglemailtxt", - "name": "获取火箭单人无道具邮件列表", + "name": "获取创建单人无道具邮件列表", "module": "mail", "type": "find" }, @@ -554,146 +554,167 @@ }, { "id": 80, - "api": "gm.gmHandler.sendMail", - "name": "发送邮件", + "api": "gm.gmHandler.sendSingleMail", + "name": "审批单人有道具邮件", "module": "mail", "type": "update" }, { "id": 81, + "api": "gm.gmHandler.sendSingleMailTxt", + "name": "审批单人无道具邮件", + "module": "mail", + "type": "update" + }, + { + "id": 82, + "api": "gm.gmHandler.sendServerMail", + "name": "审批全服有道具邮件", + "module": "mail", + "type": "update" + }, + { + "id": 83, + "api": "gm.gmHandler.sendServerMailTxt", + "name": "审批全服无道具邮件", + "module": "mail", + "type": "update" + }, + { + "id": 84, "api": "gm.gmHandler.setGuildActivityDebug", "name": "开启军团活动", "module": "guildactivity", "type": "update" }, { - "id": 82, + "id": 85, "api": "gm.gmHandler.cancelGuildActivityDebug", "name": "取消军团活动", "module": "guildactivity", "type": "update" }, { - "id": 83, + "id": 86, "api": "/api/game/getregions", "name": "获取所有大区", "module": "server", "type": "find" }, { - "id": 84, + "id": 87, "api": "/api/game/getservers", "name": "获取所有小区", "module": "server", "type": "find" }, { - "id": 85, + "id": 88, "api": "/api/game/getregionstategy", "name": "获取大区策略", "module": "server", "type": "find" }, { - "id": 86, + "id": 89, "api": "/api/game/getwhitelist", "name": "获取白名单", "module": "server", "type": "find" }, { - "id": 87, + "id": 90, "api": "/api/game/updatewhitelist", "name": "更新白名单", "module": "server", "type": "update" }, { - "id": 88, + "id": 91, "api": "/api/game/deletewhitelist", "name": "删除白名单", "module": "server", "type": "delete" }, { - "id": 89, + "id": 92, "api": "/api/game/stopserverregister", "name": "小区停止注册", "module": "server", "type": "update" }, { - "id": 90, + "id": 93, "api": "/api/game/swicthserverstatus", "name": "切换服务器状态", "module": "server", "type": "update" }, { - "id": 91, + "id": 94, "api": "gm.gmServerHandler.saveRegionConf", "name": "保存大区设置", "module": "server", "type": "update" }, { - "id": 92, + "id": 95, "api": "gm.gmServerHandler.createNewServer", "name": "手动开服", "module": "server", "type": "update" }, { - "id": 93, + "id": 96, "api": "gm.gmServerHandler.startMaintenance", "name": "开始维护", "module": "server", "type": "update" }, { - "id": 94, + "id": 97, "api": "gm.gmServerHandler.startRegionMaintenance", "name": "开始大区维护", "module": "server", "type": "update" }, { - "id": 95, + "id": 98, "api": "gm.gmServerHandler.stopMaintenance", "name": "停止维护", "module": "server", "type": "update" }, { - "id": 96, + "id": 99, "api": "/api/upload/hotupdate", "name": "上传热更新", "module": "upload", "type": "update" }, { - "id": 97, + "id": 100, "api": "/api/upload/uploadjson", "name": "上传json", "module": "upload", "type": "update" }, { - "id": 98, + "id": 101, "api": "/web/reloadresource", "name": "加载资源(web)", "module": "upload", "type": "update" }, { - "id": 99, + "id": 102, "api": "/api/upload/reloadresource", "name": "加载资源(后台)", "module": "upload", "type": "update" }, { - "id": 100, + "id": 103, "api": "gm.gmHandler.reloadResource", "name": "加载资源(游戏)", "module": "upload",