Jelajahi Sumber

用户管理,上床图片

chenying2100 3 bulan lalu
induk
melakukan
80f538f199
27 mengubah file dengan 992 tambahan dan 30 penghapusan
  1. 2 0
      pom.xml
  2. 13 0
      ruoyi-common/ruoyi-common-core/pom.xml
  3. 16 0
      ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/constant/BizConst.java
  4. 80 0
      ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/QiNiuUtil.java
  5. 324 0
      ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/file/FileUtil.java
  6. 40 0
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/QiNiuController.java
  7. 4 4
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysDeptController.java
  8. 8 8
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysUserController.java
  9. 4 0
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysDept.java
  10. 85 0
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysUser.java
  11. 4 0
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/SysDeptBo.java
  12. 88 2
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/SysUserBo.java
  13. 4 0
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/SysDeptVo.java
  14. 2 0
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/SysRoleVo.java
  15. 1 1
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/SysUserInfoVo.java
  16. 86 0
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/SysUserVo.java
  17. 2 0
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysRoleMapper.java
  18. 17 0
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/IQiNiuContentService.java
  19. 1 1
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysRoleService.java
  20. 131 0
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/QiNiuContentServiceImpl.java
  21. 13 6
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysDeptServiceImpl.java
  22. 1 1
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysDictDataServiceImpl.java
  23. 6 2
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysRoleServiceImpl.java
  24. 24 3
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysUserServiceImpl.java
  25. 16 0
      ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysRoleMapper.xml
  26. 2 2
      ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml
  27. 18 0
      script/sql/biz/update.sql

+ 2 - 0
pom.xml

@@ -39,6 +39,8 @@
         <justauth.version>1.16.7</justauth.version>
         <!-- 离线IP地址定位库 -->
         <ip2region.version>2.7.0</ip2region.version>
+        <fastjson.version>1.2.83</fastjson.version>
+        <qiniu-java-sdk.version>7.4.0</qiniu-java-sdk.version>
 
         <!-- OSS 配置 -->
         <aws.sdk.version>2.28.22</aws.sdk.version>

+ 13 - 0
ruoyi-common/ruoyi-common-core/pom.xml

@@ -16,6 +16,19 @@
     </description>
 
     <dependencies>
+        <!-- 七牛云SDK -->
+        <dependency>
+            <groupId>com.qiniu</groupId>
+            <artifactId>qiniu-java-sdk</artifactId>
+            <version>${qiniu-java-sdk.version}</version>
+        </dependency>
+        <!-- json -->
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>fastjson</artifactId>
+            <version>${fastjson.version}</version>
+        </dependency>
+
         <!-- Spring框架基本的核心工具 -->
         <dependency>
             <groupId>org.springframework</groupId>

+ 16 - 0
ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/constant/BizConst.java

@@ -6,4 +6,20 @@ package org.dromara.common.core.constant;
  **/
 public interface BizConst {
     String HOSPITAL_ROLE_TYPE = "hospital_role_type";
+
+    String QNY_CONFIG = "qny_config";
+
+    String QNY_MAX_SIZE = "max_size";
+
+    String QNY_SECRET_KEY = "secret_key";
+
+    String QNY_ACCESS_KEY = "access_key";
+
+    String QNY_ZONE = "zone";
+
+    String QNY_BUCKET_NAME = "bucket_name";
+
+    String QNY_STATIC_DOMAIN = "static_domain";
+
+    String QNY_CONFIG_CACHE = "qny:config";
 }

+ 80 - 0
ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/QiNiuUtil.java

@@ -0,0 +1,80 @@
+/*
+ *  Copyright 2019-2020 Zheng Jie
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.dromara.common.core.utils;
+
+import com.qiniu.storage.Region;
+import org.dromara.common.core.utils.file.FileUtil;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+
+public class QiNiuUtil {
+
+    /**
+     * 华东
+     */
+    private static final String HUAD = "HUAD";
+    /**
+     * 华北
+     */
+    private static final String HUAB = "HUAB";
+    /**
+     * 华南
+     */
+    private static final String HUAN = "HUAN";
+    /**
+     * 北美
+     */
+    private static final String BEIM = "BEIM";
+
+    /**
+     * 得到机房的对应关系
+     *
+     * @param zone 机房名称
+     * @return Region
+     */
+    public static Region getRegion(String zone) {
+
+        if (HUAD.equals(zone)) {
+            return Region.huadong();
+        } else if (HUAB.equals(zone)) {
+            return Region.huabei();
+        } else if (HUAN.equals(zone)) {
+            return Region.huanan();
+        } else if (BEIM.equals(zone)) {
+            return Region.beimei();
+            // 否则就是东南亚
+        } else {
+            return Region.qvmHuadong();
+        }
+    }
+
+    /**
+     * 默认不指定key的情况下,以文件内容的hash值作为文件名
+     *
+     * @param file 文件名
+     * @return String
+     */
+    public static String getName(String file) {
+        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
+        Date date = new Date();
+        return FileUtil.getFileNameNoEx(file) + "-" +
+            sdf.format(date) +
+            "." +
+            FileUtil.getExtensionName(file);
+    }
+}

+ 324 - 0
ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/file/FileUtil.java

@@ -0,0 +1,324 @@
+package org.dromara.common.core.utils.file;
+
+import cn.hutool.core.io.IoUtil;
+import cn.hutool.core.util.IdUtil;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.extern.slf4j.Slf4j;
+import org.dromara.common.core.exception.ServiceException;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.security.MessageDigest;
+import java.text.DecimalFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+
+@Slf4j
+public class FileUtil extends cn.hutool.core.io.FileUtil {
+
+
+    /**
+     * 系统临时目录
+     * <br>
+     * windows 包含路径分割符,但Linux 不包含,
+     * 在windows \\==\ 前提下,
+     * 为安全起见 同意拼装 路径分割符,
+     * <pre>
+     *       java.io.tmpdir
+     *       windows : C:\Users/xxx\AppData\Local\Temp\
+     *       linux: /temp
+     * </pre>
+     */
+    public static final String SYS_TEM_DIR = System.getProperty("java.io.tmpdir") + File.separator;
+    /**
+     * 定义GB的计算常量
+     */
+    private static final int GB = 1024 * 1024 * 1024;
+    /**
+     * 定义MB的计算常量
+     */
+    private static final int MB = 1024 * 1024;
+    /**
+     * 定义KB的计算常量
+     */
+    private static final int KB = 1024;
+
+    /**
+     * 格式化小数
+     */
+    private static final DecimalFormat DF = new DecimalFormat("0.00");
+
+    public static final String IMAGE = "图片";
+    public static final String TXT = "文档";
+    public static final String MUSIC = "音乐";
+    public static final String VIDEO = "视频";
+    public static final String OTHER = "其他";
+
+
+    /**
+     * MultipartFile转File
+     */
+    public static File toFile(MultipartFile multipartFile) {
+        // 获取文件名
+        String fileName = multipartFile.getOriginalFilename();
+        // 获取文件后缀
+        String prefix = "." + getExtensionName(fileName);
+        File file = null;
+        try {
+            // 用uuid作为文件名,防止生成的临时文件重复
+            file = File.createTempFile(IdUtil.simpleUUID(), prefix);
+            // MultipartFile to File
+            multipartFile.transferTo(file);
+        } catch (IOException e) {
+            log.error(e.getMessage(), e);
+        }
+        return file;
+    }
+
+    /**
+     * 获取文件扩展名,不带 .
+     */
+    public static String getExtensionName(String filename) {
+        if ((filename != null) && (filename.length() > 0)) {
+            int dot = filename.lastIndexOf('.');
+            if ((dot > -1) && (dot < (filename.length() - 1))) {
+                return filename.substring(dot + 1);
+            }
+        }
+        return filename;
+    }
+
+    /**
+     * Java文件操作 获取不带扩展名的文件名
+     */
+    public static String getFileNameNoEx(String filename) {
+        if ((filename != null) && (filename.length() > 0)) {
+            int dot = filename.lastIndexOf('.');
+            if ((dot > -1) && (dot < (filename.length()))) {
+                return filename.substring(0, dot);
+            }
+        }
+        return filename;
+    }
+
+    /**
+     * 文件大小转换
+     */
+    public static String getSize(long size) {
+        String resultSize;
+        if (size / GB >= 1) {
+            //如果当前Byte的值大于等于1GB
+            resultSize = DF.format(size / (float) GB) + "GB   ";
+        } else if (size / MB >= 1) {
+            //如果当前Byte的值大于等于1MB
+            resultSize = DF.format(size / (float) MB) + "MB   ";
+        } else if (size / KB >= 1) {
+            //如果当前Byte的值大于等于1KB
+            resultSize = DF.format(size / (float) KB) + "KB   ";
+        } else {
+            resultSize = size + "B   ";
+        }
+        return resultSize;
+    }
+
+    /**
+     * inputStream 转 File
+     */
+    public static File inputStreamToFile(InputStream ins, String name) throws Exception {
+        File file = new File(SYS_TEM_DIR + name);
+        if (file.exists()) {
+            return file;
+        }
+        OutputStream os = new FileOutputStream(file);
+        int bytesRead;
+        int len = 8192;
+        byte[] buffer = new byte[len];
+        while ((bytesRead = ins.read(buffer, 0, len)) != -1) {
+            os.write(buffer, 0, bytesRead);
+        }
+        os.close();
+        ins.close();
+        return file;
+    }
+
+    /**
+     * 将文件名解析成文件的上传路径
+     */
+    public static File upload(MultipartFile file, String filePath) {
+        Date date = new Date();
+        SimpleDateFormat format = new SimpleDateFormat("yyyyMMddhhmmssS");
+        String name = getFileNameNoEx(file.getOriginalFilename());
+        String suffix = getExtensionName(file.getOriginalFilename());
+        String nowStr = "-" + format.format(date);
+        try {
+            String fileName = name + nowStr + "." + suffix;
+            String path = filePath + fileName;
+            // getCanonicalFile 可解析正确各种路径
+            File dest = new File(path).getCanonicalFile();
+            // 检测是否存在目录
+            if (!dest.getParentFile().exists()) {
+                if (!dest.getParentFile().mkdirs()) {
+                    System.out.println("was not successful.");
+                }
+            }
+            // 文件写入
+            file.transferTo(dest);
+            return dest;
+        } catch (Exception e) {
+            log.error(e.getMessage(), e);
+        }
+        return null;
+    }
+
+    /**
+     * 导出excel
+     */
+//    public static void downloadExcel(List<Map<String, Object>> list, HttpServletResponse response) throws IOException {
+//        String tempPath = SYS_TEM_DIR + IdUtil.fastSimpleUUID() + ".xlsx";
+//        File file = new File(tempPath);
+//        BigExcelWriter writer = ExcelUtil.getBigWriter(file);
+//        // 一次性写出内容,使用默认样式,强制输出标题
+//        writer.write(list, true);
+//        SXSSFSheet sheet = (SXSSFSheet) writer.getSheet();
+//        //上面需要强转SXSSFSheet  不然没有trackAllColumnsForAutoSizing方法
+//        sheet.trackAllColumnsForAutoSizing();
+//        //列宽自适应
+//        writer.autoSizeColumnAll();
+//        //response为HttpServletResponse对象
+//        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
+//        //test.xls是弹出下载对话框的文件名,不能为中文,中文请自行编码
+//        response.setHeader("Content-Disposition", "attachment;filename=file.xlsx");
+//        ServletOutputStream out = response.getOutputStream();
+//        // 终止后删除临时文件
+//        file.deleteOnExit();
+//        writer.flush(out, true);
+//        //此处记得关闭输出Servlet流
+//        IoUtil.close(out);
+//    }
+    public static String getFileType(String type) {
+        String documents = "txt doc pdf ppt pps xlsx xls docx";
+        String music = "mp3 wav wma mpa ram ra aac aif m4a";
+        String video = "avi mpg mpe mpeg asf wmv mov qt rm mp4 flv m4v webm ogv ogg";
+        String image = "bmp dib pcp dif wmf gif jpg tif eps psd cdr iff tga pcd mpt png jpeg";
+        if (image.contains(type)) {
+            return IMAGE;
+        } else if (documents.contains(type)) {
+            return TXT;
+        } else if (music.contains(type)) {
+            return MUSIC;
+        } else if (video.contains(type)) {
+            return VIDEO;
+        } else {
+            return OTHER;
+        }
+    }
+
+    public static void checkSize(long maxSize, long size) {
+        // 1M
+        int len = 1024 * 1024;
+        if (size > (maxSize * len)) {
+            throw new ServiceException("文件超出规定大小");
+
+        }
+    }
+
+    /**
+     * 判断两个文件是否相同
+     */
+    public static boolean check(File file1, File file2) {
+        String img1Md5 = getMd5(file1);
+        String img2Md5 = getMd5(file2);
+        return img1Md5.equals(img2Md5);
+    }
+
+    /**
+     * 判断两个文件是否相同
+     */
+    public static boolean check(String file1Md5, String file2Md5) {
+        return file1Md5.equals(file2Md5);
+    }
+
+    private static byte[] getByte(File file) {
+        // 得到文件长度
+        byte[] b = new byte[(int) file.length()];
+        try {
+            InputStream in = new FileInputStream(file);
+            try {
+                System.out.println(in.read(b));
+            } catch (IOException e) {
+                log.error(e.getMessage(), e);
+            }
+        } catch (FileNotFoundException e) {
+            log.error(e.getMessage(), e);
+            return null;
+        }
+        return b;
+    }
+
+    private static String getMd5(byte[] bytes) {
+        // 16进制字符
+        char[] hexDigits = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
+        try {
+            MessageDigest mdTemp = MessageDigest.getInstance("MD5");
+            mdTemp.update(bytes);
+            byte[] md = mdTemp.digest();
+            int j = md.length;
+            char[] str = new char[j * 2];
+            int k = 0;
+            // 移位 输出字符串
+            for (byte byte0 : md) {
+                str[k++] = hexDigits[byte0 >>> 4 & 0xf];
+                str[k++] = hexDigits[byte0 & 0xf];
+            }
+            return new String(str);
+        } catch (Exception e) {
+            log.error(e.getMessage(), e);
+        }
+        return null;
+    }
+
+    /**
+     * 下载文件
+     *
+     * @param request  /
+     * @param response /
+     * @param file     /
+     */
+    public static void downloadFile(HttpServletRequest request, HttpServletResponse response, File file, boolean deleteOnExit) {
+        response.setCharacterEncoding(request.getCharacterEncoding());
+        response.setContentType("application/octet-stream");
+        FileInputStream fis = null;
+        try {
+            fis = new FileInputStream(file);
+            response.setHeader("Content-Disposition", "attachment; filename=" + file.getName());
+            IoUtil.copy(fis, response.getOutputStream());
+            response.flushBuffer();
+        } catch (Exception e) {
+            log.error(e.getMessage(), e);
+        } finally {
+            if (fis != null) {
+                try {
+                    fis.close();
+                    if (deleteOnExit) {
+                        file.deleteOnExit();
+                    }
+                } catch (IOException e) {
+                    log.error(e.getMessage(), e);
+                }
+            }
+        }
+    }
+
+    public static String getMd5(File file) {
+        return getMd5(getByte(file));
+    }
+
+}

+ 40 - 0
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/QiNiuController.java

@@ -0,0 +1,40 @@
+package org.dromara.system.controller.system;
+
+
+import cn.hutool.core.util.StrUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.dromara.common.core.domain.R;
+import org.dromara.system.domain.SysOss;
+import org.dromara.system.service.IQiNiuContentService;
+import org.springframework.beans.factory.annotation.Autowired;
+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;
+
+
+@Slf4j
+@RestController
+@RequestMapping("/api/qiniu")
+//@Api(tags = "七牛云存储管理")
+public class QiNiuController {
+
+    @Autowired
+    private IQiNiuContentService qiNiuService;
+
+    //    @ApiOperation("上传文件")
+    @PostMapping("/upload")
+    public R<SysOss> uploadByPrefix(@RequestParam MultipartFile file) {
+        SysOss qiniuContent = qiNiuService.upload(file);
+        if (StrUtil.isNotBlank(qiniuContent.getUrl())) {
+            SysOss ossFile = new SysOss();
+            ossFile.setOssId(qiniuContent.getOssId());
+            ossFile.setFileName(qiniuContent.getOriginalName());
+            ossFile.setUrl(qiniuContent.getUrl());
+            return R.ok("上传成功!", ossFile);
+        }
+
+        return R.fail("上传失败!");
+    }
+}

+ 4 - 4
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysDeptController.java

@@ -38,7 +38,7 @@ import java.util.List;
 public class SysDeptController extends BaseController {
 
     private final ISysDeptService deptService;
-    private final ISysPostService postService;
+//    private final ISysPostService postService;
 
     /**
      * 获取科室列表
@@ -137,9 +137,9 @@ public class SysDeptController extends BaseController {
         if (deptService.checkDeptExistUser(deptId)) {
             return R.warn("科室存在用户,不允许删除");
         }
-        if (postService.countPostByDeptId(deptId) > 0) {
-            return R.warn("科室存在岗位,不允许删除");
-        }
+//        if (postService.countPostByDeptId(deptId) > 0) {
+//            return R.warn("科室存在岗位,不允许删除");
+//        }
         deptService.checkDeptDataScope(deptId);
         return toAjax(deptService.deleteDeptById(deptId));
     }

+ 8 - 8
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysUserController.java

@@ -53,7 +53,7 @@ public class SysUserController extends BaseController {
     private final ISysRoleService roleService;
     private final ISysPostService postService;
     private final ISysDeptService deptService;
-    private final ISysTenantService tenantService;
+//    private final ISysTenantService tenantService;
 
     /**
      * 获取用户列表
@@ -159,16 +159,16 @@ public class SysUserController extends BaseController {
         deptService.checkDeptDataScope(user.getDeptId());
         if (!userService.checkUserNameUnique(user)) {
             return R.fail("新增用户'" + user.getUserName() + "'失败,登录账号已存在");
-        } else if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user)) {
+        } /*else if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user)) {
             return R.fail("新增用户'" + user.getUserName() + "'失败,手机号码已存在");
         } else if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(user)) {
             return R.fail("新增用户'" + user.getUserName() + "'失败,邮箱账号已存在");
-        }
-        if (TenantHelper.isEnable()) {
-            if (!tenantService.checkAccountBalance(TenantHelper.getTenantId())) {
-                return R.fail("当前租户下用户名额不足,请联系管理员");
-            }
-        }
+        }*/
+//        if (TenantHelper.isEnable()) {
+//            if (!tenantService.checkAccountBalance(TenantHelper.getTenantId())) {
+//                return R.fail("当前租户下用户名额不足,请联系管理员");
+//            }
+//        }
         user.setPassword(BCrypt.hashpw(user.getPassword()));
         return toAjax(userService.insertUser(user));
     }

+ 4 - 0
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysDept.java

@@ -37,6 +37,10 @@ public class SysDept extends TenantEntity {
      */
     private Long parentId;
 
+    private String hospOrDept;
+
+    private String logo;
+
     /**
      * 部门名称
      */

+ 85 - 0
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysUser.java

@@ -103,6 +103,91 @@ public class SysUser extends TenantEntity {
      */
     private String remark;
 
+    /**
+     * 别名
+     */
+    private String alias;
+
+    /**
+     * 角色
+     */
+    private String role;
+
+    /**
+     * 所属科室编码
+     */
+    private String deptCode;
+
+    /**
+     * 工号
+     */
+    private String jobNumber;
+
+    /**
+     * 身份证号码
+     */
+    private String idCard;
+
+    /**
+     * 现住地址
+     */
+    private String address;
+
+    /**
+     * 出生日期
+     */
+    private Date birthDate;
+
+    /**
+     * 户籍地址
+     */
+    private String regAddress;
+
+    /**
+     * 民族
+     */
+    private String nation;
+
+    /**
+     * 政治面貌
+     */
+    private String political;
+
+    /**
+     * 婚姻状况
+     */
+    private String marital;
+
+    /**
+     * 职称
+     */
+    private String title;
+
+    /**
+     * 学历
+     */
+    private String education;
+
+    /**
+     * 职工简介
+     */
+    private String intro;
+
+    /**
+     * 擅长疾病
+     */
+    private String expertise;
+
+    /**
+     * 签名图片路径
+     */
+    private String signatureImg;
+
+    /**
+     * 姓名
+     */
+    private String name;
+
 
     public SysUser(Long userId) {
         this.userId = userId;

+ 4 - 0
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/SysDeptBo.java

@@ -26,6 +26,10 @@ public class SysDeptBo extends BaseEntity {
      */
     private Long deptId;
 
+    private String hospOrDept;
+
+    private String logo;
+
     /**
      * 父部门ID
      */

+ 88 - 2
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/SysUserBo.java

@@ -12,6 +12,8 @@ import org.dromara.common.core.xss.Xss;
 import org.dromara.common.mybatis.core.domain.BaseEntity;
 import org.dromara.system.domain.SysUser;
 
+import java.util.Date;
+
 /**
  * 用户信息业务对象 sys_user
  *
@@ -46,7 +48,6 @@ public class SysUserBo extends BaseEntity {
      * 用户昵称
      */
     @Xss(message = "用户昵称不能包含脚本字符")
-    @NotBlank(message = "用户昵称不能为空")
     @Size(min = 0, max = 30, message = "用户昵称长度不能超过{max}个字符")
     private String nickName;
 
@@ -91,7 +92,7 @@ public class SysUserBo extends BaseEntity {
      * 角色组
      */
     @Size(min = 1, message = "用户角色不能为空")
-    private Long[] roleIds;
+    private String  roleIds;
 
     /**
      * 岗位组
@@ -113,6 +114,91 @@ public class SysUserBo extends BaseEntity {
      */
     private String excludeUserIds;
 
+    /**
+     * 别名
+     */
+    private String alias;
+
+    /**
+     * 角色
+     */
+    private String role;
+
+    /**
+     * 所属科室编码
+     */
+    private String deptCode;
+
+    /**
+     * 工号
+     */
+    private String jobNumber;
+
+    /**
+     * 身份证号码
+     */
+    private String idCard;
+
+    /**
+     * 现住地址
+     */
+    private String address;
+
+    /**
+     * 出生日期
+     */
+    private Date birthDate;
+
+    /**
+     * 户籍地址
+     */
+    private String regAddress;
+
+    /**
+     * 民族
+     */
+    private String nation;
+
+    /**
+     * 政治面貌
+     */
+    private String political;
+
+    /**
+     * 婚姻状况
+     */
+    private String marital;
+
+    /**
+     * 职称
+     */
+    private String title;
+
+    /**
+     * 学历
+     */
+    private String education;
+
+    /**
+     * 职工简介
+     */
+    private String intro;
+
+    /**
+     * 擅长疾病
+     */
+    private String expertise;
+
+    /**
+     * 签名图片路径
+     */
+    private String signatureImg;
+
+    /**
+     * 姓名
+     */
+    private String name;
+
     public SysUserBo(Long userId) {
         this.userId = userId;
     }

+ 4 - 0
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/SysDeptVo.java

@@ -32,6 +32,8 @@ public class SysDeptVo implements Serializable {
      */
     @ExcelProperty(value = "部门id")
     private Long deptId;
+
+    private String hospOrDept;
     /**
      * 科室描述
      */
@@ -46,6 +48,8 @@ public class SysDeptVo implements Serializable {
      */
     private String parentName;
 
+    private String logo;
+
     /**
      * 祖级列表
      */

+ 2 - 0
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/SysRoleVo.java

@@ -98,6 +98,8 @@ public class SysRoleVo implements Serializable {
     @ExcelProperty(value = "创建时间")
     private Date createTime;
 
+    private Long userId;
+
     /**
      * 用户是否存在此角色标识 默认不存在
      */

+ 1 - 1
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/SysUserInfoVo.java

@@ -20,7 +20,7 @@ public class SysUserInfoVo {
     /**
      * 角色ID列表
      */
-    private List<Long> roleIds;
+    private Long roleIds;
 
     /**
      * 角色列表

+ 86 - 0
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/SysUserVo.java

@@ -139,4 +139,90 @@ public class SysUserVo implements Serializable {
      */
     private Long roleId;
 
+    private String roleName;
+
+    /**
+     * 别名
+     */
+    private String alias;
+
+    /**
+     * 角色
+     */
+    private String role;
+
+    /**
+     * 所属科室编码
+     */
+    private String deptCode;
+
+    /**
+     * 工号
+     */
+    private String jobNumber;
+
+    /**
+     * 身份证号码
+     */
+    private String idCard;
+
+    /**
+     * 现住地址
+     */
+    private String address;
+
+    /**
+     * 出生日期
+     */
+    private Date birthDate;
+
+    /**
+     * 户籍地址
+     */
+    private String regAddress;
+
+    /**
+     * 民族
+     */
+    private String nation;
+
+    /**
+     * 政治面貌
+     */
+    private String political;
+
+    /**
+     * 婚姻状况
+     */
+    private String marital;
+
+    /**
+     * 职称
+     */
+    private String title;
+
+    /**
+     * 学历
+     */
+    private String education;
+
+    /**
+     * 职工简介
+     */
+    private String intro;
+
+    /**
+     * 擅长疾病
+     */
+    private String expertise;
+
+    /**
+     * 签名图片路径
+     */
+    private String signatureImg;
+
+    /**
+     * 姓名
+     */
+    private String name;
 }

+ 2 - 0
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysRoleMapper.java

@@ -72,4 +72,6 @@ public interface SysRoleMapper extends BaseMapperPlus<SysRole, SysRoleVo> {
      */
     List<SysRoleVo> selectRolesByUserId(Long userId);
 
+    List<SysRoleVo> selectRolesByUserIds(List<Long> userIdList);
+
 }

+ 17 - 0
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/IQiNiuContentService.java

@@ -0,0 +1,17 @@
+package org.dromara.system.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import org.dromara.system.domain.SysOss;
+import org.springframework.web.multipart.MultipartFile;
+
+/**
+ * <p>
+ * 文件上传 服务类
+ * </p>
+ *
+ * @author tanSir
+ * @since 2021-04-16
+ */
+public interface IQiNiuContentService extends IService<SysOss> {
+    SysOss upload(MultipartFile file);
+}

+ 1 - 1
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysRoleService.java

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

+ 131 - 0
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/QiNiuContentServiceImpl.java

@@ -0,0 +1,131 @@
+package org.dromara.system.service.impl;
+
+
+import cn.hutool.core.date.DatePattern;
+import cn.hutool.core.date.DateUtil;
+import cn.hutool.core.date.LocalDateTimeUtil;
+import cn.hutool.core.map.MapUtil;
+import cn.hutool.core.util.ObjUtil;
+import cn.hutool.core.util.StrUtil;
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.toolkit.IdWorker;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.qiniu.http.Response;
+import com.qiniu.storage.Configuration;
+import com.qiniu.storage.UploadManager;
+import com.qiniu.storage.model.DefaultPutRet;
+import com.qiniu.util.Auth;
+import jakarta.annotation.Resource;
+import org.dromara.common.core.constant.BizConst;
+import org.dromara.common.core.exception.ServiceException;
+import org.dromara.common.core.utils.QiNiuUtil;
+import org.dromara.common.core.utils.file.FileUtil;
+import org.dromara.system.domain.SysOss;
+import org.dromara.system.domain.vo.SysDictDataVo;
+import org.dromara.system.mapper.SysOssMapper;
+import org.dromara.system.service.IQiNiuContentService;
+import org.dromara.system.service.ISysDictDataService;
+import org.jetbrains.annotations.Nullable;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.stereotype.Service;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * <p>
+ * 文件上传 服务实现类
+ * </p>
+ *
+ * @author tanSir
+ * @since 2021-04-16
+ */
+@Service
+public class QiNiuContentServiceImpl extends ServiceImpl<SysOssMapper, SysOss> implements IQiNiuContentService {
+    @Resource
+    private ISysDictDataService sysDictItemService;
+
+    @Resource
+    private SysOssMapper qiNiuContentMapper;
+
+    @Resource
+    private RedisTemplate redisTemplate;
+
+
+    /**
+     * 文件上传, 自定义路径前缀
+     *
+     * @return
+     */
+    @Override
+    public SysOss upload(MultipartFile file) {
+        String prefix = "upload/" + DateUtil.format(LocalDateTimeUtil.now(), DatePattern.PURE_DATE_PATTERN) + "/";
+        JSONObject qiNiuConfig = getDynamicQiNiuConfig();
+        FileUtil.checkSize(qiNiuConfig.getInteger(BizConst.QNY_MAX_SIZE), file.getSize());
+        // 构造一个带指定Zone对象的配置类
+        Configuration cfg = new Configuration(QiNiuUtil.getRegion(qiNiuConfig.getString(BizConst.QNY_ZONE)));
+        UploadManager uploadManager = new UploadManager(cfg);
+        Auth auth = Auth.create(qiNiuConfig.getString(BizConst.QNY_ACCESS_KEY), qiNiuConfig.getString(BizConst.QNY_SECRET_KEY));
+        String upToken = auth.uploadToken(qiNiuConfig.getString(BizConst.QNY_BUCKET_NAME));
+        try {
+            Long nextId = IdWorker.getId();
+            String name = getPrefix(prefix) + nextId + "." + FileUtil.extName(file.getOriginalFilename());
+            Response response = uploadManager.put(file.getBytes(), name, upToken);
+            // 解析上传成功的结果
+            DefaultPutRet putRet = JSON.parseObject(response.bodyString(), DefaultPutRet.class);
+            // 存入数据库
+            SysOss qiniuContent = new SysOss();
+            qiniuContent.setFileName(name);
+            qiniuContent.setFileSuffix(FileUtil.getExtensionName(putRet.key));
+//            qiniuContent.setBucket(qiNiuConfig.getString(BizConst.QNY_BUCKET_NAME));
+            qiniuContent.setOriginalName(FileUtil.getFileNameNoEx(file.getOriginalFilename()));
+            qiniuContent.setUrl(qiNiuConfig.getString(BizConst.QNY_STATIC_DOMAIN) + putRet.key);
+//            qiniuContent.setFileSize(FileUtil.getSize(file.getSize()));
+            qiniuContent.setUpdateTime(DateUtil.date());
+            qiniuContent.setOssId(nextId);
+            qiNiuContentMapper.insert(qiniuContent);
+            return qiniuContent;
+        } catch (Exception e) {
+            throw new ServiceException(e.getMessage());
+        }
+    }
+
+
+    private String getPrefix(String prefix) {
+        if (StrUtil.isBlank(prefix)) {
+            prefix = "";
+        } else {
+            String separator = "/";
+            if (!prefix.endsWith(separator)) {
+                prefix += separator;
+            }
+            if (prefix.startsWith(separator)) {
+                prefix = prefix.substring(1);
+            }
+        }
+        return prefix;
+    }
+
+
+    @Nullable
+    private JSONObject getDynamicQiNiuConfig() {
+        Object qnyConfig = redisTemplate.opsForValue().get(BizConst.QNY_CONFIG_CACHE);
+        if (ObjUtil.isNull(qnyConfig)) {
+            Map<String, SysDictDataVo> dictMap = sysDictItemService.selectMapByType(BizConst.QNY_CONFIG).getData();
+            if (MapUtil.isEmpty(dictMap)) {
+                throw new ServiceException("oss配置不存在!");
+            }
+            JSONObject jsonObject = new JSONObject();
+            dictMap.forEach((k,v)->{
+                jsonObject.put(k,v.getDictValue());
+            });
+            redisTemplate.opsForValue().set(BizConst.QNY_CONFIG_CACHE, JSON.toJSONString(jsonObject));
+            redisTemplate.expire(BizConst.QNY_CONFIG_CACHE, 30, TimeUnit.MINUTES);
+            return jsonObject;
+        }
+
+        return JSONObject.parseObject(String.valueOf(qnyConfig));
+    }
+}

+ 13 - 6
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysDeptServiceImpl.java

@@ -140,12 +140,15 @@ public class SysDeptServiceImpl implements ISysDeptService, DeptService {
             Long parentId = d.getParentId();
             SysDeptVo sysDeptVo = StreamUtils.findFirst(depts, it -> it.getDeptId().longValue() == parentId);
             if (ObjectUtil.isNull(sysDeptVo)) {
-                List<Tree<Long>> trees = TreeBuildUtils.build(depts, parentId, (dept, tree) ->
-                    tree.setId(dept.getDeptId())
-                        .setParentId(dept.getParentId())
-                        .setName(dept.getDeptName())
-                        .setWeight(dept.getOrderNum())
-                        .putExtra("disabled", SystemConstants.DISABLE.equals(dept.getStatus())));
+                List<Tree<Long>> trees = TreeBuildUtils.build(depts, parentId, (dept, tree) -> {
+                        tree.setId(dept.getDeptId())
+                            .setParentId(dept.getParentId())
+                            .setName(dept.getDeptName())
+                            .setWeight(dept.getOrderNum())
+                            .putExtra("disabled", SystemConstants.DISABLE.equals(dept.getStatus()));
+                        tree.putExtra("deptCategory", dept.getDeptCategory());
+                    }
+                );
                 Tree<Long> tree = StreamUtils.findFirst(trees, it -> it.getId().longValue() == d.getDeptId());
                 treeList.add(tree);
             }
@@ -427,6 +430,10 @@ public class SysDeptServiceImpl implements ISysDeptService, DeptService {
         return baseMapper.deleteById(deptId);
     }
 
+    @Caching(evict = {
+        @CacheEvict(cacheNames = CacheNames.SYS_DEPT, key = "#bo.deptId"),
+        @CacheEvict(cacheNames = CacheNames.SYS_DEPT_AND_CHILD, allEntries = true)
+    })
     @Override
     public int updateDeptStatus(SysDeptBo bo) {
         if (StrUtil.isBlank(bo.getStatus())) {

+ 1 - 1
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysDictDataServiceImpl.java

@@ -61,7 +61,7 @@ public class SysDictDataServiceImpl implements ISysDictDataService {
             return R.ok();
         }
 
-        return R.ok(dataList.stream().collect(Collectors.toMap(k1 -> k1.getDictValue(), k2 -> k2, (k1, k2) -> k1)));
+        return R.ok(dataList.stream().collect(Collectors.toMap(k1 -> k1.getDictLabel(), k2 -> k2, (k1, k2) -> k1)));
     }
 
     @Override

+ 6 - 2
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysRoleServiceImpl.java

@@ -164,9 +164,13 @@ public class SysRoleServiceImpl implements ISysRoleService, RoleService {
      * @return 选中角色ID列表
      */
     @Override
-    public List<Long> selectRoleListByUserId(Long userId) {
+    public Long selectRoleListByUserId(Long userId) {
         List<SysRoleVo> list = baseMapper.selectRolesByUserId(userId);
-        return StreamUtils.toList(list, SysRoleVo::getRoleId);
+        if(CollUtil.isEmpty(list)){
+            return null;
+        }
+//        return StreamUtils.toList(list, SysRoleVo::getRoleId);
+        return list.get(0).getRoleId();
     }
 
     /**

+ 24 - 3
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysUserServiceImpl.java

@@ -4,6 +4,7 @@ import cn.hutool.core.bean.BeanUtil;
 import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.convert.Convert;
 import cn.hutool.core.util.ArrayUtil;
+import cn.hutool.core.util.ObjUtil;
 import cn.hutool.core.util.ObjectUtil;
 import com.baomidou.mybatisplus.core.conditions.Wrapper;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
@@ -58,6 +59,19 @@ public class SysUserServiceImpl implements ISysUserService, UserService {
     @Override
     public TableDataInfo<SysUserVo> selectPageUserList(SysUserBo user, PageQuery pageQuery) {
         Page<SysUserVo> page = baseMapper.selectPageUserList(pageQuery.build(), this.buildQueryWrapper(user));
+
+        if(CollUtil.isNotEmpty(page.getRecords())){
+            List<Long> userIdList = page.getRecords().stream().map(SysUserVo::getUserId).collect(Collectors.toList());
+            Map<Long, SysRoleVo> roleMap = roleMapper.selectRolesByUserIds(userIdList).stream().collect(Collectors.toMap(k1 -> k1.getUserId(), k2 -> k2, (k1, k2) -> k1));
+            page.getRecords().forEach(r -> {
+                SysRoleVo vo = roleMap.get(r.getUserId());
+                if (ObjUtil.isNotNull(vo)) {
+                    r.setRoleId(vo.getRoleId());
+                    r.setRoleName(vo.getRoleName());
+                }
+            });
+        }
+
         return TableDataInfo.build(page);
     }
 
@@ -78,7 +92,6 @@ public class SysUserServiceImpl implements ISysUserService, UserService {
         wrapper.eq("u.del_flag", SystemConstants.NORMAL)
             .eq(ObjectUtil.isNotNull(user.getUserId()), "u.user_id", user.getUserId())
             .in(StringUtils.isNotBlank(user.getUserIds()), "u.user_id", StringUtils.splitTo(user.getUserIds(), Convert::toLong))
-            .like(StringUtils.isNotBlank(user.getUserName()), "u.user_name", user.getUserName())
             .like(StringUtils.isNotBlank(user.getNickName()), "u.nick_name", user.getNickName())
             .eq(StringUtils.isNotBlank(user.getStatus()), "u.status", user.getStatus())
             .like(StringUtils.isNotBlank(user.getPhonenumber()), "u.phonenumber", user.getPhonenumber())
@@ -89,7 +102,15 @@ public class SysUserServiceImpl implements ISysUserService, UserService {
                 List<Long> ids = StreamUtils.toList(deptList, SysDept::getDeptId);
                 ids.add(user.getDeptId());
                 w.in("u.dept_id", ids);
-            }).orderByAsc("u.user_id");
+            })
+            .and(StringUtils.isNotBlank(user.getUserName()), w -> {
+                w.like("u.user_name", user.getUserName())
+                    .or()
+                    .like("u.job_number", user.getUserName())
+                    .or()
+                    .like("u.name", user.getUserName());
+            })
+            .orderByAsc("u.user_id");
         if (StringUtils.isNotBlank(user.getExcludeUserIds())) {
             wrapper.notIn("u.user_id", StringUtils.splitTo(user.getExcludeUserIds(), Convert::toLong));
         }
@@ -429,7 +450,7 @@ public class SysUserServiceImpl implements ISysUserService, UserService {
      * @param clear 清除已存在的关联数据
      */
     private void insertUserRole(SysUserBo user, boolean clear) {
-        this.insertUserRole(user.getUserId(), user.getRoleIds(), clear);
+        this.insertUserRole(user.getUserId(), new Long[]{Long.valueOf(user.getRoleIds())}, clear);
     }
 
     /**

+ 16 - 0
ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysRoleMapper.xml

@@ -52,6 +52,22 @@
         WHERE r.del_flag = '0' and r.role_id in (select role_id from sys_user_role where user_id = #{userId})
     </select>
 
+
+    <select id="selectRolesByUserIds" parameterType="list" resultMap="SysRoleResult">
+        select r.role_id,
+               r.role_name,
+               r.role_key,
+               r.role_sort,
+               r.data_scope,
+               r.status,
+               ur.user_id
+        from sys_role r join sys_user_role ur on r.role_id = ur.role_id
+        WHERE r.del_flag = '0' and ur.user_id in
+            <foreach collection="list" item="item" close=")" separator="," open="(">
+                #{item}
+            </foreach>
+    </select>
+
     <select id="selectRoleById" resultMap="SysRoleResult">
         <include refid="selectRoleVo"/>
         WHERE r.del_flag = '0' and r.role_id = #{roleId}

+ 2 - 2
ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml

@@ -17,8 +17,8 @@
             ${ew.getSqlSelect}
         </if>
         <if test="ew.getSqlSelect == null">
-            u.user_id, u.dept_id, u.nick_name, u.user_name, u.email, u.avatar, u.phonenumber, u.sex,
-            u.status, u.del_flag, u.login_ip, u.login_date, u.create_by, u.create_time, u.remark
+            u.user_id, u.dept_id, u.name, u.user_name, u.email, u.avatar, u.phonenumber, u.sex,
+            u.status, u.del_flag, u.login_ip, u.login_date, u.create_by, u.create_time, u.remark,u.job_number
         </if>
         from sys_user u
         ${ew.getCustomSqlSegment}

+ 18 - 0
script/sql/biz/update.sql

@@ -0,0 +1,18 @@
+ALTER TABLE sys_user
+ADD COLUMN name VARCHAR(100) COMMENT '姓名',
+ADD COLUMN alias VARCHAR(50) COMMENT '别名',
+ADD COLUMN role VARCHAR(50) COMMENT '角色',
+ADD COLUMN dept_code VARCHAR(50) COMMENT '所属科室编码',
+ADD COLUMN job_number VARCHAR(50) COMMENT '工号',
+ADD COLUMN id_card VARCHAR(18) COMMENT '身份证号码',
+ADD COLUMN address VARCHAR(200) COMMENT '现住地址',
+ADD COLUMN birth_date DATE COMMENT '出生日期',
+ADD COLUMN reg_address VARCHAR(200) COMMENT '户籍地址',
+ADD COLUMN nation VARCHAR(20) COMMENT '民族',
+ADD COLUMN political VARCHAR(20) COMMENT '政治面貌',
+ADD COLUMN marital VARCHAR(10) COMMENT '婚姻状况',
+ADD COLUMN title VARCHAR(50) COMMENT '职称',
+ADD COLUMN education VARCHAR(20) COMMENT '学历',
+ADD COLUMN intro TEXT COMMENT '职工简介',
+ADD COLUMN expertise VARCHAR(200) COMMENT '擅长疾病',
+ADD COLUMN signature_img VARCHAR(200) COMMENT '签名图片路径';