yys 1 settimana fa
parent
commit
d54d62b90b

+ 8 - 4
fs-admin-saas/src/main/java/com/fs/tenant/TenantInfoController.java

@@ -176,14 +176,18 @@ public class TenantInfoController extends BaseController
         List<Long> selected = menuDto.getSelected();
         List<Long> unSelected = menuDto.getUnSelected();
         if ("sys".equals(menuDto.getFlag())) {
-            List<SysMenu> addSysMenu = getAddSysMenu(tenantInfo, menuDto.getSelected());
+            List<SysMenu> allTemplateMenus = tenantInfoMapper.selectMenuList(new SysMenu());
+            List<Long> expandedSelected = tenantInfoService.expandSysMenuIdsWithAncestors(selected, allTemplateMenus);
+            List<SysMenu> addSysMenu = getAddSysMenu(tenantInfo, expandedSelected);
             tenantDataSourceManager.switchTenant(tenantInfo);
-            return tenantInfoService.menuEdit(selected, unSelected, menuDto.getFlag(),addSysMenu,null);
+            return tenantInfoService.menuEdit(expandedSelected, unSelected, menuDto.getFlag(), addSysMenu, null);
         }
 
-        List<TenantCompanyMenu> addCompanyMenu = getAddCompanyMenu(tenantInfo, menuDto.getSelected());
+        List<TenantCompanyMenu> allTemplateMenus = tenantInfoMapper.selectCompanyMenuList(new TenantCompanyMenu());
+        List<Long> expandedSelected = tenantInfoService.expandComMenuIdsWithAncestors(selected, allTemplateMenus);
+        List<TenantCompanyMenu> addCompanyMenu = getAddCompanyMenu(tenantInfo, expandedSelected);
         tenantDataSourceManager.switchTenant(tenantInfo);
-        return tenantInfoService.menuEdit(selected, unSelected, menuDto.getFlag(),null,addCompanyMenu);
+        return tenantInfoService.menuEdit(expandedSelected, unSelected, menuDto.getFlag(), null, addCompanyMenu);
     }
 
 

+ 14 - 4
fs-admin/src/main/java/com/fs/admin/controller/CompanyAdminController.java

@@ -286,13 +286,23 @@ public class CompanyAdminController extends BaseController {
         }
 
         if ("sys".equals(flag)) {
-            List<SysMenu> assignSysMenu = tenantContextHelper.executeInMaster(() -> loadMasterSysMenus(selected));
+            List<SysMenu> allTemplateMenus = tenantContextHelper.executeInMaster(
+                    () -> tenantInfoMapper.selectMenuList(new SysMenu()));
+            List<Long> expandedSelected = tenantInfoService.expandSysMenuIdsWithAncestors(selected, allTemplateMenus);
+            List<SysMenu> assignSysMenu = tenantContextHelper.executeInMaster(
+                    () -> loadMasterSysMenus(expandedSelected));
+            List<Long> finalSelected = expandedSelected;
             return tenantContextHelper.executeInTenant(tenantInfo,
-                    () -> tenantInfoService.menuAssignReplace(selected, flag, assignSysMenu, null));
+                    () -> tenantInfoService.menuAssignReplace(finalSelected, flag, assignSysMenu, null));
         }
-        List<TenantCompanyMenu> assignCompanyMenu = tenantContextHelper.executeInMaster(() -> loadMasterCompanyMenus(selected));
+        List<TenantCompanyMenu> allTemplateMenus = tenantContextHelper.executeInMaster(
+                () -> tenantInfoMapper.selectCompanyMenuList(new TenantCompanyMenu()));
+        List<Long> expandedSelected = tenantInfoService.expandComMenuIdsWithAncestors(selected, allTemplateMenus);
+        List<TenantCompanyMenu> assignCompanyMenu = tenantContextHelper.executeInMaster(
+                () -> loadMasterCompanyMenus(expandedSelected));
+        List<Long> finalSelected = expandedSelected;
         return tenantContextHelper.executeInTenant(tenantInfo,
-                () -> tenantInfoService.menuAssignReplace(selected, flag, null, assignCompanyMenu));
+                () -> tenantInfoService.menuAssignReplace(finalSelected, flag, null, assignCompanyMenu));
     }
 
     /** 主库 tenant_sys_menu 模板 */

+ 8 - 4
fs-admin/src/main/java/com/fs/admin/controller/tenant/TenantInfoController.java

@@ -177,14 +177,18 @@ public class TenantInfoController extends BaseController
         List<Long> selected = menuDto.getSelected();
         List<Long> unSelected = menuDto.getUnSelected();
         if ("sys".equals(menuDto.getFlag())) {
-            List<SysMenu> addSysMenu = getAddSysMenu(tenantInfo, menuDto.getSelected());
+            List<SysMenu> allTemplateMenus = tenantInfoMapper.selectMenuList(new SysMenu());
+            List<Long> expandedSelected = tenantInfoService.expandSysMenuIdsWithAncestors(selected, allTemplateMenus);
+            List<SysMenu> addSysMenu = getAddSysMenu(tenantInfo, expandedSelected);
             tenantDataSourceManager.switchTenant(tenantInfo);
-            return tenantInfoService.menuEdit(selected, unSelected, menuDto.getFlag(),addSysMenu,null);
+            return tenantInfoService.menuEdit(expandedSelected, unSelected, menuDto.getFlag(), addSysMenu, null);
         }
 
-        List<TenantCompanyMenu> addCompanyMenu = getAddCompanyMenu(tenantInfo, menuDto.getSelected());
+        List<TenantCompanyMenu> allTemplateMenus = tenantInfoMapper.selectCompanyMenuList(new TenantCompanyMenu());
+        List<Long> expandedSelected = tenantInfoService.expandComMenuIdsWithAncestors(selected, allTemplateMenus);
+        List<TenantCompanyMenu> addCompanyMenu = getAddCompanyMenu(tenantInfo, expandedSelected);
         tenantDataSourceManager.switchTenant(tenantInfo);
-        return tenantInfoService.menuEdit(selected, unSelected, menuDto.getFlag(),null,addCompanyMenu);
+        return tenantInfoService.menuEdit(expandedSelected, unSelected, menuDto.getFlag(), null, addCompanyMenu);
     }
 
 

+ 14 - 4
fs-agent/src/main/java/com/fs/admin/controller/CompanyAdminController.java

@@ -227,13 +227,23 @@ public class CompanyAdminController extends BaseController {
         }
 
         if ("sys".equals(flag)) {
-            List<SysMenu> assignSysMenu = tenantContextHelper.executeInMaster(() -> loadMasterSysMenus(selected));
+            List<SysMenu> allTemplateMenus = tenantContextHelper.executeInMaster(
+                    () -> tenantInfoMapper.selectMenuList(new SysMenu()));
+            List<Long> expandedSelected = tenantInfoService.expandSysMenuIdsWithAncestors(selected, allTemplateMenus);
+            List<SysMenu> assignSysMenu = tenantContextHelper.executeInMaster(
+                    () -> loadMasterSysMenus(expandedSelected));
+            List<Long> finalSelected = expandedSelected;
             return tenantContextHelper.executeInTenant(tenantInfo,
-                    () -> tenantInfoService.menuAssignReplace(selected, flag, assignSysMenu, null));
+                    () -> tenantInfoService.menuAssignReplace(finalSelected, flag, assignSysMenu, null));
         }
-        List<TenantCompanyMenu> assignCompanyMenu = tenantContextHelper.executeInMaster(() -> loadMasterCompanyMenus(selected));
+        List<TenantCompanyMenu> allTemplateMenus = tenantContextHelper.executeInMaster(
+                () -> tenantInfoMapper.selectCompanyMenuList(new TenantCompanyMenu()));
+        List<Long> expandedSelected = tenantInfoService.expandComMenuIdsWithAncestors(selected, allTemplateMenus);
+        List<TenantCompanyMenu> assignCompanyMenu = tenantContextHelper.executeInMaster(
+                () -> loadMasterCompanyMenus(expandedSelected));
+        List<Long> finalSelected = expandedSelected;
         return tenantContextHelper.executeInTenant(tenantInfo,
-                () -> tenantInfoService.menuAssignReplace(selected, flag, null, assignCompanyMenu));
+                () -> tenantInfoService.menuAssignReplace(finalSelected, flag, null, assignCompanyMenu));
     }
 
     /** 主库 tenant_sys_menu 模板 */

+ 8 - 4
fs-agent/src/main/java/com/fs/tenant/TenantInfoController.java

@@ -178,14 +178,18 @@ public class TenantInfoController extends BaseController
         List<Long> selected = menuDto.getSelected();
         List<Long> unSelected = menuDto.getUnSelected();
         if ("sys".equals(menuDto.getFlag())) {
-            List<SysMenu> addSysMenu = getAddSysMenu(tenantInfo, menuDto.getSelected());
+            List<SysMenu> allTemplateMenus = tenantInfoMapper.selectMenuList(new SysMenu());
+            List<Long> expandedSelected = tenantInfoService.expandSysMenuIdsWithAncestors(selected, allTemplateMenus);
+            List<SysMenu> addSysMenu = getAddSysMenu(tenantInfo, expandedSelected);
             tenantDataSourceManager.switchTenant(tenantInfo);
-            return tenantInfoService.menuEdit(selected, unSelected, menuDto.getFlag(),addSysMenu,null);
+            return tenantInfoService.menuEdit(expandedSelected, unSelected, menuDto.getFlag(), addSysMenu, null);
         }
 
-        List<TenantCompanyMenu> addCompanyMenu = getAddCompanyMenu(tenantInfo, menuDto.getSelected());
+        List<TenantCompanyMenu> allTemplateMenus = tenantInfoMapper.selectCompanyMenuList(new TenantCompanyMenu());
+        List<Long> expandedSelected = tenantInfoService.expandComMenuIdsWithAncestors(selected, allTemplateMenus);
+        List<TenantCompanyMenu> addCompanyMenu = getAddCompanyMenu(tenantInfo, expandedSelected);
         tenantDataSourceManager.switchTenant(tenantInfo);
-        return tenantInfoService.menuEdit(selected, unSelected, menuDto.getFlag(),null,addCompanyMenu);
+        return tenantInfoService.menuEdit(expandedSelected, unSelected, menuDto.getFlag(), null, addCompanyMenu);
     }
 
 

+ 4 - 0
fs-service/src/main/java/com/fs/tenant/mapper/TenantInfoMapper.java

@@ -140,6 +140,10 @@ public interface TenantInfoMapper extends BaseMapper<TenantInfo> {
 
     int addComMenu(List<TenantCompanyMenu> addCompanyMenu);
 
+    int upsertSysMenu(@Param("list") List<SysMenu> list);
+
+    int upsertComMenu(@Param("list") List<TenantCompanyMenu> list);
+
     int deleteTenantSysMenuByIds(@Param("menuIds") List<Long> menuIds);
 
     int deleteTenantComMenuByIds(@Param("menuIds") List<Long> menuIds);

+ 5 - 0
fs-service/src/main/java/com/fs/tenant/service/TenantInfoService.java

@@ -72,6 +72,11 @@ public interface TenantInfoService extends IService<TenantInfo> {
 
     R menuChange(String flag,List<SysMenu> sysMenus, List<TenantCompanyMenu> companyMenus);
 
+    /** 将勾选菜单 ID 补全其所有上级菜单 ID(树形勾选保存/回显需包含父节点) */
+    List<Long> expandSysMenuIdsWithAncestors(List<Long> menuIds, List<SysMenu> allMenus);
+
+    List<Long> expandComMenuIdsWithAncestors(List<Long> menuIds, List<TenantCompanyMenu> allMenus);
+
     R menuEdit(List<Long> selected, List<Long> unSelected, String flag,List<SysMenu> addSysMenu,List<TenantCompanyMenu> addCompanyMenu);
 
     /**

+ 105 - 39
fs-service/src/main/java/com/fs/tenant/service/impl/TenantInfoServiceImpl.java

@@ -54,6 +54,9 @@ import java.util.stream.Collectors;
 @Slf4j
 @Service
 public class TenantInfoServiceImpl extends ServiceImpl<TenantInfoMapper, TenantInfo> implements TenantInfoService {
+
+    /** 菜单 upsert 单批上限,避免 SQL 过长 */
+    private static final int MENU_UPSERT_BATCH_SIZE = 200;
     private static final String REDIS_SYSTEM_KEY_PREFIX = "tenantid:system:";
     private static final String TENANT_INFO_CODE_CACHE_KEY_PREFIX = "tenant:info:code:";
     private static final int TENANT_INFO_CODE_CACHE_HOURS = 24;
@@ -278,16 +281,57 @@ public class TenantInfoServiceImpl extends ServiceImpl<TenantInfoMapper, TenantI
         if ("sys".equals(flag)) {
             List<SysMenu> menuList = baseMapper.selectTenantMenu();
             List<SysMenu> result = mergeSysMenu(sysMenus, menuList);
-            // 返回与模板维护页一致的扁平列表,由前端 handleTree(menuId) 建树
-            return R.ok().put("menus", result);
+            List<Long> tenantMenuIds = menuList.stream()
+                    .map(SysMenu::getMenuId)
+                    .collect(Collectors.toList());
+            List<Long> checkedKeys = expandSysMenuIdsWithAncestors(tenantMenuIds, sysMenus);
+            return R.ok().put("menus", result).put("checkedKeys", checkedKeys);
         }
         List<TenantCompanyMenu> menuList = baseMapper.selectTenantComMenu();
         List<TenantCompanyMenu> result = mergeComMenu(companyMenus, menuList);
-        return R.ok().put("menus", result);
+        List<Long> tenantMenuIds = menuList.stream()
+                .map(TenantCompanyMenu::getMenuId)
+                .collect(Collectors.toList());
+        List<Long> checkedKeys = expandComMenuIdsWithAncestors(tenantMenuIds, companyMenus);
+        return R.ok().put("menus", result).put("checkedKeys", checkedKeys);
+    }
+
+    @Override
+    public List<Long> expandSysMenuIdsWithAncestors(List<Long> menuIds, List<SysMenu> allMenus) {
+        if (CollectionUtils.isEmpty(menuIds) || CollectionUtils.isEmpty(allMenus)) {
+            return new ArrayList<>(emptyIfNull(menuIds));
+        }
+        Map<Long, Long> parentById = allMenus.stream()
+                .collect(Collectors.toMap(SysMenu::getMenuId, SysMenu::getParentId, (a, b) -> a));
+        return expandMenuIdsWithAncestors(menuIds, parentById);
+    }
+
+    @Override
+    public List<Long> expandComMenuIdsWithAncestors(List<Long> menuIds, List<TenantCompanyMenu> allMenus) {
+        if (CollectionUtils.isEmpty(menuIds) || CollectionUtils.isEmpty(allMenus)) {
+            return new ArrayList<>(emptyIfNull(menuIds));
+        }
+        Map<Long, Long> parentById = allMenus.stream()
+                .collect(Collectors.toMap(TenantCompanyMenu::getMenuId, TenantCompanyMenu::getParentId, (a, b) -> a));
+        return expandMenuIdsWithAncestors(menuIds, parentById);
+    }
+
+    private List<Long> expandMenuIdsWithAncestors(List<Long> menuIds, Map<Long, Long> parentById) {
+        Set<Long> expanded = new LinkedHashSet<>();
+        for (Long menuId : menuIds) {
+            Long current = menuId;
+            while (current != null && current != 0L) {
+                if (!expanded.add(current)) {
+                    break;
+                }
+                current = parentById.get(current);
+            }
+        }
+        return new ArrayList<>(expanded);
     }
 
     /**
-     * 合并模板菜单与租户库菜单:结构以模板(tenant_sys_menu)为准,visible 以租户库为准
+     * 合并模板菜单与租户库菜单:结构以模板(tenant_sys_menu)为准,visible 以租户库是否存在为准
      */
     private List<SysMenu> mergeSysMenu(List<SysMenu> standardList, List<SysMenu> tenantList) {
         Map<Long, SysMenu> tenantMap = tenantList.stream()
@@ -302,6 +346,8 @@ public class TenantInfoServiceImpl extends ServiceImpl<TenantInfoMapper, TenantI
     private SysMenu mergeOneSysMenu(SysMenu standard, Map<Long, SysMenu> tenantMap) {
         SysMenu tenant = tenantMap.get(standard.getMenuId());
         if (tenant != null) {
+            // 租户库存在即已分配,统一 visible=0 便于前端回显
+            tenant.setVisible("0");
             return tenant;
         }
         SysMenu unassigned = new SysMenu();
@@ -326,6 +372,7 @@ public class TenantInfoServiceImpl extends ServiceImpl<TenantInfoMapper, TenantI
     private TenantCompanyMenu mergeOneComMenu(TenantCompanyMenu standard, Map<Long, TenantCompanyMenu> tenantMap) {
         TenantCompanyMenu tenant = tenantMap.get(standard.getMenuId());
         if (tenant != null) {
+            tenant.setVisible("0");
             return tenant;
         }
         TenantCompanyMenu unassigned = new TenantCompanyMenu();
@@ -362,84 +409,103 @@ public class TenantInfoServiceImpl extends ServiceImpl<TenantInfoMapper, TenantI
     }
 
     /**
-     * 租户库菜单全量替换:existIds 查租户库 sys_menu,删/插均在租户库执行
+     * 租户库菜单差量同步:仅删除取消项,对其余项批量 upsert(不先删后插)
      */
     @Override
     @Transactional(rollbackFor = Exception.class)
     public R menuAssignReplace(List<Long> selected, String flag, List<SysMenu> assignSysMenu, List<TenantCompanyMenu> assignCompanyMenu) {
-        List<Long> allSelected = emptyIfNull(selected);
-        Set<Long> selectedSet = new HashSet<>(allSelected);
+        Set<Long> selectedSet = new HashSet<>(emptyIfNull(selected));
 
         if ("sys".equals(flag)) {
-            replaceSysMenu(allSelected, selectedSet, assignSysMenu);
+            syncSysMenuAssign(selectedSet, emptyListIfNull(assignSysMenu));
             return R.ok();
         }
-        replaceComMenu(allSelected, selectedSet, assignCompanyMenu);
+        syncComMenuAssign(selectedSet, emptyListIfNull(assignCompanyMenu));
         return R.ok();
     }
 
-    private void replaceSysMenu(List<Long> allSelected, Set<Long> selectedSet, List<SysMenu> assignSysMenu) {
-        List<Long> existIds = emptyIfNull(baseMapper.selectTenantDbSysMenuIds());
+    private void syncSysMenuAssign(Set<Long> selectedSet, List<SysMenu> assignSysMenu) {
+        Set<Long> existSet = new HashSet<>(emptyIfNull(baseMapper.selectTenantDbSysMenuIds()));
 
-        List<Long> toRemove = existIds.stream()
+        List<Long> toRemove = existSet.stream()
                 .filter(id -> !selectedSet.contains(id))
                 .collect(Collectors.toList());
         removeTenantSysMenus(toRemove);
 
-        List<Long> toRefresh = existIds.stream()
-                .filter(selectedSet::contains)
-                .collect(Collectors.toList());
-        removeTenantSysMenus(toRefresh);
-
-        if (!CollectionUtils.isEmpty(assignSysMenu)) {
-            baseMapper.addSysMenu(assignSysMenu);
-        }
-        if (!CollectionUtils.isEmpty(allSelected)) {
-            baseMapper.updatePitchMenu(allSelected);
-        }
+        batchUpsertSysMenu(assignSysMenu);
     }
 
-    private void replaceComMenu(List<Long> allSelected, Set<Long> selectedSet, List<TenantCompanyMenu> assignCompanyMenu) {
-        List<Long> existIds = emptyIfNull(baseMapper.selectTenantDbComMenuIds());
+    private void syncComMenuAssign(Set<Long> selectedSet, List<TenantCompanyMenu> assignCompanyMenu) {
+        Set<Long> existSet = new HashSet<>(emptyIfNull(baseMapper.selectTenantDbComMenuIds()));
 
-        List<Long> toRemove = existIds.stream()
+        List<Long> toRemove = existSet.stream()
                 .filter(id -> !selectedSet.contains(id))
                 .collect(Collectors.toList());
         removeTenantComMenus(toRemove);
 
-        List<Long> toRefresh = existIds.stream()
-                .filter(selectedSet::contains)
-                .collect(Collectors.toList());
-        removeTenantComMenus(toRefresh);
+        batchUpsertComMenu(assignCompanyMenu);
+    }
+
+    private void batchUpsertSysMenu(List<SysMenu> menus) {
+        if (CollectionUtils.isEmpty(menus)) {
+            return;
+        }
+        for (int i = 0; i < menus.size(); i += MENU_UPSERT_BATCH_SIZE) {
+            int end = Math.min(i + MENU_UPSERT_BATCH_SIZE, menus.size());
+            baseMapper.upsertSysMenu(new ArrayList<>(menus.subList(i, end)));
+        }
+    }
 
-        if (!CollectionUtils.isEmpty(assignCompanyMenu)) {
-            baseMapper.addComMenu(assignCompanyMenu);
+    private void batchUpsertComMenu(List<TenantCompanyMenu> menus) {
+        if (CollectionUtils.isEmpty(menus)) {
+            return;
         }
-        if (!CollectionUtils.isEmpty(allSelected)) {
-            baseMapper.updatePitchComMenu(allSelected);
+        for (int i = 0; i < menus.size(); i += MENU_UPSERT_BATCH_SIZE) {
+            int end = Math.min(i + MENU_UPSERT_BATCH_SIZE, menus.size());
+            baseMapper.upsertComMenu(new ArrayList<>(menus.subList(i, end)));
         }
     }
 
     private void removeTenantSysMenus(List<Long> menuIds) {
+        batchRemoveTenantSysMenus(menuIds);
+    }
+
+    private void removeTenantComMenus(List<Long> menuIds) {
+        batchRemoveTenantComMenus(menuIds);
+    }
+
+    private void batchRemoveTenantSysMenus(List<Long> menuIds) {
         if (CollectionUtils.isEmpty(menuIds)) {
             return;
         }
-        baseMapper.deleteSysRoleMenuByMenuIds(menuIds);
-        baseMapper.deleteTenantSysMenuByIds(menuIds);
+        for (int i = 0; i < menuIds.size(); i += MENU_UPSERT_BATCH_SIZE) {
+            int end = Math.min(i + MENU_UPSERT_BATCH_SIZE, menuIds.size());
+            List<Long> batch = menuIds.subList(i, end);
+            baseMapper.deleteSysRoleMenuByMenuIds(batch);
+            baseMapper.deleteTenantSysMenuByIds(batch);
+        }
     }
 
-    private void removeTenantComMenus(List<Long> menuIds) {
+    private void batchRemoveTenantComMenus(List<Long> menuIds) {
         if (CollectionUtils.isEmpty(menuIds)) {
             return;
         }
-        baseMapper.deleteComRoleMenuByMenuIds(menuIds);
-        baseMapper.deleteTenantComMenuByIds(menuIds);
+        for (int i = 0; i < menuIds.size(); i += MENU_UPSERT_BATCH_SIZE) {
+            int end = Math.min(i + MENU_UPSERT_BATCH_SIZE, menuIds.size());
+            List<Long> batch = menuIds.subList(i, end);
+            baseMapper.deleteComRoleMenuByMenuIds(batch);
+            baseMapper.deleteTenantComMenuByIds(batch);
+        }
     }
 
     private static List<Long> emptyIfNull(List<Long> list) {
         return list == null ? Collections.emptyList() : list;
     }
 
+    private static <T> List<T> emptyListIfNull(List<T> list) {
+        return list == null ? Collections.emptyList() : list;
+    }
+
     @Override
     public TenantInfo getTenByCorpId(String corpId) {
         return baseMapper.getTenByCorpId(corpId);

+ 99 - 3
fs-service/src/main/resources/mapper/tenant/TenantInfoMapper.xml

@@ -465,7 +465,7 @@
             #{item.isFrame},
             #{item.isCache},
             #{item.menuType},
-            #{item.visible},
+            '0',
             #{item.status},
             #{item.perms},
             #{item.icon},
@@ -494,8 +494,8 @@
             #{item.isFrame},
             #{item.isCache},
             #{item.menuType},
-            0,
-            0,
+            '0',
+            #{item.status},
             #{item.perms},
             #{item.icon},
             #{item.createBy},
@@ -509,6 +509,102 @@
 
     </insert>
 
+    <!-- 租户库 sys_menu 批量 upsert:新增 + 按模板更新已有项,避免先删后插 -->
+    <insert id="upsertSysMenu">
+        INSERT INTO `sys_menu` (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`,
+                                `query`, `is_frame`, `is_cache`, `menu_type`, `visible`, `status`, `perms`,
+                                `icon`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`)
+        VALUES
+        <foreach collection="list" item="item" separator=",">
+            (
+            #{item.menuId},
+            #{item.menuName},
+            #{item.parentId},
+            #{item.orderNum},
+            #{item.path},
+            #{item.component},
+            #{item.query},
+            #{item.isFrame},
+            #{item.isCache},
+            #{item.menuType},
+            '0',
+            #{item.status},
+            #{item.perms},
+            #{item.icon},
+            #{item.createBy},
+            NOW(),
+            #{item.updateBy},
+            NOW(),
+            #{item.remark}
+            )
+        </foreach>
+        ON DUPLICATE KEY UPDATE
+            menu_name = VALUES(menu_name),
+            parent_id = VALUES(parent_id),
+            order_num = VALUES(order_num),
+            path = VALUES(path),
+            component = VALUES(component),
+            `query` = VALUES(`query`),
+            is_frame = VALUES(is_frame),
+            is_cache = VALUES(is_cache),
+            menu_type = VALUES(menu_type),
+            visible = '0',
+            status = VALUES(status),
+            perms = VALUES(perms),
+            icon = VALUES(icon),
+            update_by = VALUES(update_by),
+            update_time = NOW(),
+            remark = VALUES(remark)
+    </insert>
+
+    <!-- 租户库 company_menu 批量 upsert -->
+    <insert id="upsertComMenu">
+        INSERT INTO `company_menu` (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `is_frame`,
+                                    `is_cache`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_by`,
+                                    `create_time`, `update_by`, `update_time`, `remark`, `company_id`)
+        VALUES
+        <foreach collection="list" item="item" separator=",">
+            (
+            #{item.menuId},
+            #{item.menuName},
+            #{item.parentId},
+            #{item.orderNum},
+            #{item.path},
+            #{item.component},
+            #{item.isFrame},
+            #{item.isCache},
+            #{item.menuType},
+            '0',
+            #{item.status},
+            #{item.perms},
+            #{item.icon},
+            #{item.createBy},
+            NOW(),
+            #{item.updateBy},
+            NOW(),
+            #{item.remark},
+            #{item.companyId}
+            )
+        </foreach>
+        ON DUPLICATE KEY UPDATE
+            menu_name = VALUES(menu_name),
+            parent_id = VALUES(parent_id),
+            order_num = VALUES(order_num),
+            path = VALUES(path),
+            component = VALUES(component),
+            is_frame = VALUES(is_frame),
+            is_cache = VALUES(is_cache),
+            menu_type = VALUES(menu_type),
+            visible = '0',
+            status = VALUES(status),
+            perms = VALUES(perms),
+            icon = VALUES(icon),
+            update_by = VALUES(update_by),
+            update_time = NOW(),
+            remark = VALUES(remark),
+            company_id = VALUES(company_id)
+    </insert>
+
     <delete id="deleteTenantSysMenuByIds">
         delete from sys_menu where menu_id in
         <foreach collection="menuIds" item="menuId" open="(" separator="," close=")">