true
always
diff --git a/zt-framework/pom.xml b/zt-framework/pom.xml
index 241a211e..d34ccec7 100644
--- a/zt-framework/pom.xml
+++ b/zt-framework/pom.xml
@@ -25,7 +25,7 @@
zt-spring-boot-starter-job
zt-spring-boot-starter-mq
zt-spring-boot-starter-rpc
-
+ zt-spring-boot-starter-seata-dm
zt-spring-boot-starter-excel
zt-spring-boot-starter-test
diff --git a/zt-framework/zt-spring-boot-starter-seata-dm/pom.xml b/zt-framework/zt-spring-boot-starter-seata-dm/pom.xml
new file mode 100644
index 00000000..49d7b1e2
--- /dev/null
+++ b/zt-framework/zt-spring-boot-starter-seata-dm/pom.xml
@@ -0,0 +1,32 @@
+
+
+
+ zt-framework
+ com.zt.plat
+ ${revision}
+
+ 4.0.0
+ jar
+
+ zt-spring-boot-starter-seata-dm
+
+ ${project.artifactId}
+
+ Seata 达梦数据库补丁模块
+ 解决 DmdbTimestamp 时区格式不一致导致的 dirty undo log 回滚失败问题
+ 补丁来源: https://github.com/apache/incubator-seata/pull/7538
+ Seata 2.6.0 发布后可移除此模块
+
+
+
+
+
+ org.apache.seata
+ seata-spring-boot-starter
+ provided
+
+
+
+
diff --git a/zt-framework/zt-spring-boot-starter-seata-dm/src/main/java/org/apache/seata/rm/datasource/DataCompareUtils.java b/zt-framework/zt-spring-boot-starter-seata-dm/src/main/java/org/apache/seata/rm/datasource/DataCompareUtils.java
new file mode 100644
index 00000000..24c15d5a
--- /dev/null
+++ b/zt-framework/zt-spring-boot-starter-seata-dm/src/main/java/org/apache/seata/rm/datasource/DataCompareUtils.java
@@ -0,0 +1,326 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.seata.rm.datasource;
+
+import org.apache.seata.common.util.CollectionUtils;
+import org.apache.seata.common.util.StringUtils;
+import org.apache.seata.core.model.Result;
+import org.apache.seata.rm.datasource.sql.struct.Field;
+import org.apache.seata.rm.datasource.sql.struct.Row;
+import org.apache.seata.rm.datasource.sql.struct.TableRecords;
+import org.apache.seata.rm.datasource.undo.AbstractUndoLogManager;
+import org.apache.seata.rm.datasource.undo.parser.FastjsonUndoLogParser;
+import org.apache.seata.rm.datasource.undo.parser.JacksonUndoLogParser;
+import org.apache.seata.sqlparser.struct.TableMeta;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.lang.reflect.Method;
+import java.math.BigDecimal;
+import java.sql.Date;
+import java.sql.Time;
+import java.sql.Timestamp;
+import java.sql.Types;
+import java.time.Instant;
+import java.time.LocalDateTime;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
+/**
+ * DataCompareUtils - 包含达梦数据库 DmdbTimestamp 时区问题的补丁
+ *
+ * 此类覆盖 Seata 原有的 DataCompareUtils,添加了对达梦数据库 DmdbTimestamp 类型的特殊处理。
+ * 通过将 DmdbTimestamp 转换为 UTC Instant 进行比较,解决时区格式不一致导致的 dirty undo log 问题。
+ *
+ * 问题背景:
+ * - 达梦数据库的 DmdbTimestamp 类型在序列化/反序列化后时区格式不一致
+ * - 例如:beforeImage 为 "2025-12-25 09:38:54.077811 +08:00"
+ * afterImage 为 "2025-12-25 09:38:54.077811"
+ * - 导致 Seata AT 模式回滚时 dirty undo log 检查失败
+ *
+ * 解决方案:
+ * - 当检测到 DmdbTimestamp 类型时,将两个值都转换为 UTC Instant 进行比较
+ * - 这样可以忽略时区格式差异,只比较实际的时间点
+ *
+ * 补丁来源: https://github.com/apache/incubator-seata/pull/7538
+ * 相关 Issue: https://github.com/apache/incubator-seata/issues/7453
+ * 该修复已合并到 Seata 2.x 分支,将在 Seata 2.6.0 正式发布,届时可删除此模块。
+ *
+ * @author Seata Community (PR #7538)
+ */
+public class DataCompareUtils {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(DataCompareUtils.class);
+
+ /**
+ * 标识补丁类是否已加载
+ */
+ private static final boolean PATCHED;
+
+ static {
+ PATCHED = true;
+ LOGGER.info("[zt-spring-boot-starter-seata-dm] DataCompareUtils 补丁类已加载,用于解决达梦数据库 DmdbTimestamp 时区问题");
+ }
+
+ private DataCompareUtils() {}
+
+ /**
+ * Is field equals result.
+ *
+ * @param f0 the f 0
+ * @param f1 the f 1
+ * @return the result
+ */
+ public static Result isFieldEquals(Field f0, Field f1) {
+ if (f0 == null) {
+ return Result.build(f1 == null);
+ } else {
+ if (f1 == null) {
+ return Result.build(false);
+ } else {
+ if (StringUtils.equalsIgnoreCase(f0.getName(), f1.getName()) && f0.getType() == f1.getType()) {
+ if (f0.getValue() == null) {
+ return Result.build(f1.getValue() == null);
+ } else {
+ if (f1.getValue() == null) {
+ return Result.buildWithParams(
+ false, "Field not equals, name {}, new value is null", f0.getName());
+ } else {
+ String currentSerializer = AbstractUndoLogManager.getCurrentSerializer();
+ if (StringUtils.equals(currentSerializer, FastjsonUndoLogParser.NAME)) {
+ convertType(f0, f1);
+ }
+ // 达梦数据库 DmdbTimestamp 时区补丁 (PR #7538)
+ if (StringUtils.equals(currentSerializer, JacksonUndoLogParser.NAME)) {
+ Object v0 = f0.getValue();
+ Object v1 = f1.getValue();
+ if (isDmdbTimestamp(v0) && isDmdbTimestamp(v1)) {
+ Instant i0 = toInstant(v0);
+ Instant i1 = toInstant(v1);
+ boolean equals = Objects.equals(i0, i1);
+ LOGGER.info("[zt-seata-dm-patch] DmdbTimestamp 字段比较: field={}, equals={}", f0.getName(), equals);
+ return equals
+ ? Result.ok()
+ : Result.buildWithParams(
+ false,
+ "Field not equals (DmdbTimestamp), name {}, old value {}, new value {}",
+ f0.getName(),
+ v0,
+ v1);
+ }
+ }
+ boolean result = Objects.deepEquals(f0.getValue(), f1.getValue());
+ if (result) {
+ return Result.ok();
+ } else {
+ return Result.buildWithParams(
+ false,
+ "Field not equals, name {}, old value {}, new value {}",
+ f0.getName(),
+ f0.getValue(),
+ f1.getValue());
+ }
+ }
+ }
+ } else {
+ return Result.buildWithParams(
+ false,
+ "Field not equals, old name {} type {}, new name {} type {}",
+ f0.getName(),
+ f0.getType(),
+ f1.getName(),
+ f1.getType());
+ }
+ }
+ }
+ }
+
+ private static void convertType(Field f0, Field f1) {
+ int f0Type = f0.getType();
+ int f1Type = f1.getType();
+ if (f0Type == Types.DATE && f0.getValue().getClass().equals(String.class)) {
+ String[] strings = f0.getValue().toString().split(" ");
+ f0.setValue(Date.valueOf(strings[0]));
+ }
+ if (f1Type == Types.DATE && f1.getValue().getClass().equals(String.class)) {
+ String[] strings = f1.getValue().toString().split(" ");
+ f1.setValue(Date.valueOf(strings[0]));
+ }
+ if (f0Type == Types.TIME && f0.getValue().getClass().equals(String.class)) {
+ f0.setValue(Time.valueOf(f0.getValue().toString()));
+ }
+ if (f1Type == Types.TIME && f1.getValue().getClass().equals(String.class)) {
+ f1.setValue(Time.valueOf(f1.getValue().toString()));
+ }
+ if (f0Type == Types.TIMESTAMP && f0.getValue().getClass().equals(String.class)) {
+ if (f1.getValue().getClass().equals(LocalDateTime.class)) {
+ f0.setValue(LocalDateTime.parse(f0.getValue().toString()));
+ } else {
+ f0.setValue(Timestamp.valueOf(f0.getValue().toString()));
+ }
+ }
+ if (f1Type == Types.TIMESTAMP && f1.getValue().getClass().equals(String.class)) {
+ f1.setValue(Timestamp.valueOf(f1.getValue().toString()));
+ }
+ if (f0Type == Types.DECIMAL && f0.getValue().getClass().equals(Integer.class)) {
+ f0.setValue(new BigDecimal(f0.getValue().toString()));
+ }
+ if (f1Type == Types.DECIMAL && f1.getValue().getClass().equals(Integer.class)) {
+ f1.setValue(new BigDecimal(f1.getValue().toString()));
+ }
+ if (f0Type == Types.BIGINT && f0.getValue().getClass().equals(Integer.class)) {
+ f0.setValue(Long.parseLong(f0.getValue().toString()));
+ }
+ if (f1Type == Types.BIGINT && f1.getValue().getClass().equals(Integer.class)) {
+ f1.setValue(Long.parseLong(f1.getValue().toString()));
+ }
+ }
+
+ /**
+ * Is records equals result.
+ *
+ * @param beforeImage the before image
+ * @param afterImage the after image
+ * @return the result
+ */
+ public static Result isRecordsEquals(TableRecords beforeImage, TableRecords afterImage) {
+ if (beforeImage == null) {
+ return Result.build(afterImage == null, null);
+ } else {
+ if (afterImage == null) {
+ return Result.build(false, null);
+ }
+ if (beforeImage.getTableName().equalsIgnoreCase(afterImage.getTableName())
+ && CollectionUtils.isSizeEquals(beforeImage.getRows(), afterImage.getRows())) {
+ // when image is EmptyTableRecords, getTableMeta will throw an exception
+ if (CollectionUtils.isEmpty(beforeImage.getRows())) {
+ return Result.ok();
+ }
+ return compareRows(beforeImage.getTableMeta(), beforeImage.getRows(), afterImage.getRows());
+ } else {
+ return Result.build(false, null);
+ }
+ }
+ }
+
+ /**
+ * Is rows equals result.
+ *
+ * @param tableMetaData the table meta data
+ * @param oldRows the old rows
+ * @param newRows the new rows
+ * @return the result
+ */
+ public static Result isRowsEquals(TableMeta tableMetaData, List oldRows, List newRows) {
+ if (!CollectionUtils.isSizeEquals(oldRows, newRows)) {
+ return Result.build(false, null);
+ }
+ return compareRows(tableMetaData, oldRows, newRows);
+ }
+
+ private static Result compareRows(TableMeta tableMetaData, List oldRows, List newRows) {
+ // old row to map
+ Map> oldRowsMap = rowListToMap(oldRows, tableMetaData.getPrimaryKeyOnlyName());
+ // new row to map
+ Map> newRowsMap = rowListToMap(newRows, tableMetaData.getPrimaryKeyOnlyName());
+ // compare data
+ for (Map.Entry> oldEntry : oldRowsMap.entrySet()) {
+ String key = oldEntry.getKey();
+ Map oldRow = oldEntry.getValue();
+ Map newRow = newRowsMap.get(key);
+ if (newRow == null) {
+ return Result.buildWithParams(false, "compare row failed, rowKey {}, reason [newRow is null]", key);
+ }
+ for (Map.Entry oldRowEntry : oldRow.entrySet()) {
+ String fieldName = oldRowEntry.getKey();
+ Field oldField = oldRowEntry.getValue();
+ Field newField = newRow.get(fieldName);
+ if (newField == null) {
+ return Result.buildWithParams(
+ false,
+ "compare row failed, rowKey {}, fieldName {}, reason [newField is null]",
+ key,
+ fieldName);
+ }
+ Result oldEqualsNewFieldResult = isFieldEquals(oldField, newField);
+ if (!oldEqualsNewFieldResult.getResult()) {
+ return oldEqualsNewFieldResult;
+ }
+ }
+ }
+ return Result.ok();
+ }
+
+ /**
+ * Row list to map map.
+ *
+ * @param rowList the row list
+ * @param primaryKeyList the primary key list
+ * @return the map
+ */
+ public static Map> rowListToMap(List rowList, List primaryKeyList) {
+ // {value of primaryKey, value of all columns}
+ Map> rowMap = new HashMap<>();
+ for (Row row : rowList) {
+ // ensure the order of column
+ List rowFieldList = row.getFields().stream()
+ .sorted(Comparator.comparing(Field::getName))
+ .collect(Collectors.toList());
+ // {uppercase fieldName : field}
+ Map colsMap = new HashMap<>();
+ StringBuilder rowKey = new StringBuilder();
+ boolean firstUnderline = false;
+ for (int j = 0; j < rowFieldList.size(); j++) {
+ Field field = rowFieldList.get(j);
+ if (primaryKeyList.stream().anyMatch(e -> field.getName().equals(e))) {
+ if (firstUnderline && j > 0) {
+ rowKey.append("_");
+ }
+ rowKey.append(String.valueOf(field.getValue()));
+ firstUnderline = true;
+ }
+ colsMap.put(field.getName().trim().toUpperCase(), field);
+ }
+ rowMap.put(rowKey.toString(), colsMap);
+ }
+ return rowMap;
+ }
+
+ /**
+ * 判断是否为达梦数据库的 DmdbTimestamp 类型
+ */
+ private static boolean isDmdbTimestamp(Object obj) {
+ return obj != null
+ && "dm.jdbc.driver.DmdbTimestamp".equals(obj.getClass().getName());
+ }
+
+ /**
+ * 将 DmdbTimestamp 转换为 Instant
+ */
+ private static Instant toInstant(Object dmdbTimestamp) {
+ try {
+ Method toInstantMethod = dmdbTimestamp.getClass().getMethod("toInstant");
+ return (Instant) toInstantMethod.invoke(dmdbTimestamp);
+ } catch (Exception e) {
+ throw new RuntimeException("Failed to convert DmdbTimestamp to Instant", e);
+ }
+ }
+}
From a44e7e835e553d7b5d718e3b05149eb8820021ef Mon Sep 17 00:00:00 2001
From: lenovo <549193112@qq.com>
Date: Thu, 15 Jan 2026 14:45:43 +0800
Subject: [PATCH 6/8] =?UTF-8?q?=E4=BF=AE=E5=A4=8DBUG710=EF=BC=8C=E6=B7=BB?=
=?UTF-8?q?=E5=8A=A0=E6=96=87=E4=BB=B6=E4=B8=8B=E8=BD=BD=E6=AC=A1=E6=95=B0?=
=?UTF-8?q?=E7=BB=9F=E8=AE=A1?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
sql/dm/ruoyi-vue-pro-dm8.sql | 4 +++-
sql/dm/添加文件下载次数统计字段.sql | 5 +++++
.../com/zt/plat/module/infra/api/file/dto/FileRespDTO.java | 3 +++
.../module/infra/controller/admin/file/FileController.java | 4 ++++
.../infra/controller/admin/file/vo/file/FileRespVO.java | 3 +++
.../zt/plat/module/infra/dal/dataobject/file/FileDO.java | 5 +++++
.../zt/plat/module/infra/dal/mysql/file/FileMapper.java | 5 +++++
.../com/zt/plat/module/infra/service/file/FileService.java | 7 +++++++
.../zt/plat/module/infra/service/file/FileServiceImpl.java | 5 +++++
9 files changed, 40 insertions(+), 1 deletion(-)
create mode 100644 sql/dm/添加文件下载次数统计字段.sql
diff --git a/sql/dm/ruoyi-vue-pro-dm8.sql b/sql/dm/ruoyi-vue-pro-dm8.sql
index 9dc55d0a..1a0eba7e 100644
--- a/sql/dm/ruoyi-vue-pro-dm8.sql
+++ b/sql/dm/ruoyi-vue-pro-dm8.sql
@@ -339,7 +339,8 @@ CREATE TABLE infra_file (
create_time datetime DEFAULT CURRENT_TIMESTAMP NOT NULL,
updater varchar(64) DEFAULT '' NULL,
update_time datetime DEFAULT CURRENT_TIMESTAMP NOT NULL,
- deleted bit DEFAULT '0' NOT NULL
+ deleted bit DEFAULT '0' NOT NULL,
+ DOWNLOAD_COUNT INT DEFAULT 0 NOT NULL
);
COMMENT ON COLUMN infra_file.id IS '文件编号';
@@ -356,6 +357,7 @@ COMMENT ON COLUMN infra_file.create_time IS '创建时间';
COMMENT ON COLUMN infra_file.updater IS '更新者';
COMMENT ON COLUMN infra_file.update_time IS '更新时间';
COMMENT ON COLUMN infra_file.deleted IS '是否删除';
+COMMENT ON COLUMN INFRA_FILE.DOWNLOAD_COUNT IS '下载次数';
COMMENT ON TABLE infra_file IS '文件表';
CREATE INDEX idx_infra_file_hash ON infra_file(hash);
diff --git a/sql/dm/添加文件下载次数统计字段.sql b/sql/dm/添加文件下载次数统计字段.sql
new file mode 100644
index 00000000..dac2a7b7
--- /dev/null
+++ b/sql/dm/添加文件下载次数统计字段.sql
@@ -0,0 +1,5 @@
+-- 添加文件下载次数统计字段
+ALTER TABLE JYGK_TEST.INFRA_FILE
+ ADD DOWNLOAD_COUNT INT DEFAULT 0 NOT NULL;
+
+COMMENT ON COLUMN JYGK_TEST.INFRA_FILE.DOWNLOAD_COUNT IS '下载次数';
\ No newline at end of file
diff --git a/zt-module-infra/zt-module-infra-api/src/main/java/com/zt/plat/module/infra/api/file/dto/FileRespDTO.java b/zt-module-infra/zt-module-infra-api/src/main/java/com/zt/plat/module/infra/api/file/dto/FileRespDTO.java
index 01093d15..58af4c9a 100644
--- a/zt-module-infra/zt-module-infra-api/src/main/java/com/zt/plat/module/infra/api/file/dto/FileRespDTO.java
+++ b/zt-module-infra/zt-module-infra-api/src/main/java/com/zt/plat/module/infra/api/file/dto/FileRespDTO.java
@@ -34,4 +34,7 @@ public class FileRespDTO {
@Schema(description = "文件内容", requiredMode = Schema.RequiredMode.REQUIRED)
private byte[] content;
+ @Schema(description = "文件下载次数")
+ private Integer downloadCount;
+
}
\ No newline at end of file
diff --git a/zt-module-infra/zt-module-infra-server/src/main/java/com/zt/plat/module/infra/controller/admin/file/FileController.java b/zt-module-infra/zt-module-infra-server/src/main/java/com/zt/plat/module/infra/controller/admin/file/FileController.java
index 101a2654..d4b971a9 100644
--- a/zt-module-infra/zt-module-infra-server/src/main/java/com/zt/plat/module/infra/controller/admin/file/FileController.java
+++ b/zt-module-infra/zt-module-infra-server/src/main/java/com/zt/plat/module/infra/controller/admin/file/FileController.java
@@ -133,6 +133,10 @@ public class FileController {
response.setStatus(HttpStatus.NOT_FOUND.value());
return;
}
+
+ // 统计下载次数
+ fileService.incDownloadCount(configId,path);
+
writeAttachment(response, path, content);
}
diff --git a/zt-module-infra/zt-module-infra-server/src/main/java/com/zt/plat/module/infra/controller/admin/file/vo/file/FileRespVO.java b/zt-module-infra/zt-module-infra-server/src/main/java/com/zt/plat/module/infra/controller/admin/file/vo/file/FileRespVO.java
index 161cf629..6d4d12f4 100644
--- a/zt-module-infra/zt-module-infra-server/src/main/java/com/zt/plat/module/infra/controller/admin/file/vo/file/FileRespVO.java
+++ b/zt-module-infra/zt-module-infra-server/src/main/java/com/zt/plat/module/infra/controller/admin/file/vo/file/FileRespVO.java
@@ -99,4 +99,7 @@ public class FileRespVO {
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime createTime;
+ @Schema(description = "下载次数")
+ private Integer downloadCount;
+
}
diff --git a/zt-module-infra/zt-module-infra-server/src/main/java/com/zt/plat/module/infra/dal/dataobject/file/FileDO.java b/zt-module-infra/zt-module-infra-server/src/main/java/com/zt/plat/module/infra/dal/dataobject/file/FileDO.java
index 131ea253..c82c0e3c 100644
--- a/zt-module-infra/zt-module-infra-server/src/main/java/com/zt/plat/module/infra/dal/dataobject/file/FileDO.java
+++ b/zt-module-infra/zt-module-infra-server/src/main/java/com/zt/plat/module/infra/dal/dataobject/file/FileDO.java
@@ -65,6 +65,11 @@ public class FileDO extends BaseDO {
*/
private String aesIv;
+ /**
+ * 文件下载次数统计
+ */
+ private Integer downloadCount;
+
/**
* 是否加密
*
diff --git a/zt-module-infra/zt-module-infra-server/src/main/java/com/zt/plat/module/infra/dal/mysql/file/FileMapper.java b/zt-module-infra/zt-module-infra-server/src/main/java/com/zt/plat/module/infra/dal/mysql/file/FileMapper.java
index df330c49..9857cdc2 100644
--- a/zt-module-infra/zt-module-infra-server/src/main/java/com/zt/plat/module/infra/dal/mysql/file/FileMapper.java
+++ b/zt-module-infra/zt-module-infra-server/src/main/java/com/zt/plat/module/infra/dal/mysql/file/FileMapper.java
@@ -6,6 +6,8 @@ import com.zt.plat.framework.mybatis.core.query.LambdaQueryWrapperX;
import com.zt.plat.module.infra.controller.admin.file.vo.file.FilePageReqVO;
import com.zt.plat.module.infra.dal.dataobject.file.FileDO;
import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Update;
/**
* 文件操作 Mapper
@@ -32,4 +34,7 @@ public interface FileMapper extends BaseMapperX {
return selectFirstOne(FileDO::getHash, hash);
}
+
+ @Update("UPDATE INFRA_FILE SET DOWNLOAD_COUNT = DOWNLOAD_COUNT + 1 WHERE CONFIG_ID = #{configId} AND PATH = #{path}")
+ int incDownloadCount(@Param("configId") Long configId, @Param("path") String path);
}
diff --git a/zt-module-infra/zt-module-infra-server/src/main/java/com/zt/plat/module/infra/service/file/FileService.java b/zt-module-infra/zt-module-infra-server/src/main/java/com/zt/plat/module/infra/service/file/FileService.java
index 96e6b3d4..6624810c 100644
--- a/zt-module-infra/zt-module-infra-server/src/main/java/com/zt/plat/module/infra/service/file/FileService.java
+++ b/zt-module-infra/zt-module-infra-server/src/main/java/com/zt/plat/module/infra/service/file/FileService.java
@@ -112,4 +112,11 @@ public interface FileService {
FileDO getActiveFileById(Long fileId);
boolean verifyCode(Long fileId, Long userId, String code) throws Exception;
+
+ /**
+ * 更新文件下载次数
+ * @param configId
+ * @param path
+ */
+ void incDownloadCount(Long configId, String path);
}
diff --git a/zt-module-infra/zt-module-infra-server/src/main/java/com/zt/plat/module/infra/service/file/FileServiceImpl.java b/zt-module-infra/zt-module-infra-server/src/main/java/com/zt/plat/module/infra/service/file/FileServiceImpl.java
index 2c62ec69..14f42c77 100644
--- a/zt-module-infra/zt-module-infra-server/src/main/java/com/zt/plat/module/infra/service/file/FileServiceImpl.java
+++ b/zt-module-infra/zt-module-infra-server/src/main/java/com/zt/plat/module/infra/service/file/FileServiceImpl.java
@@ -334,4 +334,9 @@ public class FileServiceImpl implements FileService {
}
}
+ @Override
+ public void incDownloadCount(Long configId, String path) {
+ fileMapper.incDownloadCount(configId, path);
+ }
+
}
From 8a7c74bfb57249302bae9ba61c6c0b2a0a990803 Mon Sep 17 00:00:00 2001
From: ranke <213539@qq.com>
Date: Thu, 15 Jan 2026 15:54:18 +0800
Subject: [PATCH 7/8] =?UTF-8?q?=E4=BF=AE=E6=94=B9docker=E9=85=8D=E7=BD=AE?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
zt-module-infra/zt-module-infra-server-app/Dockerfile | 2 +-
zt-module-report/zt-module-report-server-app/Dockerfile | 2 +-
zt-module-system/zt-module-system-server-app/Dockerfile | 2 +-
zt-module-template/zt-module-template-server-app/Dockerfile | 2 +-
4 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/zt-module-infra/zt-module-infra-server-app/Dockerfile b/zt-module-infra/zt-module-infra-server-app/Dockerfile
index 76f0282c..cdcdd75f 100644
--- a/zt-module-infra/zt-module-infra-server-app/Dockerfile
+++ b/zt-module-infra/zt-module-infra-server-app/Dockerfile
@@ -6,7 +6,7 @@ FROM 172.16.46.66:10043/base-service/eclipse-temurin:21-jre
RUN mkdir -p /zt-module-infra-server-app
WORKDIR /zt-module-infra-server-app
## 将后端项目的 Jar 文件,复制到镜像中
-COPY ../zt-module-infra-server/target/zt-module-infra-server-app.jar app.jar
+COPY ./target/zt-module-infra-server-app.jar app.jar
## 设置 TZ 时区
## 设置 JAVA_OPTS 环境变量,可通过 docker run -e "JAVA_OPTS=" 进行覆盖
diff --git a/zt-module-report/zt-module-report-server-app/Dockerfile b/zt-module-report/zt-module-report-server-app/Dockerfile
index 6e5aa793..32367c0b 100644
--- a/zt-module-report/zt-module-report-server-app/Dockerfile
+++ b/zt-module-report/zt-module-report-server-app/Dockerfile
@@ -6,7 +6,7 @@ FROM 172.16.46.66:10043/base-service/eclipse-temurin:21-jre
RUN mkdir -p /zt-module-report-server-app
WORKDIR /zt-module-report-server-app
## 将后端项目的 Jar 文件,复制到镜像中
-COPY ../zt-module-report-server/target/zt-module-report-server-app.jar app.jar
+COPY ./target/zt-module-report-server-app.jar app.jar
## 设置 TZ 时区
## 设置 JAVA_OPTS 环境变量,可通过 docker run -e "JAVA_OPTS=" 进行覆盖
diff --git a/zt-module-system/zt-module-system-server-app/Dockerfile b/zt-module-system/zt-module-system-server-app/Dockerfile
index 611da8b3..fed0ffb7 100644
--- a/zt-module-system/zt-module-system-server-app/Dockerfile
+++ b/zt-module-system/zt-module-system-server-app/Dockerfile
@@ -6,7 +6,7 @@ FROM 172.16.46.66:10043/base-service/eclipse-temurin:21-jre
RUN mkdir -p /zt-module-system-server-app
WORKDIR /zt-module-system-server-app
## 将后端项目的 Jar 文件,复制到镜像中
-COPY ../zt-module-system-server/target/zt-module-system-server-app.jar app.jar
+COPY ./target/zt-module-system-server-app.jar app.jar
## 设置 TZ 时区
## 设置 JAVA_OPTS 环境变量,可通过 docker run -e "JAVA_OPTS=" 进行覆盖
diff --git a/zt-module-template/zt-module-template-server-app/Dockerfile b/zt-module-template/zt-module-template-server-app/Dockerfile
index 0630e44e..38331059 100644
--- a/zt-module-template/zt-module-template-server-app/Dockerfile
+++ b/zt-module-template/zt-module-template-server-app/Dockerfile
@@ -6,7 +6,7 @@ FROM 172.16.46.66:10043/base-service/eclipse-temurin:21-jre
RUN mkdir -p /zt-module-template-server-app
WORKDIR /zt-module-template-server-app
## 将后端项目的 Jar 文件,复制到镜像中
-COPY ../zt-module-template-server/target/zt-module-template-server-app.jar app.jar
+COPY ./target/zt-module-template-server-app.jar app.jar
## 设置 TZ 时区
## 设置 JAVA_OPTS 环境变量,可通过 docker run -e "JAVA_OPTS=" 进行覆盖
From d1e2e25b96295b18ee32fce6bc0974395e0e0a60 Mon Sep 17 00:00:00 2001
From: ranke <213539@qq.com>
Date: Thu, 15 Jan 2026 16:05:02 +0800
Subject: [PATCH 8/8] =?UTF-8?q?=E6=96=B0=E5=A2=9E=20zt-module-databus-serv?=
=?UTF-8?q?er-app=20=E7=9A=84=20dockerfile?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../zt-module-databus-server-app/Dockerfile | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
create mode 100644 zt-module-databus/zt-module-databus-server-app/Dockerfile
diff --git a/zt-module-databus/zt-module-databus-server-app/Dockerfile b/zt-module-databus/zt-module-databus-server-app/Dockerfile
new file mode 100644
index 00000000..aff90a83
--- /dev/null
+++ b/zt-module-databus/zt-module-databus-server-app/Dockerfile
@@ -0,0 +1,19 @@
+## AdoptOpenJDK 停止发布 OpenJDK 二进制,而 Eclipse Temurin 是它的延伸,提供更好的稳定性
+
+FROM 172.16.46.66:10043/base-service/eclipse-temurin:21-jre
+
+## 创建目录,并使用它作为工作目录
+RUN mkdir -p /zt-module-databus-server-app
+WORKDIR /zt-module-databus-server-app
+## 将后端项目的 Jar 文件,复制到镜像中
+COPY ./target/zt-module-databus-server-app.jar app.jar
+
+## 设置 TZ 时区
+## 设置 JAVA_OPTS 环境变量,可通过 docker run -e "JAVA_OPTS=" 进行覆盖
+ENV TZ=Asia/Shanghai JAVA_OPTS="-Xms512m -Xmx1024m"
+
+## 暴露后端项目的 48080 端口
+EXPOSE 48082
+
+## 启动后端项目
+CMD java ${JAVA_OPTS} -Djava.security.egd=file:/dev/./urandom -jar app.jar