Selaa lähdekoodia

Merge remote-tracking branch 'upstream/master'

zyj 1 vuosi sitten
vanhempi
sitoutus
e32dd01d3b

+ 4 - 5
README.md

@@ -22,11 +22,11 @@
 <p align="center">
 	<img alt="logo" src="https://oscimg.oschina.net/oscnet/up-d3d0a9303e11d522a06cd263f3079027715.png">
 </p>
-<h1 align="center" style="margin: 30px 0 30px; font-weight: bold;">RuoYi v3.8.8</h1>
+<h1 align="center" style="margin: 30px 0 30px; font-weight: bold;">RuoYi v3.8.9</h1>
 <h4 align="center">基于SpringBoot+Vue前后端分离的Java快速开发框架</h4>
 <p align="center">
 	<a href="https://gitee.com/y_project/RuoYi-Vue/stargazers"><img src="https://gitee.com/y_project/RuoYi-Vue/badge/star.svg?theme=dark"></a>
-	<a href="https://gitee.com/y_project/RuoYi-Vue"><img src="https://img.shields.io/badge/RuoYi-v3.8.8-brightgreen.svg"></a>
+	<a href="https://gitee.com/y_project/RuoYi-Vue"><img src="https://img.shields.io/badge/RuoYi-v3.8.9-brightgreen.svg"></a>
 	<a href="https://gitee.com/y_project/RuoYi-Vue/blob/master/LICENSE"><img src="https://img.shields.io/github/license/mashape/apistatus.svg"></a>
 </p>
 
@@ -38,11 +38,10 @@
 * 权限认证使用Jwt,支持多终端认证系统。
 * 支持加载动态权限菜单,多方式轻松权限控制。
 * 高效率开发,使用代码生成器可以一键生成前后端代码。
-* 提供了技术栈([Vue3](https://v3.cn.vuejs.org) [Element Plus](https://element-plus.org/zh-CN) [Vite](https://cn.vitejs.dev))版本[RuoYi-Vue3](https://github.com/yangzongzhuan/RuoYi-Vue3),保持同步更新。
-* 提供了单应用版本[RuoYi-Vue-fast](https://github.com/yangzongzhuan/RuoYi-Vue-fast),Oracle版本[RuoYi-Vue-Oracle](https://github.com/yangzongzhuan/RuoYi-Vue-Oracle),保持同步更新。
+* 提供了技术栈([Vue3](https://v3.cn.vuejs.org) [Element Plus](https://element-plus.org/zh-CN) [Vite](https://cn.vitejs.dev))版本[RuoYi-Vue3](https://gitcode.com/yangzongzhuan/RuoYi-Vue3),保持同步更新。
+* 提供了单应用版本[RuoYi-Vue-fast](https://gitcode.com/yangzongzhuan/RuoYi-Vue-fast),Oracle版本[RuoYi-Vue-Oracle](https://gitcode.com/yangzongzhuan/RuoYi-Vue-Oracle),保持同步更新。
 * 不分离版本,请移步[RuoYi](https://gitee.com/y_project/RuoYi),微服务版本,请移步[RuoYi-Cloud](https://gitee.com/y_project/RuoYi-Cloud)
 * 阿里云折扣场:[点我进入](http://aly.ruoyi.vip),腾讯云秒杀场:[点我进入](http://txy.ruoyi.vip)&nbsp;&nbsp;
-* 阿里云优惠券:[点我领取](https://www.aliyun.com/minisite/goods?userCode=brki8iof&share_source=copy_link),腾讯云优惠券:[点我领取](https://cloud.tencent.com/redirect.php?redirect=1025&cps_key=198c8df2ed259157187173bc7f4f32fd&from=console)&nbsp;&nbsp;
 
 ## 内置功能
 

+ 2 - 2
pom.xml

@@ -6,14 +6,14 @@
 	
     <groupId>com.ruoyi</groupId>
     <artifactId>ruoyi</artifactId>
-    <version>3.8.8</version>
+    <version>3.8.9</version>
 
     <name>ruoyi</name>
     <url>http://www.ruoyi.vip</url>
     <description>若依管理系统</description>
     
     <properties>
-        <ruoyi.version>3.8.8</ruoyi.version>
+        <ruoyi.version>3.8.9</ruoyi.version>
         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
         <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
         <java.version>1.8</java.version>

+ 1 - 1
ruoyi-admin/pom.xml

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

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

@@ -1,5 +1,6 @@
 package com.ruoyi.web.controller.system;
 
+import java.util.Map;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.PostMapping;
@@ -87,8 +88,10 @@ public class SysProfileController extends BaseController
      */
     @Log(title = "个人信息", businessType = BusinessType.UPDATE)
     @PutMapping("/updatePwd")
-    public AjaxResult updatePwd(String oldPassword, String newPassword)
+    public AjaxResult updatePwd(@RequestBody Map<String, String> params)
     {
+        String oldPassword = params.get("oldPassword");
+        String newPassword = params.get("newPassword");
         LoginUser loginUser = getLoginUser();
         String userName = loginUser.getUsername();
         String password = loginUser.getPassword();

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

@@ -3,7 +3,7 @@ ruoyi:
   # 名称
   name: RuoYi
   # 版本
-  version: 3.8.8
+  version: 3.8.9
   # 版权年份
   copyrightYear: 2024
   # 文件路径 示例( 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.8</version>
+        <version>3.8.9</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 

+ 16 - 0
ruoyi-common/src/main/java/com/ruoyi/common/core/domain/TreeSelect.java

@@ -4,8 +4,10 @@ import java.io.Serializable;
 import java.util.List;
 import java.util.stream.Collectors;
 import com.fasterxml.jackson.annotation.JsonInclude;
+import com.ruoyi.common.constant.UserConstants;
 import com.ruoyi.common.core.domain.entity.SysDept;
 import com.ruoyi.common.core.domain.entity.SysMenu;
+import com.ruoyi.common.utils.StringUtils;
 
 /**
  * Treeselect树结构实体类
@@ -22,6 +24,9 @@ public class TreeSelect implements Serializable
     /** 节点名称 */
     private String label;
 
+    /** 节点禁用 */
+    private boolean disabled = false;
+
     /** 子节点 */
     @JsonInclude(JsonInclude.Include.NON_EMPTY)
     private List<TreeSelect> children;
@@ -35,6 +40,7 @@ public class TreeSelect implements Serializable
     {
         this.id = dept.getDeptId();
         this.label = dept.getDeptName();
+        this.disabled = StringUtils.equals(UserConstants.DEPT_DISABLE, dept.getStatus());
         this.children = dept.getChildren().stream().map(TreeSelect::new).collect(Collectors.toList());
     }
 
@@ -65,6 +71,16 @@ public class TreeSelect implements Serializable
         this.label = label;
     }
 
+    public boolean isDisabled()
+    {
+        return disabled;
+    }
+
+    public void setDisabled(boolean disabled)
+    {
+        this.disabled = disabled;
+    }
+
     public List<TreeSelect> getChildren()
     {
         return children;

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

@@ -310,11 +310,23 @@ public class ExcelUtil<T>
      * @return 转换后集合
      */
     public List<T> importExcel(InputStream is)
+    {
+        return importExcel(is, 0);
+    }
+
+    /**
+     * 对excel表单默认第一个索引名转换成list
+     * 
+     * @param is 输入流
+     * @param titleNum 标题占用行数
+     * @return 转换后集合
+     */
+    public List<T> importExcel(InputStream is, int titleNum)
     {
         List<T> list = null;
         try
         {
-            list = importExcel(is, 0);
+            list = importExcel(StringUtils.EMPTY, is, titleNum);
         }
         catch (Exception e)
         {
@@ -328,18 +340,6 @@ public class ExcelUtil<T>
         return list;
     }
 
-    /**
-     * 对excel表单默认第一个索引名转换成list
-     * 
-     * @param is 输入流
-     * @param titleNum 标题占用行数
-     * @return 转换后集合
-     */
-    public List<T> importExcel(InputStream is, int titleNum) throws Exception
-    {
-        return importExcel(StringUtils.EMPTY, is, titleNum);
-    }
-
     /**
      * 对excel表单指定表格索引名转换成list
      * 

+ 1 - 1
ruoyi-common/src/main/java/com/ruoyi/common/utils/sql/SqlUtil.java

@@ -13,7 +13,7 @@ public class SqlUtil
     /**
      * 定义常用的 sql关键字
      */
-    public static String SQL_REGEX = "and |extractvalue|updatexml|sleep|exec |insert |select |delete |update |drop |count |chr |mid |master |truncate |char |declare |or |union |like |+|/*|user()";
+    public static String SQL_REGEX = "\u000B|and |extractvalue|updatexml|sleep|exec |insert |select |delete |update |drop |count |chr |mid |master |truncate |char |declare |or |union |like |+|/*|user()";
 
     /**
      * 仅支持字母、数字、下划线、空格、逗号、小数点(支持多个字段排序)

+ 1 - 1
ruoyi-framework/pom.xml

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

+ 1 - 1
ruoyi-generator/pom.xml

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

+ 16 - 2
ruoyi-generator/src/main/java/com/ruoyi/generator/config/GenConfig.java

@@ -21,12 +21,15 @@ public class GenConfig
     /** 生成包路径 */
     public static String packageName;
 
-    /** 自动去除表前缀,默认是false */
+    /** 自动去除表前缀 */
     public static boolean autoRemovePre;
 
-    /** 表前缀(类名不会包含表前缀) */
+    /** 表前缀 */
     public static String tablePrefix;
 
+    /** 是否允许生成文件覆盖到本地(自定义路径) */
+    public static boolean allowOverwrite;
+
     public static String getAuthor()
     {
         return author;
@@ -70,4 +73,15 @@ public class GenConfig
     {
         GenConfig.tablePrefix = tablePrefix;
     }
+
+    public static boolean isAllowOverwrite()
+    {
+        return allowOverwrite;
+    }
+
+    @Value("${allowOverwrite}")
+    public void setAllowOverwrite(boolean allowOverwrite)
+    {
+        GenConfig.allowOverwrite = allowOverwrite;
+    }
 }

+ 5 - 0
ruoyi-generator/src/main/java/com/ruoyi/generator/controller/GenController.java

@@ -30,6 +30,7 @@ import com.ruoyi.common.core.text.Convert;
 import com.ruoyi.common.enums.BusinessType;
 import com.ruoyi.common.utils.SecurityUtils;
 import com.ruoyi.common.utils.sql.SqlUtil;
+import com.ruoyi.generator.config.GenConfig;
 import com.ruoyi.generator.domain.GenTable;
 import com.ruoyi.generator.domain.GenTableColumn;
 import com.ruoyi.generator.service.IGenTableColumnService;
@@ -213,6 +214,10 @@ public class GenController extends BaseController
     @GetMapping("/genCode/{tableName}")
     public AjaxResult genCode(@PathVariable("tableName") String tableName)
     {
+        if (!GenConfig.isAllowOverwrite())
+        {
+            return AjaxResult.error("【系统预设】不允许生成文件覆盖到本地");
+        }
         genTableService.generatorCode(tableName);
         return success();
     }

+ 3 - 1
ruoyi-generator/src/main/resources/generator.yml

@@ -7,4 +7,6 @@ gen:
   # 自动去除表前缀,默认是false
   autoRemovePre: false
   # 表前缀(生成类名不会包含表前缀,多个用逗号分隔)
-  tablePrefix: sys_
+  tablePrefix: sys_
+  # 是否允许生成文件覆盖到本地(自定义路径),默认不允许
+  allowOverwrite: false

+ 1 - 1
ruoyi-quartz/pom.xml

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

+ 1 - 1
ruoyi-system/pom.xml

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

+ 1 - 1
ruoyi-ui/package.json

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

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 0 - 0
ruoyi-ui/public/styles/theme-chalk/index.css


+ 1 - 1
ruoyi-ui/src/api/system/user.js

@@ -96,7 +96,7 @@ export function updateUserPwd(oldPassword, newPassword) {
   return request({
     url: '/system/user/profile/updatePwd',
     method: 'put',
-    params: data
+    data: data
   })
 }
 

+ 170 - 173
ruoyi-ui/src/components/ThemePicker/index.vue

@@ -1,173 +1,170 @@
-<template>
-  <el-color-picker
-    v-model="theme"
-    :predefine="['#409EFF', '#1890ff', '#304156','#212121','#11a983', '#13c2c2', '#6959CD', '#f5222d', ]"
-    class="theme-picker"
-    popper-class="theme-picker-dropdown"
-  />
-</template>
-
-<script>
-const version = require('element-ui/package.json').version // element-ui version from node_modules
-const ORIGINAL_THEME = '#409EFF' // default color
-
-export default {
-  data() {
-    return {
-      chalk: '', // content of theme-chalk css
-      theme: ''
-    }
-  },
-  computed: {
-    defaultTheme() {
-      return this.$store.state.settings.theme
-    }
-  },
-  watch: {
-    defaultTheme: {
-      handler: function(val, oldVal) {
-        this.theme = val
-      },
-      immediate: true
-    },
-    async theme(val) {
-      await this.setTheme(val)
-    }
-  },
-  created() {
-    if(this.defaultTheme !== ORIGINAL_THEME) {
-      this.setTheme(this.defaultTheme)
-    }
-  },
-
-  methods: {
-    async setTheme(val) {
-      const oldVal = this.chalk ? this.theme : ORIGINAL_THEME
-      if (typeof val !== 'string') return
-      const themeCluster = this.getThemeCluster(val.replace('#', ''))
-      const originalCluster = this.getThemeCluster(oldVal.replace('#', ''))
-
-      const getHandler = (variable, id) => {
-        return () => {
-          const originalCluster = this.getThemeCluster(ORIGINAL_THEME.replace('#', ''))
-          const newStyle = this.updateStyle(this[variable], originalCluster, themeCluster)
-
-          let styleTag = document.getElementById(id)
-          if (!styleTag) {
-            styleTag = document.createElement('style')
-            styleTag.setAttribute('id', id)
-            document.head.appendChild(styleTag)
-          }
-          styleTag.innerText = newStyle
-        }
-      }
-
-      if (!this.chalk) {
-        const url = `https://unpkg.com/element-ui@${version}/lib/theme-chalk/index.css`
-        await this.getCSSString(url, 'chalk')
-      }
-
-      const chalkHandler = getHandler('chalk', 'chalk-style')
-
-      chalkHandler()
-
-      const styles = [].slice.call(document.querySelectorAll('style'))
-        .filter(style => {
-          const text = style.innerText
-          return new RegExp(oldVal, 'i').test(text) && !/Chalk Variables/.test(text)
-        })
-      styles.forEach(style => {
-        const { innerText } = style
-        if (typeof innerText !== 'string') return
-        style.innerText = this.updateStyle(innerText, originalCluster, themeCluster)
-      })
-
-      this.$emit('change', val)
-    },
-
-    updateStyle(style, oldCluster, newCluster) {
-      let newStyle = style
-      oldCluster.forEach((color, index) => {
-        newStyle = newStyle.replace(new RegExp(color, 'ig'), newCluster[index])
-      })
-      return newStyle
-    },
-
-    getCSSString(url, variable) {
-      return new Promise(resolve => {
-        const xhr = new XMLHttpRequest()
-        xhr.onreadystatechange = () => {
-          if (xhr.readyState === 4 && xhr.status === 200) {
-            this[variable] = xhr.responseText.replace(/@font-face{[^}]+}/, '')
-            resolve()
-          }
-        }
-        xhr.open('GET', url)
-        xhr.send()
-      })
-    },
-
-    getThemeCluster(theme) {
-      const tintColor = (color, tint) => {
-        let red = parseInt(color.slice(0, 2), 16)
-        let green = parseInt(color.slice(2, 4), 16)
-        let blue = parseInt(color.slice(4, 6), 16)
-
-        if (tint === 0) { // when primary color is in its rgb space
-          return [red, green, blue].join(',')
-        } else {
-          red += Math.round(tint * (255 - red))
-          green += Math.round(tint * (255 - green))
-          blue += Math.round(tint * (255 - blue))
-
-          red = red.toString(16)
-          green = green.toString(16)
-          blue = blue.toString(16)
-
-          return `#${red}${green}${blue}`
-        }
-      }
-
-      const shadeColor = (color, shade) => {
-        let red = parseInt(color.slice(0, 2), 16)
-        let green = parseInt(color.slice(2, 4), 16)
-        let blue = parseInt(color.slice(4, 6), 16)
-
-        red = Math.round((1 - shade) * red)
-        green = Math.round((1 - shade) * green)
-        blue = Math.round((1 - shade) * blue)
-
-        red = red.toString(16)
-        green = green.toString(16)
-        blue = blue.toString(16)
-
-        return `#${red}${green}${blue}`
-      }
-
-      const clusters = [theme]
-      for (let i = 0; i <= 9; i++) {
-        clusters.push(tintColor(theme, Number((i / 10).toFixed(2))))
-      }
-      clusters.push(shadeColor(theme, 0.1))
-      return clusters
-    }
-  }
-}
-</script>
-
-<style>
-.theme-message,
-.theme-picker-dropdown {
-  z-index: 99999 !important;
-}
-
-.theme-picker .el-color-picker__trigger {
-  height: 26px !important;
-  width: 26px !important;
-  padding: 2px;
-}
-
-.theme-picker-dropdown .el-color-dropdown__link-btn {
-  display: none;
-}
-</style>
+<template>
+  <el-color-picker
+    v-model="theme"
+    :predefine="['#409EFF', '#1890ff', '#304156','#212121','#11a983', '#13c2c2', '#6959CD', '#f5222d', ]"
+    class="theme-picker"
+    popper-class="theme-picker-dropdown"
+  />
+</template>
+
+<script>
+const ORIGINAL_THEME = '#409EFF' // default color
+
+export default {
+  data() {
+    return {
+      chalk: '', // content of theme-chalk css
+      theme: ''
+    }
+  },
+  computed: {
+    defaultTheme() {
+      return this.$store.state.settings.theme
+    }
+  },
+  watch: {
+    defaultTheme: {
+      handler: function(val, oldVal) {
+        this.theme = val
+      },
+      immediate: true
+    },
+    async theme(val) {
+      await this.setTheme(val)
+    }
+  },
+  created() {
+    if(this.defaultTheme !== ORIGINAL_THEME) {
+      this.setTheme(this.defaultTheme)
+    }
+  },
+  methods: {
+    async setTheme(val) {
+      const oldVal = this.chalk ? this.theme : ORIGINAL_THEME
+      if (typeof val !== 'string') return
+      const themeCluster = this.getThemeCluster(val.replace('#', ''))
+      const originalCluster = this.getThemeCluster(oldVal.replace('#', ''))
+
+      const getHandler = (variable, id) => {
+        return () => {
+          const originalCluster = this.getThemeCluster(ORIGINAL_THEME.replace('#', ''))
+          const newStyle = this.updateStyle(this[variable], originalCluster, themeCluster)
+
+          let styleTag = document.getElementById(id)
+          if (!styleTag) {
+            styleTag = document.createElement('style')
+            styleTag.setAttribute('id', id)
+            document.head.appendChild(styleTag)
+          }
+          styleTag.innerText = newStyle
+        }
+      }
+
+      if (!this.chalk) {
+        const url = `/styles/theme-chalk/index.css`
+        await this.getCSSString(url, 'chalk')
+      }
+
+      const chalkHandler = getHandler('chalk', 'chalk-style')
+      chalkHandler()
+
+      const styles = [].slice.call(document.querySelectorAll('style'))
+        .filter(style => {
+          const text = style.innerText
+          return new RegExp(oldVal, 'i').test(text) && !/Chalk Variables/.test(text)
+        })
+      styles.forEach(style => {
+        const { innerText } = style
+        if (typeof innerText !== 'string') return
+        style.innerText = this.updateStyle(innerText, originalCluster, themeCluster)
+      })
+
+      this.$emit('change', val)
+    },
+
+    updateStyle(style, oldCluster, newCluster) {
+      let newStyle = style
+      oldCluster.forEach((color, index) => {
+        newStyle = newStyle.replace(new RegExp(color, 'ig'), newCluster[index])
+      })
+      return newStyle
+    },
+
+    getCSSString(url, variable) {
+      return new Promise(resolve => {
+        const xhr = new XMLHttpRequest()
+        xhr.onreadystatechange = () => {
+          if (xhr.readyState === 4 && xhr.status === 200) {
+            this[variable] = xhr.responseText.replace(/@font-face{[^}]+}/, '')
+            resolve()
+          }
+        }
+        xhr.open('GET', url)
+        xhr.send()
+      })
+    },
+
+    getThemeCluster(theme) {
+      const tintColor = (color, tint) => {
+        let red = parseInt(color.slice(0, 2), 16)
+        let green = parseInt(color.slice(2, 4), 16)
+        let blue = parseInt(color.slice(4, 6), 16)
+
+        if (tint === 0) { // when primary color is in its rgb space
+          return [red, green, blue].join(',')
+        } else {
+          red += Math.round(tint * (255 - red))
+          green += Math.round(tint * (255 - green))
+          blue += Math.round(tint * (255 - blue))
+
+          red = red.toString(16)
+          green = green.toString(16)
+          blue = blue.toString(16)
+
+          return `#${red}${green}${blue}`
+        }
+      }
+
+      const shadeColor = (color, shade) => {
+        let red = parseInt(color.slice(0, 2), 16)
+        let green = parseInt(color.slice(2, 4), 16)
+        let blue = parseInt(color.slice(4, 6), 16)
+
+        red = Math.round((1 - shade) * red)
+        green = Math.round((1 - shade) * green)
+        blue = Math.round((1 - shade) * blue)
+
+        red = red.toString(16)
+        green = green.toString(16)
+        blue = blue.toString(16)
+
+        return `#${red}${green}${blue}`
+      }
+
+      const clusters = [theme]
+      for (let i = 0; i <= 9; i++) {
+        clusters.push(tintColor(theme, Number((i / 10).toFixed(2))))
+      }
+      clusters.push(shadeColor(theme, 0.1))
+      return clusters
+    }
+  }
+}
+</script>
+
+<style>
+.theme-message,
+.theme-picker-dropdown {
+  z-index: 99999 !important;
+}
+
+.theme-picker .el-color-picker__trigger {
+  height: 26px !important;
+  width: 26px !important;
+  padding: 2px;
+}
+
+.theme-picker-dropdown .el-color-dropdown__link-btn {
+  display: none;
+}
+</style>

+ 1 - 1
ruoyi-ui/src/components/TopNav/index.vue

@@ -96,8 +96,8 @@ export default {
       let activePath = path;
       if (path !== undefined && path.lastIndexOf("/") > 0 && hideList.indexOf(path) === -1) {
         const tmpPath = path.substring(1, path.length);
-        activePath = "/" + tmpPath.substring(0, tmpPath.indexOf("/"));
         if (!this.$route.meta.link) {
+          activePath = "/" + tmpPath.substring(0, tmpPath.indexOf("/"));
           this.$store.dispatch('app/toggleSideBarHide', false);
         }
       } else if(!this.$route.children) {

+ 1 - 1
ruoyi-ui/src/permission.js

@@ -9,7 +9,7 @@ import { isRelogin } from '@/utils/request'
 
 NProgress.configure({ showSpinner: false })
 
-const whiteList = ['/login', '/register', '/register*', '/register/*']
+const whiteList = ['/login', '/register']
 
 const isWhiteList = (path) => {
   return whiteList.some(pattern => isPathMatch(pattern, path))

+ 40 - 1
ruoyi-ui/src/views/index.vue

@@ -147,6 +147,45 @@
             <span>更新日志</span>
           </div>
           <el-collapse accordion>
+            <el-collapse-item title="v3.8.9 - 2024-12-30">
+              <ol>
+                <li>用户管理支持分栏拖动</li>
+                <li>修改主题样式本地读取</li>
+                <li>用户头像http(s)链接支持</li>
+                <li>用户管理过滤掉已禁用部门</li>
+                <li>支持自定义显示Excel属性列</li>
+                <li>操作日志记录DELETE请求参数</li>
+                <li>白名单支持对通配符路径匹配</li>
+                <li>校检文件名是否包含特殊字符</li>
+                <li>代码生成创建表屏蔽违规的字符</li>
+                <li>菜单面包屑导航支持多层级显示</li>
+                <li>Excel注解支持wrapText是否允许内容换行</li>
+                <li>代码生成新增配置是否允许文件覆盖到本地</li>
+                <li>修复角色禁用权限不失效问题</li>
+                <li>修复代码生成上级菜单显示问题</li>
+                <li>修复导出子列表对象只能在最后的问题</li>
+                <li>修复TopNav无法正确获取active的问题</li>
+                <li>修复默认关闭Tags-Views内链页面打不开</li>
+                <li>升级oshi到最新版本6.6.5</li>
+                <li>升级tomcat到最新版本9.0.96</li>
+                <li>升级fastjson到最新版2.0.53</li>
+                <li>升级logback到最新版本1.2.13</li>
+                <li>升级spring-framework到最新版本5.3.39</li>
+                <li>升级quill到最新版本2.0.2</li>
+                <li>升级axios到最新版本0.28.1</li>
+                <li>优化身份证脱敏正则</li>
+                <li>优化权限更新后同步缓存</li>
+                <li>优化查询时间范围日期格式</li>
+                <li>优化参数键值更换为多行文本</li>
+                <li>优化导入带标题文件关闭清理</li>
+                <li>优化上传图片带域名不增加前缀</li>
+                <li>优化特殊字符密码修改失败问题</li>
+                <li>优化无用户编号不校验数据权限</li>
+                <li>优化TopNav内链菜单点击没有高亮</li>
+                <li>优化菜单管理切换Mini布局错乱问题</li>
+                <li>其他细节优化</li>
+              </ol>
+            </el-collapse-item>
             <el-collapse-item title="v3.8.8 - 2024-06-30">
               <ol>
                 <li>菜单管理新增路由名称</li>
@@ -1020,7 +1059,7 @@ export default {
   data() {
     return {
       // 版本号
-      version: "3.8.8"
+      version: "3.8.9"
     };
   },
   methods: {

+ 14 - 0
ruoyi-ui/src/views/system/menu/index.vue

@@ -117,6 +117,8 @@
               />
             </el-form-item>
           </el-col>
+        </el-row>
+        <el-row>
           <el-col :span="24">
             <el-form-item label="菜单类型" prop="menuType">
               <el-radio-group v-model="form.menuType">
@@ -126,6 +128,8 @@
               </el-radio-group>
             </el-form-item>
           </el-col>
+        </el-row>
+        <el-row>
           <el-col :span="24" v-if="form.menuType != 'F'">
             <el-form-item label="菜单图标" prop="icon">
               <el-popover
@@ -147,6 +151,8 @@
               </el-popover>
             </el-form-item>
           </el-col>
+        </el-row>
+        <el-row>
           <el-col :span="12">
             <el-form-item label="菜单名称" prop="menuName">
               <el-input v-model="form.menuName" placeholder="请输入菜单名称" />
@@ -157,6 +163,8 @@
               <el-input-number v-model="form.orderNum" controls-position="right" :min="0" />
             </el-form-item>
           </el-col>
+        </el-row>
+        <el-row>
           <el-col :span="12" v-if="form.menuType != 'F'">
             <el-form-item prop="isFrame">
               <span slot="label">
@@ -182,6 +190,8 @@
               <el-input v-model="form.path" placeholder="请输入路由地址" />
             </el-form-item>
           </el-col>
+        </el-row>
+        <el-row>
           <el-col :span="12" v-if="form.menuType == 'C'">
             <el-form-item prop="component">
               <span slot="label">
@@ -204,6 +214,8 @@
               </span>
             </el-form-item>
           </el-col>
+        </el-row>
+        <el-row>
           <el-col :span="12" v-if="form.menuType == 'C'">
             <el-form-item prop="query">
               <el-input v-model="form.query" placeholder="请输入路由参数" maxlength="255" />
@@ -229,6 +241,8 @@
               </el-radio-group>
             </el-form-item>
           </el-col>
+        </el-row>
+        <el-row>
           <el-col :span="12" v-if="form.menuType != 'F'">
             <el-form-item prop="visible">
               <span slot="label">

+ 17 - 2
ruoyi-ui/src/views/system/user/index.vue

@@ -105,7 +105,7 @@
           </el-col>
           <el-col :span="12">
             <el-form-item label="归属部门" prop="deptId">
-              <treeselect v-model="form.deptId" :options="deptOptions" :show-count="true" placeholder="请选择归属部门" />
+              <treeselect v-model="form.deptId" :options="enabledDeptOptions" :show-count="true" placeholder="请选择归属部门" />
             </el-form-item>
           </el-col>
         </el-row>
@@ -230,8 +230,10 @@ export default {
       userList: null,
       // 弹出层标题
       title: "",
-      // 部门树选项
+      // 所有部门树选项
       deptOptions: undefined,
+      // 过滤掉已禁用部门树选项
+      enabledDeptOptions: undefined,
       // 是否显示弹出层
       open: false,
       // 部门名称
@@ -343,6 +345,19 @@ export default {
     getDeptTree() {
       deptTreeSelect().then(response => {
         this.deptOptions = response.data;
+        this.enabledDeptOptions = this.filterDisabledDept(JSON.parse(JSON.stringify(response.data)));
+      });
+    },
+    // 过滤禁用的部门
+    filterDisabledDept(deptList) {
+      return deptList.filter(dept => {
+        if (dept.disabled) {
+          return false;
+        }
+        if (dept.children && dept.children.length) {
+          dept.children = this.filterDisabledDept(dept.children);
+        }
+        return true;
       });
     },
     // 筛选节点

Kaikkia tiedostoja ei voida näyttää, sillä liian monta tiedostoa muuttui tässä diffissä