context-scaling / static /template.html
heheyas's picture
Switch to FastAPI + SPA + diffusers DiT
b5f60e1
Raw
History Blame Contribute Delete
11.9 kB
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Structured Prompt Studio</title>
<style>
%%CSS%%
</style>
</head>
<body data-generated="%%GENERATION_TIME%%">
<div class="app">
<!-- ==================== History Bar ==================== -->
<div class="history-bar">
<div class="history-title">History</div>
<div class="history-scroll" id="historyScroll">
<div class="history-empty" id="historyEmpty">No history yet</div>
</div>
<button class="tool-btn history-clear-btn" id="historyClearBtn" onclick="clearHistory()" title="Clear history" style="display:none;">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="3 6 5 6 21 6"/><path d="M19 6v14a2 2 0 01-2 2H7a2 2 0 01-2-2V6m3 0V4a2 2 0 012-2h4a2 2 0 012 2v2"/></svg>
</button>
</div>
<!-- ==================== Workspace (CSS Grid) ==================== -->
<div class="workspace">
<!-- Image Panel (row 1, col 1) -->
<div class="panel image-panel" id="imagePanel">
<div class="panel-toolbar">
<span class="panel-label">Image</span>
<div class="panel-actions">
<button class="tool-btn" onclick="triggerImageUpload()" title="Import image">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4"/><polyline points="17 8 12 3 7 8"/><line x1="12" y1="3" x2="12" y2="15"/></svg>
</button>
<button class="tool-btn" id="btnBboxShow" onclick="showAllBboxes()" title="Show all bboxes" style="display:none;">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/><circle cx="12" cy="12" r="3"/></svg>
</button>
<button class="tool-btn" id="btnBboxHide" onclick="hideAllBboxes()" title="Hide all bboxes" style="display:none;">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M17.94 17.94A10.07 10.07 0 0112 20c-7 0-11-8-11-8a18.45 18.45 0 015.06-5.94M9.9 4.24A9.12 9.12 0 0112 4c7 0 11 8 11 8a18.5 18.5 0 01-2.16 3.19m-6.72-1.07a3 3 0 11-4.24-4.24"/><line x1="1" y1="1" x2="23" y2="23"/></svg>
</button>
<button class="tool-btn" id="btnImageZoom" onclick="handleImageEnlarge()" title="Zoom" style="display:none;">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/><line x1="11" y1="8" x2="11" y2="14"/><line x1="8" y1="11" x2="14" y2="11"/></svg>
</button>
<button class="tool-btn" id="btnImageDelete" onclick="handleImageDelete()" title="Delete image" style="display:none;">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="3 6 5 6 21 6"/><path d="M19 6v14a2 2 0 01-2 2H7a2 2 0 01-2-2V6m3 0V4a2 2 0 012-2h4a2 2 0 012 2v2"/></svg>
</button>
</div>
</div>
<div class="image-area" id="imageArea">
<div class="dropzone" id="dropzone" onclick="triggerImageUpload()">
<div class="dropzone-icon">πŸ–ΌοΈ</div>
<div class="dropzone-text">Drop an image here or click to upload</div>
</div>
<div class="image-display" id="imageDisplay" style="display:none;">
<img id="displayImage" onclick="handleImageClick(event)" title="Click to select a bbox" />
<div class="bbox-container" id="bboxContainer"></div>
</div>
</div>
<input type="file" id="imageFileInput" accept="image/*" onchange="handleImageFileSelected(event)" style="display:none;">
</div>
<!-- Structured Prompt Panel (row 1, col 2) -->
<div class="panel sp-panel" id="spPanel">
<div class="panel-toolbar">
<span class="panel-label">Structured Prompt</span>
<div class="panel-actions">
<button class="tool-btn" id="btnSPRaw" onclick="toggleSPRawMode()" title="Toggle raw JSON">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="16 18 22 12 16 6"/><polyline points="8 6 2 12 8 18"/></svg>
</button>
<button class="tool-btn" onclick="triggerSPImport()" title="Import JSON">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4"/><polyline points="17 8 12 3 7 8"/><line x1="12" y1="3" x2="12" y2="15"/></svg>
</button>
<button class="tool-btn" id="btnSPUndo" onclick="handleSPUndo()" title="Undo" style="display:none;">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="1 4 1 10 7 10"/><path d="M3.51 15a9 9 0 102.13-9.36L1 10"/></svg>
</button>
<button class="tool-btn" id="btnSPDelete" onclick="handleSPDelete()" title="Clear" style="display:none;">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="3 6 5 6 21 6"/><path d="M19 6v14a2 2 0 01-2 2H7a2 2 0 01-2-2V6m3 0V4a2 2 0 012-2h4a2 2 0 012 2v2"/></svg>
</button>
</div>
</div>
<div class="sp-area" id="spArea">
<div class="sp-empty" id="spEmpty">
<div class="sp-empty-icon">πŸ“‹</div>
<div>Structured Prompt is empty</div>
<div class="sp-empty-hint">Generate one with the button, or paste / import JSON</div>
</div>
<div class="sp-structured" id="spStructured" style="display:none;"></div>
<textarea id="spTextarea" style="display:none;" spellcheck="false"
placeholder="Paste Structured Prompt JSON here..."></textarea>
</div>
<input type="file" id="spFileInput" accept=".json,.txt" onchange="handleSPFileSelected(event)" style="display:none;">
</div>
<!-- Params Bar (row 2, col 1) -->
<div class="panel params-bar">
<div class="params-label">Params</div>
<div class="params-group">
<label>CFG</label>
<input type="number" id="paramCfgScale" value="4.0" min="0" max="20" step="0.1">
</div>
<div class="params-group">
<label>Steps</label>
<input type="number" id="paramSteps" value="25" min="1" max="100" step="1">
</div>
<div class="params-spacer"></div>
<div class="params-group">
<label>H</label>
<input type="number" id="paramHeight" value="1024" min="64" max="4096" step="32">
</div>
<div class="params-group">
<label>W</label>
<input type="number" id="paramWidth" value="1024" min="64" max="4096" step="32">
</div>
<div class="params-group">
<label>Seed</label>
<input type="number" id="paramSeed" value="42" min="-1" max="999999">
</div>
</div>
<!-- Generate SP Button (row 2, col 2) -->
<button class="action-btn gen-sp-btn" id="genSPBtn" onclick="handleGenerateSP()">
Generate SP
</button>
<!-- User Prompt Bar (row 3, col 1) -->
<div class="panel prompt-bar">
<div class="prompt-label">User Prompt</div>
<textarea id="userPromptInput" placeholder="Describe the image you want..." rows="1"></textarea>
</div>
<!-- Generate Image Button (row 3, col 2) -->
<button class="action-btn gen-image-btn" id="genImageBtn" onclick="handleGenerateImage()">
Generate Image
</button>
</div>
</div>
<!-- ==================== Image Enlarge Modal ==================== -->
<div class="modal-overlay" id="imageModal" onclick="closeImageModal()">
<div class="modal-image-container" id="modalImageContainer" onclick="event.stopPropagation()">
<img id="modalImage" class="modal-image" />
</div>
<button class="modal-close-btn" onclick="closeImageModal()">βœ•</button>
</div>
<!-- ==================== Diff Confirmation Dialog ==================== -->
<div class="modal-overlay" id="diffModal">
<div class="diff-dialog" onclick="event.stopPropagation()">
<div class="diff-header">
<span>Review changes</span>
<button class="modal-close-btn-sm" onclick="cancelGeneration()">βœ•</button>
</div>
<div class="diff-content" id="diffContent"></div>
<div class="diff-actions">
<button class="action-btn cancel-btn" onclick="cancelGeneration()">Cancel</button>
<button class="action-btn confirm-btn" onclick="confirmGeneration()">Confirm &amp; generate</button>
</div>
</div>
</div>
<!-- ==================== History Detail Modal ==================== -->
<div class="modal-overlay" id="historyModal" onclick="closeHistoryModal()">
<div class="history-detail" onclick="event.stopPropagation()">
<div class="history-detail-header">
<span>History entry</span>
<button class="modal-close-btn-sm" onclick="closeHistoryModal()">βœ•</button>
</div>
<div class="history-detail-body" id="historyDetailBody"></div>
<div class="history-detail-footer">
<button class="action-btn restore-part-btn" onclick="restoreImageFromHistory()" title="Restore image only">πŸ–ΌοΈ Image</button>
<button class="action-btn restore-part-btn" onclick="restorePromptFromHistory()" title="Restore User Prompt &amp; SP">πŸ“ Prompt</button>
<button class="action-btn restore-part-btn" onclick="restoreParamsFromHistory()" title="Restore params only">βš™οΈ Params</button>
<button class="action-btn restore-btn" onclick="restoreFromHistory()">Restore all</button>
</div>
</div>
</div>
<!-- ==================== Toast Container ==================== -->
<div class="toast-container" id="toastContainer"></div>
<!-- ==================== Add Field Dropdown ==================== -->
<div class="sp-add-dropdown" id="spAddDropdown" style="display:none;"></div>
<!-- ==================== Scripts ==================== -->
<script src="https://cdn.jsdelivr.net/npm/jsonrepair@3/lib/umd/jsonrepair.min.js"></script>
<script>
%%SCRIPT%%
</script>
</body>
</html>