add new logic routes
This commit is contained in:
@@ -72,9 +72,14 @@ export interface NodeByUriResponse {
|
||||
}
|
||||
|
||||
export async function getNodeByURI(uri: string): Promise<NodeByUriResponse> {
|
||||
|
||||
console.log('Fetching node for URI:', uri);
|
||||
|
||||
const normalizedUri = uri.startsWith('/') ? uri : `/${uri}`;
|
||||
const cacheKey = `node-by-uri:${normalizedUri}`;
|
||||
|
||||
|
||||
|
||||
return await cache.wrap(
|
||||
cacheKey,
|
||||
async () => {
|
||||
|
||||
87
src/lib/detect-page-type.ts
Normal file
87
src/lib/detect-page-type.ts
Normal file
@@ -0,0 +1,87 @@
|
||||
export interface PageTypeInfo {
|
||||
type: 'single' | 'archive' | 'home' | 'unknown';
|
||||
contentType?: 'news' | 'post';
|
||||
categorySlug?: string;
|
||||
postSlug?: string;
|
||||
postId?: number;
|
||||
page: number;
|
||||
uriParts: string[];
|
||||
}
|
||||
|
||||
|
||||
export function detectPageType(uri: string): PageTypeInfo {
|
||||
// Убираем слэши по краям
|
||||
const cleanUri = uri.replace(/^\/|\/$/g, '');
|
||||
const parts = cleanUri ? cleanUri.split('/') : [];
|
||||
|
||||
// Ищем пагинацию
|
||||
const processedParts: string[] = [];
|
||||
let page = 1;
|
||||
|
||||
for (let i = 0; i < parts.length; i++) {
|
||||
if (parts[i] === 'page' && i + 1 < parts.length) {
|
||||
const pageNum = parseInt(parts[i + 1]);
|
||||
if (pageNum > 0) {
|
||||
page = pageNum;
|
||||
i++; // Пропускаем номер страницы
|
||||
continue;
|
||||
}
|
||||
}
|
||||
processedParts.push(parts[i]);
|
||||
}
|
||||
|
||||
// Определяем, это новость или нет
|
||||
const isNews = processedParts[0] === 'news';
|
||||
|
||||
// Для анализа убираем 'news' из начала если есть
|
||||
const partsWithoutNews = isNews ? processedParts.slice(1) : processedParts;
|
||||
const partsCount = partsWithoutNews.length;
|
||||
|
||||
if (partsCount === 0) {
|
||||
return {
|
||||
type: 'home',
|
||||
page: 1,
|
||||
uriParts: processedParts
|
||||
};
|
||||
}
|
||||
|
||||
// Одиночный пост
|
||||
if (partsCount === 1 || partsCount === 2) {
|
||||
const lastPart = partsWithoutNews[partsWithoutNews.length - 1];
|
||||
const match = lastPart.match(/-(\d+)$/);
|
||||
|
||||
if (match) {
|
||||
const id = parseInt(match[1]);
|
||||
if (id > 0) {
|
||||
const slugWithoutId = lastPart.substring(0, lastPart.lastIndexOf('-'));
|
||||
|
||||
return {
|
||||
type: 'single',
|
||||
contentType: isNews ? 'news' : 'post', // Теперь правильно
|
||||
categorySlug: partsCount === 2 ? partsWithoutNews[0] : undefined,
|
||||
postSlug: slugWithoutId,
|
||||
postId: id,
|
||||
page,
|
||||
uriParts: processedParts // Сохраняем исходные части
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Рубрика
|
||||
if (partsCount === 1) {
|
||||
return {
|
||||
type: 'archive',
|
||||
contentType: isNews ? 'news' : undefined,
|
||||
categorySlug: partsWithoutNews[0],
|
||||
page,
|
||||
uriParts: processedParts
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
type: 'unknown',
|
||||
page,
|
||||
uriParts: processedParts
|
||||
};
|
||||
}
|
||||
@@ -1,30 +1,23 @@
|
||||
---
|
||||
import MainLayout from '@layouts/MainLayout.astro';
|
||||
import { getNodeByURI, getCategoryPosts } from '@lib/api/all';
|
||||
import { detectPageType } from '@lib/detect-page-type';
|
||||
|
||||
export const prerender = false;
|
||||
|
||||
const { slug } = Astro.params;
|
||||
const uri = slug ? `/${slug}` : '/';
|
||||
const pathname = Astro.url.pathname; // "/news/society/chto-sluchilos-nochju-27-oktyabrya-2025-goda-1772178/"
|
||||
const pageInfo = detectPageType(pathname);
|
||||
|
||||
let response;
|
||||
let node = null;
|
||||
|
||||
try {
|
||||
response = await getNodeByURI(uri);
|
||||
node = response?.nodeByUri;
|
||||
} catch (error) {
|
||||
console.error('Error fetching node:', error);
|
||||
}
|
||||
|
||||
// ISR кэширование
|
||||
//Astro.response.headers.set(
|
||||
// 'Cache-Control',
|
||||
// 'public, s-maxage=3600, stale-while-revalidate=86400'
|
||||
//);
|
||||
// Или для полного URL
|
||||
const fullUrl = Astro.url.href;
|
||||
// Или для origin + pathname
|
||||
const fullPath = Astro.url.origin + Astro.url.pathname;
|
||||
---
|
||||
|
||||
News
|
||||
|
||||
<p>{uri}</p>
|
||||
|
||||
<MainLayout>
|
||||
<div>
|
||||
<p><strong>pathname:</strong> {pathname}</p>
|
||||
<p><strong>Page Type:</strong> {pageInfo.type}</p>
|
||||
<p><strong>Content Type:</strong> {pageInfo.contentType}</p>
|
||||
<p><strong>Full URL:</strong> {fullUrl}</p>
|
||||
</div>
|
||||
</MainLayout>
|
||||
|
||||
29
src/templates/NewsSingle.astro
Normal file
29
src/templates/NewsSingle.astro
Normal file
@@ -0,0 +1,29 @@
|
||||
---
|
||||
import { getPostById } from '@lib/api/all';
|
||||
|
||||
interface Props {
|
||||
postId?: number;
|
||||
pageInfo?: any;
|
||||
}
|
||||
|
||||
const { postId, pageInfo } = Astro.props;
|
||||
|
||||
let post = null;
|
||||
if (postId) {
|
||||
const response = await getPostById(postId);
|
||||
post = response?.post;
|
||||
}
|
||||
---
|
||||
|
||||
{post ? (
|
||||
<article class="news-single">
|
||||
<h1>{post.title}</h1>
|
||||
<div class="meta">
|
||||
{post.date && <time>{new Date(post.date).toLocaleDateString('ru-RU')}</time>}
|
||||
</div>
|
||||
{post.content && <div set:html={post.content} />}
|
||||
</article>
|
||||
) : (
|
||||
<div>Новость не найдена</div>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user