mirror of
https://github.com/lsky-org/lsky-pro.git
synced 2025-01-09 04:19:32 +08:00
✨ 适配游客组能使用多个储存的特性
This commit is contained in:
parent
60a7d0a87d
commit
843abacdef
@ -90,8 +90,6 @@ class Install extends Command
|
||||
));
|
||||
// 创建锁文件
|
||||
file_put_contents(base_path('installed.lock'), '');
|
||||
// 生成系统本地储存符号链接
|
||||
Artisan::call('storage:link');
|
||||
} catch (\Throwable $e) {
|
||||
$this->warn("Installation error!\n");
|
||||
$this->error($e->getMessage());
|
||||
|
@ -16,9 +16,6 @@ final class ConfigKey
|
||||
/** @var string 程序名称 */
|
||||
const AppName = 'app_name';
|
||||
|
||||
/** @var string 程序url */
|
||||
const AppUrl = 'app_url';
|
||||
|
||||
/** @var string 程序版本 */
|
||||
const AppVersion = 'app_version';
|
||||
|
||||
|
@ -4,16 +4,13 @@ declare(strict_types=1);
|
||||
|
||||
namespace App\Http\Controllers\Admin;
|
||||
|
||||
use App\Enums\ConfigKey;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\Admin\GroupRequest;
|
||||
use App\Models\Config;
|
||||
use App\Models\Group;
|
||||
use App\Utils;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Response;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\View\View;
|
||||
|
||||
class GroupController extends Controller
|
||||
@ -21,7 +18,7 @@ class GroupController extends Controller
|
||||
public function __construct()
|
||||
{
|
||||
\Illuminate\Support\Facades\View::share([
|
||||
'default' => Utils::config(ConfigKey::Group),
|
||||
'default' => Group::getDefaultConfigs(),
|
||||
'positions' => Group::POSITIONS,
|
||||
'scenes' => Group::SCENES,
|
||||
]);
|
||||
@ -42,44 +39,43 @@ class GroupController extends Controller
|
||||
|
||||
public function edit(Request $request): View
|
||||
{
|
||||
if ($request->route('id') == 0) {
|
||||
$group = new Group([
|
||||
'id' => 0,
|
||||
'name' => '系统默认组',
|
||||
'configs' => Utils::config(ConfigKey::Group),
|
||||
]);
|
||||
} else {
|
||||
$group = Group::query()->findOrFail($request->route('id'));
|
||||
}
|
||||
$group = Group::query()->findOrFail($request->route('id'));
|
||||
return view('admin.group.edit', compact('group'));
|
||||
}
|
||||
|
||||
public function create(GroupRequest $request): Response
|
||||
{
|
||||
$group = new Group();
|
||||
$group->fill($request->validated());
|
||||
$group->save();
|
||||
DB::transaction(function () use ($request) {
|
||||
$group = new Group();
|
||||
$group->fill($request->validated());
|
||||
$group->save();
|
||||
});
|
||||
|
||||
return $this->success('创建成功');
|
||||
}
|
||||
|
||||
public function update(GroupRequest $request): Response
|
||||
{
|
||||
if ($request->route('id') == 0) {
|
||||
$configs = Utils::parseConfigs(Group::getDefaultConfigs()->toArray(), $request->validated('configs'));
|
||||
if (! Config::query()->where('name', ConfigKey::Group)->update([
|
||||
'value' => collect($configs)->toJson(),
|
||||
])) {
|
||||
return $this->error('保存失败');
|
||||
}
|
||||
// 删除配置缓存
|
||||
Cache::forget('configs');
|
||||
} else {
|
||||
DB::beginTransaction();
|
||||
try {
|
||||
/** @var Group $group */
|
||||
$group = Group::query()->findOrFail($request->route('id'));
|
||||
$group->fill($request->validated());
|
||||
if (!$group->save()) {
|
||||
return $this->error('保存失败');
|
||||
if ($group->isDirty('is_default') && ! $group->is_default) {
|
||||
if (! Group::query()->where('is_default', true)->where('id', '<>', $group->id)->exists()) {
|
||||
return $this->error('系统至少需要保留一个默认组');
|
||||
}
|
||||
}
|
||||
if ($group->isDirty('is_guest') && ! $group->is_guest) {
|
||||
if (! Group::query()->where('is_guest', true)->where('id', '<>', $group->id)->exists()) {
|
||||
return $this->error('系统至少需要保留一个游客组');
|
||||
}
|
||||
}
|
||||
$group->save();
|
||||
DB::commit();
|
||||
} catch (\Throwable $e) {
|
||||
DB::rollBack();
|
||||
return $this->error('保存失败');
|
||||
}
|
||||
|
||||
return $this->success('保存成功');
|
||||
@ -87,7 +83,11 @@ class GroupController extends Controller
|
||||
|
||||
public function delete(Request $request): Response
|
||||
{
|
||||
/** @var Group $group */
|
||||
if ($group = Group::query()->find($request->route('id'))) {
|
||||
if ($group->is_default || $group->is_guest) {
|
||||
return $this->error('默认组和游客组无法删除');
|
||||
}
|
||||
$group->delete();
|
||||
}
|
||||
return $this->success('删除成功');
|
||||
|
@ -40,9 +40,7 @@ class ImageController extends Controller
|
||||
}
|
||||
|
||||
try {
|
||||
/** @var User $user */
|
||||
$user = Auth::user();
|
||||
$image = $service->store($request, $user);
|
||||
$image = $service->store($request);
|
||||
} catch (UploadException $e) {
|
||||
return $this->error($e->getMessage());
|
||||
} catch (\Throwable $e) {
|
||||
|
@ -8,7 +8,9 @@ use App\Enums\UserStatus;
|
||||
use App\Exceptions\UploadException;
|
||||
use App\Http\Api;
|
||||
use App\Models\Config;
|
||||
use App\Models\Group;
|
||||
use App\Models\Image;
|
||||
use App\Models\Strategy;
|
||||
use App\Models\User;
|
||||
use App\Services\ImageService;
|
||||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||
@ -18,7 +20,6 @@ use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Response;
|
||||
use Illuminate\Routing\Controller as BaseController;
|
||||
use Illuminate\Support\Facades\Artisan;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
@ -87,12 +88,15 @@ class Controller extends BaseController
|
||||
'email' => $request->input('account.email'),
|
||||
'password' => Hash::make($request->input('account.password')),
|
||||
]);
|
||||
$user->group_id = Group::query()->first()['id'];
|
||||
$user->is_adminer = true;
|
||||
$user->status = UserStatus::Normal;
|
||||
$user->email_verified_at = date('Y-m-d H:i:s');
|
||||
// 设置默认策略组的 url 为当前请求 url
|
||||
Strategy::query()->where('is_guest', true)->update([
|
||||
'configs->url' => $request->getSchemeAndHttpHost().'/i',
|
||||
]);
|
||||
$user->save();
|
||||
// 更新站点域名
|
||||
Config::query()->where('name', ConfigKey::AppUrl)->update(['value' => $request->getSchemeAndHttpHost()]);
|
||||
} catch (\Throwable $e) {
|
||||
@unlink(base_path('installed.lock'));
|
||||
return $this->error($e->getMessage());
|
||||
@ -109,9 +113,7 @@ class Controller extends BaseController
|
||||
public function upload(Request $request, ImageService $service): Response
|
||||
{
|
||||
try {
|
||||
/** @var User $user */
|
||||
$user = Auth::user();
|
||||
$image = $service->store($request, $user);
|
||||
$image = $service->store($request);
|
||||
} catch (UploadException $e) {
|
||||
return $this->error($e->getMessage());
|
||||
} catch (\Throwable $e) {
|
||||
|
@ -41,7 +41,7 @@ class UserController extends Controller
|
||||
/** @var User $user */
|
||||
$user = Auth::user();
|
||||
$user->name = $request->validated('name');
|
||||
$user->url = $request->validated('url');
|
||||
$user->url = $request->validated('url') ?: '';
|
||||
$user->configs = $user->configs->merge(collect($request->validated('configs'))->transform(function ($value) {
|
||||
return (int)$value;
|
||||
}));
|
||||
|
@ -25,6 +25,7 @@ class GroupRequest extends FormRequest
|
||||
return [
|
||||
'name' => 'required|between:2,30',
|
||||
'is_default' => 'boolean',
|
||||
'is_guest' => 'boolean',
|
||||
'configs' => 'required|array',
|
||||
'configs.maximum_file_size' => 'required|numeric',
|
||||
'configs.concurrent_upload_num' => 'required|integer',
|
||||
|
@ -13,7 +13,7 @@ class UserSettingRequest extends FormRequest
|
||||
{
|
||||
return [
|
||||
'name' => 'required|between:2,20',
|
||||
'url' => 'url',
|
||||
'url' => 'nullable|url',
|
||||
'password' => 'nullable|between:6,32',
|
||||
'configs' => 'array',
|
||||
'configs.default_album' => 'required|numeric',
|
||||
|
@ -4,9 +4,7 @@ namespace App\Models;
|
||||
|
||||
use App\Enums\ConfigKey;
|
||||
use App\Utils;
|
||||
use Barryvdh\Debugbar\Facades\Debugbar;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Database\Eloquent\Casts\Attribute;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
||||
@ -17,6 +15,7 @@ use Illuminate\Support\Collection;
|
||||
* @property int $id
|
||||
* @property string $name
|
||||
* @property boolean $is_default
|
||||
* @property boolean $is_guest
|
||||
* @property Collection $configs
|
||||
* @property Carbon $updated_at
|
||||
* @property Carbon $created_at
|
||||
@ -30,12 +29,14 @@ class Group extends Model
|
||||
protected $fillable = [
|
||||
'name',
|
||||
'is_default',
|
||||
'is_guest',
|
||||
'configs',
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'id' => 'integer',
|
||||
'is_default' => 'bool',
|
||||
'is_guest' => 'bool',
|
||||
'configs' => 'collection'
|
||||
];
|
||||
|
||||
@ -64,6 +65,12 @@ class Group extends Model
|
||||
protected static function booted()
|
||||
{
|
||||
static::saving(function (self $group) {
|
||||
if ($group->isDirty('is_default') && $group->is_default) {
|
||||
Group::query()->where('is_default', true)->update(['is_default' => false]);
|
||||
}
|
||||
if ($group->isDirty('is_guest') && $group->is_guest) {
|
||||
Group::query()->where('is_guest', true)->update(['is_guest' => false]);
|
||||
}
|
||||
$group->configs = Utils::parseConfigs(self::getDefaultConfigs()->toArray(), $group->configs->toArray());
|
||||
});
|
||||
}
|
||||
@ -75,17 +82,7 @@ class Group extends Model
|
||||
*/
|
||||
public static function getDefaultConfigs(): Collection
|
||||
{
|
||||
return collect(config('convention.app.'.ConfigKey::Group));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取访客组默认配置
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public static function getGuestConfigs(): Collection
|
||||
{
|
||||
return Utils::config(ConfigKey::Group);
|
||||
return collect(config('convention.app.group'));
|
||||
}
|
||||
|
||||
public function users(): HasMany
|
||||
|
@ -194,7 +194,7 @@ class Image extends Model
|
||||
|
||||
public function filesystem(): Filesystem
|
||||
{
|
||||
return new Filesystem((new ImageService())->getAdapter($this->strategy->key, $this->strategy->configs));
|
||||
return new Filesystem((new ImageService())->getAdapter($this->strategy));
|
||||
}
|
||||
|
||||
public function user(): BelongsTo
|
||||
@ -209,18 +209,12 @@ class Image extends Model
|
||||
|
||||
public function group(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Group::class, 'group_id', 'id')->withDefault(function (Group $group) {
|
||||
$group->name = '系统默认组';
|
||||
$group->configs = $group::getGuestConfigs();
|
||||
});
|
||||
return $this->belongsTo(Group::class, 'group_id', 'id');
|
||||
}
|
||||
|
||||
public function strategy(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Strategy::class, 'strategy_id', 'id')->withDefault(function (Strategy $strategy) {
|
||||
$strategy->key = StrategyKey::Local;
|
||||
$strategy->configs = collect(config('filesystems.disks.uploads'));
|
||||
});
|
||||
return $this->belongsTo(Strategy::class, 'strategy_id', 'id');
|
||||
}
|
||||
|
||||
private function generateKey($length = 6): string
|
||||
|
@ -41,17 +41,13 @@ class AppServiceProvider extends ServiceProvider
|
||||
if (file_exists(base_path('installed.lock'))) {
|
||||
// 覆盖默认配置
|
||||
Config::set('app.name', Utils::config(ConfigKey::AppName));
|
||||
Config::set('app.url', Utils::config(ConfigKey::AppUrl));
|
||||
Config::set('mail', array_merge(\config('mail'), Utils::config(ConfigKey::Mail)->toArray()));
|
||||
|
||||
// 覆盖默认组策略配置
|
||||
Config::set('filesystems.disks.uploads.url', Utils::config(ConfigKey::AppUrl).'/i');
|
||||
|
||||
$configs = Auth::check() && Auth::user()->group ?
|
||||
Auth::user()->group->configs :
|
||||
Group::query()->where('is_guest', true)->value('configs');
|
||||
// 初始化视图中的默认数据
|
||||
View::composer('*', function (\Illuminate\View\View $view) {
|
||||
$configs = Auth::check() && Auth::user()->group ? Auth::user()->group->configs : Group::getGuestConfigs();
|
||||
$view->with('groupConfigs', $configs);
|
||||
});
|
||||
View::share('groupConfigs', $configs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -16,6 +16,7 @@ use App\Enums\UserStatus;
|
||||
use App\Enums\Watermark\FontOption;
|
||||
use App\Enums\Watermark\ImageOption;
|
||||
use App\Exceptions\UploadException;
|
||||
use App\Models\Group;
|
||||
use App\Models\Image;
|
||||
use App\Models\Strategy;
|
||||
use App\Models\User;
|
||||
@ -25,6 +26,7 @@ use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\UploadedFile;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Str;
|
||||
use Intervention\Image\Facades\Image as InterventionImage;
|
||||
@ -40,72 +42,31 @@ class ImageService
|
||||
{
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param User|null $user
|
||||
* @return Image
|
||||
* @throws UploadException
|
||||
*/
|
||||
public function store(Request $request, ?User $user = null): Image
|
||||
public function store(Request $request): Image
|
||||
{
|
||||
$file = $request->file('file');
|
||||
|
||||
if (is_null($user) && !Utils::config(ConfigKey::IsAllowGuestUpload, true)) {
|
||||
if (Auth::guest() && !Utils::config(ConfigKey::IsAllowGuestUpload, true)) {
|
||||
throw new UploadException('管理员关闭了游客上传');
|
||||
}
|
||||
|
||||
$img = InterventionImage::make($file);
|
||||
|
||||
$image = new Image();
|
||||
/** @var User|null $user */
|
||||
$user = $request->user();
|
||||
|
||||
/** @var Group $group */
|
||||
$group = ! is_null($user) ? $user->group : Group::query()->where('is_guest', true)->first();
|
||||
// 组配置
|
||||
$configs = Utils::config(ConfigKey::Group);
|
||||
// 默认使用本地储存策略
|
||||
$disk = collect([
|
||||
'driver' => StrategyKey::Local,
|
||||
'configs' => collect([LocalOption::Root => config('filesystems.disks.uploads.root')]),
|
||||
]);
|
||||
|
||||
// 图片默认权限
|
||||
$image->permission = ImagePermission::Private;
|
||||
|
||||
if (!is_null($user)) {
|
||||
if (Utils::config(ConfigKey::IsUserNeedVerify) && !$user->email_verified_at) {
|
||||
throw new UploadException('账户未验证');
|
||||
}
|
||||
|
||||
if ($user->status !== UserStatus::Normal) {
|
||||
throw new UploadException('账号状态异常');
|
||||
}
|
||||
|
||||
// 如果该用户有角色组,覆盖默认组、上传策略配置
|
||||
if ($user->group) {
|
||||
$image->group_id = $user->group_id;
|
||||
$configs = $user->group->configs;
|
||||
// 获取策略列表,根据用户所选的策略上传
|
||||
$strategies = $user->group->strategies()->get();
|
||||
if ($strategies->isNotEmpty()) {
|
||||
// 是否指定了默认的策略
|
||||
$defaultStrategyId = $user->configs->get(UserConfigKey::DefaultStrategy, 0);
|
||||
/** @var Strategy $strategy $disk */
|
||||
$strategy = $strategies->find($defaultStrategyId, $strategies->first());
|
||||
$disk = collect(['driver' => $strategy->key, 'configs' => $strategy->configs]);
|
||||
$image->strategy_id = $strategy->id;
|
||||
}
|
||||
}
|
||||
|
||||
if ($file->getSize() / 1024 + $user->images()->sum('size') > $user->capacity) {
|
||||
throw new UploadException('储存空间不足');
|
||||
}
|
||||
|
||||
$image->user_id = $user->id;
|
||||
|
||||
// 图片保存至默认相册(若有)
|
||||
if ($albumId = $user->configs->get(UserConfigKey::DefaultAlbum)) {
|
||||
if ($user->albums()->where('id', $albumId)->exists()) {
|
||||
$image->album_id = $albumId;
|
||||
}
|
||||
}
|
||||
|
||||
// 用户设置的图片默认权限
|
||||
$image->permission = $user->configs->get(UserConfigKey::DefaultPermission, ImagePermission::Private);
|
||||
$configs = $group->configs;
|
||||
// 储存策略
|
||||
$strategies = $group->strategies()->get();
|
||||
if ($strategies->isEmpty()) {
|
||||
throw new UploadException('没有可用的储存,请联系管理员。');
|
||||
}
|
||||
|
||||
if (!in_array($file->extension(), $configs->get(GroupConfigKey::AcceptedFileSuffixes))) {
|
||||
@ -116,8 +77,47 @@ class ImageService
|
||||
throw new UploadException("图片大小超出限制");
|
||||
}
|
||||
|
||||
// 图片所属组
|
||||
$image->group_id = $group->id;
|
||||
// 图片默认权限
|
||||
$image->permission = ImagePermission::Private;
|
||||
|
||||
// 默认储存策略
|
||||
if (is_null($user)) {
|
||||
// 游客随机一个储存,TODO 适配前端切换
|
||||
$strategy = $strategies->random(1)->first();
|
||||
$image->strategy_id = $strategy->id;
|
||||
} else {
|
||||
/** @var Strategy $strategy */
|
||||
$strategy = $strategies->find($user->configs->get(UserConfigKey::DefaultStrategy, 0), $strategies->first());
|
||||
|
||||
if (Utils::config(ConfigKey::IsUserNeedVerify) && ! $user->email_verified_at) {
|
||||
throw new UploadException('账户未验证');
|
||||
}
|
||||
|
||||
if ($user->status !== UserStatus::Normal) {
|
||||
throw new UploadException('账号状态异常');
|
||||
}
|
||||
|
||||
if ($file->getSize() / 1024 + $user->images()->sum('size') > $user->capacity) {
|
||||
throw new UploadException('储存空间不足');
|
||||
}
|
||||
|
||||
// 图片保存至默认相册(若有)
|
||||
if ($albumId = $user->configs->get(UserConfigKey::DefaultAlbum)) {
|
||||
if ($user->albums()->where('id', $albumId)->exists()) {
|
||||
$image->album_id = $albumId;
|
||||
}
|
||||
}
|
||||
|
||||
$image->strategy_id = $strategy->id;
|
||||
$image->user_id = $user->id;
|
||||
// 用户设置的图片默认权限
|
||||
$image->permission = $user->configs->get(UserConfigKey::DefaultPermission, ImagePermission::Private);
|
||||
}
|
||||
|
||||
// 上传频率限制
|
||||
$this->rateLimiter($configs, $request, $user);
|
||||
$this->rateLimiter($configs, $request);
|
||||
|
||||
$filename = $this->replacePathname(
|
||||
$configs->get(GroupConfigKey::PathNamingRule).'/'.$configs->get(GroupConfigKey::FileNamingRule), $file,
|
||||
@ -139,7 +139,7 @@ class ImageService
|
||||
'uploaded_ip' => $request->ip(),
|
||||
]);
|
||||
|
||||
$filesystem = new Filesystem($this->getAdapter($disk->get('driver'), $disk->get('configs')));
|
||||
$filesystem = new Filesystem($this->getAdapter($strategy));
|
||||
// 检测该策略是否存在该图片,有则只创建记录不保存文件
|
||||
/** @var Image $existing */
|
||||
$existing = Image::query()->when($image->strategy_id, function (Builder $builder, $id) {
|
||||
@ -157,7 +157,16 @@ class ImageService
|
||||
$image->fill($existing->only('path', 'name'));
|
||||
}
|
||||
|
||||
DB::transaction(function () use ($image, $user, $filesystem, $existing) {
|
||||
$updateNum = function ($method) use ($user, $image) {
|
||||
if (! is_null($user)) {
|
||||
$user->{$method}('image_num');
|
||||
}
|
||||
if (! is_null($image->album)) {
|
||||
$image->album->{$method}('image_num');
|
||||
}
|
||||
};
|
||||
|
||||
DB::transaction(function () use ($image, $user, $filesystem, $existing, $updateNum) {
|
||||
if (!$image->save()) {
|
||||
// 删除文件
|
||||
if (is_null($existing)) {
|
||||
@ -165,12 +174,7 @@ class ImageService
|
||||
}
|
||||
throw new UploadException('图片保存失败');
|
||||
}
|
||||
if (!is_null($user)) {
|
||||
$user->increment('image_num');
|
||||
}
|
||||
if (!is_null($image->album)) {
|
||||
$image->album->increment('image_num');
|
||||
}
|
||||
$updateNum('increment');
|
||||
}, 2);
|
||||
|
||||
// 图片检测
|
||||
@ -180,6 +184,7 @@ class ImageService
|
||||
// 标记 or 删除
|
||||
if ($configs->get(GroupConfigKey::ScannedAction) === 'delete') {
|
||||
$image->delete();
|
||||
DB::transaction(fn () => $updateNum('decrement'));
|
||||
throw new UploadException('图片涉嫌违规,禁止上传。');
|
||||
} else {
|
||||
$image->is_unhealthy = true;
|
||||
@ -191,10 +196,11 @@ class ImageService
|
||||
return $image;
|
||||
}
|
||||
|
||||
public function getAdapter(int $disk, Collection $configs): FilesystemAdapter
|
||||
public function getAdapter(Strategy $strategy): FilesystemAdapter
|
||||
{
|
||||
return match ($disk) {
|
||||
StrategyKey::Local => new LocalFilesystemAdapter($configs->get('root') ?: config('filesystems.disks.uploads.root')),
|
||||
$configs = $strategy->configs;
|
||||
return match ($strategy->key) {
|
||||
StrategyKey::Local => new LocalFilesystemAdapter($configs->get('root')),
|
||||
StrategyKey::Kodo => new QiniuAdapter(
|
||||
accessKey: $configs->get(KodoOption::AccessKey),
|
||||
secretKey: $configs->get(KodoOption::SecretKey),
|
||||
@ -207,8 +213,10 @@ class ImageService
|
||||
/**
|
||||
* @throws UploadException
|
||||
*/
|
||||
protected function rateLimiter(Collection $configs, Request $request, ?User $user = null)
|
||||
protected function rateLimiter(Collection $configs, Request $request)
|
||||
{
|
||||
/** @var User|null $user */
|
||||
$user = $request->user();
|
||||
$carbon = Carbon::now();
|
||||
$array = [
|
||||
'minute' => ['key' => GroupConfigKey::LimitPerMinute, 'str' => '分钟'],
|
||||
@ -222,7 +230,7 @@ class ImageService
|
||||
$value = $configs->get($item['key'], 0);
|
||||
$count = Image::query()->whereBetween('created_at', [
|
||||
$carbon->parse("-1 {$key}"), $carbon,
|
||||
])->when(!is_null($user), function (Builder $builder) use ($user) {
|
||||
])->when(! is_null($user), function (Builder $builder) use ($user) {
|
||||
$builder->where('user_id', $user->id);
|
||||
}, function (Builder $builder) use ($request) {
|
||||
$builder->where('uploaded_ip', $request->ip())->whereNull('user_id');
|
||||
|
73
composer.lock
generated
73
composer.lock
generated
@ -334,16 +334,16 @@
|
||||
},
|
||||
{
|
||||
"name": "aws/aws-sdk-php",
|
||||
"version": "3.209.30",
|
||||
"version": "3.211.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/aws/aws-sdk-php.git",
|
||||
"reference": "54c1e491b8de74360bbe94d727706db384c8d9a8"
|
||||
"reference": "be209936fc1c70bb2e842cad2f3550ebb12d4eb8"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/54c1e491b8de74360bbe94d727706db384c8d9a8",
|
||||
"reference": "54c1e491b8de74360bbe94d727706db384c8d9a8",
|
||||
"url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/be209936fc1c70bb2e842cad2f3550ebb12d4eb8",
|
||||
"reference": "be209936fc1c70bb2e842cad2f3550ebb12d4eb8",
|
||||
"shasum": "",
|
||||
"mirrors": [
|
||||
{
|
||||
@ -425,9 +425,9 @@
|
||||
"support": {
|
||||
"forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80",
|
||||
"issues": "https://github.com/aws/aws-sdk-php/issues",
|
||||
"source": "https://github.com/aws/aws-sdk-php/tree/3.209.30"
|
||||
"source": "https://github.com/aws/aws-sdk-php/tree/3.211.0"
|
||||
},
|
||||
"time": "2022-02-23T19:14:31+00:00"
|
||||
"time": "2022-02-28T19:50:29+00:00"
|
||||
},
|
||||
{
|
||||
"name": "brick/math",
|
||||
@ -1170,16 +1170,16 @@
|
||||
},
|
||||
{
|
||||
"name": "doctrine/lexer",
|
||||
"version": "1.2.2",
|
||||
"version": "1.2.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/doctrine/lexer.git",
|
||||
"reference": "9c50f840f257bbb941e6f4a0e94ccf5db5c3f76c"
|
||||
"reference": "c268e882d4dbdd85e36e4ad69e02dc284f89d229"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/doctrine/lexer/zipball/9c50f840f257bbb941e6f4a0e94ccf5db5c3f76c",
|
||||
"reference": "9c50f840f257bbb941e6f4a0e94ccf5db5c3f76c",
|
||||
"url": "https://api.github.com/repos/doctrine/lexer/zipball/c268e882d4dbdd85e36e4ad69e02dc284f89d229",
|
||||
"reference": "c268e882d4dbdd85e36e4ad69e02dc284f89d229",
|
||||
"shasum": "",
|
||||
"mirrors": [
|
||||
{
|
||||
@ -1193,7 +1193,7 @@
|
||||
},
|
||||
"require-dev": {
|
||||
"doctrine/coding-standard": "^9.0",
|
||||
"phpstan/phpstan": "1.3",
|
||||
"phpstan/phpstan": "^1.3",
|
||||
"phpunit/phpunit": "^7.5 || ^8.5 || ^9.5",
|
||||
"vimeo/psalm": "^4.11"
|
||||
},
|
||||
@ -1232,7 +1232,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/doctrine/lexer/issues",
|
||||
"source": "https://github.com/doctrine/lexer/tree/1.2.2"
|
||||
"source": "https://github.com/doctrine/lexer/tree/1.2.3"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@ -1248,7 +1248,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-01-12T08:27:12+00:00"
|
||||
"time": "2022-02-28T11:07:21+00:00"
|
||||
},
|
||||
{
|
||||
"name": "dragonmantank/cron-expression",
|
||||
@ -4499,16 +4499,16 @@
|
||||
},
|
||||
{
|
||||
"name": "psy/psysh",
|
||||
"version": "v0.11.1",
|
||||
"version": "v0.11.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/bobthecow/psysh.git",
|
||||
"reference": "570292577277f06f590635381a7f761a6cf4f026"
|
||||
"reference": "7f7da640d68b9c9fec819caae7c744a213df6514"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/bobthecow/psysh/zipball/570292577277f06f590635381a7f761a6cf4f026",
|
||||
"reference": "570292577277f06f590635381a7f761a6cf4f026",
|
||||
"url": "https://api.github.com/repos/bobthecow/psysh/zipball/7f7da640d68b9c9fec819caae7c744a213df6514",
|
||||
"reference": "7f7da640d68b9c9fec819caae7c744a213df6514",
|
||||
"shasum": "",
|
||||
"mirrors": [
|
||||
{
|
||||
@ -4525,6 +4525,9 @@
|
||||
"symfony/console": "^6.0 || ^5.0 || ^4.0 || ^3.4",
|
||||
"symfony/var-dumper": "^6.0 || ^5.0 || ^4.0 || ^3.4"
|
||||
},
|
||||
"conflict": {
|
||||
"symfony/console": "4.4.37 || 5.3.14 || 5.3.15 || 5.4.3 || 5.4.4 || 6.0.3 || 6.0.4"
|
||||
},
|
||||
"require-dev": {
|
||||
"bamarni/composer-bin-plugin": "^1.2",
|
||||
"hoa/console": "3.17.05.02"
|
||||
@ -4574,9 +4577,9 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/bobthecow/psysh/issues",
|
||||
"source": "https://github.com/bobthecow/psysh/tree/v0.11.1"
|
||||
"source": "https://github.com/bobthecow/psysh/tree/v0.11.2"
|
||||
},
|
||||
"time": "2022-01-03T13:58:38+00:00"
|
||||
"time": "2022-02-28T15:28:54+00:00"
|
||||
},
|
||||
{
|
||||
"name": "qiniu/php-sdk",
|
||||
@ -4846,12 +4849,12 @@
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Ramsey\\Uuid\\": "src/"
|
||||
},
|
||||
"files": [
|
||||
"src/functions.php"
|
||||
]
|
||||
],
|
||||
"psr-4": {
|
||||
"Ramsey\\Uuid\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
@ -9127,16 +9130,16 @@
|
||||
},
|
||||
{
|
||||
"name": "phpunit/php-code-coverage",
|
||||
"version": "9.2.13",
|
||||
"version": "9.2.14",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/php-code-coverage.git",
|
||||
"reference": "deac8540cb7bd40b2b8cfa679b76202834fd04e8"
|
||||
"reference": "9f4d60b6afe5546421462b76cd4e633ebc364ab4"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/deac8540cb7bd40b2b8cfa679b76202834fd04e8",
|
||||
"reference": "deac8540cb7bd40b2b8cfa679b76202834fd04e8",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/9f4d60b6afe5546421462b76cd4e633ebc364ab4",
|
||||
"reference": "9f4d60b6afe5546421462b76cd4e633ebc364ab4",
|
||||
"shasum": "",
|
||||
"mirrors": [
|
||||
{
|
||||
@ -9198,7 +9201,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/sebastianbergmann/php-code-coverage/issues",
|
||||
"source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.13"
|
||||
"source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.14"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@ -9206,7 +9209,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2022-02-23T17:02:38+00:00"
|
||||
"time": "2022-02-28T12:38:02+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpunit/php-file-iterator",
|
||||
@ -10712,16 +10715,16 @@
|
||||
},
|
||||
{
|
||||
"name": "spatie/flare-client-php",
|
||||
"version": "1.0.3",
|
||||
"version": "1.0.4",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/spatie/flare-client-php.git",
|
||||
"reference": "9b54db8774b6bd7ad7cfa4c035820ef63ea1a75c"
|
||||
"reference": "edf253c68fba62cdb29ad6b48e211e29691dcee8"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/spatie/flare-client-php/zipball/9b54db8774b6bd7ad7cfa4c035820ef63ea1a75c",
|
||||
"reference": "9b54db8774b6bd7ad7cfa4c035820ef63ea1a75c",
|
||||
"url": "https://api.github.com/repos/spatie/flare-client-php/zipball/edf253c68fba62cdb29ad6b48e211e29691dcee8",
|
||||
"reference": "edf253c68fba62cdb29ad6b48e211e29691dcee8",
|
||||
"shasum": "",
|
||||
"mirrors": [
|
||||
{
|
||||
@ -10770,7 +10773,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/spatie/flare-client-php/issues",
|
||||
"source": "https://github.com/spatie/flare-client-php/tree/1.0.3"
|
||||
"source": "https://github.com/spatie/flare-client-php/tree/1.0.4"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@ -10778,7 +10781,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2022-02-25T11:05:23+00:00"
|
||||
"time": "2022-02-28T15:04:23+00:00"
|
||||
},
|
||||
{
|
||||
"name": "spatie/ignition",
|
||||
|
@ -12,7 +12,6 @@ use App\Enums\Watermark\ImageOption;
|
||||
return [
|
||||
'app' => [
|
||||
ConfigKey::AppName => 'Lsky Pro',
|
||||
ConfigKey::AppUrl => env('APP_URL'),
|
||||
ConfigKey::AppVersion => '2.0',
|
||||
ConfigKey::SiteKeywords => 'Lsky Pro,lsky,兰空图床',
|
||||
ConfigKey::SiteDescription => 'Lsky Pro, Your photo album on the cloud.',
|
||||
|
@ -21,6 +21,7 @@ return new class extends Migration
|
||||
$table->id();
|
||||
$table->string('name', 64)->comment('角色组名称');
|
||||
$table->boolean('is_default')->default(false)->comment('是否默认');
|
||||
$table->boolean('is_guest')->default(false)->comment('是否为游客组');
|
||||
$table->json('configs')->comment('组配置');
|
||||
$table->timestamps();
|
||||
});
|
||||
|
@ -2,6 +2,9 @@
|
||||
|
||||
namespace Database\Seeders;
|
||||
|
||||
use App\Enums\ConfigKey;
|
||||
use App\Enums\StrategyKey;
|
||||
use App\Models\Group;
|
||||
use Illuminate\Database\Seeder;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
@ -16,7 +19,9 @@ class InstallSeeder extends Seeder
|
||||
public function run()
|
||||
{
|
||||
$date = Carbon::now()->format('Y-m-d H:i:s');
|
||||
$array = collect(config('convention.app'))->transform(function ($value, $key) use ($date) {
|
||||
$array = collect(config('convention.app'))->except([
|
||||
ConfigKey::Group,
|
||||
])->transform(function ($value, $key) use ($date) {
|
||||
return [
|
||||
'name' => $key,
|
||||
'value' => is_array($value) ? json_encode($value, JSON_UNESCAPED_UNICODE) : $value,
|
||||
@ -24,6 +29,23 @@ class InstallSeeder extends Seeder
|
||||
'created_at' => $date,
|
||||
];
|
||||
})->values()->toArray();
|
||||
DB::table('configs')->insert($array);
|
||||
DB::transaction(function () use ($array) {
|
||||
DB::table('configs')->insert($array);
|
||||
// 创建默认组和默认策略
|
||||
/** @var Group $group */
|
||||
$group = Group::query()->create([
|
||||
'name' => '系统默认组&游客组',
|
||||
'is_default' => true,
|
||||
'is_guest' => true,
|
||||
'configs' => config('convention.app.group'),
|
||||
]);
|
||||
// 创建默认策略
|
||||
$group->strategies()->create([
|
||||
'key' => StrategyKey::Local,
|
||||
'name' => '默认本地策略',
|
||||
'intro' => '系统默认的本地策略',
|
||||
'configs' => config('filesystems.disks.uploads'),
|
||||
]);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -5,7 +5,7 @@
|
||||
@include('admin.group.tips')
|
||||
|
||||
<p class="bg-blue-500 p-2 mb-2 rounded text-sm text-white">
|
||||
<i class="fas fa-exclamation-circle"></i> 角色组设置默认以后新用户注册会归属该角色组,系统可以设置多个默认角色组,出现多个默认组,新用户将会以随机的方式归属某一个默认角色组。
|
||||
<i class="fas fa-exclamation-circle"></i> 角色组设置默认以后新用户注册会归属该角色组,系统只能设置一个默认角色组。设置为游客组后,未登录用户将会受游客组控制。
|
||||
</p>
|
||||
|
||||
<div class="mt-5 md:mt-0 md:col-span-2">
|
||||
@ -78,11 +78,17 @@
|
||||
</div>
|
||||
|
||||
<div class="col-span-6">
|
||||
<x-fieldset title="是否默认" faq="设置默认后,新用户注册以后将会属于该默认角色组。">
|
||||
<x-fieldset title="是否默认" faq="设置默认后,新用户注册以后将会属于该默认角色组,且默认组只能有一个。">
|
||||
<x-switch id="is_default" name="is_default" value="1"></x-switch>
|
||||
</x-fieldset>
|
||||
</div>
|
||||
|
||||
<div class="col-span-6">
|
||||
<x-fieldset title="是否为游客组" faq="设置为游客组后,未登录用户受该组控制,且游客组只能有一个。">
|
||||
<x-switch id="is_guest" name="is_guest" value="1"></x-switch>
|
||||
</x-fieldset>
|
||||
</div>
|
||||
|
||||
<div class="col-span-6">
|
||||
<x-fieldset title="允许上传的图片类型">
|
||||
@foreach($default->get('accepted_file_suffixes') as $extension)
|
||||
|
@ -4,12 +4,6 @@
|
||||
<div class="my-6 md:my-9">
|
||||
@include('admin.group.tips')
|
||||
|
||||
@if($group->id == 0)
|
||||
<p class="bg-blue-500 p-2 mb-2 rounded text-sm text-white">
|
||||
<i class="fas fa-exclamation-circle"></i> 当前编辑的是系统默认组,所有访客、以及未被设置角色组的用户上传的图片将会受这个角色组控制。默认组的图片访问域名为站点域名,域名可以在系统设置中更改。
|
||||
</p>
|
||||
@endif
|
||||
|
||||
<div class="mt-5 md:mt-0 md:col-span-2">
|
||||
<ul id="tabs" class="flex space-x-2 text-sm">
|
||||
<li class="group">
|
||||
@ -25,18 +19,13 @@
|
||||
<a data-target="watermark" href="javascript:void(0)" class="block rounded-t-lg px-3 py-2 bg-gray-200 group-hover:bg-white">水印配置</a>
|
||||
</li>
|
||||
</ul>
|
||||
<form action="{{ route('admin.group.update', ['id' => $group->id ?: '0']) }}" method="POST">
|
||||
<form action="{{ route('admin.group.update', ['id' => $group->id]) }}" method="POST">
|
||||
<div class="overflow-hidden rounded-md rounded-l-none">
|
||||
<div class="px-4 py-5 bg-white sm:p-6">
|
||||
<div data-tab="basic" class="grid grid-cols-6 gap-6">
|
||||
<div class="col-span-6">
|
||||
<label for="name" class="block text-sm font-medium text-gray-700"><span class="text-red-600">*</span>组名称</label>
|
||||
@if($group->id == 0)
|
||||
<x-input type="text" value="{{ $group->name }}" disabled readonly />
|
||||
<input type="hidden" name="name" id="name" value="{{ $group->name }}">
|
||||
@else
|
||||
<x-input type="text" name="name" id="name" autocomplete="name" placeholder="请输入组名称" value="{{ $group->name }}" />
|
||||
@endif
|
||||
<x-input type="text" name="name" id="name" autocomplete="name" placeholder="请输入组名称" value="{{ $group->name }}" />
|
||||
</div>
|
||||
|
||||
<div class="col-span-6">
|
||||
@ -84,13 +73,17 @@
|
||||
<x-input type="text" name="configs[file_naming_rule]" id="file_naming_rule" autocomplete="file_naming_rule" placeholder="请输入文件命名规则" value="{{ $group->configs['file_naming_rule'] }}" />
|
||||
</div>
|
||||
|
||||
@if($group->id)
|
||||
<div class="col-span-6">
|
||||
<x-fieldset title="是否默认" faq="设置默认后,新用户注册以后将会属于该默认角色组。">
|
||||
<x-fieldset title="是否默认" faq="设置默认后,新用户注册以后将会属于该默认角色组,且默认组只能有一个。">
|
||||
<x-switch id="is_default" name="is_default" value="1" :checked="(bool)$group->is_default"></x-switch>
|
||||
</x-fieldset>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<div class="col-span-6">
|
||||
<x-fieldset title="是否为游客组" faq="设置为游客组后,未登录用户受该组控制,且游客组只能有一个。">
|
||||
<x-switch id="is_guest" name="is_guest" value="1" :checked="(bool)$group->is_guest"></x-switch>
|
||||
</x-fieldset>
|
||||
</div>
|
||||
|
||||
<div class="col-span-6">
|
||||
<x-fieldset title="允许上传的图片类型">
|
||||
|
@ -9,32 +9,7 @@
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<x-table :columns="['ID', '名称', '是否默认', '图片审核', '原图保护', '水印' ,'用户数量', '策略数量', '操作']">
|
||||
<tr data-id="0">
|
||||
<td class="px-6 py-4 whitespace-nowrap">-</td>
|
||||
<td class="px-6 py-4 whitespace-nowrap name">系统默认组</td>
|
||||
<td class="px-6 py-4 whitespace-nowrap">-</td>
|
||||
<td class="px-6 py-4 whitespace-nowrap">
|
||||
<span class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full {{ $default['is_enable_scan'] ? 'text-green-500' : 'text-rose-500' }}">
|
||||
<i class="text-lg fas fa-{{ $default['is_enable_scan'] ? 'check-circle' : 'times-circle' }}"></i>
|
||||
</span>
|
||||
</td>
|
||||
<td class="px-6 py-4 whitespace-nowrap">
|
||||
<span class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full {{ $default['is_enable_original_protection'] ? 'text-green-500' : 'text-rose-500' }}">
|
||||
<i class="text-lg fas fa-{{ $default['is_enable_original_protection'] ? 'check-circle' : 'times-circle' }}"></i>
|
||||
</span>
|
||||
</td>
|
||||
<td class="px-6 py-4 whitespace-nowrap">
|
||||
<span class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full {{ $default['is_enable_watermark'] ? 'text-green-500' : 'text-rose-500' }}">
|
||||
<i class="text-lg fas fa-{{ $default['is_enable_watermark'] ? 'check-circle' : 'times-circle' }}"></i>
|
||||
</span>
|
||||
</td>
|
||||
<td class="px-6 py-4 whitespace-nowrap">-</td>
|
||||
<td class="px-6 py-4 whitespace-nowrap">-</td>
|
||||
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium space-x-2">
|
||||
<a href="{{ route('admin.group.edit', ['id' => 0]) }}" class="text-indigo-600 hover:text-indigo-900">编辑</a>
|
||||
</td>
|
||||
</tr>
|
||||
<x-table :columns="['ID', '名称', '是否默认', '是否为游客组', '图片审核', '原图保护', '水印' ,'用户数量', '策略数量', '操作']">
|
||||
@foreach($groups as $group)
|
||||
<tr data-id="{{ $group->id }}">
|
||||
<td class="px-6 py-4 whitespace-nowrap">{{ $group->id }}</td>
|
||||
@ -44,6 +19,11 @@
|
||||
<i class="text-lg fas fa-{{ $group->is_default ? 'check-circle' : 'times-circle' }}"></i>
|
||||
</span>
|
||||
</td>
|
||||
<td class="px-6 py-4 whitespace-nowrap">
|
||||
<span class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full {{ $group->is_guest ? 'text-green-500' : 'text-rose-500' }}">
|
||||
<i class="text-lg fas fa-{{ $group->is_guest ? 'check-circle' : 'times-circle' }}"></i>
|
||||
</span>
|
||||
</td>
|
||||
<td class="px-6 py-4 whitespace-nowrap">
|
||||
<span class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full {{ $group->configs['is_enable_scan'] ? 'text-green-500' : 'text-rose-500' }}">
|
||||
<i class="text-lg fas fa-{{ $group->configs['is_enable_scan'] ? 'check-circle' : 'times-circle' }}"></i>
|
||||
@ -63,13 +43,15 @@
|
||||
<td class="px-6 py-4 whitespace-nowrap">{{ $group->strategies_count }}</td>
|
||||
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium space-x-2">
|
||||
<a href="{{ route('admin.group.edit', ['id' => $group->id]) }}" class="text-indigo-600 hover:text-indigo-900">编辑</a>
|
||||
@if(! $group->is_default && ! $group->is_guest)
|
||||
<a href="javascript:void(0)" data-operate="delete" class="text-red-600 hover:text-red-900">删除</a>
|
||||
@endif
|
||||
</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</x-table>
|
||||
@if($groups->isEmpty())
|
||||
<x-no-data message="没有找到自定义角色组"/>
|
||||
<x-no-data message="没有找到任何角色组"/>
|
||||
@else
|
||||
<div class="mt-4">
|
||||
{{ $groups->links() }}
|
||||
|
@ -13,10 +13,6 @@
|
||||
<label for="app_name" class="block text-sm font-medium text-gray-700"><span class="text-red-600">*</span>应用名称</label>
|
||||
<x-input type="text" name="app_name" id="app_name" value="{{ $configs['app_name'] }}" placeholder="请输入应用名称"/>
|
||||
</div>
|
||||
<div>
|
||||
<label for="app_url" class="block text-sm font-medium text-gray-700"><span class="text-red-600">*</span>应用网址</label>
|
||||
<x-input type="text" name="app_url" id="app_url" value="{{ $configs['app_url'] }}" placeholder="请输入应用网址 http(s)://"/>
|
||||
</div>
|
||||
<div>
|
||||
<label for="site_keywords" class="block text-sm font-medium text-gray-700">网站关键字</label>
|
||||
<x-textarea type="text" name="site_keywords" id="site_keywords" placeholder="请输入网站关键字">{{ $configs['site_keywords'] }}</x-textarea>
|
||||
|
@ -2,6 +2,8 @@
|
||||
|
||||
<x-app-layout>
|
||||
<div class="my-6 md:my-9">
|
||||
@include('admin.strategy.tips')
|
||||
|
||||
<div class="md:mt-0 md:col-span-2">
|
||||
<form action="{{ route('admin.strategy.create') }}" method="POST">
|
||||
<div class="overflow-hidden rounded-md">
|
||||
|
@ -2,6 +2,8 @@
|
||||
|
||||
<x-app-layout>
|
||||
<div class="my-6 md:my-9">
|
||||
@include('admin.strategy.tips')
|
||||
|
||||
<div class="md:mt-0 md:col-span-2">
|
||||
<form action="{{ route('admin.strategy.update', ['id' => $strategy->id]) }}" method="POST">
|
||||
<div class="overflow-hidden rounded-md">
|
||||
|
3
resources/views/admin/strategy/tips.blade.php
Normal file
3
resources/views/admin/strategy/tips.blade.php
Normal file
@ -0,0 +1,3 @@
|
||||
<p class="bg-blue-500 p-2 mb-2 rounded text-sm text-white">
|
||||
<i class="fas fa-exclamation-circle"></i> 一个策略可以关联多个角色组,一个角色组也可以关联多个策略,注意,如果某个组未设置储存策略,那么该角色组下的用户将无法上传图片。
|
||||
</p>
|
@ -6,7 +6,7 @@
|
||||
<div class="space-y-4 bg-white p-3 rounded-md mb-10">
|
||||
<div>
|
||||
<p class="text-lg text-gray-700 font-semibold">接口URL</p>
|
||||
<x-code>{{ \App\Utils::config(\App\Enums\ConfigKey::AppUrl) }}/api/v1</x-code>
|
||||
<x-code>{{ request()->getSchemeAndHttpHost() }}/api/v1</x-code>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
|
@ -46,5 +46,15 @@
|
||||
</x-container>
|
||||
</div>
|
||||
</body>
|
||||
<script>
|
||||
// 开关组件默认值
|
||||
$('.switch input[type=checkbox]').click(function () {
|
||||
if (this.checked) {
|
||||
$(this).closest('.switch').find('input[type=hidden]').remove();
|
||||
} else {
|
||||
$(this).before('<input type="hidden" name="'+this.name+'" value="0" />');
|
||||
}
|
||||
});
|
||||
</script>
|
||||
@stack('scripts')
|
||||
</html>
|
||||
|
Loading…
Reference in New Issue
Block a user