122 lines
3.9 KiB
JavaScript
122 lines
3.9 KiB
JavaScript
import { getSiteSettings } from '../repositories/content-repository'
|
|
import { getAnalyticsSummary } from '../repositories/analytics-repository'
|
|
import { getPublicBlogStatistics } from '../repositories/blog-statistics-repository'
|
|
|
|
/**
|
|
* 초 단위 체류 시간을 짧은 한국어 문자열로 변환한다.
|
|
* @param {number} seconds - 초 단위 시간
|
|
* @returns {string} 표시 문자열
|
|
*/
|
|
const formatDuration = (seconds) => {
|
|
const safeSeconds = Math.max(0, Math.round(Number(seconds) || 0))
|
|
|
|
if (safeSeconds < 60) {
|
|
return `${safeSeconds}초`
|
|
}
|
|
|
|
const minutes = Math.floor(safeSeconds / 60)
|
|
const restSeconds = safeSeconds % 60
|
|
|
|
return restSeconds > 0 ? `${minutes}분 ${restSeconds}초` : `${minutes}분`
|
|
}
|
|
|
|
/**
|
|
* 숫자를 한국어 단위 문자열로 변환한다.
|
|
* @param {number} value - 숫자 값
|
|
* @param {string} unit - 단위
|
|
* @returns {string} 표시 문자열
|
|
*/
|
|
const formatNumberLabel = (value, unit) => `${Number(value || 0).toLocaleString('ko-KR')}${unit}`
|
|
|
|
/**
|
|
* gethomepage 커스텀 API용 사이트 요약 위젯 데이터를 반환한다.
|
|
* @returns {Promise<Object>} 위젯 데이터
|
|
*/
|
|
export default defineEventHandler(async () => {
|
|
const [settings, summary, statistics] = await Promise.all([
|
|
getSiteSettings(),
|
|
getAnalyticsSummary({ days: 1 }),
|
|
getPublicBlogStatistics()
|
|
])
|
|
const avgEngagedSeconds = summary.todayAvgEngagedSeconds || summary.avgEngagedSeconds || 0
|
|
|
|
return {
|
|
title: settings.title || 'sori.studio',
|
|
updatedAt: new Date().toISOString(),
|
|
todayVisitors: summary.todayVisitors,
|
|
totalVisitors: statistics.totalVisitors,
|
|
todayPageViews: summary.todayPageViews,
|
|
totalPageViews: statistics.totalPageViews,
|
|
onlineNow: summary.onlineNow,
|
|
loggedInNow: summary.loggedInNow,
|
|
avgEngagedSeconds,
|
|
visitorsLast7Days: summary.visitorsLast7Days,
|
|
visitorsLast30Days: summary.visitorsLast30Days,
|
|
visitorsLast180Days: summary.visitorsLast180Days,
|
|
visitorsLast365Days: summary.visitorsLast365Days,
|
|
pageViewsLast30Days: summary.pageViewsLast30Days,
|
|
totalPosts: statistics.totalPosts,
|
|
totalComments: statistics.totalComments,
|
|
totalPages: statistics.totalPages,
|
|
totalTags: statistics.totalTags,
|
|
totalMembers: statistics.totalMembers,
|
|
items: [
|
|
{
|
|
name: '오늘 방문자',
|
|
label: formatNumberLabel(summary.todayVisitors, '명'),
|
|
value: summary.todayVisitors
|
|
},
|
|
{
|
|
name: '오늘 페이지뷰',
|
|
label: formatNumberLabel(summary.todayPageViews, '회'),
|
|
value: summary.todayPageViews
|
|
},
|
|
{
|
|
name: '최근 7일 방문자',
|
|
label: formatNumberLabel(summary.visitorsLast7Days, '명'),
|
|
value: summary.visitorsLast7Days
|
|
},
|
|
{
|
|
name: '최근 30일 방문자',
|
|
label: formatNumberLabel(summary.visitorsLast30Days, '명'),
|
|
value: summary.visitorsLast30Days
|
|
},
|
|
{
|
|
name: '최근 6개월 방문자',
|
|
label: formatNumberLabel(summary.visitorsLast180Days, '명'),
|
|
value: summary.visitorsLast180Days
|
|
},
|
|
{
|
|
name: '최근 1년 방문자',
|
|
label: formatNumberLabel(summary.visitorsLast365Days, '명'),
|
|
value: summary.visitorsLast365Days
|
|
},
|
|
{
|
|
name: '현재 접속자',
|
|
label: formatNumberLabel(summary.onlineNow, '명'),
|
|
value: summary.onlineNow
|
|
},
|
|
{
|
|
name: '평균 체류',
|
|
label: formatDuration(avgEngagedSeconds),
|
|
value: avgEngagedSeconds
|
|
},
|
|
{
|
|
name: '누적 방문자',
|
|
label: formatNumberLabel(statistics.totalVisitors, '명'),
|
|
value: statistics.totalVisitors
|
|
},
|
|
{
|
|
name: '전체 게시글',
|
|
label: formatNumberLabel(statistics.totalPosts, '개'),
|
|
value: statistics.totalPosts
|
|
},
|
|
{
|
|
name: '전체 댓글',
|
|
label: formatNumberLabel(statistics.totalComments, '개'),
|
|
value: statistics.totalComments
|
|
}
|
|
]
|
|
}
|
|
})
|