Просмотр исходного кода

总后台的租户菜单编辑后同步到已启用租户库

Long 8 часов назад
Родитель
Сommit
26a642549f

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

@@ -15,6 +15,7 @@ import com.fs.common.exception.CustomException;
 import com.fs.common.utils.StringUtils;
 import com.fs.common.utils.poi.ExcelUtil;
 import com.fs.framework.datasource.DynamicDataSourceContextHolder;
+import com.fs.framework.datasource.TenantDataSourceContextHelper;
 import com.fs.framework.datasource.TenantDataSourceManager;
 import com.fs.system.domain.SysConfig;
 import com.fs.system.service.ISysConfigService;
@@ -30,8 +31,10 @@ import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
 
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
 import java.util.Map;
+import java.util.concurrent.CompletableFuture;
 import java.util.stream.Collectors;
 
 /**
@@ -56,6 +59,9 @@ public class TenantInfoController extends BaseController
 
     @Autowired
     private TenantDataSourceManager tenantDataSourceManager;
+
+    @Autowired
+    private TenantDataSourceContextHelper tenantContextHelper;
     /**
      * 查询租户基础信息列表
      */
@@ -378,7 +384,12 @@ public class TenantInfoController extends BaseController
             return AjaxResult.error("修改菜单'" + menu.getMenuName() + "'失败,上级菜单不能选择自己");
         }
         menu.setUpdateBy(getUsername());
-        return toAjax(tenantInfoService.updateMenu(menu));
+        int result = tenantInfoService.updateMenu(menu);
+        if (result > 0) {
+            SysMenu fullMenu = tenantInfoService.selectMenuById(menu.getMenuId());
+            CompletableFuture.runAsync(() -> syncSysMenuUpdateToTenants(fullMenu));
+        }
+        return toAjax(result);
     }
 
     /**
@@ -402,7 +413,12 @@ public class TenantInfoController extends BaseController
             return AjaxResult.error("修改菜单'" + menu.getMenuName() + "'失败,上级菜单不能选择自己");
         }
         menu.setUpdateBy(getUsername());
-        return toAjax(tenantInfoService.updateComMenu(menu));
+        int result = tenantInfoService.updateComMenu(menu);
+        if (result > 0) {
+            TenantCompanyMenu fullMenu = tenantInfoService.getTenantComMenu(menu.getMenuId());
+            CompletableFuture.runAsync(() -> syncComMenuUpdateToTenants(fullMenu));
+        }
+        return toAjax(result);
     }
 
     @PreAuthorize("@ss.hasPermi('system:menu:remove')")
@@ -414,7 +430,11 @@ public class TenantInfoController extends BaseController
         {
             return AjaxResult.error("存在子菜单,不允许删除");
         }
-        return toAjax(tenantInfoService.deleteMenuById(menuId));
+        int result = tenantInfoService.deleteMenuById(menuId);
+        if (result > 0) {
+            CompletableFuture.runAsync(() -> syncSysMenuDeleteToTenants(menuId));
+        }
+        return toAjax(result);
     }
 
     @PreAuthorize("@ss.hasPermi('system:menu:remove')")
@@ -426,6 +446,107 @@ public class TenantInfoController extends BaseController
         {
             return AjaxResult.error("存在子菜单,不允许删除");
         }
-        return toAjax(tenantInfoService.deleteComMenuById(menuId));
+        int result = tenantInfoService.deleteComMenuById(menuId);
+        if (result > 0) {
+            CompletableFuture.runAsync(() -> syncComMenuDeleteToTenants(menuId));
+        }
+        return toAjax(result);
+    }
+
+    // ========== 菜单模板变更 → 异步同步到所有启用租户库 ==========
+
+    /**
+     * 同步 sys 菜单修改到所有 status=1 的租户库(仅已存在该菜单的租户执行 upsert)
+     */
+    private void syncSysMenuUpdateToTenants(SysMenu menu) {
+        List<TenantInfo> tenants = getActiveTenantsForSync();
+        for (TenantInfo tenant : tenants) {
+            try {
+                tenantContextHelper.executeInTenant(tenant, () -> {
+                    int count = tenantInfoMapper.countTenantSysMenuById(menu.getMenuId());
+                    if (count > 0) {
+                        tenantInfoMapper.upsertSysMenu(Collections.singletonList(menu));
+                    }
+                    return null;
+                });
+            } catch (Exception e) {
+                log.error("同步sys菜单修改失败: tenant={}, menuId={}", tenant.getTenantCode(), menu.getMenuId(), e);
+            }
+        }
+    }
+
+    /**
+     * 同步 sys 菜单删除到所有 status=1 的租户库(仅已存在该菜单的租户执行删除)
+     */
+    private void syncSysMenuDeleteToTenants(Long menuId) {
+        List<TenantInfo> tenants = getActiveTenantsForSync();
+        for (TenantInfo tenant : tenants) {
+            try {
+                tenantContextHelper.executeInTenant(tenant, () -> {
+                    int count = tenantInfoMapper.countTenantSysMenuById(menuId);
+                    if (count > 0) {
+                        List<Long> menuIds = Collections.singletonList(menuId);
+                        tenantInfoMapper.deleteSysRoleMenuByMenuIds(menuIds);
+                        tenantInfoMapper.deleteTenantSysMenuByIds(menuIds);
+                    }
+                    return null;
+                });
+            } catch (Exception e) {
+                log.error("同步sys菜单删除失败: tenant={}, menuId={}", tenant.getTenantCode(), menuId, e);
+            }
+        }
+    }
+
+    /**
+     * 同步 com 菜单修改到所有 status=1 的租户库(仅已存在该菜单的租户执行 upsert)
+     */
+    private void syncComMenuUpdateToTenants(TenantCompanyMenu menu) {
+        List<TenantInfo> tenants = getActiveTenantsForSync();
+        for (TenantInfo tenant : tenants) {
+            try {
+                tenantContextHelper.executeInTenant(tenant, () -> {
+                    int count = tenantInfoMapper.countTenantComMenuById(menu.getMenuId());
+                    if (count > 0) {
+                        tenantInfoMapper.upsertComMenu(Collections.singletonList(menu));
+                    }
+                    return null;
+                });
+            } catch (Exception e) {
+                log.error("同步com菜单修改失败: tenant={}, menuId={}", tenant.getTenantCode(), menu.getMenuId(), e);
+            }
+        }
+    }
+
+    /**
+     * 同步 com 菜单删除到所有 status=1 的租户库(仅已存在该菜单的租户执行删除)
+     */
+    private void syncComMenuDeleteToTenants(Long menuId) {
+        List<TenantInfo> tenants = getActiveTenantsForSync();
+        for (TenantInfo tenant : tenants) {
+            try {
+                tenantContextHelper.executeInTenant(tenant, () -> {
+                    int count = tenantInfoMapper.countTenantComMenuById(menuId);
+                    if (count > 0) {
+                        List<Long> menuIds = Collections.singletonList(menuId);
+                        tenantInfoMapper.deleteComRoleMenuByMenuIds(menuIds);
+                        tenantInfoMapper.deleteTenantComMenuByIds(menuIds);
+                    }
+                    return null;
+                });
+            } catch (Exception e) {
+                log.error("同步com菜单删除失败: tenant={}, menuId={}", tenant.getTenantCode(), menuId, e);
+            }
+        }
+    }
+
+    /**
+     * 查询所有 status=1(启用)的租户,在主库执行
+     */
+    private List<TenantInfo> getActiveTenantsForSync() {
+        return tenantContextHelper.executeInMaster(() -> {
+            TenantInfo query = new TenantInfo();
+            query.setStatus(1);
+            return tenantInfoService.selectTenantInfoList(query);
+        });
     }
 }

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

@@ -152,6 +152,12 @@ public interface TenantInfoMapper extends BaseMapper<TenantInfo> {
 
     int deleteComRoleMenuByMenuIds(@Param("menuIds") List<Long> menuIds);
 
+    /** 检查租户库 sys_menu 中是否存在指定菜单(须在租户数据源下调用) */
+    int countTenantSysMenuById(@Param("menuId") Long menuId);
+
+    /** 检查租户库 company_menu 中是否存在指定菜单(须在租户数据源下调用) */
+    int countTenantComMenuById(@Param("menuId") Long menuId);
+
     TenantInfo getTenByCode(String code);
 
     List<FeePlanItem> selectFeeItem(String feePlanCode);

+ 10 - 0
fs-service/src/main/resources/mapper/tenant/TenantInfoMapper.xml

@@ -761,4 +761,14 @@
         UPDATE sys_user SET password = #{password}, update_time = NOW()
         WHERE user_id = 1
     </update>
+
+    <!-- 检查租户库 sys_menu 中是否存在指定菜单(须在租户数据源下调用) -->
+    <select id="countTenantSysMenuById" resultType="int">
+        SELECT COUNT(1) FROM `sys_menu` WHERE menu_id = #{menuId}
+    </select>
+
+    <!-- 检查租户库 company_menu 中是否存在指定菜单(须在租户数据源下调用) -->
+    <select id="countTenantComMenuById" resultType="int">
+        SELECT COUNT(1) FROM `company_menu` WHERE menu_id = #{menuId}
+    </select>
 </mapper>