/
ramae
/
QualityControlApp
Обзор
Документация
Войти
/
ramae
/
QualityControlApp
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
outputs/create_app_flowchart_doc.py
222 строки
10 KB
Roman Lis
add project
14 июн 2026, 21:00
14 июн 2026, 21:00
2e49a38
Код
Авторство
О чём код?
from math import atan2, cos, sin, pi from pathlib import Path from PIL import Image, ImageDraw, ImageFont from docx import Document from docx.shared import Cm, Pt, RGBColor from docx.enum.section import WD_ORIENT from docx.enum.text import WD_ALIGN_PARAGRAPH from docx.oxml.ns import qn ROOT = Path(r"C:\Users\roman\OneDrive\Рабочий стол\QualityControlApp") PNG = ROOT / "outputs" / "Блок-схема_приложения.png" DOCX = Path(r"C:\Users\roman\OneDrive\Рабочий стол\Блок-схема_приложения_Евграфов.docx") W, H = 2400, 1500 BG = "#F8FAFC" INK = "#111827" MUTED = "#64748B" BLUE = "#2563EB" BLUE_LIGHT = "#DBEAFE" CYAN = "#06B6D4" CYAN_LIGHT = "#CFFAFE" GREEN = "#16A34A" GREEN_LIGHT = "#DCFCE7" RED = "#EF4444" RED_LIGHT = "#FEE2E2" GRAY = "#E2E8F0" WHITE = "#FFFFFF" FONT = r"C:\Windows\Fonts\arial.ttf" FONT_BOLD = r"C:\Windows\Fonts\arialbd.ttf" f_title = ImageFont.truetype(FONT_BOLD, 54) f_subtitle = ImageFont.truetype(FONT, 25) f_block = ImageFont.truetype(FONT_BOLD, 27) f_small = ImageFont.truetype(FONT, 21) f_label = ImageFont.truetype(FONT_BOLD, 20) def wrap(draw, text, font, max_width): words = text.split() lines, line = [], "" for word in words: candidate = word if not line else line + " " + word if draw.textbbox((0, 0), candidate, font=font)[2] <= max_width: line = candidate else: if line: lines.append(line) line = word if line: lines.append(line) return lines def centered_text(draw, box, title, detail=None, title_font=f_block, fill=INK): x1, y1, x2, y2 = box inner_w = x2 - x1 - 30 title_lines = wrap(draw, title, title_font, inner_w) detail_lines = wrap(draw, detail, f_small, inner_w) if detail else [] title_h = len(title_lines) * (title_font.size + 4) detail_h = len(detail_lines) * (f_small.size + 4) gap = 12 if detail_lines else 0 total = title_h + gap + detail_h y = y1 + (y2 - y1 - total) / 2 for line in title_lines: bbox = draw.textbbox((0, 0), line, font=title_font) draw.text(((x1 + x2 - (bbox[2] - bbox[0])) / 2, y), line, font=title_font, fill=fill) y += title_font.size + 4 y += gap for line in detail_lines: bbox = draw.textbbox((0, 0), line, font=f_small) draw.text(((x1 + x2 - (bbox[2] - bbox[0])) / 2, y), line, font=f_small, fill=MUTED) y += f_small.size + 4 def rounded(draw, box, fill, outline=GRAY, radius=18, width=3, title="", detail=None): draw.rounded_rectangle(box, radius=radius, fill=fill, outline=outline, width=width) centered_text(draw, box, title, detail) def diamond(draw, center, width, height, fill, outline, title): cx, cy = center pts = [(cx, cy - height // 2), (cx + width // 2, cy), (cx, cy + height // 2), (cx - width // 2, cy)] draw.polygon(pts, fill=fill, outline=outline) draw.line(pts + [pts[0]], fill=outline, width=4, joint="curve") centered_text(draw, (cx - width // 2 + 28, cy - height // 2 + 20, cx + width // 2 - 28, cy + height // 2 - 20), title, title_font=f_label) def arrow(draw, start, end, color=BLUE, width=5, label=None, label_pos=None): draw.line([start, end], fill=color, width=width) angle = atan2(end[1] - start[1], end[0] - start[0]) size = 18 p1 = (end[0] - size * cos(angle - pi / 6), end[1] - size * sin(angle - pi / 6)) p2 = (end[0] - size * cos(angle + pi / 6), end[1] - size * sin(angle + pi / 6)) draw.polygon([end, p1, p2], fill=color) if label: lx, ly = label_pos or ((start[0] + end[0]) / 2, (start[1] + end[1]) / 2 - 26) bbox = draw.textbbox((0, 0), label, font=f_label) pad = 7 draw.rounded_rectangle((lx - pad, ly - pad, lx + bbox[2] + pad, ly + bbox[3] + pad), radius=7, fill=BG) draw.text((lx, ly), label, font=f_label, fill=color) img = Image.new("RGB", (W, H), BG) d = ImageDraw.Draw(img) d.text((90, 52), "Блок-схема работы приложения контроля качества", font=f_title, fill=INK) d.text((92, 122), "Путь пользователя, основные модули и взаимодействие с базой данных", font=f_subtitle, fill=MUTED) d.rectangle((90, 168, 2310, 174), fill=CYAN) # Верхний путь авторизации rounded(d, (90, 235, 310, 340), GREEN_LIGHT, GREEN, title="Запуск\nприложения") rounded(d, (390, 220, 700, 355), BLUE_LIGHT, BLUE, title="Авторизация", detail="Ввод логина и пароля") diamond(d, (900, 287), 270, 170, CYAN_LIGHT, CYAN, "Данные верны?") rounded(d, (1080, 220, 1410, 355), BLUE_LIGHT, BLUE, title="Определение роли", detail="Администратор или инспектор") rounded(d, (1510, 220, 1890, 355), WHITE, BLUE, title="Главное окно", detail="Доступные команды зависят от роли") rounded(d, (755, 415, 1045, 525), RED_LIGHT, RED, title="Ошибка входа", detail="Повторный ввод данных") arrow(d, (310, 287), (390, 287)) arrow(d, (700, 287), (765, 287)) arrow(d, (1035, 287), (1080, 287), label="Да", label_pos=(1037, 240)) arrow(d, (1410, 287), (1510, 287)) arrow(d, (900, 372), (900, 415), color=RED, label="Нет", label_pos=(920, 375)) d.line([(755, 470), (545, 470), (545, 355)], fill=RED, width=5) arrow(d, (545, 470), (545, 355), color=RED) # Основные модули d.text((90, 555), "Основные модули", font=f_block, fill=BLUE) modules = [ ((90, 625, 510, 810), BLUE_LIGHT, BLUE, "Учёт партий", "Создание и изменение данных о партиях"), ((580, 625, 1000, 810), CYAN_LIGHT, CYAN, "Контроль качества", "Степень качества, инспектор и дата проверки"), ((1070, 625, 1490, 810), RED_LIGHT, RED, "Учёт дефектов", "Типы дефектов и их количество"), ((1560, 625, 1980, 810), GREEN_LIGHT, GREEN, "Отчёты и графики", "Фильтрация, группировка и расчёты"), ] for box, fill, outline, title, detail in modules: rounded(d, box, fill, outline, title=title, detail=detail) rounded(d, (2025, 625, 2310, 810), WHITE, BLUE, title="Справочники", detail="Только для администратора") # Чистая шина от главного окна к модулям d.line([(1700, 355), (1700, 545), (2165, 545)], fill=BLUE, width=5) d.line([(300, 545), (2165, 545)], fill=BLUE, width=5) for x in (300, 790, 1280, 1770, 2165): arrow(d, (x, 545), (x, 625), color=BLUE) d.text((2035, 555), "Только администратор", font=f_label, fill=BLUE) # База данных и слой доступа rounded(d, (410, 895, 1990, 1000), WHITE, BLUE, title="Entity Framework и LINQ-запросы", detail="Программа получает, фильтрует и сохраняет данные без ручного написания SQL для каждой операции") for x in (300, 790, 1280, 1770, 2165): arrow(d, (x, 810), (min(max(x, 470), 1930), 895), color=MUTED) rounded(d, (650, 1080, 1750, 1255), BLUE_LIGHT, BLUE, title="Microsoft SQL Server", detail="Партии · продукты · сотрудники · статусы · степени качества · типы дефектов · дефекты партий") arrow(d, (1200, 1000), (1200, 1080), color=BLUE, label="Чтение и сохранение", label_pos=(1225, 1020)) # Экспорт rounded(d, (1830, 1080, 2050, 1190), GREEN_LIGHT, GREEN, title="Excel", detail="ClosedXML") rounded(d, (2090, 1080, 2310, 1190), RED_LIGHT, RED, title="PDF", detail="PDFsharp") d.line([(1770, 810), (1770, 840), (2005, 840), (2005, 1025)], fill=GREEN, width=5) arrow(d, (2005, 1025), (1940, 1080), color=GREEN) d.line([(1830, 810), (1830, 860), (2340, 860), (2340, 1025)], fill=RED, width=5) arrow(d, (2340, 1025), (2200, 1080), color=RED) # Итог rounded(d, (650, 1325, 1750, 1440), WHITE, CYAN, title="Результат", detail="Единая история партий, результатов контроля и аналитических отчётов") arrow(d, (1200, 1255), (1200, 1325), color=CYAN) # Легенда d.rounded_rectangle((90, 1305, 500, 1445), radius=14, fill=WHITE, outline=GRAY, width=2) d.text((115, 1325), "Обозначения", font=f_label, fill=INK) d.rectangle((115, 1365, 145, 1395), fill=BLUE_LIGHT, outline=BLUE, width=2) d.text((160, 1367), "основной процесс", font=f_small, fill=MUTED) d.rectangle((115, 1405, 145, 1435), fill=RED_LIGHT, outline=RED, width=2) d.text((160, 1407), "ошибка или дефекты", font=f_small, fill=MUTED) PNG.parent.mkdir(parents=True, exist_ok=True) img.save(PNG, quality=95) # Word document: one-page landscape image sheet doc = Document() sec = doc.sections[0] sec.orientation = WD_ORIENT.LANDSCAPE sec.page_width = Cm(29.7) sec.page_height = Cm(21.0) sec.top_margin = Cm(1.0) sec.bottom_margin = Cm(0.8) sec.left_margin = Cm(1.0) sec.right_margin = Cm(1.0) title = doc.add_paragraph() title.alignment = WD_ALIGN_PARAGRAPH.CENTER title.paragraph_format.space_after = Pt(5) run = title.add_run("Блок-схема работы приложения") run.font.name = "Arial" run._element.get_or_add_rPr().rFonts.set(qn("w:ascii"), "Arial") run._element.get_or_add_rPr().rFonts.set(qn("w:hAnsi"), "Arial") run.font.size = Pt(16) run.bold = True run.font.color.rgb = RGBColor(17, 24, 39) p = doc.add_paragraph() p.alignment = WD_ALIGN_PARAGRAPH.CENTER p.paragraph_format.space_after = Pt(3) p.add_run().add_picture(str(PNG), width=Cm(26.8)) caption = doc.add_paragraph() caption.alignment = WD_ALIGN_PARAGRAPH.CENTER caption.paragraph_format.space_before = Pt(2) caption.paragraph_format.space_after = Pt(0) r = caption.add_run("Рисунок 1 – Блок-схема информационной системы контроля качества продукции") r.font.name = "Arial" r._element.get_or_add_rPr().rFonts.set(qn("w:ascii"), "Arial") r._element.get_or_add_rPr().rFonts.set(qn("w:hAnsi"), "Arial") r.font.size = Pt(10) doc.core_properties.title = "Блок-схема приложения контроля качества" doc.core_properties.author = "Евграфов" doc.save(DOCX) print(PNG) print(DOCX)