food-market/docs/pos-design/pos-mockup.html
nns 61985c1062
Some checks are pending
Auto-tag / Create date-tag (push) Waiting to run
CI / Backend (.NET 8) (push) Waiting to run
CI / Web (React + Vite) (push) Waiting to run
CI / POS (WPF, Windows) (push) Waiting to run
docs(pos-ui): сверка с эталон-макетом + финальные скриншоты + Windows 11
- docs/pos-design/: эталон-макет (pos-mockup.html + mockup-*.png) и сверка
  «макет | касса» рядом — compare-sale.png, compare-payment.png (данные те же:
  4 позиции, 3 362 ₸, получено 5 000 → сдача 1 638 ₸). Расхождений
  выравнивания/размеров > 4px нет.
- Перегенерированы скриншоты «Стало» (1920×1080 + 1366×768) и галерея.
- Реальное окно Windows 11 (software-рендер на VM): экран продажи и оплаты
  (docs/pos-screenshots/windows/windows11-{sale,payment}.png).
- Обновлены docs/pos-design.md (раздел сверки) и docs/pos-ui-progress.md (итог).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-10-08 14:35:31 +05:00

220 lines
16 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">
<title>Касса — макет</title>
<meta name="viewport" content="width=1920">
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap" rel="stylesheet">
<style>
:root{
--bg:#F4F6F5; --card:#FFFFFF; --line:#E3E8E6; --text:#0F1F17; --muted:#5F6F68;
--green:#16A34A; --green-d:#12863D; --green-soft:#E8F7EE; --red:#DC2626; --amber:#B45309; --amber-soft:#FEF3C7;
--r:14px; --gap:16px;
}
*{box-sizing:border-box;margin:0;padding:0}
body{background:var(--bg);color:var(--text);font-family:Inter,system-ui,sans-serif;font-size:16px;
width:1920px;height:1080px;overflow:hidden;font-variant-numeric:tabular-nums}
.app{display:grid;grid-template-rows:64px 1fr 40px;height:100%}
/* верхняя полоса */
.top{background:var(--card);border-bottom:1px solid var(--line);display:flex;align-items:center;gap:24px;padding:0 24px}
.logo{font-weight:800;font-size:20px;color:var(--green);letter-spacing:.2px}
.logo span{color:var(--text);font-weight:600}
.sep{width:1px;height:28px;background:var(--line)}
.meta{color:var(--muted);font-size:15px}
.meta b{color:var(--text);font-weight:600}
.spacer{flex:1}
.chip{display:inline-flex;align-items:center;gap:8px;height:34px;padding:0 14px;border-radius:999px;font-size:14px;font-weight:600}
.chip i{width:8px;height:8px;border-radius:50%;display:block}
.chip.ok{background:var(--green-soft);color:var(--green-d)} .chip.ok i{background:var(--green)}
.chip.net{background:#EEF2F1;color:var(--muted)} .chip.net i{background:var(--green)}
/* основная область */
.main{display:grid;grid-template-columns:1fr 440px;gap:var(--gap);padding:var(--gap) 24px;min-height:0}
.left{display:flex;flex-direction:column;gap:var(--gap);min-height:0}
.search{height:64px;background:var(--card);border:2px solid var(--green);border-radius:var(--r);display:flex;align-items:center;gap:14px;padding:0 20px;
box-shadow:0 0 0 4px rgba(22,163,74,.12)}
.search svg{flex:none}
.search .ph{color:#8A9993;font-size:19px}
.search kbd{margin-left:auto}
.fav-head{display:flex;align-items:center;justify-content:space-between}
.h{font-size:15px;font-weight:700;color:var(--muted);text-transform:uppercase;letter-spacing:.6px}
.link{font-size:14px;font-weight:600;color:var(--green-d)}
.fav{display:grid;grid-template-columns:repeat(6,1fr);gap:12px}
.tile{height:84px;background:var(--card);border:1px solid var(--line);border-radius:12px;display:flex;flex-direction:column;
align-items:center;justify-content:center;gap:6px;text-align:center}
.tile .n{font-size:16px;font-weight:600}
.tile .p{font-size:15px;font-weight:700;color:var(--green-d)}
.cart{flex:1;background:var(--card);border:1px solid var(--line);border-radius:var(--r);display:flex;flex-direction:column;min-height:0}
.row{display:grid;grid-template-columns:1fr 200px 160px 56px;align-items:center;column-gap:16px;padding:0 20px}
.thead{height:48px;border-bottom:1px solid var(--line);color:var(--muted);font-size:14px;font-weight:600}
.thead .r{text-align:right}
.thead .c{text-align:center}
.item{height:76px;border-bottom:1px solid var(--line)}
.item.sel{background:#F7FBF8;box-shadow:inset 4px 0 0 var(--green)}
.name{font-size:18px;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.sub{font-size:14px;color:var(--muted);margin-top:4px}
.sub.disc{color:var(--green-d);font-weight:500}
.step{display:grid;grid-template-columns:44px 1fr 44px;align-items:center;height:44px;border:1px solid var(--line);border-radius:10px;overflow:hidden}
.step b{display:flex;align-items:center;justify-content:center;height:100%;font-size:22px;font-weight:500;color:var(--text);background:#F7F9F8}
.step span{text-align:center;font-size:17px;font-weight:600}
.sum{text-align:right;font-size:20px;font-weight:700}
.del{width:44px;height:44px;border-radius:10px;display:flex;align-items:center;justify-content:center;color:#9AA7A1;justify-self:end}
/* правая панель */
.right{background:var(--card);border:1px solid var(--line);border-radius:var(--r);display:flex;flex-direction:column;padding:24px;gap:16px}
.kv{display:flex;justify-content:space-between;font-size:17px;color:var(--muted)}
.kv b{color:var(--text);font-weight:600}
.kv.disc b{color:var(--green-d)}
.total{background:var(--green-soft);border-radius:12px;padding:20px 22px;display:flex;justify-content:space-between;align-items:baseline}
.total .l{font-size:18px;font-weight:700;color:var(--green-d);text-transform:uppercase;letter-spacing:.5px}
.total .v{font-size:56px;font-weight:800;color:var(--green-d);line-height:1}
.last{margin-top:4px;border-top:1px solid var(--line);padding-top:16px;color:var(--muted);font-size:14px;display:flex;flex-direction:column;gap:10px}
.last div{display:flex;justify-content:space-between}
.last b{color:var(--text);font-weight:600}
.grow{flex:1}
.pay{height:76px;border-radius:12px;background:var(--green);color:#fff;font-size:24px;font-weight:700;display:flex;align-items:center;justify-content:center;gap:12px;
box-shadow:0 6px 16px rgba(22,163,74,.28)}
.pay kbd{background:rgba(255,255,255,.2);border-color:transparent;color:#fff}
.grid2{display:grid;grid-template-columns:1fr 1fr;gap:10px}
.btn{height:52px;border:1px solid var(--line);border-radius:10px;background:var(--card);display:flex;align-items:center;justify-content:center;gap:10px;
font-size:16px;font-weight:600;color:var(--text)}
.btn svg{color:var(--muted)}
.btn kbd{font-size:12px}
.btn.danger{grid-column:1/3;border-color:#F3C4C4;color:var(--red)}
.btn.danger svg{color:var(--red)}
.badge{min-width:22px;height:22px;border-radius:11px;background:var(--amber-soft);color:var(--amber);font-size:13px;font-weight:700;display:inline-flex;align-items:center;justify-content:center;padding:0 6px}
kbd{display:inline-flex;align-items:center;justify-content:center;min-width:30px;height:24px;padding:0 7px;border:1px solid var(--line);border-bottom-width:2px;
border-radius:6px;background:#fff;font:600 12px Inter,sans-serif;color:var(--muted)}
/* полоса клавиш */
.keys{display:flex;align-items:center;gap:28px;padding:0 24px;color:var(--muted);font-size:14px;border-top:1px solid var(--line);background:var(--card)}
.keys span{display:inline-flex;align-items:center;gap:8px}
/* модальное окно оплаты */
.shade{position:fixed;inset:0;background:rgba(15,31,23,.42);display:flex;align-items:center;justify-content:center}
.modal{width:880px;background:var(--card);border-radius:20px;box-shadow:0 24px 64px rgba(0,0,0,.25);padding:32px;display:flex;flex-direction:column;gap:24px}
.mh{display:flex;justify-content:space-between;align-items:baseline}
.mh .t{font-size:24px;font-weight:700}
.mh .a{font-size:16px;color:var(--muted)} .mh .a b{font-size:40px;color:var(--text);font-weight:800;margin-left:10px}
.seg{display:grid;grid-template-columns:repeat(3,1fr);background:#EEF2F1;border-radius:12px;padding:4px;gap:4px}
.seg div{height:52px;border-radius:9px;display:flex;align-items:center;justify-content:center;gap:10px;font-size:17px;font-weight:600;color:var(--muted)}
.seg .on{background:#fff;color:var(--text);box-shadow:0 1px 3px rgba(0,0,0,.12)}
.pbody{display:grid;grid-template-columns:1fr 300px;gap:24px}
.lbl{font-size:14px;font-weight:600;color:var(--muted);margin-bottom:8px}
.inp{height:64px;border:2px solid var(--green);border-radius:12px;display:flex;align-items:center;justify-content:flex-end;padding:0 20px;font-size:30px;font-weight:700}
.quick{display:grid;grid-template-columns:repeat(3,1fr);gap:10px;margin-top:14px}
.quick div{height:52px;border:1px solid var(--line);border-radius:10px;display:flex;align-items:center;justify-content:center;font-size:17px;font-weight:600}
.quick .ex{color:var(--green-d);border-color:#BFE6CD;background:var(--green-soft)}
.change{margin-top:14px;background:var(--green-soft);border-radius:12px;height:84px;display:flex;align-items:center;justify-content:space-between;padding:0 22px}
.change .l{font-size:16px;font-weight:700;color:var(--green-d);text-transform:uppercase;letter-spacing:.5px}
.change .v{font-size:44px;font-weight:800;color:var(--green-d)}
.pad{display:grid;grid-template-columns:repeat(3,1fr);gap:10px}
.pad div{height:72px;border:1px solid var(--line);border-radius:12px;display:flex;align-items:center;justify-content:center;font-size:26px;font-weight:600;background:#FAFBFA}
.pad .s{font-size:16px;color:var(--muted)}
.actions{display:grid;grid-template-columns:200px 1fr;gap:12px}
.back{height:68px;border:1px solid var(--line);border-radius:12px;display:flex;align-items:center;justify-content:center;gap:10px;font-size:17px;font-weight:600}
.go{height:68px;border-radius:12px;background:var(--green);color:#fff;display:flex;align-items:center;justify-content:center;gap:12px;font-size:21px;font-weight:700}
.go kbd{background:rgba(255,255,255,.2);border-color:transparent;color:#fff}
body.nomodal .shade{display:none}
</style>
</head>
<body>
<div class="app">
<header class="top">
<div class="logo">FOOD MARKET <span>· Касса</span></div>
<div class="sep"></div>
<div class="meta">Магазин <b>Демо-магазин</b> · Точка <b>Касса 1</b></div>
<div class="sep"></div>
<div class="meta">Кассир <b>Пётр Кассиров</b></div>
<div class="spacer"></div>
<div class="chip ok"><i></i>Смена С-2026-000012 открыта с 09:00</div>
<div class="chip net"><i></i>На связи · очередь пуста</div>
</header>
<section class="main">
<div class="left">
<div class="search">
<svg width="26" height="26" viewBox="0 0 24 24" fill="none" stroke="#16A34A" stroke-width="2"><path d="M3 5v14M7 5v14M11 5v14M15 5v14M19 5v14" stroke-linecap="round"/></svg>
<div class="ph">Отсканируйте товар или начните вводить название</div>
<kbd>F2</kbd>
</div>
<div class="fav-head"><div class="h">Избранное</div><div class="link">Скрыть ▴</div></div>
<div class="fav">
<div class="tile"><div class="n">Хлеб «Семейный»</div><div class="p">280 ₸</div></div>
<div class="tile"><div class="n">Молоко 2,5%</div><div class="p">450 ₸</div></div>
<div class="tile"><div class="n">Яблоки (вес)</div><div class="p">690 ₸/кг</div></div>
<div class="tile"><div class="n">Картофель (вес)</div><div class="p">280 ₸/кг</div></div>
<div class="tile"><div class="n">Пакет-майка</div><div class="p">20 ₸</div></div>
<div class="tile"><div class="n">Вода 0,5 л</div><div class="p">150 ₸</div></div>
</div>
<div class="cart">
<div class="row thead"><div>Товар</div><div class="c">Количество</div><div class="r">Сумма</div><div></div></div>
<div class="row item"><div><div class="name">Хлеб «Семейный» нарезной</div><div class="sub">280 ₸ за шт</div></div>
<div class="step"><b>−</b><span>2 шт</span><b>+</b></div><div class="sum">560 ₸</div>
<div class="del"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M4 7h16M9 7V4h6v3M6 7l1 13h10l1-13"/></svg></div></div>
<div class="row item"><div><div class="name">Молоко 2,5% 1 л</div><div class="sub">450 ₸ за шт</div></div>
<div class="step"><b>−</b><span>1 шт</span><b>+</b></div><div class="sum">450 ₸</div>
<div class="del"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M4 7h16M9 7V4h6v3M6 7l1 13h10l1-13"/></svg></div></div>
<div class="row item"><div><div class="name">Яблоки «Апорт»</div><div class="sub">690 ₸ за кг</div></div>
<div class="step"><b>−</b><span>1,235 кг</span><b>+</b></div><div class="sum">852 ₸</div>
<div class="del"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M4 7h16M9 7V4h6v3M6 7l1 13h10l1-13"/></svg></div></div>
<div class="row item sel"><div><div class="name">Сахар-песок 1 кг</div><div class="sub disc">520 ₸ за шт · скидка 60 ₸ (1 560 → 1 500 ₸)</div></div>
<div class="step"><b>−</b><span>3 шт</span><b>+</b></div><div class="sum">1 500 ₸</div>
<div class="del"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M4 7h16M9 7V4h6v3M6 7l1 13h10l1-13"/></svg></div></div>
</div>
</div>
<aside class="right">
<div class="kv"><span>Позиций</span><b>4</b></div>
<div class="kv"><span>Подытог</span><b>3 422 ₸</b></div>
<div class="kv disc"><span>Скидка</span><b>−60 ₸</b></div>
<div class="total"><div class="l">Итого</div><div class="v">3 362 ₸</div></div>
<div class="last">
<div><span>Последний чек № 000148</span><b>1 250 ₸ · нал</b></div>
<div><span>Чеков за смену</span><b>47</b></div>
</div>
<div class="grow"></div>
<div class="pay">Оплатить <kbd>F12</kbd></div>
<div class="grid2">
<div class="btn"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M19 5L5 19M7 7h.01M17 17h.01"/></svg>Скидка <kbd>F4</kbd></div>
<div class="btn"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M6 4h12v16l-6-4-6 4z"/></svg>Отложить <kbd>F7</kbd></div>
<div class="btn"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M4 6h16M4 12h16M4 18h10"/></svg>Отложенные <span class="badge">2</span></div>
<div class="btn"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M9 14L4 9l5-5M4 9h11a5 5 0 010 10h-3"/></svg>Возврат <kbd>F9</kbd></div>
<div class="btn"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 5v14M5 12h14"/></svg>Внесение</div>
<div class="btn"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M5 12h14"/></svg>Выплата</div>
<div class="btn danger"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M6 6l12 12M18 6L6 18"/></svg>Очистить чек <kbd>Esc</kbd></div>
</div>
</aside>
</section>
<footer class="keys">
<span><kbd>F1</kbd>Помощь</span><span><kbd>F2</kbd>Поиск</span><span><kbd>F4</kbd>Скидка</span><span><kbd>F7</kbd>Отложить</span>
<span><kbd>F9</kbd>Возврат</span><span><kbd>F10</kbd>Смена</span><span><kbd>F12</kbd>Оплата</span><span><kbd>Del</kbd>Удалить строку</span><span><kbd>Esc</kbd>Отмена</span>
</footer>
</div>
<div class="shade">
<div class="modal">
<div class="mh"><div class="t">Оплата</div><div class="a">К оплате<b>3 362 ₸</b></div></div>
<div class="seg"><div class="on">💵 Наличные</div><div>💳 Карта</div><div>⇄ Смешанная</div></div>
<div class="pbody">
<div>
<div class="lbl">Получено наличными</div>
<div class="inp">5 000 ₸</div>
<div class="quick"><div class="ex">Без сдачи</div><div>4 000</div><div>5 000</div><div>10 000</div><div>20 000</div><div>Своя сумма</div></div>
<div class="change"><div class="l">Сдача</div><div class="v">1 638 ₸</div></div>
</div>
<div class="pad"><div>1</div><div>2</div><div>3</div><div>4</div><div>5</div><div>6</div><div>7</div><div>8</div><div>9</div><div class="s">Сброс</div><div>0</div><div class="s">⌫</div></div>
</div>
<div class="actions"><div class="back"><kbd>Esc</kbd>Назад</div><div class="go">Провести и печатать <kbd>Enter</kbd></div></div>
</div>
</div>
</body>
</html>