承接 ewk/moonshine-resource-kit 相关项目开发

从需求分析到上线部署,全程专人跟进,保证项目质量与交付效率

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

ewk/moonshine-resource-kit

Composer 安装命令:

composer require ewk/moonshine-resource-kit

包简介

Drag & drop sorting and activity toggling toolkit for MoonShine 4 resources.

README 文档

README

Тулкит для ресурсов MoonShine 4: drag & drop сортировка и переключатель активности.

Извлечён из паттернов, повторяющихся в реальных проектах: колонка sort_order с перетаскиванием строк в админской таблице и флаг is_active с переключением по одной записи и массово. Пакет — тонкий клей над встроенными механизмами MoonShine (reorderable()-таблицы на SortableJS, updateOnPreview() у переключателей): без собственного JS, всё настраивается на уровне модели/ресурса.

Требования

  • PHP 8.3+
  • Laravel 12/13
  • MoonShine 4.15+

Установка

composer require ewk/moonshine-resource-kit

Сервис-провайдер подключается автоматически. При необходимости опубликуйте конфиг и переводы:

php artisan vendor:publish --tag=moonshine-resource-kit-config
php artisan vendor:publish --tag=moonshine-resource-kit-lang

Сортировка

Модель

Добавьте колонку sort_order ($table->unsignedInteger('sort_order')->nullable();) и трейт:

use Ewk\MoonShineResourceKit\Concerns\Sortable;

class Article extends Model
{
    use Sortable;
}

Новые записи получают позицию max + 1 автоматически. Также трейт даёт:

Article::query()->orderedBySort()->get();   // ... ->orderedBySortDesc()

$article->moveUp();
$article->moveDown();
$article->moveToStart();
$article->moveToEnd();
$article->moveToPosition(7);

Позиции плотные (всегда 1..N), перемещение дешёвое: один UPDATE со сдвигом диапазона плюс один UPDATE с установкой позиции — независимо от размера таблицы.

Своя колонка — переопределите в модели (глобальный дефолт задаётся в конфиге):

public function getSortColumn(): string
{
    return 'position';
}

Групповые последовательности — независимая сортировка внутри каждой группы (например, блоки внутри страницы):

public function getSortGroupColumns(): array
{
    return ['page_id'];
}

Ресурс

use Ewk\MoonShineResourceKit\MoonShine\Concerns\WithReorderable;

class ArticleResource extends ModelResource
{
    use WithReorderable;
}

Дальше включите drag & drop на индексной странице — либо трейтом страницы:

use Ewk\MoonShineResourceKit\MoonShine\Concerns\ReorderableIndex;

class ArticleIndexPage extends IndexPage
{
    use ReorderableIndex;
}

либо вручную в modifyListComponent():

protected function modifyListComponent(ComponentContract $component): ComponentContract
{
    return $this->getResource()->applyReorderable($component, $this);
}

Пагинация и большие таблицы

Drag & drop достаёт только до строк текущей страницы — и это нормально: когда таблица отсортирована по колонке сортировки, страница занимает непрерывный срез позиций, и пакет перераспределяет ровно этот срез. Остальные страницы не затрагиваются.

Чтобы переносить записи между страницами, добавьте кнопки перемещения на индексную страницу:

use Ewk\MoonShineResourceKit\MoonShine\Buttons\ReorderButtons;

protected function buttons(): ListOf
{
    return parent::buttons()->prepend(...ReorderButtons::for($this->getResource()));
}

Вы получите «вверх / вниз», «в начало / в конец» и модалку «на позицию». Каждое перемещение — два UPDATE, так что решение масштабируется на большие таблицы без перезаписи всех строк.

Ручка перетаскивания

По умолчанию тянется вся строка. Чтобы перетаскивать только за ручку:

use Ewk\MoonShineResourceKit\MoonShine\Fields\SortHandle;

protected function fields(): iterable
{
    return [
        SortHandle::make(),
        ID::make(),
        // ...
    ];
}

protected function reorderableWithHandle(): bool  // на индексной странице с ReorderableIndex
{
    return true;
}

Вложенные таблицы

Для таблиц HasMany, которые рендерятся внутри формы другого ресурса:

HasMany::make('Blocks', resource: BlockResource::class)
    ->modifyTable(app(BlockResource::class)->reorderableTableModifier()),

Переключатель активности

Модель

Добавьте boolean-колонку ($table->boolean('is_active')->default(true);) и трейт:

use Ewk\MoonShineResourceKit\Concerns\Activatable;

class Article extends Model
{
    use Activatable;
}

Вы получите activate() / deactivate() / toggleActive() / isActive(), скоупы active() / inactive() и boolean-каст. Чтобы использовать другую колонку, переопределите getActiveColumn().

Ресурс

use Ewk\MoonShineResourceKit\MoonShine\Concerns\WithActivatable;

class ArticleResource extends ModelResource
{
    use WithActivatable;
}

Переключение прямо из индексной таблицы:

use Ewk\MoonShineResourceKit\MoonShine\Fields\ActiveSwitcher;

protected function fields(): iterable
{
    return [
        // ...
        ActiveSwitcher::make('Активность'),
    ];
}

Кнопки массовой активации/деактивации:

use Ewk\MoonShineResourceKit\MoonShine\Buttons\ActivityButtons;

protected function buttons(): ListOf
{
    return parent::buttons()->prepend(...ActivityButtons::for($this->getResource()));
}

Глобальные скоупы (opt-in)

ActiveScope (скрывает неактивные записи) и SortOrderScope (неявная сортировка) поставляются в пакете, но никогда не регистрируются автоматически — глобальный скоуп, зависящий от текущего URL, стреляет в ногу в очередях, Octane и artisan. Регистрируйте их там, где ограничение реально нужно:

use Ewk\MoonShineResourceKit\Scopes\ActiveScope;

protected static function booted(): void
{
    static::addGlobalScope(new ActiveScope());
}

// обходной путь:
Article::query()->withInactive()->get();

Состояния фабрик

use Ewk\MoonShineResourceKit\Concerns\HasActiveFactoryStates;

class ArticleFactory extends Factory
{
    use HasActiveFactoryStates;
}

ArticleFactory::new()->active()->create();
ArticleFactory::new()->inactive()->create();
ArticleFactory::new()->randomActive()->create();

Конфигурация

config/moonshine-resource-kit.php:

Ключ По умолчанию Назначение
sort_column sort_order Глобальный дефолт для трейта Sortable
active_column is_active Глобальный дефолт для трейта Activatable
handle_class msrk-handle CSS-класс ячейки-ручки перетаскивания

Переопределения на уровне модели (getSortColumn(), getSortGroupColumns(), getActiveColumn()) всегда приоритетнее конфига.

Разработка

composer test          # arch + unit + feature
composer phpstan       # level max, только src/
composer format        # PHP-CS-Fixer (PER 3.0)

Лицензия

MIT

统计信息

  • 总下载量: 0
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 0
  • 点击次数: 1
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 0
  • Watchers: 0
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2026-07-07

承接程序开发

PHP开发

VUE

Vue开发

前端开发

小程序开发

公众号开发

系统定制

数据库设计

云部署

网站建设

安全加固