import type { AnalyzeBsNsrUrlContext, TaxerTicketForNsr } from "../types/taxerTicket"; export const BS_NSR_ABOUT_BLANK = "about:blank"; /** * 与 WPF `Analize_URL` 一致:按模板替换占位符;`ticket == null` 或空模板时返回 `about:blank`。 */ export function analyzeBsNsrUrl( ticket: TaxerTicketForNsr | null, ctx: AnalyzeBsNsrUrlContext, ): string { if (!ticket) { return BS_NSR_ABOUT_BLANK; } const template = ctx.bsNsrUrlTemplate.trim(); if (!template) { return BS_NSR_ABOUT_BLANK; } const sflb = ticket.isEnterprise === 1 ? "1" : "2"; return template .replace(/\{djxh\}/g, ticket.enterpriseId) .replace(/\{sfzhm\}/g, ctx.taxerIdCard) .replace(/\{sflb\}/g, sflb) .replace(/\{swjgDm\}/g, ctx.bsTaxAuthorityNum) .replace(/\{qhhm\}/g, ticket.tktId) .replace(/\{sjhm\}/g, ctx.phoneNo); } /** 拼接结果是否为可导航的 http(s) URL */ export function isNavigableHttpUrl(url: string): boolean { if (!url || url === BS_NSR_ABOUT_BLANK) { return false; } try { const parsed = new URL(url); return parsed.protocol === "http:" || parsed.protocol === "https:"; } catch { return false; } } /** 与 WPF `Source.AbsoluteUri` 比较一致,避免重复导航 */ export function normalizeUrlForCompare(url: string): string { if (!url || url === BS_NSR_ABOUT_BLANK) { return BS_NSR_ABOUT_BLANK; } try { return new URL(url).href; } catch { return url.trim(); } }