import { SearchRegular } from "@fluentui/react-icons"; import { useEffect, useMemo, useState } from "react"; import type { Country, CountryRule, UpstreamProxy } from "../../types"; import { Button, EmptyState, Input, Modal, Select } from "../ui"; import { useI18n } from "../../lib/i18n"; export interface CountryRulesDialogProps { open: boolean; proxies: UpstreamProxy[]; countries: Country[]; rules: CountryRule[]; busy: boolean; onSave: (assignments: Record) => void; onClose: () => void; } export function CountryRulesDialog(props: CountryRulesDialogProps) { const { t, lang } = useI18n(); const { open, proxies, countries, rules, busy, onSave, onClose } = props; const [query, setQuery] = useState(""); const [assignments, setAssignments] = useState>({}); const regionNames = useMemo(() => { try { return new Intl.DisplayNames([lang === "zh" ? "zh-CN" : "en"], { type: "region" }); } catch { return null; } }, [lang]); const countryLabel = (country: Country) => regionNames?.of(country.countryCode) || country.countryName || country.countryCode; const proxyOptions = useMemo(() => [ { value: "", label: t("直连") }, ...proxies.map((proxy) => ({ value: proxy.id, label: proxy.enabled ? (proxy.name || proxy.id) : `${proxy.name || proxy.id}(${t("已禁用")})`, disabled: !proxy.enabled, })), ], [proxies, t, lang]); useEffect(() => { if (!open) { setQuery(""); setAssignments({}); return; } setAssignments(Object.fromEntries(rules.filter((rule) => rule.enabled).map((rule) => [rule.countryCode, rule.upstreamProxyId]))); // Sample rules only when opening. Polling must not discard in-progress edits. // eslint-disable-next-line react-hooks/exhaustive-deps }, [open]); const filtered = useMemo(() => { const needle = query.trim().toLocaleLowerCase(); return [...countries] .sort((a, b) => countryLabel(a).localeCompare(countryLabel(b), lang === "zh" ? "zh-CN" : "en")) .filter((country) => { if (!needle) return true; return [country.countryCode, country.countryName, countryLabel(country), ...country.mccs] .some((value) => String(value || "").toLocaleLowerCase().includes(needle)); }); }, [countries, query, lang, regionNames]); const configuredCount = Object.values(assignments).filter(Boolean).length; return ( )} >
{t("为每个国家的 MCC 选择代理。未配置时直连;已有 ICCID 绑定始终优先,首次命中国家规则后会生成独立的 ICCID 绑定。")}
{configuredCount} {t("个国家规则")}
setQuery(event.target.value)} placeholder={t("搜索国家、地区代码或 MCC")} prefix={} className="w-full sm:w-72" />
{filtered.map((country) => ( ))}
{t("国家 / 地区")} MCC {t("规则")}
{countryLabel(country)} {country.countryCode} {country.mccs.join(", ")}
{filtered.length === 0 ? : null}
); }