Compare commits

...

93 Commits

Author SHA1 Message Date
FCL
c333395b6c Merge branch 'refs/heads/zt-test' into test
# Conflicts:
#	zt-framework/zt-common/src/main/java/com/zt/plat/framework/common/biz/system/permission/PermissionCommonApi.java
#	zt-framework/zt-spring-boot-starter-biz-tenant/src/main/java/com/zt/plat/framework/tenant/core/context/DeptContextHolder.java
#	zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/service/permission/PermissionServiceImpl.java
2026-01-19 10:59:08 +08:00
chenbowen
2917e896fd Merge branch 'dev' into test 2026-01-17 10:37:07 +08:00
chenbowen
3b099925b6 Merge remote-tracking branch 'base-version/test' into dev 2026-01-17 10:36:51 +08:00
chenbowen
a5f844d5df 1. 调整用户名可以设置为最小一位
(cherry picked from commit 0d31b54f1c13c5851ca448f9d55c4b2d4b345458)
2026-01-17 10:35:50 +08:00
chenbowen
d4f26b5244 Merge branch 'dev' into test 2026-01-16 18:19:49 +08:00
chenbowen
e6ec4f9e23 1. 调整用户可以接受空字符串 username
2. 调整 iwork 同步用户时,如果 loginid 为空,设置 username 为空格
2026-01-16 18:19:09 +08:00
chenbowen
7c0a0601ed 1. 调整用户可以接受空字符串 username
2. 调整 iwork 同步用户时,如果 loginid 为空,设置 username 为空格
2026-01-16 18:17:24 +08:00
chenbowen
da6ab95d3a 修复编译错误 2026-01-16 18:10:18 +08:00
ranke
7541cb4d6f Merge branch 'test' into test-dsc
* test:
  取消sql的日志输出
  授权菜单权限可选不展示菜单选项. http://172.16.46.63:31560/index.php?m=task&f=view&taskID=707
  1. 调整 username 同步逻辑 2. 调整 eban 回调登录逻辑
2026-01-16 16:18:53 +08:00
ranke
00cdf5bc0c 取消sql的日志输出 2026-01-16 16:18:27 +08:00
ranke
c71ac5dbd3 授权菜单权限可选不展示菜单选项. http://172.16.46.63:31560/index.php?m=task&f=view&taskID=707 2026-01-16 16:17:52 +08:00
chenbowen
adc4f4bf2d Merge branch 'dev' into test 2026-01-16 15:17:41 +08:00
chenbowen
0f37a7f9b6 修复编译错误 2026-01-16 15:17:25 +08:00
chenbowen
e5c8d922c6 Merge branch 'dev' into test 2026-01-16 15:05:49 +08:00
chenbowen
fea194b7bb 1. 调整 username 同步逻辑
2. 调整 eban 回调登录逻辑
2026-01-16 15:05:35 +08:00
chenbowen
b35c3f8db2 1. 调整 username 同步逻辑
2. 调整 eban 回调登录逻辑
2026-01-16 15:04:29 +08:00
chenbowen
4bcce5046c Merge branch 'dev' into test 2026-01-16 12:51:36 +08:00
chenbowen
d3a771a8a8 Merge remote-tracking branch 'base-version/test' into dev 2026-01-16 12:51:19 +08:00
chenbowen
098be43598 调整 username 同步逻辑 2026-01-16 12:50:25 +08:00
wuzongyong
a3386853fa refactor(databus): 移除API客户端凭证服务中的缓存实现
- 删除了基于Caffeine的凭证缓存逻辑
- 移除了PostConstruct注解的缓存初始化方法
- 删除了缓存相关的成员变量和配置
- 移除了所有缓存失效操作包括创建、更新和删除时的缓存清理
- 简化了凭证查询逻辑直接通过数据库访问
- 保留了核心的API凭证管理功能和匿名用户服务集成
2026-01-16 09:24:09 +08:00
wuzongyong
ac5e210269 refactor(databus): 移除API客户端凭证服务中的缓存实现
- 删除了基于Caffeine的凭证缓存逻辑
- 移除了PostConstruct注解的缓存初始化方法
- 删除了缓存相关的成员变量和配置
- 移除了所有缓存失效操作包括创建、更新和删除时的缓存清理
- 简化了凭证查询逻辑直接通过数据库访问
- 保留了核心的API凭证管理功能和匿名用户服务集成
2026-01-16 09:23:29 +08:00
chenbowen
1750e031c0 Merge branch 'dev' into test 2026-01-15 22:44:12 +08:00
chenbowen
e2688268ac Merge remote-tracking branch 'base-version/test' into dev
# Conflicts:
#	zt-module-databus/zt-module-databus-server-app/src/main/resources/application-dev.yml
2026-01-15 22:43:56 +08:00
chenbowen
d6e72f6045 密码为空的用户也进行同步 2026-01-15 21:25:25 +08:00
wuzongyong
781d29bed7 feat(config): 更新开发环境数据库连接和安全过滤器加密功能
- 修改 application-dev.yml 中的数据库连接地址和凭据信息
- 在 GatewaySecurityFilter 中实现条件加密验证逻辑
- 添加 wzy 环境配置文件支持 Nacos 配置中心连接
- 优化请求体解密和签名验证流程以支持选择性加密处理
- 更新缓存请求体构造以确保解密后数据正确传递
2026-01-15 18:08:33 +08:00
wuzongyong
06fb92462c feat(config): 更新开发环境数据库连接和安全过滤器加密功能
- 修改 application-dev.yml 中的数据库连接地址和凭据信息
- 在 GatewaySecurityFilter 中实现条件加密验证逻辑
- 添加 wzy 环境配置文件支持 Nacos 配置中心连接
- 优化请求体解密和签名验证流程以支持选择性加密处理
- 更新缓存请求体构造以确保解密后数据正确传递
2026-01-15 18:06:26 +08:00
chenbowen
2a1af3ed6b 同步 feign 接口查询的用户信息属性 2026-01-15 18:04:11 +08:00
chenbowen
a0ec76a8d8 iwork 同步用户的规则调整 2026-01-15 17:50:21 +08:00
chenbowen
96c9ab97e6 Merge branch 'dev' into test 2026-01-15 16:42:18 +08:00
chenbowen
db91848cd4 1. 新增物料牌号扩展功能 2026-01-15 16:41:51 +08:00
朝锦 杨
ff348e933b Merge branch 'dev' into 'test'
Dev

See merge request jygk/dsc!18
2026-01-15 08:40:23 +00:00
ranke
1c919bec41 移除多余模块 2026-01-15 16:37:49 +08:00
lenovo
ec99f49c93 Merge remote-tracking branch 'refs/remotes/ztcloud/test' into dev 2026-01-15 16:26:57 +08:00
ranke
f3e0b642ef Merge branch 'test' into test-dsc
* test:
  新增 zt-module-databus-server-app 的 dockerfile
2026-01-15 16:05:15 +08:00
ranke
d1e2e25b96 新增 zt-module-databus-server-app 的 dockerfile 2026-01-15 16:05:02 +08:00
ranke
09c5c5fde5 Merge branch 'test' into test-dsc
* test:
  修改docker配置
2026-01-15 15:54:32 +08:00
ranke
8a7c74bfb5 修改docker配置 2026-01-15 15:54:18 +08:00
ranke
35d42d4d75 移除重复模块 2026-01-15 15:53:04 +08:00
ranke
d0f7cc9734 Merge branch 'test' of http://172.16.46.63:30001/gitlab/jygk/dsc into test-dsc
* 'test' of http://172.16.46.63:30001/gitlab/jygk/dsc:
  feat(gateway): 添加API客户端凭证加密功能支持
  优化
  1. 移除多余 java 文件
  feat:登陆用户的部门数据权限接口增加角色参数
2026-01-15 14:56:51 +08:00
ranke
378a9e7bcb Merge branch 'test' into test-dsc
* test:
  修复BUG710,添加文件下载次数统计
  修改私服地址,把 seata-dm 项目从 dsc挪过来
  feat(gateway): 添加API客户端凭证加密功能支持
  bmp 已挪到 ztcloud-dist 仓库
  修改发布信息
  增加快照仓库
  恢复 erp 模块数据权限
  从maven模块中移除 zt-server
  修改版本号
  feat:登陆用户的部门数据权限接口增加角色参数;获取当前用户可访问的顶级部门列表不校验数据权限
  no message
2026-01-15 14:51:00 +08:00
lenovo
a44e7e835e 修复BUG710,添加文件下载次数统计 2026-01-15 14:45:43 +08:00
ranke
26ab7dac24 修改私服地址,把 seata-dm 项目从 dsc挪过来 2026-01-15 10:07:17 +08:00
wuzongyong
3524f0fffb feat(gateway): 添加API客户端凭证加密功能支持
- 在ApiClientCredentialDO实体类中新增enableEncryption字段
- 在ApiClientCredentialRespVO响应对象中添加加密启用状态字段
- 在ApiClientCredentialSaveReqVO请求对象中添加加密启用状态字段
- 在GatewaySecurityFilter中实现加密启用状态检查逻辑
- 添加数据库表结构变更脚本支持加密字段
2026-01-14 19:14:58 +08:00
wuzongyong
287d24fc7f feat(gateway): 添加API客户端凭证加密功能支持
- 在ApiClientCredentialDO实体类中新增enableEncryption字段
- 在ApiClientCredentialRespVO响应对象中添加加密启用状态字段
- 在ApiClientCredentialSaveReqVO请求对象中添加加密启用状态字段
- 在GatewaySecurityFilter中实现加密启用状态检查逻辑
- 添加数据库表结构变更脚本支持加密字段
2026-01-14 18:11:02 +08:00
ranke
63708dfb36 bmp 已挪到 ztcloud-dist 仓库 2026-01-14 17:09:18 +08:00
ranke
0ce56cad8b 修改发布信息 2026-01-14 17:03:55 +08:00
ranke
62e31ea360 增加快照仓库 2026-01-14 15:52:59 +08:00
chenbowen
c6ab1fefce Merge branch 'dev' into test 2026-01-14 15:28:47 +08:00
chenbowen
373fd0c412 Merge remote-tracking branch 'base-version/test' into dev 2026-01-14 15:28:26 +08:00
chenbowen
f70d742e9b 恢复 erp 模块数据权限 2026-01-14 15:13:54 +08:00
ranke
49fb84ea5a 从maven模块中移除 zt-server 2026-01-13 18:21:59 +08:00
ranke
a510ead10c Merge branch 'test' of http://172.16.46.63:30001/gitlab/base-version/ztcloud into test
* 'test' of http://172.16.46.63:30001/gitlab/base-version/ztcloud:
  feat:登陆用户的部门数据权限接口增加角色参数;获取当前用户可访问的顶级部门列表不校验数据权限
2026-01-13 17:41:49 +08:00
ranke
f96a157024 修改版本号 2026-01-13 17:41:38 +08:00
qianshijiang
7a15fff979 优化 2026-01-13 15:14:09 +08:00
chenbowen
206bf9a3c5 1. 移除多余 java 文件 2026-01-13 11:11:34 +08:00
chenbowen
429f421e1b Merge branch 'dev' into test
# Conflicts:
#	zt-module-system/zt-module-system-api/src/main/java/com/zt/plat/module/system/api/sms/dto/send/SmsSendSingleToUserReqDTO.java
#	zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/controller/admin/sms/SmsCallbackController.java
#	zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/framework/sms/core/enums/SmsChannelEnum.java
2026-01-13 11:06:39 +08:00
chenbowen
479d6c6c2a Merge remote-tracking branch 'base-version/test' into dev
# Conflicts:
#	zt-framework/zt-common/src/main/java/com/zt/plat/framework/common/util/security/CryptoSignatureUtils.java
#	zt-module-system/zt-module-system-api/src/main/java/com/zt/plat/module/system/api/sms/dto/send/SmsSendSingleToUserReqDTO.java
#	zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/api/databus/DatabusDeptProviderApiImpl.java
#	zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/controller/admin/sms/SmsCallbackController.java
#	zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/framework/sms/core/enums/SmsChannelEnum.java
2026-01-13 11:00:28 +08:00
FCL
9233f5f783 feat:登陆用户的部门数据权限接口增加角色参数;获取当前用户可访问的顶级部门列表不校验数据权限 2026-01-13 10:46:22 +08:00
FCL
cd94420b21 feat:登陆用户的部门数据权限接口增加角色参数 2026-01-13 09:56:14 +08:00
ranke
605cff08c7 no message 2026-01-13 09:30:43 +08:00
ranke
70f8e59c1b 解决编译错误 2026-01-12 19:29:29 +08:00
ranke
a0673022fa Merge branch 'test' into test-dsc
* test:
  把-server项目改为jar包,新增 server-app项目作为启动器 http://172.16.46.63:31560/index.php?m=task&f=view&taskID=699
  [+]增加国密SM4加解密工具包
  fix(user-dept): 修改用户来源筛选条件
  fix(databus): 修复部门数据查询中缺少数据源过滤条件
  fix(databus): 修改用户同步的数据源过滤条件
  fix(databus): 修改用户同步的数据源过滤条件
  [+]增加国密SM4接口加解密
  [#]修改部门推送消息逻辑

# Conflicts:
#	zt-framework/zt-common/src/main/java/com/zt/plat/framework/common/util/security/CryptoSignatureUtils.java
#	zt-module-system/zt-module-system-api/src/main/java/com/zt/plat/module/system/api/sms/dto/send/SmsSendSingleToUserReqDTO.java
#	zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/api/databus/DatabusDeptProviderApiImpl.java
#	zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/controller/admin/sms/SmsCallbackController.java
#	zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/framework/sms/core/enums/SmsChannelEnum.java
2026-01-12 18:49:36 +08:00
ranke
bdf211f44f Merge branch 'test' of http://172.16.46.63:30001/gitlab/base-version/ztcloud into test
* 'test' of http://172.16.46.63:30001/gitlab/base-version/ztcloud:
  [+]增加国密SM4加解密工具包
  [+]增加国密SM4接口加解密
  [#]修改部门推送消息逻辑
2026-01-12 18:36:46 +08:00
ranke
6644710fe0 把-server项目改为jar包,新增 server-app项目作为启动器 http://172.16.46.63:31560/index.php?m=task&f=view&taskID=699 2026-01-12 18:36:39 +08:00
chenbowen
441de77197 1. 拆分核心模块发布配置 2026-01-12 13:41:46 +08:00
chenbowen
aede30176f 1. 拆分核心模块发布配置 2026-01-12 13:28:44 +08:00
chenbowen
6bdce6e9bc 1. 拆分核心模块发布配置 2026-01-12 13:00:36 +08:00
maimaishu
22b449f7d5 Merge branch 'test' of http://172.16.46.63:30001/gitlab/base-version/ztcloud into test 2026-01-12 11:06:07 +08:00
maimaishu
2489a7f73e [+]增加国密SM4加解密工具包 2026-01-12 11:05:28 +08:00
lzx
d56587b8fd Merge branch 'dev' into test 2026-01-09 17:47:18 +08:00
lzx
041a89bb59 fix(user-dept): 修改用户来源筛选条件
- 将用户来源筛选条件从 user_source = 2 更新为 user_source = 3
- 更新了查询用户部门关系的SQL条件
- 更新了统计用户部门关系数量的SQL条件
- 修正了相关注释说明
2026-01-09 17:46:43 +08:00
lzx
75e212511d fix(user-dept): 修正用户来源筛选条件
- 将用户来源筛选条件从 user_source = 2 更新为 user_source = 3
- 同步更新了相关注释说明
- 保持了原有的租户ID和软删除过滤逻辑
2026-01-09 17:45:55 +08:00
lzx
43c4c8a94e fix(databus): 修复部门数据查询中缺少数据源过滤条件
- 在游标分页查询中添加部门数据源过滤条件
- 在总数统计查询中添加部门数据源过滤条件
- 在计数接口中添加部门数据源过滤条件
2026-01-09 17:02:02 +08:00
lzx
caca8590c7 Merge branch 'dev' into test 2026-01-09 17:00:09 +08:00
lzx
e345d48dc7 feat(databus): 限制部门数据查询只统计特定来源
- 在游标分页查询中添加部门来源过滤条件
- 在总数统计查询中添加部门来源过滤条件
- 在部门计数接口中添加部门来源过滤条件
- 确保只统计部门来源为3的数据记录
2026-01-09 16:59:48 +08:00
lzx
a210af0dd8 Merge branch 'dev' into test 2026-01-09 16:42:23 +08:00
lzx
f8f584b9ff fix(databus): 修改用户同步的数据源过滤条件
- 将用户同步的数据源从 userSource = 2 更新为 userSource = 3
- 修正了数据总线用户提供者API中的查询条件配置
2026-01-09 15:50:18 +08:00
lzx
5366a35546 Merge remote-tracking branch 'origin/dev' into dev 2026-01-09 15:49:40 +08:00
lzx
d47c91c7f2 fix(sync): 修改用户数据同步的数据源过滤条件
- 将用户同步的数据源从 userSource = 2 修改为 userSource = 3
- 更新了数据库查询条件以匹配新的数据源标识
- 修正了数据同步功能的数据过滤逻辑
2026-01-09 15:49:28 +08:00
lzx
1fd704fe9d fix(databus): 修改用户同步的数据源过滤条件
- 将用户同步的数据源从 userSource = 2 更新为 userSource = 3
- 修正了数据总线用户提供者API中的查询条件配置
2026-01-09 15:33:33 +08:00
chenbowen
c5211287ab Merge branch 'dev' into test 2026-01-09 15:33:09 +08:00
chenbowen
82c819c59a Merge remote-tracking branch 'base-version/test' into dev 2026-01-09 15:32:39 +08:00
lzx
bed76174c5 Merge remote-tracking branch 'origin/dev' into dev 2026-01-09 15:30:30 +08:00
chenbowen
c3502e78c8 1. 调整 databus 默认的重试策略 2026-01-09 15:25:42 +08:00
lzx
d283d92a4e fix(sync): 修改用户数据同步的数据源过滤条件
- 将用户同步的数据源从 userSource = 2 修改为 userSource = 3
- 更新了数据库查询条件以匹配新的数据源标识
- 修正了数据同步功能的数据过滤逻辑
2026-01-09 15:02:54 +08:00
chenbowen
03b04cd7fe Merge branch 'dev' into test 2026-01-09 13:57:09 +08:00
chenbowen
cf540e12be Merge remote-tracking branch 'base-version/test' into dev 2026-01-09 13:56:51 +08:00
chenbowen
5b660f5a11 1.不再过滤 get 开头的 url 2026-01-09 11:46:59 +08:00
chenbowen
30029e0fd6 1.新增用户界面的用户来源类型展示 2026-01-09 11:44:57 +08:00
chenbowen
c2f38608e7 1.新增用户界面的用户来源类型展示 2026-01-08 17:05:21 +08:00
maimaishu
674ef07c5a Merge branch 'test' of http://172.16.46.63:30001/gitlab/base-version/ztcloud into test 2026-01-07 08:45:17 +08:00
maimaishu
a07c71f1a0 [+]增加国密SM4接口加解密 2026-01-07 08:44:35 +08:00
maimaishu
d54edcd88b [#]修改部门推送消息逻辑 2026-01-05 17:46:31 +08:00
178 changed files with 7735 additions and 273 deletions

67
deployment-databus.yaml Normal file
View File

@@ -0,0 +1,67 @@
apiVersion: apps/v1
kind: Deployment
metadata:
namespace: ns-d6a0e78ebd674c279614498e4c57b133
name: zt-module-databus
labels:
app: zt-module-databus
annotations:
version: "VERSION_PLACEHOLDER"
description: DESC_PLACEHOLDER
rollout.kubernetes.io/change-cause: "DESC_PLACEHOLDER:VERSION_PLACEHOLDER"
spec:
replicas: 1
selector:
matchLabels:
app: zt-module-databus
template:
metadata:
labels:
app: zt-module-databus
spec:
dnsPolicy: None
dnsConfig:
nameservers:
- "172.16.36.16"
- "172.16.36.220"
containers:
- name: zt-module-databus
image: 172.16.46.66:10043/zt/zt-module-databus:VERSION_PLACEHOLDER
imagePullPolicy: Always
env:
- name: TZ
value: Asia/Shanghai
lifecycle:
preStop:
exec:
command:
- "/bin/sh"
- "-c"
- "sleep 35"
readinessProbe:
httpGet:
path: /actuator/health
port: 48108
initialDelaySeconds: 100
periodSeconds: 5
failureThreshold: 3
livenessProbe:
httpGet:
path: /actuator/health
port: 48108
initialDelaySeconds: 100
periodSeconds: 10
failureThreshold: 5
resources:
requests:
cpu: "500m"
memory: "1024Mi"
limits:
cpu: "500m"
memory: "2048Mi"
terminationGracePeriodSeconds: 40
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0

74
deployment-gateway.yaml Normal file
View File

@@ -0,0 +1,74 @@
apiVersion: apps/v1
kind: Deployment
metadata:
namespace: ns-d6a0e78ebd674c279614498e4c57b133
name: zt-gateway
labels:
app: zt-gateway
annotations:
version: "VERSION_PLACEHOLDER"
description: DESC_PLACEHOLDER
rollout.kubernetes.io/change-cause: "DESC_PLACEHOLDER:VERSION_PLACEHOLDER"
spec:
replicas: 1
selector:
matchLabels:
app: zt-gateway
template:
metadata:
labels:
app: zt-gateway
spec:
containers:
- name: zt-gateway
image: 172.16.46.66:10043/zt/zt-gateway:VERSION_PLACEHOLDER
imagePullPolicy: Always
env:
- name: TZ
value: Asia/Shanghai
lifecycle:
preStop:
exec:
command:
- "/bin/sh"
- "-c"
- "sleep 35"
ports:
- containerPort: 48080
readinessProbe:
httpGet:
path: /actuator/health
port: 48080
initialDelaySeconds: 100
periodSeconds: 5
failureThreshold: 3
livenessProbe:
httpGet:
path: /actuator/health
port: 48080
initialDelaySeconds: 100
periodSeconds: 10
failureThreshold: 5
resources:
requests:
cpu: "500m"
memory: "1024Mi"
limits:
cpu: "500m"
memory: "2048Mi"
terminationGracePeriodSeconds: 40
---
apiVersion: v1
kind: Service
metadata:
namespace: ns-d6a0e78ebd674c279614498e4c57b133
name: zt-gateway
spec:
type: NodePort
selector:
app: zt-gateway
ports:
- protocol: TCP
port: 48080
targetPort: 48080
nodePort: 30081

67
deployment-infra.yaml Normal file
View File

@@ -0,0 +1,67 @@
apiVersion: apps/v1
kind: Deployment
metadata:
namespace: ns-d6a0e78ebd674c279614498e4c57b133
name: zt-module-infra
labels:
app: zt-module-infra
annotations:
version: "VERSION_PLACEHOLDER"
description: DESC_PLACEHOLDER
rollout.kubernetes.io/change-cause: "DESC_PLACEHOLDER:VERSION_PLACEHOLDER"
spec:
replicas: 2
selector:
matchLabels:
app: zt-module-infra
template:
metadata:
labels:
app: zt-module-infra
spec:
dnsPolicy: None
dnsConfig:
nameservers:
- "172.16.36.16"
- "172.16.36.220"
containers:
- name: zt-module-infra
image: 172.16.46.66:10043/zt/zt-module-infra:VERSION_PLACEHOLDER
imagePullPolicy: Always
env:
- name: TZ
value: Asia/Shanghai
lifecycle:
preStop:
exec:
command:
- "/bin/sh"
- "-c"
- "sleep 35"
readinessProbe:
httpGet:
path: /actuator/health
port: 48082
initialDelaySeconds: 100
periodSeconds: 5
failureThreshold: 3
livenessProbe:
httpGet:
path: /actuator/health
port: 48082
initialDelaySeconds: 100
periodSeconds: 10
failureThreshold: 5
resources:
requests:
cpu: "500m"
memory: "1024Mi"
limits:
cpu: "500m"
memory: "2048Mi"
terminationGracePeriodSeconds: 40
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0

76
deployment-system.yaml Normal file
View File

@@ -0,0 +1,76 @@
apiVersion: apps/v1
kind: Deployment
metadata:
namespace: ns-d6a0e78ebd674c279614498e4c57b133
name: zt-module-system
labels:
app: zt-module-system
annotations:
version: "VERSION_PLACEHOLDER"
description: DESC_PLACEHOLDER
rollout.kubernetes.io/change-cause: "DESC_PLACEHOLDER:VERSION_PLACEHOLDER"
spec:
replicas: 1
selector:
matchLabels:
app: zt-module-system
template:
metadata:
labels:
app: zt-module-system
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- node-3
dnsPolicy: None
dnsConfig:
nameservers:
- "172.16.36.16"
- "172.16.36.220"
containers:
- name: zt-module-system
image: 172.16.46.66:10043/zt/zt-module-system:VERSION_PLACEHOLDER
imagePullPolicy: Always
env:
- name: TZ
value: Asia/Shanghai
lifecycle:
preStop:
exec:
command:
- "/bin/sh"
- "-c"
- "sleep 35"
readinessProbe:
httpGet:
path: /actuator/health
port: 48081
initialDelaySeconds: 100
periodSeconds: 5
failureThreshold: 3
livenessProbe:
httpGet:
path: /actuator/health
port: 48081
initialDelaySeconds: 100
periodSeconds: 10
failureThreshold: 5
resources:
requests:
cpu: "500m"
memory: "1024Mi"
limits:
cpu: "500m"
memory: "2048Mi"
terminationGracePeriodSeconds: 40
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0

32
pom.xml
View File

@@ -25,6 +25,7 @@
<module>zt-module-databus</module>
<!-- <module>zt-module-rule</module>-->
<!-- <module>zt-module-html2pdf</module>-->
<!-- <module>zt-server</module>-->
</modules>
<name>${project.artifactId}</name>
@@ -32,7 +33,7 @@
<url>https://github.com/YunaiV/ruoyi-vue-pro</url>
<properties>
<revision>3.0.46</revision>
<revision>3.0.47-SNAPSHOT</revision>
<!-- Maven 相关 -->
<java.version>17</java.version>
<maven.compiler.source>${java.version}</maven.compiler.source>
@@ -203,7 +204,7 @@
<repository>
<id>ZT</id>
<name>中铜 ZStack 私服</name>
<url>http://172.16.46.63:30708/repository/test/</url>
<url>http://172.16.46.63:30708/repository/zt-cloud/</url>
<releases>
<updatePolicy>always</updatePolicy>
<checksumPolicy>warn</checksumPolicy>
@@ -221,11 +222,11 @@
<name>中铜 ZStack 私服</name>
<url>http://172.16.46.63:30708/repository/test/</url>
</repository>
<!-- <snapshotRepository>-->
<!-- <id>ZT</id>-->
<!-- <name>中铜 ZStack 私服</name>-->
<!-- <url>https://your-nexus.example.com/repository/maven-snapshots/</url>-->
<!-- </snapshotRepository>-->
<snapshotRepository>
<id>ZT-snap</id>
<name>中铜 ZStack 私服</name>
<url>http://172.16.46.63:30708/repository/test-snap/</url>
</snapshotRepository>
</distributionManagement>
<profiles>
@@ -242,6 +243,19 @@
<config.version>1.0.0</config.version>
</properties>
</profile>
<profile>
<id>wzy</id>
<properties>
<env.name>dev</env.name>
<!--Nacos 配置-->
<config.server-addr>172.16.46.63:30848</config.server-addr>
<config.namespace>wzy</config.namespace>
<config.group>DEFAULT_GROUP</config.group>
<config.username>nacos</config.username>
<config.password>P@ssword25</config.password>
<config.version>1.0.0</config.version>
</properties>
</profile>
<profile>
<id>klw-dev</id>
<properties>
@@ -282,13 +296,13 @@
</properties>
</profile>
<profile>
<id>chenbowen</id>
<id>haodongqiang</id>
<properties>
<!-- <env.name>local</env.name>-->
<env.name>dev</env.name>
<!-- <config.server-addr>localhost:8848</config.server-addr>-->
<config.server-addr>172.16.46.63:30848</config.server-addr>
<config.namespace>chenbowen</config.namespace>
<config.namespace>haodongqiang</config.namespace>
<config.group>DEFAULT_GROUP</config.group>
<config.username>nacos</config.username>
<config.password>P@ssword25</config.password>

View File

@@ -0,0 +1,4 @@
ALTER TABLE "SYSTEM_ROLE_MENU" ADD COLUMN "SHOW_MENU" BIT DEFAULT ('1') NOT NULL;
COMMENT ON COLUMN "SYSTEM_ROLE_MENU"."SHOW_MENU" IS '是否显示菜单';
CREATE INDEX "IDX_SYSTEM_ROLE_ID_AND_MENU_ID" ON "SYSTEM_ROLE_MENU"(ROLE_ID,MENU_ID);

View File

@@ -0,0 +1,7 @@
-- 为 API 客户端凭证表添加"是否启用加密"字段
-- 2026-01-14
ALTER TABLE databus_api_client_credential
ADD enable_encryption BIT DEFAULT '1' NOT NULL;
COMMENT ON COLUMN databus_api_client_credential.enable_encryption IS '是否启用加密传输';

View File

@@ -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);

View File

@@ -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 '下载次数';

View File

@@ -0,0 +1,42 @@
-- 表bse_mtrl_grade_ext
CREATE TABLE IF NOT EXISTS bse_mtrl_grade_ext (
id BIGINT PRIMARY KEY,
CMP_CD VARCHAR(64) NOT NULL,
CMP_NM VARCHAR(128),
MTRL_CD VARCHAR(128) NOT NULL,
MTRL_NM VARCHAR(255),
ZH_BRAND VARCHAR(255),
EN_BRAND VARCHAR(255),
SPC_MDL VARCHAR(255),
LINE_TP VARCHAR(64),
PKG VARCHAR(255),
company_id BIGINT,
company_name VARCHAR(128),
dept_id BIGINT,
dept_name VARCHAR(128),
post_id BIGINT,
tenant_id BIGINT DEFAULT 1,
creator_name VARCHAR(64),
updater_name VARCHAR(64),
creator VARCHAR(64),
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
updater VARCHAR(64),
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
deleted BIT DEFAULT 0 NOT NULL
);
-- 索引
CREATE INDEX IF NOT EXISTS idx_bse_mtrl_grade_ext_mtrl_cd ON bse_mtrl_grade_ext (MTRL_CD);
CREATE INDEX IF NOT EXISTS idx_bse_mtrl_grade_ext_cmp_cd ON bse_mtrl_grade_ext (CMP_CD);
-- 字段注释(可选)
COMMENT ON TABLE bse_mtrl_grade_ext IS '物料牌号扩展';
COMMENT ON COLUMN bse_mtrl_grade_ext.CMP_CD IS '公司编码';
COMMENT ON COLUMN bse_mtrl_grade_ext.CMP_NM IS '公司名称';
COMMENT ON COLUMN bse_mtrl_grade_ext.MTRL_CD IS '物料编码';
COMMENT ON COLUMN bse_mtrl_grade_ext.MTRL_NM IS '物料名称';
COMMENT ON COLUMN bse_mtrl_grade_ext.ZH_BRAND IS '中文牌号';
COMMENT ON COLUMN bse_mtrl_grade_ext.EN_BRAND IS '英文牌号';
COMMENT ON COLUMN bse_mtrl_grade_ext.SPC_MDL IS '规格型号';
COMMENT ON COLUMN bse_mtrl_grade_ext.LINE_TP IS '线别material_line_type 字典)';
COMMENT ON COLUMN bse_mtrl_grade_ext.PKG IS '包装';

View File

@@ -0,0 +1,10 @@
-- 字典类型:线别
INSERT INTO system_dict_type (id, name, type, status, create_time, remark)
VALUES (202701012001000001, '线别', 'material_line_type', 0, SYSDATE, '物料牌号扩展线别');
-- 字典数据:随机两项示例
INSERT INTO system_dict_data (id, dict_type, label, value, sort, status, color_type, css_class, create_time)
VALUES (202701012001000101, 'material_line_type', '单线', 'single', 1, 0, 0, NULL, SYSDATE);
INSERT INTO system_dict_data (id, dict_type, label, value, sort, status, color_type, css_class, create_time)
VALUES (202701012001000102, 'material_line_type', '双线', 'double', 2, 0, 0, NULL, SYSDATE);

View File

@@ -0,0 +1,21 @@
-- 物料牌号扩展菜单DM 脚本)
-- 如父级“物料管理”菜单 ID 不同,请调整 parent_id 默认值 1980093482014994433
-- 清理旧数据,便于重复执行
DELETE FROM system_menu WHERE id IN (202701012002000000,202701012002000001,202701012002000002,202701012002000003,202701012002000004);
-- 功能菜单
INSERT INTO system_menu (
id, name, permission, type, sort, parent_id,
path, icon, component, component_name, status
) VALUES (
202701012002000000, '物料牌号扩展', 'base:material-grade-ext:query', 2, 30, 1980093482014994433,
'material-grade-ext', 'fa:list-alt', 'base/materialgradeext/index', 'MaterialGradeExt', 0
);
-- 按钮权限
INSERT INTO system_menu (id, name, permission, type, sort, parent_id, path, icon, component, status) VALUES
(202701012002000001, '物料牌号扩展查询', 'base:material-grade-ext:query', 3, 1, 202701012002000000, '', '', '', 0),
(202701012002000002, '物料牌号扩展新增', 'base:material-grade-ext:create', 3, 2, 202701012002000000, '', '', '', 0),
(202701012002000003, '物料牌号扩展修改', 'base:material-grade-ext:update', 3, 3, 202701012002000000, '', '', '', 0),
(202701012002000004, '物料牌号扩展删除', 'base:material-grade-ext:delete', 3, 4, 202701012002000000, '', '', '', 0);

View File

@@ -0,0 +1,9 @@
-- 短信渠道新增鸿联九五支持达梦8
-- 1) system_sms_channel 表新增 epid 字段
-- 2) system_sms_channel_code 字典新增 HL95 选项
ALTER TABLE system_sms_channel ADD COLUMN epid VARCHAR(64);
COMMENT ON COLUMN system_sms_channel.epid IS '企业编号(epid)';
INSERT INTO system_dict_data (id, sort, label, value, dict_type, status, color_type, css_class, remark, creator, create_time, updater, update_time, deleted)
VALUES (1593, 5, '中铝e办', 'ZLE', 'system_sms_channel_code', 0, '', '', '', '1', '2026-01-09 00:00:00', '1', '2026-01-09 00:00:00', '0');

View File

@@ -10,11 +10,11 @@
<name>中铜 ZStack 私服</name>
<url>http://172.16.46.63:30708/repository/test/</url>
</repository>
<!-- <snapshotRepository>-->
<!-- <id>ZT</id>-->
<!-- <name>中铜 ZStack 私服</name>-->
<!-- <url>https://your-nexus.example.com/repository/maven-snapshots/</url>-->
<!-- </snapshotRepository>-->
<snapshotRepository>
<id>ZT-snap</id>
<name>中铜 ZStack 私服</name>
<url>http://172.16.46.63:30708/repository/test-snap/</url>
</snapshotRepository>
</distributionManagement>
<groupId>com.zt.plat</groupId>
<artifactId>zt-dependencies</artifactId>
@@ -26,7 +26,7 @@
<url>https://github.com/YunaiV/ruoyi-vue-pro</url>
<properties>
<revision>3.0.46</revision>
<revision>3.0.47-SNAPSHOT</revision>
<flatten-maven-plugin.version>1.6.0</flatten-maven-plugin.version>
<!-- 统一依赖管理 -->
<spring.boot.version>3.4.5</spring.boot.version>

View File

@@ -25,7 +25,7 @@
<module>zt-spring-boot-starter-job</module>
<module>zt-spring-boot-starter-mq</module>
<module>zt-spring-boot-starter-rpc</module>
<module>zt-spring-boot-starter-seata-dm</module>
<module>zt-spring-boot-starter-excel</module>
<module>zt-spring-boot-starter-test</module>
@@ -33,7 +33,6 @@
<module>zt-spring-boot-starter-biz-data-permission</module>
<module>zt-spring-boot-starter-biz-ip</module>
<module>zt-spring-boot-starter-biz-business</module>
<module>zt-spring-boot-starter-seata-dm</module>
</modules>
<artifactId>zt-framework</artifactId>

View File

@@ -163,6 +163,33 @@
<artifactId>mockito-core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk18on</artifactId>
<version>1.78.1</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents.client5</groupId>
<artifactId>httpclient5</artifactId>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents.client5</groupId>
<artifactId>httpclient5</artifactId>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.14</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpmime</artifactId>
<version>4.5.14</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>

View File

@@ -47,5 +47,4 @@ public interface PermissionCommonApi {
@Parameter(name = "roleCodes", description = "角色编码", example = "2", required = true)
})
CommonResult<DeptDataPermissionRespDTO> getDeptDataPermissionWithRoleCodes(@RequestParam("userId") Long userId, @RequestParam("roleCodes") String roleCodes);
}

View File

@@ -15,7 +15,7 @@ import java.util.List;
import java.util.Map;
@Schema(description = "分页结果")
@Data
@Data //TODO 分页结果参考这个
public final class PageResult<T> implements Serializable {
@Schema(description = "数据", requiredMode = Schema.RequiredMode.REQUIRED)

View File

@@ -9,7 +9,7 @@ import java.util.concurrent.*;
* 多次提交,一次等待
*/
public class AsyncLatchUtils {
private static final ThreadLocal<List<TaskInfo>> THREADLOCAL = ThreadLocal.withInitial(LinkedList::new);
private static final ThreadLocal<List<TaskInfo>> THREAD_LOCAL = ThreadLocal.withInitial(LinkedList::new);
/**
* 提交一个异步任务
@@ -17,7 +17,7 @@ public class AsyncLatchUtils {
* @param runnable 需要异步执行的具体业务逻辑
*/
public static void submitTask(Executor executor, Runnable runnable) {
THREADLOCAL.get().add(new TaskInfo(executor, runnable));
THREAD_LOCAL.get().add(new TaskInfo(executor, runnable));
}
/**
@@ -25,8 +25,8 @@ public class AsyncLatchUtils {
* @return
*/
private static List<TaskInfo> popTask() {
List<TaskInfo> taskInfos = THREADLOCAL.get();
THREADLOCAL.remove();
List<TaskInfo> taskInfos = THREAD_LOCAL.get();
THREAD_LOCAL.remove();
return taskInfos;
}
@@ -39,7 +39,7 @@ public class AsyncLatchUtils {
*/
public static boolean waitFor(long timeout, TimeUnit timeUnit) {
List<TaskInfo> taskInfos = popTask();
if (taskInfos.isEmpty()) {
if (taskInfos.isEmpty()) {
return true;
}
CountDownLatch latch = new CountDownLatch(taskInfos.size());
@@ -57,8 +57,11 @@ public class AsyncLatchUtils {
boolean await = false;
try {
await = latch.await(timeout, timeUnit);
} catch (Exception ignored) {}
return await;
} catch (Exception ignored) {
// 恢复中断状态
Thread.currentThread().interrupt();
}
return await;
}
private static final class TaskInfo {

View File

@@ -0,0 +1,382 @@
package com.zt.plat.framework.common.util.http;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpStatus;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.UUID;
/**
* HttpClient工具类
*
* @author luzemin
*/
@Slf4j
public class HttpClientUtils {
/**
* 请求配置对象
*/
private static final RequestConfig REQUEST_CONFIG;
static {
/* 设置请求和传输超时时间 */
REQUEST_CONFIG = RequestConfig.custom().setSocketTimeout(60000).setConnectTimeout(60000).build();
}
/**
* post请求传输json参数
*
* @param url url地址
* @param jsonParam 参数
* @return JSONObject 请求结果对象
*/
public static JSONObject httpPost(String url, JSONObject jsonParam) {
/* 请求返回结果 */
JSONObject jsonResult = null;
/* 构建连接对象 */
CloseableHttpClient httpClient = HttpClients.createDefault();
HttpPost httpPost = new HttpPost(url);
httpPost.setConfig(REQUEST_CONFIG);
try {
/* 构建请求体 */
if (StringUtils.isNotBlank(jsonParam.toJSONString())) {
StringEntity entity = new StringEntity(jsonParam.toJSONString(), StandardCharsets.UTF_8);
entity.setContentEncoding(StandardCharsets.UTF_8.name());
entity.setContentType(ContentType.APPLICATION_JSON.getMimeType());
httpPost.setEntity(entity);
}
/* 提交请求,构建响应对象 */
CloseableHttpResponse response = httpClient.execute(httpPost);
/* 处理请求结果 */
if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
HttpEntity responseEntity = response.getEntity();
String result = EntityUtils.toString(responseEntity, StandardCharsets.UTF_8);
jsonResult = JSONObject.parseObject(result);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
httpPost.releaseConnection();
}
return jsonResult;
}
/**
* post请求传输String参数 例如name=Jack&sex=1&type=2
* Content-type:application/x-www-form-urlencoded
*
* @param url url地址
* @param strParam 参数
* @return JSONObject 请求结果对象
*/
public static JSONObject httpPost(String url, String strParam) {
/* 请求返回结果 */
JSONObject jsonResult = null;
/* 构建连接对象 */
CloseableHttpClient httpClient = HttpClients.createDefault();
HttpPost httpPost = new HttpPost(url);
httpPost.setConfig(REQUEST_CONFIG);
try {
/* 构建请求体 */
if (StringUtils.isNotBlank(strParam)) {
StringEntity entity = new StringEntity(strParam, StandardCharsets.UTF_8);
entity.setContentEncoding(StandardCharsets.UTF_8.name());
entity.setContentType(ContentType.APPLICATION_JSON.getMimeType());
httpPost.setEntity(entity);
}
/* 提交请求,构建响应对象 */
CloseableHttpResponse response = httpClient.execute(httpPost);
/* 处理请求结果 */
if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
HttpEntity responseEntity = response.getEntity();
String result = EntityUtils.toString(responseEntity, StandardCharsets.UTF_8);
jsonResult = JSONObject.parseObject(result);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
httpPost.releaseConnection();
}
return jsonResult;
}
/**
* post请求传输String参数 例如name=Jack&sex=1&type=2
* Content-type:application/x-www-form-urlencoded
*
* @param url url地址
* @param strParam 参数
* @param token 身份认证令牌
* @return JSONObject 请求结果对象
*/
public static JSONObject httpPostByToken(String url, String strParam, String token) {
/* 请求返回结果 */
JSONObject jsonResult = null;
/* 构建连接对象 */
CloseableHttpClient httpClient = HttpClients.createDefault();
HttpPost httpPost = new HttpPost(url);
httpPost.setConfig(REQUEST_CONFIG);
try {
/* 构建请求体 */
if (StringUtils.isNotBlank(strParam)) {
StringEntity entity = new StringEntity(strParam, StandardCharsets.UTF_8);
entity.setContentEncoding(StandardCharsets.UTF_8.name());
entity.setContentType(ContentType.APPLICATION_JSON.getMimeType());
httpPost.setEntity(entity);
}
if (StringUtils.isNotBlank(token)) {
httpPost.setHeader("token", token);
}
/* 提交请求,构建响应对象 */
CloseableHttpResponse response = httpClient.execute(httpPost);
/* 处理请求结果 */
if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
HttpEntity responseEntity = response.getEntity();
String result = EntityUtils.toString(responseEntity, StandardCharsets.UTF_8);
jsonResult = JSONObject.parseObject(result);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
httpPost.releaseConnection();
}
return jsonResult;
}
/**
* post请求传输String参数 例如name=Jack&sex=1&type=2
* Content-type:application/x-www-form-urlencoded
*
* @param url url地址
* @param strParam 参数
* @return String 请求结果对象
*/
public static String httpPostStr(String url, String strParam) {
/* 请求返回结果 */
String jsonResult = null;
/* 构建连接对象 */
CloseableHttpClient httpClient = HttpClients.createDefault();
HttpPost httpPost = new HttpPost(url);
httpPost.setConfig(REQUEST_CONFIG);
try {
/* 构建请求体 */
if (StringUtils.isNotBlank(strParam)) {
StringEntity entity = new StringEntity(strParam, StandardCharsets.UTF_8);
entity.setContentEncoding(StandardCharsets.UTF_8.name());
entity.setContentType(ContentType.APPLICATION_FORM_URLENCODED.getMimeType());
httpPost.setEntity(entity);
}
/* 提交请求,构建响应对象 */
CloseableHttpResponse response = httpClient.execute(httpPost);
/* 处理请求结果 */
if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
HttpEntity responseEntity = response.getEntity();
jsonResult = EntityUtils.toString(responseEntity, StandardCharsets.UTF_8);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
httpPost.releaseConnection();
}
return jsonResult;
}
/**
* post请求传输String参数 例如name=Jack&sex=1&type=2
* Content-type:application/x-www-form-urlencoded
*
* @param url url地址
* @param strParam 参数
* @param token 身份认证字符串
* @return String 请求结果对象
*/
public static String httpPostStrByToken(String url, String strParam, String token) {
/* 请求返回结果 */
String jsonResult = null;
/* 构建连接对象 */
CloseableHttpClient httpClient = HttpClients.createDefault();
HttpPost httpPost = new HttpPost(url);
httpPost.setConfig(REQUEST_CONFIG);
try {
/* 构建请求体 */
if (StringUtils.isNotBlank(strParam)) {
StringEntity entity = new StringEntity(strParam, StandardCharsets.UTF_8);
entity.setContentEncoding(StandardCharsets.UTF_8.name());
entity.setContentType(ContentType.APPLICATION_JSON.getMimeType());
httpPost.setEntity(entity);
}
if (StringUtils.isNotBlank(token)) {
httpPost.setHeader("token", token);
}
/* 提交请求,构建响应对象 */
CloseableHttpResponse response = httpClient.execute(httpPost);
/* 处理请求结果 */
if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
HttpEntity responseEntity = response.getEntity();
jsonResult = EntityUtils.toString(responseEntity, StandardCharsets.UTF_8);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
httpPost.releaseConnection();
}
return jsonResult;
}
/**
* 根据指定的url地址上传文件
*
* @param mediaName 服务器定义的读取文件流的name
* @param url 文件上传url
* @param file 文件对象
* @return JSONObject 文件上传结果
*/
public static JSONObject httpFileUpload(String mediaName, String url, MultipartFile file) {
/* 请求返回结果 */
JSONObject jsonResult = null;
/* 构建连接对象 */
CloseableHttpClient httpClient = HttpClients.createDefault();
HttpPost httpPost = new HttpPost(url);
httpPost.setConfig(REQUEST_CONFIG);
/* 构建请求头 */
String boundaryStr = UUID.randomUUID().toString();
httpPost.setHeader(HttpHeaders.ACCEPT_CHARSET, StandardCharsets.UTF_8.name());
httpPost.setHeader(HttpHeaders.CONNECTION, "Keep-Alive");
httpPost.addHeader(HttpHeaders.CONTENT_TYPE, ContentType.MULTIPART_FORM_DATA.getMimeType() + ";boundary=" + boundaryStr);
try {
/* 构建文件对象 */
MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create();
multipartEntityBuilder.setBoundary(boundaryStr)
.setContentType(ContentType.APPLICATION_OCTET_STREAM)
.setCharset(StandardCharsets.UTF_8)
.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
multipartEntityBuilder.addBinaryBody(mediaName, file.getInputStream(), ContentType.APPLICATION_OCTET_STREAM, file.getOriginalFilename());
HttpEntity entity = multipartEntityBuilder.build();
httpPost.setEntity(entity);
/* 提交请求,构建响应对象 */
CloseableHttpResponse response = httpClient.execute(httpPost);
/* 处理请求结果 */
if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
HttpEntity responseEntity = response.getEntity();
String result = EntityUtils.toString(responseEntity, StandardCharsets.UTF_8);
jsonResult = JSONObject.parseObject(result);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
httpPost.releaseConnection();
}
return jsonResult;
}
/**
* 发送get请求
*
* @param url 路径
* @return JSONObject 请求结果对象
*/
public static JSONObject httpGet(String url) {
/* 请求返回结果 */
JSONObject jsonResult = null;
/* 构建连接对象 */
CloseableHttpClient httpClient = HttpClients.createDefault();
HttpGet httpGet = new HttpGet(url);
httpGet.setConfig(REQUEST_CONFIG);
try {
/* 提交请求,构建响应对象 */
CloseableHttpResponse response = httpClient.execute(httpGet);
/* 处理请求结果 */
if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
HttpEntity responseEntity = response.getEntity();
String result = EntityUtils.toString(responseEntity, StandardCharsets.UTF_8);
jsonResult = JSONObject.parseObject(result);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
httpGet.releaseConnection();
}
return jsonResult;
}
/**
* 发送get请求
*
* @param url 路径
* @return JSONObject 请求结果对象
*/
public static String httpGetStr(String url) {
/* 请求返回结果 */
String jsonResult = null;
/* 构建连接对象 */
CloseableHttpClient httpClient = HttpClients.createDefault();
HttpGet httpGet = new HttpGet(url);
httpGet.setConfig(REQUEST_CONFIG);
try {
/* 提交请求,构建响应对象 */
CloseableHttpResponse response = httpClient.execute(httpGet);
/* 处理请求结果 */
if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
HttpEntity responseEntity = response.getEntity();
jsonResult = EntityUtils.toString(responseEntity, StandardCharsets.UTF_8);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
httpGet.releaseConnection();
}
return jsonResult;
}
}

View File

@@ -1,9 +1,10 @@
package com.zt.plat.framework.common.util.security;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.symmetric.SM4;
import com.zt.plat.framework.common.util.json.JsonUtils;
import lombok.extern.slf4j.Slf4j;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
@@ -11,6 +12,7 @@ import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.Security;
import java.util.*;
/**
@@ -27,6 +29,15 @@ public final class CryptoSignatureUtils {
private static final String AES_TRANSFORMATION = "AES/ECB/PKCS5Padding";
public static final String SIGNATURE_FIELD = "signature";
private static final String CHARSET = "UTF-8";
//@Value("${sa.encrypt.sm4.key}")
private static String SM4_KEY = "1234567890123456";
static {
Security.addProvider(new BouncyCastleProvider());
}
private CryptoSignatureUtils() {
}
@@ -220,4 +231,91 @@ public final class CryptoSignatureUtils {
}
return sb.toString();
}
//-------------------------------- 国密方式2 -------------------------------------------------------
/**
* 加密
*/
public static String enCode(String data) {
try {
// 第一步: SM4 加密
SM4 sm4 = new SM4(hexToBytes(stringToHex(SM4_KEY)));
String encryptHex = sm4.encryptHex(data);
// 第二步: Base64 编码
return new String(Base64.getEncoder().encode(encryptHex.getBytes(CHARSET)), CHARSET);
} catch (Exception e) {
log.error("国密加密失败{}",e.getMessage(),e);
return "";
}
}
/**
* 解密
*/
public static String deCode(String data) {
try {
// 第一步: Base64 解码
byte[] base64Decode = Base64.getDecoder().decode(data);
// 第二步: SM4 解密
SM4 sm4 = new SM4(hexToBytes(stringToHex(SM4_KEY)));
return sm4.decryptStr(new String(base64Decode));
} catch (Exception e) {
log.error("国密解密失败{}",e.getMessage(),e);
return "";
}
}
public static String stringToHex(String input) {
char[] chars = input.toCharArray();
StringBuilder hex = new StringBuilder();
for (char c : chars) {
hex.append(Integer.toHexString((int) c));
}
return hex.toString();
}
/**
* 16 进制串转字节数组
*
* @param hex 16进制字符串
* @return byte数组
*/
public static byte[] hexToBytes(String hex) {
int length = hex.length();
byte[] result;
if (length % 2 == 1) {
length++;
result = new byte[(length / 2)];
hex = "0" + hex;
} else {
result = new byte[(length / 2)];
}
int j = 0;
for (int i = 0; i < length; i += 2) {
result[j] = hexToByte(hex.substring(i, i + 2));
j++;
}
return result;
}
/**
* 16 进制字符转字节
*
* @param hex 16进制字符 0x00到0xFF
* @return byte
*/
private static byte hexToByte(String hex) {
return (byte) Integer.parseInt(hex, 16);
}
}

View File

@@ -0,0 +1,195 @@
package com.zt.plat.framework.common.util.security;
import javax.crypto.Cipher;
import java.nio.charset.StandardCharsets;
import java.security.Key;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
/**
* 3DES加密解密工具类
* 注意如果websphere下报错Could not find class 'com.sun.crypto.provider.SunJCE'
* 解决方法如下: 下载sunjce_provider.jar放到jdk目录\jre\lib\ext里即可解决
*
* @author apple
*/
public class DESUtil {
/**
* 默认的密钥
*/
private static final String strDefaultKey = "cymco-20160329000000000000000ABCGHDYFYSSPPOEWWWDDDSSXX-cymco";
private Cipher encryptCipher = null;
private Cipher decryptCipher = null;
/**
* 将byte数组转换为表示16进制值的字符串byte[]{8,18}转换为0813 和public static byte[]
* hexStr2ByteArr(String strIn) 互为可逆的转换过程
* @param arrB 需要转换的byte数组
* @return 转换后的字符串
* @throws Exception 本方法不处理任何异常,所有异常全部抛出
*/
public static String byteArr2HexStr(byte[] arrB) throws Exception {
int iLen = arrB.length;
// 每个byte用两个字符才能表示所以字符串的长度是数组长度的两倍
StringBuffer sb = new StringBuffer(iLen * 2);
for (int i = 0; i < iLen; i++) {
int intTmp = arrB[i];
// 把负数转换为正数
while (intTmp < 0) {
intTmp = intTmp + 256;
}
// 小于0F的数需要在前面补0
if (intTmp < 16) {
sb.append("0");
}
sb.append(Integer.toString(intTmp, 16));
}
return sb.toString();
}
/**
* 将表示16进制值的字符串转换为byte数组 和public static String byteArr2HexStr(byte[] arrB)
* 互为可逆的转换过程
* @param strIn 需要转换的字符串
* @return 转换后的byte数组
* @throws Exception 本方法不处理任何异常,所有异常全部抛出
*/
public static byte[] hexStr2ByteArr(String strIn) throws Exception {
byte[] arrB = strIn.getBytes(StandardCharsets.UTF_8);
int iLen = arrB.length;
// 两个字符表示一个字节所以字节数组长度是字符串长度除以2
byte[] arrOut = new byte[iLen / 2];
for (int i = 0; i < iLen; i = i + 2) {
String strTmp = new String(arrB, i, 2);
arrOut[i / 2] = (byte) Integer.parseInt(strTmp, 16);
}
return arrOut;
}
/**
* 默认构造方法,使用默认密钥
* @throws Exception
*/
public DESUtil() throws Exception {
this(strDefaultKey);
}
/**
* 指定密钥构造方法
* @param strKey 指定的密钥
* @throws Exception
*/
public DESUtil(String strKey) throws Exception {
//Security.addProvider(new com.sun.crypto.provider.SunJCE());
Key key = getKey(strKey.getBytes());
encryptCipher = Cipher.getInstance("DES");
encryptCipher.init(Cipher.ENCRYPT_MODE, key);
decryptCipher = Cipher.getInstance("DES");
decryptCipher.init(Cipher.DECRYPT_MODE, key);
}
/**
* 加密字节数组
* @param arrB 需加密的字节数组
* @return 加密后的字节数组
* @throws Exception
*/
public byte[] encrypt(byte[] arrB) throws Exception {
return encryptCipher.doFinal(arrB);
}
/**
* 加密字符串
* @param strIn 需加密的字符串
* @return 加密后的字符串
* @throws Exception
*/
public String encrypt(String strIn) throws Exception {
return byteArr2HexStr(encrypt(strIn.getBytes()));
}
/**
* 解密字节数组
* @param arrB 需解密的字节数组
* @return 解密后的字节数组
* @throws Exception
*/
public byte[] decrypt(byte[] arrB) throws Exception {
return decryptCipher.doFinal(arrB);
}
/**
* 解密字符串
* @param strIn 需解密的字符串
* @return 解密后的字符串
* @throws Exception
*/
public String decrypt(String strIn) throws Exception {
return new String(decrypt(hexStr2ByteArr(strIn)));
}
/**
* 从指定字符串生成密钥密钥所需的字节数组长度为8位 不足8位时后面补0超出8位只取前8位
* @param arrBTmp 构成该字符串的字节数组
* @return 生成的密钥
* @throws Exception
*/
private Key getKey(byte[] arrBTmp) throws Exception {
// 创建一个空的8位字节数组默认值为0
byte[] arrB = new byte[8];
// 将原始字节数组转换为8位
for (int i = 0; i < arrBTmp.length && i < arrB.length; i++) {
arrB[i] = arrBTmp[i];
}
// 生成密钥
Key key = new javax.crypto.spec.SecretKeySpec(arrB, "DES");
return key;
}
public static String SHA1(String decript) throws NoSuchAlgorithmException {
try {
MessageDigest digest = MessageDigest.getInstance("SHA-1");
digest.update(decript.getBytes());
byte messageDigest[] = digest.digest();
// Create Hex String
StringBuffer hexString = new StringBuffer();
// 字节数组转换为 十六进制 数
for (int i = 0; i < messageDigest.length; i++) {
String shaHex = Integer.toHexString(messageDigest[i] & 0xFF);
if (shaHex.length() < 2) {
hexString.append(0);
}
hexString.append(shaHex);
}
return hexString.toString();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return "";
}
public static void main(String [] args){
DESUtil des;
try {
des = new DESUtil();
String en= des.encrypt("fls123,12121");
System.out.println(en);
String de = des.decrypt(en);
System.out.println(de);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

View File

@@ -0,0 +1,210 @@
package com.zt.plat.framework.common.util.validation;
import java.util.regex.Pattern;
/**
* 正则校验工具
*
* @author luzemin
**/
public class MatcherSolveUtils {
/**
* 正则校验正数、负数、和小数
*/
private static final Pattern IS_NUM = Pattern.compile("^(\\-|\\+)?\\d+(\\.\\d+)?$");
/**
* 正则校验大于0的数字
*/
private static final Pattern IS_GT_0_NUM = Pattern.compile("(^[0-9]+\\.\\d+$)|(^[0-9]+$)");
/**
* 正则校验大于等于0的数字
*/
private static final Pattern IS_GE_EQ_0_NUM = Pattern.compile("(^[0-9]+\\.\\d+$)|(^[1-9]+\\d*$)");
/**
* 正则校验字母或者数字组成的字符串
*/
private static final Pattern EN_NUM = Pattern.compile("^[A-Za-z0-9]+$");
/**
* 中文、英文、数字但不包括下划线等符号
*/
private static final Pattern EN_CN_NUM = Pattern.compile("^[\\u4E00-\\u9FA5A-Za-z0-9]+$");
/**
* Email地址
*/
private static final Pattern EMAIL = Pattern.compile("^\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*$");
/**
* 域名
*/
private static final Pattern WWW = Pattern.compile("[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+\\.?");
/**
* InternetURL
*/
private static final Pattern URL = Pattern.compile("(https?|ftp|file)://[-A-Za-z0-9+&@#/%?=~_|!:,.;]+[-A-Za-z0-9+&@#/%=~_|]");
/**
* 手机号码
*/
private static final Pattern MOBILE_NUM = Pattern.compile("^(13[0-9]|14[5|7]|15[0|1|2|3|4|5|6|7|8|9]|18[0|1|2|3|5|6|7|8|9])\\d{8}$");
/**
* 车牌号
*/
private static final Pattern TRUCK_NO = Pattern.compile("^([京津晋冀蒙辽吉黑沪苏浙皖闽赣鲁豫鄂湘粤桂琼渝川贵云藏陕甘青宁新][ABCDEFGHJKLMNPQRSTUVWXY][1-9DF][1-9ABCDEFGHJKLMNPQRSTUVWXYZ]\\d{3}[1-9DF]|[京津晋冀蒙辽吉黑沪苏浙皖闽赣鲁豫鄂湘粤桂琼渝川贵云藏陕甘青宁新][ABCDEFGHJKLMNPQRSTUVWXY][\\dABCDEFGHJKLNMxPQRSTUVWXYZ]{5})$");
/**
* 电话号码正则表达式支持手机号码3-4位区号7-8位直播号码14位分机号
*/
private static final Pattern PHONE_NUM = Pattern.compile("((\\d{11})|^((\\d{7,8})|(\\d{4}|\\d{3})-(\\d{7,8})|(\\d{4}|\\d{3})-(\\d{7,8})-(\\d{4}|\\d{3}|\\d{2}|\\d{1})|(\\d{7,8})-(\\d{4}|\\d{3}|\\d{2}|\\d{1}))$)");
/**
* 身份证
*/
private static final Pattern ID_CARD = Pattern.compile("(^\\d{15}$)|(^\\d{18}$)|(^\\d{17}(\\d|X|x)$)");
/**
* 帐号是否合法(字母开头允许5-16字节允许字母数字下划线)
*/
private static final Pattern ACCOUNT = Pattern.compile("^[a-zA-Z][a-zA-Z0-9_]{4,15}$");
/**
* 密码(以字母开头长度在6~18之间只能包含字母、数字和下划线)
*/
private static final Pattern PASSWORD = Pattern.compile("^[a-zA-Z]\\w{5,17}$");
/**
* 强密码(必须包含大小写字母和数字的组合可以使用特殊字符长度在8-18之间)
*/
private static final Pattern PASSWORD_STRONG = Pattern.compile("^(?=.*\\d)(?=.*[a-z])(?=.*[A-Z]).{8,18}$");
/**
* 正则校验正数、负数、和小数
*
* @param str 待校验字符串
*/
public static boolean checkIsNum(String str) {
return IS_NUM.matcher(str).matches();
}
/**
* 正则校验大于0的数字
*
* @param str 待校验字符串t
*/
public static boolean checkIsGt0Num(String str) {
return IS_GT_0_NUM.matcher(str).matches();
}
/**
* 正则校验大于等于0的数字
*
* @param str 待校验字符串
*/
public static boolean checkIsGtEq0Num(String str) {
return IS_GE_EQ_0_NUM.matcher(str).matches();
}
/**
* 正则校验字母或者数字组成的字符串
*
* @param str 待校验字符串
*/
public static boolean checkEnNum(String str) {
return EN_NUM.matcher(str).matches();
}
/**
* 中文、英文、数字但不包括下划线等符号
*
* @param str 待校验字符串
*/
public static boolean checkEnCnNum(String str) {
return EN_CN_NUM.matcher(str).matches();
}
/**
* Email地址
*
* @param str 待校验字符串
*/
public static boolean checkEmail(String str) {
return EMAIL.matcher(str).matches();
}
/**
* 域名
*
* @param str 待校验字符串
*/
public static boolean checkWww(String str) {
return WWW.matcher(str).matches();
}
/**
* InternetURL
*
* @param str 待校验字符串
*/
public static boolean checkInternetURL(String str) {
return URL.matcher(str).matches();
}
/**
* 手机号码
*
* @param str 待校验字符串
*/
public static boolean checkMobileNum(String str) {
return MOBILE_NUM.matcher(str).matches();
}
/**
* 车牌号
*
* @param str 待校验字符串
* @return 校验通过-true反之-false
*/
public static boolean checkTruckNo(String str) {
return TRUCK_NO.matcher(str).matches();
}
/**
* 电话号码正则表达式支持手机号码3-4位区号7-8位直播号码14位分机号
*
* @param str 待校验字符串
*/
public static boolean checkPhoneNum(String str) {
return PHONE_NUM.matcher(str).matches();
}
/**
* 身份证
*
* @param str 待校验字符串
*/
public static boolean checkIdCard(String str) {
return ID_CARD.matcher(str).matches();
}
/**
* 帐号是否合法(字母开头允许5-16字节允许字母数字下划线)
*
* @param str 待校验字符串
*/
public static boolean checkAccount(String str) {
return ACCOUNT.matcher(str).matches();
}
/**
* 密码(以字母开头长度在6~18之间只能包含字母、数字和下划线)
*
* @param str 待校验字符串
*/
public static boolean checkPassword(String str) {
return PASSWORD.matcher(str).matches();
}
/**
* 强密码(必须包含大小写字母和数字的组合可以使用特殊字符长度在8-18之间)
*
* @param str 待校验字符串
*/
public static boolean checkPasswordStrong(String str) {
return PASSWORD_STRONG.matcher(str).matches();
}
}

View File

@@ -21,9 +21,11 @@ public class ZtBusinessAutoConfiguration implements WebMvcConfigurer {
public void addInterceptors(InterceptorRegistry registry) {
// 拦截所有 url统一进行业务与文件上传请求头校验
registry.addInterceptor(new BusinessHeaderInterceptor())
.addPathPatterns("/**");
.addPathPatterns("/**")
.excludePathPatterns("/get*");
registry.addInterceptor(new FileUploadHeaderInterceptor())
.addPathPatterns("/**");
.addPathPatterns("/**")
.excludePathPatterns("/get*");
}
@Bean

View File

@@ -33,7 +33,7 @@ public class BusinessDataPermissionEntityScanner {
*/
private static final Set<String> EXCLUDED_PACKAGE_PREFIXES = Set.of(
"com.zt.plat.module.backendlogistics",
"com.zt.plat.module.erp",
// "com.zt.plat.module.erp",
"com.zt.plat.framework.mybatis.core.dataobject.BusinessBaseDO");
private final Set<String> basePackages;

View File

@@ -73,7 +73,6 @@ public class DeptContextHolder {
ROLE_CODE_LIST.remove();
}
public static void clear() {
DEPT_ID.remove();
COMPANY_ID.remove();

View File

@@ -11,7 +11,7 @@ import static com.zt.plat.framework.web.core.util.WebFrameworkUtils.HEADER_TENAN
*
* Producer 发送消息时,将 {@link TenantContextHolder} 租户编号,添加到消息的 Header 中
*
* @author ZT
* @author ZT TODO
*/
public class TenantRocketMQSendMessageHook implements SendMessageHook {

View File

@@ -54,7 +54,7 @@ public interface BaseMapperX<T> extends MPJBaseMapper<T> {
PageSumSupport.tryAttachSummary(this, queryWrapper, pageResult);
return pageResult;
}
//TODO 分页结果参考这个 ===============================
// MyBatis Plus 查询
IPage<T> mpPage = MyBatisUtils.buildPage(pageParam, sortingFields);
selectPage(mpPage, queryWrapper);

View File

@@ -10,6 +10,7 @@
<modules>
<module>zt-module-databus-api</module>
<module>zt-module-databus-server</module>
<module>zt-module-databus-server-app</module>
</modules>
<modelVersion>4.0.0</modelVersion>

View File

@@ -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

View File

@@ -0,0 +1,48 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>zt-module-databus</artifactId>
<groupId>com.zt.plat</groupId>
<version>${revision}</version>
</parent>
<artifactId>zt-module-databus-server-app</artifactId>
<packaging>jar</packaging>
<name>${project.artifactId}</name>
<description>
Databus 模块启动器。
</description>
<dependencies>
<dependency>
<groupId>com.zt.plat</groupId>
<artifactId>zt-module-databus-server</artifactId>
<version>${revision}</version>
</dependency>
</dependencies>
<build>
<!-- 设置构建的 jar 包名 -->
<finalName>${project.artifactId}</finalName>
<plugins>
<!-- 打包 -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring.boot.version}</version>
<executions>
<execution>
<goals>
<goal>repackage</goal> <!-- 将引入的 jar 打入其中 -->
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@@ -37,17 +37,11 @@ spring:
primary: master
datasource:
master:
#url: jdbc:dm://172.16.46.247:1050?schema=RUOYI-VUE-PRO
#username: SYSDBA
#password: pgbsci6ddJ6Sqj@e
url: jdbc:dm://172.17.11.98:20870?schema=JYGK_TEST
username: SYSDBA
password: P@ssword25
slave: # 模拟从库,可根据自己需要修改 # 模拟从库,可根据自己需要修改
lazy: true # 开启懒加载,保证启动速度
#url: jdbc:dm://172.16.46.247:1050?schema=RUOYI-VUE-PRO
#username: SYSDBA
#password: pgbsci6ddJ6Sqj@e
url: jdbc:dm://172.17.11.98:20870?schema=JYGK_TEST
username: SYSDBA
password: P@ssword25
@@ -58,8 +52,9 @@ spring:
host: 172.16.46.63 # 地址
port: 30379 # 端口
database: 0 # 数据库索引
username: zt-redis # 密码,建议生产环境开启
username: zt-redis
password: P@ssword25
# password: 123456 # 密码,建议生产环境开启
xxl:
job:

View File

@@ -192,24 +192,4 @@
</dependency>
</dependencies>
<build>
<!-- 设置构建的 jar 包名 -->
<finalName>${project.artifactId}</finalName>
<plugins>
<!-- 打包 -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring.boot.version}</version>
<executions>
<execution>
<goals>
<goal>repackage</goal> <!-- 将引入的 jar 打入其中 -->
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@@ -42,6 +42,9 @@ public class ApiClientCredentialRespVO {
@Schema(description = "匿名访问固定用户昵称", example = "张三")
private String anonymousUserNickname;
@Schema(description = "是否启用加密", example = "true")
private Boolean enableEncryption;
@Schema(description = "创建时间")
private LocalDateTime createTime;

View File

@@ -45,4 +45,8 @@ public class ApiClientCredentialSaveReqVO {
@Schema(description = "匿名访问固定用户 ID", example = "1024")
private Long anonymousUserId;
@Schema(description = "是否启用加密", example = "true")
@NotNull(message = "启用加密标识不能为空")
private Boolean enableEncryption;
}

View File

@@ -38,4 +38,6 @@ public class ApiClientCredentialDO extends BaseDO {
private Long anonymousUserId;
private Boolean enableEncryption;
}

View File

@@ -108,7 +108,9 @@ public class GatewaySecurityFilter extends OncePerRequestFilter {
credential = credentialService.findActiveCredential(appId)
.orElseThrow(() -> new SecurityValidationException(HttpStatus.UNAUTHORIZED, "应用凭证不存在或已禁用"));
boolean allowAnonymous = Boolean.TRUE.equals(credential.getAllowAnonymous());
boolean enableEncryption = Boolean.TRUE.equals(credential.getEnableEncryption());
ApiAnonymousUserService.AnonymousUserDetails anonymousDetails = null;
byte[] requestBody = StreamUtils.copyToByteArray(request.getInputStream());
if (allowAnonymous) {
Long anonymousUserId = credential.getAnonymousUserId();
if (anonymousUserId == null) {
@@ -117,24 +119,25 @@ public class GatewaySecurityFilter extends OncePerRequestFilter {
anonymousDetails = anonymousUserService.find(anonymousUserId)
.orElseThrow(() -> new SecurityValidationException(HttpStatus.UNAUTHORIZED, "匿名访问固定用户不可用"));
}
String timestampHeader = requireHeader(request, TIMESTAMP_HEADER, "缺少时间戳");
// 校验时间戳与随机数,防止请求被重放
validateTimestamp(timestampHeader, security);
String nonce = requireHeader(request, NONCE_HEADER, "缺少随机数");
if (nonce.length() < 8) {
throw new SecurityValidationException(HttpStatus.BAD_REQUEST, "随机数长度不足");
}
String signature = requireHeader(request, SIGNATURE_HEADER, "缺少签名");
if (enableEncryption){
String nonce = requireHeader(request, NONCE_HEADER, "缺少随机数");
if (nonce.length() < 8) {
throw new SecurityValidationException(HttpStatus.BAD_REQUEST, "随机数长度不足");
}
String signature = requireHeader(request, SIGNATURE_HEADER, "缺少签名");
byte[] originalBody = StreamUtils.copyToByteArray(request.getInputStream());
// 尝试按凭证配置解密请求体,并构建签名载荷进行校验
byte[] decryptedBody = decryptRequestBody(originalBody, credential, security);
verifySignature(request, decryptedBody, signature, credential, security, appId, timestampHeader);
ensureNonce(tenantId, appId, nonce, security);
// 尝试按凭证配置解密请求体,并构建签名载荷进行校验
byte[] decryptedBody = decryptRequestBody(requestBody, credential, security);
verifySignature(request, decryptedBody, signature, credential, security, appId, timestampHeader);
ensureNonce(tenantId, appId, nonce, security);
requestBody = decryptedBody;
}
// 使用可重复读取的请求包装,供后续过滤器继续消费
CachedBodyHttpServletRequest securedRequest = new CachedBodyHttpServletRequest(request, decryptedBody);
CachedBodyHttpServletRequest securedRequest = new CachedBodyHttpServletRequest(request, requestBody);
securedRequest.setHeader(APP_ID_HEADER, credential.getAppId());
securedRequest.setHeader(HEADER_CREDENTIAL_ID, credential.getId() != null ? String.valueOf(credential.getId()) : null);
ApiGatewayAccessLogger.propagateLogIdHeader(securedRequest, accessLogId);
@@ -238,6 +241,11 @@ public class GatewaySecurityFilter extends OncePerRequestFilter {
private byte[] decryptRequestBody(byte[] originalBody,
ApiClientCredentialDO credential,
ApiGatewayProperties.Security security) {
// 检查是否启用加密,如果未启用则直接返回原文
if (credential != null && Boolean.FALSE.equals(credential.getEnableEncryption())) {
return originalBody != null ? originalBody : new byte[0];
}
if (originalBody == null || originalBody.length == 0) {
return new byte[0];
}
@@ -390,6 +398,11 @@ public class GatewaySecurityFilter extends OncePerRequestFilter {
private void encryptResponse(ContentCachingResponseWrapper responseWrapper,
ApiClientCredentialDO credential,
ApiGatewayProperties.Security security) throws IOException {
// 检查是否启用加密,如果未启用则直接返回,不加密响应
if (credential != null && Boolean.FALSE.equals(credential.getEnableEncryption())) {
return;
}
if (!security.isEncryptResponse()) {
return;
}
@@ -524,6 +537,10 @@ public class GatewaySecurityFilter extends OncePerRequestFilter {
if (security == null || credential == null) {
return false;
}
// 检查是否启用加密,如果未启用则不加密错误响应
if (Boolean.FALSE.equals(credential.getEnableEncryption())) {
return false;
}
if (!security.isEncryptResponse()) {
return false;
}

View File

@@ -46,9 +46,9 @@ public class HttpStepHandler implements ApiStepHandler {
private final WebClient.Builder webClientBuilder;
private final ExpressionExecutor expressionExecutor;
private static final Duration RETRY_DELAY = Duration.ofMillis(200);
private static final int RETRY_ATTEMPTS = 3;
private static final Duration DEFAULT_TIMEOUT = Duration.ofSeconds(20);
private static final Duration RETRY_DELAY = Duration.ofSeconds(5);
private static final int RETRY_ATTEMPTS = 5;
private static final Duration DEFAULT_TIMEOUT = Duration.ofSeconds(40);
private static final Set<String> DEFAULT_FORWARDED_HEADERS = Set.of(
"authorization",

View File

@@ -1,7 +1,5 @@
package com.zt.plat.module.databus.service.gateway.impl;
import com.github.benmanes.caffeine.cache.Caffeine;
import com.github.benmanes.caffeine.cache.LoadingCache;
import com.zt.plat.framework.common.exception.util.ServiceExceptionUtil;
import com.zt.plat.framework.common.pojo.PageResult;
import com.zt.plat.framework.common.util.object.BeanUtils;
@@ -11,14 +9,12 @@ import com.zt.plat.module.databus.dal.dataobject.gateway.ApiClientCredentialDO;
import com.zt.plat.module.databus.dal.mysql.gateway.ApiClientCredentialMapper;
import com.zt.plat.module.databus.service.gateway.ApiAnonymousUserService;
import com.zt.plat.module.databus.service.gateway.ApiClientCredentialService;
import jakarta.annotation.PostConstruct;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import java.time.Duration;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
@@ -36,16 +32,6 @@ public class ApiClientCredentialServiceImpl implements ApiClientCredentialServic
private final ApiClientCredentialMapper credentialMapper;
private final ApiAnonymousUserService anonymousUserService;
private LoadingCache<String, Optional<ApiClientCredentialDO>> credentialCache;
@PostConstruct
public void initCache() {
credentialCache = Caffeine.newBuilder()
.maximumSize(256)
.expireAfterWrite(Duration.ofMinutes(5))
.build(this::loadCredentialSync);
}
@Override
public PageResult<ApiClientCredentialDO> getPage(ApiClientCredentialPageReqVO reqVO) {
return credentialMapper.selectPage(reqVO);
@@ -67,7 +53,6 @@ public class ApiClientCredentialServiceImpl implements ApiClientCredentialServic
credential.setAnonymousUserId(null);
}
credentialMapper.insert(credential);
invalidateCache(credential.getAppId());
return credential.getId();
}
@@ -86,8 +71,6 @@ public class ApiClientCredentialServiceImpl implements ApiClientCredentialServic
updateObj.setAnonymousUserId(null);
}
credentialMapper.updateById(updateObj);
invalidateCache(existing.getAppId());
invalidateCache(updateObj.getAppId());
if (!Objects.equals(existing.getAnonymousUserId(), updateObj.getAnonymousUserId())) {
anonymousUserService.invalidate(existing.getAnonymousUserId());
anonymousUserService.invalidate(updateObj.getAnonymousUserId());
@@ -99,7 +82,6 @@ public class ApiClientCredentialServiceImpl implements ApiClientCredentialServic
public void delete(Long id) {
ApiClientCredentialDO existing = ensureExists(id);
credentialMapper.deleteById(id);
invalidateCache(existing.getAppId());
anonymousUserService.invalidate(existing.getAnonymousUserId());
}
@@ -118,11 +100,7 @@ public class ApiClientCredentialServiceImpl implements ApiClientCredentialServic
if (!StringUtils.hasText(appId)) {
return Optional.empty();
}
return credentialCache.get(appId.trim());
}
private Optional<ApiClientCredentialDO> loadCredentialSync(String appId) {
Optional<ApiClientCredentialDO> credential = credentialMapper.selectByAppId(appId)
Optional<ApiClientCredentialDO> credential = credentialMapper.selectByAppId(appId.trim())
.filter(item -> Boolean.TRUE.equals(item.getEnabled()));
if (credential.isEmpty()) {
log.debug("[API-PORTAL] 未找到 appId={} 的有效凭证", appId);
@@ -147,13 +125,6 @@ public class ApiClientCredentialServiceImpl implements ApiClientCredentialServic
return credential;
}
private void invalidateCache(String appId) {
if (!StringUtils.hasText(appId)) {
return;
}
credentialCache.invalidate(appId.trim());
}
private void normalizeAnonymousSettings(ApiClientCredentialSaveReqVO reqVO) {
if (Boolean.TRUE.equals(reqVO.getAllowAnonymous())) {
if (reqVO.getAnonymousUserId() == null) {

View File

@@ -11,6 +11,7 @@
<modules>
<module>zt-module-infra-api</module>
<module>zt-module-infra-server</module>
<module>zt-module-infra-server-app</module>
</modules>
<artifactId>zt-module-infra</artifactId>
<packaging>pom</packaging>

View File

@@ -34,4 +34,7 @@ public class FileRespDTO {
@Schema(description = "文件内容", requiredMode = Schema.RequiredMode.REQUIRED)
private byte[] content;
@Schema(description = "文件下载次数")
private Integer downloadCount;
}

View File

@@ -3,10 +3,10 @@
FROM 172.16.46.66:10043/base-service/eclipse-temurin:21-jre
## 创建目录,并使用它作为工作目录
RUN mkdir -p /zt-module-infra-server
WORKDIR /zt-module-infra-server
RUN mkdir -p /zt-module-infra-server-app
WORKDIR /zt-module-infra-server-app
## 将后端项目的 Jar 文件,复制到镜像中
COPY ./target/zt-module-infra-server.jar app.jar
COPY ./target/zt-module-infra-server-app.jar app.jar
## 设置 TZ 时区
## 设置 JAVA_OPTS 环境变量,可通过 docker run -e "JAVA_OPTS=" 进行覆盖

View File

@@ -0,0 +1,48 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>zt-module-infra</artifactId>
<groupId>com.zt.plat</groupId>
<version>${revision}</version>
</parent>
<artifactId>zt-module-infra-server-app</artifactId>
<packaging>jar</packaging>
<name>${project.artifactId}</name>
<description>
infra 模块启动器。
</description>
<dependencies>
<dependency>
<groupId>com.zt.plat</groupId>
<artifactId>zt-module-infra-server</artifactId>
<version>${revision}</version>
</dependency>
</dependencies>
<build>
<!-- 设置构建的 jar 包名 -->
<finalName>${project.artifactId}</finalName>
<plugins>
<!-- 打包 -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring.boot.version}</version>
<executions>
<execution>
<goals>
<goal>repackage</goal> <!-- 将引入的 jar 打入其中 -->
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@@ -149,24 +149,5 @@
</dependency>
</dependencies>
<build>
<!-- 设置构建的 jar 包名 -->
<finalName>${project.artifactId}</finalName>
<plugins>
<!-- 打包 -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring.boot.version}</version>
<executions>
<execution>
<goals>
<goal>repackage</goal> <!-- 将引入的 jar 打入其中 -->
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@@ -133,6 +133,10 @@ public class FileController {
response.setStatus(HttpStatus.NOT_FOUND.value());
return;
}
// 统计下载次数
fileService.incDownloadCount(configId,path);
writeAttachment(response, path, content);
}

View File

@@ -99,4 +99,7 @@ public class FileRespVO {
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime createTime;
@Schema(description = "下载次数")
private Integer downloadCount;
}

View File

@@ -65,6 +65,11 @@ public class FileDO extends BaseDO {
*/
private String aesIv;
/**
* 文件下载次数统计
*/
private Integer downloadCount;
/**
* 是否加密
* <p>

View File

@@ -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<FileDO> {
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);
}

View File

@@ -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);
}

View File

@@ -334,4 +334,9 @@ public class FileServiceImpl implements FileService {
}
}
@Override
public void incDownloadCount(Long configId, String path) {
fileMapper.incDownloadCount(configId, path);
}
}

View File

@@ -11,6 +11,7 @@
<modules>
<module>zt-module-report-api</module>
<module>zt-module-report-server</module>
<module>zt-module-report-server-app</module>
</modules>
<artifactId>zt-module-report</artifactId>
<packaging>pom</packaging>

View File

@@ -3,10 +3,10 @@
FROM 172.16.46.66:10043/base-service/eclipse-temurin:21-jre
## 创建目录,并使用它作为工作目录
RUN mkdir -p /zt-module-report-server
WORKDIR /zt-module-report-server
RUN mkdir -p /zt-module-report-server-app
WORKDIR /zt-module-report-server-app
## 将后端项目的 Jar 文件,复制到镜像中
COPY ./target/zt-module-report-server.jar app.jar
COPY ./target/zt-module-report-server-app.jar app.jar
## 设置 TZ 时区
## 设置 JAVA_OPTS 环境变量,可通过 docker run -e "JAVA_OPTS=" 进行覆盖

View File

@@ -0,0 +1,48 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>zt-module-report</artifactId>
<groupId>com.zt.plat</groupId>
<version>${revision}</version>
</parent>
<artifactId>zt-module-report-server-app</artifactId>
<packaging>jar</packaging>
<name>${project.artifactId}</name>
<description>
report 模块启动器。
</description>
<dependencies>
<dependency>
<groupId>com.zt.plat</groupId>
<artifactId>zt-module-report-server</artifactId>
<version>${revision}</version>
</dependency>
</dependencies>
<build>
<!-- 设置构建的 jar 包名 -->
<finalName>${project.artifactId}</finalName>
<plugins>
<!-- 打包 -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring.boot.version}</version>
<executions>
<execution>
<goals>
<goal>repackage</goal> <!-- 将引入的 jar 打入其中 -->
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@@ -111,23 +111,4 @@
</dependency>
</dependencies>
<build>
<!-- 设置构建的 jar 包名 -->
<finalName>${project.artifactId}</finalName>
<plugins>
<!-- 打包 -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring.boot.version}</version>
<executions>
<execution>
<goals>
<goal>repackage</goal> <!-- 将引入的 jar 打入其中 -->
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@@ -11,6 +11,7 @@
<modules>
<module>zt-module-system-api</module>
<module>zt-module-system-server</module>
<module>zt-module-system-server-app</module>
</modules>
<artifactId>zt-module-system</artifactId>
<packaging>pom</packaging>

View File

@@ -0,0 +1,58 @@
package com.zt.plat.module.system.api.dept.dto;
import com.zt.plat.framework.common.enums.CommonStatusEnum;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/**
* 公司部门推送消息 Response DTO
*
* @author ZT
*/
@Schema(description = "RPC 服务 - 部门推送消息 Response DTO")
@Data
public class DeptMsgRespDTO {
/**
* 主键编号
*/
private Long id;
/**
* 本系统部门 ID
*/
private Long deptId;
/**
* 外部系统标识
*/
private String systemCode;
/**
* 外部系统组织编码
*/
private String externalDeptCode;
/**
* 外部系统组织名称
*/
private String externalDeptName;
/**
* 映射状态
* 枚举 {@link CommonStatusEnum}
*/
private Integer status;
/**
* 备注
*/
private String remark;
/**
* 是否发送消息
*/
private Integer isSendMsg;
}

View File

@@ -2,23 +2,27 @@ package com.zt.plat.module.system.api.esp;
import com.zt.plat.framework.common.pojo.CommonResult;
import com.zt.plat.module.system.api.dept.dto.*;
import com.zt.plat.module.system.api.esp.dto.EspDto;
import com.zt.plat.module.system.enums.ApiConstants;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@FeignClient(name = ApiConstants.NAME)
@Tag(name = "RPC 服务 - 部门")
@Tag(name = "RPC 服务 - 部门推送消息")
public interface EspApi {
String PREFIX = ApiConstants.PREFIX + "/dept";
String PREFIX = ApiConstants.PREFIX + "/dept-esp";
@PostMapping(PREFIX + "/create")
@Operation(summary = "新增部门")
CommonResult<Long> createDept(@RequestBody DeptSaveReqDTO createReqVO);
@PostMapping(PREFIX + "/pushMsg")
@Operation(summary = "推送消息")
CommonResult<List<EspDto>> pushMsg(@RequestBody DeptSaveReqDTO syncReqDTO);
@Operation(summary = "查询部门消息")
CommonResult<List<DeptMsgRespDTO>> selectDepMsg(@RequestBody DeptSaveReqDTO syncReqDTO);
}

View File

@@ -0,0 +1,72 @@
package com.zt.plat.module.system.api.msg;
import com.zt.plat.framework.common.pojo.CommonResult;
import com.zt.plat.module.system.api.sms.dto.log.SmsLogRespDTO;
import com.zt.plat.module.system.api.sms.dto.send.SmsSendSingleToUserReqDTO;
import com.zt.plat.module.system.enums.ApiConstants;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
@FeignClient(name = ApiConstants.NAME)
@Tag(name = "RPC 服务 - 消息发送")
public interface MsgSendApi {
String PREFIX = ApiConstants.PREFIX + "/msg/send";
@PostMapping(PREFIX + "/sendTextMsg")
@Operation(summary = "发送企业微信文本消息", description = "在 mobile 为空时,使用 userId 加载对应 Admin 的手机号")
CommonResult<Long> sendTextMsg(@Valid @RequestBody SmsSendSingleToUserReqDTO reqDTO);
@PostMapping(PREFIX + "/sendImageMsg")
@Operation(summary = "发送企业微信图片消息", description = "在 mobile 为空时,使用 userId 加载对应 Member 的手机号")
CommonResult<Long> sendImageMsg(@Valid @RequestBody SmsSendSingleToUserReqDTO reqDTO);
@GetMapping(PREFIX + "/sendVoiceMsg")
@Operation(summary = "发送企业微信语音消息")
CommonResult<SmsLogRespDTO> getSmsLog(@RequestParam("id") Long id);
@PostMapping(PREFIX + "/sendVideoMsg")
@Operation(summary = "发送企业微信视频消息", description = "在 mobile 为空时,使用 userId 加载对应 Admin 的手机号")
CommonResult<Long> sendVideoMsg(@Valid @RequestBody SmsSendSingleToUserReqDTO reqDTO);
@PostMapping(PREFIX + "/sendFileMsg")
@Operation(summary = "发送企业微信文件消息", description = "在 mobile 为空时,使用 userId 加载对应 Member 的手机号")
CommonResult<Long> sendFileMsg(@Valid @RequestBody SmsSendSingleToUserReqDTO reqDTO);
@GetMapping(PREFIX + "/sendTextCardMsg")
@Operation(summary = "发送企业微信文本卡片消息")
CommonResult<SmsLogRespDTO> sendTextCardMsg(@RequestParam("id") Long id);
@PostMapping(PREFIX + "/sendTextCardMsgPich01")
@Operation(summary = "发送企业微信文本卡片消息 -物资存货智能管理 预警信息", description = "在 mobile 为空时,使用 userId 加载对应 Admin 的手机号")
CommonResult<Long> sendTextCardMsgPich01(@Valid @RequestBody SmsSendSingleToUserReqDTO reqDTO);
@PostMapping(PREFIX + "/sendNewsMsg")
@Operation(summary = "发送企业微信图文消息", description = "在 mobile 为空时,使用 userId 加载对应 Member 的手机号")
CommonResult<Long> sendNewsMsg(@Valid @RequestBody SmsSendSingleToUserReqDTO reqDTO);
@GetMapping(PREFIX + "/sendMpNewsMsg")
@Operation(summary = "发送企业微信图文消息mpnews")
CommonResult<SmsLogRespDTO> sendMpNewsMsg(@RequestParam("id") Long id);
@PostMapping(PREFIX + "/sendMarkdownMsg")
@Operation(summary = "发送企业微信小程序通知消息", description = "在 mobile 为空时,使用 userId 加载对应 Admin 的手机号")
CommonResult<Long> sendMarkdownMsg(@Valid @RequestBody SmsSendSingleToUserReqDTO reqDTO);
@PostMapping(PREFIX + "/sendMiniProgramNoticeMsg")
@Operation(summary = "发送企业微信图片消息", description = "在 mobile 为空时,使用 userId 加载对应 Member 的手机号")
CommonResult<Long> sendMiniProgramNoticeMsg(@Valid @RequestBody SmsSendSingleToUserReqDTO reqDTO);
@GetMapping(PREFIX + "/sendInteractiveTaskCardMsg")
@Operation(summary = "发送企业微信任务卡片消息")
CommonResult<SmsLogRespDTO> sendInteractiveTaskCardMsg(@RequestParam("id") Long id);
}

View File

@@ -0,0 +1,44 @@
package com.zt.plat.module.system.api.sms.dto.code;
import lombok.Data;
import lombok.experimental.Accessors;
import java.io.Serializable;
@Data
@Accessors(chain = true)
public class User implements Serializable {
/**
* 返回码
*/
private Integer errcode;
/**
* 对返回码的文本描述内容
*/
private String errmsg;
/**
* 成员UserID
*/
private String UserId;
/**
* 手机设备号(由中铝集团在安装时随机生成,删除重装会改变,升级不受影响)
*/
private String DeviceId;
/**
* 成员身份信息2超级管理员, 4:分级管理员5普通成员
*/
private Integer usertype;
/**
* 判断受否授权成功
*
* @return true-授权成功、false-授权失败
*/
public boolean isAuthorized() {
return this.getErrcode() == 0;
}
}

View File

@@ -4,7 +4,6 @@ import com.zt.plat.framework.common.validation.Mobile;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotEmpty;
import lombok.Data;
import java.util.Map;
@Schema(description = "RPC 服务 - 短信发送给 Admin 或者 Member 用户 Request DTO")

View File

@@ -4,6 +4,7 @@ import com.fhs.core.trans.vo.VO;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Set;
@@ -20,6 +21,12 @@ public class AdminUserRespDTO implements VO {
@Schema(description = "用户昵称", requiredMode = Schema.RequiredMode.REQUIRED, example = "小王")
private String nickname;
@Schema(description = "工号", example = "A00123")
private String workcode;
@Schema(description = "备注", example = "我是一个用户")
private String remark;
@Schema(description = "租户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Long tenantId;

View File

@@ -11,7 +11,6 @@ public class ApiConstants {
/**
* 服务名
*
* 注意,需要保证和 spring.application.name 保持一致
*/
public static final String NAME = "system-server";

View File

@@ -108,6 +108,9 @@ public interface ErrorCodeConstants {
ErrorCode SMS_CHANNEL_DISABLE = new ErrorCode(1_002_011_001, "短信渠道不处于开启状态,不允许选择");
ErrorCode SMS_CHANNEL_HAS_CHILDREN = new ErrorCode(1_002_011_002, "无法删除,该短信渠道还有短信模板");
ErrorCode SMS_CHANNEL_BALANCE_UNSUPPORTED = new ErrorCode(1_002_011_003, "该短信渠道不支持余额查询");
ErrorCode MSG_CHANNEL_NOT_EXISTS = new ErrorCode(1_002_011_004, "消息渠道不存在");
// ========== 短信模板 1-002-012-000 ==========
ErrorCode SMS_TEMPLATE_NOT_EXISTS = new ErrorCode(1_002_012_000, "短信模板不存在");
@@ -122,6 +125,7 @@ public interface ErrorCodeConstants {
ErrorCode SMS_SEND_MOBILE_TEMPLATE_PARAM_MISS = new ErrorCode(1_002_013_001, "模板参数({})缺失");
ErrorCode SMS_SEND_TEMPLATE_NOT_EXISTS = new ErrorCode(1_002_013_002, "短信模板不存在");
ErrorCode SMS_CALLBACK_SIGN_INVALID = new ErrorCode(1_002_013_100, "短信回调签名校验失败");
ErrorCode MSG_CALLBACK_SIGN_INVALID = new ErrorCode(1_002_013_101, "消息回调签名校验失败");
// ========== 短信验证码 1-002-014-000 ==========
ErrorCode SMS_CODE_NOT_FOUND = new ErrorCode(1_002_014_000, "验证码不存在");
@@ -206,6 +210,8 @@ public interface ErrorCodeConstants {
// ========== 用户与部门关系 1-002-029-000 ==========
ErrorCode USER_DEPT_NOT_EXISTS = new ErrorCode(1_002_029_000, "用户与部门关系不存在");
ErrorCode USER_DEPT_SAVE_EXISTS = new ErrorCode(1_002_029_001, "插入用户部门失败");
// ========== 系统序列号分段明细 1-002-030-000 ==========
ErrorCode SEQUENCE_DETAIL_NOT_EXISTS = new ErrorCode(1_002_030_000, "系统序列号分段明细不存在");

View File

@@ -3,10 +3,10 @@
FROM 172.16.46.66:10043/base-service/eclipse-temurin:21-jre
## 创建目录,并使用它作为工作目录
RUN mkdir -p /zt-module-system-server
WORKDIR /zt-module-system-server
RUN mkdir -p /zt-module-system-server-app
WORKDIR /zt-module-system-server-app
## 将后端项目的 Jar 文件,复制到镜像中
COPY ./target/zt-module-system-server.jar app.jar
COPY ./target/zt-module-system-server-app.jar app.jar
## 设置 TZ 时区
## 设置 JAVA_OPTS 环境变量,可通过 docker run -e "JAVA_OPTS=" 进行覆盖

View File

@@ -0,0 +1,48 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>zt-module-system</artifactId>
<groupId>com.zt.plat</groupId>
<version>${revision}</version>
</parent>
<artifactId>zt-module-system-server-app</artifactId>
<packaging>jar</packaging>
<name>${project.artifactId}</name>
<description>
system 模块启动器。
</description>
<dependencies>
<dependency>
<groupId>com.zt.plat</groupId>
<artifactId>zt-module-system-server</artifactId>
<version>${revision}</version>
</dependency>
</dependencies>
<build>
<!-- 设置构建的 jar 包名 -->
<finalName>${project.artifactId}</finalName>
<plugins>
<!-- 打包 -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring.boot.version}</version>
<executions>
<execution>
<goals>
<goal>repackage</goal> <!-- 将引入的 jar 打入其中 -->
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@@ -103,4 +103,8 @@
</root>
</springProfile>
<!-- <logger name="com.zt.plat.module.system.dal" level="DEBUG" additivity="false">-->
<!-- <appender-ref ref="STDOUT"/>-->
<!-- </logger>-->
</configuration>

View File

@@ -200,26 +200,14 @@
<artifactId>hutool-all</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-text</artifactId>
<version>1.13.1</version>
<scope>compile</scope>
</dependency>
</dependencies>
<build>
<!-- 设置构建的 jar 包名 -->
<finalName>${project.artifactId}</finalName>
<plugins>
<!-- 打包 -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring.boot.version}</version>
<executions>
<execution>
<goals>
<goal>repackage</goal> <!-- 将引入的 jar 打入其中 -->
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@@ -41,7 +41,7 @@ public class DatabusDeptProviderApiImpl implements DatabusDeptProviderApi {
public CommonResult<CursorPageResult<DatabusDeptData>> getPageByCursor(CursorPageReqDTO reqDTO) {
// 构建游标查询条件
LambdaQueryWrapper<DeptDO> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(DeptDO::getDeptSource, 3);
// 游标条件create_time > cursorTime OR (create_time = cursorTime AND id > cursorId)
if (!reqDTO.isFirstPage()) {
queryWrapper.and(w -> w
@@ -105,6 +105,7 @@ public class DatabusDeptProviderApiImpl implements DatabusDeptProviderApi {
Long total = null;
if (reqDTO.isFirstPage()) {
LambdaQueryWrapper<DeptDO> countWrapper = new LambdaQueryWrapper<>();
countWrapper.eq(DeptDO::getDeptSource, 3);
if (reqDTO.getTenantId() != null) {
countWrapper.eq(DeptDO::getTenantId, reqDTO.getTenantId());
}
@@ -175,6 +176,8 @@ public class DatabusDeptProviderApiImpl implements DatabusDeptProviderApi {
@Override
public CommonResult<Long> count(Long tenantId) {
LambdaQueryWrapper<DeptDO> queryWrapper = new LambdaQueryWrapper<>();
// ⚠️ 只统计 userSource = 3 的用户
queryWrapper.eq(DeptDO::getDeptSource, 3);
if (tenantId != null) {
queryWrapper.eq(DeptDO::getTenantId, tenantId);
}

View File

@@ -54,8 +54,8 @@ public class DatabusUserProviderApiImpl implements DatabusUserProviderApi {
// 构建游标查询条件
LambdaQueryWrapper<AdminUserDO> queryWrapper = new LambdaQueryWrapper<>();
// ⚠️ 只同步 userSource = 2 的用户
queryWrapper.eq(AdminUserDO::getUserSource, 2);
// ⚠️ 只同步 userSource = 3 的用户
queryWrapper.eq(AdminUserDO::getUserSource, 3);
// 游标条件create_time > cursorTime OR (create_time = cursorTime AND id > cursorId)
if (!reqDTO.isFirstPage()) {
@@ -103,8 +103,8 @@ public class DatabusUserProviderApiImpl implements DatabusUserProviderApi {
Long total = null;
if (reqDTO.isFirstPage()) {
LambdaQueryWrapper<AdminUserDO> countWrapper = new LambdaQueryWrapper<>();
// ⚠️ 只统计 userSource = 2 的用户
countWrapper.eq(AdminUserDO::getUserSource, 2);
// ⚠️ 只统计 userSource = 3 的用户
countWrapper.eq(AdminUserDO::getUserSource, 3);
if (reqDTO.getTenantId() != null) {
countWrapper.eq(AdminUserDO::getTenantId, reqDTO.getTenantId());
}
@@ -148,8 +148,8 @@ public class DatabusUserProviderApiImpl implements DatabusUserProviderApi {
@Override
public CommonResult<Long> count(Long tenantId) {
LambdaQueryWrapper<AdminUserDO> queryWrapper = new LambdaQueryWrapper<>();
// ⚠️ 只统计 userSource = 2 的用户
queryWrapper.eq(AdminUserDO::getUserSource, 2);
// ⚠️ 只统计 userSource = 3 的用户
queryWrapper.eq(AdminUserDO::getUserSource, 3);
if (tenantId != null) {
queryWrapper.eq(AdminUserDO::getTenantId, tenantId);
}

View File

@@ -2,15 +2,17 @@ package com.zt.plat.module.system.api.esp;
import com.zt.plat.framework.common.exception.enums.GlobalErrorCodeConstants;
import com.zt.plat.framework.common.pojo.CommonResult;
import com.zt.plat.framework.common.util.object.ObjectUtils;
import com.zt.plat.framework.common.util.object.BeanUtils;
import com.zt.plat.module.system.api.dept.dto.DeptMsgRespDTO;
import com.zt.plat.module.system.api.dept.dto.DeptSaveReqDTO;
import com.zt.plat.module.system.api.esp.dto.EspDto;
import com.zt.plat.module.system.controller.admin.dept.vo.dept.DeptSaveReqVO;
import com.zt.plat.module.system.service.dept.IEspService;
import jakarta.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import java.util.Objects;
import static com.zt.plat.framework.common.pojo.CommonResult.success;
@RestController
@Validated
@@ -18,16 +20,26 @@ public class EspApiImpl implements EspApi {
@Resource
private IEspService deptService;
private IEspService espService;
@Override
public CommonResult<List<EspDto>> pushMsg(DeptSaveReqDTO syncReqDTO)
public CommonResult<Long> createDept(DeptSaveReqDTO createReqVO) {
DeptSaveReqVO reqVO = BeanUtils.toBean(createReqVO, DeptSaveReqVO.class);
Long deptId = espService.createDept(reqVO);
return success(deptId);
}
@Override
public CommonResult<List<DeptMsgRespDTO>> selectDepMsg(DeptSaveReqDTO syncReqDTO)
{
if(Objects.isNull(syncReqDTO) || null == syncReqDTO.getId())
{
return CommonResult.error(GlobalErrorCodeConstants.BAD_REQUEST.getCode(),
"ID不能为空");
}
return CommonResult.success(deptService.pushMsg(syncReqDTO));
return espService.selectDepMsg(syncReqDTO);
}
}

View File

@@ -0,0 +1,84 @@
package com.zt.plat.module.system.api.msg;
import com.zt.plat.framework.common.pojo.CommonResult;
import com.zt.plat.framework.common.util.object.BeanUtils;
import com.zt.plat.module.system.api.sms.dto.log.SmsLogRespDTO;
import com.zt.plat.module.system.api.sms.dto.send.SmsSendSingleToUserReqDTO;
import com.zt.plat.module.system.service.sms.SmsLogService;
import com.zt.plat.module.system.service.sms.SmsSendService;
import jakarta.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RestController;
import static com.zt.plat.framework.common.pojo.CommonResult.success;
@RestController
@Validated
public class MsgSendApiImpl implements MsgSendApi {
@Resource
private SmsSendService smsSendService;
@Resource
private SmsLogService smsLogService;
@Override
public CommonResult<Long> sendTextMsg(SmsSendSingleToUserReqDTO reqDTO) {
return null;
}
@Override
public CommonResult<Long> sendImageMsg(SmsSendSingleToUserReqDTO reqDTO) {
return null;
}
@Override
public CommonResult<SmsLogRespDTO> getSmsLog(Long id) {
return success(BeanUtils.toBean(smsLogService.getSmsLog(id), SmsLogRespDTO.class));
}
@Override
public CommonResult<Long> sendVideoMsg(SmsSendSingleToUserReqDTO reqDTO) {
return null;
}
@Override
public CommonResult<Long> sendFileMsg(SmsSendSingleToUserReqDTO reqDTO) {
return null;
}
@Override
public CommonResult<SmsLogRespDTO> sendTextCardMsg(Long id) {
return null;
}
@Override
public CommonResult<Long> sendTextCardMsgPich01(SmsSendSingleToUserReqDTO reqDTO) {
return null;
}
@Override
public CommonResult<Long> sendNewsMsg(SmsSendSingleToUserReqDTO reqDTO) {
return null;
}
@Override
public CommonResult<SmsLogRespDTO> sendMpNewsMsg(Long id) {
return null;
}
@Override
public CommonResult<Long> sendMarkdownMsg(SmsSendSingleToUserReqDTO reqDTO) {
return null;
}
@Override
public CommonResult<Long> sendMiniProgramNoticeMsg(SmsSendSingleToUserReqDTO reqDTO) {
return null;
}
@Override
public CommonResult<SmsLogRespDTO> sendInteractiveTaskCardMsg(Long id) {
return null;
}
}

View File

@@ -12,6 +12,7 @@ import com.zt.plat.module.system.controller.admin.auth.vo.*;
import com.zt.plat.module.system.convert.auth.AuthConvert;
import com.zt.plat.module.system.dal.dataobject.permission.MenuDO;
import com.zt.plat.module.system.dal.dataobject.permission.RoleDO;
import com.zt.plat.module.system.dal.dataobject.permission.RoleMenuDO;
import com.zt.plat.module.system.dal.dataobject.user.AdminUserDO;
import com.zt.plat.module.system.enums.logger.LoginLogTypeEnum;
import com.zt.plat.module.system.service.auth.AdminAuthService;
@@ -33,7 +34,9 @@ import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import static com.zt.plat.framework.common.pojo.CommonResult.success;
@@ -126,7 +129,18 @@ public class AuthController {
// 1.3 获得菜单列表
Set<Long> menuIds = permissionService.getRoleMenuListByRoleId(convertSet(roles, RoleDO::getId));
List<MenuDO> menuList = menuService.getMenuList(menuIds);
Set<RoleMenuDO> roleMenuList = permissionService.getByRoleIdAndMenuIds(roleIds, menuIds);
Map<Long, RoleMenuDO> roleMenuMap = new HashMap<>(roleMenuList.size());
for (RoleMenuDO roleMenu : roleMenuList) {
roleMenuMap.put(roleMenu.getMenuId(), roleMenu);
}
menuList = menuService.filterDisableMenus(menuList);
for (MenuDO menu : menuList) {
RoleMenuDO roleMenu = roleMenuMap.get(menu.getId());
if (roleMenu != null && roleMenu.getShowMenu() != null && !roleMenu.getShowMenu()) {
menu.setVisible(false);
}
}
// 2. 拼接结果返回
return success(AuthConvert.INSTANCE.convert(user, roles, menuList));

View File

@@ -123,7 +123,7 @@ public class DeptController {
@GetMapping("/top-level-list")
@Operation(summary = "获取当前用户可访问的顶级部门列表", description = "用于懒加载,返回当前用户所属部门的最顶层祖先部门,如果用户没有关联任何部门则返回空列表")
@PreAuthorize("@ss.hasPermission('system:dept:query')")
// @PreAuthorize("@ss.hasPermission('system:dept:query')")
public CommonResult<List<DeptRespVO>> getTopLevelDeptList() {
List<DeptDO> list = deptService.getTopLevelDeptList();
return success(BeanUtils.toBean(list, DeptRespVO.class));

View File

@@ -6,11 +6,13 @@ import com.zt.plat.framework.common.enums.CommonStatusEnum;
import com.zt.plat.framework.common.pojo.CommonResult;
import com.zt.plat.framework.common.util.collection.CollectionUtils;
import com.zt.plat.module.system.controller.admin.permission.vo.permission.PermissionAssignRoleDataScopeReqVO;
import com.zt.plat.module.system.controller.admin.permission.vo.permission.PermissionAssignRoleMenuItemReqVO;
import com.zt.plat.module.system.controller.admin.permission.vo.permission.PermissionAssignRoleMenuReqVO;
import com.zt.plat.module.system.controller.admin.permission.vo.permission.PermissionAssignUserRoleReqVO;
import com.zt.plat.module.system.controller.admin.permission.vo.permission.PermissionUserSupervisionRespVO;
import com.zt.plat.module.system.dal.dataobject.permission.MenuDO;
import com.zt.plat.module.system.dal.dataobject.permission.RoleDO;
import com.zt.plat.module.system.dal.dataobject.permission.RoleMenuDO;
import com.zt.plat.module.system.dal.dataobject.user.AdminUserDO;
import com.zt.plat.module.system.enums.permission.MenuTypeEnum;
import com.zt.plat.module.system.service.permission.MenuService;
@@ -57,8 +59,16 @@ public class PermissionController {
@Parameter(name = "roleId", description = "角色编号", required = true)
@GetMapping("/list-role-menus")
@PreAuthorize("@ss.hasPermission('system:permission:assign-role-menu')")
public CommonResult<Set<Long>> getRoleMenuList(Long roleId) {
return success(permissionService.getRoleMenuListByRoleId(roleId));
public CommonResult<Set<PermissionAssignRoleMenuItemReqVO>> getRoleMenuList(Long roleId) {
Set<Long> menuIds = permissionService.getRoleMenuListByRoleId(roleId);
Set<RoleMenuDO> menuList = permissionService.getByRoleIdAndMenuIds(Collections.singleton(roleId), menuIds);
Set<PermissionAssignRoleMenuItemReqVO> result = menuList.stream().map(menu -> {
PermissionAssignRoleMenuItemReqVO reqVO = new PermissionAssignRoleMenuItemReqVO();
reqVO.setId(menu.getMenuId());
reqVO.setShowMenu(menu.getShowMenu());
return reqVO;
}).collect(Collectors.toSet());
return success(result);
}
@PostMapping("/assign-role-menu")
@@ -66,10 +76,13 @@ public class PermissionController {
@PreAuthorize("@ss.hasPermission('system:permission:assign-role-menu')")
public CommonResult<Boolean> assignRoleMenu(@Validated @RequestBody PermissionAssignRoleMenuReqVO reqVO) {
// 开启多租户的情况下,需要过滤掉未开通的菜单
tenantService.handleTenantMenu(menuIds -> reqVO.getMenuIds().removeIf(menuId -> !CollUtil.contains(menuIds, menuId)));
tenantService.handleTenantMenu(menuIds -> reqVO.getMenus().removeIf(menu -> !CollUtil.contains(menuIds, menu.getId())));
// 执行菜单的分配
permissionService.assignRoleMenu(reqVO.getRoleId(), reqVO.getMenuIds());
permissionService.assignRoleMenu(reqVO.getRoleId(), reqVO.getMenus().stream().map(PermissionAssignRoleMenuItemReqVO::getId).collect(Collectors.toSet()));
// 更新菜单的显示状态
permissionService.updateMenuDisplay(reqVO.getRoleId(), reqVO.getMenus());
return success(true);
}

View File

@@ -0,0 +1,22 @@
package com.zt.plat.module.system.controller.admin.permission.vo.permission;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
@Schema(description = "管理后台 - 赋予角色菜单--菜单列表 Request VO")
@Data
public class PermissionAssignRoleMenuItemReqVO {
@Schema(description = "菜单ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "菜单ID不能为空")
private Long id;
@Schema(description = "是否显示菜单,默认显示(true)")
private Boolean showMenu = true;
@Schema(description = "是否显示菜单按钮是否点击过(避免大量更新数据,只更新点击过的)")
private Boolean showMenuChanged = false;
}

View File

@@ -15,7 +15,7 @@ public class PermissionAssignRoleMenuReqVO {
@NotNull(message = "角色编号不能为空")
private Long roleId;
@Schema(description = "菜单编列表", example = "1,3,5")
private Set<Long> menuIds = Collections.emptySet(); // 兜底
@Schema(description = "菜单编列表")
private Set<PermissionAssignRoleMenuItemReqVO> menus = Collections.emptySet(); // 兜底
}

View File

@@ -0,0 +1,18 @@
package com.zt.plat.module.system.controller.admin.sms;
import com.zt.plat.module.system.service.sms.SmsSendService;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@Tag(name = "管理后台 - 消息回调")
@RestController
@RequestMapping("/system/sms/callback")
public class MsgCallBackController {
@Resource
private SmsSendService smsSendService;
}

View File

@@ -15,6 +15,7 @@ import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
import static com.zt.plat.framework.common.pojo.CommonResult.success;
@Tag(name = "管理后台 - 短信回调")
@@ -73,4 +74,13 @@ public class SmsCallbackController {
return success(true);
}
@PostMapping("/zle")
@PermitAll
@TenantIgnore
@Operation(summary = "中铝e办短信的回调")
public CommonResult<Boolean> receiveZleSmsStatus(@RequestBody String requestBody) throws Throwable {
smsSendService.receiveSmsStatus(SmsChannelEnum.ZLE.getCode(), requestBody);
return success(true);
}
}

View File

@@ -6,11 +6,10 @@ import com.zt.plat.framework.common.pojo.PageParam;
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.sms.vo.template.SmsTemplatePageReqVO;
import com.zt.plat.module.system.controller.admin.sms.vo.template.SmsTemplateRespVO;
import com.zt.plat.module.system.controller.admin.sms.vo.template.SmsTemplateSaveReqVO;
import com.zt.plat.module.system.controller.admin.sms.vo.template.SmsTemplateSendReqVO;
import com.zt.plat.module.system.controller.admin.sms.vo.msg.TextMessage;
import com.zt.plat.module.system.controller.admin.sms.vo.template.*;
import com.zt.plat.module.system.dal.dataobject.sms.SmsTemplateDO;
import com.zt.plat.module.system.service.msg.ISendMsgService;
import com.zt.plat.module.system.service.sms.SmsSendService;
import com.zt.plat.module.system.service.sms.SmsTemplateService;
import io.swagger.v3.oas.annotations.Operation;
@@ -19,13 +18,13 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.Valid;
import org.apache.commons.lang3.StringUtils;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import java.io.IOException;
import java.util.List;
import static com.zt.plat.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
import static com.zt.plat.framework.common.exception.enums.GlobalErrorCodeConstants.BAD_REQUEST;
import static com.zt.plat.framework.common.pojo.CommonResult.success;
@Tag(name = "管理后台 - 短信模板")
@@ -37,6 +36,8 @@ public class SmsTemplateController {
private SmsTemplateService smsTemplateService;
@Resource
private SmsSendService smsSendService;
@Resource
private ISendMsgService sendMsgService;
@PostMapping("/create")
@Operation(summary = "创建短信模板")
@@ -100,4 +101,18 @@ public class SmsTemplateController {
sendReqVO.getTemplateCode(), sendReqVO.getTemplateParams()));
}
@PostMapping("/send-msg")
@Operation(summary = "发送消息")
@PreAuthorize("@ss.hasPermission('system:sms-template:send-msg')")
public CommonResult<Object> sendMsg(@Valid @RequestBody MsgTemplateSendReqVO sendReqVO,TextMessage textMessage) throws Exception{
String msgtype = textMessage.getMsgtype();
if (StringUtils.isBlank(msgtype)){
return CommonResult.error(BAD_REQUEST.getCode(), String.format("请求参数缺失:%s",msgtype));
}
//发送消息到MQ
CommonResult<Object> objectCommonResult = sendMsgService.sendTextMsg(sendReqVO,textMessage);
return success(objectCommonResult);
}
}

View File

@@ -0,0 +1,48 @@
package com.zt.plat.module.system.controller.admin.sms.vo.msg;
import lombok.Data;
import lombok.experimental.Accessors;
import java.io.Serializable;
/**
* 企业微信消息发送对象父类
*
* @author dongqiang.hao
*/
@Data
@Accessors(chain = true)
public class BaseMessage implements Serializable {
/**
* 指定接收消息的成员成员ID列表多个接收者用|分隔最多支持1000个。特殊情况指定为”@all”则向该企业应用的全部成员发送
*/
private String touser;
/**
* 指定接收消息的部门部门ID列表多个接收者用|分隔最多支持100个。当touser为”@all”时忽略本参数
*/
private String toparty;
/**
* 指定接收消息的标签标签ID列表多个接收者用|分隔最多支持100个。当touser为”@all”时忽略本参数
*/
private String totag;
/**
* 企业应用的id整型。企业内部开发可在应用的设置页面查看第三方服务商可通过接口 获取企业授权信息 获取该参数值
*/
private String agentid;
/**
* 消息类型
*/
private String msgtype;
/**
* 发送消息的自建应用类型
*/
private String appType;
/**
* 表示是否开启重复消息检查0表示否1表示是默认0
*/
private Integer enable_duplicate_check = 0;
/**
* 表示是否重复消息检查的时间间隔默认1800s最大不超过4小时
*/
private Integer duplicate_check_interval;
}

View File

@@ -0,0 +1,34 @@
package com.zt.plat.module.system.controller.admin.sms.vo.msg;
import lombok.Data;
import java.io.Serializable;
/**
* 任务卡片消息按钮对象
*
* @author luzemin
*/
@Data
public class Btn implements Serializable {
/**
* 按钮key值用户点击后会产生任务卡片回调事件回调事件会带上该key值只能由数字、字母和“_-@”组成最长支持128字节
*/
private String key;
/**
* 按钮名称最长支持18个字节超过则截断
*/
private String name;
/**
* 按钮字体颜色可选“red”或者“blue”,默认为“blue”
*/
private String color;
/**
* 按钮字体是否加粗默认false
*/
private Boolean is_bold;
}

View File

@@ -0,0 +1,22 @@
package com.zt.plat.module.system.controller.admin.sms.vo.msg;
import lombok.Data;
import java.io.Serializable;
/**
* 小程序通知消息内容元素对象
*
* @author luzemin
*/
@Data
public class ContentItem implements Serializable {
/**
* 元素对象键值,长度10个汉字以内
*/
private String key;
/**
* 元素对象值,长度30个汉字以内支持id转译
*/
private String value;
}

View File

@@ -0,0 +1,30 @@
package com.zt.plat.module.system.controller.admin.sms.vo.msg;
import com.zt.plat.module.system.framework.sms.core.enums.WxMsgTypeConstant;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
/**
* 企业微信文件消息发送对象
*
* @author luzemin
*/
@Data
@EqualsAndHashCode(callSuper = true)
@Accessors(chain = true)
public class FileMessage extends BaseMessage {
/**
* 消息类型此时固定为file
*/
private final String msgtype = WxMsgTypeConstant.FILE.getCode();
/**
* 企业微信文件消息体对象
*/
private Media file = new Media();
/**
* 表示是否是保密消息0表示可对外分享1表示不能分享且内容显示水印默认为0
*/
private Integer safe = 0;
}

Some files were not shown because too many files have changed in this diff Show More