zov-tech/miniapp/preview-report.html
wasrusgen ef500fa446 user feedback batch: model count, specs, manual link, dimensions, export
1. MODEL COUNT SELECTOR (strategy step):
   - new PODBOR_MODEL_COUNTS [3/5/7]
   - state.model_count default '5'
   - UI on strategy page with description (быстро/оптимально/максимум)

2. AI PROMPT EXPANDED:
   - new field: manual_search_query — for Google search instruction PDF
   - new specs object per model: dimensions_mm/volume_l/weight_kg/noise_db/energy_class/color
   - 'specs ОБЯЗАТЕЛЬНЫ для проектирования кухни' explicit rule
   - reads checklist.model_count to determine how many models per category
   - max_tokens 4000 → 8000 (room for richer responses)

3. MODEL CARD RICHER:
   - _renderSpecsBlock — characteristics in 2-col grid, dimensions highlighted
   - _renderUtilityLinks — Google search buttons for инструкция (PDF) + Схема установки
   - Specs critical for ZOV kitchen design (manager needs to verify niche fits)

4. EXPORT BUTTONS:
   - 'Скачать HTML' — generates standalone HTML with inline styles, downloads as file
   - 'Печать → PDF' — opens new window with cleaned layout + auto-prints
   - User can save as PDF via system print dialog

5. PREVIEW updated with realistic specs/manual_query for all 3 fridges
2026-05-11 17:11:30 +03:00

483 lines
25 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!doctype html>
<html lang="ru">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
<meta name="theme-color" content="#FBF7F0">
<title>Превью отчёта · ЗОВ</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Geist:wght@400;500;600;700&family=Newsreader:ital,wght@0,400..600;1,400..600&family=Instrument+Serif:ital@0;1&family=JetBrains+Mono:wght@400;500&display=swap">
<link rel="stylesheet" href="assets/styles.css?v=20260511e">
<link rel="stylesheet" href="assets/podbor.css?v=20260511e">
<style>
body { padding: 24px 16px; background: var(--paper); }
.wrap { max-width: 720px; margin: 0 auto; }
.preview-kicker {
font-family: var(--font-mono);
font-size: 10px;
letter-spacing: 0.14em;
text-transform: uppercase;
color: var(--muted);
margin-bottom: 6px;
}
.preview-title {
font-family: var(--font-display);
font-style: italic;
font-size: 32px;
line-height: 1.05;
letter-spacing: -0.02em;
margin: 0 0 8px;
color: var(--ink);
}
.preview-lede {
color: var(--muted);
font-size: 14px;
margin: 0 0 24px;
}
</style>
</head>
<body>
<div class="wrap">
<div class="preview-kicker">Preview · Inline Report v1</div>
<h1 class="preview-title">Отчёт<br><em style="color: var(--accent-2)">после подбора</em></h1>
<p class="preview-lede">Как будет выглядеть страница для менеджера и клиента после нажатия «Отправить». Mock-данные.</p>
<div id="reportRoot"></div>
</div>
<script src="assets/icons.js?v=20260511e"></script>
<script src="assets/podbor.config.js?v=20260511e"></script>
<script>
/* Mock-данные — имитируем AI-ответ с DNS+WB+Я.Маркет обогащением */
const MOCK_AI = {
summary: "Подобран комплект Haier для семьи из 3 человек, бюджет средний. Холодильник с NoFrost + индукционная варочная Haier и компактная духовка с конвекцией. Все три прибора одной марки для дизайн-единства и тише в эксплуатации.",
by_category: {
fridge: {
analysis: "В этом бюджете 2026 года Haier и Korting вытеснили Bosch по соотношению цена/качество. Haier C4F744CMG — оптимальный двухкамерный по тишине и объёму, Liebherr — премиум-вариант с зоной свежести, Бирюса — бюджетная страховка.",
models: [
{
brand: "Haier", model: "C4F744CMG",
price_min_rub: 89990, price_max_rub: 105000,
highlights: ["Total NoFrost (не нужно размораживать)", "Инвертор (тише и -30% энергии)", "Класс A++ (~30% экономии)"],
pros: ["тихий 36 дБ — на 4 дБ тише среднего по сегменту", "большой объём 463 л против 380 л у Bosch в этой цене", "инвертор + класс A++ — экономия ~30% против A+ моделей", "10 лет гарантии на компрессор"],
cons: ["глубина 660 мм — на 60 мм больше стандартной ниши, проверить на замере", "нет зоны свежести BioFresh — в этом плане Liebherr заметно лучше"],
reasoning: "Лучший по цена/качество в среднем сегменте. Тише и больше Bosch в той же цене, но без премиум-зоны свежести.",
specs: { dimensions_mm: "595×660×2000", volume_l: 463, weight_kg: 75, noise_db: 36, energy_class: "A++", color: "Нержавеющая сталь" },
manual_search_query: "Haier C4F744CMG manual инструкция pdf",
tier: "middle",
enriched: {
image_url: "https://placehold.co/200x200/F5EDDC/6B4A2B?text=Haier",
price_min_rub: 89990, price_max_rub: 105000,
rating_max: 4.7, reviews_total: 1242, stores_count: 12,
citilink: { url: "https://www.citilink.ru/product/haier-123/", price_min_rub: 92000 },
ozon: { url: "https://www.ozon.ru/product/haier-c4f744cmg/", price_min_rub: 89990 },
wb: { url: "https://www.wildberries.ru/catalog/123/detail.aspx", price_min_rub: 94500 },
yamarket: { url: "https://market.yandex.ru/product--haier-c4f744cmg/123", price_min_rub: 105000 }
}
},
{
brand: "Liebherr", model: "CNd 5223",
price_min_rub: 134900, price_max_rub: 154000,
highlights: ["BioFresh (зона свежести)", "NoFrost", "SoftClose"],
pros: ["премиум-качество немецкой сборки", "очень тихий 34 дБ — на 2 дБ тише Haier", "BioFresh — овощи дольше хрустящие на 30 дней", "10 лет гарантии на компрессор"],
cons: ["цена выше Haier на ~50% при том же объёме", "идёт параллельным импортом — ждать 4-6 недель"],
reasoning: "Премиум-выбор для тех, кому важна зона свежести и тишина. Переплата ~50% за бренд и BioFresh.",
specs: { dimensions_mm: "597×675×2010", volume_l: 372, weight_kg: 89, noise_db: 34, energy_class: "A+++", color: "Нержавеющая сталь SmartSteel" },
manual_search_query: "Liebherr CNd 5223 manual инструкция pdf",
tier: "premium",
enriched: {
image_url: "https://placehold.co/200x200/EFE3CC/6B4A2B?text=Liebherr",
rating_max: 4.9, reviews_total: 873, stores_count: 4,
ozon: { url: "https://www.ozon.ru/product/liebherr-cnd5223/", price_min_rub: 134900 },
citilink: { url: "https://www.citilink.ru/product/liebherr-cnd5223/", price_min_rub: 142000 },
yamarket: { url: "https://market.yandex.ru/product--liebherr-cnd5223/", price_min_rub: 154000 }
}
},
{
brand: "Бирюса", model: "M124",
price_min_rub: 39990,
highlights: ["LowFrost (размораживать только мороз)", "класс A+"],
pros: ["доступная цена в 2 раза ниже Haier", "компактные габариты 600×600×1900 мм — идеальная ниша", "официальная гарантия 3 года от российского производителя"],
cons: ["без инвертора — компрессор работает циклами, заметнее на слух", "шум 42 дБ — на 6 дБ громче Haier", "нет зон свежести"],
reasoning: "Страховочный бюджет-вариант если клиент не хочет переплачивать. Российский, доступный, надёжный.",
specs: { dimensions_mm: "580×600×1450", volume_l: 240, weight_kg: 52, noise_db: 42, energy_class: "A+", color: "Белый" },
manual_search_query: "Бирюса M124 инструкция pdf",
tier: "budget",
enriched: {
image_url: "https://placehold.co/200x200/FBF7F0/6B4A2B?text=Birusa",
rating_max: 4.3, reviews_total: 2100, stores_count: 5,
ozon: { url: "https://www.ozon.ru/product/biryusa-m124/", price_min_rub: 39990 },
citilink: { url: "https://www.citilink.ru/product/biryusa-m124/", price_min_rub: 41500 },
wb: { url: "https://www.wildberries.ru/catalog/biryusa-m124/", price_min_rub: 42990 },
dns: { url: "https://www.dns-shop.ru/product/biryusa-m124/", price_min_rub: 44900 }
}
}
]
},
hob: {
analysis: "В 2026 году индукционные варочные среднего сегмента — это Haier и Korting. Bosch ещё доступен через ПИ, но цена выше на 25%. Все три модели — 60 см, 4 зоны, индукция.",
models: [
{
brand: "Haier", label: "Haier",
model: "HHX-Y64NFB",
price_min_rub: 39990, price_max_rub: 48000,
highlights: ["Индукция (магнитный нагрев посуды)", "Booster (кипятит за минуту)", "Сенсорное управление"],
pros: ["4 индукционные зоны 60 см — стандарт", "Booster на 2 зонах — кипятит литр за 60 сек", "защита от детей блокировкой", "класс A — экономия энергии"],
cons: ["требует индукционной посуды (магнитное дно)", "нет FlexZone — нельзя объединить две зоны под крупную сковороду"],
reasoning: "Базовая индукция от лидера рынка 2026 РФ. Идеальна когда не нужны премиум-фичи.",
tier: "middle",
enriched: {
image_url: "https://placehold.co/200x200/F5EDDC/6B4A2B?text=Haier+hob",
rating_max: 4.6, reviews_total: 845, stores_count: 4,
ozon: { url: "https://www.ozon.ru/product/haier-hhx-y64nfb/", price_min_rub: 39990 },
citilink: { url: "https://www.citilink.ru/product/haier-hhx-y64nfb/", price_min_rub: 42500 },
wb: { url: "#", price_min_rub: 44990 },
yamarket: { url: "#", price_min_rub: 48000 }
}
},
{
brand: "Korting", model: "HI 64560 BB",
price_min_rub: 54990, price_max_rub: 62000,
highlights: ["Индукция", "FlexZone (объединение зон)", "9 уровней мощности"],
pros: ["FlexZone — объединяет 2 зоны для wok или большой кастрюли", "более чувствительный сенсор чем у Haier (9 vs 4 деления)", "5 лет официальной гарантии в РФ"],
cons: ["цена выше базового Haier на 38%", "управление сенсорное — иногда срабатывает по случайному касанию"],
reasoning: "Премиум-функционал FlexZone за разумные деньги. Для тех, кто часто готовит в wok.",
tier: "middle",
enriched: {
image_url: "https://placehold.co/200x200/EFE3CC/6B4A2B?text=Korting",
rating_max: 4.8, reviews_total: 432, stores_count: 3,
ozon: { url: "https://www.ozon.ru/product/korting-hi64560bb/", price_min_rub: 54990 },
citilink: { url: "https://www.citilink.ru/product/korting-hi64560bb/", price_min_rub: 58000 },
yamarket: { url: "https://market.yandex.ru/product--korting-hi64560bb/", price_min_rub: 62000 }
}
},
{
brand: "Bosch", model: "PUE611BB5E ⚠ПИ",
price_min_rub: 64990, price_max_rub: 78000,
highlights: ["Индукция", "PowerBoost", "PerfectCook (сенсор посуды)"],
pros: ["PerfectCook — сенсор определяет посуду и держит температуру", "лучший дизайн без рамки", "немецкая надёжность"],
cons: ["параллельный импорт — гарантия только продавца, не Bosch", "цена выше Haier на 65% за похожий функционал", "ожидание поставки 3-5 недель"],
reasoning: "Премиум-выбор для эстетов. Доступен только через ПИ, переплата за бренд значительная.",
tier: "middle",
enriched: {
image_url: "https://placehold.co/200x200/D8C9A8/6B4A2B?text=Bosch+%E2%9A%A0",
rating_max: 4.7, reviews_total: 1240, stores_count: 2,
ozon: { url: "https://www.ozon.ru/product/bosch-pue611bb5e/", price_min_rub: 64990 },
yamarket: { url: "https://market.yandex.ru/product--bosch-pue611bb5e/", price_min_rub: 78000 }
}
}
]
}
},
total_price_estimate_rub: { min: 280000, max: 420000 },
budget_status: "в_рамках",
warnings: [
"Холодильник Bosch KGN39 имеет глубину 660мм — уточнить нишу клиента (стандарт 600мм)"
]
};
/* ---- mini-копия renderReport из podbor.js, чтобы превью работало автономно ---- */
function el(html) {
const t = document.createElement("template");
t.innerHTML = html.trim();
return t.content.firstChild;
}
function _esc(s) {
return String(s == null ? "" : s)
.replace(/&/g, "&amp;")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;")
.replace(/"/g, "&quot;")
.replace(/'/g, "&#39;");
}
function formatRub(n) {
if (!n) return "—";
return Math.round(n).toString().replace(/\B(?=(\d{3})+(?!\d))/g, " ");
}
function renderReport(ai, leadId) {
const summary = ai.summary || "";
const byCat = ai.by_category || {};
const total = ai.total_price_estimate_rub || {};
const budgetStatus = ai.budget_status || "";
const warnings = ai.warnings || [];
const wrap = el(`<section class="report"></section>`);
wrap.appendChild(el(`
<div class="report-head">
<div class="kicker">Отчёт · ${leadId.slice(0, 8)}</div>
${summary ? `<p class="report-summary">${_esc(summary)}</p>` : ""}
</div>
`));
for (const [catKey, catData] of Object.entries(byCat)) {
const catMeta = (window.PODBOR_CATEGORIES || []).find(c => c.key === catKey);
const catLabel = catMeta?.label || catKey;
const catIcon = catMeta?.icon;
const models = (catData && catData.models) || [];
if (!models.length) continue;
const catAnalysis = (catData && catData.analysis) || "";
const catNode = el(`
<div class="report-cat">
<h3 class="report-cat-head">
<span class="report-cat-icon">${(catIcon && window.ICONS && window.ICONS[catIcon]) || ""}</span>
${_esc(catLabel)}
</h3>
${catAnalysis ? `<div class="report-cat-analysis">${_esc(catAnalysis)}</div>` : ""}
<div class="report-models"></div>
</div>
`);
const modelsWrap = catNode.querySelector(".report-models");
// Матрица цен — primary view, ВСТАВЛЯЕМ ДО списка моделей
const matrixNode = _renderPriceMatrix(models);
if (matrixNode) catNode.insertBefore(matrixNode, modelsWrap);
for (const m of models) {
modelsWrap.appendChild(_renderModelCard(m));
}
wrap.appendChild(catNode);
}
if (total && (total.min || total.max)) {
const tmin = total.min, tmax = total.max;
const range = (tmin && tmax && tmin !== tmax)
? `${formatRub(tmin)}${formatRub(tmax)}`
: `${formatRub(tmin || tmax)}`;
wrap.appendChild(el(`
<div class="report-total">
<span class="lbl">ИТОГО</span>
<strong>${range}</strong>
${budgetStatus ? `<span class="status">${_esc(budgetStatus)}</span>` : ""}
</div>
`));
}
if (warnings.length) {
const wn = el(`<div class="report-warnings"></div>`);
warnings.forEach(w => wn.appendChild(el(`<div>⚠️ ${_esc(w)}</div>`)));
wrap.appendChild(wn);
}
return wrap;
}
function _renderModelCard(m) {
const enriched = m.enriched || {};
const pMin = m.price_min_rub || enriched.price_min_rub;
const pMax = m.price_max_rub || enriched.price_max_rub;
const img = enriched.image_url;
const rating = enriched.rating_max;
const reviews = enriched.reviews_total;
const stores = enriched.stores_count;
const priceHtml = (pMin && pMax && pMin !== pMax)
? `<strong>${formatRub(pMin)}</strong> — <strong>${formatRub(pMax)}</strong> ₽`
: pMin ? `<strong>${formatRub(pMin)}</strong> ₽`
: `<span class="muted">цена уточняется</span>`;
const metaParts = [];
if (rating) metaParts.push(`<span class="rating">★ ${Number(rating).toFixed(1)}</span>`);
if (reviews) metaParts.push(`<span class="reviews">${reviews} отзыв.</span>`);
if (stores) metaParts.push(`<span class="stores">${stores} магазинов</span>`);
const sourcesData = [
{ key: "ozon", label: "OZON", item: enriched.ozon },
{ key: "citilink", label: "Citilink", item: enriched.citilink },
{ key: "wb", label: "Wildberries", item: enriched.wb },
{ key: "yamarket", label: "Я.Маркет", item: enriched.yamarket },
{ key: "dns", label: "DNS", item: enriched.dns },
];
const sourceLinks = sourcesData
.filter(s => s.item && s.item.url)
.map(s => `<a href="${_esc(s.item.url)}" target="_blank" rel="noopener noreferrer" class="report-link report-link--${s.key}">${s.label}${s.item.price_min_rub ? ` · ${formatRub(s.item.price_min_rub)}` : ""}</a>`);
function _plural(n) {
const last = n % 10, lastTwo = n % 100;
if (lastTwo >= 11 && lastTwo <= 14) return "магазинов";
if (last === 1) return "магазин";
if (last >= 2 && last <= 4) return "магазина";
return "магазинов";
}
// Specs block
const specs = m.specs || {};
const specsItems = [];
if (specs.dimensions_mm) specsItems.push({ label: "Габариты ШхГxВ", value: specs.dimensions_mm + " мм", highlight: true });
if (specs.volume_l) specsItems.push({ label: "Объём", value: specs.volume_l + " л" });
if (specs.weight_kg) specsItems.push({ label: "Вес", value: specs.weight_kg + " кг" });
if (specs.noise_db) specsItems.push({ label: "Шум", value: specs.noise_db + " дБ" });
if (specs.energy_class) specsItems.push({ label: "Класс энергии", value: specs.energy_class });
if (specs.color) specsItems.push({ label: "Цвет / материал", value: specs.color });
const specsHtml = specsItems.length ? `
<div class="report-specs">
<div class="report-specs-head">Характеристики</div>
<div class="report-specs-grid">
${specsItems.map(i => `<div class="spec-item${i.highlight ? " highlight" : ""}"><div class="spec-label">${_esc(i.label)}</div><div class="spec-value">${_esc(i.value)}</div></div>`).join("")}
</div>
</div>` : "";
// Utility links
const utilButtons = [];
if (m.manual_search_query) {
utilButtons.push(`<a href="https://www.google.com/search?q=${encodeURIComponent(m.manual_search_query)}" target="_blank" class="util-link util-link--manual">📄 Инструкция</a>`);
}
if (specs.dimensions_mm) {
utilButtons.push(`<a href="https://www.google.com/search?q=${encodeURIComponent((m.brand || '') + ' ' + (m.model || '') + ' габариты схема установки')}" target="_blank" class="util-link util-link--dims">📐 Схема установки</a>`);
}
const utilHtml = utilButtons.length ? `<div class="report-util-links">${utilButtons.join("")}</div>` : "";
return el(`
<article class="report-model">
<div class="report-model-img${img ? "" : " placeholder"}">${img ? `<img src="${_esc(img)}" alt="" loading="lazy">` : ""}</div>
<div class="report-model-body">
<div class="report-model-brand">${_esc(m.brand || "")}</div>
<div class="report-model-name">${_esc(m.model || "")}</div>
${metaParts.length ? `<div class="report-model-meta">${metaParts.join(" · ")}</div>` : ""}
<div class="report-model-price">${priceHtml}</div>
${(m.highlights || []).length ? `<div class="report-highlights">✓ ${m.highlights.map(_esc).join(" · ")}</div>` : ""}
${(m.pros || []).length ? `
<div class="report-pros-block">
<div class="pc-head">Плюсы</div>
<ul class="pc-list">${m.pros.slice(0, 4).map(p => `<li>${_esc(p)}</li>`).join("")}</ul>
</div>
` : ""}
${(m.cons || []).length ? `
<div class="report-cons-block">
<div class="pc-head">Минусы</div>
<ul class="pc-list">${m.cons.slice(0, 3).map(c => `<li>${_esc(c)}</li>`).join("")}</ul>
</div>
` : ""}
${specsHtml}
${m.reasoning ? `<div class="report-reasoning">💡 ${_esc(m.reasoning)}</div>` : ""}
${utilHtml}
${sourceLinks.length ? `
<div class="report-links">
<div class="report-links-head">${sourceLinks.length} ${_plural(sourceLinks.length)} нашли товар:</div>
${sourceLinks.join("")}
</div>
` : `<div class="report-links-empty">— не найден в подключённых магазинах</div>`}
</div>
</article>
`);
}
function _renderPriceMatrix(models) {
if (!models || !models.length) return null;
const STORES = [
{ key: "ozon", label: "OZON" },
{ key: "citilink", label: "Citilink" },
{ key: "wb", label: "Wildberries" },
{ key: "yamarket", label: "Я.Маркет" },
{ key: "dns", label: "DNS" },
];
const activeStores = STORES.filter(s =>
models.some(m => (m.enriched || {})[s.key] && ((m.enriched || {})[s.key].price_min_rub || (m.enriched || {})[s.key].url))
);
const showStoresCols = activeStores.length > 0;
const head = `
<thead>
<tr>
<th class="col-model">Модель</th>
${showStoresCols
? activeStores.map(s => `<th class="col-store">${s.label}</th>`).join("")
: `<th class="col-store">Цена (AI)</th>`}
<th class="col-best">Мин</th>
</tr>
</thead>
`;
const rows = models.map(m => {
const enriched = m.enriched || {};
const cellPrices = showStoresCols
? activeStores.map(s => {
const item = enriched[s.key];
return { store: s.key, price: item && item.price_min_rub, url: item && item.url };
})
: [{ store: "ai", price: enriched.price_min_rub || m.price_min_rub, url: null }];
const validPrices = cellPrices.map(c => c.price).filter(p => p && p > 0);
const bestPrice = validPrices.length ? Math.min(...validPrices) : null;
const modelCell = `
<td class="col-model">
<div class="m-brand">${_esc(m.brand || "")}</div>
<div class="m-name">${_esc(m.model || "")}</div>
</td>
`;
const storeCells = cellPrices.map(c => {
if (!c.price) {
return c.url
? `<td class="cell-price"><a href="${_esc(c.url)}" target="_blank" rel="noopener noreferrer" class="cell-noprice-link">смотреть →</a></td>`
: `<td class="cell-price empty">—</td>`;
}
const isBest = bestPrice && c.price === bestPrice;
const priceHtml = `<strong>${formatRub(c.price)}</strong> ₽`;
const cellInner = c.url
? `<a href="${_esc(c.url)}" target="_blank" rel="noopener noreferrer">${priceHtml}${isBest ? ' <span class="best-mark">✓</span>' : ''}</a>`
: `${priceHtml}${isBest ? ' <span class="best-mark">✓</span>' : ''}`;
return `<td class="cell-price${isBest ? ' best' : ''}">${cellInner}</td>`;
}).join("");
const bestCell = `<td class="col-best">${bestPrice ? `<strong>${formatRub(bestPrice)}</strong>` : "—"}</td>`;
return `<tr>${modelCell}${storeCells}${bestCell}</tr>`;
}).join("");
return el(`
<div class="report-matrix-wrap">
<div class="report-matrix-head">Цены по магазинам — лучшая отмечена ✓</div>
<div class="report-matrix-scroll">
<table class="report-matrix">
${head}
<tbody>${rows}</tbody>
</table>
</div>
</div>
`);
}
function _renderCompareTable(models) {
const rows = models.map(m => {
const e = m.enriched || {};
const p = m.price_min_rub || e.price_min_rub;
return `
<tr>
<td><strong>${_esc(m.brand || "")}</strong> ${_esc(m.model || "")}</td>
<td>${p ? formatRub(p) + " ₽" : "—"}</td>
<td>${e.reviews_total || "—"}</td>
<td>${e.rating_max ? Number(e.rating_max).toFixed(1) : "—"}</td>
</tr>
`;
}).join("");
return el(`
<details class="report-compare" open>
<summary>Сравнить модели</summary>
<table>
<thead>
<tr><th>Модель</th><th>Цена от</th><th>Отзывов</th><th>★</th></tr>
</thead>
<tbody>${rows}</tbody>
</table>
</details>
`);
}
document.getElementById("reportRoot").appendChild(renderReport(MOCK_AI, "ABC12345"));
</script>
</body>
</html>