mcpField
U
unopim-datagrid

unopim-datagrid

github.com/unopim开发140 次安装2 周前更新
代码仓库

关于 unopim-datagrid

面向 UnoPim 管理后台数据网格和列表页开发的仓库专用技能,说明查询、列、操作、本地化及 Blade 约定,并提供参考实现。

主要功能

  1. 01数据网格结构与查询规则
  2. 02列和操作的配置要求
  3. 03操作的权限检查
  4. 04HTML 转义与标签翻译
  5. 05控制器和列表 Blade 模式

适用场景

  1. 01实现管理后台列表网格
  2. 02添加受权限控制的行或批量操作
  3. 03创建模块列表页

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/unopim/agent-skills --skill unopim-datagrid

安装后在 Claude Code 中输入/unopim-datagrid确认已加载。

详细介绍

UnoPim DataGrid

参照以下示例复制其结构——切勿臆造引擎 API:

  • Grid 类:packages/Webkul/AiAgent/src/DataGrids/Credential/CredentialDataGrid.php
  • 批量操作:packages/Webkul/Admin/src/DataGrids/Catalog/ProductDataGrid.php
  • 列表 Blade:packages/Webkul/Webhook/src/Resources/views/webhooks/index.blade.php
  • 带前缀的原始 SQL:packages/Webkul/Measurement/src/DataGrids/UnitDataGrid.php

规则

  • Grid 位于子目录中——src/DataGrids/{Section}/{Name}DataGrid.php——并继承 Webkul\DataGrid\DataGrid。
  • prepareQueryBuilder() 必须使用 DB::table() 和不带前缀的表名(Laravel 会应用 env('DB_PREFIX', ''))。此处绝不要查询 Eloquent 模型。
  • 任何命名表的原始片段(selectRaw、whereRaw、orderByRaw、DB::raw)都必须添加 DB::getTablePrefix() 前缀——参见 packages/Webkul/Measurement/src/DataGrids/UnitDataGrid.php。CI 同时运行 MySQL 和 PostgreSQL:不得使用仅适用于 MySQL 的 SQL(GROUP_CONCAT、反引号、DATE_FORMAT)。
  • addColumn() 必须设置全部六个键——index、label、type、searchable、filterable、sortable。引擎读取这三个标志时不会使用 null 合并;省略任何一个都会在请求时触发「Undefined array key」。
  • 钩子签名:抽象基类中的 prepareColumns()/prepareActions() 没有类型声明,因此仅含 PHPDoc @return 的写法(较旧的 Admin Grid)和 : void(较新的 Grid,包括 Credential 示例)都能编译。新代码请写 : void;编辑时遵循现有风格。绝不要将任一种风格判定为违规。
  • 操作的 url 接受任何可调用对象——优先使用 fn ($row): string => route(...)。批量操作的 url 必须是普通的 route(...) 字符串,不能是可调用对象。
  • 每个操作和批量操作都必须通过 bouncer()->hasPermission() 进行权限检查。批量操作 ACL 键使用 snake_case({module-slug}.credentials.mass_delete),并与路由名称一致——绝不要使用带连字符的形式(mass-delete)。
  • 列 closure 的输出会作为原始 HTML 渲染;引擎只会对纯字符串单元格执行 strip_tags()。在 closure HTML 中插入的任何用户提供值都必须使用 e() 转义。
  • 每个标签和标题都使用 trans(),并先将键添加到 en_US,再添加到全部 33 个语言区域设置中。布尔徽章:label-active(true)、label-info text-gray-600 dark:text-gray-300(false)。
  • 方法体或数组字面量中不得有注释。方法 PHPDoc 必须是单行祈使式摘要;仅在没有原生返回类型时使用 @return。

Grid 类

<?php

namespace Webkul\{ModuleName}\DataGrids\Credential;

use Illuminate\Database\Query\Builder;
use Illuminate\Support\Facades\DB;
use Webkul\DataGrid\DataGrid;

class CredentialDataGrid extends DataGrid
{
    /**
     * Prepare query builder.
     *
     * @return Builder
     */
    public function prepareQueryBuilder()
    {
        return DB::table('{module}_credentials')
            ->select('id', 'label', 'status', 'created_at');
    }

    /**
     * Prepare columns.
     */
    public function prepareColumns(): void
    {
        $this->addColumn([
            'index'      => 'label',
            'label'      => trans('{module-name}::app.credentials.datagrid.label'),
            'type'       => 'string',
            'searchable' => true,
            'filterable' => true,
            'sortable'   => true,
        ]);

        $this->addColumn([
            'index'      => 'status',
            'label'      => trans('{module-name}::app.credentials.datagrid.status'),
            'type'       => 'boolean',
            'searchable' => false,
            'filterable' => true,
            'sortable'   => true,
            'closure'    => fn ($row): string => $row->status
                ? '<span class="label-active">'.trans('admin::app.common.yes').'</span>'
                : '<span class="label-info text-gray-600 dark:text-gray-300">'.trans('admin::app.common.no').'</span>',
        ]);
    }

    /**
     * Prepare actions.
     */
    public function prepareActions(): void
    {
        if (bouncer()->hasPermission('{module-slug}.credentials.edit')) {
            $this->addAction([
                'icon'   => 'icon-edit',
                'title'  => trans('{module-name}::app.credentials.datagrid.edit'),
                'method' => 'GET',
                'url'    => fn ($row): string => route('{module-slug}.credentials.edit', $row->id),
            ]);
        }

        if (bouncer()->hasPermission('{module-slug}.credentials.delete')) {
            $this->addAction([
                'icon'   => 'icon-delete',
                'title'  => trans('{module-name}::app.credentials.datagrid.delete'),
                'method' => 'DELETE',
                'url'    => fn ($row): string => route('{module-slug}.credentials.destroy', $row->id),
            ]);
        }
    }

    /**
     * Prepare mass actions.
     */
    public function prepareMassActions(): void
    {
        if (bouncer()->hasPermission('{module-slug}.credentials.mass_delete')) {
            $this->addMassAction([
                'title'   => trans('{module-name}::app.credentials.datagrid.delete'),
                'url'     => route('{module-slug}.credentials.mass_delete'),
                'method'  => 'POST',
                'options' => ['actionType' => 'delete'],
            ]);
        }
    }
}

对于状态批量更新,请从 packages/Webkul/Admin/src/DataGrids/Catalog/ProductDataGrid.php 中的 catalog.products.mass_update 块复制 options 标签/值对数组。

控制器

public function index()
{
    if (request()->ajax()) {
        return resolve(CredentialDataGrid::class)->toJson();
    }

    return view('{module-name}::credentials.index');
}

列表 Blade

admin::layouts.master 和 @extends 不存在——admin 布局是一个组件。创建操作是在索引页上的模态框,其 store() 会重定向到编辑页(从 Webhook 示例复制 v-create-webhook-form);不要添加 GET 创建页面。

<x-admin::layouts>
    <x-slot:title>
        @lang('{module-name}::app.credentials.index.title')
    </x-slot>

    <x-admin::layouts.page-header :title="trans('{module-name}::app.credentials.index.title')" />

    <x-admin::datagrid :src="route('{module-slug}.credentials.index')" />
</x-admin::layouts>

评论

支持 Markdown