forked from github/dataease
Merge branch 'dev-v2' into pr@dev-v2_dzz
This commit is contained in:
commit
c6774322b5
14
README.md
14
README.md
@ -4,7 +4,6 @@
|
||||
<a href="https://www.gnu.org/licenses/gpl-3.0.html"><img src="https://img.shields.io/github/license/dataease/dataease?color=%231890FF" alt="License: GPL v3"></a>
|
||||
<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"><img src="https://img.shields.io/github/stars/dataease/dataease?color=%231890FF&style=flat-square" alt="Stars"></a>
|
||||
<a href="https://app.fossa.com/projects/git%2Bgithub.com%2F1dataease%2Fdataease?ref=badge_shield"><img src="https://app.fossa.com/api/projects/git%2Bgithub.com%2Fdataease%2Fdataease.svg?type=shield" alt="FOSSA Status"></a>
|
||||
</p>
|
||||
|
||||
|说明|
|
||||
@ -16,9 +15,7 @@
|
||||
|
||||
DataEase 是开源的数据可视化分析工具,帮助用户快速分析数据并洞察业务趋势,从而实现业务的改进与优化。DataEase 支持丰富的数据源连接,能够通过拖拉拽方式快速制作图表,并可以方便的与他人分享。
|
||||
|
||||
**DataEase 的工作原理:**
|
||||
|
||||

|
||||

|
||||
|
||||
**DataEase 的优势:**
|
||||
|
||||
@ -55,10 +52,11 @@ DataEase 是开源的数据可视化分析工具,帮助用户快速分析数
|
||||
|
||||
## DataEase 快速入门
|
||||
|
||||
- 安装部署教程
|
||||
- 快速入门视频
|
||||
- 完整在线文档
|
||||
- 中文论坛支持
|
||||
- [安装部署教程](https://dataease.io/docs/installation/installation_mode/)
|
||||
- [快速入门视频](https://www.bilibili.com/video/BV1qG4y1F7uc/)
|
||||
- [完整在线文档](https://dataease.io/docs/)
|
||||
- [中文社区论坛](https://bbs.fit2cloud.com/c/de/6)
|
||||
- [模板应用市场](https://dataease.io/templates/)
|
||||
|
||||
## License
|
||||
|
||||
|
@ -1106,11 +1106,11 @@ public class ChartDataBuild {
|
||||
break;
|
||||
}
|
||||
if (originStr.length() >= columnPermissionItem.getDesensitizationRule().getM() && originStr.length() >= columnPermissionItem.getDesensitizationRule().getN()) {
|
||||
desensitizationStr = StringUtils.substring(originStr, columnPermissionItem.getDesensitizationRule().getM() - 1, columnPermissionItem.getDesensitizationRule().getN()) + "***";
|
||||
desensitizationStr = "***" + StringUtils.substring(originStr, columnPermissionItem.getDesensitizationRule().getM() - 1, columnPermissionItem.getDesensitizationRule().getN()) + "***";
|
||||
break;
|
||||
}
|
||||
if (originStr.length() >= columnPermissionItem.getDesensitizationRule().getM() && originStr.length() < columnPermissionItem.getDesensitizationRule().getN()) {
|
||||
desensitizationStr = StringUtils.substring(originStr, columnPermissionItem.getDesensitizationRule().getM() - 1, originStr.length()) + "***";
|
||||
desensitizationStr = "***" + StringUtils.substring(originStr, columnPermissionItem.getDesensitizationRule().getM() - 1, originStr.length());
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
@ -34,7 +34,7 @@ import java.util.stream.Collectors;
|
||||
|
||||
|
||||
public class ExcelUtils {
|
||||
|
||||
public static final String UFEFF = "\uFEFF";
|
||||
private static String path = "/opt/dataease/data/excel/";
|
||||
private static ObjectMapper objectMapper = new ObjectMapper();
|
||||
|
||||
@ -450,6 +450,9 @@ public class ExcelUtils {
|
||||
if(StringUtils.isEmpty(filedName)){
|
||||
DEException.throwException("首行行中不允许有空单元格!");
|
||||
}
|
||||
if (filedName.startsWith(UFEFF)) {
|
||||
filedName = filedName.replace(UFEFF, "");
|
||||
}
|
||||
TableField tableFiled = new TableField();
|
||||
tableFiled.setName(filedName);
|
||||
tableFiled.setOriginName(filedName);
|
||||
|
@ -19,8 +19,6 @@ import io.dataease.api.permissions.user.vo.UserFormVO;
|
||||
import io.dataease.commons.constants.TaskStatus;
|
||||
import io.dataease.commons.utils.CommonThreadPool;
|
||||
import io.dataease.constant.DataSourceType;
|
||||
import io.dataease.dataset.dao.auto.entity.CoreDatasetTable;
|
||||
import io.dataease.dataset.dao.auto.mapper.CoreDatasetTableMapper;
|
||||
import io.dataease.dataset.dto.DatasourceSchemaDTO;
|
||||
import io.dataease.dataset.manage.DatasetDataManage;
|
||||
import io.dataease.dataset.utils.TableUtils;
|
||||
@ -109,6 +107,14 @@ public class DatasourceServer implements DatasourceApi {
|
||||
|
||||
private boolean isUpdatingStatus = false;
|
||||
|
||||
private void getParents(Long pid, List<Long> ids) {
|
||||
CoreDatasource parent = datasourceMapper.selectById(pid);// 查找父级folder
|
||||
ids.add(parent.getId());
|
||||
if (parent.getPid() != null && parent.getPid() != 0) {
|
||||
getParents(parent.getPid(), ids);
|
||||
}
|
||||
}
|
||||
|
||||
public void move(DatasourceDTO dataSourceDTO) throws DEException {
|
||||
switch (dataSourceDTO.getAction()) {
|
||||
case "move" -> {
|
||||
@ -116,7 +122,12 @@ public class DatasourceServer implements DatasourceApi {
|
||||
DEException.throwException("目录必选!");
|
||||
}
|
||||
if (Objects.equals(dataSourceDTO.getId(), dataSourceDTO.getPid())) {
|
||||
DEException.throwException("pid can not equal to id.");
|
||||
DEException.throwException(Translator.get("i18n_pid_not_eq_id"));
|
||||
}
|
||||
List<Long> ids = new ArrayList<>();
|
||||
getParents(dataSourceDTO.getPid(), ids);
|
||||
if (ids.contains(dataSourceDTO.getId())) {
|
||||
DEException.throwException(Translator.get("i18n_pid_not_eq_id"));
|
||||
}
|
||||
dataSourceManage.move(dataSourceDTO);
|
||||
}
|
||||
@ -144,8 +155,10 @@ public class DatasourceServer implements DatasourceApi {
|
||||
private void filterDs(List<BusiNodeVO> busiNodeVOS, List<Long> ids, String type, Long id) {
|
||||
for (BusiNodeVO busiNodeVO : busiNodeVOS) {
|
||||
if (busiNodeVO.getType() != null && busiNodeVO.getType().equalsIgnoreCase(type)) {
|
||||
if (id != null && !busiNodeVO.getId().equals(id)) {
|
||||
ids.add(busiNodeVO.getId());
|
||||
if (id != null) {
|
||||
if (!busiNodeVO.getId().equals(id)) {
|
||||
ids.add(busiNodeVO.getId());
|
||||
}
|
||||
} else {
|
||||
ids.add(busiNodeVO.getId());
|
||||
}
|
||||
@ -166,7 +179,7 @@ public class DatasourceServer implements DatasourceApi {
|
||||
List<Long> ids = new ArrayList<>();
|
||||
filterDs(busiNodeVOS, ids, dataSourceDTO.getType(), dataSourceDTO.getId());
|
||||
|
||||
if(CollectionUtil.isEmpty(ids)){
|
||||
if (CollectionUtil.isEmpty(ids)) {
|
||||
return false;
|
||||
}
|
||||
QueryWrapper<CoreDatasource> wrapper = new QueryWrapper<>();
|
||||
@ -181,7 +194,7 @@ public class DatasourceServer implements DatasourceApi {
|
||||
boolean hasRepeat = false;
|
||||
for (CoreDatasource datasource : datasources) {
|
||||
if (Arrays.asList("API", "Excel", "folder").contains(datasource.getType())) {
|
||||
continue;
|
||||
continue;
|
||||
}
|
||||
DatasourceConfiguration compare = JsonUtil.parseObject(datasource.getConfiguration(), DatasourceConfiguration.class);
|
||||
switch (dataSourceDTO.getType()) {
|
||||
|
@ -7,7 +7,6 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import io.dataease.api.visualization.request.DataVisualizationBaseRequest;
|
||||
import io.dataease.api.visualization.request.VisualizationWorkbranchQueryRequest;
|
||||
import io.dataease.api.visualization.vo.VisualizationResourceVO;
|
||||
import io.dataease.api.visualization.vo.VisualizationStoreVO;
|
||||
import io.dataease.commons.constants.DataVisualizationConstants;
|
||||
import io.dataease.commons.constants.OptConstants;
|
||||
import io.dataease.constant.BusiResourceEnum;
|
||||
@ -21,7 +20,6 @@ import io.dataease.visualization.dao.auto.entity.DataVisualizationInfo;
|
||||
import io.dataease.visualization.dao.auto.mapper.DataVisualizationInfoMapper;
|
||||
import io.dataease.visualization.dao.ext.mapper.CoreVisualiationExtMapper;
|
||||
import io.dataease.visualization.dao.ext.mapper.ExtDataVisualizationMapper;
|
||||
import io.dataease.visualization.dao.ext.po.StorePO;
|
||||
import io.dataease.visualization.dao.ext.po.VisualizationNodePO;
|
||||
import io.dataease.visualization.dao.ext.po.VisualizationResourcePO;
|
||||
import io.dataease.visualization.dto.VisualizationNodeBO;
|
||||
@ -30,7 +28,6 @@ import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@ -84,30 +81,34 @@ public class CoreVisualizationManage {
|
||||
delIds.add(tempPid);
|
||||
List<Long> childrenIdList = extMapper.queryChildrenId(tempPid);
|
||||
if (CollectionUtil.isNotEmpty(childrenIdList)) {
|
||||
stack.addAll(childrenIdList);
|
||||
childrenIdList.forEach(kid -> {
|
||||
if (!delIds.contains(kid)) {
|
||||
stack.add(kid);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
extMapper.batchDel(delIds, System.currentTimeMillis(), AuthUtils.getUser().getUserId());
|
||||
coreOptRecentManage.saveOpt(id, OptConstants.OPT_RESOURCE_TYPE.VISUALIZATION,OptConstants.OPT_TYPE.DELETE);
|
||||
coreOptRecentManage.saveOpt(id, OptConstants.OPT_RESOURCE_TYPE.VISUALIZATION, OptConstants.OPT_TYPE.DELETE);
|
||||
}
|
||||
|
||||
@XpackInteract(value = "visualizationResourceTree", before = false)
|
||||
public void move(DataVisualizationBaseRequest request) {
|
||||
if(!request.getMoveFromUpdate()){
|
||||
if (!request.getMoveFromUpdate()) {
|
||||
DataVisualizationInfo visualizationInfo = new DataVisualizationInfo();
|
||||
BeanUtils.copyBean(visualizationInfo, request);
|
||||
if (ObjectUtils.isEmpty(visualizationInfo.getId())) {
|
||||
DEException.throwException("resource not exist");
|
||||
}
|
||||
visualizationInfo.setUpdateTime(System.currentTimeMillis());
|
||||
coreOptRecentManage.saveOpt(visualizationInfo.getId(), OptConstants.OPT_RESOURCE_TYPE.VISUALIZATION,OptConstants.OPT_TYPE.UPDATE);
|
||||
coreOptRecentManage.saveOpt(visualizationInfo.getId(), OptConstants.OPT_RESOURCE_TYPE.VISUALIZATION, OptConstants.OPT_TYPE.UPDATE);
|
||||
mapper.updateById(visualizationInfo);
|
||||
}
|
||||
}
|
||||
|
||||
@XpackInteract(value = "visualizationResourceTree", before = false)
|
||||
public Long innerSave(DataVisualizationInfo visualizationInfo) {
|
||||
if(visualizationInfo.getId() == null){
|
||||
if (visualizationInfo.getId() == null) {
|
||||
Long id = IDUtils.snowID();
|
||||
visualizationInfo.setId(id);
|
||||
}
|
||||
@ -118,7 +119,7 @@ public class CoreVisualizationManage {
|
||||
visualizationInfo.setUpdateTime(System.currentTimeMillis());
|
||||
visualizationInfo.setOrgId(AuthUtils.getUser().getDefaultOid());
|
||||
mapper.insert(visualizationInfo);
|
||||
coreOptRecentManage.saveOpt(visualizationInfo.getId(), OptConstants.OPT_RESOURCE_TYPE.VISUALIZATION,OptConstants.OPT_TYPE.NEW);
|
||||
coreOptRecentManage.saveOpt(visualizationInfo.getId(), OptConstants.OPT_RESOURCE_TYPE.VISUALIZATION, OptConstants.OPT_TYPE.NEW);
|
||||
return visualizationInfo.getId();
|
||||
}
|
||||
|
||||
@ -127,7 +128,7 @@ public class CoreVisualizationManage {
|
||||
visualizationInfo.setUpdateTime(System.currentTimeMillis());
|
||||
visualizationInfo.setUpdateBy(AuthUtils.getUser().getUserId().toString());
|
||||
mapper.updateById(visualizationInfo);
|
||||
coreOptRecentManage.saveOpt(visualizationInfo.getId(), OptConstants.OPT_RESOURCE_TYPE.VISUALIZATION,OptConstants.OPT_TYPE.UPDATE);
|
||||
coreOptRecentManage.saveOpt(visualizationInfo.getId(), OptConstants.OPT_RESOURCE_TYPE.VISUALIZATION, OptConstants.OPT_TYPE.UPDATE);
|
||||
}
|
||||
|
||||
private boolean isTopNode(Long pid) {
|
||||
@ -162,15 +163,15 @@ public class CoreVisualizationManage {
|
||||
return iPage;
|
||||
}
|
||||
|
||||
List<VisualizationResourceVO> formatResult(List<VisualizationResourcePO> pos){
|
||||
if (CollectionUtil.isEmpty(pos)){
|
||||
List<VisualizationResourceVO> formatResult(List<VisualizationResourcePO> pos) {
|
||||
if (CollectionUtil.isEmpty(pos)) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
return pos.stream().map(po ->
|
||||
new VisualizationResourceVO(
|
||||
po.getId(), po.getResourceId(), po.getName(),
|
||||
po.getType(), String.valueOf(po.getCreator()),String.valueOf(po.getLastEditor()), po.getLastEditTime(),
|
||||
po.getFavorite(),9)).toList();
|
||||
po.getType(), String.valueOf(po.getCreator()), String.valueOf(po.getLastEditor()), po.getLastEditTime(),
|
||||
po.getFavorite(), 9)).toList();
|
||||
}
|
||||
|
||||
public IPage<VisualizationResourcePO> queryVisualizationPage(int goPage, int pageSize, VisualizationWorkbranchQueryRequest request) {
|
||||
@ -188,6 +189,6 @@ public class CoreVisualizationManage {
|
||||
}
|
||||
queryWrapper.orderBy(true, request.isAsc(), "core_opt_recent.time");
|
||||
Page<VisualizationResourcePO> page = new Page<>(goPage, pageSize);
|
||||
return extDataVisualizationMapper.findRecent(page,uid, queryWrapper);
|
||||
return extDataVisualizationMapper.findRecent(page, uid, queryWrapper);
|
||||
}
|
||||
}
|
||||
|
@ -49,7 +49,7 @@ const switchValue = computed({
|
||||
:effect="themes"
|
||||
size="small"
|
||||
v-model="switchValue"
|
||||
@click.stop="e => onSwitchChange(e)"
|
||||
@click.stop="onSwitchChange"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
@ -63,5 +63,18 @@ const switchValue = computed({
|
||||
align-items: center;
|
||||
padding-right: 8px;
|
||||
flex-grow: 1;
|
||||
:deep(.ed-switch.is-checked .ed-switch__core > .ed-switch__action) {
|
||||
left: calc(100% - 12px);
|
||||
}
|
||||
:deep(span.ed-switch__core) {
|
||||
min-width: 24px;
|
||||
border: none;
|
||||
height: 6px;
|
||||
border-radius: 3px;
|
||||
.ed-switch__action {
|
||||
left: 0;
|
||||
box-shadow: 0 2px 4px rgba(31, 35, 41, 0.12);
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
@ -93,7 +93,9 @@ let nameEdit = ref(false)
|
||||
let editComponentId = ref('')
|
||||
let inputName = ref('')
|
||||
let nameInput = ref(null)
|
||||
let curEditComponent = null
|
||||
const editComponentName = item => {
|
||||
curEditComponent = curComponent.value
|
||||
editComponentId.value = `#component-label-${item.id}`
|
||||
nameEdit.value = true
|
||||
inputName.value = item.name
|
||||
@ -106,11 +108,12 @@ const closeEditComponentName = () => {
|
||||
if (!inputName.value || !inputName.value.trim()) {
|
||||
return
|
||||
}
|
||||
if (inputName.value.trim() === curComponent.value.name) {
|
||||
if (inputName.value.trim() === curEditComponent.name) {
|
||||
return
|
||||
}
|
||||
curComponent.value.name = inputName.value
|
||||
curEditComponent.name = inputName.value
|
||||
inputName.value = ''
|
||||
curEditComponent = null
|
||||
}
|
||||
|
||||
const lock = () => {
|
||||
@ -221,12 +224,15 @@ const handleContextMenu = e => {
|
||||
areaData.components.includes(getComponent(index))
|
||||
}"
|
||||
@click="onClick($event, transformIndex(index))"
|
||||
@dblclick="editComponentName(getComponent(index))"
|
||||
>
|
||||
<el-icon class="component-icon">
|
||||
<Icon :name="getIconName(getComponent(index))"></Icon>
|
||||
</el-icon>
|
||||
<span :id="`component-label-${getComponent(index)?.id}`" class="component-label">
|
||||
<span
|
||||
:id="`component-label-${getComponent(index)?.id}`"
|
||||
class="component-label"
|
||||
@dblclick="editComponentName(getComponent(index))"
|
||||
>
|
||||
{{ getComponent(index)?.name }}
|
||||
</span>
|
||||
<div
|
||||
|
@ -252,7 +252,7 @@ const handleMouseDown = e => {
|
||||
}
|
||||
// 如果没有选中组件 在画布上点击时需要调用 e.preventDefault() 防止触发 drop 事件
|
||||
if (!curComponent.value || isPreventDrop(curComponent.value.component)) {
|
||||
e.preventDefault()
|
||||
// e.preventDefault()
|
||||
}
|
||||
hideArea()
|
||||
const rectInfo = editorMap.value[canvasId.value].getBoundingClientRect()
|
||||
|
@ -385,9 +385,9 @@ const handleMouseDownOnShape = e => {
|
||||
nextTick(() => eventBus.emit('componentClick'))
|
||||
dvMainStore.setInEditorStatus(true)
|
||||
dvMainStore.setClickComponentStatus(true)
|
||||
if (isPreventDrop(element.value.component)) {
|
||||
e.preventDefault()
|
||||
}
|
||||
// if (isPreventDrop(element.value.component)) {
|
||||
// e.preventDefault()
|
||||
// }
|
||||
|
||||
e.stopPropagation()
|
||||
if (element.value['isLock'] || !isEditMode.value) return
|
||||
|
@ -211,6 +211,7 @@ for (let i = 0, len = list.length; i < len; i++) {
|
||||
const item = list[i]
|
||||
item.style = { ...commonStyle, ...item.style }
|
||||
item['commonBackground'] = deepCopy(COMMON_COMPONENT_BACKGROUND_BASE)
|
||||
item['state'] = 'prepare'
|
||||
list[i] = { ...commonAttr, ...item }
|
||||
}
|
||||
|
||||
|
@ -49,6 +49,11 @@ router.beforeEach(async (to, from, next) => {
|
||||
return pre
|
||||
}, {})
|
||||
}
|
||||
if (!pathValid(to.path) && to.path !== '/404' && !to.path.startsWith('/de-link')) {
|
||||
const firstPath = getFirstAuthMenu()
|
||||
next({ path: firstPath || '/404' })
|
||||
return
|
||||
}
|
||||
next()
|
||||
return
|
||||
}
|
||||
|
@ -107,8 +107,10 @@ export const copyStore = defineStore('copy', {
|
||||
eventBus.emit('addDashboardItem-' + newComponent.canvasId, newComponent)
|
||||
}
|
||||
})
|
||||
//占位优化 整合定位
|
||||
eventBus.emit('doCanvasInit-canvas-main')
|
||||
if (dvInfo.value.type === 'dashboard') {
|
||||
//占位优化 整合定位
|
||||
eventBus.emit('doCanvasInit-canvas-main')
|
||||
}
|
||||
snapshotStore.recordSnapshotCache()
|
||||
},
|
||||
cut() {
|
||||
|
@ -577,7 +577,11 @@ export const dvMainStore = defineStore('dataVisualization', {
|
||||
} else {
|
||||
viewInfo[propertyInfo.custom][propertyInfo.property] = propertyInfo.value
|
||||
}
|
||||
useEmitt().emitter.emit('renderChart-' + viewId, viewInfo)
|
||||
if (['tablePageMode', 'tablePageSize'].includes(propertyInfo.subProp)) {
|
||||
useEmitt().emitter.emit('calcData-' + viewId, viewInfo)
|
||||
} else {
|
||||
useEmitt().emitter.emit('renderChart-' + viewId, viewInfo)
|
||||
}
|
||||
})
|
||||
} else {
|
||||
this.componentData.forEach(component => {
|
||||
|
@ -2,6 +2,7 @@ import { defineStore, storeToRefs } from 'pinia'
|
||||
import { store } from '../../index'
|
||||
import { dvMainStoreWithOut } from './dvMain'
|
||||
import { swap } from '@/utils/utils'
|
||||
import { useEmitt } from '@/hooks/web/useEmitt'
|
||||
|
||||
const dvMainStore = dvMainStoreWithOut()
|
||||
const { componentData, curComponentIndex, curComponent } = storeToRefs(dvMainStore)
|
||||
@ -52,6 +53,11 @@ export const layerStore = defineStore('layer', {
|
||||
// 显示
|
||||
if (curComponent && curComponent.value) {
|
||||
curComponent.value.isShow = true
|
||||
if (curComponent.value.innerType.indexOf('table') !== -1) {
|
||||
setTimeout(() => {
|
||||
useEmitt().emitter.emit('renderChart-' + curComponent.value.id)
|
||||
}, 400)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -83,6 +83,11 @@ const checkDialog = () => {
|
||||
haveDialog = true
|
||||
}
|
||||
})
|
||||
document.querySelectorAll('.ed-popover').forEach(element => {
|
||||
if (window.getComputedStyle(element).getPropertyValue('display') != 'none') {
|
||||
haveDialog = true
|
||||
}
|
||||
})
|
||||
// 富文本单框
|
||||
if (document.querySelector('.tox-dialog-wrap')) {
|
||||
haveDialog = true
|
||||
@ -92,19 +97,24 @@ const checkDialog = () => {
|
||||
}
|
||||
|
||||
let isCtrlOrCommandDown = false
|
||||
let isShiftDown = false
|
||||
// 全局监听按键操作并执行相应命令
|
||||
export function listenGlobalKeyDown() {
|
||||
window.onkeydown = e => {
|
||||
console.log('e.keyCode-down=' + e.keyCode)
|
||||
if (!isInEditor || checkDialog()) return
|
||||
const { keyCode } = e
|
||||
if (positionMoveKey[keyCode] && curComponent.value) {
|
||||
positionMoveKey[keyCode](keyCode)
|
||||
e.preventDefault()
|
||||
} else if (keyCode === shiftKey) {
|
||||
isShiftDown = true
|
||||
composeStore.setIsShiftDownStatus(true)
|
||||
releaseKeyCheck()
|
||||
} else if (keyCode === ctrlKey || keyCode === commandKey) {
|
||||
isCtrlOrCommandDown = true
|
||||
composeStore.setIsCtrlOrCmdDownStatus(true)
|
||||
releaseKeyCheck()
|
||||
} else if ((keyCode == deleteKey || keyCode == macDeleteKey) && curComponent.value) {
|
||||
deleteComponent()
|
||||
} else if (isCtrlOrCommandDown) {
|
||||
@ -119,10 +129,12 @@ export function listenGlobalKeyDown() {
|
||||
}
|
||||
|
||||
window.onkeyup = e => {
|
||||
console.log('e.keyCode=' + e.keyCode)
|
||||
if (e.keyCode === ctrlKey || e.keyCode === commandKey) {
|
||||
isCtrlOrCommandDown = false
|
||||
composeStore.setIsCtrlOrCmdDownStatus(false)
|
||||
} else if (e.keyCode === shiftKey) {
|
||||
isShiftDown = true
|
||||
composeStore.setIsShiftDownStatus(false)
|
||||
}
|
||||
}
|
||||
@ -132,6 +144,16 @@ export function listenGlobalKeyDown() {
|
||||
}
|
||||
}
|
||||
|
||||
//当前不支持同时ctrl + shift操作
|
||||
function releaseKeyCheck() {
|
||||
if (isCtrlOrCommandDown && isShiftDown) {
|
||||
isCtrlOrCommandDown = false
|
||||
composeStore.setIsCtrlOrCmdDownStatus(false)
|
||||
isShiftDown = true
|
||||
composeStore.setIsShiftDownStatus(false)
|
||||
}
|
||||
}
|
||||
|
||||
function copy() {
|
||||
copyStore.copy()
|
||||
}
|
||||
|
@ -521,6 +521,11 @@ const calcData = (view, resetDrill = false, updateQuery = '') => {
|
||||
}
|
||||
}
|
||||
|
||||
const updateChartData = view => {
|
||||
curComponent.value['state'] = 'ready'
|
||||
calcData(view, true, 'updateQuery')
|
||||
}
|
||||
|
||||
const renderChart = view => {
|
||||
useEmitt().emitter.emit('renderChart-' + view.id, view)
|
||||
snapshotStore.recordSnapshotCache('renderChart', view.id)
|
||||
@ -1607,7 +1612,7 @@ const onRefreshChange = val => {
|
||||
<el-button
|
||||
type="primary"
|
||||
class="result-style-button"
|
||||
@click="calcData(view, true, 'updateQuery')"
|
||||
@click="updateChartData(view)"
|
||||
>
|
||||
<span style="font-size: 12px">
|
||||
{{ t('chart.update_chart_data') }}
|
||||
|
@ -5,7 +5,7 @@ import {
|
||||
import { Line as G2Line, LineOptions } from '@antv/g2plot/esm/plots/line'
|
||||
import { getPadding } from '../../common/common_antv'
|
||||
import { flow, hexColorToRGBA, parseJson } from '@/views/chart/components/js/util'
|
||||
import { cloneDeep } from 'lodash-es'
|
||||
import { cloneDeep, isEmpty } from 'lodash-es'
|
||||
import { valueFormatter } from '@/views/chart/components/js/formatter'
|
||||
import {
|
||||
LINE_AXIS_TYPE,
|
||||
@ -214,11 +214,67 @@ export class Line extends G2PlotChartView<LineOptions, G2Line> {
|
||||
return tmpOptions
|
||||
}
|
||||
|
||||
protected configTooltip(chart: Chart, options: LineOptions): LineOptions {
|
||||
const customAttr: DeepPartial<ChartAttr> = parseJson(chart.customAttr)
|
||||
const tooltipAttr = customAttr.tooltip
|
||||
if (!tooltipAttr.show) {
|
||||
return {
|
||||
...options,
|
||||
tooltip: false
|
||||
}
|
||||
}
|
||||
const xAxisExt = chart.xAxisExt
|
||||
const formatterMap = tooltipAttr.seriesTooltipFormatter
|
||||
?.filter(i => i.show)
|
||||
.reduce((pre, next) => {
|
||||
pre[next.id] = next
|
||||
return pre
|
||||
}, {}) as Record<string, SeriesFormatter>
|
||||
const tooltip: LineOptions['tooltip'] = {
|
||||
showTitle: true,
|
||||
customItems(originalItems) {
|
||||
if (!tooltipAttr.seriesTooltipFormatter?.length) {
|
||||
return originalItems
|
||||
}
|
||||
const head = originalItems[0]
|
||||
// 非原始数据
|
||||
if (!head.data.quotaList) {
|
||||
return originalItems
|
||||
}
|
||||
const result = []
|
||||
originalItems
|
||||
.filter(item => formatterMap[item.data.quotaList[0].id])
|
||||
.forEach(item => {
|
||||
const formatter = formatterMap[item.data.quotaList[0].id]
|
||||
const value = valueFormatter(parseFloat(item.value as string), formatter.formatterCfg)
|
||||
let name = isEmpty(formatter.chartShowName) ? formatter.name : formatter.chartShowName
|
||||
if (xAxisExt?.length > 0) {
|
||||
name = item.data.category
|
||||
}
|
||||
result.push({ ...item, name, value })
|
||||
})
|
||||
head.data.dynamicTooltipValue?.forEach(item => {
|
||||
const formatter = formatterMap[item.fieldId]
|
||||
if (formatter) {
|
||||
const value = valueFormatter(parseFloat(item.value), formatter.formatterCfg)
|
||||
const name = isEmpty(formatter.chartShowName) ? formatter.name : formatter.chartShowName
|
||||
result.push({ color: 'grey', name, value })
|
||||
}
|
||||
})
|
||||
return result
|
||||
}
|
||||
}
|
||||
return {
|
||||
...options,
|
||||
tooltip
|
||||
}
|
||||
}
|
||||
|
||||
protected setupOptions(chart: Chart, options: LineOptions): LineOptions {
|
||||
return flow(
|
||||
this.configTheme,
|
||||
this.configLabel,
|
||||
this.configMultiSeriesTooltip,
|
||||
this.configTooltip,
|
||||
this.configBasicStyle,
|
||||
this.configCustomColors,
|
||||
this.configLegend,
|
||||
|
@ -108,18 +108,21 @@ const renderChartFromDialog = (viewInfo: Chart, chartDataInfo) => {
|
||||
chartData.value = chartDataInfo
|
||||
renderChart(viewInfo, false)
|
||||
}
|
||||
const renderChart = (view: Chart, resetPageInfo: boolean) => {
|
||||
if (!view) {
|
||||
const renderChart = (viewInfo: Chart, resetPageInfo: boolean) => {
|
||||
if (!viewInfo) {
|
||||
return
|
||||
}
|
||||
// view 为引用对象 需要存库 view.data 直接赋值会导致保存不必要的数据
|
||||
const chart = {
|
||||
...defaultsDeep(view, cloneDeep(BASE_VIEW_CONFIG)),
|
||||
...defaultsDeep(viewInfo, cloneDeep(BASE_VIEW_CONFIG)),
|
||||
data: chartData.value
|
||||
} as ChartObj
|
||||
setupPage(chart, resetPageInfo)
|
||||
myChart?.destroy()
|
||||
const chartView = chartViewManager.getChartView(view.render, view.type) as S2ChartView<any>
|
||||
const chartView = chartViewManager.getChartView(
|
||||
viewInfo.render,
|
||||
viewInfo.type
|
||||
) as S2ChartView<any>
|
||||
myChart = chartView.drawChart({
|
||||
container: containerId,
|
||||
chart: toRaw(chart),
|
||||
|
@ -434,7 +434,7 @@ onMounted(() => {
|
||||
}
|
||||
})
|
||||
useEmitt({
|
||||
name: 'calcData-' + view.value.id,
|
||||
name: 'calc-data-' + view.value.id,
|
||||
callback: function (val) {
|
||||
if (!state.initReady) {
|
||||
return
|
||||
@ -453,8 +453,9 @@ onMounted(() => {
|
||||
return
|
||||
}
|
||||
initTitle()
|
||||
const viewInfo = val ? val : view.value
|
||||
nextTick(() => {
|
||||
chartComponent?.value?.renderChart(val)
|
||||
chartComponent?.value?.renderChart(viewInfo)
|
||||
})
|
||||
}
|
||||
})
|
||||
@ -497,7 +498,8 @@ const loadingFlag = computed(() => {
|
||||
|
||||
const chartAreaShow = computed(() => {
|
||||
return (
|
||||
view.value.tableId ||
|
||||
(view.value.tableId &&
|
||||
(element.value['state'] === undefined || element.value['state'] === 'ready')) ||
|
||||
view.value.type === 'rich-text' ||
|
||||
(view.value.type === 'map' && view.value.customAttr.map.id)
|
||||
)
|
||||
|
@ -113,7 +113,7 @@ const handleDragOver = e => {
|
||||
}
|
||||
|
||||
const handleMouseDown = e => {
|
||||
e.stopPropagation()
|
||||
// e.stopPropagation()
|
||||
dvMainStore.setClickComponentStatus(false)
|
||||
// 点击画布的空区域 提前清空curComponent 防止右击菜单内容抖动
|
||||
dvMainStore.setCurComponent({ component: null, index: null })
|
||||
|
@ -85,12 +85,6 @@ export const dsTypes = [
|
||||
catalog: 'OLAP',
|
||||
extraParams: ''
|
||||
},
|
||||
{
|
||||
type: 'db2',
|
||||
name: 'Db2',
|
||||
catalog: 'OLTP',
|
||||
extraParams: ''
|
||||
},
|
||||
{
|
||||
type: 'redshift',
|
||||
name: 'AWS Redshift',
|
||||
|
2
de-xpack
2
de-xpack
@ -1 +1 @@
|
||||
Subproject commit 24cd326ab7961272b7b39595af475bbd76a55233
|
||||
Subproject commit 0a8337cd2b6ea435977c22614c2a24bc9460c6c9
|
Loading…
Reference in New Issue
Block a user