Not a member of GistPad yet?
Sign Up,
it unlocks many cool features!
- <!DOCTYPE html>
- <html lang="ru">
- <head>
- <meta charset="UTF-8">
- <title>Экспорт PNG — Домашняя бухгалтерия</title>
- <style>
- body { background: #121212; color: #fff; font-family: 'Segoe UI', Arial, sans-serif; padding: 20px; }
- .toolbar { margin-bottom: 20px; display: flex; gap: 12px; }
- button { background: #2563eb; color: #fff; border: none; padding: 12px 20px; border-radius: 8px; cursor: pointer; font-size: 15px; font-weight: 600; }
- button:hover { background: #1d4ed8; }
- canvas { background: #ffffff; border-radius: 8px; box-shadow: 0 4px 20px rgba(0,0,0,0.5); display: block; margin-bottom: 30px; max-width: 100%; }
- </style>
- </head>
- <body>
- <div class="toolbar">
- <button onclick="downloadCanvas('archCanvas', 'Архитектура_проекта.png')">⬇️ Скачать Архитектура_проекта.png</button>
- <button onclick="downloadCanvas('uiCanvas', 'Макеты_интерфейса.png')">⬇️ Скачать Макеты_интерфейса.png</button>
- </div>
- <h3>1. Схема архитектуры проекта (Этап 5)</h3>
- <canvas id="archCanvas" width="950" height="680"></canvas>
- <h3>2. Макеты интерфейса 375×812 с подписями элементов (Этап 7)</h3>
- <canvas id="uiCanvas" width="1350" height="900"></canvas>
- <script>
- function roundRect(ctx, x, y, w, h, r, fill, stroke) {
- ctx.beginPath();
- ctx.roundRect(x, y, w, h, r);
- if (fill) { ctx.fillStyle = fill; ctx.fill(); }
- if (stroke) { ctx.strokeStyle = stroke; ctx.lineWidth = 2; ctx.stroke(); }
- }
- function drawArrow(ctx, x1, y1, x2, y2, label) {
- ctx.strokeStyle = '#334155';
- ctx.fillStyle = '#334155';
- ctx.lineWidth = 2;
- ctx.beginPath();
- ctx.moveTo(x1, y1);
- ctx.lineTo(x2, y2);
- ctx.stroke();
- const angle = Math.atan2(y2 - y1, x2 - x1);
- ctx.beginPath();
- ctx.moveTo(x2, y2);
- ctx.lineTo(x2 - 10 * Math.cos(angle - Math.PI / 6), y2 - 10 * Math.sin(angle - Math.PI / 6));
- ctx.lineTo(x2 - 10 * Math.cos(angle + Math.PI / 6), y2 - 10 * Math.sin(angle + Math.PI / 6));
- ctx.closePath();
- ctx.fill();
- if (label) {
- ctx.font = 'italic 13px Segoe UI';
- ctx.fillStyle = '#0f172a';
- ctx.fillText(label, (x1 + x2) / 2 + 10, (y1 + y2) / 2 + 4);
- }
- }
- // 1. Отрисовка архитектуры
- const arch = document.getElementById('archCanvas').getContext('2d');
- arch.fillStyle = '#ffffff';
- arch.fillRect(0, 0, 950, 680);
- arch.fillStyle = '#0f172a';
- arch.font = 'bold 20px Segoe UI';
- arch.fillText('Архитектура приложения «Домашняя бухгалтерия»', 220, 35);
- // Блоки
- roundRect(arch, 120, 60, 360, 95, 10, '#dbeafe', '#3b82f6');
- arch.fillStyle = '#1e3a8a'; arch.font = 'bold 16px Segoe UI';
- arch.fillText('UI-модуль (Presentation Layer)', 175, 90);
- arch.fillStyle = '#1e293b'; arch.font = '14px Segoe UI';
- arch.fillText('Экраны: Главная | Добавить | История | Отчёты', 145, 120);
- arch.fillText('Ввод данных и отображение состояния', 175, 142);
- roundRect(arch, 120, 215, 360, 115, 10, '#dcfce7', '#22c55e');
- arch.fillStyle = '#14532d'; arch.font = 'bold 16px Segoe UI';
- arch.fillText('Модуль логики (Business Logic)', 175, 245);
- arch.fillStyle = '#1e293b'; arch.font = '14px Segoe UI';
- arch.fillText('Класс FinanceManager:', 145, 270);
- arch.fillText('• расчёт баланса (get_balance)', 145, 292);
- arch.fillText('• фильтрация и отчёты по категориям', 145, 314);
- roundRect(arch, 580, 215, 320, 115, 10, '#fef9c3', '#eab308');
- arch.fillStyle = '#713f12'; arch.font = 'bold 16px Segoe UI';
- arch.fillText('Модуль моделей (Domain Models)', 605, 245);
- arch.fillStyle = '#1e293b'; arch.font = '14px Segoe UI';
- arch.fillText('• Класс Operation (id, amount, type,', 600, 272);
- arch.fillText(' category_id, date, comment)', 600, 292);
- arch.fillText('• Класс Category (id, name, icon)', 600, 314);
- roundRect(arch, 120, 390, 360, 105, 10, '#ffedd5', '#f97316');
- arch.fillStyle = '#7c2d12'; arch.font = 'bold 16px Segoe UI';
- arch.fillText('Модуль данных (Data Access Layer)', 160, 420);
- arch.fillStyle = '#1e293b'; arch.font = '14px Segoe UI';
- arch.fillText('• DatabaseConnection (Singleton)', 145, 448);
- arch.fillText('• OperationRepository / CategoryRepository', 145, 472);
- roundRect(arch, 120, 555, 360, 90, 10, '#f1f5f9', '#64748b');
- arch.fillStyle = '#0f172a'; arch.font = 'bold 16px Segoe UI';
- arch.fillText('Локальная БД SQLite (finance.db)', 170, 588);
- arch.font = '14px Segoe UI';
- arch.fillText('Таблицы: operations, categories', 195, 618);
- // Стрелки
- drawArrow(arch, 300, 155, 300, 215, 'События UI / Данные операций');
- drawArrow(arch, 480, 272, 580, 272, 'Объекты моделей');
- drawArrow(arch, 300, 330, 300, 390, 'Вызовы методов репозитория');
- drawArrow(arch, 300, 495, 300, 555, 'SQL-запросы (SELECT / INSERT)');
- drawArrow(arch, 480, 442, 740, 330, 'Маппинг строк БД в объекты');
- // 2. Отрисовка макетов 375x812
- const ui = document.getElementById('uiCanvas').getContext('2d');
- ui.fillStyle = '#f8fafc';
- ui.fillRect(0, 0, 1350, 900);
- function drawPhone(x, y, title, screenNum) {
- roundRect(ui, x, y, 375, 812, 28, '#ffffff', '#1e293b');
- // Header
- roundRect(ui, x, y, 375, 64, 28, '#1e293b', '#1e293b');
- ui.fillRect(x, y + 32, 375, 32);
- ui.fillStyle = '#ffffff';
- ui.font = 'bold 17px Segoe UI';
- ui.fillText(title, x + 24, y + 40);
- // Подпись экрана сверху
- ui.fillStyle = '#0f172a';
- ui.font = 'bold 16px Segoe UI';
- ui.fillText('Экран ' + screenNum + ' (375×812 px)', x + 95, y - 14);
- }
- // Экран 1: Главная
- drawPhone(40, 50, 'Домашняя бухгалтерия', '1: Главная');
- roundRect(ui, 64, 140, 327, 90, 12, '#eff6ff', '#93c5fd');
- ui.fillStyle = '#64748b'; ui.font = '13px Segoe UI';
- ui.fillText('[Label: Текущий баланс]', 78, 165);
- ui.fillStyle = '#0f172a'; ui.font = 'bold 26px Segoe UI';
- ui.fillText('Баланс: 15 000 ₽', 78, 205);
- roundRect(ui, 64, 250, 327, 52, 10, '#dcfce7', '#22c55e');
- ui.fillStyle = '#166534'; ui.font = 'bold 16px Segoe UI';
- ui.fillText('+ Добавить доход [Button]', 110, 282);
- roundRect(ui, 64, 316, 327, 52, 10, '#fee2e2', '#ef4444');
- ui.fillStyle = '#991b1b'; ui.font = 'bold 16px Segoe UI';
- ui.fillText('- Добавить расход [Button]', 110, 348);
- ui.fillStyle = '#0f172a'; ui.font = 'bold 16px Segoe UI';
- ui.fillText('Последние операции [ListView]:', 64, 410);
- roundRect(ui, 64, 425, 327, 55, 8, '#f8fafc', '#cbd5e1');
- ui.fillStyle = '#1e293b'; ui.font = '15px Segoe UI';
- ui.fillText('🛒 Продукты', 78, 458);
- ui.fillStyle = '#dc2626'; ui.font = 'bold 15px Segoe UI';
- ui.fillText('- 1 500 ₽', 305, 458);
- roundRect(ui, 64, 490, 327, 55, 8, '#f8fafc', '#cbd5e1');
- ui.fillStyle = '#1e293b'; ui.font = '15px Segoe UI';
- ui.fillText('💼 Зарплата', 78, 523);
- ui.fillStyle = '#16a34a'; ui.font = 'bold 15px Segoe UI';
- ui.fillText('+ 30 000 ₽', 295, 523);
- roundRect(ui, 40, 798, 375, 64, 16, '#f1f5f9', '#cbd5e1');
- ui.fillStyle = '#1e293b'; ui.font = '14px Segoe UI';
- ui.fillText('🏠 Главная 📊 Отчёты ⚙️ Настройки [NavBar]', 60, 835);
- // Экран 2: Добавить операцию
- drawPhone(485, 50, '← Добавить операцию', '2: Добавить операцию');
- ui.fillStyle = '#0f172a'; ui.font = '15px Segoe UI';
- ui.fillText('Тип операции [RadioGroup]:', 510, 150);
- ui.font = 'bold 15px Segoe UI';
- ui.fillText('○ Доход ● Расход', 510, 178);
- ui.font = '14px Segoe UI'; ui.fillStyle = '#475569';
- ui.fillText('Сумма операции [TextInput / Number]:', 510, 225);
- roundRect(ui, 510, 235, 325, 46, 8, '#ffffff', '#94a3b8');
- ui.fillStyle = '#0f172a'; ui.font = '15px Segoe UI';
- ui.fillText('1500.00 ₽', 525, 263);
- ui.font = '14px Segoe UI'; ui.fillStyle = '#475569';
- ui.fillText('Категория [Dropdown Select]:', 510, 315);
- roundRect(ui, 510, 325, 325, 46, 8, '#ffffff', '#94a3b8');
- ui.fillStyle = '#0f172a'; ui.font = '15px Segoe UI';
- ui.fillText('▼ Выбрать категорию (Продукты)', 525, 353);
- ui.font = '14px Segoe UI'; ui.fillStyle = '#475569';
- ui.fillText('Дата операции [DatePicker]:', 510, 405);
- roundRect(ui, 510, 415, 325, 46, 8, '#ffffff', '#94a3b8');
- ui.fillStyle = '#0f172a'; ui.font = '15px Segoe UI';
- ui.fillText('📅 14.10.2026', 525, 443);
- ui.font = '14px Segoe UI'; ui.fillStyle = '#475569';
- ui.fillText('Комментарий [TextInput]:', 510, 495);
- roundRect(ui, 510, 505, 325, 65, 8, '#ffffff', '#94a3b8');
- ui.fillStyle = '#64748b'; ui.font = '14px Segoe UI';
- ui.fillText('Покупка продуктов на неделю...', 525, 535);
- roundRect(ui, 510, 610, 325, 54, 10, '#2563eb', '#1d4ed8');
- ui.fillStyle = '#ffffff'; ui.font = 'bold 16px Segoe UI';
- ui.fillText('Сохранить [Submit Button]', 575, 642);
- // Экран 3: История
- drawPhone(930, 50, '← История операций', '3: История');
- ui.font = '14px Segoe UI'; ui.fillStyle = '#475569';
- ui.fillText('Фильтр по категориям и дате [Dropdown]:', 955, 145);
- roundRect(ui, 955, 155, 325, 44, 8, '#f8fafc', '#94a3b8');
- ui.fillStyle = '#0f172a'; ui.font = '15px Segoe UI';
- ui.fillText('▼ Фильтр: Все категории', 970, 182);
- ui.fillStyle = '#475569'; ui.font = 'bold 14px Segoe UI';
- ui.fillText('14.10.2026 [Group Header]', 955, 235);
- roundRect(ui, 955, 245, 325, 55, 8, '#f8fafc', '#cbd5e1');
- ui.fillStyle = '#0f172a'; ui.font = '15px Segoe UI';
- ui.fillText('• Продукты — 1 500 ₽', 970, 278);
- roundRect(ui, 955, 310, 325, 55, 8, '#f8fafc', '#cbd5e1');
- ui.fillStyle = '#0f172a'; ui.font = '15px Segoe UI';
- ui.fillText('• Зарплата + 30 000 ₽', 970, 343);
- ui.fillStyle = '#475569'; ui.font = 'bold 14px Segoe UI';
- ui.fillText('13.10.2026 [Group Header]', 955, 400);
- roundRect(ui, 955, 410, 325, 55, 8, '#f8fafc', '#cbd5e1');
- ui.fillStyle = '#0f172a'; ui.font = '15px Segoe UI';
- ui.fillText('• Транспорт — 300 ₽', 970, 443);
- roundRect(ui, 930, 798, 375, 64, 16, '#f1f5f9', '#cbd5e1');
- ui.fillStyle = '#1e293b'; ui.font = '14px Segoe UI';
- ui.fillText('🏠 Главная 📊 Отчёты ⚙️ Настройки [NavBar]', 950, 835);
- function downloadCanvas(id, filename) {
- const link = document.createElement('a');
- link.download = filename;
- link.href = document.getElementById(id).toDataURL('image/png');
- link.click();
- }
- </script>
- </body>
- </html>
RAW Paste Data
Copied
