Add time method to TvController and update routes to include time endpoint for TV functionality.
This commit is contained in:
@@ -11,4 +11,9 @@ class TvController extends Controller
|
|||||||
{
|
{
|
||||||
return inertia()->render('Client/Tv/Index');
|
return inertia()->render('Client/Tv/Index');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function time()
|
||||||
|
{
|
||||||
|
return inertia()->render('Client/Tv/Time');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,9 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
use App\Containers\Widget\UI\API\Controllers\ClientWidgetAdditionalEducationalProgramController;
|
|
||||||
use App\Containers\Widget\UI\API\Controllers\ClientWidgetContactController;
|
|
||||||
use App\Containers\Widget\UI\API\Controllers\ClientWidgetEducationalProgramController;
|
|
||||||
use App\Containers\Widget\UI\API\Controllers\ClientWidgetFormController;
|
|
||||||
use App\Containers\Widget\UI\API\Controllers\ClientWidgetPageController;
|
|
||||||
use App\Containers\Widget\UI\API\Controllers\ClientWidgetPageReferenceListController;
|
|
||||||
use App\Containers\Widget\UI\API\Controllers\ClientWidgetPostController;
|
|
||||||
use App\Containers\Widget\UI\API\Controllers\ClientWidgetSliderController;
|
|
||||||
use App\Containers\Widget\UI\WEB\Controllers\TvController;
|
use App\Containers\Widget\UI\WEB\Controllers\TvController;
|
||||||
use Illuminate\Support\Facades\Route;
|
use Illuminate\Support\Facades\Route;
|
||||||
|
|
||||||
Route::get('/tv/', [TvController::class, 'index'])->name('client.tv.post.index');
|
Route::get('/tv/', [TvController::class, 'index'])->name('client.tv.post.index');
|
||||||
|
Route::get('/tv/time', [TvController::class, 'time'])->name('client.tv.post.time');
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,187 @@
|
|||||||
|
<template>
|
||||||
|
<div
|
||||||
|
class="text-white min-h-screen flex font-sans transition-all duration-500"
|
||||||
|
:class="{ 'invert': isResetting }"
|
||||||
|
>
|
||||||
|
<!-- Левый блок - Расписание -->
|
||||||
|
<div class="w-1/2 p-10 flex flex-col justify-center bg-gray-900 m-5 rounded-xl">
|
||||||
|
<!-- Состояние: Идет пара -->
|
||||||
|
<div v-if="currentStatus.type === 'class'">
|
||||||
|
<h2 class="text-6xl font-bold mb-4">
|
||||||
|
Идет {{ currentStatus.number }} пара
|
||||||
|
</h2>
|
||||||
|
<p class="text-4xl tabular-nums">
|
||||||
|
Осталось: {{ currentStatus.remaining }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Состояние: Идет перемена -->
|
||||||
|
<div v-else-if="currentStatus.type === 'break'">
|
||||||
|
<h2 class="text-6xl font-bold mb-4">
|
||||||
|
Перемена
|
||||||
|
</h2>
|
||||||
|
<p class="text-4xl tabular-nums">
|
||||||
|
До начала {{ currentStatus.nextClassNumber }} пары: {{ currentStatus.untilNext }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Состояние: До начала пар -->
|
||||||
|
<div v-else-if="currentStatus.type === 'before_classes'">
|
||||||
|
<h2 class="text-5xl font-bold text-center mb-3">Пары еще не начались</h2>
|
||||||
|
<p class="text-4xl tabular-nums text-center">
|
||||||
|
До начала первой пары: {{ currentStatus.untilNext }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Состояние: Пары закончились -->
|
||||||
|
<div v-else>
|
||||||
|
<h2 class="text-5xl font-bold">
|
||||||
|
Пары на сегодня закончены
|
||||||
|
</h2>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Правый блок - Дата и время -->
|
||||||
|
<div class="w-1/2 bg-gray-800 p-10 flex flex-col justify-center items-center m-5 rounded-xl">
|
||||||
|
<h1 class="text-8xl font-bold mb-4 tabular-nums">
|
||||||
|
{{ currentTime }}
|
||||||
|
</h1>
|
||||||
|
<p class="text-4xl">
|
||||||
|
{{ currentDate }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref, onMounted, onUnmounted, computed } from 'vue';
|
||||||
|
|
||||||
|
// --- НОВОЕ: Состояние для эффекта сброса ---
|
||||||
|
const isResetting = ref(false);
|
||||||
|
|
||||||
|
// --- Дата и время ---
|
||||||
|
const now = ref(new Date());
|
||||||
|
|
||||||
|
const currentTime = computed(() => {
|
||||||
|
return now.value.toLocaleTimeString('ru-RU', {
|
||||||
|
hour: '2-digit',
|
||||||
|
minute: '2-digit',
|
||||||
|
second: '2-digit'
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
const currentDate = computed(() => {
|
||||||
|
return now.value.toLocaleDateString('ru-RU', {
|
||||||
|
weekday: 'long',
|
||||||
|
year: 'numeric',
|
||||||
|
month: 'long',
|
||||||
|
day: 'numeric'
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
let timer;
|
||||||
|
// --- НОВОЕ: Переменная для таймера сброса ---
|
||||||
|
let resetInterval;
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
// Устанавливаем таймер для обновления времени каждую секунду
|
||||||
|
timer = setInterval(() => {
|
||||||
|
now.value = new Date();
|
||||||
|
}, 1000);
|
||||||
|
|
||||||
|
// --- НОВОЕ: Запускаем таймер для эффекта сброса ---
|
||||||
|
// Срабатывает каждые 15 минут
|
||||||
|
resetInterval = setInterval(() => {
|
||||||
|
isResetting.value = !isResetting.value;
|
||||||
|
}, 900000); // 15 минут = 900 000 мс
|
||||||
|
});
|
||||||
|
|
||||||
|
onUnmounted(() => {
|
||||||
|
// Очищаем таймер при уничтожении компонента
|
||||||
|
clearInterval(timer);
|
||||||
|
// --- НОВОЕ: Очищаем таймер сброса ---
|
||||||
|
clearInterval(resetInterval);
|
||||||
|
});
|
||||||
|
|
||||||
|
// --- Расписание на основе документа ---
|
||||||
|
const schedule = [
|
||||||
|
{ number: '1', start: '09:00', end: '10:30' },
|
||||||
|
{ number: '2', start: '10:40', end: '12:10' },
|
||||||
|
{ number: '3', start: '13:00', end: '14:30' },
|
||||||
|
{ number: '4', start: '14:40', end: '16:10' },
|
||||||
|
{ number: '5', start: '16:20', end: '17:50' },
|
||||||
|
{ number: '6', start: '18:00', end: '19:30' },
|
||||||
|
];
|
||||||
|
|
||||||
|
// Вспомогательная функция для преобразования времени 'ЧЧ:ММ' в объект Date
|
||||||
|
const parseTime = (timeStr) => {
|
||||||
|
const [hours, minutes] = timeStr.split(':').map(Number);
|
||||||
|
const date = new Date();
|
||||||
|
date.setHours(hours, minutes, 0, 0);
|
||||||
|
return date;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Вспомогательная функция для форматирования миллисекунд в 'ЧЧ:ММ:СС'
|
||||||
|
const formatDuration = (ms) => {
|
||||||
|
if (ms < 0) ms = 0;
|
||||||
|
const totalSeconds = Math.floor(ms / 1000);
|
||||||
|
const hours = Math.floor(totalSeconds / 3600);
|
||||||
|
const minutes = Math.floor((totalSeconds % 3600) / 60);
|
||||||
|
const seconds = totalSeconds % 60;
|
||||||
|
|
||||||
|
return [
|
||||||
|
hours.toString().padStart(2, '0'),
|
||||||
|
minutes.toString().padStart(2, '0'),
|
||||||
|
seconds.toString().padStart(2, '0')
|
||||||
|
].join(':');
|
||||||
|
};
|
||||||
|
|
||||||
|
// Главная вычисляемая переменная, определяющая текущий статус
|
||||||
|
const currentStatus = computed(() => {
|
||||||
|
const currentTime = now.value;
|
||||||
|
const firstClassTime = parseTime(schedule[0].start);
|
||||||
|
|
||||||
|
// Проверка, если еще до начала первой пары
|
||||||
|
if (currentTime < firstClassTime) {
|
||||||
|
const untilNextMs = firstClassTime - currentTime;
|
||||||
|
return {
|
||||||
|
type: 'before_classes',
|
||||||
|
untilNext: formatDuration(untilNextMs)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = 0; i < schedule.length; i++) {
|
||||||
|
const lesson = schedule[i];
|
||||||
|
const startTime = parseTime(lesson.start);
|
||||||
|
const endTime = parseTime(lesson.end);
|
||||||
|
|
||||||
|
// Проверка, идет ли сейчас пара
|
||||||
|
if (currentTime >= startTime && currentTime < endTime) {
|
||||||
|
const remainingMs = endTime - currentTime;
|
||||||
|
return {
|
||||||
|
type: 'class',
|
||||||
|
number: lesson.number,
|
||||||
|
remaining: formatDuration(remainingMs),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Проверка, идет ли сейчас перемена
|
||||||
|
if (i < schedule.length - 1) {
|
||||||
|
const nextLesson = schedule[i + 1];
|
||||||
|
const nextStartTime = parseTime(nextLesson.start);
|
||||||
|
if (currentTime >= endTime && currentTime < nextStartTime) {
|
||||||
|
const untilNextMs = nextStartTime - currentTime;
|
||||||
|
return {
|
||||||
|
type: 'break',
|
||||||
|
untilNext: formatDuration(untilNextMs),
|
||||||
|
nextClassNumber: nextLesson.number,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Если ни одно из условий не выполнилось, значит пары закончились
|
||||||
|
return { type: 'finished' };
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
||||||
Reference in New Issue
Block a user