From 85f2c156b0e204fef86e4eaad7ffb96c480a843e Mon Sep 17 00:00:00 2001 From: jacy <18049821889@163.com> Date: Wed, 22 Jul 2026 18:03:32 +0800 Subject: [PATCH] fix(admin): prevent false partner commission cap errors Coerce city maxPartnerCommissionRate to Number so Decimal JSON strings do not break sum checks. Co-authored-by: Cursor --- apps/admin-web/src/components/CityPartnersPanel.tsx | 9 ++++++--- apps/admin-web/src/pages/CityPartnersPage.tsx | 13 ++++++++----- .../src/modules/ops/admin-cities.service.ts | 3 +++ 3 files changed, 17 insertions(+), 8 deletions(-) diff --git a/apps/admin-web/src/components/CityPartnersPanel.tsx b/apps/admin-web/src/components/CityPartnersPanel.tsx index 3f02579..85c3f65 100644 --- a/apps/admin-web/src/components/CityPartnersPanel.tsx +++ b/apps/admin-web/src/components/CityPartnersPanel.tsx @@ -92,9 +92,12 @@ function commissionSumError( redeemPercent: number, maxRate: number, ): string | null { - const sum = orderPercent / 100 + redeemPercent / 100; - if (sum > maxRate + 1e-9) { - return `订单佣金与核销佣金合计不得超过 ${(maxRate * 100).toFixed(2)}%(当前 ${(sum * 100).toFixed(2)}%)`; + // API 可能把 Prisma Decimal 序列化为字符串;`"0.05" + 1e-9` 会变成字符串拼接导致误判超限 + const max = Number(maxRate); + const sum = Number(orderPercent) / 100 + Number(redeemPercent) / 100; + if (!Number.isFinite(max) || !Number.isFinite(sum)) return '佣金比例无效'; + if (sum > max + 1e-9) { + return `订单佣金与核销佣金合计不得超过 ${(max * 100).toFixed(2)}%(当前 ${(sum * 100).toFixed(2)}%)`; } return null; } diff --git a/apps/admin-web/src/pages/CityPartnersPage.tsx b/apps/admin-web/src/pages/CityPartnersPage.tsx index 55c9914..7cf0cb2 100644 --- a/apps/admin-web/src/pages/CityPartnersPage.tsx +++ b/apps/admin-web/src/pages/CityPartnersPage.tsx @@ -98,9 +98,12 @@ function flattenDistrictCodes(values: string[] | string[][] | undefined): string } function commissionSumError(orderPercent: number, redeemPercent: number, maxRate: number): string | null { - const sum = orderPercent / 100 + redeemPercent / 100; - if (sum > maxRate + 1e-9) { - return `订单佣金与核销佣金合计不得超过 ${(maxRate * 100).toFixed(2)}%(当前 ${(sum * 100).toFixed(2)}%)`; + // API 可能把 Prisma Decimal 序列化为字符串;`"0.05" + 1e-9` 会变成字符串拼接导致误判超限 + const max = Number(maxRate); + const sum = Number(orderPercent) / 100 + Number(redeemPercent) / 100; + if (!Number.isFinite(max) || !Number.isFinite(sum)) return '佣金比例无效'; + if (sum > max + 1e-9) { + return `订单佣金与核销佣金合计不得超过 ${(max * 100).toFixed(2)}%(当前 ${(sum * 100).toFixed(2)}%)`; } return null; } @@ -149,7 +152,7 @@ export default function CityPartnersPage() { const d = await request(`/admin/partners/${id}`); setDetail(d); setEditScopeType((d.scopeType as CityPartnerScopeType) || CityPartnerScopeType.CITY_WIDE); - setMaxCommissionRate(d.maxPartnerCommissionRate ?? 0.05); + setMaxCommissionRate(Number(d.maxPartnerCommissionRate ?? 0.05)); editForm.setFieldsValue({ name: d.name, phone: d.phone, @@ -230,7 +233,7 @@ export default function CityPartnersPage() { async function onCreateCityChange(cityId: string) { const cityRes = await request<{ maxPartnerCommissionRate?: number }>(`/admin/cities/${cityId}`); - setCreateMaxRate(cityRes.maxPartnerCommissionRate ?? 0.05); + setCreateMaxRate(Number(cityRes.maxPartnerCommissionRate ?? 0.05)); } const columns: ColumnsType = [ diff --git a/server/dukang-api/src/modules/ops/admin-cities.service.ts b/server/dukang-api/src/modules/ops/admin-cities.service.ts index 5457898..4715acd 100644 --- a/server/dukang-api/src/modules/ops/admin-cities.service.ts +++ b/server/dukang-api/src/modules/ops/admin-cities.service.ts @@ -80,6 +80,9 @@ export class AdminCitiesService { const cityPartners = await this.partnerCityService.listByCity(id); return serializeBigInt({ ...city, + // Decimal 经 JSON 会变成字符串,显式 Number 避免前端 `"0.05" + 1e-9` 字符串拼接误判 + maxPartnerCommissionRate: + city.maxPartnerCommissionRate != null ? Number(city.maxPartnerCommissionRate) : null, cityPartners, storeCount: city._count.stores, orderCount: city._count.orders,