Compare commits

...

28 Commits

Author SHA1 Message Date
c169077365 Merge pull request 'feature' (#1) from feature into master
Reviewed-on: https://git.x-lf.cn/xiao_lfeng/XF_Index/pulls/1
2023-06-15 16:08:34 +08:00
a90486fa36 Merge branch 'master' into feature 2023-06-15 16:06:55 +08:00
24b6925533 处理完毕 2023-06-15 16:02:12 +08:00
4fa90e96b4 测试 2023-06-15 15:28:08 +08:00
59cc6c6e2a 资源文件修改 2023-06-15 00:03:40 +08:00
057bccb4d0 Navbar路由表更新 2023-06-15 00:03:19 +08:00
9ad4940ce5 路由表逻辑更新 2023-06-15 00:03:10 +08:00
508040ec8e 友链及友链添加 2023-06-15 00:02:54 +08:00
12308ab75d 数据库迁移更新 2023-06-15 00:01:03 +08:00
0220fd272c 修改逻辑 2023-06-13 23:53:30 +08:00
9b2337d76b 适配手机端菜单 2023-06-13 22:25:43 +08:00
e67ebcca6c 补丁修复 2023-06-13 22:04:56 +08:00
9fbc00d8c6 其他 2023-06-13 20:27:28 +08:00
dea4a13d32 路由表 2023-06-13 20:27:21 +08:00
888a6ec144 Composer 2023-06-13 20:27:13 +08:00
27854f3a6c 控制器及中间件 2023-06-13 20:27:06 +08:00
02445457e0 视图文件 2023-06-13 20:26:53 +08:00
40f1c16591 资源文件 2023-06-13 20:26:22 +08:00
33539aa006 Markdown 2023-06-13 20:25:55 +08:00
7740802940 数据库迁移 2023-06-13 20:25:45 +08:00
25deab5da5 CSS添加 2023-06-13 12:14:11 +08:00
6d44529a08 添加navbar,及路由表逻辑修改 2023-06-13 12:14:00 +08:00
b35e8bc486 添加主页,删除默认页 2023-06-13 12:13:20 +08:00
29f15eb8aa 修改地址路由表 2023-06-13 12:12:56 +08:00
6ff5773ca3 Dashboard页面更新 2023-06-12 21:44:30 +08:00
1cd8f46fc7 数据库更新 2023-06-12 21:44:12 +08:00
de745f7c9b FixUpload 2023-06-12 16:24:05 +08:00
1c5cc9bc57 Upload 2023-06-12 16:12:20 +08:00
53 changed files with 23844 additions and 971 deletions

View File

@ -0,0 +1,37 @@
<?php
/*
* Copyright © 2016 - 2023 筱锋xiao_lfeng. All Rights Reserved.
* 开发开源遵循 MIT 许可,若需商用请联系开发者
* https://www.x-lf.com/
*/
namespace App\Http\Controllers\Console;
use App\Http\Controllers\Controller;
use App\Http\Controllers\Index;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Contracts\View\Factory;
use Illuminate\Contracts\View\View;
use Illuminate\Support\Facades\DB;
class Dashboard extends Controller
{
protected array $data;
public function __construct()
{
$data = new Index();
$this->data = $data->data;
}
protected function ViewDashboard(): Factory|View|Application
{
$dataMarge = [
'blogFriendsTotal' => DB::table('blog_link')->whereNotIn('blog_link.blogLocation', [0,7])->count(),
'blogFriendsCheck' => DB::table('blog_link')->where('blog_link.blogLocation', 0)->count(),
'blogFriendsBest' => DB::table('blog_link')->where('blog_link.blogLocation',2)->count(),
];
$this->data = array_merge($this->data,$dataMarge);
return view('console.dashboard',$this->data);
}
}

View File

@ -0,0 +1,46 @@
<?php
/*
* Copyright © 2016 - 2023 筱锋xiao_lfeng. All Rights Reserved.
* 开发开源遵循 MIT 许可,若需商用请联系开发者
* https://www.x-lf.com/
*/
namespace App\Http\Controllers\Function;
use App\Http\Controllers\Controller;
use App\Http\Controllers\Index;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Contracts\View\Factory;
use Illuminate\Contracts\View\View;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
class Link extends Controller
{
protected array $data;
public function __construct()
{
$data = new Index();
$this->data = $data->data;
}
protected function ViewLink(Request $request): Factory|View|Application
{
$this->data['webSubTitle'] = '友链';
$this->GetFriendsLink($this->data);
return view('function.link',$this->data);
}
protected function ViewMakeFriend(): Factory|View|Application
{
$this->data['webSubTitle'] = '添加友链';
return view('function.make-friend',$this->data);
}
private function GetFriendsLink(array &$data): void
{
$data['blogLink'] = DB::table('blog_link')->whereNotIn('blog_link.blogLocation',[0])->get()->toArray();
$data['blogSort'] = DB::table('blog_sort')->orderBy('blog_sort.sort')->get()->toArray();
}
}

View File

@ -0,0 +1,80 @@
<?php
/*
* Copyright © 2016 - 2023 筱锋xiao_lfeng. All Rights Reserved.
* 开发开源遵循 MIT 许可,若需商用请联系开发者
* https://www.x-lf.com/
*/
namespace App\Http\Controllers;
use App\Http\Middleware\Michelf\MarkdownExtra;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Contracts\View\Factory;
use Illuminate\Contracts\View\View;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
class Index extends Controller
{
public array $data;
public function __construct()
{
$this->data = [
'webTitle' => empty($tempStorage = DB::table('info')->find(1)->data) ? '未定义标题' : $tempStorage,
'webDescription' => empty($tempStorage = DB::table('info')->find(2)->data) ? '未定义副标题' : $tempStorage,
'webSubTitle' => empty($tempStorage = DB::table('info')->find(3)->data) ? '未定义小标题' : $tempStorage,
'webSubTitleDescription' => empty($tempStorage = DB::table('info')->find(4)->data) ? '未定义小标题内容' : $tempStorage,
'webIcon' => empty($tempStorage = DB::table('info')->find(5)->data) ? asset('images/logo.jpg') : $tempStorage,
'webHeader' => DB::table('info')->find(7)->data,
'webFooter' => DB::table('info')->find(8)->data,
'webKeyword' => empty($tempStorage = DB::table('info')->find(6)->data) ? '筱锋,凌中的锋雨,xiao_lfeng' : $tempStorage,
'sqlAuthor' => empty($tempStorage = DB::table('info')->find(12)->data) ? '筱锋xiao_lfeng' : $tempStorage,
'sqlCopyRightYear' => DB::table('info')->find(13)->data,
'sqlIcp' => DB::table('info')->find(10)->data,
'sqlGongan' => DB::table('info')->find(11)->data,
'sqlBlog' => DB::table('info')->find(14)->data,
];
if (!empty($this->data['sqlGongan'])) {
preg_match('/[0-9]+/', $this->data['sqlGongan'], $data);
$this->data = array_merge($this->data, ['GonganCode' => $data[0]]);
}
if (Auth::check()) {
$this->data = array_merge($this->data,[
'userName' => Auth::user()->username,
'userEmail' => Auth::user()->email,
'userIcon' => Auth::user()->icon]);
}
}
protected function ViewIndex(): Factory|View|Application
{
return view('index', $this->data);
}
protected function ViewAboutMe(): Factory|View|Application
{
$resultAboutMe = DB::table('info')->where('info.value', '=', 'aboutMe')->value('info.data');
$data = [
'userAbout' => $this->MarkdownToStringReplace($resultAboutMe),
];
$this->data = array_merge($this->data, $data);
return view('about', $this->data);
}
private function MarkdownToStringReplace(string $dataBase): string
{
$decodeText = MarkdownExtra::defaultTransform($dataBase);
$decodeText = str_replace('<h1>', '<p class="text-4xl font-extrabold text-gray-900 dark:text-white mb-4"><i class="bi bi-link-45deg"></i>', $decodeText);
$decodeText = str_replace('<h2>', '<p class="text-3xl font-extrabold text-gray-900 dark:text-white mb-4"><i class="bi bi-link-45deg"></i>', $decodeText);
$decodeText = str_replace('<h3>', '<p class="text-2xl font-bold text-gray-900 dark:text-white mb-4"><i class="bi bi-link-45deg"></i>', $decodeText);
$decodeText = str_replace('<h4>', '<p class="text-xl font-bold text-gray-900 dark:text-white mb-4"><i class="bi bi-link-45deg"></i>', $decodeText);
$decodeText = str_replace('<h5>', '<p class="text-lg font-semibold text-gray-900 dark:text-white mb-4"><i class="bi bi-link-45deg"></i>', $decodeText);
$decodeText = str_replace('<h6>', '<p class="text-base font-medium text-gray-900 dark:text-white mb-4"><i class="bi bi-link-45deg"></i>', $decodeText);
$decodeText = str_replace('<p>', '<p class="text-base text-gray-900 dark:text-white m-4">', $decodeText);
$decodeText = str_replace('<a', '<a class="text-base text-gray-900 dark:text-white m-4"', $decodeText);
$decodeText = str_replace('<img', '<img class="rounded-lg mb-4"', $decodeText);
$decodeText = str_replace('<hr>', '<hr class="my-4">', $decodeText);
return (string)$decodeText;
}
}

View File

@ -0,0 +1,15 @@
<?php
/*
* Copyright © 2016 - 2023 筱锋xiao_lfeng. All Rights Reserved.
* 开发开源遵循 MIT 许可,若需商用请联系开发者
* https://www.x-lf.com/
*/
// Use this file if you cannot use class autoloading. It will include all the
// files needed for the Markdown parser.
//
// Take a look at the PSR-0-compatible class autoloading implementation
// in the Readme.php file if you want a simple autoloader setup.
require_once dirname(__FILE__) . '/MarkdownInterface.php';
require_once dirname(__FILE__) . '/Markdown.php';

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,16 @@
<?php
/*
* Copyright © 2016 - 2023 筱锋xiao_lfeng. All Rights Reserved.
* 开发开源遵循 MIT 许可,若需商用请联系开发者
* https://www.x-lf.com/
*/
// Use this file if you cannot use class autoloading. It will include all the
// files needed for the MarkdownExtra parser.
//
// Take a look at the PSR-0-compatible class autoloading implementation
// in the Readme.php file if you want a simple autoloader setup.
require_once dirname(__FILE__) . '/MarkdownInterface.php';
require_once dirname(__FILE__) . '/Markdown.php';
require_once dirname(__FILE__) . '/MarkdownExtra.php';

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,14 @@
<?php
/*
* Copyright © 2016 - 2023 筱锋xiao_lfeng. All Rights Reserved.
* 开发开源遵循 MIT 许可,若需商用请联系开发者
* https://www.x-lf.com/
*/
// Use this file if you cannot use class autoloading. It will include all the
// files needed for the MarkdownInterface interface.
//
// Take a look at the PSR-0-compatible class autoloading implementation
// in the Readme.php file if you want a simple autoloader setup.
require_once dirname(__FILE__) . '/MarkdownInterface.php';

View File

@ -0,0 +1,35 @@
<?php
/*
* Copyright © 2016 - 2023 筱锋xiao_lfeng. All Rights Reserved.
* 开发开源遵循 MIT 许可,若需商用请联系开发者
* https://www.x-lf.com/
*/
namespace App\Http\Middleware\Michelf;
/**
* Markdown Parser Interface
*/
interface MarkdownInterface {
/**
* Initialize the parser and return the result of its transform method.
* This will work fine for derived classes too.
*
* @api
*
* @param string $text
* @return string
*/
public static function defaultTransform(string $text): string;
/**
* Main function. Performs some preprocessing on the input text
* and pass it through the document gamut.
*
* @api
*
* @param string $text
* @return string
*/
public function transform(string $text): string;
}

View File

@ -10,7 +10,9 @@
"guzzlehttp/guzzle": "^7.0.1",
"laravel/framework": "^8.75",
"laravel/sanctum": "^2.11",
"laravel/tinker": "^2.5"
"laravel/tinker": "^2.5",
"michelf/php-markdown": "^2.0",
"ext-http": "*"
},
"require-dev": {
"facade/ignition": "^2.5",

64
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "c61ff82cbf0142a401a48a8161e1595a",
"content-hash": "76ecfaf55321f8599920fed75a5e9b23",
"packages": [
{
"name": "asm89/stack-cors",
@ -1776,6 +1776,68 @@
],
"time": "2022-04-17T13:12:02+00:00"
},
{
"name": "michelf/php-markdown",
"version": "2.0.0",
"source": {
"type": "git",
"url": "https://github.com/michelf/php-markdown.git",
"reference": "eb176f173fbac58a045aff78e55f833264b34e71"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/michelf/php-markdown/zipball/eb176f173fbac58a045aff78e55f833264b34e71",
"reference": "eb176f173fbac58a045aff78e55f833264b34e71",
"shasum": "",
"mirrors": [
{
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
"preferred": true
}
]
},
"require": {
"php": ">=7.4"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^3.0",
"phpstan/phpstan": ">=1.0",
"phpstan/phpstan-phpunit": ">=1.0",
"phpunit/phpunit": "^9.5"
},
"type": "library",
"autoload": {
"psr-4": {
"Michelf\\": "Michelf/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Michel Fortin",
"email": "michel.fortin@michelf.ca",
"homepage": "https://michelf.ca/",
"role": "Developer"
},
{
"name": "John Gruber",
"homepage": "https://daringfireball.net/"
}
],
"description": "PHP Markdown",
"homepage": "https://michelf.ca/projects/php-markdown/",
"keywords": [
"markdown"
],
"support": {
"issues": "https://github.com/michelf/php-markdown/issues",
"source": "https://github.com/michelf/php-markdown/tree/2.0.0"
},
"time": "2022-09-26T12:21:08+00:00"
},
{
"name": "monolog/monolog",
"version": "2.9.0",

View File

@ -56,7 +56,7 @@
| users are actually retrieved out of your database or other storage
| mechanisms used by this application to persist your user's data.
|
| If you have multiple user tables or models you may configure multiple
| If you have multiple user tables or modules you may configure multiple
| sources which represent each model / table. These sources may then
| be assigned to any extra authentication guards you have defined.
|

View File

@ -23,6 +23,7 @@ public function up()
$table->string('username',40);
$table->string('email',100)->unique();
$table->string('password',255);
$table->rememberToken();
$table->timestamps();
});
}

View File

@ -0,0 +1,46 @@
<?php
/*
* Copyright © 2016 - 2023 筱锋xiao_lfeng. All Rights Reserved.
* 开发开源遵循 MIT 许可,若需商用请联系开发者
* https://www.x-lf.com/
*/
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateBlogLinkTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('blog_link', function (Blueprint $table) {
$table->id();
$table->string('blogName',40);
$table->string('blogUrl');
$table->string('blogDescription');
$table->string('blogOwnEmail',100)->nullable();
$table->text('blogIcon');
$table->boolean('blogRssJudge')->default(0);
$table->text('blogRSS')->nullable();
$table->string('blogServerHost')->nullable();
$table->unsignedInteger('blogLocation')->default(0);
$table->unsignedInteger('blogSetColor')->default(0);
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('blog_link');
}
}

View File

@ -0,0 +1,37 @@
<?php
/*
* Copyright © 2016 - 2023 筱锋xiao_lfeng. All Rights Reserved.
* 开发开源遵循 MIT 许可,若需商用请联系开发者
* https://www.x-lf.com/
*/
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class UpdateBlogLinkTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('blog_link', function (Blueprint $table) {
$table->boolean('blogAddType')->default(0)->after('blogLocation');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('blog_link', function (Blueprint $table) {
//
});
}
}

View File

@ -19,7 +19,8 @@ class UpdateUsersTable extends Migration
public function up()
{
Schema::table('users', function (Blueprint $table) {
$table->rememberToken();
$table->integer('linkId')->unique()->nullable()->default(null)->after('remember_token');
$table->string('icon')->default('https://api.x-lf.cn/avatar/?uid=1')->after('remember_token');
});
}

View File

@ -0,0 +1,38 @@
<?php
/*
* Copyright © 2016 - 2023 筱锋xiao_lfeng. All Rights Reserved.
* 开发开源遵循 MIT 许可,若需商用请联系开发者
* https://www.x-lf.com/
*/
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateInfoTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('info', function (Blueprint $table) {
$table->id();
$table->string('value')->comment('参数名字');
$table->text('data')->nullable()->comment('参数内容');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('info');
}
}

View File

@ -0,0 +1,52 @@
<?php
/*
* Copyright © 2016 - 2023 筱锋xiao_lfeng. All Rights Reserved.
* 开发开源遵循 MIT 许可,若需商用请联系开发者
* https://www.x-lf.com/
*/
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
class UpdateInfoTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('info', function (Blueprint $table) {
// 构建数据
DB::table('info')->insert(['value' => 'title', 'created_at' => date('Y-m-d H:i:s')]);
DB::table('info')->insert(['value' => 'description', 'created_at' => date('Y-m-d H:i:s')]);
DB::table('info')->insert(['value' => 'subTitle', 'created_at' => date('Y-m-d H:i:s')]);
DB::table('info')->insert(['value' => 'subTitleDescription', 'created_at' => date('Y-m-d H:i:s')]);
DB::table('info')->insert(['value' => 'icon', 'created_at' => date('Y-m-d H:i:s')]);
DB::table('info')->insert(['value' => 'keyword', 'created_at' => date('Y-m-d H:i:s')]);
DB::table('info')->insert(['value' => 'webHeader', 'created_at' => date('Y-m-d H:i:s')]);
DB::table('info')->insert(['value' => 'webFooter', 'created_at' => date('Y-m-d H:i:s')]);
DB::table('info')->insert(['value' => 'aboutMe', 'created_at' => date('Y-m-d H:i:s')]);
DB::table('info')->insert(['value' => 'icp', 'created_at' => date('Y-m-d H:i:s')]);
DB::table('info')->insert(['value' => 'gongan', 'created_at' => date('Y-m-d H:i:s')]);
DB::table('info')->insert(['value' => 'author', 'created_at' => date('Y-m-d H:i:s')]);
DB::table('info')->insert(['value' => 'copyRightYear', 'created_at' => date('Y-m-d H:i:s')]);
DB::table('info')->insert(['value' => 'blog', 'created_at' => date('Y-m-d H:i:s')]);
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('info', function (Blueprint $table) {
//
});
}
}

View File

@ -0,0 +1,39 @@
<?php
/*
* Copyright © 2016 - 2023 筱锋xiao_lfeng. All Rights Reserved.
* 开发开源遵循 MIT 许可,若需商用请联系开发者
* https://www.x-lf.com/
*/
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateBlogSortTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('blog_sort', function (Blueprint $table) {
$table->id();
$table->integer('sort')->comment('排序(数字越小权限越大)');
$table->boolean('userAble')->default(0)->comment('允许用户选择位置');
$table->string('title')->comment('标题');
$table->text('description')->comment('描述')->nullable();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('blog_sort');
}
}

1028
install.sh Normal file

File diff suppressed because it is too large Load Diff

View File

@ -24,14 +24,14 @@
</include>
</coverage>
<php>
<server name="APP_ENV" value="testing"/>
<server name="BCRYPT_ROUNDS" value="4"/>
<server name="CACHE_DRIVER" value="array"/>
<!-- <server name="DB_CONNECTION" value="sqlite"/> -->
<!-- <server name="DB_DATABASE" value=":memory:"/> -->
<server name="MAIL_MAILER" value="array"/>
<server name="QUEUE_CONNECTION" value="sync"/>
<server name="SESSION_DRIVER" value="array"/>
<server name="TELESCOPE_ENABLED" value="false"/>
<server name="APP_ENV" valueLink="testing"/>
<server name="BCRYPT_ROUNDS" valueLink="4"/>
<server name="CACHE_DRIVER" valueLink="array"/>
<!-- <server name="DB_CONNECTION" valueLink="sqlite"/> -->
<!-- <server name="DB_DATABASE" valueLink=":memory:"/> -->
<server name="MAIL_MAILER" valueLink="array"/>
<server name="QUEUE_CONNECTION" valueLink="sync"/>
<server name="SESSION_DRIVER" valueLink="array"/>
<server name="TELESCOPE_ENABLED" valueLink="false"/>
</php>
</phpunit>

1
public/.user.ini Normal file
View File

@ -0,0 +1 @@
open_basedir=/home/xiao_lfeng/Project/PHP/XF_index/:/tmp/

File diff suppressed because it is too large Load Diff

7491
public/css/flowbite.css Normal file

File diff suppressed because it is too large Load Diff

7
public/css/flowbite.min.css vendored Normal file

File diff suppressed because one or more lines are too long

BIN
public/images/avatar.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
public/images/logo.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 419 KiB

2
public/js/jquery.js vendored
View File

@ -6822,7 +6822,7 @@ function boxModelAdjustment( elem, dimension, box, isBorderBox, styles, computed
for ( ; i < 4; i += 2 ) {
// Both box models exclude margin
// Both box modules exclude margin
if ( box === "margin" ) {
delta += jQuery.css( elem, box + cssExpand[ i ], true, styles );
}

868
public/js/lazyload.js Normal file
View File

@ -0,0 +1,868 @@
/*
* Copyright © 2016 - 2023 筱锋xiao_lfeng. All Rights Reserved.
* 开发开源遵循 MIT 许可若需商用请联系开发者
* https://www.x-lf.com/
*/
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
typeof define === 'function' && define.amd ? define(factory) :
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.LazyLoad = factory());
}(this, (function () { 'use strict';
function _extends() {
_extends = Object.assign || function (target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) {
if (Object.prototype.hasOwnProperty.call(source, key)) {
target[key] = source[key];
}
}
}
return target;
};
return _extends.apply(this, arguments);
}
var runningOnBrowser = typeof window !== "undefined";
var isBot = runningOnBrowser && !("onscroll" in window) || typeof navigator !== "undefined" && /(gle|ing|ro)bot|crawl|spider/i.test(navigator.userAgent);
var supportsIntersectionObserver = runningOnBrowser && "IntersectionObserver" in window;
var supportsClassList = runningOnBrowser && "classList" in document.createElement("p");
var isHiDpi = runningOnBrowser && window.devicePixelRatio > 1;
var defaultSettings = {
elements_selector: ".lazy",
container: isBot || runningOnBrowser ? document : null,
threshold: 300,
thresholds: null,
data_src: "src",
data_srcset: "srcset",
data_sizes: "sizes",
data_bg: "bg",
data_bg_hidpi: "bg-hidpi",
data_bg_multi: "bg-multi",
data_bg_multi_hidpi: "bg-multi-hidpi",
data_bg_set: "bg-set",
data_poster: "poster",
class_applied: "applied",
class_loading: "loading",
class_loaded: "loaded",
class_error: "error",
class_entered: "entered",
class_exited: "exited",
unobserve_completed: true,
unobserve_entered: false,
cancel_on_exit: true,
callback_enter: null,
callback_exit: null,
callback_applied: null,
callback_loading: null,
callback_loaded: null,
callback_error: null,
callback_finish: null,
callback_cancel: null,
use_native: false,
restore_on_error: false
};
var getExtendedSettings = function getExtendedSettings(customSettings) {
return _extends({}, defaultSettings, customSettings);
};
/* Creates instance and notifies it through the window element */
var createInstance = function createInstance(classObj, options) {
var event;
var eventString = "LazyLoad::Initialized";
var instance = new classObj(options);
try {
// Works in modern browsers
event = new CustomEvent(eventString, {
detail: {
instance: instance
}
});
} catch (err) {
// Works in Internet Explorer (all versions)
event = document.createEvent("CustomEvent");
event.initCustomEvent(eventString, false, false, {
instance: instance
});
}
window.dispatchEvent(event);
};
/* Auto initialization of one or more instances of lazyload, depending on the
options passed in (plain object or an array) */
var autoInitialize = function autoInitialize(classObj, options) {
if (!options) {
return;
}
if (!options.length) {
// Plain object
createInstance(classObj, options);
} else {
// Array of objects
for (var i = 0, optionsItem; optionsItem = options[i]; i += 1) {
createInstance(classObj, optionsItem);
}
}
};
var SRC = "src";
var SRCSET = "srcset";
var SIZES = "sizes";
var POSTER = "poster";
var ORIGINALS = "llOriginalAttrs";
var DATA = "data";
var statusLoading = "loading";
var statusLoaded = "loaded";
var statusApplied = "applied";
var statusEntered = "entered";
var statusError = "error";
var statusNative = "native";
var dataPrefix = "data-";
var statusDataName = "ll-status";
var getData = function getData(element, attribute) {
return element.getAttribute(dataPrefix + attribute);
};
var setData = function setData(element, attribute, value) {
var attrName = dataPrefix + attribute;
if (value === null) {
element.removeAttribute(attrName);
return;
}
element.setAttribute(attrName, value);
};
var getStatus = function getStatus(element) {
return getData(element, statusDataName);
};
var setStatus = function setStatus(element, status) {
return setData(element, statusDataName, status);
};
var resetStatus = function resetStatus(element) {
return setStatus(element, null);
};
var hasEmptyStatus = function hasEmptyStatus(element) {
return getStatus(element) === null;
};
var hasStatusLoading = function hasStatusLoading(element) {
return getStatus(element) === statusLoading;
};
var hasStatusError = function hasStatusError(element) {
return getStatus(element) === statusError;
};
var hasStatusNative = function hasStatusNative(element) {
return getStatus(element) === statusNative;
};
var statusesAfterLoading = [statusLoading, statusLoaded, statusApplied, statusError];
var hadStartedLoading = function hadStartedLoading(element) {
return statusesAfterLoading.indexOf(getStatus(element)) >= 0;
};
var safeCallback = function safeCallback(callback, arg1, arg2, arg3) {
if (!callback) {
return;
}
if (arg3 !== undefined) {
callback(arg1, arg2, arg3);
return;
}
if (arg2 !== undefined) {
callback(arg1, arg2);
return;
}
callback(arg1);
};
var addClass = function addClass(element, className) {
if (supportsClassList) {
element.classList.add(className);
return;
}
element.className += (element.className ? " " : "") + className;
};
var removeClass = function removeClass(element, className) {
if (supportsClassList) {
element.classList.remove(className);
return;
}
element.className = element.className.replace(new RegExp("(^|\\s+)" + className + "(\\s+|$)"), " ").replace(/^\s+/, "").replace(/\s+$/, "");
};
var addTempImage = function addTempImage(element) {
element.llTempImage = document.createElement("IMG");
};
var deleteTempImage = function deleteTempImage(element) {
delete element.llTempImage;
};
var getTempImage = function getTempImage(element) {
return element.llTempImage;
};
var unobserve = function unobserve(element, instance) {
if (!instance) return;
var observer = instance._observer;
if (!observer) return;
observer.unobserve(element);
};
var resetObserver = function resetObserver(observer) {
observer.disconnect();
};
var unobserveEntered = function unobserveEntered(element, settings, instance) {
if (settings.unobserve_entered) unobserve(element, instance);
};
var updateLoadingCount = function updateLoadingCount(instance, delta) {
if (!instance) return;
instance.loadingCount += delta;
};
var decreaseToLoadCount = function decreaseToLoadCount(instance) {
if (!instance) return;
instance.toLoadCount -= 1;
};
var setToLoadCount = function setToLoadCount(instance, value) {
if (!instance) return;
instance.toLoadCount = value;
};
var isSomethingLoading = function isSomethingLoading(instance) {
return instance.loadingCount > 0;
};
var haveElementsToLoad = function haveElementsToLoad(instance) {
return instance.toLoadCount > 0;
};
var getSourceTags = function getSourceTags(parentTag) {
var sourceTags = [];
for (var i = 0, childTag; childTag = parentTag.children[i]; i += 1) {
if (childTag.tagName === "SOURCE") {
sourceTags.push(childTag);
}
}
return sourceTags;
};
var forEachPictureSource = function forEachPictureSource(element, fn) {
var parent = element.parentNode;
if (!parent || parent.tagName !== "PICTURE") {
return;
}
var sourceTags = getSourceTags(parent);
sourceTags.forEach(fn);
};
var forEachVideoSource = function forEachVideoSource(element, fn) {
var sourceTags = getSourceTags(element);
sourceTags.forEach(fn);
};
var attrsSrc = [SRC];
var attrsSrcPoster = [SRC, POSTER];
var attrsSrcSrcsetSizes = [SRC, SRCSET, SIZES];
var attrsData = [DATA];
var hasOriginalAttrs = function hasOriginalAttrs(element) {
return !!element[ORIGINALS];
};
var getOriginalAttrs = function getOriginalAttrs(element) {
return element[ORIGINALS];
};
var deleteOriginalAttrs = function deleteOriginalAttrs(element) {
return delete element[ORIGINALS];
}; // ## SAVE ##
var setOriginalsObject = function setOriginalsObject(element, attributes) {
if (hasOriginalAttrs(element)) {
return;
}
var originals = {};
attributes.forEach(function (attribute) {
originals[attribute] = element.getAttribute(attribute);
});
element[ORIGINALS] = originals;
};
var saveOriginalBackgroundStyle = function saveOriginalBackgroundStyle(element) {
if (hasOriginalAttrs(element)) {
return;
}
element[ORIGINALS] = {
backgroundImage: element.style.backgroundImage
};
}; // ## RESTORE ##
var setOrResetAttribute = function setOrResetAttribute(element, attrName, value) {
if (!value) {
element.removeAttribute(attrName);
return;
}
element.setAttribute(attrName, value);
};
var restoreOriginalAttrs = function restoreOriginalAttrs(element, attributes) {
if (!hasOriginalAttrs(element)) {
return;
}
var originals = getOriginalAttrs(element);
attributes.forEach(function (attribute) {
setOrResetAttribute(element, attribute, originals[attribute]);
});
};
var restoreOriginalBgImage = function restoreOriginalBgImage(element) {
if (!hasOriginalAttrs(element)) {
return;
}
var originals = getOriginalAttrs(element);
element.style.backgroundImage = originals.backgroundImage;
};
var manageApplied = function manageApplied(element, settings, instance) {
addClass(element, settings.class_applied);
setStatus(element, statusApplied); // Instance is not provided when loading is called from static class
if (!instance) return;
if (settings.unobserve_completed) {
// Unobserve now because we can't do it on load
unobserve(element, settings);
}
safeCallback(settings.callback_applied, element, instance);
};
var manageLoading = function manageLoading(element, settings, instance) {
addClass(element, settings.class_loading);
setStatus(element, statusLoading); // Instance is not provided when loading is called from static class
if (!instance) return;
updateLoadingCount(instance, +1);
safeCallback(settings.callback_loading, element, instance);
};
var setAttributeIfValue = function setAttributeIfValue(element, attrName, value) {
if (!value) {
return;
}
element.setAttribute(attrName, value);
};
var setImageAttributes = function setImageAttributes(element, settings) {
setAttributeIfValue(element, SIZES, getData(element, settings.data_sizes));
setAttributeIfValue(element, SRCSET, getData(element, settings.data_srcset));
setAttributeIfValue(element, SRC, getData(element, settings.data_src));
};
var setSourcesImg = function setSourcesImg(imgEl, settings) {
forEachPictureSource(imgEl, function (sourceTag) {
setOriginalsObject(sourceTag, attrsSrcSrcsetSizes);
setImageAttributes(sourceTag, settings);
});
setOriginalsObject(imgEl, attrsSrcSrcsetSizes);
setImageAttributes(imgEl, settings);
};
var setSourcesIframe = function setSourcesIframe(iframe, settings) {
setOriginalsObject(iframe, attrsSrc);
setAttributeIfValue(iframe, SRC, getData(iframe, settings.data_src));
};
var setSourcesVideo = function setSourcesVideo(videoEl, settings) {
forEachVideoSource(videoEl, function (sourceEl) {
setOriginalsObject(sourceEl, attrsSrc);
setAttributeIfValue(sourceEl, SRC, getData(sourceEl, settings.data_src));
});
setOriginalsObject(videoEl, attrsSrcPoster);
setAttributeIfValue(videoEl, POSTER, getData(videoEl, settings.data_poster));
setAttributeIfValue(videoEl, SRC, getData(videoEl, settings.data_src));
videoEl.load();
};
var setSourcesObject = function setSourcesObject(object, settings) {
setOriginalsObject(object, attrsData);
setAttributeIfValue(object, DATA, getData(object, settings.data_src));
};
var setBackground = function setBackground(element, settings, instance) {
var bg1xValue = getData(element, settings.data_bg);
var bgHiDpiValue = getData(element, settings.data_bg_hidpi);
var bgDataValue = isHiDpi && bgHiDpiValue ? bgHiDpiValue : bg1xValue;
if (!bgDataValue) return;
element.style.backgroundImage = "url(\"".concat(bgDataValue, "\")");
getTempImage(element).setAttribute(SRC, bgDataValue);
manageLoading(element, settings, instance);
}; // NOTE: THE TEMP IMAGE TRICK CANNOT BE DONE WITH data-multi-bg
// BECAUSE INSIDE ITS VALUES MUST BE WRAPPED WITH URL() AND ONE OF THEM
// COULD BE A GRADIENT BACKGROUND IMAGE
var setMultiBackground = function setMultiBackground(element, settings, instance) {
var bg1xValue = getData(element, settings.data_bg_multi);
var bgHiDpiValue = getData(element, settings.data_bg_multi_hidpi);
var bgDataValue = isHiDpi && bgHiDpiValue ? bgHiDpiValue : bg1xValue;
if (!bgDataValue) {
return;
}
element.style.backgroundImage = bgDataValue;
manageApplied(element, settings, instance);
};
var setImgsetBackground = function setImgsetBackground(element, settings, instance) {
var bgImgSetDataValue = getData(element, settings.data_bg_set);
if (!bgImgSetDataValue) {
return;
}
var imgSetValues = bgImgSetDataValue.split("|");
var bgImageValues = imgSetValues.map(function (value) {
return "image-set(".concat(value, ")");
});
element.style.backgroundImage = bgImageValues.join(); // Temporary fix for Chromeium with the -webkit- prefix
if (element.style.backgroundImage === '') {
bgImageValues = imgSetValues.map(function (value) {
return "-webkit-image-set(".concat(value, ")");
});
element.style.backgroundImage = bgImageValues.join();
}
manageApplied(element, settings, instance);
};
var setSourcesFunctions = {
IMG: setSourcesImg,
IFRAME: setSourcesIframe,
VIDEO: setSourcesVideo,
OBJECT: setSourcesObject
};
var setSourcesNative = function setSourcesNative(element, settings) {
var setSourcesFunction = setSourcesFunctions[element.tagName];
if (!setSourcesFunction) {
return;
}
setSourcesFunction(element, settings);
};
var setSources = function setSources(element, settings, instance) {
var setSourcesFunction = setSourcesFunctions[element.tagName];
if (!setSourcesFunction) {
return;
}
setSourcesFunction(element, settings);
manageLoading(element, settings, instance);
};
var elementsWithLoadEvent = ["IMG", "IFRAME", "VIDEO", "OBJECT"];
var hasLoadEvent = function hasLoadEvent(element) {
return elementsWithLoadEvent.indexOf(element.tagName) > -1;
};
var checkFinish = function checkFinish(settings, instance) {
if (instance && !isSomethingLoading(instance) && !haveElementsToLoad(instance)) {
safeCallback(settings.callback_finish, instance);
}
};
var addEventListener = function addEventListener(element, eventName, handler) {
element.addEventListener(eventName, handler);
element.llEvLisnrs[eventName] = handler;
};
var removeEventListener = function removeEventListener(element, eventName, handler) {
element.removeEventListener(eventName, handler);
};
var hasEventListeners = function hasEventListeners(element) {
return !!element.llEvLisnrs;
};
var addEventListeners = function addEventListeners(element, loadHandler, errorHandler) {
if (!hasEventListeners(element)) element.llEvLisnrs = {};
var loadEventName = element.tagName === "VIDEO" ? "loadeddata" : "load";
addEventListener(element, loadEventName, loadHandler);
addEventListener(element, "error", errorHandler);
};
var removeEventListeners = function removeEventListeners(element) {
if (!hasEventListeners(element)) {
return;
}
var eventListeners = element.llEvLisnrs;
for (var eventName in eventListeners) {
var handler = eventListeners[eventName];
removeEventListener(element, eventName, handler);
}
delete element.llEvLisnrs;
};
var doneHandler = function doneHandler(element, settings, instance) {
deleteTempImage(element);
updateLoadingCount(instance, -1);
decreaseToLoadCount(instance);
removeClass(element, settings.class_loading);
if (settings.unobserve_completed) {
unobserve(element, instance);
}
};
var loadHandler = function loadHandler(event, element, settings, instance) {
var goingNative = hasStatusNative(element);
doneHandler(element, settings, instance);
addClass(element, settings.class_loaded);
setStatus(element, statusLoaded);
safeCallback(settings.callback_loaded, element, instance);
if (!goingNative) checkFinish(settings, instance);
};
var errorHandler = function errorHandler(event, element, settings, instance) {
var goingNative = hasStatusNative(element);
doneHandler(element, settings, instance);
addClass(element, settings.class_error);
setStatus(element, statusError);
safeCallback(settings.callback_error, element, instance);
if (settings.restore_on_error) restoreOriginalAttrs(element, attrsSrcSrcsetSizes);
if (!goingNative) checkFinish(settings, instance);
};
var addOneShotEventListeners = function addOneShotEventListeners(element, settings, instance) {
var elementToListenTo = getTempImage(element) || element;
if (hasEventListeners(elementToListenTo)) {
// This happens when loading is retried twice
return;
}
var _loadHandler = function _loadHandler(event) {
loadHandler(event, element, settings, instance);
removeEventListeners(elementToListenTo);
};
var _errorHandler = function _errorHandler(event) {
errorHandler(event, element, settings, instance);
removeEventListeners(elementToListenTo);
};
addEventListeners(elementToListenTo, _loadHandler, _errorHandler);
};
var loadBackground = function loadBackground(element, settings, instance) {
addTempImage(element);
addOneShotEventListeners(element, settings, instance);
saveOriginalBackgroundStyle(element);
setBackground(element, settings, instance);
setMultiBackground(element, settings, instance);
setImgsetBackground(element, settings, instance);
};
var loadRegular = function loadRegular(element, settings, instance) {
addOneShotEventListeners(element, settings, instance);
setSources(element, settings, instance);
};
var load = function load(element, settings, instance) {
if (hasLoadEvent(element)) {
loadRegular(element, settings, instance);
} else {
loadBackground(element, settings, instance);
}
};
var loadNative = function loadNative(element, settings, instance) {
element.setAttribute("loading", "lazy");
addOneShotEventListeners(element, settings, instance);
setSourcesNative(element, settings);
setStatus(element, statusNative);
};
var removeImageAttributes = function removeImageAttributes(element) {
element.removeAttribute(SRC);
element.removeAttribute(SRCSET);
element.removeAttribute(SIZES);
};
var resetSourcesImg = function resetSourcesImg(element) {
forEachPictureSource(element, function (sourceTag) {
removeImageAttributes(sourceTag);
});
removeImageAttributes(element);
};
var restoreImg = function restoreImg(imgEl) {
forEachPictureSource(imgEl, function (sourceEl) {
restoreOriginalAttrs(sourceEl, attrsSrcSrcsetSizes);
});
restoreOriginalAttrs(imgEl, attrsSrcSrcsetSizes);
};
var restoreVideo = function restoreVideo(videoEl) {
forEachVideoSource(videoEl, function (sourceEl) {
restoreOriginalAttrs(sourceEl, attrsSrc);
});
restoreOriginalAttrs(videoEl, attrsSrcPoster);
videoEl.load();
};
var restoreIframe = function restoreIframe(iframeEl) {
restoreOriginalAttrs(iframeEl, attrsSrc);
};
var restoreObject = function restoreObject(objectEl) {
restoreOriginalAttrs(objectEl, attrsData);
};
var restoreFunctions = {
IMG: restoreImg,
IFRAME: restoreIframe,
VIDEO: restoreVideo,
OBJECT: restoreObject
};
var restoreAttributes = function restoreAttributes(element) {
var restoreFunction = restoreFunctions[element.tagName];
if (!restoreFunction) {
restoreOriginalBgImage(element);
return;
}
restoreFunction(element);
};
var resetClasses = function resetClasses(element, settings) {
if (hasEmptyStatus(element) || hasStatusNative(element)) {
return;
}
removeClass(element, settings.class_entered);
removeClass(element, settings.class_exited);
removeClass(element, settings.class_applied);
removeClass(element, settings.class_loading);
removeClass(element, settings.class_loaded);
removeClass(element, settings.class_error);
};
var restore = function restore(element, settings) {
restoreAttributes(element);
resetClasses(element, settings);
resetStatus(element);
deleteOriginalAttrs(element);
};
var cancelLoading = function cancelLoading(element, entry, settings, instance) {
if (!settings.cancel_on_exit) return;
if (!hasStatusLoading(element)) return;
if (element.tagName !== "IMG") return; //Works only on images
removeEventListeners(element);
resetSourcesImg(element);
restoreImg(element);
removeClass(element, settings.class_loading);
updateLoadingCount(instance, -1);
resetStatus(element);
safeCallback(settings.callback_cancel, element, entry, instance);
};
var onEnter = function onEnter(element, entry, settings, instance) {
var dontLoad = hadStartedLoading(element);
/* Save status
before setting it, to prevent loading it again. Fixes #526. */
setStatus(element, statusEntered);
addClass(element, settings.class_entered);
removeClass(element, settings.class_exited);
unobserveEntered(element, settings, instance);
safeCallback(settings.callback_enter, element, entry, instance);
if (dontLoad) return;
load(element, settings, instance);
};
var onExit = function onExit(element, entry, settings, instance) {
if (hasEmptyStatus(element)) return; //Ignore the first pass, at landing
addClass(element, settings.class_exited);
cancelLoading(element, entry, settings, instance);
safeCallback(settings.callback_exit, element, entry, instance);
};
var tagsWithNativeLazy = ["IMG", "IFRAME", "VIDEO"];
var shouldUseNative = function shouldUseNative(settings) {
return settings.use_native && "loading" in HTMLImageElement.prototype;
};
var loadAllNative = function loadAllNative(elements, settings, instance) {
elements.forEach(function (element) {
if (tagsWithNativeLazy.indexOf(element.tagName) === -1) {
return;
}
loadNative(element, settings, instance);
});
setToLoadCount(instance, 0);
};
var isIntersecting = function isIntersecting(entry) {
return entry.isIntersecting || entry.intersectionRatio > 0;
};
var getObserverSettings = function getObserverSettings(settings) {
return {
root: settings.container === document ? null : settings.container,
rootMargin: settings.thresholds || settings.threshold + "px"
};
};
var intersectionHandler = function intersectionHandler(entries, settings, instance) {
entries.forEach(function (entry) {
return isIntersecting(entry) ? onEnter(entry.target, entry, settings, instance) : onExit(entry.target, entry, settings, instance);
});
};
var observeElements = function observeElements(observer, elements) {
elements.forEach(function (element) {
observer.observe(element);
});
};
var updateObserver = function updateObserver(observer, elementsToObserve) {
resetObserver(observer);
observeElements(observer, elementsToObserve);
};
var setObserver = function setObserver(settings, instance) {
if (!supportsIntersectionObserver || shouldUseNative(settings)) {
return;
}
instance._observer = new IntersectionObserver(function (entries) {
intersectionHandler(entries, settings, instance);
}, getObserverSettings(settings));
};
var toArray = function toArray(nodeSet) {
return Array.prototype.slice.call(nodeSet);
};
var queryElements = function queryElements(settings) {
return settings.container.querySelectorAll(settings.elements_selector);
};
var excludeManagedElements = function excludeManagedElements(elements) {
return toArray(elements).filter(hasEmptyStatus);
};
var hasError = function hasError(element) {
return hasStatusError(element);
};
var filterErrorElements = function filterErrorElements(elements) {
return toArray(elements).filter(hasError);
};
var getElementsToLoad = function getElementsToLoad(elements, settings) {
return excludeManagedElements(elements || queryElements(settings));
};
var retryLazyLoad = function retryLazyLoad(settings, instance) {
var errorElements = filterErrorElements(queryElements(settings));
errorElements.forEach(function (element) {
removeClass(element, settings.class_error);
resetStatus(element);
});
instance.update();
};
var setOnlineCheck = function setOnlineCheck(settings, instance) {
if (!runningOnBrowser) {
return;
}
instance._onlineHandler = function () {
retryLazyLoad(settings, instance);
};
window.addEventListener("online", instance._onlineHandler);
};
var resetOnlineCheck = function resetOnlineCheck(instance) {
if (!runningOnBrowser) {
return;
}
window.removeEventListener("online", instance._onlineHandler);
};
var LazyLoad = function LazyLoad(customSettings, elements) {
var settings = getExtendedSettings(customSettings);
this._settings = settings;
this.loadingCount = 0;
setObserver(settings, this);
setOnlineCheck(settings, this);
this.update(elements);
};
LazyLoad.prototype = {
update: function update(givenNodeset) {
var settings = this._settings;
var elementsToLoad = getElementsToLoad(givenNodeset, settings);
setToLoadCount(this, elementsToLoad.length);
if (isBot || !supportsIntersectionObserver) {
this.loadAll(elementsToLoad);
return;
}
if (shouldUseNative(settings)) {
loadAllNative(elementsToLoad, settings, this);
return;
}
updateObserver(this._observer, elementsToLoad);
},
destroy: function destroy() {
// Observer
if (this._observer) {
this._observer.disconnect();
} // Clean handlers
resetOnlineCheck(this); // Clean custom attributes on elements
queryElements(this._settings).forEach(function (element) {
deleteOriginalAttrs(element);
}); // Delete all internal props
delete this._observer;
delete this._settings;
delete this._onlineHandler;
delete this.loadingCount;
delete this.toLoadCount;
},
loadAll: function loadAll(elements) {
var _this = this;
var settings = this._settings;
var elementsToLoad = getElementsToLoad(elements, settings);
elementsToLoad.forEach(function (element) {
unobserve(element, _this);
load(element, settings, _this);
});
},
restoreAll: function restoreAll() {
var settings = this._settings;
queryElements(settings).forEach(function (element) {
restore(element, settings);
});
}
};
LazyLoad.load = function (element, customSettings) {
var settings = getExtendedSettings(customSettings);
load(element, settings);
};
LazyLoad.resetStatus = function (element) {
resetStatus(element);
}; // Automatic instances creation if required (useful for async script loading)
if (runningOnBrowser) {
autoInitialize(LazyLoad, window.lazyLoadOptions);
}
return LazyLoad;
})));

7
public/js/lazyload.min.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

@ -4,6 +4,7 @@
* https://www.x-lf.com/
*/
@import url("https://npm.akass.cn/bootstrap-icons@1.10.0/font/bootstrap-icons.css");
@tailwind base;
@tailwind components;
@tailwind utilities;

7491
resources/css/flowbite.css Normal file

File diff suppressed because it is too large Load Diff

7
resources/css/flowbite.min.css vendored Normal file

File diff suppressed because one or more lines are too long

View File

@ -6822,7 +6822,7 @@ function boxModelAdjustment( elem, dimension, box, isBorderBox, styles, computed
for ( ; i < 4; i += 2 ) {
// Both box models exclude margin
// Both box modules exclude margin
if ( box === "margin" ) {
delta += jQuery.css( elem, box + cssExpand[ i ], true, styles );
}

8
resources/js/jquery.min.js vendored Normal file

File diff suppressed because one or more lines are too long

868
resources/js/lazyload.js Normal file
View File

@ -0,0 +1,868 @@
/*
* Copyright © 2016 - 2023 筱锋xiao_lfeng. All Rights Reserved.
* 开发开源遵循 MIT 许可若需商用请联系开发者
* https://www.x-lf.com/
*/
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
typeof define === 'function' && define.amd ? define(factory) :
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.LazyLoad = factory());
}(this, (function () { 'use strict';
function _extends() {
_extends = Object.assign || function (target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) {
if (Object.prototype.hasOwnProperty.call(source, key)) {
target[key] = source[key];
}
}
}
return target;
};
return _extends.apply(this, arguments);
}
var runningOnBrowser = typeof window !== "undefined";
var isBot = runningOnBrowser && !("onscroll" in window) || typeof navigator !== "undefined" && /(gle|ing|ro)bot|crawl|spider/i.test(navigator.userAgent);
var supportsIntersectionObserver = runningOnBrowser && "IntersectionObserver" in window;
var supportsClassList = runningOnBrowser && "classList" in document.createElement("p");
var isHiDpi = runningOnBrowser && window.devicePixelRatio > 1;
var defaultSettings = {
elements_selector: ".lazy",
container: isBot || runningOnBrowser ? document : null,
threshold: 300,
thresholds: null,
data_src: "src",
data_srcset: "srcset",
data_sizes: "sizes",
data_bg: "bg",
data_bg_hidpi: "bg-hidpi",
data_bg_multi: "bg-multi",
data_bg_multi_hidpi: "bg-multi-hidpi",
data_bg_set: "bg-set",
data_poster: "poster",
class_applied: "applied",
class_loading: "loading",
class_loaded: "loaded",
class_error: "error",
class_entered: "entered",
class_exited: "exited",
unobserve_completed: true,
unobserve_entered: false,
cancel_on_exit: true,
callback_enter: null,
callback_exit: null,
callback_applied: null,
callback_loading: null,
callback_loaded: null,
callback_error: null,
callback_finish: null,
callback_cancel: null,
use_native: false,
restore_on_error: false
};
var getExtendedSettings = function getExtendedSettings(customSettings) {
return _extends({}, defaultSettings, customSettings);
};
/* Creates instance and notifies it through the window element */
var createInstance = function createInstance(classObj, options) {
var event;
var eventString = "LazyLoad::Initialized";
var instance = new classObj(options);
try {
// Works in modern browsers
event = new CustomEvent(eventString, {
detail: {
instance: instance
}
});
} catch (err) {
// Works in Internet Explorer (all versions)
event = document.createEvent("CustomEvent");
event.initCustomEvent(eventString, false, false, {
instance: instance
});
}
window.dispatchEvent(event);
};
/* Auto initialization of one or more instances of lazyload, depending on the
options passed in (plain object or an array) */
var autoInitialize = function autoInitialize(classObj, options) {
if (!options) {
return;
}
if (!options.length) {
// Plain object
createInstance(classObj, options);
} else {
// Array of objects
for (var i = 0, optionsItem; optionsItem = options[i]; i += 1) {
createInstance(classObj, optionsItem);
}
}
};
var SRC = "src";
var SRCSET = "srcset";
var SIZES = "sizes";
var POSTER = "poster";
var ORIGINALS = "llOriginalAttrs";
var DATA = "data";
var statusLoading = "loading";
var statusLoaded = "loaded";
var statusApplied = "applied";
var statusEntered = "entered";
var statusError = "error";
var statusNative = "native";
var dataPrefix = "data-";
var statusDataName = "ll-status";
var getData = function getData(element, attribute) {
return element.getAttribute(dataPrefix + attribute);
};
var setData = function setData(element, attribute, value) {
var attrName = dataPrefix + attribute;
if (value === null) {
element.removeAttribute(attrName);
return;
}
element.setAttribute(attrName, value);
};
var getStatus = function getStatus(element) {
return getData(element, statusDataName);
};
var setStatus = function setStatus(element, status) {
return setData(element, statusDataName, status);
};
var resetStatus = function resetStatus(element) {
return setStatus(element, null);
};
var hasEmptyStatus = function hasEmptyStatus(element) {
return getStatus(element) === null;
};
var hasStatusLoading = function hasStatusLoading(element) {
return getStatus(element) === statusLoading;
};
var hasStatusError = function hasStatusError(element) {
return getStatus(element) === statusError;
};
var hasStatusNative = function hasStatusNative(element) {
return getStatus(element) === statusNative;
};
var statusesAfterLoading = [statusLoading, statusLoaded, statusApplied, statusError];
var hadStartedLoading = function hadStartedLoading(element) {
return statusesAfterLoading.indexOf(getStatus(element)) >= 0;
};
var safeCallback = function safeCallback(callback, arg1, arg2, arg3) {
if (!callback) {
return;
}
if (arg3 !== undefined) {
callback(arg1, arg2, arg3);
return;
}
if (arg2 !== undefined) {
callback(arg1, arg2);
return;
}
callback(arg1);
};
var addClass = function addClass(element, className) {
if (supportsClassList) {
element.classList.add(className);
return;
}
element.className += (element.className ? " " : "") + className;
};
var removeClass = function removeClass(element, className) {
if (supportsClassList) {
element.classList.remove(className);
return;
}
element.className = element.className.replace(new RegExp("(^|\\s+)" + className + "(\\s+|$)"), " ").replace(/^\s+/, "").replace(/\s+$/, "");
};
var addTempImage = function addTempImage(element) {
element.llTempImage = document.createElement("IMG");
};
var deleteTempImage = function deleteTempImage(element) {
delete element.llTempImage;
};
var getTempImage = function getTempImage(element) {
return element.llTempImage;
};
var unobserve = function unobserve(element, instance) {
if (!instance) return;
var observer = instance._observer;
if (!observer) return;
observer.unobserve(element);
};
var resetObserver = function resetObserver(observer) {
observer.disconnect();
};
var unobserveEntered = function unobserveEntered(element, settings, instance) {
if (settings.unobserve_entered) unobserve(element, instance);
};
var updateLoadingCount = function updateLoadingCount(instance, delta) {
if (!instance) return;
instance.loadingCount += delta;
};
var decreaseToLoadCount = function decreaseToLoadCount(instance) {
if (!instance) return;
instance.toLoadCount -= 1;
};
var setToLoadCount = function setToLoadCount(instance, value) {
if (!instance) return;
instance.toLoadCount = value;
};
var isSomethingLoading = function isSomethingLoading(instance) {
return instance.loadingCount > 0;
};
var haveElementsToLoad = function haveElementsToLoad(instance) {
return instance.toLoadCount > 0;
};
var getSourceTags = function getSourceTags(parentTag) {
var sourceTags = [];
for (var i = 0, childTag; childTag = parentTag.children[i]; i += 1) {
if (childTag.tagName === "SOURCE") {
sourceTags.push(childTag);
}
}
return sourceTags;
};
var forEachPictureSource = function forEachPictureSource(element, fn) {
var parent = element.parentNode;
if (!parent || parent.tagName !== "PICTURE") {
return;
}
var sourceTags = getSourceTags(parent);
sourceTags.forEach(fn);
};
var forEachVideoSource = function forEachVideoSource(element, fn) {
var sourceTags = getSourceTags(element);
sourceTags.forEach(fn);
};
var attrsSrc = [SRC];
var attrsSrcPoster = [SRC, POSTER];
var attrsSrcSrcsetSizes = [SRC, SRCSET, SIZES];
var attrsData = [DATA];
var hasOriginalAttrs = function hasOriginalAttrs(element) {
return !!element[ORIGINALS];
};
var getOriginalAttrs = function getOriginalAttrs(element) {
return element[ORIGINALS];
};
var deleteOriginalAttrs = function deleteOriginalAttrs(element) {
return delete element[ORIGINALS];
}; // ## SAVE ##
var setOriginalsObject = function setOriginalsObject(element, attributes) {
if (hasOriginalAttrs(element)) {
return;
}
var originals = {};
attributes.forEach(function (attribute) {
originals[attribute] = element.getAttribute(attribute);
});
element[ORIGINALS] = originals;
};
var saveOriginalBackgroundStyle = function saveOriginalBackgroundStyle(element) {
if (hasOriginalAttrs(element)) {
return;
}
element[ORIGINALS] = {
backgroundImage: element.style.backgroundImage
};
}; // ## RESTORE ##
var setOrResetAttribute = function setOrResetAttribute(element, attrName, value) {
if (!value) {
element.removeAttribute(attrName);
return;
}
element.setAttribute(attrName, value);
};
var restoreOriginalAttrs = function restoreOriginalAttrs(element, attributes) {
if (!hasOriginalAttrs(element)) {
return;
}
var originals = getOriginalAttrs(element);
attributes.forEach(function (attribute) {
setOrResetAttribute(element, attribute, originals[attribute]);
});
};
var restoreOriginalBgImage = function restoreOriginalBgImage(element) {
if (!hasOriginalAttrs(element)) {
return;
}
var originals = getOriginalAttrs(element);
element.style.backgroundImage = originals.backgroundImage;
};
var manageApplied = function manageApplied(element, settings, instance) {
addClass(element, settings.class_applied);
setStatus(element, statusApplied); // Instance is not provided when loading is called from static class
if (!instance) return;
if (settings.unobserve_completed) {
// Unobserve now because we can't do it on load
unobserve(element, settings);
}
safeCallback(settings.callback_applied, element, instance);
};
var manageLoading = function manageLoading(element, settings, instance) {
addClass(element, settings.class_loading);
setStatus(element, statusLoading); // Instance is not provided when loading is called from static class
if (!instance) return;
updateLoadingCount(instance, +1);
safeCallback(settings.callback_loading, element, instance);
};
var setAttributeIfValue = function setAttributeIfValue(element, attrName, value) {
if (!value) {
return;
}
element.setAttribute(attrName, value);
};
var setImageAttributes = function setImageAttributes(element, settings) {
setAttributeIfValue(element, SIZES, getData(element, settings.data_sizes));
setAttributeIfValue(element, SRCSET, getData(element, settings.data_srcset));
setAttributeIfValue(element, SRC, getData(element, settings.data_src));
};
var setSourcesImg = function setSourcesImg(imgEl, settings) {
forEachPictureSource(imgEl, function (sourceTag) {
setOriginalsObject(sourceTag, attrsSrcSrcsetSizes);
setImageAttributes(sourceTag, settings);
});
setOriginalsObject(imgEl, attrsSrcSrcsetSizes);
setImageAttributes(imgEl, settings);
};
var setSourcesIframe = function setSourcesIframe(iframe, settings) {
setOriginalsObject(iframe, attrsSrc);
setAttributeIfValue(iframe, SRC, getData(iframe, settings.data_src));
};
var setSourcesVideo = function setSourcesVideo(videoEl, settings) {
forEachVideoSource(videoEl, function (sourceEl) {
setOriginalsObject(sourceEl, attrsSrc);
setAttributeIfValue(sourceEl, SRC, getData(sourceEl, settings.data_src));
});
setOriginalsObject(videoEl, attrsSrcPoster);
setAttributeIfValue(videoEl, POSTER, getData(videoEl, settings.data_poster));
setAttributeIfValue(videoEl, SRC, getData(videoEl, settings.data_src));
videoEl.load();
};
var setSourcesObject = function setSourcesObject(object, settings) {
setOriginalsObject(object, attrsData);
setAttributeIfValue(object, DATA, getData(object, settings.data_src));
};
var setBackground = function setBackground(element, settings, instance) {
var bg1xValue = getData(element, settings.data_bg);
var bgHiDpiValue = getData(element, settings.data_bg_hidpi);
var bgDataValue = isHiDpi && bgHiDpiValue ? bgHiDpiValue : bg1xValue;
if (!bgDataValue) return;
element.style.backgroundImage = "url(\"".concat(bgDataValue, "\")");
getTempImage(element).setAttribute(SRC, bgDataValue);
manageLoading(element, settings, instance);
}; // NOTE: THE TEMP IMAGE TRICK CANNOT BE DONE WITH data-multi-bg
// BECAUSE INSIDE ITS VALUES MUST BE WRAPPED WITH URL() AND ONE OF THEM
// COULD BE A GRADIENT BACKGROUND IMAGE
var setMultiBackground = function setMultiBackground(element, settings, instance) {
var bg1xValue = getData(element, settings.data_bg_multi);
var bgHiDpiValue = getData(element, settings.data_bg_multi_hidpi);
var bgDataValue = isHiDpi && bgHiDpiValue ? bgHiDpiValue : bg1xValue;
if (!bgDataValue) {
return;
}
element.style.backgroundImage = bgDataValue;
manageApplied(element, settings, instance);
};
var setImgsetBackground = function setImgsetBackground(element, settings, instance) {
var bgImgSetDataValue = getData(element, settings.data_bg_set);
if (!bgImgSetDataValue) {
return;
}
var imgSetValues = bgImgSetDataValue.split("|");
var bgImageValues = imgSetValues.map(function (value) {
return "image-set(".concat(value, ")");
});
element.style.backgroundImage = bgImageValues.join(); // Temporary fix for Chromeium with the -webkit- prefix
if (element.style.backgroundImage === '') {
bgImageValues = imgSetValues.map(function (value) {
return "-webkit-image-set(".concat(value, ")");
});
element.style.backgroundImage = bgImageValues.join();
}
manageApplied(element, settings, instance);
};
var setSourcesFunctions = {
IMG: setSourcesImg,
IFRAME: setSourcesIframe,
VIDEO: setSourcesVideo,
OBJECT: setSourcesObject
};
var setSourcesNative = function setSourcesNative(element, settings) {
var setSourcesFunction = setSourcesFunctions[element.tagName];
if (!setSourcesFunction) {
return;
}
setSourcesFunction(element, settings);
};
var setSources = function setSources(element, settings, instance) {
var setSourcesFunction = setSourcesFunctions[element.tagName];
if (!setSourcesFunction) {
return;
}
setSourcesFunction(element, settings);
manageLoading(element, settings, instance);
};
var elementsWithLoadEvent = ["IMG", "IFRAME", "VIDEO", "OBJECT"];
var hasLoadEvent = function hasLoadEvent(element) {
return elementsWithLoadEvent.indexOf(element.tagName) > -1;
};
var checkFinish = function checkFinish(settings, instance) {
if (instance && !isSomethingLoading(instance) && !haveElementsToLoad(instance)) {
safeCallback(settings.callback_finish, instance);
}
};
var addEventListener = function addEventListener(element, eventName, handler) {
element.addEventListener(eventName, handler);
element.llEvLisnrs[eventName] = handler;
};
var removeEventListener = function removeEventListener(element, eventName, handler) {
element.removeEventListener(eventName, handler);
};
var hasEventListeners = function hasEventListeners(element) {
return !!element.llEvLisnrs;
};
var addEventListeners = function addEventListeners(element, loadHandler, errorHandler) {
if (!hasEventListeners(element)) element.llEvLisnrs = {};
var loadEventName = element.tagName === "VIDEO" ? "loadeddata" : "load";
addEventListener(element, loadEventName, loadHandler);
addEventListener(element, "error", errorHandler);
};
var removeEventListeners = function removeEventListeners(element) {
if (!hasEventListeners(element)) {
return;
}
var eventListeners = element.llEvLisnrs;
for (var eventName in eventListeners) {
var handler = eventListeners[eventName];
removeEventListener(element, eventName, handler);
}
delete element.llEvLisnrs;
};
var doneHandler = function doneHandler(element, settings, instance) {
deleteTempImage(element);
updateLoadingCount(instance, -1);
decreaseToLoadCount(instance);
removeClass(element, settings.class_loading);
if (settings.unobserve_completed) {
unobserve(element, instance);
}
};
var loadHandler = function loadHandler(event, element, settings, instance) {
var goingNative = hasStatusNative(element);
doneHandler(element, settings, instance);
addClass(element, settings.class_loaded);
setStatus(element, statusLoaded);
safeCallback(settings.callback_loaded, element, instance);
if (!goingNative) checkFinish(settings, instance);
};
var errorHandler = function errorHandler(event, element, settings, instance) {
var goingNative = hasStatusNative(element);
doneHandler(element, settings, instance);
addClass(element, settings.class_error);
setStatus(element, statusError);
safeCallback(settings.callback_error, element, instance);
if (settings.restore_on_error) restoreOriginalAttrs(element, attrsSrcSrcsetSizes);
if (!goingNative) checkFinish(settings, instance);
};
var addOneShotEventListeners = function addOneShotEventListeners(element, settings, instance) {
var elementToListenTo = getTempImage(element) || element;
if (hasEventListeners(elementToListenTo)) {
// This happens when loading is retried twice
return;
}
var _loadHandler = function _loadHandler(event) {
loadHandler(event, element, settings, instance);
removeEventListeners(elementToListenTo);
};
var _errorHandler = function _errorHandler(event) {
errorHandler(event, element, settings, instance);
removeEventListeners(elementToListenTo);
};
addEventListeners(elementToListenTo, _loadHandler, _errorHandler);
};
var loadBackground = function loadBackground(element, settings, instance) {
addTempImage(element);
addOneShotEventListeners(element, settings, instance);
saveOriginalBackgroundStyle(element);
setBackground(element, settings, instance);
setMultiBackground(element, settings, instance);
setImgsetBackground(element, settings, instance);
};
var loadRegular = function loadRegular(element, settings, instance) {
addOneShotEventListeners(element, settings, instance);
setSources(element, settings, instance);
};
var load = function load(element, settings, instance) {
if (hasLoadEvent(element)) {
loadRegular(element, settings, instance);
} else {
loadBackground(element, settings, instance);
}
};
var loadNative = function loadNative(element, settings, instance) {
element.setAttribute("loading", "lazy");
addOneShotEventListeners(element, settings, instance);
setSourcesNative(element, settings);
setStatus(element, statusNative);
};
var removeImageAttributes = function removeImageAttributes(element) {
element.removeAttribute(SRC);
element.removeAttribute(SRCSET);
element.removeAttribute(SIZES);
};
var resetSourcesImg = function resetSourcesImg(element) {
forEachPictureSource(element, function (sourceTag) {
removeImageAttributes(sourceTag);
});
removeImageAttributes(element);
};
var restoreImg = function restoreImg(imgEl) {
forEachPictureSource(imgEl, function (sourceEl) {
restoreOriginalAttrs(sourceEl, attrsSrcSrcsetSizes);
});
restoreOriginalAttrs(imgEl, attrsSrcSrcsetSizes);
};
var restoreVideo = function restoreVideo(videoEl) {
forEachVideoSource(videoEl, function (sourceEl) {
restoreOriginalAttrs(sourceEl, attrsSrc);
});
restoreOriginalAttrs(videoEl, attrsSrcPoster);
videoEl.load();
};
var restoreIframe = function restoreIframe(iframeEl) {
restoreOriginalAttrs(iframeEl, attrsSrc);
};
var restoreObject = function restoreObject(objectEl) {
restoreOriginalAttrs(objectEl, attrsData);
};
var restoreFunctions = {
IMG: restoreImg,
IFRAME: restoreIframe,
VIDEO: restoreVideo,
OBJECT: restoreObject
};
var restoreAttributes = function restoreAttributes(element) {
var restoreFunction = restoreFunctions[element.tagName];
if (!restoreFunction) {
restoreOriginalBgImage(element);
return;
}
restoreFunction(element);
};
var resetClasses = function resetClasses(element, settings) {
if (hasEmptyStatus(element) || hasStatusNative(element)) {
return;
}
removeClass(element, settings.class_entered);
removeClass(element, settings.class_exited);
removeClass(element, settings.class_applied);
removeClass(element, settings.class_loading);
removeClass(element, settings.class_loaded);
removeClass(element, settings.class_error);
};
var restore = function restore(element, settings) {
restoreAttributes(element);
resetClasses(element, settings);
resetStatus(element);
deleteOriginalAttrs(element);
};
var cancelLoading = function cancelLoading(element, entry, settings, instance) {
if (!settings.cancel_on_exit) return;
if (!hasStatusLoading(element)) return;
if (element.tagName !== "IMG") return; //Works only on images
removeEventListeners(element);
resetSourcesImg(element);
restoreImg(element);
removeClass(element, settings.class_loading);
updateLoadingCount(instance, -1);
resetStatus(element);
safeCallback(settings.callback_cancel, element, entry, instance);
};
var onEnter = function onEnter(element, entry, settings, instance) {
var dontLoad = hadStartedLoading(element);
/* Save status
before setting it, to prevent loading it again. Fixes #526. */
setStatus(element, statusEntered);
addClass(element, settings.class_entered);
removeClass(element, settings.class_exited);
unobserveEntered(element, settings, instance);
safeCallback(settings.callback_enter, element, entry, instance);
if (dontLoad) return;
load(element, settings, instance);
};
var onExit = function onExit(element, entry, settings, instance) {
if (hasEmptyStatus(element)) return; //Ignore the first pass, at landing
addClass(element, settings.class_exited);
cancelLoading(element, entry, settings, instance);
safeCallback(settings.callback_exit, element, entry, instance);
};
var tagsWithNativeLazy = ["IMG", "IFRAME", "VIDEO"];
var shouldUseNative = function shouldUseNative(settings) {
return settings.use_native && "loading" in HTMLImageElement.prototype;
};
var loadAllNative = function loadAllNative(elements, settings, instance) {
elements.forEach(function (element) {
if (tagsWithNativeLazy.indexOf(element.tagName) === -1) {
return;
}
loadNative(element, settings, instance);
});
setToLoadCount(instance, 0);
};
var isIntersecting = function isIntersecting(entry) {
return entry.isIntersecting || entry.intersectionRatio > 0;
};
var getObserverSettings = function getObserverSettings(settings) {
return {
root: settings.container === document ? null : settings.container,
rootMargin: settings.thresholds || settings.threshold + "px"
};
};
var intersectionHandler = function intersectionHandler(entries, settings, instance) {
entries.forEach(function (entry) {
return isIntersecting(entry) ? onEnter(entry.target, entry, settings, instance) : onExit(entry.target, entry, settings, instance);
});
};
var observeElements = function observeElements(observer, elements) {
elements.forEach(function (element) {
observer.observe(element);
});
};
var updateObserver = function updateObserver(observer, elementsToObserve) {
resetObserver(observer);
observeElements(observer, elementsToObserve);
};
var setObserver = function setObserver(settings, instance) {
if (!supportsIntersectionObserver || shouldUseNative(settings)) {
return;
}
instance._observer = new IntersectionObserver(function (entries) {
intersectionHandler(entries, settings, instance);
}, getObserverSettings(settings));
};
var toArray = function toArray(nodeSet) {
return Array.prototype.slice.call(nodeSet);
};
var queryElements = function queryElements(settings) {
return settings.container.querySelectorAll(settings.elements_selector);
};
var excludeManagedElements = function excludeManagedElements(elements) {
return toArray(elements).filter(hasEmptyStatus);
};
var hasError = function hasError(element) {
return hasStatusError(element);
};
var filterErrorElements = function filterErrorElements(elements) {
return toArray(elements).filter(hasError);
};
var getElementsToLoad = function getElementsToLoad(elements, settings) {
return excludeManagedElements(elements || queryElements(settings));
};
var retryLazyLoad = function retryLazyLoad(settings, instance) {
var errorElements = filterErrorElements(queryElements(settings));
errorElements.forEach(function (element) {
removeClass(element, settings.class_error);
resetStatus(element);
});
instance.update();
};
var setOnlineCheck = function setOnlineCheck(settings, instance) {
if (!runningOnBrowser) {
return;
}
instance._onlineHandler = function () {
retryLazyLoad(settings, instance);
};
window.addEventListener("online", instance._onlineHandler);
};
var resetOnlineCheck = function resetOnlineCheck(instance) {
if (!runningOnBrowser) {
return;
}
window.removeEventListener("online", instance._onlineHandler);
};
var LazyLoad = function LazyLoad(customSettings, elements) {
var settings = getExtendedSettings(customSettings);
this._settings = settings;
this.loadingCount = 0;
setObserver(settings, this);
setOnlineCheck(settings, this);
this.update(elements);
};
LazyLoad.prototype = {
update: function update(givenNodeset) {
var settings = this._settings;
var elementsToLoad = getElementsToLoad(givenNodeset, settings);
setToLoadCount(this, elementsToLoad.length);
if (isBot || !supportsIntersectionObserver) {
this.loadAll(elementsToLoad);
return;
}
if (shouldUseNative(settings)) {
loadAllNative(elementsToLoad, settings, this);
return;
}
updateObserver(this._observer, elementsToLoad);
},
destroy: function destroy() {
// Observer
if (this._observer) {
this._observer.disconnect();
} // Clean handlers
resetOnlineCheck(this); // Clean custom attributes on elements
queryElements(this._settings).forEach(function (element) {
deleteOriginalAttrs(element);
}); // Delete all internal props
delete this._observer;
delete this._settings;
delete this._onlineHandler;
delete this.loadingCount;
delete this.toLoadCount;
},
loadAll: function loadAll(elements) {
var _this = this;
var settings = this._settings;
var elementsToLoad = getElementsToLoad(elements, settings);
elementsToLoad.forEach(function (element) {
unobserve(element, _this);
load(element, settings, _this);
});
},
restoreAll: function restoreAll() {
var settings = this._settings;
queryElements(settings).forEach(function (element) {
restore(element, settings);
});
}
};
LazyLoad.load = function (element, customSettings) {
var settings = getExtendedSettings(customSettings);
load(element, settings);
};
LazyLoad.resetStatus = function (element) {
resetStatus(element);
}; // Automatic instances creation if required (useful for async script loading)
if (runningOnBrowser) {
autoInitialize(LazyLoad, window.lazyLoadOptions);
}
return LazyLoad;
})));

7
resources/js/lazyload.min.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,42 @@
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" href="{{ asset('css/app.css') }}">
<link rel="stylesheet" href="{{ asset('css/flowbite.css') }}">
@include('modules.head')
{!! $webHeader !!}
</head>
<body>
<div class="bg-white">
@include('modules.navbar')
<div class="relative isolate px-6 lg:px-8">
<div class="absolute inset-x-0 -top-40 -z-10 transform-gpu overflow-hidden blur-3xl sm:-top-80"
aria-hidden="true">
<div
class="relative left-[calc(50%-11rem)] aspect-[1155/678] w-[36.125rem] -translate-x-1/2 rotate-[30deg] bg-gradient-to-tr from-[#ff80b5] to-[#9089fc] opacity-30 sm:left-[calc(50%-30rem)] sm:w-[72.1875rem]"
style="clip-path: polygon(74.1% 44.1%, 100% 61.6%, 97.5% 26.9%, 85.5% 0.1%, 80.7% 2%, 72.5% 32.5%, 60.2% 62.4%, 52.4% 68.1%, 47.5% 58.3%, 45.2% 34.5%, 27.5% 76.7%, 0.1% 64.9%, 17.9% 100%, 27.6% 76.8%, 76.1% 97.7%, 74.1% 44.1%)"></div>
</div>
<div class="mx-auto my-10 max-w-4xl py-8 sm:py-16 lg:py-16">
<div class="w-full p-4 bg-white border border-gray-200 rounded-lg shadow-lg sm:p-8 dark:bg-gray-800 dark:border-gray-700">
{!! $userAbout !!}
</div>
</div>
<div
class="absolute inset-x-0 top-[calc(100%-13rem)] -z-10 transform-gpu overflow-hidden blur-3xl sm:top-[calc(100%-30rem)]"
aria-hidden="true">
<div
class="relative left-[calc(50%+3rem)] aspect-[1155/678] w-[36.125rem] -translate-x-1/2 bg-gradient-to-tr from-[#ff80b5] to-[#9089fc] opacity-30 sm:left-[calc(50%+36rem)] sm:w-[72.1875rem]"
style="clip-path: polygon(74.1% 44.1%, 100% 61.6%, 97.5% 26.9%, 85.5% 0.1%, 80.7% 2%, 72.5% 32.5%, 60.2% 62.4%, 52.4% 68.1%, 47.5% 58.3%, 45.2% 34.5%, 27.5% 76.7%, 0.1% 64.9%, 17.9% 100%, 27.6% 76.8%, 76.1% 97.7%, 74.1% 44.1%)"></div>
</div>
@include('modules.footer')
</div>
</div>
</body>
<script src="{{ asset('js/app.js') }}"></script>
<script src="{{ asset('js/jquery.js') }}"></script>
{!! $webFooter !!}
</html>

View File

@ -6,7 +6,9 @@
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" href="{{ asset('css/app.css') }}">
<title>Document</title>
<link rel="stylesheet" href="{{ asset('css/flowbite.css') }}">
@include('modules.head')
{!! $webHeader !!}
</head>
<body class="h-full">
<div class="flex min-h-full flex-col justify-center px-6 py-12 lg:px-8">
@ -70,7 +72,7 @@ function user_change() {
dataType: "json",
success: function (returnData) {
if (returnData.output === "Success") {
window.location.href = '{{ route('console.dashboard') }}'
window.location.href = '{{ route('home') }}'
} else {
window.alert("错误!")
}
@ -78,4 +80,5 @@ function user_change() {
});
}
</script>
{!! $webFooter !!}
</html>

View File

@ -6,7 +6,9 @@
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" href="{{ asset('css/app.css') }}">
<title>Document</title>
<link rel="stylesheet" href="{{ asset('css/flowbite.css') }}">
@include('modules.head')
{!! $webHeader !!}
</head>
<body class="h-full">
<div class="flex min-h-full flex-col justify-center px-6 py-12 lg:px-8">
@ -93,4 +95,5 @@ function user_change() {
});
}
</script>
{!! $webFooter !!}
</html>

View File

@ -6,7 +6,9 @@
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" href="{{ asset('css/app.css') }}">
<title>Document</title>
<link rel="stylesheet" href="{{ asset('css/flowbite.css') }}">
@include('modules.head')
{!! $webHeader !!}
</head>
<body>
@ -20,195 +22,62 @@ class="inline-flex items-center p-2 mt-2 ml-3 text-sm text-gray-500 rounded-lg s
</svg>
</button>
<aside id="sidebar-multi-level-sidebar"
class="fixed top-0 left-0 z-40 w-64 h-screen transition-transform -translate-x-full sm:translate-x-0"
aria-label="Sidebar">
<div class="h-full px-3 py-4 overflow-y-auto bg-gray-50 dark:bg-gray-800">
<ul class="space-y-2 font-medium">
<li>
<a href="#"
class="flex items-center p-2 text-gray-900 rounded-lg dark:text-white hover:bg-gray-100 dark:hover:bg-gray-700">
<svg aria-hidden="true"
class="w-6 h-6 text-gray-500 transition duration-75 dark:text-gray-400 group-hover:text-gray-900 dark:group-hover:text-white"
fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
<path d="M2 10a8 8 0 018-8v8h8a8 8 0 11-16 0z"></path>
<path d="M12 2.252A8.014 8.014 0 0117.748 8H12V2.252z"></path>
</svg>
<span class="ml-3">Dashboard</span>
</a>
</li>
<li>
<button type="button"
class="flex items-center w-full p-2 text-gray-900 transition duration-75 rounded-lg group hover:bg-gray-100 dark:text-white dark:hover:bg-gray-700"
aria-controls="dropdown-example" data-collapse-toggle="dropdown-example">
<svg aria-hidden="true"
class="flex-shrink-0 w-6 h-6 text-gray-500 transition duration-75 group-hover:text-gray-900 dark:text-gray-400 dark:group-hover:text-white"
fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd"
d="M10 2a4 4 0 00-4 4v1H5a1 1 0 00-.994.89l-1 9A1 1 0 004 18h12a1 1 0 00.994-1.11l-1-9A1 1 0 0015 7h-1V6a4 4 0 00-4-4zm2 5V6a2 2 0 10-4 0v1h4zm-6 3a1 1 0 112 0 1 1 0 01-2 0zm7-1a1 1 0 100 2 1 1 0 000-2z"
clip-rule="evenodd"></path>
</svg>
<span class="flex-1 ml-3 text-left whitespace-nowrap" sidebar-toggle-item>E-commerce</span>
<svg sidebar-toggle-item class="w-6 h-6" fill="currentColor" viewBox="0 0 20 20"
xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd"
d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z"
clip-rule="evenodd"></path>
</svg>
</button>
<ul id="dropdown-example" class="hidden py-2 space-y-2">
<li>
<a href="#"
class="flex items-center w-full p-2 text-gray-900 transition duration-75 rounded-lg pl-11 group hover:bg-gray-100 dark:text-white dark:hover:bg-gray-700">Products</a>
</li>
<li>
<a href="#"
class="flex items-center w-full p-2 text-gray-900 transition duration-75 rounded-lg pl-11 group hover:bg-gray-100 dark:text-white dark:hover:bg-gray-700">Billing</a>
</li>
<li>
<a href="#"
class="flex items-center w-full p-2 text-gray-900 transition duration-75 rounded-lg pl-11 group hover:bg-gray-100 dark:text-white dark:hover:bg-gray-700">Invoice</a>
</li>
</ul>
</li>
<li>
<a href="#"
class="flex items-center p-2 text-gray-900 rounded-lg dark:text-white hover:bg-gray-100 dark:hover:bg-gray-700">
<svg aria-hidden="true"
class="flex-shrink-0 w-6 h-6 text-gray-500 transition duration-75 dark:text-gray-400 group-hover:text-gray-900 dark:group-hover:text-white"
fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
<path
d="M5 3a2 2 0 00-2 2v2a2 2 0 002 2h2a2 2 0 002-2V5a2 2 0 00-2-2H5zM5 11a2 2 0 00-2 2v2a2 2 0 002 2h2a2 2 0 002-2v-2a2 2 0 00-2-2H5zM11 5a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2h-2a2 2 0 01-2-2V5zM11 13a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2h-2a2 2 0 01-2-2v-2z"></path>
</svg>
<span class="flex-1 ml-3 whitespace-nowrap">Kanban</span>
<span
class="inline-flex items-center justify-center px-2 ml-3 text-sm font-medium text-gray-800 bg-gray-200 rounded-full dark:bg-gray-700 dark:text-gray-300">Pro</span>
</a>
</li>
<li>
<a href="#"
class="flex items-center p-2 text-gray-900 rounded-lg dark:text-white hover:bg-gray-100 dark:hover:bg-gray-700">
<svg aria-hidden="true"
class="flex-shrink-0 w-6 h-6 text-gray-500 transition duration-75 dark:text-gray-400 group-hover:text-gray-900 dark:group-hover:text-white"
fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
<path
d="M8.707 7.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l2-2a1 1 0 00-1.414-1.414L11 7.586V3a1 1 0 10-2 0v4.586l-.293-.293z"></path>
<path
d="M3 5a2 2 0 012-2h1a1 1 0 010 2H5v7h2l1 2h4l1-2h2V5h-1a1 1 0 110-2h1a2 2 0 012 2v10a2 2 0 01-2 2H5a2 2 0 01-2-2V5z"></path>
</svg>
<span class="flex-1 ml-3 whitespace-nowrap">Inbox</span>
<span
class="inline-flex items-center justify-center w-3 h-3 p-3 ml-3 text-sm font-medium text-blue-800 bg-blue-100 rounded-full dark:bg-blue-900 dark:text-blue-300">3</span>
</a>
</li>
<li>
<a href="#"
class="flex items-center p-2 text-gray-900 rounded-lg dark:text-white hover:bg-gray-100 dark:hover:bg-gray-700">
<svg aria-hidden="true"
class="flex-shrink-0 w-6 h-6 text-gray-500 transition duration-75 dark:text-gray-400 group-hover:text-gray-900 dark:group-hover:text-white"
fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" d="M10 9a3 3 0 100-6 3 3 0 000 6zm-7 9a7 7 0 1114 0H3z"
clip-rule="evenodd"></path>
</svg>
<span class="flex-1 ml-3 whitespace-nowrap">Users</span>
</a>
</li>
<li>
<a href="#"
class="flex items-center p-2 text-gray-900 rounded-lg dark:text-white hover:bg-gray-100 dark:hover:bg-gray-700">
<svg aria-hidden="true"
class="flex-shrink-0 w-6 h-6 text-gray-500 transition duration-75 dark:text-gray-400 group-hover:text-gray-900 dark:group-hover:text-white"
fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd"
d="M10 2a4 4 0 00-4 4v1H5a1 1 0 00-.994.89l-1 9A1 1 0 004 18h12a1 1 0 00.994-1.11l-1-9A1 1 0 0015 7h-1V6a4 4 0 00-4-4zm2 5V6a2 2 0 10-4 0v1h4zm-6 3a1 1 0 112 0 1 1 0 01-2 0zm7-1a1 1 0 100 2 1 1 0 000-2z"
clip-rule="evenodd"></path>
</svg>
<span class="flex-1 ml-3 whitespace-nowrap">Products</span>
</a>
</li>
<li>
<a href="#"
class="flex items-center p-2 text-gray-900 rounded-lg dark:text-white hover:bg-gray-100 dark:hover:bg-gray-700">
<svg aria-hidden="true"
class="flex-shrink-0 w-6 h-6 text-gray-500 transition duration-75 dark:text-gray-400 group-hover:text-gray-900 dark:group-hover:text-white"
fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd"
d="M3 3a1 1 0 00-1 1v12a1 1 0 102 0V4a1 1 0 00-1-1zm10.293 9.293a1 1 0 001.414 1.414l3-3a1 1 0 000-1.414l-3-3a1 1 0 10-1.414 1.414L14.586 9H7a1 1 0 100 2h7.586l-1.293 1.293z"
clip-rule="evenodd"></path>
</svg>
<span class="flex-1 ml-3 whitespace-nowrap">Sign In</span>
</a>
</li>
<li>
<a href="#"
class="flex items-center p-2 text-gray-900 rounded-lg dark:text-white hover:bg-gray-100 dark:hover:bg-gray-700">
<svg aria-hidden="true"
class="flex-shrink-0 w-6 h-6 text-gray-500 transition duration-75 dark:text-gray-400 group-hover:text-gray-900 dark:group-hover:text-white"
fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd"
d="M5 4a3 3 0 00-3 3v6a3 3 0 003 3h10a3 3 0 003-3V7a3 3 0 00-3-3H5zm-1 9v-1h5v2H5a1 1 0 01-1-1zm7 1h4a1 1 0 001-1v-1h-5v2zm0-4h5V8h-5v2zM9 8H4v2h5V8z"
clip-rule="evenodd"></path>
</svg>
<span class="flex-1 ml-3 whitespace-nowrap">Sign Up</span>
</a>
</li>
</ul>
</div>
</aside>
@include('console.modules.aside')
<div class="p-4 sm:ml-64">
<div class="p-4 border-2 border-gray-200 border-dashed rounded-lg dark:border-gray-700">
<div class="p-4 border-gray-200 border-dashed rounded-lg dark:border-gray-700">
@include('console.modules.personal')
<div class="grid grid-cols-1 gap-4 mb-4">
<div class="text-2xl text-gray-400 dark:text-gray-500"><i class="bi bi-link-45deg"></i> 友链概况</div>
</div>
<div class="grid grid-cols-3 gap-4 mb-4">
<div class="flex items-center justify-center h-24 rounded bg-gray-50 dark:bg-gray-800">
<p class="text-2xl text-gray-400 dark:text-gray-500">+</p>
<div class="flex items-center justify-center h-24 rounded bg-gray-50 dark:bg-gray-800 shadow">
<p class="text-2xl text-gray-400 dark:text-gray-500"><i class="bi bi-person-check"></i> 当前友链 <b class="text-black dark:text-white">{{ $blogFriendsTotal }}</b> </p>
</div>
<div class="flex items-center justify-center h-24 rounded bg-gray-50 dark:bg-gray-800">
<p class="text-2xl text-gray-400 dark:text-gray-500">+</p>
<div class="flex items-center justify-center h-24 rounded bg-gray-50 dark:bg-gray-800 shadow">
<p class="text-2xl text-gray-400 dark:text-gray-500"><i class="bi bi-person-check-fill"></i> 待审友链 <b class="text-black dark:text-white">{{ $blogFriendsCheck }}</b> </p>
</div>
<div class="flex items-center justify-center h-24 rounded bg-gray-50 dark:bg-gray-800">
<p class="text-2xl text-gray-400 dark:text-gray-500">+</p>
<div class="flex items-center justify-center h-24 rounded bg-gray-50 dark:bg-gray-800 shadow">
<p class="text-2xl text-gray-400 dark:text-gray-500"><i class="bi bi-person-hearts"></i> 超级友链 <b class="text-black dark:text-white">{{ $blogFriendsBest }}</b> </p>
</div>
</div>
<div class="flex items-center justify-center h-48 mb-4 rounded bg-gray-50 dark:bg-gray-800">
<p class="text-2xl text-gray-400 dark:text-gray-500">+</p>
<div class="grid grid-cols-1 gap-4 mb-4">
<div class="text-2xl text-gray-400 dark:text-gray-500"><i class="bi bi-link-45deg"></i> 赞助概况</div>
</div>
<div class="grid grid-cols-2 gap-4 mb-4">
<div class="flex items-center justify-center rounded bg-gray-50 h-28 dark:bg-gray-800">
<div class="flex items-center justify-center rounded bg-gray-50 h-28 dark:bg-gray-800 shadow">
<p class="text-2xl text-gray-400 dark:text-gray-500">+</p>
</div>
<div class="flex items-center justify-center rounded bg-gray-50 h-28 dark:bg-gray-800">
<div class="flex items-center justify-center rounded bg-gray-50 h-28 dark:bg-gray-800 shadow">
<p class="text-2xl text-gray-400 dark:text-gray-500">+</p>
</div>
<div class="flex items-center justify-center rounded bg-gray-50 h-28 dark:bg-gray-800">
<div class="flex items-center justify-center rounded bg-gray-50 h-28 dark:bg-gray-800 shadow">
<p class="text-2xl text-gray-400 dark:text-gray-500">+</p>
</div>
<div class="flex items-center justify-center rounded bg-gray-50 h-28 dark:bg-gray-800">
<div class="flex items-center justify-center rounded bg-gray-50 h-28 dark:bg-gray-800 shadow">
<p class="text-2xl text-gray-400 dark:text-gray-500">+</p>
</div>
</div>
<div class="flex items-center justify-center h-48 mb-4 rounded bg-gray-50 dark:bg-gray-800">
<div class="flex items-center justify-center h-48 mb-4 rounded bg-gray-50 dark:bg-gray-800 shadow">
<p class="text-2xl text-gray-400 dark:text-gray-500">+</p>
</div>
<div class="grid grid-cols-2 gap-4">
<div class="flex items-center justify-center rounded bg-gray-50 h-28 dark:bg-gray-800">
<div class="flex items-center justify-center rounded bg-gray-50 h-28 dark:bg-gray-800 shadow">
<p class="text-2xl text-gray-400 dark:text-gray-500">+</p>
</div>
<div class="flex items-center justify-center rounded bg-gray-50 h-28 dark:bg-gray-800">
<div class="flex items-center justify-center rounded bg-gray-50 h-28 dark:bg-gray-800 shadow">
<p class="text-2xl text-gray-400 dark:text-gray-500">+</p>
</div>
<div class="flex items-center justify-center rounded bg-gray-50 h-28 dark:bg-gray-800">
<div class="flex items-center justify-center rounded bg-gray-50 h-28 dark:bg-gray-800 shadow">
<p class="text-2xl text-gray-400 dark:text-gray-500">+</p>
</div>
<div class="flex items-center justify-center rounded bg-gray-50 h-28 dark:bg-gray-800">
<div class="flex items-center justify-center rounded bg-gray-50 h-28 dark:bg-gray-800 shadow">
<p class="text-2xl text-gray-400 dark:text-gray-500">+</p>
</div>
</div>
</div>
</div>
</body>
<script src="{{ asset('js/app.js') }}"></script>
<script src="{{ asset('js/flowbite.js') }}"></script>
<script src="{{ asset('js/jquery.js') }}"></script>
</html>

View File

@ -0,0 +1,84 @@
<aside id="sidebar-multi-level-sidebar"
class="fixed top-0 left-0 z-40 w-64 h-screen transition-transform -translate-x-full sm:translate-x-0"
aria-label="Sidebar">
<div class="h-full px-3 py-4 overflow-y-auto bg-gray-50 dark:bg-gray-800">
<ul class="space-y-2 font-medium">
<li>
<a href="{{ route('home') }}"
class="flex items-center p-2 text-gray-900 rounded-lg dark:text-white hover:bg-gray-100 dark:hover:bg-gray-700">
<i class="bi bi-house"></i>
<span class="ml-3">返回主页</span>
</a>
</li>
<li>
<a href="#"
class="flex items-center p-2 text-gray-900 rounded-lg dark:text-white hover:bg-gray-100 dark:hover:bg-gray-700">
<i class="bi bi-layout-sidebar-inset"></i>
<span class="ml-3">概况</span>
</a>
</li>
<li>
<button type="button"
class="flex items-center w-full p-2 text-gray-900 transition duration-75 rounded-lg group hover:bg-gray-100 dark:text-white dark:hover:bg-gray-700"
aria-controls="dropdown-example" data-collapse-toggle="dropdown-example">
<i class="bi bi-person-check"></i>
<span class="flex-1 ml-3 text-left whitespace-nowrap" sidebar-toggle-item>友链管理</span>
<i class="bi bi-caret-down-fill"></i>
</button>
<ul id="dropdown-example" class="hidden py-2 space-y-2">
<li>
<a href="#"
class="flex items-center w-full p-2 text-gray-900 transition duration-75 rounded-lg pl-11 group hover:bg-gray-100 dark:text-white dark:hover:bg-gray-700">Products</a>
</li>
<li>
<a href="#"
class="flex items-center w-full p-2 text-gray-900 transition duration-75 rounded-lg pl-11 group hover:bg-gray-100 dark:text-white dark:hover:bg-gray-700">Billing</a>
</li>
<li>
<a href="#"
class="flex items-center w-full p-2 text-gray-900 transition duration-75 rounded-lg pl-11 group hover:bg-gray-100 dark:text-white dark:hover:bg-gray-700">Invoice</a>
</li>
</ul>
</li>
<li>
<a href="#"
class="flex items-center p-2 text-gray-900 rounded-lg dark:text-white hover:bg-gray-100 dark:hover:bg-gray-700">
<i class="bi bi-piggy-bank"></i>
<span class="flex-1 ml-3 whitespace-nowrap">赞助管理</span>
<span
class="inline-flex items-center justify-center px-2 ml-3 text-sm font-medium text-gray-800 bg-gray-200 rounded-full dark:bg-gray-700 dark:text-gray-300">Pro</span>
</a>
</li>
<li>
<a href="#"
class="flex items-center p-2 text-gray-900 rounded-lg dark:text-white hover:bg-gray-100 dark:hover:bg-gray-700">
<svg aria-hidden="true"
class="flex-shrink-0 w-6 h-6 text-gray-500 transition duration-75 dark:text-gray-400 group-hover:text-gray-900 dark:group-hover:text-white"
fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
<path
d="M8.707 7.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l2-2a1 1 0 00-1.414-1.414L11 7.586V3a1 1 0 10-2 0v4.586l-.293-.293z"></path>
<path
d="M3 5a2 2 0 012-2h1a1 1 0 010 2H5v7h2l1 2h4l1-2h2V5h-1a1 1 0 110-2h1a2 2 0 012 2v10a2 2 0 01-2 2H5a2 2 0 01-2-2V5z"></path>
</svg>
<span class="flex-1 ml-3 whitespace-nowrap">Inbox</span>
<span
class="inline-flex items-center justify-center w-3 h-3 p-3 ml-3 text-sm font-medium text-blue-800 bg-blue-100 rounded-full dark:bg-blue-900 dark:text-blue-300">3</span>
</a>
</li>
<li>
<a href="#"
class="flex items-center p-2 text-gray-900 rounded-lg dark:text-white hover:bg-gray-100 dark:hover:bg-gray-700">
<i class="bi bi-card-list"></i>
<span class="flex-1 ml-3 whitespace-nowrap">主页设置</span>
</a>
</li>
<li>
<a href="#"
class="flex items-center p-2 text-gray-900 rounded-lg dark:text-white hover:bg-gray-100 dark:hover:bg-gray-700">
<i class="bi bi-gear-fill"></i>
<span class="flex-1 ml-3 whitespace-nowrap">系统设置</span>
</a>
</li>
</ul>
</div>
</aside>

View File

@ -0,0 +1,42 @@
<div class="grid grid-cols-2 gap-4 mb-4 rounded bg-gray-50 dark:bg-gray-800 shadow">
<div class="flex items-center justify-start h-16">
<div class="grid grid-cols-12">
<a class="flex ps-5" href="">
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" fill="currentColor" class="bi bi-bell" viewBox="0 0 16 16">
<path d="M8 16a2 2 0 0 0 2-2H6a2 2 0 0 0 2 2zM8 1.918l-.797.161A4.002 4.002 0 0 0 4 6c0 .628-.134 2.197-.459 3.742-.16.767-.376 1.566-.663 2.258h10.244c-.287-.692-.502-1.49-.663-2.258C12.134 8.197 12 6.628 12 6a4.002 4.002 0 0 0-3.203-3.92L8 1.917zM14.22 12c.223.447.481.801.78 1H1c.299-.199.557-.553.78-1C2.68 10.2 3 6.88 3 6c0-2.42 1.72-4.44 4.005-4.901a1 1 0 1 1 1.99 0A5.002 5.002 0 0 1 13 6c0 .88.32 4.2 1.22 6z"/>
</svg>
</a>
<a class="flex ps-3" href="">
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" fill="currentColor" class="bi bi-bell" viewBox="0 0 16 16">
<path d="M8 16a2 2 0 0 0 2-2H6a2 2 0 0 0 2 2zM8 1.918l-.797.161A4.002 4.002 0 0 0 4 6c0 .628-.134 2.197-.459 3.742-.16.767-.376 1.566-.663 2.258h10.244c-.287-.692-.502-1.49-.663-2.258C12.134 8.197 12 6.628 12 6a4.002 4.002 0 0 0-3.203-3.92L8 1.917zM14.22 12c.223.447.481.801.78 1H1c.299-.199.557-.553.78-1C2.68 10.2 3 6.88 3 6c0-2.42 1.72-4.44 4.005-4.901a1 1 0 1 1 1.99 0A5.002 5.002 0 0 1 13 6c0 .88.32 4.2 1.22 6z"/>
</svg>
</a>
</div>
</div>
<div class="flex items-center justify-end h-16">
<div class="flex items-center space-x-4 m-5">
<div class="font-medium dark:text-white">
<div class="text-right">{{ $userName }}</div>
<div class="text-sm text-gray-500 dark:text-gray-400">{{ $userEmail }}</div>
</div>
<img id="avatarButton" type="button" data-dropdown-toggle="userDropdown" data-dropdown-placement="bottom-start" class="w-10 h-10 rounded-full cursor-pointer" src="{{ $userIcon }}" alt="">
<!-- Dropdown menu -->
<div id="userDropdown" class="z-10 hidden bg-white divide-y divide-gray-100 rounded-lg shadow w-44 dark:bg-gray-700 dark:divide-gray-600">
<ul class="py-2 text-sm text-gray-700 dark:text-gray-200" aria-labelledby="avatarButton">
<li>
<a href="#" class="block px-4 py-2 hover:bg-gray-100 dark:hover:bg-gray-600 dark:hover:text-white">
<i class="bi bi-person-rolodex"></i>
<span class="flex-1 ml-3 whitespace-nowrap">个人设置</span>
</a>
</li>
</ul>
<div class="py-1">
<a href="{{ route('logout') }}" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 dark:hover:bg-gray-600 dark:text-gray-200 dark:hover:text-white">
<i class="bi bi-box-arrow-left"></i>
<span class="flex-1 ml-3 whitespace-nowrap">登出</span>
</a>
</div>
</div>
</div>
</div>
</div>

View File

@ -0,0 +1,110 @@
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" href="{{ asset('css/app.css') }}">
<link rel="stylesheet" href="{{ asset('css/flowbite.css') }}">
@include('modules.head')
{!! $webHeader !!}
</head>
<body>
<div class="bg-white">
@include('modules.navbar')
<div class="relative isolate px-6 lg:px-8">
<div class="absolute inset-x-0 -top-40 -z-10 transform-gpu overflow-hidden blur-3xl sm:-top-80"
aria-hidden="true">
<div
class="relative left-[calc(50%-11rem)] aspect-[1155/678] w-[36.125rem] -translate-x-1/2 rotate-[30deg] bg-gradient-to-tr from-[#ff80b5] to-[#9089fc] opacity-30 sm:left-[calc(50%-30rem)] sm:w-[72.1875rem]"
style="clip-path: polygon(74.1% 44.1%, 100% 61.6%, 97.5% 26.9%, 85.5% 0.1%, 80.7% 2%, 72.5% 32.5%, 60.2% 62.4%, 52.4% 68.1%, 47.5% 58.3%, 45.2% 34.5%, 27.5% 76.7%, 0.1% 64.9%, 17.9% 100%, 27.6% 76.8%, 76.1% 97.7%, 74.1% 44.1%)"></div>
</div>
@foreach($blogSort as $valueSort)
<div class="mx-auto mt-28 mb-3 max-w-4xl grid grid-cols-1 px-2">
<div class="text-2xl text-bold">{!! $valueSort->title !!}</div>
@if(!empty($valueSort->description))<div class="text-gray-500">{{ $valueSort->description }}</div> @endif
</div>
<div class="mx-auto max-w-4xl mb-3 grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 xl:grid-cols-4">
@foreach($blogLink as $valueLink)
@if($valueLink->blogLocation == $valueSort->id)
<a href="{{ $valueLink->blogUrl }}" target="_blank">
<div
class="flex p-2 hover:bg-gray-100 bg-white border border-grey-200 rounded-lg shadow-lg sm:p-4 dark:bg-gray-800 dark:border-gray-700 grid-cols-2 m-1">
<img id="Lazy"
class="w-16 h-16 p-1 rounded-full ring-2 ring-gray-300 dark:ring-gray-500 me-2 sm:me-4"
src="{{ asset('images/avatar.png') }}" data-src="{{ $valueLink->blogIcon }}"
alt="Bordered avatar">
<div class="grid grid-cols-1">
<p class="text-xl font-bold">{{ $valueLink->blogName }}</p>
<p class="text-sm text-gray-500 truncate">{{ $valueLink->blogDescription }}</p>
</div>
</div>
</a>
@endif
@endforeach
</div>
@endforeach
<div class="mb-20"></div>
<div data-dial-init class="fixed right-6 bottom-6 group">
<div id="speed-dial-menu-square" class="flex flex-col items-center hidden mb-4 space-y-2">
<a href="{{ route('function.make-friend') }}" type="button" data-tooltip-target="tooltip-print" data-tooltip-placement="left" class="flex justify-center items-center w-[52px] h-[52px] text-gray-500 hover:text-gray-900 bg-red-100 rounded-lg border border-gray-200 dark:border-gray-600 shadow-sm dark:hover:text-white dark:text-gray-400 hover:bg-red-200 dark:bg-gray-700 dark:hover:bg-gray-600 focus:ring-4 focus:ring-gray-300 focus:outline-none dark:focus:ring-gray-400">
<i class="bi bi-trash3"></i>
<span class="sr-only">删除友链</span>
</a>
<div id="tooltip-print" role="tooltip" class="absolute z-10 invisible inline-block w-auto px-3 py-2 text-sm font-medium text-white transition-opacity duration-300 bg-gray-900 rounded-lg shadow-sm opacity-0 tooltip dark:bg-gray-700">
删除
<div class="tooltip-arrow" data-popper-arrow></div>
</div>
<a href="{{ route('function.make-friend') }}" type="button" data-tooltip-target="tooltip-download" data-tooltip-placement="left" class="flex justify-center items-center w-[52px] h-[52px] text-gray-500 hover:text-gray-900 bg-white rounded-lg border border-gray-200 dark:border-gray-600 shadow-sm dark:hover:text-white dark:text-gray-400 hover:bg-gray-100 dark:bg-gray-700 dark:hover:bg-gray-600 focus:ring-4 focus:ring-gray-300 focus:outline-none dark:focus:ring-gray-400">
<i class="bi bi-pencil"></i>
<span class="sr-only">修改友链</span>
</a>
<div id="tooltip-download" role="tooltip" class="absolute z-10 invisible inline-block w-auto px-3 py-2 text-sm font-medium text-white transition-opacity duration-300 bg-gray-900 rounded-lg shadow-sm opacity-0 tooltip dark:bg-gray-700">
修改
<div class="tooltip-arrow" data-popper-arrow></div>
</div>
<a href="{{ route('function.make-friend') }}" type="button" data-tooltip-target="tooltip-copy" data-tooltip-placement="left" class="flex justify-center items-center w-[52px] h-[52px] text-gray-500 hover:text-gray-900 bg-green-100 rounded-lg border border-gray-200 dark:border-gray-600 dark:hover:text-white shadow-sm dark:text-gray-400 hover:bg-green-200 dark:bg-gray-700 dark:hover:bg-gray-600 focus:ring-4 focus:ring-gray-300 focus:outline-none dark:focus:ring-gray-400">
<i class="bi bi-person-add"></i>
<span class="sr-only">申请友链</span>
</a>
<div id="tooltip-copy" role="tooltip" class="absolute z-10 invisible inline-block w-auto px-3 py-2 text-sm font-medium text-white transition-opacity duration-300 bg-gray-900 rounded-lg shadow-sm opacity-0 tooltip dark:bg-gray-700">
申请
<div class="tooltip-arrow" data-popper-arrow></div>
</div>
</div>
<button type="button" data-dial-toggle="speed-dial-menu-square" aria-controls="speed-dial-menu-square" aria-expanded="false" class="flex items-center justify-center text-white bg-blue-700 rounded-lg w-14 h-14 hover:bg-blue-800 dark:bg-blue-600 dark:hover:bg-blue-700 focus:ring-4 focus:ring-blue-300 focus:outline-none dark:focus:ring-blue-800">
<svg aria-hidden="true" class="w-8 h-8 transition-transform group-hover:rotate-45" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6v6m0 0v6m0-6h6m-6 0H6"></path></svg>
<span class="sr-only">Open actions menu</span>
</button>
</div>
<div
class="absolute inset-x-0 top-[calc(100%-13rem)] -z-10 transform-gpu overflow-hidden blur-3xl sm:top-[calc(100%-30rem)]"
aria-hidden="true">
<div
class="relative left-[calc(50%+3rem)] aspect-[1155/678] w-[36.125rem] -translate-x-1/2 bg-gradient-to-tr from-[#ff80b5] to-[#9089fc] opacity-30 sm:left-[calc(50%+36rem)] sm:w-[72.1875rem]"
style="clip-path: polygon(74.1% 44.1%, 100% 61.6%, 97.5% 26.9%, 85.5% 0.1%, 80.7% 2%, 72.5% 32.5%, 60.2% 62.4%, 52.4% 68.1%, 47.5% 58.3%, 45.2% 34.5%, 27.5% 76.7%, 0.1% 64.9%, 17.9% 100%, 27.6% 76.8%, 76.1% 97.7%, 74.1% 44.1%)"></div>
</div>
@include('modules.footer')
</div>
</div>
</body>
<script src="{{ asset('js/app.js') }}"></script>
<script async src="{{ asset('js/jquery.js') }}"></script>
<script async src="{{ asset('js/lazyload.js') }}"></script>
<script type="text/javascript">
document.addEventListener('DOMContentLoaded', function () {
const lazyLoadInstance = new LazyLoad({
elements_selector: '#Lazy', // 指定要延迟加载的元素选择器
loaded: function (element) {
element.classList.add('fade');
},
callback_error: function (element) {
element.src = '{{ asset('images/avatar.png') }}'; // 图像加载失败时替换为占位图像
}
});
});
</script>
{!! $webFooter !!}
</html>

View File

@ -0,0 +1,208 @@
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" href="{{ asset('css/app.css') }}">
<link rel="stylesheet" href="{{ asset('css/flowbite.css') }}">
@include('modules.head')
{!! $webHeader !!}
</head>
<body>
<div class="bg-white">
@include('modules.navbar')
<div class="relative isolate px-6 lg:px-8">
<div class="absolute inset-x-0 -top-40 -z-10 transform-gpu overflow-hidden blur-3xl sm:-top-80"
aria-hidden="true">
<div
class="relative left-[calc(50%-11rem)] aspect-[1155/678] w-[36.125rem] -translate-x-1/2 rotate-[30deg] bg-gradient-to-tr from-[#ff80b5] to-[#9089fc] opacity-30 sm:left-[calc(50%-30rem)] sm:w-[72.1875rem]"
style="clip-path: polygon(74.1% 44.1%, 100% 61.6%, 97.5% 26.9%, 85.5% 0.1%, 80.7% 2%, 72.5% 32.5%, 60.2% 62.4%, 52.4% 68.1%, 47.5% 58.3%, 45.2% 34.5%, 27.5% 76.7%, 0.1% 64.9%, 17.9% 100%, 27.6% 76.8%, 76.1% 97.7%, 74.1% 44.1%)"></div>
</div>
<div class="mx-auto my-10 max-w-4xl py-8 sm:py-16 lg:py-16">
<a href="{{ route('function.link') }}" type="button" class="text-white mb-5 bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm w-full sm:w-auto px-3 py-2 text-center dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800"><i class="bi bi-box-arrow-left me-1"></i> 返回友链</a>
<div class="w-full p-4 bg-white border border-gray-200 rounded-lg shadow-lg sm:p-8 dark:bg-gray-800 dark:border-gray-700">
<form>
<div class="grid gap-6 mb-6 md:grid-cols-2">
<div>
<label for="userEmail" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">博主邮箱 <span class="text-red-700">*</span></label>
<div class="relative">
<div class="absolute inset-y-0 left-0 flex items-center pl-3 pointer-events-none">
<svg aria-hidden="true" class="w-5 h-5 text-gray-500 dark:text-gray-400" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path d="M2.003 5.884L10 9.882l7.997-3.998A2 2 0 0016 4H4a2 2 0 00-1.997 1.884z"></path><path d="M18 8.118l-8 4-8-4V14a2 2 0 002 2h12a2 2 0 002-2V8.118z"></path></svg>
</div>
<input type="email" name="userEmail" id="userEmail" placeholder="gm@x-lf.cn" class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full pl-10 p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" required>
</div>
</div>
<div>
<label for="userServerHost" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">所用主机服务商<span data-tooltip-target="userServerHost-Tooltip" class="bi bi-info-circle mx-1 text-blue-700"></span> <span class="text-red-700">*</span></label>
<div id="userServerHost-Tooltip" role="tooltip" class="absolute z-10 invisible inline-block px-3 py-2 text-sm font-medium text-white transition-opacity duration-300 bg-gray-900 rounded-lg shadow-sm opacity-0 tooltip dark:bg-gray-700">
这个我只是想确定能否贵站确认长久开下去(如果不是大型服务商填写地址嗷),如果是“跑路”云会麻烦网友访问~
<div class="tooltip-arrow" data-popper-arrow></div>
</div>
<div class="relative">
<div class="absolute inset-y-0 left-0 flex items-center pl-3 pointer-events-none">
<i class="bi bi-hdd-network"></i>
</div>
<input type="text" name="userServerHost" id="userServerHost" placeholder="阿里云" class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full pl-10 p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" required>
</div>
</div>
</div>
<hr class="w-48 h-1 mx-auto my-4 bg-gray-100 border-0 rounded md:my-6 dark:bg-gray-700">
<div class="grid gap-6 mb-6 md:grid-cols-2">
<div>
<label for="userBlog" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">博客名称 <span class="text-red-700">*</span></label>
<div class="relative">
<div class="absolute inset-y-0 left-0 flex items-center pl-3 pointer-events-none">
<i class="bi bi-person"></i>
</div>
<input type="text" name="userBlog" id="userBlog" placeholder="凌中的锋雨" class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full pl-10 p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" required>
</div>
</div>
<div>
<label for="userUrl" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">博客地址<span data-tooltip-target="userUrl-Tooltip" class="bi bi-info-circle mx-1 text-blue-700"></span> <span class="text-red-700">*</span></label>
<div id="userUrl-Tooltip" role="tooltip" class="absolute z-10 invisible inline-block px-3 py-2 text-sm font-medium text-white transition-opacity duration-300 bg-gray-900 rounded-lg shadow-sm opacity-0 tooltip dark:bg-gray-700">
携带”http(s)://
<div class="tooltip-arrow" data-popper-arrow></div>
</div>
<div class="relative">
<div class="absolute inset-y-0 left-0 flex items-center pl-3 pointer-events-none">
<i class="bi bi-link-45deg"></i>
</div>
<input type="text" name="userUrl" id="userUrl" placeholder="https://www.x-lf.com/" class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full pl-10 p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" required>
</div>
</div>
</div>
<div class="mb-6">
<label for="userDescription" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">博客介绍<span data-tooltip-target="userDescription-Tooltip" class="bi bi-info-circle mx-1 text-blue-700"></span> <span class="text-red-700">*</span></label>
<div id="userDescription-Tooltip" role="tooltip" class="absolute z-10 invisible inline-block px-3 py-2 text-sm font-medium text-white transition-opacity duration-300 bg-gray-900 rounded-lg shadow-sm opacity-0 tooltip dark:bg-gray-700">
博客的一句话表述(例如):“不为如何,只为在茫茫人海中有自己的一片天空”
<div class="tooltip-arrow" data-popper-arrow></div>
</div>
<div class="relative">
<div class="absolute inset-y-0 left-0 flex items-center pl-3 pointer-events-none">
<i class="bi bi-chat-left-text"></i>
</div>
<input type="text" name="userDescription" id="userDescription" placeholder="不为如何,只为在茫茫人海中有自己的一片天空~" class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full pl-10 p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" required>
</div>
</div>
<div class="mb-6">
<label for="userIcon" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">博客图片<span data-tooltip-target="userIcon-Tooltip" class="bi bi-info-circle mx-1 text-blue-700"></span> <span class="text-red-700">*</span></label>
<div id="userIcon-Tooltip" role="tooltip" class="absolute z-10 invisible inline-block px-3 py-2 text-sm font-medium text-white transition-opacity duration-300 bg-gray-900 rounded-lg shadow-sm opacity-0 tooltip dark:bg-gray-700">
携带”http(s)://
<div class="tooltip-arrow" data-popper-arrow></div>
</div>
<div class="relative">
<div class="absolute inset-y-0 left-0 flex items-center pl-3 pointer-events-none">
<i class="bi bi-image"></i>
</div>
<input type="text" name="userIcon" id="userIcon" placeholder="https://api.x-lf.cn/avatar/?uid=1" class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full pl-10 p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" required>
</div>
</div>
<div class="mb-6 grid grid-cols-1 md:grid-cols-3 items-end">
<div class="col-span-1 mb-3 md:mb-0">
<label class="relative inline-flex">
<input type="checkbox" id="checkRssJudge" value="1" class="sr-only peer">
<div class="w-11 h-6 bg-gray-200 peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-blue-300 dark:peer-focus:ring-blue-800 rounded-full peer dark:bg-gray-700 peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all dark:border-gray-600 peer-checked:bg-blue-600"></div>
<span class="ml-3 text-sm font-medium text-gray-900 dark:text-gray-300">我的博客拥有 RSS 地址</span>
</label>
</div>
<div class="col-span-2">
<label for="userRss" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">RSS 地址 <a target="_blank" href="https://blog.x-lf.com/atom.xml"><span data-tooltip-target="userRss-Tooltip" class="bi bi-info-circle mx-1 text-blue-700"></span></a></label>
<div id="userRss-Tooltip" role="tooltip" class="absolute z-10 invisible inline-block px-3 py-2 text-sm font-medium text-white transition-opacity duration-300 bg-gray-900 rounded-lg shadow-sm opacity-0 tooltip dark:bg-gray-700">
例如可点击https://blog.x-lf.com/atom.xml<br/>
(注:下框内容需要选择后才可填写)
<div class="tooltip-arrow" data-popper-arrow></div>
</div>
<div class="relative">
<div class="absolute inset-y-0 left-0 flex items-center pl-3 pointer-events-none">
<i class="bi bi-link-45deg"></i>
</div>
<input type="text" name="userRss" id="userRss" placeholder="https://blog.x-lf.com/atom.xml" class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full pl-10 p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" disabled>
</div>
</div>
</div>
<hr class="w-48 h-1 mx-auto my-4 bg-gray-100 border-0 rounded md:my-6 dark:bg-gray-700">
<div class="grid gap-6 mb-6 md:grid-cols-2">
<div>
<label for="userLocation" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">期望板块 <span class="text-red-700">*</span></label>
<select id="userLocation" class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500">
<option selected>请选择一个板块</option>
<option value="US">United States</option>
<option value="CA">Canada</option>
<option value="FR">France</option>
<option value="DE">Germany</option>
</select>
</div>
<div>
<label for="userSelColor" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">期望颜色<span id="DemoCheck" data-tooltip-target="userSelColor-Tooltip" class="bi bi-info-circle mx-1 text-blue-700"></span> <span class="text-red-700">*</span></label>
<div id="userSelColor-Tooltip" role="tooltip" class="absolute z-10 invisible inline-block px-3 py-2 text-sm font-medium text-white transition-opacity duration-300 bg-gray-900 rounded-lg shadow-sm opacity-0 tooltip dark:bg-gray-700">
<div
class="flex p-2 hover:bg-gray-100 bg-white border-4 border-blue-500 rounded-lg shadow-lg sm:p-4 dark:bg-gray-800 dark:border-gray-700 grid-cols-2 m-1">
<img id="userDemo"
class="w-16 h-16 p-1 rounded-full ring-2 ring-gray-300 dark:ring-gray-500 me-2 sm:me-4"
src="" alt="Bordered avatar">
<div class="grid grid-cols-1">
<p id="userDemoName" class="text-xl text-black font-bold"></p>
<p id="userDemoDescription" class="text-sm text-gray-500 truncate"></p>
</div>
</div>
<div class="tooltip-arrow" data-popper-arrow></div>
</div>
<select id="userSelColor" class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500">
<option selected>请选择一个颜色</option>
<option value="US">United States</option>
<option value="CA">Canada</option>
<option value="FR">France</option>
<option value="DE">Germany</option>
</select>
</div>
</div>
<hr class="h-px my-8 bg-gray-200 border-0 dark:bg-gray-700">
<div class="flex items-start mb-6">
<div class="flex items-center h-5">
<input id="remember" type="checkbox" value="" class="w-4 h-4 border border-gray-300 rounded bg-gray-50 focus:ring-3 focus:ring-blue-300 dark:bg-gray-700 dark:border-gray-600 dark:focus:ring-blue-600 dark:ring-offset-gray-800" required>
</div>
<label for="remember" class="ml-2 text-sm font-medium text-gray-900 dark:text-gray-300">我满足 <a href="#" class="text-blue-600 hover:underline dark:text-blue-500">《凌中的锋雨-友链申请要求》</a></label>
</div>
<button type="submit" class="text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm w-full sm:w-auto px-5 py-2.5 text-center dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800"><i class="bi bi-send me-1"></i>发送申请</button>
</form>
</div>
</div>
<div class="mb-20"></div>
<div
class="absolute inset-x-0 top-[calc(100%-13rem)] -z-10 transform-gpu overflow-hidden blur-3xl sm:top-[calc(100%-30rem)]"
aria-hidden="true">
<div
class="relative left-[calc(50%+3rem)] aspect-[1155/678] w-[36.125rem] -translate-x-1/2 bg-gradient-to-tr from-[#ff80b5] to-[#9089fc] opacity-30 sm:left-[calc(50%+36rem)] sm:w-[72.1875rem]"
style="clip-path: polygon(74.1% 44.1%, 100% 61.6%, 97.5% 26.9%, 85.5% 0.1%, 80.7% 2%, 72.5% 32.5%, 60.2% 62.4%, 52.4% 68.1%, 47.5% 58.3%, 45.2% 34.5%, 27.5% 76.7%, 0.1% 64.9%, 17.9% 100%, 27.6% 76.8%, 76.1% 97.7%, 74.1% 44.1%)"></div>
</div>
@include('modules.footer')
</div>
</div>
</body>
<script src="{{ asset('js/app.js') }}"></script>
<script src="{{ asset('js/jquery.js') }}"></script>
<script type="text/javascript">
$(document).ready(function () {
let userIcon = $('#userIcon').val();
$('#checkRssJudge').change(function () {
if ($(this).is(':checked')) {
$('#userRss').prop('disabled',false);
} else {
$('#userRss').prop('disabled',true);
}
});
$('#DemoCheck').mouseenter(function () {
if (userIcon === '') userIcon = 'https://api.x-lf.cn/avatar/?uid=1';
else userIcon = $('#userIcon').val();
$('#userDemo').prop('src',userIcon);
$('#userDemoName').text($('#userBlog').val());
$('#userDemoDescription').text($('#userDescription').val());
});
})
</script>
{!! $webFooter !!}
</html>

View File

@ -0,0 +1 @@
<?php

View File

@ -0,0 +1 @@
<?php

View File

@ -0,0 +1,69 @@
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" href="{{ asset('css/app.css') }}">
<link rel="stylesheet" href="{{ asset('css/flowbite.css') }}">
@include('modules.head')
{!! $webHeader !!}
</head>
<body style="overflow: hidden;height: 100vh">
<div class="bg-white">
@include('modules.navbar')
<div class="relative isolate px-6 lg:px-8">
<div class="absolute inset-x-0 -top-40 -z-10 transform-gpu overflow-hidden blur-3xl sm:-top-80"
aria-hidden="true">
<div
class="relative left-[calc(50%-11rem)] aspect-[1155/678] w-[36.125rem] -translate-x-1/2 rotate-[30deg] bg-gradient-to-tr from-[#ff80b5] to-[#9089fc] opacity-30 sm:left-[calc(50%-30rem)] sm:w-[72.1875rem]"
style="clip-path: polygon(74.1% 44.1%, 100% 61.6%, 97.5% 26.9%, 85.5% 0.1%, 80.7% 2%, 72.5% 32.5%, 60.2% 62.4%, 52.4% 68.1%, 47.5% 58.3%, 45.2% 34.5%, 27.5% 76.7%, 0.1% 64.9%, 17.9% 100%, 27.6% 76.8%, 76.1% 97.7%, 74.1% 44.1%)"></div>
</div>
<div class="mx-auto max-w-2xl py-32 sm:py-38 lg:py-40 xl:py-48">
<div class="text-center">
<h1 class="text-6xl font-bold tracking-tight text-gray-900 sm:text-6xl"> {{ $webTitle }} </h1>
<p class="mt-6 text-lg leading-8 text-gray-600">{{ $webSubTitleDescription }}</p>
<div class="mt-10 flex items-center justify-center gap-x-6">
<a href="{{ $sqlBlog }}"
class="rounded-full bg-purple-700 px-3.5 py-2.5 text-sm font-semibold text-white shadow-sm hover:bg-purple-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600">
<i class="bi bi-door-open"></i>
<span class="flex-1 ml-1 whitespace-nowrap">去我的博客</span>
</a>
<a href="{{ route('about') }}" class="text-sm font-semibold leading-6 text-gray-900">
<span class="flex-1 whitespace-nowrap">了解我</span>
<i class="bi bi-arrow-right"></i>
</a>
</div>
</div>
</div>
<div
class="absolute inset-x-0 top-[calc(100%-13rem)] -z-10 transform-gpu overflow-hidden blur-3xl sm:top-[calc(100%-30rem)]"
aria-hidden="true">
<div
class="relative left-[calc(50%+3rem)] aspect-[1155/678] w-[36.125rem] -translate-x-1/2 bg-gradient-to-tr from-[#ff80b5] to-[#9089fc] opacity-30 sm:left-[calc(50%+36rem)] sm:w-[72.1875rem]"
style="clip-path: polygon(74.1% 44.1%, 100% 61.6%, 97.5% 26.9%, 85.5% 0.1%, 80.7% 2%, 72.5% 32.5%, 60.2% 62.4%, 52.4% 68.1%, 47.5% 58.3%, 45.2% 34.5%, 27.5% 76.7%, 0.1% 64.9%, 17.9% 100%, 27.6% 76.8%, 76.1% 97.7%, 74.1% 44.1%)"></div>
</div>
</div>
</div>
<footer class="fixed bottom-0 left-0 z-20 w-full p-4 md:flex md:items-end md:justify-between md:p-6">
@if(empty($sqlIcp) && empty($sqlGongan))
<div class="flex text-sm text-gray-500 dark:text-gray-400"></div>
<div class="flex text-sm text-gray-500 dark:text-gray-400">
<span class="flex justify-start"><i class="bi bi-c-circle"></i> @if(empty(!$sqlCopyRightYear)) {{ $sqlCopyRightYear }}-{{ date('Y') }} @else {{ date('Y') }} @endif {{ $sqlAuthor }}. All Rights Reserved.</span>
</div>
@else
<div class="flex text-sm text-gray-500 dark:text-gray-400">
<span class="flex justify-start"><i class="bi bi-c-circle pe-2"></i> @if(empty(!$sqlCopyRightYear)) {{ $sqlCopyRightYear }}-{{ date('Y') }} @else {{ date('Y') }} @endif {{ $sqlAuthor }}. All Rights Reserved.</span>
</div>
<div class="grid grid-cols-1 text-sm text-gray-500 dark:text-gray-400">
@if(!empty($sqlIcp))<a href="https://beian.miit.gov.cn/"><span class="flex justify-end @if(!empty($sqlGongan))mb-1 @endif"><i class="bi bi-balloon pe-2"></i> {{ $sqlIcp }}</span></a> @endif
@if(!empty($sqlGongan))<a href="https://www.beian.gov.cn/portal/registerSystemInfo?recordcode={{ $GonganCode }}"><span class="flex justify-end @if(!empty($sqlIcp))mt-1 @endif"><i class="bi bi-balloon-heart pe-2"></i> {{ $sqlGongan }}</span></a> @endif
</div>
@endif
</footer>
</body>
<script src="{{ asset('js/app.js') }}"></script>
<script src="{{ asset('js/jquery.js') }}"></script>
{!! $webFooter !!}
</html>

View File

@ -0,0 +1,10 @@
<footer>
<div class="w-full mx-auto max-w-screen-xl p-4 md:flex md:items-center justify-center">
<div class="text-sm text-gray-500 text-center dark:text-gray-400 gird grid-cols-1">
<span class="flex text-sm justify-center text-gray-500 dark:text-gray-400"><i class="bi bi-c-circle pe-2"></i> @if(empty(!$sqlCopyRightYear)) {{ $sqlCopyRightYear }}-{{ date('Y') }} @else {{ date('Y') }} @endif {{ $sqlAuthor }}. All Rights Reserved.</span>
@if(!empty($sqlGongang) || !empty($sqlIcp))<hr class="my-3"> @endif
@if(!empty($sqlIcp))<a href="https://beian.miit.gov.cn/"><span class="flex text-sm justify-center text-gray-500 dark:text-gray-400 @if(!empty($sqlGongan))mb-1 @endif"><i class="bi bi-balloon pe-2"></i> {{ $sqlIcp }}</span></a> @endif
@if(!empty($sqlGongan))<a href="https://www.beian.gov.cn/portal/registerSystemInfo?recordcode={{ $GonganCode }}"><span class="flex text-sm justify-center text-gray-500 dark:text-gray-400 @if(!empty($sqlIcp))mt-1 @endif"><i class="bi bi-balloon-heart pe-2"></i> {{ $sqlGongan }}</span></a> @endif
</div>
</div>
</footer>

View File

@ -0,0 +1,10 @@
<title>{{ $webTitle }} - {{ $webSubTitle }}</title>
<meta name="description" content="{{ $webDescription }}">
<meta name="keywords" content="{{ $webKeyword }}">
<meta name="author" content="{{ $sqlAuthor }}">
<meta name="copyright" content="{{ $sqlAuthor }}">
<link rel="shortcut icon" href="{{ $webIcon }}" type="image/x-icon">
<link rel="icon" sizes="any" href="{{ $webIcon }}" type="image/x-icon">
<!-- 适配Twitter卡片 -->
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="{{ $webIcon }}">

View File

@ -0,0 +1,123 @@
<header class="absolute inset-x-0 top-0 z-50">
<nav class="flex items-center justify-between p-6 lg:px-8" aria-label="Global">
<div class="flex lg:flex-1">
<a href="#" class="-m-1.5 p-1.5">
<span class="sr-only">Your Company</span>
<img class="h-8 w-auto rounded-full" src="{{ asset('images/logo.jpg') }}" alt="">
</a>
</div>
<div class="flex lg:hidden">
<button type="button" onclick="openMenuIn()"
class="-m-2.5 inline-flex items-center justify-center rounded-md p-2.5 text-gray-700">
<span class="sr-only">Open main menu</span>
<svg class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"
aria-hidden="true">
<path stroke-linecap="round" stroke-linejoin="round"
d="M3.75 6.75h16.5M3.75 12h16.5m-16.5 5.25h16.5"/>
</svg>
</button>
</div>
<div class="hidden lg:flex lg:gap-x-12">
<a href="{{ route('home') }}" class="text-sm font-semibold leading-6 text-gray-900">
<i class="bi bi-house"></i>
<span class="flex-1 ml-1 whitespace-nowrap">首页</span>
</a>
<a href="{{ route('function.link') }}" class="text-sm font-semibold leading-6 text-gray-900">
<i class="bi bi-link-45deg"></i>
<span class="flex-1 ml-1 whitespace-nowrap">友链</span>
</a>
<a href="{{ route('function.sponsor') }}" class="text-sm font-semibold leading-6 text-gray-900">
<i class="bi bi-piggy-bank"></i>
<span class="flex-1 ml-1 whitespace-nowrap">赞助</span>
</a>
<a href="{{ route('function.music') }}" class="text-sm font-semibold leading-6 text-gray-900">
<i class="bi bi-music-note"></i>
<span class="flex-1 ml-1 whitespace-nowrap">音乐</span>
</a>
</div>
<div class="hidden lg:flex lg:flex-1 lg:justify-end">
@if(Auth::guest())
<a href="{{ route('login') }}" class="text-sm font-semibold leading-6 text-gray-900">
<span class="flex-1 me-1 whitespace-nowrap">登录</span>
<i class="bi bi-box-arrow-in-right"></i>
</a>
@else
<div class="flex items-center space-x-4">
<div class="font-medium dark:text-white">
<div class="text-right">{{ $userName }}</div>
</div>
<img id="avatarButton" type="button" data-dropdown-toggle="userDropdown" data-dropdown-placement="bottom-start" class="w-8 h-8 rounded-full cursor-pointer" src="{{ $userIcon }}" alt="">
<!-- Dropdown menu -->
<div id="userDropdown" class="z-10 hidden bg-white divide-y divide-gray-100 rounded-lg shadow w-44 dark:bg-gray-700 dark:divide-gray-600">
<ul class="py-2 text-sm text-gray-700 dark:text-gray-200" aria-labelledby="avatarButton">
<li>
<a href="{{ route('console.dashboard') }}" class="block px-4 py-2 hover:bg-gray-100 dark:hover:bg-gray-600 dark:hover:text-white">
<i class="bi bi-person-rolodex"></i>
<span class="flex-1 ml-3 whitespace-nowrap">管理员</span>
</a>
<a href="#" class="block px-4 py-2 hover:bg-gray-100 dark:hover:bg-gray-600 dark:hover:text-white">
<i class="bi bi-person-rolodex"></i>
<span class="flex-1 ml-3 whitespace-nowrap">个人设置</span>
</a>
</li>
</ul>
<div class="py-1">
<a href="{{ route('logout') }}" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 dark:hover:bg-gray-600 dark:text-gray-200 dark:hover:text-white">
<i class="bi bi-box-arrow-left"></i>
<span class="flex-1 ml-3 whitespace-nowrap">登出</span>
</a>
</div>
</div>
</div>
@endif
</div>
</nav>
<!-- Mobile menu, show/hide based on menu open state. -->
<div class="lg:hidden" role="dialog" aria-modal="true">
<!-- Background backdrop, show/hide based on slide-over state. -->
<div id="phoneMenu" aria-labelledby="phoneMenuButton"
class="fixed hidden inset-y-0 right-0 z-50 w-full overflow-y-auto bg-white px-6 py-6 sm:max-w-sm sm:ring-1 sm:ring-gray-900/10">
<div class="flex items-center justify-between">
<a href="#" class="-m-1.5 p-1.5">
<span class="sr-only">Your Company</span>
<img class="h-8 w-auto" src="https://tailwindui.com/img/logos/mark.svg?color=indigo&shade=600"
alt="">
</a>
<button type="button" class="-m-2.5 rounded-md p-2.5 text-gray-700" onclick="openMenuOut()">
<span class="sr-only">Close menu</span>
<svg class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"
aria-hidden="true">
<path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12"/>
</svg>
</button>
</div>
<div class="mt-6 flow-root">
<div class="-my-6 divide-y divide-gray-500/10">
<div class="space-y-2 py-6">
<a href="#"
class="-mx-3 block rounded-lg px-3 py-2 text-base font-semibold leading-7 text-gray-900 hover:bg-gray-50">Product</a>
<a href="#"
class="-mx-3 block rounded-lg px-3 py-2 text-base font-semibold leading-7 text-gray-900 hover:bg-gray-50">Features</a>
<a href="#"
class="-mx-3 block rounded-lg px-3 py-2 text-base font-semibold leading-7 text-gray-900 hover:bg-gray-50">Marketplace</a>
<a href="#"
class="-mx-3 block rounded-lg px-3 py-2 text-base font-semibold leading-7 text-gray-900 hover:bg-gray-50">Company</a>
</div>
<div class="py-6">
<a href="#"
class="-mx-3 block rounded-lg px-3 py-2.5 text-base font-semibold leading-7 text-gray-900 hover:bg-gray-50">Log
in</a>
</div>
</div>
</div>
</div>
</div>
</header>
<script type="text/javascript">
function openMenuIn() {
$('#phoneMenu').fadeIn('fast');
}
function openMenuOut() {
$('#phoneMenu').fadeOut('fast');
}
</script>

View File

@ -1,132 +0,0 @@
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Laravel</title>
<!-- Fonts -->
<link href="https://fonts.googleapis.com/css2?family=Nunito:wght@400;600;700&display=swap" rel="stylesheet">
<!-- Styles -->
<style>
/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */html{line-height:1.15;-webkit-text-size-adjust:100%}body{margin:0}a{background-color:transparent}[hidden]{display:none}html{font-family:system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;line-height:1.5}*,:after,:before{box-sizing:border-box;border:0 solid #e2e8f0}a{color:inherit;text-decoration:inherit}svg,video{display:block;vertical-align:middle}video{max-width:100%;height:auto}.bg-white{--bg-opacity:1;background-color:#fff;background-color:rgba(255,255,255,var(--bg-opacity))}.bg-gray-100{--bg-opacity:1;background-color:#f7fafc;background-color:rgba(247,250,252,var(--bg-opacity))}.border-gray-200{--border-opacity:1;border-color:#edf2f7;border-color:rgba(237,242,247,var(--border-opacity))}.border-t{border-top-width:1px}.flex{display:flex}.grid{display:grid}.hidden{display:none}.items-center{align-items:center}.justify-center{justify-content:center}.font-semibold{font-weight:600}.h-5{height:1.25rem}.h-8{height:2rem}.h-16{height:4rem}.text-sm{font-size:.875rem}.text-lg{font-size:1.125rem}.leading-7{line-height:1.75rem}.mx-auto{margin-left:auto;margin-right:auto}.ml-1{margin-left:.25rem}.mt-2{margin-top:.5rem}.mr-2{margin-right:.5rem}.ml-2{margin-left:.5rem}.mt-4{margin-top:1rem}.ml-4{margin-left:1rem}.mt-8{margin-top:2rem}.ml-12{margin-left:3rem}.-mt-px{margin-top:-1px}.max-w-6xl{max-width:72rem}.min-h-screen{min-height:100vh}.overflow-hidden{overflow:hidden}.p-6{padding:1.5rem}.py-4{padding-top:1rem;padding-bottom:1rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.pt-8{padding-top:2rem}.fixed{position:fixed}.relative{position:relative}.top-0{top:0}.right-0{right:0}.shadow{box-shadow:0 1px 3px 0 rgba(0,0,0,.1),0 1px 2px 0 rgba(0,0,0,.06)}.text-center{text-align:center}.text-gray-200{--text-opacity:1;color:#edf2f7;color:rgba(237,242,247,var(--text-opacity))}.text-gray-300{--text-opacity:1;color:#e2e8f0;color:rgba(226,232,240,var(--text-opacity))}.text-gray-400{--text-opacity:1;color:#cbd5e0;color:rgba(203,213,224,var(--text-opacity))}.text-gray-500{--text-opacity:1;color:#a0aec0;color:rgba(160,174,192,var(--text-opacity))}.text-gray-600{--text-opacity:1;color:#718096;color:rgba(113,128,150,var(--text-opacity))}.text-gray-700{--text-opacity:1;color:#4a5568;color:rgba(74,85,104,var(--text-opacity))}.text-gray-900{--text-opacity:1;color:#1a202c;color:rgba(26,32,44,var(--text-opacity))}.underline{text-decoration:underline}.antialiased{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.w-5{width:1.25rem}.w-8{width:2rem}.w-auto{width:auto}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}@media (min-width:640px){.sm\:rounded-lg{border-radius:.5rem}.sm\:block{display:block}.sm\:items-center{align-items:center}.sm\:justify-start{justify-content:flex-start}.sm\:justify-between{justify-content:space-between}.sm\:h-20{height:5rem}.sm\:ml-0{margin-left:0}.sm\:px-6{padding-left:1.5rem;padding-right:1.5rem}.sm\:pt-0{padding-top:0}.sm\:text-left{text-align:left}.sm\:text-right{text-align:right}}@media (min-width:768px){.md\:border-t-0{border-top-width:0}.md\:border-l{border-left-width:1px}.md\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}}@media (min-width:1024px){.lg\:px-8{padding-left:2rem;padding-right:2rem}}@media (prefers-color-scheme:dark){.dark\:bg-gray-800{--bg-opacity:1;background-color:#2d3748;background-color:rgba(45,55,72,var(--bg-opacity))}.dark\:bg-gray-900{--bg-opacity:1;background-color:#1a202c;background-color:rgba(26,32,44,var(--bg-opacity))}.dark\:border-gray-700{--border-opacity:1;border-color:#4a5568;border-color:rgba(74,85,104,var(--border-opacity))}.dark\:text-white{--text-opacity:1;color:#fff;color:rgba(255,255,255,var(--text-opacity))}.dark\:text-gray-400{--text-opacity:1;color:#cbd5e0;color:rgba(203,213,224,var(--text-opacity))}.dark\:text-gray-500{--tw-text-opacity:1;color:#6b7280;color:rgba(107,114,128,var(--tw-text-opacity))}}
</style>
<style>
body {
font-family: 'Nunito', sans-serif;
}
</style>
</head>
<body class="antialiased">
<div class="relative flex items-top justify-center min-h-screen bg-gray-100 dark:bg-gray-900 sm:items-center py-4 sm:pt-0">
@if (Route::has('login'))
<div class="hidden fixed top-0 right-0 px-6 py-4 sm:block">
@auth
<a href="{{ url('/home') }}" class="text-sm text-gray-700 dark:text-gray-500 underline">Home</a>
@else
<a href="{{ route('login') }}" class="text-sm text-gray-700 dark:text-gray-500 underline">Log in</a>
@if (Route::has('register'))
<a href="{{ route('register') }}" class="ml-4 text-sm text-gray-700 dark:text-gray-500 underline">Register</a>
@endif
@endauth
</div>
@endif
<div class="max-w-6xl mx-auto sm:px-6 lg:px-8">
<div class="flex justify-center pt-8 sm:justify-start sm:pt-0">
<svg viewBox="0 0 651 192" fill="none" xmlns="http://www.w3.org/2000/svg" class="h-16 w-auto text-gray-700 sm:h-20">
<g clip-path="url(#clip0)" fill="#EF3B2D">
<path d="M248.032 44.676h-16.466v100.23h47.394v-14.748h-30.928V44.676zM337.091 87.202c-2.101-3.341-5.083-5.965-8.949-7.875-3.865-1.909-7.756-2.864-11.669-2.864-5.062 0-9.69.931-13.89 2.792-4.201 1.861-7.804 4.417-10.811 7.661-3.007 3.246-5.347 6.993-7.016 11.239-1.672 4.249-2.506 8.713-2.506 13.389 0 4.774.834 9.26 2.506 13.459 1.669 4.202 4.009 7.925 7.016 11.169 3.007 3.246 6.609 5.799 10.811 7.66 4.199 1.861 8.828 2.792 13.89 2.792 3.913 0 7.804-.955 11.669-2.863 3.866-1.908 6.849-4.533 8.949-7.875v9.021h15.607V78.182h-15.607v9.02zm-1.431 32.503c-.955 2.578-2.291 4.821-4.009 6.73-1.719 1.91-3.795 3.437-6.229 4.582-2.435 1.146-5.133 1.718-8.091 1.718-2.96 0-5.633-.572-8.019-1.718-2.387-1.146-4.438-2.672-6.156-4.582-1.719-1.909-3.032-4.152-3.938-6.73-.909-2.577-1.36-5.298-1.36-8.161 0-2.864.451-5.585 1.36-8.162.905-2.577 2.219-4.819 3.938-6.729 1.718-1.908 3.77-3.437 6.156-4.582 2.386-1.146 5.059-1.718 8.019-1.718 2.958 0 5.656.572 8.091 1.718 2.434 1.146 4.51 2.674 6.229 4.582 1.718 1.91 3.054 4.152 4.009 6.729.953 2.577 1.432 5.298 1.432 8.162-.001 2.863-.479 5.584-1.432 8.161zM463.954 87.202c-2.101-3.341-5.083-5.965-8.949-7.875-3.865-1.909-7.756-2.864-11.669-2.864-5.062 0-9.69.931-13.89 2.792-4.201 1.861-7.804 4.417-10.811 7.661-3.007 3.246-5.347 6.993-7.016 11.239-1.672 4.249-2.506 8.713-2.506 13.389 0 4.774.834 9.26 2.506 13.459 1.669 4.202 4.009 7.925 7.016 11.169 3.007 3.246 6.609 5.799 10.811 7.66 4.199 1.861 8.828 2.792 13.89 2.792 3.913 0 7.804-.955 11.669-2.863 3.866-1.908 6.849-4.533 8.949-7.875v9.021h15.607V78.182h-15.607v9.02zm-1.432 32.503c-.955 2.578-2.291 4.821-4.009 6.73-1.719 1.91-3.795 3.437-6.229 4.582-2.435 1.146-5.133 1.718-8.091 1.718-2.96 0-5.633-.572-8.019-1.718-2.387-1.146-4.438-2.672-6.156-4.582-1.719-1.909-3.032-4.152-3.938-6.73-.909-2.577-1.36-5.298-1.36-8.161 0-2.864.451-5.585 1.36-8.162.905-2.577 2.219-4.819 3.938-6.729 1.718-1.908 3.77-3.437 6.156-4.582 2.386-1.146 5.059-1.718 8.019-1.718 2.958 0 5.656.572 8.091 1.718 2.434 1.146 4.51 2.674 6.229 4.582 1.718 1.91 3.054 4.152 4.009 6.729.953 2.577 1.432 5.298 1.432 8.162 0 2.863-.479 5.584-1.432 8.161zM650.772 44.676h-15.606v100.23h15.606V44.676zM365.013 144.906h15.607V93.538h26.776V78.182h-42.383v66.724zM542.133 78.182l-19.616 51.096-19.616-51.096h-15.808l25.617 66.724h19.614l25.617-66.724h-15.808zM591.98 76.466c-19.112 0-34.239 15.706-34.239 35.079 0 21.416 14.641 35.079 36.239 35.079 12.088 0 19.806-4.622 29.234-14.688l-10.544-8.158c-.006.008-7.958 10.449-19.832 10.449-13.802 0-19.612-11.127-19.612-16.884h51.777c2.72-22.043-11.772-40.877-33.023-40.877zm-18.713 29.28c.12-1.284 1.917-16.884 18.589-16.884 16.671 0 18.697 15.598 18.813 16.884h-37.402zM184.068 43.892c-.024-.088-.073-.165-.104-.25-.058-.157-.108-.316-.191-.46-.056-.097-.137-.176-.203-.265-.087-.117-.161-.242-.265-.345-.085-.086-.194-.148-.29-.223-.109-.085-.206-.182-.327-.252l-.002-.001-.002-.002-35.648-20.524a2.971 2.971 0 00-2.964 0l-35.647 20.522-.002.002-.002.001c-.121.07-.219.167-.327.252-.096.075-.205.138-.29.223-.103.103-.178.228-.265.345-.066.089-.147.169-.203.265-.083.144-.133.304-.191.46-.031.085-.08.162-.104.25-.067.249-.103.51-.103.776v38.979l-29.706 17.103V24.493a3 3 0 00-.103-.776c-.024-.088-.073-.165-.104-.25-.058-.157-.108-.316-.191-.46-.056-.097-.137-.176-.203-.265-.087-.117-.161-.242-.265-.345-.085-.086-.194-.148-.29-.223-.109-.085-.206-.182-.327-.252l-.002-.001-.002-.002L40.098 1.396a2.971 2.971 0 00-2.964 0L1.487 21.919l-.002.002-.002.001c-.121.07-.219.167-.327.252-.096.075-.205.138-.29.223-.103.103-.178.228-.265.345-.066.089-.147.169-.203.265-.083.144-.133.304-.191.46-.031.085-.08.162-.104.25-.067.249-.103.51-.103.776v122.09c0 1.063.568 2.044 1.489 2.575l71.293 41.045c.156.089.324.143.49.202.078.028.15.074.23.095a2.98 2.98 0 001.524 0c.069-.018.132-.059.2-.083.176-.061.354-.119.519-.214l71.293-41.045a2.971 2.971 0 001.489-2.575v-38.979l34.158-19.666a2.971 2.971 0 001.489-2.575V44.666a3.075 3.075 0 00-.106-.774zM74.255 143.167l-29.648-16.779 31.136-17.926.001-.001 34.164-19.669 29.674 17.084-21.772 12.428-43.555 24.863zm68.329-76.259v33.841l-12.475-7.182-17.231-9.92V49.806l12.475 7.182 17.231 9.92zm2.97-39.335l29.693 17.095-29.693 17.095-29.693-17.095 29.693-17.095zM54.06 114.089l-12.475 7.182V46.733l17.231-9.92 12.475-7.182v74.537l-17.231 9.921zM38.614 7.398l29.693 17.095-29.693 17.095L8.921 24.493 38.614 7.398zM5.938 29.632l12.475 7.182 17.231 9.92v79.676l.001.005-.001.006c0 .114.032.221.045.333.017.146.021.294.059.434l.002.007c.032.117.094.222.14.334.051.124.088.255.156.371a.036.036 0 00.004.009c.061.105.149.191.222.288.081.105.149.22.244.314l.008.01c.084.083.19.142.284.215.106.083.202.178.32.247l.013.005.011.008 34.139 19.321v34.175L5.939 144.867V29.632h-.001zm136.646 115.235l-65.352 37.625V148.31l48.399-27.628 16.953-9.677v33.862zm35.646-61.22l-29.706 17.102V66.908l17.231-9.92 12.475-7.182v33.841z"/>
</g>
</svg>
</div>
<div class="mt-8 bg-white dark:bg-gray-800 overflow-hidden shadow sm:rounded-lg">
<div class="grid grid-cols-1 md:grid-cols-2">
<div class="p-6">
<div class="flex items-center">
<svg fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" class="w-8 h-8 text-gray-500"><path d="M12 6.253v13m0-13C10.832 5.477 9.246 5 7.5 5S4.168 5.477 3 6.253v13C4.168 18.477 5.754 18 7.5 18s3.332.477 4.5 1.253m0-13C13.168 5.477 14.754 5 16.5 5c1.747 0 3.332.477 4.5 1.253v13C19.832 18.477 18.247 18 16.5 18c-1.746 0-3.332.477-4.5 1.253"></path></svg>
<div class="ml-4 text-lg leading-7 font-semibold"><a href="https://laravel.com/docs" class="underline text-gray-900 dark:text-white">Documentation</a></div>
</div>
<div class="ml-12">
<div class="mt-2 text-gray-600 dark:text-gray-400 text-sm">
Laravel has wonderful, thorough documentation covering every aspect of the framework. Whether you are new to the framework or have previous experience with Laravel, we recommend reading all of the documentation from beginning to end.
</div>
</div>
</div>
<div class="p-6 border-t border-gray-200 dark:border-gray-700 md:border-t-0 md:border-l">
<div class="flex items-center">
<svg fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" class="w-8 h-8 text-gray-500"><path d="M3 9a2 2 0 012-2h.93a2 2 0 001.664-.89l.812-1.22A2 2 0 0110.07 4h3.86a2 2 0 011.664.89l.812 1.22A2 2 0 0018.07 7H19a2 2 0 012 2v9a2 2 0 01-2 2H5a2 2 0 01-2-2V9z"></path><path d="M15 13a3 3 0 11-6 0 3 3 0 016 0z"></path></svg>
<div class="ml-4 text-lg leading-7 font-semibold"><a href="https://laracasts.com" class="underline text-gray-900 dark:text-white">Laracasts</a></div>
</div>
<div class="ml-12">
<div class="mt-2 text-gray-600 dark:text-gray-400 text-sm">
Laracasts offers thousands of video tutorials on Laravel, PHP, and JavaScript development. Check them out, see for yourself, and massively level up your development skills in the process.
</div>
</div>
</div>
<div class="p-6 border-t border-gray-200 dark:border-gray-700">
<div class="flex items-center">
<svg fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" class="w-8 h-8 text-gray-500"><path d="M7 8h10M7 12h4m1 8l-4-4H5a2 2 0 01-2-2V6a2 2 0 012-2h14a2 2 0 012 2v8a2 2 0 01-2 2h-3l-4 4z"></path></svg>
<div class="ml-4 text-lg leading-7 font-semibold"><a href="https://laravel-news.com/" class="underline text-gray-900 dark:text-white">Laravel News</a></div>
</div>
<div class="ml-12">
<div class="mt-2 text-gray-600 dark:text-gray-400 text-sm">
Laravel News is a community driven portal and newsletter aggregating all of the latest and most important news in the Laravel ecosystem, including new package releases and tutorials.
</div>
</div>
</div>
<div class="p-6 border-t border-gray-200 dark:border-gray-700 md:border-l">
<div class="flex items-center">
<svg fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" class="w-8 h-8 text-gray-500"><path d="M3.055 11H5a2 2 0 012 2v1a2 2 0 002 2 2 2 0 012 2v2.945M8 3.935V5.5A2.5 2.5 0 0010.5 8h.5a2 2 0 012 2 2 2 0 104 0 2 2 0 012-2h1.064M15 20.488V18a2 2 0 012-2h3.064M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path></svg>
<div class="ml-4 text-lg leading-7 font-semibold text-gray-900 dark:text-white">Vibrant Ecosystem</div>
</div>
<div class="ml-12">
<div class="mt-2 text-gray-600 dark:text-gray-400 text-sm">
Laravel's robust library of first-party tools and libraries, such as <a href="https://forge.laravel.com" class="underline">Forge</a>, <a href="https://vapor.laravel.com" class="underline">Vapor</a>, <a href="https://nova.laravel.com" class="underline">Nova</a>, and <a href="https://envoyer.io" class="underline">Envoyer</a> help you take your projects to the next level. Pair them with powerful open source libraries like <a href="https://laravel.com/docs/billing" class="underline">Cashier</a>, <a href="https://laravel.com/docs/dusk" class="underline">Dusk</a>, <a href="https://laravel.com/docs/broadcasting" class="underline">Echo</a>, <a href="https://laravel.com/docs/horizon" class="underline">Horizon</a>, <a href="https://laravel.com/docs/sanctum" class="underline">Sanctum</a>, <a href="https://laravel.com/docs/telescope" class="underline">Telescope</a>, and more.
</div>
</div>
</div>
</div>
</div>
<div class="flex justify-center mt-4 sm:items-center sm:justify-between">
<div class="text-center text-sm text-gray-500 sm:text-left">
<div class="flex items-center">
<svg fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" stroke="currentColor" class="-mt-px w-5 h-5 text-gray-400">
<path d="M3 3h2l.4 2M7 13h10l4-8H5.4M7 13L5.4 5M7 13l-2.293 2.293c-.63.63-.184 1.707.707 1.707H17m0 0a2 2 0 100 4 2 2 0 000-4zm-8 2a2 2 0 11-4 0 2 2 0 014 0z"></path>
</svg>
<a href="https://laravel.bigcartel.com" class="ml-1 underline">
Shop
</a>
<svg fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" class="ml-4 -mt-px w-5 h-5 text-gray-400">
<path d="M4.318 6.318a4.5 4.5 0 000 6.364L12 20.364l7.682-7.682a4.5 4.5 0 00-6.364-6.364L12 7.636l-1.318-1.318a4.5 4.5 0 00-6.364 0z"></path>
</svg>
<a href="https://github.com/sponsors/taylorotwell" class="ml-1 underline">
Sponsor
</a>
</div>
</div>
<div class="ml-4 text-center text-sm text-gray-500 sm:text-right sm:ml-0">
Laravel v{{ Illuminate\Foundation\Application::VERSION }} (PHP v{{ PHP_VERSION }})
</div>
</div>
</div>
</div>
</body>
</html>

View File

@ -5,6 +5,9 @@
* https://www.x-lf.com/
*/
use App\Http\Controllers\Console\Dashboard;
use App\Http\Controllers\Function\Link;
use App\Http\Controllers\Index;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Response;
use Illuminate\Support\Facades\Route;
@ -20,26 +23,37 @@
|
*/
Route::get('/', function () {
return view('welcome');
})->name('home');
Route::get('/', [Index::class,'ViewIndex'])->name('home');
Route::get('about',[Index::class,'ViewAboutMe'])->name('about');
Route::prefix('function')->group(function () {
Route::get('link',[Link::class,'ViewLink'])->name('function.link');
Route::get('make-friend',[Link::class,'ViewMakeFriend'])->name('function.make-friend');
Route::get('sponsor',function () {
return view('function.sponsor');
})->name('function.sponsor');
Route::get('music',function () {
return view('function.music');
})->name('function.music');
});
Route::prefix('console')->middleware('auth')->group(function () {
Route::get('dashboard', function () {
return view('console.dashboard');
})->name('console.dashboard');
Route::get('dashboard', [Dashboard::class,'ViewDashboard'])->name('console.dashboard');
});
Route::prefix('auth')->group(function () {
Route::redirect('','auth/login');
Route::get('login', function () {
return view('auth.login');
$data = (new Index())->data;
return view('auth.login',$data);
})->name('login');
Route::get('register',function () {
return view('auth.register');
$data = (new Index())->data;
return view('auth.register',$data);
})->name('register');
Route::get('forgotpassword',function () {
return view('auth.forgotpassword');
$data = (new Index())->data;
return view('auth.forgotpassword',$data);
})->name('forgotpassword');
Route::match(['get','post'],'logout',function () {
Auth::logout();