直播日历

This commit is contained in:
2026-07-29 09:10:18 +08:00
parent 7cbc240d63
commit b7ad3fda49
6 changed files with 208 additions and 0 deletions
@@ -0,0 +1,70 @@
<?php
namespace App\Http\Controllers;
use App\Models\Videos;
use App\Util\VideoCalendarUtil;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Routing\Controller as BaseController;
class CalendarController extends BaseController
{
public function index(Request $request)
{
$month_param = $request->get("month", "");
if (preg_match("/^(\d{4})-(0[1-9]|1[0-2])$/", $month_param, $matches)) {
$month = Carbon::createFromDate((int)$matches[1], (int)$matches[2], 1)->startOfMonth();
} else {
$month = Carbon::now()->startOfMonth();
}
$videos = Videos::query()->orderBy("created_at")->get(["id", "bvid", "title", "total_duration"]);
$by_date = VideoCalendarUtil::group_by_live_date($videos);
$parsed_count = array_sum(array_map("sizeof", $by_date));
$weeks = [];
$current_week = array_fill(0, 7, null);
$cursor = $month->copy();
$month_end = $month->copy()->endOfMonth();
while ($cursor->lte($month_end)) {
$day_index = $cursor->dayOfWeekIso - 1; // 周一为一周之始
$date_key = $cursor->format("Y-m-d");
$current_week[$day_index] = [
"day" => $cursor->day,
"videos" => $by_date[$date_key] ?? [],
"is_today" => $cursor->isToday(),
];
if ($day_index === 6) {
$weeks[] = $current_week;
$current_week = array_fill(0, 7, null);
}
$cursor->addDay();
}
if (sizeof(array_filter($current_week)) > 0) {
$weeks[] = $current_week;
}
$month_prefix = $month->format("Y-m");
$live_days = sizeof(array_filter(array_keys($by_date), function (string $date) use ($month_prefix) {
return strpos($date, $month_prefix) === 0;
}));
$min_month = sizeof($by_date) > 0 ? Carbon::createFromFormat("Y-m-d", array_key_first($by_date))->startOfMonth() : $month->copy();
$max_month = sizeof($by_date) > 0 ? Carbon::createFromFormat("Y-m-d", array_key_last($by_date))->startOfMonth() : $month->copy();
$prev_month = $month->copy()->subMonth();
$next_month = $month->copy()->addMonth();
return view("calendar.index", [
"weeks" => $weeks,
"month" => $month,
"is_current_month" => $month->eq(Carbon::now()->startOfMonth()),
"live_days" => $live_days,
"unparsed_count" => sizeof($videos) - $parsed_count,
"prev_month" => $prev_month,
"next_month" => $next_month,
"has_prev" => $prev_month->gte($min_month),
"has_next" => $next_month->lte($max_month),
]);
}
}