diff --git a/application-tenant/tenant-admin/src/main/resources/application-config.yml b/application-tenant/tenant-admin/src/main/resources/application-config.yml
new file mode 100644
index 0000000..158d786
--- /dev/null
+++ b/application-tenant/tenant-admin/src/main/resources/application-config.yml
@@ -0,0 +1,161 @@
+server:
+ tomcat:
+ uri-encoding: UTF-8
+ threads:
+ max: 100
+ min-spare: 10
+ servlet:
+ encoding:
+ force: true
+ charset: UTF-8
+ enabled: true
+
+logging:
+ config: classpath:logback-spring.xml
+
+spring:
+ servlet:
+ multipart:
+ max-file-size: 50MB
+ max-request-size: 50MB
+ mvc:
+ converters:
+ preferred-json-mapper: fastjson
+ freemarker:
+ template-loader-path: classpath:/template/
+ cache: false
+ charset: UTF-8
+ check-template-location: true
+ content-type: text/html
+ expose-request-attributes: false
+ expose-session-attributes: false
+ request-context-attribute: request
+ suffix: .ftl
+ cloud:
+ sentinel:
+ transport:
+ # sentinel控制台地址。
+ # 由于8080端口容易与其他服务端口冲突,可以在启动sentinel控制台时动态修改,如:
+ # java -Dserver.port=8858 -jar sentinel-dashboard-$VERSION.jar
+ # 改为8858后,下面的配置端口也需要改为:localhost:8858。
+ dashboard: localhost:8858
+
+# feign 配置
+feign:
+ sentinel:
+ enabled: false
+ httpclient:
+ enabled: true
+ max-connections: 200
+ max-connections-per-route: 50
+ client:
+ config:
+ default:
+ # 输出feignclient的日志,缺省值为none,可选值为none/basic/headers/full
+ # 注意:需要把feignclient类所在包的日志级别设置为debug时才生效。如:
+ # logging:
+ # level:
+ # com.demo.multi: info
+ # com.demo.multi.coursepaperinterface.client: debug
+ loggerLevel: full
+ connectTimeout: 5000
+ readTimeout: 10000
+ compression:
+ request:
+ enabled: true
+ response:
+ enabled: true
+
+common-core:
+ # 可选值为 mysql / postgresql / oracle / dm8 / kingbase
+ databaseType: mysql
+
+swagger:
+ # 当enabled为false的时候,则可禁用swagger。
+ enabled: true
+ # 工程的基础包名。
+ basePackage: apelet
+ # 工程服务的基础包名。
+ serviceBasePackage:
+ title: 小猿微服务工程
+ description: 小猿微服务工程详情
+ version: 1.0
+knife4j:
+ # 打开knife4j增强模式。
+ enable: true
+
+aliyun:
+ oss:
+ enabled: false
+ expireSeconds: 1000
+ # 下面几项均需在申请阿里云OSS后,根据自己的实际情况进行配置。
+ endpoint:
+ accessKey:
+ secretKey:
+ bucketName:
+
+minio:
+ enabled: false
+ endpoint:
+ accessKey:
+ secretKey:
+ bucketName:
+
+# 暴露监控端点
+management:
+ metrics:
+ tags:
+ application: ${spring.application.name}
+ endpoints:
+ web:
+ exposure:
+ include: '*'
+ jmx:
+ exposure:
+ include: '*'
+ endpoint:
+ # 与中间件相关的健康详情也会被展示
+ health:
+ show-details: always
+ configprops:
+ # 在/actuator/configprops中,所有包含password的配置,将用 * 隐藏。
+ # 如果不想隐藏任何配置项的值,可以直接使用如下被注释的空值。
+ # keys-to-sanitize:
+ keys-to-sanitize: password
+ server:
+ base-path: "/"
+
+# 存储session数据的Redis,所有服务均需要,因此放到公共配置中。
+# 根据实际情况,该Redis也可以用于存储其他数据。
+common-redis:
+ # redisson的配置。每个服务可以自己的配置文件中覆盖此选项。
+ redisson:
+ # 如果该值为false,系统将不会创建RedissionClient的bean。
+ enabled: true
+ # mode的可用值为,single/cluster/sentinel/master-slave
+ mode: single
+ # single: 单机模式
+ # address: redis://localhost:6379
+ # cluster: 集群模式
+ # 每个节点逗号分隔,同时每个节点前必须以redis://开头。
+ # address: redis://localhost:6379,redis://localhost:6378,...
+ # sentinel:
+ # 每个节点逗号分隔,同时每个节点前必须以redis://开头。
+ # address: redis://localhost:6379,redis://localhost:6378,...
+ # master-slave:
+ # 每个节点逗号分隔,第一个为主节点,其余为从节点。同时每个节点前必须以redis://开头。
+ # address: redis://localhost:6379,redis://localhost:6378,...
+ address: redis://192.168.100.25:6379
+ # 链接超时,单位毫秒。
+ timeout: 6000
+ # 单位毫秒。分布式锁的超时检测时长。
+ # 如果一次锁内操作超该毫秒数,或在释放锁之前异常退出,Redis会在该时长之后主动删除该锁使用的key。
+ lockWatchdogTimeout: 60000
+ # redis 密码,空可以不填。
+ password:
+ database: 0
+ pool:
+ # 连接池数量。
+ poolSize: 20
+ # 连接池中最小空闲数量。
+ minIdle: 5
diff --git a/application-tenant/tenant-admin/src/main/resources/bootstrap.yml b/application-tenant/tenant-admin/src/main/resources/bootstrap.yml
index e6112a8..f1901e3 100644
--- a/application-tenant/tenant-admin/src/main/resources/bootstrap.yml
+++ b/application-tenant/tenant-admin/src/main/resources/bootstrap.yml
@@ -3,20 +3,14 @@ spring:
name: tenant-admin
profiles:
active: @profile.name@
- cloud:
- nacos:
- discovery:
- server-addr: @discovery.server-addr@
- config:
- server-addr: @config.server-addr@
- group: @config.group@
- namespace: @config.namespace@
- file-extension: yaml
- # 共享配置文件,排序越高后,优先级越高。
- shared-configs:
- - data-id: application-${spring.profiles.active}.yaml
- group: @config.group@
- refresh: true
main:
allow-bean-definition-overriding: true
allow-circular-references: true
+ autoconfigure:
+ exclude:
+ - org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
+ - com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure
+ config:
+ import:
+ - classpath:tenant-admin-dev.yml
+ - classpath:application-config.yml # 引入共享配置
diff --git a/application-tenant/tenant-admin/src/main/resources/logback-spring.xml b/application-tenant/tenant-admin/src/main/resources/logback-spring.xml
index 759d941..68533c6 100644
--- a/application-tenant/tenant-admin/src/main/resources/logback-spring.xml
+++ b/application-tenant/tenant-admin/src/main/resources/logback-spring.xml
@@ -16,6 +16,7 @@ debug:当此属性设置为true时,将打印出logback内部日志信息,
+
@@ -89,48 +91,48 @@ debug:当此属性设置为true时,将打印出logback内部日志信息,
-
-
-
-
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/common/common-generator/src/main/java/apelet/common/generator/service/IOnlFormHeadService.java b/common/common-generator/src/main/java/apelet/common/generator/service/IOnlFormHeadService.java
index 0782aa4..0172fe3 100644
--- a/common/common-generator/src/main/java/apelet/common/generator/service/IOnlFormHeadService.java
+++ b/common/common-generator/src/main/java/apelet/common/generator/service/IOnlFormHeadService.java
@@ -119,4 +119,15 @@ public interface IOnlFormHeadService extends IService {
* @return
*/
OnlFormHead getHeadTableNameCache(String tableName);
+
+ /**
+ * 创建元数据(含默认字段)并同步数据库. 返回创建后的 OnlFormHead.
+ *
+ * @param tableName 表名
+ * @param tableTxt 表描述
+ * @param metaType 表类型: "0"=附表(分录), "1"=主表(业务单据), "2"=单表(基础资料)
+ * @param sortFiled 关联字段(附表时传主表表名)
+ * @return OnlFormHead
+ */
+ OnlFormHead createMetaAndSync(String tableName, String tableTxt, String metaType, String sortFiled);
}
diff --git a/common/common-generator/src/main/java/apelet/common/generator/service/impl/OnlFormHeadServiceImpl.java b/common/common-generator/src/main/java/apelet/common/generator/service/impl/OnlFormHeadServiceImpl.java
index 4f54f5a..bb63a20 100644
--- a/common/common-generator/src/main/java/apelet/common/generator/service/impl/OnlFormHeadServiceImpl.java
+++ b/common/common-generator/src/main/java/apelet/common/generator/service/impl/OnlFormHeadServiceImpl.java
@@ -1660,4 +1660,43 @@ public class OnlFormHeadServiceImpl extends ServiceImpl list) {
onlFormHeadMapper.saveEasDict(list);
}
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public OnlFormHead createMetaAndSync(String tableName, String tableTxt, String metaType, String sortFiled) {
+ OnlFormHead head = new OnlFormHead();
+ head.setId(idGenerator.nextLongId());
+ head.setTableName(tableName);
+ head.setTableTxt(tableTxt);
+ head.setTableType(metaType);
+ head.setStatus("0"); // 未同步状态
+ head.setLine(CustomUtil.MetaType_Entry.equals(metaType) ? 1 : 0);
+ if (StringUtils.isNotEmpty(sortFiled)) {
+ head.setSort(sortFiled);
+ head.setSortFiled("parent_id");
+ }
+
+ // 初始化审计字段(createUserId/updateUserId/createTime/updateTime/deletedFlag)
+ addOrUpdateBaseData(head, head.getId());
+
+ // Build DTO
+ OnlFormHeadDto dto = new OnlFormHeadDto();
+ BeanUtil.copyProperties(head, dto);
+
+ // Generate default fields
+ List defaultFields = new ArrayList<>();
+ defaultData(defaultFields, null, null, metaType);
+ dto.setOnlFormFieldList(defaultFields);
+
+ // Save
+ this.addAll(dto);
+
+ // Reload to get full info
+ OnlFormHead saved = this.getById(head.getId());
+
+ // Sync database (type=0: CREATE TABLE or ALTER TABLE ADD COLUMN)
+ this.syncDB(saved, 0L);
+
+ return saved;
+ }
}
diff --git a/common/common-online/src/main/java/apelet/common/online/controller/OnlineFormController.java b/common/common-online/src/main/java/apelet/common/online/controller/OnlineFormController.java
index 1a1571c..3d98cbd 100644
--- a/common/common-online/src/main/java/apelet/common/online/controller/OnlineFormController.java
+++ b/common/common-online/src/main/java/apelet/common/online/controller/OnlineFormController.java
@@ -3,6 +3,7 @@ package apelet.common.online.controller;
import apelet.common.core.annotation.MyRequestBody;
import apelet.common.core.annotation.NoAuthInterface;
import apelet.common.core.cache.CacheConfig;
+import apelet.common.core.cache.CacheKey;
import apelet.common.core.constant.AppDeviceType;
import apelet.common.core.constant.ErrorCodeEnum;
import apelet.common.core.object.*;
@@ -10,8 +11,14 @@ import apelet.common.core.util.MyCommonUtil;
import apelet.common.core.util.MyModelUtil;
import apelet.common.core.util.MyPageUtil;
import apelet.common.core.validator.UpdateGroup;
+import apelet.common.dbutil.object.SqlTable;
+import apelet.common.dbutil.object.SqlTableColumn;
+import apelet.common.generator.model.OnlFormField;
import apelet.common.generator.model.OnlFormHead;
+import apelet.common.generator.service.IOnlFormFieldService;
import apelet.common.generator.service.IOnlFormHeadService;
+import apelet.common.generator.utils.CustomUtil;
+import apelet.common.generator.utils.cache.MetaCacheService;
import apelet.common.log.annotation.OperationLog;
import apelet.common.log.model.constant.SysOperationLogType;
import apelet.common.online.config.OnlineProperties;
@@ -20,6 +27,7 @@ import apelet.common.online.dto.OnlineFormDto;
import apelet.common.online.model.*;
import apelet.common.online.service.*;
import apelet.common.online.util.OnlineRedisKeyUtil;
+import apelet.common.online.util.WidgetFieldTypeMapping;
import apelet.common.online.vo.OnlineFormVo;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;
@@ -47,6 +55,8 @@ import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.validation.groups.Default;
import java.util.*;
+import java.util.function.Consumer;
+import java.util.function.Function;
import java.util.stream.Collectors;
/**
@@ -81,12 +91,17 @@ public class OnlineFormController {
@Autowired
IOnlFormHeadService onlFormHeadService;
@Autowired
+ IOnlFormFieldService onlFormFieldService;
+ @Autowired
OnlinePageService onlinePageService;
@Autowired
private OnlineProperties properties;
@Resource(name = "caffeineCacheManager")
private CacheManager cacheManager;
+ @Autowired
+ private MetaCacheService metaCacheService;
+
@Autowired(required = false)
private FormButtonPermissionChecker buttonPermissionChecker;
@@ -327,6 +342,13 @@ public class OnlineFormController {
onlineForm.setWidgetJson(jsonObject.toJSONString());
}
+ // ★ 新增: 处理新增字段和子表
+ JSONObject updatedJson = syncNewFieldsAndSubTables(onlineForm, onlineFormDto, JSON.parseObject(onlineForm.getWidgetJson()));
+ if (updatedJson != null) {
+ onlineForm.setWidgetJson(updatedJson.toJSONString());
+ onlineFormDto.setWidgetJson(updatedJson.toJSONString());
+ }
+
if (!onlineFormService.update(onlineForm, originalOnlineForm, datasourceIdSet)) {
redissonClient.getBucket(OnlineRedisKeyUtil.makeOnlineFormKey(onlineForm.getFormId())).delete();
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST);
@@ -591,6 +613,7 @@ public class OnlineFormController {
List