Merge branch 'dev' into pr@dev@dataset

This commit is contained in:
taojinlong 2022-11-24 19:07:14 +08:00
commit 07ed991283
57 changed files with 835 additions and 284 deletions

View File

@ -5,7 +5,7 @@
<a href="https://app.codacy.com/gh/dataease/dataease?utm_source=github.com&utm_medium=referral&utm_content=dataease/dataease&utm_campaign=Badge_Grade_Dashboard"><img src="https://app.codacy.com/project/badge/Grade/da67574fd82b473992781d1386b937ef" alt="Codacy"></a>
<a href="https://github.com/dataease/dataease/releases/latest"><img src="https://img.shields.io/github/v/release/dataease/dataease" alt="Latest release"></a>
<a href="https://github.com/dataease/dataease"><img src="https://img.shields.io/github/stars/dataease/dataease?color=%231890FF&style=flat-square" alt="Stars"></a>
<a href="https://github.com/dataease/dataease/releases/latest"><img src="https://img.shields.io/github/downloads/dataease/dataease/total" alt="Downloads"></a>
</p>
<hr/>

View File

@ -13,6 +13,7 @@ import io.dataease.commons.exception.DEException;
import io.dataease.controller.request.dataset.DataSetTableRequest;
import io.dataease.controller.request.dataset.MultFieldValuesRequest;
import io.dataease.controller.response.DatasetTableField4Type;
import io.dataease.dto.dataset.DatasetTableFieldDTO;
import io.dataease.i18n.Translator;
import io.dataease.plugins.common.base.domain.DatasetTable;
import io.dataease.plugins.common.base.domain.DatasetTableField;
@ -107,9 +108,33 @@ public class DataSetTableFieldController {
DatasetTableField datasetTableField = DatasetTableField.builder().build();
datasetTableField.setTableId(tableId);
datasetTableField.setGroupType("d");
List<DatasetTableField> dimensionList = dataSetTableFieldsService.list(datasetTableField);
List<DatasetTableFieldDTO> dimensionList = new ArrayList<>();
dataSetTableFieldsService.list(datasetTableField).forEach(o -> {
DatasetTableFieldDTO datasetTableFieldDTO = new DatasetTableFieldDTO();
BeanUtils.copyProperties(o, datasetTableFieldDTO);
List<Object> deTypeCascader = new ArrayList<>();
deTypeCascader.add(datasetTableFieldDTO.getDeType());
if (datasetTableFieldDTO.getDeExtractType() == 0 && datasetTableFieldDTO.getDeType() == 1) {
deTypeCascader.add(datasetTableFieldDTO.getDateFormatType());
}
datasetTableFieldDTO.setDeTypeCascader(deTypeCascader);
dimensionList.add(datasetTableFieldDTO);
});
datasetTableField.setGroupType("q");
List<DatasetTableField> quotaList = dataSetTableFieldsService.list(datasetTableField);
List<DatasetTableFieldDTO> quotaList = new ArrayList<>();
dataSetTableFieldsService.list(datasetTableField).forEach(o -> {
DatasetTableFieldDTO datasetTableFieldDTO = new DatasetTableFieldDTO();
BeanUtils.copyProperties(o, datasetTableFieldDTO);
List<Object> deTypeCascader = new ArrayList<>();
deTypeCascader.add(datasetTableFieldDTO.getDeType());
if (datasetTableFieldDTO.getDeExtractType() == 0 && datasetTableFieldDTO.getDeType() == 1) {
deTypeCascader.add(datasetTableFieldDTO.getDateFormatType());
}
datasetTableFieldDTO.setDeTypeCascader(deTypeCascader);
quotaList.add(datasetTableFieldDTO);
});
DatasetTableField4Type datasetTableField4Type = new DatasetTableField4Type();
datasetTableField4Type.setDimensionList(dimensionList);

View File

@ -1,6 +1,6 @@
package io.dataease.controller.response;
import io.dataease.plugins.common.base.domain.DatasetTableField;
import io.dataease.dto.dataset.DatasetTableFieldDTO;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@ -9,7 +9,7 @@ import java.util.List;
@Data
public class DatasetTableField4Type {
@ApiModelProperty("维度")
List<DatasetTableField> dimensionList;
List<DatasetTableFieldDTO> dimensionList;
@ApiModelProperty("指标")
List<DatasetTableField> quotaList;
List<DatasetTableFieldDTO> quotaList;
}

View File

@ -3,7 +3,10 @@ package io.dataease.dto.dataset;
import io.dataease.plugins.common.base.domain.DatasetTableField;
import lombok.Data;
import java.util.List;
@Data
public class DatasetTableFieldDTO extends DatasetTableField {
private String jsonPath;
private List<Object> deTypeCascader;
}

View File

@ -41,6 +41,7 @@ import org.apache.commons.lang3.StringUtils;
import org.quartz.*;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.web.util.HtmlUtils;
import javax.annotation.Resource;
import java.io.File;
@ -67,9 +68,7 @@ public class EmailTaskHandler extends TaskHandler implements Job {
protected JobDataMap jobDataMap(GlobalTaskEntity taskEntity) {
JobDataMap jobDataMap = new JobDataMap();
jobDataMap.put("taskEntity", taskEntity);
EmailXpackService emailXpackService = SpringContextUtil.getBean(EmailXpackService.class);
XpackEmailTemplateDTO emailTemplateDTO = emailXpackService.emailTemplate(taskEntity.getTaskId());
jobDataMap.put("emailTemplate", emailTemplateDTO);
SysUserEntity creator = authUserServiceImpl.getUserByIdNoCache(taskEntity.getCreator());
jobDataMap.put("creator", creator);
return jobDataMap;
@ -109,10 +108,9 @@ public class EmailTaskHandler extends TaskHandler implements Job {
Long instanceId = saveInstance(taskInstance);
taskInstance.setInstanceId(instanceId);
XpackEmailTemplateDTO emailTemplate = (XpackEmailTemplateDTO) jobDataMap.get("emailTemplate");
SysUserEntity creator = (SysUserEntity) jobDataMap.get("creator");
LogUtil.info("start execute send panel report task...");
proxy(taskEntity.getTaskType()).sendReport(taskInstance, emailTemplate, creator, isTempTask);
proxy(taskEntity.getTaskType()).sendReport(taskInstance, creator, isTempTask);
if (isTempTask) {
removeTask(scheduleManager, taskEntity);
}
@ -160,13 +158,14 @@ public class EmailTaskHandler extends TaskHandler implements Job {
}
@Async("priorityExecutor")
public void sendReport(GlobalTaskInstance taskInstance, XpackEmailTemplateDTO emailTemplateDTO, SysUserEntity user, Boolean isTempTask) {
public void sendReport(GlobalTaskInstance taskInstance, SysUserEntity user, Boolean isTempTask) {
EmailXpackService emailXpackService = SpringContextUtil.getBean(EmailXpackService.class);
AuthUserServiceImpl userService = SpringContextUtil.getBean(AuthUserServiceImpl.class);
SysUserService sysUserService = SpringContextUtil.getBean(SysUserService.class);
List<File> files = null;
try {
XpackEmailTemplateDTO emailTemplateDTO = emailXpackService.emailTemplate(taskInstance.getTaskId());
XpackEmailTaskRequest taskForm = emailXpackService.taskForm(taskInstance.getTaskId());
if (ObjectUtils.isEmpty(taskForm) || (!isTempTask && CronUtils.taskExpire(taskForm.getEndTime()))) {
removeInstance(taskInstance);
@ -202,7 +201,7 @@ public class EmailTaskHandler extends TaskHandler implements Job {
String contentStr = "";
if (ObjectUtils.isNotEmpty(content)) {
contentStr = new String(content, "UTF-8");
contentStr = HtmlUtils.htmlUnescape(new String(content, "UTF-8"));
}

View File

@ -4,20 +4,17 @@ import io.dataease.auth.entity.SysUserEntity;
import io.dataease.plugins.common.entity.GlobalTaskInstance;
import io.dataease.plugins.xpack.email.dto.response.XpackEmailTemplateDTO;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
@Service("emailTaskViewHandler")
public class EmailTaskViewHandler extends EmailTaskHandler {
@Async("priorityExecutor")
public void sendReport(GlobalTaskInstance taskInstance, XpackEmailTemplateDTO emailTemplateDTO, SysUserEntity user, Boolean isTempTask) {
super.sendReport(taskInstance, emailTemplateDTO, user, isTempTask);
public void sendReport(GlobalTaskInstance taskInstance, SysUserEntity user, Boolean isTempTask) {
super.sendReport(taskInstance, user, isTempTask);
}
}

View File

@ -28,6 +28,7 @@ import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.util.HtmlUtils;
import springfox.documentation.annotations.ApiIgnore;
import java.io.*;
@ -136,6 +137,9 @@ public class XEmailTaskServer {
String emailContent;
try {
emailContent = new String(bytes, "UTF-8");
if (StringUtils.isNotBlank(emailContent)) {
emailContent = HtmlUtils.htmlUnescape(emailContent);
}
} catch (Exception e) {
throw new RuntimeException(e);
}
@ -176,7 +180,7 @@ public class XEmailTaskServer {
}
String imageUrl = "/system/ui/image/" + fileId;
String html = "<div>" +
"<h2>" + content + "</h2>" +
content +
"<img style='width: 100%;' id='" + panelId + "' src='" + imageUrl + "' />" +
"</div>";

View File

@ -1695,15 +1695,34 @@ public class ChartViewService {
continue;
}
Boolean isEndParam = false;
for (String parameter : chartExtFilterRequest.getParameters()) {
if (parameter.contains("|DE|")) {
if (!parameter.split("\\|DE\\|")[0].equals(table.getId())) {
String[] parameterArray = parameter.split("\\|DE\\|");
if (!parameterArray[0].equals(table.getId())) {
continue;
}
List<SqlVariableDetails> parameters = sqlVariables.stream().filter(item -> item.getVariableName().equalsIgnoreCase(parameter.split("\\|DE\\|")[1])).collect(Collectors.toList());
String paramName = null;
if (parameterArray.length > 1) {
paramName = parameterArray[1];
if (paramName.contains("_START_END_SPLIT")) {
String[] paramNameArray = paramName.split("_START_END_SPLIT");
paramName = paramNameArray[0];
isEndParam = true;
}
} else {
continue;
}
final String finalParamName = paramName;
List<SqlVariableDetails> parameters = sqlVariables.stream().filter(item -> item.getVariableName().equalsIgnoreCase(finalParamName)).collect(Collectors.toList());
if (CollectionUtils.isNotEmpty(parameters)) {
String filter = qp.transFilter(chartExtFilterRequest, parameters.get(0));
sql = sql.replace("${" + parameter.split("\\|DE\\|")[1] + "}", filter);
String filter = null;
if (isEndParam) {
filter = transEndParamSql(chartExtFilterRequest, parameters.get(0));
} else {
filter = qp.transFilter(chartExtFilterRequest, parameters.get(0));
}
sql = sql.replace("${" + finalParamName + "}", filter);
}
} else {
List<SqlVariableDetails> parameters = sqlVariables.stream().filter(item -> item.getVariableName().equalsIgnoreCase(parameter)).collect(Collectors.toList());
@ -1719,6 +1738,11 @@ public class ChartViewService {
return sql;
}
public String transEndParamSql(ChartExtFilterRequest chartExtFilterRequest, SqlVariableDetails sqlVariableDetails) {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(sqlVariableDetails.getType().size() > 1 ? sqlVariableDetails.getType().get(1) : "YYYY");
return simpleDateFormat.format(new Date(Long.parseLong(chartExtFilterRequest.getValue().get(1))));
}
private String getDrillSort(List<ChartViewFieldDTO> xAxis, ChartViewFieldDTO field) {
String res = "";
for (ChartViewFieldDTO f : xAxis) {

View File

@ -65,49 +65,49 @@ management.health.redis.enabled=false
#management.server.port=8083
#management.endpoints.web.exposure.include=*
#spring.freemarker.checkTemplateLocation=false
#RSA非对称加密参数:私钥
#RSA\u975E\u5BF9\u79F0\u52A0\u5BC6\u53C2\u6570\uFF1A\u79C1\u94A5
rsa.private_key=MIIBUwIBADANBgkqhkiG9w0BAQEFAASCAT0wggE5AgEAAkEA0vfvyTdGJkdbHkB8mp0f3FE0GYP3AYPaJF7jUd1M0XxFSE2ceK3k2kw20YvQ09NJKk+OMjWQl9WitG9pB6tSCQIDAQABAkA2SimBrWC2/wvauBuYqjCFwLvYiRYqZKThUS3MZlebXJiLB+Ue/gUifAAKIg1avttUZsHBHrop4qfJCwAI0+YRAiEA+W3NK/RaXtnRqmoUUkb59zsZUBLpvZgQPfj1MhyHDz0CIQDYhsAhPJ3mgS64NbUZmGWuuNKp5coY2GIj/zYDMJp6vQIgUueLFXv/eZ1ekgz2Oi67MNCk5jeTF2BurZqNLR3MSmUCIFT3Q6uHMtsB9Eha4u7hS31tj1UWE+D+ADzp59MGnoftAiBeHT7gDMuqeJHPL4b+kC+gzV4FGTfhR9q3tTbklZkD2A==
rsa.public_key=MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBANL378k3RiZHWx5AfJqdH9xRNBmD9wGD2iRe41HdTNF8RUhNnHit5NpMNtGL0NPTSSpPjjI1kJfVorRvaQerUgkCAwEAAQ==
#spring.cache.type=ehcache
spring.cache.ehcache.config=classpath:/ehcache/ehcache.xml
#打印URL路径
#\u6253\u5370URL\u8DEF\u5F84
#logging.level.org.springframework.web=trace
#logging.level.org.springframework.boot.web=trace
#spring.mvc.log-request-details=true
pagehelper.PageRowBounds=true
#excel等用户上传文件路径
#excel\u7B49\u7528\u6237\u4E0A\u4F20\u6587\u4EF6\u8DEF\u5F84
upload.file.path=/opt/dataease/data/kettle/
dataease.sqlinjection.whitelists=/dataset/table/sqlPreview,/dataset/table/update
dataease.sqlinjection.whitelists=/dataset/table/sqlPreview,/dataset/table/update,/dataset/field/multFieldValues,/dataset/field/linkMultFieldValues
#开启压缩 提高响应速度 减少带宽压力
#\u5F00\u542F\u538B\u7F29 \u63D0\u9AD8\u54CD\u5E94\u901F\u5EA6 \u51CF\u5C11\u5E26\u5BBD\u538B\u529B
server.compression.enabled=true
server.compression.mime-types=application/javascript,text/css,application/json,application/xml,text/html,text/xml,text/plain
server.compression.min-response-size=1024
#下面的配置新增到/opt/dataease/conf/dataease/properties
#缓存类型
#\u4E0B\u9762\u7684\u914D\u7F6E\u65B0\u589E\u5230/opt/dataease/conf/dataease/properties
#\u7F13\u5B58\u7C7B\u578B
##spring.cache.type=redis
#spring.cache.type=ehcache
#redis公共配置
#redis\u516C\u5171\u914D\u7F6E
#spring.redis.timeout=10000
#spring.redis.lettuce.pool.max-active=8
#spring.redis.lettuce.pool.max-wait=-1
#spring.redis.lettuce.pool.max-idle=8
#单机模式redis配置
#\u5355\u673A\u6A21\u5F0Fredis\u914D\u7F6E
#spring.redis.database=0
#spring.redis.host=192.168.0.110
#spring.redis.port=6379
#spring.redis.password=DataEase_ZNB@REDIS
#哨兵模式redis配置
#\u54E8\u5175\u6A21\u5F0Fredis\u914D\u7F6E
#spring.redis.sentinel.master=mymaster
#spring.redis.sentinel.nodes=192.168.0.110:26379,192.168.0.110:26380,192.168.0.110:26381
#spring.redis.sentinel.password=
#cluster模式redis配置
#cluster\u6A21\u5F0Fredis\u914D\u7F6E
#spring.redis.cluster.nodes=192.168.0.110:7001,192.168.0.110:7002,192.168.0.110:7003,192.168.0.110:7004,192.168.0.110:7005,192.168.0.110:7006
#spring.redis.cluster.max-redirects=3
#spring.redis.password=DataEase_ZNB@REDIS

View File

@ -39,3 +39,9 @@ WHERE (`component` = 'msg/setting');
ALTER TABLE `panel_group`
ADD COLUMN `panel_sort` bigint(13) NULL COMMENT '排序' AFTER `watermark_open`;
ALTER TABLE `sys_task_email`
CHANGE COLUMN `content` `content` MEDIUMBLOB NULL DEFAULT NULL COMMENT '内容' ;
ALTER TABLE `dataset_table_field`
ADD COLUMN `date_format_type` VARCHAR(255) NULL COMMENT '时间格式类型' AFTER `date_format`;

View File

@ -38,7 +38,7 @@ export function loadShares(data) {
return request({
url: '/api/share/queryWithResourceId',
method: 'post',
loading: true,
loading: false,
data
})
}

View File

@ -13,7 +13,7 @@ export function loadTable(data) {
url: 'api/dept/search',
method: 'post',
data,
loading: true
loading: false
})
}

View File

@ -199,14 +199,18 @@ export default {
return style
},
componentActiveFlag() {
return !this.mobileLayoutStatus && ((this.curComponent && this.config === this.curComponent && !this.previewVisible && !this.showPosition.includes('email-task')) || this.showPosition.includes('multiplexing'))
return !this.mobileLayoutStatus && ((this.curComponent && this.config.id === this.curComponent.id && !this.previewVisible && !this.showPosition.includes('email-task')) || this.showPosition.includes('multiplexing'))
},
scale() {
return Math.min(this.previewCanvasScale.scalePointWidth, this.previewCanvasScale.scalePointHeight)
},
curGap() {
return (this.canvasStyleData.panel.gap === 'yes' && this.config.auxiliaryMatrix) ? this.componentGap : 0
return ((this.canvasStyleData.panel.gap === 'yes' && this.config.auxiliaryMatrix) ? this.componentGap : 0) * this.scale
},
...mapState([
'mobileLayoutStatus',
'curComponent',
'previewCanvasScale',
'componentGap'
])
},

View File

@ -1,10 +1,6 @@
<template>
<div
:id="previewMainDomId"
v-loading="dataLoading"
:element-loading-text="$t('panel.data_loading')"
element-loading-spinner="el-icon-loading"
element-loading-background="rgba(220,220,220,1)"
class="bg"
:style="customStyle"
@scroll="canvasScroll"
@ -120,6 +116,7 @@ import { userLoginInfo } from '@/api/systemInfo/userLogin'
import html2canvas from 'html2canvasde'
import { queryAll } from '@/api/panel/pdfTemplate'
import PDFPreExport from '@/views/panel/export/PDFPreExport'
import { listenGlobalKeyDownPreview } from '@/components/canvas/utils/shortcutKey'
const erd = elementResizeDetectorMaker()
export default {
@ -351,6 +348,9 @@ export default {
}
},
created() {
if (this.canvasId === 'canvas-main') {
listenGlobalKeyDownPreview()
}
//
this.$cancelRequest('/chart/view/getData/**')
this.$cancelRequest('/api/link/viewDetail/**')
@ -552,7 +552,7 @@ export default {
component.style[key] = this.format(component.style[key], this.scaleHeight)
}
if (this.needToChangeWidth.includes(key)) {
if (key === 'fontSize' && this.terminal === 'mobile') {
if (key === 'fontSize' && (this.terminal === 'mobile' || component.type === 'custom')) {
// do nothing ( v-text )
} else {
component.style[key] = this.format(component.style[key], this.scaleWidth)
@ -614,7 +614,8 @@ export default {
},
downloadAsPDF() {
this.dataLoading = true
const domId = this.canvasInfoTemp
this.$emit('change-load-status', true)
const domId = this.previewMainDomId
setTimeout(() => {
this.exporting = true
this.backScreenShot = true
@ -625,6 +626,7 @@ export default {
html2canvas(document.getElementById(domId)).then(canvas => {
const snapshot = canvas.toDataURL('image/jpeg', 1) //
this.dataLoading = false
this.$emit('change-load-status', false)
this.exporting = false
this.backScreenShot = false
if (snapshot !== '') {
@ -632,7 +634,7 @@ export default {
this.pdfExportShow = true
}
})
}, 1500)
}, 2500)
}, 500)
},
closePreExport() {

View File

@ -12,8 +12,8 @@ export default {
copyData: null, // 复制粘贴剪切
isCut: false,
baseStyle: {
width: 300,
height: 200,
width: 533,
height: 300,
top: 0,
left: 0
},
@ -25,6 +25,24 @@ export default {
}
},
mutations: {
// 复制到粘贴板
copyToClipboard(state) {
if (state.curComponent) {
Vue.prototype.$copyText('datease-component-' + state.curComponent.id)
}
},
passFromClipboard(state, componentId) {
state.componentData.forEach(item => {
if (item.id === componentId) {
state.copyData = {
data: deepCopy(item),
index: state.componentData.length
}
}
})
state.isCut = false
this.commit('paste')
},
copyMultiplexingComponents(state) {
let pYMax = 0
const _this = this
@ -89,10 +107,8 @@ export default {
paste(state, needAdaptor) {
if (!state.copyData) {
toast('请选择组件')
return
}
const data = state.copyData.data
// 仪表板复制的组件默认不在移动端部署中mobileSelected = false
data.mobileSelected = false

View File

@ -56,7 +56,27 @@ export function listenGlobalKeyDown() {
if (keyCode === ctrlKey || keyCode === commandKey) {
isCtrlOrCommandDown = true
} else if (isCtrlOrCommandDown) {
if (keyCode === zKey || keyCode === yKey || keyCode === vKey || keyCode === cKey || keyCode === sKey || keyCode === enlargeKey) {
if (keyCode === zKey || keyCode === yKey || keyCode === cKey || keyCode === sKey || keyCode === enlargeKey) {
e.preventDefault()
unlockMap[keyCode]()
}
}
}
window.onkeyup = (e) => {
if (e.keyCode === ctrlKey || e.keyCode === commandKey) {
isCtrlOrCommandDown = false
}
}
}
export function listenGlobalKeyDownPreview() {
window.onkeydown = (e) => {
const { keyCode } = e
if (keyCode === ctrlKey || keyCode === commandKey) {
isCtrlOrCommandDown = true
} else if (isCtrlOrCommandDown) {
if (keyCode === enlargeKey) {
e.preventDefault()
unlockMap[keyCode]()
}
@ -71,12 +91,11 @@ export function listenGlobalKeyDown() {
}
function copy() {
store.commit('copy')
store.commit('copyToClipboard')
}
function paste() {
store.commit('paste')
store.commit('recordSnapshot')
}
function cut() {

View File

@ -2,6 +2,7 @@
<div
ref="myContainer"
class="my-container"
:style="autoStyle"
>
<div
ref="conditionMain"
@ -60,6 +61,8 @@
<script>
import inputStyleMixin from '@/components/widget/deWidget/inputStyleMixin'
import { mapState } from 'vuex'
export default {
name: 'DeOutWidget',
mixins: [inputStyleMixin],
@ -112,6 +115,18 @@ export default {
}
},
computed: {
scale() {
return this.previewCanvasScale.scalePointHeight
},
autoStyle() {
return {
height: (100 / this.scale) + '%!important',
width: (100 / this.scale) + '%!important',
left: 50 * (1 - 1 / this.scale) + '%', // 2
top: 50 * (1 - 1 / this.scale) + '%', // 2
transform: 'scale(' + this.scale + ')'
}
},
sizeInfo() {
let size
if (this.duHeight > this.inputLargeSize) {
@ -133,7 +148,10 @@ export default {
},
isFilterComponent() {
return ['de-select', 'de-select-grid', 'de-date', 'de-input-search', 'de-number-range', 'de-select-tree'].includes(this.element.component)
}
},
...mapState([
'previewCanvasScale'
])
},
watch: {
'element.style': {

View File

@ -71,7 +71,7 @@
import { linkMultFieldValues, multFieldValues } from '@/api/dataset/dataset'
import { getLinkToken, getToken } from '@/utils/auth'
import bus from '@/utils/bus'
import { isSameVueObj } from '@/utils'
import { isSameVueObj, mergeCustomSortOption } from '@/utils'
import { attrsMap, styleAttrs, textSelectGridWidget } from '@/components/widget/deWidget/serviceNameFn.js'
export default {
@ -142,6 +142,9 @@ export default {
cssArr() {
const { brColor, wordColor, innerBgColor } = this.element.style
return { brColor, wordColor, innerBgColor }
},
isCustomSortWidget() {
return this.element.serviceName === 'textSelectGridWidget'
}
},
watch: {
@ -354,7 +357,11 @@ export default {
},
optionData(data) {
if (!data) return null
return data.filter(item => !!item).map(item => {
let tempData = data.filter(item => !!item)
if (this.isCustomSortWidget && this.element.options.attrs?.sort?.sort === 'custom') {
tempData = mergeCustomSortOption(this.element.options.attrs.sort.list, tempData)
}
return tempData.map(item => {
return {
id: item,
text: item

View File

@ -470,8 +470,8 @@ export default {
let switchCount = 1
//
this.timer = setInterval(() => {
switchCount++
const nowIndex = switchCount % this.element.options.tabList.length
switchCount++
this.activeTabName = this.element.options.tabList[nowIndex].name
}, switchTime)
}

View File

@ -135,8 +135,9 @@
type="number"
size="mini"
:min="2"
:max="3600"
class="hide-icon-number"
@change="styleChange"
@change="switchTimeChange"
>
<template slot="append">S</template>
</el-input>
@ -180,6 +181,14 @@ export default {
const current = this.$refs[pickKey]
current && (current.showPicker = true)
},
switchTimeChange() {
if (!this.styleInfo.switchTime || this.styleInfo.switchTime < 2) {
this.styleInfo.switchTime = 2
} else if (this.styleInfo.switchTime && this.styleInfo.switchTime > 3600) {
this.styleInfo.switchTime = 3600
}
this.styleChange()
},
styleChange() {
this.$store.commit('canvasChange')
}

View File

@ -107,6 +107,9 @@ class NumberSelectServiceImpl extends WidgetService {
return defaultV.split(',')[0]
}
}
isParamWidget() {
return true
}
}
const numberSelectServiceImpl = new NumberSelectServiceImpl()
export default numberSelectServiceImpl

View File

@ -96,6 +96,9 @@ class TextSelectGridServiceImpl extends WidgetService {
isSortWidget() {
return true
}
isCustomSortWidget() {
return true
}
fillValueDerfault(element) {
const defaultV = element.options.value === null ? '' : element.options.value.toString()
if (element.options.attrs.multiple) {

View File

@ -102,6 +102,9 @@ class TextSelectServiceImpl extends WidgetService {
isCustomSortWidget() {
return true
}
isParamWidget() {
return true
}
fillValueDerfault(element) {
const defaultV = element.options.value === null ? '' : element.options.value.toString()

View File

@ -31,7 +31,10 @@ const dialogPanel = {
eDynamicSuffix: 'after'
},
showTime: false,
accuracy: 'HH:mm'
accuracy: 'HH:mm',
parameters: [],
startParameters: [],
endParameters: []
},
value: '',
manualModify: false
@ -329,13 +332,13 @@ class TimeDateRangeServiceImpl extends WidgetService {
const defaultV = element.options.value === null ? '' : element.options.value.toString()
if (element.options.attrs.type === 'daterange') {
if (defaultV === null || typeof defaultV === 'undefined' || defaultV === '' || defaultV ===
'[object Object]') {
'[object Object]') {
return []
}
return defaultV.split(',').map(item => parseFloat(item))
} else {
if (defaultV === null || typeof defaultV === 'undefined' || defaultV === '' || defaultV ===
'[object Object]') {
'[object Object]') {
return null
}
return parseFloat(defaultV.split(',')[0])
@ -400,6 +403,12 @@ class TimeDateRangeServiceImpl extends WidgetService {
{ 'text': 'dynamic_year.last', 'callBack': () => this.formatShortValues([this.getStartYear(-1).getTime(), this.getEndYear(-1).getTime()]) }
]
}
isParamWidget() {
return true
}
isRangeParamWidget() {
return true
}
}
const timeDateRangeServiceImpl = new TimeDateRangeServiceImpl()
export default timeDateRangeServiceImpl

View File

@ -189,13 +189,13 @@ class TimeDateServiceImpl extends WidgetService {
const defaultV = element.options.value === null ? '' : element.options.value.toString()
if (element.options.attrs.type === 'daterange') {
if (defaultV === null || typeof defaultV === 'undefined' || defaultV === '' || defaultV ===
'[object Object]') {
'[object Object]') {
return []
}
return defaultV.split(',').map(item => parseFloat(item))
} else {
if (defaultV === null || typeof defaultV === 'undefined' || defaultV === '' || defaultV ===
'[object Object]') {
'[object Object]') {
return null
}
return parseFloat(defaultV.split(',')[0])
@ -234,6 +234,9 @@ class TimeDateServiceImpl extends WidgetService {
isTimeWidget() {
return true
}
isParamWidget() {
return true
}
}
const timeDateServiceImpl = new TimeDateServiceImpl({
name: 'timeDateWidget'

View File

@ -150,13 +150,13 @@ class TimeMonthServiceImpl extends WidgetService {
const defaultV = element.options.value === null ? '' : element.options.value.toString()
if (element.options.attrs.type === 'daterange') {
if (defaultV === null || typeof defaultV === 'undefined' || defaultV === '' || defaultV ===
'[object Object]') {
'[object Object]') {
return []
}
return defaultV.split(',').map(item => parseFloat(item))
} else {
if (defaultV === null || typeof defaultV === 'undefined' || defaultV === '' || defaultV ===
'[object Object]') {
'[object Object]') {
return null
}
return parseFloat(defaultV.split(',')[0])
@ -186,6 +186,9 @@ class TimeMonthServiceImpl extends WidgetService {
return timeSection(parseFloat(value), element.options.attrs.type)
}
}
isParamWidget() {
return true
}
}
const timeMonthServiceImpl = new TimeMonthServiceImpl()
export default timeMonthServiceImpl

View File

@ -137,13 +137,13 @@ class TimeYearServiceImpl extends WidgetService {
const defaultV = element.options.value === null ? '' : element.options.value.toString()
if (element.options.attrs.type === 'daterange') {
if (defaultV === null || typeof defaultV === 'undefined' || defaultV === '' || defaultV ===
'[object Object]') {
'[object Object]') {
return []
}
return defaultV.split(',').map(item => parseFloat(item))
} else {
if (defaultV === null || typeof defaultV === 'undefined' || defaultV === '' || defaultV ===
'[object Object]') {
'[object Object]') {
return null
}
return parseFloat(defaultV.split(',')[0])
@ -173,6 +173,9 @@ class TimeYearServiceImpl extends WidgetService {
return timeSection(parseFloat(value), element.options.attrs.type)
}
}
isParamWidget() {
return true
}
}
const timeYearServiceImpl = new TimeYearServiceImpl()
export default timeYearServiceImpl

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="1663834987781" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1963" width="200" height="200"><path transform="rotate(90 319.99999999999994,513.6666870117189) " id="svg_1" d="m-64,641.66667l768,0l0,85.33333l-768,0l0,-85.33333zm21.33333,-341.33334l85.33334,0l0,298.66667l-85.33334,0l0,-298.66667zm640,256l85.33334,0l0,42.66667l-85.33334,0l0,-42.66667zm-533.33333,-213.33333l85.33333,0l0,256l-85.33333,0l0,-256zm106.66667,42.66667l85.33333,0l0,213.33333l-85.33333,0l0,-213.33333zm106.66666,42.66666l85.33334,0l0,170.66667l-85.33334,0l0,-170.66667zm106.66667,42.66667l85.33333,0l0,128l-85.33333,0l0,-128zm106.66667,42.66667l85.33333,0l0,85.33333l-85.33333,0l0,-85.33333z"/><path transform="rotate(90 551,513.3333129882814) " id="svg_2" opacity="0.6" d="m188.33333,278.66667l85.33334,0l0,213.33333l-85.33334,0l0,-213.33333zm640,256l85.33334,0l0,213.33333l-85.33334,0l0,-213.33333zm-533.33333,-213.33334l85.33333,0l0,213.33334l-85.33333,0l0,-213.33334zm106.66667,42.66667l85.33333,0l0,213.33333l-85.33333,0l0,-213.33333zm106.66666,42.66667l85.33334,0l0,213.33333l-85.33334,0l0,-213.33333zm106.66667,42.66666l85.33333,0l0,213.33334l-85.33333,0l0,-213.33334zm106.66667,42.66667l85.33333,0l0,213.33333l-85.33333,0l0,-213.33333z"/><path transform="rotate(90 739,513.6666870117189) " stroke="null" id="svg_3" d="m1016.33333,343l85.33334,0l0,341.33333l-85.33334,0l0,-341.33333zm-640,0l85.33334,0l0,85.33333l-85.33334,0l0,-85.33333zm533.33334,0l85.33333,0l0,298.66667l-85.33333,0l0,-298.66667zm-106.66667,0l85.33333,0l0,256l-85.33333,0l0,-256zm-106.66667,0l85.33334,0l0,213.33333l-85.33334,0l0,-213.33333zm-106.66666,0l85.33333,0l0,170.66667l-85.33333,0l0,-170.66667zm-106.66667,0l85.33333,0l0,128l-85.33333,0l0,-128z"/></svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@ -1135,6 +1135,7 @@ export default {
chart_percentage_bar_stack: 'Percentage Stack Bar',
chart_bar_horizontal: 'Horizontal Bar',
chart_bar_stack_horizontal: 'Stack Horizontal Bar',
chart_percentage_bar_stack_horizontal: 'Horizontal Percentage Stack Bar',
chart_line: 'Base Line',
chart_line_stack: 'Stack Line',
chart_pie: 'Pie',
@ -1338,6 +1339,7 @@ export default {
table_align_left: 'Left',
table_align_center: 'Center',
table_align_right: 'Right',
table_scroll_bar_color: 'Scroll Bar Color',
draw_back: 'Draw Back',
senior: 'Senior',
senior_cfg: 'Senior Config',
@ -2551,9 +2553,9 @@ export default {
start_time: 'Start time',
end_time: 'End time',
chart_data: 'View data',
panel_preview: 'Preview panel',
panel_preview: 'Preview report',
preview: 'Preview',
emial_preview: 'Emial preview',
emial_preview: 'Report preview',
chart_data_range: 'View data range',
simple_repeat: 'Simple repeat',
once_a_day: 'Once a day',
@ -2683,6 +2685,7 @@ export default {
'I18N_USER_TEMPLATE_ERROR': 'Template file error',
'i18n_max_user_import_size': 'File size exceeds 10M',
app_template: {
apply_template: 'Apply template',
execution_time: 'Execution time',
app_manager: 'Application management',
app_upload: 'Upload app',

View File

@ -1135,6 +1135,7 @@ export default {
chart_percentage_bar_stack: '百分比柱狀圖',
chart_bar_horizontal: '橫嚮柱狀圖',
chart_bar_stack_horizontal: '橫嚮堆疊柱狀圖',
chart_percentage_bar_stack_horizontal: '橫嚮百分比柱狀圖',
chart_line: '基礎摺線圖',
chart_line_stack: '堆疊摺線圖',
chart_pie: '餅圖',
@ -1338,6 +1339,7 @@ export default {
table_align_left: '左對齊',
table_align_center: '居中',
table_align_right: '右對齊',
table_scroll_bar_color: '滾動條顏色',
draw_back: '收回',
senior: '高級',
senior_cfg: '高級設置',
@ -2552,9 +2554,9 @@ export default {
start_time: '開始時間',
end_time: '結束時間',
chart_data: '視圖數據',
panel_preview: '預覽儀表板',
panel_preview: '預覽報告',
preview: '預覽',
emial_preview: '郵件預覽',
emial_preview: '報告預覽',
chart_data_range: '視圖數據範圍',
simple_repeat: '簡單重複',
once_a_day: '每天一次',
@ -2684,6 +2686,7 @@ export default {
'I18N_USER_TEMPLATE_ERROR': '模版錯誤',
'i18n_max_user_import_size': '文件最大不能超過10M',
app_template: {
apply_template: '應用模版',
execution_time: '执行时间',
app_manager: '應用管理',
app_upload: '上傳應用',

View File

@ -1134,6 +1134,7 @@ export default {
chart_percentage_bar_stack: '百分比柱状图',
chart_bar_horizontal: '横向柱状图',
chart_bar_stack_horizontal: '横向堆叠柱状图',
chart_percentage_bar_stack_horizontal: '横向百分比柱状图',
chart_line: '基础折线图',
chart_line_stack: '堆叠折线图',
chart_pie: '饼图',
@ -1337,6 +1338,7 @@ export default {
table_align_left: '左对齐',
table_align_center: '居中',
table_align_right: '右对齐',
table_scroll_bar_color: '滚动条颜色',
draw_back: '收回',
senior: '高级',
senior_cfg: '高级设置',
@ -2552,9 +2554,9 @@ export default {
start_time: '开始时间',
end_time: '结束时间',
chart_data: '视图数据',
panel_preview: '预览仪表板',
panel_preview: '预览报告',
preview: '预览',
emial_preview: '邮件预览',
emial_preview: '报告预览',
chart_data_range: '视图数据范围',
simple_repeat: '简单重复',
once_a_day: '每天一次',
@ -2684,6 +2686,7 @@ export default {
'I18N_USER_TEMPLATE_ERROR': '模版错误',
'i18n_max_user_import_size': '文件最大不能超过10M',
app_template: {
apply_template: '应用模板',
execution_time: '执行时间',
app_manager: '应用管理',
app_upload: '上传应用',

View File

@ -93,7 +93,7 @@ div:focus {
}
.de-filter-dialog {
min-width: 500px !important;
min-width: 785px !important;
width: 55% !important;
.el-dialog__header {
@ -322,12 +322,12 @@ div:focus {
margin: 0 2px 1px 0;
}
.field-icon-dimension{
color: #3370FF!important;
.field-icon-dimension {
color: #3370FF !important;
}
.field-icon-quota{
color: #04B49C!important;
.field-icon-quota {
color: #04B49C !important;
}
.ds-icon-pdf {
@ -1509,6 +1509,7 @@ div:focus {
.de-status {
position: relative;
margin-left: 15px;
&::before {
content: '';
position: absolute;
@ -1546,6 +1547,7 @@ div:focus {
&::before {
background: var(--deDanger, #F54A45);
}
.el-icon-s-order {
color: var(--primary, #3370ff);
cursor: pointer;
@ -1590,6 +1592,7 @@ div:focus {
margin: 0;
margin-right: 8px;
position: relative;
i {
position: absolute;
right: 2px;
@ -1621,6 +1624,7 @@ div:focus {
justify-content: center;
align-items: center;
}
.arrow-filter:hover {
background: rgba(31, 35, 41, 0.1);
border-radius: 4px;
@ -1633,6 +1637,7 @@ div:focus {
.el-icon-arrow-left.arrow-filter {
margin-right: 5px;
}
.filter-texts-container {
flex: 1;
overflow-x: auto;
@ -1674,11 +1679,13 @@ div:focus {
transform: translate(-50%, -50%);
}
}
.calcu-field {
.calcu-cont {
display: flex;
justify-content: space-between;
}
.codemirror {
height: 250px;
overflow-y: auto;
@ -1686,6 +1693,7 @@ div:focus {
border: 1px solid #bbbfc4;
border-radius: 4px;
}
.codemirror .CodeMirror-scroll {
height: 250px;
overflow-y: auto;

View File

@ -112,7 +112,7 @@
:http-request="upload"
:file-list="fileList"
>
<i class="el-icon-plus" />
<i class="el-icon-plus"/>
</el-upload>
<el-dialog
top="25vh"
@ -375,6 +375,7 @@ export default {
}
.main-row {
background-size: 100% 100% !important;
padding-left: 10px;
height: 250px;
overflow-y: auto;

View File

@ -8,7 +8,8 @@ import {
getYAxis,
getPadding,
getSlider,
getAnalyse
getAnalyse,
setGradientColor
} from '@/views/chart/chart/common/common_antv'
import { antVCustomColor } from '@/views/chart/chart/util'
@ -105,7 +106,7 @@ export function baseBarOptionAntV(plot, container, chart, action, isGroup, isSta
options.color = antVCustomColor(chart)
if (customAttr.color.gradient) {
options.color = options.color.map((ele) => {
return `l(270) 0:#ffffff00 1:${ele}`
return setGradientColor(ele, customAttr.color.gradient, 270)
})
}
@ -202,11 +203,12 @@ export function hBaseBarOptionAntV(plot, container, chart, action, isGroup, isSt
} else {
delete options.isStack
}
options.isPercent = chart.type.includes('percentage')
// custom color
options.color = antVCustomColor(chart)
if (customAttr.color.gradient) {
options.color = options.color.map((ele) => {
return `l(0) 0:#ffffff00 1:${ele}`
return setGradientColor(ele, customAttr.color.gradient)
})
}

View File

@ -29,7 +29,9 @@ export const DEFAULT_COLOR_CASE = {
seriesColors: [], // 格式:{"name":"s1","color":"","isCustom":false}
areaBorderColor: '#303133',
gradient: false,
areaBaseColor: '#FFFFFF'
areaBaseColor: '#FFFFFF',
tableScrollBarColor: 'rgba(0, 0, 0, 0.15)',
tableScrollBarHoverColor: 'rgba(0, 0, 0, 0.4)'
}
export const DEFAULT_COLOR_CASE_DARK = {
@ -45,7 +47,9 @@ export const DEFAULT_COLOR_CASE_DARK = {
tableBorderColor: '#CCCCCC',
seriesColors: [], // 格式:{"name":"s1","color":"","isCustom":false}
areaBorderColor: '#EBEEF5',
areaBaseColor: '5470C6'
areaBaseColor: '5470C6',
tableScrollBarColor: 'rgba(255, 255, 255, 0.5)',
tableScrollBarHoverColor: 'rgba(255, 255, 255, 0.8)'
}
export const DEFAULT_SIZE = {
barDefault: true,

View File

@ -1,7 +1,7 @@
import { hexColorToRGBA } from '@/views/chart/chart/util'
import { formatterItem, valueFormatter } from '@/views/chart/chart/formatter'
import { DEFAULT_XAXIS_STYLE, DEFAULT_YAXIS_EXT_STYLE, DEFAULT_YAXIS_STYLE } from '@/views/chart/chart/chart'
import { equalsAny } from '@/utils/StringUtils'
import { equalsAny, includesAny } from '@/utils/StringUtils'
export function getPadding(chart) {
if (chart.drill) {
@ -166,11 +166,8 @@ export function getLabel(chart) {
extStack = JSON.parse(JSON.stringify(chart.extStack))
}
if (chart.type === 'bar-stack' ||
chart.type === 'line-stack' ||
chart.type === 'bar-stack-horizontal' ||
chart.type === 'percentage-bar-stack'
) {
if (equalsAny(chart.type, 'bar-stack', 'line-stack',
'bar-stack-horizontal', 'percentage-bar-stack', 'percentage-bar-stack-horizontal')) {
let f
if (extStack && extStack.length > 0) {
f = yAxis[0]
@ -189,7 +186,10 @@ export function getLabel(chart) {
f.formatterCfg = formatterItem
}
// 百分比堆叠柱状图保留小数处理
if (chart.type === 'percentage-bar-stack') {
if (chart.type.includes('percentage')) {
if (!param.value) {
return
}
f.formatterCfg.type = 'percent'
f.formatterCfg.decimalCount = l.reserveDecimalCount
f.formatterCfg.thousandSeparator = false
@ -278,10 +278,8 @@ export function getTooltip(chart) {
}
let obj
if (chart.type === 'bar-stack' ||
chart.type === 'line-stack' ||
chart.type === 'bar-stack-horizontal' ||
chart.type === 'percentage-bar-stack') {
if (equalsAny(chart.type, 'bar-stack', 'line-stack',
'bar-stack-horizontal', 'percentage-bar-stack', 'percentage-bar-stack-horizontal')) {
let f
if (extStack && extStack.length > 0) {
obj = { name: param.category, value: param.value }
@ -301,7 +299,11 @@ export function getTooltip(chart) {
if (!f.formatterCfg) {
f.formatterCfg = formatterItem
}
if (chart.type === 'percentage-bar-stack') {
if (chart.type.includes('percentage')) {
if (!param.value) {
obj.value = 0
return obj
}
// 保留小数位数和标签保持一致,这边拿一下标签的配置
const l = JSON.parse(JSON.stringify(customAttr.label))
f.formatterCfg.type = 'percent'
@ -329,7 +331,7 @@ export function getTooltip(chart) {
res = valueFormatter(param.value, formatterItem)
}
}
} else if (chart.type.includes('pie') || chart.type.includes('funnel')) {
} else if (includesAny(chart.type, 'pie', 'funnel')) {
obj = { name: param.field, value: param.value }
for (let i = 0; i < yAxis.length; i++) {
const f = yAxis[i]
@ -339,7 +341,7 @@ export function getTooltip(chart) {
res = valueFormatter(param.value, formatterItem)
}
}
} else if ((chart.type.includes('bar') || chart.type.includes('line') || chart.type.includes('scatter') || chart.type.includes('radar') || chart.type.includes('area')) && !chart.type.includes('group')) {
} else if (includesAny(chart.type, 'bar', 'line', 'scatter', 'radar', 'area') && !chart.type.includes('group')) {
obj = { name: param.category, value: param.value }
for (let i = 0; i < yAxis.length; i++) {
const f = yAxis[i]
@ -879,3 +881,9 @@ function getLineDash(type) {
return [0, 0]
}
}
export function setGradientColor(rawColor, show = false, angle = 0) {
const item = rawColor.split(',')
item.splice(3, 1, '0.3)')
return show ? `l(${angle}) 0:${item.join(',')} 1:${rawColor}` : rawColor
}

View File

@ -1,4 +1,4 @@
import { hexColorToRGBA } from '@/views/chart/chart/util'
import { hexColorToRGBA, resetRgbOpacity } from '@/views/chart/chart/util'
import { DEFAULT_COLOR_CASE, DEFAULT_SIZE } from '@/views/chart/chart/chart'
export function getCustomTheme(chart) {
@ -7,6 +7,8 @@ export function getCustomTheme(chart) {
const borderColor = hexColorToRGBA(DEFAULT_COLOR_CASE.tableBorderColor, DEFAULT_COLOR_CASE.alpha)
const headerAlign = DEFAULT_SIZE.tableHeaderAlign
const itemAlign = DEFAULT_SIZE.tableItemAlign
const scrollBarColor = DEFAULT_COLOR_CASE.tableScrollBarColor
const scrollBarHoverColor = DEFAULT_COLOR_CASE.tableScrollBarHoverColor
const theme = {
background: {
@ -105,6 +107,10 @@ export function getCustomTheme(chart) {
fontSize: DEFAULT_SIZE.tableItemFontSize,
textAlign: headerAlign
}
},
scrollBar: {
thumbColor: scrollBarColor,
thumbHoverColor: scrollBarHoverColor
}
}
@ -156,6 +162,9 @@ export function getCustomTheme(chart) {
theme.dataCell.bolderText.fill = c.tableFontColor
theme.dataCell.text.fill = c.tableFontColor
theme.dataCell.measureText.fill = c.tableFontColor
theme.scrollBar.thumbColor = c.tableScrollBarColor
theme.scrollBar.thumbHoverColor = resetRgbOpacity(c.tableScrollBarColor, 1.5)
}
// size
if (customAttr.size) {

View File

@ -1,4 +1,4 @@
import { getPadding, getTheme } from '@/views/chart/chart/common/common_antv'
import { getPadding, getTheme, setGradientColor } from '@/views/chart/chart/common/common_antv'
import { Gauge } from '@antv/g2plot'
import { DEFAULT_LABEL, DEFAULT_SIZE, DEFAULT_THRESHOLD } from '@/views/chart/chart/chart'
import { getScaleValue } from '@/components/canvas/utils/style'
@ -154,7 +154,9 @@ export function baseGaugeOptionAntV(plot, container, chart, action, scale = 1) {
}
if (customAttr.color.gradient) {
const colorList = (theme.styleSheet?.paletteQualitative10 || []).map((ele) => `l(0) 0:#ffffff00 1:${ele}`)
const colorList = (theme.styleSheet?.paletteQualitative10 || []).map((ele) => {
return setGradientColor(ele, customAttr.color.gradient)
})
if (!options.range) {
options.range = {
color: colorList

View File

@ -8,7 +8,8 @@ import {
getYAxis,
getPadding,
getSlider,
getAnalyse
getAnalyse,
setGradientColor
} from '@/views/chart/chart/common/common_antv'
import { antVCustomColor, handleEmptyDataStrategy } from '@/views/chart/chart/util'
import _ from 'lodash'
@ -183,10 +184,10 @@ export function baseAreaOptionAntV(plot, container, chart, action, isStack) {
const areaColors = [...options.color, ...options.color]
if (customAttr.color.gradient) {
options.areaStyle = () => {
const cr = areaColors.shift()
if (cr) {
const ele = areaColors.shift()
if (ele) {
return {
fill: `l(270) 0:#ffffff00 1:${cr}`
fill: setGradientColor(ele, customAttr.color.gradient, 270)
}
}
}

View File

@ -82,12 +82,6 @@ export function basePieOptionAntV(plot, container, chart, action) {
// custom color
options.color = antVCustomColor(chart)
if (customAttr.color.gradient) {
options.color = options.color.map((ele) => {
return `l(270) 0:#ffffff00 1:${ele}`
})
}
// 开始渲染
if (plot) {
plot.destroy()
@ -165,12 +159,6 @@ export function basePieRoseOptionAntV(plot, container, chart, action) {
// custom color
options.color = antVCustomColor(chart)
if (customAttr.color.gradient) {
options.color = options.color.map((ele) => {
return `l(270) 0:#ffffff00 1:${ele}`
})
}
// 开始渲染
if (plot) {
plot.destroy()

View File

@ -424,7 +424,7 @@ export function baseTablePivot(s2, container, chart, action, tableData) {
// 解析合计、小计排序
const sortParams = []
if (totalCfg.row.totalSort && totalCfg.row.totalSort !== 'none' && c.length > 0 && totalCfg.row.showGrandTotals) {
if (totalCfg.row.totalSort && totalCfg.row.totalSort !== 'none' && c.length > 0 && totalCfg.row.showGrandTotals && v.indexOf(totalCfg.row.totalSortField) > -1) {
const sort = {
sortFieldId: c[0],
sortMethod: totalCfg.row.totalSort.toUpperCase(),
@ -436,7 +436,7 @@ export function baseTablePivot(s2, container, chart, action, tableData) {
sortParams.push(sort)
}
totalCfg.col.totalSort = false
if (totalCfg.col.totalSort && totalCfg.col.totalSort !== 'none' && r.length > 0 && totalCfg.col.showGrandTotals) {
if (totalCfg.col.totalSort && totalCfg.col.totalSort !== 'none' && r.length > 0 && totalCfg.col.showGrandTotals && v.indexOf(totalCfg.col.totalSortField) > -1) {
const sort = {
sortFieldId: r[0],
sortMethod: totalCfg.col.totalSort.toUpperCase(),

View File

@ -1,5 +1,6 @@
import { DEFAULT_TITLE_STYLE } from '@/views/chart/chart/chart'
import { equalsAny, includesAny } from '@/utils/StringUtils'
import _ from 'lodash'
export function hexColorToRGBA(hex, alpha) {
const rgb = [] // 定义rgb数组
@ -49,6 +50,7 @@ export const TYPE_CONFIGS = [
'tableHeaderFontColor',
'tableFontColor',
'tableBorderColor',
'tableScrollBarColor',
'alpha'
],
'size-selector-ant-v': [
@ -95,6 +97,7 @@ export const TYPE_CONFIGS = [
'tableHeaderFontColor',
'tableFontColor',
'tableBorderColor',
'tableScrollBarColor',
'alpha'
],
'size-selector-ant-v': [
@ -144,6 +147,7 @@ export const TYPE_CONFIGS = [
'tableHeaderFontColor',
'tableFontColor',
'tableBorderColor',
'tableScrollBarColor',
'alpha'
],
'size-selector-ant-v': [
@ -943,6 +947,7 @@ export const TYPE_CONFIGS = [
'color-selector': [
'value',
'custom',
'gradient',
'alpha'
],
'label-selector-ant-v': [
@ -1149,6 +1154,87 @@ export const TYPE_CONFIGS = [
]
}
},
{
render: 'antv',
category: 'chart.chart_type_compare',
value: 'percentage-bar-stack-horizontal',
title: 'chart.chart_percentage_bar_stack_horizontal',
icon: 'percentage-bar-stack-horizontal',
properties: [
'color-selector',
'size-selector-ant-v',
'label-selector-ant-v',
'tooltip-selector-ant-v',
'x-axis-selector-ant-v',
'y-axis-selector-ant-v',
'title-selector-ant-v',
'legend-selector-ant-v'
],
propertyInner: {
'color-selector': [
'value',
'colorPanel',
'customColor',
'gradient',
'alpha'
],
'size-selector-ant-v': [
'barDefault',
'barGap'
],
'label-selector-ant-v': [
'show',
'fontSize',
'color',
'position-h',
'reserveDecimalCount'
],
'tooltip-selector-ant-v': [
'show',
'textStyle'
],
'x-axis-selector-ant-v': [
'show',
'position',
'name',
'nameTextStyle',
'axisValue',
'splitLine',
'axisForm',
'axisLabel'
],
'y-axis-selector-ant-v': [
'show',
'position',
'name',
'nameTextStyle',
'splitLine',
'axisForm',
'axisLabel'
],
'title-selector-ant-v': [
'show',
'title',
'fontSize',
'color',
'hPosition',
'isItalic',
'isBolder',
'remarkShow',
'fontFamily',
'letterSpace',
'fontShadow'
],
'legend-selector-ant-v': [
'show',
'icon',
'orient',
'textStyle',
'hPosition',
'vPosition'
]
}
},
{
render: 'antv',
category: 'chart.chart_type_distribute',
@ -1168,7 +1254,6 @@ export const TYPE_CONFIGS = [
'value',
'colorPanel',
'customColor',
'gradient',
'alpha'
],
'size-selector-ant-v': [
@ -1228,7 +1313,6 @@ export const TYPE_CONFIGS = [
'value',
'colorPanel',
'customColor',
'gradient',
'alpha'
],
'size-selector-ant-v': [
@ -1289,7 +1373,6 @@ export const TYPE_CONFIGS = [
'value',
'colorPanel',
'customColor',
'gradient',
'alpha'
],
'size-selector-ant-v': [
@ -1347,7 +1430,6 @@ export const TYPE_CONFIGS = [
'value',
'colorPanel',
'customColor',
'gradient',
'alpha'
],
'size-selector-ant-v': [
@ -1769,6 +1851,7 @@ export const TYPE_CONFIGS = [
'tableItemBgColor',
'tableHeaderFontColor',
'tableFontColor',
'tableScrollBarColor',
'alpha'
],
'size-selector': [
@ -1808,6 +1891,7 @@ export const TYPE_CONFIGS = [
'tableItemBgColor',
'tableHeaderFontColor',
'tableFontColor',
'tableScrollBarColor',
'alpha'
],
'size-selector': [
@ -3411,15 +3495,18 @@ function handleSetZeroMultiDimension(chart, data) {
let insertCount = 0
dimensionInfoMap.forEach((dimensionInfo, field) => {
if (dimensionInfo.set.size < subDimensionSet.size) {
const toBeFillDimension = [...subDimensionSet].filter(item => !dimensionInfo.set.has(item))
toBeFillDimension.forEach(dimension => {
data.splice(dimensionInfo.index + insertCount, 0, {
field,
value: 0,
category: dimension
})
let subInsertIndex = 0
subDimensionSet.forEach(dimension => {
if (!dimensionInfo.set.has(dimension)) {
data.splice(dimensionInfo.index + insertCount + subInsertIndex, 0, {
field,
value: 0,
category: dimension
})
}
subInsertIndex++
})
insertCount += toBeFillDimension.size
insertCount += subDimensionSet.size - dimensionInfo.set.size
}
})
}
@ -3440,3 +3527,21 @@ function handleIgnoreData(chart, data) {
}
}
}
export function resetRgbOpacity(sourceColor, times) {
if (sourceColor?.startsWith('rgb')) {
const numbers = sourceColor.match(/(\d(\.\d+)?)+/g)
if (numbers?.length === 4) {
const opacity = parseFloat(numbers[3])
if (_.isNumber(opacity)) {
let resultOpacity = (opacity * times).toFixed(2)
if (resultOpacity > 1) {
resultOpacity = 1
}
const colorArr = numbers.slice(0, 3).concat(resultOpacity)
return `rgba(${colorArr.join(',')})`
}
}
}
return sourceColor
}

View File

@ -4,7 +4,8 @@ import {
getTheme,
getTooltip,
getXAxis,
getYAxis
getYAxis,
setGradientColor
} from '@/views/chart/chart/common/common_antv'
import { Waterfall } from '@antv/g2plot'
import { formatterItem, valueFormatter } from '@/views/chart/chart/formatter'
@ -28,11 +29,17 @@ export function baseWaterfallOptionAntV(plot, container, chart, action) {
}
// data
const data = chart.data.data
const [risingColorRgba, fallingColorRgba, totalColorRgba] = theme.styleSheet.paletteQualitative10
let customAttrCopy = {}
if (chart.customAttr) {
customAttrCopy = JSON.parse(chart.customAttr)
}
// total
const total = {
label: '合计',
style: {
fill: theme.styleSheet.paletteQualitative10[2]
fill: setGradientColor(totalColorRgba, customAttrCopy.color.gradient, 270)
}
}
// options
@ -50,25 +57,25 @@ export function baseWaterfallOptionAntV(plot, container, chart, action) {
items: [
{ name: '增加', marker: {
style: {
fill: theme.styleSheet.paletteQualitative10[0]
fill: setGradientColor(risingColorRgba, customAttrCopy.color.gradient, 270)
}
}},
{ name: '减少', marker: {
style: {
fill: theme.styleSheet.paletteQualitative10[1]
fill: setGradientColor(fallingColorRgba, customAttrCopy.color.gradient, 270)
}
}},
{ name: '合计', marker: {
style: {
fill: theme.styleSheet.paletteQualitative10[2]
fill: setGradientColor(totalColorRgba, customAttrCopy.color.gradient, 270)
}
}}
]
},
xAxis: xAxis,
yAxis: yAxis,
risingFill: theme.styleSheet.paletteQualitative10[0],
fallingFill: theme.styleSheet.paletteQualitative10[1],
risingFill: setGradientColor(risingColorRgba, customAttrCopy.color.gradient, 270),
fallingFill: setGradientColor(fallingColorRgba, customAttrCopy.color.gradient, 270),
total: total,
interactions: [
{
@ -79,7 +86,7 @@ export function baseWaterfallOptionAntV(plot, container, chart, action) {
}
]
}
// size
let customAttr = {}
if (chart.customAttr) {
customAttr = JSON.parse(chart.customAttr)

View File

@ -57,6 +57,7 @@ import TitleRemark from '@/views/chart/view/TitleRemark'
import { DEFAULT_TITLE_STYLE } from '@/views/chart/chart/chart'
import { baseMixOptionAntV } from '@/views/chart/chart/mix/mix_antv'
import ChartTitleUpdate from './ChartTitleUpdate.vue'
import { equalsAny } from '@/utils/StringUtils'
export default {
name: 'ChartComponentG2',
@ -233,13 +234,13 @@ export default {
this.myChart = baseBarOptionAntV(this.myChart, this.chartId, chart, this.antVAction, true, false)
} else if (chart.type === 'bar-group') {
this.myChart = baseBarOptionAntV(this.myChart, this.chartId, chart, this.antVAction, true, false)
} else if (chart.type === 'bar-stack' || chart.type === 'percentage-bar-stack') {
} else if (equalsAny(chart.type, 'bar-stack', 'percentage-bar-stack')) {
this.myChart = baseBarOptionAntV(this.myChart, this.chartId, chart, this.antVAction, false, true)
} else if (chart.type === 'bar-group-stack') {
this.myChart = baseBarOptionAntV(this.myChart, this.chartId, chart, this.antVAction, true, true)
} else if (chart.type === 'bar-horizontal') {
this.myChart = hBaseBarOptionAntV(this.myChart, this.chartId, chart, this.antVAction, true, false)
} else if (chart.type === 'bar-stack-horizontal') {
} else if (equalsAny(chart.type, 'bar-stack-horizontal', 'percentage-bar-stack-horizontal')) {
this.myChart = hBaseBarOptionAntV(this.myChart, this.chartId, chart, this.antVAction, false, true)
} else if (chart.type === 'line') {
this.myChart = baseLineOptionAntV(this.myChart, this.chartId, chart, this.antVAction)

View File

@ -55,25 +55,32 @@
/>
<el-row
v-show="showPage"
class="table-page"
style="position: relative;"
>
<span class="total-style">
{{ $t('chart.total') }}
<span>{{ chart.datasetMode === 0 ? chart.totalItems : ((chart.data && chart.data.tableRow) ? chart.data.tableRow.length : 0) }}</span>
{{ $t('chart.items') }}
</span>
<el-pagination
small
:current-page="currentPage.page"
:page-sizes="[10,20,50,100]"
:page-size="currentPage.pageSize"
:pager-count="5"
layout="prev, pager, next"
:total="currentPage.show"
class="page-style"
@current-change="pageClick"
@size-change="pageChange"
/>
<el-row
class="table-page"
:style="autoStyle"
>
<span class="total-style">
{{ $t('chart.total') }}
<span>{{
chart.datasetMode === 0 ? chart.totalItems : ((chart.data && chart.data.tableRow) ? chart.data.tableRow.length : 0)
}}</span>
{{ $t('chart.items') }}
</span>
<el-pagination
small
:current-page="currentPage.page"
:page-sizes="[10,20,50,100]"
:page-size="currentPage.pageSize"
:pager-count="5"
layout="prev, pager, next"
:total="currentPage.show"
class="page-style"
@current-change="pageClick"
@size-change="pageChange"
/>
</el-row>
</el-row>
</div>
</div>
@ -87,6 +94,7 @@ import { baseTableInfo, baseTableNormal, baseTablePivot } from '@/views/chart/ch
import TitleRemark from '@/views/chart/view/TitleRemark'
import { DEFAULT_TITLE_STYLE } from '@/views/chart/chart/chart'
import ChartTitleUpdate from './ChartTitleUpdate.vue'
import { mapState } from 'vuex'
export default {
name: 'ChartComponentS2',
@ -162,6 +170,18 @@ export default {
},
computed: {
scale() {
return this.previewCanvasScale.scalePointWidth
},
autoStyle() {
return {
height: (100 / this.scale) + '%!important',
width: (100 / this.scale) + '%!important',
left: 50 * (1 - 1 / this.scale) + '%', // 2
top: 50 * (1 - 1 / this.scale) + '%', // 2
transform: 'scale(' + this.scale + ')'
}
},
trackBarStyleTime() {
return this.trackBarStyle
},
@ -173,7 +193,10 @@ export default {
chartInfo() {
const { id, title } = this.chart
return { id, title }
}
},
...mapState([
'previewCanvasScale'
])
},
watch: {
chart: {

View File

@ -248,6 +248,20 @@
@change="changeColorCase('tableBorderColor')"
/>
</el-form-item>
<el-form-item
v-show="showProperty('tableScrollBarColor')"
:label="$t('chart.table_scroll_bar_color')"
class="form-item"
>
<el-color-picker
v-model="colorForm.tableScrollBarColor"
class="color-picker-style"
:predefine="predefineColors"
color-format="rgb"
show-alpha
@change="changeColorCase('tableScrollBarColor')"
/>
</el-form-item>
</div>
<el-form-item
@ -477,6 +491,8 @@ export default {
this.colorForm.tableBorderColor = this.colorForm.tableBorderColor ? this.colorForm.tableBorderColor : DEFAULT_COLOR_CASE.tableBorderColor
this.colorForm.tableHeaderFontColor = this.colorForm.tableHeaderFontColor ? this.colorForm.tableHeaderFontColor : this.colorForm.tableFontColor
this.$set(this.colorForm, 'gradient', this.colorForm.gradient || false)
this.colorForm.tableScrollBarColor = this.colorForm.tableScrollBarColor ? this.colorForm.tableScrollBarColor : DEFAULT_COLOR_CASE.tableScrollBarColor
this.initCustomColor()
}

View File

@ -422,12 +422,15 @@ export default {
this.totalSortFields = JSON.parse(chart.yaxis)
}
if (this.totalSortFields.length > 0) {
if (this.totalForm.row.totalSortField === '') {
if (this.resetTotalSort(this.totalForm.row.totalSortField)) {
this.totalForm.row.totalSortField = this.totalSortFields[0].dataeaseName
}
if (this.totalForm.col.totalSortField === '') {
if (this.resetTotalSort(this.totalForm.col.totalSortField)) {
this.totalForm.col.totalSortField = this.totalSortFields[0].dataeaseName
}
} else {
this.totalForm.row.totalSortField = ''
this.totalForm.col.totalSortField = ''
}
}
},
@ -437,6 +440,16 @@ export default {
},
showProperty(property) {
return this.propertyInner.includes(property)
},
resetTotalSort(field) {
if (field === '') {
return true
}
const sortFieldList = []
this.totalSortFields.forEach(ele => {
sortFieldList.push(ele.dataeaseName)
})
return sortFieldList.indexOf(field) === -1
}
}
}

View File

@ -13,7 +13,7 @@
<ux-grid
ref="plxTable"
size="mini"
style="width: 100%;"
:style="tableStyle"
:height="height"
:checkbox-config="{highlight: true}"
:width-resize="true"
@ -44,23 +44,33 @@
v-show="showPage"
class="table-page"
>
<span class="total-style">
{{ $t('chart.total') }}
<span>{{ chart.datasetMode === 0 ? chart.totalItems : ((chart.data && chart.data.tableRow) ? chart.data.tableRow.length : 0) }}</span>
{{ $t('chart.items') }}
</span>
<el-pagination
small
:current-page="currentPage.page"
:page-sizes="[10,20,50,100]"
:page-size="currentPage.pageSize"
:pager-count="5"
layout="prev, pager, next"
:total="currentPage.show"
class="page-style"
@current-change="pageClick"
@size-change="pageChange"
/>
<el-row style="position: relative;width:100% ">
<el-row
class="table-page-inner"
:style="autoStyle"
>
<span class="total-style">
{{ $t('chart.total') }}
<span>{{
chart.datasetMode === 0 ? chart.totalItems : ((chart.data && chart.data.tableRow) ? chart.data.tableRow.length : 0)
}}</span>
{{ $t('chart.items') }}
</span>
<el-pagination
small
:current-page="currentPage.page"
:page-sizes="[10,20,50,100]"
:page-size="currentPage.pageSize"
:pager-count="5"
layout="prev, pager, next"
:total="currentPage.show"
class="page-style"
@current-change="pageClick"
@size-change="pageChange"
/>
</el-row>
</el-row>
</el-row>
</el-row>
</div>
@ -69,7 +79,8 @@
<script>
import { hexColorToRGBA } from '../../chart/util'
import eventBus from '@/components/canvas/utils/eventBus'
import { DEFAULT_SIZE } from '@/views/chart/chart/chart'
import { DEFAULT_COLOR_CASE, DEFAULT_SIZE } from '@/views/chart/chart/chart'
import { mapState } from 'vuex'
export default {
name: 'TableNormal',
@ -143,16 +154,39 @@ export default {
scrollTimer: null,
scrollTop: 0,
showIndex: false,
indexLabel: '序号'
indexLabel: '序号',
scrollBarColor: DEFAULT_COLOR_CASE.tableScrollBarColor,
scrollBarHoverColor: DEFAULT_COLOR_CASE.tableScrollBarHoverColor
}
},
computed: {
scale() {
return this.previewCanvasScale.scalePointWidth
},
autoStyle() {
return {
height: (100 / this.scale) + '%!important',
width: (100 / this.scale) + '%!important',
left: 50 * (1 - 1 / this.scale) + '%', // 2
top: 50 * (1 - 1 / this.scale) + '%', // 2
transform: 'scale(' + this.scale + ')'
}
},
bg_class() {
return {
background: hexColorToRGBA('#ffffff', 0),
borderRadius: this.borderRadius
}
}
},
tableStyle() {
return {
width: '100%',
'--scroll-bar-color': this.scrollBarColor
}
},
...mapState([
'previewCanvasScale'
])
},
watch: {
chart: function() {
@ -283,6 +317,7 @@ export default {
this.table_header_class.background = hexColorToRGBA(customAttr.color.tableHeaderBgColor, customAttr.color.alpha)
this.table_item_class.color = customAttr.color.tableFontColor
this.table_item_class.background = hexColorToRGBA(customAttr.color.tableItemBgColor, customAttr.color.alpha)
this.scrollBarColor = customAttr.color.tableScrollBarColor ? customAttr.color.tableScrollBarColor : DEFAULT_COLOR_CASE.tableScrollBarColor
}
if (customAttr.size) {
this.table_header_class.fontSize = customAttr.size.tableTitleFontSize + 'px'
@ -472,39 +507,62 @@ export default {
}
</script>
<style scoped>
.table-class ::v-deep .body--wrapper{
background: rgba(1,1,1,0);
}
.table-class ::v-deep .elx-cell{
max-height: none!important;
line-height: normal!important;
}
.table-page{
position: absolute;
bottom: 0;
display: flex;
align-items: center;
justify-content: flex-end;
width: 100%;
overflow: hidden;
}
.page-style{
margin-right: auto;
}
.total-style{
flex: 1;
font-size: 12px;
color: #606266;
white-space:nowrap;
}
.page-style ::v-deep .el-input__inner{
height: 24px;
}
.page-style ::v-deep button{
background: transparent!important;
}
.page-style ::v-deep li{
background: transparent!important;
<style scoped lang="scss">
.table-class ::v-deep .body--wrapper {
background: rgba(1, 1, 1, 0);
}
.table-class ::v-deep .elx-cell {
max-height: none !important;
line-height: normal !important;
}
.table-page-inner {
display: flex;
align-items: center;
justify-content: flex-end;
width: 100%;
overflow: hidden;
}
.table-page {
position: absolute;
bottom: 0;
display: flex;
align-items: center;
justify-content: flex-end;
width: 100%;
overflow: hidden;
}
.page-style {
margin-right: auto;
}
.total-style {
flex: 1;
font-size: 12px;
color: #606266;
white-space: nowrap;
}
.page-style ::v-deep .el-input__inner {
height: 24px;
}
.page-style ::v-deep button {
background: transparent !important;
}
.page-style ::v-deep li {
background: transparent !important;
}
.table-class{
::-webkit-scrollbar-thumb {
background: var(--scroll-bar-color);
}
}
.table-class{
scrollbar-color: var(--scroll-bar-color) transparent;
}
</style>

View File

@ -27,6 +27,7 @@
@onTextChange="onTextChange"
@onLegendChange="onLegendChange"
@onMarginChange="onMarginChange"
@onSuspensionChange="onSuspensionChange"
/>
<el-row v-else>
<div class="view-selected-message-class">
@ -103,6 +104,9 @@ export default {
onMarginChange(val) {
this.batchOptChange('customStyle', 'margin', val)
},
onSuspensionChange(val) {
this.batchOptChange('customAttr', 'suspension', val)
},
batchOptChange(custom, property, value) {
this.$store.commit('setChangeProperties', {
'custom': custom,

View File

@ -29,7 +29,9 @@
v-model="styleInfo.left"
type="number"
:min="0"
:max="maxLeft"
class="hide-icon-number"
@change="leftOnChange"
>
<template slot="append">px</template>
</el-input>
@ -69,6 +71,8 @@
<script>
import { mapState } from 'vuex'
export default {
name: 'PositionAdjust',
props: {},
@ -76,14 +80,26 @@ export default {
return {}
},
computed: {
maxLeft() {
return 1600 - this.styleInfo.width - this.componentGap
},
styleInfo() {
return this.$store.state.curComponent.style
}
},
...mapState([
'componentGap'
])
},
watch: {},
mounted() {
},
methods: {}
methods: {
leftOnChange() {
if (this.styleInfo.left > this.maxLeft) {
this.styleInfo.left = this.maxLeft
}
}
}
}
</script>

View File

@ -130,30 +130,30 @@
"
>
<span style="font-size: 12px; color: #c0c0c0">{{
$t('dataset.calc_field')
}}</span>
$t('dataset.calc_field')
}}</span>
</span>
</template>
</el-table-column>
<el-table-column
property="deType"
property="deTypeCascader"
:label="$t('dataset.field_type')"
min-width="200"
>
<template slot-scope="scope">
<el-cascader
v-model="scope.row.deType"
v-model="scope.row.deTypeCascader"
size="small"
popper-class="select-date-resolution-format"
:disabled="!hasDataPermission('manage', param.privileges)"
class="select-type"
:options="fields"
:options="getFields(scope.row)"
@visible-change="getPopPosition"
@change="saveEdit(scope.row)"
>
<template slot-scope="{ node, data }">
<span
v-if="node.level === 2 && node.label === '%Y-%m-%d'"
v-if="node.level === 2"
class="format-title"
:style="popPosition"
>{{ $t('chart.date_format') }}</span>
@ -180,8 +180,8 @@
/>
</span>
<span style="color: #8492a6; font-size: 12px">{{
data.label
}}</span>
data.label
}}</span>
</template>
</el-cascader>
<span class="select-svg-icon">
@ -214,16 +214,16 @@
/>
</span>
</span>
<!-- <el-input-->
<!-- v-if="scope.row.deType === 1"-->
<!-- v-model="scope.row.dateFormat"-->
<!-- :placeholder="$t('dataset.date_format')"-->
<!-- size="small"-->
<!-- class="input-type"-->
<!-- :disabled="!hasDataPermission('manage', param.privileges)"-->
<!-- @blur="saveEdit(scope.row)"-->
<!-- @keyup.enter.native="saveEdit(scope.row)"-->
<!-- />-->
<el-input
v-if="scope.row.deType === 1 && scope.row.deExtractType === 0"
v-model="scope.row.dateFormat"
:placeholder="$t('dataset.date_format')"
size="small"
class="input-type"
:disabled="!hasDataPermission('manage', param.privileges)"
@blur="saveEdit(scope.row)"
@keyup.enter.native="saveEdit(scope.row)"
/>
</template>
</el-table-column>
<el-table-column
@ -284,8 +284,8 @@
v-if="scope.row.deExtractType === 3"
class="field-class"
>{{
$t('dataset.value') + '(' + $t('dataset.float') + ')'
}}</span>
$t('dataset.value') + '(' + $t('dataset.float') + ')'
}}</span>
</span>
<span v-if="scope.row.deExtractType === 5">
<svg-icon
@ -308,8 +308,8 @@
"
>
<span style="font-size: 12px; color: #c0c0c0">{{
$t('dataset.calc_field')
}}</span>
$t('dataset.calc_field')
}}</span>
</span>
</template>
</el-table-column>
@ -356,7 +356,7 @@
"
command="copy"
>
<i class="el-icon-document-copy" />
<i class="el-icon-document-copy"/>
{{ $t('dataset.copy') }}
</el-dropdown-item>
<el-dropdown-item
@ -365,7 +365,7 @@
"
command="delete"
>
<i class="el-icon-delete" />
<i class="el-icon-delete"/>
{{ $t('chart.delete') }}
</el-dropdown-item>
</slot>
@ -470,30 +470,30 @@
"
>
<span style="font-size: 12px; color: #c0c0c0">{{
$t('dataset.calc_field')
}}</span>
$t('dataset.calc_field')
}}</span>
</span>
</template>
</el-table-column>
<el-table-column
property="deType"
property="deTypeCascader"
:label="$t('dataset.field_type')"
min-width="200"
>
<template slot-scope="scope">
<el-cascader
v-model="scope.row.deType"
v-model="scope.row.deTypeCascader"
size="small"
popper-class="select-date-resolution-format"
:disabled="!hasDataPermission('manage', param.privileges)"
class="select-type"
:options="fields"
:options="getFields(scope.row)"
@visible-change="getPopPosition"
@change="saveEdit(scope.row)"
>
<template slot-scope="{ node, data }">
<span
v-if="node.level === 2 && node.label === '%Y-%m-%d'"
v-if="node.level === 2"
class="format-title"
:style="popPosition"
>{{ $t('chart.date_format') }}</span>
@ -520,8 +520,8 @@
/>
</span>
<span style="color: #8492a6; font-size: 12px">{{
data.label
}}</span>
data.label
}}</span>
</template>
</el-cascader>
<span class="select-svg-icon">
@ -554,16 +554,16 @@
/>
</span>
</span>
<!-- <el-input-->
<!-- v-if="scope.row.deType === 1"-->
<!-- v-model="scope.row.dateFormat"-->
<!-- :placeholder="$t('dataset.date_format')"-->
<!-- size="small"-->
<!-- class="input-type"-->
<!-- :disabled="!hasDataPermission('manage', param.privileges)"-->
<!-- @blur="saveEdit(scope.row)"-->
<!-- @keyup.enter.native="saveEdit(scope.row)"-->
<!-- />-->
<el-input
v-if="scope.row.deType === 1 && scope.row.deExtractType === 0"
v-model="scope.row.dateFormat"
:placeholder="$t('dataset.date_format')"
size="small"
class="input-type"
:disabled="!hasDataPermission('manage', param.privileges)"
@blur="saveEdit(scope.row)"
@keyup.enter.native="saveEdit(scope.row)"
/>
</template>
</el-table-column>
<el-table-column
@ -616,8 +616,8 @@
v-if="scope.row.deExtractType === 3"
class="field-class"
>{{
$t('dataset.value') + '(' + $t('dataset.float') + ')'
}}</span>
$t('dataset.value') + '(' + $t('dataset.float') + ')'
}}</span>
</span>
<span v-if="scope.row.deExtractType === 5">
<svg-icon
@ -640,8 +640,8 @@
"
>
<span style="font-size: 12px; color: #c0c0c0">{{
$t('dataset.calc_field')
}}</span>
$t('dataset.calc_field')
}}</span>
</span>
</template>
</el-table-column>
@ -689,7 +689,7 @@
"
command="copy"
>
<i class="el-icon-document-copy" />
<i class="el-icon-document-copy"/>
{{ $t('dataset.copy') }}
</el-dropdown-item>
<el-dropdown-item
@ -698,7 +698,7 @@
"
command="delete"
>
<i class="el-icon-delete" />
<i class="el-icon-delete"/>
{{ $t('chart.delete') }}
</el-dropdown-item>
</slot>
@ -742,7 +742,7 @@
</template>
<script>
import { post, fieldListDQ, batchEdit, dateformats } from '@/api/dataset/dataset'
import { batchEdit, dateformats, fieldListDQ, post } from '@/api/dataset/dataset'
import CalcFieldEdit from './CalcFieldEdit'
import { getFieldName } from '@/views/dataset/data/utils'
import msgCfm from '@/components/msgCfm/index'
@ -771,7 +771,7 @@ export default {
quotaListData: []
},
popPosition: {},
fields: [],
dateformats: [],
fieldActiveNames: ['d', 'q'],
searchField: '',
editCalcField: false,
@ -835,24 +835,45 @@ export default {
dateformats(this.param.id).then((response) => {
const children = (response?.data || []).map(ele => ({ label: ele.dateformat, value: ele.dateformat }))
children.push({ label: '自定义', value: 'custom' })
this.fields = [
this.dateformats = children
})
},
getFields(item) {
if (item.deExtractType === 0) {
const children = this.dateformats
return [
{ label: this.$t('dataset.text'), value: 0 },
{ label: this.$t('dataset.time'), value: 1, children },
{ label: this.$t('dataset.value'), value: 2 },
{
label:
this.$t('dataset.value') + '(' + this.$t('dataset.float') + ')',
this.$t('dataset.value') + '(' + this.$t('dataset.float') + ')',
value: 3
},
{ label: this.$t('dataset.location'), value: 5 }
]
})
} else {
return [
{ label: this.$t('dataset.text'), value: 0 },
{ label: this.$t('dataset.time'), value: 1 },
{ label: this.$t('dataset.value'), value: 2 },
{ label: this.$t('dataset.value') + '(' + this.$t('dataset.float') + ')', value: 3 },
{ label: this.$t('dataset.location'), value: 5 }
]
}
},
saveEdit(item) {
if (item.name && item.name.length > 50) {
this.$message.error(this.$t('dataset.field_name_less_50'))
return
}
item.deType = item.deTypeCascader[0]
if (item.deTypeCascader.length === 2) { //
item.dateFormatType = item.deTypeCascader[1]
if (item.dateFormatType !== 'custom') {
item.dateFormat = item.dateFormatType
}
}
post('/dataset/field/save', item)
.then((response) => {

View File

@ -1,11 +1,18 @@
<template>
<div style="width: 100%;height: 100vh;background-color: #f7f8fa">
<div
v-loading="dataLoading"
style="width: 100%;height: 100vh;background-color: #f7f8fa"
:element-loading-text="$t('panel.data_loading')"
element-loading-spinner="el-icon-loading"
element-loading-background="rgba(220,220,220,1)"
>
<Preview
v-if="show"
:component-data="mainCanvasComponentData"
:canvas-style-data="canvasStyleData"
:panel-info="panelInfo"
:user-id="user"
@change-load-status="setLoading"
/>
</div>
</template>
@ -38,7 +45,8 @@ export default {
return {
canvasId: 'canvas-main',
show: false,
panelInfo: {}
panelInfo: {},
dataLoading: false
}
},
computed: {
@ -55,6 +63,9 @@ export default {
this.viewLog()
},
methods: {
setLoading(status) {
this.dataLoading = !!status
},
viewLog() {
const param = {
panelId: this.resourceId,

View File

@ -2,10 +2,11 @@
<el-drawer
v-closePress
v-loading="$store.getters.loadingMap[$store.getters.currentPath]"
:title="'应用模板'"
:title="$t('app_template.apply_template')"
:visible.sync="applyDrawer"
custom-class="de-user-drawer"
size="600px"
:wrapper-closable="false"
direction="rtl"
>
<ds-form
@ -19,6 +20,7 @@
<script>
import DsForm from '@/views/system/datasource/DsForm'
export default {
name: 'AppTemplateApply',
components: {
@ -30,8 +32,7 @@ export default {
applyDrawer: false
}
},
computed: {
},
computed: {},
mounted() {
},
methods: {
@ -52,7 +53,7 @@ export default {
</script>
<style scoped>
::v-deep .el-drawer__body{
padding: 0px 0px!important;
::v-deep .el-drawer__body {
padding: 0px 0px !important;
}
</style>

View File

@ -790,8 +790,8 @@ export default {
}
},
created() {
// Global listening for key events
listenGlobalKeyDown()
document.addEventListener('paste', this.passFromClipboard)
},
mounted() {
this.initWatermark()
@ -808,6 +808,7 @@ export default {
this.init(this.$store.state.panel.panelInfo.id)
},
beforeDestroy() {
document.removeEventListener('paste', this.passFromClipboard)
bus.$off('component-on-drag', this.componentOnDrag)
// bus.$off('component-dialog-edit', this.editDialog)
// bus.$off('button-dialog-edit', this.editButtonDialog)
@ -821,6 +822,14 @@ export default {
elx && elx.remove()
},
methods: {
passFromClipboard(event) {
//
const text = (event.clipboardData || window.clipboardData).getData('text')
if (text && text.includes('datease-component-')) {
event.preventDefault()
this.$store.commit('passFromClipboard', text.replace('datease-component-', ''))
}
},
initWatermark() {
if (this.panelInfo.watermarkInfo) {
userLoginInfo().then(res => {

View File

@ -169,7 +169,51 @@
width="200"
>
<div class="view-container-class">
<el-checkbox-group v-model="attrs.parameters">
<el-tabs
v-if="isRangeParamWidget"
v-model="activeName"
>
<el-tab-pane
v-for="(item, index) in tabsOption"
:key="item.name + index"
:label="item.label"
:name="item.name"
>
<el-checkbox-group
v-model="attrs[item.name + 'Parameters']"
@change="val => {changeDynamicParams(val, item.name)}"
>
<el-checkbox
v-for="(item ) in childViews.datasetParams"
:key="item.id"
:label="item.id"
:disabled="attrs[tabsOption[(index + 1)%2].name + 'Parameters'] && attrs[tabsOption[(index + 1)%2].name + 'Parameters'].includes(item.id)"
class="de-checkbox"
>
<div class="span-div">
<span
v-if="item.alias && item.alias.length <= 7"
style="margin-left: 6px"
>{{ item.alias }}</span>
<el-tooltip
v-else
class="item"
effect="dark"
:content="item.alias"
placement="left"
>
<span style="margin-left: 6px">{{ item.alias }}</span>
</el-tooltip>
</div>
</el-checkbox>
</el-checkbox-group>
</el-tab-pane>
</el-tabs>
<el-checkbox-group
v-else
v-model="attrs.parameters"
>
<el-checkbox
v-for="(item ) in childViews.datasetParams"
:key="item.id"
@ -236,7 +280,13 @@ export default {
},
data() {
return {
activeName: 'start',
tabsOption: [
{ label: this.$t('dataset.start_time'), name: 'start' },
{ label: this.$t('dataset.end_time'), name: 'end' }
],
showParams: false,
isRangeParamWidget: false,
attrs: null,
titlePopovervisible: false,
popovervisible: false,
@ -278,11 +328,21 @@ export default {
created() {
this.attrs = this.controlAttrs
if ('timeYearWidget,timeMonthWidget,timeDateWidget,textSelectWidget,numberSelectWidget'.indexOf(this.widget.name) !== -1) {
if (this.widget.isTimeWidget && this.widget.isTimeWidget()) {
this.showParams = true
this.isRangeParamWidget = this.widget.isRangeParamWidget && this.widget.isRangeParamWidget()
}
},
methods: {
changeDynamicParams(val, name) {
const start = this.attrs.startParameters ? JSON.parse(JSON.stringify(this.attrs.startParameters)) : []
const end = this.attrs.endParameters ? JSON.parse(JSON.stringify(this.attrs.endParameters)) : []
if (end?.length) {
end[0] += '_START_END_SPLIT'
}
this.attrs.parameters = [...new Set([...start, ...end])]
},
sortChange(param) {
this.element.options.attrs.sort = param
},

View File

@ -926,7 +926,7 @@ export default {
if (userCache) {
this.defaultData = JSON.parse(modelInfo)
if (showFirst && this.defaultData.length > 0) {
if (showFirst && this.defaultData && this.defaultData.length > 0) {
this.activeDefaultNodeAndClickOnly(this.defaultData[0].id)
}
}
@ -935,7 +935,7 @@ export default {
localStorage.setItem('panel-default-tree', JSON.stringify(res.data))
if (!userCache) {
this.defaultData = res.data
if (showFirst && this.defaultData.length > 0) {
if (showFirst && this.defaultData && this.defaultData.length > 0) {
this.activeDefaultNodeAndClickOnly(this.defaultData[0].id)
}
}

View File

@ -190,6 +190,19 @@
@change="changeColorCase('tableBorderColor')"
/>
</el-form-item>
<el-form-item
:label="$t('chart.table_scroll_bar_color')"
class="form-item"
>
<el-color-picker
v-model="colorForm.tableScrollBarColor"
class="color-picker-style"
:predefine="predefineColors"
color-format="rgb"
show-alpha
@change="changeColorCase('tableScrollBarColor')"
/>
</el-form-item>
</div>
</el-form>
</el-col>