785834757 1 год назад
Родитель
Сommit
354b3834b7

+ 4 - 0
authentication/src/main/java/com/jzg/controller/AuthController.java

@@ -43,6 +43,10 @@ import java.util.List;
 import java.util.Objects;
 import java.util.concurrent.TimeUnit;
 
+
+/**
+ * 授权接口
+ */
 @Tag(name="授权接口")
 @RestController
 @RequestMapping("/auth")

+ 81 - 0
commons/src/main/java/com/jzg/util/FileUtils.java

@@ -0,0 +1,81 @@
+package com.jzg.util;
+
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.Formatter;
+
+public class FileUtils {
+
+    // 将字节数组转换为十六进制字符串
+    private static String byteArrayToHex(byte[] byteArray) {
+        try (Formatter formatter = new Formatter()) {
+            for (byte b : byteArray) {
+                formatter.format("%02x", b);
+            }
+            return formatter.toString();
+        }
+    }
+
+    /**
+     * 获取文件ETAG
+     * @param file
+     * @return
+     * @throws NoSuchAlgorithmException
+     * @throws IOException
+     */
+    public static String getFileETag(MultipartFile file) throws NoSuchAlgorithmException, IOException {
+        MessageDigest md5Digest = MessageDigest.getInstance("MD5");
+
+        // 获取 MultipartFile 的输入流进行 MD5 计算
+        try (InputStream is = file.getInputStream()) {
+            byte[] byteArray = new byte[1024];
+            int bytesRead;
+            while ((bytesRead = is.read(byteArray)) != -1) {
+                md5Digest.update(byteArray, 0, bytesRead);
+            }
+        }
+
+        byte[] md5Bytes = md5Digest.digest();
+        return byteArrayToHex(md5Bytes);
+    }
+
+    /**
+     * 获取文件md5
+     * @param file
+     * @return
+     * @throws IOException
+     * @throws NoSuchAlgorithmException
+     */
+    public static String getFileMD5(MultipartFile file) throws IOException, NoSuchAlgorithmException {
+        // 获取文件输入流
+        InputStream inputStream = file.getInputStream();
+
+        // 创建 MessageDigest 对象用于计算 MD5
+        MessageDigest messageDigest = MessageDigest.getInstance("MD5");
+
+        // 使用 1KB 缓冲区读取文件内容
+        byte[] buffer = new byte[1024];
+        int bytesRead;
+        while ((bytesRead = inputStream.read(buffer)) != -1) {
+            messageDigest.update(buffer, 0, bytesRead);
+        }
+
+        // 关闭输入流
+        inputStream.close();
+
+        // 获取 MD5 校验和
+        byte[] md5Bytes = messageDigest.digest();
+
+        // 转换为 16 进制字符串
+        StringBuilder sb = new StringBuilder();
+        for (byte b : md5Bytes) {
+            sb.append(String.format("%02x", b & 0xff));
+        }
+
+        return sb.toString();  // 返回 MD5 字符串
+    }
+}

+ 1 - 0
gateway/src/main/java/com/jzg/config/CorsConfig.java

@@ -29,6 +29,7 @@ public class CorsConfig {
         corsConfiguration.addAllowedOrigin("http://127.0.0.1:9000");
         corsConfiguration.addAllowedOrigin("http://192.168.5.149:9000");
         corsConfiguration.addAllowedOrigin("http://192.168.5.30:9000");
+        corsConfiguration.addAllowedOrigin("http://192.168.5.140:9001");
         // 允许的方法
         corsConfiguration.addAllowedMethod("*");
         // 允许的头信息

+ 5 - 0
gateway/src/main/resources/application.yml

@@ -18,6 +18,11 @@ spring:
           predicates:
             - Path=/userRole/**
 
+        - id: file_route
+          uri: http://localhost:8083/
+          predicates:
+            - Path=/file/**
+
         - id: tenant_route
           uri: http://localhost:8084/
           predicates:

+ 27 - 0
platform/src/main/java/com/jzg/config/MinioConfig.java

@@ -0,0 +1,27 @@
+package com.jzg.config;
+
+import io.minio.MinioClient;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class MinioConfig {
+
+    @Value("${minio.url}")
+    private String minioUrl;
+
+    @Value("${minio.access-key}")
+    private String accessKey;
+
+    @Value("${minio.secret-key}")
+    private String secretKey;
+
+    @Bean
+    public MinioClient minioClient() {
+        return MinioClient.builder()
+                .endpoint(minioUrl)
+                .credentials(accessKey, secretKey)
+                .build();
+    }
+}

+ 129 - 0
platform/src/main/java/com/jzg/controller/FileUploadController.java

@@ -0,0 +1,129 @@
+package com.jzg.controller;
+
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.jzg.core.page.HttpResult;
+import com.jzg.entity.po.SysUploadFiles;
+import com.jzg.mapper.SysUploadFilesMapper;
+import com.jzg.util.FileUtils;
+import com.jzg.util.idgen.IdGenerate;
+import io.minio.*;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.InputStream;
+import java.text.SimpleDateFormat;
+import java.time.LocalDateTime;
+import java.util.Date;
+import java.util.Objects;
+
+/**
+ * 文件上传接口
+ */
+
+@RestController
+@RequestMapping("/file")
+public class FileUploadController {
+
+
+    @Autowired
+    private MinioClient minioClient;
+
+    @Autowired
+    private SysUploadFilesMapper sysUploadFilesMapper;
+
+    @Value("${minio.bucket-name}")
+    private String bucketName;
+
+    @PostMapping("/upload")
+    public HttpResult uploadFile(@RequestParam("file") MultipartFile file) {
+        try {
+            // 获取文件原始名称和扩展名
+            String originalFileName = file.getOriginalFilename();
+            String extension = getFileExtension(originalFileName);
+
+            // MD5,ETag
+            String fileMD5 = FileUtils.getFileMD5(file);
+            String objectName = generateObjectName(originalFileName, fileMD5, extension);
+            String fileETag = FileUtils.getFileETag(file);
+
+            // 查找文件是否已经存在于MinIO
+            if (isFileExistsInMinIO(objectName, fileETag)) {
+                return HttpResult.ok(getFileFromDatabase(fileETag));
+            }
+
+            //如果文件不存在,执行上传操作
+            SysUploadFiles sysUploadFiles = uploadFileToMinIO(file, objectName, fileETag, extension);
+
+            return HttpResult.ok(sysUploadFiles);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return HttpResult.error("文件上传失败: " + e.getMessage());
+        }
+    }
+
+    private String getFileExtension(String fileName) {
+        return fileName.substring(fileName.lastIndexOf("."));
+    }
+
+    private String generateObjectName(String originalFileName, String fileMD5, String extension) {
+        return originalFileName.substring(0, originalFileName.lastIndexOf(".")) + "_" + fileMD5 + extension;
+    }
+
+    private boolean isFileExistsInMinIO(String objectName, String fileETag) {
+        try {
+            StatObjectArgs statObjectArgs = StatObjectArgs.builder()
+                    .bucket(bucketName)
+                    .object(objectName)
+                    .build();
+
+            StatObjectResponse statObjectResponse = minioClient.statObject(statObjectArgs);
+            String minioFileETag = statObjectResponse.etag();
+
+            return minioFileETag.equals(fileETag);
+        } catch (Exception e) {
+            return false; // 如果获取对象出错,认为文件不存在
+        }
+    }
+
+    private SysUploadFiles getFileFromDatabase(String fileETag) {
+        SysUploadFiles sysUploadFiles = sysUploadFilesMapper.selectOne(
+                new LambdaQueryWrapper<SysUploadFiles>().eq(SysUploadFiles::getEtag, fileETag));
+
+        if (sysUploadFiles == null) {
+            sysUploadFiles = new SysUploadFiles();
+            sysUploadFiles.setId(IdGenerate.nextId());
+            sysUploadFiles.setCreateTime(LocalDateTime.now());
+            sysUploadFilesMapper.insert(sysUploadFiles);
+        }
+
+        return sysUploadFiles;
+    }
+
+    private SysUploadFiles uploadFileToMinIO(MultipartFile file, String objectName, String fileETag, String extension) throws Exception {
+        // 上传到minio
+        InputStream fileInputStream = file.getInputStream();
+        ObjectWriteResponse objectWriteResponse = minioClient.putObject(PutObjectArgs.builder()
+                .bucket(bucketName)
+                .object(objectName)
+                .stream(fileInputStream, file.getSize(), -1)
+                .contentType(file.getContentType())
+                .build());
+
+        SysUploadFiles sysUploadFiles = new SysUploadFiles();
+        sysUploadFiles.setId(IdGenerate.nextId());
+        sysUploadFiles.setFileName(objectName);
+        sysUploadFiles.setFileType(extension.substring(1));
+        sysUploadFiles.setBucketName(bucketName);
+        sysUploadFiles.setEtag(objectWriteResponse.etag());
+        sysUploadFiles.setCreateTime(LocalDateTime.now());
+        sysUploadFilesMapper.insert(sysUploadFiles);
+
+        return sysUploadFiles;
+    }
+}

+ 11 - 1
platform/src/main/java/com/jzg/controller/UserRoleController.java

@@ -2,15 +2,18 @@ package com.jzg.controller;
 
 
 import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.jzg.aop.PremissionCheck;
 import com.jzg.core.base.BaseController;
 import com.jzg.core.page.HttpResult;
+import com.jzg.entity.po.SysRole;
 import com.jzg.entity.vo.RolePermissionVo;
 import com.jzg.entity.vo.SysRoleVo;
 import com.jzg.exception.SystemException;
 import com.jzg.exception.ValidateException;
 import com.jzg.service.UserRoleService;
+import com.jzg.util.StringUtils;
 import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.media.Schema;
 import io.swagger.v3.oas.annotations.tags.Tag;
@@ -40,7 +43,8 @@ public class UserRoleController extends BaseController {
     @PostMapping("/roleList")
     public HttpResult roleList(@RequestBody SysRoleVo sysRoleVo){
         Page page = sysRoleVo.getPage();
-        return HttpResult.ok(userRoleService.page(page));
+        return HttpResult.ok(userRoleService.page(page,new LambdaQueryWrapper<SysRole>()
+                .like(StringUtils.isNotBlank(sysRoleVo.getName()),SysRole::getName,sysRoleVo.getName())));
     }
 
     @Operation(summary = "角色信息查询")
@@ -67,6 +71,12 @@ public class UserRoleController extends BaseController {
         return userRoleService.roleUpdate(sysRoleVo)? HttpResult.ok("修改角色成功") : HttpResult.error("修改角色失败");
     }
 
+    @Operation(summary = "角色删除检测")
+    @PostMapping("/roleDeleteValid")
+    public HttpResult roleDeleteValid(@RequestBody SysRoleVo roleVo) {
+        return userRoleService.roleDeleteValid(roleVo) ? HttpResult.ok("角色可以进行删除") : HttpResult.error("删除角色前,请先移除角色内的所有成员");
+    }
+
     @Operation(summary = "角色删除")
     @PostMapping("/roleDelete")
     public HttpResult roleDelete(@RequestBody SysRoleVo roleVo){

+ 26 - 0
platform/src/main/java/com/jzg/entity/po/SysUploadFiles.java

@@ -0,0 +1,26 @@
+package com.jzg.entity.po;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+@Schema(description = "文件实体类")
+@Data
+public class SysUploadFiles {
+
+    private String id;
+
+    private String fileName;
+
+    private String fileType;
+
+    private String bucketName;
+
+    private String etag;
+
+    private LocalDateTime createTime;
+
+    private String createBy;
+
+}

+ 2 - 0
platform/src/main/java/com/jzg/entity/vo/SysRoleVo.java

@@ -26,6 +26,8 @@ public class SysRoleVo extends PageRequest {
     @Schema(description = "系统code")
     private String system;
 
+    private String systemCode;
+
     @NotBlank(message = "角色名称不能为空")
     @Size(max=100,message = "角色名称长度不能大于100")
     @Schema(description = "角色名称")

+ 10 - 0
platform/src/main/java/com/jzg/mapper/SysUploadFilesMapper.java

@@ -0,0 +1,10 @@
+package com.jzg.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.jzg.entity.po.SysUploadFiles;
+import com.jzg.entity.po.SysUserRole;
+import org.apache.ibatis.annotations.Mapper;
+
+@Mapper
+public interface SysUploadFilesMapper extends BaseMapper<SysUploadFiles> {
+}

+ 7 - 0
platform/src/main/java/com/jzg/service/UserRoleService.java

@@ -59,5 +59,12 @@ public interface UserRoleService extends IService<SysRole> {
      */
     public boolean roleDelete(SysRoleVo sysRoleVo);
 
+    /**
+     * 角色删除检测
+     * @param sysRoleVo
+     * @return
+     */
+    public boolean roleDeleteValid(SysRoleVo sysRoleVo);
+
 
 }

+ 26 - 0
platform/src/main/java/com/jzg/service/impl/UserRoleServiceImpl.java

@@ -6,12 +6,15 @@ import com.jzg.annotation.IgnoreTenant;
 import com.jzg.entity.po.SysRole;
 import com.jzg.entity.po.SysRolePerms;
 import com.jzg.entity.po.SysSystem;
+import com.jzg.entity.po.SysUserRole;
 import com.jzg.entity.vo.RolePermissionVo;
 import com.jzg.entity.vo.SysRoleVo;
 import com.jzg.exception.SystemException;
+import com.jzg.exception.ValidateException;
 import com.jzg.mapper.SysMenuMapper;
 import com.jzg.mapper.SysRoleMapper;
 import com.jzg.mapper.SysRolePermsMapper;
+import com.jzg.mapper.SysUserRoleMapper;
 import com.jzg.service.SysSystemService;
 import com.jzg.service.UserRoleService;
 import com.jzg.util.idgen.IdGenerate;
@@ -35,6 +38,9 @@ public class UserRoleServiceImpl extends ServiceImpl<SysRoleMapper, SysRole> imp
     @Autowired
     SysRolePermsMapper sysRolePermsMapper;
 
+    @Autowired
+    SysUserRoleMapper sysUserRoleMapper;
+
     @IgnoreTenant
     @Override
     public List<RolePermissionVo> getAllRoleMenu() {
@@ -123,5 +129,25 @@ public class UserRoleServiceImpl extends ServiceImpl<SysRoleMapper, SysRole> imp
         return false;
     }
 
+    @Override
+    public boolean roleDeleteValid(SysRoleVo sysRoleVo) {
+        if(sysRoleVo.getId().equals("admin")){
+            throw new SystemException("admin角色无法删除");
+        }
+        Long count = baseMapper.selectCount(new LambdaQueryWrapper<SysRole>()
+                .eq(SysRole::getSystemCode, sysRoleVo.getSystemCode())
+                .eq(SysRole::getId, sysRoleVo.getId())
+        );
+        if(count <= 0){
+            throw new SystemException("找不到该角色");
+        }
+        count = sysUserRoleMapper.selectCount(new LambdaQueryWrapper<SysUserRole>()
+                .eq(SysUserRole::getRoleId, sysRoleVo.getId()));
+        if(count > 0){
+            return false;
+        }
+        return true;
+    }
+
 
 }

+ 8 - 0
platform/src/main/resources/application.yml

@@ -34,4 +34,12 @@ tenant:
   ignoreTables:
     - sys_system
     - sys_role_perms
+    - sys_user_role
+    - sys_upload_files
   ignoreLoginNames:
+
+minio:
+  url: http://192.168.5.250:9000
+  access-key: v7Zb8XhyLcYNcSHlxvyK
+  secret-key: 58YibMwpxGKtXcekPL065OM4GonC1hf2tFMjI9EN
+  bucket-name: jzg

+ 0 - 1
tenant/organization/src/main/java/com/jzg/organization/OrganizationApplication.java

@@ -6,7 +6,6 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
 import org.springframework.context.annotation.ComponentScan;
 
 @SpringBootApplication
-//@EnableFeignClients
 @ComponentScan(basePackages = "com.jzg")
 @MapperScan("com.jzg")
 public class OrganizationApplication {