/
nacha
/
pseado
Обзор
Документация
Войти
/
nacha
/
pseado
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
1
CI/CD
Аналитика
Безопасность
master
demo.html
414 строк
13 KB
alex
feat: add templates for Hatch/Dimension examples, update UI
04 авг 2026, 09:16
Верифицирован
04 авг 2026, 09:16
7f7c0b6
Код
Авторство
О чём код?
<!DOCTYPE html> <html lang="ru"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Псеадо — Демонстрация</title> <style> * { box-sizing: border-box; margin: 0; padding: 0; } body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; background: #f5f5f5; padding: 20px; } h1 { text-align: center; color: #333; margin-bottom: 20px; } .container { display: flex; gap: 20px; max-width: 1400px; margin: 0 auto; } .editor-panel { flex: 1; background: white; border-radius: 8px; padding: 20px; box-shadow: 0 2px 8px rgba(0,0,0,0.1); } .editor-panel h2, .canvas-panel h2 { margin-bottom: 10px; color: #555; } #code-editor { width: 100%; height: 320px; font-family: 'Courier New', monospace; font-size: 14px; padding: 12px; background: #fafafa; border: 1px solid #ddd; border-radius: 4px; resize: vertical; } .templates { margin-top: 10px; display: flex; gap: 8px; flex-wrap: wrap; } .templates button { padding: 6px 12px; border: 1px solid #ddd; border-radius: 4px; background: #fff; cursor: pointer; font-size: 12px; transition: all 0.2s; } .templates button:hover { background: #f0f0f0; border-color: #4CAF50; } .twin-panel { margin-top: 15px; padding: 15px; background: #f8f9fa; border-radius: 6px; border: 1px solid #e9ecef; } .twin-panel h3 { margin-bottom: 10px; color: #666; font-size: 14px; } .twin-field { display: flex; gap: 10px; margin-bottom: 8px; } .twin-field label { width: 120px; font-size: 13px; color: #555; display: flex; align-items: center; } .twin-field input, .twin-field select { flex: 1; padding: 6px 10px; border: 1px solid #ddd; border-radius: 4px; font-size: 13px; } .buttons { margin-top: 10px; display: flex; gap: 10px; } button { padding: 10px 20px; border: none; border-radius: 4px; font-size: 14px; cursor: pointer; transition: background 0.2s; } #render-btn { background: #4CAF50; color: white; } #render-btn:hover { background: #45a049; } #validate-twin-btn { background: #2196F3; color: white; } #validate-twin-btn:hover { background: #1976D2; } #clear-btn { background: #f44336; color: white; } #clear-btn:hover { background: #da190b; } #result { margin-top: 15px; padding: 10px; border-radius: 4px; font-size: 14px; min-height: 40px; } #result.success { background: #e8f5e9; border: 1px solid #4CAF50; color: #2e7d32; } #result.error { background: #ffebee; border: 1px solid #f44336; color: #c62828; } #result.warning { background: #fff3e0; border: 1px solid #ff9800; color: #e65100; } #canvas { border: 1px solid #ddd; border-radius: 4px; background: white; display: block; margin-top: 10px; } .canvas-panel { flex: 1; background: white; border-radius: 8px; padding: 20px; box-shadow: 0 2px 8px rgba(0,0,0,0.1); } .gost-badge { display: inline-block; background: #673AB7; color: white; padding: 2px 8px; border-radius: 12px; font-size: 11px; font-weight: bold; margin-left: 10px; } </style> </head> <body> <h1>📐 Псеадо — Демонстрация <span class="gost-badge">v1.5.0-DEV</span></h1> <div class="container"> <div class="editor-panel"> <h2>Редактор кода</h2> <textarea id="code-editor"></textarea> <div class="templates"> <button id="template-simple">Простой</button> <button id="template-hatch">Штриховка</button> <button id="template-dimension">Размеры</button> <button id="template-gost">ГОСТ чертёж</button> </div> <div class="twin-panel"> <h3>🔖 Метаданные цифрового двойника (GOST Р 57143)</h3> <div class="twin-field"> <label>ID:</label> <input type="text" id="twin-id" value="uuid-2026-001" placeholder="Уникальный идентификатор"> </div> <div class="twin-field"> <label>Ревизия:</label> <input type="number" id="twin-revision" value="1" min="1" placeholder="Версия"> </div> <div class="twin-field"> <label>Статус:</label> <select id="twin-status"> <option value="design">Разработка</option> <option value="manufacturing">Изготовление</option> <option value="operation">Эксплуатация</option> <option value="retired">Утилизировано</option> </select> </div> <div class="buttons"> <button id="validate-twin-btn">🔍 Проверить ЦД</button> </div> </div> <div class="buttons"> <button id="render-btn">▶ Отрисовать</button> <button id="clear-btn">✕ Очистить</button> </div> <div id="result"></div> </div> <div class="canvas-panel"> <h2>Холст</h2> <canvas id="canvas" width="800" height="600"></canvas> </div> </div> <script type="module"> import { Parser } from './src/core/parser.js'; import { Validator } from './src/core/validator.js'; import { GostDigitalTwinValidator } from './src/extensions/digital_twin_validator.js'; import { Renderer2D } from './src/rendering/2d_renderer.js'; const codeEditor = document.getElementById('code-editor'); const renderBtn = document.getElementById('render-btn'); const clearBtn = document.getElementById('clear-btn'); const validateTwinBtn = document.getElementById('validate-twin-btn'); const result = document.getElementById('result'); const canvas = document.getElementById('canvas'); // Примеры кода для шаблонов const templates = { 'template-simple': `-- Простой пример прямоугольник положение=(50,50) ширина=300 высота=200 линия начало=(50,50) конец=(350,250) окружность центр=(200,150) радиус=60 текст содержание="Привет, Псеадо!" позиция-х=120 позиция-у=280 размер-шрифта=16`, 'template-hatch': `-- Штриховки (ГОСТ 2.306-68) прямоугольник положение=(50,50) ширина=150 высота=200 штриховка область=(60,60,130,80) тип=line штриховка область=(60,150,130,80) тип=cross штриховка область=(60,240,130,80) тип=dots прямоугольник положение=(300,50) ширина=150 высота=200 штриховка область=(310,60,130,150) тип=angles -- Штриховки обозначают материал детали`, 'template-dimension': `-- Размерные линии (ГОСТ 2.307-2011) прямоугольник положение=(100,100) ширина=300 высота=150 размер начало=(100,100) конец=(400,100) смещение=30 значение="300" размер начало=(400,100) конец=(400,250) смещение=30 значение="150" размер начало=(100,250) конец=(100,100) смещение=-30 значение="150"`, 'template-gost': `-- Полный чертёж по ГОСТ (v1.5.0) !id=uuid-2026-gost !revision=3 !status=design -- Основной контур прямоугольник положение=(50,50) ширина=350 высота=250 -- Штриховка сечения (ГОСТ 2.306-68, тип line) штриховка область=(60,60,150,100) тип=line -- Вторая штриховка штриховка область=(240,60,150,100) тип=cross -- Отверстия окружность центр=(135,110) радиус=15 окружность центр=(315,110) радиус=15 -- Размерные линии (ГОСТ 2.307-2011) размер начало=(50,50) конец=(400,50) смещение=30 значение="350" размер начало=(400,50) конец=(400,300) смещение=30 значение="250" размер начало=(135,95) конец=(135,125) смещение=25 значение="30" -- Текстовые обозначения текст содержание="Название детали" позиция-х=100 позиция-у=330 размер-шрифта=14 текст содержание="Материал: Сталь" позиция-х=100 позиция-у=350 размер-шрифта=12` }; codeEditor.value = templates['template-gost']; // Шаблоны Object.keys(templates).forEach(id => { document.getElementById(id).addEventListener('click', () => { codeEditor.value = templates[id]; }); }); // Валидация цифрового двойника validateTwinBtn.addEventListener('click', () => { const twinId = document.getElementById('twin-id').value.trim(); const twinRevision = parseInt(document.getElementById('twin-revision').value) || 1; const twinStatus = document.getElementById('twin-status').value; const code = codeEditor.value.trim(); if (!code) { result.className = 'error'; result.textContent = '❌ Введите код для валидации'; return; } try { const parser = new Parser(); const ast = parser.parse(code); // Добавим meta данные к AST ast.meta = { id: twinId, revision: twinRevision, status: twinStatus }; // Валидация const validator = new Validator(); const validation = validator.validate(ast); // Валидация цифрового двойника const twinValidator = new GostDigitalTwinValidator(); const twinResult = twinValidator.validate(ast); // Объединяем результаты const allErrors = [...validation.errors, ...twinResult.errors]; const allWarnings = [...validation.warnings, ...twinResult.warnings]; if (allErrors.length === 0) { result.className = 'success'; let msg = `✅ Валидация пройдена!\n`; msg += `📐 Найдено команд: ${ast.body.length}\n`; // Подсчёт типов команд const types = {}; ast.body.forEach(n => { types[n.type] = (types[n.type] || 0) + 1; }); msg += ` ${Object.entries(types).map(([k,v]) => `${k}: ${v}`).join(', ')}\n`; msg += `🔖 ЦД: ${twinId} (r${twinRevision}, ${twinStatus})`; if (allWarnings.length > 0) { msg += `\n⚠️ Предупреждения: ${allWarnings.length}`; } result.textContent = msg; } else { result.className = 'error'; let msg = `❌ Ошибки валидации:\n`; allErrors.forEach(e => msg += `• ${e}\n`); if (allWarnings.length > 0) { msg += `\n⚠️ Предупреждения:\n`; allWarnings.forEach(w => msg += `• ${w}\n`); } result.textContent = msg; } } catch (e) { result.className = 'error'; result.textContent = '❌ Ошибка: ' + e.message; } }); // Отрисовка renderBtn.addEventListener('click', () => { const code = codeEditor.value.trim(); if (!code) { result.className = 'error'; result.textContent = '❌ Введите код для отрисовки'; return; } try { const parser = new Parser(); const ast = parser.parse(code); const validator = new Validator(); const validation = validator.validate(ast); result.className = validation.valid ? 'success' : 'error'; const messages = validation.valid ? `✅ Валидация пройдена! Найдено команд: ${ast.body.length}` : `❌ Ошибки валидации:\n${validation.errors.map(e => '• ' + e).join('\n')}`; result.textContent = messages; if (validation.valid && ast.body.length > 0) { const renderer = new Renderer2D(); const ctx = renderer.init('canvas'); renderer.render(ast, ctx); } } catch (e) { result.className = 'error'; result.textContent = '❌ Ошибка: ' + e.message; } }); // Очистка clearBtn.addEventListener('click', () => { codeEditor.value = ''; result.className = ''; result.textContent = ''; const ctx = canvas.getContext('2d'); ctx.clearRect(0, 0, canvas.width, canvas.height); }); // Начальная отрисовка renderBtn.click(); </script> </body> </html>