Update templates/index.html
Browse files- templates/index.html +159 -76
templates/index.html
CHANGED
|
@@ -2,108 +2,191 @@
|
|
| 2 |
<html lang="fa" dir="rtl">
|
| 3 |
<head>
|
| 4 |
<meta charset="UTF-8">
|
| 5 |
-
<
|
| 6 |
-
<title>استودیو تصویر هوش مصنوعی</title>
|
| 7 |
<link href="https://fonts.googleapis.com/css2?family=Vazirmatn:wght@400;600;800&display=swap" rel="stylesheet">
|
| 8 |
<style>
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 12 |
.form-group { margin-bottom: 20px; }
|
| 13 |
-
label { display: block;
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
.
|
| 17 |
-
.
|
| 18 |
-
.
|
| 19 |
-
|
| 20 |
-
|
| 21 |
-
|
| 22 |
-
|
| 23 |
-
|
| 24 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 25 |
</style>
|
| 26 |
</head>
|
| 27 |
-
<body>
|
| 28 |
-
<div class="container">
|
| 29 |
-
<h2>🎨 استودیو تصویر هوش مصنوعی</h2>
|
| 30 |
-
|
| 31 |
-
<div class="form-group">
|
| 32 |
-
<label>دستور ساخت تصویر (Prompt)</label>
|
| 33 |
-
<textarea id="prompt" rows="4" placeholder="مثال: A futuristic cyberpunk city, glowing neon lights..."></textarea>
|
| 34 |
-
</div>
|
| 35 |
|
| 36 |
-
|
| 37 |
-
|
| 38 |
-
<div class="
|
| 39 |
-
<
|
| 40 |
-
|
| 41 |
-
|
| 42 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 43 |
</div>
|
| 44 |
</div>
|
| 45 |
-
|
| 46 |
-
<button id="btn-submit" class="main-btn" onclick="generateImage()">🚀 ساخت تصویر</button>
|
| 47 |
-
|
| 48 |
-
<div id="status-box"></div>
|
| 49 |
-
|
| 50 |
-
<div id="result-container">
|
| 51 |
-
<h3 style="color: #38A169; margin-bottom: 15px;">🎉 تصویر شما آماده است!</h3>
|
| 52 |
-
<img id="generated-image" src="" alt="AI Generated Image">
|
| 53 |
-
</div>
|
| 54 |
</div>
|
| 55 |
|
| 56 |
<script>
|
| 57 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 58 |
|
| 59 |
-
|
| 60 |
-
|
| 61 |
-
btn.
|
| 62 |
-
|
| 63 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 64 |
}
|
| 65 |
|
| 66 |
-
|
| 67 |
-
const prompt = document.getElementById('
|
| 68 |
-
if
|
| 69 |
-
|
| 70 |
-
|
| 71 |
-
|
| 72 |
-
|
| 73 |
-
|
| 74 |
-
statusBox.style.display = 'block';
|
| 75 |
-
statusBox.innerHTML = 'در حال ارتباط با سرور پردازش... ⏳';
|
| 76 |
|
| 77 |
try {
|
|
|
|
| 78 |
const res = await fetch('/api/generate', {
|
| 79 |
-
method: 'POST',
|
| 80 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 81 |
});
|
|
|
|
| 82 |
const data = await res.json();
|
| 83 |
|
| 84 |
if (data.status === 'success') {
|
| 85 |
-
|
| 86 |
-
|
|
|
|
| 87 |
} else {
|
| 88 |
-
|
| 89 |
-
|
|
|
|
| 90 |
}
|
| 91 |
} catch (e) {
|
| 92 |
-
|
| 93 |
-
|
|
|
|
| 94 |
}
|
| 95 |
-
}
|
| 96 |
|
| 97 |
-
async function
|
| 98 |
-
|
| 99 |
-
|
| 100 |
-
|
| 101 |
-
|
| 102 |
-
|
| 103 |
-
|
| 104 |
-
|
| 105 |
-
|
| 106 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 107 |
}
|
| 108 |
}
|
| 109 |
</script>
|
|
|
|
| 2 |
<html lang="fa" dir="rtl">
|
| 3 |
<head>
|
| 4 |
<meta charset="UTF-8">
|
| 5 |
+
<title>مولد تصویر آلفا - Flux Pro</title>
|
|
|
|
| 6 |
<link href="https://fonts.googleapis.com/css2?family=Vazirmatn:wght@400;600;800&display=swap" rel="stylesheet">
|
| 7 |
<style>
|
| 8 |
+
/* دقیقاً همان CSS ارسالی شما */
|
| 9 |
+
:root {
|
| 10 |
+
--igadlm-alpha-color-primary: #5A67D8; --igadlm-alpha-color-primary-darker: #4C51BF;
|
| 11 |
+
--igadlm-alpha-color-secondary: #805AD5; --igadlm-alpha-color-secondary-darker: #6B46C1;
|
| 12 |
+
--igadlm-alpha-color-text: #1A202C; --igadlm-alpha-color-text-light: #4A5568;
|
| 13 |
+
--igadlm-alpha-color-text-muted: #718096; --igadlm-alpha-color-bg-card: #FFFFFF;
|
| 14 |
+
--igadlm-alpha-color-border: #CBD5E0; --igadlm-alpha-color-input-bg: #EDF2F7;
|
| 15 |
+
--igadlm-alpha-color-white: #FFFFFF; --igadlm-alpha-color-success: #38A169;
|
| 16 |
+
--igadlm-alpha-color-error: #E53E3E;
|
| 17 |
+
--igadlm-alpha-shadow-sm: 0 1px 3px 0 rgba(0,0,0,0.07);
|
| 18 |
+
--igadlm-alpha-shadow-md: 0 4px 8px -2px rgba(0,0,0,0.1);
|
| 19 |
+
--igadlm-alpha-shadow-lg: 0 10px 20px -5px rgba(0,0,0,0.1);
|
| 20 |
+
--igadlm-alpha-border-radius-md: 8px; --igadlm-alpha-border-radius-lg: 12px;
|
| 21 |
+
--igadlm-alpha-transition-speed: 0.25s;
|
| 22 |
+
}
|
| 23 |
+
body.standalone-igadlm-alpha-app { background-color: #f0f2f5; margin:0; padding:20px; display: flex; flex-direction: column; align-items: center; justify-content: center; min-height: 100vh;}
|
| 24 |
+
#imageGeneratorAppAlphaV2 { font-family: 'Vazirmatn', sans-serif; color: var(--igadlm-alpha-color-text); line-height: 1.6; direction: rtl; width: 100%; }
|
| 25 |
+
.app-content-wrapper { display: flex; justify-content: center; width: 100%; }
|
| 26 |
+
.app-content { width: 100%; max-width: 550px; padding: 0 15px; }
|
| 27 |
+
.app-header { text-align: center; margin-bottom: 30px; }
|
| 28 |
+
.app-header h1 { font-size: clamp(1.8em, 5.5vw, 2.3em); font-weight: 700; color: var(--igadlm-alpha-color-primary); margin-bottom: 8px; }
|
| 29 |
+
.app-header p { font-size: 0.95em; color: var(--igadlm-alpha-color-text-light); }
|
| 30 |
+
.form-section-card { background-color: var(--igadlm-alpha-color-bg-card); padding: 30px; border-radius: var(--igadlm-alpha-border-radius-lg); box-shadow: var(--igadlm-alpha-shadow-lg); border: 1px solid var(--igadlm-alpha-color-border); }
|
| 31 |
.form-group { margin-bottom: 20px; }
|
| 32 |
+
.form-group label { display: block; font-size: 0.85rem; color: var(--igadlm-alpha-color-text-light); margin-bottom: 6px; font-weight: 600; }
|
| 33 |
+
#imagePromptAlpha { width: 100%; padding: 10px 14px; border: 1px solid var(--igadlm-alpha-color-border); border-radius: var(--igadlm-alpha-border-radius-md); font-size: 0.9rem; background-color: var(--igadlm-alpha-color-input-bg); min-height: 60px; resize: vertical; }
|
| 34 |
+
#imagePromptAlpha:focus { outline: none; border-color: var(--igadlm-alpha-color-primary); background-color: var(--igadlm-alpha-color-white); }
|
| 35 |
+
.dimension-buttons-simple { display: grid; grid-template-columns: repeat(2, 1fr); gap: 10px; }
|
| 36 |
+
.dimension-button-simple { padding: 10px 8px; font-size: 0.9rem; font-weight: 500; border: 1px solid var(--igadlm-alpha-color-border); border-radius: var(--igadlm-alpha-border-radius-md); background-color: var(--igadlm-alpha-color-input-bg); cursor: pointer; text-align: center; }
|
| 37 |
+
.dimension-button-simple.selected { background: linear-gradient(60deg, var(--igadlm-alpha-color-primary) 0%, var(--igadlm-alpha-color-secondary) 100%); color: var(--igadlm-alpha-color-white); border-color: transparent; }
|
| 38 |
+
#generateBtnAlpha { display: flex; align-items: center; justify-content: center; gap: 8px; width: 100%; padding: 11px 16px; border-radius: var(--igadlm-alpha-border-radius-md); font-size: 0.95rem; font-weight: 600; cursor: pointer; background: linear-gradient(60deg, var(--igadlm-alpha-color-primary) 0%, var(--igadlm-alpha-color-secondary) 100%); color: white; border: none; margin-top: 12px; }
|
| 39 |
+
#generateBtnAlpha:disabled { background: #cbd5e0; cursor: not-allowed; }
|
| 40 |
+
#aiLoaderAlpha { display: none; flex-direction: column; align-items: center; margin: 20px auto 10px auto; }
|
| 41 |
+
.ai-loader-bar-container-inline { display: flex; justify-content: center; align-items: flex-end; height: 25px; }
|
| 42 |
+
.ai-loader-bar-inline { width: 5px; height: 5px; background-color: var(--igadlm-alpha-color-primary); border-radius: 2.5px; margin: 0 2.5px; animation: igadlmAlphaV2LoaderAnim 1.2s infinite ease-in-out; }
|
| 43 |
+
.ai-loader-bar-inline:nth-child(2) { animation-delay: 0.2s; background-color: var(--igadlm-alpha-color-secondary); }
|
| 44 |
+
.ai-loader-bar-inline:nth-child(3) { animation-delay: 0.4s; }
|
| 45 |
+
#statusAlphaText { text-align: center; font-size: 0.85em; color: var(--igadlm-alpha-color-text-muted); font-weight: 500; margin-top: 10px; min-height: 1.4em; }
|
| 46 |
+
#imageResultContainerAlpha { margin-top: 15px; text-align: center; display: none; }
|
| 47 |
+
#generatedImageAlpha { max-width: 100%; height: auto; border-radius: var(--igadlm-alpha-border-radius-md); border: 1px solid var(--igadlm-alpha-color-border); }
|
| 48 |
+
#downloadImageBtnAlpha { display: inline-flex; align-items: center; justify-content: center; width: 100%; padding: 11px 16px; border-radius: var(--igadlm-alpha-border-radius-md); margin-top: 10px; background-color: var(--igadlm-alpha-color-white); color: var(--igadlm-alpha-color-primary); border: 1px solid var(--igadlm-alpha-color-border); cursor: pointer; text-decoration: none; font-weight: bold;}
|
| 49 |
+
@keyframes igadlmAlphaV2LoaderAnim { 0%, 100% { transform: scaleY(0.5); opacity: 0.5; } 50% { transform: scaleY(1.5); opacity: 1; height: 15px; } }
|
| 50 |
</style>
|
| 51 |
</head>
|
| 52 |
+
<body class="standalone-igadlm-alpha-app">
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 53 |
|
| 54 |
+
<div id="imageGeneratorAppAlphaV2">
|
| 55 |
+
<div class="app-content-wrapper">
|
| 56 |
+
<div class="app-content">
|
| 57 |
+
<div class="app-header">
|
| 58 |
+
<h1>🖼️ مولد تصویر آلفا</h1>
|
| 59 |
+
<p><span style="color: #339966; font-weight: bold;">Flux Pro</span></p>
|
| 60 |
+
<p>ایده خود را به یک تصویر خلاقانه تبدیل کنید</p>
|
| 61 |
+
</div>
|
| 62 |
+
|
| 63 |
+
<div class="form-section-card" id="alphaFormSectionCard">
|
| 64 |
+
<div class="form-group">
|
| 65 |
+
<label for="imagePromptAlpha">ایده خود را بنویسید (به فارسی):</label>
|
| 66 |
+
<textarea id="imagePromptAlpha" rows="3" placeholder="مثال: یک قلعه باستانی بر فراز ابرها"></textarea>
|
| 67 |
+
</div>
|
| 68 |
+
|
| 69 |
+
<div class="form-group">
|
| 70 |
+
<label>اندازه تصویر (نسبت):</label>
|
| 71 |
+
<div class="dimension-buttons-simple" id="alphaDimensionButtons"></div>
|
| 72 |
+
</div>
|
| 73 |
+
|
| 74 |
+
<button id="generateBtnAlpha">🎨 ساخت تصویر</button>
|
| 75 |
+
|
| 76 |
+
<div class="ai-loader-inline" id="aiLoaderAlpha">
|
| 77 |
+
<div class="ai-loader-bar-container-inline">
|
| 78 |
+
<div class="ai-loader-bar-inline"></div>
|
| 79 |
+
<div class="ai-loader-bar-inline"></div>
|
| 80 |
+
<div class="ai-loader-bar-inline"></div>
|
| 81 |
+
</div>
|
| 82 |
+
</div>
|
| 83 |
+
|
| 84 |
+
<div id="statusAlphaText">وضعیت: آماده برای تولید تصویر.</div>
|
| 85 |
+
|
| 86 |
+
<div id="imageResultContainerAlpha">
|
| 87 |
+
<img id="generatedImageAlpha" alt="تصویر ایجاد شده" />
|
| 88 |
+
<a id="downloadImageBtnAlpha" href="#" download="flux_image.webp">📥 دانلود تصویر</a>
|
| 89 |
+
</div>
|
| 90 |
+
</div>
|
| 91 |
</div>
|
| 92 |
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 93 |
</div>
|
| 94 |
|
| 95 |
<script>
|
| 96 |
+
const dimensionsMap = {
|
| 97 |
+
"1:1": { w: 1024, h: 1024, text: "۱:۱ (مربع)" },
|
| 98 |
+
"16:9": { w: 1344, h: 768, text: "۱۶:۹ (افقی)" },
|
| 99 |
+
"9:16": { w: 768, h: 1344, text: "۹:۱۶ (عمودی)" },
|
| 100 |
+
"4:3": { w: 1152, h: 864, text: "۴:۳ (کلاسیک)" }
|
| 101 |
+
};
|
| 102 |
+
|
| 103 |
+
let selectedW = 1024, selectedH = 1024;
|
| 104 |
+
const btnContainer = document.getElementById('alphaDimensionButtons');
|
| 105 |
+
const statusText = document.getElementById('statusAlphaText');
|
| 106 |
+
const loader = document.getElementById('aiLoaderAlpha');
|
| 107 |
+
const genBtn = document.getElementById('generateBtnAlpha');
|
| 108 |
+
const resultContainer = document.getElementById('imageResultContainerAlpha');
|
| 109 |
+
const imgEl = document.getElementById('generatedImageAlpha');
|
| 110 |
+
const downloadBtn = document.getElementById('downloadImageBtnAlpha');
|
| 111 |
+
let pollTimer;
|
| 112 |
|
| 113 |
+
// ساخت دکمههای ابعاد
|
| 114 |
+
Object.keys(dimensionsMap).forEach((key, index) => {
|
| 115 |
+
const btn = document.createElement('button');
|
| 116 |
+
btn.className = 'dimension-button-simple' + (index === 0 ? ' selected' : '');
|
| 117 |
+
btn.textContent = dimensionsMap[key].text;
|
| 118 |
+
btn.onclick = () => {
|
| 119 |
+
document.querySelectorAll('.dimension-button-simple').forEach(b => b.classList.remove('selected'));
|
| 120 |
+
btn.classList.add('selected');
|
| 121 |
+
selectedW = dimensionsMap[key].w;
|
| 122 |
+
selectedH = dimensionsMap[key].h;
|
| 123 |
+
};
|
| 124 |
+
btnContainer.appendChild(btn);
|
| 125 |
+
});
|
| 126 |
+
|
| 127 |
+
function updateStatus(text, type='info') {
|
| 128 |
+
statusText.textContent = text;
|
| 129 |
+
statusText.style.color = type === 'error' ? 'var(--igadlm-alpha-color-error)' :
|
| 130 |
+
type === 'success' ? 'var(--igadlm-alpha-color-success)' : 'var(--igadlm-alpha-color-text-muted)';
|
| 131 |
}
|
| 132 |
|
| 133 |
+
genBtn.onclick = async () => {
|
| 134 |
+
const prompt = document.getElementById('imagePromptAlpha').value.trim();
|
| 135 |
+
if(!prompt) return updateStatus('لطفا ایده خود را بنویسید!', 'error');
|
| 136 |
+
|
| 137 |
+
genBtn.disabled = true;
|
| 138 |
+
resultContainer.style.display = 'none';
|
| 139 |
+
loader.style.display = 'flex';
|
| 140 |
+
updateStatus('در حال ترجمه متن به انگلیسی... (مرحله ۱ از ۳)');
|
|
|
|
|
|
|
| 141 |
|
| 142 |
try {
|
| 143 |
+
// ارسال به پایتون خودمان (پایتون هم ترجمه میکنه و هم میفرسته گیت هاب)
|
| 144 |
const res = await fetch('/api/generate', {
|
| 145 |
+
method: 'POST',
|
| 146 |
+
headers: {'Content-Type': 'application/json'},
|
| 147 |
+
body: JSON.stringify({
|
| 148 |
+
prompt: prompt,
|
| 149 |
+
width: selectedW,
|
| 150 |
+
height: selectedH,
|
| 151 |
+
action_name: "generate-flux" // نام اکشن برای گیت هاب
|
| 152 |
+
})
|
| 153 |
});
|
| 154 |
+
|
| 155 |
const data = await res.json();
|
| 156 |
|
| 157 |
if (data.status === 'success') {
|
| 158 |
+
updateStatus(`متن ترجمه شد: "${data.translated_prompt.substring(0, 25)}..."\nدر حال ساخت تصویر در سرور پردازشی... (مرحله ۲ از ۳)`);
|
| 159 |
+
// شروع به چک کردن نتیجه
|
| 160 |
+
pollTimer = setInterval(() => checkResult(data.run_id), 3000);
|
| 161 |
} else {
|
| 162 |
+
updateStatus('خطا در ارتباط با سرور پردازشی.', 'error');
|
| 163 |
+
genBtn.disabled = false;
|
| 164 |
+
loader.style.display = 'none';
|
| 165 |
}
|
| 166 |
} catch (e) {
|
| 167 |
+
updateStatus('خطای ارتباط با سرور.', 'error');
|
| 168 |
+
genBtn.disabled = false;
|
| 169 |
+
loader.style.display = 'none';
|
| 170 |
}
|
| 171 |
+
};
|
| 172 |
|
| 173 |
+
async function checkResult(run_id) {
|
| 174 |
+
try {
|
| 175 |
+
const res = await fetch(`/api/status/${run_id}`);
|
| 176 |
+
const data = await res.json();
|
| 177 |
+
|
| 178 |
+
if (data.status === 'ready') {
|
| 179 |
+
clearInterval(pollTimer);
|
| 180 |
+
loader.style.display = 'none';
|
| 181 |
+
updateStatus('تصویر با موفقیت ساخته شد! 🎉 (مرحله ۳ از ۳)', 'success');
|
| 182 |
+
|
| 183 |
+
imgEl.src = data.url;
|
| 184 |
+
downloadBtn.href = data.url;
|
| 185 |
+
resultContainer.style.display = 'block';
|
| 186 |
+
genBtn.disabled = false;
|
| 187 |
+
}
|
| 188 |
+
} catch(e) {
|
| 189 |
+
console.log('Polling...', e);
|
| 190 |
}
|
| 191 |
}
|
| 192 |
</script>
|