Update index.html
Browse files- index.html +41 -12
index.html
CHANGED
|
@@ -21,6 +21,10 @@
|
|
| 21 |
}
|
| 22 |
input:focus { outline: none; border-color: #38bdf8; }
|
| 23 |
input::placeholder { color: #475569; }
|
|
|
|
|
|
|
|
|
|
|
|
|
| 24 |
button {
|
| 25 |
padding: 10px 22px; border: none; border-radius: 8px; cursor: pointer;
|
| 26 |
font-size: 0.9rem; font-weight: 600; transition: all .15s;
|
|
@@ -40,6 +44,7 @@
|
|
| 40 |
.badge { display:inline-block; padding:3px 10px; border-radius:20px; font-size:0.78rem; font-weight:600; }
|
| 41 |
.badge-ok { background:#14532d; color:#86efac; }
|
| 42 |
.badge-na { background:#334155; color:#94a3b8; }
|
|
|
|
| 43 |
#log {
|
| 44 |
background: #020617; border: 1px solid #1e3a5f; border-radius: 8px;
|
| 45 |
padding: 14px; height: 260px; overflow-y: auto;
|
|
@@ -84,10 +89,26 @@
|
|
| 84 |
<!-- إضافة حساب -->
|
| 85 |
<div class="card">
|
| 86 |
<h2>➕ إضافة حساب جديد</h2>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 87 |
<div class="form-row">
|
| 88 |
-
<input type="
|
| 89 |
-
<input type="password" id="new-token" placeholder="API Token">
|
| 90 |
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 91 |
<button class="btn-primary" id="add-btn" onclick="addAccount()">➕ إضافة الحساب</button>
|
| 92 |
</div>
|
| 93 |
|
|
@@ -158,17 +179,23 @@ async function loadAccounts() {
|
|
| 158 |
return;
|
| 159 |
}
|
| 160 |
let html = `<table>
|
| 161 |
-
<tr><th>المستخدم</th><th>الخادم</th><th>آخر تجديد</th><th>التجديد القادم</th><th>الحالة</th></tr>`;
|
| 162 |
for (const a of data) {
|
| 163 |
-
const last
|
| 164 |
-
const nxt
|
| 165 |
-
const res
|
| 166 |
const badge = a.last_renewed
|
| 167 |
? '<span class="badge badge-ok">✅ مجدَّد</span>'
|
| 168 |
: '<span class="badge badge-na">⏳ لم يُجدَّد</span>';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 169 |
html += `<tr>
|
| 170 |
<td><b>${a.username}</b></td>
|
| 171 |
<td style="font-size:.8rem;color:#94a3b8">${a.host||'—'}</td>
|
|
|
|
| 172 |
<td style="font-size:.82rem">${last}</td>
|
| 173 |
<td style="font-size:.82rem">${nxt}</td>
|
| 174 |
<td>${badge}<br><span style="font-size:.78rem;color:#64748b">${res}</span></td>
|
|
@@ -179,18 +206,21 @@ async function loadAccounts() {
|
|
| 179 |
|
| 180 |
async function addAccount() {
|
| 181 |
const user = document.getElementById('new-user').value.trim();
|
|
|
|
| 182 |
const token = document.getElementById('new-token').value.trim();
|
| 183 |
-
if (!user
|
|
|
|
| 184 |
const btn = document.getElementById('add-btn');
|
| 185 |
btn.innerHTML = 'جاري التحقق... <span class="spinner"></span>';
|
| 186 |
btn.disabled = true;
|
| 187 |
-
const r = await api('/api/accounts','POST',{username:user,token});
|
| 188 |
btn.innerHTML = '➕ إضافة الحساب';
|
| 189 |
btn.disabled = false;
|
| 190 |
toast(r.message, r.ok);
|
| 191 |
if (r.ok) {
|
| 192 |
-
document.getElementById('new-user').value='';
|
| 193 |
-
document.getElementById('new-
|
|
|
|
| 194 |
loadAccounts();
|
| 195 |
}
|
| 196 |
}
|
|
@@ -242,11 +272,10 @@ async function loadLog() {
|
|
| 242 |
el.scrollTop = el.scrollHeight;
|
| 243 |
}
|
| 244 |
|
| 245 |
-
// تهيئة
|
| 246 |
loadAccounts();
|
| 247 |
loadLog();
|
| 248 |
setInterval(loadLog, 10000);
|
| 249 |
setInterval(loadAccounts, 30000);
|
| 250 |
</script>
|
| 251 |
</body>
|
| 252 |
-
</html>
|
|
|
|
| 21 |
}
|
| 22 |
input:focus { outline: none; border-color: #38bdf8; }
|
| 23 |
input::placeholder { color: #475569; }
|
| 24 |
+
.hint { font-size: 0.8rem; color: #64748b; margin-bottom: 10px; }
|
| 25 |
+
.hint span { color: #fbbf24; }
|
| 26 |
+
.divider { display: flex; align-items: center; gap: 10px; margin: 10px 0; color: #475569; font-size: 0.82rem; }
|
| 27 |
+
.divider::before, .divider::after { content: ''; flex: 1; height: 1px; background: #334155; }
|
| 28 |
button {
|
| 29 |
padding: 10px 22px; border: none; border-radius: 8px; cursor: pointer;
|
| 30 |
font-size: 0.9rem; font-weight: 600; transition: all .15s;
|
|
|
|
| 44 |
.badge { display:inline-block; padding:3px 10px; border-radius:20px; font-size:0.78rem; font-weight:600; }
|
| 45 |
.badge-ok { background:#14532d; color:#86efac; }
|
| 46 |
.badge-na { background:#334155; color:#94a3b8; }
|
| 47 |
+
.badge-method { background:#1e3a5f; color:#7dd3fc; font-size:0.72rem; padding:2px 8px; border-radius:10px; }
|
| 48 |
#log {
|
| 49 |
background: #020617; border: 1px solid #1e3a5f; border-radius: 8px;
|
| 50 |
padding: 14px; height: 260px; overflow-y: auto;
|
|
|
|
| 89 |
<!-- إضافة حساب -->
|
| 90 |
<div class="card">
|
| 91 |
<h2>➕ إضافة حساب جديد</h2>
|
| 92 |
+
|
| 93 |
+
<div class="hint">
|
| 94 |
+
يمكنك استخدام <span>كلمة المرور</span> (طريقة التمديد المباشر /extend) أو <span>API Token</span> (إعادة تحميل الويب آب).
|
| 95 |
+
إذا أدخلت الاثنين معاً، ستُستخدم كلمة المرور أولاً.
|
| 96 |
+
</div>
|
| 97 |
+
|
| 98 |
+
<div class="form-row">
|
| 99 |
+
<input type="text" id="new-user" placeholder="اسم المستخدم — مثال: mahmoud123">
|
| 100 |
+
</div>
|
| 101 |
+
|
| 102 |
+
<div class="divider">كلمة المرور (موصى بها)</div>
|
| 103 |
<div class="form-row">
|
| 104 |
+
<input type="password" id="new-pass" placeholder="كلمة مرور الحساب">
|
|
|
|
| 105 |
</div>
|
| 106 |
+
|
| 107 |
+
<div class="divider">أو API Token</div>
|
| 108 |
+
<div class="form-row">
|
| 109 |
+
<input type="password" id="new-token" placeholder="API Token — من /account/#api_token">
|
| 110 |
+
</div>
|
| 111 |
+
|
| 112 |
<button class="btn-primary" id="add-btn" onclick="addAccount()">➕ إضافة الحساب</button>
|
| 113 |
</div>
|
| 114 |
|
|
|
|
| 179 |
return;
|
| 180 |
}
|
| 181 |
let html = `<table>
|
| 182 |
+
<tr><th>المستخدم</th><th>الخادم</th><th>طريقة الدخول</th><th>آخر تجديد</th><th>التجديد القادم</th><th>الحالة</th></tr>`;
|
| 183 |
for (const a of data) {
|
| 184 |
+
const last = a.last_renewed ? a.last_renewed.slice(0,16).replace('T',' ') : '—';
|
| 185 |
+
const nxt = a.next_renewal ? a.next_renewal.slice(0,16).replace('T',' ') : '—';
|
| 186 |
+
const res = (a.last_results||[]).map(r=>`${r.domain}: ${r.status}`).join('<br>') || '—';
|
| 187 |
const badge = a.last_renewed
|
| 188 |
? '<span class="badge badge-ok">✅ مجدَّد</span>'
|
| 189 |
: '<span class="badge badge-na">⏳ لم يُجدَّد</span>';
|
| 190 |
+
const method = a.auth_method === 'password'
|
| 191 |
+
? '<span class="badge-method">🔑 Password</span>'
|
| 192 |
+
: a.auth_method === 'token'
|
| 193 |
+
? '<span class="badge-method">🔐 Token</span>'
|
| 194 |
+
: '—';
|
| 195 |
html += `<tr>
|
| 196 |
<td><b>${a.username}</b></td>
|
| 197 |
<td style="font-size:.8rem;color:#94a3b8">${a.host||'—'}</td>
|
| 198 |
+
<td>${method}</td>
|
| 199 |
<td style="font-size:.82rem">${last}</td>
|
| 200 |
<td style="font-size:.82rem">${nxt}</td>
|
| 201 |
<td>${badge}<br><span style="font-size:.78rem;color:#64748b">${res}</span></td>
|
|
|
|
| 206 |
|
| 207 |
async function addAccount() {
|
| 208 |
const user = document.getElementById('new-user').value.trim();
|
| 209 |
+
const pass = document.getElementById('new-pass').value.trim();
|
| 210 |
const token = document.getElementById('new-token').value.trim();
|
| 211 |
+
if (!user) { toast('❌ أدخل اسم المستخدم', false); return; }
|
| 212 |
+
if (!pass && !token) { toast('❌ أدخل كلمة المرور أو API Token', false); return; }
|
| 213 |
const btn = document.getElementById('add-btn');
|
| 214 |
btn.innerHTML = 'جاري التحقق... <span class="spinner"></span>';
|
| 215 |
btn.disabled = true;
|
| 216 |
+
const r = await api('/api/accounts', 'POST', {username: user, token, password: pass});
|
| 217 |
btn.innerHTML = '➕ إضافة الحساب';
|
| 218 |
btn.disabled = false;
|
| 219 |
toast(r.message, r.ok);
|
| 220 |
if (r.ok) {
|
| 221 |
+
document.getElementById('new-user').value = '';
|
| 222 |
+
document.getElementById('new-pass').value = '';
|
| 223 |
+
document.getElementById('new-token').value = '';
|
| 224 |
loadAccounts();
|
| 225 |
}
|
| 226 |
}
|
|
|
|
| 272 |
el.scrollTop = el.scrollHeight;
|
| 273 |
}
|
| 274 |
|
|
|
|
| 275 |
loadAccounts();
|
| 276 |
loadLog();
|
| 277 |
setInterval(loadLog, 10000);
|
| 278 |
setInterval(loadAccounts, 30000);
|
| 279 |
</script>
|
| 280 |
</body>
|
| 281 |
+
</html>
|