跳到内容

设计

编辑此页

后端的设计适用于任何类型的应用程序。它使用 Bootstrap 5Font Awesome 图标和一些自定义 CSS 和 JavaScript 代码创建;所有这些都通过 Webpack 和 Symfony 的 Webpack Encore 进行管理。

像任何其他 Symfony 扩展包一样,在安装或更新扩展包时,资源会被复制到(或符号链接自)你应用程序的 public/bundles/ 目录。如果由于任何原因这不起作用,你的后端将不会显示正确的 CSS/JS 样式。在这些情况下,运行此命令手动安装这些资源

1
2
# remove the --symlink option if your system doesn't support symbolic links
$ php bin/console assets:install --symlink

根据你的需求,有几种自定义设计的方法。其中一些需要纯 CSS/JavaScript 代码,另一些则需要覆盖和/或创建新的 Twig 模板。

修改后端模板

后端页面由多个 Twig 模板和片段创建。你可以通过两种方式修改它们

  • 使用 Symfony 的机制覆盖 EasyAdmin 模板(这对于所有扩展包都是一样的,不仅限于 EasyAdmin);
  • 使用 EasyAdmin 功能替换 EasyAdmin 模板

覆盖模板

提示

除了使用 Symfony 的机制来覆盖模板,你还可以考虑使用 EasyAdmin 提供的类似但更强大的功能来替换模板,如下一节所述

按照 Symfony 的机制从扩展包中覆盖模板,你必须在你的应用程序中创建 templates/bundles/EasyAdminBundle/ 目录,然后创建与原始模板路径相同的新模板。例如

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
your-project/
├─ ...
└─ templates/
   └─ bundles/
      └─ EasyAdminBundle/
         ├─ layout.html.twig
         ├─ menu.html.twig
         ├─ crud/
         │  ├─ index.html.twig
         │  ├─ detail.html.twig
         │  └─ field/
         │     ├─ country.html.twig
         │     └─ text.html.twig
         ├─ label/
         │  └─ null.html.twig
         └─ page/
            ├─ content.html.twig
            └─ login.html.twig

你不必从头开始创建新模板,而是可以从原始模板扩展,并仅更改要覆盖的部分。但是,你必须在 extends 内部使用特殊语法以避免无限循环

1
2
3
4
5
6
7
8
9
10
11
{# templates/bundles/EasyAdminBundle/layout.html.twig #}

{# DON'T DO THIS: it will cause an infinite loop #}
{% extends '@EasyAdmin/layout.html.twig' %}

{# DO THIS: the '!' symbol tells Symfony to extend from the original template #}
{% extends '@!EasyAdmin/layout.html.twig' %}

{% block sidebar %}
    {# ... #}
{% endblock %}

替换模板

此选项允许你使用自己的 Twig 模板渲染后端的某些部分。首先,你可以在仪表盘中全局替换一些模板

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
use EasyCorp\Bundle\EasyAdminBundle\Config\Crud;
use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractDashboardController;

class DashboardController extends AbstractDashboardController
{
    // ...

    public function configureCrud(): Crud
    {
        return Crud::new()
            // ...

            // the first argument is the "template name", which is the same as the
            // Twig path but without the `@EasyAdmin/` prefix
            ->overrideTemplate('label/null', 'admin/labels/my_null_label.html.twig')

            ->overrideTemplates([
                'crud/index' => 'admin/pages/index.html.twig',
                'crud/field/textarea' => 'admin/fields/dynamic_textarea.html.twig',
            ])
        ;
    }
}

你也可以为每个 CRUD 控制器替换模板(这将覆盖在仪表盘中所做的任何更改)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
namespace App\Controller\Admin;

use EasyCorp\Bundle\EasyAdminBundle\Config\Crud;
use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController;

class ProductCrudController extends AbstractCrudController
{
    // ...

    public function configureCrud(Crud $crud): Crud
    {
        return $crud
            // ...

            ->overrideTemplate('crud/layout', 'admin/advanced_layout.html.twig')

            ->overrideTemplates([
                'crud/field/text' => 'admin/product/field_id.html.twig',
                'label/null' => 'admin/labels/null_product.html.twig',
            ])
        ;
    }
}

字段和操作模板

每个 字段(和每个 操作)都定义了一个 setTemplatePath() 方法来设置用于渲染该特定字段(或操作)的 Twig 模板

1
2
3
4
5
6
7
8
9
TextField::new('...', '...')
    // ...
    ->setTemplatePath('custom_fields/text.html.twig');

// ...

Action::new('...', '...')
    // ...
    ->setTemplatePath('admin/actions/my_custom_action.html.twig');

setTemplatePath() 方法仅适用于在 indexdetail 页面上显示的字段。阅读下一节,了解如何自定义 newedit 页面中的字段,这些页面使用 Symfony 表单。

表单字段模板

EasyAdmin 提供了一个基于 Bootstrap 5 的即用型表单主题。仪表盘和 CRUD 控制器定义了 addFormTheme(string $themePath)setFormThemes(array $themePaths) 方法,以便你可以使用自己的表单主题自定义各个表单字段

想象一个表单字段,你想要包含一个 <a> 元素,该元素链接到其他信息。如果该字段名为 title 并且属于 Product 实体,则配置如下所示

1
2
3
4
5
TextField::new('title')
    // ...
    ->setFormTypeOptions([
        'block_name' => 'custom_title',
    ]);

下一步是定义该字段使用的模板片段,这需要了解 Symfony 定义的表单片段命名规则

1
2
3
4
5
6
7
8
{# templates/admin/form.html.twig #}
{# note that the Twig block name starts with an uppercase letter
   ('_Product_...' instead of '_product_...') because the first part
   of the block name is the unmodified entity name #}
{% block _Product_custom_title_widget %}
    {# ... #}
    <a href="...">More information</a>
{% endblock %}

最后,将此自定义主题添加到用于渲染后端表单的主题列表中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
namespace App\Controller\Admin;

use EasyCorp\Bundle\EasyAdminBundle\Config\Crud;
use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController;

class ProductCrudController extends AbstractCrudController
{
    // ...

    public function configureCrud(Crud $crud): Crud
    {
        return $crud
            // ...

            // don't forget to add EasyAdmin's form theme at the end of the list
            // (otherwise you'll lose all the styles for the rest of form fields)
            ->setFormThemes(['admin/form.html.twig', '@EasyAdmin/crud/form_theme.html.twig'])
        ;
    }
}

注意

你还可以使用原始字段名称覆盖表单 widget。在上面的示例中,它看起来像这样: {% block _Product_title_widget %}。完整语法是: {% block _<Entity name>_<Field name>_widget %}

添加自定义 Web 资源

仪表盘和/或 CRUD 控制器中使用 configureAssets() 方法来添加你自己的 CSS 和 JavaScript 文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
namespace App\Controller\Admin;

use EasyCorp\Bundle\EasyAdminBundle\Config\Assets;
use EasyCorp\Bundle\EasyAdminBundle\Config\Crud;
use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController;

class ProductCrudController extends AbstractCrudController
{
    // ...

    public function configureAssets(Assets $assets): Assets
    {
        return $assets
            // adds the CSS and JS assets associated to the given Webpack Encore entry
            // it's equivalent to adding these inside the <head> element:
            // {{ encore_entry_link_tags('...') }} and {{ encore_entry_script_tags('...') }}
            ->addWebpackEncoreEntry('admin-app')

            // it's equivalent to adding this inside the <head> element:
            // <link rel="stylesheet" href="{{ asset('...') }}">
            ->addCssFile('build/admin.css')
            ->addCssFile('https://example.org/css/admin2.css')

            // it's equivalent to adding this inside the <head> element:
            // <script src="{{ asset('...'') }}"></script>
            ->addJsFile('build/admin.js')
            ->addJsFile('https://example.org/js/admin2.js')

            // use these generic methods to add any code before </head> or </body>
            // the contents are included "as is" in the rendered page (without escaping them)
            ->addHtmlContentToHead('<link rel="dns-prefetch" href="https://assets.example.com">')
            ->addHtmlContentToBody('<script> ... </script>')
            ->addHtmlContentToBody('<!-- generated at '.time().' -->')
        ;
    }
}

3.3

JavaScript 文件和 JavaScript Webpack Encore 条目包含在页面的 <head> 元素中。在之前的 EasyAdmin 版本中,它们包含在 <body> 元素的底部。

如果你需要自定义 <link><script> 标签的 HTML 属性或其他功能,请将 Asset 对象传递给 addCssFile()addJsFile()addWebpackEncoreEntry() 方法

1
2
3
4
5
6
7
8
9
10
11
12
13
use EasyCorp\Bundle\EasyAdminBundle\Config\Asset;
// ...

return $assets
    ->addCssFile(Asset::new('build/admin.css')->preload()->nopush())
    ->addCssFile(Asset::new('build/admin-print.css')->htmlAttr('media', 'print'))

    ->addJsFile(Asset::new('build/admin.js')->defer())
    ->addJsFile(Asset::new('build/admin.js')->preload())
    ->addJsFile(Asset::new('build/admin.js')->htmlAttr('referrerpolicy', 'strict-origin'))

    ->addWebpackEncoreEntry(Asset::new('admin-app')->webpackEntrypointName('...'))
;

提示

字段也可以将 CSS 和 JavaScript 资源添加到渲染的页面中。阅读此部分以了解方法。

注意

如果你想卸载 EasyAdmin 包含的默认资源,请覆盖默认的 layout.html.twig 模板并清空 head_stylesheetshead_javascript Twig 代码块。

自定义后端设计

后端的设计使用了很多 CSS 变量创建。这使你可以更轻松地根据自己的需求进行自定义。你将在 vendor/easycorp/easyadmin-bundle/assets/css/easyadmin-theme/variables-theme.scss 文件中找到所有变量。要覆盖它们中的任何一个,请创建一个 CSS 文件并重新定义变量值

1
2
3
4
5
6
7
8
9
10
11
/* public/css/admin.css */
:root {
    /* make the backend contents as wide as the browser window */
    --body-max-width: 100%;
    /* change the background color of the <body> */
    --body-bg: #f5f5f5;
    /* make the base font size smaller */
    --font-size-base: 13px;
    /* remove all border radius to make corners straight */
    --border-radius: 0px;
}

然后,在你的仪表盘和/或资源管理中加载此 CSS 文件

1
2
3
4
5
6
7
8
9
10
11
12
use EasyCorp\Bundle\EasyAdminBundle\Config\Assets;
use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractDashboardController;

class DashboardController extends AbstractDashboardController
{
    // ...

    public function configureAssets(): Assets
    {
        return Assets::new()->addCssFile('css/admin.css');
    }
}

注意

由于 Bootstrap 样式的定义方式,不可能使用 CSS 变量来覆盖所有样式。有时你可能还需要覆盖一些 Sass 变量的值(这些变量在
assets/css/easyadmin-theme/variables-bootstrap.scss 文件)中定义。

CSS 选择器

每个后端页面的 <body> 元素都包含不同的 idclass 属性,以帮助你定位自己的样式。id 遵循此模式

页面 <body> ID 属性
详情 ea-detail-<实体名称>-<实体 ID>
编辑 ea-edit-<实体名称>-<实体 ID>
列表 ea-index-<实体名称>
新建 ea-new-<实体名称>

例如,如果你正在编辑 User 实体的 id = 200 的元素,则该页面的 <body> 将是 <body id="easyadmin-edit-User-200" ...>

class 属性的模式是不同的,因为它同时应用了多个 CSS 类

页面 <body> CSS 类
详情 ea-detail ea-detail-<实体名称>
编辑 ea-edit ea-edit-<实体名称>
列表 ea-index ea-index-<实体名称>
新建 ea-new ea-new-<实体名称>

例如,如果你正在显示 User 实体元素的列表,则该页面的 <body> 将是 <body class="ea index index-User" ...>

使用 Webpack 管理后端资源

EasyAdmin 使用 Webpack(通过 Symfony 的 Webpack Encore)来管理其 CSS 和 JavaScript 资源。此扩展包同时提供了所有资源的源文件和编译版本,因此你无需安装 Webpack 即可使用此扩展包。

但是,如果你想完全控制后端样式,可以使用 Webpack 集成 assets/ 目录中提供的 SCSS 和 JavaScript 源文件。唯一的缺点是 EasyAdmin 在加载资源时尚未使用 Webpack Encore,因此你无法使用版本控制等功能。这将在未来版本中修复。

本作品,包括代码示例,均根据 Creative Commons BY-SA 3.0 许可协议获得许可。
目录
    版本