217 lines
8.6 KiB
JavaScript
217 lines
8.6 KiB
JavaScript
(function () {
|
||
"use strict";
|
||
|
||
const REG = [
|
||
{
|
||
num: "7271UV",
|
||
type: "SIP",
|
||
station: "ГТС Алматы",
|
||
city: "Алматы",
|
||
desc: "Оконечный номер экстренных служб (пример схемы)",
|
||
reserve: "Есть: SIP Trunk 7272222222 (принадлежит ГТС Алматы)",
|
||
},
|
||
{
|
||
num: "727103",
|
||
type: "BRW SIP",
|
||
station: "ГТС Алматы",
|
||
city: "Алматы",
|
||
desc: "Номер пересчёта принадлежит BRW SIP 7273130333",
|
||
reserve: "Есть: SIP Trunk 7272222222 (принадлежит ГТС Алматы)",
|
||
},
|
||
{
|
||
num: "7272222222",
|
||
type: "ТДМ",
|
||
station: "ГТС Алматы",
|
||
city: "Алматы",
|
||
desc: "Резервный номер в SIP Trunk, принадлежит ГТС Алматы",
|
||
reserve: "Резерв для 7271UV",
|
||
},
|
||
];
|
||
|
||
const OWNERS = [
|
||
{ name: "ГТС Алматы (собственный номер станции)", short: "ГТС Алматы", match: function (d) { return d.owner === "own"; } },
|
||
{ name: "BRW SIP", short: "BRW SIP", match: function (d) { return d.owner === "brw-sip"; } },
|
||
{ name: "АТС", short: "АТС", match: function (d) { return d.owner === "pbx"; } },
|
||
{ name: "АТС зоны", short: "АТС зоны", match: function (d) { return d.owner === "zone"; } },
|
||
];
|
||
|
||
function normalize(v) {
|
||
return String(v == null ? "" : v).replace(/\s+/g, "").toUpperCase();
|
||
}
|
||
|
||
function findEntry(num) {
|
||
const n = normalize(num);
|
||
if (!n) return null;
|
||
return REG.find(function (e) { return normalize(e.num) === n; }) || null;
|
||
}
|
||
|
||
function derive(raw) {
|
||
let n = normalize(raw);
|
||
n = n.replace(/^(?:[8]\+?7|0)/, "");
|
||
if (!/^[0-9A-Z]+$/.test(n)) return null;
|
||
const digits = n.replace(/[^0-9]/g, "");
|
||
const city = digits.startsWith("727") ? "Алматы" : "неизвестен";
|
||
|
||
const entry = findEntry(raw);
|
||
let owner, reserve, viaStation, isReserve = false;
|
||
if (entry) {
|
||
owner = ownerByType(entry.type);
|
||
reserve = entry.reserve;
|
||
viaStation = entry.station;
|
||
isReserve = /резерв/i.test(entry.desc);
|
||
} else {
|
||
owner = digits.length >= 8 ? "pbx" : "zone";
|
||
reserve = "Не определён (номер не в реестре)";
|
||
viaStation = "неизвестна";
|
||
}
|
||
|
||
const owners = OWNERS.filter(function (o) { return o.match({ owner: owner }); });
|
||
const ownerName = owners.length ? owners[0].name : "станция-владелец";
|
||
const endLabel = entry ? "Оконечный номер " + entry.num : "Оконечный номер";
|
||
|
||
const mobile = [
|
||
{ t: "Мобильный оператор" },
|
||
{ t: "SSW/NGN транзит" },
|
||
{ t: "SSW/NGN рег." },
|
||
{ t: endLabel, active: true },
|
||
];
|
||
const fixed = [
|
||
{ t: "Станция владельца номера абонента" },
|
||
{ t: "SSW/NGN рег." + (viaStation ? " (" + viaStation + ")" : "") },
|
||
{ t: endLabel, active: true },
|
||
];
|
||
if (owner === "brw-sip") {
|
||
fixed.splice(2, 0, { t: "Номер пересчёта → BRW SIP", active: true });
|
||
}
|
||
if (reserve && !/не определён/i.test(reserve) && !isReserve) {
|
||
const rnum = reserve.replace(/^Есть[:\s]*/, "").split(/[\s(]/)[0];
|
||
mobile.push({ t: "Резерв", sub: rnum + " · авт. при недоступности SIP" });
|
||
fixed.push({ t: "Резерв", sub: rnum + " · авт. при недоступности SIP" });
|
||
}
|
||
|
||
return { entry: entry, city: city, owner: owner, ownerName: ownerName, reserve: reserve, viaStation: viaStation, mobile: mobile, fixed: fixed };
|
||
}
|
||
|
||
function ownerByType(type) {
|
||
const t = normalize(type);
|
||
if (t.indexOf("BRW") === 0) return "brw-sip";
|
||
if (t === "SIP" || t === "GPON") return "pbx";
|
||
if (t === "ТДМ") return "own";
|
||
return "zone";
|
||
}
|
||
|
||
function renderChain(id, nodes) {
|
||
const el = document.getElementById(id);
|
||
el.innerHTML = "";
|
||
nodes.forEach(function (node, i) {
|
||
const d = document.createElement("div");
|
||
d.className = "chain-node" + (node.active ? " active" : "");
|
||
const s = document.createElement("strong");
|
||
s.textContent = node.t;
|
||
d.appendChild(s);
|
||
if (node.sub) {
|
||
const sp = document.createElement("span");
|
||
sp.textContent = node.sub;
|
||
d.appendChild(sp);
|
||
}
|
||
el.appendChild(d);
|
||
if (i < nodes.length - 1) {
|
||
const a = document.createElement("span");
|
||
a.className = "chain-arrow";
|
||
a.setAttribute("aria-hidden", "true");
|
||
a.innerHTML = "→";
|
||
el.appendChild(a);
|
||
}
|
||
});
|
||
}
|
||
|
||
function chip(text, tone) {
|
||
const s = document.createElement("span");
|
||
s.className = "kt-ai-chip";
|
||
if (tone) s.setAttribute("data-tone", tone);
|
||
s.textContent = text;
|
||
return s;
|
||
}
|
||
|
||
function show(num) {
|
||
const d = derive(num);
|
||
const detail = document.getElementById("resDetail");
|
||
if (!d) {
|
||
detail.style.display = "none";
|
||
const empty = '<div class="chain-node"><strong>Проверьте номер</strong><span>Введите ABC21UV</span></div>';
|
||
document.getElementById("chain1").innerHTML = empty;
|
||
document.getElementById("chain2").innerHTML = empty;
|
||
document.getElementById("r1src").textContent = "";
|
||
document.getElementById("r2src").textContent = "";
|
||
return;
|
||
}
|
||
|
||
detail.style.display = "block";
|
||
document.getElementById("rdNum").textContent = d.entry ? d.entry.num : num.trim().toUpperCase();
|
||
const chips = document.getElementById("rdChips");
|
||
chips.innerHTML = "";
|
||
if (d.entry) {
|
||
chips.appendChild(chip(d.entry.type, "blue"));
|
||
chips.appendChild(chip(d.entry.station, "gray"));
|
||
chips.appendChild(chip("Город: " + d.entry.city, "gray"));
|
||
} else {
|
||
chips.appendChild(chip("Город: " + d.city, "gray"));
|
||
}
|
||
document.getElementById("rdMeta").textContent = d.entry ? d.entry.desc : "Номер не найден в реестре — показан базовый маршрут.";
|
||
document.getElementById("rdOwn").textContent = "Владелец (по пересчёту): " + d.ownerName;
|
||
const r = document.getElementById("rdReserve");
|
||
if (/не определён/i.test(d.reserve)) {
|
||
r.style.display = "none";
|
||
} else {
|
||
r.style.display = "block";
|
||
r.textContent = "Резерв: " + d.reserve;
|
||
}
|
||
|
||
document.getElementById("r1src").textContent = "Мобильный оператор → SSW/NGN транзит → SSW/NGN рег. → " + (d.entry ? d.entry.num : "оконечный номер");
|
||
document.getElementById("r2src").textContent = "Станция владельца номера → SSW/NGN рег. → " + (d.entry ? d.entry.num : "оконечный номер");
|
||
renderChain("chain1", d.mobile);
|
||
renderChain("chain2", d.fixed);
|
||
}
|
||
|
||
function renderRegister() {
|
||
const list = document.getElementById("regList");
|
||
list.innerHTML = "";
|
||
REG.forEach(function (e) {
|
||
const row = document.createElement("div");
|
||
row.className = "kt-ai-card reg-row";
|
||
const top = document.createElement("div");
|
||
top.className = "reg-row-top";
|
||
const num = document.createElement("span");
|
||
num.className = "reg-row-num";
|
||
num.textContent = e.num;
|
||
top.appendChild(num);
|
||
top.appendChild(chip(e.type, "blue"));
|
||
top.appendChild(chip(e.station, "gray"));
|
||
top.appendChild(chip("Резерв: есть", "green"));
|
||
row.appendChild(top);
|
||
const meta = document.createElement("div");
|
||
meta.className = "reg-row-meta";
|
||
meta.textContent = e.desc + " · Город: " + e.city + " · Формат набора: ABC21UV";
|
||
row.appendChild(meta);
|
||
const res = document.createElement("div");
|
||
res.className = "reg-row-reserve";
|
||
res.textContent = "Резерв: " + e.reserve;
|
||
row.appendChild(res);
|
||
list.appendChild(row);
|
||
});
|
||
document.getElementById("regCounter").textContent = "Каждый номер: тип (ТДМ / GPON / SIP), станция владения, формат набора ABC21UV и резерв. В реестре: " + REG.length + ".";
|
||
}
|
||
|
||
document.addEventListener("DOMContentLoaded", function () {
|
||
renderRegister();
|
||
const input = document.getElementById("num");
|
||
const btn = document.getElementById("findBtn");
|
||
btn.addEventListener("click", function () { show(input.value); });
|
||
input.addEventListener("keydown", function (ev) {
|
||
if (ev.key === "Enter") show(input.value);
|
||
});
|
||
input.addEventListener("input", function () { show(input.value); });
|
||
show("7271UV");
|
||
});
|
||
})();
|