feat(promo): HQ 推广码订单只计已完成并补扫码订单快链

列表与详情的订单数/转化率按 COMPLETED 实时统计;扫码、订单、事件 ID 可跳到对应页。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-08-28 12:55:19 +08:00
parent 737efb89a3
commit fccfd7abbe
15 changed files with 421 additions and 124 deletions
@@ -37,6 +37,7 @@ type OrderFilterInput = Pick<
| 'createdTo'
| 'excludeTest'
| 'deliveryType'
| 'promoCodeId'
>;
@Injectable()
@@ -94,7 +95,7 @@ export class AdminOrdersService {
skip: (page - 1) * pageSize,
take: pageSize,
include: {
user: { select: { id: true, userNo: true, phone: true, nickname: true } },
user: { select: { id: true, userNo: true, phone: true, nickname: true, hqRemark: true } },
delivery: {
select: {
provider: true,
@@ -190,6 +191,10 @@ export class AdminOrdersService {
if (query.createdTo) where.createdAt.lte = this.endOfDay(query.createdTo);
}
if (query.excludeTest) where.isTest = false;
const promoCodeId = query.promoCodeId?.trim();
if (promoCodeId && /^\d+$/.test(promoCodeId)) {
where.promoCodeId = BigInt(promoCodeId);
}
return where;
}
@@ -252,6 +257,7 @@ export class AdminOrdersService {
userNo: true,
phone: true,
nickname: true,
hqRemark: true,
deviceKey: true,
phoneVerifiedAt: true,
},
@@ -81,6 +81,13 @@ export class AdminUsersService {
if (query.phone) where.phone = { contains: query.phone };
if (query.userNo) where.userNo = { contains: query.userNo };
const userId = query.userId?.trim();
if (userId) {
if (!/^\d+$/.test(userId)) {
return serializeBigInt({ items: [], total: 0, page, pageSize });
}
where.id = BigInt(userId);
}
if (query.deviceKey) where.deviceKey = query.deviceKey;
if (query.status !== undefined) where.status = query.status;
if (query.phoneVerified === '1') where.phoneVerifiedAt = { not: null };
@@ -48,6 +48,11 @@ export class AdminUsersQueryDto extends PaginationQueryDto {
@IsString()
userNo?: string;
/** 精确匹配用户主键,供订单等页的用户快链带入筛选 */
@IsOptional()
@IsString()
userId?: string;
@IsOptional()
@IsString()
deviceKey?: string;
@@ -116,6 +121,11 @@ export class AdminOrdersQueryDto extends PaginationQueryDto {
@IsOptional()
@IsIn(['LOCAL', 'CROSS_CITY', 'ON_SITE_PICKUP'])
deliveryType?: string;
/** 按下单时绑定的推广码筛选 */
@IsOptional()
@IsString()
promoCodeId?: string;
}
/** HQ 订单导出(筛选 + 勾选范围) */
@@ -174,6 +184,10 @@ export class AdminOrdersExportDto {
@IsOptional()
@IsIn(['LOCAL', 'CROSS_CITY', 'ON_SITE_PICKUP'])
deliveryType?: string;
@IsOptional()
@IsString()
promoCodeId?: string;
}
/** 概览页用户/订单 ECharts 聚合筛选 */