sposchedule
155 строк · 4.5 Кб
1<script setup lang="ts">
2import DataTable from 'primevue/datatable';
3import Column from 'primevue/column';
4import DatePicker from 'primevue/datepicker';
5import Button from 'primevue/button';
6import { useGroupsQuery } from '@/queries/groups';
7import MultiSelect from 'primevue/multiselect';
8import { computed, ref } from 'vue';
9import { useAnalyticsSchedulesQuery } from '@/queries/schedules';
10import { useDateFormat } from '@vueuse/core';
11
12const { data: groups } = useGroupsQuery();
13
14const rangeDates = ref(null);
15const selectedGroups = ref(null);
16
17const start_date = computed(() =>
18rangeDates.value?.[0]
19? useDateFormat(rangeDates?.value?.[0], 'DD.MM.YYYY').value
20: null
21);
22const end_date = computed(() =>
23rangeDates.value?.[1]
24? useDateFormat(rangeDates?.value?.[1], 'DD.MM.YYYY').value
25: null
26);
27const groups_ids = computed(() =>
28selectedGroups.value?.map(group => group.id)
29);
30
31const { data, isLoading } = useAnalyticsSchedulesQuery(
32start_date,
33end_date,
34groups_ids
35);
36
37const dt = ref();
38
39const exportCSV = () => {
40// Формируем данные для экспорта
41const exportData = [];
42
43data.value.forEach(row => {
44Object.entries(row.subjects).forEach(([subject, hours]) => {
45exportData.push({
46group_name: row.group_name,
47subject,
48hours,
49});
50});
51});
52
53// Формируем CSV строку
54const csvContent = [
55['Группа', 'Предмет', 'Часы'], // Заголовки
56...exportData.map(item =>
57[item.group_name, item.subject, item.hours].join(',')
58), // Данные
59].join('\n');
60
61// Создаем ссылку для скачивания файла
62const BOM = '\uFEFF'; // Byte Order Mark
63const blob = new Blob([BOM + csvContent], {
64type: 'text/csv;charset=utf-8;',
65});
66const url = URL.createObjectURL(blob);
67const link = document.createElement('a');
68link.setAttribute('href', url);
69link.setAttribute(
70'download',
71`Экспорт ${start_date.value} - ${end_date.value}.csv`
72);
73link.click();
74};
75</script>
76
77<template>
78<div class="flex flex-col gap-4 mx-auto px-4 py-4">
79<div class="flex flex-wrap justify-between items-baseline">
80<h1 class="text-2xl">Аналитика</h1>
81</div>
82
83<div class="">
84<form
85class="flex flex-wrap items-center gap-2 p-4 rounded-lg bg-surface-100 dark:bg-surface-800"
86>
87<div class="flex flex-wrap items-center gap-2 justify-start">
88<MultiSelect
89v-model="selectedGroups"
90:options="groups"
91option-label="name"
92filter
93placeholder="Выбрать группы"
94:max-selected-labels="3"
95class="w-full md:w-60"
96/>
97<DatePicker
98v-model="rangeDates"
99append-to="self"
100placeholder="Период"
101date-format="dd.mm.yy"
102selection-mode="range"
103:manual-input="false"
104class="w-full md:w-60"
105/>
106</div>
107</form>
108</div>
109<div class="">
110<DataTable
111ref="dt"
112:loading="isLoading"
113:value="data"
114row-group-mode="rowspan"
115table-style="min-width: 50rem"
116>
117<template #header>
118<div style="text-align: left">
119<Button
120:disabled="!data"
121icon="pi pi-external-link"
122label="Экспорт в CSV"
123@click="exportCSV()"
124/>
125</div>
126</template>
127<Column field="group_name" header="Группа" style="min-width: 200px">
128<template #body="slotProps">
129{{ slotProps.data.group_name }}
130</template>
131</Column>
132<Column
133:exportable="true"
134:field="
135row =>
136Object.entries(row.subjects)
137.map(([subject, hours]) => `${subject} - ${hours} ак. ч.`)
138.join('\n ')
139"
140header="Предметы"
141style="min-width: 200px"
142>
143<template #body="slotProps">
144<div v-for="(value, key) in slotProps.data.subjects" class="">
145<p class="leading-normal">
146{{ key }} -
147<span class="text-lg">{{ value }} ак. ч.</span>
148</p>
149</div>
150</template>
151</Column>
152</DataTable>
153</div>
154</div>
155</template>
156