Initial commit: AI-фоторедактор (Codex-редактирование, ComfyUI upscale, HEIC, история версий, Docker, Gitea Actions)

This commit is contained in:
2026-08-25 21:28:55 +07:00
commit fc74c8f543
13 changed files with 4628 additions and 0 deletions

229
public/index.html Normal file
View File

@@ -0,0 +1,229 @@
<!doctype html>
<html lang="ru">
<head>
<meta charset="utf-8">
<meta
name="viewport"
content="width=device-width, initial-scale=1"
>
<meta
name="description"
content="Локальный редактор фотографий по текстовому промпту с увеличением разрешения."
>
<title>Кадр — AI-фоторедактор</title>
<link
rel="icon"
href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 64 64'%3E%3Crect width='64' height='64' rx='16' fill='%23202321'/%3E%3Ctext x='32' y='45' font-size='38' font-weight='bold' text-anchor='middle' fill='%23ffffff' font-family='sans-serif'%3E%D0%9A%3C/text%3E%3C/svg%3E"
>
<link rel="stylesheet" href="/style.css?v=7">
</head>
<body>
<header class="topbar">
<a class="brand" href="/" aria-label="Кадр, главная">
<span class="brand-mark" aria-hidden="true">К</span>
<span class="brand-name">Кадр</span>
</a>
<div
id="health-status"
class="health-status health-loading"
role="status"
aria-live="polite"
>
<span class="health-dot" aria-hidden="true"></span>
<span id="health-text">Проверяем сервер обработки…</span>
</div>
</header>
<main class="editor-layout">
<section class="control-panel" aria-labelledby="page-title">
<div class="intro">
<p class="eyebrow">Локальная AI-студия</p>
<h1 id="page-title">Меняйте кадр словами.</h1>
<p class="lead">
Загрузите фотографию, опишите желаемое изменение или увеличьте
разрешение одним нажатием.
</p>
</div>
<div class="control-stack">
<div class="field-group">
<span class="field-label">Фотография</span>
<div
id="drop-zone"
class="drop-zone"
role="button"
tabindex="0"
aria-label="Выбрать или перетащить фотографию"
>
<input
id="photo-input"
type="file"
accept="image/jpeg,image/png,image/webp,image/heic,image/heif,.heic,.heif"
hidden
>
<span class="upload-symbol" aria-hidden="true">+</span>
<span class="drop-copy">
<strong id="drop-title">Перетащите фото сюда</strong>
<span id="file-meta">
или нажмите, чтобы выбрать JPEG, PNG или WebP
</span>
</span>
<span class="choose-chip">Выбрать</span>
</div>
</div>
<div class="field-group">
<label class="field-label" for="prompt">Промпт</label>
<textarea
id="prompt"
rows="4"
maxlength="1000"
placeholder="Например: сделай закат, фотореалистично"
></textarea>
<div class="field-foot">
<span>Опишите свет, настроение и нужные детали.</span>
<span id="prompt-counter">0 / 1000</span>
</div>
</div>
<div class="actions">
<button
id="edit-button"
class="button button-primary"
type="button"
disabled
>
<span>Редактировать</span>
<span class="button-arrow" aria-hidden="true">→</span>
</button>
<button
id="upscale-button"
class="button button-secondary"
type="button"
disabled
>
<span class="spark" aria-hidden="true">✦</span>
<span>Увеличить разрешение</span>
</button>
</div>
<p class="privacy-note">
Фото передаётся только вашему локальному серверу ComfyUI.
</p>
</div>
</section>
<section
id="workspace"
class="workspace"
aria-labelledby="workspace-title"
>
<div class="workspace-head">
<div>
<p class="workspace-kicker">Предпросмотр</p>
<h2 id="workspace-title">До и после</h2>
</div>
<span class="local-badge">LAN · локально</span>
</div>
<div class="comparison">
<figure class="photo-frame">
<figcaption>Исходник</figcaption>
<div class="image-stage">
<img
id="source-image"
alt="Выбранная исходная фотография"
hidden
>
<div id="source-placeholder" class="placeholder">
<span class="placeholder-frame" aria-hidden="true"></span>
<strong>Здесь появится фотография</strong>
<span>Выберите файл слева, чтобы начать</span>
</div>
</div>
</figure>
<figure class="photo-frame result-frame">
<figcaption>
<span>Результат</span>
<span id="result-label" class="result-kind"></span>
</figcaption>
<div class="image-stage">
<img
id="result-image"
alt="Обработанная фотография"
hidden
>
<div id="result-placeholder" class="placeholder">
<span class="placeholder-spark" aria-hidden="true">✦</span>
<strong>Результат появится здесь</strong>
<span>Редактирование через Codex — 1–3 минуты, апскейл — несколько секунд</span>
</div>
</div>
</figure>
</div>
<div
id="job-status"
class="job-status"
role="status"
aria-live="polite"
hidden
>
<div class="status-row">
<span class="status-spinner" aria-hidden="true"></span>
<span id="job-status-text"></span>
</div>
<div class="progress-track" aria-hidden="true">
<span class="progress-bar"></span>
</div>
</div>
<div class="result-actions">
<a
id="download-link"
class="download-link"
href="#"
download
hidden
>
Скачать результат
<span aria-hidden="true">↓</span>
</a>
</div>
<section class="history-section" aria-labelledby="history-title">
<div class="history-head">
<h2 id="history-title">История версий</h2>
<span class="history-hint">
Нажмите на версию, чтобы вернуться к ней и продолжить правки
</span>
</div>
<div id="history-list" class="history-list">
<div id="history-empty" class="history-empty">
Пока пусто — загрузите фото, и все версии появятся здесь
</div>
</div>
</section>
</section>
</main>
<noscript>
<div class="noscript">
Для работы редактора необходимо включить JavaScript.
</div>
</noscript>
<script src="/app.js?v=7" defer></script>
</body>
</html>