-- ============================================================ -- 缺口补齐:地址簿 / 反馈 / 收藏 / 售后 / 库存 / 视频 / 订阅模板 / 菜单 -- 幂等;业务表 cc_*,系统表 nl_* -- ============================================================ SET @db := DATABASE(); -- 收货地址 SET @exists := (SELECT COUNT(*) FROM information_schema.TABLES WHERE TABLE_SCHEMA = @db AND TABLE_NAME = 'cc_wx_address'); SET @sql := IF(@exists = 0, 'CREATE TABLE `cc_wx_address` ( `id` int unsigned NOT NULL AUTO_INCREMENT, `user_id` int NOT NULL DEFAULT 0, `name` varchar(50) NOT NULL DEFAULT '''', `phone` varchar(20) NOT NULL DEFAULT '''', `address` varchar(255) NOT NULL DEFAULT '''', `is_default` tinyint NOT NULL DEFAULT 0 COMMENT ''1=默认'', `created_at` int NOT NULL DEFAULT 0, `updated_at` int NOT NULL DEFAULT 0, `deleted_at` int NOT NULL DEFAULT 0, PRIMARY KEY (`id`), KEY `idx_addr_user` (`user_id`, `deleted_at`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT=''小程序收货地址''', 'SELECT ''skip cc_wx_address'' AS msg'); PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt; -- 用户反馈 SET @exists := (SELECT COUNT(*) FROM information_schema.TABLES WHERE TABLE_SCHEMA = @db AND TABLE_NAME = 'cc_feedback'); SET @sql := IF(@exists = 0, 'CREATE TABLE `cc_feedback` ( `id` int unsigned NOT NULL AUTO_INCREMENT, `user_id` int NOT NULL DEFAULT 0, `content` varchar(500) NOT NULL DEFAULT '''', `images` varchar(1000) NOT NULL DEFAULT '''' COMMENT ''图 URL,逗号分隔'', `reply` varchar(500) NOT NULL DEFAULT '''', `status` tinyint NOT NULL DEFAULT 0 COMMENT ''0=待处理 1=已回复'', `created_at` int NOT NULL DEFAULT 0, `updated_at` int NOT NULL DEFAULT 0, `deleted_at` int NOT NULL DEFAULT 0, PRIMARY KEY (`id`), KEY `idx_fb_user` (`user_id`, `status`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT=''用户反馈''', 'SELECT ''skip cc_feedback'' AS msg'); PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt; -- 收藏 SET @exists := (SELECT COUNT(*) FROM information_schema.TABLES WHERE TABLE_SCHEMA = @db AND TABLE_NAME = 'cc_favorite'); SET @sql := IF(@exists = 0, 'CREATE TABLE `cc_favorite` ( `id` int unsigned NOT NULL AUTO_INCREMENT, `user_id` int NOT NULL DEFAULT 0, `catalogue_id` int NOT NULL DEFAULT 0, `created_at` int NOT NULL DEFAULT 0, `updated_at` int NOT NULL DEFAULT 0, `deleted_at` int NOT NULL DEFAULT 0, PRIMARY KEY (`id`), KEY `idx_fav_user` (`user_id`, `deleted_at`), KEY `idx_fav_cat` (`catalogue_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT=''商品收藏''', 'SELECT ''skip cc_favorite'' AS msg'); PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt; -- 售后 SET @exists := (SELECT COUNT(*) FROM information_schema.TABLES WHERE TABLE_SCHEMA = @db AND TABLE_NAME = 'cc_after_sale'); SET @sql := IF(@exists = 0, 'CREATE TABLE `cc_after_sale` ( `id` int unsigned NOT NULL AUTO_INCREMENT, `order_id` int NOT NULL DEFAULT 0, `user_id` int NOT NULL DEFAULT 0, `reason` varchar(255) NOT NULL DEFAULT '''', `amount` int NOT NULL DEFAULT 0 COMMENT ''申请退款金额(分)'', `images` varchar(1000) NOT NULL DEFAULT '''', `status` tinyint NOT NULL DEFAULT 0 COMMENT ''0=待审 1=通过 2=拒绝'', `admin_remark` varchar(255) NOT NULL DEFAULT '''', `created_at` int NOT NULL DEFAULT 0, `updated_at` int NOT NULL DEFAULT 0, `deleted_at` int NOT NULL DEFAULT 0, PRIMARY KEY (`id`), KEY `idx_as_order` (`order_id`), KEY `idx_as_user` (`user_id`, `status`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT=''售后申请''', 'SELECT ''skip cc_after_sale'' AS msg'); PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt; -- 商品视频 SET @col := (SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = @db AND TABLE_NAME = 'cc_catalogue' AND COLUMN_NAME = 'video'); SET @sql := IF(@col = 0, 'ALTER TABLE `cc_catalogue` ADD COLUMN `video` varchar(500) NOT NULL DEFAULT '''' COMMENT ''商品视频'' AFTER `pdf`', 'SELECT ''skip cc_catalogue.video'' AS msg'); PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt; -- 规格库存:-1=不限 SET @col := (SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = @db AND TABLE_NAME = 'cc_price_sheet' AND COLUMN_NAME = 'stock'); SET @sql := IF(@col = 0, 'ALTER TABLE `cc_price_sheet` ADD COLUMN `stock` int NOT NULL DEFAULT -1 COMMENT ''库存,-1不限'' AFTER `routine`', 'SELECT ''skip cc_price_sheet.stock'' AS msg'); PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt; -- 订阅消息模板 SET @col := (SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = @db AND TABLE_NAME = 'nl_wx_app' AND COLUMN_NAME = 'subscribe_pay_tpl'); SET @sql := IF(@col = 0, 'ALTER TABLE `nl_wx_app` ADD COLUMN `subscribe_pay_tpl` varchar(64) NOT NULL DEFAULT '''' COMMENT ''付款成功订阅模板'' AFTER `package_enabled`', 'SELECT ''skip nl_wx_app.subscribe_pay_tpl'' AS msg'); PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt; SET @col := (SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = @db AND TABLE_NAME = 'nl_wx_app' AND COLUMN_NAME = 'subscribe_ship_tpl'); SET @sql := IF(@col = 0, 'ALTER TABLE `nl_wx_app` ADD COLUMN `subscribe_ship_tpl` varchar(64) NOT NULL DEFAULT '''' COMMENT ''发货订阅模板'' AFTER `subscribe_pay_tpl`', 'SELECT ''skip nl_wx_app.subscribe_ship_tpl'' AS msg'); PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt; -- 套餐菜单(若 lgp:menu-sync 未跑过) SET @parent_id := (SELECT id FROM nl_menu WHERE name = 'Goods' AND deleted_at = 0 LIMIT 1); SET @exists := (SELECT COUNT(*) FROM nl_menu WHERE name = 'GoodsPackage' AND deleted_at = 0); SET @sql := IF(@parent_id IS NOT NULL AND @exists = 0, CONCAT( 'INSERT INTO `nl_menu` (`title`,`icon`,`name`,`path`,`component`,`redirect`,`keep_alive`,`hide_in_menu`,`affix_tab`,`badge`,`badge_type`,`badge_variants`,`iframe_src`,`pid`,`sort`,`query`,`created_at`,`updated_at`,`deleted_at`) VALUES (', '''套餐搭配'', ''lucide:package'', ''GoodsPackage'', ''/goods/package'', ''/goods/package/index'', '''', 1, 0, 1, '''', 0, 0, '''', ', @parent_id, ', 6, '''', UNIX_TIMESTAMP(), UNIX_TIMESTAMP(), 0)' ), 'SELECT ''skip menu GoodsPackage'' AS msg'); PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt; -- 反馈 / 售后菜单 SET @parent_id := (SELECT id FROM nl_menu WHERE name = 'Customer' AND deleted_at = 0 LIMIT 1); SET @exists := (SELECT COUNT(*) FROM nl_menu WHERE name = 'CustomerFeedback' AND deleted_at = 0); SET @sql := IF(@parent_id IS NOT NULL AND @exists = 0, CONCAT( 'INSERT INTO `nl_menu` (`title`,`icon`,`name`,`path`,`component`,`redirect`,`keep_alive`,`hide_in_menu`,`affix_tab`,`badge`,`badge_type`,`badge_variants`,`iframe_src`,`pid`,`sort`,`query`,`created_at`,`updated_at`,`deleted_at`) VALUES (', '''用户反馈'', ''lucide:message-square'', ''CustomerFeedback'', ''/customer/feedback'', ''/customer/feedback/index'', '''', 1, 0, 1, '''', 0, 0, '''', ', @parent_id, ', 5, '''', UNIX_TIMESTAMP(), UNIX_TIMESTAMP(), 0)' ), 'SELECT ''skip menu CustomerFeedback'' AS msg'); PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt; SET @exists := (SELECT COUNT(*) FROM nl_menu WHERE name = 'CustomerAfterSale' AND deleted_at = 0); SET @sql := IF(@parent_id IS NOT NULL AND @exists = 0, CONCAT( 'INSERT INTO `nl_menu` (`title`,`icon`,`name`,`path`,`component`,`redirect`,`keep_alive`,`hide_in_menu`,`affix_tab`,`badge`,`badge_type`,`badge_variants`,`iframe_src`,`pid`,`sort`,`query`,`created_at`,`updated_at`,`deleted_at`) VALUES (', '''售后管理'', ''lucide:undo-2'', ''CustomerAfterSale'', ''/customer/after-sale'', ''/customer/after-sale/index'', '''', 1, 0, 1, '''', 0, 0, '''', ', @parent_id, ', 6, '''', UNIX_TIMESTAMP(), UNIX_TIMESTAMP(), 0)' ), 'SELECT ''skip menu CustomerAfterSale'' AS msg'); PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt; -- 有微信用户菜单的角色同步新菜单 SET @wx_user_menu_id := (SELECT id FROM nl_menu WHERE name = 'CustomerWxUser' AND deleted_at = 0 LIMIT 1); SET @menu_id := (SELECT id FROM nl_menu WHERE name = 'CustomerFeedback' AND deleted_at = 0 LIMIT 1); INSERT INTO `nl_role_menu_relations` (`role_id`, `menu_id`, `created_at`) SELECT r.role_id, @menu_id, UNIX_TIMESTAMP() FROM `nl_role_menu_relations` r WHERE @menu_id IS NOT NULL AND @wx_user_menu_id IS NOT NULL AND r.menu_id = @wx_user_menu_id AND NOT EXISTS (SELECT 1 FROM `nl_role_menu_relations` x WHERE x.role_id = r.role_id AND x.menu_id = @menu_id); SET @menu_id := (SELECT id FROM nl_menu WHERE name = 'CustomerAfterSale' AND deleted_at = 0 LIMIT 1); INSERT INTO `nl_role_menu_relations` (`role_id`, `menu_id`, `created_at`) SELECT r.role_id, @menu_id, UNIX_TIMESTAMP() FROM `nl_role_menu_relations` r WHERE @menu_id IS NOT NULL AND @wx_user_menu_id IS NOT NULL AND r.menu_id = @wx_user_menu_id AND NOT EXISTS (SELECT 1 FROM `nl_role_menu_relations` x WHERE x.role_id = r.role_id AND x.menu_id = @menu_id); SET @cat_menu := (SELECT id FROM nl_menu WHERE name = 'GoodsCatalogue' AND deleted_at = 0 LIMIT 1); SET @pkg_menu := (SELECT id FROM nl_menu WHERE name = 'GoodsPackage' AND deleted_at = 0 LIMIT 1); INSERT INTO `nl_role_menu_relations` (`role_id`, `menu_id`, `created_at`) SELECT r.role_id, @pkg_menu, UNIX_TIMESTAMP() FROM `nl_role_menu_relations` r WHERE @pkg_menu IS NOT NULL AND @cat_menu IS NOT NULL AND r.menu_id = @cat_menu AND NOT EXISTS (SELECT 1 FROM `nl_role_menu_relations` x WHERE x.role_id = r.role_id AND x.menu_id = @pkg_menu);