Merge remote-tracking branch 'origin/dev' into dev

This commit is contained in:
hewencai
2025-12-04 14:07:00 +08:00
84 changed files with 1619 additions and 945 deletions

View File

@@ -13,7 +13,7 @@ import lombok.Getter;
public enum DocumentEnum {
REDIS_INSTALL("https://gitee.com/zhijiantianya/ruoyi-vue-pro/issues/I4VCSJ", "Redis 安装文档"),
TENANT("https://doc.iocoder.cn", "SaaS 多租户文档");
TENANT("http://172.16.46.63:30888", "SaaS 多租户文档");
private final String url;
private final String memo;

View File

@@ -36,6 +36,11 @@
<artifactId>zt-spring-boot-starter-biz-tenant</artifactId>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>com.zt.plat</groupId>
<artifactId>zt-spring-boot-starter-mybatis</artifactId>
<version>${revision}</version>
</dependency>
<!-- Test 测试相关 -->
<dependency>
<groupId>com.zt.plat</groupId>

View File

@@ -2,27 +2,54 @@ package com.zt.plat.framework.business.framework;
import com.zt.plat.framework.datapermission.core.rule.company.CompanyDataPermissionRuleCustomizer;
import com.zt.plat.framework.datapermission.core.rule.dept.DeptDataPermissionRuleCustomizer;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.boot.autoconfigure.AutoConfigurationPackages;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.LinkedHashSet;
import java.util.Set;
/**
* @author chenbowen
* 自动为继承 BusinessBaseDO 的实体注册公司/部门数据权限字段。
*/
@Configuration(proxyBeanMethods = false)
public class BusinessDataPermissionConfiguration {
@Bean
public CompanyDataPermissionRuleCustomizer sysCompanyDataPermissionRuleCustomizer() {
return rule -> {
// companyId
rule.addCompanyColumn("demo_contract", "company_id");
};
public BusinessDataPermissionEntityScanner businessDataPermissionEntityScanner(BeanFactory beanFactory, ApplicationContext applicationContext) {
Set<String> basePackages = new LinkedHashSet<>();
if (AutoConfigurationPackages.has(beanFactory)) {
basePackages.addAll(AutoConfigurationPackages.get(beanFactory));
}
if (basePackages.isEmpty()) {
basePackages.add("com.zt");
}
ClassLoader classLoader = applicationContext != null
? applicationContext.getClassLoader()
: Thread.currentThread().getContextClassLoader();
if (classLoader == null) {
classLoader = BusinessDataPermissionConfiguration.class.getClassLoader();
}
return new BusinessDataPermissionEntityScanner(basePackages, classLoader);
}
@Bean
public DeptDataPermissionRuleCustomizer businessDeptDataPermissionRuleCustomizer() {
return rule -> {
// dept
rule.addDeptColumn("demo_contract", "dept_id");
};
public CompanyDataPermissionRuleCustomizer autoCompanyDataPermissionRuleCustomizer(BusinessDataPermissionEntityScanner scanner) {
return rule -> scanner.getEntityMetadata().forEach(metadata -> {
if (metadata.hasCompanyColumn()) {
rule.addCompanyColumn(metadata.getTableName(), metadata.getCompanyColumn());
}
});
}
@Bean
public DeptDataPermissionRuleCustomizer autoDeptDataPermissionRuleCustomizer(BusinessDataPermissionEntityScanner scanner) {
return rule -> scanner.getEntityMetadata().forEach(metadata -> {
if (metadata.hasDeptColumn()) {
rule.addDeptColumn(metadata.getTableName(), metadata.getDeptColumn());
}
});
}
}

View File

@@ -0,0 +1,23 @@
package com.zt.plat.framework.mybatis.core.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 标记业务实体对应表中的公司字段名称,默认 company_id。
*
* @author chenbow
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface CompanyColumn {
/**
* 表中公司字段名称
*/
String value() default "company_id";
}

View File

@@ -0,0 +1,23 @@
package com.zt.plat.framework.mybatis.core.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 标记业务实体对应表中的部门字段名称,默认 dept_id。
*
* @author chenbow
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface DeptColumn {
/**
* 表中部门字段名称
*/
String value() default "dept_id";
}

View File

@@ -2,6 +2,8 @@ package com.zt.plat.framework.mybatis.core.dataobject;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import com.zt.plat.framework.mybatis.core.annotation.CompanyColumn;
import com.zt.plat.framework.mybatis.core.annotation.DeptColumn;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.apache.ibatis.type.JdbcType;
@@ -13,6 +15,8 @@ import java.util.List;
*/
@Data
@EqualsAndHashCode(callSuper = true)
@CompanyColumn
@DeptColumn
public class BusinessBaseDO extends BaseDO {
/** 公司编号 */

View File

@@ -6,6 +6,7 @@ import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.servlet.JakartaServletUtil;
import com.fasterxml.jackson.databind.exc.InvalidFormatException;
import com.zt.plat.framework.common.biz.infra.logger.ApiErrorLogCommonApi;
import com.zt.plat.framework.common.biz.infra.logger.dto.ApiErrorLogCreateReqDTO;
import com.zt.plat.framework.common.exception.ServiceException;
@@ -16,7 +17,6 @@ import com.zt.plat.framework.common.util.json.JsonUtils;
import com.zt.plat.framework.common.util.monitor.TracerUtils;
import com.zt.plat.framework.common.util.servlet.ServletUtils;
import com.zt.plat.framework.web.core.util.WebFrameworkUtils;
import com.fasterxml.jackson.databind.exc.InvalidFormatException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.validation.ConstraintViolation;
import jakarta.validation.ConstraintViolationException;
@@ -365,42 +365,12 @@ public class GlobalExceptionHandler {
return CommonResult.error(NOT_IMPLEMENTED.getCode(),
"[微信公众号 zt-module-mp - 表结构未导入][参考 http://172.16.46.63:30888/mp/build/ 开启]");
}
// 4. 商城系统
if (StrUtil.containsAny(message, "product_", "promotion_", "trade_")) {
log.error("[商城系统 zt-module-mall - 已禁用][参考 http://172.16.46.63:30888/mall/build/ 开启]");
return CommonResult.error(NOT_IMPLEMENTED.getCode(),
"[商城系统 zt-module-mall - 已禁用][参考 http://172.16.46.63:30888/mall/build/ 开启]");
}
// 5. ERP 系统
if (message.contains("erp_")) {
log.error("[ERP 系统 zt-module-erp - 表结构未导入][参考 http://172.16.46.63:30888/erp/build/ 开启]");
return CommonResult.error(NOT_IMPLEMENTED.getCode(),
"[ERP 系统 zt-module-erp - 表结构未导入][参考 http://172.16.46.63:30888/erp/build/ 开启]");
}
// 6. CRM 系统
if (message.contains("crm_")) {
log.error("[CRM 系统 zt-module-crm - 表结构未导入][参考 http://172.16.46.63:30888/crm/build/ 开启]");
return CommonResult.error(NOT_IMPLEMENTED.getCode(),
"[CRM 系统 zt-module-crm - 表结构未导入][参考 http://172.16.46.63:30888/crm/build/ 开启]");
}
// 7. 支付平台
if (message.contains("pay_")) {
log.error("[支付模块 zt-module-pay - 表结构未导入][参考 http://172.16.46.63:30888/pay/build/ 开启]");
return CommonResult.error(NOT_IMPLEMENTED.getCode(),
"[支付模块 zt-module-pay - 表结构未导入][参考 http://172.16.46.63:30888/pay/build/ 开启]");
}
// 8. AI 大模型
if (message.contains("ai_")) {
log.error("[AI 大模型 zt-module-ai - 表结构未导入][参考 http://172.16.46.63:30888/ai/build/ 开启]");
return CommonResult.error(NOT_IMPLEMENTED.getCode(),
"[AI 大模型 zt-module-ai - 表结构未导入][参考 http://172.16.46.63:30888/ai/build/ 开启]");
}
// 9. IOT 物联网
if (message.contains("iot_")) {
log.error("[IoT 物联网 zt-module-iot - 表结构未导入][参考 https://doc.iocoder.cn/iot/build/ 开启]");
return CommonResult.error(NOT_IMPLEMENTED.getCode(),
"[IoT 物联网 zt-module-iot - 表结构未导入][参考 https://doc.iocoder.cn/iot/build/ 开启]");
}
return null;
}

View File

@@ -48,7 +48,7 @@ public class DesensitizeTest {
DesensitizeDemo d = JsonUtils.parseObject(JsonUtils.toJsonString(desensitizeDemo), DesensitizeDemo.class);
// 断言
assertNotNull(d);
assertEquals("***", d.getNickname());
assertEquals("Z***", d.getNickname());
assertEquals("998800********31", d.getBankCard());
assertEquals("粤A6***6", d.getCarLicense());
assertEquals("0108*****22", d.getFixedPhone());