✨ 画廊功能
This commit is contained in:
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Common;
|
||||
|
||||
use App\Enums\ImagePermission;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Image;
|
||||
use Illuminate\View\View;
|
||||
|
||||
class GalleryController extends Controller
|
||||
{
|
||||
public function index(): View
|
||||
{
|
||||
$images = Image::query()
|
||||
->with('user')
|
||||
->where('is_unhealthy', false)
|
||||
->where('permission', ImagePermission::Public)
|
||||
->latest()
|
||||
->simplePaginate(40);
|
||||
return view('common.gallery', compact('images'));
|
||||
}
|
||||
}
|
||||
@@ -36,16 +36,6 @@ class UserController extends Controller
|
||||
return view('user.settings');
|
||||
}
|
||||
|
||||
public function gallery(): View
|
||||
{
|
||||
return view('user.gallery');
|
||||
}
|
||||
|
||||
public function works(): Response
|
||||
{
|
||||
return $this->success();
|
||||
}
|
||||
|
||||
public function update(UserSettingRequest $request): Response
|
||||
{
|
||||
/** @var User $user */
|
||||
|
||||
@@ -709,6 +709,12 @@ select {
|
||||
.z-\[1\] {
|
||||
z-index: 1;
|
||||
}
|
||||
.z-\[11\] {
|
||||
z-index: 11;
|
||||
}
|
||||
.z-\[10\] {
|
||||
z-index: 10;
|
||||
}
|
||||
.col-span-6 {
|
||||
grid-column: span 6 / span 6;
|
||||
}
|
||||
@@ -931,6 +937,12 @@ select {
|
||||
.w-4 {
|
||||
width: 1rem;
|
||||
}
|
||||
.w-1\/6 {
|
||||
width: 16.666667%;
|
||||
}
|
||||
.w-\[33\.333\%\] {
|
||||
width: 33.333%;
|
||||
}
|
||||
.min-w-full {
|
||||
min-width: 100%;
|
||||
}
|
||||
@@ -1037,6 +1049,12 @@ select {
|
||||
.grid-cols-1 {
|
||||
grid-template-columns: repeat(1, minmax(0, 1fr));
|
||||
}
|
||||
.grid-cols-4 {
|
||||
grid-template-columns: repeat(4, minmax(0, 1fr));
|
||||
}
|
||||
.grid-cols-2 {
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
}
|
||||
.flex-row {
|
||||
flex-direction: row;
|
||||
}
|
||||
@@ -1073,6 +1091,9 @@ select {
|
||||
.gap-6 {
|
||||
gap: 1.5rem;
|
||||
}
|
||||
.gap-4 {
|
||||
gap: 1rem;
|
||||
}
|
||||
.space-y-4 > :not([hidden]) ~ :not([hidden]) {
|
||||
--tw-space-y-reverse: 0;
|
||||
margin-top: calc(1rem * calc(1 - var(--tw-space-y-reverse)));
|
||||
@@ -1182,6 +1203,9 @@ select {
|
||||
.rounded {
|
||||
border-radius: 0.25rem;
|
||||
}
|
||||
.rounded-sm {
|
||||
border-radius: 0.125rem;
|
||||
}
|
||||
.rounded-l-md {
|
||||
border-top-left-radius: 0.375rem;
|
||||
border-bottom-left-radius: 0.375rem;
|
||||
@@ -1423,6 +1447,18 @@ select {
|
||||
padding-top: 3.5rem;
|
||||
padding-bottom: 3.5rem;
|
||||
}
|
||||
.px-0 {
|
||||
padding-left: 0px;
|
||||
padding-right: 0px;
|
||||
}
|
||||
.py-0 {
|
||||
padding-top: 0px;
|
||||
padding-bottom: 0px;
|
||||
}
|
||||
.px-1 {
|
||||
padding-left: 0.25rem;
|
||||
padding-right: 0.25rem;
|
||||
}
|
||||
.pb-6 {
|
||||
padding-bottom: 1.5rem;
|
||||
}
|
||||
@@ -2049,6 +2085,10 @@ select {
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
}
|
||||
|
||||
.md\:grid-cols-4 {
|
||||
grid-template-columns: repeat(4, minmax(0, 1fr));
|
||||
}
|
||||
|
||||
.md\:flex-row {
|
||||
flex-direction: row;
|
||||
}
|
||||
@@ -2102,6 +2142,10 @@ select {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.lg\:grid-cols-6 {
|
||||
grid-template-columns: repeat(6, minmax(0, 1fr));
|
||||
}
|
||||
|
||||
.lg\:px-10 {
|
||||
padding-left: 2.5rem;
|
||||
padding-right: 2.5rem;
|
||||
@@ -2122,6 +2166,10 @@ select {
|
||||
grid-template-columns: repeat(4, minmax(0, 1fr));
|
||||
}
|
||||
|
||||
.xl\:grid-cols-8 {
|
||||
grid-template-columns: repeat(8, minmax(0, 1fr));
|
||||
}
|
||||
|
||||
.xl\:gap-x-8 {
|
||||
-moz-column-gap: 2rem;
|
||||
column-gap: 2rem;
|
||||
@@ -2138,6 +2186,10 @@ select {
|
||||
}
|
||||
@media (min-width: 1536px) {
|
||||
|
||||
.\32xl\:grid-cols-10 {
|
||||
grid-template-columns: repeat(10, minmax(0, 1fr));
|
||||
}
|
||||
|
||||
.\32xl\:px-60 {
|
||||
padding-left: 15rem;
|
||||
padding-right: 15rem;
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
.images-grid {
|
||||
margin: 0 auto;
|
||||
}
|
||||
.images-grid:after {
|
||||
content: '';
|
||||
display: block;
|
||||
clear: both;
|
||||
}
|
||||
.grid-sizer,
|
||||
.grid-item {
|
||||
width: calc(50% - 10px);
|
||||
}
|
||||
.grid-item {
|
||||
float: left;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
.grid-item:hover {
|
||||
margin-top: -5px;
|
||||
box-shadow: 15.8px 21.3px 83.8px rgba(0, 0, 0, 0.07), 102px 137px 196px rgba(0, 0, 0, 0.035);
|
||||
}
|
||||
@media screen and (min-width: 640px) {
|
||||
.grid-sizer,
|
||||
.grid-item {
|
||||
width: calc(33.333% - 11px);
|
||||
}
|
||||
}
|
||||
@media screen and (min-width: 768px) {
|
||||
.grid-sizer,
|
||||
.grid-item {
|
||||
width: calc(25% - 11px);
|
||||
}
|
||||
}
|
||||
@media screen and (min-width: 1024px) {
|
||||
.grid-sizer,
|
||||
.grid-item {
|
||||
width: calc(20% - 11px);
|
||||
}
|
||||
}
|
||||
@media screen and (min-width: 1280px) {
|
||||
.grid-sizer,
|
||||
.grid-item {
|
||||
width: calc(12.5% - 11px);
|
||||
}
|
||||
}
|
||||
@media screen and (min-width: 1536px) {
|
||||
.grid-sizer,
|
||||
.grid-item {
|
||||
width: calc(10% - 11px);
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because one or more lines are too long
+9
File diff suppressed because one or more lines are too long
@@ -1,9 +1,54 @@
|
||||
.images-grid {
|
||||
.grid-item {
|
||||
transition: all .3s;
|
||||
&:hover {
|
||||
margin-top: -5px;
|
||||
box-shadow: 15.8px 21.3px 83.8px rgba(0, 0, 0, 0.07), 102px 137px 196px rgba(0, 0, 0, 0.035);
|
||||
}
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.images-grid:after {
|
||||
content: '';
|
||||
display: block;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.grid-sizer, .grid-item {
|
||||
width: calc(50% - 10px);
|
||||
}
|
||||
|
||||
.grid-item {
|
||||
float: left;
|
||||
transition: all .3s;
|
||||
|
||||
&:hover {
|
||||
margin-top: -5px;
|
||||
box-shadow: 15.8px 21.3px 83.8px rgba(0, 0, 0, 0.07), 102px 137px 196px rgba(0, 0, 0, 0.035);
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (min-width: 640px) {
|
||||
.grid-sizer, .grid-item {
|
||||
width: calc(33.333% - 11px);
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (min-width: 768px) {
|
||||
.grid-sizer, .grid-item {
|
||||
width: calc(25% - 11px);
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (min-width: 1024px) {
|
||||
.grid-sizer, .grid-item {
|
||||
width: calc(20% - 11px);
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (min-width: 1280px) {
|
||||
.grid-sizer, .grid-item {
|
||||
width: calc(12.5% - 11px);
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (min-width: 1536px) {
|
||||
.grid-sizer, .grid-item {
|
||||
width: calc(10% - 11px);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
@section('title', '画廊')
|
||||
|
||||
@push('styles')
|
||||
<link rel="stylesheet" href="{{ asset('css/gallery.css') }}">
|
||||
@endpush
|
||||
|
||||
<x-app-layout>
|
||||
<div class="p-4">
|
||||
@if($images->isNotEmpty())
|
||||
<div class="images-grid">
|
||||
<div class="grid-sizer"></div>
|
||||
@foreach($images as $image)
|
||||
<div class="grid-item relative mb-4 bg-white rounded-md overflow-hidden">
|
||||
@if($image->extension === 'gif')
|
||||
<span class="absolute top-1 right-1 z-[1] bg-white rounded-md text-sm px-1 py-0">Gif</span>
|
||||
@endif
|
||||
<a target="_blank" href="{{ $image->url }}">
|
||||
<div class="relative overflow-hidden w-full h-32">
|
||||
<img class="grow object-cover object-center w-full h-full" src="{{ $image->thumb_url }}"/>
|
||||
</div>
|
||||
</a>
|
||||
<a target="_blank" href="{{ $image->user->url ?: 'javascript:void(0)' }}" class="flex justify-between items-center px-3 py-2 bg-white overflow-hidden">
|
||||
<img src="{{ $image->user->avatar }}" class="w-6 h-6 rounded-full">
|
||||
<p class="ml-2 truncate">{{ $image->user->name }}</p>
|
||||
</a>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
{{ $images->links() }}
|
||||
@else
|
||||
<x-no-data message="暂时没有可展示的图片,再等等看吧~" />
|
||||
@endif
|
||||
</div>
|
||||
@push('scripts')
|
||||
<script src="{{ asset('js/masonry/masonry.pkgd.min.js') }}"></script>
|
||||
<script src="{{ asset('js/imagesloaded/imagesloaded.pkgd.min.js') }}"></script>
|
||||
<script>
|
||||
var $grid = $('.images-grid').masonry({
|
||||
itemSelector: '.grid-item',
|
||||
columnWidth: '.grid-sizer',
|
||||
gutter: 14,
|
||||
duration: '0.8s',
|
||||
resize: true,
|
||||
initLayout: true,
|
||||
percentPosition: true,
|
||||
horizontalOrder: true,
|
||||
});
|
||||
$grid.imagesLoaded().progress(function() {
|
||||
$grid.masonry('layout');
|
||||
});
|
||||
</script>
|
||||
@endpush
|
||||
</x-app-layout>
|
||||
@@ -1,47 +0,0 @@
|
||||
@section('title', '画廊')
|
||||
|
||||
@push('styles')
|
||||
<link rel="stylesheet" href="{{ asset('css/gallery.css') }}">
|
||||
@endpush
|
||||
|
||||
<x-app-layout>
|
||||
<div class="p-4">
|
||||
<div class="mb-4">
|
||||
<p class="mb-2 text-xl font-semibold text-gray-700">2022 年 1 月</p>
|
||||
<div class="images-grid">
|
||||
@foreach(\App\Models\Image::all() as $image)
|
||||
<div class="grid-item relative mb-4 bg-white rounded-md w-40 overflow-hidden">
|
||||
<div class="relative overflow-hidden w-full h-32">
|
||||
<img class="grow object-cover object-center w-full h-full" src="{{ $image->thumb_url }}"/>
|
||||
</div>
|
||||
<a href="{{ $image->user->url ?: 'javascript:void(0)' }}" class="flex justify-between items-center px-2 py-3 bg-white overflow-hidden">
|
||||
<img src="{{ $image->user->avatar }}" class="w-6 h-6 rounded-full">
|
||||
<p class="ml-2 truncate">{{ $image->user->name }}</p>
|
||||
</a>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@push('scripts')
|
||||
<script src="{{ asset('js/masonry/masonry.pkgd.min.js') }}"></script>
|
||||
<script src="{{ asset('js/imagesloaded/imagesloaded.pkgd.min.js') }}"></script>
|
||||
<script>
|
||||
var $grid = $('.images-grid').masonry({
|
||||
itemSelector: '.grid-item',
|
||||
gutter: 14,
|
||||
originLeft: true,
|
||||
originTop: true,
|
||||
duration: '0.8s',
|
||||
resize: true,
|
||||
initLayout: true,
|
||||
percentPosition: true,
|
||||
horizontalOrder: true,
|
||||
});
|
||||
$grid.imagesLoaded().progress(function() {
|
||||
$grid.masonry('layout');
|
||||
});
|
||||
</script>
|
||||
@endpush
|
||||
</x-app-layout>
|
||||
+2
-1
@@ -16,6 +16,7 @@ use App\Http\Controllers\Controller;
|
||||
use App\Http\Controllers\User\UserController;
|
||||
use App\Http\Controllers\User\ImageController;
|
||||
use App\Http\Controllers\User\AlbumController;
|
||||
use App\Http\Controllers\Common\GalleryController;
|
||||
|
||||
use App\Http\Controllers\Admin\GroupController as AdminGroupController;
|
||||
use App\Http\Controllers\Admin\StrategyController as AdminStrategyController;
|
||||
@@ -25,7 +26,7 @@ Route::get('/', fn () => view('welcome'))->name('/');
|
||||
Route::post('upload', [Controller::class, 'upload']);
|
||||
Route::group(['middleware' => ['auth']], function () {
|
||||
Route::get('dashboard', [UserController::class, 'dashboard'])->name('dashboard');
|
||||
Route::get('gallery', [UserController::class, 'gallery'])->name('gallery');
|
||||
Route::get('gallery', [GalleryController::class, 'index'])->name('gallery');
|
||||
Route::get('settings', [UserController::class, 'settings'])->name('settings');
|
||||
Route::put('settings', [UserController::class, 'update'])->name('settings.update');
|
||||
|
||||
|
||||
Reference in New Issue
Block a user