/
GDVlab
/
lab-service
Обзор
Документация
Войти
/
GDVlab
/
lab-service
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
index.html
364 строки
9 KB
labservice
update: index.html
29 май 2026, 15:14
Верифицирован
29 май 2026, 15:14
9c99df0
Код
Авторство
О чём код?
<!DOCTYPE html> <html lang="ru"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0"/> <title>ТОИР Mobile</title> <style> body { margin: 0; padding: 16px; background: #1e1f22; color: #e5e7eb; font-family: "Segoe UI", Arial; } .container { max-width: 760px; margin: auto; background: #2a2d31; padding: 20px; border-radius: 18px; } input, textarea, button { width: 100%; padding: 12px; margin-bottom: 10px; border-radius: 10px; border: 1px solid #444; background: #1f2226; color: #fff; } button { background: #3b82f6; border: none; font-weight: 600; } .card { background: #1f2226; padding: 12px; margin-bottom: 10px; border-radius: 10px; } .err { color: #ef4444; } .ok { color: #22c55e; } </style> </head> <body> <!-- LOGIN --> <div id="loginScreen" class="container"> <h2>🔐 Вход</h2> <input id="loginToken" placeholder="OAuth token"> <input id="loginNick" placeholder="Ник"> <button onclick="login()">Войти</button> <div id="loginStatus"></div> </div> <!-- APP --> <div id="app" class="container" style="display:none;"> <h2>⚙ ТОИР Mobile</h2> <button onclick="logout()">Выйти</button> <hr> <h3>Новая запись</h3> <input id="equipment" placeholder="Оборудование"> <textarea id="work" placeholder="Работы"></textarea> <button onclick="saveRecord()">Сохранить</button> <div id="status"></div> <hr> <h3>История</h3> <button onclick="loadHistory()">Обновить</button> <div id="history"></div> <hr> <h3>Чат</h3> <textarea id="chatMessage"></textarea> <button onclick="sendMessage()">Отправить</button> <button onclick="loadChat()">Обновить</button> <div id="chat"></div> </div> <script> // ===================== STATE ===================== let token = null; let nickname = null; // ===================== INIT ===================== function initAuth() { token = localStorage.getItem('toir_token'); nickname = localStorage.getItem('toir_nick'); if (token && nickname) { verifyToken(token); } else { showLogin(); } } function showLogin() { document.getElementById('loginScreen').style.display = 'block'; document.getElementById('app').style.display = 'none'; } function showApp() { document.getElementById('loginScreen').style.display = 'none'; document.getElementById('app').style.display = 'block'; } // ===================== LOGIN ===================== function login() { const t = document.getElementById('loginToken').value; const n = document.getElementById('loginNick').value; if (!t || !n) { document.getElementById('loginStatus').innerHTML = '<div class="err">Введите данные</div>'; return; } localStorage.setItem('toir_token', t); localStorage.setItem('toir_nick', n); verifyToken(t); } // ===================== VERIFY TOKEN ===================== async function verifyToken(t) { try { const res = await fetch( 'https://cloud-api.yandex.net/v1/disk/', { headers: { Authorization: 'OAuth ' + t } } ); if (!res.ok) throw new Error('bad token'); token = t; nickname = localStorage.getItem('toir_nick'); showApp(); initStorage(); loadHistory(); loadChat(); } catch (e) { localStorage.clear(); document.getElementById('loginStatus').innerHTML = '<div class="err">❌ Неверный токен</div>'; showLogin(); } } // ===================== LOGOUT ===================== function logout() { localStorage.clear(); location.reload(); } // ===================== STATUS ===================== function status(text, type='ok') { document.getElementById('status').innerHTML = `<div class="${type}">${text}</div>`; } // ===================== STORAGE ===================== async function createFolder(path) { await fetch( 'https://cloud-api.yandex.net/v1/disk/resources?path=' + encodeURIComponent(path), { method:'PUT', headers:{ Authorization:'OAuth '+token } } ); } async function initStorage() { try { await createFolder('app:/history'); await createFolder('app:/chat'); await createFolder('app:/photos'); } catch(e) {} } // ===================== SAVE RECORD ===================== async function saveRecord() { const record = { id: Date.now(), equipment: equipment.value, work: work.value, user: nickname, created: new Date().toISOString() }; const file = 'rec_' + Date.now() + '.json'; const r = await fetch( 'https://cloud-api.yandex.net/v1/disk/resources/upload?path=' + encodeURIComponent('app:/history/' + file) + '&overwrite=true', { headers:{ Authorization:'OAuth '+token } } ); const d = await r.json(); await fetch(d.href, { method:'PUT', body: JSON.stringify(record) }); status('OK'); loadHistory(); } // ===================== HISTORY ===================== async function loadHistory() { try { const r = await fetch( 'https://cloud-api.yandex.net/v1/disk/resources?path=' + encodeURIComponent('app:/history'), { headers:{ Authorization:'OAuth '+token } } ); const d = await r.json(); if (!d._embedded) return; const items = d._embedded.items.slice(0,10); const list = document.getElementById('history'); list.innerHTML = ''; for (const i of items) { const dr = await fetch( 'https://cloud-api.yandex.net/v1/disk/resources/download?path=' + encodeURIComponent(i.path), { headers:{ Authorization:'OAuth '+token } } ); const dd = await dr.json(); const file = await fetch(dd.href); const rec = await file.json(); const div = document.createElement('div'); div.className='card'; div.innerHTML = ` <b>${rec.equipment}</b><br> ${rec.work}<br> <small>${rec.user}</small> `; list.appendChild(div); } } catch(e) { console.log(e); } } // ===================== CHAT ===================== async function sendMessage() { const text = chatMessage.value; if (!text.trim()) return; let messages = []; try { const r = await fetch( 'https://cloud-api.yandex.net/v1/disk/resources/download?path=' + encodeURIComponent('app:/chat/global.json'), { headers:{ Authorization:'OAuth '+token } } ); const d = await r.json(); if (d.href) { const f = await fetch(d.href); messages = await f.json(); } } catch(e){} messages.push({ user:nickname, text, created:new Date().toISOString() }); const u = await fetch( 'https://cloud-api.yandex.net/v1/disk/resources/upload?path=' + encodeURIComponent('app:/chat/global.json') + '&overwrite=true', { headers:{ Authorization:'OAuth '+token } } ); const ud = await u.json(); await fetch(ud.href,{ method:'PUT', body:JSON.stringify(messages) }); chatMessage.value=''; loadChat(); } async function loadChat() { try { const r = await fetch( 'https://cloud-api.yandex.net/v1/disk/resources/download?path=' + encodeURIComponent('app:/chat/global.json'), { headers:{ Authorization:'OAuth '+token } } ); const d = await r.json(); if (!d.href) return; const f = await fetch(d.href); const messages = await f.json(); const div = document.getElementById('chat'); div.innerHTML=''; messages.reverse().forEach(m=>{ const c=document.createElement('div'); c.className='card'; c.innerHTML=`<b>${m.user}</b><br>${m.text}`; div.appendChild(c); }); } catch(e){} } // ===================== START ===================== initAuth(); </script> </body> </html>