diff --git a/continew-common/src/main/java/top/continew/admin/common/base/model/entity/TenantBaseDO.java b/continew-common/src/main/java/top/continew/admin/common/base/model/entity/TenantBaseDO.java
new file mode 100644
index 00000000..15a68891
--- /dev/null
+++ b/continew-common/src/main/java/top/continew/admin/common/base/model/entity/TenantBaseDO.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package top.continew.admin.common.base.model.entity;
+
+import lombok.Data;
+
+import java.io.Serial;
+
+/**
+ * 租户实体类基类
+ *
+ *
+ * 通用字段:ID、创建人、创建时间、修改人、修改时间、租户 ID
+ *
+ *
+ * @author Charles7c
+ * @since 2025/7/17 20:20
+ */
+@Data
+public class TenantBaseDO extends BaseDO {
+
+ @Serial
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 租户 ID
+ */
+ private Long tenantId;
+}
diff --git a/continew-common/src/main/java/top/continew/admin/common/config/TenantExtensionProperties.java b/continew-common/src/main/java/top/continew/admin/common/config/TenantExtensionProperties.java
index 4903da0e..02543017 100644
--- a/continew-common/src/main/java/top/continew/admin/common/config/TenantExtensionProperties.java
+++ b/continew-common/src/main/java/top/continew/admin/common/config/TenantExtensionProperties.java
@@ -35,6 +35,16 @@ import java.util.List;
@ConfigurationProperties(prefix = PropertiesConstants.TENANT)
public class TenantExtensionProperties {
+ /**
+ * 是否启用
+ */
+ private boolean enabled;
+
+ /**
+ * 请求头中租户编码键名
+ */
+ private String tenantCodeHeader;
+
/**
* 忽略菜单 ID(租户不能使用的菜单)
*/
diff --git a/continew-common/src/main/java/top/continew/admin/common/constant/RegexConstants.java b/continew-common/src/main/java/top/continew/admin/common/constant/RegexConstants.java
index 82bb04e1..4037298e 100644
--- a/continew-common/src/main/java/top/continew/admin/common/constant/RegexConstants.java
+++ b/continew-common/src/main/java/top/continew/admin/common/constant/RegexConstants.java
@@ -60,10 +60,22 @@ public class RegexConstants {
public static final String PACKAGE_NAME = "^(?:[a-zA-Z_][a-zA-Z0-9_]*\\.)*[a-zA-Z_][a-zA-Z0-9_]*$";
/**
- * HTTP 域名 URL 正则
+ * HTTP 域名 URL 正则(非 IP 地址)
*/
public static final String HTTP_DOMAIN_URL = "^(https?:\\/\\/)([a-zA-Z0-9-]+\\.)+[a-zA-Z]{2,}(\\/[^\\s]*)?$";
+ /**
+ * HTTP HOST 正则
+ *
+ * 域名、IPV4、IPV6
+ *
+ */
+ public static final String HTTP_HOST = """
+ ^((?:[a-zA-Z0-9-]+\\.)+[a-zA-Z]{2,}|
+ (?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)|
+ (?:(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|
+ """;
+
private RegexConstants() {
}
}
diff --git a/continew-plugin/continew-plugin-tenant/src/main/java/top/continew/admin/tenant/config/DefaultTenantProvider.java b/continew-plugin/continew-plugin-tenant/src/main/java/top/continew/admin/tenant/config/DefaultTenantProvider.java
index 1df20979..6c8fc21b 100644
--- a/continew-plugin/continew-plugin-tenant/src/main/java/top/continew/admin/tenant/config/DefaultTenantProvider.java
+++ b/continew-plugin/continew-plugin-tenant/src/main/java/top/continew/admin/tenant/config/DefaultTenantProvider.java
@@ -17,13 +17,17 @@
package top.continew.admin.tenant.config;
import cn.hutool.core.util.StrUtil;
+import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
+import top.continew.admin.common.config.TenantExtensionProperties;
+import top.continew.admin.tenant.model.entity.TenantDO;
import top.continew.admin.tenant.service.TenantService;
+import top.continew.starter.core.util.ServletUtils;
+import top.continew.starter.core.util.validation.CheckUtils;
import top.continew.starter.extension.tenant.autoconfigure.TenantProperties;
import top.continew.starter.extension.tenant.config.TenantProvider;
import top.continew.starter.extension.tenant.context.TenantContext;
-import top.continew.starter.extension.tenant.enums.TenantIsolationLevel;
/**
* 默认租户提供者
@@ -37,21 +41,38 @@ import top.continew.starter.extension.tenant.enums.TenantIsolationLevel;
public class DefaultTenantProvider implements TenantProvider {
private final TenantProperties tenantProperties;
+ private final TenantExtensionProperties tenantExtensionProperties;
private final TenantService tenantService;
@Override
public TenantContext getByTenantId(String tenantIdAsString, boolean verify) {
TenantContext context = new TenantContext();
- context.setIsolationLevel(TenantIsolationLevel.LINE);
- // 超级租户
Long superTenantId = tenantProperties.getSuperTenantId();
- if (StrUtil.isBlank(tenantIdAsString) || superTenantId.toString().equals(tenantIdAsString)) {
- context.setTenantId(superTenantId);
+ context.setTenantId(superTenantId);
+ // 超级租户
+ if (superTenantId.toString().equals(tenantIdAsString)) {
return context;
}
- // 获取租户信息
- Long tenantId = Long.valueOf(tenantIdAsString);
- tenantService.checkStatus(tenantId);
+ Long tenantId;
+ // 未指定租户
+ if (StrUtil.isBlank(tenantIdAsString)) {
+ // 检查是否指定了租户编码(登录相关接口)
+ HttpServletRequest request = ServletUtils.getRequest();
+ String tenantCode = request.getHeader(tenantExtensionProperties.getTenantCodeHeader());
+ if (StrUtil.isBlank(tenantCode)) {
+ return context;
+ }
+ TenantDO tenant = tenantService.getByCode(tenantCode);
+ CheckUtils.throwIfNull(tenant, "编码为 [%s] 的租户不存在".formatted(tenantCode));
+ tenantId = tenant.getId();
+ } else {
+ // 指定租户
+ tenantId = Long.parseLong(tenantIdAsString);
+ }
+ // 检查租户状态
+ if (verify) {
+ tenantService.checkStatus(tenantId);
+ }
context.setTenantId(tenantId);
return context;
}
diff --git a/continew-plugin/continew-plugin-tenant/src/main/java/top/continew/admin/tenant/controller/TenantCommonController.java b/continew-plugin/continew-plugin-tenant/src/main/java/top/continew/admin/tenant/controller/CommonController.java
similarity index 96%
rename from continew-plugin/continew-plugin-tenant/src/main/java/top/continew/admin/tenant/controller/TenantCommonController.java
rename to continew-plugin/continew-plugin-tenant/src/main/java/top/continew/admin/tenant/controller/CommonController.java
index 4d0f2ef7..aa04103d 100644
--- a/continew-plugin/continew-plugin-tenant/src/main/java/top/continew/admin/tenant/controller/TenantCommonController.java
+++ b/continew-plugin/continew-plugin-tenant/src/main/java/top/continew/admin/tenant/controller/CommonController.java
@@ -40,10 +40,10 @@ import java.util.List;
@Tag(name = "公共 API")
@Log(ignore = true)
@Validated
-@RestController
@RequiredArgsConstructor
+@RestController("tenantCommonController")
@RequestMapping("/tenant/common")
-public class TenantCommonController {
+public class CommonController {
private final PackageService packageService;
diff --git a/continew-plugin/continew-plugin-tenant/src/main/java/top/continew/admin/tenant/controller/TenantController.java b/continew-plugin/continew-plugin-tenant/src/main/java/top/continew/admin/tenant/controller/TenantController.java
index c3e4f20a..7093dbb6 100644
--- a/continew-plugin/continew-plugin-tenant/src/main/java/top/continew/admin/tenant/controller/TenantController.java
+++ b/continew-plugin/continew-plugin-tenant/src/main/java/top/continew/admin/tenant/controller/TenantController.java
@@ -17,13 +17,15 @@
package top.continew.admin.tenant.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
-import cn.dev33.satoken.annotation.SaIgnore;
import cn.hutool.extra.spring.SpringUtil;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
-import org.springframework.web.bind.annotation.*;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RestController;
import top.continew.admin.common.base.controller.BaseController;
import top.continew.admin.common.util.SecureUtils;
import top.continew.admin.system.model.entity.user.UserDO;
@@ -33,7 +35,6 @@ import top.continew.admin.tenant.model.entity.TenantDO;
import top.continew.admin.tenant.model.query.TenantQuery;
import top.continew.admin.tenant.model.req.TenantAdminUserPwdUpdateReq;
import top.continew.admin.tenant.model.req.TenantReq;
-import top.continew.admin.tenant.model.resp.TenantCommonResp;
import top.continew.admin.tenant.model.resp.TenantDetailResp;
import top.continew.admin.tenant.model.resp.TenantResp;
import top.continew.admin.tenant.service.TenantService;
@@ -42,7 +43,6 @@ import top.continew.starter.core.util.validation.ValidationUtils;
import top.continew.starter.extension.crud.annotation.CrudRequestMapping;
import top.continew.starter.extension.crud.enums.Api;
import top.continew.starter.extension.tenant.TenantHandler;
-import top.continew.starter.extension.tenant.autoconfigure.TenantProperties;
/**
* 租户管理 API
@@ -57,26 +57,15 @@ import top.continew.starter.extension.tenant.autoconfigure.TenantProperties;
@CrudRequestMapping(value = "/tenant/management", api = {Api.PAGE, Api.GET, Api.CREATE, Api.UPDATE, Api.DELETE})
public class TenantController extends BaseController {
- private final TenantProperties tenantProperties;
private final UserService userService;
- @SaIgnore
- @GetMapping("/common")
- @Operation(summary = "租户通用信息查询", description = "租户通用信息查询")
- public TenantCommonResp common() {
- TenantCommonResp commonResp = new TenantCommonResp();
- commonResp.setIsEnabled(tenantProperties.isEnabled());
- commonResp.setAvailableList(baseService.getAvailableList());
- return commonResp;
- }
-
@Operation(summary = "修改租户管理员密码", description = "修改租户管理员密码")
@SaCheckPermission("tenant:management:updateAdminUserPwd")
@PutMapping("/{id}/admin/pwd")
public void updateAdminUserPwd(@Valid @RequestBody TenantAdminUserPwdUpdateReq req, @PathVariable Long id) {
TenantDO tenant = baseService.getById(id);
String encryptPassword = req.getPassword();
- SpringUtil.getBean(TenantHandler.class).execute(tenant.getId(), () -> {
+ SpringUtil.getBean(TenantHandler.class).execute(id, () -> {
UserDO user = userService.getById(tenant.getAdminUser());
String password = ExceptionUtils.exToNull(() -> SecureUtils.decryptByRsaPrivateKey(encryptPassword));
ValidationUtils.throwIfNull(password, "新密码解密失败");
diff --git a/continew-plugin/continew-plugin-tenant/src/main/java/top/continew/admin/tenant/model/entity/TenantDO.java b/continew-plugin/continew-plugin-tenant/src/main/java/top/continew/admin/tenant/model/entity/TenantDO.java
index e01edac9..d36a542a 100644
--- a/continew-plugin/continew-plugin-tenant/src/main/java/top/continew/admin/tenant/model/entity/TenantDO.java
+++ b/continew-plugin/continew-plugin-tenant/src/main/java/top/continew/admin/tenant/model/entity/TenantDO.java
@@ -49,7 +49,7 @@ public class TenantDO extends BaseDO {
private String code;
/**
- * 域名
+ * 绑定域名
*/
private String domain;
diff --git a/continew-plugin/continew-plugin-tenant/src/main/java/top/continew/admin/tenant/model/req/PackageReq.java b/continew-plugin/continew-plugin-tenant/src/main/java/top/continew/admin/tenant/model/req/PackageReq.java
index 9cb16efa..064b2d24 100644
--- a/continew-plugin/continew-plugin-tenant/src/main/java/top/continew/admin/tenant/model/req/PackageReq.java
+++ b/continew-plugin/continew-plugin-tenant/src/main/java/top/continew/admin/tenant/model/req/PackageReq.java
@@ -18,13 +18,13 @@ package top.continew.admin.tenant.model.req;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotEmpty;
import lombok.Data;
import org.hibernate.validator.constraints.Length;
import top.continew.admin.common.enums.DisEnableStatusEnum;
import java.io.Serial;
import java.io.Serializable;
-import java.util.ArrayList;
import java.util.List;
/**
@@ -78,5 +78,6 @@ public class PackageReq implements Serializable {
* 关联的菜单 ID 列表
*/
@Schema(description = "关联的菜单 ID 列表", example = "[1000, 1010, 1011]")
- private List menuIds = new ArrayList<>();
+ @NotEmpty(message = "关联菜单不能为空")
+ private List menuIds;
}
\ No newline at end of file
diff --git a/continew-plugin/continew-plugin-tenant/src/main/java/top/continew/admin/tenant/model/req/TenantReq.java b/continew-plugin/continew-plugin-tenant/src/main/java/top/continew/admin/tenant/model/req/TenantReq.java
index c2851218..18efcc64 100644
--- a/continew-plugin/continew-plugin-tenant/src/main/java/top/continew/admin/tenant/model/req/TenantReq.java
+++ b/continew-plugin/continew-plugin-tenant/src/main/java/top/continew/admin/tenant/model/req/TenantReq.java
@@ -54,10 +54,11 @@ public class TenantReq implements Serializable {
private String name;
/**
- * 域名
+ * 绑定域名
*/
- @Schema(description = "域名", example = "https://T0sL6RWv0vFh.continew.top/")
- @Length(max = 255, message = "域名长度不能超过 {max} 个字符")
+ @Schema(description = "绑定域名", example = "https://T0sL6RWv0vFh.continew.top/")
+ @Length(max = 255, message = "绑定域名长度不能超过 {max} 个字符")
+ @Pattern(regexp = RegexConstants.HTTP_HOST, message = "绑定域名格式不正确")
private String domain;
/**
diff --git a/continew-plugin/continew-plugin-tenant/src/main/java/top/continew/admin/tenant/model/resp/TenantResp.java b/continew-plugin/continew-plugin-tenant/src/main/java/top/continew/admin/tenant/model/resp/TenantResp.java
index e167fa81..1d8c4bec 100644
--- a/continew-plugin/continew-plugin-tenant/src/main/java/top/continew/admin/tenant/model/resp/TenantResp.java
+++ b/continew-plugin/continew-plugin-tenant/src/main/java/top/continew/admin/tenant/model/resp/TenantResp.java
@@ -61,10 +61,10 @@ public class TenantResp extends BaseDetailResp {
private String code;
/**
- * 域名
+ * 绑定域名
*/
- @Schema(description = "域名", example = "https://T0sL6RWv0vFh.continew.top/")
- @ExcelProperty(value = "域名", order = 4)
+ @Schema(description = "绑定域名", example = "https://T0sL6RWv0vFh.continew.top/")
+ @ExcelProperty(value = "绑定域名", order = 4)
private String domain;
/**
diff --git a/continew-plugin/continew-plugin-tenant/src/main/java/top/continew/admin/tenant/service/PackageService.java b/continew-plugin/continew-plugin-tenant/src/main/java/top/continew/admin/tenant/service/PackageService.java
index 91fa9c46..ffb2f0fc 100644
--- a/continew-plugin/continew-plugin-tenant/src/main/java/top/continew/admin/tenant/service/PackageService.java
+++ b/continew-plugin/continew-plugin-tenant/src/main/java/top/continew/admin/tenant/service/PackageService.java
@@ -30,4 +30,12 @@ import top.continew.starter.data.service.IService;
* @author 小熊
* @since 2024/11/26 11:25
*/
-public interface PackageService extends BaseService, IService {}
\ No newline at end of file
+public interface PackageService extends BaseService, IService {
+
+ /**
+ * 检查套餐状态
+ *
+ * @param id ID
+ */
+ void checkStatus(Long id);
+}
\ No newline at end of file
diff --git a/continew-plugin/continew-plugin-tenant/src/main/java/top/continew/admin/tenant/service/TenantService.java b/continew-plugin/continew-plugin-tenant/src/main/java/top/continew/admin/tenant/service/TenantService.java
index 4fa6b062..e4e69a6a 100644
--- a/continew-plugin/continew-plugin-tenant/src/main/java/top/continew/admin/tenant/service/TenantService.java
+++ b/continew-plugin/continew-plugin-tenant/src/main/java/top/continew/admin/tenant/service/TenantService.java
@@ -20,7 +20,6 @@ import top.continew.admin.common.base.service.BaseService;
import top.continew.admin.tenant.model.entity.TenantDO;
import top.continew.admin.tenant.model.query.TenantQuery;
import top.continew.admin.tenant.model.req.TenantReq;
-import top.continew.admin.tenant.model.resp.TenantAvailableResp;
import top.continew.admin.tenant.model.resp.TenantDetailResp;
import top.continew.admin.tenant.model.resp.TenantResp;
import top.continew.starter.data.service.IService;
@@ -36,6 +35,22 @@ import java.util.List;
*/
public interface TenantService extends BaseService, IService {
+ /**
+ * 根据绑定域名查询
+ *
+ * @param domain 绑定域名
+ * @return 租户信息
+ */
+ TenantDO getByDomain(String domain);
+
+ /**
+ * 根据编码查询
+ *
+ * @param code 编码
+ * @return 租户信息
+ */
+ TenantDO getByCode(String code);
+
/**
* 检查租户状态
*
@@ -44,7 +59,18 @@ public interface TenantService extends BaseService getAvailableList();
+ void updateTenantMenu(List newMenuIds, Long packageId);
+
+ /**
+ * 根据套餐 ID 查询数量
+ *
+ * @param packageIds 套餐 ID 列表
+ * @return 租户数量
+ */
+ Long countByPackageIds(List packageIds);
}
\ No newline at end of file
diff --git a/continew-plugin/continew-plugin-tenant/src/main/java/top/continew/admin/tenant/service/impl/PackageServiceImpl.java b/continew-plugin/continew-plugin-tenant/src/main/java/top/continew/admin/tenant/service/impl/PackageServiceImpl.java
index 1d7d50cf..1607c056 100644
--- a/continew-plugin/continew-plugin-tenant/src/main/java/top/continew/admin/tenant/service/impl/PackageServiceImpl.java
+++ b/continew-plugin/continew-plugin-tenant/src/main/java/top/continew/admin/tenant/service/impl/PackageServiceImpl.java
@@ -16,27 +16,23 @@
package top.continew.admin.tenant.service.impl;
-import cn.hutool.core.collection.CollUtil;
-import cn.hutool.extra.spring.SpringUtil;
+import jakarta.annotation.Resource;
import lombok.RequiredArgsConstructor;
+import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import top.continew.admin.common.base.service.BaseServiceImpl;
-import top.continew.admin.system.model.entity.MenuDO;
-import top.continew.admin.system.service.MenuService;
+import top.continew.admin.common.enums.DisEnableStatusEnum;
import top.continew.admin.tenant.mapper.PackageMapper;
-import top.continew.admin.tenant.mapper.TenantMapper;
import top.continew.admin.tenant.model.entity.PackageDO;
-import top.continew.admin.tenant.model.entity.TenantDO;
import top.continew.admin.tenant.model.query.PackageQuery;
import top.continew.admin.tenant.model.req.PackageReq;
import top.continew.admin.tenant.model.resp.PackageDetailResp;
import top.continew.admin.tenant.model.resp.PackageResp;
import top.continew.admin.tenant.service.PackageMenuService;
import top.continew.admin.tenant.service.PackageService;
+import top.continew.admin.tenant.service.TenantService;
import top.continew.starter.core.util.validation.CheckUtils;
-import top.continew.starter.extension.tenant.TenantHandler;
-import java.util.ArrayList;
import java.util.List;
/**
@@ -51,8 +47,9 @@ import java.util.List;
public class PackageServiceImpl extends BaseServiceImpl implements PackageService {
private final PackageMenuService packageMenuService;
- private final MenuService menuService;
- private final TenantMapper tenantMapper;
+ @Lazy
+ @Resource
+ private TenantService tenantService;
@Override
public Long create(PackageReq req) {
@@ -75,42 +72,18 @@ public class PackageServiceImpl extends BaseServiceImpl tenantIdList = tenantMapper.lambdaQuery()
- .select(TenantDO::getId)
- .eq(TenantDO::getPackageId, id)
- .list()
- .stream()
- .map(TenantDO::getId)
- .toList();
- if (CollUtil.isEmpty(tenantIdList)) {
- return;
- }
- List oldMenuIds = packageMenuService.listMenuIdsByPackageId(id);
- List newMenuIds = req.getMenuIds();
- // 如果有删除的菜单则绑定了套餐的租户对应的菜单也会删除
- List deleteMenuIds = new ArrayList<>(oldMenuIds);
- deleteMenuIds.removeAll(newMenuIds);
- if (CollUtil.isNotEmpty(deleteMenuIds)) {
- List deleteMenus = menuService.listByIds(deleteMenuIds);
- tenantIdList.forEach(tenantId -> SpringUtil.getBean(TenantHandler.class)
- .execute(tenantId, () -> menuService.deleteTenantMenus(deleteMenus)));
- }
- // 如果有新增的菜单则绑定了套餐的租户对应的菜单也会新增
- List addMenuIds = new ArrayList<>(newMenuIds);
- addMenuIds.removeAll(oldMenuIds);
- if (CollUtil.isNotEmpty(addMenuIds)) {
- List addMenus = menuService.listByIds(addMenuIds);
- for (MenuDO addMenu : addMenus) {
- MenuDO parentMenu = addMenu.getParentId() != 0 ? menuService.getById(addMenu.getParentId()) : null;
- tenantIdList.forEach(tenantId -> SpringUtil.getBean(TenantHandler.class)
- .execute(tenantId, () -> menuService.addTenantMenu(addMenu, parentMenu)));
- }
- }
+ tenantService.updateTenantMenu(req.getMenuIds(), id);
}
@Override
public void beforeDelete(List ids) {
- CheckUtils.throwIf(tenantMapper.lambdaQuery().in(TenantDO::getPackageId, ids).exists(), "所选套餐存在关联租户,不允许删除");
+ CheckUtils.throwIf(tenantService.countByPackageIds(ids) > 0, "所选套餐存在关联租户,不允许删除");
+ }
+
+ @Override
+ public void checkStatus(Long id) {
+ PackageDO entity = this.getById(id);
+ CheckUtils.throwIfEqual(DisEnableStatusEnum.DISABLE, entity.getStatus(), "租户套餐已被禁用");
}
/**
diff --git a/continew-plugin/continew-plugin-tenant/src/main/java/top/continew/admin/tenant/service/impl/TenantServiceImpl.java b/continew-plugin/continew-plugin-tenant/src/main/java/top/continew/admin/tenant/service/impl/TenantServiceImpl.java
index 5b3b182a..a58e9f9b 100644
--- a/continew-plugin/continew-plugin-tenant/src/main/java/top/continew/admin/tenant/service/impl/TenantServiceImpl.java
+++ b/continew-plugin/continew-plugin-tenant/src/main/java/top/continew/admin/tenant/service/impl/TenantServiceImpl.java
@@ -16,25 +16,23 @@
package top.continew.admin.tenant.service.impl;
-import cn.hutool.core.bean.BeanUtil;
-import cn.hutool.core.date.DateUtil;
+import cn.hutool.core.collection.CollUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.alicp.jetcache.anno.Cached;
-import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import me.ahoo.cosid.provider.IdGeneratorProvider;
import org.springframework.stereotype.Service;
import top.continew.admin.common.base.service.BaseServiceImpl;
import top.continew.admin.common.enums.DisEnableStatusEnum;
+import top.continew.admin.system.model.entity.MenuDO;
+import top.continew.admin.system.service.MenuService;
import top.continew.admin.tenant.constant.TenantCacheConstants;
import top.continew.admin.tenant.constant.TenantConstants;
import top.continew.admin.tenant.handler.TenantDataHandler;
import top.continew.admin.tenant.mapper.TenantMapper;
-import top.continew.admin.tenant.model.entity.PackageDO;
import top.continew.admin.tenant.model.entity.TenantDO;
import top.continew.admin.tenant.model.query.TenantQuery;
import top.continew.admin.tenant.model.req.TenantReq;
-import top.continew.admin.tenant.model.resp.TenantAvailableResp;
import top.continew.admin.tenant.model.resp.TenantDetailResp;
import top.continew.admin.tenant.model.resp.TenantResp;
import top.continew.admin.tenant.service.PackageMenuService;
@@ -42,12 +40,12 @@ import top.continew.admin.tenant.service.PackageService;
import top.continew.admin.tenant.service.TenantService;
import top.continew.starter.cache.redisson.util.RedisUtils;
import top.continew.starter.core.util.validation.CheckUtils;
-import top.continew.starter.extension.crud.model.entity.BaseIdDO;
import top.continew.starter.extension.tenant.TenantHandler;
import top.continew.starter.extension.tenant.autoconfigure.TenantProperties;
import java.io.Serializable;
import java.time.LocalDateTime;
+import java.util.ArrayList;
import java.util.List;
/**
@@ -62,17 +60,18 @@ import java.util.List;
public class TenantServiceImpl extends BaseServiceImpl implements TenantService {
private final TenantProperties tenantProperties;
- private final IdGeneratorProvider idGeneratorProvider;
- private final PackageMenuService packageMenuService;
private final PackageService packageService;
+ private final IdGeneratorProvider idGeneratorProvider;
private final TenantDataHandler tenantDataHandler;
+ private final PackageMenuService packageMenuService;
+ private final MenuService menuService;
@Override
public Long create(TenantReq req) {
this.checkNameRepeat(req.getName(), null);
- // 检查租户套餐
- List menuIds = packageMenuService.listMenuIdsByPackageId(req.getPackageId());
- CheckUtils.throwIfEmpty(menuIds, "所选套餐无可用菜单");
+ this.checkDomainRepeat(req.getDomain(), null);
+ // 检查套餐
+ packageService.checkStatus(req.getPackageId());
// 生成租户编码
req.setCode(this.generateCode());
// 新增信息
@@ -86,6 +85,12 @@ public class TenantServiceImpl extends BaseServiceImpl getAvailableList() {
- List tenantList = baseMapper.selectList(Wrappers.lambdaQuery(TenantDO.class)
- .select(TenantDO::getName, BaseIdDO::getId, TenantDO::getDomain)
- .eq(TenantDO::getStatus, DisEnableStatusEnum.ENABLE)
- .and(t -> t.isNull(TenantDO::getExpireTime).or().ge(TenantDO::getExpireTime, DateUtil.date())));
- return BeanUtil.copyToList(tenantList, TenantAvailableResp.class);
+ public TenantDO getByCode(String code) {
+ return baseMapper.lambdaQuery().eq(TenantDO::getCode, code).oneOpt().orElse(null);
+ }
+
+ @Override
+ public void checkStatus(Long id) {
+ TenantDO tenant = this.getById(id);
+ if (id.equals(tenantProperties.getSuperTenantId())) {
+ return;
+ }
+ CheckUtils.throwIfEqual(DisEnableStatusEnum.DISABLE, tenant.getStatus(), "租户已被禁用");
+ CheckUtils.throwIf(tenant.getExpireTime() != null && tenant.getExpireTime()
+ .isBefore(LocalDateTime.now()), "租户已过期");
+ // 检查套餐
+ packageService.checkStatus(tenant.getPackageId());
+ }
+
+ @Override
+ public void updateTenantMenu(List newMenuIds, Long packageId) {
+ List tenantIdList = this.listIdByPackageId(packageId);
+ if (CollUtil.isEmpty(tenantIdList)) {
+ return;
+ }
+ List oldMenuIds = packageMenuService.listMenuIdsByPackageId(packageId);
+ // 如果有删除的菜单则绑定了套餐的租户对应的菜单也会删除
+ List deleteMenuIds = new ArrayList<>(oldMenuIds);
+ deleteMenuIds.removeAll(newMenuIds);
+ if (CollUtil.isNotEmpty(deleteMenuIds)) {
+ List deleteMenus = menuService.listByIds(deleteMenuIds);
+ tenantIdList.forEach(tenantId -> SpringUtil.getBean(TenantHandler.class).execute(tenantId, () -> menuService
+ .deleteTenantMenus(deleteMenus)));
+ }
+ // 如果有新增的菜单则绑定了套餐的租户对应的菜单也会新增
+ List addMenuIds = new ArrayList<>(newMenuIds);
+ addMenuIds.removeAll(oldMenuIds);
+ if (CollUtil.isNotEmpty(addMenuIds)) {
+ List addMenus = menuService.listByIds(addMenuIds);
+ for (MenuDO addMenu : addMenus) {
+ MenuDO parentMenu = addMenu.getParentId() != 0 ? menuService.getById(addMenu.getParentId()) : null;
+ tenantIdList.forEach(tenantId -> SpringUtil.getBean(TenantHandler.class).execute(tenantId, () -> menuService
+ .addTenantMenu(addMenu, parentMenu)));
+ }
+ }
+ }
+
+ @Override
+ public Long countByPackageIds(List packageIds) {
+ return baseMapper.lambdaQuery().in(TenantDO::getPackageId, packageIds).count();
}
/**
- * 名称是否存在
+ * 检查名称是否重复
*
* @param name 名称
* @param id ID
@@ -149,6 +187,19 @@ public class TenantServiceImpl extends BaseServiceImpl listIdByPackageId(Long id) {
+ return baseMapper.lambdaQuery()
+ .select(TenantDO::getId)
+ .eq(TenantDO::getPackageId, id)
+ .list()
+ .stream()
+ .map(TenantDO::getId)
+ .toList();
+ }
}
\ No newline at end of file
diff --git a/continew-server/src/main/java/top/continew/admin/config/satoken/SaExtensionInterceptor.java b/continew-server/src/main/java/top/continew/admin/config/satoken/SaExtensionInterceptor.java
index a7297c79..60846b34 100644
--- a/continew-server/src/main/java/top/continew/admin/config/satoken/SaExtensionInterceptor.java
+++ b/continew-server/src/main/java/top/continew/admin/config/satoken/SaExtensionInterceptor.java
@@ -19,10 +19,18 @@ package top.continew.admin.config.satoken;
import cn.dev33.satoken.fun.SaParamFunction;
import cn.dev33.satoken.interceptor.SaInterceptor;
import cn.dev33.satoken.stp.StpUtil;
+import cn.hutool.extra.servlet.JakartaServletUtil;
+import cn.hutool.json.JSONUtil;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
import org.springframework.lang.Nullable;
+import top.continew.admin.common.context.UserContext;
import top.continew.admin.common.context.UserContextHolder;
+import top.continew.starter.extension.tenant.context.TenantContextHolder;
+import top.continew.starter.web.model.R;
/**
* Sa-Token 扩展拦截器
@@ -30,6 +38,7 @@ import top.continew.admin.common.context.UserContextHolder;
* @author Charles7c
* @since 2024/10/10 20:25
*/
+@Slf4j
public class SaExtensionInterceptor extends SaInterceptor {
public SaExtensionInterceptor(SaParamFunction auth) {
@@ -41,11 +50,24 @@ public class SaExtensionInterceptor extends SaInterceptor {
HttpServletResponse response,
Object handler) throws Exception {
boolean flag = super.preHandle(request, response, handler);
- if (flag && StpUtil.isLogin()) {
- UserContextHolder.getContext();
- UserContextHolder.getExtraContext();
+ if (!flag || !StpUtil.isLogin()) {
+ return flag;
}
- return flag;
+ // 设置上下文
+ UserContext userContext = UserContextHolder.getContext();
+ if (userContext == null) {
+ return true;
+ }
+ // 检查用户租户权限
+ Long userTenantId = userContext.getTenantId();
+ Long tenantId = TenantContextHolder.getTenantId();
+ if (!userTenantId.equals(tenantId)) {
+ JakartaServletUtil.write(response, JSONUtil.toJsonStr(R.fail(String.valueOf(HttpStatus.FORBIDDEN
+ .value()), "您当前没有访问该租户的权限")), MediaType.APPLICATION_JSON_VALUE);
+ return false;
+ }
+ UserContextHolder.getExtraContext();
+ return true;
}
@Override
@@ -53,6 +75,7 @@ public class SaExtensionInterceptor extends SaInterceptor {
HttpServletResponse response,
Object handler,
@Nullable Exception e) throws Exception {
+ // 清除上下文
try {
super.afterCompletion(request, response, handler, e);
} finally {
diff --git a/continew-server/src/main/java/top/continew/admin/controller/common/CaptchaController.java b/continew-server/src/main/java/top/continew/admin/controller/common/CaptchaController.java
index 95de8826..610bab74 100644
--- a/continew-server/src/main/java/top/continew/admin/controller/common/CaptchaController.java
+++ b/continew-server/src/main/java/top/continew/admin/controller/common/CaptchaController.java
@@ -57,6 +57,7 @@ import top.continew.starter.core.autoconfigure.application.ApplicationProperties
import top.continew.starter.core.util.TemplateUtils;
import top.continew.starter.core.util.validation.CheckUtils;
import top.continew.starter.core.util.validation.ValidationUtils;
+import top.continew.starter.extension.tenant.annotation.TenantIgnore;
import top.continew.starter.log.annotation.Log;
import top.continew.starter.messaging.mail.util.MailUtils;
import top.continew.starter.ratelimiter.annotation.RateLimiter;
@@ -78,6 +79,7 @@ import java.util.concurrent.TimeUnit;
* @since 2022/12/11 14:00
*/
@Tag(name = "验证码 API")
+@TenantIgnore
@SaIgnore
@Validated
@RestController
diff --git a/continew-server/src/main/java/top/continew/admin/controller/common/CommonController.java b/continew-server/src/main/java/top/continew/admin/controller/common/CommonController.java
index 2e5ccba8..e1f39905 100644
--- a/continew-server/src/main/java/top/continew/admin/controller/common/CommonController.java
+++ b/continew-server/src/main/java/top/continew/admin/controller/common/CommonController.java
@@ -38,6 +38,7 @@ import top.continew.admin.system.service.*;
import top.continew.starter.core.util.validation.ValidationUtils;
import top.continew.starter.extension.crud.model.query.SortQuery;
import top.continew.starter.extension.crud.model.resp.LabelValueResp;
+import top.continew.starter.extension.tenant.annotation.TenantIgnore;
import top.continew.starter.log.annotation.Log;
import java.io.IOException;
@@ -111,6 +112,7 @@ public class CommonController {
return dictItemService.listByDictCode(code);
}
+ @TenantIgnore
@SaIgnore
@Operation(summary = "查询系统配置参数", description = "查询系统配置参数")
@GetMapping("/dict/option/site")
diff --git a/continew-server/src/main/java/top/continew/admin/job/DemoEnvironmentJob.java b/continew-server/src/main/java/top/continew/admin/job/DemoEnvironmentJob.java
index 2e10ac8a..ec49f77c 100644
--- a/continew-server/src/main/java/top/continew/admin/job/DemoEnvironmentJob.java
+++ b/continew-server/src/main/java/top/continew/admin/job/DemoEnvironmentJob.java
@@ -35,6 +35,7 @@ import top.continew.admin.system.model.entity.user.UserDO;
import top.continew.admin.system.model.entity.user.UserSocialDO;
import top.continew.starter.cache.redisson.util.RedisUtils;
import top.continew.starter.core.constant.StringConstants;
+import top.continew.starter.extension.tenant.annotation.TenantIgnore;
import java.util.List;
import java.util.function.BooleanSupplier;
@@ -78,6 +79,7 @@ public class DemoEnvironmentJob {
/**
* 重置演示环境数据
*/
+ @TenantIgnore
@JobExecutor(name = "ResetEnvironmentData")
@Transactional(rollbackFor = Exception.class)
public void resetEnvironmentData() {
diff --git a/continew-server/src/main/java/top/continew/admin/job/NoticePublishJob.java b/continew-server/src/main/java/top/continew/admin/job/NoticePublishJob.java
index a1b2bbd1..5db17f26 100644
--- a/continew-server/src/main/java/top/continew/admin/job/NoticePublishJob.java
+++ b/continew-server/src/main/java/top/continew/admin/job/NoticePublishJob.java
@@ -33,6 +33,7 @@ import top.continew.admin.system.mapper.NoticeMapper;
import top.continew.admin.system.model.entity.NoticeDO;
import top.continew.admin.system.service.NoticeService;
import top.continew.starter.core.constant.PropertiesConstants;
+import top.continew.starter.extension.tenant.annotation.TenantIgnore;
import java.time.LocalDateTime;
import java.util.List;
@@ -55,6 +56,7 @@ public class NoticePublishJob {
@ConditionalOnProperty(prefix = "snail-job", name = PropertiesConstants.ENABLED, havingValue = "false")
public static class Scheduler {
+ @TenantIgnore
@Scheduled(cron = "0 * * * * ?")
@Transactional(rollbackFor = Exception.class)
public void publishNoticeWithSchedule() {
@@ -71,6 +73,7 @@ public class NoticePublishJob {
@ConditionalOnEnabledScheduleJob
public static class ScheduleJob {
+ @TenantIgnore
@JobExecutor(name = "NoticePublishJob")
@Transactional(rollbackFor = Exception.class)
public void publishNoticeWithScheduleJob() {
diff --git a/continew-server/src/main/resources/config/application.yml b/continew-server/src/main/resources/config/application.yml
index d736cf79..9910f7f0 100644
--- a/continew-server/src/main/resources/config/application.yml
+++ b/continew-server/src/main/resources/config/application.yml
@@ -175,7 +175,7 @@ logging:
--- ### 链路追踪配置
continew-starter.trace:
enabled: true
- trace-id-name: traceId
+ trace-id-name: X-Trace-Id
## TLog 配置
tlog:
enable-invoke-time-print: false
@@ -202,24 +202,27 @@ continew-starter.tenant:
enabled: true
# 隔离级别(默认:LINE,行级)
isolation-level: LINE
- # 超级/默认租户 ID
+ # 超级/默认租户 ID:超管用户所在租户(默认:0)
super-tenant-id: 0
+ # 请求头中租户 ID 键名
+ tenant-id-header: X-Tenant-Id
+ # 请求头中租户编码键名
+ tenant-code-header: X-Tenant-Code
# 忽略表(忽略拼接租户条件)
ignore-tables:
- - gen_config # 代码生成
- - gen_field_config
+ - tenant # 租户表
+ - tenant_package # 租户套餐表
+ - tenant_package_menu # 租户套餐与菜单关联表
+ - gen_config # 代码生成配置表
+ - gen_field_config # 代码生成字段配置表
- sys_dict # 字典表
- - sys_dict_item
- - sys_option # 参数
- - sys_storage # 存储配置
- - tenant # 租户
- - tenant_package
- - tenant_package_menu
- - tenant_datasource
- - sys_client # 客户端管理
- - sys_sms_config
- - sys_sms_log
- - sys_app # 应用
+ - sys_dict_item # 字典项表
+ - sys_option # 参数表
+ - sys_storage # 存储表
+ - sys_sms_config # 短信配置表
+ - sys_sms_log # 短信日志表
+ - sys_client # 客户端表
+ - sys_app # 应用表
# 忽略菜单 ID(租户不能使用的菜单)
ignore-menus:
- 1130 # 字典管理
@@ -229,7 +232,7 @@ continew-starter.tenant:
- 3000 # 租户管理
- 7000 # 能力开放
- 8000 # 任务调度
- - 9000 # 代码生成
+ - 9000 # 开发工具
--- ### 限流器配置
continew-starter:
diff --git a/continew-server/src/main/resources/db/changelog/mysql/plugin/plugin_tenant.sql b/continew-server/src/main/resources/db/changelog/mysql/plugin/plugin_tenant.sql
index 54e08d79..0f421992 100644
--- a/continew-server/src/main/resources/db/changelog/mysql/plugin/plugin_tenant.sql
+++ b/continew-server/src/main/resources/db/changelog/mysql/plugin/plugin_tenant.sql
@@ -7,7 +7,7 @@ CREATE TABLE IF NOT EXISTS `tenant` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
`name` varchar(30) NOT NULL COMMENT '名称',
`code` varchar(30) NOT NULL COMMENT '编码',
- `domain` varchar(255) DEFAULT NULL COMMENT '域名',
+ `domain` varchar(255) DEFAULT NULL COMMENT '绑定域名',
`expire_time` datetime DEFAULT NULL COMMENT '过期时间',
`description` varchar(200) DEFAULT NULL COMMENT '描述',
`status` tinyint(1) UNSIGNED NOT NULL DEFAULT 1 COMMENT '状态(1:启用;2:禁用)',
diff --git a/continew-server/src/main/resources/db/changelog/postgresql/plugin/plugin_tenant.sql b/continew-server/src/main/resources/db/changelog/postgresql/plugin/plugin_tenant.sql
index 7163915d..93ca2157 100644
--- a/continew-server/src/main/resources/db/changelog/postgresql/plugin/plugin_tenant.sql
+++ b/continew-server/src/main/resources/db/changelog/postgresql/plugin/plugin_tenant.sql
@@ -22,13 +22,12 @@ CREATE TABLE IF NOT EXISTS "tenant" (
CREATE UNIQUE INDEX "uk_tenant_code" ON "tenant" ("code");
CREATE INDEX "idx_tenant_admin_user" ON "tenant" ("admin_user");
CREATE INDEX "idx_tenant_package_id" ON "tenant" ("package_id");
-CREATE INDEX "idx_tenant_datasource_id" ON "tenant" ("datasource_id");
CREATE INDEX "idx_tenant_create_user" ON "tenant" ("create_user");
CREATE INDEX "idx_tenant_update_user" ON "tenant" ("update_user");
COMMENT ON COLUMN "tenant"."id" IS 'ID';
COMMENT ON COLUMN "tenant"."name" IS '名称';
COMMENT ON COLUMN "tenant"."code" IS '编码';
-COMMENT ON COLUMN "tenant"."domain" IS '域名';
+COMMENT ON COLUMN "tenant"."domain" IS '绑定域名';
COMMENT ON COLUMN "tenant"."expire_time" IS '过期时间';
COMMENT ON COLUMN "tenant"."description" IS '描述';
COMMENT ON COLUMN "tenant"."status" IS '状态(1:启用;2:禁用)';
diff --git a/continew-system/src/main/java/top/continew/admin/auth/service/impl/OnlineUserServiceImpl.java b/continew-system/src/main/java/top/continew/admin/auth/service/impl/OnlineUserServiceImpl.java
index 097b41f3..5b1e9c2d 100644
--- a/continew-system/src/main/java/top/continew/admin/auth/service/impl/OnlineUserServiceImpl.java
+++ b/continew-system/src/main/java/top/continew/admin/auth/service/impl/OnlineUserServiceImpl.java
@@ -29,13 +29,13 @@ import org.springframework.stereotype.Service;
import top.continew.admin.auth.model.query.OnlineUserQuery;
import top.continew.admin.auth.model.resp.OnlineUserResp;
import top.continew.admin.auth.service.OnlineUserService;
+import top.continew.admin.common.config.TenantExtensionProperties;
import top.continew.admin.common.context.UserContext;
import top.continew.admin.common.context.UserContextHolder;
import top.continew.admin.common.context.UserExtraContext;
import top.continew.starter.core.constant.StringConstants;
import top.continew.starter.extension.crud.model.query.PageQuery;
import top.continew.starter.extension.crud.model.resp.PageResp;
-import top.continew.starter.extension.tenant.autoconfigure.TenantProperties;
import top.continew.starter.extension.tenant.context.TenantContextHolder;
import java.time.LocalDateTime;
@@ -52,7 +52,7 @@ import java.util.stream.Collectors;
@RequiredArgsConstructor
public class OnlineUserServiceImpl implements OnlineUserService {
- private final TenantProperties tenantProperties;
+ private final TenantExtensionProperties tenantExtensionProperties;
@Override
@AutoOperate(type = OnlineUserResp.class, on = "list")
@@ -92,8 +92,8 @@ public class OnlineUserServiceImpl implements OnlineUserService {
.isMatchClientId(query.getClientId(), userContext)) {
continue;
}
- //租户数据过滤
- if (tenantProperties.isEnabled()) {
+ // 只显示本租户数据
+ if (tenantExtensionProperties.isEnabled()) {
if (!TenantContextHolder.getTenantId().equals(userContext.getTenantId())) {
continue;
}
diff --git a/continew-system/src/main/java/top/continew/admin/system/model/entity/user/UserDO.java b/continew-system/src/main/java/top/continew/admin/system/model/entity/user/UserDO.java
index 92ccb92f..1b3ab65f 100644
--- a/continew-system/src/main/java/top/continew/admin/system/model/entity/user/UserDO.java
+++ b/continew-system/src/main/java/top/continew/admin/system/model/entity/user/UserDO.java
@@ -20,11 +20,11 @@ import com.baomidou.mybatisplus.annotation.FieldStrategy;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
+import top.continew.admin.common.base.model.entity.TenantBaseDO;
import top.continew.admin.common.config.mybatis.BCryptEncryptor;
import top.continew.admin.common.enums.DisEnableStatusEnum;
import top.continew.admin.common.enums.GenderEnum;
import top.continew.starter.extension.crud.annotation.DictModel;
-import top.continew.admin.common.base.model.entity.BaseDO;
import top.continew.starter.security.crypto.annotation.FieldEncrypt;
import java.io.Serial;
@@ -39,7 +39,7 @@ import java.time.LocalDateTime;
@Data
@DictModel(labelKey = "nickname", extraKeys = {"username"})
@TableName("sys_user")
-public class UserDO extends BaseDO {
+public class UserDO extends TenantBaseDO {
@Serial
private static final long serialVersionUID = 1L;
@@ -108,10 +108,4 @@ public class UserDO extends BaseDO {
* 部门 ID
*/
private Long deptId;
-
- /**
- * 租户 ID
- */
- @TableField(select = false)
- private Long tenantId;
}
diff --git a/continew-system/src/main/java/top/continew/admin/system/model/query/MenuQuery.java b/continew-system/src/main/java/top/continew/admin/system/model/query/MenuQuery.java
index 9fa4f8f8..5f6eb169 100644
--- a/continew-system/src/main/java/top/continew/admin/system/model/query/MenuQuery.java
+++ b/continew-system/src/main/java/top/continew/admin/system/model/query/MenuQuery.java
@@ -62,6 +62,6 @@ public class MenuQuery implements Serializable {
* 排除的菜单 ID 列表
*/
@Schema(hidden = true, description = "菜单 ID 列表", example = "[9000]")
- @Query(columns = "id", type = QueryType.NOT_IN)
+ @Query(columns = {"id", "parent_id"}, type = QueryType.NOT_IN)
private List excludeMenuIdList;
}
diff --git a/continew-system/src/main/java/top/continew/admin/system/service/impl/DeptServiceImpl.java b/continew-system/src/main/java/top/continew/admin/system/service/impl/DeptServiceImpl.java
index 52a8b503..145ac97b 100644
--- a/continew-system/src/main/java/top/continew/admin/system/service/impl/DeptServiceImpl.java
+++ b/continew-system/src/main/java/top/continew/admin/system/service/impl/DeptServiceImpl.java
@@ -21,6 +21,7 @@ import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import jakarta.annotation.Resource;
import lombok.RequiredArgsConstructor;
+import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import top.continew.admin.common.base.service.BaseServiceImpl;
import top.continew.admin.common.enums.DisEnableStatusEnum;
@@ -53,10 +54,10 @@ import java.util.Optional;
public class DeptServiceImpl extends BaseServiceImpl implements DeptService {
private final RoleDeptService roleDeptService;
+ private final DataSource dataSource;
+ @Lazy
@Resource
private UserService userService;
- @Resource
- private DataSource dataSource;
@Override
public void beforeCreate(DeptReq req) {
diff --git a/continew-system/src/main/java/top/continew/admin/system/service/impl/FileServiceImpl.java b/continew-system/src/main/java/top/continew/admin/system/service/impl/FileServiceImpl.java
index a586ee91..aa284ee3 100644
--- a/continew-system/src/main/java/top/continew/admin/system/service/impl/FileServiceImpl.java
+++ b/continew-system/src/main/java/top/continew/admin/system/service/impl/FileServiceImpl.java
@@ -28,6 +28,7 @@ import org.dromara.x.file.storage.core.FileInfo;
import org.dromara.x.file.storage.core.FileStorageService;
import org.dromara.x.file.storage.core.ProgressListener;
import org.dromara.x.file.storage.core.upload.UploadPretreatment;
+import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import top.continew.admin.common.base.service.BaseServiceImpl;
@@ -64,6 +65,7 @@ import java.util.stream.Collectors;
public class FileServiceImpl extends BaseServiceImpl implements FileService {
private final FileStorageService fileStorageService;
+ @Lazy
@Resource
private StorageService storageService;
diff --git a/continew-system/src/main/java/top/continew/admin/system/service/impl/SmsConfigServiceImpl.java b/continew-system/src/main/java/top/continew/admin/system/service/impl/SmsConfigServiceImpl.java
index b29e51e2..dfe6c6c0 100644
--- a/continew-system/src/main/java/top/continew/admin/system/service/impl/SmsConfigServiceImpl.java
+++ b/continew-system/src/main/java/top/continew/admin/system/service/impl/SmsConfigServiceImpl.java
@@ -73,7 +73,7 @@ public class SmsConfigServiceImpl extends BaseServiceImpl