feat(admin): link city-partner store count; fix benefitUsageRule null string
CI / verify (pull_request) Has been cancelled

City partner storeCount jumps to /stores?partnerId=; normalize empty/null text so usage rule is not saved as literal "null.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-07-28 16:03:56 +08:00
parent 118d57d710
commit 309b180087
6 changed files with 103 additions and 25 deletions
@@ -28,6 +28,14 @@ function haversineMeters(lat1: number, lng1: number, lat2: number, lng2: number)
return 2 * R * Math.asin(Math.min(1, Math.sqrt(a)));
}
/** 选填文案:空 / null / "null" 存库为 null,避免 String(null)==="null" */
function normalizeOptionalTextField(value: unknown): string | null {
if (value == null) return null;
const s = String(value).trim();
if (!s || /^null$/i.test(s) || /^undefined$/i.test(s)) return null;
return s;
}
function parseOptionalCoord(value: unknown, kind: 'lat' | 'lng' = 'lng'): number | null {
if (value == null || value === '') return null;
const n = typeof value === 'number' ? value : Number(value);
@@ -301,9 +309,8 @@ export class StoreService {
if (introRaw && (introRaw.length < 2 || introRaw.length > 500)) {
throw new BadRequestException('门店简介须为 2~500 字');
}
const benefitUsageRuleRaw =
body.benefitUsageRule != null ? String(body.benefitUsageRule).trim() : '';
if (benefitUsageRuleRaw.length > 1000) {
const benefitUsageRuleRaw = normalizeOptionalTextField(body.benefitUsageRule);
if (benefitUsageRuleRaw && benefitUsageRuleRaw.length > 1000) {
throw new BadRequestException('好客权益券使用规则最多 1000 字');
}
@@ -325,7 +332,7 @@ export class StoreService {
district: String(body.district ?? ''),
address: String(body.address),
intro: introRaw || null,
benefitUsageRule: benefitUsageRuleRaw || null,
benefitUsageRule: benefitUsageRuleRaw,
avgPrice: avgPriceRaw,
openTime,
closeTime,
@@ -522,7 +529,9 @@ export class StoreService {
const address = body.address !== undefined ? String(body.address).trim() : undefined;
const introRaw = body.intro !== undefined ? String(body.intro).trim() : undefined;
const benefitUsageRuleRaw =
body.benefitUsageRule !== undefined ? String(body.benefitUsageRule).trim() : undefined;
body.benefitUsageRule !== undefined
? normalizeOptionalTextField(body.benefitUsageRule)
: undefined;
const latitude =
body.latitude !== undefined ? parseOptionalCoord(body.latitude, 'lat') : undefined;
const longitude =
@@ -536,7 +545,7 @@ export class StoreService {
if (introRaw && (introRaw.length < 2 || introRaw.length > 500)) {
throw new BadRequestException('门店简介须为 2~500 字');
}
if (benefitUsageRuleRaw !== undefined && benefitUsageRuleRaw.length > 1000) {
if (benefitUsageRuleRaw != null && benefitUsageRuleRaw.length > 1000) {
throw new BadRequestException('好客权益券使用规则最多 1000 字');
}
if (
@@ -561,7 +570,7 @@ export class StoreService {
...(hasCoordsUpdate ? { latitude, longitude } : {}),
...(introRaw !== undefined ? { intro: introRaw || null } : {}),
...(benefitUsageRuleRaw !== undefined
? { benefitUsageRule: benefitUsageRuleRaw || null }
? { benefitUsageRule: benefitUsageRuleRaw }
: {}),
...(resubmitAudit
? {