浏览代码

Merge remote-tracking branch 'upstream/master'

# Conflicts:
#	ruoyi-quartz/src/main/java/com/ruoyi/quartz/config/ScheduleConfig.java
“zyj” 3 年之前
父节点
当前提交
c6427b82f5

+ 3 - 3
pom.xml

@@ -22,10 +22,10 @@
         <bitwalker.version>1.21</bitwalker.version>
         <swagger.version>3.0.0</swagger.version>
         <kaptcha.version>2.3.2</kaptcha.version>
-        <mybatis-spring-boot.version>2.2.0</mybatis-spring-boot.version>
-        <pagehelper.boot.version>1.4.0</pagehelper.boot.version>
+        <mybatis-spring-boot.version>2.2.2</mybatis-spring-boot.version>
+        <pagehelper.boot.version>1.4.1</pagehelper.boot.version>
         <fastjson.version>1.2.79</fastjson.version>
-        <oshi.version>5.8.6</oshi.version>
+        <oshi.version>6.1.2</oshi.version>
         <jna.version>5.10.0</jna.version>
         <commons.io.version>2.11.0</commons.io.version>
         <commons.fileupload.version>1.4</commons.fileupload.version>

+ 8 - 0
ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Jvm.java

@@ -119,4 +119,12 @@ public class Jvm
     {
         return DateUtils.getDatePoor(DateUtils.getNowDate(), DateUtils.getServerStartDate());
     }
+
+    /**
+     * 运行参数
+     */
+    public String getInputArgs()
+    {
+        return ManagementFactory.getRuntimeMXBean().getInputArguments().toString();
+    }
 }

+ 2 - 1
ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysLoginService.java

@@ -17,6 +17,7 @@ import com.ruoyi.common.exception.user.CaptchaExpireException;
 import com.ruoyi.common.exception.user.UserPasswordNotMatchException;
 import com.ruoyi.common.utils.DateUtils;
 import com.ruoyi.common.utils.MessageUtils;
+import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.common.utils.ServletUtils;
 import com.ruoyi.common.utils.ip.IpUtils;
 import com.ruoyi.framework.manager.AsyncManager;
@@ -102,7 +103,7 @@ public class SysLoginService
      */
     public void validateCaptcha(String username, String code, String uuid)
     {
-        String verifyKey = Constants.CAPTCHA_CODE_KEY + uuid;
+        String verifyKey = Constants.CAPTCHA_CODE_KEY + StringUtils.nvl(uuid, "");
         String captcha = redisCache.getCacheObject(verifyKey);
         redisCache.deleteObject(verifyKey);
         if (captcha == null)

+ 17 - 1
ruoyi-generator/src/main/java/com/ruoyi/generator/util/VelocityUtils.java

@@ -271,6 +271,23 @@ public class VelocityUtils
     {
         List<GenTableColumn> columns = genTable.getColumns();
         Set<String> dicts = new HashSet<String>();
+        addDicts(dicts, columns);
+        if (StringUtils.isNotNull(genTable.getSubTable()))
+        {
+            List<GenTableColumn> subColumns = genTable.getSubTable().getColumns();
+            addDicts(dicts, subColumns);
+        }
+        return StringUtils.join(dicts, ", ");
+    }
+
+    /**
+     * 添加字典列表
+     * 
+     * @param dicts 字典列表
+     * @param columns 列集合
+     */
+    public static void addDicts(Set<String> dicts, List<GenTableColumn> columns)
+    {
         for (GenTableColumn column : columns)
         {
             if (!column.isSuperColumn() && StringUtils.isNotEmpty(column.getDictType()) && StringUtils.equalsAny(
@@ -280,7 +297,6 @@ public class VelocityUtils
                 dicts.add("'" + column.getDictType() + "'");
             }
         }
-        return StringUtils.join(dicts, ", ");
     }
 
     /**

+ 31 - 4
ruoyi-generator/src/main/resources/vm/vue/index.vue.vm

@@ -44,7 +44,7 @@
           v-model="queryParams.${column.javaField}"
           type="date"
           value-format="yyyy-MM-dd"
-          placeholder="选择${comment}">
+          placeholder="选择${comment}">
         </el-date-picker>
       </el-form-item>
 #elseif($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
@@ -269,7 +269,7 @@
             v-model="form.${field}"
             type="date"
             value-format="yyyy-MM-dd"
-            placeholder="选择${comment}">
+            placeholder="选择${comment}">
           </el-date-picker>
         </el-form-item>
 #elseif($column.htmlType == "textarea")
@@ -302,12 +302,39 @@
 #set($comment=$column.columnComment)
 #end
 #if($column.pk || $javaField == ${subTableFkclassName})
-#elseif($column.list && "" != $javaField)
-          <el-table-column label="$comment" prop="${javaField}">
+#elseif($column.list && $column.htmlType == "input")
+          <el-table-column label="$comment" prop="${javaField}" width="150">
             <template slot-scope="scope">
               <el-input v-model="scope.row.$javaField" placeholder="请输入$comment" />
             </template>
           </el-table-column>
+#elseif($column.list && $column.htmlType == "datetime")
+          <el-table-column label="$comment" prop="${javaField}" width="240">
+            <template slot-scope="scope">
+              <el-date-picker clearable v-model="scope.row.$javaField" type="date" value-format="yyyy-MM-dd" placeholder="请选择$comment" />
+            </template>
+          </el-table-column>
+#elseif($column.list && ($column.htmlType == "select" || $column.htmlType == "radio") && "" != $column.dictType)
+          <el-table-column label="$comment" prop="${javaField}" width="150">
+            <template slot-scope="scope">
+              <el-select v-model="scope.row.$javaField" placeholder="请选择$comment">
+                <el-option
+                  v-for="dict in dict.type.$column.dictType"
+                  :key="dict.value"
+                  :label="dict.label"
+                  :value="dict.value"
+                ></el-option>
+              </el-select>
+            </template>
+          </el-table-column>
+#elseif($column.list && ($column.htmlType == "select" || $column.htmlType == "radio") && "" == $column.dictType)
+          <el-table-column label="$comment" prop="${javaField}" width="150">
+            <template slot-scope="scope">
+              <el-select v-model="scope.row.$javaField" placeholder="请选择$comment">
+                <el-option label="请选择字典生成" value="" />
+              </el-select>
+            </template>
+          </el-table-column>
 #end
 #end
         </el-table>

+ 36 - 4
ruoyi-generator/src/main/resources/vm/vue/v3/index.vue.vm

@@ -43,7 +43,7 @@
           v-model="queryParams.${column.javaField}"
           type="date"
           value-format="YYYY-MM-DD"
-          placeholder="选择${comment}">
+          placeholder="选择${comment}">
         </el-date-picker>
       </el-form-item>
 #elseif($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
@@ -260,7 +260,7 @@
             v-model="form.${field}"
             type="date"
             value-format="YYYY-MM-DD"
-            placeholder="选择${comment}">
+            placeholder="选择${comment}">
           </el-date-picker>
         </el-form-item>
 #elseif($column.htmlType == "textarea")
@@ -293,12 +293,44 @@
 #set($comment=$column.columnComment)
 #end
 #if($column.pk || $javaField == ${subTableFkclassName})
-#elseif($column.list && "" != $javaField)
-          <el-table-column label="$comment" prop="${javaField}">
+#elseif($column.list && $column.htmlType == "input")
+          <el-table-column label="$comment" prop="${javaField}" width="150">
             <template #default="scope">
               <el-input v-model="scope.row.$javaField" placeholder="请输入$comment" />
             </template>
           </el-table-column>
+#elseif($column.list && $column.htmlType == "datetime")
+          <el-table-column label="$comment" prop="${javaField}" width="240">
+            <template #default="scope">
+              <el-date-picker clearable
+                v-model="scope.row.$javaField"
+                type="date"
+                value-format="YYYY-MM-DD"
+                placeholder="请选择$comment">
+              </el-date-picker>
+            </template>
+          </el-table-column>
+#elseif($column.list && ($column.htmlType == "select" || $column.htmlType == "radio") && "" != $column.dictType)
+          <el-table-column label="$comment" prop="${javaField}" width="150">
+            <template #default="scope">
+              <el-select v-model="scope.row.$javaField" placeholder="请选择$comment">
+                <el-option
+                  v-for="dict in $column.dictType"
+                  :key="dict.value"
+                  :label="dict.label"
+                  :value="dict.value"
+                ></el-option>
+              </el-select>
+            </template>
+          </el-table-column>
+#elseif($column.list && ($column.htmlType == "select" || $column.htmlType == "radio") && "" == $column.dictType)
+          <el-table-column label="$comment" prop="${javaField}" width="150">
+            <template #default="scope">
+              <el-select v-model="scope.row.$javaField" placeholder="请选择$comment">
+                <el-option label="请选择字典生成" value="" />
+              </el-select>
+            </template>
+          </el-table-column>
 #end
 #end
         </el-table>

+ 57 - 58
ruoyi-quartz/src/main/java/com/ruoyi/quartz/config/ScheduleConfig.java

@@ -1,58 +1,57 @@
-package com.ruoyi.quartz.config;
-
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.scheduling.quartz.SchedulerFactoryBean;
-import javax.sql.DataSource;
-import java.util.Properties;
-
-/**
- * 定时任务配置(单机部署建议删除此类和qrtz数据库表,默认走内存会最高效)
- * 
- * @author ruoyi
- */
-@Configuration
-public class ScheduleConfig
-{
-    @Bean
-    public SchedulerFactoryBean schedulerFactoryBean(DataSource dataSource)
-    {
-        SchedulerFactoryBean factory = new SchedulerFactoryBean();
-        factory.setDataSource(dataSource);
-
-        // quartz参数
-        Properties prop = new Properties();
-        prop.put("org.quartz.scheduler.instanceName", "RuoyiScheduler");
-        prop.put("org.quartz.scheduler.instanceId", "AUTO");
-        prop.put("org.quartz.jobStore.driverDelegateClass", "org.quartz.impl.jdbcjobstore.PostgreSQLDelegate");
-        // 线程池配置
-        prop.put("org.quartz.threadPool.class", "org.quartz.simpl.SimpleThreadPool");
-        prop.put("org.quartz.threadPool.threadCount", "20");
-        prop.put("org.quartz.threadPool.threadPriority", "5");
-        // JobStore配置
-        prop.put("org.quartz.jobStore.class", "org.springframework.scheduling.quartz.LocalDataSourceJobStore");
-        // 集群配置
-        prop.put("org.quartz.jobStore.isClustered", "true");
-        prop.put("org.quartz.jobStore.clusterCheckinInterval", "15000");
-        prop.put("org.quartz.jobStore.maxMisfiresToHandleAtATime", "1");
-        prop.put("org.quartz.jobStore.txIsolationLevelSerializable", "true");
-
-        // sqlserver 启用
-        // prop.put("org.quartz.jobStore.selectWithLockSQL", "SELECT * FROM {0}LOCKS UPDLOCK WHERE LOCK_NAME = ?");
-        prop.put("org.quartz.jobStore.misfireThreshold", "12000");
-        prop.put("org.quartz.jobStore.tablePrefix", "QRTZ_");
-        factory.setQuartzProperties(prop);
-
-        factory.setSchedulerName("RuoyiScheduler");
-        // 延时启动
-        factory.setStartupDelay(1);
-        factory.setApplicationContextSchedulerContextKey("applicationContextKey");
-        // 可选,QuartzScheduler
-        // 启动时更新己存在的Job,这样就不用每次修改targetObject后删除qrtz_job_details表对应记录了
-        factory.setOverwriteExistingJobs(true);
-        // 设置自动启动,默认为true
-        factory.setAutoStartup(true);
-
-        return factory;
-    }
-}
+//package com.ruoyi.quartz.config;
+//
+//import org.springframework.context.annotation.Bean;
+//import org.springframework.context.annotation.Configuration;
+//import org.springframework.scheduling.quartz.SchedulerFactoryBean;
+//import javax.sql.DataSource;
+//import java.util.Properties;
+//
+///**
+// * 定时任务配置(单机部署建议删除此类和qrtz数据库表,默认走内存会最高效)
+// *
+// * @author ruoyi
+// */
+//@Configuration
+//public class ScheduleConfig
+//{
+//    @Bean
+//    public SchedulerFactoryBean schedulerFactoryBean(DataSource dataSource)
+//    {
+//        SchedulerFactoryBean factory = new SchedulerFactoryBean();
+//        factory.setDataSource(dataSource);
+//
+//        // quartz参数
+//        Properties prop = new Properties();
+//        prop.put("org.quartz.scheduler.instanceName", "RuoyiScheduler");
+//        prop.put("org.quartz.scheduler.instanceId", "AUTO");
+//        // 线程池配置
+//        prop.put("org.quartz.threadPool.class", "org.quartz.simpl.SimpleThreadPool");
+//        prop.put("org.quartz.threadPool.threadCount", "20");
+//        prop.put("org.quartz.threadPool.threadPriority", "5");
+//        // JobStore配置
+//        prop.put("org.quartz.jobStore.class", "org.springframework.scheduling.quartz.LocalDataSourceJobStore");
+//        // 集群配置
+//        prop.put("org.quartz.jobStore.isClustered", "true");
+//        prop.put("org.quartz.jobStore.clusterCheckinInterval", "15000");
+//        prop.put("org.quartz.jobStore.maxMisfiresToHandleAtATime", "1");
+//        prop.put("org.quartz.jobStore.txIsolationLevelSerializable", "true");
+//
+//        // sqlserver 启用
+//        // prop.put("org.quartz.jobStore.selectWithLockSQL", "SELECT * FROM {0}LOCKS UPDLOCK WHERE LOCK_NAME = ?");
+//        prop.put("org.quartz.jobStore.misfireThreshold", "12000");
+//        prop.put("org.quartz.jobStore.tablePrefix", "QRTZ_");
+//        factory.setQuartzProperties(prop);
+//
+//        factory.setSchedulerName("RuoyiScheduler");
+//        // 延时启动
+//        factory.setStartupDelay(1);
+//        factory.setApplicationContextSchedulerContextKey("applicationContextKey");
+//        // 可选,QuartzScheduler
+//        // 启动时更新己存在的Job,这样就不用每次修改targetObject后删除qrtz_job_details表对应记录了
+//        factory.setOverwriteExistingJobs(true);
+//        // 设置自动启动,默认为true
+//        factory.setAutoStartup(true);
+//
+//        return factory;
+//    }
+//}

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

@@ -133,7 +133,7 @@
 			<if test="orderNum != null and orderNum != ''">order_num = #{orderNum},</if>
 			<if test="path != null and path != ''">path = #{path},</if>
 			<if test="component != null">component = #{component},</if>
-			<if test="query != null">query = #{query},</if>
+			<if test="query != null">`query` = #{query},</if>
 			<if test="isFrame != null and isFrame != ''">is_frame = #{isFrame},</if>
 			<if test="isCache != null and isCache != ''">is_cache = #{isCache},</if>
 			<if test="menuType != null and menuType != ''">menu_type = #{menuType},</if>
@@ -156,7 +156,7 @@
 		<if test="orderNum != null and orderNum != ''">order_num,</if>
 		<if test="path != null and path != ''">path,</if>
 		<if test="component != null and component != ''">component,</if>
-		<if test="query != null and query != ''">query,</if>
+		<if test="query != null and query != ''">`query`,</if>
 		<if test="isFrame != null and isFrame != ''">is_frame,</if>
 		<if test="isCache != null and isCache != ''">is_cache,</if>
 		<if test="menuType != null and menuType != ''">menu_type,</if>

+ 7 - 0
ruoyi-ui/src/components/Pagination/index.vue

@@ -61,6 +61,10 @@ export default {
       default: false
     }
   },
+  data() {
+    return {
+    };
+  },
   computed: {
     currentPage: {
       get() {
@@ -81,6 +85,9 @@ export default {
   },
   methods: {
     handleSizeChange(val) {
+      if (this.currentPage * val > this.total) {
+        this.currentPage = 1
+      }
       this.$emit('pagination', { page: this.currentPage, limit: val })
       if (this.autoScroll) {
         scrollTo(0, 800)

+ 56 - 53
ruoyi-ui/src/permission.js

@@ -1,53 +1,56 @@
-import router from './router'
-import store from './store'
-import { Message } from 'element-ui'
-import NProgress from 'nprogress'
-import 'nprogress/nprogress.css'
-import { getToken } from '@/utils/auth'
-
-NProgress.configure({ showSpinner: false })
-
-const whiteList = ['/login', '/auth-redirect', '/bind', '/register']
-
-router.beforeEach((to, from, next) => {
-  NProgress.start()
-  if (getToken()) {
-    to.meta.title && store.dispatch('settings/setTitle', to.meta.title)
-    /* has token*/
-    if (to.path === '/login') {
-      next({ path: '/' })
-      NProgress.done()
-    } else {
-      if (store.getters.roles.length === 0) {
-        // 判断当前用户是否已拉取完user_info信息
-        store.dispatch('GetInfo').then(() => {
-          store.dispatch('GenerateRoutes').then(accessRoutes => {
-            // 根据roles权限生成可访问的路由表
-            router.addRoutes(accessRoutes) // 动态添加可访问路由表
-            next({ ...to, replace: true }) // hack方法 确保addRoutes已完成
-          })
-        }).catch(err => {
-            store.dispatch('LogOut').then(() => {
-              Message.error(err)
-              next({ path: '/' })
-            })
-          })
-      } else {
-        next()
-      }
-    }
-  } else {
-    // 没有token
-    if (whiteList.indexOf(to.path) !== -1) {
-      // 在免登录白名单,直接进入
-      next()
-    } else {
-      next(`/login?redirect=${to.fullPath}`) // 否则全部重定向到登录页
-      NProgress.done()
-    }
-  }
-})
-
-router.afterEach(() => {
-  NProgress.done()
-})
+import router from './router'
+import store from './store'
+import { Message } from 'element-ui'
+import NProgress from 'nprogress'
+import 'nprogress/nprogress.css'
+import { getToken } from '@/utils/auth'
+import { isRelogin } from '@/utils/request'
+
+NProgress.configure({ showSpinner: false })
+
+const whiteList = ['/login', '/auth-redirect', '/bind', '/register']
+
+router.beforeEach((to, from, next) => {
+  NProgress.start()
+  if (getToken()) {
+    to.meta.title && store.dispatch('settings/setTitle', to.meta.title)
+    /* has token*/
+    if (to.path === '/login') {
+      next({ path: '/' })
+      NProgress.done()
+    } else {
+      if (store.getters.roles.length === 0) {
+        isRelogin.show = true
+        // 判断当前用户是否已拉取完user_info信息
+        store.dispatch('GetInfo').then(() => {
+          isRelogin.show = false
+          store.dispatch('GenerateRoutes').then(accessRoutes => {
+            // 根据roles权限生成可访问的路由表
+            router.addRoutes(accessRoutes) // 动态添加可访问路由表
+            next({ ...to, replace: true }) // hack方法 确保addRoutes已完成
+          })
+        }).catch(err => {
+            store.dispatch('LogOut').then(() => {
+              Message.error(err)
+              next({ path: '/' })
+            })
+          })
+      } else {
+        next()
+      }
+    }
+  } else {
+    // 没有token
+    if (whiteList.indexOf(to.path) !== -1) {
+      // 在免登录白名单,直接进入
+      next()
+    } else {
+      next(`/login?redirect=${to.fullPath}`) // 否则全部重定向到登录页
+      NProgress.done()
+    }
+  }
+})
+
+router.afterEach(() => {
+  NProgress.done()
+})

+ 6 - 9
ruoyi-ui/src/utils/request.js

@@ -9,7 +9,7 @@ import { saveAs } from 'file-saver'
 
 let downloadLoadingInstance;
 // 是否显示重新登录
-let isReloginShow;
+export let isRelogin = { show: false };
 
 axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8'
 // 创建axios实例
@@ -76,23 +76,20 @@ service.interceptors.response.use(res => {
       return res.data
     }
     if (code === 401) {
-      if (!isReloginShow) {
-        isReloginShow = true;
+      if (!isRelogin.show) {
+        isRelogin.show = true;
         MessageBox.confirm('登录状态已过期,您可以继续留在该页面,或者重新登录', '系统提示', {
           confirmButtonText: '重新登录',
           cancelButtonText: '取消',
           type: 'warning'
         }
       ).then(() => {
-        isReloginShow = false;
+        isRelogin.show = false;
         store.dispatch('LogOut').then(() => {
-          // 如果是登录页面不需要重新加载
-          if (window.location.hash.indexOf("#/login") != 0) {
-            location.href = '/index';
-          }
+          location.href = '/index';
         })
       }).catch(() => {
-        isReloginShow = false;
+        isRelogin.show = false;
       });
     }
       return Promise.reject('无效的会话,或者会话已过期,请重新登录。')

+ 12 - 1
ruoyi-ui/src/utils/ruoyi.js

@@ -70,6 +70,9 @@ export function addDateRange(params, dateRange, propName) {
 
 // 回显数据字典 
 export function selectDictLabel(datas, value) {
+  if (value === undefined) {
+    return "";
+  }
   var actions = [];
   Object.keys(datas).some((key) => {
     if (datas[key].value == ('' + value)) {
@@ -77,23 +80,31 @@ export function selectDictLabel(datas, value) {
       return true;
     }
   })
+  if (actions.length === 0) {
+    actions.push(value);
+  }
   return actions.join('');
 }
 
 // 回显数据字典(字符串数组)
 export function selectDictLabels(datas, value, separator) {
-  if(value === undefined) {
+  if (value === undefined) {
     return "";
   }
   var actions = [];
   var currentSeparator = undefined === separator ? "," : separator;
   var temp = value.split(currentSeparator);
   Object.keys(value.split(currentSeparator)).some((val) => {
+    var match = false;
     Object.keys(datas).some((key) => {
       if (datas[key].value == ('' + temp[val])) {
         actions.push(datas[key].label + currentSeparator);
+        match = true;
       }
     })
+    if (!match) {
+      actions.push(temp[val] + currentSeparator);
+    }
   })
   return actions.join('').substring(0, actions.join('').length - 1);
 }

+ 1 - 1
ruoyi-ui/src/views/monitor/job/index.vue

@@ -165,7 +165,7 @@
           </el-col>
           <el-col :span="12">
             <el-form-item label="任务分组" prop="jobGroup">
-              <el-select v-model="form.jobGroup" placeholder="请选择">
+              <el-select v-model="form.jobGroup" placeholder="请选择任务分组">
                 <el-option
                   v-for="dict in dict.type.sys_job_group"
                   :key="dict.value"

+ 4 - 0
ruoyi-ui/src/views/monitor/server/index.vue

@@ -128,6 +128,10 @@
                   <td colspan="1" class="el-table__cell is-leaf"><div class="cell">项目路径</div></td>
                   <td colspan="3" class="el-table__cell is-leaf"><div class="cell" v-if="server.sys">{{ server.sys.userDir }}</div></td>
                 </tr>
+                <tr>
+                  <td colspan="1" class="el-table__cell is-leaf"><div class="cell">运行参数</div></td>
+                  <td colspan="3" class="el-table__cell is-leaf"><div class="cell" v-if="server.sys">{{ server.jvm.inputArgs }}</div></td>
+                </tr>
               </tbody>
             </table>
           </div>

+ 1 - 1
ruoyi-ui/src/views/system/dept/index.vue

@@ -206,7 +206,7 @@ export default {
         email: [
           {
             type: "email",
-            message: "'请输入正确的邮箱地址",
+            message: "请输入正确的邮箱地址",
             trigger: ["blur", "change"]
           }
         ],

+ 1 - 1
ruoyi-ui/src/views/system/notice/index.vue

@@ -135,7 +135,7 @@
           </el-col>
           <el-col :span="12">
             <el-form-item label="公告类型" prop="noticeType">
-              <el-select v-model="form.noticeType" placeholder="请选择">
+              <el-select v-model="form.noticeType" placeholder="请选择公告类型">
                 <el-option
                   v-for="dict in dict.type.sys_notice_type"
                   :key="dict.value"

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

@@ -248,7 +248,7 @@
         <el-row>
           <el-col :span="12">
             <el-form-item label="用户性别">
-              <el-select v-model="form.sex" placeholder="请选择">
+              <el-select v-model="form.sex" placeholder="请选择性别">
                 <el-option
                   v-for="dict in dict.type.sys_user_sex"
                   :key="dict.value"
@@ -273,7 +273,7 @@
         <el-row>
           <el-col :span="12">
             <el-form-item label="岗位">
-              <el-select v-model="form.postIds" multiple placeholder="请选择">
+              <el-select v-model="form.postIds" multiple placeholder="请选择岗位">
                 <el-option
                   v-for="item in postOptions"
                   :key="item.postId"
@@ -286,7 +286,7 @@
           </el-col>
           <el-col :span="12">
             <el-form-item label="角色">
-              <el-select v-model="form.roleIds" multiple placeholder="请选择">
+              <el-select v-model="form.roleIds" multiple placeholder="请选择角色">
                 <el-option
                   v-for="item in roleOptions"
                   :key="item.roleId"

+ 1 - 1
ruoyi-ui/src/views/system/user/profile/userInfo.vue

@@ -42,7 +42,7 @@ export default {
           { required: true, message: "邮箱地址不能为空", trigger: "blur" },
           {
             type: "email",
-            message: "'请输入正确的邮箱地址",
+            message: "请输入正确的邮箱地址",
             trigger: ["blur", "change"]
           }
         ],