Merge pull request #5619 from dataease/dev

merge dev
This commit is contained in:
fit2cloudrd 2023-07-11 09:14:30 +08:00 committed by GitHub
commit e1fcc9e194
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 165 additions and 48 deletions

View File

@ -1,5 +1,7 @@
package io.dataease.commons.utils;
import io.dataease.commons.exception.DEException;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.multipart.MultipartFile;
import java.io.*;
@ -41,6 +43,17 @@ public class DeFileUtils {
if (dir.exists()) return ;
dir.mkdirs();
}
public static void validateFile(MultipartFile file) {
String name = getFileNameNoEx(file.getOriginalFilename());
if (StringUtils.contains(name, "./")) {
DEException.throwException("file path invalid");
}
String suffix = getExtensionName(file.getOriginalFilename());
if (!StringUtils.equalsIgnoreCase(suffix, "zip")) {
DEException.throwException("please upload valid zip file");
}
}
/**
* 将文件名解析成文件的上传路径
*/

View File

@ -3,10 +3,11 @@ package io.dataease.controller.sys;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import io.dataease.auth.annotation.SqlInjectValidator;
import io.dataease.plugins.common.base.domain.MyPlugin;
import io.dataease.commons.utils.DeFileUtils;
import io.dataease.commons.utils.PageUtils;
import io.dataease.commons.utils.Pager;
import io.dataease.controller.sys.base.BaseGridRequest;
import io.dataease.plugins.common.base.domain.MyPlugin;
import io.dataease.service.sys.PluginService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
@ -41,6 +42,7 @@ public class SysPluginController {
@PostMapping("upload")
@RequiresPermissions("plugin:upload")
public Map<String, Object> localUpload(@RequestParam("file") MultipartFile file) throws Exception {
DeFileUtils.validateFile(file);
return pluginService.localInstall(file);
}
@ -54,7 +56,8 @@ public class SysPluginController {
@ApiOperation("更新插件")
@PostMapping("/update/{pluginId}")
@RequiresPermissions("plugin:upload")
public Map<String, Object> update(@PathVariable("pluginId") Long pluginId, @RequestParam("file") MultipartFile file) throws Exception{
public Map<String, Object> update(@PathVariable("pluginId") Long pluginId, @RequestParam("file") MultipartFile file) throws Exception {
DeFileUtils.validateFile(file);
if (pluginService.uninstall(pluginId)) {
return pluginService.localInstall(file);
}

View File

@ -61,7 +61,7 @@
dataset_table_field.origin_name,
dataset_table_field.`name`,
dataset_table_field.de_type
from dataset_table_field where table_id = #{table_id}
from dataset_table_field where dataset_table_field.group_type = 'd' and table_id = #{table_id}
</select>
<select id="queryTableFieldWithViewId" resultMap="TableFieldMap">

View File

@ -1065,7 +1065,7 @@ public class MysqlQueryProvider extends QueryProvider {
if (field.getDeType() == 1) {
String format = transDateFormat(request.getDateStyle(), request.getDatePattern());
if (field.getDeExtractType() == 0 || field.getDeExtractType() == 5 || field.getDeExtractType() == 1) {
String date = String.format(MySQLConstants.STR_TO_DATE, originName, StringUtils.isNotEmpty(field.getDateFormat()) ? field.getDateFormat() : MysqlConstants.DEFAULT_DATE_FORMAT);
String date = String.format(MySQLConstants.DATE_FORMAT, originName, StringUtils.isNotEmpty(field.getDateFormat()) ? field.getDateFormat() : MysqlConstants.DEFAULT_DATE_FORMAT);
if(request.getOperator().equals("between")){
whereName = date;
}else {

View File

@ -33,6 +33,7 @@ import io.dataease.plugins.common.base.mapper.ChartViewMapper;
import io.dataease.plugins.common.base.mapper.DatasetTableFieldMapper;
import io.dataease.plugins.common.base.mapper.PanelViewMapper;
import io.dataease.plugins.common.constants.DatasetType;
import io.dataease.plugins.common.constants.DatasourceTypes;
import io.dataease.plugins.common.constants.datasource.SQLConstants;
import io.dataease.plugins.common.dto.chart.ChartCustomFilterItemDTO;
import io.dataease.plugins.common.dto.chart.ChartFieldCompareDTO;
@ -611,7 +612,7 @@ public class ChartViewService {
xAxis.addAll(xAxisExt);
}
List<ChartViewFieldDTO> yAxis = gson.fromJson(view.getYAxis(), tokenType);
if (StringUtils.equalsAnyIgnoreCase(view.getType(), "chart-mix","bidirectional-bar")) {
if (StringUtils.equalsAnyIgnoreCase(view.getType(), "chart-mix", "bidirectional-bar")) {
List<ChartViewFieldDTO> yAxisExt = gson.fromJson(view.getYAxisExt(), tokenType);
yAxis.addAll(yAxisExt);
}
@ -1126,7 +1127,7 @@ public class ChartViewService {
datasourceRequest.setTotalPageFlag(false);
data = datasourceProvider.getData(datasourceRequest);
if (CollectionUtils.isNotEmpty(assistFields)) {
datasourceAssistRequest.setQuery(assistSQL(datasourceRequest.getQuery(), assistFields));
datasourceAssistRequest.setQuery(assistSQL(datasourceRequest.getQuery(), assistFields, ds));
logger.info(datasourceAssistRequest.getQuery());
assistData = datasourceProvider.getData(datasourceAssistRequest);
}
@ -1158,7 +1159,7 @@ public class ChartViewService {
}
}
if (CollectionUtils.isNotEmpty(assistFields)) {
datasourceAssistRequest.setQuery(assistSQL(datasourceRequest.getQuery(), assistFields));
datasourceAssistRequest.setQuery(assistSQL(datasourceRequest.getQuery(), assistFields, ds));
logger.info(datasourceAssistRequest.getQuery());
assistData = datasourceProvider.getData(datasourceAssistRequest);
}
@ -1405,14 +1406,15 @@ public class ChartViewService {
return res;
}
public String assistSQL(String sql, List<ChartViewFieldDTO> assistFields) {
public String assistSQL(String sql, List<ChartViewFieldDTO> assistFields, Datasource ds) {
DatasourceTypes datasourceType = DatasourceTypes.valueOf(ds.getType());
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < assistFields.size(); i++) {
ChartViewFieldDTO dto = assistFields.get(i);
if (i == (assistFields.size() - 1)) {
stringBuilder.append(dto.getSummary() + "(" + dto.getOriginName() + ")");
stringBuilder.append(dto.getSummary() + "(" + datasourceType.getKeywordPrefix() + dto.getOriginName() + datasourceType.getKeywordSuffix() + ")");
} else {
stringBuilder.append(dto.getSummary() + "(" + dto.getOriginName() + "),");
stringBuilder.append(dto.getSummary() + "(" + datasourceType.getKeywordPrefix() + dto.getOriginName() + datasourceType.getKeywordSuffix() + "),");
}
}
return "SELECT " + stringBuilder + " FROM (" + sql + ") tmp";

View File

@ -47,13 +47,15 @@ export default {
// window.SyncComponentCache[this.url] = Axios.get(this.url)
res = await window.SyncComponentCache[this.url]
} else {
res = await window.SyncComponentCache[this.url]
this.mode = await window.SyncComponentCache[this.url]
return
}
if (res) {
const Fn = Function
const dynamicCode = res.data || res
const component = new Fn(`return ${dynamicCode}`)()
this.mode = component.default || component
window.SyncComponentCache[this.url] = this.mode
}
}
}
@ -61,6 +63,9 @@ export default {
created() {
this.refId = uuid.v1
},
beforeDestroy() {
this.mode = null
},
methods: {
/* chartResize() {
this.$refs[this.refId] && this.$refs[this.refId].chartResize && this.$refs[this.refId].chartResize()

View File

@ -151,13 +151,19 @@ export default {
data() {
return {
previewVisible: false,
chart: null,
seriesIdMap: {
id: ''
}
}
},
computed: {
chart() {
if (this.config.propValue?.viewId) {
const viewInfo = this.panelViewDetailsInfo[this.config.propValue.viewId];
return viewInfo?JSON.parse(viewInfo):null
}
return null
},
componentCanvasId() {
if (this.config.type === 'view') {
return 'user-view-' + this.config.propValue.viewId
@ -216,7 +222,8 @@ export default {
'mobileLayoutStatus',
'curComponent',
'previewCanvasScale',
'componentGap'
'componentGap',
'panelViewDetailsInfo'
])
},
mounted() {
@ -286,8 +293,7 @@ export default {
}
} else {
return {
...
getStyle(style, ['top', 'left', 'width', 'height', 'rotate']),
...getStyle(style, ['top', 'left', 'width', 'height', 'rotate']),
position: 'relative'
}
}
@ -300,6 +306,9 @@ export default {
this[event](events[event])
})
}
},
setChartData() {
},
elementMouseDown(e) {
// // private

View File

@ -294,7 +294,7 @@ export default {
return this.curComponent.type === 'view' && this.terminal === 'pc' && this.curComponent.propValue.innerType && this.curComponent.propValue.innerType !== 'richTextView'
},
exportExcelShow() {
return this.detailsShow && hasDataPermission('export', this.$store.state.panel.panelInfo.privileges)
return this.detailsShow && hasDataPermission('export', this.$store.state.panel.panelInfo.privileges) && this.chart
},
enlargeShow() {
return this.curComponent.type === 'view' && this.curComponent.propValue.innerType && this.curComponent.propValue.innerType !== 'richTextView' && !this.curComponent.propValue.innerType.includes('table')

View File

@ -171,23 +171,19 @@ export default {
return this.targetLinkageInfo[this.curLinkageView.propValue.viewId]
},
...mapState([
'menuTop',
'menuLeft',
'menuShow',
'curComponent',
'componentData',
'canvasStyleData',
'linkageSettingStatus',
'targetLinkageInfo',
'curLinkageView'
])
},
mounted() {
const _this = this
//
checkSameDataSet(this.curLinkageView.propValue.viewId, this.element.propValue.viewId).then(res => {
if (res.data === 'YES' && this.linkageInfo.linkageFields.length === 0) {
this.sourceLinkageInfo.targetViewFields.forEach(item => {
this.addLinkageField(item.id, item.id)
_this.$nextTick(() => {
this.addLinkageField(item.id, item.id)
})
})
}
})

View File

@ -238,6 +238,8 @@ export default {
return {
imageDownloading: false,
chartDetailsVisible: false,
canvasMain: null,
tempCanvas: null,
showChartInfo: {},
showChartTableInfo: {},
showChartInfoType: 'details',
@ -439,8 +441,14 @@ export default {
this.initPdfTemplate()
},
beforeDestroy() {
erd.uninstall(this.$refs[this.previewTempRefId])
erd.uninstall(this.$refs[this.previewRefId])
if (this.$refs[this.previewTempRefId]) {
erd.uninstall(this.$refs[this.previewTempRefId])
}
if (this.$refs[this.previewRefId]) {
erd.uninstall(this.$refs[this.previewRefId])
}
erd.uninstall(this.canvasMain)
erd.uninstall(this.tempCanvas)
clearInterval(this.timer)
this.canvasId === 'canvas-main' && bus.$off('pcChartDetailsDialog', this.openChartDetailsDialog)
bus.$off('trigger-search-button', this.triggerSearchButton)
@ -719,26 +727,27 @@ export default {
bus.$emit('onScroll')
},
initListen() {
const _this = this
const canvasMain = document.getElementById(this.previewDomId)
this.canvasMain = document.getElementById(this.previewDomId)
// div
if (canvasMain) {
erd.listenTo(canvasMain, element => {
_this.$nextTick(() => {
_this.restore()
if (this.canvasMain) {
erd.uninstall(this.canvasMain)
erd.listenTo(this.canvasMain, () => {
this.$nextTick(() => {
this.restore()
})
})
}
setTimeout(() => {
// div
const tempCanvas = document.getElementById(this.previewTempDomId)
if (tempCanvas) {
erd.listenTo(document.getElementById(this.previewTempDomId), element => {
_this.$nextTick(() => {
this.tempCanvas = document.getElementById(this.previewTempDomId)
if (this.tempCanvas) {
erd.uninstall(this.tempCanvas)
erd.listenTo(document.getElementById(this.previewTempDomId), () => {
this.$nextTick(() => {
// mainHeight px html2canvas
_this.mainHeight = tempCanvas.scrollHeight + 'px!important'
_this.mainHeightCount = tempCanvas.scrollHeight
this.$emit('mainHeightChange', _this.mainHeight)
this.mainHeight = this.tempCanvas.scrollHeight + 'px!important'
this.mainHeightCount = this.tempCanvas.scrollHeight
this.$emit('mainHeightChange', this.mainHeight)
})
})
}

View File

@ -560,6 +560,12 @@ export default {
},
beforeDestroy() {
for (const key in this.chart) {
this.$delete(this.chart, key)
}
for (const key in this.view) {
this.$delete(this.view, key)
}
this.innerRefreshTimer && clearInterval(this.innerRefreshTimer)
bus.$off('plugin-chart-click', this.pluginChartClick)
bus.$off('plugin-jump-click', this.pluginJumpClick)
@ -570,6 +576,7 @@ export default {
bus.$off('onThemeColorChange', this.optFromBatchThemeChange)
bus.$off('onThemeAttrChange', this.optFromBatchSingleProp)
bus.$off('clear_panel_linkage', this.clearPanelLinkage)
bus.$off('tab-canvas-change', this.tabSwitch)
},
created() {
this.refId = uuid.v1
@ -865,8 +872,8 @@ export default {
},
initCurFields(chartDetails) {
this.curFields = []
this.dataRowSelect = []
this.dataRowNameSelect = []
this.dataRowSelect = {}
this.dataRowNameSelect = {}
if (chartDetails.data && chartDetails.data.sourceFields) {
const checkAllAxisStr = chartDetails.xaxis + chartDetails.xaxisExt + chartDetails.yaxis + chartDetails.yaxisExt
chartDetails.data.sourceFields.forEach(field => {

View File

@ -429,6 +429,12 @@ export function getCacheTree(treeName) {
}
export function exportExcelDownload(chart, snapshot, width, height, loadingWrapper, callBack) {
if (chart.render === 'antv' && !chart.data?.data?.length) {
return
}
if (chart.type === 'echarts' && !(chart.data?.series?.length && chart.data?.series[0].data?.length)) {
return
}
const fields = JSON.parse(JSON.stringify(chart.data.fields))
const tableRow = JSON.parse(JSON.stringify(chart.data.tableRow))
const excelHeader = fields.map(item => item.name)

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1687676106978" filter="currentColor" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3283" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M854.6 288.6L639.4 73.4c-6-6-14.1-9.4-22.6-9.4H192c-17.7 0-32 14.3-32 32v832c0 17.7 14.3 32 32 32h640c17.7 0 32-14.3 32-32V311.3c0-8.5-3.4-16.7-9.4-22.7zM790.2 326H602V137.8L790.2 326z m1.8 562H232V136h302v216a42 42 0 0 0 42 42h216v494zM514.1 580.1l-61.8-102.4c-2.2-3.6-6.1-5.8-10.3-5.8h-38.4c-2.3 0-4.5 0.6-6.4 1.9-5.6 3.5-7.3 10.9-3.7 16.6l82.3 130.4-83.4 132.8a12.04 12.04 0 0 0 10.2 18.4h34.5c4.2 0 8-2.2 10.2-5.7L510 664.8l62.3 101.4c2.2 3.6 6.1 5.7 10.2 5.7H620c2.3 0 4.5-0.7 6.5-1.9 5.6-3.6 7.2-11 3.6-16.6l-84-130.4 85.3-132.5a12.04 12.04 0 0 0-10.1-18.5h-35.7c-4.2 0-8.1 2.2-10.3 5.8l-61.2 102.3z" p-id="3284"></path></svg>

After

Width:  |  Height:  |  Size: 988 B

View File

@ -935,6 +935,8 @@ export default {
password_input_error: 'Original password input error'
},
chart: {
empty_hide: 'hide empty',
hide: 'hide',
chart_refresh_tips: 'View refresh setting takes precedence over panel refresh setting',
'1-trend': 'trend',
'2-state': 'State',

View File

@ -934,6 +934,8 @@ export default {
password_input_error: '原始密碼輸入錯誤'
},
chart: {
empty_hide: '隱藏空值',
hide: '隱藏',
chart_refresh_tips: '視圖刷新設置優先於儀表板刷新設置',
'1-trend': '趨勢',
'2-state': '狀態',

View File

@ -933,6 +933,8 @@ export default {
password_input_error: '原始密码输入错误'
},
chart: {
empty_hide: '隐藏空值',
hide: '隐藏',
chart_refresh_tips: '视图刷新设置优先于仪表板刷新设置',
'1-trend': '趋势',
'2-state': '状态',

View File

@ -72,9 +72,13 @@ export function baseMapOption(chart_option, geoJson, chart, themeStyle, curAreaC
const reg = new RegExp('\n', 'g')
const text = tooltip.formatter.replace(reg, '<br/>')
tooltip.formatter = params => {
const val = params.value
if (tooltip.emptyHide && (val === null || typeof val === 'undefined' || isNaN(val))) {
return ''
}
const a = params.seriesName
const b = params.name
const c = params.value ?? ''
const c = (val === null || typeof val === 'undefined' || isNaN(val)) ? '' : val
return text.replace(new RegExp('{a}', 'g'), a).replace(new RegExp('{b}', 'g'), b).replace(new RegExp('{c}', 'g'), c)
}
chart_option.tooltip = tooltip

View File

@ -3323,6 +3323,7 @@ export const TYPE_CONFIGS = [
],
'tooltip-selector': [
'show',
'emptyHide',
'textStyle',
'formatter'
],

View File

@ -61,7 +61,7 @@ import ChartTitleUpdate from './ChartTitleUpdate.vue'
import { equalsAny } from '@/utils/StringUtils'
import { mapState } from 'vuex'
import { baseFlowMapOption } from '@/views/chart/chart/map/map_antv'
import { clear } from 'size-sensor'
export default {
name: 'ChartComponentG2',
components: { TitleRemark, ViewTrackBar, ChartTitleUpdate },
@ -166,7 +166,28 @@ export default {
}
},
beforeDestroy() {
this.myChart.destroy()
if (this.myChart.container) {
if (typeof this.myChart.container.getAttribute === 'function') {
clear(this.myChart.container)
}
}
this.myChart?.clear?.()
this.myChart?.unbindSizeSensor?.()
this.myChart?.unbind?.()
this.myChart?.destroy?.()
if (this.myChart) {
for (const key in this.myChart.chart) {
this.myChart.chart[key] = null
this.$delete(this.myChart.chart, key)
}
for (const key in this.myChart) {
this.myChart[key] = null
this.$delete(this.myChart, key)
}
}
for (const key in this.pointParam) {
this.$delete(this.pointParam, key)
}
window.removeEventListener('resize', this.calcHeightDelay)
this.myChart = null
},
@ -222,7 +243,7 @@ export default {
window.addEventListener('resize', this.calcHeightDelay)
},
drawView() {
const chart = this.chart
const chart = JSON.parse(JSON.stringify(this.chart))
// type
// if (chart.data) {
this.antVRenderStatus = true

View File

@ -117,6 +117,13 @@ export default {
value: 'ge',
label: this.$t('chart.filter_ge')
}]
},
{
label: '',
options: [{
value: 'not_null',
label: this.$t('chart.filter_not_null')
}]
}],
logic: ''
}

View File

@ -194,6 +194,13 @@ export default {
value: 'ge',
label: this.$t('chart.filter_ge')
}]
},
{
label: '',
options: [{
value: 'not_null',
label: this.$t('chart.filter_not_null')
}]
}
],
valueOptions: [
@ -226,6 +233,13 @@ export default {
value: 'ge',
label: this.$t('chart.filter_ge')
}]
},
{
label: '',
options: [{
value: 'not_null',
label: this.$t('chart.filter_not_null')
}]
}
],
options: [],

View File

@ -18,6 +18,16 @@
>{{ $t('chart.show') }}</el-checkbox>
</el-form-item>
<div v-show="tooltipForm.show">
<el-form-item
v-show="showProperty('emptyHide')"
:label="$t('chart.empty_hide')"
class="form-item"
>
<el-checkbox
v-model="tooltipForm.emptyHide"
@change="changeTooltipAttr('emptyHide')"
>{{ $t('chart.hide') }}</el-checkbox>
</el-form-item>
<el-form-item
v-show="showProperty('trigger')"
:label="$t('chart.trigger_position')"

View File

@ -81,7 +81,7 @@ export default {
props: {},
data() {
return {
maxHeight: 2000,
maxHeight: 10000,
maxTop: 20000
}
},

View File

@ -670,7 +670,10 @@ export default {
if (this.editPanel.optType === 'toDefaultPanel') {
this.defaultTree(false)
}
updateCacheTree(this.editPanel.optType, 'panel-main-tree', panelInfo, this.tData)
updateCacheTree(this.editPanel.optType,
panelInfo.panelType === 'system' ? 'panel-default-tree' : 'panel-main-tree', panelInfo,
panelInfo.panelType === 'system' ? this.defaultData : this.tData)
if (this.editPanel.optType === 'rename' && panelInfo.id === this.$store.state.panel.panelInfo.id) {
this.$store.state.panel.panelInfo.name = panelInfo.name
}
@ -850,7 +853,7 @@ export default {
delete(data) {
const params = {
title: data.nodeType === 'folder'?'commons.delete_this_folder':'commons.delete_this_dashboard',
title: data.nodeType === 'folder' ? 'commons.delete_this_folder' : 'commons.delete_this_dashboard',
type: 'danger',
cb: () => {
delGroup(data.id).then((response) => {