#340 人员管理接口功能开发/优化

Закрыто
fanghuisheng хочет смерджить 270 коммит(ов) из uskycloud/fhs в uskycloud/system-165
100 измененных файлов с 4855 добавлено и 1079 удалено
  1. 1 1
      base-common/ruoyi-common-datascope/src/main/java/com/ruoyi/common/datascope/aspect/DataScopeAspect.java
  2. 11 0
      base-components/monitor/pom.xml
  3. 67 0
      base-components/monitor/src/main/java/com/ruoyi/modules/monitor/notify/DingTalkNotifier.java
  4. 100 0
      base-components/monitor/src/main/java/com/ruoyi/modules/monitor/notify/ServiceChangeNotifier.java
  5. 41 11
      base-modules/service-file/pom.xml
  6. 42 5
      base-modules/service-file/src/main/java/com/ruoyi/file/RuoYiFileApplication.java
  7. 82 82
      base-modules/service-file/src/main/java/com/ruoyi/file/config/MinioConfig.java
  8. 16 0
      base-modules/service-file/src/main/java/com/ruoyi/file/config/MybatisPlusConfig.java
  9. 2 2
      base-modules/service-file/src/main/java/com/ruoyi/file/config/ResourcesConfig.java
  10. 19 0
      base-modules/service-file/src/main/java/com/ruoyi/file/config/WebConfig.java
  11. 127 0
      base-modules/service-file/src/main/java/com/ruoyi/file/controller/FileUpdateInfoController.java
  12. 156 0
      base-modules/service-file/src/main/java/com/ruoyi/file/controller/FilesController.java
  13. 47 47
      base-modules/service-file/src/main/java/com/ruoyi/file/controller/SysFileController.java
  14. 82 0
      base-modules/service-file/src/main/java/com/ruoyi/file/domain/FileUpdateInfo.java
  15. 14 0
      base-modules/service-file/src/main/java/com/ruoyi/file/domain/FileWithId.java
  16. 50 0
      base-modules/service-file/src/main/java/com/ruoyi/file/domain/FilesUpload.java
  17. 9 0
      base-modules/service-file/src/main/java/com/ruoyi/file/mapper/FileUpdateInfoMapper.java
  18. 10 0
      base-modules/service-file/src/main/java/com/ruoyi/file/mapper/FilesMapper.java
  19. 42 42
      base-modules/service-file/src/main/java/com/ruoyi/file/service/FastDfsSysFileServiceImpl.java
  20. 50 0
      base-modules/service-file/src/main/java/com/ruoyi/file/service/FileUpdateInfoService.java
  21. 30 0
      base-modules/service-file/src/main/java/com/ruoyi/file/service/FileUploadResponse.java
  22. 19 0
      base-modules/service-file/src/main/java/com/ruoyi/file/service/FilesService.java
  23. 20 20
      base-modules/service-file/src/main/java/com/ruoyi/file/service/ISysFileService.java
  24. 50 50
      base-modules/service-file/src/main/java/com/ruoyi/file/service/LocalSysFileServiceImpl.java
  25. 416 0
      base-modules/service-file/src/main/java/com/ruoyi/file/service/impl/FileUpdateInfoServiceImpl.java
  26. 241 0
      base-modules/service-file/src/main/java/com/ruoyi/file/service/impl/FilesServiceImpl.java
  27. 202 202
      base-modules/service-file/src/main/java/com/ruoyi/file/utils/FileUploadUtils.java
  28. 1 1
      base-modules/service-file/src/main/resources/bootstrap.yml
  29. 5 0
      base-modules/service-file/src/main/resources/mapper/file/FilesMapper.xml
  30. 1 0
      base-modules/service-job/src/main/resources/mapper/job/SysJobMapper.xml
  31. 17 4
      base-modules/service-system/service-system-api/src/main/java/com/usky/system/RemoteMceService.java
  32. 125 0
      base-modules/service-system/service-system-api/src/main/java/com/usky/system/domain/MceRequestVO.java
  33. 7 0
      base-modules/service-system/service-system-api/src/main/java/com/usky/system/domain/SysOperLogVO.java
  34. 25 0
      base-modules/service-system/service-system-api/src/main/java/com/usky/system/domain/SysPerson.java
  35. 24 0
      base-modules/service-system/service-system-api/src/main/java/com/usky/system/domain/SysPersonVo.java
  36. 13 0
      base-modules/service-system/service-system-api/src/main/java/com/usky/system/domain/SysUserVO.java
  37. 12 10
      base-modules/service-system/service-system-api/src/main/java/com/usky/system/factory/RemoteMceFallbackFactory.java
  38. 15 3
      base-modules/service-system/service-system-biz/pom.xml
  39. 2 0
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/RuoYiSystemApplication.java
  40. 8 1
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/constant/constant.java
  41. 8 1
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/controller/api/SysMceControllerApi.java
  42. 1 1
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/controller/web/AuthorityConfigController.java
  43. 52 19
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/controller/web/MceReceiveController.java
  44. 12 2
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/controller/web/SendSmsController.java
  45. 9 2
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/controller/web/SysDeptController.java
  46. 3 1
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/controller/web/SysMenuController.java
  47. 226 4
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/controller/web/SysPersonController.java
  48. 38 28
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/controller/web/SysProfileController.java
  49. 26 12
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/controller/web/SysUserController.java
  50. 21 3
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/controller/web/SysUserPersonController.java
  51. 16 0
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/controller/web/SysUserTenantController.java
  52. 27 0
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/controller/web/SystemInfoController.java
  53. 21 5
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/controller/web/TokenController.java
  54. 68 0
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/domain/Cpu.java
  55. 112 0
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/domain/Jvm.java
  56. 47 0
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/domain/Mem.java
  57. 41 0
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/domain/Sys.java
  58. 53 0
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/domain/SysFile.java
  59. 7 0
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/domain/SysMenu.java
  60. 153 32
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/domain/SysNotice.java
  61. 47 2
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/domain/SysPerson.java
  62. 10 0
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/domain/SysPlatform.java
  63. 12 0
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/domain/SysTenant.java
  64. 27 0
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/domain/SysUser.java
  65. 6 0
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/domain/SysUserPerson.java
  66. 22 15
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/domain/SysUserRole.java
  67. 185 0
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/domain/SystemHardwareInfo.java
  68. 8 0
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/mapper/SysDeptMapper.java
  69. 3 1
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/mapper/SysMenuMapper.java
  70. 9 0
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/mapper/SysMobileMenuMapper.java
  71. 1 1
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/mapper/SysPlatformMenuMapper.java
  72. 2 1
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/mapper/SysPostMapper.java
  73. 4 2
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/mapper/SysRoleMapper.java
  74. 2 0
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/mapper/SysTenantConfigMapper.java
  75. 6 0
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/mapper/SysUserMapper.java
  76. 4 4
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/mapper/SysUserRoleMapper.java
  77. 11 0
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/service/ISysDeptService.java
  78. 1 1
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/service/ISysMenuService.java
  79. 1 1
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/service/ISysRoleService.java
  80. 1 1
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/service/ISysUserService.java
  81. 3 0
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/service/MceContentService.java
  82. 14 1
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/service/MceReceiveService.java
  83. 43 24
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/service/SysLoginService.java
  84. 13 0
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/service/SysPersonService.java
  85. 1 0
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/service/SysUserPersonService.java
  86. 12 4
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/service/SysUserTenantService.java
  87. 17 0
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/service/config/Gzip/GzipConfig.java
  88. 81 9
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/service/impl/MceContentServiceImpl.java
  89. 144 49
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/service/impl/MceMbuserServiceImpl.java
  90. 579 77
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/service/impl/MceReceiveServiceImpl.java
  91. 15 8
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/service/impl/SysDeptServiceImpl.java
  92. 165 243
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/service/impl/SysMenuServiceImpl.java
  93. 1 1
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/service/impl/SysMobileMenuServiceImpl.java
  94. 71 31
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/service/impl/SysNoticeServiceImpl.java
  95. 129 1
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/service/impl/SysPersonServiceImpl.java
  96. 17 7
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/service/impl/SysPlatformMenuServiceImpl.java
  97. 2 0
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/service/impl/SysPlatformServiceImpl.java
  98. 7 4
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/service/impl/SysRoleServiceImpl.java
  99. 2 0
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/service/impl/SysUserOnlineServiceImpl.java
  100. 35 0
      base-modules/service-system/service-system-biz/src/main/java/com/usky/system/service/impl/SysUserPersonServiceImpl.java

+ 1 - 1
base-common/ruoyi-common-datascope/src/main/java/com/ruoyi/common/datascope/aspect/DataScopeAspect.java

@@ -101,7 +101,7 @@ public class DataScopeAspect
             else if (DATA_SCOPE_CUSTOM.equals(dataScope))
             {
                 sqlString.append(StringUtils.format(" OR {}.dept_id IN ( SELECT dept_id FROM sys_role_dept WHERE role_id = {} ) ", deptAlias, role.getRoleId()));
-                sqlLambda.append(StringUtils.format(" OR dept_id IN ( SELECT dept_id FROM sys_role_dept WHERE role_id = {} ) ", deptAlias, role.getRoleId()));
+                sqlLambda.append(StringUtils.format(" OR dept_id IN ( SELECT dept_id FROM sys_role_dept WHERE role_id = {} ) ", role.getRoleId()));
             }
             else if (DATA_SCOPE_DEPT.equals(dataScope))
             {

+ 11 - 0
base-components/monitor/pom.xml

@@ -22,6 +22,12 @@
             <artifactId>spring-boot-admin-starter-server</artifactId>
             <version>${spring-boot-admin.version}</version>
         </dependency>
+
+        <!--增加安全防护,防止别人随便进-->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-security</artifactId>
+        </dependency>
 		
         <!-- SpringCloud Alibaba Nacos -->
         <dependency>
@@ -52,6 +58,11 @@
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-security</artifactId>
         </dependency>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-webflux</artifactId>
+        </dependency>
 		
     </dependencies>
 

+ 67 - 0
base-components/monitor/src/main/java/com/ruoyi/modules/monitor/notify/DingTalkNotifier.java

@@ -0,0 +1,67 @@
+package com.ruoyi.modules.monitor.notify;
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.http.MediaType;
+import org.springframework.stereotype.Component;
+import org.springframework.web.reactive.function.BodyInserters;
+import org.springframework.web.reactive.function.client.WebClient;
+import reactor.core.publisher.Mono;
+
+import javax.crypto.Mac;
+import javax.crypto.spec.SecretKeySpec;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
+import java.time.Instant;
+import java.util.Base64;
+import java.util.HashMap;
+import java.util.Map;
+
+@Component
+public class DingTalkNotifier {
+
+    @Value("${dingtalk.webhook}")
+    private String webhook;
+
+    @Value("${dingtalk.secret:}")
+    private String secret;
+
+    private final WebClient webClient = WebClient.create();
+
+    public Mono<Void> sendMarkdown(String title, String content) {
+        String url = buildUrlWithSign();
+
+        Map<String, Object> markdownMsg = new HashMap<>();
+        markdownMsg.put("msgtype", "markdown");
+
+        Map<String, String> markdown = new HashMap<>();
+        markdown.put("title", title);
+        markdown.put("text", content);
+
+        markdownMsg.put("markdown", markdown);
+
+        return webClient.post()
+                .uri(url)
+                .contentType(MediaType.APPLICATION_JSON)
+                .body(BodyInserters.fromValue(markdownMsg))
+                .retrieve()
+                .bodyToMono(String.class)
+                .then();
+    }
+
+    private String buildUrlWithSign() {
+        if (secret == null || secret.trim().isEmpty()) {
+            return webhook;
+        }
+        long timestamp = Instant.now().toEpochMilli();
+        String stringToSign = timestamp + "\n" + secret;
+        try {
+            Mac mac = Mac.getInstance("HmacSHA256");
+            mac.init(new SecretKeySpec(secret.getBytes(StandardCharsets.UTF_8), "HmacSHA256"));
+            byte[] signData = mac.doFinal(stringToSign.getBytes(StandardCharsets.UTF_8));
+            String sign = URLEncoder.encode(new String(Base64.getEncoder().encode(signData)), String.valueOf(StandardCharsets.UTF_8));
+            return webhook + "&timestamp=" + timestamp + "&sign=" + sign;
+        } catch (Exception e) {
+            throw new RuntimeException("生成钉钉签名失败", e);
+        }
+    }
+}

+ 100 - 0
base-components/monitor/src/main/java/com/ruoyi/modules/monitor/notify/ServiceChangeNotifier.java

@@ -0,0 +1,100 @@
+package com.ruoyi.modules.monitor.notify;
+
+import de.codecentric.boot.admin.server.domain.entities.Instance;
+import de.codecentric.boot.admin.server.domain.entities.InstanceRepository;
+import de.codecentric.boot.admin.server.domain.events.InstanceEvent;
+import de.codecentric.boot.admin.server.domain.events.InstanceStatusChangedEvent;
+import de.codecentric.boot.admin.server.notify.AbstractStatusChangeNotifier;
+import org.springframework.stereotype.Component;
+import reactor.core.publisher.Mono;
+
+import java.text.SimpleDateFormat;
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+
+@Component
+public class ServiceChangeNotifier extends AbstractStatusChangeNotifier {
+
+    private final DingTalkNotifier dingTalkNotifier;
+    private final InstanceRepository repository;
+
+    /* 新增字段 */
+    private final ConcurrentHashMap<String, Instance> buffer = new ConcurrentHashMap<>();
+    private final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
+
+
+    public ServiceChangeNotifier(InstanceRepository repository,
+                                 DingTalkNotifier dingTalkNotifier) {
+        super(repository);
+        this.repository = repository;
+        this.dingTalkNotifier = dingTalkNotifier;
+
+        /* 每 5 秒聚合发送一次(可按需调整) */
+        scheduler.scheduleWithFixedDelay(this::flush, 5, 5, TimeUnit.SECONDS);
+    }
+
+    @Override
+    protected boolean shouldNotify(InstanceEvent event, Instance instance) {
+        return event instanceof InstanceStatusChangedEvent;
+    }
+
+    @Override
+    protected Mono<Void> doNotify(InstanceEvent event, Instance instance) {
+        /* 仅把实例放进 buffer,不做实际推送 */
+        buffer.put(String.valueOf(instance.getId()), instance);
+        return Mono.empty();
+    }
+
+    private void flush() {
+        if (buffer.isEmpty()) {
+            return;
+        }
+
+        /* 拿到此刻的快照,然后清空 buffer */
+        List<Instance> snapshot = new ArrayList<>(buffer.values());
+        buffer.clear();
+
+        /* 计算每个实例的 total,并排序 */
+        Map<Instance, Long> totalMap = new HashMap<>();
+        for (Instance inst : snapshot) {
+            long total = repository.findAll().collectList().block().size(); // 这里简单起见直接 block
+            totalMap.put(inst, total);
+        }
+
+        snapshot.sort(Comparator.comparing(totalMap::get));
+
+        /* 依次发送钉钉 */
+        for (Instance instance : snapshot) {
+            sendOne(instance);
+        }
+    }
+
+    private void sendOne(Instance instance) {
+        String serviceName = instance.getRegistration().getName();
+        String newStatus   = instance.getStatusInfo().getStatus();
+        String serviceUrl  = instance.getRegistration().getServiceUrl();
+        String time        = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
+
+        List<Instance> all = repository.findAll().collectList().block();
+        long total   = all.size();
+        long online  = all.stream().filter(i -> "UP".equals(i.getStatusInfo().getStatus())).count();
+        long offline = total - online;
+
+        /* 根据状态决定颜色 */
+        String icon = "UP".equalsIgnoreCase(newStatus)
+                ? "<font color=\"#00ff00\">✅</font>"
+                : "<font color=\"#ff0000\">🚨</font>";
+
+        String markdown = "### " + icon + " 服务状态变更告警\n" +
+                "- **服务名**: " + serviceName + "  \n" +
+                "- **当前状态**: " + newStatus + "  \n" +
+                "- **地址**: " + serviceUrl + "  \n" +
+                "- **时间**: " + time + "  \n" +
+                "- **统计**: 总 " + total + ",在线 " + online + ",离线 " + offline;
+
+        dingTalkNotifier.sendMarkdown("服务状态变更", markdown).subscribe();
+    }
+}

+ 41 - 11
base-modules/service-file/pom.xml

@@ -1,10 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xmlns="http://maven.apache.org/POM/4.0.0"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+<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">
     <parent>
-        <groupId>com.usky</groupId>
         <artifactId>base-modules</artifactId>
+        <groupId>com.usky</groupId>
         <version>0.0.1</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
@@ -48,11 +46,11 @@
         </dependency>
         
         <!-- Minio -->
-        <dependency>
-            <groupId>io.minio</groupId>
-            <artifactId>minio</artifactId>
-            <version>${minio.version}</version>
-        </dependency>
+<!--        <dependency>-->
+<!--            <groupId>io.minio</groupId>-->
+<!--            <artifactId>minio</artifactId>-->
+<!--            <version>${minio.version}</version>-->
+<!--        </dependency>-->
         
         <!-- RuoYi Api System -->
         <dependency>
@@ -72,7 +70,24 @@
         </dependency>
         <dependency>
             <groupId>com.usky</groupId>
-            <artifactId>ruoyi-common-core</artifactId>
+            <artifactId>common-cloud-starter</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.mybatis.spring.boot</groupId>
+            <artifactId>mybatis-spring-boot-starter</artifactId>
+            <version>2.1.4</version>
+        </dependency>
+        <dependency>
+            <groupId>mysql</groupId>
+            <artifactId>mysql-connector-java</artifactId>
+            <scope>runtime</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+            <version>1.7.36</version>
         </dependency>
 
     </dependencies>
@@ -92,7 +107,22 @@
                     </execution>
                 </executions>
             </plugin>
+            <plugin>
+                <groupId>com.github.shalousun</groupId>
+                <artifactId>smart-doc-maven-plugin</artifactId>
+                <version>2.1.1</version>
+                <configuration>
+                    <!--指定生成文档的使用的配置文件,配置文件放在自己的项目中-->
+                    <configFile>./src/main/resources/smart-doc.json</configFile>
+                    <!--指定项目名称-->
+                    <projectName>test</projectName>
+                    <!--                    <excludes>-->
+                    <!--                        <exclude>com.bizmatics:product-service-provider</exclude>-->
+                    <!--                        <exclude>cn.afterturn:easypoi-web</exclude>-->
+                    <!--                    </excludes>-->
+                </configuration>
+            </plugin>
         </plugins>
     </build>
-   
+
 </project>

+ 42 - 5
base-modules/service-file/src/main/java/com/ruoyi/file/RuoYiFileApplication.java

@@ -1,21 +1,58 @@
 package com.ruoyi.file;
 
+import org.mybatis.spring.annotation.MapperScan;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
 import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
 import com.ruoyi.common.swagger.annotation.EnableCustomSwagger2;
+import org.springframework.cloud.openfeign.EnableFeignClients;
+import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.EnableAspectJAutoProxy;
+import org.springframework.core.env.Environment;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
 
 /**
  * 文件服务
  * 
  * @author ruoyi
  */
+//@EnableCustomSwagger2
+//@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class })
+//public class RuoYiFileApplication
+//{
+//    public static void main(String[] args)
+//    {
+//        SpringApplication.run(RuoYiFileApplication.class, args);
+//    }
+//}
+
+
 @EnableCustomSwagger2
-@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class })
+@EnableAspectJAutoProxy(proxyTargetClass = true, exposeProxy = true)
+@EnableFeignClients(basePackages = {"com.ruoyi"})
+@MapperScan(value = "com.ruoyi.file.mapper")
+@ComponentScan(basePackages = {"com.ruoyi"})
+@SpringBootApplication
 public class RuoYiFileApplication
 {
-    public static void main(String[] args)
-    {
-        SpringApplication.run(RuoYiFileApplication.class, args);
+    private static final Logger LOGGER = LoggerFactory.getLogger(RuoYiFileApplication.class);
+
+    public static void main(String[] args) throws UnknownHostException {
+        ConfigurableApplicationContext application = SpringApplication.run(RuoYiFileApplication.class, args);
+        Environment env = application.getEnvironment();
+        String ip = InetAddress.getLocalHost().getHostAddress();
+        String port = env.getProperty("server.port");
+        String path = env.getProperty("server.servlet.context-path");
+        LOGGER.info("\n----------------------------------------------------------\n\t" +
+                "Application is running! Access URLs:\n\t" +
+                "Local: \t\thttp://localhost:" + port + (null==path?"":path) + "/\n\t" +
+                "External: \thttp://" + ip + ":" + port + (null==path?"":path) + "/\n\t" +
+                "Api: \t\thttp://" + ip + ":" + port + (null==path?"":path) + "/swagger-ui/index.html\n\t" +
+                "----------------------------------------------------------");
     }
-}
+}

+ 82 - 82
base-modules/service-file/src/main/java/com/ruoyi/file/config/MinioConfig.java

@@ -1,82 +1,82 @@
-package com.ruoyi.file.config;
-
-import org.springframework.boot.context.properties.ConfigurationProperties;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import io.minio.MinioClient;
-
-/**
- * Minio 配置信息
- *
- * @author ruoyi
- */
-@Configuration
-@ConfigurationProperties(prefix = "minio")
-public class MinioConfig
-{
-    /**
-     * 服务地址
-     */
-    private String url;
-
-    /**
-     * 用户名
-     */
-    private String accessKey;
-
-    /**
-     * 密码
-     */
-    private String secretKey;
-
-    /**
-     * 存储桶名称
-     */
-    private String bucketName;
-
-    public String getUrl()
-    {
-        return url;
-    }
-
-    public void setUrl(String url)
-    {
-        this.url = url;
-    }
-
-    public String getAccessKey()
-    {
-        return accessKey;
-    }
-
-    public void setAccessKey(String accessKey)
-    {
-        this.accessKey = accessKey;
-    }
-
-    public String getSecretKey()
-    {
-        return secretKey;
-    }
-
-    public void setSecretKey(String secretKey)
-    {
-        this.secretKey = secretKey;
-    }
-
-    public String getBucketName()
-    {
-        return bucketName;
-    }
-
-    public void setBucketName(String bucketName)
-    {
-        this.bucketName = bucketName;
-    }
-
-    @Bean
-    public MinioClient getMinioClient()
-    {
-        return MinioClient.builder().endpoint(url).credentials(accessKey, secretKey).build();
-    }
-}
+//package com.ruoyi.file.config;
+//
+//import org.springframework.boot.context.properties.ConfigurationProperties;
+//import org.springframework.context.annotation.Bean;
+//import org.springframework.context.annotation.Configuration;
+//import io.minio.MinioClient;
+//
+///**
+// * Minio 配置信息
+// *
+// * @author ruoyi
+// */
+//@Configuration
+//@ConfigurationProperties(prefix = "minio")
+//public class MinioConfig
+//{
+//    /**
+//     * 服务地址
+//     */
+//    private String url;
+//
+//    /**
+//     * 用户名
+//     */
+//    private String accessKey;
+//
+//    /**
+//     * 密码
+//     */
+//    private String secretKey;
+//
+//    /**
+//     * 存储桶名称
+//     */
+//    private String bucketName;
+//
+//    public String getUrl()
+//    {
+//        return url;
+//    }
+//
+//    public void setUrl(String url)
+//    {
+//        this.url = url;
+//    }
+//
+//    public String getAccessKey()
+//    {
+//        return accessKey;
+//    }
+//
+//    public void setAccessKey(String accessKey)
+//    {
+//        this.accessKey = accessKey;
+//    }
+//
+//    public String getSecretKey()
+//    {
+//        return secretKey;
+//    }
+//
+//    public void setSecretKey(String secretKey)
+//    {
+//        this.secretKey = secretKey;
+//    }
+//
+//    public String getBucketName()
+//    {
+//        return bucketName;
+//    }
+//
+//    public void setBucketName(String bucketName)
+//    {
+//        this.bucketName = bucketName;
+//    }
+//
+//    @Bean
+//    public MinioClient getMinioClient()
+//    {
+//        return MinioClient.builder().endpoint(url).credentials(accessKey, secretKey).build();
+//    }
+//}

+ 16 - 0
base-modules/service-file/src/main/java/com/ruoyi/file/config/MybatisPlusConfig.java

@@ -0,0 +1,16 @@
+package com.ruoyi.file.config;
+
+import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
+import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class MybatisPlusConfig {
+    @Bean
+    public MybatisPlusInterceptor mybatisPlusInterceptor() {
+        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
+        interceptor.addInnerInterceptor(new PaginationInnerInterceptor());
+        return interceptor;
+    }
+}

+ 2 - 2
base-modules/service-file/src/main/java/com/ruoyi/file/config/ResourcesConfig.java

@@ -9,7 +9,7 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
 
 /**
  * 通用映射配置
- * 
+ *
  * @author ruoyi
  */
 @Configuration
@@ -34,7 +34,7 @@ public class ResourcesConfig implements WebMvcConfigurer
         registry.addResourceHandler(localFilePrefix + "/**")
                 .addResourceLocations("file:" + localFilePath + File.separator);
     }
-    
+
     /**
      * 开启跨域
      */

+ 19 - 0
base-modules/service-file/src/main/java/com/ruoyi/file/config/WebConfig.java

@@ -0,0 +1,19 @@
+package com.ruoyi.file.config;
+
+import org.springframework.context.annotation.Configuration;
+import org.springframework.format.FormatterRegistry;
+import org.springframework.format.datetime.standard.DateTimeFormatterRegistrar;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+import java.time.format.DateTimeFormatter;
+
+@Configuration
+public class WebConfig implements WebMvcConfigurer {
+
+    @Override
+    public void addFormatters(FormatterRegistry registry) {
+        DateTimeFormatterRegistrar registrar = new DateTimeFormatterRegistrar();
+        registrar.setDateTimeFormatter(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
+        registrar.registerFormatters(registry);
+    }
+}

+ 127 - 0
base-modules/service-file/src/main/java/com/ruoyi/file/controller/FileUpdateInfoController.java

@@ -0,0 +1,127 @@
+package com.ruoyi.file.controller;
+
+import com.ruoyi.file.domain.FileUpdateInfo;
+import com.ruoyi.file.domain.FileWithId;
+import com.ruoyi.file.service.FileUpdateInfoService;
+import com.usky.common.core.bean.ApiResult;
+import com.usky.common.core.bean.CommonPage;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+@RestController
+@RequestMapping("/api/update")
+public class FileUpdateInfoController {
+
+    @Autowired
+    private FileUpdateInfoService fileUpdateInfoService;
+
+    //增加服务信息
+    @PostMapping("/add")
+    public ApiResult<String> addFileToDatabase(@RequestBody FileUpdateInfo fileUpdateInfo) {
+        try {
+            fileUpdateInfoService.addFileToDatabase(fileUpdateInfo);
+            return ApiResult.success("文件信息录入成功");
+        } catch (Exception e) {
+            return ApiResult.error("文件信息录入失败: " + e.getMessage());
+        }
+    }
+
+    //检查服务版本
+    @PostMapping("/checkById")
+    public ApiResult<String> checkFileUpdate(@RequestParam Long id) {
+        try {
+            boolean isUpdateRequired = fileUpdateInfoService.checkFileUpdate(id);
+            String result = isUpdateRequired ? "待更新" : "无需更新";
+            return ApiResult.success(result);
+        } catch (Exception e) {
+            return ApiResult.error("检查文件更新失败:远程仓库未找到对应服务");
+        }
+    }
+
+    //下载更新服务
+    @PostMapping("/reloadById")
+    public ApiResult<String> performFileUpdate(@RequestParam Long id) {
+        try {
+            fileUpdateInfoService.performFileUpdate(id);
+            return ApiResult.success("文件更新成功");
+        } catch (Exception e) {
+            return ApiResult.error("文件更新失败," + e.getMessage());
+        }
+    }
+
+    //查询服务信息
+    @GetMapping("/query")
+    public ApiResult<CommonPage<FileUpdateInfo>> queryFiles(
+            @RequestParam(required = false) String fileName,
+            @RequestParam(required = false, defaultValue = "1") int current,
+            @RequestParam(required = false, defaultValue = "10") int size) {
+        try {
+            CommonPage<FileUpdateInfo> commonPage;
+            if (fileName == null || fileName.trim().isEmpty()) {
+                commonPage = fileUpdateInfoService.getAllFiles(current, size);
+            } else {
+                commonPage = fileUpdateInfoService.getFilesByFileNameContaining(fileName, current, size);
+            }
+            return ApiResult.success(commonPage);
+        } catch (Exception e) {
+            return ApiResult.error("查询文件信息失败: " + e.getMessage());
+        }
+    }
+
+    //删除服务信息
+    @DeleteMapping("/deleteById")
+    public ApiResult<String> deleteFileById(@RequestParam Long id) {
+        try {
+            fileUpdateInfoService.deleteFileById(id);
+            return ApiResult.success("文件信息删除成功");
+        } catch (Exception e) {
+            return ApiResult.error("删除文件信息失败: " + e.getMessage());
+        }
+    }
+
+    //控制服务运行状态(启动start、停止stop、重启restart)
+    @PostMapping("/controlById")
+    public ApiResult<String> controlServiceById(@RequestParam Long id, @RequestParam String action) {
+        try {
+            FileUpdateInfo fileUpdateInfo = fileUpdateInfoService.getFileById(id);
+            if (fileUpdateInfo == null) {
+                return ApiResult.error("未找到对应的文件信息,ID: " + id);
+            }
+            String fileName = fileUpdateInfo.getFileName();
+
+            // 在控制服务之前,先检测当前服务状态
+            int currentStatus = fileUpdateInfoService.getFileStatus(fileName);
+            if ((action.equals("start") && currentStatus == 1) || (action.equals("stop") && currentStatus == 2)) {
+                return ApiResult.error("服务已经是目标状态,无需重复操作");
+            }
+
+            fileUpdateInfoService.controlApplication(fileName, action);
+
+            // 根据 action 返回不同的成功消息
+            if ("start".equalsIgnoreCase(action)) {
+                return ApiResult.success("启动成功");
+            } else if ("stop".equalsIgnoreCase(action)) {
+                return ApiResult.success("停止成功");
+            } else if ("restart".equalsIgnoreCase(action)) {
+                return ApiResult.success("重启成功");
+            } else {
+                return ApiResult.success(action + "命令已发送");
+            }
+        } catch (Exception e) {
+            return ApiResult.error("控制服务失败: " + e.getMessage());
+        }
+    }
+
+    // 扫描服务所在目录下的文件
+    @GetMapping("/scan")
+    public ApiResult<CommonPage<FileWithId>> scanFilesInServiceDir(
+            @RequestParam(required = false, defaultValue = "1") int current,
+            @RequestParam(required = false, defaultValue = "10") int size) {
+        try {
+            CommonPage<FileWithId> fileNamesPage = fileUpdateInfoService.scanFilesInServiceDir(current, size);
+            return ApiResult.success(fileNamesPage);
+        } catch (Exception e) {
+            return ApiResult.error("扫描文件失败: " + e.getMessage());
+        }
+    }
+}

+ 156 - 0
base-modules/service-file/src/main/java/com/ruoyi/file/controller/FilesController.java

@@ -0,0 +1,156 @@
+package com.ruoyi.file.controller;
+
+import com.ruoyi.common.core.domain.R;
+import com.ruoyi.file.service.FileUploadResponse;
+import com.ruoyi.file.domain.FilesUpload;
+import com.ruoyi.file.service.FilesService;
+import com.usky.common.core.bean.ApiResult;
+import com.usky.common.core.bean.CommonPage;
+import com.usky.common.security.utils.SecurityUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.servlet.http.HttpServletRequest;
+import java.net.URL;
+import java.time.LocalDateTime;
+import java.util.Enumeration;
+import java.net.URLDecoder;
+import java.nio.charset.StandardCharsets;
+
+
+@RestController
+//@RequestMapping("/files")
+public class FilesController {
+
+    @Autowired
+    private FilesService filesService;
+
+    @PostMapping("/upload")
+    public ApiResult<FileUploadResponse> upload(@RequestParam MultipartFile file, HttpServletRequest request) {
+        // 打印所有请求头,以便调试
+/*        Enumeration<String> headerNames = request.getHeaderNames();
+        while (headerNames.hasMoreElements()) {
+            String headerName = headerNames.nextElement();
+            String headerValue = request.getHeader(headerName);
+            System.out.println(headerName + ": " + headerValue);
+        }*/
+
+        // 从请求头中获取 userid
+        String useridStr = request.getHeader("user_id");
+
+        Long userid = null; // 初始化为 null
+        if (useridStr != null && !useridStr.isEmpty()) {
+            try {
+                // 尝试将 userid 转换为 Long 类型
+                userid = Long.parseLong(useridStr);
+            } catch (NumberFormatException e) {
+                // 如果转换失败,打印错误信息并保持 userid 为 null
+                System.out.println("无法将 user_id 转换为 Long 类型: " + useridStr);
+            }
+        }
+
+        // 从请求头中获取 username
+        String username = request.getHeader("username");
+
+        // 如果用户名为空或解码失败,设置为“未知用户”
+        if (username == null || username.isEmpty()) {
+            username = "未知用户";
+        } else {
+            try {
+                // 使用 URLDecoder 解码用户名
+                username = URLDecoder.decode(username, StandardCharsets.UTF_8.name());
+            } catch (Exception e) {
+                // 如果解码失败,设置为“未知用户”
+                username = "未知用户";
+            }
+        }
+
+        // 从请求头中获取 referer
+        String referer = request.getHeader("referer");
+        String refererPath = "";
+        if (referer != null && !referer.isEmpty()) {
+            try {
+                // 提取 referer 的路径部分
+                URL url = new URL(referer);
+                refererPath = url.getPath();
+            } catch (Exception e) {
+                System.out.println("无法解析 referer URL: " + referer);
+            }
+        }
+
+        // 打印 referer 路径部分
+//        System.out.println("Referer 路径部分: " + refererPath);
+
+        // 继续处理文件上传逻辑
+        FileUploadResponse response = filesService.upload(file, userid, username, refererPath);
+        return ApiResult.success(response);
+    }
+
+
+    @DeleteMapping("/delete/{id}")
+    public ApiResult<String> delete(@PathVariable Integer id, HttpServletRequest request) {
+        // 打印所有请求头,以便调试
+/*        Enumeration<String> headerNames = request.getHeaderNames();
+        while (headerNames.hasMoreElements()) {
+            String headerName = headerNames.nextElement();
+            String headerValue = request.getHeader(headerName);
+            System.out.println(headerName + ": " + headerValue);
+        }*/
+
+        // 从请求头中获取 userid
+        String useridStr = request.getHeader("user_id");
+
+        Long userid = null; // 初始化为 null
+        if (useridStr != null && !useridStr.isEmpty()) {
+            try {
+                // 尝试将 userid 转换为 Long 类型
+                userid = Long.parseLong(useridStr);
+            } catch (NumberFormatException e) {
+                // 如果转换失败,打印错误信息并保持 userid 为 null
+                System.out.println("无法将 user_id 转换为 Long 类型: " + useridStr);
+            }
+        }
+
+        // 从请求头中获取username
+        String username = request.getHeader("username");
+
+        // 如果用户名为空或解码失败,设置为“未知用户”
+        if (username == null || username.isEmpty()) {
+            username = "未知用户";
+        } else {
+            try {
+                // 使用 URLDecoder 解码用户名
+                username = URLDecoder.decode(username, StandardCharsets.UTF_8.name());
+            } catch (Exception e) {
+                // 如果解码失败,设置为“未知用户”
+                username = "未知用户";
+            }
+        }
+
+        try {
+            filesService.deleteFile(id, userid, username);
+            return ApiResult.success("删除成功");
+        } catch (Exception e) {
+            return ApiResult.error("删除失败"); // 删除失败,返回错误信息
+        }
+    }
+
+    @GetMapping("/query")
+    public R<CommonPage<FilesUpload>> queryFiles(
+            @RequestParam(required = false) String filesName,
+            @RequestParam(required = false) LocalDateTime startTime,
+            @RequestParam(required = false) LocalDateTime endTime,
+            @RequestParam(required = false) Boolean isDeleted,
+            @RequestParam(required = false) String fileType,
+            @RequestParam(required = false) String userName,
+            @RequestParam int current,
+            @RequestParam int size) {
+
+        // 调用服务层方法
+        CommonPage<FilesUpload> resultPage = filesService.queryFiles(filesName, startTime, endTime, isDeleted, fileType, userName, current, size);
+
+        // 返回封装好的分页结果
+        return R.ok(resultPage);
+    }
+}

+ 47 - 47
base-modules/service-file/src/main/java/com/ruoyi/file/controller/SysFileController.java

@@ -1,47 +1,47 @@
-package com.ruoyi.file.controller;
-
-import com.ruoyi.common.core.domain.R;
-import com.usky.system.domain.SysFileVO;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.RestController;
-import org.springframework.web.multipart.MultipartFile;
-import com.ruoyi.file.service.ISysFileService;
-import com.ruoyi.common.core.utils.file.FileUtils;
-
-/**
- * 文件请求处理
- * @author ruoyi
- */
-@RestController
-public class SysFileController
-{
-    private static final Logger log = LoggerFactory.getLogger(SysFileController.class);
-
-    @Autowired
-    private ISysFileService sysFileService;
-
-    /**
-     * 文件上传请求
-     */
-    @PostMapping("upload")
-    public R<SysFileVO> upload(MultipartFile file)
-    {
-        try
-        {
-            // 上传并返回访问地址
-            String url = sysFileService.uploadFile(file);
-            SysFileVO sysFile = new SysFileVO();
-            sysFile.setName(FileUtils.getName(url));
-            sysFile.setUrl(url);
-            return R.ok(sysFile);
-        }
-        catch (Exception e)
-        {
-            log.error("上传文件失败", e);
-            return R.fail(e.getMessage());
-        }
-    }
-}
+//package com.ruoyi.file.controller;
+//
+//import com.ruoyi.common.core.domain.R;
+//import com.usky.system.domain.SysFileVO;
+//import org.slf4j.Logger;
+//import org.slf4j.LoggerFactory;
+//import org.springframework.beans.factory.annotation.Autowired;
+//import org.springframework.web.bind.annotation.PostMapping;
+//import org.springframework.web.bind.annotation.RestController;
+//import org.springframework.web.multipart.MultipartFile;
+//import com.ruoyi.file.service.ISysFileService;
+//import com.ruoyi.common.core.utils.file.FileUtils;
+//
+///**
+// * 文件请求处理
+// * @author ruoyi
+// */
+//@RestController
+//public class SysFileController
+//{
+//    private static final Logger log = LoggerFactory.getLogger(SysFileController.class);
+//
+//    @Autowired
+//    private ISysFileService sysFileService;
+//
+//    /**
+//     * 文件上传请求
+//     */
+//    @PostMapping("upload")
+//    public R<SysFileVO> upload(MultipartFile file)
+//    {
+//        try
+//        {
+//            // 上传并返回访问地址
+//            String url = sysFileService.uploadFile(file);
+//            SysFileVO sysFile = new SysFileVO();
+//            sysFile.setName(FileUtils.getName(url));
+//            sysFile.setUrl(url);
+//            return R.ok(sysFile);
+//        }
+//        catch (Exception e)
+//        {
+//            log.error("上传文件失败", e);
+//            return R.fail(e.getMessage());
+//        }
+//    }
+//}

+ 82 - 0
base-modules/service-file/src/main/java/com/ruoyi/file/domain/FileUpdateInfo.java

@@ -0,0 +1,82 @@
+package com.ruoyi.file.domain;
+
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import lombok.Data;
+
+import java.io.File;
+import java.net.URL;
+import java.time.LocalDateTime;
+
+@Data
+@TableName("file_update_info")
+public class FileUpdateInfo {
+    private Long id;
+    private String fileName; // 文件名
+    private String fileMd5;
+    private String remoteMd5;
+
+    @TableField(fill = FieldFill.INSERT)
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime createTime;
+
+    @TableField(fill = FieldFill.INSERT_UPDATE)
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime updateTime;
+
+    private int updateStatus;    // 0表示无需更新,1表示待更新
+
+    // 新增版本号字段
+    @TableField(fill = FieldFill.INSERT)
+    private String version = "v1.0.0"; // 默认版本号
+
+    // 新增运行状态字段
+    private int fileStatus; // 0:未知,1:运行中,2:已停止
+
+    // 获取带版本号的文件名
+//    @JsonIgnore // 忽略该字段的序列化
+//    public String getVersionedFileName() {
+//        return fileName.substring(0, fileName.lastIndexOf('.')) + "-" + version + fileName.substring(fileName.lastIndexOf('.'));
+//    }
+
+    // 获取文件完整路径(基于 JAR 文件所在的目录)
+    @JsonIgnore // 忽略该字段的序列化
+    public String getFilePath() {
+        return getServiceDir() + File.separator + fileName;
+    }
+
+    // 动态获取 JAR 文件所在的目录
+    public static String getServiceDir() {
+        try {
+            // 获取当前类的 ClassLoader
+            ClassLoader classLoader = FileUpdateInfo.class.getClassLoader();
+            // 获取当前类的资源路径(例如 JAR 文件路径)
+            URL url = classLoader.getResource(FileUpdateInfo.class.getName().replace('.', '/') + ".class");
+            if (url != null && "jar".equals(url.getProtocol())) {
+                // 从 JAR 文件中获取路径
+                String jarPath = url.getPath();
+                // 去掉 JAR 文件内部路径部分
+                int bangIndex = jarPath.indexOf("!/");
+                if (bangIndex > 0) {
+                    jarPath = jarPath.substring(0, bangIndex);
+                }
+                // 去掉 "file:" 前缀
+                if (jarPath.startsWith("file:")) {
+                    jarPath = jarPath.substring(5);
+                }
+                // 获取 JAR 文件所在的目录
+                return new java.io.File(jarPath).getParent();
+            } else if (url != null && "file".equals(url.getProtocol())) {
+                // 如果是直接运行的文件路径
+                String filePath = url.getPath();
+                return new java.io.File(filePath).getParent();
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return System.getProperty("user.dir"); // 如果无法获取 JAR 路径,退回到当前工作目录
+    }
+}

+ 14 - 0
base-modules/service-file/src/main/java/com/ruoyi/file/domain/FileWithId.java

@@ -0,0 +1,14 @@
+package com.ruoyi.file.domain;
+
+import lombok.Data;
+
+@Data
+public class FileWithId {
+    private Long id;
+    private String fileName;
+
+    public FileWithId(Long id, String fileName) {
+        this.id = id;
+        this.fileName = fileName;
+    }
+}

+ 50 - 0
base-modules/service-file/src/main/java/com/ruoyi/file/domain/FilesUpload.java

@@ -0,0 +1,50 @@
+package com.ruoyi.file.domain;
+
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+@Data
+@TableName("file_upload")
+public class FilesUpload implements Serializable {
+    private Integer id;//编号
+
+    private String filesName;//文件真实名称
+
+    private String name;//文件名
+
+    private String path;
+
+    private String type;//文件类型
+
+    private Double size;//文件大小
+
+    private String url;//下载链接
+
+    private  String refererPath;//引用路径
+
+    private Boolean enable;//链接是否可用(1:是 0:否)
+
+    private String createBy;//创建者
+
+    private Long createId;//创建者ID
+
+    @TableField(fill = FieldFill.INSERT)
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime createTime;//创建时间
+
+    private String updateBy;//更新者
+
+    private Long updateId;//更新者ID
+
+    @TableField(fill = FieldFill.INSERT_UPDATE)
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime updateTime;//更新时间
+
+    private Integer isDelete;//是否删除(1:是 0:否)
+}

+ 9 - 0
base-modules/service-file/src/main/java/com/ruoyi/file/mapper/FileUpdateInfoMapper.java

@@ -0,0 +1,9 @@
+package com.ruoyi.file.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.ruoyi.file.domain.FileUpdateInfo;
+import org.apache.ibatis.annotations.Mapper;
+
+@Mapper
+public interface FileUpdateInfoMapper extends BaseMapper<FileUpdateInfo> {
+}

+ 10 - 0
base-modules/service-file/src/main/java/com/ruoyi/file/mapper/FilesMapper.java

@@ -0,0 +1,10 @@
+package com.ruoyi.file.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.ruoyi.file.domain.FilesUpload;
+import org.apache.ibatis.annotations.Mapper;
+
+@Mapper
+public interface FilesMapper extends BaseMapper<FilesUpload> {
+
+}

+ 42 - 42
base-modules/service-file/src/main/java/com/ruoyi/file/service/FastDfsSysFileServiceImpl.java

@@ -1,42 +1,42 @@
-package com.ruoyi.file.service;
-
-import org.apache.commons.io.FilenameUtils;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.stereotype.Service;
-import org.springframework.web.multipart.MultipartFile;
-import com.github.tobato.fastdfs.domain.fdfs.StorePath;
-import com.github.tobato.fastdfs.service.FastFileStorageClient;
-
-/**
- * FastDFS 文件存储
- * 
- * @author ruoyi
- */
-@Service
-public class FastDfsSysFileServiceImpl implements ISysFileService
-{
-    /**
-     * 域名或本机访问地址
-     */
-    @Value("${fdfs.domain}")
-    public String domain;
-
-    @Autowired
-    private FastFileStorageClient storageClient;
-
-    /**
-     * FastDfs文件上传接口
-     * 
-     * @param file 上传的文件
-     * @return 访问地址
-     * @throws Exception
-     */
-    @Override
-    public String uploadFile(MultipartFile file) throws Exception
-    {
-        StorePath storePath = storageClient.uploadFile(file.getInputStream(), file.getSize(),
-                FilenameUtils.getExtension(file.getOriginalFilename()), null);
-        return domain + "/" + storePath.getFullPath();
-    }
-}
+//package com.ruoyi.file.service;
+//
+//import org.apache.commons.io.FilenameUtils;
+//import org.springframework.beans.factory.annotation.Autowired;
+//import org.springframework.beans.factory.annotation.Value;
+//import org.springframework.stereotype.Service;
+//import org.springframework.web.multipart.MultipartFile;
+//import com.github.tobato.fastdfs.domain.fdfs.StorePath;
+//import com.github.tobato.fastdfs.service.FastFileStorageClient;
+//
+///**
+// * FastDFS 文件存储
+// *
+// * @author ruoyi
+// */
+//@Service
+//public class FastDfsSysFileServiceImpl implements ISysFileService
+//{
+//    /**
+//     * 域名或本机访问地址
+//     */
+//    @Value("${fdfs.domain}")
+//    public String domain;
+//
+//    @Autowired
+//    private FastFileStorageClient storageClient;
+//
+//    /**
+//     * FastDfs文件上传接口
+//     *
+//     * @param file 上传的文件
+//     * @return 访问地址
+//     * @throws Exception
+//     */
+//    @Override
+//    public String uploadFile(MultipartFile file) throws Exception
+//    {
+//        StorePath storePath = storageClient.uploadFile(file.getInputStream(), file.getSize(),
+//                FilenameUtils.getExtension(file.getOriginalFilename()), null);
+//        return domain + "/" + storePath.getFullPath();
+//    }
+//}

+ 50 - 0
base-modules/service-file/src/main/java/com/ruoyi/file/service/FileUpdateInfoService.java

@@ -0,0 +1,50 @@
+package com.ruoyi.file.service;
+
+import com.ruoyi.file.domain.FileUpdateInfo;
+import com.ruoyi.file.domain.FileWithId;
+import com.usky.common.core.bean.CommonPage;
+import org.springframework.web.bind.annotation.RequestParam;
+
+public interface FileUpdateInfoService {
+
+    /**
+     * 获取文件的运行状态
+     * @param fileName 文件名
+     * @return 状态码(1: 运行中,2: 已停止,0: 未知)
+     */
+    int getFileStatus(String fileName);
+
+    //添加服务信息
+    void addFileToDatabase(FileUpdateInfo fileUpdateInfo) throws Exception;
+
+    //检查服务更新
+    boolean checkFileUpdate(Long id) throws Exception;
+
+    //执行服务更新
+    void performFileUpdate(Long id) throws Exception;
+
+    // 获取所有服务信息(分页)
+    CommonPage<FileUpdateInfo> getAllFiles(
+            @RequestParam(required = false, defaultValue = "1") int current,
+            @RequestParam(required = false, defaultValue = "10") int size) throws Exception;
+
+    // 根据文件名模糊查询服务信息(分页)
+    CommonPage<FileUpdateInfo> getFilesByFileNameContaining(
+            @RequestParam(required = false) String fileName,
+            @RequestParam(required = false, defaultValue = "1") int current,
+            @RequestParam(required = false, defaultValue = "10") int size) throws Exception;
+
+    //根据id查询服务信息
+    FileUpdateInfo getFileById(Long id) throws Exception;
+
+    //删除服务信息
+    void deleteFileById(Long id) throws Exception;
+
+    //控制服务运行状态
+    void controlApplication(String fileName, String action) throws Exception;
+
+    // 扫描 JAR 文件所在的目录并获取文件列表
+    CommonPage<FileWithId> scanFilesInServiceDir(
+            @RequestParam(required = false, defaultValue = "1") int current,
+            @RequestParam(required = false, defaultValue = "10") int size) throws Exception;
+}

+ 30 - 0
base-modules/service-file/src/main/java/com/ruoyi/file/service/FileUploadResponse.java

@@ -0,0 +1,30 @@
+package com.ruoyi.file.service;
+
+import lombok.Data;
+
+@Data
+public class FileUploadResponse {
+    private String name;
+    private String url;
+
+    public FileUploadResponse(String name, String url) {
+        this.name = name;
+        this.url = url;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getUrl() {
+        return url;
+    }
+
+    public void setUrl(String url) {
+        this.url = url;
+    }
+}

+ 19 - 0
base-modules/service-file/src/main/java/com/ruoyi/file/service/FilesService.java

@@ -0,0 +1,19 @@
+package com.ruoyi.file.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.ruoyi.file.domain.FilesUpload;
+import com.usky.common.core.bean.CommonPage;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.time.LocalDateTime;
+
+public interface FilesService extends IService<FilesUpload> {
+    // 修改返回类型为 FileUploadResponse
+    FileUploadResponse upload(MultipartFile file, Long userid, String userName, String refererPath);
+
+    // 删除文件
+    void deleteFile(Integer id, Long userid, String userName);
+
+    // 查询方法
+    CommonPage<FilesUpload> queryFiles(String filesName, LocalDateTime startTime, LocalDateTime endTime, Boolean isDeleted, String fileType, String userName, int current, int size);
+}

+ 20 - 20
base-modules/service-file/src/main/java/com/ruoyi/file/service/ISysFileService.java

@@ -1,20 +1,20 @@
-package com.ruoyi.file.service;
-
-import org.springframework.web.multipart.MultipartFile;
-
-/**
- * 文件上传接口
- * 
- * @author ruoyi
- */
-public interface ISysFileService
-{
-    /**
-     * 文件上传接口
-     * 
-     * @param file 上传的文件
-     * @return 访问地址
-     * @throws Exception
-     */
-    public String uploadFile(MultipartFile file) throws Exception;
-}
+//package com.ruoyi.file.service;
+//
+//import org.springframework.web.multipart.MultipartFile;
+//
+///**
+// * 文件上传接口
+// *
+// * @author ruoyi
+// */
+//public interface ISysFileService
+//{
+//    /**
+//     * 文件上传接口
+//     *
+//     * @param file 上传的文件
+//     * @return 访问地址
+//     * @throws Exception
+//     */
+//    public String uploadFile(MultipartFile file) throws Exception;
+//}

+ 50 - 50
base-modules/service-file/src/main/java/com/ruoyi/file/service/LocalSysFileServiceImpl.java

@@ -1,50 +1,50 @@
-package com.ruoyi.file.service;
-
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.context.annotation.Primary;
-import org.springframework.stereotype.Service;
-import org.springframework.web.multipart.MultipartFile;
-import com.ruoyi.file.utils.FileUploadUtils;
-
-/**
- * 本地文件存储
- *
- * @author ruoyi
- */
-@Primary
-@Service
-public class LocalSysFileServiceImpl implements ISysFileService
-{
-    /**
-     * 资源映射路径 前缀
-     */
-    @Value("${file.prefix}")
-    public String localFilePrefix;
-
-    /**
-     * 域名或本机访问地址
-     */
-    @Value("${file.domain}")
-    public String domain;
-
-    /**
-     * 上传文件存储在本地的根路径
-     */
-    @Value("${file.path}")
-    private String localFilePath;
-
-    /**
-     * 本地文件上传接口
-     *
-     * @param file 上传的文件
-     * @return 访问地址
-     * @throws Exception
-     */
-    @Override
-    public String uploadFile(MultipartFile file) throws Exception
-    {
-        String name = FileUploadUtils.upload(localFilePath, file);
-        String url = domain + localFilePrefix + name;
-        return url;
-    }
-}
+//package com.ruoyi.file.service;
+//
+//import org.springframework.beans.factory.annotation.Value;
+//import org.springframework.context.annotation.Primary;
+//import org.springframework.stereotype.Service;
+//import org.springframework.web.multipart.MultipartFile;
+//import com.ruoyi.file.utils.FileUploadUtils;
+//
+///**
+// * 本地文件存储
+// *
+// * @author ruoyi
+// */
+//@Primary
+//@Service
+//public class LocalSysFileServiceImpl implements ISysFileService
+//{
+//    /**
+//     * 资源映射路径 前缀
+//     */
+//    @Value("${file.prefix}")
+//    public String localFilePrefix;
+//
+//    /**
+//     * 域名或本机访问地址
+//     */
+//    @Value("${file.domain}")
+//    public String domain;
+//
+//    /**
+//     * 上传文件存储在本地的根路径
+//     */
+//    @Value("${file.path}")
+//    private String localFilePath;
+//
+//    /**
+//     * 本地文件上传接口
+//     *
+//     * @param file 上传的文件
+//     * @return 访问地址
+//     * @throws Exception
+//     */
+//    @Override
+//    public String uploadFile(MultipartFile file) throws Exception
+//    {
+//        String name = FileUploadUtils.upload(localFilePath, file);
+//        String url = domain + localFilePrefix + name;
+//        return url;
+//    }
+//}

+ 416 - 0
base-modules/service-file/src/main/java/com/ruoyi/file/service/impl/FileUpdateInfoServiceImpl.java

@@ -0,0 +1,416 @@
+package com.ruoyi.file.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.file.domain.FileUpdateInfo;
+import com.ruoyi.file.domain.FileWithId;
+import com.ruoyi.file.mapper.FileUpdateInfoMapper;
+import com.ruoyi.file.service.FileUpdateInfoService;
+import com.usky.common.core.bean.CommonPage;
+import org.apache.commons.codec.digest.DigestUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.*;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.StandardCopyOption;
+import java.text.SimpleDateFormat;
+import java.time.LocalDateTime;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.stream.Collectors;
+
+@Service
+public class FileUpdateInfoServiceImpl implements FileUpdateInfoService {
+    private static final Logger logger = LoggerFactory.getLogger(FileUpdateInfoServiceImpl.class);
+
+    @Autowired
+    private FileUpdateInfoMapper fileUpdateInfoMapper;
+
+    @Value("${file.remote-url}")
+    private String remoteUrlBase;
+
+    // 从配置文件中读取脚本名称
+    @Value("${file.linuxrestart}")
+    private String linuxContralScript;
+
+    @Value("${file.windowsstop}")
+    private String windowsStopScript;
+
+    @Value("${file.windowsstart}")
+    private String windowsStartScript;
+
+    @Override
+    public void addFileToDatabase(FileUpdateInfo fileUpdateInfo) throws Exception {
+        // 假设前端只传入文件名
+        String fileName = fileUpdateInfo.getFileName();
+        if (fileName == null || fileName.trim().isEmpty()) {
+            throw new IllegalArgumentException("文件名不能为空");
+        }
+
+        // 设置文件路径
+        String filePath = FileUpdateInfo.getServiceDir() + File.separator + fileUpdateInfo.getFileName();
+
+        File file = new File(filePath);
+
+        if (file.exists()) {
+            // 如果文件存在,计算本地文件的 MD5 值
+            String fileMd5 = DigestUtils.md5Hex(new FileInputStream(file));
+            fileUpdateInfo.setFileMd5(fileMd5);
+            fileUpdateInfo.setUpdateStatus(0);
+        } else {
+            // 如果文件不存在,设置状态为“待更新”
+            fileUpdateInfo.setFileMd5(null);
+            fileUpdateInfo.setUpdateStatus(1);
+        }
+
+        fileUpdateInfo.setVersion("v1.0.0"); // 初始化版本号
+        fileUpdateInfo.setCreateTime(LocalDateTime.now());
+        fileUpdateInfo.setUpdateTime(null);
+        fileUpdateInfoMapper.insert(fileUpdateInfo);
+    }
+
+    //检查是否需要更新
+    @Override
+    public boolean checkFileUpdate(Long id) throws Exception {
+        FileUpdateInfo fileUpdateInfo = fileUpdateInfoMapper.selectById(id);
+        if (fileUpdateInfo == null) {
+            throw new FileNotFoundException("文件信息未找到:id=" + id);
+        }
+
+        String localFilePath = fileUpdateInfo.getFilePath(); // 使用新的 getFilePath 方法
+        File localFile = new File(localFilePath);
+
+        String remoteFileMd5 = getRemoteFileMd5(fileUpdateInfo.getFileName());
+
+        if (!localFile.exists()) {
+            // 如果本地文件不存在,设置状态为“待更新”
+            fileUpdateInfo.setRemoteMd5(remoteFileMd5);
+            fileUpdateInfo.setUpdateStatus(1); // 设置为待更新
+            fileUpdateInfoMapper.updateById(fileUpdateInfo);
+            return true; // 需要更新
+        } else {
+            // 如果本地文件存在,比较 MD5 值
+            String localFileMd5 = DigestUtils.md5Hex(new FileInputStream(localFile));
+            boolean isUpdateRequired = !localFileMd5.equals(remoteFileMd5);
+            fileUpdateInfo.setRemoteMd5(remoteFileMd5);
+            fileUpdateInfo.setUpdateStatus(isUpdateRequired ? 1 : 0);  // 0表示无需更新,1表示待更新
+            fileUpdateInfoMapper.updateById(fileUpdateInfo);
+            return isUpdateRequired;
+        }
+    }
+
+    //下载更新
+    @Override
+    public void performFileUpdate(Long id) throws Exception {
+        FileUpdateInfo fileUpdateInfo = fileUpdateInfoMapper.selectById(id);
+        if (fileUpdateInfo == null) {
+            throw new FileNotFoundException("文件信息未找到:id=" + id);
+        }
+
+        String localFilePath = fileUpdateInfo.getFilePath(); // 使用新的 getFilePath 方法
+        String fileName = fileUpdateInfo.getFileName();
+        String remoteUrl = remoteUrlBase + fileName;
+
+        try {
+            // 获取 JAR 文件所在的目录
+            String serviceDir = FileUpdateInfo.getServiceDir();
+            String backupDirPath = serviceDir + File.separator + "backup";
+            File backupDir = new File(backupDirPath);
+            if (!backupDir.exists()) {
+                boolean created = backupDir.mkdirs();
+                if (!created) {
+                    throw new IOException("无法创建备份目录");
+                }
+            }
+
+            File originalFile = new File(localFilePath);
+            if (originalFile.exists()) {
+                String timestamp = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());
+                String backupFilePath = backupDirPath + File.separator + fileName + "." + timestamp;
+                Files.move(originalFile.toPath(), Paths.get(backupFilePath), StandardCopyOption.REPLACE_EXISTING);
+                System.out.println("旧文件已备份到: " + backupFilePath);
+            }
+
+            downloadFileFromRemote(remoteUrl, localFilePath);
+
+            String newFileMd5 = DigestUtils.md5Hex(new FileInputStream(localFilePath));
+            fileUpdateInfo.setFileMd5(newFileMd5);
+            fileUpdateInfo.setCreateTime(fileUpdateInfo.getCreateTime());
+            fileUpdateInfo.setUpdateTime(LocalDateTime.now());
+            fileUpdateInfo.setUpdateStatus(0);
+
+            // 递增版本号
+            String currentVersion = fileUpdateInfo.getVersion();
+            String[] versionParts = currentVersion.substring(1).split("\\."); // 去掉 'v' 并拆分版本号
+            int major = Integer.parseInt(versionParts[0]);
+            int minor = Integer.parseInt(versionParts[1]);
+            int patch = Integer.parseInt(versionParts[2]) + 1; // 小版本号加 1
+            fileUpdateInfo.setVersion("v" + major + "." + minor + "." + patch);
+
+            fileUpdateInfoMapper.updateById(fileUpdateInfo);
+
+            // 下载完成后重启服务
+            controlApplication(fileName, "restart");
+
+        } catch (FileNotFoundException e) {
+            throw new Exception("原因: " + e.getMessage(), e);
+        } catch (IOException e) {
+            throw new Exception("原因: " + e.getMessage(), e);
+        } catch (Exception e) {
+            throw new Exception("原因: 远程仓库未找到服务包");
+        }
+    }
+
+    private void downloadFileFromRemote(String remoteUrl, String localFilePath) throws Exception {
+        URL url = new URL(remoteUrl);
+        Path path = Paths.get(localFilePath);
+        try {
+            Files.copy(url.openStream(), path, StandardCopyOption.REPLACE_EXISTING);
+            System.out.println("文件下载成功");
+        } catch (IOException e) {
+            System.err.println("文件下载失败" + ",原因: " + e.getMessage());
+            throw new Exception("文件下载失败");
+        }
+    }
+
+    private String getRemoteFileMd5(String fileName) throws Exception {
+        String remoteUrl = remoteUrlBase + fileName;
+        System.out.println("远程文件 URL: " + remoteUrl);
+        URL url = new URL(remoteUrl);
+        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+        connection.setRequestProperty("Cache-Control", "no-cache");
+        try (InputStream in = connection.getInputStream()) {
+            return DigestUtils.md5Hex(in);
+        }
+    }
+
+    @Override
+    public CommonPage<FileUpdateInfo> getAllFiles(int current, int size) throws Exception {
+        // 使用 MyBatis-Plus 的分页功能
+        Page<FileUpdateInfo> page = new Page<>(current, size);
+        IPage<FileUpdateInfo> result = fileUpdateInfoMapper.selectPage(page, null);
+
+        // 更新每个文件的运行状态
+        for (FileUpdateInfo fileUpdateInfo : result.getRecords()) {
+            checkServiceStatus(fileUpdateInfo);
+        }
+
+        // 将 MyBatis-Plus 的分页结果转换为 CommonPage
+        return new CommonPage<>(
+                result.getRecords(),
+                (int) result.getTotal(),
+                size,
+                current
+        );
+    }
+
+    @Override
+    public CommonPage<FileUpdateInfo> getFilesByFileNameContaining(String fileName, int current, int size) throws Exception {
+        // 使用 MyBatis-Plus 的分页功能
+        Page<FileUpdateInfo> page = new Page<>(current, size);
+        QueryWrapper<FileUpdateInfo> queryWrapper = new QueryWrapper<>();
+        queryWrapper.like("file_name", fileName);
+        IPage<FileUpdateInfo> result = fileUpdateInfoMapper.selectPage(page, queryWrapper);
+
+        // 更新每个文件的运行状态
+        for (FileUpdateInfo fileUpdateInfo : result.getRecords()) {
+            checkServiceStatus(fileUpdateInfo);
+        }
+
+        // 将 MyBatis-Plus 的分页结果转换为 CommonPage
+        return new CommonPage<>(
+                result.getRecords(),
+                (int) result.getTotal(),
+                size,
+                current
+        );
+    }
+
+    @Override
+    public FileUpdateInfo getFileById(Long id) {
+        return fileUpdateInfoMapper.selectById(id);
+    }
+
+    @Override
+    public void deleteFileById(Long id) {
+        fileUpdateInfoMapper.deleteById(id);
+    }
+
+    @Override
+    public void controlApplication(String fileName, String action) throws Exception {
+        String osName = System.getProperty("os.name").toLowerCase();
+
+        if (osName.contains("linux") || osName.contains("unix")) {
+            // Linux 系统
+            String command = "sh " + linuxContralScript + " " + action + " " + fileName;
+            Runtime.getRuntime().exec(command);
+        } else if (osName.contains("windows")) {
+            // Windows 系统
+            String command;
+            switch (action.toLowerCase()) {
+                case "start":
+                    command = windowsStartScript + " " + fileName;
+                    break;
+                case "stop":
+                    command = windowsStopScript + " " + fileName;
+                    break;
+                case "restart":
+                    // Windows 系统没有单独的重启脚本,需要先停止再启动
+                    Runtime.getRuntime().exec(windowsStopScript + " " + fileName);
+                    Thread.sleep(3000); // 等待 3 秒,确保服务停止
+                    Runtime.getRuntime().exec(windowsStartScript + " " + fileName);
+                    return;
+                default:
+                    throw new IllegalArgumentException("不支持的操作类型: " + action);
+            }
+            Runtime.getRuntime().exec(command);
+        } else {
+            throw new Exception("不支持的操作系统: " + osName);
+        }
+
+        // 等待操作完成
+        long startTime = System.currentTimeMillis();
+        long timeout = 8000; // 最长等待时间 8 秒
+        boolean isActionCompleted = false;
+
+        while (System.currentTimeMillis() - startTime < timeout) {
+            int currentStatus = getFileStatus(fileName); // 获取当前服务状态
+            if (action.equals("start") && currentStatus == 1) {
+                isActionCompleted = true;
+                break; // 服务已启动
+            } else if (action.equals("stop") && currentStatus == 2) {
+                isActionCompleted = true;
+                break; // 服务已停止
+            } else if (action.equals("restart") && currentStatus == 1) {
+                isActionCompleted = true;
+                break; // 服务已重启
+            }
+
+            Thread.sleep(500); // 每隔 500 毫秒检测一次状态
+        }
+
+        if (!isActionCompleted) {
+            throw new Exception("操作超时,服务状态未达到预期");
+        }
+    }
+
+    //扫描服务所在目录下的文件
+    @Override
+    public CommonPage<FileWithId> scanFilesInServiceDir(int current, int size) throws Exception {
+        // 获取 JAR 文件所在的目录
+        String serviceDir = FileUpdateInfo.getServiceDir();
+        File dir = new File(serviceDir);
+
+        if (!dir.exists() || !dir.isDirectory()) {
+            throw new Exception("无法找到服务目录: " + serviceDir);
+        }
+
+        // 获取目录中的所有文件名
+        File[] files = dir.listFiles();
+        if (files == null) {
+            throw new Exception("无法读取目录内容: " + serviceDir);
+        }
+
+        // 提取文件名
+        List<String> fileNames = new ArrayList<>();
+        for (File file : files) {
+            if (file.isFile()) {
+                fileNames.add(file.getName());
+            }
+        }
+
+        // 查询数据库中已存在的文件名
+        List<String> existingFileNames = fileUpdateInfoMapper.selectList(null).stream()
+                .map(FileUpdateInfo::getFileName)
+                .collect(Collectors.toList());
+
+        // 从扫描结果中排除已存在的文件名
+        List<String> newFileNames = fileNames.stream()
+                .filter(fileName -> !existingFileNames.contains(fileName))
+                .collect(Collectors.toList());
+
+        // 对文件名列表进行分页处理
+        int total = newFileNames.size();
+        int start = (current - 1) * size;
+        int end = Math.min(start + size, total);
+
+        List<String> pageFileNames = newFileNames.subList(start, end);
+
+        // 创建包含 id 的文件信息列表
+        List<FileWithId> fileWithIds = new ArrayList<>();
+        for (int i = 0; i < pageFileNames.size(); i++) {
+            fileWithIds.add(new FileWithId((long) (start + i + 1), pageFileNames.get(i)));
+        }
+
+        // 返回分页结果
+        return new CommonPage<>(fileWithIds, total, size, current);
+    }
+
+
+    // 检测服务运行状态并更新到数据库
+    private void checkServiceStatus(FileUpdateInfo fileUpdateInfo) {
+        String fileName = fileUpdateInfo.getFileName();
+        int fileStatus = getFileStatus(fileName); // 调用方法获取文件运行状态
+        fileUpdateInfo.setFileStatus(fileStatus); // 更新运行状态
+        fileUpdateInfoMapper.updateById(fileUpdateInfo); // 更新数据库
+    }
+
+    // 获取文件运行状态
+    @Override
+    public int getFileStatus(String fileName) {
+        String osName = System.getProperty("os.name").toLowerCase();
+
+        if (osName.contains("linux") || osName.contains("unix")) {
+            // Linux 系统
+            String command = "pgrep -f " + fileName;
+            try {
+                Process process = Runtime.getRuntime().exec(command);
+                BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
+                String line;
+                boolean isRunning = false;
+                while ((line = reader.readLine()) != null) {
+                    if (line != null && !line.isEmpty()) {
+                        isRunning = true;
+                        break;
+                    }
+                }
+                return isRunning ? 1 : 2; // 1: 运行中,2: 已停止
+            } catch (IOException e) {
+                logger.error("Failed to execute command: {}", command, e);
+            }
+        } else if (osName.contains("windows")) {
+            // Windows 系统
+            String command = "sc query " + fileName;
+            try {
+                Process process = Runtime.getRuntime().exec(command);
+                BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
+                String line;
+                boolean isRunning = false;
+                while ((line = reader.readLine()) != null) {
+                    if (line.contains("RUNNING")) {
+                        isRunning = true;
+                        break;
+                    } else if (line.contains("STOPPED")) {
+                        break;
+                    }
+                }
+                return isRunning ? 1 : 2; // 1: 运行中,2: 已停止
+            } catch (IOException e) {
+                logger.error("Failed to execute command: {}", command, e);
+            }
+        } else {
+            logger.warn("Unsupported operating system: {}", osName);
+        }
+        return 0; // 未知
+    }
+}

+ 241 - 0
base-modules/service-file/src/main/java/com/ruoyi/file/service/impl/FilesServiceImpl.java

@@ -0,0 +1,241 @@
+package com.ruoyi.file.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.file.mapper.FilesMapper;
+import com.ruoyi.file.service.FileUploadResponse;
+import com.ruoyi.file.service.FilesService;
+import com.ruoyi.file.domain.FilesUpload;
+import com.usky.common.core.bean.CommonPage;
+import com.usky.common.security.utils.SecurityUtils;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.*;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+
+@Service
+public class FilesServiceImpl extends ServiceImpl<FilesMapper, FilesUpload> implements FilesService {
+    @Value("${file.path}")
+    private String filesUploadPath;//获取文件路径
+
+    @Value("${file.domain}")
+    private String filesUploadDomain;//文件域名
+
+    @Value("${file.prefix}")
+    private String filesPrefix;//文件前缀
+
+
+
+    @Override
+    public FileUploadResponse upload(MultipartFile file, Long userid, String userName, String refererPath) {
+
+        // 获取当前登录用户昵称(如果可用)
+//        String userName = SecurityUtils.getUsername();
+
+        // 文件夹路径名称
+        String originalFilename = file.getOriginalFilename();
+
+        //文件大小
+        double size = file.getSize() / (1024.0);
+
+        // 获取当前日期时间
+        LocalDateTime now = LocalDateTime.now();
+//        String timestamp = now.format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
+
+        //文件类型
+        String type = originalFilename.substring(originalFilename.lastIndexOf(".") + 1).toLowerCase();
+
+        // 按照年月创建文件夹
+        String yearMonth = now.format(DateTimeFormatter.ofPattern("yyyyMM"));
+        // 获取每月递增值
+        int monthIncrement = getMonthIncrement(yearMonth);
+        // 新文件名格式:时间戳+每月递增值+文件类型
+//        String fileUuid = timestamp + "A" + String.format("%04d", monthIncrement) + "." + type;
+
+        // 将相对路径转化为绝对路径
+        String destPath = filesUploadPath + "/" + yearMonth;
+
+        // 新的文件地址,绝对路径+新的文件名称
+//        File uploadFile = new File(destPath + "/" + fileUuid);
+        File uploadFile;
+        String fileUuid = originalFilename; // 初始使用原文件名
+        int count = 1; // 用于生成重复文件名的序号
+        while (true) {
+            uploadFile = new File(destPath + "/" + fileUuid);
+            if (!uploadFile.exists()) { // 如果文件不存在,直接使用该文件名
+                break;
+            } else { // 如果文件已存在,修改文件名
+                String nameWithoutType = originalFilename.substring(0, originalFilename.lastIndexOf("."));
+                fileUuid = nameWithoutType + "(" + count + ")." + type;
+                count++;
+            }
+        }
+
+        // 判断配置的文件目录是否存在,若不存在则创建一个新的文件目录
+        File parentFile = uploadFile.getParentFile();
+        if (!parentFile.exists()) {
+            parentFile.mkdirs();
+        }
+
+        try {
+            // 存储文件到本地磁盘
+            file.transferTo(uploadFile);
+
+            // 设置文件url
+            String url = filesUploadDomain + filesPrefix + "/" + yearMonth + "/" + fileUuid;
+
+            // 将文件存储到数据库
+            FilesUpload saveFile = new FilesUpload();
+            saveFile.setFilesName(originalFilename);
+            saveFile.setName(fileUuid);
+            saveFile.setPath(destPath);
+            saveFile.setType(type);
+            saveFile.setSize(size); // (单位:KB)
+            saveFile.setUrl(url);
+            saveFile.setEnable(true);
+            saveFile.setIsDelete(0);
+            saveFile.setRefererPath(refererPath);
+            saveFile.setCreateId(userid);
+            saveFile.setCreateBy(userName);
+            saveFile.setCreateTime(LocalDateTime.now());
+            saveFile.setUpdateId(null);
+            saveFile.setUpdateBy(null);
+            saveFile.setUpdateTime(null);
+            // 保存操作
+            save(saveFile);
+
+            // 返回 FileUploadResponse 对象
+            return new FileUploadResponse(originalFilename, url);
+        } catch (IOException e) {
+            e.printStackTrace();
+            return null;
+        }
+    }
+
+    /**
+     * 获取每月递增值
+     * @param yearMonth 年月(格式:yyyyMM)
+     * @return 递增值
+     */
+    private int getMonthIncrement(String yearMonth) {
+        // 目标文件夹路径
+        String destPath = filesUploadPath + "/" + yearMonth;
+        File folder = new File(destPath);
+
+        // 如果文件夹不存在,则递增值从1开始
+        if (!folder.exists()) {
+            folder.mkdirs();
+            return 1;
+        }
+
+        // 获取文件夹中已有的文件数量
+        File[] files = folder.listFiles();
+        if (files == null || files.length == 0) {
+            return 1;
+        }
+
+        // 递增值为文件夹中现有文件数量 + 1
+        return files.length + 1;
+    }
+
+    @Override
+    public void deleteFile(Integer id, Long userid, String userName) {
+        try {
+            // 根据 id 查询文件信息
+            FilesUpload file = getById(id);
+            if (file == null) {
+                throw new RuntimeException("文件不存在,无法删除");
+            }
+
+            // 删除本地文件
+            String filePath = file.getPath() + "/" + file.getName();
+            File localFile = new File(filePath);
+            if (localFile.exists()) {
+                if (!localFile.delete()) {
+                    throw new RuntimeException("文件删除失败");
+                }
+            }
+
+            // 更新数据库记录
+            FilesUpload updateFile = new FilesUpload();
+            updateFile.setId(file.getId());
+            updateFile.setFilesName(file.getFilesName());
+            updateFile.setName(file.getName());
+            updateFile.setPath(file.getPath());
+            updateFile.setType(file.getType());
+            updateFile.setSize(file.getSize());
+            updateFile.setUrl(file.getUrl());
+            updateFile.setEnable(false);
+            updateFile.setIsDelete(1); // 设置为已删除
+            updateFile.setRefererPath(file.getRefererPath());
+            updateFile.setCreateId(file.getCreateId());
+            updateFile.setCreateBy(file.getCreateBy());
+            updateFile.setCreateTime(file.getCreateTime()); // 保留原始的 createTime
+            updateFile.setUpdateId(userid);
+            updateFile.setUpdateBy(userName);
+            updateFile.setUpdateTime(LocalDateTime.now());
+
+            // 提交更新到数据库
+            updateById(updateFile); // 调用 updateById 方法更新数据库记录
+        } catch (Exception e) {
+            throw new RuntimeException("删除文件失败:" + e.getMessage());
+        }
+    }
+
+    @Override
+    public CommonPage<FilesUpload> queryFiles(String filesName, LocalDateTime startTime, LocalDateTime endTime, Boolean isDeleted, String fileType, String userName, int current, int size) {
+        QueryWrapper<FilesUpload> queryWrapper = new QueryWrapper<>();
+
+        // 默认查询未删除的文件
+        if (isDeleted == null) {
+            queryWrapper.eq("is_delete", 0);
+        } else {
+            queryWrapper.eq("is_delete", isDeleted ? 1 : 0);
+        }
+
+        if (filesName != null && !filesName.isEmpty()) {
+            queryWrapper.like("files_name", filesName);
+        }
+
+        if (startTime != null && endTime != null) {
+            queryWrapper.ge("create_time", startTime); // 大于等于起始时间
+            queryWrapper.le("create_time", endTime);   // 小于等于结束时间
+        } else if (startTime != null) {
+            queryWrapper.ge("create_time", startTime); // 只有起始时间
+        } else if (endTime != null) {
+            queryWrapper.le("create_time", endTime);   // 只有结束时间
+        }
+
+        if (fileType != null && !fileType.isEmpty()) {
+            queryWrapper.eq("type", fileType);
+        }
+
+        if (userName != null && !userName.isEmpty()) {
+            queryWrapper.like("create_by", userName);
+        }
+
+        // 按照创建时间倒序排列
+        queryWrapper.orderByDesc("create_time");
+
+        // 创建分页请求对象
+        Page<FilesUpload> page = new Page<>(current, size);
+
+        // 执行分页查询
+        IPage<FilesUpload> iPage = baseMapper.selectPage(page, queryWrapper);
+
+        // 将 MyBatis Plus 的 IPage 转换为 CommonPage
+        CommonPage<FilesUpload> commonPage = new CommonPage<>();
+        commonPage.setRecords(iPage.getRecords());
+        commonPage.setTotal(iPage.getTotal());
+        commonPage.setSize(iPage.getSize());
+        commonPage.setCurrent(iPage.getCurrent());
+
+        return commonPage;
+    }
+
+}

+ 202 - 202
base-modules/service-file/src/main/java/com/ruoyi/file/utils/FileUploadUtils.java

@@ -1,202 +1,202 @@
-package com.ruoyi.file.utils;
-
-
-import java.io.File;
-import java.io.IOException;
-import java.nio.file.Paths;
-import java.util.Date;
-import java.util.Objects;
-
-import com.ruoyi.common.core.exception.file.FileNameLengthLimitExceededException;
-import com.ruoyi.common.core.exception.file.InvalidExtensionException;
-import org.apache.commons.io.FilenameUtils;
-import com.ruoyi.common.core.exception.file.FileSizeLimitExceededException;
-import com.ruoyi.common.core.utils.DateUtils;
-import com.ruoyi.common.core.utils.StringUtils;
-import com.ruoyi.common.core.utils.file.MimeTypeUtils;
-import com.ruoyi.common.core.utils.uuid.Seq;
-import org.apache.commons.lang3.time.DateFormatUtils;
-import org.springframework.web.multipart.MultipartFile;
-
-
-/**
- * 文件上传工具类
- *
- * @author ruoyi
- */
-public class FileUploadUtils
-{
-    /**
-     * 默认大小 50M
-     */
-    public static final long DEFAULT_MAX_SIZE = 50 * 1024 * 1024;
-
-    /**
-     * 默认的文件名最大长度 100
-     */
-    public static final int DEFAULT_FILE_NAME_LENGTH = 100;
-
-    /**
-     * 根据文件路径上传
-     *
-     * @param baseDir 相对应用的基目录
-     * @param file 上传的文件
-     * @return 文件名称
-     * @throws IOException
-     */
-    public static final String upload(String baseDir, MultipartFile file) throws IOException
-    {
-        try
-        {
-            return upload(baseDir, file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION);
-        }
-        catch (Exception e)
-        {
-            throw new IOException(e.getMessage(), e);
-        }
-    }
-
-    /**
-     * 文件上传
-     *
-     * @param baseDir 相对应用的基目录
-     * @param file 上传的文件
-     * @param allowedExtension 上传文件类型
-     * @return 返回上传成功的文件名
-     * @throws FileSizeLimitExceededException 如果超出最大大小
-     * @throws FileNameLengthLimitExceededException 文件名太长
-     * @throws IOException 比如读写文件出错时
-     * @throws InvalidExtensionException 文件校验异常
-     */
-    public static final String upload(String baseDir, MultipartFile file, String[] allowedExtension)
-            throws FileSizeLimitExceededException, IOException, FileNameLengthLimitExceededException,
-            InvalidExtensionException
-    {
-        int fileNamelength = Objects.requireNonNull(file.getOriginalFilename()).length();
-        if (fileNamelength > FileUploadUtils.DEFAULT_FILE_NAME_LENGTH)
-        {
-            throw new FileNameLengthLimitExceededException(FileUploadUtils.DEFAULT_FILE_NAME_LENGTH);
-        }
-
-        assertAllowed(file, allowedExtension);
-
-        String fileName = extractFilename(file);
-
-        String absPath = getAbsoluteFile(baseDir, fileName).getAbsolutePath();
-        file.transferTo(Paths.get(absPath));
-        return getPathFileName(fileName);
-    }
-
-    /**
-     * 编码文件名
-     */
-    public static final String extractFilename(MultipartFile file)
-    {
-//        return StringUtils.format("{}/{}_{}.{}", DateUtils.datePath(),
-//                FilenameUtils.getBaseName(file.getOriginalFilename()), Seq.getId(Seq.uploadSeqType), getExtension(file));
-        String datePath = DateFormatUtils.format(new Date(), "yyyyMM");
-        return StringUtils.format("{}/{}.{}",datePath , Seq.getId(Seq.uploadSeqType), getExtension(file));
-    }
-
-    private static final File getAbsoluteFile(String uploadDir, String fileName) throws IOException
-    {
-        File desc = new File(uploadDir + File.separator + fileName);
-
-        if (!desc.exists())
-        {
-            if (!desc.getParentFile().exists())
-            {
-                desc.getParentFile().mkdirs();
-            }
-        }
-        return desc.isAbsolute() ? desc : desc.getAbsoluteFile();
-    }
-
-    private static final String getPathFileName(String fileName) throws IOException
-    {
-        String pathFileName = "/" + fileName;
-        return pathFileName;
-    }
-
-    /**
-     * 文件大小校验
-     *
-     * @param file 上传的文件
-     * @throws FileSizeLimitExceededException 如果超出最大大小
-     * @throws InvalidExtensionException 文件校验异常
-     */
-    public static final void assertAllowed(MultipartFile file, String[] allowedExtension)
-            throws FileSizeLimitExceededException, InvalidExtensionException
-    {
-        long size = file.getSize();
-        if (size > DEFAULT_MAX_SIZE)
-        {
-            throw new FileSizeLimitExceededException(DEFAULT_MAX_SIZE/1024/1024);
-        }
-
-        String fileName = file.getOriginalFilename();
-        String extension = getExtension(file);
-        if (allowedExtension != null && !isAllowedExtension(extension, allowedExtension))
-        {
-            if (allowedExtension == MimeTypeUtils.IMAGE_EXTENSION)
-            {
-                throw new InvalidExtensionException.InvalidImageExtensionException(allowedExtension, extension,
-                        fileName);
-            }
-            else if (allowedExtension == MimeTypeUtils.FLASH_EXTENSION)
-            {
-                throw new InvalidExtensionException.InvalidFlashExtensionException(allowedExtension, extension,
-                        fileName);
-            }
-            else if (allowedExtension == MimeTypeUtils.MEDIA_EXTENSION)
-            {
-                throw new InvalidExtensionException.InvalidMediaExtensionException(allowedExtension, extension,
-                        fileName);
-            }
-            else if (allowedExtension == MimeTypeUtils.VIDEO_EXTENSION)
-            {
-                throw new InvalidExtensionException.InvalidVideoExtensionException(allowedExtension, extension,
-                        fileName);
-            }
-            else
-            {
-                throw new InvalidExtensionException(allowedExtension, extension, fileName);
-            }
-        }
-    }
-
-    /**
-     * 判断MIME类型是否是允许的MIME类型
-     *
-     * @param extension 上传文件类型
-     * @param allowedExtension 允许上传文件类型
-     * @return true/false
-     */
-    public static final boolean isAllowedExtension(String extension, String[] allowedExtension)
-    {
-        for (String str : allowedExtension)
-        {
-            if (str.equalsIgnoreCase(extension))
-            {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    /**
-     * 获取文件名的后缀
-     *
-     * @param file 表单文件
-     * @return 后缀名
-     */
-    public static final String getExtension(MultipartFile file)
-    {
-        String extension = FilenameUtils.getExtension(file.getOriginalFilename());
-        if (StringUtils.isEmpty(extension))
-        {
-            extension = MimeTypeUtils.getExtension(Objects.requireNonNull(file.getContentType()));
-        }
-        return extension;
-    }
-}
+//package com.ruoyi.file.utils;
+//
+//
+//import java.io.File;
+//import java.io.IOException;
+//import java.nio.file.Paths;
+//import java.util.Date;
+//import java.util.Objects;
+//
+//import com.ruoyi.common.core.exception.file.FileNameLengthLimitExceededException;
+//import com.ruoyi.common.core.exception.file.InvalidExtensionException;
+//import org.apache.commons.io.FilenameUtils;
+//import com.ruoyi.common.core.exception.file.FileSizeLimitExceededException;
+//import com.ruoyi.common.core.utils.DateUtils;
+//import com.ruoyi.common.core.utils.StringUtils;
+//import com.ruoyi.common.core.utils.file.MimeTypeUtils;
+//import com.ruoyi.common.core.utils.uuid.Seq;
+//import org.apache.commons.lang3.time.DateFormatUtils;
+//import org.springframework.web.multipart.MultipartFile;
+//
+//
+///**
+// * 文件上传工具类
+// *
+// * @author ruoyi
+// */
+//public class FileUploadUtils
+//{
+//    /**
+//     * 默认大小 50M
+//     */
+//    public static final long DEFAULT_MAX_SIZE = 50 * 1024 * 1024;
+//
+//    /**
+//     * 默认的文件名最大长度 100
+//     */
+//    public static final int DEFAULT_FILE_NAME_LENGTH = 100;
+//
+//    /**
+//     * 根据文件路径上传
+//     *
+//     * @param baseDir 相对应用的基目录
+//     * @param file 上传的文件
+//     * @return 文件名称
+//     * @throws IOException
+//     */
+//    public static final String upload(String baseDir, MultipartFile file) throws IOException
+//    {
+//        try
+//        {
+//            return upload(baseDir, file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION);
+//        }
+//        catch (Exception e)
+//        {
+//            throw new IOException(e.getMessage(), e);
+//        }
+//    }
+//
+//    /**
+//     * 文件上传
+//     *
+//     * @param baseDir 相对应用的基目录
+//     * @param file 上传的文件
+//     * @param allowedExtension 上传文件类型
+//     * @return 返回上传成功的文件名
+//     * @throws FileSizeLimitExceededException 如果超出最大大小
+//     * @throws FileNameLengthLimitExceededException 文件名太长
+//     * @throws IOException 比如读写文件出错时
+//     * @throws InvalidExtensionException 文件校验异常
+//     */
+//    public static final String upload(String baseDir, MultipartFile file, String[] allowedExtension)
+//            throws FileSizeLimitExceededException, IOException, FileNameLengthLimitExceededException,
+//            InvalidExtensionException
+//    {
+//        int fileNamelength = Objects.requireNonNull(file.getOriginalFilename()).length();
+//        if (fileNamelength > FileUploadUtils.DEFAULT_FILE_NAME_LENGTH)
+//        {
+//            throw new FileNameLengthLimitExceededException(FileUploadUtils.DEFAULT_FILE_NAME_LENGTH);
+//        }
+//
+//        assertAllowed(file, allowedExtension);
+//
+//        String fileName = extractFilename(file);
+//
+//        String absPath = getAbsoluteFile(baseDir, fileName).getAbsolutePath();
+//        file.transferTo(Paths.get(absPath));
+//        return getPathFileName(fileName);
+//    }
+//
+//    /**
+//     * 编码文件名
+//     */
+//    public static final String extractFilename(MultipartFile file)
+//    {
+////        return StringUtils.format("{}/{}_{}.{}", DateUtils.datePath(),
+////                FilenameUtils.getBaseName(file.getOriginalFilename()), Seq.getId(Seq.uploadSeqType), getExtension(file));
+//        String datePath = DateFormatUtils.format(new Date(), "yyyyMM");
+//        return StringUtils.format("{}/{}.{}",datePath , Seq.getId(Seq.uploadSeqType), getExtension(file));
+//    }
+//
+//    private static final File getAbsoluteFile(String uploadDir, String fileName) throws IOException
+//    {
+//        File desc = new File(uploadDir + File.separator + fileName);
+//
+//        if (!desc.exists())
+//        {
+//            if (!desc.getParentFile().exists())
+//            {
+//                desc.getParentFile().mkdirs();
+//            }
+//        }
+//        return desc.isAbsolute() ? desc : desc.getAbsoluteFile();
+//    }
+//
+//    private static final String getPathFileName(String fileName) throws IOException
+//    {
+//        String pathFileName = "/" + fileName;
+//        return pathFileName;
+//    }
+//
+//    /**
+//     * 文件大小校验
+//     *
+//     * @param file 上传的文件
+//     * @throws FileSizeLimitExceededException 如果超出最大大小
+//     * @throws InvalidExtensionException 文件校验异常
+//     */
+//    public static final void assertAllowed(MultipartFile file, String[] allowedExtension)
+//            throws FileSizeLimitExceededException, InvalidExtensionException
+//    {
+//        long size = file.getSize();
+//        if (size > DEFAULT_MAX_SIZE)
+//        {
+//            throw new FileSizeLimitExceededException(DEFAULT_MAX_SIZE/1024/1024);
+//        }
+//
+//        String fileName = file.getOriginalFilename();
+//        String extension = getExtension(file);
+//        if (allowedExtension != null && !isAllowedExtension(extension, allowedExtension))
+//        {
+//            if (allowedExtension == MimeTypeUtils.IMAGE_EXTENSION)
+//            {
+//                throw new InvalidExtensionException.InvalidImageExtensionException(allowedExtension, extension,
+//                        fileName);
+//            }
+//            else if (allowedExtension == MimeTypeUtils.FLASH_EXTENSION)
+//            {
+//                throw new InvalidExtensionException.InvalidFlashExtensionException(allowedExtension, extension,
+//                        fileName);
+//            }
+//            else if (allowedExtension == MimeTypeUtils.MEDIA_EXTENSION)
+//            {
+//                throw new InvalidExtensionException.InvalidMediaExtensionException(allowedExtension, extension,
+//                        fileName);
+//            }
+//            else if (allowedExtension == MimeTypeUtils.VIDEO_EXTENSION)
+//            {
+//                throw new InvalidExtensionException.InvalidVideoExtensionException(allowedExtension, extension,
+//                        fileName);
+//            }
+//            else
+//            {
+//                throw new InvalidExtensionException(allowedExtension, extension, fileName);
+//            }
+//        }
+//    }
+//
+//    /**
+//     * 判断MIME类型是否是允许的MIME类型
+//     *
+//     * @param extension 上传文件类型
+//     * @param allowedExtension 允许上传文件类型
+//     * @return true/false
+//     */
+//    public static final boolean isAllowedExtension(String extension, String[] allowedExtension)
+//    {
+//        for (String str : allowedExtension)
+//        {
+//            if (str.equalsIgnoreCase(extension))
+//            {
+//                return true;
+//            }
+//        }
+//        return false;
+//    }
+//
+//    /**
+//     * 获取文件名的后缀
+//     *
+//     * @param file 表单文件
+//     * @return 后缀名
+//     */
+//    public static final String getExtension(MultipartFile file)
+//    {
+//        String extension = FilenameUtils.getExtension(file.getOriginalFilename());
+//        if (StringUtils.isEmpty(extension))
+//        {
+//            extension = MimeTypeUtils.getExtension(Objects.requireNonNull(file.getContentType()));
+//        }
+//        return extension;
+//    }
+//}

+ 1 - 1
base-modules/service-file/src/main/resources/bootstrap.yml

@@ -3,7 +3,7 @@ server:
   port: 9300
 
 # Spring
-spring: 
+spring:
   application:
     # 应用名称
     name: service-file

+ 5 - 0
base-modules/service-file/src/main/resources/mapper/file/FilesMapper.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.file.mapper.FilesMapper">
+
+</mapper>

+ 1 - 0
base-modules/service-job/src/main/resources/mapper/job/SysJobMapper.xml

@@ -41,6 +41,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 				AND invoke_target like concat('%', #{invokeTarget}, '%')
 			</if>
 		</where>
+		ORDER BY job_id DESC
 	</select>
 	
 	<select id="selectJobAll" resultMap="SysJobResult">

+ 17 - 4
base-modules/service-system/service-system-api/src/main/java/com/usky/system/RemoteMceService.java

@@ -2,6 +2,8 @@ package com.usky.system;
 
 
 import com.usky.common.core.bean.ApiResult;
+
+import com.usky.system.domain.MceRequestVO;
 import com.usky.system.factory.RemoteMceFallbackFactory;
 import org.springframework.cloud.openfeign.FeignClient;
 import org.springframework.http.MediaType;
@@ -11,19 +13,30 @@ import org.springframework.web.bind.annotation.RequestBody;
 
 /**
  * 消息服务
- * 
+ *
  * @author ruoyi
  */
 @FeignClient(contextId = "remoteMceService", value = "usky-system", fallbackFactory = RemoteMceFallbackFactory.class)
-public interface RemoteMceService
-{
+public interface RemoteMceService {
     /**
      * 新增消息推送
      *
      * @param mceInfo 消息信息
      * @return 结果
      */
-    @PostMapping(value = "/addMce",produces= MediaType.APPLICATION_JSON_UTF8_VALUE,consumes = "application/json;" +
+    @PostMapping(value = "/addMce", produces = MediaType.APPLICATION_JSON_UTF8_VALUE, consumes = "application/json;" +
             "charset=UTF-8")
     public ApiResult<Void> addMce(@RequestBody String mceInfo);
+
+    /**
+     * @description: 消息推送-新
+     * @author: fyc
+     * @email yuchuan.fu@chinausky.com
+     * @date: 2025/3/14 14:58
+     * @param: [mceInfo]
+     * @return: com.usky.common.core.bean.ApiResult<java.lang.Void>
+     **/
+    @PostMapping(value = "/addMceReceive")
+    ApiResult<Void> addMceReceive(MceRequestVO mceInfo);
+
 }

+ 125 - 0
base-modules/service-system/service-system-api/src/main/java/com/usky/system/domain/MceRequestVO.java

@@ -0,0 +1,125 @@
+package com.usky.system.domain;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.usky.common.core.bean.BaseEntity;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.extern.slf4j.Slf4j;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+import java.time.LocalDateTime;
+import java.util.List;
+
+/**
+ *
+ * @author fyc
+ * @email yuchuan.fu@chinausky.com
+ * @date 2025/3/13
+ */
+@EqualsAndHashCode(callSuper = true)
+@Slf4j
+@Data
+public class MceRequestVO extends BaseEntity {
+
+    /** 字典标签  */
+    private String infoTypeName;
+
+    /** 消息类型  */
+    @NotBlank(message = "消息类型 infoType 不能为空!")
+    private String infoType;
+
+    /** 消息标题  */
+    @NotBlank(message = "消息标题 infoTitle 不能为空!")
+    private String infoTitle;
+
+    /** 消息内容  */
+    @NotBlank(message = "消息内容 infoContent 不能为空!")
+    private String infoContent;
+
+    /** 用户名称
+     * 登录账号 loginAccount
+     * */
+    @NotBlank(message = "消息发布人 userName 不能为空!")
+    private String userName;
+
+    /** 消息详情id  */
+    @NotNull(message = "消息详情 id 不能为空!")
+    private Integer id;
+
+    /** 消息接收人userId集合  */
+    @NotNull(message = "消息接收人 userIds 不能为空!")
+    private List<Long> userIds;
+
+    /**
+     * ip地址
+     */
+    private String ipAddress;
+
+    /**
+     * 登录地址
+     */
+    private String loginAddress;
+
+    /**
+     * 登录方式
+     */
+    private String loginType;
+
+    /**
+     * 审批结果
+     */
+    private String approvalResult;
+
+    /**
+     * 流程名称
+     */
+    private String processName;
+
+    /**
+     * 审批节点
+     */
+    private String approvalNode;
+
+    /**
+     * 真实姓名
+     */
+    private String realName;
+
+    /**
+     * oa跳转类型 (todo我的待办、me我发起的、copy抄送我的)
+     */
+    private String oaType;
+
+    /**
+     * 设备id
+     */
+    private String deviceId;
+
+    /**
+     * 报警时间
+     */
+    private String alarmTime;
+
+    /**
+     * 备注
+     */
+    private String remark;
+
+    /**
+     * 报警发送方式(站内消息通知是默认的,1:APP,2:微信)
+     */
+    private String alarmSendType;
+
+    @Override
+    public String toString() {
+        ObjectMapper objectMapper = new ObjectMapper();
+        try {
+            return objectMapper.writeValueAsString(this);
+        } catch (JsonProcessingException e) {
+            log.error("MceRequestVO toString error: {}", e.getMessage());
+            return "{}";
+        }
+    }
+}

+ 7 - 0
base-modules/service-system/service-system-api/src/main/java/com/usky/system/domain/SysOperLogVO.java

@@ -47,6 +47,9 @@ public class SysOperLogVO extends BaseEntity
     /** 操作地址 */
     private String operIp;
 
+    /** 操作地点 */
+    private String operLocation;
+
     /** 请求参数 */
     private String operParam;
 
@@ -195,6 +198,10 @@ public class SysOperLogVO extends BaseEntity
         this.operIp = operIp;
     }
 
+    public String getOperLocation() { return operLocation; }
+
+    public void setOperLocation(String operLocation) { this.operLocation = operLocation; }
+
     public String getOperParam()
     {
         return operParam;

+ 25 - 0
base-modules/service-system/service-system-api/src/main/java/com/usky/system/domain/SysPerson.java

@@ -106,6 +106,31 @@ public class SysPerson implements Serializable {
      */
     private Date updateTime;
 
+    /**
+     * 图片数据(base64编码)
+     */
+    private String faceBase;
+
+    /**
+     * 验证次数(默认0)
+     */
+    private Integer vefNum;
+
+    /**
+     * 人脸备注
+     */
+    private String remark;
+
+    /**
+     * 人脸状态(0=可用,1=不可用)
+     */
+    private Integer faceStatus;
+
+    /**
+     * 卡号
+     */
+    private String cardNum;
+
     public static long getSerialVersionUID() {
         return serialVersionUID;
     }

+ 24 - 0
base-modules/service-system/service-system-api/src/main/java/com/usky/system/domain/SysPersonVo.java

@@ -105,5 +105,29 @@ public class SysPersonVo implements Serializable {
      */
     private LocalDateTime updateTime;
 
+    /**
+     * 图片数据(base64编码)
+     */
+    private String faceBase;
+
+    /**
+     * 验证次数(默认0)
+     */
+    private Integer vefNum;
+
+    /**
+     * 人脸备注
+     */
+    private String remark;
+
+    /**
+     * 人脸状态(0=可用,1=不可用)
+     */
+    private Integer faceStatus;
+
+    /**
+     * 卡号
+     */
+    private String cardNum;
 
 }

+ 13 - 0
base-modules/service-system/service-system-api/src/main/java/com/usky/system/domain/SysUserVO.java

@@ -133,6 +133,19 @@ public class SysUserVO extends BaseEntity {
      */
     private String fullName;
 
+    /**
+     * 是否打开登录通知(1 表示是,0 表示否,默认 0)
+     */
+    private Integer isLoginNotify;
+
+    public Integer getIsLoginNotify() {
+        return isLoginNotify;
+    }
+
+    public void setIsLoginNotify(Integer isLoginNotify) {
+        this.isLoginNotify = isLoginNotify;
+    }
+
     public String getAddress() {
         return address;
     }

+ 12 - 10
base-modules/service-system/service-system-api/src/main/java/com/usky/system/factory/RemoteMceFallbackFactory.java

@@ -3,6 +3,7 @@ package com.usky.system.factory;
 
 import com.usky.common.core.bean.ApiResult;
 import com.usky.system.RemoteMceService;
+import com.usky.system.domain.MceRequestVO;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.cloud.openfeign.FallbackFactory;
@@ -10,24 +11,25 @@ import org.springframework.stereotype.Component;
 
 /**
  * 消息服务降级处理
- * 
+ *
  * @author ruoyi
  */
 @Component
-public class RemoteMceFallbackFactory implements FallbackFactory<RemoteMceService>
-{
+public class RemoteMceFallbackFactory implements FallbackFactory<RemoteMceService> {
     private static final Logger log = LoggerFactory.getLogger(RemoteMceFallbackFactory.class);
 
     @Override
-    public RemoteMceService create(Throwable throwable)
-    {
+    public RemoteMceService create(Throwable throwable) {
         log.error("用户服务调用失败:{}", throwable.getMessage());
-        return new RemoteMceService()
-        {
+        return new RemoteMceService() {
             @Override
-            public ApiResult<Void> addMce(String mceInfo)
-            {
-                return ApiResult.error("500","新增消息失败:" + throwable.getMessage());
+            public ApiResult<Void> addMce(String mceInfo) {
+                return ApiResult.error("500", "新增消息失败:" + throwable.getMessage());
+            }
+
+            @Override
+            public ApiResult<Void> addMceReceive(MceRequestVO mceInfo) {
+                return ApiResult.error("500", "新增消息失败:" + throwable.getMessage());
             }
         };
     }

+ 15 - 3
base-modules/service-system/service-system-biz/pom.xml

@@ -59,10 +59,22 @@
             <artifactId>hutool-all</artifactId>
         </dependency>
 
+        <!-- 监控服务器资源状态 -->
         <dependency>
-            <groupId>org.json</groupId>
-            <artifactId>json</artifactId>
-            <version>20210307</version>
+            <groupId>com.github.oshi</groupId>
+            <artifactId>oshi-core</artifactId>
+            <version>3.9.1</version>
+        </dependency>
+        <dependency>
+            <groupId>net.java.dev.jna</groupId>
+            <artifactId>jna-platform</artifactId>
+            <version>4.5.2</version>
+        </dependency>
+        <!-- 支持 gzip,确保 Spring 能自动解压 -->
+        <dependency>
+            <groupId>net.sourceforge.pjl-comp-filter</groupId>
+            <artifactId>pjl-comp-filter</artifactId>
+            <version>1.7</version>
         </dependency>
     </dependencies>
 

+ 2 - 0
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/RuoYiSystemApplication.java

@@ -12,6 +12,7 @@ import org.springframework.context.ConfigurableApplicationContext;
 import org.springframework.context.annotation.ComponentScan;
 import org.springframework.context.annotation.EnableAspectJAutoProxy;
 import org.springframework.core.env.Environment;
+import org.springframework.scheduling.annotation.EnableAsync;
 
 import java.net.InetAddress;
 import java.net.UnknownHostException;
@@ -28,6 +29,7 @@ import java.net.UnknownHostException;
 @MapperScan(value = "com.usky.system.mapper")
 @ComponentScan(basePackages = {"com.usky"})
 @SpringBootApplication
+@EnableAsync
 public class RuoYiSystemApplication
 {
     private static final Logger LOGGER = LoggerFactory.getLogger(RuoYiSystemApplication.class);

+ 8 - 1
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/constant/constant.java

@@ -17,11 +17,18 @@ public class constant {
     public static final String WE_CHAT_ACCESS_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s";
     // 微信公众号消息推送地址
     public static final String WE_CHAT_REQUEST_URL = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=%s";
-    // 微信公众号推送消息模板id
+    // 微信公众号推送-告警-消息模板id
     public static final String WE_CHAT_TEMPLATE_ID = "FmrNuMzgh0E8bWg1j8a2R3zTmRarHYtZ72TSzPrF9Iw";
+    // 微信公众号推送-OA-消息模板id
+    public static final String WE_CHAT_OA_TEMPLATE_ID = "RDahJYyDGpQKEn6vzdifS9u9F-vxA6FOIIDe1cUw8WU";
+    // 微信公众号推送-报告提醒(工单)-消息模板id
+    public static final String WE_CHAT_WORK_TEMPLATE_ID = "0J7pBGkXq5nCEVsc9L6HBmfmUrO4BEOk-3d5WCndWZk";
+    // 微信公众号推送-登录-消息模板id
+    public static final String WE_CHAT_LOGIN_TEMPLATE_ID = "7o6J1_0gi89RsW3sR7Q853KTaWYT7Yu-jXjLnHbcB8M";
     // 微信公众号的消息回调地址(这儿可根据业务需求自定义动作,可选)
     public static final String WE_CHAT_CUSTOMER_CALL_URL = "https://manager.usky.cn/mobile/#/pages/common/appMessage/index?type=%s&typeName=%s&id=%s";
     public static final String WE_CHAT_CUSTOMER_CALL_URL1 = "https://manager.usky.cn/mobile/#/pages/common/appMessage/index?type=%s&id=%s";
+    public static final String WE_CHAT_CUSTOMER_CALL_URL3 = "https://manager.usky.cn/mobile/#/pages/common/appMessage/index?type=%s&typeName=%s&id=%s&oaType=%s";
     // 微信公众号的主题颜色
     public static final String WE_CHAT_TOP_COLOR = "#A349A4";
     // 微信公众号微信用户授权地址

+ 8 - 1
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/controller/api/SysMceControllerApi.java

@@ -2,15 +2,16 @@ package com.usky.system.controller.api;
 
 import com.usky.common.core.bean.ApiResult;
 import com.usky.system.RemoteMceService;
+import com.usky.system.domain.MceRequestVO;
 import com.usky.system.service.MceReceiveService;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RestController;
 
 
 @RestController
 public class SysMceControllerApi implements RemoteMceService {
 
-
     @Autowired
     private MceReceiveService mceReceiveService;
 
@@ -19,4 +20,10 @@ public class SysMceControllerApi implements RemoteMceService {
         mceReceiveService.add(mceInfo);
         return ApiResult.success();
     }
+
+    @Override
+    public ApiResult<Void> addMceReceive(@RequestBody MceRequestVO mceRequestVO) {
+        mceReceiveService.addMceReceive(mceRequestVO);
+        return ApiResult.success();
+    }
 }

+ 1 - 1
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/controller/web/AuthorityConfigController.java

@@ -78,7 +78,7 @@ public class AuthorityConfigController {
     @GetMapping("getMobileConfigMenuList")
     public ApiResult<Map<String, Object>> getMobileConfigMenuList(@RequestParam(value = "platformId") Integer platformId,
                                                                      @RequestParam(value = "tenantId") Integer tenantId) {
-        List<SysMobileMenu> menus =sysPlatformMenuService.getMobilePlatformMenuList(platformId);
+        List<SysMobileMenu> menus =sysPlatformMenuService.getMobilePlatformMenuList(tenantId);
         Map<String, Object> ajax = new HashMap<>();
         ajax.put("checkedKeys", sysPlatformMenuService.selectMobilePlatformMenu(tenantId));
         ajax.put("menus", menuService.buildMobileMenuTreeSelect(menus));

+ 52 - 19
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/controller/web/MceReceiveController.java

@@ -7,7 +7,9 @@ import com.usky.common.log.annotation.Log;
 import com.usky.common.log.enums.BusinessType;
 import com.usky.system.domain.MceReceive;
 import com.usky.system.service.MceReceiveService;
+import com.usky.system.service.vo.MceReceiveResponseVO;
 import io.swagger.models.auth.In;
+import org.apache.ibatis.annotations.Param;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 
@@ -33,7 +35,7 @@ public class MceReceiveController {
     /**
      * 消息列表分页
      * @param infoTitle  消息标题
-     * @param infoType  消息标题
+     * @param infoType  消息类型
      * @param startTime  开始时间
      * @param endTime  开始时间
      * @param current      当前页
@@ -45,11 +47,11 @@ public class MceReceiveController {
                                                  @RequestParam(value = "infoType", required = false) String infoType,
                                                  @RequestParam(value = "startTime", required = false) String startTime,
                                                  @RequestParam(value = "endTime", required = false) String endTime,
-                                                 @RequestParam(value = "id",required = false) Integer id,
+                                                 @RequestParam(value = "id", required = false) Integer id,
+                                                 @RequestParam(value = "infoId", required = false) Integer infoId,
                                                  @RequestParam(value = "current", required = false, defaultValue = "1") Integer current,
-                                                 @RequestParam(value = "size", required = false, defaultValue = "10") Integer size)
-    {
-        return ApiResult.success(mceReceiveService.mceList(infoTitle, infoType,startTime, endTime, id,current, size));
+                                                 @RequestParam(value = "size", required = false, defaultValue = "10") Integer size) {
+        return ApiResult.success(mceReceiveService.mceList(infoTitle, infoType, startTime, endTime, id, infoId, current, size));
     }
 
     /**
@@ -68,9 +70,8 @@ public class MceReceiveController {
                                                        @RequestParam(value = "startTime", required = false) String startTime,
                                                        @RequestParam(value = "endTime", required = false) String endTime,
                                                        @RequestParam(value = "current", required = false, defaultValue = "1") Integer current,
-                                                       @RequestParam(value = "size", required = false, defaultValue = "10") Integer size)
-    {
-        return ApiResult.success(mceReceiveService.mceManageList(infoTitle, infoType,startTime, endTime, current, size));
+                                                       @RequestParam(value = "size", required = false, defaultValue = "10") Integer size) {
+        return ApiResult.success(mceReceiveService.mceManageList(infoTitle, infoType, startTime, endTime, current, size));
     }
 
     /**
@@ -83,9 +84,8 @@ public class MceReceiveController {
     @GetMapping("/mceManageById")
     public ApiResult<CommonPage<MceReceive>> mceManageById(@RequestParam(value = "id") Integer id,
                                                            @RequestParam(value = "current", required = false, defaultValue = "1") Integer current,
-                                                           @RequestParam(value = "size", required = false, defaultValue = "10") Integer size)
-    {
-        return ApiResult.success(mceReceiveService.mceManageById(id,current,size));
+                                                           @RequestParam(value = "size", required = false, defaultValue = "10") Integer size) {
+        return ApiResult.success(mceReceiveService.mceManageById(id, current, size));
     }
 
     /**
@@ -93,17 +93,26 @@ public class MceReceiveController {
      * @return
      */
     @GetMapping("/mceReceiveStatic")
-    public ApiResult<Map<String, Object>> mceReceiveStatic()
-    {
+    public ApiResult<Map<String, Object>> mceReceiveStatic() {
         return ApiResult.success(mceReceiveService.mceReceiveStatic());
     }
 
+    /**
+     * 消息中心分页接口
+     * @return
+     */
+    @GetMapping("/getMceReceiveList")
+    public ApiResult<CommonPage<MceReceiveResponseVO>> getMceReceiveList(@RequestParam(value = "pageNumber", required = false, defaultValue = "1") Integer pageNumber,
+                                                                         @RequestParam(value = "pageSize", required = false, defaultValue = "20") Integer pageSize) {
+        return ApiResult.success(mceReceiveService.getMceReceiveResponseVOList(pageNumber, pageSize));
+    }
+
     /**
      * 已读
      * @return
      */
     @PutMapping
-    ApiResult<Void> updateMceReceive(@RequestBody MceReceive mceReceive){
+    ApiResult<Void> updateMceReceive(@RequestBody MceReceive mceReceive) {
         mceReceiveService.updateMceReceive(mceReceive);
         return ApiResult.success();
     }
@@ -114,20 +123,44 @@ public class MceReceiveController {
      */
     @Log(title = "新增发布消息", businessType = BusinessType.INSERT)
     @PostMapping("/mceAdd")
-    ApiResult<Void> add(@RequestBody String mceReceive){
+    ApiResult<Void> add(@RequestBody String mceReceive) {
         mceReceiveService.add(mceReceive);
         return ApiResult.success();
     }
 
     /**
-     * 删除
+     * 消息发布-无需token
+     * @return
+     */
+    @PostMapping("/addMceNew")
+    ApiResult<Void> addNoToken(@RequestBody String mceNoToken) {
+        mceReceiveService.addNoToken(mceNoToken);
+        return ApiResult.success();
+    }
+
+
+    /**
+     * 删除消息及内容,并清空所有的消息接收表数据
      */
     @Log(title = "删除已发布消息", businessType = BusinessType.DELETE)
-    @DeleteMapping("/{id}")
-    public ApiResult<Void> removeById(@PathVariable("id") Integer id)
-    {
+    @DeleteMapping("/remove/{contentId}")
+    public ApiResult<Void> removeById(@PathVariable("contentId") Integer id) {
         mceReceiveService.removeById(id);
         return ApiResult.success();
     }
+
+    /**
+     * 删除一条消息
+     **/
+    @Log(title = "删除消息", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{id}")
+    public ApiResult<Void> deleteById(@PathVariable("id") Integer id) {
+        boolean f = mceReceiveService.deleteById(id);
+        if (f) {
+            return ApiResult.success();
+        } else {
+            return ApiResult.error("删除失败");
+        }
+    }
 }
 

+ 12 - 2
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/controller/web/SendSmsController.java

@@ -16,6 +16,7 @@ import com.usky.system.domain.SysMobileTenantConfig;
 import com.usky.system.domain.SysUser;
 import com.usky.system.mapper.SysUserMapper;
 import com.usky.system.service.ISysUserService;
+import org.springframework.beans.factory.annotation.Value;
 import com.usky.system.service.SysMobileTenantConfigService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.GetMapping;
@@ -47,13 +48,22 @@ public class SendSmsController {
     @Autowired
     private ISysUserService sysUserService;
 
+    @Value("${sms.ali.region-id}")
+    private String regionId;
+
+    @Value("${sms.ali.access-key-id}")
+    private String accessKeyId;
+
+    @Value("${sms.ali.access-key-secret}")
+    private String accessKeySecret;
+
     @GetMapping("/noteSending")
     public ApiResult<Void> noteSending(@RequestParam(value = "tenantId" ,required = false) Integer tenantId,@RequestParam(value = "phone") String phone) {
         if((tenantId != null) && !StringUtils.isBlank(phone)){
-            sysUserService.getAppUserInfo(null, tenantId, phone);
+            sysUserService.getAppUserInfo(null, tenantId, phone,null);
         }
 
-        DefaultProfile profile = DefaultProfile.getProfile("cn-beijing", "LTAI9WERPIFIlHDg", "p7SQ0rYpraebcdoJ0l3tOtYmmgrR4q");
+        DefaultProfile profile = DefaultProfile.getProfile(regionId, accessKeyId, accessKeySecret);
         String code = String.valueOf(new Random().nextInt(1000000));
         redisHelper.set(phone,code,300,TimeUnit.SECONDS);//key为手机号,value为验证码存储
         IAcsClient client = new DefaultAcsClient(profile);

+ 9 - 2
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/controller/web/SysDeptController.java

@@ -12,6 +12,7 @@ import com.usky.system.domain.SysUser;
 import com.usky.system.domain.constants.UserConstants;
 import com.usky.system.service.ISysDeptService;
 import com.usky.system.service.ISysUserService;
+import com.usky.system.service.vo.TreeNode;
 import org.apache.commons.lang3.ArrayUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.validation.annotation.Validated;
@@ -46,6 +47,12 @@ public class SysDeptController extends BaseController {
         return ApiResult.success(depts);
     }
 
+    @GetMapping("/deptList")
+    public ApiResult deptList(SysDept dept) {
+        List<SysDept> depts = deptService.selectDept(dept);
+        return ApiResult.success(depts);
+    }
+
     /**
      * 查询部门列表(排除节点)
      */
@@ -84,7 +91,7 @@ public class SysDeptController extends BaseController {
      * 获取部门人员下拉树列表
      */
     @GetMapping("/deptUserTreeSelect")
-    public ApiResult treeselect(SysDept dept, SysUser user) {
+    public ApiResult <List<TreeNode>> treeselect(SysDept dept, SysUser user) {
         List<SysDept> depts = deptService.deptList(dept);
         List<SysUser> users = iSysUserService.selectDUserList(user);
         return ApiResult.success(deptService.buildDeptUserTreeSelect(depts, users));
@@ -94,7 +101,7 @@ public class SysDeptController extends BaseController {
      * 部门人员下拉树-工时统计
      */
     @GetMapping("/jurisdictionDeptUserTree")
-    public ApiResult jurisdictionDeptUserTree(SysDept dept, SysUser user) {
+    public ApiResult <List<TreeNode>> jurisdictionDeptUserTree(SysDept dept, SysUser user) {
         List<SysDept> depts = deptService.selectDeptList(dept);
         List<SysUser> users = iSysUserService.selectUserList(user);
         return ApiResult.success(deptService.buildDeptUserTreeSelect(depts, users));

+ 3 - 1
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/controller/web/SysMenuController.java

@@ -17,6 +17,7 @@ import com.usky.system.domain.constants.UserConstants;
 import com.usky.system.model.LoginUser;
 import com.usky.system.service.ISysMenuService;
 import com.usky.system.service.ISysUserService;
+import com.usky.system.service.vo.PlatformRouterVo;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
@@ -176,7 +177,8 @@ public class SysMenuController extends BaseController
     @GetMapping("getRouters1")
     public ApiResult getRouters1()
     {
-        return ApiResult.success(menuService.buildPlatformMenus());
+        List<PlatformRouterVo> list = menuService.buildPlatformMenus();
+        return ApiResult.success(list);
     }
 
     /**

+ 226 - 4
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/controller/web/SysPersonController.java

@@ -1,9 +1,31 @@
 package com.usky.system.controller.web;
 
 
-import org.springframework.web.bind.annotation.RequestMapping;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.usky.common.core.exception.BusinessException;
+import com.usky.common.core.bean.ApiResult;
+import com.usky.system.controller.web.page.TableDataInfo;
+import com.usky.common.security.utils.SecurityUtils;
+import com.usky.system.domain.SysPerson;
+import com.usky.system.domain.SysUser;
+import com.usky.system.domain.SysUserPerson;
+import com.usky.system.service.ISysUserService;
+import com.usky.system.service.SysPersonService;
+import com.usky.system.service.SysUserPersonService;
+import com.usky.common.core.util.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.BeanUtils;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.bind.annotation.*;
 
-import org.springframework.stereotype.Controller;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.stream.Collectors;
 
 /**
  * <p>
@@ -13,9 +35,209 @@ import org.springframework.stereotype.Controller;
  * @author JCB
  * @since 2022-08-22
  */
-@Controller
+@RestController
 @RequestMapping("/sysPerson")
-public class SysPersonController {
+public class SysPersonController extends BaseController {
 
+    @Autowired
+    private SysPersonService sysPersonService;
+    @Autowired
+    private SysUserPersonService sysUserPersonService;
+    @Autowired
+    private ISysUserService sysUserService;
+
+    /**
+     * 人员列表(分页)
+     */
+    @GetMapping("/list")
+    public ApiResult<TableDataInfo> list(SysPerson person) {
+        startPage();
+        // 支持 fullName 模糊查询;其他字段保持按传入条件精确匹配
+        Long filterDeptId = person != null ? person.getDeptId() : null;
+
+        SysPerson queryEntity = new SysPerson();
+        if (person != null) {
+            BeanUtils.copyProperties(person, queryEntity);
+            // fullName 用 like 查询,避免 Wrappers.query(entity) 产生 fullName=xxx 的精确条件
+            queryEntity.setFullName(null);
+            // 部门、岗位以关联用户为准,不作为人员表列条件;部门筛选见下方按用户 dept_id 关联
+            queryEntity.setDeptId(null);
+            queryEntity.setPostId(null);
+        }
+        QueryWrapper<SysPerson> queryWrapper = Wrappers.query(queryEntity);
+        queryWrapper.lambda()
+                .like(person != null && StringUtils.isNotBlank(person.getFullName()),
+                        SysPerson::getFullName, person.getFullName());
+
+        // 按部门筛选:关联用户的 dept_id = filterDeptId
+        if (filterDeptId != null) {
+            LambdaQueryWrapper<SysUser> userQuery = Wrappers.<SysUser>lambdaQuery()
+                    .eq(SysUser::getDeptId, filterDeptId)
+                    .eq(SysUser::getDelFlag, "0");
+            Integer tenantId = SecurityUtils.getTenantId();
+            if (tenantId != null) {
+                userQuery.eq(SysUser::getTenantId, tenantId);
+            }
+            List<SysUser> deptUsers = sysUserService.list(userQuery);
+            if (deptUsers == null || deptUsers.isEmpty()) {
+                queryWrapper.apply("1 = 0");
+            } else {
+                List<Long> userIds = deptUsers.stream()
+                        .map(SysUser::getUserId)
+                        .filter(Objects::nonNull)
+                        .distinct()
+                        .collect(Collectors.toList());
+                List<SysUserPerson> deptRelations = sysUserPersonService.list(
+                        Wrappers.<SysUserPerson>lambdaQuery()
+                                .in(SysUserPerson::getUserId, userIds)
+                );
+                if (deptRelations == null || deptRelations.isEmpty()) {
+                    queryWrapper.apply("1 = 0");
+                } else {
+                    List<Integer> deptPersonIds = deptRelations.stream()
+                            .map(SysUserPerson::getPersonId)
+                            .filter(Objects::nonNull)
+                            .distinct()
+                            .collect(Collectors.toList());
+                    queryWrapper.lambda().in(SysPerson::getId, deptPersonIds);
+                }
+            }
+        }
+
+        List<SysPerson> list = sysPersonService.list(queryWrapper);
+
+        // 回显 userId,以及通过 userId 回显部门、岗位
+        if (list != null && !list.isEmpty()) {
+            List<Integer> personIds = list.stream()
+                    .map(SysPerson::getId)
+                    .filter(Objects::nonNull)
+                    .collect(Collectors.toList());
+            if (!personIds.isEmpty()) {
+                List<SysUserPerson> relations = sysUserPersonService.list(
+                        Wrappers.<SysUserPerson>lambdaQuery()
+                                .in(SysUserPerson::getPersonId, personIds)
+                );
+                final Map<Integer, Long> personUserMap;
+                if (relations != null && !relations.isEmpty()) {
+                    personUserMap = relations.stream()
+                            .collect(Collectors.toMap(
+                                    SysUserPerson::getPersonId,
+                                    SysUserPerson::getUserId,
+                                    (u1, u2) -> u1
+                            ));
+                    list.forEach(p -> {
+                        Long userId = personUserMap.get(p.getId());
+                        if (userId != null) {
+                            p.setUserId(userId);
+                        }
+                    });
+                } else {
+                    personUserMap = new HashMap<>();
+                }
+                sysPersonService.fillDeptAndPostForList(list, personUserMap);
+            }
+        }
+        return ApiResult.success(getDataTable(list));
+    }
+
+    /**
+     * 根据主键获取人员详情
+     */
+    @GetMapping("/{id}")
+    public ApiResult<SysPerson> getInfo(@PathVariable("id") Integer id) {
+        SysPerson person = sysPersonService.getById(id);
+        if (person != null) {
+            Long userId = null;
+            SysUserPerson userPerson = sysUserPersonService.getOne(
+                    Wrappers.<SysUserPerson>lambdaQuery()
+                            .eq(SysUserPerson::getPersonId, id)
+                            .last("limit 1")
+            );
+            if (userPerson != null) {
+                userId = userPerson.getUserId();
+                person.setUserId(userId);
+            }
+            sysPersonService.fillDeptAndPostFromUser(person, userId);
+        }
+        return ApiResult.success(person);
+    }
+
+    /**
+     * 新增人员并绑定用户
+     */
+    @PostMapping
+    @Transactional
+    public ApiResult<Void> add(@RequestBody SysPerson person) {
+        Long userId = person.getUserId();
+        if (Objects.isNull(userId)) {
+            throw new BusinessException("lack necessary param:userId is required!");
+        }
+        // 校验账户是否已被其他人员绑定
+        SysUserPerson existBind = sysUserPersonService.getOne(
+                Wrappers.<SysUserPerson>lambdaQuery()
+                        .eq(SysUserPerson::getUserId, userId)
+                        .last("limit 1")
+        );
+        if (existBind != null) {
+            throw new BusinessException("此账户已被其它人员绑定,请解绑后重试!");
+        }
+        // 先保存人员信息
+        sysPersonService.save(person);
+        // 新增用户-人员关联
+        SysUserPerson userPerson = new SysUserPerson();
+        userPerson.setUserId(userId);
+        userPerson.setPersonId(person.getId());
+        userPerson.setIsLoginNotify(0);
+        sysUserPersonService.save(userPerson);
+        return ApiResult.success();
+    }
+
+    /**
+     * 修改人员并更新绑定用户
+     */
+    @PutMapping
+    @Transactional
+    public ApiResult<Void> edit(@RequestBody SysPerson person) {
+        Long userId = person.getUserId();
+        if (Objects.isNull(userId)) {
+            throw new BusinessException("lack necessary param:userId is required!");
+        }
+        // 校验账户是否已被其他人员绑定(排除当前人员本身)
+        SysUserPerson existBind = sysUserPersonService.getOne(
+                Wrappers.<SysUserPerson>lambdaQuery()
+                        .eq(SysUserPerson::getUserId, userId)
+                        .last("limit 1")
+        );
+        if (existBind != null && !Objects.equals(existBind.getPersonId(), person.getId())) {
+            throw new BusinessException("此账户已被其它人员绑定,请解绑后重试!");
+        }
+        // 更新人员信息
+        sysPersonService.updateById(person);
+        // 先删除原有关联,再按当前传入的 userId 重新绑定
+        QueryWrapper<SysUserPerson> wrapper = Wrappers.query();
+        wrapper.eq("person_id", person.getId());
+        sysUserPersonService.remove(wrapper);
+
+        SysUserPerson userPerson = new SysUserPerson();
+        userPerson.setUserId(userId);
+        userPerson.setPersonId(person.getId());
+        userPerson.setIsLoginNotify(0);
+        sysUserPersonService.save(userPerson);
+        return ApiResult.success();
+    }
+
+    /**
+     * 删除人员(支持批量,逗号分隔),并解绑与用户的关联
+     */
+    @DeleteMapping("/{ids}")
+    public ApiResult<Void> remove(@PathVariable("ids") Integer[] ids) {
+        // 先删除关联关系
+        QueryWrapper<SysUserPerson> wrapper = Wrappers.query();
+        wrapper.in("person_id", Arrays.asList(ids));
+        sysUserPersonService.remove(wrapper);
+        // 再删除人员
+        sysPersonService.removeByIds(Arrays.asList(ids));
+        return ApiResult.success();
+    }
 }
 

+ 38 - 28
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/controller/web/SysProfileController.java

@@ -7,10 +7,12 @@ import com.usky.common.core.util.StringUtils;
 import com.usky.common.security.service.TokenService;
 import com.usky.common.security.utils.SecurityUtils;
 import com.usky.system.domain.SysUser;
+import com.usky.system.domain.SysUserPerson;
 import com.usky.system.domain.SysUserVO;
 import com.usky.system.domain.constants.UserConstants;
 import com.usky.system.model.LoginUser;
 import com.usky.system.service.ISysUserService;
+import com.usky.system.service.SysUserPersonService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 
@@ -21,29 +23,37 @@ import java.util.Map;
 
 /**
  * 个人信息 业务处理
- * 
+ *
  * @author yq
  */
 @RestController
 @RequestMapping("/user/profile")
-public class SysProfileController extends BaseController
-{
+public class SysProfileController extends BaseController {
     @Autowired
     private ISysUserService userService;
 
     @Autowired
     private TokenService tokenService;
 
+    @Autowired
+    private SysUserPersonService sysUserPersonService;
+
     /**
      * 个人信息
      */
     @GetMapping
-    public ApiResult profile()
-    {
+    public ApiResult profile() {
         LoginUser loginUser = SecurityUtils.getLoginUser();
         SysUserVO user = loginUser.getSysUser();
-        Map<String,Object> map = new HashMap<>();
-        map.put("user",user);
+
+        SysUserPerson one = sysUserPersonService.lambdaQuery()
+                .eq(SysUserPerson::getUserId, user.getUserId())
+                .select(SysUserPerson::getIsLoginNotify)
+                .one();
+        user.setIsLoginNotify(one.getIsLoginNotify());
+
+        Map<String, Object> map = new HashMap<>();
+        map.put("user", user);
         map.put("roleGroup", userService.selectUserRoleGroup(loginUser.getUsername()));
         map.put("postGroup", userService.selectUserPostGroup(loginUser.getUsername()));
         return ApiResult.success(map);
@@ -53,24 +63,30 @@ public class SysProfileController extends BaseController
      * 修改用户
      */
     @PutMapping
-    public ApiResult updateProfile(@RequestBody SysUser user)
-    {
+    public ApiResult updateProfile(@RequestBody SysUser user) {
         if (StringUtils.isNotEmpty(user.getPhonenumber())
-                && UserConstants.NOT_UNIQUE.equals(userService.checkPhoneUnique(user)))
-        {
+                && UserConstants.NOT_UNIQUE.equals(userService.checkPhoneUnique(user))) {
             throw new BusinessException("修改用户'" + user.getUserName() + "'失败,手机号码已存在");
         }
         if (StringUtils.isNotEmpty(user.getEmail())
-                && UserConstants.NOT_UNIQUE.equals(userService.checkEmailUnique(user)))
-        {
+                && UserConstants.NOT_UNIQUE.equals(userService.checkEmailUnique(user))) {
             throw new BusinessException("修改用户'" + user.getUserName() + "'失败,邮箱账号已存在");
         }
         LoginUser loginUser = SecurityUtils.getLoginUser();
         SysUserVO sysUser = loginUser.getSysUser();
         user.setUserId(sysUser.getUserId());
         user.setPassword(null);
-        if (userService.updateUserProfile(user) > 0)
-        {
+        if (userService.updateUserProfile(user) > 0) {
+
+            // 更新登录通知设置
+            Integer isLoginNotify = user.getIsLoginNotify();
+            if (isLoginNotify != null) {
+                sysUserPersonService.lambdaUpdate()
+                        .eq(SysUserPerson::getUserId, sysUser.getUserId())
+                        .set(SysUserPerson::getIsLoginNotify, isLoginNotify)
+                        .update();
+            }
+
             // 更新缓存用户信息
             sysUser.setNickName(user.getNickName());
             sysUser.setPhonenumber(user.getPhonenumber());
@@ -86,22 +102,18 @@ public class SysProfileController extends BaseController
      * 重置密码
      */
     @PutMapping("/updatePwd")
-    public ApiResult updatePwd(String oldPassword, String newPassword)
-    {
+    public ApiResult updatePwd(String oldPassword, String newPassword) {
         LoginUser loginUser = SecurityUtils.getLoginUser();
         SysUserVO sysUser = loginUser.getSysUser();
         String userName = sysUser.getUserName();
         String password = sysUser.getPassword();
-        if (!SecurityUtils.matchesPassword(oldPassword, password))
-        {
+        if (!SecurityUtils.matchesPassword(oldPassword, password)) {
             throw new BusinessException("修改密码失败,旧密码错误");
         }
-        if (SecurityUtils.matchesPassword(newPassword, password))
-        {
+        if (SecurityUtils.matchesPassword(newPassword, password)) {
             throw new BusinessException("新密码不能与旧密码相同");
         }
-        if (userService.resetUserPwd(userName, SecurityUtils.encryptPassword(newPassword)) > 0)
-        {
+        if (userService.resetUserPwd(userName, SecurityUtils.encryptPassword(newPassword)) > 0) {
             // 更新缓存用户密码
             sysUser.setPassword(SecurityUtils.encryptPassword(newPassword));
             tokenService.setLoginUser(loginUser);
@@ -114,13 +126,11 @@ public class SysProfileController extends BaseController
      * 头像上传
      */
     @PostMapping("/avatar")
-    public ApiResult avatar(@RequestParam String filePath) throws IOException
-    {
+    public ApiResult avatar(@RequestParam String filePath) throws IOException {
         LoginUser loginUser = SecurityUtils.getLoginUser();
         SysUserVO sysUser = loginUser.getSysUser();
-        if (userService.updateUserAvatar(loginUser.getUsername(), filePath))
-        {
-            Map<String,Object> map = new HashMap<>();
+        if (userService.updateUserAvatar(loginUser.getUsername(), filePath)) {
+            Map<String, Object> map = new HashMap<>();
             map.put("imgUrl", filePath);
             // 更新缓存用户头像
             sysUser.setAvatar(filePath);

+ 26 - 12
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/controller/web/SysUserController.java

@@ -7,14 +7,10 @@ import com.usky.common.security.utils.SecurityUtils;
 import com.usky.common.core.bean.ApiResult;
 import com.usky.common.core.exception.BusinessErrorCode;
 import com.usky.system.controller.web.page.TableDataInfo;
-import com.usky.system.domain.SysDept;
-import com.usky.system.domain.SysRole;
-import com.usky.system.domain.SysUser;
+import com.usky.system.domain.*;
 import com.usky.system.domain.constants.UserConstants;
-import com.usky.system.service.ISysDeptService;
-import com.usky.system.service.ISysPostService;
-import com.usky.system.service.ISysRoleService;
-import com.usky.system.service.ISysUserService;
+import com.usky.system.mapper.SysUserTenantMapper;
+import com.usky.system.service.*;
 import com.usky.system.service.vo.SysUserNewVO;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.transaction.annotation.Transactional;
@@ -29,7 +25,7 @@ import java.util.stream.Collectors;
 
 /**
  * 用户信息
- * 
+ *
  * @author yq
  */
 @RestController
@@ -48,6 +44,12 @@ public class SysUserController extends BaseController
     @Autowired
     private ISysDeptService deptService;
 
+    @Autowired
+    private SysUserTenantMapper sysUserTenantMapper;
+
+    @Autowired
+    private SysUserPersonService sysUserPersonService;
+
     /**
      * 获取用户列表
      */
@@ -113,6 +115,7 @@ public class SysUserController extends BaseController
     @GetMapping(value = { "/", "/{userId}" })
     public ApiResult<Map<String,Object>> getInfo(@PathVariable(value = "userId", required = false) Long userId)
     {
+        Integer tenantId = SecurityUtils.getTenantId();
         Map<String,Object> ajax = new HashMap<>();
         List<SysRole> roles = roleService.selectRoleAll();
         ajax.put("roles", SysUser.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList()));
@@ -121,7 +124,7 @@ public class SysUserController extends BaseController
         {
             ajax.put("data", userService.selectUserById(userId));
             ajax.put("postIds", postService.selectPostListByUserId(userId));
-            ajax.put("roleIds", roleService.selectRoleListByUserId(userId));
+            ajax.put("roleIds", roleService.selectRoleListByUserId(userId, tenantId));
         }
         return ApiResult.success(ajax);
     }
@@ -149,6 +152,13 @@ public class SysUserController extends BaseController
         user.setCreateBy(SecurityUtils.getUsername());
         user.setPassword(SecurityUtils.encryptPassword(user.getPassword()));
         int row = userService.insertUser(user);
+
+        // 新增用户登录通知设置
+        SysUserPerson sysUserPerson = new SysUserPerson();
+        sysUserPerson.setUserId(user.getUserId());
+        sysUserPerson.setIsLoginNotify(0);
+        sysUserPersonService.save(sysUserPerson);
+
         return toAjax(row);
     }
 
@@ -160,20 +170,24 @@ public class SysUserController extends BaseController
     @PostMapping("/appAdd")
     public ApiResult<Void> appAdd(@Validated @RequestBody SysUser user)
     {
-        if (UserConstants.NOT_UNIQUE.equals(userService.checkUserNameUnique(user.getUserName(),user.getTenantId())))
+        if (UserConstants.NOT_UNIQUE.equals(userService.checkUserNameUnique(user.getUserName(),0)))
         {
             return ApiResult.error(BusinessErrorCode.BIZ_BUSINESS_ERROR.getCode(), "新增用户'" + user.getUserName() + "'失败,登录账号已存在");
         }
-        if(UserConstants.NOT_UNIQUE.equals(userService.checkPhoneUnique1(user.getPhonenumber(),user.getTenantId()))){
+        if(UserConstants.NOT_UNIQUE.equals(userService.checkPhoneUnique1(user.getPhonenumber(),0))){
             return ApiResult.error(BusinessErrorCode.BIZ_BUSINESS_ERROR.getCode(), "新增手机号'" + user.getPhonenumber() + "'失败,手机号已存在");
         }
+        if(UserConstants.NOT_UNIQUE.equals(userService.checkEmailUnique1(user.getEmail(),0))){
+            return ApiResult.error(BusinessErrorCode.BIZ_BUSINESS_ERROR.getCode(), "新增邮箱'" + user.getEmail() + "'失败,邮箱已存在");
+        }
         List<SysDept> list = deptService.deptListByTenant(user.getTenantId());
-        if (list.size() > 0){
+        if (!list.isEmpty()){
             user.setDeptId(list.get(0).getDeptId());
         }
         user.setUserType("00");
         user.setTenantId(user.getTenantId());
         user.setCreateBy(user.getUserName());
+        user.setTenantId(user.getTenantId());
         user.setPassword(SecurityUtils.encryptPassword(user.getPassword()));
         int row = userService.insertUser(user);
         return toAjax(row);

+ 21 - 3
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/controller/web/SysUserPersonController.java

@@ -1,9 +1,13 @@
 package com.usky.system.controller.web;
 
-
+import com.usky.common.core.bean.ApiResult;
+import com.usky.system.service.SysUserPersonService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.PutMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
 
-import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
 
 /**
  * <p>
@@ -13,9 +17,23 @@ import org.springframework.stereotype.Controller;
  * @author JCB
  * @since 2022-08-22
  */
-@Controller
+@RestController
 @RequestMapping("/sysUserPerson")
 public class SysUserPersonController {
 
+    @Autowired
+    private SysUserPersonService sysUserPersonService;
+
+    /**
+     * 修改登录通知开关状态
+     * @param useId 用户id
+     * @param isLoginNotify 1:开启 0:关闭
+     * @return 0:失败
+     */
+    @PutMapping("/upIsLoginNotify")
+    public ApiResult<Integer> upIsLoginNotice(@RequestParam Long userId,
+                                              @RequestParam Integer isLoginNotify) {
+        return ApiResult.success(sysUserPersonService.upIsLoginNotify(userId, isLoginNotify));
+    }
 }
 

+ 16 - 0
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/controller/web/SysUserTenantController.java

@@ -5,10 +5,14 @@ import com.usky.common.core.bean.ApiResult;
 import com.usky.common.core.exception.BusinessErrorCode;
 import com.usky.common.log.annotation.Log;
 import com.usky.common.log.enums.BusinessType;
+import com.usky.common.security.utils.SecurityUtils;
 import com.usky.system.domain.SysTenant;
+import com.usky.system.domain.SysUser;
 import com.usky.system.domain.SysUserTenant;
 import com.usky.system.service.SysUserTenantService;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
 
 import java.util.List;
@@ -62,5 +66,17 @@ public class SysUserTenantController extends BaseController {
     {
         return ApiResult.success(sysUserTenantService.getTenantByUser(userId));
     }
+
+    /**
+     * 修改用户默认租户
+     */
+    @Log(title = "修改用户默认租户", businessType = BusinessType.UPDATE)
+    @Transactional
+    @PutMapping
+    public ApiResult<Void> edit(@Validated @RequestBody SysUserTenant userTenant)
+    {
+        sysUserTenantService.updateUserTenant(userTenant);
+        return ApiResult.success();
+    }
 }
 

+ 27 - 0
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/controller/web/SystemInfoController.java

@@ -0,0 +1,27 @@
+package com.usky.system.controller.web;
+
+import com.usky.system.domain.SystemHardwareInfo;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+@RequestMapping("/oshi")
+public class SystemInfoController {
+
+    @GetMapping("/list")
+    public SystemHardwareInfo getSystemHardwareInfo() {
+        SystemHardwareInfo systemHardwareInfo = new SystemHardwareInfo();
+        try {
+            // 调用 copyTo() 方法填充数据
+            systemHardwareInfo.copyTo();
+        } catch (Exception e) {
+            // 日志记录异常信息
+            e.printStackTrace();
+            // 可以根据需要返回错误信息或空对象
+            return null;
+        }
+        // 返回填充后的数据
+        return systemHardwareInfo;
+    }
+}

+ 21 - 5
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/controller/web/TokenController.java

@@ -16,6 +16,7 @@ import com.usky.system.domain.*;
 import com.usky.system.mapper.SysUserMapper;
 import com.usky.system.model.LoginUser;
 import com.usky.system.service.*;
+import com.usky.system.service.util.IpUtils;
 import com.usky.system.service.vo.LoginBody;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
@@ -58,6 +59,9 @@ public class TokenController {
     @Autowired
     private MceSettingService mceSettingService;
 
+    @Autowired
+    private SysUserTenantService sysUserTenantService;
+
     @Resource
     private HttpServletRequest request;
     @Resource
@@ -76,10 +80,16 @@ public class TokenController {
     public ApiResult<?> appLogin(@RequestBody LoginBody form) {
 //        String phone = null;
         // 用户登录
-        SysUser userInfo = sysLoginService.appLogin(form.getUsername(), form.getPassword(), form.getTenantId(), form.getPhone(), form.getVerify());
+        SysUser userInfo = sysLoginService.appLogin(form.getUsername(), form.getPassword(), form.getTenantId(),
+                form.getPhone(), form.getVerify(), form.getMethod());
+        Integer isDefaulTenant = sysUserTenantService.getIsDefaultByUser(userInfo.getUserId());
         LoginUser sysUser = new LoginUser();
         SysUserVO sysUserVO = BeanMapperUtils.map(userInfo, SysUserVO.class);
-        sysUserVO.setTenantId(userInfo.getTenantId());
+        if (null != form.getMethod() && form.getMethod().equals("switch")){
+            sysUserVO.setTenantId(userInfo.getTenantId());
+        }else {
+            sysUserVO.setTenantId(isDefaulTenant);
+        }
         sysUser.setSysUser(sysUserVO);
         Set<String> rolePermission = permissionService.getRolePermission(userInfo.getUserId());
         sysUser.setRoles(rolePermission);
@@ -126,9 +136,9 @@ public class TokenController {
         if(CollectionUtils.isEmpty(list)){
             //新增消息设置记录
             MceSetting mceSetting = new MceSetting();
-            mceSetting.setAppMode("{\"1\":true,\"2\":true,\"3\":true,\"4\":true}");
-            mceSetting.setPcMode("{\"1\":true,\"2\":true,\"3\":true,\"4\":true}");
-            mceSetting.setWcMode("{\"1\":true,\"2\":true,\"3\":true,\"4\":true}");
+            mceSetting.setAppMode("{\"1\":true,\"2\":true,\"3\":true,\"4\":true,\"5\":true}");
+            mceSetting.setPcMode("{\"1\":true,\"2\":true,\"3\":true,\"4\":true,\"5\":true}");
+            mceSetting.setWcMode("{\"1\":true,\"2\":true,\"3\":true,\"4\":true,\"5\":true}");
 
             mceSetting.setCreateBy(userInfo.getUserName());
             mceSetting.setCreateTime(LocalDateTime.now());
@@ -145,6 +155,12 @@ public class TokenController {
         return ApiResult.success(tokenService.createToken(sysUser,openId));
     }
 
+    @PostMapping("getIp")
+    public ApiResult<?> getIp() {
+        String clientIp = IpUtils.getClientIp(request);
+        return ApiResult.success(clientIp);
+    }
+
 
     //手机端发送扫码信息,二维码编号,用户名信息
     @GetMapping("getQrCodeResult")

+ 68 - 0
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/domain/Cpu.java

@@ -0,0 +1,68 @@
+package com.usky.system.domain;
+
+import cn.hutool.core.util.NumberUtil;
+import lombok.Data;
+
+import java.io.Serializable;
+
+@Data
+public class Cpu implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+
+    /**
+     * 核心数
+     */
+    private int cpuNum;
+
+
+    /**
+     * CPU总的使用率
+     */
+    private double total;
+
+
+    /**
+     * CPU系统使用率
+     */
+    private double sys;
+
+
+    /**
+     * CPU用户使用率
+     */
+    private double used;
+
+
+    /**
+     * CPU当前等待率
+     */
+    private double wait;
+
+
+    /**
+     * CPU当前空闲率
+     */
+    private double free;
+
+
+    public double getTotal() {
+        return NumberUtil.round(NumberUtil.mul(total, 100), 2).doubleValue();
+    }
+
+    public double getSys() {
+        return NumberUtil.round(NumberUtil.mul(sys / total, 100), 2).doubleValue();
+    }
+
+    public double getUsed() {
+        return NumberUtil.round(NumberUtil.mul(used / total, 100), 2).doubleValue();
+    }
+
+    public double getWait() {
+        return NumberUtil.round(NumberUtil.mul(wait / total, 100), 2).doubleValue();
+    }
+
+    public double getFree() {
+        return NumberUtil.round(NumberUtil.mul(free / total, 100), 2).doubleValue();
+    }
+}

+ 112 - 0
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/domain/Jvm.java

@@ -0,0 +1,112 @@
+package com.usky.system.domain;
+
+import cn.hutool.core.date.DateUnit;
+import cn.hutool.core.date.DateUtil;
+import cn.hutool.core.util.NumberUtil;
+import lombok.Data;
+import java.io.Serializable;
+import java.lang.management.ManagementFactory;
+import java.util.Date;
+
+@Data
+public class Jvm implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+
+    /**
+     * 当前JVM占用的内存总数(M)
+     */
+    private double total;
+
+
+    /**
+     * JVM最大可用内存总数(M)
+     */
+    private double max;
+
+
+    /**
+     * JVM空闲内存(M)
+     */
+    private double free;
+
+
+    /**
+     * JDK版本
+     */
+    private String version;
+
+
+    /**
+     * JDK路径
+     */
+    private String home;
+
+
+    public double getTotal() {
+        return NumberUtil.div(total, (1024 * 1024), 2);
+    }
+
+    public double getMax() {
+        return NumberUtil.div(max, (1024 * 1024), 2);
+    }
+
+    public double getFree() {
+        return NumberUtil.div(free, (1024 * 1024), 2);
+    }
+
+    public double getUsed() {
+        return NumberUtil.div(total - free, (1024 * 1024), 2);
+    }
+
+    public String getVersion() {
+        return version;
+    }
+
+    public String getHome() {
+        return home;
+    }
+
+    public double getUsage() {
+        return NumberUtil.mul(NumberUtil.div(total - free, total, 4), 100);
+    }
+    /**
+     * 获取JDK名称
+     */
+    public String getName() {
+        return ManagementFactory.getRuntimeMXBean().getVmName();
+    }
+
+    /**
+     * JDK启动时间
+     */
+    public String getStartTime() {
+        long time = ManagementFactory.getRuntimeMXBean().getStartTime();
+        Date date = new Date(time);
+        return DateUtil.formatDateTime(date);
+    }
+
+    /**
+     * JDK运行时间
+     */
+    public String getRunTime() {
+        long time = ManagementFactory.getRuntimeMXBean().getStartTime();
+        Date date = new Date(time);
+
+
+        //运行多少分钟
+        long runMS = DateUtil.between(date, new Date(), DateUnit.MS);
+
+
+        long nd = 1000 * 24 * 60 * 60;
+        long nh = 1000 * 60 * 60;
+        long nm = 1000 * 60;
+
+
+        long day = runMS / nd;
+        long hour = runMS % nd / nh;
+        long min = runMS % nd % nh / nm;
+        return day + "天" + hour + "小时" + min + "分钟";
+    }
+}

+ 47 - 0
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/domain/Mem.java

@@ -0,0 +1,47 @@
+package com.usky.system.domain;
+
+import cn.hutool.core.util.NumberUtil;
+import lombok.Data;
+import java.io.Serializable;
+
+
+@Data
+public class Mem implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+
+    /**
+     * 内存总量
+     */
+    private double total;
+
+
+    /**
+     * 已用内存
+     */
+    private double used;
+
+
+    /**
+     * 剩余内存
+     */
+    private double free;
+
+
+    public double getTotal() {
+        return NumberUtil.div(total, (1024 * 1024 * 1024), 2);
+    }
+
+    public double getUsed() {
+        return NumberUtil.div(used, (1024 * 1024 * 1024), 2);
+    }
+
+    public double getFree() {
+        return NumberUtil.div(free, (1024 * 1024 * 1024), 2);
+    }
+
+    public double getUsage() {
+        return NumberUtil.mul(NumberUtil.div(used, total, 4), 100);
+    }
+}

+ 41 - 0
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/domain/Sys.java

@@ -0,0 +1,41 @@
+package com.usky.system.domain;
+
+import lombok.Data;
+import java.io.Serializable;
+
+
+@Data
+public class Sys implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+
+    /**
+     * 服务器名称
+     */
+    private String computerName;
+
+
+    /**
+     * 服务器Ip
+     */
+    private String computerIp;
+
+
+    /**
+     * 项目路径
+     */
+    private String userDir;
+
+
+    /**
+     * 操作系统
+     */
+    private String osName;
+
+
+    /**
+     * 系统架构
+     */
+    private String osArch;
+}

+ 53 - 0
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/domain/SysFile.java

@@ -0,0 +1,53 @@
+package com.usky.system.domain;
+
+import lombok.Data;
+import java.io.Serializable;
+
+
+@Data
+public class SysFile implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+
+    /**
+     * 盘符路径
+     */
+    private String dirName;
+
+
+    /**
+     * 盘符类型
+     */
+    private String sysTypeName;
+
+
+    /**
+     * 文件类型
+     */
+    private String typeName;
+
+
+    /**
+     * 总大小
+     */
+    private String total;
+
+
+    /**
+     * 剩余大小
+     */
+    private String free;
+
+
+    /**
+     * 已经使用量
+     */
+    private String used;
+
+
+    /**
+     * 资源的使用率
+     */
+    private double usage;
+}

+ 7 - 0
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/domain/SysMenu.java

@@ -57,6 +57,9 @@ public class SysMenu extends BaseEntity
     /** 类型(M目录 C菜单 F按钮) */
     private String menuType;
 
+    /** 类型(1.基础功能,2.业务功能) */
+    private Integer menuMold;
+
     /** 显示状态(0显示 1隐藏) */
     private String visible;
     
@@ -195,6 +198,10 @@ public class SysMenu extends BaseEntity
         this.menuType = menuType;
     }
 
+    public Integer getMenuMold() { return menuMold; }
+
+    public void setMenuMold(Integer menuMold) { this.menuMold = menuMold; }
+
     public String getVisible()
     {
         return visible;

+ 153 - 32
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/domain/SysNotice.java

@@ -1,22 +1,27 @@
 package com.usky.system.domain;
 
 
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.annotation.JsonIgnore;
 import com.usky.common.core.bean.BaseEntity;
 import io.swagger.models.auth.In;
 import org.apache.commons.lang3.builder.ToStringBuilder;
 import org.apache.commons.lang3.builder.ToStringStyle;
+import org.springframework.data.annotation.Transient;
+import org.springframework.format.annotation.DateTimeFormat;
 
 import javax.validation.constraints.NotBlank;
 import javax.validation.constraints.Size;
+import java.time.LocalDateTime;
 
 
 /**
  * 通知公告表 sys_notice
- * 
+ *
  * @author yq
  */
-public class SysNotice extends BaseEntity
-{
+public class SysNotice {
     private static final long serialVersionUID = 1L;
 
     /** 公告ID */
@@ -34,18 +39,52 @@ public class SysNotice extends BaseEntity
     /** 公告状态(0正常 1关闭) */
     private String status;
 
-    public Integer getNoticeId()
-    {
+    /** 附件地址 */
+    private String fileUrl;
+
+    /** 作者 */
+    private String author;
+
+    /** 通知接收部门id */
+    private String deptId;
+
+    // 新增临时字段,用于时间段查询
+    @TableField(exist = false)
+    @JsonIgnore
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime startTime;
+
+    @TableField(exist = false)
+    @JsonIgnore
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime endTime;
+
+    /** 创建者 */
+    private String createBy;
+
+    /** 创建时间 */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime createTime;
+
+    /** 更新者 */
+    private String updateBy;
+
+    /** 更新时间 */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime updateTime;
+
+    /** 租户id */
+    private Integer tenantId;
+
+    public Integer getNoticeId() {
         return noticeId;
     }
 
-    public void setNoticeId(Integer noticeId)
-    {
+    public void setNoticeId(Integer noticeId) {
         this.noticeId = noticeId;
     }
 
-    public void setNoticeTitle(String noticeTitle)
-    {
+    public void setNoticeTitle(String noticeTitle) {
         this.noticeTitle = noticeTitle;
     }
 
@@ -56,49 +95,131 @@ public class SysNotice extends BaseEntity
         return noticeTitle;
     }
 
-    public void setNoticeType(String noticeType)
-    {
+    public void setNoticeType(String noticeType) {
         this.noticeType = noticeType;
     }
 
-    public String getNoticeType()
-    {
+    public String getNoticeType() {
         return noticeType;
     }
 
-    public void setNoticeContent(String noticeContent)
-    {
+    public void setNoticeContent(String noticeContent) {
         this.noticeContent = noticeContent;
     }
 
-    public String getNoticeContent()
-    {
+    @NotBlank(message = "公告内容不能为空")
+    public String getNoticeContent() {
         return noticeContent;
     }
 
-    public void setStatus(String status)
-    {
+    public void setStatus(String status) {
         this.status = status;
     }
 
-    public String getStatus()
-    {
+    public String getStatus() {
         return status;
     }
 
+    public String getFileUrl() {
+        return fileUrl;
+    }
+
+    public void setFileUrl(String fileUrl) {
+        this.fileUrl = fileUrl;
+    }
+
+    public String getAuthor() {
+        return author;
+    }
+
+    public void setAuthor(String author) {
+        this.author = author;
+    }
+
+    public LocalDateTime getStartTime() {
+        return startTime;
+    }
+
+    public void setStartTime(LocalDateTime startTime) {
+        this.startTime = startTime;
+    }
+
+    public LocalDateTime getEndTime() {
+        return endTime;
+    }
+
+    public void setEndTime(LocalDateTime endTime) {
+        this.endTime = endTime;
+    }
+
+    @NotBlank(message = "通知接收部门id不能为空")
+    public String getDeptId() {
+        return deptId;
+    }
+
+    public void setDeptId(String deptId) {
+        this.deptId = deptId;
+    }
+
+    public String getCreateBy() {
+        return createBy;
+    }
+
+    public void setCreateBy(String createBy) {
+        this.createBy = createBy;
+    }
+
+    public LocalDateTime getCreateTime() {
+        return createTime;
+    }
+
+    public void setCreateTime(LocalDateTime createTime) {
+        this.createTime = createTime;
+    }
+
+    public String getUpdateBy() {
+        return updateBy;
+    }
+
+    public void setUpdateBy(String updateBy) {
+        this.updateBy = updateBy;
+    }
+
+    public LocalDateTime getUpdateTime() {
+        return updateTime;
+    }
+
+    public void setUpdateTime(LocalDateTime updateTime) {
+        this.updateTime = updateTime;
+    }
+
+    public Integer getTenantId() {
+        return tenantId;
+    }
+
+    public void setTenantId(Integer tenantId) {
+        this.tenantId = tenantId;
+    }
+
     @Override
     public String toString() {
         return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)
-            .append("noticeId", getNoticeId())
-            .append("noticeTitle", getNoticeTitle())
-            .append("noticeType", getNoticeType())
-            .append("noticeContent", getNoticeContent())
-            .append("status", getStatus())
-            .append("createBy", getCreateBy())
-            .append("createTime", getCreateTime())
-            .append("updateBy", getUpdateBy())
-            .append("updateTime", getUpdateTime())
-            .append("remark", getRemark())
-            .toString();
+                .append("noticeId", getNoticeId())
+                .append("noticeTitle", getNoticeTitle())
+                .append("noticeType", getNoticeType())
+                .append("noticeContent", getNoticeContent())
+                .append("status", getStatus())
+                .append("createBy", getCreateBy())
+                .append("createTime", getCreateTime())
+                .append("updateBy", getUpdateBy())
+                .append("updateTime", getUpdateTime())
+                .append("fileUrl", getFileUrl())
+                .append("author", getAuthor())
+                .append("deptId", getDeptId())
+                .append("createTime", getCreateTime())
+                .append("createBy", getCreateBy())
+                .append("updateBy", getUpdateBy())
+                .append("updateTime", getUpdateTime())
+                .toString();
     }
 }

+ 47 - 2
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/domain/SysPerson.java

@@ -1,6 +1,7 @@
 package com.usky.system.domain;
 
 import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableId;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
@@ -64,13 +65,15 @@ public class SysPerson implements Serializable {
     private String linkPhone;
 
     /**
-     * 岗位ID
+     * 岗位ID(来自关联用户,不入库)
      */
+    @TableField(exist = false)
     private Long postId;
 
     /**
-     * 部门ID
+     * 部门ID(来自关联用户,不入库)
      */
+    @TableField(exist = false)
     private Long deptId;
 
     /**
@@ -113,5 +116,47 @@ public class SysPerson implements Serializable {
      */
     private Date updateTime;
 
+    /**
+     * 图片数据(base64编码)
+     */
+    private String faceBase;
+
+    /**
+     * 验证次数(默认0)
+     */
+    private Integer vefNum;
+
+    /**
+     * 人脸备注
+     */
+    private String remark;
+
+    /**
+     * 人脸状态(0=可用,1=不可用)
+     */
+    private Integer faceStatus;
+
+    /**
+     * 卡号
+     */
+    private String cardNum;
+
+    /**
+     * 关联的用户ID(非持久化字段,仅用于回显)
+     */
+    @TableField(exist = false)
+    private Long userId;
+
+    /**
+     * 部门名称(非持久化字段,仅用于回显)
+     */
+    @TableField(exist = false)
+    private String deptName;
+
+    /**
+     * 岗位名称(来自关联用户,不入库)
+     */
+    @TableField(exist = false)
+    private String postName;
 
 }

+ 10 - 0
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/domain/SysPlatform.java

@@ -51,6 +51,16 @@ public class SysPlatform implements Serializable {
      */
     private String icon;
 
+    /**
+     * 显示顺序
+     */
+    private Integer orderNum;
+
+    /**
+     * 应用类型(1.基础功能,2.业务功能)
+     */
+    private Integer platformType;
+
     /**
      * 创建者
      */

+ 12 - 0
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/domain/SysTenant.java

@@ -121,4 +121,16 @@ public class SysTenant implements Serializable {
      */
     @TableField(exist = false)
     private Integer originalTenantId;
+
+    /**
+     * 是否为默认租户(默认0; 0:否,1:是)
+     */
+    @TableField(exist = false)
+    private Boolean isDefault;
+
+    /**
+     * 租户logo
+     */
+    @TableField(exist = false)
+    private String tenantLogo;
 }

+ 27 - 0
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/domain/SysUser.java

@@ -13,6 +13,7 @@ import javax.validation.constraints.NotBlank;
 import javax.validation.constraints.Size;
 import java.util.Date;
 import java.util.List;
+import java.util.Map;
 
 
 /**
@@ -24,6 +25,17 @@ public class SysUser extends BaseEntity
 {
     private static final long serialVersionUID = 1L;
 
+    /**
+     * 与 BaseEntity 同名字段:MyBatis-Plus 按子类优先收集字段,此处显式 {@code exist = false},
+     * 避免仅依赖父类 private 字段注解时仍生成 {@code search_value}/{@code params} 列。
+     * 读写仍使用继承自 BaseEntity 的 getter/setter(操作父类字段)。
+     */
+    @TableField(exist = false)
+    private String searchValue;
+
+    @TableField(exist = false)
+    private Map<String, Object> params;
+
     /** 用户ID */
     @TableId
     private Long userId;
@@ -100,6 +112,20 @@ public class SysUser extends BaseEntity
     /** 姓名 */
     private String fullName;
 
+    /**
+     * 是否打开登录通知(1 表示是,0 表示否,默认 0)
+     */
+    @TableField(exist = false)
+    private Integer isLoginNotify;
+
+    public Integer getIsLoginNotify() {
+        return isLoginNotify;
+    }
+
+    public void setIsLoginNotify(Integer isLoginNotify) {
+        this.isLoginNotify = isLoginNotify;
+    }
+
     /** 岗位 */
     @TableField(exist = false)
     private String post;
@@ -391,6 +417,7 @@ public class SysUser extends BaseEntity
             .append("updateTime", getUpdateTime())
             .append("remark", getRemark())
             .append("dept", getDept())
+            .append("isLoginNotify",  getIsLoginNotify())
             .toString();
     }
 }

+ 6 - 0
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/domain/SysUserPerson.java

@@ -1,6 +1,7 @@
 package com.usky.system.domain;
 
 import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableId;
 import java.io.Serializable;
 import lombok.Data;
@@ -36,5 +37,10 @@ public class SysUserPerson implements Serializable {
      */
     private Integer personId;
 
+    /**
+     * 是否打开登录通知(1 表示是,0 表示否,默认 0)
+     */
+    private Integer isLoginNotify;
+
 
 }

+ 22 - 15
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/domain/SysUserRole.java

@@ -5,42 +5,49 @@ import org.apache.commons.lang3.builder.ToStringStyle;
 
 /**
  * 用户和角色关联 sys_user_role
- * 
+ *
  * @author yq
  */
-public class SysUserRole
-{
+public class SysUserRole {
     /** 用户ID */
     private Long userId;
-    
+
     /** 角色ID */
     private Long roleId;
 
-    public Long getUserId()
-    {
+    /** 租户ID */
+    private Integer tenantId;
+
+    public Long getUserId() {
         return userId;
     }
 
-    public void setUserId(Long userId)
-    {
+    public void setUserId(Long userId) {
         this.userId = userId;
     }
 
-    public Long getRoleId()
-    {
+    public Long getRoleId() {
         return roleId;
     }
 
-    public void setRoleId(Long roleId)
-    {
+    public void setRoleId(Long roleId) {
         this.roleId = roleId;
     }
 
+    public Integer getTenantId() {
+        return tenantId;
+    }
+
+    public void setTenantId(Integer tenantId) {
+        this.tenantId = tenantId;
+    }
+
     @Override
     public String toString() {
         return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)
-            .append("userId", getUserId())
-            .append("roleId", getRoleId())
-            .toString();
+                .append("userId", getUserId())
+                .append("roleId", getRoleId())
+                .append("tenantId", getTenantId())
+                .toString();
     }
 }

+ 185 - 0
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/domain/SystemHardwareInfo.java

@@ -0,0 +1,185 @@
+package com.usky.system.domain;
+
+import cn.hutool.core.net.NetUtil;
+import cn.hutool.core.util.NumberUtil;
+import lombok.Data;
+import oshi.SystemInfo;
+import oshi.hardware.CentralProcessor;
+import oshi.hardware.CentralProcessor.TickType;
+import oshi.hardware.GlobalMemory;
+import oshi.hardware.HardwareAbstractionLayer;
+import oshi.software.os.FileSystem;
+import oshi.software.os.OSFileStore;
+import oshi.software.os.OperatingSystem;
+import oshi.util.Util;
+import java.io.Serializable;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Properties;
+
+
+@Data
+public class SystemHardwareInfo  implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+
+    private static final int OSHI_WAIT_SECOND = 1000;
+
+
+    /**
+     * CPU相关信息
+     */
+    private Cpu cpu = new Cpu();
+
+
+    /**
+     * 內存相关信息
+     */
+    private Mem mem = new Mem();
+
+
+    /**
+     * JVM相关信息
+     */
+    private Jvm jvm = new Jvm();
+
+
+    /**
+     * 服务器相关信息
+     */
+    private Sys sys = new Sys();
+
+
+    /**
+     * 磁盘相关信息
+     */
+    private List<SysFile> sysFiles = new LinkedList<SysFile>();
+
+
+    public void copyTo() throws Exception {
+        SystemInfo si = new SystemInfo();
+        HardwareAbstractionLayer hal = si.getHardware();
+
+
+        setCpuInfo(hal.getProcessor());
+
+
+        setMemInfo(hal.getMemory());
+
+
+        setSysInfo();
+
+
+        setJvmInfo();
+
+
+        setSysFiles(si.getOperatingSystem());
+    }
+
+    /**
+     * 设置CPU信息
+     */
+    private void setCpuInfo(CentralProcessor processor) {
+        // CPU信息
+        long[] prevTicks = processor.getSystemCpuLoadTicks();
+        Util.sleep(OSHI_WAIT_SECOND);
+        long[] ticks = processor.getSystemCpuLoadTicks();
+        long nice = ticks[TickType.NICE.getIndex()] - prevTicks[TickType.NICE.getIndex()];
+        long irq = ticks[TickType.IRQ.getIndex()] - prevTicks[TickType.IRQ.getIndex()];
+        long softirq = ticks[TickType.SOFTIRQ.getIndex()] - prevTicks[TickType.SOFTIRQ.getIndex()];
+        long steal = ticks[TickType.STEAL.getIndex()] - prevTicks[TickType.STEAL.getIndex()];
+        long cSys = ticks[TickType.SYSTEM.getIndex()] - prevTicks[TickType.SYSTEM.getIndex()];
+        long user = ticks[TickType.USER.getIndex()] - prevTicks[TickType.USER.getIndex()];
+        long iowait = ticks[TickType.IOWAIT.getIndex()] - prevTicks[TickType.IOWAIT.getIndex()];
+        long idle = ticks[TickType.IDLE.getIndex()] - prevTicks[TickType.IDLE.getIndex()];
+        long totalCpu = user + nice + cSys + idle + iowait + irq + softirq + steal;
+        cpu.setCpuNum(processor.getLogicalProcessorCount());
+        cpu.setTotal(totalCpu);
+        cpu.setSys(cSys);
+        cpu.setUsed(user);
+        cpu.setWait(iowait);
+        cpu.setFree(idle);
+    }
+
+    /**
+     * 设置内存信息
+     */
+    private void setMemInfo(GlobalMemory memory) {
+        mem.setTotal(memory.getTotal());
+        mem.setUsed(memory.getTotal() - memory.getAvailable());
+        mem.setFree(memory.getAvailable());
+    }
+
+    /**
+     * 设置服务器信息
+     */
+    private void setSysInfo() {
+        Properties props = System.getProperties();
+        SystemInfo si = new SystemInfo();
+        OperatingSystem os = si.getOperatingSystem();
+        // 使用 oshi 获取主机名
+        sys.setComputerName(os.getNetworkParams().getHostName());
+        sys.setComputerIp(NetUtil.getLocalhostStr());
+        sys.setOsName(props.getProperty("os.name"));
+        sys.setOsArch(props.getProperty("os.arch"));
+        sys.setUserDir(props.getProperty("user.dir"));
+    }
+
+    /**
+     * 设置Java虚拟机
+     */
+    private void setJvmInfo() {
+        Properties props = System.getProperties();
+        jvm.setTotal(Runtime.getRuntime().totalMemory());
+        jvm.setMax(Runtime.getRuntime().maxMemory());
+        jvm.setFree(Runtime.getRuntime().freeMemory());
+        jvm.setVersion(props.getProperty("java.version"));
+        jvm.setHome(props.getProperty("java.home"));
+    }
+
+    /**
+     * 设置磁盘信息
+     */
+    private void setSysFiles(OperatingSystem os) {
+        FileSystem fileSystem = os.getFileSystem();
+        OSFileStore[] fsArray = fileSystem.getFileStores();
+        for (OSFileStore fs : fsArray) {
+            long free = fs.getUsableSpace();
+            long total = fs.getTotalSpace();
+            long used = total - free;
+            SysFile sysFile = new SysFile();
+            sysFile.setDirName(fs.getMount());
+            sysFile.setSysTypeName(fs.getType());
+            sysFile.setTypeName(fs.getName());
+            sysFile.setTotal(convertFileSize(total));
+            sysFile.setFree(convertFileSize(free));
+            sysFile.setUsed(convertFileSize(used));
+            sysFile.setUsage(NumberUtil.round(NumberUtil.mul(used, total, 4), 100).doubleValue());
+            sysFiles.add(sysFile);
+        }
+    }
+
+    /**
+     * 字节转换
+     *
+     * @param size 字节大小
+     * @return 转换后值
+     */
+    public String convertFileSize(long size) {
+        long kb = 1024;
+        long mb = kb * 1024;
+        long gb = mb * 1024;
+        if (size >= gb) {
+            return String.format("%.1f GB" , (float) size / gb);
+        } else if (size >= mb) {
+            float f = (float) size / mb;
+            return String.format(f > 100 ? "%.0f MB" : "%.1f MB" , f);
+        } else if (size >= kb) {
+            float f = (float) size / kb;
+            return String.format(f > 100 ? "%.0f KB" : "%.1f KB" , f);
+        } else {
+            return String.format("%d B" , size);
+        }
+    }
+}

+ 8 - 0
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/mapper/SysDeptMapper.java

@@ -46,6 +46,14 @@ public interface SysDeptMapper extends BaseMapper<SysDept>
      */
     public SysDept selectDeptById(@Param("deptId") Long deptId);
 
+    /**
+     * 根据部门ID列表批量查询部门信息
+     *
+     * @param deptIds 部门ID列表
+     * @return 部门信息列表
+     */
+    public List<SysDept> selectDeptByIds(@Param("deptIds") List<Long> deptIds);
+
     /**
      * 根据ID查询所有子部门
      * 

+ 3 - 1
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/mapper/SysMenuMapper.java

@@ -86,7 +86,9 @@ public interface SysMenuMapper extends CrudMapper<SysMenu> {
      * @param platformId 应用ID
      * @return 应用级菜单列表
      */
-    public List<SysMenu> selectMenuTreeByUserId1(@Param("userId") Long userId,@Param("platformId") Long platformId);
+    public List<SysMenu> selectMenuTreeByUserId1(@Param("userId") Long userId,
+                                                 @Param("platformId") Long platformId,
+                                                 @Param("tenantId") Integer tenantId);
 
     public List<SysMenu> selectMenuTreeByUserIdOne(@Param("tenantId") Integer tenantId);
 

+ 9 - 0
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/mapper/SysMobileMenuMapper.java

@@ -43,6 +43,15 @@ public interface SysMobileMenuMapper extends CrudMapper<SysMobileMenu> {
      */
     public List<SysMobileMenu> selectMenuTreeByUserId(@Param("userId") long userId);
 
+    /**
+     * 根据用户Id查询菜单
+     *
+     * @param userId 用户Id
+     * @return 菜单列表
+     */
+    public List<SysMobileMenu> selectMenuTreeByUserId1(@Param("userId") long userId,
+                                                       @Param("tenantId") Integer tenantId);
+
     /**
      * 根据租户Id查询菜单
      *

+ 1 - 1
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/mapper/SysPlatformMenuMapper.java

@@ -22,7 +22,7 @@ public interface SysPlatformMenuMapper extends CrudMapper<SysPlatformMenu> {
     List<SysMenu> getMenuList(@Param("platformId") Integer platformId,
                               @Param("menuType") String menuType);
 
-    List<SysMobileMenu> getMobileMenuList(@Param("platformId") Integer platformId,
+    List<SysMobileMenu> getMobileMenuList(@Param("platformIds") List<Integer> platformIds,
                               @Param("menuType") String menuType);
 
     List<SysMenu> getMenuIdList(@Param("menuIds") Long[] menuIds,

+ 2 - 1
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/mapper/SysPostMapper.java

@@ -53,7 +53,8 @@ public interface SysPostMapper extends CrudMapper<SysPost>
      * @param userName 用户名
      * @return 结果
      */
-    public List<SysPost> selectPostsByUserName(@Param("userName") String userName);
+    public List<SysPost> selectPostsByUserName(@Param("userName") String userName,
+                                               @Param("tenantId") Integer tenantId);
 
     /**
      * 删除岗位信息

+ 4 - 2
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/mapper/SysRoleMapper.java

@@ -45,7 +45,8 @@ public interface SysRoleMapper extends CrudMapper<SysRole>
      * @param userId 用户ID
      * @return 选中角色ID列表
      */
-    public List<Integer> selectRoleListByUserId(@Param("userId") Long userId);
+    public List<Integer> selectRoleListByUserId(@Param("userId") Long userId,
+                                                @Param("tenantId") Integer tenantId);
 
     /**
      * 通过角色ID查询角色
@@ -61,7 +62,8 @@ public interface SysRoleMapper extends CrudMapper<SysRole>
      * @param userName 用户名
      * @return 角色列表
      */
-    public List<SysRole> selectRolesByUserName(@Param("userName") String userName);
+    public List<SysRole> selectRolesByUserName(@Param("userName") String userName,
+                                               @Param("tenantId") Integer tenantId);
 
     /**
      * 校验角色名称是否唯一

+ 2 - 0
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/mapper/SysTenantConfigMapper.java

@@ -5,6 +5,7 @@ import com.usky.system.domain.SysMenu;
 import com.usky.system.domain.SysTenantConfig;
 import com.usky.system.service.vo.SysTenantConfigVo;
 import org.apache.ibatis.annotations.Param;
+import org.springframework.stereotype.Repository;
 
 import java.util.List;
 
@@ -16,6 +17,7 @@ import java.util.List;
  * @author ya
  * @since 2022-05-06
  */
+@Repository
 public interface SysTenantConfigMapper extends CrudMapper<SysTenantConfig> {
     List<SysTenantConfigVo> getTenantConfig(@Param("url") String url);
 

+ 6 - 0
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/mapper/SysUserMapper.java

@@ -187,4 +187,10 @@ public interface SysUserMapper extends CrudMapper<SysUser> {
 
     SysUser selectUserTenantDataOne(@Param("tenantId") Integer tenantId,
                                     @Param("phone") String phone);
+
+    SysUser selectUserTenantData1(@Param("userName") String userName,
+                                 @Param("tenantId") Integer tenantId);
+
+    SysUser selectUserTenantDataOne1(@Param("tenantId") Integer tenantId,
+                                    @Param("phone") String phone);
 }

+ 4 - 4
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/mapper/SysUserRoleMapper.java

@@ -22,7 +22,7 @@ public interface SysUserRoleMapper extends CrudMapper<SysUserRole>
      * @param userId 用户ID
      * @return 结果
      */
-    public int deleteUserRoleByUserId(@Param("userId") Long userId);
+    public int deleteUserRoleByUserId(@Param("userId") Long userId, @Param("tenantId") Integer tenantId);
 
     /**
      * 批量删除用户和角色关联
@@ -30,7 +30,7 @@ public interface SysUserRoleMapper extends CrudMapper<SysUserRole>
      * @param ids 需要删除的数据ID
      * @return 结果
      */
-    public int deleteUserRole(@Param("ids") Long[] ids);
+    public int deleteUserRole(@Param("ids") Long[] ids, @Param("tenantId") Integer tenantId);
 
     /**
      * 通过角色ID查询角色使用数量
@@ -38,7 +38,7 @@ public interface SysUserRoleMapper extends CrudMapper<SysUserRole>
      * @param roleId 角色ID
      * @return 结果
      */
-    public int countUserRoleByRoleId(@Param("roleId") Long roleId);
+    public int countUserRoleByRoleId(@Param("roleId") Long roleId, @Param("tenantId") Integer tenantId);
 
     /**
      * 批量新增用户角色信息
@@ -63,5 +63,5 @@ public interface SysUserRoleMapper extends CrudMapper<SysUserRole>
      * @param userIds 需要删除的用户数据ID
      * @return 结果
      */
-    public int deleteUserRoleInfos(@Param("roleId") Long roleId, @Param("userIds") Long[] userIds);
+    public int deleteUserRoleInfos(@Param("roleId") Long roleId, @Param("userIds") Long[] userIds, @Param("tenantId") Integer tenantId);
 }

+ 11 - 0
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/service/ISysDeptService.java

@@ -24,6 +24,9 @@ public interface ISysDeptService extends IService<SysDept>
      */
     public List<SysDept> selectDeptList(SysDept dept);
 
+    // 查询租户下部门信,无数据权限
+    List<SysDept> selectDept(SysDept dept);
+
     public List<SysDept> deptList(SysDept dept);
 
     public List<SysDept> deptListByTenant(Integer tenantId);
@@ -67,6 +70,14 @@ public interface ISysDeptService extends IService<SysDept>
      */
     public SysDept selectDeptById(Long deptId);
 
+    /**
+     * 根据部门ID列表批量查询部门信息
+     *
+     * @param deptIds 部门ID列表
+     * @return 部门信息列表
+     */
+    public List<SysDept> selectDeptByIds(List<Long> deptIds);
+
     /**
      * 根据ID查询所有子部门(正常状态)
      * 

+ 1 - 1
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/service/ISysMenuService.java

@@ -71,7 +71,7 @@ public interface ISysMenuService extends CrudService<SysMenu>
      * @param userId 用户ID
      * @return 菜单列表
      */
-    public List<SysMenu> selectMenuTreeByUserId1(Long userId,Long platformId);
+    public List<SysMenu> selectMenuTreeByUserId1(Long userId,Long platformId, Integer tenantId);
 
     List<SysMenu> selectMenuTreeByUserIdOne(Integer tenantId);
 

+ 1 - 1
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/service/ISysRoleService.java

@@ -52,7 +52,7 @@ public interface ISysRoleService extends CrudService<SysRole>
      * @param userId 用户ID
      * @return 选中角色ID列表
      */
-    public List<Integer> selectRoleListByUserId(Long userId);
+    public List<Integer> selectRoleListByUserId(Long userId, Integer tenantId);
 
     /**
      * 通过角色ID查询角色

+ 1 - 1
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/service/ISysUserService.java

@@ -263,7 +263,7 @@ public interface ISysUserService extends CrudService<SysUser> {
 
     public LoginUser getUserInfoOne(String username,Integer tenantId);
 
-    SysUser getAppUserInfo(String username, Integer tenantId,String phone);
+    SysUser getAppUserInfo(String username, Integer tenantId,String phone,String method);
     
     public Boolean register(SysUser sysUser);
 

+ 3 - 0
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/service/MceContentService.java

@@ -3,6 +3,7 @@ package com.usky.system.service;
 import com.alibaba.fastjson.JSONObject;
 import com.usky.system.domain.MceContent;
 import com.usky.common.mybatis.core.CrudService;
+import com.usky.system.domain.MceRequestVO;
 
 /**
  * <p>
@@ -13,6 +14,8 @@ import com.usky.common.mybatis.core.CrudService;
  * @since 2024-05-09
  */
 public interface MceContentService extends CrudService<MceContent> {
+
     void sendApp(JSONObject mceReceiveVO, String cids, Integer mceReceiveId, Integer sendType);
 
+    void sendAppNew(MceRequestVO mceRequestVO, String cids, Integer mceReceiveId, Integer sendType);
 }

+ 14 - 1
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/service/MceReceiveService.java

@@ -3,6 +3,8 @@ package com.usky.system.service;
 import com.usky.common.core.bean.CommonPage;
 import com.usky.system.domain.MceReceive;
 import com.usky.common.mybatis.core.CrudService;
+import com.usky.system.domain.MceRequestVO;
+import com.usky.system.service.vo.MceReceiveResponseVO;
 
 import java.util.Map;
 
@@ -16,7 +18,7 @@ import java.util.Map;
  */
 public interface MceReceiveService extends CrudService<MceReceive> {
 
-    CommonPage<Object> mceList(String infoTitle, String infoType, String startTime, String endTime, Integer id, Integer current, Integer size);
+    CommonPage<Object> mceList(String infoTitle, String infoType, String startTime, String endTime, Integer id, Integer infoId, Integer current, Integer size);
 
     CommonPage<Object> mceManageList(String infoTitle, String infoType, String startTime, String endTime, Integer current, Integer size);
 
@@ -26,8 +28,19 @@ public interface MceReceiveService extends CrudService<MceReceive> {
 
     void updateMceReceive(MceReceive mceReceive);
 
+    void addMceReceive(MceRequestVO mceRequestVO);
+
     void add(String mceReceive);
 
     boolean removeById(Integer id);
 
+    boolean deleteById(Integer id);
+
+    CommonPage<MceReceiveResponseVO> getMceReceiveResponseVOList(Integer pageNumber, Integer pageSize);
+
+    /**
+     * 添加消息不带token
+     * @param mceReceive
+     */
+    void addNoToken(String mceReceive);
 }

+ 43 - 24
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/service/SysLoginService.java

@@ -18,7 +18,10 @@ import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
 
+import javax.servlet.http.HttpServletRequest;
 import java.util.List;
 import java.util.Objects;
 import java.util.Random;
@@ -62,19 +65,22 @@ public class SysLoginService {
 
         // 用户名或密码为空 错误
         if (StringUtils.isAnyBlank(username, password)) {
-            asyncManager.insertLog(tenantId,username,Constants.LOGIN_FAIL, "用户/密码必须填写", null);
+            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
+            asyncManager.insertLog(request, tenantId,username,Constants.LOGIN_FAIL, "用户/密码必须填写", null);
             throw new BusinessException("用户/密码必须填写");
         }
         // 密码如果不在指定范围内 错误
         if (password.length() < UserConstants.PASSWORD_MIN_LENGTH
                 || password.length() > UserConstants.PASSWORD_MAX_LENGTH) {
-            asyncManager.insertLog(tenantId,username, Constants.LOGIN_FAIL, "用户密码不在指定范围", null);
+            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
+            asyncManager.insertLog(request, tenantId,username, Constants.LOGIN_FAIL, "用户密码不在指定范围", null);
             throw new BusinessException("用户密码不在指定范围");
         }
         // 用户名不在指定范围内 错误
         if (username.length() < UserConstants.USERNAME_MIN_LENGTH
                 || username.length() > UserConstants.USERNAME_MAX_LENGTH) {
-            asyncManager.insertLog(tenantId,username, Constants.LOGIN_FAIL, "用户名不在指定范围", null);
+            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
+            asyncManager.insertLog(request, tenantId,username, Constants.LOGIN_FAIL, "用户名不在指定范围", null);
             throw new BusinessException("用户名不在指定范围");
         }
 
@@ -88,15 +94,18 @@ public class SysLoginService {
 
         SysUserVO user = loginUser.getSysUser();
         if (UserStatus.DELETED.getCode().equals(user.getDelFlag())) {
-            asyncManager.insertLog(tenantId,username, Constants.LOGIN_FAIL, "对不起,您的账号已被删除", null);
+            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
+            asyncManager.insertLog(request, tenantId,username, Constants.LOGIN_FAIL, "对不起,您的账号已被删除", null);
             throw new BusinessException("对不起,您的账号:" + username + " 已被删除");
         }
         if (UserStatus.DISABLE.getCode().equals(user.getStatus())) {
-            asyncManager.insertLog(tenantId,username, Constants.LOGIN_FAIL, "用户已停用,请联系管理员", null);
+            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
+            asyncManager.insertLog(request, tenantId,username, Constants.LOGIN_FAIL, "用户已停用,请联系管理员", null);
             throw new BusinessException("对不起,您的账号:" + username + " 已停用");
         }
         if (!SecurityUtils.matchesPassword(password, user.getPassword())) {
-            asyncManager.insertLog(tenantId,username, Constants.LOGIN_FAIL, "用户密码错误", null);
+            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
+            asyncManager.insertLog(request, tenantId,username, Constants.LOGIN_FAIL, "用户密码错误", null);
             throw new BusinessException("用户不存在/密码错误");
         }
 
@@ -109,7 +118,8 @@ public class SysLoginService {
             String status = list.get(0).getStatus();
             String domain = list.get(0).getDomain();
             if(status.equals("1")){
-                asyncManager.insertLog(tenantId,username, Constants.LOGIN_FAIL, "系统已停用,请联系管理员", null);
+                HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
+                asyncManager.insertLog(request, tenantId,username, Constants.LOGIN_FAIL, "系统已停用,请联系管理员", null);
                 throw new BusinessException("对不起,系统已停用,请联系管理员");
             }
         }
@@ -128,44 +138,48 @@ public class SysLoginService {
 
         SysPerson sysPerson = sysPersonService.getsysPerson(user.getUserId());
         loginUser.setSysPerson(sysPerson);
-        asyncManager.insertLog(tenantId,username, Constants.LOGIN_SUCCESS, "登录成功", deptId);
+        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
+        asyncManager.insertLog(request, tenantId,username, Constants.LOGIN_SUCCESS, "登录成功", deptId);
         return loginUser;
     }
 
 
-    public SysUser appLogin(String username, String password, Integer tenantId, String phone, String verify) {
+    public SysUser appLogin(String username, String password, Integer tenantId, String phone, String verify, String method) {
         SysUser loginUser = new SysUser();
         //查询用户信息
-        loginUser = sysUserService.getAppUserInfo(username, tenantId, null);
         if (!StringUtils.isBlank(username) && !StringUtils.isBlank(password)) {
             // 用户名或密码为空 错误
             if (StringUtils.isAnyBlank(username, password)) {
-                asyncManager.insertLog(tenantId,loginUser.getUserName(), Constants.LOGIN_FAIL, "用户/密码必须填写", null);
+                HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
+                asyncManager.insertLog(request, tenantId,loginUser.getUserName(), Constants.LOGIN_FAIL, "用户/密码必须填写", null);
                 throw new BusinessException("用户/密码必须填写");
             }
 
             // 密码如果不在指定范围内 错误
             if (password.length() < UserConstants.PASSWORD_MIN_LENGTH
                     || password.length() > UserConstants.PASSWORD_MAX_LENGTH) {
-                asyncManager.insertLog(tenantId,loginUser.getUserName(), Constants.LOGIN_FAIL, "用户密码不在指定范围", null);
+                HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
+                asyncManager.insertLog(request, tenantId,loginUser.getUserName(), Constants.LOGIN_FAIL, "用户密码不在指定范围", null);
                 throw new BusinessException("用户密码不在指定范围");
             }
 
             // 用户名不在指定范围内 错误
             if (username.length() < UserConstants.USERNAME_MIN_LENGTH
                     || username.length() > UserConstants.USERNAME_MAX_LENGTH) {
-                asyncManager.insertLog(tenantId,loginUser.getUserName(), Constants.LOGIN_FAIL, "用户名不在指定范围", null);
+                HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
+                asyncManager.insertLog(request, tenantId,loginUser.getUserName(), Constants.LOGIN_FAIL, "用户名不在指定范围", null);
                 throw new BusinessException("用户名不在指定范围");
             }
-
-
+            loginUser = sysUserService.getAppUserInfo(username, tenantId, null, method);
             if (Objects.isNull(loginUser)) {
-                asyncManager.insertLog(tenantId,loginUser.getUserName(), Constants.LOGIN_FAIL, "用户不存在", null);
+                HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
+                asyncManager.insertLog(request, tenantId,loginUser.getUserName(), Constants.LOGIN_FAIL, "用户不存在", null);
                 throw new BusinessException("用户不存在");
             }
 
             if (!SecurityUtils.matchesPassword(password, loginUser.getPassword())) {
-                asyncManager.insertLog(tenantId,loginUser.getUserName(), Constants.LOGIN_FAIL, "用户密码错误", null);
+                HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
+                asyncManager.insertLog(request, tenantId,loginUser.getUserName(), Constants.LOGIN_FAIL, "用户密码错误", null);
                 throw new BusinessException("用户不存在/密码错误");
             }
         } else if(!StringUtils.isBlank(phone) && !StringUtils.isBlank(verify)) {
@@ -179,7 +193,7 @@ public class SysLoginService {
             if (StringUtils.isBlank(phone)) {
                 throw new BusinessException("用户名或手机号不能为空");
             }
-            loginUser = sysUserService.getAppUserInfo(null, tenantId, phone);
+            loginUser = sysUserService.getAppUserInfo(null, tenantId, phone, method);
             // 获取部门ID
             LambdaQueryWrapper<SysUser> deptQueryWrapper = Wrappers.lambdaQuery();
             deptQueryWrapper.select(SysUser::getDeptId)
@@ -200,7 +214,7 @@ public class SysLoginService {
             if (!verify.equals(redisHelper.get(qrCode_verify))) {
                 throw new BusinessException("扫码验证码失败");
             }
-            loginUser = sysUserService.getAppUserInfo(username, tenantId, null);
+            loginUser = sysUserService.getAppUserInfo(username, tenantId, null, method);
         }
         // 获取部门ID
         LambdaQueryWrapper<SysUser> deptQueryWrapper = Wrappers.lambdaQuery();
@@ -214,11 +228,13 @@ public class SysLoginService {
             deptId = sysUser.getDeptId().intValue(); // 将Long转换为Integer
         }
         if (UserStatus.DELETED.getCode().equals(loginUser.getDelFlag())) {
-            asyncManager.insertLog(tenantId,loginUser.getUserName(), Constants.LOGIN_FAIL, "对不起,您的账号已被删除", null);
+            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
+            asyncManager.insertLog(request, tenantId,loginUser.getUserName(), Constants.LOGIN_FAIL, "对不起,您的账号已被删除", null);
             throw new BusinessException("对不起,您的账号:" + username + " 已被删除");
         }
         if (UserStatus.DISABLE.getCode().equals(loginUser.getStatus())) {
-            asyncManager.insertLog(tenantId,loginUser.getUserName(), Constants.LOGIN_FAIL, "用户已停用,请联系管理员", null);
+            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
+            asyncManager.insertLog(request, tenantId,loginUser.getUserName(), Constants.LOGIN_FAIL, "用户已停用,请联系管理员", null);
             throw new BusinessException("对不起,您的账号:" + loginUser.getUserName() + " 已停用");
         }
 
@@ -227,13 +243,15 @@ public class SysLoginService {
         if (loginUser != null && loginUser.getDeptId() != null) {
             deptId = loginUser.getDeptId().intValue();
         }
-        asyncManager.insertLog(tenantId,loginUser.getUserName(), Constants.LOGIN_SUCCESS, "登录成功", deptId);
+        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
+        asyncManager.insertLog(request, tenantId,loginUser.getUserName(), Constants.LOGIN_SUCCESS, "登录成功", deptId);
         return loginUser;
     }
 
 
     public void logout(Integer tenantId,String loginName) {
-        asyncManager.insertLog(tenantId,loginName, Constants.LOGOUT, "退出成功", null);
+        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
+        asyncManager.insertLog(request, tenantId,loginName, Constants.LOGOUT, "退出成功", null);
     }
 
     /**
@@ -259,7 +277,8 @@ public class SysLoginService {
         sysUser.setNickName(username);
         sysUser.setPassword(SecurityUtils.encryptPassword(password));
         sysUserService.register(BeanMapperUtils.map(sysUser, SysUser.class));
-        asyncManager.insertLog(SecurityUtils.getTenantId(),username, Constants.REGISTER, "注册成功", null);
+        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
+        asyncManager.insertLog(request, SecurityUtils.getTenantId(),username, Constants.REGISTER, "注册成功", null);
     }
 
 

+ 13 - 0
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/service/SysPersonService.java

@@ -3,6 +3,9 @@ package com.usky.system.service;
 import com.usky.system.domain.SysPerson;
 import com.usky.common.mybatis.core.CrudService;
 
+import java.util.List;
+import java.util.Map;
+
 /**
  * <p>
  * 人员信息 服务类
@@ -18,4 +21,14 @@ public interface SysPersonService extends CrudService<SysPerson> {
      * @return
      */
     SysPerson getsysPerson(Long userid);
+
+    /**
+     * 根据 userId 从 sys_user / 部门 / 岗位 填充人员的 dept、post 展示字段;userId 为空或查无用户时置为 null。
+     */
+    void fillDeptAndPostFromUser(SysPerson person, Long userId);
+
+    /**
+     * 批量填充列表中人员的部门、岗位(personId -> userId 由调用方传入)。
+     */
+    void fillDeptAndPostForList(List<SysPerson> list, Map<Integer, Long> personIdToUserId);
 }

+ 1 - 0
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/service/SysUserPersonService.java

@@ -13,4 +13,5 @@ import com.usky.common.mybatis.core.CrudService;
  */
 public interface SysUserPersonService extends CrudService<SysUserPerson> {
 
+    public Integer upIsLoginNotify(Long userId, Integer isLoginNotify);
 }

+ 12 - 4
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/service/SysUserTenantService.java

@@ -3,6 +3,7 @@ package com.usky.system.service;
 import com.usky.system.domain.SysTenant;
 import com.usky.system.domain.SysUserTenant;
 import com.usky.common.mybatis.core.CrudService;
+import com.usky.system.service.vo.TenantPlatformVo;
 
 import java.util.List;
 
@@ -20,7 +21,7 @@ public interface SysUserTenantService extends CrudService<SysUserTenant> {
      *
      * @param sysUserTenant
      */
-    public void insertInviteUser(SysUserTenant sysUserTenant);
+    void insertInviteUser(SysUserTenant sysUserTenant);
 
     /**
      * 企业解绑用户
@@ -28,15 +29,22 @@ public interface SysUserTenantService extends CrudService<SysUserTenant> {
      * @param tenantId 租户ID
      * @param userId 用户ID
      */
-    public void deleteUserTenant(Integer tenantId,Long userId);
+    void deleteUserTenant(Integer tenantId,Long userId);
 
     /**
      * 根据用户查询企业下拉框
      */
-    public List<SysTenant> getTenantByUser(Long userId);
+    List<SysTenant> getTenantByUser(Long userId);
 
     /**
      * 根据用户查询绑定状态
      */
-    public Boolean getIdByUser(Integer tenantId,Long userId);
+    Boolean getIdByUser(Integer tenantId,Long userId);
+
+    /**
+     * 根据用户查询默认租户ID
+     */
+    Integer getIsDefaultByUser(Long userId);
+
+    void updateUserTenant(SysUserTenant userTenant);
 }

+ 17 - 0
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/service/config/Gzip/GzipConfig.java

@@ -0,0 +1,17 @@
+package com.usky.system.service.config.Gzip;
+
+import com.planetj.servlet.filter.compression.CompressingFilter;
+import org.springframework.boot.web.servlet.FilterRegistrationBean;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class GzipConfig {
+    @Bean
+    public FilterRegistrationBean<CompressingFilter> gzipFilter() {
+        FilterRegistrationBean<CompressingFilter> bean = new FilterRegistrationBean<>();
+        bean.setFilter(new CompressingFilter());
+        bean.addUrlPatterns("/*");
+        return bean;
+    }
+}

+ 81 - 9
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/service/impl/MceContentServiceImpl.java

@@ -10,9 +10,12 @@ import com.usky.system.service.MceMbuserService;
 import com.usky.system.service.config.websocket.HttpClientUtils;
 import com.usky.system.service.vo.SendWeChatMessageRequestVO;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
 import org.springframework.scheduling.annotation.Async;
 import org.springframework.stereotype.Service;
+import com.usky.system.domain.MceRequestVO;
 
 /**
  * <p>
@@ -29,21 +32,24 @@ public class MceContentServiceImpl extends AbstractCrudService<MceContentMapper,
     @Autowired
     private MceMbuserService mceMbuserService;
 
-    //异步多线程调用
-    @Async("asyncServiceExecutor")
-    public void sendApp(JSONObject mceReceiveVO, String cids, Integer mceReceiveId, Integer sendType){
-        if (sendType.equals(0)){
-            String appUrl = "https://fc-mp-85a26092-1305-4bf1-998f-b609512c8f7b.next.bspapp.com/uniPushMessage";
+    @Value("${appUrl}")
+    private String appUrl;
+
+    // 异步多线程调用
+    @Override
+    @Async
+    public void sendApp(JSONObject mceReceiveVO, String cids, Integer mceReceiveId, Integer sendType) {
+        if (sendType.equals(0)) {
             JsonObject jsonObject = new JsonObject();
             JsonObject jsonObject1 = new JsonObject();
             jsonObject1.addProperty("infoType", mceReceiveVO.get("infoType").toString());
-            jsonObject1.addProperty("moduleId", (int)mceReceiveVO.get("id"));
+            jsonObject1.addProperty("moduleId", (int) mceReceiveVO.get("id"));
             jsonObject.addProperty("cids", cids);
             jsonObject.addProperty("title", mceReceiveVO.get("infoTitle").toString());
             jsonObject.addProperty("content", mceReceiveVO.get("infoContent").toString());
-            jsonObject.add("payload",jsonObject1);
-            String resultString = HttpClientUtils.doPostJson(appUrl,jsonObject.toString());
-        }else if (sendType.equals(1)){
+            jsonObject.add("payload", jsonObject1);
+            String resultString = HttpClientUtils.doPostJson(appUrl, jsonObject.toString());
+        } else if (sendType.equals(1)) {
             SendWeChatMessageRequestVO sendWeChatMessageRequestVO = new SendWeChatMessageRequestVO();
             sendWeChatMessageRequestVO.setInfoContent(mceReceiveVO.get("infoContent").toString());
             sendWeChatMessageRequestVO.setInfoTitle(mceReceiveVO.get("infoTitle").toString());
@@ -56,4 +62,70 @@ public class MceContentServiceImpl extends AbstractCrudService<MceContentMapper,
             mceMbuserService.sendWeChatMessage(sendWeChatMessageRequestVO);
         }
     }
+
+    @Override
+    @Async
+    public void sendAppNew(MceRequestVO mceReceiveVO, String cids, Integer mceReceiveId, Integer sendType) {
+        if (sendType.equals(0)) {
+            JsonObject jsonObject = new JsonObject();
+            JsonObject jsonObject1 = new JsonObject();
+            jsonObject1.addProperty("infoType", mceReceiveVO.getInfoType());
+            jsonObject1.addProperty("moduleId", mceReceiveVO.getId());
+            jsonObject.addProperty("cids", cids);
+            jsonObject.addProperty("title", mceReceiveVO.getInfoTitle());
+            if ("3".equals(mceReceiveVO.getInfoType())) {
+                jsonObject.addProperty("content", mceReceiveVO.getInfoContent().split("-")[0]);
+            }
+            jsonObject.addProperty("content", mceReceiveVO.getInfoContent());
+            jsonObject.add("payload", jsonObject1);
+            String resultString = HttpClientUtils.doPostJson(appUrl, jsonObject.toString());
+        } else if (sendType.equals(1)) {
+            SendWeChatMessageRequestVO sendWeChatMessageRequestVO = new SendWeChatMessageRequestVO();
+            sendWeChatMessageRequestVO.setInfoContent(mceReceiveVO.getInfoContent());
+            sendWeChatMessageRequestVO.setInfoTitle(mceReceiveVO.getInfoTitle());
+            sendWeChatMessageRequestVO.setInfoId(mceReceiveId);
+            sendWeChatMessageRequestVO.setOpenId(cids);
+            sendWeChatMessageRequestVO.setInfoType(mceReceiveVO.getInfoType());
+            if (StringUtils.isNotEmpty(mceReceiveVO.getInfoTypeName())) {
+                sendWeChatMessageRequestVO.setInfoTypeName(mceReceiveVO.getInfoTypeName());
+            }
+            if (StringUtils.isNotEmpty(mceReceiveVO.getIpAddress())) {
+                sendWeChatMessageRequestVO.setIpAddress(mceReceiveVO.getIpAddress());
+            }
+            if (StringUtils.isNotEmpty(mceReceiveVO.getUserName())) {
+                sendWeChatMessageRequestVO.setUserName(mceReceiveVO.getUserName());
+            }
+            if (StringUtils.isNotEmpty(mceReceiveVO.getLoginAddress())) {
+                sendWeChatMessageRequestVO.setLoginAddress(mceReceiveVO.getLoginAddress());
+            }
+            if (StringUtils.isNotEmpty(mceReceiveVO.getLoginType())) {
+                sendWeChatMessageRequestVO.setLoginType(mceReceiveVO.getLoginType());
+            }
+            if (StringUtils.isNotEmpty(mceReceiveVO.getApprovalResult())) {
+                sendWeChatMessageRequestVO.setApprovalResult(mceReceiveVO.getApprovalResult());
+            }
+            if (StringUtils.isNotEmpty(mceReceiveVO.getProcessName())) {
+                sendWeChatMessageRequestVO.setProcessName(mceReceiveVO.getProcessName());
+            }
+            if (StringUtils.isNotEmpty(mceReceiveVO.getApprovalNode())) {
+                sendWeChatMessageRequestVO.setApprovalNode(mceReceiveVO.getApprovalNode());
+            }
+            if (StringUtils.isNotEmpty(mceReceiveVO.getRealName())) {
+                sendWeChatMessageRequestVO.setRealName(mceReceiveVO.getRealName());
+            }
+            if (StringUtils.isNotEmpty(mceReceiveVO.getOaType())) {
+                sendWeChatMessageRequestVO.setOaType(mceReceiveVO.getOaType());
+            }
+            if (StringUtils.isNotEmpty(mceReceiveVO.getDeviceId())) {
+                sendWeChatMessageRequestVO.setDeviceId(mceReceiveVO.getDeviceId());
+            }
+            if (StringUtils.isNotEmpty(mceReceiveVO.getAlarmTime())) {
+                sendWeChatMessageRequestVO.setAlarmTime(mceReceiveVO.getAlarmTime());
+            }
+            if (StringUtils.isNotEmpty(mceReceiveVO.getRemark())) {
+                sendWeChatMessageRequestVO.setRemark(mceReceiveVO.getRemark());
+            }
+            mceMbuserService.sendWeChatMessage(sendWeChatMessageRequestVO);
+        }
+    }
 }

+ 144 - 49
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/service/impl/MceMbuserServiceImpl.java

@@ -7,14 +7,12 @@ import com.usky.common.core.exception.BusinessException;
 import com.usky.common.redis.core.RedisHelper;
 import com.usky.system.domain.MceMbuser;
 import com.usky.system.mapper.MceMbuserMapper;
-import com.usky.system.service.ISysDictDataService;
 import com.usky.system.service.MceMbuserService;
 import com.usky.system.constant.constant;
 import com.usky.common.mybatis.core.AbstractCrudService;
-import com.usky.system.service.vo.SendWeChatMessageRequestVO;
-import com.usky.system.service.vo.TemplateData;
-import com.usky.system.service.vo.TemplateMsgEntityVO;
+import com.usky.system.service.vo.*;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.ResponseEntity;
 import org.springframework.stereotype.Service;
@@ -61,13 +59,13 @@ public class MceMbuserServiceImpl extends AbstractCrudService<MceMbuserMapper, M
         return null;
     }
 
-    public static long getTimeDifference(String oldTime,String newTime) throws ParseException {
+    public static long getTimeDifference(String oldTime, String newTime) throws ParseException {
 
         SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
-        long NTime =df.parse(newTime).getTime();
-        //从对象中拿到时间
+        long NTime = df.parse(newTime).getTime();
+        // 从对象中拿到时间
         long OTime = df.parse(oldTime).getTime();
-        long diff=(NTime-OTime)/1000/60;
+        long diff = (NTime - OTime) / 1000 / 60;
         return diff;
     }
 
@@ -78,61 +76,158 @@ public class MceMbuserServiceImpl extends AbstractCrudService<MceMbuserMapper, M
         String infoContent = requestVO.getInfoContent();
         Integer infoId = requestVO.getInfoId();
         String openId = requestVO.getOpenId();
-
-        //access_token时效校验,判断获取access_token获取时间是否超过有效时间,超过就调用更新,保证一直有效
-        if(!redisHelper.hasKey("access_key")){
+        String infoType = requestVO.getInfoType();
+        String infoTypeName = requestVO.getInfoTypeName();
+        String oaType = requestVO.getOaType();
+        // access_token时效校验,判断获取access_token获取时间是否超过有效时间,超过就调用更新,保证一直有效
+        if (!redisHelper.hasKey("access_key")) {
             redisHelper.set("access_time", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
-            redisHelper.set("access_key",this.getWeChatAccessToken());
-        }else{
-            try{
-                String access_time = redisHelper.get("access_time").toString();
-                String now_time = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
-                long i = getTimeDifference(access_time,now_time);
-                if(i > 115){ //大于115分钟
-                    redisHelper.set("access_time",LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
-                    redisHelper.set("access_key",this.getWeChatAccessToken());
+            redisHelper.set("access_key", this.getWeChatAccessToken());
+        } else {
+            try {
+                String accessTime = redisHelper.get("access_time").toString();
+                String nowTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
+                long i = getTimeDifference(accessTime, nowTime);
+                // 大于115分钟
+                if (i > 115) {
+                    redisHelper.set("access_time", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
+                    redisHelper.set("access_key", this.getWeChatAccessToken());
                 }
-            }catch (Exception e){
+            } catch (Exception e) {
                 throw new BusinessException(e.getMessage());
             }
 
         }
 
         Object obj = redisHelper.get("access_key");
-        if(obj == null){
-            throw new BusinessException("token不能为空");
+        if (obj == null) {
+            log.error("消息接收id:" + requestVO.getInfoId() + ",token为空,发送微信服务号消息失败");
+            return null;
         }
 
-        String token = obj.toString();
+        String tUrl;
+        String templateId = "";
 
-        TemplateMsgEntityVO messageVo=new TemplateMsgEntityVO();
-        messageVo.setTTitle(infoTitle);
-        messageVo.setTKeyword1(infoContent);
-        messageVo.setTKeyword3(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
-        messageVo.setTRemark(infoContent);
-        if(Objects.nonNull(requestVO.getInfoTypeName())){
-            messageVo.setTUrl(String.format(constant.WE_CHAT_CUSTOMER_CALL_URL,requestVO.getInfoType(),requestVO.getInfoTypeName(),infoId));
-            messageVo.setTKeyword2(requestVO.getInfoTypeName());
-        }else{
-            messageVo.setTUrl(String.format(constant.WE_CHAT_CUSTOMER_CALL_URL1,requestVO.getInfoType(),infoId));
-            messageVo.setTKeyword2("");
+        Map<String, TemplateData> data = new HashMap<>();
+        String nowTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
+
+        switch (requestVO.getInfoType()) {
+            // 登录成功通知
+            case "0":
+                // 登录时间
+                data.put("time3", new TemplateData(nowTime, "#173177"));
+                // 登录账号 userName
+                data.put("thing6", new TemplateData(requestVO.getUserName(), "#173177"));
+                // 登录IP
+                data.put("character_string8", new TemplateData(requestVO.getIpAddress(), "#173177"));
+                // 登录地点
+                data.put("thing9", new TemplateData(requestVO.getLoginAddress(), "#173177"));
+                // 登录方式
+                data.put("thing10", new TemplateData(requestVO.getLoginType(), "#173177"));
+                // 设置公众号模板消息ID
+                templateId = constant.WE_CHAT_LOGIN_TEMPLATE_ID;
+                break;
+
+            /* 通知公告&工作报告通知(工单已完成通知)
+             * 工单标题{{thing9.DATA}}
+             * 发起人{{thing8.DATA}}
+             * 完成时间{{time12.DATA}}
+             **/
+            case "1":
+                data.put("thing9", new TemplateData("通知公告-" + requestVO.getInfoContent(), "#173177"));
+                data.put("thing8", new TemplateData(requestVO.getRealName(), "#173177"));
+                data.put("time12", new TemplateData(nowTime, "#173177"));
+                templateId = constant.WE_CHAT_WORK_TEMPLATE_ID;
+                break;
+            case "5":
+                data.put("thing9", new TemplateData("报告提醒-" + requestVO.getInfoContent(), "#173177"));
+                data.put("thing8", new TemplateData(requestVO.getRealName(), "#173177"));
+                data.put("time12", new TemplateData(nowTime, "#173177"));
+                // 设置公众号模板消息ID
+                templateId = constant.WE_CHAT_WORK_TEMPLATE_ID;
+                break;
+
+            case "3":
+                /* OA系统流程审批通知
+                 * 流程名称{{thing7.DATA}}
+                 * 审批节点{{thing8.DATA}}
+                 * 发起人{{thing13.DATA}}
+                 * 发起时间{{time10.DATA}}
+                 * 审批结果{{const21.DATA}}
+                 **/
+                data.put("thing7", new TemplateData(requestVO.getProcessName(), "#173177"));
+                data.put("thing8", new TemplateData(requestVO.getApprovalNode(), "#173177"));
+                data.put("thing13", new TemplateData(requestVO.getRealName(), "#173177"));
+                data.put("time10", new TemplateData(nowTime, "#173177"));
+                data.put("const21", new TemplateData(requestVO.getApprovalResult(), "#173177"));
+
+                // 设置公众号模板消息ID
+                templateId = constant.WE_CHAT_OA_TEMPLATE_ID;
+                break;
+
+            case "2":
+                TemplateMsgEntityVO messageVo = new TemplateMsgEntityVO();
+                messageVo.setTTitle(infoTitle);
+                messageVo.setTKeyword1(infoContent);
+                messageVo.setTKeyword2(infoType);
+                messageVo.setTKeyword3(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
+                messageVo.setTRemark(infoContent);
+                /* 设备预警信息提醒
+                 * {{first.DATA}}
+                 * 设备号:{{keyword1.DATA}}
+                 * 报警类型:{{keyword2.DATA}}
+                 * 时间:{{keyword3.DATA}}
+                 * 备注:{{remark.DATA}}
+                 **/
+                messageVo.setTemplateId(constant.WE_CHAT_TEMPLATE_ID);
+                data.put("first", new TemplateData(messageVo.getTTitle(), "#44b549"));
+                data.put("keyword1", new TemplateData(messageVo.getTKeyword1(), "#173177"));
+                data.put("keyword2", new TemplateData(messageVo.getTKeyword2(), "#173177"));
+                data.put("keyword3", new TemplateData(messageVo.getTKeyword3(), "#173177"));
+                data.put("remark", new TemplateData(messageVo.getTRemark(), "#173177"));
+
+                templateId = messageVo.getTemplateId();
+                break;
+            case "4":
+                /* 设备预警信息提醒
+                 * {{first.DATA}}
+                 * 设备号:{{keyword1.DATA}}
+                 * 报警类型:{{keyword2.DATA}}
+                 * 时间:{{keyword3.DATA}}
+                 * 备注:{{remark.DATA}}
+                 **/
+                data.put("first", new TemplateData(requestVO.getInfoTitle(), "#44b549"));
+                data.put("keyword1", new TemplateData(requestVO.getDeviceId(), "#173177"));
+                data.put("keyword2", new TemplateData(requestVO.getInfoContent(), "#173177"));
+                data.put("keyword3", new TemplateData(requestVO.getAlarmTime(), "#173177"));
+                data.put("remark", new TemplateData(requestVO.getRemark(), "#173177"));
+
+                // 设置公众号模板消息ID
+                templateId = constant.WE_CHAT_TEMPLATE_ID;
+                break;
         }
 
-        messageVo.setTemplateId(constant.WE_CHAT_TEMPLATE_ID);
+        log.info("oaType:{}", oaType);
+        // 回调地址
+        if ("3".equals(requestVO.getInfoType())) {
+            tUrl = String.format(constant.WE_CHAT_CUSTOMER_CALL_URL3, infoType, infoTypeName, infoId, oaType);
+        } else if (Objects.nonNull(infoTypeName)) {
+            tUrl = String.format(constant.WE_CHAT_CUSTOMER_CALL_URL, infoType, infoTypeName, infoId);
+        } else {
+            tUrl = String.format(constant.WE_CHAT_CUSTOMER_CALL_URL1, infoType, infoId);
+        }
 
-        String requestUrl = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token="  + token;
-        Map<String,Object> content=new HashMap<>();
-        Map<String, TemplateData> data = new HashMap<>();
-        data.put("first",new TemplateData(messageVo.getTTitle(),"#44b549"));
-        data.put("keyword1",new TemplateData(messageVo.getTKeyword1(),"#173177"));
-        data.put("keyword2",new TemplateData(messageVo.getTKeyword2(),"#173177"));
-        data.put("keyword3",new TemplateData(messageVo.getTKeyword3(),"#173177"));
-        data.put("remark",new TemplateData(messageVo.getTRemark(),"#173177"));
-
-        content.put("touser",openId);
-        content.put("url",messageVo.getTUrl());
-        content.put("template_id",messageVo.getTemplateId());
-        content.put("data",data);
+        String token = obj.toString();
+        String requestUrl = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=" + token;
+        Map<String, Object> content = new HashMap<>();
+        content.put("touser", openId);
+        if (!"0".equals(requestVO.getInfoType())) {
+            content.put("url", tUrl);
+        }
+        if (StringUtils.isNotBlank(templateId)) {
+            content.put("template_id", templateId);
+        }
+        content.put("data", data);
         String resp = HttpUtil.post(requestUrl, JSONUtil.parseObj(content).toString());
         System.out.println(content.toString());
         System.out.println(JSONUtil.parseObj(content));

+ 579 - 77
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/service/impl/MceReceiveServiceImpl.java

@@ -10,22 +10,24 @@ import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
 import com.baomidou.mybatisplus.core.toolkit.StringUtils;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.ruoyi.common.datascope.annotation.DataScope;
-import com.ruoyi.common.datascope.context.DataScopeContextHolder;
-import com.usky.common.core.bean.ApiResult;
 import com.usky.common.core.bean.CommonPage;
+import com.usky.common.core.exception.BusinessException;
 import com.usky.common.security.utils.SecurityUtils;
-import com.usky.system.RemoteUserService;
 import com.usky.system.domain.*;
 import com.usky.system.mapper.MceReceiveMapper;
+import com.usky.system.mapper.MceSettingMapper;
 import com.usky.system.mapper.SysUserMapper;
 import com.usky.system.service.*;
 import com.usky.common.mybatis.core.AbstractCrudService;
+import com.usky.system.service.vo.MceReceiveResponseVO;
+import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.scheduling.annotation.Async;
 import org.springframework.stereotype.Service;
 
 import java.time.LocalDateTime;
 import java.util.*;
+import java.util.stream.Collectors;
 
 /**
  * <p>
@@ -35,6 +37,7 @@ import java.util.*;
  * @author han
  * @since 2024-05-09
  */
+@Slf4j
 @Service
 public class MceReceiveServiceImpl extends AbstractCrudService<MceReceiveMapper, MceReceive> implements MceReceiveService {
     @Autowired
@@ -54,47 +57,73 @@ public class MceReceiveServiceImpl extends AbstractCrudService<MceReceiveMapper,
 
     @Autowired
     private SysUserMapper userMapper;
+    @Autowired
+    private MceSettingMapper mceSettingMapper;
+
+    @Autowired
+    private MceReceiveMapper mceReceiveMapper;
+
+    @Autowired
+    private SysUserPersonService sysUserPersonService;
 
     @Override
-    public CommonPage<Object> mceList(String infoTitle, String infoType, String startTime, String endTime, Integer id, Integer current, Integer size) {
+    public CommonPage<Object> mceList(String infoTitle, String infoType, String startTime, String endTime, Integer id, Integer infoId, Integer current, Integer size) {
         List<Object> list = new ArrayList<>();
+
+        if (infoId != null) {
+            LambdaQueryWrapper<MceReceive> query = Wrappers.lambdaQuery();
+            query.select(MceReceive::getContentId).eq(MceReceive::getId, infoId);
+            MceReceive mceReceive = mceReceiveMapper.selectOne(query);
+            if (mceReceive != null) {
+                id = mceReceive.getContentId();
+            } else {
+                log.error("消息内容已不存在!消息id:{}", infoId);
+                throw new BusinessException("消息内容已不存在!");
+            }
+        }
+
         LambdaQueryWrapper<MceContent> lambdaQuery1 = Wrappers.lambdaQuery();
         lambdaQuery1.select(MceContent::getId, MceContent::getInfoTitle, MceContent::getInfoContent)
-                .like(StringUtils.isNotBlank(infoTitle),MceContent::getInfoTitle,infoTitle)
-                .eq(id != null,MceContent::getId,id);
+                .like(StringUtils.isNotBlank(infoTitle), MceContent::getInfoTitle, infoTitle)
+                .eq(id != null, MceContent::getId, id)
+                .eq(MceContent::getTenantId, SecurityUtils.getTenantId());
         List<MceContent> list1 = mceContentService.list(lambdaQuery1);
         IPage<MceReceive> page = new Page<>(current, size);
         List<Integer> contentIds = new ArrayList<>();
-        if (CollectionUtils.isNotEmpty(list1)){
-            for(int i=0;i<list1.size();i++){
+        if (CollectionUtils.isNotEmpty(list1)) {
+            for (int i = 0; i < list1.size(); i++) {
                 contentIds.add(list1.get(i).getId());
             }
             Long userId = SecurityUtils.getUserId();
             LambdaQueryWrapper<MceReceive> lambdaQuery = Wrappers.lambdaQuery();
             lambdaQuery.select(MceReceive::getId, MceReceive::getInfoType,
-                    MceReceive::getContentId, MceReceive::getReadFlag, MceReceive::getCreateTime,
-                    MceReceive::getReceiverId,MceReceive::getModuleId)
-                    .between(StringUtils.isNotBlank(startTime)&&StringUtils.isNotBlank(endTime),MceReceive::getCreateTime,
-                            startTime,endTime)
-                    .eq(StringUtils.isNotBlank(infoType),MceReceive::getInfoType, infoType)
+                            MceReceive::getContentId, MceReceive::getReadFlag, MceReceive::getCreateTime,
+                            MceReceive::getReceiverId, MceReceive::getModuleId, MceReceive::getCreateBy, MceReceive::getIssuerName)
+                    .between(StringUtils.isNotBlank(startTime) && StringUtils.isNotBlank(endTime), MceReceive::getCreateTime,
+                            startTime, endTime)
+                    .eq(StringUtils.isNotBlank(infoType), MceReceive::getInfoType, infoType)
                     .eq(MceReceive::getReceiverId, SecurityUtils.getUserId())
-                    .in(CollectionUtils.isNotEmpty(contentIds),MceReceive::getContentId,contentIds)
+                    .in(CollectionUtils.isNotEmpty(contentIds), MceReceive::getContentId, contentIds)
                     .orderByDesc(MceReceive::getId);
+
 //                .inSql(StringUtils.isNotBlank(infoTitle),MceReceive::getContentId,"SELECT id FROM mce_content WHERE " +
 //                        "info_title like '%" + infoTitle + "%' AND tenant_id = "+SecurityUtils.getTenantId()+"");
-            page = this.page(page,lambdaQuery);
+            page = this.page(page, lambdaQuery);
             if (CollectionUtils.isNotEmpty(page.getRecords())) {
                 for (int i = 0; i < page.getRecords().size(); i++) {
+                    String infoType1 = page.getRecords().get(i).getInfoType();
                     Map<String, Object> map = new HashMap<>();
                     map.put("id", page.getRecords().get(i).getId());
-                    map.put("infoType", page.getRecords().get(i).getInfoType());
+                    map.put("infoType", infoType1);
                     map.put("readFlag", page.getRecords().get(i).getReadFlag());
                     map.put("moduleId", page.getRecords().get(i).getModuleId());
                     map.put("createTime", page.getRecords().get(i).getCreateTime());
+                    map.put("createBy", page.getRecords().get(i).getCreateBy());
+                    map.put("issuerName", page.getRecords().get(i).getIssuerName());
                     if (CollectionUtils.isNotEmpty(list1)) {
                         for (int j = 0; j < list1.size(); j++) {
                             if (page.getRecords().get(i).getContentId().equals(list1.get(j).getId())) {
-                                map.put("contentId",list1.get(j).getId());
+                                map.put("contentId", list1.get(j).getId());
                                 map.put("infoTitle", list1.get(j).getInfoTitle());
                                 map.put("infoContent", list1.get(j).getInfoContent());
                             }
@@ -104,7 +133,7 @@ public class MceReceiveServiceImpl extends AbstractCrudService<MceReceiveMapper,
                 }
             }
         }
-        return new CommonPage<>(list,page.getTotal(),page.getCurrent(),page.getSize());
+        return new CommonPage<>(list, page.getTotal(), page.getCurrent(), page.getSize());
     }
 
     @Override
@@ -112,16 +141,16 @@ public class MceReceiveServiceImpl extends AbstractCrudService<MceReceiveMapper,
     public CommonPage<Object> mceManageList(String infoTitle, String infoType, String startTime, String endTime, Integer current, Integer size) {
         List<Object> list = new ArrayList<>();
         IPage<MceContent> page = new Page<>(current, size);
-        //查询消息内容
+        // 查询消息内容
         LambdaQueryWrapper<MceContent> lambdaQuery1 = Wrappers.lambdaQuery();
-        lambdaQuery1.select(MceContent::getId, MceContent::getInfoTitle, MceContent::getInfoContent, MceContent::getCreateTime,MceContent::getInfoType)
-                .like(StringUtils.isNotBlank(infoTitle),MceContent::getInfoTitle,infoTitle)
-                .between(StringUtils.isNotBlank(startTime)&&StringUtils.isNotBlank(endTime),MceContent::getCreateTime, startTime,endTime)
-                .eq(StringUtils.isNotBlank(infoType),MceContent::getInfoType, infoType)
+        lambdaQuery1.select(MceContent::getId, MceContent::getInfoTitle, MceContent::getInfoContent, MceContent::getCreateTime, MceContent::getInfoType)
+                .like(StringUtils.isNotBlank(infoTitle), MceContent::getInfoTitle, infoTitle)
+                .between(StringUtils.isNotBlank(startTime) && StringUtils.isNotBlank(endTime), MceContent::getCreateTime, startTime, endTime)
+                .eq(StringUtils.isNotBlank(infoType), MceContent::getInfoType, infoType)
 //                .apply(DataScopeContextHolder.getDataScopeSql())
-                .eq(MceContent::getTenantId,SecurityUtils.getTenantId())
+                .eq(MceContent::getTenantId, SecurityUtils.getTenantId())
                 .orderByDesc(MceContent::getId);
-        page = mceContentService.page(page,lambdaQuery1);
+        page = mceContentService.page(page, lambdaQuery1);
 
         if (CollectionUtils.isNotEmpty(page.getRecords())) {
             List<Integer> contentIds = new ArrayList<>();
@@ -129,11 +158,11 @@ public class MceReceiveServiceImpl extends AbstractCrudService<MceReceiveMapper,
                 contentIds.add(page.getRecords().get(i).getId());
             }
             QueryWrapper<MceReceive> queryWrapper = Wrappers.query();
-            queryWrapper.select("content_id AS contentId","COUNT(read_flag=0 or null) as notReadCount","COUNT" +
-                    "(read_flag=1 or null) as readCount","issuer_name AS issuerName")
-                    .in("content_id",contentIds)
-                    .groupBy("content_id","issuer_name");
-            List<Map<String,Object>> readStatisticList = this.listMaps(queryWrapper);
+            queryWrapper.select("content_id AS contentId", "COUNT(read_flag=0 or null) as notReadCount", "COUNT" +
+                            "(read_flag=1 or null) as readCount", "issuer_name AS issuerName")
+                    .in("content_id", contentIds)
+                    .groupBy("content_id", "issuer_name");
+            List<Map<String, Object>> readStatisticList = this.listMaps(queryWrapper);
             for (int i = 0; i < page.getRecords().size(); i++) {
                 Map<String, Object> map = new HashMap<>();
                 map.put("id", page.getRecords().get(i).getId());
@@ -142,7 +171,7 @@ public class MceReceiveServiceImpl extends AbstractCrudService<MceReceiveMapper,
                 map.put("infoType", page.getRecords().get(i).getInfoType());
                 map.put("createTime", page.getRecords().get(i).getCreateTime());
                 for (int j = 0; j < readStatisticList.size(); j++) {
-                    if (page.getRecords().get(i).getId().equals(readStatisticList.get(j).get("contentId"))){
+                    if (page.getRecords().get(i).getId().equals(readStatisticList.get(j).get("contentId"))) {
                         map.put("notReadCount", readStatisticList.get(j).get("notReadCount"));
                         map.put("readCount", readStatisticList.get(j).get("readCount"));
                         map.put("userName", readStatisticList.get(j).get("issuerName"));
@@ -152,15 +181,15 @@ public class MceReceiveServiceImpl extends AbstractCrudService<MceReceiveMapper,
             }
         }
 
-        return new CommonPage<>(list,page.getTotal(),page.getCurrent(),page.getSize());
+        return new CommonPage<>(list, page.getTotal(), page.getCurrent(), page.getSize());
     }
 
     @Override
     public CommonPage<MceReceive> mceManageById(Integer id, Integer current, Integer size) {
         IPage<MceReceive> page = new Page<>(current, size);
         LambdaQueryWrapper<MceReceive> lambdaQuery = Wrappers.lambdaQuery();
-        lambdaQuery.eq(MceReceive::getContentId,id);
-        page = this.page(page,lambdaQuery);
+        lambdaQuery.eq(MceReceive::getContentId, id);
+        page = this.page(page, lambdaQuery);
 //        if (CollectionUtils.isNotEmpty(page.getRecords())) {
 //            List<Integer> userIds = new ArrayList<>();
 //            for (int i = 0; i < page.getRecords().size(); i++) {
@@ -183,7 +212,7 @@ public class MceReceiveServiceImpl extends AbstractCrudService<MceReceiveMapper,
 //                }
 //            }
 //        }
-        return new CommonPage<>(page.getRecords(),page.getTotal(),page.getCurrent(),page.getSize());
+        return new CommonPage<>(page.getRecords(), page.getTotal(), page.getCurrent(), page.getSize());
     }
 
     @Override
@@ -192,15 +221,15 @@ public class MceReceiveServiceImpl extends AbstractCrudService<MceReceiveMapper,
         LocalDateTime oneYearAgo = currentDate.minusYears(1);
         LocalDateTime zeroTime = oneYearAgo.withHour(0).withMinute(0).withSecond(0);
         QueryWrapper<MceReceive> queryWrapper = Wrappers.query();
-        queryWrapper.select("COUNT(read_flag=0 or null) as notReadCount","COUNT(read_flag=1 or null) as readCount"
-                ,"info_type AS infoType")
-                .eq("receiver_id",SecurityUtils.getUserId())
-                .between("create_time",zeroTime,currentDate)
+        queryWrapper.select("COUNT(read_flag=0 or null) as notReadCount", "COUNT(read_flag=1 or null) as readCount"
+                        , "info_type AS infoType")
+                .eq("receiver_id", SecurityUtils.getUserId())
+                .between("create_time", zeroTime, currentDate)
                 .groupBy("info_type");
-        List<Map<String,Object>> readStatisticList = this.listMaps(queryWrapper);
+        List<Map<String, Object>> readStatisticList = this.listMaps(queryWrapper);
         LambdaQueryWrapper<MceReceive> lambdaQuery = Wrappers.lambdaQuery();
-        lambdaQuery.eq(MceReceive::getReceiverId,SecurityUtils.getUserId())
-                .eq(MceReceive::getReadFlag,0);
+        lambdaQuery.eq(MceReceive::getReceiverId, SecurityUtils.getUserId())
+                .eq(MceReceive::getReadFlag, 0);
         Integer notReadCount = this.count(lambdaQuery);
         Map<String, Object> map = new HashMap<>();
         map.put("notReadCount", notReadCount);
@@ -209,19 +238,19 @@ public class MceReceiveServiceImpl extends AbstractCrudService<MceReceiveMapper,
     }
 
     @Override
-    public void updateMceReceive(MceReceive mceReceive){
+    public void updateMceReceive(MceReceive mceReceive) {
         LambdaUpdateWrapper<MceReceive> updateWrapper = new UpdateWrapper<MceReceive>().lambda();
-        if (Objects.nonNull(mceReceive.getId())&&!mceReceive.getId().equals(0)){
-            updateWrapper.eq(MceReceive::getId,mceReceive.getId())
-                    .set(MceReceive::getReadFlag,1)
-                    .set(MceReceive::getUpdateBy,SecurityUtils.getUsername())
-                    .set(MceReceive::getUpdateTime,LocalDateTime.now());
-        }else {
-            updateWrapper.eq(MceReceive::getReceiverId,SecurityUtils.getUserId())
-                    .eq(MceReceive::getReadFlag,0)
-                    .set(MceReceive::getReadFlag,1)
-                    .set(MceReceive::getUpdateBy,SecurityUtils.getUsername())
-                    .set(MceReceive::getUpdateTime,LocalDateTime.now());
+        if (Objects.nonNull(mceReceive.getId()) && !mceReceive.getId().equals(0)) {
+            updateWrapper.eq(MceReceive::getId, mceReceive.getId())
+                    .set(MceReceive::getReadFlag, 1)
+                    .set(MceReceive::getUpdateBy, SecurityUtils.getUsername())
+                    .set(MceReceive::getUpdateTime, LocalDateTime.now());
+        } else {
+            updateWrapper.eq(MceReceive::getReceiverId, SecurityUtils.getUserId())
+                    .eq(MceReceive::getReadFlag, 0)
+                    .set(MceReceive::getReadFlag, 1)
+                    .set(MceReceive::getUpdateBy, SecurityUtils.getUsername())
+                    .set(MceReceive::getUpdateTime, LocalDateTime.now());
         }
         this.update(updateWrapper);
     }
@@ -236,21 +265,396 @@ public class MceReceiveServiceImpl extends AbstractCrudService<MceReceiveMapper,
         }
     }
 
+    @Async
+    @Override
+    public void addMceReceive(MceRequestVO mceRequestVO) {
+        log.info("本次发送消息内容: {}", mceRequestVO.toString());
+
+        // 补充信息类型名称
+        if (mceRequestVO.getInfoTypeName() == null) {
+            String infoTypeName = sysDictDataService.selectDictLabel("message_type", mceRequestVO.getInfoType());
+            mceRequestVO.setInfoTypeName(infoTypeName);
+        }
+
+        // 获取发送者租户ID
+        Integer tenantId = getUserTenantId(mceRequestVO.getUserName());
+        if (tenantId == null) {
+            log.error("获取用户租户ID失败,未找到用户: {}", mceRequestVO.getUserName());
+            return;
+        }
+
+        // 获取租户所有用户信息
+        List<SysUser> allUsers = userMapper.tenantIdUserList(tenantId);
+        if (CollectionUtils.isEmpty(allUsers)) {
+            log.warn("租户下未找到任何用户,租户ID: {}", tenantId);
+            return;
+        }
+
+        // 构建用户信息映射
+        Map<Long, SysUser> userIdToUserMap = allUsers.stream()
+                .collect(Collectors.toMap(SysUser::getUserId, user -> user));
+
+        Map<String, String> userNameToNickNameMap = allUsers.stream()
+                .collect(Collectors.toMap(SysUser::getUserName, SysUser::getNickName));
+
+
+
+        // 筛选目标用户
+        List<Long> targetUserIds = mceRequestVO.getUserIds();
+        List<Long> validUserIds = allUsers.stream()
+                .map(SysUser::getUserId)
+                .filter(targetUserIds::contains)
+                .collect(Collectors.toList());
+
+        if (CollectionUtils.isEmpty(validUserIds)) {
+            log.error("用户: {} 发送的{},id: {},抄送用户均不存在!消息发送终止",
+                    mceRequestVO.getUserName(), mceRequestVO.getInfoTypeName(), mceRequestVO.getId());
+            return;
+        }
+
+        // 获取用户消息配置
+        List<MceMbuser> mbUserList = mceMbuserService.list(Wrappers.lambdaQuery(MceMbuser.class)
+                .in(MceMbuser::getUserId, validUserIds));
+
+        if (CollectionUtils.isEmpty(mbUserList)) {
+            log.error("消息配置为空!用户id列表为: {},id: {},消息发送终止", validUserIds, mceRequestVO.getId());
+            return;
+        }
+
+        // 构建用户ID到消息配置的映射
+        Map<Long, MceMbuser> userIdToMbUserMap = mbUserList.stream()
+                .collect(Collectors.toMap(MceMbuser::getUserId, mbUser -> mbUser));
+
+        // 获取消息发送设置
+        List<MceSetting> settings = mceSettingService.list(Wrappers.lambdaQuery(MceSetting.class)
+                .eq(MceSetting::getCreateBy, mceRequestVO.getUserName()));
+
+        if (CollectionUtils.isEmpty(settings)) {
+            log.warn("未找到消息发送设置,用户: {}", mceRequestVO.getUserName());
+            return;
+        }
+
+        MceSetting setting = settings.get(0);
+        JSONObject appMode = JSONObject.parseObject(setting.getAppMode());
+        JSONObject wcMode = JSONObject.parseObject(setting.getWcMode());
+
+        // 处理每个目标用户的消息接收和发送
+        for (Long userId : validUserIds) {
+            SysUser user = userIdToUserMap.get(userId);
+            if (user == null) {
+                continue;
+            }
+
+            // 获取用户消息配置
+            MceMbuser mbUser = userIdToMbUserMap.get(userId);
+            if (mbUser == null) {
+                continue;
+            }
+
+            // 登录不需要新增消息记录
+            if ("0".equals(mceRequestVO.getInfoType())) {
+                handleMessageDelivery(mbUser, mceRequestVO, 0, appMode, wcMode);
+                return;
+            }
+
+            // 保存消息内容
+            Integer contentId = saveMessageContent(mceRequestVO, userIdToUserMap);
+            if (contentId == null) {
+                log.error("消息内容保存失败,用户: {}", mceRequestVO.getUserName());
+                return;
+            }
+
+            // 创建消息接收记录
+            MceReceive mceReceive = createMceReceive(user, contentId, mceRequestVO, userNameToNickNameMap);
+            boolean saveResult = this.save(mceReceive);
+            if (!saveResult) {
+                log.error("创建消息接收记录失败,用户ID: {}", userId);
+                continue;
+            }
+
+            // 根据消息类型处理消息发送
+            handleMessageDelivery(mbUser, mceRequestVO, mceReceive.getId(), appMode, wcMode);
+        }
+    }
+
+    /**
+     * 获取用户租户ID
+     */
+    private Integer getUserTenantId(String userName) {
+        try {
+            SysUser user = userMapper.selectOne(new LambdaQueryWrapper<SysUser>()
+                    .eq(SysUser::getUserName, userName)
+                    .select(SysUser::getTenantId));
+            return user != null ? user.getTenantId() : null;
+        } catch (Exception e) {
+            log.error("获取用户租户ID失败,报错信息:{}", e.getMessage(), e);
+            return null;
+        }
+    }
+
+    /**
+     * 保存消息内容
+     */
+    private Integer saveMessageContent(MceRequestVO mceRequestVO, Map<Long, SysUser> userIdToUserMap) {
+        SysUser sender = userIdToUserMap.values().stream()
+                .filter(user -> mceRequestVO.getUserName().equals(user.getUserName()))
+                .findFirst()
+                .orElse(null);
+
+        if (sender == null) {
+            log.error("未找到发送者信息,用户名: {}", mceRequestVO.getUserName());
+            return null;
+        }
+
+        MceContent contentEntity = new MceContent();
+        contentEntity.setInfoTitle(mceRequestVO.getInfoTitle());
+        contentEntity.setInfoContent(mceRequestVO.getInfoContent());
+        contentEntity.setInfoType(mceRequestVO.getInfoType());
+        contentEntity.setCreateBy(sender.getUserName());
+        contentEntity.setCreateTime(LocalDateTime.now());
+        contentEntity.setDeptId(sender.getDeptId().intValue());
+        contentEntity.setTenantId(sender.getTenantId());
+
+        boolean saveResult = mceContentService.save(contentEntity);
+        return saveResult ? contentEntity.getId() : null;
+    }
+
+    /**
+     * 创建消息接收记录
+     */
+    private MceReceive createMceReceive(SysUser user, Integer contentId, MceRequestVO mceRequestVO,
+                                        Map<String, String> userNameToNickNameMap) {
+        MceReceive mceReceive = new MceReceive();
+        mceReceive.setReceiverId(user.getUserId().intValue());
+        mceReceive.setContentId(contentId);
+        mceReceive.setReadFlag(0);
+        mceReceive.setInfoType(mceRequestVO.getInfoType());
+        mceReceive.setModuleId(mceRequestVO.getId());
+        mceReceive.setIssuerName(userNameToNickNameMap.get(mceRequestVO.getUserName()));
+        mceReceive.setReceiverName(user.getUserName());
+        mceReceive.setCreateBy(mceRequestVO.getUserName());
+        mceReceive.setCreateTime(LocalDateTime.now());
+        mceReceive.setTenantId(user.getTenantId());
+        mceReceive.setDeptId(Math.toIntExact(user.getDeptId()));
+        return mceReceive;
+    }
+
+    /**
+     * 处理消息发送
+     */
+    private void handleMessageDelivery(MceMbuser mbUser, MceRequestVO mceRequestVO,
+                                       Integer mceReceiveId, JSONObject appMode, JSONObject wcMode) {
+        String infoType = mceRequestVO.getInfoType();
+
+        // 登录成功通知只给登录用户发送微信公众号消息
+        if ("0".equals(infoType)) {
+            SysUserPerson one = sysUserPersonService.lambdaQuery().select(SysUserPerson::getIsLoginNotify).eq(SysUserPerson::getUserId, mbUser.getUserId()).one();
+            Integer isLoginNotify = one.getIsLoginNotify();
+            if (isLoginNotify == 1) {
+                sendWeChatMessage(mbUser, mceRequestVO, wcMode, infoType, mceReceiveId);
+            } else {
+                log.info("用户{}未开启登录通知", mbUser.getUserId());
+            }
+            return;
+        }
+
+        // 处理告警消息
+        if ("4".equals(infoType)) {
+            handleAlarmMessage(mbUser, mceRequestVO, mceReceiveId, appMode, wcMode, infoType);
+            return;
+        }
+
+        // 处理普通消息(默认APP和微信都通知)
+        handleNormalMessage(mbUser, mceRequestVO, mceReceiveId, appMode, wcMode, infoType);
+    }
+
+    /**
+     * 处理告警消息
+     */
+    private void handleAlarmMessage(MceMbuser mbUser, MceRequestVO mceRequestVO, Integer mceReceiveId,
+                                    JSONObject appMode, JSONObject wcMode, String infoType) {
+        String alarmSendType = mceRequestVO.getAlarmSendType();
+        switch (alarmSendType) {
+            case "1":
+                sendAppMessage(mbUser, mceRequestVO, appMode, infoType);
+                break;
+            case "2":
+                sendWeChatMessage(mbUser, mceRequestVO, wcMode, infoType, mceReceiveId);
+                break;
+            default:
+                log.error("未知的告警发送类型: {}", alarmSendType);
+                break;
+        }
+    }
+
+    /**
+     * 发送普通消息
+     */
+    private void handleNormalMessage(MceMbuser mbUser, MceRequestVO mceRequestVO, Integer mceReceiveId,
+                                     JSONObject appMode, JSONObject wcMode, String infoType) {
+        sendAppMessage(mbUser, mceRequestVO, appMode, infoType);
+        sendWeChatMessage(mbUser, mceRequestVO, wcMode, infoType, mceReceiveId);
+    }
+
+    /**
+     * 发送APP消息
+     */
+    private void sendAppMessage(MceMbuser mbUser, MceRequestVO mceRequestVO, JSONObject mode, String infoType) {
+        if (mode.getBoolean(infoType) && mbUser.getCids() != null) {
+            try {
+                mceContentService.sendAppNew(mceRequestVO, mbUser.getCids(), 0, 0);
+            } catch (Exception e) {
+                log.error("为用户ID: {} 发送应用消息失败,错误信息: {}", mbUser.getUserId(), e.getMessage(), e);
+            }
+        }
+    }
+
+    /**
+     * 推送微信消息
+     */
+    private void sendWeChatMessage(MceMbuser mbUser, MceRequestVO mceRequestVO, JSONObject mode,
+                                   String infoType, Integer mceReceiveId) {
+
+        if (mbUser.getOpenid() == null) {
+            return;
+        }
+
+        if ("0".equals(infoType) || mode.getBoolean(infoType)) {
+            try {
+                mceContentService.sendAppNew(mceRequestVO, mbUser.getOpenid(), mceReceiveId, 1);
+            } catch (Exception e) {
+                log.error("为用户ID: {} 发送微信消息失败,错误信息: {}", mbUser.getUserId(), e.getMessage(), e);
+            }
+        }
+    }
+
+
+    /*
+    @Async
     @Override
-    public void add(String mceReceive){
+    public void addMceReceive(MceRequestVO mceRequestVO) {
+        if (mceRequestVO.getInfoTypeName() == null) {
+            String infoTypeName = sysDictDataService.selectDictLabel("message_type", mceRequestVO.getInfoType());
+            mceRequestVO.setInfoTypeName(infoTypeName);
+        }
+
+        List<SysUser> userList = userMapper.tenantIdUserList(SecurityUtils.getTenantId());
+        // 获取用户昵称与真实姓名Map
+        Map<String, String> userNameNickNameMap = userList.stream().collect(Collectors.toMap(SysUser::getUserName, SysUser::getNickName));
+
+        if (CollectionUtils.isNotEmpty(userList)) {
+            LocalDateTime currentTime = LocalDateTime.now();
+            List<Integer> userIdList = new ArrayList<>();
+            MceContent contentEntity = new MceContent();
+            Integer generatedContentId = 0;
+            for (SysUser user : userList) {
+                userIdList.add(user.getUserId().intValue());
+                if (mceRequestVO.getUserName().equals(user.getUserName())) {
+                    contentEntity.setInfoTitle(mceRequestVO.getInfoTitle());
+                    contentEntity.setInfoContent(mceRequestVO.getInfoContent());
+                    contentEntity.setInfoType(mceRequestVO.getInfoType());
+                    contentEntity.setCreateBy(user.getUserName());
+                    contentEntity.setCreateTime(currentTime);
+                    contentEntity.setDeptId(user.getDeptId().intValue());
+                    contentEntity.setTenantId(user.getTenantId());
+                    mceContentService.save(contentEntity);
+                    generatedContentId = contentEntity.getId();
+                }
+            }
+
+            List<Long> userIds1;
+            userIds1 = mceRequestVO.getUserIds();
+            userList.retainAll(userIds1);
+
+            LambdaQueryWrapper<MceMbuser> lambdaQuery3 = Wrappers.lambdaQuery();
+            lambdaQuery3.in(MceMbuser::getUserId, userList);
+            List<MceMbuser> list3 = mceMbuserService.list(lambdaQuery3);
+
+            for (int i = 0; i < userList.size(); i++) {
+                if (CollectionUtils.isNotEmpty(list3)) {
+                    for (int j = 0; j < list3.size(); j++) {
+                        if (userList.get(i).getUserId().equals(list3.get(j).getUserId())) {
+                            MceReceive mceReceive1 = new MceReceive();
+                            mceReceive1.setReceiverId(userList.get(i).getUserId().intValue());
+                            mceReceive1.setContentId(generatedContentId);
+                            mceReceive1.setReadFlag(0);
+                            mceReceive1.setInfoType(mceRequestVO.getInfoType());
+                            mceReceive1.setModuleId(mceRequestVO.getId());
+
+                            String userName = mceRequestVO.getUserName();
+                            String nickName = userNameNickNameMap.get(userName);
+                            mceReceive1.setIssuerName(nickName);
+
+                            mceReceive1.setReceiverName(userList.get(i).getUserName());
+                            mceReceive1.setCreateBy(mceRequestVO.getUserName());
+                            mceReceive1.setCreateTime(LocalDateTime.now());
+                            mceReceive1.setTenantId(userList.get(i).getTenantId());
+                            mceReceive1.setDeptId(Math.toIntExact(userList.get(i).getDeptId()));
+                            this.save(mceReceive1);
+                            Integer mceReceiveId = mceReceive1.getId();
+
+                            LambdaQueryWrapper<MceSetting> lambdaQuery = Wrappers.lambdaQuery();
+                            lambdaQuery.eq(MceSetting::getCreateBy, userList.get(i).getUserName());
+                            List<MceSetting> list1 = mceSettingService.list(lambdaQuery);
+
+                            if (CollectionUtils.isNotEmpty(list1)) {
+                                JSONObject appMode = JSONObject.parseObject(list1.get(0).getAppMode());
+                                JSONObject wcMode = JSONObject.parseObject(list1.get(0).getWcMode());
+
+                                if (appMode.get(mceRequestVO.getInfoType()).equals(true)) {
+                                    if (userList.get(i).getUserId().equals(list3.get(j).getUserId()) && StringUtils.isNotBlank(list3.get(j).getCids())) {
+                                        try {
+                                            mceContentService.sendAppNew(mceRequestVO, list3.get(j).getCids(), 0, 0);
+                                        } catch (Exception e) {
+                                            log.error("为用户ID: {} 发送应用消息失败,错误信息: {}", list3.get(j).getUserId(), e.getMessage(), e);
+                                        }
+                                    }
+                                }
+
+                                if (wcMode.get(mceRequestVO.getInfoType()).equals(true)) {
+                                    if (userList.get(i).getUserId().equals(list3.get(j).getUserId()) && StringUtils.isNotBlank(list3.get(j).getOpenid())) {
+                                        try {
+                                            mceContentService.sendAppNew(mceRequestVO, list3.get(j).getOpenid(), mceReceiveId, 1);
+                                        } catch (Exception e) {
+                                            log.error("为用户ID: {} 发送微信消息失败,错误信息: {}", list3.get(j).getUserId(), e.getMessage(), e);
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+    */
+
+    @Async
+    @Override
+    public void add(String mceReceive) {
         JSONObject mceReceiveVO = JSONObject.parseObject(mceReceive);
-        String infoTypeName = sysDictDataService.selectDictLabel("message_type",mceReceiveVO.get("infoType").toString());
+        String infoTypeName = sysDictDataService.selectDictLabel("message_type", mceReceiveVO.get("infoType").toString());
         if (!mceReceiveVO.containsKey("infoTypeName")) {
-            mceReceiveVO.put("infoTypeName",infoTypeName);
+            mceReceiveVO.put("infoTypeName", infoTypeName);
+        }
+
+        Integer tenantId = null;
+        try {
+            tenantId = userMapper.selectOne(new LambdaQueryWrapper<SysUser>().eq(SysUser::getUserName, mceReceiveVO.get("userName")).select(SysUser::getTenantId)).getTenantId();
+        } catch (Exception e) {
+            log.error("获取用户租户ID失败,报错信息:{}, 未找到用户-{}-的租户", e.getMessage(), mceReceiveVO.get("userName"));
         }
-        List<SysUser> list = userMapper.tenantIdUserList(SecurityUtils.getTenantId());
+        List<SysUser> list = userMapper.tenantIdUserList(tenantId);
+        // 获取用户昵称与真实姓名Map
+        Map<String, String> userNameNickNameMap = list.stream().collect(Collectors.toMap(SysUser::getUserName, SysUser::getNickName));
         MceContent mceContent = new MceContent();
         Integer contentId = 0;
+
         if (CollectionUtils.isNotEmpty(list)) {
             List<Integer> userIds = new ArrayList<>();
             for (int g = 0; g < list.size(); g++) {
                 userIds.add(list.get(g).getUserId().intValue());
-                if (mceReceiveVO.get("userName").equals(list.get(g).getUserName())){
+                if (mceReceiveVO.get("userName").equals(list.get(g).getUserName())) {
                     mceContent.setInfoTitle(mceReceiveVO.get("infoTitle").toString());
                     mceContent.setInfoContent(mceReceiveVO.get("infoContent").toString());
                     mceContent.setInfoType(mceReceiveVO.get("infoType").toString());
@@ -262,50 +666,65 @@ public class MceReceiveServiceImpl extends AbstractCrudService<MceReceiveMapper,
                     contentId = mceContent.getId();
                 }
             }
+
             List<Integer> userIds1;
             if (mceReceiveVO.containsKey("userIds")) {
                 userIds1 = convertObjectToList(mceReceiveVO.get("userIds"));
                 userIds.retainAll(userIds1);
             }
+
             LambdaQueryWrapper<MceMbuser> lambdaQuery3 = Wrappers.lambdaQuery();
-            lambdaQuery3.in(MceMbuser::getUserId,userIds);
+            lambdaQuery3.in(MceMbuser::getUserId, userIds);
             List<MceMbuser> list3 = mceMbuserService.list(lambdaQuery3);
+
             for (int i = 0; i < list.size(); i++) {
-                if (CollectionUtils.isNotEmpty(list3)){
+                if (CollectionUtils.isNotEmpty(list3)) {
                     for (int j = 0; j < list3.size(); j++) {
-                        if (list.get(i).getUserId().equals(list3.get(j).getUserId())){
+                        if (list.get(i).getUserId().equals(list3.get(j).getUserId())) {
                             MceReceive mceReceive1 = new MceReceive();
                             mceReceive1.setReceiverId(list.get(i).getUserId().intValue());
                             mceReceive1.setContentId(contentId);
                             mceReceive1.setReadFlag(0);
                             mceReceive1.setInfoType(mceReceiveVO.get("infoType").toString());
-                            mceReceive1.setModuleId((int)mceReceiveVO.get("id"));
+                            mceReceive1.setModuleId((int) mceReceiveVO.get("id"));
                             if (mceReceiveVO.containsKey("userName")) {
-                                mceReceive1.setIssuerName(mceReceiveVO.get("userName").toString());
+                                String userName = mceReceiveVO.get("userName").toString();
+                                String nickName = userNameNickNameMap.get(userName);
+                                mceReceive1.setIssuerName(nickName);
                             }
                             mceReceive1.setReceiverName(list.get(i).getUserName());
                             mceReceive1.setCreateBy(mceReceiveVO.get("userName").toString());
                             mceReceive1.setCreateTime(LocalDateTime.now());
                             mceReceive1.setTenantId(list.get(i).getTenantId());
-                            if (mceReceiveVO.get("userName").equals(list.get(i).getUserName())){
-                                mceReceive1.setDeptId(list.get(i).getDeptId().intValue());
-                            }
+                            mceReceive1.setDeptId(list.get(i).getDeptId().intValue());
                             this.save(mceReceive1);
                             Integer mceReceiveId = mceReceive1.getId();
+
                             LambdaQueryWrapper<MceSetting> lambdaQuery = Wrappers.lambdaQuery();
-                            lambdaQuery.eq(MceSetting::getCreateBy,list.get(i).getUserName());
+                            lambdaQuery.eq(MceSetting::getCreateBy, list.get(i).getUserName());
                             List<MceSetting> list1 = mceSettingService.list(lambdaQuery);
-                            if (CollectionUtils.isNotEmpty(list1)){
+
+                            if (CollectionUtils.isNotEmpty(list1)) {
                                 JSONObject appMode = JSONObject.parseObject(list1.get(0).getAppMode());
                                 JSONObject wcMode = JSONObject.parseObject(list1.get(0).getWcMode());
-                                if (appMode.get(mceReceiveVO.get("infoType").toString()).equals(true)){
-                                    if (list.get(i).getUserId().equals(list3.get(j).getUserId()) && StringUtils.isNotBlank(list3.get(j).getCids())){
-                                        mceContentService.sendApp(mceReceiveVO,list3.get(j).getCids(),0,0);
+
+                                if (appMode.get(mceReceiveVO.get("infoType").toString()).equals(true)) {
+                                    if (list.get(i).getUserId().equals(list3.get(j).getUserId()) && StringUtils.isNotBlank(list3.get(j).getCids())) {
+                                        try {
+                                            mceContentService.sendApp(mceReceiveVO, list3.get(j).getCids(), 0, 0);
+                                        } catch (Exception e) {
+                                            log.error("为用户ID: {} 发送应用消息失败,错误信息: {}", list3.get(j).getUserId(), e.getMessage(), e);
+                                        }
                                     }
                                 }
-                                if (wcMode.get(mceReceiveVO.get("infoType").toString()).equals(true)){
-                                    if (list.get(i).getUserId().equals(list3.get(j).getUserId()) && StringUtils.isNotBlank(list3.get(j).getOpenid())){
-                                        mceContentService.sendApp(mceReceiveVO,list3.get(j).getOpenid(),mceReceiveId,1);
+
+                                if (wcMode.get(mceReceiveVO.get("infoType").toString()).equals(true)) {
+                                    if (list.get(i).getUserId().equals(list3.get(j).getUserId()) && StringUtils.isNotBlank(list3.get(j).getOpenid())) {
+                                        try {
+                                            mceContentService.sendApp(mceReceiveVO, list3.get(j).getOpenid(), mceReceiveId, 1);
+                                        } catch (Exception e) {
+                                            log.error("为用户ID: {} 发送微信消息失败,错误信息: {}", list3.get(j).getUserId(), e.getMessage(), e);
+                                        }
                                     }
                                 }
                             }
@@ -319,8 +738,91 @@ public class MceReceiveServiceImpl extends AbstractCrudService<MceReceiveMapper,
     @Override
     public boolean removeById(Integer id) {
         LambdaQueryWrapper<MceReceive> lambdaQuery = Wrappers.lambdaQuery();
-        lambdaQuery.eq(MceReceive::getContentId,id);
+        lambdaQuery.eq(MceReceive::getContentId, id);
         this.remove(lambdaQuery);
         return mceContentService.removeById(id);
     }
+
+    @Override
+    public boolean deleteById(Integer id) {
+        boolean f;
+        Integer userId = SecurityUtils.getUserId().intValue();
+        MceReceive mceReceive = mceReceiveMapper.selectOne(new LambdaQueryWrapper<MceReceive>().eq(MceReceive::getId, id));
+        if (mceReceive != null) {
+            if (userId.equals(mceReceive.getReceiverId())) {
+                mceReceiveMapper.deleteById(id);
+                f = true;
+            } else {
+                throw new BusinessException("您无权删除该条记录!");
+            }
+        } else {
+            throw new BusinessException("记录不存在,删除失败!");
+        }
+        return f;
+    }
+
+    @Override
+    public CommonPage<MceReceiveResponseVO> getMceReceiveResponseVOList(Integer pageNumber, Integer pageSize) {
+        IPage<MceReceive> page = new Page<>(pageNumber, pageSize);
+        Long userId = SecurityUtils.getUserId();
+        List<MceReceiveResponseVO> returnList = new ArrayList<>();
+
+        LambdaQueryWrapper<MceReceive> lambdaQuery = Wrappers.lambdaQuery();
+        lambdaQuery.eq(MceReceive::getReceiverId, userId).orderByDesc(MceReceive::getId);
+        page = this.page(page, lambdaQuery);
+        List<MceReceive> mceReceiveList = page.getRecords();
+        List<Integer> contentIdList = mceReceiveList.stream().map(MceReceive::getContentId).distinct().collect(Collectors.toList());
+
+        List<MceContent> mceContentList = mceContentService.list(new LambdaQueryWrapper<MceContent>().in(MceContent::getId, contentIdList));
+
+        for (MceContent mceContent : mceContentList) {
+            MceReceive mceReceive = mceReceiveList.stream().filter(mceReceive1 -> mceReceive1.getContentId().equals(mceContent.getId())).findFirst().get();
+            MceReceiveResponseVO mceReceiveResponseVO = new MceReceiveResponseVO();
+            mceReceiveResponseVO.setMceId(mceReceive.getId());
+            mceReceiveResponseVO.setInfoType(mceContent.getInfoType());
+            mceReceiveResponseVO.setInfoTitle(mceContent.getInfoTitle());
+            mceReceiveResponseVO.setContentId(mceContent.getId());
+            mceReceiveResponseVO.setInfoContent(mceContent.getInfoContent());
+            mceReceiveResponseVO.setCreateTime(mceContent.getCreateTime());
+            mceReceiveResponseVO.setCreateBy(mceContent.getCreateBy());
+            mceReceiveResponseVO.setModuleId(mceReceive.getModuleId());
+            returnList.add(mceReceiveResponseVO);
+        }
+
+        return new CommonPage<>(returnList, page.getTotal(), page.getSize(), page.getCurrent());
+    }
+
+    /**
+     * 新增消息-无需token
+     * @param mceNoToken
+     */
+    @Override
+    public void addNoToken(String mceNoToken) {
+        JSONObject json = JSONObject.parseObject(mceNoToken);
+        String infoTypeName = sysDictDataService.selectDictLabel("message_type", json.get("infoType").toString());
+        if (!json.containsKey("infoTypeName")) {
+            json.put("infoTypeName", infoTypeName);
+        }
+        List<String> userNames = JSONObject.parseArray(json.get("userNames").toString(), String.class);
+
+        LambdaQueryWrapper<SysUser> lambdaQuery = Wrappers.lambdaQuery();
+        lambdaQuery.select(SysUser::getUserId)
+                .in(SysUser::getUserName, userNames);
+        List<Long> userIdList = userMapper.selectList(lambdaQuery).stream().map(SysUser::getUserId).collect(Collectors.toList());
+
+        MceRequestVO mceRequestVO = new MceRequestVO();
+        mceRequestVO.setUserIds(userIdList);
+        mceRequestVO.setInfoTitle(json.get("infoTitle").toString());
+        mceRequestVO.setInfoContent(json.get("infoContent").toString());
+        mceRequestVO.setInfoType(json.get("infoType").toString());
+        mceRequestVO.setInfoTypeName(json.get("infoTypeName").toString());
+        mceRequestVO.setId((Integer) json.get("id"));
+        mceRequestVO.setUserName(json.get("userName").toString());
+        mceRequestVO.setApprovalResult(json.get("approvalResult").toString());
+        mceRequestVO.setProcessName(json.get("processName").toString());
+        mceRequestVO.setApprovalNode(json.get("approvalNode").toString());
+        mceRequestVO.setRealName(json.get("realName").toString());
+        mceRequestVO.setOaType(json.get("oaType").toString());
+        addMceReceive(mceRequestVO);
+    }
 }

+ 15 - 8
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/service/impl/SysDeptServiceImpl.java

@@ -1,8 +1,6 @@
 package com.usky.system.service.impl;
 
 
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.ruoyi.common.datascope.annotation.DataScope;
 import com.usky.common.mybatis.core.AbstractCrudService;
 import com.usky.common.security.utils.SecurityUtils;
@@ -12,7 +10,6 @@ import com.usky.common.core.util.StringUtils;
 import com.usky.system.domain.SysDept;
 import com.usky.system.domain.SysRole;
 import com.usky.system.domain.SysUser;
-import com.usky.system.domain.SysUserPost;
 import com.usky.system.domain.constants.UserConstants;
 import com.usky.system.mapper.SysDeptMapper;
 import com.usky.system.mapper.SysRoleMapper;
@@ -21,13 +18,10 @@ import com.usky.system.service.ISysDeptService;
 import com.usky.system.service.vo.TreeNode;
 import com.usky.system.service.vo.TreeSelect;
 import com.usky.system.service.vo.UserPostVo;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
 import java.util.*;
-import java.util.function.Function;
 import java.util.stream.Collectors;
 
 
@@ -39,8 +33,6 @@ import java.util.stream.Collectors;
 @Service
 public class SysDeptServiceImpl extends AbstractCrudService<SysDeptMapper, SysDept> implements ISysDeptService {
 
-    private static final Logger log = LoggerFactory.getLogger(SysDeptServiceImpl.class);//还原代码
-
     @Autowired
     private SysDeptMapper deptMapper;
 
@@ -63,6 +55,13 @@ public class SysDeptServiceImpl extends AbstractCrudService<SysDeptMapper, SysDe
         return deptMapper.selectDeptList(dept);
     }
 
+    // 查询租户下部门信,无数据权限
+    @Override
+    public List<SysDept> selectDept(SysDept dept) {
+        dept.setTenantId(SecurityUtils.getTenantId());
+        return deptMapper.selectDeptList(dept);
+    }
+
     @Override
     public List<SysDept> deptList(SysDept dept) {
         dept.setTenantId(SecurityUtils.getTenantId());
@@ -209,6 +208,14 @@ public class SysDeptServiceImpl extends AbstractCrudService<SysDeptMapper, SysDe
         return deptMapper.selectDeptById(deptId);
     }
 
+    @Override
+    public List<SysDept> selectDeptByIds(List<Long> deptIds) {
+        if (deptIds == null || deptIds.isEmpty()) {
+            return Collections.emptyList();
+        }
+        return deptMapper.selectDeptByIds(deptIds);
+    }
+
     /**
      * 根据ID查询所有子部门(正常状态)
      *

+ 165 - 243
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/service/impl/SysMenuServiceImpl.java

@@ -28,8 +28,7 @@ import java.util.stream.Collectors;
  * @author yq
  */
 @Service
-public class SysMenuServiceImpl extends AbstractCrudService<SysMenuMapper, SysMenu> implements ISysMenuService
-{
+public class SysMenuServiceImpl extends AbstractCrudService<SysMenuMapper, SysMenu> implements ISysMenuService {
     public static final String PREMISSION_STRING = "perms[\"{0}\"]";
 
     @Autowired
@@ -69,8 +68,7 @@ public class SysMenuServiceImpl extends AbstractCrudService<SysMenuMapper, SysMe
      * @return 菜单列表
      */
     @Override
-    public List<SysMenu> selectMenuList(Long userId)
-    {
+    public List<SysMenu> selectMenuList(Long userId) {
         return selectMenuList(new SysMenu(), userId);
     }
 
@@ -81,16 +79,12 @@ public class SysMenuServiceImpl extends AbstractCrudService<SysMenuMapper, SysMe
      * @return 菜单列表
      */
     @Override
-    public List<SysMenu> selectMenuList(SysMenu menu, Long userId)
-    {
+    public List<SysMenu> selectMenuList(SysMenu menu, Long userId) {
         List<SysMenu> menuList = null;
         // 管理员显示所有菜单信息
-        if (SysUserVO.isAdmin(userId))
-        {
+        if (SysUserVO.isAdmin(userId)) {
             menuList = menuMapper.selectMenuList(menu);
-        }
-        else
-        {
+        } else {
             menu.getParams().put("userId", userId);
             menuList = menuMapper.selectMenuListByUserId(menu);
         }
@@ -98,24 +92,21 @@ public class SysMenuServiceImpl extends AbstractCrudService<SysMenuMapper, SysMe
     }
 
     @Override
-    public List<SysMenu> selectMenuListTwo(SysMenu menu)
-    {
-        List<SysMenu> menuList = menuMapper.selectMenuListOne(SecurityUtils.getTenantId(),menu.getMenuName());
+    public List<SysMenu> selectMenuListTwo(SysMenu menu) {
+        List<SysMenu> menuList = menuMapper.selectMenuListOne(SecurityUtils.getTenantId(), menu.getMenuName());
         return menuList;
     }
 
 
     @Override
-    public List<SysMenu> selectMenuListOne(Long userId)
-    {
+    public List<SysMenu> selectMenuListOne(Long userId) {
         List<SysMenu> menuList = menuMapper.selectMenuListByUserIdOne(userId);
         return menuList;
     }
 
 
     @Override
-    public List<SysMobileMenu> selectMobileMenuListOne(Long userId)
-    {
+    public List<SysMobileMenu> selectMobileMenuListOne(Long userId) {
         List<SysMobileMenu> menuList = menuMapper.selectMobileMenuListByUserIdOne(userId);
         return menuList;
     }
@@ -127,14 +118,11 @@ public class SysMenuServiceImpl extends AbstractCrudService<SysMenuMapper, SysMe
      * @return 权限列表
      */
     @Override
-    public Set<String> selectMenuPermsByUserId(Long userId)
-    {
+    public Set<String> selectMenuPermsByUserId(Long userId) {
         List<String> perms = menuMapper.selectMenuPermsByUserId(userId);
         Set<String> permsSet = new HashSet<>();
-        for (String perm : perms)
-        {
-            if (StringUtils.isNotEmpty(perm))
-            {
+        for (String perm : perms) {
+            if (StringUtils.isNotEmpty(perm)) {
                 permsSet.addAll(Arrays.asList(perm.trim().split(",")));
             }
         }
@@ -148,14 +136,11 @@ public class SysMenuServiceImpl extends AbstractCrudService<SysMenuMapper, SysMe
      * @return 权限列表
      */
     @Override
-    public Set<String> selectMenuPermsByUserIdOne(Integer tenantId)
-    {
+    public Set<String> selectMenuPermsByUserIdOne(Integer tenantId) {
         List<String> perms = menuMapper.selectMenuPermsByUserIdOne(tenantId);
         Set<String> permsSet = new HashSet<>();
-        for (String perm : perms)
-        {
-            if (StringUtils.isNotEmpty(perm))
-            {
+        for (String perm : perms) {
+            if (StringUtils.isNotEmpty(perm)) {
                 permsSet.addAll(Arrays.asList(perm.trim().split(",")));
             }
         }
@@ -170,15 +155,11 @@ public class SysMenuServiceImpl extends AbstractCrudService<SysMenuMapper, SysMe
      * @return 菜单列表
      */
     @Override
-    public List<SysMenu> selectMenuTreeByUserId(Long userId)
-    {
+    public List<SysMenu> selectMenuTreeByUserId(Long userId) {
         List<SysMenu> menus = null;
-        if (1L == userId)
-        {
+        if (1L == userId) {
             menus = menuMapper.selectMenuTreeAll();
-        }
-        else
-        {
+        } else {
             menus = menuMapper.selectMenuTreeByUserId(userId);
         }
         return getChildPerms(menus, 0);
@@ -191,33 +172,29 @@ public class SysMenuServiceImpl extends AbstractCrudService<SysMenuMapper, SysMe
      * @return 菜单列表
      */
     @Override
-    public List<SysMenu> selectMenuTreeByUserId1(Long userId,Long platformId)
-    {
+    public List<SysMenu> selectMenuTreeByUserId1(Long userId, Long platformId, Integer tenantId) {
         List<SysMenu> menus = null;
-        if (1L == userId)
-        {
+        if (1L == userId) {
             menus = menuMapper.selectMenuTreeAll();
-        }
-        else
-        {
-            menus = menuMapper.selectMenuTreeByUserId1(userId,platformId);
+        } else {
+            menus = menuMapper.selectMenuTreeByUserId1(userId, platformId, tenantId);
         }
         return getChildPerms(menus, 0);
     }
 
 
-    public List<SysMenu> selectMenuTreeByUserIdOne(Integer tenantId){
+    public List<SysMenu> selectMenuTreeByUserIdOne(Integer tenantId) {
         List<SysMenu> menus = menuMapper.selectMenuTreeByUserIdOne(tenantId);
         return getChildPerms(menus, 0);
     }
 
-    public List<SysMenu> selectMenuTreeByUserIdOne1(Integer tenantId,Integer platformId){
-        List<SysMenu> menus = menuMapper.selectMenuTreeByUserIdOne1(tenantId,platformId);
+    public List<SysMenu> selectMenuTreeByUserIdOne1(Integer tenantId, Integer platformId) {
+        List<SysMenu> menus = menuMapper.selectMenuTreeByUserIdOne1(tenantId, platformId);
         return getChildPerms(menus, 0);
     }
 
     @Override
-    public List<SysTenantMenu> selectTenantMenuList(Integer tenantId){
+    public List<SysTenantMenu> selectTenantMenuList(Integer tenantId) {
         List<SysTenantMenu> menus = tenantMenuMapper.selectTenantMenuList(tenantId);
         return menus;
     }
@@ -229,8 +206,7 @@ public class SysMenuServiceImpl extends AbstractCrudService<SysMenuMapper, SysMe
      * @return 选中菜单列表
      */
     @Override
-    public List<Integer> selectMenuListByRoleId(Long roleId)
-    {
+    public List<Integer> selectMenuListByRoleId(Long roleId) {
         SysRole role = roleMapper.selectRoleById(roleId);
         return menuMapper.selectMenuListByRoleId(roleId, role.isMenuCheckStrictly());
     }
@@ -242,47 +218,43 @@ public class SysMenuServiceImpl extends AbstractCrudService<SysMenuMapper, SysMe
      * @return 路由列表
      */
     @Override
-    public List<RouterVo> buildMenus(List<SysMenu> menus)
-    {
+    public List<RouterVo> buildMenus(List<SysMenu> menus) {
         List<RouterVo> routers = new LinkedList<RouterVo>();
-        for (SysMenu menu : menus)
-        {
+        for (SysMenu menu : menus) {
             RouterVo router = new RouterVo();
             router.setHidden("1".equals(menu.getVisible()));
             router.setName(getRouteName(menu));
             router.setPath(getRouterPath(menu));
             router.setComponent(getComponent(menu));
-            router.setMeta(new MetaVo(menu.getMenuName(), menu.getMenuAliasName(), menu.getIcon(), StringUtils.equals("1", menu.getIsCache()), menu.getPath(), menu.getIsFrame(), menu.getIsNew(), menu.getRemark()));
+            router.setOrderNum(menu.getOrderNum());
+            router.setMeta(new MetaVo(menu.getMenuName(), menu.getMenuAliasName(), menu.getIcon(), StringUtils.equals("1", menu.getIsCache()), menu.getPath(), menu.getIsFrame(), menu.getIsNew(), menu.getRemark(),menu.getMenuMold()));
             List<SysMenu> cMenus = menu.getChildren();
-            if (!cMenus.isEmpty() && cMenus.size() > 0 && UserConstants.TYPE_DIR.equals(menu.getMenuType()))
-            {
+            if (!cMenus.isEmpty() && cMenus.size() > 0 && UserConstants.TYPE_DIR.equals(menu.getMenuType())) {
                 router.setAlwaysShow(true);
                 router.setRedirect("noRedirect");
                 router.setChildren(buildMenus(cMenus));
-            }
-            else if (isMenuFrame(menu))
-            {
+            } else if (isMenuFrame(menu)) {
                 router.setMeta(null);
                 List<RouterVo> childrenList = new ArrayList<RouterVo>();
                 RouterVo children = new RouterVo();
                 children.setPath(menu.getPath());
                 children.setComponent(menu.getComponent());
                 children.setName(StringUtils.capitalize(menu.getPath()));
-                children.setMeta(new MetaVo(menu.getMenuName(), menu.getMenuAliasName(), menu.getIcon(), StringUtils.equals("1", menu.getIsCache()), menu.getPath(), menu.getIsFrame(), menu.getIsNew(), menu.getRemark()));
+                children.setOrderNum(menu.getOrderNum());
+                children.setMeta(new MetaVo(menu.getMenuName(), menu.getMenuAliasName(), menu.getIcon(), StringUtils.equals("1", menu.getIsCache()), menu.getPath(), menu.getIsFrame(), menu.getIsNew(), menu.getRemark(),menu.getMenuMold()));
                 childrenList.add(children);
                 router.setChildren(childrenList);
-            }
-            else if (menu.getParentId().intValue() == 0 && isInnerLink(menu))
-            {
-                router.setMeta(new MetaVo(menu.getMenuName(), menu.getMenuAliasName(), menu.getIcon(), menu.getIsFrame(), menu.getIsNew(), menu.getRemark()));
+            } else if (menu.getParentId().intValue() == 0 && isInnerLink(menu)) {
+                router.setMeta(new MetaVo(menu.getMenuName(), menu.getMenuAliasName(), menu.getIcon(), menu.getIsFrame(), menu.getIsNew(), menu.getRemark(),menu.getMenuMold()));
                 router.setPath("/inner");
                 List<RouterVo> childrenList = new ArrayList<RouterVo>();
                 RouterVo children = new RouterVo();
-                String routerPath = StringUtils.replaceEach(menu.getPath(), new String[] { Constants.HTTP, Constants.HTTPS }, new String[] { "", "" });
+                String routerPath = StringUtils.replaceEach(menu.getPath(), new String[]{Constants.HTTP, Constants.HTTPS}, new String[]{"", ""});
                 children.setPath(routerPath);
                 children.setComponent(UserConstants.INNER_LINK);
                 children.setName(StringUtils.capitalize(routerPath));
-                children.setMeta(new MetaVo(menu.getMenuName(), menu.getMenuAliasName(), menu.getIcon(), menu.getPath(), menu.getIsFrame(), menu.getIsNew(), menu.getRemark()));
+                children.setOrderNum(menu.getOrderNum());
+                children.setMeta(new MetaVo(menu.getMenuName(), menu.getMenuAliasName(), menu.getIcon(), menu.getPath(), menu.getIsFrame(), menu.getIsNew(), menu.getRemark(),menu.getMenuMold()));
                 childrenList.add(children);
                 router.setChildren(childrenList);
             }
@@ -296,59 +268,61 @@ public class SysMenuServiceImpl extends AbstractCrudService<SysMenuMapper, SysMe
      * @return 路由列表
      */
     @Override
-    public List<PlatformRouterVo> buildPlatformMenus()
-    {
+    public List<PlatformRouterVo> buildPlatformMenus() {
         List<PlatformRouterVo> platformRouterVos = new LinkedList<PlatformRouterVo>();
-        if (SecurityUtils.getLoginUser().getSysUser().getUserType().equals("01")){
-            List<SysPlatformVo> sysPlatformVos = sysPlatformMapper.getTenantPlatformList(SecurityUtils.getTenantId());
-            if (CollectionUtils.isNotEmpty(sysPlatformVos)){
-                for (SysPlatformVo platformVo : sysPlatformVos)
-                {
+        Long userId = SecurityUtils.getUserId();
+        Integer tenantId = SecurityUtils.getTenantId();
+        String userType = SecurityUtils.getLoginUser().getSysUser().getUserType();
+        if ("01".equals(userType)) {
+            List<SysPlatformVo> sysPlatformVos = sysPlatformMapper.getTenantPlatformList(tenantId);
+            if (CollectionUtils.isNotEmpty(sysPlatformVos)) {
+                for (SysPlatformVo platformVo : sysPlatformVos) {
                     PlatformRouterVo platformRouterVo = new PlatformRouterVo();
                     platformRouterVo.setPlatformId(platformVo.getId());
                     platformRouterVo.setPlatformName(platformVo.getPlatformName());
                     platformRouterVo.setIcon(platformVo.getIcon());
-                    List<SysMenu> menus1 = this.selectMenuTreeByUserIdOne1(SecurityUtils.getTenantId(),
+                    platformRouterVo.setOrderNum(platformVo.getOrderNum());
+                    platformRouterVo.setPlatformType(platformVo.getPlatformType());
+                    List<SysMenu> menus1 = this.selectMenuTreeByUserIdOne1(tenantId,
                             platformVo.getId());
                     List<RouterVo> routers = new LinkedList<RouterVo>();
-                    for (SysMenu menu : menus1)
-                    {
+                    for (SysMenu menu : menus1) {
                         RouterVo router = new RouterVo();
                         router.setHidden("1".equals(menu.getVisible()));
                         router.setName(getRouteName(menu));
                         router.setPath(getRouterPath(menu));
                         router.setComponent(getComponent(menu));
-                        router.setMeta(new MetaVo(menu.getMenuName(), menu.getMenuAliasName(), menu.getIcon(), StringUtils.equals("1", menu.getIsCache()), menu.getPath(), menu.getIsFrame(), menu.getIsNew(), menu.getRemark()));
+                        router.setOrderNum(menu.getOrderNum());
+                        router.setMeta(new MetaVo(menu.getMenuName(), menu.getMenuAliasName(), menu.getIcon(),
+                                StringUtils.equals("1", menu.getIsCache()), menu.getPath(), menu.getIsFrame(),
+                                menu.getIsNew(), menu.getRemark(),menu.getMenuMold()));
                         List<SysMenu> cMenus = menu.getChildren();
-                        if (!cMenus.isEmpty() && cMenus.size() > 0 && UserConstants.TYPE_DIR.equals(menu.getMenuType()))
-                        {
+                        if (!cMenus.isEmpty() && UserConstants.TYPE_DIR.equals(menu.getMenuType())) {
                             router.setAlwaysShow(true);
                             router.setRedirect("noRedirect");
                             router.setChildren(buildMenus(cMenus));
-                        }
-                        else if (isMenuFrame(menu))
-                        {
+                        } else if (isMenuFrame(menu)) {
                             router.setMeta(null);
                             List<RouterVo> childrenList = new ArrayList<RouterVo>();
                             RouterVo children = new RouterVo();
                             children.setPath(menu.getPath());
                             children.setComponent(menu.getComponent());
                             children.setName(StringUtils.capitalize(menu.getPath()));
-                            children.setMeta(new MetaVo(menu.getMenuName(), menu.getMenuAliasName(), menu.getIcon(), StringUtils.equals("1", menu.getIsCache()), menu.getPath(), menu.getIsFrame(), menu.getIsNew(), menu.getRemark()));
+                            children.setOrderNum(menu.getOrderNum());
+                            children.setMeta(new MetaVo(menu.getMenuName(), menu.getMenuAliasName(), menu.getIcon(), StringUtils.equals("1", menu.getIsCache()), menu.getPath(), menu.getIsFrame(), menu.getIsNew(), menu.getRemark(),menu.getMenuMold()));
                             childrenList.add(children);
                             router.setChildren(childrenList);
-                        }
-                        else if (menu.getParentId().intValue() == 0 && isInnerLink(menu))
-                        {
-                            router.setMeta(new MetaVo(menu.getMenuName(), menu.getMenuAliasName(), menu.getIcon(), menu.getIsFrame(), menu.getIsNew(), menu.getRemark()));
+                        } else if (menu.getParentId().intValue() == 0 && isInnerLink(menu)) {
+                            router.setMeta(new MetaVo(menu.getMenuName(), menu.getMenuAliasName(), menu.getIcon(), menu.getIsFrame(), menu.getIsNew(), menu.getRemark(),menu.getMenuMold()));
                             router.setPath("/inner");
                             List<RouterVo> childrenList = new ArrayList<RouterVo>();
                             RouterVo children = new RouterVo();
-                            String routerPath = StringUtils.replaceEach(menu.getPath(), new String[] { Constants.HTTP, Constants.HTTPS }, new String[] { "", "" });
+                            String routerPath = StringUtils.replaceEach(menu.getPath(), new String[]{Constants.HTTP, Constants.HTTPS}, new String[]{"", ""});
                             children.setPath(routerPath);
                             children.setComponent(UserConstants.INNER_LINK);
                             children.setName(StringUtils.capitalize(routerPath));
-                            children.setMeta(new MetaVo(menu.getMenuName(), menu.getMenuAliasName(), menu.getIcon(), menu.getPath(), menu.getIsFrame(), menu.getIsNew(), menu.getRemark()));
+                            children.setOrderNum(menu.getOrderNum());
+                            children.setMeta(new MetaVo(menu.getMenuName(), menu.getMenuAliasName(), menu.getIcon(), menu.getPath(), menu.getIsFrame(), menu.getIsNew(), menu.getRemark(),menu.getMenuMold()));
                             childrenList.add(children);
                             router.setChildren(childrenList);
                         }
@@ -358,61 +332,63 @@ public class SysMenuServiceImpl extends AbstractCrudService<SysMenuMapper, SysMe
                     platformRouterVos.add(platformRouterVo);
                 }
             }
-        }else {
+        } else {
             LambdaQueryWrapper<SysUserRole> queryWrapper = Wrappers.lambdaQuery();
-            queryWrapper.in(SysUserRole::getUserId,SecurityUtils.getUserId());
+            queryWrapper.eq(SysUserRole::getUserId, userId)
+                    .eq(SysUserRole::getTenantId, tenantId);
             List<SysUserRole> userRoleList = sysUserRoleMapper.selectList(queryWrapper);
-            if (CollectionUtils.isNotEmpty(userRoleList)){
-                List<SysPlatformVo> sysPlatformVos = sysPlatformMapper.getRolePlatformList(SecurityUtils.getTenantId(),
-                        userRoleList.get(0).getRoleId().intValue());
-                if (CollectionUtils.isNotEmpty(sysPlatformVos)){
-                    for (SysPlatformVo platformVo : sysPlatformVos)
-                    {
+            if (CollectionUtils.isNotEmpty(userRoleList)) {
+                List<SysPlatformVo> sysPlatformVos = userRoleList.stream()
+                        .map(userRole -> sysPlatformMapper.getRolePlatformList(tenantId, Math.toIntExact(userRole.getRoleId())))
+                        .flatMap(Collection::stream)
+                        .distinct()
+                        .collect(Collectors.toList());
+                if (CollectionUtils.isNotEmpty(sysPlatformVos)) {
+                    for (SysPlatformVo platformVo : sysPlatformVos) {
                         PlatformRouterVo platformRouterVo = new PlatformRouterVo();
                         platformRouterVo.setPlatformId(platformVo.getId());
                         platformRouterVo.setPlatformName(platformVo.getPlatformName());
                         platformRouterVo.setIcon(platformVo.getIcon());
-                        List<SysMenu> menus1 = this.selectMenuTreeByUserId1(SecurityUtils.getUserId(),
-                                platformVo.getId().longValue());
+                        platformRouterVo.setOrderNum(platformVo.getOrderNum());
+                        platformRouterVo.setPlatformType(platformVo.getPlatformType());
+                        List<SysMenu> menus1 = this.selectMenuTreeByUserId1(userId,
+                                platformVo.getId().longValue(), tenantId);
                         List<RouterVo> routers = new LinkedList<RouterVo>();
-                        for (SysMenu menu : menus1)
-                        {
+                        for (SysMenu menu : menus1) {
                             RouterVo router = new RouterVo();
                             router.setHidden("1".equals(menu.getVisible()));
                             router.setName(getRouteName(menu));
                             router.setPath(getRouterPath(menu));
                             router.setComponent(getComponent(menu));
-                            router.setMeta(new MetaVo(menu.getMenuName(), menu.getMenuAliasName(), menu.getIcon(), StringUtils.equals("1", menu.getIsCache()), menu.getPath(), menu.getIsFrame(), menu.getIsNew(), menu.getRemark()));
+                            router.setOrderNum(menu.getOrderNum());
+                            router.setMeta(new MetaVo(menu.getMenuName(), menu.getMenuAliasName(), menu.getIcon(), StringUtils.equals("1", menu.getIsCache()), menu.getPath(), menu.getIsFrame(), menu.getIsNew(), menu.getRemark(),menu.getMenuMold()));
                             List<SysMenu> cMenus = menu.getChildren();
-                            if (!cMenus.isEmpty() && cMenus.size() > 0 && UserConstants.TYPE_DIR.equals(menu.getMenuType()))
-                            {
+                            if (!cMenus.isEmpty() && cMenus.size() > 0 && UserConstants.TYPE_DIR.equals(menu.getMenuType())) {
                                 router.setAlwaysShow(true);
                                 router.setRedirect("noRedirect");
                                 router.setChildren(buildMenus(cMenus));
-                            }
-                            else if (isMenuFrame(menu))
-                            {
+                            } else if (isMenuFrame(menu)) {
                                 router.setMeta(null);
                                 List<RouterVo> childrenList = new ArrayList<RouterVo>();
                                 RouterVo children = new RouterVo();
                                 children.setPath(menu.getPath());
                                 children.setComponent(menu.getComponent());
                                 children.setName(StringUtils.capitalize(menu.getPath()));
-                                children.setMeta(new MetaVo(menu.getMenuName(), menu.getMenuAliasName(), menu.getIcon(), StringUtils.equals("1", menu.getIsCache()), menu.getPath(), menu.getIsFrame(), menu.getIsNew(), menu.getRemark()));
+                                children.setOrderNum(menu.getOrderNum());
+                                children.setMeta(new MetaVo(menu.getMenuName(), menu.getMenuAliasName(), menu.getIcon(), StringUtils.equals("1", menu.getIsCache()), menu.getPath(), menu.getIsFrame(), menu.getIsNew(), menu.getRemark(),menu.getMenuMold()));
                                 childrenList.add(children);
                                 router.setChildren(childrenList);
-                            }
-                            else if (menu.getParentId().intValue() == 0 && isInnerLink(menu))
-                            {
-                                router.setMeta(new MetaVo(menu.getMenuName(), menu.getMenuAliasName(), menu.getIcon(), menu.getIsFrame(), menu.getIsNew(), menu.getRemark()));
+                            } else if (menu.getParentId().intValue() == 0 && isInnerLink(menu)) {
+                                router.setMeta(new MetaVo(menu.getMenuName(), menu.getMenuAliasName(), menu.getIcon(), menu.getIsFrame(), menu.getIsNew(), menu.getRemark(),menu.getMenuMold()));
                                 router.setPath("/inner");
                                 List<RouterVo> childrenList = new ArrayList<RouterVo>();
                                 RouterVo children = new RouterVo();
-                                String routerPath = StringUtils.replaceEach(menu.getPath(), new String[] { Constants.HTTP, Constants.HTTPS }, new String[] { "", "" });
+                                String routerPath = StringUtils.replaceEach(menu.getPath(), new String[]{Constants.HTTP, Constants.HTTPS}, new String[]{"", ""});
                                 children.setPath(routerPath);
                                 children.setComponent(UserConstants.INNER_LINK);
                                 children.setName(StringUtils.capitalize(routerPath));
-                                children.setMeta(new MetaVo(menu.getMenuName(), menu.getMenuAliasName(), menu.getIcon(), menu.getPath(), menu.getIsFrame(), menu.getIsNew(), menu.getRemark()));
+                                children.setOrderNum(menu.getOrderNum());
+                                children.setMeta(new MetaVo(menu.getMenuName(), menu.getMenuAliasName(), menu.getIcon(), menu.getPath(), menu.getIsFrame(), menu.getIsNew(), menu.getRemark(),menu.getMenuMold()));
                                 childrenList.add(children);
                                 router.setChildren(childrenList);
                             }
@@ -434,26 +410,21 @@ public class SysMenuServiceImpl extends AbstractCrudService<SysMenuMapper, SysMe
      * @return 树结构列表
      */
     @Override
-    public List<SysMenu> buildMenuTree(List<SysMenu> menus)
-    {
+    public List<SysMenu> buildMenuTree(List<SysMenu> menus) {
         List<SysMenu> returnList = new ArrayList<SysMenu>();
         List<Long> tempList = new ArrayList<Long>();
-        for (SysMenu dept : menus)
-        {
+        for (SysMenu dept : menus) {
             tempList.add(dept.getMenuId());
         }
-        for (Iterator<SysMenu> iterator = menus.iterator(); iterator.hasNext();)
-        {
+        for (Iterator<SysMenu> iterator = menus.iterator(); iterator.hasNext(); ) {
             SysMenu menu = (SysMenu) iterator.next();
             // 如果是顶级节点, 遍历该父节点的所有子节点
-            if (!tempList.contains(menu.getParentId()))
-            {
+            if (!tempList.contains(menu.getParentId())) {
                 recursionFn(menus, menu);
                 returnList.add(menu);
             }
         }
-        if (returnList.isEmpty())
-        {
+        if (returnList.isEmpty()) {
             returnList = menus;
         }
         return returnList;
@@ -466,26 +437,21 @@ public class SysMenuServiceImpl extends AbstractCrudService<SysMenuMapper, SysMe
      * @return 树结构列表
      */
     @Override
-    public List<SysMobileMenu> buildMobileMenuTree(List<SysMobileMenu> menus)
-    {
+    public List<SysMobileMenu> buildMobileMenuTree(List<SysMobileMenu> menus) {
         List<SysMobileMenu> returnList = new ArrayList<SysMobileMenu>();
         List<Long> tempList = new ArrayList<Long>();
-        for (SysMobileMenu dept : menus)
-        {
+        for (SysMobileMenu dept : menus) {
             tempList.add(dept.getMenuId());
         }
-        for (Iterator<SysMobileMenu> iterator = menus.iterator(); iterator.hasNext();)
-        {
+        for (Iterator<SysMobileMenu> iterator = menus.iterator(); iterator.hasNext(); ) {
             SysMobileMenu menu = (SysMobileMenu) iterator.next();
             // 如果是顶级节点, 遍历该父节点的所有子节点
-            if (!tempList.contains(menu.getParentId()))
-            {
+            if (!tempList.contains(menu.getParentId())) {
                 recursionMobileFn(menus, menu);
                 returnList.add(menu);
             }
         }
-        if (returnList.isEmpty())
-        {
+        if (returnList.isEmpty()) {
             returnList = menus;
         }
         return returnList;
@@ -498,8 +464,7 @@ public class SysMenuServiceImpl extends AbstractCrudService<SysMenuMapper, SysMe
      * @return 下拉树结构列表
      */
     @Override
-    public List<TreeSelect> buildMenuTreeSelect(List<SysMenu> menus)
-    {
+    public List<TreeSelect> buildMenuTreeSelect(List<SysMenu> menus) {
         List<SysMenu> menuTrees = buildMenuTree(menus);
         return menuTrees.stream().map(TreeSelect::new).collect(Collectors.toList());
     }
@@ -511,8 +476,7 @@ public class SysMenuServiceImpl extends AbstractCrudService<SysMenuMapper, SysMe
      * @return 下拉树结构列表
      */
     @Override
-    public List<TreeMobileSelect> buildMobileMenuTreeSelect(List<SysMobileMenu> menus)
-    {
+    public List<TreeMobileSelect> buildMobileMenuTreeSelect(List<SysMobileMenu> menus) {
         List<SysMobileMenu> menuTrees = buildMobileMenuTree(menus);
         return menuTrees.stream().map(TreeMobileSelect::new).collect(Collectors.toList());
     }
@@ -524,8 +488,7 @@ public class SysMenuServiceImpl extends AbstractCrudService<SysMenuMapper, SysMe
      * @return 菜单信息
      */
     @Override
-    public SysMenu selectMenuById(Long menuId)
-    {
+    public SysMenu selectMenuById(Long menuId) {
         return menuMapper.selectMenuById(menuId);
     }
 
@@ -536,8 +499,7 @@ public class SysMenuServiceImpl extends AbstractCrudService<SysMenuMapper, SysMe
      * @return 结果
      */
     @Override
-    public boolean hasChildByMenuId(Long menuId)
-    {
+    public boolean hasChildByMenuId(Long menuId) {
         int result = menuMapper.hasChildByMenuId(menuId);
         return result > 0 ? true : false;
     }
@@ -549,8 +511,7 @@ public class SysMenuServiceImpl extends AbstractCrudService<SysMenuMapper, SysMe
      * @return 结果
      */
     @Override
-    public boolean checkMenuExistRole(Long menuId)
-    {
+    public boolean checkMenuExistRole(Long menuId) {
         int result = roleMenuMapper.checkMenuExistRole(menuId);
         return result > 0 ? true : false;
     }
@@ -562,8 +523,7 @@ public class SysMenuServiceImpl extends AbstractCrudService<SysMenuMapper, SysMe
      * @return 结果
      */
     @Override
-    public int insertMenu(SysMenu menu)
-    {
+    public int insertMenu(SysMenu menu) {
         return menuMapper.insertMenu(menu);
     }
 
@@ -574,55 +534,53 @@ public class SysMenuServiceImpl extends AbstractCrudService<SysMenuMapper, SysMe
      * @return 结果
      */
     @Override
-    public int updateMenu(SysMenu menu)
-    {
+    public int updateMenu(SysMenu menu) {
         return menuMapper.updateMenu(menu);
     }
 
     @Override
-    public void updateTenantMenu(SysTenantMenu tenantMenu){
+    public void updateTenantMenu(SysTenantMenu tenantMenu) {
         UpdateWrapper<SysTenantMenu> updateWrapper = Wrappers.update();
-        updateWrapper.set("menu_alias_name",tenantMenu.getMenuAliasName())
-                .eq("tenant_id",tenantMenu.getTenantId())
-                .eq("menu_id",tenantMenu.getMenuId());
+        updateWrapper.set("menu_alias_name", tenantMenu.getMenuAliasName())
+                .eq("tenant_id", tenantMenu.getTenantId())
+                .eq("menu_id", tenantMenu.getMenuId());
         tenantMenuService.update(updateWrapper);
 
 
-
         LambdaQueryWrapper<SysUser> queryWrapper1 = Wrappers.lambdaQuery();
         queryWrapper1.select(SysUser::getUserId)
-                .eq(SysUser::getStatus,0)
-                .eq(SysUser::getDelFlag,0)
-                .eq(SysUser::getTenantId,SecurityUtils.getTenantId());
+                .eq(SysUser::getStatus, 0)
+                .eq(SysUser::getDelFlag, 0)
+                .eq(SysUser::getTenantId, SecurityUtils.getTenantId());
         List<SysUser> list = sysUserMapper.selectList(queryWrapper1);
         List<Long> userIdList = new ArrayList<>();
-        if(CollectionUtils.isNotEmpty(list)){
+        if (CollectionUtils.isNotEmpty(list)) {
             for (int i = 0; i < list.size(); i++) {
                 userIdList.add(list.get(i).getUserId());
             }
         }
 
-        if(userIdList.size() > 0){
+        if (userIdList.size() > 0) {
             LambdaQueryWrapper<SysUserRole> queryWrapper = Wrappers.lambdaQuery();
-            queryWrapper.in(SysUserRole::getUserId,userIdList);
+            queryWrapper.in(SysUserRole::getUserId, userIdList);
             List<SysUserRole> userRoleList = sysUserRoleMapper.selectList(queryWrapper);
             List<Long> roleIdList = new ArrayList<>();
-            if(userRoleList.size() > 0){
+            if (userRoleList.size() > 0) {
                 for (int i = 0; i < userRoleList.size(); i++) {
-                    if(roleIdList.contains(userRoleList.get(i).getRoleId())){
+                    if (roleIdList.contains(userRoleList.get(i).getRoleId())) {
 
-                    }else{
+                    } else {
                         roleIdList.add(userRoleList.get(i).getRoleId());
                     }
                 }
             }
 
-            if(roleIdList.size() > 0){
+            if (roleIdList.size() > 0) {
                 UpdateWrapper<SysRoleMenu> updateWrapper1 = Wrappers.update();
-                updateWrapper1.set("menu_alias_name",tenantMenu.getMenuAliasName())
-                        .in("role_id",roleIdList)
-                        .eq("menu_id",tenantMenu.getMenuId());
-                sysRoleMenuMapper.update(null,updateWrapper1);
+                updateWrapper1.set("menu_alias_name", tenantMenu.getMenuAliasName())
+                        .in("role_id", roleIdList)
+                        .eq("menu_id", tenantMenu.getMenuId());
+                sysRoleMenuMapper.update(null, updateWrapper1);
             }
 
         }
@@ -636,8 +594,7 @@ public class SysMenuServiceImpl extends AbstractCrudService<SysMenuMapper, SysMe
      * @return 结果
      */
     @Override
-    public int deleteMenuById(Long menuId)
-    {
+    public int deleteMenuById(Long menuId) {
         return menuMapper.deleteMenuById(menuId);
     }
 
@@ -648,12 +605,10 @@ public class SysMenuServiceImpl extends AbstractCrudService<SysMenuMapper, SysMe
      * @return 结果
      */
     @Override
-    public String checkMenuNameUnique(SysMenu menu)
-    {
+    public String checkMenuNameUnique(SysMenu menu) {
         Long menuId = Objects.isNull(menu.getMenuId()) ? -1L : menu.getMenuId();
         SysMenu info = menuMapper.checkMenuNameUnique(menu.getMenuName(), menu.getParentId());
-        if (Objects.nonNull(info) && info.getMenuId().longValue() != menuId.longValue())
-        {
+        if (Objects.nonNull(info) && info.getMenuId().longValue() != menuId.longValue()) {
             return UserConstants.NOT_UNIQUE;
         }
         return UserConstants.UNIQUE;
@@ -665,12 +620,10 @@ public class SysMenuServiceImpl extends AbstractCrudService<SysMenuMapper, SysMe
      * @param menu 菜单信息
      * @return 路由名称
      */
-    public String getRouteName(SysMenu menu)
-    {
+    public String getRouteName(SysMenu menu) {
         String routerName = StringUtils.capitalize(menu.getPath());
         // 非外链并且是一级目录(类型为目录)
-        if (isMenuFrame(menu))
-        {
+        if (isMenuFrame(menu)) {
             routerName = StringUtils.EMPTY;
         }
         return routerName;
@@ -682,23 +635,19 @@ public class SysMenuServiceImpl extends AbstractCrudService<SysMenuMapper, SysMe
      * @param menu 菜单信息
      * @return 路由地址
      */
-    public String getRouterPath(SysMenu menu)
-    {
+    public String getRouterPath(SysMenu menu) {
         String routerPath = menu.getPath();
         // 内链打开外网方式
-        if (menu.getParentId().intValue() != 0 && isInnerLink(menu))
-        {
-            routerPath = StringUtils.replaceEach(routerPath, new String[] { Constants.HTTP, Constants.HTTPS }, new String[] { "", "" });
+        if (menu.getParentId().intValue() != 0 && isInnerLink(menu)) {
+            routerPath = StringUtils.replaceEach(routerPath, new String[]{Constants.HTTP, Constants.HTTPS}, new String[]{"", ""});
         }
         // 非外链并且是一级目录(类型为目录)
         if (0 == menu.getParentId().intValue() && UserConstants.TYPE_DIR.equals(menu.getMenuType())
-                && UserConstants.NO_FRAME.equals(menu.getIsFrame()))
-        {
+                && UserConstants.NO_FRAME.equals(menu.getIsFrame())) {
             routerPath = "/" + menu.getPath();
         }
         // 非外链并且是一级目录(类型为菜单)
-        else if (isMenuFrame(menu))
-        {
+        else if (isMenuFrame(menu)) {
             routerPath = "/";
         }
         return routerPath;
@@ -710,19 +659,13 @@ public class SysMenuServiceImpl extends AbstractCrudService<SysMenuMapper, SysMe
      * @param menu 菜单信息
      * @return 组件信息
      */
-    public String getComponent(SysMenu menu)
-    {
+    public String getComponent(SysMenu menu) {
         String component = UserConstants.LAYOUT;
-        if (StringUtils.isNotEmpty(menu.getComponent()) && !isMenuFrame(menu))
-        {
+        if (StringUtils.isNotEmpty(menu.getComponent()) && !isMenuFrame(menu)) {
             component = menu.getComponent();
-        }
-        else if (StringUtils.isEmpty(menu.getComponent()) && menu.getParentId().intValue() != 0 && isInnerLink(menu))
-        {
+        } else if (StringUtils.isEmpty(menu.getComponent()) && menu.getParentId().intValue() != 0 && isInnerLink(menu)) {
             component = UserConstants.INNER_LINK;
-        }
-        else if (StringUtils.isEmpty(menu.getComponent()) && isParentView(menu))
-        {
+        } else if (StringUtils.isEmpty(menu.getComponent()) && isParentView(menu)) {
             component = UserConstants.PARENT_VIEW;
         }
         return component;
@@ -734,8 +677,7 @@ public class SysMenuServiceImpl extends AbstractCrudService<SysMenuMapper, SysMe
      * @param menu 菜单信息
      * @return 结果
      */
-    public boolean isMenuFrame(SysMenu menu)
-    {
+    public boolean isMenuFrame(SysMenu menu) {
         return menu.getParentId().intValue() == 0 && UserConstants.TYPE_MENU.equals(menu.getMenuType())
                 && menu.getIsFrame().equals(UserConstants.NO_FRAME);
     }
@@ -746,8 +688,7 @@ public class SysMenuServiceImpl extends AbstractCrudService<SysMenuMapper, SysMe
      * @param menu 菜单信息
      * @return 结果
      */
-    public boolean isInnerLink(SysMenu menu)
-    {
+    public boolean isInnerLink(SysMenu menu) {
         return menu.getIsFrame().equals(UserConstants.NO_FRAME) && StringUtils.startsWithAny(menu.getPath(), Constants.HTTP, Constants.HTTPS);
     }
 
@@ -757,8 +698,7 @@ public class SysMenuServiceImpl extends AbstractCrudService<SysMenuMapper, SysMe
      * @param menu 菜单信息
      * @return 结果
      */
-    public boolean isParentView(SysMenu menu)
-    {
+    public boolean isParentView(SysMenu menu) {
         return menu.getParentId().intValue() != 0 && UserConstants.TYPE_DIR.equals(menu.getMenuType());
     }
 
@@ -769,15 +709,12 @@ public class SysMenuServiceImpl extends AbstractCrudService<SysMenuMapper, SysMe
      * @param parentId 传入的父节点ID
      * @return String
      */
-    public List<SysMenu> getChildPerms(List<SysMenu> list, int parentId)
-    {
+    public List<SysMenu> getChildPerms(List<SysMenu> list, int parentId) {
         List<SysMenu> returnList = new ArrayList<SysMenu>();
-        for (Iterator<SysMenu> iterator = list.iterator(); iterator.hasNext();)
-        {
+        for (Iterator<SysMenu> iterator = list.iterator(); iterator.hasNext(); ) {
             SysMenu t = (SysMenu) iterator.next();
             // 一、根据传入的某个父节点ID,遍历该父节点的所有子节点
-            if (t.getParentId() == parentId)
-            {
+            if (t.getParentId() == parentId) {
                 recursionFn(list, t);
                 returnList.add(t);
             }
@@ -791,15 +728,12 @@ public class SysMenuServiceImpl extends AbstractCrudService<SysMenuMapper, SysMe
      * @param list
      * @param t
      */
-    private void recursionFn(List<SysMenu> list, SysMenu t)
-    {
+    private void recursionFn(List<SysMenu> list, SysMenu t) {
         // 得到子节点列表
         List<SysMenu> childList = getChildList(list, t);
         t.setChildren(childList);
-        for (SysMenu tChild : childList)
-        {
-            if (hasChild(list, tChild))
-            {
+        for (SysMenu tChild : childList) {
+            if (hasChild(list, tChild)) {
                 recursionFn(list, tChild);
             }
         }
@@ -811,15 +745,12 @@ public class SysMenuServiceImpl extends AbstractCrudService<SysMenuMapper, SysMe
      * @param list
      * @param t
      */
-    private void recursionMobileFn(List<SysMobileMenu> list, SysMobileMenu t)
-    {
+    private void recursionMobileFn(List<SysMobileMenu> list, SysMobileMenu t) {
         // 得到子节点列表
         List<SysMobileMenu> childList = getChildMobileList(list, t);
         t.setChildren(childList);
-        for (SysMobileMenu tChild : childList)
-        {
-            if (hasMobileChild(list, tChild))
-            {
+        for (SysMobileMenu tChild : childList) {
+            if (hasMobileChild(list, tChild)) {
                 recursionMobileFn(list, tChild);
             }
         }
@@ -828,15 +759,12 @@ public class SysMenuServiceImpl extends AbstractCrudService<SysMenuMapper, SysMe
     /**
      * 得到子节点列表
      */
-    private List<SysMenu> getChildList(List<SysMenu> list, SysMenu t)
-    {
+    private List<SysMenu> getChildList(List<SysMenu> list, SysMenu t) {
         List<SysMenu> tlist = new ArrayList<SysMenu>();
         Iterator<SysMenu> it = list.iterator();
-        while (it.hasNext())
-        {
+        while (it.hasNext()) {
             SysMenu n = (SysMenu) it.next();
-            if (n.getParentId().longValue() == t.getMenuId().longValue())
-            {
+            if (n.getParentId().longValue() == t.getMenuId().longValue()) {
                 tlist.add(n);
             }
         }
@@ -846,15 +774,12 @@ public class SysMenuServiceImpl extends AbstractCrudService<SysMenuMapper, SysMe
     /**
      * 得到移动端子节点列表
      */
-    private List<SysMobileMenu> getChildMobileList(List<SysMobileMenu> list, SysMobileMenu t)
-    {
+    private List<SysMobileMenu> getChildMobileList(List<SysMobileMenu> list, SysMobileMenu t) {
         List<SysMobileMenu> tlist = new ArrayList<SysMobileMenu>();
         Iterator<SysMobileMenu> it = list.iterator();
-        while (it.hasNext())
-        {
+        while (it.hasNext()) {
             SysMobileMenu n = (SysMobileMenu) it.next();
-            if (n.getParentId().longValue() == t.getMenuId())
-            {
+            if (n.getParentId().longValue() == t.getMenuId()) {
                 tlist.add(n);
             }
         }
@@ -864,30 +789,27 @@ public class SysMenuServiceImpl extends AbstractCrudService<SysMenuMapper, SysMe
     /**
      * 判断是否有子节点
      */
-    private boolean hasChild(List<SysMenu> list, SysMenu t)
-    {
+    private boolean hasChild(List<SysMenu> list, SysMenu t) {
         return getChildList(list, t).size() > 0 ? true : false;
     }
 
     /**
      * 判断移动端是否有子节点
      */
-    private boolean hasMobileChild(List<SysMobileMenu> list, SysMobileMenu t)
-    {
+    private boolean hasMobileChild(List<SysMobileMenu> list, SysMobileMenu t) {
         return getChildMobileList(list, t).size() > 0 ? true : false;
     }
 
     @Override
-    public List<TenantPlatformMenuVo> selectRolePlatformMenu()
-    {
+    public List<TenantPlatformMenuVo> selectRolePlatformMenu() {
         List<TenantPlatformMenuVo> list1 = new ArrayList<>();
         List<SysPlatformVo> list = sysPlatformMapper.getTenantPlatformList(SecurityUtils.getTenantId());
-        if (CollectionUtils.isNotEmpty(list)){
-            for(int i=0;i<list.size();i++){
+        if (CollectionUtils.isNotEmpty(list)) {
+            for (int i = 0; i < list.size(); i++) {
                 TenantPlatformMenuVo tenantPlatformMenuVo = new TenantPlatformMenuVo();
                 tenantPlatformMenuVo.setId(list.get(i).getId());
                 tenantPlatformMenuVo.setLabel(list.get(i).getPlatformName());
-                List<SysMenu> menus = baseMapper.getTenantPlatformMenuList(SecurityUtils.getTenantId(),list.get(i).getId());
+                List<SysMenu> menus = baseMapper.getTenantPlatformMenuList(SecurityUtils.getTenantId(), list.get(i).getId());
                 tenantPlatformMenuVo.setChildren(this.buildMenuTreeSelect(menus));
                 list1.add(tenantPlatformMenuVo);
             }

+ 1 - 1
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/service/impl/SysMobileMenuServiceImpl.java

@@ -238,7 +238,7 @@ public class SysMobileMenuServiceImpl extends AbstractCrudService<SysMobileMenuM
         }
         else
         {
-            menus = sysMobileMenuMapper.selectMenuTreeByUserId(userId);
+            menus = sysMobileMenuMapper.selectMenuTreeByUserId1(userId,SecurityUtils.getTenantId());
         }
         return getChildPerms(menus, 0);
     }

+ 71 - 31
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/service/impl/SysNoticeServiceImpl.java

@@ -1,111 +1,151 @@
 package com.usky.system.service.impl;
 
 
-import com.google.gson.JsonObject;
-import com.usky.common.core.bean.ApiResult;
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.usky.common.core.exception.BusinessException;
 import com.usky.common.mybatis.core.AbstractCrudService;
+import com.usky.common.security.utils.SecurityUtils;
+import com.usky.system.domain.MceRequestVO;
 import com.usky.system.domain.SysNotice;
+import com.usky.system.domain.SysUser;
 import com.usky.system.mapper.SysNoticeMapper;
+import com.usky.system.mapper.SysUserMapper;
 import com.usky.system.service.ISysNoticeService;
 import com.usky.system.service.MceReceiveService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
-import java.util.HashMap;
+import java.util.Arrays;
 import java.util.List;
-import java.util.Map;
+import java.util.stream.Collectors;
 
 /**
  * 公告 服务层实现
- * 
+ *
  * @author ruoyi
  */
 @Service
-public class SysNoticeServiceImpl extends AbstractCrudService<SysNoticeMapper, SysNotice> implements ISysNoticeService
-{
+public class SysNoticeServiceImpl extends AbstractCrudService<SysNoticeMapper, SysNotice> implements ISysNoticeService {
     @Autowired
     private SysNoticeMapper noticeMapper;
 
     @Autowired
     private MceReceiveService mceReceiveService;
 
+    @Autowired
+    private SysUserMapper sysUserMapper;
+
     /**
      * 查询公告信息
-     * 
+     *
      * @param noticeId 公告ID
      * @return 公告信息
      */
     @Override
-    public SysNotice selectNoticeById(Long noticeId)
-    {
+    public SysNotice selectNoticeById(Long noticeId) {
         return noticeMapper.selectNoticeById(noticeId);
     }
 
     /**
      * 查询公告列表
-     * 
+     *
      * @param notice 公告信息
      * @return 公告集合
      */
     @Override
-    public List<SysNotice> selectNoticeList(SysNotice notice)
-    {
+    public List<SysNotice> selectNoticeList(SysNotice notice) {
+        notice.setTenantId(SecurityUtils.getTenantId());
+        String deptId = SecurityUtils.getLoginUser().getSysUser().getDeptId().toString();
+        notice.setDeptId(deptId);
         return noticeMapper.selectNoticeList(notice);
     }
 
     /**
      * 新增公告
-     * 
+     *
      * @param notice 公告信息
      * @return 结果
      */
     @Override
-    public int insertNotice(SysNotice notice)
-    {
+    public int insertNotice(SysNotice notice) {
+        notice.setTenantId(SecurityUtils.getTenantId());
         noticeMapper.insertNotice(notice);
         int insertId = notice.getNoticeId();
-        JsonObject jsonObject = new JsonObject();
-        jsonObject.addProperty("infoTitle", notice.getNoticeTitle());
-        jsonObject.addProperty("infoContent",notice.getNoticeContent());
-        jsonObject.addProperty("infoType",1);
-        jsonObject.addProperty("id",insertId);
-        mceReceiveService.add(jsonObject.toString());
+
+        String deptId = notice.getDeptId();
+        List<Long> deptIds = Arrays.stream(deptId.split(",")).map(Long::parseLong).collect(Collectors.toList());
+        List<Long> usersIds = sysUserMapper.selectList(Wrappers.lambdaQuery(SysUser.class).select(SysUser::getUserId).in(SysUser::getDeptId, deptIds)).stream().map(SysUser::getUserId).collect(Collectors.toList());
+
+        if (!deptIds.isEmpty()) {
+            sendNotice(notice.getNoticeTitle(), insertId, notice.getCreateBy(), usersIds);
+        }
+
         return insertId;
     }
 
+    /**
+     * 发送消息
+     * @param infoContent 消息内容
+     * @param id 通知公告id
+     * @param userName 发布人
+     * @param userIds 接收人
+     */
+    private void sendNotice(String infoContent, Integer id, String userName, List<Long> userIds) {
+
+        // JSONObject jsonObject = new JSONObject();
+        // jsonObject.put("infoTitle", "通知公告");
+        // jsonObject.put("infoContent", infoContent);
+        // jsonObject.put("infoType", 1);
+        // jsonObject.put("id", id);
+        // jsonObject.put("userName", userName);
+        // jsonObject.put("userIds", userIds);
+        MceRequestVO mceRequestVO = new MceRequestVO();
+        mceRequestVO.setInfoTitle("通知公告");
+        mceRequestVO.setInfoContent(infoContent);
+        mceRequestVO.setInfoType("1");
+        mceRequestVO.setId(id);
+        mceRequestVO.setUserName(userName);
+        mceRequestVO.setUserIds(userIds);
+        mceRequestVO.setRealName(SecurityUtils.getLoginUser().getSysUser().getNickName());
+        try {
+            // mceReceiveService.add(jsonObject.toString());
+            mceReceiveService.addMceReceive(mceRequestVO);
+        } catch (Exception e) {
+            log.error(String.format("公告:%d,消息发送失败:%s", id, e.getMessage()));
+        }
+    }
+
     /**
      * 修改公告
-     * 
+     *
      * @param notice 公告信息
      * @return 结果
      */
     @Override
-    public int updateNotice(SysNotice notice)
-    {
+    public int updateNotice(SysNotice notice) {
         return noticeMapper.updateNotice(notice);
     }
 
     /**
      * 删除公告对象
-     * 
+     *
      * @param noticeId 公告ID
      * @return 结果
      */
     @Override
-    public int deleteNoticeById(Long noticeId)
-    {
+    public int deleteNoticeById(Long noticeId) {
         return noticeMapper.deleteNoticeById(noticeId);
     }
 
     /**
      * 批量删除公告信息
-     * 
+     *
      * @param noticeIds 需要删除的公告ID
      * @return 结果
      */
     @Override
-    public int deleteNoticeByIds(Long[] noticeIds)
-    {
+    public int deleteNoticeByIds(Long[] noticeIds) {
         return noticeMapper.deleteNoticeByIds(noticeIds);
     }
 }

+ 129 - 1
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/service/impl/SysPersonServiceImpl.java

@@ -4,16 +4,27 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.usky.common.mybatis.core.AbstractCrudService;
-import com.usky.common.security.utils.SecurityUtils;
+import com.usky.system.domain.SysDept;
 import com.usky.system.domain.SysPerson;
+import com.usky.system.domain.SysPost;
+import com.usky.system.domain.SysUser;
 import com.usky.system.domain.SysUserPerson;
 import com.usky.system.mapper.SysPersonMapper;
+import com.usky.system.service.ISysDeptService;
+import com.usky.system.service.ISysPostService;
+import com.usky.system.service.ISysUserService;
 import com.usky.system.service.SysPersonService;
 import com.usky.system.service.SysUserPersonService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
+import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+import java.util.stream.Collectors;
 
 /**
  * <p>
@@ -27,6 +38,12 @@ import java.util.List;
 public class SysPersonServiceImpl extends AbstractCrudService<SysPersonMapper, SysPerson> implements SysPersonService {
     @Autowired
     private SysUserPersonService sysUserPersonService;
+    @Autowired
+    private ISysUserService sysUserService;
+    @Autowired
+    private ISysDeptService sysDeptService;
+    @Autowired
+    private ISysPostService sysPostService;
 
     @Override
     public SysPerson getsysPerson(Long userid) {
@@ -38,7 +55,118 @@ public class SysPersonServiceImpl extends AbstractCrudService<SysPersonMapper, S
             LambdaQueryWrapper<SysPerson> query = Wrappers.lambdaQuery();
             query.eq(SysPerson::getId, userPersonList.get(0).getPersonId());
             sysPerson = this.getOne(query);
+            if (sysPerson != null) {
+                fillDeptAndPostFromUser(sysPerson, userid);
+            }
         }
         return sysPerson;
     }
+
+    @Override
+    public void fillDeptAndPostFromUser(SysPerson person, Long userId) {
+        if (person == null) {
+            return;
+        }
+        if (userId == null) {
+            clearPersonDeptPost(person);
+            return;
+        }
+        SysUser user = sysUserService.selectUserById(userId);
+        if (user == null) {
+            clearPersonDeptPost(person);
+            return;
+        }
+        person.setDeptId(user.getDeptId());
+        if (user.getDeptId() != null) {
+            SysDept dept = sysDeptService.selectDeptById(user.getDeptId());
+            person.setDeptName(dept != null ? dept.getDeptName() : null);
+        } else {
+            person.setDeptName(null);
+        }
+        List<Integer> postIds = sysPostService.selectPostListByUserId(userId);
+        if (postIds == null || postIds.isEmpty()) {
+            person.setPostId(null);
+            person.setPostName(null);
+        } else {
+            Long pid = postIds.get(0).longValue();
+            person.setPostId(pid);
+            SysPost post = sysPostService.selectPostById(pid);
+            person.setPostName(post != null ? post.getPostName() : null);
+        }
+    }
+
+    @Override
+    public void fillDeptAndPostForList(List<SysPerson> list, Map<Integer, Long> personIdToUserId) {
+        if (list == null || list.isEmpty()) {
+            return;
+        }
+        if (personIdToUserId == null || personIdToUserId.isEmpty()) {
+            list.forEach(this::clearPersonDeptPost);
+            return;
+        }
+        Set<Long> userIds = new HashSet<>(personIdToUserId.values());
+        if (userIds.isEmpty()) {
+            list.forEach(this::clearPersonDeptPost);
+            return;
+        }
+        List<SysUser> users = sysUserService.list(Wrappers.<SysUser>lambdaQuery().in(SysUser::getUserId, userIds));
+        Map<Long, SysUser> userById = users.stream()
+                .collect(Collectors.toMap(SysUser::getUserId, u -> u, (a, b) -> a));
+
+        List<Long> deptIdList = users.stream()
+                .map(SysUser::getDeptId)
+                .filter(Objects::nonNull)
+                .distinct()
+                .collect(Collectors.toList());
+        Map<Long, String> deptNameMap = new HashMap<>();
+        if (!deptIdList.isEmpty()) {
+            List<SysDept> depts = sysDeptService.selectDeptByIds(deptIdList);
+            if (depts != null) {
+                for (SysDept d : depts) {
+                    deptNameMap.put(d.getDeptId(), d.getDeptName());
+                }
+            }
+        }
+
+        Map<Long, Long> userFirstPostId = new HashMap<>();
+        for (Long uid : userIds) {
+            List<Integer> pids = sysPostService.selectPostListByUserId(uid);
+            if (pids != null && !pids.isEmpty()) {
+                userFirstPostId.put(uid, pids.get(0).longValue());
+            }
+        }
+        Set<Long> postIdSet = new HashSet<>(userFirstPostId.values());
+        Map<Long, String> postNameMap = new HashMap<>();
+        for (Long pid : postIdSet) {
+            SysPost post = sysPostService.selectPostById(pid);
+            if (post != null) {
+                postNameMap.put(pid, post.getPostName());
+            }
+        }
+
+        for (SysPerson p : list) {
+            Long uid = personIdToUserId.get(p.getId());
+            if (uid == null) {
+                clearPersonDeptPost(p);
+                continue;
+            }
+            SysUser u = userById.get(uid);
+            if (u == null) {
+                clearPersonDeptPost(p);
+                continue;
+            }
+            p.setDeptId(u.getDeptId());
+            p.setDeptName(u.getDeptId() != null ? deptNameMap.get(u.getDeptId()) : null);
+            Long pid = userFirstPostId.get(uid);
+            p.setPostId(pid);
+            p.setPostName(pid != null ? postNameMap.get(pid) : null);
+        }
+    }
+
+    private void clearPersonDeptPost(SysPerson person) {
+        person.setDeptId(null);
+        person.setDeptName(null);
+        person.setPostId(null);
+        person.setPostName(null);
+    }
 }

+ 17 - 7
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/service/impl/SysPlatformMenuServiceImpl.java

@@ -1,14 +1,12 @@
 package com.usky.system.service.impl;
 
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.usky.common.mybatis.core.AbstractCrudService;
-import com.usky.system.domain.SysMenu;
-import com.usky.system.domain.SysMobileMenu;
-import com.usky.system.domain.SysPlatformMenu;
-import com.usky.system.domain.SysTenantMenu;
-import com.usky.system.domain.SysMobileTenantMenu;
+import com.usky.system.domain.*;
 import com.usky.system.mapper.SysPlatformMenuMapper;
+import com.usky.system.mapper.SysTenantPlatformMapper;
 import com.usky.system.service.SysMobileTenantMenuService;
 import com.usky.system.service.SysPlatformMenuService;
 import com.usky.system.service.SysTenantMenuService;
@@ -36,6 +34,9 @@ public class SysPlatformMenuServiceImpl extends AbstractCrudService<SysPlatformM
     @Autowired
     private SysTenantMenuService sysTenantMenuService;
 
+    @Autowired
+    private SysTenantPlatformMapper sysTenantPlatformMapper;
+
     @Autowired
     private SysMobileTenantMenuService sysMobileTenantMenuService;
 
@@ -43,8 +44,17 @@ public class SysPlatformMenuServiceImpl extends AbstractCrudService<SysPlatformM
         return baseMapper.getMenuList(platformId, null);
     }
 
-    public List<SysMobileMenu> getMobilePlatformMenuList(Integer platformId){
-        return baseMapper.getMobileMenuList(platformId, null);
+    public List<SysMobileMenu> getMobilePlatformMenuList(Integer tenantId){
+        LambdaQueryWrapper<SysTenantPlatform> queryWrapper = Wrappers.lambdaQuery();
+        queryWrapper.eq(SysTenantPlatform::getTenantId,tenantId);
+        List<SysTenantPlatform> list = sysTenantPlatformMapper.selectList(queryWrapper);
+        List<Integer> platformIds = new ArrayList<>();
+        if (CollectionUtils.isNotEmpty(list)) {
+            for (int j = 0; j < list.size(); j++) {
+                platformIds.add(list.get(j).getPlatformId());
+            }
+        }
+        return baseMapper.getMobileMenuList(platformIds, null);
     }
 
     public Long[] selectPlatformMenu(Integer tenantId){

+ 2 - 0
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/service/impl/SysPlatformServiceImpl.java

@@ -98,6 +98,8 @@ public class SysPlatformServiceImpl extends AbstractCrudService<SysPlatformMappe
         SysPlatform sysPlatform = new SysPlatform();
         sysPlatform.setPlatformName(platformMenuVo.getPlatformName());
         sysPlatform.setIcon(platformMenuVo.getIcon());
+        sysPlatform.setOrderNum(platformMenuVo.getOrderNum());
+        sysPlatform.setPlatformType(platformMenuVo.getPlatformType());
         if (platformMenuVo.getPlatformId().intValue() == 0) {
             sysPlatform.setCreateBy(SecurityUtils.getUsername());
             sysPlatform.setCreateTime(LocalDateTime.now());

+ 7 - 4
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/service/impl/SysRoleServiceImpl.java

@@ -125,9 +125,9 @@ public class SysRoleServiceImpl extends AbstractCrudService<SysRoleMapper, SysRo
      * @return 选中角色ID列表
      */
     @Override
-    public List<Integer> selectRoleListByUserId(Long userId)
+    public List<Integer> selectRoleListByUserId(Long userId, Integer tenantId)
     {
-        return roleMapper.selectRoleListByUserId(userId);
+        return roleMapper.selectRoleListByUserId(userId,tenantId);
     }
 
     /**
@@ -201,7 +201,7 @@ public class SysRoleServiceImpl extends AbstractCrudService<SysRoleMapper, SysRo
     @Override
     public int countUserRoleByRoleId(Long roleId)
     {
-        return userRoleMapper.countUserRoleByRoleId(roleId);
+        return userRoleMapper.countUserRoleByRoleId(roleId,SecurityUtils.getTenantId());
     }
 
     /**
@@ -395,7 +395,8 @@ public class SysRoleServiceImpl extends AbstractCrudService<SysRoleMapper, SysRo
     @Override
     public int deleteAuthUsers(Long roleId, Long[] userIds)
     {
-        return userRoleMapper.deleteUserRoleInfos(roleId, userIds);
+        Integer tenantId = SecurityUtils.getTenantId();
+        return userRoleMapper.deleteUserRoleInfos(roleId, userIds, tenantId);
     }
 
     /**
@@ -410,11 +411,13 @@ public class SysRoleServiceImpl extends AbstractCrudService<SysRoleMapper, SysRo
     {
         // 新增用户与角色管理
         List<SysUserRole> list = new ArrayList<SysUserRole>();
+        Integer tenantId = SecurityUtils.getTenantId();
         for (Long userId : userIds)
         {
             SysUserRole ur = new SysUserRole();
             ur.setUserId(userId);
             ur.setRoleId(roleId);
+            ur.setTenantId(tenantId);
             list.add(ur);
         }
         return userRoleMapper.batchUserRole(list);

+ 2 - 0
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/service/impl/SysUserOnlineServiceImpl.java

@@ -90,6 +90,8 @@ public class SysUserOnlineServiceImpl implements ISysUserOnlineService
         sysUserOnline.setIpaddr(user.getIpaddr());
         sysUserOnline.setLoginTime(user.getLoginTime());
         sysUserOnline.setExpireTime(user.getExpireTime());
+        sysUserOnline.setOs(user.getOs());
+        sysUserOnline.setBrowser(user.getBrowser());
         return sysUserOnline;
     }
 }

+ 35 - 0
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/service/impl/SysUserPersonServiceImpl.java

@@ -1,11 +1,17 @@
 package com.usky.system.service.impl;
 
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
+import com.usky.common.core.exception.BusinessException;
+import com.usky.common.security.utils.SecurityUtils;
 import com.usky.system.domain.SysUserPerson;
 import com.usky.system.mapper.SysUserPersonMapper;
 import com.usky.system.service.SysUserPersonService;
 import com.usky.common.mybatis.core.AbstractCrudService;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
+import java.util.Objects;
+
 /**
  * <p>
  * 用户人员关联 服务实现类
@@ -17,4 +23,33 @@ import org.springframework.stereotype.Service;
 @Service
 public class SysUserPersonServiceImpl extends AbstractCrudService<SysUserPersonMapper, SysUserPerson> implements SysUserPersonService {
 
+    @Autowired
+    private SysUserPersonMapper sysUserPersonMapper;
+
+    @Override
+    public Integer upIsLoginNotify(Long userId, Integer isLoginNotify) {
+
+        // 判断 isLoginNotify 是否为 0 或 1
+        if (isLoginNotify != 0 && isLoginNotify != 1) {
+            throw new BusinessException("参数设置错误");
+        }
+        // 判断要修改的用户是否为登录用户
+        if (!Objects.equals(userId, SecurityUtils.getUserId())) {
+            throw new BusinessException("你不能修改非本人的登录通知设置!");
+        }
+
+        // 更新登录通知设置
+        LambdaUpdateWrapper<SysUserPerson> wrapper = new LambdaUpdateWrapper<>();
+        wrapper.eq(SysUserPerson::getUserId, userId)
+                .set(SysUserPerson::getIsLoginNotify, isLoginNotify);
+        int result = sysUserPersonMapper.update(null, wrapper);
+
+        //  更新失败
+        if (result <= 0) {
+            log.error("用户:{},操作登录通知开关操作失败!");
+            throw new BusinessException("登录通知开关操作失败!请重试");
+        }
+
+        return result;
+    }
 }

Некоторые файлы не были показаны из-за большого количества измененных файлов