Merge branch 'master' of https://gitee.com/y_project/RuoYi-Vue
Conflicts:
ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CommonController.java
ruoyi-admin/src/main/resources/application.yml
ruoyi-common/src/main/java/com/ruoyi/common/constant/GenConstants.java
ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUtils.java
ruoyi-generator/src/main/java/com/ruoyi/generator/domain/GenTableColumn.java
ruoyi-generator/src/main/java/com/ruoyi/generator/util/GenUtils.java
ruoyi-generator/src/main/resources/vm/vue/index.vue.vm
ruoyi-ui/package.json
ruoyi-ui/src/views/index.vue
ruoyi-ui/src/views/tool/gen/editTable.vue
| | |
| | |
|
| | | <groupId>com.ruoyi</groupId>
|
| | | <artifactId>ruoyi</artifactId>
|
| | | <version>3.2.0</version>
|
| | | <version>3.2.1</version>
|
| | |
|
| | | <name>ruoyi</name>
|
| | | <url>http://www.ruoyi.vip</url>
|
| | | <description>è¥ä¾ç®¡çç³»ç»</description>
|
| | |
|
| | | <properties>
|
| | | <ruoyi.version>3.2.0</ruoyi.version>
|
| | | <ruoyi.version>3.2.1</ruoyi.version>
|
| | | <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
| | | <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
| | | <java.version>1.8</java.version>
|
| | |
| | | <parent>
|
| | | <artifactId>ruoyi</artifactId>
|
| | | <groupId>com.ruoyi</groupId>
|
| | | <version>3.2.0</version>
|
| | | <version>3.2.1</version>
|
| | | </parent>
|
| | | <modelVersion>4.0.0</modelVersion>
|
| | | <packaging>jar</packaging>
|
| | |
| | | import org.slf4j.Logger; |
| | | import org.slf4j.LoggerFactory; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.http.MediaType; |
| | | import org.springframework.web.bind.annotation.GetMapping; |
| | | import org.springframework.web.bind.annotation.PostMapping; |
| | | import org.springframework.web.bind.annotation.RestController; |
| | |
| | | { |
| | | try |
| | | { |
| | | if (!FileUtils.isValidFilename(fileName)) |
| | | if (!FileUtils.checkAllowDownload(fileName)) |
| | | { |
| | | throw new Exception(StringUtils.format("æä»¶åç§°({})éæ³ï¼ä¸å
许ä¸è½½ã ", fileName)); |
| | | } |
| | | String realFileName = System.currentTimeMillis() + fileName.substring(fileName.indexOf("_") + 1); |
| | | String filePath = RuoYiConfig.getDownloadPath() + fileName; |
| | | |
| | | response.setCharacterEncoding("utf-8"); |
| | | response.setContentType("multipart/form-data"); |
| | | response.setHeader("Content-Disposition", |
| | | "attachment;fileName=" + FileUtils.setFileDownloadHeader(request, realFileName)); |
| | | response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE); |
| | | FileUtils.setAttachmentResponseHeader(response, realFileName); |
| | | FileUtils.writeBytes(filePath, response.getOutputStream()); |
| | | if (delete) |
| | | { |
| | |
| | | * æ¬å°èµæºéç¨ä¸è½½ |
| | | */ |
| | | @GetMapping("/common/download/resource") |
| | | public void resourceDownload(String name, HttpServletRequest request, HttpServletResponse response) throws Exception |
| | | public void resourceDownload(String resource, HttpServletRequest request, HttpServletResponse response) |
| | | throws Exception |
| | | { |
| | | // æ¬å°èµæºè·¯å¾ |
| | | String localPath = RuoYiConfig.getProfile(); |
| | | // æ°æ®åºèµæºå°å |
| | | String downloadPath = localPath + StringUtils.substringAfter(name, Constants.RESOURCE_PREFIX); |
| | | // ä¸è½½åç§° |
| | | String downloadName = StringUtils.substringAfterLast(downloadPath, "/"); |
| | | response.setCharacterEncoding("utf-8"); |
| | | response.setContentType("multipart/form-data"); |
| | | response.setHeader("Content-Disposition", |
| | | "attachment;fileName=" + FileUtils.setFileDownloadHeader(request, downloadName)); |
| | | FileUtils.writeBytes(downloadPath, response.getOutputStream()); |
| | | try |
| | | { |
| | | if (!FileUtils.checkAllowDownload(resource)) |
| | | { |
| | | throw new Exception(StringUtils.format("èµæºæä»¶({})éæ³ï¼ä¸å
许ä¸è½½ã ", resource)); |
| | | } |
| | | // æ¬å°èµæºè·¯å¾ |
| | | String localPath = RuoYiConfig.getProfile(); |
| | | // æ°æ®åºèµæºå°å |
| | | String downloadPath = localPath + StringUtils.substringAfter(resource, Constants.RESOURCE_PREFIX); |
| | | // ä¸è½½åç§° |
| | | String downloadName = StringUtils.substringAfterLast(downloadPath, "/"); |
| | | response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE); |
| | | FileUtils.setAttachmentResponseHeader(response, downloadName); |
| | | FileUtils.writeBytes(downloadPath, response.getOutputStream()); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | log.error("ä¸è½½æä»¶å¤±è´¥", e); |
| | | } |
| | | } |
| | | } |
| | |
| | | # åç§° |
| | | name: RuoYi |
| | | # çæ¬ |
| | | version: 3.2.0 |
| | | version: 3.2.1 |
| | | # çæå¹´ä»½ |
| | | copyrightYear: 2020 |
| | | # å®ä¾æ¼ç¤ºå¼å
³ |
| | |
| | | secret: abcdefghijklmnopqrstuvwxyz |
| | | # ä»¤çæææï¼é»è®¤30åéï¼ |
| | | expireTime: 30 |
| | | |
| | | |
| | | # MyBatisé
ç½® |
| | | # https://baomidou.com/config/ |
| | | mybatis-plus: |
| | |
| | | <parent>
|
| | | <artifactId>ruoyi</artifactId>
|
| | | <groupId>com.ruoyi</groupId>
|
| | | <version>3.2.0</version>
|
| | | <version>3.2.1</version>
|
| | | </parent>
|
| | | <modelVersion>4.0.0</modelVersion>
|
| | |
|
| | |
| | | /** æ¥ææ§ä»¶ */ |
| | | public static final String HTML_DATETIME = "datetime"; |
| | | |
| | | /** ä¸ä¼ æ§ä»¶ */ |
| | | public static final String HTML_UPLOAD_IMAGE = "uploadImage"; |
| | | |
| | | /** å¯ææ¬æ§ä»¶ */ |
| | | public static final String HTML_EDITOR = "editor"; |
| | | |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package com.ruoyi.common.utils.file;
|
| | |
|
| | | import java.io.File;
|
| | | import org.apache.commons.lang3.StringUtils;
|
| | |
|
| | | /**
|
| | | * æä»¶ç±»åå·¥å
·ç±»
|
| | | *
|
| | | * @author ruoyi
|
| | | */
|
| | | public class FileTypeUtils
|
| | | {
|
| | | /**
|
| | | * è·åæä»¶ç±»å
|
| | | * <p>
|
| | | * ä¾å¦: ruoyi.txt, è¿å: txt
|
| | | * |
| | | * @param file æä»¶å
|
| | | * @return åç¼ï¼ä¸å«".")
|
| | | */
|
| | | public static String getFileType(File file)
|
| | | {
|
| | | if (null == file)
|
| | | {
|
| | | return StringUtils.EMPTY;
|
| | | }
|
| | | return getFileType(file.getName());
|
| | | }
|
| | |
|
| | | /**
|
| | | * è·åæä»¶ç±»å
|
| | | * <p>
|
| | | * ä¾å¦: ruoyi.txt, è¿å: txt
|
| | | *
|
| | | * @param fileName æä»¶å
|
| | | * @return åç¼ï¼ä¸å«".")
|
| | | */
|
| | | public static String getFileType(String fileName)
|
| | | {
|
| | | int separatorIndex = fileName.lastIndexOf(".");
|
| | | if (separatorIndex < 0)
|
| | | {
|
| | | return "";
|
| | | }
|
| | | return fileName.substring(separatorIndex + 1).toLowerCase();
|
| | | }
|
| | | } |
| | |
| | | import java.io.OutputStream; |
| | | import java.io.UnsupportedEncodingException; |
| | | import java.net.URLEncoder; |
| | | import java.nio.charset.StandardCharsets; |
| | | import javax.servlet.http.HttpServletRequest; |
| | | import javax.servlet.http.HttpServletResponse; |
| | | import org.apache.commons.lang3.ArrayUtils; |
| | | import com.ruoyi.common.utils.StringUtils; |
| | | |
| | | /** |
| | | * æä»¶å¤çå·¥å
·ç±» |
| | |
| | | } |
| | | |
| | | /** |
| | | * æ£æ¥æä»¶æ¯å¦å¯ä¸è½½ |
| | | * |
| | | * @param resource éè¦ä¸è½½çæä»¶ |
| | | * @return true æ£å¸¸ false éæ³ |
| | | */ |
| | | public static boolean checkAllowDownload(String resource) |
| | | { |
| | | // ç¦æ¢ç®å½ä¸è·³çº§å« |
| | | if (StringUtils.contains(resource, "..")) |
| | | { |
| | | return false; |
| | | } |
| | | |
| | | // æ£æ¥å
许ä¸è½½çæä»¶è§å |
| | | if (ArrayUtils.contains(MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION, FileTypeUtils.getFileType(resource))) |
| | | { |
| | | return true; |
| | | } |
| | | |
| | | // ä¸å¨å
许ä¸è½½çæä»¶è§å |
| | | return false; |
| | | } |
| | | |
| | | /** |
| | | * ä¸è½½æä»¶åéæ°ç¼ç |
| | | * |
| | | * @param request 请æ±å¯¹è±¡ |
| | | * @param fileName æä»¶å |
| | | * @return ç¼ç åçæä»¶å |
| | | */ |
| | | public static String setFileDownloadHeader(HttpServletRequest request, String fileName) |
| | | throws UnsupportedEncodingException |
| | | public static String setFileDownloadHeader(HttpServletRequest request, String fileName) throws UnsupportedEncodingException |
| | | { |
| | | final String agent = request.getHeader("USER-AGENT"); |
| | | String filename = fileName; |
| | |
| | | } |
| | | return filename; |
| | | } |
| | | |
| | | /** |
| | | * ä¸è½½æä»¶åéæ°ç¼ç |
| | | * |
| | | * @param response ååºå¯¹è±¡ |
| | | * @param realFileName ç宿件å |
| | | * @return |
| | | */ |
| | | public static void setAttachmentResponseHeader(HttpServletResponse response, String realFileName) throws UnsupportedEncodingException |
| | | { |
| | | String percentEncodedFileName = percentEncode(realFileName); |
| | | |
| | | StringBuilder contentDispositionValue = new StringBuilder(); |
| | | contentDispositionValue.append("attachment; filename=") |
| | | .append(percentEncodedFileName) |
| | | .append(";") |
| | | .append("filename*=") |
| | | .append("utf-8''") |
| | | .append(percentEncodedFileName); |
| | | |
| | | response.setHeader("Content-disposition", contentDispositionValue.toString()); |
| | | } |
| | | |
| | | /** |
| | | * ç¾åå·ç¼ç å·¥å
·æ¹æ³ |
| | | * |
| | | * @param s éè¦ç¾åå·ç¼ç çå符串 |
| | | * @return ç¾åå·ç¼ç åçå符串 |
| | | */ |
| | | public static String percentEncode(String s) throws UnsupportedEncodingException |
| | | { |
| | | String encode = URLEncoder.encode(s, StandardCharsets.UTF_8.toString()); |
| | | return encode.replaceAll("\\+", "%20"); |
| | | } |
| | | } |
| | |
| | | <parent>
|
| | | <artifactId>ruoyi</artifactId>
|
| | | <groupId>com.ruoyi</groupId>
|
| | | <version>3.2.0</version>
|
| | | <version>3.2.1</version>
|
| | | </parent>
|
| | | <modelVersion>4.0.0</modelVersion>
|
| | |
|
| | |
| | | <parent>
|
| | | <artifactId>ruoyi</artifactId>
|
| | | <groupId>com.ruoyi</groupId>
|
| | | <version>3.2.0</version>
|
| | | <version>3.2.1</version>
|
| | | </parent>
|
| | | <modelVersion>4.0.0</modelVersion>
|
| | |
|
| | |
| | | /** æ¥è¯¢æ¹å¼ï¼EQçäºãNEä¸çäºãGT大äºãLTå°äºãLIKE模ç³ãBETWEENèå´ï¼ */ |
| | | private String queryType; |
| | | |
| | | /** æ¾ç¤ºç±»åï¼inputææ¬æ¡ãtextareaææ¬åãselect䏿æ¡ãcheckboxå¤éæ¡ãradioåéæ¡ãdatetimeæ¥ææ§ä»¶ãeditorå¯ææ¬æ§ä»¶ï¼ */ |
| | | /** æ¾ç¤ºç±»åï¼inputææ¬æ¡ãtextareaææ¬åãselect䏿æ¡ãcheckboxå¤éæ¡ãradioåéæ¡ãdatetimeæ¥ææ§ä»¶ãuploadä¸ä¼ æ§ä»¶ãeditorå¯ææ¬æ§ä»¶ï¼ */ |
| | | private String htmlType; |
| | | |
| | | /** åå
¸ç±»å */ |
| | |
| | | { |
| | | column.setHtmlType(GenConstants.HTML_SELECT); |
| | | } |
| | | // æä»¶å段设置ä¸ä¼ æ§ä»¶ |
| | | else if (StringUtils.endsWithIgnoreCase(columnName, "image")) |
| | | { |
| | | column.setHtmlType(GenConstants.HTML_UPLOAD_IMAGE); |
| | | } |
| | | // å
容忮µè®¾ç½®å¯ææ¬æ§ä»¶ |
| | | else if (StringUtils.endsWithIgnoreCase(columnName, "content")) |
| | | { |
| | |
| | | <el-form-item label="${comment}" prop="${field}">
|
| | | <el-input v-model="form.${field}" placeholder="请è¾å
¥${comment}" />
|
| | | </el-form-item>
|
| | | #elseif($column.htmlType == "uploadImage")
|
| | | <el-form-item label="${comment}">
|
| | | <uploadImage v-model="form.${field}"/>
|
| | | </el-form-item>
|
| | | #elseif($column.htmlType == "editor")
|
| | | <el-form-item label="${comment}">
|
| | | <editor v-model="form.${field}" :min-height="192"/>
|
| | |
| | | import Treeselect from "@riophae/vue-treeselect";
|
| | | import "@riophae/vue-treeselect/dist/vue-treeselect.css";
|
| | | #foreach($column in $columns)
|
| | | #if($column.insert && !$column.superColumn && !$column.pk && $column.htmlType == "uploadImage")
|
| | | import UploadImage from '@/components/UploadImage';
|
| | | #break
|
| | | #end
|
| | | #end
|
| | | #foreach($column in $columns)
|
| | | #if($column.insert && !$column.superColumn && !$column.pk && $column.htmlType == "editor")
|
| | | import Editor from '@/components/Editor';
|
| | | #break
|
| | |
| | | name: "${BusinessName}",
|
| | | components: {
|
| | | #foreach($column in $columns)
|
| | | #if($column.insert && !$column.superColumn && !$column.pk && $column.htmlType == "uploadImage")
|
| | | UploadImage,
|
| | | #break
|
| | | #end
|
| | | #end
|
| | | #foreach($column in $columns)
|
| | | #if($column.insert && !$column.superColumn && !$column.pk && $column.htmlType == "editor")
|
| | | Editor,
|
| | | #break
|
| | |
| | | <el-form-item label="${comment}" prop="${field}"> |
| | | <el-input v-model="form.${field}" placeholder="请è¾å
¥${comment}" /> |
| | | </el-form-item> |
| | | #elseif($column.htmlType == "uploadImage") |
| | | <el-form-item label="${comment}"> |
| | | <uploadImage v-model="form.${field}"/> |
| | | </el-form-item> |
| | | #elseif($column.htmlType == "editor") |
| | | <el-form-item label="${comment}"> |
| | | <editor v-model="form.${field}" :min-height="192"/> |
| | |
| | | <script> |
| | | import { list${BusinessName}, get${BusinessName}, del${BusinessName}, add${BusinessName}, update${BusinessName}, export${BusinessName} } from "@/api/${moduleName}/${businessName}"; |
| | | #foreach($column in $columns) |
| | | #if($column.insert && !$column.superColumn && !$column.pk && $column.htmlType == "uploadImage") |
| | | import UploadImage from '@/components/UploadImage'; |
| | | #break |
| | | #end |
| | | #end |
| | | #foreach($column in $columns) |
| | | #if($column.insert && !$column.superColumn && !$column.pk && $column.htmlType == "editor") |
| | | import Editor from '@/components/Editor'; |
| | | #break |
| | |
| | | |
| | | export default { |
| | | name: "${BusinessName}", |
| | | components: { |
| | | #foreach($column in $columns) |
| | | #if($column.insert && !$column.superColumn && !$column.pk && $column.htmlType == "editor") |
| | | components: { Editor }, |
| | | #if($column.insert && !$column.superColumn && !$column.pk && $column.htmlType == "uploadImage") |
| | | UploadImage, |
| | | #break |
| | | #end |
| | | #end |
| | | #foreach($column in $columns) |
| | | #if($column.insert && !$column.superColumn && !$column.pk && $column.htmlType == "editor") |
| | | Editor, |
| | | #break |
| | | #end |
| | | #end |
| | | }, |
| | | data() { |
| | | return { |
| | | // é®ç½©å± |
| | |
| | | <parent>
|
| | | <artifactId>ruoyi</artifactId>
|
| | | <groupId>com.ruoyi</groupId>
|
| | | <version>3.2.0</version>
|
| | | <version>3.2.1</version>
|
| | | </parent>
|
| | | <modelVersion>4.0.0</modelVersion>
|
| | |
|
| | |
| | | <parent>
|
| | | <artifactId>ruoyi</artifactId>
|
| | | <groupId>com.ruoyi</groupId>
|
| | | <version>3.2.0</version>
|
| | | <version>3.2.1</version>
|
| | | </parent>
|
| | | <modelVersion>4.0.0</modelVersion>
|
| | |
|
| | |
| | | { |
| | | "name": "ruoyi", |
| | | "version": "3.2.0", |
| | | "version": "3.2.1", |
| | | "description": "è¥ä¾ç®¡çç³»ç»", |
| | | "author": "è¥ä¾", |
| | | "license": "MIT", |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <template>
|
| | | <div class="component-upload-image">
|
| | | <el-upload
|
| | | :action="uploadImgUrl"
|
| | | list-type="picture-card"
|
| | | :on-success="handleUploadSuccess"
|
| | | :before-upload="handleBeforeUpload"
|
| | | :on-error="handleUploadError"
|
| | | name="file"
|
| | | :show-file-list="false"
|
| | | :headers="headers"
|
| | | style="display: inline-block; vertical-align: top"
|
| | | >
|
| | | <img v-if="value" :src="value" class="avatar" />
|
| | | <i v-else class="el-icon-plus avatar-uploader-icon"></i>
|
| | | </el-upload>
|
| | | </div>
|
| | | </template>
|
| | |
|
| | | <script>
|
| | | import { getToken } from "@/utils/auth";
|
| | |
|
| | | export default {
|
| | | components: {},
|
| | | data() {
|
| | | return {
|
| | | uploadImgUrl: process.env.VUE_APP_BASE_API + "/common/upload", // ä¸ä¼ çå¾çæå¡å¨å°å
|
| | | headers: {
|
| | | Authorization: "Bearer " + getToken(),
|
| | | },
|
| | | };
|
| | | },
|
| | | props: {
|
| | | value: {
|
| | | type: String,
|
| | | default: "",
|
| | | },
|
| | | },
|
| | | methods: {
|
| | | handleUploadSuccess(res) {
|
| | | this.$emit("input", res.url);
|
| | | this.loading.close();
|
| | | },
|
| | | handleBeforeUpload() {
|
| | | this.loading = this.$loading({
|
| | | lock: true,
|
| | | text: "ä¸ä¼ ä¸",
|
| | | background: "rgba(0, 0, 0, 0.7)",
|
| | | });
|
| | | },
|
| | | handleUploadError() {
|
| | | this.$message({
|
| | | type: "error",
|
| | | message: "ä¸ä¼ 失败",
|
| | | });
|
| | | this.loading.close();
|
| | | },
|
| | | },
|
| | | watch: {},
|
| | | };
|
| | | </script>
|
| | |
|
| | | <style scoped lang="scss">
|
| | | .avatar {
|
| | | width: 100%;
|
| | | height: 100%;
|
| | | }
|
| | | </style> |
| | |
| | | <span>æ´æ°æ¥å¿</span> |
| | | </div> |
| | | <el-collapse accordion> |
| | | <el-collapse-item title="v3.2.1 - 2020-11-18"> |
| | | <ol> |
| | | <li>黿¢ä»»ææä»¶ä¸è½½æ¼æ´</li> |
| | | <li>代ç çææ¯æä¸ä¼ æ§ä»¶</li> |
| | | <li>æ°å¢å¾çä¸ä¼ ç»ä»¶</li> |
| | | <li>è°æ´é»è®¤é¦é¡µ</li> |
| | | <li>å级druidå°ææ°çæ¬v1.2.2</li> |
| | | <li>mapperLocationsé
ç½®æ¯æåé符</li> |
| | | <li>æéä¿¡æ¯è°æ´</li> |
| | | <li>è°æ´sqlé»è®¤æ¶é´</li> |
| | | <li>è§£å³ä»£ç çææ²¡æbitç±»åçé®é¢</li> |
| | | <li>å级pagehelperå°ææ°ç1.3.0</li> |
| | | </ol> |
| | | </el-collapse-item> |
| | | <el-collapse-item title="v3.2.0 - 2020-10-10"> |
| | | <ol> |
| | | <li>å级springbootçæ¬å°2.1.17 æåå®å
¨æ§</li> |
| | |
| | | data() { |
| | | return { |
| | | // çæ¬å· |
| | | version: "3.2.0", |
| | | version: "3.2.1", |
| | | }; |
| | | }, |
| | | methods: { |
| | |
| | | <el-option label="åéæ¡" value="radio" /> |
| | | <el-option label="å¤éæ¡" value="checkbox" /> |
| | | <el-option label="æ¥ææ§ä»¶" value="datetime" /> |
| | | <el-option label="ä¸ä¼ æ§ä»¶" value="uploadImage" /> |
| | | <el-option label="å¯ææ¬æ§ä»¶" value="editor" /> |
| | | </el-select> |
| | | </template> |