mcpField
S
spree-admin

spree-admin

github.com/spree开发10123 次安装4 周前更新
代码仓库

关于 spree-admin

spree-admin 是面向开发者的技能,用于定制 Spree 5.x 中基于 Rails 的旧版管理界面,涵盖资源脚手架以及导航、表格、视图和控制器调整。

主要功能

  1. 01生成 CRUD 管理界面脚手架
  2. 02定制侧边栏导航
  3. 03配置表格列
  4. 04覆盖视图并注入局部模板
  5. 05使用管理界面表单辅助工具

适用场景

  1. 01为模型添加管理界面
  2. 02调整管理列表和导航
  3. 03通过自定义视图扩展管理页面

安装

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

$npx skills add https://github.com/spree/agent-skills --skill spree-admin

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

详细介绍

Spree 旧版 Rails 管理后台(spree_admin)

以下命令使用 Spree CLI 形式(spree …、Docker)。对于没有 CLI 的经典 Rails 应用(通常是 5.4 之前的版本),请使用 spree-project 技能中的原生映射——在应用根目录下使用 bin/rails / bundle exec rake,路径不带 backend/ 前缀。

管理后台是一个 Rails 引擎——使用 ERB 视图在服务器端渲染,通过 Stimulus + Turbo 提供交互功能,并使用 Tailwind 设置样式。(Spree 6.0 将引入基于 React 的新管理后台;在 Spree 5.x 中,spree_admin 就是管理后台。)

项目布局

Rails 管理后台位于 spree_admin gem 中,挂载在 /admin。可将其视作普通 Rails 应用:

spree_admin gem
├── app/
│   ├── controllers/spree/admin/         # admin controllers
│   ├── views/spree/admin/<resource>/    # ERB views per resource
│   ├── helpers/spree/admin/             # view helpers
│   ├── presenters/spree/admin/          # presenter pattern for complex views
│   ├── javascript/spree/admin/          # Stimulus controllers, importmap-managed
│   └── models/spree/admin/navigation*   # nav + nav builder
└── lib/generators/spree/admin/
    ├── install/                         # bin/rails g spree:admin:install
    └── scaffold/                        # bin/rails g spree:admin:scaffold

在宿主应用(backend/)中,可在 backend/app/ 下相同路径覆盖文件以进行自定义。Rails 视图路径解析会优先使用宿主应用中的文件,而非 gem 中的文件。

添加新的管理资源(单命令方式)

Spree 提供了管理后台脚手架生成器,可为任何模型生成完整的 CRUD 管理后台。在模型和迁移创建完成后(使用 spree:api_resource 或 spree:model):

spree rails g spree:admin:scaffold Spree::Brand

此命令会生成:

文件用途
backend/app/controllers/spree/admin/brands_controller.rb继承自 Spree::Admin::ResourceController 的控制器
backend/app/views/spree/admin/brands/index.html.erb列表页(渲染 render_table @collection, :brands;列来自表格注册表)
backend/app/views/spree/admin/brands/new.html.erb创建表单页
backend/app/views/spree/admin/brands/edit.html.erb编辑表单页
backend/app/views/spree/admin/brands/_form.html.erb共用表单局部模板
backend/config/initializers/spree_admin_brands_table.rb表格列注册
backend/config/initializers/spree_admin_brands_navigation.rb侧边栏导航注册
backend/config/routes.rb将 namespace :admin { resources :brands } 注入 add_routes 块

生成器还会将路由注入 backend/config/routes.rb 中的 Spree::Core::Engine.add_routes do 块(该块存在于 spree-starter 模板中)。如果你的 routes.rb 中没有这个块,请手动添加路由:

# backend/config/routes.rb
Rails.application.routes.draw do
  Spree::Core::Engine.add_routes do
    namespace :admin do
      resources :brands
    end
  end

  mount Spree::Core::Engine, at: '/'
end

应使用 add_routes(而不是原始的 Spree::Core::Engine.routes.append),这是受支持的机制——它可以防止应用重新加载时重复绘制路由。

(如果你使用 spree:api_resource 创建 API,API 路由与管理后台路由相互独立,位于不同的命名空间中。)

重启 Rails 以加载新的初始化器和路由:

spree restart

自定义侧边栏

侧边栏条目在初始化器中注册。示例:

# backend/config/initializers/spree_admin_brands_navigation.rb
Rails.application.config.after_initialize do
  Spree.admin.navigation.sidebar.add :brands,
    label: :brands,                                       # i18n key or string
    url: :admin_brands_path,                              # symbol → route helper, or string
    icon: 'list',                                         # Tabler icon name (https://tabler.io/icons)
    position: 55,                                         # lower = earlier in sidebar
    active: -> { controller_name == 'brands' },           # when to highlight
    if: -> { can?(:manage, Spree::Brand) }                # CanCanCan visibility check
end

常见导航模式:

# Top-level item that opens a sub-menu
Spree.admin.navigation.sidebar.add :marketing, label: :marketing, position: 30 do |nav|
  nav.add :promotions, label: :promotions, url: :admin_promotions_path, position: 10
  nav.add :coupon_codes, label: :coupon_codes, url: :admin_coupon_codes_path, position: 20
end

# Remove an existing entry
Spree.admin.navigation.sidebar.remove :reports

# Reorder an existing entry
Spree.admin.navigation.sidebar.update :products, position: 5

完整的导航 API 位于 spree/admin/app/models/spree/admin/navigation.rb,需要时可查看源代码。

自定义管理后台表格

大多数管理后台列表页(Products、Orders、Promotions 等)都使用已注册的表格定义——请查看 gem 的 config/initializers/spree_admin_tables.rb,了解已注册的键(注意:Customers 页面注册为 :users;Payment Methods 等少数页面不使用表格注册表)。可通过初始化器添加、移除或重新排列列:

# backend/config/initializers/spree_admin_products_table_customization.rb
Rails.application.config.after_initialize do
  # Add a column to the existing Products table
  Spree.admin.tables.products.add :brand_name,
    label: :brand,                                        # i18n key
    type: :string,                                        # :string | :number | :date | :datetime | :money | :status | :link | :boolean | :image | :custom | :association
    sortable: true,
    filterable: true,
    default: true,                                        # visible by default (vs opt-in via column toggle)
    position: 25

  # Remove a column
  Spree.admin.tables.products.remove :sku

  # Update an existing column
  Spree.admin.tables.products.update :name, label: :product_name
end

对于自行生成的表格(通过 spree:admin:scaffold),生成的初始化器会提供合理的默认值——name、created_at、updated_at。在其中添加特定于业务领域的列。

自定义列渲染:如果列的值不是直接属性,请在模型或 presenter/decorator 中定义方法。列的键(add 的第一个参数)默认用作查找方法;传入 method: 可指定其他方法名或接收记录的 lambda。例如,如果你在 Products 表格中添加 brand_name 列,请在 Product 模型或 presenter 中定义 brand_name:

# In your model or decorator
def brand_name
  brand&.name
end

覆盖视图

将同路径的文件放入宿主应用,Rails 就会使用它。gem 提供 spree/admin/app/views/spree/admin/products/index.html.erb;你可以在 backend/app/views/spree/admin/products/index.html.erb 中覆盖它。

需要注意两点:

  1. 先复制完整文件,再进行编辑。部分覆盖不起作用——Rails 会完全采用宿主应用中的文件。使用 bundle show spree_admin 查找 gem 中的视图源文件。

  2. 视图文件包含用于交互行为的 data-controller Stimulus 绑定。如果删除 data-controller="…" 属性,相关 JS 就会停止工作。除非你要明确替换这些绑定,否则请保留它们。

如需进行轻量级覆盖,请使用管理后台的具名注入点,而不是覆盖整个视图。视图会通过 render_admin_partials 渲染已注册的局部视图列表(例如 head、body_end、products_header、product_form)。创建局部视图(例如 backend/app/views/spree/admin/shared/_my_banner.html.erb),并在初始化程序中注册:

Rails.application.config.after_initialize do
  Spree.admin.partials.body_end << 'spree/admin/shared/my_banner'
end

在控制台中使用 Spree.admin.partials.keys 列出所有注入点。

构建管理后台 UI——表单构建器、组件和辅助方法

编写管理后台视图或局部视图时(例如脚手架生成的资源表单、注入的 product_form 区块或覆盖的视图),请使用管理后台自己的 UI 规范,而不是原始 Rails 辅助方法——这样就能轻松获得一致的样式、标签、错误显示和 i18n。

表单构建器(重要)

每个管理后台 form_with 都会自动使用 Spree::Admin::FormBuilder(管理后台 BaseController 中的 default_form_builder)——无需进行任何设置:

<%= form_with model: [:admin, @brand] do |f| %>
  <%= f.spree_text_field :name, required: true %>
  <%= f.spree_text_field :code, help: "Leave blank to auto-generate" %>
  <%= f.spree_money_field :price, currency: current_store.default_currency %>
  <%= f.spree_collection_select :tax_category_id, Spree::TaxCategory.all, :id, :name,
        { include_blank: true, autocomplete: true }, {} %>
  <%= f.spree_check_box :active %>
  <%= f.spree_file_field :logo, width: 240, height: 240 %>
<% end %>

完整的方法集:spree_text_field、spree_number_field、spree_money_field(分隔符会根据区域设置调整,提交时会规范化为小数,并追加货币符号)、spree_email_field、spree_date_field、spree_datetime_field、spree_text_area(会自动调整高度)、spree_rich_text_area(Trix)、spree_select / spree_collection_select(传入 autocomplete: true 可启用可搜索下拉菜单——选项达到 20 个或以上时,任何选择框都可以使用它)、spree_check_box、spree_radio_button(传入明确的 :id,即可将标签绑定到指定单选按钮;否则会根据值匹配标签)、spree_file_field(支持拖放、预览、crop: true 和 allowed_file_types:)。

所有方法的常用选项:label:(字符串,或使用 false 隐藏标签)、required:(显示星号)、help:(字段下方的文本)、help_bubble:(标签旁的工具提示图标)、class:。验证错误会自动显示在字段下方;标签通过 i18n 解析(先查找 spree.<attribute>,再查找 activerecord.attributes.spree/<model>.<attribute>)。

UI 组件

由辅助方法渲染、符合管理后台设计系统的组件——请使用它们,而不是手写标记:

组件辅助方法
下拉菜单dropdown { dropdown_toggle + dropdown_menu }
对话框(模态框)/ 抽屉(侧边面板)dialog_header、dialog_close_button、dialog_discard_button;drawer_header、drawer_close_button
图标icon('plus') — Tabler 图标名称
带备用图像的图片spree_image_tag
工具提示tooltip、help_bubble
状态徽章active_badge(condition)
头像、剪贴板复制、进度条render_avatar、clipboard_component / clipboard_button、progress_bar_component
按店铺时区显示日期spree_date、spree_time、spree_time_ago、local_time
值得了解的视图辅助方法
  • 导航/链接: link_to_with_icon、link_to_edit、link_to_delete(内置 Turbo 确认)、button、external_link_to、page_header_back_button
  • Turbo: turbo_save_button_tag(提交时显示保存状态)、turbo_render_alerts、turbo_close_dialog
  • 上下文: current_store、current_currency、try_spree_current_user、supported_currencies
  • 模型偏好设置: preference_fields / preference_field_for — 自动为模型的 preference :x 声明渲染表单输入项(支付方式和商店设置表单就是这样构建的)

完整参考文档位于本地文档中:node_modules/@spree/docs/dist/developer/admin/form-builder.md、components.md 和 helper-methods.md。

装饰管理控制器

Spree 管理控制器是普通的 Rails 控制器 — 可以像装饰其他控制器一样装饰它们。使用 spree generate controller_decorator Spree::Admin::ProductsController 生成文件 — 它会生成 backend/app/controllers/spree/admin/products_controller_decorator.rb,其中包含 prepended 钩子和 prepend 配置(生成器会嵌套模块,并将完整限定的 prepend 行放在外部;这种手写的等效形式更紧凑):

# backend/app/controllers/spree/admin/products_controller_decorator.rb
module Spree::Admin::ProductsControllerDecorator
  def self.prepended(base)
    base.before_action :my_custom_check, only: [:create, :update]
  end

  private

  def my_custom_check
    # ...
  end
end

Spree::Admin::ProductsController.prepend Spree::Admin::ProductsControllerDecorator

这比自定义导航/表格影响更大 — 只有在需要更改操作行为时才使用。请先确认订阅器(用于副作用)或服务替换(用于业务逻辑)是否可行。完整的自定义决策树请参阅 spree-project 技能。

Stimulus 控制器 — 管理界面交互

Rails 管理界面使用 Stimulus + Turbo 实现客户端交互。现有控制器位于 spree_admin/app/javascript/spree/admin/controllers/:

控制器功能
sidebar_controller.js侧边栏切换 + 持久化
variants_form_controller.js在产品编辑页面管理变体
page_builder_controller.js拖放式 CMS 页面构建器
bulk_editor_controller.js多行表格编辑
dropdown_controller.js下拉菜单

要添加自己的 Stimulus 控制器,将其放在 backend/app/javascript/controllers/,并通过 importmap(backend/config/importmap.rb)注册。在视图中使用 data-controller="my-controller" 引用它。

对于 Turbo Streams(服务端推送的 UI 更新),与任何 Rails 7+ Hotwire 应用一样,渲染控制器中的 turbo_stream.*,并通过 ID 指定目标 frame。

决策树:要进行哪种管理界面更改?

想要……使用
添加指向自有页面的侧边栏项目在初始化程序中使用 Spree.admin.navigation.sidebar.add
向管理表格添加列在初始化程序中使用 Spree.admin.tables.<name>.add
添加新的资源 CRUD 区块bin/rails g spree:admin:scaffold Spree::YourModel
编写或编辑表单使用 f.spree_* 表单构建器方法 — 参见上文“构建管理界面”
添加模态框 / 下拉菜单 / 徽章 / 工具提示使用组件辅助方法 — 参见上文“构建管理界面”
更改现有页面的外观覆盖 backend/app/views/spree/admin/... 中的视图
向控制器添加新操作装饰器(最后手段 — 请先参阅 spree-project 技能)
让表单字段支持交互Stimulus 控制器 + 视图中的 data-controller="..."
向界面推送实时更新通过订阅器或服务广播 Turbo Stream
全局更改管理界面样式编辑 backend/app/assets/tailwind/spree_admin.css(由安装程序创建)— 它从 app/assets/tailwind/spree/admin/index.css 导入 gem 的基础样式;在此添加 @theme 覆盖和自定义 Tailwind 样式

进一步阅读

  • **管理后台源码:**运行 bundle show spree_admin 查找已安装 gem 的路径。gem 根目录下的 README 介绍了设计理念。
  • 自定义文档:node_modules/@spree/docs/dist/developer/admin/ 介绍了相关模式。
  • 导航 API:Spree::Admin::Navigation 源码——导航自定义的完整方法列表。
  • **表格 API:**gem 内的 Spree::Admin::Table(app/models/spree/admin/table.rb)和 Spree::Admin::Table::Column(app/models/spree/admin/table/column.rb)——列类型、选项以及排序/筛选详情。Spree.admin.tables 背后的注册表是 lib/spree/admin/engine.rb 中的 Spree::Admin::Engine::TablesEnvironment。
  • 脚手架生成器:bundle show spree_admin/lib/generators/spree/admin/scaffold/ 中包含可复制用于高级自定义的模板文件。
  • 表单构建器 / 组件 / 辅助方法:node_modules/@spree/docs/dist/developer/admin/form-builder.md、components.md、helper-methods.md——其中列出了上文“构建管理后台 UI”部分涉及的所有选项。

评论

支持 Markdown