Guest

Гмгммгиг

Oct 14th, 2026
16
0
Never
Not a member of GistPad yet? Sign Up, it unlocks many cool features!
None 21.32 KB | None | 0 0
  1. <!DOCTYPE html>
  2. <html lang="ru">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Экспорт PNG — Домашняя бухгалтерия</title>
  6. <style>
  7. body { background: #121212; color: #fff; font-family: 'Segoe UI', Arial, sans-serif; padding: 20px; }
  8. .toolbar { margin-bottom: 20px; display: flex; gap: 12px; }
  9. button { background: #2563eb; color: #fff; border: none; padding: 12px 20px; border-radius: 8px; cursor: pointer; font-size: 15px; font-weight: 600; }
  10. button:hover { background: #1d4ed8; }
  11. 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%; }
  12. </style>
  13. </head>
  14. <body>
  15.  
  16. <div class="toolbar">
  17. <button onclick="downloadCanvas('archCanvas', 'Архитектура_проекта.png')">⬇️ Скачать Архитектура_проекта.png</button>
  18. <button onclick="downloadCanvas('uiCanvas', 'Макеты_интерфейса.png')">⬇️ Скачать Макеты_интерфейса.png</button>
  19. </div>
  20.  
  21. <h3>1. Схема архитектуры проекта (Этап 5)</h3>
  22. <canvas id="archCanvas" width="950" height="680"></canvas>
  23.  
  24. <h3>2. Макеты интерфейса 375×812 с подписями элементов (Этап 7)</h3>
  25. <canvas id="uiCanvas" width="1350" height="900"></canvas>
  26.  
  27. <script>
  28. function roundRect(ctx, x, y, w, h, r, fill, stroke) {
  29. ctx.beginPath();
  30. ctx.roundRect(x, y, w, h, r);
  31. if (fill) { ctx.fillStyle = fill; ctx.fill(); }
  32. if (stroke) { ctx.strokeStyle = stroke; ctx.lineWidth = 2; ctx.stroke(); }
  33. }
  34.  
  35. function drawArrow(ctx, x1, y1, x2, y2, label) {
  36. ctx.strokeStyle = '#334155';
  37. ctx.fillStyle = '#334155';
  38. ctx.lineWidth = 2;
  39. ctx.beginPath();
  40. ctx.moveTo(x1, y1);
  41. ctx.lineTo(x2, y2);
  42. ctx.stroke();
  43. const angle = Math.atan2(y2 - y1, x2 - x1);
  44. ctx.beginPath();
  45. ctx.moveTo(x2, y2);
  46. ctx.lineTo(x2 - 10 * Math.cos(angle - Math.PI / 6), y2 - 10 * Math.sin(angle - Math.PI / 6));
  47. ctx.lineTo(x2 - 10 * Math.cos(angle + Math.PI / 6), y2 - 10 * Math.sin(angle + Math.PI / 6));
  48. ctx.closePath();
  49. ctx.fill();
  50. if (label) {
  51. ctx.font = 'italic 13px Segoe UI';
  52. ctx.fillStyle = '#0f172a';
  53. ctx.fillText(label, (x1 + x2) / 2 + 10, (y1 + y2) / 2 + 4);
  54. }
  55. }
  56.  
  57. // 1. Отрисовка архитектуры
  58. const arch = document.getElementById('archCanvas').getContext('2d');
  59. arch.fillStyle = '#ffffff';
  60. arch.fillRect(0, 0, 950, 680);
  61.  
  62. arch.fillStyle = '#0f172a';
  63. arch.font = 'bold 20px Segoe UI';
  64. arch.fillText('Архитектура приложения «Домашняя бухгалтерия»', 220, 35);
  65.  
  66. // Блоки
  67. roundRect(arch, 120, 60, 360, 95, 10, '#dbeafe', '#3b82f6');
  68. arch.fillStyle = '#1e3a8a'; arch.font = 'bold 16px Segoe UI';
  69. arch.fillText('UI-модуль (Presentation Layer)', 175, 90);
  70. arch.fillStyle = '#1e293b'; arch.font = '14px Segoe UI';
  71. arch.fillText('Экраны: Главная | Добавить | История | Отчёты', 145, 120);
  72. arch.fillText('Ввод данных и отображение состояния', 175, 142);
  73.  
  74. roundRect(arch, 120, 215, 360, 115, 10, '#dcfce7', '#22c55e');
  75. arch.fillStyle = '#14532d'; arch.font = 'bold 16px Segoe UI';
  76. arch.fillText('Модуль логики (Business Logic)', 175, 245);
  77. arch.fillStyle = '#1e293b'; arch.font = '14px Segoe UI';
  78. arch.fillText('Класс FinanceManager:', 145, 270);
  79. arch.fillText('• расчёт баланса (get_balance)', 145, 292);
  80. arch.fillText('• фильтрация и отчёты по категориям', 145, 314);
  81.  
  82. roundRect(arch, 580, 215, 320, 115, 10, '#fef9c3', '#eab308');
  83. arch.fillStyle = '#713f12'; arch.font = 'bold 16px Segoe UI';
  84. arch.fillText('Модуль моделей (Domain Models)', 605, 245);
  85. arch.fillStyle = '#1e293b'; arch.font = '14px Segoe UI';
  86. arch.fillText('• Класс Operation (id, amount, type,', 600, 272);
  87. arch.fillText(' category_id, date, comment)', 600, 292);
  88. arch.fillText('• Класс Category (id, name, icon)', 600, 314);
  89.  
  90. roundRect(arch, 120, 390, 360, 105, 10, '#ffedd5', '#f97316');
  91. arch.fillStyle = '#7c2d12'; arch.font = 'bold 16px Segoe UI';
  92. arch.fillText('Модуль данных (Data Access Layer)', 160, 420);
  93. arch.fillStyle = '#1e293b'; arch.font = '14px Segoe UI';
  94. arch.fillText('• DatabaseConnection (Singleton)', 145, 448);
  95. arch.fillText('• OperationRepository / CategoryRepository', 145, 472);
  96.  
  97. roundRect(arch, 120, 555, 360, 90, 10, '#f1f5f9', '#64748b');
  98. arch.fillStyle = '#0f172a'; arch.font = 'bold 16px Segoe UI';
  99. arch.fillText('Локальная БД SQLite (finance.db)', 170, 588);
  100. arch.font = '14px Segoe UI';
  101. arch.fillText('Таблицы: operations, categories', 195, 618);
  102.  
  103. // Стрелки
  104. drawArrow(arch, 300, 155, 300, 215, 'События UI / Данные операций');
  105. drawArrow(arch, 480, 272, 580, 272, 'Объекты моделей');
  106. drawArrow(arch, 300, 330, 300, 390, 'Вызовы методов репозитория');
  107. drawArrow(arch, 300, 495, 300, 555, 'SQL-запросы (SELECT / INSERT)');
  108. drawArrow(arch, 480, 442, 740, 330, 'Маппинг строк БД в объекты');
  109.  
  110. // 2. Отрисовка макетов 375x812
  111. const ui = document.getElementById('uiCanvas').getContext('2d');
  112. ui.fillStyle = '#f8fafc';
  113. ui.fillRect(0, 0, 1350, 900);
  114.  
  115. function drawPhone(x, y, title, screenNum) {
  116. roundRect(ui, x, y, 375, 812, 28, '#ffffff', '#1e293b');
  117. // Header
  118. roundRect(ui, x, y, 375, 64, 28, '#1e293b', '#1e293b');
  119. ui.fillRect(x, y + 32, 375, 32);
  120. ui.fillStyle = '#ffffff';
  121. ui.font = 'bold 17px Segoe UI';
  122. ui.fillText(title, x + 24, y + 40);
  123. // Подпись экрана сверху
  124. ui.fillStyle = '#0f172a';
  125. ui.font = 'bold 16px Segoe UI';
  126. ui.fillText('Экран ' + screenNum + ' (375×812 px)', x + 95, y - 14);
  127. }
  128.  
  129. // Экран 1: Главная
  130. drawPhone(40, 50, 'Домашняя бухгалтерия', '1: Главная');
  131. roundRect(ui, 64, 140, 327, 90, 12, '#eff6ff', '#93c5fd');
  132. ui.fillStyle = '#64748b'; ui.font = '13px Segoe UI';
  133. ui.fillText('[Label: Текущий баланс]', 78, 165);
  134. ui.fillStyle = '#0f172a'; ui.font = 'bold 26px Segoe UI';
  135. ui.fillText('Баланс: 15 000 ₽', 78, 205);
  136.  
  137. roundRect(ui, 64, 250, 327, 52, 10, '#dcfce7', '#22c55e');
  138. ui.fillStyle = '#166534'; ui.font = 'bold 16px Segoe UI';
  139. ui.fillText('+ Добавить доход [Button]', 110, 282);
  140.  
  141. roundRect(ui, 64, 316, 327, 52, 10, '#fee2e2', '#ef4444');
  142. ui.fillStyle = '#991b1b'; ui.font = 'bold 16px Segoe UI';
  143. ui.fillText('- Добавить расход [Button]', 110, 348);
  144.  
  145. ui.fillStyle = '#0f172a'; ui.font = 'bold 16px Segoe UI';
  146. ui.fillText('Последние операции [ListView]:', 64, 410);
  147. roundRect(ui, 64, 425, 327, 55, 8, '#f8fafc', '#cbd5e1');
  148. ui.fillStyle = '#1e293b'; ui.font = '15px Segoe UI';
  149. ui.fillText('🛒 Продукты', 78, 458);
  150. ui.fillStyle = '#dc2626'; ui.font = 'bold 15px Segoe UI';
  151. ui.fillText('- 1 500 ₽', 305, 458);
  152.  
  153. roundRect(ui, 64, 490, 327, 55, 8, '#f8fafc', '#cbd5e1');
  154. ui.fillStyle = '#1e293b'; ui.font = '15px Segoe UI';
  155. ui.fillText('💼 Зарплата', 78, 523);
  156. ui.fillStyle = '#16a34a'; ui.font = 'bold 15px Segoe UI';
  157. ui.fillText('+ 30 000 ₽', 295, 523);
  158.  
  159. roundRect(ui, 40, 798, 375, 64, 16, '#f1f5f9', '#cbd5e1');
  160. ui.fillStyle = '#1e293b'; ui.font = '14px Segoe UI';
  161. ui.fillText('🏠 Главная 📊 Отчёты ⚙️ Настройки [NavBar]', 60, 835);
  162.  
  163. // Экран 2: Добавить операцию
  164. drawPhone(485, 50, '← Добавить операцию', '2: Добавить операцию');
  165. ui.fillStyle = '#0f172a'; ui.font = '15px Segoe UI';
  166. ui.fillText('Тип операции [RadioGroup]:', 510, 150);
  167. ui.font = 'bold 15px Segoe UI';
  168. ui.fillText('○ Доход ● Расход', 510, 178);
  169.  
  170. ui.font = '14px Segoe UI'; ui.fillStyle = '#475569';
  171. ui.fillText('Сумма операции [TextInput / Number]:', 510, 225);
  172. roundRect(ui, 510, 235, 325, 46, 8, '#ffffff', '#94a3b8');
  173. ui.fillStyle = '#0f172a'; ui.font = '15px Segoe UI';
  174. ui.fillText('1500.00 ₽', 525, 263);
  175.  
  176. ui.font = '14px Segoe UI'; ui.fillStyle = '#475569';
  177. ui.fillText('Категория [Dropdown Select]:', 510, 315);
  178. roundRect(ui, 510, 325, 325, 46, 8, '#ffffff', '#94a3b8');
  179. ui.fillStyle = '#0f172a'; ui.font = '15px Segoe UI';
  180. ui.fillText('▼ Выбрать категорию (Продукты)', 525, 353);
  181.  
  182. ui.font = '14px Segoe UI'; ui.fillStyle = '#475569';
  183. ui.fillText('Дата операции [DatePicker]:', 510, 405);
  184. roundRect(ui, 510, 415, 325, 46, 8, '#ffffff', '#94a3b8');
  185. ui.fillStyle = '#0f172a'; ui.font = '15px Segoe UI';
  186. ui.fillText('📅 14.10.2026', 525, 443);
  187.  
  188. ui.font = '14px Segoe UI'; ui.fillStyle = '#475569';
  189. ui.fillText('Комментарий [TextInput]:', 510, 495);
  190. roundRect(ui, 510, 505, 325, 65, 8, '#ffffff', '#94a3b8');
  191. ui.fillStyle = '#64748b'; ui.font = '14px Segoe UI';
  192. ui.fillText('Покупка продуктов на неделю...', 525, 535);
  193.  
  194. roundRect(ui, 510, 610, 325, 54, 10, '#2563eb', '#1d4ed8');
  195. ui.fillStyle = '#ffffff'; ui.font = 'bold 16px Segoe UI';
  196. ui.fillText('Сохранить [Submit Button]', 575, 642);
  197.  
  198. // Экран 3: История
  199. drawPhone(930, 50, '← История операций', '3: История');
  200. ui.font = '14px Segoe UI'; ui.fillStyle = '#475569';
  201. ui.fillText('Фильтр по категориям и дате [Dropdown]:', 955, 145);
  202. roundRect(ui, 955, 155, 325, 44, 8, '#f8fafc', '#94a3b8');
  203. ui.fillStyle = '#0f172a'; ui.font = '15px Segoe UI';
  204. ui.fillText('▼ Фильтр: Все категории', 970, 182);
  205.  
  206. ui.fillStyle = '#475569'; ui.font = 'bold 14px Segoe UI';
  207. ui.fillText('14.10.2026 [Group Header]', 955, 235);
  208. roundRect(ui, 955, 245, 325, 55, 8, '#f8fafc', '#cbd5e1');
  209. ui.fillStyle = '#0f172a'; ui.font = '15px Segoe UI';
  210. ui.fillText('• Продукты — 1 500 ₽', 970, 278);
  211.  
  212. roundRect(ui, 955, 310, 325, 55, 8, '#f8fafc', '#cbd5e1');
  213. ui.fillStyle = '#0f172a'; ui.font = '15px Segoe UI';
  214. ui.fillText('• Зарплата + 30 000 ₽', 970, 343);
  215.  
  216. ui.fillStyle = '#475569'; ui.font = 'bold 14px Segoe UI';
  217. ui.fillText('13.10.2026 [Group Header]', 955, 400);
  218. roundRect(ui, 955, 410, 325, 55, 8, '#f8fafc', '#cbd5e1');
  219. ui.fillStyle = '#0f172a'; ui.font = '15px Segoe UI';
  220. ui.fillText('• Транспорт — 300 ₽', 970, 443);
  221.  
  222. roundRect(ui, 930, 798, 375, 64, 16, '#f1f5f9', '#cbd5e1');
  223. ui.fillStyle = '#1e293b'; ui.font = '14px Segoe UI';
  224. ui.fillText('🏠 Главная 📊 Отчёты ⚙️ Настройки [NavBar]', 950, 835);
  225.  
  226. function downloadCanvas(id, filename) {
  227. const link = document.createElement('a');
  228. link.download = filename;
  229. link.href = document.getElementById(id).toDataURL('image/png');
  230. link.click();
  231. }
  232. </script>
  233. </body>
  234. </html>
RAW Paste Data Copied