合伙人端登录验证调整还有日志落地
This commit is contained in:
@@ -0,0 +1,20 @@
|
||||
import { Controller, Get, Param, Query, UseGuards } from '@nestjs/common';
|
||||
import { HqAuthGuard } from '../../common/guards/hq-auth.guard';
|
||||
import { AdminPartnerLogsService } from './admin-partner-logs.service';
|
||||
import { AdminPartnerLogsQueryDto } from './dto/admin-query.dto';
|
||||
|
||||
@Controller('admin/logs/partners')
|
||||
@UseGuards(HqAuthGuard)
|
||||
export class AdminPartnerLogsController {
|
||||
constructor(private readonly service: AdminPartnerLogsService) {}
|
||||
|
||||
@Get()
|
||||
list(@Query() query: AdminPartnerLogsQueryDto) {
|
||||
return this.service.list(query);
|
||||
}
|
||||
|
||||
@Get(':id')
|
||||
detail(@Param('id') id: string) {
|
||||
return this.service.detail(id);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,160 @@
|
||||
import { Injectable, NotFoundException } from '@nestjs/common';
|
||||
import { Prisma } from '@prisma/client';
|
||||
import {
|
||||
eventNamesForPartnerLogCategory,
|
||||
resolvePartnerLogCategory,
|
||||
} from '@dukang/shared-types';
|
||||
import { PrismaService } from '../../common/prisma/prisma.module';
|
||||
import { serializeBigInt } from '../../common/decorators/current-user.decorator';
|
||||
import type { AdminPartnerLogsQueryDto } from './dto/admin-query.dto';
|
||||
|
||||
@Injectable()
|
||||
export class AdminPartnerLogsService {
|
||||
constructor(private readonly prisma: PrismaService) {}
|
||||
|
||||
async list(query: AdminPartnerLogsQueryDto) {
|
||||
const page = query.page ?? 1;
|
||||
const pageSize = query.pageSize ?? 20;
|
||||
const partnerIds = await this.resolvePartnerIds(query);
|
||||
if (partnerIds && partnerIds.length === 0) {
|
||||
return { items: [], total: 0, page, pageSize };
|
||||
}
|
||||
|
||||
const where = this.buildWhere(query, partnerIds);
|
||||
const [rows, total] = await Promise.all([
|
||||
this.prisma.logPartnerAnalytics.findMany({
|
||||
where,
|
||||
orderBy: { createdAt: 'desc' },
|
||||
skip: (page - 1) * pageSize,
|
||||
take: pageSize,
|
||||
}),
|
||||
this.prisma.logPartnerAnalytics.count({ where }),
|
||||
]);
|
||||
|
||||
const items = await this.enrichRows(rows);
|
||||
return serializeBigInt({ items, total, page, pageSize });
|
||||
}
|
||||
|
||||
async detail(id: string) {
|
||||
const row = await this.prisma.logPartnerAnalytics.findUnique({ where: { id: BigInt(id) } });
|
||||
if (!row) throw new NotFoundException('日志不存在');
|
||||
const [item] = await this.enrichRows([row]);
|
||||
return serializeBigInt(item);
|
||||
}
|
||||
|
||||
private buildWhere(
|
||||
query: AdminPartnerLogsQueryDto,
|
||||
partnerIds?: bigint[],
|
||||
): Prisma.LogPartnerAnalyticsWhereInput {
|
||||
const where: Prisma.LogPartnerAnalyticsWhereInput = {};
|
||||
if (partnerIds) where.partnerId = { in: partnerIds };
|
||||
if (query.partnerAccountId) where.partnerAccountId = BigInt(query.partnerAccountId);
|
||||
const categoryEvents = query.eventName
|
||||
? [query.eventName]
|
||||
: query.category
|
||||
? eventNamesForPartnerLogCategory(query.category)
|
||||
: undefined;
|
||||
if (categoryEvents?.length) where.eventName = { in: categoryEvents };
|
||||
if (query.from || query.to) {
|
||||
where.createdAt = {
|
||||
...(query.from ? { gte: new Date(query.from) } : {}),
|
||||
...(query.to ? { lte: new Date(query.to) } : {}),
|
||||
};
|
||||
}
|
||||
return where;
|
||||
}
|
||||
|
||||
private async resolvePartnerIds(query: AdminPartnerLogsQueryDto): Promise<bigint[] | undefined> {
|
||||
if (query.partnerId) return [BigInt(query.partnerId)];
|
||||
|
||||
const partnerWhere: Prisma.PartnerWhereInput = {};
|
||||
if (query.companyName) partnerWhere.companyName = { contains: query.companyName };
|
||||
|
||||
if (query.partnerAccountId || query.phone) {
|
||||
const accountWhere: Prisma.PartnerAccountWhereInput = {};
|
||||
if (query.partnerAccountId) accountWhere.id = BigInt(query.partnerAccountId);
|
||||
if (query.phone) accountWhere.phone = { contains: query.phone };
|
||||
const accounts = await this.prisma.partnerAccount.findMany({
|
||||
where: accountWhere,
|
||||
select: { partnerId: true },
|
||||
take: 100,
|
||||
});
|
||||
if (accounts.length === 0) return [];
|
||||
const ids = [...new Set(accounts.map((a) => a.partnerId))];
|
||||
if (query.companyName) {
|
||||
const partners = await this.prisma.partner.findMany({
|
||||
where: { id: { in: ids }, ...partnerWhere },
|
||||
select: { id: true },
|
||||
});
|
||||
return partners.map((p) => p.id);
|
||||
}
|
||||
return ids;
|
||||
}
|
||||
|
||||
if (query.companyName) {
|
||||
const partners = await this.prisma.partner.findMany({
|
||||
where: partnerWhere,
|
||||
select: { id: true },
|
||||
take: 100,
|
||||
});
|
||||
return partners.map((p) => p.id);
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
private async enrichRows(
|
||||
rows: Array<{
|
||||
id: bigint;
|
||||
partnerAccountId: bigint | null;
|
||||
partnerId: bigint;
|
||||
eventName: string;
|
||||
clientApp: string | null;
|
||||
refType: string | null;
|
||||
refId: bigint | null;
|
||||
extraJson: unknown;
|
||||
createdAt: Date;
|
||||
}>,
|
||||
) {
|
||||
const partnerIds = [...new Set(rows.map((r) => r.partnerId))];
|
||||
const accountIds = [...new Set(rows.map((r) => r.partnerAccountId).filter((id): id is bigint => id != null))];
|
||||
|
||||
const [partners, accounts] = await Promise.all([
|
||||
partnerIds.length
|
||||
? this.prisma.partner.findMany({
|
||||
where: { id: { in: partnerIds } },
|
||||
select: { id: true, companyName: true },
|
||||
})
|
||||
: Promise.resolve([]),
|
||||
accountIds.length
|
||||
? this.prisma.partnerAccount.findMany({
|
||||
where: { id: { in: accountIds } },
|
||||
select: { id: true, name: true, phone: true },
|
||||
})
|
||||
: Promise.resolve([]),
|
||||
]);
|
||||
|
||||
const partnerMap = new Map(partners.map((p) => [p.id.toString(), p] as const));
|
||||
const accountMap = new Map(accounts.map((a) => [a.id.toString(), a] as const));
|
||||
|
||||
return rows.map((row) => {
|
||||
const partner = partnerMap.get(row.partnerId.toString());
|
||||
const account = row.partnerAccountId ? accountMap.get(row.partnerAccountId.toString()) : undefined;
|
||||
return {
|
||||
id: row.id.toString(),
|
||||
partnerId: row.partnerId.toString(),
|
||||
partnerAccountId: row.partnerAccountId?.toString() ?? null,
|
||||
accountName: account?.name ?? null,
|
||||
accountPhone: account?.phone ?? null,
|
||||
companyName: partner?.companyName ?? null,
|
||||
category: resolvePartnerLogCategory(row.eventName),
|
||||
eventName: row.eventName,
|
||||
clientApp: row.clientApp,
|
||||
refType: row.refType,
|
||||
refId: row.refId?.toString() ?? null,
|
||||
extraJson: (row.extraJson as Record<string, unknown> | null) ?? null,
|
||||
createdAt: row.createdAt,
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -309,6 +309,40 @@ export class AdminStoreLogsQueryDto extends PaginationQueryDto {
|
||||
to?: string;
|
||||
}
|
||||
|
||||
export class AdminPartnerLogsQueryDto extends PaginationQueryDto {
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
partnerId?: string;
|
||||
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
partnerAccountId?: string;
|
||||
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
phone?: string;
|
||||
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
companyName?: string;
|
||||
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
category?: string;
|
||||
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
eventName?: string;
|
||||
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
from?: string;
|
||||
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
to?: string;
|
||||
}
|
||||
|
||||
export class AdminHqLogsQueryDto extends PaginationQueryDto {
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
|
||||
@@ -25,6 +25,8 @@ import { AdminUserLogsController } from './admin-user-logs.controller';
|
||||
import { AdminUserLogsService } from './admin-user-logs.service';
|
||||
import { AdminStoreLogsController } from './admin-store-logs.controller';
|
||||
import { AdminStoreLogsService } from './admin-store-logs.service';
|
||||
import { AdminPartnerLogsController } from './admin-partner-logs.controller';
|
||||
import { AdminPartnerLogsService } from './admin-partner-logs.service';
|
||||
import { AdminHqLogsController } from './admin-hq-logs.controller';
|
||||
import { AdminHqLogsService } from './admin-hq-logs.service';
|
||||
import { AdminTicketsController } from './admin-tickets.controller';
|
||||
@@ -63,6 +65,7 @@ import { AdminRedeemDebugService } from './admin-redeem-debug.service';
|
||||
AdminProductsController,
|
||||
AdminUserLogsController,
|
||||
AdminStoreLogsController,
|
||||
AdminPartnerLogsController,
|
||||
AdminHqLogsController,
|
||||
AdminTicketsController,
|
||||
AdminXiaofeixiaController,
|
||||
@@ -84,6 +87,7 @@ import { AdminRedeemDebugService } from './admin-redeem-debug.service';
|
||||
AdminProductsService,
|
||||
AdminUserLogsService,
|
||||
AdminStoreLogsService,
|
||||
AdminPartnerLogsService,
|
||||
AdminHqLogsService,
|
||||
AdminTicketsService,
|
||||
AdminXiaofeixiaService,
|
||||
|
||||
Reference in New Issue
Block a user