ваше сообщение коммита
This commit is contained in:
@@ -18,6 +18,13 @@
|
|||||||
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
<noscript>
|
||||||
|
<div style="padding: 20px; text-align: center; font-family: Arial, sans-serif;">
|
||||||
|
<h1>JavaScript требуется</h1>
|
||||||
|
<p>Для работы этого приложения необходимо включить JavaScript в вашем браузере.</p>
|
||||||
|
<p>Please enable JavaScript in your browser to use this application.</p>
|
||||||
|
</div>
|
||||||
|
</noscript>
|
||||||
<div id="app"></div>
|
<div id="app"></div>
|
||||||
<script type="module" src="/src/main.js"></script>
|
<script type="module" src="/src/main.js"></script>
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
@@ -14,20 +14,32 @@ http {
|
|||||||
# limit_req_zone $binary_remote_addr zone=api_limit_per_ip:10m rate=5r/s;
|
# limit_req_zone $binary_remote_addr zone=api_limit_per_ip:10m rate=5r/s;
|
||||||
|
|
||||||
# Блокировка известных сканеров и вредоносных ботов (исключая легитимные поисковые боты)
|
# Блокировка известных сканеров и вредоносных ботов (исключая легитимные поисковые боты)
|
||||||
|
# ВАЖНО: Сначала проверяем легитимные боты, потом блокируем вредоносные
|
||||||
map $http_user_agent $bad_bot {
|
map $http_user_agent $bad_bot {
|
||||||
default 0;
|
default 0;
|
||||||
# Разрешаем легитимные поисковые боты
|
# Разрешаем легитимные поисковые боты (проверяем ПЕРВЫМИ)
|
||||||
~*googlebot 0;
|
~*googlebot 0;
|
||||||
|
~*google.*bot 0;
|
||||||
~*bingbot 0;
|
~*bingbot 0;
|
||||||
|
~*bingpreview 0;
|
||||||
~*slurp 0;
|
~*slurp 0;
|
||||||
~*duckduckbot 0;
|
~*duckduckbot 0;
|
||||||
~*baiduspider 0;
|
~*baiduspider 0;
|
||||||
~*yandex 0;
|
~*yandex 0;
|
||||||
|
~*yandexbot 0;
|
||||||
~*sogou 0;
|
~*sogou 0;
|
||||||
~*exabot 0;
|
~*exabot 0;
|
||||||
~*facebot 0;
|
~*facebot 0;
|
||||||
|
~*facebookexternalhit 0;
|
||||||
~*ia_archiver 0;
|
~*ia_archiver 0;
|
||||||
# Блокируем вредоносные боты и сканеры
|
~*archive\.org_bot 0;
|
||||||
|
~*applebot 0;
|
||||||
|
~*twitterbot 0;
|
||||||
|
~*linkedinbot 0;
|
||||||
|
~*slackbot 0;
|
||||||
|
~*whatsapp 0;
|
||||||
|
~*telegrambot 0;
|
||||||
|
# Блокируем вредоносные боты и сканеры (только если не поисковый бот)
|
||||||
~*sqlmap 1;
|
~*sqlmap 1;
|
||||||
~*nikto 1;
|
~*nikto 1;
|
||||||
~*dirb 1;
|
~*dirb 1;
|
||||||
@@ -40,10 +52,12 @@ http {
|
|||||||
~*masscan 1;
|
~*masscan 1;
|
||||||
~*nmap 1;
|
~*nmap 1;
|
||||||
~*scanner 1;
|
~*scanner 1;
|
||||||
~*Chrome/[1-4][0-9]\. 1;
|
# Блокируем старые версии браузеров (только если это не поисковый бот)
|
||||||
~*Firefox/[1-6][0-9]\. 1;
|
# Убираем блокировку старых браузеров - может блокировать легитимных ботов
|
||||||
~*Safari/[1-9]\. 1;
|
# ~*Chrome/[1-4][0-9]\. 1;
|
||||||
~*MSIE\ [1-9]\. 1;
|
# ~*Firefox/[1-6][0-9]\. 1;
|
||||||
|
# ~*Safari/[1-9]\. 1;
|
||||||
|
# ~*MSIE\ [1-9]\. 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
# HTTP сервер - редирект на HTTPS
|
# HTTP сервер - редирект на HTTPS
|
||||||
|
|||||||
@@ -246,6 +246,120 @@ watch(() => page.value?.content, () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Установка мета-тегов для SEO
|
||||||
|
function updatePageMetaTags() {
|
||||||
|
if (!page.value) return;
|
||||||
|
|
||||||
|
// Парсим seo, если это строка
|
||||||
|
let seoData = page.value.seo;
|
||||||
|
if (typeof seoData === 'string') {
|
||||||
|
try {
|
||||||
|
seoData = JSON.parse(seoData);
|
||||||
|
} catch (e) {
|
||||||
|
console.warn('Ошибка парсинга SEO данных:', e);
|
||||||
|
seoData = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const title = seoData?.title || page.value.title || 'Публичная страница';
|
||||||
|
const description = seoData?.description || page.value.summary || '';
|
||||||
|
const keywords = seoData?.keywords || '';
|
||||||
|
|
||||||
|
// Определяем canonical URL
|
||||||
|
const pageUrl = page.value.slug
|
||||||
|
? `${window.location.origin}/content/published/${encodeURIComponent(page.value.slug)}`
|
||||||
|
: `${window.location.origin}/content/published?page=${page.value.id}`;
|
||||||
|
|
||||||
|
// Обновляем title
|
||||||
|
document.title = title;
|
||||||
|
|
||||||
|
// Обновляем или создаем meta теги
|
||||||
|
const updateOrCreateMeta = (name, content, attribute = 'name') => {
|
||||||
|
if (!content) return;
|
||||||
|
let meta = document.querySelector(`meta[${attribute}="${name}"]`);
|
||||||
|
if (!meta) {
|
||||||
|
meta = document.createElement('meta');
|
||||||
|
meta.setAttribute(attribute, name);
|
||||||
|
document.head.appendChild(meta);
|
||||||
|
}
|
||||||
|
meta.setAttribute('content', content);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Meta description
|
||||||
|
updateOrCreateMeta('description', description);
|
||||||
|
|
||||||
|
// Meta keywords
|
||||||
|
if (keywords) {
|
||||||
|
updateOrCreateMeta('keywords', keywords);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Canonical URL
|
||||||
|
let canonical = document.querySelector('link[rel="canonical"]');
|
||||||
|
if (!canonical) {
|
||||||
|
canonical = document.createElement('link');
|
||||||
|
canonical.setAttribute('rel', 'canonical');
|
||||||
|
document.head.appendChild(canonical);
|
||||||
|
}
|
||||||
|
canonical.setAttribute('href', pageUrl);
|
||||||
|
|
||||||
|
// Open Graph теги для социальных сетей
|
||||||
|
updateOrCreateMeta('og:title', title, 'property');
|
||||||
|
updateOrCreateMeta('og:description', description, 'property');
|
||||||
|
updateOrCreateMeta('og:type', 'article', 'property');
|
||||||
|
updateOrCreateMeta('og:url', pageUrl, 'property');
|
||||||
|
|
||||||
|
// Robots meta
|
||||||
|
updateOrCreateMeta('robots', 'index, follow');
|
||||||
|
|
||||||
|
// Добавляем JSON-LD разметку для статьи
|
||||||
|
addArticleJsonLd(page.value, pageUrl, seoData);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Добавляем JSON-LD разметку для статьи
|
||||||
|
function addArticleJsonLd(pageData, canonicalUrl, seoData) {
|
||||||
|
// Удаляем старую разметку, если есть
|
||||||
|
const oldScript = document.querySelector('script[type="application/ld+json"][data-public-article]');
|
||||||
|
if (oldScript) {
|
||||||
|
oldScript.remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
const articleJsonLd = {
|
||||||
|
'@context': 'https://schema.org',
|
||||||
|
'@type': 'Article',
|
||||||
|
'headline': seoData?.title || pageData.title || '',
|
||||||
|
'description': seoData?.description || pageData.summary || '',
|
||||||
|
'datePublished': pageData.created_at || '',
|
||||||
|
'dateModified': pageData.updated_at || pageData.created_at || '',
|
||||||
|
'url': canonicalUrl,
|
||||||
|
'author': {
|
||||||
|
'@type': 'Organization',
|
||||||
|
'name': 'HB3 Accelerator'
|
||||||
|
},
|
||||||
|
'publisher': {
|
||||||
|
'@type': 'Organization',
|
||||||
|
'name': 'HB3 Accelerator',
|
||||||
|
'url': window.location.origin
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (pageData.category) {
|
||||||
|
articleJsonLd.articleSection = pageData.category;
|
||||||
|
}
|
||||||
|
|
||||||
|
const script = document.createElement('script');
|
||||||
|
script.type = 'application/ld+json';
|
||||||
|
script.setAttribute('data-public-article', 'true');
|
||||||
|
script.textContent = JSON.stringify(articleJsonLd);
|
||||||
|
document.head.appendChild(script);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Отслеживаем загрузку страницы и обновляем мета-теги
|
||||||
|
watch(() => page.value, (newPage) => {
|
||||||
|
if (newPage) {
|
||||||
|
updatePageMetaTags();
|
||||||
|
}
|
||||||
|
}, { immediate: true });
|
||||||
|
|
||||||
// Загрузка данных
|
// Загрузка данных
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
loadPage();
|
loadPage();
|
||||||
|
|||||||
@@ -158,8 +158,56 @@ async function loadPages() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Установка мета-тегов для SEO
|
||||||
|
function updatePublicPagesMetaTags() {
|
||||||
|
const title = 'Публичные документы - HB3 Accelerator';
|
||||||
|
const description = 'Опубликованные документы и материалы платформы Digital Legal Entity. Публичная документация, статьи и информационные материалы.';
|
||||||
|
const keywords = 'публичные документы, документация, Digital Legal Entity, DLE, публикации';
|
||||||
|
const canonicalUrl = `${window.location.origin}/content/published`;
|
||||||
|
|
||||||
|
// Обновляем title
|
||||||
|
document.title = title;
|
||||||
|
|
||||||
|
// Обновляем или создаем meta теги
|
||||||
|
const updateOrCreateMeta = (name, content, attribute = 'name') => {
|
||||||
|
if (!content) return;
|
||||||
|
let meta = document.querySelector(`meta[${attribute}="${name}"]`);
|
||||||
|
if (!meta) {
|
||||||
|
meta = document.createElement('meta');
|
||||||
|
meta.setAttribute(attribute, name);
|
||||||
|
document.head.appendChild(meta);
|
||||||
|
}
|
||||||
|
meta.setAttribute('content', content);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Meta description
|
||||||
|
updateOrCreateMeta('description', description);
|
||||||
|
|
||||||
|
// Meta keywords
|
||||||
|
updateOrCreateMeta('keywords', keywords);
|
||||||
|
|
||||||
|
// Canonical URL
|
||||||
|
let canonical = document.querySelector('link[rel="canonical"]');
|
||||||
|
if (!canonical) {
|
||||||
|
canonical = document.createElement('link');
|
||||||
|
canonical.setAttribute('rel', 'canonical');
|
||||||
|
document.head.appendChild(canonical);
|
||||||
|
}
|
||||||
|
canonical.setAttribute('href', canonicalUrl);
|
||||||
|
|
||||||
|
// Open Graph теги для социальных сетей
|
||||||
|
updateOrCreateMeta('og:title', title, 'property');
|
||||||
|
updateOrCreateMeta('og:description', description, 'property');
|
||||||
|
updateOrCreateMeta('og:type', 'website', 'property');
|
||||||
|
updateOrCreateMeta('og:url', canonicalUrl, 'property');
|
||||||
|
|
||||||
|
// Robots meta
|
||||||
|
updateOrCreateMeta('robots', 'index, follow');
|
||||||
|
}
|
||||||
|
|
||||||
// Загрузка данных
|
// Загрузка данных
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
updatePublicPagesMetaTags();
|
||||||
loadPages();
|
loadPages();
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ NC='\033[0m' # No Color
|
|||||||
echo -e "${GREEN}🔄 Синхронизация кода с VDS...${NC}"
|
echo -e "${GREEN}🔄 Синхронизация кода с VDS...${NC}"
|
||||||
|
|
||||||
# Параметры VDS (из настроек)
|
# Параметры VDS (из настроек)
|
||||||
VDS_HOST="185.221.214.140"
|
VDS_HOST="185.26.121.127"
|
||||||
VDS_USER="root"
|
VDS_USER="root"
|
||||||
VDS_PORT="22"
|
VDS_PORT="22"
|
||||||
VDS_PATH="/home/docker/dapp"
|
VDS_PATH="/home/docker/dapp"
|
||||||
@@ -139,6 +139,12 @@ scp $SCP_OPTS ./backend/Dockerfile "$VDS_USER@$VDS_HOST:$VDS_PATH/backend/Docker
|
|||||||
scp $SCP_OPTS ./frontend/Dockerfile "$VDS_USER@$VDS_HOST:$VDS_PATH/frontend/Dockerfile" 2>/dev/null || true
|
scp $SCP_OPTS ./frontend/Dockerfile "$VDS_USER@$VDS_HOST:$VDS_PATH/frontend/Dockerfile" 2>/dev/null || true
|
||||||
scp $SCP_OPTS ./frontend/nginx.Dockerfile "$VDS_USER@$VDS_HOST:$VDS_PATH/frontend/nginx.Dockerfile" 2>/dev/null || true
|
scp $SCP_OPTS ./frontend/nginx.Dockerfile "$VDS_USER@$VDS_HOST:$VDS_PATH/frontend/nginx.Dockerfile" 2>/dev/null || true
|
||||||
|
|
||||||
|
# Синхронизация nginx конфигураций (критично для SEO исправлений)
|
||||||
|
echo -e "${YELLOW}📦 Синхронизация nginx конфигураций...${NC}"
|
||||||
|
scp $SCP_OPTS ./frontend/nginx-simple.conf "$VDS_USER@$VDS_HOST:$VDS_PATH/frontend/nginx-simple.conf" 2>/dev/null || true
|
||||||
|
scp $SCP_OPTS ./frontend/nginx-local.conf "$VDS_USER@$VDS_HOST:$VDS_PATH/frontend/nginx-local.conf" 2>/dev/null || true
|
||||||
|
scp $SCP_OPTS ./frontend/docker-entrypoint.sh "$VDS_USER@$VDS_HOST:$VDS_PATH/frontend/docker-entrypoint.sh" 2>/dev/null || true
|
||||||
|
|
||||||
echo -e "${GREEN}✅ Синхронизация завершена!${NC}"
|
echo -e "${GREEN}✅ Синхронизация завершена!${NC}"
|
||||||
|
|
||||||
# Спрашиваем, нужно ли пересобрать образы
|
# Спрашиваем, нужно ли пересобрать образы
|
||||||
|
|||||||
Reference in New Issue
Block a user