Добавьте этот код для замены кириллических символов на греческие в стратиграфии:
В секцию CSS добавьте:
```css
.stratigraphy-column {
font-family: 'GeoindexA', 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}
```
В секцию JavaScript добавьте эту функцию (перед parseXMLData):
```javascript
// Функция для замены кириллических символов на греческие в стратиграфии
function convertStratigraphyText(text) {
// Таблица замены кириллицы → HTML-entities греческих символов
const cyrillicToGreekEntities = {
// Строчные
'а': 'α',
'б': 'β',
'в': 'μ',
'г': '∂',
'д': 'δ',
'е': 'ε',
'ж': 'ψ',
'з': 'σ',
'и': 'ι',
'й': 'υ',
'к': 'κ',
'л': 'λ',
'м': 'ϖ',
'н': 'η',
'о': 'ο',
'п': 'π',
'р': 'ρ',
'с': 'ς',
'т': 'τ',
'у': 'γ',
'ф': 'φ',
'х': 'χ',
'ц': 'ν',
'ч': 'č',
'ш': 'ω',
'щ': 'ç',
'ъ': 'ξ',
'ы': 'ζ',
'ь': 'ϑ',
'э': 'ℓ',
'ю': 'υ',
'я': 'Δ',
// Прописные
'А': 'Α',
'Б': 'Β',
'В': 'Μ',
'Г': 'Δ',
'Д': 'Δ',
'Е': 'Ε',
'Ж': 'Ψ',
'З': 'Σ',
'И': 'Ι',
'Й': 'Υ',
'К': 'Κ',
'Л': 'Λ',
'М': 'Π',
'Н': 'Η',
'О': 'Ο',
'П': 'Π',
'Р': 'Ρ',
'С': 'Σ',
'Т': 'Τ',
'У': 'Γ',
'Ф': 'Φ',
'Х': 'Χ',
'Ц': 'Ν',
'Ч': 'Č',
'Ш': 'Ω',
'Щ': 'Ç',
'Ъ': 'Ξ',
'Ы': 'Ζ',
'Ь': 'Θ',
'Э': 'ℒ',
'Ю': 'Υ',
'Я': 'Δ'
};
return text.split('').map(char => {
return cyrillicToGreekEntities[char] || char;
}).join('');
}
```
В функции parseXMLData найдите строку где устанавливается стратиграфия и обновите ее:
```javascript
// Получаем стратиграфию
const stratigraphyId = getSafeTextContent(interval, 'ID_STRATIGRAPHY_PODI');
let stratigraphy = 'Не указано';
if (stratigraphyId && classifierMap.has(stratigraphyId)) {
stratigraphy = convertStratigraphyText(classifierMap.get(stratigraphyId));
}
```
Это заменит кириллические символы на греческие во всех ячейках стратиграфии при загрузке данных.Добавлено (2025-10-02, 09:43)
---------------------------------------------
Внесем необходимые изменения:
1. Исправление функции formatDate:
```javascript
// Функция для форматирования даты
function formatDate(dateString) {
if (!dateString || dateString.trim() === '' || dateString === 'Не указано') return '';
try {
const date = new Date(dateString);
if (isNaN(date.getTime())) return '';
const day = date.getDate().toString().padStart(2, '0');
const month = (date.getMonth() + 1).toString().padStart(2, '0');
const year = date.getFullYear();
return `${day}.${month}.${year}`;
} catch (error) {
console.error('Ошибка форматирования даты:', error);
return '';
}
}
```
2. Обновление отображения карточек бурения с красным выделением:
```javascript
// В функции displayWellData замените блок "Бурение" на:
html += `
<div class="info-group">
<div class="info-group-title">Бурение</div>
<div class="info-group-grid">
<div class="info-card ${!xmlData.drillingStartDate || xmlData.drillingStartDate === '' ? 'no-data' : ''}">
<h3>Начало бурения</h3>
<p>${xmlData.drillingStartDate || 'Не указано'}</p>
</div>
<div class="info-card ${!xmlData.drillingEndDate || xmlData.drillingEndDate === '' ? 'no-data' : ''}">
<h3>Окончание бурения</h3>
<p>${xmlData.drillingEndDate || 'Не указано'}</p>
</div>
<div class="info-card ${!xmlData.drillingBrigade || xmlData.drillingBrigade === 'Не указано' ? 'no-data' : ''}">
<h3>Бригада бурения</h3>
<p>${formatLongText(xmlData.drillingBrigade || 'Не указано')}</p>
</div>
</div>
</div>
`;
```
3. Добавление стиля для карточек без данных:
```css
.info-card.no-data {
border-left: 4px solid #e74c3c;
background-color: #fdf2f2;
}
.info-card.no-data h3 {
color: #e74c3c;
}
.info-card.no-data p {
color: #c0392b;
font-weight: 500;
}
```
4. Перенос описания в раздел "Основная информация":
```javascript
// В функции displayWellData замените блок "Основная информация" полностью на:
html += `
<div class="section">
<h2>Основная информация</h2>
<div class="info-group">
<div class="info-group-title">Общие сведения</div>
<div class="info-group-grid">
<div class="info-card">
<h3>Объект работ</h3>
<p>${formatLongText(xmlData.object)}</p>
</div>
<div class="info-card">
<h3>Геологический участок</h3>
<p>${formatLongText(xmlData.area)}</p>
</div>
<div class="info-card">
<h3>Тип скважины</h3>
<p>${xmlData.wellType}</p>
</div>
</div>
</div>
${xmlData.wellDescription && xmlData.wellDescription !== 'Не указано' ? `
<div class="info-group">
<div class="info-group-title">Описание ТН</div>
<div class="info-card" style="grid-column: 1 / -1;">
<h3>Описание</h3>
<p>${formatLongText(xmlData.wellDescription, 100)}</p>
</div>
</div>
` : ''}
<div class="info-group">
<div class="info-group-title">Бурение</div>
<div class="info-group-grid">
<div class="info-card ${!xmlData.drillingStartDate || xmlData.drillingStartDate === '' ? 'no-data' : ''}">
<h3>Начало бурения</h3>
<p>${xmlData.drillingStartDate || 'Не указано'}</p>
</div>
<div class="info-card ${!xmlData.drillingEndDate || xmlData.drillingEndDate === '' ? 'no-data' : ''}">
<h3>Окончание бурения</h3>
<p>${xmlData.drillingEndDate || 'Не указано'}</p>
</div>
<div class="info-card ${!xmlData.drillingBrigade || xmlData.drillingBrigade === 'Не указано' ? 'no-data' : ''}">
<h3>Бригада бурения</h3>
<p>${formatLongText(xmlData.drillingBrigade || 'Не указано')}</p>
</div>
</div>
</div>
</div>
`;
```
5. Удалите старый блок описания из заголовка:
```javascript
// В функции displayWellData удалите или закомментируйте этот блок:
/*
const wellDescriptionElement = document.getElementById('wellDescription');
const wellDescriptionTextElement = document.getElementById('wellDescriptionText');
if (xmlData.wellDescription && xmlData.wellDescription !== 'Не указано') {
wellDescriptionElement.innerHTML = '<div class="well-description-label">Описание:</div>';
wellDescriptionTextElement.innerHTML = `<div class="well-description-text">${xmlData.wellDescription}</div>`;
wellDescriptionTextElement.style.display = 'block';
} else {
wellDescriptionElement.innerHTML = '<div class="well-description-label">Описание отсутствует</div>';
wellDescriptionTextElement.style.display = 'none';
}
*/
```
Эти изменения:
· Исправят отображение дат (пусто вместо "Неверный формат")
· Добавят красное выделение для карточек без данных
· Перенесут описание в раздел "Основная информация" под названием "Описание ТН"
· Сделают интерфейс более информативным и аккуратным
Добавлено (2025-10-02, 10:29)
---------------------------------------------
Добавлю вкладку "Документирование по ГИС". Вот необходимые изменения:
1. В функции parseXMLData добавьте обработку ГИС интервалов:
```javascript
// Извлекаем интервалы документирования
const primaryIntervals = [];
const finalIntervals = [];
const gisIntervals = []; // Добавляем для ГИС
// Обрабатываем интервалы документирования
const intervalNodes = xmlDoc.getElementsByTagName('MR_DBA.PO_DOCUM_INT_PODI');
for (let i = 0; i < intervalNodes.length; i++) {
const interval = intervalNodes[i];
const from = parseFloat(getSafeTextContent(interval, 'PO_DOCUM_FROM_PODI') || '0');
const to = parseFloat(getSafeTextContent(interval, 'PO_DOCUM_TO_PODI') || '0');
const thickness = parseFloat(getSafeTextContent(interval, 'THICKNESS_PODI') || '0');
const description = getSafeTextContent(interval, 'DESCRIPTION_PODI');
const docId = getSafeTextContent(interval, 'ID_PO_DOCUM_PODI');
const numberPP = parseInt(getSafeTextContent(interval, 'NUMBER_PP_PODI') || '0');
// Определяем тип документирования
let documentationType = 'Не определено';
if (docId && docId !== 'Не указано' && docTypeMap.has(docId)) {
documentationType = docTypeMap.get(docId);
}
// Получаем литологию
const lithologyId = getSafeTextContent(interval, 'ID_LITHOLOGY_PODI');
let lithology = 'Не указано';
if (lithologyId && classifierMap.has(lithologyId)) {
lithology = classifierMap.get(lithologyId);
}
// Получаем стратиграфию
const stratigraphyId = getSafeTextContent(interval, 'ID_STRATIGRAPHY_PODI');
let stratigraphy = 'Не указано';
if (stratigraphyId && classifierMap.has(stratigraphyId)) {
stratigraphy = convertStratigraphyText(classifierMap.get(stratigraphyId));
}
const intervalData = {
numberPP,
from,
to,
thickness,
stratigraphy,
lithology,
description
};
// Распределяем интервалы по типам документирования
if ((documentationType.includes('Первич') || documentationType.includes('ПЕРВИЧ') || documentationType === '1') &&
!documentationType.includes('ГИС') && !documentationType.includes('геофизик')) {
primaryIntervals.push(intervalData);
} else if ((documentationType.includes('Итогов') || documentationType.includes('ИТОГОВ') || documentationType === '2') &&
!documentationType.includes('ГИС') && !documentationType.includes('геофизик')) {
finalIntervals.push(intervalData);
} else if (documentationType.includes('ГИС') || documentationType.includes('геофизик')) {
// Добавляем в ГИС интервалы
gisIntervals.push(intervalData);
} else {
// Если тип не определен, добавляем в оба списка для файлов типа "all"
if (fileType === 'all' && !documentationType.includes('ГИС') && !documentationType.includes('геофизик')) {
primaryIntervals.push(intervalData);
finalIntervals.push(intervalData);
} else if (fileType === 'primary' && !documentationType.includes('ГИС') && !documentationType.includes('геофизик')) {
primaryIntervals.push(intervalData);
} else if (fileType === 'final' && !documentationType.includes('ГИС') && !documentationType.includes('геофизик')) {
finalIntervals.push(intervalData);
}
}
}
// СОРТИРУЕМ интервалы по порядковому номеру
primaryIntervals.sort((a, b) => a.numberPP - b.numberPP);
finalIntervals.sort((a, b) => a.numberPP - b.numberPP);
gisIntervals.sort((a, b) => a.numberPP - b.numberPP); // Сортируем ГИС интервалы
```
2. В том же месте найдите информацию о документировании и добавьте для ГИС:
```javascript
// Данные документирования
let primaryDocInfo = null;
let finalDocInfo = null;
let gisDocInfo = null; // Добавляем для ГИС
const docNodes = xmlDoc.getElementsByTagName('MR_DBA.PO_DOCUM_PODC');
for (let i = 0; i < docNodes.length; i++) {
const doc = docNodes[i];
const docType = getSafeTextContent(doc, 'ID_TYPE_DOCUM_PODC');
const startDate = formatDate(getSafeTextContent(doc, 'DATE_BEG_DOCUM_PODC'));
const endDate = formatDate(getSafeTextContent(doc, 'DATE_END_DOCUM_PODC'));
const depth = formatNumber(getSafeTextContent(doc, 'DEPTH_FACT_PODC'));
const authorId = getSafeTextContent(doc, 'AUTHOR_PODC');
let authorName = 'Не указано';
if (authorId && authorId !== 'Не указано' && employeeMap.has(authorId)) {
authorName = employeeMap.get(authorId);
} else if (authorId && authorId !== 'Не указано') {
authorName = `Код: ${authorId}`;
}
const docInfo = {
startDate,
endDate,
depth,
author: authorName
};
if (docType.includes('Первич') || docType.includes('ПЕРВИЧ') || docType === '1') {
primaryDocInfo = docInfo;
} else if (docType.includes('Итогов') || docType.includes('ИТОГОВ') || docType === '2') {
finalDocInfo = docInfo;
} else if (docType.includes('ГИС') || docType.includes('геофизик')) {
gisDocInfo = docInfo; // Сохраняем информацию о ГИС документировании
}
}
```
3. Сохраните данные ГИС в xmlData:
```javascript
// Сохраняем извлеченные данные
xmlData = {
wellName,
object,
area,
wellType,
wellNumber: wellName,
lineNumber,
wellDescription,
drillingStartDate,
drillingEndDate,
drillingBrigade,
primaryDocInfo,
finalDocInfo,
gisDocInfo, // Добавляем информацию о ГИС
primaryDocumentation: primaryIntervals,
finalDocumentation: finalIntervals,
gisDocumentation: gisIntervals, // Добавляем ГИС интервалы
assays
};
```
4. В функции displayWellData обновите логику вкладок:
```javascript
// Создаем вкладки для документации и опробования
const hasPrimary = xmlData.primaryDocumentation && xmlData.primaryDocumentation.length > 0;
const hasFinal = xmlData.finalDocumentation && xmlData.finalDocumentation.length > 0;
const hasGis = xmlData.gisDocumentation && xmlData.gisDocumentation.length > 0; // Добавляем проверку ГИС
const hasAssays = xmlData.assays && xmlData.assays.length > 0;
if (hasPrimary || hasFinal || hasGis || hasAssays) {
html += `<div class="section">`;
html += `<h2>Документирование и опробование</h2>`;
// Создаем вкладки
html += `<div class="tabs">`;
if (hasPrimary) {
html += `<div class="tab active" data-tab="primary">Первичное документирование</div>`;
}
if (hasFinal) {
html += `<div class="tab ${!hasPrimary ? 'active' : ''}" data-tab="final">Итоговое документирование</div>`;
}
if (hasGis) {
html += `<div class="tab ${!hasPrimary && !hasFinal ? 'active' : ''}" data-tab="gis">Документирование по ГИС</div>`;
}
if (hasAssays) {
html += `<div class="tab ${!hasPrimary && !hasFinal && !hasGis ? 'active' : ''}" data-tab="assays">Опробование</div>`;
}
html += `</div>`;
// ... существующий код для primary и final вкладок ...
// Содержимое вкладки "Документирование по ГИС"
if (hasGis) {
html += `<div id="gisTab" class="tab-content ${!hasPrimary && !hasFinal && hasGis ? 'active' : ''}">`;
// Информация о ГИС документировании в компактном виде
if (xmlData.gisDocInfo) {
html += `
<div class="doc-info-list">
<div class="doc-info-item">
<span class="doc-info-label">Начало документирования:</span>
<span class="doc-info-value">${xmlData.gisDocInfo.startDate}</span>
</div>
<div class="doc-info-item">
<span class="doc-info-label">Окончание документирования:</span>
<span class="doc-info-value">${xmlData.gisDocInfo.endDate}</span>
</div>
<div class="doc-info-item">
<span class="doc-info-label">Фактическая глубина:</span>
<span class="doc-info-value">${xmlData.gisDocInfo.depth} м</span>
</div>
<div class="doc-info-item">
<span class="doc-info-label">Документатор:</span>
<span class="doc-info-value">${formatLongText(xmlData.gisDocInfo.author)}</span>
</div>
</div>
`;
}
html += `
<div class="table-wrapper">
<div class="table-header">
<table class="interval-table">
<thead>
<tr>
<th style="width: 50px;">ПП</th>
<th style="width: 80px;">От (м)</th>
<th style="width: 80px;">До (м)</th>
<th style="width: 100px;">Мощность (м)</th>
<th style="width: 150px;">Стратиграфия</th>
<th style="width: 150px;">Литология</th>
<th>Описание</th>
</tr>
</thead>
</table>
</div>
<div class="table-container">
<table class="interval-table">
<tbody>
`;
xmlData.gisDocumentation.forEach(interval => {
html += `
<tr>
<td style="width: 50px;">${interval.numberPP}</td>
<td style="width: 80px;">${formatNumber(interval.from)}</td>
<td style="width: 80px;">${formatNumber(interval.to)}</td>
<td style="width: 100px;">${formatNumber(interval.thickness)}</td>
<td style="width: 150px;" class="stratigraphy-column">${interval.stratigraphy}</td>
<td style="width: 150px;">${interval.lithology}</td>
<td><div class="description-text">${interval.description}</div></td>
</tr>
`;
});
html += `
</tbody>
</table>
</div>
</div>
</div>`;
}
// ... существующий код для assays вкладки ...
}
```
Теперь будет отображаться вкладка "Документирование по ГИС" после итогового документирования, если в данных есть интервалы с типом документирования, содержащим "ГИС" или "геофизик".
Добавлено (2025-10-02, 10:41)
---------------------------------------------
// Содержимое вкладки "Документирование по ГИС"
if (hasGis) {
html += `<div id="gisTab" class="tab-content ${!hasPrimary && !hasFinal && hasGis ? 'active' : ''}">`;
// Информация о ГИС документировании в компактном виде
if (xmlData.gisDocInfo && (
xmlData.gisDocInfo.startDate ||
xmlData.gisDocInfo.endDate ||
xmlData.gisDocInfo.depth ||
xmlData.gisDocInfo.author
)) {
html += `
<div class="doc-info-list">
${xmlData.gisDocInfo.startDate ? `
<div class="doc-info-item">
<span class="doc-info-label">Начало документирования:</span>
<span class="doc-info-value">${xmlData.gisDocInfo.startDate}</span>
</div>
` : ''}
${xmlData.gisDocInfo.endDate ? `
<div class="doc-info-item">
<span class="doc-info-label">Окончание документирования:</span>
<span class="doc-info-value">${xmlData.gisDocInfo.endDate}</span>
</div>
` : ''}
${xmlData.gisDocInfo.depth && xmlData.gisDocInfo.depth !== 'Не указано' ? `
<div class="doc-info-item">
<span class="doc-info-label">Фактическая глубина:</span>
<span class="doc-info-value">${xmlData.gisDocInfo.depth} м</span>
</div>
` : ''}
${xmlData.gisDocInfo.author && xmlData.gisDocInfo.author !== 'Не указано' ? `
<div class="doc-info-item">
<span class="doc-info-label">Документатор:</span>
<span class="doc-info-value">${formatLongText(xmlData.gisDocInfo.author)}</span>
</div>
` : ''}
</div>
`;
}
html += `
<div class="table-wrapper">
<div class="table-header">
<table class="interval-table">
<thead>
<tr>
<th style="width: 50px;">ПП</th>
<th style="width: 80px;">От (м)</th>
<th style="width: 80px;">До (м)</th>
<th style="width: 100px;">Мощность (м)</th>
<th style="width: 150px;">Стратиграфия</th>
<th style="width: 150px;">Литология</th>
<th>Описание</th>
</tr>
</thead>
</table>
</div>
<div class="table-container">
<table class="interval-table">
<tbody>
`;
xmlData.gisDocumentation.forEach(interval => {
html += `
<tr>
<td style="width: 50px;">${interval.numberPP}</td>
<td style="width: 80px;">${formatNumber(interval.from)}</td>
<td style="width: 80px;">${formatNumber(interval.to)}</td>
<td style="width: 100px;">${formatNumber(interval.thickness)}</td>
<td style="width: 150px;" class="stratigraphy-column">${interval.stratigraphy}</td>
<td style="width: 150px;">${interval.lithology}</td>
<td><div class="description-text">${interval.description}</div></td>
</tr>
`;
});
html += `
</tbody>
</table>
</div>
</div>
</div>`;
}
Добавлено (2025-10-02, 10:43)
---------------------------------------------
// Содержимое вкладки "Документирование по ГИС"
if (hasGis) {
html += `<div id="gisTab" class="tab-content ${!hasPrimary && !hasFinal && hasGis ? 'active' : ''}">`;
// Информация о ГИС документировании в компактном виде
if (xmlData.gisDocInfo) {
let hasDocInfo = false;
let docInfoHtml = '';
if (xmlData.gisDocInfo.startDate && xmlData.gisDocInfo.startDate !== '') {
docInfoHtml += `
<div class="doc-info-item">
<span class="doc-info-label">Начало документирования:</span>
<span class="doc-info-value">${xmlData.gisDocInfo.startDate}</span>
</div>
`;
hasDocInfo = true;
}
if (xmlData.gisDocInfo.endDate && xmlData.gisDocInfo.endDate !== '') {
docInfoHtml += `
<div class="doc-info-item">
<span class="doc-info-label">Окончание документирования:</span>
<span class="doc-info-value">${xmlData.gisDocInfo.endDate}</span>
</div>
`;
hasDocInfo = true;
}
if (xmlData.gisDocInfo.depth && xmlData.gisDocInfo.depth !== 'Не указано') {
docInfoHtml += `
<div class="doc-info-item">
<span class="doc-info-label">Фактическая глубина:</span>
<span class="doc-info-value">${xmlData.gisDocInfo.depth} м</span>
</div>
`;
hasDocInfo = true;
}
if (xmlData.gisDocInfo.author && xmlData.gisDocInfo.author !== 'Не указано') {
docInfoHtml += `
<div class="doc-info-item">
<span class="doc-info-label">Документатор:</span>
<span class="doc-info-value">${formatLongText(xmlData.gisDocInfo.author)}</span>
</div>
`;
hasDocInfo = true;
}
if (hasDocInfo) {
html += `<div class="doc-info-list">${docInfoHtml}</div>`;
}
}
html += `
<div class="table-wrapper">
<div class="table-header">
<table class="interval-table">
<thead>
<tr>
<th style="width: 50px;">ПП</th>
<th style="width: 80px;">От (м)</th>
<th style="width: 80px;">До (м)</th>
<th style="width: 100px;">Мощность (м)</th>
<th style="width: 150px;">Стратиграфия</th>
<th style="width: 150px;">Литология</th>
<th>Описание</th>
</tr>
</thead>
</table>
</div>
<div class="table-container">
<table class="interval-table">
<tbody>
`;
xmlData.gisDocumentation.forEach(interval => {
html += `
<tr>
<td style="width: 50px;">${interval.numberPP}</td>
<td style="width: 80px;">${formatNumber(interval.from)}</td>
<td style="width: 80px;">${formatNumber(interval.to)}</td>
<td style="width: 100px;">${formatNumber(interval.thickness)}</td>
<td style="width: 150px;" class="stratigraphy-column">${interval.stratigraphy}</td>
<td style="width: 150px;">${interval.lithology}</td>
<td><div class="description-text">${interval.description}</div></td>
</tr>
`;
});
html += `
</tbody>
</table>
</div>
</div>
</div>
`;
}
Добавлено (2025-10-02, 10:51)
---------------------------------------------
// Создаем вкладки для документации и опробования
const hasPrimary = xmlData.primaryDocumentation && xmlData.primaryDocumentation.length > 0;
const hasFinal = xmlData.finalDocumentation && xmlData.finalDocumentation.length > 0;
const hasGis = xmlData.gisDocumentation && xmlData.gisDocumentation.length > 0;
const hasAssays = xmlData.assays && xmlData.assays.length > 0;
if (hasPrimary || hasFinal || hasGis || hasAssays) {
html += `<div class="section">`;
html += `<h2>Документирование и опробование</h2>`;
// Создаем вкладки
html += `<div class="tabs">`;
if (hasPrimary) {
html += `<div class="tab active" data-tab="primary">Первичное документирование</div>`;
}
if (hasFinal) {
html += `<div class="tab ${!hasPrimary ? 'active' : ''}" data-tab="final">Итоговое документирование</div>`;
}
if (hasGis) {
html += `<div class="tab ${!hasPrimary && !hasFinal ? 'active' : ''}" data-tab="gis">Документирование по ГИС</div>`;
}
if (hasAssays) {
html += `<div class="tab ${!hasPrimary && !hasFinal && !hasGis ? 'active' : ''}" data-tab="assays">Опробование</div>`;
}
html += `</div>`;
// Содержимое вкладки "Первичное документирование"
if (hasPrimary) {
html += `<div id="primaryTab" class="tab-content ${hasPrimary ? 'active' : ''}">`;
// Информация о первичном документировании в компактном виде
if (xmlData.primaryDocInfo) {
html += `
<div class="doc-info-list">
<div class="doc-info-item">
<span class="doc-info-label">Начало документирования:</span>
<span class="doc-info-value">${xmlData.primaryDocInfo.startDate}</span>
</div>
<div class="doc-info-item">
<span class="doc-info-label">Окончание документирования:</span>
<span class="doc-info-value">${xmlData.primaryDocInfo.endDate}</span>
</div>
<div class="doc-info-item">
<span class="doc-info-label">Фактическая глубина:</span>
<span class="doc-info-value">${xmlData.primaryDocInfo.depth} м</span>
</div>
<div class="doc-info-item">
<span class="doc-info-label">Документатор:</span>
<span class="doc-info-value">${formatLongText(xmlData.primaryDocInfo.author)}</span>
</div>
</div>
`;
}
html += `
<div class="table-wrapper">
<div class="table-header">
<table class="interval-table">
<thead>
<tr>
<th style="width: 50px;">ПП</th>
<th style="width: 80px;">От (м)</th>
<th style="width: 80px;">До (м)</th>
<th style="width: 100px;">Мощность (м)</th>
<th style="width: 150px;">Стратиграфия</th>
<th style="width: 150px;">Литология</th>
<th>Описание</th>
</tr>
</thead>
</table>
</div>
<div class="table-container">
<table class="interval-table">
<tbody>`;
xmlData.primaryDocumentation.forEach(interval => {
html += `
<tr>
<td style="width: 50px;">${interval.numberPP}</td>
<td style="width: 80px;">${formatNumber(interval.from)}</td>
<td style="width: 80px;">${formatNumber(interval.to)}</td>
<td style="width: 100px;">${formatNumber(interval.thickness)}</td>
<td style="width: 150px;" class="stratigraphy-column">${interval.stratigraphy}</td>
<td style="width: 150px;">${interval.lithology}</td>
<td><div class="description-text">${interval.description}</div></td>
</tr>`;
});
html += `
</tbody>
</table>
</div>
</div>
</div>`;
}
// Содержимое вкладки "Итоговое документирование"
if (hasFinal) {
html += `<div id="finalTab" class="tab-content ${!hasPrimary && hasFinal ? 'active' : ''}">`;
// Информация об итоговом документировании в компактном виде
if (xmlData.finalDocInfo) {
html += `
<div class="doc-info-list">
<div class="doc-info-item">
<span class="doc-info-label">Начало документирования:</span>
<span class="doc-info-value">${xmlData.finalDocInfo.startDate}</span>
</div>
<div class="doc-info-item">
<span class="doc-info-label">Окончание документирования:</span>
<span class="doc-info-value">${xmlData.finalDocInfo.endDate}</span>
</div>
<div class="doc-info-item">
<span class="doc-info-label">Фактическая глубина:</span>
<span class="doc-info-value">${xmlData.finalDocInfo.depth} м</span>
</div>
<div class="doc-info-item">
<span class="doc-info-label">Документатор:</span>
<span class="doc-info-value">${formatLongText(xmlData.finalDocInfo.author)}</span>
</div>
</div>
`;
}
html += `
<div class="table-wrapper">
<div class="table-header">
<table class="interval-table">
<thead>
<tr>
<th style="width: 50px;">ПП</th>
<th style="width: 80px;">От (м)</th>
<th style="width: 80px;">До (м)</th>
<th style="width: 100px;">Мощность (м)</th>
<th style="width: 150px;">Стратиграфия</th>
<th style="width: 150px;">Литология</th>
<th>Описание</th>
</tr>
</thead>
</table>
</div>
<div class="table-container">
<table class="interval-table">
<tbody>`;
xmlData.finalDocumentation.forEach(interval => {
html += `
<tr>
<td style="width: 50px;">${interval.numberPP}</td>
<td style="width: 80px;">${formatNumber(interval.from)}</td>
<td style="width: 80px;">${formatNumber(interval.to)}</td>
<td style="width: 100px;">${formatNumber(interval.thickness)}</td>
<td style="width: 150px;" class="stratigraphy-column">${interval.stratigraphy}</td>
<td style="width: 150px;">${interval.lithology}</td>
<td><div class="description-text">${interval.description}</div></td>
</tr>`;
});
html += `
</tbody>
</table>
</div>
</div>
</div>`;
}
// Содержимое вкладки "Документирование по ГИС"
if (hasGis) {
html += `<div id="gisTab" class="tab-content ${!hasPrimary && !hasFinal && hasGis ? 'active' : ''}">`;
// Информация о ГИС документировании в компактном виде
if (xmlData.gisDocInfo) {
let hasDocInfo = false;
let docInfoHtml = '';
if (xmlData.gisDocInfo.startDate && xmlData.gisDocInfo.startDate !== '') {
docInfoHtml += `
<div class="doc-info-item">
<span class="doc-info-label">Начало документирования:</span>
<span class="doc-info-value">${xmlData.gisDocInfo.startDate}</span>
</div>`;
hasDocInfo = true;
}
if (xmlData.gisDocInfo.endDate && xmlData.gisDocInfo.endDate !== '') {
docInfoHtml += `
<div class="doc-info-item">
<span class="doc-info-label">Окончание документирования:</span>
<span class="doc-info-value">${xmlData.gisDocInfo.endDate}</span>
</div>`;
hasDocInfo = true;
}
if (xmlData.gisDocInfo.depth && xmlData.gisDocInfo.depth !== 'Не указано') {
docInfoHtml += `
<div class="doc-info-item">
<span class="doc-info-label">Фактическая глубина:</span>
<span class="doc-info-value">${xmlData.gisDocInfo.depth} м</span>
</div>`;
hasDocInfo = true;
}
if (xmlData.gisDocInfo.author && xmlData.gisDocInfo.author !== 'Не указано') {
docInfoHtml += `
<div class="doc-info-item">
<span class="doc-info-label">Документатор:</span>
<span class="doc-info-value">${formatLongText(xmlData.gisDocInfo.author)}</span>
</div>`;
hasDocInfo = true;
}
if (hasDocInfo) {
html += `<div class="doc-info-list">${docInfoHtml}</div>`;
}
}
html += `
<div class="table-wrapper">
<div class="table-header">
<table class="interval-table">
<thead>
<tr>
<th style="width: 50px;">ПП</th>
<th style="width: 80px;">От (м)</th>
<th style="width: 80px;">До (м)</th>
<th style="width: 100px;">Мощность (м)</th>
<th style="width: 150px;">Стратиграфия</th>
<th style="width: 150px;">Литология</th>
<th>Описание</th>
</tr>
</thead>
</table>
</div>
<div class="table-container">
<table class="interval-table">
<tbody>`;
xmlData.gisDocumentation.forEach(interval => {
html += `
<tr>
<td style="width: 50px;">${interval.numberPP}</td>
<td style="width: 80px;">${formatNumber(interval.from)}</td>
<td style="width: 80px;">${formatNumber(interval.to)}</td>
<td style="width: 100px;">${formatNumber(interval.thickness)}</td>
<td style="width: 150px;" class="stratigraphy-column">${interval.stratigraphy}</td>
<td style="width: 150px;">${interval.lithology}</td>
<td><div class="description-text">${interval.description}</div></td>
</tr>`;
});
html += `
</tbody>
</table>
</div>
</div>
</div>`;
}
// Содержимое вкладки "Опробование"
if (hasAssays) {
html += `<div id="assaysTab" class="tab-content ${!hasPrimary && !hasFinal && !hasGis ? 'active' : ''}">`;
html += `
<div class="table-wrapper">
<div class="table-header">
<table class="interval-table" style="min-width: 1200px;">
<thead>
<tr>
<th style="width: 70px;">№ пробы</th>
<th style="width: 90px;">Штрих-код</th>
<th style="width: 130px;">Тип пробы</th>
<th style="width: 190px;">Тип документирования</th>
<th style="width: 70px;">От (м)</th>
<th style="width: 70px;">До (м)</th>
<th style="width: 90px;">Значение</th>
<th style="width: 70px;">Ед. изм.</th>
<th style="width: 200px;">Описание</th>
<th style="width: 120px;">Место отбора</th>
<th style="width: 130px;">Автор отбора</th>
<th style="width: 100px;">Дата отбора</th>
</tr>
</thead>
</table>
</div>
<div class="table-container">
<table class="interval-table" style="min-width: 1200px;">
<tbody>`;
xmlData.assays.forEach(assay => {
const barcodeDisplay = (assay.barcode && assay.barcode !== 'Не указано') ? assay.barcode : '';
const placeDisplay = (assay.place && assay.place !== 'Не указано') ? assay.place : '';
const authorDisplay = (assay.author && assay.author !== '') ? assay.author : '';
const dateDisplay = (assay.samplingDate && assay.samplingDate !== 'Не указано') ? assay.samplingDate : '';
html += `
<tr>
<td style="width: 70px;">${assay.number}</td>
<td style="width: 90px;">${barcodeDisplay}</td>
<td style="width: 130px;">${assay.type}</td>
<td style="width: 190px;">${assay.documentationType}</td>
<td style="width: 70px;">${formatNumber(assay.from)}</td>
<td style="width: 70px;">${formatNumber(assay.to)}</td>
<td style="width: 90px;">${assay.value}</td>
<td style="width: 70px;">${assay.unit}</td>
<td style="width: 200px;"><div class="description-text">${assay.description}</div></td>
<td style="width: 120px;">${placeDisplay}</td>
<td style="width: 130px;">${authorDisplay}</td>
<td style="width: 100px;">${dateDisplay}</td>
</tr>`;
});
html += `
</tbody>
</table>
</div>
</div>
</div>`;
}
html += `</div>`; // закрываем section
} else {
html += `
<div class="section">
<h2>Документирование и опробование</h2>
<div class="no-data">
<p>Нет данных о документировании и опробовании</p>
</div>
</div>
`;
}
Добавлено (2025-10-02, 11:03)
---------------------------------------------
Отлично! Добавим подсветку обязательных полей. Вот необходимые изменения:
1. Для документирования - обновим блоки информации:
```javascript
// В каждом блоке документирования (primary, final, gis) замените doc-info-list на такой код:
// Для первичного документирования:
if (xmlData.primaryDocInfo) {
let hasDocInfo = false;
let docInfoHtml = '';
if (xmlData.primaryDocInfo.startDate && xmlData.primaryDocInfo.startDate !== '') {
docInfoHtml += `
<div class="doc-info-item">
<span class="doc-info-label">Начало документирования:</span>
<span class="doc-info-value">${xmlData.primaryDocInfo.startDate}</span>
</div>
`;
hasDocInfo = true;
}
// Обязательное поле - окончание документирования
if (xmlData.primaryDocInfo.endDate && xmlData.primaryDocInfo.endDate !== '') {
docInfoHtml += `
<div class="doc-info-item">
<span class="doc-info-label">Окончание документирования:</span>
<span class="doc-info-value">${xmlData.primaryDocInfo.endDate}</span>
</div>
`;
} else if (xmlData.primaryDocInfo.startDate && xmlData.primaryDocInfo.startDate !== '') {
// Если есть начало, но нет окончания - выделяем красным
docInfoHtml += `
<div class="doc-info-item missing-field">
<span class="doc-info-label">Окончание документирования:</span>
<span class="doc-info-value">Не указано (обязательное поле)</span>
</div>
`;
}
hasDocInfo = true;
if (xmlData.primaryDocInfo.depth && xmlData.primaryDocInfo.depth !== 'Не указано') {
docInfoHtml += `
<div class="doc-info-item">
<span class="doc-info-label">Фактическая глубина:</span>
<span class="doc-info-value">${xmlData.primaryDocInfo.depth} м</span>
</div>
`;
hasDocInfo = true;
}
if (xmlData.primaryDocInfo.author && xmlData.primaryDocInfo.author !== 'Не указано') {
docInfoHtml += `
<div class="doc-info-item">
<span class="doc-info-label">Документатор:</span>
<span class="doc-info-value">${formatLongText(xmlData.primaryDocInfo.author)}</span>
</div>
`;
hasDocInfo = true;
}
if (hasDocInfo) {
html += `<div class="doc-info-list">${docInfoHtml}</div>`;
}
}
// Аналогично для finalDocInfo и gisDocInfo - примените тот же принцип
```
2. Для таблицы опробования - обновите генерацию строк:
```javascript
// В блоке assays замените генерацию строк на:
xmlData.assays.forEach(assay => {
const barcodeDisplay = (assay.barcode && assay.barcode !== 'Не указано') ? assay.barcode : '';
const placeDisplay = (assay.place && assay.place !== 'Не указано') ? assay.place : '';
const authorDisplay = (assay.author && assay.author !== '') ? assay.author : '';
const dateDisplay = (assay.samplingDate && assay.samplingDate !== 'Не указано') ? assay.samplingDate : '';
// Проверяем обязательные поля для подсветки
const authorClass = (!authorDisplay || authorDisplay === '') ? 'missing-cell' : '';
const dateClass = (!dateDisplay || dateDisplay === '') ? 'missing-cell' : '';
html += `
<tr>
<td style="width: 70px;">${assay.number}</td>
<td style="width: 90px;">${barcodeDisplay}</td>
<td style="width: 130px;">${assay.type}</td>
<td style="width: 190px;">${assay.documentationType}</td>
<td style="width: 70px;">${formatNumber(assay.from)}</td>
<td style="width: 70px;">${formatNumber(assay.to)}</td>
<td style="width: 90px;">${assay.value}</td>
<td style="width: 70px;">${assay.unit}</td>
<td style="width: 200px;"><div class="description-text">${assay.description}</div></td>
<td style="width: 120px;">${placeDisplay}</td>
<td style="width: 130px;" class="${authorClass}">${authorDisplay}</td>
<td style="width: 100px;" class="${dateClass}">${dateDisplay}</td>
</tr>`;
});
```
3. Добавьте CSS стили для подсветки:
```css
/* Стили для обязательных полей в документировании */
.doc-info-item.missing-field {
background-color: #fdf2f2;
border-left: 3px solid #e74c3c;
padding-left: 8px;
margin-left: -8px;
}
.doc-info-item.missing-field .doc-info-label {
color: #e74c3c;
font-weight: 600;
}
.doc-info-item.missing-field .doc-info-value {
color: #c0392b;
font-weight: 500;
}
/* Стили для ячеек с отсутствующими данными в таблице опробования */
.missing-cell {
background-color: #fdf2f2 !important;
color: #c0392b !important;
font-style: italic;
}
.missing-cell::after {
content: " (не указано)";
font-size: 0.8em;
opacity: 0.7;
}
```
4. Примените тот же принцип для finalDocInfo и gisDocInfo:
Скопируйте логику из primaryDocInfo и примените к finalDocInfo и gisDocInfo в соответствующих блоках.
Эти изменения:
· Подсветят красным обязательное поле "Окончание документирования", если оно не заполнено при наличии начала
· Выделят ячейки автора отбора и даты отбора в таблице опробования, если они пустые
· Сохранят информативность интерфейса, показывая пользователю, какие данные отсутствуют
Добавлено (2025-10-02, 11:14)
---------------------------------------------
Добавлю подсветку обязательных полей для итогового и ГИС документирования:
1. Для итогового документирования замените блок:
```javascript
// Содержимое вкладки "Итоговое документирование"
if (hasFinal) {
html += `<div id="finalTab" class="tab-content ${!hasPrimary && hasFinal ? 'active' : ''}">`;
// Информация об итоговом документировании в компактном виде
if (xmlData.finalDocInfo) {
let hasDocInfo = false;
let docInfoHtml = '';
if (xmlData.finalDocInfo.startDate && xmlData.finalDocInfo.startDate !== '') {
docInfoHtml += `
<div class="doc-info-item">
<span class="doc-info-label">Начало документирования:</span>
<span class="doc-info-value">${xmlData.finalDocInfo.startDate}</span>
</div>
`;
hasDocInfo = true;
}
// Обязательное поле - окончание документирования
if (xmlData.finalDocInfo.endDate && xmlData.finalDocInfo.endDate !== '') {
docInfoHtml += `
<div class="doc-info-item">
<span class="doc-info-label">Окончание документирования:</span>
<span class="doc-info-value">${xmlData.finalDocInfo.endDate}</span>
</div>
`;
} else if (xmlData.finalDocInfo.startDate && xmlData.finalDocInfo.startDate !== '') {
// Если есть начало, но нет окончания - выделяем красным
docInfoHtml += `
<div class="doc-info-item missing-field">
<span class="doc-info-label">Окончание документирования:</span>
<span class="doc-info-value">Не указано (обязательное поле)</span>
</div>
`;
}
hasDocInfo = true;
if (xmlData.finalDocInfo.depth && xmlData.finalDocInfo.depth !== 'Не указано') {
docInfoHtml += `
<div class="doc-info-item">
<span class="doc-info-label">Фактическая глубина:</span>
<span class="doc-info-value">${xmlData.finalDocInfo.depth} м</span>
</div>
`;
hasDocInfo = true;
}
if (xmlData.finalDocInfo.author && xmlData.finalDocInfo.author !== 'Не указано') {
docInfoHtml += `
<div class="doc-info-item">
<span class="doc-info-label">Документатор:</span>
<span class="doc-info-value">${formatLongText(xmlData.finalDocInfo.author)}</span>
</div>
`;
hasDocInfo = true;
}
if (hasDocInfo) {
html += `<div class="doc-info-list">${docInfoHtml}</div>`;
}
}
// ... остальной код таблицы без изменений ...
}
```
2. Для ГИС документирования замените блок:
```javascript
// Содержимое вкладки "Документирование по ГИС"
if (hasGis) {
html += `<div id="gisTab" class="tab-content ${!hasPrimary && !hasFinal && hasGis ? 'active' : ''}">`;
// Информация о ГИС документировании в компактном виде
if (xmlData.gisDocInfo) {
let hasDocInfo = false;
let docInfoHtml = '';
if (xmlData.gisDocInfo.startDate && xmlData.gisDocInfo.startDate !== '') {
docInfoHtml += `
<div class="doc-info-item">
<span class="doc-info-label">Начало документирования:</span>
<span class="doc-info-value">${xmlData.gisDocInfo.startDate}</span>
</div>`;
hasDocInfo = true;
}
// Обязательное поле - окончание документирования
if (xmlData.gisDocInfo.endDate && xmlData.gisDocInfo.endDate !== '') {
docInfoHtml += `
<div class="doc-info-item">
<span class="doc-info-label">Окончание документирования:</span>
<span class="doc-info-value">${xmlData.gisDocInfo.endDate}</span>
</div>`;
} else if (xmlData.gisDocInfo.startDate && xmlData.gisDocInfo.startDate !== '') {
// Если есть начало, но нет окончания - выделяем красным
docInfoHtml += `
<div class="doc-info-item missing-field">
<span class="doc-info-label">Окончание документирования:</span>
<span class="doc-info-value">Не указано (обязательное поле)</span>
</div>`;
}
hasDocInfo = true;
if (xmlData.gisDocInfo.depth && xmlData.gisDocInfo.depth !== 'Не указано') {
docInfoHtml += `
<div class="doc-info-item">
<span class="doc-info-label">Фактическая глубина:</span>
<span class="doc-info-value">${xmlData.gisDocInfo.depth} м</span>
</div>`;
hasDocInfo = true;
}
if (xmlData.gisDocInfo.author && xmlData.gisDocInfo.author !== 'Не указано') {
docInfoHtml += `
<div class="doc-info-item">
<span class="doc-info-label">Документатор:</span>
<span class="doc-info-value">${formatLongText(xmlData.gisDocInfo.author)}</span>
</div>`;
hasDocInfo = true;
}
if (hasDocInfo) {
html += `<div class="doc-info-list">${docInfoHtml}</div>`;
}
}
// ... остальной код таблицы без изменений ...
}
```
3. Также не забудьте добавить CSS стили (если еще не добавили):
```css
/* Стили для обязательных полей в документировании */
.doc-info-item.missing-field {
background-color: #fdf2f2;
border-left: 3px solid #e74c3c;
padding-left: 8px;
margin-left: -8px;
}
.doc-info-item.missing-field .doc-info-label {
color: #e74c3c;
font-weight: 600;
}
.doc-info-item.missing-field .doc-info-value {
color: #c0392b;
font-weight: 500;
}
/* Стили для ячеек с отсутствующими данными в таблице опробования */
.missing-cell {
background-color: #fdf2f2 !important;
color: #c0392b !important;
font-style: italic;
}
.missing-cell::after {
content: " (не указано)";
font-size: 0.8em;
opacity: 0.7;
}
```
Теперь все три типа документирования (первичное, итоговое и ГИС) будут иметь одинаковую подсветку обязательных полей, а таблица опробования будет выделять ячейки с отсутствующими данными автора и даты отбора.
Добавлено (2025-10-02, 12:23)
---------------------------------------------
Добавим чекбокс для поиска в подпапках. Вот необходимые изменения:
1. Добавьте HTML для чекбокса в левую панель:
```html
<div class="folder-selector">
<div class="folder-path" id="folderPath">Выберите папку с архивами</div>
<div class="folder-buttons">
<button class="btn" id="selectFolderBtn">Выбрать папку</button>
<button class="btn" id="selectFileBtn">Открыть INU файл</button>
<button class="btn" id="refreshBtn">Обновить</button>
</div>
<div class="folder-options">
<label class="checkbox-label">
<input type="checkbox" id="searchSubfolders">
<span class="checkmark"></span>
Искать в подпапках
</label>
</div>
</div>
```
2. Добавьте CSS стили для чекбокса:
```css
/* Стили для опций папки */
.folder-options {
margin-top: 10px;
}
.checkbox-label {
display: flex;
align-items: center;
cursor: pointer;
font-size: 0.9rem;
color: #ecf0f1;
gap: 8px;
}
.checkbox-label input[type="checkbox"] {
display: none;
}
.checkmark {
width: 18px;
height: 18px;
background-color: #34495e;
border: 2px solid #7f8c8d;
border-radius: 3px;
position: relative;
transition: all 0.2s;
}
.checkbox-label input[type="checkbox"]:checked + .checkmark {
background-color: #3498db;
border-color: #3498db;
}
.checkbox-label input[type="checkbox"]:checked + .checkmark::after {
content: '';
position: absolute;
left: 5px;
top: 2px;
width: 4px;
height: 8px;
border: solid white;
border-width: 0 2px 2px 0;
transform: rotate(45deg);
}
.checkbox-label:hover .checkmark {
border-color: #bdc3c7;
}
```
3. Добавьте глобальную переменную и обновите функцию loadFileList:
```javascript
// Глобальные переменные
let currentFile = null;
let xmlData = null;
let currentDirectoryHandle = null;
let searchSubfolders = false; // Добавляем переменную для поиска в подпапках
// Инициализация при загрузке страницы
document.addEventListener('DOMContentLoaded', function() {
document.getElementById('selectFolderBtn').addEventListener('click', selectFolder);
document.getElementById('selectFileBtn').addEventListener('click', selectFileManually);
document.getElementById('refreshBtn').addEventListener('click', refreshFileList);
// Обработчик чекбокса поиска в подпапках
document.getElementById('searchSubfolders').addEventListener('change', function() {
searchSubfolders = this.checked;
if (currentDirectoryHandle) {
loadFileList();
}
});
});
// Загрузка списка файлов из директории (рекурсивно при необходимости)
async function loadFileList() {
if (!currentDirectoryHandle) return;
try {
const fileList = document.getElementById('fileList');
fileList.innerHTML = '<li class="file-item">Загрузка...</li>';
const files = [];
// Функция для рекурсивного поиска файлов
async function searchFiles(directoryHandle, path = '') {
for await (const entry of directoryHandle.values()) {
if (entry.kind === 'file') {
const file = await entry.getFile();
// Проверяем, является ли файл архивом ZIP
if (file.name.toLowerCase().endsWith('.zip')) {
files.push({
name: path ? `${path}/${file.name}` : file.name,
handle: entry,
size: file.size,
lastModified: file.lastModified,
fullPath: path
});
}
} else if (entry.kind === 'directory' && searchSubfolders) {
// Рекурсивно ищем в подпапках
const subPath = path ? `${path}/${entry.name}` : entry.name;
await searchFiles(entry, subPath);
}
}
}
// Запускаем поиск файлов
await searchFiles(currentDirectoryHandle);
// Сортируем файлы по дате изменения (новые сверху)
files.sort((a, b) => b.lastModified - a.lastModified);
fileList.innerHTML = '';
if (files.length === 0) {
fileList.innerHTML = '<li class="file-item">В папке нет архивов ZIP</li>';
document.getElementById('fileCounter').textContent = 'Найдено архивов: 0';
return;
}
files.forEach((file, index) => {
const listItem = document.createElement('li');
listItem.className = 'file-item';
const fileSize = (file.size / 1024 / 1024).toFixed(2);
const modDate = new Date(file.lastModified).toLocaleDateString();
const displayName = file.fullPath ? `${file.fullPath}/${file.name}` : file.name;
listItem.innerHTML = `
<div class="file-number">${index + 1}</div>
<div class="file-content">
<div>${displayName}</div>
<div class="file-info">${fileSize} MB · ${modDate}</div>
</div>
`;
listItem.addEventListener('click', () => selectFile(file, index + 1));
fileList.appendChild(listItem);
});
// Обновляем счетчик файлов
const subfolderText = searchSubfolders ? ' (включая подпапки)' : '';
document.getElementById('fileCounter').textContent = `Найдено архивов: ${files.length}${subfolderText}`;
} catch (error) {
console.error('Ошибка загрузки списка файлов:', error);
document.getElementById('fileList').innerHTML = '<li class="file-item">Ошибка загрузки файлов</li>';
document.getElementById('fileCounter').textContent = 'Ошибка загрузки';
}
}
```
4. Обновите функцию selectFile для работы с новым форматом данных:
```javascript
// Выбор файла
async function selectFile(file, fileNumber) {
// Сброс активного класса у всех элементов
document.querySelectorAll('.file-item').forEach(item => {
item.classList.remove('active');
});
// Добавление активного класса к выбранному элементу
event.currentTarget.classList.add('active');
currentFile = file;
await loadWellData(file, fileNumber);
}
```
Теперь в интерфейсе появится чекбокс "Искать в подпапках", который при включении будет рекурсивно искать ZIP-архивы во всех подпапках выбранной директории. Файлы будут отображаться с путями относительно корневой папки, и счетчик файлов будет показывать, ведется ли поиск в подпапках.
Добавлено (2025-10-02, 12:37)
---------------------------------------------
Улучшим отображение файлов с поддиректориями. Вот необходимые изменения:
1. Обновите CSS для лучшего отображения:
```css
/* Улучшаем стили для списка файлов */
.file-item {
padding: 10px;
margin-bottom: 5px;
background-color: #34495e;
border-radius: 4px;
cursor: pointer;
transition: background-color 0.2s;
display: flex;
align-items: flex-start;
min-height: 60px; /* Увеличиваем минимальную высоту */
}
.file-number {
background-color: #2c3e50;
color: #bdc3c7;
border-radius: 3px;
padding: 2px 6px;
margin-right: 8px;
font-size: 0.7rem;
min-width: 28px; /* Увеличиваем минимальную ширину */
text-align: center;
flex-shrink: 0;
align-self: flex-start;
}
.file-content {
flex: 1;
min-width: 0; /* Важно для обрезки длинного текста */
}
.file-content > div:first-child {
font-weight: 500;
margin-bottom: 4px;
word-break: break-all; /* Перенос длинных путей */
line-height: 1.3;
}
.file-info {
font-size: 0.8rem;
color: #bdc3c7;
margin-top: 2px;
}
/* Стили для отображения пути */
.file-path {
font-size: 0.75rem;
color: #95a5a6;
margin-bottom: 2px;
word-break: break-all;
}
.file-name {
font-weight: 500;
color: #ecf0f1;
word-break: break-word;
}
```
2. Обновите генерацию HTML для файлов в функции loadFileList:
```javascript
files.forEach((file, index) => {
const listItem = document.createElement('li');
listItem.className = 'file-item';
const fileSize = (file.size / 1024 / 1024).toFixed(2);
const modDate = new Date(file.lastModified).toLocaleDateString();
// Разделяем путь и имя файла для лучшего отображения
let pathDisplay = '';
let nameDisplay = file.name;
if (file.fullPath) {
pathDisplay = file.fullPath;
// Можно также отобразить только имя файла, если путь слишком длинный
nameDisplay = file.name;
}
listItem.innerHTML = `
<div class="file-number">${index + 1}</div>
<div class="file-content">
${pathDisplay ? `<div class="file-path">${pathDisplay}/</div>` : ''}
<div class="file-name">${nameDisplay}</div>
<div class="file-info">${fileSize} MB · ${modDate}</div>
</div>
`;
listItem.addEventListener('click', () => selectFile(file, index + 1));
fileList.appendChild(listItem);
});
```
3. Альтернативный вариант - если хотите компактнее отображать:
```javascript
files.forEach((file, index) => {
const listItem = document.createElement('li');
listItem.className = 'file-item';
const fileSize = (file.size / 1024 / 1024).toFixed(2);
const modDate = new Date(file.lastModified).toLocaleDateString();
// Компактное отображение: показываем путь и имя в одной строке
let displayName = file.name;
if (file.fullPath) {
// Укорачиваем длинные пути
const maxPathLength = 30;
let shortenedPath = file.fullPath;
if (file.fullPath.length > maxPathLength) {
shortenedPath = '...' + file.fullPath.substring(file.fullPath.length - maxPathLength + 3);
}
displayName = `${shortenedPath}/${file.name}`;
}
listItem.innerHTML = `
<div class="file-number">${index + 1}</div>
<div class="file-content">
<div class="file-name">${displayName}</div>
<div class="file-info">${fileSize} MB · ${modDate}</div>
</div>
`;
listItem.addEventListener('click', () => selectFile(file, index + 1));
fileList.appendChild(listItem);
});
```
4. Если хотите самый компактный вариант с тултипами:
```javascript
files.forEach((file, index) => {
const listItem = document.createElement('li');
listItem.className = 'file-item';
const fileSize = (file.size / 1024 / 1024).toFixed(2);
const modDate = new Date(file.lastModified).toLocaleDateString();
// Полный путь для тултипа
const fullPath = file.fullPath ? `${file.fullPath}/${file.name}` : file.name;
// Компактное отображение имени файла
let displayName = file.name;
if (file.fullPath) {
// Показываем только последнюю папку если есть подпапки
const pathParts = file.fullPath.split('/');
if (pathParts.length > 1) {
displayName = `${pathParts[pathParts.length - 1]}/${file.name}`;
} else {
displayName = `${file.fullPath}/${file.name}`;
}
}
listItem.innerHTML = `
<div class="file-number">${index + 1}</div>
<div class="file-content" title="${fullPath}">
<div class="file-name">${displayName}</div>
<div class="file-info">${fileSize} MB · ${modDate}</div>
</div>
`;
listItem.addEventListener('click', () => selectFile(file, index + 1));
fileList.appendChild(listItem);
});
```
Выберите наиболее подходящий вариант отображения. Я рекомендую первый вариант с разделением пути и имени файла - он самый читаемый и информативный. При наведении на файл можно видеть полный путь во всплывающей подсказке (добавьте title="${file.fullPath ? file.fullPath + '/' + file.name : file.name}" к .file-content если нужно).
Добавлено (2025-10-02, 12:49)
---------------------------------------------
files.forEach((file, index) => {
const listItem = document.createElement('li');
listItem.className = 'file-item';
const fileSize = (file.size / 1024 / 1024).toFixed(2);
const modDate = new Date(file.lastModified).toLocaleDateString();
listItem.innerHTML = `
<div class="file-number">${index + 1}</div>
<div class="file-content">
${file.fullPath ? `<div class="file-path">${file.fullPath}/</div>` : ''}
<div class="file-name">${file.name}</div>
<div class="file-info">${fileSize} MB · ${modDate}</div>
</div>
`;
listItem.addEventListener('click', () => selectFile(file, index + 1));
fileList.appendChild(listItem);
});
Добавлено (2025-10-02, 12:59)
---------------------------------------------
// Функция для рекурсивного поиска файлов
async function searchFiles(directoryHandle, path = '') {
for await (const entry of directoryHandle.values()) {
if (entry.kind === 'file') {
const file = await entry.getFile();
// Проверяем, является ли файл архивом ZIP
if (file.name.toLowerCase().endsWith('.zip')) {
files.push({
name: file.name, // Только имя файла без пути
handle: entry,
size: file.size,
lastModified: file.lastModified,
fullPath: path // Путь храним отдельно
});
}
} else if (entry.kind === 'directory' && searchSubfolders) {
// Рекурсивно ищем в подпапках
const subPath = path ? `${path}/${entry.name}` : entry.name;
await searchFiles(entry, subPath);
}
}
}