v1.3 — лого встроено в HTML
This commit is contained in:
+113
-90
@@ -10,7 +10,13 @@
|
|||||||
<body>
|
<body>
|
||||||
|
|
||||||
<header style="background:#fff;border-bottom:1px solid var(--border);padding:0 1.5rem;height:48px;display:flex;align-items:center;gap:.75rem;font-size:.85rem;color:var(--muted);">
|
<header style="background:#fff;border-bottom:1px solid var(--border);padding:0 1.5rem;height:48px;display:flex;align-items:center;gap:.75rem;font-size:.85rem;color:var(--muted);">
|
||||||
<img src="/nubes-logo.svg" alt="Nubes" width="130" height="28" style="display:block;">
|
<svg viewBox="0 0 311 69" width="130" height="28" style="display:block;">
|
||||||
|
<g transform="translate(-330 -228)">
|
||||||
|
<path d="M348.061 246.203 332.42 246.203 330 256.661 336.75 256.661 336.794 295.573 336.794 296.585 336.795 296.585 347.25 296.585 347.25 263.611C347.25 259.78 350.368 256.663 354.2 256.663L376.489 256.793C380.322 256.793 383.44 259.912 383.44 263.743L383.44 296.717 393.896 296.717 393.896 263.743C393.896 254.144 386.087 246.338 376.495 246.338L354.196 246.204 348.061 246.221 348.061 246.203Z" fill="#2563eb" fill-rule="evenodd"/>
|
||||||
|
<path d="M582.095 296.65 626.768 296.65C634.793 296.65 641 290.03 641 282.009 641 273.985 634.473 267.458 626.449 267.458L601.724 267.458C599.446 267.458 597.595 265.607 597.595 263.328L597.595 260.825C597.595 258.548 599.446 256.697 601.724 256.697L628.041 256.697 630.452 246.276 601.724 246.276C593.7 246.276 587.174 252.802 587.174 260.825L587.174 263.328C587.174 271.352 593.7 277.879 601.724 277.879L626.449 277.879C628.726 277.879 630.579 279.732 630.579 282.009 630.579 284.283 628.726 286.4 626.449 286.4L584.126 286.4 582.095 296.65Z" fill="#2563eb" fill-rule="evenodd"/>
|
||||||
|
<path d="M564.549 246.347 537.193 246.347C529.027 246.347 522.385 252.989 522.385 261.156L522.385 279.521C522.385 288.916 530.028 296.557 539.422 296.557L576.846 296.557 579.196 286.401 539.422 286.401C535.775 286.401 532.805 283.172 532.805 279.521L532.748 278.028 567.684 278.028 579.354 277.959 579.354 268.958 579.354 261.156C579.354 252.989 572.712 246.347 564.549 246.347ZM568.935 267.54 532.805 267.54 532.805 261.156C532.805 258.737 534.774 256.767 537.193 256.767L564.549 256.767C566.966 256.767 568.935 258.737 568.935 261.156L568.935 267.54Z" fill="#2563eb" fill-rule="evenodd"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
<span style="color:var(--border);">|</span>
|
<span style="color:var(--border);">|</span>
|
||||||
<b style="color:var(--text);">Say</b>
|
<b style="color:var(--text);">Say</b>
|
||||||
<span id="ver" style="margin-left:4px;"></span>
|
<span id="ver" style="margin-left:4px;"></span>
|
||||||
@@ -39,7 +45,13 @@
|
|||||||
|
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-header">Диалог</div>
|
<div class="card-header">Диалог</div>
|
||||||
<div class="card-body" id="chat" style="min-height:200px;max-height:380px;overflow-y:auto;"></div>
|
<div class="card-body">
|
||||||
|
<div style="display:flex;gap:.5rem;margin-bottom:10px;">
|
||||||
|
<input id="txtInput" type="text" placeholder="Введите текст или используйте микрофон..." style="flex:1;padding:.5rem .75rem;border:1px solid var(--border);border-radius:6px;font-size:.9rem;outline:none;background:var(--card);color:var(--text);">
|
||||||
|
<button id="btnSend" class="btn" style="font-size:13px;">➤</button>
|
||||||
|
</div>
|
||||||
|
<div id="chat" style="min-height:200px;max-height:340px;overflow-y:auto;"></div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -51,28 +63,31 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
const VERSION = 'v1.1';
|
const VERSION = 'v1.3';
|
||||||
document.getElementById('ver').textContent = VERSION;
|
document.getElementById('ver').textContent = VERSION;
|
||||||
|
|
||||||
const btnRecord = document.getElementById('btnRecord');
|
const btnRecord = document.getElementById('btnRecord');
|
||||||
const btnPlay = document.getElementById('btnPlay');
|
const btnPlay = document.getElementById('btnPlay');
|
||||||
const statusEl = document.getElementById('status');
|
const statusEl = document.getElementById('status');
|
||||||
const chat = document.getElementById('chat');
|
const chat = document.getElementById('chat');
|
||||||
const histList = document.getElementById('history-list');
|
const histList = document.getElementById('history-list');
|
||||||
const meter = document.getElementById('meter');
|
const meter = document.getElementById('meter');
|
||||||
const meterCtx = meter.getContext('2d');
|
const meterCtx = meter.getContext('2d');
|
||||||
|
const txtInput = document.getElementById('txtInput');
|
||||||
|
const btnSend = document.getElementById('btnSend');
|
||||||
|
|
||||||
let mediaRecorder, chunks = [], userBlob = null;
|
let mediaRecorder, chunks = [], userBlob = null;
|
||||||
let isRecording = false, micAnalyser = null, micAnimId = null;
|
let isRecording = false, micAnalyser = null, micAnimId = null;
|
||||||
let audioContext = null, chatHistory = [];
|
let audioContext = null, chatHistory = [];
|
||||||
let thinkStart = 0, thinkTimer = null;
|
|
||||||
|
|
||||||
// История — массив {q, a, time}
|
// Светлая тема — по умолчанию
|
||||||
let history = JSON.parse(localStorage.getItem('say_history') || '[]');
|
if (localStorage.getItem('say_dark') === '1') document.body.classList.add('dark');
|
||||||
|
|
||||||
function setStatus(msg) { statusEl.innerHTML = msg; }
|
let history = JSON.parse(localStorage.getItem('say_history') || '[]');
|
||||||
function renderHistory() {
|
|
||||||
|
function setStatus(msg) { statusEl.innerHTML = msg; }
|
||||||
|
function renderHistory() {
|
||||||
histList.innerHTML = history.slice(-20).map((h, i) =>
|
histList.innerHTML = history.slice(-20).map((h, i) =>
|
||||||
'<div class="hitem" data-idx="' + i + '" title="' + h.time + '">' +
|
'<div class="hitem" data-idx="' + i + '" title="' + h.time + '">' +
|
||||||
'<span class="hq">' + esc(h.q).substring(0, 60) + '</span>' +
|
'<span class="hq">' + esc(h.q).substring(0, 60) + '</span>' +
|
||||||
@@ -86,43 +101,45 @@
|
|||||||
chat.scrollTop = chat.scrollHeight;
|
chat.scrollTop = chat.scrollHeight;
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
function esc(s) { return String(s).replace(/</g,'<').replace(/>/g,'>'); }
|
function esc(s) { return String(s).replace(/</g,'<').replace(/>/g,'>'); }
|
||||||
function fmt(s) {
|
function fmt(s) {
|
||||||
s = esc(s);
|
s = esc(s);
|
||||||
// Заменяем **жирный**
|
|
||||||
s = s.replace(/\*\*(.+?)\*\*/g, '<b>$1</b>');
|
s = s.replace(/\*\*(.+?)\*\*/g, '<b>$1</b>');
|
||||||
// Заменяем `код`
|
|
||||||
s = s.replace(/`(.+?)`/g, '<code>$1</code>');
|
s = s.replace(/`(.+?)`/g, '<code>$1</code>');
|
||||||
// Заменяем *курсив*
|
|
||||||
s = s.replace(/\*(.+?)\*/g, '<i>$1</i>');
|
s = s.replace(/\*(.+?)\*/g, '<i>$1</i>');
|
||||||
// Горизонтальная линия ---
|
|
||||||
s = s.replace(/^---+/gm, '<hr>');
|
s = s.replace(/^---+/gm, '<hr>');
|
||||||
// Заголовки ###
|
|
||||||
s = s.replace(/^### (.+)$/gm, '<h3>$1</h3>');
|
s = s.replace(/^### (.+)$/gm, '<h3>$1</h3>');
|
||||||
s = s.replace(/^## (.+)$/gm, '<h2>$1</h2>');
|
s = s.replace(/^## (.+)$/gm, '<h2>$1</h2>');
|
||||||
s = s.replace(/^# (.+)$/gm, '<h1>$1</h1>');
|
s = s.replace(/^# (.+)$/gm, '<h1>$1</h1>');
|
||||||
// Маркированный список
|
|
||||||
s = s.replace(/^[•\-*] (.+)$/gm, '<li>$1</li>');
|
s = s.replace(/^[•\-*] (.+)$/gm, '<li>$1</li>');
|
||||||
s = s.replace(/(<li>[\s\S]*?<\/li>)/g, '<ul>$1</ul>');
|
s = s.replace(/(<li>[\s\S]*?<\/li>)/g, '<ul>$1</ul>');
|
||||||
// Нумерованный список
|
|
||||||
s = s.replace(/^\d+\.\s+(.+)$/gm, '<li>$1</li>');
|
s = s.replace(/^\d+\.\s+(.+)$/gm, '<li>$1</li>');
|
||||||
// Абзацы (двойной перенос строки)
|
|
||||||
s = s.replace(/\n\n+/g, '</p><p>');
|
s = s.replace(/\n\n+/g, '</p><p>');
|
||||||
// Одинарный перенос → <br>
|
|
||||||
s = s.replace(/\n/g, '<br>');
|
s = s.replace(/\n/g, '<br>');
|
||||||
// Убираем пустые <ul>
|
|
||||||
s = s.replace(/<ul>\s*<\/ul>/g, '');
|
s = s.replace(/<ul>\s*<\/ul>/g, '');
|
||||||
return '<p>' + s + '</p>';
|
return '<p>' + s + '</p>';
|
||||||
}
|
}
|
||||||
|
|
||||||
renderHistory();
|
renderHistory();
|
||||||
|
|
||||||
btnRecord.onclick = async () => {
|
// ===== Отправка текста =====
|
||||||
|
async function sendText(text) {
|
||||||
|
if (!text.trim()) return;
|
||||||
|
txtInput.value = '';
|
||||||
|
chat.innerHTML += '<div class="msg user">⌨ ' + fmt(text) + '</div>';
|
||||||
|
chat.scrollTop = chat.scrollHeight;
|
||||||
|
await askLLM(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
btnSend.onclick = () => sendText(txtInput.value);
|
||||||
|
txtInput.onkeydown = e => { if (e.key === 'Enter') sendText(txtInput.value); };
|
||||||
|
|
||||||
|
// ===== Запись =====
|
||||||
|
btnRecord.onclick = async () => {
|
||||||
if (isRecording) { stopRecording(); return; }
|
if (isRecording) { stopRecording(); return; }
|
||||||
try {
|
try {
|
||||||
isRecording = true;
|
isRecording = true; btnRecord.textContent = '⏹ Стоп';
|
||||||
btnRecord.textContent = '⏹ Стоп';
|
|
||||||
setStatus('🎤 Запись...');
|
setStatus('🎤 Запись...');
|
||||||
await startRecording();
|
await startRecording();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@@ -131,20 +148,17 @@
|
|||||||
else if (err.name === 'NotFoundError') msg += 'Микрофон не найден.';
|
else if (err.name === 'NotFoundError') msg += 'Микрофон не найден.';
|
||||||
else msg += 'Ошибка: ' + (err.message || err.name);
|
else msg += 'Ошибка: ' + (err.message || err.name);
|
||||||
setStatus(msg);
|
setStatus(msg);
|
||||||
btnRecord.textContent = '🎙 Записать';
|
btnRecord.textContent = '🎙 Записать'; isRecording = false;
|
||||||
isRecording = false;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
async function startRecording() {
|
async function startRecording() {
|
||||||
chunks = [];
|
chunks = [];
|
||||||
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
|
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
|
||||||
audioContext = new AudioContext();
|
audioContext = new AudioContext();
|
||||||
const source = audioContext.createMediaStreamSource(stream);
|
const source = audioContext.createMediaStreamSource(stream);
|
||||||
micAnalyser = audioContext.createAnalyser();
|
micAnalyser = audioContext.createAnalyser(); micAnalyser.fftSize = 256;
|
||||||
micAnalyser.fftSize = 256;
|
source.connect(micAnalyser); drawMeter();
|
||||||
source.connect(micAnalyser);
|
|
||||||
drawMeter();
|
|
||||||
mediaRecorder = new MediaRecorder(stream);
|
mediaRecorder = new MediaRecorder(stream);
|
||||||
mediaRecorder.ondataavailable = e => chunks.push(e.data);
|
mediaRecorder.ondataavailable = e => chunks.push(e.data);
|
||||||
mediaRecorder.onstop = async () => {
|
mediaRecorder.onstop = async () => {
|
||||||
@@ -156,15 +170,15 @@
|
|||||||
await transcribeAndChat();
|
await transcribeAndChat();
|
||||||
};
|
};
|
||||||
mediaRecorder.start();
|
mediaRecorder.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
function stopRecording() {
|
function stopRecording() {
|
||||||
btnRecord.disabled = true;
|
btnRecord.disabled = true;
|
||||||
setStatus('⏳ Обработка...');
|
setStatus('⏳ Обработка...');
|
||||||
mediaRecorder.stop();
|
mediaRecorder.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
function drawMeter() {
|
function drawMeter() {
|
||||||
if (!micAnalyser) return;
|
if (!micAnalyser) return;
|
||||||
const data = new Uint8Array(micAnalyser.frequencyBinCount);
|
const data = new Uint8Array(micAnalyser.frequencyBinCount);
|
||||||
micAnalyser.getByteTimeDomainData(data);
|
micAnalyser.getByteTimeDomainData(data);
|
||||||
@@ -172,85 +186,94 @@
|
|||||||
meterCtx.fillStyle = '#1a1a2e';
|
meterCtx.fillStyle = '#1a1a2e';
|
||||||
meterCtx.fillRect(0, 0, w, h);
|
meterCtx.fillRect(0, 0, w, h);
|
||||||
meterCtx.strokeStyle = '#6c5ce7';
|
meterCtx.strokeStyle = '#6c5ce7';
|
||||||
meterCtx.lineWidth = 2;
|
meterCtx.lineWidth = 2; meterCtx.beginPath();
|
||||||
meterCtx.beginPath();
|
for (let i = 0; i < data.length; i++)
|
||||||
for (let i = 0; i < data.length; i++) {
|
|
||||||
meterCtx.lineTo((i / data.length) * w, (data[i] / 255) * h);
|
meterCtx.lineTo((i / data.length) * w, (data[i] / 255) * h);
|
||||||
}
|
|
||||||
meterCtx.stroke();
|
meterCtx.stroke();
|
||||||
micAnimId = requestAnimationFrame(drawMeter);
|
micAnimId = requestAnimationFrame(drawMeter);
|
||||||
}
|
}
|
||||||
|
|
||||||
btnPlay.onclick = () => {
|
btnPlay.onclick = () => {
|
||||||
if (!userBlob) return;
|
if (!userBlob) return;
|
||||||
const a = new Audio(URL.createObjectURL(userBlob));
|
const a = new Audio(URL.createObjectURL(userBlob));
|
||||||
a.onended = () => URL.revokeObjectURL(a.src);
|
a.onended = () => URL.revokeObjectURL(a.src);
|
||||||
a.play(); setStatus('🔊 Ваша запись...');
|
a.play(); setStatus('🔊 Ваша запись...');
|
||||||
};
|
};
|
||||||
|
|
||||||
async function transcribeAndChat() {
|
// ===== Транскрибация → LLM =====
|
||||||
|
async function transcribeAndChat() {
|
||||||
|
let tStart = Date.now();
|
||||||
|
setStatus('🎤 Транскрибация... 0с');
|
||||||
|
const tTimer = setInterval(() => setStatus('🎤 Транскрибация... ' + ((Date.now() - tStart) / 1000).toFixed(0) + 'с'), 200);
|
||||||
try {
|
try {
|
||||||
setStatus('📝 Распознавание...');
|
|
||||||
const fd = new FormData(); fd.append('audio', userBlob);
|
const fd = new FormData(); fd.append('audio', userBlob);
|
||||||
const ac = new AbortController(); const to = setTimeout(() => ac.abort(), 30000);
|
const ac = new AbortController(); setTimeout(() => ac.abort(), 30000);
|
||||||
const tRes = await fetch('/api/whisper', { method: 'POST', body: fd, signal: ac.signal });
|
const tRes = await fetch('/api/whisper', { method: 'POST', body: fd, signal: ac.signal });
|
||||||
clearTimeout(to);
|
clearInterval(tTimer);
|
||||||
const tData = await tRes.json();
|
const tData = await tRes.json();
|
||||||
const text = tData.text || '(не распознано)';
|
const text = tData.text || '(не распознано)';
|
||||||
|
const tElapsed = ((Date.now() - tStart) / 1000).toFixed(1);
|
||||||
|
setStatus('✅ Транскрибация: ' + tElapsed + 'с');
|
||||||
chat.innerHTML += '<div class="msg user">🗣 ' + fmt(text) + '</div>';
|
chat.innerHTML += '<div class="msg user">🗣 ' + fmt(text) + '</div>';
|
||||||
chat.scrollTop = chat.scrollHeight;
|
chat.scrollTop = chat.scrollHeight;
|
||||||
|
await askLLM(text);
|
||||||
|
} catch (err) {
|
||||||
|
clearInterval(tTimer);
|
||||||
|
setStatus('⛔ Ошибка: ' + err.message);
|
||||||
|
btnRecord.textContent = '🎙 Записать'; btnRecord.disabled = false; isRecording = false;
|
||||||
|
userBlob = null; btnPlay.disabled = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
startThinkTimer();
|
async function askLLM(text) {
|
||||||
|
let lStart = Date.now();
|
||||||
|
statusEl.innerHTML += '<br>🤔 Думаю... 0с';
|
||||||
|
const lTimer = setInterval(() => {
|
||||||
|
const sec = ((Date.now() - lStart) / 1000).toFixed(0);
|
||||||
|
statusEl.innerHTML = statusEl.innerHTML.replace(/🤔 Думаю... [\d.]+с/, '🤔 Думаю... ' + sec + 'с');
|
||||||
|
}, 200);
|
||||||
|
try {
|
||||||
const cRes = await fetch('/api/chat', {
|
const cRes = await fetch('/api/chat', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: { 'Content-Type': 'application/json' },
|
headers: { 'Content-Type': 'application/json' },
|
||||||
body: JSON.stringify({ model: 'gpt-oss-120b', message: text, history: chatHistory }),
|
body: JSON.stringify({ model: 'gpt-oss-120b', message: text, history: chatHistory }),
|
||||||
signal: (() => { const a = new AbortController(); setTimeout(() => a.abort(), 120000); return a.signal; })(),
|
signal: (() => { const a = new AbortController(); setTimeout(() => a.abort(), 120000); return a.signal; })(),
|
||||||
});
|
});
|
||||||
stopThinkTimer();
|
clearInterval(lTimer);
|
||||||
const cData = await cRes.json();
|
const cData = await cRes.json();
|
||||||
const resp = cData.response || cData.error || 'Ошибка';
|
const resp = cData.response || cData.error || 'Ошибка';
|
||||||
|
const lElapsed = ((Date.now() - lStart) / 1000).toFixed(1);
|
||||||
|
statusEl.innerHTML = statusEl.innerHTML.replace(/🤔 Думаю... [\d.]+с/, '✅ Ответ: ' + lElapsed + 'с');
|
||||||
|
|
||||||
chatHistory.push({ role: 'user', content: text });
|
chatHistory.push({ role: 'user', content: text });
|
||||||
chatHistory.push({ role: 'assistant', content: resp });
|
chatHistory.push({ role: 'assistant', content: resp });
|
||||||
if (chatHistory.length > 40) chatHistory = chatHistory.slice(-40);
|
if (chatHistory.length > 40) chatHistory = chatHistory.slice(-40);
|
||||||
chat.innerHTML += '<div class="msg bot">🤖 ' + fmt(resp) + '</div>';
|
chat.innerHTML += '<div class="msg bot">🤖 ' + fmt(resp) + '</div>';
|
||||||
chat.scrollTop = chat.scrollHeight;
|
chat.scrollTop = chat.scrollHeight;
|
||||||
setStatus('✅ Готово — ' + ((Date.now() - thinkStart) / 1000).toFixed(1) + 'с');
|
|
||||||
|
|
||||||
history.push({ q: text, a: resp, time: new Date().toLocaleTimeString() });
|
history.push({ q: text, a: resp, time: new Date().toLocaleTimeString() });
|
||||||
if (history.length > 20) history.shift();
|
if (history.length > 20) history.shift();
|
||||||
localStorage.setItem('say_history', JSON.stringify(history));
|
localStorage.setItem('say_history', JSON.stringify(history));
|
||||||
renderHistory();
|
renderHistory();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
stopThinkTimer();
|
clearInterval(lTimer);
|
||||||
setStatus('⛔ ' + err.message);
|
statusEl.innerHTML = statusEl.innerHTML.replace(/🤔 Думаю... [\d.]+с/, '⛔ ' + err.message);
|
||||||
}
|
}
|
||||||
btnRecord.textContent = '🎙 Записать';
|
btnRecord.textContent = '🎙 Записать'; btnRecord.disabled = false; isRecording = false;
|
||||||
btnRecord.disabled = false; isRecording = false;
|
|
||||||
userBlob = null; btnPlay.disabled = true;
|
userBlob = null; btnPlay.disabled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function startThinkTimer() {
|
// Тема
|
||||||
thinkStart = Date.now();
|
document.getElementById('btnTheme').onclick = () => {
|
||||||
thinkTimer = setInterval(() => {
|
const dark = !document.body.classList.toggle('dark');
|
||||||
setStatus('🤖 Думает... ' + ((Date.now() - thinkStart) / 1000).toFixed(0) + 'с');
|
document.getElementById('btnTheme').textContent = dark ? '☀️' : '🌙';
|
||||||
}, 200);
|
localStorage.setItem('say_dark', dark ? '1' : '0');
|
||||||
}
|
};
|
||||||
function stopThinkTimer() { if (thinkTimer) { clearInterval(thinkTimer); thinkTimer = null; } }
|
document.getElementById('btnTheme').textContent = document.body.classList.contains('dark') ? '☀️' : '🌙';
|
||||||
|
|
||||||
document.getElementById('btnReset').onclick = () => {
|
document.getElementById('btnReset').onclick = () => {
|
||||||
chatHistory = []; chat.innerHTML = ''; setStatus('🧹 Очищено');
|
chatHistory = []; chat.innerHTML = ''; setStatus('');
|
||||||
};
|
};
|
||||||
|
</script>
|
||||||
// Тема
|
|
||||||
const btnTheme = document.getElementById('btnTheme');
|
|
||||||
let dark = localStorage.getItem('say_dark') !== '0';
|
|
||||||
function applyTheme() {
|
|
||||||
document.body.className = dark ? 'dark' : 'light';
|
|
||||||
btnTheme.textContent = dark ? '🌙' : '☀️';
|
|
||||||
}
|
|
||||||
applyTheme();
|
|
||||||
btnTheme.onclick = () => { dark = !dark; localStorage.setItem('say_dark', dark ? '1' : '0'); applyTheme(); };
|
|
||||||
</script>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
+543
-2
@@ -1,2 +1,543 @@
|
|||||||
Forbidden
|
<!DOCTYPE html>
|
||||||
Transaction ID: bdd7fbca-219a-4dbf-95ca-a27cc8bdecd9
|
<html lang="ru" dir="ltr" prefix="og: https://ogp.me/ns#">
|
||||||
|
<head>
|
||||||
|
<title>Страница не найдена | Nubes</title>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<link rel="canonical" href="http://nubes.ru/" />
|
||||||
|
<link rel="shortlink" href="http://nubes.ru/" />
|
||||||
|
<meta name="robots" content="index, follow" />
|
||||||
|
<meta property="og:site_name" content="Nubes" />
|
||||||
|
<meta property="og:type" content="website" />
|
||||||
|
<meta property="og:url" content="http://nubes.ru/favicon.svg" />
|
||||||
|
<meta property="og:title" content="Страница не найдена" />
|
||||||
|
<meta name="Generator" content="Drupal 10 (https://www.drupal.org)" />
|
||||||
|
<meta name="MobileOptimized" content="width" />
|
||||||
|
<meta name="HandheldFriendly" content="true" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<link rel="icon" href="/themes/custom/nubes_2025/favicon.png" type="image/png" />
|
||||||
|
|
||||||
|
<link rel="stylesheet" media="all" href="/files/css/css_jWcmDtZ1obzejBSRGuMNqJBGUcExB89Lf86WbU4U_vw.css?delta=0&language=ru&theme=nubes_2025&include=eJxlTgsKwjAMvVBtZeB5RrJlpS5tRpPh5umtOFEYhCTvkw_CMPcmLZaAv75PgxSHIqZWYbk1TekfZ1KFSOoGYakoWxhpgpWtEZVCkZqB05McbcapzGGs6wLsD-jKiqR9d-1uIbIg8EVtb0p0uqtR_hx8EE5tUziqhztsJ5KYMhXzIxkkVm8SI59nv7bj85P-Ti8_h2g3" />
|
||||||
|
<link rel="stylesheet" media="all" href="/files/css/css_vCUKkxYRRNAwlY6wZwLrhAcLThWHxfJGtyLGWsxWz9A.css?delta=1&language=ru&theme=nubes_2025&include=eJxlTgsKwjAMvVBtZeB5RrJlpS5tRpPh5umtOFEYhCTvkw_CMPcmLZaAv75PgxSHIqZWYbk1TekfZ1KFSOoGYakoWxhpgpWtEZVCkZqB05McbcapzGGs6wLsD-jKiqR9d-1uIbIg8EVtb0p0uqtR_hx8EE5tUziqhztsJ5KYMhXzIxkkVm8SI59nv7bj85P-Ti8_h2g3" />
|
||||||
|
|
||||||
|
|
||||||
|
<link rel="icon" href="/themes/custom/nubes/images/nubes-ico.svg" type="image/svg+xml" />
|
||||||
|
<meta name="yandex-verification" content="57b2f86a0f06d0db" />
|
||||||
|
</head>
|
||||||
|
<body class="page-route-system-404 path-faviconsvg">
|
||||||
|
<a href="#main-content" class="visually-hidden focusable skip-link">
|
||||||
|
Перейти к основному содержанию
|
||||||
|
</a>
|
||||||
|
<div class="body-wrapper">
|
||||||
|
|
||||||
|
<div class="dialog-off-canvas-main-canvas d-flex flex-column h-100" data-off-canvas-main-canvas>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="header-wrapper">
|
||||||
|
<header role="banner">
|
||||||
|
<nav class="navbar-expand-xl">
|
||||||
|
<div class="header d-flex">
|
||||||
|
<div class="header-mobile d-flex">
|
||||||
|
<div class="region region-nav-branding">
|
||||||
|
<div id="block-nubes-2025-brending" class="block block-system block-system-branding-block">
|
||||||
|
|
||||||
|
|
||||||
|
<div class="navbar-brand d-flex align-items-center">
|
||||||
|
|
||||||
|
<a href="/" title="Главная" rel="home" class="site-logo d-block">
|
||||||
|
<img src="/themes/custom/nubes_2025/logo.svg" alt="Главная" fetchpriority="high" />
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<button class="navbar-toggler collapsed" type="button" data-bs-toggle="collapse"
|
||||||
|
data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent"
|
||||||
|
aria-expanded="false" aria-label="Toggle navigation">
|
||||||
|
<span class="navbar-toggler-icon"></span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="collapse navbar-collapse" id="navbarSupportedContent">
|
||||||
|
<div class="region region-nav-main">
|
||||||
|
<nav role="navigation" aria-labelledby="block-nubes-2025-menu-menu" id="block-nubes-2025-menu" class="block block-menu navigation menu--main-rus">
|
||||||
|
|
||||||
|
<div class="visually-hidden h5" id="block-nubes-2025-menu-menu">Главное меню (Рус)</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<ul data-block="nav_main" class="menu">
|
||||||
|
<li class="menu-item menu-item--expanded link-service"
|
||||||
|
>
|
||||||
|
<span item="link-service">Сервисы</span>
|
||||||
|
<ul class="menu">
|
||||||
|
<li class="menu-item menu-item--collapsed"
|
||||||
|
>
|
||||||
|
<a href="/cloud/resources" data-drupal-link-system-path="node/300">Облачные ресурсы</a>
|
||||||
|
</li>
|
||||||
|
<li class="menu-item menu-item--collapsed"
|
||||||
|
>
|
||||||
|
<a href="/ai" data-drupal-link-system-path="node/1067">Искусственный интеллект</a>
|
||||||
|
</li>
|
||||||
|
<li class="menu-item menu-item--collapsed"
|
||||||
|
>
|
||||||
|
<a href="/cloud/storage" data-drupal-link-system-path="node/308">Хранение данных</a>
|
||||||
|
</li>
|
||||||
|
<li class="menu-item menu-item--collapsed"
|
||||||
|
>
|
||||||
|
<a href="/cloud/workspace" data-drupal-link-system-path="node/309">Работа офиса</a>
|
||||||
|
</li>
|
||||||
|
<li class="menu-item menu-item--collapsed"
|
||||||
|
>
|
||||||
|
<a href="/cloud/backup" data-drupal-link-system-path="node/310">Резервное копирование и DR</a>
|
||||||
|
</li>
|
||||||
|
<li class="menu-item menu-item--collapsed"
|
||||||
|
>
|
||||||
|
<a href="/security" data-drupal-link-system-path="node/950">ИБ-сервисы</a>
|
||||||
|
</li>
|
||||||
|
<li class="menu-item menu-item--collapsed"
|
||||||
|
>
|
||||||
|
<a href="/dc" data-drupal-link-system-path="node/974">Дата-центр</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
</li>
|
||||||
|
<li class="menu-item menu-item--expanded"
|
||||||
|
>
|
||||||
|
<span>Пользователям</span>
|
||||||
|
<ul class="menu">
|
||||||
|
<li class="menu-item menu-item--collapsed"
|
||||||
|
>
|
||||||
|
<a href="/instructions" data-drupal-link-system-path="instructions">Инструкции</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
</li>
|
||||||
|
<li class="menu-item"
|
||||||
|
>
|
||||||
|
<a href="/partners" data-drupal-link-system-path="node/976">Партнерам</a>
|
||||||
|
</li>
|
||||||
|
<li class="menu-item menu-item--expanded"
|
||||||
|
>
|
||||||
|
<span>О нас</span>
|
||||||
|
<ul class="menu">
|
||||||
|
<li class="menu-item"
|
||||||
|
>
|
||||||
|
<a href="/company/about" data-drupal-link-system-path="node/135">О компании</a>
|
||||||
|
</li>
|
||||||
|
<li class="menu-item"
|
||||||
|
>
|
||||||
|
<a href="/company/team" data-drupal-link-system-path="node/1045">О команде</a>
|
||||||
|
</li>
|
||||||
|
<li class="menu-item"
|
||||||
|
>
|
||||||
|
<a href="/company/licenses" data-drupal-link-system-path="node/333">Лицензии и сертификаты</a>
|
||||||
|
</li>
|
||||||
|
<li class="menu-item menu-item--collapsed"
|
||||||
|
>
|
||||||
|
<a href="/blog" data-drupal-link-system-path="blog/all">Блог</a>
|
||||||
|
</li>
|
||||||
|
<li class="menu-item footer-d-none"
|
||||||
|
>
|
||||||
|
<a href="/contacts" item="footer-d-none" data-drupal-link-system-path="node/763">Контакты</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="region region-nav-additional">
|
||||||
|
<div id="block-nubes-2025-header-order" class="block block-block-content block-block-contentadce38a4-982f-4219-bb40-3ca331878f9c">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div class="clearfix text-formatted field field--name-body field--type-text-with-summary field--label-hidden field__item"><div class="header-button">
|
||||||
|
<a class="button btn-phone phone" href="tel:+74957894135" onclick="ym(68913385,'reachGoal','header_phone_click'); return true;" data-bs-toggle="tooltip" data-bs-placement="bottom" title="+7 (495) 789-4135"><span>Связаться с нами</span></a>
|
||||||
|
<a class="button btn-login" href="https://deck.ngcloud.ru" target="_blank" onclick="ym(68913385,'reachGoal','header_login_click'); return true;" data-bs-toggle="tooltip" data-bs-placement="bottom" title="Личный кабинет"><span>Регистрация / Вход</span></a>
|
||||||
|
</div></div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div id="block-nubes-2025-login" class="block block-block-content block-block-content81db9f5f-8007-473b-bf0b-1c9b0a80ecc0">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div class="clearfix text-formatted field field--name-body field--type-text-with-summary field--label-hidden field__item"><div class="header-button d-none"><a class="button btn-login" onclick="return true;"><span>Регистрация / Вход</span></a></div></div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
</header>
|
||||||
|
</div>
|
||||||
|
<main role="main">
|
||||||
|
<a id="main-content" tabindex="-1"></a>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div class="content-header-wrapper">
|
||||||
|
<div class="content-header">
|
||||||
|
<div class="region region-content-header">
|
||||||
|
<div data-drupal-messages-fallback class="hidden"></div>
|
||||||
|
<div id="block-nubes-2025-strokanavigacii" class="block block-system block-system-breadcrumb-block">
|
||||||
|
|
||||||
|
|
||||||
|
<nav aria-label="breadcrumb">
|
||||||
|
<div id="system-breadcrumb" class="title h2 visually-hidden">Строка навигации</div>
|
||||||
|
<ol class="breadcrumb" itemscope itemtype="http://schema.org/BreadcrumbList">
|
||||||
|
<li class="breadcrumb-item" itemprop="itemListElement" itemscope itemtype="http://schema.org/ListItem">
|
||||||
|
<a href="/" itemprop="item"><span itemprop="name">Главная</span></a><meta itemprop="position" content="1" />
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div id="block-nubes-2025-page-title" class="block block-core block-page-title-block">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h1>Страница не найдена</h1>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div class="main-wrapper">
|
||||||
|
<div class="row">
|
||||||
|
<div class="order-1 order-lg-2 col-12">
|
||||||
|
<div class="content-wrapper">
|
||||||
|
<div class="region region-content">
|
||||||
|
<div id="block-nubes-2025-content" class="block block-system block-system-main-block">
|
||||||
|
|
||||||
|
|
||||||
|
Запрашиваемая страница не найдена.
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="content-footer-wrapper">
|
||||||
|
<div class="content-footer">
|
||||||
|
<div class="region region-content-footer">
|
||||||
|
<div id="block-nubes-2025-formsubscribe" class="block block-block-content block-block-content3bffcd9d-439b-405d-857a-484f93f5ef25">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div class="clearfix text-formatted field field--name-body field--type-text-with-summary field--label-hidden field__item"><div class="front-form subscribe-form">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12 col-xxl-4">
|
||||||
|
<div class="form-title">Будьте в курсе наших событий</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-12 col-xxl-8">
|
||||||
|
<span id="webform-submission-subscribe-form-ajax-content"></span><div id="webform-submission-subscribe-form-ajax" class="webform-ajax-form-wrapper" data-effect="none" data-progress-type="fullscreen"><form class="webform-submission-form webform-submission-add-form webform-submission-subscribe-form webform-submission-subscribe-add-form js-webform-submit-once js-webform-details-toggle webform-details-toggle" data-drupal-selector="webform-submission-subscribe-add-form" action="/favicon.svg" method="post" id="webform-submission-subscribe-add-form" accept-charset="UTF-8">
|
||||||
|
|
||||||
|
<div class="row js-form-wrapper form-wrapper" data-drupal-selector="edit-row" id="edit-row"><div class="col-12 left-block js-form-wrapper form-wrapper" data-drupal-selector="edit-left-block" id="edit-left-block">
|
||||||
|
<div class="js-form-item form-item js-form-type-email form-type-email js-form-item-email form-item-email form-no-label">
|
||||||
|
<label for="edit-email" class="visually-hidden js-form-required form-required">Email</label>
|
||||||
|
|
||||||
|
<input data-drupal-selector="edit-email" type="email" id="edit-email" name="email" value="" size="60" maxlength="254" placeholder="name@yourcompany.com" class="form-email required form-control" required="required" aria-required="true" />
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-12 right-block js-form-wrapper form-wrapper" data-drupal-selector="edit-right-block" id="edit-right-block"><div data-drupal-selector="edit-button-block" id="edit-button-block" class="js-form-wrapper form-wrapper"><div data-drupal-selector="edit-actions" class="form-actions webform-actions js-form-wrapper form-wrapper" id="edit-actions">
|
||||||
|
<input class="webform-button--submit button-submit button button--primary js-form-submit form-submit btn btn-primary" data-drupal-selector="edit-actions-submit" data-disable-refocus="true" type="submit" id="edit-actions-submit" name="op" value="Подписаться" />
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="edit-politic" class="js-form-item form-item js-form-type-webform-markup form-type-webform-markup js-form-item-politic form-item-politic form-no-label">
|
||||||
|
<div class="text">Оставляя заявку, вы даёте согласие на обработку персональных данных и соглашаетесь с <a href="/privacy">политикой конфиденциальности</a></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<input autocomplete="off" data-drupal-selector="form-nhen6twbpxygx-wrujubwc2d1ijznzr7jxswhlgrsjo" type="hidden" name="form_build_id" value="form-NHeN6tWbpXygX_Wrujubwc2d1iJZnZr7jxSWHLgrsjo" />
|
||||||
|
|
||||||
|
|
||||||
|
<input data-drupal-selector="edit-webform-submission-subscribe-add-form" type="hidden" name="form_id" value="webform_submission_subscribe_add_form" />
|
||||||
|
|
||||||
|
|
||||||
|
<input data-drupal-selector="edit-honeypot-time" type="hidden" name="honeypot_time" value="9bZdK62OjSCXBM2poZI0RTdAU4f51tkqWUp5p0X-KXI" />
|
||||||
|
|
||||||
|
<div class="url-textfield js-form-wrapper form-wrapper" style="display: none !important;">
|
||||||
|
<div class="js-form-item form-item js-form-type-textfield form-type-textfield js-form-item-url form-item-url">
|
||||||
|
<label for="edit-url">Оставьте это поле пустым</label>
|
||||||
|
|
||||||
|
<input autocomplete="off" data-drupal-selector="edit-url" type="text" id="edit-url" name="url" value="" size="20" maxlength="128" class="form-text form-control" />
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div></div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<footer>
|
||||||
|
<div class="footer-wrapper">
|
||||||
|
<div class="region region-footer">
|
||||||
|
<div id="block-nubes-2025-cookie" class="block block-block-content block-block-contentbf796e1f-8995-4fcf-bd28-e62aa78f0972">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div class="clearfix text-formatted field field--name-body field--type-text-with-summary field--label-hidden field__item"><div id="cookie-consent-block" style="display: none;">
|
||||||
|
<div class="container">
|
||||||
|
<div class="wrapper">
|
||||||
|
<div id="cookie-consent-text">
|
||||||
|
<span class="title">Продолжая использовать наш сайт, вы соглашаетесь с <a href="/privacy">политикой использования Cookies</a>. </span>
|
||||||
|
</div>
|
||||||
|
<div id="button-wrapper">
|
||||||
|
<a class="button" id="cookie-consent-button">Согласен</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="close-button-wrapper">
|
||||||
|
<button type="button" class="btn-round" id="cookie-consent-close-button"></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div></div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div id="block-nubes-2025-footer" class="footer-content block block-block-content block-block-content632f6451-0c10-4825-936c-787ccd945b6e">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div class="clearfix text-formatted field field--name-body field--type-text-with-summary field--label-hidden field__item"><div class="row">
|
||||||
|
<div class="col-12 col-lg-6 order-lg-2 col-xxl-4 order-xxl-2 service">
|
||||||
|
|
||||||
|
|
||||||
|
<ul class="menu">
|
||||||
|
<li class="menu-item menu-item--expanded link-service"
|
||||||
|
>
|
||||||
|
<span item="link-service">Сервисы</span>
|
||||||
|
<ul class="menu">
|
||||||
|
<li class="menu-item menu-item--collapsed"
|
||||||
|
>
|
||||||
|
<a href="/cloud/resources" data-drupal-link-system-path="node/300">Облачные ресурсы</a>
|
||||||
|
</li>
|
||||||
|
<li class="menu-item menu-item--collapsed"
|
||||||
|
>
|
||||||
|
<a href="/ai" data-drupal-link-system-path="node/1067">Искусственный интеллект</a>
|
||||||
|
</li>
|
||||||
|
<li class="menu-item menu-item--collapsed"
|
||||||
|
>
|
||||||
|
<a href="/cloud/storage" data-drupal-link-system-path="node/308">Хранение данных</a>
|
||||||
|
</li>
|
||||||
|
<li class="menu-item menu-item--collapsed"
|
||||||
|
>
|
||||||
|
<a href="/cloud/workspace" data-drupal-link-system-path="node/309">Работа офиса</a>
|
||||||
|
</li>
|
||||||
|
<li class="menu-item menu-item--collapsed"
|
||||||
|
>
|
||||||
|
<a href="/cloud/backup" data-drupal-link-system-path="node/310">Резервное копирование и DR</a>
|
||||||
|
</li>
|
||||||
|
<li class="menu-item menu-item--collapsed"
|
||||||
|
>
|
||||||
|
<a href="/security" data-drupal-link-system-path="node/950">ИБ-сервисы</a>
|
||||||
|
</li>
|
||||||
|
<li class="menu-item menu-item--collapsed"
|
||||||
|
>
|
||||||
|
<a href="/dc" data-drupal-link-system-path="node/974">Дата-центр</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
</li>
|
||||||
|
<li class="menu-item menu-item--expanded"
|
||||||
|
>
|
||||||
|
<span>Пользователям</span>
|
||||||
|
<ul class="menu">
|
||||||
|
<li class="menu-item menu-item--collapsed"
|
||||||
|
>
|
||||||
|
<a href="/instructions" data-drupal-link-system-path="instructions">Инструкции</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
</li>
|
||||||
|
<li class="menu-item"
|
||||||
|
>
|
||||||
|
<a href="/partners" data-drupal-link-system-path="node/976">Партнерам</a>
|
||||||
|
</li>
|
||||||
|
<li class="menu-item menu-item--expanded"
|
||||||
|
>
|
||||||
|
<span>О нас</span>
|
||||||
|
<ul class="menu">
|
||||||
|
<li class="menu-item"
|
||||||
|
>
|
||||||
|
<a href="/company/about" data-drupal-link-system-path="node/135">О компании</a>
|
||||||
|
</li>
|
||||||
|
<li class="menu-item"
|
||||||
|
>
|
||||||
|
<a href="/company/team" data-drupal-link-system-path="node/1045">О команде</a>
|
||||||
|
</li>
|
||||||
|
<li class="menu-item"
|
||||||
|
>
|
||||||
|
<a href="/company/licenses" data-drupal-link-system-path="node/333">Лицензии и сертификаты</a>
|
||||||
|
</li>
|
||||||
|
<li class="menu-item menu-item--collapsed"
|
||||||
|
>
|
||||||
|
<a href="/blog" data-drupal-link-system-path="blog/all">Блог</a>
|
||||||
|
</li>
|
||||||
|
<li class="menu-item footer-d-none"
|
||||||
|
>
|
||||||
|
<a href="/contacts" item="footer-d-none" data-drupal-link-system-path="node/763">Контакты</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="col-12 col-lg-3 offset-lg-0 order-lg-3 col-xxl-3 offset-xxl-1 order-xxl-3 contact">
|
||||||
|
|
||||||
|
<div class="clearfix text-formatted field field--name-body field--type-text-with-summary field--label-hidden field__item"><div class="contact-wrapper" itemscope itemtype="https://schema.org/Organization">
|
||||||
|
<div itemprop="name" class="hidden d-none">НУБЕС (Nubes)</div>
|
||||||
|
<div class="title"><a href="/contacts">Контакты</a></div>
|
||||||
|
<ul class="contact-info-list" itemprop="contactPoint" itemscope itemtype="http://schema.org/ContactPoint">
|
||||||
|
<li class="hidden d-none" itemprop="contactType">Office</li>
|
||||||
|
<li class="phone callibri--phone" itemprop="telephone"><a href="tel:+74957894135" onclick="ym(68913385,'reachGoal','click_phone'); return true;">+7 (495) 789-4135</a></li>
|
||||||
|
<li class="email" itemprop="email"><a href="mailto:info@nubes.ru" onclick="ym(68913385,'reachGoal','сlicking_on_e-mail'); return true;">info@nubes.ru</a></li>
|
||||||
|
</ul>
|
||||||
|
<ul class="contact-info-list">
|
||||||
|
<li class="address" itemprop="address" itemscope itemtype="https://schema.org/PostalAddress"><span itemprop="postalCode">115404</span><span itemprop="addressCountry" class="hidden d-none">Россия</span>, <span itemprop="addressLocality">Москва</span>, <span itemprop="streetAddress"><span class="nowrap">1-я Стекольная улица</span>, д. 7, стр. 2</span></li>
|
||||||
|
</ul>
|
||||||
|
<div class="title">Техподдержка</div>
|
||||||
|
<ul class="contact-info-list" itemprop="contactPoint" itemscope itemtype="http://schema.org/ContactPoint">
|
||||||
|
<li class="hidden d-none" itemprop="contactType">Technical support</li>
|
||||||
|
<li class="phone" itemprop="telephone"><a href="tel:+74957894187">+7 (495) 789-4187</a></li>
|
||||||
|
<li class="email" itemprop="email"><a href="mailto:support@nubes.ru" onclick="ym(68913385,'reachGoal','e-mail_technical_support'); return true;">support@nubes.ru</a></li>
|
||||||
|
</ul>
|
||||||
|
</div></div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="col-12 col-lg-3 order-lg-1 col-xxl-4 order-xxl-1">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12 col-md-6 col-lg-12 copyright">
|
||||||
|
|
||||||
|
<div class="clearfix text-formatted field field--name-body field--type-text-with-summary field--label-hidden field__item"><div class="copyright-wrapper">
|
||||||
|
<div class="logo">
|
||||||
|
<a href="/" title="Главная" rel="home" class=""><span class="site-logo" title="Главная"></span></a>
|
||||||
|
</div>
|
||||||
|
<div class="year">© 2020 - 2026. ООО «Нубес»</div>
|
||||||
|
</div></div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="col-12 col-md-6 col-lg-12">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12 socnet">
|
||||||
|
|
||||||
|
<div class="clearfix text-formatted field field--name-body field--type-text-with-summary field--label-hidden field__item">
|
||||||
|
<div class="socnet-wrapper">
|
||||||
|
<div class="social-icon">
|
||||||
|
<a class="icon telegram" href="https://t.me/nubes_ru" target="_blank">Telegram</a>
|
||||||
|
<a class="icon habr" href="https://habr.com/ru/companies/nubes/articles/" target="_blank">Habr</a>
|
||||||
|
<a class="icon vk" href="https://vk.com/cloudnubes" target="_blank">VK</a>
|
||||||
|
<a class="icon youtube" href="https://www.youtube.com/@it-nubes" target="_blank">YouTube</a>
|
||||||
|
<a class="icon phone" href="tel:+74957894135" onclick="ym(68913385,'reachGoal','click_phone'); return true;">+7 (495) 789-4135</a>
|
||||||
|
<a class="icon email" href="mailto:info@nubes.ru" onclick="ym(68913385,'reachGoal','сlicking_on_e-mail'); return true;">info@nubes.ru</a>
|
||||||
|
</div>
|
||||||
|
</div></div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="col-12 politics">
|
||||||
|
|
||||||
|
<div class="clearfix text-formatted field field--name-body field--type-text-with-summary field--label-hidden field__item"><div class="politic-wrapper">
|
||||||
|
<div class="politic"><a href="/privacy">Политика конфиденциальности</a></div>
|
||||||
|
<div class="licenses"><a href="/company/licenses">Лицензии и сертификаты</a></div>
|
||||||
|
</div></div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div></div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<script type="application/json" data-drupal-selector="drupal-settings-json">{"path":{"baseUrl":"\/","pathPrefix":"","currentPath":"","currentPathIsAdmin":false,"isFront":false,"currentLanguage":"ru"},"pluralDelimiter":"\u0003","suppressDeprecationErrors":true,"ajaxPageState":{"libraries":"eJyFkAFuwyAMRS9EYKq08yCTuJTUwRk2W7rTj25Rmy6rJiHx_3-2hQnQn71yO7MLd-1Tz9mEJ3AUE5hVtMD82ojgg7_JbpSOQFF0yyNxAOpEL5Ry3JIJRSCimJ6JS-DFDXiESnoLfMqtCd0vf-fEMLgH11hBl7JiyUB2fKtYLvbIZfohuSmg9IkGF23Dzm4odW6VqzU5ekrxpNf3bLTJNaD4w8tht9IHhut8t94WRlh2IRJOmNUOqJBIrMA7_lukHCM9L1s_cMe_t_0rtFLDlNRz7vELtwfLbQ","theme":"nubes_2025","theme_token":null},"ajaxTrustedUrl":{"form_action_p_pvdeGsVG5zNF_XLGPTvYSKCf43t8qZYSwcfZl2uzM":true,"\/system\/404?destination=\/\u0026_exception_statuscode=404\u0026ajax_form=1":true},"back_to_top":{"back_to_top_button_trigger":100,"back_to_top_speed":1200,"back_to_top_prevent_on_mobile":false,"back_to_top_prevent_in_admin":false,"back_to_top_button_type":"image","back_to_top_button_text":"\u041d\u0430\u0432\u0435\u0440\u0445"},"colorbox":{"opacity":"0.85","current":"{current} \u0438\u0437 {total}","previous":"\u00ab \u041f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0438\u0439","next":"\u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u00bb","close":"\u0417\u0430\u043a\u0440\u044b\u0442\u044c","maxWidth":"98%","maxHeight":"98%","fixed":true,"mobiledetect":true,"mobiledevicewidth":"480px"},"data":{"extlink":{"extTarget":true,"extTargetAppendNewWindowDisplay":true,"extTargetAppendNewWindowLabel":"(opens in a new window)","extTargetNoOverride":true,"extNofollow":true,"extTitleNoOverride":false,"extNoreferrer":true,"extFollowNoOverride":true,"extClass":"0","extLabel":"(\u0432\u043d\u0435\u0448\u043d\u044f\u044f \u0441\u0441\u044b\u043b\u043a\u0430)","extImgClass":false,"extSubdomains":true,"extExclude":"","extInclude":"","extCssExclude":"","extCssInclude":"","extCssExplicit":"","extAlert":false,"extAlertText":"\u042d\u0442\u0430 \u0441\u0441\u044b\u043b\u043a\u0430 \u0432\u0435\u0434\u0451\u0442 \u043d\u0430 \u0432\u043d\u0435\u0448\u043d\u0438\u0439 \u0432\u0435\u0431-\u0441\u0430\u0439\u0442. \u041c\u044b \u043d\u0435 \u043d\u0435\u0441\u0451\u043c \u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0441\u0442\u0438 \u0437\u0430 \u0435\u0433\u043e \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435.","extHideIcons":false,"mailtoClass":"0","telClass":"","mailtoLabel":"(link sends email)","telLabel":"(link is a phone number)","extUseFontAwesome":false,"extIconPlacement":"append","extPreventOrphan":false,"extFaLinkClasses":"fa fa-external-link","extFaMailtoClasses":"fa fa-envelope-o","extAdditionalLinkClasses":"","extAdditionalMailtoClasses":"","extAdditionalTelClasses":"","extFaTelClasses":"fa fa-phone","allowedDomains":[],"extExcludeNoreferrer":""}},"ajax":{"edit-actions-submit":{"callback":"::submitAjaxForm","event":"click","effect":"none","speed":500,"progress":{"type":"fullscreen","message":""},"disable-refocus":true,"url":"\/system\/404?destination=\/\u0026_exception_statuscode=404\u0026ajax_form=1","httpMethod":"POST","dialogType":"ajax","submit":{"_triggering_element_name":"op","_triggering_element_value":"\u041f\u043e\u0434\u043f\u0438\u0441\u0430\u0442\u044c\u0441\u044f"}}},"user":{"uid":0,"permissionsHash":"fb32f6d7076721adcd4aad6923188bc589668cd9f49a20dcb0dce8ae7855298b"}}</script>
|
||||||
|
<script src="/files/js/js_h7vU87ZQu_K-2jVerZgYfkoh63tbMAtBN2UAg19it-Y.js?scope=footer&delta=0&language=ru&theme=nubes_2025&include=eJyFj2uKwzAMhC_kWEuh5zFyohqnipW15Da9_XqXQtg-KAikmW_mhyKO52DSZ4W432FWF0VMreJ6hP0cZh0YjdTcKCw1ygYTnbDxboRcOBeCB71zFpzgn-qsEuRiVAuyn78b1Zs_SV0cbdbbZ5hqWzu6S1daJA2Hr8MREktEHtRunSR3pfhbhPv2OOP2ZBLTQsX8RIaZ1Ste6GPIJCV-H1tIFdMz_3vjlem1xSVbkDLSD-hwmME"></script>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Yandex.Metrika counter -->
|
||||||
|
<script type="text/javascript" >
|
||||||
|
(function(m,e,t,r,i,k,a){m[i]=m[i]||function(){(m[i].a=m[i].a||[]).push(arguments)};
|
||||||
|
m[i].l=1*new Date();
|
||||||
|
for (var j = 0; j < document.scripts.length; j++) {if (document.scripts[j].src === r) { return; }}
|
||||||
|
k=e.createElement(t),a=e.getElementsByTagName(t)[0],k.async=1,k.src=r,a.parentNode.insertBefore(k,a)})
|
||||||
|
(window, document, "script", "https://mc.yandex.ru/metrika/tag.js", "ym");
|
||||||
|
|
||||||
|
ym(68913385, "init", {
|
||||||
|
clickmap:true,
|
||||||
|
trackLinks:true,
|
||||||
|
accurateTrackBounce:true,
|
||||||
|
webvisor:true
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
<noscript><div><img src="https://mc.yandex.ru/watch/68913385" style="position:absolute; left:-9999px;" alt="" /></div></noscript>
|
||||||
|
<!-- /Yandex.Metrika counter -->
|
||||||
|
|
||||||
|
<!--script src="//cdn.callibri.ru/callibri.js" type="text/javascript" charset="utf-8"></script-->
|
||||||
|
<script async src="//widgets.mango-office.ru/site/36934" type="text/javascript"></script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
(function(w, d, u, i, o, s, p) {
|
||||||
|
if (d.getElementById(i)) { return; } w['MangoObject'] = o;
|
||||||
|
w[o] = w[o] || function() { (w[o].q = w[o].q || []).push(arguments) }; w[o].u = u; w[o].t = 1 * new Date();
|
||||||
|
s = d.createElement('script'); s.async = 1; s.id = i; s.src = u; s.charset = 'utf-8';
|
||||||
|
p = d.getElementsByTagName('script')[0]; p.parentNode.insertBefore(s, p);
|
||||||
|
}(window, document, '//widgets.mango-office.ru/widgets/mango.js', 'mango-js', 'mgo'));
|
||||||
|
mgo({multichannel: {id: 32020}});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Разработка и поддержка: xTech
|
||||||
|
Development & Support: xTech
|
||||||
|
-->
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Reference in New Issue
Block a user