From f55749417de23e110af2da118e0f7aba0855ebe2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E7=8E=8B=E5=98=89=E8=B1=AA?=
<42510293+ziyujiahao@users.noreply.github.com>
Date: Mon, 25 Apr 2022 12:13:05 +0800
Subject: [PATCH 1/3] =?UTF-8?q?refactor:=20=E8=83=8C=E6=99=AF=E5=9B=BE?=
=?UTF-8?q?=E7=89=87=E7=9B=B4=E6=8E=A5=E5=AD=98=E5=82=A8=E5=9C=A8=E6=9C=8D?=
=?UTF-8?q?=E5=8A=A1=E5=99=A8?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
refactor: 背景图片直接存储在服务器
---
.../auth/service/impl/ShiroServiceImpl.java | 1 +
.../io/dataease/commons/utils/FileUtils.java | 26 +++++++++
.../commons/utils/StaticResourceUtils.java | 54 +++++++++++++++++++
.../java/io/dataease/config/DeMvcConfig.java | 52 ++++++++++++++++++
.../properties/StaticResourceProperties.java | 18 +++++++
.../StaticResourceController.java | 28 ++++++++++
.../staticResource/StaticResourceService.java | 48 +++++++++++++++++
.../src/api/staticResource/staticResource.js | 26 +++++++++
frontend/src/store/index.js | 4 +-
frontend/src/views/background/index.vue | 18 +++----
.../PanelStyle/BackgroundSelector.vue | 22 +++-----
11 files changed, 270 insertions(+), 27 deletions(-)
create mode 100644 backend/src/main/java/io/dataease/commons/utils/FileUtils.java
create mode 100644 backend/src/main/java/io/dataease/commons/utils/StaticResourceUtils.java
create mode 100644 backend/src/main/java/io/dataease/config/DeMvcConfig.java
create mode 100644 backend/src/main/java/io/dataease/config/properties/StaticResourceProperties.java
create mode 100644 backend/src/main/java/io/dataease/controller/staticResource/StaticResourceController.java
create mode 100644 backend/src/main/java/io/dataease/service/staticResource/StaticResourceService.java
create mode 100644 frontend/src/api/staticResource/staticResource.js
diff --git a/backend/src/main/java/io/dataease/auth/service/impl/ShiroServiceImpl.java b/backend/src/main/java/io/dataease/auth/service/impl/ShiroServiceImpl.java
index 1aae87f3de..3466cadd6e 100644
--- a/backend/src/main/java/io/dataease/auth/service/impl/ShiroServiceImpl.java
+++ b/backend/src/main/java/io/dataease/auth/service/impl/ShiroServiceImpl.java
@@ -48,6 +48,7 @@ public class ShiroServiceImpl implements ShiroService {
filterChainDefinitionMap.put("/plugin/theme/themes", ANON);
filterChainDefinitionMap.put("/plugin/theme/items/**", ANON);
filterChainDefinitionMap.put("/plugin/view/types", ANON);
+ filterChainDefinitionMap.put("/static-resource/**", ANON);
// 验证链接
filterChainDefinitionMap.put("/api/link/validate**", ANON);
diff --git a/backend/src/main/java/io/dataease/commons/utils/FileUtils.java b/backend/src/main/java/io/dataease/commons/utils/FileUtils.java
new file mode 100644
index 0000000000..64760511b0
--- /dev/null
+++ b/backend/src/main/java/io/dataease/commons/utils/FileUtils.java
@@ -0,0 +1,26 @@
+package io.dataease.commons.utils;
+
+import org.springframework.lang.NonNull;
+import org.springframework.util.Assert;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+/**
+ * Author: wangjiahao
+ * Date: 2022/4/24
+ * Description:
+ */
+public class FileUtils {
+
+ public static void createIfAbsent(@NonNull Path path) throws IOException {
+ Assert.notNull(path, "Path must not be null");
+
+ if (Files.notExists(path)) {
+ // Create directories
+ Files.createDirectories(path);
+ LogUtil.debug("Created directory: [{}]", path);
+ }
+ }
+}
diff --git a/backend/src/main/java/io/dataease/commons/utils/StaticResourceUtils.java b/backend/src/main/java/io/dataease/commons/utils/StaticResourceUtils.java
new file mode 100644
index 0000000000..cd644a98a0
--- /dev/null
+++ b/backend/src/main/java/io/dataease/commons/utils/StaticResourceUtils.java
@@ -0,0 +1,54 @@
+package io.dataease.commons.utils;
+
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.lang.NonNull;
+import org.springframework.util.Assert;
+
+/**
+ * Author: wangjiahao
+ * Date: 2022/4/24
+ * Description:
+ */
+public class StaticResourceUtils {
+ public static final String URL_SEPARATOR = "/";
+
+ private static final String RE_HTML_MARK = "(<[^<]*?>)|(<[\\s]*?/[^<]*?>)|(<[^<]*?/[\\s]*?>)";
+
+ public static String ensureBoth(@NonNull String string, @NonNull String bothfix) {
+ return ensureBoth(string, bothfix, bothfix);
+ }
+
+ public static String ensureBoth(@NonNull String string, @NonNull String prefix,
+ @NonNull String suffix) {
+ return ensureSuffix(ensurePrefix(string, prefix), suffix);
+ }
+
+ /**
+ * Ensures the string contain prefix.
+ *
+ * @param string string must not be blank
+ * @param prefix prefix must not be blank
+ * @return string contain prefix specified
+ */
+ public static String ensurePrefix(@NonNull String string, @NonNull String prefix) {
+ Assert.hasText(string, "String must not be blank");
+ Assert.hasText(prefix, "Prefix must not be blank");
+
+ return prefix + StringUtils.removeStart(string, prefix);
+ }
+
+
+ /**
+ * Ensures the string contain suffix.
+ *
+ * @param string string must not be blank
+ * @param suffix suffix must not be blank
+ * @return string contain suffix specified
+ */
+ public static String ensureSuffix(@NonNull String string, @NonNull String suffix) {
+ Assert.hasText(string, "String must not be blank");
+ Assert.hasText(suffix, "Suffix must not be blank");
+
+ return StringUtils.removeEnd(string, suffix) + suffix;
+ }
+}
diff --git a/backend/src/main/java/io/dataease/config/DeMvcConfig.java b/backend/src/main/java/io/dataease/config/DeMvcConfig.java
new file mode 100644
index 0000000000..04f73c5217
--- /dev/null
+++ b/backend/src/main/java/io/dataease/config/DeMvcConfig.java
@@ -0,0 +1,52 @@
+package io.dataease.config;
+
+import org.springframework.context.annotation.Configuration;
+import org.springframework.http.CacheControl;
+import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+import java.io.File;
+import java.util.concurrent.TimeUnit;
+
+import static io.dataease.commons.utils.StaticResourceUtils.ensureBoth;
+import static io.dataease.commons.utils.StaticResourceUtils.ensureSuffix;
+
+/**
+ * Author: wangjiahao
+ * Date: 2022/4/24
+ * Description:
+ */
+@Configuration
+public class DeMvcConfig implements WebMvcConfigurer {
+ private static final String FILE_PROTOCOL = "file://";
+ public static final String FILE_SEPARATOR = File.separator;
+ public static final String USER_HOME = "/opt/dataease/data";
+
+ private static String WORK_DIR = ensureSuffix(USER_HOME, FILE_SEPARATOR) + "static-resource" + FILE_SEPARATOR;
+
+
+ /**
+ * Upload prefix.
+ */
+ private final static String UPLOAD_URL_PREFIX = "static-resource";
+
+
+ /**
+ * url separator.
+ */
+ public static final String URL_SEPARATOR = "/";
+
+ /**
+ * Configuring static resource path
+ *
+ * @param registry registry
+ */
+ @Override
+ public void addResourceHandlers(ResourceHandlerRegistry registry) {
+ String workDir = FILE_PROTOCOL + ensureSuffix(WORK_DIR, FILE_SEPARATOR);
+ String uploadUrlPattern = ensureBoth(UPLOAD_URL_PREFIX, URL_SEPARATOR) + "**";
+ registry.addResourceHandler(uploadUrlPattern)
+ .addResourceLocations(workDir);
+
+ }
+}
diff --git a/backend/src/main/java/io/dataease/config/properties/StaticResourceProperties.java b/backend/src/main/java/io/dataease/config/properties/StaticResourceProperties.java
new file mode 100644
index 0000000000..9e49adeb24
--- /dev/null
+++ b/backend/src/main/java/io/dataease/config/properties/StaticResourceProperties.java
@@ -0,0 +1,18 @@
+package io.dataease.config.properties;
+
+import lombok.Data;
+
+/**
+ * Author: wangjiahao
+ * Date: 2022/4/24
+ * Description:
+ */
+@Data
+public class StaticResourceProperties {
+
+ /**
+ * Upload prefix.
+ */
+ private String uploadUrlPrefix = "static-resource";
+
+}
diff --git a/backend/src/main/java/io/dataease/controller/staticResource/StaticResourceController.java b/backend/src/main/java/io/dataease/controller/staticResource/StaticResourceController.java
new file mode 100644
index 0000000000..8f4297289f
--- /dev/null
+++ b/backend/src/main/java/io/dataease/controller/staticResource/StaticResourceController.java
@@ -0,0 +1,28 @@
+package io.dataease.controller.staticResource;
+
+import io.dataease.service.staticResource.StaticResourceService;
+import io.swagger.annotations.ApiOperation;
+import org.pentaho.ui.xul.stereotype.Controller;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.annotation.Resource;
+
+/**
+ * Author: wangjiahao
+ * Date: 2022/4/24
+ * Description:
+ */
+@RestController
+@RequestMapping("/static/resource")
+public class StaticResourceController {
+
+ @Resource
+ StaticResourceService staticResourceService;
+
+ @PostMapping("upload/{fileId}")
+ @ApiOperation("Uploads static file")
+ public void upload(@PathVariable("fileId") String fileId, @RequestPart("file") MultipartFile file) {
+ staticResourceService.upload(fileId,file);
+ }
+}
diff --git a/backend/src/main/java/io/dataease/service/staticResource/StaticResourceService.java b/backend/src/main/java/io/dataease/service/staticResource/StaticResourceService.java
new file mode 100644
index 0000000000..61cc19bacd
--- /dev/null
+++ b/backend/src/main/java/io/dataease/service/staticResource/StaticResourceService.java
@@ -0,0 +1,48 @@
+package io.dataease.service.staticResource;
+
+import io.dataease.commons.utils.FileUtils;
+import io.dataease.commons.utils.LogUtil;
+import io.dataease.exception.DataEaseException;
+import io.swagger.annotations.ApiOperation;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.stereotype.Service;
+import org.springframework.util.Assert;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.IOException;
+import java.net.URLEncoder;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+/**
+ * Author: wangjiahao
+ * Date: 2022/4/24
+ * Description:
+ */
+@Service
+public class StaticResourceService {
+
+ private final Path staticDir = Paths.get("/opt/dataease/data/static-resource/");
+
+ public void upload(String fileId,MultipartFile file) {
+ // check if the path is valid (not outside staticDir)
+ Assert.notNull(file, "Multipart file must not be null");
+ try {
+ String originName = file.getOriginalFilename();
+ String newFileName = fileId+originName.substring(originName.lastIndexOf("."),originName.length());
+ Path uploadPath = Paths.get(staticDir.toString(), newFileName);
+ // create dir is absent
+ FileUtils.createIfAbsent(Paths.get(staticDir.toString()));
+ Files.createFile(uploadPath);
+ file.transferTo(uploadPath);
+ } catch (IOException e) {
+ LogUtil.error("文件上传失败",e);
+ DataEaseException.throwException("文件上传失败");
+ } catch (Exception e){
+ DataEaseException.throwException(e);
+ }
+ }
+}
diff --git a/frontend/src/api/staticResource/staticResource.js b/frontend/src/api/staticResource/staticResource.js
new file mode 100644
index 0000000000..de424b0680
--- /dev/null
+++ b/frontend/src/api/staticResource/staticResource.js
@@ -0,0 +1,26 @@
+import request from '@/utils/request'
+import { uuid } from 'vue-uuid'
+import store from '@/store'
+
+export function uploadFile(fileId, file) {
+ const param = new FormData()
+ param.append('file', file.file)
+ return request({
+ url: '/static/resource/upload/' + fileId,
+ method: 'post',
+ headers: { 'Content-Type': 'multipart/form-data' },
+ data: param,
+ loading: false
+ })
+}
+
+export function uploadFileResult(file, callback) {
+ const fileId = uuid.v1()
+ const fileName = file.file.name
+ const newFileName = fileId + fileName.substr(fileName.lastIndexOf('.'), fileName.length)
+ const fileUrl = store.state.staticResourcePath + newFileName
+ uploadFile(fileId, file).then(() => {
+ callback(fileUrl)
+ })
+}
+
diff --git a/frontend/src/store/index.js b/frontend/src/store/index.js
index 9aaef94971..1946f180c5 100644
--- a/frontend/src/store/index.js
+++ b/frontend/src/store/index.js
@@ -109,7 +109,9 @@ const data = {
// 仪表板视图明细
panelViewDetailsInfo: {},
// 当前tab页内组件
- curActiveTabInner: null
+ curActiveTabInner: null,
+ // static resource local path
+ staticResourcePath: '/static-resource/'
},
mutations: {
...animation.mutations,
diff --git a/frontend/src/views/background/index.vue b/frontend/src/views/background/index.vue
index 3a5ca9c74e..cdec3808a9 100644
--- a/frontend/src/views/background/index.vue
+++ b/frontend/src/views/background/index.vue
@@ -64,7 +64,6 @@
:on-remove="handleRemove"
:http-request="upload"
:file-list="fileList"
- :on-change="onChange"
>
@@ -108,9 +107,9 @@
import { queryBackground } from '@/api/background/background'
import BackgroundItem from '@/views/background/BackgroundItem'
import { mapState } from 'vuex'
-import eventBus from '@/components/canvas/utils/eventBus'
import { deepCopy } from '@/components/canvas/utils/utils'
import { COLOR_PANEL } from '@/views/chart/chart/chart'
+import { uploadFileResult } from '@/api/staticResource/staticResource'
export default {
name: 'Background',
@@ -179,7 +178,7 @@ export default {
},
handleRemove(file, fileList) {
this.uploadDisabled = false
- this.panel.imageUrl = null
+ this.curComponent.commonBackground.outerImage = null
this.fileList = []
this.commitStyle()
},
@@ -187,16 +186,11 @@ export default {
this.dialogImageUrl = file.url
this.dialogVisible = true
},
- onChange(file, fileList) {
- var _this = this
- _this.uploadDisabled = true
- const reader = new FileReader()
- reader.onload = function() {
- _this.curComponent.commonBackground.outerImage = reader.result
- }
- reader.readAsDataURL(file.raw)
- },
upload(file) {
+ const _this = this
+ uploadFileResult(file, (fileUrl) => {
+ _this.curComponent.commonBackground.outerImage = fileUrl
+ })
// console.log('this is upload')
}
diff --git a/frontend/src/views/panel/SubjectSetting/PanelStyle/BackgroundSelector.vue b/frontend/src/views/panel/SubjectSetting/PanelStyle/BackgroundSelector.vue
index 85cbcd70b3..a1ad601846 100644
--- a/frontend/src/views/panel/SubjectSetting/PanelStyle/BackgroundSelector.vue
+++ b/frontend/src/views/panel/SubjectSetting/PanelStyle/BackgroundSelector.vue
@@ -25,12 +25,11 @@
accept=".jpeg,.jpg,.png,.gif"
class="avatar-uploader"
list-type="picture-card"
+ :http-request="upload"
:class="{disabled:uploadDisabled}"
:on-preview="handlePictureCardPreview"
:on-remove="handleRemove"
- :http-request="upload"
:file-list="fileList"
- :on-change="onChange"
>
@@ -51,6 +50,7 @@
import { mapState } from 'vuex'
import { deepCopy } from '@/components/canvas/utils/utils'
import { COLOR_PANEL } from '@/views/chart/chart/chart'
+import { uploadFileResult } from '@/api/staticResource/staticResource'
export default {
name: 'BackgroundSelector',
@@ -98,19 +98,13 @@ export default {
this.dialogImageUrl = file.url
this.dialogVisible = true
},
- onChange(file, fileList) {
- var _this = this
- _this.uploadDisabled = true
- const reader = new FileReader()
- reader.onload = function() {
- _this.panel.imageUrl = reader.result
- this.commitStyle()
- }
- this.$store.state.styleChangeTimes++
- reader.readAsDataURL(file.raw)
- },
upload(file) {
- // console.log('this is upload')
+ const _this = this
+ uploadFileResult(file, (fileUrl) => {
+ _this.$store.state.styleChangeTimes++
+ _this.panel.imageUrl = fileUrl
+ _this.commitStyle()
+ })
}
}
}
From f4130f61a28a519ff65be147ab928c6056bae443 Mon Sep 17 00:00:00 2001
From: fit2cloud-chenyw
Date: Mon, 25 Apr 2022 13:00:18 +0800
Subject: [PATCH 2/3] =?UTF-8?q?feat:=20dataease=E9=80=82=E9=85=8D=E7=AC=A6?=
=?UTF-8?q?=E5=8F=B7=E5=9C=B0=E5=9B=BE=E6=8F=92=E4=BB=B6?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../java/io/dataease/service/chart/ChartViewService.java | 3 +++
.../main/java/io/dataease/service/sys/PluginService.java | 6 ++++--
.../src/components/canvas/custom-component/UserView.vue | 7 +++++++
.../components/canvas/custom-component/UserViewDialog.vue | 1 +
.../canvas/custom-component/UserViewMobileDialog.vue | 1 +
frontend/src/views/chart/view/ChartEdit.vue | 3 +++
frontend/src/views/system/plugin/PluginCom.vue | 3 +++
7 files changed, 22 insertions(+), 2 deletions(-)
diff --git a/backend/src/main/java/io/dataease/service/chart/ChartViewService.java b/backend/src/main/java/io/dataease/service/chart/ChartViewService.java
index f8dc176372..c3d1e31871 100644
--- a/backend/src/main/java/io/dataease/service/chart/ChartViewService.java
+++ b/backend/src/main/java/io/dataease/service/chart/ChartViewService.java
@@ -503,6 +503,9 @@ public class ChartViewService {
// 如果是插件视图 走插件内部的逻辑
if (ObjectUtils.isNotEmpty(view.getIsPlugin()) && view.getIsPlugin()) {
Map> fieldMap = new HashMap<>();
+ List xAxisExt = new Gson().fromJson(view.getXAxisExt(), new TypeToken>() {
+ }.getType());
+ fieldMap.put("xAxisExt",xAxisExt);
fieldMap.put("xAxis", xAxis);
fieldMap.put("yAxis", yAxis);
fieldMap.put("extStack", extStack);
diff --git a/backend/src/main/java/io/dataease/service/sys/PluginService.java b/backend/src/main/java/io/dataease/service/sys/PluginService.java
index 0627830715..db6882f081 100644
--- a/backend/src/main/java/io/dataease/service/sys/PluginService.java
+++ b/backend/src/main/java/io/dataease/service/sys/PluginService.java
@@ -1,6 +1,7 @@
package io.dataease.service.sys;
import cn.hutool.core.io.FileUtil;
+import cn.hutool.core.util.ZipUtil;
import com.google.gson.Gson;
import io.dataease.dto.MyPluginDTO;
import io.dataease.ext.ExtSysPluginMapper;
@@ -72,8 +73,9 @@ public class PluginService {
//2.解压目标文件dest 得到plugin.json和jar
String folder = pluginDir + "folder/";
try {
- ZipUtils.unzip(dest, folder);
- } catch (IOException e) {
+ ZipUtil.unzip(dest.getAbsolutePath(), folder);
+ // ZipUtils.unzip(dest, folder);
+ } catch (Exception e) {
DeFileUtils.deleteFile(pluginDir + "temp/");
DeFileUtils.deleteFile(folder);
// 需要删除文件
diff --git a/frontend/src/components/canvas/custom-component/UserView.vue b/frontend/src/components/canvas/custom-component/UserView.vue
index 0e8f35793e..3dfc26d96a 100644
--- a/frontend/src/components/canvas/custom-component/UserView.vue
+++ b/frontend/src/components/canvas/custom-component/UserView.vue
@@ -21,7 +21,14 @@
:ref="element.propValue.id"
:component-name="chart.type + '-view'"
:obj="{chart, trackMenu, searchCount, terminalType: scaleCoefficientType}"
+ :chart="chart"
+ :track-menu="trackMenu"
+ :search-count="searchCount"
+ :terminal-type="scaleCoefficientType"
+ :scale="scale"
class="chart-class"
+ @onChartClick="chartClick"
+ @onJumpClick="jumpClick"
/>
diff --git a/frontend/src/components/canvas/custom-component/UserViewMobileDialog.vue b/frontend/src/components/canvas/custom-component/UserViewMobileDialog.vue
index d57297fd04..6dd44ebe5e 100644
--- a/frontend/src/components/canvas/custom-component/UserViewMobileDialog.vue
+++ b/frontend/src/components/canvas/custom-component/UserViewMobileDialog.vue
@@ -5,6 +5,7 @@
v-if="chart.isPlugin"
:component-name="chart.type + '-view'"
:obj="{chart: mapChart || chart}"
+ :chart="mapChart || chart"
class="chart-class"
/>
diff --git a/frontend/src/views/chart/view/ChartEdit.vue b/frontend/src/views/chart/view/ChartEdit.vue
index 6ef0cf3eac..f4a1a28171 100644
--- a/frontend/src/views/chart/view/ChartEdit.vue
+++ b/frontend/src/views/chart/view/ChartEdit.vue
@@ -962,7 +962,10 @@
ref="dynamicChart"
:component-name="chart.type + '-view'"
:obj="{chart}"
+ :chart-id="chart.id"
+ :chart="chart"
class="chart-class"
+ @onChartClick="chartClick"
/>
Date: Mon, 25 Apr 2022 13:13:37 +0800
Subject: [PATCH 3/3] =?UTF-8?q?fix:=20=E6=96=B0=E5=A2=9Etab=E5=9B=BE?=
=?UTF-8?q?=E6=A0=87=E4=BC=98=E5=8C=96?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../src/components/canvas/components/Editor/SettingMenu.vue | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/frontend/src/components/canvas/components/Editor/SettingMenu.vue b/frontend/src/components/canvas/components/Editor/SettingMenu.vue
index 6c64133a79..c765fdcf1b 100644
--- a/frontend/src/components/canvas/components/Editor/SettingMenu.vue
+++ b/frontend/src/components/canvas/components/Editor/SettingMenu.vue
@@ -12,7 +12,7 @@
{{ $t('panel.upComponent') }}
{{ $t('panel.downComponent') }}
{{ $t('panel.linkage_setting') }}
- {{ $t('panel.add_tab') }}
+ {{ $t('panel.add_tab') }}
{{ $t('panel.setting_jump') }}
{{ $t('panel.component_style') }}