feat(player/admin/api): 站内邮箱、在线状态、员工菜单权限与内容管理增强
API: - 新增 player-messages 域:充值审核通过/拒绝、Banner/公告推广消息,支持多语言模板 - 新增 presence 域:Redis 心跳在线状态,管理端可查询在线玩家数 - User 表增加 visible_menus 字段;新增 player_messages 表及迁移 - 充值审核通过/拒绝时按系统配置自动写入玩家站内消息 - 管理端新增 GET /deposit-orders/pending-count、GET /presence/online-count - 玩家端新增消息 CRUD、presence/ping、home 返回 inbox 开关配置 - 员工管理支持 visibleMenus 配置与删除保护(不能删自己/最后超管) - SystemConfig 增加 inbox 功能开关及各类通知开关 Admin: - 员工管理:按角色默认菜单 + 可勾选可见菜单项 - ManageLayout:按 visibleMenus 过滤侧栏;充值待审数量角标轮询 - Contents:富文本编辑器、图片字段组件重构 - DashboardPlayers:展示在线玩家数;AdminPlayerStatusCell 在线状态列 - 多页面 i18n 与权限细节调整 Player: - 站内邮箱中心(InboxHub):消息列表/详情、未读角标、一键已读/删除 - 公告列表与详情页;走马灯可跳转详情 - 客服 Modal 改为 Panel,与邮箱 Hub 整合 - 充值状态轮询通知;presence 心跳;BetSlip 清空二次确认 - HomeView 今日赛事板块;FootballView 等体验优化 Shared: 新增 CANNOT_DELETE_SELF、STAFF_NOT_FOUND、MESSAGE_NOT_FOUND 等错误码 Docs: 玩家端缺失功能分析文档 Chore: 移除 .agents/skills 设计类 skill 文件 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -7,6 +7,8 @@ import { FundsPostingService } from '../ledger/funds-posting.service';
|
||||
import { AgentCreditService } from '../agent/agent-credit.service';
|
||||
import { appBadRequest } from '../../shared/common/app-error';
|
||||
import { deleteUploadFileByUrl } from '../../shared/uploads/delete-upload-file';
|
||||
import { PlayerMessagesService } from '../player-messages/player-messages.service';
|
||||
import { SystemConfigService } from '../../shared/config/system-config.service';
|
||||
|
||||
function generateOrderNo(): string {
|
||||
const ts = Date.now().toString(36).toUpperCase();
|
||||
@@ -49,6 +51,8 @@ export class DepositService {
|
||||
private prisma: PrismaService,
|
||||
private funds: FundsPostingService,
|
||||
private credit: AgentCreditService,
|
||||
private playerMessages: PlayerMessagesService,
|
||||
private systemConfig: SystemConfigService,
|
||||
) {}
|
||||
|
||||
// ============ Payment Methods (Admin CRUD) ============
|
||||
@@ -254,6 +258,14 @@ export class DepositService {
|
||||
|
||||
// ============ Deposit Orders ============
|
||||
|
||||
private async getPlayerLocale(playerId: bigint, tx: Prisma.TransactionClient | PrismaService = this.prisma) {
|
||||
const user = await tx.user.findUnique({
|
||||
where: { id: playerId },
|
||||
select: { locale: true },
|
||||
});
|
||||
return user?.locale ?? 'en-US';
|
||||
}
|
||||
|
||||
private async recordDepositAudit(
|
||||
client: AuditLogWriter,
|
||||
data: {
|
||||
@@ -670,6 +682,10 @@ export class DepositService {
|
||||
};
|
||||
}
|
||||
|
||||
async countPendingDepositOrders(): Promise<number> {
|
||||
return this.prisma.depositOrder.count({ where: { status: 'PENDING' } });
|
||||
}
|
||||
|
||||
async approveDepositOrder(
|
||||
orderId: bigint,
|
||||
operatorId: bigint,
|
||||
@@ -722,6 +738,22 @@ export class DepositService {
|
||||
await this.credit.recalculateUsedCredit(parentAgentId, tx);
|
||||
}
|
||||
|
||||
const playerLocale = await this.getPlayerLocale(order.playerId, tx);
|
||||
const inboxNotify = await this.systemConfig.getInboxNotifySettings();
|
||||
if (inboxNotify.inboxEnabled && inboxNotify.deposit) {
|
||||
await this.playerMessages.createDepositApprovedMessage(
|
||||
order.playerId,
|
||||
{
|
||||
depositOrderId: orderId,
|
||||
orderNo: order.orderNo,
|
||||
amount: order.amount.toString(),
|
||||
approvedAmount: creditAmount.toString(),
|
||||
locale: playerLocale,
|
||||
},
|
||||
tx,
|
||||
);
|
||||
}
|
||||
|
||||
return { success: true };
|
||||
});
|
||||
}
|
||||
@@ -753,6 +785,18 @@ export class DepositService {
|
||||
remark: reason,
|
||||
});
|
||||
|
||||
const playerLocale = await this.getPlayerLocale(order.playerId);
|
||||
const inboxNotify = await this.systemConfig.getInboxNotifySettings();
|
||||
if (inboxNotify.inboxEnabled && inboxNotify.deposit) {
|
||||
await this.playerMessages.createDepositRejectedMessage(order.playerId, {
|
||||
depositOrderId: orderId,
|
||||
orderNo: order.orderNo,
|
||||
amount: order.amount.toString(),
|
||||
rejectReason: reason,
|
||||
locale: playerLocale,
|
||||
});
|
||||
}
|
||||
|
||||
return { success: true };
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user