e8018d85c1
Фаза 1 — структура и каталог:
- frontend/textbooks/chemistry_9.html (Шиманович, 60 §) + physics_9.html (Исаченкова, 38 §)
- frontend/textbooks.html — каталог в стиле LearnSpace (карточки с обложками)
- Маршруты: /textbooks (каталог), /textbook/<slug> (полноэкранный учебник)
- Сайдбар: пункт «Учебники» (book-open-text)
- Feature flag feature_textbooks_enabled, hideDisabledFeatures map
Фаза 2 — прогресс в localStorage + UI чтения:
- frontend/js/textbook-tracker.js — инжектится в каждый учебник:
- «← Учебники» overlay-кнопка (top-left, semi-transparent)
- «Прочитано» чекбокс рядом с каждым §-заголовком
- Зелёный dot на pill уже прочитанных параграфов
- Авто-открытие последнего параграфа при возврате
- Каталог показывает прогресс-бар «X из Y прочитано» + кнопку «Продолжить»
Фаза 3 — серверный прогресс + назначение чтения как ДЗ:
- Таблица textbooks (slug, subject, grade, title, author, color, ...)
- Таблица textbook_progress (user_id, textbook_id, JSON read[], last_para)
- Колонки assignments.textbook_id + textbook_paragraphs
- API: GET /api/textbooks (с прогрессом), GET /:slug, POST /:slug/progress,
GET /:slug/class-progress (учитель)
- tracker.js синхронизирует прогресс через POST /progress (если залогинен)
- На каталоге у учителей кнопка «Назначить чтение» — модалка с выбором
классов + параграфы («1-5» или «1,3,5») + deadline
- bulkCreateAssignment расширен: принимает textbook_slug, резолвит в id
Миграция 004 идемпотентная; сиды двух учебников включены.
43 lines
2.7 KiB
SQL
43 lines
2.7 KiB
SQL
-- Feature flag for textbooks module
|
||
INSERT OR IGNORE INTO app_settings (key, value) VALUES ('feature_textbooks_enabled', '1');
|
||
|
||
-- Catalog of textbooks (admin-editable; html_path is relative to /frontend/textbooks/)
|
||
CREATE TABLE textbooks (
|
||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||
slug TEXT UNIQUE NOT NULL,
|
||
subject TEXT NOT NULL, -- 'chemistry', 'physics', 'math', 'biology', ...
|
||
grade INTEGER NOT NULL, -- 9, 10, 11, ...
|
||
title TEXT NOT NULL,
|
||
author TEXT NOT NULL DEFAULT '',
|
||
description TEXT NOT NULL DEFAULT '',
|
||
html_path TEXT NOT NULL, -- relative filename: 'chemistry_9.html'
|
||
para_count INTEGER NOT NULL DEFAULT 0, -- total paragraphs (for progress %)
|
||
color TEXT NOT NULL DEFAULT 'violet',-- visual theme: 'amber','blue','violet','green',...
|
||
sort_order INTEGER NOT NULL DEFAULT 0,
|
||
is_active INTEGER NOT NULL DEFAULT 1,
|
||
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
||
);
|
||
|
||
-- Per-user reading progress (one row per (user, textbook))
|
||
CREATE TABLE textbook_progress (
|
||
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||
textbook_id INTEGER NOT NULL REFERENCES textbooks(id) ON DELETE CASCADE,
|
||
paragraphs_read TEXT NOT NULL DEFAULT '[]', -- JSON array of para keys like ["p1","p3","p7"]
|
||
last_para TEXT, -- last opened paragraph key (e.g. 'p15')
|
||
last_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||
PRIMARY KEY (user_id, textbook_id)
|
||
);
|
||
|
||
-- Assignment extension: link to textbook + paragraph range string ("1-5" or "1,3,5")
|
||
ALTER TABLE assignments ADD COLUMN textbook_id INTEGER REFERENCES textbooks(id) ON DELETE SET NULL;
|
||
ALTER TABLE assignments ADD COLUMN textbook_paragraphs TEXT;
|
||
|
||
-- Seed: chemistry 9 + physics 9 (the two files we just copied)
|
||
INSERT INTO textbooks (slug, subject, grade, title, author, description, html_path, para_count, color, sort_order) VALUES
|
||
('chemistry-9', 'chemistry', 9, 'Химия — 9 класс', 'Шиманович Е. Я.',
|
||
'Полный курс химии за 9 класс. §1–60: строение атома, химическая связь, классы соединений, ОВР, металлы и их соединения, электролиз.',
|
||
'chemistry_9.html', 60, 'amber', 1),
|
||
('physics-9', 'physics', 9, 'Физика — 9 класс', 'Исаченкова Л. А.',
|
||
'Полный курс физики за 9 класс: §1–38. Механика, кинематика, динамика, статика, законы сохранения, импульс, работа и энергия.',
|
||
'physics_9.html', 38, 'blue', 2);
|