astro_avtourist/frontend/src/pages/api/increment-views.ts
Web-serfer e7700a3391 opt: упростить счетчики - одна запись в БД вместо тысяч
- site_stats: 1 запись с полями today/total вместо site_visitors
- posts: today_views + last_reset вместо post_views коллекции
- Удалены старые коллекции site_visitors и post_views
2026-05-07 16:55:35 +05:00

63 lines
No EOL
1.9 KiB
TypeScript

import type { APIRoute } from 'astro';
const PB_POCKETBASE_URL = import.meta.env.PB_POCKETBASE_URL || 'http://127.0.0.1:8090';
const POCKETBASE_ID_REGEX = /^[a-z0-9]{15}$/;
function jsonResponse(data: object, status = 200): Response {
return new Response(JSON.stringify(data), {
status,
headers: { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*' }
});
}
export const GET: APIRoute = async ({ url }) => {
try {
const postId = url.searchParams.get('postId');
if (!postId || !POCKETBASE_ID_REGEX.test(postId)) {
return jsonResponse({ error: 'Некорректный postId' }, 400);
}
// Получаем пост
let post;
try {
post = await fetch(`${PB_POCKETBASE_URL}/api/collections/posts/records/${postId}`, {
headers: { 'Content-Type': 'application/json' }
}).then(r => r.json());
} catch {
return jsonResponse({ error: 'Пост не найден' }, 404);
}
if (!post || !post.id) {
return jsonResponse({ error: 'Пост не найден' }, 404);
}
const now = new Date();
const todayStr = now.toISOString().split('T')[0];
let { views = 0, today_views = 0, last_reset = '' } = post;
// Если новый день - сбрасываем today_views
if (last_reset !== todayStr) {
today_views = 0;
last_reset = todayStr;
}
// Инкремент
views++;
today_views++;
// Обновляем пост
await fetch(`${PB_POCKETBASE_URL}/api/collections/posts/records/${postId}`, {
method: 'PATCH',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ views, today_views, last_reset })
});
return jsonResponse({ views, today_views }, 200);
} catch (error) {
console.error('[Increment Views] Error:', error);
return jsonResponse({ error: 'Внутренняя ошибка сервера' }, 500);
}
};