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>
|
|
@ -48,3 +48,22 @@
|
||||||
## Тёмная тема (опция)
|
## Тёмная тема (опция)
|
||||||
Те же имена токенов, тёмные значения (PosBg #0F1713, PosCard #15201B, PosText #E8EFEA…),
|
Те же имена токенов, тёмные значения (PosBg #0F1713, PosCard #15201B, PosText #E8EFEA…),
|
||||||
переключается через `RequestedThemeVariant` + подмену словаря. По умолчанию — светлая.
|
переключается через `RequestedThemeVariant` + подмену словаря. По умолчанию — светлая.
|
||||||
|
|
||||||
|
## Эталон-макет (Mac-Claude, 08.10)
|
||||||
|
Верстать ТОЧНО по макету: `docs/pos-design/pos-mockup.html` (все размеры/цвета/отступы в CSS)
|
||||||
|
+ отрисовки `mockup-sale-1920x1080.png`, `mockup-payment-1920x1080.png`. Сравнение
|
||||||
|
«макет | касса» — `docs/pos-design/compare-*.png` (расхождения выравнивания > 4px — править).
|
||||||
|
|
||||||
|
Ключевые размеры из макета: app rows 64/1fr/40; main cols 1fr/440, gap 16, padding 16/24;
|
||||||
|
search h64 border 2px green; избранное 6 плиток h84; корзина cols «1fr 200 160 56», thead h48,
|
||||||
|
строка h76, выбранная — зелёный акцент слева; степпер 44/1fr/44 слитный; правая панель p24 gap16,
|
||||||
|
ИТОГО green-soft, блок «Последний чек/Чеков за смену», pay h76; grid2 кнопки h52 с иконками и kbd;
|
||||||
|
модалка 880, pad 3×4 по 72, quick 3×2, seg 3 в серой подложке. Иконки — векторные (не эмодзи).
|
||||||
|
|
||||||
|
### Сверка «макет | касса»
|
||||||
|
`dotnet run --project src/food-market.pos -- --compare` складывает эталон и наш рендер
|
||||||
|
рядом (`CompareRunner`, SkiaSharp): `compare-sale.png`, `compare-payment.png`. Данные те же,
|
||||||
|
что в макете — 4 позиции, подытог 3 422 ₸, скидка −60 ₸, итог 3 362 ₸, получено 5 000 → сдача 1 638 ₸.
|
||||||
|
Результат сверки на 08.10: расхождений выравнивания/размеров > 4 px нет — сетка, колонки корзины,
|
||||||
|
степперы, правая панель, клавиатура, модалка и сегменты совпадают с эталоном. Оплата снимается
|
||||||
|
поверх затемнённого экрана продажи (как в макете), сегменты — векторные иконки, активный — белый.
|
||||||
|
|
|
||||||
BIN
docs/pos-design/compare-payment.png
Normal file
|
After Width: | Height: | Size: 377 KiB |
BIN
docs/pos-design/compare-sale.png
Normal file
|
After Width: | Height: | Size: 319 KiB |
BIN
docs/pos-design/mockup-payment-1920x1080.png
Normal file
|
After Width: | Height: | Size: 162 KiB |
BIN
docs/pos-design/mockup-sale-1920x1080.png
Normal file
|
After Width: | Height: | Size: 129 KiB |
219
docs/pos-design/pos-mockup.html
Normal file
|
|
@ -0,0 +1,219 @@
|
||||||
|
<!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>
|
||||||
|
Before Width: | Height: | Size: 55 KiB After Width: | Height: | Size: 54 KiB |
|
Before Width: | Height: | Size: 60 KiB After Width: | Height: | Size: 59 KiB |
|
Before Width: | Height: | Size: 77 KiB After Width: | Height: | Size: 83 KiB |
|
Before Width: | Height: | Size: 82 KiB After Width: | Height: | Size: 89 KiB |
|
Before Width: | Height: | Size: 126 KiB After Width: | Height: | Size: 145 KiB |
|
Before Width: | Height: | Size: 133 KiB After Width: | Height: | Size: 151 KiB |
|
Before Width: | Height: | Size: 52 KiB After Width: | Height: | Size: 136 KiB |
|
Before Width: | Height: | Size: 57 KiB After Width: | Height: | Size: 171 KiB |
|
Before Width: | Height: | Size: 53 KiB After Width: | Height: | Size: 125 KiB |
|
Before Width: | Height: | Size: 58 KiB After Width: | Height: | Size: 172 KiB |
|
Before Width: | Height: | Size: 60 KiB After Width: | Height: | Size: 60 KiB |
|
Before Width: | Height: | Size: 65 KiB After Width: | Height: | Size: 65 KiB |
|
Before Width: | Height: | Size: 54 KiB After Width: | Height: | Size: 54 KiB |
|
Before Width: | Height: | Size: 59 KiB After Width: | Height: | Size: 59 KiB |
|
Before Width: | Height: | Size: 128 KiB After Width: | Height: | Size: 144 KiB |
|
Before Width: | Height: | Size: 135 KiB After Width: | Height: | Size: 149 KiB |
|
Before Width: | Height: | Size: 126 KiB After Width: | Height: | Size: 143 KiB |
|
Before Width: | Height: | Size: 133 KiB After Width: | Height: | Size: 149 KiB |
|
Before Width: | Height: | Size: 124 KiB After Width: | Height: | Size: 142 KiB |
|
Before Width: | Height: | Size: 130 KiB After Width: | Height: | Size: 148 KiB |
BIN
docs/pos-screenshots/windows/windows11-payment.png
Normal file
|
After Width: | Height: | Size: 123 KiB |
|
Before Width: | Height: | Size: 108 KiB After Width: | Height: | Size: 124 KiB |
|
|
@ -20,20 +20,55 @@
|
||||||
поиск со скан-иконкой, корзина-карточки со степпером [−]N[+] и удалением,
|
поиск со скан-иконкой, корзина-карточки со степпером [−]N[+] и удалением,
|
||||||
белая карточка чека с крупным зелёным ИТОГО и «Оплатить · F12», вторичные
|
белая карточка чека с крупным зелёным ИТОГО и «Оплатить · F12», вторичные
|
||||||
кнопки-контуры, пустая корзина-заглушка, капсулы горячих клавиш.
|
кнопки-контуры, пустая корзина-заглушка, капсулы горячих клавиш.
|
||||||
4. [x] Оплата (светлое модальное): сегменты Нал/Карта/Смешанная, быстрые суммы
|
4. [x] Оплата (светлое модальное 880px): сегменты Нал/Карта/Смешанная с векторными
|
||||||
(без сдачи/1000/2000/5000/10000/20000), цифровая клавиатура, крупная «Сдача».
|
иконками (активный зелёный, иконка белая), быстрые суммы 3×2
|
||||||
|
(без сдачи/4000/5000/10000/20000/своя сумма), клавиатура 3×4 по 72px, крупная «Сдача».
|
||||||
5. [x] Остальные экраны в стиле: вход (логин + PIN-пад), регистрация/выбор точки,
|
5. [x] Остальные экраны в стиле: вход (логин + PIN-пад), регистрация/выбор точки,
|
||||||
смена/Z-отчёт (разница цветом), возврат (степперы). Нет связи — чип в шапке.
|
смена/Z-отчёт (разница цветом), возврат (степперы). Нет связи — чип в шапке.
|
||||||
6. [ ] Избранные товары: сервер (флаг/порядок у товара) + миграция + плитки UI.
|
6. [x] Избранные товары: сервер Product.IsFavorite/FavoriteOrder (миграция Phase37),
|
||||||
7. [x] Удобство: кнопки ≥48px, клавиши крупные; фокус в поле скана; адаптив 1366/1920.
|
POS-синк + карточка товара (ProductInput); PosStore.GetFavorites + плитки
|
||||||
8. [~] Скриншоты «Было/Стало» 1920×1080 + 1366×768 (галерея с разделами); реальное окно Windows 11 — в конце.
|
(сворачиваемая сетка 3 колонки) на экране продажи. Unit-тест.
|
||||||
9. [x] --uitest OK; unit 43 зелёные; скорость не хуже. Smoke Linux/Windows — в конце.
|
7. [x] Удобство: кнопки ≥48px, клавиши крупные (72px); фокус в поле скана; адаптив 1366/1920.
|
||||||
10. [~] Коммиты в main; push (по ходу).
|
8. [x] Скриншоты «Было/Стало» 1920×1080 + 1366×768 (галерея с разделами «Стало»/«Было» +
|
||||||
|
«Windows 11»); реальное окно Windows 11 (светлая тема, software-рендер на VM).
|
||||||
|
9. [x] --uitest OK; unit 82 зелёные; скорость не хуже (старт 74мс, скан 13.7мс, поиск 1.1мс).
|
||||||
|
Smoke Linux OK, Windows OK. Сверка с макетом `--compare` → расхождений > 4px нет.
|
||||||
|
10. [x] Коммиты тематические в main; push origin. global.json не коммитил.
|
||||||
|
|
||||||
Осталось: избранные товары (п.6), тёмная тема как переключатель в настройках,
|
### Эталон-макет Mac-Claude (1:1) — выполнено
|
||||||
реальное окно Windows 11, smoke Win/Linux, итоговый push.
|
Владелец: «вёрстка кривая». Перенёс макет `docs/pos-design/pos-mockup.html` в Avalonia
|
||||||
|
по размерам (не на глаз):
|
||||||
|
- Сетка: верх 64 / 1fr / низ 40; main cols 1fr/440, gap 16, padding 16/24.
|
||||||
|
- Корзина: thead h48, строки cols «товар / 200 / 160 / 56», выбранная — зелёный акцент
|
||||||
|
слева + светло-зелёный фон (чинил перекрытие стилей `:selected` локальными значениями).
|
||||||
|
- Степпер слитный 44/1fr/44; правая панель — 2-кол. сетка, «Очистить чек» во всю ширину.
|
||||||
|
- Модалка оплаты 880px по центру на затемнённом экране продажи (как в макете);
|
||||||
|
клавиатура UniformGrid 3×4 72px; быстрые суммы 3×2; сегменты 3 в серой подложке.
|
||||||
|
- Иконки везде векторные (`Path`, stroke), эмодзи убраны.
|
||||||
|
- Бейдж «Отложенные · N» как в макете.
|
||||||
|
- Сверка: `--compare` (CompareRunner, SkiaSharp) → `docs/pos-design/compare-sale.png`,
|
||||||
|
`compare-payment.png` («макет | касса» рядом, данные те же: 4 позиции, 3 362 ₸, 5 000 → сдача 1 638 ₸).
|
||||||
|
Расхождений выравнивания > 4px нет.
|
||||||
|
- Реальное окно Windows 11: экран продажи и оплаты (`docs/pos-screenshots/windows/windows11-{sale,payment}.png`).
|
||||||
|
|
||||||
|
### Замечания Mac-Claude по скриншотам — исправлены
|
||||||
|
1. Текст во всех кнопках по центру (Button.pos/key/seg: Horizontal/VerticalContentAlignment=Center
|
||||||
|
+ HorizontalAlignment=Stretch — раньше key/seg не наследовали центровку).
|
||||||
|
2. Клавиатура оплаты — ровная сетка 3×4 одинаковых крупных клавиш (72px).
|
||||||
|
3. Быстрые суммы и сегменты — UniformGrid одинаковой ширины; сегменты слитным переключателем.
|
||||||
|
4. Модалка оплаты по высоте содержимого, по центру, на затемнённой подложке.
|
||||||
|
5. Правая панель — ровная 2-кол. сетка; добавлены Возврат·F9, Внесение/Выплата·F10;
|
||||||
|
Очистить — красный контур во всю ширину; без пустот.
|
||||||
|
6. Корзина — степпер 44×44 с количеством по центру, отступ до иконки удаления.
|
||||||
|
7. Экран продажи снимается с оболочкой (верхняя полоса + капсулы горячих клавиш).
|
||||||
|
8. «Избранное» — шеврон ▾/▸.
|
||||||
|
|
||||||
НЕ трогать: прод, shared-postgres, global.json, gateway nginx, sklad, другие VM.
|
НЕ трогать: прод, shared-postgres, global.json, gateway nginx, sklad, другие VM.
|
||||||
|
|
||||||
## Журнал
|
## Журнал
|
||||||
- 08.10 — старт; сохранены «до»-скриншоты (22), замерен baseline; планы зафиксированы.
|
- 08.10 — старт; сохранены «до»-скриншоты (22), замерен baseline; планы зафиксированы.
|
||||||
|
- 08.10 — светлая тема + избранное + правки выравнивания (коммиты 7a93c19, ac55da8, 29ef769, 85e486a).
|
||||||
|
- 08.10 — эталон-макет 1:1: PaymentView 880px + векторные сегменты, оплата поверх затемнённого
|
||||||
|
экрана, бейдж отложенных, исправлена подсветка выбранной строки; CompareRunner (`--compare`) →
|
||||||
|
compare-sale/compare-payment (расхождений > 4px нет); реальное окно Windows 11 (продажа + оплата).
|
||||||
|
Проверено: --uitest OK, 82 unit зелёные, smoke OK, скорость не хуже (старт 74мс, скан 13.7мс).
|
||||||
|
|
|
||||||