diff --git a/.env.example b/.env.example index 448397e..0437563 100644 --- a/.env.example +++ b/.env.example @@ -1,3 +1,12 @@ ADMIN_USERNAME=admin ADMIN_PASSWORD=сложный-пароль-админки -DB_PASSWORD=случайная-длинная-строка \ No newline at end of file +DB_PASSWORD=случайная-длинная-строка + +# Hugging Face token (нужен для закрытых/приватных репозиториев моделей) +HUGGINGFACE_TOKEN= +# Имя GGUF-файла модели для text-corrector (скачивается с Hugging Face, если отсутствует) +AI_MODEL=qwen2.5-1.5b-instruct-q4_k_m.gguf +# Репозиторий Hugging Face, откуда скачивается модель +AI_MODEL_REPO=Qwen/Qwen2.5-1.5B-Instruct-GGUF +# Промпт по умолчанию для автоисправления текстов (переопределяет встроенный, если в настройках не сохранён свой) +AI_PROMPT=Ты — редактор текстов. Исправь ТОЛЬКО грамматические, орфографические и пунктуационные ошибки в тексте. Приведи к правильному регистру буквы. НЕ меняй слова, структуру предложений, стиль или смысл текста. Верни ТОЛЬКО исправленный текст без пояснений. \ No newline at end of file diff --git a/db/init.sql b/db/init.sql index 932dd0f..f593e9e 100644 --- a/db/init.sql +++ b/db/init.sql @@ -54,10 +54,18 @@ CREATE TABLE IF NOT EXISTS settings ( INSERT INTO settings (key, value) VALUES ('spam_interval_min', '30') ON CONFLICT (key) DO NOTHING; -INSERT INTO settings (key, value) VALUES ('ai_prompt', 'Ты — редактор текстов для педагогического журнала. Исправь грамматические, орфографические и пунктуационные ошибки. Сохрани смысл и стиль. Верни ТОЛЬКО исправленный текст, без пояснений.') +INSERT INTO settings (key, value) VALUES ('ai_prompt', 'Ты — редактор текстов. Исправь ТОЛЬКО грамматические, орфографические и пунктуационные ошибки в тексте. Приведи к правильному регистру буквы. НЕ меняй слова, структуру предложений, стиль или смысл текста. Верни ТОЛЬКО исправленный текст без пояснений.') ON CONFLICT (key) DO NOTHING; INSERT INTO settings (key, value) VALUES ('ai_autocheck_enabled', 'true') ON CONFLICT (key) DO NOTHING; +INSERT INTO settings (key, value) VALUES ('share_show_student_message', 'false') +ON CONFLICT (key) DO NOTHING; +INSERT INTO settings (key, value) VALUES ('share_show_entry_date', 'false') +ON CONFLICT (key) DO NOTHING; +INSERT INTO settings (key, value) VALUES ('share_show_student_names', 'true') +ON CONFLICT (key) DO NOTHING; +INSERT INTO settings (key, value) VALUES ('share_show_group_photos', 'true') +ON CONFLICT (key) DO NOTHING; CREATE TABLE IF NOT EXISTS share_links ( id SERIAL PRIMARY KEY, @@ -67,11 +75,14 @@ CREATE TABLE IF NOT EXISTS share_links ( student_name VARCHAR(150), date_from DATE, date_to DATE, - anonymize_names BOOLEAN DEFAULT false, + show_student_names BOOLEAN, expires_at TIMESTAMPTZ, access_password_hash VARCHAR(255), message TEXT, link_url VARCHAR(500), + show_student_message BOOLEAN, + show_entry_date BOOLEAN, + show_group_photos BOOLEAN, created_at TIMESTAMPTZ DEFAULT now() ); diff --git a/db/migration.sql b/db/migration.sql index 45d1852..941545a 100644 --- a/db/migration.sql +++ b/db/migration.sql @@ -13,8 +13,14 @@ CREATE TABLE IF NOT EXISTS settings ( INSERT INTO settings (key, value) VALUES ('spam_interval_min', '30') ON CONFLICT (key) DO NOTHING; -INSERT INTO settings (key, value) VALUES ('ai_prompt', 'Ты — редактор текстов для педагогического журнала. Исправь грамматические, орфографические и пунктуационные ошибки. Сохрани смысл и стиль. Верни ТОЛЬКО исправленный текст, без пояснений.') +INSERT INTO settings (key, value) VALUES ('ai_prompt', 'Ты — редактор текстов. Исправь ТОЛЬКО грамматические, орфографические и пунктуационные ошибки в тексте. Приведи к правильному регистру буквы. НЕ меняй слова, структуру предложений, стиль или смысл текста. Верни ТОЛЬКО исправленный текст без пояснений.') ON CONFLICT (key) DO NOTHING; +UPDATE settings +SET value = 'Ты — редактор текстов. Исправь ТОЛЬКО грамматические, орфографические и пунктуационные ошибки в тексте. Приведи к правильному регистру буквы. НЕ меняй слова, структуру предложений, стиль или смысл текста. Верни ТОЛЬКО исправленный текст без пояснений.' +WHERE key = 'ai_prompt' AND value IN ( + 'Ты — редактор текстов для педагогического журнала. Исправь грамматические, орфографические и пунктуационные ошибки. Сохрани смысл и стиль. Верни ТОЛЬКО исправленный текст, без пояснений.', + 'Ты — редактор текстов. Исправь ошибки. Верни ТОЛЬКО исправленный текст.' +); CREATE TABLE IF NOT EXISTS share_links ( id SERIAL PRIMARY KEY, @@ -29,6 +35,18 @@ CREATE TABLE IF NOT EXISTS share_links ( ALTER TABLE share_links ADD COLUMN IF NOT EXISTS message TEXT; ALTER TABLE share_links ADD COLUMN IF NOT EXISTS link_url VARCHAR(500); +ALTER TABLE share_links ADD COLUMN IF NOT EXISTS show_student_message BOOLEAN; +ALTER TABLE share_links ADD COLUMN IF NOT EXISTS show_entry_date BOOLEAN; +ALTER TABLE share_links ADD COLUMN IF NOT EXISTS show_group_photos BOOLEAN; + +DO $$ +BEGIN + IF EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'share_links' AND column_name = 'anonymize_names') THEN + ALTER TABLE share_links ADD COLUMN IF NOT EXISTS show_student_names BOOLEAN; + UPDATE share_links SET show_student_names = (NOT anonymize_names) WHERE anonymize_names IS NOT NULL; + ALTER TABLE share_links DROP COLUMN anonymize_names; + END IF; +END $$; DO $$ BEGIN @@ -76,6 +94,16 @@ CREATE INDEX IF NOT EXISTS idx_entries_ai_pending ON entries(id) WHERE ai_status INSERT INTO settings (key, value) VALUES ('ai_autocheck_enabled', 'true') ON CONFLICT (key) DO NOTHING; +INSERT INTO settings (key, value) VALUES ('share_show_student_message', 'false') +ON CONFLICT (key) DO NOTHING; +INSERT INTO settings (key, value) VALUES ('share_show_entry_date', 'false') +ON CONFLICT (key) DO NOTHING; +INSERT INTO settings (key, value) VALUES ('share_show_student_names', 'true') +ON CONFLICT (key) DO NOTHING; +DELETE FROM settings WHERE key = 'share_anonymize_names'; +INSERT INTO settings (key, value) VALUES ('share_show_group_photos', 'true') +ON CONFLICT (key) DO NOTHING; + DO $$ BEGIN IF NOT EXISTS (SELECT 1 FROM settings WHERE key = 'ai_autocheck_migrated') THEN diff --git a/db/migration_share_links.sql b/db/migration_share_links.sql index 269dae1..212a1e7 100644 --- a/db/migration_share_links.sql +++ b/db/migration_share_links.sql @@ -18,4 +18,19 @@ CREATE INDEX IF NOT EXISTS idx_share_links_expires_at ON share_links(expires_at) -- 6. Add public message and external link shown on the share page ALTER TABLE share_links ADD COLUMN IF NOT EXISTS message TEXT; -ALTER TABLE share_links ADD COLUMN IF NOT EXISTS link_url VARCHAR(500); \ No newline at end of file +ALTER TABLE share_links ADD COLUMN IF NOT EXISTS link_url VARCHAR(500); + +-- 7. Per-link visibility overrides (NULL = fall back to global settings) +ALTER TABLE share_links ADD COLUMN IF NOT EXISTS show_student_message BOOLEAN; +ALTER TABLE share_links ADD COLUMN IF NOT EXISTS show_entry_date BOOLEAN; +ALTER TABLE share_links ADD COLUMN IF NOT EXISTS show_group_photos BOOLEAN; + +-- 8. Replace anonymize_names with positive show_student_names (NULL = inherit global setting) +DO $$ +BEGIN + IF EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'share_links' AND column_name = 'anonymize_names') THEN + ALTER TABLE share_links ADD COLUMN IF NOT EXISTS show_student_names BOOLEAN; + UPDATE share_links SET show_student_names = (NOT anonymize_names) WHERE anonymize_names IS NOT NULL; + ALTER TABLE share_links DROP COLUMN anonymize_names; + END IF; +END $$; \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index 263ac0a..8bb4dad 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -29,6 +29,8 @@ services: DATABASE_URL: postgres://app:${DB_PASSWORD}@db:5432/whereldo ADMIN_PASSWORD: ${ADMIN_PASSWORD} ADMIN_USERNAME: ${ADMIN_USERNAME:-admin} + AI_MODEL: ${AI_MODEL:-qwen2.5-1.5b-instruct-q4_k_m.gguf} + AI_PROMPT: ${AI_PROMPT:-} NODE_ENV: production TZ: Europe/Moscow depends_on: @@ -65,28 +67,20 @@ services: container_name: text-corrector restart: unless-stopped + entrypoint: ["/bin/sh", "/start-text-corrector.sh"] + + environment: + AI_MODEL: ${AI_MODEL:-qwen2.5-1.5b-instruct-q4_k_m.gguf} + AI_MODEL_REPO: ${AI_MODEL_REPO:-Qwen/Qwen2.5-1.5B-Instruct-GGUF} + HUGGINGFACE_TOKEN: ${HUGGINGFACE_TOKEN:-} + volumes: - ./models:/models + - ./start-text-corrector.sh:/start-text-corrector.sh:ro ports: - "8080:8080" - command: - - -m - - /models/qwen2.5-1.5b-instruct-q4_k_m.gguf - - --host - - 0.0.0.0 - - --port - - "8080" - - -c - - "4096" - - -n - - "256" - - -t - - "8" - - --temp - - "0.1" - diff --git a/public/admin.css b/public/admin.css index d2ef58b..4654ff4 100644 --- a/public/admin.css +++ b/public/admin.css @@ -287,7 +287,7 @@ body{font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;b .bar:hover{opacity:1} .bar.today{opacity:1} .bar-day{font-size:.62rem;color:var(--muted);white-space:nowrap} -.recent{display:flex;flex-direction:column;gap:2px} +.recent{display:grid;grid-template-columns:repeat(2,1fr);gap:2px 16px} .recent-item{display:flex;align-items:center;gap:12px;padding:8px 6px;border-radius:10px;transition:background .15s} .recent-item:hover{background:var(--bg)} .recent-item img{width:44px;height:44px;border-radius:8px;object-fit:cover;flex-shrink:0;cursor:pointer} @@ -321,11 +321,11 @@ body{font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;b .stat .label a{color:var(--accent);text-decoration:none;font-weight:600} .stat .label a:hover{text-decoration:underline} @media(max-width:1100px){.dash-grid{grid-template-columns:1fr}} -@media(max-width:640px){.photos-grid-dash{grid-template-columns:repeat(2,1fr)}} +@media(max-width:640px){.photos-grid-dash{grid-template-columns:repeat(2,1fr)}.recent{grid-template-columns:1fr}} /* --- System Info Dashboard --- */ .sys-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));gap:12px} @media(max-width:480px){.sys-grid{grid-template-columns:1fr;gap:10px}} -.sys-card{background:var(--bg);border:1px solid var(--border);border-radius:12px;padding:16px;display:flex;flex-direction:column;gap:8px;min-width:0} +.sys-card{background:var(--card);border:1px solid var(--border);border-radius:12px;padding:16px;display:flex;flex-direction:column;gap:8px;min-width:0} .sys-card.loading{color:var(--muted);justify-content:center;align-items:center;min-height:80px} .sys-card.err{color:#ef4444} .sys-title{font-size:.75rem;font-weight:700;color:var(--muted);text-transform:uppercase;letter-spacing:.05em;margin-bottom:4px;padding-bottom:8px;border-bottom:1px solid var(--border)} diff --git a/public/journal.html b/public/journal.html index fe26598..ace249a 100644 --- a/public/journal.html +++ b/public/journal.html @@ -129,12 +129,30 @@ -
Управление видимостью элементов на публичных страницах записей.
+