import type { LocalDeliveryDto } from '@dukang/shared-types'; import { DEFAULT_LOCAL_DELIVERY_HINT } from '@dukang/shared-types'; import { request } from './api'; export { DEFAULT_LOCAL_DELIVERY_HINT }; const CACHE_TTL_MS = 60_000; let cached: LocalDeliveryDto[] | null = null; let cachedAt = 0; let inflight: Promise | null = null; function cityAliases(name: string): string[] { const raw = name.trim(); if (!raw) return []; const noSuffix = raw.replace(/市$/, ''); const withSuffix = raw.endsWith('市') ? raw : `${raw}市`; return [raw, noSuffix, withSuffix]; } export async function loadLocalDeliveries(force = false): Promise { if (!force && cached && Date.now() - cachedAt < CACHE_TTL_MS) return cached; if (!force && inflight) return inflight; inflight = request('/catalog/local-deliveries') .then((list) => { cached = Array.isArray(list) ? list : []; cachedAt = Date.now(); return cached; }) .catch(() => { cached = cached ?? []; return cached; }) .finally(() => { inflight = null; }); return inflight; } export function matchLocalDelivery( list: LocalDeliveryDto[], opts: { cityCode?: string | null; cityName?: string | null }, ): LocalDeliveryDto | null { const code = String(opts.cityCode || '').trim(); if (code) { const byCode = list.find((row) => row.city.code === code); if (byCode) return byCode; } const names = new Set(cityAliases(String(opts.cityName || ''))); if (!names.size) return null; return list.find((row) => cityAliases(row.city.name).some((n) => names.has(n))) ?? null; } export function resolveLocalDeliveryHintHtml(row: LocalDeliveryDto | null): string { const html = row?.hintHtml?.trim(); if (html) return html; return DEFAULT_LOCAL_DELIVERY_HINT; }