From 427c0bd6b1c04b2da4d99a39349131f168b8a509 Mon Sep 17 00:00:00 2001
From: hewencai <2357300448@qq.com>
Date: Mon, 10 Nov 2025 10:41:08 +0800
Subject: [PATCH 1/6] =?UTF-8?q?add:=E5=A2=9E=E5=8A=A0seata=E5=92=8Cdoc4j?=
=?UTF-8?q?=E4=BE=9D=E8=B5=96?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
zt-dependencies/pom.xml | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/zt-dependencies/pom.xml b/zt-dependencies/pom.xml
index b0a132d9..cf5b81fe 100644
--- a/zt-dependencies/pom.xml
+++ b/zt-dependencies/pom.xml
@@ -32,6 +32,8 @@
3.4.5
2024.0.1
2023.0.3.2
+
+ 2.4.0
2.8.3
4.6.0
@@ -87,6 +89,8 @@
1.2.5
0.9.0
4.12.0
+ 11.4.7
+ 11.4.7
2.15.1
4.5.13
@@ -132,6 +136,20 @@
import
+
+
+
+
+ org.apache.seata
+ seata-all
+ ${seata.version}
+
+
+ org.apache.seata
+ seata-spring-boot-starter
+ ${seata.version}
+
+
io.github.mouzt
From 5e24c5a509ac7e138fd62aafacbfad1186c13b75 Mon Sep 17 00:00:00 2001
From: hewencai <2357300448@qq.com>
Date: Thu, 13 Nov 2025 10:28:19 +0800
Subject: [PATCH 2/6] =?UTF-8?q?feat:=E6=96=B0=E5=A2=9E=E9=97=A8=E6=88=B7?=
=?UTF-8?q?=E7=AE=A1=E7=90=86=E5=8A=9F=E8=83=BD?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../system/enums/ErrorCodeConstants.java | 3 +
.../admin/portal/PortalController.java | 105 ++++++++++
.../admin/portal/vo/PortalPageReqVO.java | 38 ++++
.../admin/portal/vo/PortalRespVO.java | 73 +++++++
.../admin/portal/vo/PortalSaveReqVO.java | 81 ++++++++
.../app/portal/AppPortalController.java | 48 +++++
.../dal/dataobject/portal/PortalDO.java | 106 ++++++++++
.../system/dal/mysql/portal/PortalMapper.java | 44 ++++
.../enums/portal/PortalCategoryEnum.java | 29 +++
.../enums/portal/PortalOpenTypeEnum.java | 34 +++
.../system/service/portal/PortalService.java | 63 ++++++
.../service/portal/PortalServiceImpl.java | 193 ++++++++++++++++++
12 files changed, 817 insertions(+)
create mode 100644 zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/controller/admin/portal/PortalController.java
create mode 100644 zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/controller/admin/portal/vo/PortalPageReqVO.java
create mode 100644 zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/controller/admin/portal/vo/PortalRespVO.java
create mode 100644 zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/controller/admin/portal/vo/PortalSaveReqVO.java
create mode 100644 zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/controller/app/portal/AppPortalController.java
create mode 100644 zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/dal/dataobject/portal/PortalDO.java
create mode 100644 zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/dal/mysql/portal/PortalMapper.java
create mode 100644 zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/enums/portal/PortalCategoryEnum.java
create mode 100644 zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/enums/portal/PortalOpenTypeEnum.java
create mode 100644 zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/service/portal/PortalService.java
create mode 100644 zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/service/portal/PortalServiceImpl.java
diff --git a/zt-module-system/zt-module-system-api/src/main/java/com/zt/plat/module/system/enums/ErrorCodeConstants.java b/zt-module-system/zt-module-system-api/src/main/java/com/zt/plat/module/system/enums/ErrorCodeConstants.java
index 46d3bb27..aaef27c3 100644
--- a/zt-module-system/zt-module-system-api/src/main/java/com/zt/plat/module/system/enums/ErrorCodeConstants.java
+++ b/zt-module-system/zt-module-system-api/src/main/java/com/zt/plat/module/system/enums/ErrorCodeConstants.java
@@ -219,4 +219,7 @@ public interface ErrorCodeConstants {
// ========== 系统序列号记录 1-002-032-000 ==========
ErrorCode SEQUENCE_RECORD_NOT_EXISTS = new ErrorCode(1_002_032_000, "系统序列号记录不存在");
+ // ========== 门户网站 1-002-033-000 ==========
+ ErrorCode PORTAL_NOT_EXISTS = new ErrorCode(1_002_033_000, "门户不存在");
+
}
diff --git a/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/controller/admin/portal/PortalController.java b/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/controller/admin/portal/PortalController.java
new file mode 100644
index 00000000..c956f82e
--- /dev/null
+++ b/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/controller/admin/portal/PortalController.java
@@ -0,0 +1,105 @@
+package com.zt.plat.module.system.controller.admin.portal;
+
+import com.zt.plat.framework.common.pojo.CommonResult;
+import com.zt.plat.framework.common.pojo.PageResult;
+import com.zt.plat.framework.common.util.object.BeanUtils;
+import com.zt.plat.framework.excel.core.util.ExcelUtils;
+import com.zt.plat.module.system.controller.admin.portal.vo.PortalPageReqVO;
+import com.zt.plat.module.system.controller.admin.portal.vo.PortalRespVO;
+import com.zt.plat.module.system.controller.admin.portal.vo.PortalSaveReqVO;
+import com.zt.plat.module.system.dal.dataobject.portal.PortalDO;
+import com.zt.plat.module.system.service.portal.PortalService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.annotation.Resource;
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.validation.Valid;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import java.io.IOException;
+import java.util.List;
+
+import static com.zt.plat.framework.common.pojo.CommonResult.success;
+import static com.zt.plat.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
+
+/**
+ * 门户网站 Controller
+ *
+ * @author 中铜数字供应链平台
+ */
+@Tag(name = "管理后台 - 门户网站")
+@RestController
+@RequestMapping("/system/portal")
+@Validated
+public class PortalController {
+
+ @Resource
+ private PortalService portalService;
+
+ @PostMapping("/create")
+ @Operation(summary = "创建门户网站")
+ @PreAuthorize("@ss.hasPermission('system:portal:create')")
+ public CommonResult createPortal(@Valid @RequestBody PortalSaveReqVO createReqVO) {
+ return success(portalService.createPortal(createReqVO));
+ }
+
+ @PutMapping("/update")
+ @Operation(summary = "更新门户网站")
+ @PreAuthorize("@ss.hasPermission('system:portal:update')")
+ public CommonResult updatePortal(@Valid @RequestBody PortalSaveReqVO updateReqVO) {
+ portalService.updatePortal(updateReqVO);
+ return success(true);
+ }
+
+ @DeleteMapping("/delete")
+ @Operation(summary = "删除门户网站")
+ @Parameter(name = "id", description = "编号", required = true, example = "1024")
+ @PreAuthorize("@ss.hasPermission('system:portal:delete')")
+ public CommonResult deletePortal(@RequestParam("id") Long id) {
+ portalService.deletePortal(id);
+ return success(true);
+ }
+
+ @GetMapping("/get")
+ @Operation(summary = "获得门户网站")
+ @Parameter(name = "id", description = "编号", required = true, example = "1024")
+ @PreAuthorize("@ss.hasPermission('system:portal:query')")
+ public CommonResult getPortal(@RequestParam("id") Long id) {
+ PortalDO portal = portalService.getPortal(id);
+ return success(BeanUtils.toBean(portal, PortalRespVO.class));
+ }
+
+ @GetMapping("/page")
+ @Operation(summary = "获得门户网站分页")
+ @PreAuthorize("@ss.hasPermission('system:portal:query')")
+ public CommonResult> getPortalPage(@Valid PortalPageReqVO pageReqVO) {
+ PageResult pageResult = portalService.getPortalPage(pageReqVO);
+ return success(BeanUtils.toBean(pageResult, PortalRespVO.class));
+ }
+
+ @GetMapping("/export-excel")
+ @Operation(summary = "导出门户网站 Excel")
+ @PreAuthorize("@ss.hasPermission('system:portal:export')")
+ public void exportPortalExcel(@Valid PortalPageReqVO pageReqVO,
+ HttpServletResponse response) throws IOException {
+ List list = portalService.getPortalPage(pageReqVO).getList();
+ // 导出 Excel
+ List data = BeanUtils.toBean(list, PortalRespVO.class);
+ ExcelUtils.write(response, "门户网站.xls", "数据", PortalRespVO.class, data);
+ }
+ /**
+ * 获取当前用户可访问的门户列表
+ * 此接口无需权限验证,因为已经通过登录验证,
+ * 返回的门户列表已经根据用户权限进行了过滤
+ */
+ @GetMapping("/list")
+ @Operation(summary = "获取我的门户列表")
+ public CommonResult> getMyPortalList() {
+ Long userId = getLoginUserId();
+ List portals = portalService.getPortalListByUserId(userId);
+ return success(BeanUtils.toBean(portals, PortalRespVO.class));
+ }
+}
diff --git a/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/controller/admin/portal/vo/PortalPageReqVO.java b/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/controller/admin/portal/vo/PortalPageReqVO.java
new file mode 100644
index 00000000..099c6693
--- /dev/null
+++ b/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/controller/admin/portal/vo/PortalPageReqVO.java
@@ -0,0 +1,38 @@
+package com.zt.plat.module.system.controller.admin.portal.vo;
+
+import com.zt.plat.framework.common.pojo.PageParam;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.time.LocalDateTime;
+
+import static com.zt.plat.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
+
+/**
+ * 门户网站分页查询 Request VO
+ *
+ * @author 中铜数字供应链平台
+ */
+@Schema(description = "管理后台 - 门户网站分页查询 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class PortalPageReqVO extends PageParam {
+
+ @Schema(description = "门户名称", example = "采购")
+ private String name;
+
+ @Schema(description = "状态", example = "0")
+ private Integer status;
+
+ @Schema(description = "门户分类", example = "业务系统")
+ private String category;
+
+ @Schema(description = "创建时间")
+ @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+ private LocalDateTime[] createTime;
+
+}
diff --git a/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/controller/admin/portal/vo/PortalRespVO.java b/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/controller/admin/portal/vo/PortalRespVO.java
new file mode 100644
index 00000000..5150c662
--- /dev/null
+++ b/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/controller/admin/portal/vo/PortalRespVO.java
@@ -0,0 +1,73 @@
+package com.zt.plat.module.system.controller.admin.portal.vo;
+
+import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
+import com.alibaba.excel.annotation.ExcelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+/**
+ * 门户网站 Response VO
+ *
+ * @author 中铜数字供应链平台
+ */
+@Schema(description = "管理后台 - 门户网站 Response VO")
+@Data
+@ExcelIgnoreUnannotated
+public class PortalRespVO {
+
+ @Schema(description = "门户编号", example = "1024")
+ @ExcelProperty("门户编号")
+ private Long id;
+
+ @Schema(description = "门户名称", example = "采购管理系统")
+ @ExcelProperty("门户名称")
+ private String name;
+
+ @Schema(description = "门户描述", example = "统一采购平台,支持在线询价、比价")
+ @ExcelProperty("门户描述")
+ private String description;
+
+ @Schema(description = "门户地址", example = "http://purchase.zt.com")
+ @ExcelProperty("门户地址")
+ private String url;
+
+ @Schema(description = "门户图标(Element Plus图标)", example = "ep:shopping-cart")
+ private String icon;
+
+ @Schema(description = "图标类型", example = "1")
+ @ExcelProperty("图标类型")
+ private Integer iconType;
+
+ @Schema(description = "图标图片URL(当 iconType=2 时使用)", example = "https://example.com/icon.png")
+ private String iconUrl;
+
+ @Schema(description = "门户分类", example = "业务系统")
+ @ExcelProperty("门户分类")
+ private String category;
+
+ @Schema(description = "显示排序", example = "1")
+ @ExcelProperty("显示排序")
+ private Integer sort;
+
+ @Schema(description = "状态", example = "0")
+ @ExcelProperty(value = "状态", converter = com.zt.plat.framework.excel.core.convert.DictConvert.class)
+ private Integer status;
+
+ @Schema(description = "权限标识", example = "portal:purchase:access")
+ @ExcelProperty("权限标识")
+ private String permission;
+
+ @Schema(description = "打开方式", example = "1")
+ @ExcelProperty("打开方式")
+ private Integer openType;
+
+ @Schema(description = "认证配置(JSON格式)", example = "{\"enabled\":true,\"type\":\"url_params\",\"urlParams\":[{\"key\":\"token\",\"value\":\"${userToken}\"}]}")
+ private String authConfig;
+
+ @Schema(description = "创建时间", example = "2025-11-10 10:00:00")
+ @ExcelProperty("创建时间")
+ private LocalDateTime createTime;
+
+}
diff --git a/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/controller/admin/portal/vo/PortalSaveReqVO.java b/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/controller/admin/portal/vo/PortalSaveReqVO.java
new file mode 100644
index 00000000..85adc014
--- /dev/null
+++ b/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/controller/admin/portal/vo/PortalSaveReqVO.java
@@ -0,0 +1,81 @@
+package com.zt.plat.module.system.controller.admin.portal.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import jakarta.validation.constraints.*;
+
+/**
+ * 门户网站创建/修改 Request VO
+ *
+ * @author 中铜数字供应链平台
+ */
+@Schema(description = "管理后台 - 门户网站创建/修改 Request VO")
+@Data
+public class PortalSaveReqVO {
+
+ @Schema(description = "门户编号", example = "1024")
+ private Long id;
+
+ @Schema(description = "门户名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "采购管理系统")
+ @NotEmpty(message = "门户名称不能为空")
+ @Size(max = 50, message = "门户名称长度不能超过50个字符")
+ private String name;
+
+ @Schema(description = "门户描述", example = "统一采购平台,支持在线询价、比价")
+ @Size(max = 200, message = "门户描述长度不能超过200个字符")
+ private String description;
+
+ @Schema(description = "门户地址", requiredMode = Schema.RequiredMode.REQUIRED, example = "http://purchase.zt.com")
+ @NotEmpty(message = "门户地址不能为空")
+ @Size(max = 500, message = "门户地址长度不能超过500个字符")
+ @Pattern(regexp = "^(http|https)://.*", message = "门户地址必须以 http:// 或 https:// 开头")
+ private String url;
+
+ @Schema(description = "门户图标(Element Plus图标)", example = "ep:shopping-cart")
+ @Size(max = 100, message = "门户图标长度不能超过100个字符")
+ private String icon;
+
+ @Schema(description = "图标类型", example = "1")
+ @Min(value = 1, message = "图标类型值不正确")
+ @Max(value = 2, message = "图标类型值不正确")
+ private Integer iconType;
+
+ @Schema(description = "图标图片URL(当 iconType=2 时使用)", example = "https://example.com/icon.png")
+ @Size(max = 500, message = "图标图片URL长度不能超过500个字符")
+ private String iconUrl;
+
+ @Schema(description = "门户分类", example = "业务系统")
+ @Size(max = 50, message = "门户分类长度不能超过50个字符")
+ private String category;
+
+ @Schema(description = "显示排序", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+ @NotNull(message = "显示排序不能为空")
+ @Min(value = 0, message = "显示排序不能小于0")
+ private Integer sort;
+
+ @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
+ @NotNull(message = "状态不能为空")
+ @Min(value = 0, message = "状态值不正确")
+ @Max(value = 1, message = "状态值不正确")
+ private Integer status;
+
+ @Schema(description = "权限标识", requiredMode = Schema.RequiredMode.REQUIRED, example = "portal:purchase:access")
+ @NotEmpty(message = "权限标识不能为空")
+ @Size(max = 100, message = "权限标识长度不能超过100个字符")
+ @Pattern(regexp = "^portal:[a-z]+:access$", message = "权限标识格式不正确,应为 portal:{module}:access")
+ private String permission;
+
+ @Schema(description = "打开方式", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+ @NotNull(message = "打开方式不能为空")
+ @Min(value = 1, message = "打开方式值不正确")
+ @Max(value = 3, message = "打开方式值不正确")
+ private Integer openType;
+
+ @Schema(description = "父菜单ID(权限自动同步到该菜单下)", example = "2500")
+ private Long parentMenuId;
+
+ @Schema(description = "认证配置(JSON格式)", example = "{\"enabled\":true,\"type\":\"url_params\",\"urlParams\":[{\"key\":\"token\",\"value\":\"${userToken}\"}]}")
+ private String authConfig;
+
+}
diff --git a/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/controller/app/portal/AppPortalController.java b/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/controller/app/portal/AppPortalController.java
new file mode 100644
index 00000000..a1386fe7
--- /dev/null
+++ b/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/controller/app/portal/AppPortalController.java
@@ -0,0 +1,48 @@
+package com.zt.plat.module.system.controller.app.portal;
+
+import com.zt.plat.framework.common.pojo.CommonResult;
+import com.zt.plat.framework.common.util.object.BeanUtils;
+import com.zt.plat.module.system.controller.admin.portal.vo.PortalRespVO;
+import com.zt.plat.module.system.dal.dataobject.portal.PortalDO;
+import com.zt.plat.module.system.service.portal.PortalService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.annotation.Resource;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.List;
+
+import static com.zt.plat.framework.common.pojo.CommonResult.success;
+import static com.zt.plat.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
+
+/**
+ * 用户端 - 门户网站 Controller
+ *
+ * @author 中铜数字供应链平台
+ */
+@Tag(name = "用户端 - 门户网站")
+@RestController
+@RequestMapping("/system/portal")
+@Validated
+public class AppPortalController {
+
+ @Resource
+ private PortalService portalService;
+
+ /**
+ * 获取当前用户可访问的门户列表
+ * 此接口无需权限验证,因为已经通过登录验证,
+ * 返回的门户列表已经根据用户权限进行了过滤
+ */
+ @GetMapping("/list")
+ @Operation(summary = "获取我的门户列表")
+ public CommonResult> getMyPortalList() {
+ Long userId = getLoginUserId();
+ List portals = portalService.getPortalListByUserId(userId);
+ return success(BeanUtils.toBean(portals, PortalRespVO.class));
+ }
+
+}
diff --git a/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/dal/dataobject/portal/PortalDO.java b/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/dal/dataobject/portal/PortalDO.java
new file mode 100644
index 00000000..4cb722c6
--- /dev/null
+++ b/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/dal/dataobject/portal/PortalDO.java
@@ -0,0 +1,106 @@
+package com.zt.plat.module.system.dal.dataobject.portal;
+
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.zt.plat.framework.tenant.core.db.TenantBaseDO;
+import lombok.*;
+
+/**
+ * 门户网站 DO
+ *
+ * @author 中铜数字供应链平台
+ */
+@TableName("system_portal")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class PortalDO extends TenantBaseDO {
+
+ /**
+ * 门户编号
+ */
+ @TableId
+ private Long id;
+
+ /**
+ * 门户名称
+ */
+ private String name;
+
+ /**
+ * 门户描述
+ */
+ private String description;
+
+ /**
+ * 门户地址
+ */
+ private String url;
+
+ /**
+ * 门户图标(Element Plus图标,如:ep:shopping-cart)
+ */
+ private String icon;
+
+ /**
+ * 图标类型
+ *
+ * 1 - 图标库(使用 icon 字段)
+ * 2 - 自定义图片(使用 iconUrl 字段)
+ */
+ private Integer iconType;
+
+ /**
+ * 图标图片URL(当 iconType=2 时使用)
+ */
+ private String iconUrl;
+
+ /**
+ * 门户分类
+ *
+ * 枚举 {@link PortalCategoryEnum}
+ */
+ private String category;
+
+ /**
+ * 显示排序
+ */
+ private Integer sort;
+
+ /**
+ * 状态
+ *
+ * 枚举 {@link com.zt.plat.framework.common.enums.CommonStatusEnum}
+ */
+ private Integer status;
+
+ /**
+ * 权限标识
+ *
+ * 格式:portal:{module}:access
+ * 例如:portal:purchase:access
+ */
+ private String permission;
+
+ /**
+ * 打开方式
+ *
+ * 枚举 {@link PortalOpenTypeEnum}
+ * 1 - 新窗口打开
+ * 2 - 当前窗口打开
+ * 3 - iframe 内嵌
+ */
+ private Integer openType;
+
+ /**
+ * 认证配置(JSON格式)
+ *
+ * 用于配置跳转时的认证信息(URL参数或请求头)
+ * 示例:{"enabled":true,"type":"url_params","urlParams":[{"key":"token","value":"${userToken}"}]}
+ */
+ private String authConfig;
+
+}
diff --git a/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/dal/mysql/portal/PortalMapper.java b/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/dal/mysql/portal/PortalMapper.java
new file mode 100644
index 00000000..5e9f73ac
--- /dev/null
+++ b/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/dal/mysql/portal/PortalMapper.java
@@ -0,0 +1,44 @@
+package com.zt.plat.module.system.dal.mysql.portal;
+
+import com.zt.plat.framework.common.pojo.PageResult;
+import com.zt.plat.framework.mybatis.core.mapper.BaseMapperX;
+import com.zt.plat.framework.mybatis.core.query.LambdaQueryWrapperX;
+import com.zt.plat.module.system.controller.admin.portal.vo.PortalPageReqVO;
+import com.zt.plat.module.system.dal.dataobject.portal.PortalDO;
+import org.apache.ibatis.annotations.Mapper;
+
+import java.util.List;
+
+/**
+ * 门户网站 Mapper
+ *
+ * @author 中铜数字供应链平台
+ */
+@Mapper
+public interface PortalMapper extends BaseMapperX {
+
+ default PageResult selectPage(PortalPageReqVO reqVO) {
+ return selectPage(reqVO, new LambdaQueryWrapperX()
+ .likeIfPresent(PortalDO::getName, reqVO.getName())
+ .eqIfPresent(PortalDO::getStatus, reqVO.getStatus())
+ .eqIfPresent(PortalDO::getCategory, reqVO.getCategory())
+ .betweenIfPresent(PortalDO::getCreateTime, reqVO.getCreateTime())
+ .orderByAsc(PortalDO::getSort)
+ .orderByDesc(PortalDO::getId));
+ }
+
+ /**
+ * 根据权限标识列表查询门户列表
+ *
+ * @param permissions 权限标识列表
+ * @return 门户列表
+ */
+ default List selectListByPermissions(List permissions) {
+ return selectList(new LambdaQueryWrapperX()
+ .in(PortalDO::getPermission, permissions)
+ .eq(PortalDO::getStatus, 0) // 只查询启用的门户
+ .orderByAsc(PortalDO::getSort)
+ .orderByDesc(PortalDO::getId));
+ }
+
+}
diff --git a/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/enums/portal/PortalCategoryEnum.java b/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/enums/portal/PortalCategoryEnum.java
new file mode 100644
index 00000000..2a8e990b
--- /dev/null
+++ b/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/enums/portal/PortalCategoryEnum.java
@@ -0,0 +1,29 @@
+package com.zt.plat.module.system.enums.portal;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * 门户分类枚举
+ *
+ * @author 中铜数字供应链平台
+ */
+@Getter
+@AllArgsConstructor
+public enum PortalCategoryEnum {
+
+ BUSINESS("业务系统", "核心业务系统,如采购、销售、财务等"),
+ MANAGEMENT("管理工具", "管理辅助工具,如OA、数据分析等"),
+ THIRD_PARTY("第三方系统", "外部集成系统,如ERP、E办等");
+
+ /**
+ * 分类名称
+ */
+ private final String name;
+
+ /**
+ * 分类描述
+ */
+ private final String description;
+
+}
diff --git a/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/enums/portal/PortalOpenTypeEnum.java b/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/enums/portal/PortalOpenTypeEnum.java
new file mode 100644
index 00000000..5e109797
--- /dev/null
+++ b/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/enums/portal/PortalOpenTypeEnum.java
@@ -0,0 +1,34 @@
+package com.zt.plat.module.system.enums.portal;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * 门户打开方式枚举
+ *
+ * @author 中铜数字供应链平台
+ */
+@Getter
+@AllArgsConstructor
+public enum PortalOpenTypeEnum {
+
+ NEW_WINDOW(1, "新窗口", "在新窗口中打开门户"),
+ CURRENT_WINDOW(2, "当前窗口", "在当前窗口中打开门户"),
+ IFRAME(3, "iframe内嵌", "在iframe中内嵌显示门户");
+
+ /**
+ * 类型
+ */
+ private final Integer type;
+
+ /**
+ * 名称
+ */
+ private final String name;
+
+ /**
+ * 描述
+ */
+ private final String description;
+
+}
diff --git a/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/service/portal/PortalService.java b/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/service/portal/PortalService.java
new file mode 100644
index 00000000..192b1851
--- /dev/null
+++ b/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/service/portal/PortalService.java
@@ -0,0 +1,63 @@
+package com.zt.plat.module.system.service.portal;
+
+import com.zt.plat.framework.common.pojo.PageResult;
+import com.zt.plat.module.system.controller.admin.portal.vo.PortalPageReqVO;
+import com.zt.plat.module.system.controller.admin.portal.vo.PortalSaveReqVO;
+import com.zt.plat.module.system.dal.dataobject.portal.PortalDO;
+
+import java.util.List;
+
+/**
+ * 门户网站 Service 接口
+ *
+ * @author 中铜数字供应链平台
+ */
+public interface PortalService {
+
+ /**
+ * 创建门户
+ *
+ * @param createReqVO 创建信息
+ * @return 编号
+ */
+ Long createPortal(PortalSaveReqVO createReqVO);
+
+ /**
+ * 更新门户
+ *
+ * @param updateReqVO 更新信息
+ */
+ void updatePortal(PortalSaveReqVO updateReqVO);
+
+ /**
+ * 删除门户
+ *
+ * @param id 编号
+ */
+ void deletePortal(Long id);
+
+ /**
+ * 获得门户
+ *
+ * @param id 编号
+ * @return 门户
+ */
+ PortalDO getPortal(Long id);
+
+ /**
+ * 获得门户分页
+ *
+ * @param pageReqVO 分页查询
+ * @return 门户分页
+ */
+ PageResult getPortalPage(PortalPageReqVO pageReqVO);
+
+ /**
+ * 获得用户有权限访问的门户列表
+ *
+ * @param userId 用户ID
+ * @return 门户列表
+ */
+ List getPortalListByUserId(Long userId);
+
+}
diff --git a/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/service/portal/PortalServiceImpl.java b/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/service/portal/PortalServiceImpl.java
new file mode 100644
index 00000000..6749e9db
--- /dev/null
+++ b/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/service/portal/PortalServiceImpl.java
@@ -0,0 +1,193 @@
+package com.zt.plat.module.system.service.portal;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.zt.plat.framework.common.pojo.PageResult;
+import com.zt.plat.framework.common.util.object.BeanUtils;
+import com.zt.plat.module.system.controller.admin.permission.vo.menu.MenuSaveVO;
+import com.zt.plat.module.system.controller.admin.portal.vo.PortalPageReqVO;
+import com.zt.plat.module.system.controller.admin.portal.vo.PortalSaveReqVO;
+import com.zt.plat.module.system.dal.dataobject.permission.MenuDO;
+import com.zt.plat.module.system.dal.dataobject.portal.PortalDO;
+import com.zt.plat.module.system.dal.mysql.portal.PortalMapper;
+import com.zt.plat.module.system.enums.permission.MenuTypeEnum;
+import com.zt.plat.module.system.service.permission.MenuService;
+import com.zt.plat.module.system.service.permission.PermissionService;
+import jakarta.annotation.Resource;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.CollectionUtils;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import static com.zt.plat.framework.common.exception.util.ServiceExceptionUtil.exception;
+import static com.zt.plat.module.system.enums.ErrorCodeConstants.PORTAL_NOT_EXISTS;
+
+/**
+ * 门户网站 Service 实现类
+ *
+ * @author 中铜数字供应链平台
+ */
+@Service
+public class PortalServiceImpl implements PortalService {
+
+ @Resource
+ private PortalMapper portalMapper;
+
+ @Resource
+ private PermissionService permissionService;
+
+ @Resource
+ private MenuService menuService;
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public Long createPortal(PortalSaveReqVO createReqVO) {
+ // 1. 创建门户
+ PortalDO portal = BeanUtils.toBean(createReqVO, PortalDO.class);
+ portalMapper.insert(portal);
+
+ // 2. 自动创建对应的菜单权限
+ if (createReqVO.getParentMenuId() != null) {
+ syncMenuPermission(portal, createReqVO.getParentMenuId(), null);
+ }
+
+ return portal.getId();
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public void updatePortal(PortalSaveReqVO updateReqVO) {
+ // 1. 校验是否存在
+ PortalDO oldPortal = validatePortalExists(updateReqVO.getId());
+
+ // 2. 更新门户
+ PortalDO updateObj = BeanUtils.toBean(updateReqVO, PortalDO.class);
+ portalMapper.updateById(updateObj);
+
+ // 3. 自动更新对应的菜单权限
+ if (updateReqVO.getParentMenuId() != null) {
+ syncMenuPermission(updateObj, updateReqVO.getParentMenuId(), oldPortal.getPermission());
+ }
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public void deletePortal(Long id) {
+ // 1. 校验是否存在
+ PortalDO portal = validatePortalExists(id);
+
+ // 2. 删除门户
+ portalMapper.deleteById(id);
+
+ // 3. 自动删除对应的菜单权限
+ deleteMenuPermission(portal.getPermission());
+ }
+
+ @Override
+ public PortalDO getPortal(Long id) {
+ return portalMapper.selectById(id);
+ }
+
+ @Override
+ public PageResult getPortalPage(PortalPageReqVO pageReqVO) {
+ return portalMapper.selectPage(pageReqVO);
+ }
+
+ @Override
+ public List getPortalListByUserId(Long userId) {
+ // 1. 获取用户的角色ID列表
+ Set roleIds = permissionService.getUserRoleIdListByUserIdFromCache(userId);
+ if (roleIds.isEmpty()) {
+ return Collections.emptyList();
+ }
+
+ // 2. 获取角色对应的菜单ID列表
+ Set menuIds = permissionService.getRoleMenuListByRoleId(roleIds);
+ if (menuIds.isEmpty()) {
+ return Collections.emptyList();
+ }
+
+ // 3. 获取菜单列表并提取权限标识
+ List menus = menuService.getMenuList(menuIds);
+ List permissions = menus.stream()
+ .map(MenuDO::getPermission)
+ .filter(permission -> permission != null && !permission.isEmpty())
+ .collect(Collectors.toList());
+
+ if (permissions.isEmpty()) {
+ return Collections.emptyList();
+ }
+
+ // 4. 根据权限标识查询门户列表
+ return portalMapper.selectListByPermissions(permissions);
+ }
+
+ @VisibleForTesting
+ public PortalDO validatePortalExists(Long id) {
+ if (id == null) {
+ return null;
+ }
+ PortalDO portal = portalMapper.selectById(id);
+ if (portal == null) {
+ throw exception(PORTAL_NOT_EXISTS);
+ }
+ return portal;
+ }
+
+ /**
+ * 同步菜单权限
+ * - 如果菜单权限不存在,则创建
+ * - 如果菜单权限已存在,则更新
+ *
+ * @param portal 门户对象
+ * @param parentMenuId 父菜单 ID
+ * @param oldPermission 旧的权限标识(用于更新场景)
+ */
+ private void syncMenuPermission(PortalDO portal, Long parentMenuId, String oldPermission) {
+ // 1. 如果权限标识发生变化,先删除旧的菜单权限
+ if (oldPermission != null && !oldPermission.equals(portal.getPermission())) {
+ deleteMenuPermission(oldPermission);
+ }
+
+ // 2. 查询是否已存在该权限的菜单
+ List existMenuIds = menuService.getMenuIdListByPermissionFromCache(portal.getPermission());
+
+ // 3. 构建菜单对象
+ MenuSaveVO menuVO = new MenuSaveVO();
+ menuVO.setName("访问" + portal.getName());
+ menuVO.setPermission(portal.getPermission());
+ menuVO.setType(MenuTypeEnum.BUTTON.getType());
+ menuVO.setSort(portal.getSort());
+ menuVO.setParentId(parentMenuId);
+ menuVO.setStatus(portal.getStatus());
+ menuVO.setVisible(false); // 按钮权限不显示在菜单中
+
+ // 4. 如果菜单已存在则更新,否则创建
+ if (!CollectionUtils.isEmpty(existMenuIds)) {
+ menuVO.setId(existMenuIds.get(0));
+ menuService.updateMenu(menuVO);
+ } else {
+ menuService.createMenu(menuVO);
+ }
+ }
+
+ /**
+ * 删除菜单权限
+ *
+ * @param permission 权限标识
+ */
+ private void deleteMenuPermission(String permission) {
+ if (permission == null || permission.isEmpty()) {
+ return;
+ }
+
+ List menuIds = menuService.getMenuIdListByPermissionFromCache(permission);
+ if (!CollectionUtils.isEmpty(menuIds)) {
+ menuIds.forEach(menuService::deleteMenu);
+ }
+ }
+
+}
From b11ffb4782e13b6216a148dc81d0403c85405c6c Mon Sep 17 00:00:00 2001
From: hewencai <2357300448@qq.com>
Date: Thu, 13 Nov 2025 17:32:30 +0800
Subject: [PATCH 3/6] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E9=97=A8=E6=88=B7?=
=?UTF-8?q?=E7=AE=A1=E7=90=86=E5=9B=BE=E7=89=87=E6=98=BE=E7=A4=BA=E9=80=BB?=
=?UTF-8?q?=E8=BE=91?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../controller/admin/portal/vo/PortalRespVO.java | 7 +++++--
.../controller/admin/portal/vo/PortalSaveReqVO.java | 10 +++++++---
.../system/dal/dataobject/portal/PortalDO.java | 13 ++++++++++---
3 files changed, 22 insertions(+), 8 deletions(-)
diff --git a/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/controller/admin/portal/vo/PortalRespVO.java b/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/controller/admin/portal/vo/PortalRespVO.java
index 5150c662..958e5a21 100644
--- a/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/controller/admin/portal/vo/PortalRespVO.java
+++ b/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/controller/admin/portal/vo/PortalRespVO.java
@@ -40,8 +40,11 @@ public class PortalRespVO {
@ExcelProperty("图标类型")
private Integer iconType;
- @Schema(description = "图标图片URL(当 iconType=2 时使用)", example = "https://example.com/icon.png")
- private String iconUrl;
+ @Schema(description = "图标文件ID(当 iconType=2 时使用)", example = "1234567890")
+ private String iconFileId;
+
+ @Schema(description = "图标文件名(当 iconType=2 时使用)", example = "logo.png")
+ private String iconFileName;
@Schema(description = "门户分类", example = "业务系统")
@ExcelProperty("门户分类")
diff --git a/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/controller/admin/portal/vo/PortalSaveReqVO.java b/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/controller/admin/portal/vo/PortalSaveReqVO.java
index 85adc014..7b015950 100644
--- a/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/controller/admin/portal/vo/PortalSaveReqVO.java
+++ b/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/controller/admin/portal/vo/PortalSaveReqVO.java
@@ -41,9 +41,13 @@ public class PortalSaveReqVO {
@Max(value = 2, message = "图标类型值不正确")
private Integer iconType;
- @Schema(description = "图标图片URL(当 iconType=2 时使用)", example = "https://example.com/icon.png")
- @Size(max = 500, message = "图标图片URL长度不能超过500个字符")
- private String iconUrl;
+ @Schema(description = "图标文件ID(当 iconType=2 时使用)", example = "1234567890")
+ @Size(max = 64, message = "图标文件ID长度不能超过64个字符")
+ private String iconFileId;
+
+ @Schema(description = "图标文件名(当 iconType=2 时使用)", example = "logo.png")
+ @Size(max = 255, message = "图标文件名长度不能超过255个字符")
+ private String iconFileName;
@Schema(description = "门户分类", example = "业务系统")
@Size(max = 50, message = "门户分类长度不能超过50个字符")
diff --git a/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/dal/dataobject/portal/PortalDO.java b/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/dal/dataobject/portal/PortalDO.java
index 4cb722c6..f9d221e2 100644
--- a/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/dal/dataobject/portal/PortalDO.java
+++ b/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/dal/dataobject/portal/PortalDO.java
@@ -49,14 +49,21 @@ public class PortalDO extends TenantBaseDO {
* 图标类型
*
* 1 - 图标库(使用 icon 字段)
- * 2 - 自定义图片(使用 iconUrl 字段)
+ * 2 - 自定义图片(使用 iconFileId 字段)
*/
private Integer iconType;
/**
- * 图标图片URL(当 iconType=2 时使用)
+ * 图标文件ID(当 iconType=2 时使用)
+ *
+ * 通过文件ID实时获取访问URL,避免URL过期问题
*/
- private String iconUrl;
+ private String iconFileId;
+
+ /**
+ * 图标文件名(当 iconType=2 时使用)
+ */
+ private String iconFileName;
/**
* 门户分类
From ba737a6a28becdc222588f58a5b5c5759467508d Mon Sep 17 00:00:00 2001
From: hewencai <2357300448@qq.com>
Date: Fri, 5 Dec 2025 15:19:40 +0800
Subject: [PATCH 4/6] =?UTF-8?q?update=EF=BC=9A=E5=A2=9E=E5=8A=A0=E9=97=A8?=
=?UTF-8?q?=E6=88=B7=E7=AE=A1=E7=90=86=E5=85=81=E8=AE=B8=E5=8C=BF=E5=90=8D?=
=?UTF-8?q?=E8=AE=BF=E9=97=AE?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../system/controller/admin/portal/vo/PortalSaveReqVO.java | 2 --
.../plat/module/system/service/portal/PortalServiceImpl.java | 3 ++-
2 files changed, 2 insertions(+), 3 deletions(-)
diff --git a/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/controller/admin/portal/vo/PortalSaveReqVO.java b/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/controller/admin/portal/vo/PortalSaveReqVO.java
index 7b015950..4b6fc3fa 100644
--- a/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/controller/admin/portal/vo/PortalSaveReqVO.java
+++ b/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/controller/admin/portal/vo/PortalSaveReqVO.java
@@ -65,9 +65,7 @@ public class PortalSaveReqVO {
private Integer status;
@Schema(description = "权限标识", requiredMode = Schema.RequiredMode.REQUIRED, example = "portal:purchase:access")
- @NotEmpty(message = "权限标识不能为空")
@Size(max = 100, message = "权限标识长度不能超过100个字符")
- @Pattern(regexp = "^portal:[a-z]+:access$", message = "权限标识格式不正确,应为 portal:{module}:access")
private String permission;
@Schema(description = "打开方式", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
diff --git a/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/service/portal/PortalServiceImpl.java b/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/service/portal/PortalServiceImpl.java
index 6749e9db..1c30986a 100644
--- a/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/service/portal/PortalServiceImpl.java
+++ b/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/service/portal/PortalServiceImpl.java
@@ -16,6 +16,7 @@ import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
+import org.springframework.util.StringUtils;
import java.util.Collections;
import java.util.List;
@@ -50,7 +51,7 @@ public class PortalServiceImpl implements PortalService {
portalMapper.insert(portal);
// 2. 自动创建对应的菜单权限
- if (createReqVO.getParentMenuId() != null) {
+ if (createReqVO.getParentMenuId() != null&& StringUtils.hasText(createReqVO.getPermission())) {
syncMenuPermission(portal, createReqVO.getParentMenuId(), null);
}
From d1a85c7653084f59afc7ac2903bec203f7533d03 Mon Sep 17 00:00:00 2001
From: chenbowen
Date: Fri, 5 Dec 2025 15:33:29 +0800
Subject: [PATCH 5/6] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E5=AE=9A=E6=97=B6?=
=?UTF-8?q?=E8=B0=83=E5=BA=A6=E6=90=BA=E5=B8=A6=E5=85=B7=E4=BD=93=20IP?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../databus/TemplateDatabusRequestLogDO.java | 6 ++++++
.../databus/TemplateDatabusInvokeService.java | 15 +++++++++++++++
.../sql/template_databus_request_log.sql | 2 ++
3 files changed, 23 insertions(+)
diff --git a/zt-module-template/zt-module-template-server/src/main/java/com/zt/plat/module/template/dal/dataobject/databus/TemplateDatabusRequestLogDO.java b/zt-module-template/zt-module-template-server/src/main/java/com/zt/plat/module/template/dal/dataobject/databus/TemplateDatabusRequestLogDO.java
index 14427fe7..3da29e68 100644
--- a/zt-module-template/zt-module-template-server/src/main/java/com/zt/plat/module/template/dal/dataobject/databus/TemplateDatabusRequestLogDO.java
+++ b/zt-module-template/zt-module-template-server/src/main/java/com/zt/plat/module/template/dal/dataobject/databus/TemplateDatabusRequestLogDO.java
@@ -45,6 +45,12 @@ public class TemplateDatabusRequestLogDO extends BaseDO {
@TableField("HTTP_METHOD")
private String httpMethod;
+ /**
+ * 发起请求的 IP。
+ */
+ @TableField("REQUEST_IP")
+ private String requestIp;
+
/**
* Query 参数 JSON。
*/
diff --git a/zt-module-template/zt-module-template-server/src/main/java/com/zt/plat/module/template/service/databus/TemplateDatabusInvokeService.java b/zt-module-template/zt-module-template-server/src/main/java/com/zt/plat/module/template/service/databus/TemplateDatabusInvokeService.java
index d0be0ddd..85a4e978 100644
--- a/zt-module-template/zt-module-template-server/src/main/java/com/zt/plat/module/template/service/databus/TemplateDatabusInvokeService.java
+++ b/zt-module-template/zt-module-template-server/src/main/java/com/zt/plat/module/template/service/databus/TemplateDatabusInvokeService.java
@@ -12,6 +12,7 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
+import java.net.InetAddress;
import java.net.URI;
import java.net.URLEncoder;
import java.net.http.HttpClient;
@@ -51,6 +52,7 @@ public class TemplateDatabusInvokeService {
private static final String ENCRYPTION_TYPE = CryptoSignatureUtils.ENCRYPT_TYPE_AES;
private static final Duration CONNECT_TIMEOUT = Duration.ofSeconds(5);
private static final Duration READ_TIMEOUT = Duration.ofSeconds(10);
+ private static final String UNKNOWN_IP = "UNKNOWN";
private static final Map BASE_QUERY_PARAMS = Map.of(
"businessCode", "11",
"fileId", "11"
@@ -73,6 +75,7 @@ public class TemplateDatabusInvokeService {
.requestId(generateRequestId())
.httpMethod(DEFAULT_HTTP_METHOD)
.targetUrl(TARGET_URL)
+ .requestIp(resolveRequestIp())
.success(Boolean.FALSE)
.build();
Instant start = Instant.now();
@@ -301,4 +304,16 @@ public class TemplateDatabusInvokeService {
}
return value.substring(0, maxLength);
}
+
+ private String resolveRequestIp() {
+ try {
+ InetAddress localHost = InetAddress.getLocalHost();
+ if (localHost != null) {
+ return localHost.getHostAddress();
+ }
+ } catch (Exception ex) {
+ log.debug("无法获取本地请求 IP", ex);
+ }
+ return UNKNOWN_IP;
+ }
}
diff --git a/zt-module-template/zt-module-template-server/src/main/resources/sql/template_databus_request_log.sql b/zt-module-template/zt-module-template-server/src/main/resources/sql/template_databus_request_log.sql
index 5112f7b2..57b44a93 100644
--- a/zt-module-template/zt-module-template-server/src/main/resources/sql/template_databus_request_log.sql
+++ b/zt-module-template/zt-module-template-server/src/main/resources/sql/template_databus_request_log.sql
@@ -3,6 +3,7 @@ CREATE TABLE template_databus_request_log (
REQUEST_ID VARCHAR(64) NOT NULL,
TARGET_URL VARCHAR(512) NOT NULL,
HTTP_METHOD VARCHAR(16) NOT NULL,
+ REQUEST_IP VARCHAR(64),
QUERY_PARAMS TEXT,
REQUEST_HEADERS TEXT,
REQUEST_BODY TEXT,
@@ -29,6 +30,7 @@ COMMENT ON COLUMN template_databus_request_log.ID IS '主键';
COMMENT ON COLUMN template_databus_request_log.REQUEST_ID IS '请求唯一标识';
COMMENT ON COLUMN template_databus_request_log.TARGET_URL IS '目标地址(含 Query)';
COMMENT ON COLUMN template_databus_request_log.HTTP_METHOD IS 'HTTP 方法';
+COMMENT ON COLUMN template_databus_request_log.REQUEST_IP IS '发起请求的 IP';
COMMENT ON COLUMN template_databus_request_log.QUERY_PARAMS IS 'Query 参数 JSON';
COMMENT ON COLUMN template_databus_request_log.REQUEST_HEADERS IS '请求头 JSON';
COMMENT ON COLUMN template_databus_request_log.REQUEST_BODY IS '原始请求体';
From 8b7e7da6c2c34a226778c2ad807466a919dab3e3 Mon Sep 17 00:00:00 2001
From: hewencai <2357300448@qq.com>
Date: Fri, 5 Dec 2025 15:46:38 +0800
Subject: [PATCH 6/6] =?UTF-8?q?update=EF=BC=9A=E5=A2=9E=E5=8A=A0=E9=97=A8?=
=?UTF-8?q?=E6=88=B7=E7=AE=A1=E7=90=86=E5=85=81=E8=AE=B8=E5=8C=BF=E5=90=8D?=
=?UTF-8?q?=E8=AE=BF=E9=97=AE?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../plat/module/system/dal/mysql/portal/PortalMapper.java | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/dal/mysql/portal/PortalMapper.java b/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/dal/mysql/portal/PortalMapper.java
index 5e9f73ac..6dddc6c0 100644
--- a/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/dal/mysql/portal/PortalMapper.java
+++ b/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/dal/mysql/portal/PortalMapper.java
@@ -1,5 +1,6 @@
package com.zt.plat.module.system.dal.mysql.portal;
+import com.alibaba.nacos.common.utils.CollectionUtils;
import com.zt.plat.framework.common.pojo.PageResult;
import com.zt.plat.framework.mybatis.core.mapper.BaseMapperX;
import com.zt.plat.framework.mybatis.core.query.LambdaQueryWrapperX;
@@ -35,7 +36,11 @@ public interface PortalMapper extends BaseMapperX {
*/
default List selectListByPermissions(List permissions) {
return selectList(new LambdaQueryWrapperX()
- .in(PortalDO::getPermission, permissions)
+ .and(qw -> qw
+ .in(CollectionUtils.isNotEmpty(permissions), PortalDO::getPermission, permissions)
+ .or().isNull(PortalDO::getPermission)
+ .or().eq(PortalDO::getPermission, "")
+ )
.eq(PortalDO::getStatus, 0) // 只查询启用的门户
.orderByAsc(PortalDO::getSort)
.orderByDesc(PortalDO::getId));