From 2b3f30d057f4f351782b84c9b76a7a55ccc670e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=90=B4=E6=98=8A=E5=A4=A9?= <442384644@qq.com> Date: Fri, 23 Oct 2026 09:59:48 +0800 Subject: [PATCH] =?UTF-8?q?fix(=E6=95=B0=E6=8D=AE=E5=BA=93):=20=E4=B8=BA?= =?UTF-8?q?=E8=8F=9C=E5=8D=95=E8=A1=A8=E6=B7=BB=E5=8A=A0=E5=94=AF=E4=B8=80?= =?UTF-8?q?=E9=94=AE=E6=94=AF=E6=8C=81=EF=BC=8C=E9=80=82=E9=85=8D=20MySQL?= =?UTF-8?q?=205.7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/crmeb/module/BaseModuleInstaller.php | 17 +++++++++++++++-- backend/public/install/crmeb_table.sql | 3 ++- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/backend/crmeb/module/BaseModuleInstaller.php b/backend/crmeb/module/BaseModuleInstaller.php index 14306e1f8..fbf2be5a1 100644 --- a/backend/crmeb/module/BaseModuleInstaller.php +++ b/backend/crmeb/module/BaseModuleInstaller.php @@ -1608,14 +1608,27 @@ abstract class BaseModuleInstaller implements ModuleInstallerInterface ); $database = (string)config('database.connections.mysql.database'); + // MySQL 5.7 不支持函数索引,改用 STORED 生成列 + 普通唯一索引。 + // NULLIF 生成 NULL,允许空 key 重复;非空 key 仍由唯一索引约束。 + $generatedColumn = Db::query( + 'SELECT 1 FROM information_schema.columns' + . ' WHERE table_schema = ? AND table_name = ? AND column_name = ? LIMIT 1', + [$database, $fullTable, 'menu_key_unique'] + ); + if (empty($generatedColumn)) { + Db::execute( + "ALTER TABLE `{$fullTable}` ADD COLUMN `menu_key_unique` varchar(190) " + . "GENERATED ALWAYS AS (NULLIF(`menu_key`, '')) STORED " + . "COMMENT '菜单稳定标识唯一键(空值不参与唯一约束)' AFTER `menu_key`" + ); + } $index = Db::query( 'SELECT 1 FROM information_schema.statistics' . ' WHERE table_schema = ? AND table_name = ? AND index_name = ? LIMIT 1', [$database, $fullTable, 'uk_menu_key'] ); if (empty($index)) { - // NULLIF 允许极端中断场景暂存空 key,所有正常写入仍受唯一约束。 - Db::execute("ALTER TABLE `{$fullTable}` ADD UNIQUE KEY `uk_menu_key` ((NULLIF(`menu_key`, ''))) "); + Db::execute("ALTER TABLE `{$fullTable}` ADD UNIQUE KEY `uk_menu_key` (`menu_key_unique`)"); } } diff --git a/backend/public/install/crmeb_table.sql b/backend/public/install/crmeb_table.sql index 84fb39121..28c80e283 100755 --- a/backend/public/install/crmeb_table.sql +++ b/backend/public/install/crmeb_table.sql @@ -1799,6 +1799,7 @@ CREATE TABLE IF NOT EXISTS `eb_system_menus` ( `is_header` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否顶部菜单1是0否', `unique_auth` varchar(150) NOT NULL DEFAULT '' COMMENT '前台唯一标识', `menu_key` varchar(190) NOT NULL DEFAULT '' COMMENT '菜单稳定标识,系统生成且不可修改', + `menu_key_unique` varchar(190) GENERATED ALWAYS AS (NULLIF(`menu_key`, '')) STORED COMMENT '菜单稳定标识唯一键(空值不参与唯一约束)', `is_del` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否删除', `mark` varchar(500) NOT NULL DEFAULT '' COMMENT '备注', `owner_plugin_id` varchar(96) NOT NULL DEFAULT '' COMMENT '所属插件复合标识,空为核心菜单', @@ -1807,7 +1808,7 @@ CREATE TABLE IF NOT EXISTS `eb_system_menus` ( KEY `is_show` (`is_show`) USING BTREE, KEY `access` (`access`) USING BTREE, KEY `idx_owner_plugin_id` (`owner_plugin_id`), - UNIQUE KEY `uk_menu_key` ((NULLIF(`menu_key`, ''))) + UNIQUE KEY `uk_menu_key` (`menu_key_unique`) ) ENGINE=InnoDB AUTO_INCREMENT=4961 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC COMMENT='菜单表'; -- eb_system_pem:证书表