Отзывы и предложения к софту от AleXStam
  • Страница 24 из 24
  • «
  • 1
  • 2
  • 22
  • 23
  • 24
Поговорим о...
<!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;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}

body {
margin: 0;
padding: 20px;
background-color: #f5f7fa;
color: #333;
}

.container {
max-width: 1200px;
margin: 0 auto;
background-color: white;
border-radius: 10px;
box-shadow: 0 0 20px rgba(0, 0, 0, 0.1);
padding: 25px;
}

h1 {
color: #2c3e50;
text-align: center;
margin-bottom: 30px;
border-bottom: 2px solid #3498db;
padding-bottom: 15px;
}

.section {
margin-bottom: 30px;
padding: 20px;
border-radius: 8px;
background-color: #f8f9fa;
}

.section-title {
font-size: 1.3rem;
color: #2c3e50;
margin-bottom: 15px;
display: flex;
align-items: center;
}

.form-group {
margin-bottom: 15px;
}

label {
display: block;
margin-bottom: 5px;
font-weight: 600;
color: #2c3e50;
}

input, textarea, select {
width: 100%;
padding: 10px;
border: 1px solid #ddd;
border-radius: 4px;
font-size: 16px;
}

textarea {
min-height: 100px;
resize: vertical;
}

button {
background-color: #3498db;
color: white;
border: none;
padding: 12px 20px;
border-radius: 4px;
cursor: pointer;
font-size: 16px;
font-weight: 600;
transition: background-color 0.3s;
}

button:hover {
background-color: #2980b9;
}

button.secondary {
background-color: #95a5a6;
}

button.secondary:hover {
background-color: #7f8c8d;
}

table {
width: 100%;
border-collapse: collapse;
margin-top: 10px;
}

th, td {
border: 1px solid #ddd;
padding: 12px;
text-align: left;
}

th {
background-color: #3498db;
color: white;
}

tr:nth-child(even) {
background-color: #f2f2f2;
}

.preview-container {
display: flex;
flex-wrap: wrap;
gap: 20px;
margin-top: 20px;
}

.preview-item {
border: 1px solid #ddd;
border-radius: 8px;
padding: 15px;
width: 200px;
text-align: center;
background-color: white;
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
}

.preview-svg {
height: 100px;
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 10px;
}

.preview-svg svg {
max-width: 100%;
max-height: 100%;
}

.preview-code {
font-weight: bold;
color: #2c3e50;
}

.preview-name {
color: #7f8c8d;
font-size: 0.9rem;
}

.hidden {
display: none;
}

.message {
padding: 15px;
border-radius: 4px;
margin: 15px 0;
}

.success {
background-color: #d4edda;
color: #155724;
border: 1px solid #c3e6cb;
}

.error {
background-color: #f8d7da;
color: #721c24;
border: 1px solid #f5c6cb;
}

.actions {
display: flex;
gap: 10px;
margin-top: 20px;
}

.file-input-container {
position: relative;
overflow: hidden;
display: inline-block;
width: 100%;
}

.file-input-container input[type=file] {
position: absolute;
left: 0;
top: 0;
opacity: 0;
width: 100%;
height: 100%;
cursor: pointer;
}

.file-input-button {
display: block;
padding: 10px;
background: #f8f9fa;
border: 2px dashed #3498db;
border-radius: 4px;
text-align: center;
color: #3498db;
font-weight: 600;
}

.file-list {
margin-top: 10px;
max-height: 150px;
overflow-y: auto;
border: 1px solid #ddd;
border-radius: 4px;
padding: 10px;
}

.file-item {
display: flex;
justify-content: space-between;
padding: 5px 0;
border-bottom: 1px solid #eee;
}

.file-item:last-child {
border-bottom: none;
}

.file-name {
flex-grow: 1;
}

.file-size {
color: #7f8c8d;
font-size: 0.8rem;
}

.data-table-container {
overflow-x: auto;
}

.help-text {
font-size: 0.9rem;
color: #7f8c8d;
margin-top: 5px;
}
</style>
</head>
<body>
<div class="container">
<h1>Генератор шаблонов литологии</h1>

<div class="section">
<h2 class="section-title">1. Загрузка SVG-файлов с текстурами</h2>
<div class="form-group">
<label>Выберите папку с SVG-файлами:</label>
<div class="file-input-container">
<div class="file-input-button">Выбрать папку с SVG-файлами</div>
<input type="file" id="svgFolderInput" webkitdirectory multiple>
</div>
<div class="help-text">SVG-файлы должны быть названы в формате "Код_Породы Название.svg", например: "1000 Лед.svg"</div>
</div>

<div class="form-group">
<label>Путь к SVG файлам в программе:</label>
<input type="text" id="svgFilePath" placeholder="C:/Users/User/AppData/Local/OISTerra/OISTerraManager/svg/" value="C:/Users/StamberskiyAA/AppData/Local/OISTerra/OISTerraManager/svg/">
<div class="help-text">Укажите путь, который будет использоваться в сгенерированном JSON файле</div>
</div>

<div id="fileList" class="file-list hidden">
<!-- Список загруженных файлов будет здесь -->
</div>
</div>

<div class="section">
<h2 class="section-title">2. Ввод данных о породах</h2>
<div class="form-group">
<label>Добавить данные о породах:</label>
<div class="help-text">Введите данные в формате: Код_Породы Название (каждая порода с новой строки)</div>
<textarea id="rockDataInput" placeholder="1300 Суглинок
1700 Илы
1800 Торф
1400 Супесь
2300 Аргиллит
2400 Алевролит"></textarea>
</div>

<div class="actions">
<button id="parseDataBtn">Обработать данные</button>
<button id="addRockBtn" class="secondary">Добавить породу вручную</button>
</div>

<div id="rockTableContainer" class="data-table-container hidden">
<h3>Список пород:</h3>
<table id="rockTable">
<thead>
<tr>
<th>Код породы</th>
<th>Наименование породы</th>
<th>SVG файл</th>
<th>Действия</th>
</tr>
</thead>
<tbody id="rockTableBody">
<!-- Данные о породах будут здесь -->
</tbody>
</table>
</div>
</div>

<div class="section">
<h2 class="section-title">3. Предварительный просмотр</h2>
<div id="previewContainer" class="preview-container">
<!-- Предварительный просмотр будет здесь -->
</div>
</div>

<div class="section">
<h2 class="section-title">4. Генерация шаблона</h2>
<div class="form-group">
<label>Название палитры:</label>
<input type="text" id="paletteName" value="тест_лито">
</div>

<div class="form-group">
<label>Название шаблона корреляции:</label>
<input type="text" id="templateName" value="Корреляционный шаблон">
</div>

<div class="actions">
<button id="generateBtn">Сгенерировать JSON шаблон</button>
<button id="downloadBtn" class="secondary hidden">Скачать шаблон</button>
</div>

<div id="messageArea"></div>

<div id="jsonOutput" class="hidden">
<h3>Сгенерированный JSON:</h3>
<pre id="jsonContent"></pre>
</div>
</div>
</div>

<script>
// Переменные для хранения данных
let svgFiles = {};
let rockData = [];

// Элементы DOM
const svgFolderInput = document.getElementById('svgFolderInput');
const svgFilePathInput = document.getElementById('svgFilePath');
const fileList = document.getElementById('fileList');
const rockDataInput = document.getElementById('rockDataInput');
const parseDataBtn = document.getElementById('parseDataBtn');
const addRockBtn = document.getElementById('addRockBtn');
const rockTableContainer = document.getElementById('rockTableContainer');
const rockTableBody = document.getElementById('rockTableBody');
const previewContainer = document.getElementById('previewContainer');
const paletteNameInput = document.getElementById('paletteName');
const templateNameInput = document.getElementById('templateName');
const generateBtn = document.getElementById('generateBtn');
const downloadBtn = document.getElementById('downloadBtn');
const messageArea = document.getElementById('messageArea');
const jsonOutput = document.getElementById('jsonOutput');
const jsonContent = document.getElementById('jsonContent');

// Функция для правильного форматирования SVG контента
function formatSvgContent(svgContent) {
// В рабочем примере SVG имеет специфичную структуру с дополнительными атрибутами
// Заменяем корневой тег SVG на тот, который используется в рабочем примере
let formatted = svgContent.replace(
/<svg[^>]*>/,
`<svg id="svg1" height="142px" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" viewBox="0 0 282 142" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#" width="282px" xmlns:dc="http://purl.org/dc/elements/1.1/" version="1.1">`
);

// Добавляем метаданные, которые есть в рабочем примере
formatted = formatted.replace(
/<defs id="defs1"\/>/,
`<metadata> <rdf:RDF> <cc:Work> <dc:title>ИСИХОГИ_Литология</dc:title> </cc:Work> </rdf:RDF> </metadata> <defs id="defs1"/>`
);

// В рабочем примере используются одинарные кавычки для XML декларации
// и двойные для атрибутов SVG
formatted = formatted.replace(/<?xml version="1.0" encoding="UTF-8"?>/, `<?xml version='1.0' encoding='UTF-8'?>`);

// В рабочем примере теги line имеют другой формат атрибутов
formatted = formatted.replace(
/<line ([^>]*)\/>/g,
'<line $1/>'
);

// Экранируем только амперсанды
formatted = formatted.replace(/&(?!amp;|lt;|gt;|quot;|#)/g, '&');

return formatted;
}

// Обработка загрузки SVG файлов
svgFolderInput.addEventListener('change', function(e) {
const files = Array.from(e.target.files);
svgFiles = {};

// Очистка списка файлов
fileList.innerHTML = '';

// Фильтрация только SVG файлов
const svgFilesList = files.filter(file => file.name.toLowerCase().endsWith('.svg'));

if (svgFilesList.length === 0) {
fileList.innerHTML = '<div>SVG файлы не найдены</div>';
fileList.classList.remove('hidden');
return;
}

// Обработка каждого SVG файла
svgFilesList.forEach(file => {
const fileName = file.name;
const codeMatch = fileName.match(/^(\d+)/);

if (codeMatch) {
const code = codeMatch[1];

const reader = new FileReader();
reader.onload = function(e) {
const svgContent = e.target.result;
svgFiles[code] = {
name: fileName,
content: svgContent
};

// Добавление в список файлов
const fileItem = document.createElement('div');
fileItem.className = 'file-item';
fileItem.innerHTML = `
<div class="file-name">${fileName}</div>
<div class="file-size">${(file.size / 1024).toFixed(2)} KB</div>
`;
fileList.appendChild(fileItem);

// Обновление таблицы пород, если код уже есть
updateRockTableWithSvg(code);
};
reader.readAsText(file);
}
});

fileList.classList.remove('hidden');
showMessage(`Загружено ${svgFilesList.length} SVG файлов`, 'success');
});

// Обработка данных о породах
parseDataBtn.addEventListener('click', function() {
const inputText = rockDataInput.value.trim();
if (!inputText) {
showMessage('Введите данные о породах', 'error');
return;
}

const lines = inputText.split('\n');
rockData = [];

lines.forEach(line => {
const trimmedLine = line.trim();
if (trimmedLine) {
const parts = trimmedLine.split(/\s+/);
if (parts.length >= 2) {
const code = parts[0];
const name = parts.slice(1).join(' ');
rockData.push({
code: code,
name: name,
svgFile: svgFiles[code] ? svgFiles[code].name : null
});
}
}
});

updateRockTable();
updatePreview();
showMessage(`Обработано ${rockData.length} пород`, 'success');
});

// Добавление породы вручную
addRockBtn.addEventListener('click', function() {
const code = prompt('Введите код породы:');
if (!code) return;

const name = prompt('Введите название породы:');
if (!name) return;

rockData.push({
code: code,
name: name,
svgFile: svgFiles[code] ? svgFiles[code].name : null
});

updateRockTable();
updatePreview();
showMessage(`Добавлена порода: ${code} ${name}`, 'success');
});

// Обновление таблицы пород
function updateRockTable() {
rockTableBody.innerHTML = '';

if (rockData.length === 0) {
rockTableContainer.classList.add('hidden');
return;
}

rockData.forEach((rock, index) => {
const row = document.createElement('tr');
row.innerHTML = `
<td>${rock.code}</td>
<td>${rock.name}</td>
<td>${rock.svgFile || 'Не найден'}</td>
<td>
<button onclick="removeRock(${index})">Удалить</button>
</td>
`;
rockTableBody.appendChild(row);
});

rockTableContainer.classList.remove('hidden');
}

// Обновление таблицы при наличии SVG
function updateRockTableWithSvg(code) {
rockData.forEach(rock => {
if (rock.code === code) {
rock.svgFile = svgFiles[code].name;
}
});

updateRockTable();
updatePreview();
}

// Удаление породы
function removeRock(index) {
rockData.splice(index, 1);
updateRockTable();
updatePreview();
showMessage('Порода удалена', 'success');
}

// Обновление предварительного просмотра
function updatePreview() {
previewContainer.innerHTML = '';

if (rockData.length === 0) {
previewContainer.innerHTML = '<p>Нет данных для предварительного просмотра</p>';
return;
}

rockData.forEach(rock => {
const previewItem = document.createElement('div');
previewItem.className = 'preview-item';

let svgPreview = '<div>SVG не загружен</div>';
if (rock.svgFile && svgFiles[rock.code]) {
svgPreview = svgFiles[rock.code].content;
}

previewItem.innerHTML = `
<div class="preview-svg">${svgPreview}</div>
<div class="preview-code">${rock.code}</div>
<div class="preview-name">${rock.name}</div>
`;

previewContainer.appendChild(previewItem);
});
}

// Генерация JSON шаблона
generateBtn.addEventListener('click', function() {
if (rockData.length === 0) {
showMessage('Нет данных о породах для генерации шаблона', 'error');
return;
}

const paletteName = paletteNameInput.value || 'тест_лито';
const templateName = templateNameInput.value || 'Корреляционный шаблон';
const svgFilePath = svgFilePathInput.value || 'C:/Users/StamberskiyAA/AppData/Local/OISTerra/OISTerraManager/svg/';

// Создание элементов палитры
const paletteItems = rockData.map(rock => {
let svgContent = '';

if (rock.svgFile && svgFiles[rock.code]) {
// Правильное форматирование SVG для XML
svgContent = formatSvgContent(svgFiles[rock.code].content);
}

// Генерация случайного ID
const id = Date.now() + Math.floor(Math.random() * 1000);

// Полный путь к файлу SVG
const fullSvgFilePath = svgFilePath + rock.svgFile;

// Точный порядок атрибутов как в рабочем примере
return {
"color": "#ffffffff",
"data": `<StyledFill name="" group="" brushColor="#000000" objectName="" id="${id}" penColor="#000000">\n <SvgFill penWidth="0.4" objectName="" patternWidth="20" lineWidth="0.4" svgFilePath="${fullSvgFilePath}" svgContent="${svgContent}"/>\n</StyledFill>\n`,
"desc": rock.name,
"value": parseInt(rock.code)
};
});

// Создание основного JSON объекта с фиксированными ID как в рабочем примере
const templateJson = {
"Info": "OISTerra CorrTemplates",
"Palettes": [
{
"Items": paletteItems,
"id": Date.now(),
"name": paletteName,
"transp": true,
"type": 1
}
],
"ScoPaletteVersion": 1,
"corrTemplates": [
{
"Tracks": [
{
"allHeight": false,
"hTxtSet": {
"vis": true
},
"lineStyle": {
"fCol": "#ffc8ffff"
},
"trackId": 1763096947027,
"type": 0
},
{
"Logs": [
{
"logDataVers": 1,
"logId": 1763096947080,
"logParams": [
{
"contId": 1763096947014,
"contName": "РИГИС",
"id": 1763096947013,
"nm": "литология"
}
],
"logType": 3,
"trackId": 1763096947055
}
],
"allHeight": false,
"hTxtSet": {
"vis": false
},
"lineStyle": {
"fCol": "#ffc8ffff"
},
"trackId": 1763096947055,
"width": 50.69166666666666
}
],
"Version": {
"build": 3,
"fillData": 0,
"horizonView": 0,
"logData": 1,
"logRange": 0,
"plastBuild": 0,
"plastData": 0,
"stratBuild": 0,
"stratData": 0,
"stratWidth": 0,
"timeDepth": 0,
"trackWidth": 1,
"view": 7
},
"header": {
"textBlockList": {
"textBlocks": [
{
"blockId": 1763096947023,
"textItems": [
{
"blockId": 1763096947023,
"content": "[WellName]",
"font": {
"b": true
},
"itemId": 1763096947024,
"paramsHash": [
{
"id": -1,
"key": "[WellName]"
}
]
}
]
}
]
}
},
"id": Date.now() + 1000,
"name": templateName,
"plastList": {
"columnId": 1763096947025,
"isPlast": true,
"type": 0
}
}
],
"corrTemplatesVersion": 0
};

// Отображение JSON
jsonContent.textContent = JSON.stringify(templateJson, null, 2);
jsonOutput.classList.remove('hidden');
downloadBtn.classList.remove('hidden');

// Сохранение JSON для скачивания
window.generatedJson = templateJson;

showMessage('JSON шаблон успешно сгенерирован', 'success');
});

// Скачивание JSON файла
downloadBtn.addEventListener('click', function() {
if (!window.generatedJson) {
showMessage('Нет сгенерированного JSON для скачивания', 'error');
return;
}

const dataStr = JSON.stringify(window.generatedJson, null, 2);
const dataBlob = new Blob([dataStr], {type: 'application/json'});

const url = URL.createObjectURL(dataBlob);
const link = document.createElement('a');
link.href = url;
link.download = 'литология_шаблон.json';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
URL.revokeObjectURL(url);

showMessage('Файл успешно скачан', 'success');
});

// Функция для отображения сообщений
function showMessage(message, type) {
messageArea.innerHTML = `<div class="message ${type}">${message}</div>`;

// Автоматическое скрытие сообщения через 5 секунд
setTimeout(() => {
messageArea.innerHTML = '';
}, 5000);
}

// Инициализация при загрузке страницы
window.onload = function() {
// Добавляем пример данных для демонстрации
rockDataInput.value = `1300 Суглинок
1700 Илы
1800 Торф
1400 Супесь
2300 Аргиллит
2400 Алевролит`;
};
</script>
</body>
</html>
нет код должен быть таким
"data": "<StyledFill name=\"\" group=\"\" brushColor=\"#000000\" objectName=\"\" id=\"1763111511311\" penColor=\"#000000\">\n <SvgFill penWidth=\"0.4\" objectName=\"\" patternWidth=\"20\" lineWidth=\"0.4\" svgFilePath=\"C:/Users/StamberskiyAA/AppData/Local/OISTerra/OISTerraManager/svg/1000 Лед.svg\" svgContent=\"<?xml version='1.0' encoding='UTF-8'?> <svg id="svg1" height="142px" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" viewBox="0 0 282 142" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#" width="282px" xmlns:dc="http://purl.org/dc/elements/1.1/" version="1.1"> <metadata> <rdf:RDF> <cc:Work> <dc:title>ИСИХОГИ_Литология</dc:title> </cc:Work> </rdf:RDF> </metadata> <defs id="defs1"/> <g id="layer1"> <line id="19935" x1="74" y1="54" y2="54" stroke-width="2" style="stroke:#000000;" x2="127"/> <line id="19939" x1="144" y1="112" y2="91" stroke-width="2" style="stroke:#000000;" x2="144"/> <line id="35611" x1="127" y1="53" y2="75" stroke-width="2" style="stroke:#000000;" x2="127"/> <line id="35612" x1="143" y1="90" y2="91" stroke-width="2" style="stroke:#000000;" x2="198"/> <line id="35613" x1="199" y1="90" y2="112" stroke-width="2" style="stroke:#000000;" x2="198"/> <line id="35614" x1="143" y1="17" y2="17" stroke-width="2" style="stroke:#000000;" x2="199"/> <line id="35615" x1="144" y1="17" y2="38" stroke-width="2" style="stroke:#000000;" x2="143"/> <line id="35618" x1="0" y1="17" y2="17" stroke-width="2" style="stroke:#000000;" x2="58"/> <line id="35620" x1="22" y1="18" y2="18" stroke-width="2" style="stroke:#000000;" x2="22"/> <line id="35621" x1="56" y1="16" y2="37" stroke-width="2" style="stroke:#000000;" x2="57"/> <line id="35622" x1="1" y1="18" y2="37" stroke-width="2" style="stroke:#000000;" x2="0"/> <line id="35625" x1="2" y1="89" y2="89" stroke-width="2" style="stroke:#000000;" x2="56"/> <line id="35626" x1="1" y1="89" y2="108" stroke-width="2" style="stroke:#000000;" x2="0"/> <line id="35627" x1="56" y1="89" y2="108" stroke-width="2" style="stroke:#000000;" x2="55"/> <line id="28652" x1="22" y1="110" y2="110" stroke-width="2" style="stroke:#000000;" x2="22"/> <line id="28672" x1="321" y1="58" y2="79" stroke-width="2" style="stroke:#000000;" x2="320"/> <line id="40169" x1="72" y1="124" y2="125" stroke-width="2" style="stroke:#000000;" x2="126"/> <line id="40166" x1="199" y1="17" y2="38" stroke-width="2" style="stroke:#000000;" x2="198"/> <line id="40167" x1="74" y1="53" y2="74" stroke-width="2" style="stroke:#000000;" x2="73"/> <line id="40170" x1="71" y1="124" y2="145" stroke-width="2" style="stroke:#000000;" x2="72"/> <line id="40171" x1="126" y1="125" y2="145" stroke-width="2" style="stroke:#000000;" x2="127"/> <line id="36675" x1="215" y1="55" y2="54" stroke-width="2" style="stroke:#000000;" x2="271"/> <line id="36676" x1="217" y1="126" y2="125" stroke-width="2" style="stroke:#000000;" x2="268"/> <line id="36677" x1="216" y1="125" y2="144" stroke-width="2" style="stroke:#000000;" x2="217"/> <line id="36678" x1="269" y1="126" y2="143" stroke-width="2" style="stroke:#000000;" x2="269"/> <line id="36679" x1="216" y1="54" y2="74" stroke-width="2" style="stroke:#000000;" x2="217"/> <line id="36680" x1="271" y1="53" y2="74" stroke-width="2" style="stroke:#000000;" x2="270"/> </g> </svg> \"/>\n</StyledFill>\n",

а у тебя получается такой
"data": "<StyledFill name=\"\" group=\"\" brushColor=\"#000000\" objectName=\"\" id=\"1763113124411\" penColor=\"#000000\">\n <SvgFill penWidth=\"0.4\" objectName=\"\" patternWidth=\"20\" lineWidth=\"0.4\" svgFilePath=\"C:/Users/StamberskiyAA/AppData/Local/OISTerra/OISTerraManager/svg/1000 Лед.svg\" svgContent=\"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<svg id=\"svg1\" height=\"142px\" xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\" viewBox=\"0 0 282 142\" xmlns:svg=\"http://www.w3.org/2000/svg\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:cc=\"http://creativecommons.org/ns#\" width=\"282px\" xmlns:dc=\"http://purl.org/dc/elements/1.1/\" version=\"1.1\">\n <metadata> <rdf:RDF> <cc:Work> <dc:title>ИСИХОГИ_Литология</dc:title> </cc:Work> </rdf:RDF> </metadata> <defs id=\"defs1\"/>\n <g id=\"layer1\">\n <line id=\"19935\" x1=\"74\" y1=\"54\" x2=\"127\" y2=\"54\" stroke-width=\"2\" style=\"stroke:#000000;\"/><line id=\"19939\" x1=\"144\" y1=\"112\" x2=\"144\" y2=\"91\" stroke-width=\"2\" style=\"stroke:#000000;\"/><line id=\"35611\" x1=\"127\" y1=\"53\" x2=\"127\" y2=\"75\" stroke-width=\"2\" style=\"stroke:#000000;\"/><line id=\"35612\" x1=\"143\" y1=\"90\" x2=\"198\" y2=\"91\" stroke-width=\"2\" style=\"stroke:#000000;\"/><line id=\"35613\" x1=\"199\" y1=\"90\" x2=\"198\" y2=\"112\" stroke-width=\"2\" style=\"stroke:#000000;\"/><line id=\"35614\" x1=\"143\" y1=\"17\" x2=\"199\" y2=\"17\" stroke-width=\"2\" style=\"stroke:#000000;\"/><line id=\"35615\" x1=\"144\" y1=\"17\" x2=\"143\" y2=\"38\" stroke-width=\"2\" style=\"stroke:#000000;\"/><line id=\"35618\" x1=\"0\" y1=\"17\" x2=\"58\" y2=\"17\" stroke-width=\"2\" style=\"stroke:#000000;\"/><line id=\"35620\" x1=\"22\" y1=\"18\" x2=\"22\" y2=\"18\" stroke-width=\"2\" style=\"stroke:#000000;\"/><line id=\"35621\" x1=\"56\" y1=\"16\" x2=\"57\" y2=\"37\" stroke-width=\"2\" style=\"stroke:#000000;\"/><line id=\"35622\" x1=\"1\" y1=\"18\" x2=\"0\" y2=\"37\" stroke-width=\"2\" style=\"stroke:#000000;\"/><line id=\"35625\" x1=\"2\" y1=\"89\" x2=\"56\" y2=\"89\" stroke-width=\"2\" style=\"stroke:#000000;\"/><line id=\"35626\" x1=\"1\" y1=\"89\" x2=\"0\" y2=\"108\" stroke-width=\"2\" style=\"stroke:#000000;\"/><line id=\"35627\" x1=\"56\" y1=\"89\" x2=\"55\" y2=\"108\" stroke-width=\"2\" style=\"stroke:#000000;\"/><line id=\"28652\" x1=\"22\" y1=\"110\" x2=\"22\" y2=\"110\" stroke-width=\"2\" style=\"stroke:#000000;\"/><line id=\"28672\" x1=\"321\" y1=\"58\" x2=\"320\" y2=\"79\" stroke-width=\"2\" style=\"stroke:#000000;\"/><line id=\"40169\" x1=\"72\" y1=\"124\" x2=\"126\" y2=\"125\" stroke-width=\"2\" style=\"stroke:#000000;\"/><line id=\"40166\" x1=\"199\" y1=\"17\" x2=\"198\" y2=\"38\" stroke-width=\"2\" style=\"stroke:#000000;\"/><line id=\"40167\" x1=\"74\" y1=\"53\" x2=\"73\" y2=\"74\" stroke-width=\"2\" style=\"stroke:#000000;\"/><line id=\"40170\" x1=\"71\" y1=\"124\" x2=\"72\" y2=\"145\" stroke-width=\"2\" style=\"stroke:#000000;\"/><line id=\"40171\" x1=\"126\" y1=\"125\" x2=\"127\" y2=\"145\" stroke-width=\"2\" style=\"stroke:#000000;\"/><line id=\"36675\" x1=\"215\" y1=\"55\" x2=\"271\" y2=\"54\" stroke-width=\"2\" style=\"stroke:#000000;\"/><line id=\"36676\" x1=\"217\" y1=\"126\" x2=\"268\" y2=\"125\" stroke-width=\"2\" style=\"stroke:#000000;\"/><line id=\"36677\" x1=\"216\" y1=\"125\" x2=\"217\" y2=\"144\" stroke-width=\"2\" style=\"stroke:#000000;\"/><line id=\"36678\" x1=\"269\" y1=\"126\" x2=\"269\" y2=\"143\" stroke-width=\"2\" style=\"stroke:#000000;\"/><line id=\"36679\" x1=\"216\" y1=\"54\" x2=\"217\" y2=\"74\" stroke-width=\"2\" style=\"stroke:#000000;\"/><line id=\"36680\" x1=\"271\" y1=\"53\" x2=\"270\" y2=\"74\" stroke-width=\"2\" style=\"stroke:#000000;\"/></g>\n</svg>\n\"/>\n</StyledFill>\n",

и с таким неработает он непрогружается
а вот сам файл свг из него должен получится
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg" width="282px" height="142px" viewBox="0 0 282 142" version="1.1" id="svg1">
<defs id="defs1"/>
<g id="layer1">
<line id="19935" x1="74" y1="54" x2="127" y2="54" stroke-width="2" style="stroke:#000000;"/><line id="19939" x1="144" y1="112" x2="144" y2="91" stroke-width="2" style="stroke:#000000;"/><line id="35611" x1="127" y1="53" x2="127" y2="75" stroke-width="2" style="stroke:#000000;"/><line id="35612" x1="143" y1="90" x2="198" y2="91" stroke-width="2" style="stroke:#000000;"/><line id="35613" x1="199" y1="90" x2="198" y2="112" stroke-width="2" style="stroke:#000000;"/><line id="35614" x1="143" y1="17" x2="199" y2="17" stroke-width="2" style="stroke:#000000;"/><line id="35615" x1="144" y1="17" x2="143" y2="38" stroke-width="2" style="stroke:#000000;"/><line id="35618" x1="0" y1="17" x2="58" y2="17" stroke-width="2" style="stroke:#000000;"/><line id="35620" x1="22" y1="18" x2="22" y2="18" stroke-width="2" style="stroke:#000000;"/><line id="35621" x1="56" y1="16" x2="57" y2="37" stroke-width="2" style="stroke:#000000;"/><line id="35622" x1="1" y1="18" x2="0" y2="37" stroke-width="2" style="stroke:#000000;"/><line id="35625" x1="2" y1="89" x2="56" y2="89" stroke-width="2" style="stroke:#000000;"/><line id="35626" x1="1" y1="89" x2="0" y2="108" stroke-width="2" style="stroke:#000000;"/><line id="35627" x1="56" y1="89" x2="55" y2="108" stroke-width="2" style="stroke:#000000;"/><line id="28652" x1="22" y1="110" x2="22" y2="110" stroke-width="2" style="stroke:#000000;"/><line id="28672" x1="321" y1="58" x2="320" y2="79" stroke-width="2" style="stroke:#000000;"/><line id="40169" x1="72" y1="124" x2="126" y2="125" stroke-width="2" style="stroke:#000000;"/><line id="40166" x1="199" y1="17" x2="198" y2="38" stroke-width="2" style="stroke:#000000;"/><line id="40167" x1="74" y1="53" x2="73" y2="74" stroke-width="2" style="stroke:#000000;"/><line id="40170" x1="71" y1="124" x2="72" y2="145" stroke-width="2" style="stroke:#000000;"/><line id="40171" x1="126" y1="125" x2="127" y2="145" stroke-width="2" style="stroke:#000000;"/><line id="36675" x1="215" y1="55" x2="271" y2="54" stroke-width="2" style="stroke:#000000;"/><line id="36676" x1="217" y1="126" x2="268" y2="125" stroke-width="2" style="stroke:#000000;"/><line id="36677" x1="216" y1="125" x2="217" y2="144" stroke-width="2" style="stroke:#000000;"/><line id="36678" x1="269" y1="126" x2="269" y2="143" stroke-width="2" style="stroke:#000000;"/><line id="36679" x1="216" y1="54" x2="217" y2="74" stroke-width="2" style="stroke:#000000;"/><line id="36680" x1="271" y1="53" x2="270" y2="74" stroke-width="2" style="stroke:#000000;"/></g>
</svg>
<!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;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}

body {
margin: 0;
padding: 20px;
background-color: #f5f7fa;
color: #333;
}

.container {
max-width: 1200px;
margin: 0 auto;
background-color: white;
border-radius: 10px;
box-shadow: 0 0 20px rgba(0, 0, 0, 0.1);
padding: 25px;
}

h1 {
color: #2c3e50;
text-align: center;
margin-bottom: 30px;
border-bottom: 2px solid #3498db;
padding-bottom: 15px;
}

.section {
margin-bottom: 30px;
padding: 20px;
border-radius: 8px;
background-color: #f8f9fa;
}

.section-title {
font-size: 1.3rem;
color: #2c3e50;
margin-bottom: 15px;
display: flex;
align-items: center;
}

.form-group {
margin-bottom: 15px;
}

label {
display: block;
margin-bottom: 5px;
font-weight: 600;
color: #2c3e50;
}

input, textarea, select {
width: 100%;
padding: 10px;
border: 1px solid #ddd;
border-radius: 4px;
font-size: 16px;
}

textarea {
min-height: 100px;
resize: vertical;
}

button {
background-color: #3498db;
color: white;
border: none;
padding: 12px 20px;
border-radius: 4px;
cursor: pointer;
font-size: 16px;
font-weight: 600;
transition: background-color 0.3s;
}

button:hover {
background-color: #2980b9;
}

button.secondary {
background-color: #95a5a6;
}

button.secondary:hover {
background-color: #7f8c8d;
}

table {
width: 100%;
border-collapse: collapse;
margin-top: 10px;
}

th, td {
border: 1px solid #ddd;
padding: 12px;
text-align: left;
}

th {
background-color: #3498db;
color: white;
}

tr:nth-child(even) {
background-color: #f2f2f2;
}

.preview-container {
display: flex;
flex-wrap: wrap;
gap: 20px;
margin-top: 20px;
}

.preview-item {
border: 1px solid #ddd;
border-radius: 8px;
padding: 15px;
width: 200px;
text-align: center;
background-color: white;
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
}

.preview-svg {
height: 100px;
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 10px;
}

.preview-svg svg {
max-width: 100%;
max-height: 100%;
}

.preview-code {
font-weight: bold;
color: #2c3e50;
}

.preview-name {
color: #7f8c8d;
font-size: 0.9rem;
}

.hidden {
display: none;
}

.message {
padding: 15px;
border-radius: 4px;
margin: 15px 0;
}

.success {
background-color: #d4edda;
color: #155724;
border: 1px solid #c3e6cb;
}

.error {
background-color: #f8d7da;
color: #721c24;
border: 1px solid #f5c6cb;
}

.actions {
display: flex;
gap: 10px;
margin-top: 20px;
}

.file-input-container {
position: relative;
overflow: hidden;
display: inline-block;
width: 100%;
}

.file-input-container input[type=file] {
position: absolute;
left: 0;
top: 0;
opacity: 0;
width: 100%;
height: 100%;
cursor: pointer;
}

.file-input-button {
display: block;
padding: 10px;
background: #f8f9fa;
border: 2px dashed #3498db;
border-radius: 4px;
text-align: center;
color: #3498db;
font-weight: 600;
}

.file-list {
margin-top: 10px;
max-height: 150px;
overflow-y: auto;
border: 1px solid #ddd;
border-radius: 4px;
padding: 10px;
}

.file-item {
display: flex;
justify-content: space-between;
padding: 5px 0;
border-bottom: 1px solid #eee;
}

.file-item:last-child {
border-bottom: none;
}

.file-name {
flex-grow: 1;
}

.file-size {
color: #7f8c8d;
font-size: 0.8rem;
}

.data-table-container {
overflow-x: auto;
}

.help-text {
font-size: 0.9rem;
color: #7f8c8d;
margin-top: 5px;
}
</style>
</head>
<body>
<div class="container">
<h1>Генератор шаблонов литологии</h1>

<div class="section">
<h2 class="section-title">1. Загрузка SVG-файлов с текстурами</h2>
<div class="form-group">
<label>Выберите папку с SVG-файлами:</label>
<div class="file-input-container">
<div class="file-input-button">Выбрать папку с SVG-файлами</div>
<input type="file" id="svgFolderInput" webkitdirectory multiple>
</div>
<div class="help-text">SVG-файлы должны быть названы в формате "Код_Породы Название.svg", например: "1000 Лед.svg"</div>
</div>

<div class="form-group">
<label>Путь к SVG файлам в программе:</label>
<input type="text" id="svgFilePath" placeholder="C:/Users/User/AppData/Local/OISTerra/OISTerraManager/svg/" value="C:/Users/StamberskiyAA/AppData/Local/OISTerra/OISTerraManager/svg/">
<div class="help-text">Укажите путь, который будет использоваться в сгенерированном JSON файле</div>
</div>

<div id="fileList" class="file-list hidden">
<!-- Список загруженных файлов будет здесь -->
</div>
</div>

<div class="section">
<h2 class="section-title">2. Ввод данных о породах</h2>
<div class="form-group">
<label>Добавить данные о породах:</label>
<div class="help-text">Введите данные в формате: Код_Породы Название (каждая порода с новой строки)</div>
<textarea id="rockDataInput" placeholder="1300 Суглинок
1700 Илы
1800 Торф
1400 Супесь
2300 Аргиллит
2400 Алевролит"></textarea>
</div>

<div class="actions">
<button id="parseDataBtn">Обработать данные</button>
<button id="addRockBtn" class="secondary">Добавить породу вручную</button>
</div>

<div id="rockTableContainer" class="data-table-container hidden">
<h3>Список пород:</h3>
<table id="rockTable">
<thead>
<tr>
<th>Код породы</th>
<th>Наименование породы</th>
<th>SVG файл</th>
<th>Действия</th>
</tr>
</thead>
<tbody id="rockTableBody">
<!-- Данные о породах будут здесь -->
</tbody>
</table>
</div>
</div>

<div class="section">
<h2 class="section-title">3. Предварительный просмотр</h2>
<div id="previewContainer" class="preview-container">
<!-- Предварительный просмотр будет здесь -->
</div>
</div>

<div class="section">
<h2 class="section-title">4. Генерация шаблона</h2>
<div class="form-group">
<label>Название палитры:</label>
<input type="text" id="paletteName" value="тест_лито">
</div>

<div class="form-group">
<label>Название шаблона корреляции:</label>
<input type="text" id="templateName" value="Корреляционный шаблон">
</div>

<div class="actions">
<button id="generateBtn">Сгенерировать JSON шаблон</button>
<button id="downloadBtn" class="secondary hidden">Скачать шаблон</button>
</div>

<div id="messageArea"></div>

<div id="jsonOutput" class="hidden">
<h3>Сгенерированный JSON:</h3>
<pre id="jsonContent"></pre>
</div>
</div>
</div>

<script>
// Переменные для хранения данных
let svgFiles = {};
let rockData = [];

// Элементы DOM
const svgFolderInput = document.getElementById('svgFolderInput');
const svgFilePathInput = document.getElementById('svgFilePath');
const fileList = document.getElementById('fileList');
const rockDataInput = document.getElementById('rockDataInput');
const parseDataBtn = document.getElementById('parseDataBtn');
const addRockBtn = document.getElementById('addRockBtn');
const rockTableContainer = document.getElementById('rockTableContainer');
const rockTableBody = document.getElementById('rockTableBody');
const previewContainer = document.getElementById('previewContainer');
const paletteNameInput = document.getElementById('paletteName');
const templateNameInput = document.getElementById('templateName');
const generateBtn = document.getElementById('generateBtn');
const downloadBtn = document.getElementById('downloadBtn');
const messageArea = document.getElementById('messageArea');
const jsonOutput = document.getElementById('jsonOutput');
const jsonContent = document.getElementById('jsonContent');

// Функция для правильного форматирования SVG контента
function formatSvgContent(svgContent) {
// Убираем лишние пробелы и переносы строк, но сохраняем структуру
let formatted = svgContent
.replace(/\s+/g, ' ')
.trim();

// В рабочем примере XML декларация использует одинарные кавычки
formatted = formatted.replace(/<\?xml version="1.0" encoding="UTF-8"\?>/g, "<?xml version='1.0' encoding='UTF-8'?>");

// Экранируем только амперсанды
formatted = formatted.replace(/&(?!amp;|lt;|gt;|quot;|#)/g, '&');

return formatted;
}

// Обработка загрузки SVG файлов
svgFolderInput.addEventListener('change', function(e) {
const files = Array.from(e.target.files);
svgFiles = {};

// Очистка списка файлов
fileList.innerHTML = '';

// Фильтрация только SVG файлов
const svgFilesList = files.filter(file => file.name.toLowerCase().endsWith('.svg'));

if (svgFilesList.length === 0) {
fileList.innerHTML = '<div>SVG файлы не найдены</div>';
fileList.classList.remove('hidden');
return;
}

// Обработка каждого SVG файла
svgFilesList.forEach(file => {
const fileName = file.name;
const codeMatch = fileName.match(/^(\d+)/);

if (codeMatch) {
const code = codeMatch[1];

const reader = new FileReader();
reader.onload = function(e) {
const svgContent = e.target.result;
svgFiles[code] = {
name: fileName,
content: svgContent
};

// Добавление в список файлов
const fileItem = document.createElement('div');
fileItem.className = 'file-item';
fileItem.innerHTML = `
<div class="file-name">${fileName}</div>
<div class="file-size">${(file.size / 1024).toFixed(2)} KB</div>
`;
fileList.appendChild(fileItem);

// Обновление таблицы пород, если код уже есть
updateRockTableWithSvg(code);
};
reader.readAsText(file);
}
});

fileList.classList.remove('hidden');
showMessage(`Загружено ${svgFilesList.length} SVG файлов`, 'success');
});

// Обработка данных о породах
parseDataBtn.addEventListener('click', function() {
const inputText = rockDataInput.value.trim();
if (!inputText) {
showMessage('Введите данные о породах', 'error');
return;
}

const lines = inputText.split('\n');
rockData = [];

lines.forEach(line => {
const trimmedLine = line.trim();
if (trimmedLine) {
const parts = trimmedLine.split(/\s+/);
if (parts.length >= 2) {
const code = parts[0];
const name = parts.slice(1).join(' ');
rockData.push({
code: code,
name: name,
svgFile: svgFiles[code] ? svgFiles[code].name : null
});
}
}
});

updateRockTable();
updatePreview();
showMessage(`Обработано ${rockData.length} пород`, 'success');
});

// Добавление породы вручную
addRockBtn.addEventListener('click', function() {
const code = prompt('Введите код породы:');
if (!code) return;

const name = prompt('Введите название породы:');
if (!name) return;

rockData.push({
code: code,
name: name,
svgFile: svgFiles[code] ? svgFiles[code].name : null
});

updateRockTable();
updatePreview();
showMessage(`Добавлена порода: ${code} ${name}`, 'success');
});

// Обновление таблицы пород
function updateRockTable() {
rockTableBody.innerHTML = '';

if (rockData.length === 0) {
rockTableContainer.classList.add('hidden');
return;
}

rockData.forEach((rock, index) => {
const row = document.createElement('tr');
row.innerHTML = `
<td>${rock.code}</td>
<td>${rock.name}</td>
<td>${rock.svgFile || 'Не найден'}</td>
<td>
<button onclick="removeRock(${index})">Удалить</button>
</td>
`;
rockTableBody.appendChild(row);
});

rockTableContainer.classList.remove('hidden');
}

// Обновление таблицы при наличии SVG
function updateRockTableWithSvg(code) {
rockData.forEach(rock => {
if (rock.code === code) {
rock.svgFile = svgFiles[code].name;
}
});

updateRockTable();
updatePreview();
}

// Удаление породы
function removeRock(index) {
rockData.splice(index, 1);
updateRockTable();
updatePreview();
showMessage('Порода удалена', 'success');
}

// Обновление предварительного просмотра
function updatePreview() {
previewContainer.innerHTML = '';

if (rockData.length === 0) {
previewContainer.innerHTML = '<p>Нет данных для предварительного просмотра</p>';
return;
}

rockData.forEach(rock => {
const previewItem = document.createElement('div');
previewItem.className = 'preview-item';

let svgPreview = '<div>SVG не загружен</div>';
if (rock.svgFile && svgFiles[rock.code]) {
svgPreview = svgFiles[rock.code].content;
}

previewItem.innerHTML = `
<div class="preview-svg">${svgPreview}</div>
<div class="preview-code">${rock.code}</div>
<div class="preview-name">${rock.name}</div>
`;

previewContainer.appendChild(previewItem);
});
}

// Генерация JSON шаблона
generateBtn.addEventListener('click', function() {
if (rockData.length === 0) {
showMessage('Нет данных о породах для генерации шаблона', 'error');
return;
}

const paletteName = paletteNameInput.value || 'тест_лито';
const templateName = templateNameInput.value || 'Корреляционный шаблон';
const svgFilePath = svgFilePathInput.value || 'C:/Users/StamberskiyAA/AppData/Local/OISTerra/OISTerraManager/svg/';

// Создание элементов палитры
const paletteItems = rockData.map(rock => {
let svgContent = '';

if (rock.svgFile && svgFiles[rock.code]) {
// Правильное форматирование SVG для XML
svgContent = formatSvgContent(svgFiles[rock.code].content);
}

// Генерация случайного ID
const id = Date.now() + Math.floor(Math.random() * 1000);

// Полный путь к файлу SVG
const fullSvgFilePath = svgFilePath + rock.svgFile;

// Точный порядок атрибутов как в рабочем примере
return {
"color": "#ffffffff",
"data": `<StyledFill name="" group="" brushColor="#000000" objectName="" id="${id}" penColor="#000000">\n <SvgFill penWidth="0.4" objectName="" patternWidth="20" lineWidth="0.4" svgFilePath="${fullSvgFilePath}" svgContent="${svgContent}"/>\n</StyledFill>\n`,
"desc": rock.name,
"value": parseInt(rock.code)
};
});

// Создание основного JSON объекта с фиксированными ID как в рабочем примере
const templateJson = {
"Info": "OISTerra CorrTemplates",
"Palettes": [
{
"Items": paletteItems,
"id": Date.now(),
"name": paletteName,
"transp": true,
"type": 1
}
],
"ScoPaletteVersion": 1,
"corrTemplates": [
{
"Tracks": [
{
"allHeight": false,
"hTxtSet": {
"vis": true
},
"lineStyle": {
"fCol": "#ffc8ffff"
},
"trackId": 1763096947027,
"type": 0
},
{
"Logs": [
{
"logDataVers": 1,
"logId": 1763096947080,
"logParams": [
{
"contId": 1763096947014,
"contName": "РИГИС",
"id": 1763096947013,
"nm": "литология"
}
],
"logType": 3,
"trackId": 1763096947055
}
],
"allHeight": false,
"hTxtSet": {
"vis": false
},
"lineStyle": {
"fCol": "#ffc8ffff"
},
"trackId": 1763096947055,
"width": 50.69166666666666
}
],
"Version": {
"build": 3,
"fillData": 0,
"horizonView": 0,
"logData": 1,
"logRange": 0,
"plastBuild": 0,
"plastData": 0,
"stratBuild": 0,
"stratData": 0,
"stratWidth": 0,
"timeDepth": 0,
"trackWidth": 1,
"view": 7
},
"header": {
"textBlockList": {
"textBlocks": [
{
"blockId": 1763096947023,
"textItems": [
{
"blockId": 1763096947023,
"content": "[WellName]",
"font": {
"b": true
},
"itemId": 1763096947024,
"paramsHash": [
{
"id": -1,
"key": "[WellName]"
}
]
}
]
}
]
}
},
"id": Date.now() + 1000,
"name": templateName,
"plastList": {
"columnId": 1763096947025,
"isPlast": true,
"type": 0
}
}
],
"corrTemplatesVersion": 0
};

// Отображение JSON
jsonContent.textContent = JSON.stringify(templateJson, null, 2);
jsonOutput.classList.remove('hidden');
downloadBtn.classList.remove('hidden');

// Сохранение JSON для скачивания
window.generatedJson = templateJson;

showMessage('JSON шаблон успешно сгенерирован', 'success');
});

// Скачивание JSON файла
downloadBtn.addEventListener('click', function() {
if (!window.generatedJson) {
showMessage('Нет сгенерированного JSON для скачивания', 'error');
return;
}

const dataStr = JSON.stringify(window.generatedJson, null, 2);
const dataBlob = new Blob([dataStr], {type: 'application/json'});

const url = URL.createObjectURL(dataBlob);
const link = document.createElement('a');
link.href = url;
link.download = 'литология_шаблон.json';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
URL.revokeObjectURL(url);

showMessage('Файл успешно скачан', 'success');
});

// Функция для отображения сообщений
function showMessage(message, type) {
messageArea.innerHTML = `<div class="message ${type}">${message}</div>`;

// Автоматическое скрытие сообщения через 5 секунд
setTimeout(() => {
messageArea.innerHTML = '';
}, 5000);
}

// Инициализация при загрузке страницы
window.onload = function() {
// Добавляем пример данных для демонстрации
rockDataInput.value = `1300 Суглинок
1700 Илы
1800 Торф
1400 Супесь
2300 Аргиллит
2400 Алевролит`;
};
</script>
</body>
</html>

Добавлено (2025-11-14, 16:51)
---------------------------------------------
<!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;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}

body {
margin: 0;
padding: 20px;
background-color: #f5f7fa;
color: #333;
}

.container {
max-width: 1200px;
margin: 0 auto;
background-color: white;
border-radius: 10px;
box-shadow: 0 0 20px rgba(0, 0, 0, 0.1);
padding: 25px;
}

h1 {
color: #2c3e50;
text-align: center;
margin-bottom: 30px;
border-bottom: 2px solid #3498db;
padding-bottom: 15px;
}

.section {
margin-bottom: 30px;
padding: 20px;
border-radius: 8px;
background-color: #f8f9fa;
}

.section-title {
font-size: 1.3rem;
color: #2c3e50;
margin-bottom: 15px;
display: flex;
align-items: center;
}

.form-group {
margin-bottom: 15px;
}

label {
display: block;
margin-bottom: 5px;
font-weight: 600;
color: #2c3e50;
}

input, textarea, select {
width: 100%;
padding: 10px;
border: 1px solid #ddd;
border-radius: 4px;
font-size: 16px;
}

textarea {
min-height: 100px;
resize: vertical;
}

button {
background-color: #3498db;
color: white;
border: none;
padding: 12px 20px;
border-radius: 4px;
cursor: pointer;
font-size: 16px;
font-weight: 600;
transition: background-color 0.3s;
}

button:hover {
background-color: #2980b9;
}

button.secondary {
background-color: #95a5a6;
}

button.secondary:hover {
background-color: #7f8c8d;
}

table {
width: 100%;
border-collapse: collapse;
margin-top: 10px;
}

th, td {
border: 1px solid #ddd;
padding: 12px;
text-align: left;
}

th {
background-color: #3498db;
color: white;
}

tr:nth-child(even) {
background-color: #f2f2f2;
}

.preview-container {
display: flex;
flex-wrap: wrap;
gap: 20px;
margin-top: 20px;
}

.preview-item {
border: 1px solid #ddd;
border-radius: 8px;
padding: 15px;
width: 200px;
text-align: center;
background-color: white;
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
}

.preview-svg {
height: 100px;
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 10px;
}

.preview-svg svg {
max-width: 100%;
max-height: 100%;
}

.preview-code {
font-weight: bold;
color: #2c3e50;
}

.preview-name {
color: #7f8c8d;
font-size: 0.9rem;
}

.hidden {
display: none;
}

.message {
padding: 15px;
border-radius: 4px;
margin: 15px 0;
}

.success {
background-color: #d4edda;
color: #155724;
border: 1px solid #c3e6cb;
}

.error {
background-color: #f8d7da;
color: #721c24;
border: 1px solid #f5c6cb;
}

.actions {
display: flex;
gap: 10px;
margin-top: 20px;
}

.file-input-container {
position: relative;
overflow: hidden;
display: inline-block;
width: 100%;
}

.file-input-container input[type=file] {
position: absolute;
left: 0;
top: 0;
opacity: 0;
width: 100%;
height: 100%;
cursor: pointer;
}

.file-input-button {
display: block;
padding: 10px;
background: #f8f9fa;
border: 2px dashed #3498db;
border-radius: 4px;
text-align: center;
color: #3498db;
font-weight: 600;
}

.file-list {
margin-top: 10px;
max-height: 150px;
overflow-y: auto;
border: 1px solid #ddd;
border-radius: 4px;
padding: 10px;
}

.file-item {
display: flex;
justify-content: space-between;
padding: 5px 0;
border-bottom: 1px solid #eee;
}

.file-item:last-child {
border-bottom: none;
}

.file-name {
flex-grow: 1;
}

.file-size {
color: #7f8c8d;
font-size: 0.8rem;
}

.data-table-container {
overflow-x: auto;
}

.help-text {
font-size: 0.9rem;
color: #7f8c8d;
margin-top: 5px;
}
</style>
</head>
<body>
<div class="container">
<h1>Генератор шаблонов литологии</h1>

<div class="section">
<h2 class="section-title">1. Загрузка SVG-файлов с текстурами</h2>
<div class="form-group">
<label>Выберите папку с SVG-файлами:</label>
<div class="file-input-container">
<div class="file-input-button">Выбрать папку с SVG-файлами</div>
<input type="file" id="svgFolderInput" webkitdirectory multiple>
</div>
<div class="help-text">SVG-файлы должны быть названы в формате "Код_Породы Название.svg", например: "1000 Лед.svg"</div>
</div>

<div class="form-group">
<label>Путь к SVG файлам в программе:</label>
<input type="text" id="svgFilePath" placeholder="C:/Users/User/AppData/Local/OISTerra/OISTerraManager/svg/" value="C:/Users/StamberskiyAA/AppData/Local/OISTerra/OISTerraManager/svg/">
<div class="help-text">Укажите путь, который будет использоваться в сгенерированном JSON файле</div>
</div>

<div id="fileList" class="file-list hidden">
<!-- Список загруженных файлов будет здесь -->
</div>
</div>

<div class="section">
<h2 class="section-title">2. Ввод данных о породах</h2>
<div class="form-group">
<label>Добавить данные о породах:</label>
<div class="help-text">Введите данные в формате: Код_Породы Название (каждая порода с новой строки)</div>
<textarea id="rockDataInput" placeholder="1300 Суглинок
1700 Илы
1800 Торф
1400 Супесь
2300 Аргиллит
2400 Алевролит"></textarea>
</div>

<div class="actions">
<button id="parseDataBtn">Обработать данные</button>
<button id="addRockBtn" class="secondary">Добавить породу вручную</button>
</div>

<div id="rockTableContainer" class="data-table-container hidden">
<h3>Список пород:</h3>
<table id="rockTable">
<thead>
<tr>
<th>Код породы</th>
<th>Наименование породы</th>
<th>SVG файл</th>
<th>Действия</th>
</tr>
</thead>
<tbody id="rockTableBody">
<!-- Данные о породах будут здесь -->
</tbody>
</table>
</div>
</div>

<div class="section">
<h2 class="section-title">3. Предварительный просмотр</h2>
<div id="previewContainer" class="preview-container">
<!-- Предварительный просмотр будет здесь -->
</div>
</div>

<div class="section">
<h2 class="section-title">4. Генерация шаблона</h2>
<div class="form-group">
<label>Название палитры:</label>
<input type="text" id="paletteName" value="тест_лито">
</div>

<div class="form-group">
<label>Название шаблона корреляции:</label>
<input type="text" id="templateName" value="Корреляционный шаблон">
</div>

<div class="actions">
<button id="generateBtn">Сгенерировать JSON шаблон</button>
<button id="downloadBtn" class="secondary hidden">Скачать шаблон</button>
</div>

<div id="messageArea"></div>

<div id="jsonOutput" class="hidden">
<h3>Сгенерированный JSON:</h3>
<pre id="jsonContent"></pre>
</div>
</div>
</div>

<script>
// Переменные для хранения данных
let svgFiles = {};
let rockData = [];

// Элементы DOM
const svgFolderInput = document.getElementById('svgFolderInput');
const svgFilePathInput = document.getElementById('svgFilePath');
const fileList = document.getElementById('fileList');
const rockDataInput = document.getElementById('rockDataInput');
const parseDataBtn = document.getElementById('parseDataBtn');
const addRockBtn = document.getElementById('addRockBtn');
const rockTableContainer = document.getElementById('rockTableContainer');
const rockTableBody = document.getElementById('rockTableBody');
const previewContainer = document.getElementById('previewContainer');
const paletteNameInput = document.getElementById('paletteName');
const templateNameInput = document.getElementById('templateName');
const generateBtn = document.getElementById('generateBtn');
const downloadBtn = document.getElementById('downloadBtn');
const messageArea = document.getElementById('messageArea');
const jsonOutput = document.getElementById('jsonOutput');
const jsonContent = document.getElementById('jsonContent');

// Функция для правильного форматирования SVG контента
function formatSvgContent(svgContent) {
// Убираем лишние пробелы и переносы строк, но сохраняем структуру
let formatted = svgContent
.replace(/\s+/g, ' ')
.trim();

// В рабочем примере XML декларация использует одинарные кавычки
formatted = formatted.replace(/<\?xml version="1.0" encoding="UTF-8"\?>/g, "<?xml version='1.0' encoding='UTF-8'?>");

// Экранируем только амперсанды
formatted = formatted.replace(/&(?!amp;|lt;|gt;|quot;|#)/g, '&');

return formatted;
}

// Обработка загрузки SVG файлов
svgFolderInput.addEventListener('change', function(e) {
const files = Array.from(e.target.files);
svgFiles = {};

// Очистка списка файлов
fileList.innerHTML = '';

// Фильтрация только SVG файлов
const svgFilesList = files.filter(file => file.name.toLowerCase().endsWith('.svg'));

if (svgFilesList.length === 0) {
fileList.innerHTML = '<div>SVG файлы не найдены</div>';
fileList.classList.remove('hidden');
return;
}

// Обработка каждого SVG файла
svgFilesList.forEach(file => {
const fileName = file.name;
const codeMatch = fileName.match(/^(\d+)/);

if (codeMatch) {
const code = codeMatch[1];

const reader = new FileReader();
reader.onload = function(e) {
const svgContent = e.target.result;
svgFiles[code] = {
name: fileName,
content: svgContent
};

// Добавление в список файлов
const fileItem = document.createElement('div');
fileItem.className = 'file-item';
fileItem.innerHTML = `
<div class="file-name">${fileName}</div>
<div class="file-size">${(file.size / 1024).toFixed(2)} KB</div>
`;
fileList.appendChild(fileItem);

// Обновление таблицы пород, если код уже есть
updateRockTableWithSvg(code);
};
reader.readAsText(file);
}
});

fileList.classList.remove('hidden');
showMessage(`Загружено ${svgFilesList.length} SVG файлов`, 'success');
});

// Обработка данных о породах
parseDataBtn.addEventListener('click', function() {
const inputText = rockDataInput.value.trim();
if (!inputText) {
showMessage('Введите данные о породах', 'error');
return;
}

const lines = inputText.split('\n');
rockData = [];

lines.forEach(line => {
const trimmedLine = line.trim();
if (trimmedLine) {
const parts = trimmedLine.split(/\s+/);
if (parts.length >= 2) {
const code = parts[0];
const name = parts.slice(1).join(' ');
rockData.push({
code: code,
name: name,
svgFile: svgFiles[code] ? svgFiles[code].name : null
});
}
}
});

updateRockTable();
updatePreview();
showMessage(`Обработано ${rockData.length} пород`, 'success');
});

// Добавление породы вручную
addRockBtn.addEventListener('click', function() {
const code = prompt('Введите код породы:');
if (!code) return;

const name = prompt('Введите название породы:');
if (!name) return;

rockData.push({
code: code,
name: name,
svgFile: svgFiles[code] ? svgFiles[code].name : null
});

updateRockTable();
updatePreview();
showMessage(`Добавлена порода: ${code} ${name}`, 'success');
});

// Обновление таблицы пород
function updateRockTable() {
rockTableBody.innerHTML = '';

if (rockData.length === 0) {
rockTableContainer.classList.add('hidden');
return;
}

rockData.forEach((rock, index) => {
const row = document.createElement('tr');
row.innerHTML = `
<td>${rock.code}</td>
<td>${rock.name}</td>
<td>${rock.svgFile || 'Не найден'}</td>
<td>
<button onclick="removeRock(${index})">Удалить</button>
</td>
`;
rockTableBody.appendChild(row);
});

rockTableContainer.classList.remove('hidden');
}

// Обновление таблицы при наличии SVG
function updateRockTableWithSvg(code) {
rockData.forEach(rock => {
if (rock.code === code) {
rock.svgFile = svgFiles[code].name;
}
});

updateRockTable();
updatePreview();
}

// Удаление породы
function removeRock(index) {
rockData.splice(index, 1);
updateRockTable();
updatePreview();
showMessage('Порода удалена', 'success');
}

// Обновление предварительного просмотра
function updatePreview() {
previewContainer.innerHTML = '';

if (rockData.length === 0) {
previewContainer.innerHTML = '<p>Нет данных для предварительного просмотра</p>';
return;
}

rockData.forEach(rock => {
const previewItem = document.createElement('div');
previewItem.className = 'preview-item';

let svgPreview = '<div>SVG не загружен</div>';
if (rock.svgFile && svgFiles[rock.code]) {
svgPreview = svgFiles[rock.code].content;
}

previewItem.innerHTML = `
<div class="preview-svg">${svgPreview}</div>
<div class="preview-code">${rock.code}</div>
<div class="preview-name">${rock.name}</div>
`;

previewContainer.appendChild(previewItem);
});
}

// Генерация JSON шаблона
generateBtn.addEventListener('click', function() {
if (rockData.length === 0) {
showMessage('Нет данных о породах для генерации шаблона', 'error');
return;
}

const paletteName = paletteNameInput.value || 'тест_лито';
const templateName = templateNameInput.value || 'Корреляционный шаблон';
const svgFilePath = svgFilePathInput.value || 'C:/Users/StamberskiyAA/AppData/Local/OISTerra/OISTerraManager/svg/';

// Создание элементов палитры
const paletteItems = rockData.map(rock => {
let svgContent = '';

if (rock.svgFile && svgFiles[rock.code]) {
// Правильное форматирование SVG для XML
svgContent = formatSvgContent(svgFiles[rock.code].content);
}

// Генерация случайного ID
const id = Date.now() + Math.floor(Math.random() * 1000);

// Полный путь к файлу SVG
const fullSvgFilePath = svgFilePath + rock.svgFile;

// Точный порядок атрибутов как в рабочем примере
return {
"color": "#ffffffff",
"data": `<StyledFill name="" group="" brushColor="#000000" objectName="" id="${id}" penColor="#000000">\n <SvgFill penWidth="0.4" objectName="" patternWidth="20" lineWidth="0.4" svgFilePath="${fullSvgFilePath}" svgContent="${svgContent}"/>\n</StyledFill>\n`,
"desc": rock.name,
"value": parseInt(rock.code)
};
});

// Создание основного JSON объекта с фиксированными ID как в рабочем примере
const templateJson = {
"Info": "OISTerra CorrTemplates",
"Palettes": [
{
"Items": paletteItems,
"id": Date.now(),
"name": paletteName,
"transp": true,
"type": 1
}
],
"ScoPaletteVersion": 1,
"corrTemplates": [
{
"Tracks": [
{
"allHeight": false,
"hTxtSet": {
"vis": true
},
"lineStyle": {
"fCol": "#ffc8ffff"
},
"trackId": 1763096947027,
"type": 0
},
{
"Logs": [
{
"logDataVers": 1,
"logId": 1763096947080,
"logParams": [
{
"contId": 1763096947014,
"contName": "РИГИС",
"id": 1763096947013,
"nm": "литология"
}
],
"logType": 3,
"trackId": 1763096947055
}
],
"allHeight": false,
"hTxtSet": {
"vis": false
},
"lineStyle": {
"fCol": "#ffc8ffff"
},
"trackId": 1763096947055,
"width": 50.69166666666666
}
],
"Version": {
"build": 3,
"fillData": 0,
"horizonView": 0,
"logData": 1,
"logRange": 0,
"plastBuild": 0,
"plastData": 0,
"stratBuild": 0,
"stratData": 0,
"stratWidth": 0,
"timeDepth": 0,
"trackWidth": 1,
"view": 7
},
"header": {
"textBlockList": {
"textBlocks": [
{
"blockId": 1763096947023,
"textItems": [
{
"blockId": 1763096947023,
"content": "[WellName]",
"font": {
"b": true
},
"itemId": 1763096947024,
"paramsHash": [
{
"id": -1,
"key": "[WellName]"
}
]
}
]
}
]
}
},
"id": Date.now() + 1000,
"name": templateName,
"plastList": {
"columnId": 1763096947025,
"isPlast": true,
"type": 0
}
}
],
"corrTemplatesVersion": 0
};

// Отображение JSON
jsonContent.textContent = JSON.stringify(templateJson, null, 2);
jsonOutput.classList.remove('hidden');
downloadBtn.classList.remove('hidden');

// Сохранение JSON для скачивания
window.generatedJson = templateJson;

showMessage('JSON шаблон успешно сгенерирован', 'success');
});

// Скачивание JSON файла
downloadBtn.addEventListener('click', function() {
if (!window.generatedJson) {
showMessage('Нет сгенерированного JSON для скачивания', 'error');
return;
}

const dataStr = JSON.stringify(window.generatedJson, null, 2);
const dataBlob = new Blob([dataStr], {type: 'application/json'});

const url = URL.createObjectURL(dataBlob);
const link = document.createElement('a');
link.href = url;
link.download = 'литология_шаблон.json';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
URL.revokeObjectURL(url);

showMessage('Файл успешно скачан', 'success');
});

// Функция для отображения сообщений
function showMessage(message, type) {
messageArea.innerHTML = `<div class="message ${type}">${message}</div>`;

// Автоматическое скрытие сообщения через 5 секунд
setTimeout(() => {
messageArea.innerHTML = '';
}, 5000);
}

// Инициализация при загрузке страницы
window.onload = function() {
// Добавляем пример данных для демонстрации
rockDataInput.value = `1300 Суглинок
1700 Илы
1800 Торф
1400 Супесь
2300 Аргиллит
2400 Алевролит`;
};
</script>
</body>
</html>

Добавлено (2025-11-14, 16:59)
---------------------------------------------
<!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;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}

body {
margin: 0;
padding: 20px;
background-color: #f5f7fa;
color: #333;
}

.container {
max-width: 1200px;
margin: 0 auto;
background-color: white;
border-radius: 10px;
box-shadow: 0 0 20px rgba(0, 0, 0, 0.1);
padding: 25px;
}

h1 {
color: #2c3e50;
text-align: center;
margin-bottom: 30px;
border-bottom: 2px solid #3498db;
padding-bottom: 15px;
}

.section {
margin-bottom: 30px;
padding: 20px;
border-radius: 8px;
background-color: #f8f9fa;
}

.section-title {
font-size: 1.3rem;
color: #2c3e50;
margin-bottom: 15px;
display: flex;
align-items: center;
}

.form-group {
margin-bottom: 15px;
}

label {
display: block;
margin-bottom: 5px;
font-weight: 600;
color: #2c3e50;
}

input, textarea, select {
width: 100%;
padding: 10px;
border: 1px solid #ddd;
border-radius: 4px;
font-size: 16px;
}

textarea {
min-height: 100px;
resize: vertical;
}

button {
background-color: #3498db;
color: white;
border: none;
padding: 12px 20px;
border-radius: 4px;
cursor: pointer;
font-size: 16px;
font-weight: 600;
transition: background-color 0.3s;
}

button:hover {
background-color: #2980b9;
}

button.secondary {
background-color: #95a5a6;
}

button.secondary:hover {
background-color: #7f8c8d;
}

table {
width: 100%;
border-collapse: collapse;
margin-top: 10px;
}

th, td {
border: 1px solid #ddd;
padding: 12px;
text-align: left;
}

th {
background-color: #3498db;
color: white;
}

tr:nth-child(even) {
background-color: #f2f2f2;
}

.preview-container {
display: flex;
flex-wrap: wrap;
gap: 20px;
margin-top: 20px;
}

.preview-item {
border: 1px solid #ddd;
border-radius: 8px;
padding: 15px;
width: 200px;
text-align: center;
background-color: white;
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
}

.preview-svg {
height: 100px;
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 10px;
}

.preview-svg svg {
max-width: 100%;
max-height: 100%;
}

.preview-code {
font-weight: bold;
color: #2c3e50;
}

.preview-name {
color: #7f8c8d;
font-size: 0.9rem;
}

.hidden {
display: none;
}

.message {
padding: 15px;
border-radius: 4px;
margin: 15px 0;
}

.success {
background-color: #d4edda;
color: #155724;
border: 1px solid #c3e6cb;
}

.error {
background-color: #f8d7da;
color: #721c24;
border: 1px solid #f5c6cb;
}

.actions {
display: flex;
gap: 10px;
margin-top: 20px;
}

.file-input-container {
position: relative;
overflow: hidden;
display: inline-block;
width: 100%;
}

.file-input-container input[type=file] {
position: absolute;
left: 0;
top: 0;
opacity: 0;
width: 100%;
height: 100%;
cursor: pointer;
}

.file-input-button {
display: block;
padding: 10px;
background: #f8f9fa;
border: 2px dashed #3498db;
border-radius: 4px;
text-align: center;
color: #3498db;
font-weight: 600;
}

.file-list {
margin-top: 10px;
max-height: 150px;
overflow-y: auto;
border: 1px solid #ddd;
border-radius: 4px;
padding: 10px;
}

.file-item {
display: flex;
justify-content: space-between;
padding: 5px 0;
border-bottom: 1px solid #eee;
}

.file-item:last-child {
border-bottom: none;
}

.file-name {
flex-grow: 1;
}

.file-size {
color: #7f8c8d;
font-size: 0.8rem;
}

.data-table-container {
overflow-x: auto;
}

.help-text {
font-size: 0.9rem;
color: #7f8c8d;
margin-top: 5px;
}
</style>
</head>
<body>
<div class="container">
<h1>Генератор шаблонов литологии</h1>

<div class="section">
<h2 class="section-title">1. Загрузка SVG-файлов с текстурами</h2>
<div class="form-group">
<label>Выберите папку с SVG-файлами:</label>
<div class="file-input-container">
<div class="file-input-button">Выбрать папку с SVG-файлами</div>
<input type="file" id="svgFolderInput" webkitdirectory multiple>
</div>
<div class="help-text">SVG-файлы должны быть названы в формате "Код_Породы Название.svg", например: "1000 Лед.svg"</div>
</div>

<div class="form-group">
<label>Путь к SVG файлам в программе:</label>
<input type="text" id="svgFilePath" placeholder="C:/Users/User/AppData/Local/OISTerra/OISTerraManager/svg/" value="C:/Users/StamberskiyAA/AppData/Local/OISTerra/OISTerraManager/svg/">
<div class="help-text">Укажите путь, который будет использоваться в сгенерированном JSON файе</div>
</div>

<div id="fileList" class="file-list hidden">
<!-- Список загруженных файлов будет здесь -->
</div>
</div>

<div class="section">
<h2 class="section-title">2. Ввод данных о породах</h2>
<div class="form-group">
<label>Добавить данные о породах:</label>
<div class="help-text">Введите данные в формате: Код_Породы Название (каждая порода с новой строки)</div>
<textarea id="rockDataInput" placeholder="1300 Суглинок
1700 Илы
1800 Торф
1400 Супесь
2300 Аргиллит
2400 Алевролит"></textarea>
</div>

<div class="actions">
<button id="parseDataBtn">Обработать данные</button>
<button id="addRockBtn" class="secondary">Добавить породу вручную</button>
</div>

<div id="rockTableContainer" class="data-table-container hidden">
<h3>Список пород:</h3>
<table id="rockTable">
<thead>
<tr>
<th>Код породы</th>
<th>Наименование породы</th>
<th>SVG файл</th>
<th>Действия</th>
</tr>
</thead>
<tbody id="rockTableBody">
<!-- Данные о породах будут здесь -->
</tbody>
</table>
</div>
</div>

<div class="section">
<h2 class="section-title">3. Предварительный просмотр</h2>
<div id="previewContainer" class="preview-container">
<!-- Предварительный просмотр будет здесь -->
</div>
</div>

<div class="section">
<h2 class="section-title">4. Генерация шаблона</h2>
<div class="form-group">
<label>Название палитры:</label>
<input type="text" id="paletteName" value="тест_лито">
</div>

<div class="form-group">
<label>Название шаблона корреляции:</label>
<input type="text" id="templateName" value="Корреляционный шаблон">
</div>

<div class="actions">
<button id="generateBtn">Сгенерировать JSON шаблон</button>
<button id="downloadBtn" class="secondary hidden">Скачать шаблон</button>
</div>

<div id="messageArea"></div>

<div id="jsonOutput" class="hidden">
<h3>Сгенерированный JSON:</h3>
<pre id="jsonContent"></pre>
</div>
</div>
</div>

<script>
// Переменные для хранения данных
let svgFiles = {};
let rockData = [];

// Элементы DOM
const svgFolderInput = document.getElementById('svgFolderInput');
const svgFilePathInput = document.getElementById('svgFilePath');
const fileList = document.getElementById('fileList');
const rockDataInput = document.getElementById('rockDataInput');
const parseDataBtn = document.getElementById('parseDataBtn');
const addRockBtn = document.getElementById('addRockBtn');
const rockTableContainer = document.getElementById('rockTableContainer');
const rockTableBody = document.getElementById('rockTableBody');
const previewContainer = document.getElementById('previewContainer');
const paletteNameInput = document.getElementById('paletteName');
const templateNameInput = document.getElementById('templateName');
const generateBtn = document.getElementById('generateBtn');
const downloadBtn = document.getElementById('downloadBtn');
const messageArea = document.getElementById('messageArea');
const jsonOutput = document.getElementById('jsonOutput');
const jsonContent = document.getElementById('jsonContent');

// Функция для правильного форматирования SVG контента
function formatSvgContent(svgContent) {
// Убираем лишние пробелы и переносы строк
let formatted = svgContent.replace(/\s+/g, ' ').trim();

// В рабочем примере XML декларация использует одинарные кавычки
formatted = formatted.replace(/<\?xml version="1.0" encoding="UTF-8"\?>/g, "<?xml version='1.0' encoding='UTF-8'?>");

// Экранируем все специальные символы для XML как в рабочем примере
formatted = formatted
.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/"/g, '"')
.replace(/'/g, ''');

return formatted;
}

// Обработка загрузки SVG файлов
svgFolderInput.addEventListener('change', function(e) {
const files = Array.from(e.target.files);
svgFiles = {};

// Очистка списка файлов
fileList.innerHTML = '';

// Фильтрация только SVG файлов
const svgFilesList = files.filter(file => file.name.toLowerCase().endsWith('.svg'));

if (svgFilesList.length === 0) {
fileList.innerHTML = '<div>SVG файлы не найдены</div>';
fileList.classList.remove('hidden');
return;
}

// Обработка каждого SVG файла
svgFilesList.forEach(file => {
const fileName = file.name;
const codeMatch = fileName.match(/^(\d+)/);

if (codeMatch) {
const code = codeMatch[1];

const reader = new FileReader();
reader.onload = function(e) {
const svgContent = e.target.result;
svgFiles[code] = {
name: fileName,
content: svgContent
};

// Добавление в список файлов
const fileItem = document.createElement('div');
fileItem.className = 'file-item';
fileItem.innerHTML = `
<div class="file-name">${fileName}</div>
<div class="file-size">${(file.size / 1024).toFixed(2)} KB</div>
`;
fileList.appendChild(fileItem);

// Обновление таблицы пород, если код уже есть
updateRockTableWithSvg(code);
};
reader.readAsText(file);
}
});

fileList.classList.remove('hidden');
showMessage(`Загружено ${svgFilesList.length} SVG файлов`, 'success');
});

// Обработка данных о породах
parseDataBtn.addEventListener('click', function() {
const inputText = rockDataInput.value.trim();
if (!inputText) {
showMessage('Введите данные о породах', 'error');
return;
}

const lines = inputText.split('\n');
rockData = [];

lines.forEach(line => {
const trimmedLine = line.trim();
if (trimmedLine) {
const parts = trimmedLine.split(/\s+/);
if (parts.length >= 2) {
const code = parts[0];
const name = parts.slice(1).join(' ');
rockData.push({
code: code,
name: name,
svgFile: svgFiles[code] ? svgFiles[code].name : null
});
}
}
});

updateRockTable();
updatePreview();
showMessage(`Обработано ${rockData.length} пород`, 'success');
});

// Добавление породы вручную
addRockBtn.addEventListener('click', function() {
const code = prompt('Введите код породы:');
if (!code) return;

const name = prompt('Введите название породы:');
if (!name) return;

rockData.push({
code: code,
name: name,
svgFile: svgFiles[code] ? svgFiles[code].name : null
});

updateRockTable();
updatePreview();
showMessage(`Добавлена порода: ${code} ${name}`, 'success');
});

// Обновление таблицы пород
function updateRockTable() {
rockTableBody.innerHTML = '';

if (rockData.length === 0) {
rockTableContainer.classList.add('hidden');
return;
}

rockData.forEach((rock, index) => {
const row = document.createElement('tr');
row.innerHTML = `
<td>${rock.code}</td>
<td>${rock.name}</td>
<td>${rock.svgFile || 'Не найден'}</td>
<td>
<button onclick="removeRock(${index})">Удалить</button>
</td>
`;
rockTableBody.appendChild(row);
});

rockTableContainer.classList.remove('hidden');
}

// Обновление таблицы при наличии SVG
function updateRockTableWithSvg(code) {
rockData.forEach(rock => {
if (rock.code === code) {
rock.svgFile = svgFiles[code].name;
}
});

updateRockTable();
updatePreview();
}

// Удаление породы
function removeRock(index) {
rockData.splice(index, 1);
updateRockTable();
updatePreview();
showMessage('Порода удалена', 'success');
}

// Обновление предварительного просмотра
function updatePreview() {
previewContainer.innerHTML = '';

if (rockData.length === 0) {
previewContainer.innerHTML = '<p>Нет данных для предварительного просмотра</p>';
return;
}

rockData.forEach(rock => {
const previewItem = document.createElement('div');
previewItem.className = 'preview-item';

let svgPreview = '<div>SVG не загружен</div>';
if (rock.svgFile && svgFiles[rock.code]) {
svgPreview = svgFiles[rock.code].content;
}

previewItem.innerHTML = `
<div class="preview-svg">${svgPreview}</div>
<div class="preview-code">${rock.code}</div>
<div class="preview-name">${rock.name}</div>
`;

previewContainer.appendChild(previewItem);
});
}

// Генерация JSON шаблона
generateBtn.addEventListener('click', function() {
if (rockData.length === 0) {
showMessage('Нет данных о породах для генерации шаблона', 'error');
return;
}

const paletteName = paletteNameInput.value || 'тест_лито';
const templateName = templateNameInput.value || 'Корреляционный шаблон';
const svgFilePath = svgFilePathInput.value || 'C:/Users/StamberskiyAA/AppData/Local/OISTerra/OISTerraManager/svg/';

// Создание элементов палитры
const paletteItems = rockData.map(rock => {
let svgContent = '';

if (rock.svgFile && svgFiles[rock.code]) {
// Правильное форматирование SVG для XML
svgContent = formatSvgContent(svgFiles[rock.code].content);
}

// Генерация случайного ID
const id = Date.now() + Math.floor(Math.random() * 1000);

// Полный путь к файлу SVG
const fullSvgFilePath = svgFilePath + rock.svgFile;

// Точный порядок атрибутов как в рабочем примере
return {
"color": "#ffffffff",
"data": `<StyledFill name="" group="" brushColor="#000000" objectName="" id="${id}" penColor="#000000">\n <SvgFill penWidth="0.4" objectName="" patternWidth="20" lineWidth="0.4" svgFilePath="${fullSvgFilePath}" svgContent="${svgContent}"/>\n</StyledFill>\n`,
"desc": rock.name,
"value": parseInt(rock.code)
};
});

// Создание основного JSON объекта с фиксированными ID как в рабочем примере
const templateJson = {
"Info": "OISTerra CorrTemplates",
"Palettes": [
{
"Items": paletteItems,
"id": Date.now(),
"name": paletteName,
"transp": true,
"type": 1
}
],
"ScoPaletteVersion": 1,
"corrTemplates": [
{
"Tracks": [
{
"allHeight": false,
"hTxtSet": {
"vis": true
},
"lineStyle": {
"fCol": "#ffc8ffff"
},
"trackId": 1763096947027,
"type": 0
},
{
"Logs": [
{
"logDataVers": 1,
"logId": 1763096947080,
"logParams": [
{
"contId": 1763096947014,
"contName": "РИГИС",
"id": 1763096947013,
"nm": "литология"
}
],
"logType": 3,
"trackId": 1763096947055
}
],
"allHeight": false,
"hTxtSet": {
"vis": false
},
"lineStyle": {
"fCol": "#ffc8ffff"
},
"trackId": 1763096947055,
"width": 50.69166666666666
}
],
"Version": {
"build": 3,
"fillData": 0,
"horizonView": 0,
"logData": 1,
"logRange": 0,
"plastBuild": 0,
"plastData": 0,
"stratBuild": 0,
"stratData": 0,
"stratWidth": 0,
"timeDepth": 0,
"trackWidth": 1,
"view": 7
},
"header": {
"textBlockList": {
"textBlocks": [
{
"blockId": 1763096947023,
"textItems": [
{
"blockId": 1763096947023,
"content": "[WellName]",
"font": {
"b": true
},
"itemId": 1763096947024,
"paramsHash": [
{
"id": -1,
"key": "[WellName]"
}
]
}
]
}
]
}
},
"id": Date.now() + 1000,
"name": templateName,
"plastList": {
"columnId": 1763096947025,
"isPlast": true,
"type": 0
}
}
],
"corrTemplatesVersion": 0
};

// Отображение JSON
jsonContent.textContent = JSON.stringify(templateJson, null, 2);
jsonOutput.classList.remove('hidden');
downloadBtn.classList.remove('hidden');

// Сохранение JSON для скачивания
window.generatedJson = templateJson;

showMessage('JSON шаблон успешно сгенерирован', 'success');
});

// Скачивание JSON файла
downloadBtn.addEventListener('click', function() {
if (!window.generatedJson) {
showMessage('Нет сгенерированного JSON для скачивания', 'error');
return;
}

const dataStr = JSON.stringify(window.generatedJson, null, 2);
const dataBlob = new Blob([dataStr], {type: 'application/json'});

const url = URL.createObjectURL(dataBlob);
const link = document.createElement('a');
link.href = url;
link.download = 'литология_шаблон.json';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
URL.revokeObjectURL(url);

showMessage('Файл успешно скачан', 'success');
});

// Функция для отображения сообщений
function showMessage(message, type) {
messageArea.innerHTML = `<div class="message ${type}">${message}</div>`;

// Автоматическое скрытие сообщения через 5 секунд
setTimeout(() => {
messageArea.innerHTML = '';
}, 5000);
}

// Инициализация при загрузке страницы
window.onload = function() {
// Добавляем пример данных для демонстрации
rockDataInput.value = `1300 Суглинок
1700 Илы
1800 Торф
1400 Супесь
2300 Аргиллит
2400 Алевролит`;
};
</script>
</body>
</html>

Добавлено (2025-11-14, 17:07)
---------------------------------------------
<!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;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}

body {
margin: 0;
padding: 20px;
background-color: #f5f7fa;
color: #333;
}

.container {
max-width: 1200px;
margin: 0 auto;
background-color: white;
border-radius: 10px;
box-shadow: 0 0 20px rgba(0, 0, 0, 0.1);
padding: 25px;
}

h1 {
color: #2c3e50;
text-align: center;
margin-bottom: 30px;
border-bottom: 2px solid #3498db;
padding-bottom: 15px;
}

.section {
margin-bottom: 30px;
padding: 20px;
border-radius: 8px;
background-color: #f8f9fa;
}

.section-title {
font-size: 1.3rem;
color: #2c3e50;
margin-bottom: 15px;
display: flex;
align-items: center;
}

.form-group {
margin-bottom: 15px;
}

label {
display: block;
margin-bottom: 5px;
font-weight: 600;
color: #2c3e50;
}

input, textarea, select {
width: 100%;
padding: 10px;
border: 1px solid #ddd;
border-radius: 4px;
font-size: 16px;
}

textarea {
min-height: 100px;
resize: vertical;
}

button {
background-color: #3498db;
color: white;
border: none;
padding: 12px 20px;
border-radius: 4px;
cursor: pointer;
font-size: 16px;
font-weight: 600;
transition: background-color 0.3s;
}

button:hover {
background-color: #2980b9;
}

button.secondary {
background-color: #95a5a6;
}

button.secondary:hover {
background-color: #7f8c8d;
}

table {
width: 100%;
border-collapse: collapse;
margin-top: 10px;
}

th, td {
border: 1px solid #ddd;
padding: 12px;
text-align: left;
}

th {
background-color: #3498db;
color: white;
}

tr:nth-child(even) {
background-color: #f2f2f2;
}

.preview-container {
display: flex;
flex-wrap: wrap;
gap: 20px;
margin-top: 20px;
}

.preview-item {
border: 1px solid #ddd;
border-radius: 8px;
padding: 15px;
width: 200px;
text-align: center;
background-color: white;
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
}

.preview-svg {
height: 100px;
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 10px;
}

.preview-svg svg {
max-width: 100%;
max-height: 100%;
}

.preview-code {
font-weight: bold;
color: #2c3e50;
}

.preview-name {
color: #7f8c8d;
font-size: 0.9rem;
}

.hidden {
display: none;
}

.message {
padding: 15px;
border-radius: 4px;
margin: 15px 0;
}

.success {
background-color: #d4edda;
color: #155724;
border: 1px solid #c3e6cb;
}

.error {
background-color: #f8d7da;
color: #721c24;
border: 1px solid #f5c6cb;
}

.actions {
display: flex;
gap: 10px;
margin-top: 20px;
}

.file-input-container {
position: relative;
overflow: hidden;
display: inline-block;
width: 100%;
}

.file-input-container input[type=file] {
position: absolute;
left: 0;
top: 0;
opacity: 0;
width: 100%;
height: 100%;
cursor: pointer;
}

.file-input-button {
display: block;
padding: 10px;
background: #f8f9fa;
border: 2px dashed #3498db;
border-radius: 4px;
text-align: center;
color: #3498db;
font-weight: 600;
}

.file-list {
margin-top: 10px;
max-height: 150px;
overflow-y: auto;
border: 1px solid #ddd;
border-radius: 4px;
padding: 10px;
}

.file-item {
display: flex;
justify-content: space-between;
padding: 5px 0;
border-bottom: 1px solid #eee;
}

.file-item:last-child {
border-bottom: none;
}

.file-name {
flex-grow: 1;
}

.file-size {
color: #7f8c8d;
font-size: 0.8rem;
}

.data-table-container {
overflow-x: auto;
}

.help-text {
font-size: 0.9rem;
color: #7f8c8d;
margin-top: 5px;
}
</style>
</head>
<body>
<div class="container">
<h1>Генератор шаблонов литологии</h1>

<div class="section">
<h2 class="section-title">1. Загрузка SVG-файлов с текстурами</h2>
<div class="form-group">
<label>Выберите папку с SVG-файлами:</label>
<div class="file-input-container">
<div class="file-input-button">Выбрать папку с SVG-файлами</div>
<input type="file" id="svgFolderInput" webkitdirectory multiple>
</div>
<div class="help-text">SVG-файлы должны быть названы в формате "Код_Породы Название.svg", например: "1000 Лед.svg"</div>
</div>

<div class="form-group">
<label>Путь к SVG файлам в программе:</label>
<input type="text" id="svgFilePath" placeholder="C:/Users/User/AppData/Local/OISTerra/OISTerraManager/svg/" value="C:/Users/StamberskiyAA/AppData/Local/OISTerra/OISTerraManager/svg/">
<div class="help-text">Укажите путь, который будет использоваться в сгенерированном JSON файле</div>
</div>

<div id="fileList" class="file-list hidden">
<!-- Список загруженных файлов будет здесь -->
</div>
</div>

<div class="section">
<h2 class="section-title">2. Ввод данных о породах</h2>
<div class="form-group">
<label>Добавить данные о породах:</label>
<div class="help-text">Введите данные в формате: Код_Породы Название (каждая порода с новой строки)</div>
<textarea id="rockDataInput" placeholder="1300 Суглинок
1700 Илы
1800 Торф
1400 Супесь
2300 Аргиллит
2400 Алевролит"></textarea>
</div>

<div class="actions">
<button id="parseDataBtn">Обработать данные</button>
<button id="addRockBtn" class="secondary">Добавить породу вручную</button>
</div>

<div id="rockTableContainer" class="data-table-container hidden">
<h3>Список пород:</h3>
<table id="rockTable">
<thead>
<tr>
<th>Код породы</th>
<th>Наименование породы</th>
<th>SVG файл</th>
<th>Действия</th>
</tr>
</thead>
<tbody id="rockTableBody">
<!-- Данные о породах будут здесь -->
</tbody>
</table>
</div>
</div>

<div class="section">
<h2 class="section-title">3. Предварительный просмотр</h2>
<div id="previewContainer" class="preview-container">
<!-- Предварительный просмотр будет здесь -->
</div>
</div>

<div class="section">
<h2 class="section-title">4. Генерация шаблона</h2>
<div class="form-group">
<label>Название палитры:</label>
<input type="text" id="paletteName" value="тест_лито">
</div>

<div class="form-group">
<label>Название шаблона корреляции:</label>
<input type="text" id="templateName" value="Корреляционный шаблон">
</div>

<div class="actions">
<button id="generateBtn">Сгенерировать JSON шаблон</button>
<button id="downloadBtn" class="secondary hidden">Скачать шаблон</button>
</div>

<div id="messageArea"></div>

<div id="jsonOutput" class="hidden">
<h3>Сгенерированный JSON:</h3>
<pre id="jsonContent"></pre>
</div>
</div>
</div>

<script>
// Переменные для хранения данных
let svgFiles = {};
let rockData = [];

// Элементы DOM
const svgFolderInput = document.getElementById('svgFolderInput');
const svgFilePathInput = document.getElementById('svgFilePath');
const fileList = document.getElementById('fileList');
const rockDataInput = document.getElementById('rockDataInput');
const parseDataBtn = document.getElementById('parseDataBtn');
const addRockBtn = document.getElementById('addRockBtn');
const rockTableContainer = document.getElementById('rockTableContainer');
const rockTableBody = document.getElementById('rockTableBody');
const previewContainer = document.getElementById('previewContainer');
const paletteNameInput = document.getElementById('paletteName');
const templateNameInput = document.getElementById('templateName');
const generateBtn = document.getElementById('generateBtn');
const downloadBtn = document.getElementById('downloadBtn');
const messageArea = document.getElementById('messageArea');
const jsonOutput = document.getElementById('jsonOutput');
const jsonContent = document.getElementById('jsonContent');

// Функция для правильного экранирования SVG контента
function formatSvgContent(svgContent) {
// Убираем лишние пробелы и переносы строк
let formatted = svgContent.replace(/\s+/g, ' ').trim();

// Заменяем XML декларацию на версию с одинарными кавычками
formatted = formatted.replace(/<\?xml version="1.0" encoding="UTF-8"\?>/g, "<?xml version='1.0' encoding='UTF-8'?>");

// Правильно экранируем специальные символы для XML
formatted = formatted
.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/"/g, '"');

return formatted;
}

// Обработка загрузки SVG файлов
svgFolderInput.addEventListener('change', function(e) {
const files = Array.from(e.target.files);
svgFiles = {};

// Очистка списка файлов
fileList.innerHTML = '';

// Фильтрация только SVG файлов
const svgFilesList = files.filter(file => file.name.toLowerCase().endsWith('.svg'));

if (svgFilesList.length === 0) {
fileList.innerHTML = '<div>SVG файлы не найдены</div>';
fileList.classList.remove('hidden');
return;
}

// Обработка каждого SVG файла
svgFilesList.forEach(file => {
const fileName = file.name;
const codeMatch = fileName.match(/^(\d+)/);

if (codeMatch) {
const code = codeMatch[1];

const reader = new FileReader();
reader.onload = function(e) {
const svgContent = e.target.result;
svgFiles[code] = {
name: fileName,
content: svgContent
};

// Добавление в список файлов
const fileItem = document.createElement('div');
fileItem.className = 'file-item';
fileItem.innerHTML = `
<div class="file-name">${fileName}</div>
<div class="file-size">${(file.size / 1024).toFixed(2)} KB</div>
`;
fileList.appendChild(fileItem);

// Обновление таблицы пород, если код уже есть
updateRockTableWithSvg(code);
};
reader.readAsText(file);
}
});

fileList.classList.remove('hidden');
showMessage(`Загружено ${svgFilesList.length} SVG файлов`, 'success');
});

// Обработка данных о породах
parseDataBtn.addEventListener('click', function() {
const inputText = rockDataInput.value.trim();
if (!inputText) {
showMessage('Введите данные о породах', 'error');
return;
}

const lines = inputText.split('\n');
rockData = [];

lines.forEach(line => {
const trimmedLine = line.trim();
if (trimmedLine) {
const parts = trimmedLine.split(/\s+/);
if (parts.length >= 2) {
const code = parts[0];
const name = parts.slice(1).join(' ');
rockData.push({
code: code,
name: name,
svgFile: svgFiles[code] ? svgFiles[code].name : null
});
}
}
});

updateRockTable();
updatePreview();
showMessage(`Обработано ${rockData.length} пород`, 'success');
});

// Добавление породы вручную
addRockBtn.addEventListener('click', function() {
const code = prompt('Введите код породы:');
if (!code) return;

const name = prompt('Введите название породы:');
if (!name) return;

rockData.push({
code: code,
name: name,
svgFile: svgFiles[code] ? svgFiles[code].name : null
});

updateRockTable();
updatePreview();
showMessage(`Добавлена порода: ${code} ${name}`, 'success');
});

// Обновление таблицы пород
function updateRockTable() {
rockTableBody.innerHTML = '';

if (rockData.length === 0) {
rockTableContainer.classList.add('hidden');
return;
}

rockData.forEach((rock, index) => {
const row = document.createElement('tr');
row.innerHTML = `
<td>${rock.code}</td>
<td>${rock.name}</td>
<td>${rock.svgFile || 'Не найден'}</td>
<td>
<button onclick="removeRock(${index})">Удалить</button>
</td>
`;
rockTableBody.appendChild(row);
});

rockTableContainer.classList.remove('hidden');
}

// Обновление таблицы при наличии SVG
function updateRockTableWithSvg(code) {
rockData.forEach(rock => {
if (rock.code === code) {
rock.svgFile = svgFiles[code].name;
}
});

updateRockTable();
updatePreview();
}

// Удаление породы
function removeRock(index) {
rockData.splice(index, 1);
updateRockTable();
updatePreview();
showMessage('Порода удалена', 'success');
}

// Обновление предварительного просмотра
function updatePreview() {
previewContainer.innerHTML = '';

if (rockData.length === 0) {
previewContainer.innerHTML = '<p>Нет данных для предварительного просмотра</p>';
return;
}

rockData.forEach(rock => {
const previewItem = document.createElement('div');
previewItem.className = 'preview-item';

let svgPreview = '<div>SVG не загружен</div>';
if (rock.svgFile && svgFiles[rock.code]) {
svgPreview = svgFiles[rock.code].content;
}

previewItem.innerHTML = `
<div class="preview-svg">${svgPreview}</div>
<div class="preview-code">${rock.code}</div>
<div class="preview-name">${rock.name}</div>
`;

previewContainer.appendChild(previewItem);
});
}

// Генерация JSON шаблона
generateBtn.addEventListener('click', function() {
if (rockData.length === 0) {
showMessage('Нет данных о породах для генерации шаблона', 'error');
return;
}

const paletteName = paletteNameInput.value || 'тест_лито';
const templateName = templateNameInput.value || 'Корреляционный шаблон';
const svgFilePath = svgFilePathInput.value || 'C:/Users/StamberskiyAA/AppData/Local/OISTerra/OISTerraManager/svg/';

// Создание элементов палитры
const paletteItems = rockData.map(rock => {
let svgContent = '';

if (rock.svgFile && svgFiles[rock.code]) {
// Правильное форматирование SVG для XML
svgContent = formatSvgContent(svgFiles[rock.code].content);
}

// Генерация случайного ID
const id = Date.now() + Math.floor(Math.random() * 1000);

// Полный путь к файлу SVG
const fullSvgFilePath = svgFilePath + rock.svgFile;

// Точный порядок атрибутов как в рабочем примере
return {
"color": "#ffffffff",
"data": "<StyledFill name=\"\" group=\"\" brushColor=\"#000000\" objectName=\"\" id=\"" + id + "\" penColor=\"#000000\">\n <SvgFill penWidth=\"0.4\" objectName=\"\" patternWidth=\"20\" lineWidth=\"0.4\" svgFilePath=\"" + fullSvgFilePath + "\" svgContent=\"" + svgContent + "\"/>\n</StyledFill>\n",
"desc": rock.name,
"value": parseInt(rock.code)
};
});

// Создание основного JSON объекта с фиксированными ID как в рабочем примере
const templateJson = {
"Info": "OISTerra CorrTemplates",
"Palettes": [
{
"Items": paletteItems,
"id": Date.now(),
"name": paletteName,
"transp": true,
"type": 1
}
],
"ScoPaletteVersion": 1,
"corrTemplates": [
{
"Tracks": [
{
"allHeight": false,
"hTxtSet": {
"vis": true
},
"lineStyle": {
"fCol": "#ffc8ffff"
},
"trackId": 1763096947027,
"type": 0
},
{
"Logs": [
{
"logDataVers": 1,
"logId": 1763096947080,
"logParams": [
{
"contId": 1763096947014,
"contName": "РИГИС",
"id": 1763096947013,
"nm": "литология"
}
],
"logType": 3,
"trackId": 1763096947055
}
],
"allHeight": false,
"hTxtSet": {
"vis": false
},
"lineStyle": {
"fCol": "#ffc8ffff"
},
"trackId": 1763096947055,
"width": 50.69166666666666
}
],
"Version": {
"build": 3,
"fillData": 0,
"horizonView": 0,
"logData": 1,
"logRange": 0,
"plastBuild": 0,
"plastData": 0,
"stratBuild": 0,
"stratData": 0,
"stratWidth": 0,
"timeDepth": 0,
"trackWidth": 1,
"view": 7
},
"header": {
"textBlockList": {
"textBlocks": [
{
"blockId": 1763096947023,
"textItems": [
{
"blockId": 1763096947023,
"content": "[WellName]",
"font": {
"b": true
},
"itemId": 1763096947024,
"paramsHash": [
{
"id": -1,
"key": "[WellName]"
}
]
}
]
}
]
}
},
"id": Date.now() + 1000,
"name": templateName,
"plastList": {
"columnId": 1763096947025,
"isPlast": true,
"type": 0
}
}
],
"corrTemplatesVersion": 0
};

// Отображение JSON
jsonContent.textContent = JSON.stringify(templateJson, null, 2);
jsonOutput.classList.remove('hidden');
downloadBtn.classList.remove('hidden');

// Сохранение JSON для скачивания
window.generatedJson = templateJson;

showMessage('JSON шаблон успешно сгенерирован', 'success');
});

// Скачивание JSON файла
downloadBtn.addEventListener('click', function() {
if (!window.generatedJson) {
showMessage('Нет сгенерированного JSON для скачивания', 'error');
return;
}

const dataStr = JSON.stringify(window.generatedJson, null, 2);
const dataBlob = new Blob([dataStr], {type: 'application/json'});

const url = URL.createObjectURL(dataBlob);
const link = document.createElement('a');
link.href = url;
link.download = 'литология_шаблон.json';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
URL.revokeObjectURL(url);

showMessage('Файл успешно скачан', 'success');
});

// Функция для отображения сообщений
function showMessage(message, type) {
messageArea.innerHTML = '<div class="message ' + type + '">' + message + '</div>';

// Автоматическое скрытие сообщения через 5 секунд
setTimeout(function() {
messageArea.innerHTML = '';
}, 5000);
}

// Инициализация при загрузке страницы
window.onload = function() {
// Добавляем пример данных для демонстрации
rockDataInput.value = "1300 Суглинок\n1700 Илы\n1800 Торф\n1400 Супесь\n2300 Аргиллит\n2400 Алевролит";
};
</script>
</body>
</html>

  • Страница 24 из 24
  • «
  • 1
  • 2
  • 22
  • 23
  • 24
Поиск:
Новый ответ
Имя:
Текст сообщения: