145 lines
5.6 KiB
Markdown
145 lines
5.6 KiB
Markdown
|
||
## 📊 Статистика
|
||
|
||
```dataviewjs
|
||
const books = dv.pages('"Библиотека/Книги"').where(p => p.Тип == "Книга");
|
||
const read = books.where(p => p.Статус == "Прочитано");
|
||
const inProgress = books.where(p => p.Статус == "В процессе");
|
||
const planned = books.where(p => p.Статус == "Хочу прочитать" || p.Статус == "Запланировано");
|
||
const abandoned = books.where(p => p.Статус == "Заброшена");
|
||
|
||
const totalPages = read.array().reduce((sum, p) => sum + (Number(p["Количество страниц"]) || 0), 0);
|
||
const rated = read.where(p => p.Оценка);
|
||
const avgRating = rated.length
|
||
? (rated.array().reduce((s, p) => s + Number(p.Оценка), 0) / rated.length).toFixed(1)
|
||
: "—";
|
||
|
||
dv.table(["", ""], [
|
||
["📚 Всего книг", books.length],
|
||
["✅ Прочитано", read.length],
|
||
["📖 Читаю сейчас", inProgress.length],
|
||
["🔖 Хочу прочитать", planned.length],
|
||
["⛔ Заброшено", abandoned.length],
|
||
["📄 Страниц прочитано", totalPages.toLocaleString("ru-RU")],
|
||
["⭐ Средняя оценка", avgRating],
|
||
]);
|
||
```
|
||
|
||
---
|
||
|
||
```dataviewjs
|
||
const books = dv.pages('"Библиотека/Книги"')
|
||
.where(p => p.Тип == "Книга" && p.Статус == "В процессе");
|
||
|
||
if (!books.length) {
|
||
dv.paragraph("*Сейчас ничего не читаю*");
|
||
} else {
|
||
dv.table(["Обложка", "Название", "Автор", "Прогресс", "Страниц"],
|
||
books.map(p => {
|
||
const total = Number(p["Количество страниц"]) || 0;
|
||
const done = Number(p.Прогресс) || 0;
|
||
const pct = total ? Math.round(done / total * 100) : 0;
|
||
const filled = Math.round(pct / 10);
|
||
const bar = "█".repeat(filled) + "░".repeat(10 - filled);
|
||
return [
|
||
p.Обложка ? dv.span(``) : "—",
|
||
p.file.link,
|
||
p.Автор ? [].concat(p.Автор).join(", ") : "—",
|
||
`\`${bar}\` ${pct}%`,
|
||
`${done} / ${total}`
|
||
];
|
||
})
|
||
);
|
||
}
|
||
|
||
const details = document.createElement("details");
|
||
details.setAttribute("open", "");
|
||
const summary = document.createElement("summary");
|
||
summary.innerHTML = `<strong>📖 Читаю сейчас (${books.length})</strong>`;
|
||
details.appendChild(summary);
|
||
Array.from(this.container.childNodes).forEach(n => details.appendChild(n));
|
||
this.container.appendChild(details);
|
||
```
|
||
|
||
---
|
||
|
||
```dataviewjs
|
||
const fmt = f => ({ "Электронная": "📱", "Бумажная": "📗", "Аудио": "🎧" }[f] ?? "");
|
||
const books = dv.pages('"Библиотека/Книги"')
|
||
.where(p => p.Тип == "Книга" && (p.Статус == "Хочу прочитать" || p.Статус == "Запланировано"))
|
||
.sort(p => p.Название, "asc");
|
||
|
||
dv.table(["Обложка", "Название", "Автор", "Страниц", "Формат", "Категория"],
|
||
books.map(p => [
|
||
p.Обложка ? dv.span(``) : "—",
|
||
p.file.link,
|
||
p.Автор ? [].concat(p.Автор).join(", ") : "—",
|
||
p["Количество страниц"] || "—",
|
||
fmt(p.Формат),
|
||
p.Категории ? [].concat(p.Категории).join(", ") : "—"
|
||
])
|
||
);
|
||
|
||
const details = document.createElement("details");
|
||
const summary = document.createElement("summary");
|
||
summary.innerHTML = `<strong>🔖 Хочу прочитать (${books.length})</strong>`;
|
||
details.appendChild(summary);
|
||
Array.from(this.container.childNodes).forEach(n => details.appendChild(n));
|
||
this.container.appendChild(details);
|
||
```
|
||
|
||
---
|
||
|
||
```dataviewjs
|
||
const star = n => n ? `⭐ ${Number(n)}` : "—";
|
||
const fmt = f => ({ "Электронная": "📱", "Бумажная": "📗", "Аудио": "🎧" }[f] ?? f ?? "—");
|
||
const books = dv.pages('"Библиотека/Книги"')
|
||
.where(p => p.Тип == "Книга" && p.Статус == "Прочитано")
|
||
.sort(p => Number(p.Закончена) || 0, "desc");
|
||
|
||
dv.table(["Обложка", "Название", "Автор", "Год", "Оценка", "Формат", "Категория"],
|
||
books.map(p => [
|
||
p.Обложка ? dv.span(``) : "—",
|
||
p.file.link,
|
||
p.Автор ? [].concat(p.Автор).join(", ") : "—",
|
||
p.Закончена || "—",
|
||
star(p.Оценка),
|
||
fmt(p.Формат),
|
||
p.Категории ? [].concat(p.Категории).join(", ") : "—"
|
||
])
|
||
);
|
||
|
||
const details = document.createElement("details");
|
||
const summary = document.createElement("summary");
|
||
summary.innerHTML = `<strong>✅ Прочитано (${books.length})</strong>`;
|
||
details.appendChild(summary);
|
||
Array.from(this.container.childNodes).forEach(n => details.appendChild(n));
|
||
this.container.appendChild(details);
|
||
```
|
||
|
||
---
|
||
|
||
```dataviewjs
|
||
const books = dv.pages('"Библиотека/Книги"')
|
||
.where(p => p.Тип == "Книга" && p.Статус == "Заброшена");
|
||
|
||
if (!books.length) {
|
||
dv.paragraph("*Нет заброшенных книг*");
|
||
} else {
|
||
dv.table(["Название", "Автор", "Прочитано страниц"],
|
||
books.map(p => [
|
||
p.file.link,
|
||
p.Автор ? [].concat(p.Автор).join(", ") : "—",
|
||
p.Прогресс || "—"
|
||
])
|
||
);
|
||
}
|
||
|
||
const details = document.createElement("details");
|
||
const summary = document.createElement("summary");
|
||
summary.innerHTML = `<strong>⛔ Заброшено (${books.length})</strong>`;
|
||
details.appendChild(summary);
|
||
Array.from(this.container.childNodes).forEach(n => details.appendChild(n));
|
||
this.container.appendChild(details);
|
||
```
|