Procházet zdrojové kódy

Merge branch 'master' of https://gitee.com/y_project/RuoYi-Vue

 Conflicts:
	ruoyi-common/src/main/java/com/ruoyi/common/constant/GenConstants.java
	ruoyi-framework/src/main/java/com/ruoyi/framework/config/ResourcesConfig.java
	ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java
	ruoyi-generator/src/main/java/com/ruoyi/generator/controller/GenController.java
	ruoyi-generator/src/main/java/com/ruoyi/generator/domain/GenTable.java
	ruoyi-generator/src/main/java/com/ruoyi/generator/service/GenTableServiceImpl.java
	ruoyi-generator/src/main/java/com/ruoyi/generator/util/VelocityUtils.java
	ruoyi-generator/src/main/resources/vm/sql/sql.vm
	ruoyi-ui/src/utils/index.js
	ruoyi-ui/src/utils/ruoyi.js
	ruoyi-ui/src/views/tool/gen/editTable.vue
	ruoyi-ui/src/views/tool/gen/genInfoForm.vue
	ruoyi-ui/src/views/tool/gen/importTable.vue
疯狂的狮子li před 4 roky
rodič
revize
e19e2fd9cc

+ 6 - 1
ruoyi-common/src/main/java/com/ruoyi/common/annotation/Excel.java

@@ -29,6 +29,11 @@ public @interface Excel
      */
     public String dateFormat() default "";
 
+    /**
+     * 如果是字典类型,请设置字典的type值
+     */
+    public String dictType() default "";
+
     /**
      * 读取内容转表达式 (如: 0=男,1=女,2=未知)
      */
@@ -115,4 +120,4 @@ public @interface Excel
             return this.value;
         }
     }
-}
+}

+ 6 - 0
ruoyi-common/src/main/java/com/ruoyi/common/constant/GenConstants.java

@@ -22,6 +22,12 @@ public class GenConstants
     /** 树名称字段 */
     public static final String TREE_NAME = "treeName";
 
+    /** 上级菜单ID字段 */
+    public static final String PARENT_MENU_ID = "parentMenuId";
+
+    /** 上级菜单名称字段 */
+    public static final String PARENT_MENU_NAME = "parentMenuName";
+
     /** 数据库字符串类型 */
     public static final String[] COLUMNTYPE_STR = { "char", "varchar", "narchar", "varchar2", "tinytext", "text",
             "mediumtext", "longtext" };

+ 52 - 1
ruoyi-common/src/main/java/com/ruoyi/common/utils/DictUtils.java

@@ -2,7 +2,6 @@ package com.ruoyi.common.utils;
 
 import java.util.Collection;
 import java.util.List;
-
 import com.ruoyi.common.constant.Constants;
 import com.ruoyi.common.core.domain.entity.SysDictData;
 import com.ruoyi.common.core.redis.RedisCache;
@@ -43,6 +42,58 @@ public class DictUtils
         return null;
     }
 
+    /**
+     * 根据字典类型和字典值获取字典标签
+     * 
+     * @param dictType 字典类型
+     * @param dictValue 字典值
+     * @return 字典标签
+     */
+    public static String getDictLabel(String dictType, String dictValue)
+    {
+        if (StringUtils.isNotEmpty(dictType) && StringUtils.isNotEmpty(dictValue))
+        {
+            List<SysDictData> datas = getDictCache(dictType);
+            if (StringUtils.isNotEmpty(datas))
+            {
+                for (SysDictData dict : datas)
+                {
+                    if (dictValue.equals(dict.getDictValue()))
+                    {
+                        return dict.getDictLabel();
+                    }
+                }
+            }
+        }
+        return dictValue;
+    }
+
+    /**
+     * 根据字典类型和字典标签获取字典值
+     * 
+     * @param dictType 字典类型
+     * @param dictLabel 字典标签
+     * @return 字典值
+     */
+    public static String getDictValue(String dictType, String dictLabel)
+    {
+        if (StringUtils.isNotEmpty(dictType) && StringUtils.isNotEmpty(dictLabel))
+        {
+            List<SysDictData> datas = getDictCache(dictType);
+            if (StringUtils.isNotEmpty(datas))
+            {
+                for (SysDictData dict : datas)
+                {
+                    if (dictLabel.equals(dict.getDictLabel()))
+                    {
+                        return dict.getDictValue();
+                    }
+                }
+            }
+        }
+        return dictLabel;
+    }
+
     /**
      * 清空字典缓存
      */

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

@@ -50,6 +50,7 @@ import com.ruoyi.common.core.domain.AjaxResult;
 import com.ruoyi.common.core.text.Convert;
 import com.ruoyi.common.exception.CustomException;
 import com.ruoyi.common.utils.DateUtils;
+import com.ruoyi.common.utils.DictUtils;
 import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.common.utils.reflect.ReflectUtils;
 
@@ -270,7 +271,11 @@ public class ExcelUtil<T>
                         }
                         else if (StringUtils.isNotEmpty(attr.readConverterExp()))
                         {
-                            val = reverseByExp(String.valueOf(val), attr.readConverterExp());
+                            val = reverseByExp(Convert.toStr(val), attr.readConverterExp());
+                        }
+                        else if (StringUtils.isNotEmpty(attr.dictType()))
+                        {
+                            val = reverseDictByExp(attr.dictType(), Convert.toStr(val));
                         }
                         ReflectUtils.invokeSetter(entity, propertyName, val);
                     }
@@ -529,13 +534,18 @@ public class ExcelUtil<T>
                 Object value = getTargetValue(vo, field, attr);
                 String dateFormat = attr.dateFormat();
                 String readConverterExp = attr.readConverterExp();
+                String dictType = attr.dictType();
                 if (StringUtils.isNotEmpty(dateFormat) && StringUtils.isNotNull(value))
                 {
                     cell.setCellValue(DateUtils.parseDateToStr(dateFormat, (Date) value));
                 }
                 else if (StringUtils.isNotEmpty(readConverterExp) && StringUtils.isNotNull(value))
                 {
-                    cell.setCellValue(convertByExp(String.valueOf(value), readConverterExp));
+                    cell.setCellValue(convertByExp(Convert.toStr(value), readConverterExp));
+                }
+                else if (StringUtils.isNotEmpty(dictType))
+                {
+                    cell.setCellValue(convertDictByExp(dictType, Convert.toStr(value)));
                 }
                 else
                 {
@@ -666,6 +676,30 @@ public class ExcelUtil<T>
         return propertyValue;
     }
 
+    /**
+     * 解析字典值
+     * 
+     * @param dictType 字典类型
+     * @param dictValue 字典值
+     * @return 字典标签
+     */
+    public static String convertDictByExp(String dictType, String dictValue) throws Exception
+    {
+        return DictUtils.getDictLabel(dictType, dictValue);
+    }
+
+    /**
+     * 反向解析值字典值
+     * 
+     * @param dictType 字典类型
+     * @param dictValue 字典标签
+     * @return 字典值
+     */
+    public static String reverseDictByExp(String dictType, String dictLabel) throws Exception
+    {
+        return DictUtils.getDictValue(dictType, dictLabel);
+    }
+
     /**
      * 编码文件名
      */

+ 24 - 0
ruoyi-framework/src/main/java/com/ruoyi/framework/config/ResourcesConfig.java

@@ -1,7 +1,11 @@
 package com.ruoyi.framework.config;
 
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
+import org.springframework.web.cors.CorsConfiguration;
+import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
+import org.springframework.web.filter.CorsFilter;
 import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
 import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
 import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@@ -39,4 +43,24 @@ public class ResourcesConfig implements WebMvcConfigurer
     {
         registry.addInterceptor(repeatSubmitInterceptor).addPathPatterns("/**");
     }
+
+    /**
+     * 跨域配置
+     */
+    @Bean
+    public CorsFilter corsFilter()
+    {
+        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
+        CorsConfiguration config = new CorsConfiguration();
+        config.setAllowCredentials(true);
+        // 设置访问源地址
+        config.addAllowedOrigin("*");
+        // 设置访问源请求头
+        config.addAllowedHeader("*");
+        // 设置访问源请求方法
+        config.addAllowedMethod("*");
+        // 对接口配置跨域设置
+        source.registerCorsConfiguration("/**", config);
+        return new CorsFilter(source);
+    }
 }

+ 11 - 0
ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java

@@ -12,6 +12,8 @@ import org.springframework.security.config.http.SessionCreationPolicy;
 import org.springframework.security.core.userdetails.UserDetailsService;
 import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
 import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
+import org.springframework.security.web.authentication.logout.LogoutFilter;
+import org.springframework.web.filter.CorsFilter;
 import com.ruoyi.framework.security.filter.JwtAuthenticationTokenFilter;
 import com.ruoyi.framework.security.handle.AuthenticationEntryPointImpl;
 import com.ruoyi.framework.security.handle.LogoutSuccessHandlerImpl;
@@ -47,6 +49,12 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter
      */
     @Autowired
     private JwtAuthenticationTokenFilter authenticationTokenFilter;
+
+    /**
+     * 跨域过滤器
+     */
+    @Autowired
+    private CorsFilter corsFilter;
     
     /**
      * 解决 无法直接注入 AuthenticationManager
@@ -112,6 +120,9 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter
         httpSecurity.logout().logoutUrl("/logout").logoutSuccessHandler(logoutSuccessHandler);
         // 添加JWT filter
         httpSecurity.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
+        // 添加CORS filter
+        httpSecurity.addFilterBefore(corsFilter, JwtAuthenticationTokenFilter.class);
+        httpSecurity.addFilterBefore(corsFilter, LogoutFilter.class);
     }
 
     

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

@@ -178,6 +178,8 @@ public class GenController extends BaseController
     private void genCode(HttpServletResponse response, byte[] data) throws IOException
     {
         response.reset();
+        response.addHeader("Access-Control-Allow-Origin", "*");
+        response.addHeader("Access-Control-Expose-Headers", "Content-Disposition");
         response.setHeader("Content-Disposition", "attachment; filename=\"ruoyi.zip\"");
         response.addHeader("Content-Length", "" + data.length);
         response.setContentType("application/octet-stream; charset=UTF-8");

+ 27 - 1
ruoyi-generator/src/main/java/com/ruoyi/generator/domain/GenTable.java

@@ -74,6 +74,12 @@ public class GenTable extends BaseEntity
     /** 树名称字段 */
     private String treeName;
 
+    /** 上级菜单ID字段 */
+    private String parentMenuId;
+
+    /** 上级菜单名称字段 */
+    private String parentMenuName;
+
     public Long getTableId()
     {
         return tableId;
@@ -234,6 +240,26 @@ public class GenTable extends BaseEntity
         this.treeName = treeName;
     }
 
+    public String getParentMenuId()
+    {
+        return parentMenuId;
+    }
+
+    public void setParentMenuId(String parentMenuId)
+    {
+        this.parentMenuId = parentMenuId;
+    }
+
+    public String getParentMenuName()
+    {
+        return parentMenuName;
+    }
+
+    public void setParentMenuName(String parentMenuName)
+    {
+        this.parentMenuName = parentMenuName;
+    }
+
     public boolean isTree()
     {
         return isTree(this.tplCategory);
@@ -268,4 +294,4 @@ public class GenTable extends BaseEntity
         }
         return StringUtils.equalsAnyIgnoreCase(javaField, GenConstants.BASE_ENTITY);
     }
-}
+}

+ 6 - 1
ruoyi-generator/src/main/java/com/ruoyi/generator/service/GenTableServiceImpl.java

@@ -337,9 +337,14 @@ public class GenTableServiceImpl implements IGenTableService
             String treeCode = paramsObj.getString(GenConstants.TREE_CODE);
             String treeParentCode = paramsObj.getString(GenConstants.TREE_PARENT_CODE);
             String treeName = paramsObj.getString(GenConstants.TREE_NAME);
+            String parentMenuId = paramsObj.getString(GenConstants.PARENT_MENU_ID);
+            String parentMenuName = paramsObj.getString(GenConstants.PARENT_MENU_NAME);
+            
             genTable.setTreeCode(treeCode);
             genTable.setTreeParentCode(treeParentCode);
             genTable.setTreeName(treeName);
+            genTable.setParentMenuId(parentMenuId);
+            genTable.setParentMenuName(parentMenuName);
         }
     }
-}
+}

+ 32 - 10
ruoyi-generator/src/main/java/com/ruoyi/generator/util/VelocityUtils.java

@@ -11,18 +11,16 @@ import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.generator.domain.GenTable;
 import com.ruoyi.generator.domain.GenTableColumn;
 
-/**
- * 代码生成模板处理
- * 
- * @author ruoyi
- */
 public class VelocityUtils
 {
     /** 项目空间路径 */
     private static final String PROJECT_PATH = "main/java";
 
     /** mybatis空间路径 */
-    private static final String MYBATIS_PATH = "main/resources/mapper";
+    private static final String MYBATIS_PATH = "main/resources/mybatis";
+
+    /** 默认上级菜单,系统工具 */
+    private static final String DEFAULT_PARENT_MENU_ID = "3";
 
     /**
      * 设置模板变量信息
@@ -55,6 +53,7 @@ public class VelocityUtils
         velocityContext.put("permissionPrefix", getPermissionPrefix(moduleName, businessName));
         velocityContext.put("columns", genTable.getColumns());
         velocityContext.put("table", genTable);
+        setMenuVelocityContext(velocityContext, genTable);
         if (GenConstants.TPL_TREE.equals(tplCategory))
         {
             setTreeVelocityContext(velocityContext, genTable);
@@ -62,6 +61,14 @@ public class VelocityUtils
         return velocityContext;
     }
 
+    public static void setMenuVelocityContext(VelocityContext context, GenTable genTable)
+    {
+        String options = genTable.getOptions();
+        JSONObject paramsObj = JSONObject.parseObject(options);
+        String parentMenuId = getParentMenuId(paramsObj);
+        context.put("parentMenuId", parentMenuId);
+    }
+
     public static void setTreeVelocityContext(VelocityContext context, GenTable genTable)
     {
         String options = genTable.getOptions();
@@ -224,6 +231,21 @@ public class VelocityUtils
 
     }
 
+    /**
+     * 获取上级菜单ID字段
+     * 
+     * @param options 生成其他选项
+     * @return 上级菜单ID字段
+     */
+    public static String getParentMenuId(JSONObject paramsObj)
+    {
+        if (StringUtils.isNotEmpty(paramsObj) && paramsObj.containsKey(GenConstants.PARENT_MENU_ID))
+        {
+            return paramsObj.getString(GenConstants.PARENT_MENU_ID);
+        }
+        return DEFAULT_PARENT_MENU_ID;
+    }
+
     /**
      * 获取树编码
      * 
@@ -236,7 +258,7 @@ public class VelocityUtils
         {
             return StringUtils.toCamelCase(paramsObj.getString(GenConstants.TREE_CODE));
         }
-        return "";
+        return StringUtils.EMPTY;
     }
 
     /**
@@ -251,7 +273,7 @@ public class VelocityUtils
         {
             return StringUtils.toCamelCase(paramsObj.getString(GenConstants.TREE_PARENT_CODE));
         }
-        return "";
+        return StringUtils.EMPTY;
     }
 
     /**
@@ -266,7 +288,7 @@ public class VelocityUtils
         {
             return StringUtils.toCamelCase(paramsObj.getString(GenConstants.TREE_NAME));
         }
-        return "";
+        return StringUtils.EMPTY;
     }
 
     /**
@@ -295,4 +317,4 @@ public class VelocityUtils
         }
         return num;
     }
-}
+}

+ 1 - 1
ruoyi-generator/src/main/resources/vm/sql/sql.vm

@@ -1,6 +1,6 @@
 -- 菜单 SQL
 insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
-values('${functionName}', '3', '1', '${businessName}', '${moduleName}/${businessName}/index', 1, 'C', '0', '0', '${permissionPrefix}:list', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '${functionName}菜单');
+values('${functionName}', '${parentMenuId}', '1', '${businessName}', '${moduleName}/${businessName}/index', 1, 'C', '0', '0', '${permissionPrefix}:list', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '${functionName}菜单');
 
 -- 按钮父菜单ID
 SELECT @parentId := LAST_INSERT_ID();

+ 8 - 5
ruoyi-ui/src/utils/index.js

@@ -1,14 +1,16 @@
+import { parseTime } from './ruoyi'
+
 /**
  * 表格时间格式化
  */
 export function formatDate(cellValue) {
   if (cellValue == null || cellValue == "") return "";
-  var date = new Date(cellValue)
+  var date = new Date(cellValue) 
   var year = date.getFullYear()
   var month = date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1
-  var day = date.getDate() < 10 ? '0' + date.getDate() : date.getDate()
-  var hours = date.getHours() < 10 ? '0' + date.getHours() : date.getHours()
-  var minutes = date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes()
+  var day = date.getDate() < 10 ? '0' + date.getDate() : date.getDate() 
+  var hours = date.getHours() < 10 ? '0' + date.getHours() : date.getHours() 
+  var minutes = date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes() 
   var seconds = date.getSeconds() < 10 ? '0' + date.getSeconds() : date.getSeconds()
   return year + '-' + month + '-' + day + ' ' + hours + ':' + minutes + ':' + seconds
 }
@@ -328,7 +330,7 @@ export function makeMap(str, expectsLowerCase) {
     ? val => map[val.toLowerCase()]
     : val => map[val]
 }
-
+ 
 export const exportDefault = 'export default '
 
 export const beautifierConf = {
@@ -385,3 +387,4 @@ export function camelCase(str) {
 export function isNumberStr(str) {
   return /^[+-]?(0|([1-9]\d*))(\.\d+)?$/g.test(str)
 }
+ 

+ 3 - 3
ruoyi-ui/src/utils/ruoyi.js

@@ -68,10 +68,10 @@ export function addDateRange(params, dateRange) {
 // 回显数据字典
 export function selectDictLabel(datas, value) {
 	var actions = [];
-	Object.keys(datas).map((key) => {
+	Object.keys(datas).some((key) => {
 		if (datas[key].dictValue == ('' + value)) {
 			actions.push(datas[key].dictLabel);
-			return false;
+			return true;
 		}
 	})
 	return actions.join('');
@@ -131,4 +131,4 @@ export function handleTree(data, id, parentId, children, rootId) {
 	});
 	return treeData != '' ? treeData : data;
   }
-  
+  

+ 11 - 2
ruoyi-ui/src/views/tool/gen/editTable.vue

@@ -110,7 +110,7 @@
         </el-table>
       </el-tab-pane>
       <el-tab-pane label="生成信息" name="genInfo">
-        <gen-info-form ref="genInfo" :info="info" />
+        <gen-info-form ref="genInfo" :info="info" :menus="menus"/>
       </el-tab-pane>
     </el-tabs>
     <el-form label-width="100px">
@@ -124,9 +124,11 @@
 <script>
 import { getGenTable, updateGenTable } from "@/api/tool/gen";
 import { optionselect as getDictOptionselect } from "@/api/system/dict/type";
+import { listMenu as getMenuTreeselect } from "@/api/system/menu";
 import basicInfoForm from "./basicInfoForm";
 import genInfoForm from "./genInfoForm";
 import Sortable from 'sortablejs'
+
 export default {
   name: "GenEdit",
   components: {
@@ -143,6 +145,8 @@ export default {
       cloumns: [],
       // 字典信息
       dictOptions: [],
+      // 菜单信息
+      menus: [],
       // 表详细信息
       info: {}
     };
@@ -159,6 +163,10 @@ export default {
       getDictOptionselect().then(response => {
         this.dictOptions = response.data;
       });
+      /** 查询菜单下拉列表 */
+      getMenuTreeselect().then(response => {
+        this.menus = this.handleTree(response.data, "menuId");
+      });
     }
   },
   methods: {
@@ -174,7 +182,8 @@ export default {
           genTable.params = {
             treeCode: genTable.treeCode,
             treeName: genTable.treeName,
-            treeParentCode: genTable.treeParentCode
+            treeParentCode: genTable.treeParentCode,
+            parentMenuId: genTable.parentMenuId
           };
           updateGenTable(genTable).then(res => {
             this.msgSuccess(res.msg);

+ 35 - 2
ruoyi-ui/src/views/tool/gen/genInfoForm.vue

@@ -58,6 +58,18 @@
           <el-input v-model="info.functionName" />
         </el-form-item>
       </el-col>
+
+      <el-col :span="12">
+        <el-form-item prop="functionName">
+          <span slot="label">
+            上级菜单
+            <el-tooltip content="分配到指定菜单下,例如 系统管理" placement="top">
+              <i class="el-icon-question"></i>
+            </el-tooltip>
+          </span>
+          <treeselect :append-to-body="true" v-model="info.parentMenuId" :options="menus" :normalizer="normalizer" :show-count="true" placeholder="请选择系统菜单"/>
+        </el-form-item>
+      </el-col>
     </el-row>
 
     <el-row v-show="info.tplCategory == 'tree'">
@@ -120,13 +132,21 @@
   </el-form>
 </template>
 <script>
+import Treeselect from "@riophae/vue-treeselect";
+import "@riophae/vue-treeselect/dist/vue-treeselect.css";
+
 export default {
   name: "BasicInfoForm",
+  components: { Treeselect },
   props: {
     info: {
       type: Object,
       default: null
-    }
+    },
+    menus: {
+      type: Array,
+      default: []
+    },
   },
   data() {
     return {
@@ -149,6 +169,19 @@ export default {
       }
     };
   },
-  created() {}
+  created() {},
+  methods: {
+    /** 转换菜单数据结构 */
+    normalizer(node) {
+      if (node.children && !node.children.length) {
+        delete node.children;
+      }
+      return {
+        id: node.menuId,
+        label: node.menuName,
+        children: node.children
+      };
+    }
+  }
 };
 </script>

+ 2 - 2
ruoyi-ui/src/views/tool/gen/importTable.vue

@@ -28,8 +28,8 @@
     <el-row>
       <el-table @row-click="clickRow" ref="table" :data="dbTableList" @selection-change="handleSelectionChange" height="260px">
         <el-table-column type="selection" width="55"></el-table-column>
-        <el-table-column prop="tableName" label="表名称"></el-table-column>
-        <el-table-column prop="tableComment" label="表描述"></el-table-column>
+        <el-table-column prop="tableName" label="表名称" :show-overflow-tooltip="true"></el-table-column>
+        <el-table-column prop="tableComment" label="表描述" :show-overflow-tooltip="true"></el-table-column>
         <el-table-column prop="createTime" label="创建时间"></el-table-column>
         <el-table-column prop="updateTime" label="更新时间"></el-table-column>
       </el-table>