document.getElementById('cnt-diss').textContent = diss.length;
document.getElementById('cnt-part').textContent = parts.length;
document.getElementById('cnt-q').textContent = totalQ;
const recent = [...items].sort((a,b) => (b.id||0)-(a.id||0)).slice(0,6);
document.getElementById('recent-list').innerHTML = recent.map(cardHTML).join('') || '
Нет данных
';
document.getElementById('proj-list').innerHTML = proj.map(cardHTML).join('') || '
Нет проектов
';
document.getElementById('book-list').innerHTML = books.map(cardHTML).join('') || '
Нет книг
';
document.getElementById('lec-list').innerHTML = lectures.map(cardHTML).join('') || '
Нет лекций
';
document.getElementById('diss-list').innerHTML = diss.map(cardHTML).join('') || '
Нет записей
';
document.getElementById('part-list').innerHTML = parts.map(cardHTML).join('') || '
Нет данных участников
';
const userItems = readUserItems();
document.getElementById('user-list').innerHTML = userItems.map(cardHTML).join('') || '
Пока нет добавленных вручную записей
';
}
function filterParticipants() {
const q = document.getElementById('part-search').value.toLowerCase();
const parts = getItems().filter(i => i && i.type === 'participant');
const filtered = q ? parts.filter(i =>
(i.title||'').toLowerCase().includes(q) ||
(i.note||'').toLowerCase().includes(q) ||
(i.tags||[]).some(t => t.toLowerCase().includes(q)) ||
(i.quotes||[]).some(qq => (qq.text||'').toLowerCase().includes(q) || (qq.tag||'').toLowerCase().includes(q))
) : parts;
document.getElementById('part-list').innerHTML = filtered.map(cardHTML).join('') || '
Ничего не найдено
';
}
function filterProjects() {
const q = document.getElementById('proj-search').value.toLowerCase();
const proj = getItems().filter(i => i && i.type === 'project');
const filtered = q ? proj.filter(i =>
(i.title||'').toLowerCase().includes(q) ||
(i.note||'').toLowerCase().includes(q) ||
(i.tags||[]).some(t => t.toLowerCase().includes(q))
) : proj;
document.getElementById('proj-list').innerHTML = filtered.map(cardHTML).join('') || '
Ничего не найдено
';
}
function filterLectures() {
const q = document.getElementById('lec-search').value.toLowerCase();
const lectures = getItems().filter(i => i && (i.type === 'lecture' || i.type === 'practice'));
const filtered = q ? lectures.filter(i =>
(i.title||'').toLowerCase().includes(q) ||
(i.note||'').toLowerCase().includes(q) ||
(i.tags||[]).some(t => t.toLowerCase().includes(q)) ||
(i.quotes||[]).some(qq => (qq.text||'').toLowerCase().includes(q))
) : lectures;
document.getElementById('lec-list').innerHTML = filtered.map(cardHTML).join('') || '
Ничего не найдено
';
}
function doSearch() {
const q = document.getElementById('main-search').value.toLowerCase();
if (!q) { document.getElementById('search-list').innerHTML = '
Введите запрос
'; return; }
const filtered = getItems().filter(i => i && (
(i.title||'').toLowerCase().includes(q) ||
(i.note||'').toLowerCase().includes(q) ||
(i.author||'').toLowerCase().includes(q) ||
(i.tags||[]).some(t => t.toLowerCase().includes(q)) ||
(i.quotes||[]).some(qq => (qq.text||'').toLowerCase().includes(q) || (qq.tag||'').toLowerCase().includes(q))
));
document.getElementById('search-list').innerHTML = filtered.length ?
filtered.map(cardHTML).join('') :
'
Ничего не найдено по запросу «' + escapeHTML(q) + '»
';
}
function addItem() {
const title = document.getElementById('add-title').value.trim();
if (!title) {
document.getElementById('save-status').textContent = 'Добавьте название записи.';
return;
}
const item = {
id: Date.now(),
type: document.getElementById('add-type').value,
title,
author: document.getElementById('add-author').value.trim(),
publisher: document.getElementById('add-publisher').value.trim(),
status: 'добавлено вручную',
date: document.getElementById('add-date').value.trim(),
tags: splitList(document.getElementById('add-tags').value),
note: document.getElementById('add-note').value.trim(),
quotes: parseQuotes(document.getElementById('add-quotes').value),
link: '',
linkname: ''
};
const items = readUserItems();
items.unshift(item);
writeUserItems(items);
saveItemToGoogleSheet(item);
['add-title','add-author','add-publisher','add-date','add-tags','add-note','add-quotes'].forEach(id => document.getElementById(id).value = '');
document.getElementById('save-status').textContent = GOOGLE_APPS_SCRIPT_URL ? 'Запись сохранена локально и отправлена в Google Sheets.' : 'Запись сохранена локально. Для записи в Google Sheets вставьте URL Apps Script в код страницы.';
render();
}
function saveItemToGoogleSheet(item) {
if (!GOOGLE_APPS_SCRIPT_URL) return;
fetch(GOOGLE_APPS_SCRIPT_URL, {
method: 'POST',
mode: 'no-cors',
headers: {'Content-Type':'text/plain;charset=utf-8'},
body: JSON.stringify(item)
}).catch(() => {
document.getElementById('save-status').textContent = 'Запись сохранена локально, но Google Sheets не ответил.';
});
}
function exportItems() {
const items = readUserItems();
const blob = new Blob([JSON.stringify(items, null, 2)], {type:'application/json'});
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'knowledge-base-added.json';
a.click();
URL.revokeObjectURL(url);
}
function importItems(event) {
const file = event.target.files && event.target.files[0];
if (!file) return;
const reader = new FileReader();
reader.onload = () => {
try {
const incoming = JSON.parse(reader.result);
if (!Array.isArray(incoming)) throw new Error('JSON должен быть массивом записей');
const byId = new Map(readUserItems().map(item => [item.id, item]));
incoming.filter(Boolean).forEach(item => {
const normalized = {...item, id: item.id || Date.now() + Math.random()};
byId.set(normalized.id, normalized);
});
writeUserItems([...byId.values()]);
document.getElementById('save-status').textContent = 'JSON загружен. Записи добавлены в базу.';
render();
} catch (e) {
document.getElementById('save-status').textContent = 'Не получилось загрузить JSON: ' + e.message;
}
event.target.value = '';
};
reader.readAsText(file);
}
function clearUserItems() {
if (!confirm('Удалить все записи, добавленные вручную в этом браузере?')) return;
writeUserItems([]);
document.getElementById('save-status').textContent = 'Добавленные вручную записи очищены.';
render();
}
render();
loadSheetItems();