Browse Source

hms 文件上传 邮件发送

S0025136190 1 year ago
parent
commit
458f64066c
23 changed files with 910 additions and 8 deletions
  1. 6 0
      Backend/sample/pom.xml
  2. 109 0
      Backend/sample/src/main/java/com/dji/sample/common/util/EmailUtil.java
  3. 6 0
      Backend/sample/src/main/java/com/dji/sample/component/oss/model/OssConfiguration.java
  4. 95 0
      Backend/sample/src/main/java/com/dji/sample/configuration/MailConfiguration.java
  5. 32 3
      Backend/sample/src/main/java/com/dji/sample/manage/controller/DeviceLogsController.java
  6. 6 0
      Backend/sample/src/main/java/com/dji/sample/manage/model/dto/DeviceLogsDTO.java
  7. 42 0
      Backend/sample/src/main/java/com/dji/sample/manage/model/dto/DeviceLogsDetailRespDTO.java
  8. 49 0
      Backend/sample/src/main/java/com/dji/sample/manage/model/dto/DeviceLogsRespDTO.java
  9. 69 0
      Backend/sample/src/main/java/com/dji/sample/manage/model/dto/FileUploadFile.java
  10. 68 0
      Backend/sample/src/main/java/com/dji/sample/manage/model/dto/LogFileIndexDTO.java
  11. 9 0
      Backend/sample/src/main/java/com/dji/sample/manage/model/entity/DeviceLogsEntity.java
  12. 29 0
      Backend/sample/src/main/java/com/dji/sample/manage/model/param/DeviceLogsParam.java
  13. 31 0
      Backend/sample/src/main/java/com/dji/sample/manage/model/param/ManagerLogsQueryParam.java
  14. 10 0
      Backend/sample/src/main/java/com/dji/sample/manage/service/IDeviceLogsService.java
  15. 196 4
      Backend/sample/src/main/java/com/dji/sample/manage/service/impl/DeviceLogsServiceImpl.java
  16. 20 0
      Backend/sample/src/main/java/com/dji/sample/media/controller/FileController.java
  17. 12 0
      Backend/sample/src/main/java/com/dji/sample/media/dao/IOssFileMapper.java
  18. 41 0
      Backend/sample/src/main/java/com/dji/sample/media/model/OssFileEntity.java
  19. 25 0
      Backend/sample/src/main/java/com/dji/sample/media/model/UploadResultDTO.java
  20. 3 0
      Backend/sample/src/main/java/com/dji/sample/media/service/IFileService.java
  21. 27 0
      Backend/sample/src/main/java/com/dji/sample/media/service/impl/FileServiceImpl.java
  22. 1 0
      Backend/sample/src/main/resources/application-test.yml
  23. 24 1
      Backend/sample/src/main/resources/application.yml

+ 6 - 0
Backend/sample/pom.xml

@@ -206,6 +206,12 @@
             <artifactId>transmittable-thread-local</artifactId>
             <version>2.14.5</version>
         </dependency>
+        <!-- JavaMail 依赖 -->
+        <dependency>
+            <groupId>com.sun.mail</groupId>
+            <artifactId>javax.mail</artifactId>
+            <version>1.6.2</version> <!-- 请使用最新版本 -->
+        </dependency>
     </dependencies>
 
     <build>

+ 109 - 0
Backend/sample/src/main/java/com/dji/sample/common/util/EmailUtil.java

@@ -0,0 +1,109 @@
+package com.dji.sample.common.util;
+
+import cn.hutool.core.util.StrUtil;
+import cn.hutool.extra.mail.MailAccount;
+import cn.hutool.extra.mail.MailUtil;
+import com.dji.sample.configuration.MailConfiguration;
+import com.dji.sample.manage.model.entity.DeviceLogsEntity;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @description:发送邮件
+ */
+@Slf4j
+@Component
+public class EmailUtil {
+
+    public static void sendHtmlDj(String url , String fjurl,String jcUrl, DeviceLogsEntity contnet) {
+        MailAccount mailAccount = createAccount();
+        // 编写 HTML 内容
+        String htmlContent = createContent(url,fjurl,jcUrl,contnet);
+        MailUtil.send(mailAccount,"243151224@qq.com","设备异常反馈",htmlContent,true,null);
+    }
+
+    private static MailAccount createAccount(){
+        MailAccount mailAccount = new MailAccount();
+//        mailAccount.setHost(MailConfiguration.host);
+//        mailAccount.setUser(MailConfiguration.user);
+//        mailAccount.setPass(MailConfiguration.pass);
+//        mailAccount.setSslEnable(MailConfiguration.sslEnable);
+//        mailAccount.setPort(MailConfiguration.port);
+//        mailAccount.setAuth(MailConfiguration.auth);
+//        mailAccount.setFrom(MailConfiguration.from);
+//        mailAccount.setStarttlsEnable(MailConfiguration.starttlsEnable);
+//        mailAccount.setTimeout(MailConfiguration.timeout);
+//        mailAccount.setConnectionTimeout(MailConfiguration.connectionTimeout);
+
+        mailAccount.setHost("smtp.exmail.qq.com");
+        mailAccount.setUser("takai@takai-china.com");
+        mailAccount.setPass("T@kai2021");
+        mailAccount.setSslEnable(true);
+        mailAccount.setPort(465);
+        mailAccount.setAuth(true);
+        mailAccount.setFrom("takai@takai-china.com");
+        mailAccount.setStarttlsEnable(true);
+        mailAccount.setTimeout(0);
+        mailAccount.setConnectionTimeout(0);
+        return mailAccount;
+    }
+
+    private static String createContent(String ossurl, String fjurl,String jcUrl,DeviceLogsEntity  content){
+        // 处理 URL 并拼接成 HTML
+        List<String> urls = new ArrayList<>();
+
+        if (!StrUtil.isBlank(ossurl)) {
+            urls.add("附件");
+            urls.addAll(StrUtil.split(ossurl, ','));
+        }
+        if (!StrUtil.isBlank(jcUrl)) {
+            urls.add("机场日志");
+            urls.addAll(StrUtil.split(jcUrl, ','));
+        }
+        if (!StrUtil.isBlank(fjurl)) {
+            urls.add("飞行器日志");
+            urls.addAll(StrUtil.split(fjurl, ','));
+        }
+
+
+        StringBuilder htmlContent = new StringBuilder("<html><body>");
+        htmlContent.append("<h1>无人机异常邮件</h1>")
+                .append("<p>异常描述:"+content.getLogsInfo()+"</p>")
+                .append("<p>发生时间:"+content.getHappenTime()+"</p>")
+                .append("<p>联系电话:"+content.getContactNumber()+"</p>")
+                .append("<p>联系邮箱:"+content.getContactEmail()+"</p>")
+                .append("<ul>");
+        for (int i = 0; i < urls.size(); i++) {
+            String url = urls.get(i);
+            if (StrUtil.isNotBlank(url)) {
+                htmlContent.append("<li>")
+                        .append(url)
+                        .append("</li>");
+                if (i < urls.size() - 1) {
+                    htmlContent.append("<br>"); // 添加换行
+                }
+            }
+        }
+        htmlContent.append("</ul>")
+                .append("</body></html>");
+        return htmlContent.toString();
+    }
+
+    public static void main(String[] args) {
+        String url = "www.baidu.com,www.baidu.com,www.baidu.com,www.baidu.com";
+        String fjurl = "www.baidu.com,www.baidu.com,www.baidu.com";
+        String jcurl = "www.baidu.com,www.baidu.com,www.baidu.com";
+        DeviceLogsEntity deviceLogsEntity = new DeviceLogsEntity();
+        deviceLogsEntity.setContactEmail("1111");
+        deviceLogsEntity.setContactNumber("1222");
+        deviceLogsEntity.setHappenTime(Long.parseLong("10"));
+        deviceLogsEntity.setLogsInfo("测试");
+        sendHtmlDj(url,fjurl,jcurl,deviceLogsEntity);
+    }
+
+
+}

+ 6 - 0
Backend/sample/src/main/java/com/dji/sample/component/oss/model/OssConfiguration.java

@@ -42,6 +42,8 @@ public class OssConfiguration {
 
     public static String bucket;
 
+    public static String bucketLogs;
+
     public static String objectDirPrefix;
 
     public void setProvider(OssTypeEnum provider) {
@@ -87,6 +89,10 @@ public class OssConfiguration {
     public void setObjectDirPrefix(String objectDirPrefix) {
         OssConfiguration.objectDirPrefix = objectDirPrefix;
     }
+
+    public void setBucketLogs(String bucketLogs) {
+        OssConfiguration.bucketLogs = bucketLogs;
+    }
 }
 
 

+ 95 - 0
Backend/sample/src/main/java/com/dji/sample/configuration/MailConfiguration.java

@@ -0,0 +1,95 @@
+package com.dji.sample.configuration;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+/**
+ * @author hqjiang
+ * @version 0.1
+ * @date 2024/9/11
+ */
+@ConfigurationProperties(prefix = "mail")
+@Component
+public class MailConfiguration {
+
+    public String enabled;
+
+    public static String host;
+
+
+    public static Integer port;
+
+    public void setEnabled(String enabled) {
+        this.enabled = enabled;
+    }
+
+    public static void setHost(String host) {
+        MailConfiguration.host = host;
+    }
+
+    public static void setPort(Integer port) {
+        MailConfiguration.port = port;
+    }
+
+    public static void setAuth(Boolean auth) {
+        MailConfiguration.auth = auth;
+    }
+
+    public static void setFrom(String from) {
+        MailConfiguration.from = from;
+    }
+
+    public static void setUser(String user) {
+        MailConfiguration.user = user;
+    }
+
+    public static void setPass(String pass) {
+        MailConfiguration.pass = pass;
+    }
+
+    public static void setStarttlsEnable(Boolean starttlsEnable) {
+        MailConfiguration.starttlsEnable = starttlsEnable;
+    }
+
+    public static void setSslEnable(Boolean sslEnable) {
+        MailConfiguration.sslEnable = sslEnable;
+    }
+
+    public static void setTimeout(long timeout) {
+        MailConfiguration.timeout = timeout;
+    }
+
+    public static void setConnectionTimeout(long connectionTimeout) {
+        MailConfiguration.connectionTimeout = connectionTimeout;
+    }
+
+    public static Boolean auth;
+
+
+    public static String from;
+
+
+    public static String user;
+
+
+    public static String pass;
+
+
+    public static Boolean starttlsEnable;
+
+
+    public static Boolean sslEnable;
+
+
+    public static long timeout;
+
+
+    public static long connectionTimeout;
+
+
+
+
+}
+
+
+

+ 32 - 3
Backend/sample/src/main/java/com/dji/sample/manage/controller/DeviceLogsController.java

@@ -2,9 +2,9 @@ package com.dji.sample.manage.controller;
 
 import com.dji.sample.common.model.CustomClaim;
 import com.dji.sample.manage.model.dto.DeviceLogsDTO;
-import com.dji.sample.manage.model.param.DeviceLogsCreateParam;
-import com.dji.sample.manage.model.param.DeviceLogsGetParam;
-import com.dji.sample.manage.model.param.DeviceLogsQueryParam;
+import com.dji.sample.manage.model.dto.DeviceLogsDetailRespDTO;
+import com.dji.sample.manage.model.dto.DeviceLogsRespDTO;
+import com.dji.sample.manage.model.param.*;
 import com.dji.sample.manage.service.IDeviceLogsService;
 import com.dji.sdk.cloudapi.log.FileUploadUpdateRequest;
 import com.dji.sdk.common.HttpResultResponse;
@@ -15,6 +15,7 @@ import org.springframework.web.bind.annotation.*;
 
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
+import javax.validation.constraints.NotNull;
 import java.net.URL;
 
 import static com.dji.sample.component.AuthInterceptor.TOKEN_CLAIM;
@@ -119,4 +120,32 @@ public class DeviceLogsController {
         }
         return HttpResultResponse.error("Failed to get the logs file download address.");
     }
+
+    /**
+     * Initiate a log upload request to the gateway.
+     * @return
+     */
+    @PostMapping("/{workspace_id}/devices/{device_sn}/createLogs")
+    public HttpResultResponse createLogs(@PathVariable("workspace_id") String workspaceId,
+                                         @PathVariable("device_sn") String deviceSn,
+                                         HttpServletRequest request, @RequestBody DeviceLogsParam param) {
+
+        CustomClaim customClaim = (CustomClaim)request.getAttribute(TOKEN_CLAIM);
+
+        return deviceLogsService.createLogs(customClaim.getUsername(), deviceSn, param);
+    }
+
+    @GetMapping("/{workspace_id}/devices/logsList")
+    public HttpResultResponse getLogsList(ManagerLogsQueryParam param, @PathVariable("workspace_id") String workspaceId
+                                              ) {
+        PaginationData<DeviceLogsRespDTO> data = deviceLogsService.getLogsList(param);
+        return HttpResultResponse.success(data);
+    }
+
+    @GetMapping("/{workspace_id}/devices/logsDetail")
+    public HttpResultResponse getLogsDetail(@NotNull String logsId
+                                            ) {
+        DeviceLogsDetailRespDTO data = deviceLogsService.getLogsDetail(logsId);
+        return HttpResultResponse.success(data);
+    }
 }

+ 6 - 0
Backend/sample/src/main/java/com/dji/sample/manage/model/dto/DeviceLogsDTO.java

@@ -38,4 +38,10 @@ public class DeviceLogsDTO {
 
     private LogsFileUploadListDTO deviceLogs;
 
+    private String contactEmail;
+
+    private String contactNumber;
+
+    private String ossIds;
+
 }

+ 42 - 0
Backend/sample/src/main/java/com/dji/sample/manage/model/dto/DeviceLogsDetailRespDTO.java

@@ -0,0 +1,42 @@
+package com.dji.sample.manage.model.dto;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.time.LocalDateTime;
+import java.util.List;
+
+/**
+ * @author huiqing.jiang
+ * @version 1.2
+ * @date 2024/9/11
+ */
+@Data
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+public class DeviceLogsDetailRespDTO {
+
+    private String logsId;
+
+    private Long happenTime;
+
+    private String userName;
+
+    private String logsInfo;
+
+    private Long createTime;
+
+    private Integer status;
+
+    private String contactEmail;
+
+    private String contactNumber;
+
+    private List<String> ossUrls;
+
+    private List<LogsFileUploadDTO> list;
+
+}

+ 49 - 0
Backend/sample/src/main/java/com/dji/sample/manage/model/dto/DeviceLogsRespDTO.java

@@ -0,0 +1,49 @@
+package com.dji.sample.manage.model.dto;
+
+import com.dji.sdk.cloudapi.tsa.TopologyList;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.time.LocalDateTime;
+import java.util.List;
+
+/**
+ * @author huiqing.jiang
+ * @version 1.2
+ * @date 2024/9/11
+ */
+@Data
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+public class DeviceLogsRespDTO {
+
+    private String logsId;
+
+    private LocalDateTime happenTime;
+
+    private String userName;
+
+    private String logsInfo;
+
+    private LocalDateTime createTime;
+
+    private Integer status;
+
+    private String contactEmail;
+
+    private String contactNumber;
+
+    private String ossIds;
+
+    private String deviceSn;
+
+    private String deviceName;
+
+    private String nickName;
+
+    private String firmwareVersion;
+
+}

+ 69 - 0
Backend/sample/src/main/java/com/dji/sample/manage/model/dto/FileUploadFile.java

@@ -0,0 +1,69 @@
+package com.dji.sample.manage.model.dto;
+
+import com.dji.sdk.cloudapi.log.LogModuleEnum;
+import java.util.List;
+
+/**
+ * @author huiqing.jiang
+ * @version 1.2
+ * @date 2024/9/10
+ */
+public class FileUploadFile {
+
+    private String deviceSn;
+
+    private List<LogFileIndexDTO> list;
+
+    private LogModuleEnum module;
+
+    private String objectKey;
+
+    public FileUploadFile() {
+    }
+
+    @Override
+    public String toString() {
+        return "FileUploadStartFile{" +
+                "deviceSn='" + deviceSn + '\'' +
+                ", list=" + list +
+                ", module=" + module +
+                ", objectKey='" + objectKey + '\'' +
+                '}';
+    }
+
+    public String getDeviceSn() {
+        return deviceSn;
+    }
+
+    public FileUploadFile setDeviceSn(String deviceSn) {
+        this.deviceSn = deviceSn;
+        return this;
+    }
+
+    public List<LogFileIndexDTO> getList() {
+        return list;
+    }
+
+    public FileUploadFile setList(List<LogFileIndexDTO> list) {
+        this.list = list;
+        return this;
+    }
+
+    public LogModuleEnum getModule() {
+        return module;
+    }
+
+    public FileUploadFile setModule(LogModuleEnum module) {
+        this.module = module;
+        return this;
+    }
+
+    public String getObjectKey() {
+        return objectKey;
+    }
+
+    public FileUploadFile setObjectKey(String objectKey) {
+        this.objectKey = objectKey;
+        return this;
+    }
+}

+ 68 - 0
Backend/sample/src/main/java/com/dji/sample/manage/model/dto/LogFileIndexDTO.java

@@ -0,0 +1,68 @@
+package com.dji.sample.manage.model.dto;
+
+import javax.validation.constraints.NotNull;
+
+/**
+ * @author sean
+ * @version 1.2
+ * @date 2022/9/7
+ */
+public class LogFileIndexDTO {
+
+    private Integer bootIndex;
+
+    private Long endTime;
+
+    private Long startTime;
+
+    private Long size;
+
+    public LogFileIndexDTO() {
+    }
+
+    @Override
+    public String toString() {
+        return "LogFileIndexDTO{" +
+                "bootIndex=" + bootIndex +
+                ", endTime=" + endTime +
+                ", startTime=" + startTime +
+                ", size=" + size +
+                '}';
+    }
+
+    public Integer getBootIndex() {
+        return bootIndex;
+    }
+
+    public LogFileIndexDTO setBootIndex(Integer bootIndex) {
+        this.bootIndex = bootIndex;
+        return this;
+    }
+
+    public Long getEndTime() {
+        return endTime;
+    }
+
+    public LogFileIndexDTO setEndTime(Long endTime) {
+        this.endTime = endTime;
+        return this;
+    }
+
+    public Long getStartTime() {
+        return startTime;
+    }
+
+    public LogFileIndexDTO setStartTime(Long startTime) {
+        this.startTime = startTime;
+        return this;
+    }
+
+    public Long getSize() {
+        return size;
+    }
+
+    public LogFileIndexDTO setSize(Long size) {
+        this.size = size;
+        return this;
+    }
+}

+ 9 - 0
Backend/sample/src/main/java/com/dji/sample/manage/model/entity/DeviceLogsEntity.java

@@ -49,4 +49,13 @@ public class DeviceLogsEntity implements Serializable {
     @TableField(value = "update_time", fill = FieldFill.INSERT_UPDATE)
     private Long updateTime;
 
+    @TableField("contact_number")
+    private String contactNumber;
+
+    @TableField("contact_email")
+    private String contactEmail;
+
+    @TableField("oss_ids")
+    private String ossIds;
+
 }

+ 29 - 0
Backend/sample/src/main/java/com/dji/sample/manage/model/param/DeviceLogsParam.java

@@ -0,0 +1,29 @@
+package com.dji.sample.manage.model.param;
+
+import com.dji.sample.manage.model.dto.FileUploadFile;
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * @author huiqing.jiang
+ * @version 1.2
+ * @date 2024/9/10
+ */
+@Data
+public class DeviceLogsParam {
+
+    private String logsInfo;
+
+    private Long happenTime;
+
+    private String status;
+
+    private String contactEmail;
+
+    private String contactNumber;
+
+    private String ossIds;
+
+    private List<FileUploadFile> list;
+}

+ 31 - 0
Backend/sample/src/main/java/com/dji/sample/manage/model/param/ManagerLogsQueryParam.java

@@ -0,0 +1,31 @@
+package com.dji.sample.manage.model.param;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+
+/**
+ * @author huiqing.jiang
+ * @version 1.2
+ * @date 2024/9/11
+ */
+@Data
+public class ManagerLogsQueryParam {
+
+    private Long page;
+
+    @JsonProperty("page_size")
+    private Long pageSize;
+
+    private Integer status;
+
+    @JsonProperty("begin_time")
+    private Long beginTime;
+
+    @JsonProperty("end_time")
+    private Long endTime;
+
+    @JsonProperty("search_info")
+    private String searchInfo;
+
+    private String username;
+}

+ 10 - 0
Backend/sample/src/main/java/com/dji/sample/manage/service/IDeviceLogsService.java

@@ -1,8 +1,12 @@
 package com.dji.sample.manage.service;
 
 import com.dji.sample.manage.model.dto.DeviceLogsDTO;
+import com.dji.sample.manage.model.dto.DeviceLogsDetailRespDTO;
+import com.dji.sample.manage.model.dto.DeviceLogsRespDTO;
 import com.dji.sample.manage.model.param.DeviceLogsCreateParam;
+import com.dji.sample.manage.model.param.DeviceLogsParam;
 import com.dji.sample.manage.model.param.DeviceLogsQueryParam;
+import com.dji.sample.manage.model.param.ManagerLogsQueryParam;
 import com.dji.sdk.cloudapi.log.FileUploadUpdateRequest;
 import com.dji.sdk.cloudapi.log.LogModuleEnum;
 import com.dji.sdk.common.HttpResultResponse;
@@ -83,4 +87,10 @@ public interface IDeviceLogsService {
      * @return
      */
     URL getLogsFileUrl(String logsId, String fileId);
+
+    HttpResultResponse createLogs(String username, String deviceSn, DeviceLogsParam param);
+
+    PaginationData<DeviceLogsRespDTO> getLogsList(ManagerLogsQueryParam param);
+
+    DeviceLogsDetailRespDTO getLogsDetail(String logsId);
 }

+ 196 - 4
Backend/sample/src/main/java/com/dji/sample/manage/service/impl/DeviceLogsServiceImpl.java

@@ -1,9 +1,14 @@
 package com.dji.sample.manage.service.impl;
 
+import cn.hutool.extra.mail.MailUtil;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.dji.sample.common.util.EmailUtil;
 import com.dji.sample.component.mqtt.model.EventsReceiver;
+import com.dji.sample.component.oss.model.OssConfiguration;
+import com.dji.sample.component.oss.service.IOssService;
+import com.dji.sample.component.oss.service.impl.OssServiceContext;
 import com.dji.sample.component.redis.RedisConst;
 import com.dji.sample.component.redis.RedisOpsUtils;
 import com.dji.sample.component.websocket.model.BizCodeEnum;
@@ -14,11 +19,13 @@ import com.dji.sample.manage.model.entity.DeviceLogsEntity;
 import com.dji.sample.manage.model.enums.DeviceLogsStatusEnum;
 import com.dji.sample.manage.model.enums.UserTypeEnum;
 import com.dji.sample.manage.model.param.DeviceLogsCreateParam;
+import com.dji.sample.manage.model.param.DeviceLogsParam;
 import com.dji.sample.manage.model.param.DeviceLogsQueryParam;
-import com.dji.sample.manage.service.IDeviceLogsService;
-import com.dji.sample.manage.service.IDeviceRedisService;
-import com.dji.sample.manage.service.ILogsFileService;
-import com.dji.sample.manage.service.ITopologyService;
+import com.dji.sample.manage.model.param.ManagerLogsQueryParam;
+import com.dji.sample.manage.service.*;
+import com.dji.sample.media.dao.IOssFileMapper;
+import com.dji.sample.media.model.MediaFileEntity;
+import com.dji.sample.media.model.OssFileEntity;
 import com.dji.sample.storage.service.IStorageService;
 import com.dji.sdk.cloudapi.log.*;
 import com.dji.sdk.cloudapi.log.api.AbstractLogService;
@@ -85,6 +92,15 @@ public class DeviceLogsServiceImpl extends AbstractLogService implements IDevice
     @Autowired
     private AbstractLogService abstractLogService;
 
+    @Autowired
+    private OssServiceContext ossService;
+
+    @Autowired
+    private IOssFileMapper ossFileMapper;
+
+    @Autowired
+    private IDeviceService deviceService;
+
     @Override
     public PaginationData<DeviceLogsDTO> getUploadedLogs(String deviceSn, DeviceLogsQueryParam param) {
         LambdaQueryWrapper<DeviceLogsEntity> queryWrapper = new LambdaQueryWrapper<DeviceLogsEntity>()
@@ -148,6 +164,7 @@ public class DeviceLogsServiceImpl extends AbstractLogService implements IDevice
     @Override
     public HttpResultResponse pushFileUpload(String username, String deviceSn, DeviceLogsCreateParam param) {
         StsCredentialsResponse stsCredentials = storageService.getSTSCredentials();
+        stsCredentials.setBucket(OssConfiguration.bucketLogs);
         stsCredentials.getCredentials().setExpire(System.currentTimeMillis() + (stsCredentials.getCredentials().getExpire() - 60) * 1000);
         LogsUploadCredentialsDTO credentialsDTO = new LogsUploadCredentialsDTO(stsCredentials);
         // Set the storage name of the file.
@@ -288,6 +305,137 @@ public class DeviceLogsServiceImpl extends AbstractLogService implements IDevice
         return logsFileService.getLogsFileUrl(logsId, fileId);
     }
 
+    @Override
+    public HttpResultResponse createLogs(String username, String deviceSn, DeviceLogsParam param) {
+
+        String jcUrl = null;
+        String fjUrl = null;
+        String ossUrls = null;
+        DeviceLogsEntity entity = DeviceLogsEntity.builder()
+                .deviceSn(deviceSn)
+                .username(username)
+                .happenTime(param.getHappenTime())
+                .logsInfo(Objects.requireNonNullElse(param.getLogsInfo(), ""))
+                .logsId(UUID.randomUUID().toString())
+                .contactEmail(Objects.requireNonNullElse(param.getContactEmail(), ""))
+                .contactNumber(Objects.requireNonNullElse(param.getContactNumber(), ""))
+                .ossIds(Objects.requireNonNullElse(param.getOssIds(), ""))
+                .status(DeviceLogsStatusEnum.UPLOADING.getVal())
+                .build();
+        mapper.insert(entity);
+        if(param.getList().size() > 0) {
+            StsCredentialsResponse stsCredentials = storageService.getSTSCredentials();
+            stsCredentials.setBucket(OssConfiguration.bucketLogs);
+            stsCredentials.getCredentials().setExpire(System.currentTimeMillis() + (stsCredentials.getCredentials().getExpire() - 60) * 1000);
+            LogsUploadCredentialsDTO credentialsDTO = new LogsUploadCredentialsDTO(stsCredentials);
+            // Set the storage name of the file.
+            List<FileUploadStartFile> files = paramToFiles(param.getList(),deviceSn);
+            files.forEach(file -> file.setObjectKey(credentialsDTO.getObjectKeyPrefix() + "/" + UUID.randomUUID().toString() + LOGS_FILE_SUFFIX));
+
+            credentialsDTO.setParams(new FileUploadStartParam().setFiles(files));
+
+            TopicServicesResponse<ServicesReplyData> response = abstractLogService.fileuploadStart(
+                    SDKManager.getDeviceSDK(deviceSn), new FileUploadStartRequest()
+                            .setCredentials(stsCredentials.getCredentials())
+                            .setBucket(stsCredentials.getBucket())
+                            .setEndpoint(stsCredentials.getEndpoint())
+                            .setFileStoreDir(stsCredentials.getObjectKeyPrefix())
+                            .setProvider(stsCredentials.getProvider())
+                            .setRegion(stsCredentials.getRegion())
+                            .setParams(new FileUploadStartParam().setFiles(files)));
+
+            if (!response.getData().getResult().isSuccess()) {
+                return HttpResultResponse.error(response.getData().getResult());
+            }
+
+            for (FileUploadStartFile file : files) {
+                String url = ossService.getObjectUrl(OssConfiguration.bucketLogs, file.getObjectKey()).toString();
+                if(file.getModule().getDomain().equals("0")) {
+                    if (fjUrl == null) {
+                        fjUrl = url;
+                    } else  {
+                        fjUrl = fjUrl + "," + url;
+                    }
+                } else {
+                    if (jcUrl == null) {
+                        jcUrl = url;
+                    } else  {
+                        jcUrl = jcUrl + "," + url;
+                    }
+                }
+
+                logsFileService.insertFile(file, entity.getLogsId());
+            }
+
+            // Save the status of the log upload.
+            RedisOpsUtils.hashSet(RedisConst.LOGS_FILE_PREFIX + deviceSn, response.getBid(), LogsOutputProgressDTO.builder().logsId(response.getBid()).build());
+        }
+        if(param.getOssIds() != null) {
+            String[] ids = param.getOssIds().split(",");
+            for(String id : ids) {
+                OssFileEntity ossFileEntity = ossFileMapper.selectById(id);
+                if(ossFileEntity != null) {
+                    if( ossUrls == null) {
+                        ossUrls = ossFileEntity.getUrl();
+                    } else {
+                        ossUrls = ossUrls + "," + ossFileEntity.getUrl();
+                    }
+                }
+            }
+        }
+        EmailUtil.sendHtmlDj(ossUrls,fjUrl,jcUrl,entity);
+        return HttpResultResponse.success();
+
+    }
+
+    @Override
+    public PaginationData<DeviceLogsRespDTO> getLogsList(ManagerLogsQueryParam param) {
+        LambdaQueryWrapper<DeviceLogsEntity> queryWrapper = new LambdaQueryWrapper<DeviceLogsEntity>()
+                .between(Objects.nonNull(param.getBeginTime()) && Objects.nonNull(param.getEndTime()),
+                        DeviceLogsEntity::getCreateTime, param.getBeginTime(), param.getEndTime())
+                .eq(Objects.nonNull(param.getStatus()), DeviceLogsEntity::getStatus, param.getStatus())
+                .eq(Objects.nonNull(param.getUsername()), DeviceLogsEntity::getUsername, param.getUsername())
+                .eq(Objects.nonNull(param.getStatus()), DeviceLogsEntity::getStatus, param.getStatus())
+                .and(StringUtils.hasText(param.getSearchInfo()),
+                        wrapper -> wrapper.like( DeviceLogsEntity::getDeviceSn, param.getSearchInfo())
+                                .or().like( DeviceLogsEntity::getLogsInfo, param.getSearchInfo())
+                )
+                .orderByDesc(DeviceLogsEntity::getCreateTime);
+
+        Page<DeviceLogsEntity> pagination = mapper.selectPage(new Page<>(param.getPage(), param.getPageSize()), queryWrapper);
+
+        List<DeviceLogsRespDTO> deviceLogsList = pagination.getRecords().stream().map(this::entity2RespDto).collect(Collectors.toList());
+
+        return new PaginationData<DeviceLogsRespDTO>(deviceLogsList, new Pagination(pagination.getCurrent(), pagination.getSize(), pagination.getTotal()));
+    }
+
+    @Override
+    public DeviceLogsDetailRespDTO getLogsDetail(String logsId) {
+        DeviceLogsDetailRespDTO deviceLogsDetailRespDTO = new DeviceLogsDetailRespDTO();
+        LambdaQueryWrapper<DeviceLogsEntity> queryWrapper = new LambdaQueryWrapper<DeviceLogsEntity>();
+        queryWrapper.eq(DeviceLogsEntity::getLogsId,logsId);
+        DeviceLogsEntity  deviceLogsEntity = mapper.selectOne(queryWrapper);
+        if(deviceLogsEntity != null) {
+            deviceLogsDetailRespDTO.setLogsInfo(deviceLogsEntity.getLogsInfo());
+            deviceLogsDetailRespDTO.setContactEmail(deviceLogsEntity.getContactEmail());
+            deviceLogsDetailRespDTO.setContactNumber(deviceLogsEntity.getContactNumber());
+            deviceLogsDetailRespDTO.setHappenTime(deviceLogsEntity.getHappenTime());
+            if(deviceLogsEntity.getOssIds() != null) {
+                List<String> urlList = new ArrayList<>();
+                String[] ossIds = deviceLogsEntity.getOssIds().split(",");
+                for (String ossId : ossIds) {
+                    OssFileEntity ossFileEntity = ossFileMapper.selectById(ossId);
+                    urlList.add(ossFileEntity.getUrl());
+                }
+                deviceLogsDetailRespDTO.setOssUrls(urlList);
+            }
+            List<LogsFileUploadDTO> logFileIndexList = logsFileService.getLogsFileByLogsId(logsId);
+            deviceLogsDetailRespDTO.setList(logFileIndexList);
+
+        }
+        return deviceLogsDetailRespDTO;
+    }
+
     private DeviceLogsDTO entity2Dto(DeviceLogsEntity entity) {
         if (Objects.isNull(entity)) {
             return null;
@@ -311,4 +459,48 @@ public class DeviceLogsServiceImpl extends AbstractLogService implements IDevice
                 .deviceTopo(topologyService.getDeviceTopologyByGatewaySn(entity.getDeviceSn()).orElse(null))
                 .build();
     }
+
+    private List<FileUploadStartFile> paramToFiles(List<FileUploadFile> list,String deviceSn) {
+        List<FileUploadStartFile> result = new ArrayList<>();
+        for(FileUploadFile fileUploadFile : list) {
+            FileUploadStartFile fileUploadStartFile = new FileUploadStartFile();
+            List<LogFileIndex> fileIndexList = new ArrayList<>();
+            List<LogFileIndexDTO> dtoList = fileUploadFile.getList();
+            fileUploadStartFile.setDeviceSn(deviceSn);
+            fileUploadStartFile.setModule(fileUploadFile.getModule());
+            for (LogFileIndexDTO dto : dtoList) {
+                LogFileIndex logFileIndex = new LogFileIndex();
+                logFileIndex.setBootIndex(dto.getBootIndex());
+                logFileIndex.setSize(dto.getSize());
+                logFileIndex.setEndTime(dto.getEndTime());
+                logFileIndex.setStartTime(dto.getStartTime());
+                fileIndexList.add(logFileIndex);
+            }
+            fileUploadStartFile.setList(fileIndexList);
+            result.add(fileUploadStartFile);
+        }
+        return result;
+    }
+
+    private DeviceLogsRespDTO entity2RespDto(DeviceLogsEntity entity) {
+        if (Objects.isNull(entity)) {
+            return null;
+        }
+        Optional<DeviceDTO> deviceDTO = deviceService.getDeviceBySn(entity.getDeviceSn());
+
+        return DeviceLogsRespDTO.builder()
+                .logsId(entity.getLogsId())
+                .createTime(LocalDateTime.ofInstant(Instant.ofEpochMilli(entity.getCreateTime()), ZoneId.systemDefault()))
+                .happenTime(Objects.isNull(entity.getHappenTime()) ?
+                        null : LocalDateTime.ofInstant(Instant.ofEpochMilli(entity.getHappenTime()), ZoneId.systemDefault()))
+                .status(entity.getStatus())
+                .logsInfo(entity.getLogsInfo())
+                .userName(entity.getUsername())
+                .deviceSn(entity.getDeviceSn())
+                .deviceName(Objects.isNull(deviceDTO.get()) ? null : deviceDTO.get().getDeviceName())
+                .nickName(Objects.isNull(deviceDTO.get()) ? null : deviceDTO.get().getNickname())
+                .firmwareVersion(Objects.isNull(deviceDTO.get()) ? null : deviceDTO.get().getFirmwareVersion())
+                .build();
+    }
+
 }

+ 20 - 0
Backend/sample/src/main/java/com/dji/sample/media/controller/FileController.java

@@ -7,6 +7,7 @@ import com.dji.sample.map.model.param.MediaDirQueryParam;
 import com.dji.sample.map.model.param.MediaFileQueryParam;
 import com.dji.sample.media.model.MediaDirDTO;
 import com.dji.sample.media.model.MediaFileDTO;
+import com.dji.sample.media.model.UploadResultDTO;
 import com.dji.sample.media.service.IFileService;
 import com.dji.sample.media.service.IMediaDirService;
 import com.dji.sdk.cloudapi.map.CreateMapElementRequest;
@@ -146,6 +147,25 @@ public class FileController {
         return HttpResultResponse.success();
     }
 
+    /**
+     * 上传文件
+     * @param file
+     * @return
+     */
+    @PostMapping("/{workspace_id}/file/upload")
+    public HttpResultResponse uploadFile(HttpServletRequest request, MultipartFile file) {
+        if (Objects.isNull(file)) {
+            return HttpResultResponse.error("没有文件信息");
+        }
+        CustomClaim customClaim = (CustomClaim)request.getAttribute(TOKEN_CLAIM);
+        String creator = customClaim.getUsername();
+        UploadResultDTO resultDTO = fileService.uploadFile(file,creator);
+        if(resultDTO == null) {
+            return HttpResultResponse.error("上传失败");
+        }
+        return HttpResultResponse.success(resultDTO);
+    }
+
     @GetMapping("/{workspace_id}/fileDownList")
     public void getFileStreamListByDirs(@PathVariable(name = "workspace_id") String workspaceId,
                                   @NotNull @Size(min = 1) @RequestParam(name = "id") List<String> ids,

+ 12 - 0
Backend/sample/src/main/java/com/dji/sample/media/dao/IOssFileMapper.java

@@ -0,0 +1,12 @@
+package com.dji.sample.media.dao;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.dji.sample.media.model.OssFileEntity;
+
+/**
+ * @author hqjiang
+ * @version 1.0
+ * @date 2024/9/10
+ */
+public interface IOssFileMapper extends BaseMapper<OssFileEntity> {
+}

+ 41 - 0
Backend/sample/src/main/java/com/dji/sample/media/model/OssFileEntity.java

@@ -0,0 +1,41 @@
+package com.dji.sample.media.model;
+
+import com.baomidou.mybatisplus.annotation.*;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+
+/**
+ * @author hqjiang
+ * @version 1.0
+ * @date 2024/7/2
+ */
+@TableName(value = "oss_file")
+@Data
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+public class OssFileEntity implements Serializable {
+
+    @TableId(type = IdType.AUTO)
+    private Integer id;
+
+    @TableField("object_key")
+    private String objectKey;
+
+    @TableField("url")
+    private String url;
+
+    @TableField(value = "create_time", fill = FieldFill.INSERT)
+    private Long createTime;
+
+    @TableField(value = "update_time", fill = FieldFill.INSERT_UPDATE)
+    private Long updateTime;
+
+    @TableField("username")
+    private String username;
+}
+

+ 25 - 0
Backend/sample/src/main/java/com/dji/sample/media/model/UploadResultDTO.java

@@ -0,0 +1,25 @@
+package com.dji.sample.media.model;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * @author huiqing.jiang
+ * @version 0.2
+ * @date 2024/9/10
+ */
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class UploadResultDTO {
+
+    private Integer id;
+
+    private String url;
+
+    private String objectKey;
+
+}

+ 3 - 0
Backend/sample/src/main/java/com/dji/sample/media/service/IFileService.java

@@ -3,6 +3,7 @@ package com.dji.sample.media.service;
 import com.dji.sample.map.model.param.MediaFileQueryParam;
 import com.dji.sample.media.model.MediaFileDTO;
 import com.dji.sample.media.model.MediaFileEntity;
+import com.dji.sample.media.model.UploadResultDTO;
 import com.dji.sample.media.model.UpstreamMediaFileDTO;
 import com.dji.sdk.cloudapi.map.ElementPicture;
 import com.dji.sdk.cloudapi.media.MediaUploadCallbackRequest;
@@ -108,4 +109,6 @@ public interface IFileService {
     boolean deleteMediaElement(String workspaceId, MediaFileDTO mediaFileDTO);
 
     PaginationData<UpstreamMediaFileDTO> getMediaFilesPagination(String workspaceName, Long startTime, Long endTime, long page, long pageSize);
+
+    UploadResultDTO uploadFile(MultipartFile file,String creator);
 }

+ 27 - 0
Backend/sample/src/main/java/com/dji/sample/media/service/impl/FileServiceImpl.java

@@ -16,6 +16,7 @@ import com.dji.sample.map.service.IGroupElementService;
 import com.dji.sample.map.service.IGroupService;
 import com.dji.sample.media.dao.IFileMapper;
 import com.dji.sample.media.dao.IFileSumMapper;
+import com.dji.sample.media.dao.IOssFileMapper;
 import com.dji.sample.media.model.*;
 import com.dji.sample.media.service.IFileService;
 import com.dji.sample.media.service.IMediaDirService;
@@ -72,6 +73,9 @@ public class FileServiceImpl implements IFileService {
     @Autowired
     private IFileSumMapper sumMapper;
 
+    @Autowired
+    private IOssFileMapper ossFileMapper;
+
     @Autowired
     private IDeviceDictionaryService deviceDictionaryService;
 
@@ -852,4 +856,27 @@ public class FileServiceImpl implements IFileService {
         return new PaginationData<UpstreamMediaFileDTO>(respData, new Pagination(page, pageSize, total));
     }
 
+    @Override
+    public UploadResultDTO uploadFile(MultipartFile file,String creator) {
+        try (InputStream is = file.getInputStream()) {
+            UploadResultDTO dto = new UploadResultDTO();
+            String objectKey = OssConfiguration.objectDirPrefix + File.separator + file.getOriginalFilename();
+            ossService.putObject(OssConfiguration.bucket, objectKey, file.getInputStream());
+            log.info("上传成功. {}", file.getOriginalFilename());
+            String url = ossService.getObjectUrl(OssConfiguration.bucket, objectKey).toString();
+            OssFileEntity ossFileEntity = new OssFileEntity();
+            ossFileEntity.setUrl(url);
+            ossFileEntity.setObjectKey(objectKey);
+            ossFileEntity.setUsername(creator);
+            ossFileMapper.insert(ossFileEntity);
+            dto.setUrl(url);
+            dto.setObjectKey(objectKey);
+            dto.setId(ossFileEntity.getId());
+            return dto;
+        } catch (IOException e) {
+            e.printStackTrace();
+            return null;
+        }
+    }
+
 }

+ 1 - 0
Backend/sample/src/main/resources/application-test.yml

@@ -119,6 +119,7 @@ oss:
   access-key: admin
   secret-key: Qwer~123.
   bucket: dji-cloudapi
+  bucket-logs: log-files
   expire: 3600
   region: us-east-1
   object-dir-prefix: wayline

+ 24 - 1
Backend/sample/src/main/resources/application.yml

@@ -194,4 +194,27 @@ custom-config:
   #流媒体客户端ID
   clientId: e534550a85d94faba73e8040e76514bc
   #上级系统客户端ID
-  parentSysClientId: b06d1ac3fb244110a8c2b5f93f15170d
+  parentSysClientId: b06d1ac3fb244110a8c2b5f93f15170d
+
+
+--- # mail 邮件发送
+mail:
+  enabled: true
+  host: smtp.exmail.qq.com
+  port: 465
+  # 是否需要用户名密码验证
+  auth: true
+  # 发送方,遵循RFC-822标准
+  from: takai@takai-china.com
+  # 用户名(注意:如果使用foxmail邮箱,此处user为qq号)
+  user: takai@takai-china.com
+  # 密码(注意,某些邮箱需要为SMTP服务单独设置密码,详情查看相关帮助)
+  pass: T@kai2021
+  # 使用 STARTTLS安全连接,STARTTLS是对纯文本通信协议的扩展。
+  starttlsEnable: true
+  # 使用SSL安全连接
+  sslEnable: true
+  # SMTP超时时长,单位毫秒,缺省值不超时
+  timeout: 0
+  # Socket连接超时值,单位毫秒,缺省值不超时
+  connectionTimeout: 0