v4.0.18版本更新

This commit is contained in:
2026-09-08 13:47:42 +08:00
parent 23ba639e9b
commit 253430b291
14 changed files with 136 additions and 25 deletions
@@ -1,5 +1,6 @@
import { Controller, Get } from '@nestjs/common';
import {
isShowStoreRedeemCountEnabled,
parseMiniHomeBanners,
resolveClientBrandRuntime,
resolveMiniShareRuntime,
@@ -44,6 +45,7 @@ export class ClientConfigController {
(env.PARTNER_ONBOARD_CS_HINT ?? '').trim() ||
'使用问题、提现问题等随时可联系【杜康好客】客服',
share,
showStoreRedeemCount: isShowStoreRedeemCountEnabled(env),
};
}
}
@@ -1,4 +1,5 @@
import { Body, Controller, Delete, Get, Param, Post, Put, Query, UseGuards } from '@nestjs/common';
import { Body, Controller, Delete, Get, Param, Post, Put, Query, Res, UseGuards } from '@nestjs/common';
import type { Response } from 'express';
import { HqAuthGuard } from '../../common/guards/hq-auth.guard';
import {
HqPermissionGuard,
@@ -80,6 +81,17 @@ export class AdminPartnersController {
return this.assoc.listUsers(BigInt(id), Number(page) || 1, Number(pageSize) || 20);
}
@Get(':id/assoc/qrcode')
async assocQrcode(@Param('id') id: string, @Res() res: Response) {
const { buffer, fileName } = await this.assoc.getQrcodeBuffer(BigInt(id));
res.setHeader('Content-Type', 'image/png');
res.setHeader(
'Content-Disposition',
`attachment; filename="${fileName}"; filename*=UTF-8''${encodeURIComponent(fileName)}`,
);
res.send(buffer);
}
@Post(':id/assoc/qrcode')
regenQrcode(@Param('id') id: string) {
return this.assoc.ensureQrcode(BigInt(id), true);
@@ -5,7 +5,7 @@ import {
Logger,
NotFoundException,
} from '@nestjs/common';
import { loadAppConfig, ClientApp, SmsScene } from '@dukang/shared-types';
import { loadAppConfig, ClientApp, SmsScene, isShowStoreRedeemCountEnabled } from '@dukang/shared-types';
import { PARTNER_STAFF_ROLE_LABELS, PartnerStaffRole, type PartnerLeaderboardPeriod } from '@dukang/shared-types';
import { normalizeStorePackageImageUrls } from '@dukang/shared-types';
import {
@@ -36,6 +36,7 @@ import {
} from '../../common/test-whitelist/test-whitelist.service';
import { WecomMessagePushService } from '../../integrations/wecom/wecom-message-push.service';
import { formatPartnerWecomLabel } from './wecom-submitter-label';
import { SystemConfigService } from '../../common/system-config/system-config.service';
function haversineMeters(lat1: number, lng1: number, lat2: number, lng2: number): number {
const toRad = (d: number) => (d * Math.PI) / 180;
@@ -86,6 +87,7 @@ export class StoreService {
private readonly tencentLbs: TencentLbsProvider,
private readonly testWhitelist: TestWhitelistService,
private readonly wecomPush: WecomMessagePushService,
private readonly systemConfig: SystemConfigService,
) {}
/** 门店进入 PENDING 或 HQ 新建时通知企微(失败不挡业务) */
@@ -218,11 +220,12 @@ export class StoreService {
latitude?: unknown;
longitude?: unknown;
sortOrder?: number;
redeemCount: number;
redeemCount?: number;
};
const showRedeemCount = isShowStoreRedeemCountEnabled(this.systemConfig.getMergedEnv());
const redeemGroups =
visible.length === 0
!showRedeemCount || visible.length === 0
? []
: await this.prisma.redeemRecord.groupBy({
by: ['storeId'],
@@ -252,7 +255,9 @@ export class StoreService {
items.push({
...mapped,
distanceMeters,
redeemCount: redeemCountByStore.get(store.id.toString()) ?? 0,
...(showRedeemCount
? { redeemCount: redeemCountByStore.get(store.id.toString()) ?? 0 }
: {}),
});
}
@@ -286,6 +291,7 @@ export class StoreService {
throw new NotFoundException('门店不存在');
}
const coords = await this.ensureStoreCoordinates(store);
const showRedeemCount = isShowStoreRedeemCountEnabled(this.systemConfig.getMergedEnv());
const [media, packageRows, redeemCount] = await Promise.all([
this.prisma.commonResource.findMany({
where: { ownerType: 'STORE', ownerId: id, status: 'ACTIVE', bizType: 'ENV' },
@@ -295,7 +301,7 @@ export class StoreService {
where: { storeId: id },
orderBy: [{ sortOrder: 'asc' }, { id: 'asc' }],
}),
this.prisma.redeemRecord.count({ where: { storeId: id } }),
showRedeemCount ? this.prisma.redeemRecord.count({ where: { storeId: id } }) : Promise.resolve(null),
]);
const { visibilityWhitelistEnabled: _wl, ...rest } = store;
return serializeBigInt(
@@ -304,7 +310,7 @@ export class StoreService {
...rest,
latitude: coords?.latitude ?? store.latitude,
longitude: coords?.longitude ?? store.longitude,
redeemCount,
...(showRedeemCount && redeemCount != null ? { redeemCount } : {}),
media,
packages: packageRows.map((p) => {
const imageUrls = normalizeStorePackageImageUrls({