Magento2后台如何实现自定义SKU、价格字段及动态更新按钮功能
Magento2 后台自定义商品价格更新功能实现方案
需求说明
- 在后台配置页添加SKU输入框(支持逗号分隔批量输入)、价格、促销价字段
- 管理员输入SKU后,填写新价格/促销价,点击「更新价格」按钮完成商品价格批量更新
- 实现动态交互:点击按钮后异步提交,实时显示操作结果
当前问题
已通过etc/adminhtml/system.xml创建了基础静态字段,但未绑定点击事件、数据提交逻辑,无法完成实际的价格更新操作。
现有代码(system.xml)
<?xml version="1.0"?> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Config:etc/system_file.xsd"> <system> <tab id="irshad_custom" translate="label" sortOrder="10"> <label>自定义标签</label> </tab> <section id="test_section" translate="label" sortOrder="130" showInDefault="1" showInWebsite="1" showInStore="1"> <class>separator-top</class> <label>价格配置</label> <tab>irshad_custom</tab> <resource>Irshad_Ahmad::config_ahmad</resource> <group id="custom_settings" translate="label" sortOrder="10" showInDefault="1" showInWebsite="1" showInStore="1"> <label>价格管理</label> <field id="enable" translate="label" type="select" sortOrder="10" showInDefault="1" showInWebsite="1" showInStore="1"> <label>启用功能</label> <source_model>Magento\Config\Model\Config\Source\Yesno</source_model> </field> <field id="product_sku" translate="label" type="text" sortOrder="20" showInDefault="1" showInWebsite="1" showInStore="1"> <label>商品SKU</label> <comment>支持多个SKU,用逗号分隔</comment> <depends> <field id="enable">1</field> </depends> </field> <field id="price" translate="label" type="text" sortOrder="30" showInDefault="1" showInWebsite="1" showInStore="1"> <label>价格</label> <validate>required-entry validate-number validate-greater-than-zero</validate> <comment>输入新的商品价格</comment> <depends> <field id="enable">1</field> </depends> </field> <field id="sell_price" translate="label" type="text" sortOrder="40" showInDefault="1" showInWebsite="1" showInStore="1"> <label>促销价</label> <validate>validate-number validate-greater-than-zero</validate> <comment>输入新的商品促销价(可选)</comment> <depends> <field id="enable">1</field> </depends> </field> <field id="update_button" translate="label" type="button" sortOrder="50" showInDefault="1" showInWebsite="1" showInStore="1"> <label>更新价格</label> <frontend_model>Irshad\Ahmad\Block\Adminhtml\System\Config\UpdateButton</frontend_model> <depends> <field id="enable">1</field> </depends> </field> </group> </section> </system> </config>
完整实现步骤
1. 给按钮绑定前端交互模型
创建按钮前端模型文件 Irshad/Ahmad/Block/Adminhtml/System/Config/UpdateButton.php:
<?php namespace Irshad\Ahmad\Block\Adminhtml\System\Config; use Magento\Config\Block\System\Config\Form\Field; use Magento\Framework\Data\Form\Element\AbstractElement; class UpdateButton extends Field { protected $_template = 'Irshad_Ahmad::system/config/update_button.phtml'; protected function _getElementHtml(AbstractElement $element) { return $this->_toHtml(); } public function getAjaxUrl() { return $this->getUrl('irshad_ahmad/price/update'); } public function getButtonHtml() { $button = $this->getLayout()->createBlock( \Magento\Backend\Block\Widget\Button::class )->setData([ 'id' => 'update_price_button', 'label' => __('更新价格'), 'class' => 'primary' ]); return $button->toHtml(); } }
创建按钮模板文件 Irshad/Ahmad/view/adminhtml/templates/system/config/update_button.phtml:
<div class="actions"> <?= $block->getButtonHtml() ?> </div> <script type="text/x-magento-init"> { "#update_price_button": { "Irshad_Ahmad/js/update-price": { "ajaxUrl": "<?= $block->getAjaxUrl() ?>", "skuField": "#test_section_custom_settings_product_sku", "priceField": "#test_section_custom_settings_price", "salePriceField": "#test_section_custom_settings_sell_price" } } } </script>
2. 编写前端交互JS逻辑
创建JS文件 Irshad/Ahmad/view/adminhtml/web/js/update-price.js:
define([ 'jquery', 'Magento_Ui/js/modal/alert', 'mage/translate' ], function ($, alert, $t) { 'use strict'; return function (config) { $('#update_price_button').on('click', function () { let sku = $(config.skuField).val().trim(), price = $(config.priceField).val().trim(), salePrice = $(config.salePriceField).val().trim(); if (!sku || !price) { alert({ title: $t('错误'), content: $t('请填写SKU和价格') }); return; } $.ajax({ url: config.ajaxUrl, type: 'POST', data: { form_key: window.FORM_KEY, sku: sku, price: price, sale_price: salePrice }, showLoader: true, success: function (response) { if (response.success) { alert({ title: $t('成功'), content: response.message }); // 清空输入框 $(config.skuField).val(''); $(config.priceField).val(''); $(config.salePriceField).val(''); } else { alert({ title: $t('失败'), content: response.message }); } }, error: function () { alert({ title: $t('错误'), content: $t('请求失败,请稍后重试') }); } }); }); }; });
3. 配置后端路由
创建 Irshad/Ahmad/etc/adminhtml/routes.xml:
<?xml version="1.0"?> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:App/etc/routes.xsd"> <router id="admin"> <route id="irshad_ahmad" frontName="irshad_ahmad"> <module name="Irshad_Ahmad" before="Magento_Backend"/> </route> </router> </config>
4. 编写后端价格更新控制器
创建控制器文件 Irshad/Ahmad/Controller/Adminhtml/Price/Update.php:
<?php namespace Irshad\Ahmad\Controller\Adminhtml\Price; use Magento\Backend\App\Action; use Magento\Backend\App\Action\Context; use Magento\Catalog\Model\ProductRepository; use Magento\Framework\Controller\Result\JsonFactory; use Magento\Framework\Exception\NoSuchEntityException; class Update extends Action { protected $productRepository; protected $resultJsonFactory; public function __construct( Context $context, ProductRepository $productRepository, JsonFactory $resultJsonFactory ) { parent::__construct($context); $this->productRepository = $productRepository; $this->resultJsonFactory = $resultJsonFactory; } protected function _isAllowed() { return $this->_authorization->isAllowed('Irshad_Ahmad::config_ahmad'); } public function execute() { $result = $this->resultJsonFactory->create(); $postData = $this->getRequest()->getPostValue(); if (!$postData || !isset($postData['sku']) || !isset($postData['price'])) { return $result->setData([ 'success' => false, 'message' => __('缺少必要参数') ]); } $skuList = explode(',', trim($postData['sku'])); $price = (float)$postData['price']; $salePrice = isset($postData['sale_price']) ? (float)$postData['sale_price'] : null; $successCount = 0; $errorSkus = []; foreach ($skuList as $sku) { $sku = trim($sku); if (!$sku) continue; try { $product = $this->productRepository->get($sku); $product->setPrice($price); if ($salePrice !== null) { $product->setSpecialPrice($salePrice); } $this->productRepository->save($product); $successCount++; } catch (NoSuchEntityException $e) { $errorSkus[] = $sku . '(商品不存在)'; } catch (\Exception $e) { $errorSkus[] = $sku . '(更新失败:' . $e->getMessage() . ')'; } } $message = __('成功更新 %1 个商品', $successCount); if (!empty($errorSkus)) { $message .= '<br>' . __('以下SKU更新失败:') . '<br>' . implode('<br>', $errorSkus); } return $result->setData([ 'success' => $successCount > 0 || empty($errorSkus), 'message' => $message ]); } }
注意事项
- 确保模块的
registration.php和module.xml配置正确,模块已启用 - 执行命令清理缓存:
bin/magento cache:clean、bin/magento cache:flush - 给管理员角色分配
Irshad_Ahmad::config_ahmad权限
内容的提问来源于stack exchange,提问作者ahmad
相关产品推荐
相关产品推荐

