📦 Updating compiled files or packages.

This commit is contained in:
Wisp X 2022-01-19 20:28:12 +08:00
parent d6564bbfbd
commit 39feb32ba9
11 changed files with 368 additions and 220 deletions

View File

@ -2,8 +2,10 @@
namespace App\Http\Controllers;
use App\Enums\GroupConfigKey;
use App\Exceptions\UploadException;
use App\Http\Api;
use App\Models\Image;
use App\Models\User;
use App\Service\ImageService;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
@ -13,7 +15,10 @@ use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Routing\Controller as BaseController;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Log;
use League\Flysystem\FilesystemException;
use Symfony\Component\HttpFoundation\StreamedResponse;
class Controller extends BaseController
{
@ -38,4 +43,84 @@ class Controller extends BaseController
'id', 'pathname', 'origin_name', 'size', 'mimetype', 'md5', 'sha1', 'links'
));
}
public function output(Request $request, ImageService $service): StreamedResponse
{
/** @var Image $image */
$image = Image::query()
->with('group')
->where('key', $request->route('key'))
->where('extension', $request->route('extension'))
->firstOr(fn() => abort(404));
if (! $image->group->configs->get(GroupConfigKey::IsEnableOriginalProtection)) {
abort(404);
}
try {
$cacheKey = "image_{$image->key}";
if (Cache::has($cacheKey)) {
$contents = Cache::get($cacheKey);
} else {
$contents = $image->filesystem()->read($image->pathname);
// 是否启用了水印功能跳过gif图片
if ($image->group->configs->get(GroupConfigKey::IsEnableWatermark) && $image->mimetype !== 'image/gif') {
$configs = $image->group->configs->get(GroupConfigKey::WatermarkConfigs);
$contents = (string)$service->stickWatermark($contents, collect($configs))->encode();
}
$cacheTtl = (int)$image->group->configs->get(GroupConfigKey::CacheTtl, 0);
// 是否启用了缓存
if ($cacheTtl) {
Cache::remember($cacheKey, $cacheTtl, fn () => $contents);
} else {
if (Cache::has($cacheKey)) Cache::forget($cacheKey);
}
}
} catch (FilesystemException $e) {
abort(404);
}
return \response()->stream(function () use ($contents) {
echo $contents;
}, headers: ['Content-type' => $image->mimetype]);
}
public function thumbnail(Request $request): StreamedResponse
{
/** @var Image $image */
$image = Image::query()
->where('key', $request->route('key'))
->where('extension', $request->route('extension'))
->firstOr(fn() => abort(404));
try {
$cacheKey = "image_thumb_{$image->key}";
if (Cache::has($cacheKey)) {
$contents = Cache::get($cacheKey);
} else {
$stream = $image->filesystem()->readStream($image->pathname);
$img = \Intervention\Image\Facades\Image::make($stream);
$width = $w = $image->width;
$height = $h = $image->height;
$max = 400; // 最大宽高
if ($w > $max && $h > $max) {
$scale = min($max / $w, $max / $h);
$width = (int)($w * $scale);
$height = (int)($h * $scale);
}
$contents = $img->fit($width, $height, fn($constraint) => $constraint->upsize())->encode();
Cache::rememberForever($cacheKey, fn () => (string)$contents);
}
} catch (FilesystemException $e) {
abort(404);
}
return \response()->stream(function () use ($contents) {
echo $contents;
}, headers: ['Content-type' => $image->mimetype]);
}
}

View File

@ -2,24 +2,18 @@
namespace App\Http\Controllers\User;
use App\Enums\GroupConfigKey;
use App\Enums\ImagePermission;
use App\Http\Controllers\Controller;
use App\Http\Requests\ImageRenameRequest;
use App\Models\Album;
use App\Models\Image;
use App\Models\User;
use App\Service\ImageService;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
use Illuminate\View\View;
use Intervention\Image\ImageManager;
use League\Flysystem\FilesystemException;
use Symfony\Component\HttpFoundation\StreamedResponse;
class ImageController extends Controller
{
@ -92,86 +86,6 @@ class ImageController extends Controller
return $this->success('success', compact('image'));
}
public function output(Request $request, ImageService $service): StreamedResponse
{
/** @var Image $image */
$image = Image::query()
->with('group')
->where('key', $request->route('key'))
->where('extension', $request->route('extension'))
->firstOr(fn() => abort(404));
if (! $image->group->configs->get(GroupConfigKey::IsEnableOriginalProtection)) {
abort(404);
}
try {
$cacheKey = "image_{$image->key}";
if (Cache::has($cacheKey)) {
$contents = Cache::get($cacheKey);
} else {
$contents = $image->filesystem()->read($image->pathname);
// 是否启用了水印功能跳过gif图片
if ($image->group->configs->get(GroupConfigKey::IsEnableWatermark) && $image->mimetype !== 'image/gif') {
$configs = $image->group->configs->get(GroupConfigKey::WatermarkConfigs);
$contents = (string)$service->stickWatermark($contents, collect($configs))->encode();
}
$cacheTtl = (int)$image->group->configs->get(GroupConfigKey::CacheTtl, 0);
// 是否启用了缓存
if ($cacheTtl) {
Cache::remember($cacheKey, $cacheTtl, fn () => $contents);
} else {
if (Cache::has($cacheKey)) Cache::forget($cacheKey);
}
}
} catch (FilesystemException $e) {
abort(404);
}
return \response()->stream(function () use ($contents) {
echo $contents;
}, headers: ['Content-type' => $image->mimetype]);
}
public function thumbnail(Request $request): StreamedResponse
{
/** @var Image $image */
$image = Image::query()
->where('key', $request->route('key'))
->where('extension', $request->route('extension'))
->firstOr(fn() => abort(404));
try {
$cacheKey = "image_thumb_{$image->key}";
if (Cache::has($cacheKey)) {
$contents = Cache::get($cacheKey);
} else {
$stream = $image->filesystem()->readStream($image->pathname);
$img = \Intervention\Image\Facades\Image::make($stream);
$width = $w = $image->width;
$height = $h = $image->height;
$max = 400; // 最大宽高
if ($w > $max && $h > $max) {
$scale = min($max / $w, $max / $h);
$width = (int)($w * $scale);
$height = (int)($h * $scale);
}
$contents = $img->fit($width, $height, fn($constraint) => $constraint->upsize())->encode();
Cache::rememberForever($cacheKey, fn () => (string)$contents);
}
} catch (FilesystemException $e) {
abort(404);
}
return \response()->stream(function () use ($contents) {
echo $contents;
}, headers: ['Content-type' => $image->mimetype]);
}
public function permission(Request $request): Response
{
/** @var User $user */

52
composer.lock generated
View File

@ -8,16 +8,16 @@
"packages": [
{
"name": "asm89/stack-cors",
"version": "v2.1.0",
"version": "v2.1.1",
"source": {
"type": "git",
"url": "https://github.com/asm89/stack-cors.git",
"reference": "1faf1a97bddf4ce46521ba747f8474e4c15bb546"
"reference": "73e5b88775c64ccc0b84fb60836b30dc9d92ac4a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/asm89/stack-cors/zipball/1faf1a97bddf4ce46521ba747f8474e4c15bb546",
"reference": "1faf1a97bddf4ce46521ba747f8474e4c15bb546",
"url": "https://api.github.com/repos/asm89/stack-cors/zipball/73e5b88775c64ccc0b84fb60836b30dc9d92ac4a",
"reference": "73e5b88775c64ccc0b84fb60836b30dc9d92ac4a",
"shasum": "",
"mirrors": [
{
@ -27,12 +27,12 @@
]
},
"require": {
"php": "^8.0",
"symfony/http-foundation": "^6",
"symfony/http-kernel": "^6"
"php": "^7.2|^8.0",
"symfony/http-foundation": "^4|^5|^6",
"symfony/http-kernel": "^4|^5|^6"
},
"require-dev": {
"phpunit/phpunit": "^9",
"phpunit/phpunit": "^7|^9",
"squizlabs/php_codesniffer": "^3.5"
},
"type": "library",
@ -64,9 +64,9 @@
],
"support": {
"issues": "https://github.com/asm89/stack-cors/issues",
"source": "https://github.com/asm89/stack-cors/tree/v2.1.0"
"source": "https://github.com/asm89/stack-cors/tree/v2.1.1"
},
"time": "2022-01-03T15:53:27+00:00"
"time": "2022-01-18T09:12:03+00:00"
},
{
"name": "brick/math",
@ -396,16 +396,16 @@
},
{
"name": "dragonmantank/cron-expression",
"version": "v3.3.0",
"version": "v3.3.1",
"source": {
"type": "git",
"url": "https://github.com/dragonmantank/cron-expression.git",
"reference": "63f2a76a045bac6ec93cc2daf2b534b412aa0313"
"reference": "be85b3f05b46c39bbc0d95f6c071ddff669510fa"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/dragonmantank/cron-expression/zipball/63f2a76a045bac6ec93cc2daf2b534b412aa0313",
"reference": "63f2a76a045bac6ec93cc2daf2b534b412aa0313",
"url": "https://api.github.com/repos/dragonmantank/cron-expression/zipball/be85b3f05b46c39bbc0d95f6c071ddff669510fa",
"reference": "be85b3f05b46c39bbc0d95f6c071ddff669510fa",
"shasum": "",
"mirrors": [
{
@ -451,7 +451,7 @@
],
"support": {
"issues": "https://github.com/dragonmantank/cron-expression/issues",
"source": "https://github.com/dragonmantank/cron-expression/tree/v3.3.0"
"source": "https://github.com/dragonmantank/cron-expression/tree/v3.3.1"
},
"funding": [
{
@ -459,7 +459,7 @@
"type": "github"
}
],
"time": "2022-01-14T16:02:05+00:00"
"time": "2022-01-18T15:43:28+00:00"
},
{
"name": "egulias/email-validator",
@ -6242,16 +6242,16 @@
},
{
"name": "laravel/sail",
"version": "v1.12.12",
"version": "v1.13.0",
"source": {
"type": "git",
"url": "https://github.com/laravel/sail.git",
"reference": "c60773f04f093bd1d2f3b99ff9e5a1aa5b05b8b6"
"reference": "a14125e71779c99e27979431a66ea2793aa6ae50"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laravel/sail/zipball/c60773f04f093bd1d2f3b99ff9e5a1aa5b05b8b6",
"reference": "c60773f04f093bd1d2f3b99ff9e5a1aa5b05b8b6",
"url": "https://api.github.com/repos/laravel/sail/zipball/a14125e71779c99e27979431a66ea2793aa6ae50",
"reference": "a14125e71779c99e27979431a66ea2793aa6ae50",
"shasum": "",
"mirrors": [
{
@ -6304,7 +6304,7 @@
"issues": "https://github.com/laravel/sail/issues",
"source": "https://github.com/laravel/sail"
},
"time": "2021-12-16T14:58:08+00:00"
"time": "2022-01-18T18:06:55+00:00"
},
{
"name": "maximebf/debugbar",
@ -6523,16 +6523,16 @@
},
{
"name": "nunomaduro/collision",
"version": "v6.0.0",
"version": "v6.1.0",
"source": {
"type": "git",
"url": "https://github.com/nunomaduro/collision.git",
"reference": "5338ecc3909ef3ed150f6408f14e44cdb62bfdd0"
"reference": "df09e21a5e5d5a7d51a8b9ecd44d3dd150d97fec"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/nunomaduro/collision/zipball/5338ecc3909ef3ed150f6408f14e44cdb62bfdd0",
"reference": "5338ecc3909ef3ed150f6408f14e44cdb62bfdd0",
"url": "https://api.github.com/repos/nunomaduro/collision/zipball/df09e21a5e5d5a7d51a8b9ecd44d3dd150d97fec",
"reference": "df09e21a5e5d5a7d51a8b9ecd44d3dd150d97fec",
"shasum": "",
"mirrors": [
{
@ -6612,7 +6612,7 @@
"type": "patreon"
}
],
"time": "2022-01-10T17:17:19+00:00"
"time": "2022-01-18T17:49:08+00:00"
},
{
"name": "phar-io/manifest",

67
package-lock.json generated
View File

@ -1,5 +1,5 @@
{
"name": "9",
"name": "lsky-pro",
"lockfileVersion": 2,
"requires": true,
"packages": {
@ -17,6 +17,7 @@
"copy-image-clipboard": "^2.0.1",
"deepmerge": "^4.2.2",
"dragselect": "^2.3.0",
"echarts": "^5.2.2",
"jquery": "^3.6.0",
"jquery.photoswipe": "^1.1.1",
"justifiedGallery": "^3.8.1",
@ -4494,6 +4495,17 @@
"dev": true,
"license": "MIT"
},
"node_modules/echarts": {
"version": "5.2.2",
"resolved": "https://repo.huaweicloud.com/repository/npm/echarts/-/echarts-5.2.2.tgz",
"integrity": "sha512-yxuBfeIH5c+0FsoRP60w4De6omXhA06c7eUYBsC1ykB6Ys2yK5fSteIYWvkJ4xJVLQgCvAdO8C4mN6MLeJpBaw==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
"tslib": "2.3.0",
"zrender": "5.2.1"
}
},
"node_modules/ee-first": {
"version": "1.1.1",
"resolved": "https://repo.huaweicloud.com/repository/npm/ee-first/-/ee-first-1.1.1.tgz",
@ -9656,9 +9668,9 @@
}
},
"node_modules/sweetalert2": {
"version": "11.3.3",
"resolved": "https://repo.huaweicloud.com/repository/npm/sweetalert2/-/sweetalert2-11.3.3.tgz",
"integrity": "sha512-10Keqbmjng/+XpkpSOQ6dttpztl7XNohjnpC6bX6XFgm0WpRXM81YE0wmonGYOP6uyzd76vpfnZS04PdVvO31Q==",
"version": "11.3.6",
"resolved": "https://repo.huaweicloud.com/repository/npm/sweetalert2/-/sweetalert2-11.3.6.tgz",
"integrity": "sha512-0JBlA36T1e0fuihcyvg4FjoucCOYNmbYDLrEOenGMVg1Jw7UHaC7FmDFp1qf9UGbO89pjgDJrfkThYln8TrYEQ==",
"dev": true,
"license": "MIT",
"funding": {
@ -9919,9 +9931,9 @@
}
},
"node_modules/tslib": {
"version": "2.3.1",
"resolved": "https://repo.huaweicloud.com/repository/npm/tslib/-/tslib-2.3.1.tgz",
"integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==",
"version": "2.3.0",
"resolved": "https://repo.huaweicloud.com/repository/npm/tslib/-/tslib-2.3.0.tgz",
"integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==",
"dev": true,
"license": "0BSD"
},
@ -10682,6 +10694,16 @@
"engines": {
"node": ">=12"
}
},
"node_modules/zrender": {
"version": "5.2.1",
"resolved": "https://repo.huaweicloud.com/repository/npm/zrender/-/zrender-5.2.1.tgz",
"integrity": "sha512-M3bPGZuyLTNBC6LiNKXJwSCtglMp8XUEqEBG+2MdICDI3d1s500Y4P0CzldQGsqpRVB7fkvf3BKQQRxsEaTlsw==",
"dev": true,
"license": "BSD-3-Clause",
"dependencies": {
"tslib": "2.3.0"
}
}
},
"dependencies": {
@ -13880,6 +13902,16 @@
"integrity": "sha512-aRctOLFpP6QqzJ0eThXElYvGt9l5st8ecYrcDgMZ2uM9Dq/C/6LGA2oaLmQBz5TqyA+mVvegi2aSGZJSbLxNmA==",
"dev": true
},
"echarts": {
"version": "5.2.2",
"resolved": "https://repo.huaweicloud.com/repository/npm/echarts/-/echarts-5.2.2.tgz",
"integrity": "sha512-yxuBfeIH5c+0FsoRP60w4De6omXhA06c7eUYBsC1ykB6Ys2yK5fSteIYWvkJ4xJVLQgCvAdO8C4mN6MLeJpBaw==",
"dev": true,
"requires": {
"tslib": "2.3.0",
"zrender": "5.2.1"
}
},
"ee-first": {
"version": "1.1.1",
"resolved": "https://repo.huaweicloud.com/repository/npm/ee-first/-/ee-first-1.1.1.tgz",
@ -17415,9 +17447,9 @@
}
},
"sweetalert2": {
"version": "11.3.3",
"resolved": "https://repo.huaweicloud.com/repository/npm/sweetalert2/-/sweetalert2-11.3.3.tgz",
"integrity": "sha512-10Keqbmjng/+XpkpSOQ6dttpztl7XNohjnpC6bX6XFgm0WpRXM81YE0wmonGYOP6uyzd76vpfnZS04PdVvO31Q==",
"version": "11.3.6",
"resolved": "https://repo.huaweicloud.com/repository/npm/sweetalert2/-/sweetalert2-11.3.6.tgz",
"integrity": "sha512-0JBlA36T1e0fuihcyvg4FjoucCOYNmbYDLrEOenGMVg1Jw7UHaC7FmDFp1qf9UGbO89pjgDJrfkThYln8TrYEQ==",
"dev": true
},
"tailwindcss": {
@ -17586,9 +17618,9 @@
"dev": true
},
"tslib": {
"version": "2.3.1",
"resolved": "https://repo.huaweicloud.com/repository/npm/tslib/-/tslib-2.3.1.tgz",
"integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==",
"version": "2.3.0",
"resolved": "https://repo.huaweicloud.com/repository/npm/tslib/-/tslib-2.3.0.tgz",
"integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==",
"dev": true
},
"tty-browserify": {
@ -18100,6 +18132,15 @@
"resolved": "https://repo.huaweicloud.com/repository/npm/yargs-parser/-/yargs-parser-21.0.0.tgz",
"integrity": "sha512-z9kApYUOCwoeZ78rfRYYWdiU/iNL6mwwYlkkZfJoyMR1xps+NEBX5X7XmRpxkZHhXJ6+Ey00IwKxBBSW9FIjyA==",
"dev": true
},
"zrender": {
"version": "5.2.1",
"resolved": "https://repo.huaweicloud.com/repository/npm/zrender/-/zrender-5.2.1.tgz",
"integrity": "sha512-M3bPGZuyLTNBC6LiNKXJwSCtglMp8XUEqEBG+2MdICDI3d1s500Y4P0CzldQGsqpRVB7fkvf3BKQQRxsEaTlsw==",
"dev": true,
"requires": {
"tslib": "2.3.0"
}
}
}
}

View File

@ -10,16 +10,11 @@
"production": "mix --production"
},
"devDependencies": {
"@fortawesome/fontawesome-free": "^5.15.4",
"@tailwindcss/forms": "^0.4.0",
"alpinejs": "^3.4.2",
"autoprefixer": "^10.1.0",
"axios": "^0.21",
"laravel-mix": "^6.0.6",
"lodash": "^4.17.19",
"postcss": "^8.2.1",
"postcss-import": "^14.0.1",
"tailwindcss": "^3.0.0",
"@fortawesome/fontawesome-free": "^5.15.4",
"blueimp-canvas-to-blob": "^3.29.0",
"blueimp-file-upload": "^10.32.0",
"blueimp-load-image": "^5.16.0",
@ -30,11 +25,17 @@
"jquery": "^3.6.0",
"jquery.photoswipe": "^1.1.1",
"justifiedGallery": "^3.8.1",
"laravel-mix": "^6.0.6",
"less": "^4.1.2",
"less-loader": "^10.2.0",
"lodash": "^4.17.19",
"postcss": "^8.2.1",
"postcss-import": "^14.0.1",
"resolve-url-loader": "^4.0.0",
"sweetalert2": "^11.3.3",
"tailwindcss": "^3.0.0",
"toastr": "^2.1.4",
"viewerjs": "^1.10.2",
"sweetalert2": "^11.3.3"
"echarts": "^5.2.2"
}
}

90
public/css/app.css vendored
View File

@ -762,9 +762,6 @@ select {
.mt-4 {
margin-top: 1rem;
}
.ml-4 {
margin-left: 1rem;
}
.mt-6 {
margin-top: 1.5rem;
}
@ -777,6 +774,9 @@ select {
.mr-2 {
margin-right: 0.5rem;
}
.ml-4 {
margin-left: 1rem;
}
.mt-8 {
margin-top: 2rem;
}
@ -807,9 +807,6 @@ select {
.inline-flex {
display: inline-flex;
}
.table {
display: table;
}
.grid {
display: grid;
}
@ -828,9 +825,6 @@ select {
.h-10 {
height: 2.5rem;
}
.h-20 {
height: 5rem;
}
.h-screen {
height: 100vh;
}
@ -846,6 +840,9 @@ select {
.h-16 {
height: 4rem;
}
.h-20 {
height: 5rem;
}
.h-6 {
height: 1.5rem;
}
@ -879,18 +876,18 @@ select {
.w-\[80\%\] {
width: 80%;
}
.w-20 {
width: 5rem;
}
.w-48 {
width: 12rem;
}
.w-3\/4 {
width: 75%;
}
.w-auto {
width: auto;
}
.w-48 {
width: 12rem;
}
.w-20 {
width: 5rem;
}
.w-6 {
width: 1.5rem;
}
@ -1111,9 +1108,6 @@ select {
.break-words {
overflow-wrap: break-word;
}
.break-all {
word-break: break-all;
}
.rounded-md {
border-radius: 0.375rem;
}
@ -1212,26 +1206,22 @@ select {
--tw-bg-opacity: 1;
background-color: rgb(248 113 113 / var(--tw-bg-opacity));
}
.bg-gray-800 {
--tw-bg-opacity: 1;
background-color: rgb(31 41 55 / var(--tw-bg-opacity));
}
.bg-black {
--tw-bg-opacity: 1;
background-color: rgb(0 0 0 / var(--tw-bg-opacity));
}
.bg-slate-50 {
.bg-gray-800 {
--tw-bg-opacity: 1;
background-color: rgb(248 250 252 / var(--tw-bg-opacity));
}
.bg-red-500 {
--tw-bg-opacity: 1;
background-color: rgb(239 68 68 / var(--tw-bg-opacity));
background-color: rgb(31 41 55 / var(--tw-bg-opacity));
}
.bg-gray-600 {
--tw-bg-opacity: 1;
background-color: rgb(75 85 99 / var(--tw-bg-opacity));
}
.bg-slate-50 {
--tw-bg-opacity: 1;
background-color: rgb(248 250 252 / var(--tw-bg-opacity));
}
.bg-gray-700 {
--tw-bg-opacity: 1;
background-color: rgb(55 65 81 / var(--tw-bg-opacity));
@ -1240,6 +1230,10 @@ select {
--tw-bg-opacity: 1;
background-color: rgb(107 114 128 / var(--tw-bg-opacity));
}
.bg-red-500 {
--tw-bg-opacity: 1;
background-color: rgb(239 68 68 / var(--tw-bg-opacity));
}
.bg-indigo-500 {
--tw-bg-opacity: 1;
background-color: rgb(99 102 241 / var(--tw-bg-opacity));
@ -1303,10 +1297,6 @@ select {
padding-top: 0.75rem;
padding-bottom: 0.75rem;
}
.py-10 {
padding-top: 2.5rem;
padding-bottom: 2.5rem;
}
.px-6 {
padding-left: 1.5rem;
padding-right: 1.5rem;
@ -1335,6 +1325,10 @@ select {
padding-top: 0.375rem;
padding-bottom: 0.375rem;
}
.py-10 {
padding-top: 2.5rem;
padding-bottom: 2.5rem;
}
.pb-6 {
padding-bottom: 1.5rem;
}
@ -1392,14 +1386,14 @@ select {
font-size: 3rem;
line-height: 1;
}
.text-4xl {
font-size: 2.25rem;
line-height: 2.5rem;
}
.text-lg {
font-size: 1.125rem;
line-height: 1.75rem;
}
.text-4xl {
font-size: 2.25rem;
line-height: 2.5rem;
}
.text-base {
font-size: 1rem;
line-height: 1.5rem;
@ -1477,14 +1471,6 @@ select {
--tw-text-opacity: 1;
color: rgb(74 222 128 / var(--tw-text-opacity));
}
.text-gray-300 {
--tw-text-opacity: 1;
color: rgb(209 213 219 / var(--tw-text-opacity));
}
.text-green-600 {
--tw-text-opacity: 1;
color: rgb(22 163 74 / var(--tw-text-opacity));
}
.text-gray-900 {
--tw-text-opacity: 1;
color: rgb(17 24 39 / var(--tw-text-opacity));
@ -1497,6 +1483,14 @@ select {
--tw-text-opacity: 1;
color: rgb(229 231 235 / var(--tw-text-opacity));
}
.text-gray-300 {
--tw-text-opacity: 1;
color: rgb(209 213 219 / var(--tw-text-opacity));
}
.text-green-600 {
--tw-text-opacity: 1;
color: rgb(22 163 74 / var(--tw-text-opacity));
}
.text-indigo-600 {
--tw-text-opacity: 1;
color: rgb(79 70 229 / var(--tw-text-opacity));
@ -1659,14 +1653,14 @@ select {
--tw-text-opacity: 1;
color: rgb(129 140 248 / var(--tw-text-opacity));
}
.hover\:text-gray-900:hover {
--tw-text-opacity: 1;
color: rgb(17 24 39 / var(--tw-text-opacity));
}
.hover\:text-white:hover {
--tw-text-opacity: 1;
color: rgb(255 255 255 / var(--tw-text-opacity));
}
.hover\:text-gray-900:hover {
--tw-text-opacity: 1;
color: rgb(17 24 39 / var(--tw-text-opacity));
}
.hover\:text-gray-700:hover {
--tw-text-opacity: 1;
color: rgb(55 65 81 / var(--tw-text-opacity));

136
public/js/app.js vendored
View File

@ -34023,7 +34023,7 @@ process.umask = function() { return 0; };
/***/ (function(module) {
/*!
* sweetalert2 v11.3.3
* sweetalert2 v11.3.6
* Released under the MIT License.
*/
(function (global, factory) {
@ -34050,27 +34050,28 @@ process.umask = function() { return 0; };
};
/**
* Capitalize the first letter of a string
* @param str
* @param {string} str
* @returns {string}
*/
const capitalizeFirstLetter = str => str.charAt(0).toUpperCase() + str.slice(1);
/**
* Convert NodeList to Array
* @param nodeList
* @param {NodeList | HTMLCollection | NamedNodeMap} nodeList
* @returns {array}
*/
const toArray = nodeList => Array.prototype.slice.call(nodeList);
/**
* Standardise console warnings
* @param message
* Standardize console warnings
* @param {string | array} message
*/
const warn = message => {
console.warn("".concat(consolePrefix, " ").concat(typeof message === 'object' ? message.join(' ') : message));
};
/**
* Standardise console errors
* @param message
* Standardize console errors
* @param {string} message
*/
const error = message => {
@ -34085,7 +34086,7 @@ process.umask = function() { return 0; };
const previousWarnOnceMessages = [];
/**
* Show a console warning, but only if it hasn't already been shown
* @param message
* @param {string} message
*/
const warnOnce = message => {
@ -34319,12 +34320,12 @@ process.umask = function() { return 0; };
const getFocusableElements = () => {
const focusableElementsWithTabindex = toArray(getPopup().querySelectorAll('[tabindex]:not([tabindex="-1"]):not([tabindex="0"])')) // sort according to tabindex
.sort((a, b) => {
a = parseInt(a.getAttribute('tabindex'));
b = parseInt(b.getAttribute('tabindex'));
const tabindexA = parseInt(a.getAttribute('tabindex'));
const tabindexB = parseInt(b.getAttribute('tabindex'));
if (a > b) {
if (tabindexA > tabindexB) {
return 1;
} else if (a < b) {
} else if (tabindexA < tabindexB) {
return -1;
}
@ -34592,7 +34593,11 @@ process.umask = function() { return 0; };
timerProgressBar.style.width = "".concat(timerProgressBarPercent, "%");
};
// Detect Node env
/**
* Detect Node env
*
* @returns {boolean}
*/
const isNodeEnv = () => typeof window === 'undefined' || typeof document === 'undefined';
const RESTORE_FOCUS_TIMEOUT = 100;
@ -34760,8 +34765,9 @@ process.umask = function() { return 0; };
const testEl = document.createElement('div');
const transEndEventNames = {
WebkitAnimation: 'webkitAnimationEnd',
OAnimation: 'oAnimationEnd oanimationend',
animation: 'animationend'
// Chrome, Safari and Opera
animation: 'animationend' // Standard syntax
};
for (const i in transEndEventNames) {
@ -35187,13 +35193,13 @@ process.umask = function() { return 0; };
setColor(icon, params); // Success icon background color
adjustSuccessIconBackgoundColor(); // Custom class
adjustSuccessIconBackgroundColor(); // Custom class
applyCustomClass(icon, params, 'icon');
}; // Adjust success icon background color to match the popup background color
const adjustSuccessIconBackgoundColor = () => {
const adjustSuccessIconBackgroundColor = () => {
const popup = getPopup();
const popupBackgroundColor = window.getComputedStyle(popup).getPropertyValue('background-color');
const successIconParts = popup.querySelectorAll('[class^=swal2-success-circular-line], .swal2-success-fix');
@ -35437,32 +35443,39 @@ process.umask = function() { return 0; };
if (!template) {
return {};
}
/** @type {DocumentFragment} */
const templateContent = template.content;
showWarningsForElements(templateContent);
const result = Object.assign(getSwalParams(templateContent), getSwalButtons(templateContent), getSwalImage(templateContent), getSwalIcon(templateContent), getSwalInput(templateContent), getSwalStringParams(templateContent, swalStringParams));
return result;
};
/**
* @param {DocumentFragment} templateContent
*/
const getSwalParams = templateContent => {
const result = {};
toArray(templateContent.querySelectorAll('swal-param')).forEach(param => {
showWarningsForAttributes(param, ['name', 'value']);
const paramName = param.getAttribute('name');
let value = param.getAttribute('value');
const value = param.getAttribute('value');
if (typeof defaultParams[paramName] === 'boolean' && value === 'false') {
value = false;
result[paramName] = false;
}
if (typeof defaultParams[paramName] === 'object') {
value = JSON.parse(value);
result[paramName] = JSON.parse(value);
}
result[paramName] = value;
});
return result;
};
/**
* @param {DocumentFragment} templateContent
*/
const getSwalButtons = templateContent => {
const result = {};
@ -35482,9 +35495,15 @@ process.umask = function() { return 0; };
});
return result;
};
/**
* @param {DocumentFragment} templateContent
*/
const getSwalImage = templateContent => {
const result = {};
/** @type {HTMLElement} */
const image = templateContent.querySelector('swal-image');
if (image) {
@ -35509,9 +35528,15 @@ process.umask = function() { return 0; };
return result;
};
/**
* @param {DocumentFragment} templateContent
*/
const getSwalIcon = templateContent => {
const result = {};
/** @type {HTMLElement} */
const icon = templateContent.querySelector('swal-icon');
if (icon) {
@ -35530,9 +35555,15 @@ process.umask = function() { return 0; };
return result;
};
/**
* @param {DocumentFragment} templateContent
*/
const getSwalInput = templateContent => {
const result = {};
/** @type {HTMLElement} */
const input = templateContent.querySelector('swal-input');
if (input) {
@ -35566,12 +35597,19 @@ process.umask = function() { return 0; };
return result;
};
/**
* @param {DocumentFragment} templateContent
* @param {string[]} paramNames
*/
const getSwalStringParams = (templateContent, paramNames) => {
const result = {};
for (const i in paramNames) {
const paramName = paramNames[i];
/** @type {HTMLElement} */
const tag = templateContent.querySelector(paramName);
if (tag) {
@ -35582,10 +35620,14 @@ process.umask = function() { return 0; };
return result;
};
/**
* @param {DocumentFragment} templateContent
*/
const showWarningsForElements = template => {
const showWarningsForElements = templateContent => {
const allowedElements = swalStringParams.concat(['swal-param', 'swal-button', 'swal-image', 'swal-icon', 'swal-input', 'swal-input-option']);
toArray(template.children).forEach(el => {
toArray(templateContent.children).forEach(el => {
const tagName = el.tagName.toLowerCase();
if (allowedElements.indexOf(tagName) === -1) {
@ -35593,6 +35635,11 @@ process.umask = function() { return 0; };
}
});
};
/**
* @param {HTMLElement} el
* @param {string[]} allowedAttributes
*/
const showWarningsForAttributes = (el, allowedAttributes) => {
toArray(el.attributes).forEach(attribute => {
@ -35743,14 +35790,20 @@ process.umask = function() { return 0; };
document.body.style.top = "".concat(offset * -1, "px");
addClass(document.body, swalClasses.iosfix);
lockBodyScroll();
addBottomPaddingForTallPopups(); // #1948
addBottomPaddingForTallPopups();
}
};
/**
* https://github.com/sweetalert2/sweetalert2/issues/1948
*/
const addBottomPaddingForTallPopups = () => {
const safari = !navigator.userAgent.match(/(CriOS|FxiOS|EdgiOS|YaBrowser|UCBrowser)/i);
const ua = navigator.userAgent;
const iOS = !!ua.match(/iPad/i) || !!ua.match(/iPhone/i);
const webkit = !!ua.match(/WebKit/i);
const iOSSafari = iOS && webkit && !ua.match(/CriOS/i);
if (safari) {
if (iOSSafari) {
const bottomPanelHeight = 44;
if (getPopup().scrollHeight > window.innerHeight - bottomPanelHeight) {
@ -35780,7 +35833,7 @@ process.umask = function() { return 0; };
const target = event.target;
const container = getContainer();
if (isStylys(event) || isZoom(event)) {
if (isStylus(event) || isZoom(event)) {
return false;
}
@ -35797,9 +35850,15 @@ process.umask = function() { return 0; };
return false;
};
/**
* https://github.com/sweetalert2/sweetalert2/issues/1786
*
* @param {*} event
* @returns {boolean}
*/
const isStylys = event => {
// #1786
const isStylus = event => {
return event.touches && event.touches.length && event.touches[0].touchType === 'stylus';
};
@ -35891,7 +35950,7 @@ process.umask = function() { return 0; };
};
const addClasses$1 = (container, popup, params) => {
addClass(container, params.showClass.backdrop); // the workaround with setting/unsetting opacity is needed for #2019 and 2059
addClass(container, params.showClass.backdrop); // this workaround with opacity is needed for https://github.com/sweetalert2/sweetalert2/issues/2059
popup.style.setProperty('opacity', '0', 'important');
show(popup, 'grid');
@ -36157,6 +36216,11 @@ process.umask = function() { return 0; };
/* 'confirm' | 'deny' */
) => {
const innerParams = privateProps.innerParams.get(instance);
if (!innerParams.input) {
return error("The \"input\" parameter is needed to be set when using returnInputValueOn".concat(capitalizeFirstLetter(type)));
}
const inputValue = getInputValue(instance, innerParams);
if (innerParams.inputValidator) {
@ -36199,7 +36263,7 @@ process.umask = function() { return 0; };
}
if (innerParams.preDeny) {
privateProps.awaitingPromise.set(instance || undefined, true); // Flagging the instance as awaiting a promise so it's own promise's reject/resolve methods doesnt get destroyed until the result from this preDeny's promise is received
privateProps.awaitingPromise.set(instance || undefined, true); // Flagging the instance as awaiting a promise so it's own promise's reject/resolve methods doesn't get destroyed until the result from this preDeny's promise is received
const preDenyPromise = Promise.resolve().then(() => asPromise(innerParams.preDeny(value, innerParams.validationMessage)));
preDenyPromise.then(preDenyValue => {
@ -36240,7 +36304,7 @@ process.umask = function() { return 0; };
if (innerParams.preConfirm) {
instance.resetValidationMessage();
privateProps.awaitingPromise.set(instance || undefined, true); // Flagging the instance as awaiting a promise so it's own promise's reject/resolve methods doesnt get destroyed until the result from this preConfirm's promise is received
privateProps.awaitingPromise.set(instance || undefined, true); // Flagging the instance as awaiting a promise so it's own promise's reject/resolve methods doesn't get destroyed until the result from this preConfirm's promise is received
const preConfirmPromise = Promise.resolve().then(() => asPromise(innerParams.preConfirm(value, innerParams.validationMessage)));
preConfirmPromise.then(preConfirmValue => {
@ -37022,7 +37086,7 @@ process.umask = function() { return 0; };
const innerParams = privateProps.innerParams.get(this);
if (!innerParams) {
disposeWeakMaps(this); // The WeakMaps might have been partly destroyed, we must recall it to dispose any remaining weakmaps #2335
disposeWeakMaps(this); // The WeakMaps might have been partly destroyed, we must recall it to dispose any remaining WeakMaps #2335
return; // This instance has already been destroyed
} // Check if there is another Swal closing
@ -37304,7 +37368,7 @@ process.umask = function() { return 0; };
};
});
SweetAlert.DismissReason = DismissReason;
SweetAlert.version = '11.3.3';
SweetAlert.version = '11.3.6';
const Swal = SweetAlert; // @ts-ignore

45
public/js/echarts/echarts.min.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

@ -15,5 +15,6 @@
"/js/clipboard/clipboard.min.js": "/js/clipboard/clipboard.min.js",
"/js/clipboard/index.browser.js": "/js/clipboard/index.browser.js",
"/js/dragselect/ds.min.js": "/js/dragselect/ds.min.js",
"/js/context-js/context-js.js": "/js/context-js/context-js.js"
"/js/context-js/context-js.js": "/js/context-js/context-js.js",
"/js/echarts/echarts.min.js": "/js/echarts/echarts.min.js"
}

View File

@ -1,6 +1,6 @@
<?php
use App\Http\Controllers\User\ImageController;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Route;
use App\Models\Group;
use App\Enums\GroupConfigKey;
@ -8,9 +8,9 @@ use App\Enums\GroupConfigKey;
$extensions = Group::getDefaultConfigs()->get(GroupConfigKey::AcceptedFileSuffixes);
Route::middleware('cache.headers:public;max_age=2628000;etag')->group(function () use ($extensions) {
Route::any('{key}.{extension}', [
ImageController::class, 'output',
Controller::class, 'output',
])->where('extension', implode('|', $extensions));
Route::any('{key}.{extension}!thumbnail', [
ImageController::class, 'thumbnail',
Controller::class, 'thumbnail',
])->where('extension', implode('|', $extensions));
});

3
webpack.mix.js vendored
View File

@ -42,3 +42,6 @@ mix.copy('node_modules/dragselect/dist/ds.min.js', 'public/js/dragselect')
// context-menu.min.js
mix.less('resources/css/context-js.less', 'public/css/context-js')
mix.copy('resources/js/context-js.js', 'public/js/context-js')
// apache echarts
mix.copy('node_modules/echarts/dist/echarts.min.js', 'public/js/echarts')