Procházet zdrojové kódy

Merge remote-tracking branch 'upstream/master'

zyj před 5 měsíci
rodič
revize
24791e53bf
28 změnil soubory, kde provedl 221 přidání a 70 odebrání
  1. 2 2
      README.md
  2. binární
      doc/若依环境使用手册.docx
  3. 5 5
      pom.xml
  4. 1 1
      ruoyi-admin/pom.xml
  5. 1 2
      ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CommonController.java
  6. 10 4
      ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysProfileController.java
  7. 1 1
      ruoyi-admin/src/main/resources/application.yml
  8. 1 1
      ruoyi-common/pom.xml
  9. 36 8
      ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUploadUtils.java
  10. 13 1
      ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUtils.java
  11. 2 6
      ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelUtil.java
  12. 1 1
      ruoyi-framework/pom.xml
  13. 2 0
      ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysRegisterService.java
  14. 1 1
      ruoyi-generator/pom.xml
  15. 1 1
      ruoyi-quartz/pom.xml
  16. 3 3
      ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/ScheduleUtils.java
  17. 1 1
      ruoyi-system/pom.xml
  18. 4 4
      ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserMapper.java
  19. 4 4
      ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserService.java
  20. 6 6
      ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java
  21. 11 9
      ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml
  22. 1 1
      ruoyi-ui/package.json
  23. 8 2
      ruoyi-ui/src/layout/components/AppMain.vue
  24. 35 0
      ruoyi-ui/src/layout/components/Copyright/index.vue
  25. 18 1
      ruoyi-ui/src/layout/components/Settings/index.vue
  26. 11 1
      ruoyi-ui/src/settings.js
  27. 4 2
      ruoyi-ui/src/store/modules/settings.js
  28. 38 2
      ruoyi-ui/src/views/index.vue

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 2 - 2
README.md


binární
doc/若依环境使用手册.docx


+ 5 - 5
pom.xml

@@ -6,14 +6,14 @@
 	
     <groupId>com.ruoyi</groupId>
     <artifactId>ruoyi</artifactId>
-    <version>3.8.9</version>
+    <version>3.9.0</version>
 
     <name>ruoyi</name>
     <url>http://www.ruoyi.vip</url>
     <description>若依管理系统</description>
     
     <properties>
-        <ruoyi.version>3.8.9</ruoyi.version>
+        <ruoyi.version>3.9.0</ruoyi.version>
         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
         <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
         <java.version>1.8</java.version>
@@ -24,14 +24,14 @@
         <swagger.version>3.0.0</swagger.version>
         <kaptcha.version>2.3.3</kaptcha.version>
         <pagehelper.boot.version>1.4.7</pagehelper.boot.version>
-        <fastjson.version>2.0.53</fastjson.version>
-        <oshi.version>6.8.1</oshi.version>
+        <fastjson.version>2.0.57</fastjson.version>
+        <oshi.version>6.8.2</oshi.version>
         <commons.io.version>2.19.0</commons.io.version>
         <poi.version>4.1.2</poi.version>
         <velocity.version>2.3</velocity.version>
         <jwt.version>0.9.1</jwt.version>
         <!-- override dependency version -->
-        <tomcat.version>9.0.105</tomcat.version>
+        <tomcat.version>9.0.106</tomcat.version>
         <logback.version>1.2.13</logback.version>
         <spring-security.version>5.7.12</spring-security.version>
         <spring-framework.version>5.3.39</spring-framework.version>

+ 1 - 1
ruoyi-admin/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>ruoyi</artifactId>
         <groupId>com.ruoyi</groupId>
-        <version>3.8.9</version>
+        <version>3.9.0</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
     <packaging>jar</packaging>

+ 1 - 2
ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CommonController.java

@@ -14,7 +14,6 @@ import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
 import org.springframework.web.multipart.MultipartFile;
 import com.ruoyi.common.config.RuoYiConfig;
-import com.ruoyi.common.constant.Constants;
 import com.ruoyi.common.core.domain.AjaxResult;
 import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.common.utils.file.FileUploadUtils;
@@ -148,7 +147,7 @@ public class CommonController
             // 本地资源路径
             String localPath = RuoYiConfig.getProfile();
             // 数据库资源地址
-            String downloadPath = localPath + StringUtils.substringAfter(resource, Constants.RESOURCE_PREFIX);
+            String downloadPath = localPath + FileUtils.stripPrefix(resource);
             // 下载名称
             String downloadName = StringUtils.substringAfterLast(downloadPath, "/");
             response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);

+ 10 - 4
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysProfileController.java

@@ -21,6 +21,7 @@ import com.ruoyi.common.utils.DateUtils;
 import com.ruoyi.common.utils.SecurityUtils;
 import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.common.utils.file.FileUploadUtils;
+import com.ruoyi.common.utils.file.FileUtils;
 import com.ruoyi.common.utils.file.MimeTypeUtils;
 import com.ruoyi.framework.web.service.TokenService;
 import com.ruoyi.system.service.ISysUserService;
@@ -94,7 +95,7 @@ public class SysProfileController extends BaseController
         String oldPassword = params.get("oldPassword");
         String newPassword = params.get("newPassword");
         LoginUser loginUser = getLoginUser();
-        String userName = loginUser.getUsername();
+        Long userId = loginUser.getUserId();
         String password = loginUser.getPassword();
         if (!SecurityUtils.matchesPassword(oldPassword, password))
         {
@@ -105,7 +106,7 @@ public class SysProfileController extends BaseController
             return error("新密码不能与旧密码相同");
         }
         newPassword = SecurityUtils.encryptPassword(newPassword);
-        if (userService.resetUserPwd(userName, newPassword) > 0)
+        if (userService.resetUserPwd(userId, newPassword) > 0)
         {
             // 更新缓存用户密码&密码最后更新时间
             loginUser.getUser().setPwdUpdateDate(DateUtils.getNowDate());
@@ -126,9 +127,14 @@ public class SysProfileController extends BaseController
         if (!file.isEmpty())
         {
             LoginUser loginUser = getLoginUser();
-            String avatar = FileUploadUtils.upload(RuoYiConfig.getAvatarPath(), file, MimeTypeUtils.IMAGE_EXTENSION);
-            if (userService.updateUserAvatar(loginUser.getUsername(), avatar))
+            String avatar = FileUploadUtils.upload(RuoYiConfig.getAvatarPath(), file, MimeTypeUtils.IMAGE_EXTENSION, true);
+            if (userService.updateUserAvatar(loginUser.getUserId(), avatar))
             {
+                String oldAvatar = loginUser.getUser().getAvatar();
+                if (StringUtils.isNotEmpty(oldAvatar))
+                {
+                    FileUtils.deleteFile(RuoYiConfig.getProfile() + FileUtils.stripPrefix(oldAvatar));
+                }
                 AjaxResult ajax = AjaxResult.success();
                 ajax.put("imgUrl", avatar);
                 // 更新缓存用户头像

+ 1 - 1
ruoyi-admin/src/main/resources/application.yml

@@ -3,7 +3,7 @@ ruoyi:
   # 名称
   name: RuoYi
   # 版本
-  version: 3.8.9
+  version: 3.9.0
   # 版权年份
   copyrightYear: 2025
   # 文件路径 示例( Windows配置D:/ruoyi/uploadPath,Linux配置 /home/ruoyi/uploadPath)

+ 1 - 1
ruoyi-common/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>ruoyi</artifactId>
         <groupId>com.ruoyi</groupId>
-        <version>3.8.9</version>
+        <version>3.9.0</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 

+ 36 - 8
ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUploadUtils.java

@@ -13,11 +13,12 @@ import com.ruoyi.common.exception.file.FileSizeLimitExceededException;
 import com.ruoyi.common.exception.file.InvalidExtensionException;
 import com.ruoyi.common.utils.DateUtils;
 import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.utils.uuid.IdUtils;
 import com.ruoyi.common.utils.uuid.Seq;
 
 /**
  * 文件上传工具类
- *
+ * 
  * @author ruoyi
  */
 public class FileUploadUtils
@@ -102,15 +103,35 @@ public class FileUploadUtils
             throws FileSizeLimitExceededException, IOException, FileNameLengthLimitExceededException,
             InvalidExtensionException
     {
-        int fileNamelength = Objects.requireNonNull(file.getOriginalFilename()).length();
-        if (fileNamelength > FileUploadUtils.DEFAULT_FILE_NAME_LENGTH)
+        return upload(baseDir, file, allowedExtension, false);
+    }
+    
+    /**
+     * 文件上传
+     *
+     * @param baseDir 相对应用的基目录
+     * @param file 上传的文件
+     * @param useCustomNaming 系统自定义文件名
+     * @param allowedExtension 上传文件类型
+     * @return 返回上传成功的文件名
+     * @throws FileSizeLimitExceededException 如果超出最大大小
+     * @throws FileNameLengthLimitExceededException 文件名太长
+     * @throws IOException 比如读写文件出错时
+     * @throws InvalidExtensionException 文件校验异常
+     */
+    public static final String upload(String baseDir, MultipartFile file, String[] allowedExtension, boolean useCustomNaming)
+            throws FileSizeLimitExceededException, IOException, FileNameLengthLimitExceededException,
+            InvalidExtensionException
+    {
+        int fileNameLength = Objects.requireNonNull(file.getOriginalFilename()).length();
+        if (fileNameLength > FileUploadUtils.DEFAULT_FILE_NAME_LENGTH)
         {
             throw new FileNameLengthLimitExceededException(FileUploadUtils.DEFAULT_FILE_NAME_LENGTH);
         }
 
         assertAllowed(file, allowedExtension);
 
-        String fileName = extractFilename(file);
+        String fileName = useCustomNaming ? uuidFilename(file) : extractFilename(file);
 
         String absPath = getAbsoluteFile(baseDir, fileName).getAbsolutePath();
         file.transferTo(Paths.get(absPath));
@@ -118,12 +139,19 @@ public class FileUploadUtils
     }
 
     /**
-     * 编码文件名
+     * 编码文件名(日期格式目录 + 原文件名 + 序列值 + 后缀)
      */
     public static final String extractFilename(MultipartFile file)
     {
-        return StringUtils.format("{}/{}_{}.{}", DateUtils.datePath(),
-                FilenameUtils.getBaseName(file.getOriginalFilename()), Seq.getId(Seq.uploadSeqType), getExtension(file));
+        return StringUtils.format("{}/{}_{}.{}", DateUtils.datePath(), FilenameUtils.getBaseName(file.getOriginalFilename()), Seq.getId(Seq.uploadSeqType), getExtension(file));
+    }
+
+    /**
+     * 编编码文件名(日期格式目录 + UUID + 后缀)
+     */
+    public static final String uuidFilename(MultipartFile file)
+    {
+        return StringUtils.format("{}/{}.{}", DateUtils.datePath(), IdUtils.fastSimpleUUID(), getExtension(file));
     }
 
     public static final File getAbsoluteFile(String uploadDir, String fileName) throws IOException
@@ -216,7 +244,7 @@ public class FileUploadUtils
 
     /**
      * 获取文件名的后缀
-     *
+     * 
      * @param file 表单文件
      * @return 后缀名
      */

+ 13 - 1
ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUtils.java

@@ -11,13 +11,14 @@ import java.net.URLEncoder;
 import java.nio.charset.StandardCharsets;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
+import org.apache.commons.io.FilenameUtils;
 import org.apache.commons.io.IOUtils;
 import org.apache.commons.lang3.ArrayUtils;
 import com.ruoyi.common.config.RuoYiConfig;
+import com.ruoyi.common.constant.Constants;
 import com.ruoyi.common.utils.DateUtils;
 import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.common.utils.uuid.IdUtils;
-import org.apache.commons.io.FilenameUtils;
 
 /**
  * 文件处理工具类
@@ -103,6 +104,17 @@ public class FileUtils
         return FileUploadUtils.getPathFileName(uploadDir, pathName);
     }
 
+    /**
+     * 移除路径中的请求前缀片段
+     * 
+     * @param filePath 文件路径
+     * @return 移除后的文件路径
+     */
+    public static String stripPrefix(String filePath)
+    {
+        return StringUtils.substringAfter(filePath, Constants.RESOURCE_PREFIX);
+    }
+
     /**
      * 删除文件
      * 

+ 2 - 6
ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelUtil.java

@@ -186,11 +186,6 @@ public class ExcelUtil<T>
      */
     private Map<Integer, Double> statistics = new HashMap<Integer, Double>();
 
-    /**
-     * 数字格式
-     */
-    private static final DecimalFormat DOUBLE_FORMAT = new DecimalFormat("######0.00");
-
     /**
      * 实体对象
      */
@@ -861,6 +856,7 @@ public class ExcelUtil<T>
         style = wb.createCellStyle();
         style.setAlignment(HorizontalAlignment.CENTER);
         style.setVerticalAlignment(VerticalAlignment.CENTER);
+        style.setDataFormat(dataFormat.getFormat("######0.00"));
         Font totalFont = wb.createFont();
         totalFont.setFontName("Arial");
         totalFont.setFontHeightInPoints((short) 10);
@@ -1442,7 +1438,7 @@ public class ExcelUtil<T>
             {
                 cell = row.createCell(key);
                 cell.setCellStyle(styles.get("total"));
-                cell.setCellValue(DOUBLE_FORMAT.format(statistics.get(key)));
+                cell.setCellValue(statistics.get(key));
             }
             statistics.clear();
         }

+ 1 - 1
ruoyi-framework/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>ruoyi</artifactId>
         <groupId>com.ruoyi</groupId>
-        <version>3.8.9</version>
+        <version>3.9.0</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 

+ 2 - 0
ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysRegisterService.java

@@ -10,6 +10,7 @@ import com.ruoyi.common.core.domain.model.RegisterBody;
 import com.ruoyi.common.core.redis.RedisCache;
 import com.ruoyi.common.exception.user.CaptchaException;
 import com.ruoyi.common.exception.user.CaptchaExpireException;
+import com.ruoyi.common.utils.DateUtils;
 import com.ruoyi.common.utils.MessageUtils;
 import com.ruoyi.common.utils.SecurityUtils;
 import com.ruoyi.common.utils.StringUtils;
@@ -76,6 +77,7 @@ public class SysRegisterService
         else
         {
             sysUser.setNickName(username);
+            sysUser.setPwdUpdateDate(DateUtils.getNowDate());
             sysUser.setPassword(SecurityUtils.encryptPassword(password));
             boolean regFlag = userService.registerUser(sysUser);
             if (!regFlag)

+ 1 - 1
ruoyi-generator/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>ruoyi</artifactId>
         <groupId>com.ruoyi</groupId>
-        <version>3.8.9</version>
+        <version>3.9.0</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 

+ 1 - 1
ruoyi-quartz/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>ruoyi</artifactId>
         <groupId>com.ruoyi</groupId>
-        <version>3.8.9</version>
+        <version>3.9.0</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 

+ 3 - 3
ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/ScheduleUtils.java

@@ -131,11 +131,11 @@ public class ScheduleUtils
         int count = StringUtils.countMatches(packageName, ".");
         if (count > 1)
         {
-            return StringUtils.containsAnyIgnoreCase(invokeTarget, Constants.JOB_WHITELIST_STR);
+            return StringUtils.startsWithAny(invokeTarget, Constants.JOB_WHITELIST_STR);
         }
         Object obj = SpringUtils.getBean(StringUtils.split(invokeTarget, ".")[0]);
         String beanPackageName = obj.getClass().getPackage().getName();
-        return StringUtils.containsAnyIgnoreCase(beanPackageName, Constants.JOB_WHITELIST_STR)
-                && !StringUtils.containsAnyIgnoreCase(beanPackageName, Constants.JOB_ERROR_STR);
+        return StringUtils.startsWithAny(beanPackageName, Constants.JOB_WHITELIST_STR)
+                && !StringUtils.startsWithAny(beanPackageName, Constants.JOB_ERROR_STR);
     }
 }

+ 1 - 1
ruoyi-system/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>ruoyi</artifactId>
         <groupId>com.ruoyi</groupId>
-        <version>3.8.9</version>
+        <version>3.9.0</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 

+ 4 - 4
ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserMapper.java

@@ -70,20 +70,20 @@ public interface SysUserMapper
     /**
      * 修改用户头像
      * 
-     * @param userName 用户名
+     * @param userId 用户ID
      * @param avatar 头像地址
      * @return 结果
      */
-    public int updateUserAvatar(@Param("userName") String userName, @Param("avatar") String avatar);
+    public int updateUserAvatar(@Param("userId") Long userId, @Param("avatar") String avatar);
 
     /**
      * 重置用户密码
      * 
-     * @param userName 用户名
+     * @param userId 用户ID
      * @param password 密码
      * @return 结果
      */
-    public int resetUserPwd(@Param("userName") String userName, @Param("password") String password);
+    public int resetUserPwd(@Param("userId") Long userId, @Param("password") String password);
 
     /**
      * 通过用户ID删除用户

+ 4 - 4
ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserService.java

@@ -155,11 +155,11 @@ public interface ISysUserService
     /**
      * 修改用户头像
      * 
-     * @param userName 用户名
+     * @param userId 用户ID
      * @param avatar 头像地址
      * @return 结果
      */
-    public boolean updateUserAvatar(String userName, String avatar);
+    public boolean updateUserAvatar(Long userId, String avatar);
 
     /**
      * 重置用户密码
@@ -172,11 +172,11 @@ public interface ISysUserService
     /**
      * 重置用户密码
      * 
-     * @param userName 用户名
+     * @param userId 用户ID
      * @param password 密码
      * @return 结果
      */
-    public int resetUserPwd(String userName, String password);
+    public int resetUserPwd(Long userId, String password);
 
     /**
      * 通过用户ID删除用户

+ 6 - 6
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java

@@ -344,14 +344,14 @@ public class SysUserServiceImpl implements ISysUserService
     /**
      * 修改用户头像
      * 
-     * @param userName 用户名
+     * @param userId 用户ID
      * @param avatar 头像地址
      * @return 结果
      */
     @Override
-    public boolean updateUserAvatar(String userName, String avatar)
+    public boolean updateUserAvatar(Long userId, String avatar)
     {
-        return userMapper.updateUserAvatar(userName, avatar) > 0;
+        return userMapper.updateUserAvatar(userId, avatar) > 0;
     }
 
     /**
@@ -369,14 +369,14 @@ public class SysUserServiceImpl implements ISysUserService
     /**
      * 重置用户密码
      * 
-     * @param userName 用户名
+     * @param userId 用户ID
      * @param password 密码
      * @return 结果
      */
     @Override
-    public int resetUserPwd(String userName, String password)
+    public int resetUserPwd(Long userId, String password)
     {
-        return userMapper.resetUserPwd(userName, password);
+        return userMapper.resetUserPwd(userId, password);
     }
 
     /**

+ 11 - 9
ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml

@@ -19,13 +19,13 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <result property="loginIp"       column="login_ip"        />
         <result property="loginDate"     column="login_date"      />
         <result property="pwdUpdateDate" column="pwd_update_date" />
-        <result property="createBy"     column="create_by"        />
-        <result property="createTime"   column="create_time"      />
-        <result property="updateBy"     column="update_by"        />
-        <result property="updateTime"   column="update_time"      />
-        <result property="remark"       column="remark"           />
-        <association property="dept"    javaType="SysDept"         resultMap="deptResult" />
-        <collection  property="roles"   javaType="java.util.List"  resultMap="RoleResult" />
+        <result property="createBy"      column="create_by"       />
+        <result property="createTime"    column="create_time"     />
+        <result property="updateBy"      column="update_by"       />
+        <result property="updateTime"    column="update_time"     />
+        <result property="remark"        column="remark"          />
+        <association property="dept"     javaType="SysDept"         resultMap="deptResult" />
+        <collection  property="roles"    javaType="java.util.List"  resultMap="RoleResult" />
     </resultMap>
 	
     <resultMap id="deptResult" type="SysDept">
@@ -155,6 +155,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  			<if test="sex != null and sex != ''">sex,</if>
  			<if test="password != null and password != ''">password,</if>
  			<if test="status != null and status != ''">status,</if>
+ 			<if test="pwdUpdateDate != null">pwd_update_date,</if>
  			<if test="createBy != null and createBy != ''">create_by,</if>
  			<if test="remark != null and remark != ''">remark,</if>
  			create_time
@@ -169,6 +170,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  			<if test="sex != null and sex != ''">#{sex},</if>
  			<if test="password != null and password != ''">#{password},</if>
  			<if test="status != null and status != ''">#{status},</if>
+ 			<if test="pwdUpdateDate != null">#{pwdUpdateDate},</if>
  			<if test="createBy != null and createBy != ''">#{createBy},</if>
  			<if test="remark != null and remark != ''">#{remark},</if>
  			current_timestamp
@@ -200,11 +202,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 	</update>
 	
 	<update id="updateUserAvatar" parameterType="SysUser">
- 		update sys_user set avatar = #{avatar} where user_name = #{userName}
+ 		update sys_user set avatar = #{avatar} where user_id = #{userId}
 	</update>
 	
 	<update id="resetUserPwd" parameterType="SysUser">
- 		update sys_user set pwd_update_date = sysdate(), password = #{password} where user_name = #{userName}
+ 		update sys_user set pwd_update_date = sysdate(), password = #{password} where user_id = #{userId}
 	</update>
 	
 	<delete id="deleteUserById" parameterType="Long">

+ 1 - 1
ruoyi-ui/package.json

@@ -1,6 +1,6 @@
 {
   "name": "ruoyi",
-  "version": "3.8.9",
+  "version": "3.9.0",
   "description": "若依管理系统",
   "author": "若依",
   "license": "MIT",

+ 8 - 2
ruoyi-ui/src/layout/components/AppMain.vue

@@ -6,15 +6,17 @@
       </keep-alive>
     </transition>
     <iframe-toggle />
+    <copyright />
   </section>
 </template>
 
 <script>
+import copyright from "./Copyright/index"
 import iframeToggle from "./IframeToggle/index"
 
 export default {
   name: 'AppMain',
-  components: { iframeToggle },
+  components: { iframeToggle, copyright },
   computed: {
     cachedViews() {
       return this.$store.state.tagsView.cachedViews
@@ -33,7 +35,7 @@ export default {
   },
   methods: {
     addIframe() {
-      const {name} = this.$route
+      const { name } = this.$route
       if (name && this.$route.meta.link) {
         this.$store.dispatch('tagsView/addIframeView', this.$route)
       }
@@ -51,6 +53,10 @@ export default {
   overflow: hidden;
 }
 
+.app-main:has(.copyright) {
+  padding-bottom: 36px;
+}
+
 .fixed-header + .app-main {
   padding-top: 50px;
 }

+ 35 - 0
ruoyi-ui/src/layout/components/Copyright/index.vue

@@ -0,0 +1,35 @@
+<template>
+  <footer v-if="visible" class="copyright">
+    <span>{{ content }}</span>
+  </footer>
+</template>
+
+<script>
+export default {
+  computed: {
+    visible() {
+      return this.$store.state.settings.footerVisible
+    },
+    content() {
+      return this.$store.state.settings.footerContent
+    }
+  }
+}
+</script>
+
+<style scoped>
+.copyright {
+  position: fixed;
+  bottom: 0;
+  left: 0;
+  right: 0;
+  height: 36px;
+  padding: 10px 20px;
+  text-align: right;
+  background-color: #f8f8f8;
+  color: #666;
+  font-size: 14px;
+  border-top: 1px solid #e7e7e7;
+  z-index: 999;
+}
+</style>

+ 18 - 1
ruoyi-ui/src/layout/components/Settings/index.vue

@@ -1,5 +1,5 @@
 <template>
-  <el-drawer size="280px" :visible="showSettings" :with-header="false" :append-to-body="true" :before-close="closeSetting">
+  <el-drawer size="280px" :visible="showSettings" :with-header="false" :append-to-body="true" :before-close="closeSetting" :lock-scroll="false">
     <div class="drawer-container">
       <div>
         <div class="setting-drawer-content">
@@ -69,6 +69,11 @@
           <el-switch v-model="dynamicTitle" class="drawer-switch" />
         </div>
 
+        <div class="drawer-item">
+          <span>底部版权</span>
+          <el-switch v-model="footerVisible" class="drawer-switch" />
+        </div>
+
         <el-divider/>
 
         <el-button size="small" type="primary" plain icon="el-icon-document-add" @click="saveSetting">保存配置</el-button>
@@ -163,6 +168,17 @@ export default {
         this.$store.dispatch('settings/setTitle', this.$store.state.settings.title)
       }
     },
+    footerVisible: {
+      get() {
+        return this.$store.state.settings.footerVisible
+      },
+      set(val) {
+        this.$store.dispatch('settings/changeSetting', {
+          key: 'footerVisible',
+          value: val
+        })
+      }
+    }
   },
   methods: {
     themeChange(val) {
@@ -196,6 +212,7 @@ export default {
             "fixedHeader":${this.fixedHeader},
             "sidebarLogo":${this.sidebarLogo},
             "dynamicTitle":${this.dynamicTitle},
+            "footerVisible":${this.footerVisible},
             "sideTheme":"${this.sideTheme}",
             "theme":"${this.theme}"
           }`

+ 11 - 1
ruoyi-ui/src/settings.js

@@ -42,5 +42,15 @@ module.exports = {
   /**
    * 是否显示动态标题
    */
-  dynamicTitle: false
+  dynamicTitle: false,
+
+  /**
+   * 是否显示底部版权
+   */
+  footerVisible: false,
+
+  /**
+   * 底部版权文本内容
+   */
+  footerContent: 'Copyright © 2018-2025 RuoYi. All Rights Reserved.'
 }

+ 4 - 2
ruoyi-ui/src/store/modules/settings.js

@@ -1,7 +1,7 @@
 import defaultSettings from '@/settings'
 import { useDynamicTitle } from '@/utils/dynamicTitle'
 
-const { sideTheme, showSettings, topNav, tagsView, tagsIcon, fixedHeader, sidebarLogo, dynamicTitle } = defaultSettings
+const { sideTheme, showSettings, topNav, tagsView, tagsIcon, fixedHeader, sidebarLogo, dynamicTitle, footerVisible, footerContent } = defaultSettings
 
 const storageSetting = JSON.parse(localStorage.getItem('layout-setting')) || ''
 const state = {
@@ -14,7 +14,9 @@ const state = {
   tagsIcon: storageSetting.tagsIcon === undefined ? tagsIcon : storageSetting.tagsIcon,
   fixedHeader: storageSetting.fixedHeader === undefined ? fixedHeader : storageSetting.fixedHeader,
   sidebarLogo: storageSetting.sidebarLogo === undefined ? sidebarLogo : storageSetting.sidebarLogo,
-  dynamicTitle: storageSetting.dynamicTitle === undefined ? dynamicTitle : storageSetting.dynamicTitle
+  dynamicTitle: storageSetting.dynamicTitle === undefined ? dynamicTitle : storageSetting.dynamicTitle,
+  footerVisible: storageSetting.footerVisible === undefined ? footerVisible : storageSetting.footerVisible,
+  footerContent: footerContent
 }
 const mutations = {
   CHANGE_SETTING: (state, { key, value }) => {

+ 38 - 2
ruoyi-ui/src/views/index.vue

@@ -87,7 +87,7 @@
               <s> 满104748341 </s> <s> 满160110482 </s> <s> 满170801498 </s> <s> 满108482800 </s> 
               <s> 满101046199 </s> <s> 满136919097 </s> <s> 满143961921 </s> <s> 满174951577 </s> 
               <s> 满161281055 </s> <s> 满138988063 </s> <s> 满151450850 </s> <s> 满224622315 </s>
-              <s> 满287842588 </s> <s> 满187944233 </s> <a href="http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=G6r5KGCaa3pqdbUSXNIgYloyb8e0_L0D&authKey=4w8tF1eGW7%2FedWn%2FHAypQksdrML%2BDHolQSx7094Agm7Luakj9EbfPnSTxSi2T1LQ&noverify=0&group_code=228578329" target="_blank">228578329</a>
+              <s> 满287842588 </s> <s> 满187944233 </s> <s> 满228578329 </s> <a href="http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=GsOo-OLz53J8y_9TPoO6XXSGNRTgbFxA&authKey=R7Uy%2Feq%2BZsoKNqHvRKhiXpypW7DAogoWapOawUGHokJSBIBIre2%2FoiAZeZBSLuBc&noverify=0&group_code=191164766" target="_blank">191164766</a>
             </p>
             <p>
               <i class="el-icon-chat-dot-round"></i> 微信:<a
@@ -111,6 +111,42 @@
             <span>更新日志</span>
           </div>
           <el-collapse accordion>
+            <el-collapse-item title="v3.9.0 - 2025-05-28">
+              <ol>
+                <li>优化菜单搜索查询页</li>
+                <li>导航栏显示昵称&设置</li>
+                <li>菜单管理新增路由名称</li>
+                <li>添加底部版权信息&开关</li>
+                <li>分配角色禁用不允许勾选</li>
+                <li>Excel导入导出支持多图片</li>
+                <li>添加页签图标显示开关功能</li>
+                <li>上传组件新增拖动排序属性</li>
+                <li>显隐列组件支持全选/全不选</li>
+                <li>初始密码支持自定义修改策略</li>
+                <li>账号密码支持自定义更新周期</li>
+                <li>代码生成列表支持按时间排序</li>
+                <li>支持富文本复制粘贴图片上传至url</li>
+                <li>支持文件&图片组件自定义地址&参数</li>
+                <li>升级tomcat到最新版本9.0.105</li>
+                <li>升级oshi到最新版本6.8.1</li>
+                <li>升级fastjson到最新版2.0.57</li>
+                <li>升级commons.io到最新版本2.19.0</li>
+                <li>package.json移除runjs依赖</li>
+                <li>package.json移除eslint依赖</li>
+                <li>package.json移除vue-meta依赖</li>
+                <li>修复代码生成主子表校验必填失效问题</li>
+                <li>优化前端树结构性能问题</li>
+                <li>优化前端处理路由函数代码</li>
+                <li>优化文件上传组件新增类型</li>
+                <li>优化顶部菜单搜索栏为多层级显示</li>
+                <li>优化文件&图片上传组件新增disabled属性</li>
+                <li>优化空指针异常时无法获取错误信息问题</li>
+                <li>优化定时任务字符包含多个括号导致数据错误</li>
+                <li>优化登录&注册页表头使用VUE_APP_TITLE配置值</li>
+                <li>优化导出Excel日期格式双击离开后与设定的格式不一致问题</li>
+                <li>其他细节优化</li>
+              </ol>
+            </el-collapse-item>
             <el-collapse-item title="v3.8.9 - 2024-12-30">
               <ol>
                 <li>用户管理支持分栏拖动</li>
@@ -1023,7 +1059,7 @@ export default {
   data() {
     return {
       // 版本号
-      version: "3.8.9"
+      version: "3.9.0"
     }
   },
   methods: {

Některé soubory nejsou zobrazeny, neboť je v těchto rozdílových datech změněno mnoho souborů