300 lines
11 KiB
HTML
300 lines
11 KiB
HTML
<!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=14">
|
||
</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 class="topbar-right">
|
||
<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>
|
||
<button id="logout-button" class="logout-button" type="button" hidden>
|
||
Выйти
|
||
</button>
|
||
</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"
|
||
multiple
|
||
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">
|
||
<span class="field-label">Референс <span class="field-label-hint">(необязательно)</span></span>
|
||
<div class="reference-actions">
|
||
<button id="reference-upload-button" class="button button-secondary button-small" type="button">Загрузить файл</button>
|
||
<select id="reference-history-select" class="reference-select" aria-label="Выбрать референс из истории">
|
||
<option value="">— из истории —</option>
|
||
</select>
|
||
<button id="reference-clear-button" class="button button-secondary button-small" type="button">Очистить</button>
|
||
</div>
|
||
<input id="reference-file-input" type="file" accept="image/jpeg,image/png,image/webp" hidden>
|
||
<div id="reference-preview" class="reference-preview" hidden>
|
||
<canvas id="reference-canvas" class="reference-canvas"></canvas>
|
||
<div class="reference-preview-foot">
|
||
<span id="reference-region-info">Область не выбрана — потяните по превью</span>
|
||
<button id="reference-region-reset" class="button button-secondary button-small" type="button">Сбросить область</button>
|
||
</div>
|
||
</div>
|
||
<p id="reference-note" class="reference-note" hidden></p>
|
||
</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>
|
||
|
||
<button id="suggest-button" class="button button-secondary button-suggest" type="button" disabled>💡 Предложить промпт</button>
|
||
<div id="suggest-panel" class="suggest-panel" hidden>
|
||
<p class="suggest-section-title">Из истории</p>
|
||
<div id="suggest-history-chips" class="suggest-chips"></div>
|
||
<div class="suggest-actions">
|
||
<button id="suggest-codex-button" class="button button-secondary button-small" type="button" disabled>Спросить Codex</button>
|
||
<span id="suggest-codex-status" class="suggest-status" role="status" aria-live="polite"></span>
|
||
</div>
|
||
<p class="suggest-section-title">Варианты от Codex</p>
|
||
<div id="suggest-codex-chips" class="suggest-chips"></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>
|
||
<div class="workspace-head-actions">
|
||
<a
|
||
id="download-current"
|
||
class="download-current"
|
||
href="#"
|
||
download
|
||
hidden
|
||
>
|
||
Скачать
|
||
<span aria-hidden="true">↓</span>
|
||
</a>
|
||
<span class="local-badge">LAN · локально</span>
|
||
</div>
|
||
</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>
|
||
|
||
<div id="auth-overlay" class="auth-overlay" role="dialog" aria-modal="true" aria-labelledby="auth-title">
|
||
<form id="login-form" class="auth-card" novalidate>
|
||
<p class="auth-eyebrow">Закрытый доступ</p>
|
||
<h1 id="auth-title">Вход в редактор</h1>
|
||
<p class="auth-lead">Редактор доступен только владельцу. Войдите, чтобы продолжить.</p>
|
||
<div class="auth-field">
|
||
<label class="field-label" for="login-username">Логин</label>
|
||
<input id="login-username" name="username" type="text" autocomplete="username" autofocus required>
|
||
</div>
|
||
<div class="auth-field">
|
||
<label class="field-label" for="login-password">Пароль</label>
|
||
<input id="login-password" name="password" type="password" autocomplete="current-password" required>
|
||
</div>
|
||
<p id="login-error" class="auth-error" hidden></p>
|
||
<button id="login-submit" class="button button-primary auth-submit" type="submit">
|
||
<span>Войти</span>
|
||
</button>
|
||
</form>
|
||
</div>
|
||
|
||
<noscript>
|
||
<div class="noscript">
|
||
Для работы редактора необходимо включить JavaScript.
|
||
</div>
|
||
</noscript>
|
||
|
||
<script type="module" src="/js/main.js?v=13"></script>
|
||
</body>
|
||
</html>
|