feat(theme-3): sync inbox/announcements/presence/deposit/search from main

This commit is contained in:
2026-06-18 10:02:32 +08:00
parent 0d430857c7
commit 6881d325d5
87 changed files with 6944 additions and 964 deletions

View File

@@ -61,11 +61,12 @@ export class AdminStaffService {
roleName: u.adminRole?.role?.name ?? null,
lastLoginAt: u.auth?.lastLoginAt ?? null,
createdAt: u.createdAt,
visibleMenus: u.visibleMenus,
})),
};
}
async createStaff(data: { username: string; password: string; roleCode: string }) {
async createStaff(data: { username: string; password: string; roleCode: string; visibleMenus?: string }) {
const username = data.username.trim();
if (!username) throw appBadRequest('USERNAME_REQUIRED');
if (data.password.length < 8) throw appBadRequest('PASSWORD_MIN_LENGTH');
@@ -86,6 +87,7 @@ export class AdminStaffService {
userType: 'ADMIN',
auth: { create: { passwordHash: hash } },
adminRole: { create: { roleId: role.id } },
visibleMenus: data.visibleMenus,
},
include: {
adminRole: { include: { role: { select: { code: true, name: true } } } },
@@ -99,12 +101,13 @@ export class AdminStaffService {
status: user.status,
role: user.adminRole?.role?.code ?? null,
roleName: user.adminRole?.role?.name ?? null,
visibleMenus: user.visibleMenus,
};
}
async updateStaff(
staffId: bigint,
data: { status?: string; roleCode?: string; password?: string },
data: { status?: string; roleCode?: string; password?: string; visibleMenus?: string },
) {
const user = await this.prisma.user.findFirst({
where: { id: staffId, userType: 'ADMIN', deletedAt: null },
@@ -140,6 +143,13 @@ export class AdminStaffService {
}
}
if (data.visibleMenus !== undefined) {
await this.prisma.user.update({
where: { id: staffId },
data: { visibleMenus: data.visibleMenus },
});
}
let plainPassword: string | undefined;
if (data.password !== undefined) {
if (data.password.length < 8) throw appBadRequest('PASSWORD_MIN_LENGTH');
@@ -163,10 +173,40 @@ export class AdminStaffService {
status: refreshed!.status,
role: refreshed!.adminRole?.role?.code ?? null,
roleName: refreshed!.adminRole?.role?.name ?? null,
visibleMenus: refreshed!.visibleMenus,
...(plainPassword ? { password: plainPassword } : {}),
};
}
async deleteStaff(staffId: bigint, operatorId?: bigint) {
if (operatorId && staffId === operatorId) {
throw appBadRequest('CANNOT_DELETE_SELF');
}
const user = await this.prisma.user.findFirst({
where: { id: staffId, userType: 'ADMIN', deletedAt: null },
include: { adminRole: { include: { role: true } } },
});
if (!user) throw appNotFound('STAFF_NOT_FOUND');
if (user.adminRole?.role?.code === 'SUPER_ADMIN') {
const superAdminCount = await this.prisma.user.count({
where: {
userType: 'ADMIN',
deletedAt: null,
adminRole: { role: { code: 'SUPER_ADMIN' } },
},
});
if (superAdminCount <= 1) {
throw appBadRequest('CANNOT_DELETE_LAST_SUPER_ADMIN');
}
}
return this.prisma.user.update({
where: { id: staffId },
data: { deletedAt: new Date(), status: 'DISABLED' },
});
}
async resetPlayerPassword(playerId: bigint, password?: string) {
const user = await this.prisma.user.findFirst({
where: { id: playerId, userType: 'PLAYER', deletedAt: null },