- Aggiunto le Statistiche di visualizzazione delle pagine.
- Aggiunto il componente per visualizzare le statistiche
This commit is contained in:
@@ -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
0
src/components/CPageViewStats/CPageViewStats.scss
Executable file
0
src/components/CPageViewStats/CPageViewStats.scss
Executable file
120
src/components/CPageViewStats/CPageViewStats.ts
Executable file
120
src/components/CPageViewStats/CPageViewStats.ts
Executable 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,
|
||||
};
|
||||
},
|
||||
});
|
||||
153
src/components/CPageViewStats/CPageViewStats.vue
Executable file
153
src/components/CPageViewStats/CPageViewStats.vue
Executable 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>
|
||||
1
src/components/CPageViewStats/index.ts
Executable file
1
src/components/CPageViewStats/index.ts
Executable file
@@ -0,0 +1 @@
|
||||
export {default as CPageViewStats} from './CPageViewStats.vue'
|
||||
Reference in New Issue
Block a user