- Aggiunto le Statistiche di visualizzazione delle pagine.

- Aggiunto il componente per visualizzare le statistiche
This commit is contained in:
Surya Paolo
2025-07-08 16:19:12 +02:00
parent 7f5ff3da64
commit 40ec5465b2
61 changed files with 3593791 additions and 654 deletions

View File

@@ -21,6 +21,7 @@ import { CMyActivities } from '@src/components/CMyActivities'
import { CECommerce } from '@src/components/CECommerce'
import { CStatMacro } from '@src/components/CStatMacro'
import { CSearchProduct } from '@src/components/CSearchProduct'
import { CPageViewStats } from '@src/components/CPageViewStats'
import { CQRCode } from '@src/components/CQRCode'
import { CAITools } from '@src/components/CAITools'
import { CCatalogo } from '@src/components/CCatalogo'
@@ -78,7 +79,7 @@ export default defineComponent({
CVisuVideoPromoAndPDF, CECommerce, CCatalogo, CRaccolta, CAITools, CStatMacro,
CMapComuni, CMapUsers, CMapGetCoordinates, CMapEditAddressByCoord,
CDashGroup, CMovements, CGridOriz, CQRCode, CCatalogList,
CSearchProduct, CRaccoltaCataloghi,
CSearchProduct, CRaccoltaCataloghi, CPageViewStats,
// , //CMapMarker,
},
emits: ['selElemClick'],

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,120 @@
import { defineComponent, ref, onMounted } from 'vue';
import { tools } from '@tools';
import { Api } from 'app/src/store/Api';
interface WeeklyStat {
year: number;
week: number;
topPages: Array<{ url: string; count: number }>;
}
export default defineComponent({
name: 'CPageViewStats',
props: {},
emits: [],
setup() {
// Stati
const stats = ref({
total: 0,
today: 0,
week: 0,
month: 0,
topPages: [],
});
const selectedYear = ref(new Date().getFullYear());
const selectedWeek = ref(1);
const weeklyStats = ref([]);
const years = Array.from({ length: 3 }, (_, i) => new Date().getFullYear() - i);
const weeks = Array.from({ length: 52 }, (_, i) => i + 1);
const columns = [
{
name: 'url',
label: 'Pagina',
field: (row) => row.url,
format: (val) => val.replace(/^https?:\/\/[^/]+/, ''),
align: 'left',
},
{
name: 'count',
label: 'Visite',
field: 'count',
align: 'right',
},
];
const users = ref([]);
const selectedUser = ref<{ label: string; value: string } | null>(null);
const uniqueMode = ref(false);
const userOptions = ref<{ label: string; value: string }[]>([]);
async function loadStats() {
try {
const params = {} as any;
if (selectedUser.value?.value) {
params.userId = selectedUser.value.value;
}
if (uniqueMode.value) {
params.unique = true;
}
params.year = selectedYear.value;
params.week = selectedWeek.value;
// Carica statistiche generali
const statsRes = await Api.SendReq('/api/pageviews/stats', 'GET', params);
stats.value = statsRes.data;
// Carica statistiche settimanali
const weeklyRes = await Api.SendReq(
'/api/pageviews/weekly-top-pages',
'GET',
params
);
weeklyStats.value = weeklyRes.data;
// Se non ci sono utenti ancora caricati
if (users.value.length === 0) {
const usersRes = await Api.SendReq('/api/pageviews/users', 'GET', null);
users.value = usersRes.data;
const uniqueUsernamesOrIds = [
...new Set(
users.value.map((u: any) => u.username || u.userId).filter(Boolean)
),
];
userOptions.value = [
{ label: 'Tutti gli utenti', value: '' },
...uniqueUsernamesOrIds.map((name) => ({ label: name, value: name })),
];
}
} catch (error) {
console.error('Errore nel caricamento delle statistiche:', error);
}
}
onMounted(() => {
selectedWeek.value = tools.getWeekOfYear(new Date());
loadStats();
});
return {
stats,
weeklyStats,
users,
selectedUser,
userOptions,
loadStats,
tools,
uniqueMode,
columns,
years,
weeks,
selectedYear,
selectedWeek,
};
},
});

View File

@@ -0,0 +1,153 @@
<template>
<q-page
class="q-pa-md"
v-if="stats"
>
<div class="row q-mb-md">
<div class="col">
<h5>Statistiche Visite</h5>
</div>
<div class="row q-mb-md items-center">
<q-toggle
v-model="uniqueMode"
label="Mostra solo pagine uniche per utente"
@update:model-value="loadStats"
/>
</div>
<div class="col-auto">
<q-select
v-model="selectedUser"
:options="userOptions"
label="Filtra per utente"
dense
outlined
style="min-width: 200px"
@update:model-value="loadStats"
/>
</div>
</div>
<div class="row q-col-gutter-md">
<div class="col-xs-12 col-sm-6 col-md-4">
<q-card>
<q-card-section>
<div class="text-h6">Totale Pagine Visitate</div>
<div class="text-h4">{{ stats?.total }}</div>
</q-card-section>
</q-card>
</div>
<div class="col-xs-12 col-sm-6 col-md-4">
<q-card>
<q-card-section>
<div class="text-h6">Pagine Oggi</div>
<div class="text-h4">{{ stats.today }}</div>
</q-card-section>
</q-card>
</div>
<div class="col-xs-12 col-sm-6 col-md-4">
<q-card>
<q-card-section>
<div class="text-h6">Pagine Questa Settimana</div>
<div class="text-h4">{{ stats.week }}</div>
</q-card-section>
</q-card>
</div>
<div class="col-xs-12 col-sm-6 col-md-4">
<q-card>
<q-card-section>
<div class="text-h6">Pagine Questo Mese</div>
<div class="text-h4">{{ stats.month }}</div>
</q-card-section>
</q-card>
</div>
</div>
<div class="q-mt-md">
<h6>Pagine più visitate</h6>
<q-list
bordered
separator
>
<q-item
v-for="(page, index) in stats.topPages"
:key="index"
>
<q-item-section>{{ tools.escludiUrlDominio(page._id) }}</q-item-section>
<q-item-section side>{{ page.count }} visite</q-item-section>
</q-item>
</q-list>
</div>
<div class="q-mt-md">
<h6>Top Pagine per Settimana</h6>
<div class="row q-col-gutter-md">
<div class="col-6">
<q-select
v-model="selectedYear"
:options="years"
label="Anno"
style="max-width: 300px"
outlined
@update:model-value="loadStats"
/>
</div>
<div class="col-6">
<q-select
v-model="selectedWeek"
:options="
weeks.map((w) => {
const date = new Date(Date.UTC(selectedYear, 0, 4 + (w - 1) * 7));
const start = new Date(Date.UTC(selectedYear, 0, 1 + (w - 1) * 7));
const end = new Date(Date.UTC(selectedYear, 0, 7 + (w - 1) * 7));
return {
label: `dal ${start.toLocaleString('it-IT', { day: '2-digit', month: 'long' })} al ${end.toLocaleString('it-IT', { day: '2-digit', month: 'long' })}`,
value: w,
};
})
"
label="Settimana"
outlined
emit-value
map-options
@update:model-value="loadStats"
/>
<div class="col-auto">
<q-btn
:disable="selectedWeek === 1"
icon="chevron_left"
flat
round
dense
@click="selectedWeek--; loadStats()"
/>
<q-btn
:disable="selectedWeek === weeks.length"
icon="chevron_right"
flat
round
dense
@click="selectedWeek++; loadStats()"
/>
</div>
</div>
</div>
<q-table
class="q-mt-md q-pa-sm"
:rows="weeklyStats"
:columns="columns"
row-key="url"
flat
bordered
/>
</div>
</q-page>
</template>
<script lang="ts" src="./CPageViewStats.ts"></script>
<style lang="scss" scoped>
@import './CPageViewStats.scss';
</style>

View File

@@ -0,0 +1 @@
export {default as CPageViewStats} from './CPageViewStats.vue'